1 /* #include Directives {{{ */
2 #include <Foundation/NSURL.h>
3 #include <UIKit/UIKit.h>
4 #import <GraphicsServices/GraphicsServices.h>
7 #include <ext/stdio_filebuf.h>
9 #include <apt-pkg/acquire.h>
10 #include <apt-pkg/acquire-item.h>
11 #include <apt-pkg/algorithms.h>
12 #include <apt-pkg/cachefile.h>
13 #include <apt-pkg/configuration.h>
14 #include <apt-pkg/debmetaindex.h>
15 #include <apt-pkg/error.h>
16 #include <apt-pkg/init.h>
17 #include <apt-pkg/pkgrecords.h>
18 #include <apt-pkg/sourcelist.h>
19 #include <apt-pkg/sptr.h>
21 #include <sys/sysctl.h>
25 #include <mach-o/nlist.h>
28 #include <objc/objc-class.h>
34 /* Extension Keywords {{{ */
35 #define _trace() fprintf(stderr, "_trace()@%s:%u[%s]\n", __FILE__, __LINE__, __FUNCTION__)
37 #define _assert(test) do \
39 fprintf(stderr, "_assert(%d:%s)@%s:%u[%s]\n", errno, #test, __FILE__, __LINE__, __FUNCTION__); \
44 #define _not(type) ((type) ~ (type) 0)
46 /* Miscellaneous Messages {{{ */
48 - (void) setApplicationNameForUserAgent:(NSString *)applicationName;
49 - (id) frameLoadDelegate;
50 - (void) setFrameLoadDelegate:(id)delegate;
53 @interface NSString (Cydia)
54 - (NSString *) stringByAddingPercentEscapes;
55 - (NSString *) stringByReplacingCharacter:(unsigned short)arg0 withCharacter:(unsigned short)arg1;
59 /* Reset View (UIView) {{{ */
60 @interface UIView (CYResetView)
61 - (void) resetViewAnimated:(BOOL)animated;
64 @implementation UIView (CYResetView)
66 - (void) resetViewAnimated:(BOOL)animated {
67 fprintf(stderr, "%s\n", self->isa->name);
73 /* Reset View (UITable) {{{ */
74 @interface UITable (CYResetView)
75 - (void) resetViewAnimated:(BOOL)animated;
78 @implementation UITable (CYResetView)
80 - (void) resetViewAnimated:(BOOL)animated {
81 [self selectRow:-1 byExtendingSelection:NO withFade:animated];
86 /* Reset View (UISectionList) {{{ */
87 @interface UISectionList (CYResetView)
88 - (void) resetViewAnimated:(BOOL)animated;
91 @implementation UISectionList (CYResetView)
93 - (void) resetViewAnimated:(BOOL)animated {
94 [[self table] resetViewAnimated:animated];
100 /* Perl-Compatible RegEx {{{ */
110 Pcre(const char *regex) :
115 code_ = pcre_compile(regex, 0, &error, &offset, NULL);
118 fprintf(stderr, "%d:%s\n", offset, error);
122 pcre_fullinfo(code_, study_, PCRE_INFO_CAPTURECOUNT, &capture_);
123 matches_ = new int[(capture_ + 1) * 3];
131 NSString *operator [](size_t match) {
133 stringWithCString:(data_ + matches_[match * 2])
134 length:(matches_[match * 2 + 1] - matches_[match * 2])
138 bool operator ()(const char *data, size_t size) {
140 return pcre_exec(code_, study_, data, size, 0, 0, matches_, (capture_ + 1) * 3) >= 0;
144 /* CoreGraphicsServices Primitives {{{ */
150 CGColor(CGColorSpaceRef space, float red, float green, float blue, float alpha) {
151 float color[] = {red, green, blue, alpha};
152 color_ = CGColorCreate(space, color);
156 CGColorRelease(color_);
159 operator CGColorRef() {
170 /* XXX: no GSFontRelease()? */
176 static const int PulseInterval_ = 50000;
178 const char *Firmware_ = NULL;
179 const char *Machine_ = NULL;
180 const char *SerialNumber_ = NULL;
186 #define FW_LEAST(major, minor, bugfix) \
187 (major < Major_ || major == Major_ && \
188 (minor < Minor_ || minor == Minor_ && \
191 bool bootstrap_ = false;
193 static NSMutableDictionary *Metadata_;
194 static NSMutableDictionary *Packages_;
197 NSString *GetLastUpdate() {
198 NSDate *update = [Metadata_ objectForKey:@"LastUpdate"];
201 return @"Never or Unknown";
203 CFLocaleRef locale = CFLocaleCopyCurrent();
204 CFDateFormatterRef formatter = CFDateFormatterCreate(NULL, locale, kCFDateFormatterMediumStyle, kCFDateFormatterMediumStyle);
205 CFStringRef formatted = CFDateFormatterCreateStringWithDate(NULL, formatter, (CFDateRef) update);
207 CFRelease(formatter);
210 return [(NSString *) formatted autorelease];
213 @protocol ProgressDelegate
214 - (void) setError:(NSString *)error;
215 - (void) setTitle:(NSString *)title;
216 - (void) setPercent:(float)percent;
217 - (void) addOutput:(NSString *)output;
220 NSString *SizeString(double size) {
222 while (size > 1024) {
227 static const char *powers_[] = {"B", "kB", "MB", "GB"};
229 return [NSString stringWithFormat:@"%.1f%s", size, powers_[power]];
232 static const float TextViewOffset_ = 22;
234 UITextView *GetTextView(NSString *value, float left, bool html) {
235 UITextView *text([[[UITextView alloc] initWithFrame:CGRectMake(left, 3, 310 - left, 1000)] autorelease]);
236 [text setEditable:NO];
237 [text setTextSize:16];
239 [text setHTML:value];
241 [text setText:value];
242 [text setEnabled:NO];
244 CGColorSpaceRef space = CGColorSpaceCreateDeviceRGB();
245 CGColor clear(space, 0, 0, 0, 0);
246 [text setBackgroundColor:clear];
247 CGColorSpaceRelease(space);
249 CGRect frame = [text frame];
250 [text setFrame:frame];
251 CGRect rect = [text visibleTextRect];
252 frame.size.height = rect.size.height;
253 [text setFrame:frame];
258 /* Status Delegation {{{ */
260 public pkgAcquireStatus
271 void setDelegate(id delegate) {
272 delegate_ = delegate;
275 virtual bool MediaChange(std::string media, std::string drive) {
279 virtual void IMSHit(pkgAcquire::ItemDesc &item) {
282 virtual void Fetch(pkgAcquire::ItemDesc &item) {
283 [delegate_ setTitle:[NSString stringWithCString:("Downloading " + item.ShortDesc).c_str()]];
286 virtual void Done(pkgAcquire::ItemDesc &item) {
289 virtual void Fail(pkgAcquire::ItemDesc &item) {
291 item.Owner->Status == pkgAcquire::Item::StatIdle ||
292 item.Owner->Status == pkgAcquire::Item::StatDone
296 [delegate_ setError:[NSString stringWithCString:item.Owner->ErrorText.c_str()]];
299 virtual bool Pulse(pkgAcquire *Owner) {
300 bool value = pkgAcquireStatus::Pulse(Owner);
303 double(CurrentBytes + CurrentItems) /
304 double(TotalBytes + TotalItems)
307 [delegate_ setPercent:percent];
311 virtual void Start() {
314 virtual void Stop() {
318 /* Progress Delegation {{{ */
326 virtual void Update() {
327 [delegate_ setTitle:[NSString stringWithCString:Op.c_str()]];
328 [delegate_ setPercent:(Percent / 100)];
337 void setDelegate(id delegate) {
338 delegate_ = delegate;
341 virtual void Done() {
342 [delegate_ setPercent:1];
347 /* External Constants {{{ */
348 extern NSString *kUIButtonBarButtonAction;
349 extern NSString *kUIButtonBarButtonInfo;
350 extern NSString *kUIButtonBarButtonInfoOffset;
351 extern NSString *kUIButtonBarButtonSelectedInfo;
352 extern NSString *kUIButtonBarButtonStyle;
353 extern NSString *kUIButtonBarButtonTag;
354 extern NSString *kUIButtonBarButtonTarget;
355 extern NSString *kUIButtonBarButtonTitle;
356 extern NSString *kUIButtonBarButtonTitleVerticalHeight;
357 extern NSString *kUIButtonBarButtonTitleWidth;
358 extern NSString *kUIButtonBarButtonType;
360 /* Mime Addresses {{{ */
361 Pcre email_r("^\"?(.*)\"? <([^>]*)>$");
363 @interface Address : NSObject {
371 - (NSString *) email;
373 + (Address *) addressWithString:(NSString *)string;
374 - (Address *) initWithString:(NSString *)string;
377 @implementation Address
386 - (NSString *) name {
390 - (NSString *) email {
394 + (Address *) addressWithString:(NSString *)string {
395 return [[[Address alloc] initWithString:string] autorelease];
398 - (Address *) initWithString:(NSString *)string {
399 if ((self = [super init]) != nil) {
400 const char *data = [string UTF8String];
401 size_t size = [string length];
403 if (email_r(data, size)) {
404 name_ = [email_r[1] retain];
405 email_ = [email_r[2] retain];
407 name_ = [[NSString stringWithCString:data length:size] retain];
416 /* Right Alignment {{{ */
417 @interface UIRightTextLabel : UITextLabel {
418 float _savedRightEdgeX;
419 BOOL _sizedtofit_flag;
422 - (void) setFrame:(CGRect)frame;
423 - (void) setText:(NSString *)text;
424 - (void) realignText;
427 @implementation UIRightTextLabel
429 - (void) setFrame:(CGRect)frame {
430 [super setFrame:frame];
431 if (_sizedtofit_flag == NO) {
432 _savedRightEdgeX = frame.origin.x;
437 - (void) setText:(NSString *)text {
438 [super setText:text];
442 - (void) realignText {
443 CGRect oldFrame = [self frame];
445 _sizedtofit_flag = YES;
446 [self sizeToFit]; // shrink down size so I can right align it
448 CGRect newFrame = [self frame];
450 oldFrame.origin.x = _savedRightEdgeX - newFrame.size.width;
451 oldFrame.size.width = newFrame.size.width;
452 [super setFrame:oldFrame];
453 _sizedtofit_flag = NO;
458 /* Linear Algebra {{{ */
459 inline float interpolate(float begin, float end, float fraction) {
460 return (end - begin) * fraction + begin;
466 /* Database Interface {{{ */
467 @interface Database : NSObject {
469 pkgRecords *records_;
470 pkgProblemResolver *resolver_;
471 pkgAcquire *fetcher_;
473 SPtr<pkgPackageManager> manager_;
483 - (void) _readStatus:(NSNumber *)fd;
484 - (void) _readOutput:(NSNumber *)fd;
486 - (Package *) packageWithName:(NSString *)name;
489 - (pkgCacheFile &) cache;
490 - (pkgRecords *) records;
491 - (pkgProblemResolver *) resolver;
492 - (pkgAcquire &) fetcher;
500 - (void) setDelegate:(id)delegate;
505 @interface ResetView : UIView {
506 UIPushButton *configure_;
507 UIPushButton *reload_;
508 NSMutableArray *views_;
509 UINavigationBar *navbar_;
510 UITransitionView *transition_;
517 - (void) navigationBar:(UINavigationBar *)navbar poppedItem:(UINavigationItem *)item;
518 - (void) alertSheet:(UIAlertSheet *)sheet buttonClicked:(int)button;
520 - (id) initWithFrame:(CGRect)frame;
521 - (void) setDelegate:(id)delegate;
523 - (void) configurePushed;
524 - (void) reloadPushed;
526 - (void) pushView:(UIView *)view withTitle:(NSString *)title backButtonTitle:(NSString *)back rightButton:(NSString *)right;
527 - (void) popViews:(unsigned)views;
528 - (void) resetView:(BOOL)clear;
533 @implementation ResetView
536 [configure_ release];
538 [transition_ release];
544 - (void) navigationBar:(UINavigationBar *)navbar poppedItem:(UINavigationItem *)item {
545 [views_ removeLastObject];
546 UIView *view([views_ lastObject]);
547 [view resetViewAnimated:!resetting_];
550 [transition_ transition:2 toView:view];
555 - (void) alertSheet:(UIAlertSheet *)sheet buttonClicked:(int)button {
559 - (id) initWithFrame:(CGRect)frame {
560 if ((self = [super initWithFrame:frame]) != nil) {
561 views_ = [[NSMutableArray arrayWithCapacity:4] retain];
563 struct CGRect bounds = [self bounds];
564 CGSize navsize = [UINavigationBar defaultSizeWithPrompt];
565 CGRect navrect = {{0, 0}, navsize};
567 navbar_ = [[UINavigationBar alloc] initWithFrame:navrect];
568 [self addSubview:navbar_];
570 [navbar_ setBarStyle:1];
571 [navbar_ setDelegate:self];
573 transition_ = [[UITransitionView alloc] initWithFrame:CGRectMake(
574 bounds.origin.x, bounds.origin.y + navsize.height, bounds.size.width, bounds.size.height - navsize.height
577 //configure_ = [[UIPushButton alloc] initWithFrame:CGRectMake(15, 9, 17, 18)];
578 configure_ = [[UIPushButton alloc] initWithFrame:CGRectMake(10, 9, 17, 18)];
579 [configure_ setShowPressFeedback:YES];
580 [configure_ setImage:[UIImage applicationImageNamed:@"configure.png"]];
581 [configure_ addTarget:self action:@selector(configurePushed) forEvents:1];
583 //reload_ = [[UIPushButton alloc] initWithFrame:CGRectMake(288, 5, 18, 22)];
584 reload_ = [[UIPushButton alloc] initWithFrame:CGRectMake(293, 5, 18, 22)];
585 [reload_ setShowPressFeedback:YES];
586 [reload_ setImage:[UIImage applicationImageNamed:@"reload.png"]];
587 [reload_ addTarget:self action:@selector(reloadPushed) forEvents:1];
589 [navbar_ addSubview:configure_];
590 [navbar_ addSubview:reload_];
592 [self addSubview:transition_];
596 - (void) setDelegate:(id)delegate {
597 delegate_ = delegate;
600 - (void) configurePushed {
601 UIAlertSheet *sheet = [[[UIAlertSheet alloc]
602 initWithTitle:@"Sources Unimplemented"
603 buttons:[NSArray arrayWithObjects:@"Okay", nil]
609 [sheet setBodyText:@"This feature will be implemented soon. In the mean time, you may add sources by adding .list files to '/etc/apt/sources.list.d' or modifying '/etc/apt/sources.list'."];
610 [sheet popupAlertAnimated:YES];
613 - (void) reloadPushed {
617 - (void) pushView:(UIView *)view withTitle:(NSString *)title backButtonTitle:(NSString *)back rightButton:(NSString *)right {
618 UINavigationItem *navitem = [[[UINavigationItem alloc] initWithTitle:title] autorelease];
619 [navbar_ pushNavigationItem:navitem];
620 [navitem setBackButtonTitle:back];
622 [navbar_ showButtonsWithLeftTitle:nil rightTitle:right];
624 [transition_ transition:([views_ count] == 0 ? 0 : 1) toView:view];
625 [views_ addObject:view];
628 - (void) popViews:(unsigned)views {
630 for (unsigned i(0); i != views; ++i)
631 [navbar_ popNavigationItem];
635 [transition_ transition:2 toView:[views_ lastObject]];
638 - (void) resetView:(BOOL)clear {
641 if ([views_ count] > 1) {
642 [navbar_ disableAnimation];
643 while ([views_ count] != (clear ? 1 : 2))
644 [navbar_ popNavigationItem];
645 [navbar_ enableAnimation];
647 [navbar_ popNavigationItem];
653 [transition_ transition:(clear ? 0 : 2) toView:[views_ lastObject]];
656 - (void) _resetView {
657 [navbar_ showButtonsWithLeftTitle:nil rightTitle:nil];
661 [navbar_ setPrompt:[NSString stringWithFormat:@"Last Updated: %@", GetLastUpdate()]];
666 /* Confirmation View {{{ */
667 void AddTextView(NSMutableDictionary *fields, NSMutableArray *packages, NSString *key) {
668 if ([packages count] == 0)
671 UITextView *text = GetTextView([packages count] == 0 ? @"n/a" : [packages componentsJoinedByString:@", "], 110, false);
672 [fields setObject:text forKey:key];
674 CGColorSpaceRef space = CGColorSpaceCreateDeviceRGB();
675 CGColor blue(space, 0, 0, 0.4, 1);
676 [text setTextColor:blue];
677 CGColorSpaceRelease(space);
680 @protocol ConfirmationViewDelegate
685 @interface ConfirmationView : UIView {
688 UITransitionView *transition_;
690 UINavigationBar *navbar_;
691 UIPreferencesTable *table_;
692 NSMutableDictionary *fields_;
693 UIAlertSheet *essential_;
699 - (void) transitionViewDidComplete:(UITransitionView*)view fromView:(UIView*)from toView:(UIView*)to;
700 - (void) navigationBar:(UINavigationBar *)navbar buttonClicked:(int)button;
701 - (void) alertSheet:(UIAlertSheet *)sheet buttonClicked:(int)button;
703 - (int) numberOfGroupsInPreferencesTable:(UIPreferencesTable *)table;
704 - (NSString *) preferencesTable:(UIPreferencesTable *)table titleForGroup:(int)group;
705 - (float) preferencesTable:(UIPreferencesTable *)table heightForRow:(int)row inGroup:(int)group withProposedHeight:(float)proposed;
706 - (int) preferencesTable:(UIPreferencesTable *)table numberOfRowsInGroup:(int)group;
707 - (UIPreferencesTableCell *) preferencesTable:(UIPreferencesTable *)table cellForRow:(int)row inGroup:(int)group;
709 - (id) initWithView:(UIView *)view database:(Database *)database delegate:(id)delegate;
713 @implementation ConfirmationView
716 [transition_ release];
721 if (essential_ != nil)
722 [essential_ release];
727 [transition_ transition:7 toView:nil];
731 - (void) transitionViewDidComplete:(UITransitionView*)view fromView:(UIView*)from toView:(UIView*)to {
732 if (from != nil && to == nil)
733 [self removeFromSuperview];
736 - (void) navigationBar:(UINavigationBar *)navbar buttonClicked:(int)button {
739 if (essential_ != nil)
740 [essential_ popupAlertAnimated:YES];
751 - (void) alertSheet:(UIAlertSheet *)sheet buttonClicked:(int)button {
752 [essential_ dismiss];
756 - (int) numberOfGroupsInPreferencesTable:(UIPreferencesTable *)table {
760 - (NSString *) preferencesTable:(UIPreferencesTable *)table titleForGroup:(int)group {
762 case 0: return @"Statistics";
763 case 1: return @"Modifications";
765 default: _assert(false);
769 - (int) preferencesTable:(UIPreferencesTable *)table numberOfRowsInGroup:(int)group {
772 case 1: return [fields_ count];
774 default: _assert(false);
778 - (float) preferencesTable:(UIPreferencesTable *)table heightForRow:(int)row inGroup:(int)group withProposedHeight:(float)proposed {
779 if (group != 1 || row == -1)
782 _assert(size_t(row) < [fields_ count]);
783 return [[[fields_ allValues] objectAtIndex:row] visibleTextRect].size.height + TextViewOffset_;
787 - (UIPreferencesTableCell *) preferencesTable:(UIPreferencesTable *)table cellForRow:(int)row inGroup:(int)group {
788 UIPreferencesTableCell *cell = [[[UIPreferencesTableCell alloc] init] autorelease];
789 [cell setShowSelection:NO];
792 case 0: switch (row) {
794 [cell setTitle:@"Downloading"];
795 [cell setValue:SizeString([database_ fetcher].FetchNeeded())];
799 [cell setTitle:@"Resuming At"];
800 [cell setValue:SizeString([database_ fetcher].PartialPresent())];
804 double size([database_ cache]->UsrSize());
807 [cell setTitle:@"Disk Freeing"];
808 [cell setValue:SizeString(-size)];
810 [cell setTitle:@"Disk Using"];
811 [cell setValue:SizeString(size)];
815 default: _assert(false);
819 _assert(size_t(row) < [fields_ count]);
820 [cell setTitle:[[fields_ allKeys] objectAtIndex:row]];
821 [cell addSubview:[[fields_ allValues] objectAtIndex:row]];
824 default: _assert(false);
830 - (id) initWithView:(UIView *)view database:(Database *)database delegate:(id)delegate {
831 if ((self = [super initWithFrame:[view bounds]]) != nil) {
832 database_ = database;
833 delegate_ = delegate;
835 transition_ = [[UITransitionView alloc] initWithFrame:[self bounds]];
836 [self addSubview:transition_];
838 overlay_ = [[UIView alloc] initWithFrame:[transition_ bounds]];
840 CGSize navsize = [UINavigationBar defaultSize];
841 CGRect navrect = {{0, 0}, navsize};
842 CGRect bounds = [overlay_ bounds];
844 navbar_ = [[UINavigationBar alloc] initWithFrame:navrect];
845 [navbar_ setBarStyle:1];
846 [navbar_ setDelegate:self];
848 UINavigationItem *navitem = [[[UINavigationItem alloc] initWithTitle:@"Confirm"] autorelease];
849 [navbar_ pushNavigationItem:navitem];
850 [navbar_ showButtonsWithLeftTitle:@"Cancel" rightTitle:@"Confirm"];
852 fields_ = [[NSMutableDictionary dictionaryWithCapacity:16] retain];
854 NSMutableArray *installing = [NSMutableArray arrayWithCapacity:16];
855 NSMutableArray *upgrading = [NSMutableArray arrayWithCapacity:16];
856 NSMutableArray *removing = [NSMutableArray arrayWithCapacity:16];
862 pkgCacheFile &cache([database_ cache]);
863 for (pkgCache::PkgIterator iterator = cache->PkgBegin(); !iterator.end(); ++iterator) {
864 NSString *name([NSString stringWithCString:iterator.Name()]);
865 bool essential((iterator->Flags & pkgCache::Flag::Essential) != 0);
867 if (cache[iterator].NewInstall()) {
870 [installing addObject:name];
871 } else if (cache[iterator].Upgrade()) {
874 [upgrading addObject:name];
875 } else if (cache[iterator].Delete()) {
878 [removing addObject:name];
885 essential_ = [[UIAlertSheet alloc]
886 initWithTitle:@"Unable to Comply"
887 buttons:[NSArray arrayWithObjects:@"Okay", nil]
893 [essential_ setBodyText:@"One or more of the packages you are about to remove are marked 'Essential' and cannot be removed by Cydia. Please use apt-get."];
896 AddTextView(fields_, installing, @"Installing");
897 AddTextView(fields_, upgrading, @"Upgrading");
898 AddTextView(fields_, removing, @"Removing");
900 table_ = [[UIPreferencesTable alloc] initWithFrame:CGRectMake(
901 0, navsize.height, bounds.size.width, bounds.size.height - navsize.height
904 [table_ setReusesTableCells:YES];
905 [table_ setDataSource:self];
908 [overlay_ addSubview:navbar_];
909 [overlay_ addSubview:table_];
911 [view addSubview:self];
913 [transition_ setDelegate:self];
915 UIView *blank = [[[UIView alloc] initWithFrame:[transition_ bounds]] autorelease];
916 [transition_ transition:0 toView:blank];
917 [transition_ transition:3 toView:overlay_];
924 /* Package Class {{{ */
925 NSString *Scour(const char *field, const char *begin, const char *end) {
926 size_t i(0), l(strlen(field));
929 const char *name = begin + i;
930 const char *colon = name + l;
931 const char *value = colon + 1;
936 memcmp(name, field, l) == 0
938 while (value != end && value[0] == ' ')
940 const char *line = std::find(value, end, '\n');
941 while (line != value && line[-1] == ' ')
943 return [NSString stringWithCString:value length:(line - value)];
945 begin = std::find(begin, end, '\n');
953 @interface Package : NSObject {
954 pkgCache::PkgIterator iterator_;
956 pkgCache::VerIterator version_;
957 pkgCache::VerFileIterator file_;
960 NSString *installed_;
971 - (Package *) initWithIterator:(pkgCache::PkgIterator)iterator database:(Database *)database version:(pkgCache::VerIterator)version file:(pkgCache::VerFileIterator)file;
972 + (Package *) packageWithIterator:(pkgCache::PkgIterator)iterator database:(Database *)database;
974 - (NSString *) section;
975 - (Address *) maintainer;
977 - (NSString *) description;
978 - (NSString *) index;
982 - (NSString *) latest;
983 - (NSString *) installed;
988 - (NSString *) tagline;
990 - (NSString *) website;
992 - (BOOL) matches:(NSString *)text;
994 - (NSComparisonResult) compareByName:(Package *)package;
995 - (NSComparisonResult) compareBySectionAndName:(Package *)package;
996 - (NSComparisonResult) compareForChanges:(Package *)package;
1002 @implementation Package
1006 if (installed_ != nil)
1007 [installed_ release];
1018 - (Package *) initWithIterator:(pkgCache::PkgIterator)iterator database:(Database *)database version:(pkgCache::VerIterator)version file:(pkgCache::VerFileIterator)file {
1019 if ((self = [super init]) != nil) {
1020 iterator_ = iterator;
1021 database_ = database;
1026 pkgRecords::Parser *parser = &[database_ records]->Lookup(file_);
1028 const char *begin, *end;
1029 parser->GetRec(begin, end);
1031 latest_ = [[NSString stringWithCString:version_.VerStr()] retain];
1032 installed_ = iterator_.CurrentVer().end() ? nil : [[NSString stringWithCString:iterator_.CurrentVer().VerStr()] retain];
1034 id_ = [[[NSString stringWithCString:iterator_.Name()] lowercaseString] retain];
1035 name_ = Scour("Name", begin, end);
1037 name_ = [name_ retain];
1038 tagline_ = [[NSString stringWithCString:parser->ShortDesc().c_str()] retain];
1039 icon_ = Scour("Icon", begin, end);
1041 icon_ = [icon_ retain];
1042 website_ = Scour("Website", begin, end);
1043 if (website_ != nil)
1044 website_ = [website_ retain];
1046 NSMutableDictionary *metadata = [Packages_ objectForKey:id_];
1047 if (metadata == nil) {
1048 metadata = [NSMutableDictionary dictionaryWithObjectsAndKeys:
1052 [Packages_ setObject:metadata forKey:id_];
1057 + (Package *) packageWithIterator:(pkgCache::PkgIterator)iterator database:(Database *)database {
1058 for (pkgCache::VerIterator version = iterator.VersionList(); !version.end(); ++version)
1059 for (pkgCache::VerFileIterator file = version.FileList(); !file.end(); ++file)
1060 return [[[Package alloc]
1061 initWithIterator:iterator
1069 - (NSString *) section {
1070 return [[NSString stringWithCString:iterator_.Section()] stringByReplacingCharacter:'_' withCharacter:' '];
1073 - (Address *) maintainer {
1074 pkgRecords::Parser *parser = &[database_ records]->Lookup(file_);
1075 return [Address addressWithString:[NSString stringWithCString:parser->Maintainer().c_str()]];
1079 return version_->InstalledSize;
1082 - (NSString *) description {
1083 pkgRecords::Parser *parser = &[database_ records]->Lookup(file_);
1084 NSString *description([NSString stringWithCString:parser->LongDesc().c_str()]);
1086 NSArray *lines = [description componentsSeparatedByString:@"\n"];
1087 NSMutableArray *trimmed = [NSMutableArray arrayWithCapacity:([lines count] - 1)];
1088 if ([lines count] < 2)
1091 NSCharacterSet *whitespace = [NSCharacterSet whitespaceCharacterSet];
1092 for (size_t i(1); i != [lines count]; ++i) {
1093 NSString *trim = [[lines objectAtIndex:i] stringByTrimmingCharactersInSet:whitespace];
1094 [trimmed addObject:trim];
1097 return [trimmed componentsJoinedByString:@"\n"];
1100 - (NSString *) index {
1101 NSString *index = [[[self name] substringToIndex:1] uppercaseString];
1102 return [index length] != 0 && isalpha([index characterAtIndex:0]) ? index : @"123";
1106 return [[Packages_ objectForKey:id_] objectForKey:@"FirstSeen"];
1109 - (NSString *) latest {
1113 - (NSString *) installed {
1117 - (BOOL) upgradable {
1118 NSString *installed = [self installed];
1119 return installed != nil && [[self latest] compare:installed] != NSOrderedSame ? YES : NO;
1126 - (NSString *) name {
1127 return name_ == nil ? id_ : name_;
1130 - (NSString *) tagline {
1134 - (NSString *) icon {
1138 - (NSString *) website {
1142 - (BOOL) matches:(NSString *)text {
1148 range = [[self id] rangeOfString:text options:NSCaseInsensitiveSearch];
1149 if (range.location != NSNotFound)
1152 range = [[self name] rangeOfString:text options:NSCaseInsensitiveSearch];
1153 if (range.location != NSNotFound)
1156 range = [[self tagline] rangeOfString:text options:NSCaseInsensitiveSearch];
1157 if (range.location != NSNotFound)
1163 - (NSComparisonResult) compareByName:(Package *)package {
1164 NSString *lhs = [self name];
1165 NSString *rhs = [package name];
1167 if ([lhs length] != 0 && [rhs length] != 0) {
1168 unichar lhc = [lhs characterAtIndex:0];
1169 unichar rhc = [rhs characterAtIndex:0];
1171 if (isalpha(lhc) && !isalpha(rhc))
1172 return NSOrderedAscending;
1173 else if (!isalpha(lhc) && isalpha(rhc))
1174 return NSOrderedDescending;
1177 return [lhs caseInsensitiveCompare:rhs];
1180 - (NSComparisonResult) compareBySectionAndName:(Package *)package {
1181 NSComparisonResult result = [[self section] compare:[package section]];
1182 if (result != NSOrderedSame)
1184 return [self compareByName:package];
1187 - (NSComparisonResult) compareForChanges:(Package *)package {
1188 BOOL lhs = [self upgradable];
1189 BOOL rhs = [package upgradable];
1192 return lhs ? NSOrderedAscending : NSOrderedDescending;
1194 switch ([[self seen] compare:[package seen]]) {
1195 case NSOrderedAscending:
1196 return NSOrderedDescending;
1199 case NSOrderedDescending:
1200 return NSOrderedAscending;
1206 return [self compareByName:package];
1210 pkgProblemResolver *resolver = [database_ resolver];
1211 resolver->Clear(iterator_);
1212 resolver->Protect(iterator_);
1213 [database_ cache]->MarkInstall(iterator_, false);
1217 pkgProblemResolver *resolver = [database_ resolver];
1218 resolver->Clear(iterator_);
1219 resolver->Protect(iterator_);
1220 resolver->Remove(iterator_);
1221 [database_ cache]->MarkDelete(iterator_, true);
1226 /* Section Class {{{ */
1227 @interface Section : NSObject {
1230 NSMutableArray *packages_;
1235 - (Section *) initWithName:(NSString *)name row:(size_t)row;
1236 - (NSString *) name;
1238 - (NSArray *) packages;
1240 - (void) addPackage:(Package *)package;
1243 @implementation Section
1247 [packages_ release];
1251 - (Section *) initWithName:(NSString *)name row:(size_t)row {
1252 if ((self = [super init]) != nil) {
1253 name_ = [name retain];
1255 packages_ = [[NSMutableArray arrayWithCapacity:16] retain];
1259 - (NSString *) name {
1267 - (NSArray *) packages {
1272 return [packages_ count];
1275 - (void) addPackage:(Package *)package {
1276 [packages_ addObject:package];
1282 /* Package View {{{ */
1283 @protocol PackageViewDelegate
1284 - (void) performPackage:(Package *)package;
1287 @interface PackageView : UIView {
1288 UIPreferencesTable *table_;
1290 UITextView *description_;
1296 - (int) numberOfGroupsInPreferencesTable:(UIPreferencesTable *)table;
1297 - (NSString *) preferencesTable:(UIPreferencesTable *)table titleForGroup:(int)group;
1298 - (float) preferencesTable:(UIPreferencesTable *)table heightForRow:(int)row inGroup:(int)group withProposedHeight:(float)proposed;
1299 - (int) preferencesTable:(UIPreferencesTable *)table numberOfRowsInGroup:(int)group;
1300 - (UIPreferencesTableCell *) preferencesTable:(UIPreferencesTable *)table cellForRow:(int)row inGroup:(int)group;
1302 - (BOOL) canSelectRow:(int)row;
1303 - (void) tableRowSelected:(NSNotification *)notification;
1305 - (Package *) package;
1307 - (id) initWithFrame:(struct CGRect)frame;
1308 - (void) setPackage:(Package *)package;
1309 - (void) setDelegate:(id)delegate;
1312 @implementation PackageView
1315 if (package_ != nil)
1317 if (description_ != nil)
1318 [description_ release];
1323 - (int) numberOfGroupsInPreferencesTable:(UIPreferencesTable *)table {
1327 - (NSString *) preferencesTable:(UIPreferencesTable *)table titleForGroup:(int)group {
1330 case 1: return @"Details";
1331 case 2: return @"Source";
1333 default: _assert(false);
1337 - (float) preferencesTable:(UIPreferencesTable *)table heightForRow:(int)row inGroup:(int)group withProposedHeight:(float)proposed {
1338 if (group != 0 || row != 1)
1341 return [description_ visibleTextRect].size.height + TextViewOffset_;
1344 - (int) preferencesTable:(UIPreferencesTable *)table numberOfRowsInGroup:(int)group {
1346 case 0: return [package_ website] == nil ? 2 : 3;
1350 default: _assert(false);
1354 - (UIPreferencesTableCell *) preferencesTable:(UIPreferencesTable *)table cellForRow:(int)row inGroup:(int)group {
1355 UIPreferencesTableCell *cell = [[[UIPreferencesTableCell alloc] init] autorelease];
1356 [cell setShowSelection:NO];
1359 case 0: switch (row) {
1361 [cell setTitle:[package_ name]];
1362 [cell setValue:[package_ latest]];
1366 [cell addSubview:description_];
1370 [cell setTitle:@"More Information"];
1371 [cell setShowDisclosure:YES];
1372 [cell setShowSelection:YES];
1375 default: _assert(false);
1378 case 1: switch (row) {
1380 [cell setTitle:@"Identifier"];
1381 [cell setValue:[package_ id]];
1385 [cell setTitle:@"Installed Version"];
1386 NSString *installed([package_ installed]);
1387 [cell setValue:(installed == nil ? @"n/a" : installed)];
1391 [cell setTitle:@"Section"];
1392 [cell setValue:[package_ section]];
1396 [cell setTitle:@"Expanded Size"];
1397 [cell setValue:SizeString([package_ size])];
1401 [cell setTitle:@"Maintainer"];
1402 [cell setValue:[[package_ maintainer] name]];
1403 [cell setShowDisclosure:YES];
1404 [cell setShowSelection:YES];
1407 default: _assert(false);
1410 case 2: switch (row) {
1413 default: _assert(false);
1419 - (BOOL) canSelectRow:(int)row {
1423 - (void) tableRowSelected:(NSNotification *)notification {
1424 int row = [table_ selectedRow];
1425 NSString *website = [package_ website];
1427 if (row == (website == nil ? 8 : 9))
1428 [delegate_ openURL:[NSURL URLWithString:[NSString stringWithFormat:@"mailto:%@?subject=%@",
1429 [[package_ maintainer] email],
1430 [[NSString stringWithFormat:@"regarding apt package \"%@\"", [package_ name]] stringByAddingPercentEscapes]
1432 else if (website != nil && row == 3)
1433 [delegate_ openURL:[NSURL URLWithString:website]];
1436 - (Package *) package {
1440 - (id) initWithFrame:(struct CGRect)frame {
1441 if ((self = [super initWithFrame:frame]) != nil) {
1442 table_ = [[UIPreferencesTable alloc] initWithFrame:[self bounds]];
1443 [self addSubview:table_];
1445 [table_ setDataSource:self];
1446 [table_ setDelegate:self];
1450 - (void) setPackage:(Package *)package {
1451 if (package_ != nil) {
1452 [package_ autorelease];
1456 if (description_ != nil) {
1457 [description_ release];
1461 if (package != nil) {
1462 package_ = [package retain];
1464 NSString *description([package description]);
1465 if (description == nil)
1466 description = [package tagline];
1467 description_ = [GetTextView(description, 12, true) retain];
1469 CGColorSpaceRef space = CGColorSpaceCreateDeviceRGB();
1470 CGColor black(space, 0, 0, 0, 1);
1471 [description_ setTextColor:black];
1472 CGColorSpaceRelease(space);
1474 [table_ reloadData];
1478 - (void) setDelegate:(id)delegate {
1479 delegate_ = delegate;
1484 /* Package Cell {{{ */
1485 @interface PackageCell : UITableCell {
1487 UITextLabel *version_;
1488 UITextLabel *description_;
1494 - (PackageCell *) initWithVersioner:(SEL)versioner;
1495 - (void) setPackage:(Package *)package;
1497 - (void) _setSelected:(float)fraction;
1498 - (void) setSelected:(BOOL)selected;
1499 - (void) setSelected:(BOOL)selected withFade:(BOOL)fade;
1500 - (void) _setSelectionFadeFraction:(float)fraction;
1504 @implementation PackageCell
1509 [description_ release];
1513 - (PackageCell *) initWithVersioner:(SEL)versioner {
1514 if ((self = [super init]) != nil) {
1515 versioner_ = versioner;
1517 GSFontRef bold = GSFontCreateWithName("Helvetica", kGSFontTraitBold, 22);
1518 GSFontRef large = GSFontCreateWithName("Helvetica", kGSFontTraitNone, 16);
1519 GSFontRef small = GSFontCreateWithName("Helvetica", kGSFontTraitNone, 14);
1521 CGColorSpaceRef space = CGColorSpaceCreateDeviceRGB();
1523 CGColor clear(space, 0, 0, 0, 0);
1525 name_ = [[UITextLabel alloc] initWithFrame:CGRectMake(12, 7, 250, 25)];
1526 [name_ setBackgroundColor:clear];
1527 [name_ setFont:bold];
1529 version_ = [[UIRightTextLabel alloc] initWithFrame:CGRectMake(286, 7, 70, 25)];
1530 [version_ setBackgroundColor:clear];
1531 [version_ setFont:large];
1533 description_ = [[UITextLabel alloc] initWithFrame:CGRectMake(13, 35, 280, 20)];
1534 [description_ setBackgroundColor:clear];
1535 [description_ setFont:small];
1537 [self addSubview:name_];
1538 [self addSubview:version_];
1539 [self addSubview:description_];
1541 CGColorSpaceRelease(space);
1549 - (void) setPackage:(Package *)package {
1550 [name_ setText:[package name]];
1551 [version_ setText:[package latest]];
1552 [description_ setText:[package tagline]];
1555 - (void) _setSelected:(float)fraction {
1556 CGColorSpaceRef space = CGColorSpaceCreateDeviceRGB();
1558 CGColor black(space,
1559 interpolate(0.0, 1.0, fraction),
1560 interpolate(0.0, 1.0, fraction),
1561 interpolate(0.0, 1.0, fraction),
1565 interpolate(0.2, 1.0, fraction),
1566 interpolate(0.2, 1.0, fraction),
1567 interpolate(1.0, 1.0, fraction),
1571 interpolate(0.4, 1.0, fraction),
1572 interpolate(0.4, 1.0, fraction),
1573 interpolate(0.4, 1.0, fraction),
1576 [name_ setColor:black];
1577 [version_ setColor:blue];
1578 [description_ setColor:gray];
1580 CGColorSpaceRelease(space);
1583 - (void) setSelected:(BOOL)selected {
1584 [self _setSelected:(selected ? 1.0 : 0.0)];
1585 [super setSelected:selected];
1588 - (void) setSelected:(BOOL)selected withFade:(BOOL)fade {
1590 [self _setSelected:(selected ? 1.0 : 0.0)];
1591 [super setSelected:selected withFade:fade];
1594 - (void) _setSelectionFadeFraction:(float)fraction {
1595 [self _setSelected:fraction];
1596 [super _setSelectionFadeFraction:fraction];
1602 /* Database Implementation {{{ */
1603 @implementation Database
1610 - (void) _readStatus:(NSNumber *)fd {
1611 NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init];
1613 __gnu_cxx::stdio_filebuf<char> ib([fd intValue], std::ios::in);
1614 std::istream is(&ib);
1619 pcre *code = pcre_compile("^([^:]*):([^:]*):([^:]*):(.*)$", 0, &error, &offset, NULL);
1621 pcre_extra *study = NULL;
1623 pcre_fullinfo(code, study, PCRE_INFO_CAPTURECOUNT, &capture);
1624 int matches[(capture + 1) * 3];
1626 while (std::getline(is, line)) {
1627 const char *data(line.c_str());
1629 _assert(pcre_exec(code, study, data, line.size(), 0, 0, matches, sizeof(matches) / sizeof(matches[0])) >= 0);
1631 std::istringstream buffer(line.substr(matches[6], matches[7] - matches[6]));
1634 [delegate_ setPercent:(percent / 100)];
1636 NSString *string = [NSString stringWithCString:(data + matches[8]) length:(matches[9] - matches[8])];
1637 std::string type(line.substr(matches[2], matches[3] - matches[2]));
1639 if (type == "pmerror")
1640 [delegate_ setError:string];
1641 else if (type == "pmstatus")
1642 [delegate_ setTitle:string];
1643 else if (type == "pmconffile")
1645 else _assert(false);
1652 - (void) _readOutput:(NSNumber *)fd {
1653 NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init];
1655 __gnu_cxx::stdio_filebuf<char> ib([fd intValue], std::ios::in);
1656 std::istream is(&ib);
1659 while (std::getline(is, line))
1660 [delegate_ addOutput:[NSString stringWithCString:line.c_str()]];
1666 - (Package *) packageWithName:(NSString *)name {
1667 pkgCache::PkgIterator iterator(cache_->FindPkg([name cString]));
1668 return iterator.end() ? nil : [Package packageWithIterator:iterator database:self];
1671 - (Database *) init {
1672 if ((self = [super init]) != nil) {
1680 _assert(pipe(fds) != -1);
1684 detachNewThreadSelector:@selector(_readStatus:)
1686 withObject:[[NSNumber numberWithInt:fds[0]] retain]
1689 _assert(pipe(fds) != -1);
1690 _assert(dup2(fds[1], 1) != -1);
1691 _assert(close(fds[1]) != -1);
1694 detachNewThreadSelector:@selector(_readOutput:)
1696 withObject:[[NSNumber numberWithInt:fds[0]] retain]
1701 - (pkgCacheFile &) cache {
1705 - (pkgRecords *) records {
1709 - (pkgProblemResolver *) resolver {
1713 - (pkgAcquire &) fetcher {
1717 - (void) reloadData {
1726 if (!cache_.Open(progress_, true)) {
1727 fprintf(stderr, "repairing corrupted database...\n");
1730 _assert(cache_.Open(progress_, true));
1733 records_ = new pkgRecords(cache_);
1734 resolver_ = new pkgProblemResolver(cache_);
1735 fetcher_ = new pkgAcquire(&status_);
1740 pkgRecords records(cache_);
1742 lock_ = new FileFd();
1743 lock_->Fd(GetLock(_config->FindDir("Dir::Cache::Archives") + "lock"));
1744 _assert(!_error->PendingError());
1747 _assert(list.ReadMainList());
1749 manager_ = (_system->CreatePM(cache_));
1750 _assert(manager_->GetArchives(fetcher_, &list, &records));
1751 _assert(!_error->PendingError());
1755 if (fetcher_->Run(PulseInterval_) != pkgAcquire::Continue)
1759 pkgPackageManager::OrderResult result = manager_->DoInstall(statusfd_);
1761 if (result == pkgPackageManager::Failed)
1763 if (_error->PendingError())
1765 if (result != pkgPackageManager::Completed)
1771 _assert(list.ReadMainList());
1774 lock.Fd(GetLock(_config->FindDir("Dir::State::Lists") + "lock"));
1775 _assert(!_error->PendingError());
1777 pkgAcquire fetcher(&status_);
1778 _assert(list.GetIndexes(&fetcher));
1779 _assert(fetcher.Run(PulseInterval_) != pkgAcquire::Failed);
1781 bool failed = false;
1782 for (pkgAcquire::ItemIterator item = fetcher.ItemsBegin(); item != fetcher.ItemsEnd(); item++)
1783 if ((*item)->Status != pkgAcquire::Item::StatDone) {
1784 (*item)->Finished();
1788 if (!failed && _config->FindB("APT::Get::List-Cleanup", true) == true) {
1789 _assert(fetcher.Clean(_config->FindDir("Dir::State::lists")));
1790 _assert(fetcher.Clean(_config->FindDir("Dir::State::lists") + "partial/"));
1793 [Metadata_ setObject:[NSDate date] forKey:@"LastUpdate"];
1797 _assert(cache_->DelCount() == 0 && cache_->InstCount() == 0);
1798 _assert(pkgApplyStatus(cache_));
1800 if (cache_->BrokenCount() != 0) {
1801 _assert(pkgFixBroken(cache_));
1802 _assert(cache_->BrokenCount() == 0);
1803 _assert(pkgMinimizeUpgrade(cache_));
1806 _assert(pkgDistUpgrade(cache_));
1809 - (void) setDelegate:(id)delegate {
1810 delegate_ = delegate;
1811 status_.setDelegate(delegate);
1812 progress_.setDelegate(delegate);
1818 /* Progress Data {{{ */
1819 @interface ProgressData : NSObject {
1825 - (ProgressData *) initWithSelector:(SEL)selector target:(id)target object:(id)object;
1832 @implementation ProgressData
1834 - (ProgressData *) initWithSelector:(SEL)selector target:(id)target object:(id)object {
1835 if ((self = [super init]) != nil) {
1836 selector_ = selector;
1856 /* Progress View {{{ */
1857 @interface ProgressView : UIView <
1861 UIView *background_;
1862 UITransitionView *transition_;
1864 UINavigationBar *navbar_;
1865 UIProgressBar *progress_;
1866 UITextView *output_;
1867 UITextLabel *status_;
1873 - (void) transitionViewDidComplete:(UITransitionView*)view fromView:(UIView*)from toView:(UIView*)to;
1875 - (ProgressView *) initWithFrame:(struct CGRect)frame delegate:(id)delegate;
1876 - (void) setContentView:(UIView *)view;
1879 - (void) alertSheet:(UIAlertSheet *)sheet buttonClicked:(int)button;
1881 - (void) _retachThread;
1882 - (void) _detachNewThreadData:(ProgressData *)data;
1883 - (void) detachNewThreadSelector:(SEL)selector toTarget:(id)target withObject:(id)object title:(NSString *)title;
1885 - (void) setError:(NSString *)error;
1886 - (void) _setError:(NSString *)error;
1888 - (void) setTitle:(NSString *)title;
1889 - (void) _setTitle:(NSString *)title;
1891 - (void) setPercent:(float)percent;
1892 - (void) _setPercent:(NSNumber *)percent;
1894 - (void) addOutput:(NSString *)output;
1895 - (void) _addOutput:(NSString *)output;
1898 @protocol ProgressViewDelegate
1899 - (void) progressViewIsComplete:(ProgressView *)sender;
1902 @implementation ProgressView
1906 if (background_ != nil)
1907 [background_ release];
1908 [transition_ release];
1911 [progress_ release];
1917 - (void) transitionViewDidComplete:(UITransitionView*)view fromView:(UIView*)from toView:(UIView*)to {
1918 if (bootstrap_ && from == overlay_ && to == view_)
1922 - (ProgressView *) initWithFrame:(struct CGRect)frame delegate:(id)delegate {
1923 if ((self = [super initWithFrame:frame]) != nil) {
1924 delegate_ = delegate;
1926 CGColorSpaceRef space = CGColorSpaceCreateDeviceRGB();
1928 CGColor black(space, 0.0, 0.0, 0.0, 1.0);
1929 CGColor white(space, 1.0, 1.0, 1.0, 1.0);
1930 CGColor clear(space, 0.0, 0.0, 0.0, 0.0);
1932 transition_ = [[UITransitionView alloc] initWithFrame:[self bounds]];
1933 [transition_ setDelegate:self];
1935 overlay_ = [[UIView alloc] initWithFrame:[transition_ bounds]];
1938 [overlay_ setBackgroundColor:black];
1940 background_ = [[UIView alloc] initWithFrame:[self bounds]];
1941 [background_ setBackgroundColor:black];
1942 [self addSubview:background_];
1945 [self addSubview:transition_];
1947 CGSize navsize = [UINavigationBar defaultSize];
1948 CGRect navrect = {{0, 0}, navsize};
1950 navbar_ = [[UINavigationBar alloc] initWithFrame:navrect];
1951 [overlay_ addSubview:navbar_];
1953 [navbar_ setBarStyle:1];
1954 [navbar_ setDelegate:self];
1956 UINavigationItem *navitem = [[[UINavigationItem alloc] initWithTitle:nil] autorelease];
1957 [navbar_ pushNavigationItem:navitem];
1959 CGRect bounds = [overlay_ bounds];
1960 CGSize prgsize = [UIProgressBar defaultSize];
1963 (bounds.size.width - prgsize.width) / 2,
1964 bounds.size.height - prgsize.height - 20
1967 progress_ = [[UIProgressBar alloc] initWithFrame:prgrect];
1968 [overlay_ addSubview:progress_];
1970 status_ = [[UITextLabel alloc] initWithFrame:CGRectMake(
1972 bounds.size.height - prgsize.height - 50,
1973 bounds.size.width - 20,
1977 [status_ setColor:white];
1978 [status_ setBackgroundColor:clear];
1980 [status_ setCentersHorizontally:YES];
1981 //[status_ setFont:font];
1983 output_ = [[UITextView alloc] initWithFrame:CGRectMake(
1985 navrect.size.height + 20,
1986 bounds.size.width - 20,
1987 bounds.size.height - navsize.height - 62 - navrect.size.height
1990 //[output_ setTextFont:@"Courier New"];
1991 [output_ setTextSize:12];
1993 [output_ setTextColor:white];
1994 [output_ setBackgroundColor:clear];
1996 [output_ setMarginTop:0];
1997 [output_ setAllowsRubberBanding:YES];
1999 [overlay_ addSubview:output_];
2000 [overlay_ addSubview:status_];
2002 [progress_ setStyle:0];
2004 CGColorSpaceRelease(space);
2008 - (void) setContentView:(UIView *)view {
2009 view_ = [view retain];
2012 - (void) resetView {
2013 [transition_ transition:6 toView:view_];
2016 - (void) alertSheet:(UIAlertSheet *)sheet buttonClicked:(int)button {
2020 - (void) _retachThread {
2021 [delegate_ progressViewIsComplete:self];
2025 - (void) _detachNewThreadData:(ProgressData *)data {
2026 NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init];
2028 [[data target] performSelector:[data selector] withObject:[data object]];
2031 [self performSelectorOnMainThread:@selector(_retachThread) withObject:nil waitUntilDone:YES];
2036 - (void) detachNewThreadSelector:(SEL)selector toTarget:(id)target withObject:(id)object title:(NSString *)title {
2037 [navbar_ popNavigationItem];
2038 UINavigationItem *navitem = [[[UINavigationItem alloc] initWithTitle:title] autorelease];
2039 [navbar_ pushNavigationItem:navitem];
2041 [status_ setText:nil];
2042 [output_ setText:@""];
2043 [progress_ setProgress:0];
2045 [transition_ transition:6 toView:overlay_];
2048 detachNewThreadSelector:@selector(_detachNewThreadData:)
2050 withObject:[[ProgressData alloc]
2051 initWithSelector:selector
2058 - (void) setError:(NSString *)error {
2060 performSelectorOnMainThread:@selector(_setError:)
2066 - (void) _setError:(NSString *)error {
2067 UIAlertSheet *sheet = [[[UIAlertSheet alloc]
2068 initWithTitle:@"Package Error"
2069 buttons:[NSArray arrayWithObjects:@"Okay", nil]
2070 defaultButtonIndex:0
2075 [sheet setBodyText:error];
2076 [sheet popupAlertAnimated:YES];
2079 - (void) setTitle:(NSString *)title {
2081 performSelectorOnMainThread:@selector(_setTitle:)
2087 - (void) _setTitle:(NSString *)title {
2088 [status_ setText:[title stringByAppendingString:@"..."]];
2091 - (void) setPercent:(float)percent {
2093 performSelectorOnMainThread:@selector(_setPercent:)
2094 withObject:[NSNumber numberWithFloat:percent]
2099 - (void) _setPercent:(NSNumber *)percent {
2100 [progress_ setProgress:[percent floatValue]];
2103 - (void) addOutput:(NSString *)output {
2105 performSelectorOnMainThread:@selector(_addOutput:)
2111 - (void) _addOutput:(NSString *)output {
2112 [output_ setText:[NSString stringWithFormat:@"%@\n%@", [output_ text], output]];
2113 CGSize size = [output_ contentSize];
2114 CGRect rect = {{0, size.height}, {size.width, 0}};
2115 [output_ scrollRectToVisible:rect animated:YES];
2121 /* Package Table {{{ */
2122 @protocol PackageTableDelegate
2123 - (void) packageTable:(id)table packageSelected:(Package *)package;
2126 @interface PackageTable : UIView {
2128 UISectionList *list_;
2132 NSMutableArray *sections_;
2137 - (int) numberOfSectionsInSectionList:(UISectionList *)list;
2138 - (NSString *) sectionList:(UISectionList *)list titleForSection:(int)section;
2139 - (int) sectionList:(UISectionList *)list rowForSection:(int)section;
2141 - (int) numberOfRowsInTable:(UITable *)table;
2142 - (float) table:(UITable *)table heightForRow:(int)row;
2143 - (UITableCell *) table:(UITable *)table cellForRow:(int)row column:(UITableColumn *)col reusing:(UITableCell *)reusing;
2144 - (BOOL) table:(UITable *)table showDisclosureForRow:(int)row;
2145 - (void) tableRowSelected:(NSNotification *)notification;
2147 - (id) initWithFrame:(CGRect)frame versioner:(SEL)versioner;
2149 - (void) setDelegate:(id)delegate;
2150 - (void) setPackages:(NSArray *)packages;
2152 - (void) resetViewAnimated:(BOOL)animated;
2153 - (UITable *) table;
2156 @implementation PackageTable
2160 [sections_ release];
2161 if (packages_ != nil)
2162 [packages_ release];
2166 - (int) numberOfSectionsInSectionList:(UISectionList *)list {
2167 return [sections_ count];
2170 - (NSString *) sectionList:(UISectionList *)list titleForSection:(int)section {
2171 return [[sections_ objectAtIndex:section] name];
2174 - (int) sectionList:(UISectionList *)list rowForSection:(int)section {
2175 return [[sections_ objectAtIndex:section] row];
2178 - (int) numberOfRowsInTable:(UITable *)table {
2179 return [packages_ count];
2182 - (float) table:(UITable *)table heightForRow:(int)row {
2186 - (UITableCell *) table:(UITable *)table cellForRow:(int)row column:(UITableColumn *)col reusing:(UITableCell *)reusing {
2188 reusing = [[[PackageCell alloc] initWithVersioner:versioner_] autorelease];
2189 [(PackageCell *)reusing setPackage:[packages_ objectAtIndex:row]];
2193 - (BOOL) table:(UITable *)table showDisclosureForRow:(int)row {
2197 - (void) tableRowSelected:(NSNotification *)notification {
2198 int row = [[notification object] selectedRow];
2199 [delegate_ packageTable:self packageSelected:(row == INT_MAX ? nil : [packages_ objectAtIndex:row])];
2202 - (id) initWithFrame:(CGRect)frame versioner:(SEL)versioner {
2203 if ((self = [super initWithFrame:frame]) != nil) {
2204 versioner_ = versioner;
2205 sections_ = [[NSMutableArray arrayWithCapacity:16] retain];
2207 list_ = [[UISectionList alloc] initWithFrame:[self bounds] showSectionIndex:YES];
2208 [list_ setDataSource:self];
2210 UITableColumn *column = [[[UITableColumn alloc]
2211 initWithTitle:@"Name"
2213 width:frame.size.width
2216 UITable *table = [list_ table];
2217 [table setSeparatorStyle:1];
2218 [table addTableColumn:column];
2219 [table setDelegate:self];
2220 [table setReusesTableCells:YES];
2222 [self addSubview:list_];
2226 - (void) setDelegate:(id)delegate {
2227 delegate_ = delegate;
2230 - (void) setPackages:(NSArray *)packages {
2231 if (packages_ != nil)
2232 [packages_ autorelease];
2233 _assert(packages != nil);
2234 packages_ = [packages retain];
2236 [sections_ removeAllObjects];
2238 Section *section = nil;
2240 for (size_t offset(0); offset != [packages_ count]; ++offset) {
2241 Package *package = [packages_ objectAtIndex:offset];
2242 NSString *name = [package index];
2244 if (section == nil || ![[section name] isEqual:name]) {
2245 section = [[[Section alloc] initWithName:name row:offset] autorelease];
2246 [sections_ addObject:section];
2249 [section addPackage:package];
2255 - (void) resetViewAnimated:(BOOL)animated {
2256 [[list_ table] selectRow:-1 byExtendingSelection:NO withFade:animated];
2259 - (UITable *) table {
2260 return [list_ table];
2266 /* Section Cell {{{ */
2267 @interface SectionCell : UITableCell {
2269 UITextLabel *count_;
2275 - (void) setSection:(Section *)section;
2277 - (void) _setSelected:(float)fraction;
2278 - (void) setSelected:(BOOL)selected;
2279 - (void) setSelected:(BOOL)selected withFade:(BOOL)fade;
2280 - (void) _setSelectionFadeFraction:(float)fraction;
2284 @implementation SectionCell
2293 if ((self = [super init]) != nil) {
2294 GSFontRef bold = GSFontCreateWithName("Helvetica", kGSFontTraitBold, 22);
2295 GSFontRef small = GSFontCreateWithName("Helvetica", kGSFontTraitBold, 12);
2297 CGColorSpaceRef space = CGColorSpaceCreateDeviceRGB();
2298 CGColor clear(space, 0, 0, 0, 0);
2299 CGColor white(space, 1, 1, 1, 1);
2301 name_ = [[UITextLabel alloc] initWithFrame:CGRectMake(47, 9, 250, 25)];
2302 [name_ setBackgroundColor:clear];
2303 [name_ setFont:bold];
2305 count_ = [[UITextLabel alloc] initWithFrame:CGRectMake(11, 7, 29, 32)];
2306 [count_ setCentersHorizontally:YES];
2307 [count_ setBackgroundColor:clear];
2308 [count_ setFont:small];
2309 [count_ setColor:white];
2311 UIImageView *folder = [[[UIImageView alloc] initWithFrame:CGRectMake(8, 7, 32, 32)] autorelease];
2312 [folder setImage:[UIImage applicationImageNamed:@"folder.png"]];
2314 [self addSubview:folder];
2315 [self addSubview:name_];
2316 [self addSubview:count_];
2318 [self _setSelected:0];
2320 CGColorSpaceRelease(space);
2327 - (void) setSection:(Section *)section {
2328 if (section == nil) {
2329 [name_ setText:@"All Packages"];
2330 [count_ setText:nil];
2332 [name_ setText:[section name]];
2333 [count_ setText:[NSString stringWithFormat:@"%d", [section count]]];
2337 - (void) _setSelected:(float)fraction {
2338 CGColorSpaceRef space = CGColorSpaceCreateDeviceRGB();
2340 CGColor black(space,
2341 interpolate(0.0, 1.0, fraction),
2342 interpolate(0.0, 1.0, fraction),
2343 interpolate(0.0, 1.0, fraction),
2346 [name_ setColor:black];
2348 CGColorSpaceRelease(space);
2351 - (void) setSelected:(BOOL)selected {
2352 [self _setSelected:(selected ? 1.0 : 0.0)];
2353 [super setSelected:selected];
2356 - (void) setSelected:(BOOL)selected withFade:(BOOL)fade {
2358 [self _setSelected:(selected ? 1.0 : 0.0)];
2359 [super setSelected:selected withFade:fade];
2362 - (void) _setSelectionFadeFraction:(float)fraction {
2363 [self _setSelected:fraction];
2364 [super _setSelectionFadeFraction:fraction];
2369 /* Install View {{{ */
2370 @interface InstallView : ResetView <
2371 PackageTableDelegate
2375 PackageTable *table_;
2379 NSMutableArray *packages_;
2384 - (void) navigationBar:(UINavigationBar *)navbar buttonClicked:(int)button;
2386 - (int) numberOfRowsInTable:(UITable *)table;
2387 - (float) table:(UITable *)table heightForRow:(int)row;
2388 - (UITableCell *) table:(UITable *)table cellForRow:(int)row column:(UITableColumn *)col reusing:(UITableCell *)reusing;
2389 - (BOOL) table:(UITable *)table showDisclosureForRow:(int)row;
2390 - (void) tableRowSelected:(NSNotification *)notification;
2392 - (void) packageTable:(id)table packageSelected:(Package *)package;
2394 - (id) initWithFrame:(CGRect)frame;
2395 - (void) setPackages:(NSArray *)packages;
2396 - (void) setDelegate:(id)delegate;
2399 @implementation InstallView
2402 [packages_ release];
2403 if (sections_ != nil)
2404 [sections_ release];
2411 if (section_ != nil)
2413 if (package_ != nil)
2418 - (void) navigationBar:(UINavigationBar *)navbar buttonClicked:(int)button {
2420 [[view_ package] install];
2421 [delegate_ resolve];
2422 [delegate_ perform];
2426 - (int) numberOfRowsInTable:(UITable *)table {
2427 return [sections_ count] + 1;
2430 - (float) table:(UITable *)table heightForRow:(int)row {
2434 - (UITableCell *) table:(UITable *)table cellForRow:(int)row column:(UITableColumn *)col reusing:(UITableCell *)reusing {
2436 reusing = [[[SectionCell alloc] init] autorelease];
2438 [(SectionCell *)reusing setSection:nil];
2440 [(SectionCell *)reusing setSection:[sections_ objectAtIndex:(row - 1)]];
2444 - (BOOL) table:(UITable *)table showDisclosureForRow:(int)row {
2448 - (void) tableRowSelected:(NSNotification *)notification {
2449 int row = [[notification object] selectedRow];
2451 if (row == INT_MAX) {
2458 _assert(section_ == nil);
2459 _assert(table_ == nil);
2467 name = @"All Packages";
2469 section = [sections_ objectAtIndex:(row - 1)];
2470 name = [section name];
2471 section_ = [name retain];
2474 table_ = [[PackageTable alloc] initWithFrame:[transition_ bounds] versioner:@selector(latest)];
2475 [table_ setDelegate:self];
2476 [table_ setPackages:(section == nil ? packages_ : [section packages])];
2478 [self pushView:table_ withTitle:name backButtonTitle:@"Packages" rightButton:nil];
2482 - (void) packageTable:(id)table packageSelected:(Package *)package {
2483 if (package == nil) {
2490 _assert(package_ == nil);
2491 _assert(view_ == nil);
2493 package_ = [[package name] retain];
2495 view_ = [[PackageView alloc] initWithFrame:[transition_ bounds]];
2496 [view_ setDelegate:delegate_];
2498 [view_ setPackage:package];
2500 [self pushView:view_ withTitle:[package name] backButtonTitle:nil rightButton:@"Install"];
2504 - (id) initWithFrame:(CGRect)frame {
2505 if ((self = [super initWithFrame:frame]) != nil) {
2506 packages_ = [[NSMutableArray arrayWithCapacity:16] retain];
2508 list_ = [[UITable alloc] initWithFrame:[transition_ bounds]];
2509 [self pushView:list_ withTitle:@"Install" backButtonTitle:@"Sections" rightButton:nil];
2511 UITableColumn *column = [[[UITableColumn alloc]
2512 initWithTitle:@"Name"
2514 width:frame.size.width
2517 [list_ setDataSource:self];
2518 [list_ setSeparatorStyle:1];
2519 [list_ addTableColumn:column];
2520 [list_ setDelegate:self];
2521 [list_ setReusesTableCells:YES];
2523 [transition_ transition:0 toView:list_];
2527 - (void) setPackages:(NSArray *)packages {
2528 [packages_ removeAllObjects];
2530 for (size_t i(0); i != [packages count]; ++i) {
2531 Package *package([packages objectAtIndex:i]);
2532 if ([package installed] == nil)
2533 [packages_ addObject:package];
2536 [packages_ sortUsingSelector:@selector(compareBySectionAndName:)];
2537 NSMutableArray *sections = [NSMutableArray arrayWithCapacity:16];
2539 Section *nsection = nil;
2540 Package *npackage = nil;
2542 Section *section = nil;
2543 for (size_t offset = 0, count = [packages_ count]; offset != count; ++offset) {
2544 Package *package = [packages_ objectAtIndex:offset];
2545 NSString *name = [package section];
2547 if (section == nil || ![[section name] isEqual:name]) {
2548 section = [[[Section alloc] initWithName:name row:offset] autorelease];
2550 if ([name isEqualToString:section_])
2552 [sections addObject:section];
2555 if ([[package name] isEqualToString:package_])
2557 [section addPackage:package];
2560 if (sections_ != nil)
2561 [sections_ release];
2562 sections_ = [sections retain];
2564 [packages_ sortUsingSelector:@selector(compareByName:)];
2570 if (npackage != nil)
2571 [view_ setPackage:npackage];
2572 else if (package_ != nil)
2575 if (table_ != nil && section_ == nil)
2576 [table_ setPackages:packages_];
2577 else if (nsection != nil)
2578 [table_ setPackages:[nsection packages]];
2579 else if (section_ != nil)
2583 [self popViews:views];
2587 - (void) setDelegate:(id)delegate {
2589 [view_ setDelegate:delegate];
2590 [super setDelegate:delegate];
2595 /* Changes View {{{ */
2596 @interface ChangesView : ResetView <
2597 PackageTableDelegate
2599 UISectionList *list_;
2600 NSMutableArray *packages_;
2601 NSMutableArray *sections_;
2609 - (void) navigationBar:(UINavigationBar *)navbar buttonClicked:(int)button;
2611 - (int) numberOfSectionsInSectionList:(UISectionList *)list;
2612 - (NSString *) sectionList:(UISectionList *)list titleForSection:(int)section;
2613 - (int) sectionList:(UISectionList *)list rowForSection:(int)section;
2615 - (int) numberOfRowsInTable:(UITable *)table;
2616 - (float) table:(UITable *)table heightForRow:(int)row;
2617 - (UITableCell *) table:(UITable *)table cellForRow:(int)row column:(UITableColumn *)col reusing:(UITableCell *)reusing;
2618 - (BOOL) table:(UITable *)table showDisclosureForRow:(int)row;
2619 - (void) tableRowSelected:(NSNotification *)notification;
2621 - (id) initWithFrame:(CGRect)frame;
2622 - (void) setPackages:(NSArray *)packages;
2623 - (void) _resetView;
2626 - (void) setDelegate:(id)delegate;
2629 @implementation ChangesView
2633 [packages_ release];
2634 [sections_ release];
2637 if (package_ != nil)
2642 - (int) numberOfSectionsInSectionList:(UISectionList *)list {
2643 return [sections_ count];
2646 - (NSString *) sectionList:(UISectionList *)list titleForSection:(int)section {
2647 return [[sections_ objectAtIndex:section] name];
2650 - (int) sectionList:(UISectionList *)list rowForSection:(int)section {
2651 return [[sections_ objectAtIndex:section] row];
2654 - (int) numberOfRowsInTable:(UITable *)table {
2655 return [packages_ count];
2658 - (float) table:(UITable *)table heightForRow:(int)row {
2662 - (UITableCell *) table:(UITable *)table cellForRow:(int)row column:(UITableColumn *)col reusing:(UITableCell *)reusing {
2664 reusing = [[[PackageCell alloc] initWithVersioner:NULL] autorelease];
2665 [(PackageCell *)reusing setPackage:[packages_ objectAtIndex:row]];
2669 - (BOOL) table:(UITable *)table showDisclosureForRow:(int)row {
2673 - (void) tableRowSelected:(NSNotification *)notification {
2674 int row = [[notification object] selectedRow];
2675 [self packageTable:self packageSelected:(row == INT_MAX ? nil : [packages_ objectAtIndex:row])];
2678 - (void) navigationBar:(UINavigationBar *)navbar buttonClicked:(int)button {
2681 [[view_ package] install];
2682 [delegate_ resolve];
2683 [delegate_ perform];
2687 [delegate_ upgrade];
2692 - (void) packageTable:(id)table packageSelected:(Package *)package {
2693 if (package == nil) {
2700 _assert(package_ == nil);
2701 _assert(view_ == nil);
2703 package_ = [[package name] retain];
2705 view_ = [[PackageView alloc] initWithFrame:[transition_ bounds]];
2706 [view_ setDelegate:delegate_];
2708 [view_ setPackage:package];
2710 [self pushView:view_ withTitle:[package name] backButtonTitle:nil rightButton:(
2711 [package upgradable] ? @"Upgrade" : @"Install"
2716 - (id) initWithFrame:(CGRect)frame {
2717 if ((self = [super initWithFrame:frame]) != nil) {
2718 packages_ = [[NSMutableArray arrayWithCapacity:16] retain];
2719 sections_ = [[NSMutableArray arrayWithCapacity:16] retain];
2721 list_ = [[UISectionList alloc] initWithFrame:[transition_ bounds] showSectionIndex:NO];
2722 [list_ setShouldHideHeaderInShortLists:NO];
2723 [list_ setDataSource:self];
2724 //[list_ setSectionListStyle:1];
2726 UITableColumn *column = [[[UITableColumn alloc]
2727 initWithTitle:@"Name"
2729 width:frame.size.width
2732 UITable *table = [list_ table];
2733 [table setSeparatorStyle:1];
2734 [table addTableColumn:column];
2735 [table setDelegate:self];
2736 [table setReusesTableCells:YES];
2738 [self pushView:list_ withTitle:@"Changes" backButtonTitle:nil rightButton:nil];
2742 - (void) setPackages:(NSArray *)packages {
2743 [packages_ removeAllObjects];
2744 for (size_t i(0); i != [packages count]; ++i) {
2745 Package *package([packages objectAtIndex:i]);
2746 if ([package installed] == nil || [package upgradable])
2747 [packages_ addObject:package];
2750 [packages_ sortUsingSelector:@selector(compareForChanges:)];
2752 [sections_ removeAllObjects];
2754 Section *upgradable = [[[Section alloc] initWithName:@"Available Upgrades" row:0] autorelease];
2755 Section *section = nil;
2758 Package *npackage = nil;
2759 for (size_t offset = 0, count = [packages_ count]; offset != count; ++offset) {
2760 Package *package = [packages_ objectAtIndex:offset];
2761 if ([[package name] isEqualToString:package_])
2764 if ([package upgradable])
2765 [upgradable addPackage:package];
2767 NSDate *seen = [package seen];
2769 CFLocaleRef locale = CFLocaleCopyCurrent();
2770 CFDateFormatterRef formatter = CFDateFormatterCreate(NULL, locale, kCFDateFormatterMediumStyle, kCFDateFormatterMediumStyle);
2771 CFStringRef formatted = CFDateFormatterCreateStringWithDate(NULL, formatter, (CFDateRef) seen);
2773 NSString *name = (NSString *) formatted;
2775 if (section == nil || ![[section name] isEqual:name]) {
2776 section = [[[Section alloc] initWithName:name row:offset] autorelease];
2777 [sections_ addObject:section];
2780 [section addPackage:package];
2782 CFRelease(formatter);
2783 CFRelease(formatted);
2788 count_ = [[upgradable packages] count];
2790 [sections_ insertObject:upgradable atIndex:0];
2794 if (npackage != nil)
2795 [view_ setPackage:npackage];
2796 else if (package_ != nil)
2803 - (void) _resetView {
2804 if ([views_ count] == 1)
2805 [navbar_ showButtonsWithLeftTitle:(count_ == 0 ? nil : @"Upgrade All") rightTitle:nil];
2812 - (void) setDelegate:(id)delegate {
2814 [view_ setDelegate:delegate];
2815 [super setDelegate:delegate];
2820 /* Manage View {{{ */
2821 @interface ManageView : ResetView <
2822 PackageTableDelegate
2824 PackageTable *table_;
2831 - (void) navigationBar:(UINavigationBar *)navbar buttonClicked:(int)button;
2833 - (void) packageTable:(id)table packageSelected:(Package *)package;
2835 - (id) initWithFrame:(CGRect)frame;
2836 - (void) setPackages:(NSArray *)packages;
2838 - (void) setDelegate:(id)delegate;
2841 @implementation ManageView
2847 if (package_ != nil)
2852 - (void) navigationBar:(UINavigationBar *)navbar buttonClicked:(int)button {
2854 [[view_ package] remove];
2855 [delegate_ resolve];
2856 [delegate_ perform];
2860 - (void) packageTable:(id)table packageSelected:(Package *)package {
2861 if (package == nil) {
2868 _assert(package_ == nil);
2869 _assert(view_ == nil);
2871 package_ = [[package name] retain];
2873 view_ = [[PackageView alloc] initWithFrame:[transition_ bounds]];
2874 [view_ setDelegate:delegate_];
2876 [view_ setPackage:package];
2878 [self pushView:view_ withTitle:[package name] backButtonTitle:nil rightButton:@"Uninstall"];
2882 - (id) initWithFrame:(CGRect)frame {
2883 if ((self = [super initWithFrame:frame]) != nil) {
2884 table_ = [[PackageTable alloc] initWithFrame:[transition_ bounds] versioner:@selector(latest)];
2885 [table_ setDelegate:self];
2887 [self pushView:table_ withTitle:@"Uninstall" backButtonTitle:@"Packages" rightButton:nil];
2891 - (void) setPackages:(NSArray *)packages {
2892 NSMutableArray *local = [NSMutableArray arrayWithCapacity:16];
2893 for (size_t i(0); i != [packages count]; ++i) {
2894 Package *package([packages objectAtIndex:i]);
2895 if ([package installed] != nil)
2896 [local addObject:package];
2899 [local sortUsingSelector:@selector(compareByName:)];
2901 Package *npackage = nil;
2902 for (size_t offset = 0, count = [local count]; offset != count; ++offset) {
2903 Package *package = [local objectAtIndex:offset];
2904 if ([[package name] isEqualToString:package_])
2908 [table_ setPackages:local];
2910 if (npackage != nil)
2911 [view_ setPackage:npackage];
2912 else if (package_ != nil)
2918 - (void) setDelegate:(id)delegate {
2920 [view_ setDelegate:delegate];
2921 [super setDelegate:delegate];
2926 /* Search View {{{ */
2927 @protocol SearchViewDelegate
2928 - (void) showKeyboard:(BOOL)show;
2931 @interface SearchView : ResetView <
2932 PackageTableDelegate
2934 NSMutableArray *packages_;
2936 UISearchField *field_;
2937 PackageTable *table_;
2944 - (void) navigationBar:(UINavigationBar *)navbar buttonClicked:(int)button;
2945 - (void) packageTable:(id)table packageSelected:(Package *)package;
2947 - (void) textFieldDidBecomeFirstResponder:(UITextField *)field;
2948 - (void) textFieldDidResignFirstResponder:(UITextField *)field;
2950 - (void) keyboardInputChanged:(UIFieldEditor *)editor;
2951 - (BOOL) keyboardInput:(id)input shouldInsertText:(NSString *)text isMarkedText:(int)marked;
2953 - (id) initWithFrame:(CGRect)frame;
2954 - (void) setPackages:(NSArray *)packages;
2956 - (void) setDelegate:(id)delegate;
2957 - (void) resetPackage:(Package *)package;
2958 - (void) searchPackages;
2962 @implementation SearchView
2965 [packages_ release];
2966 [accessory_ release];
2971 if (package_ != nil)
2976 - (void) navigationBar:(UINavigationBar *)navbar buttonClicked:(int)button {
2978 Package *package = [view_ package];
2979 if ([package installed] == nil)
2983 [delegate_ resolve];
2984 [delegate_ perform];
2988 - (void) packageTable:(id)table packageSelected:(Package *)package {
2989 if (package == nil) {
2990 [navbar_ setAccessoryView:accessory_ animate:(resetting_ ? NO : YES) goingBack:YES];
2998 [navbar_ setAccessoryView:nil animate:YES goingBack:NO];
3000 _assert(package_ == nil);
3001 _assert(view_ == nil);
3003 package_ = [[package name] retain];
3005 view_ = [[PackageView alloc] initWithFrame:[transition_ bounds]];
3006 [view_ setDelegate:delegate_];
3008 [self pushView:view_ withTitle:[package name] backButtonTitle:nil rightButton:nil];
3009 [self resetPackage:package];
3013 - (void) textFieldDidBecomeFirstResponder:(UITextField *)field {
3014 [delegate_ showKeyboard:YES];
3015 [table_ setEnabled:NO];
3017 /*CGColorSpaceRef space = CGColorSpaceCreateDeviceRGB();
3018 CGColor dimmed(alpha, 0, 0, 0, 0.5);
3019 [editor_ setBackgroundColor:dimmed];
3020 CGColorSpaceRelease(space);*/
3023 - (void) textFieldDidResignFirstResponder:(UITextField *)field {
3024 [table_ setEnabled:YES];
3025 [delegate_ showKeyboard:NO];
3028 - (void) keyboardInputChanged:(UIFieldEditor *)editor {
3029 NSString *text([field_ text]);
3030 [field_ setClearButtonStyle:(text == nil || [text length] == 0 ? 0 : 2)];
3033 - (BOOL) keyboardInput:(id)input shouldInsertText:(NSString *)text isMarkedText:(int)marked {
3034 if ([text length] != 1 || [text characterAtIndex:0] != '\n')
3037 [self searchPackages];
3038 [field_ resignFirstResponder];
3042 - (id) initWithFrame:(CGRect)frame {
3043 if ((self = [super initWithFrame:frame]) != nil) {
3044 packages_ = [[NSMutableArray arrayWithCapacity:16] retain];
3046 table_ = [[PackageTable alloc] initWithFrame:[transition_ bounds] versioner:@selector(latest)];
3047 [table_ setDelegate:self];
3049 CGRect area = [self bounds];
3052 area.size.width -= 12;
3053 area.size.height = [UISearchField defaultHeight];
3055 field_ = [[UISearchField alloc] initWithFrame:area];
3057 GSFontRef font = GSFontCreateWithName("Helvetica", kGSFontTraitNone, 16);
3058 [field_ setFont:font];
3061 [field_ setPlaceholder:@"Package Names & Descriptions"];
3062 [field_ setPaddingTop:5];
3063 [field_ setDelegate:self];
3065 UITextTraits *traits = [field_ textTraits];
3066 [traits setEditingDelegate:self];
3067 [traits setReturnKeyType:6];
3069 accessory_ = [[UIView alloc] initWithFrame:CGRectMake(6, 6, area.size.width, area.size.height + 30)];
3070 [accessory_ addSubview:field_];
3072 [navbar_ setAccessoryView:accessory_];
3073 [self pushView:table_ withTitle:nil backButtonTitle:@"Search" rightButton:nil];
3075 /* XXX: for the love of god just fix this */
3076 [navbar_ removeFromSuperview];
3077 [reload_ removeFromSuperview];
3078 [configure_ removeFromSuperview];
3079 [self addSubview:navbar_];
3080 [self addSubview:reload_];
3081 [self addSubview:configure_];
3085 - (void) setPackages:(NSArray *)packages {
3086 [packages_ removeAllObjects];
3087 [packages_ addObjectsFromArray:packages];
3088 [packages_ sortUsingSelector:@selector(compareByName:)];
3090 Package *npackage = nil;
3091 for (size_t offset = 0, count = [packages_ count]; offset != count; ++offset) {
3092 Package *package = [packages_ objectAtIndex:offset];
3093 if ([[package name] isEqualToString:package_])
3097 [self searchPackages];
3099 if (npackage != nil)
3100 [self resetPackage:npackage];
3101 else if (package_ != nil)
3107 - (void) setDelegate:(id)delegate {
3109 [view_ setDelegate:delegate];
3110 [super setDelegate:delegate];
3113 - (void) resetPackage:(Package *)package {
3114 [view_ setPackage:package];
3115 NSString *right = [package installed] == nil ? @"Install" : @"Uninstall";
3116 [navbar_ showButtonsWithLeftTitle:nil rightTitle:right];
3119 - (void) searchPackages {
3120 NSString *text([field_ text]);
3122 NSMutableArray *packages([NSMutableArray arrayWithCapacity:16]);
3124 for (size_t offset(0), count([packages_ count]); offset != count; ++offset) {
3125 Package *package = [packages_ objectAtIndex:offset];
3126 if ([package matches:text])
3127 [packages addObject:package];
3130 [table_ setPackages:packages];
3131 [[table_ table] scrollPointVisibleAtTopLeft:CGPointMake(0, 0) animated:NO];
3137 @interface Cydia : UIApplication <
3138 ConfirmationViewDelegate,
3139 ProgressViewDelegate,
3145 UITransitionView *transition_;
3146 UIButtonBar *buttonbar_;
3148 ConfirmationView *confirm_;
3150 Database *database_;
3151 ProgressView *progress_;
3154 UINavigationBar *navbar_;
3155 UIScroller *scroller_;
3156 UIWebView *webview_;
3158 UIProgressIndicator *indicator_;
3160 InstallView *install_;
3161 ChangesView *changes_;
3162 ManageView *manage_;
3163 SearchView *search_;
3168 UIKeyboard *keyboard_;
3172 - (void) reloadData:(BOOL)reset;
3183 - (void) progressViewIsComplete:(ProgressView *)progress;
3185 - (void) navigationBar:(UINavigationBar *)navbar buttonClicked:(int)button;
3186 - (void) alertSheet:(UIAlertSheet *)sheet buttonClicked:(int)button;
3187 - (void) buttonBarItemTapped:(id)sender;
3189 - (void) view:(UIView *)sender didSetFrame:(CGRect)frame oldFrame:(CGRect)old;
3191 - (void) webView:(WebView *)sender didReceiveTitle:(NSString *)title forFrame:(WebFrame *)frame;
3193 - (void) applicationWillSuspend;
3194 - (void) applicationDidFinishLaunching:(id)unused;
3197 @implementation Cydia
3200 NSMutableURLRequest *request = [NSMutableURLRequest
3202 cachePolicy:NSURLRequestReloadIgnoringCacheData
3203 timeoutInterval:30.0
3206 [request addValue:[NSString stringWithCString:Firmware_] forHTTPHeaderField:@"X-Firmware"];
3207 [request addValue:[NSString stringWithCString:Machine_] forHTTPHeaderField:@"X-Machine"];
3208 [request addValue:[NSString stringWithCString:SerialNumber_] forHTTPHeaderField:@"X-Serial-Number"];
3210 [webview_ loadRequest:request];
3213 - (void) reloadData:(BOOL)reset {
3214 [database_ reloadData];
3218 if (Packages_ == nil) {
3219 Packages_ = [[NSMutableDictionary alloc] initWithCapacity:count];
3220 [Metadata_ setObject:Packages_ forKey:@"Packages"];
3223 now_ = [NSDate date];
3225 NSMutableArray *packages = [NSMutableArray arrayWithCapacity:count];
3226 for (pkgCache::PkgIterator iterator = [database_ cache]->PkgBegin(); !iterator.end(); ++iterator)
3227 if (Package *package = [Package packageWithIterator:iterator database:database_])
3228 [packages addObject:package];
3230 [install_ setPackages:packages];
3231 [changes_ setPackages:packages];
3232 [manage_ setPackages:packages];
3233 [search_ setPackages:packages];
3235 if (size_t count = [changes_ count]) {
3236 NSString *badge([[NSNumber numberWithInt:count] stringValue]);
3237 [buttonbar_ setBadgeValue:badge forButton:3];
3238 if ([buttonbar_ respondsToSelector:@selector(setBadgeAnimated:forButton:)])
3239 [buttonbar_ setBadgeAnimated:YES forButton:3];
3240 [self setApplicationBadge:badge];
3242 [buttonbar_ setBadgeValue:nil forButton:3];
3243 if ([buttonbar_ respondsToSelector:@selector(setBadgeAnimated:forButton:)])
3244 [buttonbar_ setBadgeAnimated:NO forButton:3];
3245 [self removeApplicationBadge];
3248 _assert([Metadata_ writeToFile:@"/var/lib/cydia/metadata.plist" atomically:YES] == YES);
3251 - (void) setPrompt {
3252 [navbar_ setPrompt:[NSString stringWithFormat:@"Last Updated: %@", GetLastUpdate()]];
3256 pkgProblemResolver *resolver = [database_ resolver];
3258 resolver->InstallProtect();
3259 if (!resolver->Resolve(true))
3264 [database_ prepare];
3265 confirm_ = [[ConfirmationView alloc] initWithView:underlay_ database:database_ delegate:self];
3269 [database_ upgrade];
3274 [self reloadData:NO];
3280 [overlay_ removeFromSuperview];
3284 detachNewThreadSelector:@selector(perform)
3291 - (void) bootstrap_ {
3293 [database_ upgrade];
3294 [database_ prepare];
3295 [database_ perform];
3298 - (void) bootstrap {
3300 detachNewThreadSelector:@selector(bootstrap_)
3303 title:@"Bootstrap Install..."
3309 detachNewThreadSelector:@selector(update)
3312 title:@"Refreshing Sources..."
3316 - (void) progressViewIsComplete:(ProgressView *)progress {
3317 [self reloadData:YES];
3319 if (confirm_ != nil) {
3320 [underlay_ addSubview:overlay_];
3321 [confirm_ removeFromSuperview];
3327 - (void) navigationBar:(UINavigationBar *)navbar buttonClicked:(int)button {
3334 UIAlertSheet *sheet = [[[UIAlertSheet alloc]
3335 initWithTitle:@"About Cydia Packager"
3336 buttons:[NSArray arrayWithObjects:@"Close", nil]
3337 defaultButtonIndex:0
3343 @"Copyright (C) 2008\n"
3344 "Jay Freeman (saurik)\n"
3345 "saurik@saurik.com\n"
3346 "http://www.saurik.com/\n"
3349 "http://www.theokorigroup.com/\n"
3351 "College of Creative Studies,\n"
3352 "University of California,\n"
3354 "http://www.ccs.ucsb.edu/\n"
3357 "bad_, BHSPitMonkey, cash, Cobra,\n"
3358 "core, Corona, crashx, cromas,\n"
3359 "Darken, dtzWill, Erica, francis,\n"
3360 "Godores, jerry, Kingstone, lounger,\n"
3361 "mbranes, rockabilly, tman, Wbiggs"
3364 [sheet presentSheetFromButtonBar:buttonbar_];
3369 - (void) alertSheet:(UIAlertSheet *)sheet buttonClicked:(int)button {
3373 - (void) buttonBarItemTapped:(id)sender {
3375 unsigned tag = [sender tag];
3378 case 1: view = featured_; break;
3379 case 2: view = install_; break;
3380 case 3: view = changes_; break;
3381 case 4: view = manage_; break;
3382 case 5: view = search_; break;
3388 if ([view respondsToSelector:@selector(resetView:)])
3389 [(id) view resetView:(tag == tag_ ? NO : YES)];
3391 [transition_ transition:0 toView:view];
3394 - (void) view:(UIView *)sender didSetFrame:(CGRect)frame oldFrame:(CGRect)old {
3395 [scroller_ setContentSize:frame.size];
3396 [indicator_ stopAnimation];
3399 - (void) webView:(WebView *)sender didReceiveTitle:(NSString *)title forFrame:(WebFrame *)frame {
3400 [navbar_ setPrompt:title];
3403 - (void) webView:(WebView *)sender didStartProvisionalLoadForFrame:(WebFrame *)frame {
3404 [navbar_ setPrompt:@"Loading..."];
3405 [indicator_ startAnimation];
3408 - (void) applicationWillSuspend {
3410 system("launchctl stop com.apple.SpringBoard");
3412 [super applicationWillSuspend];
3415 - (void) applicationDidFinishLaunching:(id)unused {
3416 _assert(pkgInitConfig(*_config));
3417 _assert(pkgInitSystem(*_config, _system));
3423 CGRect screenrect = [UIHardware fullScreenApplicationContentRect];
3424 window_ = [[UIWindow alloc] initWithContentRect:screenrect];
3426 [window_ orderFront: self];
3427 [window_ makeKey: self];
3428 [window_ _setHidden: NO];
3430 progress_ = [[ProgressView alloc] initWithFrame:[window_ bounds] delegate:self];
3431 [window_ setContentView:progress_];
3433 underlay_ = [[UIView alloc] initWithFrame:[progress_ bounds]];
3434 [progress_ setContentView:underlay_];
3436 overlay_ = [[UIView alloc] initWithFrame:[underlay_ bounds]];
3439 [underlay_ addSubview:overlay_];
3441 transition_ = [[UITransitionView alloc] initWithFrame:CGRectMake(
3442 0, 0, screenrect.size.width, screenrect.size.height - 48
3445 [overlay_ addSubview:transition_];
3447 featured_ = [[UIView alloc] initWithFrame:[transition_ bounds]];
3449 CGSize navsize = [UINavigationBar defaultSizeWithPrompt];
3450 CGRect navrect = {{0, 0}, navsize};
3452 navbar_ = [[UINavigationBar alloc] initWithFrame:navrect];
3453 [featured_ addSubview:navbar_];
3455 [navbar_ setBarStyle:1];
3456 [navbar_ setDelegate:self];
3458 [navbar_ showButtonsWithLeftTitle:@"About" rightTitle:@"Reload"];
3460 UINavigationItem *navitem = [[[UINavigationItem alloc] initWithTitle:@"Featured"] autorelease];
3461 [navbar_ pushNavigationItem:navitem];
3463 struct CGRect subbounds = [featured_ bounds];
3464 subbounds.origin.y += navsize.height;
3465 subbounds.size.height -= navsize.height;
3467 UIImageView *pinstripe = [[[UIImageView alloc] initWithFrame:subbounds] autorelease];
3468 [pinstripe setImage:[UIImage applicationImageNamed:@"pinstripe.png"]];
3469 [featured_ addSubview:pinstripe];
3471 scroller_ = [[UIScroller alloc] initWithFrame:subbounds];
3472 [featured_ addSubview:scroller_];
3474 [scroller_ setScrollingEnabled:YES];
3475 [scroller_ setAdjustForContentSizeChange:YES];
3476 [scroller_ setClipsSubviews:YES];
3477 [scroller_ setAllowsRubberBanding:YES];
3478 [scroller_ setScrollDecelerationFactor:0.99];
3479 [scroller_ setDelegate:self];
3481 CGRect webrect = [scroller_ bounds];
3482 webrect.size.height = 0;
3484 webview_ = [[UIWebView alloc] initWithFrame:webrect];
3485 [scroller_ addSubview:webview_];
3487 [webview_ setTilingEnabled:YES];
3488 [webview_ setTileSize:CGSizeMake(screenrect.size.width, 500)];
3489 [webview_ setAutoresizes:YES];
3490 [webview_ setDelegate:self];
3492 CGSize indsize = [UIProgressIndicator defaultSizeForStyle:2];
3493 indicator_ = [[UIProgressIndicator alloc] initWithFrame:CGRectMake(87, 45, indsize.width, indsize.height)];
3494 [indicator_ setStyle:2];
3495 [featured_ addSubview:indicator_];
3497 NSArray *buttonitems = [NSArray arrayWithObjects:
3498 [NSDictionary dictionaryWithObjectsAndKeys:
3499 @"buttonBarItemTapped:", kUIButtonBarButtonAction,
3500 @"featured-up.png", kUIButtonBarButtonInfo,
3501 @"featured-dn.png", kUIButtonBarButtonSelectedInfo,
3502 [NSNumber numberWithInt:1], kUIButtonBarButtonTag,
3503 self, kUIButtonBarButtonTarget,
3504 @"Featured", kUIButtonBarButtonTitle,
3505 @"0", kUIButtonBarButtonType,
3508 [NSDictionary dictionaryWithObjectsAndKeys:
3509 @"buttonBarItemTapped:", kUIButtonBarButtonAction,
3510 @"install-up.png", kUIButtonBarButtonInfo,
3511 @"install-dn.png", kUIButtonBarButtonSelectedInfo,
3512 [NSNumber numberWithInt:2], kUIButtonBarButtonTag,
3513 self, kUIButtonBarButtonTarget,
3514 @"Install", kUIButtonBarButtonTitle,
3515 @"0", kUIButtonBarButtonType,
3518 [NSDictionary dictionaryWithObjectsAndKeys:
3519 @"buttonBarItemTapped:", kUIButtonBarButtonAction,
3520 @"changes-up.png", kUIButtonBarButtonInfo,
3521 @"changes-dn.png", kUIButtonBarButtonSelectedInfo,
3522 [NSNumber numberWithInt:3], kUIButtonBarButtonTag,
3523 self, kUIButtonBarButtonTarget,
3524 @"Changes", kUIButtonBarButtonTitle,
3525 @"0", kUIButtonBarButtonType,
3528 [NSDictionary dictionaryWithObjectsAndKeys:
3529 @"buttonBarItemTapped:", kUIButtonBarButtonAction,
3530 @"manage-up.png", kUIButtonBarButtonInfo,
3531 @"manage-dn.png", kUIButtonBarButtonSelectedInfo,
3532 [NSNumber numberWithInt:4], kUIButtonBarButtonTag,
3533 self, kUIButtonBarButtonTarget,
3534 @"Uninstall", kUIButtonBarButtonTitle,
3535 @"0", kUIButtonBarButtonType,
3538 [NSDictionary dictionaryWithObjectsAndKeys:
3539 @"buttonBarItemTapped:", kUIButtonBarButtonAction,
3540 @"search-up.png", kUIButtonBarButtonInfo,
3541 @"search-dn.png", kUIButtonBarButtonSelectedInfo,
3542 [NSNumber numberWithInt:5], kUIButtonBarButtonTag,
3543 self, kUIButtonBarButtonTarget,
3544 @"Search", kUIButtonBarButtonTitle,
3545 @"0", kUIButtonBarButtonType,
3549 buttonbar_ = [[UIButtonBar alloc]
3551 withFrame:CGRectMake(
3552 0, screenrect.size.height - 48,
3553 screenrect.size.width, 48
3555 withItemList:buttonitems
3558 [buttonbar_ setDelegate:self];
3559 [buttonbar_ setBarStyle:1];
3560 [buttonbar_ setButtonBarTrackingMode:2];
3562 int buttons[5] = {1, 2, 3, 4, 5};
3563 [buttonbar_ registerButtonGroup:0 withButtons:buttons withCount:5];
3564 [buttonbar_ showButtonGroup:0 withDuration:0];
3566 for (int i = 0; i != 5; ++i)
3567 [[buttonbar_ viewWithTag:(i + 1)] setFrame:CGRectMake(
3568 i * 64 + 2, 1, 60, 48
3571 [buttonbar_ showSelectionForButton:1];
3572 [transition_ transition:0 toView:featured_];
3574 [overlay_ addSubview:buttonbar_];
3576 [UIKeyboard initImplementationNow];
3578 CGRect edtrect = [overlay_ bounds];
3579 edtrect.origin.y += navsize.height;
3580 edtrect.size.height -= navsize.height;
3582 CGSize keysize = [UIKeyboard defaultSize];
3583 CGRect keyrect = {{0, [overlay_ bounds].size.height - keysize.height}, keysize};
3584 keyboard_ = [[UIKeyboard alloc] initWithFrame:keyrect];
3586 database_ = [[Database alloc] init];
3587 [database_ setDelegate:progress_];
3589 install_ = [[InstallView alloc] initWithFrame:[transition_ bounds]];
3590 [install_ setDelegate:self];
3592 changes_ = [[ChangesView alloc] initWithFrame:[transition_ bounds]];
3593 [changes_ setDelegate:self];
3595 manage_ = [[ManageView alloc] initWithFrame:[transition_ bounds]];
3596 [manage_ setDelegate:self];
3598 search_ = [[SearchView alloc] initWithFrame:[transition_ bounds]];
3599 [search_ setDelegate:self];
3601 [self reloadData:NO];
3603 Package *package([database_ packageWithName:@"cydia"]);
3604 NSString *application = package == nil ? @"Cydia" : [NSString
3605 stringWithFormat:@"Cydia/%@",
3609 WebView *webview = [webview_ webView];
3610 [webview setApplicationNameForUserAgent:application];
3611 [webview setFrameLoadDelegate:self];
3613 url_ = [NSURL URLWithString:@"http://cydia.saurik.com/"];
3616 [progress_ resetView];
3622 - (void) showKeyboard:(BOOL)show {
3624 [overlay_ addSubview:keyboard_];
3626 [keyboard_ removeFromSuperview];
3631 void AddPreferences(NSString *plist) {
3632 NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init];
3634 NSMutableDictionary *settings = [[[NSMutableDictionary alloc] initWithContentsOfFile:plist] autorelease];
3635 _assert(settings != NULL);
3636 NSMutableArray *items = [settings objectForKey:@"items"];
3640 for (size_t i(0); i != [items count]; ++i) {
3641 NSMutableDictionary *item([items objectAtIndex:i]);
3642 NSString *label = [item objectForKey:@"label"];
3643 if (label != nil && [label isEqualToString:@"Cydia"]) {
3650 for (size_t i(0); i != [items count]; ++i) {
3651 NSDictionary *item([items objectAtIndex:i]);
3652 NSString *label = [item objectForKey:@"label"];
3653 if (label != nil && [label isEqualToString:@"General"]) {
3654 [items insertObject:[NSDictionary dictionaryWithObjectsAndKeys:
3655 @"CydiaSettings", @"bundle",
3656 @"PSLinkCell", @"cell",
3657 [NSNumber numberWithBool:YES], @"hasIcon",
3658 [NSNumber numberWithBool:YES], @"isController",
3660 nil] atIndex:(i + 1)];
3666 _assert([settings writeToFile:plist atomically:YES] == YES);
3673 id Alloc_(id self, SEL selector) {
3674 id object = alloc_(self, selector);
3675 fprintf(stderr, "[%s]A-%p\n", self->isa->name, object);
3679 int main(int argc, char *argv[]) {
3681 memset(nl, 0, sizeof(nl));
3682 nl[0].n_un.n_name = "_useMDNSResponder";
3683 nlist("/usr/lib/libc.dylib", nl);
3684 if (nl[0].n_type != N_UNDF)
3685 *(int *) nl[0].n_value = 0;
3687 bootstrap_ = argc > 1 && strcmp(argv[1], "--bootstrap") == 0;
3692 /*Method alloc = class_getClassMethod([NSObject class], @selector(alloc));
3693 alloc_ = alloc->method_imp;
3694 alloc->method_imp = (IMP) &Alloc_;*/
3696 NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init];
3698 if (NSDictionary *sysver = [NSDictionary dictionaryWithContentsOfFile:@"/System/Library/CoreServices/SystemVersion.plist"]) {
3699 if (NSString *prover = [sysver valueForKey:@"ProductVersion"]) {
3700 Firmware_ = strdup([prover cString]);
3701 NSArray *versions = [prover componentsSeparatedByString:@"."];
3702 int count = [versions count];
3703 Major_ = count > 0 ? [[versions objectAtIndex:0] intValue] : 0;
3704 Minor_ = count > 1 ? [[versions objectAtIndex:1] intValue] : 0;
3705 BugFix_ = count > 2 ? [[versions objectAtIndex:2] intValue] : 0;
3710 sysctlbyname("hw.machine", NULL, &size, NULL, 0);
3711 char *machine = new char[size];
3712 sysctlbyname("hw.machine", machine, &size, NULL, 0);
3715 if (CFMutableDictionaryRef dict = IOServiceMatching("IOPlatformExpertDevice"))
3716 if (io_service_t service = IOServiceGetMatchingService(kIOMasterPortDefault, dict)) {
3717 if (CFTypeRef serial = IORegistryEntryCreateCFProperty(service, CFSTR(kIOPlatformSerialNumberKey), kCFAllocatorDefault, 0)) {
3718 SerialNumber_ = strdup(CFStringGetCStringPtr((CFStringRef) serial, CFStringGetSystemEncoding()));
3722 IOObjectRelease(service);
3725 /*AddPreferences(@"/Applications/Preferences.app/Settings-iPhone.plist");
3726 AddPreferences(@"/Applications/Preferences.app/Settings-iPod.plist");*/
3728 if ((Metadata_ = [[NSMutableDictionary alloc] initWithContentsOfFile:@"/var/lib/cydia/metadata.plist"]) == NULL)
3729 Metadata_ = [[NSMutableDictionary alloc] initWithCapacity:2];
3731 Packages_ = [Metadata_ objectForKey:@"Packages"];
3733 setenv("CYDIA", "", _not(int));
3734 if (access("/User", F_OK) != 0)
3735 system("/usr/libexec/cydia/firmware.sh");
3736 system("dpkg --configure -a");
3738 UIApplicationMain(argc, argv, [Cydia class]);