]> git.saurik.com Git - cydia.git/blobdiff - Cydia.mm
Commit (chpwn): packages-cell-landscape.patch
[cydia.git] / Cydia.mm
index e10a7d50c8fe52d3ff7c8227e9c0e909decd0e00..53ea2eac7c71617722a92b5e8d9d7aea8a5fd653 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>
 
@@ -58,7 +60,6 @@
 #include <CoreFoundation/CFPriv.h>
 #include <CoreFoundation/CFUniChar.h>
 
-#import <QuartzCore/CALayer.h>
 #import <UIKit/UIKit.h>
 
 #include <WebCore/WebCoreThread.h>
@@ -71,6 +72,8 @@
 
 #include <ext/stdio_filebuf.h>
 
+#undef ABS
+
 #include <apt-pkg/acquire.h>
 #include <apt-pkg/acquire-item.h>
 #include <apt-pkg/algorithms.h>
@@ -113,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); \
@@ -197,54 +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 operator Type_ *() const {
-        return value_;
-    }
-
-    _finline This_ &operator =(Type_ *value) {
-        if (value_ != value) {
-            Type_ *old(value_);
-            value_ = value;
-            Retain_();
-            if (old != nil)
-                [old release];
-        } 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);
 }
@@ -253,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;
@@ -317,29 +279,44 @@ 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 LaxCompareOptions_ = NSNumericSearch | NSDiacriticInsensitiveSearch | NSWidthInsensitiveSearch | NSCaseInsensitiveSearch;
-static const CFStringCompareFlags LaxCompareFlags_ = kCFCompareCaseInsensitive | kCFCompareNonliteral | kCFCompareLocalized | kCFCompareNumerically | kCFCompareWidthInsensitive | kCFCompareForcedOrdering;
+@interface CYActionSheet : UIAlertView {
+    unsigned button_;
+}
 
-/* iPhoneOS 2.0 Compatibility {{{ */
-#ifdef __OBJC2__
-@interface UITextView (iPhoneOS)
-- (void) setTextSize:(float)size;
+- (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 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) setTextSize:(float)size {
-    [self setFont:[[self font] fontWithSize:size]];
+- (int) yieldToPopupAlertAnimated:(BOOL)animated {
+    button_ = 0;
+    [self popupAlertAnimated:animated];
+    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)
@@ -361,8 +338,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
@@ -390,10 +366,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];
 }
@@ -408,12 +388,13 @@ extern NSString * const kCAFilterNearest;
 #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 !TraceLogging
@@ -647,14 +628,18 @@ void CFArrayInsertionSortValues(CFMutableArrayRef array, CFRange range, CFCompar
 @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);
@@ -671,9 +656,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;
@@ -731,11 +716,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/"
     ];
 }
 
@@ -750,13 +732,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_;
@@ -764,8 +742,10 @@ class CYString {
     CFStringRef cache_;
 
     _finline void clear_() {
-        if (cache_ != nil)
+        if (cache_ != NULL) {
             CFRelease(cache_);
+            cache_ = NULL;
+        }
     }
 
   public:
@@ -789,7 +769,7 @@ class CYString {
     _finline CYString() :
         data_(0),
         size_(0),
-        cache_(nil)
+        cache_(NULL)
     {
     }
 
@@ -838,6 +818,8 @@ class CYString {
             if (size_ == 0)
                 return nil;
             cache_ = CFStringCreateWithBytesNoCopy(kCFAllocatorDefault, reinterpret_cast<uint8_t *>(data_), size_, kCFStringEncodingUTF8, NO, kCFAllocatorNull);
+            if (cache_ == NULL)
+                cache_ = CFStringCreateWithBytesNoCopy(kCFAllocatorDefault, reinterpret_cast<uint8_t *>(data_), size_, kCFStringEncodingISOLatin1, NO, kCFAllocatorNull);
         } return cache_;
     }
 
@@ -845,7 +827,8 @@ class CYString {
         return (NSString *) static_cast<CFStringRef>(*this);
     }
 };
-
+/* }}} */
+/* C++ NSString Algorithm Adapters {{{ */
 extern "C" {
     CF_EXPORT CFHashCode CFStringHashNSString(CFStringRef str);
 }
@@ -875,6 +858,7 @@ struct NSStringMapEqual :
         //[lhs isEqualToString:rhs];
     }
 };
+/* }}} */
 
 /* Perl-Compatible RegEx {{{ */
 class Pcre {
@@ -1036,15 +1020,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_;
@@ -1064,10 +1049,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_;
@@ -1077,17 +1060,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_;
@@ -1099,24 +1085,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;
@@ -1143,10 +1118,19 @@ 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);
 }
 
@@ -1156,7 +1140,7 @@ NSString *LocalizeSection(NSString *section) {
         NSString *parent(title_r[1]);
         NSString *child(title_r[2]);
 
-        return [NSString stringWithFormat:CYLocalize("PARENTHETICAL"),
+        return [NSString stringWithFormat:UCLocalize("PARENTHETICAL"),
             LocalizeSection(parent),
             LocalizeSection(child)
         ];
@@ -1185,6 +1169,20 @@ 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"]);
@@ -1198,19 +1196,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;
@@ -1229,6 +1216,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;
@@ -1237,10 +1225,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
 /* }}} */
@@ -1262,6 +1247,10 @@ class Status :
         delegate_ = delegate;
     }
 
+    NSObject<ProgressDelegate> *getDelegate() const {
+        return delegate_;
+    }
+
     virtual bool MediaChange(std::string media, std::string drive) {
         return false;
     }
@@ -1271,7 +1260,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) {
@@ -1292,7 +1281,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,
@@ -1327,16 +1316,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)
     {
     }
 
@@ -1344,7 +1340,12 @@ class Progress :
         delegate_ = delegate;
     }
 
+    id getDelegate() const {
+        return delegate_;
+    }
+
     virtual void Done() {
+        //NSLog(@"DONE");
         //[delegate_ setProgressPercent:1];
     }
 };
@@ -1402,20 +1403,55 @@ typedef std::map< unsigned long, _H<Source> > SourceMap;
 - (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 {
+    CYString depiction_;
     CYString description_;
     CYString label_;
     CYString origin_;
@@ -1427,6 +1463,7 @@ typedef std::map< unsigned long, _H<Source> > SourceMap;
     CYString version_;
 
     NSString *host_;
+    NSString *authority_;
 
     CYString defaultIcon_;
 
@@ -1438,6 +1475,7 @@ typedef std::map< unsigned long, _H<Source> > SourceMap;
 
 - (NSComparisonResult) compareByNameAndType:(Source *)source;
 
+- (NSString *) depictionForPackage:(NSString *)package;
 - (NSString *) supportForPackage:(NSString *)package;
 
 - (NSDictionary *) record;
@@ -1469,6 +1507,7 @@ typedef std::map< unsigned long, _H<Source> > SourceMap;
     description_.clear();
     label_.clear();
     origin_.clear();
+    depiction_.clear();
     support_.clear();
     version_.clear();
     defaultIcon_.clear();
@@ -1482,6 +1521,11 @@ typedef std::map< unsigned long, _H<Source> > SourceMap;
         [host_ release];
         host_ = nil;
     }
+
+    if (authority_ != nil) {
+        [authority_ release];
+        authority_ = nil;
+    }
 }
 
 - (void) dealloc {
@@ -1512,30 +1556,35 @@ typedef std::map< unsigned long, _H<Source> > SourceMap;
 
     debReleaseIndex *dindex(dynamic_cast<debReleaseIndex *>(index));
     if (dindex != NULL) {
-        FileFd fd(dindex->MetaIndexFile("Release"), FileFd::ReadOnly);
-        pkgTagFile tags(&fd);
+        FileFd fd;
+        if (!fd.Open(dindex->MetaIndexFile("Release"), FileFd::ReadOnly))
+            _error->Discard();
+        else {
+            pkgTagFile tags(&fd);
 
-        pkgTagSection section;
-        tags.Step(section);
+            pkgTagSection section;
+            tags.Step(section);
 
-        struct {
-            const char *name_;
-            CYString *value_;
-        } names[] = {
-            {"default-icon", &defaultIcon_},
-            {"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;
+            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);
+                if (section.Find(names[i].name_, start, end)) {
+                    CYString &value(*names[i].value_);
+                    value.set(pool, start, end - start);
+                }
             }
         }
     }
@@ -1544,7 +1593,19 @@ typedef std::map< unsigned long, _H<Source> > SourceMap;
     if (record_ != nil)
         record_ = [record_ retain];
 
-    host_ = [[[[NSURL URLWithString:uri_] host] lowercaseString] 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 inPool:(apr_pool_t *)pool {
@@ -1576,6 +1637,10 @@ typedef std::map< unsigned long, _H<Source> > SourceMap;
     return [lhs compare:rhs options:LaxCompareOptions_];
 }
 
+- (NSString *) depictionForPackage:(NSString *)package {
+    return depiction_.empty() ? nil : [depiction_ stringByReplacingOccurrencesOfString:@"*" withString:package];
+}
+
 - (NSString *) supportForPackage:(NSString *)package {
     return support_.empty() ? nil : [support_ stringByReplacingOccurrencesOfString:@"*" withString:package];
 }
@@ -1609,7 +1674,7 @@ typedef std::map< unsigned long, _H<Source> > SourceMap;
 }
 
 - (NSString *) name {
-    return origin_.empty() ? host_ : origin_;
+    return origin_.empty() ? authority_ : origin_;
 }
 
 - (NSString *) description {
@@ -1617,7 +1682,7 @@ typedef std::map< unsigned long, _H<Source> > SourceMap;
 }
 
 - (NSString *) label {
-    return label_.empty() ? host_ : label_;
+    return label_.empty() ? authority_ : label_;
 }
 
 - (NSString *) origin {
@@ -1686,10 +1751,12 @@ typedef std::map< unsigned long, _H<Source> > SourceMap;
     CYString section_;
     NSString *section$_;
     bool essential_;
+    bool required_;
     bool visible_;
+    bool obsolete_;
 
     NSString *latest_;
-    NSString *installed_;
+    CYString installed_;
 
     CYString id_;
     CYString name_;
@@ -1704,6 +1771,7 @@ typedef std::map< unsigned long, _H<Source> > SourceMap;
     CYString author_;
     Address *author$_;
 
+    CYString bugs_;
     CYString support_;
     NSMutableArray *tags_;
     NSString *role_;
@@ -1743,6 +1811,7 @@ typedef std::map< unsigned long, _H<Source> > SourceMap;
 
 - (NSString *) latest;
 - (NSString *) installed;
+- (BOOL) uninstalled;
 
 - (BOOL) valid;
 - (BOOL) upgradableAndEssential:(BOOL)essential;
@@ -1757,6 +1826,8 @@ typedef std::map< unsigned long, _H<Source> > SourceMap;
 - (BOOL) hasMode;
 - (NSString *) mode;
 
+- (void) setVisible;
+
 - (NSString *) id;
 - (NSString *) name;
 - (UIImage *) icon;
@@ -1792,8 +1863,9 @@ typedef std::map< unsigned long, _H<Source> > SourceMap;
 - (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
@@ -1890,6 +1962,11 @@ CFComparisonResult PackageNameCompare(Package *lhs, Package *rhs, void *arg) {
         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));
@@ -1934,8 +2011,6 @@ struct PackageNameOrdering :
 
     if (latest_ != nil)
         [latest_ release];
-    if (installed_ != nil)
-        [installed_ release];
 
     if (sponsor$_ != nil)
         [sponsor$_ release];
@@ -2002,6 +2077,7 @@ struct PackageNameOrdering :
                 {"depiction", &depiction_},
                 {"homepage", &homepage_},
                 {"website", &website},
+                {"bugs", &bugs_},
                 {"support", &support_},
                 {"sponsor", &sponsor_},
                 {"author", &author_},
@@ -2032,7 +2108,7 @@ struct PackageNameOrdering :
         _end
 
         _profile(Package$parse$Retain)
-            if (!homepage_.empty())
+            if (homepage_.empty())
                 homepage_ = website;
             if (homepage_ == depiction_)
                 homepage_.clear();
@@ -2040,6 +2116,10 @@ struct PackageNameOrdering :
     _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)
@@ -2059,7 +2139,7 @@ struct PackageNameOrdering :
         _profile(Package$initWithVersion$Versions)
             current = iterator_.CurrentVer();
             if (!current.end())
-                installed_ = (NSString *) StripVersion(current.VerStr());
+                installed_.set(pool_, StripVersion_(current.VerStr()));
 
             if (!version_.end())
                 file_ = version_.FileList();
@@ -2083,6 +2163,8 @@ struct PackageNameOrdering :
             _end
         }
 
+        required_ = true;
+
         _profile(Package$initWithVersion$Tags)
             pkgCache::TagIterator tag(iterator_.TagList());
             if (!tag.end()) {
@@ -2090,8 +2172,12 @@ struct PackageNameOrdering :
                 do {
                     const char *name(tag.Name());
                     [tags_ addObject:(NSString *)CFCString(name)];
-                    if (role_ == nil && strncmp(name, "role::", 6) == 0)
+                    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());
             }
@@ -2150,12 +2236,14 @@ struct PackageNameOrdering :
             section_.set(pool_, iterator_.Section());
         _end
 
+        obsolete_ = [self hasTag:@"cydia::obsolete"];
         essential_ = ((iterator_->Flags & pkgCache::Flag::Essential) == 0 ? NO : YES) || [self hasTag:@"cydia::essential"];
-        visible_ = [self hasSupportingRole] && [self unfiltered];
+        [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)
@@ -2171,7 +2259,7 @@ struct PackageNameOrdering :
         inPool:pool
         database:database
     ] autorelease];
-}
+} }
 
 - (pkgCache::PkgIterator) iterator {
     return iterator_;
@@ -2204,7 +2292,7 @@ struct PackageNameOrdering :
 }
 
 - (NSString *) longSection {
-    return LocalizeSection(section_);
+    return LocalizeSection([self section]);
 }
 
 - (NSString *) shortSection {
@@ -2302,6 +2390,10 @@ struct PackageNameOrdering :
     return installed_;
 }
 
+- (BOOL) uninstalled {
+    return installed_.empty();
+}
+
 - (BOOL) valid {
     return !version_.end();
 }
@@ -2326,7 +2418,7 @@ struct PackageNameOrdering :
 
 - (BOOL) unfiltered {
     NSString *section([self section]);
-    return section == nil || isSectionVisible(section);
+    return !obsolete_ && [self hasSupportingRole] && (section == nil || isSectionVisible(section));
 }
 
 - (BOOL) visible {
@@ -2379,11 +2471,9 @@ struct PackageNameOrdering :
                     return @"UPGRADE";
                 case 2:
                     return @"NEW_INSTALL";
-                default:
-                    _assert(false);
+                _nodefault
             }
-        default:
-            _assert(false);
+        _nodefault
     }
 }
 
@@ -2417,7 +2507,7 @@ struct PackageNameOrdering :
 }
 
 - (NSString *) depiction {
-    return depiction_;
+    return !depiction_.empty() ? depiction_ : [[self source] depictionForPackage:id_];
 }
 
 - (Address *) sponsor {
@@ -2437,7 +2527,7 @@ struct PackageNameOrdering :
 }
 
 - (NSString *) support {
-    return !support_.empty() ? support_ : [[self source] supportForPackage:id_];
+    return !bugs_.empty() ? bugs_ : [[self source] supportForPackage:id_];
 }
 
 - (NSArray *) files {
@@ -2466,7 +2556,7 @@ struct PackageNameOrdering :
 
     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 */
@@ -2478,6 +2568,7 @@ struct PackageNameOrdering :
 
     if (strcmp(name, "cydia") != 0) {
         bool cydia = false;
+        bool user = false;
         bool _private = false;
         bool stash = false;
 
@@ -2487,6 +2578,8 @@ struct PackageNameOrdering :
             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"])
@@ -2494,11 +2587,13 @@ struct PackageNameOrdering :
 
         /* 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;
@@ -2705,16 +2800,34 @@ struct PackageNameOrdering :
     _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]
@@ -2805,7 +2918,7 @@ struct PackageNameOrdering :
 /* 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;
@@ -2846,8 +2959,9 @@ struct PackageNameOrdering :
 @end
 /* }}} */
 
-static int Finish_;
-static NSArray *Finishes_;
+static NSString *Colon_;
+static NSString *Error_;
+static NSString *Warning_;
 
 /* Database Implementation {{{ */
 @implementation Database
@@ -2891,7 +3005,7 @@ static NSArray *Finishes_;
         }
     }
 
-    _assert(false);
+    _assume(false);
 }
 
 - (void) _readStatus:(NSNumber *)fd { _pooled
@@ -2904,7 +3018,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)) {
@@ -2922,7 +3036,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
                 ];
@@ -2930,11 +3044,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
@@ -2947,7 +3063,7 @@ static NSArray *Finishes_;
         [delegate_ addProgressOutput:[NSString stringWithUTF8String:line.c_str()]];
     }
 
-    _assert(false);
+    _assume(false);
 }
 
 - (FILE *) input {
@@ -2955,11 +3071,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) {
@@ -3083,8 +3200,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)
@@ -3114,7 +3233,40 @@ 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_;
     }
@@ -3152,12 +3304,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. ")
@@ -3167,8 +3319,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();
@@ -3184,15 +3340,28 @@ 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;
+
+        if (cache_->BrokenCount() != 0) {
+            [delegate_ _setProgressError:@"STILL_BROKEN_EX" withTitle:title];
+            return;
+        }
+
+        if ([self popErrorWithTitle:title forOperation:pkgMinimizeUpgrade(cache_)])
+            return;
     }
 
     _trace();
@@ -3253,20 +3422,25 @@ static NSArray *Finishes_;
 
         _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"));
@@ -3280,33 +3454,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());
+
+    NSString *title(UCLocalize("PREPARE_ARCHIVES"));
+
+    if ([self popErrorWithTitle:title])
+        return false;
 
     pkgSourceList list;
-    // XXX: explain this with an error message
-    _assert(list.ReadMainList());
+    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()]];
     }
@@ -3320,6 +3504,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;
@@ -3327,7 +3513,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]
@@ -3360,7 +3546,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()]];
     }
@@ -3369,41 +3556,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 {
@@ -3413,158 +3599,374 @@ static NSArray *Finishes_;
 }
 
 - (Source *) getSource:(pkgCache::PkgFileIterator)file {
-    return sources_[file->ID];
+    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
+
++ (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;
 }
 
-- (id) initWithView:(UIView *)view delegate:(id)delegate url:(NSURL *)url;
++ (BOOL) isSelectorExcludedFromWebScript:(SEL)selector {
+    return [self webScriptNameForSelector:selector] == nil;
+}
 
-@end
+- (BOOL) supports:(NSString *)feature {
+    return [feature isEqualToString:@"window.open"];
+}
 
-@implementation MailToView
+- (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;
+}
 
-- (void) dealloc {
-    [controller_ release];
-    [super dealloc];
+- (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_;
     NSArray *changes_;
@@ -3607,8 +4009,7 @@ bool DepSubstrate(const pkgCache::VerIterator &iterator) {
                     Finish_ = 2;
                 [delegate_ confirm];
                 break;
-            default:
-                _assert(false);
+            _nodefault
         }
 
         [sheet dismiss];
@@ -3668,34 +4069,36 @@ bool DepSubstrate(const pkgCache::VerIterator &iterator) {
 
         if (!remove)
             essential_ = nil;
-        else if (Advanced_ || true) {
-            NSString *parenthetical(CYLocalize("PARENTHETICAL"));
+        else if (Advanced_) {
+            NSString *parenthetical(UCLocalize("PARENTHETICAL"));
 
             essential_ = [[UIActionSheet alloc]
-                initWithTitle:CYLocalize("REMOVING_ESSENTIALS")
+                initWithTitle:UCLocalize("REMOVING_ESSENTIALS")
                 buttons:[NSArray arrayWithObjects:
-                    [NSString stringWithFormat:parenthetical, CYLocalize("CANCEL_OPERATION"), CYLocalize("SAFE")],
-                    [NSString stringWithFormat:parenthetical, CYLocalize("FORCE_REMOVAL"), CYLocalize("UNSAFE")],
+                    [NSString stringWithFormat:parenthetical, UCLocalize("CANCEL_OPERATION"), UCLocalize("SAFE")],
+                    [NSString stringWithFormat:parenthetical, UCLocalize("FORCE_REMOVAL"), UCLocalize("UNSAFE")],
                 nil]
                 defaultButtonIndex:0
                 delegate:self
                 context:@"remove"
             ];
 
-#ifndef __OBJC2__
-            [essential_ setDestructiveButton:[[essential_ buttons] objectAtIndex:0]];
-#endif
-            [essential_ setBodyText:CYLocalize("REMOVING_ESSENTIALS_EX")];
+            [essential_ setAutoresizingMask:(UIViewAutoresizingFlexibleWidth | UIViewAutoresizingFlexibleHeight)];
+
+            [essential_ setDestructiveButtonIndex:1];
+            [essential_ setBodyText:UCLocalize("REMOVING_ESSENTIALS_EX")];
         } else {
             essential_ = [[UIActionSheet alloc]
-                initWithTitle:CYLocalize("UNABLE_TO_COMPLY")
-                buttons:[NSArray arrayWithObjects:CYLocalize("OKAY"), nil]
+                initWithTitle:UCLocalize("UNABLE_TO_COMPLY")
+                buttons:[NSArray arrayWithObjects:UCLocalize("OKAY"), nil]
                 defaultButtonIndex:0
                 delegate:self
                 context:@"unable"
             ];
 
-            [essential_ setBodyText:CYLocalize("UNABLE_TO_COMPLY_EX")];
+            [essential_ setAutoresizingMask:(UIViewAutoresizingFlexibleWidth | UIViewAutoresizingFlexibleHeight)];
+
+            [essential_ setBodyText:UCLocalize("UNABLE_TO_COMPLY_EX")];
         }
 
         changes_ = [[NSArray alloc] initWithObjects:
@@ -3717,15 +4120,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 {
@@ -3736,7 +4141,7 @@ bool DepSubstrate(const pkgCache::VerIterator &iterator) {
 #if AlwaysReload || IgnoreInstall
     return [super _rightButtonTitle];
 #else
-    return CYLocalize("CONFIRM");
+    return UCLocalize("CONFIRM");
 #endif
 }
 
@@ -3819,11 +4224,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;
@@ -3856,31 +4259,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_];
 
@@ -3888,6 +4286,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];
@@ -3905,6 +4304,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(
@@ -3914,12 +4314,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,
@@ -3927,10 +4328,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]];
@@ -3939,8 +4342,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,
@@ -3948,6 +4349,8 @@ bool DepSubstrate(const pkgCache::VerIterator &iterator) {
             32 + prgsize.height
         )];
 
+        [close_ setAutoresizingMask:(UIViewAutoresizingFlexibleWidth | UIViewAutoresizingFlexibleTopMargin)];
+
         [close_ setAutosizesToFit:NO];
         [close_ setDrawsShadow:YES];
         [close_ setStretchBackground:YES];
@@ -3956,7 +4359,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;
@@ -3973,9 +4376,7 @@ bool DepSubstrate(const pkgCache::VerIterator &iterator) {
 - (void) alertSheet:(UIActionSheet *)sheet buttonClicked:(int)button {
     NSString *context([sheet context]);
 
-    if ([context isEqualToString:@"error"])
-        [sheet dismiss];
-    else if ([context isEqualToString:@"conffile"]) {
+    if ([context isEqualToString:@"conffile"]) {
         FILE *input = [database_ input];
 
         switch (button) {
@@ -3987,8 +4388,7 @@ bool DepSubstrate(const pkgCache::VerIterator &iterator) {
                 fprintf(input, "Y\n");
                 fflush(input);
                 break;
-            default:
-                _assert(false);
+            _nodefault
         }
 
         [sheet dismiss];
@@ -4004,7 +4404,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:
@@ -4022,96 +4426,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];
 }
@@ -4124,8 +4483,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:@""];
@@ -4139,27 +4505,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_];
@@ -4180,7 +4546,7 @@ bool DepSubstrate(const pkgCache::VerIterator &iterator) {
         detachNewThreadSelector:selector
         toTarget:database_
         withObject:nil
-        title:CYLocalize("REPAIRING")
+        title:UCLocalize("REPAIRING")
     ];
 }
 
@@ -4192,19 +4558,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 yieldToPopupAlertAnimated:YES];
+    [sheet dismiss];
 }
 
 - (void) setProgressTitle:(NSString *)title {
@@ -4241,24 +4604,29 @@ 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")
+        initWithTitle:UCLocalize("CONFIGURATION_UPGRADE")
         buttons:[NSArray arrayWithObjects:
-            CYLocalize("KEEP_OLD_COPY"),
-            CYLocalize("ACCEPT_NEW_COPY"),
-            // XXX: CYLocalize("SEE_WHAT_CHANGED"),
+            UCLocalize("KEEP_OLD_COPY"),
+            UCLocalize("ACCEPT_NEW_COPY"),
+            // XXX: UCLocalize("SEE_WHAT_CHANGED"),
         nil]
         defaultButtonIndex:0
         delegate:self
         context:@"conffile"
     ] autorelease];
 
-    [sheet setBodyText:[NSString stringWithFormat:@"%@\n\n%@", CYLocalize("CONFIGURATION_UPGRADE_EX"), ofile]];
+    [sheet setAutoresizingMask:(UIViewAutoresizingFlexibleWidth | UIViewAutoresizingFlexibleHeight)];
+
+    [sheet setBodyText:[NSString stringWithFormat:@"%@\n\n%@", UCLocalize("CONFIGURATION_UPGRADE_EX"), ofile]];
     [sheet popupAlertAnimated:YES];
 }
 
@@ -4292,24 +4660,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
 
@@ -4341,29 +4741,58 @@ 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];
 }
 
-- (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
-    } return self;
+- (float) fade {
+    return faded_ ? [self selectionPercent] : fade_;
 }
 
-- (void) setPackage:(Package *)package {
+- (PackageCell *) init {
+    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];
 
@@ -4371,7 +4800,14 @@ bool DepSubstrate(const pkgCache::VerIterator &iterator) {
 
     icon_ = [[package icon] retain];
     name_ = [[package name] retain];
-    description_ = [[package shortDescription] retain];
+
+    if (IsWildcat_)
+        description_ = [package longDescription];
+    if (description_ == nil)
+        description_ = [package shortDescription];
+    if (description_ != nil)
+        description_ = [description_ retain];
+
     commercial_ = [package isCommercial];
 
     package_ = [package retain];
@@ -4383,76 +4819,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];
@@ -4480,19 +4883,21 @@ 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 {
@@ -4503,6 +4908,7 @@ bool DepSubstrate(const pkgCache::VerIterator &iterator) {
 /* }}} */
 /* Section Cell {{{ */
 @interface SectionCell : UISimpleTableCell {
+    NSString *basic_;
     NSString *section_;
     NSString *name_;
     NSString *count_;
@@ -4519,6 +4925,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;
@@ -4545,17 +4956,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;
@@ -4574,20 +4984,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 {
+        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)];
 
@@ -4596,7 +5017,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_];
 
@@ -4668,7 +5094,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];
@@ -4678,6 +5104,9 @@ bool DepSubstrate(const pkgCache::VerIterator &iterator) {
         [list_ addTableColumn:column];
         [list_ setDelegate:self];
         [list_ setReusesTableCells:YES];
+
+               [list_ setAutoresizingMask:UIViewAutoresizingFlexibleBoth];
+        [self setAutoresizingMask:UIViewAutoresizingFlexibleBoth];
     } return self;
 }
 
@@ -4736,17 +5165,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_;
@@ -4778,15 +5207,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);
 }
@@ -4822,15 +5251,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
@@ -4852,7 +5282,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 {
@@ -4888,27 +5318,30 @@ bool DepSubstrate(const pkgCache::VerIterator &iterator) {
         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];
 
@@ -4940,7 +5373,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;
@@ -4950,7 +5385,7 @@ bool DepSubstrate(const pkgCache::VerIterator &iterator) {
 - (void) reloadData;
 - (void) resetCursor;
 
-- (UISectionList *) list;
+- (UITableView *) list;
 
 - (void) setShouldHideHeaderInShortLists:(BOOL)hide;
 
@@ -4965,51 +5400,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 {
@@ -5017,28 +5465,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;
 }
 
@@ -5062,6 +5502,9 @@ bool DepSubstrate(const pkgCache::VerIterator &iterator) {
                 [packages_ addObject:package];
     _end
 
+    [index_ removeAllObjects];
+    [indices_ removeAllObjects];
+
     Section *section = nil;
 
     _profile(PackageTable$reloadData$Section)
@@ -5079,6 +5522,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
@@ -5102,15 +5548,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
@@ -5123,6 +5569,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;
 
@@ -5136,6 +5583,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];
@@ -5145,6 +5602,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_);
@@ -5153,15 +5616,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);
-        _assert(method != NULL);
-        imp_ = method_getImplementation(method);
-        _assert(imp_ != NULL);
-
         [self reloadData];
     } return self;
 }
@@ -5227,6 +5683,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)];
 
@@ -5235,15 +5693,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];
 }
@@ -5263,11 +5721,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;
@@ -5296,6 +5755,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_];
@@ -5311,12 +5771,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
     }
 }
 
@@ -5325,9 +5783,7 @@ bool DepSubstrate(const pkgCache::VerIterator &iterator) {
         case 0: return 0;
         case 1: return offset_;
 
-        default:
-            _assert(false);
-            return -1;
+        _nodefault
     }
 }
 
@@ -5406,7 +5862,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]);
@@ -5421,7 +5877,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_;
@@ -5430,50 +5888,56 @@ 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]
+                    initWithTitle:UCLocalize("SOURCE_WARNING")
+                    buttons:[NSArray arrayWithObjects:UCLocalize("ADD_ANYWAY"), UCLocalize("CANCEL"), nil]
                     defaultButtonIndex:0
                     delegate:self
                     context:@"warning"
                 ] autorelease];
 
-                [sheet setNumberOfRows:1];
+                [sheet setAutoresizingMask:(UIViewAutoresizingFlexibleWidth | UIViewAutoresizingFlexibleHeight)];
 
+                [sheet setNumberOfRows:1];
                 [sheet setBodyText:warning];
                 [sheet popupAlertAnimated:YES];
             } else
                 [self complete];
         } else if (error_ != nil) {
             UIActionSheet *sheet = [[[UIActionSheet alloc]
-                initWithTitle:CYLocalize("VERIFICATION_ERROR")
-                buttons:[NSArray arrayWithObjects:CYLocalize("OK"), nil]
+                initWithTitle:UCLocalize("VERIFICATION_ERROR")
+                buttons:[NSArray arrayWithObjects:UCLocalize("OK"), nil]
                 defaultButtonIndex:0
                 delegate:self
                 context:@"urlerror"
             ] autorelease];
 
+            [sheet setAutoresizingMask:(UIViewAutoresizingFlexibleWidth | UIViewAutoresizingFlexibleHeight)];
+
             [sheet setBodyText:[error_ localizedDescription]];
             [sheet popupAlertAnimated:YES];
         } else {
             UIActionSheet *sheet = [[[UIActionSheet alloc]
-                initWithTitle:CYLocalize("NOT_REPOSITORY")
-                buttons:[NSArray arrayWithObjects:CYLocalize("OK"), nil]
+                initWithTitle:UCLocalize("NOT_REPOSITORY")
+                buttons:[NSArray arrayWithObjects:UCLocalize("OK"), nil]
                 defaultButtonIndex:0
                 delegate:self
                 context:@"trivial"
             ] autorelease];
 
-            [sheet setBodyText:CYLocalize("NOT_REPOSITORY_EX")];
+            [sheet setAutoresizingMask:(UIViewAutoresizingFlexibleWidth | UIViewAutoresizingFlexibleHeight)];
+
+            [sheet setBodyText:UCLocalize("NOT_REPOSITORY_EX")];
             [sheet popupAlertAnimated:YES];
         }
 
@@ -5498,7 +5962,7 @@ bool DepSubstrate(const pkgCache::VerIterator &iterator) {
 - (void) connection:(NSURLConnection *)connection didReceiveResponse:(NSHTTPURLResponse *)response {
     switch ([response statusCode]) {
         case 200:
-            trivial_ = YES;
+            cydia_ = YES;
     }
 }
 
@@ -5517,7 +5981,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];
@@ -5526,7 +5990,6 @@ 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"];
 
@@ -5549,21 +6012,21 @@ 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:
             break;
 
-            default:
-                _assert(false);
+            _nodefault
         }
 
         [sheet dismiss];
@@ -5580,8 +6043,7 @@ bool DepSubstrate(const pkgCache::VerIterator &iterator) {
             case 2:
             break;
 
-            default:
-                _assert(false);
+            _nodefault
         }
 
         [href_ release];
@@ -5598,13 +6060,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
         ];
@@ -5616,14 +6079,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]];
@@ -5631,7 +6094,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)
@@ -5652,15 +6115,16 @@ bool DepSubstrate(const pkgCache::VerIterator &iterator) {
     ] autorelease]];*/
 
     UIActionSheet *sheet = [[[UIActionSheet alloc]
-        initWithTitle:CYLocalize("ENTER_APT_URL")
-        buttons:[NSArray arrayWithObjects:CYLocalize("ADD_SOURCE"), CYLocalize("CANCEL"), nil]
+        initWithTitle:UCLocalize("ENTER_APT_URL")
+        buttons:[NSArray arrayWithObjects:UCLocalize("ADD_SOURCE"), UCLocalize("CANCEL"), nil]
         defaultButtonIndex:0
         delegate:self
         context:@"source"
     ] autorelease];
 
-    [sheet setNumberOfRows:1];
+    [sheet setAutoresizingMask:(UIViewAutoresizingFlexibleWidth | UIViewAutoresizingFlexibleHeight)];
 
+    [sheet setNumberOfRows:1];
     [sheet addTextFieldWithValue:@"http://" label:@""];
 
     UITextInputTraits *traits = [[sheet textField] textInputTraits];
@@ -5681,15 +6145,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 {
@@ -5729,10 +6193,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;
 }
 
@@ -5752,15 +6216,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 {
@@ -5776,7 +6240,7 @@ bool DepSubstrate(const pkgCache::VerIterator &iterator) {
 /* }}} */
 
 /* Home View {{{ */
-@interface HomeView : BrowserView {
+@interface HomeView : CydiaBrowserView {
 }
 
 @end
@@ -5792,41 +6256,38 @@ bool DepSubstrate(const pkgCache::VerIterator &iterator) {
         [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
@@ -5834,20 +6295,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 {
@@ -5866,8 +6328,6 @@ bool DepSubstrate(const pkgCache::VerIterator &iterator) {
 @end
 /* }}} */
 
-#include <BrowserView.m>
-
 /* Cydia Book {{{ */
 @interface CYBook : RVBook <
     ProgressDelegate
@@ -5880,11 +6340,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
 
@@ -5907,7 +6369,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];
@@ -5924,25 +6390,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];
 
@@ -5960,6 +6413,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];
 }
@@ -5968,29 +6457,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};
 
@@ -6002,13 +6494,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];
 
@@ -6026,10 +6515,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];
@@ -6049,7 +6541,6 @@ bool DepSubstrate(const pkgCache::VerIterator &iterator) {
 - (void) _update { _pooled
     Status status;
     status.setDelegate(self);
-
     [database_ updateWithStatus:status];
 
     [self
@@ -6059,10 +6550,29 @@ bool DepSubstrate(const pkgCache::VerIterator &iterator) {
     ];
 }
 
-- (void) setProgressError:(NSString *)error forPackage:(NSString *)id {
-    [prompt_ setText:[NSString stringWithFormat:CYLocalize("COLON_DELIMITED"), CYLocalize("ERROR"), 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:)
@@ -6094,10 +6604,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];
 }
@@ -6217,7 +6723,6 @@ bool DepSubstrate(const pkgCache::VerIterator &iterator) {
     _transient Database *database_;
     NSMutableArray *sections_;
     NSMutableArray *filtered_;
-    UITransitionView *transition_;
     UITable *list_;
     UIView *accessory_;
     BOOL editing_;
@@ -6237,7 +6742,6 @@ bool DepSubstrate(const pkgCache::VerIterator &iterator) {
 
     [sections_ release];
     [filtered_ release];
-    [transition_ release];
     [list_ release];
     [accessory_ release];
     [super dealloc];
@@ -6281,16 +6785,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");
         }
     }
 
@@ -6298,7 +6803,7 @@ bool DepSubstrate(const pkgCache::VerIterator &iterator) {
         initWithBook:book_
         database:database_
         title:title
-        filter:@selector(isVisiblyUninstalledInSection:)
+        filter:@selector(isVisibleInSection:)
         with:name
     ] autorelease];
 
@@ -6314,14 +6819,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];
@@ -6334,8 +6837,7 @@ bool DepSubstrate(const pkgCache::VerIterator &iterator) {
 
         [self reloadData];
 
-        [self setAutoresizingMask:UIViewAutoresizingFlexibleHeight];
-        [list_ setAutoresizingMask:UIViewAutoresizingFlexibleHeight];
+        [self setAutoresizingMask:UIViewAutoresizingFlexibleBoth];
     } return self;
 }
 
@@ -6373,7 +6875,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
 
@@ -6394,7 +6896,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
 
@@ -6445,15 +6947,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 {
@@ -6471,11 +6973,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
@@ -6483,7 +6985,7 @@ bool DepSubstrate(const pkgCache::VerIterator &iterator) {
 @implementation ChangesView
 
 - (void) dealloc {
-    [[list_ table] setDelegate:nil];
+    [list_ setDelegate:nil];
     [list_ setDataSource:nil];
 
     [packages_ release];
@@ -6492,46 +6994,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];
-}
-
-- (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]);
+    return [packages_ objectAtIndex:([section row] + row)];
 }
 
-- (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]);
     PackageView *view([delegate_ packageView]);
     [view setDelegate:delegate_];
     [view setPackage:package];
     [book_ pushPage:view];
+    return path;
 }
 
 - (void) _leftButtonClicked {
@@ -6543,49 +7048,34 @@ 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];
@@ -6593,9 +7083,23 @@ bool DepSubstrate(const pkgCache::VerIterator &iterator) {
     _trace();
     [packages_ radixSortUsingFunction:reinterpret_cast<SKRadixFunction>(&PackageChangesRadix) withContext:NULL];
     _trace();
+}
 
-    Section *upgradable = [[[Section alloc] initWithName:CYLocalize("AVAILABLE_UPGRADES") localize:NO] autorelease];
-    Section *ignored = [[[Section alloc] initWithName:CYLocalize("IGNORED_UPGRADES") localize:NO] autorelease];
+- (void) reloadData {
+    NSArray *packages = [database_ packages];
+
+    [packages_ removeAllObjects];
+    [sections_ removeAllObjects];
+
+    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;
 
@@ -6622,14 +7126,14 @@ bool DepSubstrate(const pkgCache::VerIterator &iterator) {
 
                 NSString *name;
                 if (seen == nil)
-                    name = CYLocalize("UNKNOWN");
+                    name = UCLocalize("UNKNOWN");
                 else {
                     name = (NSString *) CFDateFormatterCreateStringWithDate(NULL, formatter, (CFDateRef) seen);
                     [name autorelease];
                 }
 
                 _profile(ChangesView$reloadData$Allocate)
-                    name = [NSString stringWithFormat:CYLocalize("NEW_AT"), name];
+                    name = [NSString stringWithFormat:UCLocalize("NEW_AT"), name];
                     section = [[[Section alloc] initWithName:name row:offset localize:NO] autorelease];
                     [sections_ addObject:section];
                 _end
@@ -6668,15 +7172,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
@@ -6689,11 +7193,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_;
 }
 
@@ -6709,33 +7209,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];
@@ -6766,21 +7243,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;
     }
@@ -6808,19 +7290,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
@@ -6829,33 +7298,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];
@@ -6868,43 +7332,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];
 }
 
@@ -6912,9 +7347,6 @@ bool DepSubstrate(const pkgCache::VerIterator &iterator) {
 }
 
 - (void) reloadData {
-    if (flipped_)
-        [self flipPage];
-    [table_ setObject:[field_ text]];
     _profile(SearchView$reloadData)
         [table_ reloadData];
     _end
@@ -6931,7 +7363,7 @@ bool DepSubstrate(const pkgCache::VerIterator &iterator) {
 }
 
 - (NSString *) backButtonTitle {
-    return CYLocalize("SEARCH");
+    return UCLocalize("SEARCH");
 }
 
 - (void) setDelegate:(id)delegate {
@@ -6941,7 +7373,7 @@ bool DepSubstrate(const pkgCache::VerIterator &iterator) {
 
 @end
 /* }}} */
-
+/* Settings View {{{ */
 @interface SettingsView : RVPage {
     _transient Database *database_;
     NSString *name_;
@@ -6988,7 +7420,7 @@ bool DepSubstrate(const pkgCache::VerIterator &iterator) {
         case 0: return nil;
         case 1: return nil;
 
-        default: _assert(false);
+        _nodefault
     }
 
     return nil;
@@ -7002,7 +7434,7 @@ bool DepSubstrate(const pkgCache::VerIterator &iterator) {
         case 0: return NO;
         case 1: return YES;
 
-        default: _assert(false);
+        _nodefault
     }
 
     return NO;
@@ -7016,7 +7448,7 @@ bool DepSubstrate(const pkgCache::VerIterator &iterator) {
         case 0: return 1;
         case 1: return 1;
 
-        default: _assert(false);
+        _nodefault
     }
 
     return 0;
@@ -7061,21 +7493,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;
@@ -7090,19 +7522,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];
@@ -7128,13 +7560,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_;
 }
@@ -7173,6 +7606,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,
@@ -7180,11 +7626,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_;
 
@@ -7194,7 +7643,7 @@ bool DepSubstrate(const pkgCache::VerIterator &iterator) {
     Database *database_;
     ProgressView *progress_;
 
-    unsigned tag_;
+    int tag_;
 
     UIKeyboard *keyboard_;
     UIProgressHUD *hud_;
@@ -7204,57 +7653,106 @@ bool DepSubstrate(const pkgCache::VerIterator &iterator) {
     ManageView *manage_;
     SearchView *search_;
 
+#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])
+            initWithTitle:(count == 1 ? UCLocalize("HALFINSTALLED_PACKAGE") : [NSString stringWithFormat:UCLocalize("HALFINSTALLED_PACKAGES"), count])
             buttons:[NSArray arrayWithObjects:
-                CYLocalize("FORCIBLY_CLEAR"),
-                CYLocalize("TEMPORARY_IGNORE"),
+                UCLocalize("FORCIBLY_CLEAR"),
+                UCLocalize("TEMPORARY_IGNORE"),
             nil]
             defaultButtonIndex:0
             delegate:self
             context:@"fixhalf"
         ] autorelease];
 
-        [sheet setBodyText:CYLocalize("HALFINSTALLED_PACKAGE_EX")];
+        [sheet setAutoresizingMask:(UIViewAutoresizingFlexibleWidth | UIViewAutoresizingFlexibleHeight)];
+
+        [sheet setBodyText:UCLocalize("HALFINSTALLED_PACKAGE_EX")];
         [sheet popupAlertAnimated:YES];
     } 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])
+            initWithTitle:(count == 1 ? UCLocalize("ESSENTIAL_UPGRADE") : [NSString stringWithFormat:UCLocalize("ESSENTIAL_UPGRADES"), count])
             buttons:[NSArray arrayWithObjects:
-                CYLocalize("UPGRADE_ESSENTIAL"),
-                CYLocalize("COMPLETE_UPGRADE"),
-                CYLocalize("TEMPORARY_IGNORE"),
+                UCLocalize("UPGRADE_ESSENTIAL"),
+                UCLocalize("COMPLETE_UPGRADE"),
+                UCLocalize("TEMPORARY_IGNORE"),
             nil]
             defaultButtonIndex:0
             delegate:self
             context:@"upgrade"
         ] autorelease];
 
-        [sheet setBodyText:CYLocalize("ESSENTIAL_UPGRADE_EX")];
+        [sheet setAutoresizingMask:(UIViewAutoresizingFlexibleWidth | UIViewAutoresizingFlexibleHeight)];
+
+        [sheet setBodyText:UCLocalize("ESSENTIAL_UPGRADE_EX")];
         [sheet popupAlertAnimated:YES];
     }
 }
 
+- (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();
@@ -7266,7 +7764,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];
@@ -7279,17 +7777,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?
@@ -7297,58 +7795,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_ {
@@ -7356,13 +7826,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],
@@ -7379,7 +7847,7 @@ bool DepSubstrate(const pkgCache::VerIterator &iterator) {
         detachNewThreadSelector:@selector(update_)
         toTarget:self
         withObject:nil
-        title:CYLocalize("UPDATING_SOURCES")
+        title:UCLocalize("UPDATING_SOURCES")
     ];
 }
 
@@ -7406,10 +7874,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]);
@@ -7417,6 +7887,8 @@ bool DepSubstrate(const pkgCache::VerIterator &iterator) {
 
     [confirm_ setPage:page];
     [self popUpBook:confirm_];
+
+    return true;
 }
 
 - (void) queue {
@@ -7433,6 +7905,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];
@@ -7451,7 +7932,8 @@ bool DepSubstrate(const pkgCache::VerIterator &iterator) {
 
 - (void) distUpgrade {
     @synchronized (self) {
-        [database_ upgrade];
+        if (![database_ upgrade])
+            return;
         [self perform];
     }
 }
@@ -7459,7 +7941,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"
@@ -7485,24 +7967,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")
     ];
 }
 
@@ -7522,72 +7987,103 @@ 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];
+    ] autorelease]);
+
+    [role setBodyText:UCLocalize("ROLE_EX")];
+
+    int button([role yieldToPopupAlertAnimated:YES]);
+
+    switch (button) {
+        case 1: Role_ = @"User"; break;
+        case 2: Role_ = @"Hacker"; break;
+        case 3: Role_ = @"Developer"; break;
+
+        _nodefault
+    }
 
-    [role setBodyText:CYLocalize("ROLE_EX")];
-    [role popupAlertAnimated:YES];
+    Settings_ = [NSMutableDictionary dictionaryWithObjectsAndKeys:
+        Role_, @"Role",
+    nil];
+
+    [Metadata_ setObject:Settings_ forKey:@"Settings"];
+
+    Changed_ = true;
+
+    [role dismiss];
 }
 
 - (void) setPackageView:(PackageView *)view {
     WebThreadLock();
     [view setPackage:nil];
+#if RecyclePackageViews
     if ([details_ count] < 3)
         [details_ addObject:view];
+#endif
     WebThreadUnlock();
 }
 
@@ -7596,6 +8092,7 @@ bool DepSubstrate(const pkgCache::VerIterator &iterator) {
 }
 
 - (PackageView *) packageView {
+#if RecyclePackageViews
     PackageView *view;
     size_t count([details_ count]);
 
@@ -7611,150 +8108,9 @@ bool DepSubstrate(const pkgCache::VerIterator &iterator) {
     }
 
     return view;
-}
-
-- (void) finish {
-    if (hud_ != nil) {
-        [self setStatusBarShowsProgress:NO];
-        [self removeProgressHUD:hud_];
-
-        [hud_ autorelease];
-        hud_ = nil;
-
-        pid_t pid = ExecFork();
-        if (pid == 0) {
-            execlp("launchctl", "launchctl", "stop", "com.apple.SpringBoard", NULL);
-            perror("launchctl stop");
-        }
-
-        return;
-    }
-
-    if (Role_ == nil) {
-        [self askForSettings];
-        return;
-    }
-
-    _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],
-    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_];
-
-    [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_];
-
-    [self reloadData];
-
-    [self sectionsView];
-    changes_ = [[ChangesView alloc] initWithBook:book_ database:database_];
-    search_ = [[SearchView alloc] initWithBook:book_ database:database_];
-
-    manage_ = (ManageView *) [[self
-        _pageForURL:[NSURL fileURLWithPath:[[NSBundle mainBundle] pathForResource:@"manage" ofType:@"html"]]
-        withClass:[ManageView class]
-    ] retain];
-
-    details_ = [[NSMutableArray alloc] initWithCapacity:4];
-    [details_ addObject:[self _packageView]];
-    [details_ addObject:[self _packageView]];
-
-    PrintTimes();
-
-    if (bootstrap_)
-        [self bootstrap];
-    else
-        [self _setHomePage];
+#else
+    return [self _packageView];
+#endif
 }
 
 - (void) alertSheet:(UIActionSheet *)sheet buttonClicked:(int)button {
@@ -7774,8 +8130,7 @@ bool DepSubstrate(const pkgCache::VerIterator &iterator) {
                 clear = true;
             break;
 
-            default:
-                _assert(false);
+            _nodefault
         }
 
         [sheet dismiss];
@@ -7785,7 +8140,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];
             }
 
@@ -7818,37 +8173,9 @@ bool DepSubstrate(const pkgCache::VerIterator &iterator) {
                 [self _loaded];
             break;
 
-            default:
-                _assert(false);
+            _nodefault
         }
 
-        [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);
-        }
-
-        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];
     } else if ([context isEqualToString:@"upgrade"]) {
         switch (button) {
@@ -7870,17 +8197,20 @@ bool DepSubstrate(const pkgCache::VerIterator &iterator) {
                 Ignored_ = YES;
             break;
 
-            default:
-                _assert(false);
+            _nodefault
         }
 
         [sheet dismiss];
     }
 }
 
-- (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 {
@@ -7900,6 +8230,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];
@@ -7912,44 +8244,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"])
@@ -7964,13 +8277,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/"])
@@ -7997,39 +8310,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];
@@ -8038,34 +8359,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) {
@@ -8086,50 +8492,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);
@@ -8146,20 +8514,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");
@@ -8174,18 +8547,21 @@ int main(int argc, char *argv[]) { _pooled
     Languages_ = [NSLocale preferredLanguages];
     //CFStringRef locale(CFLocaleGetIdentifier(Locale_));
     //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);
@@ -8204,24 +8580,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);
@@ -8234,6 +8602,7 @@ int main(int argc, char *argv[]) { _pooled
     dealloc_ = dealloc->method_imp;
     dealloc->method_imp = (IMP) &Dealloc_;*/
 
+    /* System Information {{{ */
     size_t size;
 
     int maxproc;
@@ -8246,6 +8615,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)
@@ -8253,6 +8629,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"])
@@ -8261,10 +8660,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];
@@ -8280,6 +8676,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)
@@ -8305,12 +8703,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();
@@ -8330,14 +8738,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", 4);
-
+    _config->Set("Acquire::http::MaxParallel", 3);
+    /* }}} */
     /* Color Choices {{{ */
     space_ = CGColorSpaceCreateDeviceRGB();
 
@@ -8350,28 +8759,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");