X-Git-Url: https://git.saurik.com/cydia.git/blobdiff_plain/be45a862ee5609d427a51b20d04599ce902fb52c..68bd7c60c69be8fbf1d8a5ef7dc8ca62883351a5:/MobileCydia.mm diff --git a/MobileCydia.mm b/MobileCydia.mm index ce12ef64..d8f39d7b 100644 --- a/MobileCydia.mm +++ b/MobileCydia.mm @@ -66,6 +66,8 @@ #include +#include + #include #include @@ -119,19 +121,22 @@ extern "C" { #include #include +#include "Sources.h" +#include #include "Menes/Menes.h" #include "CyteKit/PerlCompatibleRegEx.hpp" +#include "CyteKit/TableViewCell.h" #include "CyteKit/WebScriptObject-Cyte.h" #include "CyteKit/WebViewController.h" #include "CyteKit/stringWithUTF8Bytes.h" +#include "Cydia/MIMEAddress.h" +#include "Cydia/LoadingViewController.h" #include "Cydia/ProgressEvent.h" #include "SDURLCache/SDURLCache.h" - -#include /* }}} */ /* Profiler {{{ */ @@ -204,16 +209,7 @@ void PrintTimes() { #define _end } /* }}} */ -#define _pooled _H _pool([[NSAutoreleasePool alloc] init], true); - -#define CYPoolStart() \ - NSAutoreleasePool *_pool([[NSAutoreleasePool alloc] init]); \ - do -#define CYPoolEnd() \ - while (false); \ - [_pool release]; - -#define Cydia_ CYDIA_VERSION +extern NSString *Cydia_; #define lprintf(args...) fprintf(stderr, args) @@ -251,6 +247,11 @@ union SplitHash { }; // }}} +static NSString *Colon_; +NSString *Elision_; +static NSString *Error_; +static NSString *Warning_; + static const NSUInteger UIViewAutoresizingFlexibleBoth(UIViewAutoresizingFlexibleWidth | UIViewAutoresizingFlexibleHeight); static _finline NSString *CydiaURL(NSString *path) { @@ -264,6 +265,15 @@ static _finline NSString *CydiaURL(NSString *path) { return [[NSString stringWithUTF8String:page] stringByAppendingString:path]; } +static void ReapZombie(pid_t pid) { + int status; + wait: + if (waitpid(pid, &status, 0) == -1) + if (errno == EINTR) + goto wait; + else _assert(false); +} + static _finline void UpdateExternalStatus(uint64_t newStatus) { int notify_token; if (notify_register_check("com.saurik.Cydia.status", ¬ify_token) == NOTIFY_STATUS_OK) { @@ -273,88 +283,16 @@ static _finline void UpdateExternalStatus(uint64_t newStatus) { notify_post("com.saurik.Cydia.status"); } +static CGFloat CYStatusBarHeight() { + CGSize size([[UIApplication sharedApplication] statusBarFrame].size); + return UIInterfaceOrientationIsPortrait([[UIApplication sharedApplication] statusBarOrientation]) ? size.height : size.width; +} + /* NSForcedOrderingSearch doesn't work on the iPhone */ static const NSStringCompareOptions MatchCompareOptions_ = NSLiteralSearch | NSCaseInsensitiveSearch; static const NSStringCompareOptions LaxCompareOptions_ = NSNumericSearch | NSDiacriticInsensitiveSearch | NSWidthInsensitiveSearch | NSCaseInsensitiveSearch; static const CFStringCompareFlags LaxCompareFlags_ = kCFCompareCaseInsensitive | kCFCompareNonliteral | kCFCompareLocalized | kCFCompareNumerically | kCFCompareWidthInsensitive | kCFCompareForcedOrdering; -/* Radix Sort {{{ */ -typedef uint32_t (*SKRadixFunction)(id, void *); - -@interface NSMutableArray (Radix) -- (void) radixSortUsingFunction:(SKRadixFunction)function withContext:(void *)argument; -@end - -struct RadixItem_ { - size_t index; - uint32_t key; -}; - -@implementation NSMutableArray (Radix) - -- (void) radixSortUsingFunction:(SKRadixFunction)function withContext:(void *)argument { - size_t count([self count]); - struct RadixItem_ *swap(new RadixItem_[count * 2]); - - for (size_t i(0); i != count; ++i) { - RadixItem_ &item(swap[i]); - item.index = i; - - id object([self objectAtIndex:i]); - item.key = function(object, argument); - } - - struct RadixItem_ *lhs(swap), *rhs(swap + count); - - static const size_t width = 32; - static const size_t bits = 11; - static const size_t slots = 1 << bits; - static const size_t passes = (width + (bits - 1)) / bits; - - size_t *hist(new size_t[slots]); - - for (size_t pass(0); pass != passes; ++pass) { - memset(hist, 0, sizeof(size_t) * slots); - - for (size_t i(0); i != count; ++i) { - uint32_t key(lhs[i].key); - key >>= pass * bits; - key &= _not(uint32_t) >> width - bits; - ++hist[key]; - } - - size_t offset(0); - for (size_t i(0); i != slots; ++i) { - size_t local(offset); - offset += hist[i]; - hist[i] = local; - } - - for (size_t i(0); i != count; ++i) { - uint32_t key(lhs[i].key); - key >>= pass * bits; - key &= _not(uint32_t) >> width - bits; - rhs[hist[key]++] = lhs[i]; - } - - RadixItem_ *tmp(lhs); - lhs = rhs; - rhs = tmp; - } - - delete [] hist; - - const void **values(new const void *[count]); - for (size_t i(0); i != count; ++i) - values[i] = [self objectAtIndex:lhs[i].index]; - CFArrayReplaceValues((CFMutableArrayRef) self, CFRangeMake(0, count), values, count); - delete [] values; - - delete [] swap; -} - -@end -/* }}} */ /* Insertion Sort {{{ */ CFIndex SKBSearch_(const void *element, CFIndex elementSize, const void *list, CFIndex count, CFComparatorFunction comparator, void *context) { @@ -475,7 +413,6 @@ NSUInteger DOMNodeList$countByEnumeratingWithState$objects$count$(DOMNodeList *s /* Cydia NSString Additions {{{ */ @interface NSString (Cydia) - (NSComparisonResult) compareByPath:(NSString *)other; -- (NSString *) stringByCachingURLWithCurrentCDN; - (NSString *) stringByAddingPercentEscapesIncludingReserved; @end @@ -511,13 +448,6 @@ NSUInteger DOMNodeList$countByEnumeratingWithState$objects$count$(DOMNodeList *s return result == NSOrderedSame ? value : result; } -- (NSString *) stringByCachingURLWithCurrentCDN { - return [self - stringByReplacingOccurrencesOfString:@"://cydia.saurik.com/" - withString:@"://cache.cydia.saurik.com/" - ]; -} - - (NSString *) stringByAddingPercentEscapesIncludingReserved { return [(id)CFURLCreateStringByAddingPercentEscapes( kCFAllocatorDefault, @@ -674,74 +604,6 @@ struct NSStringMapEqual : }; /* }}} */ -/* Mime Addresses {{{ */ -@interface Address : NSObject { - _H name_; - _H address_; -} - -- (NSString *) name; -- (NSString *) address; - -- (void) setAddress:(NSString *)address; - -+ (Address *) addressWithString:(NSString *)string; -- (Address *) initWithString:(NSString *)string; - -@end - -@implementation Address - -- (NSString *) name { - return name_; -} - -- (NSString *) address { - return address_; -} - -- (void) setAddress:(NSString *)address { - address_ = address; -} - -+ (Address *) addressWithString:(NSString *)string { - return [[[Address alloc] initWithString:string] autorelease]; -} - -+ (NSArray *) _attributeKeys { - return [NSArray arrayWithObjects: - @"address", - @"name", - nil]; -} - -- (NSArray *) attributeKeys { - return [[self class] _attributeKeys]; -} - -+ (BOOL) isKeyExcludedFromWebScript:(const char *)name { - return ![[self _attributeKeys] containsObject:[NSString stringWithUTF8String:name]] && [super isKeyExcludedFromWebScript:name]; -} - -- (Address *) initWithString:(NSString *)string { - if ((self = [super init]) != nil) { - const char *data = [string UTF8String]; - size_t size = [string length]; - - static Pcre address_r("^\"?(.*)\"? <([^>]*)>$"); - - if (address_r(data, size)) { - name_ = address_r[1]; - address_ = address_r[2]; - } else { - name_ = string; - address_ = nil; - } - } return self; -} - -@end -/* }}} */ /* CoreGraphics Primitives {{{ */ class CYColor { private: @@ -823,16 +685,15 @@ static _H Font18Bold_; static _H Font22Bold_; static const char *Machine_ = NULL; -static NSString *System_ = nil; +static _H System_; static NSString *SerialNumber_ = nil; static NSString *ChipID_ = nil; static NSString *BBSNum_ = nil; static _H Token_; static NSString *UniqueID_ = nil; -static NSString *PLMN_ = nil; -static NSString *Build_ = nil; -static NSString *Product_ = nil; -static NSString *Safari_ = nil; +static _H UserAgent_; +static _H Product_; +static _H Safari_; static CFLocaleRef Locale_; static NSArray *Languages_; @@ -843,19 +704,26 @@ static NSMutableDictionary *Metadata_; static _transient NSMutableDictionary *Settings_; static _transient NSString *Role_; static _transient NSMutableDictionary *Packages_; +static _transient NSMutableDictionary *Values_; static _transient NSMutableDictionary *Sections_; -static _transient NSMutableDictionary *Sources_; -static bool Changed_; +_H Sources_; +static _transient NSNumber *Version_; +bool Changed_; static time_t now_; bool IsWildcat_; static CGFloat ScreenScale_; static NSString *Idiom_; +static _H Firmware_; +static NSString *Major_; static _H SessionData_; static _H HostConfig_; static _H BridgedHosts_; +static _H TokenHosts_; +static _H InsecureHosts_; static _H PipelinedHosts_; +static _H CachedURLs_; static NSString *kCydiaProgressEventTypeError = @"Error"; static NSString *kCydiaProgressEventTypeInformation = @"Information"; @@ -928,7 +796,7 @@ bool isSectionVisible(NSString *section) { return hidden == nil || ![hidden boolValue]; } -static id CYIOGetValue(const char *path, NSString *property) { +static NSObject *CYIOGetValue(const char *path, NSString *property) { io_registry_entry_t entry(IORegistryEntryFromPath(kIOMasterPortDefault, path)); if (entry == MACH_PORT_NULL) return nil; @@ -941,7 +809,7 @@ static id CYIOGetValue(const char *path, NSString *property) { return [(id) value autorelease]; } -static NSString *CYHex(NSData *data, bool reverse) { +static NSString *CYHex(NSData *data, bool reverse = false) { if (data == nil) return nil; @@ -972,6 +840,8 @@ static NSString *CYHex(NSData *data, bool reverse) { @class CYPackageController; @protocol CydiaDelegate +- (void) returnToCydia; +- (void) saveState; - (void) retainNetworkActivityIndicator; - (void) releaseNetworkActivityIndicator; - (void) clearPackage:(Package *)package; @@ -984,6 +854,7 @@ static NSString *CYHex(NSData *data, bool reverse) { - (void) loadData; - (void) updateData; - (void) syncData; +- (void) addSource:(NSDictionary *)source; - (void) addTrivialSource:(NSString *)href; - (void) showSettings; - (UIProgressHUD *) addProgressHUD; @@ -1022,6 +893,7 @@ class Status : } virtual void IMSHit(pkgAcquire::ItemDesc &item) { + Done(item); } virtual void Fetch(pkgAcquire::ItemDesc &item) { @@ -1031,6 +903,9 @@ class Status : } virtual void Done(pkgAcquire::ItemDesc &item) { + NSString *name([NSString stringWithUTF8String:item.ShortDesc.c_str()]); + CydiaProgressEvent *event([CydiaProgressEvent eventWithMessage:[NSString stringWithFormat:Colon_, UCLocalize("DONE"), name] ofType:kCydiaProgressEventTypeStatus forItem:item]); + [delegate_ performSelectorOnMainThread:@selector(addProgressEvent:) withObject:event waitUntilDone:YES]; } virtual void Fail(pkgAcquire::ItemDesc &item) { @@ -1405,6 +1280,10 @@ static void PackageImport(const void *key, const void *value, void *context) { /* Source Class {{{ */ @interface Source : NSObject { + unsigned era_; + Database *database_; + metaIndex *index_; + CYString depiction_; CYString description_; CYString label_; @@ -1414,6 +1293,7 @@ static void PackageImport(const void *key, const void *value, void *context) { CYString uri_; CYString distribution_; CYString type_; + CYString base_; CYString version_; _H host_; @@ -1425,9 +1305,9 @@ static void PackageImport(const void *key, const void *value, void *context) { BOOL trusted_; } -- (Source *) initWithMetaIndex:(metaIndex *)index inPool:(apr_pool_t *)pool; +- (Source *) initWithMetaIndex:(metaIndex *)index forDatabase:(Database *)database inPool:(apr_pool_t *)pool; -- (NSComparisonResult) compareByNameAndType:(Source *)source; +- (NSComparisonResult) compareByName:(Source *)source; - (NSString *) depictionForPackage:(NSString *)package; - (NSString *) supportForPackage:(NSString *)package; @@ -1435,9 +1315,10 @@ static void PackageImport(const void *key, const void *value, void *context) { - (NSDictionary *) record; - (BOOL) trusted; -- (NSString *) uri; +- (NSString *) rooturi; - (NSString *) distribution; - (NSString *) type; + - (NSString *) key; - (NSString *) host; @@ -1448,6 +1329,7 @@ static void PackageImport(const void *key, const void *value, void *context) { - (NSString *) version; - (NSString *) defaultIcon; +- (NSURL *) iconURL; @end @@ -1458,6 +1340,8 @@ static void PackageImport(const void *key, const void *value, void *context) { distribution_.clear(); type_.clear(); + base_.clear(); + description_.clear(); label_.clear(); origin_.clear(); @@ -1471,18 +1355,39 @@ static void PackageImport(const void *key, const void *value, void *context) { authority_ = nil; } ++ (NSString *) webScriptNameForSelector:(SEL)selector { + if (false); + else if (selector == @selector(addSection:)) + return @"addSection"; + else if (selector == @selector(getField:)) + return @"getField"; + else if (selector == @selector(removeSection:)) + return @"removeSection"; + else if (selector == @selector(remove)) + return @"remove"; + else + return nil; +} + ++ (BOOL) isSelectorExcludedFromWebScript:(SEL)selector { + return [self webScriptNameForSelector:selector] == nil; +} + + (NSArray *) _attributeKeys { return [NSArray arrayWithObjects: + @"baseuri", @"distribution", @"host", @"key", + @"iconuri", @"label", @"name", @"origin", + @"rooturi", + @"sections", @"shortDescription", @"trusted", @"type", - @"uri", @"version", nil]; } @@ -1506,6 +1411,8 @@ static void PackageImport(const void *key, const void *value, void *context) { debReleaseIndex *dindex(dynamic_cast(index)); if (dindex != NULL) { + base_.set(pool, dindex->MetaIndexURI("")); + FileFd fd; if (!fd.Open(dindex->MetaIndexFile("Release"), FileFd::ReadOnly)) _error->Discard(); @@ -1548,25 +1455,49 @@ static void PackageImport(const void *key, const void *value, void *context) { host_ = [host_ lowercaseString]; if (host_ != nil) - // XXX: this is due to a bug in _H<> - authority_ = (id) host_; + authority_ = host_; else authority_ = [url path]; } -- (Source *) initWithMetaIndex:(metaIndex *)index inPool:(apr_pool_t *)pool { +- (Source *) initWithMetaIndex:(metaIndex *)index forDatabase:(Database *)database inPool:(apr_pool_t *)pool { if ((self = [super init]) != nil) { + era_ = [database era]; + database_ = database; + index_ = index; + [self setMetaIndex:index inPool:pool]; } return self; } -- (NSComparisonResult) compareByNameAndType:(Source *)source { - NSDictionary *lhr = [self record]; - NSDictionary *rhr = [source record]; +- (NSString *) getField:(NSString *)name { +@synchronized (database_) { + if ([database_ era] != era_ || index_ == NULL) + return nil; + + debReleaseIndex *dindex(dynamic_cast(index_)); + if (dindex == NULL) + return nil; + + FileFd fd; + if (!fd.Open(dindex->MetaIndexFile("Release"), FileFd::ReadOnly)) { + _error->Discard(); + return nil; + } + + pkgTagFile tags(&fd); + + pkgTagSection section; + tags.Step(section); - if (lhr != rhr) - return lhr == nil ? NSOrderedDescending : NSOrderedAscending; + const char *start, *end; + if (!section.Find([name UTF8String], start, end)) + return (NSString *) [NSNull null]; + + return [NSString stringWithString:[(NSString *) CYStringCreate(start, end - start) autorelease]]; +} } +- (NSComparisonResult) compareByName:(Source *)source { NSString *lhs = [self name]; NSString *rhs = [source name]; @@ -1591,6 +1522,62 @@ static void PackageImport(const void *key, const void *value, void *context) { return support_.empty() ? nil : [static_cast(support_) stringByReplacingOccurrencesOfString:@"*" withString:package]; } +- (NSArray *) sections { + return record_ == nil ? (id) [NSNull null] : [record_ objectForKey:@"Sections"] ?: [NSArray array]; +} + +- (void) _addSection:(NSString *)section { + if (record_ == nil) + return; + else if (NSMutableArray *sections = [record_ objectForKey:@"Sections"]) { + if (![sections containsObject:section]) { + [sections addObject:section]; + Changed_ = true; + } + } else { + [record_ setObject:[NSMutableArray arrayWithObject:section] forKey:@"Sections"]; + Changed_ = true; + } +} + +- (bool) addSection:(NSString *)section { + if (record_ == nil) + return false; + + [self performSelectorOnMainThread:@selector(_addSection:) withObject:section waitUntilDone:NO]; + return true; +} + +- (void) _removeSection:(NSString *)section { + if (record_ == nil) + return; + + if (NSMutableArray *sections = [record_ objectForKey:@"Sections"]) + if ([sections containsObject:section]) { + [sections removeObject:section]; + Changed_ = true; + } +} + +- (bool) removeSection:(NSString *)section { + if (record_ == nil) + return false; + + [self performSelectorOnMainThread:@selector(_removeSection:) withObject:section waitUntilDone:NO]; + return true; +} + +- (void) _remove { + [Sources_ removeObjectForKey:[self key]]; + Changed_ = true; +} + +- (bool) remove { + bool value(record_ != nil); + [self performSelectorOnMainThread:@selector(_remove) withObject:nil waitUntilDone:NO]; + return value; +} + - (NSDictionary *) record { return record_; } @@ -1599,7 +1586,7 @@ static void PackageImport(const void *key, const void *value, void *context) { return trusted_; } -- (NSString *) uri { +- (NSString *) rooturi { return uri_; } @@ -1611,6 +1598,23 @@ static void PackageImport(const void *key, const void *value, void *context) { return type_; } +- (NSString *) baseuri { + return base_.empty() ? nil : (id) base_; +} + +- (NSString *) iconuri { + if (NSString *base = [self baseuri]) + return [base stringByAppendingString:@"CydiaIcon.png"]; + + return nil; +} + +- (NSURL *) iconURL { + if (NSString *uri = [self iconuri]) + return [NSURL URLWithString:uri]; + return nil; +} + - (NSString *) key { return [NSString stringWithFormat:@"%@:%@:%@", (NSString *) type_, (NSString *) uri_, (NSString *) distribution_]; } @@ -1803,8 +1807,10 @@ static void PackageImport(const void *key, const void *value, void *context) { /* }}} */ /* Package Class {{{ */ struct ParsedPackage { + CYString md5sum_; CYString tagline_; + CYString architecture_; CYString icon_; CYString depiction_; @@ -1818,14 +1824,17 @@ struct ParsedPackage { }; @interface Package : NSObject { - uint32_t era_ : 26; + uint32_t era_ : 25; uint32_t role_ : 3; uint32_t essential_ : 1; uint32_t obsolete_ : 1; uint32_t ignored_ : 1; + uint32_t pooled_ : 1; apr_pool_t *pool_; + uint32_t rank_; + _transient Database *database_; pkgCache::VerIterator version_; @@ -1863,7 +1872,7 @@ struct ParsedPackage { - (NSString *) uri; -- (Address *) maintainer; +- (MIMEAddress *) maintainer; - (size_t) size; - (NSString *) longDescription; - (NSString *) shortDescription; @@ -1899,7 +1908,7 @@ struct ParsedPackage { - (UIImage *) icon; - (NSString *) homepage; - (NSString *) depiction; -- (Address *) author; +- (MIMEAddress *) author; - (NSString *) support; @@ -1909,7 +1918,8 @@ struct ParsedPackage { - (Source *) source; -- (BOOL) matches:(NSString *)text; +- (uint32_t) rank; +- (BOOL) matches:(NSArray *)query; - (bool) hasSupportingRole; - (BOOL) hasTag:(NSString *)tag; @@ -1926,7 +1936,7 @@ struct ParsedPackage { - (void) install; - (void) remove; -- (bool) isUnfilteredAndSearchedForBy:(NSString *)search; +- (bool) isUnfilteredAndSearchedForBy:(NSArray *)query; - (bool) isUnfilteredAndSelectedForBy:(NSString *)search; - (bool) isInstalledAndUnfiltered:(NSNumber *)number; - (bool) isVisibleInSection:(NSString *)section; @@ -2066,6 +2076,8 @@ struct PackageNameOrdering : } - (void) dealloc { + if (!pooled_) + apr_pool_destroy(pool_); if (parsed_ != NULL) delete parsed_; [super dealloc]; @@ -2094,6 +2106,7 @@ struct PackageNameOrdering : + (NSArray *) _attributeKeys { return [NSArray arrayWithObjects: @"applications", + @"architecture", @"author", @"depiction", @"essential", @@ -2105,6 +2118,7 @@ struct PackageNameOrdering : @"longDescription", @"longSection", @"maintainer", + @"md5sum", @"mode", @"name", @"purposes", @@ -2140,6 +2154,12 @@ struct PackageNameOrdering : return relations; } } +- (NSString *) architecture { + [self parse]; +@synchronized (database_) { + return parsed_->architecture_.empty() ? [NSNull null] : (id) parsed_->architecture_; +} } + - (NSString *) getField:(NSString *)name { @synchronized (database_) { if ([database_ era] != era_ || file_.end()) @@ -2151,7 +2171,7 @@ struct PackageNameOrdering : if (!parser.Find([name UTF8String], start, end)) return (NSString *) [NSNull null]; - return [(NSString *) CYStringCreate(start, end - start) autorelease]; + return [NSString stringWithString:[(NSString *) CYStringCreate(start, end - start) autorelease]]; } } - (void) parse { @@ -2178,6 +2198,7 @@ struct PackageNameOrdering : const char *name_; CYString *value_; } names[] = { + {"architecture", &parsed->architecture_}, {"icon", &parsed->icon_}, {"depiction", &parsed->depiction_}, {"homepage", &parsed->homepage_}, @@ -2186,6 +2207,7 @@ struct PackageNameOrdering : {"support", &parsed->support_}, {"sponsor", &parsed->sponsor_}, {"author", &parsed->author_}, + {"md5sum", &parsed->md5sum_}, }; for (size_t i(0); i != sizeof(names) / sizeof(names[0]); ++i) { @@ -2224,7 +2246,12 @@ struct PackageNameOrdering : - (Package *) initWithVersion:(pkgCache::VerIterator)version withZone:(NSZone *)zone inPool:(apr_pool_t *)pool database:(Database *)database { if ((self = [super init]) != nil) { _profile(Package$initWithVersion) - pool_ = pool; + if (pool == NULL) + apr_pool_create(&pool_, NULL); + else { + pool_ = pool; + pooled_ = true; + } database_ = database; era_ = [database era]; @@ -2405,16 +2432,20 @@ struct PackageNameOrdering : #endif } -- (Address *) maintainer { +- (MIMEAddress *) maintainer { @synchronized (database_) { if ([database_ era] != era_ || file_.end()) return nil; pkgRecords::Parser *parser = &[database_ records]->Lookup(file_); const std::string &maintainer(parser->Maintainer()); - return maintainer.empty() ? nil : [Address addressWithString:[NSString stringWithUTF8String:maintainer.c_str()]]; + return maintainer.empty() ? nil : [MIMEAddress addressWithString:[NSString stringWithUTF8String:maintainer.c_str()]]; } } +- (NSString *) md5sum { + return parsed_ == NULL ? nil : (id) parsed_->md5sum_; +} + - (size_t) size { @synchronized (database_) { if ([database_ era] != era_ || version_.end()) @@ -2446,8 +2477,29 @@ struct PackageNameOrdering : } } - (NSString *) shortDescription { - return parsed_ == NULL ? nil : static_cast(parsed_->tagline_); -} + if (parsed_ != NULL) + return static_cast(parsed_->tagline_); + +@synchronized (database_) { + pkgRecords::Parser &parser([database_ records]->Lookup(file_)); + + const char *start, *end; + if (!parser.ShortDesc(start, end)) + return nil; + + if (end - start > 200) + end = start + 200; + + /* + if (const char *stop = reinterpret_cast(memchr(start, '\n', end - start))) + end = stop; + + while (end != start && end[-1] == '\r') + --end; + */ + + return [(id) CYStringCreate(start, end - start) autorelease]; +} } - (unichar) index { _profile(Package$index) @@ -2566,11 +2618,19 @@ struct PackageNameOrdering : } - (BOOL) hasMode { +@synchronized (database_) { + if ([database_ era] != era_ || iterator_.end()) + return nil; + pkgDepCache::StateCache &state([database_ cache][iterator_]); return state.Mode != pkgDepCache::ModeKeep; -} +} } - (NSString *) mode { +@synchronized (database_) { + if ([database_ era] != era_ || iterator_.end()) + return nil; + pkgDepCache::StateCache &state([database_ cache][iterator_]); switch (state.Mode) { @@ -2602,7 +2662,7 @@ struct PackageNameOrdering : } _nodefault } -} +} } - (NSString *) id { return id_; @@ -2619,14 +2679,12 @@ struct PackageNameOrdering : if (parsed_ != NULL) if (NSString *href = parsed_->icon_) if ([href hasPrefix:@"file:///"]) - // XXX: correct escaping - icon = [UIImage imageAtPath:[href substringFromIndex:7]]; + icon = [UIImage imageAtPath:[[href substringFromIndex:7] stringByReplacingPercentEscapesUsingEncoding:NSUTF8StringEncoding]]; if (icon == nil) if (section != nil) - icon = [UIImage imageAtPath:[NSString stringWithFormat:@"%@/Sections/%@.png", App_, section]]; + icon = [UIImage imageAtPath:[NSString stringWithFormat:@"%@/Sections/%@.png", App_, [section stringByReplacingOccurrencesOfString:@" " withString:@"_"]]]; if (icon == nil) if (Source *source = [self source]) if (NSString *dicon = [source defaultIcon]) if ([dicon hasPrefix:@"file:///"]) - // XXX: correct escaping - icon = [UIImage imageAtPath:[dicon substringFromIndex:7]]; + icon = [UIImage imageAtPath:[[dicon substringFromIndex:7] stringByReplacingPercentEscapesUsingEncoding:NSUTF8StringEncoding]]; if (icon == nil) icon = [UIImage applicationImageNamed:@"unknown.png"]; return icon; @@ -2640,12 +2698,12 @@ struct PackageNameOrdering : return parsed_ != NULL && !parsed_->depiction_.empty() ? parsed_->depiction_ : [[self source] depictionForPackage:id_]; } -- (Address *) sponsor { - return parsed_ == NULL || parsed_->sponsor_.empty() ? nil : [Address addressWithString:parsed_->sponsor_]; +- (MIMEAddress *) sponsor { + return parsed_ == NULL || parsed_->sponsor_.empty() ? nil : [MIMEAddress addressWithString:parsed_->sponsor_]; } -- (Address *) author { - return parsed_ == NULL || parsed_->author_.empty() ? nil : [Address addressWithString:parsed_->author_]; +- (MIMEAddress *) author { + return parsed_ == NULL || parsed_->author_.empty() ? nil : [MIMEAddress addressWithString:parsed_->author_]; } - (NSString *) support { @@ -2813,30 +2871,51 @@ struct PackageNameOrdering : return source_ == (Source *) [NSNull null] ? nil : source_; } -- (BOOL) matches:(NSString *)text { - if (text == nil) +- (uint32_t) rank { + return rank_; +} + +- (BOOL) matches:(NSArray *)query { + if (query == nil || [query count] == 0) return NO; + rank_ = 0; + + NSString *string; NSRange range; + NSUInteger length; - range = [[self id] rangeOfString:text options:MatchCompareOptions_]; - if (range.location != NSNotFound) - return YES; + string = [self name]; + length = [string length]; - range = [[self name] rangeOfString:text options:MatchCompareOptions_]; - if (range.location != NSNotFound) - return YES; + for (NSString *term in query) { + range = [string rangeOfString:term options:MatchCompareOptions_]; + if (range.location != NSNotFound) + rank_ -= 6 * 1000000 / length; + } - [self parse]; + if (rank_ == 0) { + string = [self id]; + length = [string length]; - NSString *description([self shortDescription]); - NSUInteger length([description length]); + for (NSString *term in query) { + range = [string rangeOfString:term options:MatchCompareOptions_]; + if (range.location != NSNotFound) + rank_ -= 6 * 1000000 / length; + } + } - range = [[self shortDescription] rangeOfString:text options:MatchCompareOptions_ range:NSMakeRange(0, std::min(length, 100))]; - if (range.location != NSNotFound) - return YES; + string = [self shortDescription]; + length = [string length]; + NSUInteger stop(std::min(length, 200)); - return NO; + for (NSString *term in query) { + range = [string rangeOfString:term options:MatchCompareOptions_ range:NSMakeRange(0, stop)]; + if (range.location != NSNotFound) + rank_ -= 2 * 100000; + } + + return rank_ != 0; } - (bool) hasSupportingRole { @@ -2940,7 +3019,7 @@ struct PackageNameOrdering : cache->MarkDelete(iterator_, true); } } -- (bool) isUnfilteredAndSearchedForBy:(NSString *)search { +- (bool) isUnfilteredAndSearchedForBy:(NSArray *)query { _profile(Package$isUnfilteredAndSearchedForBy) bool value(true); @@ -2949,7 +3028,7 @@ struct PackageNameOrdering : _end _profile(Package$isUnfilteredAndSearchedForBy$Match) - value &= [self matches:search]; + value &= [self matches:query]; _end return value; @@ -3107,10 +3186,14 @@ struct PackageNameOrdering : @end /* }}} */ -static NSString *Colon_; -static NSString *Elision_; -static NSString *Error_; -static NSString *Warning_; +class CydiaLogCleaner : + public pkgArchiveCleaner +{ + protected: + virtual void Erase(const char *File, std::string Pkg, std::string Ver, struct stat &St) { + unlink(File); + } +}; /* Database Implementation {{{ */ @implementation Database @@ -3140,7 +3223,7 @@ static NSString *Warning_; [super dealloc]; } -- (void) _readCydia:(NSNumber *)fd { _pooled +- (void) _readCydia:(NSNumber *)fd { __gnu_cxx::stdio_filebuf ib([fd intValue], std::ios::in); std::istream is(&ib); std::string line; @@ -3148,6 +3231,8 @@ static NSString *Warning_; static Pcre finish_r("^finish:([^:]*)$"); while (std::getline(is, line)) { + NSAutoreleasePool *pool([[NSAutoreleasePool alloc] init]); + const char *data(line.c_str()); size_t size = line.size(); lprintf("C:%s\n", data); @@ -3158,12 +3243,14 @@ static NSString *Warning_; if (index != INT_MAX && index > Finish_) Finish_ = index; } + + [pool release]; } _assume(false); } -- (void) _readStatus:(NSNumber *)fd { _pooled +- (void) _readStatus:(NSNumber *)fd { __gnu_cxx::stdio_filebuf ib([fd intValue], std::ios::in); std::istream is(&ib); std::string line; @@ -3172,6 +3259,8 @@ static NSString *Warning_; static Pcre pmstatus_r("^([^:]*):([^:]*):([^:]*):(.*)$"); while (std::getline(is, line)) { + NSAutoreleasePool *pool([[NSAutoreleasePool alloc] init]); + const char *data(line.c_str()); size_t size(line.size()); lprintf("S:%s\n", data); @@ -3211,21 +3300,27 @@ static NSString *Warning_; lprintf("E:unknown pmstatus\n"); } else lprintf("E:unknown status\n"); + + [pool release]; } _assume(false); } -- (void) _readOutput:(NSNumber *)fd { _pooled +- (void) _readOutput:(NSNumber *)fd { __gnu_cxx::stdio_filebuf ib([fd intValue], std::ios::in); std::istream is(&ib); std::string line; while (std::getline(is, line)) { + NSAutoreleasePool *pool([[NSAutoreleasePool alloc] init]); + lprintf("O:%s\n", line.c_str()); CydiaProgressEvent *event([CydiaProgressEvent eventWithMessage:[NSString stringWithUTF8String:line.c_str()] ofType:kCydiaProgressEventTypeInformation]); [progress_ performSelectorOnMainThread:@selector(addProgressEvent:) withObject:event waitUntilDone:YES]; + + [pool release]; } _assume(false); @@ -3236,11 +3331,13 @@ static NSString *Warning_; } - (Package *) packageWithName:(NSString *)name { + if (name == nil) + return nil; @synchronized (self) { if (static_cast(cache_) == NULL) return nil; pkgCache::PkgIterator iterator(cache_->FindPkg([name UTF8String])); - return iterator.end() ? nil : [Package packageWithIterator:iterator withZone:NULL inPool:pool_ database:self]; + return iterator.end() ? nil : [Package packageWithIterator:iterator withZone:NULL inPool:NULL database:self]; } } - (id) init { @@ -3361,6 +3458,10 @@ static NSString *Warning_; lprintf("%c:[%s]\n", warning ? 'W' : 'E', error.c_str()); + static Pcre no_pubkey("^GPG error:.* NO_PUBKEY .*$"); + if (warning && no_pubkey(error.c_str())) + continue; + [delegate_ addProgressEventOnMainThread:[CydiaProgressEvent eventWithMessage:[NSString stringWithUTF8String:error.c_str()] ofType:(warning ? kCydiaProgressEventTypeWarning : kCydiaProgressEventTypeError)] forTask:title]; } @@ -3371,7 +3472,7 @@ static NSString *Warning_; return [self popErrorWithTitle:title] || !success; } -- (void) reloadDataWithInvocation:(NSInvocation *)invocation { CYPoolStart() { +- (void) reloadDataWithInvocation:(NSInvocation *)invocation { @synchronized (self) { ++era_; @@ -3474,7 +3575,7 @@ static NSString *Warning_; } for (pkgSourceList::const_iterator source = list_->begin(); source != list_->end(); ++source) { - Source *object([[[Source alloc] initWithMetaIndex:*source inPool:pool_] autorelease]); + Source *object([[[Source alloc] initWithMetaIndex:*source forDatabase:self inPool:pool_] autorelease]); [sourceList_ addObject:object]; std::vector *indices = (*source)->GetIndexFiles(); @@ -3507,9 +3608,9 @@ static NSString *Warning_; packages_ = [[NSArray alloc] initWithObjects:&packages.front() count:packages.size()]; _trace();*/ - [(NSMutableArray *) packages_ radixSortUsingFunction:reinterpret_cast(&PackagePrefixRadix) withContext:reinterpret_cast(16)]; - [(NSMutableArray *) packages_ radixSortUsingFunction:reinterpret_cast(&PackagePrefixRadix) withContext:reinterpret_cast(4)]; - [(NSMutableArray *) packages_ radixSortUsingFunction:reinterpret_cast(&PackagePrefixRadix) withContext:reinterpret_cast(0)]; + [(NSMutableArray *) packages_ radixSortUsingFunction:reinterpret_cast(&PackagePrefixRadix) withContext:reinterpret_cast(16)]; + [(NSMutableArray *) packages_ radixSortUsingFunction:reinterpret_cast(&PackagePrefixRadix) withContext:reinterpret_cast(4)]; + [(NSMutableArray *) packages_ radixSortUsingFunction:reinterpret_cast(&PackagePrefixRadix) withContext:reinterpret_cast(0)]; /*_trace(); PrintTimes(); @@ -3537,7 +3638,7 @@ static NSString *Warning_; _trace(); } -} } CYPoolEnd() _trace(); } +} } - (void) clear { @synchronized (self) { @@ -3574,15 +3675,7 @@ static NSString *Warning_; pkgAcquire fetcher; fetcher.Clean(_config->FindDir("Dir::Cache::Archives")); - class LogCleaner : - public pkgArchiveCleaner - { - protected: - virtual void Erase(const char *File, std::string Pkg, std::string Ver, struct stat &St) { - unlink(File); - } - } cleaner; - + CydiaLogCleaner cleaner; if ([self popErrorWithTitle:title forOperation:cleaner.Go(_config->FindDir("Dir::Cache::Archives") + "partial/", cache_)]) return false; @@ -3861,13 +3954,17 @@ static _H Diversions_; + (NSArray *) _attributeKeys { return [NSArray arrayWithObjects: @"bbsnum", + @"build", + @"coreFoundationVersionNumber", @"device", @"ecid", @"firmware", @"hostname", @"idiom", + @"mcc", + @"mnc", @"model", - @"plmn", + @"operator", @"role", @"serial", @"token", @@ -3884,7 +3981,15 @@ static _H Diversions_; } - (NSString *) version { - return @ Cydia_; + return Cydia_; +} + +- (NSString *) build { + return System_; +} + +- (NSString *) coreFoundationVersionNumber { + return [NSString stringWithFormat:@"%.2f", kCFCoreFoundationVersionNumber]; } - (NSString *) device { @@ -3903,17 +4008,31 @@ static _H Diversions_; return (id) Idiom_ ?: [NSNull null]; } -- (NSString *) plmn { - return (id) PLMN_ ?: [NSNull null]; +- (NSString *) mcc { + if (CFStringRef (*$CTSIMSupportCopyMobileSubscriberCountryCode)(CFAllocatorRef) = reinterpret_cast(dlsym(RTLD_DEFAULT, "CTSIMSupportCopyMobileSubscriberCountryCode"))) + return [(NSString *) (*$CTSIMSupportCopyMobileSubscriberCountryCode)(kCFAllocatorDefault) autorelease]; + return nil; } -- (NSString *) bbsnum { - return (id) BBSNum_ ?: [NSNull null]; +- (NSString *) mnc { + if (CFStringRef (*$CTSIMSupportCopyMobileSubscriberNetworkCode)(CFAllocatorRef) = reinterpret_cast(dlsym(RTLD_DEFAULT, "CTSIMSupportCopyMobileSubscriberNetworkCode"))) + return [(NSString *) (*$CTSIMSupportCopyMobileSubscriberNetworkCode)(kCFAllocatorDefault) autorelease]; + return nil; } -- (NSString *) ecid { - return (id) ChipID_ ?: [NSNull null]; -} +- (NSString *) operator { + if (CFStringRef (*$CTRegistrationCopyOperatorName)(CFAllocatorRef) = reinterpret_cast(dlsym(RTLD_DEFAULT, "CTRegistrationCopyOperatorName"))) + return [(NSString *) (*$CTRegistrationCopyOperatorName)(kCFAllocatorDefault) autorelease]; + return nil; +} + +- (NSString *) bbsnum { + return (id) BBSNum_ ?: [NSNull null]; +} + +- (NSString *) ecid { + return (id) ChipID_ ?: [NSNull null]; +} - (NSString *) serial { return SerialNumber_; @@ -3935,10 +4054,16 @@ static _H Diversions_; if (false); else if (selector == @selector(addBridgedHost:)) return @"addBridgedHost"; + else if (selector == @selector(addInsecureHost:)) + return @"addInsecureHost"; else if (selector == @selector(addInternalRedirect::)) return @"addInternalRedirect"; else if (selector == @selector(addPipelinedHost:scheme:)) return @"addPipelinedHost"; + else if (selector == @selector(addSource:::)) + return @"addSource"; + else if (selector == @selector(addTokenHost:)) + return @"addTokenHost"; else if (selector == @selector(addTrivialSource:)) return @"addTrivialSource"; else if (selector == @selector(close)) @@ -3955,12 +4080,18 @@ static _H Diversions_; return @"getKernelString"; else if (selector == @selector(getInstalledPackages)) return @"getInstalledPackages"; + else if (selector == @selector(getIORegistryEntry::)) + return @"getIORegistryEntry"; else if (selector == @selector(getLocaleIdentifier)) return @"getLocaleIdentifier"; else if (selector == @selector(getPreferredLanguages)) return @"getPreferredLanguages"; else if (selector == @selector(getPackageById:)) return @"getPackageById"; + else if (selector == @selector(getMetadataKeys)) + return @"getMetadataKeys"; + else if (selector == @selector(getMetadataValue:)) + return @"getMetadataValue"; else if (selector == @selector(getSessionValue:)) return @"getSessionValue"; else if (selector == @selector(installPackages:)) @@ -3973,6 +4104,10 @@ static _H Diversions_; return @"refreshSources"; else if (selector == @selector(removeButton)) return @"removeButton"; + else if (selector == @selector(saveConfig)) + return @"saveConfig"; + else if (selector == @selector(setMetadataValue::)) + return @"setMetadataValue"; else if (selector == @selector(setSessionValue::)) return @"setSessionValue"; else if (selector == @selector(substitutePackageNames:)) @@ -3999,6 +4134,10 @@ static _H Diversions_; return @"setPasteboardString"; else if (selector == @selector(setPasteboardURL:)) return @"setPasteboardURL"; + else if (selector == @selector(setScrollAlwaysBounceVertical:)) + return @"setScrollAlwaysBounceVertical"; + else if (selector == @selector(setScrollIndicatorStyle:)) + return @"setScrollIndicatorStyle"; else if (selector == @selector(setToken:)) return @"setToken"; else if (selector == @selector(setViewportWidth:)) @@ -4007,6 +4146,8 @@ static _H Diversions_; return @"statfs"; else if (selector == @selector(supports:)) return @"supports"; + else if (selector == @selector(unload)) + return @"unload"; else return nil; } @@ -4019,6 +4160,18 @@ static _H Diversions_; return [feature isEqualToString:@"window.open"]; } +- (void) unload { + [delegate_ performSelectorOnMainThread:@selector(unloadData) withObject:nil waitUntilDone:NO]; +} + +- (void) setScrollAlwaysBounceVertical:(NSNumber *)value { + [indirect_ performSelectorOnMainThread:@selector(setScrollAlwaysBounceVerticalNumber:) withObject:value waitUntilDone:NO]; +} + +- (void) setScrollIndicatorStyle:(NSString *)style { + [indirect_ performSelectorOnMainThread:@selector(setScrollIndicatorStyleWithName:) withObject:style waitUntilDone:NO]; +} + - (void) addInternalRedirect:(NSString *)from :(NSString *)to { [CydiaWebViewController performSelectorOnMainThread:@selector(addDiversion:) withObject:[[[Diversion alloc] initWithFrom:from to:to] autorelease] waitUntilDone:NO]; } @@ -4057,6 +4210,36 @@ static _H Diversions_; return [NSString stringWithCString:value]; } +- (NSObject *) getIORegistryEntry:(NSString *)path :(NSString *)entry { + NSObject *value(CYIOGetValue([path UTF8String], entry)); + + if (value != nil) + if ([value isKindOfClass:[NSData class]]) + value = CYHex((NSData *) value); + + return value; +} + +- (NSArray *) getMetadataKeys { +@synchronized (Values_) { + return [Values_ allKeys]; +} } + +- (id) getMetadataValue:(NSString *)key { +@synchronized (Values_) { + return [Values_ objectForKey:key]; +} } + +- (void) setMetadataValue:(NSString *)key :(NSString *)value { +@synchronized (Values_) { + if (value == nil || value == (id) [WebUndefined undefined] || value == (id) [NSNull null]) + [Values_ removeObjectForKey:key]; + else + [Values_ setObject:value forKey:key]; + + [delegate_ performSelectorOnMainThread:@selector(updateValues) withObject:nil waitUntilDone:YES]; +} } + - (id) getSessionValue:(NSString *)key { @synchronized (SessionData_) { return [SessionData_ objectForKey:key]; @@ -4075,6 +4258,16 @@ static _H Diversions_; [BridgedHosts_ addObject:host]; } } +- (void) addInsecureHost:(NSString *)host { +@synchronized (HostConfig_) { + [InsecureHosts_ addObject:host]; +} } + +- (void) addTokenHost:(NSString *)host { +@synchronized (HostConfig_) { + [TokenHosts_ addObject:host]; +} } + - (void) addPipelinedHost:(NSString *)host scheme:(NSString *)scheme { @synchronized (HostConfig_) { if (scheme != (id) [WebUndefined undefined]) @@ -4089,6 +4282,20 @@ static _H Diversions_; [indirect_ performSelectorOnMainThread:@selector(popViewControllerWithNumber:) withObject:value waitUntilDone:NO]; } +- (void) addSource:(NSString *)href :(NSString *)distribution :(WebScriptObject *)sections { + NSMutableArray *array([NSMutableArray arrayWithCapacity:[sections count]]); + + for (NSString *section in sections) + [array addObject:section]; + + [delegate_ performSelectorOnMainThread:@selector(addSource:) withObject:[NSMutableDictionary dictionaryWithObjectsAndKeys: + @"deb", @"Type", + href, @"URI", + distribution, @"Distribution", + array, @"Sections", + nil] waitUntilDone:NO]; +} + - (void) addTrivialSource:(NSString *)href { [delegate_ performSelectorOnMainThread:@selector(addTrivialSource:) withObject:href waitUntilDone:NO]; } @@ -4097,6 +4304,10 @@ static _H Diversions_; [delegate_ performSelectorOnMainThread:@selector(syncData) withObject:nil waitUntilDone:NO]; } +- (void) saveConfig { + [delegate_ performSelectorOnMainThread:@selector(_saveConfig) withObject:nil waitUntilDone:NO]; +} + - (NSArray *) getAllSources { return [[Database sharedInstance] sources]; } @@ -4175,12 +4386,7 @@ static _H Diversions_; fclose(du); } else _assert(close(fds[0])); - int status; - wait: - if (waitpid(pid, &status, 0) == -1) - if (errno == EINTR) - goto wait; - else _assert(false); + ReapZombie(pid); return value; } @@ -4293,121 +4499,24 @@ static _H Diversions_; @end /* }}} */ -/* @ Loading... Indicator {{{ */ -@interface CYLoadingIndicator : UIView { - _H spinner_; - _H label_; - _H container_; -} - -@property (readonly, nonatomic) UILabel *label; -@property (readonly, nonatomic) UIActivityIndicatorView *activityIndicatorView; - +@interface NSURL (CydiaSecure) @end -@implementation CYLoadingIndicator +@implementation NSURL (CydiaSecure) -- (id) initWithFrame:(CGRect)frame { - if ((self = [super initWithFrame:frame]) != nil) { - container_ = [[[UIView alloc] init] autorelease]; - [container_ setAutoresizingMask:UIViewAutoresizingFlexibleTopMargin | UIViewAutoresizingFlexibleLeftMargin | UIViewAutoresizingFlexibleRightMargin | UIViewAutoresizingFlexibleBottomMargin]; - - spinner_ = [[[UIActivityIndicatorView alloc] initWithActivityIndicatorStyle:UIActivityIndicatorViewStyleGray] autorelease]; - [spinner_ startAnimating]; - [container_ addSubview:spinner_]; - - label_ = [[[UILabel alloc] init] autorelease]; - [label_ setFont:[UIFont boldSystemFontOfSize:15.0f]]; - [label_ setBackgroundColor:[UIColor clearColor]]; - [label_ setTextColor:[UIColor blackColor]]; - [label_ setShadowColor:[UIColor whiteColor]]; - [label_ setShadowOffset:CGSizeMake(0, 1)]; - [label_ setText:[NSString stringWithFormat:Elision_, UCLocalize("LOADING"), nil]]; - [container_ addSubview:label_]; - - CGSize viewsize = frame.size; - CGSize spinnersize = [spinner_ bounds].size; - CGSize textsize = [[label_ text] sizeWithFont:[label_ font]]; - float bothwidth = spinnersize.width + textsize.width + 5.0f; - - CGRect containrect = { - CGPointMake(floorf((viewsize.width / 2) - (bothwidth / 2)), floorf((viewsize.height / 2) - (spinnersize.height / 2))), - CGSizeMake(bothwidth, spinnersize.height) - }; - CGRect textrect = { - CGPointMake(spinnersize.width + 5.0f, floorf((spinnersize.height / 2) - (textsize.height / 2))), - textsize - }; - CGRect spinrect = { - CGPointZero, - spinnersize - }; - - [container_ setFrame:containrect]; - [spinner_ setFrame:spinrect]; - [label_ setFrame:textrect]; - [self addSubview:container_]; - } return self; -} - -- (UILabel *) label { - return label_; -} - -- (UIActivityIndicatorView *) activityIndicatorView { - return spinner_; -} - -@end -/* }}} */ -/* Emulated Loading Controller {{{ */ -@interface CYEmulatedLoadingController : CyteViewController { - _transient Database *database_; - _H indicator_; - _H tabbar_; - _H navbar_; -} - -@end - -@implementation CYEmulatedLoadingController - -- (id) initWithDatabase:(Database *)database { - if ((self = [super init]) != nil) { - database_ = database; - } return self; -} - -- (void) loadView { - [self setView:[[[UIView alloc] initWithFrame:[[UIScreen mainScreen] applicationFrame]] autorelease]]; - - UITableView *table([[[UITableView alloc] initWithFrame:[[self view] bounds] style:UITableViewStyleGrouped] autorelease]); - [table setAutoresizingMask:UIViewAutoresizingFlexibleBoth]; - [[self view] addSubview:table]; - - indicator_ = [[[CYLoadingIndicator alloc] initWithFrame:[[self view] bounds]] autorelease]; - [indicator_ setAutoresizingMask:UIViewAutoresizingFlexibleBoth]; - [[self view] addSubview:indicator_]; - - tabbar_ = [[[UITabBar alloc] initWithFrame:CGRectMake(0, 0, 0, 49.0f)] autorelease]; - [tabbar_ setFrame:CGRectMake(0.0f, [[self view] bounds].size.height - [tabbar_ bounds].size.height, [[self view] bounds].size.width, [tabbar_ bounds].size.height)]; - [tabbar_ setAutoresizingMask:UIViewAutoresizingFlexibleTopMargin | UIViewAutoresizingFlexibleWidth]; - [[self view] addSubview:tabbar_]; +- (bool) isCydiaSecure { + if ([[[self scheme] lowercaseString] isEqualToString:@"https"]) + return true; - navbar_ = [[[UINavigationBar alloc] initWithFrame:CGRectMake(0, 0, 0, 44.0f)] autorelease]; - [navbar_ setFrame:CGRectMake(0.0f, 0.0f, [[self view] bounds].size.width, [navbar_ bounds].size.height)]; - [navbar_ setAutoresizingMask:UIViewAutoresizingFlexibleBottomMargin | UIViewAutoresizingFlexibleWidth]; - [[self view] addSubview:navbar_]; -} + @synchronized (HostConfig_) { + if ([InsecureHosts_ containsObject:[self host]]) + return true; + } -- (void) releaseSubviews { - indicator_ = nil; - tabbar_ = nil; - navbar_ = nil; + return false; } @end -/* }}} */ /* Cydia Browser Controller {{{ */ @implementation CydiaWebViewController @@ -4416,7 +4525,9 @@ static _H Diversions_; return request_ == nil ? nil : [NSURL URLWithString:[NSString stringWithFormat:@"cydia://url/%@", [[request_ URL] absoluteString]]]; } -+ (void) initialize { ++ (void) _initialize { + [super _initialize]; + Diversions_ = [NSMutableSet setWithCapacity:0]; } @@ -4446,19 +4557,45 @@ static _H Diversions_; [window setValue:cydia_ forKey:@"cydia"]; } +- (void) _setupMail:(MFMailComposeViewController *)controller { + [controller addAttachmentData:[NSData dataWithContentsOfFile:@"/tmp/cydia.log"] mimeType:@"text/plain" fileName:@"cydia.log"]; + + system("/usr/bin/dpkg -l >/tmp/dpkgl.log"); + [controller addAttachmentData:[NSData dataWithContentsOfFile:@"/tmp/dpkgl.log"] mimeType:@"text/plain" fileName:@"dpkgl.log"]; +} + - (NSURL *) URLWithURL:(NSURL *)url { return [Diversion divertURL:url]; } - (NSURLRequest *) webView:(WebView *)view resource:(id)resource willSendRequest:(NSURLRequest *)request redirectResponse:(NSURLResponse *)response fromDataSource:(WebDataSource *)source { + NSURL *url([request URL]); + NSString *host([url host]); + NSMutableURLRequest *copy([[super webView:view resource:resource willSendRequest:request redirectResponse:response fromDataSource:source] mutableCopy]); - if (System_ != NULL) - [copy setValue:System_ forHTTPHeaderField:@"X-System"]; - if (Machine_ != NULL) + if ([copy valueForHTTPHeaderField:@"X-Cydia-Cf-Version"] == nil) + [copy setValue:[NSString stringWithFormat:@"%.2f", kCFCoreFoundationVersionNumber] forHTTPHeaderField:@"X-Cydia-Cf-Version"]; + if (Machine_ != NULL && [copy valueForHTTPHeaderField:@"X-Machine"] == nil) [copy setValue:[NSString stringWithUTF8String:Machine_] forHTTPHeaderField:@"X-Machine"]; - if (Token_ != nil) - [copy setValue:Token_ forHTTPHeaderField:@"X-Cydia-Token"]; + + bool bridged; + bool token; + + @synchronized (HostConfig_) { + bridged = [BridgedHosts_ containsObject:host]; + token = [TokenHosts_ containsObject:host]; + } + + if ([url isCydiaSecure]) { + if (bridged) { + if (UniqueID_ != nil && [copy valueForHTTPHeaderField:@"X-Cydia-Id"] == nil) + [copy setValue:UniqueID_ forHTTPHeaderField:@"X-Cydia-Id"]; + } else if (token) { + if (Token_ != nil && [copy valueForHTTPHeaderField:@"X-Cydia-Token"] == nil) + [copy setValue:Token_ forHTTPHeaderField:@"X-Cydia-Token"]; + } + } return copy; } @@ -4468,23 +4605,31 @@ static _H Diversions_; [cydia_ setDelegate:delegate]; } +- (NSString *) applicationNameForUserAgent { + return UserAgent_; +} + - (id) init { if ((self = [super initWithWidth:0 ofClass:[CydiaWebViewController class]]) != nil) { cydia_ = [[[CydiaObject alloc] initWithDelegate:indirect_] autorelease]; + } return self; +} - WebView *webview([[webview_ _documentView] webView]); +@end - NSString *application([NSString stringWithFormat:@"Cydia/%@", @ Cydia_]); +@interface AppCacheController : CydiaWebViewController { +} - if (Safari_ != nil) - application = [NSString stringWithFormat:@"Safari/%@ %@", Safari_, application]; - if (Build_ != nil) - application = [NSString stringWithFormat:@"Mobile/%@ %@", Build_, application]; - if (Product_ != nil) - application = [NSString stringWithFormat:@"Version/%@ %@", Product_, application]; +@end - [webview setApplicationNameForUserAgent:application]; - } return self; +@implementation AppCacheController + +- (void) didReceiveMemoryWarning { + // XXX: this doesn't work +} + +- (bool) retainsNetworkActivityIndicator { + return false; } @end @@ -4592,8 +4737,8 @@ bool DepSubstrate(const pkgCache::VerIterator &iterator) { } - (void) _doContinue { - [self dismissModalViewControllerAnimated:YES]; [delegate_ cancelAndClear:NO]; + [self dismissModalViewControllerAnimated:YES]; } - (id) invokeDefaultMethodWithArguments:(NSArray *)args { @@ -4958,7 +5103,7 @@ bool DepSubstrate(const pkgCache::VerIterator &iterator) { ProgressDelegate > { _transient Database *database_; - _H progress_; + _H progress_; unsigned cancel_; } @@ -4975,7 +5120,6 @@ bool DepSubstrate(const pkgCache::VerIterator &iterator) { - (void) dealloc { [database_ setProgressDelegate:nil]; - [progress_ setDelegate:nil]; [super dealloc]; } @@ -5029,8 +5173,12 @@ bool DepSubstrate(const pkgCache::VerIterator &iterator) { - (void) close { UpdateExternalStatus(0); + if (Finish_ > 1) + [delegate_ saveState]; + switch (Finish_) { case 0: + [delegate_ returnToCydia]; break; case 1: @@ -5080,6 +5228,12 @@ bool DepSubstrate(const pkgCache::VerIterator &iterator) { ] autorelease]; } +- (void) uicache { + _trace(); + system("su -c /usr/bin/uicache mobile"); + _trace(); +} + - (void) invoke:(NSInvocation *)invocation withTitle:(NSString *)title { UpdateExternalStatus(1); @@ -5157,9 +5311,10 @@ bool DepSubstrate(const pkgCache::VerIterator &iterator) { case 4: [progress_ setFinish:UCLocalize("REBOOT_DEVICE")]; break; } - _trace(); - system("su -c /usr/bin/uicache mobile"); - _trace(); + UIProgressHUD *hud([delegate_ addProgressHUD]); + [hud setText:UCLocalize("LOADING")]; + [self yieldToSelector:@selector(uicache)]; + [delegate_ removeProgressHUD:hud]; UpdateExternalStatus(Finish_ == 0 ? 0 : 2); @@ -5223,71 +5378,9 @@ bool DepSubstrate(const pkgCache::VerIterator &iterator) { @end /* }}} */ -/* Cell Content View {{{ */ -@protocol ContentDelegate -- (void) drawContentRect:(CGRect)rect; -@end - -@interface ContentView : UIView { - _transient id delegate_; -} - -@end - -@implementation ContentView - -- (id) initWithFrame:(CGRect)frame { - if ((self = [super initWithFrame:frame]) != nil) { - [self setNeedsDisplayOnBoundsChange:YES]; - } return self; -} - -- (void) setDelegate:(id)delegate { - delegate_ = delegate; -} - -- (void) drawRect:(CGRect)rect { - [super drawRect:rect]; - [delegate_ drawContentRect:rect]; -} - -@end -/* }}} */ -/* Cydia TableView Cell {{{ */ -@interface CYTableViewCell : UITableViewCell { - _H content_; - bool highlighted_; -} - -@end - -@implementation CYTableViewCell - -- (void) _updateHighlightColorsForView:(UIView *)view highlighted:(BOOL)highlighted { - //NSLog(@"_updateHighlightColorsForView:%@ highlighted:%s [content_=%@]", view, highlighted ? "YES" : "NO", content_); - - if (view == (UIView *) content_) { - //NSLog(@"_updateHighlightColorsForView:content_ highlighted:%s", highlighted ? "YES" : "NO", content_); - highlighted_ = highlighted; - } - - [super _updateHighlightColorsForView:view highlighted:highlighted]; -} - -- (void) setSelected:(BOOL)selected animated:(BOOL)animated { - //NSLog(@"setSelected:%s animated:%s", selected ? "YES" : "NO", animated ? "YES" : "NO"); - highlighted_ = selected; - - [super setSelected:selected animated:animated]; - [content_ setNeedsDisplay]; -} - -@end -/* }}} */ - /* Package Cell {{{ */ -@interface PackageCell : CYTableViewCell < - ContentDelegate +@interface PackageCell : CyteTableViewCell < + CyteTableViewCellDelegate > { _H icon_; _H name_; @@ -5295,12 +5388,12 @@ bool DepSubstrate(const pkgCache::VerIterator &iterator) { bool commercial_; _H source_; _H badge_; - _H package_; _H placard_; + bool summarized_; } - (PackageCell *) init; -- (void) setPackage:(Package *)package; +- (void) setPackage:(Package *)package asSummary:(bool)summary; - (void) drawContentRect:(CGRect)rect; @@ -5314,7 +5407,7 @@ bool DepSubstrate(const pkgCache::VerIterator &iterator) { UIView *content([self contentView]); CGRect bounds([content bounds]); - content_ = [[[ContentView alloc] initWithFrame:bounds] autorelease]; + content_ = [[[CyteTableViewCellContentView alloc] initWithFrame:bounds] autorelease]; [content_ setAutoresizingMask:UIViewAutoresizingFlexibleBoth]; [content addSubview:content_]; @@ -5327,103 +5420,152 @@ bool DepSubstrate(const pkgCache::VerIterator &iterator) { return [NSString stringWithFormat:UCLocalize("COLON_DELIMITED"), (id) name_, (id) description_]; } -- (void) setPackage:(Package *)package { +- (void) setPackage:(Package *)package asSummary:(bool)summary { + summarized_ = summary; + icon_ = nil; name_ = nil; description_ = nil; source_ = nil; badge_ = nil; placard_ = nil; - package_ = nil; - [package parse]; + if (package == nil) + [content_ setBackgroundColor:[UIColor whiteColor]]; + else { + [package parse]; - Source *source = [package source]; + Source *source = [package source]; - icon_ = [package icon]; - name_ = [package name]; + icon_ = [package icon]; - if (IsWildcat_) - description_ = [package longDescription]; - if (description_ == nil) - description_ = [package shortDescription]; + if (NSString *name = [package name]) + name_ = [NSString stringWithString:name]; - commercial_ = [package isCommercial]; + NSString *description(nil); - package_ = package; + if (description == nil && IsWildcat_) + description = [package longDescription]; + if (description == nil) + description = [package shortDescription]; - NSString *label = nil; - bool trusted = false; + if (description != nil) + description_ = [NSString stringWithString:description]; - if (source != nil) { - label = [source label]; - trusted = [source trusted]; - } else if ([[package id] isEqualToString:@"firmware"]) - label = UCLocalize("APPLE"); - else - label = [NSString stringWithFormat:UCLocalize("SLASH_DELIMITED"), UCLocalize("UNKNOWN"), UCLocalize("LOCAL")]; + commercial_ = [package isCommercial]; - NSString *from(label); + NSString *label = nil; + bool trusted = false; - NSString *section = [package simpleSection]; - if (section != nil && ![section isEqualToString:label]) { - section = [[NSBundle mainBundle] localizedStringForKey:section value:nil table:@"Sections"]; - from = [NSString stringWithFormat:UCLocalize("PARENTHETICAL"), from, section]; - } + if (source != nil) { + label = [source label]; + trusted = [source trusted]; + } else if ([[package id] isEqualToString:@"firmware"]) + label = UCLocalize("APPLE"); + else + label = [NSString stringWithFormat:UCLocalize("SLASH_DELIMITED"), UCLocalize("UNKNOWN"), UCLocalize("LOCAL")]; - source_ = [NSString stringWithFormat:UCLocalize("FROM"), from]; + NSString *from(label); - if (NSString *purpose = [package primaryPurpose]) - badge_ = [UIImage imageAtPath:[NSString stringWithFormat:@"%@/Purposes/%@.png", App_, purpose]]; + NSString *section = [package simpleSection]; + if (section != nil && ![section isEqualToString:label]) { + section = [[NSBundle mainBundle] localizedStringForKey:section value:nil table:@"Sections"]; + from = [NSString stringWithFormat:UCLocalize("PARENTHETICAL"), from, section]; + } - UIColor *color; - NSString *placard; + source_ = [NSString stringWithFormat:UCLocalize("FROM"), from]; - if (NSString *mode = [package_ mode]) { - if ([mode isEqualToString:@"REMOVE"] || [mode isEqualToString:@"PURGE"]) { - color = RemovingColor_; - //placard = @"removing"; - } else { - color = InstallingColor_; - //placard = @"installing"; - } + if (NSString *purpose = [package primaryPurpose]) + badge_ = [UIImage imageAtPath:[NSString stringWithFormat:@"%@/Purposes/%@.png", App_, purpose]]; - // XXX: the removing/installing placards are not @2x - placard = nil; - } else { - color = [UIColor whiteColor]; + UIColor *color; + NSString *placard; - if ([package installed] != nil) - placard = @"installed"; - else + if (NSString *mode = [package mode]) { + if ([mode isEqualToString:@"REMOVE"] || [mode isEqualToString:@"PURGE"]) { + color = RemovingColor_; + //placard = @"removing"; + } else { + color = InstallingColor_; + //placard = @"installing"; + } + + // XXX: the removing/installing placards are not @2x placard = nil; - } + } else { + color = [UIColor whiteColor]; + + if ([package installed] != nil) + placard = @"installed"; + else + placard = nil; + } - [content_ setBackgroundColor:color]; + [content_ setBackgroundColor:color]; - if (placard != nil) - placard_ = [UIImage imageAtPath:[NSString stringWithFormat:@"%@/%@.png", App_, placard]]; + if (placard != nil) + placard_ = [UIImage imageAtPath:[NSString stringWithFormat:@"%@/%@.png", App_, placard]]; + } [self setNeedsDisplay]; [content_ setNeedsDisplay]; } -- (void) drawContentRect:(CGRect)rect { +- (void) drawSummaryContentRect:(CGRect)rect { bool highlighted(highlighted_); float width([self bounds].size.width); -#if 0 - CGContextRef context(UIGraphicsGetCurrentContext()); - [([[self selectedBackgroundView] superview] != nil ? [UIColor clearColor] : [self backgroundColor]) set]; - CGContextFillRect(context, rect); -#endif + if (icon_ != nil) { + CGRect rect; + rect.size = [(UIImage *) icon_ size]; + + while (rect.size.width > 16 || rect.size.height > 16) { + rect.size.width /= 2; + rect.size.height /= 2; + } + + rect.origin.x = 18 - rect.size.width / 2; + rect.origin.y = 18 - rect.size.height / 2; + + [icon_ drawInRect:rect]; + } + + if (badge_ != nil) { + CGRect rect; + rect.size = [(UIImage *) badge_ size]; + + rect.size.width /= 4; + rect.size.height /= 4; + + rect.origin.x = 23 - rect.size.width / 2; + rect.origin.y = 23 - rect.size.height / 2; + + [badge_ drawInRect:rect]; + } + + if (highlighted) + UISetColor(White_); + + if (!highlighted) + UISetColor(commercial_ ? Purple_ : Black_); + [name_ drawAtPoint:CGPointMake(36, 8) forWidth:(width - (placard_ == nil ? 68 : 94)) withFont:Font18Bold_ lineBreakMode:UILineBreakModeTailTruncation]; + + if (placard_ != nil) + [placard_ drawAtPoint:CGPointMake(width - 52, 9)]; +} + +- (void) drawNormalContentRect:(CGRect)rect { + bool highlighted(highlighted_); + float width([self bounds].size.width); if (icon_ != nil) { CGRect rect; rect.size = [(UIImage *) icon_ size]; - rect.size.width /= 2; - rect.size.height /= 2; + while (rect.size.width > 32 || rect.size.height > 32) { + rect.size.width /= 2; + rect.size.height /= 2; + } rect.origin.x = 25 - rect.size.width / 2; rect.origin.y = 25 - rect.size.height / 2; @@ -5460,11 +5602,18 @@ bool DepSubstrate(const pkgCache::VerIterator &iterator) { [placard_ drawAtPoint:CGPointMake(width - 52, 9)]; } +- (void) drawContentRect:(CGRect)rect { + if (summarized_) + [self drawSummaryContentRect:rect]; + else + [self drawNormalContentRect:rect]; +} + @end /* }}} */ /* Section Cell {{{ */ -@interface SectionCell : CYTableViewCell < - ContentDelegate +@interface SectionCell : CyteTableViewCell < + CyteTableViewCellDelegate > { _H basic_; _H section_; @@ -5490,7 +5639,7 @@ bool DepSubstrate(const pkgCache::VerIterator &iterator) { UIView *content([self contentView]); CGRect bounds([content bounds]); - content_ = [[[ContentView alloc] initWithFrame:bounds] autorelease]; + content_ = [[[CyteTableViewCellContentView alloc] initWithFrame:bounds] autorelease]; [content_ setAutoresizingMask:UIViewAutoresizingFlexibleBoth]; [content addSubview:content_]; [content_ setBackgroundColor:[UIColor whiteColor]]; @@ -5590,7 +5739,7 @@ bool DepSubstrate(const pkgCache::VerIterator &iterator) { _H package_; _H name_; _H files_; - _H list_; + _H list_; } - (id) initWithDatabase:(Database *)database; @@ -5600,12 +5749,6 @@ bool DepSubstrate(const pkgCache::VerIterator &iterator) { @implementation FileTable -- (void) dealloc { - [(UITableView *) list_ setDataSource:nil]; - [list_ setDelegate:nil]; - [super dealloc]; -} - - (NSInteger) tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section { return files_ == nil ? 0 : [files_ count]; } @@ -5633,14 +5776,12 @@ bool DepSubstrate(const pkgCache::VerIterator &iterator) { } - (void) loadView { - [self setView:[[[UIView alloc] initWithFrame:[[UIScreen mainScreen] applicationFrame]] autorelease]]; - - list_ = [[[UITableView alloc] initWithFrame:[[self view] bounds]] autorelease]; + list_ = [[[UITableView alloc] initWithFrame:[[UIScreen mainScreen] applicationFrame]] autorelease]; [list_ setAutoresizingMask:UIViewAutoresizingFlexibleBoth]; [list_ setRowHeight:24.0f]; [(UITableView *) list_ setDataSource:self]; [list_ setDelegate:self]; - [[self view] addSubview:list_]; + [self setView:list_]; } - (void) viewDidLoad { @@ -5651,13 +5792,16 @@ bool DepSubstrate(const pkgCache::VerIterator &iterator) { - (void) releaseSubviews { list_ = nil; + + package_ = nil; + files_ = nil; + + [super releaseSubviews]; } - (id) initWithDatabase:(Database *)database { if ((self = [super init]) != nil) { database_ = database; - - files_ = [NSMutableArray arrayWithCapacity:32]; } return self; } @@ -5665,7 +5809,7 @@ bool DepSubstrate(const pkgCache::VerIterator &iterator) { package_ = nil; name_ = nil; - [files_ removeAllObjects]; + files_ = [NSMutableArray arrayWithCapacity:32]; if (package != nil) { package_ = package; @@ -5821,7 +5965,7 @@ bool DepSubstrate(const pkgCache::VerIterator &iterator) { if ((self = [super init]) != nil) { database_ = database; buttons_ = [NSMutableArray arrayWithCapacity:4]; - name_ = [NSString stringWithString:name]; + name_ = name == nil ? @"" : [NSString stringWithString:name]; [self setURL:[NSURL URLWithString:[NSString stringWithFormat:@"%@/#!/package/%@", UI_, (id) name_]]]; } return self; } @@ -5880,26 +6024,30 @@ bool DepSubstrate(const pkgCache::VerIterator &iterator) { > { _transient Database *database_; unsigned era_; - _H packages_; + _H packages_; _H sections_; - _H list_; + _H list_; _H index_; _H indices_; _H title_; + unsigned reloading_; } - (id) initWithDatabase:(Database *)database title:(NSString *)title; - (void) setDelegate:(id)delegate; - (void) resetCursor; +- (void) clearData; @end @implementation PackageListController -- (void) dealloc { - [list_ setDataSource:nil]; - [list_ setDelegate:nil]; - [super dealloc]; +- (bool) isSummarized { + return false; +} + +- (bool) showsSections { + return true; } - (void) deselectWithAnimation:(BOOL)animated { @@ -5927,15 +6075,27 @@ bool DepSubstrate(const pkgCache::VerIterator &iterator) { [self resizeForKeyboardBounds:bounds duration:0]; } +- (void) getKeyboardCurve:(UIViewAnimationCurve *)curve duration:(NSTimeInterval *)duration forNotification:(NSNotification *)notification { + if (&UIKeyboardAnimationCurveUserInfoKey == NULL) + *curve = UIViewAnimationCurveEaseInOut; + else + [[[notification userInfo] objectForKey:UIKeyboardAnimationCurveUserInfoKey] getValue:curve]; + + if (&UIKeyboardAnimationDurationUserInfoKey == NULL) + *duration = 0.3; + else + [[[notification userInfo] objectForKey:UIKeyboardAnimationDurationUserInfoKey] getValue:duration]; +} + - (void) keyboardWillShow:(NSNotification *)notification { CGRect bounds; CGPoint center; - NSTimeInterval duration; - UIViewAnimationCurve curve; [[[notification userInfo] objectForKey:UIKeyboardBoundsUserInfoKey] getValue:&bounds]; [[[notification userInfo] objectForKey:UIKeyboardCenterEndUserInfoKey] getValue:¢er]; - [[[notification userInfo] objectForKey:UIKeyboardAnimationCurveUserInfoKey] getValue:&curve]; - [[[notification userInfo] objectForKey:UIKeyboardAnimationDurationUserInfoKey] getValue:&duration]; + + NSTimeInterval duration; + UIViewAnimationCurve curve; + [self getKeyboardCurve:&curve duration:&duration forNotification:notification]; CGRect kbframe = CGRectMake(round(center.x - bounds.size.width / 2.0), round(center.y - bounds.size.height / 2.0), bounds.size.width, bounds.size.height); UIViewController *base = self; @@ -5944,14 +6104,16 @@ bool DepSubstrate(const pkgCache::VerIterator &iterator) { CGRect viewframe = [[base view] convertRect:[list_ frame] fromView:[list_ superview]]; CGRect intersection = CGRectIntersection(viewframe, kbframe); + if (kCFCoreFoundationVersionNumber < kCFCoreFoundationVersionNumber_iPhoneOS_3_0) // XXX: _UIApplicationLinkedOnOrAfter(4) + intersection.size.height += CYStatusBarHeight(); + [self resizeForKeyboardBounds:intersection duration:duration curve:curve]; } - (void) keyboardWillHide:(NSNotification *)notification { NSTimeInterval duration; UIViewAnimationCurve curve; - [[[notification userInfo] objectForKey:UIKeyboardAnimationCurveUserInfoKey] getValue:&curve]; - [[[notification userInfo] objectForKey:UIKeyboardAnimationDurationUserInfoKey] getValue:&duration]; + [self getKeyboardCurve:&curve duration:&duration forNotification:notification]; [self resizeForKeyboardBounds:CGRectZero duration:duration curve:curve]; } @@ -6021,7 +6183,9 @@ bool DepSubstrate(const pkgCache::VerIterator &iterator) { PackageCell *cell((PackageCell *) [table dequeueReusableCellWithIdentifier:@"Package"]); if (cell == nil) cell = [[[PackageCell alloc] init] autorelease]; - [cell setPackage:[self packageAtIndexPath:path]]; + + Package *package([database_ packageWithName:[[self packageAtIndexPath:path] id]]); + [cell setPackage:package asSummary:[self isSummarized]]; return cell; } @@ -6032,8 +6196,10 @@ bool DepSubstrate(const pkgCache::VerIterator &iterator) { } - (NSArray *) sectionIndexTitlesForTableView:(UITableView *)tableView { - // XXX: is 20 the most optimal number here? - return [packages_ count] > 20 ? index_ : nil; + if (![self showsSections]) + return nil; + + return index_; } - (NSInteger) tableView:(UITableView *)tableView sectionForSectionIndexTitle:(NSString *)title atIndex:(NSInteger)index { @@ -6046,76 +6212,113 @@ bool DepSubstrate(const pkgCache::VerIterator &iterator) { return index; } +- (void) updateHeight { + [list_ setRowHeight:([self isSummarized] ? 38 : 73)]; +} + - (id) initWithDatabase:(Database *)database title:(NSString *)title { if ((self = [super init]) != nil) { database_ = database; title_ = [title copy]; [[self navigationItem] setTitle:title_]; + } return self; +} -#if TryIndexedCollation - if ([[self class] hasIndexedCollation]) - index_ = [[objc_getClass("UILocalizedIndexedCollation") currentCollation] sectionIndexTitles]; - else -#endif - index_ = [NSMutableArray arrayWithCapacity:32]; +- (void) loadView { + UIView *view([[[UIView alloc] initWithFrame:[[UIScreen mainScreen] applicationFrame]] autorelease]); + [view setAutoresizingMask:(UIViewAutoresizingFlexibleWidth | UIViewAutoresizingFlexibleHeight)]; + [self setView:view]; - indices_ = [NSMutableDictionary dictionaryWithCapacity:32]; + list_ = [[[UITableView alloc] initWithFrame:[[self view] bounds] style:UITableViewStylePlain] autorelease]; + [list_ setAutoresizingMask:UIViewAutoresizingFlexibleBoth]; + [view addSubview:list_]; - packages_ = [NSMutableArray arrayWithCapacity:16]; - sections_ = [NSMutableArray arrayWithCapacity:16]; + // XXX: is 20 the most optimal number here? + [list_ setSectionIndexMinimumDisplayRowCount:20]; - list_ = [[[UITableView alloc] initWithFrame:[[self view] bounds] style:UITableViewStylePlain] autorelease]; - [list_ setAutoresizingMask:UIViewAutoresizingFlexibleBoth]; - [list_ setRowHeight:73]; - [[self view] addSubview:list_]; + [(UITableView *) list_ setDataSource:self]; + [list_ setDelegate:self]; - [(UITableView *) list_ setDataSource:self]; - [list_ setDelegate:self]; - } return self; + [self updateHeight]; +} + +- (void) releaseSubviews { + list_ = nil; + + packages_ = nil; + sections_ = nil; + index_ = nil; + indices_ = nil; + + [super releaseSubviews]; } - (void) setDelegate:(id)delegate { delegate_ = delegate; } -- (bool) hasPackage:(Package *)package { - return true; +- (bool) shouldYield { + return false; } -- (bool) shouldYield { +- (bool) shouldBlock { return false; } -- (void) _reloadPackages:(NSArray *)packages { - [packages_ removeAllObjects]; - [sections_ removeAllObjects]; +- (NSMutableArray *) _reloadPackages { +@synchronized (database_) { + era_ = [database_ era]; + NSArray *packages([database_ packages]); - _profile(PackageTable$reloadData$Filter) - for (Package *package in packages) - if ([self hasPackage:package]) - [packages_ addObject:package]; - _end -} + return [NSMutableArray arrayWithArray:packages]; +} } - (void) _reloadData { - era_ = [database_ era]; - NSArray *packages = [database_ packages]; + if (reloading_ != 0) { + reloading_ = 2; + return; + } + NSArray *packages; + + reload: if ([self shouldYield]) { - UIProgressHUD *hud([delegate_ addProgressHUD]); - [hud setText:UCLocalize("LOADING")]; - [self yieldToSelector:@selector(_reloadPackages:) withObject:packages]; - [delegate_ removeProgressHUD:hud]; + do { + UIProgressHUD *hud; + + if (![self shouldBlock]) + hud = nil; + else { + hud = [delegate_ addProgressHUD]; + [hud setText:UCLocalize("LOADING")]; + } + + reloading_ = 1; + packages = [self yieldToSelector:@selector(_reloadPackages)]; + + if (hud != nil) + [delegate_ removeProgressHUD:hud]; + } while (reloading_ == 2); } else { - [self _reloadPackages:packages]; + packages = [self _reloadPackages]; } - [indices_ removeAllObjects]; +@synchronized (database_) { + if (era_ != [database_ era]) + goto reload; + reloading_ = 0; + + packages_ = packages; + + indices_ = [NSMutableDictionary dictionaryWithCapacity:32]; + sections_ = [NSMutableArray arrayWithCapacity:16]; Section *section = nil; #if TryIndexedCollation if ([[self class] hasIndexedCollation]) { + index_ = [[objc_getClass("UILocalizedIndexedCollation") currentCollation] sectionIndexTitles]; + id collation = [objc_getClass("UILocalizedIndexedCollation") currentCollation]; NSArray *titles = [collation sectionIndexTitles]; int secidx = -1; @@ -6148,7 +6351,13 @@ bool DepSubstrate(const pkgCache::VerIterator &iterator) { } else #endif { - [index_ removeAllObjects]; + index_ = [NSMutableArray arrayWithCapacity:32]; + + bool sectioned([self showsSections]); + if (!sectioned) { + section = [[[Section alloc] initWithName:nil localize:false] autorelease]; + [sections_ addObject:section]; + } _profile(PackageTable$reloadData$Section) for (size_t offset(0), end([packages_ count]); offset != end; ++offset) { @@ -6160,7 +6369,7 @@ bool DepSubstrate(const pkgCache::VerIterator &iterator) { index = [package index]; _end - if (section == nil || [section index] != index) { + if (sectioned && (section == nil || [section index] != index)) { _profile(PackageTable$reloadData$Section$Allocate) section = [[[Section alloc] initWithIndex:index row:offset] autorelease]; _end @@ -6178,18 +6387,34 @@ bool DepSubstrate(const pkgCache::VerIterator &iterator) { _end } + [self updateHeight]; + _profile(PackageTable$reloadData$List) + [(UITableView *) list_ setDataSource:self]; [list_ reloadData]; _end -} +} } - (void) reloadData { [super reloadData]; - [self performSelector:@selector(_reloadData) withObject:nil afterDelay:0]; + + if ([self shouldYield]) + [self performSelector:@selector(_reloadData) withObject:nil afterDelay:0]; + else + [self _reloadData]; } - (void) resetCursor { - [list_ scrollRectToVisible:CGRectMake(0, 0, 0, 0) animated:NO]; + [list_ scrollRectToVisible:CGRectMake(0, 0, 1, 1) animated:NO]; +} + +- (void) clearData { + [self updateHeight]; + + [list_ setDataSource:nil]; + [list_ reloadData]; + + [self resetCursor]; } @end @@ -6218,6 +6443,7 @@ bool DepSubstrate(const pkgCache::VerIterator &iterator) { } - (void) setFilter:(SEL)filter { +@synchronized (self) { filter_ = filter; /* XXX: this is an unsafe optimization of doomy hell */ @@ -6225,22 +6451,44 @@ bool DepSubstrate(const pkgCache::VerIterator &iterator) { _assert(method != NULL); imp_ = method_getImplementation(method); _assert(imp_ != NULL); -} +} } - (void) setObject:(id)object { +@synchronized (self) { object_ = object; -} +} } - (void) setObject:(id)object forFilter:(SEL)filter { +@synchronized (self) { [self setFilter:filter]; [self setObject:object]; -} +} } + +- (NSMutableArray *) _reloadPackages { +@synchronized (database_) { + era_ = [database_ era]; + NSArray *packages([database_ packages]); + + NSMutableArray *filtered([NSMutableArray arrayWithCapacity:[packages count]]); + + IMP imp; + SEL filter; + _H object; -- (bool) hasPackage:(Package *)package { - _profile(FilteredPackageTable$hasPackage) - return [package valid] && (*reinterpret_cast(imp_))(package, filter_, object_); + @synchronized (self) { + imp = imp_; + filter = filter_; + object = object_; + } + + _profile(PackageTable$reloadData$Filter) + for (Package *package in packages) + if ([package valid] && (*reinterpret_cast(imp))(package, filter, object)) + [filtered addObject:package]; _end -} + + return filtered; +} } - (id) initWithDatabase:(Database *)database title:(NSString *)title filter:(SEL)filter with:(id)object { if ((self = [super initWithDatabase:database title:title]) != nil) { @@ -6299,11 +6547,6 @@ bool DepSubstrate(const pkgCache::VerIterator &iterator) { ] autorelease]; } -- (void) unloadData { - [super unloadData]; - [self reloadData]; -} - @end /* }}} */ /* Manage Controller {{{ */ @@ -6318,7 +6561,7 @@ bool DepSubstrate(const pkgCache::VerIterator &iterator) { - (id) init { if ((self = [super init]) != nil) { - [self setURL:[NSURL URLWithString:[NSString stringWithFormat:@"%@/#!/manage/", UI_]]]; + [self setURL:[NSURL fileURLWithPath:[[NSBundle mainBundle] pathForResource:@"manage" ofType:@"html"]]]; } return self; } @@ -6343,13 +6586,13 @@ bool DepSubstrate(const pkgCache::VerIterator &iterator) { [delegate_ queue]; } -- (UIBarButtonItem *) customButton { +- (UIBarButtonItem *) rightButton { return Queuing_ ? [[[UIBarButtonItem alloc] initWithTitle:UCLocalize("QUEUE") style:UIBarButtonItemStyleDone target:self action:@selector(queueButtonClicked) - ] autorelease] : [super customButton]; + ] autorelease] : nil; } - (void) queueStatusDidChange { @@ -6487,7 +6730,7 @@ bool DepSubstrate(const pkgCache::VerIterator &iterator) { ProgressDelegate > { _transient Database *database_; - _H refreshbar_; + _H refreshbar_; bool dropped_; bool updating_; @@ -6509,7 +6752,32 @@ bool DepSubstrate(const pkgCache::VerIterator &iterator) { @implementation CYTabBarController +- (void) didReceiveMemoryWarning { + [super didReceiveMemoryWarning]; + + // presenting a UINavigationController on 2.x does not update its transitionView + // it thereby will not allow its topViewController to be unloaded by memory pressure + if (kCFCoreFoundationVersionNumber < kCFCoreFoundationVersionNumber_iPhoneOS_3_0) { + UIViewController *selected([self selectedViewController]); + for (UINavigationController *controller in [self viewControllers]) + if (controller != selected) + if (UIViewController *top = [controller topViewController]) + [top unloadView]; + } +} + - (void) setUnselectedViewController:(UIViewController *)transient { + if (kCFCoreFoundationVersionNumber < kCFCoreFoundationVersionNumber_iPhoneOS_3_0) { + if (transient != nil) { + [[[self viewControllers] objectAtIndex:0] pushViewController:transient animated:YES]; + [self setSelectedIndex:0]; + } return; + } + + UINavigationController *navigation([[[UINavigationController alloc] init] autorelease]); + [navigation setViewControllers:[NSArray arrayWithObject:transient]]; + transient = navigation; + NSMutableArray *controllers = [[self viewControllers] mutableCopy]; if (transient != nil) { if (transient_ == nil) @@ -6537,6 +6805,14 @@ bool DepSubstrate(const pkgCache::VerIterator &iterator) { - (void) tabBarController:(UITabBarController *)tabBarController didSelectViewController:(UIViewController *)viewController { if ([self unselectedViewController]) [self setUnselectedViewController:nil]; + + // presenting a UINavigationController on 2.x does not update its transitionView + // if this view was unloaded, the tranitionView may currently be presenting nothing + if (kCFCoreFoundationVersionNumber < kCFCoreFoundationVersionNumber_iPhoneOS_3_0) { + UINavigationController *navigation((UINavigationController *) viewController); + [navigation pushViewController:[[[UIViewController alloc] init] autorelease] animated:NO]; + [navigation popViewControllerAnimated:NO]; + } } - (NSArray *) navigationURLCollection { @@ -6552,21 +6828,29 @@ bool DepSubstrate(const pkgCache::VerIterator &iterator) { return items; } +- (void) dismissModalViewControllerAnimated:(BOOL)animated { + if ([self modalViewController] == nil && [self unselectedViewController] != nil) + [self setUnselectedViewController:nil]; + else + [super dismissModalViewControllerAnimated:YES]; +} + - (void) unloadData { - UIViewController *selected([self selectedViewController]); + [super unloadData]; + for (UINavigationController *controller in [self viewControllers]) [controller unloadData]; - [selected reloadData]; + if (UIViewController *selected = [self selectedViewController]) + [selected reloadData]; - if (UIViewController *unselected = [self unselectedViewController]) + if (UIViewController *unselected = [self unselectedViewController]) { + [unselected unloadData]; [unselected reloadData]; - - [super unloadData]; + } } - (void) dealloc { - [refreshbar_ setDelegate:nil]; [[NSNotificationCenter defaultCenter] removeObserver:self]; [super dealloc]; @@ -6602,7 +6886,9 @@ bool DepSubstrate(const pkgCache::VerIterator &iterator) { ]; } -- (void) performUpdate { _pooled +- (void) performUpdate { + NSAutoreleasePool *pool([[NSAutoreleasePool alloc] init]); + Status status; status.setDelegate(self); [database_ updateWithStatus:status]; @@ -6612,6 +6898,8 @@ bool DepSubstrate(const pkgCache::VerIterator &iterator) { withObject:nil waitUntilDone:NO ]; + + [pool release]; } - (void) stopUpdateWithSelector:(SEL)selector { @@ -6667,14 +6955,6 @@ bool DepSubstrate(const pkgCache::VerIterator &iterator) { updatedelegate_ = delegate; } -- (CGFloat) statusBarHeight { - if (UIInterfaceOrientationIsPortrait([self interfaceOrientation])) { - return [[UIApplication sharedApplication] statusBarFrame].size.height; - } else { - return [[UIApplication sharedApplication] statusBarFrame].size.width; - } -} - - (UIView *) transitionView { if ([self respondsToSelector:@selector(_transitionView)]) return [self _transitionView]; @@ -6693,7 +6973,7 @@ bool DepSubstrate(const pkgCache::VerIterator &iterator) { CGRect barframe([refreshbar_ frame]); if (kCFCoreFoundationVersionNumber >= kCFCoreFoundationVersionNumber_iPhoneOS_3_0) // XXX: _UIApplicationLinkedOnOrAfter(4) - barframe.origin.y = [self statusBarHeight]; + barframe.origin.y = CYStatusBarHeight(); else barframe.origin.y = 0; @@ -6777,8 +7057,15 @@ bool DepSubstrate(const pkgCache::VerIterator &iterator) { - (void) reloadData { [super reloadData]; - if (UIViewController *visible = [self visibleViewController]) + UIViewController *visible([self visibleViewController]); + if (visible != nil) [visible reloadData]; + + // on the iPad, this view controller is ALSO visible. :( + if (IsWildcat_) + if (UIViewController *top = [self topViewController]) + if (top != visible) + [top reloadData]; } - (void) unloadData { @@ -6867,17 +7154,9 @@ bool DepSubstrate(const pkgCache::VerIterator &iterator) { Package *package([database packageWithName:path]); if (package == nil) goto fail; + [package parse]; UIImage *icon([package icon]); [self _returnPNGWithImage:icon forRequest:request]; - } else if ([command isEqualToString:@"source-icon"]) { - if (path == nil) - goto fail; - path = [path stringByReplacingPercentEscapesUsingEncoding:NSUTF8StringEncoding]; - NSString *source(Simplify(path)); - UIImage *icon([UIImage imageAtPath:[NSString stringWithFormat:@"%@/Sources/%@.png", App_, source]]); - if (icon == nil) - icon = [UIImage applicationImageNamed:@"unknown.png"]; - [self _returnPNGWithImage:icon forRequest:request]; } else if ([command isEqualToString:@"uikit-image"]) { if (path == nil) goto fail; @@ -6888,8 +7167,7 @@ bool DepSubstrate(const pkgCache::VerIterator &iterator) { if (path == nil) goto fail; path = [path stringByReplacingPercentEscapesUsingEncoding:NSUTF8StringEncoding]; - NSString *section(Simplify(path)); - UIImage *icon([UIImage imageAtPath:[NSString stringWithFormat:@"%@/Sections/%@.png", App_, section]]); + UIImage *icon([UIImage imageAtPath:[NSString stringWithFormat:@"%@/Sections/%@.png", App_, [path stringByReplacingOccurrencesOfString:@" " withString:@"_"]]]); if (icon == nil) icon = [UIImage applicationImageNamed:@"unknown.png"]; [self _returnPNGWithImage:icon forRequest:request]; @@ -6947,7 +7225,7 @@ bool DepSubstrate(const pkgCache::VerIterator &iterator) { _transient Database *database_; _H sections_; _H filtered_; - _H list_; + _H list_; } - (id) initWithDatabase:(Database *)database; @@ -7047,14 +7325,12 @@ bool DepSubstrate(const pkgCache::VerIterator &iterator) { } - (void) loadView { - [self setView:[[[UIView alloc] initWithFrame:[[UIScreen mainScreen] applicationFrame]] autorelease]]; - - list_ = [[[UITableView alloc] initWithFrame:[[self view] bounds]] autorelease]; + list_ = [[[UITableView alloc] initWithFrame:[[UIScreen mainScreen] applicationFrame]] autorelease]; [list_ setAutoresizingMask:UIViewAutoresizingFlexibleBoth]; [list_ setRowHeight:45.0f]; [(UITableView *) list_ setDataSource:self]; [list_ setDelegate:self]; - [[self view] addSubview:list_]; + [self setView:list_]; } - (void) viewDidLoad { @@ -7065,14 +7341,16 @@ bool DepSubstrate(const pkgCache::VerIterator &iterator) { - (void) releaseSubviews { list_ = nil; + + sections_ = nil; + filtered_ = nil; + + [super releaseSubviews]; } - (id) initWithDatabase:(Database *)database { if ((self = [super init]) != nil) { database_ = database; - - sections_ = [NSMutableArray arrayWithCapacity:16]; - filtered_ = [NSMutableArray arrayWithCapacity:16]; } return self; } @@ -7081,8 +7359,8 @@ bool DepSubstrate(const pkgCache::VerIterator &iterator) { NSArray *packages = [database_ packages]; - [sections_ removeAllObjects]; - [filtered_ removeAllObjects]; + sections_ = [NSMutableArray arrayWithCapacity:16]; + filtered_ = [NSMutableArray arrayWithCapacity:16]; NSMutableDictionary *sections([NSMutableDictionary dictionaryWithCapacity:32]); @@ -7147,9 +7425,9 @@ bool DepSubstrate(const pkgCache::VerIterator &iterator) { > { _transient Database *database_; unsigned era_; - CFMutableArrayRef packages_; + _H packages_; _H sections_; - _H list_; + _H list_; unsigned upgrades_; } @@ -7159,11 +7437,6 @@ bool DepSubstrate(const pkgCache::VerIterator &iterator) { @implementation ChangesController -- (void) dealloc { - CFRelease(packages_); - [super dealloc]; -} - - (NSURL *) navigationURL { return [NSURL URLWithString:@"cydia://changes"]; } @@ -7190,10 +7463,6 @@ bool DepSubstrate(const pkgCache::VerIterator &iterator) { return [[sections_ objectAtIndex:section] count]; } -- (Package *) packageAtIndex:(NSUInteger)index { - return (Package *) CFArrayGetValueAtIndex(packages_, index); -} - - (Package *) packageAtIndexPath:(NSIndexPath *)path { @synchronized (database_) { if ([database_ era] != era_) @@ -7204,14 +7473,16 @@ bool DepSubstrate(const pkgCache::VerIterator &iterator) { return nil; Section *section([sections_ objectAtIndex:sectionIndex]); NSInteger row([path row]); - return [[[self packageAtIndex:([section row] + row)] retain] autorelease]; + return [[[packages_ objectAtIndex:([section row] + row)] retain] autorelease]; } } - (UITableViewCell *) tableView:(UITableView *)table cellForRowAtIndexPath:(NSIndexPath *)path { PackageCell *cell((PackageCell *) [table dequeueReusableCellWithIdentifier:@"Package"]); if (cell == nil) cell = [[[PackageCell alloc] init] autorelease]; - [cell setPackage:[self packageAtIndexPath:path]]; + + Package *package([database_ packageWithName:[[self packageAtIndexPath:path] id]]); + [cell setPackage:package asSummary:false]; return cell; } @@ -7230,17 +7501,16 @@ bool DepSubstrate(const pkgCache::VerIterator &iterator) { - (void) upgradeButtonClicked { [delegate_ distUpgrade]; + [[self navigationItem] setRightBarButtonItem:nil animated:YES]; } - (void) loadView { - [self setView:[[[UIView alloc] initWithFrame:[[UIScreen mainScreen] applicationFrame]] autorelease]]; - - list_ = [[[UITableView alloc] initWithFrame:[[self view] bounds] style:UITableViewStylePlain] autorelease]; + list_ = [[[UITableView alloc] initWithFrame:[[UIScreen mainScreen] applicationFrame] style:UITableViewStylePlain] autorelease]; [list_ setAutoresizingMask:UIViewAutoresizingFlexibleBoth]; [list_ setRowHeight:73]; [(UITableView *) list_ setDataSource:self]; [list_ setDelegate:self]; - [[self view] addSubview:list_]; + [self setView:list_]; } - (void) viewDidLoad { @@ -7251,52 +7521,61 @@ bool DepSubstrate(const pkgCache::VerIterator &iterator) { - (void) releaseSubviews { list_ = nil; + + packages_ = nil; + sections_ = nil; + + [super releaseSubviews]; } - (id) initWithDatabase:(Database *)database { if ((self = [super init]) != nil) { database_ = database; - - packages_ = CFArrayCreateMutable(kCFAllocatorDefault, 0, NULL); - sections_ = [NSMutableArray arrayWithCapacity:16]; } return self; } -// this mostly works because reloadData (below) is @synchronized (database_) -// XXX: that said, I've been running into problems with NSRangeExceptions :( -- (void) _reloadPackages:(NSArray *)packages { - CFRelease(packages_); - packages_ = CFArrayCreateMutable(kCFAllocatorDefault, [packages count], NULL); +- (NSMutableArray *) _reloadPackages { +@synchronized (database_) { + era_ = [database_ era]; + NSArray *packages([database_ packages]); + + NSMutableArray *filtered([NSMutableArray arrayWithCapacity:[packages count]]); _trace(); _profile(ChangesController$_reloadPackages$Filter) for (Package *package in packages) if ([package upgradableAndEssential:YES] || [package visible]) - CFArrayAppendValue(packages_, package); + CFArrayAppendValue((CFMutableArrayRef) filtered, package); _end _trace(); _profile(ChangesController$_reloadPackages$radixSort) - [(NSMutableArray *) packages_ radixSortUsingFunction:reinterpret_cast(&PackageChangesRadix) withContext:NULL]; + [filtered radixSortUsingFunction:reinterpret_cast(&PackageChangesRadix) withContext:NULL]; _end _trace(); -} + + return filtered; +} } - (void) _reloadData { -@synchronized (database_) { - era_ = [database_ era]; - NSArray *packages = [database_ packages]; + NSArray *packages; -#if 1 - UIProgressHUD *hud([delegate_ addProgressHUD]); - [hud setText:UCLocalize("LOADING")]; - //NSLog(@"HUD:%@::%@", delegate_, hud); - [self yieldToSelector:@selector(_reloadPackages:) withObject:packages]; - [delegate_ removeProgressHUD:hud]; -#else - [self _reloadPackages:packages]; -#endif + reload: + if (true) { + UIProgressHUD *hud([delegate_ addProgressHUD]); + [hud setText:UCLocalize("LOADING")]; + //NSLog(@"HUD:%@::%@", delegate_, hud); + packages = [self yieldToSelector:@selector(_reloadPackages)]; + [delegate_ removeProgressHUD:hud]; + } else { + packages = [self _reloadPackages]; + } + +@synchronized (database_) { + if (era_ != [database_ era]) + goto reload; - [sections_ removeAllObjects]; + packages_ = packages; + sections_ = [NSMutableArray arrayWithCapacity:16]; Section *upgradable = [[[Section alloc] initWithName:UCLocalize("AVAILABLE_UPGRADES") localize:NO] autorelease]; Section *ignored = nil; @@ -7308,8 +7587,8 @@ bool DepSubstrate(const pkgCache::VerIterator &iterator) { CFDateFormatterRef formatter(CFDateFormatterCreate(NULL, Locale_, kCFDateFormatterMediumStyle, kCFDateFormatterMediumStyle)); - for (size_t offset = 0, count = CFArrayGetCount(packages_); offset != count; ++offset) { - Package *package = [self packageAtIndex:offset]; + for (size_t offset = 0, count = [packages_ count]; offset != count; ++offset) { + Package *package = [packages_ objectAtIndex:offset]; BOOL uae = [package upgradableAndEssential:YES]; @@ -7349,7 +7628,7 @@ bool DepSubstrate(const pkgCache::VerIterator &iterator) { if (unseens) { Section *last = [sections_ lastObject]; size_t count = [last count]; - CFArrayReplaceValues(packages_, CFRangeMake(CFArrayGetCount(packages_) - count, count), NULL, 0); + [packages_ removeObjectsInRange:NSMakeRange([packages_ count] - count, count)]; [sections_ removeLastObject]; } @@ -7360,21 +7639,19 @@ bool DepSubstrate(const pkgCache::VerIterator &iterator) { [list_ reloadData]; - if (upgrades_ > 0) - [[self navigationItem] setRightBarButtonItem:[[[UIBarButtonItem alloc] - initWithTitle:[NSString stringWithFormat:UCLocalize("PARENTHETICAL"), UCLocalize("UPGRADE"), [NSString stringWithFormat:@"%u", upgrades_]] - style:UIBarButtonItemStylePlain - target:self - action:@selector(upgradeButtonClicked) - ] autorelease]]; + [[self navigationItem] setRightBarButtonItem:(upgrades_ == 0 ? nil : [[[UIBarButtonItem alloc] + initWithTitle:[NSString stringWithFormat:UCLocalize("PARENTHETICAL"), UCLocalize("UPGRADE"), [NSString stringWithFormat:@"%u", upgrades_]] + style:UIBarButtonItemStylePlain + target:self + action:@selector(upgradeButtonClicked) + ] autorelease]) animated:YES]; - if (![delegate_ updating]) - [[self navigationItem] setLeftBarButtonItem:[[[UIBarButtonItem alloc] - initWithTitle:UCLocalize("REFRESH") - style:UIBarButtonItemStylePlain - target:self - action:@selector(refreshButtonClicked) - ] autorelease]]; + [[self navigationItem] setLeftBarButtonItem:([delegate_ updating] ? nil : [[[UIBarButtonItem alloc] + initWithTitle:UCLocalize("REFRESH") + style:UIBarButtonItemStylePlain + target:self + action:@selector(refreshButtonClicked) + ] autorelease]) animated:YES]; PrintTimes(); } } @@ -7390,7 +7667,7 @@ bool DepSubstrate(const pkgCache::VerIterator &iterator) { @interface SearchController : FilteredPackageListController < UISearchBarDelegate > { - _H search_; + _H search_; BOOL searchloaded_; } @@ -7401,11 +7678,6 @@ bool DepSubstrate(const pkgCache::VerIterator &iterator) { @implementation SearchController -- (void) dealloc { - [search_ setDelegate:nil]; - [super dealloc]; -} - - (NSURL *) navigationURL { if ([search_ text] == nil || [[search_ text] isEqualToString:@""]) return [NSURL URLWithString:@"cydia://search"]; @@ -7413,14 +7685,28 @@ bool DepSubstrate(const pkgCache::VerIterator &iterator) { return [NSURL URLWithString:[NSString stringWithFormat:@"cydia://search/%@", [search_ text]]]; } +- (void) useSearch { + [self setObject:[[search_ text] componentsSeparatedByString:@" "] forFilter:@selector(isUnfilteredAndSearchedForBy:)]; + [self clearData]; + [self reloadData]; +} + +- (void) viewWillAppear:(BOOL)animated { + [super viewWillAppear:animated]; + + if ([self filter] == @selector(isUnfilteredAndSelectedForBy:)) + [self useSearch]; +} + - (void) searchBarTextDidBeginEditing:(UISearchBar *)searchBar { [self setObject:[search_ text] forFilter:@selector(isUnfilteredAndSelectedForBy:)]; + [self clearData]; + [self reloadData]; } - (void) searchBarButtonClicked:(UISearchBar *)searchBar { - [self setObject:[search_ text] forFilter:@selector(isUnfilteredAndSearchedForBy:)]; [search_ resignFirstResponder]; - [self reloadData]; + [self useSearch]; } - (void) searchBarCancelButtonClicked:(UISearchBar *)searchBar { @@ -7438,11 +7724,30 @@ bool DepSubstrate(const pkgCache::VerIterator &iterator) { } - (bool) shouldYield { + return YES; +} + +- (bool) shouldBlock { return [self filter] == @selector(isUnfilteredAndSearchedForBy:); } +- (bool) isSummarized { + return [self filter] == @selector(isUnfilteredAndSelectedForBy:); +} + +- (bool) showsSections { + return false; +} + +- (NSMutableArray *) _reloadPackages { + NSMutableArray *packages([super _reloadPackages]); + if ([self filter] == @selector(isUnfilteredAndSearchedForBy:)) + [packages radixSortUsingSelector:@selector(rank)]; + return packages; +} + - (id) initWithDatabase:(Database *)database query:(NSString *)query { - if ((self = [super initWithDatabase:database title:UCLocalize("SEARCH") filter:@selector(isUnfilteredAndSearchedForBy:) with:query])) { + if ((self = [super initWithDatabase:database title:UCLocalize("SEARCH") filter:@selector(isUnfilteredAndSearchedForBy:) with:[query componentsSeparatedByString:@" "]])) { search_ = [[[UISearchBar alloc] init] autorelease]; [search_ setDelegate:self]; @@ -7473,7 +7778,11 @@ bool DepSubstrate(const pkgCache::VerIterator &iterator) { } - (void) reloadData { - [self setObject:[search_ text]]; + id object([search_ text]); + if ([self filter] == @selector(isUnfilteredAndSearchedForBy:)) + object = [object componentsSeparatedByString:@" "]; + + [self setObject:object]; [self resetCursor]; [super reloadData]; @@ -7494,7 +7803,7 @@ bool DepSubstrate(const pkgCache::VerIterator &iterator) { _transient Database *database_; _H name_; _H package_; - _H table_; + _H table_; _H subscribedSwitch_; _H ignoredSwitch_; _H subscribedCell_; @@ -7508,7 +7817,7 @@ bool DepSubstrate(const pkgCache::VerIterator &iterator) { @implementation PackageSettingsController - (NSURL *) navigationURL { - return [NSURL URLWithString:[NSString stringWithFormat:@"cydia://package/%@/settings", [package_ id]]]; + return [NSURL URLWithString:[NSString stringWithFormat:@"cydia://package/%@/settings", (id) name_]]; } - (NSInteger) numberOfSectionsInTableView:(UITableView *)tableView { @@ -7568,15 +7877,7 @@ bool DepSubstrate(const pkgCache::VerIterator &iterator) { _assert(false); } - _forever { - int status; - int result(waitpid(pid, &status, 0)); - - if (result != -1) { - _assert(result == pid); - break; - } - } + ReapZombie(pid); } - (void) onIgnored:(id)control { @@ -7602,13 +7903,15 @@ bool DepSubstrate(const pkgCache::VerIterator &iterator) { } - (void) loadView { - [self setView:[[[UIView alloc] initWithFrame:[[UIScreen mainScreen] applicationFrame]] autorelease]]; + UIView *view([[[UIView alloc] initWithFrame:[[UIScreen mainScreen] applicationFrame]] autorelease]); + [view setAutoresizingMask:(UIViewAutoresizingFlexibleWidth | UIViewAutoresizingFlexibleHeight)]; + [self setView:view]; table_ = [[[UITableView alloc] initWithFrame:[[self view] bounds] style:UITableViewStyleGrouped] autorelease]; [table_ setAutoresizingMask:UIViewAutoresizingFlexibleBoth]; [(UITableView *) table_ setDataSource:self]; [table_ setDelegate:self]; - [[self view] addSubview:table_]; + [view addSubview:table_]; subscribedSwitch_ = [[[UISwitch alloc] initWithFrame:CGRectMake(0, 0, 50, 20)] autorelease]; [subscribedSwitch_ setAutoresizingMask:UIViewAutoresizingFlexibleLeftMargin]; @@ -7641,6 +7944,8 @@ bool DepSubstrate(const pkgCache::VerIterator &iterator) { table_ = nil; ignoredSwitch_ = nil; subscribedSwitch_ = nil; + + [super releaseSubviews]; } - (id) initWithDatabase:(Database *)database package:(NSString *)package { @@ -7680,10 +7985,6 @@ bool DepSubstrate(const pkgCache::VerIterator &iterator) { @implementation InstalledController -- (void) dealloc { - [super dealloc]; -} - - (NSURL *) navigationURL { return [NSURL URLWithString:@"cydia://installed"]; } @@ -7740,9 +8041,10 @@ bool DepSubstrate(const pkgCache::VerIterator &iterator) { /* }}} */ /* Source Cell {{{ */ -@interface SourceCell : CYTableViewCell < - ContentDelegate +@interface SourceCell : CyteTableViewCell < + CyteTableViewCellDelegate > { + _H url_; _H icon_; _H origin_; _H label_; @@ -7754,17 +8056,42 @@ bool DepSubstrate(const pkgCache::VerIterator &iterator) { @implementation SourceCell +- (void) _setImage:(NSArray *)data { + if ([url_ isEqual:[data objectAtIndex:0]]) { + icon_ = [data objectAtIndex:1]; + [content_ setNeedsDisplay]; + } +} + +- (void) _setSource:(NSURL *) url { + NSAutoreleasePool *pool([[NSAutoreleasePool alloc] init]); + + if (NSData *data = [NSURLConnection + sendSynchronousRequest:[NSURLRequest + requestWithURL:url + //cachePolicy:NSURLRequestUseProtocolCachePolicy + //timeoutInterval:5 + ] + + returningResponse:NULL + error:NULL + ]) + if (UIImage *image = [UIImage imageWithData:data]) + [self performSelectorOnMainThread:@selector(_setImage:) withObject:[NSArray arrayWithObjects:url, image, nil] waitUntilDone:NO]; + + [pool release]; +} + - (void) setSource:(Source *)source { - icon_ = nil; - if (icon_ == nil) - icon_ = [UIImage applicationImageNamed:[NSString stringWithFormat:@"Sources/%@.png", [source host]]]; - if (icon_ == nil) - icon_ = [UIImage applicationImageNamed:@"unknown.png"]; + icon_ = [UIImage applicationImageNamed:@"unknown.png"]; origin_ = [source name]; - label_ = [source uri]; + label_ = [source rooturi]; [content_ setNeedsDisplay]; + + url_ = [source iconURL]; + [NSThread detachNewThreadSelector:@selector(_setSource:) toTarget:self withObject:url_]; } - (SourceCell *) initWithFrame:(CGRect)frame reuseIdentifier:(NSString *)reuseIdentifier { @@ -7772,13 +8099,15 @@ bool DepSubstrate(const pkgCache::VerIterator &iterator) { UIView *content([self contentView]); CGRect bounds([content bounds]); - content_ = [[[ContentView alloc] initWithFrame:bounds] autorelease]; + content_ = [[[CyteTableViewCellContentView alloc] initWithFrame:bounds] autorelease]; [content_ setAutoresizingMask:UIViewAutoresizingFlexibleBoth]; [content_ setBackgroundColor:[UIColor whiteColor]]; [content addSubview:content_]; [content_ setDelegate:self]; [content_ setOpaque:YES]; + + [[content_ layer] setContentsGravity:kCAGravityTopLeft]; } return self; } @@ -7790,19 +8119,31 @@ bool DepSubstrate(const pkgCache::VerIterator &iterator) { bool highlighted(highlighted_); float width(rect.size.width); - if (icon_ != nil) - [icon_ drawInRect:CGRectMake(10, 10, 30, 30)]; + if (icon_ != nil) { + CGRect rect; + rect.size = [(UIImage *) icon_ size]; + + while (rect.size.width > 32 || rect.size.height > 32) { + rect.size.width /= 2; + rect.size.height /= 2; + } + + rect.origin.x = 25 - rect.size.width / 2; + rect.origin.y = 25 - rect.size.height / 2; + + [icon_ drawInRect:rect]; + } if (highlighted) UISetColor(White_); if (!highlighted) UISetColor(Black_); - [origin_ drawAtPoint:CGPointMake(48, 8) forWidth:(width - 80) withFont:Font18Bold_ lineBreakMode:UILineBreakModeTailTruncation]; + [origin_ drawAtPoint:CGPointMake(48, 8) forWidth:(width - 65) withFont:Font18Bold_ lineBreakMode:UILineBreakModeTailTruncation]; if (!highlighted) - UISetColor(Blue_); - [label_ drawAtPoint:CGPointMake(58, 29) forWidth:(width - 95) withFont:Font12_ lineBreakMode:UILineBreakModeTailTruncation]; + UISetColor(Gray_); + [label_ drawAtPoint:CGPointMake(48, 29) forWidth:(width - 65) withFont:Font12_ lineBreakMode:UILineBreakModeTailTruncation]; } @end @@ -7820,7 +8161,7 @@ bool DepSubstrate(const pkgCache::VerIterator &iterator) { @implementation SourceController - (NSURL *) navigationURL { - return [NSURL URLWithString:[NSString stringWithFormat:@"cydia://sources/%@", [source_ name]]]; + return [NSURL URLWithString:[NSString stringWithFormat:@"cydia://sources/%@", [key_ stringByAddingPercentEscapesIncludingReserved]]]; } - (id) initWithDatabase:(Database *)database source:(Source *)source { @@ -7848,7 +8189,9 @@ bool DepSubstrate(const pkgCache::VerIterator &iterator) { UITableViewDelegate > { _transient Database *database_; - _H list_; + unsigned era_; + + _H list_; _H sources_; int offset_; @@ -7900,38 +8243,24 @@ bool DepSubstrate(const pkgCache::VerIterator &iterator) { } - (NSInteger) numberOfSectionsInTableView:(UITableView *)tableView { - return offset_ == 0 ? 1 : 2; + return 1; } - (NSString *) tableView:(UITableView *)tableView titleForHeaderInSection:(NSInteger)section { - switch (section + (offset_ == 0 ? 1 : 0)) { - case 0: return UCLocalize("ENTERED_BY_USER"); - case 1: return UCLocalize("INSTALLED_BY_PACKAGE"); - - _nodefault - } + return nil; } - (NSInteger) tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section { - int count = [sources_ count]; - switch (section) { - case 0: return (offset_ == 0 ? count : offset_); - case 1: return count - offset_; - - _nodefault - } + return [sources_ count]; } - (Source *) sourceAtIndexPath:(NSIndexPath *)indexPath { - unsigned idx = 0; - switch (indexPath.section) { - case 0: idx = indexPath.row; break; - case 1: idx = indexPath.row + offset_; break; +@synchronized (database_) { + if ([database_ era] != era_) + return nil; - _nodefault - } - return [sources_ objectAtIndex:idx]; -} + return [sources_ objectAtIndex:[indexPath row]]; +} } - (UITableViewCell *) tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath { static NSString *cellIdentifier = @"SourceCell"; @@ -7972,6 +8301,8 @@ bool DepSubstrate(const pkgCache::VerIterator &iterator) { - (void) complete { [delegate_ addTrivialSource:href_]; + href_ = nil; + [delegate_ syncData]; } @@ -7982,7 +8313,6 @@ bool DepSubstrate(const pkgCache::VerIterator &iterator) { href = [href substringFromIndex:(colon.location + 3)]; href = [href stringByAddingPercentEscapes]; href = [CydiaURL(@"api/repotag/") stringByAppendingString:href]; - href = [href stringByCachingURLWithCurrentCDN]; NSURL *url([NSURL URLWithString:href]); @@ -8013,17 +8343,15 @@ bool DepSubstrate(const pkgCache::VerIterator &iterator) { trivial_bz2_ == nil && trivial_gz_ == nil ) { + NSString *warning(cydia_ ? [self yieldToSelector:@selector(getWarning)] : nil); + [delegate_ releaseNetworkActivityIndicator]; [delegate_ removeProgressHUD:hud_]; hud_ = nil; - bool defer(false); - if (cydia_) { - if (NSString *warning = [self yieldToSelector:@selector(getWarning)]) { - defer = true; - + if (warning != nil) { UIAlertView *alert = [[[UIAlertView alloc] initWithTitle:UCLocalize("SOURCE_WARNING") message:warning @@ -8037,8 +8365,13 @@ bool DepSubstrate(const pkgCache::VerIterator &iterator) { [alert setContext:@"warning"]; [alert setNumberOfRows:1]; [alert show]; - } else - [self complete]; + + // XXX: there used to be this great mechanism called yieldToPopup... who deleted it? + error_ = nil; + return; + } + + [self complete]; } else if (error_ != nil) { UIAlertView *alert = [[[UIAlertView alloc] initWithTitle:UCLocalize("VERIFICATION_ERROR") @@ -8050,6 +8383,8 @@ bool DepSubstrate(const pkgCache::VerIterator &iterator) { [alert setContext:@"urlerror"]; [alert show]; + + href_ = nil; } else { UIAlertView *alert = [[[UIAlertView alloc] initWithTitle:UCLocalize("NOT_REPOSITORY") @@ -8061,9 +8396,10 @@ bool DepSubstrate(const pkgCache::VerIterator &iterator) { [alert setContext:@"trivial"]; [alert show]; + + href_ = nil; } - href_ = nil; error_ = nil; } } @@ -8086,8 +8422,10 @@ bool DepSubstrate(const pkgCache::VerIterator &iterator) { } - (NSURLConnection *) _requestHRef:(NSString *)href method:(NSString *)method { + NSURL *url([NSURL URLWithString:href]); + NSMutableURLRequest *request = [NSMutableURLRequest - requestWithURL:[NSURL URLWithString:href] + requestWithURL:url cachePolicy:NSURLRequestUseProtocolCachePolicy timeoutInterval:120.0 ]; @@ -8096,8 +8434,13 @@ bool DepSubstrate(const pkgCache::VerIterator &iterator) { if (Machine_ != NULL) [request setValue:[NSString stringWithUTF8String:Machine_] forHTTPHeaderField:@"X-Machine"]; - if (UniqueID_ != nil) - [request setValue:UniqueID_ forHTTPHeaderField:@"X-Unique-ID"]; + + if ([url isCydiaSecure]) { + if (UniqueID_ != nil) { + [request setValue:UniqueID_ forHTTPHeaderField:@"X-Unique-ID"]; + [request setValue:UniqueID_ forHTTPHeaderField:@"X-Cydia-Id"]; + } + } return [[[NSURLConnection alloc] initWithRequest:request delegate:self] autorelease]; } @@ -8144,7 +8487,7 @@ bool DepSubstrate(const pkgCache::VerIterator &iterator) { else if ([context isEqualToString:@"warning"]) { switch (button) { case 1: - [self complete]; + [self performSelector:@selector(complete) withObject:nil afterDelay:0]; break; case 0: @@ -8153,21 +8496,17 @@ bool DepSubstrate(const pkgCache::VerIterator &iterator) { _nodefault } - href_ = nil; - [alert dismissWithClickedButtonIndex:-1 animated:YES]; } } - (void) loadView { - [self setView:[[[UIView alloc] initWithFrame:[[UIScreen mainScreen] applicationFrame]] autorelease]]; - - list_ = [[[UITableView alloc] initWithFrame:[[self view] bounds] style:UITableViewStylePlain] autorelease]; + list_ = [[[UITableView alloc] initWithFrame:[[UIScreen mainScreen] applicationFrame] style:UITableViewStylePlain] autorelease]; [list_ setAutoresizingMask:UIViewAutoresizingFlexibleBoth]; - [list_ setRowHeight:56]; + [list_ setRowHeight:53]; [(UITableView *) list_ setDataSource:self]; [list_ setDelegate:self]; - [[self view] addSubview:list_]; + [self setView:list_]; } - (void) viewDidLoad { @@ -8179,26 +8518,32 @@ bool DepSubstrate(const pkgCache::VerIterator &iterator) { - (void) releaseSubviews { list_ = nil; + + sources_ = nil; + + [super releaseSubviews]; } - (id) initWithDatabase:(Database *)database { if ((self = [super init]) != nil) { database_ = database; - sources_ = [NSMutableArray arrayWithCapacity:16]; } return self; } - (void) reloadData { [super reloadData]; +@synchronized (database_) { + era_ = [database_ era]; + pkgSourceList list; if ([database_ popErrorWithTitle:UCLocalize("SOURCES") forOperation:list.ReadMainList()]) return; - [sources_ removeAllObjects]; + sources_ = [NSMutableArray arrayWithCapacity:16]; [sources_ addObjectsFromArray:[database_ sources]]; _trace(); - [sources_ sortUsingSelector:@selector(compareByNameAndType:)]; + [sources_ sortUsingSelector:@selector(compareByName:)]; _trace(); int count([sources_ count]); @@ -8212,7 +8557,7 @@ bool DepSubstrate(const pkgCache::VerIterator &iterator) { [list_ setEditing:NO]; [self updateButtonsForEditingStatus:NO animated:NO]; [list_ reloadData]; -} +} } - (void) showAddSourcePrompt { UIAlertView *alert = [[[UIAlertView alloc] @@ -8289,7 +8634,7 @@ bool DepSubstrate(const pkgCache::VerIterator &iterator) { _transient Database *database_; // XXX: ok, "roledelegate_"?... _transient id roledelegate_; - _H table_; + _H table_; _H segment_; _H container_; } @@ -8302,13 +8647,11 @@ bool DepSubstrate(const pkgCache::VerIterator &iterator) { @implementation SettingsController - (void) loadView { - [self setView:[[[UIView alloc] initWithFrame:[[UIScreen mainScreen] applicationFrame]] autorelease]]; - - table_ = [[[UITableView alloc] initWithFrame:[[self view] bounds] style:UITableViewStyleGrouped] autorelease]; + table_ = [[[UITableView alloc] initWithFrame:[[UIScreen mainScreen] applicationFrame] style:UITableViewStyleGrouped] autorelease]; [table_ setAutoresizingMask:UIViewAutoresizingFlexibleBoth]; [table_ setDelegate:self]; [(UITableView *) table_ setDataSource:self]; - [[self view] addSubview:table_]; + [self setView:table_]; NSArray *items = [NSArray arrayWithObjects: UCLocalize("USER"), @@ -8316,6 +8659,7 @@ bool DepSubstrate(const pkgCache::VerIterator &iterator) { UCLocalize("DEVELOPER"), nil]; segment_ = [[[UISegmentedControl alloc] initWithItems:items] autorelease]; + [segment_ setAutoresizingMask:(UIViewAutoresizingFlexibleWidth | UIViewAutoresizingFlexibleLeftMargin)]; container_ = [[[UIView alloc] initWithFrame:CGRectMake(0, 0, [[self view] frame].size.width, 44.0f)] autorelease]; [container_ addSubview:segment_]; } @@ -8342,6 +8686,8 @@ bool DepSubstrate(const pkgCache::VerIterator &iterator) { table_ = nil; segment_ = nil; container_ = nil; + + [super releaseSubviews]; } - (id) initWithDatabase:(Database *)database delegate:(id)delegate { @@ -8482,8 +8828,11 @@ bool DepSubstrate(const pkgCache::VerIterator &iterator) { @implementation StashController - (void) loadView { - [self setView:[[[UIView alloc] initWithFrame:[[UIScreen mainScreen] applicationFrame]] autorelease]]; - [[self view] setBackgroundColor:[UIColor viewFlipsideBackgroundColor]]; + UIView *view([[[UIView alloc] initWithFrame:[[UIScreen mainScreen] applicationFrame]] autorelease]); + [view setAutoresizingMask:(UIViewAutoresizingFlexibleWidth | UIViewAutoresizingFlexibleHeight)]; + [self setView:view]; + + [view setBackgroundColor:[UIColor viewFlipsideBackgroundColor]]; spinner_ = [[[UIActivityIndicatorView alloc] initWithActivityIndicatorStyle:UIActivityIndicatorViewStyleWhiteLarge] autorelease]; CGRect spinrect = [spinner_ frame]; @@ -8491,7 +8840,7 @@ bool DepSubstrate(const pkgCache::VerIterator &iterator) { spinrect.origin.y = [[self view] frame].size.height - 80.0f; [spinner_ setFrame:spinrect]; [spinner_ setAutoresizingMask:UIViewAutoresizingFlexibleLeftMargin | UIViewAutoresizingFlexibleRightMargin | UIViewAutoresizingFlexibleTopMargin]; - [[self view] addSubview:spinner_]; + [view addSubview:spinner_]; [spinner_ startAnimating]; CGRect captrect; @@ -8507,7 +8856,7 @@ bool DepSubstrate(const pkgCache::VerIterator &iterator) { [caption_ setBackgroundColor:[UIColor clearColor]]; [caption_ setShadowColor:[UIColor blackColor]]; [caption_ setTextAlignment:UITextAlignmentCenter]; - [[self view] addSubview:caption_]; + [view addSubview:caption_]; CGRect statusrect; statusrect.size.width = [[self view] frame].size.width; @@ -8522,7 +8871,15 @@ bool DepSubstrate(const pkgCache::VerIterator &iterator) { [status_ setBackgroundColor:[UIColor clearColor]]; [status_ setShadowColor:[UIColor blackColor]]; [status_ setTextAlignment:UITextAlignmentCenter]; - [[self view] addSubview:status_]; + [view addSubview:status_]; +} + +- (void) releaseSubviews { + spinner_ = nil; + status_ = nil; + caption_ = nil; + + [super releaseSubviews]; } @end @@ -8555,6 +8912,24 @@ bool DepSubstrate(const pkgCache::VerIterator &iterator) { #endif } +- (void) storeCachedResponse:(NSCachedURLResponse *)cached forRequest:(NSURLRequest *)request { + if (NSURLResponse *response = [cached response]) + if (NSString *mime = [response MIMEType]) + if ([mime isEqualToString:@"text/cache-manifest"]) { + NSURL *url([response URL]); + +#if !ForRelease + NSLog(@"###: %@", [url absoluteString]); +#endif + + @synchronized (HostConfig_) { + [CachedURLs_ addObject:url]; + } + } + + [super storeCachedResponse:cached forRequest:request]; +} + @end @interface Cydia : UIApplication < @@ -8566,7 +8941,7 @@ bool DepSubstrate(const pkgCache::VerIterator &iterator) { > { _H window_; _H tabbar_; - _H emulated_; + _H emulated_; _H essential_; _H broken_; @@ -8633,10 +9008,16 @@ bool DepSubstrate(const pkgCache::VerIterator &iterator) { } } +- (void) returnToCydia { + [self _loaded]; +} + - (void) _saveConfig { - _trace(); - MetaFile_.Sync(); - _trace(); + @synchronized (database_) { + _trace(); + MetaFile_.Sync(); + _trace(); + } if (Changed_) { NSString *error(nil); @@ -8653,6 +9034,8 @@ bool DepSubstrate(const pkgCache::VerIterator &iterator) { NSLog(@"failure to serialize metadata: %@", error); } } + + CydiaWriteSources(); } // Navigation controller for the queuing badge. @@ -8667,7 +9050,6 @@ bool DepSubstrate(const pkgCache::VerIterator &iterator) { - (void) _updateData { [self _saveConfig]; - [self unloadData]; UINavigationController *navigation = [self queueNavigationController]; @@ -8695,37 +9077,36 @@ bool DepSubstrate(const pkgCache::VerIterator &iterator) { // - We already auto-refreshed this launch. // - Auto-refresh is disabled. if (recently || loaded_ || ManualRefresh) { - [self performSelectorOnMainThread:@selector(_loaded) withObject:nil waitUntilDone:NO]; - // If we are cancelling, we need to make sure it knows it's already loaded. loaded_ = true; - return; + + [self performSelectorOnMainThread:@selector(_loaded) withObject:nil waitUntilDone:NO]; } else { // We are going to load, so remember that. loaded_ = true; - } - SCNetworkReachabilityFlags flags; { - SCNetworkReachabilityRef reachability(SCNetworkReachabilityCreateWithName(NULL, "cydia.saurik.com")); - SCNetworkReachabilityGetFlags(reachability, &flags); - CFRelease(reachability); - } + SCNetworkReachabilityFlags flags; { + SCNetworkReachabilityRef reachability(SCNetworkReachabilityCreateWithName(NULL, "cydia.saurik.com")); + SCNetworkReachabilityGetFlags(reachability, &flags); + CFRelease(reachability); + } - // XXX: this elaborate mess is what Apple is using to determine this? :( - // XXX: do we care if the user has to intervene? maybe that's ok? - bool reachable( - (flags & kSCNetworkReachabilityFlagsReachable) != 0 && ( - (flags & kSCNetworkReachabilityFlagsConnectionRequired) == 0 || ( - (flags & kSCNetworkReachabilityFlagsConnectionOnDemand) != 0 || - (flags & kSCNetworkReachabilityFlagsConnectionOnTraffic) != 0 - ) && (flags & kSCNetworkReachabilityFlagsInterventionRequired) == 0 || - (flags & kSCNetworkReachabilityFlagsIsWWAN) != 0 - ) - ); + // XXX: this elaborate mess is what Apple is using to determine this? :( + // XXX: do we care if the user has to intervene? maybe that's ok? + bool reachable( + (flags & kSCNetworkReachabilityFlagsReachable) != 0 && ( + (flags & kSCNetworkReachabilityFlagsConnectionRequired) == 0 || ( + (flags & kSCNetworkReachabilityFlagsConnectionOnDemand) != 0 || + (flags & kSCNetworkReachabilityFlagsConnectionOnTraffic) != 0 + ) && (flags & kSCNetworkReachabilityFlagsInterventionRequired) == 0 || + (flags & kSCNetworkReachabilityFlagsIsWWAN) != 0 + ) + ); - // If we can reach the server, auto-refresh! - if (reachable) - [tabbar_ performSelectorOnMainThread:@selector(setUpdate:) withObject:update waitUntilDone:NO]; + // If we can reach the server, auto-refresh! + if (reachable) + [tabbar_ performSelectorOnMainThread:@selector(setUpdate:) withObject:update waitUntilDone:NO]; + } [pool release]; } @@ -8734,15 +9115,13 @@ bool DepSubstrate(const pkgCache::VerIterator &iterator) { [NSThread detachNewThreadSelector:@selector(_refreshIfPossible:) toTarget:self withObject:[Metadata_ objectForKey:@"LastUpdate"]]; } -- (void) _reloadDataWithInvocation:(NSInvocation *)invocation { +- (void) reloadDataWithInvocation:(NSInvocation *)invocation { +@synchronized (self) { UIProgressHUD *hud(loaded_ ? [self addProgressHUD] : nil); [hud setText:UCLocalize("RELOADING_DATA")]; [database_ yieldToSelector:@selector(reloadDataWithInvocation:) withObject:invocation]; - if (hud != nil) - [self removeProgressHUD:hud]; - size_t changes(0); [essential_ removeAllObjects]; @@ -8759,8 +9138,6 @@ bool DepSubstrate(const pkgCache::VerIterator &iterator) { } } - NSLog(@"changes:#%u", changes); - UITabBarItem *changesItem = [[[tabbar_ viewControllers] objectAtIndex:2] tabBarItem]; if (changes != 0) { _trace(); @@ -8777,8 +9154,9 @@ bool DepSubstrate(const pkgCache::VerIterator &iterator) { [self _updateData]; - [self refreshIfPossible]; -} + if (hud != nil) + [self removeProgressHUD:hud]; +} } - (void) updateData { [self _updateData]; @@ -8786,12 +9164,7 @@ bool DepSubstrate(const pkgCache::VerIterator &iterator) { - (void) update_ { [database_ update]; -} - -- (void) complete { - @synchronized (self) { - [self _reloadDataWithInvocation:nil]; - } + [self performSelectorOnMainThread:@selector(reloadData) withObject:nil waitUntilDone:YES]; } - (void) disemulate { @@ -8848,47 +9221,31 @@ bool DepSubstrate(const pkgCache::VerIterator &iterator) { [self performSelectorOnMainThread:@selector(repairWithInvocation:) withObject:[NSInvocation invocationWithSelector:selector forTarget:database_] waitUntilDone:YES]; } +- (void) reloadData { + [self reloadDataWithInvocation:nil]; + if ([database_ progressDelegate] == nil) + [self _loaded]; +} + - (void) syncData { [self _saveConfig]; - - FILE *file(fopen("/etc/apt/sources.list.d/cydia.list", "w")); - _assert(file != NULL); - - for (NSString *key in [Sources_ allKeys]) { - NSDictionary *source([Sources_ objectForKey:key]); - - fprintf(file, "%s %s %s\n", - [[source objectForKey:@"Type"] UTF8String], - [[source objectForKey:@"URI"] UTF8String], - [[source objectForKey:@"Distribution"] UTF8String] - ); - } - - fclose(file); - [self detachNewProgressSelector:@selector(update_) toTarget:self forController:nil title:@"UPDATING_SOURCES"]; - - [self complete]; } -- (void) addTrivialSource:(NSString *)href { - [Sources_ setObject:[NSDictionary dictionaryWithObjectsAndKeys: - @"deb", @"Type", - href, @"URI", - @"./", @"Distribution", - nil] forKey:[NSString stringWithFormat:@"deb:%@:./", href]]; +- (void) addSource:(NSDictionary *) source { + CydiaAddSource(source); +} - Changed_ = true; +- (void) addSource:(NSString *)href withDistribution:(NSString *)distribution andSections:(NSArray *)sections { + CydiaAddSource(href, distribution, sections); } -- (void) reloadDataWithInvocation:(NSInvocation *)invocation { - @synchronized (self) { - [self _reloadDataWithInvocation:invocation]; - } +- (void) addTrivialSource:(NSString *)href { + CydiaAddSource(href, @"./"); } -- (void) reloadData { - [self reloadDataWithInvocation:nil]; +- (void) updateValues { + Changed_ = true; } - (void) resolve { @@ -8968,12 +9325,17 @@ bool DepSubstrate(const pkgCache::VerIterator &iterator) { } } +- (void) perform_ { + [database_ perform]; + [self performSelectorOnMainThread:@selector(reloadData) withObject:nil waitUntilDone:YES]; +} + - (void) confirmWithNavigationController:(UINavigationController *)navigation { Queuing_ = false; ++locked_; - [self detachNewProgressSelector:@selector(perform) toTarget:database_ forController:navigation title:@"RUNNING"]; + [self detachNewProgressSelector:@selector(perform_) toTarget:self forController:navigation title:@"RUNNING"]; --locked_; - [self complete]; + [self refreshIfPossible]; } - (void) showSettings { @@ -9065,10 +9427,14 @@ bool DepSubstrate(const pkgCache::VerIterator &iterator) { } } -- (void) system:(NSString *)command { _pooled +- (void) system:(NSString *)command { + NSAutoreleasePool *pool([[NSAutoreleasePool alloc] init]); + _trace(); system([command UTF8String]); _trace(); + + [pool release]; } - (void) applicationWillSuspend { @@ -9123,7 +9489,7 @@ bool DepSubstrate(const pkgCache::VerIterator &iterator) { } - (UIProgressHUD *) addProgressHUD { - UIProgressHUD *hud([[[UIProgressHUD alloc] initWithWindow:window_] autorelease]); + UIProgressHUD *hud([[[UIProgressHUD alloc] init] autorelease]); [hud setAutoresizingMask:UIViewAutoresizingFlexibleBoth]; [window_ setUserInteractionEnabled:NO]; @@ -9132,10 +9498,7 @@ bool DepSubstrate(const pkgCache::VerIterator &iterator) { if (UIViewController *modal = [target modalViewController]) target = modal; - UIView *view([target view]); - [view addSubview:hud]; - - [hud show:YES]; + [hud showInView:[target view]]; ++locked_; return hud; @@ -9143,7 +9506,7 @@ bool DepSubstrate(const pkgCache::VerIterator &iterator) { - (void) removeProgressHUD:(UIProgressHUD *)hud { --locked_; - [hud show:NO]; + [hud hide]; [hud removeFromSuperview]; [window_ setUserInteractionEnabled:YES]; } @@ -9157,7 +9520,7 @@ bool DepSubstrate(const pkgCache::VerIterator &iterator) { if ([[url absoluteString] length] <= [scheme length] + 3) return nil; NSString *path([[url absoluteString] substringFromIndex:[scheme length] + 3]); - NSArray *components([path pathComponents]); + NSArray *components([path componentsSeparatedByString:@"/"]); if ([scheme isEqualToString:@"apptapp"] && [components count] > 0 && [[components objectAtIndex:0] isEqualToString:@"package"]) return [self pageForPackage:[components objectAtIndex:1]]; @@ -9178,6 +9541,10 @@ bool DepSubstrate(const pkgCache::VerIterator &iterator) { controller = [[[ManageController alloc] init] autorelease]; } + if ([base isEqualToString:@"storage"]) { + controller = [[[CydiaWebViewController alloc] initWithURL:[NSURL URLWithString:[NSString stringWithFormat:@"%@/storage/", UI_]]] autorelease]; + } + if ([base isEqualToString:@"sources"]) { controller = [[[SourcesController alloc] initWithDatabase:database_] autorelease]; } @@ -9223,7 +9590,7 @@ bool DepSubstrate(const pkgCache::VerIterator &iterator) { controller = [[[SourcesController alloc] initWithDatabase:database_] autorelease]; [(SourcesController *)controller showAddSourcePrompt]; } else { - Source *source = [database_ sourceWithKey:argument]; + Source *source = [database_ sourceWithKey:[argument stringByReplacingPercentEscapesUsingEncoding:NSUTF8StringEncoding]]; controller = [[[SourceController alloc] initWithDatabase:database_ source:source] autorelease]; } } @@ -9255,11 +9622,8 @@ bool DepSubstrate(const pkgCache::VerIterator &iterator) { - (BOOL) openCydiaURL:(NSURL *)url forExternal:(BOOL)external { CyteViewController *page([self pageForURL:url forExternal:external]); - if (page != nil) { - UINavigationController *nav = [[[UINavigationController alloc] init] autorelease]; - [nav setViewControllers:[NSArray arrayWithObject:page]]; - [tabbar_ setUnselectedViewController:nav]; - } + if (page != nil) + [tabbar_ setUnselectedViewController:page]; return page != nil; } @@ -9282,15 +9646,19 @@ bool DepSubstrate(const pkgCache::VerIterator &iterator) { [super applicationWillResignActive:application]; } -- (void) applicationWillTerminate:(UIApplication *)application { - Changed_ = true; +- (void) saveState { [Metadata_ setObject:[tabbar_ navigationURLCollection] forKey:@"InterfaceState"]; [Metadata_ setObject:[NSDate date] forKey:@"LastClosed"]; [Metadata_ setObject:[NSNumber numberWithInt:[tabbar_ selectedIndex]] forKey:@"InterfaceIndex"]; + Changed_ = true; [self _saveConfig]; } +- (void) applicationWillTerminate:(UIApplication *)application { + [self saveState]; +} + - (void) setConfigurationData:(NSString *)data { static Pcre conffile_r("^'(.*)' '(.*)' ([01]) ([01])$"); @@ -9340,10 +9708,14 @@ bool DepSubstrate(const pkgCache::VerIterator &iterator) { [self removeStashController]; - if (ExecFork() == 0) { + pid_t pid(ExecFork()); + if (pid == 0) { execlp("launchctl", "launchctl", "stop", "com.apple.SpringBoard", NULL); perror("launchctl stop"); + exit(0); } + + ReapZombie(pid); } - (void) setupViewControllers { @@ -9374,7 +9746,29 @@ bool DepSubstrate(const pkgCache::VerIterator &iterator) { [tabbar_ setUpdateDelegate:self]; } +- (void) _sendMemoryWarningNotification { + if (kCFCoreFoundationVersionNumber < kCFCoreFoundationVersionNumber_iPhoneOS_3_0) // XXX: maybe 4_0? + [[NSNotificationCenter defaultCenter] postNotificationName:@"UIApplicationMemoryWarningNotification" object:[UIApplication sharedApplication]]; + else + [[NSNotificationCenter defaultCenter] postNotificationName:@"UIApplicationDidReceiveMemoryWarningNotification" object:[UIApplication sharedApplication]]; +} + +- (void) _sendMemoryWarningNotifications { + while (true) { + [self performSelectorOnMainThread:@selector(_sendMemoryWarningNotification) withObject:nil waitUntilDone:NO]; + sleep(2); + //usleep(2000000); + } +} + +- (void) applicationDidReceiveMemoryWarning:(UIApplication *)application { + NSLog(@"--"); + [[NSURLCache sharedURLCache] removeAllCachedResponses]; +} + - (void) applicationDidFinishLaunching:(id)unused { + //[NSThread detachNewThreadSelector:@selector(_sendMemoryWarningNotifications) toTarget:self withObject:nil]; + _trace(); if ([self respondsToSelector:@selector(setApplicationSupportsShakeToEdit:)]) [self setApplicationSupportsShakeToEdit:NO]; @@ -9406,7 +9800,7 @@ _trace(); broken_ = [NSMutableArray arrayWithCapacity:4]; // XXX: I really need this thing... like, seriously... I'm sorry - [[[CydiaWebViewController alloc] initWithURL:[NSURL URLWithString:[NSString stringWithFormat:@"%@/appcache/", UI_]]] reloadData]; + [[[AppCacheController alloc] initWithURL:[NSURL URLWithString:[NSString stringWithFormat:@"%@/appcache/", UI_]]] reloadData]; window_ = [[[UIWindow alloc] initWithFrame:[[UIScreen mainScreen] bounds]] autorelease]; [window_ orderFront:self]; @@ -9439,7 +9833,7 @@ _trace(); [window_ setUserInteractionEnabled:NO]; [self setupViewControllers]; - emulated_ = [[[CYEmulatedLoadingController alloc] initWithDatabase:database_] autorelease]; + emulated_ = [[[CydiaLoadingViewController alloc] init] autorelease]; [window_ addSubview:[emulated_ view]]; [self performSelector:@selector(loadData) withObject:nil afterDelay:0]; @@ -9473,7 +9867,8 @@ _trace(); [window_ setUserInteractionEnabled:NO]; } - [self reloadData]; + [self reloadDataWithInvocation:nil]; + [self refreshIfPossible]; PrintTimes(); [self disemulate]; @@ -9491,8 +9886,8 @@ _trace(); NSDate *closed = [Metadata_ objectForKey:@"LastClosed"]; if (valid && closed != nil) { NSTimeInterval interval([closed timeIntervalSinceNow]); - // XXX: Is 15 minutes the optimal time here? - if (interval > 0 && interval <= -(15*60)) + // XXX: Is 30 minutes the optimal time here? + if (interval <= -(30*60)) valid = NO; } @@ -9635,6 +10030,7 @@ MSHook(id, NSURLConnection$init$, NSURLConnection *self, SEL _cmd, NSURLRequest NSMutableURLRequest *copy([request mutableCopy]); NSURL *url([copy URL]); + NSString *host([url host]); NSString *scheme([[url scheme] lowercaseString]); @@ -9644,13 +10040,29 @@ MSHook(id, NSURLConnection$init$, NSURLConnection *self, SEL _cmd, NSURLRequest if ([copy respondsToSelector:@selector(setHTTPShouldUsePipelining:)]) if ([PipelinedHosts_ containsObject:host] || [PipelinedHosts_ containsObject:compound]) [copy setHTTPShouldUsePipelining:YES]; + + if (NSString *control = [copy valueForHTTPHeaderField:@"Cache-Control"]) + if ([control isEqualToString:@"max-age=0"]) + if ([CachedURLs_ containsObject:url]) { +#if !ForRelease + NSLog(@"~~~: %@", url); +#endif + + [copy setCachePolicy:NSURLRequestReturnCacheDataDontLoad]; + + [copy setValue:nil forHTTPHeaderField:@"Cache-Control"]; + [copy setValue:nil forHTTPHeaderField:@"If-Modified-Since"]; + [copy setValue:nil forHTTPHeaderField:@"If-None-Match"]; + } } if ((self = _NSURLConnection$init$(self, _cmd, copy, delegate, usesCache, maxContentLength, startImmediately, connectionProperties)) != nil) { } return self; } -int main(int argc, char *argv[]) { _pooled +int main(int argc, char *argv[]) { + NSAutoreleasePool *pool([[NSAutoreleasePool alloc] init]); + _trace(); UpdateExternalStatus(0); @@ -9680,15 +10092,29 @@ int main(int argc, char *argv[]) { _pooled NSLog(@"unknown UIUserInterfaceIdiom!"); } + Pcre pattern("^([0-9]+\\.[0-9]+)"); + + if (pattern([device systemVersion])) + Firmware_ = pattern[1]; + if (pattern(Cydia_)) + Major_ = pattern[1]; + SessionData_ = [NSMutableDictionary dictionaryWithCapacity:4]; HostConfig_ = [[[NSObject alloc] init] autorelease]; @synchronized (HostConfig_) { BridgedHosts_ = [NSMutableSet setWithCapacity:4]; + TokenHosts_ = [NSMutableSet setWithCapacity:4]; + InsecureHosts_ = [NSMutableSet setWithCapacity:4]; PipelinedHosts_ = [NSMutableSet setWithCapacity:4]; + CachedURLs_ = [NSMutableSet setWithCapacity:32]; } - UI_ = CydiaURL([NSString stringWithFormat:@"ui/ios~%@", Idiom_]); + NSString *ui(@"ui/ios"); + if (Idiom_ != nil) + ui = [ui stringByAppendingString:[NSString stringWithFormat:@"~%@", Idiom_]]; + ui = [ui stringByAppendingString:[NSString stringWithFormat:@"/%@", Major_]]; + UI_ = CydiaURL(ui); PackageName = reinterpret_cast(method_getImplementation(class_getInstanceMethod([Package class], @selector(cyname)))); @@ -9824,34 +10250,27 @@ int main(int argc, char *argv[]) { _pooled else Machine_ = machine; - SerialNumber_ = CYIOGetValue("IOService:/", @"IOPlatformSerialNumber"); - ChipID_ = [CYHex(CYIOGetValue("IODeviceTree:/chosen", @"unique-chip-id"), true) uppercaseString]; - BBSNum_ = CYHex(CYIOGetValue("IOService:/AppleARMPE/baseband", @"snum"), false); - - UniqueID_ = [[UIDevice currentDevice] uniqueIdentifier]; + SerialNumber_ = (NSString *) CYIOGetValue("IOService:/", @"IOPlatformSerialNumber"); + ChipID_ = [CYHex((NSData *) CYIOGetValue("IODeviceTree:/chosen", @"unique-chip-id"), true) uppercaseString]; + BBSNum_ = CYHex((NSData *) CYIOGetValue("IOService:/AppleARMPE/baseband", @"snum"), false); - CFStringRef (*$CTSIMSupportCopyMobileSubscriberCountryCode)(CFAllocatorRef); - $CTSIMSupportCopyMobileSubscriberCountryCode = reinterpret_cast(dlsym(RTLD_DEFAULT, "CTSIMSupportCopyMobileSubscriberCountryCode")); - CFStringRef mcc($CTSIMSupportCopyMobileSubscriberCountryCode == NULL ? NULL : (*$CTSIMSupportCopyMobileSubscriberCountryCode)(kCFAllocatorDefault)); + UniqueID_ = [device uniqueIdentifier]; - CFStringRef (*$CTSIMSupportCopyMobileSubscriberNetworkCode)(CFAllocatorRef); - $CTSIMSupportCopyMobileSubscriberNetworkCode = reinterpret_cast(dlsym(RTLD_DEFAULT, "CTSIMSupportCopyMobileSubscriberCountryCode")); - CFStringRef mnc($CTSIMSupportCopyMobileSubscriberNetworkCode == NULL ? NULL : (*$CTSIMSupportCopyMobileSubscriberNetworkCode)(kCFAllocatorDefault)); - - if (mcc != NULL && mnc != NULL) - PLMN_ = [NSString stringWithFormat:@"%@%@", mcc, mnc]; - - if (mnc != NULL) - CFRelease(mnc); - if (mcc != NULL) - CFRelease(mcc); - - if (NSDictionary *system = [NSDictionary dictionaryWithContentsOfFile:@"/System/Library/CoreServices/SystemVersion.plist"]) - Build_ = [system objectForKey:@"ProductBuildVersion"]; if (NSDictionary *info = [NSDictionary dictionaryWithContentsOfFile:@"/Applications/MobileSafari.app/Info.plist"]) { Product_ = [info objectForKey:@"SafariProductVersion"]; Safari_ = [info objectForKey:@"CFBundleVersion"]; } + + NSString *agent([NSString stringWithFormat:@"Cydia/%@ CF/%.2f", Cydia_, kCFCoreFoundationVersionNumber]); + + if (Pcre match = Pcre("^[0-9]+(\\.[0-9]+)+", Safari_)) + agent = [NSString stringWithFormat:@"Safari/%@ %@", match[0], agent]; + if (Pcre match = Pcre("^[0-9]+[A-Z][0-9]+[a-z]?", System_)) + agent = [NSString stringWithFormat:@"Mobile/%@ %@", match[0], agent]; + if (Pcre match = Pcre("^[0-9]+(\\.[0-9]+)+", Product_)) + agent = [NSString stringWithFormat:@"Version/%@ %@", match[0], agent]; + + UserAgent_ = agent; /* }}} */ /* Load Database {{{ */ _trace(); @@ -9865,15 +10284,24 @@ int main(int argc, char *argv[]) { _pooled Settings_ = [Metadata_ objectForKey:@"Settings"]; Packages_ = [Metadata_ objectForKey:@"Packages"]; + + Values_ = [Metadata_ objectForKey:@"Values"]; Sections_ = [Metadata_ objectForKey:@"Sections"]; Sources_ = [Metadata_ objectForKey:@"Sources"]; Token_ = [Metadata_ objectForKey:@"Token"]; + + Version_ = [Metadata_ objectForKey:@"Version"]; } if (Settings_ != nil) Role_ = [Settings_ objectForKey:@"Role"]; + if (Values_ == nil) { + Values_ = [[[NSMutableDictionary alloc] initWithCapacity:4] autorelease]; + [Metadata_ setObject:Values_ forKey:@"Values"]; + } + if (Sections_ == nil) { Sections_ = [[[NSMutableDictionary alloc] initWithCapacity:32] autorelease]; [Metadata_ setObject:Sections_ forKey:@"Sections"]; @@ -9883,8 +10311,29 @@ int main(int argc, char *argv[]) { _pooled Sources_ = [[[NSMutableDictionary alloc] initWithCapacity:0] autorelease]; [Metadata_ setObject:Sources_ forKey:@"Sources"]; } + + if (Version_ == nil) { + Version_ = [NSNumber numberWithUnsignedInt:0]; + [Metadata_ setObject:Version_ forKey:@"Version"]; + } + + if ([Version_ unsignedIntValue] == 0) { + CydiaAddSource(@"http://apt.thebigboss.org/repofiles/cydia/", @"stable", [NSMutableArray arrayWithObject:@"main"]); + CydiaAddSource(@"http://apt.modmyi.com/", @"stable", [NSMutableArray arrayWithObject:@"main"]); + CydiaAddSource(@"http://cydia.zodttd.com/repo/cydia/", @"stable", [NSMutableArray arrayWithObject:@"main"]); + CydiaAddSource(@"http://repo666.ultrasn0w.com/", @"./"); + + Version_ = [NSNumber numberWithUnsignedInt:1]; + [Metadata_ setObject:Version_ forKey:@"Version"]; + + [Metadata_ removeObjectForKey:@"LastUpdate"]; + + Changed_ = true; + } /* }}} */ + CydiaWriteSources(); + _trace(); MetaFile_.Open("/var/lib/cydia/metadata.cb0"); _trace(); @@ -9920,11 +10369,7 @@ int main(int argc, char *argv[]) { _pooled 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 < 4) { - firmware: + if (access("/User", F_OK) != 0 || version != 5) { _trace(); system("/usr/libexec/cydia/firmware.sh"); _trace(); @@ -9992,5 +10437,6 @@ int main(int argc, char *argv[]) { _pooled CGColorSpaceRelease(space_); CFRelease(Locale_); + [pool release]; return value; }