]> git.saurik.com Git - cydia.git/blobdiff - Cydia.mm
Commit (chpwn): good-bye-uiactionsheet.patch
[cydia.git] / Cydia.mm
index 2784d00b592c0520b164e6462d02079a5b62cfa4..f792200194afb041200d02057256f2b9cb03becd 100644 (file)
--- a/Cydia.mm
+++ b/Cydia.mm
@@ -1,7 +1,8 @@
 /* Cydia - iPhone UIKit Front-End for Debian APT
- * Copyright (C) 2008  Jay Freeman (saurik)
+ * Copyright (C) 2008-2010  Jay Freeman (saurik)
 */
 
+/* Modified BSD License {{{ */
 /*
  *        Redistribution and use in source and binary
  * forms, with or without modification, are permitted
  * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
  * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 */
+/* }}} */
 
 // XXX: wtf/FastMalloc.h... wtf?
 #define USE_SYSTEM_MALLOC 1
 
 /* #include Directives {{{ */
-#import "UICaboodle.h"
+#import "UICaboodle/UCPlatform.h"
+#import "UICaboodle/UCLocalize.h"
 
-#include <objc/message.h>
 #include <objc/objc.h>
 #include <objc/runtime.h>
 
 #include <GraphicsServices/GraphicsServices.h>
 #include <Foundation/Foundation.h>
 
-#import <QuartzCore/CALayer.h>
+#if 0
+#define DEPLOYMENT_TARGET_MACOSX 1
+#define CF_BUILDING_CF 1
+#include <CoreFoundation/CFInternal.h>
+#endif
+
+#include <CoreFoundation/CFPriv.h>
+#include <CoreFoundation/CFUniChar.h>
+
 #import <UIKit/UIKit.h>
 
 #include <WebCore/WebCoreThread.h>
 #import <WebKit/WebDefaultUIKitDelegate.h>
 
+#include <algorithm>
 #include <iomanip>
 #include <sstream>
 #include <string>
 
 #include <ext/stdio_filebuf.h>
 
+#undef ABS
+
 #include <apt-pkg/acquire.h>
 #include <apt-pkg/acquire-item.h>
 #include <apt-pkg/algorithms.h>
@@ -77,6 +90,7 @@
 #include <apt-pkg/sourcelist.h>
 #include <apt-pkg/sptr.h>
 #include <apt-pkg/strutl.h>
+#include <apt-pkg/tagfile.h>
 
 #include <apr-1/apr_pools.h>
 
@@ -102,25 +116,16 @@ extern "C" {
 
 #include <ext/hash_map>
 
-#import "BrowserView.h"
-#import "ResetView.h"
+#import "UICaboodle/BrowserView.h"
+#import "UICaboodle/ResetView.h"
 
 #import "substrate.h"
 /* }}} */
 
-//#define _finline __attribute__((force_inline))
-#define _finline inline
-
+/* Profiler {{{ */
 struct timeval _ltv;
 bool _itv;
 
-#define _limit(count) do { \
-    static size_t _count(0); \
-    if (++_count == count) \
-        exit(0); \
-} while (false)
-
-/* Profiler {{{ */
 #define _timestamp ({ \
     struct timeval tv; \
     gettimeofday(&tv, NULL); \
@@ -186,48 +191,11 @@ void PrintTimes() {
 
 #define _end }
 /* }}} */
-/* Objective-C Handle<> {{{ */
-template <typename Type_>
-class _H {
-    typedef _H<Type_> This_;
-
-  private:
-    Type_ *value_;
-
-    _finline void Retain_() {
-        if (value_ != nil)
-            [value_ retain];
-    }
-
-    _finline void Clear_() {
-        if (value_ != nil)
-            [value_ release];
-    }
-
-  public:
-    _finline _H(Type_ *value = NULL, bool mended = false) :
-        value_(value)
-    {
-        if (!mended)
-            Retain_();
-    }
-
-    _finline ~_H() {
-        Clear_();
-    }
-
-    _finline This_ &operator =(Type_ *value) {
-        if (value_ != value) {
-            Clear_();
-            value_ = value;
-            Retain_();
-        } return this;
-    }
-};
-/* }}} */
 
 #define _pooled _H<NSAutoreleasePool> _pool([[NSAutoreleasePool alloc] init], true);
 
+static const NSUInteger UIViewAutoresizingFlexibleBoth(UIViewAutoresizingFlexibleWidth | UIViewAutoresizingFlexibleHeight);
+
 void NSLogPoint(const char *fix, const CGPoint &point) {
     NSLog(@"%s(%g,%g)", fix, point.x, point.y);
 }
@@ -236,6 +204,17 @@ void NSLogRect(const char *fix, const CGRect &rect) {
     NSLog(@"%s(%g,%g)+(%g,%g)", fix, rect.origin.x, rect.origin.y, rect.size.width, rect.size.height);
 }
 
+static _finline NSString *CydiaURL(NSString *path) {
+    char page[25];
+    page[0] = 'h'; page[1] = 't'; page[2] = 't'; page[3] = 'p'; page[4] = ':';
+    page[5] = '/'; page[6] = '/'; page[7] = 'c'; page[8] = 'y'; page[9] = 'd';
+    page[10] = 'i'; page[11] = 'a'; page[12] = '.'; page[13] = 's'; page[14] = 'a';
+    page[15] = 'u'; page[16] = 'r'; page[17] = 'i'; page[18] = 'k'; page[19] = '.';
+    page[20] = 'c'; page[21] = 'o'; page[22] = 'm'; page[23] = '/'; page[24] = '\0';
+    return [[NSString stringWithUTF8String:page] stringByAppendingString:path];
+}
+
+/* [NSObject yieldToSelector:(withObject:)] {{{*/
 @interface NSObject (Cydia)
 - (id) yieldToSelector:(SEL)selector withObject:(id)object;
 - (id) yieldToSelector:(SEL)selector;
@@ -254,8 +233,9 @@ void NSLogRect(const char *fix, const CGRect &rect) {
     /* XXX: deal with exceptions */
     id value([self performSelector:selector withObject:object]);
 
+    NSMethodSignature *signature([self methodSignatureForSelector:selector]);
     [context removeAllObjects];
-    if (value != nil)
+    if ([signature methodReturnLength] != 0 && value != nil)
         [context addObject:value];
 
     stopped = true;
@@ -299,30 +279,49 @@ void NSLogRect(const char *fix, const CGRect &rect) {
 }
 
 @end
+/* }}} */
 
-/* NSForcedOrderingSearch doesn't work on the iPhone */
-static const NSStringCompareOptions MatchCompareOptions_ = NSLiteralSearch | NSCaseInsensitiveSearch;
-static const NSStringCompareOptions BaseCompareOptions_ = NSNumericSearch | NSDiacriticInsensitiveSearch | NSWidthInsensitiveSearch;
-static const NSStringCompareOptions ForcedCompareOptions_ = BaseCompareOptions_;
-static const NSStringCompareOptions LaxCompareOptions_ = BaseCompareOptions_ | NSCaseInsensitiveSearch;
-
-/* iPhoneOS 2.0 Compatibility {{{ */
-#ifdef __OBJC2__
-@interface UITextView (iPhoneOS)
-- (void) setTextSize:(float)size;
+@interface CYActionSheet : UIAlertView {
+    unsigned button_;
+}
+
+- (int) yieldToPopupAlertAnimated:(BOOL)animated;
 @end
 
-@implementation UITextView (iPhoneOS)
+@implementation CYActionSheet
+
+- (id) initWithTitle:(NSString *)title buttons:(NSArray *)buttons defaultButtonIndex:(int)index {
+    if ((self = [super init])) {
+               [self setTitle:title];
+               [self setDelegate:self];
+               for (NSString *button in buttons) [self addButtonWithTitle:button];
+               [self setCancelButtonIndex:index];
+    } return self;
+}
+
+- (void) alertView:(UIAlertView *)alertView clickedButtonAtIndex:(NSInteger)buttonIndex {
+    button_ = buttonIndex + 1;
+}
+
+- (void) dismiss {
+       [self dismissWithClickedButtonIndex:-1 animated:YES];
+}
 
-- (void) setTextSize:(float)size {
-    [self setFont:[[self font] fontWithSize:size]];
+- (int) yieldToPopupAlertAnimated:(BOOL)animated {
+    button_ = 0;
+    [self show];
+    NSRunLoop *loop([NSRunLoop currentRunLoop]);
+    NSDate *future([NSDate distantFuture]);
+    while (button_ == 0 && [loop runMode:NSDefaultRunLoopMode beforeDate:future]);
+    return button_;
 }
 
 @end
-#endif
-/* }}} */
 
-extern NSString * const kCAFilterNearest;
+/* NSForcedOrderingSearch doesn't work on the iPhone */
+static const NSStringCompareOptions MatchCompareOptions_ = NSLiteralSearch | NSCaseInsensitiveSearch;
+static const NSStringCompareOptions LaxCompareOptions_ = NSNumericSearch | NSDiacriticInsensitiveSearch | NSWidthInsensitiveSearch | NSCaseInsensitiveSearch;
+static const CFStringCompareFlags LaxCompareFlags_ = kCFCompareCaseInsensitive | kCFCompareNonliteral | kCFCompareLocalized | kCFCompareNumerically | kCFCompareWidthInsensitive | kCFCompareForcedOrdering;
 
 /* Information Dictionaries {{{ */
 @interface NSMutableArray (Cydia)
@@ -344,8 +343,7 @@ extern NSString * const kCAFilterNearest;
 @implementation NSMutableDictionary (Cydia)
 
 - (void) addInfoDictionary:(NSDictionary *)info {
-    NSString *bundle = [info objectForKey:@"CFBundleIdentifier"];
-    [self setObject:info forKey:bundle];
+    [self setObject:info forKey:[info objectForKey:@"CFBundleIdentifier"]];
 }
 
 @end
@@ -373,10 +371,14 @@ extern NSString * const kCAFilterNearest;
 
 - (void) popSubview:(UIView *)view {
     UITransitionView *transition([[[PopTransitionView alloc] initWithFrame:[self bounds]] autorelease]);
-    [transition setDelegate:transition];
+    [transition setAutoresizingMask:(UIViewAutoresizingFlexibleWidth | UIViewAutoresizingFlexibleHeight)];
     [self addSubview:transition];
 
-    UIView *blank = [[[UIView alloc] initWithFrame:[transition bounds]] autorelease];
+    [transition setDelegate:transition];
+
+    UIView *blank([[[UIView alloc] initWithFrame:[transition bounds]] autorelease]);
+    [blank setAutoresizingMask:(UIViewAutoresizingFlexibleWidth | UIViewAutoresizingFlexibleHeight)];
+
     [transition transition:UITransitionNone toView:blank];
     [transition transition:UITransitionPushFromBottom toView:view];
 }
@@ -387,18 +389,25 @@ extern NSString * const kCAFilterNearest;
 #define lprintf(args...) fprintf(stderr, args)
 
 #define ForRelease 0
+#define TraceLogging (1 && !ForRelease)
+#define HistogramInsertionSort (0 && !ForRelease)
+#define ProfileTimes (0 && !ForRelease)
 #define ForSaurik (0 && !ForRelease)
-#define LogBrowser (1 && !ForRelease)
+#define LogBrowser (0 && !ForRelease)
 #define TrackResize (0 && !ForRelease)
-#define ManualRefresh (1 && !ForRelease)
+#define ManualRefresh (0 && !ForRelease)
 #define ShowInternals (0 && !ForRelease)
 #define IgnoreInstall (0 && !ForRelease)
 #define RecycleWebViews 0
+#define RecyclePackageViews (1 && ForRelease)
 #define AlwaysReload (1 && !ForRelease)
 
-#if ForRelease
+#if !TraceLogging
 #undef _trace
 #define _trace(args...)
+#endif
+
+#if !ProfileTimes
 #undef _profile
 #define _profile(name) {
 #undef _end
@@ -407,9 +416,11 @@ extern NSString * const kCAFilterNearest;
 #endif
 
 /* Radix Sort {{{ */
+typedef uint32_t (*SKRadixFunction)(id, void *);
+
 @interface NSMutableArray (Radix)
 - (void) radixSortUsingSelector:(SEL)selector withObject:(id)object;
-- (void) radixSortUsingFunction:(uint32_t (*)(id, void *))function withArgument:(void *)argument;
+- (void) radixSortUsingFunction:(SKRadixFunction)function withContext:(void *)argument;
 @end
 
 struct RadixItem_ {
@@ -469,11 +480,22 @@ static void RadixSort_(NSMutableArray *self, size_t count, struct RadixItem_ *sw
 @implementation NSMutableArray (Radix)
 
 - (void) radixSortUsingSelector:(SEL)selector withObject:(id)object {
+    size_t count([self count]);
+    if (count == 0)
+        return;
+
+#if 0
     NSInvocation *invocation([NSInvocation invocationWithMethodSignature:[NSMethodSignature signatureWithObjCTypes:"L12@0:4@8"]]);
     [invocation setSelector:selector];
     [invocation setArgument:&object atIndex:2];
+#else
+    /* XXX: this is an unsafe optimization of doomy hell */
+    Method method(class_getInstanceMethod([[self objectAtIndex:0] class], selector));
+    _assert(method != NULL);
+    uint32_t (*imp)(id, SEL, id) = reinterpret_cast<uint32_t (*)(id, SEL, id)>(method_getImplementation(method));
+    _assert(imp != NULL);
+#endif
 
-    size_t count([self count]);
     struct RadixItem_ *swap(new RadixItem_[count * 2]);
 
     for (size_t i(0); i != count; ++i) {
@@ -481,16 +503,20 @@ static void RadixSort_(NSMutableArray *self, size_t count, struct RadixItem_ *sw
         item.index = i;
 
         id object([self objectAtIndex:i]);
-        [invocation setTarget:object];
 
+#if 0
+        [invocation setTarget:object];
         [invocation invoke];
         [invocation getReturnValue:&item.key];
+#else
+        item.key = imp(object, selector, object);
+#endif
     }
 
     RadixSort_(self, count, swap);
 }
 
-- (void) radixSortUsingFunction:(uint32_t (*)(id, void *))function withArgument:(void *)argument {
+- (void) radixSortUsingFunction:(SKRadixFunction)function withContext:(void *)argument {
     size_t count([self count]);
     struct RadixItem_ *swap(new RadixItem_[count * 2]);
 
@@ -506,6 +532,77 @@ static void RadixSort_(NSMutableArray *self, size_t count, struct RadixItem_ *sw
 }
 
 @end
+/* }}} */
+/* 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) {
+    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;
+}
+
+void CFArrayInsertionSortValues(CFMutableArrayRef array, CFRange range, CFComparatorFunction comparator, void *context) {
+    if (range.length == 0)
+        return;
+    const void **values(new const void *[range.length]);
+    CFArrayGetValues(array, range, values);
+
+#if HistogramInsertionSort
+    uint32_t total(0), *offsets(new uint32_t[range.length]);
+#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);
+        while (comparator(value, values[correct - 1], context) == kCFCompareLessThan)
+            if (--correct == 0)
+                break;
+        if (correct != index) {
+            size_t offset(index - correct);
+#if HistogramInsertionSort
+            total += offset;
+            ++offsets[offset];
+            if (offset > 10)
+                NSLog(@"Heavy Insertion Displacement: %u = %@", offset, value);
+#endif
+            memmove(values + correct + 1, values + correct, sizeof(const void *) * offset);
+            values[correct] = value;
+        }
+    }
+
+    CFArrayReplaceValues(array, range, values, range.length);
+    delete [] values;
+
+#if HistogramInsertionSort
+    for (CFIndex 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);
+    delete [] offsets;
+#endif
+}
+
 /* }}} */
 
 /* Apple Bug Fixes {{{ */
@@ -536,14 +633,18 @@ static void RadixSort_(NSMutableArray *self, size_t count, struct RadixItem_ *sw
 @end
 /* }}} */
 
-typedef enum {
-    kUIControlEventMouseDown = 1 << 0,
-    kUIControlEventMouseMovedInside = 1 << 2, // mouse moved inside control target
-    kUIControlEventMouseMovedOutside = 1 << 3, // mouse moved outside control target
-    kUIControlEventMouseUpInside = 1 << 6, // mouse up inside control target
-    kUIControlEventMouseUpOutside = 1 << 7, // mouse up outside control target
-    kUIControlAllEvents = (kUIControlEventMouseDown | kUIControlEventMouseMovedInside | kUIControlEventMouseMovedOutside | kUIControlEventMouseUpInside | kUIControlEventMouseUpOutside)
-} UIControlEventMasks;
+NSUInteger WebScriptObject$countByEnumeratingWithState$objects$count$(WebScriptObject *self, SEL sel, NSFastEnumerationState *state, id *objects, NSUInteger count) {
+    size_t length([self count] - state->state);
+    if (length <= 0)
+        return 0;
+    else if (length > count)
+        length = count;
+    for (size_t i(0); i != length; ++i)
+        objects[i] = [self objectAtIndex:state->state++];
+    state->itemsPtr = objects;
+    state->mutationsPtr = (unsigned long *) self;
+    return length;
+}
 
 NSUInteger DOMNodeList$countByEnumeratingWithState$objects$count$(DOMNodeList *self, SEL sel, NSFastEnumerationState *state, id *objects, NSUInteger count) {
     size_t length([self length] - state->state);
@@ -560,9 +661,9 @@ NSUInteger DOMNodeList$countByEnumeratingWithState$objects$count$(DOMNodeList *s
 
 @interface NSString (UIKit)
 - (NSString *) stringByAddingPercentEscapes;
-- (NSString *) stringByReplacingCharacter:(unsigned short)arg0 withCharacter:(unsigned short)arg1;
 @end
 
+/* Cydia NSString Additions {{{ */
 @interface NSString (Cydia)
 + (NSString *) stringWithUTF8BytesNoCopy:(const char *)bytes length:(int)length;
 + (NSString *) stringWithUTF8Bytes:(const char *)bytes length:(int)length withZone:(NSZone *)zone inPool:(apr_pool_t *)pool;
@@ -620,11 +721,8 @@ NSUInteger DOMNodeList$countByEnumeratingWithState$objects$count$(DOMNodeList *s
 
 - (NSString *) stringByCachingURLWithCurrentCDN {
     return [self
-        stringByReplacingOccurrencesOfString:@"://"
-        withString:@"://ne.edgecastcdn.net/8003A4/"
-        options:0
-        /* XXX: this is somewhat inaccurate */
-        range:NSMakeRange(0, 10)
+        stringByReplacingOccurrencesOfString:@"://cydia.saurik.com/"
+        withString:@"://cache.cydia.saurik.com/"
     ];
 }
 
@@ -639,13 +737,9 @@ NSUInteger DOMNodeList$countByEnumeratingWithState$objects$count$(DOMNodeList *s
 }
 
 @end
+/* }}} */
 
-static inline NSString *CYLocalizeEx(NSString *key, NSString *value = nil) {
-    return [[NSBundle mainBundle] localizedStringForKey:key value:value table:nil];
-}
-
-#define CYLocalize(key) CYLocalizeEx(@ key)
-
+/* C++ NSString Wrapper Cache {{{ */
 class CYString {
   private:
     char *data_;
@@ -653,8 +747,10 @@ class CYString {
     CFStringRef cache_;
 
     _finline void clear_() {
-        if (cache_ != nil)
+        if (cache_ != NULL) {
             CFRelease(cache_);
+            cache_ = NULL;
+        }
     }
 
   public:
@@ -678,7 +774,7 @@ class CYString {
     _finline CYString() :
         data_(0),
         size_(0),
-        cache_(nil)
+        cache_(NULL)
     {
     }
 
@@ -702,8 +798,9 @@ class CYString {
         else {
             clear_();
 
-            char *temp(reinterpret_cast<char *>(apr_palloc(pool, size)));
+            char *temp(reinterpret_cast<char *>(apr_palloc(pool, size + 1)));
             memcpy(temp, data, size);
+            temp[size] = '\0';
             data_ = temp;
             size_ = size;
         }
@@ -721,15 +818,22 @@ class CYString {
         return size_ == rhs.size_ && memcmp(data_, rhs.data_, size_) == 0;
     }
 
-    operator id() {
+    operator CFStringRef() {
         if (cache_ == NULL) {
             if (size_ == 0)
                 return nil;
             cache_ = CFStringCreateWithBytesNoCopy(kCFAllocatorDefault, reinterpret_cast<uint8_t *>(data_), size_, kCFStringEncodingUTF8, NO, kCFAllocatorNull);
-        } return (id) cache_;
+            if (cache_ == NULL)
+                cache_ = CFStringCreateWithBytesNoCopy(kCFAllocatorDefault, reinterpret_cast<uint8_t *>(data_), size_, kCFStringEncodingISOLatin1, NO, kCFAllocatorNull);
+        } return cache_;
     }
-};
 
+    _finline operator id() {
+        return (NSString *) static_cast<CFStringRef>(*this);
+    }
+};
+/* }}} */
+/* C++ NSString Algorithm Adapters {{{ */
 extern "C" {
     CF_EXPORT CFHashCode CFStringHashNSString(CFStringRef str);
 }
@@ -759,6 +863,7 @@ struct NSStringMapEqual :
         //[lhs isEqualToString:rhs];
     }
 };
+/* }}} */
 
 /* Perl-Compatible RegEx {{{ */
 class Pcre {
@@ -920,15 +1025,16 @@ class CGColor {
 };
 /* }}} */
 
-extern "C" void UISetColor(CGColorRef color);
-
 /* Random Global Variables {{{ */
 static const int PulseInterval_ = 50000;
+static const int ButtonBarWidth_ = 60;
 static const int ButtonBarHeight_ = 48;
 static const float KeyboardTime_ = 0.3f;
 
+static int Finish_;
+static NSArray *Finishes_;
+
 #define SpringBoard_ "/System/Library/LaunchDaemons/com.apple.SpringBoard.plist"
-#define SandboxTemplate_ "/usr/share/sandbox/SandboxTemplate.sb"
 #define NotifyConfig_ "/etc/notify.conf"
 
 static bool Queuing_;
@@ -948,10 +1054,8 @@ static UIColor *RemovingColor_;
 
 static NSString *App_;
 static NSString *Home_;
-static BOOL Sounds_Keyboard_;
 
 static BOOL Advanced_;
-static BOOL Loaded_;
 static BOOL Ignored_;
 
 static UIFont *Font12_;
@@ -961,17 +1065,20 @@ static UIFont *Font18Bold_;
 static UIFont *Font22Bold_;
 
 static const char *Machine_ = NULL;
+static const NSString *System_ = NULL;
+static const NSString *SerialNumber_ = nil;
+static const NSString *ChipID_ = nil;
+static const NSString *Token_ = nil;
 static const NSString *UniqueID_ = nil;
 static const NSString *Build_ = nil;
 static const NSString *Product_ = nil;
 static const NSString *Safari_ = nil;
 
-CFLocaleRef Locale_;
-NSArray *Languages_;
-CGColorSpaceRef space_;
+static CFLocaleRef Locale_;
+static NSArray *Languages_;
+static CGColorSpaceRef space_;
 
-bool bootstrap_;
-bool reload_;
+static bool reload_;
 
 static NSDictionary *SectionMap_;
 static NSMutableDictionary *Metadata_;
@@ -983,24 +1090,13 @@ static _transient NSMutableDictionary *Sources_;
 static bool Changed_;
 static NSDate *now_;
 
+static bool IsWildcat_;
+
 #if RecycleWebViews
 static NSMutableArray *Documents_;
 #endif
-
-NSString *GetLastUpdate() {
-    NSDate *update = [Metadata_ objectForKey:@"LastUpdate"];
-
-    if (update == nil)
-        return CYLocalize("NEVER_OR_UNKNOWN");
-
-    CFDateFormatterRef formatter = CFDateFormatterCreate(NULL, Locale_, kCFDateFormatterMediumStyle, kCFDateFormatterMediumStyle);
-    CFStringRef formatted = CFDateFormatterCreateStringWithDate(NULL, formatter, (CFDateRef) update);
-
-    CFRelease(formatter);
-
-    return [(NSString *) formatted autorelease];
-}
 /* }}} */
+
 /* Display Helpers {{{ */
 inline float Interpolate(float begin, float end, float fraction) {
     return (end - begin) * fraction + begin;
@@ -1023,20 +1119,37 @@ NSString *SizeString(double size) {
     return [NSString stringWithFormat:@"%s%.1f %s", (negative ? "-" : ""), size, powers_[power]];
 }
 
-NSString *StripVersion(NSString *version) {
-    NSRange colon = [version rangeOfString:@":"];
-    if (colon.location != NSNotFound)
-        version = [version substringFromIndex:(colon.location + 1)];
+static _finline CFStringRef CFCString(const char *value) {
+    return CFStringCreateWithBytesNoCopy(kCFAllocatorDefault, reinterpret_cast<const uint8_t *>(value), strlen(value), kCFStringEncodingUTF8, NO, kCFAllocatorNull);
+}
+
+const char *StripVersion_(const char *version) {
+    const char *colon(strchr(version, ':'));
+    if (colon != NULL)
+        version = colon + 1;
     return version;
 }
 
+CFStringRef StripVersion(const char *version) {
+    const char *colon(strchr(version, ':'));
+    if (colon != NULL)
+        version = colon + 1;
+    return CFStringCreateWithBytes(kCFAllocatorDefault, reinterpret_cast<const uint8_t *>(version), strlen(version), kCFStringEncodingUTF8, NO);
+    // XXX: performance
+    return CFCString(version);
+}
+
 NSString *LocalizeSection(NSString *section) {
     static Pcre title_r("^(.*?) \\((.*)\\)$");
-    if (title_r(section))
-        return [NSString stringWithFormat:CYLocalize("PARENTHETICAL"),
-            LocalizeSection(title_r[1]),
-            LocalizeSection(title_r[2])
+    if (title_r(section)) {
+        NSString *parent(title_r[1]);
+        NSString *child(title_r[2]);
+
+        return [NSString stringWithFormat:UCLocalize("PARENTHETICAL"),
+            LocalizeSection(parent),
+            LocalizeSection(child)
         ];
+    }
 
     return [[NSBundle mainBundle] localizedStringForKey:section value:nil table:@"Sections"];
 }
@@ -1061,9 +1174,23 @@ 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"];
+    NSDictionary *metadata([Sections_ objectForKey:section]);
+    NSNumber *hidden(metadata == nil ? nil : [metadata objectForKey:@"Hidden"]);
     return hidden == nil || ![hidden boolValue];
 }
 
@@ -1074,19 +1201,8 @@ bool isSectionVisible(NSString *section) {
 @interface NSObject (ProgressDelegate)
 @end
 
-@implementation NSObject(ProgressDelegate)
-
-- (void) _setProgressError:(NSArray *)args {
-    [self performSelector:@selector(setProgressError:forPackage:)
-        withObject:[args objectAtIndex:0]
-        withObject:([args count] == 1 ? nil : [args objectAtIndex:1])
-    ];
-}
-
-@end
-
 @protocol ProgressDelegate
-- (void) setProgressError:(NSString *)error forPackage:(NSString *)id;
+- (void) setProgressError:(NSString *)error withTitle:(NSString *)id;
 - (void) setProgressTitle:(NSString *)title;
 - (void) setProgressPercent:(float)percent;
 - (void) startProgress;
@@ -1105,6 +1221,7 @@ bool isSectionVisible(NSString *section) {
 - (void) setPackageView:(PackageView *)view;
 - (void) clearPackage:(Package *)package;
 - (void) installPackage:(Package *)package;
+- (void) installPackages:(NSArray *)packages;
 - (void) removePackage:(Package *)package;
 - (void) slideUp:(UIActionSheet *)alert;
 - (void) distUpgrade;
@@ -1113,10 +1230,7 @@ bool isSectionVisible(NSString *section) {
 - (void) askForSettings;
 - (UIProgressHUD *) addProgressHUD;
 - (void) removeProgressHUD:(UIProgressHUD *)hud;
-- (RVPage *) pageForURL:(NSURL *)url hasTag:(int *)tag;
 - (RVPage *) pageForPackage:(NSString *)name;
-- (void) openMailToURL:(NSURL *)url;
-- (void) clearFirstResponder;
 - (PackageView *) packageView;
 @end
 /* }}} */
@@ -1138,6 +1252,10 @@ class Status :
         delegate_ = delegate;
     }
 
+    NSObject<ProgressDelegate> *getDelegate() const {
+        return delegate_;
+    }
+
     virtual bool MediaChange(std::string media, std::string drive) {
         return false;
     }
@@ -1147,7 +1265,7 @@ class Status :
 
     virtual void Fetch(pkgAcquire::ItemDesc &item) {
         //NSString *name([NSString stringWithUTF8String:item.ShortDesc.c_str()]);
-        [delegate_ setProgressTitle:[NSString stringWithUTF8String:("Downloading " + item.ShortDesc).c_str()]];
+        [delegate_ setProgressTitle:[NSString stringWithFormat:UCLocalize("DOWNLOADING_"), [NSString stringWithUTF8String:item.ShortDesc.c_str()]]];
     }
 
     virtual void Done(pkgAcquire::ItemDesc &item) {
@@ -1168,7 +1286,7 @@ class Status :
         NSArray *fields([description componentsSeparatedByString:@" "]);
         NSString *source([fields count] == 0 ? nil : [fields objectAtIndex:0]);
 
-        [delegate_ performSelectorOnMainThread:@selector(_setProgressError:)
+        [delegate_ performSelectorOnMainThread:@selector(_setProgressErrorPackage:)
             withObject:[NSArray arrayWithObjects:
                 [NSString stringWithUTF8String:error.c_str()],
                 source,
@@ -1203,16 +1321,23 @@ class Progress :
 {
   private:
     _transient id<ProgressDelegate> delegate_;
+    float percent_;
 
   protected:
     virtual void Update() {
+        /*if (abs(Percent - percent_) > 2)
+            //NSLog(@"%s:%s:%f", Op.c_str(), SubOp.c_str(), Percent);
+            percent_ = Percent;
+        }*/
+
         /*[delegate_ setProgressTitle:[NSString stringWithUTF8String:Op.c_str()]];
         [delegate_ setProgressPercent:(Percent / 100)];*/
     }
 
   public:
     Progress() :
-        delegate_(nil)
+        delegate_(nil),
+        percent_(0)
     {
     }
 
@@ -1220,13 +1345,20 @@ class Progress :
         delegate_ = delegate;
     }
 
+    id getDelegate() const {
+        return delegate_;
+    }
+
     virtual void Done() {
+        //NSLog(@"DONE");
         //[delegate_ setProgressPercent:1];
     }
 };
 /* }}} */
 
 /* Database Interface {{{ */
+typedef std::map< unsigned long, _H<Source> > SourceMap;
+
 @interface Database : NSObject {
     NSZone *zone_;
     apr_pool_t *pool_;
@@ -1242,7 +1374,7 @@ class Progress :
     SPtr<pkgPackageManager> manager_;
     pkgSourceList *list_;
 
-    NSMutableDictionary *sources_;
+    SourceMap sources_;
     NSMutableArray *packages_;
 
     _transient NSObject<ConfigurationDelegate, ProgressDelegate> *delegate_;
@@ -1276,40 +1408,79 @@ class Progress :
 - (void) reloadData;
 
 - (void) configure;
-- (void) prepare;
+- (bool) prepare;
 - (void) perform;
-- (void) upgrade;
+- (bool) upgrade;
 - (void) update;
 
+- (void) setVisible;
+
 - (void) updateWithStatus:(Status &)status;
 
 - (void) setDelegate:(id)delegate;
 - (Source *) getSource:(pkgCache::PkgFileIterator)file;
+@end
+/* }}} */
+/* Delegate Helpers {{{ */
+@implementation NSObject(ProgressDelegate)
+
+- (void) _setProgressErrorPackage:(NSArray *)args {
+    [self performSelector:@selector(setProgressError:forPackage:)
+        withObject:[args objectAtIndex:0]
+        withObject:([args count] == 1 ? nil : [args objectAtIndex:1])
+    ];
+}
+
+- (void) _setProgressErrorTitle:(NSArray *)args {
+    [self performSelector:@selector(setProgressError:withTitle:)
+        withObject:[args objectAtIndex:0]
+        withObject:([args count] == 1 ? nil : [args objectAtIndex:1])
+    ];
+}
+
+- (void) _setProgressError:(NSString *)error withTitle:(NSString *)title {
+    [self performSelectorOnMainThread:@selector(_setProgressErrorTitle:)
+        withObject:[NSArray arrayWithObjects:error, title, nil]
+        waitUntilDone:YES
+    ];
+}
+
+- (void) setProgressError:(NSString *)error forPackage:(NSString *)id {
+    Package *package = id == nil ? nil : [[Database sharedInstance] packageWithName:id];
+    // XXX: holy typecast batman!
+    [(id<ProgressDelegate>)self setProgressError:error withTitle:(package == nil ? id : [package name])];
+}
+
 @end
 /* }}} */
 
 /* Source Class {{{ */
 @interface Source : NSObject {
-    NSString *description_;
-    NSString *label_;
-    NSString *origin_;
-    NSString *support_;
+    CYString depiction_;
+    CYString description_;
+    CYString label_;
+    CYString origin_;
+    CYString support_;
 
-    NSString *uri_;
-    NSString *distribution_;
-    NSString *type_;
-    NSString *version_;
+    CYString uri_;
+    CYString distribution_;
+    CYString type_;
+    CYString version_;
 
-    NSString *defaultIcon_;
+    NSString *host_;
+    NSString *authority_;
+
+    CYString defaultIcon_;
 
     NSDictionary *record_;
     BOOL trusted_;
 }
 
-- (Source *) initWithMetaIndex:(metaIndex *)index;
+- (Source *) initWithMetaIndex:(metaIndex *)index inPool:(apr_pool_t *)pool;
 
 - (NSComparisonResult) compareByNameAndType:(Source *)source;
 
+- (NSString *) depictionForPackage:(NSString *)package;
 - (NSString *) supportForPackage:(NSString *)package;
 
 - (NSDictionary *) record;
@@ -1333,23 +1504,33 @@ class Progress :
 
 @implementation Source
 
-#define _clear(field) \
-    if (field != nil) \
-        [field release]; \
-    field = nil;
-
 - (void) _clear {
-    _clear(uri_)
-    _clear(distribution_)
-    _clear(type_)
+    uri_.clear();
+    distribution_.clear();
+    type_.clear();
+
+    description_.clear();
+    label_.clear();
+    origin_.clear();
+    depiction_.clear();
+    support_.clear();
+    version_.clear();
+    defaultIcon_.clear();
+
+    if (record_ != nil) {
+        [record_ release];
+        record_ = nil;
+    }
+
+    if (host_ != nil) {
+        [host_ release];
+        host_ = nil;
+    }
 
-    _clear(description_)
-    _clear(label_)
-    _clear(origin_)
-    _clear(support_)
-    _clear(version_)
-    _clear(defaultIcon_)
-    _clear(record_)
+    if (authority_ != nil) {
+        [authority_ release];
+        authority_ = nil;
+    }
 }
 
 - (void) dealloc {
@@ -1369,52 +1550,72 @@ class Progress :
     return ![[self _attributeKeys] containsObject:[NSString stringWithUTF8String:name]] && [super isKeyExcludedFromWebScript:name];
 }
 
-- (void) setMetaIndex:(metaIndex *)index {
+- (void) setMetaIndex:(metaIndex *)index inPool:(apr_pool_t *)pool {
     [self _clear];
 
     trusted_ = index->IsTrusted();
 
-    uri_ = [[NSString stringWithUTF8String:index->GetURI().c_str()] retain];
-    distribution_ = [[NSString stringWithUTF8String:index->GetDist().c_str()] retain];
-    type_ = [[NSString stringWithUTF8String:index->GetType()] retain];
+    uri_.set(pool, index->GetURI());
+    distribution_.set(pool, index->GetDist());
+    type_.set(pool, index->GetType());
 
     debReleaseIndex *dindex(dynamic_cast<debReleaseIndex *>(index));
     if (dindex != NULL) {
-        std::ifstream release(dindex->MetaIndexFile("Release").c_str());
-        std::string line;
-        while (std::getline(release, line)) {
-            std::string::size_type colon(line.find(':'));
-            if (colon == std::string::npos)
-                continue;
-
-            std::string name(line.substr(0, colon));
-            std::string value(line.substr(colon + 1));
-            while (!value.empty() && value[0] == ' ')
-                value = value.substr(1);
-
-            if (name == "Default-Icon")
-                defaultIcon_ = [[NSString stringWithUTF8String:value.c_str()] retain];
-            else if (name == "Description")
-                description_ = [[NSString stringWithUTF8String:value.c_str()] retain];
-            else if (name == "Label")
-                label_ = [[NSString stringWithUTF8String:value.c_str()] retain];
-            else if (name == "Origin")
-                origin_ = [[NSString stringWithUTF8String:value.c_str()] retain];
-            else if (name == "Support")
-                support_ = [[NSString stringWithUTF8String:value.c_str()] retain];
-            else if (name == "Version")
-                version_ = [[NSString stringWithUTF8String:value.c_str()] retain];
+        FileFd fd;
+        if (!fd.Open(dindex->MetaIndexFile("Release"), FileFd::ReadOnly))
+            _error->Discard();
+        else {
+            pkgTagFile tags(&fd);
+
+            pkgTagSection section;
+            tags.Step(section);
+
+            struct {
+                const char *name_;
+                CYString *value_;
+            } names[] = {
+                {"default-icon", &defaultIcon_},
+                {"depiction", &depiction_},
+                {"description", &description_},
+                {"label", &label_},
+                {"origin", &origin_},
+                {"support", &support_},
+                {"version", &version_},
+            };
+
+            for (size_t i(0); i != sizeof(names) / sizeof(names[0]); ++i) {
+                const char *start, *end;
+
+                if (section.Find(names[i].name_, start, end)) {
+                    CYString &value(*names[i].value_);
+                    value.set(pool, start, end - start);
+                }
+            }
         }
     }
 
     record_ = [Sources_ objectForKey:[self key]];
     if (record_ != nil)
         record_ = [record_ retain];
+
+    NSURL *url([NSURL URLWithString:uri_]);
+
+    host_ = [url host];
+    if (host_ != nil)
+        host_ = [[host_ lowercaseString] retain];
+
+    if (host_ != nil)
+        authority_ = host_;
+    else
+        authority_ = [url path];
+
+    if (authority_ != nil)
+        authority_ = [authority_ retain];
 }
 
-- (Source *) initWithMetaIndex:(metaIndex *)index {
+- (Source *) initWithMetaIndex:(metaIndex *)index inPool:(apr_pool_t *)pool {
     if ((self = [super init]) != nil) {
-        [self setMetaIndex:index];
+        [self setMetaIndex:index inPool:pool];
     } return self;
 }
 
@@ -1441,8 +1642,12 @@ class Progress :
     return [lhs compare:rhs options:LaxCompareOptions_];
 }
 
+- (NSString *) depictionForPackage:(NSString *)package {
+    return depiction_.empty() ? nil : [depiction_ stringByReplacingOccurrencesOfString:@"*" withString:package];
+}
+
 - (NSString *) supportForPackage:(NSString *)package {
-    return support_ == nil ? nil : [support_ stringByReplacingOccurrencesOfString:@"*" withString:package];
+    return support_.empty() ? nil : [support_ stringByReplacingOccurrencesOfString:@"*" withString:package];
 }
 
 - (NSDictionary *) record {
@@ -1466,15 +1671,15 @@ class Progress :
 }
 
 - (NSString *) key {
-    return [NSString stringWithFormat:@"%@:%@:%@", type_, uri_, distribution_];
+    return [NSString stringWithFormat:@"%@:%@:%@", (NSString *) type_, (NSString *) uri_, (NSString *) distribution_];
 }
 
 - (NSString *) host {
-    return [[[NSURL URLWithString:[self uri]] host] lowercaseString];
+    return host_;
 }
 
 - (NSString *) name {
-    return origin_ == nil ? [self host] : origin_;
+    return origin_.empty() ? authority_ : origin_;
 }
 
 - (NSString *) description {
@@ -1482,7 +1687,7 @@ class Progress :
 }
 
 - (NSString *) label {
-    return label_ == nil ? [self host] : label_;
+    return label_.empty() ? authority_ : label_;
 }
 
 - (NSString *) origin {
@@ -1537,6 +1742,7 @@ class Progress :
 /* Package Class {{{ */
 @interface Package : NSObject {
     unsigned era_;
+    apr_pool_t *pool_;
 
     pkgCache::VerIterator version_;
     pkgCache::PkgIterator iterator_;
@@ -1545,15 +1751,19 @@ class Progress :
 
     Source *source_;
     bool cached_;
+    bool parsed_;
 
     CYString section_;
     NSString *section$_;
     bool essential_;
+    bool required_;
+    bool visible_;
+    bool obsolete_;
 
     NSString *latest_;
-    NSString *installed_;
+    CYString installed_;
 
-    NSString *id_;
+    CYString id_;
     CYString name_;
     CYString tagline_;
     CYString icon_;
@@ -1566,18 +1776,24 @@ class Progress :
     CYString author_;
     Address *author$_;
 
+    CYString bugs_;
     CYString support_;
-    NSArray *tags_;
+    NSMutableArray *tags_;
     NSString *role_;
 
     NSArray *relationships_;
+
     NSMutableDictionary *metadata_;
+    _transient NSDate *firstSeen_;
+    _transient NSDate *lastSeen_;
+    bool subscribed_;
 }
 
 - (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;
 
 - (pkgCache::PkgIterator) iterator;
+- (void) parse;
 
 - (NSString *) section;
 - (NSString *) simpleSection;
@@ -1589,7 +1805,8 @@ class Progress :
 
 - (Address *) maintainer;
 - (size_t) size;
-- (NSString *) description;
+- (NSString *) longDescription;
+- (NSString *) shortDescription;
 - (unichar) index;
 
 - (NSMutableDictionary *) metadata;
@@ -1599,6 +1816,7 @@ class Progress :
 
 - (NSString *) latest;
 - (NSString *) installed;
+- (BOOL) uninstalled;
 
 - (BOOL) valid;
 - (BOOL) upgradableAndEssential:(BOOL)essential;
@@ -1613,9 +1831,10 @@ class Progress :
 - (BOOL) hasMode;
 - (NSString *) mode;
 
+- (void) setVisible;
+
 - (NSString *) id;
 - (NSString *) name;
-- (NSString *) tagline;
 - (UIImage *) icon;
 - (NSString *) homepage;
 - (NSString *) depiction;
@@ -1639,8 +1858,8 @@ class Progress :
 - (NSArray *) purposes;
 - (bool) isCommercial;
 
-- (uint32_t) compareByPrefix;
-- (NSComparisonResult) compareByName:(Package *)package;
+- (CYString &) cyname;
+
 - (uint32_t) compareBySection:(NSArray *)sections;
 
 - (uint32_t) compareForChanges;
@@ -1649,8 +1868,9 @@ class Progress :
 - (void) remove;
 
 - (bool) isUnfilteredAndSearchedForBy:(NSString *)search;
+- (bool) isUnfilteredAndSelectedForBy:(NSString *)search;
 - (bool) isInstalledAndVisible:(NSNumber *)number;
-- (bool) isVisiblyUninstalledInSection:(NSString *)section;
+- (bool) isVisibleInSection:(NSString *)section;
 - (bool) isVisibleInSource:(Source *)source;
 
 @end
@@ -1682,51 +1902,151 @@ uint32_t PackageChangesRadix(Package *self, void *) {
     return _not(uint32_t) - value.key;
 }
 
-@implementation Package
+_finline static void Stifle(uint8_t &value) {
+}
 
-- (void) dealloc {
-    if (source_ != nil)
-        [source_ release];
-    if (section$_ != nil)
-        [section$_ release];
+uint32_t PackagePrefixRadix(Package *self, void *context) {
+    size_t offset(reinterpret_cast<size_t>(context));
+    CYString &name([self cyname]);
 
-    if (latest_ != nil)
-        [latest_ release];
-    if (installed_ != nil)
-        [installed_ release];
+    size_t size(name.size());
+    if (size == 0)
+        return 0;
+    char *text(name.data());
 
-    if (id_ != nil)
-        [id_ release];
-    if (sponsor$_ != nil)
-        [sponsor$_ release];
-    if (author$_ != nil)
-        [author$_ release];
-    if (tags_ != nil)
-        [tags_ release];
-    if (role_ != nil)
-        [role_ release];
+    size_t zeros;
+    if (!isdigit(text[0]))
+        zeros = 0;
+    else {
+        size_t digits(1);
+        while (size != digits && isdigit(text[digits]))
+            if (++digits == 4)
+                break;
+        zeros = 4 - digits;
+    }
 
-    if (relationships_ != nil)
-        [relationships_ release];
-    if (metadata_ != nil)
-        [metadata_ release];
+    uint8_t data[4];
 
-    [super dealloc];
-}
+    // 0.607997
 
-+ (NSString *) webScriptNameForSelector:(SEL)selector {
-    if (selector == @selector(hasTag:))
-        return @"hasTag";
-    else
-        return nil;
-}
+    if (offset == 0 && zeros != 0) {
+        memset(data, '0', zeros);
+        memcpy(data + zeros, text, 4 - zeros);
+    } else {
+        /* XXX: there's some danger here if you request a non-zero offset < 4 and it gets zero padded */
+        if (size <= offset - zeros)
+            return 0;
 
-+ (BOOL) isSelectorExcludedFromWebScript:(SEL)selector {
-    return [self webScriptNameForSelector:selector] == nil;
-}
+        text += offset - zeros;
+        size -= offset - zeros;
 
-+ (NSArray *) _attributeKeys {
-    return [NSArray arrayWithObjects:@"applications", @"author", @"depiction", @"description", @"essential", @"homepage", @"icon", @"id", @"installed", @"latest", @"longSection", @"maintainer", @"mode", @"name", @"purposes", @"section", @"shortSection", @"simpleSection", @"size", @"source", @"sponsor", @"support", @"tagline", @"warnings", nil];
+        if (size >= 4)
+            memcpy(data, text, 4);
+        else {
+            memcpy(data, text, size);
+            memset(data + size, 0, 4 - size);
+        }
+
+        for (size_t i(0); i != 4; ++i)
+            if (isalpha(data[i]))
+                data[i] &= 0xdf;
+    }
+
+    if (offset == 0)
+        data[0] = (data[0] & 0x3f) | "\x80\x00\xc0\x40"[data[0] >> 6];
+
+    /* XXX: ntohl may be more honest */
+    return OSSwapInt32(*reinterpret_cast<uint32_t *>(data));
+}
+
+CYString &(*PackageName)(Package *self, SEL sel);
+
+CFComparisonResult PackageNameCompare(Package *lhs, Package *rhs, void *arg) {
+    _profile(PackageNameCompare)
+        CYString &lhi(PackageName(lhs, @selector(cyname)));
+        CYString &rhi(PackageName(rhs, @selector(cyname)));
+        CFStringRef lhn(lhi), rhn(rhi);
+
+        if (lhn == NULL)
+            return rhn == NULL ? NSOrderedSame : NSOrderedAscending;
+        else if (rhn == NULL)
+            return NSOrderedDescending;
+
+        _profile(PackageNameCompare$NumbersLast)
+            if (!lhi.empty() && !rhi.empty()) {
+                UniChar lhc(CFStringGetCharacterAtIndex(lhn, 0));
+                UniChar rhc(CFStringGetCharacterAtIndex(rhn, 0));
+                bool lha(CFUniCharIsMemberOf(lhc, kCFUniCharLetterCharacterSet));
+                if (lha != CFUniCharIsMemberOf(rhc, kCFUniCharLetterCharacterSet))
+                    return lha ? NSOrderedAscending : NSOrderedDescending;
+            }
+        _end
+
+        CFIndex length = CFStringGetLength(lhn);
+
+        _profile(PackageNameCompare$Compare)
+            return CFStringCompareWithOptionsAndLocale(lhn, rhn, CFRangeMake(0, length), LaxCompareFlags_, Locale_);
+        _end
+    _end
+}
+
+CFComparisonResult PackageNameCompare_(Package **lhs, Package **rhs, void *context) {
+    return PackageNameCompare(*lhs, *rhs, context);
+}
+
+struct PackageNameOrdering :
+    std::binary_function<Package *, Package *, bool>
+{
+    _finline bool operator ()(Package *lhs, Package *rhs) const {
+        return PackageNameCompare(lhs, rhs, NULL) == NSOrderedAscending;
+    }
+};
+
+@implementation Package
+
+- (NSString *) description {
+    return [NSString stringWithFormat:@"<Package:%@>", static_cast<NSString *>(name_)];
+}
+
+- (void) dealloc {
+    if (source_ != nil)
+        [source_ release];
+    if (section$_ != nil)
+        [section$_ release];
+
+    if (latest_ != nil)
+        [latest_ release];
+
+    if (sponsor$_ != nil)
+        [sponsor$_ release];
+    if (author$_ != nil)
+        [author$_ release];
+    if (tags_ != nil)
+        [tags_ release];
+    if (role_ != nil)
+        [role_ release];
+
+    if (relationships_ != nil)
+        [relationships_ release];
+    if (metadata_ != nil)
+        [metadata_ release];
+
+    [super dealloc];
+}
+
++ (NSString *) webScriptNameForSelector:(SEL)selector {
+    if (selector == @selector(hasTag:))
+        return @"hasTag";
+    else
+        return nil;
+}
+
++ (BOOL) isSelectorExcludedFromWebScript:(SEL)selector {
+    return [self webScriptNameForSelector:selector] == nil;
+}
+
++ (NSArray *) _attributeKeys {
+    return [NSArray arrayWithObjects:@"applications", @"author", @"depiction", @"longDescription", @"essential", @"homepage", @"icon", @"id", @"installed", @"latest", @"longSection", @"maintainer", @"mode", @"name", @"purposes", @"section", @"shortDescription", @"shortSection", @"simpleSection", @"size", @"source", @"sponsor", @"support", @"warnings", nil];
 }
 
 - (NSArray *) attributeKeys {
@@ -1737,33 +2057,95 @@ uint32_t PackageChangesRadix(Package *self, void *) {
     return ![[self _attributeKeys] containsObject:[NSString stringWithUTF8String:name]] && [super isKeyExcludedFromWebScript:name];
 }
 
+- (void) parse {
+    if (parsed_)
+        return;
+    parsed_ = true;
+    if (file_.end())
+        return;
+
+    _profile(Package$parse)
+        pkgRecords::Parser *parser;
+
+        _profile(Package$parse$Lookup)
+            parser = &[database_ records]->Lookup(file_);
+        _end
+
+        CYString website;
+
+        _profile(Package$parse$Find)
+            struct {
+                const char *name_;
+                CYString *value_;
+            } names[] = {
+                {"icon", &icon_},
+                {"depiction", &depiction_},
+                {"homepage", &homepage_},
+                {"website", &website},
+                {"bugs", &bugs_},
+                {"support", &support_},
+                {"sponsor", &sponsor_},
+                {"author", &author_},
+            };
+
+            for (size_t i(0); i != sizeof(names) / sizeof(names[0]); ++i) {
+                const char *start, *end;
+
+                if (parser->Find(names[i].name_, start, end)) {
+                    CYString &value(*names[i].value_);
+                    _profile(Package$parse$Value)
+                        value.set(pool_, start, end - start);
+                    _end
+                }
+            }
+        _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;
+                tagline_.set(pool_, start, stop - start);
+            }
+        _end
+
+        _profile(Package$parse$Retain)
+            if (homepage_.empty())
+                homepage_ = website;
+            if (homepage_ == depiction_)
+                homepage_.clear();
+        _end
+    _end
+}
+
+- (void) setVisible {
+    visible_ = required_ && [self unfiltered];
+}
+
 - (Package *) initWithVersion:(pkgCache::VerIterator)version withZone:(NSZone *)zone inPool:(apr_pool_t *)pool database:(Database *)database {
     if ((self = [super init]) != nil) {
     _profile(Package$initWithVersion)
     @synchronized (database) {
         era_ = [database era];
+        pool_ = pool;
 
         version_ = version;
         iterator_ = version.ParentPkg();
         database_ = database;
 
         _profile(Package$initWithVersion$Latest)
-            latest_ = [StripVersion([NSString stringWithUTF8String:version_.VerStr()]) retain];
+            latest_ = (NSString *) StripVersion(version_.VerStr());
         _end
 
         pkgCache::VerIterator current;
-        NSString *installed;
-
-        _profile(Package$initWithVersion$Current)
+        _profile(Package$initWithVersion$Versions)
             current = iterator_.CurrentVer();
-            installed = current.end() ? nil : [NSString stringWithUTF8String:current.VerStr()];
-        _end
+            if (!current.end())
+                installed_.set(pool_, StripVersion_(current.VerStr()));
 
-        _profile(Package$initWithVersion$Installed)
-            installed_ = [StripVersion(installed) retain];
-        _end
-
-        _profile(Package$initWithVersion$File)
             if (!version_.end())
                 file_ = version_.FileList();
             else {
@@ -1773,101 +2155,37 @@ uint32_t PackageChangesRadix(Package *self, void *) {
         _end
 
         _profile(Package$initWithVersion$Name)
-            id_ = [[NSString stringWithUTF8String:iterator_.Name()] retain];
+            id_.set(pool_, iterator_.Name());
+            name_.set(pool, iterator_.Display());
         _end
 
-        if (!file_.end())
-            source_ = [database_ getSource:file_.File()];
-            if (source_ != nil)
-                [source_ retain];
-            cached_ = true;
-
-            _profile(Package$initWithVersion$Parse)
-                pkgRecords::Parser *parser;
-
-                _profile(Package$initWithVersion$Parse$Lookup)
-                    parser = &[database_ records]->Lookup(file_);
-                _end
-
-                const char *begin, *end;
-                parser->GetRec(begin, end);
-
-                CYString website;
-                CYString tag;
-
-                struct {
-                    const char *name_;
-                    CYString *value_;
-                } names[] = {
-                    {"name", &name_},
-                    {"icon", &icon_},
-                    {"depiction", &depiction_},
-                    {"homepage", &homepage_},
-                    {"website", &website},
-                    {"support", &support_},
-                    {"sponsor", &sponsor_},
-                    {"author", &author_},
-                    {"tag", &tag},
-                };
-
-                while (begin != end)
-                    if (*begin == '\n') {
-                        ++begin;
-                        continue;
-                    } else if (isblank(*begin)) next: {
-                        begin = static_cast<char *>(memchr(begin + 1, '\n', end - begin - 1));
-                        if (begin == NULL)
-                            break;
-                    } else if (const char *colon = static_cast<char *>(memchr(begin, ':', end - begin))) {
-                        const char *name(begin);
-                        size_t size(colon - begin);
-
-                        begin = static_cast<char *>(memchr(begin, '\n', end - begin));
-
-                        {
-                            const char *stop(begin == NULL ? end : begin);
-                            while (stop[-1] == '\r')
-                                --stop;
-                            while (++colon != stop && isblank(*colon));
-
-                            for (size_t i(0); i != sizeof(names) / sizeof(names[0]); ++i)
-                                if (strncasecmp(names[i].name_, name, size) == 0) {
-                                    CYString &value(*names[i].value_);
-
-                                    _profile(Package$initWithVersion$Parse$Value)
-                                        value.set(pool, colon, stop - colon);
-                                    _end
-
-                                    break;
-                                }
-                        }
-
-                        if (begin == NULL)
-                            break;
-                        ++begin;
-                    } else goto next;
-
-                _profile(Package$initWithVersion$Parse$Tagline)
-                    tagline_.set(pool, parser->ShortDesc());
-                _end
-
-                _profile(Package$initWithVersion$Parse$Retain)
-                    if (!homepage_.empty())
-                        homepage_ = website;
-                    if (homepage_ == depiction_)
-                        homepage_.clear();
-                    if (!tag.empty())
-                        tags_ = [[tag componentsSeparatedByString:@", "] retain];
-                _end
+        if (!file_.end()) {
+            _profile(Package$initWithVersion$Source)
+                source_ = [database_ getSource:file_.File()];
+                if (source_ != nil)
+                    [source_ retain];
+                cached_ = true;
             _end
+        }
+
+        required_ = true;
 
         _profile(Package$initWithVersion$Tags)
-            if (tags_ != nil)
-                for (NSString *tag in tags_)
-                    if ([tag hasPrefix:@"role::"]) {
-                        role_ = [[tag substringFromIndex:6] retain];
-                        break;
-                    }
+            pkgCache::TagIterator tag(iterator_.TagList());
+            if (!tag.end()) {
+                tags_ = [[NSMutableArray alloc] initWithCapacity:8];
+                do {
+                    const char *name(tag.Name());
+                    [tags_ addObject:(NSString *)CFCString(name)];
+                    if (role_ == nil && strncmp(name, "role::", 6) == 0 /*&& strcmp(name, "role::leaper") != 0*/)
+                        role_ = (NSString *) CFCString(name + 6);
+                    if (required_ && strncmp(name, "require::", 9) == 0 && (
+                        true
+                    ))
+                        required_ = false;
+                    ++tag;
+                } while (!tag.end());
+            }
         _end
 
         bool changed(false);
@@ -1875,21 +2193,28 @@ uint32_t PackageChangesRadix(Package *self, void *) {
 
         _profile(Package$initWithVersion$Metadata)
             metadata_ = [Packages_ objectForKey:key];
+
             if (metadata_ == nil) {
+                firstSeen_ = now_;
+
                 metadata_ = [[NSMutableDictionary dictionaryWithObjectsAndKeys:
-                    now_, @"FirstSeen",
+                    firstSeen_, @"FirstSeen",
+                    latest_, @"LastVersion",
                 nil] mutableCopy];
 
-                [metadata_ setObject:latest_ forKey:@"LastVersion"];
                 changed = true;
             } else {
-                NSDate *first([metadata_ objectForKey:@"FirstSeen"]);
-                NSDate *last([metadata_ objectForKey:@"LastSeen"]);
+                firstSeen_ = [metadata_ objectForKey:@"FirstSeen"];
+                lastSeen_ = [metadata_ objectForKey:@"LastSeen"];
+
+                if (NSNumber *subscribed = [metadata_ objectForKey:@"IsSubscribed"])
+                    subscribed_ = [subscribed boolValue];
+
                 NSString *version([metadata_ objectForKey:@"LastVersion"]);
 
-                if (first == nil) {
-                    first = last == nil ? now_ : last;
-                    [metadata_ setObject:first forKey:@"FirstSeen"];
+                if (firstSeen_ == nil) {
+                    firstSeen_ = lastSeen_ == nil ? now_ : lastSeen_;
+                    [metadata_ setObject:firstSeen_ forKey:@"FirstSeen"];
                     changed = true;
                 }
 
@@ -1898,8 +2223,8 @@ uint32_t PackageChangesRadix(Package *self, void *) {
                     changed = true;
                 } else if (![version isEqualToString:latest_]) {
                     [metadata_ setObject:latest_ forKey:@"LastVersion"];
-                    last = now_;
-                    [metadata_ setObject:last forKey:@"LastSeen"];
+                    lastSeen_ = now_;
+                    [metadata_ setObject:lastSeen_ forKey:@"LastSeen"];
                     changed = true;
                 }
             }
@@ -1913,14 +2238,17 @@ uint32_t PackageChangesRadix(Package *self, void *) {
         _end
 
         _profile(Package$initWithVersion$Section)
-            section_.set(pool, iterator_.Section());
+            section_.set(pool_, iterator_.Section());
         _end
 
+        obsolete_ = [self hasTag:@"cydia::obsolete"];
         essential_ = ((iterator_->Flags & pkgCache::Flag::Essential) == 0 ? NO : YES) || [self hasTag:@"cydia::essential"];
+        [self setVisible];
     } _end } return self;
 }
 
 + (Package *) packageWithIterator:(pkgCache::PkgIterator)iterator withZone:(NSZone *)zone inPool:(apr_pool_t *)pool database:(Database *)database {
+@synchronized ([Database class]) {
     pkgCache::VerIterator version;
 
     _profile(Package$packageWithIterator$GetCandidateVer)
@@ -1936,7 +2264,7 @@ uint32_t PackageChangesRadix(Package *self, void *) {
         inPool:pool
         database:database
     ] autorelease];
-}
+} }
 
 - (pkgCache::PkgIterator) iterator {
     return iterator_;
@@ -1969,7 +2297,7 @@ uint32_t PackageChangesRadix(Package *self, void *) {
 }
 
 - (NSString *) longSection {
-    return LocalizeSection(section_);
+    return LocalizeSection([self section]);
 }
 
 - (NSString *) shortSection {
@@ -2001,7 +2329,7 @@ uint32_t PackageChangesRadix(Package *self, void *) {
     return version_.end() ? 0 : version_->InstalledSize;
 }
 
-- (NSString *) description {
+- (NSString *) longDescription {
     if (file_.end())
         return nil;
     pkgRecords::Parser *parser = &[database_ records]->Lookup(file_);
@@ -2021,38 +2349,34 @@ uint32_t PackageChangesRadix(Package *self, void *) {
     return [trimmed componentsJoinedByString:@"\n"];
 }
 
+- (NSString *) shortDescription {
+    return tagline_;
+}
+
 - (unichar) index {
     _profile(Package$index)
-        NSString *name([self name]);
-        if ([name length] == 0)
+        CFStringRef name((CFStringRef) [self name]);
+        if (CFStringGetLength(name) == 0)
             return '#';
-        unichar character([name characterAtIndex:0]);
-        if (!isalpha(character))
+        UniChar character(CFStringGetCharacterAtIndex(name, 0));
+        if (!CFUniCharIsMemberOf(character, kCFUniCharLetterCharacterSet))
             return '#';
         return toupper(character);
     _end
 }
 
 - (NSMutableDictionary *) metadata {
-    if (metadata_ == nil)
-        metadata_ = [[Packages_ objectForKey:[id_ lowercaseString]] retain];
     return metadata_;
 }
 
 - (NSDate *) seen {
-    NSDictionary *metadata([self metadata]);
-    if ([self subscribed])
-        if (NSDate *last = [metadata objectForKey:@"LastSeen"])
-            return last;
-    return [metadata objectForKey:@"FirstSeen"];
+    if (subscribed_ && lastSeen_ != nil)
+        return lastSeen_;
+    return firstSeen_;
 }
 
 - (BOOL) subscribed {
-    NSDictionary *metadata([self metadata]);
-    if (NSNumber *subscribed = [metadata objectForKey:@"IsSubscribed"])
-        return [subscribed boolValue];
-    else
-        return false;
+    return subscribed_;
 }
 
 - (BOOL) ignored {
@@ -2071,19 +2395,22 @@ uint32_t PackageChangesRadix(Package *self, void *) {
     return installed_;
 }
 
+- (BOOL) uninstalled {
+    return installed_.empty();
+}
+
 - (BOOL) valid {
     return !version_.end();
 }
 
 - (BOOL) upgradableAndEssential:(BOOL)essential {
-    pkgCache::VerIterator current = iterator_.CurrentVer();
-
-    bool value;
-    if (current.end())
-        value = essential && [self essential] && [self visible];
-    else
-        value = !version_.end() && version_ != current;// && (!essential || ![database_ cache][iterator_].Keep());
-    return value;
+    _profile(Package$upgradableAndEssential)
+        pkgCache::VerIterator current(iterator_.CurrentVer());
+        if (current.end())
+            return essential && essential_ && visible_;
+        else
+            return !version_.end() && version_ != current;// && (!essential || ![database_ cache][iterator_].Keep());
+    _end
 }
 
 - (BOOL) essential {
@@ -2095,16 +2422,16 @@ uint32_t PackageChangesRadix(Package *self, void *) {
 }
 
 - (BOOL) unfiltered {
-    NSString *section = [self section];
-    return section == nil || isSectionVisible(section);
+    NSString *section([self section]);
+    return !obsolete_ && [self hasSupportingRole] && (section == nil || isSectionVisible(section));
 }
 
 - (BOOL) visible {
-    return [self hasSupportingRole] && [self unfiltered];
+    return visible_;
 }
 
 - (BOOL) half {
-    unsigned char current = iterator_->CurrentState;
+    unsigned char current(iterator_->CurrentState);
     return current == pkgCache::State::HalfConfigured || current == pkgCache::State::HalfInstalled;
 }
 
@@ -2149,11 +2476,9 @@ uint32_t PackageChangesRadix(Package *self, void *) {
                     return @"UPGRADE";
                 case 2:
                     return @"NEW_INSTALL";
-                default:
-                    _assert(false);
+                _nodefault
             }
-        default:
-            _assert(false);
+        _nodefault
     }
 }
 
@@ -2162,18 +2487,14 @@ uint32_t PackageChangesRadix(Package *self, void *) {
 }
 
 - (NSString *) name {
-    return name_ == nil ? id_ : name_;
-}
-
-- (NSString *) tagline {
-    return tagline_;
+    return name_.empty() ? id_ : name_;
 }
 
 - (UIImage *) icon {
     NSString *section = [self simpleSection];
 
     UIImage *icon(nil);
-    if (icon_ != nil)
+    if (!icon_.empty())
         if ([icon_ hasPrefix:@"file:///"])
             icon = [UIImage imageAtPath:[icon_ substringFromIndex:7]];
     if (icon == nil) if (section != nil)
@@ -2191,7 +2512,7 @@ uint32_t PackageChangesRadix(Package *self, void *) {
 }
 
 - (NSString *) depiction {
-    return depiction_;
+    return !depiction_.empty() ? depiction_ : [[self source] depictionForPackage:id_];
 }
 
 - (Address *) sponsor {
@@ -2211,11 +2532,11 @@ uint32_t PackageChangesRadix(Package *self, void *) {
 }
 
 - (NSString *) support {
-    return support_ != nil ? support_ : [[self source] supportForPackage:id_];
+    return !bugs_.empty() ? bugs_ : [[self source] supportForPackage:id_];
 }
 
 - (NSArray *) files {
-    NSString *path = [NSString stringWithFormat:@"/var/lib/dpkg/info/%@.list", id_];
+    NSString *path = [NSString stringWithFormat:@"/var/lib/dpkg/info/%@.list", static_cast<NSString *>(id_)];
     NSMutableArray *files = [NSMutableArray arrayWithCapacity:128];
 
     std::ifstream fin;
@@ -2240,7 +2561,7 @@ uint32_t PackageChangesRadix(Package *self, void *) {
 
     size_t length(strlen(name));
     if (length < 2) invalid:
-        [warnings addObject:CYLocalize("ILLEGAL_PACKAGE_IDENTIFIER")];
+        [warnings addObject:UCLocalize("ILLEGAL_PACKAGE_IDENTIFIER")];
     else for (size_t i(0); i != length; ++i)
         if (
             /* XXX: technically this is not allowed */
@@ -2252,6 +2573,7 @@ uint32_t PackageChangesRadix(Package *self, void *) {
 
     if (strcmp(name, "cydia") != 0) {
         bool cydia = false;
+        bool user = false;
         bool _private = false;
         bool stash = false;
 
@@ -2261,6 +2583,8 @@ uint32_t PackageChangesRadix(Package *self, void *) {
             for (NSString *file in files)
                 if (!cydia && [file isEqualToString:@"/Applications/Cydia.app"])
                     cydia = true;
+                else if (!user && [file isEqualToString:@"/User"])
+                    user = true;
                 else if (!_private && [file isEqualToString:@"/private"])
                     _private = true;
                 else if (!stash && [file isEqualToString:@"/var/stash"])
@@ -2268,11 +2592,13 @@ uint32_t PackageChangesRadix(Package *self, void *) {
 
         /* XXX: this is not sensitive enough. only some folders are valid. */
         if (cydia && !repository)
-            [warnings addObject:[NSString stringWithFormat:CYLocalize("FILES_INSTALLED_TO"), @"Cydia.app"]];
+            [warnings addObject:[NSString stringWithFormat:UCLocalize("FILES_INSTALLED_TO"), @"Cydia.app"]];
+        if (user)
+            [warnings addObject:[NSString stringWithFormat:UCLocalize("FILES_INSTALLED_TO"), @"/User"]];
         if (_private)
-            [warnings addObject:[NSString stringWithFormat:CYLocalize("FILES_INSTALLED_TO"), @"/private"]];
+            [warnings addObject:[NSString stringWithFormat:UCLocalize("FILES_INSTALLED_TO"), @"/private"]];
         if (stash)
-            [warnings addObject:[NSString stringWithFormat:CYLocalize("FILES_INSTALLED_TO"), @"/var/stash"]];
+            [warnings addObject:[NSString stringWithFormat:UCLocalize("FILES_INSTALLED_TO"), @"/var/stash"]];
     }
 
     return [warnings count] == 0 ? nil : warnings;
@@ -2349,7 +2675,7 @@ uint32_t PackageChangesRadix(Package *self, void *) {
     if (range.location != NSNotFound)
         return YES;
 
-    range = [[self tagline] rangeOfString:text options:MatchCompareOptions_];
+    range = [[self shortDescription] rangeOfString:text options:MatchCompareOptions_];
     if (range.location != NSNotFound)
         return YES;
 
@@ -2397,25 +2723,8 @@ uint32_t PackageChangesRadix(Package *self, void *) {
     return [self hasTag:@"cydia::commercial"];
 }
 
-- (uint32_t) compareByPrefix {
-    return 0;
-}
-
-- (NSComparisonResult) compareByName:(Package *)package {
-    NSString *lhs = [self name];
-    NSString *rhs = [package name];
-
-    if ([lhs length] != 0 && [rhs length] != 0) {
-        unichar lhc = [lhs characterAtIndex:0];
-        unichar rhc = [rhs characterAtIndex:0];
-
-        if (isalpha(lhc) && !isalpha(rhc))
-            return NSOrderedAscending;
-        else if (!isalpha(lhc) && isalpha(rhc))
-            return NSOrderedDescending;
-    }
-
-    return [lhs compare:rhs options:LaxCompareOptions_];
+- (CYString &) cyname {
+    return name_.empty() ? id_ : name_;
 }
 
 - (uint32_t) compareBySection:(NSArray *)sections {
@@ -2496,16 +2805,34 @@ uint32_t PackageChangesRadix(Package *self, void *) {
     _end
 }
 
+- (bool) isUnfilteredAndSelectedForBy:(NSString *)search {
+    if ([search length] == 0)
+        return false;
+
+    _profile(Package$isUnfilteredAndSelectedForBy)
+        bool value(true);
+
+        _profile(Package$isUnfilteredAndSelectedForBy$Unfiltered)
+            value &= [self unfiltered];
+        _end
+
+        _profile(Package$isUnfilteredAndSelectedForBy$Match)
+            value &= [[self name] compare:search options:MatchCompareOptions_ range:NSMakeRange(0, [search length])] == NSOrderedSame;
+        _end
+
+        return value;
+    _end
+}
+
 - (bool) isInstalledAndVisible:(NSNumber *)number {
-    return (![number boolValue] || [self visible]) && [self installed] != nil;
+    return (![number boolValue] || [self visible]) && ![self uninstalled];
 }
 
-- (bool) isVisiblyUninstalledInSection:(NSString *)name {
+- (bool) isVisibleInSection:(NSString *)name {
     NSString *section = [self section];
 
     return
-        [self visible] &&
-        [self installed] == nil && (
+        [self visible] && (
             name == nil ||
             section == nil && [name length] == 0 ||
             [name isEqualToString:section]
@@ -2527,9 +2854,10 @@ uint32_t PackageChangesRadix(Package *self, void *) {
     NSString *localized_;
 }
 
-- (NSComparisonResult) compareByName:(Section *)section;
-- (Section *) initWithName:(NSString *)name;
-- (Section *) initWithName:(NSString *)name row:(size_t)row;
+- (NSComparisonResult) compareByLocalized:(Section *)section;
+- (Section *) initWithName:(NSString *)name localized:(NSString *)localized;
+- (Section *) initWithName:(NSString *)name localize:(BOOL)localize;
+- (Section *) initWithName:(NSString *)name row:(size_t)row localize:(BOOL)localize;
 - (Section *) initWithIndex:(unichar)index row:(size_t)row;
 - (NSString *) name;
 - (unichar) index;
@@ -2541,6 +2869,7 @@ uint32_t PackageChangesRadix(Package *self, void *) {
 - (void) addToCount;
 
 - (void) setCount:(size_t)count;
+- (NSString *) localized;
 
 @end
 
@@ -2553,11 +2882,11 @@ uint32_t PackageChangesRadix(Package *self, void *) {
     [super dealloc];
 }
 
-- (NSComparisonResult) compareByName:(Section *)section {
-    NSString *lhs = [self name];
-    NSString *rhs = [section name];
+- (NSComparisonResult) compareByLocalized:(Section *)section {
+    NSString *lhs(localized_);
+    NSString *rhs([section localized]);
 
-    if ([lhs length] != 0 && [rhs length] != 0) {
+    /*if ([lhs length] != 0 && [rhs length] != 0) {
         unichar lhc = [lhs characterAtIndex:0];
         unichar rhc = [rhs characterAtIndex:0];
 
@@ -2565,28 +2894,36 @@ uint32_t PackageChangesRadix(Package *self, void *) {
             return NSOrderedAscending;
         else if (!isalpha(lhc) && isalpha(rhc))
             return NSOrderedDescending;
-    }
+    }*/
 
     return [lhs compare:rhs options:LaxCompareOptions_];
 }
 
-- (Section *) initWithName:(NSString *)name {
-    return [self initWithName:name row:0];
+- (Section *) initWithName:(NSString *)name localized:(NSString *)localized {
+    if ((self = [self initWithName:name localize:NO]) != nil) {
+        if (localized != nil)
+            localized_ = [localized retain];
+    } return self;
+}
+
+- (Section *) initWithName:(NSString *)name localize:(BOOL)localize {
+    return [self initWithName:name row:0 localize:localize];
 }
 
-- (Section *) initWithName:(NSString *)name row:(size_t)row {
+- (Section *) initWithName:(NSString *)name row:(size_t)row localize:(BOOL)localize {
     if ((self = [super init]) != nil) {
         name_ = [name retain];
         index_ = '\0';
         row_ = row;
-        localized_ = [LocalizeSection(name_) retain];
+        if (localize)
+            localized_ = [LocalizeSection(name_) retain];
     } return self;
 }
 
 /* XXX: localize the index thingees */
 - (Section *) initWithIndex:(unichar)index row:(size_t)row {
     if ((self = [super init]) != nil) {
-        name_ = [(index == '#' ? @"123" : [NSString stringWithCharacters:&index length:1]) retain];
+        name_ = [[NSString stringWithCharacters:&index length:1] retain];
         index_ = index;
         row_ = row;
     } return self;
@@ -2627,8 +2964,9 @@ uint32_t PackageChangesRadix(Package *self, void *) {
 @end
 /* }}} */
 
-static int Finish_;
-static NSArray *Finishes_;
+static NSString *Colon_;
+static NSString *Error_;
+static NSString *Warning_;
 
 /* Database Implementation {{{ */
 @implementation Database
@@ -2672,7 +3010,7 @@ static NSArray *Finishes_;
         }
     }
 
-    _assert(false);
+    _assume(false);
 }
 
 - (void) _readStatus:(NSNumber *)fd { _pooled
@@ -2685,7 +3023,7 @@ static NSArray *Finishes_;
 
     while (std::getline(is, line)) {
         const char *data(line.c_str());
-        size_t size = line.size();
+        size_t size(line.size());
         lprintf("S:%s\n", data);
 
         if (conffile_r(data, size)) {
@@ -2703,7 +3041,7 @@ static NSArray *Finishes_;
             NSString *string = pmstatus_r[4];
 
             if (type == "pmerror")
-                [delegate_ performSelectorOnMainThread:@selector(_setProgressError:)
+                [delegate_ performSelectorOnMainThread:@selector(_setProgressErrorPackage:)
                     withObject:[NSArray arrayWithObjects:string, id, nil]
                     waitUntilDone:YES
                 ];
@@ -2711,11 +3049,13 @@ static NSArray *Finishes_;
                 [delegate_ setProgressTitle:string];
             } else if (type == "pmconffile")
                 [delegate_ setConfigurationData:string];
-            else _assert(false);
-        } else _assert(false);
+            else
+                lprintf("E:unknown pmstatus\n");
+        } else
+            lprintf("E:unknown status\n");
     }
 
-    _assert(false);
+    _assume(false);
 }
 
 - (void) _readOutput:(NSNumber *)fd { _pooled
@@ -2728,7 +3068,7 @@ static NSArray *Finishes_;
         [delegate_ addProgressOutput:[NSString stringWithUTF8String:line.c_str()]];
     }
 
-    _assert(false);
+    _assume(false);
 }
 
 - (FILE *) input {
@@ -2736,11 +3076,12 @@ static NSArray *Finishes_;
 }
 
 - (Package *) packageWithName:(NSString *)name {
+@synchronized ([Database class]) {
     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:pool_ database:self];
-}
+} }
 
 - (Database *) init {
     if ((self = [super init]) != nil) {
@@ -2753,8 +3094,7 @@ static NSArray *Finishes_;
         zone_ = NSCreateZone(1024 * 1024, 256 * 1024, NO);
         apr_pool_create(&pool_, NULL);
 
-        sources_ = [[NSMutableDictionary dictionaryWithCapacity:16] retain];
-        packages_ = [[NSMutableArray arrayWithCapacity:16] retain];
+        packages_ = [[NSMutableArray alloc] init];
 
         int fds[2];
 
@@ -2826,7 +3166,10 @@ static NSArray *Finishes_;
 }
 
 - (NSArray *) sources {
-    return [sources_ allValues];
+    NSMutableArray *sources([NSMutableArray arrayWithCapacity:sources_.size()]);
+    for (SourceMap::const_iterator i(sources_.begin()); i != sources_.end(); ++i)
+        [sources addObject:i->second];
+    return sources;
 }
 
 - (NSArray *) issues {
@@ -2862,8 +3205,10 @@ static NSArray *Finishes_;
             [entry addObject:failure];
             [failure addObject:[NSString stringWithUTF8String:start.DepType()]];
 
-            Package *package([self packageWithName:[NSString stringWithUTF8String:start.TargetPkg().Name()]]);
-            [failure addObject:[package name]];
+            NSString *name([NSString stringWithUTF8String:start.TargetPkg().Name()]);
+            if (Package *package = [self packageWithName:name])
+                name = [package name];
+            [failure addObject:name];
 
             pkgCache::PkgIterator target(start.TargetPkg());
             if (target->ProvidesList != 0)
@@ -2893,11 +3238,47 @@ static NSArray *Finishes_;
     return issues;
 }
 
+- (bool) popErrorWithTitle:(NSString *)title {
+    bool fatal(false);
+    std::string message;
+
+    while (!_error->empty()) {
+        std::string error;
+        bool warning(!_error->PopMessage(error));
+        if (!warning)
+            fatal = true;
+        for (;;) {
+            size_t size(error.size());
+            if (size == 0 || error[size - 1] != '\n')
+                break;
+            error.resize(size - 1);
+        }
+        lprintf("%c:[%s]\n", warning ? 'W' : 'E', error.c_str());
+
+        if (!message.empty())
+            message += "\n\n";
+        message += error;
+    }
+
+    if (fatal && !message.empty())
+        [delegate_ _setProgressError:[NSString stringWithUTF8String:message.c_str()] withTitle:[NSString stringWithFormat:Colon_, fatal ? Error_ : Warning_, title]];
+
+    return fatal;
+}
+
+- (bool) popErrorWithTitle:(NSString *)title forOperation:(bool)success {
+    return [self popErrorWithTitle:title] || !success;
+}
+
 - (void) reloadData { _pooled
+@synchronized ([Database class]) {
     @synchronized (self) {
         ++era_;
     }
 
+    [packages_ removeAllObjects];
+    sources_.clear();
+
     _error->Discard();
 
     delete list_;
@@ -2914,6 +3295,11 @@ static NSArray *Finishes_;
     delete policy_;
     policy_ = NULL;
 
+    if (now_ != nil) {
+        [now_ release];
+        now_ = nil;
+    }
+
     cache_.Close();
 
     apr_pool_clear(pool_);
@@ -2923,12 +3309,12 @@ static NSArray *Finishes_;
     if (chk != -1)
         close(chk);
 
+    NSString *title(UCLocalize("DATABASE"));
+
     _trace();
-    if (!cache_.Open(progress_, true)) {
+    if (!cache_.Open(progress_, true)) { pop:
         std::string error;
-        if (!_error->PopMessage(error))
-            _assert(false);
-        _error->Discard();
+        bool warning(!_error->PopMessage(error));
         lprintf("cache_.Open():[%s]\n", error.c_str());
 
         if (error == "dpkg was interrupted, you must manually run 'dpkg --configure -a' to correct the problem. ")
@@ -2938,8 +3324,12 @@ static NSArray *Finishes_;
         // else if (error == "Could not open lock file /var/lib/dpkg/lock - open (13 Permission denied)")
         // else if (error == "Could not get lock /var/lib/dpkg/lock - open (35 Resource temporarily unavailable)")
         // else if (error == "The list of sources could not be read.")
-        else _assert(false);
+        else
+            [delegate_ _setProgressError:[NSString stringWithUTF8String:error.c_str()] withTitle:[NSString stringWithFormat:Colon_, warning ? Warning_ : Error_, title]];
 
+        if (warning)
+            goto pop;
+        _error->Discard();
         return;
     }
     _trace();
@@ -2955,62 +3345,107 @@ static NSArray *Finishes_;
     lock_ = NULL;
 
     list_ = new pkgSourceList();
-    _assert(list_->ReadMainList());
+    if ([self popErrorWithTitle:title forOperation:list_->ReadMainList()])
+        return;
+
+    if (cache_->DelCount() != 0 || cache_->InstCount() != 0) {
+        [delegate_ _setProgressError:@"COUNTS_NONZERO_EX" withTitle:title];
+        return;
+    }
 
-    _assert(cache_->DelCount() == 0 && cache_->InstCount() == 0);
-    _assert(pkgApplyStatus(cache_));
+    if ([self popErrorWithTitle:title forOperation:pkgApplyStatus(cache_)])
+        return;
 
     if (cache_->BrokenCount() != 0) {
-        _assert(pkgFixBroken(cache_));
-        _assert(cache_->BrokenCount() == 0);
-        _assert(pkgMinimizeUpgrade(cache_));
-    }
+        if ([self popErrorWithTitle:title forOperation:pkgFixBroken(cache_)])
+            return;
 
-    _trace();
-    {
-        std::string lists(_config->FindDir("Dir::State::lists"));
-
-        [sources_ removeAllObjects];
-        for (pkgSourceList::const_iterator source = list_->begin(); source != list_->end(); ++source) {
-            std::vector<pkgIndexFile *> *indices = (*source)->GetIndexFiles();
-            for (std::vector<pkgIndexFile *>::const_iterator index = indices->begin(); index != indices->end(); ++index)
-                if (debPackagesIndex *packages = dynamic_cast<debPackagesIndex *>(*index))
-                    [sources_
-                        setObject:[[[Source alloc] initWithMetaIndex:*source] autorelease]
-                        forKey:[NSString stringWithFormat:@"%s%s",
-                            lists.c_str(),
-                            URItoFileName(packages->IndexURI("Packages")).c_str()
-                        ]
-                    ];
+        if (cache_->BrokenCount() != 0) {
+            [delegate_ _setProgressError:@"STILL_BROKEN_EX" withTitle:title];
+            return;
         }
+
+        if ([self popErrorWithTitle:title forOperation:pkgMinimizeUpgrade(cache_)])
+            return;
     }
-    _trace();
 
-    [packages_ removeAllObjects];
     _trace();
-    for (pkgCache::PkgIterator iterator = cache_->PkgBegin(); !iterator.end(); ++iterator)
-        if (Package *package = [Package packageWithIterator:iterator withZone:zone_ inPool:pool_ database:self])
-            [packages_ addObject:package];
-    _trace();
-    [packages_ sortUsingSelector:@selector(compareByName:)];
+
+    for (pkgSourceList::const_iterator source = list_->begin(); source != list_->end(); ++source) {
+        std::vector<pkgIndexFile *> *indices = (*source)->GetIndexFiles();
+        for (std::vector<pkgIndexFile *>::const_iterator index = indices->begin(); index != indices->end(); ++index)
+            // XXX: this could be more intelligent
+            if (dynamic_cast<debPackagesIndex *>(*index) != NULL) {
+                pkgCache::PkgFileIterator cached((*index)->FindInCache(cache_));
+                if (!cached.end())
+                    sources_[cached->ID] = [[[Source alloc] initWithMetaIndex:*source inPool:pool_] autorelease];
+            }
+    }
+
     _trace();
 
-    _config->Set("Acquire::http::Timeout", 15);
-    _config->Set("Acquire::http::MaxParallel", 4);
-}
+    {
+        /*std::vector<Package *> packages;
+        packages.reserve(std::max(10000U, [packages_ count] + 1000));
+        [packages_ release];
+        packages_ = nil;*/
+
+        _trace();
+
+        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);
+                [packages_ addObject:package];
+
+        _trace();
+
+        /*if (packages.empty())
+            packages_ = [[NSArray alloc] init];
+        else
+            packages_ = [[NSArray alloc] initWithObjects:&packages.front() count:packages.size()];
+        _trace();*/
+
+        [packages_ radixSortUsingFunction:reinterpret_cast<SKRadixFunction>(&PackagePrefixRadix) withContext:reinterpret_cast<void *>(16)];
+        [packages_ radixSortUsingFunction:reinterpret_cast<SKRadixFunction>(&PackagePrefixRadix) withContext:reinterpret_cast<void *>(4)];
+        [packages_ radixSortUsingFunction:reinterpret_cast<SKRadixFunction>(&PackagePrefixRadix) withContext:reinterpret_cast<void *>(0)];
+
+        /*_trace();
+        PrintTimes();
+        _trace();*/
+
+        _trace();
+
+        /*if (!packages.empty())
+            CFQSortArray(&packages.front(), packages.size(), sizeof(packages.front()), reinterpret_cast<CFComparatorFunction>(&PackageNameCompare_), NULL);*/
+        //std::sort(packages.begin(), packages.end(), PackageNameOrdering());
+
+        //CFArraySortValues((CFMutableArrayRef) packages_, CFRangeMake(0, [packages_ count]), reinterpret_cast<CFComparatorFunction>(&PackageNameCompare), NULL);
+
+        CFArrayInsertionSortValues((CFMutableArrayRef) packages_, CFRangeMake(0, [packages_ count]), reinterpret_cast<CFComparatorFunction>(&PackageNameCompare), NULL);
+
+        //[packages_ sortUsingFunction:reinterpret_cast<NSComparisonResult (*)(id, id, void *)>(&PackageNameCompare) context:NULL];
+
+        _trace();
+    }
+} }
 
 - (void) configure {
     NSString *dpkg = [NSString stringWithFormat:@"dpkg --configure -a --status-fd %u", statusfd_];
     system([dpkg UTF8String]);
 }
 
-- (void) clean {
+- (bool) clean {
+    // XXX: I don't remember this condition
     if (lock_ != NULL)
-        return;
+        return false;
 
     FileFd Lock;
     Lock.Fd(GetLock(_config->FindDir("Dir::Cache::Archives") + "lock"));
-    _assert(!_error->PendingError());
+
+    NSString *title(UCLocalize("CLEAN_ARCHIVES"));
+
+    if ([self popErrorWithTitle:title])
+        return false;
 
     pkgAcquire fetcher;
     fetcher.Clean(_config->FindDir("Dir::Cache::Archives"));
@@ -3024,33 +3459,43 @@ static NSArray *Finishes_;
         }
     } cleaner;
 
-    if (!cleaner.Go(_config->FindDir("Dir::Cache::Archives") + "partial/", cache_)) {
-        std::string error;
-        while (_error->PopMessage(error))
-            lprintf("ArchiveCleaner: %s\n", error.c_str());
-    }
+    if ([self popErrorWithTitle:title forOperation:cleaner.Go(_config->FindDir("Dir::Cache::Archives") + "partial/", cache_)])
+        return false;
+
+    return true;
 }
 
-- (void) prepare {
+- (bool) prepare {
+    fetcher_->Shutdown();
+
     pkgRecords records(cache_);
 
     lock_ = new FileFd();
     lock_->Fd(GetLock(_config->FindDir("Dir::Cache::Archives") + "lock"));
-    _assert(!_error->PendingError());
 
-    pkgSourceList list;
-    // XXX: explain this with an error message
-    _assert(list.ReadMainList());
+    NSString *title(UCLocalize("PREPARE_ARCHIVES"));
+
+    if ([self popErrorWithTitle:title])
+        return false;
+
+    pkgSourceList list;
+    if ([self popErrorWithTitle:title forOperation:list.ReadMainList()])
+        return false;
 
     manager_ = (_system->CreatePM(cache_));
-    _assert(manager_->GetArchives(fetcher_, &list, &records));
-    _assert(!_error->PendingError());
+    if ([self popErrorWithTitle:title forOperation:manager_->GetArchives(fetcher_, &list, &records)])
+        return false;
+
+    return true;
 }
 
 - (void) perform {
+    NSString *title(UCLocalize("PERFORM_SELECTIONS"));
+
     NSMutableArray *before = [NSMutableArray arrayWithCapacity:16]; {
         pkgSourceList list;
-        _assert(list.ReadMainList());
+        if ([self popErrorWithTitle:title forOperation:list.ReadMainList()])
+            return;
         for (pkgSourceList::const_iterator source = list.begin(); source != list.end(); ++source)
             [before addObject:[NSString stringWithUTF8String:(*source)->GetURI().c_str()]];
     }
@@ -3064,6 +3509,8 @@ static NSArray *Finishes_;
     for (pkgAcquire::ItemIterator item = fetcher_->ItemsBegin(); item != fetcher_->ItemsEnd(); item++) {
         if ((*item)->Status == pkgAcquire::Item::StatDone && (*item)->Complete)
             continue;
+        if ((*item)->Status == pkgAcquire::Item::StatIdle)
+            continue;
 
         std::string uri = (*item)->DescURI();
         std::string error = (*item)->ErrorText;
@@ -3071,7 +3518,7 @@ static NSArray *Finishes_;
         lprintf("pAf:%s:%s\n", uri.c_str(), error.c_str());
         failed = true;
 
-        [delegate_ performSelectorOnMainThread:@selector(_setProgressError:)
+        [delegate_ performSelectorOnMainThread:@selector(_setProgressErrorPackage:)
             withObject:[NSArray arrayWithObjects:
                 [NSString stringWithUTF8String:error.c_str()],
             nil]
@@ -3104,7 +3551,8 @@ static NSArray *Finishes_;
 
     NSMutableArray *after = [NSMutableArray arrayWithCapacity:16]; {
         pkgSourceList list;
-        _assert(list.ReadMainList());
+        if ([self popErrorWithTitle:title forOperation:list.ReadMainList()])
+            return;
         for (pkgSourceList::const_iterator source = list.begin(); source != list.end(); ++source)
             [after addObject:[NSString stringWithUTF8String:(*source)->GetURI().c_str()]];
     }
@@ -3113,41 +3561,40 @@ static NSArray *Finishes_;
         [self update];
 }
 
-- (void) upgrade {
-    _assert(pkgDistUpgrade(cache_));
+- (bool) upgrade {
+    NSString *title(UCLocalize("UPGRADE"));
+    if ([self popErrorWithTitle:title forOperation:pkgDistUpgrade(cache_)])
+        return false;
+    return true;
 }
 
 - (void) update {
     [self updateWithStatus:status_];
 }
 
+- (void) setVisible {
+    for (Package *package in packages_)
+        [package setVisible];
+}
+
 - (void) updateWithStatus:(Status &)status {
+    _transient NSObject<ProgressDelegate> *delegate(status.getDelegate());
+    NSString *title(UCLocalize("REFRESHING_DATA"));
+
     pkgSourceList list;
-    _assert(list.ReadMainList());
+    if (!list.ReadMainList())
+        [delegate _setProgressError:@"Unable to read source list." withTitle:title];
 
     FileFd lock;
     lock.Fd(GetLock(_config->FindDir("Dir::State::Lists") + "lock"));
-    _assert(!_error->PendingError());
-
-    pkgAcquire fetcher(&status);
-    _assert(list.GetIndexes(&fetcher));
-
-    if (fetcher.Run(PulseInterval_) != pkgAcquire::Failed) {
-        bool failed = false;
-        for (pkgAcquire::ItemIterator item = fetcher.ItemsBegin(); item != fetcher.ItemsEnd(); item++)
-            if ((*item)->Status != pkgAcquire::Item::StatDone) {
-                (*item)->Finished();
-                failed = true;
-            }
+    if ([self popErrorWithTitle:title])
+        return;
 
-        if (!failed && _config->FindB("APT::Get::List-Cleanup", true) == true) {
-            _assert(fetcher.Clean(_config->FindDir("Dir::State::lists")));
-            _assert(fetcher.Clean(_config->FindDir("Dir::State::lists") + "partial/"));
-        }
+    if ([self popErrorWithTitle:title forOperation:ListUpdate(status, list, PulseInterval_)])
+        /* XXX: ignore this because users suck and don't understand why refreshing is important: return */;
 
-        [Metadata_ setObject:[NSDate date] forKey:@"LastUpdate"];
-        Changed_ = true;
-    }
+    [Metadata_ setObject:[NSDate date] forKey:@"LastUpdate"];
+    Changed_ = true;
 }
 
 - (void) setDelegate:(id)delegate {
@@ -3157,163 +3604,376 @@ static NSArray *Finishes_;
 }
 
 - (Source *) getSource:(pkgCache::PkgFileIterator)file {
-    if (const char *name = file.FileName())
-        if (Source *source = [sources_ objectForKey:[NSString stringWithUTF8String:name]])
-            return source;
-    return nil;
+    SourceMap::const_iterator i(sources_.find(file->ID));
+    return i == sources_.end() ? nil : i->second;
 }
 
 @end
 /* }}} */
 
-/* PopUp Windows {{{ */
-@interface PopUpView : UIView {
-    _transient id delegate_;
-    UITransitionView *transition_;
-    UIView *overlay_;
+/* Confirmation View {{{ */
+bool DepSubstrate(const pkgCache::VerIterator &iterator) {
+    if (!iterator.end())
+        for (pkgCache::DepIterator dep(iterator.DependsList()); !dep.end(); ++dep) {
+            if (dep->Type != pkgCache::Dep::Depends && dep->Type != pkgCache::Dep::PreDepends)
+                continue;
+            pkgCache::PkgIterator package(dep.TargetPkg());
+            if (package.end())
+                continue;
+            if (strcmp(package.Name(), "mobilesubstrate") == 0)
+                return true;
+        }
+
+    return false;
 }
 
-- (void) cancel;
-- (id) initWithView:(UIView *)view delegate:(id)delegate;
+/* Web Scripting {{{ */
+@interface CydiaObject : NSObject {
+    id indirect_;
+    id delegate_;
+}
 
+- (id) initWithDelegate:(IndirectDelegate *)indirect;
 @end
 
-@implementation PopUpView
+@implementation CydiaObject
 
 - (void) dealloc {
-    [transition_ setDelegate:nil];
-    [transition_ release];
-    [overlay_ release];
+    [indirect_ release];
     [super dealloc];
 }
 
-- (void) cancel {
-    [transition_ transition:UITransitionPushFromTop toView:nil];
+- (id) initWithDelegate:(IndirectDelegate *)indirect {
+    if ((self = [super init]) != nil) {
+        indirect_ = [indirect retain];
+    } return self;
 }
 
-- (void) transitionViewDidComplete:(UITransitionView*)view fromView:(UIView*)from toView:(UIView*)to {
-    if (from != nil && to == nil)
-        [self removeFromSuperview];
+- (void) setDelegate:(id)delegate {
+    delegate_ = delegate;
 }
 
-- (id) initWithView:(UIView *)view delegate:(id)delegate {
-    if ((self = [super initWithFrame:[view bounds]]) != nil) {
-        delegate_ = delegate;
++ (NSArray *) _attributeKeys {
+    return [NSArray arrayWithObjects:@"device", @"firewire", @"imei", @"mac", @"serial", nil];
+}
 
-        transition_ = [[UITransitionView alloc] initWithFrame:[self bounds]];
-        [self addSubview:transition_];
+- (NSArray *) attributeKeys {
+    return [[self class] _attributeKeys];
+}
 
-        overlay_ = [[UIView alloc] initWithFrame:[transition_ bounds]];
++ (BOOL) isKeyExcludedFromWebScript:(const char *)name {
+    return ![[self _attributeKeys] containsObject:[NSString stringWithUTF8String:name]] && [super isKeyExcludedFromWebScript:name];
+}
 
-        [view addSubview:self];
+- (NSString *) device {
+    return [[UIDevice currentDevice] uniqueIdentifier];
+}
 
-        [transition_ setDelegate:self];
+#if 0 // XXX: implement!
+- (NSString *) mac {
+    if (![indirect_ promptForSensitive:@"Mac Address"])
+        return nil;
+}
 
-        UIView *blank = [[[UIView alloc] initWithFrame:[transition_ bounds]] autorelease];
-        [transition_ transition:UITransitionNone toView:blank];
-        [transition_ transition:UITransitionPushFromBottom toView:overlay_];
-    } return self;
+- (NSString *) serial {
+    if (![indirect_ promptForSensitive:@"Serial #"])
+        return nil;
 }
 
-@end
-/* }}} */
+- (NSString *) firewire {
+    if (![indirect_ promptForSensitive:@"Firewire GUID"])
+        return nil;
+}
 
-#if 0
-/* Mail Composition {{{ */
-@interface MailToView : PopUpView {
-    MailComposeController *controller_;
+- (NSString *) imei {
+    if (![indirect_ promptForSensitive:@"IMEI"])
+        return nil;
 }
+#endif
 
-- (id) initWithView:(UIView *)view delegate:(id)delegate url:(NSURL *)url;
++ (NSString *) webScriptNameForSelector:(SEL)selector {
+    if (selector == @selector(close))
+        return @"close";
+    else if (selector == @selector(getInstalledPackages))
+        return @"getInstalledPackages";
+    else if (selector == @selector(getPackageById:))
+        return @"getPackageById";
+    else if (selector == @selector(installPackages:))
+        return @"installPackages";
+    else if (selector == @selector(setAutoPopup:))
+        return @"setAutoPopup";
+    else if (selector == @selector(setButtonImage:withStyle:toFunction:))
+        return @"setButtonImage";
+    else if (selector == @selector(setButtonTitle:withStyle:toFunction:))
+        return @"setButtonTitle";
+    else if (selector == @selector(setFinishHook:))
+        return @"setFinishHook";
+    else if (selector == @selector(setPopupHook:))
+        return @"setPopupHook";
+    else if (selector == @selector(setSpecial:))
+        return @"setSpecial";
+    else if (selector == @selector(setToken:))
+        return @"setToken";
+    else if (selector == @selector(setViewportWidth:))
+        return @"setViewportWidth";
+    else if (selector == @selector(supports:))
+        return @"supports";
+    else if (selector == @selector(stringWithFormat:arguments:))
+        return @"format";
+    else if (selector == @selector(localizedStringForKey:value:table:))
+        return @"localize";
+    else if (selector == @selector(du:))
+        return @"du";
+    else if (selector == @selector(statfs:))
+        return @"statfs";
+    else
+        return nil;
+}
 
-@end
++ (BOOL) isSelectorExcludedFromWebScript:(SEL)selector {
+    return [self webScriptNameForSelector:selector] == nil;
+}
 
-@implementation MailToView
+- (BOOL) supports:(NSString *)feature {
+    return [feature isEqualToString:@"window.open"];
+}
 
-- (void) dealloc {
-    [controller_ release];
-    [super dealloc];
+- (NSArray *) getInstalledPackages {
+    NSArray *packages([[Database sharedInstance] packages]);
+    NSMutableArray *installed([NSMutableArray arrayWithCapacity:[packages count]]);
+    for (Package *package in packages)
+        if ([package installed] != nil)
+            [installed addObject:package];
+    return installed;
+}
+
+- (Package *) getPackageById:(NSString *)id {
+    Package *package([[Database sharedInstance] packageWithName:id]);
+    [package parse];
+    return package;
+}
+
+- (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);
+
+    int fds[2];
+    _assert(pipe(fds) != -1);
+
+    pid_t pid(ExecFork());
+    if (pid == 0) {
+        _assert(dup2(fds[1], 1) != -1);
+        _assert(close(fds[0]) != -1);
+        _assert(close(fds[1]) != -1);
+        /* XXX: this should probably not use du */
+        execl("/usr/libexec/cydia/du", "du", "-s", [path UTF8String], NULL);
+        exit(1);
+        _assert(false);
+    }
+
+    _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)];
+            }
+        }
+
+        fclose(du);
+    } else _assert(close(fds[0]));
+
+    int status;
+  wait:
+    if (waitpid(pid, &status, 0) == -1)
+        if (errno == EINTR)
+            goto wait;
+        else _assert(false);
+
+    return value;
 }
 
-- (void) mailComposeControllerWillAttemptToSend:(MailComposeController *)controller {
-    NSLog(@"will");
+- (void) close {
+    [indirect_ close];
 }
 
-- (void) mailComposeControllerDidAttemptToSend:(MailComposeController *)controller mailDelivery:(id)delivery {
-    NSLog(@"did:%@", delivery);
-// [UIApp setStatusBarShowsProgress:NO];
-if ([controller error]){
-NSArray *buttons = [NSArray arrayWithObjects:CYLocalize("OK"), nil];
-UIActionSheet *mailAlertSheet = [[UIActionSheet alloc] initWithTitle:CYLocalize("ERROR") buttons:buttons defaultButtonIndex:0 delegate:self context:self];
-[mailAlertSheet setBodyText:[controller error]];
-[mailAlertSheet popupAlertAnimated:YES];
+- (void) installPackages:(NSArray *)packages {
+    [delegate_ performSelectorOnMainThread:@selector(installPackages:) withObject:packages waitUntilDone:NO];
 }
+
+- (void) setAutoPopup:(BOOL)popup {
+    [indirect_ setAutoPopup:popup];
 }
 
-- (void) showError {
-    NSLog(@"%@", [controller_ error]);
-    NSArray *buttons = [NSArray arrayWithObjects:CYLocalize("OK"), nil];
-    UIActionSheet *mailAlertSheet = [[UIActionSheet alloc] initWithTitle:CYLocalize("ERROR") buttons:buttons defaultButtonIndex:0 delegate:self context:self];
-    [mailAlertSheet setBodyText:[controller_ error]];
-    [mailAlertSheet popupAlertAnimated:YES];
+- (void) setButtonImage:(NSString *)button withStyle:(NSString *)style toFunction:(id)function {
+    [indirect_ setButtonImage:button withStyle:style toFunction:function];
 }
 
-- (void) deliverMessage { _pooled
-    setuid(501);
-    setgid(501);
+- (void) setButtonTitle:(NSString *)button withStyle:(NSString *)style toFunction:(id)function {
+    [indirect_ setButtonTitle:button withStyle:style toFunction:function];
+}
 
-    if (![controller_ deliverMessage])
-        [self performSelectorOnMainThread:@selector(showError) withObject:nil waitUntilDone:NO];
+- (void) setSpecial:(id)function {
+    [indirect_ setSpecial:function];
 }
 
-- (void) mailComposeControllerCompositionFinished:(MailComposeController *)controller {
-    if ([controller_ needsDelivery])
-        [NSThread detachNewThreadSelector:@selector(deliverMessage) toTarget:self withObject:nil];
-    else
-        [self cancel];
+- (void) setToken:(NSString *)token {
+    if (Token_ != nil)
+        [Token_ release];
+    Token_ = [token retain];
+
+    [Metadata_ setObject:Token_ forKey:@"Token"];
+    Changed_ = true;
 }
 
-- (id) initWithView:(UIView *)view delegate:(id)delegate url:(NSURL *)url {
-    if ((self = [super initWithView:view delegate:delegate]) != nil) {
-        controller_ = [[MailComposeController alloc] initForContentSize:[overlay_ bounds].size];
-        [controller_ setDelegate:self];
-        [controller_ initializeUI];
-        [controller_ setupForURL:url];
+- (void) setFinishHook:(id)function {
+    [indirect_ setFinishHook:function];
+}
 
-        UIView *view([controller_ view]);
-        [overlay_ addSubview:view];
-    } return self;
+- (void) setPopupHook:(id)function {
+    [indirect_ setPopupHook:function];
+}
+
+- (void) setViewportWidth:(float)width {
+    [indirect_ setViewportWidth: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];
 }
 
 @end
 /* }}} */
-#endif
 
-/* Confirmation View {{{ */
-bool DepSubstrate(const pkgCache::VerIterator &iterator) {
-    if (!iterator.end())
-        for (pkgCache::DepIterator dep(iterator.DependsList()); !dep.end(); ++dep) {
-            if (dep->Type != pkgCache::Dep::Depends && dep->Type != pkgCache::Dep::PreDepends)
-                continue;
-            pkgCache::PkgIterator package(dep.TargetPkg());
-            if (package.end())
-                continue;
-            if (strcmp(package.Name(), "mobilesubstrate") == 0)
-                return true;
-        }
+@interface CydiaBrowserView : BrowserView {
+    CydiaObject *cydia_;
+}
 
-    return false;
+@end
+
+@implementation CydiaBrowserView
+
+- (void) dealloc {
+    [cydia_ release];
+    [super dealloc];
+}
+
+- (void) setHeaders:(NSDictionary *)headers forHost:(NSString *)host {
+}
+
+- (void) webView:(WebView *)sender didClearWindowObject:(WebScriptObject *)window forFrame:(WebFrame *)frame {
+    [super webView:sender didClearWindowObject:window forFrame:frame];
+
+    WebDataSource *source([frame dataSource]);
+    NSURLResponse *response([source response]);
+    NSURL *url([response URL]);
+    NSString *scheme([url scheme]);
+
+    NSHTTPURLResponse *http;
+    if (scheme != nil && ([scheme isEqualToString:@"http"] || [scheme isEqualToString:@"https"]))
+        http = (NSHTTPURLResponse *) response;
+    else
+        http = nil;
+
+    NSDictionary *headers([http allHeaderFields]);
+    NSString *host([url host]);
+    [self setHeaders:headers forHost:host];
+
+    if (
+        [host isEqualToString:@"cydia.saurik.com"] ||
+        [host hasSuffix:@".cydia.saurik.com"] ||
+        [scheme isEqualToString:@"file"]
+    )
+        [window setValue:cydia_ forKey:@"cydia"];
+}
+
+- (void) _setMoreHeaders:(NSMutableURLRequest *)request {
+    if (System_ != NULL)
+        [request setValue:System_ forHTTPHeaderField:@"X-System"];
+    if (Machine_ != NULL)
+        [request setValue:[NSString stringWithUTF8String:Machine_] forHTTPHeaderField:@"X-Machine"];
+    if (Token_ != nil)
+        [request setValue:Token_ forHTTPHeaderField:@"X-Cydia-Token"];
+    if (Role_ != nil)
+        [request setValue:Role_ forHTTPHeaderField:@"X-Role"];
+}
+
+- (NSURLRequest *) webView:(WebView *)sender resource:(id)identifier willSendRequest:(NSURLRequest *)request redirectResponse:(NSURLResponse *)redirectResponse fromDataSource:(WebDataSource *)source {
+    NSMutableURLRequest *copy = [request mutableCopy];
+    [self _setMoreHeaders:copy];
+    return copy;
+}
+
+- (void) setDelegate:(id)delegate {
+    [super setDelegate:delegate];
+    [cydia_ setDelegate:delegate];
+}
+
+- (id) initWithBook:(RVBook *)book forWidth:(float)width {
+    if ((self = [super initWithBook:book forWidth:width ofClass:[CydiaBrowserView class]]) != nil) {
+        cydia_ = [[CydiaObject alloc] initWithDelegate:indirect_];
+
+        WebView *webview([document_ webView]);
+
+        Package *package([[Database sharedInstance] packageWithName:@"cydia"]);
+
+        NSString *application = package == nil ? @"Cydia" : [NSString
+            stringWithFormat:@"Cydia/%@",
+            [package installed]
+        ];
+
+        if (Safari_ != nil)
+            application = [NSString stringWithFormat:@"Safari/%@ %@", Safari_, application];
+        if (Build_ != nil)
+            application = [NSString stringWithFormat:@"Mobile/%@ %@", Build_, application];
+        if (Product_ != nil)
+            application = [NSString stringWithFormat:@"Version/%@ %@", Product_, application];
+
+        [webview setApplicationNameForUserAgent:application];
+    } return self;
 }
 
+@end
+
 @protocol ConfirmationViewDelegate
 - (void) cancel;
 - (void) confirm;
 - (void) queue;
 @end
 
-@interface ConfirmationView : BrowserView {
+@interface ConfirmationView : CydiaBrowserView {
     _transient Database *database_;
-    UIActionSheet *essential_;
+    UIAlertView *essential_;
     NSArray *changes_;
     NSArray *issues_;
     NSArray *sizes_;
@@ -3341,29 +4001,25 @@ bool DepSubstrate(const pkgCache::VerIterator &iterator) {
     [book_ popFromSuperviewAnimated:YES];
 }
 
-- (void) alertSheet:(UIActionSheet *)sheet buttonClicked:(int)button {
-    NSString *context([sheet context]);
+- (void)alertView:(UIAlertView *)alert clickedButtonAtIndex:(NSInteger)button {
+    NSString *context([alert context]);
 
     if ([context isEqualToString:@"remove"]) {
-        switch (button) {
-            case 1:
+               if (button == [alert cancelButtonIndex]) {
                 [self cancel];
-                break;
-            case 2:
+        } else if (button == [alert firstOtherButtonIndex]) {
                 if (substrate_)
                     Finish_ = 2;
                 [delegate_ confirm];
-                break;
-            default:
-                _assert(false);
         }
 
-        [sheet dismiss];
+        [alert dismissWithClickedButtonIndex:-1 animated:YES];
     } else if ([context isEqualToString:@"unable"]) {
         [self cancel];
-        [sheet dismiss];
-    } else
-        [super alertSheet:sheet buttonClicked:button];
+        [alert dismissWithClickedButtonIndex:-1 animated:YES];
+    } else {
+               [super alertView:alert clickedButtonAtIndex:button];
+       }
 }
 
 - (void) webView:(WebView *)sender didClearWindowObject:(WebScriptObject *)window forFrame:(WebFrame *)frame {
@@ -3415,34 +4071,28 @@ bool DepSubstrate(const pkgCache::VerIterator &iterator) {
 
         if (!remove)
             essential_ = nil;
-        else if (Advanced_ || true) {
-            NSString *parenthetical(CYLocalize("PARENTHETICAL"));
-
-            essential_ = [[UIActionSheet alloc]
-                initWithTitle:CYLocalize("REMOVING_ESSENTIALS")
-                buttons:[NSArray arrayWithObjects:
-                    [NSString stringWithFormat:parenthetical, CYLocalize("CANCEL_OPERATION"), CYLocalize("SAFE")],
-                    [NSString stringWithFormat:parenthetical, CYLocalize("FORCE_REMOVAL"), CYLocalize("UNSAFE")],
-                nil]
-                defaultButtonIndex:0
-                delegate:self
-                context:@"remove"
-            ];
-
-#ifndef __OBJC2__
-            [essential_ setDestructiveButton:[[essential_ buttons] objectAtIndex:0]];
-#endif
-            [essential_ setBodyText:CYLocalize("REMOVING_ESSENTIALS_EX")];
+        else if (Advanced_) {
+            NSString *parenthetical(UCLocalize("PARENTHETICAL"));
+
+            essential_ = [[UIAlertView alloc]
+                initWithTitle:UCLocalize("REMOVING_ESSENTIALS")
+                               message:UCLocalize("REMOVING_ESSENTIALS_EX")
+                               delegate:self
+                               cancelButtonTitle:[NSString stringWithFormat:parenthetical, UCLocalize("CANCEL_OPERATION"), UCLocalize("SAFE")]
+                               otherButtonTitles:[NSString stringWithFormat:parenthetical, UCLocalize("FORCE_REMOVAL"), UCLocalize("UNSAFE")], nil
+                       ];
+
+            [essential_ setContext:@"remove"];
         } else {
-            essential_ = [[UIActionSheet alloc]
-                initWithTitle:CYLocalize("UNABLE_TO_COMPLY")
-                buttons:[NSArray arrayWithObjects:CYLocalize("OKAY"), nil]
-                defaultButtonIndex:0
-                delegate:self
-                context:@"unable"
+            essential_ = [[UIAlertView alloc]
+                initWithTitle:UCLocalize("UNABLE_TO_COMPLY")
+                               message:UCLocalize("UNABLE_TO_COMPLY_EX")
+                               delegate:self
+                               cancelButtonTitle:UCLocalize("OKAY")
+                               otherButtonTitles:nil
             ];
 
-            [essential_ setBodyText:CYLocalize("UNABLE_TO_COMPLY_EX")];
+                       [essential_ setContext:@"unable"];
         }
 
         changes_ = [[NSArray alloc] initWithObjects:
@@ -3464,15 +4114,17 @@ bool DepSubstrate(const pkgCache::VerIterator &iterator) {
         nil];
 
         [self loadURL:[NSURL fileURLWithPath:[[NSBundle mainBundle] pathForResource:@"confirm" ofType:@"html"]]];
+
+        [self setAutoresizingMask:UIViewAutoresizingFlexibleBoth];
     } return self;
 }
 
 - (NSString *) backButtonTitle {
-    return CYLocalize("CONFIRM");
+    return UCLocalize("CONFIRM");
 }
 
 - (NSString *) leftButtonTitle {
-    return [NSString stringWithFormat:CYLocalize("SLASH_DELIMITED"), CYLocalize("CANCEL"), CYLocalize("QUEUE")];
+    return [NSString stringWithFormat:UCLocalize("SLASH_DELIMITED"), UCLocalize("CANCEL"), UCLocalize("QUEUE")];
 }
 
 - (id) rightButtonTitle {
@@ -3483,7 +4135,7 @@ bool DepSubstrate(const pkgCache::VerIterator &iterator) {
 #if AlwaysReload || IgnoreInstall
     return [super _rightButtonTitle];
 #else
-    return CYLocalize("CONFIRM");
+    return UCLocalize("CONFIRM");
 #endif
 }
 
@@ -3566,11 +4218,9 @@ bool DepSubstrate(const pkgCache::VerIterator &iterator) {
     BOOL running_;
     SHA1SumValue springlist_;
     SHA1SumValue notifyconf_;
-    SHA1SumValue sandplate_;
+    NSString *title_;
 }
 
-- (void) transitionViewDidComplete:(UITransitionView*)view fromView:(UIView*)from toView:(UIView*)to;
-
 - (id) initWithFrame:(struct CGRect)frame database:(Database *)database delegate:(id)delegate;
 - (void) setContentView:(UIView *)view;
 - (void) resetView;
@@ -3603,31 +4253,26 @@ bool DepSubstrate(const pkgCache::VerIterator &iterator) {
     [output_ release];
     [status_ release];
     [close_ release];
+    if (title_ != nil)
+        [title_ release];
     [super dealloc];
 }
 
-- (void) transitionViewDidComplete:(UITransitionView*)view fromView:(UIView*)from toView:(UIView*)to {
-    if (bootstrap_ && from == overlay_ && to == view_)
-        exit(0);
-}
-
 - (id) initWithFrame:(struct CGRect)frame database:(Database *)database delegate:(id)delegate {
     if ((self = [super initWithFrame:frame]) != nil) {
         database_ = database;
         delegate_ = delegate;
 
         transition_ = [[UITransitionView alloc] initWithFrame:[self bounds]];
+        [transition_ setAutoresizingMask:UIViewAutoresizingFlexibleBoth];
         [transition_ setDelegate:self];
 
         overlay_ = [[UIView alloc] initWithFrame:[transition_ bounds]];
+        [overlay_ setAutoresizingMask:UIViewAutoresizingFlexibleBoth];
 
-        if (bootstrap_)
-            [overlay_ setBackgroundColor:[UIColor blackColor]];
-        else {
-            background_ = [[UIView alloc] initWithFrame:[self bounds]];
-            [background_ setBackgroundColor:[UIColor blackColor]];
-            [self addSubview:background_];
-        }
+        background_ = [[UIView alloc] initWithFrame:[self bounds]];
+        [background_ setBackgroundColor:[UIColor blackColor]];
+        [self addSubview:background_];
 
         [self addSubview:transition_];
 
@@ -3635,6 +4280,7 @@ bool DepSubstrate(const pkgCache::VerIterator &iterator) {
         CGRect navrect = {{0, 0}, navsize};
 
         navbar_ = [[UINavigationBar alloc] initWithFrame:navrect];
+        [navbar_ setAutoresizingMask:UIViewAutoresizingFlexibleWidth];
         [overlay_ addSubview:navbar_];
 
         [navbar_ setBarStyle:1];
@@ -3652,6 +4298,7 @@ bool DepSubstrate(const pkgCache::VerIterator &iterator) {
         }, prgsize};
 
         progress_ = [[UIProgressBar alloc] initWithFrame:prgrect];
+        [progress_ setAutoresizingMask:(UIViewAutoresizingFlexibleWidth | UIViewAutoresizingFlexibleTopMargin)];
         [progress_ setStyle:0];
 
         status_ = [[UITextLabel alloc] initWithFrame:CGRectMake(
@@ -3661,12 +4308,13 @@ bool DepSubstrate(const pkgCache::VerIterator &iterator) {
             24
         )];
 
+        [status_ setAutoresizingMask:(UIViewAutoresizingFlexibleWidth | UIViewAutoresizingFlexibleTopMargin)];
+
         [status_ setColor:[UIColor whiteColor]];
         [status_ setBackgroundColor:[UIColor clearColor]];
 
         [status_ setCentersHorizontally:YES];
         //[status_ setFont:font];
-        _trace();
 
         output_ = [[UITextView alloc] initWithFrame:CGRectMake(
             10,
@@ -3674,10 +4322,12 @@ bool DepSubstrate(const pkgCache::VerIterator &iterator) {
             bounds.size.width - 20,
             bounds.size.height - navsize.height - 62 - navrect.size.height
         )];
-        _trace();
+
+        [output_ setAutoresizingMask:UIViewAutoresizingFlexibleBoth];
+        [overlay_ addSubview:output_];
 
         //[output_ setTextFont:@"Courier New"];
-        [output_ setTextSize:12];
+        [output_ setFont:[[output_ font] fontWithSize:12]];
 
         [output_ setTextColor:[UIColor whiteColor]];
         [output_ setBackgroundColor:[UIColor clearColor]];
@@ -3686,8 +4336,6 @@ bool DepSubstrate(const pkgCache::VerIterator &iterator) {
         [output_ setAllowsRubberBanding:YES];
         [output_ setEditable:NO];
 
-        [overlay_ addSubview:output_];
-
         close_ = [[UIPushButton alloc] initWithFrame:CGRectMake(
             10,
             bounds.size.height - prgsize.height - 50,
@@ -3695,6 +4343,8 @@ bool DepSubstrate(const pkgCache::VerIterator &iterator) {
             32 + prgsize.height
         )];
 
+        [close_ setAutoresizingMask:(UIViewAutoresizingFlexibleWidth | UIViewAutoresizingFlexibleTopMargin)];
+
         [close_ setAutosizesToFit:NO];
         [close_ setDrawsShadow:YES];
         [close_ setStretchBackground:YES];
@@ -3703,7 +4353,7 @@ bool DepSubstrate(const pkgCache::VerIterator &iterator) {
         UIFont *bold = [UIFont boldSystemFontOfSize:22];
         [close_ setTitleFont:bold];
 
-        [close_ addTarget:self action:@selector(closeButtonPushed) forEvents:kUIControlEventMouseUpInside];
+        [close_ addTarget:self action:@selector(closeButtonPushed) forEvents:UIControlEventTouchUpInside];
         [close_ setBackground:[UIImage applicationImageNamed:@"green-up.png"] forState:0];
         [close_ setBackground:[UIImage applicationImageNamed:@"green-dn.png"] forState:1];
     } return self;
@@ -3717,28 +4367,16 @@ bool DepSubstrate(const pkgCache::VerIterator &iterator) {
     [transition_ transition:6 toView:view_];
 }
 
-- (void) alertSheet:(UIActionSheet *)sheet buttonClicked:(int)button {
-    NSString *context([sheet context]);
-
-    if ([context isEqualToString:@"error"])
-        [sheet dismiss];
-    else if ([context isEqualToString:@"conffile"]) {
-        FILE *input = [database_ input];
-
-        switch (button) {
-            case 1:
-                fprintf(input, "N\n");
-                fflush(input);
-                break;
-            case 2:
-                fprintf(input, "Y\n");
-                fflush(input);
-                break;
-            default:
-                _assert(false);
-        }
+- (void)alertView:(UIAlertView *)alert clickedButtonAtIndex:(NSInteger)button {
+    NSString *context([alert context]);
 
-        [sheet dismiss];
+    if ([context isEqualToString:@"conffile"]) {
+               FILE *input = [database_ input];
+        if (button == [alert cancelButtonIndex]) fprintf(input, "N\n");
+        else if (button == [alert firstOtherButtonIndex]) fprintf(input, "Y\n");
+               fflush(input);
+               
+        [alert dismissWithClickedButtonIndex:-1 animated:YES];
     }
 }
 
@@ -3751,7 +4389,11 @@ bool DepSubstrate(const pkgCache::VerIterator &iterator) {
         break;
 
         case 1:
-            [delegate_ suspendWithAnimation:YES];
+            [delegate_ terminateWithSuccess];
+            /*if ([delegate_ respondsToSelector:@selector(suspendWithAnimation:)])
+                [delegate_ suspendWithAnimation:YES];
+            else
+                [delegate_ suspend];*/
         break;
 
         case 2:
@@ -3769,96 +4411,51 @@ bool DepSubstrate(const pkgCache::VerIterator &iterator) {
 }
 
 - (void) _retachThread {
-    UINavigationItem *item = [navbar_ topItem];
-    [item setTitle:CYLocalize("COMPLETE")];
+    UINavigationItem *item([navbar_ topItem]);
+    [item setTitle:UCLocalize("COMPLETE")];
 
     [overlay_ addSubview:close_];
     [progress_ removeFromSuperview];
     [status_ removeFromSuperview];
 
+    [database_ popErrorWithTitle:title_];
     [delegate_ progressViewIsComplete:self];
 
     if (Finish_ < 4) {
-        FileFd file(SandboxTemplate_, FileFd::ReadOnly);
-        MMap mmap(file, MMap::ReadOnly);
-        SHA1Summation sha1;
-        sha1.Add(reinterpret_cast<uint8_t *>(mmap.Data()), mmap.Size());
-        if (!(sandplate_ == sha1.Result()))
-            Finish_ = 4;
-    }
-
-    if (Finish_ < 4) {
-        FileFd file(NotifyConfig_, FileFd::ReadOnly);
-        MMap mmap(file, MMap::ReadOnly);
-        SHA1Summation sha1;
-        sha1.Add(reinterpret_cast<uint8_t *>(mmap.Data()), mmap.Size());
-        if (!(notifyconf_ == sha1.Result()))
-            Finish_ = 4;
+        FileFd file;
+        if (!file.Open(NotifyConfig_, FileFd::ReadOnly))
+            _error->Discard();
+        else {
+            MMap mmap(file, MMap::ReadOnly);
+            SHA1Summation sha1;
+            sha1.Add(reinterpret_cast<uint8_t *>(mmap.Data()), mmap.Size());
+            if (!(notifyconf_ == sha1.Result()))
+                Finish_ = 4;
+        }
     }
 
     if (Finish_ < 3) {
-        FileFd file(SpringBoard_, FileFd::ReadOnly);
-        MMap mmap(file, MMap::ReadOnly);
-        SHA1Summation sha1;
-        sha1.Add(reinterpret_cast<uint8_t *>(mmap.Data()), mmap.Size());
-        if (!(springlist_ == sha1.Result()))
-            Finish_ = 3;
+        FileFd file;
+        if (!file.Open(SpringBoard_, FileFd::ReadOnly))
+            _error->Discard();
+        else {
+            MMap mmap(file, MMap::ReadOnly);
+            SHA1Summation sha1;
+            sha1.Add(reinterpret_cast<uint8_t *>(mmap.Data()), mmap.Size());
+            if (!(springlist_ == sha1.Result()))
+                Finish_ = 3;
+        }
     }
 
     switch (Finish_) {
-        case 0: [close_ setTitle:CYLocalize("RETURN_TO_CYDIA")]; break;
-        case 1: [close_ setTitle:CYLocalize("CLOSE_CYDIA")]; break;
-        case 2: [close_ setTitle:CYLocalize("RESTART_SPRINGBOARD")]; break;
-        case 3: [close_ setTitle:CYLocalize("RELOAD_SPRINGBOARD")]; break;
-        case 4: [close_ setTitle:CYLocalize("REBOOT_DEVICE")]; break;
-    }
-
-#define Cache_ "/User/Library/Caches/com.apple.mobile.installation.plist"
-
-    if (NSMutableDictionary *cache = [[NSMutableDictionary alloc] initWithContentsOfFile:@ Cache_]) {
-        [cache autorelease];
-
-        NSFileManager *manager = [NSFileManager defaultManager];
-        NSError *error = nil;
-
-        id system = [cache objectForKey:@"System"];
-        if (system == nil)
-            goto error;
-
-        struct stat info;
-        if (stat(Cache_, &info) == -1)
-            goto error;
-
-        [system removeAllObjects];
-
-        if (NSArray *apps = [manager contentsOfDirectoryAtPath:@"/Applications" error:&error]) {
-            for (NSString *app in apps)
-                if ([app hasSuffix:@".app"]) {
-                    NSString *path = [@"/Applications" stringByAppendingPathComponent:app];
-                    NSString *plist = [path stringByAppendingPathComponent:@"Info.plist"];
-                    if (NSMutableDictionary *info = [[NSMutableDictionary alloc] initWithContentsOfFile:plist]) {
-                        [info autorelease];
-                        if ([info objectForKey:@"CFBundleIdentifier"] != nil) {
-                            [info setObject:path forKey:@"Path"];
-                            [info setObject:@"System" forKey:@"ApplicationType"];
-                            [system addInfoDictionary:info];
-                        }
-                    }
-                }
-        } else goto error;
-
-        [cache writeToFile:@Cache_ atomically:YES];
-
-        if (chown(Cache_, info.st_uid, info.st_gid) == -1)
-            goto error;
-        if (chmod(Cache_, info.st_mode) == -1)
-            goto error;
-
-        if (false) error:
-            lprintf("%s\n", error == nil ? strerror(errno) : [[error localizedDescription] UTF8String]);
+        case 0: [close_ setTitle:UCLocalize("RETURN_TO_CYDIA")]; break;
+        case 1: [close_ setTitle:UCLocalize("CLOSE_CYDIA")]; break;
+        case 2: [close_ setTitle:UCLocalize("RESTART_SPRINGBOARD")]; break;
+        case 3: [close_ setTitle:UCLocalize("RELOAD_SPRINGBOARD")]; break;
+        case 4: [close_ setTitle:UCLocalize("REBOOT_DEVICE")]; break;
     }
 
-    notify_post("com.apple.mobile.application_installed");
+    system("su -c /usr/bin/uicache mobile");
 
     [delegate_ setStatusBarShowsProgress:NO];
 }
@@ -3871,8 +4468,15 @@ bool DepSubstrate(const pkgCache::VerIterator &iterator) {
 }
 
 - (void) detachNewThreadSelector:(SEL)selector toTarget:(id)target withObject:(id)object title:(NSString *)title {
-    UINavigationItem *item = [navbar_ topItem];
-    [item setTitle:title];
+    if (title_ != nil)
+        [title_ release];
+    if (title == nil)
+        title_ = nil;
+    else
+        title_ = [title retain];
+
+    UINavigationItem *item([navbar_ topItem]);
+    [item setTitle:title_];
 
     [status_ setText:nil];
     [output_ setText:@""];
@@ -3886,27 +4490,27 @@ bool DepSubstrate(const pkgCache::VerIterator &iterator) {
     running_ = YES;
 
     {
-        FileFd file(SandboxTemplate_, FileFd::ReadOnly);
-        MMap mmap(file, MMap::ReadOnly);
-        SHA1Summation sha1;
-        sha1.Add(reinterpret_cast<uint8_t *>(mmap.Data()), mmap.Size());
-        sandplate_ = sha1.Result();
-    }
-
-    {
-        FileFd file(NotifyConfig_, FileFd::ReadOnly);
-        MMap mmap(file, MMap::ReadOnly);
-        SHA1Summation sha1;
-        sha1.Add(reinterpret_cast<uint8_t *>(mmap.Data()), mmap.Size());
-        notifyconf_ = sha1.Result();
+        FileFd file;
+        if (!file.Open(NotifyConfig_, FileFd::ReadOnly))
+            _error->Discard();
+        else {
+            MMap mmap(file, MMap::ReadOnly);
+            SHA1Summation sha1;
+            sha1.Add(reinterpret_cast<uint8_t *>(mmap.Data()), mmap.Size());
+            notifyconf_ = sha1.Result();
+        }
     }
 
     {
-        FileFd file(SpringBoard_, FileFd::ReadOnly);
-        MMap mmap(file, MMap::ReadOnly);
-        SHA1Summation sha1;
-        sha1.Add(reinterpret_cast<uint8_t *>(mmap.Data()), mmap.Size());
-        springlist_ = sha1.Result();
+        FileFd file;
+        if (!file.Open(SpringBoard_, FileFd::ReadOnly))
+            _error->Discard();
+        else {
+            MMap mmap(file, MMap::ReadOnly);
+            SHA1Summation sha1;
+            sha1.Add(reinterpret_cast<uint8_t *>(mmap.Data()), mmap.Size());
+            springlist_ = sha1.Result();
+        }
     }
 
     [transition_ transition:6 toView:overlay_];
@@ -3927,7 +4531,7 @@ bool DepSubstrate(const pkgCache::VerIterator &iterator) {
         detachNewThreadSelector:selector
         toTarget:database_
         withObject:nil
-        title:CYLocalize("REPAIRING")
+        title:UCLocalize("REPAIRING")
     ];
 }
 
@@ -3939,19 +4543,16 @@ bool DepSubstrate(const pkgCache::VerIterator &iterator) {
     ];
 }
 
-- (void) setProgressError:(NSString *)error forPackage:(NSString *)id {
-    Package *package = id == nil ? nil : [database_ packageWithName:id];
-
-    UIActionSheet *sheet = [[[UIActionSheet alloc]
-        initWithTitle:(package == nil ? id : [package name])
-        buttons:[NSArray arrayWithObjects:CYLocalize("OKAY"), nil]
+- (void) setProgressError:(NSString *)error withTitle:(NSString *)title {
+    CYActionSheet *sheet([[[CYActionSheet alloc]
+        initWithTitle:title
+        buttons:[NSArray arrayWithObjects:UCLocalize("OKAY"), nil]
         defaultButtonIndex:0
-        delegate:self
-        context:@"error"
-    ] autorelease];
+    ] autorelease]);
 
-    [sheet setBodyText:error];
-    [sheet popupAlertAnimated:YES];
+    [sheet setMessage:error];
+    [sheet yieldToPopupAlertAnimated:YES];
+    [sheet dismiss];
 }
 
 - (void) setProgressTitle:(NSString *)title {
@@ -3988,25 +4589,26 @@ bool DepSubstrate(const pkgCache::VerIterator &iterator) {
 - (void) _setConfigurationData:(NSString *)data {
     static Pcre conffile_r("^'(.*)' '(.*)' ([01]) ([01])$");
 
-    _assert(conffile_r(data));
+    if (!conffile_r(data)) {
+        lprintf("E:invalid conffile\n");
+        return;
+    }
 
     NSString *ofile = conffile_r[1];
     //NSString *nfile = conffile_r[2];
 
-    UIActionSheet *sheet = [[[UIActionSheet alloc]
-        initWithTitle:CYLocalize("CONFIGURATION_UPGRADE")
-        buttons:[NSArray arrayWithObjects:
-            CYLocalize("KEEP_OLD_COPY"),
-            CYLocalize("ACCEPT_NEW_COPY"),
-            // XXX: CYLocalize("SEE_WHAT_CHANGED"),
-        nil]
-        defaultButtonIndex:0
-        delegate:self
-        context:@"conffile"
-    ] autorelease];
+    UIAlertView *alert = [[[UIAlertView alloc]
+        initWithTitle:UCLocalize("CONFIGURATION_UPGRADE")
+               message:[NSString stringWithFormat:@"%@\n\n%@", UCLocalize("CONFIGURATION_UPGRADE_EX"), ofile]
+               delegate:self
+               cancelButtonTitle:UCLocalize("KEEP_OLD_COPY")
+               otherButtonTitles:UCLocalize("ACCEPT_NEW_COPY"),
+        // XXX: UCLocalize("SEE_WHAT_CHANGED"),
+               nil
+       ] autorelease];
 
-    [sheet setBodyText:[NSString stringWithFormat:@"%@\n\n%@", CYLocalize("CONFIGURATION_UPGRADE_EX"), ofile]];
-    [sheet popupAlertAnimated:YES];
+       [alert setContext:@"conffile"];
+    [alert show];
 }
 
 - (void) _setProgressTitle:(NSString *)title {
@@ -4039,24 +4641,56 @@ bool DepSubstrate(const pkgCache::VerIterator &iterator) {
 /* }}} */
 
 /* Package Cell {{{ */
-@interface PackageCell : UITableCell {
+@interface ContentView : UIView {
+    _transient id delegate_;
+}
+
+@end
+
+@interface PackageCell : UITableViewCell {
     UIImage *icon_;
     NSString *name_;
     NSString *description_;
     bool commercial_;
     NSString *source_;
     UIImage *badge_;
-    bool cached_;
     Package *package_;
-#ifdef USE_BADGES
-    UITextLabel *status_;
-#endif
+    UIColor *color_;
+    ContentView *content_;
+    BOOL faded_;
+    float fade_;
+    UIImage *placard_;
 }
 
 - (PackageCell *) init;
 - (void) setPackage:(Package *)package;
 
 + (int) heightForPackage:(Package *)package;
+- (void) drawContentRect:(CGRect)rect;
+
+@end
+
+@implementation ContentView
+
+- (id) initWithFrame:(CGRect)frame {
+    if ((self = [super initWithFrame:frame]) != nil) {
+    } return self;
+}
+
+- (void) setDelegate:(id)delegate {
+    delegate_ = delegate;
+}
+
+/* Fix landscape: redraw when frame changes. */
+- (void) setFrame:(CGRect)frame {
+       [super setFrame:frame];
+       [self setNeedsDisplay];
+}
+
+- (void) drawRect:(CGRect)rect {
+    [super drawRect:rect];
+    [delegate_ drawContentRect:rect];
+}
 
 @end
 
@@ -4088,36 +4722,73 @@ bool DepSubstrate(const pkgCache::VerIterator &iterator) {
         badge_ = nil;
     }
 
+    if (placard_ != nil) {
+        [placard_ release];
+        placard_ = nil;
+    }
+
     [package_ release];
     package_ = nil;
 }
 
 - (void) dealloc {
     [self clearPackage];
-#ifdef USE_BADGES
-    [status_ release];
-#endif
+    [content_ release];
+    [color_ release];
     [super dealloc];
 }
 
+- (float) fade {
+    return faded_ ? [self selectionPercent] : fade_;
+}
+
 - (PackageCell *) init {
-    if ((self = [super init]) != nil) {
-#ifdef USE_BADGES
-        status_ = [[UITextLabel alloc] initWithFrame:CGRectMake(48, 68, 280, 20)];
-        [status_ setBackgroundColor:[UIColor clearColor]];
-        [status_ setFont:small];
-#endif
+    CGRect frame(CGRectMake(0, 0, 320, 74));
+    if ((self = [super initWithFrame:frame reuseIdentifier:@"Package"]) != nil) {
+        UIView *content([self contentView]);
+        CGRect bounds([content bounds]);
+
+        content_ = [[ContentView alloc] initWithFrame:bounds];
+        [content_ setAutoresizingMask:UIViewAutoresizingFlexibleBoth];
+        [content addSubview:content_];
+
+        [content_ setDelegate:self];
+        [content_ setOpaque:YES];
+        if ([self respondsToSelector:@selector(selectionPercent)])
+            faded_ = YES;
+
+        [self setNeedsDisplayOnBoundsChange:YES];
     } return self;
 }
 
+- (void) _setBackgroundColor {
+    UIColor *color;
+    if (NSString *mode = [package_ mode]) {
+        bool remove([mode isEqualToString:@"REMOVE"] || [mode isEqualToString:@"PURGE"]);
+        color = remove ? RemovingColor_ : InstallingColor_;
+    } else
+        color = [UIColor whiteColor];
+
+    [content_ setBackgroundColor:color];
+    [self setNeedsDisplay];
+}
+
 - (void) setPackage:(Package *)package {
     [self clearPackage];
+    [package parse];
 
     Source *source = [package source];
 
     icon_ = [[package icon] retain];
     name_ = [[package name] retain];
-    description_ = [[package tagline] retain];
+
+    if (IsWildcat_)
+        description_ = [package longDescription];
+    if (description_ == nil)
+        description_ = [package shortDescription];
+    if (description_ != nil)
+        description_ = [description_ retain];
+
     commercial_ = [package isCommercial];
 
     package_ = [package retain];
@@ -4129,76 +4800,43 @@ bool DepSubstrate(const pkgCache::VerIterator &iterator) {
         label = [source label];
         trusted = [source trusted];
     } else if ([[package id] isEqualToString:@"firmware"])
-        label = CYLocalize("APPLE");
+        label = UCLocalize("APPLE");
     else
-        label = [NSString stringWithFormat:CYLocalize("SLASH_DELIMITED"), CYLocalize("UNKNOWN"), CYLocalize("LOCAL")];
+        label = [NSString stringWithFormat:UCLocalize("SLASH_DELIMITED"), UCLocalize("UNKNOWN"), UCLocalize("LOCAL")];
 
     NSString *from(label);
 
     NSString *section = [package simpleSection];
     if (section != nil && ![section isEqualToString:label]) {
         section = [[NSBundle mainBundle] localizedStringForKey:section value:nil table:@"Sections"];
-        from = [NSString stringWithFormat:CYLocalize("PARENTHETICAL"), from, section];
+        from = [NSString stringWithFormat:UCLocalize("PARENTHETICAL"), from, section];
     }
 
-    from = [NSString stringWithFormat:CYLocalize("FROM"), from];
+    from = [NSString stringWithFormat:UCLocalize("FROM"), from];
     source_ = [from retain];
 
     if (NSString *purpose = [package primaryPurpose])
         if ((badge_ = [UIImage imageAtPath:[NSString stringWithFormat:@"%@/Purposes/%@.png", App_, purpose]]) != nil)
             badge_ = [badge_ retain];
 
-#ifdef USE_BADGES
-    if (NSString *mode = [package mode]) {
-        [badge_ setImage:[UIImage applicationImageNamed:
-            [mode isEqualToString:@"REMOVE"] || [mode isEqualToString:@"PURGE"] ? @"removing.png" : @"installing.png"
-        ]];
-
-        [status_ setText:[NSString stringWithFormat:CYLocalize("QUEUED_FOR"), CYLocalize(mode)]];
-        [status_ setColor:[UIColor colorWithCGColor:Blueish_]];
-    } else if ([package half]) {
-        [badge_ setImage:[UIImage applicationImageNamed:@"damaged.png"]];
-        [status_ setText:CYLocalize("PACKAGE_DAMAGED")];
-        [status_ setColor:[UIColor redColor]];
-    } else {
-        [badge_ setImage:nil];
-        [status_ setText:nil];
-    }
-#endif
-
-    cached_ = false;
-}
-
-- (void) drawRect:(CGRect)rect {
-    if (!cached_) {
-        UIColor *color;
-
-        if (NSString *mode = [package_ mode]) {
-            bool remove([mode isEqualToString:@"REMOVE"] || [mode isEqualToString:@"PURGE"]);
-            color = remove ? RemovingColor_ : InstallingColor_;
-        } else
-            color = [UIColor whiteColor];
-
-        [self setBackgroundColor:color];
-        cached_ = true;
-    }
+    if ([package installed] != nil)
+        if ((placard_ = [UIImage imageAtPath:[NSString stringWithFormat:@"%@/installed.png", App_]]) != nil)
+            placard_ = [placard_ retain];
 
-    [super drawRect:rect];
+    [self _setBackgroundColor];
+    [content_ setNeedsDisplay];
 }
 
-- (void) drawBackgroundInRect:(CGRect)rect withFade:(float)fade {
-    if (fade == 0) {
-        CGContextRef context(UIGraphicsGetCurrentContext());
-        [[self backgroundColor] set];
-        CGRect back(rect);
-        back.size.height -= 1;
-        CGContextFillRect(context, back);
-    }
+- (void) drawContentRect:(CGRect)rect {
+    bool selected([self isSelected]);
+    float width([self bounds].size.width);
 
-    [super drawBackgroundInRect:rect withFade:fade];
-}
+#if 0
+    CGContextRef context(UIGraphicsGetCurrentContext());
+    [([[self selectedBackgroundView] superview] != nil ? [UIColor clearColor] : [self backgroundColor]) set];
+    CGContextFillRect(context, rect);
+#endif
 
-- (void) drawContentInRect:(CGRect)rect selected:(BOOL)selected {
     if (icon_ != nil) {
         CGRect rect;
         rect.size = [icon_ size];
@@ -4226,36 +4864,32 @@ bool DepSubstrate(const pkgCache::VerIterator &iterator) {
 
     if (!selected)
         UISetColor(commercial_ ? Purple_ : Black_);
-    [name_ drawAtPoint:CGPointMake(48, 8) forWidth:240 withFont:Font18Bold_ ellipsis:2];
-    [source_ drawAtPoint:CGPointMake(58, 29) forWidth:225 withFont:Font12_ ellipsis:2];
+    [name_ drawAtPoint:CGPointMake(48, 8) forWidth:(width - (placard_ == nil ? 80 : 106)) withFont:Font18Bold_ ellipsis:2];
+    [source_ drawAtPoint:CGPointMake(58, 29) forWidth:(width - 95) withFont:Font12_ ellipsis:2];
 
     if (!selected)
         UISetColor(commercial_ ? Purplish_ : Gray_);
-    [description_ drawAtPoint:CGPointMake(12, 46) forWidth:280 withFont:Font14_ ellipsis:2];
+    [description_ drawAtPoint:CGPointMake(12, 46) forWidth:(width - 46) withFont:Font14_ ellipsis:2];
 
-    [super drawContentInRect:rect selected:selected];
+    if (placard_ != nil)
+        [placard_ drawAtPoint:CGPointMake(width - 52, 9)];
 }
 
-- (void) setSelected:(BOOL)selected withFade:(BOOL)fade {
-    cached_ = false;
-    [super setSelected:selected withFade:fade];
+- (void) setSelected:(BOOL)selected animated:(BOOL)fade {
+    //[self _setBackgroundColor];
+    [super setSelected:selected animated:fade];
+    [content_ setNeedsDisplay];
 }
 
 + (int) heightForPackage:(Package *)package {
-    NSString *tagline([package tagline]);
-    int height = tagline == nil || [tagline length] == 0 ? -17 : 0;
-#ifdef USE_BADGES
-    if ([package hasMode] || [package half])
-        return height + 96;
-    else
-#endif
-        return height + 73;
+    return 73;
 }
 
 @end
 /* }}} */
 /* Section Cell {{{ */
 @interface SectionCell : UISimpleTableCell {
+    NSString *basic_;
     NSString *section_;
     NSString *name_;
     NSString *count_;
@@ -4272,6 +4906,11 @@ bool DepSubstrate(const pkgCache::VerIterator &iterator) {
 @implementation SectionCell
 
 - (void) clearSection {
+    if (basic_ != nil) {
+        [basic_ release];
+        basic_ = nil;
+    }
+
     if (section_ != nil) {
         [section_ release];
         section_ = nil;
@@ -4298,17 +4937,16 @@ bool DepSubstrate(const pkgCache::VerIterator &iterator) {
 - (id) init {
     if ((self = [super init]) != nil) {
         icon_ = [[UIImage applicationImageNamed:@"folder.png"] retain];
-
         switch_ = [[_UISwitchSlider alloc] initWithFrame:CGRectMake(218, 9, 60, 25)];
-        [switch_ addTarget:self action:@selector(onSwitch:) forEvents:kUIControlEventMouseUpInside];
+        [switch_ addTarget:self action:@selector(onSwitch:) forEvents:UIControlEventTouchUpInside];
     } return self;
 }
 
 - (void) onSwitch:(id)sender {
-    NSMutableDictionary *metadata = [Sections_ objectForKey:section_];
+    NSMutableDictionary *metadata = [Sections_ objectForKey:basic_];
     if (metadata == nil) {
         metadata = [NSMutableDictionary dictionaryWithCapacity:2];
-        [Sections_ setObject:metadata forKey:section_];
+        [Sections_ setObject:metadata forKey:basic_];
     }
 
     Changed_ = true;
@@ -4327,20 +4965,31 @@ bool DepSubstrate(const pkgCache::VerIterator &iterator) {
     [self clearSection];
 
     if (section == nil) {
-        name_ = [CYLocalize("ALL_PACKAGES") retain];
+        name_ = [UCLocalize("ALL_PACKAGES") retain];
         count_ = nil;
     } else {
-        section_ = [section name];
+        basic_ = [section name];
+        if (basic_ != nil)
+            basic_ = [basic_ retain];
+
+        section_ = [section localized];
         if (section_ != nil)
             section_ = [section_ retain];
-        name_  = [(section_ == nil ? CYLocalize("NO_SECTION") : section_) retain];
+
+        name_  = [(section_ == nil || [section_ length] == 0 ? UCLocalize("NO_SECTION") : section_) retain];
         count_ = [[NSString stringWithFormat:@"%d", [section count]] retain];
 
         if (editing_)
-            [switch_ setValue:(isSectionVisible(section_) ? 1 : 0) animated:NO];
+            [switch_ setValue:(isSectionVisible(basic_) ? 1 : 0) animated:NO];
     }
 }
 
+- (void) setFrame:(CGRect)frame {
+    [super setFrame:frame];
+    CGRect rect([switch_ frame]);
+    [switch_ setFrame:CGRectMake(frame.size.width - 102, 9, rect.size.width, rect.size.height)];
+}
+
 - (void) drawContentInRect:(CGRect)rect selected:(BOOL)selected {
     [icon_ drawInRect:CGRectMake(8, 7, 32, 32)];
 
@@ -4349,7 +4998,12 @@ bool DepSubstrate(const pkgCache::VerIterator &iterator) {
 
     if (!selected)
         UISetColor(Black_);
-    [name_ drawAtPoint:CGPointMake(48, 9) forWidth:(editing_ ? 164 : 250) withFont:Font22Bold_ ellipsis:2];
+
+    float width(rect.size.width + 23);
+    if (editing_)
+        width -= 110;
+
+    [name_ drawAtPoint:CGPointMake(48, 9) forWidth:(width - 70) withFont:Font22Bold_ ellipsis:2];
 
     CGSize size = [count_ sizeWithFont:Font14_];
 
@@ -4421,7 +5075,7 @@ bool DepSubstrate(const pkgCache::VerIterator &iterator) {
         [self addSubview:list_];
 
         UITableColumn *column = [[[UITableColumn alloc]
-            initWithTitle:CYLocalize("NAME")
+            initWithTitle:UCLocalize("NAME")
             identifier:@"name"
             width:[self frame].size.width
         ] autorelease];
@@ -4431,6 +5085,9 @@ bool DepSubstrate(const pkgCache::VerIterator &iterator) {
         [list_ addTableColumn:column];
         [list_ setDelegate:self];
         [list_ setReusesTableCells:YES];
+
+               [list_ setAutoresizingMask:UIViewAutoresizingFlexibleBoth];
+        [self setAutoresizingMask:UIViewAutoresizingFlexibleBoth];
     } return self;
 }
 
@@ -4489,17 +5146,17 @@ bool DepSubstrate(const pkgCache::VerIterator &iterator) {
 }
 
 - (NSString *) title {
-    return CYLocalize("INSTALLED_FILES");
+    return UCLocalize("INSTALLED_FILES");
 }
 
 - (NSString *) backButtonTitle {
-    return CYLocalize("FILES");
+    return UCLocalize("FILES");
 }
 
 @end
 /* }}} */
 /* Package View {{{ */
-@interface PackageView : BrowserView {
+@interface PackageView : CydiaBrowserView {
     _transient Database *database_;
     Package *package_;
     NSString *name_;
@@ -4531,15 +5188,15 @@ bool DepSubstrate(const pkgCache::VerIterator &iterator) {
 
 /* XXX: this is not safe at all... localization of /fail/ */
 - (void) _clickButtonWithName:(NSString *)name {
-    if ([name isEqualToString:CYLocalize("CLEAR")])
+    if ([name isEqualToString:UCLocalize("CLEAR")])
         [delegate_ clearPackage:package_];
-    else if ([name isEqualToString:CYLocalize("INSTALL")])
+    else if ([name isEqualToString:UCLocalize("INSTALL")])
         [delegate_ installPackage:package_];
-    else if ([name isEqualToString:CYLocalize("REINSTALL")])
+    else if ([name isEqualToString:UCLocalize("REINSTALL")])
         [delegate_ installPackage:package_];
-    else if ([name isEqualToString:CYLocalize("REMOVE")])
+    else if ([name isEqualToString:UCLocalize("REMOVE")])
         [delegate_ removePackage:package_];
-    else if ([name isEqualToString:CYLocalize("UPGRADE")])
+    else if ([name isEqualToString:UCLocalize("UPGRADE")])
         [delegate_ installPackage:package_];
     else _assert(false);
 }
@@ -4575,15 +5232,16 @@ bool DepSubstrate(const pkgCache::VerIterator &iterator) {
 
 #if !AlwaysReload
 - (void) __rightButtonClicked {
-    int count = [buttons_ count];
-    _assert(count != 0);
+    int count([buttons_ count]);
+    if (count == 0)
+        return;
 
     if (count == 1)
         [self _clickButtonWithName:[buttons_ objectAtIndex:0]];
     else {
         NSMutableArray *buttons = [NSMutableArray arrayWithCapacity:(count + 1)];
         [buttons addObjectsFromArray:buttons_];
-        [buttons addObject:CYLocalize("CANCEL")];
+        [buttons addObject:UCLocalize("CANCEL")];
 
         [delegate_ slideUp:[[[UIActionSheet alloc]
             initWithTitle:nil
@@ -4605,7 +5263,7 @@ bool DepSubstrate(const pkgCache::VerIterator &iterator) {
 
 - (id) _rightButtonTitle {
     int count = [buttons_ count];
-    return count == 0 ? nil : count != 1 ? CYLocalize("MODIFY") : [buttons_ objectAtIndex:0];
+    return count == 0 ? nil : count != 1 ? UCLocalize("MODIFY") : [buttons_ objectAtIndex:0];
 }
 
 - (NSString *) backButtonTitle {
@@ -4634,32 +5292,37 @@ bool DepSubstrate(const pkgCache::VerIterator &iterator) {
     [buttons_ removeAllObjects];
 
     if (package != nil) {
+        [package parse];
+
         package_ = [package retain];
         name_ = [[package id] retain];
         commercial_ = [package isCommercial];
 
         if ([package_ mode] != nil)
-            [buttons_ addObject:CYLocalize("CLEAR")];
+            [buttons_ addObject:UCLocalize("CLEAR")];
         if ([package_ source] == nil);
         else if ([package_ upgradableAndEssential:NO])
-            [buttons_ addObject:CYLocalize("UPGRADE")];
-        else if ([package_ installed] == nil)
-            [buttons_ addObject:CYLocalize("INSTALL")];
+            [buttons_ addObject:UCLocalize("UPGRADE")];
+        else if ([package_ uninstalled])
+            [buttons_ addObject:UCLocalize("INSTALL")];
         else
-            [buttons_ addObject:CYLocalize("REINSTALL")];
-        if ([package_ installed] != nil)
-            [buttons_ addObject:CYLocalize("REMOVE")];
+            [buttons_ addObject:UCLocalize("REINSTALL")];
+        if (![package_ uninstalled])
+            [buttons_ addObject:UCLocalize("REMOVE")];
 
         if (special_ != NULL) {
-            CGRect frame([webview_ frame]);
+            CGRect frame([document_ frame]);
             frame.size.width = 320;
             frame.size.height = 0;
-            [webview_ setFrame:frame];
+            [document_ setFrame:frame];
 
-            [scroller_ scrollPointVisibleAtTopLeft:CGPointZero];
+            if ([scroller_ respondsToSelector:@selector(scrollPointVisibleAtTopLeft:)])
+                [scroller_ scrollPointVisibleAtTopLeft:CGPointZero];
+            else
+                [scroller_ scrollRectToVisible:CGRectZero animated:NO];
 
             WebThreadLock();
-            [[[webview_ webView] windowScriptObject] setValue:package_ forKey:@"package"];
+            [[[document_ webView] windowScriptObject] setValue:package_ forKey:@"package"];
 
             [self setButtonTitle:nil withStyle:nil toFunction:nil];
 
@@ -4691,7 +5354,9 @@ bool DepSubstrate(const pkgCache::VerIterator &iterator) {
     NSString *title_;
     NSMutableArray *packages_;
     NSMutableArray *sections_;
-    UISectionList *list_;
+    UITableView *list_;
+    NSMutableArray *index_;
+    NSMutableDictionary *indices_;
 }
 
 - (id) initWithBook:(RVBook *)book database:(Database *)database title:(NSString *)title;
@@ -4701,7 +5366,7 @@ bool DepSubstrate(const pkgCache::VerIterator &iterator) {
 - (void) reloadData;
 - (void) resetCursor;
 
-- (UISectionList *) list;
+- (UITableView *) list;
 
 - (void) setShouldHideHeaderInShortLists:(BOOL)hide;
 
@@ -4716,51 +5381,64 @@ bool DepSubstrate(const pkgCache::VerIterator &iterator) {
     [packages_ release];
     [sections_ release];
     [list_ release];
+    [index_ release];
+    [indices_ release];
     [super dealloc];
 }
 
-- (int) numberOfSectionsInSectionList:(UISectionList *)list {
-    return [sections_ count];
+- (NSInteger) numberOfSectionsInTableView:(UITableView *)list {
+    NSInteger count([sections_ count]);
+    return count == 0 ? 1 : count;
 }
 
-- (NSString *) sectionList:(UISectionList *)list titleForSection:(int)section {
+- (NSString *) tableView:(UITableView *)list titleForHeaderInSection:(NSInteger)section {
+    if ([sections_ count] == 0)
+        return nil;
     return [[sections_ objectAtIndex:section] name];
 }
 
-- (int) sectionList:(UISectionList *)list rowForSection:(int)section {
-    return [[sections_ objectAtIndex:section] row];
-}
-
-- (int) numberOfRowsInTable:(UITable *)table {
-    return [packages_ count];
+- (NSInteger) tableView:(UITableView *)list numberOfRowsInSection:(NSInteger)section {
+    if ([sections_ count] == 0)
+        return 0;
+    return [[sections_ objectAtIndex:section] count];
 }
 
-- (float) table:(UITable *)table heightForRow:(int)row {
-    return [PackageCell heightForPackage:[packages_ objectAtIndex:row]];
+- (Package *) packageAtIndexPath:(NSIndexPath *)path {
+    Section *section([sections_ objectAtIndex:[path section]]);
+    NSInteger row([path row]);
+    Package *package([packages_ objectAtIndex:([section row] + row)]);
+    return package;
 }
 
-- (UITableCell *) table:(UITable *)table cellForRow:(int)row column:(UITableColumn *)col reusing:(UITableCell *)reusing {
-    if (reusing == nil)
-        reusing = [[[PackageCell alloc] init] autorelease];
-    [(PackageCell *)reusing setPackage:[packages_ objectAtIndex:row]];
-    return reusing;
+- (UITableViewCell *) tableView:(UITableView *)table cellForRowAtIndexPath:(NSIndexPath *)path {
+    PackageCell *cell([table dequeueReusableCellWithIdentifier:@"Package"]);
+    if (cell == nil)
+        cell = [[[PackageCell alloc] init] autorelease];
+    [cell setPackage:[self packageAtIndexPath:path]];
+    return cell;
 }
 
-- (BOOL) table:(UITable *)table showDisclosureForRow:(int)row {
-    return NO;
+- (CGFloat) tableView:(UITableView *)table heightForRowAtIndexPath:(NSIndexPath *)path {
+    return 73;
+    return [PackageCell heightForPackage:[self packageAtIndexPath:path]];
 }
 
-- (void) tableRowSelected:(NSNotification *)notification {
-    int row = [[notification object] selectedRow];
-    if (row == INT_MAX)
-        return;
-
-    Package *package = [packages_ objectAtIndex:row];
+- (NSIndexPath *) tableView:(UITableView *)table willSelectRowAtIndexPath:(NSIndexPath *)path {
+    Package *package([self packageAtIndexPath:path]);
     package = [database_ packageWithName:[package id]];
     PackageView *view([delegate_ packageView]);
     [view setPackage:package];
     [view setDelegate:delegate_];
     [book_ pushPage:view];
+    return path;
+}
+
+- (NSArray *) sectionIndexTitlesForTableView:(UITableView *)tableView {
+    return [packages_ count] > 20 ? index_ : nil;
+}
+
+- (NSInteger)tableView:(UITableView *)tableView sectionForSectionIndexTitle:(NSString *)title atIndex:(NSInteger)index {
+    return index;
 }
 
 - (id) initWithBook:(RVBook *)book database:(Database *)database title:(NSString *)title {
@@ -4768,28 +5446,20 @@ bool DepSubstrate(const pkgCache::VerIterator &iterator) {
         database_ = database;
         title_ = [title retain];
 
+        index_ = [[NSMutableArray alloc] initWithCapacity:32];
+        indices_ = [[NSMutableDictionary alloc] initWithCapacity:32];
+
         packages_ = [[NSMutableArray arrayWithCapacity:16] retain];
         sections_ = [[NSMutableArray arrayWithCapacity:16] retain];
 
-        list_ = [[UISectionList alloc] initWithFrame:[self bounds] showSectionIndex:YES];
-        [list_ setDataSource:self];
-
-        UITableColumn *column = [[[UITableColumn alloc]
-            initWithTitle:CYLocalize("NAME")
-            identifier:@"name"
-            width:[self frame].size.width
-        ] autorelease];
-
-        UITable *table = [list_ table];
-        [table setSeparatorStyle:1];
-        [table addTableColumn:column];
-        [table setDelegate:self];
-        [table setReusesTableCells:YES];
-
+        list_ = [[UITableView alloc] initWithFrame:[self bounds] style:UITableViewStylePlain];
+        [list_ setAutoresizingMask:UIViewAutoresizingFlexibleBoth];
         [self addSubview:list_];
 
-        [self setAutoresizingMask:UIViewAutoresizingFlexibleHeight];
-        [list_ setAutoresizingMask:UIViewAutoresizingFlexibleHeight];
+        [list_ setDataSource:self];
+        [list_ setDelegate:self];
+
+        [self setAutoresizingMask:UIViewAutoresizingFlexibleBoth];
     } return self;
 }
 
@@ -4813,6 +5483,9 @@ bool DepSubstrate(const pkgCache::VerIterator &iterator) {
                 [packages_ addObject:package];
     _end
 
+    [index_ removeAllObjects];
+    [indices_ removeAllObjects];
+
     Section *section = nil;
 
     _profile(PackageTable$reloadData$Section)
@@ -4830,6 +5503,9 @@ bool DepSubstrate(const pkgCache::VerIterator &iterator) {
                     section = [[[Section alloc] initWithIndex:index row:offset] autorelease];
                 _end
 
+                [index_ addObject:[section name]];
+                //[indices_ setObject:[NSNumber numberForInt:[sections_ count]] forKey:index];
+
                 _profile(PackageTable$reloadData$Section$Add)
                     [sections_ addObject:section];
                 _end
@@ -4853,15 +5529,15 @@ bool DepSubstrate(const pkgCache::VerIterator &iterator) {
 }
 
 - (void) resetCursor {
-    [[list_ table] scrollPointVisibleAtTopLeft:CGPointMake(0, 0) animated:NO];
+    [list_ scrollRectToVisible:CGRectMake(0, 0, 0, 0) animated:NO];
 }
 
-- (UISectionList *) list {
+- (UITableView *) list {
     return list_;
 }
 
 - (void) setShouldHideHeaderInShortLists:(BOOL)hide {
-    [list_ setShouldHideHeaderInShortLists:hide];
+    //XXX:[list_ setShouldHideHeaderInShortLists:hide];
 }
 
 @end
@@ -4874,6 +5550,7 @@ bool DepSubstrate(const pkgCache::VerIterator &iterator) {
 }
 
 - (void) setObject:(id)object;
+- (void) setObject:(id)object forFilter:(SEL)filter;
 
 - (id) initWithBook:(RVBook *)book database:(Database *)database title:(NSString *)title filter:(SEL)filter with:(id)object;
 
@@ -4887,6 +5564,16 @@ bool DepSubstrate(const pkgCache::VerIterator &iterator) {
     [super dealloc];
 }
 
+- (void) setFilter:(SEL)filter {
+    filter_ = filter;
+
+    /* XXX: this is an unsafe optimization of doomy hell */
+    Method method(class_getInstanceMethod([Package class], filter));
+    _assert(method != NULL);
+    imp_ = method_getImplementation(method);
+    _assert(imp_ != NULL);
+}
+
 - (void) setObject:(id)object {
     if (object_ != nil)
         [object_ release];
@@ -4896,6 +5583,12 @@ bool DepSubstrate(const pkgCache::VerIterator &iterator) {
         object_ = [object retain];
 }
 
+- (void) setObject:(id)object forFilter:(SEL)filter {
+    [self setFilter:filter];
+    [self setObject:object];
+
+}
+
 - (bool) hasPackage:(Package *)package {
     _profile(FilteredPackageTable$hasPackage)
         return [package valid] && (*reinterpret_cast<bool (*)(id, SEL, id)>(imp_))(package, filter_, object_);
@@ -4904,14 +5597,8 @@ bool DepSubstrate(const pkgCache::VerIterator &iterator) {
 
 - (id) initWithBook:(RVBook *)book database:(Database *)database title:(NSString *)title filter:(SEL)filter with:(id)object {
     if ((self = [super initWithBook:book database:database title:title]) != nil) {
-        filter_ = filter;
+        [self setFilter:filter];
         object_ = object == nil ? nil : [object retain];
-
-        /* XXX: this is an unsafe optimization of doomy hell */
-        Method method = class_getInstanceMethod([Package class], filter);
-        imp_ = method_getImplementation(method);
-        _assert(imp_ != NULL);
-
         [self reloadData];
     } return self;
 }
@@ -4977,6 +5664,8 @@ bool DepSubstrate(const pkgCache::VerIterator &iterator) {
 }
 
 - (void) drawContentInRect:(CGRect)rect selected:(BOOL)selected {
+    float width(rect.size.width);
+
     if (icon_ != nil)
         [icon_ drawInRect:CGRectMake(10, 10, 30, 30)];
 
@@ -4985,15 +5674,15 @@ bool DepSubstrate(const pkgCache::VerIterator &iterator) {
 
     if (!selected)
         UISetColor(Black_);
-    [origin_ drawAtPoint:CGPointMake(48, 8) forWidth:240 withFont:Font18Bold_ ellipsis:2];
+    [origin_ drawAtPoint:CGPointMake(48, 8) forWidth:(width - 80) withFont:Font18Bold_ ellipsis:2];
 
     if (!selected)
         UISetColor(Blue_);
-    [label_ drawAtPoint:CGPointMake(58, 29) forWidth:225 withFont:Font12_ ellipsis:2];
+    [label_ drawAtPoint:CGPointMake(58, 29) forWidth:(width - 95) withFont:Font12_ ellipsis:2];
 
     if (!selected)
         UISetColor(Gray_);
-    [description_ drawAtPoint:CGPointMake(12, 46) forWidth:280 withFont:Font14_ ellipsis:2];
+    [description_ drawAtPoint:CGPointMake(12, 46) forWidth:(width - 40) withFont:Font14_ ellipsis:2];
 
     [super drawContentInRect:rect selected:selected];
 }
@@ -5013,11 +5702,12 @@ bool DepSubstrate(const pkgCache::VerIterator &iterator) {
     NSError *error_;
 
     //NSURLConnection *installer_;
+    NSURLConnection *trivial_;
     NSURLConnection *trivial_bz2_;
     NSURLConnection *trivial_gz_;
     //NSURLConnection *automatic_;
 
-    BOOL trivial_;
+    BOOL cydia_;
 }
 
 - (id) initWithBook:(RVBook *)book database:(Database *)database;
@@ -5046,6 +5736,7 @@ bool DepSubstrate(const pkgCache::VerIterator &iterator) {
         [error_ release];
 
     //[self _deallocConnection:installer_];
+    [self _deallocConnection:trivial_];
     [self _deallocConnection:trivial_gz_];
     [self _deallocConnection:trivial_bz2_];
     //[self _deallocConnection:automatic_];
@@ -5061,12 +5752,10 @@ bool DepSubstrate(const pkgCache::VerIterator &iterator) {
 
 - (NSString *) sectionList:(UISectionList *)list titleForSection:(int)section {
     switch (section + (offset_ == 0 ? 1 : 0)) {
-        case 0: return CYLocalize("ENTERED_BY_USER");
-        case 1: return CYLocalize("INSTALLED_BY_PACKAGE");
+        case 0: return UCLocalize("ENTERED_BY_USER");
+        case 1: return UCLocalize("INSTALLED_BY_PACKAGE");
 
-        default:
-            _assert(false);
-            return nil;
+        _nodefault
     }
 }
 
@@ -5075,9 +5764,7 @@ bool DepSubstrate(const pkgCache::VerIterator &iterator) {
         case 0: return 0;
         case 1: return offset_;
 
-        default:
-            _assert(false);
-            return -1;
+        _nodefault
     }
 }
 
@@ -5156,7 +5843,7 @@ bool DepSubstrate(const pkgCache::VerIterator &iterator) {
     if (colon.location != NSNotFound)
         href = [href substringFromIndex:(colon.location + 3)];
     href = [href stringByAddingPercentEscapes];
-    href = [@"http://cydia.saurik.com/api/repotag/" stringByAppendingString:href];
+    href = [CydiaURL(@"api/repotag/") stringByAppendingString:href];
     href = [href stringByCachingURLWithCurrentCDN];
 
     NSURL *url([NSURL URLWithString:href]);
@@ -5171,7 +5858,9 @@ bool DepSubstrate(const pkgCache::VerIterator &iterator) {
 
 - (void) _endConnection:(NSURLConnection *)connection {
     NSURLConnection **field = NULL;
-    if (connection == trivial_bz2_)
+    if (connection == trivial_)
+        field = &trivial_;
+    else if (connection == trivial_bz2_)
         field = &trivial_bz2_;
     else if (connection == trivial_gz_)
         field = &trivial_gz_;
@@ -5180,51 +5869,51 @@ bool DepSubstrate(const pkgCache::VerIterator &iterator) {
     *field = nil;
 
     if (
+        trivial_ == nil &&
         trivial_bz2_ == nil &&
         trivial_gz_ == nil
     ) {
         bool defer(false);
 
-        if (trivial_) {
+        if (cydia_) {
             if (NSString *warning = [self yieldToSelector:@selector(getWarning)]) {
                 defer = true;
 
-                UIActionSheet *sheet = [[[UIActionSheet alloc]
-                    initWithTitle:CYLocalize("SOURCE_WARNING")
-                    buttons:[NSArray arrayWithObjects:CYLocalize("ADD_ANYWAY"), CYLocalize("CANCEL"), nil]
-                    defaultButtonIndex:0
-                    delegate:self
-                    context:@"warning"
+                UIAlertView *alert = [[[UIAlertView alloc]
+                    initWithTitle:UCLocalize("SOURCE_WARNING")
+                                       message:warning
+                                       delegate:self
+                                       cancelButtonTitle:UCLocalize("CANCEL")
+                    otherButtonTitles:UCLocalize("ADD_ANYWAY"), nil
                 ] autorelease];
 
-                [sheet setNumberOfRows:1];
-
-                [sheet setBodyText:warning];
-                [sheet popupAlertAnimated:YES];
+                               [alert setContext:@"warning"];
+                [alert setNumberOfRows:1];
+                [alert show];
             } else
                 [self complete];
         } else if (error_ != nil) {
-            UIActionSheet *sheet = [[[UIActionSheet alloc]
-                initWithTitle:CYLocalize("VERIFICATION_ERROR")
-                buttons:[NSArray arrayWithObjects:CYLocalize("OK"), nil]
-                defaultButtonIndex:0
-                delegate:self
-                context:@"urlerror"
+            UIAlertView *alert = [[[UIAlertView alloc]
+                initWithTitle:UCLocalize("VERIFICATION_ERROR")
+                               message:[error_ localizedDescription]
+                               delegate:self
+                               cancelButtonTitle:UCLocalize("OK")
+                otherButtonTitles:nil
             ] autorelease];
 
-            [sheet setBodyText:[error_ localizedDescription]];
-            [sheet popupAlertAnimated:YES];
+                       [alert setContext:@"urlerror"];
+            [alert show];
         } else {
-            UIActionSheet *sheet = [[[UIActionSheet alloc]
-                initWithTitle:CYLocalize("NOT_REPOSITORY")
-                buttons:[NSArray arrayWithObjects:CYLocalize("OK"), nil]
-                defaultButtonIndex:0
-                delegate:self
-                context:@"trivial"
+            UIAlertView *alert = [[[UIAlertView alloc]
+                initWithTitle:UCLocalize("NOT_REPOSITORY")
+                               message:UCLocalize("NOT_REPOSITORY_EX")
+                               delegate:self
+                               cancelButtonTitle:UCLocalize("OK")
+                otherButtonTitles:nil
             ] autorelease];
 
-            [sheet setBodyText:CYLocalize("NOT_REPOSITORY_EX")];
-            [sheet popupAlertAnimated:YES];
+                       [alert setContext:@"trivial"];
+            [alert show];
         }
 
         [delegate_ setStatusBarShowsProgress:NO];
@@ -5248,7 +5937,7 @@ bool DepSubstrate(const pkgCache::VerIterator &iterator) {
 - (void) connection:(NSURLConnection *)connection didReceiveResponse:(NSHTTPURLResponse *)response {
     switch ([response statusCode]) {
         case 200:
-            trivial_ = YES;
+            cydia_ = YES;
     }
 }
 
@@ -5267,7 +5956,7 @@ bool DepSubstrate(const pkgCache::VerIterator &iterator) {
     NSMutableURLRequest *request = [NSMutableURLRequest
         requestWithURL:[NSURL URLWithString:href]
         cachePolicy:NSURLRequestUseProtocolCachePolicy
-        timeoutInterval:20.0
+        timeoutInterval:120.0
     ];
 
     [request setHTTPMethod:method];
@@ -5276,20 +5965,19 @@ bool DepSubstrate(const pkgCache::VerIterator &iterator) {
         [request setValue:[NSString stringWithUTF8String:Machine_] forHTTPHeaderField:@"X-Machine"];
     if (UniqueID_ != nil)
         [request setValue:UniqueID_ forHTTPHeaderField:@"X-Unique-ID"];
-
     if (Role_ != nil)
         [request setValue:Role_ forHTTPHeaderField:@"X-Role"];
 
     return [[[NSURLConnection alloc] initWithRequest:request delegate:self] autorelease];
 }
 
-- (void) alertSheet:(UIActionSheet *)sheet buttonClicked:(int)button {
-    NSString *context([sheet context]);
+- (void)alertView:(UIAlertView *)alert clickedButtonAtIndex:(NSInteger)button {
+    NSString *context([alert context]);
 
     if ([context isEqualToString:@"source"]) {
         switch (button) {
             case 1: {
-                NSString *href = [[sheet textField] text];
+                NSString *href = [[alert textField] text];
 
                 //installer_ = [[self _requestHRef:href method:@"GET"] retain];
 
@@ -5299,45 +5987,44 @@ bool DepSubstrate(const pkgCache::VerIterator &iterator) {
                     href_ = href;
                 href_ = [href_ retain];
 
+                trivial_ = [[self _requestHRef:[href_ stringByAppendingString:@"Packages"] 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];
                 //trivial_bz2_ = [[self _requestHRef:[href stringByAppendingString:@"dists/Release"] method:@"HEAD"] retain];
 
-                trivial_ = false;
+                cydia_ = false;
 
                 hud_ = [[delegate_ addProgressHUD] retain];
-                [hud_ setText:CYLocalize("VERIFYING_URL")];
+                [hud_ setText:UCLocalize("VERIFYING_URL")];
             } break;
 
-            case 2:
+            case 0:
             break;
 
-            default:
-                _assert(false);
+            _nodefault
         }
 
-        [sheet dismiss];
+        [alert dismissWithClickedButtonIndex:-1 animated:YES];
     } else if ([context isEqualToString:@"trivial"])
-        [sheet dismiss];
+        [alert dismissWithClickedButtonIndex:-1 animated:YES];
     else if ([context isEqualToString:@"urlerror"])
-        [sheet dismiss];
+        [alert dismissWithClickedButtonIndex:-1 animated:YES];
     else if ([context isEqualToString:@"warning"]) {
         switch (button) {
             case 1:
                 [self complete];
             break;
 
-            case 2:
+            case 0:
             break;
 
-            default:
-                _assert(false);
+            _nodefault
         }
 
         [href_ release];
         href_ = nil;
 
-        [sheet dismiss];
+        [alert dismissWithClickedButtonIndex:-1 animated:YES];
     }
 }
 
@@ -5348,13 +6035,14 @@ bool DepSubstrate(const pkgCache::VerIterator &iterator) {
 
         //list_ = [[UITable alloc] initWithFrame:[self bounds]];
         list_ = [[UISectionList alloc] initWithFrame:[self bounds] showSectionIndex:NO];
-        [list_ setShouldHideHeaderInShortLists:NO];
-
+        [list_ setAutoresizingMask:UIViewAutoresizingFlexibleBoth];
         [self addSubview:list_];
+
+        [list_ setShouldHideHeaderInShortLists:NO];
         [list_ setDataSource:self];
 
         UITableColumn *column = [[UITableColumn alloc]
-            initWithTitle:CYLocalize("NAME")
+            initWithTitle:UCLocalize("NAME")
             identifier:@"name"
             width:[self frame].size.width
         ];
@@ -5366,14 +6054,14 @@ bool DepSubstrate(const pkgCache::VerIterator &iterator) {
 
         [self reloadData];
 
-        [self setAutoresizingMask:UIViewAutoresizingFlexibleHeight];
-        [list_ setAutoresizingMask:UIViewAutoresizingFlexibleHeight];
+        [self setAutoresizingMask:UIViewAutoresizingFlexibleBoth];
     } return self;
 }
 
 - (void) reloadData {
     pkgSourceList list;
-    _assert(list.ReadMainList());
+    if (!list.ReadMainList())
+        return;
 
     [sources_ removeAllObjects];
     [sources_ addObjectsFromArray:[database_ sources]];
@@ -5381,7 +6069,7 @@ bool DepSubstrate(const pkgCache::VerIterator &iterator) {
     [sources_ sortUsingSelector:@selector(compareByNameAndType:)];
     _trace();
 
-    int count = [sources_ count];
+    int count([sources_ count]);
     for (offset_ = 0; offset_ != count; ++offset_) {
         Source *source = [sources_ objectAtIndex:offset_];
         if ([source record] == nil)
@@ -5401,26 +6089,28 @@ bool DepSubstrate(const pkgCache::VerIterator &iterator) {
         database:database_
     ] autorelease]];*/
 
-    UIActionSheet *sheet = [[[UIActionSheet alloc]
-        initWithTitle:CYLocalize("ENTER_APT_URL")
-        buttons:[NSArray arrayWithObjects:CYLocalize("ADD_SOURCE"), CYLocalize("CANCEL"), nil]
-        defaultButtonIndex:0
-        delegate:self
-        context:@"source"
+    UIAlertView *alert = [[[UIAlertView alloc]
+        initWithTitle:UCLocalize("ENTER_APT_URL")
+               message:nil
+               delegate:self
+               cancelButtonTitle:UCLocalize("CANCEL")
+               otherButtonTitles:UCLocalize("ADD_SOURCE"), nil
     ] autorelease];
 
-    [sheet setNumberOfRows:1];
+       [alert setContext:@"source"];
+       [alert setTransform:CGAffineTransformTranslate([alert transform], 0.0, 100.0)];
 
-    [sheet addTextFieldWithValue:@"http://" label:@""];
+    [alert setNumberOfRows:1];
+    [alert addTextFieldWithValue:@"http://" label:@""];
 
-    UITextInputTraits *traits = [[sheet textField] textInputTraits];
+    UITextInputTraits *traits = [[alert textField] textInputTraits];
     [traits setAutocapitalizationType:UITextAutocapitalizationTypeNone];
     [traits setAutocorrectionType:UITextAutocorrectionTypeNo];
     [traits setKeyboardType:UIKeyboardTypeURL];
     // XXX: UIReturnKeyDone
     [traits setReturnKeyType:UIReturnKeyNext];
 
-    [sheet popupAlertAnimated:YES];
+    [alert show];
 }
 
 - (void) _rightButtonClicked {
@@ -5431,15 +6121,15 @@ bool DepSubstrate(const pkgCache::VerIterator &iterator) {
 }
 
 - (NSString *) title {
-    return CYLocalize("SOURCES");
+    return UCLocalize("SOURCES");
 }
 
 - (NSString *) leftButtonTitle {
-    return [[list_ table] isRowDeletionEnabled] ? CYLocalize("ADD") : nil;
+    return [[list_ table] isRowDeletionEnabled] ? UCLocalize("ADD") : nil;
 }
 
 - (id) rightButtonTitle {
-    return [[list_ table] isRowDeletionEnabled] ? CYLocalize("DONE") : CYLocalize("EDIT");
+    return [[list_ table] isRowDeletionEnabled] ? UCLocalize("DONE") : UCLocalize("EDIT");
 }
 
 - (UINavigationButtonStyle) rightButtonStyle {
@@ -5479,10 +6169,10 @@ bool DepSubstrate(const pkgCache::VerIterator &iterator) {
             with:[NSNumber numberWithBool:YES]
         ];
 
+        [packages_ setAutoresizingMask:UIViewAutoresizingFlexibleBoth];
         [self addSubview:packages_];
 
-        [self setAutoresizingMask:UIViewAutoresizingFlexibleHeight];
-        [packages_ setAutoresizingMask:UIViewAutoresizingFlexibleHeight];
+        [self setAutoresizingMask:UIViewAutoresizingFlexibleBoth];
     } return self;
 }
 
@@ -5502,15 +6192,15 @@ bool DepSubstrate(const pkgCache::VerIterator &iterator) {
 }
 
 - (NSString *) title {
-    return CYLocalize("INSTALLED");
+    return UCLocalize("INSTALLED");
 }
 
 - (NSString *) backButtonTitle {
-    return CYLocalize("PACKAGES");
+    return UCLocalize("PACKAGES");
 }
 
 - (id) rightButtonTitle {
-    return Role_ != nil && [Role_ isEqualToString:@"Developer"] ? nil : expert_ ? CYLocalize("EXPERT") : CYLocalize("SIMPLE");
+    return Role_ != nil && [Role_ isEqualToString:@"Developer"] ? nil : expert_ ? UCLocalize("EXPERT") : UCLocalize("SIMPLE");
 }
 
 - (UINavigationButtonStyle) rightButtonStyle {
@@ -5526,57 +6216,45 @@ bool DepSubstrate(const pkgCache::VerIterator &iterator) {
 /* }}} */
 
 /* Home View {{{ */
-@interface HomeView : BrowserView {
+@interface HomeView : CydiaBrowserView {
 }
 
 @end
 
 @implementation HomeView
 
-- (void) alertSheet:(UIActionSheet *)sheet buttonClicked:(int)button {
-    NSString *context([sheet context]);
-
-    if ([context isEqualToString:@"about"])
-        [sheet dismiss];
-    else
-        [super alertSheet:sheet buttonClicked:button];
+- (void) _setMoreHeaders:(NSMutableURLRequest *)request {
+    [super _setMoreHeaders:request];
+    if (ChipID_ != nil)
+        [request setValue:ChipID_ forHTTPHeaderField:@"X-Chip-ID"];
+    if (UniqueID_ != nil)
+        [request setValue:UniqueID_ forHTTPHeaderField:@"X-Unique-ID"];
 }
 
 - (void) _leftButtonClicked {
-    UIActionSheet *sheet = [[[UIActionSheet alloc]
-        initWithTitle:CYLocalize("ABOUT_CYDIA")
-        buttons:[NSArray arrayWithObjects:CYLocalize("CLOSE"), nil]
-        defaultButtonIndex:0
-        delegate:self
-        context:@"about"
-    ] autorelease];
+    UIAlertView *alert = [[[UIAlertView alloc] init] autorelease];
+    [alert setTitle:UCLocalize("ABOUT_CYDIA")];
+    [alert addButtonWithTitle:UCLocalize("CLOSE")];
+    [alert setCancelButtonIndex:0];
 
-    [sheet setBodyText:
-        @"Copyright (C) 2008-2009\n"
+    [alert setMessage:
+        @"Copyright (C) 2008-2010\n"
         "Jay Freeman (saurik)\n"
         "saurik@saurik.com\n"
-        "http://www.saurik.com/\n"
-        "\n"
-        "The Okori Group\n"
-        "http://www.theokorigroup.com/\n"
-        "\n"
-        "College of Creative Studies,\n"
-        "University of California,\n"
-        "Santa Barbara\n"
-        "http://www.ccs.ucsb.edu/"
+        "http://www.saurik.com/"
     ];
 
-    [sheet popupAlertAnimated:YES];
+    [alert show];
 }
 
 - (NSString *) leftButtonTitle {
-    return CYLocalize("ABOUT");
+    return UCLocalize("ABOUT");
 }
 
 @end
 /* }}} */
 /* Manage View {{{ */
-@interface ManageView : BrowserView {
+@interface ManageView : CydiaBrowserView {
 }
 
 @end
@@ -5584,20 +6262,21 @@ bool DepSubstrate(const pkgCache::VerIterator &iterator) {
 @implementation ManageView
 
 - (NSString *) title {
-    return CYLocalize("MANAGE");
+    return UCLocalize("MANAGE");
 }
 
 - (void) _leftButtonClicked {
     [delegate_ askForSettings];
+    [delegate_ updateData];
 }
 
 - (NSString *) leftButtonTitle {
-    return CYLocalize("SETTINGS");
+    return UCLocalize("SETTINGS");
 }
 
 #if !AlwaysReload
 - (id) _rightButtonTitle {
-    return Queuing_ ? CYLocalize("QUEUE") : nil;
+    return Queuing_ ? UCLocalize("QUEUE") : nil;
 }
 
 - (UINavigationButtonStyle) rightButtonStyle {
@@ -5616,8 +6295,6 @@ bool DepSubstrate(const pkgCache::VerIterator &iterator) {
 @end
 /* }}} */
 
-#include <BrowserView.m>
-
 /* Cydia Book {{{ */
 @interface CYBook : RVBook <
     ProgressDelegate
@@ -5630,11 +6307,13 @@ bool DepSubstrate(const pkgCache::VerIterator &iterator) {
     UIProgressBar *progress_;
     UINavigationButton *cancel_;
     bool updating_;
+    bool dropped_;
 }
 
 - (id) initWithFrame:(CGRect)frame database:(Database *)database;
 - (void) update;
 - (BOOL) updating;
+- (void) setUpdate:(NSDate *)date;
 
 @end
 
@@ -5657,7 +6336,11 @@ bool DepSubstrate(const pkgCache::VerIterator &iterator) {
     return updating_;
 }
 
-- (void) update {
+- (void) dropBar {
+    if (dropped_)
+        return;
+    dropped_ = true;
+
     [UIView beginAnimations:nil context:NULL];
 
     CGRect ovrframe = [overlay_ frame];
@@ -5674,25 +6357,12 @@ bool DepSubstrate(const pkgCache::VerIterator &iterator) {
     [transition_ setFrame:trnframe];
 
     [UIView endAnimations];
-
-    [indicator_ startAnimation];
-    [prompt_ setText:CYLocalize("UPDATING_DATABASE")];
-    [progress_ setProgress:0];
-
-    updating_ = true;
-    [overlay_ addSubview:cancel_];
-
-    [NSThread
-        detachNewThreadSelector:@selector(_update)
-        toTarget:self
-        withObject:nil
-    ];
 }
 
-- (void) _update_ {
-    updating_ = false;
-
-    [indicator_ stopAnimation];
+- (void) raiseBar {
+    if (!dropped_)
+        return;
+    dropped_ = false;
 
     [UIView beginAnimations:nil context:NULL];
 
@@ -5710,6 +6380,42 @@ bool DepSubstrate(const pkgCache::VerIterator &iterator) {
     [transition_ setFrame:trnframe];
 
     [UIView commitAnimations];
+}
+
+- (void) setUpdate:(NSDate *)date {
+    [self update];
+}
+
+- (void) update {
+    [self dropBar];
+
+    [indicator_ startAnimation];
+    [prompt_ setText:UCLocalize("UPDATING_DATABASE")];
+    [progress_ setProgress:0];
+
+    updating_ = true;
+    [overlay_ addSubview:cancel_];
+
+    [NSThread
+        detachNewThreadSelector:@selector(_update)
+        toTarget:self
+        withObject:nil
+    ];
+}
+
+- (void) alertSheet:(UIActionSheet *)sheet buttonClicked:(int)button {
+    NSString *context([sheet context]);
+
+    if ([context isEqualToString:@"refresh"])
+        [sheet dismiss];
+}
+
+- (void) _update_ {
+    updating_ = false;
+
+    [indicator_ stopAnimation];
+
+    [self raiseBar];
 
     [delegate_ performSelector:@selector(reloadData) withObject:nil afterDelay:0];
 }
@@ -5718,29 +6424,32 @@ bool DepSubstrate(const pkgCache::VerIterator &iterator) {
     if ((self = [super initWithFrame:frame]) != nil) {
         database_ = database;
 
-        CGRect ovrrect = [navbar_ bounds];
+        CGRect ovrrect([navbar_ bounds]);
         ovrrect.size.height = [UINavigationBar defaultSize].height;
         ovrrect.origin.y = -ovrrect.size.height;
 
         overlay_ = [[UINavigationBar alloc] initWithFrame:ovrrect];
+        [overlay_ setAutoresizingMask:UIViewAutoresizingFlexibleWidth];
         [self addSubview:overlay_];
 
         ovrrect.origin.y = frame.size.height;
         underlay_ = [[UINavigationBar alloc] initWithFrame:ovrrect];
-        [underlay_ setTintColor:[UIColor colorWithRed:0.23 green:0.23 blue:0.23 alpha:1]];
+        [underlay_ setAutoresizingMask:UIViewAutoresizingFlexibleWidth];
         [self addSubview:underlay_];
 
+        [underlay_ setTintColor:[UIColor colorWithRed:0.23 green:0.23 blue:0.23 alpha:1]];
+
         [overlay_ setBarStyle:1];
         [underlay_ setBarStyle:1];
 
-        int barstyle = [overlay_ _barStyle:NO];
-        bool ugly = barstyle == 0;
+        int barstyle([overlay_ _barStyle:NO]);
+        bool ugly(barstyle == 0);
 
         UIProgressIndicatorStyle style = ugly ?
             UIProgressIndicatorStyleMediumBrown :
             UIProgressIndicatorStyleMediumWhite;
 
-        CGSize indsize = [UIProgressIndicator defaultSizeForStyle:style];
+        CGSize indsize([UIProgressIndicator defaultSizeForStyle:style]);
         unsigned indoffset = (ovrrect.size.height - indsize.height) / 2;
         CGRect indrect = {{indoffset, indoffset}, indsize};
 
@@ -5752,13 +6461,10 @@ bool DepSubstrate(const pkgCache::VerIterator &iterator) {
 
         CGRect prmrect = {{
             indoffset * 2 + indsize.width,
-#ifdef __OBJC2__
-            -1 +
-#endif
-            unsigned(ovrrect.size.height - prmsize.height) / 2
+            unsigned(ovrrect.size.height - prmsize.height) / 2 - 1
         }, prmsize};
 
-        UIFont *font = [UIFont systemFontOfSize:15];
+        UIFont *font([UIFont systemFontOfSize:15]);
 
         prompt_ = [[UITextLabel alloc] initWithFrame:prmrect];
 
@@ -5776,10 +6482,13 @@ bool DepSubstrate(const pkgCache::VerIterator &iterator) {
         } , prgsize};
 
         progress_ = [[UIProgressBar alloc] initWithFrame:prgrect];
-        [progress_ setStyle:0];
+        [progress_ setAutoresizingMask:UIViewAutoresizingFlexibleWidth];
         [overlay_ addSubview:progress_];
 
-        cancel_ = [[UINavigationButton alloc] initWithTitle:CYLocalize("CANCEL") style:UINavigationButtonStyleHighlighted];
+        [progress_ setStyle:0];
+
+        cancel_ = [[UINavigationButton alloc] initWithTitle:UCLocalize("CANCEL") style:UINavigationButtonStyleHighlighted];
+        [progress_ setAutoresizingMask:UIViewAutoresizingFlexibleLeftMargin];
         [cancel_ addTarget:self action:@selector(_onCancel) forControlEvents:UIControlEventTouchUpInside];
 
         CGRect frame = [cancel_ frame];
@@ -5799,7 +6508,6 @@ bool DepSubstrate(const pkgCache::VerIterator &iterator) {
 - (void) _update { _pooled
     Status status;
     status.setDelegate(self);
-
     [database_ updateWithStatus:status];
 
     [self
@@ -5809,10 +6517,29 @@ bool DepSubstrate(const pkgCache::VerIterator &iterator) {
     ];
 }
 
-- (void) setProgressError:(NSString *)error forPackage:(NSString *)id {
-    [prompt_ setText:[NSString stringWithFormat:CYLocalize("ERROR_MESSAGE"), error]];
+- (void) setProgressError:(NSString *)error withTitle:(NSString *)title {
+    [prompt_ setText:[NSString stringWithFormat:UCLocalize("COLON_DELIMITED"), UCLocalize("ERROR"), error]];
 }
 
+/*
+    UIActionSheet *sheet = [[[UIActionSheet alloc]
+        initWithTitle:[NSString stringWithFormat:UCLocalize("COLON_DELIMITED"), UCLocalize("ERROR"), UCLocalize("REFRESH")]
+        buttons:[NSArray arrayWithObjects:
+            UCLocalize("OK"),
+        nil]
+        defaultButtonIndex:0
+        delegate:self
+        context:@"refresh"
+    ] autorelease];
+
+    [sheet setAutoresizingMask:(UIViewAutoresizingFlexibleWidth | UIViewAutoresizingFlexibleHeight)];
+
+    [sheet setBodyText:error];
+    [sheet popupAlertAnimated:YES];
+
+    [self reloadButtons];
+*/
+
 - (void) setProgressTitle:(NSString *)title {
     [self
         performSelectorOnMainThread:@selector(_setProgressTitle:)
@@ -5844,10 +6571,6 @@ bool DepSubstrate(const pkgCache::VerIterator &iterator) {
     return !updating_;
 }
 
-- (void) alertSheet:(UIActionSheet *)sheet buttonClicked:(int)button {
-    [sheet dismiss];
-}
-
 - (void) _setProgressTitle:(NSString *)title {
     [prompt_ setText:title];
 }
@@ -5967,7 +6690,6 @@ bool DepSubstrate(const pkgCache::VerIterator &iterator) {
     _transient Database *database_;
     NSMutableArray *sections_;
     NSMutableArray *filtered_;
-    UITransitionView *transition_;
     UITable *list_;
     UIView *accessory_;
     BOOL editing_;
@@ -5987,7 +6709,6 @@ bool DepSubstrate(const pkgCache::VerIterator &iterator) {
 
     [sections_ release];
     [filtered_ release];
-    [transition_ release];
     [list_ release];
     [accessory_ release];
     [super dealloc];
@@ -6031,16 +6752,17 @@ bool DepSubstrate(const pkgCache::VerIterator &iterator) {
     if (row == 0) {
         section = nil;
         name = nil;
-        title = CYLocalize("ALL_PACKAGES");
+        title = UCLocalize("ALL_PACKAGES");
     } else {
         section = [filtered_ objectAtIndex:(row - 1)];
         name = [section name];
 
-        if (name != nil)
+        if (name != nil) {
+            name = [NSString stringWithString:name];
             title = [[NSBundle mainBundle] localizedStringForKey:Simplify(name) value:nil table:@"Sections"];
-        else {
+        else {
             name = @"";
-            title = CYLocalize("NO_SECTION");
+            title = UCLocalize("NO_SECTION");
         }
     }
 
@@ -6048,7 +6770,7 @@ bool DepSubstrate(const pkgCache::VerIterator &iterator) {
         initWithBook:book_
         database:database_
         title:title
-        filter:@selector(isVisiblyUninstalledInSection:)
+        filter:@selector(isVisibleInSection:)
         with:name
     ] autorelease];
 
@@ -6064,14 +6786,12 @@ bool DepSubstrate(const pkgCache::VerIterator &iterator) {
         sections_ = [[NSMutableArray arrayWithCapacity:16] retain];
         filtered_ = [[NSMutableArray arrayWithCapacity:16] retain];
 
-        transition_ = [[UITransitionView alloc] initWithFrame:[self bounds]];
-        [self addSubview:transition_];
-
-        list_ = [[UITable alloc] initWithFrame:[transition_ bounds]];
-        [transition_ transition:0 toView:list_];
+        list_ = [[UITable alloc] initWithFrame:[self bounds]];
+        [list_ setAutoresizingMask:UIViewAutoresizingFlexibleBoth];
+        [self addSubview:list_];
 
         UITableColumn *column = [[[UITableColumn alloc]
-            initWithTitle:CYLocalize("NAME")
+            initWithTitle:UCLocalize("NAME")
             identifier:@"name"
             width:[self frame].size.width
         ] autorelease];
@@ -6084,8 +6804,7 @@ bool DepSubstrate(const pkgCache::VerIterator &iterator) {
 
         [self reloadData];
 
-        [self setAutoresizingMask:UIViewAutoresizingFlexibleHeight];
-        [list_ setAutoresizingMask:UIViewAutoresizingFlexibleHeight];
+        [self setAutoresizingMask:UIViewAutoresizingFlexibleBoth];
     } return self;
 }
 
@@ -6115,7 +6834,7 @@ bool DepSubstrate(const pkgCache::VerIterator &iterator) {
             section = &sections[key];
             if (*section == nil) {
                 _profile(SectionsView$reloadData$Section$Allocate)
-                    *section = [[[Section alloc] initWithName:name] autorelease];
+                    *section = [[[Section alloc] initWithName:name localize:YES] autorelease];
                 _end
             }
         _end
@@ -6123,7 +6842,7 @@ bool DepSubstrate(const pkgCache::VerIterator &iterator) {
         [*section addToCount];
 
         _profile(SectionsView$reloadData$Filter)
-            if (![package valid] || [package installed] != nil || ![package visible])
+            if (![package valid] || ![package visible])
                 continue;
         _end
 
@@ -6135,7 +6854,7 @@ bool DepSubstrate(const pkgCache::VerIterator &iterator) {
             section = [sections objectForKey:key];
             if (section == nil) {
                 _profile(SectionsView$reloadData$Section$Allocate)
-                    section = [[[Section alloc] initWithName:name] autorelease];
+                    section = [[[Section alloc] initWithName:name localize:YES] autorelease];
                     [sections setObject:section forKey:key];
                 _end
             }
@@ -6144,7 +6863,7 @@ bool DepSubstrate(const pkgCache::VerIterator &iterator) {
         [section addToCount];
 
         _profile(SectionsView$reloadData$Filter)
-            if (![package valid] || [package installed] != nil || ![package visible])
+            if (![package valid] || ![package visible])
                 continue;
         _end
 
@@ -6160,14 +6879,14 @@ bool DepSubstrate(const pkgCache::VerIterator &iterator) {
     [sections_ addObjectsFromArray:[sections allValues]];
 #endif
 
-    [sections_ sortUsingSelector:@selector(compareByName:)];
+    [sections_ sortUsingSelector:@selector(compareByLocalized:)];
 
     for (Section *section in sections_) {
         size_t count([section row]);
-        if ([section row] == 0)
+        if (count == 0)
             continue;
 
-        section = [[[Section alloc] initWithName:[section name]] autorelease];
+        section = [[[Section alloc] initWithName:[section name] localized:[section localized]] autorelease];
         [section setCount:count];
         [filtered_ addObject:section];
     }
@@ -6195,15 +6914,15 @@ bool DepSubstrate(const pkgCache::VerIterator &iterator) {
 }
 
 - (NSString *) title {
-    return editing_ ? CYLocalize("SECTION_VISIBILITY") : CYLocalize("INSTALL_BY_SECTION");
+    return editing_ ? UCLocalize("SECTION_VISIBILITY") : UCLocalize("SECTIONS");
 }
 
 - (NSString *) backButtonTitle {
-    return CYLocalize("SECTIONS");
+    return UCLocalize("SECTIONS");
 }
 
 - (id) rightButtonTitle {
-    return [sections_ count] == 0 ? nil : editing_ ? CYLocalize("DONE") : CYLocalize("EDIT");
+    return [sections_ count] == 0 ? nil : editing_ ? UCLocalize("DONE") : UCLocalize("EDIT");
 }
 
 - (UINavigationButtonStyle) rightButtonStyle {
@@ -6221,11 +6940,11 @@ bool DepSubstrate(const pkgCache::VerIterator &iterator) {
     _transient Database *database_;
     NSMutableArray *packages_;
     NSMutableArray *sections_;
-    UISectionList *list_;
+    UITableView *list_;
     unsigned upgrades_;
 }
 
-- (id) initWithBook:(RVBook *)book database:(Database *)database;
+- (id) initWithBook:(RVBook *)book database:(Database *)database delegate:(id)delegate;
 - (void) reloadData;
 
 @end
@@ -6233,7 +6952,7 @@ bool DepSubstrate(const pkgCache::VerIterator &iterator) {
 @implementation ChangesView
 
 - (void) dealloc {
-    [[list_ table] setDelegate:nil];
+    [list_ setDelegate:nil];
     [list_ setDataSource:nil];
 
     [packages_ release];
@@ -6242,46 +6961,49 @@ bool DepSubstrate(const pkgCache::VerIterator &iterator) {
     [super dealloc];
 }
 
-- (int) numberOfSectionsInSectionList:(UISectionList *)list {
-    return [sections_ count];
+- (NSInteger) numberOfSectionsInTableView:(UITableView *)list {
+    NSInteger count([sections_ count]);
+    return count == 0 ? 1 : count;
 }
 
-- (NSString *) sectionList:(UISectionList *)list titleForSection:(int)section {
+- (NSString *) tableView:(UITableView *)list titleForHeaderInSection:(NSInteger)section {
+    if ([sections_ count] == 0)
+        return nil;
     return [[sections_ objectAtIndex:section] name];
 }
 
-- (int) sectionList:(UISectionList *)list rowForSection:(int)section {
-    return [[sections_ objectAtIndex:section] row];
+- (NSInteger) tableView:(UITableView *)list numberOfRowsInSection:(NSInteger)section {
+    if ([sections_ count] == 0)
+        return 0;
+    return [[sections_ objectAtIndex:section] count];
 }
 
-- (int) numberOfRowsInTable:(UITable *)table {
-    return [packages_ count];
+- (Package *) packageAtIndexPath:(NSIndexPath *)path {
+    Section *section([sections_ objectAtIndex:[path section]]);
+    NSInteger row([path row]);
+    return [packages_ objectAtIndex:([section row] + row)];
 }
 
-- (float) table:(UITable *)table heightForRow:(int)row {
-    return [PackageCell heightForPackage:[packages_ objectAtIndex:row]];
+- (UITableViewCell *) tableView:(UITableView *)table cellForRowAtIndexPath:(NSIndexPath *)path {
+    PackageCell *cell([table dequeueReusableCellWithIdentifier:@"Package"]);
+    if (cell == nil)
+        cell = [[[PackageCell alloc] init] autorelease];
+    [cell setPackage:[self packageAtIndexPath:path]];
+    return cell;
 }
 
-- (UITableCell *) table:(UITable *)table cellForRow:(int)row column:(UITableColumn *)col reusing:(UITableCell *)reusing {
-    if (reusing == nil)
-        reusing = [[[PackageCell alloc] init] autorelease];
-    [(PackageCell *)reusing setPackage:[packages_ objectAtIndex:row]];
-    return reusing;
+- (CGFloat) tableView:(UITableView *)table heightForRowAtIndexPath:(NSIndexPath *)path {
+    return 73;
+    return [PackageCell heightForPackage:[self packageAtIndexPath:path]];
 }
 
-- (BOOL) table:(UITable *)table showDisclosureForRow:(int)row {
-    return NO;
-}
-
-- (void) tableRowSelected:(NSNotification *)notification {
-    int row = [[notification object] selectedRow];
-    if (row == INT_MAX)
-        return;
-    Package *package = [packages_ objectAtIndex:row];
+- (NSIndexPath *) tableView:(UITableView *)table willSelectRowAtIndexPath:(NSIndexPath *)path {
+    Package *package([self packageAtIndexPath:path]);
     PackageView *view([delegate_ packageView]);
     [view setDelegate:delegate_];
     [view setPackage:package];
     [book_ pushPage:view];
+    return path;
 }
 
 - (void) _leftButtonClicked {
@@ -6293,75 +7015,70 @@ bool DepSubstrate(const pkgCache::VerIterator &iterator) {
     [delegate_ distUpgrade];
 }
 
-- (id) initWithBook:(RVBook *)book database:(Database *)database {
+- (id) initWithBook:(RVBook *)book database:(Database *)database delegate:(id)delegate {
     if ((self = [super initWithBook:book]) != nil) {
         database_ = database;
 
         packages_ = [[NSMutableArray arrayWithCapacity:16] retain];
         sections_ = [[NSMutableArray arrayWithCapacity:16] retain];
 
-        list_ = [[UISectionList alloc] initWithFrame:[self bounds] showSectionIndex:NO];
+        list_ = [[UITableView alloc] initWithFrame:[self bounds] style:UITableViewStylePlain];
+        [list_ setAutoresizingMask:UIViewAutoresizingFlexibleBoth];
         [self addSubview:list_];
 
-        [list_ setShouldHideHeaderInShortLists:NO];
+        //XXX:[list_ setShouldHideHeaderInShortLists:NO];
         [list_ setDataSource:self];
+        [list_ setDelegate:self];
         //[list_ setSectionListStyle:1];
 
-        UITableColumn *column = [[[UITableColumn alloc]
-            initWithTitle:CYLocalize("NAME")
-            identifier:@"name"
-            width:[self frame].size.width
-        ] autorelease];
-
-        UITable *table = [list_ table];
-        [table setSeparatorStyle:1];
-        [table addTableColumn:column];
-        [table setDelegate:self];
-        [table setReusesTableCells:YES];
-
+        delegate_ = delegate;
         [self reloadData];
 
-        [self setAutoresizingMask:UIViewAutoresizingFlexibleHeight];
-        [list_ setAutoresizingMask:UIViewAutoresizingFlexibleHeight];
+        [self setAutoresizingMask:UIViewAutoresizingFlexibleBoth];
     } return self;
 }
 
-- (void) reloadData {
-    NSArray *packages = [database_ packages];
-
-    [packages_ removeAllObjects];
-    [sections_ removeAllObjects];
-
+- (void) _reloadPackages:(NSArray *)packages {
     _trace();
     for (Package *package in packages)
         if (
-            [package installed] == nil && [package valid] && [package visible] ||
+            [package uninstalled] && [package valid] && [package visible] ||
             [package upgradableAndEssential:YES]
         )
             [packages_ addObject:package];
 
     _trace();
-    [packages_ radixSortUsingFunction:reinterpret_cast<uint32_t (*)(id, void *)>(&PackageChangesRadix) withArgument:NULL];
+    [packages_ radixSortUsingFunction:reinterpret_cast<SKRadixFunction>(&PackageChangesRadix) withContext:NULL];
     _trace();
+}
+
+- (void) reloadData {
+    NSArray *packages = [database_ packages];
+
+    [packages_ removeAllObjects];
+    [sections_ removeAllObjects];
 
-    Section *upgradable = [[[Section alloc] initWithName:CYLocalize("AVAILABLE_UPGRADES")] autorelease];
-    Section *ignored = [[[Section alloc] initWithName:CYLocalize("IGNORED_UPGRADES")] autorelease];
+    UIProgressHUD *hud([delegate_ addProgressHUD]);
+    // XXX: localize
+    [hud setText:@"Loading Changes"];
+    NSLog(@"HUD:%@::%@", delegate_, hud);
+    [self yieldToSelector:@selector(_reloadPackages:) withObject:packages];
+    [delegate_ removeProgressHUD:hud];
+
+    Section *upgradable = [[[Section alloc] initWithName:UCLocalize("AVAILABLE_UPGRADES") localize:NO] autorelease];
+    Section *ignored = [[[Section alloc] initWithName:UCLocalize("IGNORED_UPGRADES") localize:NO] autorelease];
     Section *section = nil;
     NSDate *last = nil;
 
     upgrades_ = 0;
     bool unseens = false;
 
-    CFDateFormatterRef formatter = CFDateFormatterCreate(NULL, Locale_, kCFDateFormatterMediumStyle, kCFDateFormatterMediumStyle);
+    CFDateFormatterRef formatter(CFDateFormatterCreate(NULL, Locale_, kCFDateFormatterMediumStyle, kCFDateFormatterMediumStyle));
 
-    _trace();
     for (size_t offset = 0, count = [packages_ count]; offset != count; ++offset) {
         Package *package = [packages_ objectAtIndex:offset];
 
-        BOOL uae;
-        _profile(ChangesView$reloadData$Upgrade)
-            uae = [package upgradableAndEssential:YES];
-        _end
+        BOOL uae = [package upgradableAndEssential:YES];
 
         if (!uae) {
             unseens = true;
@@ -6371,28 +7088,20 @@ bool DepSubstrate(const pkgCache::VerIterator &iterator) {
                 seen = [package seen];
             _end
 
-            bool different;
-            _profile(ChangesView$reloadData$Compare)
-                different = section == nil || last != seen && (seen == nil || [seen compare:last] != NSOrderedSame);
-            _end
-
-            if (different) {
+            if (section == nil || last != seen && (seen == nil || [seen compare:last] != NSOrderedSame)) {
                 last = seen;
 
                 NSString *name;
                 if (seen == nil)
-                    name = CYLocalize("UNKNOWN");
+                    name = UCLocalize("UNKNOWN");
                 else {
-                    _profile(ChangesView$reloadData$Format)
-                        name = (NSString *) CFDateFormatterCreateStringWithDate(NULL, formatter, (CFDateRef) seen);
-                    _end
-
+                    name = (NSString *) CFDateFormatterCreateStringWithDate(NULL, formatter, (CFDateRef) seen);
                     [name autorelease];
                 }
 
                 _profile(ChangesView$reloadData$Allocate)
-                    name = [NSString stringWithFormat:CYLocalize("NEW_AT"), name];
-                    section = [[[Section alloc] initWithName:name row:offset] autorelease];
+                    name = [NSString stringWithFormat:UCLocalize("NEW_AT"), name];
+                    section = [[[Section alloc] initWithName:name row:offset localize:NO] autorelease];
                     [sections_ addObject:section];
                 _end
             }
@@ -6430,15 +7139,15 @@ bool DepSubstrate(const pkgCache::VerIterator &iterator) {
 }
 
 - (NSString *) leftButtonTitle {
-    return [(CYBook *)book_ updating] ? nil : CYLocalize("REFRESH");
+    return [(CYBook *)book_ updating] ? nil : UCLocalize("REFRESH");
 }
 
 - (id) rightButtonTitle {
-    return upgrades_ == 0 ? nil : [NSString stringWithFormat:CYLocalize("PARENTHETICAL"), CYLocalize("UPGRADE"), [NSString stringWithFormat:@"%u", upgrades_]];
+    return upgrades_ == 0 ? nil : [NSString stringWithFormat:UCLocalize("PARENTHETICAL"), UCLocalize("UPGRADE"), [NSString stringWithFormat:@"%u", upgrades_]];
 }
 
 - (NSString *) title {
-    return CYLocalize("CHANGES");
+    return UCLocalize("CHANGES");
 }
 
 @end
@@ -6451,11 +7160,7 @@ bool DepSubstrate(const pkgCache::VerIterator &iterator) {
 @interface SearchView : RVPage {
     UIView *accessory_;
     UISearchField *field_;
-    UITransitionView *transition_;
     FilteredPackageTable *table_;
-    UIPreferencesTable *advanced_;
-    UIView *dimmed_;
-    bool flipped_;
     bool reload_;
 }
 
@@ -6471,33 +7176,10 @@ bool DepSubstrate(const pkgCache::VerIterator &iterator) {
 
     [accessory_ release];
     [field_ release];
-    [transition_ release];
     [table_ release];
-    [advanced_ release];
-    [dimmed_ release];
     [super dealloc];
 }
 
-- (int) numberOfGroupsInPreferencesTable:(UIPreferencesTable *)table {
-    return 1;
-}
-
-- (NSString *) preferencesTable:(UIPreferencesTable *)table titleForGroup:(int)group {
-    switch (group) {
-        case 0: return [NSString stringWithFormat:CYLocalize("PARENTHETICAL"), CYLocalize("ADVANCED_SEARCH"), CYLocalize("COMING_SOON")];
-
-        default: _assert(false);
-    }
-}
-
-- (int) preferencesTable:(UIPreferencesTable *)table numberOfRowsInGroup:(int)group {
-    switch (group) {
-        case 0: return 0;
-
-        default: _assert(false);
-    }
-}
-
 - (void) _showKeyboard:(BOOL)show {
     CGSize keysize = [UIKeyboard defaultSize];
     CGRect keydown = [book_ pageBounds];
@@ -6528,21 +7210,26 @@ bool DepSubstrate(const pkgCache::VerIterator &iterator) {
     if (show)
         [animator performSelector:@selector(startAnimation:) withObject:animation afterDelay:delay];
 
-    [delegate_ showKeyboard:show];
+    //[delegate_ showKeyboard:show];
 }
 
 - (void) textFieldDidBecomeFirstResponder:(UITextField *)field {
     [self _showKeyboard:YES];
+    [table_ setObject:[field_ text] forFilter:@selector(isUnfilteredAndSelectedForBy:)];
+    [self reloadData];
 }
 
 - (void) textFieldDidResignFirstResponder:(UITextField *)field {
     [self _showKeyboard:NO];
+    [table_ setObject:[field_ text] forFilter:@selector(isUnfilteredAndSearchedForBy:)];
+    [self reloadData];
 }
 
 - (void) keyboardInputChanged:(UIFieldEditor *)editor {
     if (reload_) {
         NSString *text([field_ text]);
         [field_ setClearButtonStyle:(text == nil || [text length] == 0 ? 0 : 2)];
+        [table_ setObject:text forFilter:@selector(isUnfilteredAndSelectedForBy:)];
         [self reloadData];
         reload_ = false;
     }
@@ -6570,19 +7257,6 @@ bool DepSubstrate(const pkgCache::VerIterator &iterator) {
     if ((self = [super initWithBook:book]) != nil) {
         CGRect pageBounds = [book_ pageBounds];
 
-        transition_ = [[UITransitionView alloc] initWithFrame:pageBounds];
-        [self addSubview:transition_];
-
-        advanced_ = [[UIPreferencesTable alloc] initWithFrame:pageBounds];
-
-        [advanced_ setReusesTableCells:YES];
-        [advanced_ setDataSource:self];
-        [advanced_ reloadData];
-
-        dimmed_ = [[UIView alloc] initWithFrame:pageBounds];
-        CGColor dimmed(space_, 0, 0, 0, 0.5);
-        [dimmed_ setBackgroundColor:[UIColor colorWithCGColor:dimmed]];
-
         table_ = [[FilteredPackageTable alloc]
             initWithBook:book
             database:database
@@ -6591,33 +7265,28 @@ bool DepSubstrate(const pkgCache::VerIterator &iterator) {
             with:nil
         ];
 
+        [table_ setAutoresizingMask:UIViewAutoresizingFlexibleBoth];
+        [self addSubview:table_];
+
         [table_ setShouldHideHeaderInShortLists:NO];
-        [transition_ transition:0 toView:table_];
 
-        CGRect cnfrect = {{
-#ifdef __OBJC2__
-        6 +
-#endif
-        1, 38}, {17, 18}};
+        CGRect cnfrect = {{7, 38}, {17, 18}};
 
         CGRect area;
-        area.origin.x = /*cnfrect.origin.x + cnfrect.size.width + 4 +*/ 10;
-        area.origin.y = 1;
 
-        area.size.width =
-#ifdef __OBJC2__
-            8 +
-#endif
-            [self bounds].size.width - area.origin.x - 18;
+        area.origin.x = 10;
+        area.origin.y = 1;
 
+        area.size.width = [self bounds].size.width - area.origin.x * 2;
         area.size.height = [UISearchField defaultHeight];
 
         field_ = [[UISearchField alloc] initWithFrame:area];
+        [field_ setAutoresizingMask:UIViewAutoresizingFlexibleWidth];
 
         UIFont *font = [UIFont systemFontOfSize:16];
         [field_ setFont:font];
 
-        [field_ setPlaceholder:CYLocalize("SEARCH_EX")];
+        [field_ setPlaceholder:UCLocalize("SEARCH_EX")];
         [field_ setDelegate:self];
 
         [field_ setPaddingTop:5];
@@ -6630,43 +7299,14 @@ bool DepSubstrate(const pkgCache::VerIterator &iterator) {
         CGRect accrect = {{0, 6}, {6 + cnfrect.size.width + 6 + area.size.width + 6, area.size.height}};
 
         accessory_ = [[UIView alloc] initWithFrame:accrect];
+        [accessory_ setAutoresizingMask:UIViewAutoresizingFlexibleWidth];
         [accessory_ addSubview:field_];
 
-        /*UIPushButton *configure = [[[UIPushButton alloc] initWithFrame:cnfrect] autorelease];
-        [configure setShowPressFeedback:YES];
-        [configure setImage:[UIImage applicationImageNamed:@"advanced.png"]];
-        [configure addTarget:self action:@selector(configurePushed) forEvents:1];
-        [accessory_ addSubview:configure];*/
-
-        [self setAutoresizingMask:UIViewAutoresizingFlexibleHeight];
-        [table_ setAutoresizingMask:UIViewAutoresizingFlexibleHeight];
+        [self setAutoresizingMask:UIViewAutoresizingFlexibleBoth];
     } return self;
 }
 
-- (void) flipPage {
-#ifndef __OBJC2__
-    LKAnimation *animation = [LKTransition animation];
-    [animation setType:@"oglFlip"];
-    [animation setTimingFunction:[LKTimingFunction functionWithName:@"easeInEaseOut"]];
-    [animation setFillMode:@"extended"];
-    [animation setTransitionFlags:3];
-    [animation setDuration:10];
-    [animation setSpeed:0.35];
-    [animation setSubtype:(flipped_ ? @"fromLeft" : @"fromRight")];
-    [[transition_ _layer] addAnimation:animation forKey:0];
-    [transition_ transition:0 toView:(flipped_ ? (UIView *) table_ : (UIView *) advanced_)];
-    flipped_ = !flipped_;
-#endif
-}
-
-- (void) configurePushed {
-    [field_ resignFirstResponder];
-    [self flipPage];
-}
-
 - (void) resetViewAnimated:(BOOL)animated {
-    if (flipped_)
-        [self flipPage];
     [table_ resetViewAnimated:animated];
 }
 
@@ -6674,9 +7314,6 @@ bool DepSubstrate(const pkgCache::VerIterator &iterator) {
 }
 
 - (void) reloadData {
-    if (flipped_)
-        [self flipPage];
-    [table_ setObject:[field_ text]];
     _profile(SearchView$reloadData)
         [table_ reloadData];
     _end
@@ -6693,7 +7330,7 @@ bool DepSubstrate(const pkgCache::VerIterator &iterator) {
 }
 
 - (NSString *) backButtonTitle {
-    return CYLocalize("SEARCH");
+    return UCLocalize("SEARCH");
 }
 
 - (void) setDelegate:(id)delegate {
@@ -6703,7 +7340,7 @@ bool DepSubstrate(const pkgCache::VerIterator &iterator) {
 
 @end
 /* }}} */
-
+/* Settings View {{{ */
 @interface SettingsView : RVPage {
     _transient Database *database_;
     NSString *name_;
@@ -6750,7 +7387,7 @@ bool DepSubstrate(const pkgCache::VerIterator &iterator) {
         case 0: return nil;
         case 1: return nil;
 
-        default: _assert(false);
+        _nodefault
     }
 
     return nil;
@@ -6764,7 +7401,7 @@ bool DepSubstrate(const pkgCache::VerIterator &iterator) {
         case 0: return NO;
         case 1: return YES;
 
-        default: _assert(false);
+        _nodefault
     }
 
     return NO;
@@ -6778,7 +7415,7 @@ bool DepSubstrate(const pkgCache::VerIterator &iterator) {
         case 0: return 1;
         case 1: return 1;
 
-        default: _assert(false);
+        _nodefault
     }
 
     return 0;
@@ -6823,21 +7460,21 @@ bool DepSubstrate(const pkgCache::VerIterator &iterator) {
                 return subscribedCell_;
             case 1:
                 return ignoredCell_;
-            default: _assert(false);
+            _nodefault
         } break;
 
         case 1: switch (row) {
             case 0: {
                 UIPreferencesControlTableCell *cell([[[UIPreferencesControlTableCell alloc] init] autorelease]);
                 [cell setShowSelection:NO];
-                [cell setTitle:CYLocalize("SHOW_ALL_CHANGES_EX")];
+                [cell setTitle:UCLocalize("SHOW_ALL_CHANGES_EX")];
                 return cell;
             }
 
-            default: _assert(false);
+            _nodefault
         } break;
 
-        default: _assert(false);
+        _nodefault
     }
 
     return nil;
@@ -6852,19 +7489,19 @@ bool DepSubstrate(const pkgCache::VerIterator &iterator) {
         [self addSubview:table_];
 
         subscribedSwitch_ = [[_UISwitchSlider alloc] initWithFrame:CGRectMake(200, 10, 50, 20)];
-        [subscribedSwitch_ addTarget:self action:@selector(onSubscribed:) forEvents:kUIControlEventMouseUpInside];
+        [subscribedSwitch_ addTarget:self action:@selector(onSubscribed:) forEvents:UIControlEventTouchUpInside];
 
         ignoredSwitch_ = [[_UISwitchSlider alloc] initWithFrame:CGRectMake(200, 10, 50, 20)];
-        [ignoredSwitch_ addTarget:self action:@selector(onIgnored:) forEvents:kUIControlEventMouseUpInside];
+        [ignoredSwitch_ addTarget:self action:@selector(onIgnored:) forEvents:UIControlEventTouchUpInside];
 
         subscribedCell_ = [[UIPreferencesControlTableCell alloc] init];
         [subscribedCell_ setShowSelection:NO];
-        [subscribedCell_ setTitle:CYLocalize("SHOW_ALL_CHANGES")];
+        [subscribedCell_ setTitle:UCLocalize("SHOW_ALL_CHANGES")];
         [subscribedCell_ setControl:subscribedSwitch_];
 
         ignoredCell_ = [[UIPreferencesControlTableCell alloc] init];
         [ignoredCell_ setShowSelection:NO];
-        [ignoredCell_ setTitle:CYLocalize("IGNORE_UPGRADES")];
+        [ignoredCell_ setTitle:UCLocalize("IGNORE_UPGRADES")];
         [ignoredCell_ setControl:ignoredSwitch_];
 
         [table_ setDataSource:self];
@@ -6890,13 +7527,14 @@ bool DepSubstrate(const pkgCache::VerIterator &iterator) {
 }
 
 - (NSString *) title {
-    return CYLocalize("SETTINGS");
+    return UCLocalize("SETTINGS");
 }
 
 @end
+/* }}} */
 
 /* Signature View {{{ */
-@interface SignatureView : BrowserView {
+@interface SignatureView : CydiaBrowserView {
     _transient Database *database_;
     NSString *package_;
 }
@@ -6935,6 +7573,19 @@ bool DepSubstrate(const pkgCache::VerIterator &iterator) {
 @end
 /* }}} */
 
+@interface CydiaViewController : UIViewController {
+}
+
+@end
+
+@implementation CydiaViewController
+
+- (BOOL) shouldAutorotateToInterfaceOrientation:(UIInterfaceOrientation)orientation {
+    return NO; // XXX: return YES;
+}
+
+@end
+
 @interface Cydia : UIApplication <
     ConfirmationViewDelegate,
     ProgressViewDelegate,
@@ -6942,11 +7593,14 @@ bool DepSubstrate(const pkgCache::VerIterator &iterator) {
     CydiaDelegate
 > {
     UIWindow *window_;
+    CydiaViewController *root_;
 
     UIView *underlay_;
     UIView *overlay_;
     CYBook *book_;
-    UIToolbar *buttonbar_;
+
+    NSArray *items_;
+    UITabBar *toolbar_;
 
     RVBook *confirm_;
 
@@ -6956,7 +7610,7 @@ bool DepSubstrate(const pkgCache::VerIterator &iterator) {
     Database *database_;
     ProgressView *progress_;
 
-    unsigned tag_;
+    int tag_;
 
     UIKeyboard *keyboard_;
     UIProgressHUD *hud_;
@@ -6966,57 +7620,95 @@ bool DepSubstrate(const pkgCache::VerIterator &iterator) {
     ManageView *manage_;
     SearchView *search_;
 
-    PackageView *package_;
+#if RecyclePackageViews
+    NSMutableArray *details_;
+#endif
 }
 
+- (RVPage *) _pageForURL:(NSURL *)url withClass:(Class)_class;
+- (void) setPage:(RVPage *)page;
+
 @end
 
+static _finline void _setHomePage(Cydia *self) {
+    [self setPage:[self _pageForURL:[NSURL URLWithString:CydiaURL(@"")] withClass:[HomeView class]]];
+}
+
 @implementation Cydia
 
+- (UIView *) rotatingContentViewForWindow:(UIWindow *)window {
+    return window_;
+}
+
 - (void) _loaded {
     if ([broken_ count] != 0) {
         int count = [broken_ count];
 
-        UIActionSheet *sheet = [[[UIActionSheet alloc]
-            initWithTitle:(count == 1 ? CYLocalize("HALFINSTALLED_PACKAGE") : [NSString stringWithFormat:CYLocalize("HALFINSTALLED_PACKAGES"), count])
-            buttons:[NSArray arrayWithObjects:
-                CYLocalize("FORCIBLY_CLEAR"),
-                CYLocalize("TEMPORARY_IGNORE"),
-            nil]
-            defaultButtonIndex:0
-            delegate:self
-            context:@"fixhalf"
+        UIAlertView *alert = [[[UIAlertView alloc]
+            initWithTitle:(count == 1 ? UCLocalize("HALFINSTALLED_PACKAGE") : [NSString stringWithFormat:UCLocalize("HALFINSTALLED_PACKAGES"), count])
+                       message:UCLocalize("HALFINSTALLED_PACKAGE_EX")
+                       delegate:self
+                       cancelButtonTitle:UCLocalize("FORCIBLY_CLEAR")
+                       otherButtonTitles:UCLocalize("TEMPORARY_IGNORE"), nil
         ] autorelease];
 
-        [sheet setBodyText:CYLocalize("HALFINSTALLED_PACKAGE_EX")];
-        [sheet popupAlertAnimated:YES];
+        [alert setContext:@"fixhalf"];
+        [alert show];
     } else if (!Ignored_ && [essential_ count] != 0) {
         int count = [essential_ count];
 
-        UIActionSheet *sheet = [[[UIActionSheet alloc]
-            initWithTitle:(count == 1 ? CYLocalize("ESSENTIAL_UPGRADE") : [NSString stringWithFormat:CYLocalize("ESSENTIAL_UPGRADES"), count])
-            buttons:[NSArray arrayWithObjects:
-                CYLocalize("UPGRADE_ESSENTIAL"),
-                CYLocalize("COMPLETE_UPGRADE"),
-                CYLocalize("TEMPORARY_IGNORE"),
-            nil]
-            defaultButtonIndex:0
-            delegate:self
-            context:@"upgrade"
+        UIAlertView *alert = [[[UIAlertView alloc]
+            initWithTitle:(count == 1 ? UCLocalize("ESSENTIAL_UPGRADE") : [NSString stringWithFormat:UCLocalize("ESSENTIAL_UPGRADES"), count])
+                       message:UCLocalize("ESSENTIAL_UPGRADE_EX")
+                       delegate:self
+                       cancelButtonTitle:UCLocalize("TEMPORARY_IGNORE")
+            otherButtonTitles:UCLocalize("UPGRADE_ESSENTIAL"), UCLocalize("COMPLETE_UPGRADE"), nil
         ] autorelease];
 
-        [sheet setBodyText:CYLocalize("ESSENTIAL_UPGRADE_EX")];
-        [sheet popupAlertAnimated:YES];
+        [alert setContext:@"upgrade"];
+        [alert show];
+    }
+}
+
+- (void) _saveConfig {
+    if (Changed_) {
+        _trace();
+        NSString *error(nil);
+        if (NSData *data = [NSPropertyListSerialization dataFromPropertyList:Metadata_ format:NSPropertyListBinaryFormat_v1_0 errorDescription:&error]) {
+            _trace();
+            NSError *error(nil);
+            if (![data writeToFile:@"/var/lib/cydia/metadata.plist" options:NSAtomicWrite error:&error])
+                NSLog(@"failure to save metadata data: %@", error);
+            _trace();
+        } else {
+            NSLog(@"failure to serialize metadata: %@", error);
+            return;
+        }
+
+        Changed_ = false;
     }
 }
 
+- (void) _updateData {
+    [self _saveConfig];
+
+    /* XXX: this is just stupid */
+    if (tag_ != 1 && sections_ != nil)
+        [sections_ reloadData];
+    if (tag_ != 2 && changes_ != nil)
+        [changes_ reloadData];
+    if (tag_ != 4 && search_ != nil)
+        [search_ reloadData];
+
+    [book_ reloadData];
+}
+
 - (void) _reloadData {
     UIView *block();
 
     static bool loaded(false);
     UIProgressHUD *hud([self addProgressHUD]);
-    [hud setText:(loaded ? CYLocalize("RELOADING_DATA") : CYLocalize("LOADING_DATA"))];
-    loaded = true;
+    [hud setText:(loaded ? UCLocalize("RELOADING_DATA") : UCLocalize("LOADING_DATA"))];
 
     [database_ yieldToSelector:@selector(reloadData) withObject:nil];
     _trace();
@@ -7028,7 +7720,7 @@ bool DepSubstrate(const pkgCache::VerIterator &iterator) {
     [essential_ removeAllObjects];
     [broken_ removeAllObjects];
 
-    NSArray *packages = [database_ packages];
+    NSArray *packages([database_ packages]);
     for (Package *package in packages) {
         if ([package half])
             [broken_ addObject:package];
@@ -7041,17 +7733,17 @@ bool DepSubstrate(const pkgCache::VerIterator &iterator) {
 
     if (changes != 0) {
         NSString *badge([[NSNumber numberWithInt:changes] stringValue]);
-        [buttonbar_ setBadgeValue:badge forButton:3];
-        if ([buttonbar_ respondsToSelector:@selector(setBadgeAnimated:forButton:)])
-            [buttonbar_ setBadgeAnimated:([essential_ count] != 0) forButton:3];
+               [[[toolbar_ items] objectAtIndex:2] setBadgeValue:badge];
+        if ([toolbar_ respondsToSelector:@selector(setBadgeAnimated:forButton:)])
+                       [[[toolbar_ items] objectAtIndex:2] setAnimatedBadge:YES];
         if ([self respondsToSelector:@selector(setApplicationBadge:)])
             [self setApplicationBadge:badge];
         else
             [self setApplicationBadgeString:badge];
     } else {
-        [buttonbar_ setBadgeValue:nil forButton:3];
-        if ([buttonbar_ respondsToSelector:@selector(setBadgeAnimated:forButton:)])
-            [buttonbar_ setBadgeAnimated:NO forButton:3];
+               [[[toolbar_ items] objectAtIndex:2] setBadgeValue:nil];
+        if ([toolbar_ respondsToSelector:@selector(setBadgeAnimated:forButton:)])
+            [[[toolbar_ items] objectAtIndex:2] setAnimatedBadge:NO];
         if ([self respondsToSelector:@selector(removeApplicationBadge)])
             [self removeApplicationBadge];
         else // XXX: maybe use setApplicationBadgeString also?
@@ -7059,58 +7751,30 @@ bool DepSubstrate(const pkgCache::VerIterator &iterator) {
     }
 
     Queuing_ = false;
-    [buttonbar_ setBadgeValue:nil forButton:4];
+    [[[toolbar_ items] objectAtIndex:3] setBadgeValue:nil];
 
-    [self updateData];
+    [self _updateData];
 
-    // XXX: what is this line of code for?
-    if ([packages count] == 0);
-    else if (Loaded_ || ManualRefresh) loaded:
+    if (loaded || ManualRefresh) loaded:
         [self _loaded];
     else {
-        Loaded_ = YES;
+        loaded = true;
+
+        NSDate *update([Metadata_ objectForKey:@"LastUpdate"]);
 
-        if (NSDate *update = [Metadata_ objectForKey:@"LastUpdate"]) {
+        if (update != nil) {
             NSTimeInterval interval([update timeIntervalSinceNow]);
-            if (interval <= 0 && interval > -600)
+            if (interval <= 0 && interval > -(15*60))
                 goto loaded;
         }
 
-        [book_ update];
-    }
-}
-
-- (void) _saveConfig {
-    if (Changed_) {
-        _trace();
-        NSString *error(nil);
-        if (NSData *data = [NSPropertyListSerialization dataFromPropertyList:Metadata_ format:NSPropertyListBinaryFormat_v1_0 errorDescription:&error]) {
-            _trace();
-            NSError *error(nil);
-            if (![data writeToFile:@"/var/lib/cydia/metadata.plist" options:NSAtomicWrite error:&error])
-                NSLog(@"failure to save metadata data: %@", error);
-            _trace();
-        } else {
-            NSLog(@"failure to serialize metadata: %@", error);
-            return;
-        }
-
-        Changed_ = false;
+        [book_ setUpdate:update];
     }
 }
 
 - (void) updateData {
-    [self _saveConfig];
-
-    /* XXX: this is just stupid */
-    if (tag_ != 2 && sections_ != nil)
-        [sections_ reloadData];
-    if (tag_ != 3 && changes_ != nil)
-        [changes_ reloadData];
-    if (tag_ != 5 && search_ != nil)
-        [search_ reloadData];
-
-    [book_ reloadData];
+    [database_ setVisible];
+    [self _updateData];
 }
 
 - (void) update_ {
@@ -7118,13 +7782,11 @@ bool DepSubstrate(const pkgCache::VerIterator &iterator) {
 }
 
 - (void) syncData {
-    FILE *file = fopen("/etc/apt/sources.list.d/cydia.list", "w");
+    FILE *file(fopen("/etc/apt/sources.list.d/cydia.list", "w"));
     _assert(file != NULL);
 
-    NSArray *keys = [Sources_ allKeys];
-
-    for (NSString *key in keys) {
-        NSDictionary *source = [Sources_ objectForKey:key];
+    for (NSString *key in [Sources_ allKeys]) {
+        NSDictionary *source([Sources_ objectForKey:key]);
 
         fprintf(file, "%s %s %s\n",
             [[source objectForKey:@"Type"] UTF8String],
@@ -7141,7 +7803,7 @@ bool DepSubstrate(const pkgCache::VerIterator &iterator) {
         detachNewThreadSelector:@selector(update_)
         toTarget:self
         withObject:nil
-        title:CYLocalize("UPDATING_SOURCES")
+        title:UCLocalize("UPDATING_SOURCES")
     ];
 }
 
@@ -7168,10 +7830,12 @@ bool DepSubstrate(const pkgCache::VerIterator &iterator) {
     return [underlay_ bounds];
 }
 
-- (void) perform {
-    [database_ prepare];
+- (bool) perform {
+    if (![database_ prepare])
+        return false;
 
     confirm_ = [[RVBook alloc] initWithFrame:[self popUpBounds]];
+    [confirm_ setAutoresizingMask:UIViewAutoresizingFlexibleBoth];
     [confirm_ setDelegate:self];
 
     ConfirmationView *page([[[ConfirmationView alloc] initWithBook:confirm_ database:database_] autorelease]);
@@ -7179,6 +7843,8 @@ bool DepSubstrate(const pkgCache::VerIterator &iterator) {
 
     [confirm_ setPage:page];
     [self popUpBook:confirm_];
+
+    return true;
 }
 
 - (void) queue {
@@ -7195,6 +7861,15 @@ bool DepSubstrate(const pkgCache::VerIterator &iterator) {
     }
 }
 
+- (void) installPackages:(NSArray *)packages {
+    @synchronized (self) {
+        for (Package *package in packages)
+            [package install];
+        [self resolve];
+        [self perform];
+    }
+}
+
 - (void) installPackage:(Package *)package {
     @synchronized (self) {
         [package install];
@@ -7213,7 +7888,8 @@ bool DepSubstrate(const pkgCache::VerIterator &iterator) {
 
 - (void) distUpgrade {
     @synchronized (self) {
-        [database_ upgrade];
+        if (![database_ upgrade])
+            return;
         [self perform];
     }
 }
@@ -7221,7 +7897,7 @@ bool DepSubstrate(const pkgCache::VerIterator &iterator) {
 - (void) cancel {
     [self slideUp:[[[UIActionSheet alloc]
         initWithTitle:nil
-        buttons:[NSArray arrayWithObjects:CYLocalize("CONTINUE_QUEUING"), CYLocalize("CANCEL_CLEAR"), nil]
+        buttons:[NSArray arrayWithObjects:UCLocalize("CONTINUE_QUEUING"), UCLocalize("CANCEL_CLEAR"), nil]
         defaultButtonIndex:1
         delegate:self
         context:@"cancel"
@@ -7247,24 +7923,7 @@ bool DepSubstrate(const pkgCache::VerIterator &iterator) {
         detachNewThreadSelector:@selector(perform)
         toTarget:database_
         withObject:nil
-        title:CYLocalize("RUNNING")
-    ];
-}
-
-- (void) bootstrap_ {
-    [database_ update];
-    [database_ upgrade];
-    [database_ prepare];
-    [database_ perform];
-}
-
-/* XXX: replace and localize */
-- (void) bootstrap {
-    [progress_
-        detachNewThreadSelector:@selector(bootstrap_)
-        toTarget:self
-        withObject:nil
-        title:@"Bootstrap Install"
+        title:UCLocalize("RUNNING")
     ];
 }
 
@@ -7284,226 +7943,130 @@ bool DepSubstrate(const pkgCache::VerIterator &iterator) {
 }
 
 - (RVPage *) _pageForURL:(NSURL *)url withClass:(Class)_class {
-    BrowserView *browser = [[[_class alloc] initWithBook:book_] autorelease];
+    CydiaBrowserView *browser = [[[_class alloc] initWithBook:book_] autorelease];
     [browser loadURL:url];
     return browser;
 }
 
-- (void) _setHomePage {
-    [self setPage:[self _pageForURL:[NSURL URLWithString:@"http://cydia.saurik.com/"] withClass:[HomeView class]]];
-}
-
 - (SectionsView *) sectionsView {
     if (sections_ == nil)
         sections_ = [[SectionsView alloc] initWithBook:book_ database:database_];
     return sections_;
 }
 
-- (void) buttonBarItemTapped:(id)sender {
-    unsigned tag = [sender tag];
+- (ChangesView *) changesView {
+    if (changes_ == nil)
+        changes_ = [[ChangesView alloc] initWithBook:book_ database:database_ delegate:self];
+    return changes_;
+}
+
+- (ManageView *) manageView {
+    if (manage_ == nil)
+        manage_ = (ManageView *) [[self
+            _pageForURL:[NSURL fileURLWithPath:[[NSBundle mainBundle] pathForResource:@"manage" ofType:@"html"]]
+            withClass:[ManageView class]
+        ] retain];
+    return manage_;
+}
+
+- (SearchView *) searchView {
+    if (search_ == nil)
+        search_ = [[SearchView alloc] initWithBook:book_ database:database_];
+    return search_;
+}
+
+- (void) tabBar:(UITabBar *)sender didSelectItem:(UITabBarItem *)item {
+    int tag = [item tag];
     if (tag == tag_) {
         [book_ resetViewAnimated:YES];
         return;
-    } else if (tag_ == 2 && tag != 2)
+    } else if (tag_ == 1)
         [[self sectionsView] resetView];
 
     switch (tag) {
-        case 1: [self _setHomePage]; break;
+        case 0: _setHomePage(self); break;
 
-        case 2: [self setPage:[self sectionsView]]; break;
-        case 3: [self setPage:changes_]; break;
-        case 4: [self setPage:manage_]; break;
-        case 5: [self setPage:search_]; break;
+        case 1: [self setPage:[self sectionsView]]; break;
+        case 2: [self setPage:[self changesView]]; break;
+        case 3: [self setPage:[self manageView]]; break;
+        case 4: [self setPage:[self searchView]]; break;
 
-        default: _assert(false);
+        _nodefault
     }
 
     tag_ = tag;
 }
 
-- (void) applicationWillSuspend {
-    [database_ clean];
-    [super applicationWillSuspend];
-}
-
 - (void) askForSettings {
-    NSString *parenthetical(CYLocalize("PARENTHETICAL"));
+    NSString *parenthetical(UCLocalize("PARENTHETICAL"));
 
-    UIActionSheet *role = [[[UIActionSheet alloc]
-        initWithTitle:CYLocalize("WHO_ARE_YOU")
+    CYActionSheet *role([[[CYActionSheet alloc]
+        initWithTitle:UCLocalize("WHO_ARE_YOU")
         buttons:[NSArray arrayWithObjects:
-            [NSString stringWithFormat:parenthetical, CYLocalize("USER"), CYLocalize("USER_EX")],
-            [NSString stringWithFormat:parenthetical, CYLocalize("HACKER"), CYLocalize("HACKER_EX")],
-            [NSString stringWithFormat:parenthetical, CYLocalize("DEVELOPER"), CYLocalize("DEVELOPER_EX")],
+            [NSString stringWithFormat:parenthetical, UCLocalize("USER"), UCLocalize("USER_EX")],
+            [NSString stringWithFormat:parenthetical, UCLocalize("HACKER"), UCLocalize("HACKER_EX")],
+            [NSString stringWithFormat:parenthetical, UCLocalize("DEVELOPER"), UCLocalize("DEVELOPER_EX")],
         nil]
         defaultButtonIndex:-1
-        delegate:self
-        context:@"role"
-    ] autorelease];
-
-    [role setBodyText:CYLocalize("ROLE_EX")];
-    [role popupAlertAnimated:YES];
-}
-
-- (void) setPackageView:(PackageView *)view {
-    if (package_ == nil)
-        package_ = [view retain];
-}
-
-- (PackageView *) packageView {
-    PackageView *view;
-
-    if (package_ == nil)
-        view = [[[PackageView alloc] initWithBook:book_ database:database_] autorelease];
-    else {
-        return package_;
-        view = [package_ autorelease];
-        package_ = nil;
-    }
+    ] autorelease]);
 
-    return view;
-}
+    [role setMessage:UCLocalize("ROLE_EX")];
 
-- (void) finish {
-    if (hud_ != nil) {
-        [self setStatusBarShowsProgress:NO];
-        [self removeProgressHUD:hud_];
+    int button([role yieldToPopupAlertAnimated:YES]);
 
-        [hud_ autorelease];
-        hud_ = nil;
-
-        pid_t pid = ExecFork();
-        if (pid == 0) {
-            execlp("launchctl", "launchctl", "stop", "com.apple.SpringBoard", NULL);
-            perror("launchctl stop");
-        }
-
-        return;
-    }
+    switch (button) {
+        case 1: Role_ = @"User"; break;
+        case 2: Role_ = @"Hacker"; break;
+        case 3: Role_ = @"Developer"; break;
 
-    if (Role_ == nil) {
-        [self askForSettings];
-        return;
+        _nodefault
     }
 
-    _trace();
-    overlay_ = [[UIView alloc] initWithFrame:[underlay_ bounds]];
-
-    CGRect screenrect = [UIHardware fullScreenApplicationContentRect];
-    book_ = [[CYBook alloc] initWithFrame:CGRectMake(
-        0, 0, screenrect.size.width, screenrect.size.height - 48
-    ) database:database_];
-
-    [book_ setDelegate:self];
-
-    [overlay_ addSubview:book_];
-
-    NSArray *buttonitems = [NSArray arrayWithObjects:
-        [NSDictionary dictionaryWithObjectsAndKeys:
-            @"buttonBarItemTapped:", kUIButtonBarButtonAction,
-            @"home-up.png", kUIButtonBarButtonInfo,
-            @"home-dn.png", kUIButtonBarButtonSelectedInfo,
-            [NSNumber numberWithInt:1], kUIButtonBarButtonTag,
-            self, kUIButtonBarButtonTarget,
-            @"Cydia", kUIButtonBarButtonTitle,
-            @"0", kUIButtonBarButtonType,
-        nil],
-
-        [NSDictionary dictionaryWithObjectsAndKeys:
-            @"buttonBarItemTapped:", kUIButtonBarButtonAction,
-            @"install-up.png", kUIButtonBarButtonInfo,
-            @"install-dn.png", kUIButtonBarButtonSelectedInfo,
-            [NSNumber numberWithInt:2], kUIButtonBarButtonTag,
-            self, kUIButtonBarButtonTarget,
-            CYLocalize("SECTIONS"), kUIButtonBarButtonTitle,
-            @"0", kUIButtonBarButtonType,
-        nil],
-
-        [NSDictionary dictionaryWithObjectsAndKeys:
-            @"buttonBarItemTapped:", kUIButtonBarButtonAction,
-            @"changes-up.png", kUIButtonBarButtonInfo,
-            @"changes-dn.png", kUIButtonBarButtonSelectedInfo,
-            [NSNumber numberWithInt:3], kUIButtonBarButtonTag,
-            self, kUIButtonBarButtonTarget,
-            CYLocalize("CHANGES"), kUIButtonBarButtonTitle,
-            @"0", kUIButtonBarButtonType,
-        nil],
-
-        [NSDictionary dictionaryWithObjectsAndKeys:
-            @"buttonBarItemTapped:", kUIButtonBarButtonAction,
-            @"manage-up.png", kUIButtonBarButtonInfo,
-            @"manage-dn.png", kUIButtonBarButtonSelectedInfo,
-            [NSNumber numberWithInt:4], kUIButtonBarButtonTag,
-            self, kUIButtonBarButtonTarget,
-            CYLocalize("MANAGE"), kUIButtonBarButtonTitle,
-            @"0", kUIButtonBarButtonType,
-        nil],
-
-        [NSDictionary dictionaryWithObjectsAndKeys:
-            @"buttonBarItemTapped:", kUIButtonBarButtonAction,
-            @"search-up.png", kUIButtonBarButtonInfo,
-            @"search-dn.png", kUIButtonBarButtonSelectedInfo,
-            [NSNumber numberWithInt:5], kUIButtonBarButtonTag,
-            self, kUIButtonBarButtonTarget,
-            CYLocalize("SEARCH"), kUIButtonBarButtonTitle,
-            @"0", kUIButtonBarButtonType,
-        nil],
+    Settings_ = [NSMutableDictionary dictionaryWithObjectsAndKeys:
+        Role_, @"Role",
     nil];
 
-    buttonbar_ = [[UIToolbar alloc]
-        initInView:overlay_
-        withFrame:CGRectMake(
-            0, screenrect.size.height - ButtonBarHeight_,
-            screenrect.size.width, ButtonBarHeight_
-        )
-        withItemList:buttonitems
-    ];
-
-    [buttonbar_ setDelegate:self];
-    [buttonbar_ setBarStyle:1];
-    [buttonbar_ setButtonBarTrackingMode:2];
-
-    int buttons[5] = {1, 2, 3, 4, 5};
-    [buttonbar_ registerButtonGroup:0 withButtons:buttons withCount:5];
-    [buttonbar_ showButtonGroup:0 withDuration:0];
-
-    for (int i = 0; i != 5; ++i)
-        [[buttonbar_ viewWithTag:(i + 1)] setFrame:CGRectMake(
-            i * 64 + 2, 1, 60, ButtonBarHeight_
-        )];
-
-    [buttonbar_ showSelectionForButton:1];
-    [overlay_ addSubview:buttonbar_];
+    [Metadata_ setObject:Settings_ forKey:@"Settings"];
 
-    [UIKeyboard initImplementationNow];
-    CGSize keysize = [UIKeyboard defaultSize];
-    CGRect keyrect = {{0, [overlay_ bounds].size.height}, keysize};
-    keyboard_ = [[UIKeyboard alloc] initWithFrame:keyrect];
-    //[[UIKeyboardImpl sharedInstance] setSoundsEnabled:(Sounds_Keyboard_ ? YES : NO)];
-    [overlay_ addSubview:keyboard_];
-
-    if (!bootstrap_)
-        [underlay_ addSubview:overlay_];
+    Changed_ = true;
 
-    [self reloadData];
+    [role dismiss];
+}
 
-    [self sectionsView];
-    changes_ = [[ChangesView alloc] initWithBook:book_ database:database_];
-    search_ = [[SearchView alloc] initWithBook:book_ database:database_];
+- (void) setPackageView:(PackageView *)view {
+    WebThreadLock();
+    [view setPackage:nil];
+#if RecyclePackageViews
+    if ([details_ count] < 3)
+        [details_ addObject:view];
+#endif
+    WebThreadUnlock();
+}
 
-    manage_ = (ManageView *) [[self
-        _pageForURL:[NSURL fileURLWithPath:[[NSBundle mainBundle] pathForResource:@"manage" ofType:@"html"]]
-        withClass:[ManageView class]
-    ] retain];
+- (PackageView *) _packageView {
+    return [[[PackageView alloc] initWithBook:book_ database:database_] autorelease];
+}
 
-    [self setPackageView:[self packageView]];
+- (PackageView *) packageView {
+#if RecyclePackageViews
+    PackageView *view;
+    size_t count([details_ count]);
 
-    PrintTimes();
+    if (count == 0) {
+        view = [self _packageView];
+      renew:
+        [details_ addObject:[self _packageView]];
+    } else {
+        view = [[[details_ lastObject] retain] autorelease];
+        [details_ removeLastObject];
+        if (count == 1)
+            goto renew;
+    }
 
-    if (bootstrap_)
-        [self bootstrap];
-    else
-        [self _setHomePage];
+    return view;
+#else
+    return [self _packageView];
+#endif
 }
 
 - (void) alertSheet:(UIActionSheet *)sheet buttonClicked:(int)button {
@@ -7523,8 +8086,7 @@ bool DepSubstrate(const pkgCache::VerIterator &iterator) {
                 clear = true;
             break;
 
-            default:
-                _assert(false);
+            _nodefault
         }
 
         [sheet dismiss];
@@ -7534,7 +8096,7 @@ bool DepSubstrate(const pkgCache::VerIterator &iterator) {
                 [self _reloadData];
             else {
                 Queuing_ = true;
-                [buttonbar_ setBadgeValue:CYLocalize("Q_D") forButton:4];
+                [[[toolbar_ items] objectAtIndex:3] setBadgeValue:UCLocalize("Q_D")];
                 [book_ reloadData];
             }
 
@@ -7543,93 +8105,60 @@ bool DepSubstrate(const pkgCache::VerIterator &iterator) {
                 confirm_ = nil;
             }
         }
-    } else if ([context isEqualToString:@"fixhalf"]) {
-        switch (button) {
-            case 1:
-                @synchronized (self) {
-                    for (Package *broken in broken_) {
-                        [broken remove];
-
-                        NSString *id = [broken id];
-                        unlink([[NSString stringWithFormat:@"/var/lib/dpkg/info/%@.prerm", id] UTF8String]);
-                        unlink([[NSString stringWithFormat:@"/var/lib/dpkg/info/%@.postrm", id] UTF8String]);
-                        unlink([[NSString stringWithFormat:@"/var/lib/dpkg/info/%@.preinst", id] UTF8String]);
-                        unlink([[NSString stringWithFormat:@"/var/lib/dpkg/info/%@.postinst", id] UTF8String]);
-                    }
-
-                    [self resolve];
-                    [self perform];
+    } 
+}
+
+- (void)alertView:(UIAlertView *)alert clickedButtonAtIndex:(NSInteger)button {
+       NSString *context([alert context]);
+       
+       if ([context isEqualToString:@"fixhalf"]) {
+               if (button == [alert firstOtherButtonIndex]) {
+            @synchronized (self) {
+                for (Package *broken in broken_) {
+                    [broken remove];
+
+                    NSString *id = [broken id];
+                    unlink([[NSString stringWithFormat:@"/var/lib/dpkg/info/%@.prerm", id] UTF8String]);
+                    unlink([[NSString stringWithFormat:@"/var/lib/dpkg/info/%@.postrm", id] UTF8String]);
+                    unlink([[NSString stringWithFormat:@"/var/lib/dpkg/info/%@.preinst", id] UTF8String]);
+                    unlink([[NSString stringWithFormat:@"/var/lib/dpkg/info/%@.postinst", id] UTF8String]);
                 }
-            break;
 
-            case 2:
-                [broken_ removeAllObjects];
-                [self _loaded];
-            break;
-
-            default:
-                _assert(false);
-        }
-
-        [sheet dismiss];
-    } else if ([context isEqualToString:@"role"]) {
-        switch (button) {
-            case 1: Role_ = @"User"; break;
-            case 2: Role_ = @"Hacker"; break;
-            case 3: Role_ = @"Developer"; break;
-
-            default:
-                Role_ = nil;
-                _assert(false);
+                [self resolve];
+                [self perform];
+            }
+               } else if (button == [alert cancelButtonIndex]) {
+            [broken_ removeAllObjects];
+            [self _loaded];
         }
 
-        bool reset = Settings_ != nil;
-
-        Settings_ = [NSMutableDictionary dictionaryWithObjectsAndKeys:
-            Role_, @"Role",
-        nil];
-
-        [Metadata_ setObject:Settings_ forKey:@"Settings"];
-
-        Changed_ = true;
-
-        if (reset)
-            [self updateData];
-        else
-            [self finish];
-
-        [sheet dismiss];
+        [alert dismissWithClickedButtonIndex:-1 animated:YES];
     } else if ([context isEqualToString:@"upgrade"]) {
-        switch (button) {
-            case 1:
-                @synchronized (self) {
-                    for (Package *essential in essential_)
-                        [essential install];
-
-                    [self resolve];
-                    [self perform];
-                }
-            break;
-
-            case 2:
-                [self distUpgrade];
-            break;
-
-            case 3:
-                Ignored_ = YES;
-            break;
+        if (button == [alert firstOtherButtonIndex]) {
+            @synchronized (self) {
+                for (Package *essential in essential_)
+                    [essential install];
 
-            default:
-                _assert(false);
+                [self resolve];
+                [self perform];
+            }
+        } else if (button == [alert firstOtherButtonIndex] + 1) {
+            [self distUpgrade];
+        } else if (button == [alert cancelButtonIndex]) {
+            Ignored_ = YES;
         }
 
-        [sheet dismiss];
+        [alert dismissWithClickedButtonIndex:-1 animated:YES];
     }
 }
 
-- (void) reorganize { _pooled
-    system("/usr/libexec/cydia/free.sh");
-    [self performSelectorOnMainThread:@selector(finish) withObject:nil waitUntilDone:NO];
+- (void) system:(NSString *)command { _pooled
+    system([command UTF8String]);
+}
+
+- (void) applicationWillSuspend {
+    [database_ clean];
+    [super applicationWillSuspend];
 }
 
 - (void) applicationSuspend:(__GSEvent *)event {
@@ -7649,6 +8178,8 @@ bool DepSubstrate(const pkgCache::VerIterator &iterator) {
 
 - (UIProgressHUD *) addProgressHUD {
     UIProgressHUD *hud([[[UIProgressHUD alloc] initWithWindow:window_] autorelease]);
+    [hud setAutoresizingMask:UIViewAutoresizingFlexibleBoth];
+
     [window_ setUserInteractionEnabled:NO];
     [hud show:YES];
     [progress_ addSubview:hud];
@@ -7661,44 +8192,25 @@ bool DepSubstrate(const pkgCache::VerIterator &iterator) {
     [window_ setUserInteractionEnabled:YES];
 }
 
-- (void) openMailToURL:(NSURL *)url {
-// XXX: this makes me sad
-#if 0
-    [[[MailToView alloc] initWithView:underlay_ delegate:self url:url] autorelease];
-#else
-    [UIApp openURL:url];// asPanel:YES];
-#endif
-}
-
-- (void) clearFirstResponder {
-    if (id responder = [window_ firstResponder])
-        [responder resignFirstResponder];
-}
-
 - (RVPage *) pageForPackage:(NSString *)name {
     if (Package *package = [database_ packageWithName:name]) {
         PackageView *view([self packageView]);
         [view setPackage:package];
         return view;
     } else {
-        UIActionSheet *sheet = [[[UIActionSheet alloc]
-            initWithTitle:CYLocalize("CANNOT_LOCATE_PACKAGE")
-            buttons:[NSArray arrayWithObjects:CYLocalize("CLOSE"), nil]
-            defaultButtonIndex:0
-            delegate:self
-            context:@"missing"
-        ] autorelease];
-
-        [sheet setBodyText:[NSString stringWithFormat:CYLocalize("PACKAGE_CANNOT_BE_FOUND"), name]];
-
-        [sheet popupAlertAnimated:YES];
-        return nil;
+        NSURL *url([NSURL fileURLWithPath:[[NSBundle mainBundle] pathForResource:@"unknown" ofType:@"html"]]);
+        url = [NSURL URLWithString:[[url absoluteString] stringByAppendingString:[NSString stringWithFormat:@"?%@", name]]];
+        return [self _pageForURL:url withClass:[CydiaBrowserView class]];
     }
 }
 
 - (RVPage *) pageForURL:(NSURL *)url hasTag:(int *)tag {
     if (tag != NULL)
-        tag = 0;
+        *tag = -1;
+
+    NSString *href([url absoluteString]);
+    if ([href hasPrefix:@"apptapp://package/"])
+        return [self pageForPackage:[href substringFromIndex:18]];
 
     NSString *scheme([[url scheme] lowercaseString]);
     if (![scheme isEqualToString:@"cydia"])
@@ -7713,13 +8225,13 @@ bool DepSubstrate(const pkgCache::VerIterator &iterator) {
     if ([path isEqualToString:@"/add-source"])
         return [[[AddSourceView alloc] initWithBook:book_ database:database_] autorelease];
     else if ([path isEqualToString:@"/storage"])
-        return [self _pageForURL:[NSURL fileURLWithPath:[[NSBundle mainBundle] pathForResource:@"storage" ofType:@"html"]] withClass:[BrowserView class]];
+        return [self _pageForURL:[NSURL fileURLWithPath:[[NSBundle mainBundle] pathForResource:@"storage" ofType:@"html"]] withClass:[CydiaBrowserView class]];
     else if ([path isEqualToString:@"/sources"])
         return [[[SourceTable alloc] initWithBook:book_ database:database_] autorelease];
     else if ([path isEqualToString:@"/packages"])
         return [[[InstalledView alloc] initWithBook:book_ database:database_] autorelease];
     else if ([path hasPrefix:@"/url/"])
-        return [self _pageForURL:[NSURL URLWithString:[path substringFromIndex:5]] withClass:[BrowserView class]];
+        return [self _pageForURL:[NSURL URLWithString:[path substringFromIndex:5]] withClass:[CydiaBrowserView class]];
     else if ([path hasPrefix:@"/launch/"])
         [self launchApplicationWithIdentifier:[path substringFromIndex:8] suspended:NO];
     else if ([path hasPrefix:@"/package-settings/"])
@@ -7746,39 +8258,47 @@ bool DepSubstrate(const pkgCache::VerIterator &iterator) {
     int tag;
     if (RVPage *page = [self pageForURL:url hasTag:&tag]) {
         [self setPage:page];
-        [buttonbar_ showSelectionForButton:tag];
         tag_ = tag;
+        [toolbar_ setSelectedItem:(tag_ == -1 ? nil : [items_ objectAtIndex:tag_])];
     }
 }
 
 - (void) applicationDidFinishLaunching:(id)unused {
-    _trace();
+    [BrowserView _initialize];
+
+    [NSURLProtocol registerClass:[CydiaURLProtocol class]];
+
     Font12_ = [[UIFont systemFontOfSize:12] retain];
     Font12Bold_ = [[UIFont boldSystemFontOfSize:12] retain];
     Font14_ = [[UIFont systemFontOfSize:14] retain];
     Font18Bold_ = [[UIFont boldSystemFontOfSize:18] retain];
     Font22Bold_ = [[UIFont boldSystemFontOfSize:22] retain];
 
-    tag_ = 1;
+    tag_ = 0;
 
     essential_ = [[NSMutableArray alloc] initWithCapacity:4];
     broken_ = [[NSMutableArray alloc] initWithCapacity:4];
 
-    [NSURLProtocol registerClass:[CydiaURLProtocol class]];
-
-    CGRect screenrect = [UIHardware fullScreenApplicationContentRect];
-    window_ = [[UIWindow alloc] initWithContentRect:screenrect];
+    UIScreen *screen([UIScreen mainScreen]);
 
+    window_ = [[UIWindow alloc] initWithFrame:[screen bounds]];
     [window_ orderFront:self];
     [window_ makeKey:self];
     [window_ setHidden:NO];
 
+    root_ = [[CydiaViewController alloc] init];
+    [window_ addSubview:[root_ view]];
+
     database_ = [Database sharedInstance];
-    progress_ = [[ProgressView alloc] initWithFrame:[window_ bounds] database:database_ delegate:self];
+
+    progress_ = [[ProgressView alloc] initWithFrame:[[root_ view] bounds] database:database_ delegate:self];
+    [progress_ setAutoresizingMask:UIViewAutoresizingFlexibleBoth];
+    [[root_ view] addSubview:progress_];
+
     [database_ setDelegate:progress_];
-    [window_ setContentView:progress_];
 
     underlay_ = [[UIView alloc] initWithFrame:[progress_ bounds]];
+    [underlay_ setAutoresizingMask:UIViewAutoresizingFlexibleBoth];
     [progress_ setContentView:underlay_];
 
     [progress_ resetView];
@@ -7787,34 +8307,119 @@ bool DepSubstrate(const pkgCache::VerIterator &iterator) {
         readlink("/Applications", NULL, 0) == -1 && errno == EINVAL ||
         readlink("/Library/Ringtones", NULL, 0) == -1 && errno == EINVAL ||
         readlink("/Library/Wallpaper", NULL, 0) == -1 && errno == EINVAL ||
+        //readlink("/usr/bin", NULL, 0) == -1 && errno == EINVAL ||
         readlink("/usr/include", NULL, 0) == -1 && errno == EINVAL ||
+        readlink("/usr/lib/pam", NULL, 0) == -1 && errno == EINVAL ||
         readlink("/usr/libexec", NULL, 0) == -1 && errno == EINVAL ||
-        readlink("/usr/share", NULL, 0) == -1 && errno == EINVAL /*||
-        readlink("/var/lib", NULL, 0) == -1 && errno == EINVAL*/
+        readlink("/usr/share", NULL, 0) == -1 && errno == EINVAL ||
+        //readlink("/var/lib", NULL, 0) == -1 && errno == EINVAL ||
+        false
     ) {
         [self setIdleTimerDisabled:YES];
 
-        hud_ = [[self addProgressHUD] retain];
+        hud_ = [self addProgressHUD];
         [hud_ setText:@"Reorganizing\n\nWill Automatically\nClose When Done"];
-
         [self setStatusBarShowsProgress:YES];
 
-        [NSThread
-            detachNewThreadSelector:@selector(reorganize)
-            toTarget:self
-            withObject:nil
-        ];
-    } else
-        [self finish];
+        [self yieldToSelector:@selector(system:) withObject:@"/usr/libexec/cydia/free.sh"];
+
+        [self setStatusBarShowsProgress:NO];
+        [self removeProgressHUD:hud_];
+        hud_ = nil;
+
+        if (ExecFork() == 0) {
+            execlp("launchctl", "launchctl", "stop", "com.apple.SpringBoard", NULL);
+            perror("launchctl stop");
+        }
+
+        return;
+    }
+
+    if (Role_ == nil)
+        [self askForSettings];
+
+    _trace();
+    overlay_ = [[UIView alloc] initWithFrame:[underlay_ bounds]];
+    [overlay_ setAutoresizingMask:UIViewAutoresizingFlexibleBoth];
+
+    CGRect screenrect = [UIHardware fullScreenApplicationContentRect];
+
+    book_ = [[CYBook alloc] initWithFrame:CGRectMake(
+        0, 0, screenrect.size.width, screenrect.size.height - 48
+    ) database:database_];
+
+    [book_ setAutoresizingMask:UIViewAutoresizingFlexibleBoth];
+    [overlay_ addSubview:book_];
+
+    [book_ setDelegate:self];
+
+    items_ = [[NSArray arrayWithObjects:
+        [[[UITabBarItem alloc] initWithTitle:@"Cydia" image:[UIImage applicationImageNamed:@"home.png"] tag:0] autorelease],
+        [[[UITabBarItem alloc] initWithTitle:UCLocalize("SECTIONS") image:[UIImage applicationImageNamed:@"install.png"] tag:1] autorelease],
+        [[[UITabBarItem alloc] initWithTitle:UCLocalize("CHANGES") image:[UIImage applicationImageNamed:@"changes.png"] tag:2] autorelease],
+        [[[UITabBarItem alloc] initWithTitle:UCLocalize("MANAGE") image:[UIImage applicationImageNamed:@"manage.png"] tag:3] autorelease],
+        [[[UITabBarItem alloc] initWithTitle:UCLocalize("SEARCH") image:[UIImage applicationImageNamed:@"search.png"] tag:4] autorelease],
+    nil] retain];
+
+    toolbar_ = [[UITabBar alloc]
+        initWithFrame:CGRectMake(
+            0, screenrect.size.height - ButtonBarHeight_,
+            screenrect.size.width, ButtonBarHeight_
+        )
+    ];
+
+    [toolbar_ setItems:items_];
+
+    [toolbar_ setAutoresizingMask:(UIViewAutoresizingFlexibleWidth | UIViewAutoresizingFlexibleTopMargin)];
+    [overlay_ addSubview:toolbar_];
+
+    [toolbar_ setDelegate:self];
+
+    /*int buttons[5] = {1, 2, 3, 4, 5};
+    [toolbar_ registerButtonGroup:0 withButtons:buttons withCount:5];
+    [toolbar_ showButtonGroup:0 withDuration:0];
+
+    for (int i = 0; i != 5; ++i) {
+        UIView *button([toolbar_ viewWithTag:(i + 1)]);
+
+        [button setFrame:CGRectMake(
+            i * (screenrect.size.width / 5) + (screenrect.size.width / 5 - ButtonBarWidth_) / 2, 1,
+            ButtonBarWidth_, ButtonBarHeight_
+        )];
+
+        [button setAutoresizingMask:UIViewAutoresizingFlexibleLeftMargin];
+    }*/
+
+    [toolbar_ setSelectedItem:[items_ objectAtIndex:0]];
+
+    [UIKeyboard initImplementationNow];
+    /*CGSize keysize = [UIKeyboard defaultSize];
+    CGRect keyrect = {{0, [overlay_ bounds].size.height}, keysize};
+    keyboard_ = [[UIKeyboard alloc] initWithFrame:keyrect];
+    [overlay_ addSubview:keyboard_];*/
+
+    [underlay_ addSubview:overlay_];
+
+    [self reloadData];
+
+#if RecyclePackageViews
+    details_ = [[NSMutableArray alloc] initWithCapacity:4];
+    [details_ addObject:[self _packageView]];
+    [details_ addObject:[self _packageView]];
+#endif
+
+    PrintTimes();
+
+    _setHomePage(self);
 }
 
 - (void) showKeyboard:(BOOL)show {
-    CGSize keysize = [UIKeyboard defaultSize];
+    CGSize keysize([UIKeyboard defaultSize]);
     CGRect keydown = {{0, [overlay_ bounds].size.height}, keysize};
-    CGRect keyup = keydown;
+    CGRect keyup(keydown);
     keyup.origin.y -= keysize.height;
 
-    UIFrameAnimation *animation = [[[UIFrameAnimation alloc] initWithTarget:keyboard_] autorelease];
+    UIFrameAnimation *animation([[[UIFrameAnimation alloc] initWithTarget:keyboard_] autorelease]);
     [animation setSignificantRectFields:2];
 
     if (show) {
@@ -7835,50 +8440,12 @@ bool DepSubstrate(const pkgCache::VerIterator &iterator) {
 }
 
 - (void) slideUp:(UIActionSheet *)alert {
-    if (Advanced_)
-        [alert presentSheetFromButtonBar:buttonbar_];
-    else
-        [alert presentSheetInView:overlay_];
+    [alert setAutoresizingMask:(UIViewAutoresizingFlexibleWidth | UIViewAutoresizingFlexibleHeight)];
+    [alert presentSheetInView:overlay_];
 }
 
 @end
 
-void AddPreferences(NSString *plist) { _pooled
-    NSMutableDictionary *settings = [[[NSMutableDictionary alloc] initWithContentsOfFile:plist] autorelease];
-    _assert(settings != NULL);
-    NSMutableArray *items = [settings objectForKey:@"items"];
-
-    bool cydia(false);
-
-    for (NSMutableDictionary *item in items) {
-        NSString *label = [item objectForKey:@"label"];
-        if (label != nil && [label isEqualToString:@"Cydia"]) {
-            cydia = true;
-            break;
-        }
-    }
-
-    if (!cydia) {
-        for (size_t i(0); i != [items count]; ++i) {
-            NSDictionary *item([items objectAtIndex:i]);
-            NSString *label = [item objectForKey:@"label"];
-            if (label != nil && [label isEqualToString:@"General"]) {
-                [items insertObject:[NSDictionary dictionaryWithObjectsAndKeys:
-                    @"CydiaSettings", @"bundle",
-                    @"PSLinkCell", @"cell",
-                    [NSNumber numberWithBool:YES], @"hasIcon",
-                    [NSNumber numberWithBool:YES], @"isController",
-                    @"Cydia", @"label",
-                nil] atIndex:(i + 1)];
-
-                break;
-            }
-        }
-
-        _assert([settings writeToFile:plist atomically:YES] == YES);
-    }
-}
-
 /*IMP alloc_;
 id Alloc_(id self, SEL selector) {
     id object = alloc_(self, selector);
@@ -7895,18 +8462,25 @@ id Dealloc_(id self, SEL selector) {
 
 Class $WebDefaultUIKitDelegate;
 
-void (*_UIWebDocumentView$_setUIKitDelegate$)(UIWebDocumentView *, SEL, id);
-
-void $UIWebDocumentView$_setUIKitDelegate$(UIWebDocumentView *self, SEL sel, id delegate) {
+MSHook(void, UIWebDocumentView$_setUIKitDelegate$, UIWebDocumentView *self, SEL _cmd, id delegate) {
     if (delegate == nil && $WebDefaultUIKitDelegate != nil)
         delegate = [$WebDefaultUIKitDelegate sharedUIKitDelegate];
-    return _UIWebDocumentView$_setUIKitDelegate$(self, sel, delegate);
+    return _UIWebDocumentView$_setUIKitDelegate$(self, _cmd, delegate);
 }
 
 int main(int argc, char *argv[]) { _pooled
     _trace();
 
+    if (Class $UIDevice = objc_getClass("UIDevice")) {
+        UIDevice *device([$UIDevice currentDevice]);
+        IsWildcat_ = [device respondsToSelector:@selector(isWildcat)] && [device isWildcat];
+    } else
+        IsWildcat_ = false;
+
+    PackageName = reinterpret_cast<CYString &(*)(Package *, SEL)>(method_getImplementation(class_getInstanceMethod([Package class], @selector(cyname))));
+
     /* Library Hacks {{{ */
+    class_addMethod(objc_getClass("WebScriptObject"), @selector(countByEnumeratingWithState:objects:count:), (IMP) &WebScriptObject$countByEnumeratingWithState$objects$count$, "I20@0:4^{NSFastEnumerationState}8^@12I16");
     class_addMethod(objc_getClass("DOMNodeList"), @selector(countByEnumeratingWithState:objects:count:), (IMP) &DOMNodeList$countByEnumeratingWithState$objects$count$, "I20@0:4^{NSFastEnumerationState}8^@12I16");
 
     $WebDefaultUIKitDelegate = objc_getClass("WebDefaultUIKitDelegate");
@@ -7920,19 +8494,22 @@ int main(int argc, char *argv[]) { _pooled
     Locale_ = CFLocaleCopyCurrent();
     Languages_ = [NSLocale preferredLanguages];
     //CFStringRef locale(CFLocaleGetIdentifier(Locale_));
-    NSLog(@"%@", [Languages_ description]);
+    //NSLog(@"%@", [Languages_ description]);
+
     const char *lang;
     if (Languages_ == nil || [Languages_ count] == 0)
+        // XXX: consider just setting to C and then falling through?
         lang = NULL;
-    else
+    else {
         lang = [[Languages_ objectAtIndex:0] UTF8String];
-    setenv("LANG", lang, true);
+        setenv("LANG", lang, true);
+    }
+
     //std::setlocale(LC_ALL, lang);
     NSLog(@"Setting Language: %s", lang);
     /* }}} */
 
-    // XXX: apr_app_initialize?
-    apr_initialize();
+    apr_app_initialize(&argc, const_cast<const char * const **>(&argv), NULL);
 
     /* Parse Arguments {{{ */
     bool substrate(false);
@@ -7951,24 +8528,16 @@ int main(int argc, char *argv[]) { _pooled
             }
 
         for (int argi(1); argi != arge; ++argi)
-            if (strcmp(args[argi], "--bootstrap") == 0)
-                bootstrap_ = true;
-            else if (strcmp(args[argi], "--substrate") == 0)
+            if (strcmp(args[argi], "--substrate") == 0)
                 substrate = true;
             else
                 fprintf(stderr, "unknown argument: %s\n", args[argi]);
     }
     /* }}} */
 
-    {
-        NSString *plist = [Home_ stringByAppendingString:@"/Library/Preferences/com.apple.preferences.sounds.plist"];
-        if (NSDictionary *sounds = [NSDictionary dictionaryWithContentsOfFile:plist])
-            if (NSNumber *keyboard = [sounds objectForKey:@"keyboard"])
-                Sounds_Keyboard_ = [keyboard boolValue];
-    }
-
     App_ = [[NSBundle mainBundle] bundlePath];
     Home_ = NSHomeDirectory();
+    Advanced_ = YES;
 
     setuid(0);
     setgid(0);
@@ -7981,6 +8550,7 @@ int main(int argc, char *argv[]) { _pooled
     dealloc_ = dealloc->method_imp;
     dealloc->method_imp = (IMP) &Dealloc_;*/
 
+    /* System Information {{{ */
     size_t size;
 
     int maxproc;
@@ -7993,6 +8563,13 @@ int main(int argc, char *argv[]) { _pooled
             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)
@@ -8000,6 +8577,29 @@ int main(int argc, char *argv[]) { _pooled
     else
         Machine_ = machine;
 
+    if (CFMutableDictionaryRef dict = IOServiceMatching("IOPlatformExpertDevice")) {
+        if (io_service_t service = IOServiceGetMatchingService(kIOMasterPortDefault, dict)) {
+            if (CFTypeRef serial = IORegistryEntryCreateCFProperty(service, CFSTR(kIOPlatformSerialNumberKey), kCFAllocatorDefault, 0)) {
+                SerialNumber_ = [NSString stringWithString:(NSString *)serial];
+                CFRelease(serial);
+            }
+
+            if (CFTypeRef ecid = IORegistryEntrySearchCFProperty(service, kIODeviceTreePlane, CFSTR("unique-chip-id"), kCFAllocatorDefault, kIORegistryIterateRecursively)) {
+                NSData *data((NSData *) ecid);
+                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[length - i - 1]);
+                ChipID_ = [NSString stringWithUTF8String:string];
+                CFRelease(ecid);
+            }
+
+            IOObjectRelease(service);
+        }
+    }
+
     UniqueID_ = [[UIDevice currentDevice] uniqueIdentifier];
 
     if (NSDictionary *system = [NSDictionary dictionaryWithContentsOfFile:@"/System/Library/CoreServices/SystemVersion.plist"])
@@ -8008,10 +8608,7 @@ int main(int argc, char *argv[]) { _pooled
         Product_ = [info objectForKey:@"SafariProductVersion"];
         Safari_ = [info objectForKey:@"CFBundleVersion"];
     }
-
-    /*AddPreferences(@"/Applications/Preferences.app/Settings-iPhone.plist");
-    AddPreferences(@"/Applications/Preferences.app/Settings-iPod.plist");*/
-
+    /* }}} */
     /* Load Database {{{ */
     _trace();
     Metadata_ = [[[NSMutableDictionary alloc] initWithContentsOfFile:@"/var/lib/cydia/metadata.plist"] autorelease];
@@ -8027,6 +8624,8 @@ int main(int argc, char *argv[]) { _pooled
         Packages_ = [Metadata_ objectForKey:@"Packages"];
         Sections_ = [Metadata_ objectForKey:@"Sections"];
         Sources_ = [Metadata_ objectForKey:@"Sources"];
+
+        Token_ = [Metadata_ objectForKey:@"Token"];
     }
 
     if (Settings_ != nil)
@@ -8052,12 +8651,22 @@ int main(int argc, char *argv[]) { _pooled
     Documents_ = [[[NSMutableArray alloc] initWithCapacity:4] autorelease];
 #endif
 
+    Finishes_ = [NSArray arrayWithObjects:@"return", @"reopen", @"restart", @"reload", @"reboot", nil];
+
+    if (substrate && access("/Library/MobileSubstrate/DynamicLibraries/SimulatedKeyEvents.dylib", F_OK) == 0)
+        dlopen("/Library/MobileSubstrate/DynamicLibraries/SimulatedKeyEvents.dylib", RTLD_LAZY | RTLD_GLOBAL);
     if (substrate && access("/Applications/WinterBoard.app/WinterBoard.dylib", F_OK) == 0)
         dlopen("/Applications/WinterBoard.app/WinterBoard.dylib", RTLD_LAZY | RTLD_GLOBAL);
     /*if (substrate && access("/Library/MobileSubstrate/MobileSubstrate.dylib", F_OK) == 0)
         dlopen("/Library/MobileSubstrate/MobileSubstrate.dylib", RTLD_LAZY | RTLD_GLOBAL);*/
 
-    if (access("/User", F_OK) != 0) {
+    int version([[NSString stringWithContentsOfFile:@"/var/lib/cydia/firmware.ver"] intValue]);
+
+    if (access("/tmp/.cydia.fw", F_OK) == 0) {
+        unlink("/tmp/.cydia.fw");
+        goto firmware;
+    } else if (access("/User", F_OK) != 0 || version < 2) {
+      firmware:
         _trace();
         system("/usr/libexec/cydia/firmware.sh");
         _trace();
@@ -8077,12 +8686,15 @@ int main(int argc, char *argv[]) { _pooled
             _assert(errno == ENOENT);
     }
 
+    /* APT Initialization {{{ */
     _assert(pkgInitConfig(*_config));
     _assert(pkgInitSystem(*_config, _system));
 
     if (lang != NULL)
         _config->Set("APT::Acquire::Translation", lang);
-
+    _config->Set("Acquire::http::Timeout", 15);
+    _config->Set("Acquire::http::MaxParallel", 3);
+    /* }}} */
     /* Color Choices {{{ */
     space_ = CGColorSpaceCreateDeviceRGB();
 
@@ -8095,28 +8707,23 @@ int main(int argc, char *argv[]) { _pooled
     Green_.Set(space_, 0.0, 0.5, 0.0, 1.0);
     Purple_.Set(space_, 0.0, 0.0, 0.7, 1.0);
     Purplish_.Set(space_, 0.4, 0.4, 0.8, 1.0);
-    /*Purple_.Set(space_, 1.0, 0.3, 0.0, 1.0);
-    Purplish_.Set(space_, 1.0, 0.6, 0.4, 1.0); ORANGE */
-    /*Purple_.Set(space_, 1.0, 0.5, 0.0, 1.0);
-    Purplish_.Set(space_, 1.0, 0.7, 0.2, 1.0); ORANGISH */
-    /*Purple_.Set(space_, 0.5, 0.0, 0.7, 1.0);
-    Purplish_.Set(space_, 0.7, 0.4, 0.8, 1.0); PURPLE */
-
-//.93
+
     InstallingColor_ = [UIColor colorWithRed:0.88f green:1.00f blue:0.88f alpha:1.00f];
     RemovingColor_ = [UIColor colorWithRed:1.00f green:0.88f blue:0.88f alpha:1.00f];
     /* }}}*/
-
-    Finishes_ = [NSArray arrayWithObjects:@"return", @"reopen", @"restart", @"reload", @"reboot", nil];
-
     /* UIKit Configuration {{{ */
     void (*$GSFontSetUseLegacyFontMetrics)(BOOL)(reinterpret_cast<void (*)(BOOL)>(dlsym(RTLD_DEFAULT, "GSFontSetUseLegacyFontMetrics")));
     if ($GSFontSetUseLegacyFontMetrics != NULL)
         $GSFontSetUseLegacyFontMetrics(YES);
 
-    UIKeyboardDisableAutomaticAppearance();
+    // XXX: I have a feeling this was important
+    //UIKeyboardDisableAutomaticAppearance();
     /* }}} */
 
+    Colon_ = UCLocalize("COLON_DELIMITED");
+    Error_ = UCLocalize("ERROR");
+    Warning_ = UCLocalize("WARNING");
+
     _trace();
     int value = UIApplicationMain(argc, argv, @"Cydia", @"Cydia");