mirror of
				https://github.com/opa334/TrollStore.git
				synced 2025-11-04 15:42:35 +08:00 
			
		
		
		
	1.0.2
This commit is contained in:
		
							parent
							
								
									068f735233
								
							
						
					
					
						commit
						c2a5e5b988
					
				@ -1,6 +1,6 @@
 | 
				
			|||||||
Package: com.opa334.trollstoreroothelper
 | 
					Package: com.opa334.trollstoreroothelper
 | 
				
			||||||
Name: trollstoreroothelper
 | 
					Name: trollstoreroothelper
 | 
				
			||||||
Version: 1.0.1
 | 
					Version: 1.0.2
 | 
				
			||||||
Architecture: iphoneos-arm
 | 
					Architecture: iphoneos-arm
 | 
				
			||||||
Description: An awesome tool of some sort!!
 | 
					Description: An awesome tool of some sort!!
 | 
				
			||||||
Maintainer: opa334
 | 
					Maintainer: opa334
 | 
				
			||||||
 | 
				
			|||||||
@ -200,6 +200,16 @@ NSString* dumpEntitlements(NSString* binaryPath)
 | 
				
			|||||||
	return output;
 | 
						return output;
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					NSDictionary* dumpEntitlementsDict(NSString* binaryPath)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
						NSString* entitlementsString = dumpEntitlements(binaryPath);
 | 
				
			||||||
 | 
						NSData* plistData = [entitlementsString dataUsingEncoding:NSUTF8StringEncoding];
 | 
				
			||||||
 | 
						NSError *error;
 | 
				
			||||||
 | 
						NSPropertyListFormat format;
 | 
				
			||||||
 | 
						NSDictionary* plist = [NSPropertyListSerialization propertyListWithData:plistData options:NSPropertyListImmutable format:&format error:&error];
 | 
				
			||||||
 | 
						return plist;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
BOOL signApp(NSString* appPath, NSError** error)
 | 
					BOOL signApp(NSString* appPath, NSError** error)
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
	if(!isLdidInstalled()) return NO;
 | 
						if(!isLdidInstalled()) return NO;
 | 
				
			||||||
@ -246,8 +256,10 @@ BOOL signApp(NSString* appPath, NSError** error)
 | 
				
			|||||||
// 170: failed to create container for app bundle
 | 
					// 170: failed to create container for app bundle
 | 
				
			||||||
// 171: a non trollstore app with the same identifier is already installled
 | 
					// 171: a non trollstore app with the same identifier is already installled
 | 
				
			||||||
// 172: no info.plist found in app
 | 
					// 172: no info.plist found in app
 | 
				
			||||||
int installApp(NSString* appPath, BOOL sign, NSError** error)
 | 
					int installApp(NSString* appPath, BOOL sign, BOOL force, NSError** error)
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
 | 
						NSLog(@"[installApp force = %d]", force);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	NSString* appId = appIdForAppPath(appPath);
 | 
						NSString* appId = appIdForAppPath(appPath);
 | 
				
			||||||
	if(!appId) return 172;
 | 
						if(!appId) return 172;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@ -281,12 +293,15 @@ int installApp(NSString* appPath, BOOL sign, NSError** error)
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
	// Make sure there isn't already an app store app installed with the same identifier
 | 
						// Make sure there isn't already an app store app installed with the same identifier
 | 
				
			||||||
	NSURL* trollStoreMarkURL = [appContainer.url URLByAppendingPathComponent:@"_TrollStore"];
 | 
						NSURL* trollStoreMarkURL = [appContainer.url URLByAppendingPathComponent:@"_TrollStore"];
 | 
				
			||||||
	if(existed && !isEmpty && ![trollStoreMarkURL checkResourceIsReachableAndReturnError:nil])
 | 
						if(existed && !isEmpty && ![trollStoreMarkURL checkResourceIsReachableAndReturnError:nil] && !force)
 | 
				
			||||||
	{
 | 
						{
 | 
				
			||||||
		NSLog(@"[installApp] already installed and not a TrollStore app... bailing out");
 | 
							NSLog(@"[installApp] already installed and not a TrollStore app... bailing out");
 | 
				
			||||||
		return 171;
 | 
							return 171;
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						// Mark app as TrollStore app
 | 
				
			||||||
 | 
						[[NSFileManager defaultManager] createFileAtPath:trollStoreMarkURL.path contents:[NSData data] attributes:nil];
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	// Apply correct permissions
 | 
						// Apply correct permissions
 | 
				
			||||||
	NSDirectoryEnumerator *enumerator = [[NSFileManager defaultManager] enumeratorAtURL:[NSURL fileURLWithPath:appPath] includingPropertiesForKeys:nil options:0 errorHandler:nil];
 | 
						NSDirectoryEnumerator *enumerator = [[NSFileManager defaultManager] enumeratorAtURL:[NSURL fileURLWithPath:appPath] includingPropertiesForKeys:nil options:0 errorHandler:nil];
 | 
				
			||||||
	NSURL* fileURL;
 | 
						NSURL* fileURL;
 | 
				
			||||||
@ -342,7 +357,7 @@ int installApp(NSString* appPath, BOOL sign, NSError** error)
 | 
				
			|||||||
		while(fileURL = [enumerator nextObject])
 | 
							while(fileURL = [enumerator nextObject])
 | 
				
			||||||
		{
 | 
							{
 | 
				
			||||||
			// do not under any circumstance delete this file as it makes iOS loose the app registration
 | 
								// do not under any circumstance delete this file as it makes iOS loose the app registration
 | 
				
			||||||
			if([fileURL.lastPathComponent isEqualToString:@".com.apple.mobile_container_manager.metadata.plist"])
 | 
								if([fileURL.lastPathComponent isEqualToString:@".com.apple.mobile_container_manager.metadata.plist"] || [fileURL.lastPathComponent isEqualToString:@"_TrollStore"])
 | 
				
			||||||
			{
 | 
								{
 | 
				
			||||||
				NSLog(@"[installApp] skip removal of %@", fileURL);
 | 
									NSLog(@"[installApp] skip removal of %@", fileURL);
 | 
				
			||||||
				continue;
 | 
									continue;
 | 
				
			||||||
@ -359,9 +374,6 @@ int installApp(NSString* appPath, BOOL sign, NSError** error)
 | 
				
			|||||||
	BOOL suc = [[NSFileManager defaultManager] copyItemAtPath:appPath toPath:newAppPath error:error];
 | 
						BOOL suc = [[NSFileManager defaultManager] copyItemAtPath:appPath toPath:newAppPath error:error];
 | 
				
			||||||
	if(suc)
 | 
						if(suc)
 | 
				
			||||||
	{
 | 
						{
 | 
				
			||||||
		// Mark app as TrollStore app
 | 
					 | 
				
			||||||
		[[NSFileManager defaultManager] createFileAtPath:trollStoreMarkURL.path contents:[NSData data] attributes:nil];
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
		NSLog(@"[installApp] app installed, adding to icon cache now...");
 | 
							NSLog(@"[installApp] app installed, adding to icon cache now...");
 | 
				
			||||||
		registerPath((char*)newAppPath.UTF8String, 0);
 | 
							registerPath((char*)newAppPath.UTF8String, 0);
 | 
				
			||||||
		return 0;
 | 
							return 0;
 | 
				
			||||||
@ -382,6 +394,7 @@ int uninstallApp(NSString* appId, NSError** error)
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	MCMContainer *appContainer = [objc_getClass("MCMAppDataContainer") containerWithIdentifier:appId createIfNecessary:NO existed:nil error:nil];
 | 
						MCMContainer *appContainer = [objc_getClass("MCMAppDataContainer") containerWithIdentifier:appId createIfNecessary:NO existed:nil error:nil];
 | 
				
			||||||
 | 
						NSLog(@"1");
 | 
				
			||||||
	NSString *containerPath = [appContainer url].path;
 | 
						NSString *containerPath = [appContainer url].path;
 | 
				
			||||||
	if(containerPath)
 | 
						if(containerPath)
 | 
				
			||||||
	{
 | 
						{
 | 
				
			||||||
@ -391,11 +404,11 @@ int uninstallApp(NSString* appId, NSError** error)
 | 
				
			|||||||
	}
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	// delete group container paths
 | 
						// delete group container paths
 | 
				
			||||||
	for(NSURL* groupURL in [appProxy groupContainerURLs])
 | 
						[[appProxy groupContainerURLs] enumerateKeysAndObjectsUsingBlock:^(NSString* groupID, NSURL* groupURL, BOOL* stop)
 | 
				
			||||||
	{
 | 
						{
 | 
				
			||||||
		[[NSFileManager defaultManager] removeItemAtPath:groupURL.path error:error];
 | 
							[[NSFileManager defaultManager] removeItemAtURL:groupURL error:nil];
 | 
				
			||||||
		NSLog(@"deleting %@", groupURL.path);
 | 
							NSLog(@"deleting %@", groupURL);
 | 
				
			||||||
	}
 | 
						}];
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	// delete app plugin paths
 | 
						// delete app plugin paths
 | 
				
			||||||
	for(LSPlugInKitProxy* pluginProxy in appProxy.plugInKitPlugins)
 | 
						for(LSPlugInKitProxy* pluginProxy in appProxy.plugInKitPlugins)
 | 
				
			||||||
@ -427,7 +440,7 @@ int uninstallApp(NSString* appId, NSError** error)
 | 
				
			|||||||
// 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, NSError** error)
 | 
					int installIpa(NSString* ipaPath, BOOL force, NSError** error)
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
	if(![[NSFileManager defaultManager] fileExistsAtPath:ipaPath]) return 166;
 | 
						if(![[NSFileManager defaultManager] fileExistsAtPath:ipaPath]) return 166;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@ -455,7 +468,7 @@ int installIpa(NSString* ipaPath, NSError** error)
 | 
				
			|||||||
	}
 | 
						}
 | 
				
			||||||
	if(!tmpAppPath) return 167;
 | 
						if(!tmpAppPath) return 167;
 | 
				
			||||||
	
 | 
						
 | 
				
			||||||
	int ret = installApp(tmpAppPath, YES, error);
 | 
						int ret = installApp(tmpAppPath, YES, force, error);
 | 
				
			||||||
	
 | 
						
 | 
				
			||||||
	[[NSFileManager defaultManager] removeItemAtPath:tmpAppPath error:nil];
 | 
						[[NSFileManager defaultManager] removeItemAtPath:tmpAppPath error:nil];
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@ -530,7 +543,7 @@ BOOL installTrollStore(NSString* pathToTar)
 | 
				
			|||||||
		_installPersistenceHelper(persistenceHelperApp, trollStorePersistenceHelper, trollStoreRootHelper);
 | 
							_installPersistenceHelper(persistenceHelperApp, trollStorePersistenceHelper, trollStoreRootHelper);
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	return installApp(tmpTrollStore, NO, nil);;
 | 
						return installApp(tmpTrollStore, NO, YES, nil);;
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
void refreshAppRegistrations()
 | 
					void refreshAppRegistrations()
 | 
				
			||||||
@ -663,9 +676,19 @@ int main(int argc, char *argv[], char *envp[]) {
 | 
				
			|||||||
		NSString* cmd = [NSString stringWithUTF8String:argv[1]];
 | 
							NSString* cmd = [NSString stringWithUTF8String:argv[1]];
 | 
				
			||||||
		if([cmd isEqualToString:@"install"])
 | 
							if([cmd isEqualToString:@"install"])
 | 
				
			||||||
		{
 | 
							{
 | 
				
			||||||
 | 
								NSLog(@"argc = %d", argc);
 | 
				
			||||||
 | 
								BOOL force = NO;
 | 
				
			||||||
			if(argc <= 2) return -3;
 | 
								if(argc <= 2) return -3;
 | 
				
			||||||
 | 
								if(argc > 3)
 | 
				
			||||||
 | 
								{
 | 
				
			||||||
 | 
									NSLog(@"argv3 = %s", argv[3]);
 | 
				
			||||||
 | 
									if(!strcmp(argv[3], "force"))
 | 
				
			||||||
 | 
									{
 | 
				
			||||||
 | 
										force = YES;
 | 
				
			||||||
 | 
									}
 | 
				
			||||||
 | 
								}
 | 
				
			||||||
			NSString* ipaPath = [NSString stringWithUTF8String:argv[2]];
 | 
								NSString* ipaPath = [NSString stringWithUTF8String:argv[2]];
 | 
				
			||||||
			ret = installIpa(ipaPath, &error);
 | 
								ret = installIpa(ipaPath, force, &error);
 | 
				
			||||||
		} else if([cmd isEqualToString:@"uninstall"])
 | 
							} else if([cmd isEqualToString:@"uninstall"])
 | 
				
			||||||
		{
 | 
							{
 | 
				
			||||||
			if(argc <= 2) return -3;
 | 
								if(argc <= 2) return -3;
 | 
				
			||||||
 | 
				
			|||||||
							
								
								
									
										316
									
								
								Helper/uicache.m
									
									
									
									
									
								
							
							
						
						
									
										316
									
								
								Helper/uicache.m
									
									
									
									
									
								
							@ -4,89 +4,247 @@
 | 
				
			|||||||
#import <objc/runtime.h>
 | 
					#import <objc/runtime.h>
 | 
				
			||||||
#import "dlfcn.h"
 | 
					#import "dlfcn.h"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
void registerPath(char *path, int unregister)
 | 
					// uicache on steroids
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					extern NSDictionary* dumpEntitlementsDict(NSString* binaryPath);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					NSDictionary* constructGroupsContainersForEntitlements(NSDictionary* entitlements, BOOL systemGroups)
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
    if(!path) return;
 | 
						if(!entitlements) return nil;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    LSApplicationWorkspace *workspace =
 | 
						NSString* entitlementForGroups;
 | 
				
			||||||
        [LSApplicationWorkspace defaultWorkspace];
 | 
						NSString* mcmClass;
 | 
				
			||||||
    if (unregister && ![[NSFileManager defaultManager] fileExistsAtPath:[NSString stringWithUTF8String:path]]) {
 | 
						if(systemGroups)
 | 
				
			||||||
        LSApplicationProxy *app = [LSApplicationProxy
 | 
						{
 | 
				
			||||||
            applicationProxyForIdentifier:[NSString stringWithUTF8String:path]];
 | 
							entitlementForGroups = @"com.apple.security.system-groups";
 | 
				
			||||||
        if (app.bundleURL)
 | 
							mcmClass = @"MCMSystemDataContainer";
 | 
				
			||||||
            path = (char *)[[app bundleURL] fileSystemRepresentation];
 | 
						}
 | 
				
			||||||
    }
 | 
						else
 | 
				
			||||||
 | 
						{
 | 
				
			||||||
 | 
							entitlementForGroups = @"com.apple.security.application-groups";
 | 
				
			||||||
 | 
							mcmClass = @"MCMSharedDataContainer";
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    NSString *rawPath = [NSString stringWithUTF8String:path];
 | 
						NSArray* groupIDs = entitlements[entitlementForGroups];
 | 
				
			||||||
    rawPath = [rawPath stringByResolvingSymlinksInPath];
 | 
						if(groupIDs && [groupIDs isKindOfClass:[NSArray class]])
 | 
				
			||||||
 | 
						{
 | 
				
			||||||
 | 
							NSMutableDictionary* groupContainers = [NSMutableDictionary new];
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    NSDictionary *infoPlist = [NSDictionary
 | 
							for(NSString* groupID in groupIDs)
 | 
				
			||||||
        dictionaryWithContentsOfFile:
 | 
							{
 | 
				
			||||||
            [rawPath stringByAppendingPathComponent:@"Info.plist"]];
 | 
								MCMContainer* container = [NSClassFromString(mcmClass) containerWithIdentifier:groupID createIfNecessary:YES existed:nil error:nil];
 | 
				
			||||||
    NSString *bundleID = [infoPlist objectForKey:@"CFBundleIdentifier"];
 | 
								if(container.url)
 | 
				
			||||||
 | 
								{
 | 
				
			||||||
 | 
									groupContainers[groupID] = container.url.path;
 | 
				
			||||||
 | 
								}
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    NSURL *url = [NSURL fileURLWithPath:rawPath];
 | 
							return groupContainers.copy;
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    if (bundleID && !unregister) {
 | 
						return nil;
 | 
				
			||||||
        MCMContainer *appContainer = [objc_getClass("MCMAppDataContainer")
 | 
					}
 | 
				
			||||||
            containerWithIdentifier:bundleID
 | 
					
 | 
				
			||||||
                  createIfNecessary:YES
 | 
					BOOL constructContainerizationForEntitlements(NSDictionary* entitlements)
 | 
				
			||||||
                            existed:nil
 | 
					{
 | 
				
			||||||
                              error:nil];
 | 
						NSNumber* noContainer = entitlements[@"com.apple.private.security.no-container"];
 | 
				
			||||||
        NSString *containerPath = [appContainer url].path;
 | 
						if(noContainer && [noContainer isKindOfClass:[NSNumber class]])
 | 
				
			||||||
 | 
						{
 | 
				
			||||||
        NSMutableDictionary *plist = [NSMutableDictionary dictionary];
 | 
							if(noContainer.boolValue)
 | 
				
			||||||
        [plist setObject:@"System" forKey:@"ApplicationType"];
 | 
							{
 | 
				
			||||||
        [plist setObject:@1 forKey:@"BundleNameIsLocalized"];
 | 
								return NO;
 | 
				
			||||||
        [plist setObject:bundleID forKey:@"CFBundleIdentifier"];
 | 
							}
 | 
				
			||||||
        [plist setObject:@0 forKey:@"CompatibilityState"];
 | 
						}
 | 
				
			||||||
        if (containerPath) [plist setObject:containerPath forKey:@"Container"];
 | 
					
 | 
				
			||||||
        [plist setObject:@0 forKey:@"IsDeletable"];
 | 
						NSNumber* containerRequired = entitlements[@"com.apple.private.security.container-required"];
 | 
				
			||||||
        [plist setObject:rawPath forKey:@"Path"];
 | 
						if(containerRequired && [containerRequired isKindOfClass:[NSNumber class]])
 | 
				
			||||||
 | 
						{
 | 
				
			||||||
        NSString *pluginsPath =
 | 
							if(!containerRequired.boolValue)
 | 
				
			||||||
            [rawPath stringByAppendingPathComponent:@"PlugIns"];
 | 
							{
 | 
				
			||||||
        NSArray *plugins = [[NSFileManager defaultManager]
 | 
								return NO;
 | 
				
			||||||
            contentsOfDirectoryAtPath:pluginsPath
 | 
							}
 | 
				
			||||||
                                error:nil];
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        NSMutableDictionary *bundlePlugins = [NSMutableDictionary dictionary];
 | 
						return YES;
 | 
				
			||||||
        for (NSString *pluginName in plugins) {
 | 
					}
 | 
				
			||||||
            NSString *fullPath =
 | 
					
 | 
				
			||||||
                [pluginsPath stringByAppendingPathComponent:pluginName];
 | 
					NSString* constructTeamIdentifierForEntitlements(NSDictionary* entitlements)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
            NSDictionary *infoPlist = [NSDictionary
 | 
						NSString* teamIdentifier = entitlements[@"com.apple.developer.team-identifier"];
 | 
				
			||||||
                dictionaryWithContentsOfFile:
 | 
						if(teamIdentifier && [teamIdentifier isKindOfClass:[NSString class]])
 | 
				
			||||||
                    [fullPath stringByAppendingPathComponent:@"Info.plist"]];
 | 
						{
 | 
				
			||||||
            NSString *pluginBundleID =
 | 
							return teamIdentifier;
 | 
				
			||||||
                [infoPlist objectForKey:@"CFBundleIdentifier"];
 | 
						}
 | 
				
			||||||
            if (!pluginBundleID) continue;
 | 
						return nil;
 | 
				
			||||||
            MCMContainer *pluginContainer =
 | 
					}
 | 
				
			||||||
                [objc_getClass("MCMPluginKitPluginDataContainer")
 | 
					
 | 
				
			||||||
                    containerWithIdentifier:pluginBundleID
 | 
					NSDictionary* constructEnvironmentVariablesForContainerPath(NSString* containerPath)
 | 
				
			||||||
                          createIfNecessary:YES
 | 
					{
 | 
				
			||||||
                                    existed:nil
 | 
						NSString* tmpDir = [containerPath stringByAppendingPathComponent:@"tmp"];
 | 
				
			||||||
                                      error:nil];
 | 
						return @{
 | 
				
			||||||
            NSString *pluginContainerPath = [pluginContainer url].path;
 | 
							@"CFFIXED_USER_HOME" : containerPath,
 | 
				
			||||||
 | 
							@"HOME" : containerPath,
 | 
				
			||||||
            NSMutableDictionary *pluginPlist = [NSMutableDictionary dictionary];
 | 
							@"TMPDIR" : tmpDir
 | 
				
			||||||
            [pluginPlist setObject:@"PluginKitPlugin"
 | 
						};
 | 
				
			||||||
                            forKey:@"ApplicationType"];
 | 
					}
 | 
				
			||||||
            [pluginPlist setObject:@1 forKey:@"BundleNameIsLocalized"];
 | 
					
 | 
				
			||||||
            [pluginPlist setObject:pluginBundleID forKey:@"CFBundleIdentifier"];
 | 
					void registerPath(char* cPath, int unregister)
 | 
				
			||||||
            [pluginPlist setObject:@0 forKey:@"CompatibilityState"];
 | 
					{
 | 
				
			||||||
            [pluginPlist setObject:pluginContainerPath forKey:@"Container"];
 | 
						if(!cPath) return;
 | 
				
			||||||
            [pluginPlist setObject:fullPath forKey:@"Path"];
 | 
						NSString* path = [NSString stringWithUTF8String:cPath];
 | 
				
			||||||
            [pluginPlist setObject:bundleID forKey:@"PluginOwnerBundleID"];
 | 
					
 | 
				
			||||||
            [bundlePlugins setObject:pluginPlist forKey:pluginBundleID];
 | 
						LSApplicationWorkspace* workspace = [LSApplicationWorkspace defaultWorkspace];
 | 
				
			||||||
        }
 | 
						if(unregister && ![[NSFileManager defaultManager] fileExistsAtPath:path])
 | 
				
			||||||
        [plist setObject:bundlePlugins forKey:@"_LSBundlePlugins"];
 | 
						{
 | 
				
			||||||
        if (![workspace registerApplicationDictionary:plist]) {
 | 
							LSApplicationProxy* app = [LSApplicationProxy applicationProxyForIdentifier:path];
 | 
				
			||||||
            fprintf(stderr, "Error: Unable to register %s\n", path);
 | 
							if(app.bundleURL)
 | 
				
			||||||
        }
 | 
							{
 | 
				
			||||||
    } else {
 | 
								path = [app bundleURL].path;
 | 
				
			||||||
        if (![workspace unregisterApplication:url]) {
 | 
							}
 | 
				
			||||||
            fprintf(stderr, "Error: Unable to unregister %s\n", path);
 | 
						}
 | 
				
			||||||
        }
 | 
					
 | 
				
			||||||
    }
 | 
						path = [path stringByResolvingSymlinksInPath];
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						NSDictionary* appInfoPlist = [NSDictionary dictionaryWithContentsOfFile:[path stringByAppendingPathComponent:@"Info.plist"]];
 | 
				
			||||||
 | 
						NSString* appBundleID = [appInfoPlist objectForKey:@"CFBundleIdentifier"];
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						if(appBundleID && !unregister)
 | 
				
			||||||
 | 
						{
 | 
				
			||||||
 | 
							MCMContainer* appContainer = [NSClassFromString(@"MCMAppDataContainer") containerWithIdentifier:appBundleID createIfNecessary:YES existed:nil error:nil];
 | 
				
			||||||
 | 
							NSString* containerPath = [appContainer url].path;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							NSMutableDictionary* dictToRegister = [NSMutableDictionary dictionary];
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							// Add entitlements
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							NSString* appExecutablePath = [path stringByAppendingPathComponent:appInfoPlist[@"CFBundleExecutable"]];
 | 
				
			||||||
 | 
							NSDictionary* entitlements = dumpEntitlementsDict(appExecutablePath);
 | 
				
			||||||
 | 
							if(entitlements)
 | 
				
			||||||
 | 
							{
 | 
				
			||||||
 | 
								dictToRegister[@"Entitlements"] = entitlements;
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							// Misc
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							dictToRegister[@"ApplicationType"] = @"System";
 | 
				
			||||||
 | 
							dictToRegister[@"BundleNameIsLocalized"] = @1;
 | 
				
			||||||
 | 
							dictToRegister[@"CFBundleIdentifier"] = appBundleID;
 | 
				
			||||||
 | 
							dictToRegister[@"CodeInfoIdentifier"] = appBundleID;
 | 
				
			||||||
 | 
							dictToRegister[@"CompatibilityState"] = @0;
 | 
				
			||||||
 | 
							if(containerPath)
 | 
				
			||||||
 | 
							{
 | 
				
			||||||
 | 
								dictToRegister[@"Container"] = containerPath;
 | 
				
			||||||
 | 
								dictToRegister[@"EnvironmentVariables"] = constructEnvironmentVariablesForContainerPath(containerPath);
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
							dictToRegister[@"IsDeletable"] = @0;
 | 
				
			||||||
 | 
							dictToRegister[@"Path"] = path;
 | 
				
			||||||
 | 
							dictToRegister[@"IsContainerized"] = @(constructContainerizationForEntitlements(entitlements));
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							NSString* teamIdentifier = constructTeamIdentifierForEntitlements(entitlements);
 | 
				
			||||||
 | 
							if(teamIdentifier) dictToRegister[@"TeamIdentifier"] = teamIdentifier;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							// Add group containers
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							NSDictionary* appGroupContainers = constructGroupsContainersForEntitlements(entitlements, NO);
 | 
				
			||||||
 | 
							NSDictionary* systemGroupContainers = constructGroupsContainersForEntitlements(entitlements, NO);
 | 
				
			||||||
 | 
							NSMutableDictionary* groupContainers = [NSMutableDictionary new];
 | 
				
			||||||
 | 
							[groupContainers addEntriesFromDictionary:appGroupContainers];
 | 
				
			||||||
 | 
							[groupContainers addEntriesFromDictionary:systemGroupContainers];
 | 
				
			||||||
 | 
							if(groupContainers.count)
 | 
				
			||||||
 | 
							{
 | 
				
			||||||
 | 
								if(appGroupContainers.count)
 | 
				
			||||||
 | 
								{
 | 
				
			||||||
 | 
									dictToRegister[@"HasAppGroupContainers"] = @YES;
 | 
				
			||||||
 | 
								}
 | 
				
			||||||
 | 
								if(systemGroupContainers.count)
 | 
				
			||||||
 | 
								{
 | 
				
			||||||
 | 
									dictToRegister[@"HasSystemGroupContainers"] = @YES;
 | 
				
			||||||
 | 
								}
 | 
				
			||||||
 | 
								dictToRegister[@"GroupContainers"] = groupContainers.copy;
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							// Add plugins
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							NSString* pluginsPath = [path stringByAppendingPathComponent:@"PlugIns"];
 | 
				
			||||||
 | 
							NSArray* plugins = [[NSFileManager defaultManager] contentsOfDirectoryAtPath:pluginsPath error:nil];
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							NSMutableDictionary* bundlePlugins = [NSMutableDictionary dictionary];
 | 
				
			||||||
 | 
							for (NSString* pluginName in plugins)
 | 
				
			||||||
 | 
							{
 | 
				
			||||||
 | 
								NSString* pluginPath = [pluginsPath stringByAppendingPathComponent:pluginName];
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
								NSDictionary* pluginInfoPlist = [NSDictionary dictionaryWithContentsOfFile:[pluginPath stringByAppendingPathComponent:@"Info.plist"]];
 | 
				
			||||||
 | 
								NSString* pluginBundleID = [pluginInfoPlist objectForKey:@"CFBundleIdentifier"];
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
								if(!pluginBundleID) continue;
 | 
				
			||||||
 | 
								MCMContainer* pluginContainer = [NSClassFromString(@"MCMPluginKitPluginDataContainer") containerWithIdentifier:pluginBundleID createIfNecessary:YES existed:nil error:nil];
 | 
				
			||||||
 | 
								NSString* pluginContainerPath = [pluginContainer url].path;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
								NSMutableDictionary* pluginDict = [NSMutableDictionary dictionary];
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
								// Add entitlements
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
								NSString* pluginExecutablePath = [pluginPath stringByAppendingPathComponent:pluginInfoPlist[@"CFBundleExecutable"]];
 | 
				
			||||||
 | 
								NSDictionary* pluginEntitlements = dumpEntitlementsDict(pluginExecutablePath);
 | 
				
			||||||
 | 
								if(pluginEntitlements)
 | 
				
			||||||
 | 
								{
 | 
				
			||||||
 | 
									pluginDict[@"Entitlements"] = pluginEntitlements;
 | 
				
			||||||
 | 
								}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
								// Misc
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
								pluginDict[@"ApplicationType"] = @"PluginKitPlugin";
 | 
				
			||||||
 | 
								pluginDict[@"BundleNameIsLocalized"] = @1;
 | 
				
			||||||
 | 
								pluginDict[@"CFBundleIdentifier"] = pluginBundleID;
 | 
				
			||||||
 | 
								pluginDict[@"CodeInfoIdentifier"] = pluginBundleID;
 | 
				
			||||||
 | 
								pluginDict[@"CompatibilityState"] = @0;
 | 
				
			||||||
 | 
								if(pluginContainerPath)
 | 
				
			||||||
 | 
								{
 | 
				
			||||||
 | 
									pluginDict[@"Container"] = pluginContainerPath;
 | 
				
			||||||
 | 
									pluginDict[@"EnvironmentVariables"] = constructEnvironmentVariablesForContainerPath(pluginContainerPath);
 | 
				
			||||||
 | 
								}
 | 
				
			||||||
 | 
								pluginDict[@"Path"] = pluginPath;
 | 
				
			||||||
 | 
								pluginDict[@"PluginOwnerBundleID"] = appBundleID;
 | 
				
			||||||
 | 
								pluginDict[@"IsContainerized"] = @(constructContainerizationForEntitlements(pluginEntitlements));
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
								NSString* pluginTeamIdentifier = constructTeamIdentifierForEntitlements(pluginEntitlements);
 | 
				
			||||||
 | 
								if(pluginTeamIdentifier) pluginDict[@"TeamIdentifier"] = pluginTeamIdentifier;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
								// Add plugin group containers
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
								NSDictionary* pluginAppGroupContainers = constructGroupsContainersForEntitlements(pluginEntitlements, NO);
 | 
				
			||||||
 | 
								NSDictionary* pluginSystemGroupContainers = constructGroupsContainersForEntitlements(pluginEntitlements, NO);
 | 
				
			||||||
 | 
								NSMutableDictionary* pluginGroupContainers = [NSMutableDictionary new];
 | 
				
			||||||
 | 
								[pluginGroupContainers addEntriesFromDictionary:pluginAppGroupContainers];
 | 
				
			||||||
 | 
								[pluginGroupContainers addEntriesFromDictionary:pluginSystemGroupContainers];
 | 
				
			||||||
 | 
								if(pluginGroupContainers.count)
 | 
				
			||||||
 | 
								{
 | 
				
			||||||
 | 
									if(pluginAppGroupContainers.count)
 | 
				
			||||||
 | 
									{
 | 
				
			||||||
 | 
										pluginDict[@"HasAppGroupContainers"] = @YES;
 | 
				
			||||||
 | 
									}
 | 
				
			||||||
 | 
									if(pluginSystemGroupContainers.count)
 | 
				
			||||||
 | 
									{
 | 
				
			||||||
 | 
										pluginDict[@"HasSystemGroupContainers"] = @YES;
 | 
				
			||||||
 | 
									}
 | 
				
			||||||
 | 
									pluginDict[@"GroupContainers"] = pluginGroupContainers.copy;
 | 
				
			||||||
 | 
								}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
								[bundlePlugins setObject:pluginDict forKey:pluginBundleID];
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
							[dictToRegister setObject:bundlePlugins forKey:@"_LSBundlePlugins"];
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							if(![workspace registerApplicationDictionary:dictToRegister])
 | 
				
			||||||
 | 
							{
 | 
				
			||||||
 | 
								NSLog(@"Error: Unable to register %@", path);
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						else
 | 
				
			||||||
 | 
						{
 | 
				
			||||||
 | 
							NSURL* url = [NSURL fileURLWithPath:path];
 | 
				
			||||||
 | 
							if(![workspace unregisterApplication:url])
 | 
				
			||||||
 | 
							{
 | 
				
			||||||
 | 
								NSLog(@"Error: Unable to unregister %@", path);
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
@ -65,6 +65,7 @@ int IOGPU_get_command_queue_extra_refills_needed(void)
 | 
				
			|||||||
    || strstr(u.machine, "iPhone14,")
 | 
					    || strstr(u.machine, "iPhone14,")
 | 
				
			||||||
    || strstr(u.machine, "iPad13,")
 | 
					    || strstr(u.machine, "iPad13,")
 | 
				
			||||||
    || strstr(u.machine, "iPad7,")
 | 
					    || strstr(u.machine, "iPad7,")
 | 
				
			||||||
 | 
					    || strstr(u.machine, "iPad12,")
 | 
				
			||||||
    )
 | 
					    )
 | 
				
			||||||
    {
 | 
					    {
 | 
				
			||||||
        return 1;
 | 
					        return 1;
 | 
				
			||||||
@ -72,10 +73,12 @@ int IOGPU_get_command_queue_extra_refills_needed(void)
 | 
				
			|||||||
    // iPhone 8, X
 | 
					    // iPhone 8, X
 | 
				
			||||||
    // iPhone XS, XR
 | 
					    // iPhone XS, XR
 | 
				
			||||||
    // iPad Pro A12Z
 | 
					    // iPad Pro A12Z
 | 
				
			||||||
 | 
					    // iPad 8 A12
 | 
				
			||||||
    else if (
 | 
					    else if (
 | 
				
			||||||
       strstr(u.machine, "iPhone10,")
 | 
					       strstr(u.machine, "iPhone10,")
 | 
				
			||||||
    || strstr(u.machine, "iPhone11,")
 | 
					    || strstr(u.machine, "iPhone11,")
 | 
				
			||||||
    || strstr(u.machine, "iPad8,")
 | 
					    || strstr(u.machine, "iPad8,")
 | 
				
			||||||
 | 
					    || strstr(u.machine, "iPad11,")
 | 
				
			||||||
    )
 | 
					    )
 | 
				
			||||||
    {
 | 
					    {
 | 
				
			||||||
        return 3;
 | 
					        return 3;
 | 
				
			||||||
 | 
				
			|||||||
@ -52,7 +52,7 @@
 | 
				
			|||||||
		<string>iPhoneOS</string>
 | 
							<string>iPhoneOS</string>
 | 
				
			||||||
	</array>
 | 
						</array>
 | 
				
			||||||
	<key>CFBundleVersion</key>
 | 
						<key>CFBundleVersion</key>
 | 
				
			||||||
	<string>1.0</string>
 | 
						<string>1.0.2</string>
 | 
				
			||||||
	<key>LSRequiresIPhoneOS</key>
 | 
						<key>LSRequiresIPhoneOS</key>
 | 
				
			||||||
	<true/>
 | 
						<true/>
 | 
				
			||||||
	<key>UIDeviceFamily</key>
 | 
						<key>UIDeviceFamily</key>
 | 
				
			||||||
 | 
				
			|||||||
										
											Binary file not shown.
										
									
								
							@ -1,6 +1,6 @@
 | 
				
			|||||||
Package: com.opa334.trollstorehelper
 | 
					Package: com.opa334.trollstorehelper
 | 
				
			||||||
Name: TrollStore Helper
 | 
					Name: TrollStore Helper
 | 
				
			||||||
Version: 1.0
 | 
					Version: 1.0.2
 | 
				
			||||||
Architecture: iphoneos-arm
 | 
					Architecture: iphoneos-arm
 | 
				
			||||||
Description: Helper app to install and manage TrollStore!
 | 
					Description: Helper app to install and manage TrollStore!
 | 
				
			||||||
Maintainer: opa334
 | 
					Maintainer: opa334
 | 
				
			||||||
 | 
				
			|||||||
@ -50,7 +50,7 @@
 | 
				
			|||||||
		<string>iPhoneOS</string>
 | 
							<string>iPhoneOS</string>
 | 
				
			||||||
	</array>
 | 
						</array>
 | 
				
			||||||
	<key>CFBundleVersion</key>
 | 
						<key>CFBundleVersion</key>
 | 
				
			||||||
	<string>1.0.1</string>
 | 
						<string>1.0.2</string>
 | 
				
			||||||
	<key>LSRequiresIPhoneOS</key>
 | 
						<key>LSRequiresIPhoneOS</key>
 | 
				
			||||||
	<true/>
 | 
						<true/>
 | 
				
			||||||
	<key>UIDeviceFamily</key>
 | 
						<key>UIDeviceFamily</key>
 | 
				
			||||||
 | 
				
			|||||||
@ -14,6 +14,7 @@
 | 
				
			|||||||
- (NSString*)displayNameForAppPath:(NSString*)appPath;
 | 
					- (NSString*)displayNameForAppPath:(NSString*)appPath;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
- (NSError*)errorForCode:(int)code;
 | 
					- (NSError*)errorForCode:(int)code;
 | 
				
			||||||
 | 
					- (int)installIpa:(NSString*)pathToIpa force:(BOOL)force;
 | 
				
			||||||
- (int)installIpa:(NSString*)pathToIpa;
 | 
					- (int)installIpa:(NSString*)pathToIpa;
 | 
				
			||||||
- (int)uninstallApp:(NSString*)appId;
 | 
					- (int)uninstallApp:(NSString*)appId;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
				
			|||||||
@ -67,7 +67,7 @@
 | 
				
			|||||||
        errorDescription = @"Failed to create container for app bundle.";
 | 
					        errorDescription = @"Failed to create container for app bundle.";
 | 
				
			||||||
        break;
 | 
					        break;
 | 
				
			||||||
        case 171:
 | 
					        case 171:
 | 
				
			||||||
        errorDescription = @"A non-TrollStore app with the same identifier is already installed. If you are absolutely sure it is not, try refreshing icon cache in TrollStore settings or try rebooting your device.";
 | 
					        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;
 | 
					        break;
 | 
				
			||||||
        case 172:
 | 
					        case 172:
 | 
				
			||||||
        errorDescription = @"The app does not seem to contain an Info.plist";
 | 
					        errorDescription = @"The app does not seem to contain an Info.plist";
 | 
				
			||||||
@ -78,13 +78,26 @@
 | 
				
			|||||||
    return error;
 | 
					    return error;
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
- (int)installIpa:(NSString*)pathToIpa
 | 
					- (int)installIpa:(NSString*)pathToIpa force:(BOOL)force
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
    int ret = spawnRoot(helperPath(), @[@"install", pathToIpa]);
 | 
					    int ret;
 | 
				
			||||||
 | 
					    if(force)
 | 
				
			||||||
 | 
					    {
 | 
				
			||||||
 | 
					        ret = spawnRoot(helperPath(), @[@"install", pathToIpa, @"force"]);
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					    else
 | 
				
			||||||
 | 
					    {
 | 
				
			||||||
 | 
					        ret = spawnRoot(helperPath(), @[@"install", pathToIpa]);
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
    [[NSNotificationCenter defaultCenter] postNotificationName:@"ApplicationsChanged" object:nil];
 | 
					    [[NSNotificationCenter defaultCenter] postNotificationName:@"ApplicationsChanged" object:nil];
 | 
				
			||||||
    return ret;
 | 
					    return ret;
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					- (int)installIpa:(NSString*)pathToIpa
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
					    return [self installIpa:pathToIpa force:NO];
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
- (int)uninstallApp:(NSString*)appId
 | 
					- (int)uninstallApp:(NSString*)appId
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
    int ret = spawnRoot(helperPath(), @[@"uninstall", appId]);
 | 
					    int ret = spawnRoot(helperPath(), @[@"uninstall", appId]);
 | 
				
			||||||
 | 
				
			|||||||
@ -5,7 +5,7 @@
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
@implementation TSSceneDelegate
 | 
					@implementation TSSceneDelegate
 | 
				
			||||||
 | 
					
 | 
				
			||||||
- (void)handleURLContexts:(NSSet<UIOpenURLContext *> *)URLContexts scene:(UIWindowScene*)scene
 | 
					- (void)doIPAInstall:(NSString*)ipaPath scene:(UIWindowScene*)scene force:(BOOL)force completion:(void (^)(void))completion
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
    UIWindow* keyWindow = nil;
 | 
					    UIWindow* keyWindow = nil;
 | 
				
			||||||
    for(UIWindow* window in scene.windows)
 | 
					    for(UIWindow* window in scene.windows)
 | 
				
			||||||
@ -17,6 +17,60 @@
 | 
				
			|||||||
        }
 | 
					        }
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    UIAlertController* infoAlert = [UIAlertController alertControllerWithTitle:@"Installing" message:@"" preferredStyle:UIAlertControllerStyleAlert];
 | 
				
			||||||
 | 
					    UIActivityIndicatorView* activityIndicator = [[UIActivityIndicatorView alloc] initWithFrame:CGRectMake(5,5,50,50)];
 | 
				
			||||||
 | 
					    activityIndicator.hidesWhenStopped = YES;
 | 
				
			||||||
 | 
					    activityIndicator.activityIndicatorViewStyle = UIActivityIndicatorViewStyleMedium;
 | 
				
			||||||
 | 
					    [activityIndicator startAnimating];
 | 
				
			||||||
 | 
					    [infoAlert.view addSubview:activityIndicator];
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    [keyWindow.rootViewController presentViewController:infoAlert animated:YES completion:nil];
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^
 | 
				
			||||||
 | 
					    {
 | 
				
			||||||
 | 
					        // Install IPA
 | 
				
			||||||
 | 
					        int ret = [[TSApplicationsManager sharedInstance] installIpa:ipaPath force:force];
 | 
				
			||||||
 | 
					        NSError* error = [[TSApplicationsManager sharedInstance] errorForCode:ret];
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        NSLog(@"installed app! ret:%d, error: %@", ret, error);
 | 
				
			||||||
 | 
					        dispatch_async(dispatch_get_main_queue(), ^
 | 
				
			||||||
 | 
					        {
 | 
				
			||||||
 | 
					            [infoAlert dismissViewControllerAnimated:YES completion:^
 | 
				
			||||||
 | 
					            {
 | 
				
			||||||
 | 
					                if(ret != 0)
 | 
				
			||||||
 | 
					                {
 | 
				
			||||||
 | 
					                    UIAlertController* errorAlert = [UIAlertController alertControllerWithTitle:[NSString stringWithFormat:@"Install Error %d", ret] message:[error localizedDescription] preferredStyle:UIAlertControllerStyleAlert];
 | 
				
			||||||
 | 
					                    UIAlertAction* closeAction = [UIAlertAction actionWithTitle:@"Close" style:UIAlertActionStyleDefault handler:^(UIAlertAction* action)
 | 
				
			||||||
 | 
					                    {
 | 
				
			||||||
 | 
					                        if(ret == 171)
 | 
				
			||||||
 | 
					                        {
 | 
				
			||||||
 | 
					                            completion();
 | 
				
			||||||
 | 
					                        }
 | 
				
			||||||
 | 
					                    }];
 | 
				
			||||||
 | 
					                    if(ret == 171)
 | 
				
			||||||
 | 
					                    {
 | 
				
			||||||
 | 
					                        UIAlertAction* forceInstallAction = [UIAlertAction actionWithTitle:@"Force Installation" style:UIAlertActionStyleDefault handler:^(UIAlertAction* action)
 | 
				
			||||||
 | 
					                        {
 | 
				
			||||||
 | 
					                            [self doIPAInstall:ipaPath scene:scene force:YES completion:completion];
 | 
				
			||||||
 | 
					                        }];
 | 
				
			||||||
 | 
					                        [errorAlert addAction:forceInstallAction];
 | 
				
			||||||
 | 
					                    }
 | 
				
			||||||
 | 
					                    [errorAlert addAction:closeAction];
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					                    [keyWindow.rootViewController presentViewController:errorAlert animated:YES completion:nil];
 | 
				
			||||||
 | 
					                }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					                if(ret != 171)
 | 
				
			||||||
 | 
					                {
 | 
				
			||||||
 | 
					                    completion();
 | 
				
			||||||
 | 
					                }
 | 
				
			||||||
 | 
					            }];
 | 
				
			||||||
 | 
					        });
 | 
				
			||||||
 | 
					    });
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					- (void)handleURLContexts:(NSSet<UIOpenURLContext *> *)URLContexts scene:(UIWindowScene*)scene
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
    for(UIOpenURLContext* context in URLContexts)
 | 
					    for(UIOpenURLContext* context in URLContexts)
 | 
				
			||||||
    {
 | 
					    {
 | 
				
			||||||
        NSLog(@"openURLContexts %@", context.URL);
 | 
					        NSLog(@"openURLContexts %@", context.URL);
 | 
				
			||||||
@ -43,39 +97,9 @@
 | 
				
			|||||||
            
 | 
					            
 | 
				
			||||||
            if ([url.pathExtension isEqualToString:@"ipa"])
 | 
					            if ([url.pathExtension isEqualToString:@"ipa"])
 | 
				
			||||||
            {
 | 
					            {
 | 
				
			||||||
                UIAlertController* infoAlert = [UIAlertController alertControllerWithTitle:@"Installing" message:@"" preferredStyle:UIAlertControllerStyleAlert];
 | 
					                [self doIPAInstall:url.path scene:(UIWindowScene*)scene force:NO completion:^{
 | 
				
			||||||
                UIActivityIndicatorView* activityIndicator = [[UIActivityIndicatorView alloc] initWithFrame:CGRectMake(5,5,50,50)];
 | 
					                    doneBlock(NO);
 | 
				
			||||||
                activityIndicator.hidesWhenStopped = YES;
 | 
					                }];
 | 
				
			||||||
                activityIndicator.activityIndicatorViewStyle = UIActivityIndicatorViewStyleMedium;
 | 
					 | 
				
			||||||
                [activityIndicator startAnimating];
 | 
					 | 
				
			||||||
                [infoAlert.view addSubview:activityIndicator];
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
                [keyWindow.rootViewController presentViewController:infoAlert animated:YES completion:nil];
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
                dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^
 | 
					 | 
				
			||||||
                {
 | 
					 | 
				
			||||||
                    // Install IPA
 | 
					 | 
				
			||||||
                    int ret = [[TSApplicationsManager sharedInstance] installIpa:tmpCopyURL.path];
 | 
					 | 
				
			||||||
                    NSError* error = [[TSApplicationsManager sharedInstance] errorForCode:ret];
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
                    NSLog(@"installed app! ret:%d, error: %@", ret, error);
 | 
					 | 
				
			||||||
                    dispatch_async(dispatch_get_main_queue(), ^
 | 
					 | 
				
			||||||
                    {
 | 
					 | 
				
			||||||
                        [infoAlert dismissViewControllerAnimated:YES completion:^
 | 
					 | 
				
			||||||
                        {
 | 
					 | 
				
			||||||
                            if(ret != 0)
 | 
					 | 
				
			||||||
                            {
 | 
					 | 
				
			||||||
                                UIAlertController* errorAlert = [UIAlertController alertControllerWithTitle:[NSString stringWithFormat:@"Install Error %d", ret] message:[error localizedDescription] preferredStyle:UIAlertControllerStyleAlert];
 | 
					 | 
				
			||||||
                                UIAlertAction* closeAction = [UIAlertAction actionWithTitle:@"Close" style:UIAlertActionStyleDefault handler:nil];
 | 
					 | 
				
			||||||
                                [errorAlert addAction:closeAction];
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
                                [keyWindow.rootViewController presentViewController:errorAlert animated:YES completion:nil];
 | 
					 | 
				
			||||||
                            }
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
                            doneBlock(NO);
 | 
					 | 
				
			||||||
                        }];
 | 
					 | 
				
			||||||
                    });
 | 
					 | 
				
			||||||
                });
 | 
					 | 
				
			||||||
            }
 | 
					            }
 | 
				
			||||||
            else if([url.pathExtension isEqualToString:@"tar"])
 | 
					            else if([url.pathExtension isEqualToString:@"tar"])
 | 
				
			||||||
            {
 | 
					            {
 | 
				
			||||||
 | 
				
			|||||||
@ -1,6 +1,6 @@
 | 
				
			|||||||
Package: com.opa334.trollstore
 | 
					Package: com.opa334.trollstore
 | 
				
			||||||
Name: TrollStore
 | 
					Name: TrollStore
 | 
				
			||||||
Version: 1.0.1
 | 
					Version: 1.0.2
 | 
				
			||||||
Architecture: iphoneos-arm
 | 
					Architecture: iphoneos-arm
 | 
				
			||||||
Description: An awesome application!
 | 
					Description: An awesome application!
 | 
				
			||||||
Maintainer: opa334
 | 
					Maintainer: opa334
 | 
				
			||||||
 | 
				
			|||||||
		Loading…
	
		Reference in New Issue
	
	Block a user