Skip to content

Commit

Permalink
Updated to v1.0.7
Browse files Browse the repository at this point in the history
- Added support for iOS 15 and Rootless
- Refactored tweaksettings-utility with support for forking child processes
  • Loading branch information
CreatureSurvive committed May 6, 2023
1 parent 3dd6925 commit 4162605
Show file tree
Hide file tree
Showing 18 changed files with 315 additions and 72 deletions.
13 changes: 10 additions & 3 deletions Makefile
Original file line number Diff line number Diff line change
@@ -1,5 +1,11 @@
ifeq ($(THEOS_PACKAGE_SCHEME),rootless)
export TARGET = iphone:clang:14.4:15.0
export ARCHS = arm64
TweakSettings_XCODEFLAGS = GCC_PREPROCESSOR_DEFINITIONS='THEOS_PACKAGE_INSTALL_PREFIX=\"$(THEOS_PACKAGE_INSTALL_PREFIX)\"'
else
export TARGET = iphone:clang:14.4:10.0
export ARCHS = armv7 arm64
endif

DEBUG = 1
DEBUG_EXT =
Expand All @@ -14,7 +20,7 @@ include $(THEOS)/makefiles/common.mk

LAUNCH_URL =
XCODEPROJ_NAME = TweakSettings
TweakSettings_XCODEFLAGS = PACKAGE_VERSION='@\"$(THEOS_PACKAGE_BASE_VERSION)\"'
TweakSettings_XCODEFLAGS += PACKAGE_VERSION='@\"$(THEOS_PACKAGE_BASE_VERSION)\"'
TweakSettings_CODESIGN_FLAGS = -SResources/entitlements.plist

include $(THEOS_MAKE_PATH)/xcodeproj.mk
Expand All @@ -27,7 +33,8 @@ after-stage::
$(ECHO_NOTHING)rm -f $(THEOS_STAGING_DIR)/Applications/TweakSettings.app/Localizable.strings$(ECHO_END)
$(ECHO_NOTHING)/usr/libexec/PlistBuddy -c "Set :CFBundleVersion ${THEOS_PACKAGE_BASE_VERSION}" "${THEOS_STAGING_DIR}/Applications/${XCODEPROJ_NAME}.app/Info.plist"$(ECHO_END)
$(ECHO_NOTHING)/usr/libexec/PlistBuddy -c "Set :CFBundleShortVersionString ${PACKAGE_VERSION}" "${THEOS_STAGING_DIR}/Applications/${XCODEPROJ_NAME}.app/Info.plist"$(ECHO_END)
@echo "Set bundle version to: ${PACKAGE_VERSION}"
$(ECHO_BEGIN)$(PRINT_FORMAT_MAGENTA) "Set bundle version to: ${PACKAGE_VERSION}"$(ECHO_END)
$(ECHO_BEGIN)$(PRINT_FORMAT_MAGENTA) "Built for $(or $(THEOS_PACKAGE_SCHEME),rootful)"$(ECHO_END)

after-install::
install.exec "killall -9 ${XCODEPROJ_NAME}; uicache -p /Applications/${XCODEPROJ_NAME}.app; uiopen tweaks:$(LAUNCH_URL)"
install.exec "killall -9 ${XCODEPROJ_NAME}; uicache -p $(THEOS_PACKAGE_INSTALL_PREFIX)/Applications/${XCODEPROJ_NAME}.app; uiopen tweaks:$(LAUNCH_URL)"
Binary file not shown.
Binary file not shown.
22 changes: 22 additions & 0 deletions Resources/entitlements.plist
Original file line number Diff line number Diff line change
Expand Up @@ -36,6 +36,28 @@
<key>com.apple.private.security.storage.AppDataContainers</key>
<true/>


<key>com.apple.private.MobileContainerManager.allowed</key>
<true/>
<key>com.apple.private.MobileContainerManager.otherIdLookup</key>
<true/>
<key>com.apple.private.MobileContainerManager.otherIdentifierLookup</key>
<true/>
<key>com.apple.private.MobileContainerManager.userManagedAssets</key>
<true/>

<key>com.apple.springboard.opensensitiveurl</key>
<true/>
<key>com.apple.springboard.presentPowerDownUI</key>
<true/>

<key>com.apple.frontboard.delete-application-snapshots</key>
<true/>
<key>com.apple.frontboard.shutdown</key>
<true/>
<key>com.apple.frontboardservices.display-layout-monitor</key>
<true/>

<!-- Fix EAGLContext crash when loading custom images on iOS 14.x -->
<key>com.apple.security.iokit-user-client-class</key>
<array>
Expand Down
66 changes: 66 additions & 0 deletions TweakSettings-App/NSTask.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,66 @@
#import <Foundation/NSObject.h>

@class NSString, NSArray, NSDictionary;

@interface NSTask : NSObject

// Create an NSTask which can be run at a later time
// An NSTask can only be run once. Subsequent attempts to
// run an NSTask will raise.
// Upon task death a notification will be sent
// { Name = NSTaskDidTerminateNotification; object = task; }
//

- (_Nullable instancetype)init;

// set parameters
// these methods can only be done before a launch
// if not set, use current
// if not set, use current

// set standard I/O channels; may be either an NSFileHandle or an NSPipe
- (void)setStandardInput:(id _Nullable)input;
- (void)setStandardOutput:(id _Nullable)output;
- (void)setStandardError:(id _Nullable)error;

// get parameters
@property (NS_NONATOMIC_IOSONLY, copy) NSString *_Nullable launchPath;
@property (NS_NONATOMIC_IOSONLY, copy) NSArray *_Nullable arguments;
@property (NS_NONATOMIC_IOSONLY, copy) NSDictionary *_Nullable environment;
@property (NS_NONATOMIC_IOSONLY, copy) NSString *_Nullable currentDirectoryPath;
@property(NS_NONATOMIC_IOSONLY, copy) NSURL *_Nullable currentDirectoryURL;

// get standard I/O channels; could be either an NSFileHandle or an NSPipe
- (id _Nullable)standardInput;
- (id _Nullable)standardOutput;
- (id _Nullable)standardError;

// actions
- (void)launch;

- (void)interrupt; // Not always possible. Sends SIGINT.
- (void)terminate; // Not always possible. Sends SIGTERM.

@property (NS_NONATOMIC_IOSONLY, readonly) BOOL suspend;
@property (NS_NONATOMIC_IOSONLY, readonly) BOOL resume;

// status
@property (NS_NONATOMIC_IOSONLY, readonly) int processIdentifier;
@property (NS_NONATOMIC_IOSONLY, getter = isRunning, readonly) BOOL running;

@property (NS_NONATOMIC_IOSONLY, readonly) int terminationStatus;
@property (copy, nonnull) void (^terminationHandler)(NSTask *_Nonnull);

@end

@interface NSTask (NSTaskConveniences)

+ (NSTask *_Nullable)launchedTaskWithLaunchPath:(NSString *_Nonnull)path arguments:(NSArray *_Nullable)arguments;
// convenience; create and launch

- (void)waitUntilExit;
// poll the runLoop in defaultMode until task completes

@end

FOUNDATION_EXPORT NSString *_Nullable const NSTaskDidTerminateNotification;
15 changes: 0 additions & 15 deletions TweakSettings-App/TS-Prefix.pch
Original file line number Diff line number Diff line change
Expand Up @@ -73,19 +73,4 @@ NS_INLINE __unused NSArray *ARRAY_WITH_PLIST(NSString *path) {
return ARRAY_WITH_PLIST_OPTIONS(path, NSPropertyListImmutable);
}

NS_INLINE __unused int STATUS_FOR_COMMAND(NSString *command) {
FILE *proc = popen(command.UTF8String, "r");

if (!proc) {return EXIT_FAILURE;}

int size = 1024;
char data[size];

while (fgets(data, size, proc) != NULL) {}

int status = pclose(proc);

return status;
}

#endif /* TS_Prefix_pch */
2 changes: 1 addition & 1 deletion TweakSettings-App/TSOptionsController.m
Original file line number Diff line number Diff line change
Expand Up @@ -90,7 +90,7 @@ - (void)_openLink:(PSSpecifier *)specifier {
- (NSArray <PSSpecifier *> *)_footerSpecifiers {

PSSpecifier *developerGroupSpecifier = [PSSpecifier emptyGroupSpecifier];
[developerGroupSpecifier setProperty:@"CreatureCoding © 2021" forKey:PSFooterTextGroupKey];
[developerGroupSpecifier setProperty:@"CreatureCoding © 2023" forKey:PSFooterTextGroupKey];
[developerGroupSpecifier setProperty:@1 forKey:PSFooterAlignmentGroupKey];

PSSpecifier *changelogSpecifier = [PSSpecifier preferenceSpecifierNamed:@"Changelog" target:self set:nil get:nil detail:TSChangelogController.class cell:PSLinkCell edit:nil];
Expand Down
15 changes: 8 additions & 7 deletions TweakSettings-App/TSPackageUtility.m
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@

#import "TSPackageUtility.h"
#import "libprefs.h"
#import "rootless.h"

#pragma mark - LIBPREFS Shim

Expand All @@ -36,9 +37,9 @@ BOOL PREFERENCE_FILTER_PASSES_ENVIRONMENT_CHECKS(NSDictionary *filter) {
if (isBundle) {
NSFileManager *fileManger = NSFileManager.defaultManager;
if (![fileManger fileExistsAtPath:bundlePath])
bundlePath = [NSString stringWithFormat:@"/Library/PreferenceBundles/%@.bundle", bundleName];
bundlePath = [NSString stringWithFormat:ROOT_PATH_NS(@"/Library/PreferenceBundles/%@.bundle"), bundleName];
if (![fileManger fileExistsAtPath:bundlePath])
bundlePath = [NSString stringWithFormat:@"/System/Library/PreferenceBundles/%@.bundle", bundleName];
bundlePath = [NSString stringWithFormat:ROOT_PATH_NS(@"/System/Library/PreferenceBundles/%@.bundle"), bundleName];
if (![fileManger fileExistsAtPath:bundlePath]) {
return nil;
}
Expand Down Expand Up @@ -91,14 +92,14 @@ @implementation TSPackageUtility {

+ (NSArray<PSSpecifier *> *)loadTweakSpecifiersInController:(PSListController *)controller {
NSMutableArray *preferenceSpecifiers = [NSMutableArray new];
NSArray *preferenceBundlePaths = [NSFileManager.defaultManager subpathsOfDirectoryAtPath:@"/Library/PreferenceLoader/Preferences" error:nil];
NSArray *preferenceBundlePaths = [NSFileManager.defaultManager subpathsOfDirectoryAtPath:ROOT_PATH_NS(@"/Library/PreferenceLoader/Preferences") error:nil];
NSMutableArray *searchableItems = [NSMutableArray new];

for (NSString *item in preferenceBundlePaths)
{
if (![item.pathExtension isEqualToString:@"plist"]) continue;

NSString *plistPath = [NSString stringWithFormat:@"/Library/PreferenceLoader/Preferences/%@", item];
NSString *plistPath = [NSString stringWithFormat:ROOT_PATH_NS(@"/Library/PreferenceLoader/Preferences/%@"), item];
NSDictionary *plist = DICTIONARY_WITH_PLIST(plistPath);

if (!plist[@"entry"]) continue;
Expand All @@ -107,8 +108,8 @@ @implementation TSPackageUtility {

NSString *bundlePath = [plistPath stringByDeletingLastPathComponent];
NSString *title = [item.lastPathComponent stringByDeletingPathExtension];
BOOL customInstall = access("/var/lib/dpkg/info/com.artikus.preferenceloader.list", F_OK) == 0
|| access("/var/lib/dpkg/info/com.creaturecoding.preferred.list", F_OK) == 0;
BOOL customInstall = access(ROOT_PATH("/var/lib/dpkg/info/com.artikus.preferenceloader.list"), F_OK) == 0
|| access(ROOT_PATH("/var/lib/dpkg/info/com.creaturecoding.preferred.list"), F_OK) == 0;

NSArray *itemSpecifiers = !customInstall
? SPECIFIERS_FROM_ENTRY(plist[@"entry"], bundlePath, title, controller)
Expand All @@ -123,7 +124,7 @@ @implementation TSPackageUtility {
[specifier setProperty:[UIImage imageNamed:@"tweak"] forKey:PSIconImageKey];
}

CSSearchableItemAttributeSet *attributeSet = [[CSSearchableItemAttributeSet alloc] initWithItemContentType:(NSString *) kUTTypeImage];
CSSearchableItemAttributeSet *attributeSet = [[CSSearchableItemAttributeSet alloc] init];
attributeSet.title = specifier.name;
attributeSet.contentDescription = [NSString stringWithFormat:@"Tweak Settings \u2192 %@", specifier.name];
attributeSet.thumbnailData = UIImagePNGRepresentation([specifier propertyForKey:PSIconImageKey]);
Expand Down
8 changes: 8 additions & 0 deletions TweakSettings-App/TSUtilityActionManager.h
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,12 @@
@class UIAlertController;
@class UIAlertAction;

struct TaskResult {
int status;
__strong NSString *output;
__strong NSString *error;
};

extern NSString *const TSActionTypeRespring;
extern NSString *const TSActionTypeSafemode;
extern NSString *const TSActionTypeUICache;
Expand All @@ -20,12 +26,14 @@ extern NSString *const TSActionTypeReboot;
extern NSString *const TSActionTypeUserspaceReboot;
extern NSString *const TSActionTypeTweakInject;

extern struct TaskResult ExecuteCommand(NSString *command);
extern NSString *TitleForActionType(NSString *type);
extern NSString *SubtitleForActionType(NSString *type);
extern BOOL CanRunWithoutConfirmation(NSString *actionType);
extern int HandleActionForType(NSString *actionType);
extern UIAlertController *ActionAlertForType(NSString *actionType);
extern UIAlertController *ActionListAlert(void);
extern UIMenu *ActionListMenu(void) API_AVAILABLE(ios(13.0));
extern NSString *CommandForActionType(NSString *actionType);

#endif /* TSActionType_h */
68 changes: 56 additions & 12 deletions TweakSettings-App/TSUtilityActionManager.m
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,8 @@
#import "TSUtilityActionManager.h"
#import "Localizable.h"
#import "TSAppDelegate.h"
#import "rootless.h"
#import "NSTask.h"

NSString *const TSActionTypeRespring = @"respring";
NSString *const TSActionTypeSafemode = @"safemode";
Expand All @@ -19,6 +21,50 @@
NSString *const TSActionTypeUserspaceReboot = @"usreboot";
NSString *const TSActionTypeTweakInject = @"tweakinject";

struct TaskResult ExecuteCommand(NSString *command) {
NSTask *task = [[NSTask alloc] init];
[task setLaunchPath:ROOT_PATH_NS(@"/bin/sh")];
[task setArguments:@[@"-c", command]];

NSPipe *outputPipe = [NSPipe pipe];
[task setStandardOutput:outputPipe];

NSPipe *errorPipe = [NSPipe pipe];
[task setStandardError:errorPipe];

[task launch];
[task waitUntilExit];

NSData *errorData;
NSData *outputData;
NSString *output;
NSString *error;

if (@available(iOS 13.0, *)) {
outputData = [[[task standardOutput] fileHandleForReading] readDataToEndOfFileAndReturnError:nil];
errorData = [[[task standardError] fileHandleForReading] readDataToEndOfFileAndReturnError:nil];
} else {
outputData = [[[task standardOutput] fileHandleForReading] readDataToEndOfFile];
errorData = [[[task standardError] fileHandleForReading] readDataToEndOfFile];
}

if (outputData && outputData.length > 0) {
output = [[NSString alloc] initWithData:outputData encoding:NSASCIIStringEncoding];
}

if (errorData && errorData.length > 0) {
error = [[NSString alloc] initWithData:errorData encoding:NSASCIIStringEncoding];
NSLog(@"TweakSettings: TASK INPUT: %@ ERROR: %@, STATUS: %d", task.arguments.lastObject, error, task.terminationStatus);
}

struct TaskResult result;
result.status = task.terminationStatus;
result.output = output;
result.error = error;

return result;
}

NSString *TitleForActionType(NSString *type) {
if ([type isEqualToString:TSActionTypeRespring]) return NSLocalizedString(RESPRING_TITLE_KEY, nil);
if ([type isEqualToString:TSActionTypeSafemode]) return NSLocalizedString(SAFEMODE_TITLE_KEY, nil);
Expand Down Expand Up @@ -53,16 +99,7 @@ int HandleActionForType(NSString *actionType) {

if (!actionType || !actionType.length) return EXIT_FAILURE;

int status = STATUS_FOR_COMMAND([NSString stringWithFormat:@"/usr/bin/tweaksettings-utility --%@", actionType]);
if (status == EXIT_SUCCESS && [actionType isEqualToString:TSActionTypeTweakInject]) {
if (access("/etc/rc.d/substrate", F_OK) == 0) {
if (STATUS_FOR_COMMAND(@"/usr/bin/tweaksettings-utility --substrated") == EXIT_SUCCESS) {
STATUS_FOR_COMMAND(@"/usr/bin/tweaksettings-utility --respring");
}
} else {
STATUS_FOR_COMMAND(@"/usr/bin/tweaksettings-utility --respring");
}
}
int status = ExecuteCommand(CommandForActionType(actionType)).status;

return status;
}
Expand All @@ -83,7 +120,7 @@ int HandleActionForType(NSString *actionType) {

UIAlertController *ActionListAlert(void) {

BOOL userspace_supported = access("/odyssey/jailbreakd.plist", F_OK) == 0 || access("/taurine/jailbreakd.plist", F_OK) == 0;
BOOL userspace_supported = access(ROOT_PATH("/odyssey/jailbreakd.plist"), F_OK) == 0 || access(ROOT_PATH("/taurine/jailbreakd.plist"), F_OK) == 0;
UIAlertController *controller = [UIAlertController alertControllerWithTitle:nil message:nil preferredStyle:UIAlertControllerStyleActionSheet];

[controller addAction:[UIAlertAction actionWithTitle:NSLocalizedString(RESPRING_TITLE_KEY, nil) style:UIAlertActionStyleDefault handler:^(UIAlertAction *action) {
Expand Down Expand Up @@ -117,7 +154,10 @@ int HandleActionForType(NSString *actionType) {
UIMenu *ActionListMenu(void) API_AVAILABLE(ios(13.0)) {

NSMutableArray *menuActions = [NSMutableArray new];
BOOL userspace_supported = access("/odyssey/jailbreakd.plist", F_OK) == 0 || access("/taurine/jailbreakd.plist", F_OK) == 0;
BOOL userspace_supported =
access(ROOT_PATH("/odyssey/jailbreakd.plist"), F_OK) == 0 ||
access(ROOT_PATH("/taurine/jailbreakd.plist"), F_OK) == 0 ||
access(ROOT_PATH("/.installed_dopamine"), F_OK) == 0;

[menuActions addObject:[UIAction actionWithTitle:NSLocalizedString(RESPRING_TITLE_KEY, nil) image:nil identifier:nil handler:^(__kindof UIAction *action) {
[APP_DELEGATE handleActionForType:TSActionTypeRespring];
Expand All @@ -144,4 +184,8 @@ int HandleActionForType(NSString *actionType) {
}]];

return [UIMenu menuWithTitle:@"" children:menuActions];
}

NSString *CommandForActionType(NSString *actionType) {
return [NSString stringWithFormat:ROOT_PATH_NS(@"/usr/bin/tweaksettings-utility --%@"), actionType];
}
5 changes: 3 additions & 2 deletions TweakSettings-App/main.m
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@
#import <dlfcn.h>

#import "TSAppDelegate.h"
#import "rootless.h"


int main(int argc, char *argv[]) {
Expand All @@ -21,10 +22,10 @@ int main(int argc, char *argv[]) {
// Setup code that might create autoreleased objects goes here.
appDelegateClassName = NSStringFromClass([TSAppDelegate class]);

NSArray *librariesToLoad = ARRAY_WITH_PLIST(@"/Applications/TweakSettings.app/libraries.plist");
NSArray *librariesToLoad = ARRAY_WITH_PLIST(ROOT_PATH_NS(@"/Applications/TweakSettings.app/libraries.plist"));

for (NSString *path in librariesToLoad) {
dlopen(path.UTF8String, RTLD_NOW);
dlopen(ROOT_PATH_NS_VAR(path).UTF8String, RTLD_NOW);
}

}
Expand Down
11 changes: 11 additions & 0 deletions TweakSettings-App/rootless.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
#ifdef THEOS_PACKAGE_INSTALL_PREFIX
#define ROOT_PATH(cPath) THEOS_PACKAGE_INSTALL_PREFIX cPath
#define ROOT_PATH_NS(path) @THEOS_PACKAGE_INSTALL_PREFIX path
#define ROOT_PATH_NS_VAR(path) [@THEOS_PACKAGE_INSTALL_PREFIX stringByAppendingPathComponent:path]
#define ROOT_PATH_VAR(cPath) ROOT_PATH_NS_VAR(@cPath).fileSystemRepresentation
#else
#define ROOT_PATH(cPath) cPath
#define ROOT_PATH_NS(path) path
#define ROOT_PATH_NS_VAR(path) path
#define ROOT_PATH_VAR(cPath) cPath
#endif
Loading

0 comments on commit 4162605

Please sign in to comment.