1 /* #include Directives {{{ */
2 #include <Foundation/NSURL.h>
3 #include <UIKit/UIKit.h>
4 #import <GraphicsServices/GraphicsServices.h>
7 #include <ext/stdio_filebuf.h>
9 #include <apt-pkg/acquire.h>
10 #include <apt-pkg/acquire-item.h>
11 #include <apt-pkg/algorithms.h>
12 #include <apt-pkg/cachefile.h>
13 #include <apt-pkg/configuration.h>
14 #include <apt-pkg/debmetaindex.h>
15 #include <apt-pkg/error.h>
16 #include <apt-pkg/init.h>
17 #include <apt-pkg/pkgrecords.h>
18 #include <apt-pkg/sourcelist.h>
19 #include <apt-pkg/sptr.h>
21 #include <sys/sysctl.h>
27 /* Extension Keywords {{{ */
28 #define _trace() fprintf(stderr, "_trace()@%s:%u[%s]\n", __FILE__, __LINE__, __FUNCTION__)
30 #define _assert(test) do \
32 fprintf(stderr, "_assert(%d:%s)@%s:%u[%s]\n", errno, #test, __FILE__, __LINE__, __FUNCTION__); \
39 - (void) setApplicationNameForUserAgent:(NSString *)applicationName;
42 static const int PulseInterval_ = 50000;
43 const char *Machine_ = NULL;
44 const char *SerialNumber_ = NULL;
46 @interface NSString (CydiaBypass)
47 - (NSString *) stringByAddingPercentEscapes;
50 @protocol ProgressDelegate
51 - (void) setError:(NSString *)error;
52 - (void) setTitle:(NSString *)title;
53 - (void) setPercent:(float)percent;
54 - (void) addOutput:(NSString *)output;
57 NSString *SizeString(double size) {
64 static const char *powers_[] = {"B", "kB", "MB", "GB"};
66 return [NSString stringWithFormat:@"%.1f%s", size, powers_[power]];
69 /* Status Delegation {{{ */
71 public pkgAcquireStatus
82 void setDelegate(id delegate) {
86 virtual bool MediaChange(std::string media, std::string drive) {
90 virtual void IMSHit(pkgAcquire::ItemDesc &item) {
93 virtual void Fetch(pkgAcquire::ItemDesc &item) {
94 [delegate_ setTitle:[NSString stringWithCString:("Downloading " + item.ShortDesc).c_str()]];
97 virtual void Done(pkgAcquire::ItemDesc &item) {
100 virtual void Fail(pkgAcquire::ItemDesc &item) {
101 [delegate_ performSelectorOnMainThread:@selector(setStatusFail) withObject:nil waitUntilDone:YES];
104 virtual bool Pulse(pkgAcquire *Owner) {
105 bool value = pkgAcquireStatus::Pulse(Owner);
108 double(CurrentBytes + CurrentItems) /
109 double(TotalBytes + TotalItems)
112 [delegate_ setPercent:percent];
116 virtual void Start() {
119 virtual void Stop() {
123 /* Progress Delegation {{{ */
131 virtual void Update() {
132 [delegate_ setTitle:[NSString stringWithCString:Op.c_str()]];
133 [delegate_ setPercent:(Percent / 100)];
142 void setDelegate(id delegate) {
143 delegate_ = delegate;
146 virtual void Done() {
147 [delegate_ setPercent:1];
152 /* External Constants {{{ */
153 extern NSString *kUIButtonBarButtonAction;
154 extern NSString *kUIButtonBarButtonInfo;
155 extern NSString *kUIButtonBarButtonInfoOffset;
156 extern NSString *kUIButtonBarButtonSelectedInfo;
157 extern NSString *kUIButtonBarButtonStyle;
158 extern NSString *kUIButtonBarButtonTag;
159 extern NSString *kUIButtonBarButtonTarget;
160 extern NSString *kUIButtonBarButtonTitle;
161 extern NSString *kUIButtonBarButtonTitleVerticalHeight;
162 extern NSString *kUIButtonBarButtonTitleWidth;
163 extern NSString *kUIButtonBarButtonType;
165 /* Mime Addresses {{{ */
166 @interface Address : NSObject {
174 - (NSString *) email;
176 + (Address *) addressWithString:(NSString *)string;
177 - (Address *) initWithString:(NSString *)string;
180 @implementation Address
189 - (NSString *) name {
193 - (NSString *) email {
197 + (Address *) addressWithString:(NSString *)string {
198 return [[[Address alloc] initWithString:string] autorelease];
201 - (Address *) initWithString:(NSString *)string {
202 if ((self = [super init]) != nil) {
205 pcre *code = pcre_compile("^\"?(.*)\"? <([^>]*)>$", 0, &error, &offset, NULL);
208 fprintf(stderr, "%d:%s\n", offset, error);
212 pcre_extra *study = NULL;
214 pcre_fullinfo(code, study, PCRE_INFO_CAPTURECOUNT, &capture);
215 int matches[(capture + 1) * 3];
217 size_t size = [string length];
218 const char *data = [string UTF8String];
220 if (pcre_exec(code, study, data, size, 0, 0, matches, sizeof(matches) / sizeof(matches[0])) >= 0) {
221 name_ = [[NSString stringWithCString:(data + matches[2]) length:(matches[3] - matches[2])] retain];
222 email_ = [[NSString stringWithCString:(data + matches[4]) length:(matches[5] - matches[4])] retain];
224 name_ = [[NSString stringWithCString:data length:size] retain];
233 /* Right Alignment {{{ */
234 @interface UIRightTextLabel : UITextLabel {
235 float _savedRightEdgeX;
236 BOOL _sizedtofit_flag;
239 - (void) setFrame:(CGRect)frame;
240 - (void) setText:(NSString *)text;
241 - (void) realignText;
244 @implementation UIRightTextLabel
246 - (void) setFrame:(CGRect)frame {
247 [super setFrame:frame];
248 if (_sizedtofit_flag == NO) {
249 _savedRightEdgeX = frame.origin.x;
254 - (void) setText:(NSString *)text {
255 [super setText:text];
259 - (void) realignText {
260 CGRect oldFrame = [self frame];
262 _sizedtofit_flag = YES;
263 [self sizeToFit]; // shrink down size so I can right align it
265 CGRect newFrame = [self frame];
267 oldFrame.origin.x = _savedRightEdgeX - newFrame.size.width;
268 oldFrame.size.width = newFrame.size.width;
269 [super setFrame:oldFrame];
270 _sizedtofit_flag = NO;
275 /* Linear Algebra {{{ */
276 inline float interpolate(float begin, float end, float fraction) {
277 return (end - begin) * fraction + begin;
282 @interface ResetView : UIView {
283 UINavigationBar *navbar_;
287 - (void) navigationBar:(UINavigationBar *)navbar poppedItem:(UINavigationItem *)item;
292 - (NSString *) leftTitle;
293 - (NSString *) rightTitle;
296 @implementation ResetView
298 - (void) navigationBar:(UINavigationBar *)navbar poppedItem:(UINavigationItem *)item {
299 if ([[navbar_ navigationItems] count] == 1)
310 if ([[navbar_ navigationItems] count] == 1)
312 else while ([[navbar_ navigationItems] count] != 1)
313 [navbar_ popNavigationItem];
317 - (void) _resetView {
318 [navbar_ showButtonsWithLeftTitle:[self leftTitle] rightTitle:[self rightTitle]];
321 - (NSString *) leftTitle {
325 - (NSString *) rightTitle {
334 @interface Database : NSObject {
336 pkgRecords *records_;
337 pkgProblemResolver *resolver_;
338 pkgAcquire *fetcher_;
340 SPtr<pkgPackageManager> manager_;
348 - (void) _readStatus:(NSNumber *)fd;
349 - (void) _readOutput:(NSNumber *)fd;
351 - (Package *) packageWithName:(NSString *)name;
354 - (pkgCacheFile &) cache;
355 - (pkgRecords *) records;
356 - (pkgProblemResolver *) resolver;
357 - (pkgAcquire &) fetcher;
365 - (void) setDelegate:(id)delegate;
368 /* Package Class {{{ */
369 @interface Package : NSObject {
370 pkgCache::PkgIterator iterator_;
372 pkgRecords::Parser *parser_;
373 pkgCache::VerIterator version_;
374 pkgCache::VerFileIterator file_;
377 - (Package *) initWithIterator:(pkgCache::PkgIterator)iterator database:(Database *)database version:(pkgCache::VerIterator)version file:(pkgCache::VerFileIterator)file;
378 + (Package *) packageWithIterator:(pkgCache::PkgIterator)iterator database:(Database *)database;
381 - (NSString *) section;
382 - (NSString *) latest;
383 - (NSString *) installed;
384 - (Address *) maintainer;
386 - (NSString *) tagline;
387 - (NSString *) description;
388 - (NSComparisonResult) compareBySectionAndName:(Package *)package;
394 @implementation Package
396 - (Package *) initWithIterator:(pkgCache::PkgIterator)iterator database:(Database *)database version:(pkgCache::VerIterator)version file:(pkgCache::VerFileIterator)file {
397 if ((self = [super init]) != nil) {
398 iterator_ = iterator;
399 database_ = database;
403 parser_ = &[database_ records]->Lookup(file);
407 + (Package *) packageWithIterator:(pkgCache::PkgIterator)iterator database:(Database *)database {
408 for (pkgCache::VerIterator version = iterator.VersionList(); !version.end(); ++version)
409 for (pkgCache::VerFileIterator file = version.FileList(); !file.end(); ++file)
410 return [[[Package alloc]
411 initWithIterator:iterator
419 - (NSString *) name {
420 return [[NSString stringWithCString:iterator_.Name()] lowercaseString];
423 - (NSString *) section {
424 return [NSString stringWithCString:iterator_.Section()];
427 - (NSString *) latest {
428 return [NSString stringWithCString:version_.VerStr()];
431 - (NSString *) installed {
432 return iterator_.CurrentVer().end() ? nil : [NSString stringWithCString:iterator_.CurrentVer().VerStr()];
435 - (Address *) maintainer {
436 return [Address addressWithString:[NSString stringWithCString:parser_->Maintainer().c_str()]];
440 return version_->InstalledSize;
443 - (NSString *) tagline {
444 return [NSString stringWithCString:parser_->ShortDesc().c_str()];
447 - (NSString *) description {
448 return [NSString stringWithCString:parser_->LongDesc().c_str()];
451 - (NSComparisonResult) compareBySectionAndName:(Package *)package {
452 NSComparisonResult result = [[self section] compare:[package section]];
453 if (result != NSOrderedSame)
455 return [[self name] compare:[package name]];
459 pkgProblemResolver *resolver = [database_ resolver];
460 resolver->Clear(iterator_);
461 resolver->Protect(iterator_);
462 [database_ cache]->MarkInstall(iterator_, false);
466 pkgProblemResolver *resolver = [database_ resolver];
467 resolver->Clear(iterator_);
468 resolver->Protect(iterator_);
469 resolver->Remove(iterator_);
470 [database_ cache]->MarkDelete(iterator_, true);
475 /* Section Class {{{ */
476 @interface Section : NSObject {
479 NSMutableArray *packages_;
484 - (Section *) initWithName:(NSString *)name row:(size_t)row;
487 - (void) addPackage:(Package *)package;
490 @implementation Section
498 - (Section *) initWithName:(NSString *)name row:(size_t)row {
499 if ((self = [super init]) != nil) {
500 name_ = [name retain];
502 packages_ = [[NSMutableArray arrayWithCapacity:16] retain];
506 - (NSString *) name {
514 - (void) addPackage:(Package *)package {
515 [packages_ addObject:package];
521 /* Confirmation View {{{ */
522 void AddTextView(NSMutableDictionary *fields, NSMutableArray *packages, NSString *key) {
523 if ([packages count] == 0)
526 CGColorSpaceRef space = CGColorSpaceCreateDeviceRGB();
527 float clear[] = {0, 0, 0, 0};
528 float blue[] = {0, 0, 0.4, 1};
530 UITextView *text([[[UITextView alloc] initWithFrame: CGRectMake(110, 3, 200, 60)] autorelease]);
531 [text setEditable:NO];
532 [text setTextSize:16];
533 [text setBackgroundColor:CGColorCreate(space, clear)];
534 [text setTextColor:CGColorCreate(space, blue)];
535 [text setText:([packages count] == 0 ? @"n/a" : [packages componentsJoinedByString:@", "])];
536 [text setEnabled:NO];
538 CGRect frame([text frame]);
539 CGSize size([text contentSize]);
540 frame.size.height = size.height;
541 [text setFrame:frame];
543 [fields setObject:text forKey:key];
546 @protocol ConfirmationViewDelegate
551 @interface ConfirmationView : UIView {
554 UITransitionView *transition_;
556 UINavigationBar *navbar_;
557 UIPreferencesTable *table_;
558 NSMutableDictionary *fields_;
559 UIAlertSheet *essential_;
565 - (void) transitionViewDidComplete:(UITransitionView*)view fromView:(UIView*)from toView:(UIView*)to;
566 - (void) navigationBar:(UINavigationBar *)navbar buttonClicked:(int)button;
567 - (void) alertSheet:(UIAlertSheet *)sheet buttonClicked:(int)button;
569 - (int) numberOfGroupsInPreferencesTable:(UIPreferencesTable *)table;
570 - (NSString *) preferencesTable:(UIPreferencesTable *)table titleForGroup:(int)group;
571 - (float) preferencesTable:(UIPreferencesTable *)table heightForRow:(int)row inGroup:(int)group withProposedHeight:(float)proposed;
572 - (int) preferencesTable:(UIPreferencesTable *)table numberOfRowsInGroup:(int)group;
573 - (UIPreferencesTableCell *) preferencesTable:(UIPreferencesTable *)table cellForRow:(int)row inGroup:(int)group;
575 - (id) initWithView:(UIView *)view database:(Database *)database delegate:(id)delegate;
579 @implementation ConfirmationView
582 [transition_ release];
587 if (essential_ != nil)
588 [essential_ release];
593 [transition_ transition:7 toView:nil];
597 - (void) transitionViewDidComplete:(UITransitionView*)view fromView:(UIView*)from toView:(UIView*)to {
598 if (from != nil && to == nil)
599 [self removeFromSuperview];
602 - (void) navigationBar:(UINavigationBar *)navbar buttonClicked:(int)button {
605 if (essential_ != nil)
606 [essential_ popupAlertAnimated:YES];
617 - (void) alertSheet:(UIAlertSheet *)sheet buttonClicked:(int)button {
618 [essential_ dismiss];
622 - (int) numberOfGroupsInPreferencesTable:(UIPreferencesTable *)table {
626 - (NSString *) preferencesTable:(UIPreferencesTable *)table titleForGroup:(int)group {
628 case 0: return @"Statistics";
629 case 1: return @"Modifications";
631 default: _assert(false);
635 - (int) preferencesTable:(UIPreferencesTable *)table numberOfRowsInGroup:(int)group {
638 case 1: return [fields_ count];
640 default: _assert(false);
644 - (float) preferencesTable:(UIPreferencesTable *)table heightForRow:(int)row inGroup:(int)group withProposedHeight:(float)proposed {
645 if (group != 1 || row == -1)
648 _assert(size_t(row) < [fields_ count]);
649 fprintf(stderr, "%f\n", [[[fields_ allValues] objectAtIndex:row] contentSize].height);
650 return [[[fields_ allValues] objectAtIndex:row] contentSize].height;
654 - (UIPreferencesTableCell *) preferencesTable:(UIPreferencesTable *)table cellForRow:(int)row inGroup:(int)group {
655 UIPreferencesTableCell *cell = [[[UIPreferencesTableCell alloc] init] autorelease];
656 [cell setShowSelection:NO];
659 case 0: switch (row) {
661 [cell setTitle:@"Downloading"];
662 [cell setValue:SizeString([database_ fetcher].FetchNeeded())];
666 [cell setTitle:@"Resuming At"];
667 [cell setValue:SizeString([database_ fetcher].PartialPresent())];
671 double size([database_ cache]->UsrSize());
674 [cell setTitle:@"Disk Freeing"];
675 [cell setValue:SizeString(-size)];
677 [cell setTitle:@"Disk Using"];
678 [cell setValue:SizeString(size)];
682 default: _assert(false);
686 _assert(size_t(row) < [fields_ count]);
687 [cell setTitle:[[fields_ allKeys] objectAtIndex:row]];
688 [cell addSubview:[[fields_ allValues] objectAtIndex:row]];
691 default: _assert(false);
697 - (id) initWithView:(UIView *)view database:(Database *)database delegate:(id)delegate {
698 if ((self = [super initWithFrame:[view bounds]]) != nil) {
699 database_ = database;
700 delegate_ = delegate;
702 transition_ = [[UITransitionView alloc] initWithFrame:[self bounds]];
703 [self addSubview:transition_];
705 overlay_ = [[UIView alloc] initWithFrame:[transition_ bounds]];
707 CGSize navsize = [UINavigationBar defaultSize];
708 CGRect navrect = {{0, 0}, navsize};
709 CGRect bounds = [overlay_ bounds];
711 navbar_ = [[UINavigationBar alloc] initWithFrame:navrect];
712 [navbar_ setBarStyle:1];
713 [navbar_ setDelegate:self];
715 UINavigationItem *navitem = [[[UINavigationItem alloc] initWithTitle:@"Confirm"] autorelease];
716 [navbar_ pushNavigationItem:navitem];
717 [navbar_ showButtonsWithLeftTitle:@"Cancel" rightTitle:@"Confirm"];
719 fields_ = [[NSMutableDictionary dictionaryWithCapacity:16] retain];
721 NSMutableArray *installing = [NSMutableArray arrayWithCapacity:16];
722 NSMutableArray *upgrading = [NSMutableArray arrayWithCapacity:16];
723 NSMutableArray *removing = [NSMutableArray arrayWithCapacity:16];
725 bool essential(false);
727 pkgCacheFile &cache([database_ cache]);
728 for (pkgCache::PkgIterator iterator = cache->PkgBegin(); !iterator.end(); ++iterator) {
729 NSString *name([NSString stringWithCString:iterator.Name()]);
730 if (cache[iterator].NewInstall())
731 [installing addObject:name];
732 else if (cache[iterator].Upgrade())
733 [upgrading addObject:name];
734 else if (cache[iterator].Delete()) {
735 [removing addObject:name];
736 if ((iterator->Flags & pkgCache::Flag::Essential) != 0)
744 essential_ = [[UIAlertSheet alloc]
745 initWithTitle:@"Unable to Comply"
746 buttons:[NSArray arrayWithObjects:@"Okay", nil]
752 [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."];
755 AddTextView(fields_, installing, @"Installing");
756 AddTextView(fields_, upgrading, @"Upgrading");
757 AddTextView(fields_, removing, @"Removing");
759 table_ = [[UIPreferencesTable alloc] initWithFrame:CGRectMake(
760 0, navsize.height, bounds.size.width, bounds.size.height - navsize.height
763 [table_ setReusesTableCells:YES];
764 [table_ setDataSource:self];
767 [overlay_ addSubview:navbar_];
768 [overlay_ addSubview:table_];
770 [view addSubview:self];
772 [transition_ setDelegate:self];
774 UIView *blank = [[[UIView alloc] initWithFrame:[transition_ bounds]] autorelease];
775 [transition_ transition:0 toView:blank];
776 [transition_ transition:3 toView:overlay_];
782 /* Package View {{{ */
783 @interface PackageView : UIView {
784 UIPreferencesTable *table_;
787 NSMutableArray *cells_;
793 - (int) numberOfGroupsInPreferencesTable:(UIPreferencesTable *)table;
794 - (NSString *) preferencesTable:(UIPreferencesTable *)table titleForGroup:(int)group;
795 - (int) preferencesTable:(UIPreferencesTable *)table numberOfRowsInGroup:(int)group;
796 - (UIPreferencesTableCell *) preferencesTable:(UIPreferencesTable *)table cellForRow:(int)row inGroup:(int)group;
798 - (BOOL) canSelectRow:(int)row;
799 - (void) tableRowSelected:(NSNotification *)notification;
801 - (id) initWithFrame:(struct CGRect)frame database:(Database *)database;
802 - (void) setPackage:(Package *)package;
803 - (void) setDelegate:(id)delegate;
806 @implementation PackageView
817 - (int) numberOfGroupsInPreferencesTable:(UIPreferencesTable *)table {
821 - (NSString *) preferencesTable:(UIPreferencesTable *)table titleForGroup:(int)group {
823 case 0: return @"Specifics";
824 case 1: return @"Description";
826 default: _assert(false);
830 - (int) preferencesTable:(UIPreferencesTable *)table numberOfRowsInGroup:(int)group {
835 default: _assert(false);
839 - (UIPreferencesTableCell *) preferencesTable:(UIPreferencesTable *)table cellForRow:(int)row inGroup:(int)group {
840 UIPreferencesTableCell *cell;
843 case 0: switch (row) {
845 cell = [cells_ objectAtIndex:0];
846 [cell setTitle:@"Name"];
847 [cell setValue:[package_ name]];
851 cell = [cells_ objectAtIndex:1];
852 [cell setTitle:@"Installed"];
853 NSString *installed([package_ installed]);
854 [cell setValue:(installed == nil ? @"n/a" : installed)];
858 cell = [cells_ objectAtIndex:2];
859 [cell setTitle:@"Latest"];
860 [cell setValue:[package_ latest]];
864 cell = [cells_ objectAtIndex:3];
865 [cell setTitle:@"Section"];
866 [cell setValue:[package_ section]];
870 cell = [cells_ objectAtIndex:4];
871 [cell setTitle:@"Size"];
872 [cell setValue:SizeString([package_ size])];
876 cell = [cells_ objectAtIndex:5];
877 [cell setTitle:@"Maintainer"];
878 [cell setValue:[[package_ maintainer] name]];
879 [cell setShowDisclosure:YES];
880 [cell setShowSelection:YES];
883 default: _assert(false);
886 case 1: switch (row) {
888 cell = [cells_ objectAtIndex:6];
890 [cell setValue:[package_ tagline]];
894 cell = [cells_ objectAtIndex:7];
895 [cell setTitle:@"Description"];
896 [cell setValue:[package_ description]];
900 default: _assert(false);
906 - (BOOL) canSelectRow:(int)row {
910 - (void) tableRowSelected:(NSNotification *)notification {
911 switch ([table_ selectedRow]) {
913 [delegate_ openURL:[NSURL URLWithString:[NSString stringWithFormat:@"mailto:%@?subject=%@",
914 [[package_ maintainer] email],
915 [[NSString stringWithFormat:@"regarding apt package \"%@\"", [package_ name]] stringByAddingPercentEscapes]
921 - (id) initWithFrame:(struct CGRect)frame database:(Database *)database {
922 if ((self = [super initWithFrame:frame]) != nil) {
923 database_ = [database retain];
925 table_ = [[UIPreferencesTable alloc] initWithFrame:[self bounds]];
926 [self addSubview:table_];
928 [table_ setDataSource:self];
929 [table_ setDelegate:self];
931 cells_ = [[NSMutableArray arrayWithCapacity:16] retain];
933 for (unsigned i = 0; i != 8; ++i) {
934 UIPreferencesTableCell *cell = [[[UIPreferencesTableCell alloc] init] autorelease];
935 [cell setShowSelection:NO];
936 [cells_ addObject:cell];
941 - (void) setPackage:(Package *)package {
942 package_ = [package retain];
946 - (void) setDelegate:(id)delegate {
947 delegate_ = delegate;
952 /* Package Cell {{{ */
953 @protocol PackageCellDelegate
954 - (NSString *) versionWithPackage:(Package *)package;
957 @interface PackageCell : UITableCell {
959 UIRightTextLabel *version_;
960 UITextLabel *description_;
965 - (PackageCell *) initWithPackage:(Package *)package delegate:(id)delegate;
967 - (void) _setSelected:(float)fraction;
968 - (void) setSelected:(BOOL)selected;
969 - (void) setSelected:(BOOL)selected withFade:(BOOL)fade;
970 - (void) _setSelectionFadeFraction:(float)fraction;
974 @implementation PackageCell
979 [description_ release];
983 - (PackageCell *) initWithPackage:(Package *)package delegate:(id)delegate {
984 if ((self = [super init]) != nil) {
985 GSFontRef bold = GSFontCreateWithName("Helvetica", kGSFontTraitBold, 22);
986 GSFontRef large = GSFontCreateWithName("Helvetica", kGSFontTraitNone, 16);
987 GSFontRef small = GSFontCreateWithName("Helvetica", kGSFontTraitNone, 14);
989 CGColorSpaceRef space = CGColorSpaceCreateDeviceRGB();
990 float clear[] = {0, 0, 0, 0};
992 name_ = [[UITextLabel alloc] initWithFrame:CGRectMake(12, 7, 250, 25)];
993 [name_ setText:[package name]];
994 [name_ setBackgroundColor:CGColorCreate(space, clear)];
995 [name_ setFont:bold];
997 version_ = [[UIRightTextLabel alloc] initWithFrame:CGRectMake(290, 7, 70, 25)];
998 [version_ setText:[delegate versionWithPackage:package]];
999 [version_ setBackgroundColor:CGColorCreate(space, clear)];
1000 [version_ setFont:large];
1002 description_ = [[UITextLabel alloc] initWithFrame:CGRectMake(13, 35, 315, 20)];
1003 [description_ setText:[package tagline]];
1004 [description_ setBackgroundColor:CGColorCreate(space, clear)];
1005 [description_ setFont:small];
1007 [self addSubview:name_];
1008 [self addSubview:version_];
1009 [self addSubview:description_];
1017 - (void) _setSelected:(float)fraction {
1018 CGColorSpaceRef space = CGColorSpaceCreateDeviceRGB();
1021 interpolate(0.0, 1.0, fraction),
1022 interpolate(0.0, 1.0, fraction),
1023 interpolate(0.0, 1.0, fraction),
1027 interpolate(0.2, 1.0, fraction),
1028 interpolate(0.2, 1.0, fraction),
1029 interpolate(1.0, 1.0, fraction),
1033 interpolate(0.4, 1.0, fraction),
1034 interpolate(0.4, 1.0, fraction),
1035 interpolate(0.4, 1.0, fraction),
1038 [name_ setColor:CGColorCreate(space, black)];
1039 [version_ setColor:CGColorCreate(space, blue)];
1040 [description_ setColor:CGColorCreate(space, gray)];
1043 - (void) setSelected:(BOOL)selected {
1044 [self _setSelected:(selected ? 1.0 : 0.0)];
1045 [super setSelected:selected];
1048 - (void) setSelected:(BOOL)selected withFade:(BOOL)fade {
1050 [self _setSelected:(selected ? 1.0 : 0.0)];
1051 [super setSelected:selected withFade:fade];
1054 - (void) _setSelectionFadeFraction:(float)fraction {
1055 [self _setSelected:fraction];
1056 [super _setSelectionFadeFraction:fraction];
1061 /* Sources View {{{ */
1062 @interface SourcesView : ResetView {
1063 UISectionList *list_;
1064 Database *database_;
1066 NSMutableArray *sources_;
1069 - (void) navigationBar:(UINavigationBar *)navbar buttonClicked:(int)button;
1071 - (id) initWithFrame:(CGRect)frame database:(Database *)database;
1072 - (void) setDelegate:(id)delegate;
1073 - (void) reloadData;
1074 - (NSString *) leftTitle;
1075 - (NSString *) rightTitle;
1078 @implementation SourcesView
1080 - (void) navigationBar:(UINavigationBar *)navbar buttonClicked:(int)button {
1092 if (sources_ != nil)
1098 - (id) initWithFrame:(CGRect)frame database:(Database *)database {
1099 if ((self = [super initWithFrame:frame]) != nil) {
1100 database_ = database;
1103 CGSize navsize = [UINavigationBar defaultSize];
1104 CGRect navrect = {{0, 0}, navsize};
1105 CGRect bounds = [self bounds];
1107 navbar_ = [[UINavigationBar alloc] initWithFrame:navrect];
1108 [self addSubview:navbar_];
1110 [navbar_ setBarStyle:1];
1111 [navbar_ setDelegate:self];
1113 UINavigationItem *navitem = [[[UINavigationItem alloc] initWithTitle:@"Sources"] autorelease];
1114 [navbar_ pushNavigationItem:navitem];
1116 list_ = [[UISectionList alloc] initWithFrame:CGRectMake(
1117 0, navsize.height, bounds.size.width, bounds.size.height - navsize.height
1120 [list_ setDataSource:self];
1121 //[list_ setShouldHideHeaderInShortLists:NO];
1125 - (void) setDelegate:(id)delegate {
1126 delegate_ = delegate;
1129 - (void) reloadData {
1131 _assert(list.ReadMainList());
1133 sources_ = [[NSMutableArray arrayWithCapacity:16] retain];
1135 for (pkgSourceList::const_iterator source = list.begin(); source != list.end(); ++source) {
1136 metaIndex *index(*source);
1137 fprintf(stderr, "\"%s\" \"%s\" \"%s\" \"%s\"\n", index->GetURI().c_str(), index->GetDist().c_str(), index->GetType(), index->IsTrusted() ? "true" : "false");
1139 debReleaseIndex *dindex(dynamic_cast<debReleaseIndex *>(index));
1143 fprintf(stderr, " \"%s\"\n", dindex->MetaIndexFile("Release").c_str());
1145 std::ifstream release(dindex->MetaIndexFile("Release").c_str());
1147 while (std::getline(release, line)) {
1148 std::string::size_type colon(line.find(':'));
1149 if (colon == std::string::npos)
1151 std::string name(line.substr(0, colon));
1152 std::string value(line.substr(colon + 1));
1153 while (!value.empty() && value[0] == ' ')
1154 value = value.substr(1);
1155 std::cerr << "[" << name << "|" << value << "]" << std::endl;
1162 - (NSString *) leftTitle {
1163 return @"Refresh All";
1166 - (NSString *) rightTitle {
1173 @implementation Database
1175 - (void) _readStatus:(NSNumber *)fd {
1176 NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init];
1178 __gnu_cxx::stdio_filebuf<char> ib([fd intValue], std::ios::in);
1179 std::istream is(&ib);
1184 pcre *code = pcre_compile("^([^:]*):([^:]*):([^:]*):(.*)$", 0, &error, &offset, NULL);
1186 pcre_extra *study = NULL;
1188 pcre_fullinfo(code, study, PCRE_INFO_CAPTURECOUNT, &capture);
1189 int matches[(capture + 1) * 3];
1191 while (std::getline(is, line)) {
1192 const char *data(line.c_str());
1194 _assert(pcre_exec(code, study, data, line.size(), 0, 0, matches, sizeof(matches) / sizeof(matches[0])) >= 0);
1196 std::istringstream buffer(line.substr(matches[6], matches[7] - matches[6]));
1199 [delegate_ setPercent:(percent / 100)];
1201 NSString *string = [NSString stringWithCString:(data + matches[8]) length:(matches[9] - matches[8])];
1202 std::string type(line.substr(matches[2], matches[3] - matches[2]));
1204 if (type == "pmerror")
1205 [delegate_ setError:string];
1206 else if (type == "pmstatus")
1207 [delegate_ setTitle:string];
1208 else if (type == "pmconffile")
1210 else _assert(false);
1216 - (void) _readOutput:(NSNumber *)fd {
1217 NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init];
1219 __gnu_cxx::stdio_filebuf<char> ib([fd intValue], std::ios::in);
1220 std::istream is(&ib);
1223 while (std::getline(is, line))
1224 [delegate_ addOutput:[NSString stringWithCString:line.c_str()]];
1229 - (Package *) packageWithName:(NSString *)name {
1230 pkgCache::PkgIterator iterator(cache_->FindPkg([name cString]));
1231 return iterator.end() ? nil : [Package packageWithIterator:iterator database:self];
1234 - (Database *) init {
1235 if ((self = [super init]) != nil) {
1243 _assert(pipe(fds) != -1);
1247 detachNewThreadSelector:@selector(_readStatus:)
1249 withObject:[[NSNumber numberWithInt:fds[0]] retain]
1252 _assert(pipe(fds) != -1);
1253 _assert(dup2(fds[1], 1) != -1);
1254 _assert(close(fds[1]) != -1);
1257 detachNewThreadSelector:@selector(_readOutput:)
1259 withObject:[[NSNumber numberWithInt:fds[0]] retain]
1264 - (pkgCacheFile &) cache {
1268 - (pkgRecords *) records {
1272 - (pkgProblemResolver *) resolver {
1276 - (pkgAcquire &) fetcher {
1280 - (void) reloadData {
1288 cache_.Open(progress_, true);
1289 records_ = new pkgRecords(cache_);
1290 resolver_ = new pkgProblemResolver(cache_);
1291 fetcher_ = new pkgAcquire(&status_);
1296 pkgRecords records(cache_);
1298 lock_ = new FileFd();
1299 lock_->Fd(GetLock(_config->FindDir("Dir::Cache::Archives") + "lock"));
1300 _assert(!_error->PendingError());
1303 _assert(list.ReadMainList());
1305 manager_ = (_system->CreatePM(cache_));
1306 _assert(manager_->GetArchives(fetcher_, &list, &records));
1307 _assert(!_error->PendingError());
1311 if (fetcher_->Run(PulseInterval_) != pkgAcquire::Continue)
1315 pkgPackageManager::OrderResult result = manager_->DoInstall(statusfd_);
1317 if (result == pkgPackageManager::Failed)
1319 if (_error->PendingError())
1321 if (result != pkgPackageManager::Completed)
1327 _assert(list.ReadMainList());
1330 lock.Fd(GetLock(_config->FindDir("Dir::State::Lists") + "lock"));
1331 _assert(!_error->PendingError());
1333 pkgAcquire fetcher(&status_);
1334 _assert(list.GetIndexes(&fetcher));
1335 _assert(fetcher.Run(PulseInterval_) != pkgAcquire::Failed);
1337 bool failed = false;
1338 for (pkgAcquire::ItemIterator item = fetcher.ItemsBegin(); item != fetcher.ItemsEnd(); item++)
1339 if ((*item)->Status != pkgAcquire::Item::StatDone) {
1340 (*item)->Finished();
1344 if (!failed && _config->FindB("APT::Get::List-Cleanup", true) == true) {
1345 _assert(fetcher.Clean(_config->FindDir("Dir::State::lists")));
1346 _assert(fetcher.Clean(_config->FindDir("Dir::State::lists") + "partial/"));
1351 _assert(cache_->DelCount() == 0 && cache_->InstCount() == 0);
1352 _assert(pkgApplyStatus(cache_));
1354 if (cache_->BrokenCount() != 0) {
1355 _assert(pkgFixBroken(cache_));
1356 _assert(cache_->BrokenCount() == 0);
1357 _assert(pkgMinimizeUpgrade(cache_));
1360 _assert(pkgDistUpgrade(cache_));
1362 //InstallPackages(cache_, true);
1365 - (void) setDelegate:(id)delegate {
1366 delegate_ = delegate;
1367 status_.setDelegate(delegate);
1368 progress_.setDelegate(delegate);
1373 /* Progress Data {{{ */
1374 @interface ProgressData : NSObject {
1380 - (ProgressData *) initWithSelector:(SEL)selector target:(id)target object:(id)object;
1387 @implementation ProgressData
1389 - (ProgressData *) initWithSelector:(SEL)selector target:(id)target object:(id)object {
1390 if ((self = [super init]) != nil) {
1391 selector_ = selector;
1411 /* Progress View {{{ */
1412 @interface ProgressView : UIView <
1416 UIView *background_;
1417 UITransitionView *transition_;
1419 UINavigationBar *navbar_;
1420 UIProgressBar *progress_;
1421 UITextView *output_;
1422 UITextLabel *status_;
1424 UIAlertSheet *alert_;
1429 - (ProgressView *) initWithFrame:(struct CGRect)frame delegate:(id)delegate;
1430 - (void) setContentView:(UIView *)view;
1433 - (void) alertSheet:(UIAlertSheet *)sheet buttonClicked:(int)button;
1435 - (void) _retachThread;
1436 - (void) _detachNewThreadData:(ProgressData *)data;
1437 - (void) detachNewThreadSelector:(SEL)selector toTarget:(id)target withObject:(id)object;
1439 - (void) setError:(NSString *)error;
1440 - (void) _setError:(NSString *)error;
1442 - (void) setTitle:(NSString *)title;
1443 - (void) _setTitle:(NSString *)title;
1445 - (void) setPercent:(float)percent;
1446 - (void) _setPercent:(NSNumber *)percent;
1448 - (void) addOutput:(NSString *)output;
1449 - (void) _addOutput:(NSString *)output;
1451 - (void) setStatusFail;
1454 @protocol ProgressViewDelegate
1455 - (void) progressViewIsComplete:(ProgressView *)sender;
1458 @implementation ProgressView
1462 [background_ release];
1463 [transition_ release];
1466 [progress_ release];
1472 - (ProgressView *) initWithFrame:(struct CGRect)frame delegate:(id)delegate {
1473 if ((self = [super initWithFrame:frame]) != nil) {
1474 delegate_ = delegate;
1477 CGColorSpaceRef space = CGColorSpaceCreateDeviceRGB();
1478 float black[] = {0.0, 0.0, 0.0, 1.0};
1479 float white[] = {1.0, 1.0, 1.0, 1.0};
1480 float clear[] = {0.0, 0.0, 0.0, 0.0};
1482 background_ = [[UIView alloc] initWithFrame:[self bounds]];
1483 [background_ setBackgroundColor:CGColorCreate(space, black)];
1484 [self addSubview:background_];
1486 transition_ = [[UITransitionView alloc] initWithFrame:[self bounds]];
1487 [self addSubview:transition_];
1489 overlay_ = [[UIView alloc] initWithFrame:[transition_ bounds]];
1491 CGSize navsize = [UINavigationBar defaultSize];
1492 CGRect navrect = {{0, 0}, navsize};
1494 navbar_ = [[UINavigationBar alloc] initWithFrame:navrect];
1495 [overlay_ addSubview:navbar_];
1497 [navbar_ setBarStyle:1];
1498 [navbar_ setDelegate:self];
1500 UINavigationItem *navitem = [[[UINavigationItem alloc] initWithTitle:@"Running..."] autorelease];
1501 [navbar_ pushNavigationItem:navitem];
1503 CGRect bounds = [overlay_ bounds];
1504 CGSize prgsize = [UIProgressBar defaultSize];
1507 (bounds.size.width - prgsize.width) / 2,
1508 bounds.size.height - prgsize.height - 20
1511 progress_ = [[UIProgressBar alloc] initWithFrame:prgrect];
1512 [overlay_ addSubview:progress_];
1514 status_ = [[UITextLabel alloc] initWithFrame:CGRectMake(
1516 bounds.size.height - prgsize.height - 50,
1517 bounds.size.width - 20,
1521 [status_ setColor:CGColorCreate(space, white)];
1522 [status_ setBackgroundColor:CGColorCreate(space, clear)];
1524 [status_ setCentersHorizontally:YES];
1525 //[status_ setFont:font];
1527 output_ = [[UITextView alloc] initWithFrame:CGRectMake(
1529 navrect.size.height + 20,
1530 bounds.size.width - 20,
1531 bounds.size.height - navsize.height - 62 - navrect.size.height
1534 //[output_ setTextFont:@"Courier New"];
1535 [output_ setTextSize:12];
1537 [output_ setTextColor:CGColorCreate(space, white)];
1538 [output_ setBackgroundColor:CGColorCreate(space, clear)];
1540 [output_ setMarginTop:0];
1541 [output_ setAllowsRubberBanding:YES];
1543 [overlay_ addSubview:output_];
1544 [overlay_ addSubview:status_];
1546 [progress_ setStyle:0];
1550 - (void) setContentView:(UIView *)view {
1554 - (void) resetView {
1555 [transition_ transition:6 toView:view_];
1558 - (void) alertSheet:(UIAlertSheet *)sheet buttonClicked:(int)button {
1564 - (void) _retachThread {
1565 [delegate_ progressViewIsComplete:self];
1569 - (void) _detachNewThreadData:(ProgressData *)data {
1570 NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init];
1572 [[data target] performSelector:[data selector] withObject:[data object]];
1573 [self performSelectorOnMainThread:@selector(_retachThread) withObject:nil waitUntilDone:YES];
1579 - (void) detachNewThreadSelector:(SEL)selector toTarget:(id)target withObject:(id)object {
1580 [status_ setText:nil];
1581 [output_ setText:@""];
1582 [progress_ setProgress:0];
1584 [transition_ transition:6 toView:overlay_];
1587 detachNewThreadSelector:@selector(_detachNewThreadData:)
1589 withObject:[[ProgressData alloc]
1590 initWithSelector:selector
1597 - (void) setStatusFail {
1600 - (void) setError:(NSString *)error {
1602 performSelectorOnMainThread:@selector(_setError:)
1608 - (void) _setError:(NSString *)error {
1609 _assert(alert_ == nil);
1611 alert_ = [[UIAlertSheet alloc]
1612 initWithTitle:@"Package Error"
1613 buttons:[NSArray arrayWithObjects:@"Okay", nil]
1614 defaultButtonIndex:0
1619 [alert_ setBodyText:error];
1620 [alert_ popupAlertAnimated:YES];
1623 - (void) setTitle:(NSString *)title {
1625 performSelectorOnMainThread:@selector(_setTitle:)
1631 - (void) _setTitle:(NSString *)title {
1632 [status_ setText:[title stringByAppendingString:@"..."]];
1635 - (void) setPercent:(float)percent {
1637 performSelectorOnMainThread:@selector(_setPercent:)
1638 withObject:[NSNumber numberWithFloat:percent]
1643 - (void) _setPercent:(NSNumber *)percent {
1644 [progress_ setProgress:[percent floatValue]];
1647 - (void) addOutput:(NSString *)output {
1649 performSelectorOnMainThread:@selector(_addOutput:)
1655 - (void) _addOutput:(NSString *)output {
1656 [output_ setText:[NSString stringWithFormat:@"%@\n%@", [output_ text], output]];
1657 CGSize size = [output_ contentSize];
1658 CGRect rect = {{0, size.height}, {size.width, 0}};
1659 [output_ scrollRectToVisible:rect animated:YES];
1665 @protocol PackagesViewDelegate
1668 - (void) openURL:(NSString *)url;
1671 /* PackagesView {{{ */
1672 @interface PackagesView : ResetView <
1675 Database *database_;
1676 NSMutableArray *packages_;
1677 NSMutableArray *sections_;
1679 UISectionList *list_;
1680 UITransitionView *transition_;
1683 PackageView *pkgview_;
1686 - (int) numberOfSectionsInSectionList:(UISectionList *)list;
1687 - (NSString *) sectionList:(UISectionList *)list titleForSection:(int)section;
1688 - (int) sectionList:(UISectionList *)list rowForSection:(int)section;
1690 - (int) numberOfRowsInTable:(UITable *)table;
1691 - (float) table:(UITable *)table heightForRow:(int)row;
1692 - (UITableCell *) table:(UITable *)table cellForRow:(int)row column:(UITableColumn *)col;
1693 - (BOOL) table:(UITable *)table showDisclosureForRow:(int)row;
1694 - (void) tableRowSelected:(NSNotification*)notification;
1696 - (void) navigationBar:(UINavigationBar *)navbar buttonClicked:(int)button;
1697 - (void) navigationBar:(UINavigationBar *)navbar poppedItem:(UINavigationItem *)item;
1699 - (id) initWithFrame:(struct CGRect)frame database:(Database *)database;
1700 - (void) setDelegate:(id)delegate;
1702 - (void) reloadData:(BOOL)reset;
1704 - (NSString *) title;
1705 - (void) perform:(Package *)package;
1706 - (void) addPackage:(Package *)package;
1707 - (NSString *) versionWithPackage:(Package *)package;
1710 @implementation PackagesView
1712 - (int) numberOfSectionsInSectionList:(UISectionList *)list {
1713 return [sections_ count];
1716 - (NSString *) sectionList:(UISectionList *)list titleForSection:(int)section {
1717 return [[sections_ objectAtIndex:section] name];
1720 - (int) sectionList:(UISectionList *)list rowForSection:(int)section {
1721 return [[sections_ objectAtIndex:section] row];
1724 - (int) numberOfRowsInTable:(UITable *)table {
1725 return [packages_ count];
1728 - (float) table:(UITable *)table heightForRow:(int)row {
1732 - (UITableCell *) table:(UITable *)table cellForRow:(int)row column:(UITableColumn *)col {
1733 Package *package = [packages_ objectAtIndex:row];
1734 PackageCell *cell = [[[PackageCell alloc] initWithPackage:package delegate:self] autorelease];
1738 - (BOOL) table:(UITable *)table showDisclosureForRow:(int)row {
1742 - (void) tableRowSelected:(NSNotification*)notification {
1743 int row = [[list_ table] selectedRow];
1747 package_ = [packages_ objectAtIndex:row];
1748 pkgname_ = [[package_ name] retain];
1750 UINavigationItem *navitem = [[UINavigationItem alloc] initWithTitle:[package_ name]];
1751 [navbar_ pushNavigationItem:navitem];
1753 [navbar_ showButtonsWithLeftTitle:nil rightTitle:[self title]];
1755 [pkgview_ setPackage:package_];
1756 [transition_ transition:1 toView:pkgview_];
1759 - (void) navigationBar:(UINavigationBar *)navbar buttonClicked:(int)button {
1761 [self perform:package_];
1763 pkgProblemResolver *resolver = [database_ resolver];
1765 resolver->InstallProtect();
1766 if (!resolver->Resolve(true))
1769 [delegate_ perform];
1773 - (void) navigationBar:(UINavigationBar *)navbar poppedItem:(UINavigationItem *)item {
1775 [super navigationBar:navbar poppedItem:item];
1778 - (id) initWithFrame:(struct CGRect)frame database:(Database *)database {
1779 if ((self = [super initWithFrame:frame]) != nil) {
1780 database_ = [database retain];
1782 struct CGRect bounds = [self bounds];
1783 CGSize navsize = [UINavigationBar defaultSize];
1784 CGRect navrect = {{0, 0}, navsize};
1786 navbar_ = [[UINavigationBar alloc] initWithFrame:navrect];
1787 [self addSubview:navbar_];
1789 [navbar_ setBarStyle:1];
1790 [navbar_ setDelegate:self];
1792 UINavigationItem *navitem = [[[UINavigationItem alloc] initWithTitle:[self title]] autorelease];
1793 [navbar_ pushNavigationItem:navitem];
1794 [navitem setBackButtonTitle:@"Packages"];
1796 transition_ = [[UITransitionView alloc] initWithFrame:CGRectMake(
1797 bounds.origin.x, bounds.origin.y + navsize.height, bounds.size.width, bounds.size.height - navsize.height
1800 [self addSubview:transition_];
1802 list_ = [[UISectionList alloc] initWithFrame:[transition_ bounds] showSectionIndex:NO];
1803 [list_ setDataSource:self];
1804 [list_ setShouldHideHeaderInShortLists:NO];
1806 [transition_ transition:0 toView:list_];
1808 UITableColumn *column = [[UITableColumn alloc]
1809 initWithTitle:@"Name"
1811 width:frame.size.width
1814 UITable *table = [list_ table];
1815 [table setSeparatorStyle:1];
1816 [table addTableColumn:column];
1817 [table setDelegate:self];
1819 pkgview_ = [[PackageView alloc] initWithFrame:[transition_ bounds] database:database_];
1823 - (void) setDelegate:(id)delegate {
1824 delegate_ = delegate;
1825 [pkgview_ setDelegate:delegate];
1829 [transition_ transition:(resetting_ ? 0 : 2) toView:list_];
1830 UITable *table = [list_ table];
1831 [table selectRow:-1 byExtendingSelection:NO withFade:(resetting_ ? NO : YES)];
1835 - (void) reloadData:(BOOL)reset {
1836 packages_ = [[NSMutableArray arrayWithCapacity:16] retain];
1838 if (sections_ != nil) {
1839 [sections_ release];
1843 for (pkgCache::PkgIterator iterator = [database_ cache]->PkgBegin(); !iterator.end(); ++iterator)
1844 if (Package *package = [Package packageWithIterator:iterator database:database_])
1845 [self addPackage:package];
1847 [packages_ sortUsingSelector:@selector(compareBySectionAndName:)];
1848 sections_ = [[NSMutableArray arrayWithCapacity:16] retain];
1850 Section *section = nil;
1851 for (size_t offset = 0, count = [packages_ count]; offset != count; ++offset) {
1852 Package *package = [packages_ objectAtIndex:offset];
1853 NSString *name = [package section];
1855 if (section == nil || ![[section name] isEqual:name]) {
1856 section = [[Section alloc] initWithName:name row:offset];
1857 [sections_ addObject:section];
1860 [section addPackage:package];
1866 else if (package_ != nil) {
1867 package_ = [database_ packageWithName:pkgname_];
1868 [pkgview_ setPackage:package_];
1872 - (NSString *) title {
1876 - (void) perform:(Package *)package {
1879 - (void) addPackage:(Package *)package {
1880 [packages_ addObject:package];
1883 - (NSString *) versionWithPackage:(Package *)package {
1890 /* InstallView {{{ */
1891 @interface InstallView : PackagesView {
1894 - (NSString *) title;
1895 - (void) addPackage:(Package *)package;
1896 - (void) perform:(Package *)package;
1897 - (NSString *) versionWithPackage:(Package *)package;
1900 @implementation InstallView
1902 - (NSString *) title {
1906 - (void) addPackage:(Package *)package {
1907 if ([package installed] == nil)
1908 [super addPackage:package];
1911 - (void) perform:(Package *)package {
1915 - (NSString *) versionWithPackage:(Package *)package {
1916 return [package latest];
1921 /* UpgradeView {{{ */
1922 @interface UpgradeView : PackagesView {
1925 - (NSString *) title;
1926 - (NSString *) leftTitle;
1927 - (void) addPackage:(Package *)package;
1928 - (void) perform:(Package *)package;
1929 - (NSString *) versionWithPackage:(Package *)package;
1932 @implementation UpgradeView
1934 - (NSString *) title {
1938 - (NSString *) leftTitle {
1939 return @"Upgrade All";
1942 - (void) addPackage:(Package *)package {
1943 NSString *installed = [package installed];
1944 if (installed != nil && [[package latest] compare:installed] != NSOrderedSame)
1945 [super addPackage:package];
1948 - (void) perform:(Package *)package {
1952 - (NSString *) versionWithPackage:(Package *)package {
1953 return [package latest];
1958 /* UninstallView {{{ */
1959 @interface UninstallView : PackagesView {
1962 - (NSString *) title;
1963 - (void) addPackage:(Package *)package;
1964 - (void) perform:(Package *)package;
1965 - (NSString *) versionWithPackage:(Package *)package;
1968 @implementation UninstallView
1970 - (NSString *) title {
1971 return @"Uninstall";
1974 - (void) addPackage:(Package *)package {
1975 if ([package installed] != nil)
1976 [super addPackage:package];
1979 - (void) perform:(Package *)package {
1983 - (NSString *) versionWithPackage:(Package *)package {
1984 return [package installed];
1990 @interface Cydia : UIApplication <
1991 ConfirmationViewDelegate,
1992 PackagesViewDelegate,
1993 ProgressViewDelegate
1998 UITransitionView *transition_;
1999 UIButtonBar *buttonbar_;
2001 UIAlertSheet *alert_;
2002 ConfirmationView *confirm_;
2004 Database *database_;
2005 ProgressView *progress_;
2008 UINavigationBar *navbar_;
2009 UIScroller *scroller_;
2010 UIWebView *webview_;
2013 InstallView *install_;
2014 UpgradeView *upgrade_;
2015 UninstallView *uninstall_;
2016 SourcesView *sources_;
2020 - (void) reloadData:(BOOL)reset;
2026 - (void) progressViewIsComplete:(ProgressView *)progress;
2028 - (void) navigationBar:(UINavigationBar *)navbar buttonClicked:(int)button;
2029 - (void) alertSheet:(UIAlertSheet *)sheet buttonClicked:(int)button;
2030 - (void) buttonBarItemTapped:(id)sender;
2032 - (void) view:(UIView *)sender didSetFrame:(CGRect)frame;
2033 - (void) view:(UIView *)view didDrawInRect:(CGRect)rect duration:(float)duration;
2035 - (void) applicationDidFinishLaunching:(id)unused;
2038 #include <objc/objc-class.h>
2040 @implementation Cydia
2043 NSMutableURLRequest *request = [NSMutableURLRequest
2045 cachePolicy:NSURLRequestReloadIgnoringCacheData
2046 timeoutInterval:30.0
2049 [request addValue:[NSString stringWithCString:Machine_] forHTTPHeaderField:@"X-Machine"];
2050 [request addValue:[NSString stringWithCString:SerialNumber_] forHTTPHeaderField:@"X-Serial-Number"];
2052 [webview_ loadRequest:request];
2055 - (void) reloadData:(BOOL)reset {
2056 [database_ reloadData];
2057 [install_ reloadData:reset];
2058 [upgrade_ reloadData:reset];
2059 [uninstall_ reloadData:reset];
2060 [sources_ reloadData];
2064 [database_ prepare];
2065 confirm_ = [[ConfirmationView alloc] initWithView:underlay_ database:database_ delegate:self];
2069 [self reloadData:NO];
2075 [overlay_ removeFromSuperview];
2078 detachNewThreadSelector:@selector(perform)
2086 detachNewThreadSelector:@selector(update)
2092 - (void) progressViewIsComplete:(ProgressView *)progress {
2093 [self reloadData:YES];
2095 if (confirm_ != nil) {
2096 [underlay_ addSubview:overlay_];
2097 [confirm_ removeFromSuperview];
2103 - (void) navigationBar:(UINavigationBar *)navbar buttonClicked:(int)button {
2110 _assert(alert_ == nil);
2112 alert_ = [[UIAlertSheet alloc]
2113 initWithTitle:@"About Cydia Packager"
2114 buttons:[NSArray arrayWithObjects:@"Close", nil]
2115 defaultButtonIndex:0
2120 [alert_ setBodyText:
2121 @"Copyright (C) 2007\n"
2122 "Jay Freeman (saurik)\n"
2123 "saurik@saurik.com\n"
2124 "http://www.saurik.com/\n"
2127 "http://www.theokorigroup.com/\n"
2129 "College of Creative Studies,\n"
2130 "University of California,\n"
2132 "http://www.ccs.ucsb.edu/\n"
2135 "bad_, BHSPitMonkey, Cobra, core,\n"
2136 "Corona, cromas, Darken, dtzWill,\n"
2137 "francis, Godores, jerry, Kingstone,\n"
2138 "lounger, rockabilly, tman, Wbiggs"
2141 [alert_ presentSheetFromButtonBar:buttonbar_];
2146 - (void) alertSheet:(UIAlertSheet *)sheet buttonClicked:(int)button {
2152 - (void) buttonBarItemTapped:(id)sender {
2155 switch ([sender tag]) {
2156 case 1: view = featured_; break;
2157 case 2: view = install_; break;
2158 case 3: view = upgrade_; break;
2159 case 4: view = uninstall_; break;
2160 case 5: view = sources_; break;
2166 if ([view respondsToSelector:@selector(resetView)])
2167 [(id) view resetView];
2168 [transition_ transition:0 toView:view];
2171 - (void) view:(UIView *)view didSetFrame:(CGRect)frame {
2172 [scroller_ setContentSize:frame.size];
2175 - (void) view:(UIView *)view didDrawInRect:(CGRect)rect duration:(float)duration {
2176 [scroller_ setContentSize:[webview_ bounds].size];
2179 - (void) applicationDidFinishLaunching:(id)unused {
2180 _assert(pkgInitConfig(*_config));
2181 _assert(pkgInitSystem(*_config, _system));
2186 CGRect screenrect = [UIHardware fullScreenApplicationContentRect];
2187 window_ = [[UIWindow alloc] initWithContentRect:screenrect];
2189 [window_ orderFront: self];
2190 [window_ makeKey: self];
2191 [window_ _setHidden: NO];
2193 progress_ = [[ProgressView alloc] initWithFrame:[window_ bounds] delegate:self];
2194 [window_ setContentView:progress_];
2196 underlay_ = [[UIView alloc] initWithFrame:[progress_ bounds]];
2197 [progress_ setContentView:underlay_];
2199 overlay_ = [[UIView alloc] initWithFrame:[underlay_ bounds]];
2200 [underlay_ addSubview:overlay_];
2202 transition_ = [[UITransitionView alloc] initWithFrame:CGRectMake(
2203 0, 0, screenrect.size.width, screenrect.size.height - 48
2206 [overlay_ addSubview:transition_];
2208 featured_ = [[UIView alloc] initWithFrame:[transition_ bounds]];
2210 CGSize navsize = [UINavigationBar defaultSize];
2211 CGRect navrect = {{0, 0}, navsize};
2213 navbar_ = [[UINavigationBar alloc] initWithFrame:navrect];
2214 [featured_ addSubview:navbar_];
2216 [navbar_ setBarStyle:1];
2217 [navbar_ setDelegate:self];
2219 [navbar_ showButtonsWithLeftTitle:@"About" rightTitle:@"Reload"];
2221 UINavigationItem *navitem = [[UINavigationItem alloc] initWithTitle:@"Featured"];
2222 [navbar_ pushNavigationItem:navitem];
2224 struct CGRect subbounds = [featured_ bounds];
2225 subbounds.origin.y += navsize.height;
2226 subbounds.size.height -= navsize.height;
2228 UIImageView *pinstripe = [[UIImageView alloc] initWithFrame:subbounds];
2229 [pinstripe setImage:[UIImage applicationImageNamed:@"pinstripe.png"]];
2230 [featured_ addSubview:pinstripe];
2232 scroller_ = [[UIScroller alloc] initWithFrame:subbounds];
2233 [featured_ addSubview:scroller_];
2235 [scroller_ setScrollingEnabled:YES];
2236 [scroller_ setAdjustForContentSizeChange:YES];
2237 [scroller_ setClipsSubviews:YES];
2238 [scroller_ setAllowsRubberBanding:YES];
2239 [scroller_ setScrollDecelerationFactor:0.99];
2240 [scroller_ setDelegate:self];
2242 webview_ = [[UIWebView alloc] initWithFrame:[scroller_ bounds]];
2243 [scroller_ addSubview:webview_];
2245 [webview_ setTilingEnabled:YES];
2246 [webview_ setTileSize:CGSizeMake(screenrect.size.width, 500)];
2247 [webview_ setAutoresizes:YES];
2248 [webview_ setDelegate:self];
2250 NSArray *buttonitems = [NSArray arrayWithObjects:
2251 [NSDictionary dictionaryWithObjectsAndKeys:
2252 @"buttonBarItemTapped:", kUIButtonBarButtonAction,
2253 @"featured-up.png", kUIButtonBarButtonInfo,
2254 @"featured-dn.png", kUIButtonBarButtonSelectedInfo,
2255 [NSNumber numberWithInt:1], kUIButtonBarButtonTag,
2256 self, kUIButtonBarButtonTarget,
2257 @"Featured", kUIButtonBarButtonTitle,
2258 @"0", kUIButtonBarButtonType,
2261 [NSDictionary dictionaryWithObjectsAndKeys:
2262 @"buttonBarItemTapped:", kUIButtonBarButtonAction,
2263 @"install-up.png", kUIButtonBarButtonInfo,
2264 @"install-dn.png", kUIButtonBarButtonSelectedInfo,
2265 [NSNumber numberWithInt:2], kUIButtonBarButtonTag,
2266 self, kUIButtonBarButtonTarget,
2267 @"Install", kUIButtonBarButtonTitle,
2268 @"0", kUIButtonBarButtonType,
2271 [NSDictionary dictionaryWithObjectsAndKeys:
2272 @"buttonBarItemTapped:", kUIButtonBarButtonAction,
2273 @"upgrade-up.png", kUIButtonBarButtonInfo,
2274 @"upgrade-dn.png", kUIButtonBarButtonSelectedInfo,
2275 [NSNumber numberWithInt:3], kUIButtonBarButtonTag,
2276 self, kUIButtonBarButtonTarget,
2277 @"Upgrade", kUIButtonBarButtonTitle,
2278 @"0", kUIButtonBarButtonType,
2281 [NSDictionary dictionaryWithObjectsAndKeys:
2282 @"buttonBarItemTapped:", kUIButtonBarButtonAction,
2283 @"uninstall-up.png", kUIButtonBarButtonInfo,
2284 @"uninstall-dn.png", kUIButtonBarButtonSelectedInfo,
2285 [NSNumber numberWithInt:4], kUIButtonBarButtonTag,
2286 self, kUIButtonBarButtonTarget,
2287 @"Uninstall", kUIButtonBarButtonTitle,
2288 @"0", kUIButtonBarButtonType,
2291 [NSDictionary dictionaryWithObjectsAndKeys:
2292 @"buttonBarItemTapped:", kUIButtonBarButtonAction,
2293 @"sources-up.png", kUIButtonBarButtonInfo,
2294 @"sources-dn.png", kUIButtonBarButtonSelectedInfo,
2295 [NSNumber numberWithInt:5], kUIButtonBarButtonTag,
2296 self, kUIButtonBarButtonTarget,
2297 @"Sources", kUIButtonBarButtonTitle,
2298 @"0", kUIButtonBarButtonType,
2302 buttonbar_ = [[UIButtonBar alloc]
2304 withFrame:CGRectMake(
2305 0, screenrect.size.height - 48,
2306 screenrect.size.width, 48
2308 withItemList:buttonitems
2311 [buttonbar_ setDelegate:self];
2312 [buttonbar_ setBarStyle:1];
2313 [buttonbar_ setButtonBarTrackingMode:2];
2315 int buttons[5] = {1, 2, 3, 4, 5};
2316 [buttonbar_ registerButtonGroup:0 withButtons:buttons withCount:5];
2317 [buttonbar_ showButtonGroup:0 withDuration:0];
2319 for (int i = 0; i != 5; ++i)
2320 [[buttonbar_ viewWithTag:(i + 1)] setFrame:CGRectMake(
2321 i * 64 + 2, 1, 60, 48
2324 [buttonbar_ showSelectionForButton:1];
2325 [transition_ transition:0 toView:featured_];
2327 [overlay_ addSubview:buttonbar_];
2329 database_ = [[Database alloc] init];
2330 [database_ setDelegate:progress_];
2332 install_ = [[InstallView alloc] initWithFrame:[transition_ bounds] database:database_];
2333 [install_ setDelegate:self];
2335 upgrade_ = [[UpgradeView alloc] initWithFrame:[transition_ bounds] database:database_];
2336 [upgrade_ setDelegate:self];
2338 uninstall_ = [[UninstallView alloc] initWithFrame:[transition_ bounds] database:database_];
2339 [uninstall_ setDelegate:self];
2341 sources_ = [[SourcesView alloc] initWithFrame:[transition_ bounds] database:database_];
2342 [sources_ setDelegate:self];
2346 UIAlertSheet *alert = [[UIAlertSheet alloc]
2347 initWithTitle:@"Alert Title"
2348 buttons:[NSArray arrayWithObjects:@"Yes", nil]
2349 defaultButtonIndex:0
2354 NSLog(@"%p\n", [alert table]);
2355 [[alert table] setDelegate:self];
2356 [[alert table] reloadData];
2358 [alert addTextFieldWithValue:@"Title" label:@"Label"];
2359 [alert setShowsOverSpringBoardAlerts:YES];
2360 [alert setBodyText:@"This is an alert."];
2361 [alert presentSheetFromButtonBar:buttonbar_];
2362 //[alert popupAlertAnimated:YES];
2366 [self reloadData:NO];
2367 [progress_ resetView];
2369 Package *package([database_ packageWithName:@"cydia"]);
2370 NSString *application = package == nil ? @"Cydia" : [NSString stringWithFormat:@"Cydia/%@", [package installed]];
2371 WebView *webview = [webview_ webView];
2372 [webview setApplicationNameForUserAgent:application];
2374 url_ = [NSURL URLWithString:@"http://cydia.saurik.com/"];
2380 int main(int argc, char *argv[]) {
2381 NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init];
2384 sysctlbyname("hw.machine", NULL, &size, NULL, 0);
2385 char *machine = new char[size];
2386 sysctlbyname("hw.machine", machine, &size, NULL, 0);
2389 if (CFMutableDictionaryRef dict = IOServiceMatching("IOPlatformExpertDevice"))
2390 if (io_service_t service = IOServiceGetMatchingService(kIOMasterPortDefault, dict)) {
2391 if (CFTypeRef serial = IORegistryEntryCreateCFProperty(service, CFSTR(kIOPlatformSerialNumberKey), kCFAllocatorDefault, 0)) {
2392 SerialNumber_ = strdup(CFStringGetCStringPtr((CFStringRef) serial, CFStringGetSystemEncoding()));
2396 IOObjectRelease(service);
2399 UIApplicationMain(argc, argv, [Cydia class]);