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 || [metadata count] == 0) {
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 now_ = [NSDate date];
1993 records_ = new pkgRecords(cache_);
1994 resolver_ = new pkgProblemResolver(cache_);
1995 fetcher_ = new pkgAcquire(&status_);
1998 list_ = new pkgSourceList();
1999 _assert(list_->ReadMainList());
2001 [sources_ removeAllObjects];
2002 for (pkgSourceList::const_iterator source = list_->begin(); source != list_->end(); ++source) {
2003 std::vector<pkgIndexFile *> *indices = (*source)->GetIndexFiles();
2004 for (std::vector<pkgIndexFile *>::const_iterator index = indices->begin(); index != indices->end(); ++index)
2006 setObject:[[[Source alloc] initWithMetaIndex:*source] autorelease]
2007 forKey:[NSNumber numberWithLong:reinterpret_cast<uintptr_t>(*index)]
2011 [packages_ removeAllObjects];
2012 for (pkgCache::PkgIterator iterator = cache_->PkgBegin(); !iterator.end(); ++iterator)
2013 if (Package *package = [Package packageWithIterator:iterator database:self])
2014 [packages_ addObject:package];
2018 pkgRecords records(cache_);
2020 lock_ = new FileFd();
2021 lock_->Fd(GetLock(_config->FindDir("Dir::Cache::Archives") + "lock"));
2022 _assert(!_error->PendingError());
2025 _assert(list.ReadMainList());
2027 manager_ = (_system->CreatePM(cache_));
2028 _assert(manager_->GetArchives(fetcher_, &list, &records));
2029 _assert(!_error->PendingError());
2033 if (fetcher_->Run(PulseInterval_) != pkgAcquire::Continue)
2037 pkgPackageManager::OrderResult result = manager_->DoInstall(statusfd_);
2039 if (result == pkgPackageManager::Failed)
2041 if (_error->PendingError())
2043 if (result != pkgPackageManager::Completed)
2049 _assert(list.ReadMainList());
2052 lock.Fd(GetLock(_config->FindDir("Dir::State::Lists") + "lock"));
2053 _assert(!_error->PendingError());
2055 pkgAcquire fetcher(&status_);
2056 _assert(list.GetIndexes(&fetcher));
2057 _assert(fetcher.Run(PulseInterval_) != pkgAcquire::Failed);
2059 bool failed = false;
2060 for (pkgAcquire::ItemIterator item = fetcher.ItemsBegin(); item != fetcher.ItemsEnd(); item++)
2061 if ((*item)->Status != pkgAcquire::Item::StatDone) {
2062 (*item)->Finished();
2066 if (!failed && _config->FindB("APT::Get::List-Cleanup", true) == true) {
2067 _assert(fetcher.Clean(_config->FindDir("Dir::State::lists")));
2068 _assert(fetcher.Clean(_config->FindDir("Dir::State::lists") + "partial/"));
2071 [Metadata_ setObject:[NSDate date] forKey:@"LastUpdate"];
2075 _assert(cache_->DelCount() == 0 && cache_->InstCount() == 0);
2076 _assert(pkgApplyStatus(cache_));
2078 if (cache_->BrokenCount() != 0) {
2079 _assert(pkgFixBroken(cache_));
2080 _assert(cache_->BrokenCount() == 0);
2081 _assert(pkgMinimizeUpgrade(cache_));
2084 _assert(pkgDistUpgrade(cache_));
2087 - (void) setDelegate:(id)delegate {
2088 delegate_ = delegate;
2089 status_.setDelegate(delegate);
2090 progress_.setDelegate(delegate);
2093 - (Source *) getSource:(const pkgCache::PkgFileIterator &)file {
2094 pkgIndexFile *index(NULL);
2095 list_->FindIndex(file, index);
2096 return [sources_ objectForKey:[NSNumber numberWithLong:reinterpret_cast<uintptr_t>(index)]];
2102 /* Progress Data {{{ */
2103 @interface ProgressData : NSObject {
2109 - (ProgressData *) initWithSelector:(SEL)selector target:(id)target object:(id)object;
2116 @implementation ProgressData
2118 - (ProgressData *) initWithSelector:(SEL)selector target:(id)target object:(id)object {
2119 if ((self = [super init]) != nil) {
2120 selector_ = selector;
2140 /* Progress View {{{ */
2141 @interface ProgressView : UIView <
2145 UIView *background_;
2146 UITransitionView *transition_;
2148 UINavigationBar *navbar_;
2149 UIProgressBar *progress_;
2150 UITextView *output_;
2151 UITextLabel *status_;
2157 - (void) transitionViewDidComplete:(UITransitionView*)view fromView:(UIView*)from toView:(UIView*)to;
2159 - (ProgressView *) initWithFrame:(struct CGRect)frame delegate:(id)delegate;
2160 - (void) setContentView:(UIView *)view;
2163 - (void) alertSheet:(UIAlertSheet *)sheet buttonClicked:(int)button;
2165 - (void) _retachThread;
2166 - (void) _detachNewThreadData:(ProgressData *)data;
2167 - (void) detachNewThreadSelector:(SEL)selector toTarget:(id)target withObject:(id)object title:(NSString *)title;
2169 - (void) setError:(NSString *)error;
2170 - (void) _setError:(NSString *)error;
2172 - (void) setTitle:(NSString *)title;
2173 - (void) _setTitle:(NSString *)title;
2175 - (void) setPercent:(float)percent;
2176 - (void) _setPercent:(NSNumber *)percent;
2178 - (void) addOutput:(NSString *)output;
2179 - (void) _addOutput:(NSString *)output;
2182 @protocol ProgressViewDelegate
2183 - (void) progressViewIsComplete:(ProgressView *)sender;
2186 @implementation ProgressView
2190 if (background_ != nil)
2191 [background_ release];
2192 [transition_ release];
2195 [progress_ release];
2201 - (void) transitionViewDidComplete:(UITransitionView*)view fromView:(UIView*)from toView:(UIView*)to {
2202 if (bootstrap_ && from == overlay_ && to == view_)
2206 - (ProgressView *) initWithFrame:(struct CGRect)frame delegate:(id)delegate {
2207 if ((self = [super initWithFrame:frame]) != nil) {
2208 delegate_ = delegate;
2210 CGColorSpaceRef space = CGColorSpaceCreateDeviceRGB();
2212 CGColor black(space, 0.0, 0.0, 0.0, 1.0);
2213 CGColor white(space, 1.0, 1.0, 1.0, 1.0);
2214 CGColor clear(space, 0.0, 0.0, 0.0, 0.0);
2216 transition_ = [[UITransitionView alloc] initWithFrame:[self bounds]];
2217 [transition_ setDelegate:self];
2219 overlay_ = [[UIView alloc] initWithFrame:[transition_ bounds]];
2222 [overlay_ setBackgroundColor:black];
2224 background_ = [[UIView alloc] initWithFrame:[self bounds]];
2225 [background_ setBackgroundColor:black];
2226 [self addSubview:background_];
2229 [self addSubview:transition_];
2231 CGSize navsize = [UINavigationBar defaultSize];
2232 CGRect navrect = {{0, 0}, navsize};
2234 navbar_ = [[UINavigationBar alloc] initWithFrame:navrect];
2235 [overlay_ addSubview:navbar_];
2237 [navbar_ setBarStyle:1];
2238 [navbar_ setDelegate:self];
2240 UINavigationItem *navitem = [[[UINavigationItem alloc] initWithTitle:nil] autorelease];
2241 [navbar_ pushNavigationItem:navitem];
2243 CGRect bounds = [overlay_ bounds];
2244 CGSize prgsize = [UIProgressBar defaultSize];
2247 (bounds.size.width - prgsize.width) / 2,
2248 bounds.size.height - prgsize.height - 20
2251 progress_ = [[UIProgressBar alloc] initWithFrame:prgrect];
2252 [overlay_ addSubview:progress_];
2254 status_ = [[UITextLabel alloc] initWithFrame:CGRectMake(
2256 bounds.size.height - prgsize.height - 50,
2257 bounds.size.width - 20,
2261 [status_ setColor:white];
2262 [status_ setBackgroundColor:clear];
2264 [status_ setCentersHorizontally:YES];
2265 //[status_ setFont:font];
2267 output_ = [[UITextView alloc] initWithFrame:CGRectMake(
2269 navrect.size.height + 20,
2270 bounds.size.width - 20,
2271 bounds.size.height - navsize.height - 62 - navrect.size.height
2274 //[output_ setTextFont:@"Courier New"];
2275 [output_ setTextSize:12];
2277 [output_ setTextColor:white];
2278 [output_ setBackgroundColor:clear];
2280 [output_ setMarginTop:0];
2281 [output_ setAllowsRubberBanding:YES];
2283 [overlay_ addSubview:output_];
2284 [overlay_ addSubview:status_];
2286 [progress_ setStyle:0];
2288 CGColorSpaceRelease(space);
2292 - (void) setContentView:(UIView *)view {
2293 view_ = [view retain];
2296 - (void) resetView {
2297 [transition_ transition:6 toView:view_];
2300 - (void) alertSheet:(UIAlertSheet *)sheet buttonClicked:(int)button {
2304 - (void) _retachThread {
2305 [delegate_ progressViewIsComplete:self];
2309 - (void) _detachNewThreadData:(ProgressData *)data {
2310 NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init];
2312 [[data target] performSelector:[data selector] withObject:[data object]];
2315 [self performSelectorOnMainThread:@selector(_retachThread) withObject:nil waitUntilDone:YES];
2320 - (void) detachNewThreadSelector:(SEL)selector toTarget:(id)target withObject:(id)object title:(NSString *)title {
2321 [navbar_ popNavigationItem];
2322 UINavigationItem *navitem = [[[UINavigationItem alloc] initWithTitle:title] autorelease];
2323 [navbar_ pushNavigationItem:navitem];
2325 [status_ setText:nil];
2326 [output_ setText:@""];
2327 [progress_ setProgress:0];
2329 [transition_ transition:6 toView:overlay_];
2332 detachNewThreadSelector:@selector(_detachNewThreadData:)
2334 withObject:[[ProgressData alloc]
2335 initWithSelector:selector
2342 - (void) setError:(NSString *)error {
2344 performSelectorOnMainThread:@selector(_setError:)
2350 - (void) _setError:(NSString *)error {
2351 UIAlertSheet *sheet = [[[UIAlertSheet alloc]
2352 initWithTitle:@"Package Error"
2353 buttons:[NSArray arrayWithObjects:@"Okay", nil]
2354 defaultButtonIndex:0
2359 [sheet setBodyText:error];
2360 [sheet popupAlertAnimated:YES];
2363 - (void) setTitle:(NSString *)title {
2365 performSelectorOnMainThread:@selector(_setTitle:)
2371 - (void) _setTitle:(NSString *)title {
2372 [status_ setText:[title stringByAppendingString:@"..."]];
2375 - (void) setPercent:(float)percent {
2377 performSelectorOnMainThread:@selector(_setPercent:)
2378 withObject:[NSNumber numberWithFloat:percent]
2383 - (void) _setPercent:(NSNumber *)percent {
2384 [progress_ setProgress:[percent floatValue]];
2387 - (void) addOutput:(NSString *)output {
2389 performSelectorOnMainThread:@selector(_addOutput:)
2395 - (void) _addOutput:(NSString *)output {
2396 [output_ setText:[NSString stringWithFormat:@"%@\n%@", [output_ text], output]];
2397 CGSize size = [output_ contentSize];
2398 CGRect rect = {{0, size.height}, {size.width, 0}};
2399 [output_ scrollRectToVisible:rect animated:YES];
2405 /* Package Table {{{ */
2406 @protocol PackageTableDelegate
2407 - (void) packageTable:(id)table packageSelected:(Package *)package;
2410 @interface PackageTable : UIView {
2412 UISectionList *list_;
2416 NSMutableArray *sections_;
2421 - (int) numberOfSectionsInSectionList:(UISectionList *)list;
2422 - (NSString *) sectionList:(UISectionList *)list titleForSection:(int)section;
2423 - (int) sectionList:(UISectionList *)list rowForSection:(int)section;
2425 - (int) numberOfRowsInTable:(UITable *)table;
2426 - (float) table:(UITable *)table heightForRow:(int)row;
2427 - (UITableCell *) table:(UITable *)table cellForRow:(int)row column:(UITableColumn *)col reusing:(UITableCell *)reusing;
2428 - (BOOL) table:(UITable *)table showDisclosureForRow:(int)row;
2429 - (void) tableRowSelected:(NSNotification *)notification;
2431 - (id) initWithFrame:(CGRect)frame versioner:(SEL)versioner;
2433 - (void) setDelegate:(id)delegate;
2434 - (void) setPackages:(NSArray *)packages;
2436 - (void) resetViewAnimated:(BOOL)animated;
2437 - (UITable *) table;
2440 @implementation PackageTable
2444 [sections_ release];
2445 if (packages_ != nil)
2446 [packages_ release];
2450 - (int) numberOfSectionsInSectionList:(UISectionList *)list {
2451 return [sections_ count];
2454 - (NSString *) sectionList:(UISectionList *)list titleForSection:(int)section {
2455 return [[sections_ objectAtIndex:section] name];
2458 - (int) sectionList:(UISectionList *)list rowForSection:(int)section {
2459 return [[sections_ objectAtIndex:section] row];
2462 - (int) numberOfRowsInTable:(UITable *)table {
2463 return [packages_ count];
2466 - (float) table:(UITable *)table heightForRow:(int)row {
2470 - (UITableCell *) table:(UITable *)table cellForRow:(int)row column:(UITableColumn *)col reusing:(UITableCell *)reusing {
2472 reusing = [[[PackageCell alloc] initWithVersioner:versioner_] autorelease];
2473 [(PackageCell *)reusing setPackage:[packages_ objectAtIndex:row]];
2477 - (BOOL) table:(UITable *)table showDisclosureForRow:(int)row {
2481 - (void) tableRowSelected:(NSNotification *)notification {
2482 int row = [[notification object] selectedRow];
2483 [delegate_ packageTable:self packageSelected:(row == INT_MAX ? nil : [packages_ objectAtIndex:row])];
2486 - (id) initWithFrame:(CGRect)frame versioner:(SEL)versioner {
2487 if ((self = [super initWithFrame:frame]) != nil) {
2488 versioner_ = versioner;
2489 sections_ = [[NSMutableArray arrayWithCapacity:16] retain];
2491 list_ = [[UISectionList alloc] initWithFrame:[self bounds] showSectionIndex:YES];
2492 [list_ setDataSource:self];
2494 UITableColumn *column = [[[UITableColumn alloc]
2495 initWithTitle:@"Name"
2497 width:frame.size.width
2500 UITable *table = [list_ table];
2501 [table setSeparatorStyle:1];
2502 [table addTableColumn:column];
2503 [table setDelegate:self];
2504 [table setReusesTableCells:YES];
2506 [self addSubview:list_];
2510 - (void) setDelegate:(id)delegate {
2511 delegate_ = delegate;
2514 - (void) setPackages:(NSArray *)packages {
2515 if (packages_ != nil)
2516 [packages_ autorelease];
2517 _assert(packages != nil);
2518 packages_ = [packages retain];
2520 [sections_ removeAllObjects];
2522 Section *section = nil;
2524 for (size_t offset(0); offset != [packages_ count]; ++offset) {
2525 Package *package = [packages_ objectAtIndex:offset];
2526 NSString *name = [package index];
2528 if (section == nil || ![[section name] isEqual:name]) {
2529 section = [[[Section alloc] initWithName:name row:offset] autorelease];
2530 [sections_ addObject:section];
2533 [section addPackage:package];
2539 - (void) resetViewAnimated:(BOOL)animated {
2540 [[list_ table] selectRow:-1 byExtendingSelection:NO withFade:animated];
2543 - (UITable *) table {
2544 return [list_ table];
2550 /* Section Cell {{{ */
2551 @interface SectionCell : UITableCell {
2553 UITextLabel *count_;
2559 - (void) setSection:(Section *)section;
2561 - (void) _setSelected:(float)fraction;
2562 - (void) setSelected:(BOOL)selected;
2563 - (void) setSelected:(BOOL)selected withFade:(BOOL)fade;
2564 - (void) _setSelectionFadeFraction:(float)fraction;
2568 @implementation SectionCell
2577 if ((self = [super init]) != nil) {
2578 GSFontRef bold = GSFontCreateWithName("Helvetica", kGSFontTraitBold, 22);
2579 GSFontRef small = GSFontCreateWithName("Helvetica", kGSFontTraitBold, 12);
2581 CGColorSpaceRef space = CGColorSpaceCreateDeviceRGB();
2582 CGColor clear(space, 0, 0, 0, 0);
2583 CGColor white(space, 1, 1, 1, 1);
2585 name_ = [[UITextLabel alloc] initWithFrame:CGRectMake(48, 9, 250, 25)];
2586 [name_ setBackgroundColor:clear];
2587 [name_ setFont:bold];
2589 count_ = [[UITextLabel alloc] initWithFrame:CGRectMake(11, 7, 29, 32)];
2590 [count_ setCentersHorizontally:YES];
2591 [count_ setBackgroundColor:clear];
2592 [count_ setFont:small];
2593 [count_ setColor:white];
2595 UIImageView *folder = [[[UIImageView alloc] initWithFrame:CGRectMake(8, 7, 32, 32)] autorelease];
2596 [folder setImage:[UIImage applicationImageNamed:@"folder.png"]];
2598 [self addSubview:folder];
2599 [self addSubview:name_];
2600 [self addSubview:count_];
2602 [self _setSelected:0];
2604 CGColorSpaceRelease(space);
2611 - (void) setSection:(Section *)section {
2612 if (section == nil) {
2613 [name_ setText:@"All Packages"];
2614 [count_ setText:nil];
2616 NSString *name = [section name];
2617 [name_ setText:(name == nil ? @"(No Section)" : name)];
2618 [count_ setText:[NSString stringWithFormat:@"%d", [section count]]];
2622 - (void) _setSelected:(float)fraction {
2623 CGColorSpaceRef space = CGColorSpaceCreateDeviceRGB();
2625 CGColor black(space,
2626 interpolate(0.0, 1.0, fraction),
2627 interpolate(0.0, 1.0, fraction),
2628 interpolate(0.0, 1.0, fraction),
2631 [name_ setColor:black];
2633 CGColorSpaceRelease(space);
2636 - (void) setSelected:(BOOL)selected {
2637 [self _setSelected:(selected ? 1.0 : 0.0)];
2638 [super setSelected:selected];
2641 - (void) setSelected:(BOOL)selected withFade:(BOOL)fade {
2643 [self _setSelected:(selected ? 1.0 : 0.0)];
2644 [super setSelected:selected withFade:fade];
2647 - (void) _setSelectionFadeFraction:(float)fraction {
2648 [self _setSelected:fraction];
2649 [super _setSelectionFadeFraction:fraction];
2654 /* Install View {{{ */
2655 @interface InstallView : ResetView <
2656 PackageTableDelegate
2660 PackageTable *table_;
2664 NSMutableArray *packages_;
2669 - (void) navigationBar:(UINavigationBar *)navbar buttonClicked:(int)button;
2671 - (int) numberOfRowsInTable:(UITable *)table;
2672 - (float) table:(UITable *)table heightForRow:(int)row;
2673 - (UITableCell *) table:(UITable *)table cellForRow:(int)row column:(UITableColumn *)col reusing:(UITableCell *)reusing;
2674 - (BOOL) table:(UITable *)table showDisclosureForRow:(int)row;
2675 - (void) tableRowSelected:(NSNotification *)notification;
2677 - (void) packageTable:(id)table packageSelected:(Package *)package;
2679 - (id) initWithFrame:(CGRect)frame;
2680 - (void) setPackages:(NSArray *)packages;
2681 - (void) setDelegate:(id)delegate;
2684 @implementation InstallView
2687 [packages_ release];
2688 if (sections_ != nil)
2689 [sections_ release];
2696 if (section_ != nil)
2698 if (package_ != nil)
2703 - (void) navigationBar:(UINavigationBar *)navbar buttonClicked:(int)button {
2705 [[view_ package] install];
2706 [delegate_ resolve];
2707 [delegate_ perform];
2711 - (int) numberOfRowsInTable:(UITable *)table {
2712 return [sections_ count] + 1;
2715 - (float) table:(UITable *)table heightForRow:(int)row {
2719 - (UITableCell *) table:(UITable *)table cellForRow:(int)row column:(UITableColumn *)col reusing:(UITableCell *)reusing {
2721 reusing = [[[SectionCell alloc] init] autorelease];
2723 [(SectionCell *)reusing setSection:nil];
2725 [(SectionCell *)reusing setSection:[sections_ objectAtIndex:(row - 1)]];
2729 - (BOOL) table:(UITable *)table showDisclosureForRow:(int)row {
2733 - (void) tableRowSelected:(NSNotification *)notification {
2734 int row = [[notification object] selectedRow];
2736 if (row == INT_MAX) {
2743 _assert(section_ == nil);
2744 _assert(table_ == nil);
2752 name = @"All Packages";
2754 section = [sections_ objectAtIndex:(row - 1)];
2755 name = [section name];
2756 section_ = [name retain];
2759 table_ = [[PackageTable alloc] initWithFrame:[transition_ bounds] versioner:@selector(latest)];
2760 [table_ setDelegate:self];
2761 [table_ setPackages:(section == nil ? packages_ : [section packages])];
2763 [self pushView:table_ withTitle:name backButtonTitle:@"Packages" rightButton:nil];
2767 - (void) packageTable:(id)table packageSelected:(Package *)package {
2768 if (package == nil) {
2775 _assert(package_ == nil);
2776 _assert(view_ == nil);
2778 package_ = [[package name] retain];
2780 view_ = [[PackageView alloc] initWithFrame:[transition_ bounds]];
2781 [view_ setDelegate:delegate_];
2783 [view_ setPackage:package];
2785 [self pushView:view_ withTitle:[package name] backButtonTitle:nil rightButton:@"Install"];
2789 - (id) initWithFrame:(CGRect)frame {
2790 if ((self = [super initWithFrame:frame]) != nil) {
2791 packages_ = [[NSMutableArray arrayWithCapacity:16] retain];
2793 list_ = [[UITable alloc] initWithFrame:[transition_ bounds]];
2794 [self pushView:list_ withTitle:@"Install" backButtonTitle:@"Sections" rightButton:nil];
2796 UITableColumn *column = [[[UITableColumn alloc]
2797 initWithTitle:@"Name"
2799 width:frame.size.width
2802 [list_ setDataSource:self];
2803 [list_ setSeparatorStyle:1];
2804 [list_ addTableColumn:column];
2805 [list_ setDelegate:self];
2806 [list_ setReusesTableCells:YES];
2808 [transition_ transition:0 toView:list_];
2812 - (void) setPackages:(NSArray *)packages {
2813 [packages_ removeAllObjects];
2815 for (size_t i(0); i != [packages count]; ++i) {
2816 Package *package([packages objectAtIndex:i]);
2817 if ([package installed] == nil)
2818 [packages_ addObject:package];
2821 [packages_ sortUsingSelector:@selector(compareBySectionAndName:)];
2822 NSMutableArray *sections = [NSMutableArray arrayWithCapacity:16];
2824 Section *nsection = nil;
2825 Package *npackage = nil;
2827 Section *section = nil;
2828 for (size_t offset = 0, count = [packages_ count]; offset != count; ++offset) {
2829 Package *package = [packages_ objectAtIndex:offset];
2830 NSString *name = [package section];
2832 if (section == nil || name != nil && ![[section name] isEqual:name]) {
2833 section = [[[Section alloc] initWithName:name row:offset] autorelease];
2835 if (name == nil || [name isEqualToString:section_])
2837 [sections addObject:section];
2840 if ([[package name] isEqualToString:package_])
2842 [section addPackage:package];
2845 if (sections_ != nil)
2846 [sections_ release];
2847 sections_ = [sections retain];
2849 [packages_ sortUsingSelector:@selector(compareByName:)];
2855 if (npackage != nil)
2856 [view_ setPackage:npackage];
2857 else if (package_ != nil)
2860 if (table_ != nil && section_ == nil)
2861 [table_ setPackages:packages_];
2862 else if (nsection != nil)
2863 [table_ setPackages:[nsection packages]];
2864 else if (section_ != nil)
2868 [self popViews:views];
2872 - (void) setDelegate:(id)delegate {
2874 [view_ setDelegate:delegate];
2875 [super setDelegate:delegate];
2880 /* Changes View {{{ */
2881 @interface ChangesView : ResetView <
2882 PackageTableDelegate
2884 UISectionList *list_;
2885 NSMutableArray *packages_;
2886 NSMutableArray *sections_;
2894 - (void) navigationBar:(UINavigationBar *)navbar buttonClicked:(int)button;
2896 - (int) numberOfSectionsInSectionList:(UISectionList *)list;
2897 - (NSString *) sectionList:(UISectionList *)list titleForSection:(int)section;
2898 - (int) sectionList:(UISectionList *)list rowForSection:(int)section;
2900 - (int) numberOfRowsInTable:(UITable *)table;
2901 - (float) table:(UITable *)table heightForRow:(int)row;
2902 - (UITableCell *) table:(UITable *)table cellForRow:(int)row column:(UITableColumn *)col reusing:(UITableCell *)reusing;
2903 - (BOOL) table:(UITable *)table showDisclosureForRow:(int)row;
2904 - (void) tableRowSelected:(NSNotification *)notification;
2906 - (id) initWithFrame:(CGRect)frame;
2907 - (void) setPackages:(NSArray *)packages;
2908 - (void) _resetView;
2911 - (void) setDelegate:(id)delegate;
2914 @implementation ChangesView
2918 [packages_ release];
2919 [sections_ release];
2922 if (package_ != nil)
2927 - (int) numberOfSectionsInSectionList:(UISectionList *)list {
2928 return [sections_ count];
2931 - (NSString *) sectionList:(UISectionList *)list titleForSection:(int)section {
2932 return [[sections_ objectAtIndex:section] name];
2935 - (int) sectionList:(UISectionList *)list rowForSection:(int)section {
2936 return [[sections_ objectAtIndex:section] row];
2939 - (int) numberOfRowsInTable:(UITable *)table {
2940 return [packages_ count];
2943 - (float) table:(UITable *)table heightForRow:(int)row {
2947 - (UITableCell *) table:(UITable *)table cellForRow:(int)row column:(UITableColumn *)col reusing:(UITableCell *)reusing {
2949 reusing = [[[PackageCell alloc] initWithVersioner:NULL] autorelease];
2950 [(PackageCell *)reusing setPackage:[packages_ objectAtIndex:row]];
2954 - (BOOL) table:(UITable *)table showDisclosureForRow:(int)row {
2958 - (void) tableRowSelected:(NSNotification *)notification {
2959 int row = [[notification object] selectedRow];
2960 [self packageTable:self packageSelected:(row == INT_MAX ? nil : [packages_ objectAtIndex:row])];
2963 - (void) navigationBar:(UINavigationBar *)navbar buttonClicked:(int)button {
2966 [[view_ package] install];
2967 [delegate_ resolve];
2968 [delegate_ perform];
2972 [delegate_ upgrade];
2977 - (void) packageTable:(id)table packageSelected:(Package *)package {
2978 if (package == nil) {
2985 _assert(package_ == nil);
2986 _assert(view_ == nil);
2988 package_ = [[package name] retain];
2990 view_ = [[PackageView alloc] initWithFrame:[transition_ bounds]];
2991 [view_ setDelegate:delegate_];
2993 [view_ setPackage:package];
2995 [self pushView:view_ withTitle:[package name] backButtonTitle:nil rightButton:(
2996 [package upgradable] ? @"Upgrade" : @"Install"
3001 - (id) initWithFrame:(CGRect)frame {
3002 if ((self = [super initWithFrame:frame]) != nil) {
3003 packages_ = [[NSMutableArray arrayWithCapacity:16] retain];
3004 sections_ = [[NSMutableArray arrayWithCapacity:16] retain];
3006 list_ = [[UISectionList alloc] initWithFrame:[transition_ bounds] showSectionIndex:NO];
3007 [list_ setShouldHideHeaderInShortLists:NO];
3008 [list_ setDataSource:self];
3009 //[list_ setSectionListStyle:1];
3011 UITableColumn *column = [[[UITableColumn alloc]
3012 initWithTitle:@"Name"
3014 width:frame.size.width
3017 UITable *table = [list_ table];
3018 [table setSeparatorStyle:1];
3019 [table addTableColumn:column];
3020 [table setDelegate:self];
3021 [table setReusesTableCells:YES];
3023 [self pushView:list_ withTitle:@"Changes" backButtonTitle:nil rightButton:nil];
3027 - (void) setPackages:(NSArray *)packages {
3028 [packages_ removeAllObjects];
3029 for (size_t i(0); i != [packages count]; ++i) {
3030 Package *package([packages objectAtIndex:i]);
3031 if ([package installed] == nil || [package upgradable])
3032 [packages_ addObject:package];
3035 [packages_ sortUsingSelector:@selector(compareForChanges:)];
3037 [sections_ removeAllObjects];
3039 Section *upgradable = [[[Section alloc] initWithName:@"Available Upgrades" row:0] autorelease];
3040 Section *section = nil;
3043 Package *npackage = nil;
3044 for (size_t offset = 0, count = [packages_ count]; offset != count; ++offset) {
3045 Package *package = [packages_ objectAtIndex:offset];
3046 if ([[package name] isEqualToString:package_])
3049 if ([package upgradable])
3050 [upgradable addPackage:package];
3052 NSDate *seen = [package seen];
3055 CFStringRef formatted = NULL;
3060 CFLocaleRef locale = CFLocaleCopyCurrent();
3061 CFDateFormatterRef formatter = CFDateFormatterCreate(NULL, locale, kCFDateFormatterMediumStyle, kCFDateFormatterMediumStyle);
3062 formatted = CFDateFormatterCreateStringWithDate(NULL, formatter, (CFDateRef) seen);
3063 name = (NSString *) formatted;
3064 CFRelease(formatter);
3068 if (section == nil || ![[section name] isEqual:name]) {
3069 section = [[[Section alloc] initWithName:name row:offset] autorelease];
3070 [sections_ addObject:section];
3073 [section addPackage:package];
3075 if (formatted != NULL)
3076 CFRelease(formatted);
3080 count_ = [[upgradable packages] count];
3082 [sections_ insertObject:upgradable atIndex:0];
3086 if (npackage != nil)
3087 [view_ setPackage:npackage];
3088 else if (package_ != nil)
3095 - (void) _resetView {
3096 if ([views_ count] == 1)
3097 [navbar_ showButtonsWithLeftTitle:(count_ == 0 ? nil : @"Upgrade All") rightTitle:nil];
3104 - (void) setDelegate:(id)delegate {
3106 [view_ setDelegate:delegate];
3107 [super setDelegate:delegate];
3112 /* Manage View {{{ */
3113 @interface ManageView : ResetView <
3114 PackageTableDelegate
3116 PackageTable *table_;
3123 - (void) navigationBar:(UINavigationBar *)navbar buttonClicked:(int)button;
3125 - (void) packageTable:(id)table packageSelected:(Package *)package;
3127 - (id) initWithFrame:(CGRect)frame;
3128 - (void) setPackages:(NSArray *)packages;
3130 - (void) setDelegate:(id)delegate;
3133 @implementation ManageView
3139 if (package_ != nil)
3144 - (void) navigationBar:(UINavigationBar *)navbar buttonClicked:(int)button {
3146 [[view_ package] remove];
3147 [delegate_ resolve];
3148 [delegate_ perform];
3152 - (void) packageTable:(id)table packageSelected:(Package *)package {
3153 if (package == nil) {
3160 _assert(package_ == nil);
3161 _assert(view_ == nil);
3163 package_ = [[package name] retain];
3165 view_ = [[PackageView alloc] initWithFrame:[transition_ bounds]];
3166 [view_ setDelegate:delegate_];
3168 [view_ setPackage:package];
3170 [self pushView:view_ withTitle:[package name] backButtonTitle:nil rightButton:@"Uninstall"];
3174 - (id) initWithFrame:(CGRect)frame {
3175 if ((self = [super initWithFrame:frame]) != nil) {
3176 table_ = [[PackageTable alloc] initWithFrame:[transition_ bounds] versioner:@selector(latest)];
3177 [table_ setDelegate:self];
3179 [self pushView:table_ withTitle:@"Uninstall" backButtonTitle:@"Packages" rightButton:nil];
3183 - (void) setPackages:(NSArray *)packages {
3184 NSMutableArray *local = [NSMutableArray arrayWithCapacity:16];
3185 for (size_t i(0); i != [packages count]; ++i) {
3186 Package *package([packages objectAtIndex:i]);
3187 if ([package installed] != nil)
3188 [local addObject:package];
3191 [local sortUsingSelector:@selector(compareByName:)];
3193 Package *npackage = nil;
3194 for (size_t offset = 0, count = [local count]; offset != count; ++offset) {
3195 Package *package = [local objectAtIndex:offset];
3196 if ([[package name] isEqualToString:package_])
3200 [table_ setPackages:local];
3202 if (npackage != nil)
3203 [view_ setPackage:npackage];
3204 else if (package_ != nil)
3210 - (void) setDelegate:(id)delegate {
3212 [view_ setDelegate:delegate];
3213 [super setDelegate:delegate];
3218 /* Search View {{{ */
3219 @protocol SearchViewDelegate
3220 - (void) showKeyboard:(BOOL)show;
3223 @interface SearchView : ResetView <
3224 PackageTableDelegate
3226 NSMutableArray *packages_;
3228 UISearchField *field_;
3229 PackageTable *table_;
3236 - (void) navigationBar:(UINavigationBar *)navbar buttonClicked:(int)button;
3237 - (void) packageTable:(id)table packageSelected:(Package *)package;
3239 - (void) textFieldDidBecomeFirstResponder:(UITextField *)field;
3240 - (void) textFieldDidResignFirstResponder:(UITextField *)field;
3242 - (void) keyboardInputChanged:(UIFieldEditor *)editor;
3243 - (BOOL) keyboardInput:(id)input shouldInsertText:(NSString *)text isMarkedText:(int)marked;
3245 - (id) initWithFrame:(CGRect)frame;
3246 - (void) setPackages:(NSArray *)packages;
3248 - (void) setDelegate:(id)delegate;
3249 - (void) resetPackage:(Package *)package;
3250 - (void) searchPackages;
3254 @implementation SearchView
3257 [packages_ release];
3258 [accessory_ release];
3263 if (package_ != nil)
3268 - (void) navigationBar:(UINavigationBar *)navbar buttonClicked:(int)button {
3270 Package *package = [view_ package];
3271 if ([package installed] == nil)
3275 [delegate_ resolve];
3276 [delegate_ perform];
3280 - (void) packageTable:(id)table packageSelected:(Package *)package {
3281 if (package == nil) {
3282 [navbar_ setAccessoryView:accessory_ animate:(resetting_ ? NO : YES) goingBack:YES];
3290 [navbar_ setAccessoryView:nil animate:YES goingBack:NO];
3292 _assert(package_ == nil);
3293 _assert(view_ == nil);
3295 package_ = [[package name] retain];
3297 view_ = [[PackageView alloc] initWithFrame:[transition_ bounds]];
3298 [view_ setDelegate:delegate_];
3300 [self pushView:view_ withTitle:[package name] backButtonTitle:nil rightButton:nil];
3301 [self resetPackage:package];
3305 - (void) textFieldDidBecomeFirstResponder:(UITextField *)field {
3306 [delegate_ showKeyboard:YES];
3307 [table_ setEnabled:NO];
3309 /*CGColorSpaceRef space = CGColorSpaceCreateDeviceRGB();
3310 CGColor dimmed(alpha, 0, 0, 0, 0.5);
3311 [editor_ setBackgroundColor:dimmed];
3312 CGColorSpaceRelease(space);*/
3315 - (void) textFieldDidResignFirstResponder:(UITextField *)field {
3316 [table_ setEnabled:YES];
3317 [delegate_ showKeyboard:NO];
3320 - (void) keyboardInputChanged:(UIFieldEditor *)editor {
3321 NSString *text([field_ text]);
3322 [field_ setClearButtonStyle:(text == nil || [text length] == 0 ? 0 : 2)];
3325 - (BOOL) keyboardInput:(id)input shouldInsertText:(NSString *)text isMarkedText:(int)marked {
3326 if ([text length] != 1 || [text characterAtIndex:0] != '\n')
3329 [self searchPackages];
3330 [field_ resignFirstResponder];
3334 - (id) initWithFrame:(CGRect)frame {
3335 if ((self = [super initWithFrame:frame]) != nil) {
3336 packages_ = [[NSMutableArray arrayWithCapacity:16] retain];
3338 table_ = [[PackageTable alloc] initWithFrame:[transition_ bounds] versioner:@selector(latest)];
3339 [table_ setDelegate:self];
3341 CGRect area = [self bounds];
3344 area.size.width -= 12;
3345 area.size.height = [UISearchField defaultHeight];
3347 field_ = [[UISearchField alloc] initWithFrame:area];
3349 GSFontRef font = GSFontCreateWithName("Helvetica", kGSFontTraitNone, 16);
3350 [field_ setFont:font];
3353 [field_ setPlaceholder:@"Package Names & Descriptions"];
3354 [field_ setPaddingTop:5];
3355 [field_ setDelegate:self];
3357 UITextTraits *traits = [field_ textTraits];
3358 [traits setEditingDelegate:self];
3359 [traits setReturnKeyType:6];
3361 accessory_ = [[UIView alloc] initWithFrame:CGRectMake(6, 6, area.size.width, area.size.height + 30)];
3362 [accessory_ addSubview:field_];
3364 [navbar_ setAccessoryView:accessory_];
3365 [self pushView:table_ withTitle:nil backButtonTitle:@"Search" rightButton:nil];
3367 /* XXX: for the love of god just fix this */
3368 [navbar_ removeFromSuperview];
3369 [reload_ removeFromSuperview];
3370 [configure_ removeFromSuperview];
3371 [self addSubview:navbar_];
3372 [self addSubview:reload_];
3373 [self addSubview:configure_];
3377 - (void) setPackages:(NSArray *)packages {
3378 [packages_ removeAllObjects];
3379 [packages_ addObjectsFromArray:packages];
3380 [packages_ sortUsingSelector:@selector(compareByName:)];
3382 Package *npackage = nil;
3383 for (size_t offset = 0, count = [packages_ count]; offset != count; ++offset) {
3384 Package *package = [packages_ objectAtIndex:offset];
3385 if ([[package name] isEqualToString:package_])
3389 [self searchPackages];
3391 if (npackage != nil)
3392 [self resetPackage:npackage];
3393 else if (package_ != nil)
3399 - (void) setDelegate:(id)delegate {
3401 [view_ setDelegate:delegate];
3402 [super setDelegate:delegate];
3405 - (void) resetPackage:(Package *)package {
3406 [view_ setPackage:package];
3407 NSString *right = [package installed] == nil ? @"Install" : @"Uninstall";
3408 [navbar_ showButtonsWithLeftTitle:nil rightTitle:right];
3411 - (void) searchPackages {
3412 NSString *text([field_ text]);
3414 NSMutableArray *packages([NSMutableArray arrayWithCapacity:16]);
3416 for (size_t offset(0), count([packages_ count]); offset != count; ++offset) {
3417 Package *package = [packages_ objectAtIndex:offset];
3418 if ([package matches:text])
3419 [packages addObject:package];
3422 [table_ setPackages:packages];
3423 [[table_ table] scrollPointVisibleAtTopLeft:CGPointMake(0, 0) animated:NO];
3429 @interface Cydia : UIApplication <
3430 ConfirmationViewDelegate,
3431 ProgressViewDelegate,
3437 UITransitionView *transition_;
3438 UIButtonBar *buttonbar_;
3440 ConfirmationView *confirm_;
3442 Database *database_;
3443 ProgressView *progress_;
3446 UINavigationBar *navbar_;
3447 UIScroller *scroller_;
3448 UIWebView *webview_;
3450 UIProgressIndicator *indicator_;
3452 InstallView *install_;
3453 ChangesView *changes_;
3454 ManageView *manage_;
3455 SearchView *search_;
3460 UIKeyboard *keyboard_;
3464 - (void) reloadData:(BOOL)reset;
3475 - (void) progressViewIsComplete:(ProgressView *)progress;
3477 - (void) navigationBar:(UINavigationBar *)navbar buttonClicked:(int)button;
3478 - (void) alertSheet:(UIAlertSheet *)sheet buttonClicked:(int)button;
3479 - (void) buttonBarItemTapped:(id)sender;
3481 - (void) view:(UIView *)sender didSetFrame:(CGRect)frame oldFrame:(CGRect)old;
3483 - (void) webView:(WebView *)sender didReceiveTitle:(NSString *)title forFrame:(WebFrame *)frame;
3485 - (void) applicationWillSuspend;
3486 - (void) applicationDidFinishLaunching:(id)unused;
3489 @implementation Cydia
3492 NSMutableURLRequest *request = [NSMutableURLRequest
3494 cachePolicy:NSURLRequestReloadIgnoringCacheData
3495 timeoutInterval:30.0
3498 [request addValue:[NSString stringWithCString:Firmware_] forHTTPHeaderField:@"X-Firmware"];
3499 [request addValue:[NSString stringWithCString:Machine_] forHTTPHeaderField:@"X-Machine"];
3500 [request addValue:[NSString stringWithCString:SerialNumber_] forHTTPHeaderField:@"X-Serial-Number"];
3502 [webview_ loadRequest:request];
3505 - (void) reloadData:(BOOL)reset {
3506 [database_ reloadData];
3510 if (Packages_ == nil) {
3511 Packages_ = [[NSMutableDictionary alloc] initWithCapacity:count];
3512 [Metadata_ setObject:Packages_ forKey:@"Packages"];
3515 NSArray *packages = [database_ packages];
3517 [install_ setPackages:packages];
3518 [changes_ setPackages:packages];
3519 [manage_ setPackages:packages];
3520 [search_ setPackages:packages];
3522 if (size_t count = [changes_ count]) {
3523 NSString *badge([[NSNumber numberWithInt:count] stringValue]);
3524 [buttonbar_ setBadgeValue:badge forButton:3];
3525 if ([buttonbar_ respondsToSelector:@selector(setBadgeAnimated:forButton:)])
3526 [buttonbar_ setBadgeAnimated:YES forButton:3];
3527 [self setApplicationBadge:badge];
3529 [buttonbar_ setBadgeValue:nil forButton:3];
3530 if ([buttonbar_ respondsToSelector:@selector(setBadgeAnimated:forButton:)])
3531 [buttonbar_ setBadgeAnimated:NO forButton:3];
3532 [self removeApplicationBadge];
3535 _assert([Metadata_ writeToFile:@"/var/lib/cydia/metadata.plist" atomically:YES] == YES);
3538 - (void) setPrompt {
3539 [navbar_ setPrompt:[NSString stringWithFormat:@"Last Updated: %@", GetLastUpdate()]];
3543 pkgProblemResolver *resolver = [database_ resolver];
3545 resolver->InstallProtect();
3546 if (!resolver->Resolve(true))
3551 [database_ prepare];
3553 if ([database_ cache]->BrokenCount() == 0)
3554 confirm_ = [[ConfirmationView alloc] initWithView:underlay_ database:database_ delegate:self];
3556 NSMutableArray *broken = [NSMutableArray arrayWithCapacity:16];
3557 NSArray *packages = [database_ packages];
3559 for (size_t i(0); i != [packages count]; ++i) {
3560 Package *package = [packages objectAtIndex:i];
3561 if ([package broken])
3562 [broken addObject:[package name]];
3565 UIAlertSheet *sheet = [[[UIAlertSheet alloc]
3566 initWithTitle:[NSString stringWithFormat:@"%d Broken Packages", [database_ cache]->BrokenCount()]
3567 buttons:[NSArray arrayWithObjects:@"Okay", nil]
3568 defaultButtonIndex:0
3573 [sheet setBodyText:[NSString stringWithFormat:@"The following packages have unmet dependencies:\n\n%@", [broken componentsJoinedByString:@"\n"]]];
3574 [sheet popupAlertAnimated:YES];
3576 [self reloadData:NO];
3581 [database_ upgrade];
3586 [self reloadData:NO];
3592 [overlay_ removeFromSuperview];
3596 detachNewThreadSelector:@selector(perform)
3603 - (void) bootstrap_ {
3605 [database_ upgrade];
3606 [database_ prepare];
3607 [database_ perform];
3610 - (void) bootstrap {
3612 detachNewThreadSelector:@selector(bootstrap_)
3615 title:@"Bootstrap Install..."
3621 detachNewThreadSelector:@selector(update)
3624 title:@"Refreshing Sources..."
3628 - (void) progressViewIsComplete:(ProgressView *)progress {
3629 [self reloadData:YES];
3631 if (confirm_ != nil) {
3632 [underlay_ addSubview:overlay_];
3633 [confirm_ removeFromSuperview];
3639 - (void) navigationBar:(UINavigationBar *)navbar buttonClicked:(int)button {
3646 UIAlertSheet *sheet = [[[UIAlertSheet alloc]
3647 initWithTitle:@"About Cydia Packager"
3648 buttons:[NSArray arrayWithObjects:@"Close", nil]
3649 defaultButtonIndex:0
3655 @"Copyright (C) 2008\n"
3656 "Jay Freeman (saurik)\n"
3657 "saurik@saurik.com\n"
3658 "http://www.saurik.com/\n"
3661 "http://www.theokorigroup.com/\n"
3663 "College of Creative Studies,\n"
3664 "University of California,\n"
3666 "http://www.ccs.ucsb.edu/\n"
3669 "bad_, BHSPitMonkey, cash, Cobra,\n"
3670 "core, Corona, crashx, cromas,\n"
3671 "Darken, dtzWill, Erica, francis,\n"
3672 "Godores, jerry, Kingstone, lounger,\n"
3673 "mbranes, rockabilly, tman, Wbiggs"
3676 [sheet presentSheetFromButtonBar:buttonbar_];
3681 - (void) alertSheet:(UIAlertSheet *)sheet buttonClicked:(int)button {
3685 - (void) buttonBarItemTapped:(id)sender {
3687 unsigned tag = [sender tag];
3690 case 1: view = featured_; break;
3691 case 2: view = install_; break;
3692 case 3: view = changes_; break;
3693 case 4: view = manage_; break;
3694 case 5: view = search_; break;
3700 if ([view respondsToSelector:@selector(resetView:)])
3701 [(id) view resetView:(tag == tag_ ? NO : YES)];
3703 [transition_ transition:0 toView:view];
3706 - (void) view:(UIView *)sender didSetFrame:(CGRect)frame oldFrame:(CGRect)old {
3707 [scroller_ setContentSize:frame.size];
3708 [indicator_ stopAnimation];
3711 - (void) webView:(WebView *)sender didReceiveTitle:(NSString *)title forFrame:(WebFrame *)frame {
3712 [navbar_ setPrompt:title];
3715 - (void) webView:(WebView *)sender didStartProvisionalLoadForFrame:(WebFrame *)frame {
3716 [navbar_ setPrompt:@"Loading..."];
3717 [indicator_ startAnimation];
3720 - (void) applicationWillSuspend {
3722 if (FW_LEAST(1,1,3))
3723 notify_post("com.apple.language.changed");
3725 system("launchctl stop com.apple.SpringBoard");
3727 [super applicationWillSuspend];
3730 - (void) applicationDidFinishLaunching:(id)unused {
3731 _assert(pkgInitConfig(*_config));
3732 _assert(pkgInitSystem(*_config, _system));
3738 CGRect screenrect = [UIHardware fullScreenApplicationContentRect];
3739 window_ = [[UIWindow alloc] initWithContentRect:screenrect];
3741 [window_ orderFront: self];
3742 [window_ makeKey: self];
3743 [window_ _setHidden: NO];
3745 progress_ = [[ProgressView alloc] initWithFrame:[window_ bounds] delegate:self];
3746 [window_ setContentView:progress_];
3748 underlay_ = [[UIView alloc] initWithFrame:[progress_ bounds]];
3749 [progress_ setContentView:underlay_];
3751 overlay_ = [[UIView alloc] initWithFrame:[underlay_ bounds]];
3754 [underlay_ addSubview:overlay_];
3756 transition_ = [[UITransitionView alloc] initWithFrame:CGRectMake(
3757 0, 0, screenrect.size.width, screenrect.size.height - 48
3760 [overlay_ addSubview:transition_];
3762 featured_ = [[UIView alloc] initWithFrame:[transition_ bounds]];
3764 CGSize navsize = [UINavigationBar defaultSizeWithPrompt];
3765 CGRect navrect = {{0, 0}, navsize};
3767 navbar_ = [[UINavigationBar alloc] initWithFrame:navrect];
3768 [featured_ addSubview:navbar_];
3770 [navbar_ setBarStyle:1];
3771 [navbar_ setDelegate:self];
3773 [navbar_ showButtonsWithLeftTitle:@"About" rightTitle:@"Reload"];
3775 UINavigationItem *navitem = [[[UINavigationItem alloc] initWithTitle:@"Featured"] autorelease];
3776 [navbar_ pushNavigationItem:navitem];
3778 struct CGRect subbounds = [featured_ bounds];
3779 subbounds.origin.y += navsize.height;
3780 subbounds.size.height -= navsize.height;
3782 UIImageView *pinstripe = [[[UIImageView alloc] initWithFrame:subbounds] autorelease];
3783 [pinstripe setImage:[UIImage applicationImageNamed:@"pinstripe.png"]];
3784 [featured_ addSubview:pinstripe];
3786 scroller_ = [[UIScroller alloc] initWithFrame:subbounds];
3787 [featured_ addSubview:scroller_];
3789 [scroller_ setScrollingEnabled:YES];
3790 [scroller_ setAdjustForContentSizeChange:YES];
3791 [scroller_ setClipsSubviews:YES];
3792 [scroller_ setAllowsRubberBanding:YES];
3793 [scroller_ setScrollDecelerationFactor:0.99];
3794 [scroller_ setDelegate:self];
3796 CGRect webrect = [scroller_ bounds];
3797 webrect.size.height = 0;
3799 webview_ = [[UIWebView alloc] initWithFrame:webrect];
3800 [scroller_ addSubview:webview_];
3802 [webview_ setTilingEnabled:YES];
3803 [webview_ setTileSize:CGSizeMake(screenrect.size.width, 500)];
3804 [webview_ setAutoresizes:YES];
3805 [webview_ setDelegate:self];
3807 CGSize indsize = [UIProgressIndicator defaultSizeForStyle:2];
3808 indicator_ = [[UIProgressIndicator alloc] initWithFrame:CGRectMake(87, 45, indsize.width, indsize.height)];
3809 [indicator_ setStyle:2];
3810 [featured_ addSubview:indicator_];
3812 NSArray *buttonitems = [NSArray arrayWithObjects:
3813 [NSDictionary dictionaryWithObjectsAndKeys:
3814 @"buttonBarItemTapped:", kUIButtonBarButtonAction,
3815 @"featured-up.png", kUIButtonBarButtonInfo,
3816 @"featured-dn.png", kUIButtonBarButtonSelectedInfo,
3817 [NSNumber numberWithInt:1], kUIButtonBarButtonTag,
3818 self, kUIButtonBarButtonTarget,
3819 @"Featured", kUIButtonBarButtonTitle,
3820 @"0", kUIButtonBarButtonType,
3823 [NSDictionary dictionaryWithObjectsAndKeys:
3824 @"buttonBarItemTapped:", kUIButtonBarButtonAction,
3825 @"install-up.png", kUIButtonBarButtonInfo,
3826 @"install-dn.png", kUIButtonBarButtonSelectedInfo,
3827 [NSNumber numberWithInt:2], kUIButtonBarButtonTag,
3828 self, kUIButtonBarButtonTarget,
3829 @"Install", kUIButtonBarButtonTitle,
3830 @"0", kUIButtonBarButtonType,
3833 [NSDictionary dictionaryWithObjectsAndKeys:
3834 @"buttonBarItemTapped:", kUIButtonBarButtonAction,
3835 @"changes-up.png", kUIButtonBarButtonInfo,
3836 @"changes-dn.png", kUIButtonBarButtonSelectedInfo,
3837 [NSNumber numberWithInt:3], kUIButtonBarButtonTag,
3838 self, kUIButtonBarButtonTarget,
3839 @"Changes", kUIButtonBarButtonTitle,
3840 @"0", kUIButtonBarButtonType,
3843 [NSDictionary dictionaryWithObjectsAndKeys:
3844 @"buttonBarItemTapped:", kUIButtonBarButtonAction,
3845 @"manage-up.png", kUIButtonBarButtonInfo,
3846 @"manage-dn.png", kUIButtonBarButtonSelectedInfo,
3847 [NSNumber numberWithInt:4], kUIButtonBarButtonTag,
3848 self, kUIButtonBarButtonTarget,
3849 @"Uninstall", kUIButtonBarButtonTitle,
3850 @"0", kUIButtonBarButtonType,
3853 [NSDictionary dictionaryWithObjectsAndKeys:
3854 @"buttonBarItemTapped:", kUIButtonBarButtonAction,
3855 @"search-up.png", kUIButtonBarButtonInfo,
3856 @"search-dn.png", kUIButtonBarButtonSelectedInfo,
3857 [NSNumber numberWithInt:5], kUIButtonBarButtonTag,
3858 self, kUIButtonBarButtonTarget,
3859 @"Search", kUIButtonBarButtonTitle,
3860 @"0", kUIButtonBarButtonType,
3864 buttonbar_ = [[UIButtonBar alloc]
3866 withFrame:CGRectMake(
3867 0, screenrect.size.height - 48,
3868 screenrect.size.width, 48
3870 withItemList:buttonitems
3873 [buttonbar_ setDelegate:self];
3874 [buttonbar_ setBarStyle:1];
3875 [buttonbar_ setButtonBarTrackingMode:2];
3877 int buttons[5] = {1, 2, 3, 4, 5};
3878 [buttonbar_ registerButtonGroup:0 withButtons:buttons withCount:5];
3879 [buttonbar_ showButtonGroup:0 withDuration:0];
3881 for (int i = 0; i != 5; ++i)
3882 [[buttonbar_ viewWithTag:(i + 1)] setFrame:CGRectMake(
3883 i * 64 + 2, 1, 60, 48
3886 [buttonbar_ showSelectionForButton:1];
3887 [transition_ transition:0 toView:featured_];
3889 [overlay_ addSubview:buttonbar_];
3891 [UIKeyboard initImplementationNow];
3893 CGRect edtrect = [overlay_ bounds];
3894 edtrect.origin.y += navsize.height;
3895 edtrect.size.height -= navsize.height;
3897 CGSize keysize = [UIKeyboard defaultSize];
3898 CGRect keyrect = {{0, [overlay_ bounds].size.height - keysize.height}, keysize};
3899 keyboard_ = [[UIKeyboard alloc] initWithFrame:keyrect];
3901 database_ = [[Database alloc] init];
3902 [database_ setDelegate:progress_];
3904 install_ = [[InstallView alloc] initWithFrame:[transition_ bounds]];
3905 [install_ setDelegate:self];
3907 changes_ = [[ChangesView alloc] initWithFrame:[transition_ bounds]];
3908 [changes_ setDelegate:self];
3910 manage_ = [[ManageView alloc] initWithFrame:[transition_ bounds]];
3911 [manage_ setDelegate:self];
3913 search_ = [[SearchView alloc] initWithFrame:[transition_ bounds]];
3914 [search_ setDelegate:self];
3916 [self reloadData:NO];
3918 Package *package([database_ packageWithName:@"cydia"]);
3919 NSString *application = package == nil ? @"Cydia" : [NSString
3920 stringWithFormat:@"Cydia/%@",
3924 WebView *webview = [webview_ webView];
3925 [webview setApplicationNameForUserAgent:application];
3926 [webview setFrameLoadDelegate:self];
3928 url_ = [NSURL URLWithString:@"http://cydia.saurik.com/"];
3931 [progress_ resetView];
3937 - (void) showKeyboard:(BOOL)show {
3939 [overlay_ addSubview:keyboard_];
3941 [keyboard_ removeFromSuperview];
3946 void AddPreferences(NSString *plist) {
3947 NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init];
3949 NSMutableDictionary *settings = [[[NSMutableDictionary alloc] initWithContentsOfFile:plist] autorelease];
3950 _assert(settings != NULL);
3951 NSMutableArray *items = [settings objectForKey:@"items"];
3955 for (size_t i(0); i != [items count]; ++i) {
3956 NSMutableDictionary *item([items objectAtIndex:i]);
3957 NSString *label = [item objectForKey:@"label"];
3958 if (label != nil && [label isEqualToString:@"Cydia"]) {
3965 for (size_t i(0); i != [items count]; ++i) {
3966 NSDictionary *item([items objectAtIndex:i]);
3967 NSString *label = [item objectForKey:@"label"];
3968 if (label != nil && [label isEqualToString:@"General"]) {
3969 [items insertObject:[NSDictionary dictionaryWithObjectsAndKeys:
3970 @"CydiaSettings", @"bundle",
3971 @"PSLinkCell", @"cell",
3972 [NSNumber numberWithBool:YES], @"hasIcon",
3973 [NSNumber numberWithBool:YES], @"isController",
3975 nil] atIndex:(i + 1)];
3981 _assert([settings writeToFile:plist atomically:YES] == YES);
3988 id Alloc_(id self, SEL selector) {
3989 id object = alloc_(self, selector);
3990 fprintf(stderr, "[%s]A-%p\n", self->isa->name, object);
3994 int main(int argc, char *argv[]) {
3996 memset(nl, 0, sizeof(nl));
3997 nl[0].n_un.n_name = "_useMDNSResponder";
3998 nlist("/usr/lib/libc.dylib", nl);
3999 if (nl[0].n_type != N_UNDF)
4000 *(int *) nl[0].n_value = 0;
4002 bootstrap_ = argc > 1 && strcmp(argv[1], "--bootstrap") == 0;
4007 /*Method alloc = class_getClassMethod([NSObject class], @selector(alloc));
4008 alloc_ = alloc->method_imp;
4009 alloc->method_imp = (IMP) &Alloc_;*/
4011 NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init];
4013 if (NSDictionary *sysver = [NSDictionary dictionaryWithContentsOfFile:@"/System/Library/CoreServices/SystemVersion.plist"]) {
4014 if (NSString *prover = [sysver valueForKey:@"ProductVersion"]) {
4015 Firmware_ = strdup([prover cString]);
4016 NSArray *versions = [prover componentsSeparatedByString:@"."];
4017 int count = [versions count];
4018 Major_ = count > 0 ? [[versions objectAtIndex:0] intValue] : 0;
4019 Minor_ = count > 1 ? [[versions objectAtIndex:1] intValue] : 0;
4020 BugFix_ = count > 2 ? [[versions objectAtIndex:2] intValue] : 0;
4025 sysctlbyname("hw.machine", NULL, &size, NULL, 0);
4026 char *machine = new char[size];
4027 sysctlbyname("hw.machine", machine, &size, NULL, 0);
4030 if (CFMutableDictionaryRef dict = IOServiceMatching("IOPlatformExpertDevice"))
4031 if (io_service_t service = IOServiceGetMatchingService(kIOMasterPortDefault, dict)) {
4032 if (CFTypeRef serial = IORegistryEntryCreateCFProperty(service, CFSTR(kIOPlatformSerialNumberKey), kCFAllocatorDefault, 0)) {
4033 SerialNumber_ = strdup(CFStringGetCStringPtr((CFStringRef) serial, CFStringGetSystemEncoding()));
4037 IOObjectRelease(service);
4040 /*AddPreferences(@"/Applications/Preferences.app/Settings-iPhone.plist");
4041 AddPreferences(@"/Applications/Preferences.app/Settings-iPod.plist");*/
4043 if ((Metadata_ = [[NSMutableDictionary alloc] initWithContentsOfFile:@"/var/lib/cydia/metadata.plist"]) == NULL)
4044 Metadata_ = [[NSMutableDictionary alloc] initWithCapacity:2];
4046 Packages_ = [Metadata_ objectForKey:@"Packages"];
4048 setenv("CYDIA", "", _not(int));
4049 if (access("/User", F_OK) != 0)
4050 system("/usr/libexec/cydia/firmware.sh");
4051 system("dpkg --configure -a");
4053 UIApplicationMain(argc, argv, [Cydia class]);