X-Git-Url: https://git.saurik.com/cydia.git/blobdiff_plain/76933519310a2b5ee1d6020b27d173316498adb6..e124f5222a28c2a3e2081155cbaa02017b763b93:/Cydia.mm diff --git a/Cydia.mm b/Cydia.mm index 7e4f33fe..d898ef3a 100644 --- a/Cydia.mm +++ b/Cydia.mm @@ -232,7 +232,8 @@ void NSLogRect(const char *fix, const CGRect &rect) { } @interface NSObject (Cydia) -- (void) yieldToSelector:(SEL)selector withObject:(id)object; +- (id) yieldToSelector:(SEL)selector withObject:(id)object; +- (id) yieldToSelector:(SEL)selector; @end @implementation NSObject (Cydia) @@ -240,12 +241,17 @@ void NSLogRect(const char *fix, const CGRect &rect) { - (void) doNothing { } -- (void) _yieldToContext:(NSArray *)context { _pooled +- (void) _yieldToContext:(NSMutableArray *)context { _pooled SEL selector(reinterpret_cast([[context objectAtIndex:0] pointerValue])); id object([[context objectAtIndex:1] nonretainedObjectValue]); volatile bool &stopped(*reinterpret_cast([[context objectAtIndex:2] pointerValue])); - [self performSelector:selector withObject:object]; + /* XXX: deal with exceptions */ + id value([self performSelector:selector withObject:object]); + + [context removeAllObjects]; + if (value != nil) + [context addObject:value]; stopped = true; @@ -256,13 +262,12 @@ void NSLogRect(const char *fix, const CGRect &rect) { ]; } -- (void) yieldToSelector:(SEL)selector withObject:(id)object { - [self performSelector:selector withObject:object]; - return; +- (id) yieldToSelector:(SEL)selector withObject:(id)object { + /*return [self performSelector:selector withObject:object];*/ volatile bool stopped(false); - NSArray *context([NSArray arrayWithObjects: + NSMutableArray *context([NSMutableArray arrayWithObjects: [NSValue valueWithPointer:selector], [NSValue valueWithNonretainedObject:object], [NSValue valueWithPointer:const_cast(&stopped)], @@ -280,6 +285,12 @@ void NSLogRect(const char *fix, const CGRect &rect) { NSDate *future([NSDate distantFuture]); while (!stopped && [loop runMode:NSDefaultRunLoopMode beforeDate:future]); + + return [context count] == 0 ? nil : [context objectAtIndex:0]; +} + +- (id) yieldToSelector:(SEL)selector { + return [self yieldToSelector:selector withObject:nil]; } @end @@ -370,9 +381,9 @@ extern NSString * const kCAFilterNearest; #define lprintf(args...) fprintf(stderr, args) -#define ForRelease 0 +#define ForRelease 1 #define ForSaurik (1 && !ForRelease) -#define ShowInternals (0 && !ForRelease) +#define ShowInternals (1 && !ForRelease) #define IgnoreInstall (0 && !ForRelease) #define RecycleWebViews 0 #define AlwaysReload (1 && !ForRelease) @@ -381,9 +392,10 @@ extern NSString * const kCAFilterNearest; #undef _trace #define _trace(args...) #undef _profile -#define _profile(name) +#define _profile(name) { #undef _end -#define _end +#define _end } +#define PrintTimes() do {} while (false) #endif /* Radix Sort {{{ */ @@ -524,6 +536,8 @@ NSUInteger DOMNodeList$countByEnumeratingWithState$objects$count$(DOMNodeList *s + (NSString *) stringWithUTF8BytesNoCopy:(const char *)bytes length:(int)length; + (NSString *) stringWithUTF8Bytes:(const char *)bytes length:(int)length; - (NSComparisonResult) compareByPath:(NSString *)other; +- (NSString *) stringByCachingURLWithCurrentCDN; +- (NSString *) stringByAddingPercentEscapesIncludingReserved; @end @implementation NSString (Cydia) @@ -566,6 +580,26 @@ NSUInteger DOMNodeList$countByEnumeratingWithState$objects$count$(DOMNodeList *s return result == NSOrderedSame ? value : result; } +- (NSString *) stringByCachingURLWithCurrentCDN { + return [self + stringByReplacingOccurrencesOfString:@"://" + withString:@"://ne.edgecastcdn.net/8003A4/" + options:0 + /* XXX: this is somewhat inaccurate */ + range:NSMakeRange(0, 10) + ]; +} + +- (NSString *) stringByAddingPercentEscapesIncludingReserved { + return [(id)CFURLCreateStringByAddingPercentEscapes( + kCFAllocatorDefault, + (CFStringRef) self, + NULL, + CFSTR(";/?:@&=+$,"), + kCFStringEncodingUTF8 + ) autorelease]; +} + @end /* Perl-Compatible RegEx {{{ */ @@ -752,6 +786,8 @@ static UIFont *Font22Bold_; static const char *Machine_ = NULL; static const NSString *UniqueID_ = nil; static const NSString *Build_ = nil; +static const NSString *Product_ = nil; +static const NSString *Safari_ = nil; CFLocaleRef Locale_; CGColorSpaceRef space_; @@ -997,6 +1033,8 @@ class Progress : /* Database Interface {{{ */ @interface Database : NSObject { + unsigned era_; + pkgCacheFile cache_; pkgDepCache::Policy *policy_; pkgRecords *records_; @@ -1019,6 +1057,7 @@ class Progress : } + (Database *) sharedInstance; +- (unsigned) era; - (void) _readCydia:(NSNumber *)fd; - (void) _readStatus:(NSNumber *)fd; @@ -1289,6 +1328,8 @@ class Progress : /* }}} */ /* Package Class {{{ */ @interface Package : NSObject { + unsigned era_; + pkgCache::PkgIterator iterator_; _transient Database *database_; pkgCache::VerIterator version_; @@ -1298,6 +1339,7 @@ class Progress : bool cached_; NSString *section_; + bool essential_; NSString *latest_; NSString *installed_; @@ -1395,7 +1437,6 @@ class Progress : - (void) dealloc { if (source_ != nil) [source_ release]; - if (section_ != nil) [section_ release]; @@ -1441,7 +1482,11 @@ class Progress : } - (Package *) initWithIterator:(pkgCache::PkgIterator)iterator database:(Database *)database { - if ((self = [super init]) != nil) { _profile(Package$initWithIterator) + if ((self = [super init]) != nil) { + _profile(Package$initWithIterator) + @synchronized (database) { + era_ = [database era]; + iterator_ = iterator; database_ = database; @@ -1628,7 +1673,25 @@ class Progress : Changed_ = true; } _end - _end } return self; + + const char *section(iterator_.Section()); + if (section == NULL) + section_ = nil; + else { + NSString *name([[NSString stringWithUTF8String:section] stringByReplacingCharacter:' ' withCharacter:'_']); + + lookup: + if (NSDictionary *value = [SectionMap_ objectForKey:name]) + if (NSString *rename = [value objectForKey:@"Rename"]) { + name = rename; + goto lookup; + } + + section_ = [[name stringByReplacingCharacter:'_' withCharacter:' '] retain]; + } + + essential_ = (iterator_->Flags & pkgCache::Flag::Essential) == 0 ? NO : YES; + } _end } return self; } + (Package *) packageWithIterator:(pkgCache::PkgIterator)iterator database:(Database *)database { @@ -1643,23 +1706,6 @@ class Progress : } - (NSString *) section { - if (section_ != nil) - return section_; - - const char *section = iterator_.Section(); - if (section == NULL) - return nil; - - NSString *name = [[NSString stringWithUTF8String:section] stringByReplacingCharacter:' ' withCharacter:'_']; - - lookup: - if (NSDictionary *value = [SectionMap_ objectForKey:name]) - if (NSString *rename = [value objectForKey:@"Rename"]) { - name = rename; - goto lookup; - } - - section_ = [[name stringByReplacingCharacter:'_' withCharacter:' '] retain]; return section_; } @@ -1723,7 +1769,7 @@ class Progress : unichar character([name characterAtIndex:0]); if (!isalpha(character)) return '#'; - return character; + return toupper(character); _end } @@ -1779,7 +1825,7 @@ class Progress : } - (BOOL) essential { - return (iterator_->Flags & pkgCache::Flag::Essential) == 0 ? NO : YES; + return essential_; } - (BOOL) broken { @@ -1993,8 +2039,17 @@ class Progress : - (Source *) source { if (!cached_) { - source_ = file_.end() ? nil : [[database_ getSource:file_.File()] retain]; - cached_ = true; + @synchronized (database_) { + if ([database_ era] != era_ || file_.end()) + source_ = nil; + else { + source_ = [database_ getSource:file_.File()]; + if (source_ != nil) + [source_ retain]; + } + + cached_ = true; + } } return source_; @@ -2237,7 +2292,7 @@ class Progress : - (Section *) initWithIndex:(unichar)index row:(size_t)row { if ((self = [super init]) != nil) { - name_ = [[NSString stringWithCharacters:&index length:1] retain]; + name_ = [(index == '#' ? @"123" : [NSString stringWithCharacters:&index length:1]) retain]; index_ = index; row_ = row; } return self; @@ -2279,6 +2334,10 @@ static NSArray *Finishes_; return instance; } +- (unsigned) era { + return era_; +} + - (void) dealloc { _assert(false); [super dealloc]; @@ -2523,6 +2582,10 @@ static NSArray *Finishes_; } - (void) reloadData { _pooled + @synchronized (self) { + ++era_; + } + _error->Discard(); delete list_; @@ -3074,11 +3137,15 @@ bool DepSubstrate(const pkgCache::VerIterator &iterator) { return @"Cancel"; } +- (id) rightButtonTitle { + return issues_ != nil ? nil : [super rightButtonTitle]; +} + - (id) _rightButtonTitle { #if AlwaysReload || IgnoreInstall - return @"Reload"; + return [super _rightButtonTitle]; #else - return issues_ == nil ? @"Confirm" : nil; + return @"Confirm"; #endif } @@ -4110,6 +4177,10 @@ bool DepSubstrate(const pkgCache::VerIterator &iterator) { [super webView:sender didClearWindowObject:window forFrame:frame]; } +- (bool) _allowJavaScriptPanel { + return false; +} + #if !AlwaysReload - (void) _rightButtonClicked { /*[super _rightButtonClicked]; @@ -4649,6 +4720,35 @@ bool DepSubstrate(const pkgCache::VerIterator &iterator) { [delegate_ syncData]; } +- (void) complete { + [Sources_ setObject:[NSDictionary dictionaryWithObjectsAndKeys: + @"deb", @"Type", + href_, @"URI", + @"./", @"Distribution", + nil] forKey:[NSString stringWithFormat:@"deb:%@:./", href_]]; + + [delegate_ syncData]; +} + +- (NSString *) getWarning { + NSString *href(href_); + NSRange colon([href rangeOfString:@"://"]); + if (colon.location != NSNotFound) + href = [href substringFromIndex:(colon.location + 3)]; + href = [href stringByAddingPercentEscapes]; + href = [@"http://cydia.saurik.com/api/repotag/" stringByAppendingString:href]; + href = [href stringByCachingURLWithCurrentCDN]; + + NSURL *url([NSURL URLWithString:href]); + + NSStringEncoding encoding; + NSError *error(nil); + + if (NSString *warning = [NSString stringWithContentsOfURL:url usedEncoding:&encoding error:&error]) + return [warning length] == 0 ? nil : warning; + return nil; +} + - (void) _endConnection:(NSURLConnection *)connection { NSURLConnection **field = NULL; if (connection == trivial_bz2_) @@ -4663,20 +4763,26 @@ bool DepSubstrate(const pkgCache::VerIterator &iterator) { trivial_bz2_ == nil && trivial_gz_ == nil ) { - [delegate_ setStatusBarShowsProgress:NO]; - [delegate_ removeProgressHUD:hud_]; - - [hud_ autorelease]; - hud_ = nil; + bool defer(false); if (trivial_) { - [Sources_ setObject:[NSDictionary dictionaryWithObjectsAndKeys: - @"deb", @"Type", - href_, @"URI", - @"./", @"Distribution", - nil] forKey:[NSString stringWithFormat:@"deb:%@:./", href_]]; - - [delegate_ syncData]; + if (NSString *warning = [self yieldToSelector:@selector(getWarning)]) { + defer = true; + + UIActionSheet *sheet = [[[UIActionSheet alloc] + initWithTitle:@"Source Warning" + buttons:[NSArray arrayWithObjects:@"Add Anyway", @"Cancel", nil] + defaultButtonIndex:0 + delegate:self + context:@"warning" + ] autorelease]; + + [sheet setNumberOfRows:1]; + + [sheet setBodyText:warning]; + [sheet popupAlertAnimated:YES]; + } else + [self complete]; } else if (error_ != nil) { UIActionSheet *sheet = [[[UIActionSheet alloc] initWithTitle:@"Verification Error" @@ -4701,8 +4807,16 @@ bool DepSubstrate(const pkgCache::VerIterator &iterator) { [sheet popupAlertAnimated:YES]; } - [href_ release]; - href_ = nil; + [delegate_ setStatusBarShowsProgress:NO]; + [delegate_ removeProgressHUD:hud_]; + + [hud_ autorelease]; + hud_ = nil; + + if (!defer) { + [href_ release]; + href_ = nil; + } if (error_ != nil) { [error_ release]; @@ -4779,6 +4893,24 @@ bool DepSubstrate(const pkgCache::VerIterator &iterator) { [sheet dismiss]; else if ([context isEqualToString:@"urlerror"]) [sheet dismiss]; + else if ([context isEqualToString:@"warning"]) { + switch (button) { + case 1: + [self complete]; + break; + + case 2: + break; + + default: + _assert(false); + } + + [href_ release]; + href_ = nil; + + [sheet dismiss]; + } } - (id) initWithBook:(RVBook *)book database:(Database *)database { @@ -4992,7 +5124,7 @@ bool DepSubstrate(const pkgCache::VerIterator &iterator) { ] autorelease]; [sheet setBodyText: - @"Copyright (C) 2008\n" + @"Copyright (C) 2008-2009\n" "Jay Freeman (saurik)\n" "saurik@saurik.com\n" "http://www.saurik.com/\n" @@ -6383,8 +6515,10 @@ bool DepSubstrate(const pkgCache::VerIterator &iterator) { - (void) _reloadData { UIView *block(); + static bool loaded(false); UIProgressHUD *hud([self addProgressHUD]); - [hud setText:@"Reloading Data"]; + [hud setText:(loaded ? @"Reloading Data" : @"Loading Data")]; + loaded = true; [database_ yieldToSelector:@selector(reloadData) withObject:nil]; _trace(); @@ -6424,7 +6558,7 @@ bool DepSubstrate(const pkgCache::VerIterator &iterator) { // XXX: what is this line of code for? if ([packages count] == 0); - else if (Loaded_) loaded: + else if (Loaded_ || ForSaurik) loaded: [self _loaded]; else { Loaded_ = YES; @@ -7202,7 +7336,7 @@ int main(int argc, char *argv[]) { _pooled setuid(0); setgid(0); -#if 0 /* XXX: this costs 1.4s of startup performance */ +#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) @@ -7240,6 +7374,10 @@ int main(int argc, char *argv[]) { _pooled if (NSDictionary *system = [NSDictionary dictionaryWithContentsOfFile:@"/System/Library/CoreServices/SystemVersion.plist"]) Build_ = [system objectForKey:@"ProductBuildVersion"]; + if (NSDictionary *info = [NSDictionary dictionaryWithContentsOfFile:@"/Applications/MobileSafari.app/Info.plist"]) { + Product_ = [info objectForKey:@"SafariProductVersion"]; + Safari_ = [info objectForKey:@"CFBundleVersion"]; + } /*AddPreferences(@"/Applications/Preferences.app/Settings-iPhone.plist"); AddPreferences(@"/Applications/Preferences.app/Settings-iPod.plist");*/