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 const char *section = iterator_.Section();
1071 return section == NULL ? nil : [[NSString stringWithCString:section] stringByReplacingCharacter:'_' withCharacter:' '];
1074 - (Address *) maintainer {
1075 pkgRecords::Parser *parser = &[database_ records]->Lookup(file_);
1076 return [Address addressWithString:[NSString stringWithCString:parser->Maintainer().c_str()]];
1080 return version_->InstalledSize;
1083 - (NSString *) description {
1084 pkgRecords::Parser *parser = &[database_ records]->Lookup(file_);
1085 NSString *description([NSString stringWithCString:parser->LongDesc().c_str()]);
1087 NSArray *lines = [description componentsSeparatedByString:@"\n"];
1088 NSMutableArray *trimmed = [NSMutableArray arrayWithCapacity:([lines count] - 1)];
1089 if ([lines count] < 2)
1092 NSCharacterSet *whitespace = [NSCharacterSet whitespaceCharacterSet];
1093 for (size_t i(1); i != [lines count]; ++i) {
1094 NSString *trim = [[lines objectAtIndex:i] stringByTrimmingCharactersInSet:whitespace];
1095 [trimmed addObject:trim];
1098 return [trimmed componentsJoinedByString:@"\n"];
1101 - (NSString *) index {
1102 NSString *index = [[[self name] substringToIndex:1] uppercaseString];
1103 return [index length] != 0 && isalpha([index characterAtIndex:0]) ? index : @"123";
1107 return [[Packages_ objectForKey:id_] objectForKey:@"FirstSeen"];
1110 - (NSString *) latest {
1114 - (NSString *) installed {
1118 - (BOOL) upgradable {
1119 NSString *installed = [self installed];
1120 return installed != nil && [[self latest] compare:installed] != NSOrderedSame ? YES : NO;
1127 - (NSString *) name {
1128 return name_ == nil ? id_ : name_;
1131 - (NSString *) tagline {
1135 - (NSString *) icon {
1139 - (NSString *) website {
1143 - (BOOL) matches:(NSString *)text {
1149 range = [[self id] rangeOfString:text options:NSCaseInsensitiveSearch];
1150 if (range.location != NSNotFound)
1153 range = [[self name] rangeOfString:text options:NSCaseInsensitiveSearch];
1154 if (range.location != NSNotFound)
1157 range = [[self tagline] rangeOfString:text options:NSCaseInsensitiveSearch];
1158 if (range.location != NSNotFound)
1164 - (NSComparisonResult) compareByName:(Package *)package {
1165 NSString *lhs = [self name];
1166 NSString *rhs = [package name];
1168 if ([lhs length] != 0 && [rhs length] != 0) {
1169 unichar lhc = [lhs characterAtIndex:0];
1170 unichar rhc = [rhs characterAtIndex:0];
1172 if (isalpha(lhc) && !isalpha(rhc))
1173 return NSOrderedAscending;
1174 else if (!isalpha(lhc) && isalpha(rhc))
1175 return NSOrderedDescending;
1178 return [lhs caseInsensitiveCompare:rhs];
1181 - (NSComparisonResult) compareBySectionAndName:(Package *)package {
1182 NSString *lhs = [self section];
1183 NSString *rhs = [package section];
1185 if (lhs == NULL && rhs != NULL)
1186 return NSOrderedAscending;
1187 else if (lhs != NULL && rhs == NULL)
1188 return NSOrderedDescending;
1189 else if (lhs != NULL && rhs != NULL) {
1190 NSComparisonResult result = [lhs compare:rhs];
1191 if (result != NSOrderedSame)
1195 return [self compareByName:package];
1198 - (NSComparisonResult) compareForChanges:(Package *)package {
1199 BOOL lhs = [self upgradable];
1200 BOOL rhs = [package upgradable];
1203 return lhs ? NSOrderedAscending : NSOrderedDescending;
1205 switch ([[self seen] compare:[package seen]]) {
1206 case NSOrderedAscending:
1207 return NSOrderedDescending;
1210 case NSOrderedDescending:
1211 return NSOrderedAscending;
1217 return [self compareByName:package];
1221 pkgProblemResolver *resolver = [database_ resolver];
1222 resolver->Clear(iterator_);
1223 resolver->Protect(iterator_);
1224 [database_ cache]->MarkInstall(iterator_, false);
1228 pkgProblemResolver *resolver = [database_ resolver];
1229 resolver->Clear(iterator_);
1230 resolver->Protect(iterator_);
1231 resolver->Remove(iterator_);
1232 [database_ cache]->MarkDelete(iterator_, true);
1237 /* Section Class {{{ */
1238 @interface Section : NSObject {
1241 NSMutableArray *packages_;
1246 - (Section *) initWithName:(NSString *)name row:(size_t)row;
1247 - (NSString *) name;
1249 - (NSArray *) packages;
1251 - (void) addPackage:(Package *)package;
1254 @implementation Section
1258 [packages_ release];
1262 - (Section *) initWithName:(NSString *)name row:(size_t)row {
1263 if ((self = [super init]) != nil) {
1264 name_ = [name retain];
1266 packages_ = [[NSMutableArray arrayWithCapacity:16] retain];
1270 - (NSString *) name {
1278 - (NSArray *) packages {
1283 return [packages_ count];
1286 - (void) addPackage:(Package *)package {
1287 [packages_ addObject:package];
1293 /* Package View {{{ */
1294 @protocol PackageViewDelegate
1295 - (void) performPackage:(Package *)package;
1298 @interface PackageView : UIView {
1299 UIPreferencesTable *table_;
1301 UITextView *description_;
1307 - (int) numberOfGroupsInPreferencesTable:(UIPreferencesTable *)table;
1308 - (NSString *) preferencesTable:(UIPreferencesTable *)table titleForGroup:(int)group;
1309 - (float) preferencesTable:(UIPreferencesTable *)table heightForRow:(int)row inGroup:(int)group withProposedHeight:(float)proposed;
1310 - (int) preferencesTable:(UIPreferencesTable *)table numberOfRowsInGroup:(int)group;
1311 - (UIPreferencesTableCell *) preferencesTable:(UIPreferencesTable *)table cellForRow:(int)row inGroup:(int)group;
1313 - (BOOL) canSelectRow:(int)row;
1314 - (void) tableRowSelected:(NSNotification *)notification;
1316 - (Package *) package;
1318 - (id) initWithFrame:(struct CGRect)frame;
1319 - (void) setPackage:(Package *)package;
1320 - (void) setDelegate:(id)delegate;
1323 @implementation PackageView
1326 if (package_ != nil)
1328 if (description_ != nil)
1329 [description_ release];
1334 - (int) numberOfGroupsInPreferencesTable:(UIPreferencesTable *)table {
1338 - (NSString *) preferencesTable:(UIPreferencesTable *)table titleForGroup:(int)group {
1341 case 1: return @"Details";
1342 case 2: return @"Source";
1344 default: _assert(false);
1348 - (float) preferencesTable:(UIPreferencesTable *)table heightForRow:(int)row inGroup:(int)group withProposedHeight:(float)proposed {
1349 if (group != 0 || row != 1)
1352 return [description_ visibleTextRect].size.height + TextViewOffset_;
1355 - (int) preferencesTable:(UIPreferencesTable *)table numberOfRowsInGroup:(int)group {
1357 case 0: return [package_ website] == nil ? 2 : 3;
1361 default: _assert(false);
1365 - (UIPreferencesTableCell *) preferencesTable:(UIPreferencesTable *)table cellForRow:(int)row inGroup:(int)group {
1366 UIPreferencesTableCell *cell = [[[UIPreferencesTableCell alloc] init] autorelease];
1367 [cell setShowSelection:NO];
1370 case 0: switch (row) {
1372 [cell setTitle:[package_ name]];
1373 [cell setValue:[package_ latest]];
1377 [cell addSubview:description_];
1381 [cell setTitle:@"More Information"];
1382 [cell setShowDisclosure:YES];
1383 [cell setShowSelection:YES];
1386 default: _assert(false);
1389 case 1: switch (row) {
1391 [cell setTitle:@"Identifier"];
1392 [cell setValue:[package_ id]];
1396 [cell setTitle:@"Installed Version"];
1397 NSString *installed([package_ installed]);
1398 [cell setValue:(installed == nil ? @"n/a" : installed)];
1402 [cell setTitle:@"Section"];
1403 NSString *section([package_ section]);
1404 [cell setValue:(section == nil ? @"n/a" : section)];
1408 [cell setTitle:@"Expanded Size"];
1409 [cell setValue:SizeString([package_ size])];
1413 [cell setTitle:@"Maintainer"];
1414 [cell setValue:[[package_ maintainer] name]];
1415 [cell setShowDisclosure:YES];
1416 [cell setShowSelection:YES];
1419 default: _assert(false);
1422 case 2: switch (row) {
1425 default: _assert(false);
1431 - (BOOL) canSelectRow:(int)row {
1435 - (void) tableRowSelected:(NSNotification *)notification {
1436 int row = [table_ selectedRow];
1437 NSString *website = [package_ website];
1439 if (row == (website == nil ? 8 : 9))
1440 [delegate_ openURL:[NSURL URLWithString:[NSString stringWithFormat:@"mailto:%@?subject=%@",
1441 [[package_ maintainer] email],
1442 [[NSString stringWithFormat:@"regarding apt package \"%@\"", [package_ name]] stringByAddingPercentEscapes]
1444 else if (website != nil && row == 3)
1445 [delegate_ openURL:[NSURL URLWithString:website]];
1448 - (Package *) package {
1452 - (id) initWithFrame:(struct CGRect)frame {
1453 if ((self = [super initWithFrame:frame]) != nil) {
1454 table_ = [[UIPreferencesTable alloc] initWithFrame:[self bounds]];
1455 [self addSubview:table_];
1457 [table_ setDataSource:self];
1458 [table_ setDelegate:self];
1462 - (void) setPackage:(Package *)package {
1463 if (package_ != nil) {
1464 [package_ autorelease];
1468 if (description_ != nil) {
1469 [description_ release];
1473 if (package != nil) {
1474 package_ = [package retain];
1476 NSString *description([package description]);
1477 if (description == nil)
1478 description = [package tagline];
1479 description_ = [GetTextView(description, 12, true) retain];
1481 CGColorSpaceRef space = CGColorSpaceCreateDeviceRGB();
1482 CGColor black(space, 0, 0, 0, 1);
1483 [description_ setTextColor:black];
1484 CGColorSpaceRelease(space);
1486 [table_ reloadData];
1490 - (void) setDelegate:(id)delegate {
1491 delegate_ = delegate;
1496 /* Package Cell {{{ */
1497 @interface PackageCell : UITableCell {
1499 UITextLabel *version_;
1500 UITextLabel *description_;
1506 - (PackageCell *) initWithVersioner:(SEL)versioner;
1507 - (void) setPackage:(Package *)package;
1509 - (void) _setSelected:(float)fraction;
1510 - (void) setSelected:(BOOL)selected;
1511 - (void) setSelected:(BOOL)selected withFade:(BOOL)fade;
1512 - (void) _setSelectionFadeFraction:(float)fraction;
1516 @implementation PackageCell
1521 [description_ release];
1525 - (PackageCell *) initWithVersioner:(SEL)versioner {
1526 if ((self = [super init]) != nil) {
1527 versioner_ = versioner;
1529 GSFontRef bold = GSFontCreateWithName("Helvetica", kGSFontTraitBold, 22);
1530 GSFontRef large = GSFontCreateWithName("Helvetica", kGSFontTraitNone, 16);
1531 GSFontRef small = GSFontCreateWithName("Helvetica", kGSFontTraitNone, 14);
1533 CGColorSpaceRef space = CGColorSpaceCreateDeviceRGB();
1535 CGColor clear(space, 0, 0, 0, 0);
1537 name_ = [[UITextLabel alloc] initWithFrame:CGRectMake(12, 7, 250, 25)];
1538 [name_ setBackgroundColor:clear];
1539 [name_ setFont:bold];
1541 version_ = [[UIRightTextLabel alloc] initWithFrame:CGRectMake(286, 7, 70, 25)];
1542 [version_ setBackgroundColor:clear];
1543 [version_ setFont:large];
1545 description_ = [[UITextLabel alloc] initWithFrame:CGRectMake(13, 35, 280, 20)];
1546 [description_ setBackgroundColor:clear];
1547 [description_ setFont:small];
1549 [self addSubview:name_];
1550 [self addSubview:version_];
1551 [self addSubview:description_];
1553 CGColorSpaceRelease(space);
1561 - (void) setPackage:(Package *)package {
1562 [name_ setText:[package name]];
1563 [version_ setText:[package latest]];
1564 [description_ setText:[package tagline]];
1567 - (void) _setSelected:(float)fraction {
1568 CGColorSpaceRef space = CGColorSpaceCreateDeviceRGB();
1570 CGColor black(space,
1571 interpolate(0.0, 1.0, fraction),
1572 interpolate(0.0, 1.0, fraction),
1573 interpolate(0.0, 1.0, fraction),
1577 interpolate(0.2, 1.0, fraction),
1578 interpolate(0.2, 1.0, fraction),
1579 interpolate(1.0, 1.0, fraction),
1583 interpolate(0.4, 1.0, fraction),
1584 interpolate(0.4, 1.0, fraction),
1585 interpolate(0.4, 1.0, fraction),
1588 [name_ setColor:black];
1589 [version_ setColor:blue];
1590 [description_ setColor:gray];
1592 CGColorSpaceRelease(space);
1595 - (void) setSelected:(BOOL)selected {
1596 [self _setSelected:(selected ? 1.0 : 0.0)];
1597 [super setSelected:selected];
1600 - (void) setSelected:(BOOL)selected withFade:(BOOL)fade {
1602 [self _setSelected:(selected ? 1.0 : 0.0)];
1603 [super setSelected:selected withFade:fade];
1606 - (void) _setSelectionFadeFraction:(float)fraction {
1607 [self _setSelected:fraction];
1608 [super _setSelectionFadeFraction:fraction];
1614 /* Database Implementation {{{ */
1615 @implementation Database
1622 - (void) _readStatus:(NSNumber *)fd {
1623 NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init];
1625 __gnu_cxx::stdio_filebuf<char> ib([fd intValue], std::ios::in);
1626 std::istream is(&ib);
1631 pcre *code = pcre_compile("^([^:]*):([^:]*):([^:]*):(.*)$", 0, &error, &offset, NULL);
1633 pcre_extra *study = NULL;
1635 pcre_fullinfo(code, study, PCRE_INFO_CAPTURECOUNT, &capture);
1636 int matches[(capture + 1) * 3];
1638 while (std::getline(is, line)) {
1639 const char *data(line.c_str());
1641 _assert(pcre_exec(code, study, data, line.size(), 0, 0, matches, sizeof(matches) / sizeof(matches[0])) >= 0);
1643 std::istringstream buffer(line.substr(matches[6], matches[7] - matches[6]));
1646 [delegate_ setPercent:(percent / 100)];
1648 NSString *string = [NSString stringWithCString:(data + matches[8]) length:(matches[9] - matches[8])];
1649 std::string type(line.substr(matches[2], matches[3] - matches[2]));
1651 if (type == "pmerror")
1652 [delegate_ setError:string];
1653 else if (type == "pmstatus")
1654 [delegate_ setTitle:string];
1655 else if (type == "pmconffile")
1657 else _assert(false);
1664 - (void) _readOutput:(NSNumber *)fd {
1665 NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init];
1667 __gnu_cxx::stdio_filebuf<char> ib([fd intValue], std::ios::in);
1668 std::istream is(&ib);
1671 while (std::getline(is, line))
1672 [delegate_ addOutput:[NSString stringWithCString:line.c_str()]];
1678 - (Package *) packageWithName:(NSString *)name {
1679 pkgCache::PkgIterator iterator(cache_->FindPkg([name cString]));
1680 return iterator.end() ? nil : [Package packageWithIterator:iterator database:self];
1683 - (Database *) init {
1684 if ((self = [super init]) != nil) {
1692 _assert(pipe(fds) != -1);
1696 detachNewThreadSelector:@selector(_readStatus:)
1698 withObject:[[NSNumber numberWithInt:fds[0]] retain]
1701 _assert(pipe(fds) != -1);
1702 _assert(dup2(fds[1], 1) != -1);
1703 _assert(close(fds[1]) != -1);
1706 detachNewThreadSelector:@selector(_readOutput:)
1708 withObject:[[NSNumber numberWithInt:fds[0]] retain]
1713 - (pkgCacheFile &) cache {
1717 - (pkgRecords *) records {
1721 - (pkgProblemResolver *) resolver {
1725 - (pkgAcquire &) fetcher {
1729 - (void) reloadData {
1738 if (!cache_.Open(progress_, true)) {
1739 fprintf(stderr, "repairing corrupted database...\n");
1742 _assert(cache_.Open(progress_, true));
1745 records_ = new pkgRecords(cache_);
1746 resolver_ = new pkgProblemResolver(cache_);
1747 fetcher_ = new pkgAcquire(&status_);
1752 pkgRecords records(cache_);
1754 lock_ = new FileFd();
1755 lock_->Fd(GetLock(_config->FindDir("Dir::Cache::Archives") + "lock"));
1756 _assert(!_error->PendingError());
1759 _assert(list.ReadMainList());
1761 manager_ = (_system->CreatePM(cache_));
1762 _assert(manager_->GetArchives(fetcher_, &list, &records));
1763 _assert(!_error->PendingError());
1767 if (fetcher_->Run(PulseInterval_) != pkgAcquire::Continue)
1771 pkgPackageManager::OrderResult result = manager_->DoInstall(statusfd_);
1773 if (result == pkgPackageManager::Failed)
1775 if (_error->PendingError())
1777 if (result != pkgPackageManager::Completed)
1783 _assert(list.ReadMainList());
1786 lock.Fd(GetLock(_config->FindDir("Dir::State::Lists") + "lock"));
1787 _assert(!_error->PendingError());
1789 pkgAcquire fetcher(&status_);
1790 _assert(list.GetIndexes(&fetcher));
1791 _assert(fetcher.Run(PulseInterval_) != pkgAcquire::Failed);
1793 bool failed = false;
1794 for (pkgAcquire::ItemIterator item = fetcher.ItemsBegin(); item != fetcher.ItemsEnd(); item++)
1795 if ((*item)->Status != pkgAcquire::Item::StatDone) {
1796 (*item)->Finished();
1800 if (!failed && _config->FindB("APT::Get::List-Cleanup", true) == true) {
1801 _assert(fetcher.Clean(_config->FindDir("Dir::State::lists")));
1802 _assert(fetcher.Clean(_config->FindDir("Dir::State::lists") + "partial/"));
1805 [Metadata_ setObject:[NSDate date] forKey:@"LastUpdate"];
1809 _assert(cache_->DelCount() == 0 && cache_->InstCount() == 0);
1810 _assert(pkgApplyStatus(cache_));
1812 if (cache_->BrokenCount() != 0) {
1813 _assert(pkgFixBroken(cache_));
1814 _assert(cache_->BrokenCount() == 0);
1815 _assert(pkgMinimizeUpgrade(cache_));
1818 _assert(pkgDistUpgrade(cache_));
1821 - (void) setDelegate:(id)delegate {
1822 delegate_ = delegate;
1823 status_.setDelegate(delegate);
1824 progress_.setDelegate(delegate);
1830 /* Progress Data {{{ */
1831 @interface ProgressData : NSObject {
1837 - (ProgressData *) initWithSelector:(SEL)selector target:(id)target object:(id)object;
1844 @implementation ProgressData
1846 - (ProgressData *) initWithSelector:(SEL)selector target:(id)target object:(id)object {
1847 if ((self = [super init]) != nil) {
1848 selector_ = selector;
1868 /* Progress View {{{ */
1869 @interface ProgressView : UIView <
1873 UIView *background_;
1874 UITransitionView *transition_;
1876 UINavigationBar *navbar_;
1877 UIProgressBar *progress_;
1878 UITextView *output_;
1879 UITextLabel *status_;
1885 - (void) transitionViewDidComplete:(UITransitionView*)view fromView:(UIView*)from toView:(UIView*)to;
1887 - (ProgressView *) initWithFrame:(struct CGRect)frame delegate:(id)delegate;
1888 - (void) setContentView:(UIView *)view;
1891 - (void) alertSheet:(UIAlertSheet *)sheet buttonClicked:(int)button;
1893 - (void) _retachThread;
1894 - (void) _detachNewThreadData:(ProgressData *)data;
1895 - (void) detachNewThreadSelector:(SEL)selector toTarget:(id)target withObject:(id)object title:(NSString *)title;
1897 - (void) setError:(NSString *)error;
1898 - (void) _setError:(NSString *)error;
1900 - (void) setTitle:(NSString *)title;
1901 - (void) _setTitle:(NSString *)title;
1903 - (void) setPercent:(float)percent;
1904 - (void) _setPercent:(NSNumber *)percent;
1906 - (void) addOutput:(NSString *)output;
1907 - (void) _addOutput:(NSString *)output;
1910 @protocol ProgressViewDelegate
1911 - (void) progressViewIsComplete:(ProgressView *)sender;
1914 @implementation ProgressView
1918 if (background_ != nil)
1919 [background_ release];
1920 [transition_ release];
1923 [progress_ release];
1929 - (void) transitionViewDidComplete:(UITransitionView*)view fromView:(UIView*)from toView:(UIView*)to {
1930 if (bootstrap_ && from == overlay_ && to == view_)
1934 - (ProgressView *) initWithFrame:(struct CGRect)frame delegate:(id)delegate {
1935 if ((self = [super initWithFrame:frame]) != nil) {
1936 delegate_ = delegate;
1938 CGColorSpaceRef space = CGColorSpaceCreateDeviceRGB();
1940 CGColor black(space, 0.0, 0.0, 0.0, 1.0);
1941 CGColor white(space, 1.0, 1.0, 1.0, 1.0);
1942 CGColor clear(space, 0.0, 0.0, 0.0, 0.0);
1944 transition_ = [[UITransitionView alloc] initWithFrame:[self bounds]];
1945 [transition_ setDelegate:self];
1947 overlay_ = [[UIView alloc] initWithFrame:[transition_ bounds]];
1950 [overlay_ setBackgroundColor:black];
1952 background_ = [[UIView alloc] initWithFrame:[self bounds]];
1953 [background_ setBackgroundColor:black];
1954 [self addSubview:background_];
1957 [self addSubview:transition_];
1959 CGSize navsize = [UINavigationBar defaultSize];
1960 CGRect navrect = {{0, 0}, navsize};
1962 navbar_ = [[UINavigationBar alloc] initWithFrame:navrect];
1963 [overlay_ addSubview:navbar_];
1965 [navbar_ setBarStyle:1];
1966 [navbar_ setDelegate:self];
1968 UINavigationItem *navitem = [[[UINavigationItem alloc] initWithTitle:nil] autorelease];
1969 [navbar_ pushNavigationItem:navitem];
1971 CGRect bounds = [overlay_ bounds];
1972 CGSize prgsize = [UIProgressBar defaultSize];
1975 (bounds.size.width - prgsize.width) / 2,
1976 bounds.size.height - prgsize.height - 20
1979 progress_ = [[UIProgressBar alloc] initWithFrame:prgrect];
1980 [overlay_ addSubview:progress_];
1982 status_ = [[UITextLabel alloc] initWithFrame:CGRectMake(
1984 bounds.size.height - prgsize.height - 50,
1985 bounds.size.width - 20,
1989 [status_ setColor:white];
1990 [status_ setBackgroundColor:clear];
1992 [status_ setCentersHorizontally:YES];
1993 //[status_ setFont:font];
1995 output_ = [[UITextView alloc] initWithFrame:CGRectMake(
1997 navrect.size.height + 20,
1998 bounds.size.width - 20,
1999 bounds.size.height - navsize.height - 62 - navrect.size.height
2002 //[output_ setTextFont:@"Courier New"];
2003 [output_ setTextSize:12];
2005 [output_ setTextColor:white];
2006 [output_ setBackgroundColor:clear];
2008 [output_ setMarginTop:0];
2009 [output_ setAllowsRubberBanding:YES];
2011 [overlay_ addSubview:output_];
2012 [overlay_ addSubview:status_];
2014 [progress_ setStyle:0];
2016 CGColorSpaceRelease(space);
2020 - (void) setContentView:(UIView *)view {
2021 view_ = [view retain];
2024 - (void) resetView {
2025 [transition_ transition:6 toView:view_];
2028 - (void) alertSheet:(UIAlertSheet *)sheet buttonClicked:(int)button {
2032 - (void) _retachThread {
2033 [delegate_ progressViewIsComplete:self];
2037 - (void) _detachNewThreadData:(ProgressData *)data {
2038 NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init];
2040 [[data target] performSelector:[data selector] withObject:[data object]];
2043 [self performSelectorOnMainThread:@selector(_retachThread) withObject:nil waitUntilDone:YES];
2048 - (void) detachNewThreadSelector:(SEL)selector toTarget:(id)target withObject:(id)object title:(NSString *)title {
2049 [navbar_ popNavigationItem];
2050 UINavigationItem *navitem = [[[UINavigationItem alloc] initWithTitle:title] autorelease];
2051 [navbar_ pushNavigationItem:navitem];
2053 [status_ setText:nil];
2054 [output_ setText:@""];
2055 [progress_ setProgress:0];
2057 [transition_ transition:6 toView:overlay_];
2060 detachNewThreadSelector:@selector(_detachNewThreadData:)
2062 withObject:[[ProgressData alloc]
2063 initWithSelector:selector
2070 - (void) setError:(NSString *)error {
2072 performSelectorOnMainThread:@selector(_setError:)
2078 - (void) _setError:(NSString *)error {
2079 UIAlertSheet *sheet = [[[UIAlertSheet alloc]
2080 initWithTitle:@"Package Error"
2081 buttons:[NSArray arrayWithObjects:@"Okay", nil]
2082 defaultButtonIndex:0
2087 [sheet setBodyText:error];
2088 [sheet popupAlertAnimated:YES];
2091 - (void) setTitle:(NSString *)title {
2093 performSelectorOnMainThread:@selector(_setTitle:)
2099 - (void) _setTitle:(NSString *)title {
2100 [status_ setText:[title stringByAppendingString:@"..."]];
2103 - (void) setPercent:(float)percent {
2105 performSelectorOnMainThread:@selector(_setPercent:)
2106 withObject:[NSNumber numberWithFloat:percent]
2111 - (void) _setPercent:(NSNumber *)percent {
2112 [progress_ setProgress:[percent floatValue]];
2115 - (void) addOutput:(NSString *)output {
2117 performSelectorOnMainThread:@selector(_addOutput:)
2123 - (void) _addOutput:(NSString *)output {
2124 [output_ setText:[NSString stringWithFormat:@"%@\n%@", [output_ text], output]];
2125 CGSize size = [output_ contentSize];
2126 CGRect rect = {{0, size.height}, {size.width, 0}};
2127 [output_ scrollRectToVisible:rect animated:YES];
2133 /* Package Table {{{ */
2134 @protocol PackageTableDelegate
2135 - (void) packageTable:(id)table packageSelected:(Package *)package;
2138 @interface PackageTable : UIView {
2140 UISectionList *list_;
2144 NSMutableArray *sections_;
2149 - (int) numberOfSectionsInSectionList:(UISectionList *)list;
2150 - (NSString *) sectionList:(UISectionList *)list titleForSection:(int)section;
2151 - (int) sectionList:(UISectionList *)list rowForSection:(int)section;
2153 - (int) numberOfRowsInTable:(UITable *)table;
2154 - (float) table:(UITable *)table heightForRow:(int)row;
2155 - (UITableCell *) table:(UITable *)table cellForRow:(int)row column:(UITableColumn *)col reusing:(UITableCell *)reusing;
2156 - (BOOL) table:(UITable *)table showDisclosureForRow:(int)row;
2157 - (void) tableRowSelected:(NSNotification *)notification;
2159 - (id) initWithFrame:(CGRect)frame versioner:(SEL)versioner;
2161 - (void) setDelegate:(id)delegate;
2162 - (void) setPackages:(NSArray *)packages;
2164 - (void) resetViewAnimated:(BOOL)animated;
2165 - (UITable *) table;
2168 @implementation PackageTable
2172 [sections_ release];
2173 if (packages_ != nil)
2174 [packages_ release];
2178 - (int) numberOfSectionsInSectionList:(UISectionList *)list {
2179 return [sections_ count];
2182 - (NSString *) sectionList:(UISectionList *)list titleForSection:(int)section {
2183 return [[sections_ objectAtIndex:section] name];
2186 - (int) sectionList:(UISectionList *)list rowForSection:(int)section {
2187 return [[sections_ objectAtIndex:section] row];
2190 - (int) numberOfRowsInTable:(UITable *)table {
2191 return [packages_ count];
2194 - (float) table:(UITable *)table heightForRow:(int)row {
2198 - (UITableCell *) table:(UITable *)table cellForRow:(int)row column:(UITableColumn *)col reusing:(UITableCell *)reusing {
2200 reusing = [[[PackageCell alloc] initWithVersioner:versioner_] autorelease];
2201 [(PackageCell *)reusing setPackage:[packages_ objectAtIndex:row]];
2205 - (BOOL) table:(UITable *)table showDisclosureForRow:(int)row {
2209 - (void) tableRowSelected:(NSNotification *)notification {
2210 int row = [[notification object] selectedRow];
2211 [delegate_ packageTable:self packageSelected:(row == INT_MAX ? nil : [packages_ objectAtIndex:row])];
2214 - (id) initWithFrame:(CGRect)frame versioner:(SEL)versioner {
2215 if ((self = [super initWithFrame:frame]) != nil) {
2216 versioner_ = versioner;
2217 sections_ = [[NSMutableArray arrayWithCapacity:16] retain];
2219 list_ = [[UISectionList alloc] initWithFrame:[self bounds] showSectionIndex:YES];
2220 [list_ setDataSource:self];
2222 UITableColumn *column = [[[UITableColumn alloc]
2223 initWithTitle:@"Name"
2225 width:frame.size.width
2228 UITable *table = [list_ table];
2229 [table setSeparatorStyle:1];
2230 [table addTableColumn:column];
2231 [table setDelegate:self];
2232 [table setReusesTableCells:YES];
2234 [self addSubview:list_];
2238 - (void) setDelegate:(id)delegate {
2239 delegate_ = delegate;
2242 - (void) setPackages:(NSArray *)packages {
2243 if (packages_ != nil)
2244 [packages_ autorelease];
2245 _assert(packages != nil);
2246 packages_ = [packages retain];
2248 [sections_ removeAllObjects];
2250 Section *section = nil;
2252 for (size_t offset(0); offset != [packages_ count]; ++offset) {
2253 Package *package = [packages_ objectAtIndex:offset];
2254 NSString *name = [package index];
2256 if (section == nil || ![[section name] isEqual:name]) {
2257 section = [[[Section alloc] initWithName:name row:offset] autorelease];
2258 [sections_ addObject:section];
2261 [section addPackage:package];
2267 - (void) resetViewAnimated:(BOOL)animated {
2268 [[list_ table] selectRow:-1 byExtendingSelection:NO withFade:animated];
2271 - (UITable *) table {
2272 return [list_ table];
2278 /* Section Cell {{{ */
2279 @interface SectionCell : UITableCell {
2281 UITextLabel *count_;
2287 - (void) setSection:(Section *)section;
2289 - (void) _setSelected:(float)fraction;
2290 - (void) setSelected:(BOOL)selected;
2291 - (void) setSelected:(BOOL)selected withFade:(BOOL)fade;
2292 - (void) _setSelectionFadeFraction:(float)fraction;
2296 @implementation SectionCell
2305 if ((self = [super init]) != nil) {
2306 GSFontRef bold = GSFontCreateWithName("Helvetica", kGSFontTraitBold, 22);
2307 GSFontRef small = GSFontCreateWithName("Helvetica", kGSFontTraitBold, 12);
2309 CGColorSpaceRef space = CGColorSpaceCreateDeviceRGB();
2310 CGColor clear(space, 0, 0, 0, 0);
2311 CGColor white(space, 1, 1, 1, 1);
2313 name_ = [[UITextLabel alloc] initWithFrame:CGRectMake(47, 9, 250, 25)];
2314 [name_ setBackgroundColor:clear];
2315 [name_ setFont:bold];
2317 count_ = [[UITextLabel alloc] initWithFrame:CGRectMake(11, 7, 29, 32)];
2318 [count_ setCentersHorizontally:YES];
2319 [count_ setBackgroundColor:clear];
2320 [count_ setFont:small];
2321 [count_ setColor:white];
2323 UIImageView *folder = [[[UIImageView alloc] initWithFrame:CGRectMake(8, 7, 32, 32)] autorelease];
2324 [folder setImage:[UIImage applicationImageNamed:@"folder.png"]];
2326 [self addSubview:folder];
2327 [self addSubview:name_];
2328 [self addSubview:count_];
2330 [self _setSelected:0];
2332 CGColorSpaceRelease(space);
2339 - (void) setSection:(Section *)section {
2340 if (section == nil) {
2341 [name_ setText:@"All Packages"];
2342 [count_ setText:nil];
2344 NSString *name = [section name];
2345 [name_ setText:(name == nil ? @"(No Section)" : name)];
2346 [count_ setText:[NSString stringWithFormat:@"%d", [section count]]];
2350 - (void) _setSelected:(float)fraction {
2351 CGColorSpaceRef space = CGColorSpaceCreateDeviceRGB();
2353 CGColor black(space,
2354 interpolate(0.0, 1.0, fraction),
2355 interpolate(0.0, 1.0, fraction),
2356 interpolate(0.0, 1.0, fraction),
2359 [name_ setColor:black];
2361 CGColorSpaceRelease(space);
2364 - (void) setSelected:(BOOL)selected {
2365 [self _setSelected:(selected ? 1.0 : 0.0)];
2366 [super setSelected:selected];
2369 - (void) setSelected:(BOOL)selected withFade:(BOOL)fade {
2371 [self _setSelected:(selected ? 1.0 : 0.0)];
2372 [super setSelected:selected withFade:fade];
2375 - (void) _setSelectionFadeFraction:(float)fraction {
2376 [self _setSelected:fraction];
2377 [super _setSelectionFadeFraction:fraction];
2382 /* Install View {{{ */
2383 @interface InstallView : ResetView <
2384 PackageTableDelegate
2388 PackageTable *table_;
2392 NSMutableArray *packages_;
2397 - (void) navigationBar:(UINavigationBar *)navbar buttonClicked:(int)button;
2399 - (int) numberOfRowsInTable:(UITable *)table;
2400 - (float) table:(UITable *)table heightForRow:(int)row;
2401 - (UITableCell *) table:(UITable *)table cellForRow:(int)row column:(UITableColumn *)col reusing:(UITableCell *)reusing;
2402 - (BOOL) table:(UITable *)table showDisclosureForRow:(int)row;
2403 - (void) tableRowSelected:(NSNotification *)notification;
2405 - (void) packageTable:(id)table packageSelected:(Package *)package;
2407 - (id) initWithFrame:(CGRect)frame;
2408 - (void) setPackages:(NSArray *)packages;
2409 - (void) setDelegate:(id)delegate;
2412 @implementation InstallView
2415 [packages_ release];
2416 if (sections_ != nil)
2417 [sections_ release];
2424 if (section_ != nil)
2426 if (package_ != nil)
2431 - (void) navigationBar:(UINavigationBar *)navbar buttonClicked:(int)button {
2433 [[view_ package] install];
2434 [delegate_ resolve];
2435 [delegate_ perform];
2439 - (int) numberOfRowsInTable:(UITable *)table {
2440 return [sections_ count] + 1;
2443 - (float) table:(UITable *)table heightForRow:(int)row {
2447 - (UITableCell *) table:(UITable *)table cellForRow:(int)row column:(UITableColumn *)col reusing:(UITableCell *)reusing {
2449 reusing = [[[SectionCell alloc] init] autorelease];
2451 [(SectionCell *)reusing setSection:nil];
2453 [(SectionCell *)reusing setSection:[sections_ objectAtIndex:(row - 1)]];
2457 - (BOOL) table:(UITable *)table showDisclosureForRow:(int)row {
2461 - (void) tableRowSelected:(NSNotification *)notification {
2462 int row = [[notification object] selectedRow];
2464 if (row == INT_MAX) {
2471 _assert(section_ == nil);
2472 _assert(table_ == nil);
2480 name = @"All Packages";
2482 section = [sections_ objectAtIndex:(row - 1)];
2483 name = [section name];
2484 section_ = [name retain];
2487 table_ = [[PackageTable alloc] initWithFrame:[transition_ bounds] versioner:@selector(latest)];
2488 [table_ setDelegate:self];
2489 [table_ setPackages:(section == nil ? packages_ : [section packages])];
2491 [self pushView:table_ withTitle:name backButtonTitle:@"Packages" rightButton:nil];
2495 - (void) packageTable:(id)table packageSelected:(Package *)package {
2496 if (package == nil) {
2503 _assert(package_ == nil);
2504 _assert(view_ == nil);
2506 package_ = [[package name] retain];
2508 view_ = [[PackageView alloc] initWithFrame:[transition_ bounds]];
2509 [view_ setDelegate:delegate_];
2511 [view_ setPackage:package];
2513 [self pushView:view_ withTitle:[package name] backButtonTitle:nil rightButton:@"Install"];
2517 - (id) initWithFrame:(CGRect)frame {
2518 if ((self = [super initWithFrame:frame]) != nil) {
2519 packages_ = [[NSMutableArray arrayWithCapacity:16] retain];
2521 list_ = [[UITable alloc] initWithFrame:[transition_ bounds]];
2522 [self pushView:list_ withTitle:@"Install" backButtonTitle:@"Sections" rightButton:nil];
2524 UITableColumn *column = [[[UITableColumn alloc]
2525 initWithTitle:@"Name"
2527 width:frame.size.width
2530 [list_ setDataSource:self];
2531 [list_ setSeparatorStyle:1];
2532 [list_ addTableColumn:column];
2533 [list_ setDelegate:self];
2534 [list_ setReusesTableCells:YES];
2536 [transition_ transition:0 toView:list_];
2540 - (void) setPackages:(NSArray *)packages {
2541 [packages_ removeAllObjects];
2543 for (size_t i(0); i != [packages count]; ++i) {
2544 Package *package([packages objectAtIndex:i]);
2545 if ([package installed] == nil)
2546 [packages_ addObject:package];
2549 [packages_ sortUsingSelector:@selector(compareBySectionAndName:)];
2550 NSMutableArray *sections = [NSMutableArray arrayWithCapacity:16];
2552 Section *nsection = nil;
2553 Package *npackage = nil;
2555 Section *section = nil;
2556 for (size_t offset = 0, count = [packages_ count]; offset != count; ++offset) {
2557 Package *package = [packages_ objectAtIndex:offset];
2558 NSString *name = [package section];
2560 if (section == nil || name != nil && ![[section name] isEqual:name]) {
2561 section = [[[Section alloc] initWithName:name row:offset] autorelease];
2563 if (name == nil || [name isEqualToString:section_])
2565 [sections addObject:section];
2568 if ([[package name] isEqualToString:package_])
2570 [section addPackage:package];
2573 if (sections_ != nil)
2574 [sections_ release];
2575 sections_ = [sections retain];
2577 [packages_ sortUsingSelector:@selector(compareByName:)];
2583 if (npackage != nil)
2584 [view_ setPackage:npackage];
2585 else if (package_ != nil)
2588 if (table_ != nil && section_ == nil)
2589 [table_ setPackages:packages_];
2590 else if (nsection != nil)
2591 [table_ setPackages:[nsection packages]];
2592 else if (section_ != nil)
2596 [self popViews:views];
2600 - (void) setDelegate:(id)delegate {
2602 [view_ setDelegate:delegate];
2603 [super setDelegate:delegate];
2608 /* Changes View {{{ */
2609 @interface ChangesView : ResetView <
2610 PackageTableDelegate
2612 UISectionList *list_;
2613 NSMutableArray *packages_;
2614 NSMutableArray *sections_;
2622 - (void) navigationBar:(UINavigationBar *)navbar buttonClicked:(int)button;
2624 - (int) numberOfSectionsInSectionList:(UISectionList *)list;
2625 - (NSString *) sectionList:(UISectionList *)list titleForSection:(int)section;
2626 - (int) sectionList:(UISectionList *)list rowForSection:(int)section;
2628 - (int) numberOfRowsInTable:(UITable *)table;
2629 - (float) table:(UITable *)table heightForRow:(int)row;
2630 - (UITableCell *) table:(UITable *)table cellForRow:(int)row column:(UITableColumn *)col reusing:(UITableCell *)reusing;
2631 - (BOOL) table:(UITable *)table showDisclosureForRow:(int)row;
2632 - (void) tableRowSelected:(NSNotification *)notification;
2634 - (id) initWithFrame:(CGRect)frame;
2635 - (void) setPackages:(NSArray *)packages;
2636 - (void) _resetView;
2639 - (void) setDelegate:(id)delegate;
2642 @implementation ChangesView
2646 [packages_ release];
2647 [sections_ release];
2650 if (package_ != nil)
2655 - (int) numberOfSectionsInSectionList:(UISectionList *)list {
2656 return [sections_ count];
2659 - (NSString *) sectionList:(UISectionList *)list titleForSection:(int)section {
2660 return [[sections_ objectAtIndex:section] name];
2663 - (int) sectionList:(UISectionList *)list rowForSection:(int)section {
2664 return [[sections_ objectAtIndex:section] row];
2667 - (int) numberOfRowsInTable:(UITable *)table {
2668 return [packages_ count];
2671 - (float) table:(UITable *)table heightForRow:(int)row {
2675 - (UITableCell *) table:(UITable *)table cellForRow:(int)row column:(UITableColumn *)col reusing:(UITableCell *)reusing {
2677 reusing = [[[PackageCell alloc] initWithVersioner:NULL] autorelease];
2678 [(PackageCell *)reusing setPackage:[packages_ objectAtIndex:row]];
2682 - (BOOL) table:(UITable *)table showDisclosureForRow:(int)row {
2686 - (void) tableRowSelected:(NSNotification *)notification {
2687 int row = [[notification object] selectedRow];
2688 [self packageTable:self packageSelected:(row == INT_MAX ? nil : [packages_ objectAtIndex:row])];
2691 - (void) navigationBar:(UINavigationBar *)navbar buttonClicked:(int)button {
2694 [[view_ package] install];
2695 [delegate_ resolve];
2696 [delegate_ perform];
2700 [delegate_ upgrade];
2705 - (void) packageTable:(id)table packageSelected:(Package *)package {
2706 if (package == nil) {
2713 _assert(package_ == nil);
2714 _assert(view_ == nil);
2716 package_ = [[package name] retain];
2718 view_ = [[PackageView alloc] initWithFrame:[transition_ bounds]];
2719 [view_ setDelegate:delegate_];
2721 [view_ setPackage:package];
2723 [self pushView:view_ withTitle:[package name] backButtonTitle:nil rightButton:(
2724 [package upgradable] ? @"Upgrade" : @"Install"
2729 - (id) initWithFrame:(CGRect)frame {
2730 if ((self = [super initWithFrame:frame]) != nil) {
2731 packages_ = [[NSMutableArray arrayWithCapacity:16] retain];
2732 sections_ = [[NSMutableArray arrayWithCapacity:16] retain];
2734 list_ = [[UISectionList alloc] initWithFrame:[transition_ bounds] showSectionIndex:NO];
2735 [list_ setShouldHideHeaderInShortLists:NO];
2736 [list_ setDataSource:self];
2737 //[list_ setSectionListStyle:1];
2739 UITableColumn *column = [[[UITableColumn alloc]
2740 initWithTitle:@"Name"
2742 width:frame.size.width
2745 UITable *table = [list_ table];
2746 [table setSeparatorStyle:1];
2747 [table addTableColumn:column];
2748 [table setDelegate:self];
2749 [table setReusesTableCells:YES];
2751 [self pushView:list_ withTitle:@"Changes" backButtonTitle:nil rightButton:nil];
2755 - (void) setPackages:(NSArray *)packages {
2756 [packages_ removeAllObjects];
2757 for (size_t i(0); i != [packages count]; ++i) {
2758 Package *package([packages objectAtIndex:i]);
2759 if ([package installed] == nil || [package upgradable])
2760 [packages_ addObject:package];
2763 [packages_ sortUsingSelector:@selector(compareForChanges:)];
2765 [sections_ removeAllObjects];
2767 Section *upgradable = [[[Section alloc] initWithName:@"Available Upgrades" row:0] autorelease];
2768 Section *section = nil;
2771 Package *npackage = nil;
2772 for (size_t offset = 0, count = [packages_ count]; offset != count; ++offset) {
2773 Package *package = [packages_ objectAtIndex:offset];
2774 if ([[package name] isEqualToString:package_])
2777 if ([package upgradable])
2778 [upgradable addPackage:package];
2780 NSDate *seen = [package seen];
2782 CFLocaleRef locale = CFLocaleCopyCurrent();
2783 CFDateFormatterRef formatter = CFDateFormatterCreate(NULL, locale, kCFDateFormatterMediumStyle, kCFDateFormatterMediumStyle);
2784 CFStringRef formatted = CFDateFormatterCreateStringWithDate(NULL, formatter, (CFDateRef) seen);
2786 NSString *name = (NSString *) formatted;
2788 if (section == nil || ![[section name] isEqual:name]) {
2789 section = [[[Section alloc] initWithName:name row:offset] autorelease];
2790 [sections_ addObject:section];
2793 [section addPackage:package];
2795 CFRelease(formatter);
2796 CFRelease(formatted);
2801 count_ = [[upgradable packages] count];
2803 [sections_ insertObject:upgradable atIndex:0];
2807 if (npackage != nil)
2808 [view_ setPackage:npackage];
2809 else if (package_ != nil)
2816 - (void) _resetView {
2817 if ([views_ count] == 1)
2818 [navbar_ showButtonsWithLeftTitle:(count_ == 0 ? nil : @"Upgrade All") rightTitle:nil];
2825 - (void) setDelegate:(id)delegate {
2827 [view_ setDelegate:delegate];
2828 [super setDelegate:delegate];
2833 /* Manage View {{{ */
2834 @interface ManageView : ResetView <
2835 PackageTableDelegate
2837 PackageTable *table_;
2844 - (void) navigationBar:(UINavigationBar *)navbar buttonClicked:(int)button;
2846 - (void) packageTable:(id)table packageSelected:(Package *)package;
2848 - (id) initWithFrame:(CGRect)frame;
2849 - (void) setPackages:(NSArray *)packages;
2851 - (void) setDelegate:(id)delegate;
2854 @implementation ManageView
2860 if (package_ != nil)
2865 - (void) navigationBar:(UINavigationBar *)navbar buttonClicked:(int)button {
2867 [[view_ package] remove];
2868 [delegate_ resolve];
2869 [delegate_ perform];
2873 - (void) packageTable:(id)table packageSelected:(Package *)package {
2874 if (package == nil) {
2881 _assert(package_ == nil);
2882 _assert(view_ == nil);
2884 package_ = [[package name] retain];
2886 view_ = [[PackageView alloc] initWithFrame:[transition_ bounds]];
2887 [view_ setDelegate:delegate_];
2889 [view_ setPackage:package];
2891 [self pushView:view_ withTitle:[package name] backButtonTitle:nil rightButton:@"Uninstall"];
2895 - (id) initWithFrame:(CGRect)frame {
2896 if ((self = [super initWithFrame:frame]) != nil) {
2897 table_ = [[PackageTable alloc] initWithFrame:[transition_ bounds] versioner:@selector(latest)];
2898 [table_ setDelegate:self];
2900 [self pushView:table_ withTitle:@"Uninstall" backButtonTitle:@"Packages" rightButton:nil];
2904 - (void) setPackages:(NSArray *)packages {
2905 NSMutableArray *local = [NSMutableArray arrayWithCapacity:16];
2906 for (size_t i(0); i != [packages count]; ++i) {
2907 Package *package([packages objectAtIndex:i]);
2908 if ([package installed] != nil)
2909 [local addObject:package];
2912 [local sortUsingSelector:@selector(compareByName:)];
2914 Package *npackage = nil;
2915 for (size_t offset = 0, count = [local count]; offset != count; ++offset) {
2916 Package *package = [local objectAtIndex:offset];
2917 if ([[package name] isEqualToString:package_])
2921 [table_ setPackages:local];
2923 if (npackage != nil)
2924 [view_ setPackage:npackage];
2925 else if (package_ != nil)
2931 - (void) setDelegate:(id)delegate {
2933 [view_ setDelegate:delegate];
2934 [super setDelegate:delegate];
2939 /* Search View {{{ */
2940 @protocol SearchViewDelegate
2941 - (void) showKeyboard:(BOOL)show;
2944 @interface SearchView : ResetView <
2945 PackageTableDelegate
2947 NSMutableArray *packages_;
2949 UISearchField *field_;
2950 PackageTable *table_;
2957 - (void) navigationBar:(UINavigationBar *)navbar buttonClicked:(int)button;
2958 - (void) packageTable:(id)table packageSelected:(Package *)package;
2960 - (void) textFieldDidBecomeFirstResponder:(UITextField *)field;
2961 - (void) textFieldDidResignFirstResponder:(UITextField *)field;
2963 - (void) keyboardInputChanged:(UIFieldEditor *)editor;
2964 - (BOOL) keyboardInput:(id)input shouldInsertText:(NSString *)text isMarkedText:(int)marked;
2966 - (id) initWithFrame:(CGRect)frame;
2967 - (void) setPackages:(NSArray *)packages;
2969 - (void) setDelegate:(id)delegate;
2970 - (void) resetPackage:(Package *)package;
2971 - (void) searchPackages;
2975 @implementation SearchView
2978 [packages_ release];
2979 [accessory_ release];
2984 if (package_ != nil)
2989 - (void) navigationBar:(UINavigationBar *)navbar buttonClicked:(int)button {
2991 Package *package = [view_ package];
2992 if ([package installed] == nil)
2996 [delegate_ resolve];
2997 [delegate_ perform];
3001 - (void) packageTable:(id)table packageSelected:(Package *)package {
3002 if (package == nil) {
3003 [navbar_ setAccessoryView:accessory_ animate:(resetting_ ? NO : YES) goingBack:YES];
3011 [navbar_ setAccessoryView:nil animate:YES goingBack:NO];
3013 _assert(package_ == nil);
3014 _assert(view_ == nil);
3016 package_ = [[package name] retain];
3018 view_ = [[PackageView alloc] initWithFrame:[transition_ bounds]];
3019 [view_ setDelegate:delegate_];
3021 [self pushView:view_ withTitle:[package name] backButtonTitle:nil rightButton:nil];
3022 [self resetPackage:package];
3026 - (void) textFieldDidBecomeFirstResponder:(UITextField *)field {
3027 [delegate_ showKeyboard:YES];
3028 [table_ setEnabled:NO];
3030 /*CGColorSpaceRef space = CGColorSpaceCreateDeviceRGB();
3031 CGColor dimmed(alpha, 0, 0, 0, 0.5);
3032 [editor_ setBackgroundColor:dimmed];
3033 CGColorSpaceRelease(space);*/
3036 - (void) textFieldDidResignFirstResponder:(UITextField *)field {
3037 [table_ setEnabled:YES];
3038 [delegate_ showKeyboard:NO];
3041 - (void) keyboardInputChanged:(UIFieldEditor *)editor {
3042 NSString *text([field_ text]);
3043 [field_ setClearButtonStyle:(text == nil || [text length] == 0 ? 0 : 2)];
3046 - (BOOL) keyboardInput:(id)input shouldInsertText:(NSString *)text isMarkedText:(int)marked {
3047 if ([text length] != 1 || [text characterAtIndex:0] != '\n')
3050 [self searchPackages];
3051 [field_ resignFirstResponder];
3055 - (id) initWithFrame:(CGRect)frame {
3056 if ((self = [super initWithFrame:frame]) != nil) {
3057 packages_ = [[NSMutableArray arrayWithCapacity:16] retain];
3059 table_ = [[PackageTable alloc] initWithFrame:[transition_ bounds] versioner:@selector(latest)];
3060 [table_ setDelegate:self];
3062 CGRect area = [self bounds];
3065 area.size.width -= 12;
3066 area.size.height = [UISearchField defaultHeight];
3068 field_ = [[UISearchField alloc] initWithFrame:area];
3070 GSFontRef font = GSFontCreateWithName("Helvetica", kGSFontTraitNone, 16);
3071 [field_ setFont:font];
3074 [field_ setPlaceholder:@"Package Names & Descriptions"];
3075 [field_ setPaddingTop:5];
3076 [field_ setDelegate:self];
3078 UITextTraits *traits = [field_ textTraits];
3079 [traits setEditingDelegate:self];
3080 [traits setReturnKeyType:6];
3082 accessory_ = [[UIView alloc] initWithFrame:CGRectMake(6, 6, area.size.width, area.size.height + 30)];
3083 [accessory_ addSubview:field_];
3085 [navbar_ setAccessoryView:accessory_];
3086 [self pushView:table_ withTitle:nil backButtonTitle:@"Search" rightButton:nil];
3088 /* XXX: for the love of god just fix this */
3089 [navbar_ removeFromSuperview];
3090 [reload_ removeFromSuperview];
3091 [configure_ removeFromSuperview];
3092 [self addSubview:navbar_];
3093 [self addSubview:reload_];
3094 [self addSubview:configure_];
3098 - (void) setPackages:(NSArray *)packages {
3099 [packages_ removeAllObjects];
3100 [packages_ addObjectsFromArray:packages];
3101 [packages_ sortUsingSelector:@selector(compareByName:)];
3103 Package *npackage = nil;
3104 for (size_t offset = 0, count = [packages_ count]; offset != count; ++offset) {
3105 Package *package = [packages_ objectAtIndex:offset];
3106 if ([[package name] isEqualToString:package_])
3110 [self searchPackages];
3112 if (npackage != nil)
3113 [self resetPackage:npackage];
3114 else if (package_ != nil)
3120 - (void) setDelegate:(id)delegate {
3122 [view_ setDelegate:delegate];
3123 [super setDelegate:delegate];
3126 - (void) resetPackage:(Package *)package {
3127 [view_ setPackage:package];
3128 NSString *right = [package installed] == nil ? @"Install" : @"Uninstall";
3129 [navbar_ showButtonsWithLeftTitle:nil rightTitle:right];
3132 - (void) searchPackages {
3133 NSString *text([field_ text]);
3135 NSMutableArray *packages([NSMutableArray arrayWithCapacity:16]);
3137 for (size_t offset(0), count([packages_ count]); offset != count; ++offset) {
3138 Package *package = [packages_ objectAtIndex:offset];
3139 if ([package matches:text])
3140 [packages addObject:package];
3143 [table_ setPackages:packages];
3144 [[table_ table] scrollPointVisibleAtTopLeft:CGPointMake(0, 0) animated:NO];
3150 @interface Cydia : UIApplication <
3151 ConfirmationViewDelegate,
3152 ProgressViewDelegate,
3158 UITransitionView *transition_;
3159 UIButtonBar *buttonbar_;
3161 ConfirmationView *confirm_;
3163 Database *database_;
3164 ProgressView *progress_;
3167 UINavigationBar *navbar_;
3168 UIScroller *scroller_;
3169 UIWebView *webview_;
3171 UIProgressIndicator *indicator_;
3173 InstallView *install_;
3174 ChangesView *changes_;
3175 ManageView *manage_;
3176 SearchView *search_;
3181 UIKeyboard *keyboard_;
3185 - (void) reloadData:(BOOL)reset;
3196 - (void) progressViewIsComplete:(ProgressView *)progress;
3198 - (void) navigationBar:(UINavigationBar *)navbar buttonClicked:(int)button;
3199 - (void) alertSheet:(UIAlertSheet *)sheet buttonClicked:(int)button;
3200 - (void) buttonBarItemTapped:(id)sender;
3202 - (void) view:(UIView *)sender didSetFrame:(CGRect)frame oldFrame:(CGRect)old;
3204 - (void) webView:(WebView *)sender didReceiveTitle:(NSString *)title forFrame:(WebFrame *)frame;
3206 - (void) applicationWillSuspend;
3207 - (void) applicationDidFinishLaunching:(id)unused;
3210 @implementation Cydia
3213 NSMutableURLRequest *request = [NSMutableURLRequest
3215 cachePolicy:NSURLRequestReloadIgnoringCacheData
3216 timeoutInterval:30.0
3219 [request addValue:[NSString stringWithCString:Firmware_] forHTTPHeaderField:@"X-Firmware"];
3220 [request addValue:[NSString stringWithCString:Machine_] forHTTPHeaderField:@"X-Machine"];
3221 [request addValue:[NSString stringWithCString:SerialNumber_] forHTTPHeaderField:@"X-Serial-Number"];
3223 [webview_ loadRequest:request];
3226 - (void) reloadData:(BOOL)reset {
3227 [database_ reloadData];
3231 if (Packages_ == nil) {
3232 Packages_ = [[NSMutableDictionary alloc] initWithCapacity:count];
3233 [Metadata_ setObject:Packages_ forKey:@"Packages"];
3236 now_ = [NSDate date];
3238 NSMutableArray *packages = [NSMutableArray arrayWithCapacity:count];
3239 for (pkgCache::PkgIterator iterator = [database_ cache]->PkgBegin(); !iterator.end(); ++iterator)
3240 if (Package *package = [Package packageWithIterator:iterator database:database_])
3241 [packages addObject:package];
3243 [install_ setPackages:packages];
3244 [changes_ setPackages:packages];
3245 [manage_ setPackages:packages];
3246 [search_ setPackages:packages];
3248 if (size_t count = [changes_ count]) {
3249 NSString *badge([[NSNumber numberWithInt:count] stringValue]);
3250 [buttonbar_ setBadgeValue:badge forButton:3];
3251 if ([buttonbar_ respondsToSelector:@selector(setBadgeAnimated:forButton:)])
3252 [buttonbar_ setBadgeAnimated:YES forButton:3];
3253 [self setApplicationBadge:badge];
3255 [buttonbar_ setBadgeValue:nil forButton:3];
3256 if ([buttonbar_ respondsToSelector:@selector(setBadgeAnimated:forButton:)])
3257 [buttonbar_ setBadgeAnimated:NO forButton:3];
3258 [self removeApplicationBadge];
3261 _assert([Metadata_ writeToFile:@"/var/lib/cydia/metadata.plist" atomically:YES] == YES);
3264 - (void) setPrompt {
3265 [navbar_ setPrompt:[NSString stringWithFormat:@"Last Updated: %@", GetLastUpdate()]];
3269 pkgProblemResolver *resolver = [database_ resolver];
3271 resolver->InstallProtect();
3272 if (!resolver->Resolve(true))
3277 [database_ prepare];
3278 confirm_ = [[ConfirmationView alloc] initWithView:underlay_ database:database_ delegate:self];
3282 [database_ upgrade];
3287 [self reloadData:NO];
3293 [overlay_ removeFromSuperview];
3297 detachNewThreadSelector:@selector(perform)
3304 - (void) bootstrap_ {
3306 [database_ upgrade];
3307 [database_ prepare];
3308 [database_ perform];
3311 - (void) bootstrap {
3313 detachNewThreadSelector:@selector(bootstrap_)
3316 title:@"Bootstrap Install..."
3322 detachNewThreadSelector:@selector(update)
3325 title:@"Refreshing Sources..."
3329 - (void) progressViewIsComplete:(ProgressView *)progress {
3330 [self reloadData:YES];
3332 if (confirm_ != nil) {
3333 [underlay_ addSubview:overlay_];
3334 [confirm_ removeFromSuperview];
3340 - (void) navigationBar:(UINavigationBar *)navbar buttonClicked:(int)button {
3347 UIAlertSheet *sheet = [[[UIAlertSheet alloc]
3348 initWithTitle:@"About Cydia Packager"
3349 buttons:[NSArray arrayWithObjects:@"Close", nil]
3350 defaultButtonIndex:0
3356 @"Copyright (C) 2008\n"
3357 "Jay Freeman (saurik)\n"
3358 "saurik@saurik.com\n"
3359 "http://www.saurik.com/\n"
3362 "http://www.theokorigroup.com/\n"
3364 "College of Creative Studies,\n"
3365 "University of California,\n"
3367 "http://www.ccs.ucsb.edu/\n"
3370 "bad_, BHSPitMonkey, cash, Cobra,\n"
3371 "core, Corona, crashx, cromas,\n"
3372 "Darken, dtzWill, Erica, francis,\n"
3373 "Godores, jerry, Kingstone, lounger,\n"
3374 "mbranes, rockabilly, tman, Wbiggs"
3377 [sheet presentSheetFromButtonBar:buttonbar_];
3382 - (void) alertSheet:(UIAlertSheet *)sheet buttonClicked:(int)button {
3386 - (void) buttonBarItemTapped:(id)sender {
3388 unsigned tag = [sender tag];
3391 case 1: view = featured_; break;
3392 case 2: view = install_; break;
3393 case 3: view = changes_; break;
3394 case 4: view = manage_; break;
3395 case 5: view = search_; break;
3401 if ([view respondsToSelector:@selector(resetView:)])
3402 [(id) view resetView:(tag == tag_ ? NO : YES)];
3404 [transition_ transition:0 toView:view];
3407 - (void) view:(UIView *)sender didSetFrame:(CGRect)frame oldFrame:(CGRect)old {
3408 [scroller_ setContentSize:frame.size];
3409 [indicator_ stopAnimation];
3412 - (void) webView:(WebView *)sender didReceiveTitle:(NSString *)title forFrame:(WebFrame *)frame {
3413 [navbar_ setPrompt:title];
3416 - (void) webView:(WebView *)sender didStartProvisionalLoadForFrame:(WebFrame *)frame {
3417 [navbar_ setPrompt:@"Loading..."];
3418 [indicator_ startAnimation];
3421 - (void) applicationWillSuspend {
3423 system("launchctl stop com.apple.SpringBoard");
3425 [super applicationWillSuspend];
3428 - (void) applicationDidFinishLaunching:(id)unused {
3429 _assert(pkgInitConfig(*_config));
3430 _assert(pkgInitSystem(*_config, _system));
3436 CGRect screenrect = [UIHardware fullScreenApplicationContentRect];
3437 window_ = [[UIWindow alloc] initWithContentRect:screenrect];
3439 [window_ orderFront: self];
3440 [window_ makeKey: self];
3441 [window_ _setHidden: NO];
3443 progress_ = [[ProgressView alloc] initWithFrame:[window_ bounds] delegate:self];
3444 [window_ setContentView:progress_];
3446 underlay_ = [[UIView alloc] initWithFrame:[progress_ bounds]];
3447 [progress_ setContentView:underlay_];
3449 overlay_ = [[UIView alloc] initWithFrame:[underlay_ bounds]];
3452 [underlay_ addSubview:overlay_];
3454 transition_ = [[UITransitionView alloc] initWithFrame:CGRectMake(
3455 0, 0, screenrect.size.width, screenrect.size.height - 48
3458 [overlay_ addSubview:transition_];
3460 featured_ = [[UIView alloc] initWithFrame:[transition_ bounds]];
3462 CGSize navsize = [UINavigationBar defaultSizeWithPrompt];
3463 CGRect navrect = {{0, 0}, navsize};
3465 navbar_ = [[UINavigationBar alloc] initWithFrame:navrect];
3466 [featured_ addSubview:navbar_];
3468 [navbar_ setBarStyle:1];
3469 [navbar_ setDelegate:self];
3471 [navbar_ showButtonsWithLeftTitle:@"About" rightTitle:@"Reload"];
3473 UINavigationItem *navitem = [[[UINavigationItem alloc] initWithTitle:@"Featured"] autorelease];
3474 [navbar_ pushNavigationItem:navitem];
3476 struct CGRect subbounds = [featured_ bounds];
3477 subbounds.origin.y += navsize.height;
3478 subbounds.size.height -= navsize.height;
3480 UIImageView *pinstripe = [[[UIImageView alloc] initWithFrame:subbounds] autorelease];
3481 [pinstripe setImage:[UIImage applicationImageNamed:@"pinstripe.png"]];
3482 [featured_ addSubview:pinstripe];
3484 scroller_ = [[UIScroller alloc] initWithFrame:subbounds];
3485 [featured_ addSubview:scroller_];
3487 [scroller_ setScrollingEnabled:YES];
3488 [scroller_ setAdjustForContentSizeChange:YES];
3489 [scroller_ setClipsSubviews:YES];
3490 [scroller_ setAllowsRubberBanding:YES];
3491 [scroller_ setScrollDecelerationFactor:0.99];
3492 [scroller_ setDelegate:self];
3494 CGRect webrect = [scroller_ bounds];
3495 webrect.size.height = 0;
3497 webview_ = [[UIWebView alloc] initWithFrame:webrect];
3498 [scroller_ addSubview:webview_];
3500 [webview_ setTilingEnabled:YES];
3501 [webview_ setTileSize:CGSizeMake(screenrect.size.width, 500)];
3502 [webview_ setAutoresizes:YES];
3503 [webview_ setDelegate:self];
3505 CGSize indsize = [UIProgressIndicator defaultSizeForStyle:2];
3506 indicator_ = [[UIProgressIndicator alloc] initWithFrame:CGRectMake(87, 45, indsize.width, indsize.height)];
3507 [indicator_ setStyle:2];
3508 [featured_ addSubview:indicator_];
3510 NSArray *buttonitems = [NSArray arrayWithObjects:
3511 [NSDictionary dictionaryWithObjectsAndKeys:
3512 @"buttonBarItemTapped:", kUIButtonBarButtonAction,
3513 @"featured-up.png", kUIButtonBarButtonInfo,
3514 @"featured-dn.png", kUIButtonBarButtonSelectedInfo,
3515 [NSNumber numberWithInt:1], kUIButtonBarButtonTag,
3516 self, kUIButtonBarButtonTarget,
3517 @"Featured", kUIButtonBarButtonTitle,
3518 @"0", kUIButtonBarButtonType,
3521 [NSDictionary dictionaryWithObjectsAndKeys:
3522 @"buttonBarItemTapped:", kUIButtonBarButtonAction,
3523 @"install-up.png", kUIButtonBarButtonInfo,
3524 @"install-dn.png", kUIButtonBarButtonSelectedInfo,
3525 [NSNumber numberWithInt:2], kUIButtonBarButtonTag,
3526 self, kUIButtonBarButtonTarget,
3527 @"Install", kUIButtonBarButtonTitle,
3528 @"0", kUIButtonBarButtonType,
3531 [NSDictionary dictionaryWithObjectsAndKeys:
3532 @"buttonBarItemTapped:", kUIButtonBarButtonAction,
3533 @"changes-up.png", kUIButtonBarButtonInfo,
3534 @"changes-dn.png", kUIButtonBarButtonSelectedInfo,
3535 [NSNumber numberWithInt:3], kUIButtonBarButtonTag,
3536 self, kUIButtonBarButtonTarget,
3537 @"Changes", kUIButtonBarButtonTitle,
3538 @"0", kUIButtonBarButtonType,
3541 [NSDictionary dictionaryWithObjectsAndKeys:
3542 @"buttonBarItemTapped:", kUIButtonBarButtonAction,
3543 @"manage-up.png", kUIButtonBarButtonInfo,
3544 @"manage-dn.png", kUIButtonBarButtonSelectedInfo,
3545 [NSNumber numberWithInt:4], kUIButtonBarButtonTag,
3546 self, kUIButtonBarButtonTarget,
3547 @"Uninstall", kUIButtonBarButtonTitle,
3548 @"0", kUIButtonBarButtonType,
3551 [NSDictionary dictionaryWithObjectsAndKeys:
3552 @"buttonBarItemTapped:", kUIButtonBarButtonAction,
3553 @"search-up.png", kUIButtonBarButtonInfo,
3554 @"search-dn.png", kUIButtonBarButtonSelectedInfo,
3555 [NSNumber numberWithInt:5], kUIButtonBarButtonTag,
3556 self, kUIButtonBarButtonTarget,
3557 @"Search", kUIButtonBarButtonTitle,
3558 @"0", kUIButtonBarButtonType,
3562 buttonbar_ = [[UIButtonBar alloc]
3564 withFrame:CGRectMake(
3565 0, screenrect.size.height - 48,
3566 screenrect.size.width, 48
3568 withItemList:buttonitems
3571 [buttonbar_ setDelegate:self];
3572 [buttonbar_ setBarStyle:1];
3573 [buttonbar_ setButtonBarTrackingMode:2];
3575 int buttons[5] = {1, 2, 3, 4, 5};
3576 [buttonbar_ registerButtonGroup:0 withButtons:buttons withCount:5];
3577 [buttonbar_ showButtonGroup:0 withDuration:0];
3579 for (int i = 0; i != 5; ++i)
3580 [[buttonbar_ viewWithTag:(i + 1)] setFrame:CGRectMake(
3581 i * 64 + 2, 1, 60, 48
3584 [buttonbar_ showSelectionForButton:1];
3585 [transition_ transition:0 toView:featured_];
3587 [overlay_ addSubview:buttonbar_];
3589 [UIKeyboard initImplementationNow];
3591 CGRect edtrect = [overlay_ bounds];
3592 edtrect.origin.y += navsize.height;
3593 edtrect.size.height -= navsize.height;
3595 CGSize keysize = [UIKeyboard defaultSize];
3596 CGRect keyrect = {{0, [overlay_ bounds].size.height - keysize.height}, keysize};
3597 keyboard_ = [[UIKeyboard alloc] initWithFrame:keyrect];
3599 database_ = [[Database alloc] init];
3600 [database_ setDelegate:progress_];
3602 install_ = [[InstallView alloc] initWithFrame:[transition_ bounds]];
3603 [install_ setDelegate:self];
3605 changes_ = [[ChangesView alloc] initWithFrame:[transition_ bounds]];
3606 [changes_ setDelegate:self];
3608 manage_ = [[ManageView alloc] initWithFrame:[transition_ bounds]];
3609 [manage_ setDelegate:self];
3611 search_ = [[SearchView alloc] initWithFrame:[transition_ bounds]];
3612 [search_ setDelegate:self];
3614 [self reloadData:NO];
3616 Package *package([database_ packageWithName:@"cydia"]);
3617 NSString *application = package == nil ? @"Cydia" : [NSString
3618 stringWithFormat:@"Cydia/%@",
3622 WebView *webview = [webview_ webView];
3623 [webview setApplicationNameForUserAgent:application];
3624 [webview setFrameLoadDelegate:self];
3626 url_ = [NSURL URLWithString:@"http://cydia.saurik.com/"];
3629 [progress_ resetView];
3635 - (void) showKeyboard:(BOOL)show {
3637 [overlay_ addSubview:keyboard_];
3639 [keyboard_ removeFromSuperview];
3644 void AddPreferences(NSString *plist) {
3645 NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init];
3647 NSMutableDictionary *settings = [[[NSMutableDictionary alloc] initWithContentsOfFile:plist] autorelease];
3648 _assert(settings != NULL);
3649 NSMutableArray *items = [settings objectForKey:@"items"];
3653 for (size_t i(0); i != [items count]; ++i) {
3654 NSMutableDictionary *item([items objectAtIndex:i]);
3655 NSString *label = [item objectForKey:@"label"];
3656 if (label != nil && [label isEqualToString:@"Cydia"]) {
3663 for (size_t i(0); i != [items count]; ++i) {
3664 NSDictionary *item([items objectAtIndex:i]);
3665 NSString *label = [item objectForKey:@"label"];
3666 if (label != nil && [label isEqualToString:@"General"]) {
3667 [items insertObject:[NSDictionary dictionaryWithObjectsAndKeys:
3668 @"CydiaSettings", @"bundle",
3669 @"PSLinkCell", @"cell",
3670 [NSNumber numberWithBool:YES], @"hasIcon",
3671 [NSNumber numberWithBool:YES], @"isController",
3673 nil] atIndex:(i + 1)];
3679 _assert([settings writeToFile:plist atomically:YES] == YES);
3686 id Alloc_(id self, SEL selector) {
3687 id object = alloc_(self, selector);
3688 fprintf(stderr, "[%s]A-%p\n", self->isa->name, object);
3692 int main(int argc, char *argv[]) {
3694 memset(nl, 0, sizeof(nl));
3695 nl[0].n_un.n_name = "_useMDNSResponder";
3696 nlist("/usr/lib/libc.dylib", nl);
3697 if (nl[0].n_type != N_UNDF)
3698 *(int *) nl[0].n_value = 0;
3700 bootstrap_ = argc > 1 && strcmp(argv[1], "--bootstrap") == 0;
3705 /*Method alloc = class_getClassMethod([NSObject class], @selector(alloc));
3706 alloc_ = alloc->method_imp;
3707 alloc->method_imp = (IMP) &Alloc_;*/
3709 NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init];
3711 if (NSDictionary *sysver = [NSDictionary dictionaryWithContentsOfFile:@"/System/Library/CoreServices/SystemVersion.plist"]) {
3712 if (NSString *prover = [sysver valueForKey:@"ProductVersion"]) {
3713 Firmware_ = strdup([prover cString]);
3714 NSArray *versions = [prover componentsSeparatedByString:@"."];
3715 int count = [versions count];
3716 Major_ = count > 0 ? [[versions objectAtIndex:0] intValue] : 0;
3717 Minor_ = count > 1 ? [[versions objectAtIndex:1] intValue] : 0;
3718 BugFix_ = count > 2 ? [[versions objectAtIndex:2] intValue] : 0;
3723 sysctlbyname("hw.machine", NULL, &size, NULL, 0);
3724 char *machine = new char[size];
3725 sysctlbyname("hw.machine", machine, &size, NULL, 0);
3728 if (CFMutableDictionaryRef dict = IOServiceMatching("IOPlatformExpertDevice"))
3729 if (io_service_t service = IOServiceGetMatchingService(kIOMasterPortDefault, dict)) {
3730 if (CFTypeRef serial = IORegistryEntryCreateCFProperty(service, CFSTR(kIOPlatformSerialNumberKey), kCFAllocatorDefault, 0)) {
3731 SerialNumber_ = strdup(CFStringGetCStringPtr((CFStringRef) serial, CFStringGetSystemEncoding()));
3735 IOObjectRelease(service);
3738 /*AddPreferences(@"/Applications/Preferences.app/Settings-iPhone.plist");
3739 AddPreferences(@"/Applications/Preferences.app/Settings-iPod.plist");*/
3741 if ((Metadata_ = [[NSMutableDictionary alloc] initWithContentsOfFile:@"/var/lib/cydia/metadata.plist"]) == NULL)
3742 Metadata_ = [[NSMutableDictionary alloc] initWithCapacity:2];
3744 Packages_ = [Metadata_ objectForKey:@"Packages"];
3746 setenv("CYDIA", "", _not(int));
3747 if (access("/User", F_OK) != 0)
3748 system("/usr/libexec/cydia/firmware.sh");
3749 system("dpkg --configure -a");
3751 UIApplicationMain(argc, argv, [Cydia class]);