1 /* #include Directives {{{ */
2 #include <Foundation/NSURL.h>
3 #include <UIKit/UIKit.h>
4 #import <GraphicsServices/GraphicsServices.h>
7 #include <ext/stdio_filebuf.h>
9 #include <apt-pkg/acquire.h>
10 #include <apt-pkg/acquire-item.h>
11 #include <apt-pkg/algorithms.h>
12 #include <apt-pkg/cachefile.h>
13 #include <apt-pkg/configuration.h>
14 #include <apt-pkg/debmetaindex.h>
15 #include <apt-pkg/error.h>
16 #include <apt-pkg/init.h>
17 #include <apt-pkg/pkgrecords.h>
18 #include <apt-pkg/sourcelist.h>
19 #include <apt-pkg/sptr.h>
21 #include <sys/sysctl.h>
25 #include <mach-o/nlist.h>
28 #include <objc/objc-class.h>
34 /* Extension Keywords {{{ */
35 #define _trace() fprintf(stderr, "_trace()@%s:%u[%s]\n", __FILE__, __LINE__, __FUNCTION__)
37 #define _assert(test) do \
39 fprintf(stderr, "_assert(%d:%s)@%s:%u[%s]\n", errno, #test, __FILE__, __LINE__, __FUNCTION__); \
44 #define _not(type) ((type) ~ (type) 0)
46 /* Miscellaneous Messages {{{ */
48 - (void) setApplicationNameForUserAgent:(NSString *)applicationName;
49 - (id) frameLoadDelegate;
50 - (void) setFrameLoadDelegate:(id)delegate;
53 @interface NSString (Cydia)
54 - (NSString *) stringByAddingPercentEscapes;
55 - (NSString *) stringByReplacingCharacter:(unsigned short)arg0 withCharacter:(unsigned short)arg1;
59 /* Reset View (UIView) {{{ */
60 @interface UIView (CYResetView)
61 - (void) resetViewAnimated:(BOOL)animated;
64 @implementation UIView (CYResetView)
66 - (void) resetViewAnimated:(BOOL)animated {
67 fprintf(stderr, "%s\n", self->isa->name);
73 /* Reset View (UITable) {{{ */
74 @interface UITable (CYResetView)
75 - (void) resetViewAnimated:(BOOL)animated;
78 @implementation UITable (CYResetView)
80 - (void) resetViewAnimated:(BOOL)animated {
81 [self selectRow:-1 byExtendingSelection:NO withFade:animated];
86 /* Reset View (UISectionList) {{{ */
87 @interface UISectionList (CYResetView)
88 - (void) resetViewAnimated:(BOOL)animated;
91 @implementation UISectionList (CYResetView)
93 - (void) resetViewAnimated:(BOOL)animated {
94 [[self table] resetViewAnimated:animated];
100 /* Perl-Compatible RegEx {{{ */
110 Pcre(const char *regex) :
115 code_ = pcre_compile(regex, 0, &error, &offset, NULL);
118 fprintf(stderr, "%d:%s\n", offset, error);
122 pcre_fullinfo(code_, study_, PCRE_INFO_CAPTURECOUNT, &capture_);
123 matches_ = new int[(capture_ + 1) * 3];
131 NSString *operator [](size_t match) {
133 stringWithCString:(data_ + matches_[match * 2])
134 length:(matches_[match * 2 + 1] - matches_[match * 2])
138 bool operator ()(const char *data, size_t size) {
140 return pcre_exec(code_, study_, data, size, 0, 0, matches_, (capture_ + 1) * 3) >= 0;
144 /* CoreGraphicsServices Primitives {{{ */
150 CGColor(CGColorSpaceRef space, float red, float green, float blue, float alpha) {
151 float color[] = {red, green, blue, alpha};
152 color_ = CGColorCreate(space, color);
156 CGColorRelease(color_);
159 operator CGColorRef() {
170 /* XXX: no GSFontRelease()? */
176 static const int PulseInterval_ = 50000;
178 const char *Firmware_ = NULL;
179 const char *Machine_ = NULL;
180 const char *SerialNumber_ = NULL;
186 #define FW_LEAST(major, minor, bugfix) \
187 (major < Major_ || major == Major_ && \
188 (minor < Minor_ || minor == Minor_ && \
191 bool bootstrap_ = false;
193 static NSMutableDictionary *Metadata_;
194 static NSMutableDictionary *Packages_;
197 NSString *GetLastUpdate() {
198 NSDate *update = [Metadata_ objectForKey:@"LastUpdate"];
201 return @"Never or Unknown";
203 CFLocaleRef locale = CFLocaleCopyCurrent();
204 CFDateFormatterRef formatter = CFDateFormatterCreate(NULL, locale, kCFDateFormatterMediumStyle, kCFDateFormatterMediumStyle);
205 CFStringRef formatted = CFDateFormatterCreateStringWithDate(NULL, formatter, (CFDateRef) update);
207 CFRelease(formatter);
210 return [(NSString *) formatted autorelease];
213 @protocol ProgressDelegate
214 - (void) setError:(NSString *)error;
215 - (void) setTitle:(NSString *)title;
216 - (void) setPercent:(float)percent;
217 - (void) addOutput:(NSString *)output;
220 NSString *SizeString(double size) {
222 while (size > 1024) {
227 static const char *powers_[] = {"B", "kB", "MB", "GB"};
229 return [NSString stringWithFormat:@"%.1f%s", size, powers_[power]];
232 static const float TextViewOffset_ = 22;
234 UITextView *GetTextView(NSString *value, float left, bool html) {
235 UITextView *text([[[UITextView alloc] initWithFrame:CGRectMake(left, 3, 310 - left, 1000)] autorelease]);
236 [text setEditable:NO];
237 [text setTextSize:16];
239 [text setHTML:value];
241 [text setText:value];
242 [text setEnabled:NO];
244 CGColorSpaceRef space = CGColorSpaceCreateDeviceRGB();
245 CGColor clear(space, 0, 0, 0, 0);
246 [text setBackgroundColor:clear];
247 CGColorSpaceRelease(space);
249 CGRect frame = [text frame];
250 [text setFrame:frame];
251 CGRect rect = [text visibleTextRect];
252 frame.size.height = rect.size.height;
253 [text setFrame:frame];
258 /* Status Delegation {{{ */
260 public pkgAcquireStatus
271 void setDelegate(id delegate) {
272 delegate_ = delegate;
275 virtual bool MediaChange(std::string media, std::string drive) {
279 virtual void IMSHit(pkgAcquire::ItemDesc &item) {
282 virtual void Fetch(pkgAcquire::ItemDesc &item) {
283 [delegate_ setTitle:[NSString stringWithCString:("Downloading " + item.ShortDesc).c_str()]];
286 virtual void Done(pkgAcquire::ItemDesc &item) {
289 virtual void Fail(pkgAcquire::ItemDesc &item) {
291 item.Owner->Status == pkgAcquire::Item::StatIdle ||
292 item.Owner->Status == pkgAcquire::Item::StatDone
296 [delegate_ setError:[NSString stringWithCString:item.Owner->ErrorText.c_str()]];
299 virtual bool Pulse(pkgAcquire *Owner) {
300 bool value = pkgAcquireStatus::Pulse(Owner);
303 double(CurrentBytes + CurrentItems) /
304 double(TotalBytes + TotalItems)
307 [delegate_ setPercent:percent];
311 virtual void Start() {
314 virtual void Stop() {
318 /* Progress Delegation {{{ */
326 virtual void Update() {
327 [delegate_ setTitle:[NSString stringWithCString:Op.c_str()]];
328 [delegate_ setPercent:(Percent / 100)];
337 void setDelegate(id delegate) {
338 delegate_ = delegate;
341 virtual void Done() {
342 [delegate_ setPercent:1];
347 /* External Constants {{{ */
348 extern NSString *kUIButtonBarButtonAction;
349 extern NSString *kUIButtonBarButtonInfo;
350 extern NSString *kUIButtonBarButtonInfoOffset;
351 extern NSString *kUIButtonBarButtonSelectedInfo;
352 extern NSString *kUIButtonBarButtonStyle;
353 extern NSString *kUIButtonBarButtonTag;
354 extern NSString *kUIButtonBarButtonTarget;
355 extern NSString *kUIButtonBarButtonTitle;
356 extern NSString *kUIButtonBarButtonTitleVerticalHeight;
357 extern NSString *kUIButtonBarButtonTitleWidth;
358 extern NSString *kUIButtonBarButtonType;
360 /* Mime Addresses {{{ */
361 Pcre email_r("^\"?(.*)\"? <([^>]*)>$");
363 @interface Address : NSObject {
371 - (NSString *) email;
373 + (Address *) addressWithString:(NSString *)string;
374 - (Address *) initWithString:(NSString *)string;
377 @implementation Address
386 - (NSString *) name {
390 - (NSString *) email {
394 + (Address *) addressWithString:(NSString *)string {
395 return [[[Address alloc] initWithString:string] autorelease];
398 - (Address *) initWithString:(NSString *)string {
399 if ((self = [super init]) != nil) {
400 const char *data = [string UTF8String];
401 size_t size = [string length];
403 if (email_r(data, size)) {
404 name_ = [email_r[1] retain];
405 email_ = [email_r[2] retain];
407 name_ = [[NSString stringWithCString:data length:size] retain];
416 /* Right Alignment {{{ */
417 @interface UIRightTextLabel : UITextLabel {
418 float _savedRightEdgeX;
419 BOOL _sizedtofit_flag;
422 - (void) setFrame:(CGRect)frame;
423 - (void) setText:(NSString *)text;
424 - (void) realignText;
427 @implementation UIRightTextLabel
429 - (void) setFrame:(CGRect)frame {
430 [super setFrame:frame];
431 if (_sizedtofit_flag == NO) {
432 _savedRightEdgeX = frame.origin.x;
437 - (void) setText:(NSString *)text {
438 [super setText:text];
442 - (void) realignText {
443 CGRect oldFrame = [self frame];
445 _sizedtofit_flag = YES;
446 [self sizeToFit]; // shrink down size so I can right align it
448 CGRect newFrame = [self frame];
450 oldFrame.origin.x = _savedRightEdgeX - newFrame.size.width;
451 oldFrame.size.width = newFrame.size.width;
452 [super setFrame:oldFrame];
453 _sizedtofit_flag = NO;
458 /* Linear Algebra {{{ */
459 inline float interpolate(float begin, float end, float fraction) {
460 return (end - begin) * fraction + begin;
467 /* Database Interface {{{ */
468 @interface Database : NSObject {
470 pkgRecords *records_;
471 pkgProblemResolver *resolver_;
472 pkgAcquire *fetcher_;
474 SPtr<pkgPackageManager> manager_;
475 pkgSourceList *list_;
477 NSMutableDictionary *sources_;
487 - (void) _readStatus:(NSNumber *)fd;
488 - (void) _readOutput:(NSNumber *)fd;
490 - (Package *) packageWithName:(NSString *)name;
493 - (pkgCacheFile &) cache;
494 - (pkgRecords *) records;
495 - (pkgProblemResolver *) resolver;
496 - (pkgAcquire &) fetcher;
504 - (void) setDelegate:(id)delegate;
505 - (Source *) getSource:(const pkgCache::PkgFileIterator &)file;
510 @interface ResetView : UIView {
511 UIPushButton *configure_;
512 UIPushButton *reload_;
513 NSMutableArray *views_;
514 UINavigationBar *navbar_;
515 UITransitionView *transition_;
522 - (void) navigationBar:(UINavigationBar *)navbar poppedItem:(UINavigationItem *)item;
523 - (void) alertSheet:(UIAlertSheet *)sheet buttonClicked:(int)button;
525 - (id) initWithFrame:(CGRect)frame;
526 - (void) setDelegate:(id)delegate;
528 - (void) configurePushed;
529 - (void) reloadPushed;
531 - (void) pushView:(UIView *)view withTitle:(NSString *)title backButtonTitle:(NSString *)back rightButton:(NSString *)right;
532 - (void) popViews:(unsigned)views;
533 - (void) resetView:(BOOL)clear;
538 @implementation ResetView
541 [configure_ release];
543 [transition_ release];
549 - (void) navigationBar:(UINavigationBar *)navbar poppedItem:(UINavigationItem *)item {
550 [views_ removeLastObject];
551 UIView *view([views_ lastObject]);
552 [view resetViewAnimated:!resetting_];
555 [transition_ transition:2 toView:view];
560 - (void) alertSheet:(UIAlertSheet *)sheet buttonClicked:(int)button {
564 - (id) initWithFrame:(CGRect)frame {
565 if ((self = [super initWithFrame:frame]) != nil) {
566 views_ = [[NSMutableArray arrayWithCapacity:4] retain];
568 struct CGRect bounds = [self bounds];
569 CGSize navsize = [UINavigationBar defaultSizeWithPrompt];
570 CGRect navrect = {{0, 0}, navsize};
572 navbar_ = [[UINavigationBar alloc] initWithFrame:navrect];
573 [self addSubview:navbar_];
575 [navbar_ setBarStyle:1];
576 [navbar_ setDelegate:self];
578 transition_ = [[UITransitionView alloc] initWithFrame:CGRectMake(
579 bounds.origin.x, bounds.origin.y + navsize.height, bounds.size.width, bounds.size.height - navsize.height
582 //configure_ = [[UIPushButton alloc] initWithFrame:CGRectMake(15, 9, 17, 18)];
583 configure_ = [[UIPushButton alloc] initWithFrame:CGRectMake(10, 9, 17, 18)];
584 [configure_ setShowPressFeedback:YES];
585 [configure_ setImage:[UIImage applicationImageNamed:@"configure.png"]];
586 [configure_ addTarget:self action:@selector(configurePushed) forEvents:1];
588 //reload_ = [[UIPushButton alloc] initWithFrame:CGRectMake(288, 5, 18, 22)];
589 reload_ = [[UIPushButton alloc] initWithFrame:CGRectMake(293, 5, 18, 22)];
590 [reload_ setShowPressFeedback:YES];
591 [reload_ setImage:[UIImage applicationImageNamed:@"reload.png"]];
592 [reload_ addTarget:self action:@selector(reloadPushed) forEvents:1];
594 [navbar_ addSubview:configure_];
595 [navbar_ addSubview:reload_];
597 [self addSubview:transition_];
601 - (void) setDelegate:(id)delegate {
602 delegate_ = delegate;
605 - (void) configurePushed {
606 UIAlertSheet *sheet = [[[UIAlertSheet alloc]
607 initWithTitle:@"Sources Unimplemented"
608 buttons:[NSArray arrayWithObjects:@"Okay", nil]
614 [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'."];
615 [sheet popupAlertAnimated:YES];
618 - (void) reloadPushed {
622 - (void) pushView:(UIView *)view withTitle:(NSString *)title backButtonTitle:(NSString *)back rightButton:(NSString *)right {
623 UINavigationItem *navitem = [[[UINavigationItem alloc] initWithTitle:title] autorelease];
624 [navbar_ pushNavigationItem:navitem];
625 [navitem setBackButtonTitle:back];
627 [navbar_ showButtonsWithLeftTitle:nil rightTitle:right];
629 [transition_ transition:([views_ count] == 0 ? 0 : 1) toView:view];
630 [views_ addObject:view];
633 - (void) popViews:(unsigned)views {
635 for (unsigned i(0); i != views; ++i)
636 [navbar_ popNavigationItem];
640 [transition_ transition:2 toView:[views_ lastObject]];
643 - (void) resetView:(BOOL)clear {
646 if ([views_ count] > 1) {
647 [navbar_ disableAnimation];
648 while ([views_ count] != (clear ? 1 : 2))
649 [navbar_ popNavigationItem];
650 [navbar_ enableAnimation];
652 [navbar_ popNavigationItem];
658 [transition_ transition:(clear ? 0 : 2) toView:[views_ lastObject]];
661 - (void) _resetView {
662 [navbar_ showButtonsWithLeftTitle:nil rightTitle:nil];
666 [navbar_ setPrompt:[NSString stringWithFormat:@"Last Updated: %@", GetLastUpdate()]];
671 /* Confirmation View {{{ */
672 void AddTextView(NSMutableDictionary *fields, NSMutableArray *packages, NSString *key) {
673 if ([packages count] == 0)
676 UITextView *text = GetTextView([packages count] == 0 ? @"n/a" : [packages componentsJoinedByString:@", "], 110, false);
677 [fields setObject:text forKey:key];
679 CGColorSpaceRef space = CGColorSpaceCreateDeviceRGB();
680 CGColor blue(space, 0, 0, 0.4, 1);
681 [text setTextColor:blue];
682 CGColorSpaceRelease(space);
685 @protocol ConfirmationViewDelegate
690 @interface ConfirmationView : UIView {
693 UITransitionView *transition_;
695 UINavigationBar *navbar_;
696 UIPreferencesTable *table_;
697 NSMutableDictionary *fields_;
698 UIAlertSheet *essential_;
704 - (void) transitionViewDidComplete:(UITransitionView*)view fromView:(UIView*)from toView:(UIView*)to;
705 - (void) navigationBar:(UINavigationBar *)navbar buttonClicked:(int)button;
706 - (void) alertSheet:(UIAlertSheet *)sheet buttonClicked:(int)button;
708 - (int) numberOfGroupsInPreferencesTable:(UIPreferencesTable *)table;
709 - (NSString *) preferencesTable:(UIPreferencesTable *)table titleForGroup:(int)group;
710 - (float) preferencesTable:(UIPreferencesTable *)table heightForRow:(int)row inGroup:(int)group withProposedHeight:(float)proposed;
711 - (int) preferencesTable:(UIPreferencesTable *)table numberOfRowsInGroup:(int)group;
712 - (UIPreferencesTableCell *) preferencesTable:(UIPreferencesTable *)table cellForRow:(int)row inGroup:(int)group;
714 - (id) initWithView:(UIView *)view database:(Database *)database delegate:(id)delegate;
718 @implementation ConfirmationView
721 [transition_ release];
726 if (essential_ != nil)
727 [essential_ release];
732 [transition_ transition:7 toView:nil];
736 - (void) transitionViewDidComplete:(UITransitionView*)view fromView:(UIView*)from toView:(UIView*)to {
737 if (from != nil && to == nil)
738 [self removeFromSuperview];
741 - (void) navigationBar:(UINavigationBar *)navbar buttonClicked:(int)button {
744 if (essential_ != nil)
745 [essential_ popupAlertAnimated:YES];
756 - (void) alertSheet:(UIAlertSheet *)sheet buttonClicked:(int)button {
757 [essential_ dismiss];
761 - (int) numberOfGroupsInPreferencesTable:(UIPreferencesTable *)table {
765 - (NSString *) preferencesTable:(UIPreferencesTable *)table titleForGroup:(int)group {
767 case 0: return @"Statistics";
768 case 1: return @"Modifications";
770 default: _assert(false);
774 - (int) preferencesTable:(UIPreferencesTable *)table numberOfRowsInGroup:(int)group {
777 case 1: return [fields_ count];
779 default: _assert(false);
783 - (float) preferencesTable:(UIPreferencesTable *)table heightForRow:(int)row inGroup:(int)group withProposedHeight:(float)proposed {
784 if (group != 1 || row == -1)
787 _assert(size_t(row) < [fields_ count]);
788 return [[[fields_ allValues] objectAtIndex:row] visibleTextRect].size.height + TextViewOffset_;
792 - (UIPreferencesTableCell *) preferencesTable:(UIPreferencesTable *)table cellForRow:(int)row inGroup:(int)group {
793 UIPreferencesTableCell *cell = [[[UIPreferencesTableCell alloc] init] autorelease];
794 [cell setShowSelection:NO];
797 case 0: switch (row) {
799 [cell setTitle:@"Downloading"];
800 [cell setValue:SizeString([database_ fetcher].FetchNeeded())];
804 [cell setTitle:@"Resuming At"];
805 [cell setValue:SizeString([database_ fetcher].PartialPresent())];
809 double size([database_ cache]->UsrSize());
812 [cell setTitle:@"Disk Freeing"];
813 [cell setValue:SizeString(-size)];
815 [cell setTitle:@"Disk Using"];
816 [cell setValue:SizeString(size)];
820 default: _assert(false);
824 _assert(size_t(row) < [fields_ count]);
825 [cell setTitle:[[fields_ allKeys] objectAtIndex:row]];
826 [cell addSubview:[[fields_ allValues] objectAtIndex:row]];
829 default: _assert(false);
835 - (id) initWithView:(UIView *)view database:(Database *)database delegate:(id)delegate {
836 if ((self = [super initWithFrame:[view bounds]]) != nil) {
837 database_ = database;
838 delegate_ = delegate;
840 transition_ = [[UITransitionView alloc] initWithFrame:[self bounds]];
841 [self addSubview:transition_];
843 overlay_ = [[UIView alloc] initWithFrame:[transition_ bounds]];
845 CGSize navsize = [UINavigationBar defaultSize];
846 CGRect navrect = {{0, 0}, navsize};
847 CGRect bounds = [overlay_ bounds];
849 navbar_ = [[UINavigationBar alloc] initWithFrame:navrect];
850 [navbar_ setBarStyle:1];
851 [navbar_ setDelegate:self];
853 UINavigationItem *navitem = [[[UINavigationItem alloc] initWithTitle:@"Confirm"] autorelease];
854 [navbar_ pushNavigationItem:navitem];
855 [navbar_ showButtonsWithLeftTitle:@"Cancel" rightTitle:@"Confirm"];
857 fields_ = [[NSMutableDictionary dictionaryWithCapacity:16] retain];
859 NSMutableArray *installing = [NSMutableArray arrayWithCapacity:16];
860 NSMutableArray *upgrading = [NSMutableArray arrayWithCapacity:16];
861 NSMutableArray *removing = [NSMutableArray arrayWithCapacity:16];
867 pkgCacheFile &cache([database_ cache]);
868 for (pkgCache::PkgIterator iterator = cache->PkgBegin(); !iterator.end(); ++iterator) {
869 NSString *name([NSString stringWithCString:iterator.Name()]);
870 bool essential((iterator->Flags & pkgCache::Flag::Essential) != 0);
872 if (cache[iterator].NewInstall()) {
875 [installing addObject:name];
876 } else if (cache[iterator].Upgrade()) {
879 [upgrading addObject:name];
880 } else if (cache[iterator].Delete()) {
883 [removing addObject:name];
890 essential_ = [[UIAlertSheet alloc]
891 initWithTitle:@"Unable to Comply"
892 buttons:[NSArray arrayWithObjects:@"Okay", nil]
898 [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."];
901 AddTextView(fields_, installing, @"Installing");
902 AddTextView(fields_, upgrading, @"Upgrading");
903 AddTextView(fields_, removing, @"Removing");
905 table_ = [[UIPreferencesTable alloc] initWithFrame:CGRectMake(
906 0, navsize.height, bounds.size.width, bounds.size.height - navsize.height
909 [table_ setReusesTableCells:YES];
910 [table_ setDataSource:self];
913 [overlay_ addSubview:navbar_];
914 [overlay_ addSubview:table_];
916 [view addSubview:self];
918 [transition_ setDelegate:self];
920 UIView *blank = [[[UIView alloc] initWithFrame:[transition_ bounds]] autorelease];
921 [transition_ transition:0 toView:blank];
922 [transition_ transition:3 toView:overlay_];
929 /* Source Class {{{ */
930 @interface Source : NSObject {
931 NSString *description_;
936 NSString *distribution_;
945 - (Source *) initWithMetaIndex:(metaIndex *)index;
950 - (NSString *) distribution;
953 - (NSString *) description;
954 - (NSString *) label;
955 - (NSString *) origin;
956 - (NSString *) version;
959 @implementation Source
963 [distribution_ release];
966 if (description_ != nil)
967 [description_ release];
978 - (Source *) initWithMetaIndex:(metaIndex *)index {
979 if ((self = [super init]) != nil) {
980 trusted_ = index->IsTrusted();
982 uri_ = [[NSString stringWithCString:index->GetURI().c_str()] retain];
983 distribution_ = [[NSString stringWithCString:index->GetDist().c_str()] retain];
984 type_ = [[NSString stringWithCString:index->GetType()] retain];
990 debReleaseIndex *dindex(dynamic_cast<debReleaseIndex *>(index));
991 if (dindex != NULL) {
992 std::ifstream release(dindex->MetaIndexFile("Release").c_str());
994 while (std::getline(release, line)) {
995 std::string::size_type colon(line.find(':'));
996 if (colon == std::string::npos)
999 std::string name(line.substr(0, colon));
1000 std::string value(line.substr(colon + 1));
1001 while (!value.empty() && value[0] == ' ')
1002 value = value.substr(1);
1004 if (name == "Description")
1005 description_ = [[NSString stringWithCString:value.c_str()] retain];
1006 else if (name == "Label")
1007 label_ = [[NSString stringWithCString:value.c_str()] retain];
1008 else if (name == "Origin")
1009 origin_ = [[NSString stringWithCString:value.c_str()] retain];
1010 else if (name == "Version")
1011 version_ = [[NSString stringWithCString:value.c_str()] retain];
1021 - (NSString *) uri {
1025 - (NSString *) distribution {
1026 return distribution_;
1029 - (NSString *) type {
1033 - (NSString *) description {
1034 return description_;
1037 - (NSString *) label {
1041 - (NSString *) origin {
1045 - (NSString *) version {
1051 /* Package Class {{{ */
1052 NSString *Scour(const char *field, const char *begin, const char *end) {
1053 size_t i(0), l(strlen(field));
1056 const char *name = begin + i;
1057 const char *colon = name + l;
1058 const char *value = colon + 1;
1063 memcmp(name, field, l) == 0
1065 while (value != end && value[0] == ' ')
1067 const char *line = std::find(value, end, '\n');
1068 while (line != value && line[-1] == ' ')
1070 return [NSString stringWithCString:value length:(line - value)];
1072 begin = std::find(begin, end, '\n');
1080 @interface Package : NSObject {
1081 pkgCache::PkgIterator iterator_;
1082 Database *database_;
1083 pkgCache::VerIterator version_;
1084 pkgCache::VerFileIterator file_;
1088 NSString *installed_;
1099 - (Package *) initWithIterator:(pkgCache::PkgIterator)iterator database:(Database *)database version:(pkgCache::VerIterator)version file:(pkgCache::VerFileIterator)file;
1100 + (Package *) packageWithIterator:(pkgCache::PkgIterator)iterator database:(Database *)database;
1102 - (NSString *) section;
1103 - (Address *) maintainer;
1105 - (NSString *) description;
1106 - (NSString *) index;
1110 - (NSString *) latest;
1111 - (NSString *) installed;
1112 - (BOOL) upgradable;
1115 - (NSString *) name;
1116 - (NSString *) tagline;
1117 - (NSString *) icon;
1118 - (NSString *) website;
1120 - (Source *) source;
1122 - (BOOL) matches:(NSString *)text;
1124 - (NSComparisonResult) compareByName:(Package *)package;
1125 - (NSComparisonResult) compareBySectionAndName:(Package *)package;
1126 - (NSComparisonResult) compareForChanges:(Package *)package;
1132 @implementation Package
1136 if (installed_ != nil)
1137 [installed_ release];
1145 if (website_ != nil)
1154 - (Package *) initWithIterator:(pkgCache::PkgIterator)iterator database:(Database *)database version:(pkgCache::VerIterator)version file:(pkgCache::VerFileIterator)file {
1155 if ((self = [super init]) != nil) {
1156 iterator_ = iterator;
1157 database_ = database;
1162 pkgRecords::Parser *parser = &[database_ records]->Lookup(file_);
1164 const char *begin, *end;
1165 parser->GetRec(begin, end);
1167 latest_ = [[NSString stringWithCString:version_.VerStr()] retain];
1168 installed_ = iterator_.CurrentVer().end() ? nil : [[NSString stringWithCString:iterator_.CurrentVer().VerStr()] retain];
1170 id_ = [[[NSString stringWithCString:iterator_.Name()] lowercaseString] retain];
1171 name_ = Scour("Name", begin, end);
1173 name_ = [name_ retain];
1174 tagline_ = [[NSString stringWithCString:parser->ShortDesc().c_str()] retain];
1175 icon_ = Scour("Icon", begin, end);
1177 icon_ = [icon_ retain];
1178 website_ = Scour("Website", begin, end);
1179 if (website_ != nil)
1180 website_ = [website_ retain];
1182 source_ = [[database_ getSource:file_.File()] retain];
1184 NSMutableDictionary *metadata = [Packages_ objectForKey:id_];
1185 if (metadata == nil) {
1186 metadata = [NSMutableDictionary dictionaryWithObjectsAndKeys:
1190 [Packages_ setObject:metadata forKey:id_];
1195 + (Package *) packageWithIterator:(pkgCache::PkgIterator)iterator database:(Database *)database {
1196 for (pkgCache::VerIterator version = iterator.VersionList(); !version.end(); ++version)
1197 for (pkgCache::VerFileIterator file = version.FileList(); !file.end(); ++file)
1198 return [[[Package alloc]
1199 initWithIterator:iterator
1207 - (NSString *) section {
1208 const char *section = iterator_.Section();
1209 return section == NULL ? nil : [[NSString stringWithCString:section] stringByReplacingCharacter:'_' withCharacter:' '];
1212 - (Address *) maintainer {
1213 pkgRecords::Parser *parser = &[database_ records]->Lookup(file_);
1214 return [Address addressWithString:[NSString stringWithCString:parser->Maintainer().c_str()]];
1218 return version_->InstalledSize;
1221 - (NSString *) description {
1222 pkgRecords::Parser *parser = &[database_ records]->Lookup(file_);
1223 NSString *description([NSString stringWithCString:parser->LongDesc().c_str()]);
1225 NSArray *lines = [description componentsSeparatedByString:@"\n"];
1226 NSMutableArray *trimmed = [NSMutableArray arrayWithCapacity:([lines count] - 1)];
1227 if ([lines count] < 2)
1230 NSCharacterSet *whitespace = [NSCharacterSet whitespaceCharacterSet];
1231 for (size_t i(1); i != [lines count]; ++i) {
1232 NSString *trim = [[lines objectAtIndex:i] stringByTrimmingCharactersInSet:whitespace];
1233 [trimmed addObject:trim];
1236 return [trimmed componentsJoinedByString:@"\n"];
1239 - (NSString *) index {
1240 NSString *index = [[[self name] substringToIndex:1] uppercaseString];
1241 return [index length] != 0 && isalpha([index characterAtIndex:0]) ? index : @"123";
1245 return [[Packages_ objectForKey:id_] objectForKey:@"FirstSeen"];
1248 - (NSString *) latest {
1252 - (NSString *) installed {
1256 - (BOOL) upgradable {
1257 NSString *installed = [self installed];
1258 return installed != nil && [[self latest] compare:installed] != NSOrderedSame ? YES : NO;
1265 - (NSString *) name {
1266 return name_ == nil ? id_ : name_;
1269 - (NSString *) tagline {
1273 - (NSString *) icon {
1277 - (NSString *) website {
1281 - (Source *) source {
1285 - (BOOL) matches:(NSString *)text {
1291 range = [[self id] rangeOfString:text options:NSCaseInsensitiveSearch];
1292 if (range.location != NSNotFound)
1295 range = [[self name] rangeOfString:text options:NSCaseInsensitiveSearch];
1296 if (range.location != NSNotFound)
1299 range = [[self tagline] rangeOfString:text options:NSCaseInsensitiveSearch];
1300 if (range.location != NSNotFound)
1306 - (NSComparisonResult) compareByName:(Package *)package {
1307 NSString *lhs = [self name];
1308 NSString *rhs = [package name];
1310 if ([lhs length] != 0 && [rhs length] != 0) {
1311 unichar lhc = [lhs characterAtIndex:0];
1312 unichar rhc = [rhs characterAtIndex:0];
1314 if (isalpha(lhc) && !isalpha(rhc))
1315 return NSOrderedAscending;
1316 else if (!isalpha(lhc) && isalpha(rhc))
1317 return NSOrderedDescending;
1320 return [lhs caseInsensitiveCompare:rhs];
1323 - (NSComparisonResult) compareBySectionAndName:(Package *)package {
1324 NSString *lhs = [self section];
1325 NSString *rhs = [package section];
1327 if (lhs == NULL && rhs != NULL)
1328 return NSOrderedAscending;
1329 else if (lhs != NULL && rhs == NULL)
1330 return NSOrderedDescending;
1331 else if (lhs != NULL && rhs != NULL) {
1332 NSComparisonResult result = [lhs compare:rhs];
1333 if (result != NSOrderedSame)
1337 return [self compareByName:package];
1340 - (NSComparisonResult) compareForChanges:(Package *)package {
1341 BOOL lhs = [self upgradable];
1342 BOOL rhs = [package upgradable];
1345 return lhs ? NSOrderedAscending : NSOrderedDescending;
1347 switch ([[self seen] compare:[package seen]]) {
1348 case NSOrderedAscending:
1349 return NSOrderedDescending;
1352 case NSOrderedDescending:
1353 return NSOrderedAscending;
1359 return [self compareByName:package];
1363 pkgProblemResolver *resolver = [database_ resolver];
1364 resolver->Clear(iterator_);
1365 resolver->Protect(iterator_);
1366 [database_ cache]->MarkInstall(iterator_, false);
1370 pkgProblemResolver *resolver = [database_ resolver];
1371 resolver->Clear(iterator_);
1372 resolver->Protect(iterator_);
1373 resolver->Remove(iterator_);
1374 [database_ cache]->MarkDelete(iterator_, true);
1379 /* Section Class {{{ */
1380 @interface Section : NSObject {
1383 NSMutableArray *packages_;
1388 - (Section *) initWithName:(NSString *)name row:(size_t)row;
1389 - (NSString *) name;
1391 - (NSArray *) packages;
1393 - (void) addPackage:(Package *)package;
1396 @implementation Section
1400 [packages_ release];
1404 - (Section *) initWithName:(NSString *)name row:(size_t)row {
1405 if ((self = [super init]) != nil) {
1406 name_ = [name retain];
1408 packages_ = [[NSMutableArray arrayWithCapacity:16] retain];
1412 - (NSString *) name {
1420 - (NSArray *) packages {
1425 return [packages_ count];
1428 - (void) addPackage:(Package *)package {
1429 [packages_ addObject:package];
1435 /* Package View {{{ */
1436 @protocol PackageViewDelegate
1437 - (void) performPackage:(Package *)package;
1440 @interface PackageView : UIView {
1441 UIPreferencesTable *table_;
1443 UITextView *description_;
1449 - (int) numberOfGroupsInPreferencesTable:(UIPreferencesTable *)table;
1450 - (NSString *) preferencesTable:(UIPreferencesTable *)table titleForGroup:(int)group;
1451 - (float) preferencesTable:(UIPreferencesTable *)table heightForRow:(int)row inGroup:(int)group withProposedHeight:(float)proposed;
1452 - (int) preferencesTable:(UIPreferencesTable *)table numberOfRowsInGroup:(int)group;
1453 - (UIPreferencesTableCell *) preferencesTable:(UIPreferencesTable *)table cellForRow:(int)row inGroup:(int)group;
1455 - (BOOL) canSelectRow:(int)row;
1456 - (void) tableRowSelected:(NSNotification *)notification;
1458 - (Package *) package;
1460 - (id) initWithFrame:(struct CGRect)frame;
1461 - (void) setPackage:(Package *)package;
1462 - (void) setDelegate:(id)delegate;
1465 @implementation PackageView
1468 if (package_ != nil)
1470 if (description_ != nil)
1471 [description_ release];
1476 - (int) numberOfGroupsInPreferencesTable:(UIPreferencesTable *)table {
1480 - (NSString *) preferencesTable:(UIPreferencesTable *)table titleForGroup:(int)group {
1483 case 1: return @"Package Details";
1484 case 2: return @"Source Information";
1486 default: _assert(false);
1490 - (float) preferencesTable:(UIPreferencesTable *)table heightForRow:(int)row inGroup:(int)group withProposedHeight:(float)proposed {
1491 if (group != 0 || row != 1)
1494 return [description_ visibleTextRect].size.height + TextViewOffset_;
1497 - (int) preferencesTable:(UIPreferencesTable *)table numberOfRowsInGroup:(int)group {
1499 case 0: return [package_ website] == nil ? 2 : 3;
1503 default: _assert(false);
1507 - (UIPreferencesTableCell *) preferencesTable:(UIPreferencesTable *)table cellForRow:(int)row inGroup:(int)group {
1508 UIPreferencesTableCell *cell = [[[UIPreferencesTableCell alloc] init] autorelease];
1509 [cell setShowSelection:NO];
1512 case 0: switch (row) {
1514 [cell setTitle:[package_ name]];
1515 [cell setValue:[package_ latest]];
1519 [cell addSubview:description_];
1523 [cell setTitle:@"More Information"];
1524 [cell setShowDisclosure:YES];
1525 [cell setShowSelection:YES];
1528 default: _assert(false);
1531 case 1: switch (row) {
1533 [cell setTitle:@"Identifier"];
1534 [cell setValue:[package_ id]];
1538 [cell setTitle:@"Installed Version"];
1539 NSString *installed([package_ installed]);
1540 [cell setValue:(installed == nil ? @"n/a" : installed)];
1544 [cell setTitle:@"Section"];
1545 NSString *section([package_ section]);
1546 [cell setValue:(section == nil ? @"n/a" : section)];
1550 [cell setTitle:@"Expanded Size"];
1551 [cell setValue:SizeString([package_ size])];
1555 [cell setTitle:@"Maintainer"];
1556 [cell setValue:[[package_ maintainer] name]];
1557 [cell setShowDisclosure:YES];
1558 [cell setShowSelection:YES];
1561 default: _assert(false);
1564 case 2: switch (row) {
1566 [cell setTitle:[[package_ source] label]];
1567 [cell setValue:[[package_ source] version]];
1571 [cell setValue:[[package_ source] description]];
1575 [cell setTitle:@"Origin"];
1576 [cell setValue:[[package_ source] origin]];
1579 default: _assert(false);
1582 default: _assert(false);
1588 - (BOOL) canSelectRow:(int)row {
1592 - (void) tableRowSelected:(NSNotification *)notification {
1593 int row = [table_ selectedRow];
1594 NSString *website = [package_ website];
1596 if (row == (website == nil ? 8 : 9))
1597 [delegate_ openURL:[NSURL URLWithString:[NSString stringWithFormat:@"mailto:%@?subject=%@",
1598 [[package_ maintainer] email],
1599 [[NSString stringWithFormat:@"regarding apt package \"%@\"", [package_ name]] stringByAddingPercentEscapes]
1601 else if (website != nil && row == 3)
1602 [delegate_ openURL:[NSURL URLWithString:website]];
1605 - (Package *) package {
1609 - (id) initWithFrame:(struct CGRect)frame {
1610 if ((self = [super initWithFrame:frame]) != nil) {
1611 table_ = [[UIPreferencesTable alloc] initWithFrame:[self bounds]];
1612 [self addSubview:table_];
1614 [table_ setDataSource:self];
1615 [table_ setDelegate:self];
1619 - (void) setPackage:(Package *)package {
1620 if (package_ != nil) {
1621 [package_ autorelease];
1625 if (description_ != nil) {
1626 [description_ release];
1630 if (package != nil) {
1631 package_ = [package retain];
1633 NSString *description([package description]);
1634 if (description == nil)
1635 description = [package tagline];
1636 description_ = [GetTextView(description, 12, true) retain];
1638 CGColorSpaceRef space = CGColorSpaceCreateDeviceRGB();
1639 CGColor black(space, 0, 0, 0, 1);
1640 [description_ setTextColor:black];
1641 CGColorSpaceRelease(space);
1643 [table_ reloadData];
1647 - (void) setDelegate:(id)delegate {
1648 delegate_ = delegate;
1653 /* Package Cell {{{ */
1654 @interface PackageCell : UITableCell {
1657 UITextLabel *description_;
1658 UITextLabel *source_;
1659 UITextLabel *version_;
1660 UIImageView *trusted_;
1666 - (PackageCell *) initWithVersioner:(SEL)versioner;
1667 - (void) setPackage:(Package *)package;
1669 - (void) _setSelected:(float)fraction;
1670 - (void) setSelected:(BOOL)selected;
1671 - (void) setSelected:(BOOL)selected withFade:(BOOL)fade;
1672 - (void) _setSelectionFadeFraction:(float)fraction;
1676 @implementation PackageCell
1681 [description_ release];
1688 - (PackageCell *) initWithVersioner:(SEL)versioner {
1689 if ((self = [super init]) != nil) {
1690 versioner_ = versioner;
1692 GSFontRef bold = GSFontCreateWithName("Helvetica", kGSFontTraitBold, 22);
1693 GSFontRef large = GSFontCreateWithName("Helvetica", kGSFontTraitNone, 16);
1694 GSFontRef small = GSFontCreateWithName("Helvetica", kGSFontTraitNone, 14);
1696 CGColorSpaceRef space = CGColorSpaceCreateDeviceRGB();
1698 CGColor clear(space, 0, 0, 0, 0);
1700 icon_ = [[UIImageView alloc] initWithFrame:CGRectMake(10, 10, 30, 30)];
1702 name_ = [[UITextLabel alloc] initWithFrame:CGRectMake(48, 12, 240, 25)];
1703 [name_ setBackgroundColor:clear];
1704 [name_ setFont:bold];
1706 description_ = [[UITextLabel alloc] initWithFrame:CGRectMake(12, 46, 280, 20)];
1707 [description_ setBackgroundColor:clear];
1708 [description_ setFont:small];
1710 source_ = [[UITextLabel alloc] initWithFrame:CGRectMake(12, 72, 150, 20)];
1711 [source_ setBackgroundColor:clear];
1712 [source_ setFont:large];
1714 version_ = [[UIRightTextLabel alloc] initWithFrame:CGRectMake(286, 69, 70, 25)];
1715 [version_ setBackgroundColor:clear];
1716 [version_ setFont:large];
1718 //trusted_ = [[UIImageView alloc] initWithFrame:CGRectMake(278, 7, 16, 16)];
1719 trusted_ = [[UIImageView alloc] initWithFrame:CGRectMake(30, 30, 16, 16)];
1720 [trusted_ setImage:[UIImage applicationImageNamed:@"trusted.png"]];
1722 [self addSubview:icon_];
1723 [self addSubview:name_];
1724 [self addSubview:description_];
1725 [self addSubview:source_];
1726 [self addSubview:version_];
1728 CGColorSpaceRelease(space);
1736 - (void) setPackage:(Package *)package {
1737 UIImage *image = nil;
1738 if (NSString *icon = [package icon])
1739 image = [UIImage imageAtPath:[icon substringFromIndex:6]];
1741 image = [UIImage applicationImageNamed:@"unknown.png"];
1743 [icon_ setImage:image];
1744 [icon_ zoomToScale:0.5f];
1745 [icon_ setFrame:CGRectMake(10, 10, 30, 30)];
1747 [name_ setText:[package name]];
1748 [version_ setText:[package latest]];
1749 [description_ setText:[package tagline]];
1751 Source *source = [package source];
1755 if (source == nil) {
1759 label = [source label];
1760 trusted = [source trusted];
1763 [source_ setText:[NSString stringWithFormat:@"from %@", label]];
1765 [trusted_ removeFromSuperview];
1767 [self addSubview:trusted_];
1770 - (void) _setSelected:(float)fraction {
1771 CGColorSpaceRef space = CGColorSpaceCreateDeviceRGB();
1773 CGColor black(space,
1774 interpolate(0.0, 1.0, fraction),
1775 interpolate(0.0, 1.0, fraction),
1776 interpolate(0.0, 1.0, fraction),
1780 interpolate(0.2, 1.0, fraction),
1781 interpolate(0.2, 1.0, fraction),
1782 interpolate(1.0, 1.0, fraction),
1786 interpolate(0.4, 1.0, fraction),
1787 interpolate(0.4, 1.0, fraction),
1788 interpolate(0.4, 1.0, fraction),
1791 [name_ setColor:black];
1792 [description_ setColor:gray];
1793 [source_ setColor:black];
1794 [version_ setColor:blue];
1796 CGColorSpaceRelease(space);
1799 - (void) setSelected:(BOOL)selected {
1800 [self _setSelected:(selected ? 1.0 : 0.0)];
1801 [super setSelected:selected];
1804 - (void) setSelected:(BOOL)selected withFade:(BOOL)fade {
1806 [self _setSelected:(selected ? 1.0 : 0.0)];
1807 [super setSelected:selected withFade:fade];
1810 - (void) _setSelectionFadeFraction:(float)fraction {
1811 [self _setSelected:fraction];
1812 [super _setSelectionFadeFraction:fraction];
1818 /* Database Implementation {{{ */
1819 @implementation Database
1826 - (void) _readStatus:(NSNumber *)fd {
1827 NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init];
1829 __gnu_cxx::stdio_filebuf<char> ib([fd intValue], std::ios::in);
1830 std::istream is(&ib);
1835 pcre *code = pcre_compile("^([^:]*):([^:]*):([^:]*):(.*)$", 0, &error, &offset, NULL);
1837 pcre_extra *study = NULL;
1839 pcre_fullinfo(code, study, PCRE_INFO_CAPTURECOUNT, &capture);
1840 int matches[(capture + 1) * 3];
1842 while (std::getline(is, line)) {
1843 const char *data(line.c_str());
1845 _assert(pcre_exec(code, study, data, line.size(), 0, 0, matches, sizeof(matches) / sizeof(matches[0])) >= 0);
1847 std::istringstream buffer(line.substr(matches[6], matches[7] - matches[6]));
1850 [delegate_ setPercent:(percent / 100)];
1852 NSString *string = [NSString stringWithCString:(data + matches[8]) length:(matches[9] - matches[8])];
1853 std::string type(line.substr(matches[2], matches[3] - matches[2]));
1855 if (type == "pmerror")
1856 [delegate_ setError:string];
1857 else if (type == "pmstatus")
1858 [delegate_ setTitle:string];
1859 else if (type == "pmconffile")
1861 else _assert(false);
1868 - (void) _readOutput:(NSNumber *)fd {
1869 NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init];
1871 __gnu_cxx::stdio_filebuf<char> ib([fd intValue], std::ios::in);
1872 std::istream is(&ib);
1875 while (std::getline(is, line))
1876 [delegate_ addOutput:[NSString stringWithCString:line.c_str()]];
1882 - (Package *) packageWithName:(NSString *)name {
1883 pkgCache::PkgIterator iterator(cache_->FindPkg([name cString]));
1884 return iterator.end() ? nil : [Package packageWithIterator:iterator database:self];
1887 - (Database *) init {
1888 if ((self = [super init]) != nil) {
1894 sources_ = [[NSMutableDictionary dictionaryWithCapacity:16] retain];
1898 _assert(pipe(fds) != -1);
1902 detachNewThreadSelector:@selector(_readStatus:)
1904 withObject:[[NSNumber numberWithInt:fds[0]] retain]
1907 _assert(pipe(fds) != -1);
1908 _assert(dup2(fds[1], 1) != -1);
1909 _assert(close(fds[1]) != -1);
1912 detachNewThreadSelector:@selector(_readOutput:)
1914 withObject:[[NSNumber numberWithInt:fds[0]] retain]
1919 - (pkgCacheFile &) cache {
1923 - (pkgRecords *) records {
1927 - (pkgProblemResolver *) resolver {
1931 - (pkgAcquire &) fetcher {
1935 - (void) reloadData {
1945 if (!cache_.Open(progress_, true)) {
1946 fprintf(stderr, "repairing corrupted database...\n");
1949 _assert(cache_.Open(progress_, true));
1952 records_ = new pkgRecords(cache_);
1953 resolver_ = new pkgProblemResolver(cache_);
1954 fetcher_ = new pkgAcquire(&status_);
1957 list_ = new pkgSourceList();
1958 _assert(list_->ReadMainList());
1960 [sources_ removeAllObjects];
1961 for (pkgSourceList::const_iterator source = list_->begin(); source != list_->end(); ++source) {
1962 std::vector<pkgIndexFile *> *indices = (*source)->GetIndexFiles();
1963 for (std::vector<pkgIndexFile *>::const_iterator index = indices->begin(); index != indices->end(); ++index)
1965 setObject:[[[Source alloc] initWithMetaIndex:*source] autorelease]
1966 forKey:[NSNumber numberWithLong:reinterpret_cast<uintptr_t>(*index)]
1972 pkgRecords records(cache_);
1974 lock_ = new FileFd();
1975 lock_->Fd(GetLock(_config->FindDir("Dir::Cache::Archives") + "lock"));
1976 _assert(!_error->PendingError());
1979 _assert(list.ReadMainList());
1981 manager_ = (_system->CreatePM(cache_));
1982 _assert(manager_->GetArchives(fetcher_, &list, &records));
1983 _assert(!_error->PendingError());
1987 if (fetcher_->Run(PulseInterval_) != pkgAcquire::Continue)
1991 pkgPackageManager::OrderResult result = manager_->DoInstall(statusfd_);
1993 if (result == pkgPackageManager::Failed)
1995 if (_error->PendingError())
1997 if (result != pkgPackageManager::Completed)
2003 _assert(list.ReadMainList());
2006 lock.Fd(GetLock(_config->FindDir("Dir::State::Lists") + "lock"));
2007 _assert(!_error->PendingError());
2009 pkgAcquire fetcher(&status_);
2010 _assert(list.GetIndexes(&fetcher));
2011 _assert(fetcher.Run(PulseInterval_) != pkgAcquire::Failed);
2013 bool failed = false;
2014 for (pkgAcquire::ItemIterator item = fetcher.ItemsBegin(); item != fetcher.ItemsEnd(); item++)
2015 if ((*item)->Status != pkgAcquire::Item::StatDone) {
2016 (*item)->Finished();
2020 if (!failed && _config->FindB("APT::Get::List-Cleanup", true) == true) {
2021 _assert(fetcher.Clean(_config->FindDir("Dir::State::lists")));
2022 _assert(fetcher.Clean(_config->FindDir("Dir::State::lists") + "partial/"));
2025 [Metadata_ setObject:[NSDate date] forKey:@"LastUpdate"];
2029 _assert(cache_->DelCount() == 0 && cache_->InstCount() == 0);
2030 _assert(pkgApplyStatus(cache_));
2032 if (cache_->BrokenCount() != 0) {
2033 _assert(pkgFixBroken(cache_));
2034 _assert(cache_->BrokenCount() == 0);
2035 _assert(pkgMinimizeUpgrade(cache_));
2038 _assert(pkgDistUpgrade(cache_));
2041 - (void) setDelegate:(id)delegate {
2042 delegate_ = delegate;
2043 status_.setDelegate(delegate);
2044 progress_.setDelegate(delegate);
2047 - (Source *) getSource:(const pkgCache::PkgFileIterator &)file {
2048 pkgIndexFile *index(NULL);
2049 list_->FindIndex(file, index);
2050 return [sources_ objectForKey:[NSNumber numberWithLong:reinterpret_cast<uintptr_t>(index)]];
2056 /* Progress Data {{{ */
2057 @interface ProgressData : NSObject {
2063 - (ProgressData *) initWithSelector:(SEL)selector target:(id)target object:(id)object;
2070 @implementation ProgressData
2072 - (ProgressData *) initWithSelector:(SEL)selector target:(id)target object:(id)object {
2073 if ((self = [super init]) != nil) {
2074 selector_ = selector;
2094 /* Progress View {{{ */
2095 @interface ProgressView : UIView <
2099 UIView *background_;
2100 UITransitionView *transition_;
2102 UINavigationBar *navbar_;
2103 UIProgressBar *progress_;
2104 UITextView *output_;
2105 UITextLabel *status_;
2111 - (void) transitionViewDidComplete:(UITransitionView*)view fromView:(UIView*)from toView:(UIView*)to;
2113 - (ProgressView *) initWithFrame:(struct CGRect)frame delegate:(id)delegate;
2114 - (void) setContentView:(UIView *)view;
2117 - (void) alertSheet:(UIAlertSheet *)sheet buttonClicked:(int)button;
2119 - (void) _retachThread;
2120 - (void) _detachNewThreadData:(ProgressData *)data;
2121 - (void) detachNewThreadSelector:(SEL)selector toTarget:(id)target withObject:(id)object title:(NSString *)title;
2123 - (void) setError:(NSString *)error;
2124 - (void) _setError:(NSString *)error;
2126 - (void) setTitle:(NSString *)title;
2127 - (void) _setTitle:(NSString *)title;
2129 - (void) setPercent:(float)percent;
2130 - (void) _setPercent:(NSNumber *)percent;
2132 - (void) addOutput:(NSString *)output;
2133 - (void) _addOutput:(NSString *)output;
2136 @protocol ProgressViewDelegate
2137 - (void) progressViewIsComplete:(ProgressView *)sender;
2140 @implementation ProgressView
2144 if (background_ != nil)
2145 [background_ release];
2146 [transition_ release];
2149 [progress_ release];
2155 - (void) transitionViewDidComplete:(UITransitionView*)view fromView:(UIView*)from toView:(UIView*)to {
2156 if (bootstrap_ && from == overlay_ && to == view_)
2160 - (ProgressView *) initWithFrame:(struct CGRect)frame delegate:(id)delegate {
2161 if ((self = [super initWithFrame:frame]) != nil) {
2162 delegate_ = delegate;
2164 CGColorSpaceRef space = CGColorSpaceCreateDeviceRGB();
2166 CGColor black(space, 0.0, 0.0, 0.0, 1.0);
2167 CGColor white(space, 1.0, 1.0, 1.0, 1.0);
2168 CGColor clear(space, 0.0, 0.0, 0.0, 0.0);
2170 transition_ = [[UITransitionView alloc] initWithFrame:[self bounds]];
2171 [transition_ setDelegate:self];
2173 overlay_ = [[UIView alloc] initWithFrame:[transition_ bounds]];
2176 [overlay_ setBackgroundColor:black];
2178 background_ = [[UIView alloc] initWithFrame:[self bounds]];
2179 [background_ setBackgroundColor:black];
2180 [self addSubview:background_];
2183 [self addSubview:transition_];
2185 CGSize navsize = [UINavigationBar defaultSize];
2186 CGRect navrect = {{0, 0}, navsize};
2188 navbar_ = [[UINavigationBar alloc] initWithFrame:navrect];
2189 [overlay_ addSubview:navbar_];
2191 [navbar_ setBarStyle:1];
2192 [navbar_ setDelegate:self];
2194 UINavigationItem *navitem = [[[UINavigationItem alloc] initWithTitle:nil] autorelease];
2195 [navbar_ pushNavigationItem:navitem];
2197 CGRect bounds = [overlay_ bounds];
2198 CGSize prgsize = [UIProgressBar defaultSize];
2201 (bounds.size.width - prgsize.width) / 2,
2202 bounds.size.height - prgsize.height - 20
2205 progress_ = [[UIProgressBar alloc] initWithFrame:prgrect];
2206 [overlay_ addSubview:progress_];
2208 status_ = [[UITextLabel alloc] initWithFrame:CGRectMake(
2210 bounds.size.height - prgsize.height - 50,
2211 bounds.size.width - 20,
2215 [status_ setColor:white];
2216 [status_ setBackgroundColor:clear];
2218 [status_ setCentersHorizontally:YES];
2219 //[status_ setFont:font];
2221 output_ = [[UITextView alloc] initWithFrame:CGRectMake(
2223 navrect.size.height + 20,
2224 bounds.size.width - 20,
2225 bounds.size.height - navsize.height - 62 - navrect.size.height
2228 //[output_ setTextFont:@"Courier New"];
2229 [output_ setTextSize:12];
2231 [output_ setTextColor:white];
2232 [output_ setBackgroundColor:clear];
2234 [output_ setMarginTop:0];
2235 [output_ setAllowsRubberBanding:YES];
2237 [overlay_ addSubview:output_];
2238 [overlay_ addSubview:status_];
2240 [progress_ setStyle:0];
2242 CGColorSpaceRelease(space);
2246 - (void) setContentView:(UIView *)view {
2247 view_ = [view retain];
2250 - (void) resetView {
2251 [transition_ transition:6 toView:view_];
2254 - (void) alertSheet:(UIAlertSheet *)sheet buttonClicked:(int)button {
2258 - (void) _retachThread {
2259 [delegate_ progressViewIsComplete:self];
2263 - (void) _detachNewThreadData:(ProgressData *)data {
2264 NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init];
2266 [[data target] performSelector:[data selector] withObject:[data object]];
2269 [self performSelectorOnMainThread:@selector(_retachThread) withObject:nil waitUntilDone:YES];
2274 - (void) detachNewThreadSelector:(SEL)selector toTarget:(id)target withObject:(id)object title:(NSString *)title {
2275 [navbar_ popNavigationItem];
2276 UINavigationItem *navitem = [[[UINavigationItem alloc] initWithTitle:title] autorelease];
2277 [navbar_ pushNavigationItem:navitem];
2279 [status_ setText:nil];
2280 [output_ setText:@""];
2281 [progress_ setProgress:0];
2283 [transition_ transition:6 toView:overlay_];
2286 detachNewThreadSelector:@selector(_detachNewThreadData:)
2288 withObject:[[ProgressData alloc]
2289 initWithSelector:selector
2296 - (void) setError:(NSString *)error {
2298 performSelectorOnMainThread:@selector(_setError:)
2304 - (void) _setError:(NSString *)error {
2305 UIAlertSheet *sheet = [[[UIAlertSheet alloc]
2306 initWithTitle:@"Package Error"
2307 buttons:[NSArray arrayWithObjects:@"Okay", nil]
2308 defaultButtonIndex:0
2313 [sheet setBodyText:error];
2314 [sheet popupAlertAnimated:YES];
2317 - (void) setTitle:(NSString *)title {
2319 performSelectorOnMainThread:@selector(_setTitle:)
2325 - (void) _setTitle:(NSString *)title {
2326 [status_ setText:[title stringByAppendingString:@"..."]];
2329 - (void) setPercent:(float)percent {
2331 performSelectorOnMainThread:@selector(_setPercent:)
2332 withObject:[NSNumber numberWithFloat:percent]
2337 - (void) _setPercent:(NSNumber *)percent {
2338 [progress_ setProgress:[percent floatValue]];
2341 - (void) addOutput:(NSString *)output {
2343 performSelectorOnMainThread:@selector(_addOutput:)
2349 - (void) _addOutput:(NSString *)output {
2350 [output_ setText:[NSString stringWithFormat:@"%@\n%@", [output_ text], output]];
2351 CGSize size = [output_ contentSize];
2352 CGRect rect = {{0, size.height}, {size.width, 0}};
2353 [output_ scrollRectToVisible:rect animated:YES];
2359 /* Package Table {{{ */
2360 @protocol PackageTableDelegate
2361 - (void) packageTable:(id)table packageSelected:(Package *)package;
2364 @interface PackageTable : UIView {
2366 UISectionList *list_;
2370 NSMutableArray *sections_;
2375 - (int) numberOfSectionsInSectionList:(UISectionList *)list;
2376 - (NSString *) sectionList:(UISectionList *)list titleForSection:(int)section;
2377 - (int) sectionList:(UISectionList *)list rowForSection:(int)section;
2379 - (int) numberOfRowsInTable:(UITable *)table;
2380 - (float) table:(UITable *)table heightForRow:(int)row;
2381 - (UITableCell *) table:(UITable *)table cellForRow:(int)row column:(UITableColumn *)col reusing:(UITableCell *)reusing;
2382 - (BOOL) table:(UITable *)table showDisclosureForRow:(int)row;
2383 - (void) tableRowSelected:(NSNotification *)notification;
2385 - (id) initWithFrame:(CGRect)frame versioner:(SEL)versioner;
2387 - (void) setDelegate:(id)delegate;
2388 - (void) setPackages:(NSArray *)packages;
2390 - (void) resetViewAnimated:(BOOL)animated;
2391 - (UITable *) table;
2394 @implementation PackageTable
2398 [sections_ release];
2399 if (packages_ != nil)
2400 [packages_ release];
2404 - (int) numberOfSectionsInSectionList:(UISectionList *)list {
2405 return [sections_ count];
2408 - (NSString *) sectionList:(UISectionList *)list titleForSection:(int)section {
2409 return [[sections_ objectAtIndex:section] name];
2412 - (int) sectionList:(UISectionList *)list rowForSection:(int)section {
2413 return [[sections_ objectAtIndex:section] row];
2416 - (int) numberOfRowsInTable:(UITable *)table {
2417 return [packages_ count];
2420 - (float) table:(UITable *)table heightForRow:(int)row {
2424 - (UITableCell *) table:(UITable *)table cellForRow:(int)row column:(UITableColumn *)col reusing:(UITableCell *)reusing {
2426 reusing = [[[PackageCell alloc] initWithVersioner:versioner_] autorelease];
2427 [(PackageCell *)reusing setPackage:[packages_ objectAtIndex:row]];
2431 - (BOOL) table:(UITable *)table showDisclosureForRow:(int)row {
2435 - (void) tableRowSelected:(NSNotification *)notification {
2436 int row = [[notification object] selectedRow];
2437 [delegate_ packageTable:self packageSelected:(row == INT_MAX ? nil : [packages_ objectAtIndex:row])];
2440 - (id) initWithFrame:(CGRect)frame versioner:(SEL)versioner {
2441 if ((self = [super initWithFrame:frame]) != nil) {
2442 versioner_ = versioner;
2443 sections_ = [[NSMutableArray arrayWithCapacity:16] retain];
2445 list_ = [[UISectionList alloc] initWithFrame:[self bounds] showSectionIndex:YES];
2446 [list_ setDataSource:self];
2448 UITableColumn *column = [[[UITableColumn alloc]
2449 initWithTitle:@"Name"
2451 width:frame.size.width
2454 UITable *table = [list_ table];
2455 [table setSeparatorStyle:1];
2456 [table addTableColumn:column];
2457 [table setDelegate:self];
2458 [table setReusesTableCells:YES];
2460 [self addSubview:list_];
2464 - (void) setDelegate:(id)delegate {
2465 delegate_ = delegate;
2468 - (void) setPackages:(NSArray *)packages {
2469 if (packages_ != nil)
2470 [packages_ autorelease];
2471 _assert(packages != nil);
2472 packages_ = [packages retain];
2474 [sections_ removeAllObjects];
2476 Section *section = nil;
2478 for (size_t offset(0); offset != [packages_ count]; ++offset) {
2479 Package *package = [packages_ objectAtIndex:offset];
2480 NSString *name = [package index];
2482 if (section == nil || ![[section name] isEqual:name]) {
2483 section = [[[Section alloc] initWithName:name row:offset] autorelease];
2484 [sections_ addObject:section];
2487 [section addPackage:package];
2493 - (void) resetViewAnimated:(BOOL)animated {
2494 [[list_ table] selectRow:-1 byExtendingSelection:NO withFade:animated];
2497 - (UITable *) table {
2498 return [list_ table];
2504 /* Section Cell {{{ */
2505 @interface SectionCell : UITableCell {
2507 UITextLabel *count_;
2513 - (void) setSection:(Section *)section;
2515 - (void) _setSelected:(float)fraction;
2516 - (void) setSelected:(BOOL)selected;
2517 - (void) setSelected:(BOOL)selected withFade:(BOOL)fade;
2518 - (void) _setSelectionFadeFraction:(float)fraction;
2522 @implementation SectionCell
2531 if ((self = [super init]) != nil) {
2532 GSFontRef bold = GSFontCreateWithName("Helvetica", kGSFontTraitBold, 22);
2533 GSFontRef small = GSFontCreateWithName("Helvetica", kGSFontTraitBold, 12);
2535 CGColorSpaceRef space = CGColorSpaceCreateDeviceRGB();
2536 CGColor clear(space, 0, 0, 0, 0);
2537 CGColor white(space, 1, 1, 1, 1);
2539 name_ = [[UITextLabel alloc] initWithFrame:CGRectMake(48, 9, 250, 25)];
2540 [name_ setBackgroundColor:clear];
2541 [name_ setFont:bold];
2543 count_ = [[UITextLabel alloc] initWithFrame:CGRectMake(11, 7, 29, 32)];
2544 [count_ setCentersHorizontally:YES];
2545 [count_ setBackgroundColor:clear];
2546 [count_ setFont:small];
2547 [count_ setColor:white];
2549 UIImageView *folder = [[[UIImageView alloc] initWithFrame:CGRectMake(8, 7, 32, 32)] autorelease];
2550 [folder setImage:[UIImage applicationImageNamed:@"folder.png"]];
2552 [self addSubview:folder];
2553 [self addSubview:name_];
2554 [self addSubview:count_];
2556 [self _setSelected:0];
2558 CGColorSpaceRelease(space);
2565 - (void) setSection:(Section *)section {
2566 if (section == nil) {
2567 [name_ setText:@"All Packages"];
2568 [count_ setText:nil];
2570 NSString *name = [section name];
2571 [name_ setText:(name == nil ? @"(No Section)" : name)];
2572 [count_ setText:[NSString stringWithFormat:@"%d", [section count]]];
2576 - (void) _setSelected:(float)fraction {
2577 CGColorSpaceRef space = CGColorSpaceCreateDeviceRGB();
2579 CGColor black(space,
2580 interpolate(0.0, 1.0, fraction),
2581 interpolate(0.0, 1.0, fraction),
2582 interpolate(0.0, 1.0, fraction),
2585 [name_ setColor:black];
2587 CGColorSpaceRelease(space);
2590 - (void) setSelected:(BOOL)selected {
2591 [self _setSelected:(selected ? 1.0 : 0.0)];
2592 [super setSelected:selected];
2595 - (void) setSelected:(BOOL)selected withFade:(BOOL)fade {
2597 [self _setSelected:(selected ? 1.0 : 0.0)];
2598 [super setSelected:selected withFade:fade];
2601 - (void) _setSelectionFadeFraction:(float)fraction {
2602 [self _setSelected:fraction];
2603 [super _setSelectionFadeFraction:fraction];
2608 /* Install View {{{ */
2609 @interface InstallView : ResetView <
2610 PackageTableDelegate
2614 PackageTable *table_;
2618 NSMutableArray *packages_;
2623 - (void) navigationBar:(UINavigationBar *)navbar buttonClicked:(int)button;
2625 - (int) numberOfRowsInTable:(UITable *)table;
2626 - (float) table:(UITable *)table heightForRow:(int)row;
2627 - (UITableCell *) table:(UITable *)table cellForRow:(int)row column:(UITableColumn *)col reusing:(UITableCell *)reusing;
2628 - (BOOL) table:(UITable *)table showDisclosureForRow:(int)row;
2629 - (void) tableRowSelected:(NSNotification *)notification;
2631 - (void) packageTable:(id)table packageSelected:(Package *)package;
2633 - (id) initWithFrame:(CGRect)frame;
2634 - (void) setPackages:(NSArray *)packages;
2635 - (void) setDelegate:(id)delegate;
2638 @implementation InstallView
2641 [packages_ release];
2642 if (sections_ != nil)
2643 [sections_ release];
2650 if (section_ != nil)
2652 if (package_ != nil)
2657 - (void) navigationBar:(UINavigationBar *)navbar buttonClicked:(int)button {
2659 [[view_ package] install];
2660 [delegate_ resolve];
2661 [delegate_ perform];
2665 - (int) numberOfRowsInTable:(UITable *)table {
2666 return [sections_ count] + 1;
2669 - (float) table:(UITable *)table heightForRow:(int)row {
2673 - (UITableCell *) table:(UITable *)table cellForRow:(int)row column:(UITableColumn *)col reusing:(UITableCell *)reusing {
2675 reusing = [[[SectionCell alloc] init] autorelease];
2677 [(SectionCell *)reusing setSection:nil];
2679 [(SectionCell *)reusing setSection:[sections_ objectAtIndex:(row - 1)]];
2683 - (BOOL) table:(UITable *)table showDisclosureForRow:(int)row {
2687 - (void) tableRowSelected:(NSNotification *)notification {
2688 int row = [[notification object] selectedRow];
2690 if (row == INT_MAX) {
2697 _assert(section_ == nil);
2698 _assert(table_ == nil);
2706 name = @"All Packages";
2708 section = [sections_ objectAtIndex:(row - 1)];
2709 name = [section name];
2710 section_ = [name retain];
2713 table_ = [[PackageTable alloc] initWithFrame:[transition_ bounds] versioner:@selector(latest)];
2714 [table_ setDelegate:self];
2715 [table_ setPackages:(section == nil ? packages_ : [section packages])];
2717 [self pushView:table_ withTitle:name backButtonTitle:@"Packages" rightButton:nil];
2721 - (void) packageTable:(id)table packageSelected:(Package *)package {
2722 if (package == nil) {
2729 _assert(package_ == nil);
2730 _assert(view_ == nil);
2732 package_ = [[package name] retain];
2734 view_ = [[PackageView alloc] initWithFrame:[transition_ bounds]];
2735 [view_ setDelegate:delegate_];
2737 [view_ setPackage:package];
2739 [self pushView:view_ withTitle:[package name] backButtonTitle:nil rightButton:@"Install"];
2743 - (id) initWithFrame:(CGRect)frame {
2744 if ((self = [super initWithFrame:frame]) != nil) {
2745 packages_ = [[NSMutableArray arrayWithCapacity:16] retain];
2747 list_ = [[UITable alloc] initWithFrame:[transition_ bounds]];
2748 [self pushView:list_ withTitle:@"Install" backButtonTitle:@"Sections" rightButton:nil];
2750 UITableColumn *column = [[[UITableColumn alloc]
2751 initWithTitle:@"Name"
2753 width:frame.size.width
2756 [list_ setDataSource:self];
2757 [list_ setSeparatorStyle:1];
2758 [list_ addTableColumn:column];
2759 [list_ setDelegate:self];
2760 [list_ setReusesTableCells:YES];
2762 [transition_ transition:0 toView:list_];
2766 - (void) setPackages:(NSArray *)packages {
2767 [packages_ removeAllObjects];
2769 for (size_t i(0); i != [packages count]; ++i) {
2770 Package *package([packages objectAtIndex:i]);
2771 if ([package installed] == nil)
2772 [packages_ addObject:package];
2775 [packages_ sortUsingSelector:@selector(compareBySectionAndName:)];
2776 NSMutableArray *sections = [NSMutableArray arrayWithCapacity:16];
2778 Section *nsection = nil;
2779 Package *npackage = nil;
2781 Section *section = nil;
2782 for (size_t offset = 0, count = [packages_ count]; offset != count; ++offset) {
2783 Package *package = [packages_ objectAtIndex:offset];
2784 NSString *name = [package section];
2786 if (section == nil || name != nil && ![[section name] isEqual:name]) {
2787 section = [[[Section alloc] initWithName:name row:offset] autorelease];
2789 if (name == nil || [name isEqualToString:section_])
2791 [sections addObject:section];
2794 if ([[package name] isEqualToString:package_])
2796 [section addPackage:package];
2799 if (sections_ != nil)
2800 [sections_ release];
2801 sections_ = [sections retain];
2803 [packages_ sortUsingSelector:@selector(compareByName:)];
2809 if (npackage != nil)
2810 [view_ setPackage:npackage];
2811 else if (package_ != nil)
2814 if (table_ != nil && section_ == nil)
2815 [table_ setPackages:packages_];
2816 else if (nsection != nil)
2817 [table_ setPackages:[nsection packages]];
2818 else if (section_ != nil)
2822 [self popViews:views];
2826 - (void) setDelegate:(id)delegate {
2828 [view_ setDelegate:delegate];
2829 [super setDelegate:delegate];
2834 /* Changes View {{{ */
2835 @interface ChangesView : ResetView <
2836 PackageTableDelegate
2838 UISectionList *list_;
2839 NSMutableArray *packages_;
2840 NSMutableArray *sections_;
2848 - (void) navigationBar:(UINavigationBar *)navbar buttonClicked:(int)button;
2850 - (int) numberOfSectionsInSectionList:(UISectionList *)list;
2851 - (NSString *) sectionList:(UISectionList *)list titleForSection:(int)section;
2852 - (int) sectionList:(UISectionList *)list rowForSection:(int)section;
2854 - (int) numberOfRowsInTable:(UITable *)table;
2855 - (float) table:(UITable *)table heightForRow:(int)row;
2856 - (UITableCell *) table:(UITable *)table cellForRow:(int)row column:(UITableColumn *)col reusing:(UITableCell *)reusing;
2857 - (BOOL) table:(UITable *)table showDisclosureForRow:(int)row;
2858 - (void) tableRowSelected:(NSNotification *)notification;
2860 - (id) initWithFrame:(CGRect)frame;
2861 - (void) setPackages:(NSArray *)packages;
2862 - (void) _resetView;
2865 - (void) setDelegate:(id)delegate;
2868 @implementation ChangesView
2872 [packages_ release];
2873 [sections_ release];
2876 if (package_ != nil)
2881 - (int) numberOfSectionsInSectionList:(UISectionList *)list {
2882 return [sections_ count];
2885 - (NSString *) sectionList:(UISectionList *)list titleForSection:(int)section {
2886 return [[sections_ objectAtIndex:section] name];
2889 - (int) sectionList:(UISectionList *)list rowForSection:(int)section {
2890 return [[sections_ objectAtIndex:section] row];
2893 - (int) numberOfRowsInTable:(UITable *)table {
2894 return [packages_ count];
2897 - (float) table:(UITable *)table heightForRow:(int)row {
2901 - (UITableCell *) table:(UITable *)table cellForRow:(int)row column:(UITableColumn *)col reusing:(UITableCell *)reusing {
2903 reusing = [[[PackageCell alloc] initWithVersioner:NULL] autorelease];
2904 [(PackageCell *)reusing setPackage:[packages_ objectAtIndex:row]];
2908 - (BOOL) table:(UITable *)table showDisclosureForRow:(int)row {
2912 - (void) tableRowSelected:(NSNotification *)notification {
2913 int row = [[notification object] selectedRow];
2914 [self packageTable:self packageSelected:(row == INT_MAX ? nil : [packages_ objectAtIndex:row])];
2917 - (void) navigationBar:(UINavigationBar *)navbar buttonClicked:(int)button {
2920 [[view_ package] install];
2921 [delegate_ resolve];
2922 [delegate_ perform];
2926 [delegate_ upgrade];
2931 - (void) packageTable:(id)table packageSelected:(Package *)package {
2932 if (package == nil) {
2939 _assert(package_ == nil);
2940 _assert(view_ == nil);
2942 package_ = [[package name] retain];
2944 view_ = [[PackageView alloc] initWithFrame:[transition_ bounds]];
2945 [view_ setDelegate:delegate_];
2947 [view_ setPackage:package];
2949 [self pushView:view_ withTitle:[package name] backButtonTitle:nil rightButton:(
2950 [package upgradable] ? @"Upgrade" : @"Install"
2955 - (id) initWithFrame:(CGRect)frame {
2956 if ((self = [super initWithFrame:frame]) != nil) {
2957 packages_ = [[NSMutableArray arrayWithCapacity:16] retain];
2958 sections_ = [[NSMutableArray arrayWithCapacity:16] retain];
2960 list_ = [[UISectionList alloc] initWithFrame:[transition_ bounds] showSectionIndex:NO];
2961 [list_ setShouldHideHeaderInShortLists:NO];
2962 [list_ setDataSource:self];
2963 //[list_ setSectionListStyle:1];
2965 UITableColumn *column = [[[UITableColumn alloc]
2966 initWithTitle:@"Name"
2968 width:frame.size.width
2971 UITable *table = [list_ table];
2972 [table setSeparatorStyle:1];
2973 [table addTableColumn:column];
2974 [table setDelegate:self];
2975 [table setReusesTableCells:YES];
2977 [self pushView:list_ withTitle:@"Changes" backButtonTitle:nil rightButton:nil];
2981 - (void) setPackages:(NSArray *)packages {
2982 [packages_ removeAllObjects];
2983 for (size_t i(0); i != [packages count]; ++i) {
2984 Package *package([packages objectAtIndex:i]);
2985 if ([package installed] == nil || [package upgradable])
2986 [packages_ addObject:package];
2989 [packages_ sortUsingSelector:@selector(compareForChanges:)];
2991 [sections_ removeAllObjects];
2993 Section *upgradable = [[[Section alloc] initWithName:@"Available Upgrades" row:0] autorelease];
2994 Section *section = nil;
2997 Package *npackage = nil;
2998 for (size_t offset = 0, count = [packages_ count]; offset != count; ++offset) {
2999 Package *package = [packages_ objectAtIndex:offset];
3000 if ([[package name] isEqualToString:package_])
3003 if ([package upgradable])
3004 [upgradable addPackage:package];
3006 NSDate *seen = [package seen];
3008 CFLocaleRef locale = CFLocaleCopyCurrent();
3009 CFDateFormatterRef formatter = CFDateFormatterCreate(NULL, locale, kCFDateFormatterMediumStyle, kCFDateFormatterMediumStyle);
3010 CFStringRef formatted = CFDateFormatterCreateStringWithDate(NULL, formatter, (CFDateRef) seen);
3012 NSString *name = (NSString *) formatted;
3014 if (section == nil || ![[section name] isEqual:name]) {
3015 section = [[[Section alloc] initWithName:name row:offset] autorelease];
3016 [sections_ addObject:section];
3019 [section addPackage:package];
3021 CFRelease(formatter);
3022 CFRelease(formatted);
3027 count_ = [[upgradable packages] count];
3029 [sections_ insertObject:upgradable atIndex:0];
3033 if (npackage != nil)
3034 [view_ setPackage:npackage];
3035 else if (package_ != nil)
3042 - (void) _resetView {
3043 if ([views_ count] == 1)
3044 [navbar_ showButtonsWithLeftTitle:(count_ == 0 ? nil : @"Upgrade All") rightTitle:nil];
3051 - (void) setDelegate:(id)delegate {
3053 [view_ setDelegate:delegate];
3054 [super setDelegate:delegate];
3059 /* Manage View {{{ */
3060 @interface ManageView : ResetView <
3061 PackageTableDelegate
3063 PackageTable *table_;
3070 - (void) navigationBar:(UINavigationBar *)navbar buttonClicked:(int)button;
3072 - (void) packageTable:(id)table packageSelected:(Package *)package;
3074 - (id) initWithFrame:(CGRect)frame;
3075 - (void) setPackages:(NSArray *)packages;
3077 - (void) setDelegate:(id)delegate;
3080 @implementation ManageView
3086 if (package_ != nil)
3091 - (void) navigationBar:(UINavigationBar *)navbar buttonClicked:(int)button {
3093 [[view_ package] remove];
3094 [delegate_ resolve];
3095 [delegate_ perform];
3099 - (void) packageTable:(id)table packageSelected:(Package *)package {
3100 if (package == nil) {
3107 _assert(package_ == nil);
3108 _assert(view_ == nil);
3110 package_ = [[package name] retain];
3112 view_ = [[PackageView alloc] initWithFrame:[transition_ bounds]];
3113 [view_ setDelegate:delegate_];
3115 [view_ setPackage:package];
3117 [self pushView:view_ withTitle:[package name] backButtonTitle:nil rightButton:@"Uninstall"];
3121 - (id) initWithFrame:(CGRect)frame {
3122 if ((self = [super initWithFrame:frame]) != nil) {
3123 table_ = [[PackageTable alloc] initWithFrame:[transition_ bounds] versioner:@selector(latest)];
3124 [table_ setDelegate:self];
3126 [self pushView:table_ withTitle:@"Uninstall" backButtonTitle:@"Packages" rightButton:nil];
3130 - (void) setPackages:(NSArray *)packages {
3131 NSMutableArray *local = [NSMutableArray arrayWithCapacity:16];
3132 for (size_t i(0); i != [packages count]; ++i) {
3133 Package *package([packages objectAtIndex:i]);
3134 if ([package installed] != nil)
3135 [local addObject:package];
3138 [local sortUsingSelector:@selector(compareByName:)];
3140 Package *npackage = nil;
3141 for (size_t offset = 0, count = [local count]; offset != count; ++offset) {
3142 Package *package = [local objectAtIndex:offset];
3143 if ([[package name] isEqualToString:package_])
3147 [table_ setPackages:local];
3149 if (npackage != nil)
3150 [view_ setPackage:npackage];
3151 else if (package_ != nil)
3157 - (void) setDelegate:(id)delegate {
3159 [view_ setDelegate:delegate];
3160 [super setDelegate:delegate];
3165 /* Search View {{{ */
3166 @protocol SearchViewDelegate
3167 - (void) showKeyboard:(BOOL)show;
3170 @interface SearchView : ResetView <
3171 PackageTableDelegate
3173 NSMutableArray *packages_;
3175 UISearchField *field_;
3176 PackageTable *table_;
3183 - (void) navigationBar:(UINavigationBar *)navbar buttonClicked:(int)button;
3184 - (void) packageTable:(id)table packageSelected:(Package *)package;
3186 - (void) textFieldDidBecomeFirstResponder:(UITextField *)field;
3187 - (void) textFieldDidResignFirstResponder:(UITextField *)field;
3189 - (void) keyboardInputChanged:(UIFieldEditor *)editor;
3190 - (BOOL) keyboardInput:(id)input shouldInsertText:(NSString *)text isMarkedText:(int)marked;
3192 - (id) initWithFrame:(CGRect)frame;
3193 - (void) setPackages:(NSArray *)packages;
3195 - (void) setDelegate:(id)delegate;
3196 - (void) resetPackage:(Package *)package;
3197 - (void) searchPackages;
3201 @implementation SearchView
3204 [packages_ release];
3205 [accessory_ release];
3210 if (package_ != nil)
3215 - (void) navigationBar:(UINavigationBar *)navbar buttonClicked:(int)button {
3217 Package *package = [view_ package];
3218 if ([package installed] == nil)
3222 [delegate_ resolve];
3223 [delegate_ perform];
3227 - (void) packageTable:(id)table packageSelected:(Package *)package {
3228 if (package == nil) {
3229 [navbar_ setAccessoryView:accessory_ animate:(resetting_ ? NO : YES) goingBack:YES];
3237 [navbar_ setAccessoryView:nil animate:YES goingBack:NO];
3239 _assert(package_ == nil);
3240 _assert(view_ == nil);
3242 package_ = [[package name] retain];
3244 view_ = [[PackageView alloc] initWithFrame:[transition_ bounds]];
3245 [view_ setDelegate:delegate_];
3247 [self pushView:view_ withTitle:[package name] backButtonTitle:nil rightButton:nil];
3248 [self resetPackage:package];
3252 - (void) textFieldDidBecomeFirstResponder:(UITextField *)field {
3253 [delegate_ showKeyboard:YES];
3254 [table_ setEnabled:NO];
3256 /*CGColorSpaceRef space = CGColorSpaceCreateDeviceRGB();
3257 CGColor dimmed(alpha, 0, 0, 0, 0.5);
3258 [editor_ setBackgroundColor:dimmed];
3259 CGColorSpaceRelease(space);*/
3262 - (void) textFieldDidResignFirstResponder:(UITextField *)field {
3263 [table_ setEnabled:YES];
3264 [delegate_ showKeyboard:NO];
3267 - (void) keyboardInputChanged:(UIFieldEditor *)editor {
3268 NSString *text([field_ text]);
3269 [field_ setClearButtonStyle:(text == nil || [text length] == 0 ? 0 : 2)];
3272 - (BOOL) keyboardInput:(id)input shouldInsertText:(NSString *)text isMarkedText:(int)marked {
3273 if ([text length] != 1 || [text characterAtIndex:0] != '\n')
3276 [self searchPackages];
3277 [field_ resignFirstResponder];
3281 - (id) initWithFrame:(CGRect)frame {
3282 if ((self = [super initWithFrame:frame]) != nil) {
3283 packages_ = [[NSMutableArray arrayWithCapacity:16] retain];
3285 table_ = [[PackageTable alloc] initWithFrame:[transition_ bounds] versioner:@selector(latest)];
3286 [table_ setDelegate:self];
3288 CGRect area = [self bounds];
3291 area.size.width -= 12;
3292 area.size.height = [UISearchField defaultHeight];
3294 field_ = [[UISearchField alloc] initWithFrame:area];
3296 GSFontRef font = GSFontCreateWithName("Helvetica", kGSFontTraitNone, 16);
3297 [field_ setFont:font];
3300 [field_ setPlaceholder:@"Package Names & Descriptions"];
3301 [field_ setPaddingTop:5];
3302 [field_ setDelegate:self];
3304 UITextTraits *traits = [field_ textTraits];
3305 [traits setEditingDelegate:self];
3306 [traits setReturnKeyType:6];
3308 accessory_ = [[UIView alloc] initWithFrame:CGRectMake(6, 6, area.size.width, area.size.height + 30)];
3309 [accessory_ addSubview:field_];
3311 [navbar_ setAccessoryView:accessory_];
3312 [self pushView:table_ withTitle:nil backButtonTitle:@"Search" rightButton:nil];
3314 /* XXX: for the love of god just fix this */
3315 [navbar_ removeFromSuperview];
3316 [reload_ removeFromSuperview];
3317 [configure_ removeFromSuperview];
3318 [self addSubview:navbar_];
3319 [self addSubview:reload_];
3320 [self addSubview:configure_];
3324 - (void) setPackages:(NSArray *)packages {
3325 [packages_ removeAllObjects];
3326 [packages_ addObjectsFromArray:packages];
3327 [packages_ sortUsingSelector:@selector(compareByName:)];
3329 Package *npackage = nil;
3330 for (size_t offset = 0, count = [packages_ count]; offset != count; ++offset) {
3331 Package *package = [packages_ objectAtIndex:offset];
3332 if ([[package name] isEqualToString:package_])
3336 [self searchPackages];
3338 if (npackage != nil)
3339 [self resetPackage:npackage];
3340 else if (package_ != nil)
3346 - (void) setDelegate:(id)delegate {
3348 [view_ setDelegate:delegate];
3349 [super setDelegate:delegate];
3352 - (void) resetPackage:(Package *)package {
3353 [view_ setPackage:package];
3354 NSString *right = [package installed] == nil ? @"Install" : @"Uninstall";
3355 [navbar_ showButtonsWithLeftTitle:nil rightTitle:right];
3358 - (void) searchPackages {
3359 NSString *text([field_ text]);
3361 NSMutableArray *packages([NSMutableArray arrayWithCapacity:16]);
3363 for (size_t offset(0), count([packages_ count]); offset != count; ++offset) {
3364 Package *package = [packages_ objectAtIndex:offset];
3365 if ([package matches:text])
3366 [packages addObject:package];
3369 [table_ setPackages:packages];
3370 [[table_ table] scrollPointVisibleAtTopLeft:CGPointMake(0, 0) animated:NO];
3376 @interface Cydia : UIApplication <
3377 ConfirmationViewDelegate,
3378 ProgressViewDelegate,
3384 UITransitionView *transition_;
3385 UIButtonBar *buttonbar_;
3387 ConfirmationView *confirm_;
3389 Database *database_;
3390 ProgressView *progress_;
3393 UINavigationBar *navbar_;
3394 UIScroller *scroller_;
3395 UIWebView *webview_;
3397 UIProgressIndicator *indicator_;
3399 InstallView *install_;
3400 ChangesView *changes_;
3401 ManageView *manage_;
3402 SearchView *search_;
3407 UIKeyboard *keyboard_;
3411 - (void) reloadData:(BOOL)reset;
3422 - (void) progressViewIsComplete:(ProgressView *)progress;
3424 - (void) navigationBar:(UINavigationBar *)navbar buttonClicked:(int)button;
3425 - (void) alertSheet:(UIAlertSheet *)sheet buttonClicked:(int)button;
3426 - (void) buttonBarItemTapped:(id)sender;
3428 - (void) view:(UIView *)sender didSetFrame:(CGRect)frame oldFrame:(CGRect)old;
3430 - (void) webView:(WebView *)sender didReceiveTitle:(NSString *)title forFrame:(WebFrame *)frame;
3432 - (void) applicationWillSuspend;
3433 - (void) applicationDidFinishLaunching:(id)unused;
3436 @implementation Cydia
3439 NSMutableURLRequest *request = [NSMutableURLRequest
3441 cachePolicy:NSURLRequestReloadIgnoringCacheData
3442 timeoutInterval:30.0
3445 [request addValue:[NSString stringWithCString:Firmware_] forHTTPHeaderField:@"X-Firmware"];
3446 [request addValue:[NSString stringWithCString:Machine_] forHTTPHeaderField:@"X-Machine"];
3447 [request addValue:[NSString stringWithCString:SerialNumber_] forHTTPHeaderField:@"X-Serial-Number"];
3449 [webview_ loadRequest:request];
3452 - (void) reloadData:(BOOL)reset {
3453 [database_ reloadData];
3457 if (Packages_ == nil) {
3458 Packages_ = [[NSMutableDictionary alloc] initWithCapacity:count];
3459 [Metadata_ setObject:Packages_ forKey:@"Packages"];
3462 now_ = [NSDate date];
3464 NSMutableArray *packages = [NSMutableArray arrayWithCapacity:count];
3465 for (pkgCache::PkgIterator iterator = [database_ cache]->PkgBegin(); !iterator.end(); ++iterator)
3466 if (Package *package = [Package packageWithIterator:iterator database:database_])
3467 [packages addObject:package];
3469 [install_ setPackages:packages];
3470 [changes_ setPackages:packages];
3471 [manage_ setPackages:packages];
3472 [search_ setPackages:packages];
3474 if (size_t count = [changes_ count]) {
3475 NSString *badge([[NSNumber numberWithInt:count] stringValue]);
3476 [buttonbar_ setBadgeValue:badge forButton:3];
3477 if ([buttonbar_ respondsToSelector:@selector(setBadgeAnimated:forButton:)])
3478 [buttonbar_ setBadgeAnimated:YES forButton:3];
3479 [self setApplicationBadge:badge];
3481 [buttonbar_ setBadgeValue:nil forButton:3];
3482 if ([buttonbar_ respondsToSelector:@selector(setBadgeAnimated:forButton:)])
3483 [buttonbar_ setBadgeAnimated:NO forButton:3];
3484 [self removeApplicationBadge];
3487 _assert([Metadata_ writeToFile:@"/var/lib/cydia/metadata.plist" atomically:YES] == YES);
3490 - (void) setPrompt {
3491 [navbar_ setPrompt:[NSString stringWithFormat:@"Last Updated: %@", GetLastUpdate()]];
3495 pkgProblemResolver *resolver = [database_ resolver];
3497 resolver->InstallProtect();
3498 if (!resolver->Resolve(true))
3503 [database_ prepare];
3504 confirm_ = [[ConfirmationView alloc] initWithView:underlay_ database:database_ delegate:self];
3508 [database_ upgrade];
3513 [self reloadData:NO];
3519 [overlay_ removeFromSuperview];
3523 detachNewThreadSelector:@selector(perform)
3530 - (void) bootstrap_ {
3532 [database_ upgrade];
3533 [database_ prepare];
3534 [database_ perform];
3537 - (void) bootstrap {
3539 detachNewThreadSelector:@selector(bootstrap_)
3542 title:@"Bootstrap Install..."
3548 detachNewThreadSelector:@selector(update)
3551 title:@"Refreshing Sources..."
3555 - (void) progressViewIsComplete:(ProgressView *)progress {
3556 [self reloadData:YES];
3558 if (confirm_ != nil) {
3559 [underlay_ addSubview:overlay_];
3560 [confirm_ removeFromSuperview];
3566 - (void) navigationBar:(UINavigationBar *)navbar buttonClicked:(int)button {
3573 UIAlertSheet *sheet = [[[UIAlertSheet alloc]
3574 initWithTitle:@"About Cydia Packager"
3575 buttons:[NSArray arrayWithObjects:@"Close", nil]
3576 defaultButtonIndex:0
3582 @"Copyright (C) 2008\n"
3583 "Jay Freeman (saurik)\n"
3584 "saurik@saurik.com\n"
3585 "http://www.saurik.com/\n"
3588 "http://www.theokorigroup.com/\n"
3590 "College of Creative Studies,\n"
3591 "University of California,\n"
3593 "http://www.ccs.ucsb.edu/\n"
3596 "bad_, BHSPitMonkey, cash, Cobra,\n"
3597 "core, Corona, crashx, cromas,\n"
3598 "Darken, dtzWill, Erica, francis,\n"
3599 "Godores, jerry, Kingstone, lounger,\n"
3600 "mbranes, rockabilly, tman, Wbiggs"
3603 [sheet presentSheetFromButtonBar:buttonbar_];
3608 - (void) alertSheet:(UIAlertSheet *)sheet buttonClicked:(int)button {
3612 - (void) buttonBarItemTapped:(id)sender {
3614 unsigned tag = [sender tag];
3617 case 1: view = featured_; break;
3618 case 2: view = install_; break;
3619 case 3: view = changes_; break;
3620 case 4: view = manage_; break;
3621 case 5: view = search_; break;
3627 if ([view respondsToSelector:@selector(resetView:)])
3628 [(id) view resetView:(tag == tag_ ? NO : YES)];
3630 [transition_ transition:0 toView:view];
3633 - (void) view:(UIView *)sender didSetFrame:(CGRect)frame oldFrame:(CGRect)old {
3634 [scroller_ setContentSize:frame.size];
3635 [indicator_ stopAnimation];
3638 - (void) webView:(WebView *)sender didReceiveTitle:(NSString *)title forFrame:(WebFrame *)frame {
3639 [navbar_ setPrompt:title];
3642 - (void) webView:(WebView *)sender didStartProvisionalLoadForFrame:(WebFrame *)frame {
3643 [navbar_ setPrompt:@"Loading..."];
3644 [indicator_ startAnimation];
3647 - (void) applicationWillSuspend {
3649 if (FW_LEAST(1,1,3))
3650 notify_post("com.apple.language.changed");
3652 system("launchctl stop com.apple.SpringBoard");
3654 [super applicationWillSuspend];
3657 - (void) applicationDidFinishLaunching:(id)unused {
3658 _assert(pkgInitConfig(*_config));
3659 _assert(pkgInitSystem(*_config, _system));
3665 CGRect screenrect = [UIHardware fullScreenApplicationContentRect];
3666 window_ = [[UIWindow alloc] initWithContentRect:screenrect];
3668 [window_ orderFront: self];
3669 [window_ makeKey: self];
3670 [window_ _setHidden: NO];
3672 progress_ = [[ProgressView alloc] initWithFrame:[window_ bounds] delegate:self];
3673 [window_ setContentView:progress_];
3675 underlay_ = [[UIView alloc] initWithFrame:[progress_ bounds]];
3676 [progress_ setContentView:underlay_];
3678 overlay_ = [[UIView alloc] initWithFrame:[underlay_ bounds]];
3681 [underlay_ addSubview:overlay_];
3683 transition_ = [[UITransitionView alloc] initWithFrame:CGRectMake(
3684 0, 0, screenrect.size.width, screenrect.size.height - 48
3687 [overlay_ addSubview:transition_];
3689 featured_ = [[UIView alloc] initWithFrame:[transition_ bounds]];
3691 CGSize navsize = [UINavigationBar defaultSizeWithPrompt];
3692 CGRect navrect = {{0, 0}, navsize};
3694 navbar_ = [[UINavigationBar alloc] initWithFrame:navrect];
3695 [featured_ addSubview:navbar_];
3697 [navbar_ setBarStyle:1];
3698 [navbar_ setDelegate:self];
3700 [navbar_ showButtonsWithLeftTitle:@"About" rightTitle:@"Reload"];
3702 UINavigationItem *navitem = [[[UINavigationItem alloc] initWithTitle:@"Featured"] autorelease];
3703 [navbar_ pushNavigationItem:navitem];
3705 struct CGRect subbounds = [featured_ bounds];
3706 subbounds.origin.y += navsize.height;
3707 subbounds.size.height -= navsize.height;
3709 UIImageView *pinstripe = [[[UIImageView alloc] initWithFrame:subbounds] autorelease];
3710 [pinstripe setImage:[UIImage applicationImageNamed:@"pinstripe.png"]];
3711 [featured_ addSubview:pinstripe];
3713 scroller_ = [[UIScroller alloc] initWithFrame:subbounds];
3714 [featured_ addSubview:scroller_];
3716 [scroller_ setScrollingEnabled:YES];
3717 [scroller_ setAdjustForContentSizeChange:YES];
3718 [scroller_ setClipsSubviews:YES];
3719 [scroller_ setAllowsRubberBanding:YES];
3720 [scroller_ setScrollDecelerationFactor:0.99];
3721 [scroller_ setDelegate:self];
3723 CGRect webrect = [scroller_ bounds];
3724 webrect.size.height = 0;
3726 webview_ = [[UIWebView alloc] initWithFrame:webrect];
3727 [scroller_ addSubview:webview_];
3729 [webview_ setTilingEnabled:YES];
3730 [webview_ setTileSize:CGSizeMake(screenrect.size.width, 500)];
3731 [webview_ setAutoresizes:YES];
3732 [webview_ setDelegate:self];
3734 CGSize indsize = [UIProgressIndicator defaultSizeForStyle:2];
3735 indicator_ = [[UIProgressIndicator alloc] initWithFrame:CGRectMake(87, 45, indsize.width, indsize.height)];
3736 [indicator_ setStyle:2];
3737 [featured_ addSubview:indicator_];
3739 NSArray *buttonitems = [NSArray arrayWithObjects:
3740 [NSDictionary dictionaryWithObjectsAndKeys:
3741 @"buttonBarItemTapped:", kUIButtonBarButtonAction,
3742 @"featured-up.png", kUIButtonBarButtonInfo,
3743 @"featured-dn.png", kUIButtonBarButtonSelectedInfo,
3744 [NSNumber numberWithInt:1], kUIButtonBarButtonTag,
3745 self, kUIButtonBarButtonTarget,
3746 @"Featured", kUIButtonBarButtonTitle,
3747 @"0", kUIButtonBarButtonType,
3750 [NSDictionary dictionaryWithObjectsAndKeys:
3751 @"buttonBarItemTapped:", kUIButtonBarButtonAction,
3752 @"install-up.png", kUIButtonBarButtonInfo,
3753 @"install-dn.png", kUIButtonBarButtonSelectedInfo,
3754 [NSNumber numberWithInt:2], kUIButtonBarButtonTag,
3755 self, kUIButtonBarButtonTarget,
3756 @"Install", kUIButtonBarButtonTitle,
3757 @"0", kUIButtonBarButtonType,
3760 [NSDictionary dictionaryWithObjectsAndKeys:
3761 @"buttonBarItemTapped:", kUIButtonBarButtonAction,
3762 @"changes-up.png", kUIButtonBarButtonInfo,
3763 @"changes-dn.png", kUIButtonBarButtonSelectedInfo,
3764 [NSNumber numberWithInt:3], kUIButtonBarButtonTag,
3765 self, kUIButtonBarButtonTarget,
3766 @"Changes", kUIButtonBarButtonTitle,
3767 @"0", kUIButtonBarButtonType,
3770 [NSDictionary dictionaryWithObjectsAndKeys:
3771 @"buttonBarItemTapped:", kUIButtonBarButtonAction,
3772 @"manage-up.png", kUIButtonBarButtonInfo,
3773 @"manage-dn.png", kUIButtonBarButtonSelectedInfo,
3774 [NSNumber numberWithInt:4], kUIButtonBarButtonTag,
3775 self, kUIButtonBarButtonTarget,
3776 @"Uninstall", kUIButtonBarButtonTitle,
3777 @"0", kUIButtonBarButtonType,
3780 [NSDictionary dictionaryWithObjectsAndKeys:
3781 @"buttonBarItemTapped:", kUIButtonBarButtonAction,
3782 @"search-up.png", kUIButtonBarButtonInfo,
3783 @"search-dn.png", kUIButtonBarButtonSelectedInfo,
3784 [NSNumber numberWithInt:5], kUIButtonBarButtonTag,
3785 self, kUIButtonBarButtonTarget,
3786 @"Search", kUIButtonBarButtonTitle,
3787 @"0", kUIButtonBarButtonType,
3791 buttonbar_ = [[UIButtonBar alloc]
3793 withFrame:CGRectMake(
3794 0, screenrect.size.height - 48,
3795 screenrect.size.width, 48
3797 withItemList:buttonitems
3800 [buttonbar_ setDelegate:self];
3801 [buttonbar_ setBarStyle:1];
3802 [buttonbar_ setButtonBarTrackingMode:2];
3804 int buttons[5] = {1, 2, 3, 4, 5};
3805 [buttonbar_ registerButtonGroup:0 withButtons:buttons withCount:5];
3806 [buttonbar_ showButtonGroup:0 withDuration:0];
3808 for (int i = 0; i != 5; ++i)
3809 [[buttonbar_ viewWithTag:(i + 1)] setFrame:CGRectMake(
3810 i * 64 + 2, 1, 60, 48
3813 [buttonbar_ showSelectionForButton:1];
3814 [transition_ transition:0 toView:featured_];
3816 [overlay_ addSubview:buttonbar_];
3818 [UIKeyboard initImplementationNow];
3820 CGRect edtrect = [overlay_ bounds];
3821 edtrect.origin.y += navsize.height;
3822 edtrect.size.height -= navsize.height;
3824 CGSize keysize = [UIKeyboard defaultSize];
3825 CGRect keyrect = {{0, [overlay_ bounds].size.height - keysize.height}, keysize};
3826 keyboard_ = [[UIKeyboard alloc] initWithFrame:keyrect];
3828 database_ = [[Database alloc] init];
3829 [database_ setDelegate:progress_];
3831 install_ = [[InstallView alloc] initWithFrame:[transition_ bounds]];
3832 [install_ setDelegate:self];
3834 changes_ = [[ChangesView alloc] initWithFrame:[transition_ bounds]];
3835 [changes_ setDelegate:self];
3837 manage_ = [[ManageView alloc] initWithFrame:[transition_ bounds]];
3838 [manage_ setDelegate:self];
3840 search_ = [[SearchView alloc] initWithFrame:[transition_ bounds]];
3841 [search_ setDelegate:self];
3843 [self reloadData:NO];
3845 Package *package([database_ packageWithName:@"cydia"]);
3846 NSString *application = package == nil ? @"Cydia" : [NSString
3847 stringWithFormat:@"Cydia/%@",
3851 WebView *webview = [webview_ webView];
3852 [webview setApplicationNameForUserAgent:application];
3853 [webview setFrameLoadDelegate:self];
3855 url_ = [NSURL URLWithString:@"http://cydia.saurik.com/"];
3858 [progress_ resetView];
3864 - (void) showKeyboard:(BOOL)show {
3866 [overlay_ addSubview:keyboard_];
3868 [keyboard_ removeFromSuperview];
3873 void AddPreferences(NSString *plist) {
3874 NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init];
3876 NSMutableDictionary *settings = [[[NSMutableDictionary alloc] initWithContentsOfFile:plist] autorelease];
3877 _assert(settings != NULL);
3878 NSMutableArray *items = [settings objectForKey:@"items"];
3882 for (size_t i(0); i != [items count]; ++i) {
3883 NSMutableDictionary *item([items objectAtIndex:i]);
3884 NSString *label = [item objectForKey:@"label"];
3885 if (label != nil && [label isEqualToString:@"Cydia"]) {
3892 for (size_t i(0); i != [items count]; ++i) {
3893 NSDictionary *item([items objectAtIndex:i]);
3894 NSString *label = [item objectForKey:@"label"];
3895 if (label != nil && [label isEqualToString:@"General"]) {
3896 [items insertObject:[NSDictionary dictionaryWithObjectsAndKeys:
3897 @"CydiaSettings", @"bundle",
3898 @"PSLinkCell", @"cell",
3899 [NSNumber numberWithBool:YES], @"hasIcon",
3900 [NSNumber numberWithBool:YES], @"isController",
3902 nil] atIndex:(i + 1)];
3908 _assert([settings writeToFile:plist atomically:YES] == YES);
3915 id Alloc_(id self, SEL selector) {
3916 id object = alloc_(self, selector);
3917 fprintf(stderr, "[%s]A-%p\n", self->isa->name, object);
3921 int main(int argc, char *argv[]) {
3923 memset(nl, 0, sizeof(nl));
3924 nl[0].n_un.n_name = "_useMDNSResponder";
3925 nlist("/usr/lib/libc.dylib", nl);
3926 if (nl[0].n_type != N_UNDF)
3927 *(int *) nl[0].n_value = 0;
3929 bootstrap_ = argc > 1 && strcmp(argv[1], "--bootstrap") == 0;
3934 /*Method alloc = class_getClassMethod([NSObject class], @selector(alloc));
3935 alloc_ = alloc->method_imp;
3936 alloc->method_imp = (IMP) &Alloc_;*/
3938 NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init];
3940 if (NSDictionary *sysver = [NSDictionary dictionaryWithContentsOfFile:@"/System/Library/CoreServices/SystemVersion.plist"]) {
3941 if (NSString *prover = [sysver valueForKey:@"ProductVersion"]) {
3942 Firmware_ = strdup([prover cString]);
3943 NSArray *versions = [prover componentsSeparatedByString:@"."];
3944 int count = [versions count];
3945 Major_ = count > 0 ? [[versions objectAtIndex:0] intValue] : 0;
3946 Minor_ = count > 1 ? [[versions objectAtIndex:1] intValue] : 0;
3947 BugFix_ = count > 2 ? [[versions objectAtIndex:2] intValue] : 0;
3952 sysctlbyname("hw.machine", NULL, &size, NULL, 0);
3953 char *machine = new char[size];
3954 sysctlbyname("hw.machine", machine, &size, NULL, 0);
3957 if (CFMutableDictionaryRef dict = IOServiceMatching("IOPlatformExpertDevice"))
3958 if (io_service_t service = IOServiceGetMatchingService(kIOMasterPortDefault, dict)) {
3959 if (CFTypeRef serial = IORegistryEntryCreateCFProperty(service, CFSTR(kIOPlatformSerialNumberKey), kCFAllocatorDefault, 0)) {
3960 SerialNumber_ = strdup(CFStringGetCStringPtr((CFStringRef) serial, CFStringGetSystemEncoding()));
3964 IOObjectRelease(service);
3967 /*AddPreferences(@"/Applications/Preferences.app/Settings-iPhone.plist");
3968 AddPreferences(@"/Applications/Preferences.app/Settings-iPod.plist");*/
3970 if ((Metadata_ = [[NSMutableDictionary alloc] initWithContentsOfFile:@"/var/lib/cydia/metadata.plist"]) == NULL)
3971 Metadata_ = [[NSMutableDictionary alloc] initWithCapacity:2];
3973 Packages_ = [Metadata_ objectForKey:@"Packages"];
3975 setenv("CYDIA", "", _not(int));
3976 if (access("/User", F_OK) != 0)
3977 system("/usr/libexec/cydia/firmware.sh");
3978 system("dpkg --configure -a");
3980 UIApplicationMain(argc, argv, [Cydia class]);