]> git.saurik.com Git - cydia.git/blobdiff - MobileCydia.mm
The default permission from mktemp is only 600 :/.
[cydia.git] / MobileCydia.mm
index 2fcb90e3df052f78823a2b41dd20e20ae9303f42..addc9418f6ba0383348cf30df22c877e14870f6e 100644 (file)
@@ -1,5 +1,5 @@
 /* Cydia - iPhone UIKit Front-End for Debian APT
 /* Cydia - iPhone UIKit Front-End for Debian APT
- * Copyright (C) 2008-2013  Jay Freeman (saurik)
+ * Copyright (C) 2008-2015  Jay Freeman (saurik)
 */
 
 /* GNU General Public License, Version 3 {{{ */
 */
 
 /* GNU General Public License, Version 3 {{{ */
@@ -26,6 +26,9 @@
 #include "CyteKit/UCPlatform.h"
 #include "CyteKit/Localize.h"
 
 #include "CyteKit/UCPlatform.h"
 #include "CyteKit/Localize.h"
 
+#include <unicode/ustring.h>
+#include <unicode/utrans.h>
+
 #include <objc/objc.h>
 #include <objc/runtime.h>
 
 #include <objc/objc.h>
 #include <objc/runtime.h>
 
@@ -38,7 +41,6 @@
 #include <CoreFoundation/CFInternal.h>
 #endif
 
 #include <CoreFoundation/CFInternal.h>
 #endif
 
-#include <CoreFoundation/CFPriv.h>
 #include <CoreFoundation/CFUniChar.h>
 
 #include <SystemConfiguration/SystemConfiguration.h>
 #include <CoreFoundation/CFUniChar.h>
 
 #include <SystemConfiguration/SystemConfiguration.h>
 #include <WebKit/DOMHTMLIFrameElement.h>
 
 #include <algorithm>
 #include <WebKit/DOMHTMLIFrameElement.h>
 
 #include <algorithm>
+#include <fstream>
 #include <iomanip>
 #include <set>
 #include <sstream>
 #include <string>
 
 #include <iomanip>
 #include <set>
 #include <sstream>
 #include <string>
 
-#include <ext/stdio_filebuf.h>
+#include "fdstream.hpp"
 
 #undef ABS
 
 
 #undef ABS
 
+#include "apt.h"
 #include <apt-pkg/acquire.h>
 #include <apt-pkg/acquire-item.h>
 #include <apt-pkg/algorithms.h>
 #include <apt-pkg/acquire.h>
 #include <apt-pkg/acquire-item.h>
 #include <apt-pkg/algorithms.h>
@@ -81,8 +85,6 @@
 #include <apt-pkg/strutl.h>
 #include <apt-pkg/tagfile.h>
 
 #include <apt-pkg/strutl.h>
 #include <apt-pkg/tagfile.h>
 
-#include <apr-1/apr_pools.h>
-
 #include <sys/types.h>
 #include <sys/stat.h>
 #include <sys/sysctl.h>
 #include <sys/types.h>
 #include <sys/stat.h>
 #include <sys/sysctl.h>
@@ -90,6 +92,7 @@
 #include <sys/mount.h>
 #include <sys/reboot.h>
 
 #include <sys/mount.h>
 #include <sys/reboot.h>
 
+#include <dirent.h>
 #include <fcntl.h>
 #include <notify.h>
 #include <dlfcn.h>
 #include <fcntl.h>
 #include <notify.h>
 #include <dlfcn.h>
@@ -107,11 +110,11 @@ extern "C" {
 #include <Cytore.hpp>
 #include "Sources.h"
 
 #include <Cytore.hpp>
 #include "Sources.h"
 
-#include <CydiaSubstrate/CydiaSubstrate.h>
+#include "Substrate.hpp"
 #include "Menes/Menes.h"
 
 #include "CyteKit/IndirectDelegate.h"
 #include "Menes/Menes.h"
 
 #include "CyteKit/IndirectDelegate.h"
-#include "CyteKit/PerlCompatibleRegEx.hpp"
+#include "CyteKit/RegEx.hpp"
 #include "CyteKit/TableViewCell.h"
 #include "CyteKit/TabBarController.h"
 #include "CyteKit/WebScriptObject-Cyte.h"
 #include "CyteKit/TableViewCell.h"
 #include "CyteKit/TabBarController.h"
 #include "CyteKit/WebScriptObject-Cyte.h"
@@ -160,7 +163,7 @@ class ProfileTime {
 
     void Print() {
         if (total_ != 0)
 
     void Print() {
         if (total_ != 0)
-            std::cerr << std::setw(5) << count_ << ", " << std::setw(7) << total_ << " : " << name_ << std::endl;
+            std::cerr << std::setw(7) << count_ << ", " << std::setw(8) << total_ << " : " << name_ << std::endl;
         total_ = 0;
         count_ = 0;
     }
         total_ = 0;
         count_ = 0;
     }
@@ -206,7 +209,7 @@ extern NSString *Cydia_;
 
 #define ForRelease 1
 #define TraceLogging (1 && !ForRelease)
 
 #define ForRelease 1
 #define TraceLogging (1 && !ForRelease)
-#define HistogramInsertionSort (!ForRelease ? 0 : 0)
+#define HistogramInsertionSort (0 && !ForRelease)
 #define ProfileTimes (0 && !ForRelease)
 #define ForSaurik (0 && !ForRelease)
 #define LogBrowser (0 && !ForRelease)
 #define ProfileTimes (0 && !ForRelease)
 #define ForSaurik (0 && !ForRelease)
 #define LogBrowser (0 && !ForRelease)
@@ -214,7 +217,6 @@ extern NSString *Cydia_;
 #define ManualRefresh (1 && !ForRelease)
 #define ShowInternals (0 && !ForRelease)
 #define AlwaysReload (0 && !ForRelease)
 #define ManualRefresh (1 && !ForRelease)
 #define ShowInternals (0 && !ForRelease)
 #define AlwaysReload (0 && !ForRelease)
-#define TryIndexedCollation (0 && !ForRelease)
 
 #if !TraceLogging
 #undef _trace
 
 #if !TraceLogging
 #undef _trace
@@ -238,14 +240,27 @@ union SplitHash {
 };
 // }}}
 
 };
 // }}}
 
+@implementation NSDictionary (Cydia)
+- (id) invokeUndefinedMethodFromWebScript:(NSString *)name withArguments:(NSArray *)arguments {
+    if (false);
+    else if ([name isEqualToString:@"get"])
+        return [self objectForKey:[arguments objectAtIndex:0]];
+    else if ([name isEqualToString:@"keys"])
+        return [self allKeys];
+    return nil;
+} @end
+
 static NSString *Colon_;
 NSString *Elision_;
 static NSString *Error_;
 static NSString *Warning_;
 
 static NSString *Cache_;
 static NSString *Colon_;
 NSString *Elision_;
 static NSString *Error_;
 static NSString *Warning_;
 
 static NSString *Cache_;
+#define Cache(file) \
+    [NSString stringWithFormat:@"%@/%s", Cache_, file]
 
 static void (*$SBSSetInterceptsMenuButtonForever)(bool);
 
 static void (*$SBSSetInterceptsMenuButtonForever)(bool);
+static NSData *(*$SBSCopyIconImagePNGDataForDisplayIdentifier)(NSString *);
 
 static CFStringRef (*$MGCopyAnswer)(CFStringRef);
 
 
 static CFStringRef (*$MGCopyAnswer)(CFStringRef);
 
@@ -289,13 +304,8 @@ static _finline NSString *CydiaURL(NSString *path) {
     return [[NSString stringWithUTF8String:page] stringByAppendingString:path];
 }
 
     return [[NSString stringWithUTF8String:page] stringByAppendingString:path];
 }
 
-static void ReapZombie(pid_t pid) {
-    int status;
-  wait:
-    if (waitpid(pid, &status, 0) == -1)
-        if (errno == EINTR)
-            goto wait;
-        else _assert(false);
+static NSString *ShellEscape(NSString *value) {
+    return [NSString stringWithFormat:@"'%@'", [value stringByReplacingOccurrencesOfString:@"'" withString:@"'\\''"]];
 }
 
 static _finline void UpdateExternalStatus(uint64_t newStatus) {
 }
 
 static _finline void UpdateExternalStatus(uint64_t newStatus) {
@@ -315,7 +325,7 @@ static CGFloat CYStatusBarHeight() {
 /* NSForcedOrderingSearch doesn't work on the iPhone */
 static const NSStringCompareOptions MatchCompareOptions_ = NSLiteralSearch | NSCaseInsensitiveSearch;
 static const NSStringCompareOptions LaxCompareOptions_ = NSNumericSearch | NSDiacriticInsensitiveSearch | NSWidthInsensitiveSearch | NSCaseInsensitiveSearch;
 /* NSForcedOrderingSearch doesn't work on the iPhone */
 static const NSStringCompareOptions MatchCompareOptions_ = NSLiteralSearch | NSCaseInsensitiveSearch;
 static const NSStringCompareOptions LaxCompareOptions_ = NSNumericSearch | NSDiacriticInsensitiveSearch | NSWidthInsensitiveSearch | NSCaseInsensitiveSearch;
-static const CFStringCompareFlags LaxCompareFlags_ = kCFCompareCaseInsensitive | kCFCompareNonliteral | kCFCompareLocalized | kCFCompareNumerically | kCFCompareWidthInsensitive | kCFCompareForcedOrdering;
+static const CFStringCompareFlags LaxCompareFlags_ = kCFCompareNumerically | kCFCompareWidthInsensitive | kCFCompareForcedOrdering;
 
 /* Insertion Sort {{{ */
 
 
 /* Insertion Sort {{{ */
 
@@ -492,6 +502,10 @@ static _finline CFStringRef CYStringCreate(const char *data, size_t size) {
         CFStringCreateWithBytesNoCopy(kCFAllocatorDefault, reinterpret_cast<const uint8_t *>(data), size, kCFStringEncodingISOLatin1, NO, kCFAllocatorNull);
 }
 
         CFStringCreateWithBytesNoCopy(kCFAllocatorDefault, reinterpret_cast<const uint8_t *>(data), size, kCFStringEncodingISOLatin1, NO, kCFAllocatorNull);
 }
 
+static _finline CFStringRef CYStringCreate(const std::string &data) {
+    return CYStringCreate(data.data(), data.size());
+}
+
 static _finline CFStringRef CYStringCreate(const char *data) {
     return CYStringCreate(data, strlen(data));
 }
 static _finline CFStringRef CYStringCreate(const char *data) {
     return CYStringCreate(data, strlen(data));
 }
@@ -548,14 +562,14 @@ class CYString {
             cache_ = reinterpret_cast<CFStringRef>(CFRetain(rhs.cache_));
     }
 
             cache_ = reinterpret_cast<CFStringRef>(CFRetain(rhs.cache_));
     }
 
-    void copy(apr_pool_t *pool) {
-        char *temp(reinterpret_cast<char *>(apr_palloc(pool, size_ + 1)));
+    void copy(CYPool *pool) {
+        char *temp(pool->malloc<char>(size_ + 1));
         memcpy(temp, data_, size_);
         temp[size_] = '\0';
         data_ = temp;
     }
 
         memcpy(temp, data_, size_);
         temp[size_] = '\0';
         data_ = temp;
     }
 
-    void set(apr_pool_t *pool, const char *data, size_t size) {
+    void set(CYPool *pool, const char *data, size_t size) {
         if (size == 0)
             clear();
         else {
         if (size == 0)
             clear();
         else {
@@ -569,11 +583,11 @@ class CYString {
         }
     }
 
         }
     }
 
-    _finline void set(apr_pool_t *pool, const char *data) {
+    _finline void set(CYPool *pool, const char *data) {
         set(pool, data, data == NULL ? 0 : strlen(data));
     }
 
         set(pool, data, data == NULL ? 0 : strlen(data));
     }
 
-    _finline void set(apr_pool_t *pool, const std::string &rhs) {
+    _finline void set(CYPool *pool, const std::string &rhs) {
         set(pool, rhs.data(), rhs.size());
     }
 
         set(pool, rhs.data(), rhs.size());
     }
 
@@ -715,29 +729,78 @@ static _H<NSString> System_;
 static NSString *SerialNumber_ = nil;
 static NSString *ChipID_ = nil;
 static NSString *BBSNum_ = nil;
 static NSString *SerialNumber_ = nil;
 static NSString *ChipID_ = nil;
 static NSString *BBSNum_ = nil;
-static _H<NSString> Token_;
 static _H<NSString> UniqueID_;
 static _H<NSString> UserAgent_;
 static _H<NSString> Product_;
 static _H<NSString> Safari_;
 
 static _H<NSString> UniqueID_;
 static _H<NSString> UserAgent_;
 static _H<NSString> Product_;
 static _H<NSString> Safari_;
 
+static _H<NSLocale> CollationLocale_;
+static _H<NSArray> CollationThumbs_;
+static std::vector<NSInteger> CollationOffset_;
+static _H<NSArray> CollationTitles_;
+static _H<NSArray> CollationStarts_;
+static UTransliterator *CollationTransl_;
+//static Function<NSString *, NSString *> CollationModify_;
+
+typedef std::basic_string<UChar> ustring;
+static ustring CollationString_;
+
+#define CUC const ustring &str(*reinterpret_cast<const ustring *>(rep))
+#define UC ustring &str(*reinterpret_cast<ustring *>(rep))
+static struct UReplaceableCallbacks CollationUCalls_ = {
+    .length = [](const UReplaceable *rep) -> int32_t { CUC;
+        return str.size();
+    },
+
+    .charAt = [](const UReplaceable *rep, int32_t offset) -> UChar { CUC;
+        //fprintf(stderr, "charAt(%d) : %d\n", offset, str.size());
+        if (offset >= str.size())
+            return 0xffff;
+        return str[offset];
+    },
+
+    .char32At = [](const UReplaceable *rep, int32_t offset) -> UChar32 { CUC;
+        //fprintf(stderr, "char32At(%d) : %d\n", offset, str.size());
+        if (offset >= str.size())
+            return 0xffff;
+        UChar32 c;
+        U16_GET(str.data(), 0, offset, str.size(), c);
+        return c;
+    },
+
+    .replace = [](UReplaceable *rep, int32_t start, int32_t limit, const UChar *text, int32_t length) -> void { UC;
+        //fprintf(stderr, "replace(%d, %d, %d) : %d\n", start, limit, length, str.size());
+        str.replace(start, limit - start, text, length);
+    },
+
+    .extract = [](UReplaceable *rep, int32_t start, int32_t limit, UChar *dst) -> void { UC;
+        //fprintf(stderr, "extract(%d, %d) : %d\n", start, limit, str.size());
+        str.copy(dst, limit - start, start);
+    },
+
+    .copy = [](UReplaceable *rep, int32_t start, int32_t limit, int32_t dest) -> void { UC;
+        //fprintf(stderr, "copy(%d, %d, %d) : %d\n", start, limit, dest, str.size());
+        str.replace(dest, 0, str, start, limit - start);
+    },
+};
+
 static CFLocaleRef Locale_;
 static NSArray *Languages_;
 static CGColorSpaceRef space_;
 
 static CFLocaleRef Locale_;
 static NSArray *Languages_;
 static CGColorSpaceRef space_;
 
+#define CacheState_ "/var/mobile/Library/Caches/com.saurik.Cydia/CacheState.plist"
+#define SavedState_ "/var/mobile/Library/Caches/com.saurik.Cydia/SavedState.plist"
+
 static NSDictionary *SectionMap_;
 static NSDictionary *SectionMap_;
-static NSMutableDictionary *Metadata_;
-static _transient NSMutableDictionary *Settings_;
-static _transient NSMutableDictionary *Packages_;
+static _H<NSDate> Backgrounded_;
 static _transient NSMutableDictionary *Values_;
 static _transient NSMutableDictionary *Sections_;
 _H<NSMutableDictionary> Sources_;
 static _transient NSNumber *Version_;
 static _transient NSMutableDictionary *Values_;
 static _transient NSMutableDictionary *Sections_;
 _H<NSMutableDictionary> Sources_;
 static _transient NSNumber *Version_;
-bool Changed_;
 static time_t now_;
 
 bool IsWildcat_;
 static time_t now_;
 
 bool IsWildcat_;
-static CGFloat ScreenScale_;
+CGFloat ScreenScale_;
 static NSString *Idiom_;
 static _H<NSString> Firmware_;
 static NSString *Major_;
 static NSString *Idiom_;
 static _H<NSString> Firmware_;
 static NSString *Major_;
@@ -745,7 +808,6 @@ static NSString *Major_;
 static _H<NSMutableDictionary> SessionData_;
 static _H<NSObject> HostConfig_;
 static _H<NSMutableSet> BridgedHosts_;
 static _H<NSMutableDictionary> SessionData_;
 static _H<NSObject> HostConfig_;
 static _H<NSMutableSet> BridgedHosts_;
-static _H<NSMutableSet> TokenHosts_;
 static _H<NSMutableSet> InsecureHosts_;
 static _H<NSMutableSet> PipelinedHosts_;
 static _H<NSMutableSet> CachedURLs_;
 static _H<NSMutableSet> InsecureHosts_;
 static _H<NSMutableSet> PipelinedHosts_;
 static _H<NSMutableSet> CachedURLs_;
@@ -761,13 +823,33 @@ inline float Interpolate(float begin, float end, float fraction) {
     return (end - begin) * fraction + begin;
 }
 
     return (end - begin) * fraction + begin;
 }
 
+static inline double Retina(double value) {
+    value *= ScreenScale_;
+    value = round(value);
+    value /= ScreenScale_;
+    return value;
+}
+
+static inline CGRect Retina(CGRect value) {
+    value.origin.x *= ScreenScale_;
+    value.origin.y *= ScreenScale_;
+    value.size.width *= ScreenScale_;
+    value.size.height *= ScreenScale_;
+    value = CGRectIntegral(value);
+    value.origin.x /= ScreenScale_;
+    value.origin.y /= ScreenScale_;
+    value.size.width /= ScreenScale_;
+    value.size.height /= ScreenScale_;
+    return value;
+}
+
 static _finline const char *StripVersion_(const char *version) {
     const char *colon(strchr(version, ':'));
     return colon == NULL ? version : colon + 1;
 }
 
 NSString *LocalizeSection(NSString *section) {
 static _finline const char *StripVersion_(const char *version) {
     const char *colon(strchr(version, ':'));
     return colon == NULL ? version : colon + 1;
 }
 
 NSString *LocalizeSection(NSString *section) {
-    static Pcre title_r("^(.*?) \\((.*)\\)$");
+    static RegEx title_r("(.*?) \\((.*)\\)");
     if (title_r(section)) {
         NSString *parent(title_r[1]);
         NSString *child(title_r[2]);
     if (title_r(section)) {
         NSString *parent(title_r[1]);
         NSString *child(title_r[2]);
@@ -783,17 +865,17 @@ NSString *LocalizeSection(NSString *section) {
 
 NSString *Simplify(NSString *title) {
     const char *data = [title UTF8String];
 
 NSString *Simplify(NSString *title) {
     const char *data = [title UTF8String];
-    size_t size = [title length];
+    size_t size = [title lengthOfBytesUsingEncoding:NSUTF8StringEncoding];
 
 
-    static Pcre square_r("^\\[(.*)\\]$");
+    static RegEx square_r("\\[(.*)\\]");
     if (square_r(data, size))
         return Simplify(square_r[1]);
 
     if (square_r(data, size))
         return Simplify(square_r[1]);
 
-    static Pcre paren_r("^\\((.*)\\)$");
+    static RegEx paren_r("\\((.*)\\)");
     if (paren_r(data, size))
         return Simplify(paren_r[1]);
 
     if (paren_r(data, size))
         return Simplify(paren_r[1]);
 
-    static Pcre title_r("^(.*?) \\((.*)\\)$");
+    static RegEx title_r("(.*?) \\((.*)\\)");
     if (title_r(data, size))
         return Simplify(title_r[1]);
 
     if (title_r(data, size))
         return Simplify(title_r[1]);
 
@@ -801,20 +883,6 @@ NSString *Simplify(NSString *title) {
 }
 /* }}} */
 
 }
 /* }}} */
 
-NSString *GetLastUpdate() {
-    NSDate *update = [Metadata_ objectForKey:@"LastUpdate"];
-
-    if (update == nil)
-        return UCLocalize("NEVER_OR_UNKNOWN");
-
-    CFDateFormatterRef formatter = CFDateFormatterCreate(NULL, Locale_, kCFDateFormatterMediumStyle, kCFDateFormatterMediumStyle);
-    CFStringRef formatted = CFDateFormatterCreateStringWithDate(NULL, formatter, (CFDateRef) update);
-
-    CFRelease(formatter);
-
-    return [(NSString *) formatted autorelease];
-}
-
 bool isSectionVisible(NSString *section) {
     NSDictionary *metadata([Sections_ objectForKey:(section ?: @"")]);
     NSNumber *hidden(metadata == nil ? nil : [metadata objectForKey:@"Hidden"]);
 bool isSectionVisible(NSString *section) {
     NSDictionary *metadata([Sections_ objectForKey:(section ?: @"")]);
     NSNumber *hidden(metadata == nil ? nil : [metadata objectForKey:@"Hidden"]);
@@ -849,6 +917,25 @@ static NSString *CYHex(NSData *data, bool reverse = false) {
     return [NSString stringWithUTF8String:string];
 }
 
     return [NSString stringWithUTF8String:string];
 }
 
+static NSString *VerifySource(NSString *href) {
+    static RegEx href_r("(http(s?)://|file:///)[^# ]*");
+    if (!href_r(href)) {
+        [[[[UIAlertView alloc]
+            initWithTitle:[NSString stringWithFormat:Colon_, Error_, UCLocalize("INVALID_URL")]
+            message:UCLocalize("INVALID_URL_EX")
+            delegate:nil
+            cancelButtonTitle:UCLocalize("OK")
+            otherButtonTitles:nil
+        ] autorelease] show];
+
+        return nil;
+    }
+
+    if (![href hasSuffix:@"/"])
+        href = [href stringByAppendingString:@"/"];
+    return href;
+}
+
 @class Cydia;
 
 /* Delegate Prototypes {{{ */
 @class Cydia;
 
 /* Delegate Prototypes {{{ */
@@ -892,7 +979,7 @@ static NSString *CYHex(NSData *data, bool reverse = false) {
 - (void) _saveConfig;
 - (void) syncData;
 - (void) addSource:(NSDictionary *)source;
 - (void) _saveConfig;
 - (void) syncData;
 - (void) addSource:(NSDictionary *)source;
-- (void) addTrivialSource:(NSString *)href;
+- (BOOL) addTrivialSource:(NSString *)href;
 - (UIProgressHUD *) addProgressHUD;
 - (void) removeProgressHUD:(UIProgressHUD *)hud;
 - (void) showActionSheet:(UIActionSheet *)sheet fromItem:(UIBarButtonItem *)item;
 - (UIProgressHUD *) addProgressHUD;
 - (void) removeProgressHUD:(UIProgressHUD *)hud;
 - (void) showActionSheet:(UIActionSheet *)sheet fromItem:(UIBarButtonItem *)item;
@@ -917,8 +1004,8 @@ class CancelStatus :
         return false;
     }
 
         return false;
     }
 
-    virtual void IMSHit(pkgAcquire::ItemDesc &item) {
-        Done(item);
+    virtual void IMSHit(pkgAcquire::ItemDesc &desc) {
+        Done(desc);
     }
 
     virtual bool Pulse_(pkgAcquire *Owner) = 0;
     }
 
     virtual bool Pulse_(pkgAcquire *Owner) = 0;
@@ -954,30 +1041,30 @@ class CydiaStatus :
         delegate_ = delegate;
     }
 
         delegate_ = delegate;
     }
 
-    virtual void Fetch(pkgAcquire::ItemDesc &item) {
-        NSString *name([NSString stringWithUTF8String:item.ShortDesc.c_str()]);
-        CydiaProgressEvent *event([CydiaProgressEvent eventWithMessage:[NSString stringWithFormat:UCLocalize("DOWNLOADING_"), name] ofType:kCydiaProgressEventTypeStatus forItem:item]);
+    virtual void Fetch(pkgAcquire::ItemDesc &desc) {
+        NSString *name([NSString stringWithUTF8String:desc.ShortDesc.c_str()]);
+        CydiaProgressEvent *event([CydiaProgressEvent eventWithMessage:[NSString stringWithFormat:UCLocalize("DOWNLOADING_"), name] ofType:kCydiaProgressEventTypeStatus forItemDesc:desc]);
         [delegate_ performSelectorOnMainThread:@selector(addProgressEvent:) withObject:event waitUntilDone:YES];
     }
 
         [delegate_ performSelectorOnMainThread:@selector(addProgressEvent:) withObject:event waitUntilDone:YES];
     }
 
-    virtual void Done(pkgAcquire::ItemDesc &item) {
-        NSString *name([NSString stringWithUTF8String:item.ShortDesc.c_str()]);
-        CydiaProgressEvent *event([CydiaProgressEvent eventWithMessage:[NSString stringWithFormat:Colon_, UCLocalize("DONE"), name] ofType:kCydiaProgressEventTypeStatus forItem:item]);
+    virtual void Done(pkgAcquire::ItemDesc &desc) {
+        NSString *name([NSString stringWithUTF8String:desc.ShortDesc.c_str()]);
+        CydiaProgressEvent *event([CydiaProgressEvent eventWithMessage:[NSString stringWithFormat:Colon_, UCLocalize("DONE"), name] ofType:kCydiaProgressEventTypeStatus forItemDesc:desc]);
         [delegate_ performSelectorOnMainThread:@selector(addProgressEvent:) withObject:event waitUntilDone:YES];
     }
 
         [delegate_ performSelectorOnMainThread:@selector(addProgressEvent:) withObject:event waitUntilDone:YES];
     }
 
-    virtual void Fail(pkgAcquire::ItemDesc &item) {
+    virtual void Fail(pkgAcquire::ItemDesc &desc) {
         if (
         if (
-            item.Owner->Status == pkgAcquire::Item::StatIdle ||
-            item.Owner->Status == pkgAcquire::Item::StatDone
+            desc.Owner->Status == pkgAcquire::Item::StatIdle ||
+            desc.Owner->Status == pkgAcquire::Item::StatDone
         )
             return;
 
         )
             return;
 
-        std::string &error(item.Owner->ErrorText);
+        std::string &error(desc.Owner->ErrorText);
         if (error.empty())
             return;
 
         if (error.empty())
             return;
 
-        CydiaProgressEvent *event([CydiaProgressEvent eventWithMessage:[NSString stringWithUTF8String:error.c_str()] ofType:kCydiaProgressEventTypeError forItem:item]);
+        CydiaProgressEvent *event([CydiaProgressEvent eventWithMessage:[NSString stringWithUTF8String:error.c_str()] ofType:kCydiaProgressEventTypeError forItemDesc:desc]);
         [delegate_ performSelectorOnMainThread:@selector(addProgressEvent:) withObject:event waitUntilDone:YES];
     }
 
         [delegate_ performSelectorOnMainThread:@selector(addProgressEvent:) withObject:event waitUntilDone:YES];
     }
 
@@ -1015,9 +1102,10 @@ typedef std::map< unsigned long, _H<Source> > SourceMap;
 
 @interface Database : NSObject {
     NSZone *zone_;
 
 @interface Database : NSObject {
     NSZone *zone_;
-    apr_pool_t *pool_;
+    CYPool pool_;
 
     unsigned era_;
 
     unsigned era_;
+    _H<NSDate> delock_;
 
     pkgCacheFile cache_;
     pkgDepCache::Policy *policy_;
 
     pkgCacheFile cache_;
     pkgDepCache::Policy *policy_;
@@ -1047,6 +1135,7 @@ typedef std::map< unsigned long, _H<Source> > SourceMap;
 
 + (Database *) sharedInstance;
 - (unsigned) era;
 
 + (Database *) sharedInstance;
 - (unsigned) era;
+- (bool) hasPackages;
 
 - (void) _readCydia:(NSNumber *)fd;
 - (void) _readStatus:(NSNumber *)fd;
 
 - (void) _readCydia:(NSNumber *)fd;
 - (void) _readStatus:(NSNumber *)fd;
@@ -1095,6 +1184,7 @@ class SourceStatus :
   private:
     _transient NSObject<FetchDelegate> *delegate_;
     _transient Database *database_;
   private:
     _transient NSObject<FetchDelegate> *delegate_;
     _transient Database *database_;
+    std::set<std::string> fetches_;
 
   public:
     SourceStatus(NSObject<FetchDelegate> *delegate, Database *database) :
 
   public:
     SourceStatus(NSObject<FetchDelegate> *delegate, Database *database) :
@@ -1103,30 +1193,74 @@ class SourceStatus :
     {
     }
 
     {
     }
 
-    void Set(bool fetch, pkgAcquire::ItemDesc &desc) {
-        desc.Owner->ID = 0;
-        [database_ setFetch:fetch forURI:desc.Owner->DescURI().c_str()];
+    void Set(bool fetch, const std::string &uri) {
+        if (fetch) {
+            if (!fetches_.insert(uri).second)
+                return;
+        } else {
+            if (fetches_.erase(uri) == 0)
+                return;
+        }
+
+        //printf("Set(%s, %s)\n", fetch ? "true" : "false", uri.c_str());
+        [database_ setFetch:fetch forURI:uri.c_str()];
+    }
+
+    _finline void Set(bool fetch, pkgAcquire::Item *item) {
+        /*unsigned long ID(fetch ? 1 : 0);
+        if (item->ID == ID)
+            return;
+        item->ID = ID;*/
+        Set(fetch, item->DescURI());
+    }
+
+    void Log(const char *tag, pkgAcquire::Item *item) {
+        //printf("%s(%s) S:%u Q:%u\n", tag, item->DescURI().c_str(), item->Status, item->QueueCounter);
     }
 
     virtual void Fetch(pkgAcquire::ItemDesc &desc) {
     }
 
     virtual void Fetch(pkgAcquire::ItemDesc &desc) {
-        Set(true, desc);
+        Log("Fetch", desc.Owner);
+        Set(true, desc.Owner);
     }
 
     virtual void Done(pkgAcquire::ItemDesc &desc) {
     }
 
     virtual void Done(pkgAcquire::ItemDesc &desc) {
-        Set(false, desc);
+        Log("Done", desc.Owner);
+        Set(false, desc.Owner);
     }
 
     virtual void Fail(pkgAcquire::ItemDesc &desc) {
     }
 
     virtual void Fail(pkgAcquire::ItemDesc &desc) {
-        Set(false, desc);
+        Log("Fail", desc.Owner);
+        Set(false, desc.Owner);
     }
 
     virtual bool Pulse_(pkgAcquire *Owner) {
     }
 
     virtual bool Pulse_(pkgAcquire *Owner) {
-        for (pkgAcquire::ItemCIterator item = Owner->ItemsBegin(); item != Owner->ItemsEnd(); ++item)
-            if ((*item)->ID != 0);
-            else if ((*item)->Status == pkgAcquire::Item::StatIdle) {
-                (*item)->ID = 1;
-                [database_ setFetch:true forURI:(*item)->DescURI().c_str()];
-            } else (*item)->ID = 0;
+        std::set<std::string> fetches;
+        for (pkgAcquire::ItemCIterator item(Owner->ItemsBegin()); item != Owner->ItemsEnd(); ++item) {
+            bool fetch;
+            if ((*item)->QueueCounter == 0)
+                fetch = false;
+            else switch ((*item)->Status) {
+                case pkgAcquire::Item::StatFetching:
+                    fetches.insert((*item)->DescURI());
+                    fetch = true;
+                break;
+
+                default:
+                    fetch = false;
+                break;
+            }
+
+            Log(fetch ? "Pulse<true>" : "Pulse<false>", *item);
+            Set(fetch, *item);
+        }
+
+        std::vector<std::string> stops;
+        std::set_difference(fetches_.begin(), fetches_.end(), fetches.begin(), fetches.end(), std::back_insert_iterator<std::vector<std::string>>(stops));
+        for (std::vector<std::string>::const_iterator stop(stops.begin()); stop != stops.end(); ++stop) {
+            //printf("Stop(%s)\n", stop->c_str());
+            Set(false, *stop);
+        }
+
         return ![delegate_ isSourceCancelled];
     }
 
         return ![delegate_ isSourceCancelled];
     }
 
@@ -1149,10 +1283,10 @@ class SourceStatus :
     return event;
 }
 
     return event;
 }
 
-+ (CydiaProgressEvent *) eventWithMessage:(NSString *)message ofType:(NSString *)type forItem:(pkgAcquire::ItemDesc &)item {
++ (CydiaProgressEvent *) eventWithMessage:(NSString *)message ofType:(NSString *)type forItemDesc:(pkgAcquire::ItemDesc &)desc {
     CydiaProgressEvent *event([self eventWithMessage:message ofType:type]);
 
     CydiaProgressEvent *event([self eventWithMessage:message ofType:type]);
 
-    NSString *description([NSString stringWithUTF8String:item.Description.c_str()]);
+    NSString *description([NSString stringWithUTF8String:desc.Description.c_str()]);
     NSArray *fields([description componentsSeparatedByString:@" "]);
     [event setItem:fields];
 
     NSArray *fields([description componentsSeparatedByString:@" "]);
     [event setItem:fields];
 
@@ -1161,7 +1295,7 @@ class SourceStatus :
         [event setVersion:[fields objectAtIndex:3]];
     }
 
         [event setVersion:[fields objectAtIndex:3]];
     }
 
-    [event setURL:[NSString stringWithUTF8String:item.URI.c_str()]];
+    [event setURL:[NSString stringWithUTF8String:desc.URI.c_str()]];
 
     return event;
 }
 
     return event;
 }
@@ -1287,14 +1421,14 @@ struct PackageValue :
 
     char version_[8];
     char name_[];
 
     char version_[8];
     char name_[];
-};
+} _packed;
 
 struct MetaValue :
     Cytore::Block
 {
     uint32_t active_;
     Cytore::Offset<PackageValue> packages_[1 << 16];
 
 struct MetaValue :
     Cytore::Block
 {
     uint32_t active_;
     Cytore::Offset<PackageValue> packages_[1 << 16];
-};
+} _packed;
 
 static Cytore::File<MetaValue> MetaFile_;
 // }}}
 
 static Cytore::File<MetaValue> MetaFile_;
 // }}}
@@ -1305,7 +1439,7 @@ static PackageValue *PackageFind(const char *name, size_t length, bool *fail = N
     PackageValue *metadata;
 
     Cytore::Offset<PackageValue> *offset(&MetaFile_->packages_[nhash.u16[0]]);
     PackageValue *metadata;
 
     Cytore::Offset<PackageValue> *offset(&MetaFile_->packages_[nhash.u16[0]]);
-    offset: if (offset->IsNull()) {
+    for (;; offset = &metadata->next_) { if (offset->IsNull()) {
         *offset = MetaFile_.New<PackageValue>(length + 1);
         metadata = &MetaFile_.Get(*offset);
 
         *offset = MetaFile_.New<PackageValue>(length + 1);
         metadata = &MetaFile_.Get(*offset);
 
@@ -1317,16 +1451,18 @@ static PackageValue *PackageFind(const char *name, size_t length, bool *fail = N
             memset(metadata, 0, sizeof(*metadata));
         }
 
             memset(metadata, 0, sizeof(*metadata));
         }
 
-        memcpy(metadata->name_, name, length + 1);
+        memcpy(metadata->name_, name, length);
+        metadata->name_[length] = '\0';
         metadata->nhash_ = nhash.u16[1];
     } else {
         metadata = &MetaFile_.Get(*offset);
         metadata->nhash_ = nhash.u16[1];
     } else {
         metadata = &MetaFile_.Get(*offset);
-
-        if (metadata->nhash_ != nhash.u16[1] || strncmp(metadata->name_, name, length + 1) != 0) {
-            offset = &metadata->next_;
-            goto offset;
-        }
-    }
+        if (metadata->nhash_ != nhash.u16[1])
+            continue;
+        if (strncmp(metadata->name_, name, length) != 0)
+            continue;
+        if (metadata->name_[length] != '\0')
+            continue;
+    } break; }
 
     return metadata;
 }
 
     return metadata;
 }
@@ -1375,6 +1511,30 @@ static void PackageImport(const void *key, const void *value, void *context) {
 }
 // }}}
 
 }
 // }}}
 
+static NSDate *GetStatusDate() {
+    return [[[NSFileManager defaultManager] attributesOfItemAtPath:@"/var/lib/dpkg/status" error:NULL] fileModificationDate];
+}
+
+static void SaveConfig(NSObject *lock) {
+    @synchronized (lock) {
+        _trace();
+        MetaFile_.Sync();
+        _trace();
+    }
+
+    CFPreferencesSetMultiple((CFDictionaryRef) [NSDictionary dictionaryWithObjectsAndKeys:
+        Values_, @"CydiaValues",
+        Sections_, @"CydiaSections",
+        (id) Sources_, @"CydiaSources",
+        Version_, @"CydiaVersion",
+    nil], NULL, CFSTR("com.saurik.Cydia"), kCFPreferencesCurrentUser, kCFPreferencesCurrentHost);
+
+    if (!CFPreferencesAppSynchronize(CFSTR("com.saurik.Cydia")))
+        NSLog(@"CFPreferencesAppSynchronize(com.saurik.Cydia) == false");
+
+    CydiaWriteSources();
+}
+
 /* Source Class {{{ */
 @interface Source : NSObject {
     unsigned era_;
 /* Source Class {{{ */
 @interface Source : NSObject {
     unsigned era_;
@@ -1406,7 +1566,7 @@ static void PackageImport(const void *key, const void *value, void *context) {
     _transient NSObject<SourceDelegate> *delegate_;
 }
 
     _transient NSObject<SourceDelegate> *delegate_;
 }
 
-- (Source *) initWithMetaIndex:(metaIndex *)index forDatabase:(Database *)database inPool:(apr_pool_t *)pool;
+- (Source *) initWithMetaIndex:(metaIndex *)index forDatabase:(Database *)database inPool:(CYPool *)pool;
 
 - (NSComparisonResult) compareByName:(Source *)source;
 
 
 - (NSComparisonResult) compareByName:(Source *)source;
 
@@ -1489,7 +1649,7 @@ static void PackageImport(const void *key, const void *value, void *context) {
     return index_;
 }
 
     return index_;
 }
 
-- (void) setMetaIndex:(metaIndex *)index inPool:(apr_pool_t *)pool {
+- (void) setMetaIndex:(metaIndex *)index inPool:(CYPool *)pool {
     trusted_ = index->IsTrusted();
 
     uri_.set(pool, index->GetURI());
     trusted_ = index->IsTrusted();
 
     uri_.set(pool, index->GetURI());
@@ -1499,18 +1659,24 @@ static void PackageImport(const void *key, const void *value, void *context) {
     debReleaseIndex *dindex(dynamic_cast<debReleaseIndex *>(index));
     if (dindex != NULL) {
         std::string file(dindex->MetaIndexURI(""));
     debReleaseIndex *dindex(dynamic_cast<debReleaseIndex *>(index));
     if (dindex != NULL) {
         std::string file(dindex->MetaIndexURI(""));
-        files_.insert(file + "Release.gpg");
-        files_.insert(file + "Release");
         base_.set(pool, file);
 
         base_.set(pool, file);
 
-        std::vector<IndexTarget *> *targets(dindex->ComputeIndexTargets());
-        for (std::vector<IndexTarget *>::const_iterator target(targets->begin()); target != targets->end(); ++target) {
-            std::string file((*target)->URI);
+        pkgAcquire acquire;
+        _profile(Source$setMetaIndex$GetIndexes)
+        dindex->GetIndexes(&acquire, true);
+        _end
+        _profile(Source$setMetaIndex$DescURI)
+        for (pkgAcquire::ItemIterator item(acquire.ItemsBegin()); item != acquire.ItemsEnd(); item++) {
+            std::string file((*item)->DescURI());
+            files_.insert(file);
+            if (file.length() < sizeof("Packages.bz2") || file.substr(file.length() - sizeof("Packages.bz2")) != "/Packages.bz2")
+                continue;
+            file = file.substr(0, file.length() - 4);
             files_.insert(file);
             files_.insert(file + ".gz");
             files_.insert(file);
             files_.insert(file + ".gz");
-            files_.insert(file + ".bz2");
             files_.insert(file + "Index");
             files_.insert(file + "Index");
-        } delete targets;
+        }
+        _end
 
         FileFd fd;
         if (!fd.Open(dindex->MetaIndexFile("Release"), FileFd::ReadOnly))
 
         FileFd fd;
         if (!fd.Open(dindex->MetaIndexFile("Release"), FileFd::ReadOnly))
@@ -1559,13 +1725,15 @@ static void PackageImport(const void *key, const void *value, void *context) {
         authority_ = [url path];
 }
 
         authority_ = [url path];
 }
 
-- (Source *) initWithMetaIndex:(metaIndex *)index forDatabase:(Database *)database inPool:(apr_pool_t *)pool {
+- (Source *) initWithMetaIndex:(metaIndex *)index forDatabase:(Database *)database inPool:(CYPool *)pool {
     if ((self = [super init]) != nil) {
         era_ = [database era];
         database_ = database;
         index_ = index;
 
     if ((self = [super init]) != nil) {
         era_ = [database era];
         database_ = database;
         index_ = index;
 
+        _profile(Source$initWithMetaIndex$setMetaIndex)
         [self setMetaIndex:index inPool:pool];
         [self setMetaIndex:index inPool:pool];
+        _end
     } return self;
 }
 
     } return self;
 }
 
@@ -1629,14 +1797,10 @@ static void PackageImport(const void *key, const void *value, void *context) {
     if (record_ == nil)
         return;
     else if (NSMutableArray *sections = [record_ objectForKey:@"Sections"]) {
     if (record_ == nil)
         return;
     else if (NSMutableArray *sections = [record_ objectForKey:@"Sections"]) {
-        if (![sections containsObject:section]) {
+        if (![sections containsObject:section])
             [sections addObject:section];
             [sections addObject:section];
-            Changed_ = true;
-        }
-    } else {
+    } else
         [record_ setObject:[NSMutableArray arrayWithObject:section] forKey:@"Sections"];
         [record_ setObject:[NSMutableArray arrayWithObject:section] forKey:@"Sections"];
-        Changed_ = true;
-    }
 }
 
 - (bool) addSection:(NSString *)section {
 }
 
 - (bool) addSection:(NSString *)section {
@@ -1652,10 +1816,8 @@ static void PackageImport(const void *key, const void *value, void *context) {
         return;
 
     if (NSMutableArray *sections = [record_ objectForKey:@"Sections"])
         return;
 
     if (NSMutableArray *sections = [record_ objectForKey:@"Sections"])
-        if ([sections containsObject:section]) {
+        if ([sections containsObject:section])
             [sections removeObject:section];
             [sections removeObject:section];
-            Changed_ = true;
-        }
 }
 
 - (bool) removeSection:(NSString *)section {
 }
 
 - (bool) removeSection:(NSString *)section {
@@ -1668,7 +1830,6 @@ static void PackageImport(const void *key, const void *value, void *context) {
 
 - (void) _remove {
     [Sources_ removeObjectForKey:[self key]];
 
 - (void) _remove {
     [Sources_ removeObjectForKey:[self key]];
-    Changed_ = true;
 }
 
 - (bool) remove {
 }
 
 - (bool) remove {
@@ -1946,13 +2107,13 @@ struct ParsedPackage {
 
 @interface Package : NSObject {
     uint32_t era_ : 25;
 
 @interface Package : NSObject {
     uint32_t era_ : 25;
-    uint32_t role_ : 3;
+    @public uint32_t role_ : 3;
     uint32_t essential_ : 1;
     uint32_t obsolete_ : 1;
     uint32_t ignored_ : 1;
     uint32_t pooled_ : 1;
 
     uint32_t essential_ : 1;
     uint32_t obsolete_ : 1;
     uint32_t ignored_ : 1;
     uint32_t pooled_ : 1;
 
-    apr_pool_t *pool_;
+    CYPool *pool_;
 
     uint32_t rank_;
 
 
     uint32_t rank_;
 
@@ -1964,9 +2125,11 @@ struct ParsedPackage {
 
     CYString id_;
     CYString name_;
 
     CYString id_;
     CYString name_;
+    CYString transform_;
 
     CYString latest_;
     CYString installed_;
 
     CYString latest_;
     CYString installed_;
+    time_t upgraded_;
 
     const char *section_;
     _transient NSString *section$_;
 
     const char *section_;
     _transient NSString *section$_;
@@ -1979,8 +2142,8 @@ struct ParsedPackage {
     _H<NSMutableArray> tags_;
 }
 
     _H<NSMutableArray> tags_;
 }
 
-- (Package *) initWithVersion:(pkgCache::VerIterator)version withZone:(NSZone *)zone inPool:(apr_pool_t *)pool database:(Database *)database;
-+ (Package *) packageWithIterator:(pkgCache::PkgIterator)iterator withZone:(NSZone *)zone inPool:(apr_pool_t *)pool database:(Database *)database;
+- (Package *) initWithVersion:(pkgCache::VerIterator)version withZone:(NSZone *)zone inPool:(CYPool *)pool database:(Database *)database;
++ (Package *) packageWithIterator:(pkgCache::PkgIterator)iterator withZone:(NSZone *)zone inPool:(CYPool *)pool database:(Database *)database;
 
 - (pkgCache::PkgIterator) iterator;
 - (void) parse;
 
 - (pkgCache::PkgIterator) iterator;
 - (void) parse;
@@ -2011,7 +2174,6 @@ struct ParsedPackage {
 - (NSString *) installed;
 - (BOOL) uninstalled;
 
 - (NSString *) installed;
 - (BOOL) uninstalled;
 
-- (BOOL) valid;
 - (BOOL) upgradableAndEssential:(BOOL)essential;
 - (BOOL) essential;
 - (BOOL) broken;
 - (BOOL) upgradableAndEssential:(BOOL)essential;
 - (BOOL) essential;
 - (BOOL) broken;
@@ -2056,12 +2218,6 @@ struct ParsedPackage {
 - (void) install;
 - (void) remove;
 
 - (void) install;
 - (void) remove;
 
-- (bool) isUnfilteredAndSearchedForBy:(NSArray *)query;
-- (bool) isUnfilteredAndSelectedForBy:(NSString *)search;
-- (bool) isInstalledAndUnfiltered:(NSNumber *)number;
-- (bool) isVisibleInSection:(NSString *)section source:(Source *)source;
-- (bool) isVisibleInSource:(Source *)source;
-
 @end
 
 uint32_t PackageChangesRadix(Package *self, void *) {
 @end
 
 uint32_t PackageChangesRadix(Package *self, void *) {
@@ -2091,9 +2247,11 @@ uint32_t PackageChangesRadix(Package *self, void *) {
     return _not(uint32_t) - value.key;
 }
 
     return _not(uint32_t) - value.key;
 }
 
+CYString &(*PackageName)(Package *self, SEL sel);
+
 uint32_t PackagePrefixRadix(Package *self, void *context) {
     size_t offset(reinterpret_cast<size_t>(context));
 uint32_t PackagePrefixRadix(Package *self, void *context) {
     size_t offset(reinterpret_cast<size_t>(context));
-    CYString &name([self cyname]);
+    CYString &name(PackageName(self, @selector(cyname)));
 
     size_t size(name.size());
     if (size == 0)
 
     size_t size(name.size());
     if (size == 0)
@@ -2146,46 +2304,50 @@ uint32_t PackagePrefixRadix(Package *self, void *context) {
     return OSSwapInt32(*reinterpret_cast<uint32_t *>(data));
 }
 
     return OSSwapInt32(*reinterpret_cast<uint32_t *>(data));
 }
 
-CYString &(*PackageName)(Package *self, SEL sel);
-
-CFComparisonResult PackageNameCompare(Package *lhs, Package *rhs, void *arg) {
+CFComparisonResult StringNameCompare(CFStringRef lhn, CFStringRef rhn, size_t length) {
     _profile(PackageNameCompare)
     _profile(PackageNameCompare)
-        CYString &lhi(PackageName(lhs, @selector(cyname)));
-        CYString &rhi(PackageName(rhs, @selector(cyname)));
-        CFStringRef lhn(lhi), rhn(rhi);
-
         if (lhn == NULL)
         if (lhn == NULL)
-            return rhn == NULL ? NSOrderedSame : NSOrderedAscending;
+            return rhn == NULL ? kCFCompareEqualTo : kCFCompareLessThan;
         else if (rhn == NULL)
         else if (rhn == NULL)
-            return NSOrderedDescending;
+            return kCFCompareGreaterThan;
+
+        CFIndex length(CFStringGetLength(lhn));
 
         _profile(PackageNameCompare$NumbersLast)
 
         _profile(PackageNameCompare$NumbersLast)
-            if (!lhi.empty() && !rhi.empty()) {
+            if (length != 0 && CFStringGetLength(rhn) != 0) {
                 UniChar lhc(CFStringGetCharacterAtIndex(lhn, 0));
                 UniChar rhc(CFStringGetCharacterAtIndex(rhn, 0));
                 bool lha(CFUniCharIsMemberOf(lhc, kCFUniCharLetterCharacterSet));
                 if (lha != CFUniCharIsMemberOf(rhc, kCFUniCharLetterCharacterSet))
                 UniChar lhc(CFStringGetCharacterAtIndex(lhn, 0));
                 UniChar rhc(CFStringGetCharacterAtIndex(rhn, 0));
                 bool lha(CFUniCharIsMemberOf(lhc, kCFUniCharLetterCharacterSet));
                 if (lha != CFUniCharIsMemberOf(rhc, kCFUniCharLetterCharacterSet))
-                    return lha ? NSOrderedAscending : NSOrderedDescending;
+                    return lha ? kCFCompareLessThan : kCFCompareGreaterThan;
             }
         _end
 
             }
         _end
 
-        CFIndex length = CFStringGetLength(lhn);
-
         _profile(PackageNameCompare$Compare)
         _profile(PackageNameCompare$Compare)
-            return CFStringCompareWithOptionsAndLocale(lhn, rhn, CFRangeMake(0, length), LaxCompareFlags_, Locale_);
+            return CFStringCompareWithOptionsAndLocale(lhn, rhn, CFRangeMake(0, length), LaxCompareFlags_, (CFLocaleRef) (id) CollationLocale_);
         _end
     _end
 }
 
         _end
     _end
 }
 
-CFComparisonResult PackageNameCompare_(Package **lhs, Package **rhs, void *context) {
-    return PackageNameCompare(*lhs, *rhs, context);
+_finline CFComparisonResult StringNameCompare(NSString *lhn, NSString*rhn, size_t length) {
+    return StringNameCompare((CFStringRef) lhn, (CFStringRef) rhn, length);
+}
+
+CFComparisonResult PackageNameCompare(Package *lhs, Package *rhs, void *arg) {
+    CYString &lhn(PackageName(lhs, @selector(cyname)));
+    NSString *rhn(PackageName(rhs, @selector(cyname)));
+    return StringNameCompare(lhn, rhn, lhn.size());
+}
+
+CFComparisonResult PackageNameCompare_(Package **lhs, Package **rhs, void *arg) {
+    return PackageNameCompare(*lhs, *rhs, arg);
 }
 
 struct PackageNameOrdering :
     std::binary_function<Package *, Package *, bool>
 {
     _finline bool operator ()(Package *lhs, Package *rhs) const {
 }
 
 struct PackageNameOrdering :
     std::binary_function<Package *, Package *, bool>
 {
     _finline bool operator ()(Package *lhs, Package *rhs) const {
-        return PackageNameCompare(lhs, rhs, NULL) == NSOrderedAscending;
+        return PackageNameCompare(lhs, rhs, NULL) == kCFCompareLessThan;
     }
 };
 
     }
 };
 
@@ -2197,7 +2359,7 @@ struct PackageNameOrdering :
 
 - (void) dealloc {
     if (!pooled_)
 
 - (void) dealloc {
     if (!pooled_)
-        apr_pool_destroy(pool_);
+        delete pool_;
     if (parsed_ != NULL)
         delete parsed_;
     [super dealloc];
     if (parsed_ != NULL)
         delete parsed_;
     [super dealloc];
@@ -2255,6 +2417,7 @@ struct PackageNameOrdering :
         @"state",
         @"support",
         @"tags",
         @"state",
         @"support",
         @"tags",
+        @"upgraded",
         @"warnings",
     nil];
 }
         @"warnings",
     nil];
 }
@@ -2357,15 +2520,7 @@ struct PackageNameOrdering :
         _end
 
         _profile(Package$parse$Tagline)
         _end
 
         _profile(Package$parse$Tagline)
-            const char *start, *end;
-            if (parser->ShortDesc(start, end)) {
-                const char *stop(reinterpret_cast<const char *>(memchr(start, '\n', end - start)));
-                if (stop == NULL)
-                    stop = end;
-                while (stop != start && stop[-1] == '\r')
-                    --stop;
-                parsed->tagline_.set(pool_, start, stop - start);
-            }
+            parsed->tagline_.set(pool_, parser->ShortDesc());
         _end
 
         _profile(Package$parse$Retain)
         _end
 
         _profile(Package$parse$Retain)
@@ -2379,11 +2534,11 @@ struct PackageNameOrdering :
     _end
 } }
 
     _end
 } }
 
-- (Package *) initWithVersion:(pkgCache::VerIterator)version withZone:(NSZone *)zone inPool:(apr_pool_t *)pool database:(Database *)database {
+- (Package *) initWithVersion:(pkgCache::VerIterator)version withZone:(NSZone *)zone inPool:(CYPool *)pool database:(Database *)database {
     if ((self = [super init]) != nil) {
     _profile(Package$initWithVersion)
         if (pool == NULL)
     if ((self = [super init]) != nil) {
     _profile(Package$initWithVersion)
         if (pool == NULL)
-            apr_pool_create(&pool_, NULL);
+            pool_ = new CYPool();
         else {
             pool_ = pool;
             pooled_ = true;
         else {
             pool_ = pool;
             pooled_ = true;
@@ -2394,20 +2549,15 @@ struct PackageNameOrdering :
 
         version_ = version;
 
 
         version_ = version;
 
-        pkgCache::PkgIterator iterator(version.ParentPkg());
+        pkgCache::PkgIterator iterator(version_.ParentPkg());
         iterator_ = iterator;
 
         _profile(Package$initWithVersion$Version)
         iterator_ = iterator;
 
         _profile(Package$initWithVersion$Version)
-            if (!version_.end())
-                file_ = version_.FileList();
-            else {
-                pkgCache &cache([database_ cache]);
-                file_ = pkgCache::VerFileIterator(cache, cache.VerFileP);
-            }
+            file_ = version_.FileList();
         _end
 
         _profile(Package$initWithVersion$Cache)
         _end
 
         _profile(Package$initWithVersion$Cache)
-            name_.set(NULL, iterator.Display());
+            name_.set(NULL, version_.Display());
 
             latest_.set(NULL, StripVersion_(version_.VerStr()));
 
 
             latest_.set(NULL, StripVersion_(version_.VerStr()));
 
@@ -2416,8 +2566,66 @@ struct PackageNameOrdering :
                 installed_.set(NULL, StripVersion_(current.VerStr()));
         _end
 
                 installed_.set(NULL, StripVersion_(current.VerStr()));
         _end
 
+        _profile(Package$initWithVersion$Transliterate) do {
+            if (CollationTransl_ == NULL)
+                break;
+            if (name_.empty())
+                break;
+
+            _profile(Package$initWithVersion$Transliterate$utf8)
+            const uint8_t *data(reinterpret_cast<const uint8_t *>(name_.data()));
+            for (size_t i(0), e(name_.size()); i != e; ++i)
+                if (data[i] >= 0x80)
+                    goto extended;
+            break; extended:;
+            _end
+
+            UErrorCode code(U_ZERO_ERROR);
+            int32_t length;
+
+            _profile(Package$initWithVersion$Transliterate$u_strFromUTF8WithSub)
+            CollationString_.resize(name_.size());
+            u_strFromUTF8WithSub(&CollationString_[0], CollationString_.size(), &length, name_.data(), name_.size(), 0xfffd, NULL, &code);
+            if (!U_SUCCESS(code))
+                break;
+            CollationString_.resize(length);
+            _end
+
+            _profile(Package$initWithVersion$Transliterate$utrans_trans)
+            length = CollationString_.size();
+            utrans_trans(CollationTransl_, reinterpret_cast<UReplaceable *>(&CollationString_), &CollationUCalls_, 0, &length, &code);
+            if (!U_SUCCESS(code))
+                break;
+            _assert(CollationString_.size() == length);
+            _end
+
+            _profile(Package$initWithVersion$Transliterate$u_strToUTF8WithSub$preflight)
+            u_strToUTF8WithSub(NULL, 0, &length, CollationString_.data(), CollationString_.size(), 0xfffd, NULL, &code);
+            if (code == U_BUFFER_OVERFLOW_ERROR)
+                code = U_ZERO_ERROR;
+            else if (!U_SUCCESS(code))
+                break;
+            _end
+
+            char *transform;
+            _profile(Package$initWithVersion$Transliterate$apr_palloc)
+            transform = pool_->malloc<char>(length);
+            _end
+            _profile(Package$initWithVersion$Transliterate$u_strToUTF8WithSub$transform)
+            u_strToUTF8WithSub(transform, length, NULL, CollationString_.data(), CollationString_.size(), 0xfffd, NULL, &code);
+            if (!U_SUCCESS(code))
+                break;
+            _end
+
+            transform_.set(NULL, transform, length);
+        } while (false); _end
+
         _profile(Package$initWithVersion$Tags)
         _profile(Package$initWithVersion$Tags)
+#ifdef __arm64__
+            pkgCache::TagIterator tag(version_.TagList());
+#else
             pkgCache::TagIterator tag(iterator.TagList());
             pkgCache::TagIterator tag(iterator.TagList());
+#endif
             if (!tag.end()) {
                 tags_ = [NSMutableArray arrayWithCapacity:8];
 
             if (!tag.end()) {
                 tags_ = [NSMutableArray arrayWithCapacity:8];
 
@@ -2455,13 +2663,21 @@ struct PackageNameOrdering :
         _profile(Package$initWithVersion$Metadata)
             const char *mixed(iterator.Name());
             size_t size(strlen(mixed));
         _profile(Package$initWithVersion$Metadata)
             const char *mixed(iterator.Name());
             size_t size(strlen(mixed));
-            char lower[size + 1];
+            static const size_t prefix(sizeof("/var/lib/dpkg/info/") - 1);
+            char lower[prefix + size + 5 + 1];
 
             for (size_t i(0); i != size; ++i)
 
             for (size_t i(0); i != size; ++i)
-                lower[i] = mixed[i] | 0x20;
-            lower[size] = '\0';
+                lower[prefix + i] = mixed[i] | 0x20;
+
+            if (!installed_.empty()) {
+                memcpy(lower, "/var/lib/dpkg/info/", prefix);
+                memcpy(lower + prefix + size, ".list", 6);
+                struct stat info;
+                if (stat(lower, &info) != -1)
+                    upgraded_ = info.st_birthtime;
+            }
 
 
-            PackageValue *metadata(PackageFind(lower, size));
+            PackageValue *metadata(PackageFind(lower + prefix, size));
             metadata_ = metadata;
 
             id_.set(NULL, metadata->name_, size);
             metadata_ = metadata;
 
             id_.set(NULL, metadata->name_, size);
@@ -2496,7 +2712,7 @@ struct PackageNameOrdering :
     _end } return self;
 }
 
     _end } return self;
 }
 
-+ (Package *) packageWithIterator:(pkgCache::PkgIterator)iterator withZone:(NSZone *)zone inPool:(apr_pool_t *)pool database:(Database *)database {
++ (Package *) packageWithIterator:(pkgCache::PkgIterator)iterator withZone:(NSZone *)zone inPool:(CYPool *)pool database:(Database *)database {
     pkgCache::VerIterator version;
 
     _profile(Package$packageWithIterator$GetCandidateVer)
     pkgCache::VerIterator version;
 
     _profile(Package$packageWithIterator$GetCandidateVer)
@@ -2532,6 +2748,21 @@ struct PackageNameOrdering :
     return iterator_;
 }
 
     return iterator_;
 }
 
+- (NSArray *) downgrades {
+    NSMutableArray *versions([NSMutableArray arrayWithCapacity:4]);
+
+    for (auto version(iterator_.VersionList()); !version.end(); ++version) {
+        if (version == version_)
+            continue;
+        Package *package([[[Package allocWithZone:NULL] initWithVersion:version withZone:NULL inPool:NULL database:database_] autorelease]);
+        if ([package source] == nil)
+            continue;
+        [versions addObject:package];
+    }
+
+    return versions;
+}
+
 - (NSString *) section {
     if (section$_ == nil) {
         if (section_ == NULL)
 - (NSString *) section {
     if (section$_ == nil) {
         if (section_ == NULL)
@@ -2551,7 +2782,10 @@ struct PackageNameOrdering :
 }
 
 - (NSString *) longSection {
 }
 
 - (NSString *) longSection {
-    return LocalizeSection([self section]);
+    if (NSString *section = [self section])
+        return LocalizeSection(section);
+    else
+        return nil;
 }
 
 - (NSString *) shortSection {
 }
 
 - (NSString *) shortSection {
@@ -2621,23 +2855,12 @@ struct PackageNameOrdering :
 
 @synchronized (database_) {
     pkgRecords::Parser &parser([database_ records]->Lookup(file_));
 
 @synchronized (database_) {
     pkgRecords::Parser &parser([database_ records]->Lookup(file_));
-
-    const char *start, *end;
-    if (!parser.ShortDesc(start, end))
+    std::string value(parser.ShortDesc());
+    if (value.empty())
         return nil;
         return nil;
-
-    if (end - start > 200)
-        end = start + 200;
-
-    /*
-    if (const char *stop = reinterpret_cast<const char *>(memchr(start, '\n', end - start)))
-        end = stop;
-
-    while (end != start && end[-1] == '\r')
-        --end;
-    */
-
-    return [(id) CYStringCreate(start, end - start) autorelease];
+    if (value.size() > 200)
+        value.resize(200);
+    return [(id) CYStringCreate(value) autorelease];
 } }
 
 - (unichar) index {
 } }
 
 - (unichar) index {
@@ -2689,17 +2912,13 @@ struct PackageNameOrdering :
     return installed_.empty();
 }
 
     return installed_.empty();
 }
 
-- (BOOL) valid {
-    return !version_.end();
-}
-
 - (BOOL) upgradableAndEssential:(BOOL)essential {
     _profile(Package$upgradableAndEssential)
         pkgCache::VerIterator current(iterator_.CurrentVer());
         if (current.end())
             return essential && essential_;
         else
 - (BOOL) upgradableAndEssential:(BOOL)essential {
     _profile(Package$upgradableAndEssential)
         pkgCache::VerIterator current(iterator_.CurrentVer());
         if (current.end())
             return essential && essential_;
         else
-            return !version_.end() && version_ != current;
+            return version_ != current;
     _end
 }
 
     _end
 }
 
@@ -2759,7 +2978,7 @@ struct PackageNameOrdering :
 - (BOOL) hasMode {
 @synchronized (database_) {
     if ([database_ era] != era_ || iterator_.end())
 - (BOOL) hasMode {
 @synchronized (database_) {
     if ([database_ era] != era_ || iterator_.end())
-        return nil;
+        return NO;
 
     pkgDepCache::StateCache &state([database_ cache][iterator_]);
     return state.Mode != pkgDepCache::ModeKeep;
 
     pkgDepCache::StateCache &state([database_ cache][iterator_]);
     return state.Mode != pkgDepCache::ModeKeep;
@@ -2825,7 +3044,7 @@ struct PackageNameOrdering :
         if ([dicon hasPrefix:@"file:///"])
             icon = [UIImage imageAtPath:[[dicon substringFromIndex:7] stringByReplacingPercentEscapesUsingEncoding:NSUTF8StringEncoding]];
     if (icon == nil)
         if ([dicon hasPrefix:@"file:///"])
             icon = [UIImage imageAtPath:[[dicon substringFromIndex:7] stringByReplacingPercentEscapesUsingEncoding:NSUTF8StringEncoding]];
     if (icon == nil)
-        icon = [UIImage applicationImageNamed:@"unknown.png"];
+        icon = [UIImage imageNamed:@"unknown.png"];
     return icon;
 }
 
     return icon;
 }
 
@@ -2910,6 +3129,10 @@ struct PackageNameOrdering :
 } }
 
 - (NSArray *) warnings {
 } }
 
 - (NSArray *) warnings {
+@synchronized (database_) {
+    if ([database_ era] != era_ || file_.end())
+        return nil;
+
     NSMutableArray *warnings([NSMutableArray arrayWithCapacity:4]);
     const char *name(iterator_.Name());
 
     NSMutableArray *warnings([NSMutableArray arrayWithCapacity:4]);
     const char *name(iterator_.Name());
 
@@ -2930,6 +3153,8 @@ struct PackageNameOrdering :
         bool user = false;
         bool _private = false;
         bool stash = false;
         bool user = false;
         bool _private = false;
         bool stash = false;
+        bool dbstash = false;
+        bool dsstore = false;
 
         bool repository = [[self section] isEqualToString:@"Repositories"];
 
 
         bool repository = [[self section] isEqualToString:@"Repositories"];
 
@@ -2943,6 +3168,10 @@ struct PackageNameOrdering :
                     _private = true;
                 else if (!stash && [file isEqualToString:@"/var/stash"])
                     stash = true;
                     _private = true;
                 else if (!stash && [file isEqualToString:@"/var/stash"])
                     stash = true;
+                else if (!dbstash && [file isEqualToString:@"/var/db/stash"])
+                    dbstash = true;
+                else if (!dsstore && [file hasSuffix:@"/.DS_Store"])
+                    dsstore = true;
 
         /* XXX: this is not sensitive enough. only some folders are valid. */
         if (cydia && !repository)
 
         /* XXX: this is not sensitive enough. only some folders are valid. */
         if (cydia && !repository)
@@ -2953,23 +3182,29 @@ struct PackageNameOrdering :
             [warnings addObject:[NSString stringWithFormat:UCLocalize("FILES_INSTALLED_TO"), @"/private"]];
         if (stash)
             [warnings addObject:[NSString stringWithFormat:UCLocalize("FILES_INSTALLED_TO"), @"/var/stash"]];
             [warnings addObject:[NSString stringWithFormat:UCLocalize("FILES_INSTALLED_TO"), @"/private"]];
         if (stash)
             [warnings addObject:[NSString stringWithFormat:UCLocalize("FILES_INSTALLED_TO"), @"/var/stash"]];
+        if (dbstash)
+            [warnings addObject:[NSString stringWithFormat:UCLocalize("FILES_INSTALLED_TO"), @"/var/db/stash"]];
+        if (dsstore)
+            [warnings addObject:[NSString stringWithFormat:UCLocalize("FILES_INSTALLED_TO"), @".DS_Store"]];
     }
 
     return [warnings count] == 0 ? nil : warnings;
     }
 
     return [warnings count] == 0 ? nil : warnings;
-}
+} }
 
 - (NSArray *) applications {
     NSString *me([[NSBundle mainBundle] bundleIdentifier]);
 
     NSMutableArray *applications([NSMutableArray arrayWithCapacity:2]);
 
 
 - (NSArray *) applications {
     NSString *me([[NSBundle mainBundle] bundleIdentifier]);
 
     NSMutableArray *applications([NSMutableArray arrayWithCapacity:2]);
 
-    static Pcre application_r("^/Applications/(.*)\\.app/Info.plist$");
+    static RegEx application_r("/Applications/(.*)\\.app/Info.plist");
     if (NSArray *files = [self files])
         for (NSString *file in files)
             if (application_r(file)) {
                 NSDictionary *info([NSDictionary dictionaryWithContentsOfFile:file]);
     if (NSArray *files = [self files])
         for (NSString *file in files)
             if (application_r(file)) {
                 NSDictionary *info([NSDictionary dictionaryWithContentsOfFile:file]);
+                if (info == nil)
+                    continue;
                 NSString *id([info objectForKey:@"CFBundleIdentifier"]);
                 NSString *id([info objectForKey:@"CFBundleIdentifier"]);
-                if ([id isEqualToString:me])
+                if (id == nil || [id isEqualToString:me])
                     continue;
 
                 NSString *display([info objectForKey:@"CFBundleDisplayName"]);
                     continue;
 
                 NSString *display([info objectForKey:@"CFBundleDisplayName"]);
@@ -3007,6 +3242,14 @@ struct PackageNameOrdering :
     return source_ == (Source *) [NSNull null] ? nil : source_;
 }
 
     return source_ == (Source *) [NSNull null] ? nil : source_;
 }
 
+- (time_t) upgraded {
+    return upgraded_;
+}
+
+- (uint32_t) recent {
+    return std::numeric_limits<uint32_t>::max() - upgraded_;
+}
+
 - (uint32_t) rank {
     return rank_;
 }
 - (uint32_t) rank {
     return rank_;
 }
@@ -3024,6 +3267,7 @@ struct PackageNameOrdering :
     string = [self name];
     length = [string length];
 
     string = [self name];
     length = [string length];
 
+    if (length != 0)
     for (NSString *term in query) {
         range = [string rangeOfString:term options:MatchCompareOptions_];
         if (range.location != NSNotFound)
     for (NSString *term in query) {
         range = [string rangeOfString:term options:MatchCompareOptions_];
         if (range.location != NSNotFound)
@@ -3034,6 +3278,7 @@ struct PackageNameOrdering :
         string = [self id];
         length = [string length];
 
         string = [self id];
         length = [string length];
 
+        if (length != 0)
         for (NSString *term in query) {
             range = [string rangeOfString:term options:MatchCompareOptions_];
             if (range.location != NSNotFound)
         for (NSString *term in query) {
             range = [string rangeOfString:term options:MatchCompareOptions_];
             if (range.location != NSNotFound)
@@ -3045,6 +3290,7 @@ struct PackageNameOrdering :
     length = [string length];
     NSUInteger stop(std::min<NSUInteger>(length, 200));
 
     length = [string length];
     NSUInteger stop(std::min<NSUInteger>(length, 200));
 
+    if (length != 0)
     for (NSString *term in query) {
         range = [string rangeOfString:term options:MatchCompareOptions_ range:NSMakeRange(0, stop)];
         if (range.location != NSNotFound)
     for (NSString *term in query) {
         range = [string rangeOfString:term options:MatchCompareOptions_ range:NSMakeRange(0, stop)];
         if (range.location != NSNotFound)
@@ -3087,7 +3333,7 @@ struct PackageNameOrdering :
 }
 
 - (CYString &) cyname {
 }
 
 - (CYString &) cyname {
-    return name_.empty() ? id_ : name_;
+    return !transform_.empty() ? transform_ : !name_.empty() ? name_ : id_;
 }
 
 - (uint32_t) compareBySection:(NSArray *)sections {
 }
 
 - (uint32_t) compareBySection:(NSArray *)sections {
@@ -3102,6 +3348,9 @@ struct PackageNameOrdering :
 
 - (void) clear {
 @synchronized (database_) {
 
 - (void) clear {
 @synchronized (database_) {
+    if ([database_ era] != era_ || file_.end())
+        return;
+
     pkgProblemResolver *resolver = [database_ resolver];
     resolver->Clear(iterator_);
 
     pkgProblemResolver *resolver = [database_ resolver];
     resolver->Clear(iterator_);
 
@@ -3112,11 +3361,15 @@ struct PackageNameOrdering :
 
 - (void) install {
 @synchronized (database_) {
 
 - (void) install {
 @synchronized (database_) {
+    if ([database_ era] != era_ || file_.end())
+        return;
+
     pkgProblemResolver *resolver = [database_ resolver];
     resolver->Clear(iterator_);
     resolver->Protect(iterator_);
 
     pkgCacheFile &cache([database_ cache]);
     pkgProblemResolver *resolver = [database_ resolver];
     resolver->Clear(iterator_);
     resolver->Protect(iterator_);
 
     pkgCacheFile &cache([database_ cache]);
+    cache->SetCandidateVersion(version_);
     cache->SetReInstall(iterator_, false);
     cache->MarkInstall(iterator_, false);
 
     cache->SetReInstall(iterator_, false);
     cache->MarkInstall(iterator_, false);
 
@@ -3127,6 +3380,9 @@ struct PackageNameOrdering :
 
 - (void) remove {
 @synchronized (database_) {
 
 - (void) remove {
 @synchronized (database_) {
+    if ([database_ era] != era_ || file_.end())
+        return;
+
     pkgProblemResolver *resolver = [database_ resolver];
     resolver->Clear(iterator_);
     resolver->Remove(iterator_);
     pkgProblemResolver *resolver = [database_ resolver];
     resolver->Clear(iterator_);
     resolver->Remove(iterator_);
@@ -3137,68 +3393,11 @@ struct PackageNameOrdering :
     cache->MarkDelete(iterator_, true);
 } }
 
     cache->MarkDelete(iterator_, true);
 } }
 
-- (bool) isUnfilteredAndSearchedForBy:(NSArray *)query {
-    _profile(Package$isUnfilteredAndSearchedForBy)
-        bool value(true);
-
-        _profile(Package$isUnfilteredAndSearchedForBy$Unfiltered)
-            value &= [self unfiltered];
-        _end
-
-        _profile(Package$isUnfilteredAndSearchedForBy$Match)
-            value &= [self matches:query];
-        _end
-
-        return value;
-    _end
-}
-
-- (bool) isUnfilteredAndSelectedForBy:(NSString *)search {
-    if ([search length] == 0)
-        return false;
-
-    _profile(Package$isUnfilteredAndSelectedForBy)
-        bool value(true);
-
-        _profile(Package$isUnfilteredAndSelectedForBy$Unfiltered)
-            value &= [self unfiltered];
-        _end
-
-        _profile(Package$isUnfilteredAndSelectedForBy$Match)
-            value &= [[self name] compare:search options:MatchCompareOptions_ range:NSMakeRange(0, [search length])] == NSOrderedSame;
-        _end
-
-        return value;
-    _end
-}
-
-- (bool) isInstalledAndUnfiltered:(NSNumber *)number {
-    return ![self uninstalled] && role_ <= ([number boolValue] ? 1 : 3);
-}
-
-- (bool) isVisibleInSection:(NSString *)name source:(Source *)source {
-    NSString *section([self section]);
-
-    return (
-        name == nil ||
-        section == nil && [name length] == 0 ||
-        [name isEqualToString:section]
-    ) && (
-        source == nil ||
-        [self source] == source
-    ) && [self visible];
-}
-
-- (bool) isVisibleInSource:(Source *)source {
-    return [self source] == source && [self visible];
-}
-
 @end
 /* }}} */
 /* Section Class {{{ */
 @interface Section : NSObject {
     _H<NSString> name_;
 @end
 /* }}} */
 /* Section Class {{{ */
 @interface Section : NSObject {
     _H<NSString> name_;
-    unichar index_;
     size_t row_;
     size_t count_;
     _H<NSString> localized_;
     size_t row_;
     size_t count_;
     _H<NSString> localized_;
@@ -3208,9 +3407,9 @@ struct PackageNameOrdering :
 - (Section *) initWithName:(NSString *)name localized:(NSString *)localized;
 - (Section *) initWithName:(NSString *)name localize:(BOOL)localize;
 - (Section *) initWithName:(NSString *)name row:(size_t)row localize:(BOOL)localize;
 - (Section *) initWithName:(NSString *)name localized:(NSString *)localized;
 - (Section *) initWithName:(NSString *)name localize:(BOOL)localize;
 - (Section *) initWithName:(NSString *)name row:(size_t)row localize:(BOOL)localize;
-- (Section *) initWithIndex:(unichar)index row:(size_t)row;
+
 - (NSString *) name;
 - (NSString *) name;
-- (unichar) index;
+- (void) setName:(NSString *)name;
 
 - (size_t) row;
 - (size_t) count;
 
 - (size_t) row;
 - (size_t) count;
@@ -3256,28 +3455,18 @@ struct PackageNameOrdering :
 - (Section *) initWithName:(NSString *)name row:(size_t)row localize:(BOOL)localize {
     if ((self = [super init]) != nil) {
         name_ = name;
 - (Section *) initWithName:(NSString *)name row:(size_t)row localize:(BOOL)localize {
     if ((self = [super init]) != nil) {
         name_ = name;
-        index_ = '\0';
         row_ = row;
         if (localize)
             localized_ = LocalizeSection(name_);
     } return self;
 }
 
         row_ = row;
         if (localize)
             localized_ = LocalizeSection(name_);
     } return self;
 }
 
-/* XXX: localize the index thingees */
-- (Section *) initWithIndex:(unichar)index row:(size_t)row {
-    if ((self = [super init]) != nil) {
-        name_ = [NSString stringWithCharacters:&index length:1];
-        index_ = index;
-        row_ = row;
-    } return self;
-}
-
 - (NSString *) name {
     return name_;
 }
 
 - (NSString *) name {
     return name_;
 }
 
-- (unichar) index {
-    return index_;
+- (void) setName:(NSString *)name {
+    name_ = name;
 }
 
 - (size_t) row {
 }
 
 - (size_t) row {
@@ -3335,21 +3524,23 @@ class CydiaLogCleaner :
     CFArrayRemoveAllValues(packages_);
 }
 
     CFArrayRemoveAllValues(packages_);
 }
 
+- (bool) hasPackages {
+    return CFArrayGetCount(packages_) != 0;
+}
+
 - (void) dealloc {
     // XXX: actually implement this thing
     _assert(false);
     [self releasePackages];
 - (void) dealloc {
     // XXX: actually implement this thing
     _assert(false);
     [self releasePackages];
-    apr_pool_destroy(pool_);
     NSRecycleZone(zone_);
     [super dealloc];
 }
 
 - (void) _readCydia:(NSNumber *)fd {
     NSRecycleZone(zone_);
     [super dealloc];
 }
 
 - (void) _readCydia:(NSNumber *)fd {
-    __gnu_cxx::stdio_filebuf<char> ib([fd intValue], std::ios::in);
-    std::istream is(&ib);
+    boost::fdistream is([fd intValue]);
     std::string line;
 
     std::string line;
 
-    static Pcre finish_r("^finish:([^:]*)$");
+    static RegEx finish_r("finish:([^:]*)");
 
     while (std::getline(is, line)) {
         NSAutoreleasePool *pool([[NSAutoreleasePool alloc] init]);
 
     while (std::getline(is, line)) {
         NSAutoreleasePool *pool([[NSAutoreleasePool alloc] init]);
@@ -3372,12 +3563,11 @@ class CydiaLogCleaner :
 }
 
 - (void) _readStatus:(NSNumber *)fd {
 }
 
 - (void) _readStatus:(NSNumber *)fd {
-    __gnu_cxx::stdio_filebuf<char> ib([fd intValue], std::ios::in);
-    std::istream is(&ib);
+    boost::fdistream is([fd intValue]);
     std::string line;
 
     std::string line;
 
-    static Pcre conffile_r("^status: [^ ]* : conffile-prompt : (.*?) *$");
-    static Pcre pmstatus_r("^([^:]*):([^:]*):([^:]*):(.*)$");
+    static RegEx conffile_r("status: [^ ]* : conffile-prompt : (.*?) *");
+    static RegEx pmstatus_r("([^:]*):([^:]*):([^:]*):(.*)");
 
     while (std::getline(is, line)) {
         NSAutoreleasePool *pool([[NSAutoreleasePool alloc] init]);
 
     while (std::getline(is, line)) {
         NSAutoreleasePool *pool([[NSAutoreleasePool alloc] init]);
@@ -3429,8 +3619,7 @@ class CydiaLogCleaner :
 }
 
 - (void) _readOutput:(NSNumber *)fd {
 }
 
 - (void) _readOutput:(NSNumber *)fd {
-    __gnu_cxx::stdio_filebuf<char> ib([fd intValue], std::ios::in);
-    std::istream is(&ib);
+    boost::fdistream is([fd intValue]);
     std::string line;
 
     while (std::getline(is, line)) {
     std::string line;
 
     while (std::getline(is, line)) {
@@ -3457,7 +3646,11 @@ class CydiaLogCleaner :
 @synchronized (self) {
     if (static_cast<pkgDepCache *>(cache_) == NULL)
         return nil;
 @synchronized (self) {
     if (static_cast<pkgDepCache *>(cache_) == NULL)
         return nil;
-    pkgCache::PkgIterator iterator(cache_->FindPkg([name UTF8String]));
+    pkgCache::PkgIterator iterator(cache_->FindPkg([name UTF8String]
+#ifdef __arm64__
+        , "any"
+#endif
+    ));
     return iterator.end() ? nil : [Package packageWithIterator:iterator withZone:NULL inPool:NULL database:self];
 } }
 
     return iterator.end() ? nil : [Package packageWithIterator:iterator withZone:NULL inPool:NULL database:self];
 } }
 
@@ -3470,7 +3663,6 @@ class CydiaLogCleaner :
         lock_ = NULL;
 
         zone_ = NSCreateZone(1024 * 1024, 256 * 1024, NO);
         lock_ = NULL;
 
         zone_ = NSCreateZone(1024 * 1024, 256 * 1024, NO);
-        apr_pool_create(&pool_, NULL);
 
         size_t capacity(MetaFile_->active_);
         if (capacity == 0)
 
         size_t capacity(MetaFile_->active_);
         if (capacity == 0)
@@ -3579,7 +3771,7 @@ class CydiaLogCleaner :
 
         lprintf("%c:[%s]\n", warning ? 'W' : 'E', error.c_str());
 
 
         lprintf("%c:[%s]\n", warning ? 'W' : 'E', error.c_str());
 
-        static Pcre no_pubkey("^GPG error:.* NO_PUBKEY .*$");
+        static RegEx no_pubkey("GPG error:.* NO_PUBKEY .*");
         if (warning && no_pubkey(error.c_str()))
             continue;
 
         if (warning && no_pubkey(error.c_str()))
             continue;
 
@@ -3593,6 +3785,31 @@ class CydiaLogCleaner :
     return [self popErrorWithTitle:title] || !success;
 }
 
     return [self popErrorWithTitle:title] || !success;
 }
 
+- (bool) popErrorWithTitle:(NSString *)title forReadList:(pkgSourceList &)list {
+    if ([self popErrorWithTitle:title forOperation:list.ReadMainList()])
+        return true;
+    return false;
+
+    list.Reset();
+
+    bool error(false);
+
+    if (access("/etc/apt/sources.list", F_OK) == 0)
+        error |= [self popErrorWithTitle:title forOperation:list.ReadAppend("/etc/apt/sources.list")];
+
+    std::string base("/etc/apt/sources.list.d");
+    if (DIR *sources = opendir(base.c_str())) {
+        while (dirent *source = readdir(sources))
+            if (source->d_name[0] != '.' && source->d_namlen > 5 && strcmp(source->d_name + source->d_namlen - 5, ".list") == 0 && strcmp(source->d_name, "cydia.list") != 0)
+                error |= [self popErrorWithTitle:title forOperation:list.ReadAppend((base + "/" + source->d_name).c_str())];
+        closedir(sources);
+    }
+
+    error |= [self popErrorWithTitle:title forOperation:list.ReadAppend(SOURCES_LIST)];
+
+    return error;
+}
+
 - (void) reloadDataWithInvocation:(NSInvocation *)invocation {
 @synchronized (self) {
     ++era_;
 - (void) reloadDataWithInvocation:(NSInvocation *)invocation {
 @synchronized (self) {
     ++era_;
@@ -3620,7 +3837,8 @@ class CydiaLogCleaner :
 
     cache_.Close();
 
 
     cache_.Close();
 
-    apr_pool_clear(pool_);
+    pool_.~CYPool();
+    new (&pool_) CYPool();
 
     NSRecycleZone(zone_);
     zone_ = NSCreateZone(1024 * 1024, 256 * 1024, NO);
 
     NSRecycleZone(zone_);
     zone_ = NSCreateZone(1024 * 1024, 256 * 1024, NO);
@@ -3635,19 +3853,28 @@ class CydiaLogCleaner :
     NSString *title(UCLocalize("DATABASE"));
 
     list_ = new pkgSourceList();
     NSString *title(UCLocalize("DATABASE"));
 
     list_ = new pkgSourceList();
-    if ([self popErrorWithTitle:title forOperation:list_->ReadMainList()])
+    _profile(reloadDataWithInvocation$ReadMainList)
+    if ([self popErrorWithTitle:title forReadList:*list_])
         return;
         return;
+    _end
 
 
+    _profile(reloadDataWithInvocation$Source$initWithMetaIndex)
     for (pkgSourceList::const_iterator source = list_->begin(); source != list_->end(); ++source) {
     for (pkgSourceList::const_iterator source = list_->begin(); source != list_->end(); ++source) {
-        Source *object([[[Source alloc] initWithMetaIndex:*source forDatabase:self inPool:pool_] autorelease]);
+        Source *object([[[Source alloc] initWithMetaIndex:*source forDatabase:self inPool:&pool_] autorelease]);
         [sourceList_ addObject:object];
     }
         [sourceList_ addObject:object];
     }
+    _end
 
     _trace();
     OpProgress progress;
 
     _trace();
     OpProgress progress;
+    bool opened;
   open:
   open:
-    if (!cache_.Open(progress, true)) {
-        // XXX: what if there are errors, but Open() == true? this should be merged with popError:
+    delock_ = GetStatusDate();
+    _profile(reloadDataWithInvocation$pkgCacheFile)
+        opened = cache_.Open(progress, false);
+    _end
+    if (!opened) {
+        // XXX: this block should probably be merged with popError: in some way
         while (!_error->empty()) {
             std::string error;
             bool warning(!_error->PopMessage(error));
         while (!_error->empty()) {
             std::string error;
             bool warning(!_error->PopMessage(error));
@@ -3675,7 +3902,8 @@ class CydiaLogCleaner :
         }
 
         return;
         }
 
         return;
-    }
+    } else if ([self popErrorWithTitle:title forOperation:true])
+        return;
     _trace();
 
     unlink("/tmp/cydia.chk");
     _trace();
 
     unlink("/tmp/cydia.chk");
@@ -3693,20 +3921,26 @@ class CydiaLogCleaner :
         return;
     }
 
         return;
     }
 
+    _profile(reloadDataWithInvocation$pkgApplyStatus)
     if ([self popErrorWithTitle:title forOperation:pkgApplyStatus(cache_)])
         return;
     if ([self popErrorWithTitle:title forOperation:pkgApplyStatus(cache_)])
         return;
+    _end
 
     if (cache_->BrokenCount() != 0) {
 
     if (cache_->BrokenCount() != 0) {
+        _profile(pkgApplyStatus$pkgFixBroken)
         if ([self popErrorWithTitle:title forOperation:pkgFixBroken(cache_)])
             return;
         if ([self popErrorWithTitle:title forOperation:pkgFixBroken(cache_)])
             return;
+        _end
 
         if (cache_->BrokenCount() != 0) {
             [delegate_ addProgressEventOnMainThread:[CydiaProgressEvent eventWithMessage:UCLocalize("STILL_BROKEN_EX") ofType:kCydiaProgressEventTypeError] forTask:title];
             return;
         }
 
 
         if (cache_->BrokenCount() != 0) {
             [delegate_ addProgressEventOnMainThread:[CydiaProgressEvent eventWithMessage:UCLocalize("STILL_BROKEN_EX") ofType:kCydiaProgressEventTypeError] forTask:title];
             return;
         }
 
+        _profile(pkgApplyStatus$pkgMinimizeUpgrade)
         if ([self popErrorWithTitle:title forOperation:pkgMinimizeUpgrade(cache_)])
             return;
         if ([self popErrorWithTitle:title forOperation:pkgMinimizeUpgrade(cache_)])
             return;
+        _end
     }
 
     for (Source *object in (id) sourceList_) {
     }
 
     for (Source *object in (id) sourceList_) {
@@ -3726,14 +3960,13 @@ class CydiaLogCleaner :
         packages.reserve(std::max(10000U, [packages_ count] + 1000));
         packages_ = nil;*/
 
         packages.reserve(std::max(10000U, [packages_ count] + 1000));
         packages_ = nil;*/
 
-        _trace();
-
+        _profile(reloadDataWithInvocation$packageWithIterator)
         for (pkgCache::PkgIterator iterator = cache_->PkgBegin(); !iterator.end(); ++iterator)
         for (pkgCache::PkgIterator iterator = cache_->PkgBegin(); !iterator.end(); ++iterator)
-            if (Package *package = [Package packageWithIterator:iterator withZone:zone_ inPool:pool_ database:self])
+            if (Package *package = [Package packageWithIterator:iterator withZone:zone_ inPool:&pool_ database:self])
                 //packages.push_back(package);
                 CFArrayAppendValue(packages_, CFRetain(package));
                 //packages.push_back(package);
                 CFArrayAppendValue(packages_, CFRetain(package));
+        _end
 
 
-        _trace();
 
         /*if (packages.empty())
             packages_ = [[NSArray alloc] init];
 
         /*if (packages.empty())
             packages_ = [[NSArray alloc] init];
@@ -3741,35 +3974,43 @@ class CydiaLogCleaner :
             packages_ = [[NSArray alloc] initWithObjects:&packages.front() count:packages.size()];
         _trace();*/
 
             packages_ = [[NSArray alloc] initWithObjects:&packages.front() count:packages.size()];
         _trace();*/
 
-        [(NSMutableArray *) packages_ radixSortUsingFunction:reinterpret_cast<MenesRadixSortFunction>(&PackagePrefixRadix) withContext:reinterpret_cast<void *>(16)];
+        _profile(reloadDataWithInvocation$radix$8)
+        [(NSMutableArray *) packages_ radixSortUsingFunction:reinterpret_cast<MenesRadixSortFunction>(&PackagePrefixRadix) withContext:reinterpret_cast<void *>(8)];
+        _end
+
+        _profile(reloadDataWithInvocation$radix$4)
         [(NSMutableArray *) packages_ radixSortUsingFunction:reinterpret_cast<MenesRadixSortFunction>(&PackagePrefixRadix) withContext:reinterpret_cast<void *>(4)];
         [(NSMutableArray *) packages_ radixSortUsingFunction:reinterpret_cast<MenesRadixSortFunction>(&PackagePrefixRadix) withContext:reinterpret_cast<void *>(4)];
-        [(NSMutableArray *) packages_ radixSortUsingFunction:reinterpret_cast<MenesRadixSortFunction>(&PackagePrefixRadix) withContext:reinterpret_cast<void *>(0)];
+        _end
 
 
-        /*_trace();
-        PrintTimes();
-        _trace();*/
+        _profile(reloadDataWithInvocation$radix$0)
+        [(NSMutableArray *) packages_ radixSortUsingFunction:reinterpret_cast<MenesRadixSortFunction>(&PackagePrefixRadix) withContext:reinterpret_cast<void *>(0)];
+        _end
 
 
-        _trace();
+        _profile(reloadDataWithInvocation$insertion)
+        CFArrayInsertionSortValues(packages_, CFRangeMake(0, CFArrayGetCount(packages_)), reinterpret_cast<CFComparatorFunction>(&PackageNameCompare), NULL);
+        _end
 
 
-        /*if (!packages.empty())
-            CFQSortArray(&packages.front(), packages.size(), sizeof(packages.front()), reinterpret_cast<CFComparatorFunction>(&PackageNameCompare_), NULL);*/
-        //std::sort(packages.begin(), packages.end(), PackageNameOrdering());
+        /*_profile(reloadDataWithInvocation$CFQSortArray)
+        CFQSortArray(&packages.front(), packages.size(), sizeof(packages.front()), reinterpret_cast<CFComparatorFunction>(&PackageNameCompare_), NULL);
+        _end*/
 
 
-        //CFArraySortValues((CFMutableArrayRef) packages_, CFRangeMake(0, [packages_ count]), reinterpret_cast<CFComparatorFunction>(&PackageNameCompare), NULL);
+        /*_profile(reloadDataWithInvocation$stdsort)
+        std::sort(packages.begin(), packages.end(), PackageNameOrdering());
+        _end*/
 
 
-        CFArrayInsertionSortValues(packages_, CFRangeMake(0, CFArrayGetCount(packages_)), reinterpret_cast<CFComparatorFunction>(&PackageNameCompare), NULL);
+        /*_profile(reloadDataWithInvocation$CFArraySortValues)
+        CFArraySortValues((CFMutableArrayRef) packages_, CFRangeMake(0, [packages_ count]), reinterpret_cast<CFComparatorFunction>(&PackageNameCompare), NULL);
+        _end*/
 
 
-        //[packages_ sortUsingFunction:reinterpret_cast<NSComparisonResult (*)(id, id, void *)>(&PackageNameCompare) context:NULL];
+        /*_profile(reloadDataWithInvocation$sortUsingFunction)
+        [packages_ sortUsingFunction:reinterpret_cast<NSComparisonResult (*)(id, id, void *)>(&PackageNameCompare) context:NULL];
+        _end*/
 
 
-        _trace();
 
         size_t count(CFArrayGetCount(packages_));
         MetaFile_->active_ = count;
 
         size_t count(CFArrayGetCount(packages_));
         MetaFile_->active_ = count;
-
         for (size_t index(0); index != count; ++index)
             [(Package *) CFArrayGetValueAtIndex(packages_, index) setIndex:index];
         for (size_t index(0); index != count; ++index)
             [(Package *) CFArrayGetValueAtIndex(packages_, index) setIndex:index];
-
-        _trace();
     }
 } }
 
     }
 } }
 
@@ -3786,7 +4027,7 @@ class CydiaLogCleaner :
 } }
 
 - (void) configure {
 } }
 
 - (void) configure {
-    NSString *dpkg = [NSString stringWithFormat:@"dpkg --configure -a --status-fd %u", statusfd_];
+    NSString *dpkg = [NSString stringWithFormat:@"/usr/libexec/cydo --configure -a --status-fd %u", statusfd_];
     _trace();
     system([dpkg UTF8String]);
     _trace();
     _trace();
     system([dpkg UTF8String]);
     _trace();
@@ -3830,7 +4071,7 @@ class CydiaLogCleaner :
         return false;
 
     pkgSourceList list;
         return false;
 
     pkgSourceList list;
-    if ([self popErrorWithTitle:title forOperation:list.ReadMainList()])
+    if ([self popErrorWithTitle:title forReadList:list])
         return false;
 
     manager_ = (_system->CreatePM(cache_));
         return false;
 
     manager_ = (_system->CreatePM(cache_));
@@ -3848,7 +4089,7 @@ class CydiaLogCleaner :
 
     NSMutableArray *before = [NSMutableArray arrayWithCapacity:16]; {
         pkgSourceList list;
 
     NSMutableArray *before = [NSMutableArray arrayWithCapacity:16]; {
         pkgSourceList list;
-        if ([self popErrorWithTitle:title forOperation:list.ReadMainList()])
+        if ([self popErrorWithTitle:title forReadList:list])
             return;
         for (pkgSourceList::const_iterator source = list.begin(); source != list.end(); ++source)
             [before addObject:[NSString stringWithUTF8String:(*source)->GetURI().c_str()]];
             return;
         for (pkgSourceList::const_iterator source = list.begin(); source != list.end(); ++source)
             [before addObject:[NSString stringWithUTF8String:(*source)->GetURI().c_str()]];
@@ -3889,8 +4130,25 @@ class CydiaLogCleaner :
     if (substrate)
         RestartSubstrate_ = true;
 
     if (substrate)
         RestartSubstrate_ = true;
 
-    _system->UnLock();
-    pkgPackageManager::OrderResult result = manager_->DoInstall(statusfd_);
+    if (![delock_ isEqual:GetStatusDate()]) {
+        [delegate_ addProgressEventOnMainThread:[CydiaProgressEvent eventWithMessage:UCLocalize("DPKG_LOCKED") ofType:kCydiaProgressEventTypeError] forTask:title];
+        return;
+    }
+
+    delock_ = nil;
+
+    pkgPackageManager::OrderResult result(manager_->DoInstall(statusfd_));
+
+    NSString *oextended(@"/var/lib/apt/extended_states");
+    NSString *nextended(Cache("extended_states"));
+
+    struct stat info;
+    if (stat([nextended UTF8String], &info) != -1 && (info.st_mode & S_IFMT) == S_IFREG)
+        system([[NSString stringWithFormat:@"/usr/libexec/cydia/cydo /bin/cp --remove-destination %@ %@", ShellEscape(nextended), ShellEscape(oextended)] UTF8String]);
+
+    unlink([nextended UTF8String]);
+    symlink([oextended UTF8String], [nextended UTF8String]);
+
     if ([self popErrorWithTitle:title])
         return;
 
     if ([self popErrorWithTitle:title])
         return;
 
@@ -3906,7 +4164,7 @@ class CydiaLogCleaner :
 
     NSMutableArray *after = [NSMutableArray arrayWithCapacity:16]; {
         pkgSourceList list;
 
     NSMutableArray *after = [NSMutableArray arrayWithCapacity:16]; {
         pkgSourceList list;
-        if ([self popErrorWithTitle:title forOperation:list.ReadMainList()])
+        if ([self popErrorWithTitle:title forReadList:list])
             return;
         for (pkgSourceList::const_iterator source = list.begin(); source != list.end(); ++source)
             [after addObject:[NSString stringWithUTF8String:(*source)->GetURI().c_str()]];
             return;
         for (pkgSourceList::const_iterator source = list.begin(); source != list.end(); ++source)
             [after addObject:[NSString stringWithUTF8String:(*source)->GetURI().c_str()]];
@@ -3916,6 +4174,10 @@ class CydiaLogCleaner :
         [self update];
 }
 
         [self update];
 }
 
+- (bool) delocked {
+    return ![delock_ isEqual:GetStatusDate()];
+}
+
 - (bool) upgrade {
     NSString *title(UCLocalize("UPGRADE"));
     if ([self popErrorWithTitle:title forOperation:pkgDistUpgrade(cache_)])
 - (bool) upgrade {
     NSString *title(UCLocalize("UPGRADE"));
     if ([self popErrorWithTitle:title forOperation:pkgDistUpgrade(cache_)])
@@ -3931,7 +4193,7 @@ class CydiaLogCleaner :
     NSString *title(UCLocalize("REFRESHING_DATA"));
 
     pkgSourceList list;
     NSString *title(UCLocalize("REFRESHING_DATA"));
 
     pkgSourceList list;
-    if ([self popErrorWithTitle:title forOperation:list.ReadMainList()])
+    if ([self popErrorWithTitle:title forReadList:list])
         return;
 
     FileFd lock;
         return;
 
     FileFd lock;
@@ -3946,8 +4208,10 @@ class CydiaLogCleaner :
         _error->Discard();
     else {
         [self popErrorWithTitle:title forOperation:success];
         _error->Discard();
     else {
         [self popErrorWithTitle:title forOperation:success];
-        [Metadata_ setObject:[NSDate date] forKey:@"LastUpdate"];
-        Changed_ = true;
+
+        [[NSDictionary dictionaryWithObjectsAndKeys:
+            [NSDate date], @"LastUpdate",
+        nil] writeToFile:@ CacheState_ atomically:YES];
     }
 
     [delegate_ performSelectorOnMainThread:@selector(releaseNetworkActivityIndicator) withObject:nil waitUntilDone:YES];
     }
 
     [delegate_ performSelectorOnMainThread:@selector(releaseNetworkActivityIndicator) withObject:nil waitUntilDone:YES];
@@ -4018,7 +4282,7 @@ class CydiaLogCleaner :
 static _H<NSMutableSet> Diversions_;
 
 @interface Diversion : NSObject {
 static _H<NSMutableSet> Diversions_;
 
 @interface Diversion : NSObject {
-    Pcre pattern_;
+    RegEx pattern_;
     _H<NSString> key_;
     _H<NSString> format_;
 }
     _H<NSString> key_;
     _H<NSString> format_;
 }
@@ -4106,8 +4370,10 @@ static _H<NSMutableSet> Diversions_;
 
 + (NSArray *) _attributeKeys {
     return [NSArray arrayWithObjects:
 
 + (NSArray *) _attributeKeys {
     return [NSArray arrayWithObjects:
+        @"bittage",
         @"bbsnum",
         @"build",
         @"bbsnum",
         @"build",
+        @"cells",
         @"coreFoundationVersionNumber",
         @"device",
         @"ecid",
         @"coreFoundationVersionNumber",
         @"device",
         @"ecid",
@@ -4120,7 +4386,6 @@ static _H<NSMutableSet> Diversions_;
         @"operator",
         @"role",
         @"serial",
         @"operator",
         @"role",
         @"serial",
-        @"token",
         @"version",
     nil];
 }
         @"version",
     nil];
 }
@@ -4137,6 +4402,17 @@ static _H<NSMutableSet> Diversions_;
     return Cydia_;
 }
 
     return Cydia_;
 }
 
+- (unsigned) bittage {
+#if 0
+#elif defined(__arm64__)
+    return 64;
+#elif defined(__arm__)
+    return 32;
+#else
+    return 0;
+#endif
+}
+
 - (NSString *) build {
     return System_;
 }
 - (NSString *) build {
     return System_;
 }
@@ -4161,11 +4437,34 @@ static _H<NSMutableSet> Diversions_;
     return (id) Idiom_ ?: [NSNull null];
 }
 
     return (id) Idiom_ ?: [NSNull null];
 }
 
-- (NSString *) mcc {
-    if (CFStringRef (*$CTSIMSupportCopyMobileSubscriberCountryCode)(CFAllocatorRef) = reinterpret_cast<CFStringRef (*)(CFAllocatorRef)>(dlsym(RTLD_DEFAULT, "CTSIMSupportCopyMobileSubscriberCountryCode")))
-        return [(NSString *) (*$CTSIMSupportCopyMobileSubscriberCountryCode)(kCFAllocatorDefault) autorelease];
-    return nil;
-}
+- (NSArray *) cells {
+    auto *$_CTServerConnectionCreate(reinterpret_cast<id (*)(void *, void *, void *)>(dlsym(RTLD_DEFAULT, "_CTServerConnectionCreate")));
+    if ($_CTServerConnectionCreate == NULL)
+        return nil;
+
+    struct CTResult { int flag; int error; };
+    auto *$_CTServerConnectionCellMonitorCopyCellInfo(reinterpret_cast<CTResult (*)(CFTypeRef, void *, CFArrayRef *)>(dlsym(RTLD_DEFAULT, "_CTServerConnectionCellMonitorCopyCellInfo")));
+    if ($_CTServerConnectionCellMonitorCopyCellInfo == NULL)
+        return nil;
+
+    _H<const void> connection($_CTServerConnectionCreate(NULL, NULL, NULL), true);
+    if (connection == nil)
+        return nil;
+
+    int count(0);
+    CFArrayRef cells(NULL);
+    auto result($_CTServerConnectionCellMonitorCopyCellInfo(connection, &count, &cells));
+    if (result.flag != 0)
+        return nil;
+
+    return [(NSArray *) cells autorelease];
+}
+
+- (NSString *) mcc {
+    if (CFStringRef (*$CTSIMSupportCopyMobileSubscriberCountryCode)(CFAllocatorRef) = reinterpret_cast<CFStringRef (*)(CFAllocatorRef)>(dlsym(RTLD_DEFAULT, "CTSIMSupportCopyMobileSubscriberCountryCode")))
+        return [(NSString *) (*$CTSIMSupportCopyMobileSubscriberCountryCode)(kCFAllocatorDefault) autorelease];
+    return nil;
+}
 
 - (NSString *) mnc {
     if (CFStringRef (*$CTSIMSupportCopyMobileSubscriberNetworkCode)(CFAllocatorRef) = reinterpret_cast<CFStringRef (*)(CFAllocatorRef)>(dlsym(RTLD_DEFAULT, "CTSIMSupportCopyMobileSubscriberNetworkCode")))
 
 - (NSString *) mnc {
     if (CFStringRef (*$CTSIMSupportCopyMobileSubscriberNetworkCode)(CFAllocatorRef) = reinterpret_cast<CFStringRef (*)(CFAllocatorRef)>(dlsym(RTLD_DEFAULT, "CTSIMSupportCopyMobileSubscriberNetworkCode")))
@@ -4199,10 +4498,6 @@ static _H<NSMutableSet> Diversions_;
     return [NSString stringWithUTF8String:Machine_];
 }
 
     return [NSString stringWithUTF8String:Machine_];
 }
 
-- (NSString *) token {
-    return (id) Token_ ?: [NSNull null];
-}
-
 + (NSString *) webScriptNameForSelector:(SEL)selector {
     if (false);
     else if (selector == @selector(addBridgedHost:))
 + (NSString *) webScriptNameForSelector:(SEL)selector {
     if (false);
     else if (selector == @selector(addBridgedHost:))
@@ -4215,8 +4510,6 @@ static _H<NSMutableSet> Diversions_;
         return @"addPipelinedHost";
     else if (selector == @selector(addSource:::))
         return @"addSource";
         return @"addPipelinedHost";
     else if (selector == @selector(addSource:::))
         return @"addSource";
-    else if (selector == @selector(addTokenHost:))
-        return @"addTokenHost";
     else if (selector == @selector(addTrivialSource:))
         return @"addTrivialSource";
     else if (selector == @selector(close))
     else if (selector == @selector(addTrivialSource:))
         return @"addTrivialSource";
     else if (selector == @selector(close))
@@ -4229,6 +4522,10 @@ static _H<NSMutableSet> Diversions_;
         return @"getAllSources";
     else if (selector == @selector(getApplicationInfo:value:))
         return @"getApplicationInfoValue";
         return @"getAllSources";
     else if (selector == @selector(getApplicationInfo:value:))
         return @"getApplicationInfoValue";
+    else if (selector == @selector(getDisplayIdentifiers))
+        return @"getDisplayIdentifiers";
+    else if (selector == @selector(getLocalizedNameForDisplayIdentifier:))
+        return @"getLocalizedNameForDisplayIdentifier";
     else if (selector == @selector(getKernelNumber:))
         return @"getKernelNumber";
     else if (selector == @selector(getKernelString:))
     else if (selector == @selector(getKernelNumber:))
         return @"getKernelNumber";
     else if (selector == @selector(getKernelString:))
@@ -4345,6 +4642,14 @@ static _H<NSMutableSet> Diversions_;
     return [info objectForKey:key];
 }
 
     return [info objectForKey:key];
 }
 
+- (NSArray *) getDisplayIdentifiers {
+    return SBSCopyApplicationDisplayIdentifiers(false, false);
+}
+
+- (NSString *) getLocalizedNameForDisplayIdentifier:(NSString *)identifier {
+    return [SBSCopyLocalizedApplicationNameForDisplayIdentifier(identifier) autorelease] ?: (id) [NSNull null];
+}
+
 - (NSNumber *) getKernelNumber:(NSString *)name {
     const char *string([name UTF8String]);
 
 - (NSNumber *) getKernelNumber:(NSString *)name {
     const char *string([name UTF8String]);
 
@@ -4410,8 +4715,6 @@ static _H<NSMutableSet> Diversions_;
         [Values_ removeObjectForKey:key];
     else
         [Values_ setObject:value forKey:key];
         [Values_ removeObjectForKey:key];
     else
         [Values_ setObject:value forKey:key];
-
-    [delegate_ performSelectorOnMainThread:@selector(updateValues) withObject:nil waitUntilDone:YES];
 } }
 
 - (id) getSessionValue:(NSString *)key {
 } }
 
 - (id) getSessionValue:(NSString *)key {
@@ -4437,11 +4740,6 @@ static _H<NSMutableSet> Diversions_;
     [InsecureHosts_ addObject:host];
 } }
 
     [InsecureHosts_ addObject:host];
 } }
 
-- (void) addTokenHost:(NSString *)host {
-@synchronized (HostConfig_) {
-    [TokenHosts_ addObject:host];
-} }
-
 - (void) addPipelinedHost:(NSString *)host scheme:(NSString *)scheme {
 @synchronized (HostConfig_) {
     if (scheme != (id) [WebUndefined undefined])
 - (void) addPipelinedHost:(NSString *)host scheme:(NSString *)scheme {
 @synchronized (HostConfig_) {
     if (scheme != (id) [WebUndefined undefined])
@@ -4470,8 +4768,12 @@ static _H<NSMutableSet> Diversions_;
     nil] waitUntilDone:NO];
 }
 
     nil] waitUntilDone:NO];
 }
 
-- (void) addTrivialSource:(NSString *)href {
+- (BOOL) addTrivialSource:(NSString *)href {
+    href = VerifySource(href);
+    if (href == nil)
+        return NO;
     [delegate_ performSelectorOnMainThread:@selector(addTrivialSource:) withObject:href waitUntilDone:NO];
     [delegate_ performSelectorOnMainThread:@selector(addTrivialSource:) withObject:href waitUntilDone:NO];
+    return YES;
 }
 
 - (void) refreshSources {
 }
 
 - (void) refreshSources {
@@ -4529,36 +4831,20 @@ static _H<NSMutableSet> Diversions_;
 - (NSNumber *) du:(NSString *)path {
     NSNumber *value(nil);
 
 - (NSNumber *) du:(NSString *)path {
     NSNumber *value(nil);
 
-    int fds[2];
-    _assert(pipe(fds) != -1);
-
-    pid_t pid(ExecFork());
-    if (pid == 0) {
-        _assert(dup2(fds[1], 1) != -1);
-        _assert(close(fds[0]) != -1);
-        _assert(close(fds[1]) != -1);
-        /* XXX: this should probably not use du */
-        execl("/usr/libexec/cydia/du", "du", "-s", [path UTF8String], NULL);
-        exit(1);
-    } else {
-        _assert(close(fds[1]) != -1);
-
-        if (FILE *du = fdopen(fds[0], "r")) {
-            char line[1024];
-            while (fgets(line, sizeof(line), du) != NULL) {
-                size_t length(strlen(line));
-                while (length != 0 && line[length - 1] == '\n')
-                    line[--length] = '\0';
-                if (char *tab = strchr(line, '\t')) {
-                    *tab = '\0';
-                    value = [NSNumber numberWithUnsignedLong:strtoul(line, NULL, 0)];
-                }
+    FILE *du(popen([[NSString stringWithFormat:@"/usr/libexec/cydia/cydo /usr/libexec/cydia/du -ks %@", ShellEscape(path)] UTF8String], "r"));
+    if (du != NULL) {
+        char line[1024];
+        while (fgets(line, sizeof(line), du) != NULL) {
+            size_t length(strlen(line));
+            while (length != 0 && line[length - 1] == '\n')
+                line[--length] = '\0';
+            if (char *tab = strchr(line, '\t')) {
+                *tab = '\0';
+                value = [NSNumber numberWithUnsignedLong:strtoul(line, NULL, 0)];
             }
             }
-
-            fclose(du);
-        } else
-            _assert(close(fds[0]) != -1);
-    } ReapZombie(pid);
+        }
+        pclose(du);
+    }
 
     return value;
 }
 
     return value;
 }
@@ -4576,10 +4862,16 @@ static _H<NSMutableSet> Diversions_;
 }
 
 - (NSString *) substitutePackageNames:(NSString *)message {
 }
 
 - (NSString *) substitutePackageNames:(NSString *)message {
+    auto database([Database sharedInstance]);
+
+    // XXX: this check is less racy than you'd expect, but this entire concept is a little awkward
+    if ([database hasPackages])
+        return message;
+
     NSMutableArray *words([[[message componentsSeparatedByString:@" "] mutableCopy] autorelease]);
     for (size_t i(0), e([words count]); i != e; ++i) {
         NSString *word([words objectAtIndex:i]);
     NSMutableArray *words([[[message componentsSeparatedByString:@" "] mutableCopy] autorelease]);
     for (size_t i(0), e([words count]); i != e; ++i) {
         NSString *word([words objectAtIndex:i]);
-        if (Package *package = [[Database sharedInstance] packageWithName:word])
+        if (Package *package = [database packageWithName:word])
             [words replaceObjectAtIndex:i withObject:[package name]];
     }
 
             [words replaceObjectAtIndex:i withObject:[package name]];
     }
 
@@ -4632,19 +4924,8 @@ static _H<NSMutableSet> Diversions_;
     [[objc_getClass("UIPasteboard") generalPasteboard] setURL:[NSURL URLWithString:value]];
 }
 
     [[objc_getClass("UIPasteboard") generalPasteboard] setURL:[NSURL URLWithString:value]];
 }
 
-- (void) _setToken:(NSString *)token {
-    Token_ = token;
-
-    if (token == nil)
-        [Metadata_ removeObjectForKey:@"Token"];
-    else
-        [Metadata_ setObject:Token_ forKey:@"Token"];
-
-    Changed_ = true;
-}
-
 - (void) setToken:(NSString *)token {
 - (void) setToken:(NSString *)token {
-    [self performSelectorOnMainThread:@selector(_setToken:) withObject:token waitUntilDone:NO];
+    // XXX: the website expects this :/
 }
 
 - (void) scrollToBottom:(NSNumber *)animated {
 }
 
 - (void) scrollToBottom:(NSNumber *)animated {
@@ -4751,6 +5032,10 @@ static _H<NSMutableSet> Diversions_;
     return [CydiaWebViewController requestWithHeaders:[super webView:view resource:resource willSendRequest:request redirectResponse:response fromDataSource:source]];
 }
 
     return [CydiaWebViewController requestWithHeaders:[super webView:view resource:resource willSendRequest:request redirectResponse:response fromDataSource:source]];
 }
 
+- (NSURLRequest *) webThreadWebView:(WebView *)view resource:(id)resource willSendRequest:(NSURLRequest *)request redirectResponse:(NSURLResponse *)response fromDataSource:(WebDataSource *)source {
+    return [CydiaWebViewController requestWithHeaders:[super webThreadWebView:view resource:resource willSendRequest:request redirectResponse:response fromDataSource:source]];
+}
+
 + (NSURLRequest *) requestWithHeaders:(NSURLRequest *)request {
     NSMutableURLRequest *copy([[request mutableCopy] autorelease]);
 
 + (NSURLRequest *) requestWithHeaders:(NSURLRequest *)request {
     NSMutableURLRequest *copy([[request mutableCopy] autorelease]);
 
@@ -4776,23 +5061,12 @@ static _H<NSMutableSet> Diversions_;
     if (Machine_ != NULL && [copy valueForHTTPHeaderField:@"X-Machine"] == nil)
         [copy setValue:[NSString stringWithUTF8String:Machine_] forHTTPHeaderField:@"X-Machine"];
 
     if (Machine_ != NULL && [copy valueForHTTPHeaderField:@"X-Machine"] == nil)
         [copy setValue:[NSString stringWithUTF8String:Machine_] forHTTPHeaderField:@"X-Machine"];
 
-    bool bridged;
-    bool token;
-
-    @synchronized (HostConfig_) {
+    bool bridged; @synchronized (HostConfig_) {
         bridged = [BridgedHosts_ containsObject:host];
         bridged = [BridgedHosts_ containsObject:host];
-        token = [TokenHosts_ containsObject:host];
     }
 
     }
 
-    if ([url isCydiaSecure]) {
-        if (bridged) {
-            if (UniqueID_ != nil && [copy valueForHTTPHeaderField:@"X-Cydia-Id"] == nil)
-                [copy setValue:UniqueID_ forHTTPHeaderField:@"X-Cydia-Id"];
-        } else if (token) {
-            if (Token_ != nil && [copy valueForHTTPHeaderField:@"X-Cydia-Token"] == nil)
-                [copy setValue:Token_ forHTTPHeaderField:@"X-Cydia-Token"];
-        }
-    }
+    if ([url isCydiaSecure] && bridged && UniqueID_ != nil && [copy valueForHTTPHeaderField:@"X-Cydia-Id"] == nil)
+        [copy setValue:UniqueID_ forHTTPHeaderField:@"X-Cydia-Id"];
 
     return copy;
 }
 
     return copy;
 }
@@ -4919,7 +5193,7 @@ bool DepSubstrate(const pkgCache::VerIterator &iterator) {
 
     if ([context isEqualToString:@"remove"]) {
         if (button == [alert cancelButtonIndex])
 
     if ([context isEqualToString:@"remove"]) {
         if (button == [alert cancelButtonIndex])
-            [self dismissModalViewControllerAnimated:YES];
+            [self _doContinue];
         else if (button == [alert firstOtherButtonIndex]) {
             [self performSelector:@selector(complete) withObject:nil afterDelay:0];
         }
         else if (button == [alert firstOtherButtonIndex]) {
             [self performSelector:@selector(complete) withObject:nil afterDelay:0];
         }
@@ -5024,7 +5298,7 @@ bool DepSubstrate(const pkgCache::VerIterator &iterator) {
                                 reason = @"virtual";
                         }
 
                                 reason = @"virtual";
                         }
 
-                        NSDictionary *version(start.TargetVer() == 0 ? [NSNull null] : [NSDictionary dictionaryWithObjectsAndKeys:
+                        NSDictionary *version(start.TargetVer() == 0 ? (NSDictionary *) [NSNull null] : [NSDictionary dictionaryWithObjectsAndKeys:
                             [NSString stringWithUTF8String:start.CompType()], @"operator",
                             [NSString stringWithUTF8String:start.TargetVer()], @"value",
                         nil]);
                             [NSString stringWithUTF8String:start.CompType()], @"operator",
                             [NSString stringWithUTF8String:start.TargetVer()], @"value",
                         nil]);
@@ -5046,7 +5320,7 @@ bool DepSubstrate(const pkgCache::VerIterator &iterator) {
 
             pkgDepCache::StateCache &state(cache[iterator]);
 
 
             pkgDepCache::StateCache &state(cache[iterator]);
 
-            static Pcre special_r("^(firmware$|gsc\\.|cy\\+)");
+            static RegEx special_r("(firmware|gsc\\..*|cy\\+.*)");
 
             if (state.NewInstall())
                 [installs addObject:name];
 
             if (state.NewInstall())
                 [installs addObject:name];
@@ -5372,34 +5646,6 @@ bool DepSubstrate(const pkgCache::VerIterator &iterator) {
     [super viewWillAppear:animated];
 }
 
     [super viewWillAppear:animated];
 }
 
-- (void) reloadSpringBoard {
-    if (kCFCoreFoundationVersionNumber > 700) { // XXX: iOS 6.x
-        system("/bin/launchctl stop com.apple.backboardd");
-        sleep(15);
-        system("/usr/bin/killall backboardd SpringBoard sbreload");
-        return;
-    }
-
-    pid_t pid(ExecFork());
-    if (pid == 0) {
-        if (setsid() == -1)
-            perror("setsid");
-
-        pid_t pid(ExecFork());
-        if (pid == 0) {
-            execl("/usr/bin/sbreload", "sbreload", NULL);
-            perror("sbreload");
-
-            exit(0);
-        } ReapZombie(pid);
-
-        exit(0);
-    } ReapZombie(pid);
-
-    sleep(15);
-    system("/usr/bin/killall backboardd SpringBoard sbreload");
-}
-
 - (void) close {
     UpdateExternalStatus(0);
 
 - (void) close {
     UpdateExternalStatus(0);
 
@@ -5430,7 +5676,7 @@ bool DepSubstrate(const pkgCache::VerIterator &iterator) {
         reload: {
             UIProgressHUD *hud([delegate_ addProgressHUD]);
             [hud setText:UCLocalize("LOADING")];
         reload: {
             UIProgressHUD *hud([delegate_ addProgressHUD]);
             [hud setText:UCLocalize("LOADING")];
-            [self performSelector:@selector(reloadSpringBoard) withObject:nil afterDelay:0.5];
+            [delegate_ performSelector:@selector(reloadSpringBoard) withObject:nil afterDelay:0.5];
             return;
         }
 
             return;
         }
 
@@ -5738,7 +5984,7 @@ bool DepSubstrate(const pkgCache::VerIterator &iterator) {
         rect.origin.x = 19 - rect.size.width / 2;
         rect.origin.y = 19 - rect.size.height / 2;
 
         rect.origin.x = 19 - rect.size.width / 2;
         rect.origin.y = 19 - rect.size.height / 2;
 
-        [icon_ drawInRect:rect];
+        [icon_ drawInRect:Retina(rect)];
     }
 
     if (badge_ != nil) {
     }
 
     if (badge_ != nil) {
@@ -5751,7 +5997,7 @@ bool DepSubstrate(const pkgCache::VerIterator &iterator) {
         rect.origin.x = 25 - rect.size.width / 2;
         rect.origin.y = 25 - rect.size.height / 2;
 
         rect.origin.x = 25 - rect.size.width / 2;
         rect.origin.y = 25 - rect.size.height / 2;
 
-        [badge_ drawInRect:rect];
+        [badge_ drawInRect:Retina(rect)];
     }
 
     if (highlighted && kCFCoreFoundationVersionNumber < 800)
     }
 
     if (highlighted && kCFCoreFoundationVersionNumber < 800)
@@ -5759,7 +6005,7 @@ bool DepSubstrate(const pkgCache::VerIterator &iterator) {
 
     if (!highlighted)
         UISetColor(commercial_ ? Purple_ : Black_);
 
     if (!highlighted)
         UISetColor(commercial_ ? Purple_ : Black_);
-    [name_ drawAtPoint:CGPointMake(36, 8) forWidth:(width - (placard_ == nil ? 68 : 94)) withFont:Font18Bold_ lineBreakMode:UILineBreakModeTailTruncation];
+    [name_ drawAtPoint:CGPointMake(36, 8) forWidth:(width - (placard_ == nil ? 68 : 94)) withFont:Font18Bold_ lineBreakMode:NSLineBreakByTruncatingTail];
 
     if (placard_ != nil)
         [placard_ drawAtPoint:CGPointMake(width - 52, 11)];
 
     if (placard_ != nil)
         [placard_ drawAtPoint:CGPointMake(width - 52, 11)];
@@ -5781,7 +6027,7 @@ bool DepSubstrate(const pkgCache::VerIterator &iterator) {
         rect.origin.x = 25 - rect.size.width / 2;
         rect.origin.y = 25 - rect.size.height / 2;
 
         rect.origin.x = 25 - rect.size.width / 2;
         rect.origin.y = 25 - rect.size.height / 2;
 
-        [icon_ drawInRect:rect];
+        [icon_ drawInRect:Retina(rect)];
     }
 
     if (badge_ != nil) {
     }
 
     if (badge_ != nil) {
@@ -5794,7 +6040,7 @@ bool DepSubstrate(const pkgCache::VerIterator &iterator) {
         rect.origin.x = 36 - rect.size.width / 2;
         rect.origin.y = 36 - rect.size.height / 2;
 
         rect.origin.x = 36 - rect.size.width / 2;
         rect.origin.y = 36 - rect.size.height / 2;
 
-        [badge_ drawInRect:rect];
+        [badge_ drawInRect:Retina(rect)];
     }
 
     if (highlighted && kCFCoreFoundationVersionNumber < 800)
     }
 
     if (highlighted && kCFCoreFoundationVersionNumber < 800)
@@ -5802,12 +6048,12 @@ bool DepSubstrate(const pkgCache::VerIterator &iterator) {
 
     if (!highlighted)
         UISetColor(commercial_ ? Purple_ : Black_);
 
     if (!highlighted)
         UISetColor(commercial_ ? Purple_ : Black_);
-    [name_ drawAtPoint:CGPointMake(48, 8) forWidth:(width - (placard_ == nil ? 80 : 106)) withFont:Font18Bold_ lineBreakMode:UILineBreakModeTailTruncation];
-    [source_ drawAtPoint:CGPointMake(58, 29) forWidth:(width - 95) withFont:Font12_ lineBreakMode:UILineBreakModeTailTruncation];
+    [name_ drawAtPoint:CGPointMake(48, 8) forWidth:(width - (placard_ == nil ? 80 : 106)) withFont:Font18Bold_ lineBreakMode:NSLineBreakByTruncatingTail];
+    [source_ drawAtPoint:CGPointMake(58, 29) forWidth:(width - 95) withFont:Font12_ lineBreakMode:NSLineBreakByTruncatingTail];
 
     if (!highlighted)
         UISetColor(commercial_ ? Purplish_ : Gray_);
 
     if (!highlighted)
         UISetColor(commercial_ ? Purplish_ : Gray_);
-    [description_ drawAtPoint:CGPointMake(12, 46) forWidth:(width - 46) withFont:Font14_ lineBreakMode:UILineBreakModeTailTruncation];
+    [description_ drawAtPoint:CGPointMake(12, 46) forWidth:(width - 46) withFont:Font14_ lineBreakMode:NSLineBreakByTruncatingTail];
 
     if (placard_ != nil)
         [placard_ drawAtPoint:CGPointMake(width - 52, 9)];
 
     if (placard_ != nil)
         [placard_ drawAtPoint:CGPointMake(width - 52, 9)];
@@ -5843,7 +6089,7 @@ bool DepSubstrate(const pkgCache::VerIterator &iterator) {
 
 - (id) initWithFrame:(CGRect)frame reuseIdentifier:(NSString *)reuseIdentifier {
     if ((self = [super initWithFrame:frame reuseIdentifier:reuseIdentifier]) != nil) {
 
 - (id) initWithFrame:(CGRect)frame reuseIdentifier:(NSString *)reuseIdentifier {
     if ((self = [super initWithFrame:frame reuseIdentifier:reuseIdentifier]) != nil) {
-        icon_ = [UIImage applicationImageNamed:@"folder.png"];
+        icon_ = [UIImage imageNamed:@"folder.png"];
         // XXX: this initial frame is wrong, but is fixed later
         switch_ = [[[UISwitch alloc] initWithFrame:CGRectMake(218, 9, 60, 25)] autorelease];
         [switch_ addTarget:self action:@selector(onSwitch:) forEvents:UIControlEventValueChanged];
         // XXX: this initial frame is wrong, but is fixed later
         switch_ = [[[UISwitch alloc] initWithFrame:CGRectMake(218, 9, 60, 25)] autorelease];
         [switch_ addTarget:self action:@selector(onSwitch:) forEvents:UIControlEventValueChanged];
@@ -5868,7 +6114,6 @@ bool DepSubstrate(const pkgCache::VerIterator &iterator) {
     }
 
     [metadata setObject:[NSNumber numberWithBool:([switch_ isOn] == NO)] forKey:@"Hidden"];
     }
 
     [metadata setObject:[NSNumber numberWithBool:([switch_ isOn] == NO)] forKey:@"Hidden"];
-    Changed_ = true;
 }
 
 - (void) setSection:(Section *)section editing:(BOOL)editing {
 }
 
 - (void) setSection:(Section *)section editing:(BOOL)editing {
@@ -5893,7 +6138,7 @@ bool DepSubstrate(const pkgCache::VerIterator &iterator) {
         section_ = [section localized];
 
         name_  = section_ == nil || [section_ length] == 0 ? UCLocalize("NO_SECTION") : (NSString *) section_;
         section_ = [section localized];
 
         name_  = section_ == nil || [section_ length] == 0 ? UCLocalize("NO_SECTION") : (NSString *) section_;
-        count_ = [NSString stringWithFormat:@"%d", [section count]];
+        count_ = [NSString stringWithFormat:@"%zd", [section count]];
 
         if (editing_)
             [switch_ setOn:(isSectionVisible(basic_) ? 1 : 0) animated:NO];
 
         if (editing_)
             [switch_ setOn:(isSectionVisible(basic_) ? 1 : 0) animated:NO];
@@ -5930,13 +6175,13 @@ bool DepSubstrate(const pkgCache::VerIterator &iterator) {
 
     if (!highlighted)
         UISetColor(Black_);
 
     if (!highlighted)
         UISetColor(Black_);
-    [name_ drawAtPoint:CGPointMake(48, 12) forWidth:(width - 58) withFont:Font18_ lineBreakMode:UILineBreakModeTailTruncation];
+    [name_ drawAtPoint:CGPointMake(48, 12) forWidth:(width - 58) withFont:Font18_ lineBreakMode:NSLineBreakByTruncatingTail];
 
     CGSize size = [count_ sizeWithFont:Font14_];
 
     UISetColor(Folder_);
     if (count_ != nil)
 
     CGSize size = [count_ sizeWithFont:Font14_];
 
     UISetColor(Folder_);
     if (count_ != nil)
-        [count_ drawAtPoint:CGPointMake(10 + (30 - size.width) / 2, 18) withFont:Font12Bold_];
+        [count_ drawAtPoint:CGPointMake(Retina(10 + (30 - size.width) / 2), 18) withFont:Font12Bold_];
 }
 
 @end
 }
 
 @end
@@ -6045,7 +6290,7 @@ bool DepSubstrate(const pkgCache::VerIterator &iterator) {
                 NSString *directory = [stack lastObject];
                 [stack addObject:[file stringByAppendingString:@"/"]];
                 [files_ replaceObjectAtIndex:i withObject:[NSString stringWithFormat:@"%*s%@",
                 NSString *directory = [stack lastObject];
                 [stack addObject:[file stringByAppendingString:@"/"]];
                 [files_ replaceObjectAtIndex:i withObject:[NSString stringWithFormat:@"%*s%@",
-                    ([stack count] - 2) * 3, "",
+                    int(([stack count] - 2) * 3), "",
                     [file substringFromIndex:[directory length]]
                 ]];
             }
                     [file substringFromIndex:[directory length]]
                 ]];
             }
@@ -6071,8 +6316,10 @@ bool DepSubstrate(const pkgCache::VerIterator &iterator) {
     _H<Package> package_;
     _H<NSString> name_;
     bool commercial_;
     _H<Package> package_;
     _H<NSString> name_;
     bool commercial_;
-    _H<NSMutableArray> buttons_;
+    std::vector<std::pair<_H<NSString>, _H<NSString>>> buttons_;
+    _H<UIActionSheet> sheet_;
     _H<UIBarButtonItem> button_;
     _H<UIBarButtonItem> button_;
+    _H<NSArray> versions_;
 }
 
 - (id) initWithDatabase:(Database *)database forPackage:(NSString *)name withReferrer:(NSString *)referrer;
 }
 
 - (id) initWithDatabase:(Database *)database forPackage:(NSString *)name withReferrer:(NSString *)referrer;
@@ -6085,31 +6332,64 @@ bool DepSubstrate(const pkgCache::VerIterator &iterator) {
     return [NSURL URLWithString:[NSString stringWithFormat:@"cydia://package/%@", (id) name_]];
 }
 
     return [NSURL URLWithString:[NSString stringWithFormat:@"cydia://package/%@", (id) name_]];
 }
 
-/* XXX: this is not safe at all... localization of /fail/ */
+- (void) _clickButtonWithPackage:(Package *)package {
+    [delegate_ installPackage:package];
+}
+
 - (void) _clickButtonWithName:(NSString *)name {
 - (void) _clickButtonWithName:(NSString *)name {
-    if ([name isEqualToString:UCLocalize("CLEAR")])
-        [delegate_ clearPackage:package_];
-    else if ([name isEqualToString:UCLocalize("INSTALL")])
-        [delegate_ installPackage:package_];
-    else if ([name isEqualToString:UCLocalize("REINSTALL")])
-        [delegate_ installPackage:package_];
-    else if ([name isEqualToString:UCLocalize("REMOVE")])
-        [delegate_ removePackage:package_];
-    else if ([name isEqualToString:UCLocalize("UPGRADE")])
-        [delegate_ installPackage:package_];
+    if ([name isEqualToString:@"CLEAR"])
+        return [delegate_ clearPackage:package_];
+    else if ([name isEqualToString:@"REMOVE"])
+        return [delegate_ removePackage:package_];
+    else if ([name isEqualToString:@"DOWNGRADE"]) {
+        sheet_ = [[[UIActionSheet alloc]
+            initWithTitle:nil
+            delegate:self
+            cancelButtonTitle:nil
+            destructiveButtonTitle:nil
+            otherButtonTitles:nil
+        ] autorelease];
+
+        for (Package *version in (id) versions_)
+            [sheet_ addButtonWithTitle:[version latest]];
+        [sheet_ setContext:@"version"];
+
+        [delegate_ showActionSheet:sheet_ fromItem:[[self navigationItem] rightBarButtonItem]];
+        return;
+    }
+
+    else if ([name isEqualToString:@"INSTALL"]);
+    else if ([name isEqualToString:@"REINSTALL"]);
+    else if ([name isEqualToString:@"UPGRADE"]);
     else _assert(false);
     else _assert(false);
+
+    [delegate_ installPackage:package_];
 }
 
 - (void) actionSheet:(UIActionSheet *)sheet clickedButtonAtIndex:(NSInteger)button {
     NSString *context([sheet context]);
 }
 
 - (void) actionSheet:(UIActionSheet *)sheet clickedButtonAtIndex:(NSInteger)button {
     NSString *context([sheet context]);
+    if (sheet_ == sheet)
+        sheet_ = nil;
 
     if ([context isEqualToString:@"modify"]) {
         if (button != [sheet cancelButtonIndex]) {
 
     if ([context isEqualToString:@"modify"]) {
         if (button != [sheet cancelButtonIndex]) {
-            NSString *buttonName = [buttons_ objectAtIndex:button];
-            [self _clickButtonWithName:buttonName];
+            if (IsWildcat_)
+                [self performSelector:@selector(_clickButtonWithName:) withObject:buttons_[button].first afterDelay:0];
+            else
+                [self _clickButtonWithName:buttons_[button].first];
+        }
+
+        [sheet dismissWithClickedButtonIndex:button animated:YES];
+    } else if ([context isEqualToString:@"version"]) {
+        if (button != [sheet cancelButtonIndex]) {
+            Package *version([versions_ objectAtIndex:button]);
+            if (IsWildcat_)
+                [self performSelector:@selector(_clickButtonWithPackage:) withObject:version afterDelay:0];
+            else
+                [self _clickButtonWithPackage:version];
         }
 
         }
 
-        [sheet dismissWithClickedButtonIndex:-1 animated:YES];
+        [sheet dismissWithClickedButtonIndex:button animated:YES];
     }
 }
 
     }
 }
 
@@ -6119,17 +6399,18 @@ bool DepSubstrate(const pkgCache::VerIterator &iterator) {
 
 #if !AlwaysReload
 - (void) _customButtonClicked {
 
 #if !AlwaysReload
 - (void) _customButtonClicked {
-    int count([buttons_ count]);
+    size_t count(buttons_.size());
     if (count == 0)
         return;
 
     if (count == 1)
     if (count == 0)
         return;
 
     if (count == 1)
-        [self _clickButtonWithName:[buttons_ objectAtIndex:0]];
+        [self _clickButtonWithName:buttons_[0].first];
     else {
         NSMutableArray *buttons = [NSMutableArray arrayWithCapacity:count];
     else {
         NSMutableArray *buttons = [NSMutableArray arrayWithCapacity:count];
-        [buttons addObjectsFromArray:buttons_];
+        for (const auto &button : buttons_)
+            [buttons addObject:button.second];
 
 
-        UIActionSheet *sheet = [[[UIActionSheet alloc]
+        sheet_ = [[[UIActionSheet alloc]
             initWithTitle:nil
             delegate:self
             cancelButtonTitle:nil
             initWithTitle:nil
             delegate:self
             cancelButtonTitle:nil
@@ -6137,14 +6418,11 @@ bool DepSubstrate(const pkgCache::VerIterator &iterator) {
             otherButtonTitles:nil
         ] autorelease];
 
             otherButtonTitles:nil
         ] autorelease];
 
-        for (NSString *button in buttons) [sheet addButtonWithTitle:button];
-        if (!IsWildcat_) {
-           [sheet addButtonWithTitle:UCLocalize("CANCEL")];
-           [sheet setCancelButtonIndex:[sheet numberOfButtons] - 1];
-        }
-        [sheet setContext:@"modify"];
+        for (NSString *button in buttons)
+            [sheet_ addButtonWithTitle:button];
+        [sheet_ setContext:@"modify"];
 
 
-        [delegate_ showActionSheet:sheet fromItem:[[self navigationItem] rightBarButtonItem]];
+        [delegate_ showActionSheet:sheet_ fromItem:[[self navigationItem] rightBarButtonItem]];
     }
 }
 
     }
 }
 
@@ -6163,10 +6441,13 @@ bool DepSubstrate(const pkgCache::VerIterator &iterator) {
 }
 #endif
 
 }
 #endif
 
+- (void) setPageColor:(UIColor *)color {
+    return [super setPageColor:nil];
+}
+
 - (id) initWithDatabase:(Database *)database forPackage:(NSString *)name withReferrer:(NSString *)referrer {
     if ((self = [super init]) != nil) {
         database_ = database;
 - (id) initWithDatabase:(Database *)database forPackage:(NSString *)name withReferrer:(NSString *)referrer {
     if ((self = [super init]) != nil) {
         database_ = database;
-        buttons_ = [NSMutableArray arrayWithCapacity:4];
         name_ = name == nil ? @"" : [NSString stringWithString:name];
         [self setURL:[NSURL URLWithString:[NSString stringWithFormat:@"%@/#!/package/%@", UI_, (id) name_]] withReferrer:referrer];
     } return self;
         name_ = name == nil ? @"" : [NSString stringWithString:name];
         [self setURL:[NSURL URLWithString:[NSString stringWithFormat:@"%@/#!/package/%@", UI_, (id) name_]] withReferrer:referrer];
     } return self;
@@ -6175,9 +6456,13 @@ bool DepSubstrate(const pkgCache::VerIterator &iterator) {
 - (void) reloadData {
     [super reloadData];
 
 - (void) reloadData {
     [super reloadData];
 
+    [sheet_ dismissWithClickedButtonIndex:[sheet_ cancelButtonIndex] animated:YES];
+    sheet_ = nil;
+
     package_ = [database_ packageWithName:name_];
     package_ = [database_ packageWithName:name_];
+    versions_ = [package_ downgrades];
 
 
-    [buttons_ removeAllObjects];
+    buttons_.clear();
 
     if (package_ != nil) {
         [(Package *) package_ parse];
 
     if (package_ != nil) {
         [(Package *) package_ parse];
@@ -6185,22 +6470,24 @@ bool DepSubstrate(const pkgCache::VerIterator &iterator) {
         commercial_ = [package_ isCommercial];
 
         if ([package_ mode] != nil)
         commercial_ = [package_ isCommercial];
 
         if ([package_ mode] != nil)
-            [buttons_ addObject:UCLocalize("CLEAR")];
+            buttons_.push_back(std::make_pair(@"CLEAR", UCLocalize("CLEAR")));
         if ([package_ source] == nil);
         else if ([package_ upgradableAndEssential:NO])
         if ([package_ source] == nil);
         else if ([package_ upgradableAndEssential:NO])
-            [buttons_ addObject:UCLocalize("UPGRADE")];
+            buttons_.push_back(std::make_pair(@"UPGRADE", UCLocalize("UPGRADE")));
         else if ([package_ uninstalled])
         else if ([package_ uninstalled])
-            [buttons_ addObject:UCLocalize("INSTALL")];
+            buttons_.push_back(std::make_pair(@"INSTALL", UCLocalize("INSTALL")));
         else
         else
-            [buttons_ addObject:UCLocalize("REINSTALL")];
+            buttons_.push_back(std::make_pair(@"REINSTALL", UCLocalize("REINSTALL")));
         if (![package_ uninstalled])
         if (![package_ uninstalled])
-            [buttons_ addObject:UCLocalize("REMOVE")];
+            buttons_.push_back(std::make_pair(@"REMOVE", UCLocalize("REMOVE")));
+        if ([versions_ count] != 0)
+            buttons_.push_back(std::make_pair(@"DOWNGRADE", UCLocalize("DOWNGRADE")));
     }
 
     NSString *title;
     }
 
     NSString *title;
-    switch ([buttons_ count]) {
+    switch (buttons_.size()) {
         case 0: title = nil; break;
         case 0: title = nil; break;
-        case 1: title = [buttons_ objectAtIndex:0]; break;
+        case 1: title = buttons_[0].second; break;
         default: title = UCLocalize("MODIFY"); break;
     }
 
         default: title = UCLocalize("MODIFY"); break;
     }
 
@@ -6227,10 +6514,12 @@ bool DepSubstrate(const pkgCache::VerIterator &iterator) {
     _transient Database *database_;
     unsigned era_;
     _H<NSArray> packages_;
     _transient Database *database_;
     unsigned era_;
     _H<NSArray> packages_;
-    _H<NSMutableArray> sections_;
+    _H<NSArray> sections_;
     _H<UITableView, 2> list_;
     _H<UITableView, 2> list_;
-    _H<NSMutableArray> index_;
-    _H<NSMutableDictionary> indices_;
+
+    _H<NSArray> thumbs_;
+    std::vector<NSInteger> offset_;
+
     _H<NSString> title_;
     unsigned reloading_;
 }
     _H<NSString> title_;
     unsigned reloading_;
 }
@@ -6240,6 +6529,8 @@ bool DepSubstrate(const pkgCache::VerIterator &iterator) {
 - (void) resetCursor;
 - (void) clearData;
 
 - (void) resetCursor;
 - (void) clearData;
 
+- (NSArray *) sectionsForPackages:(NSMutableArray *)packages;
+
 @end
 
 @implementation PackageListController
 @end
 
 @implementation PackageListController
@@ -6303,7 +6594,7 @@ bool DepSubstrate(const pkgCache::VerIterator &iterator) {
     UIViewAnimationCurve curve;
     [self getKeyboardCurve:&curve duration:&duration forNotification:notification];
 
     UIViewAnimationCurve curve;
     [self getKeyboardCurve:&curve duration:&duration forNotification:notification];
 
-    CGRect kbframe = CGRectMake(round(center.x - bounds.size.width / 2.0), round(center.y - bounds.size.height / 2.0), bounds.size.width, bounds.size.height);
+    CGRect kbframe = CGRectMake(Retina(center.x - bounds.size.width / 2), Retina(center.y - bounds.size.height / 2), bounds.size.width, bounds.size.height);
     UIViewController *base = self;
     while ([base parentOrPresentingViewController] != nil)
         base = [base parentOrPresentingViewController];
     UIViewController *base = self;
     while ([base parentOrPresentingViewController] != nil)
         base = [base parentOrPresentingViewController];
@@ -6351,12 +6642,6 @@ bool DepSubstrate(const pkgCache::VerIterator &iterator) {
     [[self navigationController] pushViewController:view animated:YES];
 }
 
     [[self navigationController] pushViewController:view animated:YES];
 }
 
-#if TryIndexedCollation
-+ (BOOL) hasIndexedCollation {
-    return NO; // XXX: objc_getClass("UILocalizedIndexedCollation") != nil;
-}
-#endif
-
 - (NSInteger) numberOfSectionsInTableView:(UITableView *)list {
     NSInteger count([sections_ count]);
     return count == 0 ? 1 : count;
 - (NSInteger) numberOfSectionsInTableView:(UITableView *)list {
     NSInteger count([sections_ count]);
     return count == 0 ? 1 : count;
@@ -6402,20 +6687,11 @@ bool DepSubstrate(const pkgCache::VerIterator &iterator) {
 }
 
 - (NSArray *) sectionIndexTitlesForTableView:(UITableView *)tableView {
 }
 
 - (NSArray *) sectionIndexTitlesForTableView:(UITableView *)tableView {
-    if (![self showsSections])
-        return nil;
-
-    return index_;
+    return thumbs_;
 }
 
 - (NSInteger) tableView:(UITableView *)tableView sectionForSectionIndexTitle:(NSString *)title atIndex:(NSInteger)index {
 }
 
 - (NSInteger) tableView:(UITableView *)tableView sectionForSectionIndexTitle:(NSString *)title atIndex:(NSInteger)index {
-#if TryIndexedCollation
-    if ([[self class] hasIndexedCollation]) {
-        return [[objc_getClass("UILocalizedIndexedCollation") currentCollation] sectionForSectionIndexTitleAtIndex:index];
-    }
-#endif
-
-    return index;
+    return offset_[index];
 }
 
 - (void) updateHeight {
 }
 
 - (void) updateHeight {
@@ -6453,8 +6729,9 @@ bool DepSubstrate(const pkgCache::VerIterator &iterator) {
 
     packages_ = nil;
     sections_ = nil;
 
     packages_ = nil;
     sections_ = nil;
-    index_ = nil;
-    indices_ = nil;
+
+    thumbs_ = nil;
+    offset_.clear();
 
     [super releaseSubviews];
 }
 
     [super releaseSubviews];
 }
@@ -6485,7 +6762,7 @@ bool DepSubstrate(const pkgCache::VerIterator &iterator) {
         return;
     }
 
         return;
     }
 
-    NSArray *packages;
+    NSMutableArray *packages;
 
   reload:
     if ([self shouldYield]) {
 
   reload:
     if ([self shouldYield]) {
@@ -6514,92 +6791,82 @@ bool DepSubstrate(const pkgCache::VerIterator &iterator) {
         goto reload;
     reloading_ = 0;
 
         goto reload;
     reloading_ = 0;
 
-    packages_ = packages;
-
-    indices_ = [NSMutableDictionary dictionaryWithCapacity:32];
-    sections_ = [NSMutableArray arrayWithCapacity:16];
-
-    Section *section = nil;
+    thumbs_ = nil;
+    offset_.clear();
 
 
-#if TryIndexedCollation
-    if ([[self class] hasIndexedCollation]) {
-        index_ = [[objc_getClass("UILocalizedIndexedCollation") currentCollation] sectionIndexTitles];
+    packages_ = packages;
 
 
-        id collation = [objc_getClass("UILocalizedIndexedCollation") currentCollation];
-        NSArray *titles = [collation sectionIndexTitles];
-        int secidx = -1;
+    if ([self showsSections])
+        sections_ = [self sectionsForPackages:packages];
+    else {
+        Section *section([[[Section alloc] initWithName:nil row:0 localize:NO] autorelease]);
+        [section setCount:[packages_ count]];
+        sections_ = [NSArray arrayWithObject:section];
+    }
 
 
-        _profile(PackageTable$reloadData$Section)
-            for (size_t offset(0), end([packages_ count]); offset != end; ++offset) {
-                Package *package;
-                int index;
+    [self updateHeight];
 
 
-                _profile(PackageTable$reloadData$Section$Package)
-                    package = [packages_ objectAtIndex:offset];
-                    index = [collation sectionForObject:package collationStringSelector:@selector(name)];
-                _end
+    _profile(PackageTable$reloadData$List)
+        [(UITableView *) list_ setDataSource:self];
+        [list_ reloadData];
+    _end
+}
 
 
-                while (secidx < index) {
-                    secidx += 1;
+    PrintTimes();
+}
 
 
-                    _profile(PackageTable$reloadData$Section$Allocate)
-                        section = [[[Section alloc] initWithName:[titles objectAtIndex:secidx] row:offset localize:NO] autorelease];
-                    _end
+- (NSArray *) sectionsForPackages:(NSMutableArray *)packages {
+    Section *prefix([[[Section alloc] initWithName:nil row:0 localize:NO] autorelease]);
+    size_t end([packages count]);
 
 
-                    _profile(PackageTable$reloadData$Section$Add)
-                        [sections_ addObject:section];
-                    _end
-                }
+    NSMutableArray *sections([NSMutableArray arrayWithCapacity:16]);
+    Section *section(prefix);
 
 
-                [section addToCount];
-            }
-        _end
-    } else
-#endif
-    {
-        index_ = [NSMutableArray arrayWithCapacity:32];
+    thumbs_ = CollationThumbs_;
+    offset_ = CollationOffset_;
 
 
-        bool sectioned([self showsSections]);
-        if (!sectioned) {
-            section = [[[Section alloc] initWithName:nil localize:false] autorelease];
-            [sections_ addObject:section];
-        }
+    size_t offset(0);
+    size_t offsets([CollationStarts_ count]);
 
 
-        _profile(PackageTable$reloadData$Section)
-            for (size_t offset(0), end([packages_ count]); offset != end; ++offset) {
-                Package *package;
-                unichar index;
+    NSString *start([CollationStarts_ objectAtIndex:offset]);
+    size_t length([start length]);
 
 
-                _profile(PackageTable$reloadData$Section$Package)
-                    package = [packages_ objectAtIndex:offset];
-                    index = [package index];
-                _end
+    for (size_t index(0); index != end; ++index) {
+        if (start != nil) {
+            Package *package([packages objectAtIndex:index]);
+            NSString *name(PackageName(package, @selector(cyname)));
 
 
-                if (sectioned && (section == nil || [section index] != index)) {
-                    _profile(PackageTable$reloadData$Section$Allocate)
-                        section = [[[Section alloc] initWithIndex:index row:offset] autorelease];
-                    _end
+            //while ([start compare:name options:NSNumericSearch range:NSMakeRange(0, length) locale:CollationLocale_] != NSOrderedDescending) {
+            while (StringNameCompare(start, name, length) != kCFCompareGreaterThan) {
+                NSString *title([CollationTitles_ objectAtIndex:offset]);
+                section = [[[Section alloc] initWithName:title row:index localize:NO] autorelease];
+                [sections addObject:section];
 
 
-                    [index_ addObject:[section name]];
-                    //[indices_ setObject:[NSNumber numberForInt:[sections_ count]] forKey:index];
+                start = ++offset == offsets ? nil : [CollationStarts_ objectAtIndex:offset];
+                if (start == nil)
+                    break;
+                length = [start length];
+            }
+        }
 
 
-                    _profile(PackageTable$reloadData$Section$Add)
-                        [sections_ addObject:section];
-                    _end
-                }
+        [section addToCount];
+    }
 
 
-                [section addToCount];
-            }
-        _end
+    for (; offset != offsets; ++offset) {
+        NSString *title([CollationTitles_ objectAtIndex:offset]);
+        Section *section([[[Section alloc] initWithName:title row:end localize:NO] autorelease]);
+        [sections addObject:section];
     }
 
     }
 
-    [self updateHeight];
+    if ([prefix count] != 0) {
+        Section *suffix([sections lastObject]);
+        [prefix setName:[suffix name]];
+        [suffix setName:nil];
+        [sections insertObject:prefix atIndex:(offsets - 1)];
+    }
 
 
-    _profile(PackageTable$reloadData$List)
-        [(UITableView *) list_ setDataSource:self];
-        [list_ reloadData];
-    _end
-} }
+    return sections;
+}
 
 - (void) reloadData {
     [super reloadData];
 
 - (void) reloadData {
     [super reloadData];
@@ -6626,113 +6893,61 @@ bool DepSubstrate(const pkgCache::VerIterator &iterator) {
 @end
 /* }}} */
 /* Filtered Package List Controller {{{ */
 @end
 /* }}} */
 /* Filtered Package List Controller {{{ */
+typedef Function<bool, Package *> PackageFilter;
+typedef Function<void, NSMutableArray *> PackageSorter;
 @interface FilteredPackageListController : PackageListController {
 @interface FilteredPackageListController : PackageListController {
-    SEL filter_;
-    IMP imp_;
-    _H<NSObject> object_;
-    _H<NSObject> stuff_;
+    PackageFilter filter_;
+    PackageSorter sorter_;
 }
 
 }
 
-- (void) setObject:(id)object;
-- (void) setStuff:(id)object;
-- (void) setObject:(id)object andStuff:(id)stuff;
-
-- (void) setObject:(id)object forFilter:(SEL)filter;
-- (void) setObject:(id)object andStuff:(id)stuff forFilter:(SEL)filter;
+- (id) initWithDatabase:(Database *)database title:(NSString *)title filter:(PackageFilter)filter;
 
 
-- (SEL) filter;
-- (void) setFilter:(SEL)filter;
-
-- (id) initWithDatabase:(Database *)database title:(NSString *)title filter:(SEL)filter with:(id)object;
+- (void) setFilter:(PackageFilter)filter;
+- (void) setSorter:(PackageSorter)sorter;
 
 @end
 
 @implementation FilteredPackageListController
 
 
 @end
 
 @implementation FilteredPackageListController
 
-- (SEL) filter {
-    return filter_;
-}
-
-- (void) setFilter:(SEL)filter {
+- (void) setFilter:(PackageFilter)filter {
 @synchronized (self) {
     filter_ = filter;
 @synchronized (self) {
     filter_ = filter;
-
-    /* XXX: this is an unsafe optimization of doomy hell */
-    Method method(class_getInstanceMethod([Package class], filter));
-    _assert(method != NULL);
-    imp_ = method_getImplementation(method);
-    _assert(imp_ != NULL);
-} }
-
-- (void) setObject:(id)object {
-@synchronized (self) {
-    object_ = object;
-} }
-
-- (void) setStuff:(id)stuff {
-@synchronized (self) {
-    stuff_ = stuff;
-} }
-
-- (void) setObject:(id)object andStuff:(id)stuff {
-@synchronized (self) {
-    object_ = object;
-    stuff_ = stuff;
-} }
-
-- (void) setObject:(id)object forFilter:(SEL)filter {
-@synchronized (self) {
-    [self setFilter:filter];
-    object_ = object;
 } }
 
 } }
 
-- (void) setObject:(id)object andStuff:(id)stuff forFilter:(SEL)filter {
+- (void) setSorter:(PackageSorter)sorter {
 @synchronized (self) {
 @synchronized (self) {
-    [self setFilter:filter];
-    object_ = object;
-    stuff_ = stuff;
+    sorter_ = sorter;
 } }
 
 - (NSMutableArray *) _reloadPackages {
 @synchronized (database_) {
     era_ = [database_ era];
 } }
 
 - (NSMutableArray *) _reloadPackages {
 @synchronized (database_) {
     era_ = [database_ era];
-    NSArray *packages([database_ packages]);
 
 
+    NSArray *packages([database_ packages]);
     NSMutableArray *filtered([NSMutableArray arrayWithCapacity:[packages count]]);
 
     NSMutableArray *filtered([NSMutableArray arrayWithCapacity:[packages count]]);
 
-    IMP imp;
-    SEL filter;
-    _H<NSObject> object;
-    _H<NSObject> stuff;
+    PackageFilter filter;
+    PackageSorter sorter;
 
     @synchronized (self) {
 
     @synchronized (self) {
-        imp = imp_;
         filter = filter_;
         filter = filter_;
-        object = object_;
-        stuff = stuff_;
+        sorter = sorter_;
     }
 
     _profile(PackageTable$reloadData$Filter)
         for (Package *package in packages)
     }
 
     _profile(PackageTable$reloadData$Filter)
         for (Package *package in packages)
-            if ([package valid] && (*reinterpret_cast<bool (*)(id, SEL, id, id)>(imp))(package, filter, object, stuff))
+            if (filter(package))
                 [filtered addObject:package];
     _end
 
                 [filtered addObject:package];
     _end
 
+    if (sorter)
+        sorter(filtered);
     return filtered;
 } }
 
     return filtered;
 } }
 
-- (id) initWithDatabase:(Database *)database title:(NSString *)title filter:(SEL)filter with:(id)object {
-    if ((self = [super initWithDatabase:database title:title]) != nil) {
-        [self setFilter:filter];
-        object_ = object;
-    } return self;
-}
-
-- (id) initWithDatabase:(Database *)database title:(NSString *)title filter:(SEL)filter with:(id)object with:(id)stuff {
+- (id) initWithDatabase:(Database *)database title:(NSString *)title filter:(PackageFilter)filter {
     if ((self = [super initWithDatabase:database title:title]) != nil) {
         [self setFilter:filter];
     if ((self = [super initWithDatabase:database title:title]) != nil) {
         [self setFilter:filter];
-        object_ = object;
-        stuff_ = stuff;
     } return self;
 }
 
     } return self;
 }
 
@@ -6788,7 +7003,7 @@ static void HomeControllerReachabilityCallback(SCNetworkReachabilityRef reachabi
     [alert setCancelButtonIndex:0];
 
     [alert setMessage:
     [alert setCancelButtonIndex:0];
 
     [alert setMessage:
-        @"Copyright \u00a9 2008-2013\n"
+        @"Copyright \u00a9 2008-2015\n"
         "SaurikIT, LLC\n"
         "\n"
         "Jay Freeman (saurik)\n"
         "SaurikIT, LLC\n"
         "\n"
         "Jay Freeman (saurik)\n"
@@ -6867,11 +7082,10 @@ static void HomeControllerReachabilityCallback(SCNetworkReachabilityRef reachabi
     } return self;
 }
 
     } return self;
 }
 
-- (void) setUpdate:(NSDate *)date {
-    [self beginUpdate];
-}
-
 - (void) beginUpdate {
 - (void) beginUpdate {
+    if (updating_)
+        return;
+
     UIViewController *controller([[self viewControllers] objectAtIndex:1]);
     UITabBarItem *item([controller tabBarItem]);
 
     UIViewController *controller([[self viewControllers] objectAtIndex:1]);
     UITabBarItem *item([controller tabBarItem]);
 
@@ -6951,15 +7165,6 @@ static void HomeControllerReachabilityCallback(SCNetworkReachabilityRef reachabi
     updatedelegate_ = delegate;
 }
 
     updatedelegate_ = delegate;
 }
 
-- (UIView *) transitionView {
-    if (![self respondsToSelector:@selector(_transitionView)])
-        return MSHookIvar<id>(self, "_viewControllerTransitionView");
-    else if (kCFCoreFoundationVersionNumber < 800)
-        return [self _transitionView];
-    else
-        return [[[self _transitionView] superview] superview];
-}
-
 @end
 /* }}} */
 
 @end
 /* }}} */
 
@@ -6987,9 +7192,11 @@ static void HomeControllerReachabilityCallback(SCNetworkReachabilityRef reachabi
 
     // on the iPad, this view controller is ALSO visible. :(
     if (IsWildcat_)
 
     // on the iPad, this view controller is ALSO visible. :(
     if (IsWildcat_)
-        if (UIViewController *top = [self topViewController])
-            if (top != visible)
-                [top reloadData];
+        if (UIViewController *modal = [self modalViewController])
+            if ([modal modalPresentationStyle] == UIModalPresentationFormSheet)
+                if (UIViewController *top = [self topViewController])
+                    if (top != visible)
+                        [top reloadData];
 }
 
 - (void) unloadData {
 }
 
 - (void) unloadData {
@@ -7071,7 +7278,28 @@ static void HomeControllerReachabilityCallback(SCNetworkReachabilityRef reachabi
 
     Database *database([Database sharedInstance]);
 
 
     Database *database([Database sharedInstance]);
 
-    if ([command isEqualToString:@"package-icon"]) {
+    if (false);
+    else if ([command isEqualToString:@"application-icon"]) {
+        if (path == nil)
+            goto fail;
+        path = [path stringByReplacingPercentEscapesUsingEncoding:NSUTF8StringEncoding];
+
+        UIImage *icon(nil);
+
+        if (icon == nil && $SBSCopyIconImagePNGDataForDisplayIdentifier != NULL) {
+            NSData *data([$SBSCopyIconImagePNGDataForDisplayIdentifier(path) autorelease]);
+            icon = [UIImage imageWithData:data];
+        }
+
+        if (icon == nil)
+            if (NSString *file = SBSCopyIconImagePathForDisplayIdentifier(path))
+                icon = [UIImage imageAtPath:file];
+
+        if (icon == nil)
+            icon = [UIImage imageNamed:@"unknown.png"];
+
+        [self _returnPNGWithImage:icon forRequest:request];
+    } else if ([command isEqualToString:@"package-icon"]) {
         if (path == nil)
             goto fail;
         path = [path stringByReplacingPercentEscapesUsingEncoding:NSUTF8StringEncoding];
         if (path == nil)
             goto fail;
         path = [path stringByReplacingPercentEscapesUsingEncoding:NSUTF8StringEncoding];
@@ -7093,7 +7321,7 @@ static void HomeControllerReachabilityCallback(SCNetworkReachabilityRef reachabi
         path = [path stringByReplacingPercentEscapesUsingEncoding:NSUTF8StringEncoding];
         UIImage *icon([UIImage imageAtPath:[NSString stringWithFormat:@"%@/Sections/%@.png", App_, [path stringByReplacingOccurrencesOfString:@" " withString:@"_"]]]);
         if (icon == nil)
         path = [path stringByReplacingPercentEscapesUsingEncoding:NSUTF8StringEncoding];
         UIImage *icon([UIImage imageAtPath:[NSString stringWithFormat:@"%@/Sections/%@.png", App_, [path stringByReplacingOccurrencesOfString:@" " withString:@"_"]]]);
         if (icon == nil)
-            icon = [UIImage applicationImageNamed:@"unknown.png"];
+            icon = [UIImage imageNamed:@"unknown.png"];
         [self _returnPNGWithImage:icon forRequest:request];
     } else fail: {
         [client URLProtocol:self didFailWithError:[NSError errorWithDomain:NSURLErrorDomain code:NSURLErrorResourceUnavailable userInfo:nil]];
         [self _returnPNGWithImage:icon forRequest:request];
     } else fail: {
         [client URLProtocol:self didFailWithError:[NSError errorWithDomain:NSURLErrorDomain code:NSURLErrorResourceUnavailable userInfo:nil]];
@@ -7143,14 +7371,29 @@ static void HomeControllerReachabilityCallback(SCNetworkReachabilityRef reachabi
     else
         title = UCLocalize("NO_SECTION");
 
     else
         title = UCLocalize("NO_SECTION");
 
-    if ((self = [super initWithDatabase:database title:title filter:@selector(isVisibleInSection:source:) with:section with:source]) != nil) {
+    if ((self = [super initWithDatabase:database title:title]) != nil) {
         key_ = [source key];
         section_ = section;
     } return self;
 }
 
 - (void) reloadData {
         key_ = [source key];
         section_ = section;
     } return self;
 }
 
 - (void) reloadData {
-    [super setStuff:[database_ sourceWithKey:key_]];
+    Source *source([database_ sourceWithKey:key_]);
+    _H<NSString> name(section_);
+
+    [self setFilter:[=](Package *package) {
+        NSString *section([package section]);
+
+        return (
+            name == nil ||
+            section == nil && [name length] == 0 ||
+            [name isEqualToString:section]
+        ) && (
+            source == nil ||
+            [package source] == source
+        ) && [package visible];
+    }];
+
     [super reloadData];
 }
 
     [super reloadData];
 }
 
@@ -7337,7 +7580,7 @@ static void HomeControllerReachabilityCallback(SCNetworkReachabilityRef reachabi
         [section addToCount];
 
         _profile(SectionsView$reloadData$Filter)
         [section addToCount];
 
         _profile(SectionsView$reloadData$Filter)
-            if (![package valid] || ![package visible])
+            if (![package visible])
                 continue;
         _end
 
                 continue;
         _end
 
@@ -7372,15 +7615,7 @@ static void HomeControllerReachabilityCallback(SCNetworkReachabilityRef reachabi
 /* }}} */
 
 /* Changes Controller {{{ */
 /* }}} */
 
 /* Changes Controller {{{ */
-@interface ChangesController : CyteViewController <
-    UITableViewDataSource,
-    UITableViewDelegate
-> {
-    _transient Database *database_;
-    unsigned era_;
-    _H<NSMutableArray> packages_;
-    _H<NSMutableArray> sections_;
-    _H<UITableView, 2> list_;
+@interface ChangesController : FilteredPackageListController {
     unsigned upgrades_;
 }
 
     unsigned upgrades_;
 }
 
@@ -7390,30 +7625,12 @@ static void HomeControllerReachabilityCallback(SCNetworkReachabilityRef reachabi
 
 @implementation ChangesController
 
 
 @implementation ChangesController
 
-- (NSURL *) navigationURL {
-    return [NSURL URLWithString:@"cydia://changes"];
-}
-
-- (void) viewDidAppear:(BOOL)animated {
-    [super viewDidAppear:animated];
-    [list_ deselectRowAtIndexPath:[list_ indexPathForSelectedRow] animated:animated];
-}
-
-- (NSInteger) numberOfSectionsInTableView:(UITableView *)list {
-    NSInteger count([sections_ count]);
-    return count == 0 ? 1 : count;
-}
-
-- (NSString *) tableView:(UITableView *)list titleForHeaderInSection:(NSInteger)section {
-    if ([sections_ count] == 0)
-        return nil;
-    return [[sections_ objectAtIndex:section] name];
+- (NSURL *) referrerURL {
+    return [NSURL URLWithString:[NSString stringWithFormat:@"%@/#!/changes/", UI_]];
 }
 
 }
 
-- (NSInteger) tableView:(UITableView *)list numberOfRowsInSection:(NSInteger)section {
-    if ([sections_ count] == 0)
-        return 0;
-    return [[sections_ objectAtIndex:section] count];
+- (NSURL *) navigationURL {
+    return [NSURL URLWithString:@"cydia://changes"];
 }
 
 - (Package *) packageAtIndexPath:(NSIndexPath *)path {
 }
 
 - (Package *) packageAtIndexPath:(NSIndexPath *)path {
@@ -7429,24 +7646,6 @@ static void HomeControllerReachabilityCallback(SCNetworkReachabilityRef reachabi
     return [[[packages_ objectAtIndex:([section row] + row)] retain] autorelease];
 } }
 
     return [[[packages_ objectAtIndex:([section row] + row)] retain] autorelease];
 } }
 
-- (UITableViewCell *) tableView:(UITableView *)table cellForRowAtIndexPath:(NSIndexPath *)path {
-    PackageCell *cell((PackageCell *) [table dequeueReusableCellWithIdentifier:@"Package"]);
-    if (cell == nil)
-        cell = [[[PackageCell alloc] init] autorelease];
-
-    Package *package([database_ packageWithName:[[self packageAtIndexPath:path] id]]);
-    [cell setPackage:package asSummary:false];
-    return cell;
-}
-
-- (NSIndexPath *) tableView:(UITableView *)table willSelectRowAtIndexPath:(NSIndexPath *)path {
-    Package *package([self packageAtIndexPath:path]);
-    CYPackageController *view([[[CYPackageController alloc] initWithDatabase:database_ forPackage:[package id] withReferrer:[NSString stringWithFormat:@"%@/#!/changes/", UI_]] autorelease]);
-    [view setDelegate:delegate_];
-    [[self navigationController] pushViewController:view animated:YES];
-    return path;
-}
-
 - (void) alertView:(UIAlertView *)alert clickedButtonAtIndex:(NSInteger)button {
     NSString *context([alert context]);
 
 - (void) alertView:(UIAlertView *)alert clickedButtonAtIndex:(NSInteger)button {
     NSString *context([alert context]);
 
@@ -7485,84 +7684,48 @@ static void HomeControllerReachabilityCallback(SCNetworkReachabilityRef reachabi
     [[self navigationItem] setRightBarButtonItem:nil animated:YES];
 }
 
     [[self navigationItem] setRightBarButtonItem:nil animated:YES];
 }
 
-- (void) loadView {
-    UIView *view([[[UIView alloc] initWithFrame:[[UIScreen mainScreen] applicationFrame]] autorelease]);
-    [view setAutoresizingMask:(UIViewAutoresizingFlexibleWidth | UIViewAutoresizingFlexibleHeight)];
-    [self setView:view];
-
-    list_ = [[[UITableView alloc] initWithFrame:[view bounds] style:UITableViewStylePlain] autorelease];
-    [list_ setAutoresizingMask:UIViewAutoresizingFlexibleBoth];
-    [list_ setRowHeight:73];
-    [(UITableView *) list_ setDataSource:self];
-    [list_ setDelegate:self];
-    [view addSubview:list_];
+- (bool) shouldYield {
+    return true;
 }
 
 }
 
-- (void) viewDidLoad {
-    [super viewDidLoad];
-
-    [[self navigationItem] setTitle:UCLocalize("CHANGES")];
+- (bool) shouldBlock {
+    return true;
 }
 
 }
 
-- (void) releaseSubviews {
-    list_ = nil;
-
-    packages_ = nil;
-    sections_ = nil;
+- (void) useFilter {
+@synchronized (self) {
+    [self setFilter:[](Package *package) {
+        return [package upgradableAndEssential:YES] || [package visible];
+    }];
 
 
-    [super releaseSubviews];
-}
+    [self setSorter:[](NSMutableArray *packages) {
+        [packages radixSortUsingFunction:reinterpret_cast<MenesRadixSortFunction>(&PackageChangesRadix) withContext:NULL];
+    }];
+} }
 
 - (id) initWithDatabase:(Database *)database {
 
 - (id) initWithDatabase:(Database *)database {
-    if ((self = [super init]) != nil) {
-        database_ = database;
+    if ((self = [super initWithDatabase:database title:UCLocalize("CHANGES")]) != nil) {
+        [self useFilter];
     } return self;
 }
 
     } return self;
 }
 
-- (NSMutableArray *) _reloadPackages {
-@synchronized (database_) {
-    era_ = [database_ era];
-    NSArray *packages([database_ packages]);
-
-    NSMutableArray *filtered([NSMutableArray arrayWithCapacity:[packages count]]);
-
-    _trace();
-    _profile(ChangesController$_reloadPackages$Filter)
-        for (Package *package in packages)
-            if ([package upgradableAndEssential:YES] || [package visible])
-                CFArrayAppendValue((CFMutableArrayRef) filtered, package);
-    _end
-    _trace();
-    _profile(ChangesController$_reloadPackages$radixSort)
-        [filtered radixSortUsingFunction:reinterpret_cast<MenesRadixSortFunction>(&PackageChangesRadix) withContext:NULL];
-    _end
-    _trace();
-
-    return filtered;
-} }
-
-- (void) _reloadData {
+- (void) viewDidLoad {
+    [super viewDidLoad];
     [self setLeftBarButtonItem];
     [self setLeftBarButtonItem];
+}
 
 
-    NSMutableArray *packages;
-
-  reload:
-    if (true) {
-        UIProgressHUD *hud([delegate_ addProgressHUD]);
-        [hud setText:UCLocalize("LOADING")];
-        //NSLog(@"HUD:%@::%@", delegate_, hud);
-        packages = [self yieldToSelector:@selector(_reloadPackages)];
-        [delegate_ removeProgressHUD:hud];
-    } else {
-        packages = [self _reloadPackages];
-    }
+- (void) viewWillAppear:(BOOL)animated {
+    [super viewWillAppear:animated];
+    [self setLeftBarButtonItem];
+}
 
 
-@synchronized (database_) {
-    if (era_ != [database_ era])
-        goto reload;
+- (void) reloadData {
+    [self setLeftBarButtonItem];
+    [super reloadData];
+}
 
 
-    packages_ = packages;
-    sections_ = [NSMutableArray arrayWithCapacity:16];
+- (NSArray *) sectionsForPackages:(NSMutableArray *)packages {
+    NSMutableArray *sections([NSMutableArray arrayWithCapacity:16]);
 
     Section *upgradable = [[[Section alloc] initWithName:UCLocalize("AVAILABLE_UPGRADES") localize:NO] autorelease];
     Section *ignored = nil;
 
     Section *upgradable = [[[Section alloc] initWithName:UCLocalize("AVAILABLE_UPGRADES") localize:NO] autorelease];
     Section *ignored = nil;
@@ -7574,8 +7737,8 @@ static void HomeControllerReachabilityCallback(SCNetworkReachabilityRef reachabi
 
     CFDateFormatterRef formatter(CFDateFormatterCreate(NULL, Locale_, kCFDateFormatterMediumStyle, kCFDateFormatterMediumStyle));
 
 
     CFDateFormatterRef formatter(CFDateFormatterCreate(NULL, Locale_, kCFDateFormatterMediumStyle, kCFDateFormatterMediumStyle));
 
-    for (size_t offset = 0, count = [packages_ count]; offset != count; ++offset) {
-        Package *package = [packages_ objectAtIndex:offset];
+    for (size_t offset = 0, count = [packages count]; offset != count; ++offset) {
+        Package *package = [packages objectAtIndex:offset];
 
         BOOL uae = [package upgradableAndEssential:YES];
 
 
         BOOL uae = [package upgradableAndEssential:YES];
 
@@ -7593,7 +7756,7 @@ static void HomeControllerReachabilityCallback(SCNetworkReachabilityRef reachabi
                 _profile(ChangesController$reloadData$Allocate)
                     name = [NSString stringWithFormat:UCLocalize("NEW_AT"), name];
                     section = [[[Section alloc] initWithName:name row:offset localize:NO] autorelease];
                 _profile(ChangesController$reloadData$Allocate)
                     name = [NSString stringWithFormat:UCLocalize("NEW_AT"), name];
                     section = [[[Section alloc] initWithName:name row:offset localize:NO] autorelease];
-                    [sections_ addObject:section];
+                    [sections addObject:section];
                 _end
             }
 
                 _end
             }
 
@@ -7613,16 +7776,16 @@ static void HomeControllerReachabilityCallback(SCNetworkReachabilityRef reachabi
     CFRelease(formatter);
 
     if (unseens) {
     CFRelease(formatter);
 
     if (unseens) {
-        Section *last = [sections_ lastObject];
+        Section *last = [sections lastObject];
         size_t count = [last count];
         size_t count = [last count];
-        [packages_ removeObjectsInRange:NSMakeRange([packages_ count] - count, count)];
-        [sections_ removeLastObject];
+        [packages removeObjectsInRange:NSMakeRange([packages count] - count, count)];
+        [sections removeLastObject];
     }
 
     if ([ignored count] != 0)
     }
 
     if ([ignored count] != 0)
-        [sections_ insertObject:ignored atIndex:0];
+        [sections insertObject:ignored atIndex:0];
     if (upgrades_ != 0)
     if (upgrades_ != 0)
-        [sections_ insertObject:upgradable atIndex:0];
+        [sections insertObject:upgradable atIndex:0];
 
     [list_ reloadData];
 
 
     [list_ reloadData];
 
@@ -7633,12 +7796,7 @@ static void HomeControllerReachabilityCallback(SCNetworkReachabilityRef reachabi
         action:@selector(upgradeButtonClicked)
     ] autorelease]) animated:YES];
 
         action:@selector(upgradeButtonClicked)
     ] autorelease]) animated:YES];
 
-    PrintTimes();
-} }
-
-- (void) reloadData {
-    [super reloadData];
-    [self performSelector:@selector(_reloadData) withObject:nil afterDelay:0];
+    return sections;
 }
 
 @end
 }
 
 @end
@@ -7649,6 +7807,7 @@ static void HomeControllerReachabilityCallback(SCNetworkReachabilityRef reachabi
 > {
     _H<UISearchBar, 1> search_;
     BOOL searchloaded_;
 > {
     _H<UISearchBar, 1> search_;
     BOOL searchloaded_;
+    bool summary_;
 }
 
 - (id) initWithDatabase:(Database *)database query:(NSString *)query;
 }
 
 - (id) initWithDatabase:(Database *)database query:(NSString *)query;
@@ -7679,15 +7838,51 @@ static void HomeControllerReachabilityCallback(SCNetworkReachabilityRef reachabi
 }
 
 - (void) useSearch {
 }
 
 - (void) useSearch {
-    [self setObject:[self termsForQuery:[search_ text]] forFilter:@selector(isUnfilteredAndSearchedForBy:)];
+    _H<NSArray> query([self termsForQuery:[search_ text]]);
+    summary_ = false;
+
+@synchronized (self) {
+    [self setFilter:[=](Package *package) {
+        if (![package unfiltered])
+            return false;
+        if (![package matches:query])
+            return false;
+        return true;
+    }];
+
+    [self setSorter:[](NSMutableArray *packages) {
+        [packages radixSortUsingSelector:@selector(rank)];
+    }];
+}
+
     [self clearData];
     [self reloadData];
 }
 
     [self clearData];
     [self reloadData];
 }
 
+- (void) usePrefix:(NSString *)prefix {
+    _H<NSString> query(prefix);
+    summary_ = true;
+
+@synchronized (self) {
+    [self setFilter:[=](Package *package) {
+        if ([query length] == 0)
+            return false;
+        if (![package unfiltered])
+            return false;
+        if ([[package name] compare:query options:MatchCompareOptions_ range:NSMakeRange(0, [query length])] != NSOrderedSame)
+            return false;
+        return true;
+    }];
+
+    [self setSorter:nullptr];
+}
+
+    [self reloadData];
+}
+
 - (void) searchBarTextDidBeginEditing:(UISearchBar *)searchBar {
 - (void) searchBarTextDidBeginEditing:(UISearchBar *)searchBar {
-    [self setObject:[search_ text] forFilter:@selector(isUnfilteredAndSelectedForBy:)];
     [self clearData];
     [self clearData];
-    [self reloadData];
+    [self usePrefix:[search_ text]];
 }
 
 - (void) searchBarButtonClicked:(UISearchBar *)searchBar {
 }
 
 - (void) searchBarButtonClicked:(UISearchBar *)searchBar {
@@ -7705,8 +7900,7 @@ static void HomeControllerReachabilityCallback(SCNetworkReachabilityRef reachabi
 }
 
 - (void) searchBar:(UISearchBar *)searchBar textDidChange:(NSString *)text {
 }
 
 - (void) searchBar:(UISearchBar *)searchBar textDidChange:(NSString *)text {
-    [self setObject:text forFilter:@selector(isUnfilteredAndSelectedForBy:)];
-    [self reloadData];
+    [self usePrefix:text];
 }
 
 - (bool) shouldYield {
 }
 
 - (bool) shouldYield {
@@ -7714,31 +7908,36 @@ static void HomeControllerReachabilityCallback(SCNetworkReachabilityRef reachabi
 }
 
 - (bool) shouldBlock {
 }
 
 - (bool) shouldBlock {
-    return [self filter] == @selector(isUnfilteredAndSearchedForBy:);
+    return !summary_;
 }
 
 - (bool) isSummarized {
 }
 
 - (bool) isSummarized {
-    return [self filter] == @selector(isUnfilteredAndSelectedForBy:);
+    return summary_;
 }
 
 - (bool) showsSections {
     return false;
 }
 
 }
 
 - (bool) showsSections {
     return false;
 }
 
-- (NSMutableArray *) _reloadPackages {
-    NSMutableArray *packages([super _reloadPackages]);
-    if ([self filter] == @selector(isUnfilteredAndSearchedForBy:))
-        [packages radixSortUsingSelector:@selector(rank)];
-    return packages;
-}
-
 - (id) initWithDatabase:(Database *)database query:(NSString *)query {
 - (id) initWithDatabase:(Database *)database query:(NSString *)query {
-    if ((self = [super initWithDatabase:database title:UCLocalize("SEARCH") filter:@selector(isUnfilteredAndSearchedForBy:) with:[self termsForQuery:query]])) {
+    if ((self = [super initWithDatabase:database title:UCLocalize("SEARCH")])) {
         search_ = [[[UISearchBar alloc] init] autorelease];
         search_ = [[[UISearchBar alloc] init] autorelease];
+        [search_ setPlaceholder:UCLocalize("SEARCH_EX")];
         [search_ setDelegate:self];
 
         [search_ setDelegate:self];
 
+        UITextField *textField;
+        if ([search_ respondsToSelector:@selector(searchField)])
+            textField = [search_ searchField];
+        else
+            textField = MSHookIvar<UITextField *>(search_, "_searchField");
+
+        [textField setAutoresizingMask:UIViewAutoresizingFlexibleWidth | UIViewAutoresizingFlexibleTopMargin | UIViewAutoresizingFlexibleBottomMargin];
+        [textField setEnablesReturnKeyAutomatically:NO];
+        [[self navigationItem] setTitleView:textField];
+
         if (query != nil)
             [search_ setText:query];
         if (query != nil)
             [search_ setText:query];
+        [self useSearch];
     } return self;
 }
 
     } return self;
 }
 
@@ -7749,17 +7948,6 @@ static void HomeControllerReachabilityCallback(SCNetworkReachabilityRef reachabi
         searchloaded_ = YES;
         [search_ setFrame:CGRectMake(0, 0, [[self view] bounds].size.width, 44.0f)];
         [search_ layoutSubviews];
         searchloaded_ = YES;
         [search_ setFrame:CGRectMake(0, 0, [[self view] bounds].size.width, 44.0f)];
         [search_ layoutSubviews];
-        [search_ setPlaceholder:UCLocalize("SEARCH_EX")];
-
-        UITextField *textField;
-        if ([search_ respondsToSelector:@selector(searchField)])
-            textField = [search_ searchField];
-        else
-            textField = MSHookIvar<UITextField *>(search_, "_searchField");
-
-        [textField setAutoresizingMask:UIViewAutoresizingFlexibleWidth | UIViewAutoresizingFlexibleTopMargin | UIViewAutoresizingFlexibleBottomMargin];
-        [textField setEnablesReturnKeyAutomatically:NO];
-        [[self navigationItem] setTitleView:textField];
     }
 
     if ([self isSummarized])
     }
 
     if ([self isSummarized])
@@ -7767,13 +7955,7 @@ static void HomeControllerReachabilityCallback(SCNetworkReachabilityRef reachabi
 }
 
 - (void) reloadData {
 }
 
 - (void) reloadData {
-    id object([search_ text]);
-    if ([self filter] == @selector(isUnfilteredAndSearchedForBy:))
-        object = [self termsForQuery:object];
-
-    [self setObject:object];
     [self resetCursor];
     [self resetCursor];
-
     [super reloadData];
 }
 
     [super reloadData];
 }
 
@@ -7850,20 +8032,15 @@ static void HomeControllerReachabilityCallback(SCNetworkReachabilityRef reachabi
     const char *package([name_ UTF8String]);
     bool on([ignoredSwitch_ isOn]);
 
     const char *package([name_ UTF8String]);
     bool on([ignoredSwitch_ isOn]);
 
-    pid_t pid(ExecFork());
-    if (pid == 0) {
-        FILE *dpkg(popen("dpkg --set-selections", "w"));
-        fwrite(package, strlen(package), 1, dpkg);
-
-        if (on)
-            fwrite(" hold\n", 6, 1, dpkg);
-        else
-            fwrite(" install\n", 9, 1, dpkg);
+    FILE *dpkg(popen("/usr/libexec/cydia/cydo --set-selections", "w"));
+    fwrite(package, strlen(package), 1, dpkg);
 
 
-        pclose(dpkg);
+    if (on)
+        fwrite(" hold\n", 6, 1, dpkg);
+    else
+        fwrite(" install\n", 9, 1, dpkg);
 
 
-        exit(0);
-    } ReapZombie(pid);
+    pclose(dpkg);
 }
 
 - (void) onIgnored:(id)control {
 }
 
 - (void) onIgnored:(id)control {
@@ -7959,6 +8136,7 @@ static void HomeControllerReachabilityCallback(SCNetworkReachabilityRef reachabi
 
 /* Installed Controller {{{ */
 @interface InstalledController : FilteredPackageListController {
 
 /* Installed Controller {{{ */
 @interface InstalledController : FilteredPackageListController {
+    bool sectioned_;
 }
 
 - (id) initWithDatabase:(Database *)database;
 }
 
 - (id) initWithDatabase:(Database *)database;
@@ -7976,14 +8154,84 @@ static void HomeControllerReachabilityCallback(SCNetworkReachabilityRef reachabi
     return [NSURL URLWithString:@"cydia://installed"];
 }
 
     return [NSURL URLWithString:@"cydia://installed"];
 }
 
+- (void) useRecent {
+    sectioned_ = false;
+
+@synchronized (self) {
+    [self setFilter:[](Package *package) {
+        return ![package uninstalled] && package->role_ < 7;
+    }];
+
+    [self setSorter:[](NSMutableArray *packages) {
+        [packages radixSortUsingSelector:@selector(recent)];
+    }];
+} }
+
+- (void) useFilter:(UISegmentedControl *)segmented {
+    NSInteger selected([segmented selectedSegmentIndex]);
+    if (selected == 2)
+        return [self useRecent];
+    bool simple(selected == 0);
+    sectioned_ = true;
+
+@synchronized (self) {
+    [self setFilter:[=](Package *package) {
+        return ![package uninstalled] && package->role_ <= (simple ? 1 : 3);
+    }];
+
+    [self setSorter:nullptr];
+} }
+
+- (NSArray *) sectionsForPackages:(NSMutableArray *)packages {
+    if (sectioned_)
+        return [super sectionsForPackages:packages];
+
+    CFDateFormatterRef formatter(CFDateFormatterCreate(NULL, Locale_, kCFDateFormatterLongStyle, kCFDateFormatterNoStyle));
+
+    NSMutableArray *sections([NSMutableArray arrayWithCapacity:16]);
+    Section *section(nil);
+    time_t last(0);
+
+    for (size_t offset(0), count([packages count]); offset != count; ++offset) {
+        Package *package([packages objectAtIndex:offset]);
+
+        time_t upgraded([package upgraded]);
+        if (upgraded < 1168364520)
+            upgraded = 0;
+        else
+            upgraded -= upgraded % (60 * 60 * 24);
+
+        if (section == nil || upgraded != last) {
+            last = upgraded;
+
+            NSString *name;
+            if (upgraded == 0)
+                continue; // XXX: name = UCLocalize("...");
+            else {
+                name = (NSString *) CFDateFormatterCreateStringWithDate(NULL, formatter, (CFDateRef) [NSDate dateWithTimeIntervalSince1970:upgraded]);
+                [name autorelease];
+            }
+
+            section = [[[Section alloc] initWithName:name row:offset localize:NO] autorelease];
+            [sections addObject:section];
+        }
+
+        [section addToCount];
+    }
+
+    CFRelease(formatter);
+    return sections;
+}
+
 - (id) initWithDatabase:(Database *)database {
 - (id) initWithDatabase:(Database *)database {
-    if ((self = [super initWithDatabase:database title:UCLocalize("INSTALLED") filter:@selector(isInstalledAndUnfiltered:) with:[NSNumber numberWithBool:YES]]) != nil) {
-        UISegmentedControl *segmented([[[UISegmentedControl alloc] initWithItems:[NSArray arrayWithObjects:UCLocalize("SIMPLE"), UCLocalize("EXPERT"), nil]] autorelease]);
+    if ((self = [super initWithDatabase:database title:UCLocalize("INSTALLED")]) != nil) {
+        UISegmentedControl *segmented([[[UISegmentedControl alloc] initWithItems:[NSArray arrayWithObjects:UCLocalize("USER"), UCLocalize("EXPERT"), UCLocalize("RECENT"), nil]] autorelease]);
         [segmented setSelectedSegmentIndex:0];
         [segmented setSegmentedControlStyle:UISegmentedControlStyleBar];
         [[self navigationItem] setTitleView:segmented];
 
         [segmented addTarget:self action:@selector(modeChanged:) forEvents:UIControlEventValueChanged];
         [segmented setSelectedSegmentIndex:0];
         [segmented setSegmentedControlStyle:UISegmentedControlStyleBar];
         [[self navigationItem] setTitleView:segmented];
 
         [segmented addTarget:self action:@selector(modeChanged:) forEvents:UIControlEventValueChanged];
+        [self useFilter:segmented];
 
         [self queueStatusDidChange];
     } return self;
 
         [self queueStatusDidChange];
     } return self;
@@ -7998,21 +8246,20 @@ static void HomeControllerReachabilityCallback(SCNetworkReachabilityRef reachabi
 - (void) queueStatusDidChange {
 #if !AlwaysReload
     if (Queuing_) {
 - (void) queueStatusDidChange {
 #if !AlwaysReload
     if (Queuing_) {
-        [[self navigationItem] setLeftBarButtonItem:[[[UIBarButtonItem alloc]
+        [[self navigationItem] setRightBarButtonItem:[[[UIBarButtonItem alloc]
             initWithTitle:UCLocalize("QUEUE")
             style:UIBarButtonItemStyleDone
             target:self
             action:@selector(queueButtonClicked)
         ] autorelease]];
     } else {
             initWithTitle:UCLocalize("QUEUE")
             style:UIBarButtonItemStyleDone
             target:self
             action:@selector(queueButtonClicked)
         ] autorelease]];
     } else {
-        [[self navigationItem] setLeftBarButtonItem:nil];
+        [[self navigationItem] setRightBarButtonItem:nil];
     }
 #endif
 }
 
 - (void) modeChanged:(UISegmentedControl *)segmented {
     }
 #endif
 }
 
 - (void) modeChanged:(UISegmentedControl *)segmented {
-    bool simple([segmented selectedSegmentIndex] == 0);
-    [self setObject:[NSNumber numberWithBool:simple]];
+    [self useFilter:segmented];
     [self reloadData];
 }
 
     [self reloadData];
 }
 
@@ -8071,7 +8318,7 @@ static void HomeControllerReachabilityCallback(SCNetworkReachabilityRef reachabi
 
     [self setFetch:[NSNumber numberWithBool:[source_ fetch]]];
 
 
     [self setFetch:[NSNumber numberWithBool:[source_ fetch]]];
 
-    icon_ = [UIImage applicationImageNamed:@"unknown.png"];
+    icon_ = [UIImage imageNamed:@"unknown.png"];
 
     origin_ = [source name];
     label_ = [source rooturi];
 
     origin_ = [source name];
     label_ = [source rooturi];
@@ -8086,7 +8333,7 @@ static void HomeControllerReachabilityCallback(SCNetworkReachabilityRef reachabi
     source_ = nil;
     [indicator_ stopAnimating];
 
     source_ = nil;
     [indicator_ stopAnimating];
 
-    icon_ = [UIImage applicationImageNamed:@"folder.png"];
+    icon_ = [UIImage imageNamed:@"folder.png"];
     origin_ = UCLocalize("ALL_SOURCES");
     label_ = UCLocalize("ALL_SOURCES_EX");
     [content_ setNeedsDisplay];
     origin_ = UCLocalize("ALL_SOURCES");
     label_ = UCLocalize("ALL_SOURCES_EX");
     [content_ setNeedsDisplay];
@@ -8121,7 +8368,7 @@ static void HomeControllerReachabilityCallback(SCNetworkReachabilityRef reachabi
 
     CGRect frame([indicator_ frame]);
     frame.origin.x = bounds.size.width - frame.size.width;
 
     CGRect frame([indicator_ frame]);
     frame.origin.x = bounds.size.width - frame.size.width;
-    frame.origin.y = (bounds.size.height - frame.size.height) / 2;
+    frame.origin.y = Retina((bounds.size.height - frame.size.height) / 2);
 
     if (kCFCoreFoundationVersionNumber < 800)
         frame.origin.x -= 8;
 
     if (kCFCoreFoundationVersionNumber < 800)
         frame.origin.x -= 8;
@@ -8148,7 +8395,7 @@ static void HomeControllerReachabilityCallback(SCNetworkReachabilityRef reachabi
         rect.origin.x = 26 - rect.size.width / 2;
         rect.origin.y = 26 - rect.size.height / 2;
 
         rect.origin.x = 26 - rect.size.width / 2;
         rect.origin.y = 26 - rect.size.height / 2;
 
-        [icon_ drawInRect:rect];
+        [icon_ drawInRect:Retina(rect)];
     }
 
     if (highlighted && kCFCoreFoundationVersionNumber < 800)
     }
 
     if (highlighted && kCFCoreFoundationVersionNumber < 800)
@@ -8156,11 +8403,11 @@ static void HomeControllerReachabilityCallback(SCNetworkReachabilityRef reachabi
 
     if (!highlighted)
         UISetColor(Black_);
 
     if (!highlighted)
         UISetColor(Black_);
-    [origin_ drawAtPoint:CGPointMake(52, 8) forWidth:(width - 61) withFont:Font18Bold_ lineBreakMode:UILineBreakModeTailTruncation];
+    [origin_ drawAtPoint:CGPointMake(52, 8) forWidth:(width - 49) withFont:Font18Bold_ lineBreakMode:NSLineBreakByTruncatingTail];
 
     if (!highlighted)
         UISetColor(Gray_);
 
     if (!highlighted)
         UISetColor(Gray_);
-    [label_ drawAtPoint:CGPointMake(52, 29) forWidth:(width - 61) withFont:Font12_ lineBreakMode:UILineBreakModeTailTruncation];
+    [label_ drawAtPoint:CGPointMake(52, 29) forWidth:(width - 49) withFont:Font12_ lineBreakMode:NSLineBreakByTruncatingTail];
 }
 
 - (void) setFetch:(NSNumber *)fetch {
 }
 
 - (void) setFetch:(NSNumber *)fetch {
@@ -8295,10 +8542,8 @@ static void HomeControllerReachabilityCallback(SCNetworkReachabilityRef reachabi
         if (source == nil) return;
 
         [Sources_ removeObjectForKey:[source key]];
         if (source == nil) return;
 
         [Sources_ removeObjectForKey:[source key]];
-        Changed_ = true;
 
 
-        [delegate_ _saveConfig];
-        [delegate_ reloadDataWithInvocation:nil];
+        [delegate_ syncData];
     }
 }
 
     }
 }
 
@@ -8457,27 +8702,10 @@ static void HomeControllerReachabilityCallback(SCNetworkReachabilityRef reachabi
         switch (button) {
             case 1: {
                 NSString *href = [[alert textField] text];
         switch (button) {
             case 1: {
                 NSString *href = [[alert textField] text];
-
-                static Pcre href_r("^http(s?)://[^# ]*$");
-                if (!href_r(href)) {
-                    UIAlertView *alert = [[[UIAlertView alloc]
-                        initWithTitle:Error_
-                        message:UCLocalize("INVALID_URL")
-                        delegate:self
-                        cancelButtonTitle:UCLocalize("OK")
-                        otherButtonTitles:nil
-                    ] autorelease];
-
-                    [alert setContext:@"badurl"];
-                    [alert show];
-
+                href = VerifySource(href);
+                if (href == nil)
                     break;
                     break;
-                }
-
-                if (![href hasSuffix:@"/"])
-                    href_ = [href stringByAppendingString:@"/"];
-                else
-                    href_ = href;
+                href_ = href;
 
                 trivial_bz2_ = [[self _requestHRef:[href_ stringByAppendingString:@"Packages.bz2"] method:@"HEAD"] retain];
                 trivial_gz_ = [[self _requestHRef:[href_ stringByAppendingString:@"Packages.gz"] method:@"HEAD"] retain];
 
                 trivial_bz2_ = [[self _requestHRef:[href_ stringByAppendingString:@"Packages.bz2"] method:@"HEAD"] retain];
                 trivial_gz_ = [[self _requestHRef:[href_ stringByAppendingString:@"Packages.gz"] method:@"HEAD"] retain];
@@ -8678,7 +8906,7 @@ static void HomeControllerReachabilityCallback(SCNetworkReachabilityRef reachabi
 
     spinner_ = [[[UIActivityIndicatorView alloc] initWithActivityIndicatorStyle:UIActivityIndicatorViewStyleWhiteLarge] autorelease];
     CGRect spinrect = [spinner_ frame];
 
     spinner_ = [[[UIActivityIndicatorView alloc] initWithActivityIndicatorStyle:UIActivityIndicatorViewStyleWhiteLarge] autorelease];
     CGRect spinrect = [spinner_ frame];
-    spinrect.origin.x = ([[self view] frame].size.width / 2) - (spinrect.size.width / 2);
+    spinrect.origin.x = Retina([[self view] frame].size.width / 2 - spinrect.size.width / 2);
     spinrect.origin.y = [[self view] frame].size.height - 80.0f;
     [spinner_ setFrame:spinrect];
     [spinner_ setAutoresizingMask:UIViewAutoresizingFlexibleLeftMargin | UIViewAutoresizingFlexibleRightMargin | UIViewAutoresizingFlexibleTopMargin];
     spinrect.origin.y = [[self view] frame].size.height - 80.0f;
     [spinner_ setFrame:spinrect];
     [spinner_ setAutoresizingMask:UIViewAutoresizingFlexibleLeftMargin | UIViewAutoresizingFlexibleRightMargin | UIViewAutoresizingFlexibleTopMargin];
@@ -8689,7 +8917,7 @@ static void HomeControllerReachabilityCallback(SCNetworkReachabilityRef reachabi
     captrect.size.width = [[self view] frame].size.width;
     captrect.size.height = 40.0f;
     captrect.origin.x = 0;
     captrect.size.width = [[self view] frame].size.width;
     captrect.size.height = 40.0f;
     captrect.origin.x = 0;
-    captrect.origin.y = ([[self view] frame].size.height / 2) - (captrect.size.height * 2);
+    captrect.origin.y = Retina([[self view] frame].size.height / 2 - captrect.size.height * 2);
     caption_ = [[[UILabel alloc] initWithFrame:captrect] autorelease];
     [caption_ setText:UCLocalize("PREPARING_FILESYSTEM")];
     [caption_ setAutoresizingMask:UIViewAutoresizingFlexibleWidth | UIViewAutoresizingFlexibleTopMargin | UIViewAutoresizingFlexibleBottomMargin];
     caption_ = [[[UILabel alloc] initWithFrame:captrect] autorelease];
     [caption_ setText:UCLocalize("PREPARING_FILESYSTEM")];
     [caption_ setAutoresizingMask:UIViewAutoresizingFlexibleWidth | UIViewAutoresizingFlexibleTopMargin | UIViewAutoresizingFlexibleBottomMargin];
@@ -8697,14 +8925,14 @@ static void HomeControllerReachabilityCallback(SCNetworkReachabilityRef reachabi
     [caption_ setTextColor:[UIColor whiteColor]];
     [caption_ setBackgroundColor:[UIColor clearColor]];
     [caption_ setShadowColor:[UIColor blackColor]];
     [caption_ setTextColor:[UIColor whiteColor]];
     [caption_ setBackgroundColor:[UIColor clearColor]];
     [caption_ setShadowColor:[UIColor blackColor]];
-    [caption_ setTextAlignment:UITextAlignmentCenter];
+    [caption_ setTextAlignment:NSTextAlignmentCenter];
     [view addSubview:caption_];
 
     CGRect statusrect;
     statusrect.size.width = [[self view] frame].size.width;
     statusrect.size.height = 30.0f;
     statusrect.origin.x = 0;
     [view addSubview:caption_];
 
     CGRect statusrect;
     statusrect.size.width = [[self view] frame].size.width;
     statusrect.size.height = 30.0f;
     statusrect.origin.x = 0;
-    statusrect.origin.y = ([[self view] frame].size.height / 2) - statusrect.size.height;
+    statusrect.origin.y = Retina([[self view] frame].size.height / 2 - statusrect.size.height);
     status_ = [[[UILabel alloc] initWithFrame:statusrect] autorelease];
     [status_ setAutoresizingMask:UIViewAutoresizingFlexibleLeftMargin | UIViewAutoresizingFlexibleRightMargin | UIViewAutoresizingFlexibleTopMargin | UIViewAutoresizingFlexibleBottomMargin];
     [status_ setText:UCLocalize("EXIT_WHEN_COMPLETE")];
     status_ = [[[UILabel alloc] initWithFrame:statusrect] autorelease];
     [status_ setAutoresizingMask:UIViewAutoresizingFlexibleLeftMargin | UIViewAutoresizingFlexibleRightMargin | UIViewAutoresizingFlexibleTopMargin | UIViewAutoresizingFlexibleBottomMargin];
     [status_ setText:UCLocalize("EXIT_WHEN_COMPLETE")];
@@ -8712,7 +8940,7 @@ static void HomeControllerReachabilityCallback(SCNetworkReachabilityRef reachabi
     [status_ setTextColor:[UIColor whiteColor]];
     [status_ setBackgroundColor:[UIColor clearColor]];
     [status_ setShadowColor:[UIColor blackColor]];
     [status_ setTextColor:[UIColor whiteColor]];
     [status_ setBackgroundColor:[UIColor clearColor]];
     [status_ setShadowColor:[UIColor blackColor]];
-    [status_ setTextAlignment:UITextAlignmentCenter];
+    [status_ setTextAlignment:NSTextAlignmentCenter];
     [view addSubview:status_];
 }
 
     [view addSubview:status_];
 }
 
@@ -8772,18 +9000,21 @@ static void HomeControllerReachabilityCallback(SCNetworkReachabilityRef reachabi
     [super storeCachedResponse:cached forRequest:request];
 }
 
     [super storeCachedResponse:cached forRequest:request];
 }
 
+- (void) createDiskCachePath {
+    [super createDiskCachePath];
+}
+
 @end
 
 @interface Cydia : UIApplication <
     ConfirmationControllerDelegate,
     DatabaseDelegate,
 @end
 
 @interface Cydia : UIApplication <
     ConfirmationControllerDelegate,
     DatabaseDelegate,
-    CydiaDelegate,
-    UINavigationControllerDelegate,
-    UITabBarControllerDelegate
+    CydiaDelegate
 > {
     _H<UIWindow> window_;
     _H<CydiaTabBarController> tabbar_;
 > {
     _H<UIWindow> window_;
     _H<CydiaTabBarController> tabbar_;
-    _H<CydiaLoadingViewController> emulated_;
+    _H<CyteTabBarController> emulated_;
+    _H<AppCacheController> appcache_;
 
     _H<NSMutableArray> essential_;
     _H<NSMutableArray> broken_;
 
     _H<NSMutableArray> essential_;
     _H<NSMutableArray> broken_;
@@ -8896,30 +9127,17 @@ static void HomeControllerReachabilityCallback(SCNetworkReachabilityRef reachabi
     [self _loaded];
 }
 
     [self _loaded];
 }
 
-- (void) _saveConfig {
-    @synchronized (database_) {
-        _trace();
-        MetaFile_.Sync();
-        _trace();
-    }
-
-    if (Changed_) {
-        NSString *error(nil);
-
-        if (NSData *data = [NSPropertyListSerialization dataFromPropertyList:Metadata_ format:NSPropertyListBinaryFormat_v1_0 errorDescription:&error]) {
-            _trace();
-            NSError *error(nil);
-            if (![data writeToFile:@"/var/lib/cydia/metadata.plist" options:NSAtomicWrite error:&error])
-                NSLog(@"failure to save metadata data: %@", error);
-            _trace();
-
-            Changed_ = false;
-        } else {
-            NSLog(@"failure to serialize metadata: %@", error);
-        }
-    }
+- (void) reloadSpringBoard {
+    if (kCFCoreFoundationVersionNumber >= 700) // XXX: iOS 6.x
+        system("/usr/libexec/cydia/cydo /bin/launchctl stop com.apple.backboardd");
+    else
+        system("/usr/libexec/cydia/cydo /bin/launchctl stop com.apple.SpringBoard");
+    sleep(15);
+    system("/usr/bin/killall backboardd SpringBoard");
+}
 
 
-    CydiaWriteSources();
+- (void) _saveConfig {
+    SaveConfig(database_);
 }
 
 // Navigation controller for the queuing badge.
 }
 
 // Navigation controller for the queuing badge.
@@ -8946,13 +9164,15 @@ static void HomeControllerReachabilityCallback(SCNetworkReachabilityRef reachabi
     [[navigation tabBarItem] setBadgeValue:(Queuing_ ? UCLocalize("Q_D") : nil)];
 }
 
     [[navigation tabBarItem] setBadgeValue:(Queuing_ ? UCLocalize("Q_D") : nil)];
 }
 
-- (void) _refreshIfPossible:(NSDate *)update {
+- (void) _refreshIfPossible {
     NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init];
 
     NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init];
 
+    NSDate *update([[NSDictionary dictionaryWithContentsOfFile:@ CacheState_] objectForKey:@"LastUpdate"]);
+
     bool recently = false;
     if (update != nil) {
         NSTimeInterval interval([update timeIntervalSinceNow]);
     bool recently = false;
     if (update != nil) {
         NSTimeInterval interval([update timeIntervalSinceNow]);
-        if (interval <= 0 && interval > -(15*60))
+        if (interval > -(15*60))
             recently = true;
     }
 
             recently = true;
     }
 
@@ -8970,17 +9190,18 @@ static void HomeControllerReachabilityCallback(SCNetworkReachabilityRef reachabi
         // We are going to load, so remember that.
         loaded_ = true;
 
         // We are going to load, so remember that.
         loaded_ = true;
 
-        [tabbar_ performSelectorOnMainThread:@selector(setUpdate:) withObject:update waitUntilDone:NO];
+        [tabbar_ performSelectorOnMainThread:@selector(beginUpdate) withObject:nil waitUntilDone:NO];
     }
 
     [pool release];
 }
 
 - (void) refreshIfPossible {
     }
 
     [pool release];
 }
 
 - (void) refreshIfPossible {
-    [NSThread detachNewThreadSelector:@selector(_refreshIfPossible:) toTarget:self withObject:[Metadata_ objectForKey:@"LastUpdate"]];
+    [NSThread detachNewThreadSelector:@selector(_refreshIfPossible) toTarget:self withObject:nil];
 }
 
 - (void) reloadDataWithInvocation:(NSInvocation *)invocation {
 }
 
 - (void) reloadDataWithInvocation:(NSInvocation *)invocation {
+_profile(reloadDataWithInvocation)
 @synchronized (self) {
     UIProgressHUD *hud(loaded_ ? [self addProgressHUD] : nil);
     if (hud != nil)
 @synchronized (self) {
     UIProgressHUD *hud(loaded_ ? [self addProgressHUD] : nil);
     if (hud != nil)
@@ -8993,6 +9214,7 @@ static void HomeControllerReachabilityCallback(SCNetworkReachabilityRef reachabi
     [essential_ removeAllObjects];
     [broken_ removeAllObjects];
 
     [essential_ removeAllObjects];
     [broken_ removeAllObjects];
 
+    _profile(reloadDataWithInvocation$Essential)
     NSArray *packages([database_ packages]);
     for (Package *package in packages) {
         if ([package half])
     NSArray *packages([database_ packages]);
     for (Package *package in packages) {
         if ([package half])
@@ -9003,6 +9225,7 @@ static void HomeControllerReachabilityCallback(SCNetworkReachabilityRef reachabi
             ++changes;
         }
     }
             ++changes;
         }
     }
+    _end
 
     UITabBarItem *changesItem = [[[tabbar_ viewControllers] objectAtIndex:2] tabBarItem];
     if (changes != 0) {
 
     UITabBarItem *changesItem = [[[tabbar_ viewControllers] objectAtIndex:2] tabBarItem];
     if (changes != 0) {
@@ -9018,11 +9241,16 @@ static void HomeControllerReachabilityCallback(SCNetworkReachabilityRef reachabi
         [self setApplicationIconBadgeNumber:0];
     }
 
         [self setApplicationIconBadgeNumber:0];
     }
 
+    Queuing_ = false;
     [self _updateData];
 
     if (hud != nil)
         [self removeProgressHUD:hud];
     [self _updateData];
 
     if (hud != nil)
         [self removeProgressHUD:hud];
-} }
+}
+_end
+
+    PrintTimes();
+}
 
 - (void) updateData {
     [self _updateData];
 
 - (void) updateData {
     [self _updateData];
@@ -9043,18 +9271,19 @@ static void HomeControllerReachabilityCallback(SCNetworkReachabilityRef reachabi
     if (emulated_ == nil)
         return;
 
     if (emulated_ == nil)
         return;
 
-    [window_ addSubview:[tabbar_ view]];
     if ([window_ respondsToSelector:@selector(setRootViewController:)])
         [window_ setRootViewController:tabbar_];
     if ([window_ respondsToSelector:@selector(setRootViewController:)])
         [window_ setRootViewController:tabbar_];
-    [[emulated_ view] removeFromSuperview];
+    else {
+        [window_ addSubview:[tabbar_ view]];
+        [[emulated_ view] removeFromSuperview];
+    }
+
     emulated_ = nil;
     [window_ setUserInteractionEnabled:YES];
 }
 
 - (void) presentModalViewController:(UIViewController *)controller force:(BOOL)force {
     UINavigationController *navigation([[[UINavigationController alloc] initWithRootViewController:controller] autorelease]);
     emulated_ = nil;
     [window_ setUserInteractionEnabled:YES];
 }
 
 - (void) presentModalViewController:(UIViewController *)controller force:(BOOL)force {
     UINavigationController *navigation([[[UINavigationController alloc] initWithRootViewController:controller] autorelease]);
-    if (IsWildcat_)
-        [navigation setModalPresentationStyle:UIModalPresentationFormSheet];
 
     UIViewController *parent;
     if (emulated_ == nil)
 
     UIViewController *parent;
     if (emulated_ == nil)
@@ -9066,6 +9295,8 @@ static void HomeControllerReachabilityCallback(SCNetworkReachabilityRef reachabi
         parent = tabbar_;
     }
 
         parent = tabbar_;
     }
 
+    if (IsWildcat_)
+        [navigation setModalPresentationStyle:UIModalPresentationFormSheet];
     [parent presentModalViewController:navigation animated:YES];
 }
 
     [parent presentModalViewController:navigation animated:YES];
 }
 
@@ -9114,12 +9345,10 @@ static void HomeControllerReachabilityCallback(SCNetworkReachabilityRef reachabi
     CydiaAddSource(href, distribution, sections);
 }
 
     CydiaAddSource(href, distribution, sections);
 }
 
-- (void) addTrivialSource:(NSString *)href {
+// XXX: this method should not return anything
+- (BOOL) addTrivialSource:(NSString *)href {
     CydiaAddSource(href, @"./");
     CydiaAddSource(href, @"./");
-}
-
-- (void) updateValues {
-    Changed_ = true;
+    return YES;
 }
 
 - (void) resolve {
 }
 
 - (void) resolve {
@@ -9201,7 +9430,7 @@ static void HomeControllerReachabilityCallback(SCNetworkReachabilityRef reachabi
 
 - (void) _uicache {
     _trace();
 
 - (void) _uicache {
     _trace();
-    system("su -c /usr/bin/uicache mobile");
+    system("/usr/bin/uicache");
     _trace();
 }
 
     _trace();
 }
 
@@ -9274,12 +9503,14 @@ static void HomeControllerReachabilityCallback(SCNetworkReachabilityRef reachabi
             @synchronized (self) {
                 for (Package *broken in (id) broken_) {
                     [broken remove];
             @synchronized (self) {
                 for (Package *broken in (id) 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]);
+                    NSString *id(ShellEscape([broken id]));
+                    system([[NSString stringWithFormat:@"/usr/libexec/cydia/cydo /bin/rm -f"
+                        " /var/lib/dpkg/info/%@.prerm"
+                        " /var/lib/dpkg/info/%@.postrm"
+                        " /var/lib/dpkg/info/%@.preinst"
+                        " /var/lib/dpkg/info/%@.postinst"
+                        " /var/lib/dpkg/info/%@.extrainst_"
+                    "", id, id, id, id, id] UTF8String]);
                 }
 
                 [self resolve];
                 }
 
                 [self resolve];
@@ -9333,6 +9564,9 @@ static void HomeControllerReachabilityCallback(SCNetworkReachabilityRef reachabi
         return false;
     }
 
         return false;
     }
 
+    if ([tabbar_ modalViewController] != nil)
+        return false;
+
     // Use external process status API internally.
     // This is probably a really bad idea.
     // XXX: what is the point of this? does this solve anything at all?
     // Use external process status API internally.
     // This is probably a really bad idea.
     // XXX: what is the point of this? does this solve anything at all?
@@ -9356,6 +9590,21 @@ static void HomeControllerReachabilityCallback(SCNetworkReachabilityRef reachabi
     return true;
 }
 
     return true;
 }
 
+- (void) suspendReturningToLastApp:(BOOL)returning {
+    if ([self isSafeToSuspend])
+        [super suspendReturningToLastApp:returning];
+}
+
+- (void) suspend {
+    if ([self isSafeToSuspend])
+        [super suspend];
+}
+
+- (void) applicationSuspend {
+    if ([self isSafeToSuspend])
+        [super applicationSuspend];
+}
+
 - (void) applicationSuspend:(__GSEvent *)event {
     if ([self isSafeToSuspend])
         [super applicationSuspend:event];
 - (void) applicationSuspend:(__GSEvent *)event {
     if ([self isSafeToSuspend])
         [super applicationSuspend:event];
@@ -9464,7 +9713,7 @@ static void HomeControllerReachabilityCallback(SCNetworkReachabilityRef reachabi
             controller = [[[SectionController alloc] initWithDatabase:database_ source:nil section:argument] autorelease];
         }
 
             controller = [[[SectionController alloc] initWithDatabase:database_ source:nil section:argument] autorelease];
         }
 
-        if (!external && [base isEqualToString:@"sources"]) {
+        if ([base isEqualToString:@"sources"]) {
             if ([argument isEqualToString:@"add"]) {
                 controller = [[[SourcesController alloc] initWithDatabase:database_] autorelease];
                 [(SourcesController *)controller showAddSourcePrompt];
             if ([argument isEqualToString:@"add"]) {
                 controller = [[[SourcesController alloc] initWithDatabase:database_] autorelease];
                 [(SourcesController *)controller showAddSourcePrompt];
@@ -9532,10 +9781,11 @@ static void HomeControllerReachabilityCallback(SCNetworkReachabilityRef reachabi
 }
 
 - (void) saveState {
 }
 
 - (void) saveState {
-    [Metadata_ setObject:[tabbar_ navigationURLCollection] forKey:@"InterfaceState"];
-    [Metadata_ setObject:[NSDate date] forKey:@"LastClosed"];
-    [Metadata_ setObject:[NSNumber numberWithInt:[tabbar_ selectedIndex]] forKey:@"InterfaceIndex"];
-    Changed_ = true;
+    [[NSDictionary dictionaryWithObjectsAndKeys:
+        @"InterfaceState", [tabbar_ navigationURLCollection],
+        @"LastClosed", [NSDate date],
+        @"InterfaceIndex", [NSNumber numberWithInt:[tabbar_ selectedIndex]],
+    nil] writeToFile:@ SavedState_ atomically:YES];
 
     [self _saveConfig];
 }
 
     [self _saveConfig];
 }
@@ -9544,8 +9794,37 @@ static void HomeControllerReachabilityCallback(SCNetworkReachabilityRef reachabi
     [self saveState];
 }
 
     [self saveState];
 }
 
+- (void) applicationDidEnterBackground:(UIApplication *)application {
+    if (kCFCoreFoundationVersionNumber < 1000 && [self isSafeToSuspend])
+        return [self terminateWithSuccess];
+    Backgrounded_ = [NSDate date];
+    [self saveState];
+}
+
+- (void) applicationWillEnterForeground:(UIApplication *)application {
+    if (Backgrounded_ == nil)
+        return;
+
+    NSTimeInterval interval([Backgrounded_ timeIntervalSinceNow]);
+
+    if (interval <= -(30*60)) {
+        [tabbar_ setSelectedIndex:0];
+        [[[tabbar_ viewControllers] objectAtIndex:0] popToRootViewControllerAnimated:NO];
+    }
+
+    if (interval <= -(15*60)) {
+        if (IsReachable("cydia.saurik.com")) {
+            [tabbar_ beginUpdate];
+            [appcache_ reloadURLWithCache:YES];
+        }
+    }
+
+    if ([database_ delocked])
+        [self reloadData];
+}
+
 - (void) setConfigurationData:(NSString *)data {
 - (void) setConfigurationData:(NSString *)data {
-    static Pcre conffile_r("^'(.*)' '(.*)' ([01]) ([01])$");
+    static RegEx conffile_r("'(.*)' '(.*)' ([01]) ([01])");
 
     if (!conffile_r(data)) {
         lprintf("E:invalid conffile\n");
 
     if (!conffile_r(data)) {
         lprintf("E:invalid conffile\n");
@@ -9586,18 +9865,11 @@ static void HomeControllerReachabilityCallback(SCNetworkReachabilityRef reachabi
 - (void) stash {
     [[UIApplication sharedApplication] setStatusBarStyle:UIStatusBarStyleBlackOpaque];
     UpdateExternalStatus(1);
 - (void) stash {
     [[UIApplication sharedApplication] setStatusBarStyle:UIStatusBarStyleBlackOpaque];
     UpdateExternalStatus(1);
-    [self yieldToSelector:@selector(system:) withObject:@"/usr/libexec/cydia/free.sh"];
+    [self yieldToSelector:@selector(system:) withObject:@"/usr/libexec/cydia/cydo /usr/libexec/cydia/free.sh"];
     UpdateExternalStatus(0);
 
     [self removeStashController];
     UpdateExternalStatus(0);
 
     [self removeStashController];
-
-    pid_t pid(ExecFork());
-    if (pid == 0) {
-        execlp("launchctl", "launchctl", "stop", "com.apple.SpringBoard", NULL);
-        perror("launchctl stop");
-
-        exit(0);
-    } ReapZombie(pid);
+    [self reloadSpringBoard];
 }
 
 - (void) setupViewControllers {
 }
 
 - (void) setupViewControllers {
@@ -9606,19 +9878,19 @@ static void HomeControllerReachabilityCallback(SCNetworkReachabilityRef reachabi
     NSMutableArray *items;
     if (kCFCoreFoundationVersionNumber < 800) {
         items = [NSMutableArray arrayWithObjects:
     NSMutableArray *items;
     if (kCFCoreFoundationVersionNumber < 800) {
         items = [NSMutableArray arrayWithObjects:
-            [[[UITabBarItem alloc] initWithTitle:@"Cydia" image:[UIImage applicationImageNamed:@"home.png"] tag:0] autorelease],
-            [[[UITabBarItem alloc] initWithTitle:UCLocalize("SOURCES") image:[UIImage applicationImageNamed:@"install.png"] tag:0] autorelease],
-            [[[UITabBarItem alloc] initWithTitle:UCLocalize("CHANGES") image:[UIImage applicationImageNamed:@"changes.png"] tag:0] autorelease],
-            [[[UITabBarItem alloc] initWithTitle:UCLocalize("INSTALLED") image:[UIImage applicationImageNamed:@"manage.png"] tag:0] autorelease],
-            [[[UITabBarItem alloc] initWithTitle:UCLocalize("SEARCH") image:[UIImage applicationImageNamed:@"search.png"] tag:0] autorelease],
+            [[[UITabBarItem alloc] initWithTitle:@"Cydia" image:[UIImage imageNamed:@"home.png"] tag:0] autorelease],
+            [[[UITabBarItem alloc] initWithTitle:UCLocalize("SOURCES") image:[UIImage imageNamed:@"install.png"] tag:0] autorelease],
+            [[[UITabBarItem alloc] initWithTitle:UCLocalize("CHANGES") image:[UIImage imageNamed:@"changes.png"] tag:0] autorelease],
+            [[[UITabBarItem alloc] initWithTitle:UCLocalize("INSTALLED") image:[UIImage imageNamed:@"manage.png"] tag:0] autorelease],
+            [[[UITabBarItem alloc] initWithTitle:UCLocalize("SEARCH") image:[UIImage imageNamed:@"search.png"] tag:0] autorelease],
         nil];
     } else {
         items = [NSMutableArray arrayWithObjects:
         nil];
     } else {
         items = [NSMutableArray arrayWithObjects:
-            [[[UITabBarItem alloc] initWithTitle:@"Cydia" image:[UIImage applicationImageNamed:@"home7.png"] selectedImage:[UIImage applicationImageNamed:@"home7s.png"]] autorelease],
-            [[[UITabBarItem alloc] initWithTitle:UCLocalize("SOURCES") image:[UIImage applicationImageNamed:@"install7.png"] selectedImage:[UIImage applicationImageNamed:@"install7s.png"]] autorelease],
-            [[[UITabBarItem alloc] initWithTitle:UCLocalize("CHANGES") image:[UIImage applicationImageNamed:@"changes7.png"] selectedImage:[UIImage applicationImageNamed:@"changes7s.png"]] autorelease],
-            [[[UITabBarItem alloc] initWithTitle:UCLocalize("INSTALLED") image:[UIImage applicationImageNamed:@"manage7.png"] selectedImage:[UIImage applicationImageNamed:@"manage7s.png"]] autorelease],
-            [[[UITabBarItem alloc] initWithTitle:UCLocalize("SEARCH") image:[UIImage applicationImageNamed:@"search7.png"] selectedImage:[UIImage applicationImageNamed:@"search7s.png"]] autorelease],
+            [[[UITabBarItem alloc] initWithTitle:@"Cydia" image:[UIImage imageNamed:@"home7.png"] selectedImage:[UIImage imageNamed:@"home7s.png"]] autorelease],
+            [[[UITabBarItem alloc] initWithTitle:UCLocalize("SOURCES") image:[UIImage imageNamed:@"install7.png"] selectedImage:[UIImage imageNamed:@"install7s.png"]] autorelease],
+            [[[UITabBarItem alloc] initWithTitle:UCLocalize("CHANGES") image:[UIImage imageNamed:@"changes7.png"] selectedImage:[UIImage imageNamed:@"changes7s.png"]] autorelease],
+            [[[UITabBarItem alloc] initWithTitle:UCLocalize("INSTALLED") image:[UIImage imageNamed:@"manage7.png"] selectedImage:[UIImage imageNamed:@"manage7s.png"]] autorelease],
+            [[[UITabBarItem alloc] initWithTitle:UCLocalize("SEARCH") image:[UIImage imageNamed:@"search7.png"] selectedImage:[UIImage imageNamed:@"search7s.png"]] autorelease],
         nil];
     }
 
         nil];
     }
 
@@ -9667,7 +9939,7 @@ _trace();
     [NSURLCache setSharedURLCache:[[[CYURLCache alloc]
         initWithMemoryCapacity:524288
         diskCapacity:10485760
     [NSURLCache setSharedURLCache:[[[CYURLCache alloc]
         initWithMemoryCapacity:524288
         diskCapacity:10485760
-        diskPath:[NSString stringWithFormat:@"%@/SDURLCache", Cache_]
+        diskPath:Cache("SDURLCache")
     ] autorelease]];
 
     [CydiaWebViewController _initialize];
     ] autorelease]];
 
     [CydiaWebViewController _initialize];
@@ -9688,13 +9960,17 @@ _trace();
     broken_ = [NSMutableArray arrayWithCapacity:4];
 
     // XXX: I really need this thing... like, seriously... I'm sorry
     broken_ = [NSMutableArray arrayWithCapacity:4];
 
     // XXX: I really need this thing... like, seriously... I'm sorry
-    [[[AppCacheController alloc] initWithURL:[NSURL URLWithString:[NSString stringWithFormat:@"%@/appcache/", UI_]]] reloadData];
+    appcache_ = [[[AppCacheController alloc] initWithURL:[NSURL URLWithString:[NSString stringWithFormat:@"%@/appcache/", UI_]]] autorelease];
+    [appcache_ reloadData];
 
     window_ = [[[UIWindow alloc] initWithFrame:[[UIScreen mainScreen] bounds]] autorelease];
     [window_ orderFront:self];
     [window_ makeKey:self];
     [window_ setHidden:NO];
 
 
     window_ = [[[UIWindow alloc] initWithFrame:[[UIScreen mainScreen] bounds]] autorelease];
     [window_ orderFront:self];
     [window_ makeKey:self];
     [window_ setHidden:NO];
 
+    if (access("/.cydia_no_stash", F_OK) == 0);
+    else {
+
     if (false) stash: {
         [self addStashController];
         // XXX: this would be much cleaner as a yieldToSelector:
     if (false) stash: {
         [self addStashController];
         // XXX: this would be much cleaner as a yieldToSelector:
@@ -9725,20 +10001,32 @@ _trace();
     Stash_("/Library/Wallpaper");
     //Stash_("/usr/bin");
     Stash_("/usr/include");
     Stash_("/Library/Wallpaper");
     //Stash_("/usr/bin");
     Stash_("/usr/include");
-    Stash_("/usr/lib/pam");
     Stash_("/usr/share");
     //Stash_("/var/lib");
 
     Stash_("/usr/share");
     //Stash_("/var/lib");
 
+    }
+
     database_ = [Database sharedInstance];
     [database_ setDelegate:self];
 
     [window_ setUserInteractionEnabled:NO];
     [self setupViewControllers];
 
     database_ = [Database sharedInstance];
     [database_ setDelegate:self];
 
     [window_ setUserInteractionEnabled:NO];
     [self setupViewControllers];
 
-    emulated_ = [[[CydiaLoadingViewController alloc] init] autorelease];
-    [window_ addSubview:[emulated_ view]];
+    CydiaLoadingViewController *loading([[[CydiaLoadingViewController alloc] init] autorelease]);
+    UINavigationController *navigation([[[UINavigationController alloc] init] autorelease]);
+    [navigation setViewControllers:[NSArray arrayWithObject:loading]];
+
+    emulated_ = [[[CyteTabBarController alloc] init] autorelease];
+    [emulated_ setViewControllers:[NSArray arrayWithObject:navigation]];
+    [emulated_ setSelectedIndex:0];
+
+    if ([emulated_ respondsToSelector:@selector(concealTabBarSelection)])
+        [emulated_ concealTabBarSelection];
+
     if ([window_ respondsToSelector:@selector(setRootViewController:)])
         [window_ setRootViewController:emulated_];
     if ([window_ respondsToSelector:@selector(setRootViewController:)])
         [window_ setRootViewController:emulated_];
+    else
+        [window_ addSubview:[emulated_ view]];
 
     [self performSelector:@selector(loadData) withObject:nil afterDelay:0];
 _trace();
 
     [self performSelector:@selector(loadData) withObject:nil afterDelay:0];
 _trace();
@@ -9762,12 +10050,12 @@ _trace();
 
     [self reloadDataWithInvocation:nil];
     [self refreshIfPossible];
 
     [self reloadDataWithInvocation:nil];
     [self refreshIfPossible];
-    PrintTimes();
-
     [self disemulate];
 
     [self disemulate];
 
-    int savedIndex = [[Metadata_ objectForKey:@"InterfaceIndex"] intValue];
-    NSArray *saved = [[[Metadata_ objectForKey:@"InterfaceState"] mutableCopy] autorelease];
+    NSDictionary *state([NSDictionary dictionaryWithContentsOfFile:@ SavedState_]);
+
+    int savedIndex = [[state objectForKey:@"InterfaceIndex"] intValue];
+    NSArray *saved = [[[state objectForKey:@"InterfaceState"] mutableCopy] autorelease];
     int standardIndex = 0;
     NSArray *standard = [self defaultStartPages];
 
     int standardIndex = 0;
     NSArray *standard = [self defaultStartPages];
 
@@ -9776,10 +10064,9 @@ _trace();
     if (saved == nil)
         valid = NO;
 
     if (saved == nil)
         valid = NO;
 
-    NSDate *closed = [Metadata_ objectForKey:@"LastClosed"];
+    NSDate *closed = [state objectForKey:@"LastClosed"];
     if (valid && closed != nil) {
         NSTimeInterval interval([closed timeIntervalSinceNow]);
     if (valid && closed != nil) {
         NSTimeInterval interval([closed timeIntervalSinceNow]);
-        // XXX: Is 30 minutes the optimal time here?
         if (interval <= -(30*60))
             valid = NO;
     }
         if (interval <= -(30*60))
             valid = NO;
     }
@@ -9826,12 +10113,17 @@ _trace();
 
     // (Try to) show the startup URL.
     if (starturl_ != nil) {
 
     // (Try to) show the startup URL.
     if (starturl_ != nil) {
-        [self openCydiaURL:starturl_ forExternal:NO];
+        [self openCydiaURL:starturl_ forExternal:YES];
         starturl_ = nil;
     }
 }
 
 - (void) showActionSheet:(UIActionSheet *)sheet fromItem:(UIBarButtonItem *)item {
         starturl_ = nil;
     }
 }
 
 - (void) showActionSheet:(UIActionSheet *)sheet fromItem:(UIBarButtonItem *)item {
+    if (!IsWildcat_) {
+       [sheet addButtonWithTitle:UCLocalize("CANCEL")];
+       [sheet setCancelButtonIndex:[sheet numberOfButtons] - 1];
+    }
+
     if (item != nil && IsWildcat_) {
         [sheet showFromBarButtonItem:item animated:YES];
     } else {
     if (item != nil && IsWildcat_) {
         [sheet showFromBarButtonItem:item animated:YES];
     } else {
@@ -9871,44 +10163,6 @@ id Dealloc_(id self, SEL selector) {
     return object;
 }*/
 
     return object;
 }*/
 
-static NSSet *MobilizedFiles_;
-
-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];
-    }
-
-    return url;
-}
-
-Class $CFXPreferencesPropertyListSource;
-@class CFXPreferencesPropertyListSource;
-
-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;
-}
-
-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;
 
 MSHook(id, NSURLConnection$init$, NSURLConnection *self, SEL _cmd, NSURLRequest *request, id delegate, BOOL usesCache, int64_t maxContentLength, BOOL startImmediately, NSDictionary *connectionProperties) {
 Class $NSURLConnection;
 
 MSHook(id, NSURLConnection$init$, NSURLConnection *self, SEL _cmd, NSURLRequest *request, id delegate, BOOL usesCache, int64_t maxContentLength, BOOL startImmediately, NSDictionary *connectionProperties) {
@@ -9959,11 +10213,36 @@ Class $NSUserDefaults;
 
 MSHook(id, NSUserDefaults$objectForKey$, NSUserDefaults *self, SEL _cmd, NSString *key) {
     if ([key respondsToSelector:@selector(isEqualToString:)] && [key isEqualToString:@"WebKitLocalStorageDatabasePathPreferenceKey"])
 
 MSHook(id, NSUserDefaults$objectForKey$, NSUserDefaults *self, SEL _cmd, NSString *key) {
     if ([key respondsToSelector:@selector(isEqualToString:)] && [key isEqualToString:@"WebKitLocalStorageDatabasePathPreferenceKey"])
-        return [NSString stringWithFormat:@"%@/LocalStorage", Cache_];
+        return Cache("LocalStorage");
     return _NSUserDefaults$objectForKey$(self, _cmd, key);
 }
 
     return _NSUserDefaults$objectForKey$(self, _cmd, key);
 }
 
+static NSMutableDictionary *AutoreleaseDeepMutableCopyOfDictionary(CFTypeRef type) {
+    if (type == NULL)
+        return nil;
+    if (CFGetTypeID(type) != CFDictionaryGetTypeID())
+        return nil;
+    CFTypeRef copy(CFPropertyListCreateDeepCopy(kCFAllocatorDefault, type, kCFPropertyListMutableContainers));
+    CFRelease(type);
+    return [(NSMutableDictionary *) copy autorelease];
+}
+
+int main_store(int, char *argv[]);
+
 int main(int argc, char *argv[]) {
 int main(int argc, char *argv[]) {
+#ifdef __arm64__
+    const char *argv0(argv[0]);
+    if (const char *slash = strrchr(argv0, '/'))
+        argv0 = slash + 1;
+    if (false);
+    else if (!strcmp(argv0, "store"))
+        return main_store(argc, argv);
+#endif
+
+    int fd(open("/tmp/cydia.log", O_WRONLY | O_APPEND | O_CREAT, 0644));
+    dup2(fd, 2);
+    close(fd);
+
     NSAutoreleasePool *pool([[NSAutoreleasePool alloc] init]);
 
     _trace();
     NSAutoreleasePool *pool([[NSAutoreleasePool alloc] init]);
 
     _trace();
@@ -9985,7 +10264,7 @@ int main(int argc, char *argv[]) {
 
     Idiom_ = IsWildcat_ ? @"ipad" : @"iphone";
 
 
     Idiom_ = IsWildcat_ ? @"ipad" : @"iphone";
 
-    Pcre pattern("^([0-9]+\\.[0-9]+)");
+    RegEx pattern("([0-9]+\\.[0-9]+).*");
 
     if (pattern([device systemVersion]))
         Firmware_ = pattern[1];
 
     if (pattern([device systemVersion]))
         Firmware_ = pattern[1];
@@ -9997,7 +10276,6 @@ int main(int argc, char *argv[]) {
     HostConfig_ = [[[NSObject alloc] init] autorelease];
     @synchronized (HostConfig_) {
         BridgedHosts_ = [NSMutableSet setWithCapacity:4];
     HostConfig_ = [[[NSObject alloc] init] autorelease];
     @synchronized (HostConfig_) {
         BridgedHosts_ = [NSMutableSet setWithCapacity:4];
-        TokenHosts_ = [NSMutableSet setWithCapacity:4];
         InsecureHosts_ = [NSMutableSet setWithCapacity:4];
         PipelinedHosts_ = [NSMutableSet setWithCapacity:4];
         CachedURLs_ = [NSMutableSet setWithCapacity:32];
         InsecureHosts_ = [NSMutableSet setWithCapacity:4];
         PipelinedHosts_ = [NSMutableSet setWithCapacity:4];
         CachedURLs_ = [NSMutableSet setWithCapacity:32];
@@ -10011,11 +10289,6 @@ int main(int argc, char *argv[]) {
 
     PackageName = reinterpret_cast<CYString &(*)(Package *, SEL)>(method_getImplementation(class_getInstanceMethod([Package class], @selector(cyname))));
 
 
     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");
 
     /* Library Hacks {{{ */
     class_addMethod(objc_getClass("DOMNodeList"), @selector(countByEnumeratingWithState:objects:count:), (IMP) &DOMNodeList$countByEnumeratingWithState$objects$count$, "I20@0:4^{NSFastEnumerationState}8^@12I16");
 
@@ -10024,20 +10297,6 @@ int main(int argc, char *argv[]) {
         if (Method method = class_getInstanceMethod($WAKWindow, @selector(screenSize)))
             method_setImplementation(method, (IMP) &$WAKWindow$screenSize);
 
         if (Method method = class_getInstanceMethod($WAKWindow, @selector(screenSize)))
             method_setImplementation(method, (IMP) &$WAKWindow$screenSize);
 
-    $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));
-    }
-
     $NSURLConnection = objc_getClass("NSURLConnection");
     Method NSURLConnection$init$(class_getInstanceMethod($NSURLConnection, @selector(_initWithRequest:delegate:usesCache:maxContentLength:startImmediately:connectionProperties:)));
     if (NSURLConnection$init$ != NULL) {
     $NSURLConnection = objc_getClass("NSURLConnection");
     Method NSURLConnection$init$(class_getInstanceMethod($NSURLConnection, @selector(_initWithRequest:delegate:usesCache:maxContentLength:startImmediately:connectionProperties:)));
     if (NSURLConnection$init$ != NULL) {
@@ -10056,33 +10315,80 @@ int main(int argc, char *argv[]) {
     Locale_ = CFLocaleCopyCurrent();
     Languages_ = [NSLocale preferredLanguages];
 
     Locale_ = CFLocaleCopyCurrent();
     Languages_ = [NSLocale preferredLanguages];
 
-    //CFStringRef locale(CFLocaleGetIdentifier(Locale_));
-    //NSLog(@"%@", [Languages_ description]);
+    std::string languages;
+    const char *translation(NULL);
 
 
-    const char *lang;
+    // XXX: this isn't really a language, but this is compatible with older Cydia builds
     if (Locale_ != NULL)
     if (Locale_ != NULL)
-        lang = [(NSString *) CFLocaleGetIdentifier(Locale_) UTF8String];
-    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;
-
-    if (lang != NULL) {
-        Pcre pattern("^([a-z][a-z])(?:-[A-Za-z]*)?(_[A-Z][A-Z])?$");
-        lang = !pattern(lang) ? NULL : [pattern->*@"%1$@%2$@" UTF8String];
-    }
+        if (const char *language = [(NSString *) CFLocaleGetIdentifier(Locale_) UTF8String]) {
+            RegEx pattern("([a-z][a-z])(?:-[A-Za-z]*)?(_[A-Z][A-Z])?");
+            if (pattern(language)) {
+                translation = strdup([pattern->*@"%1$@%2$@" UTF8String]);
+                languages += translation;
+                languages += ",";
+            }
+        }
 
 
-    NSLog(@"Setting Language: %s", lang);
+    if (Languages_ != nil)
+        for (NSString *language : Languages_) {
+            languages += [language UTF8String];
+            languages += ",";
+        }
 
 
-    if (lang != NULL) {
-        setenv("LANG", lang, true);
-        std::setlocale(LC_ALL, lang);
-    }
+    languages += "en";
+    NSLog(@"Setting Language: [%s] %s", translation, languages.c_str());
     /* }}} */
     /* }}} */
+    /* Index Collation {{{ */
+    if (Class $UILocalizedIndexedCollation = objc_getClass("UILocalizedIndexedCollation")) { @try {
+        NSBundle *bundle([NSBundle bundleForClass:$UILocalizedIndexedCollation]);
+        NSString *path([bundle pathForResource:@"UITableViewLocalizedSectionIndex" ofType:@"plist"]);
+        //path = @"/System/Library/Frameworks/UIKit.framework/.lproj/UITableViewLocalizedSectionIndex.plist";
+        NSDictionary *dictionary([NSDictionary dictionaryWithContentsOfFile:path]);
+        _H<UILocalizedIndexedCollation> collation([[[$UILocalizedIndexedCollation alloc] initWithDictionary:dictionary] autorelease]);
+
+        CollationLocale_ = MSHookIvar<NSLocale *>(collation, "_locale");
+
+        if (kCFCoreFoundationVersionNumber >= 800 && [[CollationLocale_ localeIdentifier] isEqualToString:@"zh@collation=stroke"]) {
+            CollationThumbs_ = [NSArray arrayWithObjects:@"1",@"•",@"4",@"•",@"7",@"•",@"10",@"•",@"13",@"•",@"16",@"•",@"19",@"A",@"•",@"E",@"•",@"I",@"•",@"M",@"•",@"R",@"•",@"V",@"•",@"Z",@"#",nil];
+            for (NSInteger offset : (NSInteger[]) {0,1,3,4,6,7,9,10,12,13,15,16,18,25,26,29,30,33,34,37,38,42,43,46,47,50,51})
+                CollationOffset_.push_back(offset);
+            CollationTitles_ = [NSArray arrayWithObjects:@"1 畫",@"2 畫",@"3 畫",@"4 畫",@"5 畫",@"6 畫",@"7 畫",@"8 畫",@"9 畫",@"10 畫",@"11 畫",@"12 畫",@"13 畫",@"14 畫",@"15 畫",@"16 畫",@"17 畫",@"18 畫",@"19 畫",@"20 畫",@"21 畫",@"22 畫",@"23 畫",@"24 畫",@"25 畫以上",@"A",@"B",@"C",@"D",@"E",@"F",@"G",@"H",@"I",@"J",@"K",@"L",@"M",@"N",@"O",@"P",@"Q",@"R",@"S",@"T",@"U",@"V",@"W",@"X",@"Y",@"Z",@"#",nil];
+            CollationStarts_ = [NSArray arrayWithObjects:@"一",@"丁",@"丈",@"不",@"且",@"丞",@"串",@"並",@"亭",@"乘",@"乾",@"傀",@"亂",@"僎",@"僵",@"儐",@"償",@"叢",@"儳",@"嚴",@"儷",@"儻",@"囌",@"囑",@"廳",@"a",@"b",@"c",@"d",@"e",@"f",@"g",@"h",@"i",@"j",@"k",@"l",@"m",@"n",@"o",@"p",@"q",@"r",@"s",@"t",@"u",@"v",@"w",@"x",@"y",@"z",@"ʒ",nil];
+        } else {
+
+        CollationThumbs_ = [collation sectionIndexTitles];
+        for (size_t index(0), end([CollationThumbs_ count]); index != end; ++index)
+            CollationOffset_.push_back([collation sectionForSectionIndexTitleAtIndex:index]);
+
+        CollationTitles_ = [collation sectionTitles];
+        CollationStarts_ = MSHookIvar<NSArray *>(collation, "_sectionStartStrings");
+
+        NSString *&transform(MSHookIvar<NSString *>(collation, "_transform"));
+        if (&transform != NULL && transform != nil) {
+            /*if ([collation respondsToSelector:@selector(transformedCollationStringForString:)])
+                CollationModify_ = [=](NSString *value) { return [collation transformedCollationStringForString:value]; };*/
+            const UChar *uid(reinterpret_cast<const UChar *>([transform cStringUsingEncoding:NSUnicodeStringEncoding]));
+            UErrorCode code(U_ZERO_ERROR);
+            CollationTransl_ = utrans_openU(uid, -1, UTRANS_FORWARD, NULL, 0, NULL, &code);
+            if (!U_SUCCESS(code))
+                NSLog(@"%s", u_errorName(code));
+        }
+
+        }
+    } @catch (NSException *e) {
+        NSLog(@"%@", e);
+        goto hard;
+    } } else hard: {
+        CollationLocale_ = [[[NSLocale alloc] initWithLocaleIdentifier:@"en@collation=dictionary"] autorelease];
 
 
-    apr_app_initialize(&argc, const_cast<const char * const **>(&argv), NULL);
+        CollationThumbs_ = [NSArray arrayWithObjects:@"A",@"B",@"C",@"D",@"E",@"F",@"G",@"H",@"I",@"J",@"K",@"L",@"M",@"N",@"O",@"P",@"Q",@"R",@"S",@"T",@"U",@"V",@"W",@"X",@"Y",@"Z",@"#",nil];
+        for (NSInteger offset(0); offset != 28; ++offset)
+            CollationOffset_.push_back(offset);
 
 
+        CollationTitles_ = [NSArray arrayWithObjects:@"A",@"B",@"C",@"D",@"E",@"F",@"G",@"H",@"I",@"J",@"K",@"L",@"M",@"N",@"O",@"P",@"Q",@"R",@"S",@"T",@"U",@"V",@"W",@"X",@"Y",@"Z",@"#",nil];
+        CollationStarts_ = [NSArray arrayWithObjects:@"a",@"b",@"c",@"d",@"e",@"f",@"g",@"h",@"i",@"j",@"k",@"l",@"m",@"n",@"o",@"p",@"q",@"r",@"s",@"t",@"u",@"v",@"w",@"x",@"y",@"z",@"ʒ",nil];
+    }
+    /* }}} */
     /* Parse Arguments {{{ */
     bool substrate(false);
 
     /* Parse Arguments {{{ */
     bool substrate(false);
 
@@ -10110,13 +10416,8 @@ int main(int argc, char *argv[]) {
     App_ = [[NSBundle mainBundle] bundlePath];
     Advanced_ = YES;
 
     App_ = [[NSBundle mainBundle] bundlePath];
     Advanced_ = YES;
 
-    setuid(0);
-    setgid(0);
-
-    if (access("/var/mobile/Library/Keyboard/UserDictionary.sqlite", F_OK) == 0)
-        system("mkdir -p /var/root/Library/Keyboard; cp -af /var/mobile/Library/Keyboard/UserDictionary.sqlite /var/root/Library/Keyboard/");
-
-    Cache_ = [[NSString stringWithFormat:@"%@/Library/Caches/com.saurik.Cydia", @"/var/root"] retain];
+    Cache_ = [[NSString stringWithFormat:@"%@/Library/Caches/com.saurik.Cydia", @"/var/mobile"] retain];
+    mkdir([Cache_ UTF8String], 0755);
 
     /*Method alloc = class_getClassMethod([NSObject class], @selector(alloc));
     alloc_ = alloc->method_imp;
 
     /*Method alloc = class_getClassMethod([NSObject class], @selector(alloc));
     alloc_ = alloc->method_imp;
@@ -10156,6 +10457,11 @@ int main(int argc, char *argv[]) {
     else
         Machine_ = machine;
 
     else
         Machine_ = machine;
 
+    int64_t usermem(0);
+    size = sizeof(usermem);
+    if (sysctlbyname("hw.usermem", &usermem, &size, NULL, 0) == -1)
+        usermem = 0;
+
     SerialNumber_ = (NSString *) CYIOGetValue("IOService:/", @"IOPlatformSerialNumber");
     ChipID_ = [CYHex((NSData *) CYIOGetValue("IODeviceTree:/chosen", @"unique-chip-id"), true) uppercaseString];
     BBSNum_ = CYHex((NSData *) CYIOGetValue("IOService:/AppleARMPE/baseband", @"snum"), false);
     SerialNumber_ = (NSString *) CYIOGetValue("IOService:/", @"IOPlatformSerialNumber");
     ChipID_ = [CYHex((NSData *) CYIOGetValue("IODeviceTree:/chosen", @"unique-chip-id"), true) uppercaseString];
     BBSNum_ = CYHex((NSData *) CYIOGetValue("IOService:/AppleARMPE/baseband", @"snum"), false);
@@ -10169,55 +10475,58 @@ int main(int argc, char *argv[]) {
 
     NSString *agent([NSString stringWithFormat:@"Cydia/%@ CyF/%.2f", Cydia_, kCFCoreFoundationVersionNumber]);
 
 
     NSString *agent([NSString stringWithFormat:@"Cydia/%@ CyF/%.2f", Cydia_, kCFCoreFoundationVersionNumber]);
 
-    if (Pcre match = Pcre("^[0-9]+(\\.[0-9]+)+", Safari_))
-        agent = [NSString stringWithFormat:@"Safari/%@ %@", match[0], agent];
-    if (Pcre match = Pcre("^[0-9]+[A-Z][0-9]+[a-z]?", System_))
-        agent = [NSString stringWithFormat:@"Mobile/%@ %@", match[0], agent];
-    if (Pcre match = Pcre("^[0-9]+(\\.[0-9]+)+", Product_))
-        agent = [NSString stringWithFormat:@"Version/%@ %@", match[0], agent];
+    if (RegEx match = RegEx("([0-9]+(\\.[0-9]+)+).*", Safari_))
+        agent = [NSString stringWithFormat:@"Safari/%@ %@", match[1], agent];
+    if (RegEx match = RegEx("([0-9]+[A-Z][0-9]+[a-z]?).*", System_))
+        agent = [NSString stringWithFormat:@"Mobile/%@ %@", match[1], agent];
+    if (RegEx match = RegEx("([0-9]+(\\.[0-9]+)+).*", Product_))
+        agent = [NSString stringWithFormat:@"Version/%@ %@", match[1], agent];
 
     UserAgent_ = agent;
     /* }}} */
     /* Load Database {{{ */
 
     UserAgent_ = agent;
     /* }}} */
     /* Load Database {{{ */
-    _trace();
-    Metadata_ = [[[NSMutableDictionary alloc] initWithContentsOfFile:@"/var/lib/cydia/metadata.plist"] autorelease];
-    _trace();
     SectionMap_ = [[[NSDictionary alloc] initWithContentsOfFile:[[NSBundle mainBundle] pathForResource:@"Sections" ofType:@"plist"]] autorelease];
 
     SectionMap_ = [[[NSDictionary alloc] initWithContentsOfFile:[[NSBundle mainBundle] pathForResource:@"Sections" ofType:@"plist"]] autorelease];
 
-    if (Metadata_ == NULL)
-        Metadata_ = [NSMutableDictionary dictionaryWithCapacity:2];
-    else {
-        Settings_ = [Metadata_ objectForKey:@"Settings"];
-
-        Packages_ = [Metadata_ objectForKey:@"Packages"];
-
-        Values_ = [Metadata_ objectForKey:@"Values"];
-        Sections_ = [Metadata_ objectForKey:@"Sections"];
-        Sources_ = [Metadata_ objectForKey:@"Sources"];
+    _trace();
+    mkdir("/var/mobile/Library/Cydia", 0755);
+    MetaFile_.Open("/var/mobile/Library/Cydia/metadata.cb0");
+    _trace();
 
 
-        Token_ = [Metadata_ objectForKey:@"Token"];
+    Values_ = AutoreleaseDeepMutableCopyOfDictionary(CFPreferencesCopyAppValue(CFSTR("CydiaValues"), CFSTR("com.saurik.Cydia")));
+    Sections_ = AutoreleaseDeepMutableCopyOfDictionary(CFPreferencesCopyAppValue(CFSTR("CydiaSections"), CFSTR("com.saurik.Cydia")));
+    Sources_ = AutoreleaseDeepMutableCopyOfDictionary(CFPreferencesCopyAppValue(CFSTR("CydiaSources"), CFSTR("com.saurik.Cydia")));
+    Version_ = [(NSNumber *) CFPreferencesCopyAppValue(CFSTR("CydiaVersion"), CFSTR("com.saurik.Cydia")) autorelease];
 
 
-        Version_ = [Metadata_ objectForKey:@"Version"];
-    }
+    _trace();
+    NSDictionary *metadata([[[NSMutableDictionary alloc] initWithContentsOfFile:@"/var/lib/cydia/metadata.plist"] autorelease]);
 
 
-    if (Values_ == nil) {
+    if (Values_ == nil)
+        Values_ = [metadata objectForKey:@"Values"];
+    if (Values_ == nil)
         Values_ = [[[NSMutableDictionary alloc] initWithCapacity:4] autorelease];
         Values_ = [[[NSMutableDictionary alloc] initWithCapacity:4] autorelease];
-        [Metadata_ setObject:Values_ forKey:@"Values"];
-    }
 
 
-    if (Sections_ == nil) {
+    if (Sections_ == nil)
+        Sections_ = [metadata objectForKey:@"Sections"];
+    if (Sections_ == nil)
         Sections_ = [[[NSMutableDictionary alloc] initWithCapacity:32] autorelease];
         Sections_ = [[[NSMutableDictionary alloc] initWithCapacity:32] autorelease];
-        [Metadata_ setObject:Sections_ forKey:@"Sections"];
-    }
 
 
-    if (Sources_ == nil) {
+    if (Sources_ == nil)
+        Sources_ = [metadata objectForKey:@"Sources"];
+    if (Sources_ == nil)
         Sources_ = [[[NSMutableDictionary alloc] initWithCapacity:0] autorelease];
         Sources_ = [[[NSMutableDictionary alloc] initWithCapacity:0] autorelease];
-        [Metadata_ setObject:Sources_ forKey:@"Sources"];
-    }
 
 
-    if (Version_ == nil) {
+    // XXX: this wrong, but in a way that doesn't matter :/
+    if (Version_ == nil)
+        Version_ = [metadata objectForKey:@"Version"];
+    if (Version_ == nil)
         Version_ = [NSNumber numberWithUnsignedInt:0];
         Version_ = [NSNumber numberWithUnsignedInt:0];
-        [Metadata_ setObject:Version_ forKey:@"Version"];
+
+    if (NSDictionary *packages = [metadata objectForKey:@"Packages"]) {
+        bool fail(false);
+        CFDictionaryApplyFunction((CFDictionaryRef) packages, &PackageImport, &fail);
+        _trace();
+        if (fail)
+            NSLog(@"unable to import package preferences... from 2010? oh well :/");
     }
 
     if ([Version_ unsignedIntValue] == 0) {
     }
 
     if ([Version_ unsignedIntValue] == 0) {
@@ -10227,92 +10536,84 @@ int main(int argc, char *argv[]) {
         CydiaAddSource(@"http://repo666.ultrasn0w.com/", @"./");
 
         Version_ = [NSNumber numberWithUnsignedInt:1];
         CydiaAddSource(@"http://repo666.ultrasn0w.com/", @"./");
 
         Version_ = [NSNumber numberWithUnsignedInt:1];
-        [Metadata_ setObject:Version_ forKey:@"Version"];
 
 
-        [Metadata_ removeObjectForKey:@"LastUpdate"];
-
-        Changed_ = true;
+        if (NSMutableDictionary *cache = [NSMutableDictionary dictionaryWithContentsOfFile:@ CacheState_]) {
+            [cache removeObjectForKey:@"LastUpdate"];
+            [cache writeToFile:@ CacheState_ atomically:YES];
+        }
     }
 
     _H<NSMutableArray> broken([NSMutableArray array]);
     for (NSString *key in (id) Sources_)
     }
 
     _H<NSMutableArray> broken([NSMutableArray array]);
     for (NSString *key in (id) Sources_)
-        if ([key rangeOfCharacterFromSet:[NSCharacterSet characterSetWithCharactersInString:@"# "]].location != NSNotFound)
+        if ([key rangeOfCharacterFromSet:[NSCharacterSet characterSetWithCharactersInString:@"# "]].location != NSNotFound || ![([[Sources_ objectForKey:key] objectForKey:@"URI"] ?: @"/") hasSuffix:@"/"])
             [broken addObject:key];
             [broken addObject:key];
-    if ([broken count] != 0) {
+    if ([broken count] != 0)
         for (NSString *key in (id) broken)
             [Sources_ removeObjectForKey:key];
         for (NSString *key in (id) broken)
             [Sources_ removeObjectForKey:key];
-        Changed_ = true;
-    } broken = nil;
-    /* }}} */
-
-    CydiaWriteSources();
-
-    _trace();
-    MetaFile_.Open("/var/lib/cydia/metadata.cb0");
-    _trace();
+    broken = nil;
 
 
-    if (Packages_ != nil) {
-        bool fail(false);
-        CFDictionaryApplyFunction((CFDictionaryRef) Packages_, &PackageImport, &fail);
-        _trace();
-
-        if (!fail) {
-            [Metadata_ removeObjectForKey:@"Packages"];
-            Packages_ = nil;
-            Changed_ = true;
-        }
-    }
+    SaveConfig(nil);
+    system("/usr/libexec/cydia/cydo /bin/rm -f /var/lib/cydia/metadata.plist");
+    /* }}} */
 
     Finishes_ = [NSArray arrayWithObjects:@"return", @"reopen", @"restart", @"reload", @"reboot", nil];
 
 
     Finishes_ = [NSArray arrayWithObjects:@"return", @"reopen", @"restart", @"reload", @"reboot", nil];
 
-#define MobileSubstrate_(name) \
-    if (substrate && access("/Library/MobileSubstrate/DynamicLibraries/" #name ".dylib", F_OK) == 0) { \
-        void *handle(dlopen("/Library/MobileSubstrate/DynamicLibraries/" #name ".dylib", RTLD_LAZY | RTLD_GLOBAL)); \
-        if (handle == NULL) \
-            NSLog(@"%s", dlerror()); \
-    }
-
-    MobileSubstrate_(Activator)
-    MobileSubstrate_(libstatusbar)
-    MobileSubstrate_(SimulatedKeyEvents)
-    MobileSubstrate_(WinterBoard)
-
-    /*if (substrate && access("/Library/MobileSubstrate/MobileSubstrate.dylib", F_OK) == 0)
-        dlopen("/Library/MobileSubstrate/MobileSubstrate.dylib", RTLD_LAZY | RTLD_GLOBAL);*/
+    if (kCFCoreFoundationVersionNumber > 1000)
+        system("/usr/libexec/cydia/cydo /usr/libexec/cydia/setnsfpn /var/lib");
 
     int version([[NSString stringWithContentsOfFile:@"/var/lib/cydia/firmware.ver"] intValue]);
 
     if (access("/User", F_OK) != 0 || version != 6) {
         _trace();
 
     int version([[NSString stringWithContentsOfFile:@"/var/lib/cydia/firmware.ver"] intValue]);
 
     if (access("/User", F_OK) != 0 || version != 6) {
         _trace();
-        system("/usr/libexec/cydia/firmware.sh");
+        system("/usr/libexec/cydia/cydo /usr/libexec/cydia/firmware.sh");
         _trace();
     }
 
         _trace();
     }
 
-    _assert([[NSFileManager defaultManager]
-        createDirectoryAtPath:@"/var/cache/apt/archives/partial"
-        withIntermediateDirectories:YES
-        attributes:nil
-        error:NULL
-    ]);
-
     if (access("/tmp/cydia.chk", F_OK) == 0) {
     if (access("/tmp/cydia.chk", F_OK) == 0) {
-        if (unlink("/var/cache/apt/pkgcache.bin") == -1)
+        if (unlink([Cache("pkgcache.bin") UTF8String]) == -1)
             _assert(errno == ENOENT);
             _assert(errno == ENOENT);
-        if (unlink("/var/cache/apt/srcpkgcache.bin") == -1)
+        if (unlink([Cache("srcpkgcache.bin") UTF8String]) == -1)
             _assert(errno == ENOENT);
     }
 
             _assert(errno == ENOENT);
     }
 
+    system("/usr/libexec/cydia/cydo /bin/ln -sf /var/mobile/Library/Caches/com.saurik.Cydia/sources.list /etc/apt/sources.list.d/cydia.list");
+
     /* APT Initialization {{{ */
     _assert(pkgInitConfig(*_config));
     _assert(pkgInitSystem(*_config, _system));
 
     /* APT Initialization {{{ */
     _assert(pkgInitConfig(*_config));
     _assert(pkgInitSystem(*_config, _system));
 
-    if (lang != NULL)
-        _config->Set("APT::Acquire::Translation", lang);
+    _config->Set("Acquire::AllowInsecureRepositories", true);
+    _config->Set("Acquire::Check-Valid-Until", false);
+    _config->Set("Dir::Bin::Methods::store", "/Applications/Cydia.app/store");
+
+    _config->Set("pkgCacheGen::ForceEssential", "");
+
+    if (translation != NULL)
+        _config->Set("APT::Acquire::Translation", translation);
+    _config->Set("Acquire::Languages", languages);
 
     // XXX: this timeout might be important :(
     //_config->Set("Acquire::http::Timeout", 15);
 
 
     // XXX: this timeout might be important :(
     //_config->Set("Acquire::http::Timeout", 15);
 
-    _config->Set("Acquire::http::MaxParallel", 3);
+    _config->Set("Acquire::http::MaxParallel", usermem >= 384 * 1024 * 1024 ? 16 : 3);
+
+    mkdir([Cache("archives") UTF8String], 0755);
+    mkdir([Cache("archives/partial") UTF8String], 0755);
+    _config->Set("Dir::Cache", [Cache_ UTF8String]);
+
+    symlink("/var/lib/apt/extended_states", [Cache("extended_states") UTF8String]);
+    _config->Set("Dir::State", [Cache_ UTF8String]);
+
+    mkdir([Cache("lists") UTF8String], 0755);
+    mkdir([Cache("lists/partial") UTF8String], 0755);
+    mkdir([Cache("periodic") UTF8String], 0755);
+    _config->Set("Dir::State::Lists", [Cache("lists") UTF8String]);
+
+    std::string logs("/var/mobile/Library/Logs/Cydia");
+    mkdir(logs.c_str(), 0755);
+    _config->Set("Dir::Log", logs);
+
+    _config->Set("Dir::Bin::dpkg", "/usr/libexec/cydia/cydo");
     /* }}} */
     /* Color Choices {{{ */
     space_ = CGColorSpaceCreateDeviceRGB();
     /* }}} */
     /* Color Choices {{{ */
     space_ = CGColorSpaceCreateDeviceRGB();
@@ -10337,6 +10638,7 @@ int main(int argc, char *argv[]) {
     /* }}} */
 
     $SBSSetInterceptsMenuButtonForever = reinterpret_cast<void (*)(bool)>(dlsym(RTLD_DEFAULT, "SBSSetInterceptsMenuButtonForever"));
     /* }}} */
 
     $SBSSetInterceptsMenuButtonForever = reinterpret_cast<void (*)(bool)>(dlsym(RTLD_DEFAULT, "SBSSetInterceptsMenuButtonForever"));
+    $SBSCopyIconImagePNGDataForDisplayIdentifier = reinterpret_cast<NSData *(*)(NSString *)>(dlsym(RTLD_DEFAULT, "SBSCopyIconImagePNGDataForDisplayIdentifier"));
 
     const char *symbol(kCFCoreFoundationVersionNumber >= 800 ? "MGGetBoolAnswer" : "GSSystemHasCapability");
     BOOL (*GSSystemHasCapability)(CFStringRef) = reinterpret_cast<BOOL (*)(CFStringRef)>(dlsym(RTLD_DEFAULT, symbol));
 
     const char *symbol(kCFCoreFoundationVersionNumber >= 800 ? "MGGetBoolAnswer" : "GSSystemHasCapability");
     BOOL (*GSSystemHasCapability)(CFStringRef) = reinterpret_cast<BOOL (*)(CFStringRef)>(dlsym(RTLD_DEFAULT, symbol));