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;
60 #define UITable UITableView
63 /* Reset View (UIView) {{{ */
64 @interface UIView (CYResetView)
65 - (void) resetViewAnimated:(BOOL)animated;
68 @implementation UIView (CYResetView)
70 - (void) resetViewAnimated:(BOOL)animated {
71 fprintf(stderr, "%s\n", self->isa->name);
77 /* Reset View (UITable) {{{ */
78 @interface UITable (CYResetView)
79 - (void) resetViewAnimated:(BOOL)animated;
82 @implementation UITable (CYResetView)
84 - (void) resetViewAnimated:(BOOL)animated {
85 [self selectRow:-1 byExtendingSelection:NO withFade:animated];
90 /* Reset View (UISectionList) {{{ */
91 @interface UISectionList (CYResetView)
92 - (void) resetViewAnimated:(BOOL)animated;
95 @implementation UISectionList (CYResetView)
97 - (void) resetViewAnimated:(BOOL)animated {
98 [[self table] resetViewAnimated:animated];
104 /* Perl-Compatible RegEx {{{ */
114 Pcre(const char *regex) :
119 code_ = pcre_compile(regex, 0, &error, &offset, NULL);
122 fprintf(stderr, "%d:%s\n", offset, error);
126 pcre_fullinfo(code_, study_, PCRE_INFO_CAPTURECOUNT, &capture_);
127 matches_ = new int[(capture_ + 1) * 3];
135 NSString *operator [](size_t match) {
137 stringWithCString:(data_ + matches_[match * 2])
138 length:(matches_[match * 2 + 1] - matches_[match * 2])
142 bool operator ()(const char *data, size_t size) {
144 return pcre_exec(code_, study_, data, size, 0, 0, matches_, (capture_ + 1) * 3) >= 0;
148 /* CoreGraphicsServices Primitives {{{ */
154 CGColor(CGColorSpaceRef space, float red, float green, float blue, float alpha) {
155 float color[] = {red, green, blue, alpha};
156 color_ = CGColorCreate(space, color);
160 CGColorRelease(color_);
163 operator CGColorRef() {
174 /* XXX: no GSFontRelease()? */
180 static const int PulseInterval_ = 50000;
182 const char *Firmware_ = NULL;
183 const char *Machine_ = NULL;
184 const char *SerialNumber_ = NULL;
190 #define FW_LEAST(major, minor, bugfix) \
191 (major < Major_ || major == Major_ && \
192 (minor < Minor_ || minor == Minor_ && \
195 bool bootstrap_ = false;
197 static NSMutableDictionary *Metadata_;
198 static NSMutableDictionary *Packages_;
201 NSString *GetLastUpdate() {
202 NSDate *update = [Metadata_ objectForKey:@"LastUpdate"];
205 return @"Never or Unknown";
207 CFLocaleRef locale = CFLocaleCopyCurrent();
208 CFDateFormatterRef formatter = CFDateFormatterCreate(NULL, locale, kCFDateFormatterMediumStyle, kCFDateFormatterMediumStyle);
209 CFStringRef formatted = CFDateFormatterCreateStringWithDate(NULL, formatter, (CFDateRef) update);
211 CFRelease(formatter);
214 return [(NSString *) formatted autorelease];
217 @protocol ProgressDelegate
218 - (void) setError:(NSString *)error;
219 - (void) setTitle:(NSString *)title;
220 - (void) setPercent:(float)percent;
221 - (void) addOutput:(NSString *)output;
224 NSString *SizeString(double size) {
226 while (size > 1024) {
231 static const char *powers_[] = {"B", "kB", "MB", "GB"};
233 return [NSString stringWithFormat:@"%.1f%s", size, powers_[power]];
236 static const float TextViewOffset_ = 22;
238 UITextView *GetTextView(NSString *value, float left, bool html) {
239 UITextView *text([[[UITextView alloc] initWithFrame:CGRectMake(left, 3, 310 - left, 1000)] autorelease]);
240 [text setEditable:NO];
241 [text setTextSize:16];
243 [text setHTML:value];
245 [text setText:value];
246 [text setEnabled:NO];
248 CGColorSpaceRef space = CGColorSpaceCreateDeviceRGB();
249 CGColor clear(space, 0, 0, 0, 0);
250 [text setBackgroundColor:clear];
251 CGColorSpaceRelease(space);
253 CGRect frame = [text frame];
254 [text setFrame:frame];
255 CGRect rect = [text visibleTextRect];
256 frame.size.height = rect.size.height;
257 [text setFrame:frame];
262 /* Status Delegation {{{ */
264 public pkgAcquireStatus
275 void setDelegate(id delegate) {
276 delegate_ = delegate;
279 virtual bool MediaChange(std::string media, std::string drive) {
283 virtual void IMSHit(pkgAcquire::ItemDesc &item) {
286 virtual void Fetch(pkgAcquire::ItemDesc &item) {
287 [delegate_ setTitle:[NSString stringWithCString:("Downloading " + item.ShortDesc).c_str()]];
290 virtual void Done(pkgAcquire::ItemDesc &item) {
293 virtual void Fail(pkgAcquire::ItemDesc &item) {
295 item.Owner->Status == pkgAcquire::Item::StatIdle ||
296 item.Owner->Status == pkgAcquire::Item::StatDone
300 [delegate_ setError:[NSString stringWithCString:item.Owner->ErrorText.c_str()]];
303 virtual bool Pulse(pkgAcquire *Owner) {
304 bool value = pkgAcquireStatus::Pulse(Owner);
307 double(CurrentBytes + CurrentItems) /
308 double(TotalBytes + TotalItems)
311 [delegate_ setPercent:percent];
315 virtual void Start() {
318 virtual void Stop() {
322 /* Progress Delegation {{{ */
330 virtual void Update() {
331 [delegate_ setTitle:[NSString stringWithCString:Op.c_str()]];
332 [delegate_ setPercent:(Percent / 100)];
341 void setDelegate(id delegate) {
342 delegate_ = delegate;
345 virtual void Done() {
346 [delegate_ setPercent:1];
351 /* External Constants {{{ */
352 extern NSString *kUIButtonBarButtonAction;
353 extern NSString *kUIButtonBarButtonInfo;
354 extern NSString *kUIButtonBarButtonInfoOffset;
355 extern NSString *kUIButtonBarButtonSelectedInfo;
356 extern NSString *kUIButtonBarButtonStyle;
357 extern NSString *kUIButtonBarButtonTag;
358 extern NSString *kUIButtonBarButtonTarget;
359 extern NSString *kUIButtonBarButtonTitle;
360 extern NSString *kUIButtonBarButtonTitleVerticalHeight;
361 extern NSString *kUIButtonBarButtonTitleWidth;
362 extern NSString *kUIButtonBarButtonType;
364 /* Mime Addresses {{{ */
365 Pcre email_r("^\"?(.*)\"? <([^>]*)>$");
367 @interface Address : NSObject {
375 - (NSString *) email;
377 + (Address *) addressWithString:(NSString *)string;
378 - (Address *) initWithString:(NSString *)string;
381 @implementation Address
390 - (NSString *) name {
394 - (NSString *) email {
398 + (Address *) addressWithString:(NSString *)string {
399 return [[[Address alloc] initWithString:string] autorelease];
402 - (Address *) initWithString:(NSString *)string {
403 if ((self = [super init]) != nil) {
404 const char *data = [string UTF8String];
405 size_t size = [string length];
407 if (email_r(data, size)) {
408 name_ = [email_r[1] retain];
409 email_ = [email_r[2] retain];
411 name_ = [[NSString stringWithCString:data length:size] retain];
420 /* Right Alignment {{{ */
421 @interface UIRightTextLabel : UITextLabel {
422 float _savedRightEdgeX;
423 BOOL _sizedtofit_flag;
426 - (void) setFrame:(CGRect)frame;
427 - (void) setText:(NSString *)text;
428 - (void) realignText;
431 @implementation UIRightTextLabel
433 - (void) setFrame:(CGRect)frame {
434 [super setFrame:frame];
435 if (_sizedtofit_flag == NO) {
436 _savedRightEdgeX = frame.origin.x;
441 - (void) setText:(NSString *)text {
442 [super setText:text];
446 - (void) realignText {
447 CGRect oldFrame = [self frame];
449 _sizedtofit_flag = YES;
450 [self sizeToFit]; // shrink down size so I can right align it
452 CGRect newFrame = [self frame];
454 oldFrame.origin.x = _savedRightEdgeX - newFrame.size.width;
455 oldFrame.size.width = newFrame.size.width;
456 [super setFrame:oldFrame];
457 _sizedtofit_flag = NO;
462 /* Linear Algebra {{{ */
463 inline float interpolate(float begin, float end, float fraction) {
464 return (end - begin) * fraction + begin;
471 /* Database Interface {{{ */
472 @interface Database : NSObject {
474 pkgRecords *records_;
475 pkgProblemResolver *resolver_;
476 pkgAcquire *fetcher_;
478 SPtr<pkgPackageManager> manager_;
479 pkgSourceList *list_;
481 NSMutableDictionary *sources_;
482 NSMutableArray *packages_;
492 - (void) _readStatus:(NSNumber *)fd;
493 - (void) _readOutput:(NSNumber *)fd;
495 - (Package *) packageWithName:(NSString *)name;
498 - (pkgCacheFile &) cache;
499 - (pkgRecords *) records;
500 - (pkgProblemResolver *) resolver;
501 - (pkgAcquire &) fetcher;
502 - (NSArray *) packages;
510 - (void) setDelegate:(id)delegate;
511 - (Source *) getSource:(const pkgCache::PkgFileIterator &)file;
516 @interface ResetView : UIView {
517 UIPushButton *configure_;
518 UIPushButton *reload_;
519 NSMutableArray *views_;
520 UINavigationBar *navbar_;
521 UITransitionView *transition_;
528 - (void) navigationBar:(UINavigationBar *)navbar poppedItem:(UINavigationItem *)item;
529 - (void) alertSheet:(UIAlertSheet *)sheet buttonClicked:(int)button;
531 - (id) initWithFrame:(CGRect)frame;
532 - (void) setDelegate:(id)delegate;
534 - (void) configurePushed;
535 - (void) reloadPushed;
537 - (void) pushView:(UIView *)view withTitle:(NSString *)title backButtonTitle:(NSString *)back rightButton:(NSString *)right;
538 - (void) popViews:(unsigned)views;
539 - (void) resetView:(BOOL)clear;
544 @implementation ResetView
547 [configure_ release];
549 [transition_ release];
555 - (void) navigationBar:(UINavigationBar *)navbar poppedItem:(UINavigationItem *)item {
556 [views_ removeLastObject];
557 UIView *view([views_ lastObject]);
558 [view resetViewAnimated:!resetting_];
561 [transition_ transition:2 toView:view];
566 - (void) alertSheet:(UIAlertSheet *)sheet buttonClicked:(int)button {
570 - (id) initWithFrame:(CGRect)frame {
571 if ((self = [super initWithFrame:frame]) != nil) {
572 views_ = [[NSMutableArray arrayWithCapacity:4] retain];
574 struct CGRect bounds = [self bounds];
575 CGSize navsize = [UINavigationBar defaultSizeWithPrompt];
576 CGRect navrect = {{0, 0}, navsize};
578 navbar_ = [[UINavigationBar alloc] initWithFrame:navrect];
579 [self addSubview:navbar_];
581 [navbar_ setBarStyle:1];
582 [navbar_ setDelegate:self];
584 transition_ = [[UITransitionView alloc] initWithFrame:CGRectMake(
585 bounds.origin.x, bounds.origin.y + navsize.height, bounds.size.width, bounds.size.height - navsize.height
588 //configure_ = [[UIPushButton alloc] initWithFrame:CGRectMake(15, 9, 17, 18)];
589 configure_ = [[UIPushButton alloc] initWithFrame:CGRectMake(10, 9, 17, 18)];
590 [configure_ setShowPressFeedback:YES];
591 [configure_ setImage:[UIImage applicationImageNamed:@"configure.png"]];
592 [configure_ addTarget:self action:@selector(configurePushed) forEvents:1];
594 //reload_ = [[UIPushButton alloc] initWithFrame:CGRectMake(288, 5, 18, 22)];
595 reload_ = [[UIPushButton alloc] initWithFrame:CGRectMake(293, 5, 18, 22)];
596 [reload_ setShowPressFeedback:YES];
597 [reload_ setImage:[UIImage applicationImageNamed:@"reload.png"]];
598 [reload_ addTarget:self action:@selector(reloadPushed) forEvents:1];
600 [navbar_ addSubview:configure_];
601 [navbar_ addSubview:reload_];
603 [self addSubview:transition_];
607 - (void) setDelegate:(id)delegate {
608 delegate_ = delegate;
611 - (void) configurePushed {
612 UIAlertSheet *sheet = [[[UIAlertSheet alloc]
613 initWithTitle:@"Sources Unimplemented"
614 buttons:[NSArray arrayWithObjects:@"Okay", nil]
620 [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'."];
621 [sheet popupAlertAnimated:YES];
624 - (void) reloadPushed {
628 - (void) pushView:(UIView *)view withTitle:(NSString *)title backButtonTitle:(NSString *)back rightButton:(NSString *)right {
629 UINavigationItem *navitem = [[[UINavigationItem alloc] initWithTitle:title] autorelease];
630 [navbar_ pushNavigationItem:navitem];
631 [navitem setBackButtonTitle:back];
633 [navbar_ showButtonsWithLeftTitle:nil rightTitle:right];
635 [transition_ transition:([views_ count] == 0 ? 0 : 1) toView:view];
636 [views_ addObject:view];
639 - (void) popViews:(unsigned)views {
641 for (unsigned i(0); i != views; ++i)
642 [navbar_ popNavigationItem];
646 [transition_ transition:2 toView:[views_ lastObject]];
649 - (void) resetView:(BOOL)clear {
652 if ([views_ count] > 1) {
653 [navbar_ disableAnimation];
654 while ([views_ count] != (clear ? 1 : 2))
655 [navbar_ popNavigationItem];
656 [navbar_ enableAnimation];
658 [navbar_ popNavigationItem];
664 [transition_ transition:(clear ? 0 : 2) toView:[views_ lastObject]];
667 - (void) _resetView {
668 [navbar_ showButtonsWithLeftTitle:nil rightTitle:nil];
672 [navbar_ setPrompt:[NSString stringWithFormat:@"Last Updated: %@", GetLastUpdate()]];
677 /* Confirmation View {{{ */
678 void AddTextView(NSMutableDictionary *fields, NSMutableArray *packages, NSString *key) {
679 if ([packages count] == 0)
682 UITextView *text = GetTextView([packages count] == 0 ? @"n/a" : [packages componentsJoinedByString:@", "], 110, false);
683 [fields setObject:text forKey:key];
685 CGColorSpaceRef space = CGColorSpaceCreateDeviceRGB();
686 CGColor blue(space, 0, 0, 0.4, 1);
687 [text setTextColor:blue];
688 CGColorSpaceRelease(space);
691 @protocol ConfirmationViewDelegate
696 @interface ConfirmationView : UIView {
699 UITransitionView *transition_;
701 UINavigationBar *navbar_;
702 UIPreferencesTable *table_;
703 NSMutableDictionary *fields_;
704 UIAlertSheet *essential_;
710 - (void) transitionViewDidComplete:(UITransitionView*)view fromView:(UIView*)from toView:(UIView*)to;
711 - (void) navigationBar:(UINavigationBar *)navbar buttonClicked:(int)button;
712 - (void) alertSheet:(UIAlertSheet *)sheet buttonClicked:(int)button;
714 - (int) numberOfGroupsInPreferencesTable:(UIPreferencesTable *)table;
715 - (NSString *) preferencesTable:(UIPreferencesTable *)table titleForGroup:(int)group;
716 - (float) preferencesTable:(UIPreferencesTable *)table heightForRow:(int)row inGroup:(int)group withProposedHeight:(float)proposed;
717 - (int) preferencesTable:(UIPreferencesTable *)table numberOfRowsInGroup:(int)group;
718 - (UIPreferencesTableCell *) preferencesTable:(UIPreferencesTable *)table cellForRow:(int)row inGroup:(int)group;
720 - (id) initWithView:(UIView *)view database:(Database *)database delegate:(id)delegate;
724 @implementation ConfirmationView
727 [transition_ release];
732 if (essential_ != nil)
733 [essential_ release];
738 [transition_ transition:7 toView:nil];
742 - (void) transitionViewDidComplete:(UITransitionView*)view fromView:(UIView*)from toView:(UIView*)to {
743 if (from != nil && to == nil)
744 [self removeFromSuperview];
747 - (void) navigationBar:(UINavigationBar *)navbar buttonClicked:(int)button {
750 if (essential_ != nil)
751 [essential_ popupAlertAnimated:YES];
762 - (void) alertSheet:(UIAlertSheet *)sheet buttonClicked:(int)button {
763 [essential_ dismiss];
767 - (int) numberOfGroupsInPreferencesTable:(UIPreferencesTable *)table {
771 - (NSString *) preferencesTable:(UIPreferencesTable *)table titleForGroup:(int)group {
773 case 0: return @"Statistics";
774 case 1: return @"Modifications";
776 default: _assert(false);
780 - (int) preferencesTable:(UIPreferencesTable *)table numberOfRowsInGroup:(int)group {
783 case 1: return [fields_ count];
785 default: _assert(false);
789 - (float) preferencesTable:(UIPreferencesTable *)table heightForRow:(int)row inGroup:(int)group withProposedHeight:(float)proposed {
790 if (group != 1 || row == -1)
793 _assert(size_t(row) < [fields_ count]);
794 return [[[fields_ allValues] objectAtIndex:row] visibleTextRect].size.height + TextViewOffset_;
798 - (UIPreferencesTableCell *) preferencesTable:(UIPreferencesTable *)table cellForRow:(int)row inGroup:(int)group {
799 UIPreferencesTableCell *cell = [[[UIPreferencesTableCell alloc] init] autorelease];
800 [cell setShowSelection:NO];
803 case 0: switch (row) {
805 [cell setTitle:@"Downloading"];
806 [cell setValue:SizeString([database_ fetcher].FetchNeeded())];
810 [cell setTitle:@"Resuming At"];
811 [cell setValue:SizeString([database_ fetcher].PartialPresent())];
815 double size([database_ cache]->UsrSize());
818 [cell setTitle:@"Disk Freeing"];
819 [cell setValue:SizeString(-size)];
821 [cell setTitle:@"Disk Using"];
822 [cell setValue:SizeString(size)];
826 default: _assert(false);
830 _assert(size_t(row) < [fields_ count]);
831 [cell setTitle:[[fields_ allKeys] objectAtIndex:row]];
832 [cell addSubview:[[fields_ allValues] objectAtIndex:row]];
835 default: _assert(false);
841 - (id) initWithView:(UIView *)view database:(Database *)database delegate:(id)delegate {
842 if ((self = [super initWithFrame:[view bounds]]) != nil) {
843 database_ = database;
844 delegate_ = delegate;
846 transition_ = [[UITransitionView alloc] initWithFrame:[self bounds]];
847 [self addSubview:transition_];
849 overlay_ = [[UIView alloc] initWithFrame:[transition_ bounds]];
851 CGSize navsize = [UINavigationBar defaultSize];
852 CGRect navrect = {{0, 0}, navsize};
853 CGRect bounds = [overlay_ bounds];
855 navbar_ = [[UINavigationBar alloc] initWithFrame:navrect];
856 [navbar_ setBarStyle:1];
857 [navbar_ setDelegate:self];
859 UINavigationItem *navitem = [[[UINavigationItem alloc] initWithTitle:@"Confirm"] autorelease];
860 [navbar_ pushNavigationItem:navitem];
861 [navbar_ showButtonsWithLeftTitle:@"Cancel" rightTitle:@"Confirm"];
863 fields_ = [[NSMutableDictionary dictionaryWithCapacity:16] retain];
865 NSMutableArray *installing = [NSMutableArray arrayWithCapacity:16];
866 NSMutableArray *upgrading = [NSMutableArray arrayWithCapacity:16];
867 NSMutableArray *removing = [NSMutableArray arrayWithCapacity:16];
873 pkgCacheFile &cache([database_ cache]);
874 for (pkgCache::PkgIterator iterator = cache->PkgBegin(); !iterator.end(); ++iterator) {
875 NSString *name([NSString stringWithCString:iterator.Name()]);
876 bool essential((iterator->Flags & pkgCache::Flag::Essential) != 0);
878 if (cache[iterator].NewInstall()) {
881 [installing addObject:name];
882 } else if (cache[iterator].Upgrade()) {
885 [upgrading addObject:name];
886 } else if (cache[iterator].Delete()) {
889 [removing addObject:name];
896 essential_ = [[UIAlertSheet alloc]
897 initWithTitle:@"Unable to Comply"
898 buttons:[NSArray arrayWithObjects:@"Okay", nil]
904 [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."];
907 AddTextView(fields_, installing, @"Installing");
908 AddTextView(fields_, upgrading, @"Upgrading");
909 AddTextView(fields_, removing, @"Removing");
911 table_ = [[UIPreferencesTable alloc] initWithFrame:CGRectMake(
912 0, navsize.height, bounds.size.width, bounds.size.height - navsize.height
915 [table_ setReusesTableCells:YES];
916 [table_ setDataSource:self];
919 [overlay_ addSubview:navbar_];
920 [overlay_ addSubview:table_];
922 [view addSubview:self];
924 [transition_ setDelegate:self];
926 UIView *blank = [[[UIView alloc] initWithFrame:[transition_ bounds]] autorelease];
927 [transition_ transition:0 toView:blank];
928 [transition_ transition:3 toView:overlay_];
935 /* Source Class {{{ */
936 @interface Source : NSObject {
937 NSString *description_;
942 NSString *distribution_;
946 NSString *defaultIcon_;
953 - (Source *) initWithMetaIndex:(metaIndex *)index;
958 - (NSString *) distribution;
961 - (NSString *) description;
962 - (NSString *) label;
963 - (NSString *) origin;
964 - (NSString *) version;
966 - (NSString *) defaultIcon;
969 @implementation Source
973 [distribution_ release];
976 if (description_ != nil)
977 [description_ release];
988 - (Source *) initWithMetaIndex:(metaIndex *)index {
989 if ((self = [super init]) != nil) {
990 trusted_ = index->IsTrusted();
992 uri_ = [[NSString stringWithCString:index->GetURI().c_str()] retain];
993 distribution_ = [[NSString stringWithCString:index->GetDist().c_str()] retain];
994 type_ = [[NSString stringWithCString:index->GetType()] retain];
1000 debReleaseIndex *dindex(dynamic_cast<debReleaseIndex *>(index));
1001 if (dindex != NULL) {
1002 std::ifstream release(dindex->MetaIndexFile("Release").c_str());
1004 while (std::getline(release, line)) {
1005 std::string::size_type colon(line.find(':'));
1006 if (colon == std::string::npos)
1009 std::string name(line.substr(0, colon));
1010 std::string value(line.substr(colon + 1));
1011 while (!value.empty() && value[0] == ' ')
1012 value = value.substr(1);
1014 if (name == "Default-Icon")
1015 defaultIcon_ = [[NSString stringWithCString:value.c_str()] retain];
1016 else if (name == "Description")
1017 description_ = [[NSString stringWithCString:value.c_str()] retain];
1018 else if (name == "Label")
1019 label_ = [[NSString stringWithCString:value.c_str()] retain];
1020 else if (name == "Origin")
1021 origin_ = [[NSString stringWithCString:value.c_str()] retain];
1022 else if (name == "Version")
1023 version_ = [[NSString stringWithCString:value.c_str()] retain];
1033 - (NSString *) uri {
1037 - (NSString *) distribution {
1038 return distribution_;
1041 - (NSString *) type {
1045 - (NSString *) description {
1046 return description_;
1049 - (NSString *) label {
1053 - (NSString *) origin {
1057 - (NSString *) version {
1061 - (NSString *) defaultIcon {
1062 return defaultIcon_;
1067 /* Package Class {{{ */
1068 NSString *Scour(const char *field, const char *begin, const char *end) {
1069 size_t i(0), l(strlen(field));
1072 const char *name = begin + i;
1073 const char *colon = name + l;
1074 const char *value = colon + 1;
1079 memcmp(name, field, l) == 0
1081 while (value != end && value[0] == ' ')
1083 const char *line = std::find(value, end, '\n');
1084 while (line != value && line[-1] == ' ')
1086 return [NSString stringWithCString:value length:(line - value)];
1088 begin = std::find(begin, end, '\n');
1096 @interface Package : NSObject {
1097 pkgCache::PkgIterator iterator_;
1098 Database *database_;
1099 pkgCache::VerIterator version_;
1100 pkgCache::VerFileIterator file_;
1104 NSString *installed_;
1115 - (Package *) initWithIterator:(pkgCache::PkgIterator)iterator database:(Database *)database version:(pkgCache::VerIterator)version file:(pkgCache::VerFileIterator)file;
1116 + (Package *) packageWithIterator:(pkgCache::PkgIterator)iterator database:(Database *)database;
1118 - (NSString *) section;
1119 - (Address *) maintainer;
1121 - (NSString *) description;
1122 - (NSString *) index;
1126 - (NSString *) latest;
1127 - (NSString *) installed;
1128 - (BOOL) upgradable;
1133 - (NSString *) name;
1134 - (NSString *) tagline;
1135 - (NSString *) icon;
1136 - (NSString *) website;
1138 - (Source *) source;
1140 - (BOOL) matches:(NSString *)text;
1142 - (NSComparisonResult) compareByName:(Package *)package;
1143 - (NSComparisonResult) compareBySectionAndName:(Package *)package;
1144 - (NSComparisonResult) compareForChanges:(Package *)package;
1150 @implementation Package
1154 if (installed_ != nil)
1155 [installed_ release];
1163 if (website_ != nil)
1172 - (Package *) initWithIterator:(pkgCache::PkgIterator)iterator database:(Database *)database version:(pkgCache::VerIterator)version file:(pkgCache::VerFileIterator)file {
1173 if ((self = [super init]) != nil) {
1174 iterator_ = iterator;
1175 database_ = database;
1180 pkgRecords::Parser *parser = &[database_ records]->Lookup(file_);
1182 const char *begin, *end;
1183 parser->GetRec(begin, end);
1185 latest_ = [[NSString stringWithCString:version_.VerStr()] retain];
1186 installed_ = iterator_.CurrentVer().end() ? nil : [[NSString stringWithCString:iterator_.CurrentVer().VerStr()] retain];
1188 id_ = [[[NSString stringWithCString:iterator_.Name()] lowercaseString] retain];
1189 name_ = Scour("Name", begin, end);
1191 name_ = [name_ retain];
1192 tagline_ = [[NSString stringWithCString:parser->ShortDesc().c_str()] retain];
1193 icon_ = Scour("Icon", begin, end);
1195 icon_ = [icon_ retain];
1196 website_ = Scour("Website", begin, end);
1197 if (website_ != nil)
1198 website_ = [website_ retain];
1200 source_ = [[database_ getSource:file_.File()] retain];
1202 NSMutableDictionary *metadata = [Packages_ objectForKey:id_];
1203 if (metadata == nil) {
1204 metadata = [NSMutableDictionary dictionaryWithObjectsAndKeys:
1208 [Packages_ setObject:metadata forKey:id_];
1213 + (Package *) packageWithIterator:(pkgCache::PkgIterator)iterator database:(Database *)database {
1214 for (pkgCache::VerIterator version = iterator.VersionList(); !version.end(); ++version)
1215 for (pkgCache::VerFileIterator file = version.FileList(); !file.end(); ++file)
1216 return [[[Package alloc]
1217 initWithIterator:iterator
1225 - (NSString *) section {
1226 const char *section = iterator_.Section();
1227 return section == NULL ? nil : [[NSString stringWithCString:section] stringByReplacingCharacter:'_' withCharacter:' '];
1230 - (Address *) maintainer {
1231 pkgRecords::Parser *parser = &[database_ records]->Lookup(file_);
1232 return [Address addressWithString:[NSString stringWithCString:parser->Maintainer().c_str()]];
1236 return version_->InstalledSize;
1239 - (NSString *) description {
1240 pkgRecords::Parser *parser = &[database_ records]->Lookup(file_);
1241 NSString *description([NSString stringWithCString:parser->LongDesc().c_str()]);
1243 NSArray *lines = [description componentsSeparatedByString:@"\n"];
1244 NSMutableArray *trimmed = [NSMutableArray arrayWithCapacity:([lines count] - 1)];
1245 if ([lines count] < 2)
1248 NSCharacterSet *whitespace = [NSCharacterSet whitespaceCharacterSet];
1249 for (size_t i(1); i != [lines count]; ++i) {
1250 NSString *trim = [[lines objectAtIndex:i] stringByTrimmingCharactersInSet:whitespace];
1251 [trimmed addObject:trim];
1254 return [trimmed componentsJoinedByString:@"\n"];
1257 - (NSString *) index {
1258 NSString *index = [[[self name] substringToIndex:1] uppercaseString];
1259 return [index length] != 0 && isalpha([index characterAtIndex:0]) ? index : @"123";
1263 return [[Packages_ objectForKey:id_] objectForKey:@"FirstSeen"];
1266 - (NSString *) latest {
1270 - (NSString *) installed {
1274 - (BOOL) upgradable {
1275 if (NSString *installed = [self installed])
1276 return [[self latest] compare:installed] != NSOrderedSame ? YES : NO;
1278 return [self essential];
1281 - (BOOL) essential {
1282 return (iterator_->Flags & pkgCache::Flag::Essential) == 0 ? NO : YES;
1286 return (*[database_ cache])[iterator_].InstBroken();
1293 - (NSString *) name {
1294 return name_ == nil ? id_ : name_;
1297 - (NSString *) tagline {
1301 - (NSString *) icon {
1305 - (NSString *) website {
1309 - (Source *) source {
1313 - (BOOL) matches:(NSString *)text {
1319 range = [[self id] rangeOfString:text options:NSCaseInsensitiveSearch];
1320 if (range.location != NSNotFound)
1323 range = [[self name] rangeOfString:text options:NSCaseInsensitiveSearch];
1324 if (range.location != NSNotFound)
1327 range = [[self tagline] rangeOfString:text options:NSCaseInsensitiveSearch];
1328 if (range.location != NSNotFound)
1334 - (NSComparisonResult) compareByName:(Package *)package {
1335 NSString *lhs = [self name];
1336 NSString *rhs = [package name];
1338 if ([lhs length] != 0 && [rhs length] != 0) {
1339 unichar lhc = [lhs characterAtIndex:0];
1340 unichar rhc = [rhs characterAtIndex:0];
1342 if (isalpha(lhc) && !isalpha(rhc))
1343 return NSOrderedAscending;
1344 else if (!isalpha(lhc) && isalpha(rhc))
1345 return NSOrderedDescending;
1348 return [lhs caseInsensitiveCompare:rhs];
1351 - (NSComparisonResult) compareBySectionAndName:(Package *)package {
1352 NSString *lhs = [self section];
1353 NSString *rhs = [package section];
1355 if (lhs == NULL && rhs != NULL)
1356 return NSOrderedAscending;
1357 else if (lhs != NULL && rhs == NULL)
1358 return NSOrderedDescending;
1359 else if (lhs != NULL && rhs != NULL) {
1360 NSComparisonResult result = [lhs compare:rhs];
1361 if (result != NSOrderedSame)
1365 return [self compareByName:package];
1368 - (NSComparisonResult) compareForChanges:(Package *)package {
1369 BOOL lhs = [self upgradable];
1370 BOOL rhs = [package upgradable];
1373 return lhs ? NSOrderedAscending : NSOrderedDescending;
1375 switch ([[self seen] compare:[package seen]]) {
1376 case NSOrderedAscending:
1377 return NSOrderedDescending;
1380 case NSOrderedDescending:
1381 return NSOrderedAscending;
1387 return [self compareByName:package];
1391 pkgProblemResolver *resolver = [database_ resolver];
1392 resolver->Clear(iterator_);
1393 resolver->Protect(iterator_);
1394 [database_ cache]->MarkInstall(iterator_, false);
1398 pkgProblemResolver *resolver = [database_ resolver];
1399 resolver->Clear(iterator_);
1400 resolver->Protect(iterator_);
1401 resolver->Remove(iterator_);
1402 [database_ cache]->MarkDelete(iterator_, true);
1407 /* Section Class {{{ */
1408 @interface Section : NSObject {
1411 NSMutableArray *packages_;
1416 - (Section *) initWithName:(NSString *)name row:(size_t)row;
1417 - (NSString *) name;
1419 - (NSArray *) packages;
1421 - (void) addPackage:(Package *)package;
1424 @implementation Section
1428 [packages_ release];
1432 - (Section *) initWithName:(NSString *)name row:(size_t)row {
1433 if ((self = [super init]) != nil) {
1434 name_ = [name retain];
1436 packages_ = [[NSMutableArray arrayWithCapacity:16] retain];
1440 - (NSString *) name {
1448 - (NSArray *) packages {
1453 return [packages_ count];
1456 - (void) addPackage:(Package *)package {
1457 [packages_ addObject:package];
1463 /* Package View {{{ */
1464 @protocol PackageViewDelegate
1465 - (void) performPackage:(Package *)package;
1468 @interface PackageView : UIView {
1469 UIPreferencesTable *table_;
1471 UITextView *description_;
1477 - (int) numberOfGroupsInPreferencesTable:(UIPreferencesTable *)table;
1478 - (NSString *) preferencesTable:(UIPreferencesTable *)table titleForGroup:(int)group;
1479 - (float) preferencesTable:(UIPreferencesTable *)table heightForRow:(int)row inGroup:(int)group withProposedHeight:(float)proposed;
1480 - (int) preferencesTable:(UIPreferencesTable *)table numberOfRowsInGroup:(int)group;
1481 - (UIPreferencesTableCell *) preferencesTable:(UIPreferencesTable *)table cellForRow:(int)row inGroup:(int)group;
1483 - (BOOL) canSelectRow:(int)row;
1484 - (void) tableRowSelected:(NSNotification *)notification;
1486 - (Package *) package;
1488 - (id) initWithFrame:(struct CGRect)frame;
1489 - (void) setPackage:(Package *)package;
1490 - (void) setDelegate:(id)delegate;
1493 @implementation PackageView
1496 if (package_ != nil)
1498 if (description_ != nil)
1499 [description_ release];
1504 - (int) numberOfGroupsInPreferencesTable:(UIPreferencesTable *)table {
1508 - (NSString *) preferencesTable:(UIPreferencesTable *)table titleForGroup:(int)group {
1511 case 1: return @"Package Details";
1512 case 2: return @"Source Information";
1514 default: _assert(false);
1518 - (float) preferencesTable:(UIPreferencesTable *)table heightForRow:(int)row inGroup:(int)group withProposedHeight:(float)proposed {
1519 if (group != 0 || row != 1)
1522 return [description_ visibleTextRect].size.height + TextViewOffset_;
1525 - (int) preferencesTable:(UIPreferencesTable *)table numberOfRowsInGroup:(int)group {
1527 case 0: return [package_ website] == nil ? 2 : 3;
1531 default: _assert(false);
1535 - (UIPreferencesTableCell *) preferencesTable:(UIPreferencesTable *)table cellForRow:(int)row inGroup:(int)group {
1536 UIPreferencesTableCell *cell = [[[UIPreferencesTableCell alloc] init] autorelease];
1537 [cell setShowSelection:NO];
1540 case 0: switch (row) {
1542 [cell setTitle:[package_ name]];
1543 [cell setValue:[package_ latest]];
1547 [cell addSubview:description_];
1551 [cell setTitle:@"More Information"];
1552 [cell setShowDisclosure:YES];
1553 [cell setShowSelection:YES];
1556 default: _assert(false);
1559 case 1: switch (row) {
1561 [cell setTitle:@"Identifier"];
1562 [cell setValue:[package_ id]];
1566 [cell setTitle:@"Installed Version"];
1567 NSString *installed([package_ installed]);
1568 [cell setValue:(installed == nil ? @"n/a" : installed)];
1572 [cell setTitle:@"Section"];
1573 NSString *section([package_ section]);
1574 [cell setValue:(section == nil ? @"n/a" : section)];
1578 [cell setTitle:@"Expanded Size"];
1579 [cell setValue:SizeString([package_ size])];
1583 [cell setTitle:@"Maintainer"];
1584 [cell setValue:[[package_ maintainer] name]];
1585 [cell setShowDisclosure:YES];
1586 [cell setShowSelection:YES];
1589 default: _assert(false);
1592 case 2: switch (row) {
1594 [cell setTitle:[[package_ source] label]];
1595 [cell setValue:[[package_ source] version]];
1599 [cell setValue:[[package_ source] description]];
1603 [cell setTitle:@"Origin"];
1604 [cell setValue:[[package_ source] origin]];
1607 default: _assert(false);
1610 default: _assert(false);
1616 - (BOOL) canSelectRow:(int)row {
1620 - (void) tableRowSelected:(NSNotification *)notification {
1621 int row = [table_ selectedRow];
1622 NSString *website = [package_ website];
1624 if (row == (website == nil ? 8 : 9))
1625 [delegate_ openURL:[NSURL URLWithString:[NSString stringWithFormat:@"mailto:%@?subject=%@",
1626 [[package_ maintainer] email],
1627 [[NSString stringWithFormat:@"regarding apt package \"%@\"", [package_ name]] stringByAddingPercentEscapes]
1629 else if (website != nil && row == 3)
1630 [delegate_ openURL:[NSURL URLWithString:website]];
1633 - (Package *) package {
1637 - (id) initWithFrame:(struct CGRect)frame {
1638 if ((self = [super initWithFrame:frame]) != nil) {
1639 table_ = [[UIPreferencesTable alloc] initWithFrame:[self bounds]];
1640 [self addSubview:table_];
1642 [table_ setDataSource:self];
1643 [table_ setDelegate:self];
1647 - (void) setPackage:(Package *)package {
1648 if (package_ != nil) {
1649 [package_ autorelease];
1653 if (description_ != nil) {
1654 [description_ release];
1658 if (package != nil) {
1659 package_ = [package retain];
1661 NSString *description([package description]);
1662 if (description == nil)
1663 description = [package tagline];
1664 description_ = [GetTextView(description, 12, true) retain];
1666 CGColorSpaceRef space = CGColorSpaceCreateDeviceRGB();
1667 CGColor black(space, 0, 0, 0, 1);
1668 [description_ setTextColor:black];
1669 CGColorSpaceRelease(space);
1671 [table_ reloadData];
1675 - (void) setDelegate:(id)delegate {
1676 delegate_ = delegate;
1681 /* Package Cell {{{ */
1682 @interface PackageCell : UITableCell {
1685 UITextLabel *description_;
1686 UITextLabel *source_;
1687 UITextLabel *version_;
1688 UIImageView *trusted_;
1694 - (PackageCell *) initWithVersioner:(SEL)versioner;
1695 - (void) setPackage:(Package *)package;
1697 - (void) _setSelected:(float)fraction;
1698 - (void) setSelected:(BOOL)selected;
1699 - (void) setSelected:(BOOL)selected withFade:(BOOL)fade;
1700 - (void) _setSelectionFadeFraction:(float)fraction;
1704 @implementation PackageCell
1709 [description_ release];
1716 - (PackageCell *) initWithVersioner:(SEL)versioner {
1717 if ((self = [super init]) != nil) {
1718 versioner_ = versioner;
1720 GSFontRef bold = GSFontCreateWithName("Helvetica", kGSFontTraitBold, 22);
1721 GSFontRef large = GSFontCreateWithName("Helvetica", kGSFontTraitNone, 16);
1722 GSFontRef small = GSFontCreateWithName("Helvetica", kGSFontTraitNone, 14);
1724 CGColorSpaceRef space = CGColorSpaceCreateDeviceRGB();
1726 CGColor clear(space, 0, 0, 0, 0);
1728 icon_ = [[UIImageView alloc] initWithFrame:CGRectMake(10, 10, 30, 30)];
1730 name_ = [[UITextLabel alloc] initWithFrame:CGRectMake(48, 12, 240, 25)];
1731 [name_ setBackgroundColor:clear];
1732 [name_ setFont:bold];
1734 description_ = [[UITextLabel alloc] initWithFrame:CGRectMake(12, 46, 280, 20)];
1735 [description_ setBackgroundColor:clear];
1736 [description_ setFont:small];
1738 source_ = [[UITextLabel alloc] initWithFrame:CGRectMake(12, 72, 225, 20)];
1739 [source_ setBackgroundColor:clear];
1740 [source_ setFont:large];
1742 version_ = [[UIRightTextLabel alloc] initWithFrame:CGRectMake(286, 69, 70, 25)];
1743 [version_ setBackgroundColor:clear];
1744 [version_ setFont:large];
1746 //trusted_ = [[UIImageView alloc] initWithFrame:CGRectMake(278, 7, 16, 16)];
1747 trusted_ = [[UIImageView alloc] initWithFrame:CGRectMake(30, 30, 16, 16)];
1748 [trusted_ setImage:[UIImage applicationImageNamed:@"trusted.png"]];
1750 [self addSubview:icon_];
1751 [self addSubview:name_];
1752 [self addSubview:description_];
1753 [self addSubview:source_];
1754 [self addSubview:version_];
1756 CGColorSpaceRelease(space);
1764 - (void) setPackage:(Package *)package {
1765 Source *source = [package source];
1767 UIImage *image = nil;
1768 if (NSString *icon = [package icon])
1769 image = [UIImage imageAtPath:[icon substringFromIndex:6]];
1770 if (image == nil) if (NSString *icon = [source defaultIcon])
1771 image = [UIImage imageAtPath:[icon substringFromIndex:6]];
1773 image = [UIImage applicationImageNamed:@"unknown.png"];
1775 [icon_ setImage:image];
1776 [icon_ zoomToScale:0.5f];
1777 [icon_ setFrame:CGRectMake(10, 10, 30, 30)];
1779 [name_ setText:[package name]];
1780 [version_ setText:[package latest]];
1781 [description_ setText:[package tagline]];
1786 if (source != nil) {
1787 label = [source label];
1788 trusted = [source trusted];
1789 } else if ([[package id] isEqualToString:@"firmware"]) {
1793 label = @"Unknown/Local";
1797 [source_ setText:[NSString stringWithFormat:@"from %@", label]];
1799 [trusted_ removeFromSuperview];
1801 [self addSubview:trusted_];
1804 - (void) _setSelected:(float)fraction {
1805 CGColorSpaceRef space = CGColorSpaceCreateDeviceRGB();
1807 CGColor black(space,
1808 interpolate(0.0, 1.0, fraction),
1809 interpolate(0.0, 1.0, fraction),
1810 interpolate(0.0, 1.0, fraction),
1814 interpolate(0.2, 1.0, fraction),
1815 interpolate(0.2, 1.0, fraction),
1816 interpolate(1.0, 1.0, fraction),
1820 interpolate(0.4, 1.0, fraction),
1821 interpolate(0.4, 1.0, fraction),
1822 interpolate(0.4, 1.0, fraction),
1825 [name_ setColor:black];
1826 [description_ setColor:gray];
1827 [source_ setColor:black];
1828 [version_ setColor:blue];
1830 CGColorSpaceRelease(space);
1833 - (void) setSelected:(BOOL)selected {
1834 [self _setSelected:(selected ? 1.0 : 0.0)];
1835 [super setSelected:selected];
1838 - (void) setSelected:(BOOL)selected withFade:(BOOL)fade {
1840 [self _setSelected:(selected ? 1.0 : 0.0)];
1841 [super setSelected:selected withFade:fade];
1844 - (void) _setSelectionFadeFraction:(float)fraction {
1845 [self _setSelected:fraction];
1846 [super _setSelectionFadeFraction:fraction];
1852 /* Database Implementation {{{ */
1853 @implementation Database
1860 - (void) _readStatus:(NSNumber *)fd {
1861 NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init];
1863 __gnu_cxx::stdio_filebuf<char> ib([fd intValue], std::ios::in);
1864 std::istream is(&ib);
1869 pcre *code = pcre_compile("^([^:]*):([^:]*):([^:]*):(.*)$", 0, &error, &offset, NULL);
1871 pcre_extra *study = NULL;
1873 pcre_fullinfo(code, study, PCRE_INFO_CAPTURECOUNT, &capture);
1874 int matches[(capture + 1) * 3];
1876 while (std::getline(is, line)) {
1877 const char *data(line.c_str());
1879 _assert(pcre_exec(code, study, data, line.size(), 0, 0, matches, sizeof(matches) / sizeof(matches[0])) >= 0);
1881 std::istringstream buffer(line.substr(matches[6], matches[7] - matches[6]));
1884 [delegate_ setPercent:(percent / 100)];
1886 NSString *string = [NSString stringWithCString:(data + matches[8]) length:(matches[9] - matches[8])];
1887 std::string type(line.substr(matches[2], matches[3] - matches[2]));
1889 if (type == "pmerror")
1890 [delegate_ setError:string];
1891 else if (type == "pmstatus")
1892 [delegate_ setTitle:string];
1893 else if (type == "pmconffile")
1895 else _assert(false);
1902 - (void) _readOutput:(NSNumber *)fd {
1903 NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init];
1905 __gnu_cxx::stdio_filebuf<char> ib([fd intValue], std::ios::in);
1906 std::istream is(&ib);
1909 while (std::getline(is, line))
1910 [delegate_ addOutput:[NSString stringWithCString:line.c_str()]];
1916 - (Package *) packageWithName:(NSString *)name {
1917 pkgCache::PkgIterator iterator(cache_->FindPkg([name cString]));
1918 return iterator.end() ? nil : [Package packageWithIterator:iterator database:self];
1921 - (Database *) init {
1922 if ((self = [super init]) != nil) {
1928 sources_ = [[NSMutableDictionary dictionaryWithCapacity:16] retain];
1929 packages_ = [[NSMutableArray arrayWithCapacity:16] retain];
1933 _assert(pipe(fds) != -1);
1937 detachNewThreadSelector:@selector(_readStatus:)
1939 withObject:[[NSNumber numberWithInt:fds[0]] retain]
1942 _assert(pipe(fds) != -1);
1943 _assert(dup2(fds[1], 1) != -1);
1944 _assert(close(fds[1]) != -1);
1947 detachNewThreadSelector:@selector(_readOutput:)
1949 withObject:[[NSNumber numberWithInt:fds[0]] retain]
1954 - (pkgCacheFile &) cache {
1958 - (pkgRecords *) records {
1962 - (pkgProblemResolver *) resolver {
1966 - (pkgAcquire &) fetcher {
1970 - (NSArray *) packages {
1974 - (void) reloadData {
1984 if (!cache_.Open(progress_, true)) {
1985 fprintf(stderr, "repairing corrupted database...\n");
1988 _assert(cache_.Open(progress_, true));
1991 records_ = new pkgRecords(cache_);
1992 resolver_ = new pkgProblemResolver(cache_);
1993 fetcher_ = new pkgAcquire(&status_);
1996 list_ = new pkgSourceList();
1997 _assert(list_->ReadMainList());
1999 [sources_ removeAllObjects];
2000 for (pkgSourceList::const_iterator source = list_->begin(); source != list_->end(); ++source) {
2001 std::vector<pkgIndexFile *> *indices = (*source)->GetIndexFiles();
2002 for (std::vector<pkgIndexFile *>::const_iterator index = indices->begin(); index != indices->end(); ++index)
2004 setObject:[[[Source alloc] initWithMetaIndex:*source] autorelease]
2005 forKey:[NSNumber numberWithLong:reinterpret_cast<uintptr_t>(*index)]
2009 [packages_ removeAllObjects];
2010 for (pkgCache::PkgIterator iterator = cache_->PkgBegin(); !iterator.end(); ++iterator)
2011 if (Package *package = [Package packageWithIterator:iterator database:self])
2012 [packages_ addObject:package];
2016 pkgRecords records(cache_);
2018 lock_ = new FileFd();
2019 lock_->Fd(GetLock(_config->FindDir("Dir::Cache::Archives") + "lock"));
2020 _assert(!_error->PendingError());
2023 _assert(list.ReadMainList());
2025 manager_ = (_system->CreatePM(cache_));
2026 _assert(manager_->GetArchives(fetcher_, &list, &records));
2027 _assert(!_error->PendingError());
2031 if (fetcher_->Run(PulseInterval_) != pkgAcquire::Continue)
2035 pkgPackageManager::OrderResult result = manager_->DoInstall(statusfd_);
2037 if (result == pkgPackageManager::Failed)
2039 if (_error->PendingError())
2041 if (result != pkgPackageManager::Completed)
2047 _assert(list.ReadMainList());
2050 lock.Fd(GetLock(_config->FindDir("Dir::State::Lists") + "lock"));
2051 _assert(!_error->PendingError());
2053 pkgAcquire fetcher(&status_);
2054 _assert(list.GetIndexes(&fetcher));
2055 _assert(fetcher.Run(PulseInterval_) != pkgAcquire::Failed);
2057 bool failed = false;
2058 for (pkgAcquire::ItemIterator item = fetcher.ItemsBegin(); item != fetcher.ItemsEnd(); item++)
2059 if ((*item)->Status != pkgAcquire::Item::StatDone) {
2060 (*item)->Finished();
2064 if (!failed && _config->FindB("APT::Get::List-Cleanup", true) == true) {
2065 _assert(fetcher.Clean(_config->FindDir("Dir::State::lists")));
2066 _assert(fetcher.Clean(_config->FindDir("Dir::State::lists") + "partial/"));
2069 [Metadata_ setObject:[NSDate date] forKey:@"LastUpdate"];
2073 _assert(cache_->DelCount() == 0 && cache_->InstCount() == 0);
2074 _assert(pkgApplyStatus(cache_));
2076 if (cache_->BrokenCount() != 0) {
2077 _assert(pkgFixBroken(cache_));
2078 _assert(cache_->BrokenCount() == 0);
2079 _assert(pkgMinimizeUpgrade(cache_));
2082 _assert(pkgDistUpgrade(cache_));
2085 - (void) setDelegate:(id)delegate {
2086 delegate_ = delegate;
2087 status_.setDelegate(delegate);
2088 progress_.setDelegate(delegate);
2091 - (Source *) getSource:(const pkgCache::PkgFileIterator &)file {
2092 pkgIndexFile *index(NULL);
2093 list_->FindIndex(file, index);
2094 return [sources_ objectForKey:[NSNumber numberWithLong:reinterpret_cast<uintptr_t>(index)]];
2100 /* Progress Data {{{ */
2101 @interface ProgressData : NSObject {
2107 - (ProgressData *) initWithSelector:(SEL)selector target:(id)target object:(id)object;
2114 @implementation ProgressData
2116 - (ProgressData *) initWithSelector:(SEL)selector target:(id)target object:(id)object {
2117 if ((self = [super init]) != nil) {
2118 selector_ = selector;
2138 /* Progress View {{{ */
2139 @interface ProgressView : UIView <
2143 UIView *background_;
2144 UITransitionView *transition_;
2146 UINavigationBar *navbar_;
2147 UIProgressBar *progress_;
2148 UITextView *output_;
2149 UITextLabel *status_;
2155 - (void) transitionViewDidComplete:(UITransitionView*)view fromView:(UIView*)from toView:(UIView*)to;
2157 - (ProgressView *) initWithFrame:(struct CGRect)frame delegate:(id)delegate;
2158 - (void) setContentView:(UIView *)view;
2161 - (void) alertSheet:(UIAlertSheet *)sheet buttonClicked:(int)button;
2163 - (void) _retachThread;
2164 - (void) _detachNewThreadData:(ProgressData *)data;
2165 - (void) detachNewThreadSelector:(SEL)selector toTarget:(id)target withObject:(id)object title:(NSString *)title;
2167 - (void) setError:(NSString *)error;
2168 - (void) _setError:(NSString *)error;
2170 - (void) setTitle:(NSString *)title;
2171 - (void) _setTitle:(NSString *)title;
2173 - (void) setPercent:(float)percent;
2174 - (void) _setPercent:(NSNumber *)percent;
2176 - (void) addOutput:(NSString *)output;
2177 - (void) _addOutput:(NSString *)output;
2180 @protocol ProgressViewDelegate
2181 - (void) progressViewIsComplete:(ProgressView *)sender;
2184 @implementation ProgressView
2188 if (background_ != nil)
2189 [background_ release];
2190 [transition_ release];
2193 [progress_ release];
2199 - (void) transitionViewDidComplete:(UITransitionView*)view fromView:(UIView*)from toView:(UIView*)to {
2200 if (bootstrap_ && from == overlay_ && to == view_)
2204 - (ProgressView *) initWithFrame:(struct CGRect)frame delegate:(id)delegate {
2205 if ((self = [super initWithFrame:frame]) != nil) {
2206 delegate_ = delegate;
2208 CGColorSpaceRef space = CGColorSpaceCreateDeviceRGB();
2210 CGColor black(space, 0.0, 0.0, 0.0, 1.0);
2211 CGColor white(space, 1.0, 1.0, 1.0, 1.0);
2212 CGColor clear(space, 0.0, 0.0, 0.0, 0.0);
2214 transition_ = [[UITransitionView alloc] initWithFrame:[self bounds]];
2215 [transition_ setDelegate:self];
2217 overlay_ = [[UIView alloc] initWithFrame:[transition_ bounds]];
2220 [overlay_ setBackgroundColor:black];
2222 background_ = [[UIView alloc] initWithFrame:[self bounds]];
2223 [background_ setBackgroundColor:black];
2224 [self addSubview:background_];
2227 [self addSubview:transition_];
2229 CGSize navsize = [UINavigationBar defaultSize];
2230 CGRect navrect = {{0, 0}, navsize};
2232 navbar_ = [[UINavigationBar alloc] initWithFrame:navrect];
2233 [overlay_ addSubview:navbar_];
2235 [navbar_ setBarStyle:1];
2236 [navbar_ setDelegate:self];
2238 UINavigationItem *navitem = [[[UINavigationItem alloc] initWithTitle:nil] autorelease];
2239 [navbar_ pushNavigationItem:navitem];
2241 CGRect bounds = [overlay_ bounds];
2242 CGSize prgsize = [UIProgressBar defaultSize];
2245 (bounds.size.width - prgsize.width) / 2,
2246 bounds.size.height - prgsize.height - 20
2249 progress_ = [[UIProgressBar alloc] initWithFrame:prgrect];
2250 [overlay_ addSubview:progress_];
2252 status_ = [[UITextLabel alloc] initWithFrame:CGRectMake(
2254 bounds.size.height - prgsize.height - 50,
2255 bounds.size.width - 20,
2259 [status_ setColor:white];
2260 [status_ setBackgroundColor:clear];
2262 [status_ setCentersHorizontally:YES];
2263 //[status_ setFont:font];
2265 output_ = [[UITextView alloc] initWithFrame:CGRectMake(
2267 navrect.size.height + 20,
2268 bounds.size.width - 20,
2269 bounds.size.height - navsize.height - 62 - navrect.size.height
2272 //[output_ setTextFont:@"Courier New"];
2273 [output_ setTextSize:12];
2275 [output_ setTextColor:white];
2276 [output_ setBackgroundColor:clear];
2278 [output_ setMarginTop:0];
2279 [output_ setAllowsRubberBanding:YES];
2281 [overlay_ addSubview:output_];
2282 [overlay_ addSubview:status_];
2284 [progress_ setStyle:0];
2286 CGColorSpaceRelease(space);
2290 - (void) setContentView:(UIView *)view {
2291 view_ = [view retain];
2294 - (void) resetView {
2295 [transition_ transition:6 toView:view_];
2298 - (void) alertSheet:(UIAlertSheet *)sheet buttonClicked:(int)button {
2302 - (void) _retachThread {
2303 [delegate_ progressViewIsComplete:self];
2307 - (void) _detachNewThreadData:(ProgressData *)data {
2308 NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init];
2310 [[data target] performSelector:[data selector] withObject:[data object]];
2313 [self performSelectorOnMainThread:@selector(_retachThread) withObject:nil waitUntilDone:YES];
2318 - (void) detachNewThreadSelector:(SEL)selector toTarget:(id)target withObject:(id)object title:(NSString *)title {
2319 [navbar_ popNavigationItem];
2320 UINavigationItem *navitem = [[[UINavigationItem alloc] initWithTitle:title] autorelease];
2321 [navbar_ pushNavigationItem:navitem];
2323 [status_ setText:nil];
2324 [output_ setText:@""];
2325 [progress_ setProgress:0];
2327 [transition_ transition:6 toView:overlay_];
2330 detachNewThreadSelector:@selector(_detachNewThreadData:)
2332 withObject:[[ProgressData alloc]
2333 initWithSelector:selector
2340 - (void) setError:(NSString *)error {
2342 performSelectorOnMainThread:@selector(_setError:)
2348 - (void) _setError:(NSString *)error {
2349 UIAlertSheet *sheet = [[[UIAlertSheet alloc]
2350 initWithTitle:@"Package Error"
2351 buttons:[NSArray arrayWithObjects:@"Okay", nil]
2352 defaultButtonIndex:0
2357 [sheet setBodyText:error];
2358 [sheet popupAlertAnimated:YES];
2361 - (void) setTitle:(NSString *)title {
2363 performSelectorOnMainThread:@selector(_setTitle:)
2369 - (void) _setTitle:(NSString *)title {
2370 [status_ setText:[title stringByAppendingString:@"..."]];
2373 - (void) setPercent:(float)percent {
2375 performSelectorOnMainThread:@selector(_setPercent:)
2376 withObject:[NSNumber numberWithFloat:percent]
2381 - (void) _setPercent:(NSNumber *)percent {
2382 [progress_ setProgress:[percent floatValue]];
2385 - (void) addOutput:(NSString *)output {
2387 performSelectorOnMainThread:@selector(_addOutput:)
2393 - (void) _addOutput:(NSString *)output {
2394 [output_ setText:[NSString stringWithFormat:@"%@\n%@", [output_ text], output]];
2395 CGSize size = [output_ contentSize];
2396 CGRect rect = {{0, size.height}, {size.width, 0}};
2397 [output_ scrollRectToVisible:rect animated:YES];
2403 /* Package Table {{{ */
2404 @protocol PackageTableDelegate
2405 - (void) packageTable:(id)table packageSelected:(Package *)package;
2408 @interface PackageTable : UIView {
2410 UISectionList *list_;
2414 NSMutableArray *sections_;
2419 - (int) numberOfSectionsInSectionList:(UISectionList *)list;
2420 - (NSString *) sectionList:(UISectionList *)list titleForSection:(int)section;
2421 - (int) sectionList:(UISectionList *)list rowForSection:(int)section;
2423 - (int) numberOfRowsInTable:(UITable *)table;
2424 - (float) table:(UITable *)table heightForRow:(int)row;
2425 - (UITableCell *) table:(UITable *)table cellForRow:(int)row column:(UITableColumn *)col reusing:(UITableCell *)reusing;
2426 - (BOOL) table:(UITable *)table showDisclosureForRow:(int)row;
2427 - (void) tableRowSelected:(NSNotification *)notification;
2429 - (id) initWithFrame:(CGRect)frame versioner:(SEL)versioner;
2431 - (void) setDelegate:(id)delegate;
2432 - (void) setPackages:(NSArray *)packages;
2434 - (void) resetViewAnimated:(BOOL)animated;
2435 - (UITable *) table;
2438 @implementation PackageTable
2442 [sections_ release];
2443 if (packages_ != nil)
2444 [packages_ release];
2448 - (int) numberOfSectionsInSectionList:(UISectionList *)list {
2449 return [sections_ count];
2452 - (NSString *) sectionList:(UISectionList *)list titleForSection:(int)section {
2453 return [[sections_ objectAtIndex:section] name];
2456 - (int) sectionList:(UISectionList *)list rowForSection:(int)section {
2457 return [[sections_ objectAtIndex:section] row];
2460 - (int) numberOfRowsInTable:(UITable *)table {
2461 return [packages_ count];
2464 - (float) table:(UITable *)table heightForRow:(int)row {
2468 - (UITableCell *) table:(UITable *)table cellForRow:(int)row column:(UITableColumn *)col reusing:(UITableCell *)reusing {
2470 reusing = [[[PackageCell alloc] initWithVersioner:versioner_] autorelease];
2471 [(PackageCell *)reusing setPackage:[packages_ objectAtIndex:row]];
2475 - (BOOL) table:(UITable *)table showDisclosureForRow:(int)row {
2479 - (void) tableRowSelected:(NSNotification *)notification {
2480 int row = [[notification object] selectedRow];
2481 [delegate_ packageTable:self packageSelected:(row == INT_MAX ? nil : [packages_ objectAtIndex:row])];
2484 - (id) initWithFrame:(CGRect)frame versioner:(SEL)versioner {
2485 if ((self = [super initWithFrame:frame]) != nil) {
2486 versioner_ = versioner;
2487 sections_ = [[NSMutableArray arrayWithCapacity:16] retain];
2489 list_ = [[UISectionList alloc] initWithFrame:[self bounds] showSectionIndex:YES];
2490 [list_ setDataSource:self];
2492 UITableColumn *column = [[[UITableColumn alloc]
2493 initWithTitle:@"Name"
2495 width:frame.size.width
2498 UITable *table = [list_ table];
2499 [table setSeparatorStyle:1];
2500 [table addTableColumn:column];
2501 [table setDelegate:self];
2502 [table setReusesTableCells:YES];
2504 [self addSubview:list_];
2508 - (void) setDelegate:(id)delegate {
2509 delegate_ = delegate;
2512 - (void) setPackages:(NSArray *)packages {
2513 if (packages_ != nil)
2514 [packages_ autorelease];
2515 _assert(packages != nil);
2516 packages_ = [packages retain];
2518 [sections_ removeAllObjects];
2520 Section *section = nil;
2522 for (size_t offset(0); offset != [packages_ count]; ++offset) {
2523 Package *package = [packages_ objectAtIndex:offset];
2524 NSString *name = [package index];
2526 if (section == nil || ![[section name] isEqual:name]) {
2527 section = [[[Section alloc] initWithName:name row:offset] autorelease];
2528 [sections_ addObject:section];
2531 [section addPackage:package];
2537 - (void) resetViewAnimated:(BOOL)animated {
2538 [[list_ table] selectRow:-1 byExtendingSelection:NO withFade:animated];
2541 - (UITable *) table {
2542 return [list_ table];
2548 /* Section Cell {{{ */
2549 @interface SectionCell : UITableCell {
2551 UITextLabel *count_;
2557 - (void) setSection:(Section *)section;
2559 - (void) _setSelected:(float)fraction;
2560 - (void) setSelected:(BOOL)selected;
2561 - (void) setSelected:(BOOL)selected withFade:(BOOL)fade;
2562 - (void) _setSelectionFadeFraction:(float)fraction;
2566 @implementation SectionCell
2575 if ((self = [super init]) != nil) {
2576 GSFontRef bold = GSFontCreateWithName("Helvetica", kGSFontTraitBold, 22);
2577 GSFontRef small = GSFontCreateWithName("Helvetica", kGSFontTraitBold, 12);
2579 CGColorSpaceRef space = CGColorSpaceCreateDeviceRGB();
2580 CGColor clear(space, 0, 0, 0, 0);
2581 CGColor white(space, 1, 1, 1, 1);
2583 name_ = [[UITextLabel alloc] initWithFrame:CGRectMake(48, 9, 250, 25)];
2584 [name_ setBackgroundColor:clear];
2585 [name_ setFont:bold];
2587 count_ = [[UITextLabel alloc] initWithFrame:CGRectMake(11, 7, 29, 32)];
2588 [count_ setCentersHorizontally:YES];
2589 [count_ setBackgroundColor:clear];
2590 [count_ setFont:small];
2591 [count_ setColor:white];
2593 UIImageView *folder = [[[UIImageView alloc] initWithFrame:CGRectMake(8, 7, 32, 32)] autorelease];
2594 [folder setImage:[UIImage applicationImageNamed:@"folder.png"]];
2596 [self addSubview:folder];
2597 [self addSubview:name_];
2598 [self addSubview:count_];
2600 [self _setSelected:0];
2602 CGColorSpaceRelease(space);
2609 - (void) setSection:(Section *)section {
2610 if (section == nil) {
2611 [name_ setText:@"All Packages"];
2612 [count_ setText:nil];
2614 NSString *name = [section name];
2615 [name_ setText:(name == nil ? @"(No Section)" : name)];
2616 [count_ setText:[NSString stringWithFormat:@"%d", [section count]]];
2620 - (void) _setSelected:(float)fraction {
2621 CGColorSpaceRef space = CGColorSpaceCreateDeviceRGB();
2623 CGColor black(space,
2624 interpolate(0.0, 1.0, fraction),
2625 interpolate(0.0, 1.0, fraction),
2626 interpolate(0.0, 1.0, fraction),
2629 [name_ setColor:black];
2631 CGColorSpaceRelease(space);
2634 - (void) setSelected:(BOOL)selected {
2635 [self _setSelected:(selected ? 1.0 : 0.0)];
2636 [super setSelected:selected];
2639 - (void) setSelected:(BOOL)selected withFade:(BOOL)fade {
2641 [self _setSelected:(selected ? 1.0 : 0.0)];
2642 [super setSelected:selected withFade:fade];
2645 - (void) _setSelectionFadeFraction:(float)fraction {
2646 [self _setSelected:fraction];
2647 [super _setSelectionFadeFraction:fraction];
2652 /* Install View {{{ */
2653 @interface InstallView : ResetView <
2654 PackageTableDelegate
2658 PackageTable *table_;
2662 NSMutableArray *packages_;
2667 - (void) navigationBar:(UINavigationBar *)navbar buttonClicked:(int)button;
2669 - (int) numberOfRowsInTable:(UITable *)table;
2670 - (float) table:(UITable *)table heightForRow:(int)row;
2671 - (UITableCell *) table:(UITable *)table cellForRow:(int)row column:(UITableColumn *)col reusing:(UITableCell *)reusing;
2672 - (BOOL) table:(UITable *)table showDisclosureForRow:(int)row;
2673 - (void) tableRowSelected:(NSNotification *)notification;
2675 - (void) packageTable:(id)table packageSelected:(Package *)package;
2677 - (id) initWithFrame:(CGRect)frame;
2678 - (void) setPackages:(NSArray *)packages;
2679 - (void) setDelegate:(id)delegate;
2682 @implementation InstallView
2685 [packages_ release];
2686 if (sections_ != nil)
2687 [sections_ release];
2694 if (section_ != nil)
2696 if (package_ != nil)
2701 - (void) navigationBar:(UINavigationBar *)navbar buttonClicked:(int)button {
2703 [[view_ package] install];
2704 [delegate_ resolve];
2705 [delegate_ perform];
2709 - (int) numberOfRowsInTable:(UITable *)table {
2710 return [sections_ count] + 1;
2713 - (float) table:(UITable *)table heightForRow:(int)row {
2717 - (UITableCell *) table:(UITable *)table cellForRow:(int)row column:(UITableColumn *)col reusing:(UITableCell *)reusing {
2719 reusing = [[[SectionCell alloc] init] autorelease];
2721 [(SectionCell *)reusing setSection:nil];
2723 [(SectionCell *)reusing setSection:[sections_ objectAtIndex:(row - 1)]];
2727 - (BOOL) table:(UITable *)table showDisclosureForRow:(int)row {
2731 - (void) tableRowSelected:(NSNotification *)notification {
2732 int row = [[notification object] selectedRow];
2734 if (row == INT_MAX) {
2741 _assert(section_ == nil);
2742 _assert(table_ == nil);
2750 name = @"All Packages";
2752 section = [sections_ objectAtIndex:(row - 1)];
2753 name = [section name];
2754 section_ = [name retain];
2757 table_ = [[PackageTable alloc] initWithFrame:[transition_ bounds] versioner:@selector(latest)];
2758 [table_ setDelegate:self];
2759 [table_ setPackages:(section == nil ? packages_ : [section packages])];
2761 [self pushView:table_ withTitle:name backButtonTitle:@"Packages" rightButton:nil];
2765 - (void) packageTable:(id)table packageSelected:(Package *)package {
2766 if (package == nil) {
2773 _assert(package_ == nil);
2774 _assert(view_ == nil);
2776 package_ = [[package name] retain];
2778 view_ = [[PackageView alloc] initWithFrame:[transition_ bounds]];
2779 [view_ setDelegate:delegate_];
2781 [view_ setPackage:package];
2783 [self pushView:view_ withTitle:[package name] backButtonTitle:nil rightButton:@"Install"];
2787 - (id) initWithFrame:(CGRect)frame {
2788 if ((self = [super initWithFrame:frame]) != nil) {
2789 packages_ = [[NSMutableArray arrayWithCapacity:16] retain];
2791 list_ = [[UITable alloc] initWithFrame:[transition_ bounds]];
2792 [self pushView:list_ withTitle:@"Install" backButtonTitle:@"Sections" rightButton:nil];
2794 UITableColumn *column = [[[UITableColumn alloc]
2795 initWithTitle:@"Name"
2797 width:frame.size.width
2800 [list_ setDataSource:self];
2801 [list_ setSeparatorStyle:1];
2802 [list_ addTableColumn:column];
2803 [list_ setDelegate:self];
2804 [list_ setReusesTableCells:YES];
2806 [transition_ transition:0 toView:list_];
2810 - (void) setPackages:(NSArray *)packages {
2811 [packages_ removeAllObjects];
2813 for (size_t i(0); i != [packages count]; ++i) {
2814 Package *package([packages objectAtIndex:i]);
2815 if ([package installed] == nil)
2816 [packages_ addObject:package];
2819 [packages_ sortUsingSelector:@selector(compareBySectionAndName:)];
2820 NSMutableArray *sections = [NSMutableArray arrayWithCapacity:16];
2822 Section *nsection = nil;
2823 Package *npackage = nil;
2825 Section *section = nil;
2826 for (size_t offset = 0, count = [packages_ count]; offset != count; ++offset) {
2827 Package *package = [packages_ objectAtIndex:offset];
2828 NSString *name = [package section];
2830 if (section == nil || name != nil && ![[section name] isEqual:name]) {
2831 section = [[[Section alloc] initWithName:name row:offset] autorelease];
2833 if (name == nil || [name isEqualToString:section_])
2835 [sections addObject:section];
2838 if ([[package name] isEqualToString:package_])
2840 [section addPackage:package];
2843 if (sections_ != nil)
2844 [sections_ release];
2845 sections_ = [sections retain];
2847 [packages_ sortUsingSelector:@selector(compareByName:)];
2853 if (npackage != nil)
2854 [view_ setPackage:npackage];
2855 else if (package_ != nil)
2858 if (table_ != nil && section_ == nil)
2859 [table_ setPackages:packages_];
2860 else if (nsection != nil)
2861 [table_ setPackages:[nsection packages]];
2862 else if (section_ != nil)
2866 [self popViews:views];
2870 - (void) setDelegate:(id)delegate {
2872 [view_ setDelegate:delegate];
2873 [super setDelegate:delegate];
2878 /* Changes View {{{ */
2879 @interface ChangesView : ResetView <
2880 PackageTableDelegate
2882 UISectionList *list_;
2883 NSMutableArray *packages_;
2884 NSMutableArray *sections_;
2892 - (void) navigationBar:(UINavigationBar *)navbar buttonClicked:(int)button;
2894 - (int) numberOfSectionsInSectionList:(UISectionList *)list;
2895 - (NSString *) sectionList:(UISectionList *)list titleForSection:(int)section;
2896 - (int) sectionList:(UISectionList *)list rowForSection:(int)section;
2898 - (int) numberOfRowsInTable:(UITable *)table;
2899 - (float) table:(UITable *)table heightForRow:(int)row;
2900 - (UITableCell *) table:(UITable *)table cellForRow:(int)row column:(UITableColumn *)col reusing:(UITableCell *)reusing;
2901 - (BOOL) table:(UITable *)table showDisclosureForRow:(int)row;
2902 - (void) tableRowSelected:(NSNotification *)notification;
2904 - (id) initWithFrame:(CGRect)frame;
2905 - (void) setPackages:(NSArray *)packages;
2906 - (void) _resetView;
2909 - (void) setDelegate:(id)delegate;
2912 @implementation ChangesView
2916 [packages_ release];
2917 [sections_ release];
2920 if (package_ != nil)
2925 - (int) numberOfSectionsInSectionList:(UISectionList *)list {
2926 return [sections_ count];
2929 - (NSString *) sectionList:(UISectionList *)list titleForSection:(int)section {
2930 return [[sections_ objectAtIndex:section] name];
2933 - (int) sectionList:(UISectionList *)list rowForSection:(int)section {
2934 return [[sections_ objectAtIndex:section] row];
2937 - (int) numberOfRowsInTable:(UITable *)table {
2938 return [packages_ count];
2941 - (float) table:(UITable *)table heightForRow:(int)row {
2945 - (UITableCell *) table:(UITable *)table cellForRow:(int)row column:(UITableColumn *)col reusing:(UITableCell *)reusing {
2947 reusing = [[[PackageCell alloc] initWithVersioner:NULL] autorelease];
2948 [(PackageCell *)reusing setPackage:[packages_ objectAtIndex:row]];
2952 - (BOOL) table:(UITable *)table showDisclosureForRow:(int)row {
2956 - (void) tableRowSelected:(NSNotification *)notification {
2957 int row = [[notification object] selectedRow];
2958 [self packageTable:self packageSelected:(row == INT_MAX ? nil : [packages_ objectAtIndex:row])];
2961 - (void) navigationBar:(UINavigationBar *)navbar buttonClicked:(int)button {
2964 [[view_ package] install];
2965 [delegate_ resolve];
2966 [delegate_ perform];
2970 [delegate_ upgrade];
2975 - (void) packageTable:(id)table packageSelected:(Package *)package {
2976 if (package == nil) {
2983 _assert(package_ == nil);
2984 _assert(view_ == nil);
2986 package_ = [[package name] retain];
2988 view_ = [[PackageView alloc] initWithFrame:[transition_ bounds]];
2989 [view_ setDelegate:delegate_];
2991 [view_ setPackage:package];
2993 [self pushView:view_ withTitle:[package name] backButtonTitle:nil rightButton:(
2994 [package upgradable] ? @"Upgrade" : @"Install"
2999 - (id) initWithFrame:(CGRect)frame {
3000 if ((self = [super initWithFrame:frame]) != nil) {
3001 packages_ = [[NSMutableArray arrayWithCapacity:16] retain];
3002 sections_ = [[NSMutableArray arrayWithCapacity:16] retain];
3004 list_ = [[UISectionList alloc] initWithFrame:[transition_ bounds] showSectionIndex:NO];
3005 [list_ setShouldHideHeaderInShortLists:NO];
3006 [list_ setDataSource:self];
3007 //[list_ setSectionListStyle:1];
3009 UITableColumn *column = [[[UITableColumn alloc]
3010 initWithTitle:@"Name"
3012 width:frame.size.width
3015 UITable *table = [list_ table];
3016 [table setSeparatorStyle:1];
3017 [table addTableColumn:column];
3018 [table setDelegate:self];
3019 [table setReusesTableCells:YES];
3021 [self pushView:list_ withTitle:@"Changes" backButtonTitle:nil rightButton:nil];
3025 - (void) setPackages:(NSArray *)packages {
3026 [packages_ removeAllObjects];
3027 for (size_t i(0); i != [packages count]; ++i) {
3028 Package *package([packages objectAtIndex:i]);
3029 if ([package installed] == nil || [package upgradable])
3030 [packages_ addObject:package];
3033 [packages_ sortUsingSelector:@selector(compareForChanges:)];
3035 [sections_ removeAllObjects];
3037 Section *upgradable = [[[Section alloc] initWithName:@"Available Upgrades" row:0] autorelease];
3038 Section *section = nil;
3041 Package *npackage = nil;
3042 for (size_t offset = 0, count = [packages_ count]; offset != count; ++offset) {
3043 Package *package = [packages_ objectAtIndex:offset];
3044 if ([[package name] isEqualToString:package_])
3047 if ([package upgradable])
3048 [upgradable addPackage:package];
3050 NSDate *seen = [package seen];
3052 CFLocaleRef locale = CFLocaleCopyCurrent();
3053 CFDateFormatterRef formatter = CFDateFormatterCreate(NULL, locale, kCFDateFormatterMediumStyle, kCFDateFormatterMediumStyle);
3054 CFStringRef formatted = CFDateFormatterCreateStringWithDate(NULL, formatter, (CFDateRef) seen);
3056 NSString *name = (NSString *) formatted;
3058 if (section == nil || ![[section name] isEqual:name]) {
3059 section = [[[Section alloc] initWithName:name row:offset] autorelease];
3060 [sections_ addObject:section];
3063 [section addPackage:package];
3065 CFRelease(formatter);
3066 CFRelease(formatted);
3071 count_ = [[upgradable packages] count];
3073 [sections_ insertObject:upgradable atIndex:0];
3077 if (npackage != nil)
3078 [view_ setPackage:npackage];
3079 else if (package_ != nil)
3086 - (void) _resetView {
3087 if ([views_ count] == 1)
3088 [navbar_ showButtonsWithLeftTitle:(count_ == 0 ? nil : @"Upgrade All") rightTitle:nil];
3095 - (void) setDelegate:(id)delegate {
3097 [view_ setDelegate:delegate];
3098 [super setDelegate:delegate];
3103 /* Manage View {{{ */
3104 @interface ManageView : ResetView <
3105 PackageTableDelegate
3107 PackageTable *table_;
3114 - (void) navigationBar:(UINavigationBar *)navbar buttonClicked:(int)button;
3116 - (void) packageTable:(id)table packageSelected:(Package *)package;
3118 - (id) initWithFrame:(CGRect)frame;
3119 - (void) setPackages:(NSArray *)packages;
3121 - (void) setDelegate:(id)delegate;
3124 @implementation ManageView
3130 if (package_ != nil)
3135 - (void) navigationBar:(UINavigationBar *)navbar buttonClicked:(int)button {
3137 [[view_ package] remove];
3138 [delegate_ resolve];
3139 [delegate_ perform];
3143 - (void) packageTable:(id)table packageSelected:(Package *)package {
3144 if (package == nil) {
3151 _assert(package_ == nil);
3152 _assert(view_ == nil);
3154 package_ = [[package name] retain];
3156 view_ = [[PackageView alloc] initWithFrame:[transition_ bounds]];
3157 [view_ setDelegate:delegate_];
3159 [view_ setPackage:package];
3161 [self pushView:view_ withTitle:[package name] backButtonTitle:nil rightButton:@"Uninstall"];
3165 - (id) initWithFrame:(CGRect)frame {
3166 if ((self = [super initWithFrame:frame]) != nil) {
3167 table_ = [[PackageTable alloc] initWithFrame:[transition_ bounds] versioner:@selector(latest)];
3168 [table_ setDelegate:self];
3170 [self pushView:table_ withTitle:@"Uninstall" backButtonTitle:@"Packages" rightButton:nil];
3174 - (void) setPackages:(NSArray *)packages {
3175 NSMutableArray *local = [NSMutableArray arrayWithCapacity:16];
3176 for (size_t i(0); i != [packages count]; ++i) {
3177 Package *package([packages objectAtIndex:i]);
3178 if ([package installed] != nil)
3179 [local addObject:package];
3182 [local sortUsingSelector:@selector(compareByName:)];
3184 Package *npackage = nil;
3185 for (size_t offset = 0, count = [local count]; offset != count; ++offset) {
3186 Package *package = [local objectAtIndex:offset];
3187 if ([[package name] isEqualToString:package_])
3191 [table_ setPackages:local];
3193 if (npackage != nil)
3194 [view_ setPackage:npackage];
3195 else if (package_ != nil)
3201 - (void) setDelegate:(id)delegate {
3203 [view_ setDelegate:delegate];
3204 [super setDelegate:delegate];
3209 /* Search View {{{ */
3210 @protocol SearchViewDelegate
3211 - (void) showKeyboard:(BOOL)show;
3214 @interface SearchView : ResetView <
3215 PackageTableDelegate
3217 NSMutableArray *packages_;
3219 UISearchField *field_;
3220 PackageTable *table_;
3227 - (void) navigationBar:(UINavigationBar *)navbar buttonClicked:(int)button;
3228 - (void) packageTable:(id)table packageSelected:(Package *)package;
3230 - (void) textFieldDidBecomeFirstResponder:(UITextField *)field;
3231 - (void) textFieldDidResignFirstResponder:(UITextField *)field;
3233 - (void) keyboardInputChanged:(UIFieldEditor *)editor;
3234 - (BOOL) keyboardInput:(id)input shouldInsertText:(NSString *)text isMarkedText:(int)marked;
3236 - (id) initWithFrame:(CGRect)frame;
3237 - (void) setPackages:(NSArray *)packages;
3239 - (void) setDelegate:(id)delegate;
3240 - (void) resetPackage:(Package *)package;
3241 - (void) searchPackages;
3245 @implementation SearchView
3248 [packages_ release];
3249 [accessory_ release];
3254 if (package_ != nil)
3259 - (void) navigationBar:(UINavigationBar *)navbar buttonClicked:(int)button {
3261 Package *package = [view_ package];
3262 if ([package installed] == nil)
3266 [delegate_ resolve];
3267 [delegate_ perform];
3271 - (void) packageTable:(id)table packageSelected:(Package *)package {
3272 if (package == nil) {
3273 [navbar_ setAccessoryView:accessory_ animate:(resetting_ ? NO : YES) goingBack:YES];
3281 [navbar_ setAccessoryView:nil animate:YES goingBack:NO];
3283 _assert(package_ == nil);
3284 _assert(view_ == nil);
3286 package_ = [[package name] retain];
3288 view_ = [[PackageView alloc] initWithFrame:[transition_ bounds]];
3289 [view_ setDelegate:delegate_];
3291 [self pushView:view_ withTitle:[package name] backButtonTitle:nil rightButton:nil];
3292 [self resetPackage:package];
3296 - (void) textFieldDidBecomeFirstResponder:(UITextField *)field {
3297 [delegate_ showKeyboard:YES];
3298 [table_ setEnabled:NO];
3300 /*CGColorSpaceRef space = CGColorSpaceCreateDeviceRGB();
3301 CGColor dimmed(alpha, 0, 0, 0, 0.5);
3302 [editor_ setBackgroundColor:dimmed];
3303 CGColorSpaceRelease(space);*/
3306 - (void) textFieldDidResignFirstResponder:(UITextField *)field {
3307 [table_ setEnabled:YES];
3308 [delegate_ showKeyboard:NO];
3311 - (void) keyboardInputChanged:(UIFieldEditor *)editor {
3312 NSString *text([field_ text]);
3313 [field_ setClearButtonStyle:(text == nil || [text length] == 0 ? 0 : 2)];
3316 - (BOOL) keyboardInput:(id)input shouldInsertText:(NSString *)text isMarkedText:(int)marked {
3317 if ([text length] != 1 || [text characterAtIndex:0] != '\n')
3320 [self searchPackages];
3321 [field_ resignFirstResponder];
3325 - (id) initWithFrame:(CGRect)frame {
3326 if ((self = [super initWithFrame:frame]) != nil) {
3327 packages_ = [[NSMutableArray arrayWithCapacity:16] retain];
3329 table_ = [[PackageTable alloc] initWithFrame:[transition_ bounds] versioner:@selector(latest)];
3330 [table_ setDelegate:self];
3332 CGRect area = [self bounds];
3335 area.size.width -= 12;
3336 area.size.height = [UISearchField defaultHeight];
3338 field_ = [[UISearchField alloc] initWithFrame:area];
3340 GSFontRef font = GSFontCreateWithName("Helvetica", kGSFontTraitNone, 16);
3341 [field_ setFont:font];
3344 [field_ setPlaceholder:@"Package Names & Descriptions"];
3345 [field_ setPaddingTop:5];
3346 [field_ setDelegate:self];
3348 UITextTraits *traits = [field_ textTraits];
3349 [traits setEditingDelegate:self];
3350 [traits setReturnKeyType:6];
3352 accessory_ = [[UIView alloc] initWithFrame:CGRectMake(6, 6, area.size.width, area.size.height + 30)];
3353 [accessory_ addSubview:field_];
3355 [navbar_ setAccessoryView:accessory_];
3356 [self pushView:table_ withTitle:nil backButtonTitle:@"Search" rightButton:nil];
3358 /* XXX: for the love of god just fix this */
3359 [navbar_ removeFromSuperview];
3360 [reload_ removeFromSuperview];
3361 [configure_ removeFromSuperview];
3362 [self addSubview:navbar_];
3363 [self addSubview:reload_];
3364 [self addSubview:configure_];
3368 - (void) setPackages:(NSArray *)packages {
3369 [packages_ removeAllObjects];
3370 [packages_ addObjectsFromArray:packages];
3371 [packages_ sortUsingSelector:@selector(compareByName:)];
3373 Package *npackage = nil;
3374 for (size_t offset = 0, count = [packages_ count]; offset != count; ++offset) {
3375 Package *package = [packages_ objectAtIndex:offset];
3376 if ([[package name] isEqualToString:package_])
3380 [self searchPackages];
3382 if (npackage != nil)
3383 [self resetPackage:npackage];
3384 else if (package_ != nil)
3390 - (void) setDelegate:(id)delegate {
3392 [view_ setDelegate:delegate];
3393 [super setDelegate:delegate];
3396 - (void) resetPackage:(Package *)package {
3397 [view_ setPackage:package];
3398 NSString *right = [package installed] == nil ? @"Install" : @"Uninstall";
3399 [navbar_ showButtonsWithLeftTitle:nil rightTitle:right];
3402 - (void) searchPackages {
3403 NSString *text([field_ text]);
3405 NSMutableArray *packages([NSMutableArray arrayWithCapacity:16]);
3407 for (size_t offset(0), count([packages_ count]); offset != count; ++offset) {
3408 Package *package = [packages_ objectAtIndex:offset];
3409 if ([package matches:text])
3410 [packages addObject:package];
3413 [table_ setPackages:packages];
3414 [[table_ table] scrollPointVisibleAtTopLeft:CGPointMake(0, 0) animated:NO];
3420 @interface Cydia : UIApplication <
3421 ConfirmationViewDelegate,
3422 ProgressViewDelegate,
3428 UITransitionView *transition_;
3429 UIButtonBar *buttonbar_;
3431 ConfirmationView *confirm_;
3433 Database *database_;
3434 ProgressView *progress_;
3437 UINavigationBar *navbar_;
3438 UIScroller *scroller_;
3439 UIWebView *webview_;
3441 UIProgressIndicator *indicator_;
3443 InstallView *install_;
3444 ChangesView *changes_;
3445 ManageView *manage_;
3446 SearchView *search_;
3451 UIKeyboard *keyboard_;
3455 - (void) reloadData:(BOOL)reset;
3466 - (void) progressViewIsComplete:(ProgressView *)progress;
3468 - (void) navigationBar:(UINavigationBar *)navbar buttonClicked:(int)button;
3469 - (void) alertSheet:(UIAlertSheet *)sheet buttonClicked:(int)button;
3470 - (void) buttonBarItemTapped:(id)sender;
3472 - (void) view:(UIView *)sender didSetFrame:(CGRect)frame oldFrame:(CGRect)old;
3474 - (void) webView:(WebView *)sender didReceiveTitle:(NSString *)title forFrame:(WebFrame *)frame;
3476 - (void) applicationWillSuspend;
3477 - (void) applicationDidFinishLaunching:(id)unused;
3480 @implementation Cydia
3483 NSMutableURLRequest *request = [NSMutableURLRequest
3485 cachePolicy:NSURLRequestReloadIgnoringCacheData
3486 timeoutInterval:30.0
3489 [request addValue:[NSString stringWithCString:Firmware_] forHTTPHeaderField:@"X-Firmware"];
3490 [request addValue:[NSString stringWithCString:Machine_] forHTTPHeaderField:@"X-Machine"];
3491 [request addValue:[NSString stringWithCString:SerialNumber_] forHTTPHeaderField:@"X-Serial-Number"];
3493 [webview_ loadRequest:request];
3496 - (void) reloadData:(BOOL)reset {
3497 [database_ reloadData];
3501 if (Packages_ == nil) {
3502 Packages_ = [[NSMutableDictionary alloc] initWithCapacity:count];
3503 [Metadata_ setObject:Packages_ forKey:@"Packages"];
3506 now_ = [NSDate date];
3508 NSArray *packages = [database_ packages];
3510 [install_ setPackages:packages];
3511 [changes_ setPackages:packages];
3512 [manage_ setPackages:packages];
3513 [search_ setPackages:packages];
3515 if (size_t count = [changes_ count]) {
3516 NSString *badge([[NSNumber numberWithInt:count] stringValue]);
3517 [buttonbar_ setBadgeValue:badge forButton:3];
3518 if ([buttonbar_ respondsToSelector:@selector(setBadgeAnimated:forButton:)])
3519 [buttonbar_ setBadgeAnimated:YES forButton:3];
3520 [self setApplicationBadge:badge];
3522 [buttonbar_ setBadgeValue:nil forButton:3];
3523 if ([buttonbar_ respondsToSelector:@selector(setBadgeAnimated:forButton:)])
3524 [buttonbar_ setBadgeAnimated:NO forButton:3];
3525 [self removeApplicationBadge];
3528 _assert([Metadata_ writeToFile:@"/var/lib/cydia/metadata.plist" atomically:YES] == YES);
3531 - (void) setPrompt {
3532 [navbar_ setPrompt:[NSString stringWithFormat:@"Last Updated: %@", GetLastUpdate()]];
3536 pkgProblemResolver *resolver = [database_ resolver];
3538 resolver->InstallProtect();
3539 if (!resolver->Resolve(true))
3544 [database_ prepare];
3546 if ([database_ cache]->BrokenCount() == 0)
3547 confirm_ = [[ConfirmationView alloc] initWithView:underlay_ database:database_ delegate:self];
3549 NSMutableArray *broken = [NSMutableArray arrayWithCapacity:16];
3550 NSArray *packages = [database_ packages];
3552 for (size_t i(0); i != [packages count]; ++i) {
3553 Package *package = [packages objectAtIndex:i];
3554 if ([package broken])
3555 [broken addObject:[package name]];
3558 UIAlertSheet *sheet = [[[UIAlertSheet alloc]
3559 initWithTitle:[NSString stringWithFormat:@"%d Broken Packages", [database_ cache]->BrokenCount()]
3560 buttons:[NSArray arrayWithObjects:@"Okay", nil]
3561 defaultButtonIndex:0
3566 [sheet setBodyText:[NSString stringWithFormat:@"The following packages have unmet dependencies:\n\n%@", [broken componentsJoinedByString:@"\n"]]];
3567 [sheet popupAlertAnimated:YES];
3569 [self reloadData:NO];
3574 [database_ upgrade];
3579 [self reloadData:NO];
3585 [overlay_ removeFromSuperview];
3589 detachNewThreadSelector:@selector(perform)
3596 - (void) bootstrap_ {
3598 [database_ upgrade];
3599 [database_ prepare];
3600 [database_ perform];
3603 - (void) bootstrap {
3605 detachNewThreadSelector:@selector(bootstrap_)
3608 title:@"Bootstrap Install..."
3614 detachNewThreadSelector:@selector(update)
3617 title:@"Refreshing Sources..."
3621 - (void) progressViewIsComplete:(ProgressView *)progress {
3622 [self reloadData:YES];
3624 if (confirm_ != nil) {
3625 [underlay_ addSubview:overlay_];
3626 [confirm_ removeFromSuperview];
3632 - (void) navigationBar:(UINavigationBar *)navbar buttonClicked:(int)button {
3639 UIAlertSheet *sheet = [[[UIAlertSheet alloc]
3640 initWithTitle:@"About Cydia Packager"
3641 buttons:[NSArray arrayWithObjects:@"Close", nil]
3642 defaultButtonIndex:0
3648 @"Copyright (C) 2008\n"
3649 "Jay Freeman (saurik)\n"
3650 "saurik@saurik.com\n"
3651 "http://www.saurik.com/\n"
3654 "http://www.theokorigroup.com/\n"
3656 "College of Creative Studies,\n"
3657 "University of California,\n"
3659 "http://www.ccs.ucsb.edu/\n"
3662 "bad_, BHSPitMonkey, cash, Cobra,\n"
3663 "core, Corona, crashx, cromas,\n"
3664 "Darken, dtzWill, Erica, francis,\n"
3665 "Godores, jerry, Kingstone, lounger,\n"
3666 "mbranes, rockabilly, tman, Wbiggs"
3669 [sheet presentSheetFromButtonBar:buttonbar_];
3674 - (void) alertSheet:(UIAlertSheet *)sheet buttonClicked:(int)button {
3678 - (void) buttonBarItemTapped:(id)sender {
3680 unsigned tag = [sender tag];
3683 case 1: view = featured_; break;
3684 case 2: view = install_; break;
3685 case 3: view = changes_; break;
3686 case 4: view = manage_; break;
3687 case 5: view = search_; break;
3693 if ([view respondsToSelector:@selector(resetView:)])
3694 [(id) view resetView:(tag == tag_ ? NO : YES)];
3696 [transition_ transition:0 toView:view];
3699 - (void) view:(UIView *)sender didSetFrame:(CGRect)frame oldFrame:(CGRect)old {
3700 [scroller_ setContentSize:frame.size];
3701 [indicator_ stopAnimation];
3704 - (void) webView:(WebView *)sender didReceiveTitle:(NSString *)title forFrame:(WebFrame *)frame {
3705 [navbar_ setPrompt:title];
3708 - (void) webView:(WebView *)sender didStartProvisionalLoadForFrame:(WebFrame *)frame {
3709 [navbar_ setPrompt:@"Loading..."];
3710 [indicator_ startAnimation];
3713 - (void) applicationWillSuspend {
3715 if (FW_LEAST(1,1,3))
3716 notify_post("com.apple.language.changed");
3718 system("launchctl stop com.apple.SpringBoard");
3720 [super applicationWillSuspend];
3723 - (void) applicationDidFinishLaunching:(id)unused {
3724 _assert(pkgInitConfig(*_config));
3725 _assert(pkgInitSystem(*_config, _system));
3731 CGRect screenrect = [UIHardware fullScreenApplicationContentRect];
3732 window_ = [[UIWindow alloc] initWithContentRect:screenrect];
3734 [window_ orderFront: self];
3735 [window_ makeKey: self];
3736 [window_ _setHidden: NO];
3738 progress_ = [[ProgressView alloc] initWithFrame:[window_ bounds] delegate:self];
3739 [window_ setContentView:progress_];
3741 underlay_ = [[UIView alloc] initWithFrame:[progress_ bounds]];
3742 [progress_ setContentView:underlay_];
3744 overlay_ = [[UIView alloc] initWithFrame:[underlay_ bounds]];
3747 [underlay_ addSubview:overlay_];
3749 transition_ = [[UITransitionView alloc] initWithFrame:CGRectMake(
3750 0, 0, screenrect.size.width, screenrect.size.height - 48
3753 [overlay_ addSubview:transition_];
3755 featured_ = [[UIView alloc] initWithFrame:[transition_ bounds]];
3757 CGSize navsize = [UINavigationBar defaultSizeWithPrompt];
3758 CGRect navrect = {{0, 0}, navsize};
3760 navbar_ = [[UINavigationBar alloc] initWithFrame:navrect];
3761 [featured_ addSubview:navbar_];
3763 [navbar_ setBarStyle:1];
3764 [navbar_ setDelegate:self];
3766 [navbar_ showButtonsWithLeftTitle:@"About" rightTitle:@"Reload"];
3768 UINavigationItem *navitem = [[[UINavigationItem alloc] initWithTitle:@"Featured"] autorelease];
3769 [navbar_ pushNavigationItem:navitem];
3771 struct CGRect subbounds = [featured_ bounds];
3772 subbounds.origin.y += navsize.height;
3773 subbounds.size.height -= navsize.height;
3775 UIImageView *pinstripe = [[[UIImageView alloc] initWithFrame:subbounds] autorelease];
3776 [pinstripe setImage:[UIImage applicationImageNamed:@"pinstripe.png"]];
3777 [featured_ addSubview:pinstripe];
3779 scroller_ = [[UIScroller alloc] initWithFrame:subbounds];
3780 [featured_ addSubview:scroller_];
3782 [scroller_ setScrollingEnabled:YES];
3783 [scroller_ setAdjustForContentSizeChange:YES];
3784 [scroller_ setClipsSubviews:YES];
3785 [scroller_ setAllowsRubberBanding:YES];
3786 [scroller_ setScrollDecelerationFactor:0.99];
3787 [scroller_ setDelegate:self];
3789 CGRect webrect = [scroller_ bounds];
3790 webrect.size.height = 0;
3792 webview_ = [[UIWebView alloc] initWithFrame:webrect];
3793 [scroller_ addSubview:webview_];
3795 [webview_ setTilingEnabled:YES];
3796 [webview_ setTileSize:CGSizeMake(screenrect.size.width, 500)];
3797 [webview_ setAutoresizes:YES];
3798 [webview_ setDelegate:self];
3800 CGSize indsize = [UIProgressIndicator defaultSizeForStyle:2];
3801 indicator_ = [[UIProgressIndicator alloc] initWithFrame:CGRectMake(87, 45, indsize.width, indsize.height)];
3802 [indicator_ setStyle:2];
3803 [featured_ addSubview:indicator_];
3805 NSArray *buttonitems = [NSArray arrayWithObjects:
3806 [NSDictionary dictionaryWithObjectsAndKeys:
3807 @"buttonBarItemTapped:", kUIButtonBarButtonAction,
3808 @"featured-up.png", kUIButtonBarButtonInfo,
3809 @"featured-dn.png", kUIButtonBarButtonSelectedInfo,
3810 [NSNumber numberWithInt:1], kUIButtonBarButtonTag,
3811 self, kUIButtonBarButtonTarget,
3812 @"Featured", kUIButtonBarButtonTitle,
3813 @"0", kUIButtonBarButtonType,
3816 [NSDictionary dictionaryWithObjectsAndKeys:
3817 @"buttonBarItemTapped:", kUIButtonBarButtonAction,
3818 @"install-up.png", kUIButtonBarButtonInfo,
3819 @"install-dn.png", kUIButtonBarButtonSelectedInfo,
3820 [NSNumber numberWithInt:2], kUIButtonBarButtonTag,
3821 self, kUIButtonBarButtonTarget,
3822 @"Install", kUIButtonBarButtonTitle,
3823 @"0", kUIButtonBarButtonType,
3826 [NSDictionary dictionaryWithObjectsAndKeys:
3827 @"buttonBarItemTapped:", kUIButtonBarButtonAction,
3828 @"changes-up.png", kUIButtonBarButtonInfo,
3829 @"changes-dn.png", kUIButtonBarButtonSelectedInfo,
3830 [NSNumber numberWithInt:3], kUIButtonBarButtonTag,
3831 self, kUIButtonBarButtonTarget,
3832 @"Changes", kUIButtonBarButtonTitle,
3833 @"0", kUIButtonBarButtonType,
3836 [NSDictionary dictionaryWithObjectsAndKeys:
3837 @"buttonBarItemTapped:", kUIButtonBarButtonAction,
3838 @"manage-up.png", kUIButtonBarButtonInfo,
3839 @"manage-dn.png", kUIButtonBarButtonSelectedInfo,
3840 [NSNumber numberWithInt:4], kUIButtonBarButtonTag,
3841 self, kUIButtonBarButtonTarget,
3842 @"Uninstall", kUIButtonBarButtonTitle,
3843 @"0", kUIButtonBarButtonType,
3846 [NSDictionary dictionaryWithObjectsAndKeys:
3847 @"buttonBarItemTapped:", kUIButtonBarButtonAction,
3848 @"search-up.png", kUIButtonBarButtonInfo,
3849 @"search-dn.png", kUIButtonBarButtonSelectedInfo,
3850 [NSNumber numberWithInt:5], kUIButtonBarButtonTag,
3851 self, kUIButtonBarButtonTarget,
3852 @"Search", kUIButtonBarButtonTitle,
3853 @"0", kUIButtonBarButtonType,
3857 buttonbar_ = [[UIButtonBar alloc]
3859 withFrame:CGRectMake(
3860 0, screenrect.size.height - 48,
3861 screenrect.size.width, 48
3863 withItemList:buttonitems
3866 [buttonbar_ setDelegate:self];
3867 [buttonbar_ setBarStyle:1];
3868 [buttonbar_ setButtonBarTrackingMode:2];
3870 int buttons[5] = {1, 2, 3, 4, 5};
3871 [buttonbar_ registerButtonGroup:0 withButtons:buttons withCount:5];
3872 [buttonbar_ showButtonGroup:0 withDuration:0];
3874 for (int i = 0; i != 5; ++i)
3875 [[buttonbar_ viewWithTag:(i + 1)] setFrame:CGRectMake(
3876 i * 64 + 2, 1, 60, 48
3879 [buttonbar_ showSelectionForButton:1];
3880 [transition_ transition:0 toView:featured_];
3882 [overlay_ addSubview:buttonbar_];
3884 [UIKeyboard initImplementationNow];
3886 CGRect edtrect = [overlay_ bounds];
3887 edtrect.origin.y += navsize.height;
3888 edtrect.size.height -= navsize.height;
3890 CGSize keysize = [UIKeyboard defaultSize];
3891 CGRect keyrect = {{0, [overlay_ bounds].size.height - keysize.height}, keysize};
3892 keyboard_ = [[UIKeyboard alloc] initWithFrame:keyrect];
3894 database_ = [[Database alloc] init];
3895 [database_ setDelegate:progress_];
3897 install_ = [[InstallView alloc] initWithFrame:[transition_ bounds]];
3898 [install_ setDelegate:self];
3900 changes_ = [[ChangesView alloc] initWithFrame:[transition_ bounds]];
3901 [changes_ setDelegate:self];
3903 manage_ = [[ManageView alloc] initWithFrame:[transition_ bounds]];
3904 [manage_ setDelegate:self];
3906 search_ = [[SearchView alloc] initWithFrame:[transition_ bounds]];
3907 [search_ setDelegate:self];
3909 [self reloadData:NO];
3911 Package *package([database_ packageWithName:@"cydia"]);
3912 NSString *application = package == nil ? @"Cydia" : [NSString
3913 stringWithFormat:@"Cydia/%@",
3917 WebView *webview = [webview_ webView];
3918 [webview setApplicationNameForUserAgent:application];
3919 [webview setFrameLoadDelegate:self];
3921 url_ = [NSURL URLWithString:@"http://cydia.saurik.com/"];
3924 [progress_ resetView];
3930 - (void) showKeyboard:(BOOL)show {
3932 [overlay_ addSubview:keyboard_];
3934 [keyboard_ removeFromSuperview];
3939 void AddPreferences(NSString *plist) {
3940 NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init];
3942 NSMutableDictionary *settings = [[[NSMutableDictionary alloc] initWithContentsOfFile:plist] autorelease];
3943 _assert(settings != NULL);
3944 NSMutableArray *items = [settings objectForKey:@"items"];
3948 for (size_t i(0); i != [items count]; ++i) {
3949 NSMutableDictionary *item([items objectAtIndex:i]);
3950 NSString *label = [item objectForKey:@"label"];
3951 if (label != nil && [label isEqualToString:@"Cydia"]) {
3958 for (size_t i(0); i != [items count]; ++i) {
3959 NSDictionary *item([items objectAtIndex:i]);
3960 NSString *label = [item objectForKey:@"label"];
3961 if (label != nil && [label isEqualToString:@"General"]) {
3962 [items insertObject:[NSDictionary dictionaryWithObjectsAndKeys:
3963 @"CydiaSettings", @"bundle",
3964 @"PSLinkCell", @"cell",
3965 [NSNumber numberWithBool:YES], @"hasIcon",
3966 [NSNumber numberWithBool:YES], @"isController",
3968 nil] atIndex:(i + 1)];
3974 _assert([settings writeToFile:plist atomically:YES] == YES);
3981 id Alloc_(id self, SEL selector) {
3982 id object = alloc_(self, selector);
3983 fprintf(stderr, "[%s]A-%p\n", self->isa->name, object);
3987 int main(int argc, char *argv[]) {
3989 memset(nl, 0, sizeof(nl));
3990 nl[0].n_un.n_name = "_useMDNSResponder";
3991 nlist("/usr/lib/libc.dylib", nl);
3992 if (nl[0].n_type != N_UNDF)
3993 *(int *) nl[0].n_value = 0;
3995 bootstrap_ = argc > 1 && strcmp(argv[1], "--bootstrap") == 0;
4000 /*Method alloc = class_getClassMethod([NSObject class], @selector(alloc));
4001 alloc_ = alloc->method_imp;
4002 alloc->method_imp = (IMP) &Alloc_;*/
4004 NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init];
4006 if (NSDictionary *sysver = [NSDictionary dictionaryWithContentsOfFile:@"/System/Library/CoreServices/SystemVersion.plist"]) {
4007 if (NSString *prover = [sysver valueForKey:@"ProductVersion"]) {
4008 Firmware_ = strdup([prover cString]);
4009 NSArray *versions = [prover componentsSeparatedByString:@"."];
4010 int count = [versions count];
4011 Major_ = count > 0 ? [[versions objectAtIndex:0] intValue] : 0;
4012 Minor_ = count > 1 ? [[versions objectAtIndex:1] intValue] : 0;
4013 BugFix_ = count > 2 ? [[versions objectAtIndex:2] intValue] : 0;
4018 sysctlbyname("hw.machine", NULL, &size, NULL, 0);
4019 char *machine = new char[size];
4020 sysctlbyname("hw.machine", machine, &size, NULL, 0);
4023 if (CFMutableDictionaryRef dict = IOServiceMatching("IOPlatformExpertDevice"))
4024 if (io_service_t service = IOServiceGetMatchingService(kIOMasterPortDefault, dict)) {
4025 if (CFTypeRef serial = IORegistryEntryCreateCFProperty(service, CFSTR(kIOPlatformSerialNumberKey), kCFAllocatorDefault, 0)) {
4026 SerialNumber_ = strdup(CFStringGetCStringPtr((CFStringRef) serial, CFStringGetSystemEncoding()));
4030 IOObjectRelease(service);
4033 /*AddPreferences(@"/Applications/Preferences.app/Settings-iPhone.plist");
4034 AddPreferences(@"/Applications/Preferences.app/Settings-iPod.plist");*/
4036 if ((Metadata_ = [[NSMutableDictionary alloc] initWithContentsOfFile:@"/var/lib/cydia/metadata.plist"]) == NULL)
4037 Metadata_ = [[NSMutableDictionary alloc] initWithCapacity:2];
4039 Packages_ = [Metadata_ objectForKey:@"Packages"];
4041 setenv("CYDIA", "", _not(int));
4042 if (access("/User", F_OK) != 0)
4043 system("/usr/libexec/cydia/firmware.sh");
4044 system("dpkg --configure -a");
4046 UIApplicationMain(argc, argv, [Cydia class]);