X-Git-Url: https://git.saurik.com/cydia.git/blobdiff_plain/9fe109d1a81b281765de84f150862db88c65dcd0..02ccb263caa97381f1eaf9ed305ff57fd7b69734:/MobileCydia.mm diff --git a/MobileCydia.mm b/MobileCydia.mm index 247d3a88..addc9418 100644 --- a/MobileCydia.mm +++ b/MobileCydia.mm @@ -56,15 +56,17 @@ #include #include +#include #include #include #include #include -#include +#include "fdstream.hpp" #undef ABS +#include "apt.h" #include #include #include @@ -238,6 +240,16 @@ union SplitHash { }; // }}} +@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_; static NSString *Error_; @@ -490,6 +502,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)); } @@ -1119,6 +1135,7 @@ typedef std::map< unsigned long, _H > SourceMap; + (Database *) sharedInstance; - (unsigned) era; +- (bool) hasPackages; - (void) _readCydia:(NSNumber *)fd; - (void) _readStatus:(NSNumber *)fd; @@ -1404,14 +1421,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_; // }}} @@ -2503,15 +2520,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) @@ -2540,7 +2549,7 @@ struct PackageNameOrdering : version_ = version; - pkgCache::PkgIterator iterator(version.ParentPkg()); + pkgCache::PkgIterator iterator(version_.ParentPkg()); iterator_ = iterator; _profile(Package$initWithVersion$Version) @@ -2548,7 +2557,7 @@ struct PackageNameOrdering : _end _profile(Package$initWithVersion$Cache) - name_.set(NULL, iterator.Display()); + name_.set(NULL, version_.Display()); latest_.set(NULL, StripVersion_(version_.VerStr())); @@ -2612,7 +2621,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]; @@ -2735,6 +2748,21 @@ struct PackageNameOrdering : 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) @@ -2754,7 +2782,10 @@ struct PackageNameOrdering : } - (NSString *) longSection { - return LocalizeSection([self section]); + if (NSString *section = [self section]) + return LocalizeSection(section); + else + return nil; } - (NSString *) shortSection { @@ -2824,23 +2855,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 { @@ -3349,6 +3369,7 @@ struct PackageNameOrdering : resolver->Protect(iterator_); pkgCacheFile &cache([database_ cache]); + cache->SetCandidateVersion(version_); cache->SetReInstall(iterator_, false); cache->MarkInstall(iterator_, false); @@ -3503,6 +3524,10 @@ class CydiaLogCleaner : CFArrayRemoveAllValues(packages_); } +- (bool) hasPackages { + return CFArrayGetCount(packages_) != 0; +} + - (void) dealloc { // XXX: actually implement this thing _assert(false); @@ -3512,8 +3537,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:([^:]*)"); @@ -3539,8 +3563,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 : (.*?) *"); @@ -3596,8 +3619,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)) { @@ -3624,7 +3646,11 @@ class CydiaLogCleaner : @synchronized (self) { if (static_cast(cache_) == NULL) return nil; - pkgCache::PkgIterator iterator(cache_->FindPkg([name UTF8String])); + pkgCache::PkgIterator iterator(cache_->FindPkg([name UTF8String] +#ifdef __arm64__ + , "any" +#endif + )); return iterator.end() ? nil : [Package packageWithIterator:iterator withZone:NULL inPool:NULL database:self]; } } @@ -3848,7 +3874,7 @@ class CydiaLogCleaner : 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)); @@ -3876,7 +3902,8 @@ class CydiaLogCleaner : } return; - } + } else if ([self popErrorWithTitle:title forOperation:true]) + return; _trace(); unlink("/tmp/cydia.chk"); @@ -4116,10 +4143,8 @@ class CydiaLogCleaner : 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 %@ %@", ShellEscape(nextended), ShellEscape(oextended)] UTF8String]); - system([[NSString stringWithFormat:@"/usr/libexec/cydia/cydo /bin/chown 0:0 %@", ShellEscape(oextended)] UTF8String]); - } + 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]); @@ -4345,8 +4370,10 @@ static _H Diversions_; + (NSArray *) _attributeKeys { return [NSArray arrayWithObjects: + @"bittage", @"bbsnum", @"build", + @"cells", @"coreFoundationVersionNumber", @"device", @"ecid", @@ -4375,6 +4402,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_; } @@ -4399,6 +4437,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]; @@ -4582,10 +4643,7 @@ static _H Diversions_; } - (NSArray *) getDisplayIdentifiers { - NSSet *set([SBSCopyDisplayIdentifiers() autorelease]); - if (set == nil || ![set isKindOfClass:[NSSet class]]) - return [NSArray array]; - return [set allObjects]; + return SBSCopyApplicationDisplayIdentifiers(false, false); } - (NSString *) getLocalizedNameForDisplayIdentifier:(NSString *)identifier { @@ -4804,10 +4862,16 @@ static _H Diversions_; } - (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]]; } @@ -6226,7 +6290,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]] ]]; } @@ -6255,6 +6319,7 @@ bool DepSubstrate(const pkgCache::VerIterator &iterator) { std::vector, _H>> buttons_; _H sheet_; _H button_; + _H versions_; } - (id) initWithDatabase:(Database *)database forPackage:(NSString *)name withReferrer:(NSString *)referrer; @@ -6267,18 +6332,38 @@ bool DepSubstrate(const pkgCache::VerIterator &iterator) { return [NSURL URLWithString:[NSString stringWithFormat:@"cydia://package/%@", (id) name_]]; } +- (void) _clickButtonWithPackage:(Package *)package { + [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 [delegate_ clearPackage:package_]; else if ([name isEqualToString:@"REMOVE"]) - [delegate_ removePackage:package_]; - else if ([name isEqualToString:@"UPGRADE"]) - [delegate_ installPackage:package_]; + return [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"]; + + [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); + + [delegate_ installPackage:package_]; } - (void) actionSheet:(UIActionSheet *)sheet clickedButtonAtIndex:(NSInteger)button { @@ -6294,6 +6379,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]; } } @@ -6323,11 +6418,8 @@ 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]; - } + for (NSString *button in buttons) + [sheet_ addButtonWithTitle:button]; [sheet_ setContext:@"modify"]; [delegate_ showActionSheet:sheet_ fromItem:[[self navigationItem] rightBarButtonItem]]; @@ -6368,6 +6460,7 @@ bool DepSubstrate(const pkgCache::VerIterator &iterator) { sheet_ = nil; package_ = [database_ packageWithName:name_]; + versions_ = [package_ downgrades]; buttons_.clear(); @@ -6387,6 +6480,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; @@ -8448,8 +8543,7 @@ static void HomeControllerReachabilityCallback(SCNetworkReachabilityRef reachabi [Sources_ removeObjectForKey:[source key]]; - [delegate_ _saveConfig]; - [delegate_ reloadDataWithInvocation:nil]; + [delegate_ syncData]; } } @@ -9035,9 +9129,9 @@ static void HomeControllerReachabilityCallback(SCNetworkReachabilityRef reachabi - (void) reloadSpringBoard { if (kCFCoreFoundationVersionNumber >= 700) // XXX: iOS 6.x - system("/bin/launchctl stop com.apple.backboardd"); + system("/usr/libexec/cydia/cydo /bin/launchctl stop com.apple.backboardd"); else - system("/bin/launchctl stop com.apple.SpringBoard"); + system("/usr/libexec/cydia/cydo /bin/launchctl stop com.apple.SpringBoard"); sleep(15); system("/usr/bin/killall backboardd SpringBoard"); } @@ -10025,6 +10119,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 { @@ -10128,7 +10227,18 @@ static NSMutableDictionary *AutoreleaseDeepMutableCopyOfDictionary(CFTypeRef typ return [(NSMutableDictionary *) copy autorelease]; } +int main_store(int, char *argv[]); + int main(int argc, char *argv[]) { +#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); @@ -10205,29 +10315,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 { @@ -10308,6 +10417,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; @@ -10472,15 +10582,21 @@ int main(int argc, char *argv[]) { _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]); @@ -10495,7 +10611,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"); /* }}} */