]> git.saurik.com Git - cydia.git/blobdiff - Cydia.mm
Added a cool finish.sh script.
[cydia.git] / Cydia.mm
index bc34076cd0fef1d51643ecf2b7a7e78f6bc5b1a6..1ad22345b4081b5d266630065c0edd20ec8beac0 100644 (file)
--- a/Cydia.mm
+++ b/Cydia.mm
 #include <WebCore/DOMHTML.h>
 #import <QuartzCore/CALayer.h>
 
-#import <UIKit/UIActionSheet.h>
-#import <UIKit/UIAnimator.h>
-#import <UIKit/UIApplication.h>
-#import <UIKit/UIColor.h>
-#import <UIKit/UIFieldEditor.h>
-#import <UIKit/UIFrameAnimation.h>
-#import <UIKit/UIHardware.h>
-#import <UIKit/UIImage.h>
-#import <UIKit/UIImageAndTextTableCell.h>
-#import <UIKit/UIImageView.h>
-#import <UIKit/UIKeyboard.h>
-#import <UIKit/UIKeyboardImpl.h>
-#import <UIKit/UINavigationBar.h>
-#import <UIKit/UINavigationItem.h>
-#import <UIKit/UIPreferencesTable.h>
-#import <UIKit/UIPreferencesTableCell.h>
-#import <UIKit/UIProgressBar.h>
-#import <UIKit/UIProgressHUD.h>
-#import <UIKit/UIProgressIndicator.h>
-#import <UIKit/UIPushButton.h>
-#import <UIKit/UISearchField.h>
-#import <UIKit/UISimpleTableCell.h>
-#import <UIKit/_UISwitchSlider.h>
-#import <UIKit/UITableCell.h>
-#import <UIKit/UITableColumn.h>
-#import <UIKit/UITextField.h>
-#import <UIKit/UITextInputTraits.h>
-#import <UIKit/UITextLabel.h>
-#import <UIKit/UITextView.h>
-#import <UIKit/UIToolbar.h>
-#import <UIKit/UITransitionView.h>
-#import <UIKit/UIWebDocumentView.h>
-#import <UIKit/UIWebView.h>
-#import <UIKit/UIWindow.h>
-
-#import <UIKit/UIView-Geometry.h>
-#import <UIKit/UIView-Gestures.h>
-#import <UIKit/UIView-Hierarchy.h>
-#import <UIKit/UIView-Rendering.h>
-
-#import <UIKit/UIWebDocumentView-Forms.h>
-
-#import <UIKit/NSString-UIStringDrawing.h>
+#import <UIKit/UIKit.h>
 
 // XXX: remove
 #import <UIKit/UIActionSheet-Private.h>
 #include <apt-pkg/sourcelist.h>
 #include <apt-pkg/sptr.h>
 
+#include <sys/types.h>
+#include <sys/stat.h>
 #include <sys/sysctl.h>
+
 #include <notify.h>
 #include <dlfcn.h>
 
@@ -142,13 +103,13 @@ extern "C" {
 #include <errno.h>
 #include <pcre.h>
 
-#define UIWebView UIWebDocumentView
-
 #import "BrowserView.h"
 #import "ResetView.h"
 #import "UICaboodle.h"
 /* }}} */
 
+static const NSStringCompareOptions CompareOptions_ = NSCaseInsensitiveSearch | NSNumericSearch | NSDiacriticInsensitiveSearch | NSWidthInsensitiveSearch | NSForcedOrderingSearch;
+
 @interface WebView (Cydia)
 - (void) _setLayoutInterval:(float)interval;
 @end
@@ -161,14 +122,6 @@ extern "C" {
 - (id) initWithCGColor:(CGColorRef)color;
 @end
 
-@interface UIFont {
-}
-
-+ (id)systemFontOfSize:(float)fp8;
-+ (id)boldSystemFontOfSize:(float)fp8;
-- (UIFont *) fontWithSize:(CGFloat)size;
-@end
-
 @interface NSObject (iPhoneOS)
 - (CGColorRef) cgColor;
 - (CGColorRef) CGColor;
@@ -226,8 +179,10 @@ extern NSString *kUIButtonBarButtonType;
 typedef enum {
     kUIProgressIndicatorStyleLargeWhite = 0,
     kUIProgressIndicatorStyleMediumWhite = 1,
+    kUIProgressIndicatorStyleMediumBrown = 2,
     kUIProgressIndicatorStyleSmallWhite = 3,
-    kUIProgressIndicatorStyleSmallBlack = 4
+    kUIProgressIndicatorStyleSmallBlack = 4,
+    kUIProgressIndicatorStyleTinyWhite = 5,
 } UIProgressIndicatorStyle;
 
 typedef enum {
@@ -442,16 +397,6 @@ class CGColor {
         return color_;
     }
 };
-
-class GSFont {
-  private:
-    GSFontRef font_;
-
-  public:
-    ~GSFont() {
-        CFRelease(font_);
-    }
-};
 /* }}} */
 
 extern "C" void UISetColor(CGColorRef color);
@@ -465,7 +410,7 @@ static const char * const SpringBoard_ = "/System/Library/LaunchDaemons/com.appl
 static CGColor Blue_;
 static CGColor Blueish_;
 static CGColor Black_;
-static CGColor Clear_;
+static CGColor Off_;
 static CGColor Red_;
 static CGColor White_;
 static CGColor Gray_;
@@ -484,9 +429,9 @@ static UIFont *Font14_;
 static UIFont *Font18Bold_;
 static UIFont *Font22Bold_;
 
-const char *Firmware_ = NULL;
-const char *Machine_ = NULL;
-const char *SerialNumber_ = NULL;
+static const char *Firmware_ = NULL;
+static const char *Machine_ = NULL;
+static const NSString *UniqueID_ = NULL;
 
 unsigned Major_;
 unsigned Minor_;
@@ -510,6 +455,7 @@ static _transient NSString *Role_;
 static _transient NSMutableDictionary *Packages_;
 static _transient NSMutableDictionary *Sections_;
 static _transient NSMutableDictionary *Sources_;
+static _transient NSMutableArray *Documents_;
 static bool Changed_;
 static NSDate *now_;
 
@@ -563,7 +509,7 @@ UITextView *GetTextView(NSString *value, float left, bool html) {
         [text setText:value];
     [text setEnabled:NO];
 
-    [text setBackgroundColor:[UIColor colorWithCGColor:Clear_]];
+    [text setBackgroundColor:[UIColor clearColor]];
 
     CGRect frame = [text frame];
     [text setFrame:frame];
@@ -622,7 +568,9 @@ bool isSectionVisible(NSString *section) {
 - (void) setProgressError:(NSString *)error forPackage:(NSString *)id;
 - (void) setProgressTitle:(NSString *)title;
 - (void) setProgressPercent:(float)percent;
+- (void) startProgress;
 - (void) addProgressOutput:(NSString *)output;
+- (bool) isCancelling:(size_t)received;
 @end
 
 @protocol ConfigurationDelegate
@@ -695,10 +643,11 @@ class Status :
         );
 
         [delegate_ setProgressPercent:percent];
-        return value;
+        return [delegate_ isCancelling:CurrentBytes] ? false : value;
     }
 
     virtual void Start() {
+        [delegate_ startProgress];
     }
 
     virtual void Stop() {
@@ -924,7 +873,7 @@ class Progress :
             return NSOrderedDescending;
     }
 
-    return [lhs caseInsensitiveCompare:rhs];
+    return [lhs compare:rhs options:CompareOptions_];
 }
 
 - (NSDictionary *) record {
@@ -1524,7 +1473,7 @@ NSString *Scour(const char *field, const char *begin, const char *end) {
             return NSOrderedDescending;
     }
 
-    return [lhs caseInsensitiveCompare:rhs];
+    return [lhs compare:rhs options:CompareOptions_];
 }
 
 - (NSComparisonResult) compareBySection:(Package *)package {
@@ -1536,7 +1485,7 @@ NSString *Scour(const char *field, const char *begin, const char *end) {
     else if (lhs != NULL && rhs == NULL)
         return NSOrderedDescending;
     else if (lhs != NULL && rhs != NULL) {
-        NSComparisonResult result = [lhs caseInsensitiveCompare:rhs];
+        NSComparisonResult result = [lhs compare:rhs options:CompareOptions_];
         if (result != NSOrderedSame)
             return result;
     }
@@ -1671,7 +1620,7 @@ NSString *Scour(const char *field, const char *begin, const char *end) {
             return NSOrderedDescending;
     }
 
-    return [lhs caseInsensitiveCompare:rhs];
+    return [lhs compare:rhs options:CompareOptions_];
 }
 
 - (Section *) initWithName:(NSString *)name {
@@ -2425,7 +2374,6 @@ bool DepSubstrate(const pkgCache::VerIterator &iterator) {
             0, navsize.height, bounds.size.width, bounds.size.height - navsize.height
         )];
 
-        [table_ setReusesTableCells:YES];
         [table_ setDataSource:self];
         [table_ reloadData];
 
@@ -2501,6 +2449,8 @@ bool DepSubstrate(const pkgCache::VerIterator &iterator) {
     id delegate_;
     BOOL running_;
     SHA1SumValue springlist_;
+    size_t received_;
+    NSTimeInterval last_;
 }
 
 - (void) transitionViewDidComplete:(UITransitionView*)view fromView:(UIView*)from toView:(UIView*)to;
@@ -2556,10 +2506,10 @@ bool DepSubstrate(const pkgCache::VerIterator &iterator) {
         overlay_ = [[UIView alloc] initWithFrame:[transition_ bounds]];
 
         if (bootstrap_)
-            [overlay_ setBackgroundColor:[UIColor colorWithCGColor:Black_]];
+            [overlay_ setBackgroundColor:[UIColor blackColor]];
         else {
             background_ = [[UIView alloc] initWithFrame:[self bounds]];
-            [background_ setBackgroundColor:[UIColor colorWithCGColor:Black_]];
+            [background_ setBackgroundColor:[UIColor blackColor]];
             [self addSubview:background_];
         }
 
@@ -2595,8 +2545,8 @@ bool DepSubstrate(const pkgCache::VerIterator &iterator) {
             24
         )];
 
-        [status_ setColor:[UIColor colorWithCGColor:White_]];
-        [status_ setBackgroundColor:[UIColor colorWithCGColor:Clear_]];
+        [status_ setColor:[UIColor whiteColor]];
+        [status_ setBackgroundColor:[UIColor clearColor]];
 
         [status_ setCentersHorizontally:YES];
         //[status_ setFont:font];
@@ -2611,8 +2561,8 @@ bool DepSubstrate(const pkgCache::VerIterator &iterator) {
         //[output_ setTextFont:@"Courier New"];
         [output_ setTextSize:12];
 
-        [output_ setTextColor:[UIColor colorWithCGColor:White_]];
-        [output_ setBackgroundColor:[UIColor colorWithCGColor:Clear_]];
+        [output_ setTextColor:[UIColor whiteColor]];
+        [output_ setBackgroundColor:[UIColor clearColor]];
 
         [output_ setMarginTop:0];
         [output_ setAllowsRubberBanding:YES];
@@ -2721,9 +2671,51 @@ bool DepSubstrate(const pkgCache::VerIterator &iterator) {
         case 4: [close_ setTitle:@"Reboot Device"]; break;
     }
 
-#ifdef __OBJC2__
+#define Cache_ "/User/Library/Caches/com.apple.mobile.installation.plist"
+
+    if (NSMutableDictionary *cache = [[NSDictionary alloc] initWithContentsOfFile:@ Cache_]) {
+        [cache autorelease];
+
+        NSFileManager *manager = [NSFileManager defaultManager];
+        id error = nil;
+
+        NSMutableDictionary *system = [cache objectForKey:@"System"];
+        if (system == nil)
+            goto error;
+
+        struct stat info;
+        if (stat(Cache_, &info) == -1)
+            goto error;
+
+        [system removeAllObjects];
+
+        if (NSArray *apps = [manager contentsOfDirectoryAtPath:@"/Applications" error:&error])
+            for (NSString *app in apps)
+                if ([app hasSuffix:@".app"]) {
+                    NSString *path = [@"/Applications" stringByAppendingPathComponent:app];
+                    NSString *plist = [path stringByAppendingPathComponent:@"Info.plist"];
+                    if (NSMutableDictionary *info = [[NSMutableDictionary alloc] initWithContentsOfFile:plist]) {
+                        [info autorelease];
+                        [info setObject:path forKey:@"Path"];
+                        [info setObject:@"System" forKey:@"ApplicationType"];
+                        NSString *bundle = [info objectForKey:@"CFBundleIdentifier"];
+                        [system setObject:info forKey:bundle];
+                    }
+                }
+        else goto error;
+
+        [cache writeToFile:@Cache_ atomically:YES];
+
+        if (chown(Cache_, info.st_uid, info.st_gid) == -1)
+            goto error;
+        if (chmod(Cache_, info.st_mode) == -1)
+            goto error;
+
+        if (false) error:
+            fprintf(stderr, "%s\n", error == nil ? strerror(errno) : [[error localizedDescription] UTF8String]);
+    }
+
     notify_post("com.apple.mobile.application_installed");
-#endif
 
     [delegate_ setStatusBarShowsProgress:NO];
 
@@ -2749,6 +2741,9 @@ bool DepSubstrate(const pkgCache::VerIterator &iterator) {
     [output_ setText:@""];
     [progress_ setProgress:0];
 
+    received_ = 0;
+    last_ = 0;//[NSDate timeIntervalSinceReferenceDate];
+
     [close_ removeFromSuperview];
     [overlay_ addSubview:progress_];
     [overlay_ addSubview:status_];
@@ -2782,7 +2777,7 @@ bool DepSubstrate(const pkgCache::VerIterator &iterator) {
         detachNewThreadSelector:selector
         toTarget:database_
         withObject:nil
-        title:@"Repairing..."
+        title:@"Repairing"
     ];
 }
 
@@ -2825,6 +2820,10 @@ bool DepSubstrate(const pkgCache::VerIterator &iterator) {
     ];
 }
 
+- (void) startProgress {
+    last_ = [NSDate timeIntervalSinceReferenceDate];
+}
+
 - (void) addProgressOutput:(NSString *)output {
     [self
         performSelectorOnMainThread:@selector(_addProgressOutput:)
@@ -2833,6 +2832,19 @@ bool DepSubstrate(const pkgCache::VerIterator &iterator) {
     ];
 }
 
+- (bool) isCancelling:(size_t)received {
+    if (last_ != 0) {
+        NSTimeInterval now = [NSDate timeIntervalSinceReferenceDate];
+        if (received_ != received) {
+            received_ = received;
+            last_ = now;
+        } else if (now - last_ > 30)
+            return true;
+    }
+
+    return false;
+}
+
 - (void) _setConfigurationData:(NSString *)data {
     static Pcre conffile_r("^'(.*)' '(.*)' ([01]) ([01])$");
 
@@ -2861,7 +2873,7 @@ bool DepSubstrate(const pkgCache::VerIterator &iterator) {
 }
 
 - (void) _setProgressTitle:(NSString *)title {
-    [status_ setText:[title stringByAppendingString:@"..."]];
+    [status_ setText:title];
 }
 
 - (void) _setProgressPercent:(NSNumber *)percent {
@@ -2942,7 +2954,7 @@ bool DepSubstrate(const pkgCache::VerIterator &iterator) {
         badge_ = [[UIImageView alloc] initWithFrame:CGRectMake(17, 70, 16, 16)];
 
         status_ = [[UITextLabel alloc] initWithFrame:CGRectMake(48, 68, 280, 20)];
-        [status_ setBackgroundColor:Clear_];
+        [status_ setBackgroundColor:[UIColor clearColor]];
         [status_ setFont:small];
 #endif
     } return self;
@@ -3001,7 +3013,7 @@ bool DepSubstrate(const pkgCache::VerIterator &iterator) {
     } else if ([package half]) {
         [badge_ setImage:[UIImage applicationImageNamed:@"damaged.png"]];
         [status_ setText:@"Package Damaged"];
-        [status_ setColor:Red_];
+        [status_ setColor:[UIColor redColor]];
     } else {
         [badge_ setImage:nil];
         [status_ setText:nil];
@@ -3015,8 +3027,18 @@ bool DepSubstrate(const pkgCache::VerIterator &iterator) {
 }
 
 - (void) drawContentInRect:(CGRect)rect selected:(BOOL)selected {
-    if (icon_ != nil)
-        [icon_ drawInRect:CGRectMake(10, 10, 30, 30)];
+    if (icon_ != nil) {
+        CGRect rect;
+        rect.size = [icon_ size];
+
+        rect.size.width /= 2;
+        rect.size.height /= 2;
+
+        rect.origin.x = 25 - rect.size.width / 2;
+        rect.origin.y = 25 - rect.size.height / 2;
+
+        [icon_ drawInRect:rect];
+    }
 
     if (selected)
         UISetColor(White_);
@@ -3342,8 +3364,6 @@ bool DepSubstrate(const pkgCache::VerIterator &iterator) {
     [sheet dismiss];
 }
 
-#include "internals.h"
-
 - (void) webView:(WebView *)sender didFinishLoadForFrame:(WebFrame *)frame {
     [[frame windowObject] evaluateWebScript:@"document.base.target = '_top'"];
     return [super webView:sender didFinishLoadForFrame:frame];
@@ -3540,6 +3560,9 @@ bool DepSubstrate(const pkgCache::VerIterator &iterator) {
 
         [self addSubview:list_];
         [self reloadData];
+
+        [self setAutoresizingMask:UIViewAutoresizingFlexibleHeight];
+        [list_ setAutoresizingMask:UIViewAutoresizingFlexibleHeight];
     } return self;
 }
 
@@ -3981,6 +4004,9 @@ bool DepSubstrate(const pkgCache::VerIterator &iterator) {
         [table setDelegate:self];
 
         [self reloadData];
+
+        [self setAutoresizingMask:UIViewAutoresizingFlexibleHeight];
+        [list_ setAutoresizingMask:UIViewAutoresizingFlexibleHeight];
     } return self;
 }
 
@@ -4053,8 +4079,8 @@ bool DepSubstrate(const pkgCache::VerIterator &iterator) {
     return [[list_ table] isRowDeletionEnabled] ? @"Done" : @"Edit";
 }
 
-- (RVUINavBarButtonStyle) rightButtonStyle {
-    return [[list_ table] isRowDeletionEnabled] ? RVUINavBarButtonStyleHighlighted : RVUINavBarButtonStyleNormal;
+- (UINavigationButtonStyle) rightButtonStyle {
+    return [[list_ table] isRowDeletionEnabled] ? UINavigationButtonStyleHighlighted : UINavigationButtonStyleNormal;
 }
 
 @end
@@ -4091,6 +4117,9 @@ bool DepSubstrate(const pkgCache::VerIterator &iterator) {
         ];
 
         [self addSubview:packages_];
+
+        [self setAutoresizingMask:UIViewAutoresizingFlexibleHeight];
+        [packages_ setAutoresizingMask:UIViewAutoresizingFlexibleHeight];
     } return self;
 }
 
@@ -4121,8 +4150,8 @@ bool DepSubstrate(const pkgCache::VerIterator &iterator) {
     return Role_ != nil && [Role_ isEqualToString:@"Developer"] ? nil : expert_ ? @"Expert" : @"Simple";
 }
 
-- (RVUINavBarButtonStyle) rightButtonStyle {
-    return expert_ ? RVUINavBarButtonStyleHighlighted : RVUINavBarButtonStyleNormal;
+- (UINavigationButtonStyle) rightButtonStyle {
+    return expert_ ? UINavigationButtonStyleHighlighted : UINavigationButtonStyleNormal;
 }
 
 - (void) setDelegate:(id)delegate {
@@ -4205,6 +4234,45 @@ bool DepSubstrate(const pkgCache::VerIterator &iterator) {
 @end
 /* }}} */
 
+/* Indirect Delegate {{{ */
+@interface IndirectDelegate : NSProxy {
+    _transient id delegate_;
+}
+
+- (void) setDelegate:(id)delegate;
+- (id) initWithDelegate:(id)delegate;
+@end
+
+@implementation IndirectDelegate
+
+- (void) setDelegate:(id)delegate {
+    delegate_ = delegate;
+}
+
+- (id) initWithDelegate:(id)delegate {
+    delegate_ = delegate;
+    return self;
+}
+
+- (void) doesNotRecognizeSelector:(SEL)sel {
+    fprintf(stderr, "doesNotRecognizeSelector:@selector(%s)", sel_getName(sel));
+}
+
+- (NSMethodSignature*) methodSignatureForSelector:(SEL)sel {
+    if (delegate_ != nil)
+        if (NSMethodSignature *sig = [delegate_ methodSignatureForSelector:sel])
+            return sig;
+    return nil;
+}
+
+- (void) forwardInvocation:(NSInvocation*)inv {
+    SEL sel = [inv selector];
+    if (delegate_ != nil && [delegate_ respondsToSelector:sel])
+        [inv invokeWithTarget:delegate_];
+}
+
+@end
+/* }}} */
 /* Browser Implementation {{{ */
 @implementation BrowserView
 
@@ -4214,11 +4282,22 @@ bool DepSubstrate(const pkgCache::VerIterator &iterator) {
     [webview setResourceLoadDelegate:nil];
     [webview setUIDelegate:nil];
 
-    [scroller_ setDelegate:nil];
     [webview_ setDelegate:nil];
+    [webview_ setGestureDelegate:nil];
 
-    [scroller_ release];
+    /*WebFrame *frame = [webview mainFrame];
+    [frame loadHTMLString:@"" baseURL:[NSURL URLWithString:@"http://cydia.saurik.com/"]];*/
+
+    //[webview_ removeFromSuperview];
+    //[Documents_ addObject:[webview_ autorelease]];
     [webview_ release];
+
+    [indirect_ setDelegate:nil];
+    [indirect_ release];
+
+    [scroller_ setDelegate:nil];
+
+    [scroller_ release];
     [urls_ release];
     [indicator_ release];
     if (title_ != nil)
@@ -4243,7 +4322,7 @@ bool DepSubstrate(const pkgCache::VerIterator &iterator) {
 
     [copy addValue:[NSString stringWithUTF8String:Firmware_] forHTTPHeaderField:@"X-Firmware"];
     [copy addValue:[NSString stringWithUTF8String:Machine_] forHTTPHeaderField:@"X-Machine"];
-    [copy addValue:[NSString stringWithUTF8String:SerialNumber_] forHTTPHeaderField:@"X-Serial-Number"];
+    [copy addValue:UniqueID_ forHTTPHeaderField:@"X-Unique-ID"];
 
     if (Role_ != nil)
         [copy addValue:Role_ forHTTPHeaderField:@"X-Role"];
@@ -4257,6 +4336,8 @@ bool DepSubstrate(const pkgCache::VerIterator &iterator) {
 }
 
 - (void) reloadURL {
+    if ([urls_ count] == 0)
+        return;
     NSURL *url = [[[urls_ lastObject] retain] autorelease];
     [urls_ removeLastObject];
     [self loadURL:url cachePolicy:NSURLRequestReloadIgnoringCacheData];
@@ -4307,11 +4388,15 @@ bool DepSubstrate(const pkgCache::VerIterator &iterator) {
     RVPage *page = nil;
 
     if (
+        [href hasPrefix:@"http://ax.phobos.apple.com/"] ||
         [href hasPrefix:@"http://phobos.apple.com/"] ||
-        [href hasPrefix:@"mailto:"]
+        [href hasPrefix:@"http://www.youtube.com/watch?"] ||
+        [href hasPrefix:@"tel:"]
     )
         [delegate_ openURL:[NSURL URLWithString:href]];
-    else if ([href isEqualToString:@"cydia://add-source"])
+    else if ([href hasPrefix:@"mailto:"]) {
+        [delegate_ openURL:[NSURL URLWithString:href]];
+    } else if ([href isEqualToString:@"cydia://add-source"])
         page = [[[AddSourceView alloc] initWithBook:book_ database:database_] autorelease];
     else if ([href isEqualToString:@"cydia://sources"])
         page = [[[SourceTable alloc] initWithBook:book_ database:database_] autorelease];
@@ -4352,7 +4437,6 @@ bool DepSubstrate(const pkgCache::VerIterator &iterator) {
 
 - (NSURLRequest *) webView:(WebView *)sender resource:(id)identifier willSendRequest:(NSURLRequest *)request redirectResponse:(NSURLResponse *)redirectResponse fromDataSource:(WebDataSource *)dataSource {
     NSURL *url = [request URL];
-    NSLog(@"Cydia:%@", url);
     if ([self getSpecial:[url absoluteString]])
         return nil;
 
@@ -4368,14 +4452,21 @@ bool DepSubstrate(const pkgCache::VerIterator &iterator) {
     return
         [scheme isEqualToString:@"apptapp"] ||
         [scheme isEqualToString:@"cydia"] ||
-        [scheme isEqualToString:@"mailto"];
+        [scheme isEqualToString:@"mailto"] ||
+        [scheme isEqualToString:@"tel"];
 }
 
 - (WebView *) webView:(WebView *)sender createWebViewWithRequest:(NSURLRequest *)request {
     if (request != nil) {
         NSURL *url = [request URL];
         NSString *scheme = [url scheme];
-        if ([self isSpecialScheme:scheme] || [[url absoluteString] hasPrefix:@"http://phobos.apple.com/"])
+        NSString *absolute = [url absoluteString];
+        if (
+            [self isSpecialScheme:scheme] ||
+            [absolute hasPrefix:@"http://ax.phobos.apple.com/"] ||
+            [absolute hasPrefix:@"http://phobos.apple.com/"] ||
+            [absolute hasPrefix:@"http://www.yahoo.com/watch?"]
+        )
             return nil;
     }
 
@@ -4414,17 +4505,17 @@ bool DepSubstrate(const pkgCache::VerIterator &iterator) {
         title_ = nil;
     }
 
-    [self setTitle:@"Loading..."];
+    [self setTitle:@"Loading"];
 
     WebView *webview = [webview_ webView];
     NSString *href = [webview mainFrameURL];
     [urls_ addObject:[NSURL URLWithString:href]];
 
-    [scroller_ scrollPointVisibleAtTopLeft:CGPointZero];
-
     CGRect webrect = [scroller_ bounds];
     webrect.size.height = 0;
     [webview_ setFrame:webrect];
+
+    [scroller_ scrollPointVisibleAtTopLeft:CGPointZero];
 }
 
 - (void) _finishLoading {
@@ -4497,32 +4588,40 @@ bool DepSubstrate(const pkgCache::VerIterator &iterator) {
         CGRect webrect = [scroller_ bounds];
         webrect.size.height = 0;
 
-        webview_ = [[UIWebView alloc] initWithFrame:webrect];
-        [scroller_ addSubview:webview_];
+        webview_ = [Documents_ lastObject];
+        if (webview_ != nil) {
+            webview_ = [webview_ retain];
+            [Documents_ removeLastObject];
+            [webview_ setFrame:webrect];
+        } else {
+            webview_ = [[UIWebDocumentView alloc] initWithFrame:webrect];
 
-        [webview_ setTileSize:CGSizeMake(webrect.size.width, 500)];
+            [webview_ setTileSize:CGSizeMake(webrect.size.width, 500)];
 
-        [webview_ setTilingEnabled:YES];
-        [webview_ setTileMinificationFilter:kCAFilterNearest];
-        [webview_ setAutoresizes:YES];
+            [webview_ setTilingEnabled:YES];
+            [webview_ setTileMinificationFilter:kCAFilterNearest];
+            [webview_ setAutoresizes:YES];
 
-        [webview_ setViewportSize:CGSizeMake(980, -1) forDocumentTypes:0x10];
-        [webview_ setViewportSize:CGSizeMake(320, -1) forDocumentTypes:0x2];
-        [webview_ setViewportSize:CGSizeMake(320, -1) forDocumentTypes:0x8];
+            [webview_ setViewportSize:CGSizeMake(980, -1) forDocumentTypes:0x10];
+            [webview_ setViewportSize:CGSizeMake(320, -1) forDocumentTypes:0x2];
+            [webview_ setViewportSize:CGSizeMake(320, -1) forDocumentTypes:0x8];
 
-        [webview_ _setDocumentType:0x4];
+            [webview_ _setDocumentType:0x4];
+
+            [webview_ setZoomsFocusedFormControl:YES];
+            [webview_ setContentsPosition:7];
+            [webview_ setEnabledGestures:0xa];
+            [webview_ setValue:[NSNumber numberWithBool:YES] forGestureAttribute:0x4];
+            [webview_ setValue:[NSNumber numberWithBool:YES] forGestureAttribute:0x7];
+            [webview_ setSmoothsFonts:YES];
+        }
 
-        [webview_ setZoomsFocusedFormControl:YES];
-        [webview_ setContentsPosition:7];
-        [webview_ setEnabledGestures:0xa];
-        [webview_ setValue:[NSNumber numberWithBool:YES] forGestureAttribute:0x4];
-        [webview_ setValue:[NSNumber numberWithBool:YES] forGestureAttribute:0x7];
         [webview_ setDelegate:self];
         [webview_ setGestureDelegate:self];
-        [webview_ setSmoothsFonts:YES];
+        [scroller_ addSubview:webview_];
 
         CGSize indsize = [UIProgressIndicator defaultSizeForStyle:kUIProgressIndicatorStyleMediumWhite];
-        indicator_ = [[UIProgressIndicator alloc] initWithFrame:CGRectMake(281, 42, indsize.width, indsize.height)];
+        indicator_ = [[UIProgressIndicator alloc] initWithFrame:CGRectMake(281, 12, indsize.width, indsize.height)];
         [indicator_ setStyle:kUIProgressIndicatorStyleMediumWhite];
 
         Package *package([database_ packageWithName:@"cydia"]);
@@ -4531,15 +4630,21 @@ bool DepSubstrate(const pkgCache::VerIterator &iterator) {
             [package installed]
         ];
 
+        indirect_ = [[IndirectDelegate alloc] initWithDelegate:self];
+
         WebView *webview = [webview_ webView];
         [webview setApplicationNameForUserAgent:application];
         [webview setFrameLoadDelegate:self];
-        [webview setResourceLoadDelegate:self];
+        [webview setResourceLoadDelegate:indirect_];
         [webview setUIDelegate:self];
 
         //[webview _setLayoutInterval:0.5];
 
         urls_ = [[NSMutableArray alloc] initWithCapacity:16];
+
+        [self setAutoresizingMask:UIViewAutoresizingFlexibleHeight];
+        [scroller_ setAutoresizingMask:UIViewAutoresizingFlexibleHeight];
+        [pinstripe setAutoresizingMask:UIViewAutoresizingFlexibleHeight];
     } return self;
 }
 
@@ -4569,10 +4674,10 @@ bool DepSubstrate(const pkgCache::VerIterator &iterator) {
 }
 
 - (void) setPageActive:(BOOL)active {
-    if (active)
-        [book_ addSubview:indicator_];
-    else
+    if (!active)
         [indicator_ removeFromSuperview];
+    else
+        [[book_ navigationBar] addSubview:indicator_];
 }
 
 - (void) resetViewAnimated:(BOOL)animated {
@@ -4589,11 +4694,14 @@ bool DepSubstrate(const pkgCache::VerIterator &iterator) {
     ProgressDelegate
 > {
     _transient Database *database_;
-    UIView *overlay_;
+    UINavigationBar *overlay_;
     UIProgressIndicator *indicator_;
     UITextLabel *prompt_;
     UIProgressBar *progress_;
+    UINavigationButton *cancel_;
     bool updating_;
+    size_t received_;
+    NSTimeInterval last_;
 }
 
 - (id) initWithFrame:(CGRect)frame database:(Database *)database;
@@ -4723,6 +4831,9 @@ bool DepSubstrate(const pkgCache::VerIterator &iterator) {
         [list_ setReusesTableCells:YES];
 
         [self reloadData];
+
+        [self setAutoresizingMask:UIViewAutoresizingFlexibleHeight];
+        [list_ setAutoresizingMask:UIViewAutoresizingFlexibleHeight];
     } return self;
 }
 
@@ -4806,6 +4917,10 @@ bool DepSubstrate(const pkgCache::VerIterator &iterator) {
     return [sections_ count] == 0 ? nil : editing_ ? @"Done" : @"Edit";
 }
 
+- (UINavigationButtonStyle) rightButtonStyle {
+    return editing_ ? UINavigationButtonStyleHighlighted : UINavigationButtonStyleNormal;
+}
+
 - (UIView *) accessoryView {
     return accessory_;
 }
@@ -4916,6 +5031,9 @@ bool DepSubstrate(const pkgCache::VerIterator &iterator) {
         [table setReusesTableCells:YES];
 
         [self reloadData];
+
+        [self setAutoresizingMask:UIViewAutoresizingFlexibleHeight];
+        [list_ setAutoresizingMask:UIViewAutoresizingFlexibleHeight];
     } return self;
 }
 
@@ -5031,9 +5149,6 @@ bool DepSubstrate(const pkgCache::VerIterator &iterator) {
 @implementation SearchView
 
 - (void) dealloc {
-#ifndef __OBJC2__
-    [[field_ textTraits] setEditingDelegate:nil];
-#endif
     [field_ setDelegate:nil];
 
     [accessory_ release];
@@ -5095,9 +5210,7 @@ bool DepSubstrate(const pkgCache::VerIterator &iterator) {
     if (show)
         [animator performSelector:@selector(startAnimation:) withObject:animation afterDelay:delay];
 
-#ifndef __OBJC2__
     [delegate_ showKeyboard:show];
-#endif
 }
 
 - (void) textFieldDidBecomeFirstResponder:(UITextField *)field {
@@ -5175,7 +5288,7 @@ bool DepSubstrate(const pkgCache::VerIterator &iterator) {
 
         CGRect area;
         area.origin.x = /*cnfrect.origin.x + cnfrect.size.width + 4 +*/ 10;
-        area.origin.y = 30;
+        area.origin.y = 1;
 
         area.size.width =
 #ifdef __OBJC2__
@@ -5193,14 +5306,14 @@ bool DepSubstrate(const pkgCache::VerIterator &iterator) {
         [field_ setPlaceholder:@"Package Names & Descriptions"];
         [field_ setDelegate:self];
 
-        [field_ setPaddingTop:3];
+        [field_ setPaddingTop:5];
 
         UITextInputTraits *traits = [field_ textInputTraits];
         [traits setAutocapitalizationType:0];
         [traits setAutocorrectionType:1];
         [traits setReturnKeyType:6];
 
-        CGRect accrect = {{0, 6}, {6 + cnfrect.size.width + 6 + area.size.width + 6, area.size.height + 30}};
+        CGRect accrect = {{0, 6}, {6 + cnfrect.size.width + 6 + area.size.width + 6, area.size.height}};
 
         accessory_ = [[UIView alloc] initWithFrame:accrect];
         [accessory_ addSubview:field_];
@@ -5210,6 +5323,9 @@ bool DepSubstrate(const pkgCache::VerIterator &iterator) {
         [configure setImage:[UIImage applicationImageNamed:@"advanced.png"]];
         [configure addTarget:self action:@selector(configurePushed) forEvents:1];
         [accessory_ addSubview:configure];*/
+
+        [self setAutoresizingMask:UIViewAutoresizingFlexibleHeight];
+        [table_ setAutoresizingMask:UIViewAutoresizingFlexibleHeight];
     } return self;
 }
 
@@ -5275,6 +5391,7 @@ bool DepSubstrate(const pkgCache::VerIterator &iterator) {
     [indicator_ release];
     [prompt_ release];
     [progress_ release];
+    [cancel_ release];
     [super dealloc];
 }
 
@@ -5287,13 +5404,31 @@ bool DepSubstrate(const pkgCache::VerIterator &iterator) {
 }
 
 - (void) update {
-    [navbar_ setPrompt:@""];
-    [navbar_ addSubview:overlay_];
+    [UIView beginAnimations:nil context:NULL];
+
+    CGRect ovrframe = [overlay_ frame];
+    ovrframe.origin.y = 0;
+    [overlay_ setFrame:ovrframe];
+
+    CGRect barframe = [navbar_ frame];
+    barframe.origin.y += ovrframe.size.height;
+    [navbar_ setFrame:barframe];
+
+    CGRect trnframe = [transition_ frame];
+    trnframe.origin.y += ovrframe.size.height;
+    trnframe.size.height -= ovrframe.size.height;
+    [transition_ setFrame:trnframe];
+
+    [UIView endAnimations];
+
     [indicator_ startAnimation];
-    [prompt_ setText:@"Updating Database..."];
+    [prompt_ setText:@"Updating Database"];
     [progress_ setProgress:0];
 
+    received_ = 0;
+    last_ = [NSDate timeIntervalSinceReferenceDate];
     updating_ = true;
+    [overlay_ addSubview:cancel_];
 
     [NSThread
         detachNewThreadSelector:@selector(_update)
@@ -5305,11 +5440,26 @@ bool DepSubstrate(const pkgCache::VerIterator &iterator) {
 - (void) _update_ {
     updating_ = false;
 
-    [overlay_ removeFromSuperview];
     [indicator_ stopAnimation];
-    [delegate_ reloadData];
 
-    [self setPrompt:[NSString stringWithFormat:@"Last Updated: %@", GetLastUpdate()]];
+    [UIView beginAnimations:nil context:NULL];
+
+    CGRect ovrframe = [overlay_ frame];
+    ovrframe.origin.y = -ovrframe.size.height;
+    [overlay_ setFrame:ovrframe];
+
+    CGRect barframe = [navbar_ frame];
+    barframe.origin.y -= ovrframe.size.height;
+    [navbar_ setFrame:barframe];
+
+    CGRect trnframe = [transition_ frame];
+    trnframe.origin.y -= ovrframe.size.height;
+    trnframe.size.height += ovrframe.size.height;
+    [transition_ setFrame:trnframe];
+
+    [UIView commitAnimations];
+
+    [delegate_ performSelector:@selector(reloadData) withObject:nil afterDelay:0];
 }
 
 - (id) initWithFrame:(CGRect)frame database:(Database *)database {
@@ -5317,15 +5467,19 @@ bool DepSubstrate(const pkgCache::VerIterator &iterator) {
         database_ = database;
 
         CGRect ovrrect = [navbar_ bounds];
-        ovrrect.size.height = ([UINavigationBar defaultSizeWithPrompt].height - [UINavigationBar defaultSize].height);
+        ovrrect.size.height = [UINavigationBar defaultSize].height;
+        ovrrect.origin.y = -ovrrect.size.height;
 
-        overlay_ = [[UIView alloc] initWithFrame:ovrrect];
+        overlay_ = [[UINavigationBar alloc] initWithFrame:ovrrect];
+        [self addSubview:overlay_];
 
-        bool ugly = [navbar_ _barStyle:NO] == 0;
+        [overlay_ setBarStyle:1];
+        int barstyle = [overlay_ _barStyle:NO];
+        bool ugly = barstyle == 0;
 
         UIProgressIndicatorStyle style = ugly ?
-            kUIProgressIndicatorStyleSmallBlack :
-            kUIProgressIndicatorStyleSmallWhite;
+            kUIProgressIndicatorStyleMediumBrown :
+            kUIProgressIndicatorStyleMediumWhite;
 
         CGSize indsize = [UIProgressIndicator defaultSizeForStyle:style];
         unsigned indoffset = (ovrrect.size.height - indsize.height) / 2;
@@ -5335,22 +5489,22 @@ bool DepSubstrate(const pkgCache::VerIterator &iterator) {
         [indicator_ setStyle:style];
         [overlay_ addSubview:indicator_];
 
-        CGSize prmsize = {200, indsize.width + 4};
+        CGSize prmsize = {215, indsize.height + 4};
 
         CGRect prmrect = {{
             indoffset * 2 + indsize.width,
 #ifdef __OBJC2__
             -1 +
 #endif
-            (ovrrect.size.height - prmsize.height) / 2
+            unsigned(ovrrect.size.height - prmsize.height) / 2
         }, prmsize};
 
-        UIFont *font = [UIFont systemFontOfSize:12];
+        UIFont *font = [UIFont systemFontOfSize:15];
 
         prompt_ = [[UITextLabel alloc] initWithFrame:prmrect];
 
-        [prompt_ setColor:[UIColor colorWithCGColor:(ugly ? Blueish_ : White_)]];
-        [prompt_ setBackgroundColor:[UIColor colorWithCGColor:Clear_]];
+        [prompt_ setColor:[UIColor colorWithCGColor:(ugly ? Blueish_ : Off_)]];
+        [prompt_ setBackgroundColor:[UIColor clearColor]];
         [prompt_ setFont:font];
 
         [overlay_ addSubview:prompt_];
@@ -5365,9 +5519,25 @@ bool DepSubstrate(const pkgCache::VerIterator &iterator) {
         progress_ = [[UIProgressBar alloc] initWithFrame:prgrect];
         [progress_ setStyle:0];
         [overlay_ addSubview:progress_];
+
+        cancel_ = [[UINavigationButton alloc] initWithTitle:@"Cancel" style:UINavigationButtonStyleHighlighted];
+        [cancel_ addTarget:self action:@selector(_onCancel) forControlEvents:UIControlEventTouchUpInside];
+
+        CGRect frame = [cancel_ frame];
+        frame.size.width = 65;
+        frame.origin.x = ovrrect.size.width - frame.size.width - 5;
+        frame.origin.y = (ovrrect.size.height - frame.size.height) / 2;
+        [cancel_ setFrame:frame];
+
+        [cancel_ setBarStyle:barstyle];
     } return self;
 }
 
+- (void) _onCancel {
+    updating_ = false;
+    [cancel_ removeFromSuperview];
+}
+
 - (void) _update {
     NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init];
 
@@ -5398,6 +5568,14 @@ bool DepSubstrate(const pkgCache::VerIterator &iterator) {
 }
 
 - (void) setProgressPercent:(float)percent {
+    [self
+        performSelectorOnMainThread:@selector(_setProgressPercent:)
+        withObject:[NSNumber numberWithFloat:percent]
+        waitUntilDone:YES
+    ];
+}
+
+- (void) startProgress {
 }
 
 - (void) addProgressOutput:(NSString *)output {
@@ -5408,12 +5586,26 @@ bool DepSubstrate(const pkgCache::VerIterator &iterator) {
     ];
 }
 
+- (bool) isCancelling:(size_t)received {
+    NSTimeInterval now = [NSDate timeIntervalSinceReferenceDate];
+    if (received_ != received) {
+        received_ = received;
+        last_ = now;
+    } else if (now - last_ > 15)
+        return true;
+    return !updating_;
+}
+
 - (void) alertSheet:(UIActionSheet *)sheet buttonClicked:(int)button {
     [sheet dismiss];
 }
 
 - (void) _setProgressTitle:(NSString *)title {
-    [prompt_ setText:[title stringByAppendingString:@"..."]];
+    [prompt_ setText:title];
+}
+
+- (void) _setProgressPercent:(NSNumber *)percent {
+    [progress_ setProgress:[percent floatValue]];
 }
 
 - (void) _addProgressOutput:(NSString *)output {
@@ -5592,7 +5784,7 @@ bool DepSubstrate(const pkgCache::VerIterator &iterator) {
         detachNewThreadSelector:@selector(update_)
         toTarget:self
         withObject:nil
-        title:@"Updating Sources..."
+        title:@"Updating Sources"
     ];
 }
 
@@ -5680,7 +5872,7 @@ bool DepSubstrate(const pkgCache::VerIterator &iterator) {
         detachNewThreadSelector:@selector(perform)
         toTarget:database_
         withObject:nil
-        title:@"Running..."
+        title:@"Running"
     ];
 }
 
@@ -5696,7 +5888,7 @@ bool DepSubstrate(const pkgCache::VerIterator &iterator) {
         detachNewThreadSelector:@selector(bootstrap_)
         toTarget:self
         withObject:nil
-        title:@"Bootstrap Install..."
+        title:@"Bootstrap Install"
     ];
 }
 
@@ -5751,34 +5943,8 @@ bool DepSubstrate(const pkgCache::VerIterator &iterator) {
     tag_ = tag;
 }
 
-- (void) fixSpringBoard {
-    pid_t pid = ExecFork();
-    if (pid == 0) {
-        sleep(1);
-
-        if (pid_t child = fork()) {
-            waitpid(child, NULL, 0);
-        } else {
-            execlp("launchctl", "launchctl", "unload", SpringBoard_, NULL);
-            perror("launchctl unload");
-            exit(0);
-        }
-
-        execlp("launchctl", "launchctl", "load", SpringBoard_, NULL);
-        perror("launchctl load");
-        exit(0);
-    }
-}
-
 - (void) applicationWillSuspend {
     [database_ clean];
-
-    if (reload_) {
-#ifndef __OBJC2__
-        [self fixSpringBoard];
-#endif
-}
-
     [super applicationWillSuspend];
 }
 
@@ -6085,7 +6251,8 @@ bool DepSubstrate(const pkgCache::VerIterator &iterator) {
         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("/usr/share", NULL, 0) == -1 && errno == EINVAL /*||
+        readlink("/var/lib", NULL, 0) == -1 && errno == EINVAL*/
     ) {
         [self setIdleTimerDisabled:YES];
 
@@ -6200,6 +6367,7 @@ int main(int argc, char *argv[]) {
 
     App_ = [[NSBundle mainBundle] bundlePath];
     Home_ = NSHomeDirectory();
+    Locale_ = CFLocaleCopyCurrent();
 
     {
         NSString *plist = [Home_ stringByAppendingString:@"/Library/Preferences/com.apple.preferences.sounds.plist"];
@@ -6241,15 +6409,7 @@ int main(int argc, char *argv[]) {
     sysctlbyname("hw.machine", machine, &size, NULL, 0);
     Machine_ = machine;
 
-    if (CFMutableDictionaryRef dict = IOServiceMatching("IOPlatformExpertDevice"))
-        if (io_service_t service = IOServiceGetMatchingService(kIOMasterPortDefault, dict)) {
-            if (CFTypeRef serial = IORegistryEntryCreateCFProperty(service, CFSTR(kIOPlatformSerialNumberKey), kCFAllocatorDefault, 0)) {
-                SerialNumber_ = strdup(CFStringGetCStringPtr((CFStringRef) serial, CFStringGetSystemEncoding()));
-                CFRelease(serial);
-            }
-
-            IOObjectRelease(service);
-        }
+    UniqueID_ = [[UIDevice currentDevice] uniqueIdentifier];
 
     /*AddPreferences(@"/Applications/Preferences.app/Settings-iPhone.plist");
     AddPreferences(@"/Applications/Preferences.app/Settings-iPod.plist");*/
@@ -6282,19 +6442,27 @@ int main(int argc, char *argv[]) {
         [Metadata_ setObject:Sources_ forKey:@"Sources"];
     }
 
+    Documents_ = [[[NSMutableArray alloc] initWithCapacity:4] autorelease];
+
     if (access("/Library/MobileSubstrate/MobileSubstrate.dylib", F_OK) == 0)
         dlopen("/Library/MobileSubstrate/MobileSubstrate.dylib", RTLD_LAZY | RTLD_GLOBAL);
 
     if (access("/User", F_OK) != 0)
         system("/usr/libexec/cydia/firmware.sh");
 
-    Locale_ = CFLocaleCopyCurrent();
+    _assert([[NSFileManager defaultManager]
+        createDirectoryAtPath:@"/var/cache/apt/archives/partial"
+        withIntermediateDirectories:YES
+        attributes:nil
+        error:NULL
+    ]);
+
     space_ = CGColorSpaceCreateDeviceRGB();
 
     Blue_.Set(space_, 0.2, 0.2, 1.0, 1.0);
     Blueish_.Set(space_, 0x19/255.f, 0x32/255.f, 0x50/255.f, 1.0);
     Black_.Set(space_, 0.0, 0.0, 0.0, 1.0);
-    Clear_.Set(space_, 0.0, 0.0, 0.0, 0.0);
+    Off_.Set(space_, 0.9, 0.9, 0.9, 1.0);
     Red_.Set(space_, 1.0, 0.0, 0.0, 1.0);
     White_.Set(space_, 1.0, 1.0, 1.0, 1.0);
     Gray_.Set(space_, 0.4, 0.4, 0.4, 1.0);
@@ -6303,6 +6471,9 @@ int main(int argc, char *argv[]) {
 
     SectionMap_ = [[[NSDictionary alloc] initWithContentsOfFile:[[NSBundle mainBundle] pathForResource:@"Sections" ofType:@"plist"]] autorelease];
 
+    UIApplicationUseLegacyEvents(YES);
+    UIKeyboardDisableAutomaticAppearance();
+
     int value = UIApplicationMain(argc, argv, @"Cydia", @"Cydia");
 
     CGColorSpaceRelease(space_);