]> git.saurik.com Git - cydia.git/blobdiff - MobileCydia.mm
Migrate the user's legacy APT lists to new Caches.
[cydia.git] / MobileCydia.mm
index 40785ed2eff7fe4704daaa021bbe16ee46ad0986..ac7f0b9a50a02479ac01d438d4f60c84a84ab046 100644 (file)
@@ -239,12 +239,43 @@ 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; })
+
 static NSString *Colon_;
 NSString *Elision_;
 static NSString *Error_;
 static NSString *Warning_;
 
 static NSString *Cache_;
+#define Cache(file) \
+    [NSString stringWithFormat:@"%@/%s", Cache_, file]
 
 static void (*$SBSSetInterceptsMenuButtonForever)(bool);
 
@@ -3787,12 +3818,14 @@ class CydiaLogCleaner :
     }
     _end
 
+    _root(_system->Lock());
+
     _trace();
     OpProgress progress;
     bool opened;
   open:
     _profile(reloadDataWithInvocation$pkgCacheFile)
-        opened = cache_.Open(progress, true);
+        opened = cache_.Open(progress, false);
     _end
     if (!opened) {
         // XXX: what if there are errors, but Open() == true? this should be merged with popError:
@@ -3822,6 +3855,7 @@ class CydiaLogCleaner :
             }
         }
 
+        _system->UnLock();
         return;
     }
     _trace();
@@ -3949,7 +3983,7 @@ class CydiaLogCleaner :
 - (void) configure {
     NSString *dpkg = [NSString stringWithFormat:@"dpkg --configure -a --status-fd %u", statusfd_];
     _trace();
-    system([dpkg UTF8String]);
+    _root(system([dpkg UTF8String]));
     _trace();
 }
 
@@ -4051,7 +4085,7 @@ class CydiaLogCleaner :
         RestartSubstrate_ = true;
 
     _system->UnLock();
-    pkgPackageManager::OrderResult result = manager_->DoInstall(statusfd_);
+    pkgPackageManager::OrderResult result(_root(manager_->DoInstall(statusfd_)));
     if ([self popErrorWithTitle:title])
         return;
 
@@ -4699,7 +4733,7 @@ static _H<NSMutableSet> Diversions_;
         _assert(close(fds[0]) != -1);
         _assert(close(fds[1]) != -1);
         /* XXX: this should probably not use du */
-        execl("/usr/libexec/cydia/du", "du", "-s", [path UTF8String], NULL);
+        _root(execl("/usr/libexec/cydia/du", "du", "-s", [path UTF8String], NULL));
         exit(1);
     } else {
         _assert(close(fds[1]) != -1);
@@ -5080,7 +5114,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];
         }
@@ -5548,7 +5582,7 @@ bool DepSubstrate(const pkgCache::VerIterator &iterator) {
 
         pid_t pid(ExecFork());
         if (pid == 0) {
-            execl("/usr/bin/sbreload", "sbreload", NULL);
+            _root(execl("/usr/bin/sbreload", "sbreload", NULL));
             perror("sbreload");
 
             exit(0);
@@ -6265,7 +6299,7 @@ bool DepSubstrate(const pkgCache::VerIterator &iterator) {
 
     if ([context isEqualToString:@"modify"]) {
         if (button != [sheet cancelButtonIndex]) {
-            [self _clickButtonWithName:buttons_[button].first];
+            [self performSelector:@selector(_clickButtonWithName:) withObject:buttons_[button].first afterDelay:0];
         }
 
         [sheet dismissWithClickedButtonIndex:-1 animated:YES];
@@ -7891,7 +7925,7 @@ static void HomeControllerReachabilityCallback(SCNetworkReachabilityRef reachabi
 
     pid_t pid(ExecFork());
     if (pid == 0) {
-        FILE *dpkg(popen("dpkg --set-selections", "w"));
+        FILE *dpkg(_root(popen("dpkg --set-selections", "w")));
         fwrite(package, strlen(package), 1, dpkg);
 
         if (on)
@@ -8881,6 +8915,11 @@ static void HomeControllerReachabilityCallback(SCNetworkReachabilityRef reachabi
     [super storeCachedResponse:cached forRequest:request];
 }
 
+- (void) createDiskCachePath {
+    [super createDiskCachePath];
+    _root(chown([[self diskCachePath] UTF8String], 501, 501));
+}
+
 @end
 
 @interface Cydia : UIApplication <
@@ -8891,6 +8930,7 @@ static void HomeControllerReachabilityCallback(SCNetworkReachabilityRef reachabi
     _H<UIWindow> window_;
     _H<CydiaTabBarController> tabbar_;
     _H<CyteTabBarController> emulated_;
+    _H<AppCacheController> appcache_;
 
     _H<NSMutableArray> essential_;
     _H<NSMutableArray> broken_;
@@ -9016,7 +9056,7 @@ static void HomeControllerReachabilityCallback(SCNetworkReachabilityRef reachabi
         if (NSData *data = [NSPropertyListSerialization dataFromPropertyList:Metadata_ format:NSPropertyListBinaryFormat_v1_0 errorDescription:&error]) {
             _trace();
             NSError *error(nil);
-            if (![data writeToFile:@"/var/lib/cydia/metadata.plist" options:NSAtomicWrite error:&error])
+            if (!_root([data writeToFile:@"/var/lib/cydia/metadata.plist" options:NSAtomicWrite error:&error]))
                 NSLog(@"failure to save metadata data: %@", error);
             _trace();
 
@@ -9026,7 +9066,7 @@ static void HomeControllerReachabilityCallback(SCNetworkReachabilityRef reachabi
         }
     }
 
-    CydiaWriteSources();
+    _root(CydiaWriteSources());
 }
 
 // Navigation controller for the queuing badge.
@@ -9059,7 +9099,7 @@ static void HomeControllerReachabilityCallback(SCNetworkReachabilityRef reachabi
     bool recently = false;
     if (update != nil) {
         NSTimeInterval interval([update timeIntervalSinceNow]);
-        if (interval <= 0 && interval > -(15*60))
+        if (interval > -(15*60))
             recently = true;
     }
 
@@ -9128,6 +9168,7 @@ _profile(reloadDataWithInvocation)
         [self setApplicationIconBadgeNumber:0];
     }
 
+    Queuing_ = false;
     [self _updateData];
 
     if (hud != nil)
@@ -9318,7 +9359,7 @@ _end
 
 - (void) _uicache {
     _trace();
-    system("su -c /usr/bin/uicache mobile");
+    system("/usr/bin/uicache");
     _trace();
 }
 
@@ -9391,12 +9432,14 @@ _end
             @synchronized (self) {
                 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]);
+
+                    _root({
+                        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]);
+                    });
                 }
 
                 [self resolve];
@@ -9431,7 +9474,7 @@ _end
     NSAutoreleasePool *pool([[NSAutoreleasePool alloc] init]);
 
     _trace();
-    system([command UTF8String]);
+    _root(system([command UTF8String]));
     _trace();
 
     [pool release];
@@ -9476,6 +9519,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];
@@ -9664,6 +9722,30 @@ _end
     [self saveState];
 }
 
+- (void) applicationDidEnterBackground:(UIApplication *)application {
+    [self saveState];
+}
+
+- (void) applicationWillEnterForeground:(UIApplication *)application {
+    NSDate *closed = [Metadata_ objectForKey:@"LastClosed"];
+    if (closed == nil)
+        return;
+
+    NSTimeInterval interval([closed timeIntervalSinceNow]);
+
+    if (interval <= -(30)) {
+        [tabbar_ setSelectedIndex:0];
+        [[[tabbar_ viewControllers] objectAtIndex:0] popToRootViewControllerAnimated:NO];
+    }
+
+    if (interval <= -(15)) {
+        if (IsReachable("cydia.saurik.com")) {
+            [tabbar_ beginUpdate];
+            [appcache_ reloadURLWithCache:YES];
+        }
+    }
+}
+
 - (void) setConfigurationData:(NSString *)data {
     static Pcre conffile_r("^'(.*)' '(.*)' ([01]) ([01])$");
 
@@ -9787,7 +9869,7 @@ _trace();
     [NSURLCache setSharedURLCache:[[[CYURLCache alloc]
         initWithMemoryCapacity:524288
         diskCapacity:10485760
-        diskPath:[NSString stringWithFormat:@"%@/SDURLCache", Cache_]
+        diskPath:Cache("SDURLCache")
     ] autorelease]];
 
     [CydiaWebViewController _initialize];
@@ -9808,7 +9890,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];
@@ -9908,7 +9991,6 @@ _trace();
     NSDate *closed = [Metadata_ objectForKey:@"LastClosed"];
     if (valid && closed != nil) {
         NSTimeInterval interval([closed timeIntervalSinceNow]);
-        // XXX: Is 30 minutes the optimal time here?
         if (interval <= -(30*60))
             valid = NO;
     }
@@ -10000,54 +10082,6 @@ id Dealloc_(id self, SEL selector) {
     return object;
 }*/
 
-static NSSet *MobilizedFiles_;
-
-static NSURL *MobilizeURL(NSURL *url) {
-    NSString *path([url path]);
-    if ([path hasPrefix:@"/var/root/"]) {
-        NSString *file([path substringFromIndex:10]);
-        if ([MobilizedFiles_ containsObject:file])
-            url = [NSURL fileURLWithPath:[@"/var/mobile/" stringByAppendingString:file] isDirectory:NO];
-    }
-
-    return url;
-}
-
-Class $CFXPreferencesPropertyListSource;
-@class CFXPreferencesPropertyListSource;
-
-MSHook(BOOL, CFXPreferencesPropertyListSource$_backingPlistChangedSinceLastSync, CFXPreferencesPropertyListSource *self, SEL _cmd) {
-    NSURL *&url(MSHookIvar<NSURL *>(self, "_url")), *old(url);
-    NSAutoreleasePool *pool([[NSAutoreleasePool alloc] init]);
-
-    url = MobilizeURL(url);
-    BOOL value; @try {
-        value = _CFXPreferencesPropertyListSource$_backingPlistChangedSinceLastSync(self, _cmd);
-        //NSLog(@"CFX %@ %s", [url absoluteString], value ? "YES" : "NO");
-    } @finally {
-        url = old;
-    }
-
-    [pool release];
-    return value;
-}
-
-MSHook(void *, CFXPreferencesPropertyListSource$createPlistFromDisk, CFXPreferencesPropertyListSource *self, SEL _cmd) {
-    NSURL *&url(MSHookIvar<NSURL *>(self, "_url")), *old(url);
-    NSAutoreleasePool *pool([[NSAutoreleasePool alloc] init]);
-
-    url = MobilizeURL(url);
-    void *value; @try {
-        value = _CFXPreferencesPropertyListSource$createPlistFromDisk(self, _cmd);
-        //NSLog(@"CFX %@ %@", [url absoluteString], value);
-    } @finally {
-        url = old;
-    }
-
-    [pool release];
-    return value;
-}
-
 Class $NSURLConnection;
 
 MSHook(id, NSURLConnection$init$, NSURLConnection *self, SEL _cmd, NSURLRequest *request, id delegate, BOOL usesCache, int64_t maxContentLength, BOOL startImmediately, NSDictionary *connectionProperties) {
@@ -10098,11 +10132,13 @@ Class $NSUserDefaults;
 
 MSHook(id, NSUserDefaults$objectForKey$, NSUserDefaults *self, SEL _cmd, NSString *key) {
     if ([key respondsToSelector:@selector(isEqualToString:)] && [key isEqualToString:@"WebKitLocalStorageDatabasePathPreferenceKey"])
-        return [NSString stringWithFormat:@"%@/LocalStorage", Cache_];
+        return Cache("LocalStorage");
     return _NSUserDefaults$objectForKey$(self, _cmd, key);
 }
 
 int main(int argc, char *argv[]) {
+    setreugid(501, 501);
+
     NSAutoreleasePool *pool([[NSAutoreleasePool alloc] init]);
 
     _trace();
@@ -10150,12 +10186,6 @@ int main(int argc, char *argv[]) {
 
     PackageName = reinterpret_cast<CYString &(*)(Package *, SEL)>(method_getImplementation(class_getInstanceMethod([Package class], @selector(cyname))));
 
-    MobilizedFiles_ = [NSMutableSet setWithObjects:
-        @"Library/Preferences/.GlobalPreferences.plist",
-        @"Library/Preferences/com.apple.Accessibility.plist",
-        @"Library/Preferences/com.apple.preferences.sounds.plist",
-    nil];
-
     /* Library Hacks {{{ */
     class_addMethod(objc_getClass("DOMNodeList"), @selector(countByEnumeratingWithState:objects:count:), (IMP) &DOMNodeList$countByEnumeratingWithState$objects$count$, "I20@0:4^{NSFastEnumerationState}8^@12I16");
 
@@ -10164,22 +10194,6 @@ int main(int argc, char *argv[]) {
         if (Method method = class_getInstanceMethod($WAKWindow, @selector(screenSize)))
             method_setImplementation(method, (IMP) &$WAKWindow$screenSize);
 
-    $CFXPreferencesPropertyListSource = objc_getClass("CFXPreferencesPropertyListSourceSynchronizer");
-    if ($CFXPreferencesPropertyListSource == Nil)
-        $CFXPreferencesPropertyListSource = objc_getClass("CFXPreferencesPropertyListSource");
-
-    Method CFXPreferencesPropertyListSource$_backingPlistChangedSinceLastSync(class_getInstanceMethod($CFXPreferencesPropertyListSource, @selector(_backingPlistChangedSinceLastSync)));
-    if (CFXPreferencesPropertyListSource$_backingPlistChangedSinceLastSync != NULL) {
-        _CFXPreferencesPropertyListSource$_backingPlistChangedSinceLastSync = reinterpret_cast<BOOL (*)(CFXPreferencesPropertyListSource *, SEL)>(method_getImplementation(CFXPreferencesPropertyListSource$_backingPlistChangedSinceLastSync));
-        method_setImplementation(CFXPreferencesPropertyListSource$_backingPlistChangedSinceLastSync, reinterpret_cast<IMP>(&$CFXPreferencesPropertyListSource$_backingPlistChangedSinceLastSync));
-    }
-
-    Method CFXPreferencesPropertyListSource$createPlistFromDisk(class_getInstanceMethod($CFXPreferencesPropertyListSource, @selector(createPlistFromDisk)));
-    if (CFXPreferencesPropertyListSource$createPlistFromDisk != NULL) {
-        _CFXPreferencesPropertyListSource$createPlistFromDisk = reinterpret_cast<void *(*)(CFXPreferencesPropertyListSource *, SEL)>(method_getImplementation(CFXPreferencesPropertyListSource$createPlistFromDisk));
-        method_setImplementation(CFXPreferencesPropertyListSource$createPlistFromDisk, reinterpret_cast<IMP>(&$CFXPreferencesPropertyListSource$createPlistFromDisk));
-    }
-
     $NSURLConnection = objc_getClass("NSURLConnection");
     Method NSURLConnection$init$(class_getInstanceMethod($NSURLConnection, @selector(_initWithRequest:delegate:usesCache:maxContentLength:startImmediately:connectionProperties:)));
     if (NSURLConnection$init$ != NULL) {
@@ -10303,13 +10317,7 @@ int main(int argc, char *argv[]) {
     App_ = [[NSBundle mainBundle] bundlePath];
     Advanced_ = YES;
 
-    setuid(0);
-    setgid(0);
-
-    if (access("/var/mobile/Library/Keyboard/UserDictionary.sqlite", F_OK) == 0)
-        system("mkdir -p /var/root/Library/Keyboard; cp -af /var/mobile/Library/Keyboard/UserDictionary.sqlite /var/root/Library/Keyboard/");
-
-    Cache_ = [[NSString stringWithFormat:@"%@/Library/Caches/com.saurik.Cydia", @"/var/root"] retain];
+    Cache_ = [[NSString stringWithFormat:@"%@/Library/Caches/com.saurik.Cydia", @"/var/mobile"] retain];
 
     /*Method alloc = class_getClassMethod([NSObject class], @selector(alloc));
     alloc_ = alloc->method_imp;
@@ -10443,10 +10451,10 @@ int main(int argc, char *argv[]) {
     } broken = nil;
     /* }}} */
 
-    CydiaWriteSources();
+    _root(CydiaWriteSources());
 
     _trace();
-    MetaFile_.Open("/var/lib/cydia/metadata.cb0");
+    _root(MetaFile_.Open("/var/lib/cydia/metadata.cb0"));
     _trace();
 
     if (Packages_ != nil) {
@@ -10482,21 +10490,14 @@ int main(int argc, char *argv[]) {
 
     if (access("/User", F_OK) != 0 || version != 6) {
         _trace();
-        system("/usr/libexec/cydia/firmware.sh");
+        _root(system("/usr/libexec/cydia/firmware.sh"));
         _trace();
     }
 
-    _assert([[NSFileManager defaultManager]
-        createDirectoryAtPath:@"/var/cache/apt/archives/partial"
-        withIntermediateDirectories:YES
-        attributes:nil
-        error:NULL
-    ]);
-
     if (access("/tmp/cydia.chk", F_OK) == 0) {
-        if (unlink("/var/cache/apt/pkgcache.bin") == -1)
+        if (unlink([Cache("pkgcache.bin") UTF8String]) == -1)
             _assert(errno == ENOENT);
-        if (unlink("/var/cache/apt/srcpkgcache.bin") == -1)
+        if (unlink([Cache("srcpkgcache.bin") UTF8String]) == -1)
             _assert(errno == ENOENT);
     }
 
@@ -10511,6 +10512,16 @@ int main(int argc, char *argv[]) {
     //_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]);
+
+    mkdir([Cache("lists") UTF8String], 0755);
+    mkdir([Cache("lists/partial") UTF8String], 0755);
+    mkdir([Cache("periodic") UTF8String], 0755);
+    _config->Set("Dir::State::Lists", [Cache("lists") UTF8String]);
     /* }}} */
     /* Color Choices {{{ */
     space_ = CGColorSpaceCreateDeviceRGB();
@@ -10534,6 +10545,13 @@ int main(int argc, char *argv[]) {
     //UIKeyboardDisableAutomaticAppearance();
     /* }}} */
 
+    _root({
+        chown([Cache("ApplicationCache.db") UTF8String], 501, 501);
+        chown([Cache("Cache.db") UTF8String], 501, 501);
+        chown([Cache("Cache.db-shm") UTF8String], 501, 501);
+        chown([Cache("Cache.db-wal") UTF8String], 501, 501);
+    });
+
     $SBSSetInterceptsMenuButtonForever = reinterpret_cast<void (*)(bool)>(dlsym(RTLD_DEFAULT, "SBSSetInterceptsMenuButtonForever"));
 
     const char *symbol(kCFCoreFoundationVersionNumber >= 800 ? "MGGetBoolAnswer" : "GSSystemHasCapability");