X-Git-Url: https://git.saurik.com/cydia.git/blobdiff_plain/92d4a16a35b9963afc5b644b168df1488fc72af0..185f1f6fb02a64bbadb68cfe47c23a063a644f9b:/Cydia.mm?ds=inline diff --git a/Cydia.mm b/Cydia.mm index 57b24dfc..bac29757 100644 --- a/Cydia.mm +++ b/Cydia.mm @@ -1,5 +1,5 @@ /* Cydia - iPhone UIKit Front-End for Debian APT - * Copyright (C) 2008 Jay Freeman (saurik) + * Copyright (C) 2008-2009 Jay Freeman (saurik) */ /* @@ -39,7 +39,8 @@ #define USE_SYSTEM_MALLOC 1 /* #include Directives {{{ */ -#import "UICaboodle.h" +#import "UICaboodle/UCPlatform.h" +#import "UICaboodle/UCLocalize.h" #include #include @@ -49,12 +50,21 @@ #include #include -#import +#if 0 +#define DEPLOYMENT_TARGET_MACOSX 1 +#define CF_BUILDING_CF 1 +#include +#endif + +#include +#include + #import #include #import +#include #include #include #include @@ -67,6 +77,7 @@ #include #include #include +#include #include #include #include @@ -76,6 +87,7 @@ #include #include #include +#include #include @@ -101,8 +113,8 @@ extern "C" { #include -#import "BrowserView.h" -#import "ResetView.h" +#import "UICaboodle/BrowserView.h" +#import "UICaboodle/ResetView.h" #import "substrate.h" /* }}} */ @@ -204,6 +216,11 @@ class _H { } public: + _finline _H(const This_ &rhs) : + value_(rhs.value_ == nil ? nil : [rhs.value_ retain]) + { + } + _finline _H(Type_ *value = NULL, bool mended = false) : value_(value) { @@ -215,12 +232,18 @@ class _H { Clear_(); } + _finline operator Type_ *() const { + return value_; + } + _finline This_ &operator =(Type_ *value) { if (value_ != value) { - Clear_(); + Type_ *old(value_); value_ = value; Retain_(); - } return this; + if (old != nil) + [old release]; + } return *this; } }; /* }}} */ @@ -253,8 +276,9 @@ void NSLogRect(const char *fix, const CGRect &rect) { /* XXX: deal with exceptions */ id value([self performSelector:selector withObject:object]); + NSMethodSignature *signature([self methodSignatureForSelector:selector]); [context removeAllObjects]; - if (value != nil) + if ([signature methodReturnLength] != 0 && value != nil) [context addObject:value]; stopped = true; @@ -301,9 +325,8 @@ void NSLogRect(const char *fix, const CGRect &rect) { /* NSForcedOrderingSearch doesn't work on the iPhone */ static const NSStringCompareOptions MatchCompareOptions_ = NSLiteralSearch | NSCaseInsensitiveSearch; -static const NSStringCompareOptions BaseCompareOptions_ = NSNumericSearch | NSDiacriticInsensitiveSearch | NSWidthInsensitiveSearch; -static const NSStringCompareOptions ForcedCompareOptions_ = BaseCompareOptions_; -static const NSStringCompareOptions LaxCompareOptions_ = BaseCompareOptions_ | NSCaseInsensitiveSearch; +static const NSStringCompareOptions LaxCompareOptions_ = NSNumericSearch | NSDiacriticInsensitiveSearch | NSWidthInsensitiveSearch | NSCaseInsensitiveSearch; +static const CFStringCompareFlags LaxCompareFlags_ = kCFCompareCaseInsensitive | kCFCompareNonliteral | kCFCompareLocalized | kCFCompareNumerically | kCFCompareWidthInsensitive | kCFCompareForcedOrdering; /* iPhoneOS 2.0 Compatibility {{{ */ #ifdef __OBJC2__ @@ -321,8 +344,6 @@ static const NSStringCompareOptions LaxCompareOptions_ = BaseCompareOptions_ | N #endif /* }}} */ -extern NSString * const kCAFilterNearest; - /* Information Dictionaries {{{ */ @interface NSMutableArray (Cydia) - (void) addInfoDictionary:(NSDictionary *)info; @@ -385,18 +406,25 @@ extern NSString * const kCAFilterNearest; #define lprintf(args...) fprintf(stderr, args) -#define ForRelease 0 +#define ForRelease 1 +#define TraceLogging (1 && !ForRelease) +#define HistogramInsertionSort (0 && !ForRelease) +#define ProfileTimes (0 && !ForRelease) #define ForSaurik (0 && !ForRelease) #define LogBrowser (1 && !ForRelease) +#define TrackResize (0 && !ForRelease) #define ManualRefresh (1 && !ForRelease) #define ShowInternals (0 && !ForRelease) #define IgnoreInstall (0 && !ForRelease) #define RecycleWebViews 0 #define AlwaysReload (1 && !ForRelease) -#if ForRelease +#if !TraceLogging #undef _trace #define _trace(args...) +#endif + +#if !ProfileTimes #undef _profile #define _profile(name) { #undef _end @@ -405,9 +433,11 @@ extern NSString * const kCAFilterNearest; #endif /* Radix Sort {{{ */ +typedef uint32_t (*SKRadixFunction)(id, void *); + @interface NSMutableArray (Radix) - (void) radixSortUsingSelector:(SEL)selector withObject:(id)object; -- (void) radixSortUsingFunction:(uint32_t (*)(id, void *))function withArgument:(void *)argument; +- (void) radixSortUsingFunction:(SKRadixFunction)function withContext:(void *)argument; @end struct RadixItem_ { @@ -467,11 +497,22 @@ static void RadixSort_(NSMutableArray *self, size_t count, struct RadixItem_ *sw @implementation NSMutableArray (Radix) - (void) radixSortUsingSelector:(SEL)selector withObject:(id)object { + size_t count([self count]); + if (count == 0) + return; + +#if 0 NSInvocation *invocation([NSInvocation invocationWithMethodSignature:[NSMethodSignature signatureWithObjCTypes:"L12@0:4@8"]]); [invocation setSelector:selector]; [invocation setArgument:&object atIndex:2]; +#else + /* XXX: this is an unsafe optimization of doomy hell */ + Method method(class_getInstanceMethod([[self objectAtIndex:0] class], selector)); + _assert(method != NULL); + uint32_t (*imp)(id, SEL, id) = reinterpret_cast(method_getImplementation(method)); + _assert(imp != NULL); +#endif - size_t count([self count]); struct RadixItem_ *swap(new RadixItem_[count * 2]); for (size_t i(0); i != count; ++i) { @@ -479,16 +520,20 @@ static void RadixSort_(NSMutableArray *self, size_t count, struct RadixItem_ *sw item.index = i; id object([self objectAtIndex:i]); - [invocation setTarget:object]; +#if 0 + [invocation setTarget:object]; [invocation invoke]; [invocation getReturnValue:&item.key]; +#else + item.key = imp(object, selector, object); +#endif } RadixSort_(self, count, swap); } -- (void) radixSortUsingFunction:(uint32_t (*)(id, void *))function withArgument:(void *)argument { +- (void) radixSortUsingFunction:(SKRadixFunction)function withContext:(void *)argument { size_t count([self count]); struct RadixItem_ *swap(new RadixItem_[count * 2]); @@ -504,6 +549,77 @@ static void RadixSort_(NSMutableArray *self, size_t count, struct RadixItem_ *sw } @end +/* }}} */ +/* Insertion Sort {{{ */ + +CFIndex SKBSearch_(const void *element, CFIndex elementSize, const void *list, CFIndex count, CFComparatorFunction comparator, void *context) { + const char *ptr = (const char *)list; + while (0 < count) { + CFIndex half = count / 2; + const char *probe = ptr + elementSize * half; + CFComparisonResult cr = comparator(element, probe, context); + if (0 == cr) return (probe - (const char *)list) / elementSize; + ptr = (cr < 0) ? ptr : probe + elementSize; + count = (cr < 0) ? half : (half + (count & 1) - 1); + } + return (ptr - (const char *)list) / elementSize; +} + +CFIndex CFBSearch_(const void *element, CFIndex elementSize, const void *list, CFIndex count, CFComparatorFunction comparator, void *context) { + const char *ptr = (const char *)list; + while (0 < count) { + CFIndex half = count / 2; + const char *probe = ptr + elementSize * half; + CFComparisonResult cr = comparator(element, probe, context); + if (0 == cr) return (probe - (const char *)list) / elementSize; + ptr = (cr < 0) ? ptr : probe + elementSize; + count = (cr < 0) ? half : (half + (count & 1) - 1); + } + return (ptr - (const char *)list) / elementSize; +} + +void CFArrayInsertionSortValues(CFMutableArrayRef array, CFRange range, CFComparatorFunction comparator, void *context) { + if (range.length == 0) + return; + const void **values(new const void *[range.length]); + CFArrayGetValues(array, range, values); + +#if HistogramInsertionSort + uint32_t total(0), *offsets(new uint32_t[range.length]); +#endif + + for (CFIndex index(1); index != range.length; ++index) { + const void *value(values[index]); + //CFIndex correct(SKBSearch_(&value, sizeof(const void *), values, index, comparator, context)); + CFIndex correct(index); + while (comparator(value, values[correct - 1], context) == kCFCompareLessThan) + if (--correct == 0) + break; + if (correct != index) { + size_t offset(index - correct); +#if HistogramInsertionSort + total += offset; + ++offsets[offset]; + if (offset > 10) + NSLog(@"Heavy Insertion Displacement: %u = %@", offset, value); +#endif + memmove(values + correct + 1, values + correct, sizeof(const void *) * offset); + values[correct] = value; + } + } + + CFArrayReplaceValues(array, range, values, range.length); + delete [] values; + +#if HistogramInsertionSort + for (CFIndex index(0); index != range.length; ++index) + if (offsets[index] != 0) + NSLog(@"Insertion Displacement [%u]: %u", index, offsets[index]); + NSLog(@"Average Insertion Displacement: %f", double(total) / range.length); + delete [] offsets; +#endif +} + /* }}} */ /* Apple Bug Fixes {{{ */ @@ -638,12 +754,6 @@ NSUInteger DOMNodeList$countByEnumeratingWithState$objects$count$(DOMNodeList *s @end -static inline NSString *CYLocalizeEx(NSString *key, NSString *value = nil) { - return [[NSBundle mainBundle] localizedStringForKey:key value:value table:nil]; -} - -#define CYLocalize(key) CYLocalizeEx(@ key) - class CYString { private: char *data_; @@ -651,8 +761,10 @@ class CYString { CFStringRef cache_; _finline void clear_() { - if (cache_ != nil) + if (cache_ != NULL) { CFRelease(cache_); + cache_ = NULL; + } } public: @@ -676,7 +788,7 @@ class CYString { _finline CYString() : data_(0), size_(0), - cache_(nil) + cache_(NULL) { } @@ -700,8 +812,9 @@ class CYString { else { clear_(); - char *temp(reinterpret_cast(apr_palloc(pool, size))); + char *temp(reinterpret_cast(apr_palloc(pool, size + 1))); memcpy(temp, data, size); + temp[size] = '\0'; data_ = temp; size_ = size; } @@ -719,12 +832,16 @@ class CYString { return size_ == rhs.size_ && memcmp(data_, rhs.data_, size_) == 0; } - operator id() { + operator CFStringRef() { if (cache_ == NULL) { if (size_ == 0) return nil; cache_ = CFStringCreateWithBytesNoCopy(kCFAllocatorDefault, reinterpret_cast(data_), size_, kCFStringEncodingUTF8, NO, kCFAllocatorNull); - } return (id) cache_; + } return cache_; + } + + _finline operator id() { + return (NSString *) static_cast(*this); } }; @@ -926,7 +1043,6 @@ static const int ButtonBarHeight_ = 48; static const float KeyboardTime_ = 0.3f; #define SpringBoard_ "/System/Library/LaunchDaemons/com.apple.SpringBoard.plist" -#define SandboxTemplate_ "/usr/share/sandbox/SandboxTemplate.sb" #define NotifyConfig_ "/etc/notify.conf" static bool Queuing_; @@ -965,6 +1081,7 @@ static const NSString *Product_ = nil; static const NSString *Safari_ = nil; CFLocaleRef Locale_; +NSArray *Languages_; CGColorSpaceRef space_; bool bootstrap_; @@ -988,7 +1105,7 @@ NSString *GetLastUpdate() { NSDate *update = [Metadata_ objectForKey:@"LastUpdate"]; if (update == nil) - return CYLocalize("NEVER_OR_UNKNOWN"); + return UCLocalize("NEVER_OR_UNKNOWN"); CFDateFormatterRef formatter = CFDateFormatterCreate(NULL, Locale_, kCFDateFormatterMediumStyle, kCFDateFormatterMediumStyle); CFStringRef formatted = CFDateFormatterCreateStringWithDate(NULL, formatter, (CFDateRef) update); @@ -1020,15 +1137,39 @@ NSString *SizeString(double size) { return [NSString stringWithFormat:@"%s%.1f %s", (negative ? "-" : ""), size, powers_[power]]; } -NSString *StripVersion(NSString *version) { - NSRange colon = [version rangeOfString:@":"]; - if (colon.location != NSNotFound) - version = [version substringFromIndex:(colon.location + 1)]; +static _finline CFStringRef CFCString(const char *value) { + return CFStringCreateWithBytesNoCopy(kCFAllocatorDefault, reinterpret_cast(value), strlen(value), kCFStringEncodingUTF8, NO, kCFAllocatorNull); +} + +const char *StripVersion_(const char *version) { + const char *colon(strchr(version, ':')); + if (colon != NULL) + version = colon + 1; return version; } +CFStringRef StripVersion(const char *version) { + const char *colon(strchr(version, ':')); + if (colon != NULL) + version = colon + 1; + return CFStringCreateWithBytes(kCFAllocatorDefault, reinterpret_cast(version), strlen(version), kCFStringEncodingUTF8, NO); + // XXX: performance + return CFCString(version); +} + NSString *LocalizeSection(NSString *section) { - return section; + static Pcre title_r("^(.*?) \\((.*)\\)$"); + if (title_r(section)) { + NSString *parent(title_r[1]); + NSString *child(title_r[2]); + + return [NSString stringWithFormat:UCLocalize("PARENTHETICAL"), + LocalizeSection(parent), + LocalizeSection(child) + ]; + } + + return [[NSBundle mainBundle] localizedStringForKey:section value:nil table:@"Sections"]; } NSString *Simplify(NSString *title) { @@ -1043,7 +1184,7 @@ NSString *Simplify(NSString *title) { if (paren_r(data, size)) return Simplify(paren_r[1]); - static Pcre title_r("^(.*?) \\(.*\\)$"); + static Pcre title_r("^(.*?) \\((.*)\\)$"); if (title_r(data, size)) return Simplify(title_r[1]); @@ -1052,8 +1193,8 @@ NSString *Simplify(NSString *title) { /* }}} */ bool isSectionVisible(NSString *section) { - NSDictionary *metadata = [Sections_ objectForKey:section]; - NSNumber *hidden = metadata == nil ? nil : [metadata objectForKey:@"Hidden"]; + NSDictionary *metadata([Sections_ objectForKey:section]); + NSNumber *hidden(metadata == nil ? nil : [metadata objectForKey:@"Hidden"]); return hidden == nil || ![hidden boolValue]; } @@ -1103,10 +1244,7 @@ bool isSectionVisible(NSString *section) { - (void) askForSettings; - (UIProgressHUD *) addProgressHUD; - (void) removeProgressHUD:(UIProgressHUD *)hud; -- (RVPage *) pageForURL:(NSURL *)url hasTag:(int *)tag; - (RVPage *) pageForPackage:(NSString *)name; -- (void) openMailToURL:(NSURL *)url; -- (void) clearFirstResponder; - (PackageView *) packageView; @end /* }}} */ @@ -1217,6 +1355,8 @@ class Progress : /* }}} */ /* Database Interface {{{ */ +typedef std::map< unsigned long, _H > SourceMap; + @interface Database : NSObject { NSZone *zone_; apr_pool_t *pool_; @@ -1232,7 +1372,7 @@ class Progress : SPtr manager_; pkgSourceList *list_; - NSMutableDictionary *sources_; + SourceMap sources_; NSMutableArray *packages_; _transient NSObject *delegate_; @@ -1271,35 +1411,39 @@ class Progress : - (void) upgrade; - (void) update; -- (void) updateWithStatus:(Status &)status; +- (NSString *) updateWithStatus:(Status &)status; - (void) setDelegate:(id)delegate; -- (Source *) getSource:(const pkgCache::PkgFileIterator &)file; +- (Source *) getSource:(pkgCache::PkgFileIterator)file; @end /* }}} */ /* Source Class {{{ */ @interface Source : NSObject { - NSString *description_; - NSString *label_; - NSString *origin_; - NSString *support_; + CYString depiction_; + CYString description_; + CYString label_; + CYString origin_; + CYString support_; - NSString *uri_; - NSString *distribution_; - NSString *type_; - NSString *version_; + CYString uri_; + CYString distribution_; + CYString type_; + CYString version_; + + NSString *host_; - NSString *defaultIcon_; + CYString defaultIcon_; NSDictionary *record_; BOOL trusted_; } -- (Source *) initWithMetaIndex:(metaIndex *)index; +- (Source *) initWithMetaIndex:(metaIndex *)index inPool:(apr_pool_t *)pool; - (NSComparisonResult) compareByNameAndType:(Source *)source; +- (NSString *) depictionForPackage:(NSString *)package; - (NSString *) supportForPackage:(NSString *)package; - (NSDictionary *) record; @@ -1323,23 +1467,28 @@ class Progress : @implementation Source -#define _clear(field) \ - if (field != nil) \ - [field release]; \ - field = nil; - - (void) _clear { - _clear(uri_) - _clear(distribution_) - _clear(type_) + uri_.clear(); + distribution_.clear(); + type_.clear(); + + description_.clear(); + label_.clear(); + origin_.clear(); + depiction_.clear(); + support_.clear(); + version_.clear(); + defaultIcon_.clear(); + + if (record_ != nil) { + [record_ release]; + record_ = nil; + } - _clear(description_) - _clear(label_) - _clear(origin_) - _clear(support_) - _clear(version_) - _clear(defaultIcon_) - _clear(record_) + if (host_ != nil) { + [host_ release]; + host_ = nil; + } } - (void) dealloc { @@ -1359,52 +1508,60 @@ class Progress : return ![[self _attributeKeys] containsObject:[NSString stringWithUTF8String:name]] && [super isKeyExcludedFromWebScript:name]; } -- (void) setMetaIndex:(metaIndex *)index { +- (void) setMetaIndex:(metaIndex *)index inPool:(apr_pool_t *)pool { [self _clear]; trusted_ = index->IsTrusted(); - uri_ = [[NSString stringWithUTF8String:index->GetURI().c_str()] retain]; - distribution_ = [[NSString stringWithUTF8String:index->GetDist().c_str()] retain]; - type_ = [[NSString stringWithUTF8String:index->GetType()] retain]; + uri_.set(pool, index->GetURI()); + distribution_.set(pool, index->GetDist()); + type_.set(pool, index->GetType()); debReleaseIndex *dindex(dynamic_cast(index)); if (dindex != NULL) { - std::ifstream release(dindex->MetaIndexFile("Release").c_str()); - std::string line; - while (std::getline(release, line)) { - std::string::size_type colon(line.find(':')); - if (colon == std::string::npos) - continue; - - std::string name(line.substr(0, colon)); - std::string value(line.substr(colon + 1)); - while (!value.empty() && value[0] == ' ') - value = value.substr(1); - - if (name == "Default-Icon") - defaultIcon_ = [[NSString stringWithUTF8String:value.c_str()] retain]; - else if (name == "Description") - description_ = [[NSString stringWithUTF8String:value.c_str()] retain]; - else if (name == "Label") - label_ = [[NSString stringWithUTF8String:value.c_str()] retain]; - else if (name == "Origin") - origin_ = [[NSString stringWithUTF8String:value.c_str()] retain]; - else if (name == "Support") - support_ = [[NSString stringWithUTF8String:value.c_str()] retain]; - else if (name == "Version") - version_ = [[NSString stringWithUTF8String:value.c_str()] retain]; + FileFd fd; + if (!fd.Open(dindex->MetaIndexFile("Release"), FileFd::ReadOnly)) + _error->Discard(); + else { + pkgTagFile tags(&fd); + + pkgTagSection section; + tags.Step(section); + + struct { + const char *name_; + CYString *value_; + } names[] = { + {"default-icon", &defaultIcon_}, + {"depiction", &depiction_}, + {"description", &description_}, + {"label", &label_}, + {"origin", &origin_}, + {"support", &support_}, + {"version", &version_}, + }; + + for (size_t i(0); i != sizeof(names) / sizeof(names[0]); ++i) { + const char *start, *end; + + if (section.Find(names[i].name_, start, end)) { + CYString &value(*names[i].value_); + value.set(pool, start, end - start); + } + } } } record_ = [Sources_ objectForKey:[self key]]; if (record_ != nil) record_ = [record_ retain]; + + host_ = [[[[NSURL URLWithString:uri_] host] lowercaseString] retain]; } -- (Source *) initWithMetaIndex:(metaIndex *)index { +- (Source *) initWithMetaIndex:(metaIndex *)index inPool:(apr_pool_t *)pool { if ((self = [super init]) != nil) { - [self setMetaIndex:index]; + [self setMetaIndex:index inPool:pool]; } return self; } @@ -1431,8 +1588,12 @@ class Progress : return [lhs compare:rhs options:LaxCompareOptions_]; } +- (NSString *) depictionForPackage:(NSString *)package { + return depiction_.empty() ? nil : [depiction_ stringByReplacingOccurrencesOfString:@"*" withString:package]; +} + - (NSString *) supportForPackage:(NSString *)package { - return support_ == nil ? nil : [support_ stringByReplacingOccurrencesOfString:@"*" withString:package]; + return support_.empty() ? nil : [support_ stringByReplacingOccurrencesOfString:@"*" withString:package]; } - (NSDictionary *) record { @@ -1456,15 +1617,15 @@ class Progress : } - (NSString *) key { - return [NSString stringWithFormat:@"%@:%@:%@", type_, uri_, distribution_]; + return [NSString stringWithFormat:@"%@:%@:%@", (NSString *) type_, (NSString *) uri_, (NSString *) distribution_]; } - (NSString *) host { - return [[[NSURL URLWithString:[self uri]] host] lowercaseString]; + return host_; } - (NSString *) name { - return origin_ == nil ? [self host] : origin_; + return origin_.empty() ? host_ : origin_; } - (NSString *) description { @@ -1472,7 +1633,7 @@ class Progress : } - (NSString *) label { - return label_ == nil ? [self host] : label_; + return label_.empty() ? host_ : label_; } - (NSString *) origin { @@ -1527,23 +1688,26 @@ class Progress : /* Package Class {{{ */ @interface Package : NSObject { unsigned era_; + apr_pool_t *pool_; + pkgCache::VerIterator version_; pkgCache::PkgIterator iterator_; _transient Database *database_; - pkgCache::VerIterator version_; pkgCache::VerFileIterator file_; Source *source_; bool cached_; + bool parsed_; CYString section_; NSString *section$_; bool essential_; + bool visible_; NSString *latest_; - NSString *installed_; + CYString installed_; - NSString *id_; + CYString id_; CYString name_; CYString tagline_; CYString icon_; @@ -1557,17 +1721,22 @@ class Progress : Address *author$_; CYString support_; - NSArray *tags_; + NSMutableArray *tags_; NSString *role_; NSArray *relationships_; + NSMutableDictionary *metadata_; + _transient NSDate *firstSeen_; + _transient NSDate *lastSeen_; + bool subscribed_; } -- (Package *) initWithIterator:(pkgCache::PkgIterator)iterator withZone:(NSZone *)zone inPool:(apr_pool_t *)pool database:(Database *)database; +- (Package *) initWithVersion:(pkgCache::VerIterator)version withZone:(NSZone *)zone inPool:(apr_pool_t *)pool database:(Database *)database; + (Package *) packageWithIterator:(pkgCache::PkgIterator)iterator withZone:(NSZone *)zone inPool:(apr_pool_t *)pool database:(Database *)database; - (pkgCache::PkgIterator) iterator; +- (void) parse; - (NSString *) section; - (NSString *) simpleSection; @@ -1579,7 +1748,8 @@ class Progress : - (Address *) maintainer; - (size_t) size; -- (NSString *) description; +- (NSString *) longDescription; +- (NSString *) shortDescription; - (unichar) index; - (NSMutableDictionary *) metadata; @@ -1589,6 +1759,7 @@ class Progress : - (NSString *) latest; - (NSString *) installed; +- (BOOL) uninstalled; - (BOOL) valid; - (BOOL) upgradableAndEssential:(BOOL)essential; @@ -1605,7 +1776,6 @@ class Progress : - (NSString *) id; - (NSString *) name; -- (NSString *) tagline; - (UIImage *) icon; - (NSString *) homepage; - (NSString *) depiction; @@ -1629,8 +1799,8 @@ class Progress : - (NSArray *) purposes; - (bool) isCommercial; -- (uint32_t) compareByPrefix; -- (NSComparisonResult) compareByName:(Package *)package; +- (CYString &) cyname; + - (uint32_t) compareBySection:(NSArray *)sections; - (uint32_t) compareForChanges; @@ -1672,19 +1842,116 @@ uint32_t PackageChangesRadix(Package *self, void *) { return _not(uint32_t) - value.key; } +_finline static void Stifle(uint8_t &value) { +} + +uint32_t PackagePrefixRadix(Package *self, void *context) { + size_t offset(reinterpret_cast(context)); + CYString &name([self cyname]); + + size_t size(name.size()); + if (size == 0) + return 0; + char *text(name.data()); + + size_t zeros; + if (!isdigit(text[0])) + zeros = 0; + else { + size_t digits(1); + while (size != digits && isdigit(text[digits])) + if (++digits == 4) + break; + zeros = 4 - digits; + } + + uint8_t data[4]; + + // 0.607997 + + if (offset == 0 && zeros != 0) { + memset(data, '0', zeros); + memcpy(data + zeros, text, 4 - zeros); + } else { + /* XXX: there's some danger here if you request a non-zero offset < 4 and it gets zero padded */ + if (size <= offset - zeros) + return 0; + + text += offset - zeros; + size -= offset - zeros; + + if (size >= 4) + memcpy(data, text, 4); + else { + memcpy(data, text, size); + memset(data + size, 0, 4 - size); + } + + for (size_t i(0); i != 4; ++i) + if (isalpha(data[i])) + data[i] &= 0xdf; + } + + if (offset == 0) + data[0] = (data[0] & 0x3f) | "\x80\x00\xc0\x40"[data[0] >> 6]; + + /* XXX: ntohl may be more honest */ + return OSSwapInt32(*reinterpret_cast(data)); +} + +CYString &(*PackageName)(Package *self, SEL sel); + +CFComparisonResult PackageNameCompare(Package *lhs, Package *rhs, void *arg) { + _profile(PackageNameCompare) + CYString &lhi(PackageName(lhs, @selector(cyname))); + CYString &rhi(PackageName(rhs, @selector(cyname))); + CFStringRef lhn(lhi), rhn(rhi); + + _profile(PackageNameCompare$NumbersLast) + if (!lhi.empty() && !rhi.empty()) { + UniChar lhc(CFStringGetCharacterAtIndex(lhn, 0)); + UniChar rhc(CFStringGetCharacterAtIndex(rhn, 0)); + bool lha(CFUniCharIsMemberOf(lhc, kCFUniCharLetterCharacterSet)); + if (lha != CFUniCharIsMemberOf(rhc, kCFUniCharLetterCharacterSet)) + return lha ? NSOrderedAscending : NSOrderedDescending; + } + _end + + CFIndex length = CFStringGetLength(lhn); + + _profile(PackageNameCompare$Compare) + return CFStringCompareWithOptionsAndLocale(lhn, rhn, CFRangeMake(0, length), LaxCompareFlags_, Locale_); + _end + _end +} + +CFComparisonResult PackageNameCompare_(Package **lhs, Package **rhs, void *context) { + return PackageNameCompare(*lhs, *rhs, context); +} + +struct PackageNameOrdering : + std::binary_function +{ + _finline bool operator ()(Package *lhs, Package *rhs) const { + return PackageNameCompare(lhs, rhs, NULL) == NSOrderedAscending; + } +}; + @implementation Package +- (NSString *) description { + return [NSString stringWithFormat:@"", static_cast(name_)]; +} + - (void) dealloc { if (source_ != nil) [source_ release]; if (section$_ != nil) [section$_ release]; - [latest_ release]; - if (installed_ != nil) - [installed_ release]; + if (latest_ != nil) + [latest_ release]; - [id_ release]; if (sponsor$_ != nil) [sponsor$_ release]; if (author$_ != nil) @@ -1714,7 +1981,7 @@ uint32_t PackageChangesRadix(Package *self, void *) { } + (NSArray *) _attributeKeys { - return [NSArray arrayWithObjects:@"applications", @"author", @"depiction", @"description", @"essential", @"homepage", @"icon", @"id", @"installed", @"latest", @"longSection", @"maintainer", @"mode", @"name", @"purposes", @"section", @"shortSection", @"simpleSection", @"size", @"source", @"sponsor", @"support", @"tagline", @"warnings", nil]; + return [NSArray arrayWithObjects:@"applications", @"author", @"depiction", @"longDescription", @"essential", @"homepage", @"icon", @"id", @"installed", @"latest", @"longSection", @"maintainer", @"mode", @"name", @"purposes", @"section", @"shortDescription", @"shortSection", @"simpleSection", @"size", @"source", @"sponsor", @"support", @"warnings", nil]; } - (NSArray *) attributeKeys { @@ -1725,41 +1992,90 @@ uint32_t PackageChangesRadix(Package *self, void *) { return ![[self _attributeKeys] containsObject:[NSString stringWithUTF8String:name]] && [super isKeyExcludedFromWebScript:name]; } -- (Package *) initWithIterator:(pkgCache::PkgIterator)iterator withZone:(NSZone *)zone inPool:(apr_pool_t *)pool database:(Database *)database { - if ((self = [super init]) != nil) { - _profile(Package$initWithIterator) - @synchronized (database) { - era_ = [database era]; +- (void) parse { + if (parsed_) + return; + parsed_ = true; + if (file_.end()) + return; - iterator_ = iterator; - database_ = database; + _profile(Package$parse) + pkgRecords::Parser *parser; - _profile(Package$initWithIterator$Control) + _profile(Package$parse$Lookup) + parser = &[database_ records]->Lookup(file_); _end - _profile(Package$initWithIterator$Version) - version_ = [database_ policy]->GetCandidateVer(iterator_); + CYString website; + + _profile(Package$parse$Find) + struct { + const char *name_; + CYString *value_; + } names[] = { + {"icon", &icon_}, + {"depiction", &depiction_}, + {"homepage", &homepage_}, + {"website", &website}, + {"support", &support_}, + {"sponsor", &sponsor_}, + {"author", &author_}, + }; + + for (size_t i(0); i != sizeof(names) / sizeof(names[0]); ++i) { + const char *start, *end; + + if (parser->Find(names[i].name_, start, end)) { + CYString &value(*names[i].value_); + _profile(Package$parse$Value) + value.set(pool_, start, end - start); + _end + } + } _end - NSString *latest = version_.end() ? nil : [NSString stringWithUTF8String:version_.VerStr()]; + _profile(Package$parse$Tagline) + const char *start, *end; + if (parser->ShortDesc(start, end)) { + const char *stop(reinterpret_cast(memchr(start, '\n', end - start))); + if (stop == NULL) + stop = end; + while (stop != start && stop[-1] == '\r') + --stop; + tagline_.set(pool_, start, stop - start); + } + _end - _profile(Package$initWithIterator$Latest) - latest_ = latest == nil ? nil : [StripVersion(latest) retain]; + _profile(Package$parse$Retain) + if (!homepage_.empty()) + homepage_ = website; + if (homepage_ == depiction_) + homepage_.clear(); _end + _end +} - pkgCache::VerIterator current; - NSString *installed; +- (Package *) initWithVersion:(pkgCache::VerIterator)version withZone:(NSZone *)zone inPool:(apr_pool_t *)pool database:(Database *)database { + if ((self = [super init]) != nil) { + _profile(Package$initWithVersion) + @synchronized (database) { + era_ = [database era]; + pool_ = pool; - _profile(Package$initWithIterator$Current) - current = iterator_.CurrentVer(); - installed = current.end() ? nil : [NSString stringWithUTF8String:current.VerStr()]; - _end + version_ = version; + iterator_ = version.ParentPkg(); + database_ = database; - _profile(Package$initWithIterator$Installed) - installed_ = [StripVersion(installed) retain]; + _profile(Package$initWithVersion$Latest) + latest_ = (NSString *) StripVersion(version_.VerStr()); _end - _profile(Package$initWithIterator$File) + pkgCache::VerIterator current; + _profile(Package$initWithVersion$Versions) + current = iterator_.CurrentVer(); + if (!current.end()) + installed_.set(pool_, StripVersion_(current.VerStr())); + if (!version_.end()) file_ = version_.FileList(); else { @@ -1768,135 +2084,80 @@ uint32_t PackageChangesRadix(Package *self, void *) { } _end - _profile(Package$initWithIterator$Name) - id_ = [[NSString stringWithUTF8String:iterator_.Name()] retain]; + _profile(Package$initWithVersion$Name) + id_.set(pool_, iterator_.Name()); + name_.set(pool, iterator_.Display()); _end - if (!file_.end()) - _profile(Package$initWithIterator$Parse) - pkgRecords::Parser *parser; - - _profile(Package$initWithIterator$Parse$Lookup) - parser = &[database_ records]->Lookup(file_); - _end - - const char *begin, *end; - parser->GetRec(begin, end); - - CYString website; - CYString tag; - - struct { - const char *name_; - CYString *value_; - } names[] = { - {"name", &name_}, - {"icon", &icon_}, - {"depiction", &depiction_}, - {"homepage", &homepage_}, - {"website", &website}, - {"support", &support_}, - {"sponsor", &sponsor_}, - {"author", &author_}, - {"tag", &tag}, - }; - - while (begin != end) - if (*begin == '\n') { - ++begin; - continue; - } else if (isblank(*begin)) next: { - begin = static_cast(memchr(begin + 1, '\n', end - begin - 1)); - if (begin == NULL) - break; - } else if (const char *colon = static_cast(memchr(begin, ':', end - begin))) { - const char *name(begin); - size_t size(colon - begin); - - begin = static_cast(memchr(begin, '\n', end - begin)); - - { - const char *stop(begin == NULL ? end : begin); - while (stop[-1] == '\r') - --stop; - while (++colon != stop && isblank(*colon)); - - for (size_t i(0); i != sizeof(names) / sizeof(names[0]); ++i) - if (strncasecmp(names[i].name_, name, size) == 0) { - CYString &value(*names[i].value_); - - _profile(Package$initWithIterator$Parse$Value) - value.set(pool, colon, stop - colon); - _end - - break; - } - } - - if (begin == NULL) - break; - ++begin; - } else goto next; - - _profile(Package$initWithIterator$Parse$Tagline) - tagline_.set(pool, parser->ShortDesc()); - _end - - _profile(Package$initWithIterator$Parse$Retain) - if (!homepage_.empty()) - homepage_ = website; - if (homepage_ == depiction_) - homepage_.clear(); - if (!tag.empty()) - tags_ = [[tag componentsSeparatedByString:@", "] retain]; - _end + if (!file_.end()) { + _profile(Package$initWithVersion$Source) + source_ = [database_ getSource:file_.File()]; + if (source_ != nil) + [source_ retain]; + cached_ = true; _end + } - _profile(Package$initWithIterator$Tags) - if (tags_ != nil) - for (NSString *tag in tags_) - if ([tag hasPrefix:@"role::"]) { - role_ = [[tag substringFromIndex:6] retain]; - break; - } + visible_ = true; + + _profile(Package$initWithVersion$Tags) + pkgCache::TagIterator tag(iterator_.TagList()); + if (!tag.end()) { + tags_ = [[NSMutableArray alloc] initWithCapacity:8]; + do { + const char *name(tag.Name()); + [tags_ addObject:(NSString *)CFCString(name)]; + if (role_ == nil && strncmp(name, "role::", 6) == 0 /*&& strcmp(name, "role::leaper") != 0*/) + role_ = (NSString *) CFCString(name + 6); + if (visible_ && strncmp(name, "require::", 9) == 0 && ( + true + )) + visible_ = false; + ++tag; + } while (!tag.end()); + } _end - NSString *solid(latest == nil ? installed : latest); bool changed(false); - NSString *key([id_ lowercaseString]); - _profile(Package$initWithIterator$Metadata) + _profile(Package$initWithVersion$Metadata) metadata_ = [Packages_ objectForKey:key]; + if (metadata_ == nil) { + firstSeen_ = now_; + metadata_ = [[NSMutableDictionary dictionaryWithObjectsAndKeys: - now_, @"FirstSeen", + firstSeen_, @"FirstSeen", + latest_, @"LastVersion", nil] mutableCopy]; - if (solid != nil) - [metadata_ setObject:solid forKey:@"LastVersion"]; changed = true; } else { - NSDate *first([metadata_ objectForKey:@"FirstSeen"]); - NSDate *last([metadata_ objectForKey:@"LastSeen"]); + firstSeen_ = [metadata_ objectForKey:@"FirstSeen"]; + lastSeen_ = [metadata_ objectForKey:@"LastSeen"]; + + if (NSNumber *subscribed = [metadata_ objectForKey:@"IsSubscribed"]) + subscribed_ = [subscribed boolValue]; + NSString *version([metadata_ objectForKey:@"LastVersion"]); - if (first == nil) { - first = last == nil ? now_ : last; - [metadata_ setObject:first forKey:@"FirstSeen"]; + if (firstSeen_ == nil) { + firstSeen_ = lastSeen_ == nil ? now_ : lastSeen_; + [metadata_ setObject:firstSeen_ forKey:@"FirstSeen"]; changed = true; } - if (solid != nil) - if (version == nil) { - [metadata_ setObject:solid forKey:@"LastVersion"]; - changed = true; - } else if (![version isEqualToString:solid]) { - [metadata_ setObject:solid forKey:@"LastVersion"]; - last = now_; - [metadata_ setObject:last forKey:@"LastSeen"]; - changed = true; - } + if (version == nil) { + [metadata_ setObject:latest_ forKey:@"LastVersion"]; + changed = true; + } else { + if (![version isEqualToString:latest_]) { + [metadata_ setObject:latest_ forKey:@"LastVersion"]; + lastSeen_ = now_; + [metadata_ setObject:lastSeen_ forKey:@"LastSeen"]; + changed = true; + } } } metadata_ = [metadata_ retain]; @@ -1907,22 +2168,33 @@ uint32_t PackageChangesRadix(Package *self, void *) { } _end - _profile(Package$initWithIterator$Section) - section_.set(pool, iterator_.Section()); + _profile(Package$initWithVersion$Section) + section_.set(pool_, iterator_.Section()); _end essential_ = ((iterator_->Flags & pkgCache::Flag::Essential) == 0 ? NO : YES) || [self hasTag:@"cydia::essential"]; + visible_ = visible_ && [self hasSupportingRole] && [self unfiltered]; } _end } return self; } + (Package *) packageWithIterator:(pkgCache::PkgIterator)iterator withZone:(NSZone *)zone inPool:(apr_pool_t *)pool database:(Database *)database { +@synchronized ([Database class]) { + pkgCache::VerIterator version; + + _profile(Package$packageWithIterator$GetCandidateVer) + version = [database policy]->GetCandidateVer(iterator); + _end + + if (version.end()) + return nil; + return [[[Package alloc] - initWithIterator:iterator + initWithVersion:version withZone:zone inPool:pool database:database ] autorelease]; -} +} } - (pkgCache::PkgIterator) iterator { return iterator_; @@ -1955,7 +2227,7 @@ uint32_t PackageChangesRadix(Package *self, void *) { } - (NSString *) longSection { - return LocalizeSection(section_); + return LocalizeSection([self section]); } - (NSString *) shortSection { @@ -1987,7 +2259,7 @@ uint32_t PackageChangesRadix(Package *self, void *) { return version_.end() ? 0 : version_->InstalledSize; } -- (NSString *) description { +- (NSString *) longDescription { if (file_.end()) return nil; pkgRecords::Parser *parser = &[database_ records]->Lookup(file_); @@ -2007,38 +2279,34 @@ uint32_t PackageChangesRadix(Package *self, void *) { return [trimmed componentsJoinedByString:@"\n"]; } +- (NSString *) shortDescription { + return tagline_; +} + - (unichar) index { _profile(Package$index) - NSString *name([self name]); - if ([name length] == 0) + CFStringRef name((CFStringRef) [self name]); + if (CFStringGetLength(name) == 0) return '#'; - unichar character([name characterAtIndex:0]); - if (!isalpha(character)) + UniChar character(CFStringGetCharacterAtIndex(name, 0)); + if (!CFUniCharIsMemberOf(character, kCFUniCharLetterCharacterSet)) return '#'; return toupper(character); _end } - (NSMutableDictionary *) metadata { - if (metadata_ == nil) - metadata_ = [[Packages_ objectForKey:[id_ lowercaseString]] retain]; return metadata_; } - (NSDate *) seen { - NSDictionary *metadata([self metadata]); - if ([self subscribed]) - if (NSDate *last = [metadata objectForKey:@"LastSeen"]) - return last; - return [metadata objectForKey:@"FirstSeen"]; + if (subscribed_ && lastSeen_ != nil) + return lastSeen_; + return firstSeen_; } - (BOOL) subscribed { - NSDictionary *metadata([self metadata]); - if (NSNumber *subscribed = [metadata objectForKey:@"IsSubscribed"]) - return [subscribed boolValue]; - else - return false; + return subscribed_; } - (BOOL) ignored { @@ -2057,19 +2325,22 @@ uint32_t PackageChangesRadix(Package *self, void *) { return installed_; } +- (BOOL) uninstalled { + return installed_.empty(); +} + - (BOOL) valid { return !version_.end(); } - (BOOL) upgradableAndEssential:(BOOL)essential { - pkgCache::VerIterator current = iterator_.CurrentVer(); - - bool value; - if (current.end()) - value = essential && [self essential] && [self visible]; - else - value = !version_.end() && version_ != current;// && (!essential || ![database_ cache][iterator_].Keep()); - return value; + _profile(Package$upgradableAndEssential) + pkgCache::VerIterator current(iterator_.CurrentVer()); + if (current.end()) + return essential && essential_ && visible_; + else + return !version_.end() && version_ != current;// && (!essential || ![database_ cache][iterator_].Keep()); + _end } - (BOOL) essential { @@ -2081,16 +2352,16 @@ uint32_t PackageChangesRadix(Package *self, void *) { } - (BOOL) unfiltered { - NSString *section = [self section]; + NSString *section([self section]); return section == nil || isSectionVisible(section); } - (BOOL) visible { - return [self hasSupportingRole] && [self unfiltered]; + return visible_; } - (BOOL) half { - unsigned char current = iterator_->CurrentState; + unsigned char current(iterator_->CurrentState); return current == pkgCache::State::HalfConfigured || current == pkgCache::State::HalfInstalled; } @@ -2148,18 +2419,14 @@ uint32_t PackageChangesRadix(Package *self, void *) { } - (NSString *) name { - return name_ == nil ? id_ : name_; -} - -- (NSString *) tagline { - return tagline_; + return name_.empty() ? id_ : name_; } - (UIImage *) icon { NSString *section = [self simpleSection]; UIImage *icon(nil); - if (icon_ != nil) + if (!icon_.empty()) if ([icon_ hasPrefix:@"file:///"]) icon = [UIImage imageAtPath:[icon_ substringFromIndex:7]]; if (icon == nil) if (section != nil) @@ -2177,7 +2444,7 @@ uint32_t PackageChangesRadix(Package *self, void *) { } - (NSString *) depiction { - return depiction_; + return !depiction_.empty() ? depiction_ : [[self source] depictionForPackage:id_]; } - (Address *) sponsor { @@ -2197,11 +2464,11 @@ uint32_t PackageChangesRadix(Package *self, void *) { } - (NSString *) support { - return support_ != nil ? support_ : [[self source] supportForPackage:id_]; + return !support_.empty() ? support_ : [[self source] supportForPackage:id_]; } - (NSArray *) files { - NSString *path = [NSString stringWithFormat:@"/var/lib/dpkg/info/%@.list", id_]; + NSString *path = [NSString stringWithFormat:@"/var/lib/dpkg/info/%@.list", static_cast(id_)]; NSMutableArray *files = [NSMutableArray arrayWithCapacity:128]; std::ifstream fin; @@ -2226,7 +2493,7 @@ uint32_t PackageChangesRadix(Package *self, void *) { size_t length(strlen(name)); if (length < 2) invalid: - [warnings addObject:CYLocalize("ILLEGAL_PACKAGE_IDENTIFIER")]; + [warnings addObject:UCLocalize("ILLEGAL_PACKAGE_IDENTIFIER")]; else for (size_t i(0); i != length; ++i) if ( /* XXX: technically this is not allowed */ @@ -2254,11 +2521,11 @@ uint32_t PackageChangesRadix(Package *self, void *) { /* XXX: this is not sensitive enough. only some folders are valid. */ if (cydia && !repository) - [warnings addObject:[NSString stringWithFormat:CYLocalize("FILES_INSTALLED_TO"), @"Cydia.app"]]; + [warnings addObject:[NSString stringWithFormat:UCLocalize("FILES_INSTALLED_TO"), @"Cydia.app"]]; if (_private) - [warnings addObject:[NSString stringWithFormat:CYLocalize("FILES_INSTALLED_TO"), @"/private"]]; + [warnings addObject:[NSString stringWithFormat:UCLocalize("FILES_INSTALLED_TO"), @"/private"]]; if (stash) - [warnings addObject:[NSString stringWithFormat:CYLocalize("FILES_INSTALLED_TO"), @"/var/stash"]]; + [warnings addObject:[NSString stringWithFormat:UCLocalize("FILES_INSTALLED_TO"), @"/var/stash"]]; } return [warnings count] == 0 ? nil : warnings; @@ -2335,7 +2602,7 @@ uint32_t PackageChangesRadix(Package *self, void *) { if (range.location != NSNotFound) return YES; - range = [[self tagline] rangeOfString:text options:MatchCompareOptions_]; + range = [[self shortDescription] rangeOfString:text options:MatchCompareOptions_]; if (range.location != NSNotFound) return YES; @@ -2383,27 +2650,8 @@ uint32_t PackageChangesRadix(Package *self, void *) { return [self hasTag:@"cydia::commercial"]; } -- (uint32_t) compareByPrefix { - return 0; -} - -- (NSComparisonResult) compareByName:(Package *)package { - NSString *lhs = [self name]; - NSString *rhs = [package name]; - - /*if ([lhs length] != 0 && [rhs length] != 0) { - unichar lhc = [lhs characterAtIndex:0]; - unichar rhc = [rhs characterAtIndex:0]; - - if (isalpha(lhc) && !isalpha(rhc)) - return NSOrderedAscending; - else if (!isalpha(lhc) && isalpha(rhc)) - return NSOrderedDescending; - } - - return [lhs compare:rhs options:LaxCompareOptions_];*/ - - return [lhs compare:rhs]; +- (CYString &) cyname { + return name_.empty() ? id_ : name_; } - (uint32_t) compareBySection:(NSArray *)sections { @@ -2485,7 +2733,7 @@ uint32_t PackageChangesRadix(Package *self, void *) { } - (bool) isInstalledAndVisible:(NSNumber *)number { - return (![number boolValue] || [self visible]) && [self installed] != nil; + return (![number boolValue] || [self visible]) && ![self uninstalled]; } - (bool) isVisiblyUninstalledInSection:(NSString *)name { @@ -2493,7 +2741,7 @@ uint32_t PackageChangesRadix(Package *self, void *) { return [self visible] && - [self installed] == nil && ( + [self uninstalled] && ( name == nil || section == nil && [name length] == 0 || [name isEqualToString:section] @@ -2515,9 +2763,10 @@ uint32_t PackageChangesRadix(Package *self, void *) { NSString *localized_; } -- (NSComparisonResult) compareByName:(Section *)section; -- (Section *) initWithName:(NSString *)name; -- (Section *) initWithName:(NSString *)name row:(size_t)row; +- (NSComparisonResult) compareByLocalized:(Section *)section; +- (Section *) initWithName:(NSString *)name localized:(NSString *)localized; +- (Section *) initWithName:(NSString *)name localize:(BOOL)localize; +- (Section *) initWithName:(NSString *)name row:(size_t)row localize:(BOOL)localize; - (Section *) initWithIndex:(unichar)index row:(size_t)row; - (NSString *) name; - (unichar) index; @@ -2529,6 +2778,7 @@ uint32_t PackageChangesRadix(Package *self, void *) { - (void) addToCount; - (void) setCount:(size_t)count; +- (NSString *) localized; @end @@ -2541,11 +2791,11 @@ uint32_t PackageChangesRadix(Package *self, void *) { [super dealloc]; } -- (NSComparisonResult) compareByName:(Section *)section { - NSString *lhs = [self name]; - NSString *rhs = [section name]; +- (NSComparisonResult) compareByLocalized:(Section *)section { + NSString *lhs(localized_); + NSString *rhs([section localized]); - if ([lhs length] != 0 && [rhs length] != 0) { + /*if ([lhs length] != 0 && [rhs length] != 0) { unichar lhc = [lhs characterAtIndex:0]; unichar rhc = [rhs characterAtIndex:0]; @@ -2553,21 +2803,29 @@ uint32_t PackageChangesRadix(Package *self, void *) { return NSOrderedAscending; else if (!isalpha(lhc) && isalpha(rhc)) return NSOrderedDescending; - } + }*/ return [lhs compare:rhs options:LaxCompareOptions_]; } -- (Section *) initWithName:(NSString *)name { - return [self initWithName:name row:0]; +- (Section *) initWithName:(NSString *)name localized:(NSString *)localized { + if ((self = [self initWithName:name localize:NO]) != nil) { + if (localized != nil) + localized_ = [localized retain]; + } return self; +} + +- (Section *) initWithName:(NSString *)name localize:(BOOL)localize { + return [self initWithName:name row:0 localize:localize]; } -- (Section *) initWithName:(NSString *)name row:(size_t)row { +- (Section *) initWithName:(NSString *)name row:(size_t)row localize:(BOOL)localize { if ((self = [super init]) != nil) { name_ = [name retain]; index_ = '\0'; row_ = row; - localized_ = [LocalizeSection(name_) retain]; + if (localize) + localized_ = [LocalizeSection(name_) retain]; } return self; } @@ -2724,11 +2982,12 @@ static NSArray *Finishes_; } - (Package *) packageWithName:(NSString *)name { +@synchronized ([Database class]) { 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]; -} +} } - (Database *) init { if ((self = [super init]) != nil) { @@ -2741,8 +3000,7 @@ static NSArray *Finishes_; zone_ = NSCreateZone(1024 * 1024, 256 * 1024, NO); apr_pool_create(&pool_, NULL); - sources_ = [[NSMutableDictionary dictionaryWithCapacity:16] retain]; - packages_ = [[NSMutableArray arrayWithCapacity:16] retain]; + packages_ = [[NSMutableArray alloc] init]; int fds[2]; @@ -2814,7 +3072,10 @@ static NSArray *Finishes_; } - (NSArray *) sources { - return [sources_ allValues]; + NSMutableArray *sources([NSMutableArray arrayWithCapacity:sources_.size()]); + for (SourceMap::const_iterator i(sources_.begin()); i != sources_.end(); ++i) + [sources addObject:i->second]; + return sources; } - (NSArray *) issues { @@ -2882,10 +3143,15 @@ static NSArray *Finishes_; } - (void) reloadData { _pooled +@synchronized ([Database class]) { + @synchronized (self) { ++era_; } + [packages_ removeAllObjects]; + sources_.clear(); + _error->Discard(); delete list_; @@ -2902,11 +3168,20 @@ static NSArray *Finishes_; delete policy_; policy_ = NULL; + if (now_ != nil) { + [now_ release]; + now_ = nil; + } + cache_.Close(); apr_pool_clear(pool_); NSRecycleZone(zone_); + int chk(creat("/tmp/cydia.chk", 0644)); + if (chk != -1) + close(chk); + _trace(); if (!cache_.Open(progress_, true)) { std::string error; @@ -2928,6 +3203,8 @@ static NSArray *Finishes_; } _trace(); + unlink("/tmp/cydia.chk"); + now_ = [[NSDate date] retain]; policy_ = new pkgDepCache::Policy(); @@ -2948,28 +3225,65 @@ static NSArray *Finishes_; _assert(pkgMinimizeUpgrade(cache_)); } - [sources_ removeAllObjects]; + _trace(); + for (pkgSourceList::const_iterator source = list_->begin(); source != list_->end(); ++source) { std::vector *indices = (*source)->GetIndexFiles(); for (std::vector::const_iterator index = indices->begin(); index != indices->end(); ++index) - [sources_ - setObject:[[[Source alloc] initWithMetaIndex:*source] autorelease] - forKey:[NSNumber numberWithLong:reinterpret_cast(*index)] - ]; + // XXX: this could be more intelligent + if (dynamic_cast(*index) != NULL) { + pkgCache::PkgFileIterator cached((*index)->FindInCache(cache_)); + if (!cached.end()) + sources_[cached->ID] = [[[Source alloc] initWithMetaIndex:*source inPool:pool_] autorelease]; + } } - [packages_ removeAllObjects]; - _trace(); - for (pkgCache::PkgIterator iterator = cache_->PkgBegin(); !iterator.end(); ++iterator) - if (Package *package = [Package packageWithIterator:iterator withZone:zone_ inPool:pool_ database:self]) - [packages_ addObject:package]; - _trace(); - [packages_ sortUsingSelector:@selector(compareByName:)]; _trace(); - _config->Set("Acquire::http::Timeout", 15); - _config->Set("Acquire::http::MaxParallel", 4); -} + { + /*std::vector packages; + packages.reserve(std::max(10000U, [packages_ count] + 1000)); + [packages_ release]; + packages_ = nil;*/ + + _trace(); + + for (pkgCache::PkgIterator iterator = cache_->PkgBegin(); !iterator.end(); ++iterator) + if (Package *package = [Package packageWithIterator:iterator withZone:zone_ inPool:pool_ database:self]) + //packages.push_back(package); + [packages_ addObject:package]; + + _trace(); + + /*if (packages.empty()) + packages_ = [[NSArray alloc] init]; + else + packages_ = [[NSArray alloc] initWithObjects:&packages.front() count:packages.size()]; + _trace();*/ + + [packages_ radixSortUsingFunction:reinterpret_cast(&PackagePrefixRadix) withContext:reinterpret_cast(16)]; + [packages_ radixSortUsingFunction:reinterpret_cast(&PackagePrefixRadix) withContext:reinterpret_cast(4)]; + [packages_ radixSortUsingFunction:reinterpret_cast(&PackagePrefixRadix) withContext:reinterpret_cast(0)]; + + /*_trace(); + PrintTimes(); + _trace();*/ + + _trace(); + + /*if (!packages.empty()) + CFQSortArray(&packages.front(), packages.size(), sizeof(packages.front()), reinterpret_cast(&PackageNameCompare_), NULL);*/ + //std::sort(packages.begin(), packages.end(), PackageNameOrdering()); + + //CFArraySortValues((CFMutableArrayRef) packages_, CFRangeMake(0, [packages_ count]), reinterpret_cast(&PackageNameCompare), NULL); + + CFArrayInsertionSortValues((CFMutableArrayRef) packages_, CFRangeMake(0, [packages_ count]), reinterpret_cast(&PackageNameCompare), NULL); + + //[packages_ sortUsingFunction:reinterpret_cast(&PackageNameCompare) context:NULL]; + + _trace(); + } +} } - (void) configure { NSString *dpkg = [NSString stringWithFormat:@"dpkg --configure -a --status-fd %u", statusfd_]; @@ -3036,6 +3350,8 @@ static NSArray *Finishes_; for (pkgAcquire::ItemIterator item = fetcher_->ItemsBegin(); item != fetcher_->ItemsEnd(); item++) { if ((*item)->Status == pkgAcquire::Item::StatDone && (*item)->Complete) continue; + if ((*item)->Status == pkgAcquire::Item::StatIdle) + continue; std::string uri = (*item)->DescURI(); std::string error = (*item)->ErrorText; @@ -3093,13 +3409,20 @@ static NSArray *Finishes_; [self updateWithStatus:status_]; } -- (void) updateWithStatus:(Status &)status { +- (NSString *) updateWithStatus:(Status &)status { pkgSourceList list; _assert(list.ReadMainList()); FileFd lock; lock.Fd(GetLock(_config->FindDir("Dir::State::Lists") + "lock")); - _assert(!_error->PendingError()); + + if (_error->PendingError()) { + std::string error; + if (!_error->PopMessage(error)) + _assert(false); + _error->Discard(); + return [NSString stringWithUTF8String:error.c_str()]; + } pkgAcquire fetcher(&status); _assert(list.GetIndexes(&fetcher)); @@ -3120,6 +3443,8 @@ static NSArray *Finishes_; [Metadata_ setObject:[NSDate date] forKey:@"LastUpdate"]; Changed_ = true; } + + return nil; } - (void) setDelegate:(id)delegate { @@ -3128,10 +3453,9 @@ static NSArray *Finishes_; progress_.setDelegate(delegate); } -- (Source *) getSource:(const pkgCache::PkgFileIterator &)file { - pkgIndexFile *index(NULL); - list_->FindIndex(file, index); - return [sources_ objectForKey:[NSNumber numberWithLong:reinterpret_cast(index)]]; +- (Source *) getSource:(pkgCache::PkgFileIterator)file { + SourceMap::const_iterator i(sources_.find(file->ID)); + return i == sources_.end() ? nil : i->second; } @end @@ -3189,92 +3513,291 @@ static NSArray *Finishes_; @end /* }}} */ -#if 0 -/* Mail Composition {{{ */ -@interface MailToView : PopUpView { - MailComposeController *controller_; +/* Confirmation View {{{ */ +bool DepSubstrate(const pkgCache::VerIterator &iterator) { + if (!iterator.end()) + for (pkgCache::DepIterator dep(iterator.DependsList()); !dep.end(); ++dep) { + if (dep->Type != pkgCache::Dep::Depends && dep->Type != pkgCache::Dep::PreDepends) + continue; + pkgCache::PkgIterator package(dep.TargetPkg()); + if (package.end()) + continue; + if (strcmp(package.Name(), "mobilesubstrate") == 0) + return true; + } + + return false; +} + +/* Web Scripting {{{ */ +@interface CydiaObject : NSObject { + id indirect_; +} + +- (id) initWithDelegate:(IndirectDelegate *)indirect; +@end + +@implementation CydiaObject + +- (void) dealloc { + [indirect_ release]; + [super dealloc]; +} + +- (id) initWithDelegate:(IndirectDelegate *)indirect { + if ((self = [super init]) != nil) { + indirect_ = [indirect retain]; + } return self; +} + ++ (NSArray *) _attributeKeys { + return [NSArray arrayWithObjects:@"device", @"firewire", @"imei", @"mac", @"serial", nil]; +} + +- (NSArray *) attributeKeys { + return [[self class] _attributeKeys]; +} + ++ (BOOL) isKeyExcludedFromWebScript:(const char *)name { + return ![[self _attributeKeys] containsObject:[NSString stringWithUTF8String:name]] && [super isKeyExcludedFromWebScript:name]; +} + +- (NSString *) device { + return [[UIDevice currentDevice] uniqueIdentifier]; +} + +#if 0 // XXX: implement! +- (NSString *) mac { + if (![indirect_ promptForSensitive:@"Mac Address"]) + return nil; } -- (id) initWithView:(UIView *)view delegate:(id)delegate url:(NSURL *)url; +- (NSString *) serial { + if (![indirect_ promptForSensitive:@"Serial #"]) + return nil; +} + +- (NSString *) firewire { + if (![indirect_ promptForSensitive:@"Firewire GUID"]) + return nil; +} + +- (NSString *) imei { + if (![indirect_ promptForSensitive:@"IMEI"]) + return nil; +} +#endif + ++ (NSString *) webScriptNameForSelector:(SEL)selector { + if (selector == @selector(close)) + return @"close"; + else if (selector == @selector(getPackageById:)) + return @"getPackageById"; + else if (selector == @selector(setAutoPopup:)) + return @"setAutoPopup"; + else if (selector == @selector(setButtonImage:withStyle:toFunction:)) + return @"setButtonImage"; + else if (selector == @selector(setButtonTitle:withStyle:toFunction:)) + return @"setButtonTitle"; + else if (selector == @selector(setFinishHook:)) + return @"setFinishHook"; + else if (selector == @selector(setPopupHook:)) + return @"setPopupHook"; + else if (selector == @selector(setSpecial:)) + return @"setSpecial"; + else if (selector == @selector(setViewportWidth:)) + return @"setViewportWidth"; + else if (selector == @selector(supports:)) + return @"supports"; + else if (selector == @selector(stringWithFormat:arguments:)) + return @"format"; + else if (selector == @selector(localizedStringForKey:value:table:)) + return @"localize"; + else if (selector == @selector(du:)) + return @"du"; + else if (selector == @selector(statfs:)) + return @"statfs"; + else + return nil; +} + ++ (BOOL) isSelectorExcludedFromWebScript:(SEL)selector { + return [self webScriptNameForSelector:selector] == nil; +} + +- (BOOL) supports:(NSString *)feature { + return [feature isEqualToString:@"window.open"]; +} + +- (Package *) getPackageById:(NSString *)id { + return [[Database sharedInstance] packageWithName:id]; +} + +- (NSArray *) statfs:(NSString *)path { + struct statfs stat; + + if (path == nil || statfs([path UTF8String], &stat) == -1) + return nil; + + return [NSArray arrayWithObjects: + [NSNumber numberWithUnsignedLong:stat.f_bsize], + [NSNumber numberWithUnsignedLong:stat.f_blocks], + [NSNumber numberWithUnsignedLong:stat.f_bfree], + nil]; +} + +- (NSNumber *) du:(NSString *)path { + NSNumber *value(nil); + + int fds[2]; + _assert(pipe(fds) != -1); + + pid_t pid(ExecFork()); + if (pid == 0) { + _assert(dup2(fds[1], 1) != -1); + _assert(close(fds[0]) != -1); + _assert(close(fds[1]) != -1); + /* XXX: this should probably not use du */ + execl("/usr/libexec/cydia/du", "du", "-s", [path UTF8String], NULL); + exit(1); + _assert(false); + } + + _assert(close(fds[1]) != -1); + + if (FILE *du = fdopen(fds[0], "r")) { + char line[1024]; + while (fgets(line, sizeof(line), du) != NULL) { + size_t length(strlen(line)); + while (length != 0 && line[length - 1] == '\n') + line[--length] = '\0'; + if (char *tab = strchr(line, '\t')) { + *tab = '\0'; + value = [NSNumber numberWithUnsignedLong:strtoul(line, NULL, 0)]; + } + } + + fclose(du); + } else _assert(close(fds[0])); + + int status; + wait: + if (waitpid(pid, &status, 0) == -1) + if (errno == EINTR) + goto wait; + else _assert(false); + + return value; +} + +- (void) close { + [indirect_ close]; +} + +- (void) setAutoPopup:(BOOL)popup { + [indirect_ setAutoPopup:popup]; +} + +- (void) setButtonImage:(NSString *)button withStyle:(NSString *)style toFunction:(id)function { + [indirect_ setButtonImage:button withStyle:style toFunction:function]; +} + +- (void) setButtonTitle:(NSString *)button withStyle:(NSString *)style toFunction:(id)function { + [indirect_ setButtonTitle:button withStyle:style toFunction:function]; +} + +- (void) setSpecial:(id)function { + [indirect_ setSpecial:function]; +} + +- (void) setFinishHook:(id)function { + [indirect_ setFinishHook:function]; +} + +- (void) setPopupHook:(id)function { + [indirect_ setPopupHook:function]; +} + +- (void) setViewportWidth:(float)width { + [indirect_ setViewportWidth:width]; +} + +- (NSString *) stringWithFormat:(NSString *)format arguments:(WebScriptObject *)arguments { + //NSLog(@"SWF:\"%@\" A:%@", format, [arguments description]); + unsigned count([arguments count]); + id values[count]; + for (unsigned i(0); i != count; ++i) + values[i] = [arguments objectAtIndex:i]; + return [[[NSString alloc] initWithFormat:format arguments:reinterpret_cast(values)] autorelease]; +} + +- (NSString *) localizedStringForKey:(NSString *)key value:(NSString *)value table:(NSString *)table { + if (reinterpret_cast(value) == [WebUndefined undefined]) + value = nil; + if (reinterpret_cast(table) == [WebUndefined undefined]) + table = nil; + return [[NSBundle mainBundle] localizedStringForKey:key value:value table:table]; +} + +@end +/* }}} */ + +@interface CydiaBrowserView : BrowserView { + CydiaObject *cydia_; +} @end -@implementation MailToView +@implementation CydiaBrowserView - (void) dealloc { - [controller_ release]; + [cydia_ release]; [super dealloc]; } -- (void) mailComposeControllerWillAttemptToSend:(MailComposeController *)controller { - NSLog(@"will"); +- (void) webView:(WebView *)sender didClearWindowObject:(WebScriptObject *)window forFrame:(WebFrame *)frame { + [super webView:sender didClearWindowObject:window forFrame:frame]; + [window setValue:cydia_ forKey:@"cydia"]; } -- (void) mailComposeControllerDidAttemptToSend:(MailComposeController *)controller mailDelivery:(id)delivery { - NSLog(@"did:%@", delivery); -// [UIApp setStatusBarShowsProgress:NO]; -if ([controller error]){ -NSArray *buttons = [NSArray arrayWithObjects:CYLocalize("OK"), nil]; -UIActionSheet *mailAlertSheet = [[UIActionSheet alloc] initWithTitle:CYLocalize("ERROR") buttons:buttons defaultButtonIndex:0 delegate:self context:self]; -[mailAlertSheet setBodyText:[controller error]]; -[mailAlertSheet popupAlertAnimated:YES]; -} -} +- (NSURLRequest *) webView:(WebView *)sender resource:(id)identifier willSendRequest:(NSURLRequest *)request redirectResponse:(NSURLResponse *)redirectResponse fromDataSource:(WebDataSource *)source { + NSMutableURLRequest *copy = [request mutableCopy]; + + if (Machine_ != NULL) + [copy setValue:[NSString stringWithUTF8String:Machine_] forHTTPHeaderField:@"X-Machine"]; + if (UniqueID_ != nil) + [copy setValue:UniqueID_ forHTTPHeaderField:@"X-Unique-ID"]; + + if (Role_ != nil) + [copy setValue:Role_ forHTTPHeaderField:@"X-Role"]; -- (void) showError { - NSLog(@"%@", [controller_ error]); - NSArray *buttons = [NSArray arrayWithObjects:CYLocalize("OK"), nil]; - UIActionSheet *mailAlertSheet = [[UIActionSheet alloc] initWithTitle:CYLocalize("ERROR") buttons:buttons defaultButtonIndex:0 delegate:self context:self]; - [mailAlertSheet setBodyText:[controller_ error]]; - [mailAlertSheet popupAlertAnimated:YES]; + return copy; } -- (void) deliverMessage { _pooled - setuid(501); - setgid(501); +- (id) initWithBook:(RVBook *)book forWidth:(float)width { + if ((self = [super initWithBook:book forWidth:width ofClass:[CydiaBrowserView class]]) != nil) { + cydia_ = [[CydiaObject alloc] initWithDelegate:indirect_]; - if (![controller_ deliverMessage]) - [self performSelectorOnMainThread:@selector(showError) withObject:nil waitUntilDone:NO]; -} + WebView *webview([webview_ webView]); -- (void) mailComposeControllerCompositionFinished:(MailComposeController *)controller { - if ([controller_ needsDelivery]) - [NSThread detachNewThreadSelector:@selector(deliverMessage) toTarget:self withObject:nil]; - else - [self cancel]; -} + Package *package([[Database sharedInstance] packageWithName:@"cydia"]); + NSString *application = package == nil ? @"Cydia" : [NSString + stringWithFormat:@"Cydia/%@", + [package installed] + ]; -- (id) initWithView:(UIView *)view delegate:(id)delegate url:(NSURL *)url { - if ((self = [super initWithView:view delegate:delegate]) != nil) { - controller_ = [[MailComposeController alloc] initForContentSize:[overlay_ bounds].size]; - [controller_ setDelegate:self]; - [controller_ initializeUI]; - [controller_ setupForURL:url]; + if (Product_ != nil) + application = [NSString stringWithFormat:@"%@ Version/%@", application, Product_]; + if (Build_ != nil) + application = [NSString stringWithFormat:@"%@ Mobile/%@", application, Build_]; + if (Safari_ != nil) + application = [NSString stringWithFormat:@"%@ Safari/%@", application, Safari_]; - UIView *view([controller_ view]); - [overlay_ addSubview:view]; + [webview setApplicationNameForUserAgent:application]; } return self; } @end -/* }}} */ -#endif - -/* Confirmation View {{{ */ -bool DepSubstrate(const pkgCache::VerIterator &iterator) { - if (!iterator.end()) - for (pkgCache::DepIterator dep(iterator.DependsList()); !dep.end(); ++dep) { - if (dep->Type != pkgCache::Dep::Depends && dep->Type != pkgCache::Dep::PreDepends) - continue; - pkgCache::PkgIterator package(dep.TargetPkg()); - if (package.end()) - continue; - if (strcmp(package.Name(), "mobilesubstrate") == 0) - return true; - } - - return false; -} @protocol ConfirmationViewDelegate - (void) cancel; @@ -3282,7 +3805,7 @@ bool DepSubstrate(const pkgCache::VerIterator &iterator) { - (void) queue; @end -@interface ConfirmationView : BrowserView { +@interface ConfirmationView : CydiaBrowserView { _transient Database *database_; UIActionSheet *essential_; NSArray *changes_; @@ -3387,13 +3910,13 @@ bool DepSubstrate(const pkgCache::VerIterator &iterator) { if (!remove) essential_ = nil; else if (Advanced_ || true) { - NSString *parenthetical(CYLocalize("PARENTHETICAL")); + NSString *parenthetical(UCLocalize("PARENTHETICAL")); essential_ = [[UIActionSheet alloc] - initWithTitle:CYLocalize("REMOVING_ESSENTIALS") + initWithTitle:UCLocalize("REMOVING_ESSENTIALS") buttons:[NSArray arrayWithObjects: - [NSString stringWithFormat:parenthetical, CYLocalize("CANCEL_OPERATION"), CYLocalize("SAFE")], - [NSString stringWithFormat:parenthetical, CYLocalize("FORCE_REMOVAL"), CYLocalize("UNSAFE")], + [NSString stringWithFormat:parenthetical, UCLocalize("CANCEL_OPERATION"), UCLocalize("SAFE")], + [NSString stringWithFormat:parenthetical, UCLocalize("FORCE_REMOVAL"), UCLocalize("UNSAFE")], nil] defaultButtonIndex:0 delegate:self @@ -3403,17 +3926,17 @@ bool DepSubstrate(const pkgCache::VerIterator &iterator) { #ifndef __OBJC2__ [essential_ setDestructiveButton:[[essential_ buttons] objectAtIndex:0]]; #endif - [essential_ setBodyText:CYLocalize("REMOVING_ESSENTIALS_EX")]; + [essential_ setBodyText:UCLocalize("REMOVING_ESSENTIALS_EX")]; } else { essential_ = [[UIActionSheet alloc] - initWithTitle:CYLocalize("UNABLE_TO_COMPLY") - buttons:[NSArray arrayWithObjects:CYLocalize("OKAY"), nil] + initWithTitle:UCLocalize("UNABLE_TO_COMPLY") + buttons:[NSArray arrayWithObjects:UCLocalize("OKAY"), nil] defaultButtonIndex:0 delegate:self context:@"unable" ]; - [essential_ setBodyText:CYLocalize("UNABLE_TO_COMPLY_EX")]; + [essential_ setBodyText:UCLocalize("UNABLE_TO_COMPLY_EX")]; } changes_ = [[NSArray alloc] initWithObjects: @@ -3439,11 +3962,11 @@ bool DepSubstrate(const pkgCache::VerIterator &iterator) { } - (NSString *) backButtonTitle { - return CYLocalize("CONFIRM"); + return UCLocalize("CONFIRM"); } - (NSString *) leftButtonTitle { - return [NSString stringWithFormat:CYLocalize("SLASH_DELIMITED"), CYLocalize("CANCEL"), CYLocalize("QUEUE")]; + return [NSString stringWithFormat:UCLocalize("SLASH_DELIMITED"), UCLocalize("CANCEL"), UCLocalize("QUEUE")]; } - (id) rightButtonTitle { @@ -3454,7 +3977,7 @@ bool DepSubstrate(const pkgCache::VerIterator &iterator) { #if AlwaysReload || IgnoreInstall return [super _rightButtonTitle]; #else - return CYLocalize("CONFIRM"); + return UCLocalize("CONFIRM"); #endif } @@ -3688,100 +4211,60 @@ bool DepSubstrate(const pkgCache::VerIterator &iterator) { [transition_ transition:6 toView:view_]; } -- (void) alertSheet:(UIActionSheet *)sheet buttonClicked:(int)button { - NSString *context([sheet context]); - - if ([context isEqualToString:@"error"]) - [sheet dismiss]; - else if ([context isEqualToString:@"conffile"]) { - FILE *input = [database_ input]; - - switch (button) { - case 1: - fprintf(input, "N\n"); - fflush(input); - break; - case 2: - fprintf(input, "Y\n"); - fflush(input); - break; - default: - _assert(false); - } - - [sheet dismiss]; - } -} - -- (void) closeButtonPushed { - running_ = NO; - - switch (Finish_) { - case 0: - [self resetView]; - break; - - case 1: - [delegate_ suspendWithAnimation:YES]; - break; +- (void) _checkError { + if (_error->PendingError()) { + std::string error; + if (!_error->PopMessage(error)) + _assert(false); - case 2: - system("launchctl stop com.apple.SpringBoard"); - break; + UIActionSheet *sheet = [[[UIActionSheet alloc] + initWithTitle:UCLocalize("ERROR") + buttons:[NSArray arrayWithObjects:UCLocalize("OKAY"), nil] + defaultButtonIndex:0 + delegate:self + context:@"_error" + ] autorelease]; - case 3: - system("launchctl unload "SpringBoard_"; launchctl load "SpringBoard_); - break; + [sheet setBodyText:[NSString stringWithUTF8String:error.c_str()]]; + [sheet popupAlertAnimated:YES]; - case 4: - system("reboot"); - break; + return; } -} - -- (void) _retachThread { - UINavigationItem *item = [navbar_ topItem]; - [item setTitle:CYLocalize("COMPLETE")]; - - [overlay_ addSubview:close_]; - [progress_ removeFromSuperview]; - [status_ removeFromSuperview]; [delegate_ progressViewIsComplete:self]; if (Finish_ < 4) { - FileFd file(SandboxTemplate_, FileFd::ReadOnly); - MMap mmap(file, MMap::ReadOnly); - SHA1Summation sha1; - sha1.Add(reinterpret_cast(mmap.Data()), mmap.Size()); - if (!(sandplate_ == sha1.Result())) - Finish_ = 4; - } - - if (Finish_ < 4) { - FileFd file(NotifyConfig_, FileFd::ReadOnly); - MMap mmap(file, MMap::ReadOnly); - SHA1Summation sha1; - sha1.Add(reinterpret_cast(mmap.Data()), mmap.Size()); - if (!(notifyconf_ == sha1.Result())) - Finish_ = 4; + FileFd file; + if (!file.Open(NotifyConfig_, FileFd::ReadOnly)) + _error->Discard(); + else { + MMap mmap(file, MMap::ReadOnly); + SHA1Summation sha1; + sha1.Add(reinterpret_cast(mmap.Data()), mmap.Size()); + if (!(notifyconf_ == sha1.Result())) + Finish_ = 4; + } } if (Finish_ < 3) { - FileFd file(SpringBoard_, FileFd::ReadOnly); - MMap mmap(file, MMap::ReadOnly); - SHA1Summation sha1; - sha1.Add(reinterpret_cast(mmap.Data()), mmap.Size()); - if (!(springlist_ == sha1.Result())) - Finish_ = 3; + FileFd file; + if (!file.Open(SpringBoard_, FileFd::ReadOnly)) + _error->Discard(); + else { + MMap mmap(file, MMap::ReadOnly); + SHA1Summation sha1; + sha1.Add(reinterpret_cast(mmap.Data()), mmap.Size()); + if (!(springlist_ == sha1.Result())) + Finish_ = 3; + } } switch (Finish_) { - case 0: [close_ setTitle:CYLocalize("RETURN_TO_CYDIA")]; break; - case 1: [close_ setTitle:CYLocalize("CLOSE_CYDIA")]; break; - case 2: [close_ setTitle:CYLocalize("RESTART_SPRINGBOARD")]; break; - case 3: [close_ setTitle:CYLocalize("RELOAD_SPRINGBOARD")]; break; - case 4: [close_ setTitle:CYLocalize("REBOOT_DEVICE")]; break; + case 0: [close_ setTitle:UCLocalize("RETURN_TO_CYDIA")]; break; + case 1: [close_ setTitle:UCLocalize("CLOSE_CYDIA")]; break; + case 2: [close_ setTitle:UCLocalize("RESTART_SPRINGBOARD")]; break; + case 3: [close_ setTitle:UCLocalize("RELOAD_SPRINGBOARD")]; break; + case 4: [close_ setTitle:UCLocalize("REBOOT_DEVICE")]; break; } #define Cache_ "/User/Library/Caches/com.apple.mobile.installation.plist" @@ -3834,6 +4317,71 @@ bool DepSubstrate(const pkgCache::VerIterator &iterator) { [delegate_ setStatusBarShowsProgress:NO]; } +- (void) alertSheet:(UIActionSheet *)sheet buttonClicked:(int)button { + NSString *context([sheet context]); + + if ([context isEqualToString:@"error"]) + [sheet dismiss]; + else if ([context isEqualToString:@"_error"]) { + [sheet dismiss]; + [self _checkError]; + } else if ([context isEqualToString:@"conffile"]) { + FILE *input = [database_ input]; + + switch (button) { + case 1: + fprintf(input, "N\n"); + fflush(input); + break; + case 2: + fprintf(input, "Y\n"); + fflush(input); + break; + default: + _assert(false); + } + + [sheet dismiss]; + } +} + +- (void) closeButtonPushed { + running_ = NO; + + switch (Finish_) { + case 0: + [self resetView]; + break; + + case 1: + [delegate_ suspendWithAnimation:YES]; + break; + + case 2: + system("launchctl stop com.apple.SpringBoard"); + break; + + case 3: + system("launchctl unload "SpringBoard_"; launchctl load "SpringBoard_); + break; + + case 4: + system("reboot"); + break; + } +} + +- (void) _retachThread { + UINavigationItem *item = [navbar_ topItem]; + [item setTitle:UCLocalize("COMPLETE")]; + + [overlay_ addSubview:close_]; + [progress_ removeFromSuperview]; + [status_ removeFromSuperview]; + + [self _checkError]; +} + - (void) _detachNewThreadData:(ProgressData *)data { _pooled [[data target] performSelector:[data selector] withObject:[data object]]; [data release]; @@ -3857,27 +4405,27 @@ bool DepSubstrate(const pkgCache::VerIterator &iterator) { running_ = YES; { - FileFd file(SandboxTemplate_, FileFd::ReadOnly); - MMap mmap(file, MMap::ReadOnly); - SHA1Summation sha1; - sha1.Add(reinterpret_cast(mmap.Data()), mmap.Size()); - sandplate_ = sha1.Result(); - } - - { - FileFd file(NotifyConfig_, FileFd::ReadOnly); - MMap mmap(file, MMap::ReadOnly); - SHA1Summation sha1; - sha1.Add(reinterpret_cast(mmap.Data()), mmap.Size()); - notifyconf_ = sha1.Result(); + FileFd file; + if (!file.Open(NotifyConfig_, FileFd::ReadOnly)) + _error->Discard(); + else { + MMap mmap(file, MMap::ReadOnly); + SHA1Summation sha1; + sha1.Add(reinterpret_cast(mmap.Data()), mmap.Size()); + notifyconf_ = sha1.Result(); + } } { - FileFd file(SpringBoard_, FileFd::ReadOnly); - MMap mmap(file, MMap::ReadOnly); - SHA1Summation sha1; - sha1.Add(reinterpret_cast(mmap.Data()), mmap.Size()); - springlist_ = sha1.Result(); + FileFd file; + if (!file.Open(SpringBoard_, FileFd::ReadOnly)) + _error->Discard(); + else { + MMap mmap(file, MMap::ReadOnly); + SHA1Summation sha1; + sha1.Add(reinterpret_cast(mmap.Data()), mmap.Size()); + springlist_ = sha1.Result(); + } } [transition_ transition:6 toView:overlay_]; @@ -3898,7 +4446,7 @@ bool DepSubstrate(const pkgCache::VerIterator &iterator) { detachNewThreadSelector:selector toTarget:database_ withObject:nil - title:CYLocalize("REPAIRING") + title:UCLocalize("REPAIRING") ]; } @@ -3915,7 +4463,7 @@ bool DepSubstrate(const pkgCache::VerIterator &iterator) { UIActionSheet *sheet = [[[UIActionSheet alloc] initWithTitle:(package == nil ? id : [package name]) - buttons:[NSArray arrayWithObjects:CYLocalize("OKAY"), nil] + buttons:[NSArray arrayWithObjects:UCLocalize("OKAY"), nil] defaultButtonIndex:0 delegate:self context:@"error" @@ -3965,18 +4513,18 @@ bool DepSubstrate(const pkgCache::VerIterator &iterator) { //NSString *nfile = conffile_r[2]; UIActionSheet *sheet = [[[UIActionSheet alloc] - initWithTitle:CYLocalize("CONFIGURATION_UPGRADE") + initWithTitle:UCLocalize("CONFIGURATION_UPGRADE") buttons:[NSArray arrayWithObjects: - CYLocalize("KEEP_OLD_COPY"), - CYLocalize("ACCEPT_NEW_COPY"), - // XXX: CYLocalize("SEE_WHAT_CHANGED"), + UCLocalize("KEEP_OLD_COPY"), + UCLocalize("ACCEPT_NEW_COPY"), + // XXX: UCLocalize("SEE_WHAT_CHANGED"), nil] defaultButtonIndex:0 delegate:self context:@"conffile" ] autorelease]; - [sheet setBodyText:[NSString stringWithFormat:@"%@\n\n%@", CYLocalize("CONFIGURATION_UPGRADE_EX"), ofile]]; + [sheet setBodyText:[NSString stringWithFormat:@"%@\n\n%@", UCLocalize("CONFIGURATION_UPGRADE_EX"), ofile]]; [sheet popupAlertAnimated:YES]; } @@ -4083,12 +4631,13 @@ bool DepSubstrate(const pkgCache::VerIterator &iterator) { - (void) setPackage:(Package *)package { [self clearPackage]; + [package parse]; Source *source = [package source]; icon_ = [[package icon] retain]; name_ = [[package name] retain]; - description_ = [[package tagline] retain]; + description_ = [[package shortDescription] retain]; commercial_ = [package isCommercial]; package_ = [package retain]; @@ -4100,19 +4649,19 @@ bool DepSubstrate(const pkgCache::VerIterator &iterator) { label = [source label]; trusted = [source trusted]; } else if ([[package id] isEqualToString:@"firmware"]) - label = CYLocalize("APPLE"); + label = UCLocalize("APPLE"); else - label = [NSString stringWithFormat:CYLocalize("SLASH_DELIMITED"), CYLocalize("UNKNOWN"), CYLocalize("LOCAL")]; + label = [NSString stringWithFormat:UCLocalize("SLASH_DELIMITED"), UCLocalize("UNKNOWN"), UCLocalize("LOCAL")]; NSString *from(label); NSString *section = [package simpleSection]; if (section != nil && ![section isEqualToString:label]) { section = [[NSBundle mainBundle] localizedStringForKey:section value:nil table:@"Sections"]; - from = [NSString stringWithFormat:CYLocalize("PARENTHETICAL"), from, section]; + from = [NSString stringWithFormat:UCLocalize("PARENTHETICAL"), from, section]; } - from = [NSString stringWithFormat:CYLocalize("FROM"), label]; + from = [NSString stringWithFormat:UCLocalize("FROM"), from]; source_ = [from retain]; if (NSString *purpose = [package primaryPurpose]) @@ -4125,11 +4674,11 @@ bool DepSubstrate(const pkgCache::VerIterator &iterator) { [mode isEqualToString:@"REMOVE"] || [mode isEqualToString:@"PURGE"] ? @"removing.png" : @"installing.png" ]]; - [status_ setText:[NSString stringWithFormat:CYLocalize("QUEUED_FOR"), CYLocalize(mode)]]; + [status_ setText:[NSString stringWithFormat:UCLocalize("QUEUED_FOR"), UCLocalize(mode)]]; [status_ setColor:[UIColor colorWithCGColor:Blueish_]]; } else if ([package half]) { [badge_ setImage:[UIImage applicationImageNamed:@"damaged.png"]]; - [status_ setText:CYLocalize("PACKAGE_DAMAGED")]; + [status_ setText:UCLocalize("PACKAGE_DAMAGED")]; [status_ setColor:[UIColor redColor]]; } else { [badge_ setImage:nil]; @@ -4213,14 +4762,7 @@ bool DepSubstrate(const pkgCache::VerIterator &iterator) { } + (int) heightForPackage:(Package *)package { - NSString *tagline([package tagline]); - int height = tagline == nil || [tagline length] == 0 ? -17 : 0; -#ifdef USE_BADGES - if ([package hasMode] || [package half]) - return height + 96; - else -#endif - return height + 73; + return 73; } @end @@ -4298,13 +4840,13 @@ bool DepSubstrate(const pkgCache::VerIterator &iterator) { [self clearSection]; if (section == nil) { - name_ = [CYLocalize("ALL_PACKAGES") retain]; + name_ = [UCLocalize("ALL_PACKAGES") retain]; count_ = nil; } else { - section_ = [section name]; + section_ = [section localized]; if (section_ != nil) section_ = [section_ retain]; - name_ = [(section_ == nil ? CYLocalize("NO_SECTION") : section_) retain]; + name_ = [(section_ == nil || [section_ length] == 0 ? UCLocalize("NO_SECTION") : section_) retain]; count_ = [[NSString stringWithFormat:@"%d", [section count]] retain]; if (editing_) @@ -4392,7 +4934,7 @@ bool DepSubstrate(const pkgCache::VerIterator &iterator) { [self addSubview:list_]; UITableColumn *column = [[[UITableColumn alloc] - initWithTitle:CYLocalize("NAME") + initWithTitle:UCLocalize("NAME") identifier:@"name" width:[self frame].size.width ] autorelease]; @@ -4460,17 +5002,17 @@ bool DepSubstrate(const pkgCache::VerIterator &iterator) { } - (NSString *) title { - return CYLocalize("INSTALLED_FILES"); + return UCLocalize("INSTALLED_FILES"); } - (NSString *) backButtonTitle { - return CYLocalize("FILES"); + return UCLocalize("FILES"); } @end /* }}} */ /* Package View {{{ */ -@interface PackageView : BrowserView { +@interface PackageView : CydiaBrowserView { _transient Database *database_; Package *package_; NSString *name_; @@ -4502,15 +5044,15 @@ bool DepSubstrate(const pkgCache::VerIterator &iterator) { /* XXX: this is not safe at all... localization of /fail/ */ - (void) _clickButtonWithName:(NSString *)name { - if ([name isEqualToString:CYLocalize("CLEAR")]) + if ([name isEqualToString:UCLocalize("CLEAR")]) [delegate_ clearPackage:package_]; - else if ([name isEqualToString:CYLocalize("INSTALL")]) + else if ([name isEqualToString:UCLocalize("INSTALL")]) [delegate_ installPackage:package_]; - else if ([name isEqualToString:CYLocalize("REINSTALL")]) + else if ([name isEqualToString:UCLocalize("REINSTALL")]) [delegate_ installPackage:package_]; - else if ([name isEqualToString:CYLocalize("REMOVE")]) + else if ([name isEqualToString:UCLocalize("REMOVE")]) [delegate_ removePackage:package_]; - else if ([name isEqualToString:CYLocalize("UPGRADE")]) + else if ([name isEqualToString:UCLocalize("UPGRADE")]) [delegate_ installPackage:package_]; else _assert(false); } @@ -4554,7 +5096,7 @@ bool DepSubstrate(const pkgCache::VerIterator &iterator) { else { NSMutableArray *buttons = [NSMutableArray arrayWithCapacity:(count + 1)]; [buttons addObjectsFromArray:buttons_]; - [buttons addObject:CYLocalize("CANCEL")]; + [buttons addObject:UCLocalize("CANCEL")]; [delegate_ slideUp:[[[UIActionSheet alloc] initWithTitle:nil @@ -4576,7 +5118,7 @@ bool DepSubstrate(const pkgCache::VerIterator &iterator) { - (id) _rightButtonTitle { int count = [buttons_ count]; - return count == 0 ? nil : count != 1 ? CYLocalize("MODIFY") : [buttons_ objectAtIndex:0]; + return count == 0 ? nil : count != 1 ? UCLocalize("MODIFY") : [buttons_ objectAtIndex:0]; } - (NSString *) backButtonTitle { @@ -4605,21 +5147,23 @@ bool DepSubstrate(const pkgCache::VerIterator &iterator) { [buttons_ removeAllObjects]; if (package != nil) { + [package parse]; + package_ = [package retain]; name_ = [[package id] retain]; commercial_ = [package isCommercial]; if ([package_ mode] != nil) - [buttons_ addObject:CYLocalize("CLEAR")]; + [buttons_ addObject:UCLocalize("CLEAR")]; if ([package_ source] == nil); else if ([package_ upgradableAndEssential:NO]) - [buttons_ addObject:CYLocalize("UPGRADE")]; - else if ([package_ installed] == nil) - [buttons_ addObject:CYLocalize("INSTALL")]; + [buttons_ addObject:UCLocalize("UPGRADE")]; + else if ([package_ uninstalled]) + [buttons_ addObject:UCLocalize("INSTALL")]; else - [buttons_ addObject:CYLocalize("REINSTALL")]; - if ([package_ installed] != nil) - [buttons_ addObject:CYLocalize("REMOVE")]; + [buttons_ addObject:UCLocalize("REINSTALL")]; + if (![package_ uninstalled]) + [buttons_ addObject:UCLocalize("REMOVE")]; if (special_ != NULL) { CGRect frame([webview_ frame]); @@ -4638,6 +5182,7 @@ bool DepSubstrate(const pkgCache::VerIterator &iterator) { [self setPopupHook:nil]; WebThreadUnlock(); + //[self yieldToSelector:@selector(callFunction:) withObject:special_]; [super callFunction:special_]; } } @@ -4745,7 +5290,7 @@ bool DepSubstrate(const pkgCache::VerIterator &iterator) { [list_ setDataSource:self]; UITableColumn *column = [[[UITableColumn alloc] - initWithTitle:CYLocalize("NAME") + initWithTitle:UCLocalize("NAME") identifier:@"name" width:[self frame].size.width ] autorelease]; @@ -4879,6 +5424,7 @@ bool DepSubstrate(const pkgCache::VerIterator &iterator) { /* XXX: this is an unsafe optimization of doomy hell */ Method method = class_getInstanceMethod([Package class], filter); + _assert(method != NULL); imp_ = method_getImplementation(method); _assert(imp_ != NULL); @@ -5031,8 +5577,8 @@ bool DepSubstrate(const pkgCache::VerIterator &iterator) { - (NSString *) sectionList:(UISectionList *)list titleForSection:(int)section { switch (section + (offset_ == 0 ? 1 : 0)) { - case 0: return CYLocalize("ENTERED_BY_USER"); - case 1: return CYLocalize("INSTALLED_BY_PACKAGE"); + case 0: return UCLocalize("ENTERED_BY_USER"); + case 1: return UCLocalize("INSTALLED_BY_PACKAGE"); default: _assert(false); @@ -5160,8 +5706,8 @@ bool DepSubstrate(const pkgCache::VerIterator &iterator) { defer = true; UIActionSheet *sheet = [[[UIActionSheet alloc] - initWithTitle:CYLocalize("SOURCE_WARNING") - buttons:[NSArray arrayWithObjects:CYLocalize("ADD_ANYWAY"), CYLocalize("CANCEL"), nil] + initWithTitle:UCLocalize("SOURCE_WARNING") + buttons:[NSArray arrayWithObjects:UCLocalize("ADD_ANYWAY"), UCLocalize("CANCEL"), nil] defaultButtonIndex:0 delegate:self context:@"warning" @@ -5175,8 +5721,8 @@ bool DepSubstrate(const pkgCache::VerIterator &iterator) { [self complete]; } else if (error_ != nil) { UIActionSheet *sheet = [[[UIActionSheet alloc] - initWithTitle:CYLocalize("VERIFICATION_ERROR") - buttons:[NSArray arrayWithObjects:CYLocalize("OK"), nil] + initWithTitle:UCLocalize("VERIFICATION_ERROR") + buttons:[NSArray arrayWithObjects:UCLocalize("OK"), nil] defaultButtonIndex:0 delegate:self context:@"urlerror" @@ -5186,14 +5732,14 @@ bool DepSubstrate(const pkgCache::VerIterator &iterator) { [sheet popupAlertAnimated:YES]; } else { UIActionSheet *sheet = [[[UIActionSheet alloc] - initWithTitle:CYLocalize("NOT_REPOSITORY") - buttons:[NSArray arrayWithObjects:CYLocalize("OK"), nil] + initWithTitle:UCLocalize("NOT_REPOSITORY") + buttons:[NSArray arrayWithObjects:UCLocalize("OK"), nil] defaultButtonIndex:0 delegate:self context:@"trivial" ] autorelease]; - [sheet setBodyText:CYLocalize("NOT_REPOSITORY_EX")]; + [sheet setBodyText:UCLocalize("NOT_REPOSITORY_EX")]; [sheet popupAlertAnimated:YES]; } @@ -5276,7 +5822,7 @@ bool DepSubstrate(const pkgCache::VerIterator &iterator) { trivial_ = false; hud_ = [[delegate_ addProgressHUD] retain]; - [hud_ setText:CYLocalize("VERIFYING_URL")]; + [hud_ setText:UCLocalize("VERIFYING_URL")]; } break; case 2: @@ -5324,7 +5870,7 @@ bool DepSubstrate(const pkgCache::VerIterator &iterator) { [list_ setDataSource:self]; UITableColumn *column = [[UITableColumn alloc] - initWithTitle:CYLocalize("NAME") + initWithTitle:UCLocalize("NAME") identifier:@"name" width:[self frame].size.width ]; @@ -5372,8 +5918,8 @@ bool DepSubstrate(const pkgCache::VerIterator &iterator) { ] autorelease]];*/ UIActionSheet *sheet = [[[UIActionSheet alloc] - initWithTitle:CYLocalize("ENTER_APT_URL") - buttons:[NSArray arrayWithObjects:CYLocalize("ADD_SOURCE"), CYLocalize("CANCEL"), nil] + initWithTitle:UCLocalize("ENTER_APT_URL") + buttons:[NSArray arrayWithObjects:UCLocalize("ADD_SOURCE"), UCLocalize("CANCEL"), nil] defaultButtonIndex:0 delegate:self context:@"source" @@ -5401,15 +5947,15 @@ bool DepSubstrate(const pkgCache::VerIterator &iterator) { } - (NSString *) title { - return CYLocalize("SOURCES"); + return UCLocalize("SOURCES"); } - (NSString *) leftButtonTitle { - return [[list_ table] isRowDeletionEnabled] ? CYLocalize("ADD") : nil; + return [[list_ table] isRowDeletionEnabled] ? UCLocalize("ADD") : nil; } - (id) rightButtonTitle { - return [[list_ table] isRowDeletionEnabled] ? CYLocalize("DONE") : CYLocalize("EDIT"); + return [[list_ table] isRowDeletionEnabled] ? UCLocalize("DONE") : UCLocalize("EDIT"); } - (UINavigationButtonStyle) rightButtonStyle { @@ -5472,15 +6018,15 @@ bool DepSubstrate(const pkgCache::VerIterator &iterator) { } - (NSString *) title { - return CYLocalize("INSTALLED"); + return UCLocalize("INSTALLED"); } - (NSString *) backButtonTitle { - return CYLocalize("PACKAGES"); + return UCLocalize("PACKAGES"); } - (id) rightButtonTitle { - return Role_ != nil && [Role_ isEqualToString:@"Developer"] ? nil : expert_ ? CYLocalize("EXPERT") : CYLocalize("SIMPLE"); + return Role_ != nil && [Role_ isEqualToString:@"Developer"] ? nil : expert_ ? UCLocalize("EXPERT") : UCLocalize("SIMPLE"); } - (UINavigationButtonStyle) rightButtonStyle { @@ -5496,7 +6042,7 @@ bool DepSubstrate(const pkgCache::VerIterator &iterator) { /* }}} */ /* Home View {{{ */ -@interface HomeView : BrowserView { +@interface HomeView : CydiaBrowserView { } @end @@ -5514,8 +6060,8 @@ bool DepSubstrate(const pkgCache::VerIterator &iterator) { - (void) _leftButtonClicked { UIActionSheet *sheet = [[[UIActionSheet alloc] - initWithTitle:CYLocalize("ABOUT_CYDIA") - buttons:[NSArray arrayWithObjects:CYLocalize("CLOSE"), nil] + initWithTitle:UCLocalize("ABOUT_CYDIA") + buttons:[NSArray arrayWithObjects:UCLocalize("CLOSE"), nil] defaultButtonIndex:0 delegate:self context:@"about" @@ -5540,13 +6086,13 @@ bool DepSubstrate(const pkgCache::VerIterator &iterator) { } - (NSString *) leftButtonTitle { - return CYLocalize("ABOUT"); + return UCLocalize("ABOUT"); } @end /* }}} */ /* Manage View {{{ */ -@interface ManageView : BrowserView { +@interface ManageView : CydiaBrowserView { } @end @@ -5554,7 +6100,7 @@ bool DepSubstrate(const pkgCache::VerIterator &iterator) { @implementation ManageView - (NSString *) title { - return CYLocalize("MANAGE"); + return UCLocalize("MANAGE"); } - (void) _leftButtonClicked { @@ -5562,12 +6108,12 @@ bool DepSubstrate(const pkgCache::VerIterator &iterator) { } - (NSString *) leftButtonTitle { - return CYLocalize("SETTINGS"); + return UCLocalize("SETTINGS"); } #if !AlwaysReload - (id) _rightButtonTitle { - return Queuing_ ? CYLocalize("QUEUE") : nil; + return Queuing_ ? UCLocalize("QUEUE") : nil; } - (UINavigationButtonStyle) rightButtonStyle { @@ -5586,8 +6132,6 @@ bool DepSubstrate(const pkgCache::VerIterator &iterator) { @end /* }}} */ -#include - /* Cydia Book {{{ */ @interface CYBook : RVBook < ProgressDelegate @@ -5646,7 +6190,7 @@ bool DepSubstrate(const pkgCache::VerIterator &iterator) { [UIView endAnimations]; [indicator_ startAnimation]; - [prompt_ setText:CYLocalize("UPDATING_DATABASE")]; + [prompt_ setText:UCLocalize("UPDATING_DATABASE")]; [progress_ setProgress:0]; updating_ = true; @@ -5659,7 +6203,14 @@ bool DepSubstrate(const pkgCache::VerIterator &iterator) { ]; } -- (void) _update_ { +- (void) alertSheet:(UIActionSheet *)sheet buttonClicked:(int)button { + NSString *context([sheet context]); + + if ([context isEqualToString:@"refresh"]) + [sheet dismiss]; +} + +- (void) _update_:(NSString *)error { updating_ = false; [indicator_ stopAnimation]; @@ -5681,7 +6232,24 @@ bool DepSubstrate(const pkgCache::VerIterator &iterator) { [UIView commitAnimations]; - [delegate_ performSelector:@selector(reloadData) withObject:nil afterDelay:0]; + if (error == nil) + [delegate_ performSelector:@selector(reloadData) withObject:nil afterDelay:0]; + else { + UIActionSheet *sheet = [[[UIActionSheet alloc] + initWithTitle:[NSString stringWithFormat:UCLocalize("COLON_DELIMITED"), UCLocalize("ERROR"), UCLocalize("REFRESH")] + buttons:[NSArray arrayWithObjects: + UCLocalize("OK"), + nil] + defaultButtonIndex:0 + delegate:self + context:@"refresh" + ] autorelease]; + + [sheet setBodyText:error]; + [sheet popupAlertAnimated:YES]; + + [self reloadButtons]; + } } - (id) initWithFrame:(CGRect)frame database:(Database *)database { @@ -5749,11 +6317,10 @@ bool DepSubstrate(const pkgCache::VerIterator &iterator) { [progress_ setStyle:0]; [overlay_ addSubview:progress_]; - cancel_ = [[UINavigationButton alloc] initWithTitle:CYLocalize("CANCEL") style:UINavigationButtonStyleHighlighted]; + cancel_ = [[UINavigationButton alloc] initWithTitle:UCLocalize("CANCEL") style:UINavigationButtonStyleHighlighted]; [cancel_ addTarget:self action:@selector(_onCancel) forControlEvents:UIControlEventTouchUpInside]; CGRect frame = [cancel_ frame]; - frame.size.width = 65; frame.origin.x = ovrrect.size.width - frame.size.width - 5; frame.origin.y = (ovrrect.size.height - frame.size.height) / 2; [cancel_ setFrame:frame]; @@ -5771,17 +6338,17 @@ bool DepSubstrate(const pkgCache::VerIterator &iterator) { Status status; status.setDelegate(self); - [database_ updateWithStatus:status]; + NSString *error([database_ updateWithStatus:status]); [self - performSelectorOnMainThread:@selector(_update_) - withObject:nil + performSelectorOnMainThread:@selector(_update_:) + withObject:error waitUntilDone:NO ]; } - (void) setProgressError:(NSString *)error forPackage:(NSString *)id { - [prompt_ setText:[NSString stringWithFormat:CYLocalize("ERROR_MESSAGE"), error]]; + [prompt_ setText:[NSString stringWithFormat:UCLocalize("COLON_DELIMITED"), UCLocalize("ERROR"), error]]; } - (void) setProgressTitle:(NSString *)title { @@ -5815,10 +6382,6 @@ bool DepSubstrate(const pkgCache::VerIterator &iterator) { return !updating_; } -- (void) alertSheet:(UIActionSheet *)sheet buttonClicked:(int)button { - [sheet dismiss]; -} - - (void) _setProgressTitle:(NSString *)title { [prompt_ setText:title]; } @@ -6002,16 +6565,17 @@ bool DepSubstrate(const pkgCache::VerIterator &iterator) { if (row == 0) { section = nil; name = nil; - title = CYLocalize("ALL_PACKAGES"); + title = UCLocalize("ALL_PACKAGES"); } else { section = [filtered_ objectAtIndex:(row - 1)]; name = [section name]; - if (name != nil) + if (name != nil) { + name = [NSString stringWithString:name]; title = [[NSBundle mainBundle] localizedStringForKey:Simplify(name) value:nil table:@"Sections"]; - else { + } else { name = @""; - title = CYLocalize("NO_SECTION"); + title = UCLocalize("NO_SECTION"); } } @@ -6042,7 +6606,7 @@ bool DepSubstrate(const pkgCache::VerIterator &iterator) { [transition_ transition:0 toView:list_]; UITableColumn *column = [[[UITableColumn alloc] - initWithTitle:CYLocalize("NAME") + initWithTitle:UCLocalize("NAME") identifier:@"name" width:[self frame].size.width ] autorelease]; @@ -6086,7 +6650,7 @@ bool DepSubstrate(const pkgCache::VerIterator &iterator) { section = §ions[key]; if (*section == nil) { _profile(SectionsView$reloadData$Section$Allocate) - *section = [[[Section alloc] initWithName:name] autorelease]; + *section = [[[Section alloc] initWithName:name localize:YES] autorelease]; _end } _end @@ -6094,7 +6658,7 @@ bool DepSubstrate(const pkgCache::VerIterator &iterator) { [*section addToCount]; _profile(SectionsView$reloadData$Filter) - if (![package valid] || [package installed] != nil || ![package visible]) + if (![package valid] || ![package uninstalled] || ![package visible]) continue; _end @@ -6106,7 +6670,7 @@ bool DepSubstrate(const pkgCache::VerIterator &iterator) { section = [sections objectForKey:key]; if (section == nil) { _profile(SectionsView$reloadData$Section$Allocate) - section = [[[Section alloc] initWithName:name] autorelease]; + section = [[[Section alloc] initWithName:name localize:YES] autorelease]; [sections setObject:section forKey:key]; _end } @@ -6115,7 +6679,7 @@ bool DepSubstrate(const pkgCache::VerIterator &iterator) { [section addToCount]; _profile(SectionsView$reloadData$Filter) - if (![package valid] || [package installed] != nil || ![package visible]) + if (![package valid] || ![package uninstalled] || ![package visible]) continue; _end @@ -6131,14 +6695,14 @@ bool DepSubstrate(const pkgCache::VerIterator &iterator) { [sections_ addObjectsFromArray:[sections allValues]]; #endif - [sections_ sortUsingSelector:@selector(compareByName:)]; + [sections_ sortUsingSelector:@selector(compareByLocalized:)]; for (Section *section in sections_) { size_t count([section row]); - if ([section row] == 0) + if (count == 0) continue; - section = [[[Section alloc] initWithName:[section name]] autorelease]; + section = [[[Section alloc] initWithName:[section name] localized:[section localized]] autorelease]; [section setCount:count]; [filtered_ addObject:section]; } @@ -6166,15 +6730,15 @@ bool DepSubstrate(const pkgCache::VerIterator &iterator) { } - (NSString *) title { - return editing_ ? CYLocalize("SECTION_VISIBILITY") : CYLocalize("INSTALL_BY_SECTION"); + return editing_ ? UCLocalize("SECTION_VISIBILITY") : UCLocalize("INSTALL_BY_SECTION"); } - (NSString *) backButtonTitle { - return CYLocalize("SECTIONS"); + return UCLocalize("SECTIONS"); } - (id) rightButtonTitle { - return [sections_ count] == 0 ? nil : editing_ ? CYLocalize("DONE") : CYLocalize("EDIT"); + return [sections_ count] == 0 ? nil : editing_ ? UCLocalize("DONE") : UCLocalize("EDIT"); } - (UINavigationButtonStyle) rightButtonStyle { @@ -6218,7 +6782,6 @@ bool DepSubstrate(const pkgCache::VerIterator &iterator) { } - (NSString *) sectionList:(UISectionList *)list titleForSection:(int)section { - NSLog(@"titleForSection:%u", section); return [[sections_ objectAtIndex:section] name]; } @@ -6280,7 +6843,7 @@ bool DepSubstrate(const pkgCache::VerIterator &iterator) { //[list_ setSectionListStyle:1]; UITableColumn *column = [[[UITableColumn alloc] - initWithTitle:CYLocalize("NAME") + initWithTitle:UCLocalize("NAME") identifier:@"name" width:[self frame].size.width ] autorelease]; @@ -6307,33 +6870,29 @@ bool DepSubstrate(const pkgCache::VerIterator &iterator) { _trace(); for (Package *package in packages) if ( - [package installed] == nil && [package valid] && [package visible] || + [package uninstalled] && [package valid] && [package visible] || [package upgradableAndEssential:YES] ) [packages_ addObject:package]; _trace(); - [packages_ radixSortUsingFunction:reinterpret_cast(&PackageChangesRadix) withArgument:NULL]; + [packages_ radixSortUsingFunction:reinterpret_cast(&PackageChangesRadix) withContext:NULL]; _trace(); - Section *upgradable = [[[Section alloc] initWithName:CYLocalize("AVAILABLE_UPGRADES")] autorelease]; - Section *ignored = [[[Section alloc] initWithName:CYLocalize("IGNORED_UPGRADES")] autorelease]; + Section *upgradable = [[[Section alloc] initWithName:UCLocalize("AVAILABLE_UPGRADES") localize:NO] autorelease]; + Section *ignored = [[[Section alloc] initWithName:UCLocalize("IGNORED_UPGRADES") localize:NO] autorelease]; Section *section = nil; NSDate *last = nil; upgrades_ = 0; bool unseens = false; - CFDateFormatterRef formatter = CFDateFormatterCreate(NULL, Locale_, kCFDateFormatterMediumStyle, kCFDateFormatterMediumStyle); + CFDateFormatterRef formatter(CFDateFormatterCreate(NULL, Locale_, kCFDateFormatterMediumStyle, kCFDateFormatterMediumStyle)); - _trace(); for (size_t offset = 0, count = [packages_ count]; offset != count; ++offset) { Package *package = [packages_ objectAtIndex:offset]; - BOOL uae; - _profile(ChangesView$reloadData$Upgrade) - uae = [package upgradableAndEssential:YES]; - _end + BOOL uae = [package upgradableAndEssential:YES]; if (!uae) { unseens = true; @@ -6343,28 +6902,20 @@ bool DepSubstrate(const pkgCache::VerIterator &iterator) { seen = [package seen]; _end - bool different; - _profile(ChangesView$reloadData$Compare) - different = section == nil || last != seen && (seen == nil || [seen compare:last] != NSOrderedSame); - _end - - if (different) { + if (section == nil || last != seen && (seen == nil || [seen compare:last] != NSOrderedSame)) { last = seen; NSString *name; if (seen == nil) - name = CYLocalize("UNKNOWN"); + name = UCLocalize("UNKNOWN"); else { - _profile(ChangesView$reloadData$Format) - name = (NSString *) CFDateFormatterCreateStringWithDate(NULL, formatter, (CFDateRef) seen); - _end - + name = (NSString *) CFDateFormatterCreateStringWithDate(NULL, formatter, (CFDateRef) seen); [name autorelease]; } _profile(ChangesView$reloadData$Allocate) - name = [NSString stringWithFormat:CYLocalize("NEW_AT"), name]; - section = [[[Section alloc] initWithName:name row:offset] autorelease]; + name = [NSString stringWithFormat:UCLocalize("NEW_AT"), name]; + section = [[[Section alloc] initWithName:name row:offset localize:NO] autorelease]; [sections_ addObject:section]; _end } @@ -6402,15 +6953,15 @@ bool DepSubstrate(const pkgCache::VerIterator &iterator) { } - (NSString *) leftButtonTitle { - return [(CYBook *)book_ updating] ? nil : CYLocalize("REFRESH"); + return [(CYBook *)book_ updating] ? nil : UCLocalize("REFRESH"); } - (id) rightButtonTitle { - return upgrades_ == 0 ? nil : [NSString stringWithFormat:CYLocalize("PARENTHETICAL"), CYLocalize("UPGRADE"), [NSString stringWithFormat:@"%u", upgrades_]]; + return upgrades_ == 0 ? nil : [NSString stringWithFormat:UCLocalize("PARENTHETICAL"), UCLocalize("UPGRADE"), [NSString stringWithFormat:@"%u", upgrades_]]; } - (NSString *) title { - return CYLocalize("CHANGES"); + return UCLocalize("CHANGES"); } @end @@ -6456,7 +7007,7 @@ bool DepSubstrate(const pkgCache::VerIterator &iterator) { - (NSString *) preferencesTable:(UIPreferencesTable *)table titleForGroup:(int)group { switch (group) { - case 0: return [NSString stringWithFormat:CYLocalize("PARENTHETICAL"), CYLocalize("ADVANCED_SEARCH"), CYLocalize("COMING_SOON")]; + case 0: return [NSString stringWithFormat:UCLocalize("PARENTHETICAL"), UCLocalize("ADVANCED_SEARCH"), UCLocalize("COMING_SOON")]; default: _assert(false); } @@ -6589,7 +7140,7 @@ bool DepSubstrate(const pkgCache::VerIterator &iterator) { UIFont *font = [UIFont systemFontOfSize:16]; [field_ setFont:font]; - [field_ setPlaceholder:CYLocalize("SEARCH_EX")]; + [field_ setPlaceholder:UCLocalize("SEARCH_EX")]; [field_ setDelegate:self]; [field_ setPaddingTop:5]; @@ -6665,7 +7216,7 @@ bool DepSubstrate(const pkgCache::VerIterator &iterator) { } - (NSString *) backButtonTitle { - return CYLocalize("SEARCH"); + return UCLocalize("SEARCH"); } - (void) setDelegate:(id)delegate { @@ -6802,7 +7353,7 @@ bool DepSubstrate(const pkgCache::VerIterator &iterator) { case 0: { UIPreferencesControlTableCell *cell([[[UIPreferencesControlTableCell alloc] init] autorelease]); [cell setShowSelection:NO]; - [cell setTitle:CYLocalize("SHOW_ALL_CHANGES_EX")]; + [cell setTitle:UCLocalize("SHOW_ALL_CHANGES_EX")]; return cell; } @@ -6831,12 +7382,12 @@ bool DepSubstrate(const pkgCache::VerIterator &iterator) { subscribedCell_ = [[UIPreferencesControlTableCell alloc] init]; [subscribedCell_ setShowSelection:NO]; - [subscribedCell_ setTitle:CYLocalize("SHOW_ALL_CHANGES")]; + [subscribedCell_ setTitle:UCLocalize("SHOW_ALL_CHANGES")]; [subscribedCell_ setControl:subscribedSwitch_]; ignoredCell_ = [[UIPreferencesControlTableCell alloc] init]; [ignoredCell_ setShowSelection:NO]; - [ignoredCell_ setTitle:CYLocalize("IGNORE_UPGRADES")]; + [ignoredCell_ setTitle:UCLocalize("IGNORE_UPGRADES")]; [ignoredCell_ setControl:ignoredSwitch_]; [table_ setDataSource:self]; @@ -6862,13 +7413,13 @@ bool DepSubstrate(const pkgCache::VerIterator &iterator) { } - (NSString *) title { - return CYLocalize("SETTINGS"); + return UCLocalize("SETTINGS"); } @end /* Signature View {{{ */ -@interface SignatureView : BrowserView { +@interface SignatureView : CydiaBrowserView { _transient Database *database_; NSString *package_; } @@ -6938,7 +7489,7 @@ bool DepSubstrate(const pkgCache::VerIterator &iterator) { ManageView *manage_; SearchView *search_; - PackageView *package_; + NSMutableArray *details_; } @end @@ -6950,34 +7501,34 @@ bool DepSubstrate(const pkgCache::VerIterator &iterator) { int count = [broken_ count]; UIActionSheet *sheet = [[[UIActionSheet alloc] - initWithTitle:(count == 1 ? CYLocalize("HALFINSTALLED_PACKAGE") : [NSString stringWithFormat:CYLocalize("HALFINSTALLED_PACKAGES"), count]) + initWithTitle:(count == 1 ? UCLocalize("HALFINSTALLED_PACKAGE") : [NSString stringWithFormat:UCLocalize("HALFINSTALLED_PACKAGES"), count]) buttons:[NSArray arrayWithObjects: - CYLocalize("FORCIBLY_CLEAR"), - CYLocalize("TEMPORARY_IGNORE"), + UCLocalize("FORCIBLY_CLEAR"), + UCLocalize("TEMPORARY_IGNORE"), nil] defaultButtonIndex:0 delegate:self context:@"fixhalf" ] autorelease]; - [sheet setBodyText:CYLocalize("HALFINSTALLED_PACKAGE_EX")]; + [sheet setBodyText:UCLocalize("HALFINSTALLED_PACKAGE_EX")]; [sheet popupAlertAnimated:YES]; } else if (!Ignored_ && [essential_ count] != 0) { int count = [essential_ count]; UIActionSheet *sheet = [[[UIActionSheet alloc] - initWithTitle:(count == 1 ? CYLocalize("ESSENTIAL_UPGRADE") : [NSString stringWithFormat:CYLocalize("ESSENTIAL_UPGRADES"), count]) + initWithTitle:(count == 1 ? UCLocalize("ESSENTIAL_UPGRADE") : [NSString stringWithFormat:UCLocalize("ESSENTIAL_UPGRADES"), count]) buttons:[NSArray arrayWithObjects: - CYLocalize("UPGRADE_ESSENTIAL"), - CYLocalize("COMPLETE_UPGRADE"), - CYLocalize("TEMPORARY_IGNORE"), + UCLocalize("UPGRADE_ESSENTIAL"), + UCLocalize("COMPLETE_UPGRADE"), + UCLocalize("TEMPORARY_IGNORE"), nil] defaultButtonIndex:0 delegate:self context:@"upgrade" ] autorelease]; - [sheet setBodyText:CYLocalize("ESSENTIAL_UPGRADE_EX")]; + [sheet setBodyText:UCLocalize("ESSENTIAL_UPGRADE_EX")]; [sheet popupAlertAnimated:YES]; } } @@ -6987,7 +7538,7 @@ bool DepSubstrate(const pkgCache::VerIterator &iterator) { static bool loaded(false); UIProgressHUD *hud([self addProgressHUD]); - [hud setText:(loaded ? CYLocalize("RELOADING_DATA") : CYLocalize("LOADING_DATA"))]; + [hud setText:(loaded ? UCLocalize("RELOADING_DATA") : UCLocalize("LOADING_DATA"))]; loaded = true; [database_ yieldToSelector:@selector(reloadData) withObject:nil]; @@ -7113,7 +7664,7 @@ bool DepSubstrate(const pkgCache::VerIterator &iterator) { detachNewThreadSelector:@selector(update_) toTarget:self withObject:nil - title:CYLocalize("UPDATING_SOURCES") + title:UCLocalize("UPDATING_SOURCES") ]; } @@ -7193,7 +7744,7 @@ bool DepSubstrate(const pkgCache::VerIterator &iterator) { - (void) cancel { [self slideUp:[[[UIActionSheet alloc] initWithTitle:nil - buttons:[NSArray arrayWithObjects:CYLocalize("CONTINUE_QUEUING"), CYLocalize("CANCEL_CLEAR"), nil] + buttons:[NSArray arrayWithObjects:UCLocalize("CONTINUE_QUEUING"), UCLocalize("CANCEL_CLEAR"), nil] defaultButtonIndex:1 delegate:self context:@"cancel" @@ -7219,7 +7770,7 @@ bool DepSubstrate(const pkgCache::VerIterator &iterator) { detachNewThreadSelector:@selector(perform) toTarget:database_ withObject:nil - title:CYLocalize("RUNNING") + title:UCLocalize("RUNNING") ]; } @@ -7256,7 +7807,7 @@ bool DepSubstrate(const pkgCache::VerIterator &iterator) { } - (RVPage *) _pageForURL:(NSURL *)url withClass:(Class)_class { - BrowserView *browser = [[[_class alloc] initWithBook:book_] autorelease]; + CydiaBrowserView *browser = [[[_class alloc] initWithBook:book_] autorelease]; [browser loadURL:url]; return browser; } @@ -7299,38 +7850,49 @@ bool DepSubstrate(const pkgCache::VerIterator &iterator) { } - (void) askForSettings { - NSString *parenthetical(CYLocalize("PARENTHETICAL")); + NSString *parenthetical(UCLocalize("PARENTHETICAL")); UIActionSheet *role = [[[UIActionSheet alloc] - initWithTitle:CYLocalize("WHO_ARE_YOU") + initWithTitle:UCLocalize("WHO_ARE_YOU") buttons:[NSArray arrayWithObjects: - [NSString stringWithFormat:parenthetical, CYLocalize("USER"), CYLocalize("USER_EX")], - [NSString stringWithFormat:parenthetical, CYLocalize("HACKER"), CYLocalize("HACKER_EX")], - [NSString stringWithFormat:parenthetical, CYLocalize("DEVELOPER"), CYLocalize("DEVELOPER_EX")], + [NSString stringWithFormat:parenthetical, UCLocalize("USER"), UCLocalize("USER_EX")], + [NSString stringWithFormat:parenthetical, UCLocalize("HACKER"), UCLocalize("HACKER_EX")], + [NSString stringWithFormat:parenthetical, UCLocalize("DEVELOPER"), UCLocalize("DEVELOPER_EX")], nil] defaultButtonIndex:-1 delegate:self context:@"role" ] autorelease]; - [role setBodyText:CYLocalize("ROLE_EX")]; + [role setBodyText:UCLocalize("ROLE_EX")]; [role popupAlertAnimated:YES]; } - (void) setPackageView:(PackageView *)view { - if (package_ == nil) - package_ = [view retain]; + WebThreadLock(); + [view setPackage:nil]; + if ([details_ count] < 3) + [details_ addObject:view]; + WebThreadUnlock(); +} + +- (PackageView *) _packageView { + return [[[PackageView alloc] initWithBook:book_ database:database_] autorelease]; } - (PackageView *) packageView { PackageView *view; + size_t count([details_ count]); - if (package_ == nil) - view = [[[PackageView alloc] initWithBook:book_ database:database_] autorelease]; - else { - return package_; - view = [package_ autorelease]; - package_ = nil; + if (count == 0) { + view = [self _packageView]; + renew: + [details_ addObject:[self _packageView]]; + } else { + view = [[[details_ lastObject] retain] autorelease]; + [details_ removeLastObject]; + if (count == 1) + goto renew; } return view; @@ -7377,7 +7939,7 @@ bool DepSubstrate(const pkgCache::VerIterator &iterator) { @"home-dn.png", kUIButtonBarButtonSelectedInfo, [NSNumber numberWithInt:1], kUIButtonBarButtonTag, self, kUIButtonBarButtonTarget, - CYLocalize("HOME"), kUIButtonBarButtonTitle, + @"Cydia", kUIButtonBarButtonTitle, @"0", kUIButtonBarButtonType, nil], @@ -7387,7 +7949,7 @@ bool DepSubstrate(const pkgCache::VerIterator &iterator) { @"install-dn.png", kUIButtonBarButtonSelectedInfo, [NSNumber numberWithInt:2], kUIButtonBarButtonTag, self, kUIButtonBarButtonTarget, - CYLocalize("SECTIONS"), kUIButtonBarButtonTitle, + UCLocalize("SECTIONS"), kUIButtonBarButtonTitle, @"0", kUIButtonBarButtonType, nil], @@ -7397,7 +7959,7 @@ bool DepSubstrate(const pkgCache::VerIterator &iterator) { @"changes-dn.png", kUIButtonBarButtonSelectedInfo, [NSNumber numberWithInt:3], kUIButtonBarButtonTag, self, kUIButtonBarButtonTarget, - CYLocalize("CHANGES"), kUIButtonBarButtonTitle, + UCLocalize("CHANGES"), kUIButtonBarButtonTitle, @"0", kUIButtonBarButtonType, nil], @@ -7407,7 +7969,7 @@ bool DepSubstrate(const pkgCache::VerIterator &iterator) { @"manage-dn.png", kUIButtonBarButtonSelectedInfo, [NSNumber numberWithInt:4], kUIButtonBarButtonTag, self, kUIButtonBarButtonTarget, - CYLocalize("MANAGE"), kUIButtonBarButtonTitle, + UCLocalize("MANAGE"), kUIButtonBarButtonTitle, @"0", kUIButtonBarButtonType, nil], @@ -7417,7 +7979,7 @@ bool DepSubstrate(const pkgCache::VerIterator &iterator) { @"search-dn.png", kUIButtonBarButtonSelectedInfo, [NSNumber numberWithInt:5], kUIButtonBarButtonTag, self, kUIButtonBarButtonTarget, - CYLocalize("SEARCH"), kUIButtonBarButtonTitle, + UCLocalize("SEARCH"), kUIButtonBarButtonTitle, @"0", kUIButtonBarButtonType, nil], nil]; @@ -7468,7 +8030,9 @@ bool DepSubstrate(const pkgCache::VerIterator &iterator) { withClass:[ManageView class] ] retain]; - [self setPackageView:[self packageView]]; + details_ = [[NSMutableArray alloc] initWithCapacity:4]; + [details_ addObject:[self _packageView]]; + [details_ addObject:[self _packageView]]; PrintTimes(); @@ -7506,7 +8070,7 @@ bool DepSubstrate(const pkgCache::VerIterator &iterator) { [self _reloadData]; else { Queuing_ = true; - [buttonbar_ setBadgeValue:CYLocalize("Q_D") forButton:4]; + [buttonbar_ setBadgeValue:UCLocalize("Q_D") forButton:4]; [book_ reloadData]; } @@ -7565,12 +8129,12 @@ bool DepSubstrate(const pkgCache::VerIterator &iterator) { Changed_ = true; + [sheet dismiss]; + if (reset) [self updateData]; else [self finish]; - - [sheet dismiss]; } else if ([context isEqualToString:@"upgrade"]) { switch (button) { case 1: @@ -7633,20 +8197,6 @@ bool DepSubstrate(const pkgCache::VerIterator &iterator) { [window_ setUserInteractionEnabled:YES]; } -- (void) openMailToURL:(NSURL *)url { -// XXX: this makes me sad -#if 0 - [[[MailToView alloc] initWithView:underlay_ delegate:self url:url] autorelease]; -#else - [UIApp openURL:url];// asPanel:YES]; -#endif -} - -- (void) clearFirstResponder { - if (id responder = [window_ firstResponder]) - [responder resignFirstResponder]; -} - - (RVPage *) pageForPackage:(NSString *)name { if (Package *package = [database_ packageWithName:name]) { PackageView *view([self packageView]); @@ -7654,14 +8204,14 @@ bool DepSubstrate(const pkgCache::VerIterator &iterator) { return view; } else { UIActionSheet *sheet = [[[UIActionSheet alloc] - initWithTitle:CYLocalize("CANNOT_LOCATE_PACKAGE") - buttons:[NSArray arrayWithObjects:CYLocalize("CLOSE"), nil] + initWithTitle:UCLocalize("CANNOT_LOCATE_PACKAGE") + buttons:[NSArray arrayWithObjects:UCLocalize("CLOSE"), nil] defaultButtonIndex:0 delegate:self context:@"missing" ] autorelease]; - [sheet setBodyText:[NSString stringWithFormat:CYLocalize("PACKAGE_CANNOT_BE_FOUND"), name]]; + [sheet setBodyText:[NSString stringWithFormat:UCLocalize("PACKAGE_CANNOT_BE_FOUND"), name]]; [sheet popupAlertAnimated:YES]; return nil; @@ -7672,6 +8222,10 @@ bool DepSubstrate(const pkgCache::VerIterator &iterator) { if (tag != NULL) tag = 0; + NSString *href([url absoluteString]); + if ([href hasPrefix:@"apptapp://package/"]) + return [self pageForPackage:[href substringFromIndex:18]]; + NSString *scheme([[url scheme] lowercaseString]); if (![scheme isEqualToString:@"cydia"]) return nil; @@ -7685,13 +8239,13 @@ bool DepSubstrate(const pkgCache::VerIterator &iterator) { if ([path isEqualToString:@"/add-source"]) return [[[AddSourceView alloc] initWithBook:book_ database:database_] autorelease]; else if ([path isEqualToString:@"/storage"]) - return [self _pageForURL:[NSURL fileURLWithPath:[[NSBundle mainBundle] pathForResource:@"storage" ofType:@"html"]] withClass:[BrowserView class]]; + return [self _pageForURL:[NSURL fileURLWithPath:[[NSBundle mainBundle] pathForResource:@"storage" ofType:@"html"]] withClass:[CydiaBrowserView class]]; else if ([path isEqualToString:@"/sources"]) return [[[SourceTable alloc] initWithBook:book_ database:database_] autorelease]; else if ([path isEqualToString:@"/packages"]) return [[[InstalledView alloc] initWithBook:book_ database:database_] autorelease]; else if ([path hasPrefix:@"/url/"]) - return [self _pageForURL:[NSURL URLWithString:[path substringFromIndex:5]] withClass:[BrowserView class]]; + return [self _pageForURL:[NSURL URLWithString:[path substringFromIndex:5]] withClass:[CydiaBrowserView class]]; else if ([path hasPrefix:@"/launch/"]) [self launchApplicationWithIdentifier:[path substringFromIndex:8] suspended:NO]; else if ([path hasPrefix:@"/package-settings/"]) @@ -7731,9 +8285,6 @@ bool DepSubstrate(const pkgCache::VerIterator &iterator) { Font18Bold_ = [[UIFont boldSystemFontOfSize:18] retain]; Font22Bold_ = [[UIFont boldSystemFontOfSize:22] retain]; - _assert(pkgInitConfig(*_config)); - _assert(pkgInitSystem(*_config, _system)); - tag_ = 1; essential_ = [[NSMutableArray alloc] initWithCapacity:4]; @@ -7761,8 +8312,10 @@ bool DepSubstrate(const pkgCache::VerIterator &iterator) { if ( readlink("/Applications", NULL, 0) == -1 && errno == EINVAL || readlink("/Library/Ringtones", NULL, 0) == -1 && errno == EINVAL || - readlink("/Library/Wallpaper", NULL, 0) == -1 && errno == EINVAL || + readlink("/Library/Wallpaper", NULL, 0) == -1 && errno == EINVAL /*|| + readlink("/usr/bin", NULL, 0) == -1 && errno == EINVAL*/ || readlink("/usr/include", NULL, 0) == -1 && errno == EINVAL || + readlink("/usr/lib/pam", NULL, 0) == -1 && errno == EINVAL || readlink("/usr/libexec", NULL, 0) == -1 && errno == EINVAL || readlink("/usr/share", NULL, 0) == -1 && errno == EINVAL /*|| readlink("/var/lib", NULL, 0) == -1 && errno == EINVAL*/ @@ -7881,16 +8434,37 @@ void $UIWebDocumentView$_setUIKitDelegate$(UIWebDocumentView *self, SEL sel, id int main(int argc, char *argv[]) { _pooled _trace(); - Locale_ = CFLocaleCopyCurrent(); + PackageName = reinterpret_cast(method_getImplementation(class_getInstanceMethod([Package class], @selector(cyname)))); + + /* Library Hacks {{{ */ + class_addMethod(objc_getClass("DOMNodeList"), @selector(countByEnumeratingWithState:objects:count:), (IMP) &DOMNodeList$countByEnumeratingWithState$objects$count$, "I20@0:4^{NSFastEnumerationState}8^@12I16"); - CFStringRef locale(CFLocaleGetIdentifier(Locale_)); - setenv("LANG", [(NSString *) locale UTF8String], true); + $WebDefaultUIKitDelegate = objc_getClass("WebDefaultUIKitDelegate"); + Method UIWebDocumentView$_setUIKitDelegate$(class_getInstanceMethod([WebView class], @selector(_setUIKitDelegate:))); + if (UIWebDocumentView$_setUIKitDelegate$ != NULL) { + _UIWebDocumentView$_setUIKitDelegate$ = reinterpret_cast(method_getImplementation(UIWebDocumentView$_setUIKitDelegate$)); + method_setImplementation(UIWebDocumentView$_setUIKitDelegate$, reinterpret_cast(&$UIWebDocumentView$_setUIKitDelegate$)); + } + /* }}} */ + /* Set Locale {{{ */ + Locale_ = CFLocaleCopyCurrent(); + Languages_ = [NSLocale preferredLanguages]; + //CFStringRef locale(CFLocaleGetIdentifier(Locale_)); + //NSLog(@"%@", [Languages_ description]); + const char *lang; + if (Languages_ == nil || [Languages_ count] == 0) + lang = NULL; + else + lang = [[Languages_ objectAtIndex:0] UTF8String]; + setenv("LANG", lang, true); + //std::setlocale(LC_ALL, lang); + NSLog(@"Setting Language: %s", lang); + /* }}} */ // XXX: apr_app_initialize? apr_initialize(); - class_addMethod(objc_getClass("DOMNodeList"), @selector(countByEnumeratingWithState:objects:count:), (IMP) &DOMNodeList$countByEnumeratingWithState$objects$count$, "I20@0:4^{NSFastEnumerationState}8^@12I16"); - + /* Parse Arguments {{{ */ bool substrate(false); if (argc != 0) { @@ -7914,9 +8488,7 @@ int main(int argc, char *argv[]) { _pooled else fprintf(stderr, "unknown argument: %s\n", args[argi]); } - - App_ = [[NSBundle mainBundle] bundlePath]; - Home_ = NSHomeDirectory(); + /* }}} */ { NSString *plist = [Home_ stringByAppendingString:@"/Library/Preferences/com.apple.preferences.sounds.plist"]; @@ -7925,23 +8497,12 @@ int main(int argc, char *argv[]) { _pooled Sounds_Keyboard_ = [keyboard boolValue]; } + App_ = [[NSBundle mainBundle] bundlePath]; + Home_ = NSHomeDirectory(); + setuid(0); setgid(0); -#if 1 /* XXX: this costs 1.4s of startup performance */ - if (unlink("/var/cache/apt/pkgcache.bin") == -1) - _assert(errno == ENOENT); - if (unlink("/var/cache/apt/srcpkgcache.bin") == -1) - _assert(errno == ENOENT); -#endif - - $WebDefaultUIKitDelegate = objc_getClass("WebDefaultUIKitDelegate"); - Method UIWebDocumentView$_setUIKitDelegate$(class_getInstanceMethod([WebView class], @selector(_setUIKitDelegate:))); - if (UIWebDocumentView$_setUIKitDelegate$ != NULL) { - _UIWebDocumentView$_setUIKitDelegate$ = reinterpret_cast(method_getImplementation(UIWebDocumentView$_setUIKitDelegate$)); - method_setImplementation(UIWebDocumentView$_setUIKitDelegate$, reinterpret_cast(&$UIWebDocumentView$_setUIKitDelegate$)); - } - /*Method alloc = class_getClassMethod([NSObject class], @selector(alloc)); alloc_ = alloc->method_imp; alloc->method_imp = (IMP) &Alloc_;*/ @@ -7981,6 +8542,7 @@ int main(int argc, char *argv[]) { _pooled /*AddPreferences(@"/Applications/Preferences.app/Settings-iPhone.plist"); AddPreferences(@"/Applications/Preferences.app/Settings-iPod.plist");*/ + /* Load Database {{{ */ _trace(); Metadata_ = [[[NSMutableDictionary alloc] initWithContentsOfFile:@"/var/lib/cydia/metadata.plist"] autorelease]; _trace(); @@ -8014,6 +8576,7 @@ int main(int argc, char *argv[]) { _pooled Sources_ = [[[NSMutableDictionary alloc] initWithCapacity:0] autorelease]; [Metadata_ setObject:Sources_ forKey:@"Sources"]; } + /* }}} */ #if RecycleWebViews Documents_ = [[[NSMutableArray alloc] initWithCapacity:4] autorelease]; @@ -8037,6 +8600,22 @@ int main(int argc, char *argv[]) { _pooled error:NULL ]); + if (access("/tmp/cydia.chk", F_OK) == 0) { + if (unlink("/var/cache/apt/pkgcache.bin") == -1) + _assert(errno == ENOENT); + if (unlink("/var/cache/apt/srcpkgcache.bin") == -1) + _assert(errno == ENOENT); + } + + _assert(pkgInitConfig(*_config)); + _assert(pkgInitSystem(*_config, _system)); + + if (lang != NULL) + _config->Set("APT::Acquire::Translation", lang); + _config->Set("Acquire::http::Timeout", 15); + _config->Set("Acquire::http::MaxParallel", 4); + + /* Color Choices {{{ */ space_ = CGColorSpaceCreateDeviceRGB(); Blue_.Set(space_, 0.2, 0.2, 1.0, 1.0); @@ -8058,14 +8637,17 @@ int main(int argc, char *argv[]) { _pooled //.93 InstallingColor_ = [UIColor colorWithRed:0.88f green:1.00f blue:0.88f alpha:1.00f]; RemovingColor_ = [UIColor colorWithRed:1.00f green:0.88f blue:0.88f alpha:1.00f]; + /* }}}*/ Finishes_ = [NSArray arrayWithObjects:@"return", @"reopen", @"restart", @"reload", @"reboot", nil]; + /* UIKit Configuration {{{ */ void (*$GSFontSetUseLegacyFontMetrics)(BOOL)(reinterpret_cast(dlsym(RTLD_DEFAULT, "GSFontSetUseLegacyFontMetrics"))); if ($GSFontSetUseLegacyFontMetrics != NULL) $GSFontSetUseLegacyFontMetrics(YES); UIKeyboardDisableAutomaticAppearance(); + /* }}} */ _trace(); int value = UIApplicationMain(argc, argv, @"Cydia", @"Cydia");