X-Git-Url: https://git.saurik.com/cydia.git/blobdiff_plain/bf7c998c9b68756e925462bbfe1f9a699fc5055b..1d678719bf238263796da048ff173824c5aa05fa:/MobileCydia.mm diff --git a/MobileCydia.mm b/MobileCydia.mm index 4e0343a0..776c31ce 100644 --- a/MobileCydia.mm +++ b/MobileCydia.mm @@ -129,6 +129,8 @@ extern "C" { #include "CyteKit/WebViewController.h" #include "CyteKit/stringWithUTF8Bytes.h" +#include "Cydia/MIMEAddress.h" +#include "Cydia/LoadingViewController.h" #include "Cydia/ProgressEvent.h" #include "SDURLCache/SDURLCache.h" @@ -204,6 +206,7 @@ void PrintTimes() { #define _end } /* }}} */ +#include "Version.h" #define Cydia_ CYDIA_VERSION #define lprintf(args...) fprintf(stderr, args) @@ -264,6 +267,11 @@ static _finline void UpdateExternalStatus(uint64_t newStatus) { notify_post("com.saurik.Cydia.status"); } +static CGFloat CYStatusBarHeight(UIInterfaceOrientation orientation) { + CGSize size([[UIApplication sharedApplication] statusBarFrame].size); + return UIInterfaceOrientationIsPortrait(orientation) ? size.height : size.width; +} + /* NSForcedOrderingSearch doesn't work on the iPhone */ static const NSStringCompareOptions MatchCompareOptions_ = NSLiteralSearch | NSCaseInsensitiveSearch; static const NSStringCompareOptions LaxCompareOptions_ = NSNumericSearch | NSDiacriticInsensitiveSearch | NSWidthInsensitiveSearch | NSCaseInsensitiveSearch; @@ -588,74 +596,6 @@ struct NSStringMapEqual : }; /* }}} */ -/* Mime Addresses {{{ */ -@interface Address : NSObject { - _H name_; - _H address_; -} - -- (NSString *) name; -- (NSString *) address; - -- (void) setAddress:(NSString *)address; - -+ (Address *) addressWithString:(NSString *)string; -- (Address *) initWithString:(NSString *)string; - -@end - -@implementation Address - -- (NSString *) name { - return name_; -} - -- (NSString *) address { - return address_; -} - -- (void) setAddress:(NSString *)address { - address_ = address; -} - -+ (Address *) addressWithString:(NSString *)string { - return [[[Address alloc] initWithString:string] autorelease]; -} - -+ (NSArray *) _attributeKeys { - return [NSArray arrayWithObjects: - @"address", - @"name", - nil]; -} - -- (NSArray *) attributeKeys { - return [[self class] _attributeKeys]; -} - -+ (BOOL) isKeyExcludedFromWebScript:(const char *)name { - return ![[self _attributeKeys] containsObject:[NSString stringWithUTF8String:name]] && [super isKeyExcludedFromWebScript:name]; -} - -- (Address *) initWithString:(NSString *)string { - if ((self = [super init]) != nil) { - const char *data = [string UTF8String]; - size_t size = [string length]; - - static Pcre address_r("^\"?(.*)\"? <([^>]*)>$"); - - if (address_r(data, size)) { - name_ = address_r[1]; - address_ = address_r[2]; - } else { - name_ = string; - address_ = nil; - } - } return self; -} - -@end -/* }}} */ /* CoreGraphics Primitives {{{ */ class CYColor { private: @@ -769,7 +709,10 @@ static NSString *Idiom_; static _H SessionData_; static _H HostConfig_; static _H BridgedHosts_; +static _H TokenHosts_; +static _H InsecureHosts_; static _H PipelinedHosts_; +static _H CachedURLs_; static NSString *kCydiaProgressEventTypeError = @"Error"; static NSString *kCydiaProgressEventTypeInformation = @"Information"; @@ -1328,6 +1271,7 @@ static void PackageImport(const void *key, const void *value, void *context) { CYString uri_; CYString distribution_; CYString type_; + CYString base_; CYString version_; _H host_; @@ -1352,6 +1296,9 @@ static void PackageImport(const void *key, const void *value, void *context) { - (NSString *) uri; - (NSString *) distribution; - (NSString *) type; + +- (NSString *) base; + - (NSString *) key; - (NSString *) host; @@ -1372,6 +1319,8 @@ static void PackageImport(const void *key, const void *value, void *context) { distribution_.clear(); type_.clear(); + base_.clear(); + description_.clear(); label_.clear(); origin_.clear(); @@ -1420,6 +1369,8 @@ static void PackageImport(const void *key, const void *value, void *context) { debReleaseIndex *dindex(dynamic_cast(index)); if (dindex != NULL) { + base_.set(pool, dindex->MetaIndexURI("")); + FileFd fd; if (!fd.Open(dindex->MetaIndexFile("Release"), FileFd::ReadOnly)) _error->Discard(); @@ -1524,6 +1475,10 @@ static void PackageImport(const void *key, const void *value, void *context) { return type_; } +- (NSString *) base { + return base_; +} + - (NSString *) key { return [NSString stringWithFormat:@"%@:%@:%@", (NSString *) type_, (NSString *) uri_, (NSString *) distribution_]; } @@ -1739,6 +1694,8 @@ struct ParsedPackage { apr_pool_t *pool_; + uint32_t rank_; + _transient Database *database_; pkgCache::VerIterator version_; @@ -1776,7 +1733,7 @@ struct ParsedPackage { - (NSString *) uri; -- (Address *) maintainer; +- (MIMEAddress *) maintainer; - (size_t) size; - (NSString *) longDescription; - (NSString *) shortDescription; @@ -1812,7 +1769,7 @@ struct ParsedPackage { - (UIImage *) icon; - (NSString *) homepage; - (NSString *) depiction; -- (Address *) author; +- (MIMEAddress *) author; - (NSString *) support; @@ -1822,7 +1779,8 @@ struct ParsedPackage { - (Source *) source; -- (BOOL) matches:(NSString *)text; +- (uint32_t) rank; +- (BOOL) matches:(NSArray *)query; - (bool) hasSupportingRole; - (BOOL) hasTag:(NSString *)tag; @@ -1839,7 +1797,7 @@ struct ParsedPackage { - (void) install; - (void) remove; -- (bool) isUnfilteredAndSearchedForBy:(NSString *)search; +- (bool) isUnfilteredAndSearchedForBy:(NSArray *)query; - (bool) isUnfilteredAndSelectedForBy:(NSString *)search; - (bool) isInstalledAndUnfiltered:(NSNumber *)number; - (bool) isVisibleInSection:(NSString *)section; @@ -2318,14 +2276,14 @@ struct PackageNameOrdering : #endif } -- (Address *) maintainer { +- (MIMEAddress *) maintainer { @synchronized (database_) { if ([database_ era] != era_ || file_.end()) return nil; pkgRecords::Parser *parser = &[database_ records]->Lookup(file_); const std::string &maintainer(parser->Maintainer()); - return maintainer.empty() ? nil : [Address addressWithString:[NSString stringWithUTF8String:maintainer.c_str()]]; + return maintainer.empty() ? nil : [MIMEAddress addressWithString:[NSString stringWithUTF8String:maintainer.c_str()]]; } } - (size_t) size { @@ -2553,12 +2511,12 @@ struct PackageNameOrdering : return parsed_ != NULL && !parsed_->depiction_.empty() ? parsed_->depiction_ : [[self source] depictionForPackage:id_]; } -- (Address *) sponsor { - return parsed_ == NULL || parsed_->sponsor_.empty() ? nil : [Address addressWithString:parsed_->sponsor_]; +- (MIMEAddress *) sponsor { + return parsed_ == NULL || parsed_->sponsor_.empty() ? nil : [MIMEAddress addressWithString:parsed_->sponsor_]; } -- (Address *) author { - return parsed_ == NULL || parsed_->author_.empty() ? nil : [Address addressWithString:parsed_->author_]; +- (MIMEAddress *) author { + return parsed_ == NULL || parsed_->author_.empty() ? nil : [MIMEAddress addressWithString:parsed_->author_]; } - (NSString *) support { @@ -2726,30 +2684,50 @@ struct PackageNameOrdering : return source_ == (Source *) [NSNull null] ? nil : source_; } -- (BOOL) matches:(NSString *)text { - if (text == nil) +- (uint32_t) rank { + return rank_; +} + +- (BOOL) matches:(NSArray *)query { + if (query == nil || [query count] == 0) return NO; + rank_ = 0; + + NSString *string; NSRange range; + NSUInteger length; - range = [[self id] rangeOfString:text options:MatchCompareOptions_]; - if (range.location != NSNotFound) - return YES; + [self parse]; - range = [[self name] rangeOfString:text options:MatchCompareOptions_]; - if (range.location != NSNotFound) - return YES; + string = [self id]; + length = [string length]; - [self parse]; + for (NSString *term in query) { + range = [string rangeOfString:term options:MatchCompareOptions_]; + if (range.location != NSNotFound) + rank_ -= 10 * 100000 / length; + } - NSString *description([self shortDescription]); - NSUInteger length([description length]); + string = [self name]; - range = [[self shortDescription] rangeOfString:text options:MatchCompareOptions_ range:NSMakeRange(0, std::min(length, 100))]; - if (range.location != NSNotFound) - return YES; + for (NSString *term in query) { + range = [string rangeOfString:term options:MatchCompareOptions_]; + if (range.location != NSNotFound) + rank_ -= 6 * 100000 / length; + } - return NO; + string = [self shortDescription]; + length = [string length]; + NSUInteger stop(std::min(length, 100)); + + for (NSString *term in query) { + range = [string rangeOfString:term options:MatchCompareOptions_ range:NSMakeRange(0, stop)]; + if (range.location != NSNotFound) + rank_ -= 2 * 100000 / length; + } + + return rank_ != 0; } - (bool) hasSupportingRole { @@ -2853,7 +2831,7 @@ struct PackageNameOrdering : cache->MarkDelete(iterator_, true); } } -- (bool) isUnfilteredAndSearchedForBy:(NSString *)search { +- (bool) isUnfilteredAndSearchedForBy:(NSArray *)query { _profile(Package$isUnfilteredAndSearchedForBy) bool value(true); @@ -2862,7 +2840,7 @@ struct PackageNameOrdering : _end _profile(Package$isUnfilteredAndSearchedForBy$Match) - value &= [self matches:search]; + value &= [self matches:query]; _end return value; @@ -3021,7 +2999,7 @@ struct PackageNameOrdering : /* }}} */ static NSString *Colon_; -static NSString *Elision_; +NSString *Elision_; static NSString *Error_; static NSString *Warning_; @@ -3861,10 +3839,14 @@ static _H Diversions_; if (false); else if (selector == @selector(addBridgedHost:)) return @"addBridgedHost"; + else if (selector == @selector(addInsecureHost:)) + return @"addInsecureHost"; else if (selector == @selector(addInternalRedirect::)) return @"addInternalRedirect"; else if (selector == @selector(addPipelinedHost:scheme:)) return @"addPipelinedHost"; + else if (selector == @selector(addTokenHost:)) + return @"addTokenHost"; else if (selector == @selector(addTrivialSource:)) return @"addTrivialSource"; else if (selector == @selector(close)) @@ -3935,6 +3917,8 @@ static _H Diversions_; return @"statfs"; else if (selector == @selector(supports:)) return @"supports"; + else if (selector == @selector(unload)) + return @"unload"; else return nil; } @@ -3947,6 +3931,10 @@ static _H Diversions_; return [feature isEqualToString:@"window.open"]; } +- (void) unload { + [delegate_ performSelectorOnMainThread:@selector(unloadData) withObject:nil waitUntilDone:NO]; +} + - (void) addInternalRedirect:(NSString *)from :(NSString *)to { [CydiaWebViewController performSelectorOnMainThread:@selector(addDiversion:) withObject:[[[Diversion alloc] initWithFrom:from to:to] autorelease] waitUntilDone:NO]; } @@ -4013,6 +4001,16 @@ static _H Diversions_; [BridgedHosts_ addObject:host]; } } +- (void) addInsecureHost:(NSString *)host { +@synchronized (HostConfig_) { + [InsecureHosts_ addObject:host]; +} } + +- (void) addTokenHost:(NSString *)host { +@synchronized (HostConfig_) { + [TokenHosts_ addObject:host]; +} } + - (void) addPipelinedHost:(NSString *)host scheme:(NSString *)scheme { @synchronized (HostConfig_) { if (scheme != (id) [WebUndefined undefined]) @@ -4231,121 +4229,24 @@ static _H Diversions_; @end /* }}} */ -/* @ Loading... Indicator {{{ */ -@interface CYLoadingIndicator : UIView { - _H spinner_; - _H label_; - _H container_; -} - -@property (readonly, nonatomic) UILabel *label; -@property (readonly, nonatomic) UIActivityIndicatorView *activityIndicatorView; - -@end - -@implementation CYLoadingIndicator - -- (id) initWithFrame:(CGRect)frame { - if ((self = [super initWithFrame:frame]) != nil) { - container_ = [[[UIView alloc] init] autorelease]; - [container_ setAutoresizingMask:UIViewAutoresizingFlexibleTopMargin | UIViewAutoresizingFlexibleLeftMargin | UIViewAutoresizingFlexibleRightMargin | UIViewAutoresizingFlexibleBottomMargin]; - - spinner_ = [[[UIActivityIndicatorView alloc] initWithActivityIndicatorStyle:UIActivityIndicatorViewStyleGray] autorelease]; - [spinner_ startAnimating]; - [container_ addSubview:spinner_]; - - label_ = [[[UILabel alloc] init] autorelease]; - [label_ setFont:[UIFont boldSystemFontOfSize:15.0f]]; - [label_ setBackgroundColor:[UIColor clearColor]]; - [label_ setTextColor:[UIColor blackColor]]; - [label_ setShadowColor:[UIColor whiteColor]]; - [label_ setShadowOffset:CGSizeMake(0, 1)]; - [label_ setText:[NSString stringWithFormat:Elision_, UCLocalize("LOADING"), nil]]; - [container_ addSubview:label_]; - - CGSize viewsize = frame.size; - CGSize spinnersize = [spinner_ bounds].size; - CGSize textsize = [[label_ text] sizeWithFont:[label_ font]]; - float bothwidth = spinnersize.width + textsize.width + 5.0f; - - CGRect containrect = { - CGPointMake(floorf((viewsize.width / 2) - (bothwidth / 2)), floorf((viewsize.height / 2) - (spinnersize.height / 2))), - CGSizeMake(bothwidth, spinnersize.height) - }; - CGRect textrect = { - CGPointMake(spinnersize.width + 5.0f, floorf((spinnersize.height / 2) - (textsize.height / 2))), - textsize - }; - CGRect spinrect = { - CGPointZero, - spinnersize - }; - - [container_ setFrame:containrect]; - [spinner_ setFrame:spinrect]; - [label_ setFrame:textrect]; - [self addSubview:container_]; - } return self; -} - -- (UILabel *) label { - return label_; -} - -- (UIActivityIndicatorView *) activityIndicatorView { - return spinner_; -} - -@end -/* }}} */ -/* Emulated Loading Controller {{{ */ -@interface CYEmulatedLoadingController : CyteViewController { - _transient Database *database_; - _H indicator_; - _H tabbar_; - _H navbar_; -} - +@interface NSURL (CydiaSecure) @end -@implementation CYEmulatedLoadingController - -- (id) initWithDatabase:(Database *)database { - if ((self = [super init]) != nil) { - database_ = database; - } return self; -} +@implementation NSURL (CydiaSecure) -- (void) loadView { - [self setView:[[[UIView alloc] initWithFrame:[[UIScreen mainScreen] applicationFrame]] autorelease]]; - - UITableView *table([[[UITableView alloc] initWithFrame:[[self view] bounds] style:UITableViewStyleGrouped] autorelease]); - [table setAutoresizingMask:UIViewAutoresizingFlexibleBoth]; - [[self view] addSubview:table]; - - indicator_ = [[[CYLoadingIndicator alloc] initWithFrame:[[self view] bounds]] autorelease]; - [indicator_ setAutoresizingMask:UIViewAutoresizingFlexibleBoth]; - [[self view] addSubview:indicator_]; - - tabbar_ = [[[UITabBar alloc] initWithFrame:CGRectMake(0, 0, 0, 49.0f)] autorelease]; - [tabbar_ setFrame:CGRectMake(0.0f, [[self view] bounds].size.height - [tabbar_ bounds].size.height, [[self view] bounds].size.width, [tabbar_ bounds].size.height)]; - [tabbar_ setAutoresizingMask:UIViewAutoresizingFlexibleTopMargin | UIViewAutoresizingFlexibleWidth]; - [[self view] addSubview:tabbar_]; +- (bool) isCydiaSecure { + if ([[[self scheme] lowercaseString] isEqualToString:@"https"]) + return true; - navbar_ = [[[UINavigationBar alloc] initWithFrame:CGRectMake(0, 0, 0, 44.0f)] autorelease]; - [navbar_ setFrame:CGRectMake(0.0f, 0.0f, [[self view] bounds].size.width, [navbar_ bounds].size.height)]; - [navbar_ setAutoresizingMask:UIViewAutoresizingFlexibleBottomMargin | UIViewAutoresizingFlexibleWidth]; - [[self view] addSubview:navbar_]; -} + @synchronized (HostConfig_) { + if ([InsecureHosts_ containsObject:[self host]]) + return true; + } -- (void) releaseSubviews { - indicator_ = nil; - tabbar_ = nil; - navbar_ = nil; + return false; } @end -/* }}} */ /* Cydia Browser Controller {{{ */ @implementation CydiaWebViewController @@ -4384,19 +4285,37 @@ static _H Diversions_; [window setValue:cydia_ forKey:@"cydia"]; } +- (void) _setupMail:(MFMailComposeViewController *)controller { + [controller addAttachmentData:[NSData dataWithContentsOfFile:@"/tmp/cydia.log"] mimeType:@"text/plain" fileName:@"cydia.log"]; + + system("/usr/bin/dpkg -l >/tmp/dpkgl.log"); + [controller addAttachmentData:[NSData dataWithContentsOfFile:@"/tmp/dpkgl.log"] mimeType:@"text/plain" fileName:@"dpkgl.log"]; +} + - (NSURL *) URLWithURL:(NSURL *)url { return [Diversion divertURL:url]; } - (NSURLRequest *) webView:(WebView *)view resource:(id)resource willSendRequest:(NSURLRequest *)request redirectResponse:(NSURLResponse *)response fromDataSource:(WebDataSource *)source { + NSURL *url([request URL]); + NSString *host([url host]); + NSMutableURLRequest *copy([[super webView:view resource:resource willSendRequest:request redirectResponse:response fromDataSource:source] mutableCopy]); - if (System_ != NULL) + if (System_ != NULL && [copy valueForHTTPHeaderField:@"X-System"] == nil) [copy setValue:System_ forHTTPHeaderField:@"X-System"]; - if (Machine_ != NULL) + if (Machine_ != NULL && [copy valueForHTTPHeaderField:@"X-Machine"] == nil) [copy setValue:[NSString stringWithUTF8String:Machine_] forHTTPHeaderField:@"X-Machine"]; - if (Token_ != nil) - [copy setValue:Token_ forHTTPHeaderField:@"X-Cydia-Token"]; + + bool token; + @synchronized (HostConfig_) { + token = [TokenHosts_ containsObject:host] || [BridgedHosts_ containsObject:host]; + } + + if ([url isCydiaSecure] && token) { + if (Token_ != nil && [copy valueForHTTPHeaderField:@"X-Cydia-Token"] == nil) + [copy setValue:Token_ forHTTPHeaderField:@"X-Cydia-Token"]; + } return copy; } @@ -4406,22 +4325,22 @@ static _H Diversions_; [cydia_ setDelegate:delegate]; } -- (id) init { - if ((self = [super initWithWidth:0 ofClass:[CydiaWebViewController class]]) != nil) { - cydia_ = [[[CydiaObject alloc] initWithDelegate:indirect_] autorelease]; - - WebView *webview([[webview_ _documentView] webView]); +- (NSString *) applicationNameForUserAgent { + NSString *application([NSString stringWithFormat:@"Cydia/%@", @ Cydia_]); - NSString *application([NSString stringWithFormat:@"Cydia/%@", @ Cydia_]); + if (Safari_ != nil) + application = [NSString stringWithFormat:@"Safari/%@ %@", Safari_, application]; + if (Build_ != nil) + application = [NSString stringWithFormat:@"Mobile/%@ %@", Build_, application]; + if (Product_ != nil) + application = [NSString stringWithFormat:@"Version/%@ %@", Product_, application]; - if (Safari_ != nil) - application = [NSString stringWithFormat:@"Safari/%@ %@", Safari_, application]; - if (Build_ != nil) - application = [NSString stringWithFormat:@"Mobile/%@ %@", Build_, application]; - if (Product_ != nil) - application = [NSString stringWithFormat:@"Version/%@ %@", Product_, application]; + return application; +} - [webview setApplicationNameForUserAgent:application]; +- (id) init { + if ((self = [super initWithWidth:0 ofClass:[CydiaWebViewController class]]) != nil) { + cydia_ = [[[CydiaObject alloc] initWithDelegate:indirect_] autorelease]; } return self; } @@ -5161,7 +5080,7 @@ bool DepSubstrate(const pkgCache::VerIterator &iterator) { /* }}} */ /* Package Cell {{{ */ -@interface PackageCell : CYTableViewCell < +@interface PackageCell : CyteTableViewCell < CyteTableViewCellDelegate > { _H icon_; @@ -5219,12 +5138,19 @@ bool DepSubstrate(const pkgCache::VerIterator &iterator) { Source *source = [package source]; icon_ = [package icon]; - name_ = [package name]; - if (IsWildcat_) - description_ = [package longDescription]; - if (description_ == nil) - description_ = [package shortDescription]; + if (NSString *name = [package name]) + name_ = [NSString stringWithString:name]; + + NSString *description(nil); + + if (description == nil && IsWildcat_) + description = [package longDescription]; + if (description == nil) + description = [package shortDescription]; + + if (description != nil) + description_ = [NSString stringWithString:description]; commercial_ = [package isCommercial]; @@ -5383,7 +5309,7 @@ bool DepSubstrate(const pkgCache::VerIterator &iterator) { @end /* }}} */ /* Section Cell {{{ */ -@interface SectionCell : CYTableViewCell < +@interface SectionCell : CyteTableViewCell < CyteTableViewCellDelegate > { _H basic_; @@ -5565,6 +5491,8 @@ bool DepSubstrate(const pkgCache::VerIterator &iterator) { - (void) releaseSubviews { list_ = nil; + + [super releaseSubviews]; } - (id) initWithDatabase:(Database *)database { @@ -5816,6 +5744,10 @@ bool DepSubstrate(const pkgCache::VerIterator &iterator) { return false; } +- (bool) showsSections { + return true; +} + - (void) deselectWithAnimation:(BOOL)animated { [list_ deselectRowAtIndexPath:[list_ indexPathForSelectedRow] animated:animated]; } @@ -5841,15 +5773,27 @@ bool DepSubstrate(const pkgCache::VerIterator &iterator) { [self resizeForKeyboardBounds:bounds duration:0]; } +- (void) getKeyboardCurve:(UIViewAnimationCurve *)curve duration:(NSTimeInterval *)duration forNotification:(NSNotification *)notification { + if (&UIKeyboardAnimationCurveUserInfoKey == NULL) + *curve = UIViewAnimationCurveEaseInOut; + else + [[[notification userInfo] objectForKey:UIKeyboardAnimationCurveUserInfoKey] getValue:curve]; + + if (&UIKeyboardAnimationDurationUserInfoKey == NULL) + *duration = 0.3; + else + [[[notification userInfo] objectForKey:UIKeyboardAnimationDurationUserInfoKey] getValue:duration]; +} + - (void) keyboardWillShow:(NSNotification *)notification { CGRect bounds; CGPoint center; - NSTimeInterval duration; - UIViewAnimationCurve curve; [[[notification userInfo] objectForKey:UIKeyboardBoundsUserInfoKey] getValue:&bounds]; [[[notification userInfo] objectForKey:UIKeyboardCenterEndUserInfoKey] getValue:¢er]; - [[[notification userInfo] objectForKey:UIKeyboardAnimationCurveUserInfoKey] getValue:&curve]; - [[[notification userInfo] objectForKey:UIKeyboardAnimationDurationUserInfoKey] getValue:&duration]; + + NSTimeInterval duration; + UIViewAnimationCurve curve; + [self getKeyboardCurve:&curve duration:&duration forNotification:notification]; CGRect kbframe = CGRectMake(round(center.x - bounds.size.width / 2.0), round(center.y - bounds.size.height / 2.0), bounds.size.width, bounds.size.height); UIViewController *base = self; @@ -5858,14 +5802,16 @@ bool DepSubstrate(const pkgCache::VerIterator &iterator) { CGRect viewframe = [[base view] convertRect:[list_ frame] fromView:[list_ superview]]; CGRect intersection = CGRectIntersection(viewframe, kbframe); + if (kCFCoreFoundationVersionNumber < kCFCoreFoundationVersionNumber_iPhoneOS_3_0) // XXX: _UIApplicationLinkedOnOrAfter(4) + intersection.size.height += CYStatusBarHeight([self interfaceOrientation]); + [self resizeForKeyboardBounds:intersection duration:duration curve:curve]; } - (void) keyboardWillHide:(NSNotification *)notification { NSTimeInterval duration; UIViewAnimationCurve curve; - [[[notification userInfo] objectForKey:UIKeyboardAnimationCurveUserInfoKey] getValue:&curve]; - [[[notification userInfo] objectForKey:UIKeyboardAnimationDurationUserInfoKey] getValue:&duration]; + [self getKeyboardCurve:&curve duration:&duration forNotification:notification]; [self resizeForKeyboardBounds:CGRectZero duration:duration curve:curve]; } @@ -5946,7 +5892,7 @@ bool DepSubstrate(const pkgCache::VerIterator &iterator) { } - (NSArray *) sectionIndexTitlesForTableView:(UITableView *)tableView { - if ([self isSummarized]) + if ([self showsSections]) return nil; return index_; @@ -5983,27 +5929,33 @@ bool DepSubstrate(const pkgCache::VerIterator &iterator) { packages_ = [NSArray array]; sections_ = [NSMutableArray arrayWithCapacity:16]; + } return self; +} - list_ = [[[UITableView alloc] initWithFrame:[[self view] bounds] style:UITableViewStylePlain] autorelease]; - [list_ setAutoresizingMask:UIViewAutoresizingFlexibleBoth]; - [[self view] addSubview:list_]; +- (void) loadView { + [self setView:[[[UIView alloc] initWithFrame:[[UIScreen mainScreen] applicationFrame]] autorelease]]; - // XXX: is 20 the most optimal number here? - [list_ setSectionIndexMinimumDisplayRowCount:20]; + list_ = [[[UITableView alloc] initWithFrame:[[self view] bounds] style:UITableViewStylePlain] autorelease]; + [list_ setAutoresizingMask:UIViewAutoresizingFlexibleBoth]; + [[self view] addSubview:list_]; - [(UITableView *) list_ setDataSource:self]; - [list_ setDelegate:self]; + // XXX: is 20 the most optimal number here? + [list_ setSectionIndexMinimumDisplayRowCount:20]; - [self updateHeight]; - } return self; + [(UITableView *) list_ setDataSource:self]; + [list_ setDelegate:self]; + + [self updateHeight]; } -- (void) setDelegate:(id)delegate { - delegate_ = delegate; +- (void) releaseSubviews { + list_ = nil; + + [super releaseSubviews]; } -- (bool) hasPackage:(Package *)package { - return true; +- (void) setDelegate:(id)delegate { + delegate_ = delegate; } - (bool) shouldYield { @@ -6014,17 +5966,13 @@ bool DepSubstrate(const pkgCache::VerIterator &iterator) { return false; } -- (NSArray *) _reloadPackages:(NSArray *)packages { - NSMutableArray *filtered([NSMutableArray arrayWithCapacity:[packages count]]); - - _profile(PackageTable$reloadData$Filter) - for (Package *package in packages) - if ([self hasPackage:package]) - [filtered addObject:package]; - _end +- (NSMutableArray *) _reloadPackages { +@synchronized (database_) { + era_ = [database_ era]; + NSArray *packages([database_ packages]); - return filtered; -} + return [NSMutableArray arrayWithArray:packages]; +} } - (void) _reloadData { if (reloading_ != 0) { @@ -6032,32 +5980,33 @@ bool DepSubstrate(const pkgCache::VerIterator &iterator) { return; } - era_ = [database_ era]; - NSArray *packages = [database_ packages]; + NSArray *packages; if ([self shouldYield]) { - UIProgressHUD *hud; + do { + UIProgressHUD *hud; - if (![self shouldBlock]) - hud = nil; - else { - hud = [delegate_ addProgressHUD]; - [hud setText:UCLocalize("LOADING")]; - } + if (![self shouldBlock]) + hud = nil; + else { + hud = [delegate_ addProgressHUD]; + [hud setText:UCLocalize("LOADING")]; + } - do { reloading_ = 1; - packages_ = [self yieldToSelector:@selector(_reloadPackages:) withObject:packages]; + packages = [self yieldToSelector:@selector(_reloadPackages)]; + + if (hud != nil) + [delegate_ removeProgressHUD:hud]; } while (reloading_ == 2); reloading_ = 0; - - if (hud != nil) - [delegate_ removeProgressHUD:hud]; } else { - packages_ = [self _reloadPackages:packages]; + packages = [self _reloadPackages]; } + packages_ = packages; + [indices_ removeAllObjects]; [sections_ removeAllObjects]; @@ -6099,8 +6048,8 @@ bool DepSubstrate(const pkgCache::VerIterator &iterator) { { [index_ removeAllObjects]; - bool summary([self isSummarized]); - if (summary) { + bool sectioned([self showsSections]); + if (!sectioned) { section = [[[Section alloc] initWithName:nil localize:false] autorelease]; [sections_ addObject:section]; } @@ -6115,7 +6064,7 @@ bool DepSubstrate(const pkgCache::VerIterator &iterator) { index = [package index]; _end - if (!summary && (section == nil || [section index] != index)) { + if (sectioned && (section == nil || [section index] != index)) { _profile(PackageTable$reloadData$Section$Allocate) section = [[[Section alloc] initWithIndex:index row:offset] autorelease]; _end @@ -6185,6 +6134,7 @@ bool DepSubstrate(const pkgCache::VerIterator &iterator) { } - (void) setFilter:(SEL)filter { +@synchronized (self) { filter_ = filter; /* XXX: this is an unsafe optimization of doomy hell */ @@ -6192,22 +6142,44 @@ bool DepSubstrate(const pkgCache::VerIterator &iterator) { _assert(method != NULL); imp_ = method_getImplementation(method); _assert(imp_ != NULL); -} +} } - (void) setObject:(id)object { +@synchronized (self) { object_ = object; -} +} } - (void) setObject:(id)object forFilter:(SEL)filter { +@synchronized (self) { [self setFilter:filter]; [self setObject:object]; -} +} } + +- (NSMutableArray *) _reloadPackages { +@synchronized (database_) { + era_ = [database_ era]; + NSArray *packages([database_ packages]); + + NSMutableArray *filtered([NSMutableArray arrayWithCapacity:[packages count]]); + + IMP imp; + SEL filter; + _H object; -- (bool) hasPackage:(Package *)package { - _profile(FilteredPackageTable$hasPackage) - return [package valid] && (*reinterpret_cast(imp_))(package, filter_, object_); + @synchronized (self) { + imp = imp_; + filter = filter_; + object = object_; + } + + _profile(PackageTable$reloadData$Filter) + for (Package *package in packages) + if ([package valid] && (*reinterpret_cast(imp))(package, filter, object)) + [filtered addObject:package]; _end -} + + return filtered; +} } - (id) initWithDatabase:(Database *)database title:(NSString *)title filter:(SEL)filter with:(id)object { if ((self = [super initWithDatabase:database title:title]) != nil) { @@ -6266,11 +6238,6 @@ bool DepSubstrate(const pkgCache::VerIterator &iterator) { ] autorelease]; } -- (void) unloadData { - [super unloadData]; - [self reloadData]; -} - @end /* }}} */ /* Manage Controller {{{ */ @@ -6520,16 +6487,18 @@ bool DepSubstrate(const pkgCache::VerIterator &iterator) { } - (void) unloadData { - UIViewController *selected([self selectedViewController]); + [super unloadData]; + for (UINavigationController *controller in [self viewControllers]) [controller unloadData]; - [selected reloadData]; + if (UIViewController *selected = [self selectedViewController]) + [selected reloadData]; - if (UIViewController *unselected = [self unselectedViewController]) + if (UIViewController *unselected = [self unselectedViewController]) { + [unselected unloadData]; [unselected reloadData]; - - [super unloadData]; + } } - (void) dealloc { @@ -6637,14 +6606,6 @@ bool DepSubstrate(const pkgCache::VerIterator &iterator) { updatedelegate_ = delegate; } -- (CGFloat) statusBarHeight { - if (UIInterfaceOrientationIsPortrait([self interfaceOrientation])) { - return [[UIApplication sharedApplication] statusBarFrame].size.height; - } else { - return [[UIApplication sharedApplication] statusBarFrame].size.width; - } -} - - (UIView *) transitionView { if ([self respondsToSelector:@selector(_transitionView)]) return [self _transitionView]; @@ -6663,7 +6624,7 @@ bool DepSubstrate(const pkgCache::VerIterator &iterator) { CGRect barframe([refreshbar_ frame]); if (kCFCoreFoundationVersionNumber >= kCFCoreFoundationVersionNumber_iPhoneOS_3_0) // XXX: _UIApplicationLinkedOnOrAfter(4) - barframe.origin.y = [self statusBarHeight]; + barframe.origin.y = CYStatusBarHeight([self interfaceOrientation]); else barframe.origin.y = 0; @@ -7036,6 +6997,8 @@ bool DepSubstrate(const pkgCache::VerIterator &iterator) { - (void) releaseSubviews { list_ = nil; + + [super releaseSubviews]; } - (id) initWithDatabase:(Database *)database { @@ -7213,6 +7176,8 @@ bool DepSubstrate(const pkgCache::VerIterator &iterator) { - (void) releaseSubviews { list_ = nil; + + [super releaseSubviews]; } - (id) initWithDatabase:(Database *)database { @@ -7224,7 +7189,11 @@ bool DepSubstrate(const pkgCache::VerIterator &iterator) { } return self; } -- (NSArray *) _reloadPackages:(NSArray *)packages { +- (NSMutableArray *) _reloadPackages { +@synchronized (database_) { + era_ = [database_ era]; + NSArray *packages([database_ packages]); + NSMutableArray *filtered([NSMutableArray arrayWithCapacity:[packages count]]); _trace(); @@ -7240,23 +7209,27 @@ bool DepSubstrate(const pkgCache::VerIterator &iterator) { _trace(); return filtered; -} +} } - (void) _reloadData { -@synchronized (database_) { - era_ = [database_ era]; - NSArray *packages = [database_ packages]; + NSArray *packages; + + reload: + if (true) { + UIProgressHUD *hud([delegate_ addProgressHUD]); + [hud setText:UCLocalize("LOADING")]; + //NSLog(@"HUD:%@::%@", delegate_, hud); + packages = [self yieldToSelector:@selector(_reloadPackages)]; + [delegate_ removeProgressHUD:hud]; + } else { + packages = [self _reloadPackages]; + } -#if 1 - UIProgressHUD *hud([delegate_ addProgressHUD]); - [hud setText:UCLocalize("LOADING")]; - //NSLog(@"HUD:%@::%@", delegate_, hud); - packages_ = [self yieldToSelector:@selector(_reloadPackages:) withObject:packages]; - [delegate_ removeProgressHUD:hud]; -#else - packages_ = [self _reloadPackages:packages]; -#endif +@synchronized (database_) { + if (era_ != [database_ era]) + goto reload; + packages_ = packages; [sections_ removeAllObjects]; Section *upgradable = [[[Section alloc] initWithName:UCLocalize("AVAILABLE_UPGRADES") localize:NO] autorelease]; @@ -7370,7 +7343,7 @@ bool DepSubstrate(const pkgCache::VerIterator &iterator) { } - (void) useSearch { - [self setObject:[search_ text] forFilter:@selector(isUnfilteredAndSearchedForBy:)]; + [self setObject:[[search_ text] componentsSeparatedByString:@" "] forFilter:@selector(isUnfilteredAndSearchedForBy:)]; [self clearData]; [self reloadData]; } @@ -7419,8 +7392,19 @@ bool DepSubstrate(const pkgCache::VerIterator &iterator) { return [self filter] == @selector(isUnfilteredAndSelectedForBy:); } +- (bool) showsSections { + return false; +} + +- (NSMutableArray *) _reloadPackages { + NSMutableArray *packages([super _reloadPackages]); + if ([self filter] == @selector(isUnfilteredAndSearchedForBy:)) + [packages radixSortUsingSelector:@selector(rank)]; + return packages; +} + - (id) initWithDatabase:(Database *)database query:(NSString *)query { - if ((self = [super initWithDatabase:database title:UCLocalize("SEARCH") filter:@selector(isUnfilteredAndSearchedForBy:) with:query])) { + if ((self = [super initWithDatabase:database title:UCLocalize("SEARCH") filter:@selector(isUnfilteredAndSearchedForBy:) with:[query componentsSeparatedByString:@" "]])) { search_ = [[[UISearchBar alloc] init] autorelease]; [search_ setDelegate:self]; @@ -7451,7 +7435,11 @@ bool DepSubstrate(const pkgCache::VerIterator &iterator) { } - (void) reloadData { - [self setObject:[search_ text]]; + id object([search_ text]); + if ([self filter] == @selector(isUnfilteredAndSearchedForBy:)) + object = [object componentsSeparatedByString:@" "]; + + [self setObject:object]; [self resetCursor]; [super reloadData]; @@ -7619,6 +7607,8 @@ bool DepSubstrate(const pkgCache::VerIterator &iterator) { table_ = nil; ignoredSwitch_ = nil; subscribedSwitch_ = nil; + + [super releaseSubviews]; } - (id) initWithDatabase:(Database *)database package:(NSString *)package { @@ -7714,7 +7704,7 @@ bool DepSubstrate(const pkgCache::VerIterator &iterator) { /* }}} */ /* Source Cell {{{ */ -@interface SourceCell : CYTableViewCell < +@interface SourceCell : CyteTableViewCell < CyteTableViewCellDelegate > { _H icon_; @@ -7728,17 +7718,44 @@ bool DepSubstrate(const pkgCache::VerIterator &iterator) { @implementation SourceCell +- (void) _setImage:(UIImage *)image { + icon_ = image; + [content_ setNeedsDisplay]; +} + +- (void) _setSource:(Source *)source { + NSAutoreleasePool *pool([[NSAutoreleasePool alloc] init]); + + if (NSString *base = [source base]) + if ([base length] != 0) { + NSURL *url([NSURL URLWithString:[base stringByAppendingString:@"CydiaIcon.png"]]); + + if (NSData *data = [NSURLConnection + sendSynchronousRequest:[NSURLRequest + requestWithURL:url + //cachePolicy:NSURLRequestUseProtocolCachePolicy + //timeoutInterval:5 + ] + + returningResponse:NULL + error:NULL + ]) + if (UIImage *image = [UIImage imageWithData:data]) + [self performSelectorOnMainThread:@selector(_setImage:) withObject:image waitUntilDone:NO]; + } + + [pool release]; +} + - (void) setSource:(Source *)source { - icon_ = nil; - if (icon_ == nil) - icon_ = [UIImage applicationImageNamed:[NSString stringWithFormat:@"Sources/%@.png", [source host]]]; - if (icon_ == nil) - icon_ = [UIImage applicationImageNamed:@"unknown.png"]; + icon_ = [UIImage applicationImageNamed:@"unknown.png"]; origin_ = [source name]; label_ = [source uri]; [content_ setNeedsDisplay]; + + [NSThread detachNewThreadSelector:@selector(_setSource:) toTarget:self withObject:source]; } - (SourceCell *) initWithFrame:(CGRect)frame reuseIdentifier:(NSString *)reuseIdentifier { @@ -8060,8 +8077,10 @@ bool DepSubstrate(const pkgCache::VerIterator &iterator) { } - (NSURLConnection *) _requestHRef:(NSString *)href method:(NSString *)method { + NSURL *url([NSURL URLWithString:href]); + NSMutableURLRequest *request = [NSMutableURLRequest - requestWithURL:[NSURL URLWithString:href] + requestWithURL:url cachePolicy:NSURLRequestUseProtocolCachePolicy timeoutInterval:120.0 ]; @@ -8070,8 +8089,11 @@ bool DepSubstrate(const pkgCache::VerIterator &iterator) { if (Machine_ != NULL) [request setValue:[NSString stringWithUTF8String:Machine_] forHTTPHeaderField:@"X-Machine"]; - if (UniqueID_ != nil) - [request setValue:UniqueID_ forHTTPHeaderField:@"X-Unique-ID"]; + + if ([url isCydiaSecure]) { + if (UniqueID_ != nil) + [request setValue:UniqueID_ forHTTPHeaderField:@"X-Unique-ID"]; + } return [[[NSURLConnection alloc] initWithRequest:request delegate:self] autorelease]; } @@ -8153,6 +8175,8 @@ bool DepSubstrate(const pkgCache::VerIterator &iterator) { - (void) releaseSubviews { list_ = nil; + + [super releaseSubviews]; } - (id) initWithDatabase:(Database *)database { @@ -8316,6 +8340,8 @@ bool DepSubstrate(const pkgCache::VerIterator &iterator) { table_ = nil; segment_ = nil; container_ = nil; + + [super releaseSubviews]; } - (id) initWithDatabase:(Database *)database delegate:(id)delegate { @@ -8499,6 +8525,14 @@ bool DepSubstrate(const pkgCache::VerIterator &iterator) { [[self view] addSubview:status_]; } +- (void) releaseSubviews { + spinner_ = nil; + status_ = nil; + caption_ = nil; + + [super releaseSubviews]; +} + @end /* }}} */ @@ -8529,6 +8563,24 @@ bool DepSubstrate(const pkgCache::VerIterator &iterator) { #endif } +- (void) storeCachedResponse:(NSCachedURLResponse *)cached forRequest:(NSURLRequest *)request { + if (NSURLResponse *response = [cached response]) + if (NSString *mime = [response MIMEType]) + if ([mime isEqualToString:@"text/cache-manifest"]) { + NSURL *url([response URL]); + +#if !ForRelease + NSLog(@"###: %@", [url absoluteString]); +#endif + + @synchronized (HostConfig_) { + [CachedURLs_ addObject:url]; + } + } + + [super storeCachedResponse:cached forRequest:request]; +} + @end @interface Cydia : UIApplication < @@ -8540,7 +8592,7 @@ bool DepSubstrate(const pkgCache::VerIterator &iterator) { > { _H window_; _H tabbar_; - _H emulated_; + _H emulated_; _H essential_; _H broken_; @@ -8707,7 +8759,8 @@ bool DepSubstrate(const pkgCache::VerIterator &iterator) { [NSThread detachNewThreadSelector:@selector(_refreshIfPossible:) toTarget:self withObject:[Metadata_ objectForKey:@"LastUpdate"]]; } -- (void) _reloadDataWithInvocation:(NSInvocation *)invocation { +- (void) reloadDataWithInvocation:(NSInvocation *)invocation { +@synchronized (self) { UIProgressHUD *hud(loaded_ ? [self addProgressHUD] : nil); [hud setText:UCLocalize("RELOADING_DATA")]; @@ -8732,8 +8785,6 @@ bool DepSubstrate(const pkgCache::VerIterator &iterator) { } } - NSLog(@"changes:#%u", changes); - UITabBarItem *changesItem = [[[tabbar_ viewControllers] objectAtIndex:2] tabBarItem]; if (changes != 0) { _trace(); @@ -8751,7 +8802,7 @@ bool DepSubstrate(const pkgCache::VerIterator &iterator) { [self _updateData]; [self refreshIfPossible]; -} +} } - (void) updateData { [self _updateData]; @@ -8759,12 +8810,7 @@ bool DepSubstrate(const pkgCache::VerIterator &iterator) { - (void) update_ { [database_ update]; -} - -- (void) complete { - @synchronized (self) { - [self _reloadDataWithInvocation:nil]; - } + [self performSelectorOnMainThread:@selector(reloadData) withObject:nil waitUntilDone:YES]; } - (void) disemulate { @@ -8821,6 +8867,10 @@ bool DepSubstrate(const pkgCache::VerIterator &iterator) { [self performSelectorOnMainThread:@selector(repairWithInvocation:) withObject:[NSInvocation invocationWithSelector:selector forTarget:database_] waitUntilDone:YES]; } +- (void) reloadData { + [self reloadDataWithInvocation:nil]; +} + - (void) syncData { [self _saveConfig]; @@ -8840,8 +8890,6 @@ bool DepSubstrate(const pkgCache::VerIterator &iterator) { fclose(file); [self detachNewProgressSelector:@selector(update_) toTarget:self forController:nil title:@"UPDATING_SOURCES"]; - - [self complete]; } - (void) addTrivialSource:(NSString *)href { @@ -8854,16 +8902,6 @@ bool DepSubstrate(const pkgCache::VerIterator &iterator) { Changed_ = true; } -- (void) reloadDataWithInvocation:(NSInvocation *)invocation { - @synchronized (self) { - [self _reloadDataWithInvocation:invocation]; - } -} - -- (void) reloadData { - [self reloadDataWithInvocation:nil]; -} - - (void) resolve { pkgProblemResolver *resolver = [database_ resolver]; @@ -8941,12 +8979,16 @@ bool DepSubstrate(const pkgCache::VerIterator &iterator) { } } +- (void) perform_ { + [database_ perform]; + [self performSelectorOnMainThread:@selector(reloadData) withObject:nil waitUntilDone:YES]; +} + - (void) confirmWithNavigationController:(UINavigationController *)navigation { Queuing_ = false; ++locked_; - [self detachNewProgressSelector:@selector(perform) toTarget:database_ forController:navigation title:@"RUNNING"]; + [self detachNewProgressSelector:@selector(perform_) toTarget:self forController:navigation title:@"RUNNING"]; --locked_; - [self complete]; } - (void) showSettings { @@ -9416,7 +9458,7 @@ _trace(); [window_ setUserInteractionEnabled:NO]; [self setupViewControllers]; - emulated_ = [[[CYEmulatedLoadingController alloc] initWithDatabase:database_] autorelease]; + emulated_ = [[[CydiaLoadingViewController alloc] init] autorelease]; [window_ addSubview:[emulated_ view]]; [self performSelector:@selector(loadData) withObject:nil afterDelay:0]; @@ -9612,6 +9654,8 @@ MSHook(id, NSURLConnection$init$, NSURLConnection *self, SEL _cmd, NSURLRequest NSMutableURLRequest *copy([request mutableCopy]); NSURL *url([copy URL]); + + NSString *href([url absoluteString]); NSString *host([url host]); NSString *scheme([[url scheme] lowercaseString]); @@ -9621,6 +9665,20 @@ MSHook(id, NSURLConnection$init$, NSURLConnection *self, SEL _cmd, NSURLRequest if ([copy respondsToSelector:@selector(setHTTPShouldUsePipelining:)]) if ([PipelinedHosts_ containsObject:host] || [PipelinedHosts_ containsObject:compound]) [copy setHTTPShouldUsePipelining:YES]; + + if (NSString *control = [copy valueForHTTPHeaderField:@"Cache-Control"]) + if ([control isEqualToString:@"max-age=0"]) + if ([CachedURLs_ containsObject:href]) { +#if !ForRelease + NSLog(@"~~~: %@", href); +#endif + + [copy setCachePolicy:NSURLRequestReturnCacheDataDontLoad]; + + [copy setValue:nil forHTTPHeaderField:@"Cache-Control"]; + [copy setValue:nil forHTTPHeaderField:@"If-Modified-Since"]; + [copy setValue:nil forHTTPHeaderField:@"If-None-Match"]; + } } if ((self = _NSURLConnection$init$(self, _cmd, copy, delegate, usesCache, maxContentLength, startImmediately, connectionProperties)) != nil) { @@ -9664,7 +9722,10 @@ int main(int argc, char *argv[]) { HostConfig_ = [[[NSObject alloc] init] autorelease]; @synchronized (HostConfig_) { BridgedHosts_ = [NSMutableSet setWithCapacity:4]; + TokenHosts_ = [NSMutableSet setWithCapacity:4]; + InsecureHosts_ = [NSMutableSet setWithCapacity:4]; PipelinedHosts_ = [NSMutableSet setWithCapacity:4]; + CachedURLs_ = [NSMutableSet setWithCapacity:32]; } UI_ = CydiaURL([NSString stringWithFormat:@"ui/ios~%@", Idiom_]);