1 /* #include Directives {{{ */
2 #include <Foundation/NSURL.h>
3 #include <UIKit/UIKit.h>
4 #include <GraphicsServices/GraphicsServices.h>
9 #include <ext/stdio_filebuf.h>
11 #include <apt-pkg/acquire.h>
12 #include <apt-pkg/acquire-item.h>
13 #include <apt-pkg/algorithms.h>
14 #include <apt-pkg/cachefile.h>
15 #include <apt-pkg/configuration.h>
16 #include <apt-pkg/debmetaindex.h>
17 #include <apt-pkg/error.h>
18 #include <apt-pkg/init.h>
19 #include <apt-pkg/pkgrecords.h>
20 #include <apt-pkg/sourcelist.h>
21 #include <apt-pkg/sptr.h>
23 #include <sys/sysctl.h>
27 #include <mach-o/nlist.h>
37 /* Extension Keywords {{{ */
38 #define _trace() fprintf(stderr, "_trace()@%s:%u[%s]\n", __FILE__, __LINE__, __FUNCTION__)
40 #define _assert(test) do \
42 fprintf(stderr, "_assert(%d:%s)@%s:%u[%s]\n", errno, #test, __FILE__, __LINE__, __FUNCTION__); \
47 #define _not(type) ((type) ~ (type) 0)
49 /* Miscellaneous Messages {{{ */
51 - (void) setApplicationNameForUserAgent:(NSString *)applicationName;
52 - (id) frameLoadDelegate;
53 - (void) setFrameLoadDelegate:(id)delegate;
56 @interface NSString (Cydia)
57 - (NSString *) stringByAddingPercentEscapes;
58 - (NSString *) stringByReplacingCharacter:(unsigned short)arg0 withCharacter:(unsigned short)arg1;
63 #define UITable UITableView
66 OBJC_EXPORT const char *class_getName(Class cls);
68 /* Reset View (UIView) {{{ */
69 @interface UIView (CYResetView)
70 - (void) resetViewAnimated:(BOOL)animated;
73 @implementation UIView (CYResetView)
75 - (void) resetViewAnimated:(BOOL)animated {
76 fprintf(stderr, "%s\n", class_getName(self->isa));
82 /* Reset View (UITable) {{{ */
83 @interface UITable (CYResetView)
84 - (void) resetViewAnimated:(BOOL)animated;
87 @implementation UITable (CYResetView)
89 - (void) resetViewAnimated:(BOOL)animated {
90 [self selectRow:-1 byExtendingSelection:NO withFade:animated];
95 /* Reset View (UISectionList) {{{ */
96 @interface UISectionList (CYResetView)
97 - (void) resetViewAnimated:(BOOL)animated;
100 @implementation UISectionList (CYResetView)
102 - (void) resetViewAnimated:(BOOL)animated {
103 [[self table] resetViewAnimated:animated];
109 /* Perl-Compatible RegEx {{{ */
119 Pcre(const char *regex) :
124 code_ = pcre_compile(regex, 0, &error, &offset, NULL);
127 fprintf(stderr, "%d:%s\n", offset, error);
131 pcre_fullinfo(code_, study_, PCRE_INFO_CAPTURECOUNT, &capture_);
132 matches_ = new int[(capture_ + 1) * 3];
140 NSString *operator [](size_t match) {
142 stringWithCString:(data_ + matches_[match * 2])
143 length:(matches_[match * 2 + 1] - matches_[match * 2])
147 bool operator ()(const char *data, size_t size) {
149 return pcre_exec(code_, study_, data, size, 0, 0, matches_, (capture_ + 1) * 3) >= 0;
153 /* CoreGraphicsServices Primitives {{{ */
159 CGColor(CGColorSpaceRef space, float red, float green, float blue, float alpha) {
160 float color[] = {red, green, blue, alpha};
161 color_ = CGColorCreate(space, color);
165 CGColorRelease(color_);
168 operator CGColorRef() {
179 /* XXX: no GSFontRelease()? */
185 static const int PulseInterval_ = 50000;
187 const char *Firmware_ = NULL;
188 const char *Machine_ = NULL;
189 const char *SerialNumber_ = NULL;
195 #define FW_LEAST(major, minor, bugfix) \
196 (major < Major_ || major == Major_ && \
197 (minor < Minor_ || minor == Minor_ && \
200 bool bootstrap_ = false;
202 static NSMutableDictionary *Metadata_;
203 static NSMutableDictionary *Packages_;
206 NSString *GetLastUpdate() {
207 NSDate *update = [Metadata_ objectForKey:@"LastUpdate"];
210 return @"Never or Unknown";
212 CFLocaleRef locale = CFLocaleCopyCurrent();
213 CFDateFormatterRef formatter = CFDateFormatterCreate(NULL, locale, kCFDateFormatterMediumStyle, kCFDateFormatterMediumStyle);
214 CFStringRef formatted = CFDateFormatterCreateStringWithDate(NULL, formatter, (CFDateRef) update);
216 CFRelease(formatter);
219 return [(NSString *) formatted autorelease];
222 @protocol ProgressDelegate
223 - (void) setError:(NSString *)error;
224 - (void) setTitle:(NSString *)title;
225 - (void) setPercent:(float)percent;
226 - (void) addOutput:(NSString *)output;
229 NSString *SizeString(double size) {
231 while (size > 1024) {
236 static const char *powers_[] = {"B", "kB", "MB", "GB"};
238 return [NSString stringWithFormat:@"%.1f%s", size, powers_[power]];
241 static const float TextViewOffset_ = 22;
243 UITextView *GetTextView(NSString *value, float left, bool html) {
244 UITextView *text([[[UITextView alloc] initWithFrame:CGRectMake(left, 3, 310 - left, 1000)] autorelease]);
245 [text setEditable:NO];
246 [text setTextSize:16];
248 [text setHTML:value];
250 [text setText:value];
251 [text setEnabled:NO];
253 CGColorSpaceRef space = CGColorSpaceCreateDeviceRGB();
254 CGColor clear(space, 0, 0, 0, 0);
255 [text setBackgroundColor:clear];
256 CGColorSpaceRelease(space);
258 CGRect frame = [text frame];
259 [text setFrame:frame];
260 CGRect rect = [text visibleTextRect];
261 frame.size.height = rect.size.height;
262 [text setFrame:frame];
267 /* Status Delegation {{{ */
269 public pkgAcquireStatus
280 void setDelegate(id delegate) {
281 delegate_ = delegate;
284 virtual bool MediaChange(std::string media, std::string drive) {
288 virtual void IMSHit(pkgAcquire::ItemDesc &item) {
291 virtual void Fetch(pkgAcquire::ItemDesc &item) {
292 [delegate_ setTitle:[NSString stringWithCString:("Downloading " + item.ShortDesc).c_str()]];
295 virtual void Done(pkgAcquire::ItemDesc &item) {
298 virtual void Fail(pkgAcquire::ItemDesc &item) {
300 item.Owner->Status == pkgAcquire::Item::StatIdle ||
301 item.Owner->Status == pkgAcquire::Item::StatDone
305 [delegate_ setError:[NSString stringWithCString:item.Owner->ErrorText.c_str()]];
308 virtual bool Pulse(pkgAcquire *Owner) {
309 bool value = pkgAcquireStatus::Pulse(Owner);
312 double(CurrentBytes + CurrentItems) /
313 double(TotalBytes + TotalItems)
316 [delegate_ setPercent:percent];
320 virtual void Start() {
323 virtual void Stop() {
327 /* Progress Delegation {{{ */
335 virtual void Update() {
336 [delegate_ setTitle:[NSString stringWithCString:Op.c_str()]];
337 [delegate_ setPercent:(Percent / 100)];
346 void setDelegate(id delegate) {
347 delegate_ = delegate;
350 virtual void Done() {
351 [delegate_ setPercent:1];
356 /* External Constants {{{ */
357 extern NSString *kUIButtonBarButtonAction;
358 extern NSString *kUIButtonBarButtonInfo;
359 extern NSString *kUIButtonBarButtonInfoOffset;
360 extern NSString *kUIButtonBarButtonSelectedInfo;
361 extern NSString *kUIButtonBarButtonStyle;
362 extern NSString *kUIButtonBarButtonTag;
363 extern NSString *kUIButtonBarButtonTarget;
364 extern NSString *kUIButtonBarButtonTitle;
365 extern NSString *kUIButtonBarButtonTitleVerticalHeight;
366 extern NSString *kUIButtonBarButtonTitleWidth;
367 extern NSString *kUIButtonBarButtonType;
369 /* Mime Addresses {{{ */
370 Pcre email_r("^\"?(.*)\"? <([^>]*)>$");
372 @interface Address : NSObject {
380 - (NSString *) email;
382 + (Address *) addressWithString:(NSString *)string;
383 - (Address *) initWithString:(NSString *)string;
386 @implementation Address
395 - (NSString *) name {
399 - (NSString *) email {
403 + (Address *) addressWithString:(NSString *)string {
404 return [[[Address alloc] initWithString:string] autorelease];
407 - (Address *) initWithString:(NSString *)string {
408 if ((self = [super init]) != nil) {
409 const char *data = [string UTF8String];
410 size_t size = [string length];
412 if (email_r(data, size)) {
413 name_ = [email_r[1] retain];
414 email_ = [email_r[2] retain];
416 name_ = [[NSString stringWithCString:data length:size] retain];
425 /* Right Alignment {{{ */
426 @interface UIRightTextLabel : UITextLabel {
427 float _savedRightEdgeX;
428 BOOL _sizedtofit_flag;
431 - (void) setFrame:(CGRect)frame;
432 - (void) setText:(NSString *)text;
433 - (void) realignText;
436 @implementation UIRightTextLabel
438 - (void) setFrame:(CGRect)frame {
439 [super setFrame:frame];
440 if (_sizedtofit_flag == NO) {
441 _savedRightEdgeX = frame.origin.x;
446 - (void) setText:(NSString *)text {
447 [super setText:text];
451 - (void) realignText {
452 CGRect oldFrame = [self frame];
454 _sizedtofit_flag = YES;
455 [self sizeToFit]; // shrink down size so I can right align it
457 CGRect newFrame = [self frame];
459 oldFrame.origin.x = _savedRightEdgeX - newFrame.size.width;
460 oldFrame.size.width = newFrame.size.width;
461 [super setFrame:oldFrame];
462 _sizedtofit_flag = NO;
467 /* Linear Algebra {{{ */
468 inline float interpolate(float begin, float end, float fraction) {
469 return (end - begin) * fraction + begin;
476 /* Database Interface {{{ */
477 @interface Database : NSObject {
479 pkgRecords *records_;
480 pkgProblemResolver *resolver_;
481 pkgAcquire *fetcher_;
483 SPtr<pkgPackageManager> manager_;
484 pkgSourceList *list_;
486 NSMutableDictionary *sources_;
487 NSMutableArray *packages_;
497 - (void) _readStatus:(NSNumber *)fd;
498 - (void) _readOutput:(NSNumber *)fd;
500 - (Package *) packageWithName:(NSString *)name;
503 - (pkgCacheFile &) cache;
504 - (pkgRecords *) records;
505 - (pkgProblemResolver *) resolver;
506 - (pkgAcquire &) fetcher;
507 - (NSArray *) packages;
515 - (void) setDelegate:(id)delegate;
516 - (Source *) getSource:(const pkgCache::PkgFileIterator &)file;
521 @interface ResetView : UIView {
522 UIPushButton *configure_;
523 UIPushButton *reload_;
524 NSMutableArray *views_;
525 UINavigationBar *navbar_;
526 UITransitionView *transition_;
533 - (void) navigationBar:(UINavigationBar *)navbar poppedItem:(UINavigationItem *)item;
534 - (void) alertSheet:(UIAlertSheet *)sheet buttonClicked:(int)button;
536 - (id) initWithFrame:(CGRect)frame;
537 - (void) setDelegate:(id)delegate;
539 - (void) configurePushed;
540 - (void) reloadPushed;
542 - (void) pushView:(UIView *)view withTitle:(NSString *)title backButtonTitle:(NSString *)back rightButton:(NSString *)right;
543 - (void) popViews:(unsigned)views;
544 - (void) resetView:(BOOL)clear;
549 @implementation ResetView
552 [configure_ release];
554 [transition_ release];
560 - (void) navigationBar:(UINavigationBar *)navbar poppedItem:(UINavigationItem *)item {
561 [views_ removeLastObject];
562 UIView *view([views_ lastObject]);
563 [view resetViewAnimated:!resetting_];
566 [transition_ transition:2 toView:view];
571 - (void) alertSheet:(UIAlertSheet *)sheet buttonClicked:(int)button {
575 - (id) initWithFrame:(CGRect)frame {
576 if ((self = [super initWithFrame:frame]) != nil) {
577 views_ = [[NSMutableArray arrayWithCapacity:4] retain];
579 struct CGRect bounds = [self bounds];
580 CGSize navsize = [UINavigationBar defaultSizeWithPrompt];
581 CGRect navrect = {{0, 0}, navsize};
583 navbar_ = [[UINavigationBar alloc] initWithFrame:navrect];
584 [self addSubview:navbar_];
586 [navbar_ setBarStyle:1];
587 [navbar_ setDelegate:self];
589 transition_ = [[UITransitionView alloc] initWithFrame:CGRectMake(
590 bounds.origin.x, bounds.origin.y + navsize.height, bounds.size.width, bounds.size.height - navsize.height
593 //configure_ = [[UIPushButton alloc] initWithFrame:CGRectMake(15, 9, 17, 18)];
594 configure_ = [[UIPushButton alloc] initWithFrame:CGRectMake(10, 9, 17, 18)];
595 [configure_ setShowPressFeedback:YES];
596 [configure_ setImage:[UIImage applicationImageNamed:@"configure.png"]];
597 [configure_ addTarget:self action:@selector(configurePushed) forEvents:1];
599 //reload_ = [[UIPushButton alloc] initWithFrame:CGRectMake(288, 5, 18, 22)];
600 reload_ = [[UIPushButton alloc] initWithFrame:CGRectMake(293, 5, 18, 22)];
601 [reload_ setShowPressFeedback:YES];
602 [reload_ setImage:[UIImage applicationImageNamed:@"reload.png"]];
603 [reload_ addTarget:self action:@selector(reloadPushed) forEvents:1];
605 [navbar_ addSubview:configure_];
606 [navbar_ addSubview:reload_];
608 [self addSubview:transition_];
612 - (void) setDelegate:(id)delegate {
613 delegate_ = delegate;
616 - (void) configurePushed {
617 UIAlertSheet *sheet = [[[UIAlertSheet alloc]
618 initWithTitle:@"Sources Unimplemented"
619 buttons:[NSArray arrayWithObjects:@"Okay", nil]
625 [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'."];
626 [sheet popupAlertAnimated:YES];
629 - (void) reloadPushed {
633 - (void) pushView:(UIView *)view withTitle:(NSString *)title backButtonTitle:(NSString *)back rightButton:(NSString *)right {
634 UINavigationItem *navitem = [[[UINavigationItem alloc] initWithTitle:title] autorelease];
635 [navbar_ pushNavigationItem:navitem];
636 [navitem setBackButtonTitle:back];
638 [navbar_ showButtonsWithLeftTitle:nil rightTitle:right];
640 [transition_ transition:([views_ count] == 0 ? 0 : 1) toView:view];
641 [views_ addObject:view];
644 - (void) popViews:(unsigned)views {
646 for (unsigned i(0); i != views; ++i)
647 [navbar_ popNavigationItem];
651 [transition_ transition:2 toView:[views_ lastObject]];
654 - (void) resetView:(BOOL)clear {
657 if ([views_ count] > 1) {
658 [navbar_ disableAnimation];
659 while ([views_ count] != (clear ? 1 : 2))
660 [navbar_ popNavigationItem];
661 [navbar_ enableAnimation];
663 [navbar_ popNavigationItem];
669 [transition_ transition:(clear ? 0 : 2) toView:[views_ lastObject]];
672 - (void) _resetView {
673 [navbar_ showButtonsWithLeftTitle:nil rightTitle:nil];
677 [navbar_ setPrompt:[NSString stringWithFormat:@"Last Updated: %@", GetLastUpdate()]];
682 /* Confirmation View {{{ */
683 void AddTextView(NSMutableDictionary *fields, NSMutableArray *packages, NSString *key) {
684 if ([packages count] == 0)
687 UITextView *text = GetTextView([packages count] == 0 ? @"n/a" : [packages componentsJoinedByString:@", "], 110, false);
688 [fields setObject:text forKey:key];
690 CGColorSpaceRef space = CGColorSpaceCreateDeviceRGB();
691 CGColor blue(space, 0, 0, 0.4, 1);
692 [text setTextColor:blue];
693 CGColorSpaceRelease(space);
696 @protocol ConfirmationViewDelegate
701 @interface ConfirmationView : UIView {
704 UITransitionView *transition_;
706 UINavigationBar *navbar_;
707 UIPreferencesTable *table_;
708 NSMutableDictionary *fields_;
709 UIAlertSheet *essential_;
715 - (void) transitionViewDidComplete:(UITransitionView*)view fromView:(UIView*)from toView:(UIView*)to;
716 - (void) navigationBar:(UINavigationBar *)navbar buttonClicked:(int)button;
717 - (void) alertSheet:(UIAlertSheet *)sheet buttonClicked:(int)button;
719 - (int) numberOfGroupsInPreferencesTable:(UIPreferencesTable *)table;
720 - (NSString *) preferencesTable:(UIPreferencesTable *)table titleForGroup:(int)group;
721 - (float) preferencesTable:(UIPreferencesTable *)table heightForRow:(int)row inGroup:(int)group withProposedHeight:(float)proposed;
722 - (int) preferencesTable:(UIPreferencesTable *)table numberOfRowsInGroup:(int)group;
723 - (UIPreferencesTableCell *) preferencesTable:(UIPreferencesTable *)table cellForRow:(int)row inGroup:(int)group;
725 - (id) initWithView:(UIView *)view database:(Database *)database delegate:(id)delegate;
729 @implementation ConfirmationView
732 [transition_ release];
737 if (essential_ != nil)
738 [essential_ release];
743 [transition_ transition:7 toView:nil];
747 - (void) transitionViewDidComplete:(UITransitionView*)view fromView:(UIView*)from toView:(UIView*)to {
748 if (from != nil && to == nil)
749 [self removeFromSuperview];
752 - (void) navigationBar:(UINavigationBar *)navbar buttonClicked:(int)button {
755 if (essential_ != nil)
756 [essential_ popupAlertAnimated:YES];
767 - (void) alertSheet:(UIAlertSheet *)sheet buttonClicked:(int)button {
768 [essential_ dismiss];
772 - (int) numberOfGroupsInPreferencesTable:(UIPreferencesTable *)table {
776 - (NSString *) preferencesTable:(UIPreferencesTable *)table titleForGroup:(int)group {
778 case 0: return @"Statistics";
779 case 1: return @"Modifications";
781 default: _assert(false);
785 - (int) preferencesTable:(UIPreferencesTable *)table numberOfRowsInGroup:(int)group {
788 case 1: return [fields_ count];
790 default: _assert(false);
794 - (float) preferencesTable:(UIPreferencesTable *)table heightForRow:(int)row inGroup:(int)group withProposedHeight:(float)proposed {
795 if (group != 1 || row == -1)
798 _assert(size_t(row) < [fields_ count]);
799 return [[[fields_ allValues] objectAtIndex:row] visibleTextRect].size.height + TextViewOffset_;
803 - (UIPreferencesTableCell *) preferencesTable:(UIPreferencesTable *)table cellForRow:(int)row inGroup:(int)group {
804 UIPreferencesTableCell *cell = [[[UIPreferencesTableCell alloc] init] autorelease];
805 [cell setShowSelection:NO];
808 case 0: switch (row) {
810 [cell setTitle:@"Downloading"];
811 [cell setValue:SizeString([database_ fetcher].FetchNeeded())];
815 [cell setTitle:@"Resuming At"];
816 [cell setValue:SizeString([database_ fetcher].PartialPresent())];
820 double size([database_ cache]->UsrSize());
823 [cell setTitle:@"Disk Freeing"];
824 [cell setValue:SizeString(-size)];
826 [cell setTitle:@"Disk Using"];
827 [cell setValue:SizeString(size)];
831 default: _assert(false);
835 _assert(size_t(row) < [fields_ count]);
836 [cell setTitle:[[fields_ allKeys] objectAtIndex:row]];
837 [cell addSubview:[[fields_ allValues] objectAtIndex:row]];
840 default: _assert(false);
846 - (id) initWithView:(UIView *)view database:(Database *)database delegate:(id)delegate {
847 if ((self = [super initWithFrame:[view bounds]]) != nil) {
848 database_ = database;
849 delegate_ = delegate;
851 transition_ = [[UITransitionView alloc] initWithFrame:[self bounds]];
852 [self addSubview:transition_];
854 overlay_ = [[UIView alloc] initWithFrame:[transition_ bounds]];
856 CGSize navsize = [UINavigationBar defaultSize];
857 CGRect navrect = {{0, 0}, navsize};
858 CGRect bounds = [overlay_ bounds];
860 navbar_ = [[UINavigationBar alloc] initWithFrame:navrect];
861 [navbar_ setBarStyle:1];
862 [navbar_ setDelegate:self];
864 UINavigationItem *navitem = [[[UINavigationItem alloc] initWithTitle:@"Confirm"] autorelease];
865 [navbar_ pushNavigationItem:navitem];
866 [navbar_ showButtonsWithLeftTitle:@"Cancel" rightTitle:@"Confirm"];
868 fields_ = [[NSMutableDictionary dictionaryWithCapacity:16] retain];
870 NSMutableArray *installing = [NSMutableArray arrayWithCapacity:16];
871 NSMutableArray *upgrading = [NSMutableArray arrayWithCapacity:16];
872 NSMutableArray *removing = [NSMutableArray arrayWithCapacity:16];
878 pkgCacheFile &cache([database_ cache]);
879 for (pkgCache::PkgIterator iterator = cache->PkgBegin(); !iterator.end(); ++iterator) {
880 NSString *name([NSString stringWithCString:iterator.Name()]);
881 bool essential((iterator->Flags & pkgCache::Flag::Essential) != 0);
883 if (cache[iterator].NewInstall()) {
886 [installing addObject:name];
887 } else if (cache[iterator].Upgrade()) {
890 [upgrading addObject:name];
891 } else if (cache[iterator].Delete()) {
894 [removing addObject:name];
901 essential_ = [[UIAlertSheet alloc]
902 initWithTitle:@"Unable to Comply"
903 buttons:[NSArray arrayWithObjects:@"Okay", nil]
909 [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."];
912 AddTextView(fields_, installing, @"Installing");
913 AddTextView(fields_, upgrading, @"Upgrading");
914 AddTextView(fields_, removing, @"Removing");
916 table_ = [[UIPreferencesTable alloc] initWithFrame:CGRectMake(
917 0, navsize.height, bounds.size.width, bounds.size.height - navsize.height
920 [table_ setReusesTableCells:YES];
921 [table_ setDataSource:self];
924 [overlay_ addSubview:navbar_];
925 [overlay_ addSubview:table_];
927 [view addSubview:self];
929 [transition_ setDelegate:self];
931 UIView *blank = [[[UIView alloc] initWithFrame:[transition_ bounds]] autorelease];
932 [transition_ transition:0 toView:blank];
933 [transition_ transition:3 toView:overlay_];
940 /* Source Class {{{ */
941 @interface Source : NSObject {
942 NSString *description_;
947 NSString *distribution_;
951 NSString *defaultIcon_;
958 - (Source *) initWithMetaIndex:(metaIndex *)index;
963 - (NSString *) distribution;
966 - (NSString *) description;
967 - (NSString *) label;
968 - (NSString *) origin;
969 - (NSString *) version;
971 - (NSString *) defaultIcon;
974 @implementation Source
978 [distribution_ release];
981 if (description_ != nil)
982 [description_ release];
993 - (Source *) initWithMetaIndex:(metaIndex *)index {
994 if ((self = [super init]) != nil) {
995 trusted_ = index->IsTrusted();
997 uri_ = [[NSString stringWithCString:index->GetURI().c_str()] retain];
998 distribution_ = [[NSString stringWithCString:index->GetDist().c_str()] retain];
999 type_ = [[NSString stringWithCString:index->GetType()] retain];
1005 debReleaseIndex *dindex(dynamic_cast<debReleaseIndex *>(index));
1006 if (dindex != NULL) {
1007 std::ifstream release(dindex->MetaIndexFile("Release").c_str());
1009 while (std::getline(release, line)) {
1010 std::string::size_type colon(line.find(':'));
1011 if (colon == std::string::npos)
1014 std::string name(line.substr(0, colon));
1015 std::string value(line.substr(colon + 1));
1016 while (!value.empty() && value[0] == ' ')
1017 value = value.substr(1);
1019 if (name == "Default-Icon")
1020 defaultIcon_ = [[NSString stringWithCString:value.c_str()] retain];
1021 else if (name == "Description")
1022 description_ = [[NSString stringWithCString:value.c_str()] retain];
1023 else if (name == "Label")
1024 label_ = [[NSString stringWithCString:value.c_str()] retain];
1025 else if (name == "Origin")
1026 origin_ = [[NSString stringWithCString:value.c_str()] retain];
1027 else if (name == "Version")
1028 version_ = [[NSString stringWithCString:value.c_str()] retain];
1038 - (NSString *) uri {
1042 - (NSString *) distribution {
1043 return distribution_;
1046 - (NSString *) type {
1050 - (NSString *) description {
1051 return description_;
1054 - (NSString *) label {
1058 - (NSString *) origin {
1062 - (NSString *) version {
1066 - (NSString *) defaultIcon {
1067 return defaultIcon_;
1072 /* Package Class {{{ */
1073 NSString *Scour(const char *field, const char *begin, const char *end) {
1074 size_t i(0), l(strlen(field));
1077 const char *name = begin + i;
1078 const char *colon = name + l;
1079 const char *value = colon + 1;
1084 memcmp(name, field, l) == 0
1086 while (value != end && value[0] == ' ')
1088 const char *line = std::find(value, end, '\n');
1089 while (line != value && line[-1] == ' ')
1091 return [NSString stringWithCString:value length:(line - value)];
1093 begin = std::find(begin, end, '\n');
1101 @interface Package : NSObject {
1102 pkgCache::PkgIterator iterator_;
1103 Database *database_;
1104 pkgCache::VerIterator version_;
1105 pkgCache::VerFileIterator file_;
1109 NSString *installed_;
1120 - (Package *) initWithIterator:(pkgCache::PkgIterator)iterator database:(Database *)database version:(pkgCache::VerIterator)version file:(pkgCache::VerFileIterator)file;
1121 + (Package *) packageWithIterator:(pkgCache::PkgIterator)iterator database:(Database *)database;
1123 - (NSString *) section;
1124 - (Address *) maintainer;
1126 - (NSString *) description;
1127 - (NSString *) index;
1131 - (NSString *) latest;
1132 - (NSString *) installed;
1133 - (BOOL) upgradable;
1138 - (NSString *) name;
1139 - (NSString *) tagline;
1140 - (NSString *) icon;
1141 - (NSString *) website;
1143 - (Source *) source;
1145 - (BOOL) matches:(NSString *)text;
1147 - (NSComparisonResult) compareByName:(Package *)package;
1148 - (NSComparisonResult) compareBySectionAndName:(Package *)package;
1149 - (NSComparisonResult) compareForChanges:(Package *)package;
1155 @implementation Package
1159 if (installed_ != nil)
1160 [installed_ release];
1168 if (website_ != nil)
1177 - (Package *) initWithIterator:(pkgCache::PkgIterator)iterator database:(Database *)database version:(pkgCache::VerIterator)version file:(pkgCache::VerFileIterator)file {
1178 if ((self = [super init]) != nil) {
1179 iterator_ = iterator;
1180 database_ = database;
1185 pkgRecords::Parser *parser = &[database_ records]->Lookup(file_);
1187 const char *begin, *end;
1188 parser->GetRec(begin, end);
1190 latest_ = [[NSString stringWithCString:version_.VerStr()] retain];
1191 installed_ = iterator_.CurrentVer().end() ? nil : [[NSString stringWithCString:iterator_.CurrentVer().VerStr()] retain];
1193 id_ = [[[NSString stringWithCString:iterator_.Name()] lowercaseString] retain];
1194 name_ = Scour("Name", begin, end);
1196 name_ = [name_ retain];
1197 tagline_ = [[NSString stringWithCString:parser->ShortDesc().c_str()] retain];
1198 icon_ = Scour("Icon", begin, end);
1200 icon_ = [icon_ retain];
1201 website_ = Scour("Website", begin, end);
1202 if (website_ != nil)
1203 website_ = [website_ retain];
1205 source_ = [[database_ getSource:file_.File()] retain];
1207 NSMutableDictionary *metadata = [Packages_ objectForKey:id_];
1208 if (metadata == nil || [metadata count] == 0) {
1209 metadata = [NSMutableDictionary dictionaryWithObjectsAndKeys:
1213 [Packages_ setObject:metadata forKey:id_];
1218 + (Package *) packageWithIterator:(pkgCache::PkgIterator)iterator database:(Database *)database {
1219 for (pkgCache::VerIterator version = iterator.VersionList(); !version.end(); ++version)
1220 for (pkgCache::VerFileIterator file = version.FileList(); !file.end(); ++file)
1221 return [[[Package alloc]
1222 initWithIterator:iterator
1230 - (NSString *) section {
1231 const char *section = iterator_.Section();
1232 return section == NULL ? nil : [[NSString stringWithCString:section] stringByReplacingCharacter:'_' withCharacter:' '];
1235 - (Address *) maintainer {
1236 pkgRecords::Parser *parser = &[database_ records]->Lookup(file_);
1237 return [Address addressWithString:[NSString stringWithCString:parser->Maintainer().c_str()]];
1241 return version_->InstalledSize;
1244 - (NSString *) description {
1245 pkgRecords::Parser *parser = &[database_ records]->Lookup(file_);
1246 NSString *description([NSString stringWithCString:parser->LongDesc().c_str()]);
1248 NSArray *lines = [description componentsSeparatedByString:@"\n"];
1249 NSMutableArray *trimmed = [NSMutableArray arrayWithCapacity:([lines count] - 1)];
1250 if ([lines count] < 2)
1253 NSCharacterSet *whitespace = [NSCharacterSet whitespaceCharacterSet];
1254 for (size_t i(1); i != [lines count]; ++i) {
1255 NSString *trim = [[lines objectAtIndex:i] stringByTrimmingCharactersInSet:whitespace];
1256 [trimmed addObject:trim];
1259 return [trimmed componentsJoinedByString:@"\n"];
1262 - (NSString *) index {
1263 NSString *index = [[[self name] substringToIndex:1] uppercaseString];
1264 return [index length] != 0 && isalpha([index characterAtIndex:0]) ? index : @"123";
1268 return [[Packages_ objectForKey:id_] objectForKey:@"FirstSeen"];
1271 - (NSString *) latest {
1275 - (NSString *) installed {
1279 - (BOOL) upgradable {
1280 if (NSString *installed = [self installed])
1281 return [[self latest] compare:installed] != NSOrderedSame ? YES : NO;
1283 return [self essential];
1286 - (BOOL) essential {
1287 return (iterator_->Flags & pkgCache::Flag::Essential) == 0 ? NO : YES;
1291 return (*[database_ cache])[iterator_].InstBroken();
1298 - (NSString *) name {
1299 return name_ == nil ? id_ : name_;
1302 - (NSString *) tagline {
1306 - (NSString *) icon {
1310 - (NSString *) website {
1314 - (Source *) source {
1318 - (BOOL) matches:(NSString *)text {
1324 range = [[self id] rangeOfString:text options:NSCaseInsensitiveSearch];
1325 if (range.location != NSNotFound)
1328 range = [[self name] rangeOfString:text options:NSCaseInsensitiveSearch];
1329 if (range.location != NSNotFound)
1332 range = [[self tagline] rangeOfString:text options:NSCaseInsensitiveSearch];
1333 if (range.location != NSNotFound)
1339 - (NSComparisonResult) compareByName:(Package *)package {
1340 NSString *lhs = [self name];
1341 NSString *rhs = [package name];
1343 if ([lhs length] != 0 && [rhs length] != 0) {
1344 unichar lhc = [lhs characterAtIndex:0];
1345 unichar rhc = [rhs characterAtIndex:0];
1347 if (isalpha(lhc) && !isalpha(rhc))
1348 return NSOrderedAscending;
1349 else if (!isalpha(lhc) && isalpha(rhc))
1350 return NSOrderedDescending;
1353 return [lhs caseInsensitiveCompare:rhs];
1356 - (NSComparisonResult) compareBySectionAndName:(Package *)package {
1357 NSString *lhs = [self section];
1358 NSString *rhs = [package section];
1360 if (lhs == NULL && rhs != NULL)
1361 return NSOrderedAscending;
1362 else if (lhs != NULL && rhs == NULL)
1363 return NSOrderedDescending;
1364 else if (lhs != NULL && rhs != NULL) {
1365 NSComparisonResult result = [lhs compare:rhs];
1366 if (result != NSOrderedSame)
1370 return [self compareByName:package];
1373 - (NSComparisonResult) compareForChanges:(Package *)package {
1374 BOOL lhs = [self upgradable];
1375 BOOL rhs = [package upgradable];
1378 return lhs ? NSOrderedAscending : NSOrderedDescending;
1380 switch ([[self seen] compare:[package seen]]) {
1381 case NSOrderedAscending:
1382 return NSOrderedDescending;
1385 case NSOrderedDescending:
1386 return NSOrderedAscending;
1392 return [self compareByName:package];
1396 pkgProblemResolver *resolver = [database_ resolver];
1397 resolver->Clear(iterator_);
1398 resolver->Protect(iterator_);
1399 [database_ cache]->MarkInstall(iterator_, false);
1403 pkgProblemResolver *resolver = [database_ resolver];
1404 resolver->Clear(iterator_);
1405 resolver->Protect(iterator_);
1406 resolver->Remove(iterator_);
1407 [database_ cache]->MarkDelete(iterator_, true);
1412 /* Section Class {{{ */
1413 @interface Section : NSObject {
1416 NSMutableArray *packages_;
1421 - (Section *) initWithName:(NSString *)name row:(size_t)row;
1422 - (NSString *) name;
1424 - (NSArray *) packages;
1426 - (void) addPackage:(Package *)package;
1429 @implementation Section
1433 [packages_ release];
1437 - (Section *) initWithName:(NSString *)name row:(size_t)row {
1438 if ((self = [super init]) != nil) {
1439 name_ = [name retain];
1441 packages_ = [[NSMutableArray arrayWithCapacity:16] retain];
1445 - (NSString *) name {
1453 - (NSArray *) packages {
1458 return [packages_ count];
1461 - (void) addPackage:(Package *)package {
1462 [packages_ addObject:package];
1468 /* Package View {{{ */
1469 @protocol PackageViewDelegate
1470 - (void) performPackage:(Package *)package;
1473 @interface PackageView : UIView {
1474 UIPreferencesTable *table_;
1476 UITextView *description_;
1482 - (int) numberOfGroupsInPreferencesTable:(UIPreferencesTable *)table;
1483 - (NSString *) preferencesTable:(UIPreferencesTable *)table titleForGroup:(int)group;
1484 - (float) preferencesTable:(UIPreferencesTable *)table heightForRow:(int)row inGroup:(int)group withProposedHeight:(float)proposed;
1485 - (int) preferencesTable:(UIPreferencesTable *)table numberOfRowsInGroup:(int)group;
1486 - (UIPreferencesTableCell *) preferencesTable:(UIPreferencesTable *)table cellForRow:(int)row inGroup:(int)group;
1488 - (BOOL) canSelectRow:(int)row;
1489 - (void) tableRowSelected:(NSNotification *)notification;
1491 - (Package *) package;
1493 - (id) initWithFrame:(struct CGRect)frame;
1494 - (void) setPackage:(Package *)package;
1495 - (void) setDelegate:(id)delegate;
1498 @implementation PackageView
1501 if (package_ != nil)
1503 if (description_ != nil)
1504 [description_ release];
1509 - (int) numberOfGroupsInPreferencesTable:(UIPreferencesTable *)table {
1513 - (NSString *) preferencesTable:(UIPreferencesTable *)table titleForGroup:(int)group {
1516 case 1: return @"Package Details";
1517 case 2: return @"Source Information";
1519 default: _assert(false);
1523 - (float) preferencesTable:(UIPreferencesTable *)table heightForRow:(int)row inGroup:(int)group withProposedHeight:(float)proposed {
1524 if (group != 0 || row != 1)
1527 return [description_ visibleTextRect].size.height + TextViewOffset_;
1530 - (int) preferencesTable:(UIPreferencesTable *)table numberOfRowsInGroup:(int)group {
1532 case 0: return [package_ website] == nil ? 2 : 3;
1536 default: _assert(false);
1540 - (UIPreferencesTableCell *) preferencesTable:(UIPreferencesTable *)table cellForRow:(int)row inGroup:(int)group {
1541 UIPreferencesTableCell *cell = [[[UIPreferencesTableCell alloc] init] autorelease];
1542 [cell setShowSelection:NO];
1545 case 0: switch (row) {
1547 [cell setTitle:[package_ name]];
1548 [cell setValue:[package_ latest]];
1552 [cell addSubview:description_];
1556 [cell setTitle:@"More Information"];
1557 [cell setShowDisclosure:YES];
1558 [cell setShowSelection:YES];
1561 default: _assert(false);
1564 case 1: switch (row) {
1566 [cell setTitle:@"Identifier"];
1567 [cell setValue:[package_ id]];
1571 [cell setTitle:@"Installed Version"];
1572 NSString *installed([package_ installed]);
1573 [cell setValue:(installed == nil ? @"n/a" : installed)];
1577 [cell setTitle:@"Section"];
1578 NSString *section([package_ section]);
1579 [cell setValue:(section == nil ? @"n/a" : section)];
1583 [cell setTitle:@"Expanded Size"];
1584 [cell setValue:SizeString([package_ size])];
1588 [cell setTitle:@"Maintainer"];
1589 [cell setValue:[[package_ maintainer] name]];
1590 [cell setShowDisclosure:YES];
1591 [cell setShowSelection:YES];
1594 default: _assert(false);
1597 case 2: switch (row) {
1599 [cell setTitle:[[package_ source] label]];
1600 [cell setValue:[[package_ source] version]];
1604 [cell setValue:[[package_ source] description]];
1608 [cell setTitle:@"Origin"];
1609 [cell setValue:[[package_ source] origin]];
1612 default: _assert(false);
1615 default: _assert(false);
1621 - (BOOL) canSelectRow:(int)row {
1625 - (void) tableRowSelected:(NSNotification *)notification {
1626 int row = [table_ selectedRow];
1627 NSString *website = [package_ website];
1629 if (row == (website == nil ? 8 : 9))
1630 [delegate_ openURL:[NSURL URLWithString:[NSString stringWithFormat:@"mailto:%@?subject=%@",
1631 [[package_ maintainer] email],
1632 [[NSString stringWithFormat:@"regarding apt package \"%@\"", [package_ name]] stringByAddingPercentEscapes]
1634 else if (website != nil && row == 3)
1635 [delegate_ openURL:[NSURL URLWithString:website]];
1638 - (Package *) package {
1642 - (id) initWithFrame:(struct CGRect)frame {
1643 if ((self = [super initWithFrame:frame]) != nil) {
1644 table_ = [[UIPreferencesTable alloc] initWithFrame:[self bounds]];
1645 [self addSubview:table_];
1647 [table_ setDataSource:self];
1648 [table_ setDelegate:self];
1652 - (void) setPackage:(Package *)package {
1653 if (package_ != nil) {
1654 [package_ autorelease];
1658 if (description_ != nil) {
1659 [description_ release];
1663 if (package != nil) {
1664 package_ = [package retain];
1666 NSString *description([package description]);
1667 if (description == nil)
1668 description = [package tagline];
1669 description_ = [GetTextView(description, 12, true) retain];
1671 CGColorSpaceRef space = CGColorSpaceCreateDeviceRGB();
1672 CGColor black(space, 0, 0, 0, 1);
1673 [description_ setTextColor:black];
1674 CGColorSpaceRelease(space);
1676 [table_ reloadData];
1680 - (void) setDelegate:(id)delegate {
1681 delegate_ = delegate;
1686 /* Package Cell {{{ */
1687 @interface PackageCell : UITableCell {
1690 UITextLabel *description_;
1691 UITextLabel *source_;
1692 UITextLabel *version_;
1693 UIImageView *trusted_;
1699 - (PackageCell *) initWithVersioner:(SEL)versioner;
1700 - (void) setPackage:(Package *)package;
1702 - (void) _setSelected:(float)fraction;
1703 - (void) setSelected:(BOOL)selected;
1704 - (void) setSelected:(BOOL)selected withFade:(BOOL)fade;
1705 - (void) _setSelectionFadeFraction:(float)fraction;
1709 @implementation PackageCell
1714 [description_ release];
1721 - (PackageCell *) initWithVersioner:(SEL)versioner {
1722 if ((self = [super init]) != nil) {
1723 versioner_ = versioner;
1725 GSFontRef bold = GSFontCreateWithName("Helvetica", kGSFontTraitBold, 22);
1726 GSFontRef large = GSFontCreateWithName("Helvetica", kGSFontTraitNone, 16);
1727 GSFontRef small = GSFontCreateWithName("Helvetica", kGSFontTraitNone, 14);
1729 CGColorSpaceRef space = CGColorSpaceCreateDeviceRGB();
1731 CGColor clear(space, 0, 0, 0, 0);
1733 icon_ = [[UIImageView alloc] initWithFrame:CGRectMake(10, 10, 30, 30)];
1735 name_ = [[UITextLabel alloc] initWithFrame:CGRectMake(48, 12, 240, 25)];
1736 [name_ setBackgroundColor:clear];
1737 [name_ setFont:bold];
1739 description_ = [[UITextLabel alloc] initWithFrame:CGRectMake(12, 46, 280, 20)];
1740 [description_ setBackgroundColor:clear];
1741 [description_ setFont:small];
1743 source_ = [[UITextLabel alloc] initWithFrame:CGRectMake(12, 72, 225, 20)];
1744 [source_ setBackgroundColor:clear];
1745 [source_ setFont:large];
1747 version_ = [[UIRightTextLabel alloc] initWithFrame:CGRectMake(286, 69, 70, 25)];
1748 [version_ setBackgroundColor:clear];
1749 [version_ setFont:large];
1751 //trusted_ = [[UIImageView alloc] initWithFrame:CGRectMake(278, 7, 16, 16)];
1752 trusted_ = [[UIImageView alloc] initWithFrame:CGRectMake(30, 30, 16, 16)];
1753 [trusted_ setImage:[UIImage applicationImageNamed:@"trusted.png"]];
1755 [self addSubview:icon_];
1756 [self addSubview:name_];
1757 [self addSubview:description_];
1758 [self addSubview:source_];
1759 [self addSubview:version_];
1761 CGColorSpaceRelease(space);
1769 - (void) setPackage:(Package *)package {
1770 Source *source = [package source];
1772 UIImage *image = nil;
1773 if (NSString *icon = [package icon])
1774 image = [UIImage imageAtPath:[icon substringFromIndex:6]];
1775 if (image == nil) if (NSString *icon = [source defaultIcon])
1776 image = [UIImage imageAtPath:[icon substringFromIndex:6]];
1778 image = [UIImage applicationImageNamed:@"unknown.png"];
1780 [icon_ setImage:image];
1781 [icon_ zoomToScale:0.5f];
1782 [icon_ setFrame:CGRectMake(10, 10, 30, 30)];
1784 [name_ setText:[package name]];
1785 [version_ setText:[package latest]];
1786 [description_ setText:[package tagline]];
1791 if (source != nil) {
1792 label = [source label];
1793 trusted = [source trusted];
1794 } else if ([[package id] isEqualToString:@"firmware"]) {
1798 label = @"Unknown/Local";
1802 [source_ setText:[NSString stringWithFormat:@"from %@", label]];
1804 [trusted_ removeFromSuperview];
1806 [self addSubview:trusted_];
1809 - (void) _setSelected:(float)fraction {
1810 CGColorSpaceRef space = CGColorSpaceCreateDeviceRGB();
1812 CGColor black(space,
1813 interpolate(0.0, 1.0, fraction),
1814 interpolate(0.0, 1.0, fraction),
1815 interpolate(0.0, 1.0, fraction),
1819 interpolate(0.2, 1.0, fraction),
1820 interpolate(0.2, 1.0, fraction),
1821 interpolate(1.0, 1.0, fraction),
1825 interpolate(0.4, 1.0, fraction),
1826 interpolate(0.4, 1.0, fraction),
1827 interpolate(0.4, 1.0, fraction),
1830 [name_ setColor:black];
1831 [description_ setColor:gray];
1832 [source_ setColor:black];
1833 [version_ setColor:blue];
1835 CGColorSpaceRelease(space);
1838 - (void) setSelected:(BOOL)selected {
1839 [self _setSelected:(selected ? 1.0 : 0.0)];
1840 [super setSelected:selected];
1843 - (void) setSelected:(BOOL)selected withFade:(BOOL)fade {
1845 [self _setSelected:(selected ? 1.0 : 0.0)];
1846 [super setSelected:selected withFade:fade];
1849 - (void) _setSelectionFadeFraction:(float)fraction {
1850 [self _setSelected:fraction];
1851 [super _setSelectionFadeFraction:fraction];
1857 /* Database Implementation {{{ */
1858 @implementation Database
1865 - (void) _readStatus:(NSNumber *)fd {
1866 NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init];
1868 __gnu_cxx::stdio_filebuf<char> ib([fd intValue], std::ios::in);
1869 std::istream is(&ib);
1874 pcre *code = pcre_compile("^([^:]*):([^:]*):([^:]*):(.*)$", 0, &error, &offset, NULL);
1876 pcre_extra *study = NULL;
1878 pcre_fullinfo(code, study, PCRE_INFO_CAPTURECOUNT, &capture);
1879 int matches[(capture + 1) * 3];
1881 while (std::getline(is, line)) {
1882 const char *data(line.c_str());
1884 _assert(pcre_exec(code, study, data, line.size(), 0, 0, matches, sizeof(matches) / sizeof(matches[0])) >= 0);
1886 std::istringstream buffer(line.substr(matches[6], matches[7] - matches[6]));
1889 [delegate_ setPercent:(percent / 100)];
1891 NSString *string = [NSString stringWithCString:(data + matches[8]) length:(matches[9] - matches[8])];
1892 std::string type(line.substr(matches[2], matches[3] - matches[2]));
1894 if (type == "pmerror")
1895 [delegate_ setError:string];
1896 else if (type == "pmstatus")
1897 [delegate_ setTitle:string];
1898 else if (type == "pmconffile")
1900 else _assert(false);
1907 - (void) _readOutput:(NSNumber *)fd {
1908 NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init];
1910 __gnu_cxx::stdio_filebuf<char> ib([fd intValue], std::ios::in);
1911 std::istream is(&ib);
1914 while (std::getline(is, line))
1915 [delegate_ addOutput:[NSString stringWithCString:line.c_str()]];
1921 - (Package *) packageWithName:(NSString *)name {
1922 pkgCache::PkgIterator iterator(cache_->FindPkg([name cString]));
1923 return iterator.end() ? nil : [Package packageWithIterator:iterator database:self];
1926 - (Database *) init {
1927 if ((self = [super init]) != nil) {
1933 sources_ = [[NSMutableDictionary dictionaryWithCapacity:16] retain];
1934 packages_ = [[NSMutableArray arrayWithCapacity:16] retain];
1938 _assert(pipe(fds) != -1);
1942 detachNewThreadSelector:@selector(_readStatus:)
1944 withObject:[[NSNumber numberWithInt:fds[0]] retain]
1947 _assert(pipe(fds) != -1);
1948 _assert(dup2(fds[1], 1) != -1);
1949 _assert(close(fds[1]) != -1);
1952 detachNewThreadSelector:@selector(_readOutput:)
1954 withObject:[[NSNumber numberWithInt:fds[0]] retain]
1959 - (pkgCacheFile &) cache {
1963 - (pkgRecords *) records {
1967 - (pkgProblemResolver *) resolver {
1971 - (pkgAcquire &) fetcher {
1975 - (NSArray *) packages {
1979 - (void) reloadData {
1989 if (!cache_.Open(progress_, true)) {
1990 fprintf(stderr, "repairing corrupted database...\n");
1993 _assert(cache_.Open(progress_, true));
1996 now_ = [NSDate date];
1998 records_ = new pkgRecords(cache_);
1999 resolver_ = new pkgProblemResolver(cache_);
2000 fetcher_ = new pkgAcquire(&status_);
2003 list_ = new pkgSourceList();
2004 _assert(list_->ReadMainList());
2006 [sources_ removeAllObjects];
2007 for (pkgSourceList::const_iterator source = list_->begin(); source != list_->end(); ++source) {
2008 std::vector<pkgIndexFile *> *indices = (*source)->GetIndexFiles();
2009 for (std::vector<pkgIndexFile *>::const_iterator index = indices->begin(); index != indices->end(); ++index)
2011 setObject:[[[Source alloc] initWithMetaIndex:*source] autorelease]
2012 forKey:[NSNumber numberWithLong:reinterpret_cast<uintptr_t>(*index)]
2016 [packages_ removeAllObjects];
2017 for (pkgCache::PkgIterator iterator = cache_->PkgBegin(); !iterator.end(); ++iterator)
2018 if (Package *package = [Package packageWithIterator:iterator database:self])
2019 if ([package source] != nil || [package installed] != nil)
2020 [packages_ addObject:package];
2024 pkgRecords records(cache_);
2026 lock_ = new FileFd();
2027 lock_->Fd(GetLock(_config->FindDir("Dir::Cache::Archives") + "lock"));
2028 _assert(!_error->PendingError());
2031 _assert(list.ReadMainList());
2033 manager_ = (_system->CreatePM(cache_));
2034 _assert(manager_->GetArchives(fetcher_, &list, &records));
2035 _assert(!_error->PendingError());
2039 if (fetcher_->Run(PulseInterval_) != pkgAcquire::Continue)
2043 pkgPackageManager::OrderResult result = manager_->DoInstall(statusfd_);
2045 if (result == pkgPackageManager::Failed)
2047 if (_error->PendingError())
2049 if (result != pkgPackageManager::Completed)
2055 _assert(list.ReadMainList());
2058 lock.Fd(GetLock(_config->FindDir("Dir::State::Lists") + "lock"));
2059 _assert(!_error->PendingError());
2061 pkgAcquire fetcher(&status_);
2062 _assert(list.GetIndexes(&fetcher));
2063 _assert(fetcher.Run(PulseInterval_) != pkgAcquire::Failed);
2065 bool failed = false;
2066 for (pkgAcquire::ItemIterator item = fetcher.ItemsBegin(); item != fetcher.ItemsEnd(); item++)
2067 if ((*item)->Status != pkgAcquire::Item::StatDone) {
2068 (*item)->Finished();
2072 if (!failed && _config->FindB("APT::Get::List-Cleanup", true) == true) {
2073 _assert(fetcher.Clean(_config->FindDir("Dir::State::lists")));
2074 _assert(fetcher.Clean(_config->FindDir("Dir::State::lists") + "partial/"));
2077 [Metadata_ setObject:[NSDate date] forKey:@"LastUpdate"];
2081 _assert(cache_->DelCount() == 0 && cache_->InstCount() == 0);
2082 _assert(pkgApplyStatus(cache_));
2084 if (cache_->BrokenCount() != 0) {
2085 _assert(pkgFixBroken(cache_));
2086 _assert(cache_->BrokenCount() == 0);
2087 _assert(pkgMinimizeUpgrade(cache_));
2090 _assert(pkgDistUpgrade(cache_));
2093 - (void) setDelegate:(id)delegate {
2094 delegate_ = delegate;
2095 status_.setDelegate(delegate);
2096 progress_.setDelegate(delegate);
2099 - (Source *) getSource:(const pkgCache::PkgFileIterator &)file {
2100 pkgIndexFile *index(NULL);
2101 list_->FindIndex(file, index);
2102 return [sources_ objectForKey:[NSNumber numberWithLong:reinterpret_cast<uintptr_t>(index)]];
2108 /* Progress Data {{{ */
2109 @interface ProgressData : NSObject {
2115 - (ProgressData *) initWithSelector:(SEL)selector target:(id)target object:(id)object;
2122 @implementation ProgressData
2124 - (ProgressData *) initWithSelector:(SEL)selector target:(id)target object:(id)object {
2125 if ((self = [super init]) != nil) {
2126 selector_ = selector;
2146 /* Progress View {{{ */
2147 @interface ProgressView : UIView <
2151 UIView *background_;
2152 UITransitionView *transition_;
2154 UINavigationBar *navbar_;
2155 UIProgressBar *progress_;
2156 UITextView *output_;
2157 UITextLabel *status_;
2163 - (void) transitionViewDidComplete:(UITransitionView*)view fromView:(UIView*)from toView:(UIView*)to;
2165 - (ProgressView *) initWithFrame:(struct CGRect)frame delegate:(id)delegate;
2166 - (void) setContentView:(UIView *)view;
2169 - (void) alertSheet:(UIAlertSheet *)sheet buttonClicked:(int)button;
2171 - (void) _retachThread;
2172 - (void) _detachNewThreadData:(ProgressData *)data;
2173 - (void) detachNewThreadSelector:(SEL)selector toTarget:(id)target withObject:(id)object title:(NSString *)title;
2175 - (void) setError:(NSString *)error;
2176 - (void) _setError:(NSString *)error;
2178 - (void) setTitle:(NSString *)title;
2179 - (void) _setTitle:(NSString *)title;
2181 - (void) setPercent:(float)percent;
2182 - (void) _setPercent:(NSNumber *)percent;
2184 - (void) addOutput:(NSString *)output;
2185 - (void) _addOutput:(NSString *)output;
2188 @protocol ProgressViewDelegate
2189 - (void) progressViewIsComplete:(ProgressView *)sender;
2192 @implementation ProgressView
2196 if (background_ != nil)
2197 [background_ release];
2198 [transition_ release];
2201 [progress_ release];
2207 - (void) transitionViewDidComplete:(UITransitionView*)view fromView:(UIView*)from toView:(UIView*)to {
2208 if (bootstrap_ && from == overlay_ && to == view_)
2212 - (ProgressView *) initWithFrame:(struct CGRect)frame delegate:(id)delegate {
2213 if ((self = [super initWithFrame:frame]) != nil) {
2214 delegate_ = delegate;
2216 CGColorSpaceRef space = CGColorSpaceCreateDeviceRGB();
2218 CGColor black(space, 0.0, 0.0, 0.0, 1.0);
2219 CGColor white(space, 1.0, 1.0, 1.0, 1.0);
2220 CGColor clear(space, 0.0, 0.0, 0.0, 0.0);
2222 transition_ = [[UITransitionView alloc] initWithFrame:[self bounds]];
2223 [transition_ setDelegate:self];
2225 overlay_ = [[UIView alloc] initWithFrame:[transition_ bounds]];
2228 [overlay_ setBackgroundColor:black];
2230 background_ = [[UIView alloc] initWithFrame:[self bounds]];
2231 [background_ setBackgroundColor:black];
2232 [self addSubview:background_];
2235 [self addSubview:transition_];
2237 CGSize navsize = [UINavigationBar defaultSize];
2238 CGRect navrect = {{0, 0}, navsize};
2240 navbar_ = [[UINavigationBar alloc] initWithFrame:navrect];
2241 [overlay_ addSubview:navbar_];
2243 [navbar_ setBarStyle:1];
2244 [navbar_ setDelegate:self];
2246 UINavigationItem *navitem = [[[UINavigationItem alloc] initWithTitle:nil] autorelease];
2247 [navbar_ pushNavigationItem:navitem];
2249 CGRect bounds = [overlay_ bounds];
2250 CGSize prgsize = [UIProgressBar defaultSize];
2253 (bounds.size.width - prgsize.width) / 2,
2254 bounds.size.height - prgsize.height - 20
2257 progress_ = [[UIProgressBar alloc] initWithFrame:prgrect];
2258 [overlay_ addSubview:progress_];
2260 status_ = [[UITextLabel alloc] initWithFrame:CGRectMake(
2262 bounds.size.height - prgsize.height - 50,
2263 bounds.size.width - 20,
2267 [status_ setColor:white];
2268 [status_ setBackgroundColor:clear];
2270 [status_ setCentersHorizontally:YES];
2271 //[status_ setFont:font];
2273 output_ = [[UITextView alloc] initWithFrame:CGRectMake(
2275 navrect.size.height + 20,
2276 bounds.size.width - 20,
2277 bounds.size.height - navsize.height - 62 - navrect.size.height
2280 //[output_ setTextFont:@"Courier New"];
2281 [output_ setTextSize:12];
2283 [output_ setTextColor:white];
2284 [output_ setBackgroundColor:clear];
2286 [output_ setMarginTop:0];
2287 [output_ setAllowsRubberBanding:YES];
2289 [overlay_ addSubview:output_];
2290 [overlay_ addSubview:status_];
2292 [progress_ setStyle:0];
2294 CGColorSpaceRelease(space);
2298 - (void) setContentView:(UIView *)view {
2299 view_ = [view retain];
2302 - (void) resetView {
2303 [transition_ transition:6 toView:view_];
2306 - (void) alertSheet:(UIAlertSheet *)sheet buttonClicked:(int)button {
2310 - (void) _retachThread {
2311 [delegate_ progressViewIsComplete:self];
2315 - (void) _detachNewThreadData:(ProgressData *)data {
2316 NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init];
2318 [[data target] performSelector:[data selector] withObject:[data object]];
2321 [self performSelectorOnMainThread:@selector(_retachThread) withObject:nil waitUntilDone:YES];
2326 - (void) detachNewThreadSelector:(SEL)selector toTarget:(id)target withObject:(id)object title:(NSString *)title {
2327 [navbar_ popNavigationItem];
2328 UINavigationItem *navitem = [[[UINavigationItem alloc] initWithTitle:title] autorelease];
2329 [navbar_ pushNavigationItem:navitem];
2331 [status_ setText:nil];
2332 [output_ setText:@""];
2333 [progress_ setProgress:0];
2335 [transition_ transition:6 toView:overlay_];
2338 detachNewThreadSelector:@selector(_detachNewThreadData:)
2340 withObject:[[ProgressData alloc]
2341 initWithSelector:selector
2348 - (void) setError:(NSString *)error {
2350 performSelectorOnMainThread:@selector(_setError:)
2356 - (void) _setError:(NSString *)error {
2357 UIAlertSheet *sheet = [[[UIAlertSheet alloc]
2358 initWithTitle:@"Package Error"
2359 buttons:[NSArray arrayWithObjects:@"Okay", nil]
2360 defaultButtonIndex:0
2365 [sheet setBodyText:error];
2366 [sheet popupAlertAnimated:YES];
2369 - (void) setTitle:(NSString *)title {
2371 performSelectorOnMainThread:@selector(_setTitle:)
2377 - (void) _setTitle:(NSString *)title {
2378 [status_ setText:[title stringByAppendingString:@"..."]];
2381 - (void) setPercent:(float)percent {
2383 performSelectorOnMainThread:@selector(_setPercent:)
2384 withObject:[NSNumber numberWithFloat:percent]
2389 - (void) _setPercent:(NSNumber *)percent {
2390 [progress_ setProgress:[percent floatValue]];
2393 - (void) addOutput:(NSString *)output {
2395 performSelectorOnMainThread:@selector(_addOutput:)
2401 - (void) _addOutput:(NSString *)output {
2402 [output_ setText:[NSString stringWithFormat:@"%@\n%@", [output_ text], output]];
2403 CGSize size = [output_ contentSize];
2404 CGRect rect = {{0, size.height}, {size.width, 0}};
2405 [output_ scrollRectToVisible:rect animated:YES];
2411 /* Package Table {{{ */
2412 @protocol PackageTableDelegate
2413 - (void) packageTable:(id)table packageSelected:(Package *)package;
2416 @interface PackageTable : UIView {
2418 UISectionList *list_;
2422 NSMutableArray *sections_;
2427 - (int) numberOfSectionsInSectionList:(UISectionList *)list;
2428 - (NSString *) sectionList:(UISectionList *)list titleForSection:(int)section;
2429 - (int) sectionList:(UISectionList *)list rowForSection:(int)section;
2431 - (int) numberOfRowsInTable:(UITable *)table;
2432 - (float) table:(UITable *)table heightForRow:(int)row;
2433 - (UITableCell *) table:(UITable *)table cellForRow:(int)row column:(UITableColumn *)col reusing:(UITableCell *)reusing;
2434 - (BOOL) table:(UITable *)table showDisclosureForRow:(int)row;
2435 - (void) tableRowSelected:(NSNotification *)notification;
2437 - (id) initWithFrame:(CGRect)frame versioner:(SEL)versioner;
2439 - (void) setDelegate:(id)delegate;
2440 - (void) setPackages:(NSArray *)packages;
2442 - (void) resetViewAnimated:(BOOL)animated;
2443 - (UITable *) table;
2446 @implementation PackageTable
2450 [sections_ release];
2451 if (packages_ != nil)
2452 [packages_ release];
2456 - (int) numberOfSectionsInSectionList:(UISectionList *)list {
2457 return [sections_ count];
2460 - (NSString *) sectionList:(UISectionList *)list titleForSection:(int)section {
2461 return [[sections_ objectAtIndex:section] name];
2464 - (int) sectionList:(UISectionList *)list rowForSection:(int)section {
2465 return [[sections_ objectAtIndex:section] row];
2468 - (int) numberOfRowsInTable:(UITable *)table {
2469 return [packages_ count];
2472 - (float) table:(UITable *)table heightForRow:(int)row {
2476 - (UITableCell *) table:(UITable *)table cellForRow:(int)row column:(UITableColumn *)col reusing:(UITableCell *)reusing {
2478 reusing = [[[PackageCell alloc] initWithVersioner:versioner_] autorelease];
2479 [(PackageCell *)reusing setPackage:[packages_ objectAtIndex:row]];
2483 - (BOOL) table:(UITable *)table showDisclosureForRow:(int)row {
2487 - (void) tableRowSelected:(NSNotification *)notification {
2488 int row = [[notification object] selectedRow];
2489 [delegate_ packageTable:self packageSelected:(row == INT_MAX ? nil : [packages_ objectAtIndex:row])];
2492 - (id) initWithFrame:(CGRect)frame versioner:(SEL)versioner {
2493 if ((self = [super initWithFrame:frame]) != nil) {
2494 versioner_ = versioner;
2495 sections_ = [[NSMutableArray arrayWithCapacity:16] retain];
2497 list_ = [[UISectionList alloc] initWithFrame:[self bounds] showSectionIndex:YES];
2498 [list_ setDataSource:self];
2500 UITableColumn *column = [[[UITableColumn alloc]
2501 initWithTitle:@"Name"
2503 width:frame.size.width
2506 UITable *table = [list_ table];
2507 [table setSeparatorStyle:1];
2508 [table addTableColumn:column];
2509 [table setDelegate:self];
2510 [table setReusesTableCells:YES];
2512 [self addSubview:list_];
2516 - (void) setDelegate:(id)delegate {
2517 delegate_ = delegate;
2520 - (void) setPackages:(NSArray *)packages {
2521 if (packages_ != nil)
2522 [packages_ autorelease];
2523 _assert(packages != nil);
2524 packages_ = [packages retain];
2526 [sections_ removeAllObjects];
2528 Section *section = nil;
2530 for (size_t offset(0); offset != [packages_ count]; ++offset) {
2531 Package *package = [packages_ objectAtIndex:offset];
2532 NSString *name = [package index];
2534 if (section == nil || ![[section name] isEqual:name]) {
2535 section = [[[Section alloc] initWithName:name row:offset] autorelease];
2536 [sections_ addObject:section];
2539 [section addPackage:package];
2545 - (void) resetViewAnimated:(BOOL)animated {
2546 [[list_ table] selectRow:-1 byExtendingSelection:NO withFade:animated];
2549 - (UITable *) table {
2550 return [list_ table];
2556 /* Section Cell {{{ */
2557 @interface SectionCell : UITableCell {
2559 UITextLabel *count_;
2565 - (void) setSection:(Section *)section;
2567 - (void) _setSelected:(float)fraction;
2568 - (void) setSelected:(BOOL)selected;
2569 - (void) setSelected:(BOOL)selected withFade:(BOOL)fade;
2570 - (void) _setSelectionFadeFraction:(float)fraction;
2574 @implementation SectionCell
2583 if ((self = [super init]) != nil) {
2584 GSFontRef bold = GSFontCreateWithName("Helvetica", kGSFontTraitBold, 22);
2585 GSFontRef small = GSFontCreateWithName("Helvetica", kGSFontTraitBold, 12);
2587 CGColorSpaceRef space = CGColorSpaceCreateDeviceRGB();
2588 CGColor clear(space, 0, 0, 0, 0);
2589 CGColor white(space, 1, 1, 1, 1);
2591 name_ = [[UITextLabel alloc] initWithFrame:CGRectMake(48, 9, 250, 25)];
2592 [name_ setBackgroundColor:clear];
2593 [name_ setFont:bold];
2595 count_ = [[UITextLabel alloc] initWithFrame:CGRectMake(11, 7, 29, 32)];
2596 [count_ setCentersHorizontally:YES];
2597 [count_ setBackgroundColor:clear];
2598 [count_ setFont:small];
2599 [count_ setColor:white];
2601 UIImageView *folder = [[[UIImageView alloc] initWithFrame:CGRectMake(8, 7, 32, 32)] autorelease];
2602 [folder setImage:[UIImage applicationImageNamed:@"folder.png"]];
2604 [self addSubview:folder];
2605 [self addSubview:name_];
2606 [self addSubview:count_];
2608 [self _setSelected:0];
2610 CGColorSpaceRelease(space);
2617 - (void) setSection:(Section *)section {
2618 if (section == nil) {
2619 [name_ setText:@"All Packages"];
2620 [count_ setText:nil];
2622 NSString *name = [section name];
2623 [name_ setText:(name == nil ? @"(No Section)" : name)];
2624 [count_ setText:[NSString stringWithFormat:@"%d", [section count]]];
2628 - (void) _setSelected:(float)fraction {
2629 CGColorSpaceRef space = CGColorSpaceCreateDeviceRGB();
2631 CGColor black(space,
2632 interpolate(0.0, 1.0, fraction),
2633 interpolate(0.0, 1.0, fraction),
2634 interpolate(0.0, 1.0, fraction),
2637 [name_ setColor:black];
2639 CGColorSpaceRelease(space);
2642 - (void) setSelected:(BOOL)selected {
2643 [self _setSelected:(selected ? 1.0 : 0.0)];
2644 [super setSelected:selected];
2647 - (void) setSelected:(BOOL)selected withFade:(BOOL)fade {
2649 [self _setSelected:(selected ? 1.0 : 0.0)];
2650 [super setSelected:selected withFade:fade];
2653 - (void) _setSelectionFadeFraction:(float)fraction {
2654 [self _setSelected:fraction];
2655 [super _setSelectionFadeFraction:fraction];
2660 /* Install View {{{ */
2661 @interface InstallView : ResetView <
2662 PackageTableDelegate
2666 PackageTable *table_;
2670 NSMutableArray *packages_;
2675 - (void) navigationBar:(UINavigationBar *)navbar buttonClicked:(int)button;
2677 - (int) numberOfRowsInTable:(UITable *)table;
2678 - (float) table:(UITable *)table heightForRow:(int)row;
2679 - (UITableCell *) table:(UITable *)table cellForRow:(int)row column:(UITableColumn *)col reusing:(UITableCell *)reusing;
2680 - (BOOL) table:(UITable *)table showDisclosureForRow:(int)row;
2681 - (void) tableRowSelected:(NSNotification *)notification;
2683 - (void) packageTable:(id)table packageSelected:(Package *)package;
2685 - (id) initWithFrame:(CGRect)frame;
2686 - (void) setPackages:(NSArray *)packages;
2687 - (void) setDelegate:(id)delegate;
2690 @implementation InstallView
2693 [packages_ release];
2694 if (sections_ != nil)
2695 [sections_ release];
2702 if (section_ != nil)
2704 if (package_ != nil)
2709 - (void) navigationBar:(UINavigationBar *)navbar buttonClicked:(int)button {
2711 [[view_ package] install];
2712 [delegate_ resolve];
2713 [delegate_ perform];
2717 - (int) numberOfRowsInTable:(UITable *)table {
2718 return [sections_ count] + 1;
2721 - (float) table:(UITable *)table heightForRow:(int)row {
2725 - (UITableCell *) table:(UITable *)table cellForRow:(int)row column:(UITableColumn *)col reusing:(UITableCell *)reusing {
2727 reusing = [[[SectionCell alloc] init] autorelease];
2729 [(SectionCell *)reusing setSection:nil];
2731 [(SectionCell *)reusing setSection:[sections_ objectAtIndex:(row - 1)]];
2735 - (BOOL) table:(UITable *)table showDisclosureForRow:(int)row {
2739 - (void) tableRowSelected:(NSNotification *)notification {
2740 int row = [[notification object] selectedRow];
2742 if (row == INT_MAX) {
2749 _assert(section_ == nil);
2750 _assert(table_ == nil);
2758 name = @"All Packages";
2760 section = [sections_ objectAtIndex:(row - 1)];
2761 name = [section name];
2762 section_ = [name retain];
2765 table_ = [[PackageTable alloc] initWithFrame:[transition_ bounds] versioner:@selector(latest)];
2766 [table_ setDelegate:self];
2767 [table_ setPackages:(section == nil ? packages_ : [section packages])];
2769 [self pushView:table_ withTitle:name backButtonTitle:@"Packages" rightButton:nil];
2773 - (void) packageTable:(id)table packageSelected:(Package *)package {
2774 if (package == nil) {
2781 _assert(package_ == nil);
2782 _assert(view_ == nil);
2784 package_ = [[package name] retain];
2786 view_ = [[PackageView alloc] initWithFrame:[transition_ bounds]];
2787 [view_ setDelegate:delegate_];
2789 [view_ setPackage:package];
2791 [self pushView:view_ withTitle:[package name] backButtonTitle:nil rightButton:@"Install"];
2795 - (id) initWithFrame:(CGRect)frame {
2796 if ((self = [super initWithFrame:frame]) != nil) {
2797 packages_ = [[NSMutableArray arrayWithCapacity:16] retain];
2799 list_ = [[UITable alloc] initWithFrame:[transition_ bounds]];
2800 [self pushView:list_ withTitle:@"Install" backButtonTitle:@"Sections" rightButton:nil];
2802 UITableColumn *column = [[[UITableColumn alloc]
2803 initWithTitle:@"Name"
2805 width:frame.size.width
2808 [list_ setDataSource:self];
2809 [list_ setSeparatorStyle:1];
2810 [list_ addTableColumn:column];
2811 [list_ setDelegate:self];
2812 [list_ setReusesTableCells:YES];
2814 [transition_ transition:0 toView:list_];
2818 - (void) setPackages:(NSArray *)packages {
2819 [packages_ removeAllObjects];
2821 for (size_t i(0); i != [packages count]; ++i) {
2822 Package *package([packages objectAtIndex:i]);
2823 if ([package installed] == nil)
2824 [packages_ addObject:package];
2827 [packages_ sortUsingSelector:@selector(compareBySectionAndName:)];
2828 NSMutableArray *sections = [NSMutableArray arrayWithCapacity:16];
2830 Section *nsection = nil;
2831 Package *npackage = nil;
2833 Section *section = nil;
2834 for (size_t offset = 0, count = [packages_ count]; offset != count; ++offset) {
2835 Package *package = [packages_ objectAtIndex:offset];
2836 NSString *name = [package section];
2838 if (section == nil || name != nil && ![[section name] isEqual:name]) {
2839 section = [[[Section alloc] initWithName:name row:offset] autorelease];
2841 if (name == nil || [name isEqualToString:section_])
2843 [sections addObject:section];
2846 if ([[package name] isEqualToString:package_])
2848 [section addPackage:package];
2851 if (sections_ != nil)
2852 [sections_ release];
2853 sections_ = [sections retain];
2855 [packages_ sortUsingSelector:@selector(compareByName:)];
2861 if (npackage != nil)
2862 [view_ setPackage:npackage];
2863 else if (package_ != nil)
2866 if (table_ != nil && section_ == nil)
2867 [table_ setPackages:packages_];
2868 else if (nsection != nil)
2869 [table_ setPackages:[nsection packages]];
2870 else if (section_ != nil)
2874 [self popViews:views];
2878 - (void) setDelegate:(id)delegate {
2880 [view_ setDelegate:delegate];
2881 [super setDelegate:delegate];
2886 /* Changes View {{{ */
2887 @interface ChangesView : ResetView <
2888 PackageTableDelegate
2890 UISectionList *list_;
2891 NSMutableArray *packages_;
2892 NSMutableArray *sections_;
2900 - (void) navigationBar:(UINavigationBar *)navbar buttonClicked:(int)button;
2902 - (int) numberOfSectionsInSectionList:(UISectionList *)list;
2903 - (NSString *) sectionList:(UISectionList *)list titleForSection:(int)section;
2904 - (int) sectionList:(UISectionList *)list rowForSection:(int)section;
2906 - (int) numberOfRowsInTable:(UITable *)table;
2907 - (float) table:(UITable *)table heightForRow:(int)row;
2908 - (UITableCell *) table:(UITable *)table cellForRow:(int)row column:(UITableColumn *)col reusing:(UITableCell *)reusing;
2909 - (BOOL) table:(UITable *)table showDisclosureForRow:(int)row;
2910 - (void) tableRowSelected:(NSNotification *)notification;
2912 - (id) initWithFrame:(CGRect)frame;
2913 - (void) setPackages:(NSArray *)packages;
2914 - (void) _resetView;
2917 - (void) setDelegate:(id)delegate;
2920 @implementation ChangesView
2924 [packages_ release];
2925 [sections_ release];
2928 if (package_ != nil)
2933 - (int) numberOfSectionsInSectionList:(UISectionList *)list {
2934 return [sections_ count];
2937 - (NSString *) sectionList:(UISectionList *)list titleForSection:(int)section {
2938 return [[sections_ objectAtIndex:section] name];
2941 - (int) sectionList:(UISectionList *)list rowForSection:(int)section {
2942 return [[sections_ objectAtIndex:section] row];
2945 - (int) numberOfRowsInTable:(UITable *)table {
2946 return [packages_ count];
2949 - (float) table:(UITable *)table heightForRow:(int)row {
2953 - (UITableCell *) table:(UITable *)table cellForRow:(int)row column:(UITableColumn *)col reusing:(UITableCell *)reusing {
2955 reusing = [[[PackageCell alloc] initWithVersioner:NULL] autorelease];
2956 [(PackageCell *)reusing setPackage:[packages_ objectAtIndex:row]];
2960 - (BOOL) table:(UITable *)table showDisclosureForRow:(int)row {
2964 - (void) tableRowSelected:(NSNotification *)notification {
2965 int row = [[notification object] selectedRow];
2966 [self packageTable:self packageSelected:(row == INT_MAX ? nil : [packages_ objectAtIndex:row])];
2969 - (void) navigationBar:(UINavigationBar *)navbar buttonClicked:(int)button {
2972 [[view_ package] install];
2973 [delegate_ resolve];
2974 [delegate_ perform];
2978 [delegate_ upgrade];
2983 - (void) packageTable:(id)table packageSelected:(Package *)package {
2984 if (package == nil) {
2991 _assert(package_ == nil);
2992 _assert(view_ == nil);
2994 package_ = [[package name] retain];
2996 view_ = [[PackageView alloc] initWithFrame:[transition_ bounds]];
2997 [view_ setDelegate:delegate_];
2999 [view_ setPackage:package];
3001 [self pushView:view_ withTitle:[package name] backButtonTitle:nil rightButton:(
3002 [package upgradable] ? @"Upgrade" : @"Install"
3007 - (id) initWithFrame:(CGRect)frame {
3008 if ((self = [super initWithFrame:frame]) != nil) {
3009 packages_ = [[NSMutableArray arrayWithCapacity:16] retain];
3010 sections_ = [[NSMutableArray arrayWithCapacity:16] retain];
3012 list_ = [[UISectionList alloc] initWithFrame:[transition_ bounds] showSectionIndex:NO];
3013 [list_ setShouldHideHeaderInShortLists:NO];
3014 [list_ setDataSource:self];
3015 //[list_ setSectionListStyle:1];
3017 UITableColumn *column = [[[UITableColumn alloc]
3018 initWithTitle:@"Name"
3020 width:frame.size.width
3023 UITable *table = [list_ table];
3024 [table setSeparatorStyle:1];
3025 [table addTableColumn:column];
3026 [table setDelegate:self];
3027 [table setReusesTableCells:YES];
3029 [self pushView:list_ withTitle:@"Changes" backButtonTitle:nil rightButton:nil];
3033 - (void) setPackages:(NSArray *)packages {
3034 [packages_ removeAllObjects];
3035 for (size_t i(0); i != [packages count]; ++i) {
3036 Package *package([packages objectAtIndex:i]);
3037 if ([package installed] == nil || [package upgradable])
3038 [packages_ addObject:package];
3041 [packages_ sortUsingSelector:@selector(compareForChanges:)];
3043 [sections_ removeAllObjects];
3045 Section *upgradable = [[[Section alloc] initWithName:@"Available Upgrades" row:0] autorelease];
3046 Section *section = nil;
3049 Package *npackage = nil;
3050 for (size_t offset = 0, count = [packages_ count]; offset != count; ++offset) {
3051 Package *package = [packages_ objectAtIndex:offset];
3052 if ([[package name] isEqualToString:package_])
3055 if ([package upgradable])
3056 [upgradable addPackage:package];
3058 NSDate *seen = [package seen];
3061 CFStringRef formatted = NULL;
3066 CFLocaleRef locale = CFLocaleCopyCurrent();
3067 CFDateFormatterRef formatter = CFDateFormatterCreate(NULL, locale, kCFDateFormatterMediumStyle, kCFDateFormatterMediumStyle);
3068 formatted = CFDateFormatterCreateStringWithDate(NULL, formatter, (CFDateRef) seen);
3069 name = (NSString *) formatted;
3070 CFRelease(formatter);
3074 if (section == nil || ![[section name] isEqual:name]) {
3075 section = [[[Section alloc] initWithName:name row:offset] autorelease];
3076 [sections_ addObject:section];
3079 [section addPackage:package];
3081 if (formatted != NULL)
3082 CFRelease(formatted);
3086 count_ = [[upgradable packages] count];
3088 [sections_ insertObject:upgradable atIndex:0];
3092 if (npackage != nil)
3093 [view_ setPackage:npackage];
3094 else if (package_ != nil)
3101 - (void) _resetView {
3102 if ([views_ count] == 1)
3103 [navbar_ showButtonsWithLeftTitle:(count_ == 0 ? nil : @"Upgrade All") rightTitle:nil];
3110 - (void) setDelegate:(id)delegate {
3112 [view_ setDelegate:delegate];
3113 [super setDelegate:delegate];
3118 /* Manage View {{{ */
3119 @interface ManageView : ResetView <
3120 PackageTableDelegate
3122 PackageTable *table_;
3129 - (void) navigationBar:(UINavigationBar *)navbar buttonClicked:(int)button;
3131 - (void) packageTable:(id)table packageSelected:(Package *)package;
3133 - (id) initWithFrame:(CGRect)frame;
3134 - (void) setPackages:(NSArray *)packages;
3136 - (void) setDelegate:(id)delegate;
3139 @implementation ManageView
3145 if (package_ != nil)
3150 - (void) navigationBar:(UINavigationBar *)navbar buttonClicked:(int)button {
3152 [[view_ package] remove];
3153 [delegate_ resolve];
3154 [delegate_ perform];
3158 - (void) packageTable:(id)table packageSelected:(Package *)package {
3159 if (package == nil) {
3166 _assert(package_ == nil);
3167 _assert(view_ == nil);
3169 package_ = [[package name] retain];
3171 view_ = [[PackageView alloc] initWithFrame:[transition_ bounds]];
3172 [view_ setDelegate:delegate_];
3174 [view_ setPackage:package];
3176 [self pushView:view_ withTitle:[package name] backButtonTitle:nil rightButton:@"Uninstall"];
3180 - (id) initWithFrame:(CGRect)frame {
3181 if ((self = [super initWithFrame:frame]) != nil) {
3182 table_ = [[PackageTable alloc] initWithFrame:[transition_ bounds] versioner:@selector(latest)];
3183 [table_ setDelegate:self];
3185 [self pushView:table_ withTitle:@"Uninstall" backButtonTitle:@"Packages" rightButton:nil];
3189 - (void) setPackages:(NSArray *)packages {
3190 NSMutableArray *local = [NSMutableArray arrayWithCapacity:16];
3191 for (size_t i(0); i != [packages count]; ++i) {
3192 Package *package([packages objectAtIndex:i]);
3193 if ([package installed] != nil)
3194 [local addObject:package];
3197 [local sortUsingSelector:@selector(compareByName:)];
3199 Package *npackage = nil;
3200 for (size_t offset = 0, count = [local count]; offset != count; ++offset) {
3201 Package *package = [local objectAtIndex:offset];
3202 if ([[package name] isEqualToString:package_])
3206 [table_ setPackages:local];
3208 if (npackage != nil)
3209 [view_ setPackage:npackage];
3210 else if (package_ != nil)
3216 - (void) setDelegate:(id)delegate {
3218 [view_ setDelegate:delegate];
3219 [super setDelegate:delegate];
3224 /* Search View {{{ */
3225 @protocol SearchViewDelegate
3226 - (void) showKeyboard:(BOOL)show;
3229 @interface SearchView : ResetView <
3230 PackageTableDelegate
3232 NSMutableArray *packages_;
3234 UISearchField *field_;
3235 PackageTable *table_;
3242 - (void) navigationBar:(UINavigationBar *)navbar buttonClicked:(int)button;
3243 - (void) packageTable:(id)table packageSelected:(Package *)package;
3245 - (void) textFieldDidBecomeFirstResponder:(UITextField *)field;
3246 - (void) textFieldDidResignFirstResponder:(UITextField *)field;
3248 - (void) keyboardInputChanged:(UIFieldEditor *)editor;
3249 - (BOOL) keyboardInput:(id)input shouldInsertText:(NSString *)text isMarkedText:(int)marked;
3251 - (id) initWithFrame:(CGRect)frame;
3252 - (void) setPackages:(NSArray *)packages;
3254 - (void) setDelegate:(id)delegate;
3255 - (void) resetPackage:(Package *)package;
3256 - (void) searchPackages;
3260 @implementation SearchView
3263 [packages_ release];
3264 [accessory_ release];
3269 if (package_ != nil)
3274 - (void) navigationBar:(UINavigationBar *)navbar buttonClicked:(int)button {
3276 Package *package = [view_ package];
3277 if ([package installed] == nil)
3281 [delegate_ resolve];
3282 [delegate_ perform];
3286 - (void) packageTable:(id)table packageSelected:(Package *)package {
3287 if (package == nil) {
3288 [navbar_ setAccessoryView:accessory_ animate:(resetting_ ? NO : YES) goingBack:YES];
3296 [navbar_ setAccessoryView:nil animate:YES goingBack:NO];
3298 _assert(package_ == nil);
3299 _assert(view_ == nil);
3301 package_ = [[package name] retain];
3303 view_ = [[PackageView alloc] initWithFrame:[transition_ bounds]];
3304 [view_ setDelegate:delegate_];
3306 [self pushView:view_ withTitle:[package name] backButtonTitle:nil rightButton:nil];
3307 [self resetPackage:package];
3311 - (void) textFieldDidBecomeFirstResponder:(UITextField *)field {
3312 [delegate_ showKeyboard:YES];
3313 [table_ setEnabled:NO];
3315 /*CGColorSpaceRef space = CGColorSpaceCreateDeviceRGB();
3316 CGColor dimmed(alpha, 0, 0, 0, 0.5);
3317 [editor_ setBackgroundColor:dimmed];
3318 CGColorSpaceRelease(space);*/
3321 - (void) textFieldDidResignFirstResponder:(UITextField *)field {
3322 [table_ setEnabled:YES];
3323 [delegate_ showKeyboard:NO];
3326 - (void) keyboardInputChanged:(UIFieldEditor *)editor {
3327 NSString *text([field_ text]);
3328 [field_ setClearButtonStyle:(text == nil || [text length] == 0 ? 0 : 2)];
3331 - (BOOL) keyboardInput:(id)input shouldInsertText:(NSString *)text isMarkedText:(int)marked {
3332 if ([text length] != 1 || [text characterAtIndex:0] != '\n')
3335 [self searchPackages];
3336 [field_ resignFirstResponder];
3340 - (id) initWithFrame:(CGRect)frame {
3341 if ((self = [super initWithFrame:frame]) != nil) {
3342 packages_ = [[NSMutableArray arrayWithCapacity:16] retain];
3344 table_ = [[PackageTable alloc] initWithFrame:[transition_ bounds] versioner:@selector(latest)];
3345 [table_ setDelegate:self];
3347 CGRect area = [self bounds];
3350 area.size.width -= 12;
3351 area.size.height = [UISearchField defaultHeight];
3353 field_ = [[UISearchField alloc] initWithFrame:area];
3355 GSFontRef font = GSFontCreateWithName("Helvetica", kGSFontTraitNone, 16);
3356 [field_ setFont:font];
3359 [field_ setPlaceholder:@"Package Names & Descriptions"];
3360 [field_ setPaddingTop:5];
3361 [field_ setDelegate:self];
3363 UITextTraits *traits = [field_ textTraits];
3364 [traits setEditingDelegate:self];
3365 [traits setReturnKeyType:6];
3367 accessory_ = [[UIView alloc] initWithFrame:CGRectMake(6, 6, area.size.width, area.size.height + 30)];
3368 [accessory_ addSubview:field_];
3370 [navbar_ setAccessoryView:accessory_];
3371 [self pushView:table_ withTitle:nil backButtonTitle:@"Search" rightButton:nil];
3373 /* XXX: for the love of god just fix this */
3374 [navbar_ removeFromSuperview];
3375 [reload_ removeFromSuperview];
3376 [configure_ removeFromSuperview];
3377 [self addSubview:navbar_];
3378 [self addSubview:reload_];
3379 [self addSubview:configure_];
3383 - (void) setPackages:(NSArray *)packages {
3384 [packages_ removeAllObjects];
3385 [packages_ addObjectsFromArray:packages];
3386 [packages_ sortUsingSelector:@selector(compareByName:)];
3388 Package *npackage = nil;
3389 for (size_t offset = 0, count = [packages_ count]; offset != count; ++offset) {
3390 Package *package = [packages_ objectAtIndex:offset];
3391 if ([[package name] isEqualToString:package_])
3395 [self searchPackages];
3397 if (npackage != nil)
3398 [self resetPackage:npackage];
3399 else if (package_ != nil)
3405 - (void) setDelegate:(id)delegate {
3407 [view_ setDelegate:delegate];
3408 [super setDelegate:delegate];
3411 - (void) resetPackage:(Package *)package {
3412 [view_ setPackage:package];
3413 NSString *right = [package installed] == nil ? @"Install" : @"Uninstall";
3414 [navbar_ showButtonsWithLeftTitle:nil rightTitle:right];
3417 - (void) searchPackages {
3418 NSString *text([field_ text]);
3420 NSMutableArray *packages([NSMutableArray arrayWithCapacity:16]);
3422 for (size_t offset(0), count([packages_ count]); offset != count; ++offset) {
3423 Package *package = [packages_ objectAtIndex:offset];
3424 if ([package matches:text])
3425 [packages addObject:package];
3428 [table_ setPackages:packages];
3429 [[table_ table] scrollPointVisibleAtTopLeft:CGPointMake(0, 0) animated:NO];
3435 @interface Cydia : UIApplication <
3436 ConfirmationViewDelegate,
3437 ProgressViewDelegate,
3443 UITransitionView *transition_;
3444 UIButtonBar *buttonbar_;
3446 ConfirmationView *confirm_;
3448 Database *database_;
3449 ProgressView *progress_;
3452 UINavigationBar *navbar_;
3453 UIScroller *scroller_;
3454 UIWebView *webview_;
3456 UIProgressIndicator *indicator_;
3458 InstallView *install_;
3459 ChangesView *changes_;
3460 ManageView *manage_;
3461 SearchView *search_;
3466 UIKeyboard *keyboard_;
3470 - (void) reloadData:(BOOL)reset;
3481 - (void) progressViewIsComplete:(ProgressView *)progress;
3483 - (void) navigationBar:(UINavigationBar *)navbar buttonClicked:(int)button;
3484 - (void) alertSheet:(UIAlertSheet *)sheet buttonClicked:(int)button;
3485 - (void) buttonBarItemTapped:(id)sender;
3487 - (void) view:(UIView *)sender didSetFrame:(CGRect)frame oldFrame:(CGRect)old;
3489 - (void) webView:(WebView *)sender didReceiveTitle:(NSString *)title forFrame:(WebFrame *)frame;
3491 - (void) applicationWillSuspend;
3492 - (void) applicationDidFinishLaunching:(id)unused;
3495 @implementation Cydia
3498 NSMutableURLRequest *request = [NSMutableURLRequest
3500 cachePolicy:NSURLRequestReloadIgnoringCacheData
3501 timeoutInterval:30.0
3504 [request addValue:[NSString stringWithCString:Firmware_] forHTTPHeaderField:@"X-Firmware"];
3505 [request addValue:[NSString stringWithCString:Machine_] forHTTPHeaderField:@"X-Machine"];
3506 [request addValue:[NSString stringWithCString:SerialNumber_] forHTTPHeaderField:@"X-Serial-Number"];
3508 [webview_ loadRequest:request];
3511 - (void) reloadData:(BOOL)reset {
3512 [database_ reloadData];
3516 if (Packages_ == nil) {
3517 Packages_ = [[NSMutableDictionary alloc] initWithCapacity:count];
3518 [Metadata_ setObject:Packages_ forKey:@"Packages"];
3521 NSArray *packages = [database_ packages];
3523 [install_ setPackages:packages];
3524 [changes_ setPackages:packages];
3525 [manage_ setPackages:packages];
3526 [search_ setPackages:packages];
3528 if (size_t count = [changes_ count]) {
3529 NSString *badge([[NSNumber numberWithInt:count] stringValue]);
3530 [buttonbar_ setBadgeValue:badge forButton:3];
3531 if ([buttonbar_ respondsToSelector:@selector(setBadgeAnimated:forButton:)])
3532 [buttonbar_ setBadgeAnimated:YES forButton:3];
3533 [self setApplicationBadge:badge];
3535 [buttonbar_ setBadgeValue:nil forButton:3];
3536 if ([buttonbar_ respondsToSelector:@selector(setBadgeAnimated:forButton:)])
3537 [buttonbar_ setBadgeAnimated:NO forButton:3];
3538 [self removeApplicationBadge];
3541 _assert([Metadata_ writeToFile:@"/var/lib/cydia/metadata.plist" atomically:YES] == YES);
3544 - (void) setPrompt {
3545 [navbar_ setPrompt:[NSString stringWithFormat:@"Last Updated: %@", GetLastUpdate()]];
3549 pkgProblemResolver *resolver = [database_ resolver];
3551 resolver->InstallProtect();
3552 if (!resolver->Resolve(true))
3557 [database_ prepare];
3559 if ([database_ cache]->BrokenCount() == 0)
3560 confirm_ = [[ConfirmationView alloc] initWithView:underlay_ database:database_ delegate:self];
3562 NSMutableArray *broken = [NSMutableArray arrayWithCapacity:16];
3563 NSArray *packages = [database_ packages];
3565 for (size_t i(0); i != [packages count]; ++i) {
3566 Package *package = [packages objectAtIndex:i];
3567 if ([package broken])
3568 [broken addObject:[package name]];
3571 UIAlertSheet *sheet = [[[UIAlertSheet alloc]
3572 initWithTitle:[NSString stringWithFormat:@"%d Broken Packages", [database_ cache]->BrokenCount()]
3573 buttons:[NSArray arrayWithObjects:@"Okay", nil]
3574 defaultButtonIndex:0
3579 [sheet setBodyText:[NSString stringWithFormat:@"The following packages have unmet dependencies:\n\n%@", [broken componentsJoinedByString:@"\n"]]];
3580 [sheet popupAlertAnimated:YES];
3582 [self reloadData:NO];
3587 [database_ upgrade];
3592 [self reloadData:NO];
3598 [overlay_ removeFromSuperview];
3602 detachNewThreadSelector:@selector(perform)
3609 - (void) bootstrap_ {
3611 [database_ upgrade];
3612 [database_ prepare];
3613 [database_ perform];
3616 - (void) bootstrap {
3618 detachNewThreadSelector:@selector(bootstrap_)
3621 title:@"Bootstrap Install..."
3627 detachNewThreadSelector:@selector(update)
3630 title:@"Refreshing Sources..."
3634 - (void) progressViewIsComplete:(ProgressView *)progress {
3635 [self reloadData:YES];
3637 if (confirm_ != nil) {
3638 [underlay_ addSubview:overlay_];
3639 [confirm_ removeFromSuperview];
3645 - (void) navigationBar:(UINavigationBar *)navbar buttonClicked:(int)button {
3652 UIAlertSheet *sheet = [[[UIAlertSheet alloc]
3653 initWithTitle:@"About Cydia Packager"
3654 buttons:[NSArray arrayWithObjects:@"Close", nil]
3655 defaultButtonIndex:0
3661 @"Copyright (C) 2008\n"
3662 "Jay Freeman (saurik)\n"
3663 "saurik@saurik.com\n"
3664 "http://www.saurik.com/\n"
3667 "http://www.theokorigroup.com/\n"
3669 "College of Creative Studies,\n"
3670 "University of California,\n"
3672 "http://www.ccs.ucsb.edu/\n"
3675 "bad_, BHSPitMonkey, cash, Cobra,\n"
3676 "core, Corona, crashx, cromas,\n"
3677 "Darken, dtzWill, Erica, francis,\n"
3678 "Godores, jerry, Kingstone, lounger,\n"
3679 "mbranes, rockabilly, tman, Wbiggs"
3682 [sheet presentSheetFromButtonBar:buttonbar_];
3687 - (void) alertSheet:(UIAlertSheet *)sheet buttonClicked:(int)button {
3691 - (void) buttonBarItemTapped:(id)sender {
3693 unsigned tag = [sender tag];
3696 case 1: view = featured_; break;
3697 case 2: view = install_; break;
3698 case 3: view = changes_; break;
3699 case 4: view = manage_; break;
3700 case 5: view = search_; break;
3706 if ([view respondsToSelector:@selector(resetView:)])
3707 [(id) view resetView:(tag == tag_ ? NO : YES)];
3709 [transition_ transition:0 toView:view];
3712 - (void) view:(UIView *)sender didSetFrame:(CGRect)frame oldFrame:(CGRect)old {
3713 [scroller_ setContentSize:frame.size];
3714 [indicator_ stopAnimation];
3717 - (void) webView:(WebView *)sender didReceiveTitle:(NSString *)title forFrame:(WebFrame *)frame {
3718 [navbar_ setPrompt:title];
3721 - (void) webView:(WebView *)sender didStartProvisionalLoadForFrame:(WebFrame *)frame {
3722 [navbar_ setPrompt:@"Loading..."];
3723 [indicator_ startAnimation];
3726 - (void) applicationWillSuspend {
3728 if (FW_LEAST(1,1,3))
3729 notify_post("com.apple.language.changed");
3731 system("launchctl stop com.apple.SpringBoard");
3733 [super applicationWillSuspend];
3736 - (void) applicationDidFinishLaunching:(id)unused {
3737 _assert(pkgInitConfig(*_config));
3738 _assert(pkgInitSystem(*_config, _system));
3744 CGRect screenrect = [UIHardware fullScreenApplicationContentRect];
3745 window_ = [[UIWindow alloc] initWithContentRect:screenrect];
3747 [window_ orderFront: self];
3748 [window_ makeKey: self];
3749 [window_ _setHidden: NO];
3751 progress_ = [[ProgressView alloc] initWithFrame:[window_ bounds] delegate:self];
3752 [window_ setContentView:progress_];
3754 underlay_ = [[UIView alloc] initWithFrame:[progress_ bounds]];
3755 [progress_ setContentView:underlay_];
3757 overlay_ = [[UIView alloc] initWithFrame:[underlay_ bounds]];
3760 [underlay_ addSubview:overlay_];
3762 transition_ = [[UITransitionView alloc] initWithFrame:CGRectMake(
3763 0, 0, screenrect.size.width, screenrect.size.height - 48
3766 [overlay_ addSubview:transition_];
3768 featured_ = [[UIView alloc] initWithFrame:[transition_ bounds]];
3770 CGSize navsize = [UINavigationBar defaultSizeWithPrompt];
3771 CGRect navrect = {{0, 0}, navsize};
3773 navbar_ = [[UINavigationBar alloc] initWithFrame:navrect];
3774 [featured_ addSubview:navbar_];
3776 [navbar_ setBarStyle:1];
3777 [navbar_ setDelegate:self];
3779 [navbar_ showButtonsWithLeftTitle:@"About" rightTitle:@"Reload"];
3781 UINavigationItem *navitem = [[[UINavigationItem alloc] initWithTitle:@"Featured"] autorelease];
3782 [navbar_ pushNavigationItem:navitem];
3784 struct CGRect subbounds = [featured_ bounds];
3785 subbounds.origin.y += navsize.height;
3786 subbounds.size.height -= navsize.height;
3788 UIImageView *pinstripe = [[[UIImageView alloc] initWithFrame:subbounds] autorelease];
3789 [pinstripe setImage:[UIImage applicationImageNamed:@"pinstripe.png"]];
3790 [featured_ addSubview:pinstripe];
3792 scroller_ = [[UIScroller alloc] initWithFrame:subbounds];
3793 [featured_ addSubview:scroller_];
3795 [scroller_ setScrollingEnabled:YES];
3796 [scroller_ setAdjustForContentSizeChange:YES];
3797 [scroller_ setClipsSubviews:YES];
3798 [scroller_ setAllowsRubberBanding:YES];
3799 [scroller_ setScrollDecelerationFactor:0.99];
3800 [scroller_ setDelegate:self];
3802 CGRect webrect = [scroller_ bounds];
3803 webrect.size.height = 0;
3805 webview_ = [[UIWebView alloc] initWithFrame:webrect];
3806 [scroller_ addSubview:webview_];
3808 [webview_ setTilingEnabled:YES];
3809 [webview_ setTileSize:CGSizeMake(screenrect.size.width, 500)];
3810 [webview_ setAutoresizes:YES];
3811 [webview_ setDelegate:self];
3813 CGSize indsize = [UIProgressIndicator defaultSizeForStyle:2];
3814 indicator_ = [[UIProgressIndicator alloc] initWithFrame:CGRectMake(87, 45, indsize.width, indsize.height)];
3815 [indicator_ setStyle:2];
3816 [featured_ addSubview:indicator_];
3818 NSArray *buttonitems = [NSArray arrayWithObjects:
3819 [NSDictionary dictionaryWithObjectsAndKeys:
3820 @"buttonBarItemTapped:", kUIButtonBarButtonAction,
3821 @"featured-up.png", kUIButtonBarButtonInfo,
3822 @"featured-dn.png", kUIButtonBarButtonSelectedInfo,
3823 [NSNumber numberWithInt:1], kUIButtonBarButtonTag,
3824 self, kUIButtonBarButtonTarget,
3825 @"Featured", kUIButtonBarButtonTitle,
3826 @"0", kUIButtonBarButtonType,
3829 [NSDictionary dictionaryWithObjectsAndKeys:
3830 @"buttonBarItemTapped:", kUIButtonBarButtonAction,
3831 @"install-up.png", kUIButtonBarButtonInfo,
3832 @"install-dn.png", kUIButtonBarButtonSelectedInfo,
3833 [NSNumber numberWithInt:2], kUIButtonBarButtonTag,
3834 self, kUIButtonBarButtonTarget,
3835 @"Install", kUIButtonBarButtonTitle,
3836 @"0", kUIButtonBarButtonType,
3839 [NSDictionary dictionaryWithObjectsAndKeys:
3840 @"buttonBarItemTapped:", kUIButtonBarButtonAction,
3841 @"changes-up.png", kUIButtonBarButtonInfo,
3842 @"changes-dn.png", kUIButtonBarButtonSelectedInfo,
3843 [NSNumber numberWithInt:3], kUIButtonBarButtonTag,
3844 self, kUIButtonBarButtonTarget,
3845 @"Changes", kUIButtonBarButtonTitle,
3846 @"0", kUIButtonBarButtonType,
3849 [NSDictionary dictionaryWithObjectsAndKeys:
3850 @"buttonBarItemTapped:", kUIButtonBarButtonAction,
3851 @"manage-up.png", kUIButtonBarButtonInfo,
3852 @"manage-dn.png", kUIButtonBarButtonSelectedInfo,
3853 [NSNumber numberWithInt:4], kUIButtonBarButtonTag,
3854 self, kUIButtonBarButtonTarget,
3855 @"Uninstall", kUIButtonBarButtonTitle,
3856 @"0", kUIButtonBarButtonType,
3859 [NSDictionary dictionaryWithObjectsAndKeys:
3860 @"buttonBarItemTapped:", kUIButtonBarButtonAction,
3861 @"search-up.png", kUIButtonBarButtonInfo,
3862 @"search-dn.png", kUIButtonBarButtonSelectedInfo,
3863 [NSNumber numberWithInt:5], kUIButtonBarButtonTag,
3864 self, kUIButtonBarButtonTarget,
3865 @"Search", kUIButtonBarButtonTitle,
3866 @"0", kUIButtonBarButtonType,
3870 buttonbar_ = [[UIButtonBar alloc]
3872 withFrame:CGRectMake(
3873 0, screenrect.size.height - 48,
3874 screenrect.size.width, 48
3876 withItemList:buttonitems
3879 [buttonbar_ setDelegate:self];
3880 [buttonbar_ setBarStyle:1];
3881 [buttonbar_ setButtonBarTrackingMode:2];
3883 int buttons[5] = {1, 2, 3, 4, 5};
3884 [buttonbar_ registerButtonGroup:0 withButtons:buttons withCount:5];
3885 [buttonbar_ showButtonGroup:0 withDuration:0];
3887 for (int i = 0; i != 5; ++i)
3888 [[buttonbar_ viewWithTag:(i + 1)] setFrame:CGRectMake(
3889 i * 64 + 2, 1, 60, 48
3892 [buttonbar_ showSelectionForButton:1];
3893 [transition_ transition:0 toView:featured_];
3895 [overlay_ addSubview:buttonbar_];
3897 [UIKeyboard initImplementationNow];
3899 CGRect edtrect = [overlay_ bounds];
3900 edtrect.origin.y += navsize.height;
3901 edtrect.size.height -= navsize.height;
3903 CGSize keysize = [UIKeyboard defaultSize];
3904 CGRect keyrect = {{0, [overlay_ bounds].size.height - keysize.height}, keysize};
3905 keyboard_ = [[UIKeyboard alloc] initWithFrame:keyrect];
3907 database_ = [[Database alloc] init];
3908 [database_ setDelegate:progress_];
3910 install_ = [[InstallView alloc] initWithFrame:[transition_ bounds]];
3911 [install_ setDelegate:self];
3913 changes_ = [[ChangesView alloc] initWithFrame:[transition_ bounds]];
3914 [changes_ setDelegate:self];
3916 manage_ = [[ManageView alloc] initWithFrame:[transition_ bounds]];
3917 [manage_ setDelegate:self];
3919 search_ = [[SearchView alloc] initWithFrame:[transition_ bounds]];
3920 [search_ setDelegate:self];
3922 [self reloadData:NO];
3924 Package *package([database_ packageWithName:@"cydia"]);
3925 NSString *application = package == nil ? @"Cydia" : [NSString
3926 stringWithFormat:@"Cydia/%@",
3930 WebView *webview = [webview_ webView];
3931 [webview setApplicationNameForUserAgent:application];
3932 [webview setFrameLoadDelegate:self];
3934 url_ = [NSURL URLWithString:@"http://cydia.saurik.com/"];
3937 [progress_ resetView];
3943 - (void) showKeyboard:(BOOL)show {
3945 [overlay_ addSubview:keyboard_];
3947 [keyboard_ removeFromSuperview];
3952 void AddPreferences(NSString *plist) {
3953 NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init];
3955 NSMutableDictionary *settings = [[[NSMutableDictionary alloc] initWithContentsOfFile:plist] autorelease];
3956 _assert(settings != NULL);
3957 NSMutableArray *items = [settings objectForKey:@"items"];
3961 for (size_t i(0); i != [items count]; ++i) {
3962 NSMutableDictionary *item([items objectAtIndex:i]);
3963 NSString *label = [item objectForKey:@"label"];
3964 if (label != nil && [label isEqualToString:@"Cydia"]) {
3971 for (size_t i(0); i != [items count]; ++i) {
3972 NSDictionary *item([items objectAtIndex:i]);
3973 NSString *label = [item objectForKey:@"label"];
3974 if (label != nil && [label isEqualToString:@"General"]) {
3975 [items insertObject:[NSDictionary dictionaryWithObjectsAndKeys:
3976 @"CydiaSettings", @"bundle",
3977 @"PSLinkCell", @"cell",
3978 [NSNumber numberWithBool:YES], @"hasIcon",
3979 [NSNumber numberWithBool:YES], @"isController",
3981 nil] atIndex:(i + 1)];
3987 _assert([settings writeToFile:plist atomically:YES] == YES);
3994 id Alloc_(id self, SEL selector) {
3995 id object = alloc_(self, selector);
3996 fprintf(stderr, "[%s]A-%p\n", self->isa->name, object);
4000 int main(int argc, char *argv[]) {
4002 memset(nl, 0, sizeof(nl));
4003 nl[0].n_un.n_name = "_useMDNSResponder";
4004 nlist("/usr/lib/libc.dylib", nl);
4005 if (nl[0].n_type != N_UNDF)
4006 *(int *) nl[0].n_value = 0;
4008 bootstrap_ = argc > 1 && strcmp(argv[1], "--bootstrap") == 0;
4013 /*Method alloc = class_getClassMethod([NSObject class], @selector(alloc));
4014 alloc_ = alloc->method_imp;
4015 alloc->method_imp = (IMP) &Alloc_;*/
4017 NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init];
4019 if (NSDictionary *sysver = [NSDictionary dictionaryWithContentsOfFile:@"/System/Library/CoreServices/SystemVersion.plist"]) {
4020 if (NSString *prover = [sysver valueForKey:@"ProductVersion"]) {
4021 Firmware_ = strdup([prover cString]);
4022 NSArray *versions = [prover componentsSeparatedByString:@"."];
4023 int count = [versions count];
4024 Major_ = count > 0 ? [[versions objectAtIndex:0] intValue] : 0;
4025 Minor_ = count > 1 ? [[versions objectAtIndex:1] intValue] : 0;
4026 BugFix_ = count > 2 ? [[versions objectAtIndex:2] intValue] : 0;
4031 sysctlbyname("hw.machine", NULL, &size, NULL, 0);
4032 char *machine = new char[size];
4033 sysctlbyname("hw.machine", machine, &size, NULL, 0);
4036 if (CFMutableDictionaryRef dict = IOServiceMatching("IOPlatformExpertDevice"))
4037 if (io_service_t service = IOServiceGetMatchingService(kIOMasterPortDefault, dict)) {
4038 if (CFTypeRef serial = IORegistryEntryCreateCFProperty(service, CFSTR(kIOPlatformSerialNumberKey), kCFAllocatorDefault, 0)) {
4039 SerialNumber_ = strdup(CFStringGetCStringPtr((CFStringRef) serial, CFStringGetSystemEncoding()));
4043 IOObjectRelease(service);
4046 /*AddPreferences(@"/Applications/Preferences.app/Settings-iPhone.plist");
4047 AddPreferences(@"/Applications/Preferences.app/Settings-iPod.plist");*/
4049 if ((Metadata_ = [[NSMutableDictionary alloc] initWithContentsOfFile:@"/var/lib/cydia/metadata.plist"]) == NULL)
4050 Metadata_ = [[NSMutableDictionary alloc] initWithCapacity:2];
4052 Packages_ = [Metadata_ objectForKey:@"Packages"];
4054 setenv("CYDIA", "", _not(int));
4055 if (access("/User", F_OK) != 0)
4056 system("/usr/libexec/cydia/firmware.sh");
4057 system("dpkg --configure -a");
4059 UIApplicationMain(argc, argv, [Cydia class]);