Skip to content

Commit

Permalink
Merge branch 'roothide:main' into main
Browse files Browse the repository at this point in the history
bankm1 authored Feb 21, 2024
2 parents 658a1d8 + 130867f commit 568da93
Showing 68 changed files with 2,803 additions and 481 deletions.
64 changes: 64 additions & 0 deletions .github/ISSUE_TEMPLATE/bootstrap-bug.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,64 @@
name: Bootstrap Bug
description: A bug while using the roothide Bootstrap
labels: ["bug"]
body:
- type: markdown
attributes:
value: |
Thanks for using the roothide Bootstap! If your issue can be solved with simple troubleshooting, check out these resources:
[Bootstrap README.md](https://github.com/roothide/Bootstrap/blob/main/README.md)
[Bootstrap FAQ](https://github.com/dleovl/Bootstrap/blob/faq/README.md)
[roothide Discord server](https://discord.com/invite/scqCkumAYp) (with support channels)
- type: input
id: device-model
attributes:
label: Device Model
description: What device model are you using? (Device, Chipset)
placeholder: ex. iPhone 11, A13
validations:
required: true
- type: input
id: ios-version
attributes:
label: iOS Version
description: What iOS version are you using?
placeholder: ex. 17.0
validations:
required: true
- type: input
id: bootstrap-version
attributes:
label: Bootstrap Version
description: What version of the roothide Bootstrap are you using?
placeholder: ex. 1.0
validations:
required: true
- type: input
id: serotonin-version
attributes:
label: Serotonin Version
description: What version of Serotonin are you using? (if applicable)
placeholder: ex. 1.0.1
- type: textarea
id: bugs
attributes:
label: What happened
description: Also, what did you expect to happen? How can we reproduce this?
placeholder: I did ..., but ... was supposed to happen. ... doesn't work!
validations:
required: true
- type: textarea
id: logs
attributes:
label: Log output
description: Please copy and paste any relevant log output. This will be automatically formatted into code, so no need for backticks.
render: shell
- type: checkboxes
id: acknowledgement
attributes:
label: Acknowledgement of README and FAQ
description: By submitting this issue, you acknowledge you have read both the [README](https://github.com/roothide/Bootstrap/blob/main/README.md) and the [FAQ](https://github.com/dleovl/Bootstrap/blob/faq/README.md), and neither solve the issue (nor should it be written).
options:
- label: I have read both the README and the FAQ.
required: true
4 changes: 1 addition & 3 deletions .gitignore
Original file line number Diff line number Diff line change
@@ -1,9 +1,7 @@
.theos/
packages/
.DS_Store
/basebin/
/layout/
*.xcuserstate
Bootstrap.xcodeproj/project.xcworkspace/xcuserdata/admin.xcuserdatad/UserInterfaceState.xcuserstate
Bootstrap.xcodeproj/project.xcworkspace/xcuserdata/admin.xcuserdatad/UserInterfaceState.xcuserstate
/Bootstrap.xcodeproj/project.xcworkspace/xcuserdata/admin.xcuserdatad/UserInterfaceState.xcuserstate
*.xcuserstate
3 changes: 3 additions & 0 deletions .gitmodules
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
[submodule "basebin"]
path = basebin
url = https://github.com/roothide/Bootstrap-basebin
162 changes: 156 additions & 6 deletions Bootstrap.xcodeproj/project.pbxproj

Large diffs are not rendered by default.

Original file line number Diff line number Diff line change
@@ -1,5 +1,14 @@
{
"pins" : [
{
"identity" : "fluidgradient",
"kind" : "remoteSourceControl",
"location" : "https://github.com/Cindori/FluidGradient.git",
"state" : {
"revision" : "9ddda4cf23671ef0228e88681ec6210cb3e0d7f7",
"version" : "1.0.0"
}
},
{
"identity" : "zstd",
"kind" : "remoteSourceControl",
Binary file not shown.
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
<?xml version="1.0" encoding="UTF-8"?>
<Bucket
uuid = "EFE94600-8EE3-4753-ACB3-301BC523BB0D"
type = "1"
version = "2.0">
</Bucket>
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
<dict>
<key>SchemeUserState</key>
<dict>
<key>Bootstrap.xcscheme_^#shared#^_</key>
<dict>
<key>orderHint</key>
<integer>0</integer>
</dict>
</dict>
</dict>
</plist>
1 change: 0 additions & 1 deletion Bootstrap/AppDelegate.h
Original file line number Diff line number Diff line change
@@ -13,7 +13,6 @@
+ (void)showMesage:(NSString*)msg title:(NSString*)title;

+ (void)addLogText:(NSString*)text;
+ (void)registerLogView:(UITextView*)view;

@end

34 changes: 16 additions & 18 deletions Bootstrap/AppDelegate.m
Original file line number Diff line number Diff line change
@@ -8,23 +8,9 @@ @interface AppDelegate ()

@implementation AppDelegate

UITextView* logView=nil;

+ (void)registerLogView:(UITextView*)view
{
dispatch_async(dispatch_get_main_queue(), ^{
logView = view;
logView.layoutManager.allowsNonContiguousLayout = NO;
});
}

+ (void)addLogText:(NSString*)text
{
dispatch_async(dispatch_get_main_queue(), ^{
[logView setText:[logView.text stringByAppendingString:[NSString stringWithFormat:@"%@\n",text]]];
if(logView.contentSize.height >= logView.bounds.size.height)
[logView setContentOffset:CGPointMake(0, logView.contentSize.height - logView.bounds.size.height) animated:YES];
});
[NSNotificationCenter.defaultCenter postNotificationName:@"LogMsgNotification" object:text];
}

MBProgressHUD *switchHud=nil;
@@ -64,11 +50,23 @@ + (void)showAlert:(UIAlertController*)alert {
});

dispatch_async(alertQueue, ^{

__block UIViewController* availableVC=nil;
while(!availableVC) {
dispatch_async(dispatch_get_main_queue(), ^{
UIViewController* vc = UIApplication.sharedApplication.keyWindow.rootViewController;
while(vc.presentedViewController){
vc = vc.presentedViewController;
if(vc.isBeingDismissed) return;
}
availableVC = vc;
});
if(!availableVC) usleep(1000*100);
}

__block BOOL presented = NO;
dispatch_async(dispatch_get_main_queue(), ^{
UIViewController* vc = UIApplication.sharedApplication.keyWindow.rootViewController;
while(vc.presentedViewController) vc = vc.presentedViewController;
[vc presentViewController:alert animated:YES completion:^{ presented=YES; }];
[availableVC presentViewController:alert animated:YES completion:^{ presented=YES; }];
});

while(!presented) usleep(100*1000);
50 changes: 43 additions & 7 deletions Bootstrap/AppEnabler.m
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
#import <Foundation/Foundation.h>
#include <sys/stat.h>
#include "AppList.h"
#include "common.h"

@@ -135,6 +136,7 @@ int backupApp(NSString* bundlePath)
return 0;
}

//if the app package is changed/upgraded, the directory structure may change and some paths may become invalid.
int restoreApp(NSString* bundlePath)
{
SYSLOG("restoreApp=%@", bundlePath);
@@ -200,24 +202,39 @@ int enableForApp(NSString* bundlePath)

ASSERT([fm createSymbolicLinkAtPath:[jbroot(bundlePath) stringByAppendingString:@"/.jbroot"] withDestinationPath:jbroot(@"/") error:nil]);

ASSERT(spawnBootstrap((char*[]){"/usr/bin/uicache","-p", bundlePath.UTF8String, NULL}, nil, nil) == 0);
NSString* log=nil;
NSString* err=nil;
if(spawnBootstrap((char*[]){"/usr/bin/uicache","-p", bundlePath.UTF8String, NULL}, &log, &err) != 0) {
STRAPLOG("%@\nERR:%@", log, err);
ABORT();
}
}
else if([appInfo[@"CFBundleIdentifier"] hasPrefix:@"com.apple."]
|| [NSFileManager.defaultManager fileExistsAtPath:[bundlePath stringByAppendingString:@"/../_TrollStore"]])
{
ASSERT(backupApp(bundlePath) == 0);

ASSERT([fm createSymbolicLinkAtPath:[bundlePath stringByAppendingString:@"/.jbroot"] withDestinationPath:jbroot(@"/") error:nil]);

ASSERT(spawnBootstrap((char*[]){"/usr/bin/uicache","-s","-p", rootfsPrefix(bundlePath).UTF8String, NULL}, nil, nil) == 0);

NSString* log=nil;
NSString* err=nil;
if(spawnBootstrap((char*[]){"/usr/bin/uicache","-s","-p", rootfsPrefix(bundlePath).UTF8String, NULL}, &log, &err) != 0) {
STRAPLOG("%@\nERR:%@", log, err);
ABORT();
}
}
else
{
ASSERT(backupApp(bundlePath) == 0);

ASSERT([fm createSymbolicLinkAtPath:[bundlePath stringByAppendingString:@"/.jbroot"] withDestinationPath:jbroot(@"/") error:nil]);

ASSERT(spawnBootstrap((char*[]){"/usr/bin/uicache","-s","-p", rootfsPrefix(bundlePath).UTF8String, NULL}, nil, nil) == 0);
NSString* log=nil;
NSString* err=nil;
if(spawnBootstrap((char*[]){"/usr/bin/uicache","-s","-p", rootfsPrefix(bundlePath).UTF8String, NULL}, &log, &err) != 0) {
STRAPLOG("%@\nERR:%@", log, err);
ABORT();
}
}

return 0;
@@ -242,17 +259,36 @@ int disableForApp(NSString* bundlePath)
else if([appInfo[@"CFBundleIdentifier"] hasPrefix:@"com.apple."]
|| [NSFileManager.defaultManager fileExistsAtPath:[bundlePath stringByAppendingString:@"/../_TrollStore"]])
{

struct stat st;
if(lstat([bundlePath stringByAppendingString:@"/.jbroot"].fileSystemRepresentation, &st)==0)
ASSERT([fm removeItemAtPath:[bundlePath stringByAppendingString:@"/.jbroot"] error:nil]);
if(lstat([bundlePath stringByAppendingString:@"/.prelib"].fileSystemRepresentation, &st)==0)
ASSERT([fm removeItemAtPath:[bundlePath stringByAppendingString:@"/.prelib"] error:nil]);
if(lstat([bundlePath stringByAppendingString:@"/.preload"].fileSystemRepresentation, &st)==0)
ASSERT([fm removeItemAtPath:[bundlePath stringByAppendingString:@"/.preload"] error:nil]);
if(lstat([bundlePath stringByAppendingString:@"/.rebuild"].fileSystemRepresentation, &st)==0)
ASSERT([fm removeItemAtPath:[bundlePath stringByAppendingString:@"/.rebuild"] error:nil]);

ASSERT(restoreApp(bundlePath) == 0);
ASSERT([fm removeItemAtPath:[bundlePath stringByAppendingString:@"/.jbroot"] error:nil]);

ASSERT(spawnBootstrap((char*[]){"/usr/bin/uicache","-s","-p", rootfsPrefix(bundlePath).UTF8String, NULL}, nil, nil) == 0);
}
else
{
//should be an appstored app

ASSERT(restoreApp(bundlePath) == 0);
struct stat st;
if(lstat([bundlePath stringByAppendingString:@"/.jbroot"].fileSystemRepresentation, &st)==0)
ASSERT([fm removeItemAtPath:[bundlePath stringByAppendingString:@"/.jbroot"] error:nil]);
if(lstat([bundlePath stringByAppendingString:@"/.prelib"].fileSystemRepresentation, &st)==0)
ASSERT([fm removeItemAtPath:[bundlePath stringByAppendingString:@"/.prelib"] error:nil]);
if(lstat([bundlePath stringByAppendingString:@"/.preload"].fileSystemRepresentation, &st)==0)
ASSERT([fm removeItemAtPath:[bundlePath stringByAppendingString:@"/.preload"] error:nil]);
if(lstat([bundlePath stringByAppendingString:@"/.rebuild"].fileSystemRepresentation, &st)==0)
ASSERT([fm removeItemAtPath:[bundlePath stringByAppendingString:@"/.rebuild"] error:nil]);

ASSERT([fm removeItemAtPath:[bundlePath stringByAppendingString:@"/.jbroot"] error:nil]);
ASSERT(restoreApp(bundlePath) == 0);

//unregister or respring to keep app's icon on home screen
ASSERT(spawnBootstrap((char*[]){"/usr/bin/uicache","-u", rootfsPrefix(bundlePath).UTF8String, NULL}, nil, nil) == 0);
45 changes: 35 additions & 10 deletions Bootstrap/AppViewController.m
Original file line number Diff line number Diff line change
@@ -76,7 +76,7 @@ - (void)viewDidLoad {
self.tableView = [[UITableView alloc] initWithFrame:self.view.bounds style:UITableViewStyleInsetGrouped];
self.tableView.tableFooterView = [[UIView alloc] init];

[self setTitle:Localized(@"Tweak Enabler")];
[self setTitle:Localized(@"Enable Tweak for App")];

isFiltered = false;

@@ -127,6 +127,28 @@ - (void)viewWillAppear:(BOOL)animated {
[self.tableView.refreshControl endRefreshing];
}

-(BOOL)tweakEnabled:(AppList*)app {
struct stat st;
if(lstat([app.bundleURL.path stringByAppendingPathComponent:@".jbroot"].fileSystemRepresentation, &st)==0) {
return YES;
}

if(!isDefaultInstallationPath(app.bundleURL.path)) {
return NO;
}

NSString* uuidPath = [app.bundleURL.path stringByDeletingLastPathComponent];
NSString* backupFlag = [uuidPath stringByAppendingPathComponent:@".appbackup"];
NSString* backupPath = [[uuidPath stringByAppendingPathComponent:app.bundleURL.path.lastPathComponent] stringByAppendingPathExtension:@"appbackup"];
SYSLOG("uuidPath=%@, backupFlag=%@, backupPath=%@", uuidPath, backupFlag, backupPath);
if([NSFileManager.defaultManager fileExistsAtPath:backupFlag] && [NSFileManager.defaultManager fileExistsAtPath:backupPath]) {
//if the app has been successfully backed up but failed to enable tweak injection for some reason, or the app bundle is overwritten, we will still show that tweak injection has been enabled so that the user will have the chance to restore the app in appenabler
return YES;
}

return NO;
}

- (void)updateData:(BOOL)sort {
NSMutableArray* applications = [NSMutableArray new];
PrivateApi_LSApplicationWorkspace* _workspace = [NSClassFromString(@"LSApplicationWorkspace") new];
@@ -155,6 +177,10 @@ - (void)updateData:(BOOL)sort {
[app.bundleURL.path stringByAppendingString:@"/.TrollStorePresistenceHelper"]])
continue;

if([NSFileManager.defaultManager fileExistsAtPath:
[app.bundleURL.path stringByAppendingString:@"/.Bootstrap"]])
continue;

if([app.bundleURL.path.lastPathComponent isEqualToString:@"TrollStore.app"])
continue;

@@ -171,15 +197,16 @@ - (void)updateData:(BOOL)sort {
if(sort)
{
NSArray *appsSortedByName = [applications sortedArrayUsingComparator:^NSComparisonResult(AppList *app1, AppList *app2) {
struct stat st;
BOOL enabled1 = lstat([app1.bundleURL.path stringByAppendingPathComponent:@".jbroot"].fileSystemRepresentation, &st)==0;
BOOL enabled2 = lstat([app2.bundleURL.path stringByAppendingPathComponent:@".jbroot"].fileSystemRepresentation, &st)==0;
if(enabled1 || enabled2) {

BOOL enabled1 = [self tweakEnabled:app1];
BOOL enabled2 = [self tweakEnabled:app2];

if((enabled1&&!enabled2) || (!enabled1&&enabled2)) {
return [@(enabled2) compare:@(enabled1)];
}

if(app1.isHiddenApp || app2.isHiddenApp) {
return [@(app1.isHiddenApp) compare:@(app2.isHiddenApp)];
return (enabled1&&enabled2) ? [@(app2.isHiddenApp) compare:@(app1.isHiddenApp)] : [@(app1.isHiddenApp) compare:@(app2.isHiddenApp)];
}

return [app1.name localizedStandardCompare:app2.name];
@@ -281,9 +308,7 @@ - (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(N
if([unsupportedBundleIDs containsObject:app.bundleIdentifier])
theSwitch.enabled = NO;

struct stat st;
BOOL enabled = lstat([app.bundleURL.path stringByAppendingPathComponent:@".jbroot"].fileSystemRepresentation, &st)==0;
[theSwitch setOn:enabled];
[theSwitch setOn:[self tweakEnabled:app]];
[theSwitch addTarget:self action:@selector(switchChanged:) forControlEvents:UIControlEventValueChanged];

cell.accessoryView = theSwitch;
@@ -320,7 +345,7 @@ - (void)switchChanged:(id)sender {
}

if(status != 0) {
[AppDelegate showMesage:[NSString stringWithFormat:@"%@\n\nstderr:\n%@",log,err] title:[NSString stringWithFormat:@"code(%d)",status]];
[AppDelegate showMesage:[NSString stringWithFormat:@"%@\nstderr:\n%@",log,err] title:[NSString stringWithFormat:@"error(%d)",status]];
}

killAllForApp(app.bundleURL.path.UTF8String);
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
21 changes: 21 additions & 0 deletions Bootstrap/Assets.xcassets/Bootstrap.imageset/Contents.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
{
"images" : [
{
"filename" : "Bootstrap.png",
"idiom" : "universal",
"scale" : "1x"
},
{
"idiom" : "universal",
"scale" : "2x"
},
{
"idiom" : "universal",
"scale" : "3x"
}
],
"info" : {
"author" : "xcode",
"version" : 1
}
}
Loading

0 comments on commit 568da93

Please sign in to comment.