#import "TSApplicationsManager.h" #import "TSUtil.h" #import "../Helper/Shared.h" #define TrollStoreErrorDomain @"TrollStoreErrorDomain" @implementation TSApplicationsManager + (instancetype)sharedInstance { static TSApplicationsManager *sharedInstance = nil; static dispatch_once_t onceToken; dispatch_once(&onceToken, ^{ sharedInstance = [[TSApplicationsManager alloc] init]; }); return sharedInstance; } - (NSArray*)installedAppPaths { return trollStoreInstalledAppBundlePaths(); } - (NSDictionary*)infoDictionaryForAppPath:(NSString*)appPath { NSString* infoPlistPath = [appPath stringByAppendingPathComponent:@"Info.plist"]; NSError* error; NSDictionary* infoDict = [NSDictionary dictionaryWithContentsOfURL:[NSURL fileURLWithPath:infoPlistPath] error:&error]; if(error) { NSLog(@"error getting info dict: %@", error); } return infoDict; } - (NSString*)appIdForAppPath:(NSString*)appPath { return [self infoDictionaryForAppPath:appPath][@"CFBundleIdentifier"]; } - (NSString*)displayNameForAppPath:(NSString*)appPath { NSDictionary* infoDict = [self infoDictionaryForAppPath:appPath]; NSString* displayName = infoDict[@"CFBundleDisplayName"]; if(![displayName isKindOfClass:[NSString class]]) displayName = nil; if(!displayName || [displayName isEqualToString:@""]) { displayName = infoDict[@"CFBundleName"]; if(![displayName isKindOfClass:[NSString class]]) displayName = nil; if(!displayName || [displayName isEqualToString:@""]) { displayName = infoDict[@"CFBundleExecutable"]; if(![displayName isKindOfClass:[NSString class]]) displayName = [appPath lastPathComponent]; } } return displayName; } - (NSString*)versionStringForAppPath:(NSString*)appPath { NSDictionary* infoDict = [self infoDictionaryForAppPath:appPath]; NSString* versionString = infoDict[@"CFBundleShortVersionString"]; if(!versionString) { versionString = infoDict[@"CFBundleVersion"]; } return versionString; } - (NSError*)errorForCode:(int)code { NSString* errorDescription = @"Unknown Error"; switch(code) { // IPA install errors case 166: errorDescription = @"The IPA file does not exist or is not accessible."; break; case 167: errorDescription = @"The IPA file does not appear to contain an app."; break; // App install errors case 170: errorDescription = @"Failed to create container for app bundle."; break; case 171: errorDescription = @"A non-TrollStore app with the same identifier is already installed. If you are absolutely sure it is not, you can force install it."; break; case 172: errorDescription = @"The app does not contain an Info.plist file."; break; case 173: errorDescription = @"The app is not signed with a fake CoreTrust certificate and ldid is not installed. Install ldid in the settings tab and try again."; break; case 174: errorDescription = @"The apps main executable does not exists."; break; case 175: errorDescription = @"Failed to sign the app. ldid returned a non zero status code."; break; case 176: errorDescription = @"The apps Info.plist is missing required values."; break; case 177: errorDescription = @"Failed to mark app as TrollStore app."; break; case 178: errorDescription = @"Failed to copy app bundle."; break; // App detach errors /*case 184: errorDescription = @"Refusing to detach, the app is still signed with a fake root certificate. The detach option is only for when you have installed an App Store app on top of a TrollStore app."; break;*/ } NSError* error = [NSError errorWithDomain:TrollStoreErrorDomain code:code userInfo:@{NSLocalizedDescriptionKey : errorDescription}]; return error; } - (int)installIpa:(NSString*)pathToIpa force:(BOOL)force log:(NSString**)logOut { int ret; if(force) { ret = spawnRoot(helperPath(), @[@"install", pathToIpa, @"force"], nil, logOut); } else { ret = spawnRoot(helperPath(), @[@"install", pathToIpa], nil, logOut); } [[NSNotificationCenter defaultCenter] postNotificationName:@"ApplicationsChanged" object:nil]; return ret; } - (int)installIpa:(NSString*)pathToIpa { return [self installIpa:pathToIpa force:NO log:nil]; } - (int)uninstallApp:(NSString*)appId { if(!appId) return -200; int ret = spawnRoot(helperPath(), @[@"uninstall", appId], nil, nil); [[NSNotificationCenter defaultCenter] postNotificationName:@"ApplicationsChanged" object:nil]; return ret; } - (int)uninstallAppByPath:(NSString*)path { if(!path) return -200; int ret = spawnRoot(helperPath(), @[@"uninstall-path", path], nil, nil); [[NSNotificationCenter defaultCenter] postNotificationName:@"ApplicationsChanged" object:nil]; return ret; } /*- (int)detachFromApp:(NSString*)appId { if(!appId) return -200; int ret = spawnRoot(helperPath(), @[@"detach", appId], nil, nil); [[NSNotificationCenter defaultCenter] postNotificationName:@"ApplicationsChanged" object:nil]; return ret; }*/ @end