X-Git-Url: https://git.saurik.com/cydia.git/blobdiff_plain/1ff58dbb314cd849f0e018f5b895f1c91596aba9..0fc560b63efa94e4aef1d48fd6c2d07b6f615f3f:/Cydia.mm diff --git a/Cydia.mm b/Cydia.mm index cf27f1ee..e069dd7f 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) */ /* @@ -87,6 +87,7 @@ #include #include #include +#include #include @@ -215,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) { @@ -226,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; } }; /* }}} */ @@ -396,11 +408,12 @@ 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 (0 && !ForRelease) +#define LogBrowser (1 && !ForRelease) #define TrackResize (0 && !ForRelease) #define ManualRefresh (1 && !ForRelease) #define ShowInternals (0 && !ForRelease) @@ -567,8 +580,6 @@ CFIndex CFBSearch_(const void *element, CFIndex elementSize, const void *list, C return (ptr - (const char *)list) / elementSize; } -#define HistogramInsertionSort 0 - void CFArrayInsertionSortValues(CFMutableArrayRef array, CFRange range, CFComparatorFunction comparator, void *context) { if (range.length == 0) return; @@ -758,8 +769,10 @@ class CYString { CFStringRef cache_; _finline void clear_() { - if (cache_ != nil) + if (cache_ != NULL) { CFRelease(cache_); + cache_ = NULL; + } } public: @@ -783,7 +796,7 @@ class CYString { _finline CYString() : data_(0), size_(0), - cache_(nil) + cache_(NULL) { } @@ -1038,7 +1051,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_; @@ -1133,18 +1145,24 @@ NSString *SizeString(double size) { return [NSString stringWithFormat:@"%s%.1f %s", (negative ? "-" : ""), size, powers_[power]]; } -NSString *StripVersion(const char *version) { +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 [NSString stringWithUTF8String:version]; + return version; } -NSString *StripVersion(NSString *version) { - NSRange colon = [version rangeOfString:@":"]; - if (colon.location != NSNotFound) - version = [version substringFromIndex:(colon.location + 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) { @@ -1348,6 +1366,8 @@ class Progress : /* }}} */ /* Database Interface {{{ */ +typedef std::map< unsigned long, _H > SourceMap; + @interface Database : NSObject { NSZone *zone_; apr_pool_t *pool_; @@ -1363,7 +1383,7 @@ class Progress : SPtr manager_; pkgSourceList *list_; - NSMutableDictionary *sources_; + SourceMap sources_; NSMutableArray *packages_; _transient NSObject *delegate_; @@ -1402,7 +1422,7 @@ class Progress : - (void) upgrade; - (void) update; -- (void) updateWithStatus:(Status &)status; +- (NSString *) updateWithStatus:(Status &)status; - (void) setDelegate:(id)delegate; - (Source *) getSource:(pkgCache::PkgFileIterator)file; @@ -1411,26 +1431,30 @@ class Progress : /* Source Class {{{ */ @interface Source : NSObject { - NSString *description_; - NSString *label_; - NSString *origin_; - NSString *support_; + CYString depiction_; + CYString description_; + CYString label_; + CYString origin_; + CYString support_; - NSString *uri_; - NSString *distribution_; - NSString *type_; - NSString *version_; + CYString uri_; + CYString distribution_; + CYString type_; + CYString version_; - NSString *defaultIcon_; + NSString *host_; + + 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; @@ -1454,23 +1478,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(); - _clear(description_) - _clear(label_) - _clear(origin_) - _clear(support_) - _clear(version_) - _clear(defaultIcon_) - _clear(record_) + description_.clear(); + label_.clear(); + origin_.clear(); + depiction_.clear(); + support_.clear(); + version_.clear(); + defaultIcon_.clear(); + + if (record_ != nil) { + [record_ release]; + record_ = nil; + } + + if (host_ != nil) { + [host_ release]; + host_ = nil; + } } - (void) dealloc { @@ -1490,52 +1519,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; } @@ -1562,8 +1599,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 { @@ -1587,15 +1628,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 { @@ -1603,7 +1644,7 @@ class Progress : } - (NSString *) label { - return label_ == nil ? [self host] : label_; + return label_.empty() ? host_ : label_; } - (NSString *) origin { @@ -1658,6 +1699,7 @@ class Progress : /* Package Class {{{ */ @interface Package : NSObject { unsigned era_; + apr_pool_t *pool_; pkgCache::VerIterator version_; pkgCache::PkgIterator iterator_; @@ -1666,6 +1708,7 @@ class Progress : Source *source_; bool cached_; + bool parsed_; CYString section_; NSString *section$_; @@ -1673,7 +1716,7 @@ class Progress : bool visible_; NSString *latest_; - NSString *installed_; + CYString installed_; CYString id_; CYString name_; @@ -1689,7 +1732,7 @@ class Progress : Address *author$_; CYString support_; - NSArray *tags_; + NSMutableArray *tags_; NSString *role_; NSArray *relationships_; @@ -1704,6 +1747,7 @@ class Progress : + (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; @@ -1726,6 +1770,7 @@ class Progress : - (NSString *) latest; - (NSString *) installed; +- (BOOL) uninstalled; - (BOOL) valid; - (BOOL) upgradableAndEssential:(BOOL)essential; @@ -1917,8 +1962,6 @@ struct PackageNameOrdering : if (latest_ != nil) [latest_ release]; - if (installed_ != nil) - [installed_ release]; if (sponsor$_ != nil) [sponsor$_ release]; @@ -1960,100 +2003,130 @@ struct PackageNameOrdering : return ![[self _attributeKeys] containsObject:[NSString stringWithUTF8String:name]] && [super isKeyExcludedFromWebScript:name]; } +- (void) parse { + if (parsed_) + return; + parsed_ = true; + if (file_.end()) + return; + + _profile(Package$parse) + pkgRecords::Parser *parser; + + _profile(Package$parse$Lookup) + parser = &[database_ records]->Lookup(file_); + _end + + CYString website; + + _profile(Package$parse$Find) + struct { + const char *name_; + CYString *value_; + } names[] = { + {"icon", &icon_}, + {"depiction", &depiction_}, + {"homepage", &homepage_}, + {"website", &website}, + {"support", &support_}, + {"sponsor", &sponsor_}, + {"author", &author_}, + }; + + for (size_t i(0); i != sizeof(names) / sizeof(names[0]); ++i) { + const char *start, *end; + + if (parser->Find(names[i].name_, start, end)) { + CYString &value(*names[i].value_); + _profile(Package$parse$Value) + value.set(pool_, start, end - start); + _end + } + } + _end + + _profile(Package$parse$Tagline) + const char *start, *end; + if (parser->ShortDesc(start, end)) { + const char *stop(reinterpret_cast(memchr(start, '\n', end - start))); + if (stop == NULL) + stop = end; + while (stop != start && stop[-1] == '\r') + --stop; + tagline_.set(pool_, start, stop - start); + } + _end + + _profile(Package$parse$Retain) + if (!homepage_.empty()) + homepage_ = website; + if (homepage_ == depiction_) + homepage_.clear(); + _end + _end +} + - (Package *) initWithVersion:(pkgCache::VerIterator)version withZone:(NSZone *)zone inPool:(apr_pool_t *)pool database:(Database *)database { if ((self = [super init]) != nil) { _profile(Package$initWithVersion) @synchronized (database) { era_ = [database era]; + pool_ = pool; version_ = version; iterator_ = version.ParentPkg(); database_ = database; _profile(Package$initWithVersion$Latest) - latest_ = [StripVersion(version_.VerStr()) retain]; + latest_ = (NSString *) StripVersion(version_.VerStr()); _end - pkgCache::VerIterator current(iterator_.CurrentVer()); - if (!current.end()) - installed_ = [StripVersion(current.VerStr()) retain]; + 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 { - pkgCache &cache([database_ cache]); - file_ = pkgCache::VerFileIterator(cache, cache.VerFileP); - } + if (!version_.end()) + file_ = version_.FileList(); + else { + pkgCache &cache([database_ cache]); + file_ = pkgCache::VerFileIterator(cache, cache.VerFileP); + } + _end _profile(Package$initWithVersion$Name) - id_.set(pool, iterator_.Name()); + id_.set(pool_, iterator_.Name()); + name_.set(pool, iterator_.Display()); _end - if (!file_.end()) - source_ = [database_ getSource:file_.File()]; - if (source_ != nil) - [source_ retain]; - cached_ = true; - - _profile(Package$initWithVersion$Parse) - pkgRecords::Parser *parser; - - _profile(Package$initWithVersion$Parse$Lookup) - parser = &[database_ records]->Lookup(file_); - _end - - CYString website; - CYString tag; - - _profile(Package$initWithVersion$Parse$Find) - 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}, - }; - - 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$initWithVersion$Parse$Value) - value.set(pool, start, end - start); - _end - } - } - _end - - _profile(Package$initWithVersion$Parse$Tagline) - tagline_.set(pool, parser->ShortDesc()); - _end - - _profile(Package$initWithVersion$Parse$Retain) - if (!homepage_.empty()) - homepage_ = website; - if (homepage_ == depiction_) - homepage_.clear(); - if (!tag.empty()) - tags_ = [[tag componentsSeparatedByString:@", "] retain]; - _end + if (!file_.end()) { + _profile(Package$initWithVersion$Source) + source_ = [database_ getSource:file_.File()]; + if (source_ != nil) + [source_ retain]; + cached_ = true; _end + } + + visible_ = true; _profile(Package$initWithVersion$Tags) - if (tags_ != nil) - for (NSString *tag in tags_) - if ([tag hasPrefix:@"role::"]) { - role_ = [[tag substringFromIndex:6] retain]; - break; - } + pkgCache::TagIterator tag(iterator_.TagList()); + if (!tag.end()) { + tags_ = [[NSMutableArray alloc] initWithCapacity:8]; + do { + const char *name(tag.Name()); + [tags_ addObject:(NSString *)CFCString(name)]; + if (role_ == nil && strncmp(name, "role::", 6) == 0 /*&& strcmp(name, "role::leaper") != 0*/) + role_ = (NSString *) CFCString(name + 6); + if (visible_ && strncmp(name, "require::", 9) == 0 && ( + true + )) + visible_ = false; + ++tag; + } while (!tag.end()); + } _end bool changed(false); @@ -2063,7 +2136,7 @@ struct PackageNameOrdering : metadata_ = [Packages_ objectForKey:key]; if (metadata_ == nil) { - firstSeen_ = [now_ retain]; + firstSeen_ = now_; metadata_ = [[NSMutableDictionary dictionaryWithObjectsAndKeys: firstSeen_, @"FirstSeen", @@ -2089,12 +2162,13 @@ struct PackageNameOrdering : if (version == nil) { [metadata_ setObject:latest_ forKey:@"LastVersion"]; changed = true; - } else if (![version isEqualToString:latest_]) { + } else { + if (![version isEqualToString:latest_]) { [metadata_ setObject:latest_ forKey:@"LastVersion"]; lastSeen_ = now_; [metadata_ setObject:lastSeen_ forKey:@"LastSeen"]; changed = true; - } + } } } metadata_ = [metadata_ retain]; @@ -2106,11 +2180,11 @@ struct PackageNameOrdering : _end _profile(Package$initWithVersion$Section) - section_.set(pool, iterator_.Section()); + section_.set(pool_, iterator_.Section()); _end essential_ = ((iterator_->Flags & pkgCache::Flag::Essential) == 0 ? NO : YES) || [self hasTag:@"cydia::essential"]; - visible_ = [self hasSupportingRole] && [self unfiltered]; + visible_ = visible_ && [self hasSupportingRole] && [self unfiltered]; } _end } return self; } @@ -2163,7 +2237,7 @@ struct PackageNameOrdering : } - (NSString *) longSection { - return LocalizeSection(section_); + return LocalizeSection([self section]); } - (NSString *) shortSection { @@ -2261,6 +2335,10 @@ struct PackageNameOrdering : return installed_; } +- (BOOL) uninstalled { + return installed_.empty(); +} + - (BOOL) valid { return !version_.end(); } @@ -2376,7 +2454,7 @@ struct PackageNameOrdering : } - (NSString *) depiction { - return depiction_; + return !depiction_.empty() ? depiction_ : [[self source] depictionForPackage:id_]; } - (Address *) sponsor { @@ -2665,7 +2743,7 @@ struct PackageNameOrdering : } - (bool) isInstalledAndVisible:(NSNumber *)number { - return (![number boolValue] || [self visible]) && [self installed] != nil; + return (![number boolValue] || [self visible]) && ![self uninstalled]; } - (bool) isVisiblyUninstalledInSection:(NSString *)name { @@ -2673,7 +2751,7 @@ struct PackageNameOrdering : return [self visible] && - [self installed] == nil && ( + [self uninstalled] && ( name == nil || section == nil && [name length] == 0 || [name isEqualToString:section] @@ -2931,7 +3009,6 @@ static NSArray *Finishes_; zone_ = NSCreateZone(1024 * 1024, 256 * 1024, NO); apr_pool_create(&pool_, NULL); - sources_ = [[NSMutableDictionary dictionaryWithCapacity:16] retain]; packages_ = [[NSMutableArray alloc] init]; int fds[2]; @@ -3004,7 +3081,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 { @@ -3076,6 +3156,9 @@ static NSArray *Finishes_; ++era_; } + [packages_ removeAllObjects]; + sources_.clear(); + _error->Discard(); delete list_; @@ -3092,6 +3175,11 @@ static NSArray *Finishes_; delete policy_; policy_ = NULL; + if (now_ != nil) { + [now_ release]; + now_ = nil; + } + cache_.Close(); apr_pool_clear(pool_); @@ -3145,23 +3233,18 @@ static NSArray *Finishes_; } _trace(); - { - std::string lists(_config->FindDir("Dir::State::lists")); - - [sources_ removeAllObjects]; - 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) - if (debPackagesIndex *packages = dynamic_cast(*index)) - [sources_ - setObject:[[[Source alloc] initWithMetaIndex:*source] autorelease] - forKey:[NSString stringWithFormat:@"%s%s", - lists.c_str(), - URItoFileName(packages->IndexURI("Packages")).c_str() - ] - ]; - } + + 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) + // 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]; + } } + _trace(); { @@ -3170,8 +3253,6 @@ static NSArray *Finishes_; [packages_ release]; packages_ = nil;*/ - [packages_ removeAllObjects]; - _trace(); for (pkgCache::PkgIterator iterator = cache_->PkgBegin(); !iterator.end(); ++iterator) @@ -3276,6 +3357,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; @@ -3333,13 +3416,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)); @@ -3360,6 +3450,8 @@ static NSArray *Finishes_; [Metadata_ setObject:[NSDate date] forKey:@"LastUpdate"]; Changed_ = true; } + + return nil; } - (void) setDelegate:(id)delegate { @@ -3369,10 +3461,8 @@ static NSArray *Finishes_; } - (Source *) getSource:(pkgCache::PkgFileIterator)file { - if (const char *name = file.FileName()) - if (Source *source = [sources_ objectForKey:[NSString stringWithUTF8String:name]]) - return source; - return nil; + SourceMap::const_iterator i(sources_.find(file->ID)); + return i == sources_.end() ? nil : i->second; } @end @@ -3929,92 +4019,52 @@ 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:CYLocalize("ERROR") + buttons:[NSArray arrayWithObjects:CYLocalize("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_) { @@ -4075,6 +4125,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:CYLocalize("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]; @@ -4098,27 +4213,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_]; @@ -4324,6 +4439,7 @@ bool DepSubstrate(const pkgCache::VerIterator &iterator) { - (void) setPackage:(Package *)package { [self clearPackage]; + [package parse]; Source *source = [package source]; @@ -4454,14 +4570,7 @@ bool DepSubstrate(const pkgCache::VerIterator &iterator) { } + (int) heightForPackage:(Package *)package { - NSString *tagline([package shortDescription]); - 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 @@ -4545,7 +4654,7 @@ bool DepSubstrate(const pkgCache::VerIterator &iterator) { section_ = [section localized]; if (section_ != nil) section_ = [section_ retain]; - name_ = [(section_ == nil ? CYLocalize("NO_SECTION") : section_) retain]; + name_ = [(section_ == nil || [section_ length] == 0 ? CYLocalize("NO_SECTION") : section_) retain]; count_ = [[NSString stringWithFormat:@"%d", [section count]] retain]; if (editing_) @@ -4846,6 +4955,8 @@ bool DepSubstrate(const pkgCache::VerIterator &iterator) { [buttons_ removeAllObjects]; if (package != nil) { + [package parse]; + package_ = [package retain]; name_ = [[package id] retain]; commercial_ = [package isCommercial]; @@ -4855,11 +4966,11 @@ bool DepSubstrate(const pkgCache::VerIterator &iterator) { if ([package_ source] == nil); else if ([package_ upgradableAndEssential:NO]) [buttons_ addObject:CYLocalize("UPGRADE")]; - else if ([package_ installed] == nil) + else if ([package_ uninstalled]) [buttons_ addObject:CYLocalize("INSTALL")]; else [buttons_ addObject:CYLocalize("REINSTALL")]; - if ([package_ installed] != nil) + if (![package_ uninstalled]) [buttons_ addObject:CYLocalize("REMOVE")]; if (special_ != NULL) { @@ -5902,7 +6013,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]; @@ -5924,7 +6042,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:CYLocalize("COLON_DELIMITED"), CYLocalize("ERROR"), CYLocalize("REFRESH")] + buttons:[NSArray arrayWithObjects: + CYLocalize("OK"), + nil] + defaultButtonIndex:0 + delegate:self + context:@"refresh" + ] autorelease]; + + [sheet setBodyText:error]; + [sheet popupAlertAnimated:YES]; + + [self reloadButtons]; + } } - (id) initWithFrame:(CGRect)frame database:(Database *)database { @@ -6013,11 +6148,11 @@ 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 ]; } @@ -6057,10 +6192,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]; } @@ -6336,7 +6467,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 @@ -6357,7 +6488,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 @@ -6548,7 +6679,7 @@ 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]; @@ -7167,7 +7298,7 @@ bool DepSubstrate(const pkgCache::VerIterator &iterator) { ManageView *manage_; SearchView *search_; - PackageView *package_; + NSMutableArray *details_; } @end @@ -7547,19 +7678,30 @@ bool DepSubstrate(const pkgCache::VerIterator &iterator) { } - (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; @@ -7697,7 +7839,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(); @@ -7794,12 +7938,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: @@ -7987,8 +8131,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*/