mirror of
				https://github.com/opa334/TrollStore.git
				synced 2025-11-04 15:42:35 +08:00 
			
		
		
		
	1.5.0~b1
This commit is contained in:
		
							parent
							
								
									d244304313
								
							
						
					
					
						commit
						3aafa51503
					
				@ -123,6 +123,33 @@ NSString* appPathForAppId(NSString* appId)
 | 
				
			|||||||
	return nil;
 | 
						return nil;
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					NSString* findAppNameInBundlePath(NSString* bundlePath)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
						NSArray* bundleItems = [[NSFileManager defaultManager] contentsOfDirectoryAtPath:bundlePath error:nil];
 | 
				
			||||||
 | 
						for(NSString* bundleItem in bundleItems)
 | 
				
			||||||
 | 
						{
 | 
				
			||||||
 | 
							if([bundleItem.pathExtension isEqualToString:@"app"])
 | 
				
			||||||
 | 
							{
 | 
				
			||||||
 | 
								return bundleItem;
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						return nil;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					NSString* findAppPathInBundlePath(NSString* bundlePath)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
						NSString* appName = findAppNameInBundlePath(bundlePath);
 | 
				
			||||||
 | 
						if(!appName) return nil;
 | 
				
			||||||
 | 
						return [bundlePath stringByAppendingPathComponent:appName];
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					NSURL* findAppURLInBundleURL(NSURL* bundleURL)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
						NSString* appName = findAppNameInBundlePath(bundleURL.path);
 | 
				
			||||||
 | 
						if(!appName) return nil;
 | 
				
			||||||
 | 
						return [bundleURL URLByAppendingPathComponent:appName];
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
BOOL isMachoFile(NSString* filePath)
 | 
					BOOL isMachoFile(NSString* filePath)
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
	FILE* file = fopen(filePath.fileSystemRepresentation, "r");
 | 
						FILE* file = fopen(filePath.fileSystemRepresentation, "r");
 | 
				
			||||||
@ -205,12 +232,13 @@ void setTSURLSchemeState(BOOL newState, NSString* customAppPath)
 | 
				
			|||||||
	}
 | 
						}
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					void installLdid(NSString* ldidToCopyPath, NSString* ldidVersion)
 | 
				
			||||||
void installLdid(NSString* ldidToCopyPath)
 | 
					 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
	if(![[NSFileManager defaultManager] fileExistsAtPath:ldidToCopyPath]) return;
 | 
						if(![[NSFileManager defaultManager] fileExistsAtPath:ldidToCopyPath]) return;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	NSString* ldidPath = [trollStoreAppPath() stringByAppendingPathComponent:@"ldid"];
 | 
						NSString* ldidPath = [trollStoreAppPath() stringByAppendingPathComponent:@"ldid"];
 | 
				
			||||||
 | 
						NSString* ldidVersionPath = [trollStoreAppPath() stringByAppendingPathComponent:@"ldid.version"];
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	if([[NSFileManager defaultManager] fileExistsAtPath:ldidPath])
 | 
						if([[NSFileManager defaultManager] fileExistsAtPath:ldidPath])
 | 
				
			||||||
	{
 | 
						{
 | 
				
			||||||
		[[NSFileManager defaultManager] removeItemAtPath:ldidPath error:nil];
 | 
							[[NSFileManager defaultManager] removeItemAtPath:ldidPath error:nil];
 | 
				
			||||||
@ -218,8 +246,11 @@ void installLdid(NSString* ldidToCopyPath)
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
	[[NSFileManager defaultManager] copyItemAtPath:ldidToCopyPath toPath:ldidPath error:nil];
 | 
						[[NSFileManager defaultManager] copyItemAtPath:ldidToCopyPath toPath:ldidPath error:nil];
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						NSData* ldidVersionData = [ldidVersion dataUsingEncoding:NSUTF8StringEncoding];
 | 
				
			||||||
 | 
						[ldidVersionData writeToFile:ldidVersionPath atomically:YES];
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	chmod(ldidPath.fileSystemRepresentation, 0755);
 | 
						chmod(ldidPath.fileSystemRepresentation, 0755);
 | 
				
			||||||
	chown(ldidPath.fileSystemRepresentation, 0, 0);
 | 
						chmod(ldidVersionPath.fileSystemRepresentation, 0644);
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
BOOL isLdidInstalled(void)
 | 
					BOOL isLdidInstalled(void)
 | 
				
			||||||
@ -433,7 +464,6 @@ int signApp(NSString* appPath)
 | 
				
			|||||||
	NSObject *tsBundleIsPreSigned = appInfoDict[@"TSBundlePreSigned"];
 | 
						NSObject *tsBundleIsPreSigned = appInfoDict[@"TSBundlePreSigned"];
 | 
				
			||||||
	if([tsBundleIsPreSigned isKindOfClass:[NSNumber class]])
 | 
						if([tsBundleIsPreSigned isKindOfClass:[NSNumber class]])
 | 
				
			||||||
	{
 | 
						{
 | 
				
			||||||
		
 | 
					 | 
				
			||||||
		// if TSBundlePreSigned = YES, this bundle has been externally signed so we can skip over signing it now
 | 
							// if TSBundlePreSigned = YES, this bundle has been externally signed so we can skip over signing it now
 | 
				
			||||||
		NSNumber *tsBundleIsPreSignedNum = (NSNumber *)tsBundleIsPreSigned;
 | 
							NSNumber *tsBundleIsPreSignedNum = (NSNumber *)tsBundleIsPreSigned;
 | 
				
			||||||
		if([tsBundleIsPreSignedNum boolValue] == YES)
 | 
							if([tsBundleIsPreSignedNum boolValue] == YES)
 | 
				
			||||||
@ -442,7 +472,7 @@ int signApp(NSString* appPath)
 | 
				
			|||||||
			return 0;
 | 
								return 0;
 | 
				
			||||||
		}
 | 
							}
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
	
 | 
					
 | 
				
			||||||
	SecStaticCodeRef codeRef = getStaticCodeRef(executablePath);
 | 
						SecStaticCodeRef codeRef = getStaticCodeRef(executablePath);
 | 
				
			||||||
	if(codeRef != NULL)
 | 
						if(codeRef != NULL)
 | 
				
			||||||
	{
 | 
						{
 | 
				
			||||||
@ -478,34 +508,8 @@ int signApp(NSString* appPath)
 | 
				
			|||||||
	}
 | 
						}
 | 
				
			||||||
	else
 | 
						else
 | 
				
			||||||
	{
 | 
						{
 | 
				
			||||||
		// Work around an ldid bug where it doesn't keep entitlements on stray binaries
 | 
					 | 
				
			||||||
		NSMutableDictionary* storedEntitlements = [NSMutableDictionary new];
 | 
					 | 
				
			||||||
		NSDirectoryEnumerator *enumerator = [[NSFileManager defaultManager] enumeratorAtURL:[NSURL fileURLWithPath:appPath] includingPropertiesForKeys:nil options:0 errorHandler:nil];
 | 
					 | 
				
			||||||
		NSURL* fileURL;
 | 
					 | 
				
			||||||
		while(fileURL = [enumerator nextObject])
 | 
					 | 
				
			||||||
		{
 | 
					 | 
				
			||||||
			NSString* filePath = fileURL.path;
 | 
					 | 
				
			||||||
			if(isMachoFile(filePath))
 | 
					 | 
				
			||||||
			{
 | 
					 | 
				
			||||||
				storedEntitlements[filePath] = dumpEntitlementsFromBinaryAtPath(filePath);
 | 
					 | 
				
			||||||
			}
 | 
					 | 
				
			||||||
		}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
		// app has entitlements, keep them
 | 
							// app has entitlements, keep them
 | 
				
			||||||
		ldidRet = runLdid(@[@"-s", certArg, appPath], nil, &errorOutput);
 | 
							ldidRet = runLdid(@[@"-s", certArg, appPath], nil, &errorOutput);
 | 
				
			||||||
 | 
					 | 
				
			||||||
		[storedEntitlements enumerateKeysAndObjectsUsingBlock:^(NSString* binaryPath, NSDictionary* entitlements, BOOL* stop)
 | 
					 | 
				
			||||||
		{
 | 
					 | 
				
			||||||
			NSDictionary* newEntitlements = dumpEntitlementsFromBinaryAtPath(binaryPath);
 | 
					 | 
				
			||||||
			if(!newEntitlements || ![newEntitlements isEqualToDictionary:entitlements])
 | 
					 | 
				
			||||||
			{
 | 
					 | 
				
			||||||
				NSString* tmpEntitlementPlistPath = [NSTemporaryDirectory() stringByAppendingPathComponent:@"ent.xml"];
 | 
					 | 
				
			||||||
				[entitlements writeToURL:[NSURL fileURLWithPath:tmpEntitlementPlistPath] error:nil];
 | 
					 | 
				
			||||||
				NSString* tmpEntitlementArg = [@"-S" stringByAppendingString:tmpEntitlementPlistPath];
 | 
					 | 
				
			||||||
				runLdid(@[tmpEntitlementArg, certArg, binaryPath], nil, nil);
 | 
					 | 
				
			||||||
				[[NSFileManager defaultManager] removeItemAtPath:tmpEntitlementPlistPath error:nil];
 | 
					 | 
				
			||||||
			}
 | 
					 | 
				
			||||||
		}];
 | 
					 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	NSLog(@"ldid exited with status %d", ldidRet);
 | 
						NSLog(@"ldid exited with status %d", ldidRet);
 | 
				
			||||||
@ -581,7 +585,7 @@ void applyPatchesToInfoDictionary(NSString* appPath)
 | 
				
			|||||||
// 172: no info.plist found in app
 | 
					// 172: no info.plist found in app
 | 
				
			||||||
// 173: app is not signed and cannot be signed because ldid not installed or didn't work
 | 
					// 173: app is not signed and cannot be signed because ldid not installed or didn't work
 | 
				
			||||||
// 174: 
 | 
					// 174: 
 | 
				
			||||||
int installApp(NSString* appPackagePath, BOOL sign, BOOL force, BOOL isTSUpdate)
 | 
					int installApp(NSString* appPackagePath, BOOL sign, BOOL force, BOOL isTSUpdate, BOOL useInstalldMethod)
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
	NSLog(@"[installApp force = %d]", force);
 | 
						NSLog(@"[installApp force = %d]", force);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@ -590,18 +594,18 @@ int installApp(NSString* appPackagePath, BOOL sign, BOOL force, BOOL isTSUpdate)
 | 
				
			|||||||
	NSArray* items = [[NSFileManager defaultManager] contentsOfDirectoryAtPath:appPayloadPath error:nil];
 | 
						NSArray* items = [[NSFileManager defaultManager] contentsOfDirectoryAtPath:appPayloadPath error:nil];
 | 
				
			||||||
	if(!items) return 167;
 | 
						if(!items) return 167;
 | 
				
			||||||
	
 | 
						
 | 
				
			||||||
	NSString* appBundlePath;
 | 
						NSString* appBundleToInstallPath;
 | 
				
			||||||
	for(NSString* item in items)
 | 
						for(NSString* item in items)
 | 
				
			||||||
	{
 | 
						{
 | 
				
			||||||
		if([item.pathExtension isEqualToString:@"app"])
 | 
							if([item.pathExtension isEqualToString:@"app"])
 | 
				
			||||||
		{
 | 
							{
 | 
				
			||||||
			appBundlePath = [appPayloadPath stringByAppendingPathComponent:item];
 | 
								appBundleToInstallPath = [appPayloadPath stringByAppendingPathComponent:item];
 | 
				
			||||||
			break;
 | 
								break;
 | 
				
			||||||
		}
 | 
							}
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
	if(!appBundlePath) return 167;
 | 
						if(!appBundleToInstallPath) return 167;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	NSString* appId = appIdForAppPath(appBundlePath);
 | 
						NSString* appId = appIdForAppPath(appBundleToInstallPath);
 | 
				
			||||||
	if(!appId) return 176;
 | 
						if(!appId) return 176;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	if(([appId.lowercaseString isEqualToString:@"com.opa334.trollstore"] && !isTSUpdate) || [immutableAppBundleIdentifiers() containsObject:appId.lowercaseString])
 | 
						if(([appId.lowercaseString isEqualToString:@"com.opa334.trollstore"] && !isTSUpdate) || [immutableAppBundleIdentifiers() containsObject:appId.lowercaseString])
 | 
				
			||||||
@ -609,115 +613,151 @@ int installApp(NSString* appPackagePath, BOOL sign, BOOL force, BOOL isTSUpdate)
 | 
				
			|||||||
		return 179;
 | 
							return 179;
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	if(!infoDictionaryForAppPath(appBundlePath)) return 172;
 | 
						if(!infoDictionaryForAppPath(appBundleToInstallPath)) return 172;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	if(!isTSUpdate)
 | 
						if(!isTSUpdate)
 | 
				
			||||||
	{
 | 
						{
 | 
				
			||||||
		applyPatchesToInfoDictionary(appBundlePath);
 | 
							applyPatchesToInfoDictionary(appBundleToInstallPath);
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	if(sign)
 | 
						if(sign)
 | 
				
			||||||
	{
 | 
						{
 | 
				
			||||||
		int signRet = signApp(appBundlePath);
 | 
							int signRet = signApp(appBundleToInstallPath);
 | 
				
			||||||
		if(signRet != 0) return signRet;
 | 
							if(signRet != 0) return signRet;
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	loadMCMFramework();
 | 
						MCMAppContainer* appContainer = [objc_getClass("MCMAppContainer") containerWithIdentifier:appId createIfNecessary:NO existed:nil error:nil];
 | 
				
			||||||
 | 
						if(appContainer)
 | 
				
			||||||
 | 
						{
 | 
				
			||||||
 | 
							// App update
 | 
				
			||||||
 | 
							// Replace existing bundle with new version
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	BOOL existed;
 | 
							// Check if the existing app bundle is empty
 | 
				
			||||||
	NSError* mcmError;
 | 
							NSURL* bundleContainerURL = appContainer.url;
 | 
				
			||||||
	MCMAppContainer* appContainer = [objc_getClass("MCMAppContainer") containerWithIdentifier:appId createIfNecessary:YES existed:&existed error:&mcmError];
 | 
							NSURL* appBundleURL = findAppURLInBundleURL(bundleContainerURL);
 | 
				
			||||||
	if(!appContainer || mcmError)
 | 
					 | 
				
			||||||
	{
 | 
					 | 
				
			||||||
		NSLog(@"[installApp] failed to create app container for %@: %@", appId, mcmError);
 | 
					 | 
				
			||||||
		return 170;
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
	if(existed)
 | 
							// Make sure the installed app is a TrollStore app or the container is empty (or the force flag is set)
 | 
				
			||||||
	{
 | 
							NSURL* trollStoreMarkURL = [bundleContainerURL URLByAppendingPathComponent:@"_TrollStore"];
 | 
				
			||||||
		NSLog(@"[installApp] got existing app container: %@", appContainer);
 | 
							if(!appBundleURL && ![trollStoreMarkURL checkResourceIsReachableAndReturnError:nil] && !force)
 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
	else
 | 
					 | 
				
			||||||
	{
 | 
					 | 
				
			||||||
		NSLog(@"[installApp] created app container: %@", appContainer);
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	// check if the bundle is empty
 | 
					 | 
				
			||||||
	BOOL isEmpty = YES;
 | 
					 | 
				
			||||||
	NSArray* bundleItems = [[NSFileManager defaultManager] contentsOfDirectoryAtPath:appContainer.url.path error:nil];
 | 
					 | 
				
			||||||
	for(NSString* bundleItem in bundleItems)
 | 
					 | 
				
			||||||
	{
 | 
					 | 
				
			||||||
		if([bundleItem.pathExtension isEqualToString:@"app"])
 | 
					 | 
				
			||||||
		{
 | 
							{
 | 
				
			||||||
			isEmpty = NO;
 | 
								NSLog(@"[installApp] already installed and not a TrollStore app... bailing out");
 | 
				
			||||||
			break;
 | 
								return 171;
 | 
				
			||||||
		}
 | 
							}
 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
	NSLog(@"[installApp] container is empty? %d", isEmpty);
 | 
							// Terminate app if it's still running
 | 
				
			||||||
 | 
							if(!isTSUpdate)
 | 
				
			||||||
	// Make sure there isn't already an app store app installed with the same identifier
 | 
					 | 
				
			||||||
	NSURL* trollStoreMarkURL = [appContainer.url URLByAppendingPathComponent:@"_TrollStore"];
 | 
					 | 
				
			||||||
	if(existed && !isEmpty && ![trollStoreMarkURL checkResourceIsReachableAndReturnError:nil] && !force)
 | 
					 | 
				
			||||||
	{
 | 
					 | 
				
			||||||
		NSLog(@"[installApp] already installed and not a TrollStore app... bailing out");
 | 
					 | 
				
			||||||
		return 171;
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	// Mark app as TrollStore app
 | 
					 | 
				
			||||||
	BOOL marked = [[NSFileManager defaultManager] createFileAtPath:trollStoreMarkURL.path contents:[NSData data] attributes:nil];
 | 
					 | 
				
			||||||
	if(!marked)
 | 
					 | 
				
			||||||
	{
 | 
					 | 
				
			||||||
		NSLog(@"[installApp] failed to mark %@ as TrollStore app", appId);
 | 
					 | 
				
			||||||
		return 177;
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	fixPermissionsOfAppBundle(appBundlePath);
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	// Wipe old version if needed
 | 
					 | 
				
			||||||
	if(existed)
 | 
					 | 
				
			||||||
	{
 | 
					 | 
				
			||||||
		if(![appId isEqualToString:@"com.opa334.TrollStore"])
 | 
					 | 
				
			||||||
		{
 | 
							{
 | 
				
			||||||
			BKSTerminateApplicationForReasonAndReportWithDescription(appId, 5, false, @"TrollStore - App updated");
 | 
								BKSTerminateApplicationForReasonAndReportWithDescription(appId, 5, false, @"TrollStore - App updated");
 | 
				
			||||||
		}
 | 
							}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
		NSLog(@"[installApp] found existing TrollStore app, cleaning directory");
 | 
							NSLog(@"[installApp] replacing existing app with new version");
 | 
				
			||||||
		NSDirectoryEnumerator *enumerator = [[NSFileManager defaultManager] enumeratorAtURL:appContainer.url includingPropertiesForKeys:nil options:0 errorHandler:nil];
 | 
					
 | 
				
			||||||
		NSURL* fileURL;
 | 
							// Delete existing .app directory if it exists
 | 
				
			||||||
		while(fileURL = [enumerator nextObject])
 | 
							if(appBundleURL)
 | 
				
			||||||
		{
 | 
							{
 | 
				
			||||||
			// do not under any circumstance delete this file as it makes iOS loose the app registration
 | 
								[[NSFileManager defaultManager] removeItemAtURL:appBundleURL error:nil];
 | 
				
			||||||
			if([fileURL.lastPathComponent isEqualToString:@".com.apple.mobile_container_manager.metadata.plist"] || [fileURL.lastPathComponent isEqualToString:@"_TrollStore"])
 | 
					 | 
				
			||||||
			{
 | 
					 | 
				
			||||||
				NSLog(@"[installApp] skipping removal of %@", fileURL);
 | 
					 | 
				
			||||||
				continue;
 | 
					 | 
				
			||||||
			}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
			[[NSFileManager defaultManager] removeItemAtURL:fileURL error:nil];
 | 
					 | 
				
			||||||
		}
 | 
							}
 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
	// Install app
 | 
							NSString* newAppBundlePath = [bundleContainerURL.path stringByAppendingPathComponent:appBundleToInstallPath.lastPathComponent];
 | 
				
			||||||
	NSString* newAppBundlePath = [appContainer.url.path stringByAppendingPathComponent:appBundlePath.lastPathComponent];
 | 
							NSLog(@"[installApp] new app path: %@", newAppBundlePath);
 | 
				
			||||||
	NSLog(@"[installApp] new app path: %@", newAppBundlePath);
 | 
					
 | 
				
			||||||
	
 | 
							// Install new version into existing app bundle
 | 
				
			||||||
	NSError* copyError;
 | 
							NSError* copyError;
 | 
				
			||||||
	BOOL suc = [[NSFileManager defaultManager] copyItemAtPath:appBundlePath toPath:newAppBundlePath error:©Error];
 | 
							BOOL suc = [[NSFileManager defaultManager] copyItemAtPath:appBundleToInstallPath toPath:newAppBundlePath error:©Error];
 | 
				
			||||||
	if(suc)
 | 
							if(!suc)
 | 
				
			||||||
	{
 | 
							{
 | 
				
			||||||
		NSLog(@"[installApp] App %@ installed, adding to icon cache now...", appId);
 | 
								NSLog(@"[installApp] Error copying new version during update: %@", copyError);
 | 
				
			||||||
		registerPath(newAppBundlePath, NO, YES);
 | 
								return 178;
 | 
				
			||||||
		return 0;
 | 
							}
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
	else
 | 
						else
 | 
				
			||||||
	{
 | 
						{
 | 
				
			||||||
		NSLog(@"[installApp] Failed to copy app bundle for app %@, error: %@", appId, copyError);
 | 
							// Initial app install
 | 
				
			||||||
		return 178;
 | 
							BOOL systemMethodSuccessful = NO;
 | 
				
			||||||
 | 
							if(useInstalldMethod)
 | 
				
			||||||
 | 
							{
 | 
				
			||||||
 | 
								// System method
 | 
				
			||||||
 | 
								// Do initial placeholder installation using LSApplicationWorkspace
 | 
				
			||||||
 | 
								NSLog(@"[installApp] doing placeholder installation using LSApplicationWorkspace");
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
								NSError* installError;
 | 
				
			||||||
 | 
								@try
 | 
				
			||||||
 | 
								{
 | 
				
			||||||
 | 
									systemMethodSuccessful = [[LSApplicationWorkspace defaultWorkspace] installApplication:[NSURL fileURLWithPath:appPackagePath] withOptions:@{
 | 
				
			||||||
 | 
										LSInstallTypeKey : @1,
 | 
				
			||||||
 | 
										@"PackageType" : @"Placeholder"
 | 
				
			||||||
 | 
									} error:&installError];
 | 
				
			||||||
 | 
								}
 | 
				
			||||||
 | 
								@catch(NSException* e)
 | 
				
			||||||
 | 
								{
 | 
				
			||||||
 | 
									NSLog(@"[installApp] encountered expection %@ while trying to do placeholder install", e);
 | 
				
			||||||
 | 
									systemMethodSuccessful = NO;
 | 
				
			||||||
 | 
								}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
								if(!systemMethodSuccessful)
 | 
				
			||||||
 | 
								{
 | 
				
			||||||
 | 
									NSLog(@"[installApp] encountered error %@ while trying to do placeholder install", installError);
 | 
				
			||||||
 | 
								}
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
						
 | 
				
			||||||
 | 
							if(!systemMethodSuccessful)
 | 
				
			||||||
 | 
							{
 | 
				
			||||||
 | 
								// Custom method
 | 
				
			||||||
 | 
								// Manually create app bundle via MCM apis and move app there
 | 
				
			||||||
 | 
								NSLog(@"[installApp] doing custom installation using MCMAppContainer");
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
								NSError* mcmError;
 | 
				
			||||||
 | 
								appContainer = [objc_getClass("MCMAppContainer") containerWithIdentifier:appId createIfNecessary:YES existed:nil error:&mcmError];
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
								if(!appContainer || mcmError)
 | 
				
			||||||
 | 
								{
 | 
				
			||||||
 | 
									NSLog(@"[installApp] failed to create app container for %@: %@", appId, mcmError);
 | 
				
			||||||
 | 
									return 170;
 | 
				
			||||||
 | 
								}
 | 
				
			||||||
 | 
								else
 | 
				
			||||||
 | 
								{
 | 
				
			||||||
 | 
									NSLog(@"[installApp] created app container: %@", appContainer);
 | 
				
			||||||
 | 
								}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
								NSString* newAppBundlePath = [appContainer.url.path stringByAppendingPathComponent:appBundleToInstallPath.lastPathComponent];
 | 
				
			||||||
 | 
								NSLog(@"[installApp] new app path: %@", newAppBundlePath);
 | 
				
			||||||
 | 
								
 | 
				
			||||||
 | 
								NSError* copyError;
 | 
				
			||||||
 | 
								BOOL suc = [[NSFileManager defaultManager] copyItemAtPath:appBundleToInstallPath toPath:newAppBundlePath error:©Error];
 | 
				
			||||||
 | 
								if(!suc)
 | 
				
			||||||
 | 
								{
 | 
				
			||||||
 | 
									
 | 
				
			||||||
 | 
									NSLog(@"[installApp] Failed to copy app bundle for app %@, error: %@", appId, copyError);
 | 
				
			||||||
 | 
									return 178;
 | 
				
			||||||
 | 
								}
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						appContainer = [objc_getClass("MCMAppContainer") containerWithIdentifier:appId createIfNecessary:NO existed:nil error:nil];
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						// Mark app as TrollStore app
 | 
				
			||||||
 | 
						NSURL* trollStoreMarkURL = [appContainer.url URLByAppendingPathComponent:@"_TrollStore"];
 | 
				
			||||||
 | 
						if(![[NSFileManager defaultManager] fileExistsAtPath:trollStoreMarkURL.path])
 | 
				
			||||||
 | 
						{
 | 
				
			||||||
 | 
							NSError* creationError;
 | 
				
			||||||
 | 
							NSData* emptyData = [NSData data];
 | 
				
			||||||
 | 
							BOOL marked = [emptyData writeToURL:trollStoreMarkURL options:0 error:&creationError];
 | 
				
			||||||
 | 
							if(!marked)
 | 
				
			||||||
 | 
							{
 | 
				
			||||||
 | 
								NSLog(@"[installApp] failed to mark %@ as TrollStore app by creating %@, error: %@", appId, trollStoreMarkURL.path, creationError);
 | 
				
			||||||
 | 
								return 177;
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						// At this point the (new version of the) app is installed but still needs to be registered
 | 
				
			||||||
 | 
						// Also permissions need to be fixed
 | 
				
			||||||
 | 
						NSURL* updatedAppURL = findAppURLInBundleURL(appContainer.url);
 | 
				
			||||||
 | 
						fixPermissionsOfAppBundle(updatedAppURL.path);
 | 
				
			||||||
 | 
						registerPath(updatedAppURL.path, 0, YES);
 | 
				
			||||||
 | 
						return 0;
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
int uninstallApp(NSString* appPath, NSString* appId)
 | 
					int uninstallApp(NSString* appPath, NSString* appId, BOOL useCustomMethod)
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
	BOOL deleteSuc = NO;
 | 
						BOOL deleteSuc = NO;
 | 
				
			||||||
	if(!appId && appPath)
 | 
						if(!appId && appPath)
 | 
				
			||||||
@ -760,7 +800,21 @@ int uninstallApp(NSString* appPath, NSString* appId)
 | 
				
			|||||||
			}
 | 
								}
 | 
				
			||||||
		}
 | 
							}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
		deleteSuc = [[LSApplicationWorkspace defaultWorkspace] uninstallApplication:appId withOptions:nil];
 | 
							BOOL systemMethodSuccessful = NO;
 | 
				
			||||||
 | 
							if(!useCustomMethod)
 | 
				
			||||||
 | 
							{
 | 
				
			||||||
 | 
								systemMethodSuccessful = [[LSApplicationWorkspace defaultWorkspace] uninstallApplication:appId withOptions:nil];
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							if(!systemMethodSuccessful)
 | 
				
			||||||
 | 
							{
 | 
				
			||||||
 | 
								deleteSuc = [[NSFileManager defaultManager] removeItemAtPath:[appPath stringByDeletingLastPathComponent] error:nil];
 | 
				
			||||||
 | 
								registerPath(appPath, YES, YES);
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
							else
 | 
				
			||||||
 | 
							{
 | 
				
			||||||
 | 
								deleteSuc = systemMethodSuccessful;
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	if(deleteSuc)
 | 
						if(deleteSuc)
 | 
				
			||||||
@ -774,7 +828,7 @@ int uninstallApp(NSString* appPath, NSString* appId)
 | 
				
			|||||||
	}
 | 
						}
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
int uninstallAppByPath(NSString* appPath)
 | 
					int uninstallAppByPath(NSString* appPath, BOOL useCustomMethod)
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
	if(!appPath) return 1;
 | 
						if(!appPath) return 1;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@ -786,21 +840,20 @@ int uninstallAppByPath(NSString* appPath)
 | 
				
			|||||||
	}
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	NSString* appId = appIdForAppPath(standardizedAppPath);
 | 
						NSString* appId = appIdForAppPath(standardizedAppPath);
 | 
				
			||||||
	return uninstallApp(appPath, appId);
 | 
						return uninstallApp(appPath, appId, useCustomMethod);
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
int uninstallAppById(NSString* appId)
 | 
					int uninstallAppById(NSString* appId, BOOL useCustomMethod)
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
	if(!appId) return 1;
 | 
						if(!appId) return 1;
 | 
				
			||||||
	NSString* appPath = appPathForAppId(appId);
 | 
						NSString* appPath = appPathForAppId(appId);
 | 
				
			||||||
	if(!appPath) return 1;
 | 
						if(!appPath) return 1;
 | 
				
			||||||
	return uninstallApp(appPath, appId);
 | 
						return uninstallApp(appPath, appId, useCustomMethod);
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
// 166: IPA does not exist or is not accessible
 | 
					// 166: IPA does not exist or is not accessible
 | 
				
			||||||
// 167: IPA does not appear to contain an app
 | 
					// 167: IPA does not appear to contain an app
 | 
				
			||||||
 | 
					int installIpa(NSString* ipaPath, BOOL force, BOOL useInstalldMethod)
 | 
				
			||||||
int installIpa(NSString* ipaPath, BOOL force)
 | 
					 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
	cleanRestrictions();
 | 
						cleanRestrictions();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@ -819,18 +872,18 @@ int installIpa(NSString* ipaPath, BOOL force)
 | 
				
			|||||||
		return 168;
 | 
							return 168;
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	int ret = installApp(tmpPackagePath, YES, force, NO);
 | 
						int ret = installApp(tmpPackagePath, YES, force, NO, useInstalldMethod);
 | 
				
			||||||
	
 | 
						
 | 
				
			||||||
	[[NSFileManager defaultManager] removeItemAtPath:tmpPackagePath error:nil];
 | 
						[[NSFileManager defaultManager] removeItemAtPath:tmpPackagePath error:nil];
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	return ret;
 | 
						return ret;
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
void uninstallAllApps(void)
 | 
					void uninstallAllApps(BOOL useCustomMethod)
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
	for(NSString* appPath in trollStoreInstalledAppBundlePaths())
 | 
						for(NSString* appPath in trollStoreInstalledAppBundlePaths())
 | 
				
			||||||
	{
 | 
						{
 | 
				
			||||||
		uninstallAppById(appIdForAppPath(appPath));
 | 
							uninstallAppById(appIdForAppPath(appPath), useCustomMethod);
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@ -872,14 +925,36 @@ int installTrollStore(NSString* pathToTar)
 | 
				
			|||||||
	NSString* tmpTrollStorePath = [tmpPayloadPath stringByAppendingPathComponent:@"TrollStore.app"];
 | 
						NSString* tmpTrollStorePath = [tmpPayloadPath stringByAppendingPathComponent:@"TrollStore.app"];
 | 
				
			||||||
	if(![[NSFileManager defaultManager] fileExistsAtPath:tmpTrollStorePath]) return 1;
 | 
						if(![[NSFileManager defaultManager] fileExistsAtPath:tmpTrollStorePath]) return 1;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	// Save existing ldid installation if it exists
 | 
						// Transfer existing ldid installation if it exists
 | 
				
			||||||
	NSString* existingLdidPath = [trollStoreAppPath() stringByAppendingPathComponent:@"ldid"];
 | 
						// But only if the to-be-installed version of TrollStore is 1.5.0 or above
 | 
				
			||||||
	if([[NSFileManager defaultManager] fileExistsAtPath:existingLdidPath])
 | 
						// This is to make it possible to downgrade to older versions still
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						NSString* toInstallInfoPlistPath = [tmpTrollStorePath stringByAppendingPathComponent:@"Info.plist"];
 | 
				
			||||||
 | 
						if(![[NSFileManager defaultManager] fileExistsAtPath:toInstallInfoPlistPath]) return 1;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						NSDictionary* toInstallInfoDict = [NSDictionary dictionaryWithContentsOfFile:toInstallInfoPlistPath];
 | 
				
			||||||
 | 
						NSString* toInstallVersion = toInstallInfoDict[@"CFBundleVersion"];
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						NSComparisonResult result = [@"1.5.0" compare:toInstallVersion options:NSNumericSearch];
 | 
				
			||||||
 | 
						if(result != NSOrderedDescending)
 | 
				
			||||||
	{
 | 
						{
 | 
				
			||||||
		NSString* tmpLdidPath = [tmpTrollStorePath stringByAppendingPathComponent:@"ldid"];
 | 
							NSString* existingLdidPath = [trollStoreAppPath() stringByAppendingPathComponent:@"ldid"];
 | 
				
			||||||
		if(![[NSFileManager defaultManager] fileExistsAtPath:tmpLdidPath])
 | 
							NSString* existingLdidVersionPath = [trollStoreAppPath() stringByAppendingPathComponent:@"ldid.version"];
 | 
				
			||||||
 | 
							if([[NSFileManager defaultManager] fileExistsAtPath:existingLdidPath])
 | 
				
			||||||
		{
 | 
							{
 | 
				
			||||||
			[[NSFileManager defaultManager] copyItemAtPath:existingLdidPath toPath:tmpLdidPath error:nil];
 | 
								NSString* tmpLdidPath = [tmpTrollStorePath stringByAppendingPathComponent:@"ldid"];
 | 
				
			||||||
 | 
								if(![[NSFileManager defaultManager] fileExistsAtPath:tmpLdidPath])
 | 
				
			||||||
 | 
								{
 | 
				
			||||||
 | 
									[[NSFileManager defaultManager] copyItemAtPath:existingLdidPath toPath:tmpLdidPath error:nil];
 | 
				
			||||||
 | 
								}
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
							if([[NSFileManager defaultManager] fileExistsAtPath:existingLdidVersionPath])
 | 
				
			||||||
 | 
							{
 | 
				
			||||||
 | 
								NSString* tmpLdidVersionPath = [tmpTrollStorePath stringByAppendingPathComponent:@"ldid.version"];
 | 
				
			||||||
 | 
								if(![[NSFileManager defaultManager] fileExistsAtPath:tmpLdidVersionPath])
 | 
				
			||||||
 | 
								{
 | 
				
			||||||
 | 
									[[NSFileManager defaultManager] copyItemAtPath:existingLdidVersionPath toPath:tmpLdidVersionPath error:nil];
 | 
				
			||||||
 | 
								}
 | 
				
			||||||
		}
 | 
							}
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@ -898,7 +973,7 @@ int installTrollStore(NSString* pathToTar)
 | 
				
			|||||||
		_installPersistenceHelper(persistenceHelperApp, trollStorePersistenceHelper, trollStoreRootHelper);
 | 
							_installPersistenceHelper(persistenceHelperApp, trollStorePersistenceHelper, trollStoreRootHelper);
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	int ret = installApp(tmpPackagePath, NO, YES, YES);
 | 
						int ret = installApp(tmpPackagePath, NO, YES, YES, YES);
 | 
				
			||||||
	NSLog(@"[installTrollStore] installApp => %d", ret);
 | 
						NSLog(@"[installTrollStore] installApp => %d", ret);
 | 
				
			||||||
	[[NSFileManager defaultManager] removeItemAtPath:tmpPackagePath error:nil];
 | 
						[[NSFileManager defaultManager] removeItemAtPath:tmpPackagePath error:nil];
 | 
				
			||||||
	return ret;
 | 
						return ret;
 | 
				
			||||||
@ -1106,90 +1181,114 @@ int MAIN_NAME(int argc, char *argv[], char *envp[])
 | 
				
			|||||||
	@autoreleasepool {
 | 
						@autoreleasepool {
 | 
				
			||||||
		if(argc <= 1) return -1;
 | 
							if(argc <= 1) return -1;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
		NSLog(@"trollstore helper go, uid: %d, gid: %d", getuid(), getgid());
 | 
							if(getuid() != 0)
 | 
				
			||||||
 | 
							{
 | 
				
			||||||
 | 
								NSLog(@"ERROR: trollstorehelper has to be run as root.");
 | 
				
			||||||
 | 
								return -1;
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							NSMutableArray* args = [NSMutableArray new];
 | 
				
			||||||
 | 
							for (int i = 1; i < argc; i++)
 | 
				
			||||||
 | 
							{
 | 
				
			||||||
 | 
								[args addObject:[NSString stringWithUTF8String:argv[i]]];
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							NSLog(@"trollstorehelper invoked with arguments: %@", args);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
		int ret = 0;
 | 
							int ret = 0;
 | 
				
			||||||
 | 
							NSString* cmd = args.firstObject;
 | 
				
			||||||
		NSString* cmd = [NSString stringWithUTF8String:argv[1]];
 | 
					 | 
				
			||||||
		if([cmd isEqualToString:@"install"])
 | 
							if([cmd isEqualToString:@"install"])
 | 
				
			||||||
		{
 | 
							{
 | 
				
			||||||
			BOOL force = NO;
 | 
								if(args.count < 2) return -3;
 | 
				
			||||||
			if(argc <= 2) return -3;
 | 
								// use system method when specified, otherwise use custom method
 | 
				
			||||||
			if(argc > 3)
 | 
								BOOL useInstalldMethod = [args containsObject:@"installd"];
 | 
				
			||||||
			{
 | 
								BOOL force = [args containsObject:@"force"];
 | 
				
			||||||
				if(!strcmp(argv[3], "force"))
 | 
								NSString* ipaPath = args.lastObject;
 | 
				
			||||||
				{
 | 
								ret = installIpa(ipaPath, force, useInstalldMethod);
 | 
				
			||||||
					force = YES;
 | 
							}
 | 
				
			||||||
				}
 | 
							else if([cmd isEqualToString:@"uninstall"])
 | 
				
			||||||
			}
 | 
					 | 
				
			||||||
			NSString* ipaPath = [NSString stringWithUTF8String:argv[2]];
 | 
					 | 
				
			||||||
			ret = installIpa(ipaPath, force);
 | 
					 | 
				
			||||||
		} else if([cmd isEqualToString:@"uninstall"])
 | 
					 | 
				
			||||||
		{
 | 
							{
 | 
				
			||||||
			if(argc <= 2) return -3;
 | 
								if(args.count < 2) return -3;
 | 
				
			||||||
			NSString* appId = [NSString stringWithUTF8String:argv[2]];
 | 
								// use custom method when specified, otherwise use system method
 | 
				
			||||||
			ret = uninstallAppById(appId);
 | 
								BOOL useCustomMethod = [args containsObject:@"custom"];
 | 
				
			||||||
		} else if([cmd isEqualToString:@"uninstall-path"])
 | 
								NSString* appId = args.lastObject;
 | 
				
			||||||
 | 
								ret = uninstallAppById(appId, useCustomMethod);
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
							else if([cmd isEqualToString:@"uninstall-path"])
 | 
				
			||||||
		{
 | 
							{
 | 
				
			||||||
			if(argc <= 2) return -3;
 | 
								if(args.count < 2) return -3;
 | 
				
			||||||
			NSString* appPath = [NSString stringWithUTF8String:argv[2]];
 | 
								// use custom method when specified, otherwise use system method
 | 
				
			||||||
			ret = uninstallAppByPath(appPath);
 | 
								BOOL useCustomMethod = [args containsObject:@"custom"];
 | 
				
			||||||
		}else if([cmd isEqualToString:@"install-trollstore"])
 | 
								NSString* appPath = args.lastObject;
 | 
				
			||||||
 | 
								ret = uninstallAppByPath(appPath, useCustomMethod);
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
							else if([cmd isEqualToString:@"install-trollstore"])
 | 
				
			||||||
		{
 | 
							{
 | 
				
			||||||
			if(argc <= 2) return -3;
 | 
								if(args.count < 2) return -3;
 | 
				
			||||||
			NSString* tsTar = [NSString stringWithUTF8String:argv[2]];
 | 
								NSString* tsTar = args.lastObject;
 | 
				
			||||||
			ret = installTrollStore(tsTar);
 | 
								ret = installTrollStore(tsTar);
 | 
				
			||||||
			NSLog(@"installed troll store? %d", ret==0);
 | 
								NSLog(@"installed troll store? %d", ret==0);
 | 
				
			||||||
		} else if([cmd isEqualToString:@"uninstall-trollstore"])
 | 
							}
 | 
				
			||||||
 | 
							else if([cmd isEqualToString:@"uninstall-trollstore"])
 | 
				
			||||||
		{
 | 
							{
 | 
				
			||||||
			uninstallAllApps();
 | 
								if(![args containsObject:@"preserve-apps"])
 | 
				
			||||||
 | 
								{
 | 
				
			||||||
 | 
									uninstallAllApps([args containsObject:@"custom"]);
 | 
				
			||||||
 | 
								}
 | 
				
			||||||
			uninstallTrollStore(YES);
 | 
								uninstallTrollStore(YES);
 | 
				
			||||||
		} else if([cmd isEqualToString:@"uninstall-trollstore-preserve-apps"])
 | 
							}
 | 
				
			||||||
 | 
							else if([cmd isEqualToString:@"install-ldid"])
 | 
				
			||||||
		{
 | 
							{
 | 
				
			||||||
			uninstallTrollStore(YES);
 | 
								if(args.count < 3) return -3;
 | 
				
			||||||
		}else if([cmd isEqualToString:@"install-ldid"])
 | 
								NSString* ldidPath = args[1];
 | 
				
			||||||
		{
 | 
								NSString* ldidVersion = args[2];
 | 
				
			||||||
			if(argc <= 2) return -3;
 | 
								installLdid(ldidPath, ldidVersion);
 | 
				
			||||||
			NSString* ldidPath = [NSString stringWithUTF8String:argv[2]];
 | 
							}
 | 
				
			||||||
			installLdid(ldidPath);
 | 
							else if([cmd isEqualToString:@"refresh"])
 | 
				
			||||||
		} else if([cmd isEqualToString:@"refresh"])
 | 
					 | 
				
			||||||
		{
 | 
							{
 | 
				
			||||||
			refreshAppRegistrations(YES);
 | 
								refreshAppRegistrations(YES);
 | 
				
			||||||
		} else if([cmd isEqualToString:@"refresh-all"])
 | 
							}
 | 
				
			||||||
 | 
							else if([cmd isEqualToString:@"refresh-all"])
 | 
				
			||||||
		{
 | 
							{
 | 
				
			||||||
			cleanRestrictions();
 | 
								cleanRestrictions();
 | 
				
			||||||
			//refreshAppRegistrations(NO); // <- fixes app permissions resetting, causes apps to move around on home screen, so I had to disable it
 | 
								//refreshAppRegistrations(NO); // <- fixes app permissions resetting, causes apps to move around on home screen, so I had to disable it
 | 
				
			||||||
 | 
								[[NSFileManager defaultManager] removeItemAtPath:@"/var/containers/Shared/SystemGroup/systemgroup.com.apple.lsd.iconscache/Library/Caches/com.apple.IconsCache" error:nil];
 | 
				
			||||||
			[[LSApplicationWorkspace defaultWorkspace] _LSPrivateRebuildApplicationDatabasesForSystemApps:YES internal:YES user:YES];
 | 
								[[LSApplicationWorkspace defaultWorkspace] _LSPrivateRebuildApplicationDatabasesForSystemApps:YES internal:YES user:YES];
 | 
				
			||||||
			refreshAppRegistrations(YES);
 | 
								refreshAppRegistrations(YES);
 | 
				
			||||||
			killall(@"backboardd", YES);
 | 
								killall(@"backboardd", YES);
 | 
				
			||||||
		} else if([cmd isEqualToString:@"install-persistence-helper"])
 | 
							}
 | 
				
			||||||
 | 
							else if([cmd isEqualToString:@"install-persistence-helper"])
 | 
				
			||||||
		{
 | 
							{
 | 
				
			||||||
			if(argc <= 2) return -3;
 | 
								if(args.count < 2) return -3;
 | 
				
			||||||
			NSString* systemAppId = [NSString stringWithUTF8String:argv[2]];
 | 
								NSString* systemAppId = args.lastObject;
 | 
				
			||||||
			installPersistenceHelper(systemAppId);
 | 
								installPersistenceHelper(systemAppId);
 | 
				
			||||||
		} else if([cmd isEqualToString:@"uninstall-persistence-helper"])
 | 
							}
 | 
				
			||||||
 | 
							else if([cmd isEqualToString:@"uninstall-persistence-helper"])
 | 
				
			||||||
		{
 | 
							{
 | 
				
			||||||
			uninstallPersistenceHelper();
 | 
								uninstallPersistenceHelper();
 | 
				
			||||||
		} else if([cmd isEqualToString:@"register-user-persistence-helper"])
 | 
							}
 | 
				
			||||||
 | 
							else if([cmd isEqualToString:@"register-user-persistence-helper"])
 | 
				
			||||||
		{
 | 
							{
 | 
				
			||||||
			if(argc <= 2) return -3;
 | 
								if(args.count < 2) return -3;
 | 
				
			||||||
			NSString* userAppId = [NSString stringWithUTF8String:argv[2]];
 | 
								NSString* userAppId = args.lastObject;
 | 
				
			||||||
			registerUserPersistenceHelper(userAppId);
 | 
								registerUserPersistenceHelper(userAppId);
 | 
				
			||||||
		} else if([cmd isEqualToString:@"modify-registration"])
 | 
							}
 | 
				
			||||||
 | 
							else if([cmd isEqualToString:@"modify-registration"])
 | 
				
			||||||
		{
 | 
							{
 | 
				
			||||||
			if(argc <= 3) return -3;
 | 
								if(args.count < 3) return -3;
 | 
				
			||||||
			NSString* appPath = [NSString stringWithUTF8String:argv[2]];
 | 
								NSString* appPath = args[1];
 | 
				
			||||||
			NSString* newRegistration = [NSString stringWithUTF8String:argv[3]];
 | 
								NSString* newRegistration = args[2];
 | 
				
			||||||
 | 
					
 | 
				
			||||||
			NSString* trollStoreMark = [[appPath stringByDeletingLastPathComponent] stringByAppendingPathComponent:@"_TrollStore"];
 | 
								NSString* trollStoreMark = [[appPath stringByDeletingLastPathComponent] stringByAppendingPathComponent:@"_TrollStore"];
 | 
				
			||||||
			if([[NSFileManager defaultManager] fileExistsAtPath:trollStoreMark])
 | 
								if([[NSFileManager defaultManager] fileExistsAtPath:trollStoreMark])
 | 
				
			||||||
			{
 | 
								{
 | 
				
			||||||
				registerPath(appPath, NO, [newRegistration isEqualToString:@"System"]);
 | 
									registerPath(appPath, NO, [newRegistration isEqualToString:@"System"]);
 | 
				
			||||||
			}
 | 
								}
 | 
				
			||||||
		} else if([cmd isEqualToString:@"url-scheme"])
 | 
							}
 | 
				
			||||||
 | 
							else if([cmd isEqualToString:@"url-scheme"])
 | 
				
			||||||
		{
 | 
							{
 | 
				
			||||||
			if(argc <= 2) return -3;
 | 
								if(args.count < 2) return -3;
 | 
				
			||||||
			NSString* modifyArg = [NSString stringWithUTF8String:argv[2]];
 | 
								NSString* modifyArg = args.lastObject;
 | 
				
			||||||
			BOOL newState = [modifyArg isEqualToString:@"enable"];
 | 
								BOOL newState = [modifyArg isEqualToString:@"enable"];
 | 
				
			||||||
			if(newState == YES || [modifyArg isEqualToString:@"disable"])
 | 
								if(newState == YES || [modifyArg isEqualToString:@"disable"])
 | 
				
			||||||
			{
 | 
								{
 | 
				
			||||||
@ -1197,8 +1296,7 @@ int MAIN_NAME(int argc, char *argv[], char *envp[])
 | 
				
			|||||||
			}
 | 
								}
 | 
				
			||||||
		}
 | 
							}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
		NSLog(@"returning %d", ret);
 | 
							NSLog(@"trollstorehelper returning %d", ret);
 | 
				
			||||||
 | 
					 | 
				
			||||||
		return ret;
 | 
							return ret;
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
				
			|||||||
@ -12,5 +12,6 @@
 | 
				
			|||||||
- (void)refreshAppRegistrationsPressed;
 | 
					- (void)refreshAppRegistrationsPressed;
 | 
				
			||||||
- (void)uninstallPersistenceHelperPressed;
 | 
					- (void)uninstallPersistenceHelperPressed;
 | 
				
			||||||
- (void)handleUninstallation;
 | 
					- (void)handleUninstallation;
 | 
				
			||||||
 | 
					- (NSMutableArray*)argsForUninstallingTrollStore;
 | 
				
			||||||
- (void)uninstallTrollStorePressed;
 | 
					- (void)uninstallTrollStorePressed;
 | 
				
			||||||
@end
 | 
					@end
 | 
				
			||||||
@ -188,20 +188,28 @@
 | 
				
			|||||||
	}
 | 
						}
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					- (NSMutableArray*)argsForUninstallingTrollStore
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
						return @[@"uninstall-trollstore"].mutableCopy;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
- (void)uninstallTrollStorePressed
 | 
					- (void)uninstallTrollStorePressed
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
	UIAlertController* uninstallAlert = [UIAlertController alertControllerWithTitle:@"Uninstall" message:@"You are about to uninstall TrollStore, do you want to preserve the apps installed by it?" preferredStyle:UIAlertControllerStyleAlert];
 | 
						UIAlertController* uninstallAlert = [UIAlertController alertControllerWithTitle:@"Uninstall" message:@"You are about to uninstall TrollStore, do you want to preserve the apps installed by it?" preferredStyle:UIAlertControllerStyleAlert];
 | 
				
			||||||
	
 | 
						
 | 
				
			||||||
	UIAlertAction* uninstallAllAction = [UIAlertAction actionWithTitle:@"Uninstall TrollStore, Uninstall Apps" style:UIAlertActionStyleDestructive handler:^(UIAlertAction* action)
 | 
						UIAlertAction* uninstallAllAction = [UIAlertAction actionWithTitle:@"Uninstall TrollStore, Uninstall Apps" style:UIAlertActionStyleDestructive handler:^(UIAlertAction* action)
 | 
				
			||||||
	{
 | 
						{
 | 
				
			||||||
		spawnRoot(rootHelperPath(), @[@"uninstall-trollstore"], nil, nil);
 | 
							NSMutableArray* args = [self argsForUninstallingTrollStore];
 | 
				
			||||||
 | 
							spawnRoot(rootHelperPath(), @[args], nil, nil);
 | 
				
			||||||
		[self handleUninstallation];
 | 
							[self handleUninstallation];
 | 
				
			||||||
	}];
 | 
						}];
 | 
				
			||||||
	[uninstallAlert addAction:uninstallAllAction];
 | 
						[uninstallAlert addAction:uninstallAllAction];
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	UIAlertAction* preserveAppsAction = [UIAlertAction actionWithTitle:@"Uninstall TrollStore, Preserve Apps" style:UIAlertActionStyleDestructive handler:^(UIAlertAction* action)
 | 
						UIAlertAction* preserveAppsAction = [UIAlertAction actionWithTitle:@"Uninstall TrollStore, Preserve Apps" style:UIAlertActionStyleDestructive handler:^(UIAlertAction* action)
 | 
				
			||||||
	{
 | 
						{
 | 
				
			||||||
		spawnRoot(rootHelperPath(), @[@"uninstall-trollstore-preserve-apps"], nil, nil);
 | 
							NSMutableArray* args = [self argsForUninstallingTrollStore];
 | 
				
			||||||
 | 
							[args addObject:@"preserve-apps"];
 | 
				
			||||||
 | 
							spawnRoot(rootHelperPath(), args, nil, nil);
 | 
				
			||||||
		[self handleUninstallation];
 | 
							[self handleUninstallation];
 | 
				
			||||||
	}];
 | 
						}];
 | 
				
			||||||
	[uninstallAlert addAction:preserveAppsAction];
 | 
						[uninstallAlert addAction:preserveAppsAction];
 | 
				
			||||||
 | 
				
			|||||||
@ -13,6 +13,7 @@ extern int spawnRoot(NSString* path, NSArray* args, NSString** stdOut, NSString*
 | 
				
			|||||||
extern void killall(NSString* processName, BOOL softly);
 | 
					extern void killall(NSString* processName, BOOL softly);
 | 
				
			||||||
extern void respring(void);
 | 
					extern void respring(void);
 | 
				
			||||||
extern void fetchLatestTrollStoreVersion(void (^completionHandler)(NSString* latestVersion));
 | 
					extern void fetchLatestTrollStoreVersion(void (^completionHandler)(NSString* latestVersion));
 | 
				
			||||||
 | 
					extern void fetchLatestLdidVersion(void (^completionHandler)(NSString* latestVersion));
 | 
				
			||||||
 | 
					
 | 
				
			||||||
extern NSArray* trollStoreInstalledAppBundlePaths();
 | 
					extern NSArray* trollStoreInstalledAppBundlePaths();
 | 
				
			||||||
extern NSArray* trollStoreInstalledAppContainerPaths();
 | 
					extern NSArray* trollStoreInstalledAppContainerPaths();
 | 
				
			||||||
 | 
				
			|||||||
@ -287,9 +287,10 @@ void respring(void)
 | 
				
			|||||||
	exit(0);
 | 
						exit(0);
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
void fetchLatestTrollStoreVersion(void (^completionHandler)(NSString* latestVersion))
 | 
					void github_fetchLatestVersion(NSString* repo, void (^completionHandler)(NSString* latestVersion))
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
	NSURL* githubLatestAPIURL = [NSURL URLWithString:@"https://api.github.com/repos/opa334/TrollStore/releases/latest"];
 | 
						NSString* urlString = [NSString stringWithFormat:@"https://api.github.com/repos/%@/releases/latest", repo];
 | 
				
			||||||
 | 
						NSURL* githubLatestAPIURL = [NSURL URLWithString:urlString];
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	NSURLSessionDataTask* task = [NSURLSession.sharedSession dataTaskWithURL:githubLatestAPIURL completionHandler:^(NSData *data, NSURLResponse *response, NSError *error)
 | 
						NSURLSessionDataTask* task = [NSURLSession.sharedSession dataTaskWithURL:githubLatestAPIURL completionHandler:^(NSData *data, NSURLResponse *response, NSError *error)
 | 
				
			||||||
	{
 | 
						{
 | 
				
			||||||
@ -311,6 +312,16 @@ void fetchLatestTrollStoreVersion(void (^completionHandler)(NSString* latestVers
 | 
				
			|||||||
	[task resume];
 | 
						[task resume];
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					void fetchLatestTrollStoreVersion(void (^completionHandler)(NSString* latestVersion))
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
						github_fetchLatestVersion(@"opa334/TrollStore", completionHandler);
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					void fetchLatestLdidVersion(void (^completionHandler)(NSString* latestVersion))
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
						github_fetchLatestVersion(@"opa334/ldid", completionHandler);
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
NSArray* trollStoreInstalledAppContainerPaths()
 | 
					NSArray* trollStoreInstalledAppContainerPaths()
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
	NSMutableArray* appContainerPaths = [NSMutableArray new];
 | 
						NSMutableArray* appContainerPaths = [NSMutableArray new];
 | 
				
			||||||
 | 
				
			|||||||
@ -1,5 +1,6 @@
 | 
				
			|||||||
#import "TSApplicationsManager.h"
 | 
					#import "TSApplicationsManager.h"
 | 
				
			||||||
#import <TSUtil.h>
 | 
					#import <TSUtil.h>
 | 
				
			||||||
 | 
					extern NSUserDefaults* trollStoreUserDefaults();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@implementation TSApplicationsManager
 | 
					@implementation TSApplicationsManager
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@ -75,15 +76,25 @@
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
- (int)installIpa:(NSString*)pathToIpa force:(BOOL)force log:(NSString**)logOut
 | 
					- (int)installIpa:(NSString*)pathToIpa force:(BOOL)force log:(NSString**)logOut
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
    int ret;
 | 
					    NSMutableArray* args = [NSMutableArray new];
 | 
				
			||||||
 | 
					    [args addObject:@"install"];
 | 
				
			||||||
    if(force)
 | 
					    if(force)
 | 
				
			||||||
    {
 | 
					    {
 | 
				
			||||||
        ret = spawnRoot(rootHelperPath(), @[@"install", pathToIpa, @"force"], nil, logOut);
 | 
					        [args addObject:@"force"];
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					    NSNumber* installationMethodToUseNum = [trollStoreUserDefaults() objectForKey:@"installationMethod"];
 | 
				
			||||||
 | 
					    int installationMethodToUse = installationMethodToUseNum ? installationMethodToUseNum.intValue : 1;
 | 
				
			||||||
 | 
					    if(installationMethodToUse == 1)
 | 
				
			||||||
 | 
					    {
 | 
				
			||||||
 | 
					        [args addObject:@"custom"];
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
    else
 | 
					    else
 | 
				
			||||||
    {
 | 
					    {
 | 
				
			||||||
        ret = spawnRoot(rootHelperPath(), @[@"install", pathToIpa], nil, logOut);
 | 
					        [args addObject:@"installd"];
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					    [args addObject:pathToIpa];
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    int ret = spawnRoot(rootHelperPath(), args, nil, logOut);
 | 
				
			||||||
    [[NSNotificationCenter defaultCenter] postNotificationName:@"ApplicationsChanged" object:nil];
 | 
					    [[NSNotificationCenter defaultCenter] postNotificationName:@"ApplicationsChanged" object:nil];
 | 
				
			||||||
    return ret;
 | 
					    return ret;
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
@ -96,7 +107,24 @@
 | 
				
			|||||||
- (int)uninstallApp:(NSString*)appId
 | 
					- (int)uninstallApp:(NSString*)appId
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
    if(!appId) return -200;
 | 
					    if(!appId) return -200;
 | 
				
			||||||
    int ret = spawnRoot(rootHelperPath(), @[@"uninstall", appId], nil, nil);
 | 
					
 | 
				
			||||||
 | 
					    NSMutableArray* args = [NSMutableArray new];
 | 
				
			||||||
 | 
					    [args addObject:@"uninstall"];
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    NSNumber* uninstallationMethodToUseNum = [trollStoreUserDefaults() objectForKey:@"uninstallationMethod"];
 | 
				
			||||||
 | 
					    int uninstallationMethodToUse = uninstallationMethodToUseNum ? uninstallationMethodToUseNum.intValue : 0;
 | 
				
			||||||
 | 
					    if(uninstallationMethodToUse == 1)
 | 
				
			||||||
 | 
					    {
 | 
				
			||||||
 | 
					        [args addObject:@"custom"];
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					    else
 | 
				
			||||||
 | 
					    {
 | 
				
			||||||
 | 
					        [args addObject:@"installd"];
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    [args addObject:appId];
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    int ret = spawnRoot(rootHelperPath(), args, nil, nil);
 | 
				
			||||||
    [[NSNotificationCenter defaultCenter] postNotificationName:@"ApplicationsChanged" object:nil];
 | 
					    [[NSNotificationCenter defaultCenter] postNotificationName:@"ApplicationsChanged" object:nil];
 | 
				
			||||||
    return ret;
 | 
					    return ret;
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
@ -104,7 +132,24 @@
 | 
				
			|||||||
- (int)uninstallAppByPath:(NSString*)path
 | 
					- (int)uninstallAppByPath:(NSString*)path
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
    if(!path) return -200;
 | 
					    if(!path) return -200;
 | 
				
			||||||
    int ret = spawnRoot(rootHelperPath(), @[@"uninstall-path", path], nil, nil);
 | 
					
 | 
				
			||||||
 | 
					    NSMutableArray* args = [NSMutableArray new];
 | 
				
			||||||
 | 
					    [args addObject:@"uninstall-path"];
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    NSNumber* uninstallationMethodToUseNum = [trollStoreUserDefaults() objectForKey:@"uninstallationMethod"];
 | 
				
			||||||
 | 
					    int uninstallationMethodToUse = uninstallationMethodToUseNum ? uninstallationMethodToUseNum.intValue : 0;
 | 
				
			||||||
 | 
					    if(uninstallationMethodToUse == 1)
 | 
				
			||||||
 | 
					    {
 | 
				
			||||||
 | 
					        [args addObject:@"custom"];
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					    else
 | 
				
			||||||
 | 
					    {
 | 
				
			||||||
 | 
					        [args addObject:@"installd"];
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    [args addObject:path];
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    int ret = spawnRoot(rootHelperPath(), args, nil, nil);
 | 
				
			||||||
    [[NSNotificationCenter defaultCenter] postNotificationName:@"ApplicationsChanged" object:nil];
 | 
					    [[NSNotificationCenter defaultCenter] postNotificationName:@"ApplicationsChanged" object:nil];
 | 
				
			||||||
    return ret;
 | 
					    return ret;
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
				
			|||||||
@ -9,4 +9,6 @@
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
+ (void)handleAppInstallFromRemoteURL:(NSURL*)remoteURL completion:(void (^)(BOOL, NSError*))completion;
 | 
					+ (void)handleAppInstallFromRemoteURL:(NSURL*)remoteURL completion:(void (^)(BOOL, NSError*))completion;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					+ (void)installLdid;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@end
 | 
					@end
 | 
				
			||||||
@ -187,4 +187,47 @@ extern NSUserDefaults* trollStoreUserDefaults(void);
 | 
				
			|||||||
	});
 | 
						});
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					+ (void)installLdid
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
						fetchLatestLdidVersion(^(NSString* latestVersion)
 | 
				
			||||||
 | 
						{
 | 
				
			||||||
 | 
							dispatch_async(dispatch_get_main_queue(), ^
 | 
				
			||||||
 | 
							{
 | 
				
			||||||
 | 
								NSURL* ldidURL = [NSURL URLWithString:@"https://github.com/opa334/ldid/releases/latest/download/ldid"];
 | 
				
			||||||
 | 
								NSURLRequest* ldidRequest = [NSURLRequest requestWithURL:ldidURL];
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
								[TSPresentationDelegate startActivity:@"Installing ldid"];
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
								NSURLSessionDownloadTask* downloadTask = [NSURLSession.sharedSession downloadTaskWithRequest:ldidRequest completionHandler:^(NSURL *location, NSURLResponse *response, NSError *error)
 | 
				
			||||||
 | 
								{
 | 
				
			||||||
 | 
									if(error)
 | 
				
			||||||
 | 
									{
 | 
				
			||||||
 | 
										UIAlertController* errorAlert = [UIAlertController alertControllerWithTitle:@"Error" message:[NSString stringWithFormat:@"Error downloading ldid: %@", error] preferredStyle:UIAlertControllerStyleAlert];
 | 
				
			||||||
 | 
										UIAlertAction* closeAction = [UIAlertAction actionWithTitle:@"Close" style:UIAlertActionStyleDefault handler:nil];
 | 
				
			||||||
 | 
										[errorAlert addAction:closeAction];
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
										dispatch_async(dispatch_get_main_queue(), ^
 | 
				
			||||||
 | 
										{
 | 
				
			||||||
 | 
											[TSPresentationDelegate stopActivityWithCompletion:^
 | 
				
			||||||
 | 
											{
 | 
				
			||||||
 | 
												[TSPresentationDelegate presentViewController:errorAlert animated:YES completion:nil];
 | 
				
			||||||
 | 
											}];
 | 
				
			||||||
 | 
										});
 | 
				
			||||||
 | 
									}
 | 
				
			||||||
 | 
									else
 | 
				
			||||||
 | 
									{
 | 
				
			||||||
 | 
										spawnRoot(rootHelperPath(), @[@"install-ldid", location.path, latestVersion], nil, nil);
 | 
				
			||||||
 | 
										dispatch_async(dispatch_get_main_queue(), ^
 | 
				
			||||||
 | 
										{
 | 
				
			||||||
 | 
											[TSPresentationDelegate stopActivityWithCompletion:nil];
 | 
				
			||||||
 | 
											[[NSNotificationCenter defaultCenter] postNotificationName:@"TrollStoreReloadSettingsNotification" object:nil userInfo:nil];
 | 
				
			||||||
 | 
										});
 | 
				
			||||||
 | 
									}
 | 
				
			||||||
 | 
								}];
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
								[downloadTask resume];
 | 
				
			||||||
 | 
							});
 | 
				
			||||||
 | 
						});
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@end
 | 
					@end
 | 
				
			||||||
@ -72,6 +72,20 @@
 | 
				
			|||||||
	}
 | 
						}
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					// We want to auto install ldid if either it doesn't exist
 | 
				
			||||||
 | 
					// or if it's the one from an old TrollStore version that's no longer supported
 | 
				
			||||||
 | 
					- (void)handleLdidCheck
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
						NSString* tsAppPath = [NSBundle mainBundle].bundlePath;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						NSString* ldidPath = [tsAppPath stringByAppendingPathComponent:@"ldid"];
 | 
				
			||||||
 | 
						NSString* ldidVersionPath = [tsAppPath stringByAppendingPathComponent:@"ldid.version"];
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						if(![[NSFileManager defaultManager] fileExistsAtPath:ldidPath] || ![[NSFileManager defaultManager] fileExistsAtPath:ldidVersionPath])
 | 
				
			||||||
 | 
						{
 | 
				
			||||||
 | 
							[TSInstallationController installLdid];
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
- (void)scene:(UIScene *)scene willConnectToSession:(UISceneSession *)session options:(UISceneConnectionOptions *)connectionOptions {
 | 
					- (void)scene:(UIScene *)scene willConnectToSession:(UISceneSession *)session options:(UISceneConnectionOptions *)connectionOptions {
 | 
				
			||||||
	// Use this method to optionally configure and attach the UIWindow `window` to the provided UIWindowScene `scene`.
 | 
						// Use this method to optionally configure and attach the UIWindow `window` to the provided UIWindowScene `scene`.
 | 
				
			||||||
@ -88,6 +102,10 @@
 | 
				
			|||||||
	{
 | 
						{
 | 
				
			||||||
		[self handleURLContexts:connectionOptions.URLContexts scene:(UIWindowScene*)scene];
 | 
							[self handleURLContexts:connectionOptions.URLContexts scene:(UIWindowScene*)scene];
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
						else
 | 
				
			||||||
 | 
						{
 | 
				
			||||||
 | 
							[self handleLdidCheck];
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
				
			|||||||
							
								
								
									
										5
									
								
								TrollStore/TSSettingsAdvancedListController.h
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										5
									
								
								TrollStore/TSSettingsAdvancedListController.h
									
									
									
									
									
										Normal file
									
								
							@ -0,0 +1,5 @@
 | 
				
			|||||||
 | 
					#import <Preferences/PSListController.h>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					@interface TSSettingsAdvancedListController : PSListController
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					@end
 | 
				
			||||||
							
								
								
									
										103
									
								
								TrollStore/TSSettingsAdvancedListController.m
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										103
									
								
								TrollStore/TSSettingsAdvancedListController.m
									
									
									
									
									
										Normal file
									
								
							@ -0,0 +1,103 @@
 | 
				
			|||||||
 | 
					#import "TSSettingsAdvancedListController.h"
 | 
				
			||||||
 | 
					#import <Preferences/PSSpecifier.h>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					extern NSUserDefaults* trollStoreUserDefaults();
 | 
				
			||||||
 | 
					@interface PSSpecifier ()
 | 
				
			||||||
 | 
					@property (nonatomic,retain) NSArray* values;
 | 
				
			||||||
 | 
					@end
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					@implementation TSSettingsAdvancedListController
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					- (NSMutableArray*)specifiers
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
						if(!_specifiers)
 | 
				
			||||||
 | 
						{
 | 
				
			||||||
 | 
							_specifiers = [NSMutableArray new];
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							PSSpecifier* installationMethodGroupSpecifier = [PSSpecifier emptyGroupSpecifier];
 | 
				
			||||||
 | 
							//installationMethodGroupSpecifier.name = @"Installation";
 | 
				
			||||||
 | 
							[installationMethodGroupSpecifier setProperty:@"installd:\nInstalls applications by doing a placeholder installation through installd, fixing the permissions and then adding it to icon cache.\nAdvantage: Might be slightly more persistent then the custom method in terms of icon cache reloads.\nDisadvantage: Causes some small issues with certain applications for seemingly no reason (E.g. Watusi cannot save preferences when being installed using this method).\n\nCustom (Recommended):\nInstalls applications by manually creating a bundle using MobileContainerManager, copying the app into it and adding it to icon cache.\nAdvantage: No known issues (As opposed to the Watusi issue outlined in the installd method).\nDisadvantage: Might be slightly less persistent then the installd method in terms of icon cache reloads.\n\nNOTE: In cases where installd is selected but the placeholder installation fails, TrollStore automatically falls back to using the Custom method." forKey:@"footerText"];
 | 
				
			||||||
 | 
							[_specifiers addObject:installationMethodGroupSpecifier];
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							PSSpecifier* installationMethodSpecifier = [PSSpecifier preferenceSpecifierNamed:@"Installation Method"
 | 
				
			||||||
 | 
																target:self
 | 
				
			||||||
 | 
																set:nil
 | 
				
			||||||
 | 
																get:nil
 | 
				
			||||||
 | 
																detail:nil
 | 
				
			||||||
 | 
																cell:PSStaticTextCell
 | 
				
			||||||
 | 
																edit:nil];
 | 
				
			||||||
 | 
							[installationMethodSpecifier setProperty:@YES forKey:@"enabled"];
 | 
				
			||||||
 | 
							installationMethodSpecifier.identifier = @"installationMethodLabel";
 | 
				
			||||||
 | 
							[_specifiers addObject:installationMethodSpecifier];
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							PSSpecifier* installationMethodSegmentSpecifier = [PSSpecifier preferenceSpecifierNamed:@"Installation Method Segment"
 | 
				
			||||||
 | 
																target:self
 | 
				
			||||||
 | 
																set:@selector(setPreferenceValue:specifier:)
 | 
				
			||||||
 | 
																get:@selector(readPreferenceValue:)
 | 
				
			||||||
 | 
																detail:nil
 | 
				
			||||||
 | 
																cell:PSSegmentCell
 | 
				
			||||||
 | 
																edit:nil];
 | 
				
			||||||
 | 
							[installationMethodSegmentSpecifier setProperty:@YES forKey:@"enabled"];
 | 
				
			||||||
 | 
							installationMethodSegmentSpecifier.identifier = @"installationMethodSegment";
 | 
				
			||||||
 | 
							[installationMethodSegmentSpecifier setProperty:@"com.opa334.TrollStore" forKey:@"defaults"];
 | 
				
			||||||
 | 
							[installationMethodSegmentSpecifier setProperty:@"installationMethod" forKey:@"key"];
 | 
				
			||||||
 | 
							installationMethodSegmentSpecifier.values = @[@0, @1];
 | 
				
			||||||
 | 
							installationMethodSegmentSpecifier.titleDictionary = @{@0 : @"installd", @1 : @"Custom"};
 | 
				
			||||||
 | 
							[installationMethodSegmentSpecifier setProperty:@1 forKey:@"default"];
 | 
				
			||||||
 | 
							[_specifiers addObject:installationMethodSegmentSpecifier];
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							PSSpecifier* uninstallationMethodGroupSpecifier = [PSSpecifier emptyGroupSpecifier];
 | 
				
			||||||
 | 
							//uninstallationMethodGroupSpecifier.name = @"Uninstallation";
 | 
				
			||||||
 | 
							[uninstallationMethodGroupSpecifier setProperty:@"installd (Recommended):\nUninstalls applications using the same API that SpringBoard uses when uninstalling them from the home screen.\n\nCustom:\nUninstalls applications by removing them from icon cache and then deleting their application and data bundles directly.\n\nNOTE: In cases where installd is selected but the stock uninstallation fails, TrollStore automatically falls back to using the Custom method." forKey:@"footerText"];
 | 
				
			||||||
 | 
							[_specifiers addObject:uninstallationMethodGroupSpecifier];
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							PSSpecifier* uninstallationMethodSpecifier = [PSSpecifier preferenceSpecifierNamed:@"Uninstallation Method"
 | 
				
			||||||
 | 
																target:self
 | 
				
			||||||
 | 
																set:nil
 | 
				
			||||||
 | 
																get:nil
 | 
				
			||||||
 | 
																detail:nil
 | 
				
			||||||
 | 
																cell:PSStaticTextCell
 | 
				
			||||||
 | 
																edit:nil];
 | 
				
			||||||
 | 
							[uninstallationMethodSpecifier setProperty:@YES forKey:@"enabled"];
 | 
				
			||||||
 | 
							uninstallationMethodSpecifier.identifier = @"uninstallationMethodLabel";
 | 
				
			||||||
 | 
							[_specifiers addObject:uninstallationMethodSpecifier];
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							PSSpecifier* uninstallationMethodSegmentSpecifier = [PSSpecifier preferenceSpecifierNamed:@"Installation Method Segment"
 | 
				
			||||||
 | 
																target:self
 | 
				
			||||||
 | 
																set:@selector(setPreferenceValue:specifier:)
 | 
				
			||||||
 | 
																get:@selector(readPreferenceValue:)
 | 
				
			||||||
 | 
																detail:nil
 | 
				
			||||||
 | 
																cell:PSSegmentCell
 | 
				
			||||||
 | 
																edit:nil];
 | 
				
			||||||
 | 
							[uninstallationMethodSegmentSpecifier setProperty:@YES forKey:@"enabled"];
 | 
				
			||||||
 | 
							uninstallationMethodSegmentSpecifier.identifier = @"uninstallationMethodSegment";
 | 
				
			||||||
 | 
							[uninstallationMethodSegmentSpecifier setProperty:@"com.opa334.TrollStore" forKey:@"defaults"];
 | 
				
			||||||
 | 
							[uninstallationMethodSegmentSpecifier setProperty:@"uninstallationMethod" forKey:@"key"];
 | 
				
			||||||
 | 
							uninstallationMethodSegmentSpecifier.values = @[@0, @1];
 | 
				
			||||||
 | 
							uninstallationMethodSegmentSpecifier.titleDictionary = @{@0 : @"installd", @1 : @"Custom"};
 | 
				
			||||||
 | 
							[uninstallationMethodSegmentSpecifier setProperty:@0 forKey:@"default"];
 | 
				
			||||||
 | 
							[_specifiers addObject:uninstallationMethodSegmentSpecifier];
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						[(UINavigationItem *)self.navigationItem setTitle:@"Advanced"];
 | 
				
			||||||
 | 
						return _specifiers;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					- (void)setPreferenceValue:(NSObject*)value specifier:(PSSpecifier*)specifier
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
						NSUserDefaults* tsDefaults = trollStoreUserDefaults();
 | 
				
			||||||
 | 
						[tsDefaults setObject:value forKey:[specifier propertyForKey:@"key"]];
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					- (NSObject*)readPreferenceValue:(PSSpecifier*)specifier
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
						NSUserDefaults* tsDefaults = trollStoreUserDefaults();
 | 
				
			||||||
 | 
						NSObject* toReturn = [tsDefaults objectForKey:[specifier propertyForKey:@"key"]];
 | 
				
			||||||
 | 
						if(!toReturn)
 | 
				
			||||||
 | 
						{
 | 
				
			||||||
 | 
							toReturn = [specifier propertyForKey:@"default"];
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						return toReturn;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					@end
 | 
				
			||||||
@ -4,5 +4,6 @@
 | 
				
			|||||||
{
 | 
					{
 | 
				
			||||||
    PSSpecifier* _installPersistenceHelperSpecifier;
 | 
					    PSSpecifier* _installPersistenceHelperSpecifier;
 | 
				
			||||||
    NSString* _newerVersion;
 | 
					    NSString* _newerVersion;
 | 
				
			||||||
 | 
					    NSString* _newerLdidVersion;
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
@end
 | 
					@end
 | 
				
			||||||
@ -3,6 +3,8 @@
 | 
				
			|||||||
#import <Preferences/PSSpecifier.h>
 | 
					#import <Preferences/PSSpecifier.h>
 | 
				
			||||||
#import <Preferences/PSListItemsController.h>
 | 
					#import <Preferences/PSListItemsController.h>
 | 
				
			||||||
#import <TSPresentationDelegate.h>
 | 
					#import <TSPresentationDelegate.h>
 | 
				
			||||||
 | 
					#import "TSInstallationController.h"
 | 
				
			||||||
 | 
					#import "TSSettingsAdvancedListController.h"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@interface NSUserDefaults (Private)
 | 
					@interface NSUserDefaults (Private)
 | 
				
			||||||
- (instancetype)_initWithSuiteName:(NSString *)suiteName container:(NSURL *)container;
 | 
					- (instancetype)_initWithSuiteName:(NSString *)suiteName container:(NSURL *)container;
 | 
				
			||||||
@ -15,6 +17,7 @@ extern NSUserDefaults* trollStoreUserDefaults(void);
 | 
				
			|||||||
{
 | 
					{
 | 
				
			||||||
	[super viewDidLoad];
 | 
						[super viewDidLoad];
 | 
				
			||||||
	[[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(reloadSpecifiers) name:UIApplicationWillEnterForegroundNotification object:nil];
 | 
						[[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(reloadSpecifiers) name:UIApplicationWillEnterForegroundNotification object:nil];
 | 
				
			||||||
 | 
						[[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(reloadSpecifiers) name:@"TrollStoreReloadSettingsNotification" object:nil];
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	fetchLatestTrollStoreVersion(^(NSString* latestVersion)
 | 
						fetchLatestTrollStoreVersion(^(NSString* latestVersion)
 | 
				
			||||||
	{
 | 
						{
 | 
				
			||||||
@ -29,6 +32,26 @@ extern NSUserDefaults* trollStoreUserDefaults(void);
 | 
				
			|||||||
			});
 | 
								});
 | 
				
			||||||
		}
 | 
							}
 | 
				
			||||||
	});
 | 
						});
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						fetchLatestLdidVersion(^(NSString* latestVersion)
 | 
				
			||||||
 | 
						{
 | 
				
			||||||
 | 
							NSString* ldidVersionPath = [NSBundle.mainBundle.bundlePath stringByAppendingPathComponent:@"ldid.version"];
 | 
				
			||||||
 | 
							NSString* ldidVersion = nil;
 | 
				
			||||||
 | 
							NSData* ldidVersionData = [NSData dataWithContentsOfFile:ldidVersionPath];
 | 
				
			||||||
 | 
							if(ldidVersionData)
 | 
				
			||||||
 | 
							{
 | 
				
			||||||
 | 
								ldidVersion = [[NSString alloc] initWithData:ldidVersionData encoding:NSUTF8StringEncoding];
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
							
 | 
				
			||||||
 | 
							if(![latestVersion isEqualToString:ldidVersion])
 | 
				
			||||||
 | 
							{
 | 
				
			||||||
 | 
								_newerLdidVersion = latestVersion;
 | 
				
			||||||
 | 
								dispatch_async(dispatch_get_main_queue(), ^
 | 
				
			||||||
 | 
								{
 | 
				
			||||||
 | 
									[self reloadSpecifiers];
 | 
				
			||||||
 | 
								});
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
						});
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
- (NSMutableArray*)specifiers
 | 
					- (NSMutableArray*)specifiers
 | 
				
			||||||
@ -88,8 +111,16 @@ extern NSUserDefaults* trollStoreUserDefaults(void);
 | 
				
			|||||||
		[_specifiers addObject:rebuildIconCacheSpecifier];
 | 
							[_specifiers addObject:rebuildIconCacheSpecifier];
 | 
				
			||||||
 | 
					
 | 
				
			||||||
		NSString* ldidPath = [NSBundle.mainBundle.bundlePath stringByAppendingPathComponent:@"ldid"];
 | 
							NSString* ldidPath = [NSBundle.mainBundle.bundlePath stringByAppendingPathComponent:@"ldid"];
 | 
				
			||||||
 | 
							NSString* ldidVersionPath = [NSBundle.mainBundle.bundlePath stringByAppendingPathComponent:@"ldid.version"];
 | 
				
			||||||
		BOOL ldidInstalled = [[NSFileManager defaultManager] fileExistsAtPath:ldidPath];
 | 
							BOOL ldidInstalled = [[NSFileManager defaultManager] fileExistsAtPath:ldidPath];
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							NSString* ldidVersion = nil;
 | 
				
			||||||
 | 
							NSData* ldidVersionData = [NSData dataWithContentsOfFile:ldidVersionPath];
 | 
				
			||||||
 | 
							if(ldidVersionData)
 | 
				
			||||||
 | 
							{
 | 
				
			||||||
 | 
								ldidVersion = [[NSString alloc] initWithData:ldidVersionData encoding:NSUTF8StringEncoding];
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
		PSSpecifier* signingGroupSpecifier = [PSSpecifier emptyGroupSpecifier];
 | 
							PSSpecifier* signingGroupSpecifier = [PSSpecifier emptyGroupSpecifier];
 | 
				
			||||||
		signingGroupSpecifier.name = @"Signing";
 | 
							signingGroupSpecifier.name = @"Signing";
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@ -106,7 +137,13 @@ extern NSUserDefaults* trollStoreUserDefaults(void);
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
		if(ldidInstalled)
 | 
							if(ldidInstalled)
 | 
				
			||||||
		{
 | 
							{
 | 
				
			||||||
			PSSpecifier* ldidInstalledSpecifier = [PSSpecifier preferenceSpecifierNamed:@"ldid: Installed"
 | 
								NSString* installedTitle = @"ldid: Installed";
 | 
				
			||||||
 | 
								if(ldidVersion)
 | 
				
			||||||
 | 
								{
 | 
				
			||||||
 | 
									installedTitle = [NSString stringWithFormat:@"%@ (%@)", installedTitle, ldidVersion];
 | 
				
			||||||
 | 
								}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
								PSSpecifier* ldidInstalledSpecifier = [PSSpecifier preferenceSpecifierNamed:installedTitle
 | 
				
			||||||
											target:self
 | 
																target:self
 | 
				
			||||||
											set:nil
 | 
																set:nil
 | 
				
			||||||
											get:nil
 | 
																get:nil
 | 
				
			||||||
@ -116,6 +153,22 @@ extern NSUserDefaults* trollStoreUserDefaults(void);
 | 
				
			|||||||
			[ldidInstalledSpecifier setProperty:@NO forKey:@"enabled"];
 | 
								[ldidInstalledSpecifier setProperty:@NO forKey:@"enabled"];
 | 
				
			||||||
			ldidInstalledSpecifier.identifier = @"ldidInstalled";
 | 
								ldidInstalledSpecifier.identifier = @"ldidInstalled";
 | 
				
			||||||
			[_specifiers addObject:ldidInstalledSpecifier];
 | 
								[_specifiers addObject:ldidInstalledSpecifier];
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
								if(_newerLdidVersion && ![_newerLdidVersion isEqualToString:ldidVersion])
 | 
				
			||||||
 | 
								{
 | 
				
			||||||
 | 
									NSString* updateTitle = [NSString stringWithFormat:@"Update to %@", _newerLdidVersion];
 | 
				
			||||||
 | 
									PSSpecifier* ldidUpdateSpecifier = [PSSpecifier preferenceSpecifierNamed:updateTitle
 | 
				
			||||||
 | 
																target:self
 | 
				
			||||||
 | 
																set:nil
 | 
				
			||||||
 | 
																get:nil
 | 
				
			||||||
 | 
																detail:nil
 | 
				
			||||||
 | 
																cell:PSButtonCell
 | 
				
			||||||
 | 
																edit:nil];
 | 
				
			||||||
 | 
									ldidUpdateSpecifier.identifier = @"updateLdid";
 | 
				
			||||||
 | 
									[ldidUpdateSpecifier setProperty:@YES forKey:@"enabled"];
 | 
				
			||||||
 | 
									ldidUpdateSpecifier.buttonAction = @selector(installOrUpdateLdidPressed);
 | 
				
			||||||
 | 
									[_specifiers addObject:ldidUpdateSpecifier];
 | 
				
			||||||
 | 
								}
 | 
				
			||||||
		}
 | 
							}
 | 
				
			||||||
		else
 | 
							else
 | 
				
			||||||
		{
 | 
							{
 | 
				
			||||||
@ -126,9 +179,9 @@ extern NSUserDefaults* trollStoreUserDefaults(void);
 | 
				
			|||||||
											detail:nil
 | 
																detail:nil
 | 
				
			||||||
											cell:PSButtonCell
 | 
																cell:PSButtonCell
 | 
				
			||||||
											edit:nil];
 | 
																edit:nil];
 | 
				
			||||||
			installLdidSpecifier.identifier = @"ldidInstalled";
 | 
								installLdidSpecifier.identifier = @"installLdid";
 | 
				
			||||||
			[installLdidSpecifier setProperty:@YES forKey:@"enabled"];
 | 
								[installLdidSpecifier setProperty:@YES forKey:@"enabled"];
 | 
				
			||||||
			installLdidSpecifier.buttonAction = @selector(installLdidPressed);
 | 
								installLdidSpecifier.buttonAction = @selector(installOrUpdateLdidPressed);
 | 
				
			||||||
			[_specifiers addObject:installLdidSpecifier];
 | 
								[_specifiers addObject:installLdidSpecifier];
 | 
				
			||||||
		}
 | 
							}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@ -234,11 +287,21 @@ extern NSUserDefaults* trollStoreUserDefaults(void);
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
		[_specifiers addObject:installAlertConfigurationSpecifier];
 | 
							[_specifiers addObject:installAlertConfigurationSpecifier];
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					 | 
				
			||||||
		PSSpecifier* otherGroupSpecifier = [PSSpecifier emptyGroupSpecifier];
 | 
							PSSpecifier* otherGroupSpecifier = [PSSpecifier emptyGroupSpecifier];
 | 
				
			||||||
		[otherGroupSpecifier setProperty:[NSString stringWithFormat:@"TrollStore %@\n\n© 2022 Lars Fröder (opa334)\n\nCredits:\n@LinusHenze: CoreTrust bug\n@zhuowei: CoreTrust bug writeup and cert\n@lunotech11, @SerenaKit, @tylinux: Various contributions\n@ProcursusTeam: uicache and ldid build\n@cstar_ow: uicache\n@saurik: ldid", [self getTrollStoreVersion]] forKey:@"footerText"];
 | 
							[otherGroupSpecifier setProperty:[NSString stringWithFormat:@"TrollStore %@\n\n© 2022 Lars Fröder (opa334)\n\nTrollStore is NOT for piracy!\n\nCredits:\n@LinusHenze: CoreTrust bug\n@zhuowei: CoreTrust bug writeup and cert\n@lunotech11, @SerenaKit, @tylinux: Various contributions\n@ProcursusTeam: uicache and ldid build\n@cstar_ow: uicache\n@saurik: ldid", [self getTrollStoreVersion]] forKey:@"footerText"];
 | 
				
			||||||
		[_specifiers addObject:otherGroupSpecifier];
 | 
							[_specifiers addObject:otherGroupSpecifier];
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							PSSpecifier* advancedLinkSpecifier = [PSSpecifier preferenceSpecifierNamed:@"Advanced"
 | 
				
			||||||
 | 
															target:self
 | 
				
			||||||
 | 
															set:nil
 | 
				
			||||||
 | 
															get:nil
 | 
				
			||||||
 | 
															detail:nil
 | 
				
			||||||
 | 
															cell:PSLinkListCell
 | 
				
			||||||
 | 
															edit:nil];
 | 
				
			||||||
 | 
							advancedLinkSpecifier.detailControllerClass = [TSSettingsAdvancedListController class];
 | 
				
			||||||
 | 
							[advancedLinkSpecifier setProperty:@YES forKey:@"enabled"];
 | 
				
			||||||
 | 
							[_specifiers addObject:advancedLinkSpecifier];
 | 
				
			||||||
 | 
					
 | 
				
			||||||
		// Uninstall TrollStore
 | 
							// Uninstall TrollStore
 | 
				
			||||||
		PSSpecifier* uninstallTrollStoreSpecifier = [PSSpecifier preferenceSpecifierNamed:@"Uninstall TrollStore"
 | 
							PSSpecifier* uninstallTrollStoreSpecifier = [PSSpecifier preferenceSpecifierNamed:@"Uninstall TrollStore"
 | 
				
			||||||
										target:self
 | 
															target:self
 | 
				
			||||||
@ -277,7 +340,7 @@ extern NSUserDefaults* trollStoreUserDefaults(void);
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
- (NSArray*)installationConfirmationNames
 | 
					- (NSArray*)installationConfirmationNames
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
	return @[@"Always (Recommended)", @"Only on Remote Installs", @"Never (Not Recommeded)"];
 | 
						return @[@"Always (Recommended)", @"Only on Remote URL Installs", @"Never (Not Recommeded)"];
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
- (void)respringButtonPressed
 | 
					- (void)respringButtonPressed
 | 
				
			||||||
@ -285,41 +348,9 @@ extern NSUserDefaults* trollStoreUserDefaults(void);
 | 
				
			|||||||
	respring();
 | 
						respring();
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
- (void)installLdidPressed
 | 
					- (void)installOrUpdateLdidPressed
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
	NSURL* ldidURL = [NSURL URLWithString:@"https://github.com/opa334/ldid/releases/download/v2.1.5-procursus5/ldid"];
 | 
						[TSInstallationController installLdid];
 | 
				
			||||||
	NSURLRequest* ldidRequest = [NSURLRequest requestWithURL:ldidURL];
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	[TSPresentationDelegate startActivity:@"Installing ldid"];
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	NSURLSessionDownloadTask* downloadTask = [NSURLSession.sharedSession downloadTaskWithRequest:ldidRequest completionHandler:^(NSURL *location, NSURLResponse *response, NSError *error)
 | 
					 | 
				
			||||||
	{
 | 
					 | 
				
			||||||
		if(error)
 | 
					 | 
				
			||||||
		{
 | 
					 | 
				
			||||||
			UIAlertController* errorAlert = [UIAlertController alertControllerWithTitle:@"Error" message:[NSString stringWithFormat:@"Error downloading ldid: %@", error] preferredStyle:UIAlertControllerStyleAlert];
 | 
					 | 
				
			||||||
			UIAlertAction* closeAction = [UIAlertAction actionWithTitle:@"Close" style:UIAlertActionStyleDefault handler:nil];
 | 
					 | 
				
			||||||
			[errorAlert addAction:closeAction];
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
			dispatch_async(dispatch_get_main_queue(), ^
 | 
					 | 
				
			||||||
			{
 | 
					 | 
				
			||||||
				[TSPresentationDelegate stopActivityWithCompletion:^
 | 
					 | 
				
			||||||
				{
 | 
					 | 
				
			||||||
					[TSPresentationDelegate presentViewController:errorAlert animated:YES completion:nil];
 | 
					 | 
				
			||||||
				}];
 | 
					 | 
				
			||||||
			});
 | 
					 | 
				
			||||||
		}
 | 
					 | 
				
			||||||
		else
 | 
					 | 
				
			||||||
		{
 | 
					 | 
				
			||||||
			spawnRoot(rootHelperPath(), @[@"install-ldid", location.path], nil, nil);
 | 
					 | 
				
			||||||
			dispatch_async(dispatch_get_main_queue(), ^
 | 
					 | 
				
			||||||
			{
 | 
					 | 
				
			||||||
				[TSPresentationDelegate stopActivityWithCompletion:nil];
 | 
					 | 
				
			||||||
				[self reloadSpecifiers];
 | 
					 | 
				
			||||||
			});
 | 
					 | 
				
			||||||
		}
 | 
					 | 
				
			||||||
	}];
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	[downloadTask resume];
 | 
					 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
- (void)installPersistenceHelperPressed
 | 
					- (void)installPersistenceHelperPressed
 | 
				
			||||||
@ -410,4 +441,18 @@ extern NSUserDefaults* trollStoreUserDefaults(void);
 | 
				
			|||||||
	return toReturn;
 | 
						return toReturn;
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					- (NSMutableArray*)argsForUninstallingTrollStore
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
						NSMutableArray* args = @[@"uninstall-trollstore"].mutableCopy;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						NSNumber* uninstallationMethodToUseNum = [trollStoreUserDefaults() objectForKey:@"uninstallationMethod"];
 | 
				
			||||||
 | 
					    int uninstallationMethodToUse = uninstallationMethodToUseNum ? uninstallationMethodToUseNum.intValue : 0;
 | 
				
			||||||
 | 
					    if(uninstallationMethodToUse == 1)
 | 
				
			||||||
 | 
					    {
 | 
				
			||||||
 | 
					        [args addObject:@"custom"];
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						return args;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@end
 | 
					@end
 | 
				
			||||||
							
								
								
									
										
											BIN
										
									
								
								cert_new.p12
									
									
									
									
									
								
							
							
						
						
									
										
											BIN
										
									
								
								cert_new.p12
									
									
									
									
									
								
							
										
											Binary file not shown.
										
									
								
							
		Loading…
	
		Reference in New Issue
	
	Block a user