X-Git-Url: https://git.saurik.com/cydia.git/blobdiff_plain/f26c90b114a5fdb3b701cd7e73ce9328a93eaeda..5ddde60fb69b9b9d2466044e208977981d2e1fcb:/MobileCydia.mm diff --git a/MobileCydia.mm b/MobileCydia.mm index 612cd23e..47033741 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 {{{ */ @@ -53,18 +53,19 @@ #include #include -#include #include +#include #include #include #include #include -#include +#include "fdstream.hpp" #undef ABS +#include "apt.h" #include #include #include @@ -90,6 +91,7 @@ #include #include +#include #include #include #include @@ -110,7 +112,8 @@ extern "C" { #include "Substrate.hpp" #include "Menes/Menes.h" -#include "CyteKit/IndirectDelegate.h" +#include "CyteKit/Application.h" +#include "CyteKit/NavigationController.h" #include "CyteKit/RegEx.hpp" #include "CyteKit/TableViewCell.h" #include "CyteKit/TabBarController.h" @@ -237,34 +240,15 @@ union SplitHash { }; // }}} -static void setreugid(uid_t uid, gid_t gid) { - _assert(setreuid(uid, uid) != -1); - _assert(setregid(gid, gid) != -1); -} - -static void setreguid(gid_t gid, uid_t uid) { - _assert(setregid(gid, gid) != -1); - _assert(setreuid(uid, uid) != -1); -} - -struct Root { - Root() { - _trace(); - setreugid(0, 0); - _assert(pthread_setugid_np(0, 0) != -1); - setreguid(501, 501); - } - - ~Root() { - _trace(); - setreugid(0, 0); - _assert(pthread_setugid_np(KAUTH_UID_NONE, KAUTH_GID_NONE) != -1); - setreguid(501, 501); - } -}; - -#define _root(code) \ - ({ Root _root; code; }) +@implementation NSDictionary (Cydia) +- (id) invokeUndefinedMethodFromWebScript:(NSString *)name withArguments:(NSArray *)arguments { + if (false); + else if ([name isEqualToString:@"get"]) + return [self objectForKey:[arguments objectAtIndex:0]]; + else if ([name isEqualToString:@"keys"]) + return [self allKeys]; + return nil; +} @end static NSString *Colon_; NSString *Elision_; @@ -276,6 +260,7 @@ static NSString *Cache_; [NSString stringWithFormat:@"%@/%s", Cache_, file] static void (*$SBSSetInterceptsMenuButtonForever)(bool); +static NSData *(*$SBSCopyIconImagePNGDataForDisplayIdentifier)(NSString *); static CFStringRef (*$MGCopyAnswer)(CFStringRef); @@ -319,13 +304,8 @@ static _finline NSString *CydiaURL(NSString *path) { return [[NSString stringWithUTF8String:page] stringByAppendingString:path]; } -static void ReapZombie(pid_t pid) { - int status; - wait: - if (waitpid(pid, &status, 0) == -1) - if (errno == EINTR) - goto wait; - else _assert(false); +static NSString *ShellEscape(NSString *value) { + return [NSString stringWithFormat:@"'%@'", [value stringByReplacingOccurrencesOfString:@"'" withString:@"'\\''"]]; } static _finline void UpdateExternalStatus(uint64_t newStatus) { @@ -349,53 +329,47 @@ static const CFStringCompareFlags LaxCompareFlags_ = kCFCompareNumerically | kCF /* Insertion Sort {{{ */ -CFIndex SKBSearch_(const void *element, CFIndex elementSize, const void *list, CFIndex count, CFComparatorFunction comparator, void *context) { - const char *ptr = (const char *)list; - while (0 < count) { - CFIndex half = count / 2; - const char *probe = ptr + elementSize * half; - CFComparisonResult cr = comparator(element, probe, context); - if (0 == cr) return (probe - (const char *)list) / elementSize; - ptr = (cr < 0) ? ptr : probe + elementSize; - count = (cr < 0) ? half : (half + (count & 1) - 1); - } - return (ptr - (const char *)list) / elementSize; -} - -CFIndex CFBSearch_(const void *element, CFIndex elementSize, const void *list, CFIndex count, CFComparatorFunction comparator, void *context) { +template +size_t CFBSearch_(const Type_ &element, const void *list, size_t count, CFComparisonResult (*comparator)(Type_, Type_, void *), void *context) { const char *ptr = (const char *)list; while (0 < count) { - CFIndex half = count / 2; - const char *probe = ptr + elementSize * half; - CFComparisonResult cr = comparator(element, probe, context); - if (0 == cr) return (probe - (const char *)list) / elementSize; - ptr = (cr < 0) ? ptr : probe + elementSize; + size_t half = count / 2; + const char *probe = ptr + sizeof(Type_) * half; + CFComparisonResult cr = comparator(element, * (const Type_ *) probe, context); + if (0 == cr) return (probe - (const char *)list) / sizeof(Type_); + ptr = (cr < 0) ? ptr : probe + sizeof(Type_); count = (cr < 0) ? half : (half + (count & 1) - 1); } - return (ptr - (const char *)list) / elementSize; + return (ptr - (const char *)list) / sizeof(Type_); } -void CFArrayInsertionSortValues(CFMutableArrayRef array, CFRange range, CFComparatorFunction comparator, void *context) { - if (range.length == 0) +template +void CYArrayInsertionSortValues(Type_ *values, size_t length, CFComparisonResult (*comparator)(Type_, Type_, void *), void *context) { + if (length == 0) return; - const void **values(new const void *[range.length]); - CFArrayGetValues(array, range, values); #if HistogramInsertionSort > 0 - uint32_t total(0), *offsets(new uint32_t[range.length]); + uint32_t total(0), *offsets(new uint32_t[length]); #endif - for (CFIndex index(1); index != range.length; ++index) { - const void *value(values[index]); - //CFIndex correct(SKBSearch_(&value, sizeof(const void *), values, index, comparator, context)); - CFIndex correct(index); + for (size_t index(1); index != length; ++index) { + Type_ value(values[index]); +#if 0 + size_t correct(CFBSearch_(value, values, index, comparator, context)); +#else + size_t correct(index); while (comparator(value, values[correct - 1], context) == kCFCompareLessThan) { #if HistogramInsertionSort > 1 NSLog(@"%@ < %@", value, values[correct - 1]); #endif if (--correct == 0) break; + if (index - correct >= 8) { + correct = CFBSearch_(value, values, correct, comparator, context); + break; + } } +#endif if (correct != index) { size_t offset(index - correct); #if HistogramInsertionSort @@ -409,11 +383,8 @@ void CFArrayInsertionSortValues(CFMutableArrayRef array, CFRange range, CFCompar } } - CFArrayReplaceValues(array, range, values, range.length); - delete [] values; - #if HistogramInsertionSort > 0 - for (CFIndex index(0); index != range.length; ++index) + for (size_t index(0); index != range.length; ++index) if (offsets[index] != 0) NSLog(@"Insertion Displacement [%u]: %u", index, offsets[index]); NSLog(@"Average Insertion Displacement: %f", double(total) / range.length); @@ -522,6 +493,10 @@ static _finline CFStringRef CYStringCreate(const char *data, size_t size) { CFStringCreateWithBytesNoCopy(kCFAllocatorDefault, reinterpret_cast(data), size, kCFStringEncodingISOLatin1, NO, kCFAllocatorNull); } +static _finline CFStringRef CYStringCreate(const std::string &data) { + return CYStringCreate(data.data(), data.size()); +} + static _finline CFStringRef CYStringCreate(const char *data) { return CYStringCreate(data, strlen(data)); } @@ -707,7 +682,6 @@ static const NSString *UI_; static int Finish_; static bool RestartSubstrate_; -static bool UpgradeCydia_; static NSArray *Finishes_; #define SpringBoard_ "/System/Library/LaunchDaemons/com.apple.SpringBoard.plist" @@ -934,6 +908,25 @@ static NSString *CYHex(NSData *data, bool reverse = false) { return [NSString stringWithUTF8String:string]; } +static NSString *VerifySource(NSString *href) { + static RegEx href_r("(http(s?)://|file:///)[^# ]*"); + if (!href_r(href)) { + [[[[UIAlertView alloc] + initWithTitle:[NSString stringWithFormat:Colon_, Error_, UCLocalize("INVALID_URL")] + message:UCLocalize("INVALID_URL_EX") + delegate:nil + cancelButtonTitle:UCLocalize("OK") + otherButtonTitles:nil + ] autorelease] show]; + + return nil; + } + + if (![href hasSuffix:@"/"]) + href = [href stringByAppendingString:@"/"]; + return href; +} + @class Cydia; /* Delegate Prototypes {{{ */ @@ -977,7 +970,7 @@ static NSString *CYHex(NSData *data, bool reverse = false) { - (void) _saveConfig; - (void) syncData; - (void) addSource:(NSDictionary *)source; -- (void) addTrivialSource:(NSString *)href; +- (BOOL) addTrivialSource:(NSString *)href; - (UIProgressHUD *) addProgressHUD; - (void) removeProgressHUD:(UIProgressHUD *)hud; - (void) showActionSheet:(UIActionSheet *)sheet fromItem:(UIBarButtonItem *)item; @@ -1117,7 +1110,7 @@ typedef std::map< unsigned long, _H > SourceMap; SourceMap sourceMap_; _H sourceList_; - CFMutableArrayRef packages_; + _H packages_; _transient NSObject *delegate_; _transient NSObject *progress_; @@ -1133,6 +1126,7 @@ typedef std::map< unsigned long, _H > SourceMap; + (Database *) sharedInstance; - (unsigned) era; +- (bool) hasPackages; - (void) _readCydia:(NSNumber *)fd; - (void) _readStatus:(NSNumber *)fd; @@ -1418,14 +1412,14 @@ struct PackageValue : char version_[8]; char name_[]; -}; +} _packed; struct MetaValue : Cytore::Block { uint32_t active_; Cytore::Offset packages_[1 << 16]; -}; +} _packed; static Cytore::File MetaFile_; // }}} @@ -2140,6 +2134,8 @@ struct ParsedPackage { } - (Package *) initWithVersion:(pkgCache::VerIterator)version withZone:(NSZone *)zone inPool:(CYPool *)pool database:(Database *)database; ++ (Package *) newPackageWithIterator:(pkgCache::PkgIterator)iterator 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; @@ -2171,7 +2167,6 @@ struct ParsedPackage { - (NSString *) installed; - (BOOL) uninstalled; -- (BOOL) valid; - (BOOL) upgradableAndEssential:(BOOL)essential; - (BOOL) essential; - (BOOL) broken; @@ -2518,15 +2513,7 @@ struct PackageNameOrdering : _end _profile(Package$parse$Tagline) - const char *start, *end; - if (parser->ShortDesc(start, end)) { - const char *stop(reinterpret_cast(memchr(start, '\n', end - start))); - if (stop == NULL) - stop = end; - while (stop != start && stop[-1] == '\r') - --stop; - parsed->tagline_.set(pool_, start, stop - start); - } + parsed->tagline_.set(pool_, parser->ShortDesc()); _end _profile(Package$parse$Retain) @@ -2555,20 +2542,15 @@ struct PackageNameOrdering : version_ = version; - pkgCache::PkgIterator iterator(version.ParentPkg()); + pkgCache::PkgIterator iterator(version_.ParentPkg()); iterator_ = iterator; _profile(Package$initWithVersion$Version) - if (!version_.end()) - file_ = version_.FileList(); - else { - pkgCache &cache([database_ cache]); - file_ = pkgCache::VerFileIterator(cache, cache.VerFileP); - } + file_ = version_.FileList(); _end _profile(Package$initWithVersion$Cache) - name_.set(NULL, iterator.Display()); + name_.set(NULL, version_.Display()); latest_.set(NULL, StripVersion_(version_.VerStr())); @@ -2632,7 +2614,11 @@ struct PackageNameOrdering : } while (false); _end _profile(Package$initWithVersion$Tags) +#ifdef __arm64__ + pkgCache::TagIterator tag(version_.TagList()); +#else pkgCache::TagIterator tag(iterator.TagList()); +#endif if (!tag.end()) { tags_ = [NSMutableArray arrayWithCapacity:8]; @@ -2719,7 +2705,7 @@ struct PackageNameOrdering : _end } return self; } -+ (Package *) packageWithIterator:(pkgCache::PkgIterator)iterator withZone:(NSZone *)zone inPool:(CYPool *)pool database:(Database *)database { ++ (Package *) newPackageWithIterator:(pkgCache::PkgIterator)iterator withZone:(NSZone *)zone inPool:(CYPool *)pool database:(Database *)database { pkgCache::VerIterator version; _profile(Package$packageWithIterator$GetCandidateVer) @@ -2744,17 +2730,33 @@ struct PackageNameOrdering : ]; _end - _profile(Package$packageWithIterator$Autorelease) - package = [package autorelease]; - _end - return package; } +// XXX: just in case a Cydia extension is using this (I bet this is unlikely, though, due to CYPool?) ++ (Package *) packageWithIterator:(pkgCache::PkgIterator)iterator withZone:(NSZone *)zone inPool:(CYPool *)pool database:(Database *)database { + return [[self newPackageWithIterator:iterator withZone:zone inPool:pool database:database] autorelease]; +} + - (pkgCache::PkgIterator) iterator { return iterator_; } +- (NSArray *) downgrades { + NSMutableArray *versions([NSMutableArray arrayWithCapacity:4]); + + for (auto version(iterator_.VersionList()); !version.end(); ++version) { + if (version == version_) + continue; + Package *package([[[Package allocWithZone:NULL] initWithVersion:version withZone:NULL inPool:NULL database:database_] autorelease]); + if ([package source] == nil) + continue; + [versions addObject:package]; + } + + return versions; +} + - (NSString *) section { if (section$_ == nil) { if (section_ == NULL) @@ -2774,7 +2776,10 @@ struct PackageNameOrdering : } - (NSString *) longSection { - return LocalizeSection([self section]); + if (NSString *section = [self section]) + return LocalizeSection(section); + else + return nil; } - (NSString *) shortSection { @@ -2844,23 +2849,12 @@ struct PackageNameOrdering : @synchronized (database_) { pkgRecords::Parser &parser([database_ records]->Lookup(file_)); - - const char *start, *end; - if (!parser.ShortDesc(start, end)) + std::string value(parser.ShortDesc()); + if (value.empty()) return nil; - - if (end - start > 200) - end = start + 200; - - /* - if (const char *stop = reinterpret_cast(memchr(start, '\n', end - start))) - end = stop; - - while (end != start && end[-1] == '\r') - --end; - */ - - return [(id) CYStringCreate(start, end - start) autorelease]; + if (value.size() > 200) + value.resize(200); + return [(id) CYStringCreate(value) autorelease]; } } - (unichar) index { @@ -2912,17 +2906,13 @@ struct PackageNameOrdering : return installed_.empty(); } -- (BOOL) valid { - return !version_.end(); -} - - (BOOL) upgradableAndEssential:(BOOL)essential { _profile(Package$upgradableAndEssential) pkgCache::VerIterator current(iterator_.CurrentVer()); if (current.end()) return essential && essential_; else - return !version_.end() && version_ != current; + return version_ != current; _end } @@ -3205,8 +3195,10 @@ struct PackageNameOrdering : for (NSString *file in files) if (application_r(file)) { NSDictionary *info([NSDictionary dictionaryWithContentsOfFile:file]); + if (info == nil) + continue; NSString *id([info objectForKey:@"CFBundleIdentifier"]); - if ([id isEqualToString:me]) + if (id == nil || [id isEqualToString:me]) continue; NSString *display([info objectForKey:@"CFBundleDisplayName"]); @@ -3330,8 +3322,8 @@ struct PackageNameOrdering : } - (void) setIndex:(size_t)index { - if (metadata_->index_ != index) - metadata_->index_ = index; + if (metadata_->index_ != index + 1) + metadata_->index_ = index + 1; } - (CYString &) cyname { @@ -3350,6 +3342,9 @@ struct PackageNameOrdering : - (void) clear { @synchronized (database_) { + if ([database_ era] != era_ || file_.end()) + return; + pkgProblemResolver *resolver = [database_ resolver]; resolver->Clear(iterator_); @@ -3360,11 +3355,15 @@ struct PackageNameOrdering : - (void) install { @synchronized (database_) { + if ([database_ era] != era_ || file_.end()) + return; + pkgProblemResolver *resolver = [database_ resolver]; resolver->Clear(iterator_); resolver->Protect(iterator_); pkgCacheFile &cache([database_ cache]); + cache->SetCandidateVersion(version_); cache->SetReInstall(iterator_, false); cache->MarkInstall(iterator_, false); @@ -3375,6 +3374,9 @@ struct PackageNameOrdering : - (void) remove { @synchronized (database_) { + if ([database_ era] != era_ || file_.end()) + return; + pkgProblemResolver *resolver = [database_ resolver]; resolver->Clear(iterator_); resolver->Remove(iterator_); @@ -3512,8 +3514,11 @@ class CydiaLogCleaner : } - (void) releasePackages { - CFArrayApplyFunction(packages_, CFRangeMake(0, CFArrayGetCount(packages_)), reinterpret_cast(&CFRelease), NULL); - CFArrayRemoveAllValues(packages_); + packages_ = nil; +} + +- (bool) hasPackages { + return [packages_ count] != 0; } - (void) dealloc { @@ -3525,8 +3530,7 @@ class CydiaLogCleaner : } - (void) _readCydia:(NSNumber *)fd { - __gnu_cxx::stdio_filebuf ib([fd intValue], std::ios::in); - std::istream is(&ib); + boost::fdistream is([fd intValue]); std::string line; static RegEx finish_r("finish:([^:]*)"); @@ -3552,8 +3556,7 @@ class CydiaLogCleaner : } - (void) _readStatus:(NSNumber *)fd { - __gnu_cxx::stdio_filebuf ib([fd intValue], std::ios::in); - std::istream is(&ib); + boost::fdistream is([fd intValue]); std::string line; static RegEx conffile_r("status: [^ ]* : conffile-prompt : (.*?) *"); @@ -3609,8 +3612,7 @@ class CydiaLogCleaner : } - (void) _readOutput:(NSNumber *)fd { - __gnu_cxx::stdio_filebuf ib([fd intValue], std::ios::in); - std::istream is(&ib); + boost::fdistream is([fd intValue]); std::string line; while (std::getline(is, line)) { @@ -3637,8 +3639,12 @@ class CydiaLogCleaner : @synchronized (self) { if (static_cast(cache_) == NULL) return nil; - pkgCache::PkgIterator iterator(cache_->FindPkg([name UTF8String])); - return iterator.end() ? nil : [Package packageWithIterator:iterator withZone:NULL inPool:NULL database:self]; + pkgCache::PkgIterator iterator(cache_->FindPkg([name UTF8String] +#ifdef __arm64__ + , "any" +#endif + )); + return iterator.end() ? nil : [[Package newPackageWithIterator:iterator withZone:NULL inPool:NULL database:self] autorelease]; } } - (id) init { @@ -3651,13 +3657,6 @@ class CydiaLogCleaner : zone_ = NSCreateZone(1024 * 1024, 256 * 1024, NO); - size_t capacity(MetaFile_->active_); - if (capacity == 0) - capacity = 16384; - else - capacity += 1024; - - packages_ = CFArrayCreateMutable(kCFAllocatorDefault, capacity, NULL); sourceList_ = [NSMutableArray arrayWithCapacity:16]; int fds[2]; @@ -3726,7 +3725,7 @@ class CydiaLogCleaner : } - (NSArray *) packages { - return (NSArray *) packages_; + return packages_; } - (NSArray *) sources { @@ -3775,9 +3774,26 @@ class CydiaLogCleaner : - (bool) popErrorWithTitle:(NSString *)title forReadList:(pkgSourceList &)list { if ([self popErrorWithTitle:title forOperation:list.ReadMainList()]) return true; - if ([self popErrorWithTitle:title forOperation:list.Read(SOURCES_LIST)]) - return true; return false; + + list.Reset(); + + bool error(false); + + if (access("/etc/apt/sources.list", F_OK) == 0) + error |= [self popErrorWithTitle:title forOperation:list.ReadAppend("/etc/apt/sources.list")]; + + std::string base("/etc/apt/sources.list.d"); + if (DIR *sources = opendir(base.c_str())) { + while (dirent *source = readdir(sources)) + if (source->d_name[0] != '.' && source->d_namlen > 5 && strcmp(source->d_name + source->d_namlen - 5, ".list") == 0 && strcmp(source->d_name, "cydia.list") != 0) + error |= [self popErrorWithTitle:title forOperation:list.ReadAppend((base + "/" + source->d_name).c_str())]; + closedir(sources); + } + + error |= [self popErrorWithTitle:title forOperation:list.ReadAppend(SOURCES_LIST)]; + + return error; } - (void) reloadDataWithInvocation:(NSInvocation *)invocation { @@ -3835,17 +3851,16 @@ class CydiaLogCleaner : } _end - delock_ = GetStatusDate(); - _trace(); OpProgress progress; bool opened; open: + delock_ = GetStatusDate(); _profile(reloadDataWithInvocation$pkgCacheFile) opened = cache_.Open(progress, false); _end if (!opened) { - // XXX: what if there are errors, but Open() == true? this should be merged with popError: + // XXX: this block should probably be merged with popError: in some way while (!_error->empty()) { std::string error; bool warning(!_error->PopMessage(error)); @@ -3873,7 +3888,8 @@ class CydiaLogCleaner : } return; - } + } else if ([self popErrorWithTitle:title forOperation:true]) + return; _trace(); unlink("/tmp/cydia.chk"); @@ -3926,40 +3942,88 @@ class CydiaLogCleaner : } { - /*std::vector packages; - packages.reserve(std::max(10000U, [packages_ count] + 1000)); - packages_ = nil;*/ + size_t capacity(MetaFile_->active_); + if (capacity == 0) + capacity = 128*1024; + else + capacity += 1024; + + std::vector packages; + packages.reserve(capacity); + size_t lost(0); + size_t last(0); _profile(reloadDataWithInvocation$packageWithIterator) for (pkgCache::PkgIterator iterator = cache_->PkgBegin(); !iterator.end(); ++iterator) - if (Package *package = [Package packageWithIterator:iterator withZone:zone_ inPool:&pool_ database:self]) - //packages.push_back(package); - CFArrayAppendValue(packages_, CFRetain(package)); + if (Package *package = [Package newPackageWithIterator:iterator withZone:zone_ inPool:&pool_ database:self]) { + if (unsigned index = package.metadata->index_) { + --index; + if (packages.size() == index) { + packages.push_back(package); + } else if (packages.size() <= index) { + packages.resize(index + 1, nil); + packages[index] = package; + continue; + } else { + std::swap(package, packages[index]); + if (package != nil) + goto lost; + if (last != index) + continue; + } + } else lost: { + ++lost; + if (last == packages.size()) { + packages.push_back(package); + ++last; + } else { + packages[last] = package; + ++last; + } + } + + for (; last != packages.size(); ++last) + if (packages[last] == nil) + break; + } _end + for (size_t next(last + 1); last != packages.size(); ++last, ++next) { + while (true) { + if (next == packages.size()) + goto done; + if (packages[next] != nil) + break; + ++next; + } - /*if (packages.empty()) - packages_ = [[NSArray alloc] init]; - else - packages_ = [[NSArray alloc] initWithObjects:&packages.front() count:packages.size()]; - _trace();*/ + std::swap(packages[last], packages[next]); + } done:; - _profile(reloadDataWithInvocation$radix$8) - [(NSMutableArray *) packages_ radixSortUsingFunction:reinterpret_cast(&PackagePrefixRadix) withContext:reinterpret_cast(8)]; - _end + packages.resize(last); - _profile(reloadDataWithInvocation$radix$4) - [(NSMutableArray *) packages_ radixSortUsingFunction:reinterpret_cast(&PackagePrefixRadix) withContext:reinterpret_cast(4)]; - _end + if (lost > 128) { + NSLog(@"lost = %zu", lost); - _profile(reloadDataWithInvocation$radix$0) - [(NSMutableArray *) packages_ radixSortUsingFunction:reinterpret_cast(&PackagePrefixRadix) withContext:reinterpret_cast(0)]; - _end + _profile(reloadDataWithInvocation$radix$8) + CYRadixSortUsingFunction(packages.data(), packages.size(), reinterpret_cast(&PackagePrefixRadix), reinterpret_cast(8)); + _end + + _profile(reloadDataWithInvocation$radix$4) + CYRadixSortUsingFunction(packages.data(), packages.size(), reinterpret_cast(&PackagePrefixRadix), reinterpret_cast(4)); + _end + + _profile(reloadDataWithInvocation$radix$0) + CYRadixSortUsingFunction(packages.data(), packages.size(), reinterpret_cast(&PackagePrefixRadix), reinterpret_cast(0)); + _end + } _profile(reloadDataWithInvocation$insertion) - CFArrayInsertionSortValues(packages_, CFRangeMake(0, CFArrayGetCount(packages_)), reinterpret_cast(&PackageNameCompare), NULL); + CYArrayInsertionSortValues(packages.data(), packages.size(), &PackageNameCompare, NULL); _end + packages_ = [[[NSArray alloc] initWithObjects:packages.data() count:packages.size()] autorelease]; + /*_profile(reloadDataWithInvocation$CFQSortArray) CFQSortArray(&packages.front(), packages.size(), sizeof(packages.front()), reinterpret_cast(&PackageNameCompare_), NULL); _end*/ @@ -3976,11 +4040,12 @@ class CydiaLogCleaner : [packages_ sortUsingFunction:reinterpret_cast(&PackageNameCompare) context:NULL]; _end*/ - - size_t count(CFArrayGetCount(packages_)); - MetaFile_->active_ = count; - for (size_t index(0); index != count; ++index) - [(Package *) CFArrayGetValueAtIndex(packages_, index) setIndex:index]; + MetaFile_->active_ = packages.size(); + for (size_t index(0), count(packages.size()); index != count; ++index) { + auto package(packages[index]); + [package setIndex:index]; + [package release]; + } } } } @@ -4108,6 +4173,17 @@ class CydiaLogCleaner : 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/cp --remove-destination %@ %@", ShellEscape(nextended), ShellEscape(oextended)] UTF8String]); + + unlink([nextended UTF8String]); + symlink([oextended UTF8String], [nextended UTF8String]); + if ([self popErrorWithTitle:title]) return; @@ -4297,7 +4373,7 @@ static _H Diversions_; _transient id delegate_; } -- (id) initWithDelegate:(IndirectDelegate *)indirect; +- (id) initWithDelegate:(CyteWebViewController *)indirect; @end @@ -4317,9 +4393,9 @@ static _H Diversions_; /* Web Scripting {{{ */ @implementation CydiaObject -- (id) initWithDelegate:(IndirectDelegate *)indirect { +- (id) initWithDelegate:(CyteWebViewController *)indirect { if ((self = [super init]) != nil) { - indirect_ = (CyteWebViewController *) indirect; + indirect_ = indirect; } return self; } @@ -4329,8 +4405,10 @@ static _H Diversions_; + (NSArray *) _attributeKeys { return [NSArray arrayWithObjects: + @"bittage", @"bbsnum", @"build", + @"cells", @"coreFoundationVersionNumber", @"device", @"ecid", @@ -4359,6 +4437,17 @@ static _H Diversions_; return Cydia_; } +- (unsigned) bittage { +#if 0 +#elif defined(__arm64__) + return 64; +#elif defined(__arm__) + return 32; +#else + return 0; +#endif +} + - (NSString *) build { return System_; } @@ -4383,6 +4472,29 @@ static _H Diversions_; return (id) Idiom_ ?: [NSNull null]; } +- (NSArray *) cells { + auto *$_CTServerConnectionCreate(reinterpret_cast(dlsym(RTLD_DEFAULT, "_CTServerConnectionCreate"))); + if ($_CTServerConnectionCreate == NULL) + return nil; + + struct CTResult { int flag; int error; }; + auto *$_CTServerConnectionCellMonitorCopyCellInfo(reinterpret_cast(dlsym(RTLD_DEFAULT, "_CTServerConnectionCellMonitorCopyCellInfo"))); + if ($_CTServerConnectionCellMonitorCopyCellInfo == NULL) + return nil; + + _H connection($_CTServerConnectionCreate(NULL, NULL, NULL), true); + if (connection == nil) + return nil; + + int count(0); + CFArrayRef cells(NULL); + auto result($_CTServerConnectionCellMonitorCopyCellInfo(connection, &count, &cells)); + if (result.flag != 0) + return nil; + + return [(NSArray *) cells autorelease]; +} + - (NSString *) mcc { if (CFStringRef (*$CTSIMSupportCopyMobileSubscriberCountryCode)(CFAllocatorRef) = reinterpret_cast(dlsym(RTLD_DEFAULT, "CTSIMSupportCopyMobileSubscriberCountryCode"))) return [(NSString *) (*$CTSIMSupportCopyMobileSubscriberCountryCode)(kCFAllocatorDefault) autorelease]; @@ -4445,6 +4557,10 @@ static _H Diversions_; return @"getAllSources"; else if (selector == @selector(getApplicationInfo:value:)) return @"getApplicationInfoValue"; + else if (selector == @selector(getDisplayIdentifiers)) + return @"getDisplayIdentifiers"; + else if (selector == @selector(getLocalizedNameForDisplayIdentifier:)) + return @"getLocalizedNameForDisplayIdentifier"; else if (selector == @selector(getKernelNumber:)) return @"getKernelNumber"; else if (selector == @selector(getKernelString:)) @@ -4561,6 +4677,14 @@ static _H Diversions_; return [info objectForKey:key]; } +- (NSArray *) getDisplayIdentifiers { + return SBSCopyApplicationDisplayIdentifiers(false, false); +} + +- (NSString *) getLocalizedNameForDisplayIdentifier:(NSString *)identifier { + return [SBSCopyLocalizedApplicationNameForDisplayIdentifier(identifier) autorelease] ?: (id) [NSNull null]; +} + - (NSNumber *) getKernelNumber:(NSString *)name { const char *string([name UTF8String]); @@ -4679,8 +4803,12 @@ static _H Diversions_; nil] waitUntilDone:NO]; } -- (void) addTrivialSource:(NSString *)href { +- (BOOL) addTrivialSource:(NSString *)href { + href = VerifySource(href); + if (href == nil) + return NO; [delegate_ performSelectorOnMainThread:@selector(addTrivialSource:) withObject:href waitUntilDone:NO]; + return YES; } - (void) refreshSources { @@ -4735,13 +4863,25 @@ static _H Diversions_; nil]; } -ssize_t DiskUsage(const char *path); - - (NSNumber *) du:(NSString *)path { - ssize_t usage(DiskUsage([path UTF8String])); - if (usage != -1) - usage /= 1024; - return [NSNumber numberWithUnsignedLong:usage]; + NSNumber *value(nil); + + FILE *du(popen([[NSString stringWithFormat:@"/usr/libexec/cydia/cydo /usr/libexec/cydia/du -ks %@", ShellEscape(path)] UTF8String], "r")); + if (du != NULL) { + 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)]; + } + } + pclose(du); + } + + return value; } - (void) close { @@ -4757,10 +4897,16 @@ ssize_t DiskUsage(const char *path); } - (NSString *) substitutePackageNames:(NSString *)message { + auto database([Database sharedInstance]); + + // XXX: this check is less racy than you'd expect, but this entire concept is a little awkward + if (![database hasPackages]) + return message; + NSMutableArray *words([[[message componentsSeparatedByString:@" "] mutableCopy] autorelease]); for (size_t i(0), e([words count]); i != e; ++i) { NSString *word([words objectAtIndex:i]); - if (Package *package = [[Database sharedInstance] packageWithName:word]) + if (Package *package = [database packageWithName:word]) [words replaceObjectAtIndex:i withObject:[package name]]; } @@ -4868,7 +5014,10 @@ ssize_t DiskUsage(const char *path); @implementation CydiaWebViewController - (NSURL *) navigationURL { - return request_ == nil ? nil : [NSURL URLWithString:[NSString stringWithFormat:@"cydia://url/%@", [[request_ URL] absoluteString]]]; + if (NSURLRequest *request = self.request) + return [NSURL URLWithString:[NSString stringWithFormat:@"cydia://url/%@", [[request URL] absoluteString]]]; + else + return nil; } + (void) _initialize { @@ -4971,7 +5120,7 @@ ssize_t DiskUsage(const char *path); - (id) init { if ((self = [super initWithWidth:0 ofClass:[CydiaWebViewController class]]) != nil) { - cydia_ = [[[CydiaObject alloc] initWithDelegate:indirect_] autorelease]; + cydia_ = [[[CydiaObject alloc] initWithDelegate:self.indirect] autorelease]; } return self; } @@ -5074,7 +5223,7 @@ bool DepSubstrate(const pkgCache::VerIterator &iterator) { - (void) complete { if (substrate_) RestartSubstrate_ = true; - [delegate_ confirmWithNavigationController:[self navigationController]]; + [self.delegate confirmWithNavigationController:[self navigationController]]; } - (void) alertView:(UIAlertView *)alert clickedButtonAtIndex:(NSInteger)button { @@ -5097,7 +5246,7 @@ bool DepSubstrate(const pkgCache::VerIterator &iterator) { } - (void) _doContinue { - [delegate_ cancelAndClear:NO]; + [self.delegate cancelAndClear:NO]; [self dismissModalViewControllerAnimated:YES]; } @@ -5135,8 +5284,6 @@ bool DepSubstrate(const pkgCache::VerIterator &iterator) { issues_ = [NSMutableArray arrayWithCapacity:4]; - UpgradeCydia_ = false; - for (Package *package in packages) { pkgCache::PkgIterator iterator([package iterator]); NSString *name([package id]); @@ -5248,9 +5395,6 @@ bool DepSubstrate(const pkgCache::VerIterator &iterator) { [removes addObject:name]; } - if ([name isEqualToString:@"cydia"]) - UpgradeCydia_ = true; - substrate_ |= DepSubstrate(policy->GetCandidateVer(iterator)); substrate_ |= DepSubstrate(iterator.CurrentVer()); } @@ -5325,7 +5469,7 @@ bool DepSubstrate(const pkgCache::VerIterator &iterator) { #endif - (void) cancelButtonClicked { - [delegate_ cancelAndClear:YES]; + [self.delegate cancelAndClear:YES]; [self dismissModalViewControllerAnimated:YES]; } @@ -5509,7 +5653,7 @@ bool DepSubstrate(const pkgCache::VerIterator &iterator) { - (id) initWithDatabase:(Database *)database delegate:(id)delegate { if ((self = [super init]) != nil) { database_ = database; - delegate_ = delegate; + self.delegate = delegate; [database_ setProgressDelegate:self]; @@ -5518,7 +5662,7 @@ bool DepSubstrate(const pkgCache::VerIterator &iterator) { [self setURL:[NSURL URLWithString:[NSString stringWithFormat:@"%@/#!/progress/", UI_]]]; - [scroller_ setBackgroundColor:[UIColor blackColor]]; + [self setPageColor:[UIColor blackColor]]; [[self navigationItem] setHidesBackButton:YES]; @@ -5540,51 +5684,23 @@ bool DepSubstrate(const pkgCache::VerIterator &iterator) { [super viewWillAppear:animated]; } -- (void) reloadSpringBoard { - 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) { - execl("/usr/libexec/cydia/cydo", "cydo", "/usr/bin/sbreload", NULL); - perror("sbreload"); - - exit(0); - } ReapZombie(pid); - - exit(0); - } ReapZombie(pid); - - sleep(15); - system("/usr/bin/killall backboardd SpringBoard sbreload"); -} - - (void) close { UpdateExternalStatus(0); if (Finish_ > 1) - [delegate_ saveState]; + [self.delegate saveState]; switch (Finish_) { case 0: - [delegate_ returnToCydia]; + [self.delegate returnToCydia]; break; case 1: - [delegate_ terminateWithSuccess]; - /*if ([delegate_ respondsToSelector:@selector(suspendWithAnimation:)]) - [delegate_ suspendWithAnimation:YES]; + [self.delegate terminateWithSuccess]; + /*if ([self.delegate respondsToSelector:@selector(suspendWithAnimation:)]) + [self.delegate suspendWithAnimation:YES]; else - [delegate_ suspend];*/ + [self.delegate suspend];*/ break; case 2: @@ -5596,9 +5712,9 @@ bool DepSubstrate(const pkgCache::VerIterator &iterator) { goto reload; reload: { - UIProgressHUD *hud([delegate_ addProgressHUD]); + UIProgressHUD *hud([self.delegate addProgressHUD]); [hud setText:UCLocalize("LOADING")]; - [self performSelector:@selector(reloadSpringBoard) withObject:nil afterDelay:0.5]; + [self.delegate performSelector:@selector(reloadSpringBoard) withObject:nil afterDelay:0.5]; return; } @@ -5796,12 +5912,12 @@ bool DepSubstrate(const pkgCache::VerIterator &iterator) { UIView *content([self contentView]); CGRect bounds([content bounds]); - content_ = [[[CyteTableViewCellContentView alloc] initWithFrame:bounds] autorelease]; - [content_ setAutoresizingMask:UIViewAutoresizingFlexibleBoth]; - [content addSubview:content_]; + self.content = [[[CyteTableViewCellContentView alloc] initWithFrame:bounds] autorelease]; + [self.content setAutoresizingMask:UIViewAutoresizingFlexibleBoth]; + [content addSubview:self.content]; - [content_ setDelegate:self]; - [content_ setOpaque:YES]; + [self.content setDelegate:self]; + [self.content setOpaque:YES]; } return self; } @@ -5820,7 +5936,7 @@ bool DepSubstrate(const pkgCache::VerIterator &iterator) { placard_ = nil; if (package == nil) - [content_ setBackgroundColor:[UIColor whiteColor]]; + [self.content setBackgroundColor:[UIColor whiteColor]]; else { [package parse]; @@ -5880,18 +5996,18 @@ bool DepSubstrate(const pkgCache::VerIterator &iterator) { placard = nil; } - [content_ setBackgroundColor:color]; + [self.content setBackgroundColor:color]; if (placard != nil) placard_ = [UIImage imageAtPath:[NSString stringWithFormat:@"%@/%@.png", App_, placard]]; } [self setNeedsDisplay]; - [content_ setNeedsDisplay]; + [self.content setNeedsDisplay]; } - (void) drawSummaryContentRect:(CGRect)rect { - bool highlighted(highlighted_); + bool highlighted(self.highlighted); float width([self bounds].size.width); if (icon_ != nil) { @@ -5934,7 +6050,7 @@ bool DepSubstrate(const pkgCache::VerIterator &iterator) { } - (void) drawNormalContentRect:(CGRect)rect { - bool highlighted(highlighted_); + bool highlighted(self.highlighted); float width([self bounds].size.width); if (icon_ != nil) { @@ -6019,12 +6135,12 @@ bool DepSubstrate(const pkgCache::VerIterator &iterator) { UIView *content([self contentView]); CGRect bounds([content bounds]); - content_ = [[[CyteTableViewCellContentView alloc] initWithFrame:bounds] autorelease]; - [content_ setAutoresizingMask:UIViewAutoresizingFlexibleBoth]; - [content addSubview:content_]; - [content_ setBackgroundColor:[UIColor whiteColor]]; + self.content = [[[CyteTableViewCellContentView alloc] initWithFrame:bounds] autorelease]; + [self.content setAutoresizingMask:UIViewAutoresizingFlexibleBoth]; + [content addSubview:self.content]; + [self.content setBackgroundColor:[UIColor whiteColor]]; - [content_ setDelegate:self]; + [self.content setDelegate:self]; } return self; } @@ -6069,7 +6185,7 @@ bool DepSubstrate(const pkgCache::VerIterator &iterator) { [self setAccessoryType:editing ? UITableViewCellAccessoryNone : UITableViewCellAccessoryDisclosureIndicator]; [self setSelectionStyle:editing ? UITableViewCellSelectionStyleNone : UITableViewCellSelectionStyleBlue]; - [content_ setNeedsDisplay]; + [self.content setNeedsDisplay]; } - (void) setFrame:(CGRect)frame { @@ -6084,7 +6200,7 @@ bool DepSubstrate(const pkgCache::VerIterator &iterator) { } - (void) drawContentRect:(CGRect)rect { - bool highlighted(highlighted_ && !editing_); + bool highlighted(self.highlighted && !editing_); [icon_ drawInRect:CGRectMake(7, 7, 32, 32)]; @@ -6212,7 +6328,7 @@ bool DepSubstrate(const pkgCache::VerIterator &iterator) { NSString *directory = [stack lastObject]; [stack addObject:[file stringByAppendingString:@"/"]]; [files_ replaceObjectAtIndex:i withObject:[NSString stringWithFormat:@"%*s%@", - ([stack count] - 2) * 3, "", + int(([stack count] - 2) * 3), "", [file substringFromIndex:[directory length]] ]]; } @@ -6239,7 +6355,9 @@ bool DepSubstrate(const pkgCache::VerIterator &iterator) { _H name_; bool commercial_; std::vector, _H>> buttons_; + _H sheet_; _H button_; + _H versions_; } - (id) initWithDatabase:(Database *)database forPackage:(NSString *)name withReferrer:(NSString *)referrer; @@ -6252,22 +6370,44 @@ bool DepSubstrate(const pkgCache::VerIterator &iterator) { return [NSURL URLWithString:[NSString stringWithFormat:@"cydia://package/%@", (id) name_]]; } +- (void) _clickButtonWithPackage:(Package *)package { + [self.delegate installPackage:package]; +} + - (void) _clickButtonWithName:(NSString *)name { if ([name isEqualToString:@"CLEAR"]) - [delegate_ clearPackage:package_]; - else if ([name isEqualToString:@"INSTALL"]) - [delegate_ installPackage:package_]; - else if ([name isEqualToString:@"REINSTALL"]) - [delegate_ installPackage:package_]; + return [self.delegate clearPackage:package_]; else if ([name isEqualToString:@"REMOVE"]) - [delegate_ removePackage:package_]; - else if ([name isEqualToString:@"UPGRADE"]) - [delegate_ installPackage:package_]; + return [self.delegate removePackage:package_]; + else if ([name isEqualToString:@"DOWNGRADE"]) { + sheet_ = [[[UIActionSheet alloc] + initWithTitle:nil + delegate:self + cancelButtonTitle:nil + destructiveButtonTitle:nil + otherButtonTitles:nil + ] autorelease]; + + for (Package *version in (id) versions_) + [sheet_ addButtonWithTitle:[version latest]]; + [sheet_ setContext:@"version"]; + + [self.delegate showActionSheet:sheet_ fromItem:[[self navigationItem] rightBarButtonItem]]; + return; + } + + else if ([name isEqualToString:@"INSTALL"]); + else if ([name isEqualToString:@"REINSTALL"]); + else if ([name isEqualToString:@"UPGRADE"]); else _assert(false); + + [self.delegate installPackage:package_]; } - (void) actionSheet:(UIActionSheet *)sheet clickedButtonAtIndex:(NSInteger)button { NSString *context([sheet context]); + if (sheet_ == sheet) + sheet_ = nil; if ([context isEqualToString:@"modify"]) { if (button != [sheet cancelButtonIndex]) { @@ -6277,6 +6417,16 @@ bool DepSubstrate(const pkgCache::VerIterator &iterator) { [self _clickButtonWithName:buttons_[button].first]; } + [sheet dismissWithClickedButtonIndex:button animated:YES]; + } else if ([context isEqualToString:@"version"]) { + if (button != [sheet cancelButtonIndex]) { + Package *version([versions_ objectAtIndex:button]); + if (IsWildcat_) + [self performSelector:@selector(_clickButtonWithPackage:) withObject:version afterDelay:0]; + else + [self _clickButtonWithPackage:version]; + } + [sheet dismissWithClickedButtonIndex:button animated:YES]; } } @@ -6287,6 +6437,9 @@ bool DepSubstrate(const pkgCache::VerIterator &iterator) { #if !AlwaysReload - (void) _customButtonClicked { + if (commercial_ && [package_ uninstalled]) + return [self reloadURLWithCache:NO]; + size_t count(buttons_.size()); if (count == 0) return; @@ -6298,7 +6451,7 @@ bool DepSubstrate(const pkgCache::VerIterator &iterator) { for (const auto &button : buttons_) [buttons addObject:button.second]; - UIActionSheet *sheet = [[[UIActionSheet alloc] + sheet_ = [[[UIActionSheet alloc] initWithTitle:nil delegate:self cancelButtonTitle:nil @@ -6306,23 +6459,14 @@ bool DepSubstrate(const pkgCache::VerIterator &iterator) { otherButtonTitles:nil ] autorelease]; - for (NSString *button in buttons) [sheet addButtonWithTitle:button]; - if (!IsWildcat_) { - [sheet addButtonWithTitle:UCLocalize("CANCEL")]; - [sheet setCancelButtonIndex:[sheet numberOfButtons] - 1]; - } - [sheet setContext:@"modify"]; + for (NSString *button in buttons) + [sheet_ addButtonWithTitle:button]; + [sheet_ setContext:@"modify"]; - [delegate_ showActionSheet:sheet fromItem:[[self navigationItem] rightBarButtonItem]]; + [self.delegate showActionSheet:sheet_ fromItem:[[self navigationItem] rightBarButtonItem]]; } } -- (void) reloadButtonClicked { - if (commercial_ && function_ == nil && [package_ uninstalled]) - return; - [self customButtonClicked]; -} - - (void) applyLoadingTitle { // Don't show "Loading" as the title. Ever. } @@ -6347,7 +6491,11 @@ bool DepSubstrate(const pkgCache::VerIterator &iterator) { - (void) reloadData { [super reloadData]; + [sheet_ dismissWithClickedButtonIndex:[sheet_ cancelButtonIndex] animated:YES]; + sheet_ = nil; + package_ = [database_ packageWithName:name_]; + versions_ = [package_ downgrades]; buttons_.clear(); @@ -6367,6 +6515,8 @@ bool DepSubstrate(const pkgCache::VerIterator &iterator) { buttons_.push_back(std::make_pair(@"REINSTALL", UCLocalize("REINSTALL"))); if (![package_ uninstalled]) buttons_.push_back(std::make_pair(@"REMOVE", UCLocalize("REMOVE"))); + if ([versions_ count] != 0) + buttons_.push_back(std::make_pair(@"DOWNGRADE", UCLocalize("DOWNGRADE"))); } NSString *title; @@ -6410,7 +6560,6 @@ bool DepSubstrate(const pkgCache::VerIterator &iterator) { } - (id) initWithDatabase:(Database *)database title:(NSString *)title; -- (void) setDelegate:(id)delegate; - (void) resetCursor; - (void) clearData; @@ -6523,7 +6672,7 @@ bool DepSubstrate(const pkgCache::VerIterator &iterator) { - (void) didSelectPackage:(Package *)package { CYPackageController *view([[[CYPackageController alloc] initWithDatabase:database_ forPackage:[package id] withReferrer:[[self referrerURL] absoluteString]] autorelease]); - [view setDelegate:delegate_]; + [view setDelegate:self.delegate]; [[self navigationController] pushViewController:view animated:YES]; } @@ -6621,10 +6770,6 @@ bool DepSubstrate(const pkgCache::VerIterator &iterator) { [super releaseSubviews]; } -- (void) setDelegate:(id)delegate { - delegate_ = delegate; -} - - (bool) shouldYield { return false; } @@ -6657,7 +6802,7 @@ bool DepSubstrate(const pkgCache::VerIterator &iterator) { if (![self shouldBlock]) hud = nil; else { - hud = [delegate_ addProgressHUD]; + hud = [self.delegate addProgressHUD]; [hud setText:UCLocalize("LOADING")]; } @@ -6665,7 +6810,7 @@ bool DepSubstrate(const pkgCache::VerIterator &iterator) { packages = [self yieldToSelector:@selector(_reloadPackages)]; if (hud != nil) - [delegate_ removeProgressHUD:hud]; + [self.delegate removeProgressHUD:hud]; } while (reloading_ == 2); } else { packages = [self _reloadPackages]; @@ -6821,7 +6966,7 @@ typedef Function PackageSorter; _profile(PackageTable$reloadData$Filter) for (Package *package in packages) - if ([package valid] && filter(package)) + if (filter(package)) [filtered addObject:package]; _end @@ -6888,7 +7033,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" @@ -6911,15 +7056,6 @@ static void HomeControllerReachabilityCallback(SCNetworkReachabilityRef reachabi @end /* }}} */ -/* Cydia Navigation Controller Interface {{{ */ -@interface UINavigationController (Cydia) - -- (NSArray *) navigationURLCollection; -- (void) unloadData; - -@end -/* }}} */ - /* Cydia Tab Bar Controller {{{ */ @interface CydiaTabBarController : CyteTabBarController < UITabBarControllerDelegate, @@ -6934,7 +7070,6 @@ static void HomeControllerReachabilityCallback(SCNetworkReachabilityRef reachabi _transient NSObject *updatedelegate_; } -- (NSArray *) navigationURLCollection; - (void) beginUpdate; - (BOOL) updating; @@ -6942,19 +7077,6 @@ static void HomeControllerReachabilityCallback(SCNetworkReachabilityRef reachabi @implementation CydiaTabBarController -- (NSArray *) navigationURLCollection { - NSMutableArray *items([NSMutableArray array]); - - // XXX: Should this deal with transient view controllers? - for (id navigation in [self viewControllers]) { - NSArray *stack = [navigation performSelector:@selector(navigationURLCollection)]; - if (stack != nil) - [items addObject:stack]; - } - - return items; -} - - (id) initWithDatabase:(Database *)database { if ((self = [super init]) != nil) { database_ = database; @@ -7053,47 +7175,6 @@ static void HomeControllerReachabilityCallback(SCNetworkReachabilityRef reachabi @end /* }}} */ -/* Cydia Navigation Controller Implementation {{{ */ -@implementation UINavigationController (Cydia) - -- (NSArray *) navigationURLCollection { - NSMutableArray *stack([NSMutableArray array]); - - for (CyteViewController *controller in [self viewControllers]) { - NSString *url = [[controller navigationURL] absoluteString]; - if (url != nil) - [stack addObject:url]; - } - - return stack; -} - -- (void) reloadData { - [super reloadData]; - - UIViewController *visible([self visibleViewController]); - if (visible != nil) - [visible reloadData]; - - // on the iPad, this view controller is ALSO visible. :( - if (IsWildcat_) - if (UIViewController *modal = [self modalViewController]) - if ([modal modalPresentationStyle] == UIModalPresentationFormSheet) - if (UIViewController *top = [self topViewController]) - if (top != visible) - [top reloadData]; -} - -- (void) unloadData { - for (CyteViewController *page in [self viewControllers]) - [page unloadData]; - - [super unloadData]; -} - -@end -/* }}} */ - /* Cydia:// Protocol {{{ */ @interface CydiaURLProtocol : NSURLProtocol { } @@ -7163,7 +7244,28 @@ static void HomeControllerReachabilityCallback(SCNetworkReachabilityRef reachabi Database *database([Database sharedInstance]); - if ([command isEqualToString:@"package-icon"]) { + if (false); + else if ([command isEqualToString:@"application-icon"]) { + if (path == nil) + goto fail; + path = [path stringByReplacingPercentEscapesUsingEncoding:NSUTF8StringEncoding]; + + UIImage *icon(nil); + + if (icon == nil && $SBSCopyIconImagePNGDataForDisplayIdentifier != NULL) { + NSData *data([$SBSCopyIconImagePNGDataForDisplayIdentifier(path) autorelease]); + icon = [UIImage imageWithData:data]; + } + + if (icon == nil) + if (NSString *file = SBSCopyIconImagePathForDisplayIdentifier(path)) + icon = [UIImage imageAtPath:file]; + + if (icon == nil) + icon = [UIImage imageNamed:@"unknown.png"]; + + [self _returnPNGWithImage:icon forRequest:request]; + } else if ([command isEqualToString:@"package-icon"]) { if (path == nil) goto fail; path = [path stringByReplacingPercentEscapesUsingEncoding:NSUTF8StringEncoding]; @@ -7311,7 +7413,7 @@ static void HomeControllerReachabilityCallback(SCNetworkReachabilityRef reachabi if (editing) [list_ reloadData]; else - [delegate_ updateData]; + [self.delegate updateData]; [self updateNavigationItem]; } @@ -7373,7 +7475,7 @@ static void HomeControllerReachabilityCallback(SCNetworkReachabilityRef reachabi source:[self source] section:[section name] ] autorelease]; - [controller setDelegate:delegate_]; + [controller setDelegate:self.delegate]; [[self navigationController] pushViewController:controller animated:YES]; } @@ -7444,7 +7546,7 @@ static void HomeControllerReachabilityCallback(SCNetworkReachabilityRef reachabi [section addToCount]; _profile(SectionsView$reloadData$Filter) - if (![package valid] || ![package visible]) + if (![package visible]) continue; _end @@ -7518,7 +7620,7 @@ static void HomeControllerReachabilityCallback(SCNetworkReachabilityRef reachabi } - (void) setLeftBarButtonItem { - if ([delegate_ updating]) + if ([self.delegate updating]) [[self navigationItem] setLeftBarButtonItem:[[[UIBarButtonItem alloc] initWithTitle:UCLocalize("CANCEL") style:UIBarButtonItemStyleDone @@ -7535,16 +7637,16 @@ static void HomeControllerReachabilityCallback(SCNetworkReachabilityRef reachabi } - (void) refreshButtonClicked { - if ([delegate_ requestUpdate]) + if ([self.delegate requestUpdate]) [self setLeftBarButtonItem]; } - (void) cancelButtonClicked { - [delegate_ cancelUpdate]; + [self.delegate cancelUpdate]; } - (void) upgradeButtonClicked { - [delegate_ distUpgrade]; + [self.delegate distUpgrade]; [[self navigationItem] setRightBarButtonItem:nil animated:YES]; } @@ -7889,27 +7991,22 @@ static void HomeControllerReachabilityCallback(SCNetworkReachabilityRef reachabi if (package_ == nil) return; if ([package_ setSubscribed:value]) - [delegate_ updateData]; + [self.delegate updateData]; } - (void) _updateIgnored { const char *package([name_ UTF8String]); bool on([ignoredSwitch_ isOn]); - pid_t pid(ExecFork()); - if (pid == 0) { - FILE *dpkg(popen("/usr/libexec/cydo --set-selections", "w")); - fwrite(package, strlen(package), 1, dpkg); + FILE *dpkg(popen("/usr/libexec/cydia/cydo --set-selections", "w")); + fwrite(package, strlen(package), 1, dpkg); - if (on) - fwrite(" hold\n", 6, 1, dpkg); - else - fwrite(" install\n", 9, 1, dpkg); - - pclose(dpkg); + if (on) + fwrite(" hold\n", 6, 1, dpkg); + else + fwrite(" install\n", 9, 1, dpkg); - exit(0); - } ReapZombie(pid); + pclose(dpkg); } - (void) onIgnored:(id)control { @@ -7917,7 +8014,7 @@ static void HomeControllerReachabilityCallback(SCNetworkReachabilityRef reachabi [invocation setTarget:self]; [invocation setSelector:@selector(_updateIgnored)]; - [delegate_ reloadDataWithInvocation:invocation]; + [self.delegate reloadDataWithInvocation:invocation]; } - (UITableViewCell *) tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath { @@ -8108,7 +8205,7 @@ static void HomeControllerReachabilityCallback(SCNetworkReachabilityRef reachabi #if !AlwaysReload - (void) queueButtonClicked { - [delegate_ queue]; + [self.delegate queue]; } #endif @@ -8158,7 +8255,7 @@ static void HomeControllerReachabilityCallback(SCNetworkReachabilityRef reachabi - (void) _setImage:(NSArray *)data { if ([url_ isEqual:[data objectAtIndex:0]]) { icon_ = [data objectAtIndex:1]; - [content_ setNeedsDisplay]; + [self.content setNeedsDisplay]; } } @@ -8192,7 +8289,7 @@ static void HomeControllerReachabilityCallback(SCNetworkReachabilityRef reachabi origin_ = [source name]; label_ = [source rooturi]; - [content_ setNeedsDisplay]; + [self.content setNeedsDisplay]; url_ = [source iconURL]; [NSThread detachNewThreadSelector:@selector(_setSource:) toTarget:self withObject:url_]; @@ -8205,7 +8302,7 @@ static void HomeControllerReachabilityCallback(SCNetworkReachabilityRef reachabi icon_ = [UIImage imageNamed:@"folder.png"]; origin_ = UCLocalize("ALL_SOURCES"); label_ = UCLocalize("ALL_SOURCES_EX"); - [content_ setNeedsDisplay]; + [self.content setNeedsDisplay]; } - (SourceCell *) initWithFrame:(CGRect)frame reuseIdentifier:(NSString *)reuseIdentifier { @@ -8213,19 +8310,19 @@ static void HomeControllerReachabilityCallback(SCNetworkReachabilityRef reachabi UIView *content([self contentView]); CGRect bounds([content bounds]); - content_ = [[[CyteTableViewCellContentView alloc] initWithFrame:bounds] autorelease]; - [content_ setAutoresizingMask:UIViewAutoresizingFlexibleBoth]; - [content_ setBackgroundColor:[UIColor whiteColor]]; - [content addSubview:content_]; + self.content = [[[CyteTableViewCellContentView alloc] initWithFrame:bounds] autorelease]; + [self.content setAutoresizingMask:UIViewAutoresizingFlexibleBoth]; + [self.content setBackgroundColor:[UIColor whiteColor]]; + [content addSubview:self.content]; - [content_ setDelegate:self]; - [content_ setOpaque:YES]; + [self.content setDelegate:self]; + [self.content setOpaque:YES]; indicator_ = [[[UIActivityIndicatorView alloc] initWithActivityIndicatorStyle:UIActivityIndicatorViewStyleGraySmall] autorelease]; [indicator_ setAutoresizingMask:UIViewAutoresizingFlexibleLeftMargin | UIViewAutoresizingFlexibleTopMargin];// | UIViewAutoresizingFlexibleBottomMargin]; [content addSubview:indicator_]; - [[content_ layer] setContentsGravity:kCAGravityTopLeft]; + [[self.content layer] setContentsGravity:kCAGravityTopLeft]; } return self; } @@ -8249,7 +8346,7 @@ static void HomeControllerReachabilityCallback(SCNetworkReachabilityRef reachabi } - (void) drawContentRect:(CGRect)rect { - bool highlighted(highlighted_); + bool highlighted(self.highlighted); float width(rect.size.width); if (icon_ != nil) { @@ -8393,7 +8490,7 @@ static void HomeControllerReachabilityCallback(SCNetworkReachabilityRef reachabi source:[self sourceAtIndexPath:indexPath] ] autorelease]); - [controller setDelegate:delegate_]; + [controller setDelegate:self.delegate]; [[self navigationController] pushViewController:controller animated:YES]; } @@ -8412,8 +8509,7 @@ static void HomeControllerReachabilityCallback(SCNetworkReachabilityRef reachabi [Sources_ removeObjectForKey:[source key]]; - [delegate_ _saveConfig]; - [delegate_ reloadDataWithInvocation:nil]; + [self.delegate syncData]; } } @@ -8422,10 +8518,10 @@ static void HomeControllerReachabilityCallback(SCNetworkReachabilityRef reachabi } - (void) complete { - [delegate_ addTrivialSource:href_]; + [self.delegate addTrivialSource:href_]; href_ = nil; - [delegate_ syncData]; + [self.delegate syncData]; } - (NSString *) getWarning { @@ -8464,9 +8560,9 @@ static void HomeControllerReachabilityCallback(SCNetworkReachabilityRef reachabi ) { NSString *warning(cydia_ ? [self yieldToSelector:@selector(getWarning)] : nil); - [delegate_ releaseNetworkActivityIndicator]; + [self.delegate releaseNetworkActivityIndicator]; - [delegate_ removeProgressHUD:hud_]; + [self.delegate removeProgressHUD:hud_]; hud_ = nil; if (cydia_) { @@ -8572,27 +8668,10 @@ static void HomeControllerReachabilityCallback(SCNetworkReachabilityRef reachabi switch (button) { case 1: { NSString *href = [[alert textField] text]; - - static RegEx href_r("(http(s?)://|file:///)[^# ]*"); - if (!href_r(href)) { - UIAlertView *alert = [[[UIAlertView alloc] - initWithTitle:[NSString stringWithFormat:Colon_, Error_, UCLocalize("INVALID_URL")] - message:UCLocalize("INVALID_URL_EX") - delegate:self - cancelButtonTitle:UCLocalize("OK") - otherButtonTitles:nil - ] autorelease]; - - [alert setContext:@"badurl"]; - [alert show]; - + href = VerifySource(href); + if (href == nil) break; - } - - if (![href hasSuffix:@"/"]) - href_ = [href stringByAppendingString:@"/"]; - else - href_ = href; + href_ = href; trivial_bz2_ = [[self _requestHRef:[href_ stringByAppendingString:@"Packages.bz2"] method:@"HEAD"] retain]; trivial_gz_ = [[self _requestHRef:[href_ stringByAppendingString:@"Packages.gz"] method:@"HEAD"] retain]; @@ -8600,9 +8679,9 @@ static void HomeControllerReachabilityCallback(SCNetworkReachabilityRef reachabi cydia_ = false; // XXX: this is stupid - hud_ = [delegate_ addProgressHUD]; + hud_ = [self.delegate addProgressHUD]; [hud_ setText:UCLocalize("VERIFYING_URL")]; - [delegate_ retainNetworkActivityIndicator]; + [self.delegate retainNetworkActivityIndicator]; } break; case 0: @@ -8642,7 +8721,7 @@ static void HomeControllerReachabilityCallback(SCNetworkReachabilityRef reachabi target:self action:@selector(addButtonClicked) ] autorelease] animated:animated]; - else if ([delegate_ updating]) + else if ([self.delegate updating]) [[self navigationItem] setLeftBarButtonItem:[[[UIBarButtonItem alloc] initWithTitle:UCLocalize("CANCEL") style:UIBarButtonItemStyleDone @@ -8742,7 +8821,7 @@ static void HomeControllerReachabilityCallback(SCNetworkReachabilityRef reachabi [alert setNumberOfRows:1]; [alert addTextFieldWithValue:@"http://" label:@""]; - UITextInputTraits *traits = [[alert textField] textInputTraits]; + NSObject *traits = [[alert textField] textInputTraits]; [traits setAutocapitalizationType:UITextAutocapitalizationTypeNone]; [traits setAutocorrectionType:UITextAutocorrectionTypeNo]; [traits setKeyboardType:UIKeyboardTypeURL]; @@ -8757,12 +8836,12 @@ static void HomeControllerReachabilityCallback(SCNetworkReachabilityRef reachabi } - (void) refreshButtonClicked { - if ([delegate_ requestUpdate]) + if ([self.delegate requestUpdate]) [self updateButtonsForEditingStatusAnimated:YES]; } - (void) cancelButtonClicked { - [delegate_ cancelUpdate]; + [self.delegate cancelUpdate]; } - (void) editButtonClicked { @@ -8893,7 +8972,7 @@ static void HomeControllerReachabilityCallback(SCNetworkReachabilityRef reachabi @end -@interface Cydia : UIApplication < +@interface Cydia : CyteApplication < ConfirmationControllerDelegate, DatabaseDelegate, CydiaDelegate @@ -9014,6 +9093,15 @@ static void HomeControllerReachabilityCallback(SCNetworkReachabilityRef reachabi [self _loaded]; } +- (void) reloadSpringBoard { + if (kCFCoreFoundationVersionNumber >= 700) // XXX: iOS 6.x + system("/usr/libexec/cydia/cydo /bin/launchctl stop com.apple.backboardd"); + else + system("/usr/libexec/cydia/cydo /bin/launchctl stop com.apple.SpringBoard"); + sleep(15); + system("/usr/bin/killall backboardd SpringBoard"); +} + - (void) _saveConfig { SaveConfig(database_); } @@ -9223,8 +9311,10 @@ _end CydiaAddSource(href, distribution, sections); } -- (void) addTrivialSource:(NSString *)href { +// XXX: this method should not return anything +- (BOOL) addTrivialSource:(NSString *)href { CydiaAddSource(href, @"./"); + return YES; } - (void) resolve { @@ -9306,14 +9396,7 @@ _end - (void) _uicache { _trace(); - - if (UpgradeCydia_ && Finish_ > 0) { - setreugid(0, 0); - system("su -c /usr/bin/uicache mobile"); - } else { - system("/usr/bin/uicache"); - } - + system("/usr/bin/uicache"); _trace(); } @@ -9386,15 +9469,14 @@ _end @synchronized (self) { for (Package *broken in (id) broken_) { [broken remove]; - NSString *id = [broken id]; - + NSString *id(ShellEscape([broken id])); system([[NSString stringWithFormat:@"/usr/libexec/cydia/cydo /bin/rm -f" " /var/lib/dpkg/info/%@.prerm" " /var/lib/dpkg/info/%@.postrm" " /var/lib/dpkg/info/%@.preinst" " /var/lib/dpkg/info/%@.postinst" " /var/lib/dpkg/info/%@.extrainst_" - , id, id, id, id, id] UTF8String]); + "", id, id, id, id, id] UTF8String]); } [self resolve]; @@ -9489,7 +9571,7 @@ _end [super applicationSuspend]; } -- (void) applicationSuspend:(__GSEvent *)event { +- (void) applicationSuspend:(GSEventRef)event { if ([self isSafeToSuspend]) [super applicationSuspend:event]; } @@ -9597,7 +9679,7 @@ _end controller = [[[SectionController alloc] initWithDatabase:database_ source:nil section:argument] autorelease]; } - if (!external && [base isEqualToString:@"sources"]) { + if ([base isEqualToString:@"sources"]) { if ([argument isEqualToString:@"add"]) { controller = [[[SourcesController alloc] initWithDatabase:database_] autorelease]; [(SourcesController *)controller showAddSourcePrompt]; @@ -9753,14 +9835,7 @@ _end UpdateExternalStatus(0); [self removeStashController]; - - pid_t pid(ExecFork()); - if (pid == 0) { - execlp("launchctl", "launchctl", "stop", "com.apple.SpringBoard", NULL); - perror("launchctl stop"); - - exit(0); - } ReapZombie(pid); + [self reloadSpringBoard]; } - (void) setupViewControllers { @@ -9796,32 +9871,9 @@ _end [tabbar_ setUpdateDelegate:self]; } -- (void) _sendMemoryWarningNotification { - if (kCFCoreFoundationVersionNumber < kCFCoreFoundationVersionNumber_iPhoneOS_3_0) // XXX: maybe 4_0? - [[NSNotificationCenter defaultCenter] postNotificationName:@"UIApplicationMemoryWarningNotification" object:[UIApplication sharedApplication]]; - else - [[NSNotificationCenter defaultCenter] postNotificationName:@"UIApplicationDidReceiveMemoryWarningNotification" object:[UIApplication sharedApplication]]; -} - -- (void) _sendMemoryWarningNotifications { - while (true) { - [self performSelectorOnMainThread:@selector(_sendMemoryWarningNotification) withObject:nil waitUntilDone:NO]; - sleep(2); - //usleep(2000000); - } -} - -- (void) applicationDidReceiveMemoryWarning:(UIApplication *)application { - NSLog(@"--"); - [[NSURLCache sharedURLCache] removeAllCachedResponses]; -} - - (void) applicationDidFinishLaunching:(id)unused { - //[NSThread detachNewThreadSelector:@selector(_sendMemoryWarningNotifications) toTarget:self withObject:nil]; - + [super applicationDidFinishLaunching:unused]; _trace(); - if ([self respondsToSelector:@selector(setApplicationSupportsShakeToEdit:)]) - [self setApplicationSupportsShakeToEdit:NO]; @synchronized (HostConfig_) { [BridgedHosts_ addObject:[[NSURL URLWithString:CydiaURL(@"")] host]]; @@ -9859,6 +9911,9 @@ _trace(); [window_ makeKey:self]; [window_ setHidden:NO]; + if (access("/.cydia_no_stash", F_OK) == 0); + else { + if (false) stash: { [self addStashController]; // XXX: this would be much cleaner as a yieldToSelector: @@ -9892,6 +9947,8 @@ _trace(); Stash_("/usr/share"); //Stash_("/var/lib"); + } + database_ = [Database sharedInstance]; [database_ setDelegate:self]; @@ -10005,6 +10062,11 @@ _trace(); } - (void) showActionSheet:(UIActionSheet *)sheet fromItem:(UIBarButtonItem *)item { + if (!IsWildcat_) { + [sheet addButtonWithTitle:UCLocalize("CANCEL")]; + [sheet setCancelButtonIndex:[sheet numberOfButtons] - 1]; + } + if (item != nil && IsWildcat_) { [sheet showFromBarButtonItem:item animated:YES]; } else { @@ -10098,8 +10160,31 @@ MSHook(id, NSUserDefaults$objectForKey$, NSUserDefaults *self, SEL _cmd, NSStrin return _NSUserDefaults$objectForKey$(self, _cmd, key); } +static NSMutableDictionary *AutoreleaseDeepMutableCopyOfDictionary(CFTypeRef type) { + if (type == NULL) + return nil; + if (CFGetTypeID(type) != CFDictionaryGetTypeID()) + return nil; + CFTypeRef copy(CFPropertyListCreateDeepCopy(kCFAllocatorDefault, type, kCFPropertyListMutableContainers)); + CFRelease(type); + return [(NSMutableDictionary *) copy autorelease]; +} + +int main_store(int, char *argv[]); + int main(int argc, char *argv[]) { - setreugid(501, 501); +#ifdef __arm64__ + const char *argv0(argv[0]); + if (const char *slash = strrchr(argv0, '/')) + argv0 = slash + 1; + if (false); + else if (!strcmp(argv0, "store")) + return main_store(argc, argv); +#endif + + int fd(open("/tmp/cydia.log", O_WRONLY | O_APPEND | O_CREAT, 0644)); + dup2(fd, 2); + close(fd); NSAutoreleasePool *pool([[NSAutoreleasePool alloc] init]); @@ -10173,29 +10258,28 @@ int main(int argc, char *argv[]) { Locale_ = CFLocaleCopyCurrent(); Languages_ = [NSLocale preferredLanguages]; - //CFStringRef locale(CFLocaleGetIdentifier(Locale_)); - //NSLog(@"%@", [Languages_ description]); + std::string languages; + const char *translation(NULL); - const char *lang; + // XXX: this isn't really a language, but this is compatible with older Cydia builds if (Locale_ != NULL) - lang = [(NSString *) CFLocaleGetIdentifier(Locale_) UTF8String]; - else if (Languages_ != nil && [Languages_ count] != 0) - lang = [[Languages_ objectAtIndex:0] UTF8String]; - else - // XXX: consider just setting to C and then falling through? - lang = NULL; - - if (lang != NULL) { - RegEx pattern("([a-z][a-z])(?:-[A-Za-z]*)?(_[A-Z][A-Z])?"); - lang = !pattern(lang) ? NULL : [pattern->*@"%1$@%2$@" UTF8String]; - } + if (const char *language = [(NSString *) CFLocaleGetIdentifier(Locale_) UTF8String]) { + RegEx pattern("([a-z][a-z])(?:-[A-Za-z]*)?(_[A-Z][A-Z])?"); + if (pattern(language)) { + translation = strdup([pattern->*@"%1$@%2$@" UTF8String]); + languages += translation; + languages += ","; + } + } - NSLog(@"Setting Language: %s", lang); + if (Languages_ != nil) + for (NSString *language : Languages_) { + languages += [language UTF8String]; + languages += ","; + } - if (lang != NULL) { - setenv("LANG", lang, true); - std::setlocale(LC_ALL, lang); - } + languages += "en"; + NSLog(@"Setting Language: [%s] %s", translation, languages.c_str()); /* }}} */ /* Index Collation {{{ */ if (Class $UILocalizedIndexedCollation = objc_getClass("UILocalizedIndexedCollation")) { @try { @@ -10276,6 +10360,7 @@ int main(int argc, char *argv[]) { Advanced_ = YES; Cache_ = [[NSString stringWithFormat:@"%@/Library/Caches/com.saurik.Cydia", @"/var/mobile"] retain]; + mkdir([Cache_ UTF8String], 0755); /*Method alloc = class_getClassMethod([NSObject class], @selector(alloc)); alloc_ = alloc->method_imp; @@ -10350,10 +10435,9 @@ int main(int argc, char *argv[]) { MetaFile_.Open("/var/mobile/Library/Cydia/metadata.cb0"); _trace(); - // 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]; + Values_ = AutoreleaseDeepMutableCopyOfDictionary(CFPreferencesCopyAppValue(CFSTR("CydiaValues"), CFSTR("com.saurik.Cydia"))); + Sections_ = AutoreleaseDeepMutableCopyOfDictionary(CFPreferencesCopyAppValue(CFSTR("CydiaSections"), CFSTR("com.saurik.Cydia"))); + Sources_ = AutoreleaseDeepMutableCopyOfDictionary(CFPreferencesCopyAppValue(CFSTR("CydiaSources"), CFSTR("com.saurik.Cydia"))); Version_ = [(NSNumber *) CFPreferencesCopyAppValue(CFSTR("CydiaVersion"), CFSTR("com.saurik.Cydia")) autorelease]; _trace(); @@ -10404,7 +10488,7 @@ int main(int argc, char *argv[]) { _H broken([NSMutableArray array]); for (NSString *key in (id) Sources_) - if ([key rangeOfCharacterFromSet:[NSCharacterSet characterSetWithCharactersInString:@"# "]].location != NSNotFound) + if ([key rangeOfCharacterFromSet:[NSCharacterSet characterSetWithCharactersInString:@"# "]].location != NSNotFound || ![([[Sources_ objectForKey:key] objectForKey:@"URI"] ?: @"/") hasSuffix:@"/"]) [broken addObject:key]; if ([broken count] != 0) for (NSString *key in (id) broken) @@ -10417,21 +10501,6 @@ int main(int argc, char *argv[]) { 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"); @@ -10450,23 +10519,34 @@ int main(int argc, char *argv[]) { _assert(errno == ENOENT); } + system("/usr/libexec/cydia/cydo /bin/ln -sf /var/mobile/Library/Caches/com.saurik.Cydia/sources.list /etc/apt/sources.list.d/cydia.list"); + /* APT Initialization {{{ */ _assert(pkgInitConfig(*_config)); _assert(pkgInitSystem(*_config, _system)); - if (lang != NULL) - _config->Set("APT::Acquire::Translation", lang); + _config->Set("Acquire::AllowInsecureRepositories", true); + _config->Set("Acquire::Check-Valid-Until", false); + _config->Set("Dir::Bin::Methods::store", "/Applications/Cydia.app/store"); + + _config->Set("pkgCacheGen::ForceEssential", ""); + + if (translation != NULL) + _config->Set("APT::Acquire::Translation", translation); + _config->Set("Acquire::Languages", languages); // XXX: this timeout might be important :( //_config->Set("Acquire::http::Timeout", 15); _config->Set("Acquire::http::MaxParallel", usermem >= 384 * 1024 * 1024 ? 16 : 3); - mkdir([Cache_ UTF8String], 0755); mkdir([Cache("archives") UTF8String], 0755); 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); @@ -10474,7 +10554,7 @@ int main(int argc, char *argv[]) { std::string logs("/var/mobile/Library/Logs/Cydia"); mkdir(logs.c_str(), 0755); - _config->Set("Dir::Log::Terminal", logs + "/apt.log"); + _config->Set("Dir::Log", logs); _config->Set("Dir::Bin::dpkg", "/usr/libexec/cydia/cydo"); /* }}} */ @@ -10501,6 +10581,7 @@ int main(int argc, char *argv[]) { /* }}} */ $SBSSetInterceptsMenuButtonForever = reinterpret_cast(dlsym(RTLD_DEFAULT, "SBSSetInterceptsMenuButtonForever")); + $SBSCopyIconImagePNGDataForDisplayIdentifier = reinterpret_cast(dlsym(RTLD_DEFAULT, "SBSCopyIconImagePNGDataForDisplayIdentifier")); const char *symbol(kCFCoreFoundationVersionNumber >= 800 ? "MGGetBoolAnswer" : "GSSystemHasCapability"); BOOL (*GSSystemHasCapability)(CFStringRef) = reinterpret_cast(dlsym(RTLD_DEFAULT, symbol));