]> git.saurik.com Git - cydia.git/blobdiff - Cydia.mm
Commit (chpwn): packages-cell-landscape.patch
[cydia.git] / Cydia.mm
index 40c83bdc84d40e63cc7639915ebb6b5259e64a2f..53ea2eac7c71617722a92b5e8d9d7aea8a5fd653 100644 (file)
--- a/Cydia.mm
+++ b/Cydia.mm
@@ -1,7 +1,8 @@
 /* Cydia - iPhone UIKit Front-End for Debian APT
- * Copyright (C) 2008-2009  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
@@ -34,6 +35,7 @@
  * 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
@@ -42,7 +44,6 @@
 #import "UICaboodle/UCPlatform.h"
 #import "UICaboodle/UCLocalize.h"
 
-#include <objc/message.h>
 #include <objc/objc.h>
 #include <objc/runtime.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>
@@ -119,19 +122,10 @@ extern "C" {
 #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,59 +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(const This_ &rhs) :
-        value_(rhs.value_ == nil ? nil : [rhs.value_ retain])
-    {
-    }
-
-    _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);
 }
@@ -258,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;
@@ -322,27 +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
-/* }}} */
+
+/* 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)
@@ -364,8 +338,7 @@ static const CFStringCompareFlags LaxCompareFlags_ = kCFCompareCaseInsensitive |
 @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
@@ -393,10 +366,14 @@ static const CFStringCompareFlags LaxCompareFlags_ = kCFCompareCaseInsensitive |
 
 - (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];
 }
@@ -406,19 +383,19 @@ static const CFStringCompareFlags LaxCompareFlags_ = kCFCompareCaseInsensitive |
 
 #define lprintf(args...) fprintf(stderr, args)
 
-#define ForRelease 1
+#define ForRelease 0
 #define TraceLogging (1 && !ForRelease)
 #define HistogramInsertionSort (0 && !ForRelease)
 #define ProfileTimes (0 && !ForRelease)
 #define ForSaurik (0 && !ForRelease)
-#define LogBrowser (1 && !ForRelease)
+#define LogBrowser (0 && !ForRelease)
 #define TrackResize (0 && !ForRelease)
-#define ManualRefresh (1 && !ForRelease)
+#define ManualRefresh (0 && !ForRelease)
 #define ShowInternals (0 && !ForRelease)
 #define IgnoreInstall (0 && !ForRelease)
 #define RecycleWebViews 0
-#define RecyclePackageViews 1
-#define AlwaysReload (0 && !ForRelease)
+#define RecyclePackageViews (1 && ForRelease)
+#define AlwaysReload (1 && !ForRelease)
 
 #if !TraceLogging
 #undef _trace
@@ -651,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);
@@ -675,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;
@@ -735,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/"
     ];
 }
 
@@ -754,7 +732,9 @@ NSUInteger DOMNodeList$countByEnumeratingWithState$objects$count$(DOMNodeList *s
 }
 
 @end
+/* }}} */
 
+/* C++ NSString Wrapper Cache {{{ */
 class CYString {
   private:
     char *data_;
@@ -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,13 +1020,15 @@ 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 NotifyConfig_ "/etc/notify.conf"
 
@@ -1063,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_;
@@ -1076,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_;
@@ -1098,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 UCLocalize("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;
@@ -1193,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"]);
@@ -1206,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;
@@ -1237,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;
@@ -1267,6 +1247,10 @@ class Status :
         delegate_ = delegate;
     }
 
+    NSObject<ProgressDelegate> *getDelegate() const {
+        return delegate_;
+    }
+
     virtual bool MediaChange(std::string media, std::string drive) {
         return false;
     }
@@ -1276,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) {
@@ -1297,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,
@@ -1332,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)
     {
     }
 
@@ -1349,7 +1340,12 @@ class Progress :
         delegate_ = delegate;
     }
 
+    id getDelegate() const {
+        return delegate_;
+    }
+
     virtual void Done() {
+        //NSLog(@"DONE");
         //[delegate_ setProgressPercent:1];
     }
 };
@@ -1407,15 +1403,49 @@ typedef std::map< unsigned long, _H<Source> > SourceMap;
 - (void) reloadData;
 
 - (void) configure;
-- (void) prepare;
+- (bool) prepare;
 - (void) perform;
-- (void) upgrade;
+- (bool) upgrade;
 - (void) update;
 
-- (NSString *) updateWithStatus:(Status &)status;
+- (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
 /* }}} */
 
@@ -1433,6 +1463,7 @@ typedef std::map< unsigned long, _H<Source> > SourceMap;
     CYString version_;
 
     NSString *host_;
+    NSString *authority_;
 
     CYString defaultIcon_;
 
@@ -1490,6 +1521,11 @@ typedef std::map< unsigned long, _H<Source> > SourceMap;
         [host_ release];
         host_ = nil;
     }
+
+    if (authority_ != nil) {
+        [authority_ release];
+        authority_ = nil;
+    }
 }
 
 - (void) dealloc {
@@ -1557,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 {
@@ -1626,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 {
@@ -1634,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 {
@@ -1703,7 +1751,9 @@ typedef std::map< unsigned long, _H<Source> > SourceMap;
     CYString section_;
     NSString *section$_;
     bool essential_;
+    bool required_;
     bool visible_;
+    bool obsolete_;
 
     NSString *latest_;
     CYString installed_;
@@ -1721,6 +1771,7 @@ typedef std::map< unsigned long, _H<Source> > SourceMap;
     CYString author_;
     Address *author$_;
 
+    CYString bugs_;
     CYString support_;
     NSMutableArray *tags_;
     NSString *role_;
@@ -1775,6 +1826,8 @@ typedef std::map< unsigned long, _H<Source> > SourceMap;
 - (BOOL) hasMode;
 - (NSString *) mode;
 
+- (void) setVisible;
+
 - (NSString *) id;
 - (NSString *) name;
 - (UIImage *) icon;
@@ -1810,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
@@ -1908,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));
@@ -2018,6 +2077,7 @@ struct PackageNameOrdering :
                 {"depiction", &depiction_},
                 {"homepage", &homepage_},
                 {"website", &website},
+                {"bugs", &bugs_},
                 {"support", &support_},
                 {"sponsor", &sponsor_},
                 {"author", &author_},
@@ -2048,7 +2108,7 @@ struct PackageNameOrdering :
         _end
 
         _profile(Package$parse$Retain)
-            if (!homepage_.empty())
+            if (homepage_.empty())
                 homepage_ = website;
             if (homepage_ == depiction_)
                 homepage_.clear();
@@ -2056,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)
@@ -2099,7 +2163,7 @@ struct PackageNameOrdering :
             _end
         }
 
-        visible_ = true;
+        required_ = true;
 
         _profile(Package$initWithVersion$Tags)
             pkgCache::TagIterator tag(iterator_.TagList());
@@ -2110,10 +2174,10 @@ struct PackageNameOrdering :
                     [tags_ addObject:(NSString *)CFCString(name)];
                     if (role_ == nil && strncmp(name, "role::", 6) == 0 /*&& strcmp(name, "role::leaper") != 0*/)
                         role_ = (NSString *) CFCString(name + 6);
-                    if (visible_ && strncmp(name, "require::", 9) == 0 && (
+                    if (required_ && strncmp(name, "require::", 9) == 0 && (
                         true
                     ))
-                        visible_ = false;
+                        required_ = false;
                     ++tag;
                 } while (!tag.end());
             }
@@ -2152,13 +2216,12 @@ struct PackageNameOrdering :
                 if (version == nil) {
                     [metadata_ setObject:latest_ forKey:@"LastVersion"];
                     changed = true;
-                } else {
-                if (![version isEqualToString:latest_]) {
+                } else if (![version isEqualToString:latest_]) {
                     [metadata_ setObject:latest_ forKey:@"LastVersion"];
                     lastSeen_ = now_;
                     [metadata_ setObject:lastSeen_ forKey:@"LastSeen"];
                     changed = true;
-                } }
+                }
             }
 
             metadata_ = [metadata_ retain];
@@ -2173,8 +2236,9 @@ 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_ = visible_ && [self hasSupportingRole] && [self unfiltered];
+        [self setVisible];
     } _end } return self;
 }
 
@@ -2354,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 {
@@ -2407,11 +2471,9 @@ struct PackageNameOrdering :
                     return @"UPGRADE";
                 case 2:
                     return @"NEW_INSTALL";
-                default:
-                    _assert(false);
+                _nodefault
             }
-        default:
-            _assert(false);
+        _nodefault
     }
 }
 
@@ -2465,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 {
@@ -2506,6 +2568,7 @@ struct PackageNameOrdering :
 
     if (strcmp(name, "cydia") != 0) {
         bool cydia = false;
+        bool user = false;
         bool _private = false;
         bool stash = false;
 
@@ -2515,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"])
@@ -2523,6 +2588,8 @@ struct PackageNameOrdering :
         /* XXX: this is not sensitive enough. only some folders are valid. */
         if (cydia && !repository)
             [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:UCLocalize("FILES_INSTALLED_TO"), @"/private"]];
         if (stash)
@@ -2733,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 uninstalled];
 }
 
-- (bool) isVisiblyUninstalledInSection:(NSString *)name {
+- (bool) isVisibleInSection:(NSString *)name {
     NSString *section = [self section];
 
     return
-        [self visible] &&
-        [self uninstalled] && (
+        [self visible] && (
             name == nil ||
             section == nil && [name length] == 0 ||
             [name isEqualToString:section]
@@ -2833,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;
@@ -2874,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
@@ -2919,7 +3005,7 @@ static NSArray *Finishes_;
         }
     }
 
-    _assert(false);
+    _assume(false);
 }
 
 - (void) _readStatus:(NSNumber *)fd { _pooled
@@ -2932,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)) {
@@ -2950,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
                 ];
@@ -2958,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
@@ -2975,7 +3063,7 @@ static NSArray *Finishes_;
         [delegate_ addProgressOutput:[NSString stringWithUTF8String:line.c_str()]];
     }
 
-    _assert(false);
+    _assume(false);
 }
 
 - (FILE *) input {
@@ -3145,9 +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_;
     }
@@ -3185,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. ")
@@ -3200,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();
@@ -3217,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();
@@ -3293,13 +3429,18 @@ static NSArray *Finishes_;
     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"));
@@ -3313,35 +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()]];
     }
@@ -3364,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]
@@ -3397,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()]];
     }
@@ -3406,50 +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_];
 }
 
-- (NSString *) updateWithStatus:(Status &)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"));
+    if ([self popErrorWithTitle:title])
+        return;
 
-    if (_error->PendingError()) {
-        std::string error;
-        if (!_error->PopMessage(error))
-            _assert(false);
-        _error->Discard();
-        return [NSString stringWithUTF8String:error.c_str()];
-    }
-
-    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 (!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/"));
-        }
-
-        [Metadata_ setObject:[NSDate date] forKey:@"LastUpdate"];
-        Changed_ = true;
-    }
+    if ([self popErrorWithTitle:title forOperation:ListUpdate(status, list, PulseInterval_)])
+        /* XXX: ignore this because users suck and don't understand why refreshing is important: return */;
 
-    return nil;
+    [Metadata_ setObject:[NSDate date] forKey:@"LastUpdate"];
+    Changed_ = true;
 }
 
 - (void) setDelegate:(id)delegate {
@@ -3466,58 +3606,6 @@ static NSArray *Finishes_;
 @end
 /* }}} */
 
-/* PopUp Windows {{{ */
-@interface PopUpView : UIView {
-    _transient id delegate_;
-    UITransitionView *transition_;
-    UIView *overlay_;
-}
-
-- (void) cancel;
-- (id) initWithView:(UIView *)view delegate:(id)delegate;
-
-@end
-
-@implementation PopUpView
-
-- (void) dealloc {
-    [transition_ setDelegate:nil];
-    [transition_ release];
-    [overlay_ release];
-    [super dealloc];
-}
-
-- (void) cancel {
-    [transition_ transition:UITransitionPushFromTop toView:nil];
-}
-
-- (void) transitionViewDidComplete:(UITransitionView*)view fromView:(UIView*)from toView:(UIView*)to {
-    if (from != nil && to == nil)
-        [self removeFromSuperview];
-}
-
-- (id) initWithView:(UIView *)view delegate:(id)delegate {
-    if ((self = [super initWithFrame:[view bounds]]) != nil) {
-        delegate_ = delegate;
-
-        transition_ = [[UITransitionView alloc] initWithFrame:[self bounds]];
-        [self addSubview:transition_];
-
-        overlay_ = [[UIView alloc] initWithFrame:[transition_ bounds]];
-
-        [view addSubview:self];
-
-        [transition_ setDelegate:self];
-
-        UIView *blank = [[[UIView alloc] initWithFrame:[transition_ bounds]] autorelease];
-        [transition_ transition:UITransitionNone toView:blank];
-        [transition_ transition:UITransitionPushFromBottom toView:overlay_];
-    } return self;
-}
-
-@end
-/* }}} */
-
 /* Confirmation View {{{ */
 bool DepSubstrate(const pkgCache::VerIterator &iterator) {
     if (!iterator.end())
@@ -3537,6 +3625,7 @@ bool DepSubstrate(const pkgCache::VerIterator &iterator) {
 /* Web Scripting {{{ */
 @interface CydiaObject : NSObject {
     id indirect_;
+    id delegate_;
 }
 
 - (id) initWithDelegate:(IndirectDelegate *)indirect;
@@ -3555,6 +3644,10 @@ bool DepSubstrate(const pkgCache::VerIterator &iterator) {
     } return self;
 }
 
+- (void) setDelegate:(id)delegate {
+    delegate_ = delegate;
+}
+
 + (NSArray *) _attributeKeys {
     return [NSArray arrayWithObjects:@"device", @"firewire", @"imei", @"mac", @"serial", nil];
 }
@@ -3596,8 +3689,12 @@ bool DepSubstrate(const pkgCache::VerIterator &iterator) {
 + (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:))
@@ -3610,6 +3707,8 @@ bool DepSubstrate(const pkgCache::VerIterator &iterator) {
         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:))
@@ -3634,6 +3733,15 @@ bool DepSubstrate(const pkgCache::VerIterator &iterator) {
     return [feature isEqualToString:@"window.open"];
 }
 
+- (NSArray *) getInstalledPackages {
+    NSArray *packages([[Database sharedInstance] packages]);
+    NSMutableArray *installed([NSMutableArray arrayWithCapacity:[packages count]]);
+    for (Package *package in packages)
+        if ([package installed] != nil)
+            [installed addObject:package];
+    return installed;
+}
+
 - (Package *) getPackageById:(NSString *)id {
     Package *package([[Database sharedInstance] packageWithName:id]);
     [package parse];
@@ -3701,6 +3809,10 @@ bool DepSubstrate(const pkgCache::VerIterator &iterator) {
     [indirect_ close];
 }
 
+- (void) installPackages:(NSArray *)packages {
+    [delegate_ performSelectorOnMainThread:@selector(installPackages:) withObject:packages waitUntilDone:NO];
+}
+
 - (void) setAutoPopup:(BOOL)popup {
     [indirect_ setAutoPopup:popup];
 }
@@ -3717,6 +3829,15 @@ bool DepSubstrate(const pkgCache::VerIterator &iterator) {
     [indirect_ setSpecial:function];
 }
 
+- (void) setToken:(NSString *)token {
+    if (Token_ != nil)
+        [Token_ release];
+    Token_ = [token retain];
+
+    [Metadata_ setObject:Token_ forKey:@"Token"];
+    Changed_ = true;
+}
+
 - (void) setFinishHook:(id)function {
     [indirect_ setFinishHook:function];
 }
@@ -3762,43 +3883,76 @@ bool DepSubstrate(const pkgCache::VerIterator &iterator) {
     [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];
-    [window setValue:cydia_ forKey:@"cydia"];
-}
 
-- (NSURLRequest *) webView:(WebView *)sender resource:(id)identifier willSendRequest:(NSURLRequest *)request redirectResponse:(NSURLResponse *)redirectResponse fromDataSource:(WebDataSource *)source {
-    NSMutableURLRequest *copy = [request mutableCopy];
+    WebDataSource *source([frame dataSource]);
+    NSURLResponse *response([source response]);
+    NSURL *url([response URL]);
+    NSString *scheme([url scheme]);
 
-    if (Machine_ != NULL)
-        [copy setValue:[NSString stringWithUTF8String:Machine_] forHTTPHeaderField:@"X-Machine"];
-    if (UniqueID_ != nil)
-        [copy setValue:UniqueID_ forHTTPHeaderField:@"X-Unique-ID"];
+    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)
-        [copy setValue:Role_ forHTTPHeaderField:@"X-Role"];
+        [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([webview_ webView]);
+        WebView *webview([document_ webView]);
 
         Package *package([[Database sharedInstance] packageWithName:@"cydia"]);
+
         NSString *application = package == nil ? @"Cydia" : [NSString
             stringWithFormat:@"Cydia/%@",
             [package installed]
         ];
 
-        if (Product_ != nil)
-            application = [NSString stringWithFormat:@"%@ Version/%@", application, Product_];
-        if (Build_ != nil)
-            application = [NSString stringWithFormat:@"%@ Mobile/%@", application, Build_];
         if (Safari_ != nil)
-            application = [NSString stringWithFormat:@"%@ Safari/%@", application, Safari_];
+            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;
@@ -3855,8 +4009,7 @@ bool DepSubstrate(const pkgCache::VerIterator &iterator) {
                     Finish_ = 2;
                 [delegate_ confirm];
                 break;
-            default:
-                _assert(false);
+            _nodefault
         }
 
         [sheet dismiss];
@@ -3916,7 +4069,7 @@ bool DepSubstrate(const pkgCache::VerIterator &iterator) {
 
         if (!remove)
             essential_ = nil;
-        else if (Advanced_ || true) {
+        else if (Advanced_) {
             NSString *parenthetical(UCLocalize("PARENTHETICAL"));
 
             essential_ = [[UIActionSheet alloc]
@@ -3930,9 +4083,9 @@ bool DepSubstrate(const pkgCache::VerIterator &iterator) {
                 context:@"remove"
             ];
 
-#ifndef __OBJC2__
-            [essential_ setDestructiveButton:[[essential_ buttons] objectAtIndex:0]];
-#endif
+            [essential_ setAutoresizingMask:(UIViewAutoresizingFlexibleWidth | UIViewAutoresizingFlexibleHeight)];
+
+            [essential_ setDestructiveButtonIndex:1];
             [essential_ setBodyText:UCLocalize("REMOVING_ESSENTIALS_EX")];
         } else {
             essential_ = [[UIActionSheet alloc]
@@ -3943,6 +4096,8 @@ bool DepSubstrate(const pkgCache::VerIterator &iterator) {
                 context:@"unable"
             ];
 
+            [essential_ setAutoresizingMask:(UIViewAutoresizingFlexibleWidth | UIViewAutoresizingFlexibleHeight)];
+
             [essential_ setBodyText:UCLocalize("UNABLE_TO_COMPLY_EX")];
         }
 
@@ -3965,6 +4120,8 @@ bool DepSubstrate(const pkgCache::VerIterator &iterator) {
         nil];
 
         [self loadURL:[NSURL fileURLWithPath:[[NSBundle mainBundle] pathForResource:@"confirm" ofType:@"html"]]];
+
+        [self setAutoresizingMask:UIViewAutoresizingFlexibleBoth];
     } return self;
 }
 
@@ -4067,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;
@@ -4104,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_];
 
@@ -4136,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];
@@ -4153,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(
@@ -4162,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,
@@ -4175,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]];
@@ -4187,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,
@@ -4196,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];
@@ -4204,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;
@@ -4218,121 +4373,10 @@ bool DepSubstrate(const pkgCache::VerIterator &iterator) {
     [transition_ transition:6 toView:view_];
 }
 
-- (void) _checkError {
-    if (_error->PendingError()) {
-        std::string error;
-        if (!_error->PopMessage(error))
-            _assert(false);
-
-        UIActionSheet *sheet = [[[UIActionSheet alloc]
-            initWithTitle:UCLocalize("ERROR")
-            buttons:[NSArray arrayWithObjects:UCLocalize("OKAY"), nil]
-            defaultButtonIndex:0
-            delegate:self
-            context:@"_error"
-        ] autorelease];
-
-        [sheet setBodyText:[NSString stringWithUTF8String:error.c_str()]];
-        [sheet popupAlertAnimated:YES];
-
-        return;
-    }
-
-    [delegate_ progressViewIsComplete:self];
-
-    if (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;
-        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: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;
-    }
-
-#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]);
-    }
-
-    notify_post("com.apple.mobile.application_installed");
-
-    [delegate_ setStatusBarShowsProgress:NO];
-}
-
 - (void) alertSheet:(UIActionSheet *)sheet buttonClicked:(int)button {
     NSString *context([sheet context]);
 
-    if ([context isEqualToString:@"error"])
-        [sheet dismiss];
-    else if ([context isEqualToString:@"_error"]) {
-        [sheet dismiss];
-        [self _checkError];
-    } else if ([context isEqualToString:@"conffile"]) {
+    if ([context isEqualToString:@"conffile"]) {
         FILE *input = [database_ input];
 
         switch (button) {
@@ -4344,8 +4388,7 @@ bool DepSubstrate(const pkgCache::VerIterator &iterator) {
                 fprintf(input, "Y\n");
                 fflush(input);
                 break;
-            default:
-                _assert(false);
+            _nodefault
         }
 
         [sheet dismiss];
@@ -4361,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:
@@ -4379,14 +4426,53 @@ bool DepSubstrate(const pkgCache::VerIterator &iterator) {
 }
 
 - (void) _retachThread {
-    UINavigationItem *item = [navbar_ topItem];
+    UINavigationItem *item([navbar_ topItem]);
     [item setTitle:UCLocalize("COMPLETE")];
 
     [overlay_ addSubview:close_];
     [progress_ removeFromSuperview];
     [status_ removeFromSuperview];
 
-    [self _checkError];
+    [database_ popErrorWithTitle:title_];
+    [delegate_ progressViewIsComplete:self];
+
+    if (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;
+        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: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;
+    }
+
+    system("su -c /usr/bin/uicache mobile");
+
+    [delegate_ setStatusBarShowsProgress:NO];
 }
 
 - (void) _detachNewThreadData:(ProgressData *)data { _pooled
@@ -4397,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:@""];
@@ -4465,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])
+- (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 {
@@ -4514,7 +4604,10 @@ 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];
@@ -4531,6 +4624,8 @@ bool DepSubstrate(const pkgCache::VerIterator &iterator) {
         context:@"conffile"
     ] autorelease];
 
+    [sheet setAutoresizingMask:(UIViewAutoresizingFlexibleWidth | UIViewAutoresizingFlexibleHeight)];
+
     [sheet setBodyText:[NSString stringWithFormat:@"%@\n\n%@", UCLocalize("CONFIGURATION_UPGRADE_EX"), ofile]];
     [sheet popupAlertAnimated:YES];
 }
@@ -4565,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
 
@@ -4614,28 +4741,57 @@ bool DepSubstrate(const pkgCache::VerIterator &iterator) {
         badge_ = nil;
     }
 
+    if (placard_ != nil) {
+        [placard_ release];
+        placard_ = nil;
+    }
+
     [package_ release];
     package_ = nil;
 }
 
 - (void) dealloc {
     [self clearPackage];
-#ifdef USE_BADGES
-    [status_ release];
-#endif
+    [content_ release];
+    [color_ release];
     [super dealloc];
 }
 
+- (float) fade {
+    return faded_ ? [self selectionPercent] : fade_;
+}
+
 - (PackageCell *) init {
-    if ((self = [super init]) != nil) {
-#ifdef USE_BADGES
-        status_ = [[UITextLabel alloc] initWithFrame:CGRectMake(48, 68, 280, 20)];
-        [status_ setBackgroundColor:[UIColor clearColor]];
-        [status_ setFont:small];
-#endif
+    CGRect frame(CGRectMake(0, 0, 320, 74));
+    if ((self = [super initWithFrame:frame reuseIdentifier:@"Package"]) != nil) {
+        UIView *content([self contentView]);
+        CGRect bounds([content bounds]);
+
+        content_ = [[ContentView alloc] initWithFrame:bounds];
+        [content_ setAutoresizingMask:UIViewAutoresizingFlexibleBoth];
+        [content addSubview:content_];
+
+        [content_ setDelegate:self];
+        [content_ setOpaque:YES];
+        if ([self respondsToSelector:@selector(selectionPercent)])
+            faded_ = YES;
+
+        [self setNeedsDisplayOnBoundsChange:YES];
     } return self;
 }
 
+- (void) _setBackgroundColor {
+    UIColor *color;
+    if (NSString *mode = [package_ mode]) {
+        bool remove([mode isEqualToString:@"REMOVE"] || [mode isEqualToString:@"PURGE"]);
+        color = remove ? RemovingColor_ : InstallingColor_;
+    } else
+        color = [UIColor whiteColor];
+
+    [content_ setBackgroundColor:color];
+    [self setNeedsDisplay];
+}
+
 - (void) setPackage:(Package *)package {
     [self clearPackage];
     [package parse];
@@ -4644,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];
@@ -4675,57 +4838,24 @@ bool DepSubstrate(const pkgCache::VerIterator &iterator) {
         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:UCLocalize("QUEUED_FOR"), UCLocalize(mode)]];
-        [status_ setColor:[UIColor colorWithCGColor:Blueish_]];
-    } else if ([package half]) {
-        [badge_ setImage:[UIImage applicationImageNamed:@"damaged.png"]];
-        [status_ setText:UCLocalize("PACKAGE_DAMAGED")];
-        [status_ setColor:[UIColor redColor]];
-    } else {
-        [badge_ setImage:nil];
-        [status_ setText:nil];
-    }
-#endif
+    if ([package installed] != nil)
+        if ((placard_ = [UIImage imageAtPath:[NSString stringWithFormat:@"%@/installed.png", App_]]) != nil)
+            placard_ = [placard_ retain];
 
-    cached_ = false;
+    [self _setBackgroundColor];
+    [content_ setNeedsDisplay];
 }
 
-- (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;
-    }
-
-    [super drawRect:rect];
-}
+- (void) drawContentRect:(CGRect)rect {
+    bool selected([self isSelected]);
+    float width([self bounds].size.width);
 
-- (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);
-    }
-
-    [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];
@@ -4753,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 {
@@ -4776,6 +4908,7 @@ bool DepSubstrate(const pkgCache::VerIterator &iterator) {
 /* }}} */
 /* Section Cell {{{ */
 @interface SectionCell : UISimpleTableCell {
+    NSString *basic_;
     NSString *section_;
     NSString *name_;
     NSString *count_;
@@ -4792,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;
@@ -4818,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;
@@ -4850,17 +4987,28 @@ bool DepSubstrate(const pkgCache::VerIterator &iterator) {
         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 || [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)];
 
@@ -4869,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_];
 
@@ -4951,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;
 }
 
@@ -5095,8 +5251,9 @@ 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]];
@@ -5173,15 +5330,18 @@ bool DepSubstrate(const pkgCache::VerIterator &iterator) {
             [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];
 
@@ -5213,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;
@@ -5223,7 +5385,7 @@ bool DepSubstrate(const pkgCache::VerIterator &iterator) {
 - (void) reloadData;
 - (void) resetCursor;
 
-- (UISectionList *) list;
+- (UITableView *) list;
 
 - (void) setShouldHideHeaderInShortLists:(BOOL)hide;
 
@@ -5238,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 {
@@ -5290,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:UCLocalize("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;
 }
 
@@ -5335,6 +5502,9 @@ bool DepSubstrate(const pkgCache::VerIterator &iterator) {
                 [packages_ addObject:package];
     _end
 
+    [index_ removeAllObjects];
+    [indices_ removeAllObjects];
+
     Section *section = nil;
 
     _profile(PackageTable$reloadData$Section)
@@ -5352,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
@@ -5375,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
@@ -5396,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;
 
@@ -5409,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];
@@ -5418,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_);
@@ -5426,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;
 }
@@ -5500,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)];
 
@@ -5508,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];
 }
@@ -5536,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;
@@ -5569,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_];
@@ -5587,9 +5774,7 @@ bool DepSubstrate(const pkgCache::VerIterator &iterator) {
         case 0: return UCLocalize("ENTERED_BY_USER");
         case 1: return UCLocalize("INSTALLED_BY_PACKAGE");
 
-        default:
-            _assert(false);
-            return nil;
+        _nodefault
     }
 }
 
@@ -5598,9 +5783,7 @@ bool DepSubstrate(const pkgCache::VerIterator &iterator) {
         case 0: return 0;
         case 1: return offset_;
 
-        default:
-            _assert(false);
-            return -1;
+        _nodefault
     }
 }
 
@@ -5679,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]);
@@ -5694,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_;
@@ -5703,12 +5888,13 @@ 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;
 
@@ -5720,8 +5906,9 @@ bool DepSubstrate(const pkgCache::VerIterator &iterator) {
                     context:@"warning"
                 ] autorelease];
 
-                [sheet setNumberOfRows:1];
+                [sheet setAutoresizingMask:(UIViewAutoresizingFlexibleWidth | UIViewAutoresizingFlexibleHeight)];
 
+                [sheet setNumberOfRows:1];
                 [sheet setBodyText:warning];
                 [sheet popupAlertAnimated:YES];
             } else
@@ -5735,6 +5922,8 @@ bool DepSubstrate(const pkgCache::VerIterator &iterator) {
                 context:@"urlerror"
             ] autorelease];
 
+            [sheet setAutoresizingMask:(UIViewAutoresizingFlexibleWidth | UIViewAutoresizingFlexibleHeight)];
+
             [sheet setBodyText:[error_ localizedDescription]];
             [sheet popupAlertAnimated:YES];
         } else {
@@ -5746,6 +5935,8 @@ bool DepSubstrate(const pkgCache::VerIterator &iterator) {
                 context:@"trivial"
             ] autorelease];
 
+            [sheet setAutoresizingMask:(UIViewAutoresizingFlexibleWidth | UIViewAutoresizingFlexibleHeight)];
+
             [sheet setBodyText:UCLocalize("NOT_REPOSITORY_EX")];
             [sheet popupAlertAnimated:YES];
         }
@@ -5771,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;
     }
 }
 
@@ -5790,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];
@@ -5799,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"];
 
@@ -5822,11 +6012,12 @@ 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:UCLocalize("VERIFYING_URL")];
@@ -5835,8 +6026,7 @@ bool DepSubstrate(const pkgCache::VerIterator &iterator) {
             case 2:
             break;
 
-            default:
-                _assert(false);
+            _nodefault
         }
 
         [sheet dismiss];
@@ -5853,8 +6043,7 @@ bool DepSubstrate(const pkgCache::VerIterator &iterator) {
             case 2:
             break;
 
-            default:
-                _assert(false);
+            _nodefault
         }
 
         [href_ release];
@@ -5871,9 +6060,10 @@ 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]
@@ -5889,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]];
@@ -5904,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)
@@ -5932,8 +6122,9 @@ bool DepSubstrate(const pkgCache::VerIterator &iterator) {
         context:@"source"
     ] autorelease];
 
-    [sheet setNumberOfRows:1];
+    [sheet setAutoresizingMask:(UIViewAutoresizingFlexibleWidth | UIViewAutoresizingFlexibleHeight)];
 
+    [sheet setNumberOfRows:1];
     [sheet addTextFieldWithValue:@"http://" label:@""];
 
     UITextInputTraits *traits = [[sheet textField] textInputTraits];
@@ -6002,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;
 }
 
@@ -6065,31 +6256,28 @@ 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:UCLocalize("ABOUT_CYDIA")
-        buttons:[NSArray arrayWithObjects:UCLocalize("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 {
@@ -6112,6 +6300,7 @@ bool DepSubstrate(const pkgCache::VerIterator &iterator) {
 
 - (void) _leftButtonClicked {
     [delegate_ askForSettings];
+    [delegate_ updateData];
 }
 
 - (NSString *) leftButtonTitle {
@@ -6151,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
 
@@ -6178,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];
@@ -6195,6 +6390,37 @@ bool DepSubstrate(const pkgCache::VerIterator &iterator) {
     [transition_ setFrame:trnframe];
 
     [UIView endAnimations];
+}
+
+- (void) raiseBar {
+    if (!dropped_)
+        return;
+    dropped_ = false;
+
+    [UIView beginAnimations:nil context:NULL];
+
+    CGRect ovrframe = [overlay_ frame];
+    ovrframe.origin.y = -ovrframe.size.height;
+    [overlay_ setFrame:ovrframe];
+
+    CGRect barframe = [navbar_ frame];
+    barframe.origin.y -= ovrframe.size.height;
+    [navbar_ setFrame:barframe];
+
+    CGRect trnframe = [transition_ frame];
+    trnframe.origin.y -= ovrframe.size.height;
+    trnframe.size.height += ovrframe.size.height;
+    [transition_ setFrame:trnframe];
+
+    [UIView commitAnimations];
+}
+
+- (void) setUpdate:(NSDate *)date {
+    [self update];
+}
+
+- (void) update {
+    [self dropBar];
 
     [indicator_ startAnimation];
     [prompt_ setText:UCLocalize("UPDATING_DATABASE")];
@@ -6217,75 +6443,46 @@ bool DepSubstrate(const pkgCache::VerIterator &iterator) {
         [sheet dismiss];
 }
 
-- (void) _update_:(NSString *)error {
+- (void) _update_ {
     updating_ = false;
 
     [indicator_ stopAnimation];
 
-    [UIView beginAnimations:nil context:NULL];
-
-    CGRect ovrframe = [overlay_ frame];
-    ovrframe.origin.y = -ovrframe.size.height;
-    [overlay_ setFrame:ovrframe];
-
-    CGRect barframe = [navbar_ frame];
-    barframe.origin.y -= ovrframe.size.height;
-    [navbar_ setFrame:barframe];
-
-    CGRect trnframe = [transition_ frame];
-    trnframe.origin.y -= ovrframe.size.height;
-    trnframe.size.height += ovrframe.size.height;
-    [transition_ setFrame:trnframe];
-
-    [UIView commitAnimations];
-
-    if (error == nil)
-        [delegate_ performSelector:@selector(reloadData) withObject:nil afterDelay:0];
-    else {
-        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 setBodyText:error];
-        [sheet popupAlertAnimated:YES];
+    [self raiseBar];
 
-        [self reloadButtons];
-    }
+    [delegate_ performSelector:@selector(reloadData) withObject:nil afterDelay:0];
 }
 
 - (id) initWithFrame:(CGRect)frame database:(Database *)database {
     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};
 
@@ -6297,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];
 
@@ -6321,10 +6515,13 @@ bool DepSubstrate(const pkgCache::VerIterator &iterator) {
         } , prgsize};
 
         progress_ = [[UIProgressBar alloc] initWithFrame:prgrect];
-        [progress_ setStyle:0];
+        [progress_ setAutoresizingMask:UIViewAutoresizingFlexibleWidth];
         [overlay_ addSubview:progress_];
 
+        [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];
@@ -6344,20 +6541,38 @@ bool DepSubstrate(const pkgCache::VerIterator &iterator) {
 - (void) _update { _pooled
     Status status;
     status.setDelegate(self);
-
-    NSString *error([database_ updateWithStatus:status]);
+    [database_ updateWithStatus:status];
 
     [self
-        performSelectorOnMainThread:@selector(_update_:)
-        withObject:error
+        performSelectorOnMainThread:@selector(_update_)
+        withObject:nil
         waitUntilDone:NO
     ];
 }
 
-- (void) setProgressError:(NSString *)error forPackage:(NSString *)id {
+- (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:)
@@ -6508,7 +6723,6 @@ bool DepSubstrate(const pkgCache::VerIterator &iterator) {
     _transient Database *database_;
     NSMutableArray *sections_;
     NSMutableArray *filtered_;
-    UITransitionView *transition_;
     UITable *list_;
     UIView *accessory_;
     BOOL editing_;
@@ -6528,7 +6742,6 @@ bool DepSubstrate(const pkgCache::VerIterator &iterator) {
 
     [sections_ release];
     [filtered_ release];
-    [transition_ release];
     [list_ release];
     [accessory_ release];
     [super dealloc];
@@ -6590,7 +6803,7 @@ bool DepSubstrate(const pkgCache::VerIterator &iterator) {
         initWithBook:book_
         database:database_
         title:title
-        filter:@selector(isVisiblyUninstalledInSection:)
+        filter:@selector(isVisibleInSection:)
         with:name
     ] autorelease];
 
@@ -6606,11 +6819,9 @@ 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:UCLocalize("NAME")
@@ -6626,8 +6837,7 @@ bool DepSubstrate(const pkgCache::VerIterator &iterator) {
 
         [self reloadData];
 
-        [self setAutoresizingMask:UIViewAutoresizingFlexibleHeight];
-        [list_ setAutoresizingMask:UIViewAutoresizingFlexibleHeight];
+        [self setAutoresizingMask:UIViewAutoresizingFlexibleBoth];
     } return self;
 }
 
@@ -6665,7 +6875,7 @@ bool DepSubstrate(const pkgCache::VerIterator &iterator) {
         [*section addToCount];
 
         _profile(SectionsView$reloadData$Filter)
-            if (![package valid] || ![package uninstalled] || ![package visible])
+            if (![package valid] || ![package visible])
                 continue;
         _end
 
@@ -6686,7 +6896,7 @@ bool DepSubstrate(const pkgCache::VerIterator &iterator) {
         [section addToCount];
 
         _profile(SectionsView$reloadData$Filter)
-            if (![package valid] || ![package uninstalled] || ![package visible])
+            if (![package valid] || ![package visible])
                 continue;
         _end
 
@@ -6737,7 +6947,7 @@ bool DepSubstrate(const pkgCache::VerIterator &iterator) {
 }
 
 - (NSString *) title {
-    return editing_ ? UCLocalize("SECTION_VISIBILITY") : UCLocalize("INSTALL_BY_SECTION");
+    return editing_ ? UCLocalize("SECTION_VISIBILITY") : UCLocalize("SECTIONS");
 }
 
 - (NSString *) backButtonTitle {
@@ -6763,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
@@ -6775,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];
@@ -6784,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 {
@@ -6835,45 +7048,30 @@ 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:UCLocalize("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 (
@@ -6885,6 +7083,20 @@ bool DepSubstrate(const pkgCache::VerIterator &iterator) {
     _trace();
     [packages_ radixSortUsingFunction:reinterpret_cast<SKRadixFunction>(&PackageChangesRadix) withContext:NULL];
     _trace();
+}
+
+- (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];
@@ -6981,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_;
 }
 
@@ -7001,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:UCLocalize("PARENTHETICAL"), UCLocalize("ADVANCED_SEARCH"), UCLocalize("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];
@@ -7058,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;
     }
@@ -7100,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
@@ -7121,28 +7298,23 @@ 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];
@@ -7160,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];
 }
 
@@ -7204,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
@@ -7233,7 +7373,7 @@ bool DepSubstrate(const pkgCache::VerIterator &iterator) {
 
 @end
 /* }}} */
-
+/* Settings View {{{ */
 @interface SettingsView : RVPage {
     _transient Database *database_;
     NSString *name_;
@@ -7280,7 +7420,7 @@ bool DepSubstrate(const pkgCache::VerIterator &iterator) {
         case 0: return nil;
         case 1: return nil;
 
-        default: _assert(false);
+        _nodefault
     }
 
     return nil;
@@ -7294,7 +7434,7 @@ bool DepSubstrate(const pkgCache::VerIterator &iterator) {
         case 0: return NO;
         case 1: return YES;
 
-        default: _assert(false);
+        _nodefault
     }
 
     return NO;
@@ -7308,7 +7448,7 @@ bool DepSubstrate(const pkgCache::VerIterator &iterator) {
         case 0: return 1;
         case 1: return 1;
 
-        default: _assert(false);
+        _nodefault
     }
 
     return 0;
@@ -7353,7 +7493,7 @@ bool DepSubstrate(const pkgCache::VerIterator &iterator) {
                 return subscribedCell_;
             case 1:
                 return ignoredCell_;
-            default: _assert(false);
+            _nodefault
         } break;
 
         case 1: switch (row) {
@@ -7364,10 +7504,10 @@ bool DepSubstrate(const pkgCache::VerIterator &iterator) {
                 return cell;
             }
 
-            default: _assert(false);
+            _nodefault
         } break;
 
-        default: _assert(false);
+        _nodefault
     }
 
     return nil;
@@ -7382,10 +7522,10 @@ 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];
@@ -7424,6 +7564,7 @@ bool DepSubstrate(const pkgCache::VerIterator &iterator) {
 }
 
 @end
+/* }}} */
 
 /* Signature View {{{ */
 @interface SignatureView : CydiaBrowserView {
@@ -7465,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,
@@ -7472,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_;
 
@@ -7486,7 +7643,7 @@ bool DepSubstrate(const pkgCache::VerIterator &iterator) {
     Database *database_;
     ProgressView *progress_;
 
-    unsigned tag_;
+    int tag_;
 
     UIKeyboard *keyboard_;
     UIProgressHUD *hud_;
@@ -7501,10 +7658,21 @@ bool DepSubstrate(const pkgCache::VerIterator &iterator) {
 #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];
@@ -7520,6 +7688,8 @@ bool DepSubstrate(const pkgCache::VerIterator &iterator) {
             context:@"fixhalf"
         ] autorelease];
 
+        [sheet setAutoresizingMask:(UIViewAutoresizingFlexibleWidth | UIViewAutoresizingFlexibleHeight)];
+
         [sheet setBodyText:UCLocalize("HALFINSTALLED_PACKAGE_EX")];
         [sheet popupAlertAnimated:YES];
     } else if (!Ignored_ && [essential_ count] != 0) {
@@ -7537,18 +7707,52 @@ bool DepSubstrate(const pkgCache::VerIterator &iterator) {
             context:@"upgrade"
         ] autorelease];
 
+        [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 ? UCLocalize("RELOADING_DATA") : UCLocalize("LOADING_DATA"))];
-    loaded = true;
 
     [database_ yieldToSelector:@selector(reloadData) withObject:nil];
     _trace();
@@ -7560,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];
@@ -7573,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?
@@ -7591,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_ {
@@ -7650,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],
@@ -7700,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]);
@@ -7711,6 +7887,8 @@ bool DepSubstrate(const pkgCache::VerIterator &iterator) {
 
     [confirm_ setPage:page];
     [self popUpBook:confirm_];
+
+    return true;
 }
 
 - (void) queue {
@@ -7727,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];
@@ -7745,7 +7932,8 @@ bool DepSubstrate(const pkgCache::VerIterator &iterator) {
 
 - (void) distUpgrade {
     @synchronized (self) {
-        [database_ upgrade];
+        if (![database_ upgrade])
+            return;
         [self perform];
     }
 }
@@ -7783,23 +7971,6 @@ bool DepSubstrate(const pkgCache::VerIterator &iterator) {
     ];
 }
 
-- (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"
-    ];
-}
-
 - (void) progressViewIsComplete:(ProgressView *)progress {
     if (confirm_ != nil) {
         [underlay_ addSubview:overlay_];
@@ -7821,47 +7992,59 @@ bool DepSubstrate(const pkgCache::VerIterator &iterator) {
     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(UCLocalize("PARENTHETICAL"));
 
-    UIActionSheet *role = [[[UIActionSheet alloc]
+    CYActionSheet *role([[[CYActionSheet alloc]
         initWithTitle:UCLocalize("WHO_ARE_YOU")
         buttons:[NSArray arrayWithObjects:
             [NSString stringWithFormat:parenthetical, UCLocalize("USER"), UCLocalize("USER_EX")],
@@ -7869,12 +8052,29 @@ bool DepSubstrate(const pkgCache::VerIterator &iterator) {
             [NSString stringWithFormat:parenthetical, UCLocalize("DEVELOPER"), UCLocalize("DEVELOPER_EX")],
         nil]
         defaultButtonIndex:-1
-        delegate:self
-        context:@"role"
-    ] autorelease];
+    ] autorelease]);
 
     [role setBodyText:UCLocalize("ROLE_EX")];
-    [role popupAlertAnimated:YES];
+
+    int button([role yieldToPopupAlertAnimated:YES]);
+
+    switch (button) {
+        case 1: Role_ = @"User"; break;
+        case 2: Role_ = @"Hacker"; break;
+        case 3: Role_ = @"Developer"; break;
+
+        _nodefault
+    }
+
+    Settings_ = [NSMutableDictionary dictionaryWithObjectsAndKeys:
+        Role_, @"Role",
+    nil];
+
+    [Metadata_ setObject:Settings_ forKey:@"Settings"];
+
+    Changed_ = true;
+
+    [role dismiss];
 }
 
 - (void) setPackageView:(PackageView *)view {
@@ -7913,152 +8113,6 @@ bool DepSubstrate(const pkgCache::VerIterator &iterator) {
 #endif
 }
 
-- (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,
-            UCLocalize("SECTIONS"), kUIButtonBarButtonTitle,
-            @"0", kUIButtonBarButtonType,
-        nil],
-
-        [NSDictionary dictionaryWithObjectsAndKeys:
-            @"buttonBarItemTapped:", kUIButtonBarButtonAction,
-            @"changes-up.png", kUIButtonBarButtonInfo,
-            @"changes-dn.png", kUIButtonBarButtonSelectedInfo,
-            [NSNumber numberWithInt:3], kUIButtonBarButtonTag,
-            self, kUIButtonBarButtonTarget,
-            UCLocalize("CHANGES"), kUIButtonBarButtonTitle,
-            @"0", kUIButtonBarButtonType,
-        nil],
-
-        [NSDictionary dictionaryWithObjectsAndKeys:
-            @"buttonBarItemTapped:", kUIButtonBarButtonAction,
-            @"manage-up.png", kUIButtonBarButtonInfo,
-            @"manage-dn.png", kUIButtonBarButtonSelectedInfo,
-            [NSNumber numberWithInt:4], kUIButtonBarButtonTag,
-            self, kUIButtonBarButtonTarget,
-            UCLocalize("MANAGE"), kUIButtonBarButtonTitle,
-            @"0", kUIButtonBarButtonType,
-        nil],
-
-        [NSDictionary dictionaryWithObjectsAndKeys:
-            @"buttonBarItemTapped:", kUIButtonBarButtonAction,
-            @"search-up.png", kUIButtonBarButtonInfo,
-            @"search-dn.png", kUIButtonBarButtonSelectedInfo,
-            [NSNumber numberWithInt:5], kUIButtonBarButtonTag,
-            self, kUIButtonBarButtonTarget,
-            UCLocalize("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];
-
-#if RecyclePackageViews
-    details_ = [[NSMutableArray alloc] initWithCapacity:4];
-    [details_ addObject:[self _packageView]];
-    [details_ addObject:[self _packageView]];
-#endif
-
-    PrintTimes();
-
-    if (bootstrap_)
-        [self bootstrap];
-    else
-        [self _setHomePage];
-}
-
 - (void) alertSheet:(UIActionSheet *)sheet buttonClicked:(int)button {
     NSString *context([sheet context]);
 
@@ -8076,8 +8130,7 @@ bool DepSubstrate(const pkgCache::VerIterator &iterator) {
                 clear = true;
             break;
 
-            default:
-                _assert(false);
+            _nodefault
         }
 
         [sheet dismiss];
@@ -8087,7 +8140,7 @@ bool DepSubstrate(const pkgCache::VerIterator &iterator) {
                 [self _reloadData];
             else {
                 Queuing_ = true;
-                [buttonbar_ setBadgeValue:UCLocalize("Q_D") forButton:4];
+                [[[toolbar_ items] objectAtIndex:3] setBadgeValue:UCLocalize("Q_D")];
                 [book_ reloadData];
             }
 
@@ -8120,38 +8173,10 @@ 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;
-
-        [sheet dismiss];
-
-        if (reset)
-            [self updateData];
-        else
-            [self finish];
     } else if ([context isEqualToString:@"upgrade"]) {
         switch (button) {
             case 1:
@@ -8172,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 {
@@ -8202,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];
@@ -8220,24 +8250,15 @@ bool DepSubstrate(const pkgCache::VerIterator &iterator) {
         [view setPackage:package];
         return view;
     } else {
-        UIActionSheet *sheet = [[[UIActionSheet alloc]
-            initWithTitle:UCLocalize("CANNOT_LOCATE_PACKAGE")
-            buttons:[NSArray arrayWithObjects:UCLocalize("CLOSE"), nil]
-            defaultButtonIndex:0
-            delegate:self
-            context:@"missing"
-        ] autorelease];
-
-        [sheet setBodyText:[NSString stringWithFormat:UCLocalize("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/"])
@@ -8289,41 +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 {
     [BrowserView _initialize];
 
-    _trace();
+    [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];
@@ -8331,37 +8358,120 @@ bool DepSubstrate(const pkgCache::VerIterator &iterator) {
     if (
         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("/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) {
@@ -8382,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);
@@ -8442,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");
@@ -8470,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);
@@ -8500,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);
@@ -8530,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;
@@ -8542,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)
@@ -8549,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"])
@@ -8557,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];
@@ -8576,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)
@@ -8601,13 +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 || access("/tmp/.cydia.fw", 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();
@@ -8627,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();
 
@@ -8647,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");