X-Git-Url: https://git.saurik.com/cydia.git/blobdiff_plain/3720d3d33be98b467736c5f2c2eb43b8afbc2e8c..ca0a920d902e70044e20bbd4efd993e5d63789e7:/MobileCydia.mm diff --git a/MobileCydia.mm b/MobileCydia.mm index a6d5e892..86e6a6f2 100644 --- a/MobileCydia.mm +++ b/MobileCydia.mm @@ -1,5 +1,5 @@ /* Cydia - iPhone UIKit Front-End for Debian APT - * Copyright (C) 2008-2014 Jay Freeman (saurik) + * Copyright (C) 2008-2015 Jay Freeman (saurik) */ /* GNU General Public License, Version 3 {{{ */ @@ -83,8 +83,6 @@ #include #include -#include - #include #include #include @@ -109,11 +107,11 @@ extern "C" { #include #include "Sources.h" -#include +#include "Substrate.hpp" #include "Menes/Menes.h" #include "CyteKit/IndirectDelegate.h" -#include "CyteKit/PerlCompatibleRegEx.hpp" +#include "CyteKit/RegEx.hpp" #include "CyteKit/TableViewCell.h" #include "CyteKit/TabBarController.h" #include "CyteKit/WebScriptObject-Cyte.h" @@ -239,34 +237,6 @@ union SplitHash { }; // }}} -struct Root { - static bool root_; - - Root(bool real) { - _assert(!root_); - root_ = true; - _trace(); - _assert(setreuid(real ? 0 : 501, 0) != -1); - _assert(setregid(real ? 0 : 501, 0) != -1); - } - - ~Root() { - root_ = false; - _trace(); - _assert(setregid(501, 501) != -1); - _assert(setreuid(501, 501) != -1); - } - - operator bool() const { - return true; - } -}; - -bool Root::root_; - -#define _root(real) \ - if (__attribute__((__unused__)) const Root &root = Root(real)) - static NSString *Colon_; NSString *Elision_; static NSString *Error_; @@ -579,14 +549,14 @@ class CYString { cache_ = reinterpret_cast(CFRetain(rhs.cache_)); } - void copy(apr_pool_t *pool) { - char *temp(reinterpret_cast(apr_palloc(pool, size_ + 1))); + void copy(CYPool *pool) { + char *temp(pool->malloc(size_ + 1)); memcpy(temp, data_, size_); temp[size_] = '\0'; data_ = temp; } - void set(apr_pool_t *pool, const char *data, size_t size) { + void set(CYPool *pool, const char *data, size_t size) { if (size == 0) clear(); else { @@ -600,11 +570,11 @@ class CYString { } } - _finline void set(apr_pool_t *pool, const char *data) { + _finline void set(CYPool *pool, const char *data) { set(pool, data, data == NULL ? 0 : strlen(data)); } - _finline void set(apr_pool_t *pool, const std::string &rhs) { + _finline void set(CYPool *pool, const std::string &rhs) { set(pool, rhs.data(), rhs.size()); } @@ -746,7 +716,6 @@ static _H System_; static NSString *SerialNumber_ = nil; static NSString *ChipID_ = nil; static NSString *BBSNum_ = nil; -static _H Token_; static _H UniqueID_; static _H UserAgent_; static _H Product_; @@ -806,19 +775,19 @@ static CFLocaleRef Locale_; static NSArray *Languages_; static CGColorSpaceRef space_; +#define CacheState_ "/var/mobile/Library/Caches/com.saurik.Cydia/CacheState.plist" +#define SavedState_ "/var/mobile/Library/Caches/com.saurik.Cydia/SavedState.plist" + static NSDictionary *SectionMap_; -static NSMutableDictionary *Metadata_; -static _transient NSMutableDictionary *Settings_; -static _transient NSMutableDictionary *Packages_; +static _H Backgrounded_; static _transient NSMutableDictionary *Values_; static _transient NSMutableDictionary *Sections_; _H Sources_; static _transient NSNumber *Version_; -bool Changed_; static time_t now_; bool IsWildcat_; -static CGFloat ScreenScale_; +CGFloat ScreenScale_; static NSString *Idiom_; static _H Firmware_; static NSString *Major_; @@ -826,7 +795,6 @@ static NSString *Major_; static _H SessionData_; static _H HostConfig_; static _H BridgedHosts_; -static _H TokenHosts_; static _H InsecureHosts_; static _H PipelinedHosts_; static _H CachedURLs_; @@ -868,7 +836,7 @@ static _finline const char *StripVersion_(const char *version) { } NSString *LocalizeSection(NSString *section) { - static Pcre title_r("^(.*?) \\((.*)\\)$"); + static RegEx title_r("(.*?) \\((.*)\\)"); if (title_r(section)) { NSString *parent(title_r[1]); NSString *child(title_r[2]); @@ -886,15 +854,15 @@ NSString *Simplify(NSString *title) { const char *data = [title UTF8String]; size_t size = [title lengthOfBytesUsingEncoding:NSUTF8StringEncoding]; - static Pcre square_r("^\\[(.*)\\]$"); + static RegEx square_r("\\[(.*)\\]"); if (square_r(data, size)) return Simplify(square_r[1]); - static Pcre paren_r("^\\((.*)\\)$"); + static RegEx paren_r("\\((.*)\\)"); if (paren_r(data, size)) return Simplify(paren_r[1]); - static Pcre title_r("^(.*?) \\((.*)\\)$"); + static RegEx title_r("(.*?) \\((.*)\\)"); if (title_r(data, size)) return Simplify(title_r[1]); @@ -902,20 +870,6 @@ NSString *Simplify(NSString *title) { } /* }}} */ -NSString *GetLastUpdate() { - NSDate *update = [Metadata_ objectForKey:@"LastUpdate"]; - - if (update == nil) - return UCLocalize("NEVER_OR_UNKNOWN"); - - CFDateFormatterRef formatter = CFDateFormatterCreate(NULL, Locale_, kCFDateFormatterMediumStyle, kCFDateFormatterMediumStyle); - CFStringRef formatted = CFDateFormatterCreateStringWithDate(NULL, formatter, (CFDateRef) update); - - CFRelease(formatter); - - return [(NSString *) formatted autorelease]; -} - bool isSectionVisible(NSString *section) { NSDictionary *metadata([Sections_ objectForKey:(section ?: @"")]); NSNumber *hidden(metadata == nil ? nil : [metadata objectForKey:@"Hidden"]); @@ -1116,9 +1070,10 @@ typedef std::map< unsigned long, _H > SourceMap; @interface Database : NSObject { NSZone *zone_; - apr_pool_t *pool_; + CYPool pool_; unsigned era_; + _H delock_; pkgCacheFile cache_; pkgDepCache::Policy *policy_; @@ -1523,6 +1478,30 @@ static void PackageImport(const void *key, const void *value, void *context) { } // }}} +static NSDate *GetStatusDate() { + return [[[NSFileManager defaultManager] attributesOfItemAtPath:@"/var/lib/dpkg/status" error:NULL] fileModificationDate]; +} + +static void SaveConfig(NSObject *lock) { + @synchronized (lock) { + _trace(); + MetaFile_.Sync(); + _trace(); + } + + CFPreferencesSetMultiple((CFDictionaryRef) [NSDictionary dictionaryWithObjectsAndKeys: + Values_, @"CydiaValues", + Sections_, @"CydiaSections", + (id) Sources_, @"CydiaSources", + Version_, @"CydiaVersion", + nil], NULL, CFSTR("com.saurik.Cydia"), kCFPreferencesCurrentUser, kCFPreferencesCurrentHost); + + if (!CFPreferencesAppSynchronize(CFSTR("com.saurik.Cydia"))) + NSLog(@"CFPreferencesAppSynchronize(com.saurik.Cydia) == false"); + + CydiaWriteSources(); +} + /* Source Class {{{ */ @interface Source : NSObject { unsigned era_; @@ -1554,7 +1533,7 @@ static void PackageImport(const void *key, const void *value, void *context) { _transient NSObject *delegate_; } -- (Source *) initWithMetaIndex:(metaIndex *)index forDatabase:(Database *)database inPool:(apr_pool_t *)pool; +- (Source *) initWithMetaIndex:(metaIndex *)index forDatabase:(Database *)database inPool:(CYPool *)pool; - (NSComparisonResult) compareByName:(Source *)source; @@ -1637,7 +1616,7 @@ static void PackageImport(const void *key, const void *value, void *context) { return index_; } -- (void) setMetaIndex:(metaIndex *)index inPool:(apr_pool_t *)pool { +- (void) setMetaIndex:(metaIndex *)index inPool:(CYPool *)pool { trusted_ = index->IsTrusted(); uri_.set(pool, index->GetURI()); @@ -1713,7 +1692,7 @@ static void PackageImport(const void *key, const void *value, void *context) { authority_ = [url path]; } -- (Source *) initWithMetaIndex:(metaIndex *)index forDatabase:(Database *)database inPool:(apr_pool_t *)pool { +- (Source *) initWithMetaIndex:(metaIndex *)index forDatabase:(Database *)database inPool:(CYPool *)pool { if ((self = [super init]) != nil) { era_ = [database era]; database_ = database; @@ -1785,14 +1764,10 @@ static void PackageImport(const void *key, const void *value, void *context) { if (record_ == nil) return; else if (NSMutableArray *sections = [record_ objectForKey:@"Sections"]) { - if (![sections containsObject:section]) { + if (![sections containsObject:section]) [sections addObject:section]; - Changed_ = true; - } - } else { + } else [record_ setObject:[NSMutableArray arrayWithObject:section] forKey:@"Sections"]; - Changed_ = true; - } } - (bool) addSection:(NSString *)section { @@ -1808,10 +1783,8 @@ static void PackageImport(const void *key, const void *value, void *context) { return; if (NSMutableArray *sections = [record_ objectForKey:@"Sections"]) - if ([sections containsObject:section]) { + if ([sections containsObject:section]) [sections removeObject:section]; - Changed_ = true; - } } - (bool) removeSection:(NSString *)section { @@ -1824,7 +1797,6 @@ static void PackageImport(const void *key, const void *value, void *context) { - (void) _remove { [Sources_ removeObjectForKey:[self key]]; - Changed_ = true; } - (bool) remove { @@ -2108,7 +2080,7 @@ struct ParsedPackage { uint32_t ignored_ : 1; uint32_t pooled_ : 1; - apr_pool_t *pool_; + CYPool *pool_; uint32_t rank_; @@ -2137,8 +2109,8 @@ struct ParsedPackage { _H tags_; } -- (Package *) initWithVersion:(pkgCache::VerIterator)version withZone:(NSZone *)zone inPool:(apr_pool_t *)pool database:(Database *)database; -+ (Package *) packageWithIterator:(pkgCache::PkgIterator)iterator withZone:(NSZone *)zone inPool:(apr_pool_t *)pool database:(Database *)database; +- (Package *) initWithVersion:(pkgCache::VerIterator)version withZone:(NSZone *)zone inPool:(CYPool *)pool database:(Database *)database; ++ (Package *) packageWithIterator:(pkgCache::PkgIterator)iterator withZone:(NSZone *)zone inPool:(CYPool *)pool database:(Database *)database; - (pkgCache::PkgIterator) iterator; - (void) parse; @@ -2355,7 +2327,7 @@ struct PackageNameOrdering : - (void) dealloc { if (!pooled_) - apr_pool_destroy(pool_); + delete pool_; if (parsed_ != NULL) delete parsed_; [super dealloc]; @@ -2538,11 +2510,11 @@ struct PackageNameOrdering : _end } } -- (Package *) initWithVersion:(pkgCache::VerIterator)version withZone:(NSZone *)zone inPool:(apr_pool_t *)pool database:(Database *)database { +- (Package *) initWithVersion:(pkgCache::VerIterator)version withZone:(NSZone *)zone inPool:(CYPool *)pool database:(Database *)database { if ((self = [super init]) != nil) { _profile(Package$initWithVersion) if (pool == NULL) - apr_pool_create(&pool_, NULL); + pool_ = new CYPool(); else { pool_ = pool; pooled_ = true; @@ -2618,7 +2590,7 @@ struct PackageNameOrdering : char *transform; _profile(Package$initWithVersion$Transliterate$apr_palloc) - transform = static_cast(apr_palloc(pool_, length)); + transform = pool_->malloc(length); _end _profile(Package$initWithVersion$Transliterate$u_strToUTF8WithSub$transform) u_strToUTF8WithSub(transform, length, NULL, CollationString_.data(), CollationString_.size(), 0xfffd, NULL, &code); @@ -2717,7 +2689,7 @@ struct PackageNameOrdering : _end } return self; } -+ (Package *) packageWithIterator:(pkgCache::PkgIterator)iterator withZone:(NSZone *)zone inPool:(apr_pool_t *)pool database:(Database *)database { ++ (Package *) packageWithIterator:(pkgCache::PkgIterator)iterator withZone:(NSZone *)zone inPool:(CYPool *)pool database:(Database *)database { pkgCache::VerIterator version; _profile(Package$packageWithIterator$GetCandidateVer) @@ -3131,6 +3103,10 @@ struct PackageNameOrdering : } } - (NSArray *) warnings { +@synchronized (database_) { + if ([database_ era] != era_ || file_.end()) + return nil; + NSMutableArray *warnings([NSMutableArray arrayWithCapacity:4]); const char *name(iterator_.Name()); @@ -3151,6 +3127,7 @@ struct PackageNameOrdering : bool user = false; bool _private = false; bool stash = false; + bool dbstash = false; bool dsstore = false; bool repository = [[self section] isEqualToString:@"Repositories"]; @@ -3165,6 +3142,8 @@ struct PackageNameOrdering : _private = true; else if (!stash && [file isEqualToString:@"/var/stash"]) stash = true; + else if (!dbstash && [file isEqualToString:@"/var/db/stash"]) + dbstash = true; else if (!dsstore && [file hasSuffix:@"/.DS_Store"]) dsstore = true; @@ -3177,19 +3156,21 @@ struct PackageNameOrdering : [warnings addObject:[NSString stringWithFormat:UCLocalize("FILES_INSTALLED_TO"), @"/private"]]; if (stash) [warnings addObject:[NSString stringWithFormat:UCLocalize("FILES_INSTALLED_TO"), @"/var/stash"]]; + if (dbstash) + [warnings addObject:[NSString stringWithFormat:UCLocalize("FILES_INSTALLED_TO"), @"/var/db/stash"]]; if (dsstore) [warnings addObject:[NSString stringWithFormat:UCLocalize("FILES_INSTALLED_TO"), @".DS_Store"]]; } return [warnings count] == 0 ? nil : warnings; -} +} } - (NSArray *) applications { NSString *me([[NSBundle mainBundle] bundleIdentifier]); NSMutableArray *applications([NSMutableArray arrayWithCapacity:2]); - static Pcre application_r("^/Applications/(.*)\\.app/Info.plist$"); + static RegEx application_r("/Applications/(.*)\\.app/Info.plist"); if (NSArray *files = [self files]) for (NSString *file in files) if (application_r(file)) { @@ -3509,7 +3490,6 @@ class CydiaLogCleaner : // XXX: actually implement this thing _assert(false); [self releasePackages]; - apr_pool_destroy(pool_); NSRecycleZone(zone_); [super dealloc]; } @@ -3519,7 +3499,7 @@ class CydiaLogCleaner : std::istream is(&ib); std::string line; - static Pcre finish_r("^finish:([^:]*)$"); + static RegEx finish_r("finish:([^:]*)"); while (std::getline(is, line)) { NSAutoreleasePool *pool([[NSAutoreleasePool alloc] init]); @@ -3546,8 +3526,8 @@ class CydiaLogCleaner : std::istream is(&ib); std::string line; - static Pcre conffile_r("^status: [^ ]* : conffile-prompt : (.*?) *$"); - static Pcre pmstatus_r("^([^:]*):([^:]*):([^:]*):(.*)$"); + static RegEx conffile_r("status: [^ ]* : conffile-prompt : (.*?) *"); + static RegEx pmstatus_r("([^:]*):([^:]*):([^:]*):(.*)"); while (std::getline(is, line)) { NSAutoreleasePool *pool([[NSAutoreleasePool alloc] init]); @@ -3640,7 +3620,6 @@ class CydiaLogCleaner : lock_ = NULL; zone_ = NSCreateZone(1024 * 1024, 256 * 1024, NO); - apr_pool_create(&pool_, NULL); size_t capacity(MetaFile_->active_); if (capacity == 0) @@ -3749,7 +3728,7 @@ class CydiaLogCleaner : lprintf("%c:[%s]\n", warning ? 'W' : 'E', error.c_str()); - static Pcre no_pubkey("^GPG error:.* NO_PUBKEY .*$"); + static RegEx no_pubkey("GPG error:.* NO_PUBKEY .*"); if (warning && no_pubkey(error.c_str())) continue; @@ -3763,6 +3742,26 @@ class CydiaLogCleaner : return [self popErrorWithTitle:title] || !success; } +- (bool) _isEtceteraAptSourcesListDirectoryCydiaListSymbolicallyLinkedToMobileCachesCydiaSourceList { + char target[1024]; + ssize_t length(readlink("/etc/apt/sources.list.d/cydia.list", target, sizeof(target) - 1)); + if (length == -1) + return false; + if (length >= sizeof(target)) + return false; + target[length] = '\0'; + return strcmp(target, "/var/mobile/Library/Caches/com.saurik.Cydia/sources.list") == 0; +} + +- (bool) popErrorWithTitle:(NSString *)title forReadList:(pkgSourceList &)list { + if ([self popErrorWithTitle:title forOperation:list.ReadMainList()]) + return true; + if (![self _isEtceteraAptSourcesListDirectoryCydiaListSymbolicallyLinkedToMobileCachesCydiaSourceList]) + if ([self popErrorWithTitle:title forOperation:list.Read(SOURCES_LIST)]) + return true; + return false; +} + - (void) reloadDataWithInvocation:(NSInvocation *)invocation { @synchronized (self) { ++era_; @@ -3790,7 +3789,8 @@ class CydiaLogCleaner : cache_.Close(); - apr_pool_clear(pool_); + pool_.~CYPool(); + new (&pool_) CYPool(); NSRecycleZone(zone_); zone_ = NSCreateZone(1024 * 1024, 256 * 1024, NO); @@ -3806,18 +3806,18 @@ class CydiaLogCleaner : list_ = new pkgSourceList(); _profile(reloadDataWithInvocation$ReadMainList) - if ([self popErrorWithTitle:title forOperation:list_->ReadMainList()]) + if ([self popErrorWithTitle:title forReadList:*list_]) return; _end _profile(reloadDataWithInvocation$Source$initWithMetaIndex) for (pkgSourceList::const_iterator source = list_->begin(); source != list_->end(); ++source) { - Source *object([[[Source alloc] initWithMetaIndex:*source forDatabase:self inPool:pool_] autorelease]); + Source *object([[[Source alloc] initWithMetaIndex:*source forDatabase:self inPool:&pool_] autorelease]); [sourceList_ addObject:object]; } _end - _root(true) _system->Lock(); + delock_ = GetStatusDate(); _trace(); OpProgress progress; @@ -3854,7 +3854,6 @@ class CydiaLogCleaner : } } - _system->UnLock(); return; } _trace(); @@ -3915,7 +3914,7 @@ class CydiaLogCleaner : _profile(reloadDataWithInvocation$packageWithIterator) for (pkgCache::PkgIterator iterator = cache_->PkgBegin(); !iterator.end(); ++iterator) - if (Package *package = [Package packageWithIterator:iterator withZone:zone_ inPool:pool_ database:self]) + if (Package *package = [Package packageWithIterator:iterator withZone:zone_ inPool:&pool_ database:self]) //packages.push_back(package); CFArrayAppendValue(packages_, CFRetain(package)); _end @@ -3980,9 +3979,9 @@ class CydiaLogCleaner : } } - (void) configure { - NSString *dpkg = [NSString stringWithFormat:@"dpkg --configure -a --status-fd %u", statusfd_]; + NSString *dpkg = [NSString stringWithFormat:@"/usr/libexec/cydo --configure -a --status-fd %u", statusfd_]; _trace(); - _root(true) system([dpkg UTF8String]); + system([dpkg UTF8String]); _trace(); } @@ -4024,7 +4023,7 @@ class CydiaLogCleaner : return false; pkgSourceList list; - if ([self popErrorWithTitle:title forOperation:list.ReadMainList()]) + if ([self popErrorWithTitle:title forReadList:list]) return false; manager_ = (_system->CreatePM(cache_)); @@ -4042,7 +4041,7 @@ class CydiaLogCleaner : NSMutableArray *before = [NSMutableArray arrayWithCapacity:16]; { pkgSourceList list; - if ([self popErrorWithTitle:title forOperation:list.ReadMainList()]) + if ([self popErrorWithTitle:title forReadList:list]) return; for (pkgSourceList::const_iterator source = list.begin(); source != list.end(); ++source) [before addObject:[NSString stringWithUTF8String:(*source)->GetURI().c_str()]]; @@ -4083,9 +4082,27 @@ class CydiaLogCleaner : if (substrate) RestartSubstrate_ = true; - _system->UnLock(); - pkgPackageManager::OrderResult result; - _root(true) result = manager_->DoInstall(statusfd_); + if (![delock_ isEqual:GetStatusDate()]) { + [delegate_ addProgressEventOnMainThread:[CydiaProgressEvent eventWithMessage:UCLocalize("DPKG_LOCKED") ofType:kCydiaProgressEventTypeError] forTask:title]; + return; + } + + delock_ = nil; + + pkgPackageManager::OrderResult result(manager_->DoInstall(statusfd_)); + + NSString *oextended(@"/var/lib/apt/extended_states"); + NSString *nextended(Cache("extended_states")); + + struct stat info; + if (stat([nextended UTF8String], &info) != -1 && (info.st_mode & S_IFMT) == S_IFREG) { + system([[NSString stringWithFormat:@"/usr/libexec/cydia/cydo /bin/mv -f %@ %@", nextended, oextended] UTF8String]); + system([[NSString stringWithFormat:@"/usr/libexec/cydia/cydo /bin/chown 0:0 %@", oextended] UTF8String]); + } + + unlink([nextended UTF8String]); + symlink([oextended UTF8String], [nextended UTF8String]); + if ([self popErrorWithTitle:title]) return; @@ -4101,7 +4118,7 @@ class CydiaLogCleaner : NSMutableArray *after = [NSMutableArray arrayWithCapacity:16]; { pkgSourceList list; - if ([self popErrorWithTitle:title forOperation:list.ReadMainList()]) + if ([self popErrorWithTitle:title forReadList:list]) return; for (pkgSourceList::const_iterator source = list.begin(); source != list.end(); ++source) [after addObject:[NSString stringWithUTF8String:(*source)->GetURI().c_str()]]; @@ -4111,6 +4128,10 @@ class CydiaLogCleaner : [self update]; } +- (bool) delocked { + return ![delock_ isEqual:GetStatusDate()]; +} + - (bool) upgrade { NSString *title(UCLocalize("UPGRADE")); if ([self popErrorWithTitle:title forOperation:pkgDistUpgrade(cache_)]) @@ -4126,7 +4147,7 @@ class CydiaLogCleaner : NSString *title(UCLocalize("REFRESHING_DATA")); pkgSourceList list; - if ([self popErrorWithTitle:title forOperation:list.ReadMainList()]) + if ([self popErrorWithTitle:title forReadList:list]) return; FileFd lock; @@ -4141,8 +4162,10 @@ class CydiaLogCleaner : _error->Discard(); else { [self popErrorWithTitle:title forOperation:success]; - [Metadata_ setObject:[NSDate date] forKey:@"LastUpdate"]; - Changed_ = true; + + [[NSDictionary dictionaryWithObjectsAndKeys: + [NSDate date], @"LastUpdate", + nil] writeToFile:@ CacheState_ atomically:YES]; } [delegate_ performSelectorOnMainThread:@selector(releaseNetworkActivityIndicator) withObject:nil waitUntilDone:YES]; @@ -4213,7 +4236,7 @@ class CydiaLogCleaner : static _H Diversions_; @interface Diversion : NSObject { - Pcre pattern_; + RegEx pattern_; _H key_; _H format_; } @@ -4315,7 +4338,6 @@ static _H Diversions_; @"operator", @"role", @"serial", - @"token", @"version", nil]; } @@ -4394,10 +4416,6 @@ static _H Diversions_; return [NSString stringWithUTF8String:Machine_]; } -- (NSString *) token { - return (id) Token_ ?: [NSNull null]; -} - + (NSString *) webScriptNameForSelector:(SEL)selector { if (false); else if (selector == @selector(addBridgedHost:)) @@ -4410,8 +4428,6 @@ static _H Diversions_; return @"addPipelinedHost"; else if (selector == @selector(addSource:::)) return @"addSource"; - else if (selector == @selector(addTokenHost:)) - return @"addTokenHost"; else if (selector == @selector(addTrivialSource:)) return @"addTrivialSource"; else if (selector == @selector(close)) @@ -4605,8 +4621,6 @@ static _H Diversions_; [Values_ removeObjectForKey:key]; else [Values_ setObject:value forKey:key]; - - [delegate_ performSelectorOnMainThread:@selector(updateValues) withObject:nil waitUntilDone:YES]; } } - (id) getSessionValue:(NSString *)key { @@ -4632,11 +4646,6 @@ static _H Diversions_; [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]) @@ -4721,41 +4730,13 @@ static _H Diversions_; nil]; } -- (NSNumber *) du:(NSString *)path { - NSNumber *value(nil); - - int fds[2]; - _assert(pipe(fds) != -1); +ssize_t DiskUsage(const char *path); - pid_t pid(ExecFork()); - if (pid == 0) { - _assert(dup2(fds[1], 1) != -1); - _assert(close(fds[0]) != -1); - _assert(close(fds[1]) != -1); - /* XXX: this should probably not use du */ - _root(true) execl("/usr/libexec/cydia/du", "du", "-s", [path UTF8String], NULL); - exit(1); - } else { - _assert(close(fds[1]) != -1); - - if (FILE *du = fdopen(fds[0], "r")) { - char line[1024]; - while (fgets(line, sizeof(line), du) != NULL) { - size_t length(strlen(line)); - while (length != 0 && line[length - 1] == '\n') - line[--length] = '\0'; - if (char *tab = strchr(line, '\t')) { - *tab = '\0'; - value = [NSNumber numberWithUnsignedLong:strtoul(line, NULL, 0)]; - } - } - - fclose(du); - } else - _assert(close(fds[0]) != -1); - } ReapZombie(pid); - - return value; +- (NSNumber *) du:(NSString *)path { + ssize_t usage(DiskUsage([path UTF8String])); + if (usage != -1) + usage /= 1024; + return [NSNumber numberWithUnsignedLong:usage]; } - (void) close { @@ -4827,19 +4808,8 @@ static _H Diversions_; [[objc_getClass("UIPasteboard") generalPasteboard] setURL:[NSURL URLWithString:value]]; } -- (void) _setToken:(NSString *)token { - Token_ = token; - - if (token == nil) - [Metadata_ removeObjectForKey:@"Token"]; - else - [Metadata_ setObject:Token_ forKey:@"Token"]; - - Changed_ = true; -} - - (void) setToken:(NSString *)token { - [self performSelectorOnMainThread:@selector(_setToken:) withObject:token waitUntilDone:NO]; + // XXX: the website expects this :/ } - (void) scrollToBottom:(NSNumber *)animated { @@ -4946,6 +4916,10 @@ static _H Diversions_; return [CydiaWebViewController requestWithHeaders:[super webView:view resource:resource willSendRequest:request redirectResponse:response fromDataSource:source]]; } +- (NSURLRequest *) webThreadWebView:(WebView *)view resource:(id)resource willSendRequest:(NSURLRequest *)request redirectResponse:(NSURLResponse *)response fromDataSource:(WebDataSource *)source { + return [CydiaWebViewController requestWithHeaders:[super webThreadWebView:view resource:resource willSendRequest:request redirectResponse:response fromDataSource:source]]; +} + + (NSURLRequest *) requestWithHeaders:(NSURLRequest *)request { NSMutableURLRequest *copy([[request mutableCopy] autorelease]); @@ -4971,23 +4945,12 @@ static _H Diversions_; if (Machine_ != NULL && [copy valueForHTTPHeaderField:@"X-Machine"] == nil) [copy setValue:[NSString stringWithUTF8String:Machine_] forHTTPHeaderField:@"X-Machine"]; - bool bridged; - bool token; - - @synchronized (HostConfig_) { + bool bridged; @synchronized (HostConfig_) { bridged = [BridgedHosts_ containsObject:host]; - token = [TokenHosts_ containsObject:host]; } - if ([url isCydiaSecure]) { - if (bridged) { - if (UniqueID_ != nil && [copy valueForHTTPHeaderField:@"X-Cydia-Id"] == nil) - [copy setValue:UniqueID_ forHTTPHeaderField:@"X-Cydia-Id"]; - } else if (token) { - if (Token_ != nil && [copy valueForHTTPHeaderField:@"X-Cydia-Token"] == nil) - [copy setValue:Token_ forHTTPHeaderField:@"X-Cydia-Token"]; - } - } + if ([url isCydiaSecure] && bridged && UniqueID_ != nil && [copy valueForHTTPHeaderField:@"X-Cydia-Id"] == nil) + [copy setValue:UniqueID_ forHTTPHeaderField:@"X-Cydia-Id"]; return copy; } @@ -5114,7 +5077,7 @@ bool DepSubstrate(const pkgCache::VerIterator &iterator) { if ([context isEqualToString:@"remove"]) { if (button == [alert cancelButtonIndex]) - [self dismissModalViewControllerAnimated:YES]; + [self _doContinue]; else if (button == [alert firstOtherButtonIndex]) { [self performSelector:@selector(complete) withObject:nil afterDelay:0]; } @@ -5241,7 +5204,7 @@ bool DepSubstrate(const pkgCache::VerIterator &iterator) { pkgDepCache::StateCache &state(cache[iterator]); - static Pcre special_r("^(firmware$|gsc\\.|cy\\+)"); + static RegEx special_r("(firmware|gsc\\..*|cy\\+.*)"); if (state.NewInstall()) [installs addObject:name]; @@ -5568,31 +5531,12 @@ bool DepSubstrate(const pkgCache::VerIterator &iterator) { } - (void) reloadSpringBoard { - if (kCFCoreFoundationVersionNumber > 700) { // XXX: iOS 6.x + if (kCFCoreFoundationVersionNumber >= 700) // XXX: iOS 6.x system("/bin/launchctl stop com.apple.backboardd"); - sleep(15); - system("/usr/bin/killall backboardd SpringBoard sbreload"); - return; - } - - pid_t pid(ExecFork()); - if (pid == 0) { - if (setsid() == -1) - perror("setsid"); - - pid_t pid(ExecFork()); - if (pid == 0) { - _root(true) execl("/usr/bin/sbreload", "sbreload", NULL); - perror("sbreload"); - - exit(0); - } ReapZombie(pid); - - exit(0); - } ReapZombie(pid); - + else + system("/bin/launchctl stop com.apple.SpringBoard"); sleep(15); - system("/usr/bin/killall backboardd SpringBoard sbreload"); + system("/usr/bin/killall backboardd SpringBoard"); } - (void) close { @@ -6063,7 +6007,6 @@ bool DepSubstrate(const pkgCache::VerIterator &iterator) { } [metadata setObject:[NSNumber numberWithBool:([switch_ isOn] == NO)] forKey:@"Hidden"]; - Changed_ = true; } - (void) setSection:(Section *)section editing:(BOOL)editing { @@ -6299,10 +6242,13 @@ bool DepSubstrate(const pkgCache::VerIterator &iterator) { if ([context isEqualToString:@"modify"]) { if (button != [sheet cancelButtonIndex]) { - [self _clickButtonWithName:buttons_[button].first]; + if (IsWildcat_) + [self performSelector:@selector(_clickButtonWithName:) withObject:buttons_[button].first afterDelay:0]; + else + [self _clickButtonWithName:buttons_[button].first]; } - [sheet dismissWithClickedButtonIndex:-1 animated:YES]; + [sheet dismissWithClickedButtonIndex:button animated:YES]; } } @@ -6913,7 +6859,7 @@ static void HomeControllerReachabilityCallback(SCNetworkReachabilityRef reachabi [alert setCancelButtonIndex:0]; [alert setMessage: - @"Copyright \u00a9 2008-2014\n" + @"Copyright \u00a9 2008-2015\n" "SaurikIT, LLC\n" "\n" "Jay Freeman (saurik)\n" @@ -6992,10 +6938,6 @@ static void HomeControllerReachabilityCallback(SCNetworkReachabilityRef reachabi } return self; } -- (void) setUpdate:(NSDate *)date { - [self beginUpdate]; -} - - (void) beginUpdate { if (updating_) return; @@ -7106,9 +7048,11 @@ static void HomeControllerReachabilityCallback(SCNetworkReachabilityRef reachabi // on the iPad, this view controller is ALSO visible. :( if (IsWildcat_) - if (UIViewController *top = [self topViewController]) - if (top != visible) - [top reloadData]; + if (UIViewController *modal = [self modalViewController]) + if ([modal modalPresentationStyle] == UIModalPresentationFormSheet) + if (UIViewController *top = [self topViewController]) + if (top != visible) + [top reloadData]; } - (void) unloadData { @@ -7925,8 +7869,7 @@ static void HomeControllerReachabilityCallback(SCNetworkReachabilityRef reachabi pid_t pid(ExecFork()); if (pid == 0) { - FILE *dpkg(nullptr); // XXX: this is due to _root's if - _root(true) dpkg = popen("dpkg --set-selections", "w"); + FILE *dpkg(popen("/usr/libexec/cydo --set-selections", "w")); fwrite(package, strlen(package), 1, dpkg); if (on) @@ -8439,7 +8382,6 @@ static void HomeControllerReachabilityCallback(SCNetworkReachabilityRef reachabi if (source == nil) return; [Sources_ removeObjectForKey:[source key]]; - Changed_ = true; [delegate_ _saveConfig]; [delegate_ reloadDataWithInvocation:nil]; @@ -8602,7 +8544,7 @@ static void HomeControllerReachabilityCallback(SCNetworkReachabilityRef reachabi case 1: { NSString *href = [[alert textField] text]; - static Pcre href_r("^http(s?)://[^# ]*$"); + static RegEx href_r("(http(s?)://|file:///)[^# ]*"); if (!href_r(href)) { UIAlertView *alert = [[[UIAlertView alloc] initWithTitle:[NSString stringWithFormat:Colon_, Error_, UCLocalize("INVALID_URL")] @@ -8916,6 +8858,10 @@ static void HomeControllerReachabilityCallback(SCNetworkReachabilityRef reachabi [super storeCachedResponse:cached forRequest:request]; } +- (void) createDiskCachePath { + [super createDiskCachePath]; +} + @end @interface Cydia : UIApplication < @@ -8926,6 +8872,7 @@ static void HomeControllerReachabilityCallback(SCNetworkReachabilityRef reachabi _H window_; _H tabbar_; _H emulated_; + _H appcache_; _H essential_; _H broken_; @@ -9039,29 +8986,7 @@ static void HomeControllerReachabilityCallback(SCNetworkReachabilityRef reachabi } - (void) _saveConfig { - @synchronized (database_) { - _trace(); - MetaFile_.Sync(); - _trace(); - } - - if (Changed_) { - NSString *error(nil); - - if (NSData *data = [NSPropertyListSerialization dataFromPropertyList:Metadata_ format:NSPropertyListBinaryFormat_v1_0 errorDescription:&error]) { - _trace(); - NSError *error(nil); - _root(true) if (![data writeToFile:@"/var/lib/cydia/metadata.plist" options:NSAtomicWrite error:&error]) - NSLog(@"failure to save metadata data: %@", error); - _trace(); - - Changed_ = false; - } else { - NSLog(@"failure to serialize metadata: %@", error); - } - } - - _root(true) CydiaWriteSources(); + SaveConfig(database_); } // Navigation controller for the queuing badge. @@ -9088,13 +9013,15 @@ static void HomeControllerReachabilityCallback(SCNetworkReachabilityRef reachabi [[navigation tabBarItem] setBadgeValue:(Queuing_ ? UCLocalize("Q_D") : nil)]; } -- (void) _refreshIfPossible:(NSDate *)update { +- (void) _refreshIfPossible { NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init]; + NSDate *update([[NSDictionary dictionaryWithContentsOfFile:@ CacheState_] objectForKey:@"LastUpdate"]); + bool recently = false; if (update != nil) { NSTimeInterval interval([update timeIntervalSinceNow]); - if (interval <= 0 && interval > -(15*60)) + if (interval > -(15*60)) recently = true; } @@ -9112,14 +9039,14 @@ static void HomeControllerReachabilityCallback(SCNetworkReachabilityRef reachabi // We are going to load, so remember that. loaded_ = true; - [tabbar_ performSelectorOnMainThread:@selector(setUpdate:) withObject:update waitUntilDone:NO]; + [tabbar_ performSelectorOnMainThread:@selector(beginUpdate) withObject:nil waitUntilDone:NO]; } [pool release]; } - (void) refreshIfPossible { - [NSThread detachNewThreadSelector:@selector(_refreshIfPossible:) toTarget:self withObject:[Metadata_ objectForKey:@"LastUpdate"]]; + [NSThread detachNewThreadSelector:@selector(_refreshIfPossible) toTarget:self withObject:nil]; } - (void) reloadDataWithInvocation:(NSInvocation *)invocation { @@ -9163,6 +9090,7 @@ _profile(reloadDataWithInvocation) [self setApplicationIconBadgeNumber:0]; } + Queuing_ = false; [self _updateData]; if (hud != nil) @@ -9205,8 +9133,6 @@ _end - (void) presentModalViewController:(UIViewController *)controller force:(BOOL)force { UINavigationController *navigation([[[UINavigationController alloc] initWithRootViewController:controller] autorelease]); - if (IsWildcat_) - [navigation setModalPresentationStyle:UIModalPresentationFormSheet]; UIViewController *parent; if (emulated_ == nil) @@ -9218,6 +9144,8 @@ _end parent = tabbar_; } + if (IsWildcat_) + [navigation setModalPresentationStyle:UIModalPresentationFormSheet]; [parent presentModalViewController:navigation animated:YES]; } @@ -9270,10 +9198,6 @@ _end CydiaAddSource(href, @"./"); } -- (void) updateValues { - Changed_ = true; -} - - (void) resolve { pkgProblemResolver *resolver = [database_ resolver]; @@ -9424,14 +9348,9 @@ _end } else if ([context isEqualToString:@"fixhalf"]) { if (button == [alert cancelButtonIndex]) { @synchronized (self) { - _root(false) for (Package *broken in (id) broken_) { + for (Package *broken in (id) broken_) { [broken remove]; - - NSString *id = [broken id]; - unlink([[NSString stringWithFormat:@"/var/lib/dpkg/info/%@.prerm", id] UTF8String]); - unlink([[NSString stringWithFormat:@"/var/lib/dpkg/info/%@.postrm", id] UTF8String]); - unlink([[NSString stringWithFormat:@"/var/lib/dpkg/info/%@.preinst", id] UTF8String]); - unlink([[NSString stringWithFormat:@"/var/lib/dpkg/info/%@.postinst", id] UTF8String]); + system([[NSString stringWithFormat:@"/usr/libexec/cydia/cydo /usr/libexec/cydia/fixhalf.sh %@", [broken id]] UTF8String]); } [self resolve]; @@ -9511,6 +9430,21 @@ _end return true; } +- (void) suspendReturningToLastApp:(BOOL)returning { + if ([self isSafeToSuspend]) + [super suspendReturningToLastApp:returning]; +} + +- (void) suspend { + if ([self isSafeToSuspend]) + [super suspend]; +} + +- (void) applicationSuspend { + if ([self isSafeToSuspend]) + [super applicationSuspend]; +} + - (void) applicationSuspend:(__GSEvent *)event { if ([self isSafeToSuspend]) [super applicationSuspend:event]; @@ -9687,10 +9621,11 @@ _end } - (void) saveState { - [Metadata_ setObject:[tabbar_ navigationURLCollection] forKey:@"InterfaceState"]; - [Metadata_ setObject:[NSDate date] forKey:@"LastClosed"]; - [Metadata_ setObject:[NSNumber numberWithInt:[tabbar_ selectedIndex]] forKey:@"InterfaceIndex"]; - Changed_ = true; + [[NSDictionary dictionaryWithObjectsAndKeys: + @"InterfaceState", [tabbar_ navigationURLCollection], + @"LastClosed", [NSDate date], + @"InterfaceIndex", [NSNumber numberWithInt:[tabbar_ selectedIndex]], + nil] writeToFile:@ SavedState_ atomically:YES]; [self _saveConfig]; } @@ -9699,8 +9634,37 @@ _end [self saveState]; } +- (void) applicationDidEnterBackground:(UIApplication *)application { + if (kCFCoreFoundationVersionNumber < 1000 && [self isSafeToSuspend]) + return [self terminateWithSuccess]; + Backgrounded_ = [NSDate date]; + [self saveState]; +} + +- (void) applicationWillEnterForeground:(UIApplication *)application { + if (Backgrounded_ == nil) + return; + + NSTimeInterval interval([Backgrounded_ timeIntervalSinceNow]); + + if (interval <= -(30*60)) { + [tabbar_ setSelectedIndex:0]; + [[[tabbar_ viewControllers] objectAtIndex:0] popToRootViewControllerAnimated:NO]; + } + + if (interval <= -(15*60)) { + if (IsReachable("cydia.saurik.com")) { + [tabbar_ beginUpdate]; + [appcache_ reloadURLWithCache:YES]; + } + } + + if ([database_ delocked]) + [self reloadData]; +} + - (void) setConfigurationData:(NSString *)data { - static Pcre conffile_r("^'(.*)' '(.*)' ([01]) ([01])$"); + static RegEx conffile_r("'(.*)' '(.*)' ([01]) ([01])"); if (!conffile_r(data)) { lprintf("E:invalid conffile\n"); @@ -9741,7 +9705,7 @@ _end - (void) stash { [[UIApplication sharedApplication] setStatusBarStyle:UIStatusBarStyleBlackOpaque]; UpdateExternalStatus(1); - _root(true) [self yieldToSelector:@selector(system:) withObject:@"/usr/libexec/cydia/free.sh"]; + [self yieldToSelector:@selector(system:) withObject:@"/usr/libexec/cydia/cydo /usr/libexec/cydia/free.sh"]; UpdateExternalStatus(0); [self removeStashController]; @@ -9843,7 +9807,8 @@ _trace(); broken_ = [NSMutableArray arrayWithCapacity:4]; // XXX: I really need this thing... like, seriously... I'm sorry - [[[AppCacheController alloc] initWithURL:[NSURL URLWithString:[NSString stringWithFormat:@"%@/appcache/", UI_]]] reloadData]; + appcache_ = [[[AppCacheController alloc] initWithURL:[NSURL URLWithString:[NSString stringWithFormat:@"%@/appcache/", UI_]]] autorelease]; + [appcache_ reloadData]; window_ = [[[UIWindow alloc] initWithFrame:[[UIScreen mainScreen] bounds]] autorelease]; [window_ orderFront:self]; @@ -9880,7 +9845,6 @@ _trace(); Stash_("/Library/Wallpaper"); //Stash_("/usr/bin"); Stash_("/usr/include"); - Stash_("/usr/lib/pam"); Stash_("/usr/share"); //Stash_("/var/lib"); @@ -9930,8 +9894,10 @@ _trace(); [self refreshIfPossible]; [self disemulate]; - int savedIndex = [[Metadata_ objectForKey:@"InterfaceIndex"] intValue]; - NSArray *saved = [[[Metadata_ objectForKey:@"InterfaceState"] mutableCopy] autorelease]; + NSDictionary *state([NSDictionary dictionaryWithContentsOfFile:@ SavedState_]); + + int savedIndex = [[state objectForKey:@"InterfaceIndex"] intValue]; + NSArray *saved = [[[state objectForKey:@"InterfaceState"] mutableCopy] autorelease]; int standardIndex = 0; NSArray *standard = [self defaultStartPages]; @@ -9940,10 +9906,9 @@ _trace(); if (saved == nil) valid = NO; - NSDate *closed = [Metadata_ objectForKey:@"LastClosed"]; + NSDate *closed = [state objectForKey:@"LastClosed"]; if (valid && closed != nil) { NSTimeInterval interval([closed timeIntervalSinceNow]); - // XXX: Is 30 minutes the optimal time here? if (interval <= -(30*60)) valid = NO; } @@ -10090,7 +10055,9 @@ MSHook(id, NSUserDefaults$objectForKey$, NSUserDefaults *self, SEL _cmd, NSStrin } int main(int argc, char *argv[]) { - seteuid(501); + int fd(open("/tmp/cydia.log", O_WRONLY | O_APPEND | O_CREAT, 0644)); + dup2(fd, 2); + close(fd); NSAutoreleasePool *pool([[NSAutoreleasePool alloc] init]); @@ -10113,7 +10080,7 @@ int main(int argc, char *argv[]) { Idiom_ = IsWildcat_ ? @"ipad" : @"iphone"; - Pcre pattern("^([0-9]+\\.[0-9]+)"); + RegEx pattern("([0-9]+\\.[0-9]+).*"); if (pattern([device systemVersion])) Firmware_ = pattern[1]; @@ -10125,7 +10092,6 @@ 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]; @@ -10178,7 +10144,7 @@ int main(int argc, char *argv[]) { lang = NULL; if (lang != NULL) { - Pcre pattern("^([a-z][a-z])(?:-[A-Za-z]*)?(_[A-Z][A-Z])?$"); + RegEx pattern("([a-z][a-z])(?:-[A-Za-z]*)?(_[A-Z][A-Z])?"); lang = !pattern(lang) ? NULL : [pattern->*@"%1$@%2$@" UTF8String]; } @@ -10240,9 +10206,6 @@ int main(int argc, char *argv[]) { CollationStarts_ = [NSArray arrayWithObjects:@"a",@"b",@"c",@"d",@"e",@"f",@"g",@"h",@"i",@"j",@"k",@"l",@"m",@"n",@"o",@"p",@"q",@"r",@"s",@"t",@"u",@"v",@"w",@"x",@"y",@"z",@"ʒ",nil]; } /* }}} */ - - apr_app_initialize(&argc, const_cast(&argv), NULL); - /* Parse Arguments {{{ */ bool substrate(false); @@ -10328,55 +10291,59 @@ int main(int argc, char *argv[]) { NSString *agent([NSString stringWithFormat:@"Cydia/%@ CyF/%.2f", Cydia_, kCFCoreFoundationVersionNumber]); - if (Pcre match = Pcre("^[0-9]+(\\.[0-9]+)+", Safari_)) - agent = [NSString stringWithFormat:@"Safari/%@ %@", match[0], agent]; - if (Pcre match = Pcre("^[0-9]+[A-Z][0-9]+[a-z]?", System_)) - agent = [NSString stringWithFormat:@"Mobile/%@ %@", match[0], agent]; - if (Pcre match = Pcre("^[0-9]+(\\.[0-9]+)+", Product_)) - agent = [NSString stringWithFormat:@"Version/%@ %@", match[0], agent]; + if (RegEx match = RegEx("([0-9]+(\\.[0-9]+)+).*", Safari_)) + agent = [NSString stringWithFormat:@"Safari/%@ %@", match[1], agent]; + if (RegEx match = RegEx("([0-9]+[A-Z][0-9]+[a-z]?).*", System_)) + agent = [NSString stringWithFormat:@"Mobile/%@ %@", match[1], agent]; + if (RegEx match = RegEx("([0-9]+(\\.[0-9]+)+).*", Product_)) + agent = [NSString stringWithFormat:@"Version/%@ %@", match[1], agent]; UserAgent_ = agent; /* }}} */ /* Load Database {{{ */ - _trace(); - Metadata_ = [[[NSMutableDictionary alloc] initWithContentsOfFile:@"/var/lib/cydia/metadata.plist"] autorelease]; - _trace(); SectionMap_ = [[[NSDictionary alloc] initWithContentsOfFile:[[NSBundle mainBundle] pathForResource:@"Sections" ofType:@"plist"]] autorelease]; - if (Metadata_ == NULL) - Metadata_ = [NSMutableDictionary dictionaryWithCapacity:2]; - else { - Settings_ = [Metadata_ objectForKey:@"Settings"]; - - Packages_ = [Metadata_ objectForKey:@"Packages"]; - - Values_ = [Metadata_ objectForKey:@"Values"]; - Sections_ = [Metadata_ objectForKey:@"Sections"]; - Sources_ = [Metadata_ objectForKey:@"Sources"]; + _trace(); + mkdir("/var/mobile/Library/Cydia", 0755); + MetaFile_.Open("/var/mobile/Library/Cydia/metadata.cb0"); + _trace(); - Token_ = [Metadata_ objectForKey:@"Token"]; + // XXX: port this to NSUserDefaults when you aren't in such a rush + Values_ = [[[(NSDictionary *) CFPreferencesCopyAppValue(CFSTR("CydiaValues"), CFSTR("com.saurik.Cydia")) autorelease] mutableCopy] autorelease]; + Sections_ = [[[(NSDictionary *) CFPreferencesCopyAppValue(CFSTR("CydiaSections"), CFSTR("com.saurik.Cydia")) autorelease] mutableCopy] autorelease]; + Sources_ = [[[(NSDictionary *) CFPreferencesCopyAppValue(CFSTR("CydiaSources"), CFSTR("com.saurik.Cydia")) autorelease] mutableCopy] autorelease]; + Version_ = [(NSNumber *) CFPreferencesCopyAppValue(CFSTR("CydiaVersion"), CFSTR("com.saurik.Cydia")) autorelease]; - Version_ = [Metadata_ objectForKey:@"Version"]; - } + _trace(); + NSDictionary *metadata([[[NSMutableDictionary alloc] initWithContentsOfFile:@"/var/lib/cydia/metadata.plist"] autorelease]); - if (Values_ == nil) { + if (Values_ == nil) + Values_ = [metadata objectForKey:@"Values"]; + if (Values_ == nil) Values_ = [[[NSMutableDictionary alloc] initWithCapacity:4] autorelease]; - [Metadata_ setObject:Values_ forKey:@"Values"]; - } - if (Sections_ == nil) { + if (Sections_ == nil) + Sections_ = [metadata objectForKey:@"Sections"]; + if (Sections_ == nil) Sections_ = [[[NSMutableDictionary alloc] initWithCapacity:32] autorelease]; - [Metadata_ setObject:Sections_ forKey:@"Sections"]; - } - if (Sources_ == nil) { + if (Sources_ == nil) + Sources_ = [metadata objectForKey:@"Sources"]; + if (Sources_ == nil) Sources_ = [[[NSMutableDictionary alloc] initWithCapacity:0] autorelease]; - [Metadata_ setObject:Sources_ forKey:@"Sources"]; - } - if (Version_ == nil) { + // XXX: this wrong, but in a way that doesn't matter :/ + if (Version_ == nil) + Version_ = [metadata objectForKey:@"Version"]; + if (Version_ == nil) Version_ = [NSNumber numberWithUnsignedInt:0]; - [Metadata_ setObject:Version_ forKey:@"Version"]; + + if (NSDictionary *packages = [metadata objectForKey:@"Packages"]) { + bool fail(false); + CFDictionaryApplyFunction((CFDictionaryRef) packages, &PackageImport, &fail); + _trace(); + if (fail) + NSLog(@"unable to import package preferences... from 2010? oh well :/"); } if ([Version_ unsignedIntValue] == 0) { @@ -10386,64 +10353,36 @@ int main(int argc, char *argv[]) { CydiaAddSource(@"http://repo666.ultrasn0w.com/", @"./"); Version_ = [NSNumber numberWithUnsignedInt:1]; - [Metadata_ setObject:Version_ forKey:@"Version"]; - - [Metadata_ removeObjectForKey:@"LastUpdate"]; - Changed_ = true; + if (NSMutableDictionary *cache = [NSMutableDictionary dictionaryWithContentsOfFile:@ CacheState_]) { + [cache removeObjectForKey:@"LastUpdate"]; + [cache writeToFile:@ CacheState_ atomically:YES]; + } } _H broken([NSMutableArray array]); for (NSString *key in (id) Sources_) if ([key rangeOfCharacterFromSet:[NSCharacterSet characterSetWithCharactersInString:@"# "]].location != NSNotFound) [broken addObject:key]; - if ([broken count] != 0) { + if ([broken count] != 0) for (NSString *key in (id) broken) [Sources_ removeObjectForKey:key]; - Changed_ = true; - } broken = nil; - /* }}} */ - - _root(true) CydiaWriteSources(); - - _trace(); - _root(true) MetaFile_.Open("/var/lib/cydia/metadata.cb0"); - _trace(); + broken = nil; - if (Packages_ != nil) { - bool fail(false); - CFDictionaryApplyFunction((CFDictionaryRef) Packages_, &PackageImport, &fail); - _trace(); - - if (!fail) { - [Metadata_ removeObjectForKey:@"Packages"]; - Packages_ = nil; - Changed_ = true; - } - } + SaveConfig(nil); + system("/usr/libexec/cydia/cydo /bin/rm -f /var/lib/cydia/metadata.plist"); + /* }}} */ Finishes_ = [NSArray arrayWithObjects:@"return", @"reopen", @"restart", @"reload", @"reboot", nil]; -#define MobileSubstrate_(name) \ - if (substrate && access("/Library/MobileSubstrate/DynamicLibraries/" #name ".dylib", F_OK) == 0) { \ - void *handle(dlopen("/Library/MobileSubstrate/DynamicLibraries/" #name ".dylib", RTLD_LAZY | RTLD_GLOBAL)); \ - if (handle == NULL) \ - NSLog(@"%s", dlerror()); \ - } - - MobileSubstrate_(Activator) - MobileSubstrate_(libstatusbar) - MobileSubstrate_(SimulatedKeyEvents) - MobileSubstrate_(WinterBoard) - - /*if (substrate && access("/Library/MobileSubstrate/MobileSubstrate.dylib", F_OK) == 0) - dlopen("/Library/MobileSubstrate/MobileSubstrate.dylib", RTLD_LAZY | RTLD_GLOBAL);*/ + if (kCFCoreFoundationVersionNumber > 1000) + system("/usr/libexec/cydia/cydo /usr/libexec/cydia/setnsfpn /var/lib"); int version([[NSString stringWithContentsOfFile:@"/var/lib/cydia/firmware.ver"] intValue]); if (access("/User", F_OK) != 0 || version != 6) { _trace(); - _root(true) system("/usr/libexec/cydia/firmware.sh"); + system("/usr/libexec/cydia/cydo /usr/libexec/cydia/firmware.sh"); _trace(); } @@ -10471,10 +10410,19 @@ int main(int argc, char *argv[]) { mkdir([Cache("archives/partial") UTF8String], 0755); _config->Set("Dir::Cache", [Cache_ UTF8String]); + symlink("/var/lib/apt/extended_states", [Cache("extended_states") UTF8String]); + _config->Set("Dir::State", [Cache_ UTF8String]); + mkdir([Cache("lists") UTF8String], 0755); mkdir([Cache("lists/partial") UTF8String], 0755); mkdir([Cache("periodic") UTF8String], 0755); _config->Set("Dir::State::Lists", [Cache("lists") UTF8String]); + + std::string logs("/var/mobile/Library/Logs/Cydia"); + mkdir(logs.c_str(), 0755); + _config->Set("Dir::Log::Terminal", logs + "/apt.log"); + + _config->Set("Dir::Bin::dpkg", "/usr/libexec/cydia/cydo"); /* }}} */ /* Color Choices {{{ */ space_ = CGColorSpaceCreateDeviceRGB();