]> git.saurik.com Git - cydia.git/blobdiff - MobileCydia.mm
Remove obsolete CydiaSettings.bundle.
[cydia.git] / MobileCydia.mm
index f3fd9a5a0b148f7850bd098b8232d9db2a4dd38a..9ef5db99ae0532225e4581d24e806bb091cb76da 100644 (file)
@@ -41,8 +41,8 @@
 #define USE_SYSTEM_MALLOC 1
 
 /* #include Directives {{{ */
-#include "UICaboodle/UCPlatform.h"
-#include "UICaboodle/UCLocalize.h"
+#include "CyteKit/UCPlatform.h"
+#include "CyteKit/CyteLocalize.h"
 
 #include <objc/objc.h>
 #include <objc/runtime.h>
@@ -117,14 +117,17 @@ extern "C" {
 #include <cstring>
 
 #include <errno.h>
-#include <pcre.h>
 
 #include <Cytore.hpp>
 
-#include "UICaboodle/BrowserView.h"
+#include "CyteKit/CyteWebViewController.h"
+#include "CyteKit/NSString-Cyte.h"
+#include "CyteKit/PerlCompatibleRegEx.hpp"
+#include "CyteKit/WebScriptObject-Cyte.h"
+
 #include "SDURLCache/SDURLCache.h"
 
-#include "substrate.h"
+#include <CydiaSubstrate/CydiaSubstrate.h>
 /* }}} */
 
 /* Profiler {{{ */
@@ -585,23 +588,6 @@ void CFArrayInsertionSortValues(CFMutableArrayRef array, CFRange range, CFCompar
 
 @end
 
-@implementation WebScriptObject (NSFastEnumeration)
-
-- (NSUInteger) countByEnumeratingWithState:(NSFastEnumerationState *)state objects:(id *)objects count:(NSUInteger)count {
-    size_t length([self count] - state->state);
-    if (length <= 0)
-        return 0;
-    else if (length > count)
-        length = count;
-    for (size_t i(0); i != length; ++i)
-        objects[i] = [self objectAtIndex:state->state++];
-    state->itemsPtr = objects;
-    state->mutationsPtr = (unsigned long *) self;
-    return length;
-}
-
-@end
-
 NSUInteger DOMNodeList$countByEnumeratingWithState$objects$count$(DOMNodeList *self, SEL sel, NSFastEnumerationState *state, id *objects, NSUInteger count) {
     size_t length([self length] - state->state);
     if (length <= 0)
@@ -617,9 +603,6 @@ NSUInteger DOMNodeList$countByEnumeratingWithState$objects$count$(DOMNodeList *s
 
 /* Cydia NSString Additions {{{ */
 @interface NSString (Cydia)
-+ (NSString *) stringWithUTF8BytesNoCopy:(const char *)bytes length:(int)length;
-+ (NSString *) stringWithUTF8Bytes:(const char *)bytes length:(int)length withZone:(NSZone *)zone inPool:(apr_pool_t *)pool;
-+ (NSString *) stringWithUTF8Bytes:(const char *)bytes length:(int)length;
 - (NSComparisonResult) compareByPath:(NSString *)other;
 - (NSString *) stringByCachingURLWithCurrentCDN;
 - (NSString *) stringByAddingPercentEscapesIncludingReserved;
@@ -627,20 +610,6 @@ NSUInteger DOMNodeList$countByEnumeratingWithState$objects$count$(DOMNodeList *s
 
 @implementation NSString (Cydia)
 
-+ (NSString *) stringWithUTF8BytesNoCopy:(const char *)bytes length:(int)length {
-    return [[[NSString alloc] initWithBytesNoCopy:const_cast<char *>(bytes) length:length encoding:NSUTF8StringEncoding freeWhenDone:NO] autorelease];
-}
-
-+ (NSString *) stringWithUTF8Bytes:(const char *)bytes length:(int)length withZone:(NSZone *)zone inPool:(apr_pool_t *)pool {
-    char *data(reinterpret_cast<char *>(apr_palloc(pool, length)));
-    memcpy(data, bytes, length);
-    return [[[NSString allocWithZone:zone] initWithBytesNoCopy:data length:length encoding:NSUTF8StringEncoding freeWhenDone:NO] autorelease];
-}
-
-+ (NSString *) stringWithUTF8Bytes:(const char *)bytes length:(int)length {
-    return [[[NSString alloc] initWithBytes:bytes length:length encoding:NSUTF8StringEncoding] autorelease];
-}
-
 - (NSComparisonResult) compareByPath:(NSString *)other {
     NSString *prefix = [self commonPrefixWithString:other options:0];
     size_t length = [prefix length];
@@ -834,69 +803,6 @@ struct NSStringMapEqual :
 };
 /* }}} */
 
-/* Perl-Compatible RegEx {{{ */
-class Pcre {
-  private:
-    pcre *code_;
-    pcre_extra *study_;
-    int capture_;
-    int *matches_;
-    const char *data_;
-
-  public:
-    Pcre() :
-        code_(NULL),
-        study_(NULL)
-    {
-    }
-
-    Pcre(const char *regex) :
-        code_(NULL),
-        study_(NULL)
-    {
-        this->operator =(regex);
-    }
-
-    void operator =(const char *regex) {
-        _assert(code_ == NULL);
-
-        const char *error;
-        int offset;
-        code_ = pcre_compile(regex, 0, &error, &offset, NULL);
-
-        if (code_ == NULL) {
-            lprintf("%d:%s\n", offset, error);
-            _assert(false);
-        }
-
-        pcre_fullinfo(code_, study_, PCRE_INFO_CAPTURECOUNT, &capture_);
-        matches_ = new int[(capture_ + 1) * 3];
-    }
-
-    ~Pcre() {
-        pcre_free(code_);
-        delete matches_;
-    }
-
-    NSString *operator [](size_t match) {
-        return [NSString stringWithUTF8Bytes:(data_ + matches_[match * 2]) length:(matches_[match * 2 + 1] - matches_[match * 2])];
-    }
-
-    bool operator ()(NSString *data) {
-        // XXX: length is for characters, not for bytes
-        return operator ()([data UTF8String], [data length]);
-    }
-
-    bool operator ()(const char *data, size_t size) {
-        data_ = data;
-        return pcre_exec(code_, study_, data, size, 0, 0, matches_, (capture_ + 1) * 3) >= 0;
-    }
-
-    _finline size_t size() const {
-        return capture_;
-    }
-};
-/* }}} */
 /* Mime Addresses {{{ */
 @interface Address : NSObject {
     NSString *name_;
@@ -1693,7 +1599,7 @@ static void PackageImport(const void *key, const void *value, void *context) {
 - (NSString *) host;
 
 - (NSString *) name;
-- (NSString *) description;
+- (NSString *) shortDescription;
 - (NSString *) label;
 - (NSString *) origin;
 - (NSString *) version;
@@ -1730,13 +1636,13 @@ static void PackageImport(const void *key, const void *value, void *context) {
 
 + (NSArray *) _attributeKeys {
     return [NSArray arrayWithObjects:
-        @"description",
         @"distribution",
         @"host",
         @"key",
         @"label",
         @"name",
         @"origin",
+        @"shortDescription",
         @"trusted",
         @"type",
         @"uri",
@@ -1880,7 +1786,7 @@ static void PackageImport(const void *key, const void *value, void *context) {
     return origin_.empty() ? (id) authority_ : origin_;
 }
 
-- (NSString *) description {
+- (NSString *) shortDescription {
     return description_;
 }
 
@@ -3108,7 +3014,10 @@ struct PackageNameOrdering :
 
     [self parse];
 
-    range = [[self shortDescription] rangeOfString:text options:MatchCompareOptions_];
+    NSString *description([self shortDescription]);
+    NSUInteger length([description length]);
+
+    range = [[self shortDescription] rangeOfString:text options:MatchCompareOptions_ range:NSMakeRange(0, std::min<NSUInteger>(length, 100))];
     if (range.location != NSNotFound)
         return YES;
 
@@ -4059,6 +3968,8 @@ static NSString *Warning_;
 @end
 /* }}} */
 
+static NSMutableSet *Diversions_;
+
 @interface Diversion : NSObject {
     Pcre pattern_;
     _H<NSString> key_;
@@ -4078,15 +3989,23 @@ static NSString *Warning_;
 }
 
 - (NSString *) divert:(NSString *)url {
-    if (!pattern_(url))
-        return nil;
+    return !pattern_(url) ? nil : pattern_->*format_;
+}
 
-    size_t count(pattern_.size());
-    id values[count];
-    for (size_t i(0); i != count; ++i)
-        values[i] = pattern_[i + 1];
++ (NSURL *) divertURL:(NSURL *)url {
+  divert:
+    NSString *href([url absoluteString]);
 
-    return [[[NSString alloc] initWithFormat:format_ arguments:reinterpret_cast<va_list>(values)] autorelease];
+    for (Diversion *diversion in Diversions_)
+        if (NSString *diverted = [diversion divert:href]) {
+#if !ForRelease
+            NSLog(@"div: %@", diverted);
+#endif
+            url = [NSURL URLWithString:diverted];
+            goto divert;
+        }
+
+    return url;
 }
 
 - (NSString *) key {
@@ -4120,8 +4039,6 @@ static NSString *Warning_;
 
 @end
 
-static NSMutableSet *Diversions_;
-
 /* Web Scripting {{{ */
 @implementation CydiaObject
 
@@ -4232,6 +4149,10 @@ static NSMutableSet *Diversions_;
         return @"getKernelString";
     else if (selector == @selector(getInstalledPackages))
         return @"getInstalledPackages";
+    else if (selector == @selector(getLocaleIdentifier))
+        return @"getLocaleIdentifier";
+    else if (selector == @selector(getPreferredLanguages))
+        return @"getPreferredLanguages";
     else if (selector == @selector(getPackageById:))
         return @"getPackageById";
     else if (selector == @selector(getSessionValue:))
@@ -4254,6 +4175,8 @@ static NSMutableSet *Diversions_;
         return @"scrollToBottom";
     else if (selector == @selector(setAllowsNavigationAction:))
         return @"setAllowsNavigationAction";
+    else if (selector == @selector(setBadgeValue:))
+        return @"setBadgeValue";
     else if (selector == @selector(setButtonImage:withStyle:toFunction:))
         return @"setButtonImage";
     else if (selector == @selector(setButtonTitle:withStyle:toFunction:))
@@ -4266,8 +4189,10 @@ static NSMutableSet *Diversions_;
         return @"setNavigationBarStyle";
     else if (selector == @selector(setNavigationBarTintRed:green:blue:alpha:))
         return @"setNavigationBarTintColor";
-    else if (selector == @selector(setPopupHook:))
-        return @"setPopupHook";
+    else if (selector == @selector(setPasteboardString:))
+        return @"setPasteboardString";
+    else if (selector == @selector(setPasteboardURL:))
+        return @"setPasteboardURL";
     else if (selector == @selector(setToken:))
         return @"setToken";
     else if (selector == @selector(setViewportWidth:))
@@ -4389,6 +4314,14 @@ static NSMutableSet *Diversions_;
         return (Package *) [NSNull null];
 }
 
+- (NSString *) getLocaleIdentifier {
+    return Locale_ == NULL ? (NSString *) [NSNull null] : (NSString *) CFLocaleGetIdentifier(Locale_);
+}
+
+- (NSArray *) getPreferredLanguages {
+    return Languages_;
+}
+
 - (NSArray *) statfs:(NSString *)path {
     struct statfs stat;
 
@@ -4477,6 +4410,10 @@ static NSMutableSet *Diversions_;
     [indirect_ setButtonTitle:button withStyle:style toFunction:function];
 }
 
+- (void) setBadgeValue:(id)value {
+    [indirect_ performSelectorOnMainThread:@selector(setBadgeValue:) withObject:value waitUntilDone:NO];
+}
+
 - (void) setAllowsNavigationAction:(NSString *)value {
     [indirect_ performSelectorOnMainThread:@selector(setAllowsNavigationActionByNumber:) withObject:value waitUntilDone:NO];
 }
@@ -4499,6 +4436,14 @@ static NSMutableSet *Diversions_;
     [indirect_ performSelectorOnMainThread:@selector(setNavigationBarTintColor:) withObject:color waitUntilDone:NO];
 }
 
+- (void) setPasteboardString:(NSString *)value {
+    [[objc_getClass("UIPasteboard") generalPasteboard] setString:value];
+}
+
+- (void) setPasteboardURL:(NSString *)value {
+    [[objc_getClass("UIPasteboard") generalPasteboard] setURL:[NSURL URLWithString:value]];
+}
+
 - (void) _setToken:(NSString *)token {
     Token_ = token;
 
@@ -4514,10 +4459,6 @@ static NSMutableSet *Diversions_;
     [self performSelectorOnMainThread:@selector(_setToken:) withObject:token waitUntilDone:NO];
 }
 
-- (void) setPopupHook:(id)function {
-    [indirect_ setPopupHook:function];
-}
-
 - (void) scrollToBottom:(NSNumber *)animated {
     [indirect_ performSelectorOnMainThread:@selector(scrollToBottomAnimated:) withObject:animated waitUntilDone:NO];
 }
@@ -4671,7 +4612,7 @@ static NSMutableSet *Diversions_;
 }
 
 - (NSURL *) navigationURL {
-    return [NSURL URLWithString:[NSString stringWithFormat:@"cydia://url/%@", [[[webview_ request] URL] absoluteString]]];
+    return [NSURL URLWithString:[NSString stringWithFormat:@"cydia://url/%@", [[request_ URL] absoluteString]]];
 }
 
 + (void) initialize {
@@ -4688,27 +4629,29 @@ static NSMutableSet *Diversions_;
     WebDataSource *source([frame dataSource]);
     NSURLResponse *response([source response]);
     NSURL *url([response URL]);
+    NSString *scheme([[url scheme] lowercaseString]);
+
+    bool bridged(false);
 
     @synchronized (HostConfig_) {
-        if ([[[url scheme] lowercaseString] isEqualToString:@"https"])
+        if ([scheme isEqualToString:@"file"])
+            bridged = true;
+        else if ([scheme isEqualToString:@"https"])
             if ([BridgedHosts_ containsObject:[url host]])
-                [window setValue:cydia_ forKey:@"cydia"];
+                bridged = true;
     }
+
+    if (bridged)
+        [window setValue:cydia_ forKey:@"cydia"];
+}
+
+- (NSURL *) URLWithURL:(NSURL *)url {
+    return [Diversion divertURL:url];
 }
 
 - (NSURLRequest *) webView:(WebView *)view resource:(id)resource willSendRequest:(NSURLRequest *)request redirectResponse:(NSURLResponse *)response fromDataSource:(WebDataSource *)source {
     NSMutableURLRequest *copy([[super webView:view resource:resource willSendRequest:request redirectResponse:response fromDataSource:source] mutableCopy]);
 
-  divert:
-    NSURL *url([copy URL]);
-    NSString *href([url absoluteString]);
-
-    for (Diversion *diversion in Diversions_)
-        if (NSString *diverted = [diversion divert:href]) {
-            [copy setURL:[NSURL URLWithString:diverted]];
-            goto divert;
-        }
-
     if (System_ != NULL)
         [copy setValue:System_ forHTTPHeaderField:@"X-System"];
     if (Machine_ != NULL)
@@ -4975,13 +4918,16 @@ bool DepSubstrate(const pkgCache::VerIterator &iterator) {
 
             if (state.NewInstall())
                 [installs addObject:name];
+            // XXX: else if (state.Install())
             else if (!state.Delete() && (state.iFlags & pkgDepCache::ReInstall) == pkgDepCache::ReInstall)
                 [reinstalls addObject:name];
+            // XXX: move before previous if
             else if (state.Upgrade())
                 [upgrades addObject:name];
             else if (state.Downgrade())
                 [downgrades addObject:name];
             else if (!state.Delete())
+                // XXX: _assert(state.Keep());
                 continue;
             else if (special_r(name))
                 [issues_ addObject:[NSDictionary dictionaryWithObjectsAndKeys:
@@ -5980,6 +5926,8 @@ bool DepSubstrate(const pkgCache::VerIterator &iterator) {
 }
 
 - (void) viewDidLoad {
+    [super viewDidLoad];
+
     [[self navigationItem] setTitle:UCLocalize("INSTALLED_FILES")];
 }
 
@@ -6169,6 +6117,8 @@ bool DepSubstrate(const pkgCache::VerIterator &iterator) {
 }
 
 - (void) reloadData {
+    [super reloadData];
+
     package_ = [database_ packageWithName:name_];
 
     [buttons_ removeAllObjects];
@@ -6204,8 +6154,6 @@ bool DepSubstrate(const pkgCache::VerIterator &iterator) {
         target:self
         action:@selector(customButtonClicked)
     ] autorelease];
-
-    [super reloadData];
 }
 
 - (bool) isLoading {
@@ -6596,6 +6544,7 @@ bool DepSubstrate(const pkgCache::VerIterator &iterator) {
 - (id) init {
     if ((self = [super init]) != nil) {
         [self setURL:[NSURL URLWithString:[NSString stringWithFormat:@"%@/#!/home/", UI_]]];
+        [self reloadData];
     } return self;
 }
 
@@ -6621,6 +6570,8 @@ bool DepSubstrate(const pkgCache::VerIterator &iterator) {
 }
 
 - (void) viewDidLoad {
+    [super viewDidLoad];
+
     [[self navigationItem] setLeftBarButtonItem:[[[UIBarButtonItem alloc]
         initWithTitle:UCLocalize("ABOUT")
         style:UIBarButtonItemStylePlain
@@ -6629,6 +6580,11 @@ bool DepSubstrate(const pkgCache::VerIterator &iterator) {
     ] autorelease]];
 }
 
+- (void) unloadData {
+    [super unloadData];
+    [self reloadData];
+}
+
 @end
 /* }}} */
 /* Manage Controller {{{ */
@@ -6652,6 +6608,8 @@ bool DepSubstrate(const pkgCache::VerIterator &iterator) {
 }
 
 - (void) viewDidLoad {
+    [super viewDidLoad];
+
     [[self navigationItem] setLeftBarButtonItem:[[[UIBarButtonItem alloc]
         initWithTitle:UCLocalize("SETTINGS")
         style:UIBarButtonItemStylePlain
@@ -6820,7 +6778,14 @@ bool DepSubstrate(const pkgCache::VerIterator &iterator) {
 @end
 /* }}} */
 
-@class CYNavigationController;
+/* Cydia Navigation Controller Interface {{{ */
+@interface UINavigationController (Cydia)
+
+- (NSArray *) navigationURLCollection;
+- (void) unloadData;
+
+@end
+/* }}} */
 
 /* Cydia Tab Bar Controller {{{ */
 @interface CYTabBarController : UITabBarController <
@@ -6845,6 +6810,7 @@ bool DepSubstrate(const pkgCache::VerIterator &iterator) {
 - (void) beginUpdate;
 - (void) raiseBar:(BOOL)animated;
 - (BOOL) updating;
+- (void) unloadData;
 
 @end
 
@@ -6894,11 +6860,17 @@ bool DepSubstrate(const pkgCache::VerIterator &iterator) {
     return items;
 }
 
-- (void) reloadData {
-    for (CYViewController *controller in [self viewControllers])
-        [controller reloadData];
+- (void) unloadData {
+    UIViewController *selected([self selectedViewController]);
+    for (UINavigationController *controller in [self viewControllers])
+        [controller unloadData];
+
+    [selected reloadData];
+
+    if (UIViewController *unselected = [self unselectedViewController])
+        [unselected reloadData];
 
-    [(CYNavigationController *)[self unselectedViewController] reloadData];
+    [super unloadData];
 }
 
 - (void) dealloc {
@@ -7110,20 +7082,9 @@ bool DepSubstrate(const pkgCache::VerIterator &iterator) {
 
 @end
 /* }}} */
-/* Cydia Navigation Controller {{{ */
-@interface CYNavigationController : UINavigationController {
-    _transient Database *database_;
-    _transient id<UINavigationControllerDelegate> delegate_;
-}
 
-- (NSArray *) navigationURLCollection;
-- (id) initWithDatabase:(Database *)database;
-- (void) reloadData;
-
-@end
-
-
-@implementation CYNavigationController
+/* Cydia Navigation Controller Implementation {{{ */
+@implementation UINavigationController (Cydia)
 
 - (NSArray *) navigationURLCollection {
     NSMutableArray *stack([NSMutableArray array]);
@@ -7138,23 +7099,17 @@ bool DepSubstrate(const pkgCache::VerIterator &iterator) {
 }
 
 - (void) reloadData {
-    for (CYViewController *page in [self viewControllers]) {
-        // Only reload controllers that have already loaded.
-        // This prevents a page from accidentally loading too
-        // early if it hasn't been shown on the screen yet.
-        if ([page hasLoaded])
-            [page reloadData];
-    }
-}
+    [super reloadData];
 
-- (void) setDelegate:(id<UINavigationControllerDelegate>)delegate {
-    delegate_ = delegate;
+    if (UIViewController *visible = [self visibleViewController])
+        [visible reloadData];
 }
 
-- (id) initWithDatabase:(Database *)database {
-    if ((self = [super init]) != nil) {
-        database_ = database;
-    } return self;
+- (void) unloadData {
+    for (CYViewController *page in [self viewControllers])
+        [page unloadData];
+
+    [super unloadData];
 }
 
 @end
@@ -7435,6 +7390,8 @@ bool DepSubstrate(const pkgCache::VerIterator &iterator) {
 }
 
 - (void) viewDidLoad {
+    [super viewDidLoad];
+
     [[self navigationItem] setTitle:UCLocalize("SECTIONS")];
 }
 
@@ -7623,6 +7580,8 @@ bool DepSubstrate(const pkgCache::VerIterator &iterator) {
 }
 
 - (void) viewDidLoad {
+    [super viewDidLoad];
+
     [[self navigationItem] setTitle:UCLocalize("CHANGES")];
 }
 
@@ -7838,8 +7797,9 @@ bool DepSubstrate(const pkgCache::VerIterator &iterator) {
 
 - (void) reloadData {
     [self setObject:[search_ text]];
-    [super reloadData];
     [self resetCursor];
+
+    [super reloadData];
 }
 
 - (void) didSelectPackage:(Package *)package {
@@ -8001,6 +7961,8 @@ bool DepSubstrate(const pkgCache::VerIterator &iterator) {
 }
 
 - (void) viewDidLoad {
+    [super viewDidLoad];
+
     [[self navigationItem] setTitle:UCLocalize("SETTINGS")];
 }
 
@@ -8233,6 +8195,7 @@ bool DepSubstrate(const pkgCache::VerIterator &iterator) {
     [key_ release];
     key_ = [[source_ key] retain];
     [self setObject:source_];
+
     [[self navigationItem] setTitle:[source_ label]];
 
     [super reloadData];
@@ -8585,6 +8548,8 @@ bool DepSubstrate(const pkgCache::VerIterator &iterator) {
 }
 
 - (void) viewDidLoad {
+    [super viewDidLoad];
+
     [[self navigationItem] setTitle:UCLocalize("SOURCES")];
     [self updateButtonsForEditingStatus:NO animated:NO];
 }
@@ -8741,6 +8706,8 @@ bool DepSubstrate(const pkgCache::VerIterator &iterator) {
 }
 
 - (void) viewDidLoad {
+    [super viewDidLoad];
+
     [[self navigationItem] setTitle:UCLocalize("WHO_ARE_YOU")];
 
     int index = -1;
@@ -8887,6 +8854,7 @@ bool DepSubstrate(const pkgCache::VerIterator &iterator) {
 
 - (void) reloadData {
     [super reloadData];
+
     [table_ reloadData];
 }
 
@@ -9068,17 +9036,21 @@ bool DepSubstrate(const pkgCache::VerIterator &iterator) {
 }
 
 // Navigation controller for the queuing badge.
-- (CYNavigationController *) queueNavigationController {
+- (UINavigationController *) queueNavigationController {
     NSArray *controllers = [tabbar_ viewControllers];
     return [controllers objectAtIndex:3];
 }
 
+- (void) unloadData {
+    [tabbar_ unloadData];
+}
+
 - (void) _updateData {
     [self _saveConfig];
 
-    [tabbar_ reloadData];
+    [self unloadData];
 
-    CYNavigationController *navigation = [self queueNavigationController];
+    UINavigationController *navigation = [self queueNavigationController];
 
     id queuedelegate = nil;
     if ([[navigation viewControllers] count] > 0)
@@ -9214,7 +9186,7 @@ bool DepSubstrate(const pkgCache::VerIterator &iterator) {
 }
 
 - (void) presentModalViewController:(UIViewController *)controller force:(BOOL)force {
-    UINavigationController *navigation([[[CYNavigationController alloc] initWithRootViewController:controller] autorelease]);
+    UINavigationController *navigation([[[UINavigationController alloc] initWithRootViewController:controller] autorelease]);
     if (IsWildcat_)
         [navigation setModalPresentationStyle:UIModalPresentationFormSheet];
 
@@ -9321,8 +9293,7 @@ bool DepSubstrate(const pkgCache::VerIterator &iterator) {
 
     ConfirmationController *page([[[ConfirmationController alloc] initWithDatabase:database_] autorelease]);
     [page setDelegate:self];
-    CYNavigationController *confirm_([[[CYNavigationController alloc] initWithRootViewController:page] autorelease]);
-    [confirm_ setDelegate:self];
+    UINavigationController *confirm_([[[UINavigationController alloc] initWithRootViewController:page] autorelease]);
 
     if (IsWildcat_)
         [confirm_ setModalPresentationStyle:UIModalPresentationFormSheet];
@@ -9387,11 +9358,7 @@ bool DepSubstrate(const pkgCache::VerIterator &iterator) {
 }
 
 - (void) showSettings {
-    SettingsController *role = [[[SettingsController alloc] initWithDatabase:database_ delegate:self] autorelease];
-    CYNavigationController *nav = [[[CYNavigationController alloc] initWithRootViewController:role] autorelease];
-    if (IsWildcat_)
-        [nav setModalPresentationStyle:UIModalPresentationFormSheet];
-    [tabbar_ presentModalViewController:nav animated:YES];
+    [self presentModalViewController:[[[SettingsController alloc] initWithDatabase:database_ delegate:self] autorelease] force:NO];
 }
 
 - (void) retainNetworkActivityIndicator {
@@ -9541,21 +9508,25 @@ bool DepSubstrate(const pkgCache::VerIterator &iterator) {
     [hud setAutoresizingMask:UIViewAutoresizingFlexibleBoth];
 
     [window_ setUserInteractionEnabled:NO];
-    [hud show:YES];
 
-    UIViewController *target = tabbar_;
-    while ([target modalViewController] != nil) target = [target modalViewController];
-    [[target view] addSubview:hud];
+    UIViewController *target(tabbar_);
+    if (UIViewController *modal = [target modalViewController])
+        target = modal;
+
+    UIView *view([target view]);
+    [view addSubview:hud];
+
+    [hud show:YES];
 
     ++locked_;
     return hud;
 }
 
 - (void) removeProgressHUD:(UIProgressHUD *)hud {
+    --locked_;
     [hud show:NO];
     [hud removeFromSuperview];
     [window_ setUserInteractionEnabled:YES];
-    --locked_;
 }
 
 - (CYViewController *) pageForPackage:(NSString *)name {
@@ -9667,7 +9638,7 @@ bool DepSubstrate(const pkgCache::VerIterator &iterator) {
     CYViewController *page([self pageForURL:url forExternal:external]);
 
     if (page != nil) {
-        CYNavigationController *nav = [[[CYNavigationController alloc] init] autorelease];
+        UINavigationController *nav = [[[UINavigationController alloc] init] autorelease];
         [nav setViewControllers:[NSArray arrayWithObject:page]];
         [tabbar_ setUnselectedViewController:nav];
     }
@@ -9774,7 +9745,7 @@ bool DepSubstrate(const pkgCache::VerIterator &iterator) {
 
     NSMutableArray *controllers([NSMutableArray array]);
     for (UITabBarItem *item in items) {
-        CYNavigationController *controller([[[CYNavigationController alloc] initWithDatabase:database_] autorelease]);
+        UINavigationController *controller([[[UINavigationController alloc] init] autorelease]);
         [controller setTabBarItem:item];
         [controllers addObject:controller];
     }
@@ -9811,6 +9782,9 @@ _trace();
     essential_ = [[NSMutableArray alloc] initWithCapacity:4];
     broken_ = [[NSMutableArray alloc] initWithCapacity:4];
 
+    // XXX: I really need this thing... like, seriously... I'm sorry
+    [[[CYBrowserController alloc] initWithURL:[NSURL URLWithString:[NSString stringWithFormat:@"%@/appcache/", UI_]]] reloadData];
+
     window_ = [[UIWindow alloc] initWithFrame:[[UIScreen mainScreen] bounds]];
     [window_ orderFront:self];
     [window_ makeKey:self];
@@ -9868,7 +9842,7 @@ _trace();
 _trace();
     if (Role_ == nil) {
         [window_ setUserInteractionEnabled:YES];
-        [self presentModalViewController:[[[SettingsController alloc] initWithDatabase:database_ delegate:self] autorelease] force:NO];
+        [self showSettings];
         return;
     } else {
         if ([emulated_ modalViewController] != nil)
@@ -9925,7 +9899,7 @@ _trace();
 
     for (unsigned int tab = 0; tab < [[tabbar_ viewControllers] count]; tab++) {
         NSArray *stack = [items objectAtIndex:tab];
-        CYNavigationController *navigation = [[tabbar_ viewControllers] objectAtIndex:tab];
+        UINavigationController *navigation = [[tabbar_ viewControllers] objectAtIndex:tab];
         NSMutableArray *current = [NSMutableArray array];
 
         for (unsigned int nav = 0; nav < [stack count]; nav++) {
@@ -9995,52 +9969,42 @@ MSHook(void, UIWebDocumentView$_setUIKitDelegate$, UIWebDocumentView *self, SEL
     return _UIWebDocumentView$_setUIKitDelegate$(self, _cmd, delegate);
 }
 
-static NSNumber *shouldPlayKeyboardSounds;
-
-Class $UIHardware;
-
-MSHook(void, UIHardware$_playSystemSound$, Class self, SEL _cmd, int sound) {
-    switch (sound) {
-        case 1104: // Keyboard Button Clicked
-        case 1105: // Keyboard Delete Repeated
-            if (shouldPlayKeyboardSounds == nil) {
-                NSDictionary *dict([[[NSDictionary alloc] initWithContentsOfFile:@"/var/mobile/Library/Preferences/com.apple.preferences.sounds.plist"] autorelease]);
-                shouldPlayKeyboardSounds = [([dict objectForKey:@"keyboard"] ?: (id) kCFBooleanTrue) retain];
-            }
-
-            if (![shouldPlayKeyboardSounds boolValue])
-                break;
+static NSSet *MobilizedFiles_;
 
-        default:
-            _UIHardware$_playSystemSound$(self, _cmd, sound);
+static NSURL *MobilizeURL(NSURL *url) {
+    NSString *path([url path]);
+    if ([path hasPrefix:@"/var/root/"]) {
+        NSString *file([path substringFromIndex:10]);
+        if ([MobilizedFiles_ containsObject:file])
+            url = [NSURL fileURLWithPath:[@"/var/mobile/" stringByAppendingString:file] isDirectory:NO];
     }
-}
 
-Class $UIApplication;
-
-MSHook(void, UIApplication$_updateApplicationAccessibility, UIApplication *self, SEL _cmd) {
-    static BOOL initialized = NO;
-    static BOOL started = NO;
+    return url;
+}
 
-    NSDictionary *dict([[[NSDictionary alloc] initWithContentsOfFile:@"/var/mobile/Library/Preferences/com.apple.Accessibility.plist"] autorelease]);
-    BOOL enabled = [[dict objectForKey:@"VoiceOverTouchEnabled"] boolValue] || [[dict objectForKey:@"VoiceOverTouchEnabledByiTunes"] boolValue];
+Class $CFXPreferencesPropertyListSource;
+@class CFXPreferencesPropertyListSource;
 
-    if ([self respondsToSelector:@selector(_accessibilityBundlePrincipalClass)]) {
-        id bundle = [self performSelector:@selector(_accessibilityBundlePrincipalClass)];
-        if (![bundle respondsToSelector:@selector(_accessibilityStopServer)]) return;
-        if (![bundle respondsToSelector:@selector(_accessibilityStartServer)]) return;
+MSHook(BOOL, CFXPreferencesPropertyListSource$_backingPlistChangedSinceLastSync, CFXPreferencesPropertyListSource *self, SEL _cmd) {
+    NSURL *&url(MSHookIvar<NSURL *>(self, "_url")), *old(url);
+    NSAutoreleasePool *pool([[NSAutoreleasePool alloc] init]);
+    url = MobilizeURL(url);
+    BOOL value(_CFXPreferencesPropertyListSource$_backingPlistChangedSinceLastSync(self, _cmd));
+    //NSLog(@"%@ %s", [url absoluteString], value ? "YES" : "NO");
+    url = old;
+    [pool release];
+    return value;
+}
 
-        if (initialized && !enabled) {
-            initialized = NO;
-            [bundle performSelector:@selector(_accessibilityStopServer)];
-        } else if (enabled) {
-            initialized = YES;
-            if (!started) {
-                started = YES;
-                [bundle performSelector:@selector(_accessibilityStartServer)];
-            }
-        }
-    }
+MSHook(void *, CFXPreferencesPropertyListSource$createPlistFromDisk, CFXPreferencesPropertyListSource *self, SEL _cmd) {
+    NSURL *&url(MSHookIvar<NSURL *>(self, "_url")), *old(url);
+    NSAutoreleasePool *pool([[NSAutoreleasePool alloc] init]);
+    url = MobilizeURL(url);
+    void *value(_CFXPreferencesPropertyListSource$createPlistFromDisk(self, _cmd));
+    //NSLog(@"%@ %@", [url absoluteString], value);
+    url = old;
+    [pool release];
+    return value;
 }
 
 Class $NSURLConnection;
@@ -10106,9 +10070,28 @@ int main(int argc, char *argv[]) { _pooled
 
     PackageName = reinterpret_cast<CYString &(*)(Package *, SEL)>(method_getImplementation(class_getInstanceMethod([Package class], @selector(cyname))));
 
+    MobilizedFiles_ = [NSMutableSet setWithObjects:
+        @"Library/Preferences/com.apple.Accessibility.plist",
+        @"Library/Preferences/com.apple.preferences.sounds.plist",
+    nil];
+
     /* Library Hacks {{{ */
     class_addMethod(objc_getClass("DOMNodeList"), @selector(countByEnumeratingWithState:objects:count:), (IMP) &DOMNodeList$countByEnumeratingWithState$objects$count$, "I20@0:4^{NSFastEnumerationState}8^@12I16");
 
+    $CFXPreferencesPropertyListSource = objc_getClass("CFXPreferencesPropertyListSource");
+
+    Method CFXPreferencesPropertyListSource$_backingPlistChangedSinceLastSync(class_getInstanceMethod($CFXPreferencesPropertyListSource, @selector(_backingPlistChangedSinceLastSync)));
+    if (CFXPreferencesPropertyListSource$_backingPlistChangedSinceLastSync != NULL) {
+        _CFXPreferencesPropertyListSource$_backingPlistChangedSinceLastSync = reinterpret_cast<BOOL (*)(CFXPreferencesPropertyListSource *, SEL)>(method_getImplementation(CFXPreferencesPropertyListSource$_backingPlistChangedSinceLastSync));
+        method_setImplementation(CFXPreferencesPropertyListSource$_backingPlistChangedSinceLastSync, reinterpret_cast<IMP>(&$CFXPreferencesPropertyListSource$_backingPlistChangedSinceLastSync));
+    }
+
+    Method CFXPreferencesPropertyListSource$createPlistFromDisk(class_getInstanceMethod($CFXPreferencesPropertyListSource, @selector(createPlistFromDisk)));
+    if (CFXPreferencesPropertyListSource$createPlistFromDisk != NULL) {
+        _CFXPreferencesPropertyListSource$createPlistFromDisk = reinterpret_cast<void *(*)(CFXPreferencesPropertyListSource *, SEL)>(method_getImplementation(CFXPreferencesPropertyListSource$createPlistFromDisk));
+        method_setImplementation(CFXPreferencesPropertyListSource$createPlistFromDisk, reinterpret_cast<IMP>(&$CFXPreferencesPropertyListSource$createPlistFromDisk));
+    }
+
     $WebDefaultUIKitDelegate = objc_getClass("WebDefaultUIKitDelegate");
     Method UIWebDocumentView$_setUIKitDelegate$(class_getInstanceMethod([WebView class], @selector(_setUIKitDelegate:)));
     if (UIWebDocumentView$_setUIKitDelegate$ != NULL) {
@@ -10122,20 +10105,6 @@ int main(int argc, char *argv[]) { _pooled
         _NSURLConnection$init$ = reinterpret_cast<id (*)(NSURLConnection *, SEL, NSURLRequest *, id, BOOL, int64_t, BOOL, NSDictionary *)>(method_getImplementation(NSURLConnection$init$));
         method_setImplementation(NSURLConnection$init$, reinterpret_cast<IMP>(&$NSURLConnection$init$));
     }
-
-    $UIHardware = objc_getClass("UIHardware");
-    Method UIHardware$_playSystemSound$(class_getClassMethod($UIHardware, @selector(_playSystemSound:)));
-    if (UIHardware$_playSystemSound$ != NULL) {
-        _UIHardware$_playSystemSound$ = reinterpret_cast<void (*)(Class, SEL, int)>(method_getImplementation(UIHardware$_playSystemSound$));
-        method_setImplementation(UIHardware$_playSystemSound$, reinterpret_cast<IMP>(&$UIHardware$_playSystemSound$));
-    }
-
-    $UIApplication = objc_getClass("UIApplication");
-    Method UIApplication$_updateApplicationAccessibility(class_getInstanceMethod($UIApplication, @selector(_updateApplicationAccessibility)));
-    if (UIApplication$_updateApplicationAccessibility != NULL) {
-        _UIApplication$_updateApplicationAccessibility = reinterpret_cast<void (*)(UIApplication *, SEL)>(method_getImplementation(UIApplication$_updateApplicationAccessibility));
-        method_setImplementation(UIApplication$_updateApplicationAccessibility, reinterpret_cast<IMP>(&$UIApplication$_updateApplicationAccessibility));
-    }
     /* }}} */
     /* Set Locale {{{ */
     Locale_ = CFLocaleCopyCurrent();
@@ -10147,16 +10116,23 @@ int main(int argc, char *argv[]) { _pooled
     const char *lang;
     if (Locale_ != NULL)
         lang = [(NSString *) CFLocaleGetIdentifier(Locale_) UTF8String];
-    else if (Languages_ == nil || [Languages_ count] == 0)
+    else if (Languages_ != nil && [Languages_ count] != 0)
+        lang = [[Languages_ objectAtIndex:0] UTF8String];
+    else
         // XXX: consider just setting to C and then falling through?
         lang = NULL;
-    else {
-        lang = [[Languages_ objectAtIndex:0] UTF8String];
-        setenv("LANG", lang, true);
-        std::setlocale(LC_ALL, lang);
+
+    if (lang != NULL) {
+        Pcre pattern("^([a-z][a-z])(?:-[A-Za-z]*)?(_[A-Z][A-Z])?$");
+        lang = !pattern(lang) ? NULL : [pattern->*@"%1$@%2$@" UTF8String];
     }
 
     NSLog(@"Setting Language: %s", lang);
+
+    if (lang != NULL) {
+        setenv("LANG", lang, true);
+        std::setlocale(LC_ALL, lang);
+    }
     /* }}} */
 
     apr_app_initialize(&argc, const_cast<const char * const **>(&argv), NULL);