#include "SDURLCache/SDURLCache.h"
#include "substrate.h"
-
-#include "Version.h"
/* }}} */
/* Profiler {{{ */
while (false); \
[_pool release];
+#define Cydia_ CYDIA_VERSION
+
+#define lprintf(args...) fprintf(stderr, args)
+
+#define ForRelease 1
+#define TraceLogging (1 && !ForRelease)
+#define HistogramInsertionSort (!ForRelease ? 0 : 0)
+#define ProfileTimes (0 && !ForRelease)
+#define ForSaurik (0 && !ForRelease)
+#define LogBrowser (0 && !ForRelease)
+#define TrackResize (0 && !ForRelease)
+#define ManualRefresh (1 && !ForRelease)
+#define ShowInternals (0 && !ForRelease)
+#define AlwaysReload (0 && !ForRelease)
+#define TryIndexedCollation (0 && !ForRelease)
+
+#if !TraceLogging
+#undef _trace
+#define _trace(args...)
+#endif
+
+#if !ProfileTimes
+#undef _profile
+#define _profile(name) {
+#undef _end
+#define _end }
+#define PrintTimes() do {} while (false)
+#endif
+
// Hash Functions/Structures {{{
extern "C" uint32_t hashlittle(const void *key, size_t length, uint32_t initval = 0);
NSDate *future([NSDate distantFuture]);
NSString *mode([loop currentMode] ?: NSDefaultRunLoopMode);
+_trace();
while (!stopped && [loop runMode:mode beforeDate:future]);
+_trace();
return [context count] == 0 ? nil : [context objectAtIndex:0];
}
static const NSStringCompareOptions LaxCompareOptions_ = NSNumericSearch | NSDiacriticInsensitiveSearch | NSWidthInsensitiveSearch | NSCaseInsensitiveSearch;
static const CFStringCompareFlags LaxCompareFlags_ = kCFCompareCaseInsensitive | kCFCompareNonliteral | kCFCompareLocalized | kCFCompareNumerically | kCFCompareWidthInsensitive | kCFCompareForcedOrdering;
-#define lprintf(args...) fprintf(stderr, args)
-
-#define ForRelease 1
-#define TraceLogging (1 && !ForRelease)
-#define HistogramInsertionSort (!ForRelease ? 0 : 0)
-#define ProfileTimes (0 && !ForRelease)
-#define ForSaurik (0 && !ForRelease)
-#define LogBrowser (0 && !ForRelease)
-#define TrackResize (0 && !ForRelease)
-#define ManualRefresh (1 && !ForRelease)
-#define ShowInternals (0 && !ForRelease)
-#define AlwaysReload (0 && !ForRelease)
-#define TryIndexedCollation (0 && !ForRelease)
-
-#if !TraceLogging
-#undef _trace
-#define _trace(args...)
-#endif
-
-#if !ProfileTimes
-#undef _profile
-#define _profile(name) {
-#undef _end
-#define _end }
-#define PrintTimes() do {} while (false)
-#endif
-
/* Radix Sort {{{ */
typedef uint32_t (*SKRadixFunction)(id, void *);
bool IsWildcat_;
static CGFloat ScreenScale_;
static NSString *Idiom_;
+
+static NSMutableSet *CydiaHosts_;
+
+static NSString *kCydiaProgressEventTypeError = @"Error";
+static NSString *kCydiaProgressEventTypeInformation = @"Information";
+static NSString *kCydiaProgressEventTypeStatus = @"Status";
+static NSString *kCydiaProgressEventTypeWarning = @"Warning";
/* }}} */
/* Display Helpers {{{ */
- (CYViewController *) pageForPackage:(NSString *)name;
- (void) showActionSheet:(UIActionSheet *)sheet fromItem:(UIBarButtonItem *)item;
- (void) reloadDataWithInvocation:(NSInvocation *)invocation;
+- (void) addCydiaHost:(NSString *)host;
@end
/* }}} */
virtual void Fetch(pkgAcquire::ItemDesc &item) {
NSString *name([NSString stringWithUTF8String:item.ShortDesc.c_str()]);
- CydiaProgressEvent *event([CydiaProgressEvent eventWithMessage:[NSString stringWithFormat:UCLocalize("DOWNLOADING_"), name] ofType:@"STATUS" forItem:item]);
+ CydiaProgressEvent *event([CydiaProgressEvent eventWithMessage:[NSString stringWithFormat:UCLocalize("DOWNLOADING_"), name] ofType:kCydiaProgressEventTypeStatus forItem:item]);
[delegate_ performSelectorOnMainThread:@selector(addProgressEvent:) withObject:event waitUntilDone:YES];
}
if (error.empty())
return;
- CydiaProgressEvent *event([CydiaProgressEvent eventWithMessage:[NSString stringWithUTF8String:error.c_str()] ofType:@"ERROR" forItem:item]);
+ CydiaProgressEvent *event([CydiaProgressEvent eventWithMessage:[NSString stringWithUTF8String:error.c_str()] ofType:kCydiaProgressEventTypeError forItem:item]);
[delegate_ performSelectorOnMainThread:@selector(addProgressEvent:) withObject:event waitUntilDone:YES];
}
if (value != nil) {
NSString *mode(nil); {
NSString *type([self type]);
- if ([type isEqualToString:@"ERROR"])
+ if ([type isEqualToString:kCydiaProgressEventTypeError])
mode = UCLocalize("ERROR");
- else if ([type isEqualToString:@"WARNING"])
+ else if ([type isEqualToString:kCydiaProgressEventTypeWarning])
mode = UCLocalize("WARNING");
}
@"purposes",
@"relations",
@"section",
+ @"selection",
@"shortDescription",
@"shortSection",
@"simpleSection",
@"size",
@"source",
@"sponsor",
+ @"state",
@"support",
+ @"tags",
@"warnings",
nil];
}
return files;
}
+- (NSString *) state {
+@synchronized (database_) {
+ if ([database_ era] != era_ || file_.end())
+ return nil;
+
+ switch (iterator_->CurrentState) {
+ case pkgCache::State::NotInstalled:
+ return @"NotInstalled";
+ case pkgCache::State::UnPacked:
+ return @"UnPacked";
+ case pkgCache::State::HalfConfigured:
+ return @"HalfConfigured";
+ case pkgCache::State::HalfInstalled:
+ return @"HalfInstalled";
+ case pkgCache::State::ConfigFiles:
+ return @"ConfigFiles";
+ case pkgCache::State::Installed:
+ return @"Installed";
+ case pkgCache::State::TriggersAwaited:
+ return @"TriggersAwaited";
+ case pkgCache::State::TriggersPending:
+ return @"TriggersPending";
+ }
+
+ return (NSString *) [NSNull null];
+} }
+
+- (NSString *) selection {
+@synchronized (database_) {
+ if ([database_ era] != era_ || file_.end())
+ return nil;
+
+ switch (iterator_->SelectedState) {
+ case pkgCache::State::Unknown:
+ return @"Unknown";
+ case pkgCache::State::Install:
+ return @"Install";
+ case pkgCache::State::Hold:
+ return @"Hold";
+ case pkgCache::State::DeInstall:
+ return @"DeInstall";
+ case pkgCache::State::Purge:
+ return @"Purge";
+ }
+
+ return (NSString *) [NSNull null];
+} }
+
- (NSArray *) warnings {
NSMutableArray *warnings([NSMutableArray arrayWithCapacity:4]);
const char *name(iterator_.Name());
_assert(false);
}
+- (NSArray *) tags {
+ return tags_;
+}
+
- (BOOL) hasTag:(NSString *)tag {
return tags_ == nil ? NO : [tags_ containsObject:tag];
}
[delegate_ performSelectorOnMainThread:@selector(setConfigurationData:) withObject:conffile_r[1] waitUntilDone:YES];
} else if (strncmp(data, "status: ", 8) == 0) {
// status: <package>: {unpacked,half-configured,installed}
- CydiaProgressEvent *event([CydiaProgressEvent eventWithMessage:[NSString stringWithUTF8String:(data + 8)] ofType:@"STATUS"]);
+ CydiaProgressEvent *event([CydiaProgressEvent eventWithMessage:[NSString stringWithUTF8String:(data + 8)] ofType:kCydiaProgressEventTypeStatus]);
[progress_ performSelectorOnMainThread:@selector(addProgressEvent:) withObject:event waitUntilDone:YES];
} else if (strncmp(data, "processing: ", 12) == 0) {
// processing: configure: config-test
- CydiaProgressEvent *event([CydiaProgressEvent eventWithMessage:[NSString stringWithUTF8String:(data + 12)] ofType:@"STATUS"]);
+ CydiaProgressEvent *event([CydiaProgressEvent eventWithMessage:[NSString stringWithUTF8String:(data + 12)] ofType:kCydiaProgressEventTypeStatus]);
[progress_ performSelectorOnMainThread:@selector(addProgressEvent:) withObject:event waitUntilDone:YES];
} else if (pmstatus_r(data, size)) {
std::string type([pmstatus_r[1] UTF8String]);
NSString *string = pmstatus_r[4];
if (type == "pmerror") {
- CydiaProgressEvent *event([CydiaProgressEvent eventWithMessage:string ofType:@"ERROR" forPackage:package]);
+ CydiaProgressEvent *event([CydiaProgressEvent eventWithMessage:string ofType:kCydiaProgressEventTypeError forPackage:package]);
[progress_ performSelectorOnMainThread:@selector(addProgressEvent:) withObject:event waitUntilDone:YES];
} else if (type == "pmstatus") {
- CydiaProgressEvent *event([CydiaProgressEvent eventWithMessage:string ofType:@"STATUS" forPackage:package]);
+ CydiaProgressEvent *event([CydiaProgressEvent eventWithMessage:string ofType:kCydiaProgressEventTypeStatus forPackage:package]);
[progress_ performSelectorOnMainThread:@selector(addProgressEvent:) withObject:event waitUntilDone:YES];
} else if (type == "pmconffile")
[delegate_ performSelectorOnMainThread:@selector(setConfigurationData:) withObject:string waitUntilDone:YES];
while (std::getline(is, line)) {
lprintf("O:%s\n", line.c_str());
- CydiaProgressEvent *event([CydiaProgressEvent eventWithMessage:[NSString stringWithUTF8String:line.c_str()] ofType:@"INFORMATION"]);
+ CydiaProgressEvent *event([CydiaProgressEvent eventWithMessage:[NSString stringWithUTF8String:line.c_str()] ofType:kCydiaProgressEventTypeInformation]);
[progress_ performSelectorOnMainThread:@selector(addProgressEvent:) withObject:event waitUntilDone:YES];
}
lprintf("%c:[%s]\n", warning ? 'W' : 'E', error.c_str());
- [delegate_ addProgressEventOnMainThread:[CydiaProgressEvent eventWithMessage:[NSString stringWithUTF8String:error.c_str()] ofType:(warning ? @"WARNING" : @"ERROR")] forTask:title];
+ [delegate_ addProgressEventOnMainThread:[CydiaProgressEvent eventWithMessage:[NSString stringWithUTF8String:error.c_str()] ofType:(warning ? kCydiaProgressEventTypeWarning : kCydiaProgressEventTypeError)] forTask:title];
}
return fatal;
// else if (error == "Malformed Status line")
// else if (error == "The list of sources could not be read.")
else {
- [delegate_ addProgressEventOnMainThread:[CydiaProgressEvent eventWithMessage:[NSString stringWithUTF8String:error.c_str()] ofType:(warning ? @"WARNING" : @"ERROR")] forTask:title];
+ [delegate_ addProgressEventOnMainThread:[CydiaProgressEvent eventWithMessage:[NSString stringWithUTF8String:error.c_str()] ofType:(warning ? kCydiaProgressEventTypeWarning : kCydiaProgressEventTypeError)] forTask:title];
return;
}
return;
if (cache_->DelCount() != 0 || cache_->InstCount() != 0) {
- [delegate_ addProgressEventOnMainThread:[CydiaProgressEvent eventWithMessage:UCLocalize("COUNTS_NONZERO_EX") ofType:@"ERROR"] forTask:title];
+ [delegate_ addProgressEventOnMainThread:[CydiaProgressEvent eventWithMessage:UCLocalize("COUNTS_NONZERO_EX") ofType:kCydiaProgressEventTypeError] forTask:title];
return;
}
return;
if (cache_->BrokenCount() != 0) {
- [delegate_ addProgressEventOnMainThread:[CydiaProgressEvent eventWithMessage:UCLocalize("STILL_BROKEN_EX") ofType:@"ERROR"] forTask:title];
+ [delegate_ addProgressEventOnMainThread:[CydiaProgressEvent eventWithMessage:UCLocalize("STILL_BROKEN_EX") ofType:kCydiaProgressEventTypeError] forTask:title];
return;
}
+ (NSString *) webScriptNameForSelector:(SEL)selector {
if (false);
+ else if (selector == @selector(addCydiaHost:))
+ return @"addCydiaHost";
else if (selector == @selector(addTrivialSource:))
return @"addTrivialSource";
else if (selector == @selector(close))
return [NSString stringWithCString:value];
}
+- (void) addCydiaHost:(NSString *)host {
+ [delegate_ performSelectorOnMainThread:@selector(addCydiaHost:) withObject:host waitUntilDone:NO];
+}
+
- (void) addTrivialSource:(NSString *)href {
[delegate_ performSelectorOnMainThread:@selector(addTrivialSource:) withObject:href waitUntilDone:NO];
}
return [NSURL URLWithString:[NSString stringWithFormat:@"cydia://url/%@", [[[webview_ request] URL] absoluteString]]];
}
-- (void) setHeaders:(NSDictionary *)headers forHost:(NSString *)host {
-}
-
- (void) webView:(WebView *)view didClearWindowObject:(WebScriptObject *)window forFrame:(WebFrame *)frame {
[super webView:view didClearWindowObject:window forFrame:frame];
WebDataSource *source([frame dataSource]);
NSURLResponse *response([source response]);
-
NSURL *url([response URL]);
- NSString *scheme([url scheme]);
- NSString *host([url host]);
-
- if ([response isKindOfClass:[NSHTTPURLResponse class]]) {
- NSHTTPURLResponse *http((NSHTTPURLResponse *) response);
- NSDictionary *headers([http allHeaderFields]);
- [self setHeaders:headers forHost:host];
- }
- if (
- [host isEqualToString:@"cydia.saurik.com"] ||
- [host hasSuffix:@".cydia.saurik.com"] ||
- [scheme isEqualToString:@"file"]
- )
- [window setValue:cydia_ forKey:@"cydia"];
+ if ([[[url scheme] lowercaseString] isEqualToString:@"https"])
+ if ([CydiaHosts_ containsObject:[url host]])
+ [window setValue:cydia_ forKey:@"cydia"];
}
-- (void) _setMoreHeaders:(NSMutableURLRequest *)request {
+- (NSURLRequest *) webView:(WebView *)view resource:(id)resource willSendRequest:(NSURLRequest *)request redirectResponse:(NSURLResponse *)response fromDataSource:(WebDataSource *)source {
+ NSMutableURLRequest *copy([[super webView:view resource:resource willSendRequest:request redirectResponse:response fromDataSource:source] mutableCopy]);
+
if (System_ != NULL)
- [request setValue:System_ forHTTPHeaderField:@"X-System"];
+ [copy setValue:System_ forHTTPHeaderField:@"X-System"];
if (Machine_ != NULL)
- [request setValue:[NSString stringWithUTF8String:Machine_] forHTTPHeaderField:@"X-Machine"];
+ [copy setValue:[NSString stringWithUTF8String:Machine_] forHTTPHeaderField:@"X-Machine"];
if (Token_ != nil)
- [request setValue:Token_ forHTTPHeaderField:@"X-Cydia-Token"];
- if (Role_ != nil)
- [request setValue:Role_ forHTTPHeaderField:@"X-Role"];
-}
+ [copy setValue:Token_ forHTTPHeaderField:@"X-Cydia-Token"];
-- (NSURLRequest *) webView:(WebView *)view resource:(id)resource willSendRequest:(NSURLRequest *)request redirectResponse:(NSURLResponse *)response fromDataSource:(WebDataSource *)source {
- NSMutableURLRequest *copy([[super webView:view resource:resource willSendRequest:request redirectResponse:response fromDataSource:source] mutableCopy]);
- [self _setMoreHeaders:copy];
return copy;
}
return [NSURL URLWithString:@"cydia://home"];
}
-- (void) _setMoreHeaders:(NSMutableURLRequest *)request {
- [super _setMoreHeaders:request];
-
- if (ChipID_ != nil)
- [request setValue:ChipID_ forHTTPHeaderField:@"X-Chip-ID"];
- if (UniqueID_ != nil)
- [request setValue:UniqueID_ forHTTPHeaderField:@"X-Unique-ID"];
- if (PLMN_ != nil)
- [request setValue:PLMN_ forHTTPHeaderField:@"X-Carrier-ID"];
-}
-
- (void) aboutButtonClicked {
UIAlertView *alert([[[UIAlertView alloc] init] autorelease]);
[request setValue:[NSString stringWithUTF8String:Machine_] forHTTPHeaderField:@"X-Machine"];
if (UniqueID_ != nil)
[request setValue:UniqueID_ forHTTPHeaderField:@"X-Unique-ID"];
- if (Role_ != nil)
- [request setValue:Role_ forHTTPHeaderField:@"X-Role"];
return [[[NSURLConnection alloc] initWithRequest:request delegate:self] autorelease];
}
- (void) repairWithInvocation:(NSInvocation *)invocation {
_trace();
- [self invokeNewProgress:invocation forController:nil withTitle:UCLocalize("REPAIRING")];
+ [self invokeNewProgress:invocation forController:nil withTitle:@"REPAIRING"];
_trace();
}
fclose(file);
- [self detachNewProgressSelector:@selector(update_) toTarget:self forController:nil title:UCLocalize("UPDATING_SOURCES")];
+ [self detachNewProgressSelector:@selector(update_) toTarget:self forController:nil title:@"UPDATING_SOURCES"];
[self complete];
}
- (void) confirmWithNavigationController:(UINavigationController *)navigation {
Queuing_ = false;
++locked_;
- [self detachNewProgressSelector:@selector(perform) toTarget:database_ forController:navigation title:UCLocalize("RUNNING")];
+ [self detachNewProgressSelector:@selector(perform) toTarget:database_ forController:navigation title:@"RUNNING"];
--locked_;
[self complete];
}
}
- (BOOL) isSafeToSuspend {
+ if (locked_ != 0) {
+#if !ForRelease
+ NSLog(@"isSafeToSuspend: locked_ != 0");
+#endif
+ return false;
+ }
+
// Use external process status API internally.
// This is probably a really bad idea.
// XXX: what is the point of this? does this solve anything at all?
notify_cancel(notify_token);
}
- return locked_ == 0 && status == 0;
+ if (status != 0) {
+#if !ForRelease
+ NSLog(@"isSafeToSuspend: status != 0");
+#endif
+ return false;
+ }
+
+#if !ForRelease
+ NSLog(@"isSafeToSuspend: -> true");
+#endif
+ return true;
}
- (void) applicationSuspend:(__GSEvent *)event {
[tabbar_ setUpdateDelegate:self];
}
+- (void) addCydiaHost:(NSString *)host {
+ [CydiaHosts_ addObject:host];
+}
+
- (void) applicationDidFinishLaunching:(id)unused {
_trace();
if ([self respondsToSelector:@selector(setApplicationSupportsShakeToEdit:)])
[self setApplicationSupportsShakeToEdit:NO];
+ [self addCydiaHost:[[NSURL URLWithString:CydiaURL(@"")] host]];
+
[NSURLCache setSharedURLCache:[[[SDURLCache alloc]
initWithMemoryCapacity:524288
diskCapacity:10485760
NSLog(@"unknown UIUserInterfaceIdiom!");
}
+ CydiaHosts_ = [NSMutableSet setWithCapacity:2];
+
UI_ = CydiaURL([NSString stringWithFormat:@"ui/ios~%@", Idiom_]);
PackageName = reinterpret_cast<CYString &(*)(Package *, SEL)>(method_getImplementation(class_getInstanceMethod([Package class], @selector(cyname))));