mirror of https://github.com/opa334/TrollStore.git
Readd ldid for use on iOS 14
This commit is contained in:
parent
b79c9c1ad5
commit
c6ea42cf5a
|
@ -1,6 +1,7 @@
|
||||||
#include <Foundation/Foundation.h>
|
#include <Foundation/Foundation.h>
|
||||||
#include <Security/Security.h>
|
#include <Security/Security.h>
|
||||||
#include <TargetConditionals.h>
|
#include <TargetConditionals.h>
|
||||||
|
#include <dlfcn.h>
|
||||||
|
|
||||||
#ifdef __cplusplus
|
#ifdef __cplusplus
|
||||||
extern "C" {
|
extern "C" {
|
||||||
|
@ -64,12 +65,27 @@ typedef struct CF_BRIDGED_TYPE(id) __SecCodeSigner* SecCodeSignerRef SPI_AVAILAB
|
||||||
typedef struct __SecCodeSigner* SecCodeSignerRef SPI_AVAILABLE(macos(10.5), ios(15.0), macCatalyst(13.0));
|
typedef struct __SecCodeSigner* SecCodeSignerRef SPI_AVAILABLE(macos(10.5), ios(15.0), macCatalyst(13.0));
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
extern const CFStringRef kSecCodeSignerEntitlements SPI_AVAILABLE(macos(10.5), ios(15.0), macCatalyst(13.0));
|
const CFStringRef kSecCodeSignerApplicationData = CFSTR("application-specific");
|
||||||
extern const CFStringRef kSecCodeSignerIdentifier SPI_AVAILABLE(macos(10.5), ios(15.0), macCatalyst(13.0));
|
const CFStringRef kSecCodeSignerDetached = CFSTR("detached");
|
||||||
extern const CFStringRef kSecCodeSignerIdentity SPI_AVAILABLE(macos(10.5), ios(15.0), macCatalyst(13.0));
|
const CFStringRef kSecCodeSignerDigestAlgorithm = CFSTR("digest-algorithm");
|
||||||
extern const CFStringRef kSecCodeSignerPreserveMetadata SPI_AVAILABLE(macos(10.5), ios(15.0), macCatalyst(13.0));
|
const CFStringRef kSecCodeSignerDryRun = CFSTR("dryrun");
|
||||||
extern const CFStringRef kSecCodeSignerRequirements SPI_AVAILABLE(macos(10.5), ios(15.0), macCatalyst(13.0));
|
const CFStringRef kSecCodeSignerEntitlements = CFSTR("entitlements");
|
||||||
extern const CFStringRef kSecCodeSignerResourceRules SPI_AVAILABLE(macos(10.5), ios(15.0), macCatalyst(13.0));
|
const CFStringRef kSecCodeSignerFlags = CFSTR("flags");
|
||||||
|
const CFStringRef kSecCodeSignerIdentifier = CFSTR("identifier");
|
||||||
|
const CFStringRef kSecCodeSignerIdentifierPrefix = CFSTR("identifier-prefix");
|
||||||
|
const CFStringRef kSecCodeSignerIdentity = CFSTR("signer");
|
||||||
|
const CFStringRef kSecCodeSignerPageSize = CFSTR("pagesize");
|
||||||
|
const CFStringRef kSecCodeSignerRequirements = CFSTR("requirements");
|
||||||
|
const CFStringRef kSecCodeSignerResourceRules = CFSTR("resource-rules");
|
||||||
|
const CFStringRef kSecCodeSignerSDKRoot = CFSTR("sdkroot");
|
||||||
|
const CFStringRef kSecCodeSignerSigningTime = CFSTR("signing-time");
|
||||||
|
const CFStringRef kSecCodeSignerRequireTimestamp = CFSTR("timestamp-required");
|
||||||
|
const CFStringRef kSecCodeSignerTimestampServer = CFSTR("timestamp-url");
|
||||||
|
const CFStringRef kSecCodeSignerTimestampAuthentication = CFSTR("timestamp-authentication");
|
||||||
|
const CFStringRef kSecCodeSignerTimestampOmitCertificates = CFSTR("timestamp-omit-certificates");
|
||||||
|
const CFStringRef kSecCodeSignerPreserveMetadata = CFSTR("preserve-metadata");
|
||||||
|
const CFStringRef kSecCodeSignerTeamIdentifier = CFSTR("teamidentifier");
|
||||||
|
const CFStringRef kSecCodeSignerPlatformIdentifier = CFSTR("platform-identifier");
|
||||||
|
|
||||||
#ifdef BRIDGED_SECCODESIGNER
|
#ifdef BRIDGED_SECCODESIGNER
|
||||||
OSStatus SecCodeSignerCreate(CFDictionaryRef parameters, SecCSFlags flags, SecCodeSignerRef* __nonnull CF_RETURNS_RETAINED signer)
|
OSStatus SecCodeSignerCreate(CFDictionaryRef parameters, SecCSFlags flags, SecCodeSignerRef* __nonnull CF_RETURNS_RETAINED signer)
|
||||||
|
@ -91,6 +107,13 @@ extern const CFStringRef kSecCodeInfoResourceDirectory; /* Internal */
|
||||||
|
|
||||||
int codesign_sign_adhoc(const char *path, bool preserveMetadata, NSDictionary *customEntitlements)
|
int codesign_sign_adhoc(const char *path, bool preserveMetadata, NSDictionary *customEntitlements)
|
||||||
{
|
{
|
||||||
|
// We need to do this shit because iOS 14 does not have the symbol
|
||||||
|
OSStatus (*__SecCodeSignerCreate)(CFDictionaryRef parameters, SecCSFlags flags, SecCodeSignerRef *signerRef) = dlsym(RTLD_DEFAULT, "SecCodeSignerCreate");
|
||||||
|
OSStatus (*__SecCodeSignerAddSignatureWithErrors)(SecCodeSignerRef signerRef, SecStaticCodeRef codeRef, SecCSFlags flags, CFErrorRef *errors) = dlsym(RTLD_DEFAULT, "SecCodeSignerAddSignatureWithErrors");
|
||||||
|
// if this is not found, all bets are off
|
||||||
|
if (!__SecCodeSignerCreate) return 404;
|
||||||
|
if (!__SecCodeSignerAddSignatureWithErrors) return 404;
|
||||||
|
|
||||||
NSString *filePath = [NSString stringWithUTF8String:path];
|
NSString *filePath = [NSString stringWithUTF8String:path];
|
||||||
OSStatus status = 0;
|
OSStatus status = 0;
|
||||||
int retval = 200;
|
int retval = 200;
|
||||||
|
@ -127,13 +150,13 @@ int codesign_sign_adhoc(const char *path, bool preserveMetadata, NSDictionary *c
|
||||||
}
|
}
|
||||||
|
|
||||||
SecCodeSignerRef signerRef;
|
SecCodeSignerRef signerRef;
|
||||||
status = SecCodeSignerCreate((__bridge CFDictionaryRef)parameters, kSecCSDefaultFlags, &signerRef);
|
status = __SecCodeSignerCreate((__bridge CFDictionaryRef)parameters, kSecCSDefaultFlags, &signerRef);
|
||||||
if (status == 0) {
|
if (status == 0) {
|
||||||
SecStaticCodeRef code;
|
SecStaticCodeRef code;
|
||||||
status = SecStaticCodeCreateWithPathAndAttributes((__bridge CFURLRef)[NSURL fileURLWithPath:filePath], kSecCSDefaultFlags, (__bridge CFDictionaryRef)@{}, &code);
|
status = SecStaticCodeCreateWithPathAndAttributes((__bridge CFURLRef)[NSURL fileURLWithPath:filePath], kSecCSDefaultFlags, (__bridge CFDictionaryRef)@{}, &code);
|
||||||
if (status == 0) {
|
if (status == 0) {
|
||||||
CFErrorRef errors;
|
CFErrorRef errors;
|
||||||
status = SecCodeSignerAddSignatureWithErrors(signerRef, code, kSecCSDefaultFlags, &errors);
|
status = __SecCodeSignerAddSignatureWithErrors(signerRef, code, kSecCSDefaultFlags, &errors);
|
||||||
if (status == 0) {
|
if (status == 0) {
|
||||||
CFDictionaryRef newSigningInformation;
|
CFDictionaryRef newSigningInformation;
|
||||||
// Difference from codesign: added kSecCSSigningInformation, kSecCSRequirementInformation, kSecCSInternalInformation
|
// Difference from codesign: added kSecCSSigningInformation, kSecCSRequirementInformation, kSecCSInternalInformation
|
||||||
|
|
|
@ -240,6 +240,105 @@ void setTSURLSchemeState(BOOL newState, NSString* customAppPath)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void installLdid(NSString* ldidToCopyPath, NSString* ldidVersion)
|
||||||
|
{
|
||||||
|
if(![[NSFileManager defaultManager] fileExistsAtPath:ldidToCopyPath]) return;
|
||||||
|
|
||||||
|
NSString* ldidPath = [trollStoreAppPath() stringByAppendingPathComponent:@"ldid"];
|
||||||
|
NSString* ldidVersionPath = [trollStoreAppPath() stringByAppendingPathComponent:@"ldid.version"];
|
||||||
|
|
||||||
|
if([[NSFileManager defaultManager] fileExistsAtPath:ldidPath])
|
||||||
|
{
|
||||||
|
[[NSFileManager defaultManager] removeItemAtPath: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(ldidVersionPath.fileSystemRepresentation, 0644);
|
||||||
|
}
|
||||||
|
|
||||||
|
BOOL isLdidInstalled(void)
|
||||||
|
{
|
||||||
|
NSString* ldidPath = [trollStoreAppPath() stringByAppendingPathComponent:@"ldid"];
|
||||||
|
return [[NSFileManager defaultManager] fileExistsAtPath:ldidPath];
|
||||||
|
}
|
||||||
|
|
||||||
|
int runLdid(NSArray* args, NSString** output, NSString** errorOutput)
|
||||||
|
{
|
||||||
|
NSString* ldidPath = [trollStoreAppPath() stringByAppendingPathComponent:@"ldid"];
|
||||||
|
NSMutableArray* argsM = args.mutableCopy ?: [NSMutableArray new];
|
||||||
|
[argsM insertObject:ldidPath.lastPathComponent atIndex:0];
|
||||||
|
|
||||||
|
NSUInteger argCount = [argsM count];
|
||||||
|
char **argsC = (char **)malloc((argCount + 1) * sizeof(char*));
|
||||||
|
|
||||||
|
for (NSUInteger i = 0; i < argCount; i++)
|
||||||
|
{
|
||||||
|
argsC[i] = strdup([[argsM objectAtIndex:i] UTF8String]);
|
||||||
|
}
|
||||||
|
argsC[argCount] = NULL;
|
||||||
|
|
||||||
|
posix_spawn_file_actions_t action;
|
||||||
|
posix_spawn_file_actions_init(&action);
|
||||||
|
|
||||||
|
int outErr[2];
|
||||||
|
pipe(outErr);
|
||||||
|
posix_spawn_file_actions_adddup2(&action, outErr[1], STDERR_FILENO);
|
||||||
|
posix_spawn_file_actions_addclose(&action, outErr[0]);
|
||||||
|
|
||||||
|
int out[2];
|
||||||
|
pipe(out);
|
||||||
|
posix_spawn_file_actions_adddup2(&action, out[1], STDOUT_FILENO);
|
||||||
|
posix_spawn_file_actions_addclose(&action, out[0]);
|
||||||
|
|
||||||
|
pid_t task_pid;
|
||||||
|
int status = -200;
|
||||||
|
int spawnError = posix_spawn(&task_pid, [ldidPath fileSystemRepresentation], &action, NULL, (char* const*)argsC, NULL);
|
||||||
|
for (NSUInteger i = 0; i < argCount; i++)
|
||||||
|
{
|
||||||
|
free(argsC[i]);
|
||||||
|
}
|
||||||
|
free(argsC);
|
||||||
|
|
||||||
|
if(spawnError != 0)
|
||||||
|
{
|
||||||
|
NSLog(@"posix_spawn error %d\n", spawnError);
|
||||||
|
return spawnError;
|
||||||
|
}
|
||||||
|
|
||||||
|
do
|
||||||
|
{
|
||||||
|
if (waitpid(task_pid, &status, 0) != -1) {
|
||||||
|
//printf("Child status %dn", WEXITSTATUS(status));
|
||||||
|
} else
|
||||||
|
{
|
||||||
|
perror("waitpid");
|
||||||
|
return -222;
|
||||||
|
}
|
||||||
|
} while (!WIFEXITED(status) && !WIFSIGNALED(status));
|
||||||
|
|
||||||
|
close(outErr[1]);
|
||||||
|
close(out[1]);
|
||||||
|
|
||||||
|
NSString* ldidOutput = getNSStringFromFile(out[0]);
|
||||||
|
if(output)
|
||||||
|
{
|
||||||
|
*output = ldidOutput;
|
||||||
|
}
|
||||||
|
|
||||||
|
NSString* ldidErrorOutput = getNSStringFromFile(outErr[0]);
|
||||||
|
if(errorOutput)
|
||||||
|
{
|
||||||
|
*errorOutput = ldidErrorOutput;
|
||||||
|
}
|
||||||
|
|
||||||
|
return WEXITSTATUS(status);
|
||||||
|
}
|
||||||
|
|
||||||
BOOL certificateHasDataForExtensionOID(SecCertificateRef certificate, CFStringRef oidString)
|
BOOL certificateHasDataForExtensionOID(SecCertificateRef certificate, CFStringRef oidString)
|
||||||
{
|
{
|
||||||
if(certificate == NULL || oidString == NULL)
|
if(certificate == NULL || oidString == NULL)
|
||||||
|
@ -377,6 +476,52 @@ int signApp(NSString* appPath)
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
#else
|
#else
|
||||||
|
int signAdhoc(NSString *filePath, NSDictionary *entitlements)
|
||||||
|
{
|
||||||
|
if (@available(iOS 15, *)) {
|
||||||
|
return codesign_sign_adhoc(filePath.fileSystemRepresentation, true, entitlements);
|
||||||
|
}
|
||||||
|
// If iOS 14 is so great, how come there is no iOS 14 2?????
|
||||||
|
else {
|
||||||
|
if(!isLdidInstalled()) return 173;
|
||||||
|
|
||||||
|
NSString *entitlementsPath = nil;
|
||||||
|
NSString *signArg = @"-s";
|
||||||
|
NSString* errorOutput;
|
||||||
|
if(entitlements)
|
||||||
|
{
|
||||||
|
NSData *entitlementsXML = [NSPropertyListSerialization dataWithPropertyList:entitlements format:NSPropertyListXMLFormat_v1_0 options:0 error:nil];
|
||||||
|
if (entitlementsXML) {
|
||||||
|
entitlementsPath = [[NSTemporaryDirectory() stringByAppendingPathComponent:[NSUUID UUID].UUIDString] stringByAppendingPathExtension:@"plist"];
|
||||||
|
[entitlementsXML writeToFile:entitlementsPath atomically:NO];
|
||||||
|
signArg = [@"-S" stringByAppendingString:entitlementsPath];
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
int ldidRet = runLdid(@[signArg, filePath], nil, &errorOutput);
|
||||||
|
if (entitlementsPath) {
|
||||||
|
[[NSFileManager defaultManager] removeItemAtPath:entitlementsPath error:nil];
|
||||||
|
}
|
||||||
|
|
||||||
|
NSLog(@"ldid exited with status %d", ldidRet);
|
||||||
|
|
||||||
|
NSLog(@"- ldid error output start -");
|
||||||
|
|
||||||
|
printMultilineNSString(errorOutput);
|
||||||
|
|
||||||
|
NSLog(@"- ldid error output end -");
|
||||||
|
|
||||||
|
if(ldidRet == 0)
|
||||||
|
{
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
return 175;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
int signApp(NSString* appPath)
|
int signApp(NSString* appPath)
|
||||||
{
|
{
|
||||||
NSDictionary* appInfoDict = infoDictionaryForAppPath(appPath);
|
NSDictionary* appInfoDict = infoDictionaryForAppPath(appPath);
|
||||||
|
@ -460,7 +605,7 @@ int signApp(NSString* appPath)
|
||||||
}
|
}
|
||||||
|
|
||||||
// First attempt ad hoc signing
|
// First attempt ad hoc signing
|
||||||
int r = codesign_sign_adhoc(tmpPath.fileSystemRepresentation, true, entitlementsToUse);
|
int r = signAdhoc(tmpPath, entitlementsToUse);
|
||||||
if (r != 0) {
|
if (r != 0) {
|
||||||
NSLog(@"[%@] Adhoc signing failed with error code %d, continuing anyways...\n", filePath, r);
|
NSLog(@"[%@] Adhoc signing failed with error code %d, continuing anyways...\n", filePath, r);
|
||||||
}
|
}
|
||||||
|
@ -545,6 +690,7 @@ void applyPatchesToInfoDictionary(NSString* appPath)
|
||||||
// 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
|
||||||
|
// 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, BOOL useInstalldMethod)
|
int installApp(NSString* appPackagePath, BOOL sign, BOOL force, BOOL isTSUpdate, BOOL useInstalldMethod)
|
||||||
{
|
{
|
||||||
|
@ -892,6 +1038,41 @@ 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;
|
||||||
|
|
||||||
|
if (@available(iOS 15, *)) {} else {
|
||||||
|
// Transfer existing ldid installation if it exists
|
||||||
|
// But only if the to-be-installed version of TrollStore is 1.5.0 or above
|
||||||
|
// 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* existingLdidPath = [trollStoreAppPath() stringByAppendingPathComponent:@"ldid"];
|
||||||
|
NSString* existingLdidVersionPath = [trollStoreAppPath() stringByAppendingPathComponent:@"ldid.version"];
|
||||||
|
if([[NSFileManager defaultManager] fileExistsAtPath:existingLdidPath])
|
||||||
|
{
|
||||||
|
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];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// Merge existing URL scheme settings value
|
// Merge existing URL scheme settings value
|
||||||
if(!getTSURLSchemeState(nil))
|
if(!getTSURLSchemeState(nil))
|
||||||
{
|
{
|
||||||
|
@ -1171,6 +1352,15 @@ int MAIN_NAME(int argc, char *argv[], char *envp[])
|
||||||
}
|
}
|
||||||
uninstallTrollStore(YES);
|
uninstallTrollStore(YES);
|
||||||
}
|
}
|
||||||
|
else if([cmd isEqualToString:@"install-ldid"])
|
||||||
|
{
|
||||||
|
if (@available(iOS 15, *)) {} else {
|
||||||
|
if(args.count < 3) return -3;
|
||||||
|
NSString* ldidPath = args[1];
|
||||||
|
NSString* ldidVersion = args[2];
|
||||||
|
installLdid(ldidPath, ldidVersion);
|
||||||
|
}
|
||||||
|
}
|
||||||
else if([cmd isEqualToString:@"refresh"])
|
else if([cmd isEqualToString:@"refresh"])
|
||||||
{
|
{
|
||||||
refreshAppRegistrations(YES);
|
refreshAppRegistrations(YES);
|
||||||
|
|
|
@ -12,6 +12,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();
|
||||||
|
|
|
@ -310,6 +310,11 @@ void fetchLatestTrollStoreVersion(void (^completionHandler)(NSString* latestVers
|
||||||
github_fetchLatestVersion(@"opa334/TrollStore", completionHandler);
|
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];
|
||||||
|
|
|
@ -191,6 +191,7 @@
|
||||||
<key>TSRootBinaries</key>
|
<key>TSRootBinaries</key>
|
||||||
<array>
|
<array>
|
||||||
<string>trollstorehelper</string>
|
<string>trollstorehelper</string>
|
||||||
|
<string>ldid</string>
|
||||||
</array>
|
</array>
|
||||||
</dict>
|
</dict>
|
||||||
</plist>
|
</plist>
|
||||||
|
|
|
@ -47,11 +47,20 @@ extern NSUserDefaults* trollStoreUserDefaults();
|
||||||
case 172:
|
case 172:
|
||||||
errorDescription = @"The app does not contain an Info.plist file.";
|
errorDescription = @"The app does not contain an Info.plist file.";
|
||||||
break;
|
break;
|
||||||
|
case 173:
|
||||||
|
errorDescription = @"The app is not signed with a fake CoreTrust certificate and ldid is not installed. Install ldid in the settings tab and try again.";
|
||||||
|
break;
|
||||||
case 174:
|
case 174:
|
||||||
errorDescription = @"The app's main executable does not exist.";
|
errorDescription = @"The app's main executable does not exist.";
|
||||||
break;
|
break;
|
||||||
case 175:
|
case 175: {
|
||||||
|
if (@available(iOS 15, *)) {
|
||||||
errorDescription = @"Failed to sign the app.";
|
errorDescription = @"Failed to sign the app.";
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
errorDescription = @"Failed to sign the app. ldid returned a non zero status code.";
|
||||||
|
}
|
||||||
|
}
|
||||||
break;
|
break;
|
||||||
case 176:
|
case 176:
|
||||||
errorDescription = @"The app's Info.plist is missing required values.";
|
errorDescription = @"The app's Info.plist is missing required values.";
|
||||||
|
|
|
@ -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,48 @@ extern NSUserDefaults* trollStoreUserDefaults(void);
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
+ (void)installLdid
|
||||||
|
{
|
||||||
|
fetchLatestLdidVersion(^(NSString* latestVersion)
|
||||||
|
{
|
||||||
|
if(!latestVersion) return;
|
||||||
|
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 if(location)
|
||||||
|
{
|
||||||
|
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,23 @@
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// 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
|
||||||
|
{
|
||||||
|
if (@available(iOS 15, *)) {} else {
|
||||||
|
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`.
|
||||||
// If using a storyboard, the `window` property will automatically be initialized and attached to the scene.
|
// If using a storyboard, the `window` property will automatically be initialized and attached to the scene.
|
||||||
|
@ -87,6 +104,10 @@
|
||||||
{
|
{
|
||||||
[self handleURLContexts:connectionOptions.URLContexts scene:(UIWindowScene*)scene];
|
[self handleURLContexts:connectionOptions.URLContexts scene:(UIWindowScene*)scene];
|
||||||
}
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
[self handleLdidCheck];
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -4,5 +4,6 @@
|
||||||
{
|
{
|
||||||
PSSpecifier* _installPersistenceHelperSpecifier;
|
PSSpecifier* _installPersistenceHelperSpecifier;
|
||||||
NSString* _newerVersion;
|
NSString* _newerVersion;
|
||||||
|
NSString* _newerLdidVersion;
|
||||||
}
|
}
|
||||||
@end
|
@end
|
|
@ -33,6 +33,28 @@ extern NSUserDefaults* trollStoreUserDefaults(void);
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
|
if (@available(iOS 15, *)) {} else {
|
||||||
|
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
|
||||||
|
@ -91,6 +113,84 @@ extern NSUserDefaults* trollStoreUserDefaults(void);
|
||||||
|
|
||||||
[_specifiers addObject:rebuildIconCacheSpecifier];
|
[_specifiers addObject:rebuildIconCacheSpecifier];
|
||||||
|
|
||||||
|
if (@available(iOS 15, *)) { }
|
||||||
|
else {
|
||||||
|
NSString* ldidPath = [NSBundle.mainBundle.bundlePath stringByAppendingPathComponent:@"ldid"];
|
||||||
|
NSString* ldidVersionPath = [NSBundle.mainBundle.bundlePath stringByAppendingPathComponent:@"ldid.version"];
|
||||||
|
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];
|
||||||
|
signingGroupSpecifier.name = @"Signing";
|
||||||
|
|
||||||
|
if(ldidInstalled)
|
||||||
|
{
|
||||||
|
[signingGroupSpecifier setProperty:@"ldid is installed and allows TrollStore to install unsigned IPA files." forKey:@"footerText"];
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
[signingGroupSpecifier setProperty:@"In order for TrollStore to be able to install unsigned IPAs, ldid has to be installed using this button. It can't be directly included in TrollStore because of licensing issues." forKey:@"footerText"];
|
||||||
|
}
|
||||||
|
|
||||||
|
[_specifiers addObject:signingGroupSpecifier];
|
||||||
|
|
||||||
|
if(ldidInstalled)
|
||||||
|
{
|
||||||
|
NSString* installedTitle = @"ldid: Installed";
|
||||||
|
if(ldidVersion)
|
||||||
|
{
|
||||||
|
installedTitle = [NSString stringWithFormat:@"%@ (%@)", installedTitle, ldidVersion];
|
||||||
|
}
|
||||||
|
|
||||||
|
PSSpecifier* ldidInstalledSpecifier = [PSSpecifier preferenceSpecifierNamed:installedTitle
|
||||||
|
target:self
|
||||||
|
set:nil
|
||||||
|
get:nil
|
||||||
|
detail:nil
|
||||||
|
cell:PSStaticTextCell
|
||||||
|
edit:nil];
|
||||||
|
[ldidInstalledSpecifier setProperty:@NO forKey:@"enabled"];
|
||||||
|
ldidInstalledSpecifier.identifier = @"ldidInstalled";
|
||||||
|
[_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
|
||||||
|
{
|
||||||
|
PSSpecifier* installLdidSpecifier = [PSSpecifier preferenceSpecifierNamed:@"Install ldid"
|
||||||
|
target:self
|
||||||
|
set:nil
|
||||||
|
get:nil
|
||||||
|
detail:nil
|
||||||
|
cell:PSButtonCell
|
||||||
|
edit:nil];
|
||||||
|
installLdidSpecifier.identifier = @"installLdid";
|
||||||
|
[installLdidSpecifier setProperty:@YES forKey:@"enabled"];
|
||||||
|
installLdidSpecifier.buttonAction = @selector(installOrUpdateLdidPressed);
|
||||||
|
[_specifiers addObject:installLdidSpecifier];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
PSSpecifier* persistenceGroupSpecifier = [PSSpecifier emptyGroupSpecifier];
|
PSSpecifier* persistenceGroupSpecifier = [PSSpecifier emptyGroupSpecifier];
|
||||||
persistenceGroupSpecifier.name = @"Persistence";
|
persistenceGroupSpecifier.name = @"Persistence";
|
||||||
[_specifiers addObject:persistenceGroupSpecifier];
|
[_specifiers addObject:persistenceGroupSpecifier];
|
||||||
|
@ -265,6 +365,11 @@ extern NSUserDefaults* trollStoreUserDefaults(void);
|
||||||
respring();
|
respring();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
- (void)installOrUpdateLdidPressed
|
||||||
|
{
|
||||||
|
[TSInstallationController installLdid];
|
||||||
|
}
|
||||||
|
|
||||||
- (void)installPersistenceHelperPressed
|
- (void)installPersistenceHelperPressed
|
||||||
{
|
{
|
||||||
NSMutableArray* appCandidates = [NSMutableArray new];
|
NSMutableArray* appCandidates = [NSMutableArray new];
|
||||||
|
|
|
@ -14,7 +14,9 @@
|
||||||
|
|
||||||
4. Wait a few seconds, your device should respring and TrollStore will be installed.
|
4. Wait a few seconds, your device should respring and TrollStore will be installed.
|
||||||
|
|
||||||
5. Done, you can now share IPA files with TrollStore and they will be permanently installed on your device.
|
5. Open the TrollStore app and press "Install ldid" in the Settings tab, then read the information under "Persistence", the TrollHelper app on the home screen will be your persistence helper.
|
||||||
|
|
||||||
|
6. Done, you can now share IPA files with TrollStore and they will be permanently installed on your device.
|
||||||
|
|
||||||
## Unjailbreaking while retaining TrollStore
|
## Unjailbreaking while retaining TrollStore
|
||||||
|
|
||||||
|
|
|
@ -20,6 +20,6 @@
|
||||||
|
|
||||||
7. You can now either delete the "GTA Car Tracker" app, or register it as the persistence helper by opening it and tapping the option at the bottom. If you do this, don't delete the app.
|
7. You can now either delete the "GTA Car Tracker" app, or register it as the persistence helper by opening it and tapping the option at the bottom. If you do this, don't delete the app.
|
||||||
|
|
||||||
8. Open the TrollStore app and read the information under "Persistence", and install the Persistence Helper into a system app if you want persistence (not needed if you registered the GTA Car Tracker app as the persistence helper in step 7).
|
8. Open the TrollStore app and press "Install ldid" in the Settings tab, then read the information under "Persistence", and install the Persistence Helper into a system app if you want persistence (not needed if you registered the GTA Car Tracker app as the persistence helper in step 7).
|
||||||
|
|
||||||
9. Done, you can now share IPA files with TrollStore and they will be permanently installed on your device.
|
9. Done, you can now share IPA files with TrollStore and they will be permanently installed on your device.
|
||||||
|
|
|
@ -20,6 +20,6 @@
|
||||||
|
|
||||||
7. You can now either delete the "GTA Car Tracker" app, or register it as the persistence helper by opening it and tapping the option at the bottom. If you do this, don't delete the app.
|
7. You can now either delete the "GTA Car Tracker" app, or register it as the persistence helper by opening it and tapping the option at the bottom. If you do this, don't delete the app.
|
||||||
|
|
||||||
8. Open the TrollStore app and read the information under "Persistence", and install the Persistence Helper into a system app if you want persistence (not needed if you registered the GTA Car Tracker app as the persistence helper in step 7).
|
8. Open the TrollStore app and press "Install ldid" in the Settings tab, then read the information under "Persistence", and install the Persistence Helper into a system app if you want persistence (not needed if you registered the GTA Car Tracker app as the persistence helper in step 7).
|
||||||
|
|
||||||
9. Done, you can now share IPA files with TrollStore and they will be permanently installed on your device.
|
9. Done, you can now share IPA files with TrollStore and they will be permanently installed on your device.
|
||||||
|
|
Loading…
Reference in New Issue