This commit is contained in:
opa334
2023-01-21 13:52:39 +01:00
parent d244304313
commit 3aafa51503
15 changed files with 616 additions and 235 deletions
+50 -5
View File
@@ -1,5 +1,6 @@
#import "TSApplicationsManager.h"
#import <TSUtil.h>
extern NSUserDefaults* trollStoreUserDefaults();
@implementation TSApplicationsManager
@@ -75,15 +76,25 @@
- (int)installIpa:(NSString*)pathToIpa force:(BOOL)force log:(NSString**)logOut
{
int ret;
NSMutableArray* args = [NSMutableArray new];
[args addObject:@"install"];
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
{
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];
return ret;
}
@@ -96,7 +107,24 @@
- (int)uninstallApp:(NSString*)appId
{
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];
return ret;
}
@@ -104,7 +132,24 @@
- (int)uninstallAppByPath:(NSString*)path
{
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];
return ret;
}
+2
View File
@@ -9,4 +9,6 @@
+ (void)handleAppInstallFromRemoteURL:(NSURL*)remoteURL completion:(void (^)(BOOL, NSError*))completion;
+ (void)installLdid;
@end
+43
View File
@@ -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
+18
View File
@@ -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 {
// 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];
}
else
{
[self handleLdidCheck];
}
}
@@ -0,0 +1,5 @@
#import <Preferences/PSListController.h>
@interface TSSettingsAdvancedListController : PSListController
@end
@@ -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
+1
View File
@@ -4,5 +4,6 @@
{
PSSpecifier* _installPersistenceHelperSpecifier;
NSString* _newerVersion;
NSString* _newerLdidVersion;
}
@end
+85 -40
View File
@@ -3,6 +3,8 @@
#import <Preferences/PSSpecifier.h>
#import <Preferences/PSListItemsController.h>
#import <TSPresentationDelegate.h>
#import "TSInstallationController.h"
#import "TSSettingsAdvancedListController.h"
@interface NSUserDefaults (Private)
- (instancetype)_initWithSuiteName:(NSString *)suiteName container:(NSURL *)container;
@@ -15,6 +17,7 @@ extern NSUserDefaults* trollStoreUserDefaults(void);
{
[super viewDidLoad];
[[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)
{
@@ -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
@@ -88,8 +111,16 @@ extern NSUserDefaults* trollStoreUserDefaults(void);
[_specifiers addObject:rebuildIconCacheSpecifier];
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";
@@ -106,7 +137,13 @@ extern NSUserDefaults* trollStoreUserDefaults(void);
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
set:nil
get:nil
@@ -116,6 +153,22 @@ extern NSUserDefaults* trollStoreUserDefaults(void);
[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
{
@@ -126,9 +179,9 @@ extern NSUserDefaults* trollStoreUserDefaults(void);
detail:nil
cell:PSButtonCell
edit:nil];
installLdidSpecifier.identifier = @"ldidInstalled";
installLdidSpecifier.identifier = @"installLdid";
[installLdidSpecifier setProperty:@YES forKey:@"enabled"];
installLdidSpecifier.buttonAction = @selector(installLdidPressed);
installLdidSpecifier.buttonAction = @selector(installOrUpdateLdidPressed);
[_specifiers addObject:installLdidSpecifier];
}
@@ -234,11 +287,21 @@ extern NSUserDefaults* trollStoreUserDefaults(void);
[_specifiers addObject:installAlertConfigurationSpecifier];
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];
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
PSSpecifier* uninstallTrollStoreSpecifier = [PSSpecifier preferenceSpecifierNamed:@"Uninstall TrollStore"
target:self
@@ -277,7 +340,7 @@ extern NSUserDefaults* trollStoreUserDefaults(void);
- (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
@@ -285,41 +348,9 @@ extern NSUserDefaults* trollStoreUserDefaults(void);
respring();
}
- (void)installLdidPressed
- (void)installOrUpdateLdidPressed
{
NSURL* ldidURL = [NSURL URLWithString:@"https://github.com/opa334/ldid/releases/download/v2.1.5-procursus5/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], nil, nil);
dispatch_async(dispatch_get_main_queue(), ^
{
[TSPresentationDelegate stopActivityWithCompletion:nil];
[self reloadSpecifiers];
});
}
}];
[downloadTask resume];
[TSInstallationController installLdid];
}
- (void)installPersistenceHelperPressed
@@ -410,4 +441,18 @@ extern NSUserDefaults* trollStoreUserDefaults(void);
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