mirror of
https://github.com/opa334/TrollStore.git
synced 2026-07-02 03:00:39 +08:00
TrollStore 1.2, new build setup, deprecate installers in favor of TrollHelperOTA, add jailbreak guide, add better version compatibility notes
This commit is contained in:
@@ -0,0 +1,58 @@
|
||||
@interface LSBundleProxy
|
||||
@property (nonatomic,readonly) NSString * bundleIdentifier;
|
||||
@property (nonatomic) NSURL* dataContainerURL;
|
||||
-(NSString*)localizedName;
|
||||
@end
|
||||
|
||||
@interface LSApplicationProxy : LSBundleProxy
|
||||
+ (instancetype)applicationProxyForIdentifier:(NSString*)identifier;
|
||||
@property NSURL* bundleURL;
|
||||
@property NSString* bundleType;
|
||||
@property NSString* canonicalExecutablePath;
|
||||
@property (nonatomic,readonly) NSDictionary* groupContainerURLs;
|
||||
@property (nonatomic,readonly) NSArray* plugInKitPlugins;
|
||||
@property (getter=isInstalled,nonatomic,readonly) BOOL installed;
|
||||
@property (getter=isPlaceholder,nonatomic,readonly) BOOL placeholder;
|
||||
@property (getter=isRestricted,nonatomic,readonly) BOOL restricted;
|
||||
@property (nonatomic,readonly) NSSet * claimedURLSchemes;
|
||||
@end
|
||||
|
||||
@interface LSApplicationWorkspace : NSObject
|
||||
+ (instancetype)defaultWorkspace;
|
||||
- (BOOL)registerApplicationDictionary:(NSDictionary*)dict;
|
||||
- (BOOL)unregisterApplication:(id)arg1;
|
||||
- (BOOL)_LSPrivateRebuildApplicationDatabasesForSystemApps:(BOOL)arg1 internal:(BOOL)arg2 user:(BOOL)arg3;
|
||||
- (BOOL)uninstallApplication:(NSString*)arg1 withOptions:(id)arg2;
|
||||
- (BOOL)openApplicationWithBundleID:(NSString *)arg1 ;
|
||||
- (void)enumerateApplicationsOfType:(NSUInteger)type block:(void (^)(LSApplicationProxy*))block;
|
||||
@end
|
||||
|
||||
@interface LSEnumerator : NSEnumerator
|
||||
@property (nonatomic,copy) NSPredicate * predicate;
|
||||
+ (instancetype)enumeratorForApplicationProxiesWithOptions:(NSUInteger)options;
|
||||
@end
|
||||
|
||||
@interface LSPlugInKitProxy : LSBundleProxy
|
||||
@property (nonatomic,readonly) NSString* pluginIdentifier;
|
||||
@property (nonatomic,readonly) NSDictionary * pluginKitDictionary;
|
||||
+ (instancetype)pluginKitProxyForIdentifier:(NSString*)arg1;
|
||||
@end
|
||||
|
||||
@interface MCMContainer : NSObject
|
||||
+ (id)containerWithIdentifier:(id)arg1 createIfNecessary:(BOOL)arg2 existed:(BOOL*)arg3 error:(id*)arg4;
|
||||
@property (nonatomic,readonly) NSURL * url;
|
||||
@end
|
||||
|
||||
@interface MCMDataContainer : MCMContainer
|
||||
|
||||
@end
|
||||
|
||||
@interface MCMAppDataContainer : MCMDataContainer
|
||||
|
||||
@end
|
||||
|
||||
@interface MCMAppContainer : MCMContainer
|
||||
@end
|
||||
|
||||
@interface MCMPluginKitPluginDataContainer : MCMDataContainer
|
||||
@end
|
||||
@@ -0,0 +1,24 @@
|
||||
#import <UIKit/UIKit.h>
|
||||
#import <Preferences/PSListController.h>
|
||||
#import <Preferences/PSSpecifier.h>
|
||||
|
||||
@interface TSListControllerShared : PSListController
|
||||
{
|
||||
UIAlertController* _activityController;
|
||||
}
|
||||
|
||||
- (BOOL)isTrollStore;
|
||||
- (NSString*)getTrollStoreVersion;
|
||||
|
||||
- (void)startActivity:(NSString*)activity;
|
||||
- (void)stopActivityWithCompletion:(void (^)(void))completion;
|
||||
|
||||
- (void)downloadTrollStoreAndDo:(void (^)(NSString* localTrollStoreTarPath))doHandler;
|
||||
- (void)installTrollStorePressed;
|
||||
- (void)updateTrollStorePressed;
|
||||
- (void)rebuildIconCachePressed;
|
||||
- (void)refreshAppRegistrationsPressed;
|
||||
- (void)uninstallPersistenceHelperPressed;
|
||||
- (void)handleUninstallation;
|
||||
- (void)uninstallTrollStorePressed;
|
||||
@end
|
||||
@@ -0,0 +1,234 @@
|
||||
#import "TSListControllerShared.h"
|
||||
#import "TSUtil.h"
|
||||
|
||||
@implementation TSListControllerShared
|
||||
|
||||
- (BOOL)isTrollStore
|
||||
{
|
||||
return YES;
|
||||
}
|
||||
|
||||
- (NSString*)getTrollStoreVersion
|
||||
{
|
||||
if([self isTrollStore])
|
||||
{
|
||||
return [NSBundle.mainBundle objectForInfoDictionaryKey:@"CFBundleVersion"];
|
||||
}
|
||||
else
|
||||
{
|
||||
NSString* trollStorePath = trollStoreAppPath();
|
||||
if(!trollStorePath) return nil;
|
||||
|
||||
NSBundle* trollStoreBundle = [NSBundle bundleWithPath:trollStorePath];
|
||||
return [trollStoreBundle objectForInfoDictionaryKey:@"CFBundleVersion"];
|
||||
}
|
||||
}
|
||||
|
||||
- (void)startActivity:(NSString*)activity
|
||||
{
|
||||
if(_activityController) return;
|
||||
|
||||
_activityController = [UIAlertController alertControllerWithTitle:activity message:@"" preferredStyle:UIAlertControllerStyleAlert];
|
||||
UIActivityIndicatorView* activityIndicator = [[UIActivityIndicatorView alloc] initWithFrame:CGRectMake(5,5,50,50)];
|
||||
activityIndicator.hidesWhenStopped = YES;
|
||||
activityIndicator.activityIndicatorViewStyle = UIActivityIndicatorViewStyleMedium;
|
||||
[activityIndicator startAnimating];
|
||||
[_activityController.view addSubview:activityIndicator];
|
||||
|
||||
[self presentViewController:_activityController animated:YES completion:nil];
|
||||
}
|
||||
|
||||
- (void)stopActivityWithCompletion:(void (^)(void))completion
|
||||
{
|
||||
if(!_activityController) return;
|
||||
|
||||
[_activityController dismissViewControllerAnimated:YES completion:^
|
||||
{
|
||||
_activityController = nil;
|
||||
if(completion)
|
||||
{
|
||||
completion();
|
||||
}
|
||||
}];
|
||||
}
|
||||
|
||||
- (void)downloadTrollStoreAndDo:(void (^)(NSString* localTrollStoreTarPath))doHandler
|
||||
{
|
||||
NSURL* trollStoreURL = [NSURL URLWithString:@"https://github.com/opa334/TrollStore/releases/latest/download/TrollStore.tar"];
|
||||
NSURLRequest* trollStoreRequest = [NSURLRequest requestWithURL:trollStoreURL];
|
||||
|
||||
NSURLSessionDownloadTask* downloadTask = [NSURLSession.sharedSession downloadTaskWithRequest:trollStoreRequest completionHandler:^(NSURL *location, NSURLResponse *response, NSError *error)
|
||||
{
|
||||
if(error)
|
||||
{
|
||||
UIAlertController* errorAlert = [UIAlertController alertControllerWithTitle:@"Error" message:[NSString stringWithFormat:@"Error downloading TrollStore: %@", error] preferredStyle:UIAlertControllerStyleAlert];
|
||||
UIAlertAction* closeAction = [UIAlertAction actionWithTitle:@"Close" style:UIAlertActionStyleDefault handler:nil];
|
||||
[errorAlert addAction:closeAction];
|
||||
|
||||
dispatch_async(dispatch_get_main_queue(), ^
|
||||
{
|
||||
[self stopActivityWithCompletion:^
|
||||
{
|
||||
[self presentViewController:errorAlert animated:YES completion:nil];
|
||||
}];
|
||||
});
|
||||
}
|
||||
else
|
||||
{
|
||||
NSString* tarTmpPath = [NSTemporaryDirectory() stringByAppendingPathComponent:@"TrollStore.tar"];
|
||||
[[NSFileManager defaultManager] copyItemAtPath:location.path toPath:tarTmpPath error:nil];
|
||||
|
||||
doHandler(tarTmpPath);
|
||||
}
|
||||
}];
|
||||
|
||||
[downloadTask resume];
|
||||
}
|
||||
|
||||
- (void)_updateOrInstallTrollStore:(BOOL)update
|
||||
{
|
||||
if(update)
|
||||
{
|
||||
[self startActivity:@"Updating TrollStore"];
|
||||
}
|
||||
else
|
||||
{
|
||||
[self startActivity:@"Installing TrollStore"];
|
||||
}
|
||||
|
||||
[self downloadTrollStoreAndDo:^(NSString* tmpTarPath)
|
||||
{
|
||||
int ret = spawnRoot(rootHelperPath(), @[@"install-trollstore", tmpTarPath], nil, nil);
|
||||
[[NSFileManager defaultManager] removeItemAtPath:tmpTarPath error:nil];
|
||||
|
||||
if(ret == 0)
|
||||
{
|
||||
respring();
|
||||
|
||||
if([self isTrollStore])
|
||||
{
|
||||
exit(0);
|
||||
}
|
||||
else
|
||||
{
|
||||
dispatch_async(dispatch_get_main_queue(), ^
|
||||
{
|
||||
[self stopActivityWithCompletion:^
|
||||
{
|
||||
[self reloadSpecifiers];
|
||||
}];
|
||||
});
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
dispatch_async(dispatch_get_main_queue(), ^
|
||||
{
|
||||
[self stopActivityWithCompletion:^
|
||||
{
|
||||
UIAlertController* errorAlert = [UIAlertController alertControllerWithTitle:@"Error" message:[NSString stringWithFormat:@"Error installing TrollStore: trollstorehelper returned %d", ret] preferredStyle:UIAlertControllerStyleAlert];
|
||||
UIAlertAction* closeAction = [UIAlertAction actionWithTitle:@"Close" style:UIAlertActionStyleDefault handler:nil];
|
||||
[errorAlert addAction:closeAction];
|
||||
[self presentViewController:errorAlert animated:YES completion:nil];
|
||||
}];
|
||||
});
|
||||
}
|
||||
}];
|
||||
}
|
||||
|
||||
- (void)installTrollStorePressed
|
||||
{
|
||||
[self _updateOrInstallTrollStore:NO];
|
||||
}
|
||||
|
||||
- (void)updateTrollStorePressed
|
||||
{
|
||||
[self _updateOrInstallTrollStore:YES];
|
||||
}
|
||||
|
||||
- (void)rebuildIconCachePressed
|
||||
{
|
||||
[self startActivity:@"Rebuilding Icon Cache"];
|
||||
|
||||
dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^
|
||||
{
|
||||
spawnRoot(rootHelperPath(), @[@"refresh-all"], nil, nil);
|
||||
|
||||
dispatch_async(dispatch_get_main_queue(), ^
|
||||
{
|
||||
[self stopActivityWithCompletion:nil];
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
- (void)refreshAppRegistrationsPressed
|
||||
{
|
||||
[self startActivity:@"Refreshing"];
|
||||
|
||||
dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^
|
||||
{
|
||||
spawnRoot(rootHelperPath(), @[@"refresh"], nil, nil);
|
||||
respring();
|
||||
|
||||
dispatch_async(dispatch_get_main_queue(), ^
|
||||
{
|
||||
[self stopActivityWithCompletion:nil];
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
- (void)uninstallPersistenceHelperPressed
|
||||
{
|
||||
if([self isTrollStore])
|
||||
{
|
||||
spawnRoot(rootHelperPath(), @[@"uninstall-persistence-helper"], nil, nil);
|
||||
[self reloadSpecifiers];
|
||||
}
|
||||
else
|
||||
{
|
||||
UIAlertController* uninstallWarningAlert = [UIAlertController alertControllerWithTitle:@"Warning" message:@"Uninstalling the persistence helper will revert this app back to it's original state, you will however no longer be able to persistently refresh the TrollStore app registrations. Continue?" preferredStyle:UIAlertControllerStyleAlert];
|
||||
|
||||
UIAlertAction* cancelAction = [UIAlertAction actionWithTitle:@"Cancel" style:UIAlertActionStyleCancel handler:nil];
|
||||
[uninstallWarningAlert addAction:cancelAction];
|
||||
|
||||
UIAlertAction* continueAction = [UIAlertAction actionWithTitle:@"Continue" style:UIAlertActionStyleDestructive handler:^(UIAlertAction* action)
|
||||
{
|
||||
spawnRoot(rootHelperPath(), @[@"uninstall-persistence-helper"], nil, nil);
|
||||
exit(0);
|
||||
}];
|
||||
[uninstallWarningAlert addAction:continueAction];
|
||||
|
||||
[self presentViewController:uninstallWarningAlert animated:YES completion:nil];
|
||||
}
|
||||
}
|
||||
|
||||
- (void)handleUninstallation
|
||||
{
|
||||
if([self isTrollStore])
|
||||
{
|
||||
exit(0);
|
||||
}
|
||||
else
|
||||
{
|
||||
[self reloadSpecifiers];
|
||||
}
|
||||
}
|
||||
|
||||
- (void)uninstallTrollStorePressed
|
||||
{
|
||||
UIAlertController* uninstallWarningAlert = [UIAlertController alertControllerWithTitle:@"Warning" message:@"About to uninstall TrollStore and all of the apps installed by it. Continue?" preferredStyle:UIAlertControllerStyleAlert];
|
||||
|
||||
UIAlertAction* cancelAction = [UIAlertAction actionWithTitle:@"Cancel" style:UIAlertActionStyleCancel handler:nil];
|
||||
[uninstallWarningAlert addAction:cancelAction];
|
||||
|
||||
UIAlertAction* continueAction = [UIAlertAction actionWithTitle:@"Continue" style:UIAlertActionStyleDestructive handler:^(UIAlertAction* action)
|
||||
{
|
||||
spawnRoot(rootHelperPath(), @[@"uninstall-trollstore"], nil, nil);
|
||||
[self handleUninstallation];
|
||||
}];
|
||||
[uninstallWarningAlert addAction:continueAction];
|
||||
|
||||
[self presentViewController:uninstallWarningAlert animated:YES completion:nil];
|
||||
}
|
||||
|
||||
@end
|
||||
@@ -0,0 +1,26 @@
|
||||
@import Foundation;
|
||||
#import "CoreServices.h"
|
||||
|
||||
extern void chineseWifiFixup(void);
|
||||
extern void loadMCMFramework(void);
|
||||
extern NSString* safe_getExecutablePath();
|
||||
extern NSString* rootHelperPath(void);
|
||||
extern NSString* getNSStringFromFile(int fd);
|
||||
extern void printMultilineNSString(NSString* stringToPrint);
|
||||
extern int spawnRoot(NSString* path, NSArray* args, NSString** stdOut, NSString** stdErr);
|
||||
extern void respring(void);
|
||||
extern void fetchLatestTrollStoreVersion(void (^completionHandler)(NSString* latestVersion));
|
||||
|
||||
extern NSArray* trollStoreInstalledAppBundlePaths();
|
||||
extern NSArray* trollStoreInstalledAppContainerPaths();
|
||||
extern NSString* trollStorePath();
|
||||
extern NSString* trollStoreAppPath();
|
||||
|
||||
typedef enum
|
||||
{
|
||||
PERSISTENCE_HELPER_TYPE_USER = 1 << 0,
|
||||
PERSISTENCE_HELPER_TYPE_SYSTEM = 1 << 1,
|
||||
PERSISTENCE_HELPER_TYPE_ALL = PERSISTENCE_HELPER_TYPE_USER | PERSISTENCE_HELPER_TYPE_SYSTEM
|
||||
} PERSISTENCE_HELPER_TYPE;
|
||||
|
||||
extern LSApplicationProxy* findPersistenceHelperApp(PERSISTENCE_HELPER_TYPE allowedTypes);
|
||||
+346
@@ -0,0 +1,346 @@
|
||||
#import "TSUtil.h"
|
||||
|
||||
#import <Foundation/Foundation.h>
|
||||
#import <spawn.h>
|
||||
#import <sys/sysctl.h>
|
||||
|
||||
@interface PSAppDataUsagePolicyCache : NSObject
|
||||
+ (instancetype)sharedInstance;
|
||||
- (void)setUsagePoliciesForBundle:(NSString*)bundleId cellular:(BOOL)cellular wifi:(BOOL)wifi;
|
||||
@end
|
||||
|
||||
#define POSIX_SPAWN_PERSONA_FLAGS_OVERRIDE 1
|
||||
extern int posix_spawnattr_set_persona_np(const posix_spawnattr_t* __restrict, uid_t, uint32_t);
|
||||
extern int posix_spawnattr_set_persona_uid_np(const posix_spawnattr_t* __restrict, uid_t);
|
||||
extern int posix_spawnattr_set_persona_gid_np(const posix_spawnattr_t* __restrict, uid_t);
|
||||
|
||||
void chineseWifiFixup(void)
|
||||
{
|
||||
NSBundle *bundle = [NSBundle bundleWithPath:@"/System/Library/PrivateFrameworks/SettingsCellular.framework"];
|
||||
[bundle load];
|
||||
[[NSClassFromString(@"PSAppDataUsagePolicyCache") sharedInstance] setUsagePoliciesForBundle:NSBundle.mainBundle.bundleIdentifier cellular:true wifi:true];
|
||||
}
|
||||
|
||||
void loadMCMFramework(void)
|
||||
{
|
||||
static dispatch_once_t onceToken;
|
||||
dispatch_once (&onceToken, ^{
|
||||
NSBundle* mcmBundle = [NSBundle bundleWithPath:@"/System/Library/PrivateFrameworks/MobileContainerManager.framework"];
|
||||
[mcmBundle load];
|
||||
});
|
||||
}
|
||||
|
||||
extern char*** _NSGetArgv();
|
||||
NSString* safe_getExecutablePath()
|
||||
{
|
||||
char* executablePathC = **_NSGetArgv();
|
||||
return [NSString stringWithUTF8String:executablePathC];
|
||||
}
|
||||
|
||||
#ifdef EMBEDDED_ROOT_HELPER
|
||||
NSString* rootHelperPath(void)
|
||||
{
|
||||
return safe_getExecutablePath();
|
||||
}
|
||||
#else
|
||||
NSString* rootHelperPath(void)
|
||||
{
|
||||
return [[NSBundle mainBundle].bundlePath stringByAppendingPathComponent:@"trollstorehelper"];
|
||||
}
|
||||
#endif
|
||||
|
||||
NSString* getNSStringFromFile(int fd)
|
||||
{
|
||||
NSMutableString* ms = [NSMutableString new];
|
||||
ssize_t num_read;
|
||||
char c;
|
||||
while((num_read = read(fd, &c, sizeof(c))))
|
||||
{
|
||||
[ms appendString:[NSString stringWithFormat:@"%c", c]];
|
||||
}
|
||||
return ms.copy;
|
||||
}
|
||||
|
||||
void printMultilineNSString(NSString* stringToPrint)
|
||||
{
|
||||
NSCharacterSet *separator = [NSCharacterSet newlineCharacterSet];
|
||||
NSArray* lines = [stringToPrint componentsSeparatedByCharactersInSet:separator];
|
||||
for(NSString* line in lines)
|
||||
{
|
||||
NSLog(@"%@", line);
|
||||
}
|
||||
}
|
||||
|
||||
int spawnRoot(NSString* path, NSArray* args, NSString** stdOut, NSString** stdErr)
|
||||
{
|
||||
NSMutableArray* argsM = args.mutableCopy ?: [NSMutableArray new];
|
||||
[argsM insertObject:path.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_spawnattr_t attr;
|
||||
posix_spawnattr_init(&attr);
|
||||
|
||||
posix_spawnattr_set_persona_np(&attr, 99, POSIX_SPAWN_PERSONA_FLAGS_OVERRIDE);
|
||||
posix_spawnattr_set_persona_uid_np(&attr, 0);
|
||||
posix_spawnattr_set_persona_gid_np(&attr, 0);
|
||||
|
||||
posix_spawn_file_actions_t action;
|
||||
posix_spawn_file_actions_init(&action);
|
||||
|
||||
int outErr[2];
|
||||
if(stdErr)
|
||||
{
|
||||
pipe(outErr);
|
||||
posix_spawn_file_actions_adddup2(&action, outErr[1], STDERR_FILENO);
|
||||
posix_spawn_file_actions_addclose(&action, outErr[0]);
|
||||
}
|
||||
|
||||
int out[2];
|
||||
if(stdOut)
|
||||
{
|
||||
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, [path UTF8String], &action, &attr, (char* const*)argsC, NULL);
|
||||
posix_spawnattr_destroy(&attr);
|
||||
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) {
|
||||
NSLog(@"Child status %d", WEXITSTATUS(status));
|
||||
} else
|
||||
{
|
||||
perror("waitpid");
|
||||
return -222;
|
||||
}
|
||||
} while (!WIFEXITED(status) && !WIFSIGNALED(status));
|
||||
|
||||
if(stdOut)
|
||||
{
|
||||
close(out[1]);
|
||||
NSString* output = getNSStringFromFile(out[0]);
|
||||
*stdOut = output;
|
||||
}
|
||||
|
||||
if(stdErr)
|
||||
{
|
||||
close(outErr[1]);
|
||||
NSString* errorOutput = getNSStringFromFile(outErr[0]);
|
||||
*stdErr = errorOutput;
|
||||
}
|
||||
|
||||
return WEXITSTATUS(status);
|
||||
}
|
||||
|
||||
void enumerateProcessesUsingBlock(void (^enumerator)(pid_t pid, NSString* executablePath, BOOL* stop))
|
||||
{
|
||||
static int maxArgumentSize = 0;
|
||||
if (maxArgumentSize == 0) {
|
||||
size_t size = sizeof(maxArgumentSize);
|
||||
if (sysctl((int[]){ CTL_KERN, KERN_ARGMAX }, 2, &maxArgumentSize, &size, NULL, 0) == -1) {
|
||||
perror("sysctl argument size");
|
||||
maxArgumentSize = 4096; // Default
|
||||
}
|
||||
}
|
||||
int mib[3] = { CTL_KERN, KERN_PROC, KERN_PROC_ALL};
|
||||
struct kinfo_proc *info;
|
||||
size_t length;
|
||||
int count;
|
||||
|
||||
if (sysctl(mib, 3, NULL, &length, NULL, 0) < 0)
|
||||
return;
|
||||
if (!(info = malloc(length)))
|
||||
return;
|
||||
if (sysctl(mib, 3, info, &length, NULL, 0) < 0) {
|
||||
free(info);
|
||||
return;
|
||||
}
|
||||
count = length / sizeof(struct kinfo_proc);
|
||||
for (int i = 0; i < count; i++) {
|
||||
@autoreleasepool {
|
||||
pid_t pid = info[i].kp_proc.p_pid;
|
||||
if (pid == 0) {
|
||||
continue;
|
||||
}
|
||||
size_t size = maxArgumentSize;
|
||||
char* buffer = (char *)malloc(length);
|
||||
if (sysctl((int[]){ CTL_KERN, KERN_PROCARGS2, pid }, 3, buffer, &size, NULL, 0) == 0) {
|
||||
NSString* executablePath = [NSString stringWithCString:(buffer+sizeof(int)) encoding:NSUTF8StringEncoding];
|
||||
|
||||
BOOL stop = NO;
|
||||
enumerator(pid, executablePath, &stop);
|
||||
if(stop)
|
||||
{
|
||||
free(buffer);
|
||||
break;
|
||||
}
|
||||
}
|
||||
free(buffer);
|
||||
}
|
||||
}
|
||||
free(info);
|
||||
}
|
||||
|
||||
void killall(NSString* processName)
|
||||
{
|
||||
enumerateProcessesUsingBlock(^(pid_t pid, NSString* executablePath, BOOL* stop)
|
||||
{
|
||||
if([executablePath.lastPathComponent isEqualToString:processName])
|
||||
{
|
||||
kill(pid, SIGTERM);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
void respring(void)
|
||||
{
|
||||
killall(@"SpringBoard");
|
||||
exit(0);
|
||||
}
|
||||
|
||||
void fetchLatestTrollStoreVersion(void (^completionHandler)(NSString* latestVersion))
|
||||
{
|
||||
NSURL* githubLatestAPIURL = [NSURL URLWithString:@"https://api.github.com/repos/opa334/TrollStore/releases/latest"];
|
||||
|
||||
NSURLSessionDataTask* task = [NSURLSession.sharedSession dataTaskWithURL:githubLatestAPIURL completionHandler:^(NSData *data, NSURLResponse *response, NSError *error)
|
||||
{
|
||||
if(!error)
|
||||
{
|
||||
if ([response isKindOfClass:[NSHTTPURLResponse class]])
|
||||
{
|
||||
NSError *jsonError;
|
||||
NSDictionary *jsonResponse = [NSJSONSerialization JSONObjectWithData:data options:0 error:&jsonError];
|
||||
|
||||
if (!jsonError)
|
||||
{
|
||||
completionHandler(jsonResponse[@"tag_name"]);
|
||||
}
|
||||
}
|
||||
}
|
||||
}];
|
||||
|
||||
[task resume];
|
||||
}
|
||||
|
||||
NSArray* trollStoreInstalledAppContainerPaths()
|
||||
{
|
||||
NSMutableArray* appContainerPaths = [NSMutableArray new];
|
||||
|
||||
NSString* appContainersPath = @"/var/containers/Bundle/Application";
|
||||
|
||||
NSError* error;
|
||||
NSArray* containers = [[NSFileManager defaultManager] contentsOfDirectoryAtPath:appContainersPath error:&error];
|
||||
if(error)
|
||||
{
|
||||
NSLog(@"error getting app bundles paths %@", error);
|
||||
}
|
||||
if(!containers) return nil;
|
||||
|
||||
for(NSString* container in containers)
|
||||
{
|
||||
NSString* containerPath = [appContainersPath stringByAppendingPathComponent:container];
|
||||
BOOL isDirectory = NO;
|
||||
BOOL exists = [[NSFileManager defaultManager] fileExistsAtPath:containerPath isDirectory:&isDirectory];
|
||||
if(exists && isDirectory)
|
||||
{
|
||||
NSString* trollStoreMark = [containerPath stringByAppendingPathComponent:@"_TrollStore"];
|
||||
if([[NSFileManager defaultManager] fileExistsAtPath:trollStoreMark])
|
||||
{
|
||||
NSString* trollStoreApp = [containerPath stringByAppendingPathComponent:@"TrollStore.app"];
|
||||
if(![[NSFileManager defaultManager] fileExistsAtPath:trollStoreApp])
|
||||
{
|
||||
[appContainerPaths addObject:containerPath];
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return appContainerPaths.copy;
|
||||
}
|
||||
|
||||
NSArray* trollStoreInstalledAppBundlePaths()
|
||||
{
|
||||
NSMutableArray* appPaths = [NSMutableArray new];
|
||||
for(NSString* containerPath in trollStoreInstalledAppContainerPaths())
|
||||
{
|
||||
NSArray* items = [[NSFileManager defaultManager] contentsOfDirectoryAtPath:containerPath error:nil];
|
||||
if(!items) return nil;
|
||||
|
||||
for(NSString* item in items)
|
||||
{
|
||||
if([item.pathExtension isEqualToString:@"app"])
|
||||
{
|
||||
[appPaths addObject:[containerPath stringByAppendingPathComponent:item]];
|
||||
}
|
||||
}
|
||||
}
|
||||
return appPaths.copy;
|
||||
}
|
||||
|
||||
NSString* trollStorePath()
|
||||
{
|
||||
loadMCMFramework();
|
||||
NSError* mcmError;
|
||||
MCMAppContainer* appContainer = [NSClassFromString(@"MCMAppContainer") containerWithIdentifier:@"com.opa334.TrollStore" createIfNecessary:NO existed:NULL error:&mcmError];
|
||||
if(!appContainer) return nil;
|
||||
return appContainer.url.path;
|
||||
}
|
||||
|
||||
NSString* trollStoreAppPath()
|
||||
{
|
||||
return [trollStorePath() stringByAppendingPathComponent:@"TrollStore.app"];
|
||||
}
|
||||
|
||||
LSApplicationProxy* findPersistenceHelperApp(PERSISTENCE_HELPER_TYPE allowedTypes)
|
||||
{
|
||||
__block LSApplicationProxy* outProxy;
|
||||
|
||||
void (^searchBlock)(LSApplicationProxy* appProxy) = ^(LSApplicationProxy* appProxy)
|
||||
{
|
||||
if(appProxy.installed && !appProxy.restricted)
|
||||
{
|
||||
if([appProxy.bundleURL.path hasPrefix:@"/private/var/containers"])
|
||||
{
|
||||
NSURL* trollStorePersistenceMarkURL = [appProxy.bundleURL URLByAppendingPathComponent:@".TrollStorePersistenceHelper"];
|
||||
if([trollStorePersistenceMarkURL checkResourceIsReachableAndReturnError:nil])
|
||||
{
|
||||
outProxy = appProxy;
|
||||
}
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
if(allowedTypes & PERSISTENCE_HELPER_TYPE_USER)
|
||||
{
|
||||
[[LSApplicationWorkspace defaultWorkspace] enumerateApplicationsOfType:0 block:searchBlock];
|
||||
}
|
||||
if(allowedTypes & PERSISTENCE_HELPER_TYPE_SYSTEM)
|
||||
{
|
||||
[[LSApplicationWorkspace defaultWorkspace] enumerateApplicationsOfType:1 block:searchBlock];
|
||||
}
|
||||
|
||||
return outProxy;
|
||||
}
|
||||
Reference in New Issue
Block a user