Skip to content

Commit

Permalink
fix khanhduytran0#146, khanhduytran0#329, #35, crash on removing cont…
Browse files Browse the repository at this point in the history
…ainer, improve jit popup, allow copying bundle ids
  • Loading branch information
hugeBlack committed Feb 4, 2025
1 parent b60e25e commit ad24bb6
Show file tree
Hide file tree
Showing 13 changed files with 84 additions and 34 deletions.
22 changes: 13 additions & 9 deletions LiveContainerSwiftUI/LCAppBanner.swift
Original file line number Diff line number Diff line change
Expand Up @@ -253,22 +253,26 @@ struct LCAppBanner : View {

var JITEnablingModal : some View {
NavigationView {
VStack{
Text("lc.appBanner.waitForJitMsg".loc)
ScrollViewReader { proxy in
ScrollView {
ScrollViewReader { proxy in
ScrollView {
Text("lc.appBanner.waitForJitMsg".loc)
.padding(.vertical)
.id(0)

HStack {
Text(model.jitLog)
.font(.system(size: 12).monospaced())
.fixedSize(horizontal: false, vertical: false)
.textSelection(.enabled)
Spacer()
.id(0)
}
.onAppear {
proxy.scrollTo(0)
}

}
.frame(maxWidth: .infinity)
.padding(.horizontal)
.onAppear {
proxy.scrollTo(0)
}
.padding()
}
.navigationTitle("lc.appBanner.waitForJitTitle".loc)
.navigationBarTitleDisplayMode(.inline)
Expand Down
11 changes: 10 additions & 1 deletion LiveContainerSwiftUI/LCAppInfo.m
Original file line number Diff line number Diff line change
Expand Up @@ -268,7 +268,7 @@ - (void)patchExecAndSignIfNeedWithCompletionHandler:(void(^)(bool success, NSStr
}

// Update patch
int currentPatchRev = 5;
int currentPatchRev = 6;
if ([info[@"LCPatchRevision"] intValue] < currentPatchRev) {
NSString *execPath = [NSString stringWithFormat:@"%@/%@", appPath, _infoPlist[@"CFBundleExecutable"]];
NSString *error = LCParseMachO(execPath.UTF8String, ^(const char *path, struct mach_header_64 *header) {
Expand All @@ -279,6 +279,15 @@ - (void)patchExecAndSignIfNeedWithCompletionHandler:(void(^)(bool success, NSStr
return;
}
info[@"LCPatchRevision"] = @(currentPatchRev);
forceSign = true;
// remove ZSign cache since hash is changed after upgrading patch
NSFileManager* fm = NSFileManager.defaultManager;
NSString* cachePath = [appPath stringByAppendingPathComponent:@"zsign_cache.json"];
if([fm fileExistsAtPath:cachePath]) {
NSError* err;
[fm removeItemAtPath:cachePath error:&err];
}

[self save];
}

Expand Down
1 change: 1 addition & 0 deletions LiveContainerSwiftUI/LCAppListView.swift
Original file line number Diff line number Diff line change
Expand Up @@ -67,6 +67,7 @@ struct LCAppListView : View, LCAppBannerDelegate, LCAppModelDelegate {
label: {
EmptyView()
})
.hidden()

GeometryReader { g in
ProgressView(value: uiInstallProgressPercentage)
Expand Down
8 changes: 5 additions & 3 deletions LiveContainerSwiftUI/LCAppSettingsView.swift
Original file line number Diff line number Diff line change
Expand Up @@ -47,6 +47,7 @@ struct LCAppSettingsView : View{
Text(appInfo.relativeBundlePath)
.foregroundColor(.gray)
.multilineTextAlignment(.trailing)
.textSelection(.enabled)
}
if !model.uiIsShared {
Menu {
Expand Down Expand Up @@ -99,11 +100,11 @@ struct LCAppSettingsView : View{

Section {
List{
ForEach($model.uiContainers, id:\.self) { $container in
ForEach(model.uiContainers.indices, id:\.self) { i in
NavigationLink {
LCContainerView(container: $container, uiDefaultDataFolder: $model.uiDefaultDataFolder, delegate: self)
LCContainerView(container: model.uiContainers[i], uiDefaultDataFolder: $model.uiDefaultDataFolder, delegate: self)
} label: {
Text(container.name)
Text(model.uiContainers[i].name)
}
}
}
Expand Down Expand Up @@ -606,6 +607,7 @@ extension LCAppSettingsView : LCContainerViewDelegate {
func saveContainer(container: LCContainer) {
container.makeLCContainerInfoPlist(appIdentifier: appInfo.bundleIdentifier()!, keychainGroupId: container.keychainGroupId)
appInfo.containers = model.uiContainers
model.objectWillChange.send()
}

func getSettingsBundle() -> Bundle? {
Expand Down
10 changes: 5 additions & 5 deletions LiveContainerSwiftUI/LCContainerView.swift
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,7 @@ protocol LCContainerViewDelegate {
}

struct LCContainerView : View {
@Binding var container : LCContainer
@ObservedObject var container : LCContainer
let delegate : LCContainerViewDelegate
@Binding var uiDefaultDataFolder : String?
@State var settingsBundle : Bundle? = nil
Expand All @@ -35,10 +35,10 @@ struct LCContainerView : View {
@State private var successShow = false
@State private var successInfo = ""

init(container: Binding<LCContainer>, uiDefaultDataFolder : Binding<String?>, delegate: LCContainerViewDelegate) {
self._container = Binding(projectedValue: container)
init(container: LCContainer, uiDefaultDataFolder : Binding<String?>, delegate: LCContainerViewDelegate) {
self._container = ObservedObject(initialValue: container)
self.delegate = delegate
self._typingContainerName = State(initialValue: container.wrappedValue.name)
self._typingContainerName = State(initialValue: container.name)
self._uiDefaultDataFolder = Binding(projectedValue: uiDefaultDataFolder)
}

Expand All @@ -51,7 +51,7 @@ struct LCContainerView : View {
TextField("lc.container.containerName".loc, text: $typingContainerName)
.multilineTextAlignment(.trailing)
.onSubmit {
$container.name.wrappedValue = typingContainerName
container.name = typingContainerName
saveContainer()
}
}
Expand Down
2 changes: 2 additions & 0 deletions LiveContainerSwiftUI/LCJITLessDiagnoseView.swift
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,7 @@ struct LCEntitlementView : View {
Spacer()
Text(Bundle.main.bundleIdentifier ?? "lc.common.unknown".loc)
.foregroundStyle(entitlementReadSuccess && teamId != nil ? (isBundleIdCorrect ? .green : .red): .gray)
.textSelection(.enabled)
}

if entitlementReadSuccess {
Expand Down Expand Up @@ -176,6 +177,7 @@ struct LCJITLessDiagnoseView : View {
Spacer()
Text(Bundle.main.bundleIdentifier ?? "lc.common.unknown".loc)
.foregroundStyle(.gray)
.textSelection(.enabled)
}
if !sharedModel.certificateImported {
HStack {
Expand Down
9 changes: 5 additions & 4 deletions LiveContainerSwiftUI/LCMachOUtils.m
Original file line number Diff line number Diff line change
Expand Up @@ -74,11 +74,12 @@ void LCPatchExecSlice(const char *path, struct mach_header_64 *header) {
// Patch __PAGEZERO to map just a single zero page, fixing "out of address space"
struct segment_command_64 *seg = (struct segment_command_64 *)imageHeaderPtr;
assert(seg->cmd == LC_SEGMENT_64);
if (seg->vmaddr == 0) {
assert(seg->vmsize == 0x100000000);
seg->vmaddr = 0x100000000 - 0x4000;
seg->vmsize = 0x4000;
if (strcmp(seg->segname, "__PAGENOPE")) {
seg->vmaddr = 0;
seg->vmsize = 0;
strcpy(seg->segname, "__PAGENOPE");
}

}

NSString *LCParseMachO(const char *path, LCParseMachOCallback callback) {
Expand Down
13 changes: 11 additions & 2 deletions LiveContainerSwiftUI/Shared.swift
Original file line number Diff line number Diff line change
Expand Up @@ -841,12 +841,21 @@ extension LCUtils {
}
if statusResponse.done {
onServerMessage?("Server done.")
if launchAppResponse.mounting {
onServerMessage?("Run the app again to enable JIT.")
}

return true
}
if statusResponse.in_progress {
onServerMessage?("JIT enabling in progress.")
if launchAppResponse.mounting {
onServerMessage?("JIT enabling in progress. (Attempt \(i + 1)/\(maxTries))")
} else {
onServerMessage?("Mounting in progress. (Attempt \(i + 1)/\(maxTries))")
}

} else {
onServerMessage?("Your app will launch soon! You are position \(launchAppResponse.position ?? -1) in the queue. (Try \(i + 1)/\(maxTries))")
onServerMessage?("Your app will launch soon! You are position \(launchAppResponse.position ?? -1) in the queue. (Attempt \(i + 1)/\(maxTries))")
}

}
Expand Down
4 changes: 4 additions & 0 deletions Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -23,8 +23,12 @@ include $(THEOS_MAKE_PATH)/aggregate.mk

# Make the executable name longer so we have space to overwrite it with the guest app's name
before-package::
ifeq ($(shell sw_vers -productName),macOS)
@/Applications/Xcode.app/Contents/Developer/usr/bin/xcstringstool compile ./LiveContainerSwiftUI/Localizable.xcstrings --output-directory $(THEOS_STAGING_DIR)/Applications/LiveContainer.app
@/Applications/Xcode.app/Contents/Developer/usr/bin/actool LiveContainerSwiftUI/Assets.xcassets --compile $(THEOS_STAGING_DIR)/Applications/LiveContainer.app --platform iphoneos --minimum-deployment-target 14.0
else
@echo "Building on iOS, some commands will be skipped"
endif
@mv $(THEOS_STAGING_DIR)/Applications/LiveContainer.app/LiveContainer $(THEOS_STAGING_DIR)/Applications/LiveContainer.app/LiveContainer_PleaseDoNotShortenTheExecutableNameBecauseItIsUsedToReserveSpaceForOverwritingThankYou

before-all::
Expand Down
4 changes: 2 additions & 2 deletions Resources/Info.plist
Original file line number Diff line number Diff line change
Expand Up @@ -42,7 +42,7 @@
<key>CFBundlePackageType</key>
<string>APPL</string>
<key>CFBundleShortVersionString</key>
<string>3.2.54</string>
<string>3.2.55</string>
<key>CFBundleSignature</key>
<string>????</string>
<key>CFBundleSupportedPlatforms</key>
Expand All @@ -61,7 +61,7 @@
</dict>
</array>
<key>CFBundleVersion</key>
<string>3.2.54</string>
<string>3.2.55</string>
<key>LSApplicationCategoryType</key>
<string>public.app-category.games</string>
<key>LSApplicationQueriesSchemes</key>
Expand Down
20 changes: 18 additions & 2 deletions TweakLoader/NSBundle+FixCydiaSubstrate.m
Original file line number Diff line number Diff line change
@@ -1,9 +1,25 @@
#import <Foundation/Foundation.h>
#import "utils.h"

__attribute__((constructor))
static void NSBundleHookInit(void) {
swizzle(NSBundle.class, @selector(bundlePath), @selector(hook_bundlePath));
swizzle(NSBundle.class, @selector(executablePath), @selector(hook_executablePath));

}

@implementation NSBundle(FixCydiaSubstrate)

- (NSString *)bundlePath {
NSString *path = self.bundleURL.path;
- (NSString *)hook_bundlePath {
NSString *path = self.hook_bundlePath;
if ([path hasPrefix:@"/var"]) {
return [@"/private" stringByAppendingPathComponent:path];
}
return path;
}

- (NSString *)hook_executablePath {
NSString *path = self.hook_executablePath;
if ([path hasPrefix:@"/var"]) {
return [@"/private" stringByAppendingPathComponent:path];
}
Expand Down
2 changes: 1 addition & 1 deletion control
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
Package: com.kdt.livecontainer
Name: livecontainer
Version: 3.2.54
Version: 3.2.55
Architecture: iphoneos-arm
Description: Run iOS app without actually installing it!
Maintainer: khanhduytran0
Expand Down
12 changes: 7 additions & 5 deletions main.m
Original file line number Diff line number Diff line change
Expand Up @@ -249,7 +249,7 @@ static void overwriteExecPath(NSString *bundlePath) {
}

if(!guestAppInfo) {
return @"Unable to read LCAppInfo.plist";
return @"App bundle not found! Unable to read LCAppInfo.plist.";
}

if([guestAppInfo[@"doUseLCBundleId"] boolValue] ) {
Expand Down Expand Up @@ -409,11 +409,13 @@ static void overwriteExecPath(NSString *bundlePath) {
overwriteMainCFBundle();

// Overwrite executable info
NSMutableArray<NSString *> *objcArgv = NSProcessInfo.processInfo.arguments.mutableCopy;
if(objcArgv && objcArgv.count > 0) {
objcArgv[0] = appBundle.executablePath;
[NSProcessInfo.processInfo performSelector:@selector(setArguments:) withObject:objcArgv];
if(!appBundle.executablePath) {
return @"App's executable path not found. Please try force re-signing or reinstalling this app.";
}

NSMutableArray<NSString *> *objcArgv = NSProcessInfo.processInfo.arguments.mutableCopy;
objcArgv[0] = appBundle.executablePath;
[NSProcessInfo.processInfo performSelector:@selector(setArguments:) withObject:objcArgv];
NSProcessInfo.processInfo.processName = appBundle.infoDictionary[@"CFBundleExecutable"];
*_CFGetProgname() = NSProcessInfo.processInfo.processName.UTF8String;

Expand Down

0 comments on commit ad24bb6

Please sign in to comment.