]> git.saurik.com Git - cydia.git/blobdiff - MobileCydia.mm
Split PackageListController partially for CyteKit.
[cydia.git] / MobileCydia.mm
index 0b8f15710248cce70ab89ee5aa53ed4aa1f6f249..3e81b07003e4a675f3c88ba11324e13501b20cf6 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-2014  Jay Freeman (saurik)
+ * Copyright (C) 2008-2015  Jay Freeman (saurik)
 */
 
 /* GNU General Public License, Version 3 {{{ */
 */
 
 /* GNU General Public License, Version 3 {{{ */
 #include <UIKit/UIKit.h>
 #include "iPhonePrivate.h"
 
 #include <UIKit/UIKit.h>
 #include "iPhonePrivate.h"
 
-#include <IOKit/IOKitLib.h>
-
 #include <QuartzCore/CALayer.h>
 
 #include <WebCore/WebCoreThread.h>
 #include <QuartzCore/CALayer.h>
 
 #include <WebCore/WebCoreThread.h>
-#include <WebKit/DOMHTMLIFrameElement.h>
 
 #include <algorithm>
 
 #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>
@@ -83,8 +82,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>
@@ -92,6 +89,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>
@@ -109,23 +107,15 @@ 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 "Menes/Menes.h"
 
-#include "CyteKit/IndirectDelegate.h"
-#include "CyteKit/PerlCompatibleRegEx.hpp"
-#include "CyteKit/TableViewCell.h"
-#include "CyteKit/TabBarController.h"
-#include "CyteKit/WebScriptObject-Cyte.h"
-#include "CyteKit/WebViewController.h"
-#include "CyteKit/WebViewTableViewCell.h"
-#include "CyteKit/stringWithUTF8Bytes.h"
+#include "CyteKit/CyteKit.h"
+#include "CyteKit/RegEx.hpp"
 
 #include "Cydia/MIMEAddress.h"
 #include "Cydia/LoadingViewController.h"
 #include "Cydia/ProgressEvent.h"
 
 #include "Cydia/MIMEAddress.h"
 #include "Cydia/LoadingViewController.h"
 #include "Cydia/ProgressEvent.h"
-
-#include "SDURLCache/SDURLCache.h"
 /* }}} */
 
 /* Profiler {{{ */
 /* }}} */
 
 /* Profiler {{{ */
@@ -198,10 +188,6 @@ void PrintTimes() {
 #define _end }
 /* }}} */
 
 #define _end }
 /* }}} */
 
-// XXX: I hate clang. Apple: please get over your petty hatred of GPL and fix your gcc fork
-#define synchronized(lock) \
-    synchronized(static_cast<NSObject *>(lock))
-
 extern NSString *Cydia_;
 
 #define lprintf(args...) fprintf(stderr, args)
 extern NSString *Cydia_;
 
 #define lprintf(args...) fprintf(stderr, args)
@@ -239,35 +225,6 @@ union SplitHash {
 };
 // }}}
 
 };
 // }}}
 
-static void setreugid(uid_t uid, gid_t gid) {
-    _assert(setreuid(uid, uid) != -1);
-    _assert(setregid(gid, gid) != -1);
-}
-
-static void setreguid(gid_t gid, uid_t uid) {
-    _assert(setregid(gid, gid) != -1);
-    _assert(setreuid(uid, uid) != -1);
-}
-
-struct Root {
-    Root() {
-        _trace();
-        setreugid(0, 0);
-        _assert(pthread_setugid_np(0, 0) != -1);
-        setreguid(501, 501);
-    }
-
-    ~Root() {
-        _trace();
-        setreugid(0, 0);
-        _assert(pthread_setugid_np(KAUTH_UID_NONE, KAUTH_GID_NONE) != -1);
-        setreguid(501, 501);
-    }
-};
-
-#define _root(code) \
-    ({ Root _root; code; })
-
 static NSString *Colon_;
 NSString *Elision_;
 static NSString *Error_;
 static NSString *Colon_;
 NSString *Elision_;
 static NSString *Error_;
@@ -278,6 +235,7 @@ static NSString *Cache_;
     [NSString stringWithFormat:@"%@/%s", Cache_, file]
 
 static void (*$SBSSetInterceptsMenuButtonForever)(bool);
     [NSString stringWithFormat:@"%@/%s", Cache_, file]
 
 static void (*$SBSSetInterceptsMenuButtonForever)(bool);
+static NSData *(*$SBSCopyIconImagePNGDataForDisplayIdentifier)(NSString *);
 
 static CFStringRef (*$MGCopyAnswer)(CFStringRef);
 
 
 static CFStringRef (*$MGCopyAnswer)(CFStringRef);
 
@@ -288,26 +246,6 @@ static NSString *UniqueIdentifier(UIDevice *device = nil) {
         return [(id)$MGCopyAnswer(CFSTR("UniqueDeviceID")) autorelease];
 }
 
         return [(id)$MGCopyAnswer(CFSTR("UniqueDeviceID")) autorelease];
 }
 
-static bool IsReachable(const char *name) {
-    SCNetworkReachabilityFlags flags; {
-        SCNetworkReachabilityRef reachability(SCNetworkReachabilityCreateWithName(kCFAllocatorDefault, name));
-        SCNetworkReachabilityGetFlags(reachability, &flags);
-        CFRelease(reachability);
-    }
-
-    // XXX: this elaborate mess is what Apple is using to determine this? :(
-    // XXX: do we care if the user has to intervene? maybe that's ok?
-    return
-        (flags & kSCNetworkReachabilityFlagsReachable) != 0 && (
-            (flags & kSCNetworkReachabilityFlagsConnectionRequired) == 0 || (
-                (flags & kSCNetworkReachabilityFlagsConnectionOnDemand) != 0 ||
-                (flags & kSCNetworkReachabilityFlagsConnectionOnTraffic) != 0
-            ) && (flags & kSCNetworkReachabilityFlagsInterventionRequired) == 0 ||
-            (flags & kSCNetworkReachabilityFlagsIsWWAN) != 0
-        )
-    ;
-}
-
 static const NSUInteger UIViewAutoresizingFlexibleBoth(UIViewAutoresizingFlexibleWidth | UIViewAutoresizingFlexibleHeight);
 
 static _finline NSString *CydiaURL(NSString *path) {
 static const NSUInteger UIViewAutoresizingFlexibleBoth(UIViewAutoresizingFlexibleWidth | UIViewAutoresizingFlexibleHeight);
 
 static _finline NSString *CydiaURL(NSString *path) {
@@ -321,13 +259,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) {
@@ -339,11 +272,6 @@ static _finline void UpdateExternalStatus(uint64_t newStatus) {
     notify_post("com.saurik.Cydia.status");
 }
 
     notify_post("com.saurik.Cydia.status");
 }
 
-static CGFloat CYStatusBarHeight() {
-    CGSize size([[UIApplication sharedApplication] statusBarFrame].size);
-    return UIInterfaceOrientationIsPortrait([[UIApplication sharedApplication] statusBarOrientation]) ? size.height : size.width;
-}
-
 /* 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;
@@ -351,53 +279,47 @@ static const CFStringCompareFlags LaxCompareFlags_ = kCFCompareNumerically | kCF
 
 /* Insertion Sort {{{ */
 
 
 /* Insertion Sort {{{ */
 
-CFIndex SKBSearch_(const void *element, CFIndex elementSize, const void *list, CFIndex count, CFComparatorFunction comparator, void *context) {
-    const char *ptr = (const char *)list;
-    while (0 < count) {
-        CFIndex half = count / 2;
-        const char *probe = ptr + elementSize * half;
-        CFComparisonResult cr = comparator(element, probe, context);
-    if (0 == cr) return (probe - (const char *)list) / elementSize;
-        ptr = (cr < 0) ? ptr : probe + elementSize;
-        count = (cr < 0) ? half : (half + (count & 1) - 1);
-    }
-    return (ptr - (const char *)list) / elementSize;
-}
-
-CFIndex CFBSearch_(const void *element, CFIndex elementSize, const void *list, CFIndex count, CFComparatorFunction comparator, void *context) {
+template <typename Type_>
+size_t CFBSearch_(const Type_ &element, const void *list, size_t count, CFComparisonResult (*comparator)(Type_, Type_, void *), void *context) {
     const char *ptr = (const char *)list;
     while (0 < count) {
     const char *ptr = (const char *)list;
     while (0 < count) {
-        CFIndex half = count / 2;
-        const char *probe = ptr + elementSize * half;
-        CFComparisonResult cr = comparator(element, probe, context);
-    if (0 == cr) return (probe - (const char *)list) / elementSize;
-        ptr = (cr < 0) ? ptr : probe + elementSize;
+        size_t half = count / 2;
+        const char *probe = ptr + sizeof(Type_) * half;
+        CFComparisonResult cr = comparator(element, * (const Type_ *) probe, context);
+        if (0 == cr) return (probe - (const char *)list) / sizeof(Type_);
+        ptr = (cr < 0) ? ptr : probe + sizeof(Type_);
         count = (cr < 0) ? half : (half + (count & 1) - 1);
     }
         count = (cr < 0) ? half : (half + (count & 1) - 1);
     }
-    return (ptr - (const char *)list) / elementSize;
+    return (ptr - (const char *)list) / sizeof(Type_);
 }
 
 }
 
-void CFArrayInsertionSortValues(CFMutableArrayRef array, CFRange range, CFComparatorFunction comparator, void *context) {
-    if (range.length == 0)
+template <typename Type_>
+void CYArrayInsertionSortValues(Type_ *values, size_t length, CFComparisonResult (*comparator)(Type_, Type_, void *), void *context) {
+    if (length == 0)
         return;
         return;
-    const void **values(new const void *[range.length]);
-    CFArrayGetValues(array, range, values);
 
 #if HistogramInsertionSort > 0
 
 #if HistogramInsertionSort > 0
-    uint32_t total(0), *offsets(new uint32_t[range.length]);
+    uint32_t total(0), *offsets(new uint32_t[length]);
 #endif
 
 #endif
 
-    for (CFIndex index(1); index != range.length; ++index) {
-        const void *value(values[index]);
-        //CFIndex correct(SKBSearch_(&value, sizeof(const void *), values, index, comparator, context));
-        CFIndex correct(index);
+    for (size_t index(1); index != length; ++index) {
+        Type_ value(values[index]);
+#if 0
+        size_t correct(CFBSearch_(value, values, index, comparator, context));
+#else
+        size_t correct(index);
         while (comparator(value, values[correct - 1], context) == kCFCompareLessThan) {
 #if HistogramInsertionSort > 1
             NSLog(@"%@ < %@", value, values[correct - 1]);
 #endif
             if (--correct == 0)
                 break;
         while (comparator(value, values[correct - 1], context) == kCFCompareLessThan) {
 #if HistogramInsertionSort > 1
             NSLog(@"%@ < %@", value, values[correct - 1]);
 #endif
             if (--correct == 0)
                 break;
+            if (index - correct >= 8) {
+                correct = CFBSearch_(value, values, correct, comparator, context);
+                break;
+            }
         }
         }
+#endif
         if (correct != index) {
             size_t offset(index - correct);
 #if HistogramInsertionSort
         if (correct != index) {
             size_t offset(index - correct);
 #if HistogramInsertionSort
@@ -411,11 +333,8 @@ void CFArrayInsertionSortValues(CFMutableArrayRef array, CFRange range, CFCompar
         }
     }
 
         }
     }
 
-    CFArrayReplaceValues(array, range, values, range.length);
-    delete [] values;
-
 #if HistogramInsertionSort > 0
 #if HistogramInsertionSort > 0
-    for (CFIndex index(0); index != range.length; ++index)
+    for (size_t index(0); index != range.length; ++index)
         if (offsets[index] != 0)
             NSLog(@"Insertion Displacement [%u]: %u", index, offsets[index]);
     NSLog(@"Average Insertion Displacement: %f", double(total) / range.length);
         if (offsets[index] != 0)
             NSLog(@"Insertion Displacement [%u]: %u", index, offsets[index]);
     NSLog(@"Average Insertion Displacement: %f", double(total) / range.length);
@@ -425,47 +344,6 @@ void CFArrayInsertionSortValues(CFMutableArrayRef array, CFRange range, CFCompar
 
 /* }}} */
 
 
 /* }}} */
 
-/* Apple Bug Fixes {{{ */
-@implementation UIWebDocumentView (Cydia)
-
-- (void) _setScrollerOffset:(CGPoint)offset {
-    UIScroller *scroller([self _scroller]);
-
-    CGSize size([scroller contentSize]);
-    CGSize bounds([scroller bounds].size);
-
-    CGPoint max;
-    max.x = size.width - bounds.width;
-    max.y = size.height - bounds.height;
-
-    // wtf Apple?!
-    if (max.x < 0)
-        max.x = 0;
-    if (max.y < 0)
-        max.y = 0;
-
-    offset.x = offset.x < 0 ? 0 : offset.x > max.x ? max.x : offset.x;
-    offset.y = offset.y < 0 ? 0 : offset.y > max.y ? max.y : offset.y;
-
-    [scroller setOffset:offset];
-}
-
-@end
-/* }}} */
-
-NSUInteger DOMNodeList$countByEnumeratingWithState$objects$count$(DOMNodeList *self, SEL sel, NSFastEnumerationState *state, id *objects, NSUInteger count) {
-    size_t length([self length] - state->state);
-    if (length <= 0)
-        return 0;
-    else if (length > count)
-        length = count;
-    for (size_t i(0); i != length; ++i)
-        objects[i] = [self item:state->state++];
-    state->itemsPtr = objects;
-    state->mutationsPtr = (unsigned long *) self;
-    return length;
-}
-
 /* Cydia NSString Additions {{{ */
 @interface NSString (Cydia)
 - (NSComparisonResult) compareByPath:(NSString *)other;
 /* Cydia NSString Additions {{{ */
 @interface NSString (Cydia)
 - (NSComparisonResult) compareByPath:(NSString *)other;
@@ -524,6 +402,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));
 }
@@ -580,14 +462,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 {
@@ -601,11 +483,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());
     }
 
@@ -709,7 +591,6 @@ static const NSString *UI_;
 
 static int Finish_;
 static bool RestartSubstrate_;
 
 static int Finish_;
 static bool RestartSubstrate_;
-static bool UpgradeCydia_;
 static NSArray *Finishes_;
 
 #define SpringBoard_ "/System/Library/LaunchDaemons/com.apple.SpringBoard.plist"
 static NSArray *Finishes_;
 
 #define SpringBoard_ "/System/Library/LaunchDaemons/com.apple.SpringBoard.plist"
@@ -743,16 +624,7 @@ static _H<UIFont> Font18_;
 static _H<UIFont> Font18Bold_;
 static _H<UIFont> Font22Bold_;
 
 static _H<UIFont> Font18Bold_;
 static _H<UIFont> Font22Bold_;
 
-static const char *Machine_ = NULL;
-static _H<NSString> System_;
-static NSString *SerialNumber_ = nil;
-static NSString *ChipID_ = nil;
-static NSString *BBSNum_ = nil;
-static _H<NSString> Token_;
 static _H<NSString> UniqueID_;
 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 _H<NSLocale> CollationLocale_;
 static _H<NSArray> CollationThumbs_;
@@ -808,30 +680,20 @@ static CFLocaleRef Locale_;
 static NSArray *Languages_;
 static CGColorSpaceRef space_;
 
 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_;
 
 static time_t now_;
 
-bool IsWildcat_;
-CGFloat ScreenScale_;
-static NSString *Idiom_;
-static _H<NSString> Firmware_;
-static NSString *Major_;
-
 static _H<NSMutableDictionary> SessionData_;
 static _H<NSMutableDictionary> SessionData_;
-static _H<NSObject> HostConfig_;
 static _H<NSMutableSet> BridgedHosts_;
 static _H<NSMutableSet> BridgedHosts_;
-static _H<NSMutableSet> TokenHosts_;
 static _H<NSMutableSet> InsecureHosts_;
 static _H<NSMutableSet> InsecureHosts_;
-static _H<NSMutableSet> PipelinedHosts_;
-static _H<NSMutableSet> CachedURLs_;
 
 static NSString *kCydiaProgressEventTypeError = @"Error";
 static NSString *kCydiaProgressEventTypeInformation = @"Information";
 
 static NSString *kCydiaProgressEventTypeError = @"Error";
 static NSString *kCydiaProgressEventTypeInformation = @"Information";
@@ -840,37 +702,13 @@ static NSString *kCydiaProgressEventTypeWarning = @"Warning";
 /* }}} */
 
 /* Display Helpers {{{ */
 /* }}} */
 
 /* Display Helpers {{{ */
-inline float Interpolate(float begin, float end, float fraction) {
-    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]);
@@ -888,15 +726,15 @@ NSString *Simplify(NSString *title) {
     const char *data = [title UTF8String];
     size_t size = [title lengthOfBytesUsingEncoding:NSUTF8StringEncoding];
 
     const char *data = [title UTF8String];
     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]);
 
@@ -904,52 +742,29 @@ 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"]);
     return hidden == nil || ![hidden boolValue];
 }
 
 bool isSectionVisible(NSString *section) {
     NSDictionary *metadata([Sections_ objectForKey:(section ?: @"")]);
     NSNumber *hidden(metadata == nil ? nil : [metadata objectForKey:@"Hidden"]);
     return hidden == nil || ![hidden boolValue];
 }
 
-static NSObject *CYIOGetValue(const char *path, NSString *property) {
-    io_registry_entry_t entry(IORegistryEntryFromPath(kIOMasterPortDefault, path));
-    if (entry == MACH_PORT_NULL)
-        return nil;
-
-    CFTypeRef value(IORegistryEntryCreateCFProperty(entry, (CFStringRef) property, kCFAllocatorDefault, 0));
-    IOObjectRelease(entry);
-
-    if (value == NULL)
-        return nil;
-    return [(id) value autorelease];
-}
+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];
 
 
-static NSString *CYHex(NSData *data, bool reverse = false) {
-    if (data == nil)
         return nil;
         return nil;
+    }
 
 
-    size_t length([data length]);
-    uint8_t bytes[length];
-    [data getBytes:bytes];
-
-    char string[length * 2 + 1];
-    for (size_t i(0); i != length; ++i)
-        sprintf(string + i * 2, "%.2x", bytes[reverse ? length - i - 1 : i]);
-
-    return [NSString stringWithUTF8String:string];
+    if (![href hasSuffix:@"/"])
+        href = [href stringByAppendingString:@"/"];
+    return href;
 }
 
 @class Cydia;
 }
 
 @class Cydia;
@@ -995,7 +810,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;
@@ -1118,9 +933,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_;
@@ -1134,7 +950,7 @@ typedef std::map< unsigned long, _H<Source> > SourceMap;
     SourceMap sourceMap_;
     _H<NSMutableArray> sourceList_;
 
     SourceMap sourceMap_;
     _H<NSMutableArray> sourceList_;
 
-    CFMutableArrayRef packages_;
+    _H<NSArray> packages_;
 
     _transient NSObject<DatabaseDelegate> *delegate_;
     _transient NSObject<ProgressDelegate> *progress_;
 
     _transient NSObject<DatabaseDelegate> *delegate_;
     _transient NSObject<ProgressDelegate> *progress_;
@@ -1150,6 +966,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;
@@ -1217,7 +1034,10 @@ class SourceStatus :
         }
 
         //printf("Set(%s, %s)\n", fetch ? "true" : "false", uri.c_str());
         }
 
         //printf("Set(%s, %s)\n", fetch ? "true" : "false", uri.c_str());
-        [database_ setFetch:fetch forURI:uri.c_str()];
+
+        auto slash(uri.rfind('/'));
+        if (slash != std::string::npos)
+            [database_ setFetch:fetch forURI:uri.substr(0, slash).c_str()];
     }
 
     _finline void Set(bool fetch, pkgAcquire::Item *item) {
     }
 
     _finline void Set(bool fetch, pkgAcquire::Item *item) {
@@ -1435,14 +1255,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_;
 // }}}
@@ -1525,6 +1345,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_;
@@ -1556,7 +1400,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;
 
@@ -1639,7 +1483,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());
@@ -1658,13 +1502,10 @@ static void PackageImport(const void *key, const void *value, void *context) {
         _profile(Source$setMetaIndex$DescURI)
         for (pkgAcquire::ItemIterator item(acquire.ItemsBegin()); item != acquire.ItemsEnd(); item++) {
             std::string file((*item)->DescURI());
         _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")
+            auto slash(file.rfind('/'));
+            if (slash == std::string::npos)
                 continue;
                 continue;
-            file = file.substr(0, file.length() - 4);
-            files_.insert(file);
-            files_.insert(file + ".gz");
-            files_.insert(file + "Index");
+            files_.insert(file.substr(0, slash));
         }
         _end
 
         }
         _end
 
@@ -1715,7 +1556,7 @@ 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;
     if ((self = [super init]) != nil) {
         era_ = [database era];
         database_ = database;
@@ -1787,14 +1628,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 {
@@ -1810,10 +1647,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 {
@@ -1826,7 +1661,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 {
@@ -2110,7 +1944,7 @@ struct ParsedPackage {
     uint32_t ignored_ : 1;
     uint32_t pooled_ : 1;
 
     uint32_t ignored_ : 1;
     uint32_t pooled_ : 1;
 
-    apr_pool_t *pool_;
+    CYPool *pool_;
 
     uint32_t rank_;
 
 
     uint32_t rank_;
 
@@ -2139,8 +1973,10 @@ 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 *) newPackageWithIterator:(pkgCache::PkgIterator)iterator 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;
@@ -2171,7 +2007,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;
@@ -2357,7 +2192,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];
@@ -2518,15 +2353,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)
@@ -2540,11 +2367,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;
@@ -2555,20 +2382,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()));
 
@@ -2620,7 +2442,7 @@ struct PackageNameOrdering :
 
             char *transform;
             _profile(Package$initWithVersion$Transliterate$apr_palloc)
 
             char *transform;
             _profile(Package$initWithVersion$Transliterate$apr_palloc)
-            transform = static_cast<char *>(apr_palloc(pool_, length));
+            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);
             _end
             _profile(Package$initWithVersion$Transliterate$u_strToUTF8WithSub$transform)
             u_strToUTF8WithSub(transform, length, NULL, CollationString_.data(), CollationString_.size(), 0xfffd, NULL, &code);
@@ -2632,7 +2454,11 @@ struct PackageNameOrdering :
         } while (false); _end
 
         _profile(Package$initWithVersion$Tags)
         } while (false); _end
 
         _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];
 
@@ -2719,7 +2545,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 *) newPackageWithIterator:(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)
@@ -2744,17 +2570,33 @@ struct PackageNameOrdering :
         ];
     _end
 
         ];
     _end
 
-    _profile(Package$packageWithIterator$Autorelease)
-        package = [package autorelease];
-    _end
-
     return package;
 }
 
     return package;
 }
 
+// XXX: just in case a Cydia extension is using this (I bet this is unlikely, though, due to CYPool?)
++ (Package *) packageWithIterator:(pkgCache::PkgIterator)iterator withZone:(NSZone *)zone inPool:(CYPool *)pool database:(Database *)database {
+    return [[self newPackageWithIterator:iterator withZone:zone inPool:pool database:database] autorelease];
+}
+
 - (pkgCache::PkgIterator) iterator {
     return iterator_;
 }
 
 - (pkgCache::PkgIterator) 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)
@@ -2774,7 +2616,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 {
@@ -2844,23 +2689,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 {
@@ -2912,17 +2746,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
 }
 
@@ -3200,13 +3030,15 @@ struct PackageNameOrdering :
 
     NSMutableArray *applications([NSMutableArray arrayWithCapacity:2]);
 
 
     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"]);
@@ -3330,8 +3162,8 @@ struct PackageNameOrdering :
 }
 
 - (void) setIndex:(size_t)index {
 }
 
 - (void) setIndex:(size_t)index {
-    if (metadata_->index_ != index)
-        metadata_->index_ = index;
+    if (metadata_->index_ != index + 1)
+        metadata_->index_ = index + 1;
 }
 
 - (CYString &) cyname {
 }
 
 - (CYString &) cyname {
@@ -3350,6 +3182,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_);
 
@@ -3360,11 +3195,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);
 
@@ -3375,6 +3214,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_);
@@ -3512,25 +3354,26 @@ class CydiaLogCleaner :
 }
 
 - (void) releasePackages {
 }
 
 - (void) releasePackages {
-    CFArrayApplyFunction(packages_, CFRangeMake(0, CFArrayGetCount(packages_)), reinterpret_cast<CFArrayApplierFunction>(&CFRelease), NULL);
-    CFArrayRemoveAllValues(packages_);
+    packages_ = nil;
+}
+
+- (bool) hasPackages {
+    return [packages_ count] != 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]);
@@ -3553,12 +3396,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]);
@@ -3610,8 +3452,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)) {
@@ -3638,8 +3479,12 @@ 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]));
-    return iterator.end() ? nil : [Package packageWithIterator:iterator withZone:NULL inPool:NULL database:self];
+    pkgCache::PkgIterator iterator(cache_->FindPkg([name UTF8String]
+#ifdef __arm64__
+        , "any"
+#endif
+    ));
+    return iterator.end() ? nil : [[Package newPackageWithIterator:iterator withZone:NULL inPool:NULL database:self] autorelease];
 } }
 
 - (id) init {
 } }
 
 - (id) init {
@@ -3651,15 +3496,7 @@ 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)
-            capacity = 16384;
-        else
-            capacity += 1024;
 
 
-        packages_ = CFArrayCreateMutable(kCFAllocatorDefault, capacity, NULL);
         sourceList_ = [NSMutableArray arrayWithCapacity:16];
 
         int fds[2];
         sourceList_ = [NSMutableArray arrayWithCapacity:16];
 
         int fds[2];
@@ -3728,7 +3565,7 @@ class CydiaLogCleaner :
 }
 
 - (NSArray *) packages {
 }
 
 - (NSArray *) packages {
-    return (NSArray *) packages_;
+    return packages_;
 }
 
 - (NSArray *) sources {
 }
 
 - (NSArray *) sources {
@@ -3760,7 +3597,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;
 
@@ -3774,6 +3611,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_;
@@ -3801,7 +3663,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);
@@ -3817,28 +3680,27 @@ class CydiaLogCleaner :
 
     list_ = new pkgSourceList();
     _profile(reloadDataWithInvocation$ReadMainList)
 
     list_ = new pkgSourceList();
     _profile(reloadDataWithInvocation$ReadMainList)
-    if ([self popErrorWithTitle:title forOperation:list_->ReadMainList()])
+    if ([self popErrorWithTitle:title forReadList:*list_])
         return;
     _end
 
     _profile(reloadDataWithInvocation$Source$initWithMetaIndex)
     for (pkgSourceList::const_iterator source = list_->begin(); source != list_->end(); ++source) {
         return;
     _end
 
     _profile(reloadDataWithInvocation$Source$initWithMetaIndex)
     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];
     }
     _end
 
         [sourceList_ addObject:object];
     }
     _end
 
-    _root(_system->Lock());
-
     _trace();
     OpProgress progress;
     bool opened;
   open:
     _trace();
     OpProgress progress;
     bool opened;
   open:
+    delock_ = GetStatusDate();
     _profile(reloadDataWithInvocation$pkgCacheFile)
         opened = cache_.Open(progress, false);
     _end
     if (!opened) {
     _profile(reloadDataWithInvocation$pkgCacheFile)
         opened = cache_.Open(progress, false);
     _end
     if (!opened) {
-        // XXX: what if there are errors, but Open() == true? this should be merged with popError:
+        // 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));
@@ -3865,9 +3727,9 @@ class CydiaLogCleaner :
             }
         }
 
             }
         }
 
-        _system->UnLock();
         return;
         return;
-    }
+    } else if ([self popErrorWithTitle:title forOperation:true])
+        return;
     _trace();
 
     unlink("/tmp/cydia.chk");
     _trace();
 
     unlink("/tmp/cydia.chk");
@@ -3920,40 +3782,89 @@ class CydiaLogCleaner :
     }
 
     {
     }
 
     {
-        /*std::vector<Package *> packages;
-        packages.reserve(std::max(10000U, [packages_ count] + 1000));
-        packages_ = nil;*/
+        size_t capacity(MetaFile_->active_);
+        if (capacity == 0)
+            capacity = 128*1024;
+        else
+            capacity += 1024;
 
 
+        std::vector<Package *> packages;
+        packages.reserve(capacity);
+        size_t lost(0);
+
+        size_t last(0);
         _profile(reloadDataWithInvocation$packageWithIterator)
         for (pkgCache::PkgIterator iterator = cache_->PkgBegin(); !iterator.end(); ++iterator)
         _profile(reloadDataWithInvocation$packageWithIterator)
         for (pkgCache::PkgIterator iterator = cache_->PkgBegin(); !iterator.end(); ++iterator)
-            if (Package *package = [Package packageWithIterator:iterator withZone:zone_ inPool:pool_ database:self])
-                //packages.push_back(package);
-                CFArrayAppendValue(packages_, CFRetain(package));
+            if (Package *package = [Package newPackageWithIterator:iterator withZone:zone_ inPool:&pool_ database:self]) {
+                if (unsigned index = package.metadata->index_) {
+                    --index;
+                    if (packages.size() == index) {
+                        packages.push_back(package);
+                    } else if (packages.size() <= index) {
+                        packages.resize(index + 1, nil);
+                        packages[index] = package;
+                        continue;
+                    } else {
+                        std::swap(package, packages[index]);
+                        if (package != nil) {
+                            if (package.metadata->index_ == index + 1)
+                                ++lost;
+                            goto lost;
+                        }
+                        if (last != index)
+                            continue;
+                    }
+                } else {
+                    ++lost;
+                    lost: if (last == packages.size())
+                        packages.push_back(package);
+                    else
+                        packages[last] = package;
+                    ++last;
+                }
+
+                for (; last != packages.size(); ++last)
+                    if (packages[last] == nil)
+                        break;
+            }
         _end
 
         _end
 
+        for (size_t next(last + 1); last != packages.size(); ++last, ++next) {
+            while (true) {
+                if (next == packages.size())
+                    goto done;
+                if (packages[next] != nil)
+                    break;
+                ++next;
+            }
 
 
-        /*if (packages.empty())
-            packages_ = [[NSArray alloc] init];
-        else
-            packages_ = [[NSArray alloc] initWithObjects:&packages.front() count:packages.size()];
-        _trace();*/
+            std::swap(packages[last], packages[next]);
+        } done:;
 
 
-        _profile(reloadDataWithInvocation$radix$8)
-        [(NSMutableArray *) packages_ radixSortUsingFunction:reinterpret_cast<MenesRadixSortFunction>(&PackagePrefixRadix) withContext:reinterpret_cast<void *>(8)];
-        _end
+        packages.resize(last);
 
 
-        _profile(reloadDataWithInvocation$radix$4)
-        [(NSMutableArray *) packages_ radixSortUsingFunction:reinterpret_cast<MenesRadixSortFunction>(&PackagePrefixRadix) withContext:reinterpret_cast<void *>(4)];
-        _end
+        if (lost > 128) {
+            NSLog(@"lost = %zu", lost);
 
 
-        _profile(reloadDataWithInvocation$radix$0)
-        [(NSMutableArray *) packages_ radixSortUsingFunction:reinterpret_cast<MenesRadixSortFunction>(&PackagePrefixRadix) withContext:reinterpret_cast<void *>(0)];
-        _end
+            _profile(reloadDataWithInvocation$radix$8)
+            CYRadixSortUsingFunction(packages.data(), packages.size(), reinterpret_cast<MenesRadixSortFunction>(&PackagePrefixRadix), reinterpret_cast<void *>(8));
+            _end
+
+            _profile(reloadDataWithInvocation$radix$4)
+            CYRadixSortUsingFunction(packages.data(), packages.size(), reinterpret_cast<MenesRadixSortFunction>(&PackagePrefixRadix), reinterpret_cast<void *>(4));
+            _end
+
+            _profile(reloadDataWithInvocation$radix$0)
+            CYRadixSortUsingFunction(packages.data(), packages.size(), reinterpret_cast<MenesRadixSortFunction>(&PackagePrefixRadix), reinterpret_cast<void *>(0));
+            _end
+        }
 
         _profile(reloadDataWithInvocation$insertion)
 
         _profile(reloadDataWithInvocation$insertion)
-        CFArrayInsertionSortValues(packages_, CFRangeMake(0, CFArrayGetCount(packages_)), reinterpret_cast<CFComparatorFunction>(&PackageNameCompare), NULL);
+        CYArrayInsertionSortValues(packages.data(), packages.size(), &PackageNameCompare, NULL);
         _end
 
         _end
 
+        packages_ = [[[NSArray alloc] initWithObjects:packages.data() count:packages.size()] autorelease];
+
         /*_profile(reloadDataWithInvocation$CFQSortArray)
         CFQSortArray(&packages.front(), packages.size(), sizeof(packages.front()), reinterpret_cast<CFComparatorFunction>(&PackageNameCompare_), NULL);
         _end*/
         /*_profile(reloadDataWithInvocation$CFQSortArray)
         CFQSortArray(&packages.front(), packages.size(), sizeof(packages.front()), reinterpret_cast<CFComparatorFunction>(&PackageNameCompare_), NULL);
         _end*/
@@ -3970,11 +3881,12 @@ class CydiaLogCleaner :
         [packages_ sortUsingFunction:reinterpret_cast<NSComparisonResult (*)(id, id, void *)>(&PackageNameCompare) context:NULL];
         _end*/
 
         [packages_ sortUsingFunction:reinterpret_cast<NSComparisonResult (*)(id, id, void *)>(&PackageNameCompare) context:NULL];
         _end*/
 
-
-        size_t count(CFArrayGetCount(packages_));
-        MetaFile_->active_ = count;
-        for (size_t index(0); index != count; ++index)
-            [(Package *) CFArrayGetValueAtIndex(packages_, index) setIndex:index];
+        MetaFile_->active_ = packages.size();
+        for (size_t index(0), count(packages.size()); index != count; ++index) {
+            auto package(packages[index]);
+            [package setIndex:index];
+            [package release];
+        }
     }
 } }
 
     }
 } }
 
@@ -3991,9 +3903,9 @@ 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();
     _trace();
-    _root(system([dpkg UTF8String]));
+    system([dpkg UTF8String]);
     _trace();
 }
 
     _trace();
 }
 
@@ -4035,7 +3947,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_));
@@ -4053,7 +3965,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()]];
@@ -4094,8 +4006,25 @@ class CydiaLogCleaner :
     if (substrate)
         RestartSubstrate_ = true;
 
     if (substrate)
         RestartSubstrate_ = true;
 
-    _system->UnLock();
-    pkgPackageManager::OrderResult result(_root(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;
 
@@ -4111,7 +4040,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()]];
@@ -4121,6 +4050,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_)])
@@ -4136,7 +4069,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;
@@ -4151,8 +4084,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];
@@ -4220,76 +4155,16 @@ class CydiaLogCleaner :
 @end
 /* }}} */
 
 @end
 /* }}} */
 
-static _H<NSMutableSet> Diversions_;
-
-@interface Diversion : NSObject {
-    Pcre pattern_;
-    _H<NSString> key_;
-    _H<NSString> format_;
-}
-
-@end
-
-@implementation Diversion
-
-- (id) initWithFrom:(NSString *)from to:(NSString *)to {
-    if ((self = [super init]) != nil) {
-        pattern_ = [from UTF8String];
-        key_ = from;
-        format_ = to;
-    } return self;
-}
-
-- (NSString *) divert:(NSString *)url {
-    return !pattern_(url) ? nil : pattern_->*format_;
-}
-
-+ (NSURL *) divertURL:(NSURL *)url {
-  divert:
-    NSString *href([url absoluteString]);
-
-    for (Diversion *diversion in (id) Diversions_)
-        if (NSString *diverted = [diversion divert:href]) {
-#if !ForRelease
-            NSLog(@"div: %@", diverted);
-#endif
-            url = [NSURL URLWithString:diverted];
-            goto divert;
-        }
-
-    return url;
-}
-
-- (NSString *) key {
-    return key_;
-}
-
-- (NSUInteger) hash {
-    return [key_ hash];
-}
-
-- (BOOL) isEqual:(Diversion *)object {
-    return self == object || [self class] == [object class] && [key_ isEqual:[object key]];
-}
-
-@end
-
-@interface CydiaObject : NSObject {
-    _H<CyteWebViewController> indirect_;
+@interface CydiaObject : CyteObject {
     _transient id delegate_;
 }
 
     _transient id delegate_;
 }
 
-- (id) initWithDelegate:(IndirectDelegate *)indirect;
-
 @end
 
 @end
 
-@class CydiaObject;
-
 @interface CydiaWebViewController : CyteWebViewController {
     _H<CydiaObject> cydia_;
 }
 
 @interface CydiaWebViewController : CyteWebViewController {
     _H<CydiaObject> cydia_;
 }
 
-+ (void) addDiversion:(Diversion *)diversion;
 + (NSURLRequest *) requestWithHeaders:(NSURLRequest *)request;
 + (void) didClearWindowObject:(WebScriptObject *)window forFrame:(WebFrame *)frame withCydia:(CydiaObject *)cydia;
 - (void) setDelegate:(id)delegate;
 + (NSURLRequest *) requestWithHeaders:(NSURLRequest *)request;
 + (void) didClearWindowObject:(WebScriptObject *)window forFrame:(WebFrame *)frame withCydia:(CydiaObject *)cydia;
 - (void) setDelegate:(id)delegate;
@@ -4299,74 +4174,54 @@ static _H<NSMutableSet> Diversions_;
 /* Web Scripting {{{ */
 @implementation CydiaObject
 
 /* Web Scripting {{{ */
 @implementation CydiaObject
 
-- (id) initWithDelegate:(IndirectDelegate *)indirect {
-    if ((self = [super init]) != nil) {
-        indirect_ = (CyteWebViewController *) indirect;
-    } return self;
-}
-
 - (void) setDelegate:(id)delegate {
     delegate_ = delegate;
 }
 
 - (void) setDelegate:(id)delegate {
     delegate_ = delegate;
 }
 
-+ (NSArray *) _attributeKeys {
-    return [NSArray arrayWithObjects:
-        @"bbsnum",
-        @"build",
-        @"coreFoundationVersionNumber",
+- (NSArray *) attributeKeys {
+    return [[NSArray arrayWithObjects:
+        @"cells",
         @"device",
         @"device",
-        @"ecid",
-        @"firmware",
-        @"hostname",
-        @"idiom",
         @"mcc",
         @"mnc",
         @"mcc",
         @"mnc",
-        @"model",
         @"operator",
         @"role",
         @"operator",
         @"role",
-        @"serial",
-        @"token",
         @"version",
         @"version",
-    nil];
-}
-
-- (NSArray *) attributeKeys {
-    return [[self class] _attributeKeys];
-}
-
-+ (BOOL) isKeyExcludedFromWebScript:(const char *)name {
-    return ![[self _attributeKeys] containsObject:[NSString stringWithUTF8String:name]] && [super isKeyExcludedFromWebScript:name];
+    nil] arrayByAddingObjectsFromArray:[super attributeKeys]];
 }
 
 - (NSString *) version {
     return Cydia_;
 }
 
 }
 
 - (NSString *) version {
     return Cydia_;
 }
 
-- (NSString *) build {
-    return System_;
-}
-
-- (NSString *) coreFoundationVersionNumber {
-    return [NSString stringWithFormat:@"%.2f", kCFCoreFoundationVersionNumber];
-}
-
 - (NSString *) device {
     return UniqueIdentifier();
 }
 
 - (NSString *) device {
     return UniqueIdentifier();
 }
 
-- (NSString *) firmware {
-    return [[UIDevice currentDevice] systemVersion];
-}
+- (NSArray *) cells {
+    auto *$_CTServerConnectionCreate(reinterpret_cast<id (*)(void *, void *, void *)>(dlsym(RTLD_DEFAULT, "_CTServerConnectionCreate")));
+    if ($_CTServerConnectionCreate == NULL)
+        return nil;
 
 
-- (NSString *) hostname {
-    return [[UIDevice currentDevice] name];
-}
+    struct CTResult { int flag; int error; };
+    auto *$_CTServerConnectionCellMonitorCopyCellInfo(reinterpret_cast<CTResult (*)(CFTypeRef, void *, CFArrayRef *)>(dlsym(RTLD_DEFAULT, "_CTServerConnectionCellMonitorCopyCellInfo")));
+    if ($_CTServerConnectionCellMonitorCopyCellInfo == NULL)
+        return nil;
 
 
-- (NSString *) idiom {
-    return (id) Idiom_ ?: [NSNull null];
-}
+    _H<const void> connection($_CTServerConnectionCreate(NULL, NULL, NULL), true);
+    if (connection == nil)
+        return nil;
 
 
-- (NSString *) mcc {
+    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;
     if (CFStringRef (*$CTSIMSupportCopyMobileSubscriberCountryCode)(CFAllocatorRef) = reinterpret_cast<CFStringRef (*)(CFAllocatorRef)>(dlsym(RTLD_DEFAULT, "CTSIMSupportCopyMobileSubscriberCountryCode")))
         return [(NSString *) (*$CTSIMSupportCopyMobileSubscriberCountryCode)(kCFAllocatorDefault) autorelease];
     return nil;
@@ -4384,68 +4239,32 @@ static _H<NSMutableSet> Diversions_;
     return nil;
 }
 
     return nil;
 }
 
-- (NSString *) bbsnum {
-    return (id) BBSNum_ ?: [NSNull null];
-}
-
-- (NSString *) ecid {
-    return (id) ChipID_ ?: [NSNull null];
-}
-
-- (NSString *) serial {
-    return SerialNumber_;
-}
-
 - (NSString *) role {
     return (id) [NSNull null];
 }
 
 - (NSString *) role {
     return (id) [NSNull null];
 }
 
-- (NSString *) model {
-    return [NSString stringWithUTF8String:Machine_];
-}
-
-- (NSString *) token {
-    return (id) Token_ ?: [NSNull null];
-}
-
 + (NSString *) webScriptNameForSelector:(SEL)selector {
     if (false);
     else if (selector == @selector(addBridgedHost:))
         return @"addBridgedHost";
     else if (selector == @selector(addInsecureHost:))
         return @"addInsecureHost";
 + (NSString *) webScriptNameForSelector:(SEL)selector {
     if (false);
     else if (selector == @selector(addBridgedHost:))
         return @"addBridgedHost";
     else if (selector == @selector(addInsecureHost:))
         return @"addInsecureHost";
-    else if (selector == @selector(addInternalRedirect::))
-        return @"addInternalRedirect";
-    else if (selector == @selector(addPipelinedHost:scheme:))
-        return @"addPipelinedHost";
     else if (selector == @selector(addSource:::))
         return @"addSource";
     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(addTrivialSource:))
         return @"addTrivialSource";
-    else if (selector == @selector(close))
-        return @"close";
     else if (selector == @selector(du:))
         return @"du";
     else if (selector == @selector(du:))
         return @"du";
-    else if (selector == @selector(stringWithFormat:arguments:))
-        return @"format";
     else if (selector == @selector(getAllSources))
         return @"getAllSources";
     else if (selector == @selector(getApplicationInfo:value:))
         return @"getApplicationInfoValue";
     else if (selector == @selector(getAllSources))
         return @"getAllSources";
     else if (selector == @selector(getApplicationInfo:value:))
         return @"getApplicationInfoValue";
-    else if (selector == @selector(getKernelNumber:))
-        return @"getKernelNumber";
-    else if (selector == @selector(getKernelString:))
-        return @"getKernelString";
+    else if (selector == @selector(getDisplayIdentifiers))
+        return @"getDisplayIdentifiers";
+    else if (selector == @selector(getLocalizedNameForDisplayIdentifier:))
+        return @"getLocalizedNameForDisplayIdentifier";
     else if (selector == @selector(getInstalledPackages))
         return @"getInstalledPackages";
     else if (selector == @selector(getInstalledPackages))
         return @"getInstalledPackages";
-    else if (selector == @selector(getIORegistryEntry::))
-        return @"getIORegistryEntry";
-    else if (selector == @selector(getLocaleIdentifier))
-        return @"getLocaleIdentifier";
-    else if (selector == @selector(getPreferredLanguages))
-        return @"getPreferredLanguages";
     else if (selector == @selector(getPackageById:))
         return @"getPackageById";
     else if (selector == @selector(getMetadataKeys))
     else if (selector == @selector(getPackageById:))
         return @"getPackageById";
     else if (selector == @selector(getMetadataKeys))
@@ -4456,18 +4275,8 @@ static _H<NSMutableSet> Diversions_;
         return @"getSessionValue";
     else if (selector == @selector(installPackages:))
         return @"installPackages";
         return @"getSessionValue";
     else if (selector == @selector(installPackages:))
         return @"installPackages";
-    else if (selector == @selector(isReachable:))
-        return @"isReachable";
-    else if (selector == @selector(localizedStringForKey:value:table:))
-        return @"localize";
-    else if (selector == @selector(popViewController:))
-        return @"popViewController";
     else if (selector == @selector(refreshSources))
         return @"refreshSources";
     else if (selector == @selector(refreshSources))
         return @"refreshSources";
-    else if (selector == @selector(registerFrame:))
-        return @"registerFrame";
-    else if (selector == @selector(removeButton))
-        return @"removeButton";
     else if (selector == @selector(saveConfig))
         return @"saveConfig";
     else if (selector == @selector(setMetadataValue::))
     else if (selector == @selector(saveConfig))
         return @"saveConfig";
     else if (selector == @selector(setMetadataValue::))
@@ -4476,42 +4285,8 @@ static _H<NSMutableSet> Diversions_;
         return @"setSessionValue";
     else if (selector == @selector(substitutePackageNames:))
         return @"substitutePackageNames";
         return @"setSessionValue";
     else if (selector == @selector(substitutePackageNames:))
         return @"substitutePackageNames";
-    else if (selector == @selector(scrollToBottom:))
-        return @"scrollToBottom";
-    else if (selector == @selector(setAllowsNavigationAction:))
-        return @"setAllowsNavigationAction";
-    else if (selector == @selector(setBadgeValue:))
-        return @"setBadgeValue";
-    else if (selector == @selector(setButtonImage:withStyle:toFunction:))
-        return @"setButtonImage";
-    else if (selector == @selector(setButtonTitle:withStyle:toFunction:))
-        return @"setButtonTitle";
-    else if (selector == @selector(setHidesBackButton:))
-        return @"setHidesBackButton";
-    else if (selector == @selector(setHidesNavigationBar:))
-        return @"setHidesNavigationBar";
-    else if (selector == @selector(setNavigationBarStyle:))
-        return @"setNavigationBarStyle";
-    else if (selector == @selector(setNavigationBarTintRed:green:blue:alpha:))
-        return @"setNavigationBarTintColor";
-    else if (selector == @selector(setPasteboardString:))
-        return @"setPasteboardString";
-    else if (selector == @selector(setPasteboardURL:))
-        return @"setPasteboardURL";
-    else if (selector == @selector(setScrollAlwaysBounceVertical:))
-        return @"setScrollAlwaysBounceVertical";
-    else if (selector == @selector(setScrollIndicatorStyle:))
-        return @"setScrollIndicatorStyle";
     else if (selector == @selector(setToken:))
         return @"setToken";
     else if (selector == @selector(setToken:))
         return @"setToken";
-    else if (selector == @selector(setViewportWidth:))
-        return @"setViewportWidth";
-    else if (selector == @selector(statfs:))
-        return @"statfs";
-    else if (selector == @selector(supports:))
-        return @"supports";
-    else if (selector == @selector(unload))
-        return @"unload";
     else
         return nil;
 }
     else
         return nil;
 }
@@ -4520,26 +4295,6 @@ static _H<NSMutableSet> Diversions_;
     return [self webScriptNameForSelector:selector] == nil;
 }
 
     return [self webScriptNameForSelector:selector] == nil;
 }
 
-- (BOOL) supports:(NSString *)feature {
-    return [feature isEqualToString:@"window.open"];
-}
-
-- (void) unload {
-    [delegate_ performSelectorOnMainThread:@selector(unloadData) withObject:nil waitUntilDone:NO];
-}
-
-- (void) setScrollAlwaysBounceVertical:(NSNumber *)value {
-    [indirect_ performSelectorOnMainThread:@selector(setScrollAlwaysBounceVerticalNumber:) withObject:value waitUntilDone:NO];
-}
-
-- (void) setScrollIndicatorStyle:(NSString *)style {
-    [indirect_ performSelectorOnMainThread:@selector(setScrollIndicatorStyleWithName:) withObject:style waitUntilDone:NO];
-}
-
-- (void) addInternalRedirect:(NSString *)from :(NSString *)to {
-    [CydiaWebViewController performSelectorOnMainThread:@selector(addDiversion:) withObject:[[[Diversion alloc] initWithFrom:from to:to] autorelease] waitUntilDone:NO];
-}
-
 - (NSDictionary *) getApplicationInfo:(NSString *)display value:(NSString *)key {
     char path[1024];
     if (SBBundlePathForDisplayIdentifier(SBSSpringBoardServerPort(), [display UTF8String], path) != 0)
 - (NSDictionary *) getApplicationInfo:(NSString *)display value:(NSString *)key {
     char path[1024];
     if (SBBundlePathForDisplayIdentifier(SBSSpringBoardServerPort(), [display UTF8String], path) != 0)
@@ -4550,6 +4305,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]);
 
@@ -4567,43 +4330,11 @@ static _H<NSMutableSet> Diversions_;
     return [NSNumber numberWithInt:value];
 }
 
     return [NSNumber numberWithInt:value];
 }
 
-- (NSString *) getKernelString:(NSString *)name {
-    const char *string([name UTF8String]);
-
-    size_t size;
-    if (sysctlbyname(string, NULL, &size, NULL, 0) == -1)
-        return (id) [NSNull null];
-
-    char value[size + 1];
-    if (sysctlbyname(string, value, &size, NULL, 0) == -1)
-        return (id) [NSNull null];
-
-    // XXX: just in case you request something ludicrous
-    value[size] = '\0';
-
-    return [NSString stringWithCString:value];
-}
-
-- (NSObject *) getIORegistryEntry:(NSString *)path :(NSString *)entry {
-    NSObject *value(CYIOGetValue([path UTF8String], entry));
-
-    if (value != nil)
-        if ([value isKindOfClass:[NSData class]])
-            value = CYHex((NSData *) value);
-
-    return value;
-}
-
 - (NSArray *) getMetadataKeys {
 @synchronized (Values_) {
     return [Values_ allKeys];
 } }
 
 - (NSArray *) getMetadataKeys {
 @synchronized (Values_) {
     return [Values_ allKeys];
 } }
 
-- (void) registerFrame:(DOMHTMLIFrameElement *)iframe {
-    WebFrame *frame([iframe contentFrame]);
-    [indirect_ registerFrame:frame];
-}
-
 - (id) getMetadataValue:(NSString *)key {
 @synchronized (Values_) {
     return [Values_ objectForKey:key];
 - (id) getMetadataValue:(NSString *)key {
 @synchronized (Values_) {
     return [Values_ objectForKey:key];
@@ -4615,8 +4346,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 {
@@ -4633,34 +4362,15 @@ static _H<NSMutableSet> Diversions_;
 } }
 
 - (void) addBridgedHost:(NSString *)host {
 } }
 
 - (void) addBridgedHost:(NSString *)host {
-@synchronized (HostConfig_) {
+@synchronized (BridgedHosts_) {
     [BridgedHosts_ addObject:host];
 } }
 
 - (void) addInsecureHost:(NSString *)host {
     [BridgedHosts_ addObject:host];
 } }
 
 - (void) addInsecureHost:(NSString *)host {
-@synchronized (HostConfig_) {
+@synchronized (InsecureHosts_) {
     [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])
-        host = [NSString stringWithFormat:@"%@:%@", [scheme lowercaseString], host];
-
-    [PipelinedHosts_ addObject:host];
-} }
-
-- (void) popViewController:(NSNumber *)value {
-    if (value == (id) [WebUndefined undefined])
-        value = [NSNumber numberWithBool:YES];
-    [indirect_ performSelectorOnMainThread:@selector(popViewControllerWithNumber:) withObject:value waitUntilDone:NO];
-}
-
 - (void) addSource:(NSString *)href :(NSString *)distribution :(WebScriptObject *)sections {
     NSMutableArray *array([NSMutableArray arrayWithCapacity:[sections count]]);
 
 - (void) addSource:(NSString *)href :(NSString *)distribution :(WebScriptObject *)sections {
     NSMutableArray *array([NSMutableArray arrayWithCapacity:[sections count]]);
 
@@ -4675,8 +4385,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 {
@@ -4710,171 +4424,50 @@ static _H<NSMutableSet> Diversions_;
         return (Package *) [NSNull null];
 }
 
         return (Package *) [NSNull null];
 }
 
-- (NSString *) getLocaleIdentifier {
-    return Locale_ == NULL ? (NSString *) [NSNull null] : (NSString *) CFLocaleGetIdentifier(Locale_);
-}
-
-- (NSArray *) getPreferredLanguages {
-    return Languages_;
-}
-
-- (NSArray *) statfs:(NSString *)path {
-    struct statfs stat;
-
-    if (path == nil || statfs([path UTF8String], &stat) == -1)
-        return nil;
-
-    return [NSArray arrayWithObjects:
-        [NSNumber numberWithUnsignedLong:stat.f_bsize],
-        [NSNumber numberWithUnsignedLong:stat.f_blocks],
-        [NSNumber numberWithUnsignedLong:stat.f_bfree],
-    nil];
-}
-
 - (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 */
-        _root(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;
 }
 
-- (void) close {
-    [indirect_ performSelectorOnMainThread:@selector(close) withObject:nil waitUntilDone:NO];
-}
-
-- (NSNumber *) isReachable:(NSString *)name {
-    return [NSNumber numberWithBool:IsReachable([name UTF8String])];
-}
-
 - (void) installPackages:(NSArray *)packages {
     [delegate_ performSelectorOnMainThread:@selector(installPackages:) withObject:packages waitUntilDone:NO];
 }
 
 - (NSString *) substitutePackageNames:(NSString *)message {
 - (void) installPackages:(NSArray *)packages {
     [delegate_ performSelectorOnMainThread:@selector(installPackages:) withObject:packages waitUntilDone:NO];
 }
 
 - (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]];
     }
 
     return [words componentsJoinedByString:@" "];
 }
 
             [words replaceObjectAtIndex:i withObject:[package name]];
     }
 
     return [words componentsJoinedByString:@" "];
 }
 
-- (void) removeButton {
-    [indirect_ removeButton];
-}
-
-- (void) setButtonImage:(NSString *)button withStyle:(NSString *)style toFunction:(id)function {
-    [indirect_ setButtonImage:button withStyle:style toFunction:function];
-}
-
-- (void) setButtonTitle:(NSString *)button withStyle:(NSString *)style toFunction:(id)function {
-    [indirect_ setButtonTitle:button withStyle:style toFunction:function];
-}
-
-- (void) setBadgeValue:(id)value {
-    [indirect_ performSelectorOnMainThread:@selector(setBadgeValue:) withObject:value waitUntilDone:NO];
-}
-
-- (void) setAllowsNavigationAction:(NSString *)value {
-    [indirect_ performSelectorOnMainThread:@selector(setAllowsNavigationActionByNumber:) withObject:value waitUntilDone:NO];
-}
-
-- (void) setHidesBackButton:(NSString *)value {
-    [indirect_ performSelectorOnMainThread:@selector(setHidesBackButtonByNumber:) withObject:value waitUntilDone:NO];
-}
-
-- (void) setHidesNavigationBar:(NSString *)value {
-    [indirect_ performSelectorOnMainThread:@selector(setHidesNavigationBarByNumber:) withObject:value waitUntilDone:NO];
-}
-
-- (void) setNavigationBarStyle:(NSString *)value {
-    [indirect_ performSelectorOnMainThread:@selector(setNavigationBarStyle:) withObject:value waitUntilDone:NO];
-}
-
-- (void) setNavigationBarTintRed:(NSNumber *)red green:(NSNumber *)green blue:(NSNumber *)blue alpha:(NSNumber *)alpha {
-    float opacity(alpha == (id) [WebUndefined undefined] ? 1 : [alpha floatValue]);
-    UIColor *color([UIColor colorWithRed:[red floatValue] green:[green floatValue] blue:[blue floatValue] alpha:opacity]);
-    [indirect_ performSelectorOnMainThread:@selector(setNavigationBarTintColor:) withObject:color waitUntilDone:NO];
-}
-
-- (void) setPasteboardString:(NSString *)value {
-    [[objc_getClass("UIPasteboard") generalPasteboard] setString:value];
-}
-
-- (void) setPasteboardURL:(NSString *)value {
-    [[objc_getClass("UIPasteboard") generalPasteboard] setURL:[NSURL URLWithString:value]];
-}
-
-- (void) _setToken:(NSString *)token {
-    Token_ = token;
-
-    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];
-}
-
-- (void) scrollToBottom:(NSNumber *)animated {
-    [indirect_ performSelectorOnMainThread:@selector(scrollToBottomAnimated:) withObject:animated waitUntilDone:NO];
-}
-
-- (void) setViewportWidth:(float)width {
-    [indirect_ setViewportWidthOnMainThread:width];
-}
-
-- (NSString *) stringWithFormat:(NSString *)format arguments:(WebScriptObject *)arguments {
-    //NSLog(@"SWF:\"%@\" A:%@", format, [arguments description]);
-    unsigned count([arguments count]);
-    id values[count];
-    for (unsigned i(0); i != count; ++i)
-        values[i] = [arguments objectAtIndex:i];
-    return [[[NSString alloc] initWithFormat:format arguments:reinterpret_cast<va_list>(values)] autorelease];
-}
-
-- (NSString *) localizedStringForKey:(NSString *)key value:(NSString *)value table:(NSString *)table {
-    if (reinterpret_cast<id>(value) == [WebUndefined undefined])
-        value = nil;
-    if (reinterpret_cast<id>(table) == [WebUndefined undefined])
-        table = nil;
-    return [[NSBundle mainBundle] localizedStringForKey:key value:value table:table];
+    // XXX: the website expects this :/
 }
 
 @end
 }
 
 @end
@@ -4889,7 +4482,7 @@ static _H<NSMutableSet> Diversions_;
     if ([[[self scheme] lowercaseString] isEqualToString:@"https"])
         return true;
 
     if ([[[self scheme] lowercaseString] isEqualToString:@"https"])
         return true;
 
-    @synchronized (HostConfig_) {
+    @synchronized (InsecureHosts_) {
         if ([InsecureHosts_ containsObject:[self host]])
             return true;
     }
         if ([InsecureHosts_ containsObject:[self host]])
             return true;
     }
@@ -4903,17 +4496,10 @@ static _H<NSMutableSet> Diversions_;
 @implementation CydiaWebViewController
 
 - (NSURL *) navigationURL {
 @implementation CydiaWebViewController
 
 - (NSURL *) navigationURL {
-    return request_ == nil ? nil : [NSURL URLWithString:[NSString stringWithFormat:@"cydia://url/%@", [[request_ URL] absoluteString]]];
-}
-
-+ (void) _initialize {
-    [super _initialize];
-
-    Diversions_ = [NSMutableSet setWithCapacity:0];
-}
-
-+ (void) addDiversion:(Diversion *)diversion {
-    [Diversions_ addObject:diversion];
+    if (NSURLRequest *request = self.request)
+        return [NSURL URLWithString:[NSString stringWithFormat:@"cydia://url/%@", [[request URL] absoluteString]]];
+    else
+        return nil;
 }
 
 - (void) webView:(WebView *)view didClearWindowObject:(WebScriptObject *)window forFrame:(WebFrame *)frame {
 }
 
 - (void) webView:(WebView *)view didClearWindowObject:(WebScriptObject *)window forFrame:(WebFrame *)frame {
@@ -4929,7 +4515,7 @@ static _H<NSMutableSet> Diversions_;
 
     bool bridged(false);
 
 
     bool bridged(false);
 
-    @synchronized (HostConfig_) {
+    @synchronized (BridgedHosts_) {
         if ([scheme isEqualToString:@"file"])
             bridged = true;
         else if ([scheme isEqualToString:@"https"])
         if ([scheme isEqualToString:@"file"])
             bridged = true;
         else if ([scheme isEqualToString:@"https"])
@@ -4948,10 +4534,6 @@ static _H<NSMutableSet> Diversions_;
     [controller addAttachmentData:[NSData dataWithContentsOfFile:@"/tmp/dpkgl.log"] mimeType:@"text/plain" fileName:@"dpkgl.log"];
 }
 
     [controller addAttachmentData:[NSData dataWithContentsOfFile:@"/tmp/dpkgl.log"] mimeType:@"text/plain" fileName:@"dpkgl.log"];
 }
 
-- (NSURL *) URLWithURL:(NSURL *)url {
-    return [Diversion divertURL:url];
-}
-
 - (NSURLRequest *) webView:(WebView *)view resource:(id)resource willSendRequest:(NSURLRequest *)request redirectResponse:(NSURLResponse *)response fromDataSource:(WebDataSource *)source {
     return [CydiaWebViewController requestWithHeaders:[super webView:view resource:resource willSendRequest:request redirectResponse:response fromDataSource:source]];
 }
 - (NSURLRequest *) webView:(WebView *)view resource:(id)resource willSendRequest:(NSURLRequest *)request redirectResponse:(NSURLResponse *)response fromDataSource:(WebDataSource *)source {
     return [CydiaWebViewController requestWithHeaders:[super webView:view resource:resource willSendRequest:request redirectResponse:response fromDataSource:source]];
 }
@@ -4985,23 +4567,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 (BridgedHosts_) {
         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;
 }
@@ -5011,13 +4582,9 @@ static _H<NSMutableSet> Diversions_;
     [cydia_ setDelegate:delegate];
 }
 
     [cydia_ setDelegate:delegate];
 }
 
-- (NSString *) applicationNameForUserAgent {
-    return UserAgent_;
-}
-
 - (id) init {
     if ((self = [super initWithWidth:0 ofClass:[CydiaWebViewController class]]) != nil) {
 - (id) init {
     if ((self = [super initWithWidth:0 ofClass:[CydiaWebViewController class]]) != nil) {
-        cydia_ = [[[CydiaObject alloc] initWithDelegate:indirect_] autorelease];
+        cydia_ = [[[CydiaObject alloc] initWithDelegate:self.indirect] autorelease];
     } return self;
 }
 
     } return self;
 }
 
@@ -5041,42 +4608,6 @@ static _H<NSMutableSet> Diversions_;
 @end
 /* }}} */
 
 @end
 /* }}} */
 
-// CydiaScript {{{
-@interface NSObject (CydiaScript)
-- (id) Cydia$webScriptObjectInContext:(WebScriptObject *)context;
-@end
-
-@implementation NSObject (CydiaScript)
-
-- (id) Cydia$webScriptObjectInContext:(WebScriptObject *)context {
-    return self;
-}
-
-@end
-
-@implementation NSArray (CydiaScript)
-
-- (id) Cydia$webScriptObjectInContext:(WebScriptObject *)context {
-    WebScriptObject *object([context evaluateWebScript:@"[]"]);
-    for (size_t i(0), e([self count]); i != e; ++i)
-        [object setWebScriptValueAtIndex:i value:[[self objectAtIndex:i] Cydia$webScriptObjectInContext:context]];
-    return object;
-}
-
-@end
-
-@implementation NSDictionary (CydiaScript)
-
-- (id) Cydia$webScriptObjectInContext:(WebScriptObject *)context {
-    WebScriptObject *object([context evaluateWebScript:@"({})"]);
-    for (id i in self)
-        [object setValue:[[self objectForKey:i] Cydia$webScriptObjectInContext:context] forKey:i];
-    return object;
-}
-
-@end
-// }}}
-
 /* Confirmation Controller {{{ */
 bool DepSubstrate(const pkgCache::VerIterator &iterator) {
     if (!iterator.end())
 /* Confirmation Controller {{{ */
 bool DepSubstrate(const pkgCache::VerIterator &iterator) {
     if (!iterator.end())
@@ -5120,7 +4651,7 @@ bool DepSubstrate(const pkgCache::VerIterator &iterator) {
 - (void) complete {
     if (substrate_)
         RestartSubstrate_ = true;
 - (void) complete {
     if (substrate_)
         RestartSubstrate_ = true;
-    [delegate_ confirmWithNavigationController:[self navigationController]];
+    [self.delegate confirmWithNavigationController:[self navigationController]];
 }
 
 - (void) alertView:(UIAlertView *)alert clickedButtonAtIndex:(NSInteger)button {
 }
 
 - (void) alertView:(UIAlertView *)alert clickedButtonAtIndex:(NSInteger)button {
@@ -5143,7 +4674,7 @@ bool DepSubstrate(const pkgCache::VerIterator &iterator) {
 }
 
 - (void) _doContinue {
 }
 
 - (void) _doContinue {
-    [delegate_ cancelAndClear:NO];
+    [self.delegate cancelAndClear:NO];
     [self dismissModalViewControllerAnimated:YES];
 }
 
     [self dismissModalViewControllerAnimated:YES];
 }
 
@@ -5181,8 +4712,6 @@ bool DepSubstrate(const pkgCache::VerIterator &iterator) {
 
         issues_ = [NSMutableArray arrayWithCapacity:4];
 
 
         issues_ = [NSMutableArray arrayWithCapacity:4];
 
-        UpgradeCydia_ = false;
-
         for (Package *package in packages) {
             pkgCache::PkgIterator iterator([package iterator]);
             NSString *name([package id]);
         for (Package *package in packages) {
             pkgCache::PkgIterator iterator([package iterator]);
             NSString *name([package id]);
@@ -5257,7 +4786,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];
@@ -5294,9 +4823,6 @@ bool DepSubstrate(const pkgCache::VerIterator &iterator) {
                 [removes addObject:name];
             }
 
                 [removes addObject:name];
             }
 
-            if ([name isEqualToString:@"cydia"])
-                UpgradeCydia_ = true;
-
             substrate_ |= DepSubstrate(policy->GetCandidateVer(iterator));
             substrate_ |= DepSubstrate(iterator.CurrentVer());
         }
             substrate_ |= DepSubstrate(policy->GetCandidateVer(iterator));
             substrate_ |= DepSubstrate(iterator.CurrentVer());
         }
@@ -5371,7 +4897,7 @@ bool DepSubstrate(const pkgCache::VerIterator &iterator) {
 #endif
 
 - (void) cancelButtonClicked {
 #endif
 
 - (void) cancelButtonClicked {
-    [delegate_ cancelAndClear:YES];
+    [self.delegate cancelAndClear:YES];
     [self dismissModalViewControllerAnimated:YES];
 }
 
     [self dismissModalViewControllerAnimated:YES];
 }
 
@@ -5555,7 +5081,7 @@ bool DepSubstrate(const pkgCache::VerIterator &iterator) {
 - (id) initWithDatabase:(Database *)database delegate:(id)delegate {
     if ((self = [super init]) != nil) {
         database_ = database;
 - (id) initWithDatabase:(Database *)database delegate:(id)delegate {
     if ((self = [super init]) != nil) {
         database_ = database;
-        delegate_ = delegate;
+        self.delegate = delegate;
 
         [database_ setProgressDelegate:self];
 
 
         [database_ setProgressDelegate:self];
 
@@ -5564,7 +5090,7 @@ bool DepSubstrate(const pkgCache::VerIterator &iterator) {
 
         [self setURL:[NSURL URLWithString:[NSString stringWithFormat:@"%@/#!/progress/", UI_]]];
 
 
         [self setURL:[NSURL URLWithString:[NSString stringWithFormat:@"%@/#!/progress/", UI_]]];
 
-        [scroller_ setBackgroundColor:[UIColor blackColor]];
+        [self setPageColor:[UIColor blackColor]];
 
         [[self navigationItem] setHidesBackButton:YES];
 
 
         [[self navigationItem] setHidesBackButton:YES];
 
@@ -5586,51 +5112,23 @@ 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) {
-            _root(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);
 
     if (Finish_ > 1)
 - (void) close {
     UpdateExternalStatus(0);
 
     if (Finish_ > 1)
-        [delegate_ saveState];
+        [self.delegate saveState];
 
     switch (Finish_) {
         case 0:
 
     switch (Finish_) {
         case 0:
-            [delegate_ returnToCydia];
+            [self.delegate returnToCydia];
         break;
 
         case 1:
         break;
 
         case 1:
-            [delegate_ terminateWithSuccess];
-            /*if ([delegate_ respondsToSelector:@selector(suspendWithAnimation:)])
-                [delegate_ suspendWithAnimation:YES];
+            [self.delegate terminateWithSuccess];
+            /*if ([self.delegate respondsToSelector:@selector(suspendWithAnimation:)])
+                [self.delegate suspendWithAnimation:YES];
             else
             else
-                [delegate_ suspend];*/
+                [self.delegate suspend];*/
         break;
 
         case 2:
         break;
 
         case 2:
@@ -5642,9 +5140,9 @@ bool DepSubstrate(const pkgCache::VerIterator &iterator) {
             goto reload;
 
         reload: {
             goto reload;
 
         reload: {
-            UIProgressHUD *hud([delegate_ addProgressHUD]);
+            UIProgressHUD *hud([self.delegate addProgressHUD]);
             [hud setText:UCLocalize("LOADING")];
             [hud setText:UCLocalize("LOADING")];
-            [self performSelector:@selector(reloadSpringBoard) withObject:nil afterDelay:0.5];
+            [self.delegate performSelector:@selector(reloadSpringBoard) withObject:nil afterDelay:0.5];
             return;
         }
 
             return;
         }
 
@@ -5842,12 +5340,12 @@ bool DepSubstrate(const pkgCache::VerIterator &iterator) {
         UIView *content([self contentView]);
         CGRect bounds([content bounds]);
 
         UIView *content([self contentView]);
         CGRect bounds([content bounds]);
 
-        content_ = [[[CyteTableViewCellContentView alloc] initWithFrame:bounds] autorelease];
-        [content_ setAutoresizingMask:UIViewAutoresizingFlexibleBoth];
-        [content addSubview:content_];
+        self.content = [[[CyteTableViewCellContentView alloc] initWithFrame:bounds] autorelease];
+        [self.content setAutoresizingMask:UIViewAutoresizingFlexibleBoth];
+        [content addSubview:self.content];
 
 
-        [content_ setDelegate:self];
-        [content_ setOpaque:YES];
+        [self.content setDelegate:self];
+        [self.content setOpaque:YES];
     } return self;
 }
 
     } return self;
 }
 
@@ -5866,7 +5364,7 @@ bool DepSubstrate(const pkgCache::VerIterator &iterator) {
     placard_ = nil;
 
     if (package == nil)
     placard_ = nil;
 
     if (package == nil)
-        [content_ setBackgroundColor:[UIColor whiteColor]];
+        [self.content setBackgroundColor:[UIColor whiteColor]];
     else {
         [package parse];
 
     else {
         [package parse];
 
@@ -5926,18 +5424,18 @@ bool DepSubstrate(const pkgCache::VerIterator &iterator) {
                 placard = nil;
         }
 
                 placard = nil;
         }
 
-        [content_ setBackgroundColor:color];
+        [self.content setBackgroundColor:color];
 
         if (placard != nil)
             placard_ = [UIImage imageAtPath:[NSString stringWithFormat:@"%@/%@.png", App_, placard]];
     }
 
     [self setNeedsDisplay];
 
         if (placard != nil)
             placard_ = [UIImage imageAtPath:[NSString stringWithFormat:@"%@/%@.png", App_, placard]];
     }
 
     [self setNeedsDisplay];
-    [content_ setNeedsDisplay];
+    [self.content setNeedsDisplay];
 }
 
 - (void) drawSummaryContentRect:(CGRect)rect {
 }
 
 - (void) drawSummaryContentRect:(CGRect)rect {
-    bool highlighted(highlighted_);
+    bool highlighted(self.highlighted);
     float width([self bounds].size.width);
 
     if (icon_ != nil) {
     float width([self bounds].size.width);
 
     if (icon_ != nil) {
@@ -5980,7 +5478,7 @@ bool DepSubstrate(const pkgCache::VerIterator &iterator) {
 }
 
 - (void) drawNormalContentRect:(CGRect)rect {
 }
 
 - (void) drawNormalContentRect:(CGRect)rect {
-    bool highlighted(highlighted_);
+    bool highlighted(self.highlighted);
     float width([self bounds].size.width);
 
     if (icon_ != nil) {
     float width([self bounds].size.width);
 
     if (icon_ != nil) {
@@ -6065,12 +5563,12 @@ bool DepSubstrate(const pkgCache::VerIterator &iterator) {
         UIView *content([self contentView]);
         CGRect bounds([content bounds]);
 
         UIView *content([self contentView]);
         CGRect bounds([content bounds]);
 
-        content_ = [[[CyteTableViewCellContentView alloc] initWithFrame:bounds] autorelease];
-        [content_ setAutoresizingMask:UIViewAutoresizingFlexibleBoth];
-        [content addSubview:content_];
-        [content_ setBackgroundColor:[UIColor whiteColor]];
+        self.content = [[[CyteTableViewCellContentView alloc] initWithFrame:bounds] autorelease];
+        [self.content setAutoresizingMask:UIViewAutoresizingFlexibleBoth];
+        [content addSubview:self.content];
+        [self.content setBackgroundColor:[UIColor whiteColor]];
 
 
-        [content_ setDelegate:self];
+        [self.content setDelegate:self];
     } return self;
 }
 
     } return self;
 }
 
@@ -6082,7 +5580,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 {
@@ -6116,7 +5613,7 @@ bool DepSubstrate(const pkgCache::VerIterator &iterator) {
     [self setAccessoryType:editing ? UITableViewCellAccessoryNone : UITableViewCellAccessoryDisclosureIndicator];
     [self setSelectionStyle:editing ? UITableViewCellSelectionStyleNone : UITableViewCellSelectionStyleBlue];
 
     [self setAccessoryType:editing ? UITableViewCellAccessoryNone : UITableViewCellAccessoryDisclosureIndicator];
     [self setSelectionStyle:editing ? UITableViewCellSelectionStyleNone : UITableViewCellSelectionStyleBlue];
 
-    [content_ setNeedsDisplay];
+    [self.content setNeedsDisplay];
 }
 
 - (void) setFrame:(CGRect)frame {
 }
 
 - (void) setFrame:(CGRect)frame {
@@ -6131,7 +5628,7 @@ bool DepSubstrate(const pkgCache::VerIterator &iterator) {
 }
 
 - (void) drawContentRect:(CGRect)rect {
 }
 
 - (void) drawContentRect:(CGRect)rect {
-    bool highlighted(highlighted_ && !editing_);
+    bool highlighted(self.highlighted && !editing_);
 
     [icon_ drawInRect:CGRectMake(7, 7, 32, 32)];
 
 
     [icon_ drawInRect:CGRectMake(7, 7, 32, 32)];
 
@@ -6259,7 +5756,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]]
                 ]];
             }
@@ -6286,7 +5783,9 @@ bool DepSubstrate(const pkgCache::VerIterator &iterator) {
     _H<NSString> name_;
     bool commercial_;
     std::vector<std::pair<_H<NSString>, _H<NSString>>> buttons_;
     _H<NSString> name_;
     bool commercial_;
     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;
@@ -6299,22 +5798,44 @@ bool DepSubstrate(const pkgCache::VerIterator &iterator) {
     return [NSURL URLWithString:[NSString stringWithFormat:@"cydia://package/%@", (id) name_]];
 }
 
     return [NSURL URLWithString:[NSString stringWithFormat:@"cydia://package/%@", (id) name_]];
 }
 
+- (void) _clickButtonWithPackage:(Package *)package {
+    [self.delegate installPackage:package];
+}
+
 - (void) _clickButtonWithName:(NSString *)name {
     if ([name isEqualToString:@"CLEAR"])
 - (void) _clickButtonWithName:(NSString *)name {
     if ([name isEqualToString:@"CLEAR"])
-        [delegate_ clearPackage:package_];
-    else if ([name isEqualToString:@"INSTALL"])
-        [delegate_ installPackage:package_];
-    else if ([name isEqualToString:@"REINSTALL"])
-        [delegate_ installPackage:package_];
+        return [self.delegate clearPackage:package_];
     else if ([name isEqualToString:@"REMOVE"])
     else if ([name isEqualToString:@"REMOVE"])
-        [delegate_ removePackage:package_];
-    else if ([name isEqualToString:@"UPGRADE"])
-        [delegate_ installPackage:package_];
+        return [self.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"];
+
+        [self.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);
+
+    [self.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]) {
@@ -6324,6 +5845,16 @@ bool DepSubstrate(const pkgCache::VerIterator &iterator) {
                 [self _clickButtonWithName:buttons_[button].first];
         }
 
                 [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:button animated:YES];
     }
 }
         [sheet dismissWithClickedButtonIndex:button animated:YES];
     }
 }
@@ -6334,6 +5865,9 @@ bool DepSubstrate(const pkgCache::VerIterator &iterator) {
 
 #if !AlwaysReload
 - (void) _customButtonClicked {
 
 #if !AlwaysReload
 - (void) _customButtonClicked {
+    if (commercial_ && self.isLoading && [package_ uninstalled])
+        return [self reloadURLWithCache:NO];
+
     size_t count(buttons_.size());
     if (count == 0)
         return;
     size_t count(buttons_.size());
     if (count == 0)
         return;
@@ -6345,7 +5879,7 @@ bool DepSubstrate(const pkgCache::VerIterator &iterator) {
         for (const auto &button : buttons_)
             [buttons addObject:button.second];
 
         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
@@ -6353,23 +5887,14 @@ 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]];
+        [self.delegate showActionSheet:sheet_ fromItem:[[self navigationItem] rightBarButtonItem]];
     }
 }
 
     }
 }
 
-- (void) reloadButtonClicked {
-    if (commercial_ && function_ == nil && [package_ uninstalled])
-        return;
-    [self customButtonClicked];
-}
-
 - (void) applyLoadingTitle {
     // Don't show "Loading" as the title. Ever.
 }
 - (void) applyLoadingTitle {
     // Don't show "Loading" as the title. Ever.
 }
@@ -6394,7 +5919,11 @@ 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_.clear();
 
 
     buttons_.clear();
 
@@ -6414,6 +5943,8 @@ bool DepSubstrate(const pkgCache::VerIterator &iterator) {
             buttons_.push_back(std::make_pair(@"REINSTALL", UCLocalize("REINSTALL")));
         if (![package_ uninstalled])
             buttons_.push_back(std::make_pair(@"REMOVE", UCLocalize("REMOVE")));
             buttons_.push_back(std::make_pair(@"REINSTALL", UCLocalize("REINSTALL")));
         if (![package_ uninstalled])
             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;
@@ -6439,7 +5970,7 @@ bool DepSubstrate(const pkgCache::VerIterator &iterator) {
 /* }}} */
 
 /* Package List Controller {{{ */
 /* }}} */
 
 /* Package List Controller {{{ */
-@interface PackageListController : CyteViewController <
+@interface PackageListController : CyteListController <
     UITableViewDataSource,
     UITableViewDelegate
 > {
     UITableViewDataSource,
     UITableViewDelegate
 > {
@@ -6447,7 +5978,6 @@ bool DepSubstrate(const pkgCache::VerIterator &iterator) {
     unsigned era_;
     _H<NSArray> packages_;
     _H<NSArray> sections_;
     unsigned era_;
     _H<NSArray> packages_;
     _H<NSArray> sections_;
-    _H<UITableView, 2> list_;
 
     _H<NSArray> thumbs_;
     std::vector<NSInteger> offset_;
 
     _H<NSArray> thumbs_;
     std::vector<NSInteger> offset_;
@@ -6457,9 +5987,6 @@ bool DepSubstrate(const pkgCache::VerIterator &iterator) {
 }
 
 - (id) initWithDatabase:(Database *)database title:(NSString *)title;
 }
 
 - (id) initWithDatabase:(Database *)database title:(NSString *)title;
-- (void) setDelegate:(id)delegate;
-- (void) resetCursor;
-- (void) clearData;
 
 - (NSArray *) sectionsForPackages:(NSMutableArray *)packages;
 
 
 - (NSArray *) sectionsForPackages:(NSMutableArray *)packages;
 
@@ -6479,98 +6006,9 @@ bool DepSubstrate(const pkgCache::VerIterator &iterator) {
     return true;
 }
 
     return true;
 }
 
-- (void) deselectWithAnimation:(BOOL)animated {
-    [list_ deselectRowAtIndexPath:[list_ indexPathForSelectedRow] animated:animated];
-}
-
-- (void) resizeForKeyboardBounds:(CGRect)bounds duration:(NSTimeInterval)duration curve:(UIViewAnimationCurve)curve {
-    CGRect base = [[self view] bounds];
-    base.size.height -= bounds.size.height;
-    base.origin = [list_ frame].origin;
-
-    [UIView beginAnimations:nil context:NULL];
-    [UIView setAnimationBeginsFromCurrentState:YES];
-    [UIView setAnimationCurve:curve];
-    [UIView setAnimationDuration:duration];
-    [list_ setFrame:base];
-    [UIView commitAnimations];
-}
-
-- (void) resizeForKeyboardBounds:(CGRect)bounds duration:(NSTimeInterval)duration {
-    [self resizeForKeyboardBounds:bounds duration:duration curve:UIViewAnimationCurveLinear];
-}
-
-- (void) resizeForKeyboardBounds:(CGRect)bounds {
-    [self resizeForKeyboardBounds:bounds duration:0];
-}
-
-- (void) getKeyboardCurve:(UIViewAnimationCurve *)curve duration:(NSTimeInterval *)duration forNotification:(NSNotification *)notification {
-    if (&UIKeyboardAnimationCurveUserInfoKey == NULL)
-        *curve = UIViewAnimationCurveEaseInOut;
-    else
-        [[[notification userInfo] objectForKey:UIKeyboardAnimationCurveUserInfoKey] getValue:curve];
-
-    if (&UIKeyboardAnimationDurationUserInfoKey == NULL)
-        *duration = 0.3;
-    else
-        [[[notification userInfo] objectForKey:UIKeyboardAnimationDurationUserInfoKey] getValue:duration];
-}
-
-- (void) keyboardWillShow:(NSNotification *)notification {
-    CGRect bounds;
-    CGPoint center;
-    [[[notification userInfo] objectForKey:UIKeyboardBoundsUserInfoKey] getValue:&bounds];
-    [[[notification userInfo] objectForKey:UIKeyboardCenterEndUserInfoKey] getValue:&center];
-
-    NSTimeInterval duration;
-    UIViewAnimationCurve curve;
-    [self getKeyboardCurve:&curve duration:&duration forNotification:notification];
-
-    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];
-    CGRect viewframe = [[base view] convertRect:[list_ frame] fromView:[list_ superview]];
-    CGRect intersection = CGRectIntersection(viewframe, kbframe);
-
-    if (kCFCoreFoundationVersionNumber < kCFCoreFoundationVersionNumber_iPhoneOS_3_0) // XXX: _UIApplicationLinkedOnOrAfter(4)
-        intersection.size.height += CYStatusBarHeight();
-
-    [self resizeForKeyboardBounds:intersection duration:duration curve:curve];
-}
-
-- (void) keyboardWillHide:(NSNotification *)notification {
-    NSTimeInterval duration;
-    UIViewAnimationCurve curve;
-    [self getKeyboardCurve:&curve duration:&duration forNotification:notification];
-
-    [self resizeForKeyboardBounds:CGRectZero duration:duration curve:curve];
-}
-
-- (void) viewWillAppear:(BOOL)animated {
-    [super viewWillAppear:animated];
-
-    [self resizeForKeyboardBounds:CGRectZero];
-    [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(keyboardWillShow:) name:UIKeyboardWillShowNotification object:nil];
-    [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(keyboardWillHide:) name:UIKeyboardWillHideNotification object:nil];
-}
-
-- (void) viewWillDisappear:(BOOL)animated {
-    [super viewWillDisappear:animated];
-
-    [self resizeForKeyboardBounds:CGRectZero];
-    [[NSNotificationCenter defaultCenter] removeObserver:self name:UIKeyboardWillShowNotification object:nil];
-    [[NSNotificationCenter defaultCenter] removeObserver:self name:UIKeyboardWillHideNotification object:nil];
-}
-
-- (void) viewDidAppear:(BOOL)animated {
-    [super viewDidAppear:animated];
-    [self deselectWithAnimation:animated];
-}
-
 - (void) didSelectPackage:(Package *)package {
     CYPackageController *view([[[CYPackageController alloc] initWithDatabase:database_ forPackage:[package id] withReferrer:[[self referrerURL] absoluteString]] autorelease]);
 - (void) didSelectPackage:(Package *)package {
     CYPackageController *view([[[CYPackageController alloc] initWithDatabase:database_ forPackage:[package id] withReferrer:[[self referrerURL] absoluteString]] autorelease]);
-    [view setDelegate:delegate_];
+    [view setDelegate:self.delegate];
     [[self navigationController] pushViewController:view animated:YES];
 }
 
     [[self navigationController] pushViewController:view animated:YES];
 }
 
@@ -6626,8 +6064,8 @@ bool DepSubstrate(const pkgCache::VerIterator &iterator) {
     return offset_[index];
 }
 
     return offset_[index];
 }
 
-- (void) updateHeight {
-    [list_ setRowHeight:([self isSummarized] ? 38 : 73)];
+- (CGFloat) rowHeight {
+    return [self isSummarized] ? 38 : 73;
 }
 
 - (id) initWithDatabase:(Database *)database title:(NSString *)title {
 }
 
 - (id) initWithDatabase:(Database *)database title:(NSString *)title {
@@ -6638,27 +6076,7 @@ bool DepSubstrate(const pkgCache::VerIterator &iterator) {
     } return self;
 }
 
     } return self;
 }
 
-- (void) loadView {
-    UIView *view([[[UIView alloc] initWithFrame:[[UIScreen mainScreen] applicationFrame]] autorelease]);
-    [view setAutoresizingMask:(UIViewAutoresizingFlexibleWidth | UIViewAutoresizingFlexibleHeight)];
-    [self setView:view];
-
-    list_ = [[[UITableView alloc] initWithFrame:[[self view] bounds] style:UITableViewStylePlain] autorelease];
-    [list_ setAutoresizingMask:UIViewAutoresizingFlexibleBoth];
-    [view addSubview:list_];
-
-    // XXX: is 20 the most optimal number here?
-    [list_ setSectionIndexMinimumDisplayRowCount:20];
-
-    [(UITableView *) list_ setDataSource:self];
-    [list_ setDelegate:self];
-
-    [self updateHeight];
-}
-
 - (void) releaseSubviews {
 - (void) releaseSubviews {
-    list_ = nil;
-
     packages_ = nil;
     sections_ = nil;
 
     packages_ = nil;
     sections_ = nil;
 
@@ -6668,14 +6086,6 @@ bool DepSubstrate(const pkgCache::VerIterator &iterator) {
     [super releaseSubviews];
 }
 
     [super releaseSubviews];
 }
 
-- (void) setDelegate:(id)delegate {
-    delegate_ = delegate;
-}
-
-- (bool) shouldYield {
-    return false;
-}
-
 - (bool) shouldBlock {
     return false;
 }
 - (bool) shouldBlock {
     return false;
 }
@@ -6704,7 +6114,7 @@ bool DepSubstrate(const pkgCache::VerIterator &iterator) {
             if (![self shouldBlock])
                 hud = nil;
             else {
             if (![self shouldBlock])
                 hud = nil;
             else {
-                hud = [delegate_ addProgressHUD];
+                hud = [self.delegate addProgressHUD];
                 [hud setText:UCLocalize("LOADING")];
             }
 
                 [hud setText:UCLocalize("LOADING")];
             }
 
@@ -6712,7 +6122,7 @@ bool DepSubstrate(const pkgCache::VerIterator &iterator) {
             packages = [self yieldToSelector:@selector(_reloadPackages)];
 
             if (hud != nil)
             packages = [self yieldToSelector:@selector(_reloadPackages)];
 
             if (hud != nil)
-                [delegate_ removeProgressHUD:hud];
+                [self.delegate removeProgressHUD:hud];
         } while (reloading_ == 2);
     } else {
         packages = [self _reloadPackages];
         } while (reloading_ == 2);
     } else {
         packages = [self _reloadPackages];
@@ -6736,12 +6146,7 @@ bool DepSubstrate(const pkgCache::VerIterator &iterator) {
         sections_ = [NSArray arrayWithObject:section];
     }
 
         sections_ = [NSArray arrayWithObject:section];
     }
 
-    [self updateHeight];
-
-    _profile(PackageTable$reloadData$List)
-        [(UITableView *) list_ setDataSource:self];
-        [list_ reloadData];
-    _end
+    [super _reloadData];
 }
 
     PrintTimes();
 }
 
     PrintTimes();
@@ -6800,28 +6205,6 @@ bool DepSubstrate(const pkgCache::VerIterator &iterator) {
     return sections;
 }
 
     return sections;
 }
 
-- (void) reloadData {
-    [super reloadData];
-
-    if ([self shouldYield])
-        [self performSelector:@selector(_reloadData) withObject:nil afterDelay:0];
-    else
-        [self _reloadData];
-}
-
-- (void) resetCursor {
-    [list_ scrollRectToVisible:CGRectMake(0, 0, 1, 1) animated:NO];
-}
-
-- (void) clearData {
-    [self updateHeight];
-
-    [list_ setDataSource:nil];
-    [list_ reloadData];
-
-    [self resetCursor];
-}
-
 @end
 /* }}} */
 /* Filtered Package List Controller {{{ */
 @end
 /* }}} */
 /* Filtered Package List Controller {{{ */
@@ -6868,7 +6251,7 @@ typedef Function<void, NSMutableArray *> PackageSorter;
 
     _profile(PackageTable$reloadData$Filter)
         for (Package *package in packages)
 
     _profile(PackageTable$reloadData$Filter)
         for (Package *package in packages)
-            if ([package valid] && filter(package))
+            if (filter(package))
                 [filtered addObject:package];
     _end
 
                 [filtered addObject:package];
     _end
 
@@ -6935,7 +6318,7 @@ static void HomeControllerReachabilityCallback(SCNetworkReachabilityRef reachabi
     [alert setCancelButtonIndex:0];
 
     [alert setMessage:
     [alert setCancelButtonIndex:0];
 
     [alert setMessage:
-        @"Copyright \u00a9 2008-2014\n"
+        @"Copyright \u00a9 2008-2015\n"
         "SaurikIT, LLC\n"
         "\n"
         "Jay Freeman (saurik)\n"
         "SaurikIT, LLC\n"
         "\n"
         "Jay Freeman (saurik)\n"
@@ -6958,15 +6341,6 @@ static void HomeControllerReachabilityCallback(SCNetworkReachabilityRef reachabi
 @end
 /* }}} */
 
 @end
 /* }}} */
 
-/* Cydia Navigation Controller Interface {{{ */
-@interface UINavigationController (Cydia)
-
-- (NSArray *) navigationURLCollection;
-- (void) unloadData;
-
-@end
-/* }}} */
-
 /* Cydia Tab Bar Controller {{{ */
 @interface CydiaTabBarController : CyteTabBarController <
     UITabBarControllerDelegate,
 /* Cydia Tab Bar Controller {{{ */
 @interface CydiaTabBarController : CyteTabBarController <
     UITabBarControllerDelegate,
@@ -6981,7 +6355,6 @@ static void HomeControllerReachabilityCallback(SCNetworkReachabilityRef reachabi
     _transient NSObject<CydiaDelegate> *updatedelegate_;
 }
 
     _transient NSObject<CydiaDelegate> *updatedelegate_;
 }
 
-- (NSArray *) navigationURLCollection;
 - (void) beginUpdate;
 - (BOOL) updating;
 
 - (void) beginUpdate;
 - (BOOL) updating;
 
@@ -6989,19 +6362,6 @@ static void HomeControllerReachabilityCallback(SCNetworkReachabilityRef reachabi
 
 @implementation CydiaTabBarController
 
 
 @implementation CydiaTabBarController
 
-- (NSArray *) navigationURLCollection {
-    NSMutableArray *items([NSMutableArray array]);
-
-    // XXX: Should this deal with transient view controllers?
-    for (id navigation in [self viewControllers]) {
-        NSArray *stack = [navigation performSelector:@selector(navigationURLCollection)];
-        if (stack != nil)
-            [items addObject:stack];
-    }
-
-    return items;
-}
-
 - (id) initWithDatabase:(Database *)database {
     if ((self = [super init]) != nil) {
         database_ = database;
 - (id) initWithDatabase:(Database *)database {
     if ((self = [super init]) != nil) {
         database_ = database;
@@ -7014,10 +6374,6 @@ static void HomeControllerReachabilityCallback(SCNetworkReachabilityRef reachabi
     } return self;
 }
 
     } return self;
 }
 
-- (void) setUpdate:(NSDate *)date {
-    [self beginUpdate];
-}
-
 - (void) beginUpdate {
     if (updating_)
         return;
 - (void) beginUpdate {
     if (updating_)
         return;
@@ -7104,103 +6460,19 @@ static void HomeControllerReachabilityCallback(SCNetworkReachabilityRef reachabi
 @end
 /* }}} */
 
 @end
 /* }}} */
 
-/* Cydia Navigation Controller Implementation {{{ */
-@implementation UINavigationController (Cydia)
-
-- (NSArray *) navigationURLCollection {
-    NSMutableArray *stack([NSMutableArray array]);
-
-    for (CyteViewController *controller in [self viewControllers]) {
-        NSString *url = [[controller navigationURL] absoluteString];
-        if (url != nil)
-            [stack addObject:url];
-    }
-
-    return stack;
-}
-
-- (void) reloadData {
-    [super reloadData];
-
-    UIViewController *visible([self visibleViewController]);
-    if (visible != nil)
-        [visible reloadData];
-
-    // on the iPad, this view controller is ALSO visible. :(
-    if (IsWildcat_)
-        if (UIViewController *modal = [self modalViewController])
-            if ([modal modalPresentationStyle] == UIModalPresentationFormSheet)
-                if (UIViewController *top = [self topViewController])
-                    if (top != visible)
-                        [top reloadData];
-}
-
-- (void) unloadData {
-    for (CyteViewController *page in [self viewControllers])
-        [page unloadData];
-
-    [super unloadData];
-}
-
-@end
-/* }}} */
-
 /* Cydia:// Protocol {{{ */
 /* Cydia:// Protocol {{{ */
-@interface CydiaURLProtocol : NSURLProtocol {
+@interface CydiaURLProtocol : CyteURLProtocol {
 }
 
 @end
 
 @implementation CydiaURLProtocol
 
 }
 
 @end
 
 @implementation CydiaURLProtocol
 
-+ (BOOL) canInitWithRequest:(NSURLRequest *)request {
-    NSURL *url([request URL]);
-    if (url == nil)
-        return NO;
-
-    NSString *scheme([[url scheme] lowercaseString]);
-    if (scheme != nil && [scheme isEqualToString:@"cydia"])
-        return YES;
-    if ([[url absoluteString] hasPrefix:@"about:cydia-"])
-        return YES;
-
-    return NO;
++ (NSString *) scheme {
+    return @"cydia";
 }
 
 }
 
-+ (NSURLRequest *) canonicalRequestForRequest:(NSURLRequest *)request {
-    return request;
-}
-
-- (void) _returnPNGWithImage:(UIImage *)icon forRequest:(NSURLRequest *)request {
-    id<NSURLProtocolClient> client([self client]);
-    if (icon == nil)
-        [client URLProtocol:self didFailWithError:[NSError errorWithDomain:NSURLErrorDomain code:NSURLErrorFileDoesNotExist userInfo:nil]];
-    else {
-        NSData *data(UIImagePNGRepresentation(icon));
-
-        NSURLResponse *response([[[NSURLResponse alloc] initWithURL:[request URL] MIMEType:@"image/png" expectedContentLength:-1 textEncodingName:nil] autorelease]);
-        [client URLProtocol:self didReceiveResponse:response cacheStoragePolicy:NSURLCacheStorageNotAllowed];
-        [client URLProtocol:self didLoadData:data];
-        [client URLProtocolDidFinishLoading:self];
-    }
-}
-
-- (void) startLoading {
-    id<NSURLProtocolClient> client([self client]);
-    NSURLRequest *request([self request]);
-
-    NSURL *url([request URL]);
-    NSString *href([url absoluteString]);
-    NSString *scheme([[url scheme] lowercaseString]);
-
-    NSString *path;
-
-    if ([scheme isEqualToString:@"cydia"])
-        path = [href substringFromIndex:8];
-    else if ([scheme isEqualToString:@"about"])
-        path = [href substringFromIndex:12];
-    else _assert(false);
-
+- (bool) loadForPath:(NSString *)path ofRequest:(NSURLRequest *)request {
     NSRange slash([path rangeOfString:@"/"]);
 
     NSString *command;
     NSRange slash([path rangeOfString:@"/"]);
 
     NSString *command;
@@ -7212,9 +6484,30 @@ static void HomeControllerReachabilityCallback(SCNetworkReachabilityRef reachabi
         path = [path substringFromIndex:(slash.location + 1)];
     }
 
         path = [path substringFromIndex:(slash.location + 1)];
     }
 
-    Database *database([Database sharedInstance]);
+    Database *database([Database sharedInstance]);
+
+    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"];
 
 
-    if ([command isEqualToString:@"package-icon"]) {
+        [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];
@@ -7239,11 +6532,10 @@ static void HomeControllerReachabilityCallback(SCNetworkReachabilityRef reachabi
             icon = [UIImage imageNamed:@"unknown.png"];
         [self _returnPNGWithImage:icon forRequest:request];
     } else fail: {
             icon = [UIImage imageNamed:@"unknown.png"];
         [self _returnPNGWithImage:icon forRequest:request];
     } else fail: {
-        [client URLProtocol:self didFailWithError:[NSError errorWithDomain:NSURLErrorDomain code:NSURLErrorResourceUnavailable userInfo:nil]];
+        return [super loadForPath:path ofRequest:request];
     }
     }
-}
 
 
-- (void) stopLoading {
+    return true;
 }
 
 @end
 }
 
 @end
@@ -7362,7 +6654,7 @@ static void HomeControllerReachabilityCallback(SCNetworkReachabilityRef reachabi
     if (editing)
         [list_ reloadData];
     else
     if (editing)
         [list_ reloadData];
     else
-        [delegate_ updateData];
+        [self.delegate updateData];
 
     [self updateNavigationItem];
 }
 
     [self updateNavigationItem];
 }
@@ -7424,7 +6716,7 @@ static void HomeControllerReachabilityCallback(SCNetworkReachabilityRef reachabi
         source:[self source]
         section:[section name]
     ] autorelease];
         source:[self source]
         section:[section name]
     ] autorelease];
-    [controller setDelegate:delegate_];
+    [controller setDelegate:self.delegate];
 
     [[self navigationController] pushViewController:controller animated:YES];
 }
 
     [[self navigationController] pushViewController:controller animated:YES];
 }
@@ -7495,7 +6787,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
 
@@ -7569,7 +6861,7 @@ static void HomeControllerReachabilityCallback(SCNetworkReachabilityRef reachabi
 }
 
 - (void) setLeftBarButtonItem {
 }
 
 - (void) setLeftBarButtonItem {
-    if ([delegate_ updating])
+    if ([self.delegate updating])
         [[self navigationItem] setLeftBarButtonItem:[[[UIBarButtonItem alloc]
             initWithTitle:UCLocalize("CANCEL")
             style:UIBarButtonItemStyleDone
         [[self navigationItem] setLeftBarButtonItem:[[[UIBarButtonItem alloc]
             initWithTitle:UCLocalize("CANCEL")
             style:UIBarButtonItemStyleDone
@@ -7586,16 +6878,16 @@ static void HomeControllerReachabilityCallback(SCNetworkReachabilityRef reachabi
 }
 
 - (void) refreshButtonClicked {
 }
 
 - (void) refreshButtonClicked {
-    if ([delegate_ requestUpdate])
+    if ([self.delegate requestUpdate])
         [self setLeftBarButtonItem];
 }
 
 - (void) cancelButtonClicked {
         [self setLeftBarButtonItem];
 }
 
 - (void) cancelButtonClicked {
-    [delegate_ cancelUpdate];
+    [self.delegate cancelUpdate];
 }
 
 - (void) upgradeButtonClicked {
 }
 
 - (void) upgradeButtonClicked {
-    [delegate_ distUpgrade];
+    [self.delegate distUpgrade];
     [[self navigationItem] setRightBarButtonItem:nil animated:YES];
 }
 
     [[self navigationItem] setRightBarButtonItem:nil animated:YES];
 }
 
@@ -7702,8 +6994,6 @@ static void HomeControllerReachabilityCallback(SCNetworkReachabilityRef reachabi
     if (upgrades_ != 0)
         [sections insertObject:upgradable atIndex:0];
 
     if (upgrades_ != 0)
         [sections insertObject:upgradable atIndex:0];
 
-    [list_ reloadData];
-
     [[self navigationItem] setRightBarButtonItem:(upgrades_ == 0 ? nil : [[[UIBarButtonItem alloc]
         initWithTitle:[NSString stringWithFormat:UCLocalize("PARENTHETICAL"), UCLocalize("UPGRADE"), [NSString stringWithFormat:@"%u", upgrades_]]
         style:UIBarButtonItemStylePlain
     [[self navigationItem] setRightBarButtonItem:(upgrades_ == 0 ? nil : [[[UIBarButtonItem alloc]
         initWithTitle:[NSString stringWithFormat:UCLocalize("PARENTHETICAL"), UCLocalize("UPGRADE"), [NSString stringWithFormat:@"%u", upgrades_]]
         style:UIBarButtonItemStylePlain
@@ -7940,27 +7230,22 @@ static void HomeControllerReachabilityCallback(SCNetworkReachabilityRef reachabi
     if (package_ == nil)
         return;
     if ([package_ setSubscribed:value])
     if (package_ == nil)
         return;
     if ([package_ setSubscribed:value])
-        [delegate_ updateData];
+        [self.delegate updateData];
 }
 
 - (void) _updateIgnored {
     const char *package([name_ UTF8String]);
     bool on([ignoredSwitch_ isOn]);
 
 }
 
 - (void) _updateIgnored {
     const char *package([name_ UTF8String]);
     bool on([ignoredSwitch_ isOn]);
 
-    pid_t pid(ExecFork());
-    if (pid == 0) {
-        FILE *dpkg(_root(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 {
@@ -7968,7 +7253,7 @@ static void HomeControllerReachabilityCallback(SCNetworkReachabilityRef reachabi
     [invocation setTarget:self];
     [invocation setSelector:@selector(_updateIgnored)];
 
     [invocation setTarget:self];
     [invocation setSelector:@selector(_updateIgnored)];
 
-    [delegate_ reloadDataWithInvocation:invocation];
+    [self.delegate reloadDataWithInvocation:invocation];
 }
 
 - (UITableViewCell *) tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath {
 }
 
 - (UITableViewCell *) tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath {
@@ -8159,7 +7444,7 @@ static void HomeControllerReachabilityCallback(SCNetworkReachabilityRef reachabi
 
 #if !AlwaysReload
 - (void) queueButtonClicked {
 
 #if !AlwaysReload
 - (void) queueButtonClicked {
-    [delegate_ queue];
+    [self.delegate queue];
 }
 #endif
 
 }
 #endif
 
@@ -8209,7 +7494,7 @@ static void HomeControllerReachabilityCallback(SCNetworkReachabilityRef reachabi
 - (void) _setImage:(NSArray *)data {
     if ([url_ isEqual:[data objectAtIndex:0]]) {
         icon_ = [data objectAtIndex:1];
 - (void) _setImage:(NSArray *)data {
     if ([url_ isEqual:[data objectAtIndex:0]]) {
         icon_ = [data objectAtIndex:1];
-        [content_ setNeedsDisplay];
+        [self.content setNeedsDisplay];
     }
 }
 
     }
 }
 
@@ -8243,7 +7528,7 @@ static void HomeControllerReachabilityCallback(SCNetworkReachabilityRef reachabi
     origin_ = [source name];
     label_ = [source rooturi];
 
     origin_ = [source name];
     label_ = [source rooturi];
 
-    [content_ setNeedsDisplay];
+    [self.content setNeedsDisplay];
 
     url_ = [source iconURL];
     [NSThread detachNewThreadSelector:@selector(_setSource:) toTarget:self withObject:url_];
 
     url_ = [source iconURL];
     [NSThread detachNewThreadSelector:@selector(_setSource:) toTarget:self withObject:url_];
@@ -8256,7 +7541,7 @@ static void HomeControllerReachabilityCallback(SCNetworkReachabilityRef reachabi
     icon_ = [UIImage imageNamed:@"folder.png"];
     origin_ = UCLocalize("ALL_SOURCES");
     label_ = UCLocalize("ALL_SOURCES_EX");
     icon_ = [UIImage imageNamed:@"folder.png"];
     origin_ = UCLocalize("ALL_SOURCES");
     label_ = UCLocalize("ALL_SOURCES_EX");
-    [content_ setNeedsDisplay];
+    [self.content setNeedsDisplay];
 }
 
 - (SourceCell *) initWithFrame:(CGRect)frame reuseIdentifier:(NSString *)reuseIdentifier {
 }
 
 - (SourceCell *) initWithFrame:(CGRect)frame reuseIdentifier:(NSString *)reuseIdentifier {
@@ -8264,19 +7549,19 @@ static void HomeControllerReachabilityCallback(SCNetworkReachabilityRef reachabi
         UIView *content([self contentView]);
         CGRect bounds([content bounds]);
 
         UIView *content([self contentView]);
         CGRect bounds([content bounds]);
 
-        content_ = [[[CyteTableViewCellContentView alloc] initWithFrame:bounds] autorelease];
-        [content_ setAutoresizingMask:UIViewAutoresizingFlexibleBoth];
-        [content_ setBackgroundColor:[UIColor whiteColor]];
-        [content addSubview:content_];
+        self.content = [[[CyteTableViewCellContentView alloc] initWithFrame:bounds] autorelease];
+        [self.content setAutoresizingMask:UIViewAutoresizingFlexibleBoth];
+        [self.content setBackgroundColor:[UIColor whiteColor]];
+        [content addSubview:self.content];
 
 
-        [content_ setDelegate:self];
-        [content_ setOpaque:YES];
+        [self.content setDelegate:self];
+        [self.content setOpaque:YES];
 
         indicator_ = [[[UIActivityIndicatorView alloc] initWithActivityIndicatorStyle:UIActivityIndicatorViewStyleGraySmall] autorelease];
         [indicator_ setAutoresizingMask:UIViewAutoresizingFlexibleLeftMargin | UIViewAutoresizingFlexibleTopMargin];// | UIViewAutoresizingFlexibleBottomMargin];
         [content addSubview:indicator_];
 
 
         indicator_ = [[[UIActivityIndicatorView alloc] initWithActivityIndicatorStyle:UIActivityIndicatorViewStyleGraySmall] autorelease];
         [indicator_ setAutoresizingMask:UIViewAutoresizingFlexibleLeftMargin | UIViewAutoresizingFlexibleTopMargin];// | UIViewAutoresizingFlexibleBottomMargin];
         [content addSubview:indicator_];
 
-        [[content_ layer] setContentsGravity:kCAGravityTopLeft];
+        [[self.content layer] setContentsGravity:kCAGravityTopLeft];
     } return self;
 }
 
     } return self;
 }
 
@@ -8300,7 +7585,7 @@ static void HomeControllerReachabilityCallback(SCNetworkReachabilityRef reachabi
 }
 
 - (void) drawContentRect:(CGRect)rect {
 }
 
 - (void) drawContentRect:(CGRect)rect {
-    bool highlighted(highlighted_);
+    bool highlighted(self.highlighted);
     float width(rect.size.width);
 
     if (icon_ != nil) {
     float width(rect.size.width);
 
     if (icon_ != nil) {
@@ -8444,7 +7729,7 @@ static void HomeControllerReachabilityCallback(SCNetworkReachabilityRef reachabi
         source:[self sourceAtIndexPath:indexPath]
     ] autorelease]);
 
         source:[self sourceAtIndexPath:indexPath]
     ] autorelease]);
 
-    [controller setDelegate:delegate_];
+    [controller setDelegate:self.delegate];
     [[self navigationController] pushViewController:controller animated:YES];
 }
 
     [[self navigationController] pushViewController:controller animated:YES];
 }
 
@@ -8462,10 +7747,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];
+        [self.delegate syncData];
     }
 }
 
     }
 }
 
@@ -8474,10 +7757,10 @@ static void HomeControllerReachabilityCallback(SCNetworkReachabilityRef reachabi
 }
 
 - (void) complete {
 }
 
 - (void) complete {
-    [delegate_ addTrivialSource:href_];
+    [self.delegate addTrivialSource:href_];
     href_ = nil;
 
     href_ = nil;
 
-    [delegate_ syncData];
+    [self.delegate syncData];
 }
 
 - (NSString *) getWarning {
 }
 
 - (NSString *) getWarning {
@@ -8516,9 +7799,9 @@ static void HomeControllerReachabilityCallback(SCNetworkReachabilityRef reachabi
     ) {
         NSString *warning(cydia_ ? [self yieldToSelector:@selector(getWarning)] : nil);
 
     ) {
         NSString *warning(cydia_ ? [self yieldToSelector:@selector(getWarning)] : nil);
 
-        [delegate_ releaseNetworkActivityIndicator];
+        [self.delegate releaseNetworkActivityIndicator];
 
 
-        [delegate_ removeProgressHUD:hud_];
+        [self.delegate removeProgressHUD:hud_];
         hud_ = nil;
 
         if (cydia_) {
         hud_ = nil;
 
         if (cydia_) {
@@ -8624,27 +7907,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?)://|file:///)[^# ]*$");
-                if (!href_r(href)) {
-                    UIAlertView *alert = [[[UIAlertView alloc]
-                        initWithTitle:[NSString stringWithFormat:Colon_, Error_, UCLocalize("INVALID_URL")]
-                        message:UCLocalize("INVALID_URL_EX")
-                        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];
@@ -8652,9 +7918,9 @@ static void HomeControllerReachabilityCallback(SCNetworkReachabilityRef reachabi
                 cydia_ = false;
 
                 // XXX: this is stupid
                 cydia_ = false;
 
                 // XXX: this is stupid
-                hud_ = [delegate_ addProgressHUD];
+                hud_ = [self.delegate addProgressHUD];
                 [hud_ setText:UCLocalize("VERIFYING_URL")];
                 [hud_ setText:UCLocalize("VERIFYING_URL")];
-                [delegate_ retainNetworkActivityIndicator];
+                [self.delegate retainNetworkActivityIndicator];
             } break;
 
             case 0:
             } break;
 
             case 0:
@@ -8694,7 +7960,7 @@ static void HomeControllerReachabilityCallback(SCNetworkReachabilityRef reachabi
             target:self
             action:@selector(addButtonClicked)
         ] autorelease] animated:animated];
             target:self
             action:@selector(addButtonClicked)
         ] autorelease] animated:animated];
-    else if ([delegate_ updating])
+    else if ([self.delegate updating])
         [[self navigationItem] setLeftBarButtonItem:[[[UIBarButtonItem alloc]
             initWithTitle:UCLocalize("CANCEL")
             style:UIBarButtonItemStyleDone
         [[self navigationItem] setLeftBarButtonItem:[[[UIBarButtonItem alloc]
             initWithTitle:UCLocalize("CANCEL")
             style:UIBarButtonItemStyleDone
@@ -8794,7 +8060,7 @@ static void HomeControllerReachabilityCallback(SCNetworkReachabilityRef reachabi
     [alert setNumberOfRows:1];
     [alert addTextFieldWithValue:@"http://" label:@""];
 
     [alert setNumberOfRows:1];
     [alert addTextFieldWithValue:@"http://" label:@""];
 
-    UITextInputTraits *traits = [[alert textField] textInputTraits];
+    NSObject<UITextInputTraits> *traits = [[alert textField] textInputTraits];
     [traits setAutocapitalizationType:UITextAutocapitalizationTypeNone];
     [traits setAutocorrectionType:UITextAutocorrectionTypeNo];
     [traits setKeyboardType:UIKeyboardTypeURL];
     [traits setAutocapitalizationType:UITextAutocapitalizationTypeNone];
     [traits setAutocorrectionType:UITextAutocorrectionTypeNo];
     [traits setKeyboardType:UIKeyboardTypeURL];
@@ -8809,12 +8075,12 @@ static void HomeControllerReachabilityCallback(SCNetworkReachabilityRef reachabi
 }
 
 - (void) refreshButtonClicked {
 }
 
 - (void) refreshButtonClicked {
-    if ([delegate_ requestUpdate])
+    if ([self.delegate requestUpdate])
         [self updateButtonsForEditingStatusAnimated:YES];
 }
 
 - (void) cancelButtonClicked {
         [self updateButtonsForEditingStatusAnimated:YES];
 }
 
 - (void) cancelButtonClicked {
-    [delegate_ cancelUpdate];
+    [self.delegate cancelUpdate];
 }
 
 - (void) editButtonClicked {
 }
 
 - (void) editButtonClicked {
@@ -8894,64 +8160,12 @@ static void HomeControllerReachabilityCallback(SCNetworkReachabilityRef reachabi
 @end
 /* }}} */
 
 @end
 /* }}} */
 
-@interface CYURLCache : SDURLCache {
-}
-
-@end
-
-@implementation CYURLCache
-
-- (void) logEvent:(NSString *)event forRequest:(NSURLRequest *)request {
-#if !ForRelease
-    if (false);
-    else if ([event isEqualToString:@"no-cache"])
-        event = @"!!!";
-    else if ([event isEqualToString:@"store"])
-        event = @">>>";
-    else if ([event isEqualToString:@"invalid"])
-        event = @"???";
-    else if ([event isEqualToString:@"memory"])
-        event = @"mem";
-    else if ([event isEqualToString:@"disk"])
-        event = @"ssd";
-    else if ([event isEqualToString:@"miss"])
-        event = @"---";
-
-    NSLog(@"%@: %@", event, [[request URL] absoluteString]);
-#endif
-}
-
-- (void) storeCachedResponse:(NSCachedURLResponse *)cached forRequest:(NSURLRequest *)request {
-    if (NSURLResponse *response = [cached response])
-        if (NSString *mime = [response MIMEType])
-            if ([mime isEqualToString:@"text/cache-manifest"]) {
-                NSURL *url([response URL]);
-
-#if !ForRelease
-                NSLog(@"###: %@", [url absoluteString]);
-#endif
-
-                @synchronized (HostConfig_) {
-                    [CachedURLs_ addObject:url];
-                }
-            }
-
-    [super storeCachedResponse:cached forRequest:request];
-}
-
-- (void) createDiskCachePath {
-    [super createDiskCachePath];
-    _root(chown([[self diskCachePath] UTF8String], 501, 501));
-}
-
-@end
-
-@interface Cydia : UIApplication <
+@interface Cydia : CyteApplication <
     ConfirmationControllerDelegate,
     DatabaseDelegate,
     CydiaDelegate
 > {
     ConfirmationControllerDelegate,
     DatabaseDelegate,
     CydiaDelegate
 > {
-    _H<UIWindow> window_;
+    _H<CyteWindow> window_;
     _H<CydiaTabBarController> tabbar_;
     _H<CyteTabBarController> emulated_;
     _H<AppCacheController> appcache_;
     _H<CydiaTabBarController> tabbar_;
     _H<CyteTabBarController> emulated_;
     _H<AppCacheController> appcache_;
@@ -8964,7 +8178,6 @@ static void HomeControllerReachabilityCallback(SCNetworkReachabilityRef reachabi
     _H<NSURL> starturl_;
 
     unsigned locked_;
     _H<NSURL> starturl_;
 
     unsigned locked_;
-    unsigned activity_;
 
     _H<StashController> stash_;
 
 
     _H<StashController> stash_;
 
@@ -9004,7 +8217,7 @@ static void HomeControllerReachabilityCallback(SCNetworkReachabilityRef reachabi
 }
 
 - (bool) requestUpdate {
 }
 
 - (bool) requestUpdate {
-    if (IsReachable("cydia.saurik.com")) {
+    if (CyteIsReachable("cydia.saurik.com")) {
         [self beginUpdate];
         return true;
     } else {
         [self beginUpdate];
         return true;
     } else {
@@ -9067,30 +8280,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 (!_root([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");
+}
 
 
-    _root(CydiaWriteSources());
+- (void) _saveConfig {
+    SaveConfig(database_);
 }
 
 // Navigation controller for the queuing badge.
 }
 
 // Navigation controller for the queuing badge.
@@ -9099,13 +8299,9 @@ static void HomeControllerReachabilityCallback(SCNetworkReachabilityRef reachabi
     return [controllers objectAtIndex:3];
 }
 
     return [controllers objectAtIndex:3];
 }
 
-- (void) unloadData {
-    [tabbar_ unloadData];
-}
-
 - (void) _updateData {
     [self _saveConfig];
 - (void) _updateData {
     [self _saveConfig];
-    [self unloadData];
+    [window_ unloadData];
 
     UINavigationController *navigation = [self queueNavigationController];
 
 
     UINavigationController *navigation = [self queueNavigationController];
 
@@ -9117,9 +8313,11 @@ 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]);
@@ -9132,7 +8330,7 @@ static void HomeControllerReachabilityCallback(SCNetworkReachabilityRef reachabi
     //  - We already auto-refreshed this launch.
     //  - Auto-refresh is disabled.
     //  - Cydia's server is not reachable
     //  - We already auto-refreshed this launch.
     //  - Auto-refresh is disabled.
     //  - Cydia's server is not reachable
-    if (recently || loaded_ || ManualRefresh || !IsReachable("cydia.saurik.com")) {
+    if (recently || loaded_ || ManualRefresh || !CyteIsReachable("cydia.saurik.com")) {
         // If we are cancelling, we need to make sure it knows it's already loaded.
         loaded_ = true;
 
         // If we are cancelling, we need to make sure it knows it's already loaded.
         loaded_ = true;
 
@@ -9141,14 +8339,14 @@ 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 {
@@ -9222,14 +8420,9 @@ _end
     if (emulated_ == nil)
         return;
 
     if (emulated_ == nil)
         return;
 
-    if ([window_ respondsToSelector:@selector(setRootViewController:)])
-        [window_ setRootViewController:tabbar_];
-    else {
-        [window_ addSubview:[tabbar_ view]];
-        [[emulated_ view] removeFromSuperview];
-    }
-
+    [window_ setRootViewController:tabbar_];
     emulated_ = nil;
     emulated_ = nil;
+
     [window_ setUserInteractionEnabled:YES];
 }
 
     [window_ setUserInteractionEnabled:YES];
 }
 
@@ -9296,12 +8489,10 @@ _end
     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 {
@@ -9383,14 +8574,7 @@ _end
 
 - (void) _uicache {
     _trace();
 
 - (void) _uicache {
     _trace();
-
-    if (UpgradeCydia_ && Finish_ > 0) {
-        setreugid(0, 0);
-        system("su -c /usr/bin/uicache mobile");
-    } else {
-        system("/usr/bin/uicache");
-    }
-
+    system("/usr/bin/uicache");
     _trace();
 }
 
     _trace();
 }
 
@@ -9414,25 +8598,6 @@ _end
     [self unlockSuspend];
 }
 
     [self unlockSuspend];
 }
 
-- (void) retainNetworkActivityIndicator {
-    if (activity_++ == 0)
-        [self setNetworkActivityIndicatorVisible:YES];
-
-#if TraceLogging
-    NSLog(@"retainNetworkActivityIndicator->%d", activity_);
-#endif
-}
-
-- (void) releaseNetworkActivityIndicator {
-    if (--activity_ == 0)
-        [self setNetworkActivityIndicatorVisible:NO];
-
-#if TraceLogging
-    NSLog(@"releaseNetworkActivityIndicator->%d", activity_);
-#endif
-
-}
-
 - (void) cancelAndClear:(bool)clear {
     @synchronized (self) {
         if (clear) {
 - (void) cancelAndClear:(bool)clear {
     @synchronized (self) {
         if (clear) {
@@ -9463,14 +8628,14 @@ _end
             @synchronized (self) {
                 for (Package *broken in (id) broken_) {
                     [broken remove];
             @synchronized (self) {
                 for (Package *broken in (id) broken_) {
                     [broken remove];
-                    NSString *id = [broken id];
-
-                    _root({
-                        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];
@@ -9505,7 +8670,7 @@ _end
     NSAutoreleasePool *pool([[NSAutoreleasePool alloc] init]);
 
     _trace();
     NSAutoreleasePool *pool([[NSAutoreleasePool alloc] init]);
 
     _trace();
-    _root(system([command UTF8String]));
+    system([command UTF8String]);
     _trace();
 
     [pool release];
     _trace();
 
     [pool release];
@@ -9565,7 +8730,7 @@ _end
         [super applicationSuspend];
 }
 
         [super applicationSuspend];
 }
 
-- (void) applicationSuspend:(__GSEvent *)event {
+- (void) applicationSuspend:(GSEventRef)event {
     if ([self isSafeToSuspend])
         [super applicationSuspend:event];
 }
     if ([self isSafeToSuspend])
         [super applicationSuspend:event];
 }
@@ -9673,7 +8838,7 @@ _end
             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];
@@ -9741,10 +8906,11 @@ _end
 }
 
 - (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];
 }
@@ -9756,15 +8922,15 @@ _end
 - (void) applicationDidEnterBackground:(UIApplication *)application {
     if (kCFCoreFoundationVersionNumber < 1000 && [self isSafeToSuspend])
         return [self terminateWithSuccess];
 - (void) applicationDidEnterBackground:(UIApplication *)application {
     if (kCFCoreFoundationVersionNumber < 1000 && [self isSafeToSuspend])
         return [self terminateWithSuccess];
+    Backgrounded_ = [NSDate date];
     [self saveState];
 }
 
 - (void) applicationWillEnterForeground:(UIApplication *)application {
     [self saveState];
 }
 
 - (void) applicationWillEnterForeground:(UIApplication *)application {
-    NSDate *closed = [Metadata_ objectForKey:@"LastClosed"];
-    if (closed == nil)
+    if (Backgrounded_ == nil)
         return;
 
         return;
 
-    NSTimeInterval interval([closed timeIntervalSinceNow]);
+    NSTimeInterval interval([Backgrounded_ timeIntervalSinceNow]);
 
     if (interval <= -(30*60)) {
         [tabbar_ setSelectedIndex:0];
 
     if (interval <= -(30*60)) {
         [tabbar_ setSelectedIndex:0];
@@ -9772,15 +8938,18 @@ _end
     }
 
     if (interval <= -(15*60)) {
     }
 
     if (interval <= -(15*60)) {
-        if (IsReachable("cydia.saurik.com")) {
+        if (CyteIsReachable("cydia.saurik.com")) {
             [tabbar_ beginUpdate];
             [appcache_ reloadURLWithCache:YES];
         }
     }
             [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");
@@ -9821,91 +8990,18 @@ _end
 - (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);
-}
-
-- (void) setupViewControllers {
-    tabbar_ = [[[CydiaTabBarController alloc] initWithDatabase:database_] autorelease];
-
-    NSMutableArray *items;
-    if (kCFCoreFoundationVersionNumber < 800) {
-        items = [NSMutableArray arrayWithObjects:
-            [[[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:
-            [[[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];
-    }
-
-    NSMutableArray *controllers([NSMutableArray array]);
-    for (UITabBarItem *item in items) {
-        UINavigationController *controller([[[UINavigationController alloc] init] autorelease]);
-        [controller setTabBarItem:item];
-        [controllers addObject:controller];
-    }
-    [tabbar_ setViewControllers:controllers];
-
-    [tabbar_ setUpdateDelegate:self];
-}
-
-- (void) _sendMemoryWarningNotification {
-    if (kCFCoreFoundationVersionNumber < kCFCoreFoundationVersionNumber_iPhoneOS_3_0) // XXX: maybe 4_0?
-        [[NSNotificationCenter defaultCenter] postNotificationName:@"UIApplicationMemoryWarningNotification" object:[UIApplication sharedApplication]];
-    else
-        [[NSNotificationCenter defaultCenter] postNotificationName:@"UIApplicationDidReceiveMemoryWarningNotification" object:[UIApplication sharedApplication]];
-}
-
-- (void) _sendMemoryWarningNotifications {
-    while (true) {
-        [self performSelectorOnMainThread:@selector(_sendMemoryWarningNotification) withObject:nil waitUntilDone:NO];
-        sleep(2);
-        //usleep(2000000);
-    }
-}
-
-- (void) applicationDidReceiveMemoryWarning:(UIApplication *)application {
-    NSLog(@"--");
-    [[NSURLCache sharedURLCache] removeAllCachedResponses];
+    [self reloadSpringBoard];
 }
 
 - (void) applicationDidFinishLaunching:(id)unused {
 }
 
 - (void) applicationDidFinishLaunching:(id)unused {
-    //[NSThread detachNewThreadSelector:@selector(_sendMemoryWarningNotifications) toTarget:self withObject:nil];
-
-_trace();
-    if ([self respondsToSelector:@selector(setApplicationSupportsShakeToEdit:)])
-        [self setApplicationSupportsShakeToEdit:NO];
-
-    @synchronized (HostConfig_) {
-        [BridgedHosts_ addObject:[[NSURL URLWithString:CydiaURL(@"")] host]];
-    }
-
-    [NSURLCache setSharedURLCache:[[[CYURLCache alloc]
-        initWithMemoryCapacity:524288
-        diskCapacity:10485760
-        diskPath:Cache("SDURLCache")
-    ] autorelease]];
+    [super applicationDidFinishLaunching:unused];
+    [CyteWebViewController _initialize];
 
 
-    [CydiaWebViewController _initialize];
+    [BridgedHosts_ addObject:[[NSURL URLWithString:CydiaURL(@"")] host]];
 
     [NSURLProtocol registerClass:[CydiaURLProtocol class]];
 
 
     [NSURLProtocol registerClass:[CydiaURLProtocol class]];
 
@@ -9926,11 +9022,14 @@ _trace();
     appcache_ = [[[AppCacheController alloc] initWithURL:[NSURL URLWithString:[NSString stringWithFormat:@"%@/appcache/", UI_]]] autorelease];
     [appcache_ reloadData];
 
     appcache_ = [[[AppCacheController alloc] initWithURL:[NSURL URLWithString:[NSString stringWithFormat:@"%@/appcache/", UI_]]] autorelease];
     [appcache_ reloadData];
 
-    window_ = [[[UIWindow alloc] initWithFrame:[[UIScreen mainScreen] bounds]] autorelease];
+    window_ = [[[CyteWindow alloc] initWithFrame:[[UIScreen mainScreen] bounds]] autorelease];
     [window_ orderFront:self];
     [window_ makeKey:self];
     [window_ setHidden:NO];
 
     [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:
@@ -9961,15 +9060,27 @@ _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];
     database_ = [Database sharedInstance];
     [database_ setDelegate:self];
 
     [window_ setUserInteractionEnabled:NO];
-    [self setupViewControllers];
+
+    tabbar_ = [[[CydiaTabBarController alloc] initWithDatabase:database_] autorelease];
+
+    [tabbar_ addViewControllers:nil,
+        @"Cydia", @"home.png", @"home7.png", @"home7s.png",
+        UCLocalize("SOURCES"), @"install.png", @"install7.png", @"install7s.png",
+        UCLocalize("CHANGES"), @"changes.png", @"changes7.png", @"changes7s.png",
+        UCLocalize("INSTALLED"), @"manage.png", @"manage7.png", @"manage7s.png",
+        UCLocalize("SEARCH"), @"search.png", @"search7.png", @"search7s.png",
+    nil];
+
+    [tabbar_ setUpdateDelegate:self];
 
     CydiaLoadingViewController *loading([[[CydiaLoadingViewController alloc] init] autorelease]);
     UINavigationController *navigation([[[UINavigationController alloc] init] autorelease]);
 
     CydiaLoadingViewController *loading([[[CydiaLoadingViewController alloc] init] autorelease]);
     UINavigationController *navigation([[[UINavigationController alloc] init] autorelease]);
@@ -9982,10 +9093,7 @@ _trace();
     if ([emulated_ respondsToSelector:@selector(concealTabBarSelection)])
         [emulated_ concealTabBarSelection];
 
     if ([emulated_ respondsToSelector:@selector(concealTabBarSelection)])
         [emulated_ concealTabBarSelection];
 
-    if ([window_ respondsToSelector:@selector(setRootViewController:)])
-        [window_ setRootViewController:emulated_];
-    else
-        [window_ addSubview:[emulated_ view]];
+    [window_ setRootViewController:emulated_];
 
     [self performSelector:@selector(loadData) withObject:nil afterDelay:0];
 _trace();
 
     [self performSelector:@selector(loadData) withObject:nil afterDelay:0];
 _trace();
@@ -10011,8 +9119,10 @@ _trace();
     [self refreshIfPossible];
     [self disemulate];
 
     [self refreshIfPossible];
     [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];
 
@@ -10021,7 +9131,7 @@ _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 (interval <= -(30*60))
     if (valid && closed != nil) {
         NSTimeInterval interval([closed timeIntervalSinceNow]);
         if (interval <= -(30*60))
@@ -10076,6 +9186,11 @@ _trace();
 }
 
 - (void) showActionSheet:(UIActionSheet *)sheet fromItem:(UIBarButtonItem *)item {
 }
 
 - (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 {
@@ -10115,159 +9230,76 @@ id Dealloc_(id self, SEL selector) {
     return object;
 }*/
 
     return object;
 }*/
 
-Class $NSURLConnection;
-
-MSHook(id, NSURLConnection$init$, NSURLConnection *self, SEL _cmd, NSURLRequest *request, id delegate, BOOL usesCache, int64_t maxContentLength, BOOL startImmediately, NSDictionary *connectionProperties) {
-    NSMutableURLRequest *copy([[request mutableCopy] autorelease]);
-
-    NSURL *url([copy URL]);
-
-    NSString *host([url host]);
-    NSString *scheme([[url scheme] lowercaseString]);
-
-    NSString *compound([NSString stringWithFormat:@"%@:%@", scheme, host]);
-
-    @synchronized (HostConfig_) {
-        if ([copy respondsToSelector:@selector(setHTTPShouldUsePipelining:)])
-            if ([PipelinedHosts_ containsObject:host] || [PipelinedHosts_ containsObject:compound])
-                [copy setHTTPShouldUsePipelining:YES];
-
-        if (NSString *control = [copy valueForHTTPHeaderField:@"Cache-Control"])
-            if ([control isEqualToString:@"max-age=0"])
-                if ([CachedURLs_ containsObject:url]) {
-#if !ForRelease
-                    NSLog(@"~~~: %@", url);
-#endif
-
-                    [copy setCachePolicy:NSURLRequestReturnCacheDataDontLoad];
-
-                    [copy setValue:nil forHTTPHeaderField:@"Cache-Control"];
-                    [copy setValue:nil forHTTPHeaderField:@"If-Modified-Since"];
-                    [copy setValue:nil forHTTPHeaderField:@"If-None-Match"];
-                }
-    }
-
-    if ((self = _NSURLConnection$init$(self, _cmd, copy, delegate, usesCache, maxContentLength, startImmediately, connectionProperties)) != nil) {
-    } return self;
-}
-
-Class $WAKWindow;
-
-static CGSize $WAKWindow$screenSize(WAKWindow *self, SEL _cmd) {
-    CGSize size([[UIScreen mainScreen] bounds].size);
-    /*if ([$WAKWindow respondsToSelector:@selector(hasLandscapeOrientation)])
-        if ([$WAKWindow hasLandscapeOrientation])
-            std::swap(size.width, size.height);*/
-    return size;
+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];
 }
 
 }
 
-Class $NSUserDefaults;
-
-MSHook(id, NSUserDefaults$objectForKey$, NSUserDefaults *self, SEL _cmd, NSString *key) {
-    if ([key respondsToSelector:@selector(isEqualToString:)] && [key isEqualToString:@"WebKitLocalStorageDatabasePathPreferenceKey"])
-        return Cache("LocalStorage");
-    return _NSUserDefaults$objectForKey$(self, _cmd, key);
-}
+int main_store(int, char *argv[]);
 
 int main(int argc, char *argv[]) {
 
 int main(int argc, char *argv[]) {
-    setreugid(501, 501);
+#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();
 
+    CyteInitialize(@"Cydia", Cydia_);
     UpdateExternalStatus(0);
 
     UpdateExternalStatus(0);
 
-    UIScreen *screen([UIScreen mainScreen]);
-    if ([screen respondsToSelector:@selector(scale)])
-        ScreenScale_ = [screen scale];
-    else
-        ScreenScale_ = 1;
-
-    UIDevice *device([UIDevice currentDevice]);
-    if ([device respondsToSelector:@selector(userInterfaceIdiom)]) {
-        UIUserInterfaceIdiom idiom([device userInterfaceIdiom]);
-        if (idiom == UIUserInterfaceIdiomPad)
-            IsWildcat_ = true;
-    }
-
-    Idiom_ = IsWildcat_ ? @"ipad" : @"iphone";
-
-    Pcre pattern("^([0-9]+\\.[0-9]+)");
-
-    if (pattern([device systemVersion]))
-        Firmware_ = pattern[1];
-    if (pattern(Cydia_))
-        Major_ = pattern[1];
-
     SessionData_ = [NSMutableDictionary dictionaryWithCapacity:4];
     SessionData_ = [NSMutableDictionary dictionaryWithCapacity:4];
+    BridgedHosts_ = [NSMutableSet setWithCapacity:4];
+    InsecureHosts_ = [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];
-    }
-
-    NSString *ui(@"ui/ios");
-    if (Idiom_ != nil)
-        ui = [ui stringByAppendingString:[NSString stringWithFormat:@"~%@", Idiom_]];
-    ui = [ui stringByAppendingString:[NSString stringWithFormat:@"/%@", Major_]];
-    UI_ = CydiaURL(ui);
-
+    UI_ = CydiaURL([NSString stringWithFormat:@"ui/ios~%@/1.1", IsWildcat_ ? @"ipad" : @"iphone"]);
     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))));
 
-    /* Library Hacks {{{ */
-    class_addMethod(objc_getClass("DOMNodeList"), @selector(countByEnumeratingWithState:objects:count:), (IMP) &DOMNodeList$countByEnumeratingWithState$objects$count$, "I20@0:4^{NSFastEnumerationState}8^@12I16");
-
-    $WAKWindow = objc_getClass("WAKWindow");
-    if ($WAKWindow != NULL)
-        if (Method method = class_getInstanceMethod($WAKWindow, @selector(screenSize)))
-            method_setImplementation(method, (IMP) &$WAKWindow$screenSize);
-
-    $NSURLConnection = objc_getClass("NSURLConnection");
-    Method NSURLConnection$init$(class_getInstanceMethod($NSURLConnection, @selector(_initWithRequest:delegate:usesCache:maxContentLength:startImmediately:connectionProperties:)));
-    if (NSURLConnection$init$ != NULL) {
-        _NSURLConnection$init$ = reinterpret_cast<id (*)(NSURLConnection *, SEL, NSURLRequest *, id, BOOL, int64_t, BOOL, NSDictionary *)>(method_getImplementation(NSURLConnection$init$));
-        method_setImplementation(NSURLConnection$init$, reinterpret_cast<IMP>(&$NSURLConnection$init$));
-    }
-
-    $NSUserDefaults = objc_getClass("NSUserDefaults");
-    Method NSUserDefaults$objectForKey$(class_getInstanceMethod($NSUserDefaults, @selector(objectForKey:)));
-    if (NSUserDefaults$objectForKey$ != NULL) {
-        _NSUserDefaults$objectForKey$ = reinterpret_cast<id (*)(NSUserDefaults *, SEL, NSString *)>(method_getImplementation(NSUserDefaults$objectForKey$));
-        method_setImplementation(NSUserDefaults$objectForKey$, reinterpret_cast<IMP>(&$NSUserDefaults$objectForKey$));
-    }
-    /* }}} */
     /* Set Locale {{{ */
     Locale_ = CFLocaleCopyCurrent();
     Languages_ = [NSLocale preferredLanguages];
 
     /* Set Locale {{{ */
     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 *locale : Languages_) {
+            auto components([NSLocale componentsFromLocaleIdentifier:locale]);
+            NSString *language([components objectForKey:(id)kCFLocaleLanguageCode]);
+            if (NSString *script = [components objectForKey:(id)kCFLocaleScriptCode])
+                language = [NSString stringWithFormat:@"%@-%@", language, script];
+            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 {
     /* }}} */
     /* Index Collation {{{ */
     if (Class $UILocalizedIndexedCollation = objc_getClass("UILocalizedIndexedCollation")) { @try {
@@ -10321,36 +9353,11 @@ int main(int argc, char *argv[]) {
     }
     /* }}} */
 
     }
     /* }}} */
 
-    apr_app_initialize(&argc, const_cast<const char * const **>(&argv), NULL);
-
-    /* Parse Arguments {{{ */
-    bool substrate(false);
-
-    if (argc != 0) {
-        char **args(argv);
-        int arge(1);
-
-        for (int argi(1); argi != argc; ++argi)
-            if (strcmp(argv[argi], "--") == 0) {
-                arge = argi;
-                argv[argi] = argv[0];
-                argv += argi;
-                argc -= argi;
-                break;
-            }
-
-        for (int argi(1); argi != arge; ++argi)
-            if (strcmp(args[argi], "--substrate") == 0)
-                substrate = true;
-            else
-                fprintf(stderr, "unknown argument: %s\n", args[argi]);
-    }
-    /* }}} */
-
     App_ = [[NSBundle mainBundle] bundlePath];
     Advanced_ = YES;
 
     Cache_ = [[NSString stringWithFormat:@"%@/Library/Caches/com.saurik.Cydia", @"/var/mobile"] retain];
     App_ = [[NSBundle mainBundle] bundlePath];
     Advanced_ = YES;
 
     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;
@@ -10362,6 +9369,7 @@ int main(int argc, char *argv[]) {
 
     void *gestalt(dlopen("/usr/lib/libMobileGestalt.dylib", RTLD_GLOBAL | RTLD_LAZY));
     $MGCopyAnswer = reinterpret_cast<CFStringRef (*)(CFStringRef)>(dlsym(gestalt, "MGCopyAnswer"));
 
     void *gestalt(dlopen("/usr/lib/libMobileGestalt.dylib", RTLD_GLOBAL | RTLD_LAZY));
     $MGCopyAnswer = reinterpret_cast<CFStringRef (*)(CFStringRef)>(dlsym(gestalt, "MGCopyAnswer"));
+    UniqueID_ = UniqueIdentifier([UIDevice currentDevice]);
 
     /* System Information {{{ */
     size_t size;
 
     /* System Information {{{ */
     size_t size;
@@ -10375,88 +9383,50 @@ int main(int argc, char *argv[]) {
         if (sysctlbyname("kern.maxproc", NULL, NULL, &maxproc, sizeof(maxproc)) == -1)
             perror("sysctlbyname(\"kern.maxproc\", #)");
     }
         if (sysctlbyname("kern.maxproc", NULL, NULL, &maxproc, sizeof(maxproc)) == -1)
             perror("sysctlbyname(\"kern.maxproc\", #)");
     }
-
-    sysctlbyname("kern.osversion", NULL, &size, NULL, 0);
-    char *osversion = new char[size];
-    if (sysctlbyname("kern.osversion", osversion, &size, NULL, 0) == -1)
-        perror("sysctlbyname(\"kern.osversion\", ?)");
-    else
-        System_ = [NSString stringWithUTF8String:osversion];
-
-    sysctlbyname("hw.machine", NULL, &size, NULL, 0);
-    char *machine = new char[size];
-    if (sysctlbyname("hw.machine", machine, &size, NULL, 0) == -1)
-        perror("sysctlbyname(\"hw.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);
-
-    UniqueID_ = UniqueIdentifier(device);
-
-    if (NSDictionary *info = [NSDictionary dictionaryWithContentsOfFile:@"/Applications/MobileSafari.app/Info.plist"]) {
-        Product_ = [info objectForKey:@"SafariProductVersion"];
-        Safari_ = [info objectForKey:@"CFBundleVersion"];
-    }
-
-    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];
-
-    UserAgent_ = agent;
     /* }}} */
     /* Load Database {{{ */
     /* }}} */
     /* 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) {
@@ -10466,68 +9436,36 @@ 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;
-    /* }}} */
-
-    _root(CydiaWriteSources());
-
-    _trace();
-    mkdir("/var/mobile/Library/Cydia", 0755);
-    MetaFile_.Open("/var/mobile/Library/Cydia/metadata.cb0");
-    _trace();
-
-    if (Packages_ != nil) {
-        bool fail(false);
-        CFDictionaryApplyFunction((CFDictionaryRef) Packages_, &PackageImport, &fail);
-        _trace();
+    broken = nil;
 
 
-        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)
     if (kCFCoreFoundationVersionNumber > 1000)
-        _root(system([[NSString stringWithFormat:@"/usr/libexec/cydia/setnsfpn /var/lib"] UTF8String]));
+        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();
-        _root(system("/usr/libexec/cydia/firmware.sh"));
+        system("/usr/libexec/cydia/cydo /usr/libexec/cydia/firmware.sh");
         _trace();
     }
 
         _trace();
     }
 
@@ -10538,27 +9476,48 @@ int main(int argc, char *argv[]) {
             _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);
 
+    int64_t usermem(0);
+    size = sizeof(usermem);
+    if (sysctlbyname("hw.usermem", &usermem, &size, NULL, 0) == -1)
+        usermem = 0;
     _config->Set("Acquire::http::MaxParallel", usermem >= 384 * 1024 * 1024 ? 16 : 3);
 
     _config->Set("Acquire::http::MaxParallel", usermem >= 384 * 1024 * 1024 ? 16 : 3);
 
-    mkdir([Cache_ UTF8String], 0755);
     mkdir([Cache("archives") UTF8String], 0755);
     mkdir([Cache("archives/partial") UTF8String], 0755);
     _config->Set("Dir::Cache", [Cache_ UTF8String]);
 
     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]);
     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();
@@ -10582,14 +9541,8 @@ int main(int argc, char *argv[]) {
     //UIKeyboardDisableAutomaticAppearance();
     /* }}} */
 
     //UIKeyboardDisableAutomaticAppearance();
     /* }}} */
 
-    _root({
-        chown([Cache("ApplicationCache.db") UTF8String], 501, 501);
-        chown([Cache("Cache.db") UTF8String], 501, 501);
-        chown([Cache("Cache.db-shm") UTF8String], 501, 501);
-        chown([Cache("Cache.db-wal") UTF8String], 501, 501);
-    });
-
     $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));