]> git.saurik.com Git - cydia.git/blob - Cydia.mm
Finished install/uninstall.
[cydia.git] / Cydia.mm
1 /* #include Directives {{{ */
2 #include <Foundation/NSURL.h>
3 #include <UIKit/UIKit.h>
4 #import <GraphicsServices/GraphicsServices.h>
5
6 #include <sstream>
7 #include <ext/stdio_filebuf.h>
8
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>
20
21 #include <sys/sysctl.h>
22
23 #include <errno.h>
24 #include <pcre.h>
25 #include <string.h>
26 /* }}} */
27 /* Extension Keywords {{{ */
28 #define _trace() fprintf(stderr, "_trace()@%s:%u[%s]\n", __FILE__, __LINE__, __FUNCTION__)
29
30 #define _assert(test) do \
31 if (!(test)) { \
32 fprintf(stderr, "_assert(%d:%s)@%s:%u[%s]\n", errno, #test, __FILE__, __LINE__, __FUNCTION__); \
33 exit(-1); \
34 } \
35 while (false)
36 /* }}} */
37
38 @interface WebView
39 - (void) setApplicationNameForUserAgent:(NSString *)applicationName;
40 @end
41
42 static const int PulseInterval_ = 50000;
43 const char *Machine_ = NULL;
44 const char *SerialNumber_ = NULL;
45
46 @interface NSString (CydiaBypass)
47 - (NSString *) stringByAddingPercentEscapes;
48 @end
49
50 @protocol ProgressDelegate
51 - (void) setError:(NSString *)error;
52 - (void) setTitle:(NSString *)title;
53 - (void) setPercent:(float)percent;
54 - (void) addOutput:(NSString *)output;
55 @end
56
57 NSString *SizeString(double size) {
58 unsigned power = 0;
59 while (size > 1024) {
60 size /= 1024;
61 ++power;
62 }
63
64 static const char *powers_[] = {"B", "kB", "MB", "GB"};
65
66 return [NSString stringWithFormat:@"%.1f%s", size, powers_[power]];
67 }
68
69 /* Status Delegation {{{ */
70 class Status :
71 public pkgAcquireStatus
72 {
73 private:
74 id delegate_;
75
76 public:
77 Status() :
78 delegate_(nil)
79 {
80 }
81
82 void setDelegate(id delegate) {
83 delegate_ = delegate;
84 }
85
86 virtual bool MediaChange(std::string media, std::string drive) {
87 return false;
88 }
89
90 virtual void IMSHit(pkgAcquire::ItemDesc &item) {
91 }
92
93 virtual void Fetch(pkgAcquire::ItemDesc &item) {
94 [delegate_ setTitle:[NSString stringWithCString:("Downloading " + item.ShortDesc).c_str()]];
95 }
96
97 virtual void Done(pkgAcquire::ItemDesc &item) {
98 }
99
100 virtual void Fail(pkgAcquire::ItemDesc &item) {
101 [delegate_ performSelectorOnMainThread:@selector(setStatusFail) withObject:nil waitUntilDone:YES];
102 }
103
104 virtual bool Pulse(pkgAcquire *Owner) {
105 bool value = pkgAcquireStatus::Pulse(Owner);
106
107 float percent(
108 double(CurrentBytes + CurrentItems) /
109 double(TotalBytes + TotalItems)
110 );
111
112 [delegate_ setPercent:percent];
113 return value;
114 }
115
116 virtual void Start() {
117 }
118
119 virtual void Stop() {
120 }
121 };
122 /* }}} */
123 /* Progress Delegation {{{ */
124 class Progress :
125 public OpProgress
126 {
127 private:
128 id delegate_;
129
130 protected:
131 virtual void Update() {
132 [delegate_ setTitle:[NSString stringWithCString:Op.c_str()]];
133 [delegate_ setPercent:(Percent / 100)];
134 }
135
136 public:
137 Progress() :
138 delegate_(nil)
139 {
140 }
141
142 void setDelegate(id delegate) {
143 delegate_ = delegate;
144 }
145
146 virtual void Done() {
147 [delegate_ setPercent:1];
148 }
149 };
150 /* }}} */
151
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;
164 /* }}} */
165 /* Mime Addresses {{{ */
166 @interface Address : NSObject {
167 NSString *name_;
168 NSString *email_;
169 }
170
171 - (void) dealloc;
172
173 - (NSString *) name;
174 - (NSString *) email;
175
176 + (Address *) addressWithString:(NSString *)string;
177 - (Address *) initWithString:(NSString *)string;
178 @end
179
180 @implementation Address
181
182 - (void) dealloc {
183 [name_ release];
184 if (email_ != nil)
185 [email_ release];
186 [super dealloc];
187 }
188
189 - (NSString *) name {
190 return name_;
191 }
192
193 - (NSString *) email {
194 return email_;
195 }
196
197 + (Address *) addressWithString:(NSString *)string {
198 return [[[Address alloc] initWithString:string] autorelease];
199 }
200
201 - (Address *) initWithString:(NSString *)string {
202 if ((self = [super init]) != nil) {
203 const char *error;
204 int offset;
205 pcre *code = pcre_compile("^\"?(.*)\"? <([^>]*)>$", 0, &error, &offset, NULL);
206
207 if (code == NULL) {
208 fprintf(stderr, "%d:%s\n", offset, error);
209 _assert(false);
210 }
211
212 pcre_extra *study = NULL;
213 int capture;
214 pcre_fullinfo(code, study, PCRE_INFO_CAPTURECOUNT, &capture);
215 int matches[(capture + 1) * 3];
216
217 size_t size = [string length];
218 const char *data = [string UTF8String];
219
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];
223 } else {
224 name_ = [[NSString stringWithCString:data length:size] retain];
225 email_ = nil;
226 }
227 } return self;
228 }
229
230 @end
231 /* }}} */
232
233 /* Right Alignment {{{ */
234 @interface UIRightTextLabel : UITextLabel {
235 float _savedRightEdgeX;
236 BOOL _sizedtofit_flag;
237 }
238
239 - (void) setFrame:(CGRect)frame;
240 - (void) setText:(NSString *)text;
241 - (void) realignText;
242 @end
243
244 @implementation UIRightTextLabel
245
246 - (void) setFrame:(CGRect)frame {
247 [super setFrame:frame];
248 if (_sizedtofit_flag == NO) {
249 _savedRightEdgeX = frame.origin.x;
250 [self realignText];
251 }
252 }
253
254 - (void) setText:(NSString *)text {
255 [super setText:text];
256 [self realignText];
257 }
258
259 - (void) realignText {
260 CGRect oldFrame = [self frame];
261
262 _sizedtofit_flag = YES;
263 [self sizeToFit]; // shrink down size so I can right align it
264
265 CGRect newFrame = [self frame];
266
267 oldFrame.origin.x = _savedRightEdgeX - newFrame.size.width;
268 oldFrame.size.width = newFrame.size.width;
269 [super setFrame:oldFrame];
270 _sizedtofit_flag = NO;
271 }
272
273 @end
274 /* }}} */
275 /* Linear Algebra {{{ */
276 inline float interpolate(float begin, float end, float fraction) {
277 return (end - begin) * fraction + begin;
278 }
279 /* }}} */
280
281 /* Reset View {{{ */
282 @interface ResetView : UIView {
283 UINavigationBar *navbar_;
284 bool resetting_;
285 }
286
287 - (void) navigationBar:(UINavigationBar *)navbar poppedItem:(UINavigationItem *)item;
288
289 - (void) dealloc;
290 - (void) resetView;
291 - (void) _resetView;
292 - (NSString *) leftTitle;
293 - (NSString *) rightTitle;
294 @end
295
296 @implementation ResetView
297
298 - (void) navigationBar:(UINavigationBar *)navbar poppedItem:(UINavigationItem *)item {
299 if ([[navbar_ navigationItems] count] == 1)
300 [self _resetView];
301 }
302
303 - (void) dealloc {
304 [navbar_ release];
305 [super dealloc];
306 }
307
308 - (void) resetView {
309 resetting_ = true;
310 if ([[navbar_ navigationItems] count] == 1)
311 [self _resetView];
312 else while ([[navbar_ navigationItems] count] != 1)
313 [navbar_ popNavigationItem];
314 resetting_ = false;
315 }
316
317 - (void) _resetView {
318 [navbar_ showButtonsWithLeftTitle:[self leftTitle] rightTitle:[self rightTitle]];
319 }
320
321 - (NSString *) leftTitle {
322 return nil;
323 }
324
325 - (NSString *) rightTitle {
326 return nil;
327 }
328
329 @end
330 /* }}} */
331
332 @class Package;
333
334 @interface Database : NSObject {
335 pkgCacheFile cache_;
336 pkgRecords *records_;
337 pkgProblemResolver *resolver_;
338 pkgAcquire *fetcher_;
339 FileFd *lock_;
340 SPtr<pkgPackageManager> manager_;
341
342 id delegate_;
343 Status status_;
344 Progress progress_;
345 int statusfd_;
346 }
347
348 - (void) _readStatus:(NSNumber *)fd;
349 - (void) _readOutput:(NSNumber *)fd;
350
351 - (Package *) packageWithName:(NSString *)name;
352
353 - (Database *) init;
354 - (pkgCacheFile &) cache;
355 - (pkgRecords *) records;
356 - (pkgProblemResolver *) resolver;
357 - (pkgAcquire &) fetcher;
358 - (void) reloadData;
359
360 - (void) prepare;
361 - (void) perform;
362 - (void) update;
363 - (void) upgrade;
364
365 - (void) setDelegate:(id)delegate;
366 @end
367
368 /* Package Class {{{ */
369 @interface Package : NSObject {
370 pkgCache::PkgIterator iterator_;
371 Database *database_;
372 pkgRecords::Parser *parser_;
373 pkgCache::VerIterator version_;
374 pkgCache::VerFileIterator file_;
375 }
376
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;
379
380 - (NSString *) name;
381 - (NSString *) section;
382 - (NSString *) latest;
383 - (NSString *) installed;
384 - (Address *) maintainer;
385 - (size_t) size;
386 - (NSString *) tagline;
387 - (NSString *) description;
388 - (NSComparisonResult) compareBySectionAndName:(Package *)package;
389
390 - (void) install;
391 - (void) remove;
392 @end
393
394 @implementation Package
395
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;
400
401 version_ = version;
402 file_ = file;
403 parser_ = &[database_ records]->Lookup(file);
404 } return self;
405 }
406
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
412 database:database
413 version:version
414 file:file]
415 autorelease];
416 return nil;
417 }
418
419 - (NSString *) name {
420 return [[NSString stringWithCString:iterator_.Name()] lowercaseString];
421 }
422
423 - (NSString *) section {
424 return [NSString stringWithCString:iterator_.Section()];
425 }
426
427 - (NSString *) latest {
428 return [NSString stringWithCString:version_.VerStr()];
429 }
430
431 - (NSString *) installed {
432 return iterator_.CurrentVer().end() ? nil : [NSString stringWithCString:iterator_.CurrentVer().VerStr()];
433 }
434
435 - (Address *) maintainer {
436 return [Address addressWithString:[NSString stringWithCString:parser_->Maintainer().c_str()]];
437 }
438
439 - (size_t) size {
440 return version_->InstalledSize;
441 }
442
443 - (NSString *) tagline {
444 return [NSString stringWithCString:parser_->ShortDesc().c_str()];
445 }
446
447 - (NSString *) description {
448 return [NSString stringWithCString:parser_->LongDesc().c_str()];
449 }
450
451 - (NSComparisonResult) compareBySectionAndName:(Package *)package {
452 NSComparisonResult result = [[self section] compare:[package section]];
453 if (result != NSOrderedSame)
454 return result;
455 return [[self name] compare:[package name]];
456 }
457
458 - (void) install {
459 pkgProblemResolver *resolver = [database_ resolver];
460 resolver->Clear(iterator_);
461 resolver->Protect(iterator_);
462 [database_ cache]->MarkInstall(iterator_, false);
463 }
464
465 - (void) remove {
466 pkgProblemResolver *resolver = [database_ resolver];
467 resolver->Clear(iterator_);
468 resolver->Protect(iterator_);
469 resolver->Remove(iterator_);
470 [database_ cache]->MarkDelete(iterator_, true);
471 }
472
473 @end
474 /* }}} */
475 /* Section Class {{{ */
476 @interface Section : NSObject {
477 NSString *name_;
478 size_t row_;
479 NSMutableArray *packages_;
480 }
481
482 - (void) dealloc;
483
484 - (Section *) initWithName:(NSString *)name row:(size_t)row;
485 - (NSString *) name;
486 - (size_t) row;
487 - (void) addPackage:(Package *)package;
488 @end
489
490 @implementation Section
491
492 - (void) dealloc {
493 [name_ release];
494 [packages_ release];
495 [super dealloc];
496 }
497
498 - (Section *) initWithName:(NSString *)name row:(size_t)row {
499 if ((self = [super init]) != nil) {
500 name_ = [name retain];
501 row_ = row;
502 packages_ = [[NSMutableArray arrayWithCapacity:16] retain];
503 } return self;
504 }
505
506 - (NSString *) name {
507 return name_;
508 }
509
510 - (size_t) row {
511 return row_;
512 }
513
514 - (void) addPackage:(Package *)package {
515 [packages_ addObject:package];
516 }
517
518 @end
519 /* }}} */
520
521 /* Confirmation View {{{ */
522 void AddTextView(NSMutableDictionary *fields, NSMutableArray *packages, NSString *key) {
523 if ([packages count] == 0)
524 return;
525
526 CGColorSpaceRef space = CGColorSpaceCreateDeviceRGB();
527 float clear[] = {0, 0, 0, 0};
528 float blue[] = {0, 0, 0.4, 1};
529
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];
537
538 CGRect frame([text frame]);
539 CGSize size([text contentSize]);
540 frame.size.height = size.height;
541 [text setFrame:frame];
542
543 [fields setObject:text forKey:key];
544 }
545
546 @protocol ConfirmationViewDelegate
547 - (void) cancel;
548 - (void) confirm;
549 @end
550
551 @interface ConfirmationView : UIView {
552 Database *database_;
553 id delegate_;
554 UITransitionView *transition_;
555 UIView *overlay_;
556 UINavigationBar *navbar_;
557 UIPreferencesTable *table_;
558 NSMutableDictionary *fields_;
559 UIAlertSheet *essential_;
560 }
561
562 - (void) dealloc;
563 - (void) cancel;
564
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;
568
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;
574
575 - (id) initWithView:(UIView *)view database:(Database *)database delegate:(id)delegate;
576
577 @end
578
579 @implementation ConfirmationView
580
581 - (void) dealloc {
582 [transition_ release];
583 [overlay_ release];
584 [navbar_ release];
585 [table_ release];
586 [fields_ release];
587 if (essential_ != nil)
588 [essential_ release];
589 [super dealloc];
590 }
591
592 - (void) cancel {
593 [transition_ transition:7 toView:nil];
594 [delegate_ cancel];
595 }
596
597 - (void) transitionViewDidComplete:(UITransitionView*)view fromView:(UIView*)from toView:(UIView*)to {
598 if (from != nil && to == nil)
599 [self removeFromSuperview];
600 }
601
602 - (void) navigationBar:(UINavigationBar *)navbar buttonClicked:(int)button {
603 switch (button) {
604 case 0:
605 if (essential_ != nil)
606 [essential_ popupAlertAnimated:YES];
607 else
608 [delegate_ confirm];
609 break;
610
611 case 1:
612 [self cancel];
613 break;
614 }
615 }
616
617 - (void) alertSheet:(UIAlertSheet *)sheet buttonClicked:(int)button {
618 [essential_ dismiss];
619 [self cancel];
620 }
621
622 - (int) numberOfGroupsInPreferencesTable:(UIPreferencesTable *)table {
623 return 2;
624 }
625
626 - (NSString *) preferencesTable:(UIPreferencesTable *)table titleForGroup:(int)group {
627 switch (group) {
628 case 0: return @"Statistics";
629 case 1: return @"Modifications";
630
631 default: _assert(false);
632 }
633 }
634
635 - (int) preferencesTable:(UIPreferencesTable *)table numberOfRowsInGroup:(int)group {
636 switch (group) {
637 case 0: return 3;
638 case 1: return [fields_ count];
639
640 default: _assert(false);
641 }
642 }
643
644 - (float) preferencesTable:(UIPreferencesTable *)table heightForRow:(int)row inGroup:(int)group withProposedHeight:(float)proposed {
645 if (group != 1 || row == -1)
646 return proposed;
647 else {
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;
651 }
652 }
653
654 - (UIPreferencesTableCell *) preferencesTable:(UIPreferencesTable *)table cellForRow:(int)row inGroup:(int)group {
655 UIPreferencesTableCell *cell = [[[UIPreferencesTableCell alloc] init] autorelease];
656 [cell setShowSelection:NO];
657
658 switch (group) {
659 case 0: switch (row) {
660 case 0: {
661 [cell setTitle:@"Downloading"];
662 [cell setValue:SizeString([database_ fetcher].FetchNeeded())];
663 } break;
664
665 case 1: {
666 [cell setTitle:@"Resuming At"];
667 [cell setValue:SizeString([database_ fetcher].PartialPresent())];
668 } break;
669
670 case 2: {
671 double size([database_ cache]->UsrSize());
672
673 if (size < 0) {
674 [cell setTitle:@"Disk Freeing"];
675 [cell setValue:SizeString(-size)];
676 } else {
677 [cell setTitle:@"Disk Using"];
678 [cell setValue:SizeString(size)];
679 }
680 } break;
681
682 default: _assert(false);
683 } break;
684
685 case 1:
686 _assert(size_t(row) < [fields_ count]);
687 [cell setTitle:[[fields_ allKeys] objectAtIndex:row]];
688 [cell addSubview:[[fields_ allValues] objectAtIndex:row]];
689 break;
690
691 default: _assert(false);
692 }
693
694 return cell;
695 }
696
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;
701
702 transition_ = [[UITransitionView alloc] initWithFrame:[self bounds]];
703 [self addSubview:transition_];
704
705 overlay_ = [[UIView alloc] initWithFrame:[transition_ bounds]];
706
707 CGSize navsize = [UINavigationBar defaultSize];
708 CGRect navrect = {{0, 0}, navsize};
709 CGRect bounds = [overlay_ bounds];
710
711 navbar_ = [[UINavigationBar alloc] initWithFrame:navrect];
712 [navbar_ setBarStyle:1];
713 [navbar_ setDelegate:self];
714
715 UINavigationItem *navitem = [[[UINavigationItem alloc] initWithTitle:@"Confirm"] autorelease];
716 [navbar_ pushNavigationItem:navitem];
717 [navbar_ showButtonsWithLeftTitle:@"Cancel" rightTitle:@"Confirm"];
718
719 fields_ = [[NSMutableDictionary dictionaryWithCapacity:16] retain];
720
721 NSMutableArray *installing = [NSMutableArray arrayWithCapacity:16];
722 NSMutableArray *upgrading = [NSMutableArray arrayWithCapacity:16];
723 NSMutableArray *removing = [NSMutableArray arrayWithCapacity:16];
724
725 bool essential(false);
726
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)
737 essential = true;
738 }
739 }
740
741 if (!essential)
742 essential_ = nil;
743 else {
744 essential_ = [[UIAlertSheet alloc]
745 initWithTitle:@"Unable to Comply"
746 buttons:[NSArray arrayWithObjects:@"Okay", nil]
747 defaultButtonIndex:0
748 delegate:self
749 context:self
750 ];
751
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."];
753 }
754
755 AddTextView(fields_, installing, @"Installing");
756 AddTextView(fields_, upgrading, @"Upgrading");
757 AddTextView(fields_, removing, @"Removing");
758
759 table_ = [[UIPreferencesTable alloc] initWithFrame:CGRectMake(
760 0, navsize.height, bounds.size.width, bounds.size.height - navsize.height
761 )];
762
763 [table_ setReusesTableCells:YES];
764 [table_ setDataSource:self];
765 [table_ reloadData];
766
767 [overlay_ addSubview:navbar_];
768 [overlay_ addSubview:table_];
769
770 [view addSubview:self];
771
772 [transition_ setDelegate:self];
773
774 UIView *blank = [[[UIView alloc] initWithFrame:[transition_ bounds]] autorelease];
775 [transition_ transition:0 toView:blank];
776 [transition_ transition:3 toView:overlay_];
777 } return self;
778 }
779
780 @end
781 /* }}} */
782 /* Package View {{{ */
783 @interface PackageView : UIView {
784 UIPreferencesTable *table_;
785 Package *package_;
786 Database *database_;
787 NSMutableArray *cells_;
788 id delegate_;
789 }
790
791 - (void) dealloc;
792
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;
797
798 - (BOOL) canSelectRow:(int)row;
799 - (void) tableRowSelected:(NSNotification *)notification;
800
801 - (id) initWithFrame:(struct CGRect)frame database:(Database *)database;
802 - (void) setPackage:(Package *)package;
803 - (void) setDelegate:(id)delegate;
804 @end
805
806 @implementation PackageView
807
808 - (void) dealloc {
809 if (package_ != nil)
810 [package_ release];
811 [table_ release];
812 [database_ release];
813 [cells_ release];
814 [super dealloc];
815 }
816
817 - (int) numberOfGroupsInPreferencesTable:(UIPreferencesTable *)table {
818 return 2;
819 }
820
821 - (NSString *) preferencesTable:(UIPreferencesTable *)table titleForGroup:(int)group {
822 switch (group) {
823 case 0: return @"Specifics";
824 case 1: return @"Description";
825
826 default: _assert(false);
827 }
828 }
829
830 - (int) preferencesTable:(UIPreferencesTable *)table numberOfRowsInGroup:(int)group {
831 switch (group) {
832 case 0: return 6;
833 case 1: return 1;
834
835 default: _assert(false);
836 }
837 }
838
839 - (UIPreferencesTableCell *) preferencesTable:(UIPreferencesTable *)table cellForRow:(int)row inGroup:(int)group {
840 UIPreferencesTableCell *cell;
841
842 switch (group) {
843 case 0: switch (row) {
844 case 0:
845 cell = [cells_ objectAtIndex:0];
846 [cell setTitle:@"Name"];
847 [cell setValue:[package_ name]];
848 break;
849
850 case 1: {
851 cell = [cells_ objectAtIndex:1];
852 [cell setTitle:@"Installed"];
853 NSString *installed([package_ installed]);
854 [cell setValue:(installed == nil ? @"n/a" : installed)];
855 } break;
856
857 case 2:
858 cell = [cells_ objectAtIndex:2];
859 [cell setTitle:@"Latest"];
860 [cell setValue:[package_ latest]];
861 break;
862
863 case 3:
864 cell = [cells_ objectAtIndex:3];
865 [cell setTitle:@"Section"];
866 [cell setValue:[package_ section]];
867 break;
868
869 case 4:
870 cell = [cells_ objectAtIndex:4];
871 [cell setTitle:@"Size"];
872 [cell setValue:SizeString([package_ size])];
873 break;
874
875 case 5:
876 cell = [cells_ objectAtIndex:5];
877 [cell setTitle:@"Maintainer"];
878 [cell setValue:[[package_ maintainer] name]];
879 [cell setShowDisclosure:YES];
880 [cell setShowSelection:YES];
881 break;
882
883 default: _assert(false);
884 } break;
885
886 case 1: switch (row) {
887 case 0:
888 cell = [cells_ objectAtIndex:6];
889 [cell setTitle:nil];
890 [cell setValue:[package_ tagline]];
891 break;
892
893 case 1:
894 cell = [cells_ objectAtIndex:7];
895 [cell setTitle:@"Description"];
896 [cell setValue:[package_ description]];
897 break;
898 } break;
899
900 default: _assert(false);
901 }
902
903 return cell;
904 }
905
906 - (BOOL) canSelectRow:(int)row {
907 return YES;
908 }
909
910 - (void) tableRowSelected:(NSNotification *)notification {
911 switch ([table_ selectedRow]) {
912 case 5:
913 [delegate_ openURL:[NSURL URLWithString:[NSString stringWithFormat:@"mailto:%@?subject=%@",
914 [[package_ maintainer] email],
915 [[NSString stringWithFormat:@"regarding apt package \"%@\"", [package_ name]] stringByAddingPercentEscapes]
916 ]]];
917 break;
918 }
919 }
920
921 - (id) initWithFrame:(struct CGRect)frame database:(Database *)database {
922 if ((self = [super initWithFrame:frame]) != nil) {
923 database_ = [database retain];
924
925 table_ = [[UIPreferencesTable alloc] initWithFrame:[self bounds]];
926 [self addSubview:table_];
927
928 [table_ setDataSource:self];
929 [table_ setDelegate:self];
930
931 cells_ = [[NSMutableArray arrayWithCapacity:16] retain];
932
933 for (unsigned i = 0; i != 8; ++i) {
934 UIPreferencesTableCell *cell = [[[UIPreferencesTableCell alloc] init] autorelease];
935 [cell setShowSelection:NO];
936 [cells_ addObject:cell];
937 }
938 } return self;
939 }
940
941 - (void) setPackage:(Package *)package {
942 package_ = [package retain];
943 [table_ reloadData];
944 }
945
946 - (void) setDelegate:(id)delegate {
947 delegate_ = delegate;
948 }
949
950 @end
951 /* }}} */
952 /* Package Cell {{{ */
953 @protocol PackageCellDelegate
954 - (NSString *) versionWithPackage:(Package *)package;
955 @end
956
957 @interface PackageCell : UITableCell {
958 UITextLabel *name_;
959 UIRightTextLabel *version_;
960 UITextLabel *description_;
961 }
962
963 - (void) dealloc;
964
965 - (PackageCell *) initWithPackage:(Package *)package delegate:(id)delegate;
966
967 - (void) _setSelected:(float)fraction;
968 - (void) setSelected:(BOOL)selected;
969 - (void) setSelected:(BOOL)selected withFade:(BOOL)fade;
970 - (void) _setSelectionFadeFraction:(float)fraction;
971
972 @end
973
974 @implementation PackageCell
975
976 - (void) dealloc {
977 [name_ release];
978 [version_ release];
979 [description_ release];
980 [super dealloc];
981 }
982
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);
988
989 CGColorSpaceRef space = CGColorSpaceCreateDeviceRGB();
990 float clear[] = {0, 0, 0, 0};
991
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];
996
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];
1001
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];
1006
1007 [self addSubview:name_];
1008 [self addSubview:version_];
1009 [self addSubview:description_];
1010
1011 CFRelease(small);
1012 CFRelease(large);
1013 CFRelease(bold);
1014 } return self;
1015 }
1016
1017 - (void) _setSelected:(float)fraction {
1018 CGColorSpaceRef space = CGColorSpaceCreateDeviceRGB();
1019
1020 float black[] = {
1021 interpolate(0.0, 1.0, fraction),
1022 interpolate(0.0, 1.0, fraction),
1023 interpolate(0.0, 1.0, fraction),
1024 1.0};
1025
1026 float blue[] = {
1027 interpolate(0.2, 1.0, fraction),
1028 interpolate(0.2, 1.0, fraction),
1029 interpolate(1.0, 1.0, fraction),
1030 1.0};
1031
1032 float gray[] = {
1033 interpolate(0.4, 1.0, fraction),
1034 interpolate(0.4, 1.0, fraction),
1035 interpolate(0.4, 1.0, fraction),
1036 1.0};
1037
1038 [name_ setColor:CGColorCreate(space, black)];
1039 [version_ setColor:CGColorCreate(space, blue)];
1040 [description_ setColor:CGColorCreate(space, gray)];
1041 }
1042
1043 - (void) setSelected:(BOOL)selected {
1044 [self _setSelected:(selected ? 1.0 : 0.0)];
1045 [super setSelected:selected];
1046 }
1047
1048 - (void) setSelected:(BOOL)selected withFade:(BOOL)fade {
1049 if (!fade)
1050 [self _setSelected:(selected ? 1.0 : 0.0)];
1051 [super setSelected:selected withFade:fade];
1052 }
1053
1054 - (void) _setSelectionFadeFraction:(float)fraction {
1055 [self _setSelected:fraction];
1056 [super _setSelectionFadeFraction:fraction];
1057 }
1058
1059 @end
1060 /* }}} */
1061 /* Sources View {{{ */
1062 @interface SourcesView : ResetView {
1063 UISectionList *list_;
1064 Database *database_;
1065 id delegate_;
1066 NSMutableArray *sources_;
1067 }
1068
1069 - (void) navigationBar:(UINavigationBar *)navbar buttonClicked:(int)button;
1070 - (void) dealloc;
1071 - (id) initWithFrame:(CGRect)frame database:(Database *)database;
1072 - (void) setDelegate:(id)delegate;
1073 - (void) reloadData;
1074 - (NSString *) leftTitle;
1075 - (NSString *) rightTitle;
1076 @end
1077
1078 @implementation SourcesView
1079
1080 - (void) navigationBar:(UINavigationBar *)navbar buttonClicked:(int)button {
1081 switch (button) {
1082 case 0:
1083 break;
1084
1085 case 1:
1086 [delegate_ update];
1087 break;
1088 }
1089 }
1090
1091 - (void) dealloc {
1092 if (sources_ != nil)
1093 [sources_ release];
1094 [list_ release];
1095 [super dealloc];
1096 }
1097
1098 - (id) initWithFrame:(CGRect)frame database:(Database *)database {
1099 if ((self = [super initWithFrame:frame]) != nil) {
1100 database_ = database;
1101 sources_ = nil;
1102
1103 CGSize navsize = [UINavigationBar defaultSize];
1104 CGRect navrect = {{0, 0}, navsize};
1105 CGRect bounds = [self bounds];
1106
1107 navbar_ = [[UINavigationBar alloc] initWithFrame:navrect];
1108 [self addSubview:navbar_];
1109
1110 [navbar_ setBarStyle:1];
1111 [navbar_ setDelegate:self];
1112
1113 UINavigationItem *navitem = [[[UINavigationItem alloc] initWithTitle:@"Sources"] autorelease];
1114 [navbar_ pushNavigationItem:navitem];
1115
1116 list_ = [[UISectionList alloc] initWithFrame:CGRectMake(
1117 0, navsize.height, bounds.size.width, bounds.size.height - navsize.height
1118 )];
1119
1120 [list_ setDataSource:self];
1121 //[list_ setShouldHideHeaderInShortLists:NO];
1122 } return self;
1123 }
1124
1125 - (void) setDelegate:(id)delegate {
1126 delegate_ = delegate;
1127 }
1128
1129 - (void) reloadData {
1130 pkgSourceList list;
1131 _assert(list.ReadMainList());
1132
1133 sources_ = [[NSMutableArray arrayWithCapacity:16] retain];
1134
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");
1138
1139 debReleaseIndex *dindex(dynamic_cast<debReleaseIndex *>(index));
1140 if (dindex == NULL)
1141 continue;
1142
1143 fprintf(stderr, " \"%s\"\n", dindex->MetaIndexFile("Release").c_str());
1144
1145 std::ifstream release(dindex->MetaIndexFile("Release").c_str());
1146 std::string line;
1147 while (std::getline(release, line)) {
1148 std::string::size_type colon(line.find(':'));
1149 if (colon == std::string::npos)
1150 continue;
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;
1156 }
1157 }
1158
1159 [self resetView];
1160 }
1161
1162 - (NSString *) leftTitle {
1163 return @"Refresh All";
1164 }
1165
1166 - (NSString *) rightTitle {
1167 return @"Edit";
1168 }
1169
1170 @end
1171 /* }}} */
1172
1173 @implementation Database
1174
1175 - (void) _readStatus:(NSNumber *)fd {
1176 NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init];
1177
1178 __gnu_cxx::stdio_filebuf<char> ib([fd intValue], std::ios::in);
1179 std::istream is(&ib);
1180 std::string line;
1181
1182 const char *error;
1183 int offset;
1184 pcre *code = pcre_compile("^([^:]*):([^:]*):([^:]*):(.*)$", 0, &error, &offset, NULL);
1185
1186 pcre_extra *study = NULL;
1187 int capture;
1188 pcre_fullinfo(code, study, PCRE_INFO_CAPTURECOUNT, &capture);
1189 int matches[(capture + 1) * 3];
1190
1191 while (std::getline(is, line)) {
1192 const char *data(line.c_str());
1193
1194 _assert(pcre_exec(code, study, data, line.size(), 0, 0, matches, sizeof(matches) / sizeof(matches[0])) >= 0);
1195
1196 std::istringstream buffer(line.substr(matches[6], matches[7] - matches[6]));
1197 float percent;
1198 buffer >> percent;
1199 [delegate_ setPercent:(percent / 100)];
1200
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]));
1203
1204 if (type == "pmerror")
1205 [delegate_ setError:string];
1206 else if (type == "pmstatus")
1207 [delegate_ setTitle:string];
1208 else if (type == "pmconffile")
1209 ;
1210 else _assert(false);
1211 }
1212
1213 [pool release];
1214 }
1215
1216 - (void) _readOutput:(NSNumber *)fd {
1217 NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init];
1218
1219 __gnu_cxx::stdio_filebuf<char> ib([fd intValue], std::ios::in);
1220 std::istream is(&ib);
1221 std::string line;
1222
1223 while (std::getline(is, line))
1224 [delegate_ addOutput:[NSString stringWithCString:line.c_str()]];
1225
1226 [pool release];
1227 }
1228
1229 - (Package *) packageWithName:(NSString *)name {
1230 pkgCache::PkgIterator iterator(cache_->FindPkg([name cString]));
1231 return iterator.end() ? nil : [Package packageWithIterator:iterator database:self];
1232 }
1233
1234 - (Database *) init {
1235 if ((self = [super init]) != nil) {
1236 records_ = NULL;
1237 resolver_ = NULL;
1238 fetcher_ = NULL;
1239 lock_ = NULL;
1240
1241 int fds[2];
1242
1243 _assert(pipe(fds) != -1);
1244 statusfd_ = fds[1];
1245
1246 [NSThread
1247 detachNewThreadSelector:@selector(_readStatus:)
1248 toTarget:self
1249 withObject:[[NSNumber numberWithInt:fds[0]] retain]
1250 ];
1251
1252 _assert(pipe(fds) != -1);
1253 _assert(dup2(fds[1], 1) != -1);
1254 _assert(close(fds[1]) != -1);
1255
1256 [NSThread
1257 detachNewThreadSelector:@selector(_readOutput:)
1258 toTarget:self
1259 withObject:[[NSNumber numberWithInt:fds[0]] retain]
1260 ];
1261 } return self;
1262 }
1263
1264 - (pkgCacheFile &) cache {
1265 return cache_;
1266 }
1267
1268 - (pkgRecords *) records {
1269 return records_;
1270 }
1271
1272 - (pkgProblemResolver *) resolver {
1273 return resolver_;
1274 }
1275
1276 - (pkgAcquire &) fetcher {
1277 return *fetcher_;
1278 }
1279
1280 - (void) reloadData {
1281 _error->Discard();
1282 manager_ = NULL;
1283 delete lock_;
1284 delete fetcher_;
1285 delete resolver_;
1286 delete records_;
1287 cache_.Close();
1288 cache_.Open(progress_, true);
1289 records_ = new pkgRecords(cache_);
1290 resolver_ = new pkgProblemResolver(cache_);
1291 fetcher_ = new pkgAcquire(&status_);
1292 lock_ = NULL;
1293 }
1294
1295 - (void) prepare {
1296 pkgRecords records(cache_);
1297
1298 lock_ = new FileFd();
1299 lock_->Fd(GetLock(_config->FindDir("Dir::Cache::Archives") + "lock"));
1300 _assert(!_error->PendingError());
1301
1302 pkgSourceList list;
1303 _assert(list.ReadMainList());
1304
1305 manager_ = (_system->CreatePM(cache_));
1306 _assert(manager_->GetArchives(fetcher_, &list, &records));
1307 _assert(!_error->PendingError());
1308 }
1309
1310 - (void) perform {
1311 if (fetcher_->Run(PulseInterval_) != pkgAcquire::Continue)
1312 return;
1313
1314 _system->UnLock();
1315 pkgPackageManager::OrderResult result = manager_->DoInstall(statusfd_);
1316
1317 if (result == pkgPackageManager::Failed)
1318 return;
1319 if (_error->PendingError())
1320 return;
1321 if (result != pkgPackageManager::Completed)
1322 return;
1323 }
1324
1325 - (void) update {
1326 pkgSourceList list;
1327 _assert(list.ReadMainList());
1328
1329 FileFd lock;
1330 lock.Fd(GetLock(_config->FindDir("Dir::State::Lists") + "lock"));
1331 _assert(!_error->PendingError());
1332
1333 pkgAcquire fetcher(&status_);
1334 _assert(list.GetIndexes(&fetcher));
1335 _assert(fetcher.Run(PulseInterval_) != pkgAcquire::Failed);
1336
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();
1341 failed = true;
1342 }
1343
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/"));
1347 }
1348 }
1349
1350 - (void) upgrade {
1351 _assert(cache_->DelCount() == 0 && cache_->InstCount() == 0);
1352 _assert(pkgApplyStatus(cache_));
1353
1354 if (cache_->BrokenCount() != 0) {
1355 _assert(pkgFixBroken(cache_));
1356 _assert(cache_->BrokenCount() == 0);
1357 _assert(pkgMinimizeUpgrade(cache_));
1358 }
1359
1360 _assert(pkgDistUpgrade(cache_));
1361
1362 //InstallPackages(cache_, true);
1363 }
1364
1365 - (void) setDelegate:(id)delegate {
1366 delegate_ = delegate;
1367 status_.setDelegate(delegate);
1368 progress_.setDelegate(delegate);
1369 }
1370
1371 @end
1372
1373 /* Progress Data {{{ */
1374 @interface ProgressData : NSObject {
1375 SEL selector_;
1376 id target_;
1377 id object_;
1378 }
1379
1380 - (ProgressData *) initWithSelector:(SEL)selector target:(id)target object:(id)object;
1381
1382 - (SEL) selector;
1383 - (id) target;
1384 - (id) object;
1385 @end
1386
1387 @implementation ProgressData
1388
1389 - (ProgressData *) initWithSelector:(SEL)selector target:(id)target object:(id)object {
1390 if ((self = [super init]) != nil) {
1391 selector_ = selector;
1392 target_ = target;
1393 object_ = object;
1394 } return self;
1395 }
1396
1397 - (SEL) selector {
1398 return selector_;
1399 }
1400
1401 - (id) target {
1402 return target_;
1403 }
1404
1405 - (id) object {
1406 return object_;
1407 }
1408
1409 @end
1410 /* }}} */
1411 /* Progress View {{{ */
1412 @interface ProgressView : UIView <
1413 ProgressDelegate
1414 > {
1415 UIView *view_;
1416 UIView *background_;
1417 UITransitionView *transition_;
1418 UIView *overlay_;
1419 UINavigationBar *navbar_;
1420 UIProgressBar *progress_;
1421 UITextView *output_;
1422 UITextLabel *status_;
1423 id delegate_;
1424 UIAlertSheet *alert_;
1425 }
1426
1427 - (void) dealloc;
1428
1429 - (ProgressView *) initWithFrame:(struct CGRect)frame delegate:(id)delegate;
1430 - (void) setContentView:(UIView *)view;
1431 - (void) resetView;
1432
1433 - (void) alertSheet:(UIAlertSheet *)sheet buttonClicked:(int)button;
1434
1435 - (void) _retachThread;
1436 - (void) _detachNewThreadData:(ProgressData *)data;
1437 - (void) detachNewThreadSelector:(SEL)selector toTarget:(id)target withObject:(id)object;
1438
1439 - (void) setError:(NSString *)error;
1440 - (void) _setError:(NSString *)error;
1441
1442 - (void) setTitle:(NSString *)title;
1443 - (void) _setTitle:(NSString *)title;
1444
1445 - (void) setPercent:(float)percent;
1446 - (void) _setPercent:(NSNumber *)percent;
1447
1448 - (void) addOutput:(NSString *)output;
1449 - (void) _addOutput:(NSString *)output;
1450
1451 - (void) setStatusFail;
1452 @end
1453
1454 @protocol ProgressViewDelegate
1455 - (void) progressViewIsComplete:(ProgressView *)sender;
1456 @end
1457
1458 @implementation ProgressView
1459
1460 - (void) dealloc {
1461 [view_ release];
1462 [background_ release];
1463 [transition_ release];
1464 [overlay_ release];
1465 [navbar_ release];
1466 [progress_ release];
1467 [output_ release];
1468 [status_ release];
1469 [super dealloc];
1470 }
1471
1472 - (ProgressView *) initWithFrame:(struct CGRect)frame delegate:(id)delegate {
1473 if ((self = [super initWithFrame:frame]) != nil) {
1474 delegate_ = delegate;
1475 alert_ = nil;
1476
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};
1481
1482 background_ = [[UIView alloc] initWithFrame:[self bounds]];
1483 [background_ setBackgroundColor:CGColorCreate(space, black)];
1484 [self addSubview:background_];
1485
1486 transition_ = [[UITransitionView alloc] initWithFrame:[self bounds]];
1487 [self addSubview:transition_];
1488
1489 overlay_ = [[UIView alloc] initWithFrame:[transition_ bounds]];
1490
1491 CGSize navsize = [UINavigationBar defaultSize];
1492 CGRect navrect = {{0, 0}, navsize};
1493
1494 navbar_ = [[UINavigationBar alloc] initWithFrame:navrect];
1495 [overlay_ addSubview:navbar_];
1496
1497 [navbar_ setBarStyle:1];
1498 [navbar_ setDelegate:self];
1499
1500 UINavigationItem *navitem = [[[UINavigationItem alloc] initWithTitle:@"Running..."] autorelease];
1501 [navbar_ pushNavigationItem:navitem];
1502
1503 CGRect bounds = [overlay_ bounds];
1504 CGSize prgsize = [UIProgressBar defaultSize];
1505
1506 CGRect prgrect = {{
1507 (bounds.size.width - prgsize.width) / 2,
1508 bounds.size.height - prgsize.height - 20
1509 }, prgsize};
1510
1511 progress_ = [[UIProgressBar alloc] initWithFrame:prgrect];
1512 [overlay_ addSubview:progress_];
1513
1514 status_ = [[UITextLabel alloc] initWithFrame:CGRectMake(
1515 10,
1516 bounds.size.height - prgsize.height - 50,
1517 bounds.size.width - 20,
1518 24
1519 )];
1520
1521 [status_ setColor:CGColorCreate(space, white)];
1522 [status_ setBackgroundColor:CGColorCreate(space, clear)];
1523
1524 [status_ setCentersHorizontally:YES];
1525 //[status_ setFont:font];
1526
1527 output_ = [[UITextView alloc] initWithFrame:CGRectMake(
1528 10,
1529 navrect.size.height + 20,
1530 bounds.size.width - 20,
1531 bounds.size.height - navsize.height - 62 - navrect.size.height
1532 )];
1533
1534 //[output_ setTextFont:@"Courier New"];
1535 [output_ setTextSize:12];
1536
1537 [output_ setTextColor:CGColorCreate(space, white)];
1538 [output_ setBackgroundColor:CGColorCreate(space, clear)];
1539
1540 [output_ setMarginTop:0];
1541 [output_ setAllowsRubberBanding:YES];
1542
1543 [overlay_ addSubview:output_];
1544 [overlay_ addSubview:status_];
1545
1546 [progress_ setStyle:0];
1547 } return self;
1548 }
1549
1550 - (void) setContentView:(UIView *)view {
1551 view_ = view;
1552 }
1553
1554 - (void) resetView {
1555 [transition_ transition:6 toView:view_];
1556 }
1557
1558 - (void) alertSheet:(UIAlertSheet *)sheet buttonClicked:(int)button {
1559 [alert_ dismiss];
1560 [alert_ release];
1561 alert_ = nil;
1562 }
1563
1564 - (void) _retachThread {
1565 [delegate_ progressViewIsComplete:self];
1566 [self resetView];
1567 }
1568
1569 - (void) _detachNewThreadData:(ProgressData *)data {
1570 NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init];
1571
1572 [[data target] performSelector:[data selector] withObject:[data object]];
1573 [self performSelectorOnMainThread:@selector(_retachThread) withObject:nil waitUntilDone:YES];
1574
1575 [data release];
1576 [pool release];
1577 }
1578
1579 - (void) detachNewThreadSelector:(SEL)selector toTarget:(id)target withObject:(id)object {
1580 [status_ setText:nil];
1581 [output_ setText:@""];
1582 [progress_ setProgress:0];
1583
1584 [transition_ transition:6 toView:overlay_];
1585
1586 [NSThread
1587 detachNewThreadSelector:@selector(_detachNewThreadData:)
1588 toTarget:self
1589 withObject:[[ProgressData alloc]
1590 initWithSelector:selector
1591 target:target
1592 object:object
1593 ]
1594 ];
1595 }
1596
1597 - (void) setStatusFail {
1598 }
1599
1600 - (void) setError:(NSString *)error {
1601 [self
1602 performSelectorOnMainThread:@selector(_setError:)
1603 withObject:error
1604 waitUntilDone:YES
1605 ];
1606 }
1607
1608 - (void) _setError:(NSString *)error {
1609 _assert(alert_ == nil);
1610
1611 alert_ = [[UIAlertSheet alloc]
1612 initWithTitle:@"Package Error"
1613 buttons:[NSArray arrayWithObjects:@"Okay", nil]
1614 defaultButtonIndex:0
1615 delegate:self
1616 context:self
1617 ];
1618
1619 [alert_ setBodyText:error];
1620 [alert_ popupAlertAnimated:YES];
1621 }
1622
1623 - (void) setTitle:(NSString *)title {
1624 [self
1625 performSelectorOnMainThread:@selector(_setTitle:)
1626 withObject:title
1627 waitUntilDone:YES
1628 ];
1629 }
1630
1631 - (void) _setTitle:(NSString *)title {
1632 [status_ setText:[title stringByAppendingString:@"..."]];
1633 }
1634
1635 - (void) setPercent:(float)percent {
1636 [self
1637 performSelectorOnMainThread:@selector(_setPercent:)
1638 withObject:[NSNumber numberWithFloat:percent]
1639 waitUntilDone:YES
1640 ];
1641 }
1642
1643 - (void) _setPercent:(NSNumber *)percent {
1644 [progress_ setProgress:[percent floatValue]];
1645 }
1646
1647 - (void) addOutput:(NSString *)output {
1648 [self
1649 performSelectorOnMainThread:@selector(_addOutput:)
1650 withObject:output
1651 waitUntilDone:YES
1652 ];
1653 }
1654
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];
1660 }
1661
1662 @end
1663 /* }}} */
1664
1665 @protocol PackagesViewDelegate
1666 - (void) perform;
1667 - (void) update;
1668 - (void) openURL:(NSString *)url;
1669 @end
1670
1671 /* PackagesView {{{ */
1672 @interface PackagesView : ResetView <
1673 PackageCellDelegate
1674 > {
1675 Database *database_;
1676 NSMutableArray *packages_;
1677 NSMutableArray *sections_;
1678 id delegate_;
1679 UISectionList *list_;
1680 UITransitionView *transition_;
1681 Package *package_;
1682 NSString *pkgname_;
1683 PackageView *pkgview_;
1684 }
1685
1686 - (int) numberOfSectionsInSectionList:(UISectionList *)list;
1687 - (NSString *) sectionList:(UISectionList *)list titleForSection:(int)section;
1688 - (int) sectionList:(UISectionList *)list rowForSection:(int)section;
1689
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;
1695
1696 - (void) navigationBar:(UINavigationBar *)navbar buttonClicked:(int)button;
1697 - (void) navigationBar:(UINavigationBar *)navbar poppedItem:(UINavigationItem *)item;
1698
1699 - (id) initWithFrame:(struct CGRect)frame database:(Database *)database;
1700 - (void) setDelegate:(id)delegate;
1701 - (void) deselect;
1702 - (void) reloadData:(BOOL)reset;
1703
1704 - (NSString *) title;
1705 - (void) perform:(Package *)package;
1706 - (void) addPackage:(Package *)package;
1707 - (NSString *) versionWithPackage:(Package *)package;
1708 @end
1709
1710 @implementation PackagesView
1711
1712 - (int) numberOfSectionsInSectionList:(UISectionList *)list {
1713 return [sections_ count];
1714 }
1715
1716 - (NSString *) sectionList:(UISectionList *)list titleForSection:(int)section {
1717 return [[sections_ objectAtIndex:section] name];
1718 }
1719
1720 - (int) sectionList:(UISectionList *)list rowForSection:(int)section {
1721 return [[sections_ objectAtIndex:section] row];
1722 }
1723
1724 - (int) numberOfRowsInTable:(UITable *)table {
1725 return [packages_ count];
1726 }
1727
1728 - (float) table:(UITable *)table heightForRow:(int)row {
1729 return 64;
1730 }
1731
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];
1735 return cell;
1736 }
1737
1738 - (BOOL) table:(UITable *)table showDisclosureForRow:(int)row {
1739 return YES;
1740 }
1741
1742 - (void) tableRowSelected:(NSNotification*)notification {
1743 int row = [[list_ table] selectedRow];
1744 if (row == INT_MAX)
1745 return;
1746
1747 package_ = [packages_ objectAtIndex:row];
1748 pkgname_ = [[package_ name] retain];
1749
1750 UINavigationItem *navitem = [[UINavigationItem alloc] initWithTitle:[package_ name]];
1751 [navbar_ pushNavigationItem:navitem];
1752
1753 [navbar_ showButtonsWithLeftTitle:nil rightTitle:[self title]];
1754
1755 [pkgview_ setPackage:package_];
1756 [transition_ transition:1 toView:pkgview_];
1757 }
1758
1759 - (void) navigationBar:(UINavigationBar *)navbar buttonClicked:(int)button {
1760 if (button == 0) {
1761 [self perform:package_];
1762
1763 pkgProblemResolver *resolver = [database_ resolver];
1764
1765 resolver->InstallProtect();
1766 if (!resolver->Resolve(true))
1767 _error->Discard();
1768
1769 [delegate_ perform];
1770 }
1771 }
1772
1773 - (void) navigationBar:(UINavigationBar *)navbar poppedItem:(UINavigationItem *)item {
1774 [self deselect];
1775 [super navigationBar:navbar poppedItem:item];
1776 }
1777
1778 - (id) initWithFrame:(struct CGRect)frame database:(Database *)database {
1779 if ((self = [super initWithFrame:frame]) != nil) {
1780 database_ = [database retain];
1781
1782 struct CGRect bounds = [self bounds];
1783 CGSize navsize = [UINavigationBar defaultSize];
1784 CGRect navrect = {{0, 0}, navsize};
1785
1786 navbar_ = [[UINavigationBar alloc] initWithFrame:navrect];
1787 [self addSubview:navbar_];
1788
1789 [navbar_ setBarStyle:1];
1790 [navbar_ setDelegate:self];
1791
1792 UINavigationItem *navitem = [[[UINavigationItem alloc] initWithTitle:[self title]] autorelease];
1793 [navbar_ pushNavigationItem:navitem];
1794 [navitem setBackButtonTitle:@"Packages"];
1795
1796 transition_ = [[UITransitionView alloc] initWithFrame:CGRectMake(
1797 bounds.origin.x, bounds.origin.y + navsize.height, bounds.size.width, bounds.size.height - navsize.height
1798 )];
1799
1800 [self addSubview:transition_];
1801
1802 list_ = [[UISectionList alloc] initWithFrame:[transition_ bounds] showSectionIndex:NO];
1803 [list_ setDataSource:self];
1804 [list_ setShouldHideHeaderInShortLists:NO];
1805
1806 [transition_ transition:0 toView:list_];
1807
1808 UITableColumn *column = [[UITableColumn alloc]
1809 initWithTitle:@"Name"
1810 identifier:@"name"
1811 width:frame.size.width
1812 ];
1813
1814 UITable *table = [list_ table];
1815 [table setSeparatorStyle:1];
1816 [table addTableColumn:column];
1817 [table setDelegate:self];
1818
1819 pkgview_ = [[PackageView alloc] initWithFrame:[transition_ bounds] database:database_];
1820 } return self;
1821 }
1822
1823 - (void) setDelegate:(id)delegate {
1824 delegate_ = delegate;
1825 [pkgview_ setDelegate:delegate];
1826 }
1827
1828 - (void) deselect {
1829 [transition_ transition:(resetting_ ? 0 : 2) toView:list_];
1830 UITable *table = [list_ table];
1831 [table selectRow:-1 byExtendingSelection:NO withFade:(resetting_ ? NO : YES)];
1832 package_ = nil;
1833 }
1834
1835 - (void) reloadData:(BOOL)reset {
1836 packages_ = [[NSMutableArray arrayWithCapacity:16] retain];
1837
1838 if (sections_ != nil) {
1839 [sections_ release];
1840 sections_ = nil;
1841 }
1842
1843 for (pkgCache::PkgIterator iterator = [database_ cache]->PkgBegin(); !iterator.end(); ++iterator)
1844 if (Package *package = [Package packageWithIterator:iterator database:database_])
1845 [self addPackage:package];
1846
1847 [packages_ sortUsingSelector:@selector(compareBySectionAndName:)];
1848 sections_ = [[NSMutableArray arrayWithCapacity:16] retain];
1849
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];
1854
1855 if (section == nil || ![[section name] isEqual:name]) {
1856 section = [[Section alloc] initWithName:name row:offset];
1857 [sections_ addObject:section];
1858 }
1859
1860 [section addPackage:package];
1861 }
1862
1863 [list_ reloadData];
1864 if (reset)
1865 [self resetView];
1866 else if (package_ != nil) {
1867 package_ = [database_ packageWithName:pkgname_];
1868 [pkgview_ setPackage:package_];
1869 }
1870 }
1871
1872 - (NSString *) title {
1873 return nil;
1874 }
1875
1876 - (void) perform:(Package *)package {
1877 }
1878
1879 - (void) addPackage:(Package *)package {
1880 [packages_ addObject:package];
1881 }
1882
1883 - (NSString *) versionWithPackage:(Package *)package {
1884 return nil;
1885 }
1886
1887 @end
1888 /* }}} */
1889
1890 /* InstallView {{{ */
1891 @interface InstallView : PackagesView {
1892 }
1893
1894 - (NSString *) title;
1895 - (void) addPackage:(Package *)package;
1896 - (void) perform:(Package *)package;
1897 - (NSString *) versionWithPackage:(Package *)package;
1898 @end
1899
1900 @implementation InstallView
1901
1902 - (NSString *) title {
1903 return @"Install";
1904 }
1905
1906 - (void) addPackage:(Package *)package {
1907 if ([package installed] == nil)
1908 [super addPackage:package];
1909 }
1910
1911 - (void) perform:(Package *)package {
1912 [package install];
1913 }
1914
1915 - (NSString *) versionWithPackage:(Package *)package {
1916 return [package latest];
1917 }
1918
1919 @end
1920 /* }}} */
1921 /* UpgradeView {{{ */
1922 @interface UpgradeView : PackagesView {
1923 }
1924
1925 - (NSString *) title;
1926 - (NSString *) leftTitle;
1927 - (void) addPackage:(Package *)package;
1928 - (void) perform:(Package *)package;
1929 - (NSString *) versionWithPackage:(Package *)package;
1930 @end
1931
1932 @implementation UpgradeView
1933
1934 - (NSString *) title {
1935 return @"Upgrade";
1936 }
1937
1938 - (NSString *) leftTitle {
1939 return @"Upgrade All";
1940 }
1941
1942 - (void) addPackage:(Package *)package {
1943 NSString *installed = [package installed];
1944 if (installed != nil && [[package latest] compare:installed] != NSOrderedSame)
1945 [super addPackage:package];
1946 }
1947
1948 - (void) perform:(Package *)package {
1949 [package install];
1950 }
1951
1952 - (NSString *) versionWithPackage:(Package *)package {
1953 return [package latest];
1954 }
1955
1956 @end
1957 /* }}} */
1958 /* UninstallView {{{ */
1959 @interface UninstallView : PackagesView {
1960 }
1961
1962 - (NSString *) title;
1963 - (void) addPackage:(Package *)package;
1964 - (void) perform:(Package *)package;
1965 - (NSString *) versionWithPackage:(Package *)package;
1966 @end
1967
1968 @implementation UninstallView
1969
1970 - (NSString *) title {
1971 return @"Uninstall";
1972 }
1973
1974 - (void) addPackage:(Package *)package {
1975 if ([package installed] != nil)
1976 [super addPackage:package];
1977 }
1978
1979 - (void) perform:(Package *)package {
1980 [package remove];
1981 }
1982
1983 - (NSString *) versionWithPackage:(Package *)package {
1984 return [package installed];
1985 }
1986
1987 @end
1988 /* }}} */
1989
1990 @interface Cydia : UIApplication <
1991 ConfirmationViewDelegate,
1992 PackagesViewDelegate,
1993 ProgressViewDelegate
1994 > {
1995 UIWindow *window_;
1996 UIView *underlay_;
1997 UIView *overlay_;
1998 UITransitionView *transition_;
1999 UIButtonBar *buttonbar_;
2000
2001 UIAlertSheet *alert_;
2002 ConfirmationView *confirm_;
2003
2004 Database *database_;
2005 ProgressView *progress_;
2006
2007 UIView *featured_;
2008 UINavigationBar *navbar_;
2009 UIScroller *scroller_;
2010 UIWebView *webview_;
2011 NSURL *url_;
2012
2013 InstallView *install_;
2014 UpgradeView *upgrade_;
2015 UninstallView *uninstall_;
2016 SourcesView *sources_;
2017 }
2018
2019 - (void) loadNews;
2020 - (void) reloadData:(BOOL)reset;
2021 - (void) perform;
2022 - (void) cancel;
2023 - (void) confirm;
2024 - (void) update;
2025
2026 - (void) progressViewIsComplete:(ProgressView *)progress;
2027
2028 - (void) navigationBar:(UINavigationBar *)navbar buttonClicked:(int)button;
2029 - (void) alertSheet:(UIAlertSheet *)sheet buttonClicked:(int)button;
2030 - (void) buttonBarItemTapped:(id)sender;
2031
2032 - (void) view:(UIView *)sender didSetFrame:(CGRect)frame;
2033 - (void) view:(UIView *)view didDrawInRect:(CGRect)rect duration:(float)duration;
2034
2035 - (void) applicationDidFinishLaunching:(id)unused;
2036 @end
2037
2038 #include <objc/objc-class.h>
2039
2040 @implementation Cydia
2041
2042 - (void) loadNews {
2043 NSMutableURLRequest *request = [NSMutableURLRequest
2044 requestWithURL:url_
2045 cachePolicy:NSURLRequestReloadIgnoringCacheData
2046 timeoutInterval:30.0
2047 ];
2048
2049 [request addValue:[NSString stringWithCString:Machine_] forHTTPHeaderField:@"X-Machine"];
2050 [request addValue:[NSString stringWithCString:SerialNumber_] forHTTPHeaderField:@"X-Serial-Number"];
2051
2052 [webview_ loadRequest:request];
2053 }
2054
2055 - (void) reloadData:(BOOL)reset {
2056 [database_ reloadData];
2057 [install_ reloadData:reset];
2058 [upgrade_ reloadData:reset];
2059 [uninstall_ reloadData:reset];
2060 [sources_ reloadData];
2061 }
2062
2063 - (void) perform {
2064 [database_ prepare];
2065 confirm_ = [[ConfirmationView alloc] initWithView:underlay_ database:database_ delegate:self];
2066 }
2067
2068 - (void) cancel {
2069 [self reloadData:NO];
2070 [confirm_ release];
2071 confirm_ = nil;
2072 }
2073
2074 - (void) confirm {
2075 [overlay_ removeFromSuperview];
2076
2077 [progress_
2078 detachNewThreadSelector:@selector(perform)
2079 toTarget:database_
2080 withObject:nil
2081 ];
2082 }
2083
2084 - (void) update {
2085 [progress_
2086 detachNewThreadSelector:@selector(update)
2087 toTarget:database_
2088 withObject:nil
2089 ];
2090 }
2091
2092 - (void) progressViewIsComplete:(ProgressView *)progress {
2093 [self reloadData:YES];
2094
2095 if (confirm_ != nil) {
2096 [underlay_ addSubview:overlay_];
2097 [confirm_ removeFromSuperview];
2098 [confirm_ release];
2099 confirm_ = nil;
2100 }
2101 }
2102
2103 - (void) navigationBar:(UINavigationBar *)navbar buttonClicked:(int)button {
2104 switch (button) {
2105 case 0:
2106 [self loadNews];
2107 break;
2108
2109 case 1:
2110 _assert(alert_ == nil);
2111
2112 alert_ = [[UIAlertSheet alloc]
2113 initWithTitle:@"About Cydia Packager"
2114 buttons:[NSArray arrayWithObjects:@"Close", nil]
2115 defaultButtonIndex:0
2116 delegate:self
2117 context:self
2118 ];
2119
2120 [alert_ setBodyText:
2121 @"Copyright (C) 2007\n"
2122 "Jay Freeman (saurik)\n"
2123 "saurik@saurik.com\n"
2124 "http://www.saurik.com/\n"
2125 "\n"
2126 "The Okori Group\n"
2127 "http://www.theokorigroup.com/\n"
2128 "\n"
2129 "College of Creative Studies,\n"
2130 "University of California,\n"
2131 "Santa Barbara\n"
2132 "http://www.ccs.ucsb.edu/\n"
2133 "\n"
2134 "Special Thanks:\n"
2135 "bad_, BHSPitMonkey, Cobra, core,\n"
2136 "Corona, cromas, Darken, dtzWill,\n"
2137 "francis, Godores, jerry, Kingstone,\n"
2138 "lounger, rockabilly, tman, Wbiggs"
2139 ];
2140
2141 [alert_ presentSheetFromButtonBar:buttonbar_];
2142 break;
2143 }
2144 }
2145
2146 - (void) alertSheet:(UIAlertSheet *)sheet buttonClicked:(int)button {
2147 [alert_ dismiss];
2148 [alert_ release];
2149 alert_ = nil;
2150 }
2151
2152 - (void) buttonBarItemTapped:(id)sender {
2153 UIView *view;
2154
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;
2161
2162 default:
2163 _assert(false);
2164 }
2165
2166 if ([view respondsToSelector:@selector(resetView)])
2167 [(id) view resetView];
2168 [transition_ transition:0 toView:view];
2169 }
2170
2171 - (void) view:(UIView *)view didSetFrame:(CGRect)frame {
2172 [scroller_ setContentSize:frame.size];
2173 }
2174
2175 - (void) view:(UIView *)view didDrawInRect:(CGRect)rect duration:(float)duration {
2176 [scroller_ setContentSize:[webview_ bounds].size];
2177 }
2178
2179 - (void) applicationDidFinishLaunching:(id)unused {
2180 _assert(pkgInitConfig(*_config));
2181 _assert(pkgInitSystem(*_config, _system));
2182
2183 alert_ = nil;
2184 confirm_ = nil;
2185
2186 CGRect screenrect = [UIHardware fullScreenApplicationContentRect];
2187 window_ = [[UIWindow alloc] initWithContentRect:screenrect];
2188
2189 [window_ orderFront: self];
2190 [window_ makeKey: self];
2191 [window_ _setHidden: NO];
2192
2193 progress_ = [[ProgressView alloc] initWithFrame:[window_ bounds] delegate:self];
2194 [window_ setContentView:progress_];
2195
2196 underlay_ = [[UIView alloc] initWithFrame:[progress_ bounds]];
2197 [progress_ setContentView:underlay_];
2198
2199 overlay_ = [[UIView alloc] initWithFrame:[underlay_ bounds]];
2200 [underlay_ addSubview:overlay_];
2201
2202 transition_ = [[UITransitionView alloc] initWithFrame:CGRectMake(
2203 0, 0, screenrect.size.width, screenrect.size.height - 48
2204 )];
2205
2206 [overlay_ addSubview:transition_];
2207
2208 featured_ = [[UIView alloc] initWithFrame:[transition_ bounds]];
2209
2210 CGSize navsize = [UINavigationBar defaultSize];
2211 CGRect navrect = {{0, 0}, navsize};
2212
2213 navbar_ = [[UINavigationBar alloc] initWithFrame:navrect];
2214 [featured_ addSubview:navbar_];
2215
2216 [navbar_ setBarStyle:1];
2217 [navbar_ setDelegate:self];
2218
2219 [navbar_ showButtonsWithLeftTitle:@"About" rightTitle:@"Reload"];
2220
2221 UINavigationItem *navitem = [[UINavigationItem alloc] initWithTitle:@"Featured"];
2222 [navbar_ pushNavigationItem:navitem];
2223
2224 struct CGRect subbounds = [featured_ bounds];
2225 subbounds.origin.y += navsize.height;
2226 subbounds.size.height -= navsize.height;
2227
2228 UIImageView *pinstripe = [[UIImageView alloc] initWithFrame:subbounds];
2229 [pinstripe setImage:[UIImage applicationImageNamed:@"pinstripe.png"]];
2230 [featured_ addSubview:pinstripe];
2231
2232 scroller_ = [[UIScroller alloc] initWithFrame:subbounds];
2233 [featured_ addSubview:scroller_];
2234
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];
2241
2242 webview_ = [[UIWebView alloc] initWithFrame:[scroller_ bounds]];
2243 [scroller_ addSubview:webview_];
2244
2245 [webview_ setTilingEnabled:YES];
2246 [webview_ setTileSize:CGSizeMake(screenrect.size.width, 500)];
2247 [webview_ setAutoresizes:YES];
2248 [webview_ setDelegate:self];
2249
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,
2259 nil],
2260
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,
2269 nil],
2270
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,
2279 nil],
2280
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,
2289 nil],
2290
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,
2299 nil],
2300 nil];
2301
2302 buttonbar_ = [[UIButtonBar alloc]
2303 initInView:overlay_
2304 withFrame:CGRectMake(
2305 0, screenrect.size.height - 48,
2306 screenrect.size.width, 48
2307 )
2308 withItemList:buttonitems
2309 ];
2310
2311 [buttonbar_ setDelegate:self];
2312 [buttonbar_ setBarStyle:1];
2313 [buttonbar_ setButtonBarTrackingMode:2];
2314
2315 int buttons[5] = {1, 2, 3, 4, 5};
2316 [buttonbar_ registerButtonGroup:0 withButtons:buttons withCount:5];
2317 [buttonbar_ showButtonGroup:0 withDuration:0];
2318
2319 for (int i = 0; i != 5; ++i)
2320 [[buttonbar_ viewWithTag:(i + 1)] setFrame:CGRectMake(
2321 i * 64 + 2, 1, 60, 48
2322 )];
2323
2324 [buttonbar_ showSelectionForButton:1];
2325 [transition_ transition:0 toView:featured_];
2326
2327 [overlay_ addSubview:buttonbar_];
2328
2329 database_ = [[Database alloc] init];
2330 [database_ setDelegate:progress_];
2331
2332 install_ = [[InstallView alloc] initWithFrame:[transition_ bounds] database:database_];
2333 [install_ setDelegate:self];
2334
2335 upgrade_ = [[UpgradeView alloc] initWithFrame:[transition_ bounds] database:database_];
2336 [upgrade_ setDelegate:self];
2337
2338 uninstall_ = [[UninstallView alloc] initWithFrame:[transition_ bounds] database:database_];
2339 [uninstall_ setDelegate:self];
2340
2341 sources_ = [[SourcesView alloc] initWithFrame:[transition_ bounds] database:database_];
2342 [sources_ setDelegate:self];
2343
2344 #if 0
2345
2346 UIAlertSheet *alert = [[UIAlertSheet alloc]
2347 initWithTitle:@"Alert Title"
2348 buttons:[NSArray arrayWithObjects:@"Yes", nil]
2349 defaultButtonIndex:0
2350 delegate:self
2351 context:self
2352 ];
2353
2354 NSLog(@"%p\n", [alert table]);
2355 [[alert table] setDelegate:self];
2356 [[alert table] reloadData];
2357
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];
2363
2364 #endif
2365
2366 [self reloadData:NO];
2367 [progress_ resetView];
2368
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];
2373
2374 url_ = [NSURL URLWithString:@"http://cydia.saurik.com/"];
2375 [self loadNews];
2376 }
2377
2378 @end
2379
2380 int main(int argc, char *argv[]) {
2381 NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init];
2382
2383 size_t size;
2384 sysctlbyname("hw.machine", NULL, &size, NULL, 0);
2385 char *machine = new char[size];
2386 sysctlbyname("hw.machine", machine, &size, NULL, 0);
2387 Machine_ = machine;
2388
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()));
2393 CFRelease(serial);
2394 }
2395
2396 IOObjectRelease(service);
2397 }
2398
2399 UIApplicationMain(argc, argv, [Cydia class]);
2400 [pool release];
2401 }