+- (void) alertSheet:(UIActionSheet *)sheet buttonClicked:(int)button {
+ NSString *context([sheet context]);
+
+ if ([context isEqualToString:@"missing"])
+ [sheet dismiss];
+ else if ([context isEqualToString:@"cancel"]) {
+ bool clear;
+
+ switch (button) {
+ case 1:
+ clear = false;
+ break;
+
+ case 2:
+ clear = true;
+ break;
+
+ default:
+ _assert(false);
+ }
+
+ [sheet dismiss];
+
+ @synchronized (self) {
+ if (clear)
+ [self _reloadData];
+ else {
+ Queuing_ = true;
+ [buttonbar_ setBadgeValue:CYLocalize("Q_D") forButton:4];
+ [book_ reloadData];
+ }
+
+ if (confirm_ != nil) {
+ [confirm_ release];
+ confirm_ = nil;
+ }
+ }
+ } else if ([context isEqualToString:@"fixhalf"]) {
+ switch (button) {
+ case 1:
+ @synchronized (self) {
+ for (Package *broken in broken_) {
+ [broken remove];
+
+ NSString *id = [broken id];
+ unlink([[NSString stringWithFormat:@"/var/lib/dpkg/info/%@.prerm", id] UTF8String]);
+ unlink([[NSString stringWithFormat:@"/var/lib/dpkg/info/%@.postrm", id] UTF8String]);
+ unlink([[NSString stringWithFormat:@"/var/lib/dpkg/info/%@.preinst", id] UTF8String]);
+ unlink([[NSString stringWithFormat:@"/var/lib/dpkg/info/%@.postinst", id] UTF8String]);
+ }
+
+ [self resolve];
+ [self perform];
+ }
+ break;
+
+ case 2:
+ [broken_ removeAllObjects];
+ [self _loaded];
+ break;
+
+ default:
+ _assert(false);
+ }
+
+ [sheet dismiss];
+ } else if ([context isEqualToString:@"role"]) {
+ switch (button) {
+ case 1: Role_ = @"User"; break;
+ case 2: Role_ = @"Hacker"; break;
+ case 3: Role_ = @"Developer"; break;
+
+ default:
+ Role_ = nil;
+ _assert(false);
+ }
+
+ bool reset = Settings_ != nil;
+
+ Settings_ = [NSMutableDictionary dictionaryWithObjectsAndKeys:
+ Role_, @"Role",
+ nil];
+
+ [Metadata_ setObject:Settings_ forKey:@"Settings"];
+
+ Changed_ = true;
+
+ if (reset)
+ [self updateData];
+ else
+ [self finish];
+
+ [sheet dismiss];
+ } else if ([context isEqualToString:@"upgrade"]) {
+ switch (button) {
+ case 1:
+ @synchronized (self) {
+ for (Package *essential in essential_)
+ [essential install];
+
+ [self resolve];
+ [self perform];
+ }
+ break;
+
+ case 2:
+ [self distUpgrade];
+ break;
+
+ case 3:
+ Ignored_ = YES;
+ break;
+
+ default:
+ _assert(false);
+ }
+
+ [sheet dismiss];
+ }
+}
+
+- (void) reorganize { _pooled
+ system("/usr/libexec/cydia/free.sh");
+ [self performSelectorOnMainThread:@selector(finish) withObject:nil waitUntilDone:NO];
+}
+
+- (void) applicationSuspend:(__GSEvent *)event {
+ if (hud_ == nil && ![progress_ isRunning])
+ [super applicationSuspend:event];
+}
+
+- (void) _animateSuspension:(BOOL)arg0 duration:(double)arg1 startTime:(double)arg2 scale:(float)arg3 {
+ if (hud_ == nil)
+ [super _animateSuspension:arg0 duration:arg1 startTime:arg2 scale:arg3];
+}
+
+- (void) _setSuspended:(BOOL)value {
+ if (hud_ == nil)
+ [super _setSuspended:value];
+}
+
+- (UIProgressHUD *) addProgressHUD {
+ UIProgressHUD *hud([[[UIProgressHUD alloc] initWithWindow:window_] autorelease]);
+ [window_ setUserInteractionEnabled:NO];
+ [hud show:YES];
+ [progress_ addSubview:hud];
+ return hud;
+}
+
+- (void) removeProgressHUD:(UIProgressHUD *)hud {
+ [hud show:NO];
+ [hud removeFromSuperview];
+ [window_ setUserInteractionEnabled:YES];
+}
+
+- (void) openMailToURL:(NSURL *)url {
+// XXX: this makes me sad
+#if 0
+ [[[MailToView alloc] initWithView:underlay_ delegate:self url:url] autorelease];
+#else
+ [UIApp openURL:url];// asPanel:YES];
+#endif
+}
+
+- (void) clearFirstResponder {
+ if (id responder = [window_ firstResponder])
+ [responder resignFirstResponder];
+}
+
+- (RVPage *) pageForPackage:(NSString *)name {
+ if (Package *package = [database_ packageWithName:name]) {
+ PackageView *view([self packageView]);
+ [view setPackage:package];
+ return view;
+ } else {
+ UIActionSheet *sheet = [[[UIActionSheet alloc]
+ initWithTitle:CYLocalize("CANNOT_LOCATE_PACKAGE")
+ buttons:[NSArray arrayWithObjects:CYLocalize("CLOSE"), nil]
+ defaultButtonIndex:0
+ delegate:self
+ context:@"missing"
+ ] autorelease];
+
+ [sheet setBodyText:[NSString stringWithFormat:CYLocalize("PACKAGE_CANNOT_BE_FOUND"), name]];
+
+ [sheet popupAlertAnimated:YES];
+ return nil;
+ }
+}
+
+- (RVPage *) pageForURL:(NSURL *)url hasTag:(int *)tag {
+ if (tag != NULL)
+ tag = 0;
+
+ NSString *scheme([[url scheme] lowercaseString]);
+ if (![scheme isEqualToString:@"cydia"])
+ return nil;
+ NSString *path([url absoluteString]);
+ if ([path length] < 8)
+ return nil;
+ path = [path substringFromIndex:8];
+ if (![path hasPrefix:@"/"])
+ path = [@"/" stringByAppendingString:path];
+
+ if ([path isEqualToString:@"/add-source"])
+ return [[[AddSourceView alloc] initWithBook:book_ database:database_] autorelease];
+ else if ([path isEqualToString:@"/storage"])
+ return [self _pageForURL:[NSURL fileURLWithPath:[[NSBundle mainBundle] pathForResource:@"storage" ofType:@"html"]] withClass:[BrowserView class]];
+ else if ([path isEqualToString:@"/sources"])
+ return [[[SourceTable alloc] initWithBook:book_ database:database_] autorelease];
+ else if ([path isEqualToString:@"/packages"])
+ return [[[InstalledView alloc] initWithBook:book_ database:database_] autorelease];
+ else if ([path hasPrefix:@"/url/"])
+ return [self _pageForURL:[NSURL URLWithString:[path substringFromIndex:5]] withClass:[BrowserView class]];
+ else if ([path hasPrefix:@"/launch/"])
+ [self launchApplicationWithIdentifier:[path substringFromIndex:8] suspended:NO];
+ else if ([path hasPrefix:@"/package-settings/"])
+ return [[[SettingsView alloc] initWithBook:book_ database:database_ package:[path substringFromIndex:18]] autorelease];
+ else if ([path hasPrefix:@"/package-signature/"])
+ return [[[SignatureView alloc] initWithBook:book_ database:database_ package:[path substringFromIndex:19]] autorelease];
+ else if ([path hasPrefix:@"/package/"])
+ return [self pageForPackage:[path substringFromIndex:9]];
+ else if ([path hasPrefix:@"/files/"]) {
+ NSString *name = [path substringFromIndex:7];
+
+ if (Package *package = [database_ packageWithName:name]) {
+ FileTable *files = [[[FileTable alloc] initWithBook:book_ database:database_] autorelease];
+ [files setPackage:package];
+ return files;
+ }
+ }
+
+ return nil;
+}
+
+- (void) applicationOpenURL:(NSURL *)url {
+ [super applicationOpenURL:url];
+ int tag;
+ if (RVPage *page = [self pageForURL:url hasTag:&tag]) {
+ [self setPage:page];
+ [buttonbar_ showSelectionForButton:tag];
+ tag_ = tag;
+ }
+}
+
+- (void) applicationDidFinishLaunching:(id)unused {
+ _trace();
+ Font12_ = [[UIFont systemFontOfSize:12] retain];
+ Font12Bold_ = [[UIFont boldSystemFontOfSize:12] retain];
+ Font14_ = [[UIFont systemFontOfSize:14] retain];
+ Font18Bold_ = [[UIFont boldSystemFontOfSize:18] retain];
+ Font22Bold_ = [[UIFont boldSystemFontOfSize:22] retain];
+
+ tag_ = 1;
+
+ essential_ = [[NSMutableArray alloc] initWithCapacity:4];
+ broken_ = [[NSMutableArray alloc] initWithCapacity:4];
+
+ [NSURLProtocol registerClass:[CydiaURLProtocol class]];
+
+ CGRect screenrect = [UIHardware fullScreenApplicationContentRect];
+ window_ = [[UIWindow alloc] initWithContentRect:screenrect];
+
+ [window_ orderFront:self];
+ [window_ makeKey:self];
+ [window_ setHidden:NO];
+
+ database_ = [Database sharedInstance];
+ progress_ = [[ProgressView alloc] initWithFrame:[window_ bounds] database:database_ delegate:self];
+ [database_ setDelegate:progress_];
+ [window_ setContentView:progress_];
+
+ underlay_ = [[UIView alloc] initWithFrame:[progress_ bounds]];
+ [progress_ setContentView:underlay_];
+
+ [progress_ resetView];
+
+ if (
+ readlink("/Applications", NULL, 0) == -1 && errno == EINVAL ||
+ readlink("/Library/Ringtones", NULL, 0) == -1 && errno == EINVAL ||
+ readlink("/Library/Wallpaper", NULL, 0) == -1 && errno == EINVAL ||
+ readlink("/usr/include", NULL, 0) == -1 && errno == EINVAL ||
+ readlink("/usr/libexec", NULL, 0) == -1 && errno == EINVAL ||
+ readlink("/usr/share", NULL, 0) == -1 && errno == EINVAL /*||
+ readlink("/var/lib", NULL, 0) == -1 && errno == EINVAL*/
+ ) {
+ [self setIdleTimerDisabled:YES];
+
+ hud_ = [[self addProgressHUD] retain];
+ [hud_ setText:@"Reorganizing\n\nWill Automatically\nClose When Done"];
+
+ [self setStatusBarShowsProgress:YES];
+
+ [NSThread
+ detachNewThreadSelector:@selector(reorganize)
+ toTarget:self
+ withObject:nil
+ ];
+ } else
+ [self finish];
+}
+