add project

This commit is contained in:
opa334
2022-09-02 17:19:48 +02:00
commit 057bd1a45f
166 changed files with 8422 additions and 0 deletions
+51
View File
@@ -0,0 +1,51 @@
@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;
@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;
- (void)enumerateApplicationsOfType:(NSUInteger)type block:(void (^)(LSApplicationProxy*))block;
@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
+15
View File
@@ -0,0 +1,15 @@
TARGET := iphone:clang:14.5:14.0
ARCHS = arm64
include $(THEOS)/makefiles/common.mk
TOOL_NAME = trollstorehelper
trollstorehelper_FILES = $(wildcard *.m)
trollstorehelper_CFLAGS = -fobjc-arc
trollstorehelper_CODESIGN_FLAGS = -Sentitlements.plist
trollstorehelper_INSTALL_PATH = /usr/local/bin
trollstorehelper_LIBRARIES = archive
trollstorehelper_PRIVATE_FRAMEWORKS = SpringBoardServices BackBoardServices
include $(THEOS_MAKE_PATH)/tool.mk
+7
View File
@@ -0,0 +1,7 @@
#import "CoreServices.h"
NSArray* trollStoreInstalledAppBundlePaths();
NSArray* trollStoreInstalledAppContainerPaths();
NSString* trollStorePath();
NSString* trollStoreAppPath();
LSApplicationProxy* findPersistenceHelperApp(void);
+91
View File
@@ -0,0 +1,91 @@
@import Foundation;
#import "CoreServices.h"
#import <objc/runtime.h>
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()
{
NSError* mcmError;
MCMAppContainer* appContainer = [objc_getClass("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(void)
{
__block LSApplicationProxy* outProxy;
[[LSApplicationWorkspace defaultWorkspace] enumerateApplicationsOfType:1 block:^(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;
}
}
}
}];
return outProxy;
}
+9
View File
@@ -0,0 +1,9 @@
Package: com.opa334.trollstoreroothelper
Name: trollstoreroothelper
Version: 1.0
Architecture: iphoneos-arm
Description: An awesome tool of some sort!!
Maintainer: opa334
Author: opa334
Section: System
Tag: role::hacker
+33
View File
@@ -0,0 +1,33 @@
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
<dict>
<key>platform-application</key>
<true/>
<key>com.apple.private.security.container-required</key>
<false/>
<key>com.apple.security.exception.files.absolute-path.read-write</key>
<array>
<string>/</string>
</array>
<key>com.apple.private.security.container-manager</key>
<true/>
<key>com.apple.private.coreservices.canmaplsdatabase</key>
<true/>
<key>com.apple.lsapplicationworkspace.rebuildappdatabases</key>
<true/>
<key>com.apple.private.security.storage.AppBundles</key>
<true/>
<key>com.apple.private.MobileContainerManager.allowed</key>
<true/>
<key>com.apple.private.MobileInstallationHelperService.InstallDaemonOpsEnabled</key>
<true/>
<key>com.apple.private.MobileInstallationHelperService.allowed</key>
<true/>
<key>com.apple.private.uninstall.deletion</key>
<true/>
<key>com.apple.backboardd.launchapplications</key>
<true/>
<key>com.apple.multitasking.termination</key>
<true/>
</dict>
</plist>
+685
View File
@@ -0,0 +1,685 @@
#import <stdio.h>
#import "unarchive.h"
@import Foundation;
#import "uicache.h"
#import <sys/stat.h>
#import <dlfcn.h>
#import <spawn.h>
#import <objc/runtime.h>
#import "CoreServices.h"
#import "Shared.h"
#import <SpringBoardServices/SpringBoardServices.h>
extern mach_msg_return_t SBReloadIconForIdentifier(mach_port_t machport, const char* identifier);
@interface SBSHomeScreenService : NSObject
- (void)reloadIcons;
@end
extern NSString* BKSActivateForEventOptionTypeBackgroundContentFetching;
extern NSString* BKSOpenApplicationOptionKeyActivateForEvent;
extern void BKSTerminateApplicationForReasonAndReportWithDescription(NSString *bundleID, int reasonID, bool report, NSString *description);
#define kCFPreferencesNoContainer CFSTR("kCFPreferencesNoContainer")
typedef CFPropertyListRef (*_CFPreferencesCopyValueWithContainerType)(CFStringRef key, CFStringRef applicationID, CFStringRef userName, CFStringRef hostName, CFStringRef containerPath);
typedef void (*_CFPreferencesSetValueWithContainerType)(CFStringRef key, CFPropertyListRef value, CFStringRef applicationID, CFStringRef userName, CFStringRef hostName, CFStringRef containerPath);
typedef Boolean (*_CFPreferencesSynchronizeWithContainerType)(CFStringRef applicationID, CFStringRef userName, CFStringRef hostName, CFStringRef containerPath);
typedef CFArrayRef (*_CFPreferencesCopyKeyListWithContainerType)(CFStringRef applicationID, CFStringRef userName, CFStringRef hostName, CFStringRef containerPath);
typedef CFDictionaryRef (*_CFPreferencesCopyMultipleWithContainerType)(CFArrayRef keysToFetch, CFStringRef applicationID, CFStringRef userName, CFStringRef hostName, CFStringRef containerPath);
BOOL _installPersistenceHelper(LSApplicationProxy* appProxy, NSString* sourcePersistenceHelper, NSString* sourceRootHelper);
extern char*** _NSGetArgv();
NSString* safe_getExecutablePath()
{
char* executablePathC = **_NSGetArgv();
return [NSString stringWithUTF8String:executablePathC];
}
NSDictionary* infoDictionaryForAppPath(NSString* appPath)
{
NSString* infoPlistPath = [appPath stringByAppendingPathComponent:@"Info.plist"];
return [NSDictionary dictionaryWithContentsOfFile:infoPlistPath];
}
NSString* appIdForAppPath(NSString* appPath)
{
return infoDictionaryForAppPath(appPath)[@"CFBundleIdentifier"];
}
NSString* appPathForAppId(NSString* appId, NSError** error)
{
for(NSString* appPath in trollStoreInstalledAppBundlePaths())
{
if([appIdForAppPath(appPath) isEqualToString:appId])
{
return appPath;
}
}
return nil;
}
static 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;
}
static void printMultilineNSString(NSString* stringToPrint)
{
NSCharacterSet *separator = [NSCharacterSet newlineCharacterSet];
NSArray* lines = [stringToPrint componentsSeparatedByCharactersInSet:separator];
for(NSString* line in lines)
{
NSLog(@"%@", line);
}
}
void installLdid(NSString* ldidToCopyPath)
{
if(![[NSFileManager defaultManager] fileExistsAtPath:ldidToCopyPath]) return;
NSString* ldidPath = [trollStoreAppPath() stringByAppendingPathComponent:@"ldid"];
if([[NSFileManager defaultManager] fileExistsAtPath:ldidPath])
{
[[NSFileManager defaultManager] removeItemAtPath:ldidPath error:nil];
}
[[NSFileManager defaultManager] copyItemAtPath:ldidToCopyPath toPath:ldidPath error:nil];
chmod(ldidPath.UTF8String, 0755);
chown(ldidPath.UTF8String, 0, 0);
}
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 UTF8String], &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);
}
NSString* dumpEntitlements(NSString* binaryPath)
{
NSString* output;
NSString* errorOutput;
int ldidRet = runLdid(@[@"-e", binaryPath], &output, &errorOutput);
NSLog(@"entitlements dump exited with status %d", ldidRet);
NSLog(@"- dump error output start -");
printMultilineNSString(errorOutput);
NSLog(@"- dump error output end -");
NSLog(@"- dumped entitlements output start -");
printMultilineNSString(output);
NSLog(@"- dumped entitlements output end -");
return output;
}
BOOL signApp(NSString* appPath, NSError** error)
{
if(!isLdidInstalled()) return NO;
NSDictionary* appInfoDict = [NSDictionary dictionaryWithContentsOfFile:[appPath stringByAppendingPathComponent:@"Info.plist"]];
if(!appInfoDict) return NO;
NSString* executable = appInfoDict[@"CFBundleExecutable"];
NSString* executablePath = [appPath stringByAppendingPathComponent:executable];
if(![[NSFileManager defaultManager] fileExistsAtPath:executablePath]) return NO;
NSString* certPath = [trollStoreAppPath() stringByAppendingPathComponent:@"cert.p12"];
NSString* certArg = [@"-K" stringByAppendingPathComponent:certPath];
NSString* errorOutput;
int ldidRet;
NSString* entitlements = dumpEntitlements(executablePath);
if(entitlements.length == 0)
{
NSLog(@"app main binary has no entitlements, signing app with fallback entitlements...");
// app has no entitlements, sign with fallback entitlements
NSString* entitlementPath = [trollStoreAppPath() stringByAppendingPathComponent:@"fallback.entitlements"];
NSString* entitlementArg = [@"-S" stringByAppendingString:entitlementPath];
ldidRet = runLdid(@[entitlementArg, certArg, appPath], nil, &errorOutput);
}
else
{
// app has entitlements, keep them
ldidRet = runLdid(@[@"-S", @"-M", certArg, appPath], nil, &errorOutput);
}
NSLog(@"ldid exited with status %d", ldidRet);
NSLog(@"- ldid error output start -");
printMultilineNSString(errorOutput);
NSLog(@"- ldid error output end -");
return ldidRet == 0;
}
BOOL installApp(NSString* appPath, BOOL sign, NSError** error)
{
NSString* appId = appIdForAppPath(appPath);
if(!appId) return NO;
if(sign)
{
// if it fails to sign, we don't care
signApp(appPath, error);
}
BOOL existed;
NSError* mcmError;
MCMAppContainer* appContainer = [objc_getClass("MCMAppContainer") containerWithIdentifier:appId createIfNecessary:YES existed:&existed error:&mcmError];
NSLog(@"[installApp] appContainer: %@, mcmError: %@", appContainer, mcmError);
if(!appContainer || mcmError)
{
if(error) *error = mcmError;
return NO;
}
// Make sure there isn't already an app store app installed with the same identifier
NSURL* trollStoreMarkURL = [appContainer.url URLByAppendingPathComponent:@"_TrollStore"];
if(existed && ![trollStoreMarkURL checkResourceIsReachableAndReturnError:nil])
{
NSLog(@"[installApp] already installed and not a TrollStore app... bailing out");
return NO;
}
// Apply correct permissions
NSDirectoryEnumerator *enumerator = [[NSFileManager defaultManager] enumeratorAtURL:[NSURL fileURLWithPath:appPath] includingPropertiesForKeys:nil options:0 errorHandler:nil];
NSURL* fileURL;
while(fileURL = [enumerator nextObject])
{
NSString* filePath = fileURL.path;
chown(filePath.UTF8String, 33, 33);
if([filePath.lastPathComponent isEqualToString:@"Info.plist"])
{
NSDictionary* infoDictionary = [NSDictionary dictionaryWithContentsOfFile:filePath];
NSString* executable = infoDictionary[@"CFBundleExecutable"];
if(executable)
{
NSString* executablePath = [[filePath stringByDeletingLastPathComponent] stringByAppendingPathComponent:executable];
chmod(executablePath.UTF8String, 0755);
}
}
else if([filePath.pathExtension isEqualToString:@"dylib"])
{
chmod(filePath.UTF8String, 0755);
}
}
// chown 0 all root binaries
NSDictionary* mainInfoDictionary = [NSDictionary dictionaryWithContentsOfFile:[appPath stringByAppendingPathComponent:@"Info.plist"]];
if(!mainInfoDictionary) return NO;
NSObject* tsRootBinaries = mainInfoDictionary[@"TSRootBinaries"];
if([tsRootBinaries isKindOfClass:[NSArray class]])
{
NSArray* tsRootBinariesArr = (NSArray*)tsRootBinaries;
for(NSObject* rootBinary in tsRootBinariesArr)
{
if([rootBinary isKindOfClass:[NSString class]])
{
NSString* rootBinaryStr = (NSString*)rootBinary;
NSString* rootBinaryPath = [appPath stringByAppendingPathComponent:rootBinaryStr];
if([[NSFileManager defaultManager] fileExistsAtPath:rootBinaryPath])
{
chmod(rootBinaryPath.UTF8String, 0755);
chown(rootBinaryPath.UTF8String, 0, 0);
NSLog(@"[installApp] applying permissions for root binary %@", rootBinaryPath);
}
}
}
}
// Wipe old version if needed
if(existed)
{
NSLog(@"[installApp] found existing TrollStore app, cleaning directory");
NSDirectoryEnumerator *enumerator = [[NSFileManager defaultManager] enumeratorAtURL:appContainer.url includingPropertiesForKeys:nil options:0 errorHandler:nil];
NSURL* fileURL;
while(fileURL = [enumerator nextObject])
{
// 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"])
{
NSLog(@"[installApp] skip removal of %@", fileURL);
continue;
}
[[NSFileManager defaultManager] removeItemAtURL:fileURL error:nil];
}
}
// Install app
NSString* newAppPath = [appContainer.url.path stringByAppendingPathComponent:appPath.lastPathComponent];
NSLog(@"[installApp] new app path: %@", newAppPath);
BOOL suc = [[NSFileManager defaultManager] copyItemAtPath:appPath toPath:newAppPath error:error];
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...");
registerPath((char*)newAppPath.UTF8String, 0);
return YES;
}
else
{
return suc;
}
}
BOOL uninstallApp(NSString* appId, NSError** error)
{
NSString* appPath = appPathForAppId(appId, error);
if(!appPath) return NO;
LSApplicationProxy* appProxy = [LSApplicationProxy applicationProxyForIdentifier:appId];
NSLog(@"appProxy: %@", appProxy);
MCMContainer *appContainer = [objc_getClass("MCMAppDataContainer") containerWithIdentifier:appId createIfNecessary:NO existed:nil error:nil];
NSString *containerPath = [appContainer url].path;
if(containerPath)
{
NSLog(@"deleting %@", containerPath);
// delete app container path
[[NSFileManager defaultManager] removeItemAtPath:containerPath error:error];
}
// delete group container paths
for(NSURL* groupURL in [appProxy groupContainerURLs])
{
[[NSFileManager defaultManager] removeItemAtPath:groupURL.path error:error];
NSLog(@"deleting %@", groupURL.path);
}
// delete app plugin paths
for(LSPlugInKitProxy* pluginProxy in appProxy.plugInKitPlugins)
{
NSURL* pluginURL = pluginProxy.dataContainerURL;
if(pluginURL)
{
[[NSFileManager defaultManager] removeItemAtPath:pluginURL.path error:error];
NSLog(@"deleting %@", pluginURL.path);
}
}
// unregister app
registerPath((char*)appPath.UTF8String, 1);
NSLog(@"deleting %@", [appPath stringByDeletingLastPathComponent]);
// delete app
return [[NSFileManager defaultManager] removeItemAtPath:[appPath stringByDeletingLastPathComponent] error:error];
}
BOOL installIpa(NSString* ipaPath, NSError** error)
{
BOOL suc = NO;
NSString* tmpPath = [NSTemporaryDirectory() stringByAppendingPathComponent:[NSUUID UUID].UUIDString];
suc = [[NSFileManager defaultManager] createDirectoryAtPath:tmpPath withIntermediateDirectories:NO attributes:nil error:error];
if(!suc) return NO;
extract(ipaPath, tmpPath);
NSString* tmpPayloadPath = [tmpPath stringByAppendingPathComponent:@"Payload"];
NSArray* items = [[NSFileManager defaultManager] contentsOfDirectoryAtPath:tmpPayloadPath error:error];
if(!items) return NO;
NSString* tmpAppPath;
for(NSString* item in items)
{
if([item.pathExtension isEqualToString:@"app"])
{
tmpAppPath = [tmpPayloadPath stringByAppendingPathComponent:item];
break;
}
}
if(!tmpAppPath) return NO;
suc = installApp(tmpAppPath, YES, error);
[[NSFileManager defaultManager] removeItemAtPath:tmpAppPath error:nil];
return suc;
}
void uninstallAllApps(void)
{
for(NSString* appPath in trollStoreInstalledAppBundlePaths())
{
uninstallApp(appIdForAppPath(appPath), nil);
}
}
BOOL uninstallTrollStore(BOOL unregister)
{
NSString* trollStore = trollStorePath();
if(![[NSFileManager defaultManager] fileExistsAtPath:trollStore]) return NO;
if(unregister)
{
registerPath((char*)trollStoreAppPath().UTF8String, 1);
}
return [[NSFileManager defaultManager] removeItemAtPath:trollStore error:nil];
}
BOOL installTrollStore(NSString* pathToTar)
{
//_CFPreferencesCopyValueWithContainerType _CFPreferencesCopyValueWithContainer = (_CFPreferencesCopyValueWithContainerType)dlsym(RTLD_DEFAULT, "_CFPreferencesCopyValueWithContainer");
_CFPreferencesSetValueWithContainerType _CFPreferencesSetValueWithContainer = (_CFPreferencesSetValueWithContainerType)dlsym(RTLD_DEFAULT, "_CFPreferencesSetValueWithContainer");
_CFPreferencesSynchronizeWithContainerType _CFPreferencesSynchronizeWithContainer = (_CFPreferencesSynchronizeWithContainerType)dlsym(RTLD_DEFAULT, "_CFPreferencesSynchronizeWithContainer");
/*CFPropertyListRef SBShowNonDefaultSystemAppsValue = _CFPreferencesCopyValueWithContainer(CFSTR("SBShowNonDefaultSystemApps"), CFSTR("com.apple.springboard"), CFSTR("mobile"), kCFPreferencesAnyHost, kCFPreferencesNoContainer);
if(SBShowNonDefaultSystemAppsValue != kCFBooleanTrue)
{*/
_CFPreferencesSetValueWithContainer(CFSTR("SBShowNonDefaultSystemApps"), kCFBooleanTrue, CFSTR("com.apple.springboard"), CFSTR("mobile"), kCFPreferencesAnyHost, kCFPreferencesNoContainer);
_CFPreferencesSynchronizeWithContainer(CFSTR("com.apple.springboard"), CFSTR("mobile"), kCFPreferencesAnyHost, kCFPreferencesNoContainer);
//NSLog(@"unrestricted springboard apps");
/*}*/
if(![[NSFileManager defaultManager] fileExistsAtPath:pathToTar]) return NO;
if(![pathToTar.pathExtension isEqualToString:@"tar"]) return NO;
NSString* tmpPath = [NSTemporaryDirectory() stringByAppendingPathComponent:[NSUUID UUID].UUIDString];
BOOL suc = [[NSFileManager defaultManager] createDirectoryAtPath:tmpPath withIntermediateDirectories:NO attributes:nil error:nil];
if(!suc) return NO;
extract(pathToTar, tmpPath);
NSString* tmpTrollStore = [tmpPath stringByAppendingPathComponent:@"TrollStore.app"];
if(![[NSFileManager defaultManager] fileExistsAtPath:tmpTrollStore]) return NO;
// Save existing ldid installation if it exists
NSString* existingLdidPath = [trollStoreAppPath() stringByAppendingPathComponent:@"ldid"];
if([[NSFileManager defaultManager] fileExistsAtPath:existingLdidPath])
{
NSString* tmpLdidPath = [tmpTrollStore stringByAppendingPathComponent:@"ldid"];
if(![[NSFileManager defaultManager] fileExistsAtPath:tmpLdidPath])
{
[[NSFileManager defaultManager] copyItemAtPath:existingLdidPath toPath:tmpLdidPath error:nil];
}
}
// Update persistence helper if installed
LSApplicationProxy* persistenceHelperApp = findPersistenceHelperApp();
if(persistenceHelperApp)
{
NSString* trollStorePersistenceHelper = [tmpTrollStore stringByAppendingPathComponent:@"PersistenceHelper"];
NSString* trollStoreRootHelper = [tmpTrollStore stringByAppendingPathComponent:@"trollstorehelper"];
_installPersistenceHelper(persistenceHelperApp, trollStorePersistenceHelper, trollStoreRootHelper);
}
return installApp(tmpTrollStore, NO, nil);;
}
void refreshAppRegistrations()
{
//registerPath((char*)trollStoreAppPath().UTF8String, 1);
registerPath((char*)trollStoreAppPath().UTF8String, 0);
for(NSString* appPath in trollStoreInstalledAppBundlePaths())
{
//registerPath((char*)appPath.UTF8String, 1);
registerPath((char*)appPath.UTF8String, 0);
}
}
BOOL _installPersistenceHelper(LSApplicationProxy* appProxy, NSString* sourcePersistenceHelper, NSString* sourceRootHelper)
{
NSLog(@"_installPersistenceHelper(%@, %@, %@)", appProxy, sourcePersistenceHelper, sourceRootHelper);
NSString* executablePath = appProxy.canonicalExecutablePath;
NSString* bundlePath = appProxy.bundleURL.path;
if(!executablePath)
{
NSBundle* appBundle = [NSBundle bundleWithPath:bundlePath];
executablePath = [bundlePath stringByAppendingPathComponent:[appBundle objectForInfoDictionaryKey:@"CFBundleExecutable"]];
}
NSString* markPath = [bundlePath stringByAppendingPathComponent:@".TrollStorePersistenceHelper"];
NSString* helperPath = [bundlePath stringByAppendingPathComponent:@"trollstorehelper"];
// remove existing persistence helper binary if exists
if([[NSFileManager defaultManager] fileExistsAtPath:markPath] && [[NSFileManager defaultManager] fileExistsAtPath:executablePath])
{
[[NSFileManager defaultManager] removeItemAtPath:executablePath error:nil];
}
// remove existing root helper binary if exists
if([[NSFileManager defaultManager] fileExistsAtPath:helperPath])
{
[[NSFileManager defaultManager] removeItemAtPath:helperPath error:nil];
}
// install new persistence helper binary
if(![[NSFileManager defaultManager] copyItemAtPath:sourcePersistenceHelper toPath:executablePath error:nil])
{
return NO;
}
chmod(executablePath.UTF8String, 0755);
chown(executablePath.UTF8String, 33, 33);
NSError* error;
if(![[NSFileManager defaultManager] copyItemAtPath:sourceRootHelper toPath:helperPath error:&error])
{
NSLog(@"error copying root helper: %@", error);
}
chmod(helperPath.UTF8String, 0755);
chown(helperPath.UTF8String, 0, 0);
// mark system app as persistence helper
if(![[NSFileManager defaultManager] fileExistsAtPath:markPath])
{
[[NSFileManager defaultManager] createFileAtPath:markPath contents:[NSData data] attributes:nil];
}
return YES;
}
void installPersistenceHelper(NSString* systemAppId)
{
if(findPersistenceHelperApp()) return;
NSString* persistenceHelperBinary = [trollStoreAppPath() stringByAppendingPathComponent:@"PersistenceHelper"];
NSString* rootHelperBinary = [trollStoreAppPath() stringByAppendingPathComponent:@"trollstorehelper"];
LSApplicationProxy* appProxy = [LSApplicationProxy applicationProxyForIdentifier:systemAppId];
if(!appProxy || ![appProxy.bundleType isEqualToString:@"System"]) return;
NSString* executablePath = appProxy.canonicalExecutablePath;
NSString* bundlePath = appProxy.bundleURL.path;
NSString* backupPath = [bundlePath stringByAppendingPathComponent:[[executablePath lastPathComponent] stringByAppendingString:@"_TROLLSTORE_BACKUP"]];
if([[NSFileManager defaultManager] fileExistsAtPath:backupPath]) return;
if(![[NSFileManager defaultManager] moveItemAtPath:executablePath toPath:backupPath error:nil]) return;
if(!_installPersistenceHelper(appProxy, persistenceHelperBinary, rootHelperBinary))
{
[[NSFileManager defaultManager] moveItemAtPath:backupPath toPath:executablePath error:nil];
return;
}
BKSTerminateApplicationForReasonAndReportWithDescription(systemAppId, 5, false, @"TrollStore - Reload persistence helper");
}
void uninstallPersistenceHelper(void)
{
LSApplicationProxy* appProxy = findPersistenceHelperApp();
if(appProxy)
{
NSString* executablePath = appProxy.canonicalExecutablePath;
NSString* bundlePath = appProxy.bundleURL.path;
NSString* backupPath = [bundlePath stringByAppendingPathComponent:[[executablePath lastPathComponent] stringByAppendingString:@"_TROLLSTORE_BACKUP"]];
if(![[NSFileManager defaultManager] fileExistsAtPath:backupPath]) return;
NSString* helperPath = [bundlePath stringByAppendingPathComponent:@"trollstorehelper"];
NSString* markPath = [bundlePath stringByAppendingPathComponent:@".TrollStorePersistenceHelper"];
[[NSFileManager defaultManager] removeItemAtPath:executablePath error:nil];
[[NSFileManager defaultManager] removeItemAtPath:markPath error:nil];
[[NSFileManager defaultManager] removeItemAtPath:helperPath error:nil];
[[NSFileManager defaultManager] moveItemAtPath:backupPath toPath:executablePath error:nil];
BKSTerminateApplicationForReasonAndReportWithDescription(appProxy.bundleIdentifier, 5, false, @"TrollStore - Reload persistence helper");
}
}
int main(int argc, char *argv[], char *envp[]) {
@autoreleasepool {
if(argc <= 1) return -1;
NSLog(@"trollstore helper go, uid: %d, gid: %d", getuid(), getgid());
NSBundle* mcmBundle = [NSBundle bundleWithPath:@"/System/Library/PrivateFrameworks/MobileContainerManager.framework"];
[mcmBundle load];
BOOL suc = NO;
NSError* error;
NSString* cmd = [NSString stringWithUTF8String:argv[1]];
if([cmd isEqualToString:@"install"])
{
if(argc <= 2) return -2;
NSString* ipaPath = [NSString stringWithUTF8String:argv[2]];
suc = installIpa(ipaPath, &error);
} else if([cmd isEqualToString:@"uninstall"])
{
if(argc <= 2) return -2;
NSString* appId = [NSString stringWithUTF8String:argv[2]];
suc = uninstallApp(appId, &error);
} else if([cmd isEqualToString:@"install-trollstore"])
{
if(argc <= 2) return -2;
NSString* tsTar = [NSString stringWithUTF8String:argv[2]];
suc = installTrollStore(tsTar);
NSLog(@"installed troll store? %d", suc);
} else if([cmd isEqualToString:@"uninstall-trollstore"])
{
uninstallAllApps();
uninstallTrollStore(YES);
} else if([cmd isEqualToString:@"install-ldid"])
{
if(argc <= 2) return -2;
NSString* ldidPath = [NSString stringWithUTF8String:argv[2]];
installLdid(ldidPath);
} else if([cmd isEqualToString:@"refresh"])
{
refreshAppRegistrations();
} else if([cmd isEqualToString:@"refresh-all"])
{
[[LSApplicationWorkspace defaultWorkspace] _LSPrivateRebuildApplicationDatabasesForSystemApps:YES internal:YES user:YES];
refreshAppRegistrations();
} else if([cmd isEqualToString:@"install-persistence-helper"])
{
if(argc <= 2) return -2;
NSString* systemAppId = [NSString stringWithUTF8String:argv[2]];
installPersistenceHelper(systemAppId);
} else if([cmd isEqualToString:@"uninstall-persistence-helper"])
{
uninstallPersistenceHelper();
}
if(error)
{
NSLog(@"error: %@", error);
}
return !suc;
}
}
+351
View File
@@ -0,0 +1,351 @@
#import <stdio.h>
#import "unarchive.h"
@import Foundation;
#import "uicache.h"
#import <sys/stat.h>
#import <dlfcn.h>
#import <spawn.h>
#import "path.h"
#import "CoreServices.h"
#import <objc/runtime.h>
#define kCFPreferencesNoContainer CFSTR("kCFPreferencesNoContainer")
typedef CFPropertyListRef (*_CFPreferencesCopyValueWithContainerType)(CFStringRef key, CFStringRef applicationID, CFStringRef userName, CFStringRef hostName, CFStringRef containerPath);
typedef void (*_CFPreferencesSetValueWithContainerType)(CFStringRef key, CFPropertyListRef value, CFStringRef applicationID, CFStringRef userName, CFStringRef hostName, CFStringRef containerPath);
typedef Boolean (*_CFPreferencesSynchronizeWithContainerType)(CFStringRef applicationID, CFStringRef userName, CFStringRef hostName, CFStringRef containerPath);
typedef CFArrayRef (*_CFPreferencesCopyKeyListWithContainerType)(CFStringRef applicationID, CFStringRef userName, CFStringRef hostName, CFStringRef containerPath);
typedef CFDictionaryRef (*_CFPreferencesCopyMultipleWithContainerType)(CFArrayRef keysToFetch, CFStringRef applicationID, CFStringRef userName, CFStringRef hostName, CFStringRef containerPath);
extern char*** _NSGetArgv();
NSString* safe_getExecutablePath()
{
char* executablePathC = **_NSGetArgv();
return [NSString stringWithUTF8String:executablePathC];
}
NSDictionary* infoDictionaryForAppPath(NSString* appPath)
{
NSString* infoPlistPath = [appPath stringByAppendingPathComponent:@"Info.plist"];
return [NSDictionary dictionaryWithContentsOfFile:infoPlistPath];
}
NSString* appIdForAppPath(NSString* appPath)
{
return infoDictionaryForAppPath(appPath)[@"CFBundleIdentifier"];
}
NSString* appPathForAppId(NSString* appId, NSError** error)
{
NSString* appPath = [TROLLSTORE_APPLICATIONS_PATH stringByAppendingPathComponent:appId];
NSArray* items = [[NSFileManager defaultManager] contentsOfDirectoryAtPath:appPath error:error];
if(!items) return nil;
for(NSString* item in items)
{
if([item.pathExtension isEqualToString:@"app"])
{
return [appPath stringByAppendingPathComponent:item];
}
}
return nil;
}
static void dump_file_content(int fd)
{
ssize_t num_read;
char line_buf[256];
int cur_pos = 0;
for (;;)
{
char c;
num_read = read(fd, &c, sizeof(c));
if(num_read <= 0)
if(c == '\n' || cur_pos >= 255 || num_read <= 0)
{
line_buf[cur_pos] = '\n';
NSLog(@"%s", (char*)line_buf);
if(c == '\n') cur_pos++;
if(num_read > 0)
{
continue;
}
else
{
break;
}
}
line_buf[cur_pos++] = c;
}
}
BOOL signApp(NSString* appPath, NSError** error)
{
NSString* ldidPath = [[safe_getExecutablePath() stringByDeletingLastPathComponent] stringByAppendingPathComponent:@"ldid"];
if(![[NSFileManager defaultManager] fileExistsAtPath:ldidPath])
{
NSLog(@"WARNING: ldid not found, not signing application");
return NO;
}
NSString* certPath = [TROLLSTORE_MAIN_PATH stringByAppendingPathComponent:@"TrollStore.app/cert.p12"];
NSString* certArg = [@"-K" stringByAppendingPathComponent:certPath];
int out[2];
posix_spawn_file_actions_t action;
posix_spawn_file_actions_init(&action);
pipe(out);
posix_spawn_file_actions_adddup2(&action, out[1], STDERR_FILENO);
posix_spawn_file_actions_addclose(&action, out[0]);
char* args[] = { "ldid", "-S", "-M", (char*)certArg.UTF8String, (char*)appPath.UTF8String, NULL };
NSLog(@"%@ ldid -S -M %@ %@", ldidPath, certArg, appPath);
pid_t task_pid;
int status = -200;
int spawnError = posix_spawn(&task_pid, [ldidPath UTF8String], &action, NULL, args, NULL);
if(spawnError != 0)
{
NSLog(@"posix_spawn error %d\n", spawnError);
return spawnError;
}
waitpid(task_pid, &status, WEXITED);
NSLog(@"ldid exited with status %d", status);
waitpid(task_pid, &status, 0);
NSLog(@"ldid exited with status %d", status);
NSLog(@"ldid output:");
close(out[1]);
dump_file_content(out[0]);
NSLog(@"end ldid output:");
return status == 0;
}
BOOL installApp(NSString* appPath, NSString* appId, BOOL sign, NSError** error)
{
if(sign)
{
// if it fails to sign, we don't care
signApp(appPath, error);
}
BOOL existed;
NSError* mcmError;
MCMAppContainer* appContainer = [objc_getClass("MCMAppContainer") containerWithIdentifier:appId createIfNecessary:YES existed:&existed error:&mcmError];
NSLog(@"installApp appContainer: %@, mcmError: %@", appContainer, mcmError);
if(!appContainer || mcmError)
{
if(error) *error = mcmError;
return NO;
}
//TODO: if TrollStore, preserve by moving it into appPath if needed ldid if needed
NSURL* trollStoreMarkURL = [appContainer.url URLByAppendingPathComponent:@"_TrollStore"];
if(existed)
{
// trying to update an app not installed by TrollStore... bailing out
if(![trollStoreMarkURL checkResourceIsReachableAndReturnError:nil])
{
NSLog(@"installApp already installed and not a TrollStore app... bailing out");
return NO;
}
else
{
// update existing app... clean old app directory
NSLog(@"installApp found existing TrollStore app, cleaning directory");
NSDirectoryEnumerator *enumerator = [[NSFileManager defaultManager] enumeratorAtURL:appContainer.url includingPropertiesForKeys:nil options:0 errorHandler:nil];
NSURL* fileURL;
while(fileURL = [enumerator nextObject])
{
[[NSFileManager defaultManager] removeItemAtURL:fileURL error:nil];
}
}
}
[[NSFileManager defaultManager] createFileAtPath:trollStoreMarkURL.path contents:[NSData data] attributes:nil];
NSString* newAppPath = [appContainer.url.path stringByAppendingPathComponent:appPath.lastPathComponent];
NSLog(@"installApp new app path: %@", newAppPath);
BOOL suc = [[NSFileManager defaultManager] copyItemAtPath:appPath toPath:newAppPath error:error];
NSLog(@"installApp copied app? %d, adding to uicache now...", suc);
registerPath((char*)newAppPath.UTF8String, 0);
return YES;
}
BOOL uninstallApp(NSString* appId, NSError** error)
{
NSString* appPath = appPathForAppId(appId, error);
if(!appPath) return NO;
registerPath((char*)appPath.UTF8String, 1);
return [[NSFileManager defaultManager] removeItemAtPath:[appPath stringByDeletingLastPathComponent] error:error];
}
BOOL installIpa(NSString* ipaPath, NSError** error)
{
BOOL suc = NO;
NSString* tmpPath = [NSTemporaryDirectory() stringByAppendingPathComponent:[NSUUID UUID].UUIDString];
suc = [[NSFileManager defaultManager] createDirectoryAtPath:tmpPath withIntermediateDirectories:NO attributes:nil error:error];
if(!suc) return NO;
extract(ipaPath, tmpPath);
NSString* tmpPayloadPath = [tmpPath stringByAppendingPathComponent:@"Payload"];
NSArray* items = [[NSFileManager defaultManager] contentsOfDirectoryAtPath:tmpPayloadPath error:error];
if(!items) return NO;
NSString* tmpAppPath;
for(NSString* item in items)
{
if([item.pathExtension isEqualToString:@"app"])
{
tmpAppPath = [tmpPayloadPath stringByAppendingPathComponent:item];
break;
}
}
if(!tmpAppPath) return NO;
NSString* appId = appIdForAppPath(tmpAppPath);
suc = installApp(tmpAppPath, appId, YES, error);
[[NSFileManager defaultManager] removeItemAtPath:tmpAppPath error:nil];
return suc;
}
void uninstallAllApps(void)
{
NSArray* items = [[NSFileManager defaultManager] contentsOfDirectoryAtPath:TROLLSTORE_APPLICATIONS_PATH error:nil];
for(NSString* appId in items)
{
NSString* appPath = appPathForAppId(appId, nil);
registerPath((char*)appPath.UTF8String, 1);
}
[[NSFileManager defaultManager] removeItemAtPath:TROLLSTORE_ROOT_PATH error:nil];
}
BOOL uninstallTrollStore(void)
{
NSString* trollStore = [TROLLSTORE_MAIN_PATH stringByAppendingPathComponent:@"TrollStore.app"];
if(![[NSFileManager defaultManager] fileExistsAtPath:trollStore]) return NO;
registerPath((char*)trollStore.UTF8String, 1);
return [[NSFileManager defaultManager] removeItemAtPath:trollStore error:nil];
}
BOOL installTrollStore(NSString* pathToTar)
{
_CFPreferencesSetValueWithContainerType _CFPreferencesSetValueWithContainer = (_CFPreferencesSetValueWithContainerType)dlsym(RTLD_DEFAULT, "_CFPreferencesSetValueWithContainer");
_CFPreferencesSynchronizeWithContainerType _CFPreferencesSynchronizeWithContainer = (_CFPreferencesSynchronizeWithContainerType)dlsym(RTLD_DEFAULT, "_CFPreferencesSynchronizeWithContainer");
_CFPreferencesSetValueWithContainer(CFSTR("SBShowNonDefaultSystemApps"), kCFBooleanTrue, CFSTR("com.apple.springboard"), CFSTR("mobile"), kCFPreferencesAnyHost, kCFPreferencesNoContainer);
_CFPreferencesSynchronizeWithContainer(CFSTR("com.apple.springboard"), CFSTR("mobile"), kCFPreferencesAnyHost, kCFPreferencesNoContainer);
if(![[NSFileManager defaultManager] fileExistsAtPath:pathToTar]) return NO;
if(![pathToTar.pathExtension isEqualToString:@"tar"]) return NO;
NSString* tmpPath = [NSTemporaryDirectory() stringByAppendingPathComponent:[NSUUID UUID].UUIDString];
BOOL suc = [[NSFileManager defaultManager] createDirectoryAtPath:tmpPath withIntermediateDirectories:NO attributes:nil error:nil];
if(!suc) return NO;
extract(pathToTar, tmpPath);
NSLog(@"installTrollStore extracted %@ to %@", pathToTar, tmpPath);
NSString* tmpTrollStore = [tmpPath stringByAppendingPathComponent:@"TrollStore.app"];
if(![[NSFileManager defaultManager] fileExistsAtPath:tmpTrollStore]) return NO;
NSLog(@"installTrollStore temp TrollStore path: %@", tmpTrollStore);
NSString* tmpTrollStoreMain = [tmpTrollStore stringByAppendingPathComponent:@"TrollStore"];
NSString* tmpTrollStoreRootHelper = [tmpTrollStore stringByAppendingPathComponent:@"trollstorehelper"];
NSString* tmpTrollStoreLdid = [tmpTrollStore stringByAppendingPathComponent:@"ldid"];
// make executable
chmod(tmpTrollStoreMain.UTF8String, 0755);
chmod(tmpTrollStoreRootHelper.UTF8String, 0755);
chmod(tmpTrollStoreLdid.UTF8String, 0755);
// set owners
chown(tmpTrollStoreMain.UTF8String, 33, 33);
chown(tmpTrollStoreRootHelper.UTF8String, 0, 0); // set root helper binary owner to root
chown(tmpTrollStoreLdid.UTF8String, 0, 0);
NSLog(@"installTrollStore extracted and prepared TrollStore app, now installing...");
installApp(tmpTrollStore, @"com.apple.TrollStore", NO, nil);
[[NSFileManager defaultManager] removeItemAtPath:tmpPath error:nil];
return YES;
}
int main(int argc, char *argv[], char *envp[]) {
@autoreleasepool {
if(argc <= 1) return -1;
NSLog(@"trollstore helper go, uid: %d, gid: %d", getuid(), getgid());
NSLog(@"ok %d", argc);
NSBundle* mcmBundle = [NSBundle bundleWithPath:@"/System/Library/PrivateFrameworks/MobileContainerManager.framework"];
[mcmBundle load];
BOOL suc = NO;
NSError* error;
NSString* cmd = [NSString stringWithUTF8String:argv[1]];
if([cmd isEqualToString:@"install"])
{
if(argc <= 2) return -2;
NSString* ipaPath = [NSString stringWithUTF8String:argv[2]];
suc = installIpa(ipaPath, &error);
} else if([cmd isEqualToString:@"uninstall"])
{
if(argc <= 2) return -2;
NSString* appId = [NSString stringWithUTF8String:argv[2]];
suc = uninstallApp(appId, &error);
} else if([cmd isEqualToString:@"install-trollstore"])
{
if(argc <= 2) return -2;
NSString* tsTar = [NSString stringWithUTF8String:argv[2]];
suc = installTrollStore(tsTar);
NSLog(@"installed troll store? %d", suc);
} else if([cmd isEqualToString:@"uninstall-trollstore"])
{
uninstallTrollStore();
uninstallAllApps();
}
if(!suc)
{
NSLog(@"error: %@", error);
}
return !suc;
}
}
+1
View File
@@ -0,0 +1 @@
extern void registerPath(char *path, int unregister);
+92
View File
@@ -0,0 +1,92 @@
@import Foundation;
@import CoreServices;
#import "CoreServices.h"
#import <objc/runtime.h>
#import "dlfcn.h"
void registerPath(char *path, int unregister)
{
if(!path) return;
LSApplicationWorkspace *workspace =
[LSApplicationWorkspace defaultWorkspace];
if (unregister && ![[NSFileManager defaultManager] fileExistsAtPath:[NSString stringWithUTF8String:path]]) {
LSApplicationProxy *app = [LSApplicationProxy
applicationProxyForIdentifier:[NSString stringWithUTF8String:path]];
if (app.bundleURL)
path = (char *)[[app bundleURL] fileSystemRepresentation];
}
NSString *rawPath = [NSString stringWithUTF8String:path];
rawPath = [rawPath stringByResolvingSymlinksInPath];
NSDictionary *infoPlist = [NSDictionary
dictionaryWithContentsOfFile:
[rawPath stringByAppendingPathComponent:@"Info.plist"]];
NSString *bundleID = [infoPlist objectForKey:@"CFBundleIdentifier"];
NSURL *url = [NSURL fileURLWithPath:rawPath];
if (bundleID && !unregister) {
MCMContainer *appContainer = [objc_getClass("MCMAppDataContainer")
containerWithIdentifier:bundleID
createIfNecessary:YES
existed:nil
error:nil];
NSString *containerPath = [appContainer url].path;
NSMutableDictionary *plist = [NSMutableDictionary dictionary];
[plist setObject:@"System" forKey:@"ApplicationType"];
[plist setObject:@1 forKey:@"BundleNameIsLocalized"];
[plist setObject:bundleID forKey:@"CFBundleIdentifier"];
[plist setObject:@0 forKey:@"CompatibilityState"];
if (containerPath) [plist setObject:containerPath forKey:@"Container"];
[plist setObject:@0 forKey:@"IsDeletable"];
[plist setObject:rawPath forKey:@"Path"];
NSString *pluginsPath =
[rawPath stringByAppendingPathComponent:@"PlugIns"];
NSArray *plugins = [[NSFileManager defaultManager]
contentsOfDirectoryAtPath:pluginsPath
error:nil];
NSMutableDictionary *bundlePlugins = [NSMutableDictionary dictionary];
for (NSString *pluginName in plugins) {
NSString *fullPath =
[pluginsPath stringByAppendingPathComponent:pluginName];
NSDictionary *infoPlist = [NSDictionary
dictionaryWithContentsOfFile:
[fullPath stringByAppendingPathComponent:@"Info.plist"]];
NSString *pluginBundleID =
[infoPlist objectForKey:@"CFBundleIdentifier"];
if (!pluginBundleID) continue;
MCMContainer *pluginContainer =
[objc_getClass("MCMPluginKitPluginDataContainer")
containerWithIdentifier:pluginBundleID
createIfNecessary:YES
existed:nil
error:nil];
NSString *pluginContainerPath = [pluginContainer url].path;
NSMutableDictionary *pluginPlist = [NSMutableDictionary dictionary];
[pluginPlist setObject:@"PluginKitPlugin"
forKey:@"ApplicationType"];
[pluginPlist setObject:@1 forKey:@"BundleNameIsLocalized"];
[pluginPlist setObject:pluginBundleID forKey:@"CFBundleIdentifier"];
[pluginPlist setObject:@0 forKey:@"CompatibilityState"];
[pluginPlist setObject:pluginContainerPath forKey:@"Container"];
[pluginPlist setObject:fullPath forKey:@"Path"];
[pluginPlist setObject:bundleID forKey:@"PluginOwnerBundleID"];
[bundlePlugins setObject:pluginPlist forKey:pluginBundleID];
}
[plist setObject:bundlePlugins forKey:@"_LSBundlePlugins"];
if (![workspace registerApplicationDictionary:plist]) {
fprintf(stderr, "Error: Unable to register %s\n", path);
}
} else {
if (![workspace unregisterApplication:url]) {
fprintf(stderr, "Error: Unable to unregister %s\n", path);
}
}
}
+3
View File
@@ -0,0 +1,3 @@
@import Foundation;
extern int extract(NSString* fileToExtract, NSString* extractionPath);
+87
View File
@@ -0,0 +1,87 @@
#import "unarchive.h"
#include <libarchive/archive.h>
#include <libarchive/archive_entry.h>
static int
copy_data(struct archive *ar, struct archive *aw)
{
int r;
const void *buff;
size_t size;
la_int64_t offset;
for (;;) {
r = archive_read_data_block(ar, &buff, &size, &offset);
if (r == ARCHIVE_EOF)
return (ARCHIVE_OK);
if (r < ARCHIVE_OK)
return (r);
r = archive_write_data_block(aw, buff, size, offset);
if (r < ARCHIVE_OK) {
fprintf(stderr, "%s\n", archive_error_string(aw));
return (r);
}
}
}
int extract(NSString* fileToExtract, NSString* extractionPath)
{
struct archive *a;
struct archive *ext;
struct archive_entry *entry;
int flags;
int r;
/* Select which attributes we want to restore. */
flags = ARCHIVE_EXTRACT_TIME;
flags |= ARCHIVE_EXTRACT_PERM;
flags |= ARCHIVE_EXTRACT_ACL;
flags |= ARCHIVE_EXTRACT_FFLAGS;
a = archive_read_new();
archive_read_support_format_all(a);
archive_read_support_filter_all(a);
ext = archive_write_disk_new();
archive_write_disk_set_options(ext, flags);
archive_write_disk_set_standard_lookup(ext);
if ((r = archive_read_open_filename(a, fileToExtract.UTF8String, 10240)))
return 1;
for (;;)
{
r = archive_read_next_header(a, &entry);
if (r == ARCHIVE_EOF)
break;
if (r < ARCHIVE_OK)
fprintf(stderr, "%s\n", archive_error_string(a));
if (r < ARCHIVE_WARN)
return 1;
NSString* currentFile = [NSString stringWithUTF8String:archive_entry_pathname(entry)];
NSString* fullOutputPath = [extractionPath stringByAppendingPathComponent:currentFile];
//printf("extracting %s to %s\n", currentFile.UTF8String, fullOutputPath.UTF8String);
archive_entry_set_pathname(entry, fullOutputPath.UTF8String);
r = archive_write_header(ext, entry);
if (r < ARCHIVE_OK)
fprintf(stderr, "%s\n", archive_error_string(ext));
else if (archive_entry_size(entry) > 0) {
r = copy_data(a, ext);
if (r < ARCHIVE_OK)
fprintf(stderr, "%s\n", archive_error_string(ext));
if (r < ARCHIVE_WARN)
return 1;
}
r = archive_write_finish_entry(ext);
if (r < ARCHIVE_OK)
fprintf(stderr, "%s\n", archive_error_string(ext));
if (r < ARCHIVE_WARN)
return 1;
}
archive_read_close(a);
archive_read_free(a);
archive_write_close(ext);
archive_write_free(ext);
return 0;
}