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 {
1725 _assert(cache_.Open(progress_, true));
1726 records_ = new pkgRecords(cache_);
1727 resolver_ = new pkgProblemResolver(cache_);
1728 fetcher_ = new pkgAcquire(&status_);
1733 pkgRecords records(cache_);
1735 lock_ = new FileFd();
1736 lock_->Fd(GetLock(_config->FindDir("Dir::Cache::Archives") + "lock"));
1737 _assert(!_error->PendingError());
1740 _assert(list.ReadMainList());
1742 manager_ = (_system->CreatePM(cache_));
1743 _assert(manager_->GetArchives(fetcher_, &list, &records));
1744 _assert(!_error->PendingError());
1748 if (fetcher_->Run(PulseInterval_) != pkgAcquire::Continue)
1752 pkgPackageManager::OrderResult result = manager_->DoInstall(statusfd_);
1754 if (result == pkgPackageManager::Failed)
1756 if (_error->PendingError())
1758 if (result != pkgPackageManager::Completed)
1764 _assert(list.ReadMainList());
1767 lock.Fd(GetLock(_config->FindDir("Dir::State::Lists") + "lock"));
1768 _assert(!_error->PendingError());
1770 pkgAcquire fetcher(&status_);
1771 _assert(list.GetIndexes(&fetcher));
1772 _assert(fetcher.Run(PulseInterval_) != pkgAcquire::Failed);
1774 bool failed = false;
1775 for (pkgAcquire::ItemIterator item = fetcher.ItemsBegin(); item != fetcher.ItemsEnd(); item++)
1776 if ((*item)->Status != pkgAcquire::Item::StatDone) {
1777 (*item)->Finished();
1781 if (!failed && _config->FindB("APT::Get::List-Cleanup", true) == true) {
1782 _assert(fetcher.Clean(_config->FindDir("Dir::State::lists")));
1783 _assert(fetcher.Clean(_config->FindDir("Dir::State::lists") + "partial/"));
1786 [Metadata_ setObject:[NSDate date] forKey:@"LastUpdate"];
1790 _assert(cache_->DelCount() == 0 && cache_->InstCount() == 0);
1791 _assert(pkgApplyStatus(cache_));
1793 if (cache_->BrokenCount() != 0) {
1794 _assert(pkgFixBroken(cache_));
1795 _assert(cache_->BrokenCount() == 0);
1796 _assert(pkgMinimizeUpgrade(cache_));
1799 _assert(pkgDistUpgrade(cache_));
1802 - (void) setDelegate:(id)delegate {
1803 delegate_ = delegate;
1804 status_.setDelegate(delegate);
1805 progress_.setDelegate(delegate);
1811 /* Progress Data {{{ */
1812 @interface ProgressData : NSObject {
1818 - (ProgressData *) initWithSelector:(SEL)selector target:(id)target object:(id)object;
1825 @implementation ProgressData
1827 - (ProgressData *) initWithSelector:(SEL)selector target:(id)target object:(id)object {
1828 if ((self = [super init]) != nil) {
1829 selector_ = selector;
1849 /* Progress View {{{ */
1850 @interface ProgressView : UIView <
1854 UIView *background_;
1855 UITransitionView *transition_;
1857 UINavigationBar *navbar_;
1858 UIProgressBar *progress_;
1859 UITextView *output_;
1860 UITextLabel *status_;
1866 - (void) transitionViewDidComplete:(UITransitionView*)view fromView:(UIView*)from toView:(UIView*)to;
1868 - (ProgressView *) initWithFrame:(struct CGRect)frame delegate:(id)delegate;
1869 - (void) setContentView:(UIView *)view;
1872 - (void) alertSheet:(UIAlertSheet *)sheet buttonClicked:(int)button;
1874 - (void) _retachThread;
1875 - (void) _detachNewThreadData:(ProgressData *)data;
1876 - (void) detachNewThreadSelector:(SEL)selector toTarget:(id)target withObject:(id)object title:(NSString *)title;
1878 - (void) setError:(NSString *)error;
1879 - (void) _setError:(NSString *)error;
1881 - (void) setTitle:(NSString *)title;
1882 - (void) _setTitle:(NSString *)title;
1884 - (void) setPercent:(float)percent;
1885 - (void) _setPercent:(NSNumber *)percent;
1887 - (void) addOutput:(NSString *)output;
1888 - (void) _addOutput:(NSString *)output;
1891 @protocol ProgressViewDelegate
1892 - (void) progressViewIsComplete:(ProgressView *)sender;
1895 @implementation ProgressView
1899 if (background_ != nil)
1900 [background_ release];
1901 [transition_ release];
1904 [progress_ release];
1910 - (void) transitionViewDidComplete:(UITransitionView*)view fromView:(UIView*)from toView:(UIView*)to {
1911 if (bootstrap_ && from == overlay_ && to == view_)
1915 - (ProgressView *) initWithFrame:(struct CGRect)frame delegate:(id)delegate {
1916 if ((self = [super initWithFrame:frame]) != nil) {
1917 delegate_ = delegate;
1919 CGColorSpaceRef space = CGColorSpaceCreateDeviceRGB();
1921 CGColor black(space, 0.0, 0.0, 0.0, 1.0);
1922 CGColor white(space, 1.0, 1.0, 1.0, 1.0);
1923 CGColor clear(space, 0.0, 0.0, 0.0, 0.0);
1925 transition_ = [[UITransitionView alloc] initWithFrame:[self bounds]];
1926 [transition_ setDelegate:self];
1928 overlay_ = [[UIView alloc] initWithFrame:[transition_ bounds]];
1931 [overlay_ setBackgroundColor:black];
1933 background_ = [[UIView alloc] initWithFrame:[self bounds]];
1934 [background_ setBackgroundColor:black];
1935 [self addSubview:background_];
1938 [self addSubview:transition_];
1940 CGSize navsize = [UINavigationBar defaultSize];
1941 CGRect navrect = {{0, 0}, navsize};
1943 navbar_ = [[UINavigationBar alloc] initWithFrame:navrect];
1944 [overlay_ addSubview:navbar_];
1946 [navbar_ setBarStyle:1];
1947 [navbar_ setDelegate:self];
1949 UINavigationItem *navitem = [[[UINavigationItem alloc] initWithTitle:nil] autorelease];
1950 [navbar_ pushNavigationItem:navitem];
1952 CGRect bounds = [overlay_ bounds];
1953 CGSize prgsize = [UIProgressBar defaultSize];
1956 (bounds.size.width - prgsize.width) / 2,
1957 bounds.size.height - prgsize.height - 20
1960 progress_ = [[UIProgressBar alloc] initWithFrame:prgrect];
1961 [overlay_ addSubview:progress_];
1963 status_ = [[UITextLabel alloc] initWithFrame:CGRectMake(
1965 bounds.size.height - prgsize.height - 50,
1966 bounds.size.width - 20,
1970 [status_ setColor:white];
1971 [status_ setBackgroundColor:clear];
1973 [status_ setCentersHorizontally:YES];
1974 //[status_ setFont:font];
1976 output_ = [[UITextView alloc] initWithFrame:CGRectMake(
1978 navrect.size.height + 20,
1979 bounds.size.width - 20,
1980 bounds.size.height - navsize.height - 62 - navrect.size.height
1983 //[output_ setTextFont:@"Courier New"];
1984 [output_ setTextSize:12];
1986 [output_ setTextColor:white];
1987 [output_ setBackgroundColor:clear];
1989 [output_ setMarginTop:0];
1990 [output_ setAllowsRubberBanding:YES];
1992 [overlay_ addSubview:output_];
1993 [overlay_ addSubview:status_];
1995 [progress_ setStyle:0];
1997 CGColorSpaceRelease(space);
2001 - (void) setContentView:(UIView *)view {
2002 view_ = [view retain];
2005 - (void) resetView {
2006 [transition_ transition:6 toView:view_];
2009 - (void) alertSheet:(UIAlertSheet *)sheet buttonClicked:(int)button {
2013 - (void) _retachThread {
2014 [delegate_ progressViewIsComplete:self];
2018 - (void) _detachNewThreadData:(ProgressData *)data {
2019 NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init];
2021 [[data target] performSelector:[data selector] withObject:[data object]];
2024 [self performSelectorOnMainThread:@selector(_retachThread) withObject:nil waitUntilDone:YES];
2029 - (void) detachNewThreadSelector:(SEL)selector toTarget:(id)target withObject:(id)object title:(NSString *)title {
2030 [navbar_ popNavigationItem];
2031 UINavigationItem *navitem = [[[UINavigationItem alloc] initWithTitle:title] autorelease];
2032 [navbar_ pushNavigationItem:navitem];
2034 [status_ setText:nil];
2035 [output_ setText:@""];
2036 [progress_ setProgress:0];
2038 [transition_ transition:6 toView:overlay_];
2041 detachNewThreadSelector:@selector(_detachNewThreadData:)
2043 withObject:[[ProgressData alloc]
2044 initWithSelector:selector
2051 - (void) setError:(NSString *)error {
2053 performSelectorOnMainThread:@selector(_setError:)
2059 - (void) _setError:(NSString *)error {
2060 UIAlertSheet *sheet = [[[UIAlertSheet alloc]
2061 initWithTitle:@"Package Error"
2062 buttons:[NSArray arrayWithObjects:@"Okay", nil]
2063 defaultButtonIndex:0
2068 [sheet setBodyText:error];
2069 [sheet popupAlertAnimated:YES];
2072 - (void) setTitle:(NSString *)title {
2074 performSelectorOnMainThread:@selector(_setTitle:)
2080 - (void) _setTitle:(NSString *)title {
2081 [status_ setText:[title stringByAppendingString:@"..."]];
2084 - (void) setPercent:(float)percent {
2086 performSelectorOnMainThread:@selector(_setPercent:)
2087 withObject:[NSNumber numberWithFloat:percent]
2092 - (void) _setPercent:(NSNumber *)percent {
2093 [progress_ setProgress:[percent floatValue]];
2096 - (void) addOutput:(NSString *)output {
2098 performSelectorOnMainThread:@selector(_addOutput:)
2104 - (void) _addOutput:(NSString *)output {
2105 [output_ setText:[NSString stringWithFormat:@"%@\n%@", [output_ text], output]];
2106 CGSize size = [output_ contentSize];
2107 CGRect rect = {{0, size.height}, {size.width, 0}};
2108 [output_ scrollRectToVisible:rect animated:YES];
2114 /* Package Table {{{ */
2115 @protocol PackageTableDelegate
2116 - (void) packageTable:(id)table packageSelected:(Package *)package;
2119 @interface PackageTable : UIView {
2121 UISectionList *list_;
2125 NSMutableArray *sections_;
2130 - (int) numberOfSectionsInSectionList:(UISectionList *)list;
2131 - (NSString *) sectionList:(UISectionList *)list titleForSection:(int)section;
2132 - (int) sectionList:(UISectionList *)list rowForSection:(int)section;
2134 - (int) numberOfRowsInTable:(UITable *)table;
2135 - (float) table:(UITable *)table heightForRow:(int)row;
2136 - (UITableCell *) table:(UITable *)table cellForRow:(int)row column:(UITableColumn *)col reusing:(UITableCell *)reusing;
2137 - (BOOL) table:(UITable *)table showDisclosureForRow:(int)row;
2138 - (void) tableRowSelected:(NSNotification *)notification;
2140 - (id) initWithFrame:(CGRect)frame versioner:(SEL)versioner;
2142 - (void) setDelegate:(id)delegate;
2143 - (void) setPackages:(NSArray *)packages;
2145 - (void) resetViewAnimated:(BOOL)animated;
2146 - (UITable *) table;
2149 @implementation PackageTable
2153 [sections_ release];
2154 if (packages_ != nil)
2155 [packages_ release];
2159 - (int) numberOfSectionsInSectionList:(UISectionList *)list {
2160 return [sections_ count];
2163 - (NSString *) sectionList:(UISectionList *)list titleForSection:(int)section {
2164 return [[sections_ objectAtIndex:section] name];
2167 - (int) sectionList:(UISectionList *)list rowForSection:(int)section {
2168 return [[sections_ objectAtIndex:section] row];
2171 - (int) numberOfRowsInTable:(UITable *)table {
2172 return [packages_ count];
2175 - (float) table:(UITable *)table heightForRow:(int)row {
2179 - (UITableCell *) table:(UITable *)table cellForRow:(int)row column:(UITableColumn *)col reusing:(UITableCell *)reusing {
2181 reusing = [[[PackageCell alloc] initWithVersioner:versioner_] autorelease];
2182 [(PackageCell *)reusing setPackage:[packages_ objectAtIndex:row]];
2186 - (BOOL) table:(UITable *)table showDisclosureForRow:(int)row {
2190 - (void) tableRowSelected:(NSNotification *)notification {
2191 int row = [[notification object] selectedRow];
2192 [delegate_ packageTable:self packageSelected:(row == INT_MAX ? nil : [packages_ objectAtIndex:row])];
2195 - (id) initWithFrame:(CGRect)frame versioner:(SEL)versioner {
2196 if ((self = [super initWithFrame:frame]) != nil) {
2197 versioner_ = versioner;
2198 sections_ = [[NSMutableArray arrayWithCapacity:16] retain];
2200 list_ = [[UISectionList alloc] initWithFrame:[self bounds] showSectionIndex:YES];
2201 [list_ setDataSource:self];
2203 UITableColumn *column = [[[UITableColumn alloc]
2204 initWithTitle:@"Name"
2206 width:frame.size.width
2209 UITable *table = [list_ table];
2210 [table setSeparatorStyle:1];
2211 [table addTableColumn:column];
2212 [table setDelegate:self];
2213 [table setReusesTableCells:YES];
2215 [self addSubview:list_];
2219 - (void) setDelegate:(id)delegate {
2220 delegate_ = delegate;
2223 - (void) setPackages:(NSArray *)packages {
2224 if (packages_ != nil)
2225 [packages_ autorelease];
2226 _assert(packages != nil);
2227 packages_ = [packages retain];
2229 [sections_ removeAllObjects];
2231 Section *section = nil;
2233 for (size_t offset(0); offset != [packages_ count]; ++offset) {
2234 Package *package = [packages_ objectAtIndex:offset];
2235 NSString *name = [package index];
2237 if (section == nil || ![[section name] isEqual:name]) {
2238 section = [[[Section alloc] initWithName:name row:offset] autorelease];
2239 [sections_ addObject:section];
2242 [section addPackage:package];
2248 - (void) resetViewAnimated:(BOOL)animated {
2249 [[list_ table] selectRow:-1 byExtendingSelection:NO withFade:animated];
2252 - (UITable *) table {
2253 return [list_ table];
2259 /* Section Cell {{{ */
2260 @interface SectionCell : UITableCell {
2262 UITextLabel *count_;
2268 - (void) setSection:(Section *)section;
2270 - (void) _setSelected:(float)fraction;
2271 - (void) setSelected:(BOOL)selected;
2272 - (void) setSelected:(BOOL)selected withFade:(BOOL)fade;
2273 - (void) _setSelectionFadeFraction:(float)fraction;
2277 @implementation SectionCell
2286 if ((self = [super init]) != nil) {
2287 GSFontRef bold = GSFontCreateWithName("Helvetica", kGSFontTraitBold, 22);
2288 GSFontRef small = GSFontCreateWithName("Helvetica", kGSFontTraitBold, 12);
2290 CGColorSpaceRef space = CGColorSpaceCreateDeviceRGB();
2291 CGColor clear(space, 0, 0, 0, 0);
2292 CGColor white(space, 1, 1, 1, 1);
2294 name_ = [[UITextLabel alloc] initWithFrame:CGRectMake(47, 9, 250, 25)];
2295 [name_ setBackgroundColor:clear];
2296 [name_ setFont:bold];
2298 count_ = [[UITextLabel alloc] initWithFrame:CGRectMake(11, 7, 29, 32)];
2299 [count_ setCentersHorizontally:YES];
2300 [count_ setBackgroundColor:clear];
2301 [count_ setFont:small];
2302 [count_ setColor:white];
2304 UIImageView *folder = [[[UIImageView alloc] initWithFrame:CGRectMake(8, 7, 32, 32)] autorelease];
2305 [folder setImage:[UIImage applicationImageNamed:@"folder.png"]];
2307 [self addSubview:folder];
2308 [self addSubview:name_];
2309 [self addSubview:count_];
2311 [self _setSelected:0];
2313 CGColorSpaceRelease(space);
2320 - (void) setSection:(Section *)section {
2321 if (section == nil) {
2322 [name_ setText:@"All Packages"];
2323 [count_ setText:nil];
2325 [name_ setText:[section name]];
2326 [count_ setText:[NSString stringWithFormat:@"%d", [section count]]];
2330 - (void) _setSelected:(float)fraction {
2331 CGColorSpaceRef space = CGColorSpaceCreateDeviceRGB();
2333 CGColor black(space,
2334 interpolate(0.0, 1.0, fraction),
2335 interpolate(0.0, 1.0, fraction),
2336 interpolate(0.0, 1.0, fraction),
2339 [name_ setColor:black];
2341 CGColorSpaceRelease(space);
2344 - (void) setSelected:(BOOL)selected {
2345 [self _setSelected:(selected ? 1.0 : 0.0)];
2346 [super setSelected:selected];
2349 - (void) setSelected:(BOOL)selected withFade:(BOOL)fade {
2351 [self _setSelected:(selected ? 1.0 : 0.0)];
2352 [super setSelected:selected withFade:fade];
2355 - (void) _setSelectionFadeFraction:(float)fraction {
2356 [self _setSelected:fraction];
2357 [super _setSelectionFadeFraction:fraction];
2362 /* Install View {{{ */
2363 @interface InstallView : ResetView <
2364 PackageTableDelegate
2368 PackageTable *table_;
2372 NSMutableArray *packages_;
2377 - (void) navigationBar:(UINavigationBar *)navbar buttonClicked:(int)button;
2379 - (int) numberOfRowsInTable:(UITable *)table;
2380 - (float) table:(UITable *)table heightForRow:(int)row;
2381 - (UITableCell *) table:(UITable *)table cellForRow:(int)row column:(UITableColumn *)col reusing:(UITableCell *)reusing;
2382 - (BOOL) table:(UITable *)table showDisclosureForRow:(int)row;
2383 - (void) tableRowSelected:(NSNotification *)notification;
2385 - (void) packageTable:(id)table packageSelected:(Package *)package;
2387 - (id) initWithFrame:(CGRect)frame;
2388 - (void) setPackages:(NSArray *)packages;
2389 - (void) setDelegate:(id)delegate;
2392 @implementation InstallView
2395 [packages_ release];
2396 if (sections_ != nil)
2397 [sections_ release];
2404 if (section_ != nil)
2406 if (package_ != nil)
2411 - (void) navigationBar:(UINavigationBar *)navbar buttonClicked:(int)button {
2413 [[view_ package] install];
2414 [delegate_ resolve];
2415 [delegate_ perform];
2419 - (int) numberOfRowsInTable:(UITable *)table {
2420 return [sections_ count] + 1;
2423 - (float) table:(UITable *)table heightForRow:(int)row {
2427 - (UITableCell *) table:(UITable *)table cellForRow:(int)row column:(UITableColumn *)col reusing:(UITableCell *)reusing {
2429 reusing = [[[SectionCell alloc] init] autorelease];
2431 [(SectionCell *)reusing setSection:nil];
2433 [(SectionCell *)reusing setSection:[sections_ objectAtIndex:(row - 1)]];
2437 - (BOOL) table:(UITable *)table showDisclosureForRow:(int)row {
2441 - (void) tableRowSelected:(NSNotification *)notification {
2442 int row = [[notification object] selectedRow];
2444 if (row == INT_MAX) {
2451 _assert(section_ == nil);
2452 _assert(table_ == nil);
2460 name = @"All Packages";
2462 section = [sections_ objectAtIndex:(row - 1)];
2463 name = [section name];
2464 section_ = [name retain];
2467 table_ = [[PackageTable alloc] initWithFrame:[transition_ bounds] versioner:@selector(latest)];
2468 [table_ setDelegate:self];
2469 [table_ setPackages:(section == nil ? packages_ : [section packages])];
2471 [self pushView:table_ withTitle:name backButtonTitle:@"Packages" rightButton:nil];
2475 - (void) packageTable:(id)table packageSelected:(Package *)package {
2476 if (package == nil) {
2483 _assert(package_ == nil);
2484 _assert(view_ == nil);
2486 package_ = [[package name] retain];
2488 view_ = [[PackageView alloc] initWithFrame:[transition_ bounds]];
2489 [view_ setDelegate:delegate_];
2491 [view_ setPackage:package];
2493 [self pushView:view_ withTitle:[package name] backButtonTitle:nil rightButton:@"Install"];
2497 - (id) initWithFrame:(CGRect)frame {
2498 if ((self = [super initWithFrame:frame]) != nil) {
2499 packages_ = [[NSMutableArray arrayWithCapacity:16] retain];
2501 list_ = [[UITable alloc] initWithFrame:[transition_ bounds]];
2502 [self pushView:list_ withTitle:@"Install" backButtonTitle:@"Sections" rightButton:nil];
2504 UITableColumn *column = [[[UITableColumn alloc]
2505 initWithTitle:@"Name"
2507 width:frame.size.width
2510 [list_ setDataSource:self];
2511 [list_ setSeparatorStyle:1];
2512 [list_ addTableColumn:column];
2513 [list_ setDelegate:self];
2514 [list_ setReusesTableCells:YES];
2516 [transition_ transition:0 toView:list_];
2520 - (void) setPackages:(NSArray *)packages {
2521 [packages_ removeAllObjects];
2523 for (size_t i(0); i != [packages count]; ++i) {
2524 Package *package([packages objectAtIndex:i]);
2525 if ([package installed] == nil)
2526 [packages_ addObject:package];
2529 [packages_ sortUsingSelector:@selector(compareBySectionAndName:)];
2530 NSMutableArray *sections = [NSMutableArray arrayWithCapacity:16];
2532 Section *nsection = nil;
2533 Package *npackage = nil;
2535 Section *section = nil;
2536 for (size_t offset = 0, count = [packages_ count]; offset != count; ++offset) {
2537 Package *package = [packages_ objectAtIndex:offset];
2538 NSString *name = [package section];
2540 if (section == nil || ![[section name] isEqual:name]) {
2541 section = [[[Section alloc] initWithName:name row:offset] autorelease];
2543 if ([name isEqualToString:section_])
2545 [sections addObject:section];
2548 if ([[package name] isEqualToString:package_])
2550 [section addPackage:package];
2553 if (sections_ != nil)
2554 [sections_ release];
2555 sections_ = [sections retain];
2557 [packages_ sortUsingSelector:@selector(compareByName:)];
2563 if (npackage != nil)
2564 [view_ setPackage:npackage];
2565 else if (package_ != nil)
2568 if (table_ != nil && section_ == nil)
2569 [table_ setPackages:packages_];
2570 else if (nsection != nil)
2571 [table_ setPackages:[nsection packages]];
2572 else if (section_ != nil)
2576 [self popViews:views];
2580 - (void) setDelegate:(id)delegate {
2582 [view_ setDelegate:delegate];
2583 [super setDelegate:delegate];
2588 /* Changes View {{{ */
2589 @interface ChangesView : ResetView <
2590 PackageTableDelegate
2592 UISectionList *list_;
2593 NSMutableArray *packages_;
2594 NSMutableArray *sections_;
2602 - (void) navigationBar:(UINavigationBar *)navbar buttonClicked:(int)button;
2604 - (int) numberOfSectionsInSectionList:(UISectionList *)list;
2605 - (NSString *) sectionList:(UISectionList *)list titleForSection:(int)section;
2606 - (int) sectionList:(UISectionList *)list rowForSection:(int)section;
2608 - (int) numberOfRowsInTable:(UITable *)table;
2609 - (float) table:(UITable *)table heightForRow:(int)row;
2610 - (UITableCell *) table:(UITable *)table cellForRow:(int)row column:(UITableColumn *)col reusing:(UITableCell *)reusing;
2611 - (BOOL) table:(UITable *)table showDisclosureForRow:(int)row;
2612 - (void) tableRowSelected:(NSNotification *)notification;
2614 - (id) initWithFrame:(CGRect)frame;
2615 - (void) setPackages:(NSArray *)packages;
2616 - (void) _resetView;
2619 - (void) setDelegate:(id)delegate;
2622 @implementation ChangesView
2626 [packages_ release];
2627 [sections_ release];
2630 if (package_ != nil)
2635 - (int) numberOfSectionsInSectionList:(UISectionList *)list {
2636 return [sections_ count];
2639 - (NSString *) sectionList:(UISectionList *)list titleForSection:(int)section {
2640 return [[sections_ objectAtIndex:section] name];
2643 - (int) sectionList:(UISectionList *)list rowForSection:(int)section {
2644 return [[sections_ objectAtIndex:section] row];
2647 - (int) numberOfRowsInTable:(UITable *)table {
2648 return [packages_ count];
2651 - (float) table:(UITable *)table heightForRow:(int)row {
2655 - (UITableCell *) table:(UITable *)table cellForRow:(int)row column:(UITableColumn *)col reusing:(UITableCell *)reusing {
2657 reusing = [[[PackageCell alloc] initWithVersioner:NULL] autorelease];
2658 [(PackageCell *)reusing setPackage:[packages_ objectAtIndex:row]];
2662 - (BOOL) table:(UITable *)table showDisclosureForRow:(int)row {
2666 - (void) tableRowSelected:(NSNotification *)notification {
2667 int row = [[notification object] selectedRow];
2668 [self packageTable:self packageSelected:(row == INT_MAX ? nil : [packages_ objectAtIndex:row])];
2671 - (void) navigationBar:(UINavigationBar *)navbar buttonClicked:(int)button {
2674 [[view_ package] install];
2675 [delegate_ resolve];
2676 [delegate_ perform];
2680 [delegate_ upgrade];
2685 - (void) packageTable:(id)table packageSelected:(Package *)package {
2686 if (package == nil) {
2693 _assert(package_ == nil);
2694 _assert(view_ == nil);
2696 package_ = [[package name] retain];
2698 view_ = [[PackageView alloc] initWithFrame:[transition_ bounds]];
2699 [view_ setDelegate:delegate_];
2701 [view_ setPackage:package];
2703 [self pushView:view_ withTitle:[package name] backButtonTitle:nil rightButton:(
2704 [package upgradable] ? @"Upgrade" : @"Install"
2709 - (id) initWithFrame:(CGRect)frame {
2710 if ((self = [super initWithFrame:frame]) != nil) {
2711 packages_ = [[NSMutableArray arrayWithCapacity:16] retain];
2712 sections_ = [[NSMutableArray arrayWithCapacity:16] retain];
2714 list_ = [[UISectionList alloc] initWithFrame:[transition_ bounds] showSectionIndex:NO];
2715 [list_ setShouldHideHeaderInShortLists:NO];
2716 [list_ setDataSource:self];
2717 //[list_ setSectionListStyle:1];
2719 UITableColumn *column = [[[UITableColumn alloc]
2720 initWithTitle:@"Name"
2722 width:frame.size.width
2725 UITable *table = [list_ table];
2726 [table setSeparatorStyle:1];
2727 [table addTableColumn:column];
2728 [table setDelegate:self];
2729 [table setReusesTableCells:YES];
2731 [self pushView:list_ withTitle:@"Changes" backButtonTitle:nil rightButton:nil];
2735 - (void) setPackages:(NSArray *)packages {
2736 [packages_ removeAllObjects];
2737 for (size_t i(0); i != [packages count]; ++i) {
2738 Package *package([packages objectAtIndex:i]);
2739 if ([package installed] == nil || [package upgradable])
2740 [packages_ addObject:package];
2743 [packages_ sortUsingSelector:@selector(compareForChanges:)];
2745 [sections_ removeAllObjects];
2747 Section *upgradable = [[[Section alloc] initWithName:@"Available Upgrades" row:0] autorelease];
2748 Section *section = nil;
2751 Package *npackage = nil;
2752 for (size_t offset = 0, count = [packages_ count]; offset != count; ++offset) {
2753 Package *package = [packages_ objectAtIndex:offset];
2754 if ([[package name] isEqualToString:package_])
2757 if ([package upgradable])
2758 [upgradable addPackage:package];
2760 NSDate *seen = [package seen];
2762 CFLocaleRef locale = CFLocaleCopyCurrent();
2763 CFDateFormatterRef formatter = CFDateFormatterCreate(NULL, locale, kCFDateFormatterMediumStyle, kCFDateFormatterMediumStyle);
2764 CFStringRef formatted = CFDateFormatterCreateStringWithDate(NULL, formatter, (CFDateRef) seen);
2766 NSString *name = (NSString *) formatted;
2768 if (section == nil || ![[section name] isEqual:name]) {
2769 section = [[[Section alloc] initWithName:name row:offset] autorelease];
2770 [sections_ addObject:section];
2773 [section addPackage:package];
2775 CFRelease(formatter);
2776 CFRelease(formatted);
2781 count_ = [[upgradable packages] count];
2783 [sections_ insertObject:upgradable atIndex:0];
2787 if (npackage != nil)
2788 [view_ setPackage:npackage];
2789 else if (package_ != nil)
2796 - (void) _resetView {
2797 if ([views_ count] == 1)
2798 [navbar_ showButtonsWithLeftTitle:(count_ == 0 ? nil : @"Upgrade All") rightTitle:nil];
2805 - (void) setDelegate:(id)delegate {
2807 [view_ setDelegate:delegate];
2808 [super setDelegate:delegate];
2813 /* Manage View {{{ */
2814 @interface ManageView : ResetView <
2815 PackageTableDelegate
2817 PackageTable *table_;
2824 - (void) navigationBar:(UINavigationBar *)navbar buttonClicked:(int)button;
2826 - (void) packageTable:(id)table packageSelected:(Package *)package;
2828 - (id) initWithFrame:(CGRect)frame;
2829 - (void) setPackages:(NSArray *)packages;
2831 - (void) setDelegate:(id)delegate;
2834 @implementation ManageView
2840 if (package_ != nil)
2845 - (void) navigationBar:(UINavigationBar *)navbar buttonClicked:(int)button {
2847 [[view_ package] remove];
2848 [delegate_ resolve];
2849 [delegate_ perform];
2853 - (void) packageTable:(id)table packageSelected:(Package *)package {
2854 if (package == nil) {
2861 _assert(package_ == nil);
2862 _assert(view_ == nil);
2864 package_ = [[package name] retain];
2866 view_ = [[PackageView alloc] initWithFrame:[transition_ bounds]];
2867 [view_ setDelegate:delegate_];
2869 [view_ setPackage:package];
2871 [self pushView:view_ withTitle:[package name] backButtonTitle:nil rightButton:@"Uninstall"];
2875 - (id) initWithFrame:(CGRect)frame {
2876 if ((self = [super initWithFrame:frame]) != nil) {
2877 table_ = [[PackageTable alloc] initWithFrame:[transition_ bounds] versioner:@selector(latest)];
2878 [table_ setDelegate:self];
2880 [self pushView:table_ withTitle:@"Uninstall" backButtonTitle:@"Packages" rightButton:nil];
2884 - (void) setPackages:(NSArray *)packages {
2885 NSMutableArray *local = [NSMutableArray arrayWithCapacity:16];
2886 for (size_t i(0); i != [packages count]; ++i) {
2887 Package *package([packages objectAtIndex:i]);
2888 if ([package installed] != nil)
2889 [local addObject:package];
2892 [local sortUsingSelector:@selector(compareByName:)];
2894 Package *npackage = nil;
2895 for (size_t offset = 0, count = [local count]; offset != count; ++offset) {
2896 Package *package = [local objectAtIndex:offset];
2897 if ([[package name] isEqualToString:package_])
2901 [table_ setPackages:local];
2903 if (npackage != nil)
2904 [view_ setPackage:npackage];
2905 else if (package_ != nil)
2911 - (void) setDelegate:(id)delegate {
2913 [view_ setDelegate:delegate];
2914 [super setDelegate:delegate];
2919 /* Search View {{{ */
2920 @protocol SearchViewDelegate
2921 - (void) showKeyboard:(BOOL)show;
2924 @interface SearchView : ResetView <
2925 PackageTableDelegate
2927 NSMutableArray *packages_;
2929 UISearchField *field_;
2930 PackageTable *table_;
2937 - (void) navigationBar:(UINavigationBar *)navbar buttonClicked:(int)button;
2938 - (void) packageTable:(id)table packageSelected:(Package *)package;
2940 - (void) textFieldDidBecomeFirstResponder:(UITextField *)field;
2941 - (void) textFieldDidResignFirstResponder:(UITextField *)field;
2943 - (void) keyboardInputChanged:(UIFieldEditor *)editor;
2944 - (BOOL) keyboardInput:(id)input shouldInsertText:(NSString *)text isMarkedText:(int)marked;
2946 - (id) initWithFrame:(CGRect)frame;
2947 - (void) setPackages:(NSArray *)packages;
2949 - (void) setDelegate:(id)delegate;
2950 - (void) resetPackage:(Package *)package;
2951 - (void) searchPackages;
2955 @implementation SearchView
2958 [packages_ release];
2959 [accessory_ release];
2964 if (package_ != nil)
2969 - (void) navigationBar:(UINavigationBar *)navbar buttonClicked:(int)button {
2971 Package *package = [view_ package];
2972 if ([package installed] == nil)
2976 [delegate_ resolve];
2977 [delegate_ perform];
2981 - (void) packageTable:(id)table packageSelected:(Package *)package {
2982 if (package == nil) {
2983 [navbar_ setAccessoryView:accessory_ animate:(resetting_ ? NO : YES) goingBack:YES];
2991 [navbar_ setAccessoryView:nil animate:YES goingBack:NO];
2993 _assert(package_ == nil);
2994 _assert(view_ == nil);
2996 package_ = [[package name] retain];
2998 view_ = [[PackageView alloc] initWithFrame:[transition_ bounds]];
2999 [view_ setDelegate:delegate_];
3001 [self pushView:view_ withTitle:[package name] backButtonTitle:nil rightButton:nil];
3002 [self resetPackage:package];
3006 - (void) textFieldDidBecomeFirstResponder:(UITextField *)field {
3007 [delegate_ showKeyboard:YES];
3008 [table_ setEnabled:NO];
3010 /*CGColorSpaceRef space = CGColorSpaceCreateDeviceRGB();
3011 CGColor dimmed(alpha, 0, 0, 0, 0.5);
3012 [editor_ setBackgroundColor:dimmed];
3013 CGColorSpaceRelease(space);*/
3016 - (void) textFieldDidResignFirstResponder:(UITextField *)field {
3017 [table_ setEnabled:YES];
3018 [delegate_ showKeyboard:NO];
3021 - (void) keyboardInputChanged:(UIFieldEditor *)editor {
3022 NSString *text([field_ text]);
3023 [field_ setClearButtonStyle:(text == nil || [text length] == 0 ? 0 : 2)];
3026 - (BOOL) keyboardInput:(id)input shouldInsertText:(NSString *)text isMarkedText:(int)marked {
3027 if ([text length] != 1 || [text characterAtIndex:0] != '\n')
3030 [self searchPackages];
3031 [field_ resignFirstResponder];
3035 - (id) initWithFrame:(CGRect)frame {
3036 if ((self = [super initWithFrame:frame]) != nil) {
3037 packages_ = [[NSMutableArray arrayWithCapacity:16] retain];
3039 table_ = [[PackageTable alloc] initWithFrame:[transition_ bounds] versioner:@selector(latest)];
3040 [table_ setDelegate:self];
3042 CGRect area = [self bounds];
3045 area.size.width -= 12;
3046 area.size.height = [UISearchField defaultHeight];
3048 field_ = [[UISearchField alloc] initWithFrame:area];
3050 GSFontRef font = GSFontCreateWithName("Helvetica", kGSFontTraitNone, 16);
3051 [field_ setFont:font];
3054 [field_ setPlaceholder:@"Package Names & Descriptions"];
3055 [field_ setPaddingTop:5];
3056 [field_ setDelegate:self];
3058 UITextTraits *traits = [field_ textTraits];
3059 [traits setEditingDelegate:self];
3060 [traits setReturnKeyType:6];
3062 accessory_ = [[UIView alloc] initWithFrame:CGRectMake(6, 6, area.size.width, area.size.height + 30)];
3063 [accessory_ addSubview:field_];
3065 [navbar_ setAccessoryView:accessory_];
3066 [self pushView:table_ withTitle:nil backButtonTitle:@"Search" rightButton:nil];
3068 /* XXX: for the love of god just fix this */
3069 [navbar_ removeFromSuperview];
3070 [reload_ removeFromSuperview];
3071 [configure_ removeFromSuperview];
3072 [self addSubview:navbar_];
3073 [self addSubview:reload_];
3074 [self addSubview:configure_];
3078 - (void) setPackages:(NSArray *)packages {
3079 [packages_ removeAllObjects];
3080 [packages_ addObjectsFromArray:packages];
3081 [packages_ sortUsingSelector:@selector(compareByName:)];
3083 Package *npackage = nil;
3084 for (size_t offset = 0, count = [packages_ count]; offset != count; ++offset) {
3085 Package *package = [packages_ objectAtIndex:offset];
3086 if ([[package name] isEqualToString:package_])
3090 [self searchPackages];
3092 if (npackage != nil)
3093 [self resetPackage:npackage];
3094 else if (package_ != nil)
3100 - (void) setDelegate:(id)delegate {
3102 [view_ setDelegate:delegate];
3103 [super setDelegate:delegate];
3106 - (void) resetPackage:(Package *)package {
3107 [view_ setPackage:package];
3108 NSString *right = [package installed] == nil ? @"Install" : @"Uninstall";
3109 [navbar_ showButtonsWithLeftTitle:nil rightTitle:right];
3112 - (void) searchPackages {
3113 NSString *text([field_ text]);
3115 NSMutableArray *packages([NSMutableArray arrayWithCapacity:16]);
3117 for (size_t offset(0), count([packages_ count]); offset != count; ++offset) {
3118 Package *package = [packages_ objectAtIndex:offset];
3119 if ([package matches:text])
3120 [packages addObject:package];
3123 [table_ setPackages:packages];
3124 [[table_ table] scrollPointVisibleAtTopLeft:CGPointMake(0, 0) animated:NO];
3130 @interface Cydia : UIApplication <
3131 ConfirmationViewDelegate,
3132 ProgressViewDelegate,
3138 UITransitionView *transition_;
3139 UIButtonBar *buttonbar_;
3141 ConfirmationView *confirm_;
3143 Database *database_;
3144 ProgressView *progress_;
3147 UINavigationBar *navbar_;
3148 UIScroller *scroller_;
3149 UIWebView *webview_;
3151 UIProgressIndicator *indicator_;
3153 InstallView *install_;
3154 ChangesView *changes_;
3155 ManageView *manage_;
3156 SearchView *search_;
3161 UIKeyboard *keyboard_;
3165 - (void) reloadData:(BOOL)reset;
3176 - (void) progressViewIsComplete:(ProgressView *)progress;
3178 - (void) navigationBar:(UINavigationBar *)navbar buttonClicked:(int)button;
3179 - (void) alertSheet:(UIAlertSheet *)sheet buttonClicked:(int)button;
3180 - (void) buttonBarItemTapped:(id)sender;
3182 - (void) view:(UIView *)sender didSetFrame:(CGRect)frame oldFrame:(CGRect)old;
3184 - (void) webView:(WebView *)sender didReceiveTitle:(NSString *)title forFrame:(WebFrame *)frame;
3186 - (void) applicationWillSuspend;
3187 - (void) applicationDidFinishLaunching:(id)unused;
3190 @implementation Cydia
3193 NSMutableURLRequest *request = [NSMutableURLRequest
3195 cachePolicy:NSURLRequestReloadIgnoringCacheData
3196 timeoutInterval:30.0
3199 [request addValue:[NSString stringWithCString:Firmware_] forHTTPHeaderField:@"X-Firmware"];
3200 [request addValue:[NSString stringWithCString:Machine_] forHTTPHeaderField:@"X-Machine"];
3201 [request addValue:[NSString stringWithCString:SerialNumber_] forHTTPHeaderField:@"X-Serial-Number"];
3203 [webview_ loadRequest:request];
3206 - (void) reloadData:(BOOL)reset {
3207 [database_ reloadData];
3211 if (Packages_ == nil) {
3212 Packages_ = [[NSMutableDictionary alloc] initWithCapacity:count];
3213 [Metadata_ setObject:Packages_ forKey:@"Packages"];
3216 now_ = [NSDate date];
3218 NSMutableArray *packages = [NSMutableArray arrayWithCapacity:count];
3219 for (pkgCache::PkgIterator iterator = [database_ cache]->PkgBegin(); !iterator.end(); ++iterator)
3220 if (Package *package = [Package packageWithIterator:iterator database:database_])
3221 [packages addObject:package];
3223 [install_ setPackages:packages];
3224 [changes_ setPackages:packages];
3225 [manage_ setPackages:packages];
3226 [search_ setPackages:packages];
3228 if (size_t count = [changes_ count]) {
3229 NSString *badge([[NSNumber numberWithInt:count] stringValue]);
3230 [buttonbar_ setBadgeValue:badge forButton:3];
3231 if ([buttonbar_ respondsToSelector:@selector(setBadgeAnimated:forButton:)])
3232 [buttonbar_ setBadgeAnimated:YES forButton:3];
3233 [self setApplicationBadge:badge];
3235 [buttonbar_ setBadgeValue:nil forButton:3];
3236 if ([buttonbar_ respondsToSelector:@selector(setBadgeAnimated:forButton:)])
3237 [buttonbar_ setBadgeAnimated:NO forButton:3];
3238 [self removeApplicationBadge];
3241 _assert([Metadata_ writeToFile:@"/var/lib/cydia/metadata.plist" atomically:YES] == YES);
3244 - (void) setPrompt {
3245 [navbar_ setPrompt:[NSString stringWithFormat:@"Last Updated: %@", GetLastUpdate()]];
3249 pkgProblemResolver *resolver = [database_ resolver];
3251 resolver->InstallProtect();
3252 if (!resolver->Resolve(true))
3257 [database_ prepare];
3258 confirm_ = [[ConfirmationView alloc] initWithView:underlay_ database:database_ delegate:self];
3262 [database_ upgrade];
3267 [self reloadData:NO];
3273 [overlay_ removeFromSuperview];
3277 detachNewThreadSelector:@selector(perform)
3284 - (void) bootstrap_ {
3286 [database_ upgrade];
3287 [database_ prepare];
3288 [database_ perform];
3291 - (void) bootstrap {
3293 detachNewThreadSelector:@selector(bootstrap_)
3296 title:@"Bootstrap Install..."
3302 detachNewThreadSelector:@selector(update)
3305 title:@"Refreshing Sources..."
3309 - (void) progressViewIsComplete:(ProgressView *)progress {
3310 [self reloadData:YES];
3312 if (confirm_ != nil) {
3313 [underlay_ addSubview:overlay_];
3314 [confirm_ removeFromSuperview];
3320 - (void) navigationBar:(UINavigationBar *)navbar buttonClicked:(int)button {
3327 UIAlertSheet *sheet = [[[UIAlertSheet alloc]
3328 initWithTitle:@"About Cydia Packager"
3329 buttons:[NSArray arrayWithObjects:@"Close", nil]
3330 defaultButtonIndex:0
3336 @"Copyright (C) 2008\n"
3337 "Jay Freeman (saurik)\n"
3338 "saurik@saurik.com\n"
3339 "http://www.saurik.com/\n"
3342 "http://www.theokorigroup.com/\n"
3344 "College of Creative Studies,\n"
3345 "University of California,\n"
3347 "http://www.ccs.ucsb.edu/\n"
3350 "bad_, BHSPitMonkey, cash, Cobra,\n"
3351 "core, Corona, crashx, cromas,\n"
3352 "Darken, dtzWill, Erica, francis,\n"
3353 "Godores, jerry, Kingstone, lounger,\n"
3354 "mbranes, rockabilly, tman, Wbiggs"
3357 [sheet presentSheetFromButtonBar:buttonbar_];
3362 - (void) alertSheet:(UIAlertSheet *)sheet buttonClicked:(int)button {
3366 - (void) buttonBarItemTapped:(id)sender {
3368 unsigned tag = [sender tag];
3371 case 1: view = featured_; break;
3372 case 2: view = install_; break;
3373 case 3: view = changes_; break;
3374 case 4: view = manage_; break;
3375 case 5: view = search_; break;
3381 if ([view respondsToSelector:@selector(resetView:)])
3382 [(id) view resetView:(tag == tag_ ? NO : YES)];
3384 [transition_ transition:0 toView:view];
3387 - (void) view:(UIView *)sender didSetFrame:(CGRect)frame oldFrame:(CGRect)old {
3388 [scroller_ setContentSize:frame.size];
3389 [indicator_ stopAnimation];
3392 - (void) webView:(WebView *)sender didReceiveTitle:(NSString *)title forFrame:(WebFrame *)frame {
3393 [navbar_ setPrompt:title];
3396 - (void) webView:(WebView *)sender didStartProvisionalLoadForFrame:(WebFrame *)frame {
3397 [navbar_ setPrompt:@"Loading..."];
3398 [indicator_ startAnimation];
3401 - (void) applicationWillSuspend {
3403 system("launchctl stop com.apple.SpringBoard");
3405 [super applicationWillSuspend];
3408 - (void) applicationDidFinishLaunching:(id)unused {
3409 _assert(pkgInitConfig(*_config));
3410 _assert(pkgInitSystem(*_config, _system));
3416 CGRect screenrect = [UIHardware fullScreenApplicationContentRect];
3417 window_ = [[UIWindow alloc] initWithContentRect:screenrect];
3419 [window_ orderFront: self];
3420 [window_ makeKey: self];
3421 [window_ _setHidden: NO];
3423 progress_ = [[ProgressView alloc] initWithFrame:[window_ bounds] delegate:self];
3424 [window_ setContentView:progress_];
3426 underlay_ = [[UIView alloc] initWithFrame:[progress_ bounds]];
3427 [progress_ setContentView:underlay_];
3429 overlay_ = [[UIView alloc] initWithFrame:[underlay_ bounds]];
3432 [underlay_ addSubview:overlay_];
3434 transition_ = [[UITransitionView alloc] initWithFrame:CGRectMake(
3435 0, 0, screenrect.size.width, screenrect.size.height - 48
3438 [overlay_ addSubview:transition_];
3440 featured_ = [[UIView alloc] initWithFrame:[transition_ bounds]];
3442 CGSize navsize = [UINavigationBar defaultSizeWithPrompt];
3443 CGRect navrect = {{0, 0}, navsize};
3445 navbar_ = [[UINavigationBar alloc] initWithFrame:navrect];
3446 [featured_ addSubview:navbar_];
3448 [navbar_ setBarStyle:1];
3449 [navbar_ setDelegate:self];
3451 [navbar_ showButtonsWithLeftTitle:@"About" rightTitle:@"Reload"];
3453 UINavigationItem *navitem = [[[UINavigationItem alloc] initWithTitle:@"Featured"] autorelease];
3454 [navbar_ pushNavigationItem:navitem];
3456 struct CGRect subbounds = [featured_ bounds];
3457 subbounds.origin.y += navsize.height;
3458 subbounds.size.height -= navsize.height;
3460 UIImageView *pinstripe = [[[UIImageView alloc] initWithFrame:subbounds] autorelease];
3461 [pinstripe setImage:[UIImage applicationImageNamed:@"pinstripe.png"]];
3462 [featured_ addSubview:pinstripe];
3464 scroller_ = [[UIScroller alloc] initWithFrame:subbounds];
3465 [featured_ addSubview:scroller_];
3467 [scroller_ setScrollingEnabled:YES];
3468 [scroller_ setAdjustForContentSizeChange:YES];
3469 [scroller_ setClipsSubviews:YES];
3470 [scroller_ setAllowsRubberBanding:YES];
3471 [scroller_ setScrollDecelerationFactor:0.99];
3472 [scroller_ setDelegate:self];
3474 CGRect webrect = [scroller_ bounds];
3475 webrect.size.height = 0;
3477 webview_ = [[UIWebView alloc] initWithFrame:webrect];
3478 [scroller_ addSubview:webview_];
3480 [webview_ setTilingEnabled:YES];
3481 [webview_ setTileSize:CGSizeMake(screenrect.size.width, 500)];
3482 [webview_ setAutoresizes:YES];
3483 [webview_ setDelegate:self];
3485 CGSize indsize = [UIProgressIndicator defaultSizeForStyle:2];
3486 indicator_ = [[UIProgressIndicator alloc] initWithFrame:CGRectMake(87, 45, indsize.width, indsize.height)];
3487 [indicator_ setStyle:2];
3488 [featured_ addSubview:indicator_];
3490 NSArray *buttonitems = [NSArray arrayWithObjects:
3491 [NSDictionary dictionaryWithObjectsAndKeys:
3492 @"buttonBarItemTapped:", kUIButtonBarButtonAction,
3493 @"featured-up.png", kUIButtonBarButtonInfo,
3494 @"featured-dn.png", kUIButtonBarButtonSelectedInfo,
3495 [NSNumber numberWithInt:1], kUIButtonBarButtonTag,
3496 self, kUIButtonBarButtonTarget,
3497 @"Featured", kUIButtonBarButtonTitle,
3498 @"0", kUIButtonBarButtonType,
3501 [NSDictionary dictionaryWithObjectsAndKeys:
3502 @"buttonBarItemTapped:", kUIButtonBarButtonAction,
3503 @"install-up.png", kUIButtonBarButtonInfo,
3504 @"install-dn.png", kUIButtonBarButtonSelectedInfo,
3505 [NSNumber numberWithInt:2], kUIButtonBarButtonTag,
3506 self, kUIButtonBarButtonTarget,
3507 @"Install", kUIButtonBarButtonTitle,
3508 @"0", kUIButtonBarButtonType,
3511 [NSDictionary dictionaryWithObjectsAndKeys:
3512 @"buttonBarItemTapped:", kUIButtonBarButtonAction,
3513 @"changes-up.png", kUIButtonBarButtonInfo,
3514 @"changes-dn.png", kUIButtonBarButtonSelectedInfo,
3515 [NSNumber numberWithInt:3], kUIButtonBarButtonTag,
3516 self, kUIButtonBarButtonTarget,
3517 @"Changes", kUIButtonBarButtonTitle,
3518 @"0", kUIButtonBarButtonType,
3521 [NSDictionary dictionaryWithObjectsAndKeys:
3522 @"buttonBarItemTapped:", kUIButtonBarButtonAction,
3523 @"manage-up.png", kUIButtonBarButtonInfo,
3524 @"manage-dn.png", kUIButtonBarButtonSelectedInfo,
3525 [NSNumber numberWithInt:4], kUIButtonBarButtonTag,
3526 self, kUIButtonBarButtonTarget,
3527 @"Uninstall", kUIButtonBarButtonTitle,
3528 @"0", kUIButtonBarButtonType,
3531 [NSDictionary dictionaryWithObjectsAndKeys:
3532 @"buttonBarItemTapped:", kUIButtonBarButtonAction,
3533 @"search-up.png", kUIButtonBarButtonInfo,
3534 @"search-dn.png", kUIButtonBarButtonSelectedInfo,
3535 [NSNumber numberWithInt:5], kUIButtonBarButtonTag,
3536 self, kUIButtonBarButtonTarget,
3537 @"Search", kUIButtonBarButtonTitle,
3538 @"0", kUIButtonBarButtonType,
3542 buttonbar_ = [[UIButtonBar alloc]
3544 withFrame:CGRectMake(
3545 0, screenrect.size.height - 48,
3546 screenrect.size.width, 48
3548 withItemList:buttonitems
3551 [buttonbar_ setDelegate:self];
3552 [buttonbar_ setBarStyle:1];
3553 [buttonbar_ setButtonBarTrackingMode:2];
3555 int buttons[5] = {1, 2, 3, 4, 5};
3556 [buttonbar_ registerButtonGroup:0 withButtons:buttons withCount:5];
3557 [buttonbar_ showButtonGroup:0 withDuration:0];
3559 for (int i = 0; i != 5; ++i)
3560 [[buttonbar_ viewWithTag:(i + 1)] setFrame:CGRectMake(
3561 i * 64 + 2, 1, 60, 48
3564 [buttonbar_ showSelectionForButton:1];
3565 [transition_ transition:0 toView:featured_];
3567 [overlay_ addSubview:buttonbar_];
3569 [UIKeyboard initImplementationNow];
3571 CGRect edtrect = [overlay_ bounds];
3572 edtrect.origin.y += navsize.height;
3573 edtrect.size.height -= navsize.height;
3575 CGSize keysize = [UIKeyboard defaultSize];
3576 CGRect keyrect = {{0, [overlay_ bounds].size.height - keysize.height}, keysize};
3577 keyboard_ = [[UIKeyboard alloc] initWithFrame:keyrect];
3579 database_ = [[Database alloc] init];
3580 [database_ setDelegate:progress_];
3582 install_ = [[InstallView alloc] initWithFrame:[transition_ bounds]];
3583 [install_ setDelegate:self];
3585 changes_ = [[ChangesView alloc] initWithFrame:[transition_ bounds]];
3586 [changes_ setDelegate:self];
3588 manage_ = [[ManageView alloc] initWithFrame:[transition_ bounds]];
3589 [manage_ setDelegate:self];
3591 search_ = [[SearchView alloc] initWithFrame:[transition_ bounds]];
3592 [search_ setDelegate:self];
3594 [self reloadData:NO];
3596 Package *package([database_ packageWithName:@"cydia"]);
3597 NSString *application = package == nil ? @"Cydia" : [NSString
3598 stringWithFormat:@"Cydia/%@",
3602 WebView *webview = [webview_ webView];
3603 [webview setApplicationNameForUserAgent:application];
3604 [webview setFrameLoadDelegate:self];
3606 url_ = [NSURL URLWithString:@"http://cydia.saurik.com/"];
3609 [progress_ resetView];
3615 - (void) showKeyboard:(BOOL)show {
3617 [overlay_ addSubview:keyboard_];
3619 [keyboard_ removeFromSuperview];
3624 void AddPreferences(NSString *plist) {
3625 NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init];
3627 NSMutableDictionary *settings = [[[NSMutableDictionary alloc] initWithContentsOfFile:plist] autorelease];
3628 _assert(settings != NULL);
3629 NSMutableArray *items = [settings objectForKey:@"items"];
3633 for (size_t i(0); i != [items count]; ++i) {
3634 NSMutableDictionary *item([items objectAtIndex:i]);
3635 NSString *label = [item objectForKey:@"label"];
3636 if (label != nil && [label isEqualToString:@"Cydia"]) {
3643 for (size_t i(0); i != [items count]; ++i) {
3644 NSDictionary *item([items objectAtIndex:i]);
3645 NSString *label = [item objectForKey:@"label"];
3646 if (label != nil && [label isEqualToString:@"General"]) {
3647 [items insertObject:[NSDictionary dictionaryWithObjectsAndKeys:
3648 @"CydiaSettings", @"bundle",
3649 @"PSLinkCell", @"cell",
3650 [NSNumber numberWithBool:YES], @"hasIcon",
3651 [NSNumber numberWithBool:YES], @"isController",
3653 nil] atIndex:(i + 1)];
3659 _assert([settings writeToFile:plist atomically:YES] == YES);
3666 id Alloc_(id self, SEL selector) {
3667 id object = alloc_(self, selector);
3668 fprintf(stderr, "[%s]A-%p\n", self->isa->name, object);
3672 int main(int argc, char *argv[]) {
3674 memset(nl, 0, sizeof(nl));
3675 nl[0].n_un.n_name = "_useMDNSResponder";
3676 nlist("/usr/lib/libc.dylib", nl);
3677 if (nl[0].n_type != N_UNDF)
3678 *(int *) nl[0].n_value = 0;
3680 bootstrap_ = argc > 1 && strcmp(argv[1], "--bootstrap") == 0;
3685 /*Method alloc = class_getClassMethod([NSObject class], @selector(alloc));
3686 alloc_ = alloc->method_imp;
3687 alloc->method_imp = (IMP) &Alloc_;*/
3689 NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init];
3691 if (NSDictionary *sysver = [NSDictionary dictionaryWithContentsOfFile:@"/System/Library/CoreServices/SystemVersion.plist"]) {
3692 if (NSString *prover = [sysver valueForKey:@"ProductVersion"]) {
3693 Firmware_ = strdup([prover cString]);
3694 NSArray *versions = [prover componentsSeparatedByString:@"."];
3695 int count = [versions count];
3696 Major_ = count > 0 ? [[versions objectAtIndex:0] intValue] : 0;
3697 Minor_ = count > 1 ? [[versions objectAtIndex:0] intValue] : 0;
3698 BugFix_ = count > 2 ? [[versions objectAtIndex:0] intValue] : 0;
3703 sysctlbyname("hw.machine", NULL, &size, NULL, 0);
3704 char *machine = new char[size];
3705 sysctlbyname("hw.machine", machine, &size, NULL, 0);
3708 if (CFMutableDictionaryRef dict = IOServiceMatching("IOPlatformExpertDevice"))
3709 if (io_service_t service = IOServiceGetMatchingService(kIOMasterPortDefault, dict)) {
3710 if (CFTypeRef serial = IORegistryEntryCreateCFProperty(service, CFSTR(kIOPlatformSerialNumberKey), kCFAllocatorDefault, 0)) {
3711 SerialNumber_ = strdup(CFStringGetCStringPtr((CFStringRef) serial, CFStringGetSystemEncoding()));
3715 IOObjectRelease(service);
3718 /*AddPreferences(@"/Applications/Preferences.app/Settings-iPhone.plist");
3719 AddPreferences(@"/Applications/Preferences.app/Settings-iPod.plist");*/
3721 if ((Metadata_ = [[NSMutableDictionary alloc] initWithContentsOfFile:@"/var/lib/cydia/metadata.plist"]) == NULL)
3722 Metadata_ = [[NSMutableDictionary alloc] initWithCapacity:2];
3724 Packages_ = [Metadata_ objectForKey:@"Packages"];
3726 setenv("CYDIA", "", _not(int));
3727 if (access("/User", F_OK) != 0)
3728 system("/usr/libexec/cydia/firmware.sh");
3729 system("dpkg --configure -a");
3731 UIApplicationMain(argc, argv, [Cydia class]);