};
// }}}
-struct Root {
- static bool root_;
+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);
+}
- Root(bool real) {
- _assert(!root_);
- root_ = true;
+struct Root {
+ Root() {
_trace();
- _assert(setreuid(real ? 0 : 501, 0) != -1);
+ setreugid(0, 0);
+ _assert(pthread_setugid_np(0, 0) != -1);
+ setreguid(501, 501);
}
~Root() {
- root_ = false;
_trace();
- _assert(setreuid(501, 501) != -1);
- }
-
- operator bool() const {
- return true;
+ setreugid(0, 0);
+ _assert(pthread_setugid_np(KAUTH_UID_NONE, KAUTH_GID_NONE) != -1);
+ setreguid(501, 501);
}
};
-bool Root::root_;
-
-#define _root(real) \
- if (__attribute__((__unused__)) const Root &root = Root(real))
+#define _root(code) \
+ ({ Root _root; code; })
static NSString *Colon_;
NSString *Elision_;
static int Finish_;
static bool RestartSubstrate_;
+static bool UpgradeCydia_;
static NSArray *Finishes_;
#define SpringBoard_ "/System/Library/LaunchDaemons/com.apple.SpringBoard.plist"
static time_t now_;
bool IsWildcat_;
-static CGFloat ScreenScale_;
+CGFloat ScreenScale_;
static NSString *Idiom_;
static _H<NSString> Firmware_;
static NSString *Major_;
} }
- (NSArray *) warnings {
+@synchronized (database_) {
+ if ([database_ era] != era_ || file_.end())
+ return nil;
+
NSMutableArray *warnings([NSMutableArray arrayWithCapacity:4]);
const char *name(iterator_.Name());
bool user = false;
bool _private = false;
bool stash = false;
+ bool dbstash = false;
bool dsstore = false;
bool repository = [[self section] isEqualToString:@"Repositories"];
_private = true;
else if (!stash && [file isEqualToString:@"/var/stash"])
stash = true;
+ else if (!dbstash && [file isEqualToString:@"/var/db/stash"])
+ dbstash = true;
else if (!dsstore && [file hasSuffix:@"/.DS_Store"])
dsstore = true;
[warnings addObject:[NSString stringWithFormat:UCLocalize("FILES_INSTALLED_TO"), @"/private"]];
if (stash)
[warnings addObject:[NSString stringWithFormat:UCLocalize("FILES_INSTALLED_TO"), @"/var/stash"]];
+ if (dbstash)
+ [warnings addObject:[NSString stringWithFormat:UCLocalize("FILES_INSTALLED_TO"), @"/var/db/stash"]];
if (dsstore)
[warnings addObject:[NSString stringWithFormat:UCLocalize("FILES_INSTALLED_TO"), @".DS_Store"]];
}
return [warnings count] == 0 ? nil : warnings;
-}
+} }
- (NSArray *) applications {
NSString *me([[NSBundle mainBundle] bundleIdentifier]);
}
_end
+ _root(_system->Lock());
+
_trace();
OpProgress progress;
bool opened;
}
}
+ _system->UnLock();
return;
}
_trace();
- (void) configure {
NSString *dpkg = [NSString stringWithFormat:@"dpkg --configure -a --status-fd %u", statusfd_];
_trace();
- system([dpkg UTF8String]);
+ _root(system([dpkg UTF8String]));
_trace();
}
RestartSubstrate_ = true;
_system->UnLock();
- pkgPackageManager::OrderResult result;
- _root(true) result = manager_->DoInstall(statusfd_);
+ pkgPackageManager::OrderResult result(_root(manager_->DoInstall(statusfd_)));
if ([self popErrorWithTitle:title])
return;
_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);
return [CydiaWebViewController requestWithHeaders:[super webView:view resource:resource willSendRequest:request redirectResponse:response fromDataSource:source]];
}
+- (NSURLRequest *) webThreadWebView:(WebView *)view resource:(id)resource willSendRequest:(NSURLRequest *)request redirectResponse:(NSURLResponse *)response fromDataSource:(WebDataSource *)source {
+ return [CydiaWebViewController requestWithHeaders:[super webThreadWebView:view resource:resource willSendRequest:request redirectResponse:response fromDataSource:source]];
+}
+
+ (NSURLRequest *) requestWithHeaders:(NSURLRequest *)request {
NSMutableURLRequest *copy([[request mutableCopy] autorelease]);
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];
}
issues_ = [NSMutableArray arrayWithCapacity:4];
+ UpgradeCydia_ = false;
+
for (Package *package in packages) {
pkgCache::PkgIterator iterator([package iterator]);
NSString *name([package id]);
[removes addObject:name];
}
+ if ([name isEqualToString:@"cydia"])
+ UpgradeCydia_ = true;
+
substrate_ |= DepSubstrate(policy->GetCandidateVer(iterator));
substrate_ |= DepSubstrate(iterator.CurrentVer());
}
pid_t pid(ExecFork());
if (pid == 0) {
- execl("/usr/bin/sbreload", "sbreload", NULL);
+ _root(execl("/usr/bin/sbreload", "sbreload", NULL));
perror("sbreload");
exit(0);
if ([context isEqualToString:@"modify"]) {
if (button != [sheet cancelButtonIndex]) {
- [self _clickButtonWithName:buttons_[button].first];
+ if (IsWildcat_)
+ [self performSelector:@selector(_clickButtonWithName:) withObject:buttons_[button].first afterDelay:0];
+ else
+ [self _clickButtonWithName:buttons_[button].first];
}
- [sheet dismissWithClickedButtonIndex:-1 animated:YES];
+ [sheet dismissWithClickedButtonIndex:button animated:YES];
}
}
// on the iPad, this view controller is ALSO visible. :(
if (IsWildcat_)
- if (UIViewController *top = [self topViewController])
- if (top != visible)
- [top reloadData];
+ if (UIViewController *modal = [self modalViewController])
+ if ([modal modalPresentationStyle] == UIModalPresentationFormSheet)
+ if (UIViewController *top = [self topViewController])
+ if (top != visible)
+ [top reloadData];
}
- (void) unloadData {
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)
case 1: {
NSString *href = [[alert textField] text];
- static Pcre href_r("^http(s?)://[^# ]*$");
+ static Pcre href_r("^(http(s?)://|file:///)[^# ]*$");
if (!href_r(href)) {
UIAlertView *alert = [[[UIAlertView alloc]
initWithTitle:[NSString stringWithFormat:Colon_, Error_, UCLocalize("INVALID_URL")]
[super storeCachedResponse:cached forRequest:request];
}
+- (void) createDiskCachePath {
+ [super createDiskCachePath];
+ _root(chown([[self diskCachePath] UTF8String], 501, 501));
+}
+
@end
@interface Cydia : UIApplication <
_H<UIWindow> window_;
_H<CydiaTabBarController> tabbar_;
_H<CyteTabBarController> emulated_;
+ _H<AppCacheController> appcache_;
_H<NSMutableArray> essential_;
_H<NSMutableArray> broken_;
if (NSData *data = [NSPropertyListSerialization dataFromPropertyList:Metadata_ format:NSPropertyListBinaryFormat_v1_0 errorDescription:&error]) {
_trace();
NSError *error(nil);
- _root(true) if (![data writeToFile:@"/var/lib/cydia/metadata.plist" options:NSAtomicWrite error:&error])
+ if (!_root([data writeToFile:@"/var/lib/cydia/metadata.plist" options:NSAtomicWrite error:&error]))
NSLog(@"failure to save metadata data: %@", error);
_trace();
}
}
- CydiaWriteSources();
+ _root(CydiaWriteSources());
}
// Navigation controller for the queuing badge.
bool recently = false;
if (update != nil) {
NSTimeInterval interval([update timeIntervalSinceNow]);
- if (interval <= 0 && interval > -(15*60))
+ if (interval > -(15*60))
recently = true;
}
[self setApplicationIconBadgeNumber:0];
}
+ Queuing_ = false;
[self _updateData];
if (hud != nil)
- (void) presentModalViewController:(UIViewController *)controller force:(BOOL)force {
UINavigationController *navigation([[[UINavigationController alloc] initWithRootViewController:controller] autorelease]);
- if (IsWildcat_)
- [navigation setModalPresentationStyle:UIModalPresentationFormSheet];
UIViewController *parent;
if (emulated_ == nil)
parent = tabbar_;
}
+ if (IsWildcat_)
+ [navigation setModalPresentationStyle:UIModalPresentationFormSheet];
[parent presentModalViewController:navigation animated:YES];
}
- (void) _uicache {
_trace();
- system("/usr/bin/uicache");
+
+ if (UpgradeCydia_ && Finish_ > 0) {
+ setreugid(0, 0);
+ system("su -c /usr/bin/uicache mobile");
+ } else {
+ system("/usr/bin/uicache");
+ }
+
_trace();
}
} else if ([context isEqualToString:@"fixhalf"]) {
if (button == [alert cancelButtonIndex]) {
@synchronized (self) {
- _root(false) for (Package *broken in (id) broken_) {
+ for (Package *broken in (id) broken_) {
[broken remove];
-
NSString *id = [broken id];
- unlink([[NSString stringWithFormat:@"/var/lib/dpkg/info/%@.prerm", id] UTF8String]);
- unlink([[NSString stringWithFormat:@"/var/lib/dpkg/info/%@.postrm", id] UTF8String]);
- unlink([[NSString stringWithFormat:@"/var/lib/dpkg/info/%@.preinst", id] UTF8String]);
- unlink([[NSString stringWithFormat:@"/var/lib/dpkg/info/%@.postinst", id] UTF8String]);
+
+ _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];
NSAutoreleasePool *pool([[NSAutoreleasePool alloc] init]);
_trace();
- system([command UTF8String]);
+ _root(system([command UTF8String]));
_trace();
[pool release];
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];
[self saveState];
}
+- (void) applicationDidEnterBackground:(UIApplication *)application {
+ if (kCFCoreFoundationVersionNumber < 1000 && [self isSafeToSuspend])
+ return [self terminateWithSuccess];
+ [self saveState];
+}
+
+- (void) applicationWillEnterForeground:(UIApplication *)application {
+ NSDate *closed = [Metadata_ objectForKey:@"LastClosed"];
+ if (closed == nil)
+ return;
+
+ NSTimeInterval interval([closed timeIntervalSinceNow]);
+
+ if (interval <= -(30*60)) {
+ [tabbar_ setSelectedIndex:0];
+ [[[tabbar_ viewControllers] objectAtIndex:0] popToRootViewControllerAnimated:NO];
+ }
+
+ if (interval <= -(15*60)) {
+ if (IsReachable("cydia.saurik.com")) {
+ [tabbar_ beginUpdate];
+ [appcache_ reloadURLWithCache:YES];
+ }
+ }
+}
+
- (void) setConfigurationData:(NSString *)data {
static Pcre conffile_r("^'(.*)' '(.*)' ([01]) ([01])$");
- (void) stash {
[[UIApplication sharedApplication] setStatusBarStyle:UIStatusBarStyleBlackOpaque];
UpdateExternalStatus(1);
- _root(true) [self yieldToSelector:@selector(system:) withObject:@"/usr/libexec/cydia/free.sh"];
+ [self yieldToSelector:@selector(system:) withObject:@"/usr/libexec/cydia/free.sh"];
UpdateExternalStatus(0);
[self removeStashController];
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];
Stash_("/Library/Wallpaper");
//Stash_("/usr/bin");
Stash_("/usr/include");
- Stash_("/usr/lib/pam");
Stash_("/usr/share");
//Stash_("/var/lib");
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;
}
}
int main(int argc, char *argv[]) {
- seteuid(501);
+ setreugid(501, 501);
NSAutoreleasePool *pool([[NSAutoreleasePool alloc] init]);
} broken = nil;
/* }}} */
- CydiaWriteSources();
+ _root(CydiaWriteSources());
_trace();
- _root(true) MetaFile_.Open("/var/lib/cydia/metadata.cb0");
+ mkdir("/var/mobile/Library/Cydia", 0755);
+ MetaFile_.Open("/var/mobile/Library/Cydia/metadata.cb0");
_trace();
if (Packages_ != nil) {
/*if (substrate && access("/Library/MobileSubstrate/MobileSubstrate.dylib", F_OK) == 0)
dlopen("/Library/MobileSubstrate/MobileSubstrate.dylib", RTLD_LAZY | RTLD_GLOBAL);*/
+ if (kCFCoreFoundationVersionNumber > 1000)
+ _root(system([[NSString stringWithFormat:@"/usr/libexec/cydia/setnsfpn /var/lib"] UTF8String]));
+
int version([[NSString stringWithContentsOfFile:@"/var/lib/cydia/firmware.ver"] intValue]);
- _root(true) if (access("/User", F_OK) != 0 || version != 6) {
+ if (access("/User", F_OK) != 0 || version != 6) {
_trace();
- system("/usr/libexec/cydia/firmware.sh");
+ _root(system("/usr/libexec/cydia/firmware.sh"));
_trace();
}
mkdir([Cache("lists") UTF8String], 0755);
mkdir([Cache("lists/partial") UTF8String], 0755);
mkdir([Cache("periodic") UTF8String], 0755);
- _config->Set("Dir::State", [Cache_ UTF8String]);
+ _config->Set("Dir::State::Lists", [Cache("lists") UTF8String]);
/* }}} */
/* Color Choices {{{ */
space_ = CGColorSpaceCreateDeviceRGB();
//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");