diff --git a/JavaApp/src/main/java/net/kdt/pojavlaunch/PLaunchApp.java b/JavaApp/src/main/java/net/kdt/pojavlaunch/PojavLauncher.java similarity index 83% rename from JavaApp/src/main/java/net/kdt/pojavlaunch/PLaunchApp.java rename to JavaApp/src/main/java/net/kdt/pojavlaunch/PojavLauncher.java index bdca3177..1fae9f31 100644 --- a/JavaApp/src/main/java/net/kdt/pojavlaunch/PLaunchApp.java +++ b/JavaApp/src/main/java/net/kdt/pojavlaunch/PojavLauncher.java @@ -11,10 +11,15 @@ import net.kdt.pojavlaunch.uikit.*; import net.kdt.pojavlaunch.utils.*; import net.kdt.pojavlaunch.value.*; -public class PLaunchApp { +public class PojavLauncher { private static float currProgress, maxProgress; public static void main(String[] args) throws Throwable { + /* + try { + Runtime.getRuntime().exec("/usr/bin/true"); + } catch (IOException e) {} + */ try { sun.font.FontUtilities.isLinux = true; } catch (Throwable th) { @@ -72,16 +77,4 @@ public class PLaunchApp { Tools.launchMinecraft(account, version); } - -// TODO -/* - public static void downloadAssetMapped(String assetName, JAssetInfo asset, File resDir) throws IOException { - String assetPath = asset.hash.substring(0, 2) + "/" + asset.hash; - File outFile = new File(resDir,"/"+assetName); - if (!outFile.exists()) { - UIKit.updateProgressSafe(currProgress / maxProgress, "Downloading " + assetName); - DownloadUtils.downloadFile(MINECRAFT_RES + assetPath, outFile); - } - } - */ } diff --git a/JavaApp/src/main/java/net/kdt/pojavlaunch/utils/JREUtils.java b/JavaApp/src/main/java/net/kdt/pojavlaunch/utils/JREUtils.java deleted file mode 100644 index 24768440..00000000 --- a/JavaApp/src/main/java/net/kdt/pojavlaunch/utils/JREUtils.java +++ /dev/null @@ -1,22 +0,0 @@ -package net.kdt.pojavlaunch.utils; - -import android.util.*; - -import java.io.*; -import java.util.*; - -// import libcore.io.*; - -import net.kdt.pojavlaunch.*; - -import org.lwjgl.glfw.*; - -public class JREUtils -{ - private JREUtils() {} - - - static { - System.load(System.getenv("BUNDLE_PATH") + "/PojavLauncher"); - } -} diff --git a/Natives/JavaLauncher.m b/Natives/JavaLauncher.m index 7550eac4..a7099397 100644 --- a/Natives/JavaLauncher.m +++ b/Natives/JavaLauncher.m @@ -379,7 +379,7 @@ int launchJVM(NSString *username, id launchTarget, int width, int height, int mi margv[++margc] = "-cp"; margv[++margc] = classpath; - margv[++margc] = "net.kdt.pojavlaunch.PLaunchApp"; + margv[++margc] = "net.kdt.pojavlaunch.PojavLauncher"; if (username == nil) { margv[++margc] = ".LaunchJAR"; diff --git a/Natives/MinecraftDownloader.m b/Natives/MinecraftDownloader.m index d82cc677..8a7ae235 100644 --- a/Natives/MinecraftDownloader.m +++ b/Natives/MinecraftDownloader.m @@ -29,7 +29,7 @@ todo for now - might change anytime + assets - download assets + new structure - + old structure + + old structure (mapped) */ @implementation MinecraftDownloader diff --git a/Natives/input_bridge_v3.m b/Natives/input_bridge_v3.m index 1d8ee24c..4ee63c08 100644 --- a/Natives/input_bridge_v3.m +++ b/Natives/input_bridge_v3.m @@ -15,6 +15,8 @@ #import "SurfaceViewController.h" #include +#include +#include #include #include "jni.h" @@ -25,6 +27,8 @@ #include "JavaLauncher.h" +jint (*orig_ProcessImpl_forkAndExec)(JNIEnv *env, jobject process, jint mode, jbyteArray helperpath, jbyteArray prog, jbyteArray argBlock, jint argc, jbyteArray envBlock, jint envc, jbyteArray dir, jintArray std_fds, jboolean redirectErrorStream); + typedef void GLFW_invoke_Char_func(void* window, unsigned int codepoint); typedef void GLFW_invoke_CharMods_func(void* window, unsigned int codepoint, int mods); typedef void GLFW_invoke_CursorEnter_func(void* window, int entered); @@ -44,8 +48,71 @@ jmethodID inputBridgeMethod_ANDROID; jclass uikitBridgeClass; jmethodID uikitBridgeTouchMethod; +/** + * Hooked version of java.lang.UNIXProcess.forkAndExec() + * which is used to handle the "open" command. + */ +jint +hooked_ProcessImpl_forkAndExec(JNIEnv *env, jobject process, jint mode, jbyteArray helperpath, jbyteArray prog, jbyteArray argBlock, jint argc, jbyteArray envBlock, jint envc, jbyteArray dir, jintArray std_fds, jboolean redirectErrorStream) { + char *pProg = (char *)((*env)->GetByteArrayElements(env, prog, NULL)); + + // Here we only handle the "open" command + if (strcmp(basename(pProg), "open")) { + (*env)->ReleaseByteArrayElements(env, prog, (jbyte *)pProg, 0); + return orig_ProcessImpl_forkAndExec(env, process, mode, helperpath, prog, argBlock, argc, envBlock, envc, dir, std_fds, redirectErrorStream); + } + + dispatch_group_t group = dispatch_group_create(); + dispatch_group_enter(group); + + char *path = (char *)((*env)->GetByteArrayElements(env, argBlock, NULL)); + dispatch_async(dispatch_get_main_queue(), ^{ + NSString *realPath = @(path); + if ([realPath hasPrefix:@"file:"]) { + realPath = [realPath substringFromIndex:5].stringByRemovingPercentEncoding; + } + if (![realPath hasPrefix:@"http"]) { + realPath = [NSString stringWithFormat:@"filza:/%@", realPath.stringByResolvingSymlinksInPath]; + } + + [[UIApplication sharedApplication] openURL:[NSURL URLWithString:realPath] options:@{} completionHandler:^(BOOL success) { + if (success) { + NSLog(@"Opened \"%@\"", realPath); + } else { + NSLog(@"Failed to open \"%@\"", realPath); + } + dispatch_group_leave(group); + }]; + }); + + dispatch_group_wait(group, DISPATCH_TIME_FOREVER); + + (*env)->ReleaseByteArrayElements(env, prog, (jbyte *)pProg, 0); + (*env)->ReleaseByteArrayElements(env, argBlock, (jbyte *)path, 0); + return 0; +} + +void hookExec(JNIEnv *env) { + jclass cls; + orig_ProcessImpl_forkAndExec = dlsym(RTLD_DEFAULT, "Java_java_lang_UNIXProcess_forkAndExec"); + if (!orig_ProcessImpl_forkAndExec) { + orig_ProcessImpl_forkAndExec = dlsym(RTLD_DEFAULT, "Java_java_lang_ProcessImpl_forkAndExec"); + cls = (*env)->FindClass(env, "java/lang/ProcessImpl"); + } else { + cls = (*env)->FindClass(env, "java/lang/UNIXProcess"); + } + JNINativeMethod methods[] = { + {"forkAndExec", "(I[B[B[BI[BI[B[IZ)I", (void *)&hooked_ProcessImpl_forkAndExec} + }; + (*env)->RegisterNatives(env, cls, methods, 1); +} + // JNI_OnLoad jint JNI_OnLoad(JavaVM* vm, void* reserved) { + JNIEnv *env; + (*vm)->GetEnv(vm, (void **)&env, JNI_VERSION_1_4); + hookExec(env); + runtimeJavaVMPtr = vm; return JNI_VERSION_1_4; } @@ -178,17 +245,6 @@ JNIEXPORT void JNICALL Java_net_kdt_pojavlaunch_uikit_UIKit_updateMCGuiScale(JNI guiScale = scale; } -/* -JNIEXPORT void JNICALL Java_net_kdt_pojavlaunch_uikit_UIKit_runOnUIThread(JNIEnv* env, jclass clazz, jobject callback) { - UIKit_runOnUIThread(callback); -} -*/ -JNIEXPORT jint JNICALL Java_net_kdt_pojavlaunch_uikit_UIKit_launchUI(JNIEnv* env, jclass clazz) { - @autoreleasepool { - return UIApplicationMain(1, (char *[]){ getenv("EXEC_PATH") }, nil, NSStringFromClass([AppDelegate class])); - } -} - JNIEXPORT jstring JNICALL Java_org_lwjgl_glfw_CallbackBridge_nativeClipboard(JNIEnv* env, jclass clazz, jint action, jstring copySrc) { DEBUG_LOGD("Debug: Clipboard access is going on\n"); return UIKit_accessClipboard(env, action, copySrc); @@ -198,7 +254,6 @@ JNIEXPORT jboolean JNICALL Java_org_lwjgl_glfw_CallbackBridge_nativeSetInputRead #ifdef DEBUG LOGD("Debug: Changing input state, isReady=%d, isUseStackQueueCall=%d\n", inputReady, isUseStackQueueCall); #endif - isInputReady = inputReady; return isUseStackQueueCall; diff --git a/Natives/ios_uikit_bridge.h b/Natives/ios_uikit_bridge.h index 7d890b29..d09bd2d9 100644 --- a/Natives/ios_uikit_bridge.h +++ b/Natives/ios_uikit_bridge.h @@ -6,6 +6,5 @@ void showDialog(UIViewController *viewController, NSString* title, NSString* mes UIAlertController* createLoadingAlert(NSString* message); jstring UIKit_accessClipboard(JNIEnv* env, jint action, jstring copySrc); void UIKit_updateProgress(float progress, const char* message); -void UIKit_launchJarFile(const char* filepath); void UIKit_launchMinecraftSurfaceVC(); void launchInitialViewController(); diff --git a/Natives/ios_uikit_bridge.m b/Natives/ios_uikit_bridge.m index 60b4365c..509bbd82 100644 --- a/Natives/ios_uikit_bridge.m +++ b/Natives/ios_uikit_bridge.m @@ -104,23 +104,6 @@ jstring UIKit_accessClipboard(JNIEnv* env, jint action, jstring copySrc) { } } -void UIKit_launchJarFile(const char* filepath) { - jclass uikitBridgeClass = (*runtimeJNIEnvPtr)->FindClass(runtimeJNIEnvPtr, "net/kdt/pojavlaunch/uikit/UIKit"); - assert(uikitBridgeClass != NULL); - - jstring filepathStr = (*runtimeJNIEnvPtr)->NewStringUTF(runtimeJNIEnvPtr, filepath); - jmethodID method = (*runtimeJNIEnvPtr)->GetStaticMethodID(runtimeJNIEnvPtr, uikitBridgeClass, "callback_JavaGUIViewController_launchJarFile", "(Ljava/lang/String;II)V"); - assert(method != NULL); - - (*runtimeJNIEnvPtr)->CallStaticVoidMethod( - runtimeJNIEnvPtr, - uikitBridgeClass, method, - filepathStr, - savedWidth, savedHeight - ); - (*runtimeJNIEnvPtr)->DeleteLocalRef(runtimeJNIEnvPtr, filepathStr); -} - void UIKit_launchMinecraftSurfaceVC() { setPreference(@"internal_launch_on_boot", getPreference(@"restart_before_launch")); setPreference(@"internal_selected_account", BaseAuthenticator.current.authData[@"username"]); diff --git a/Natives/main_hook.m b/Natives/main_hook.m index c2b70f4e..56b65b98 100644 --- a/Natives/main_hook.m +++ b/Natives/main_hook.m @@ -1,5 +1,7 @@ #include +#include #include +#include #include #include "external/fishhook/fishhook.h" @@ -13,6 +15,7 @@ static int (*orig_dladdr)(const void* addr, Dl_info* info); static void* (*orig_dlopen)(const char* path, int mode); //static void* (*orig_mmap)(void *addr, size_t len, int prot, int flags, int fd, off_t offset); static char* (*orig_realpath)(const char *restrict path, char *restrict resolved_path); +pid_t (*orig_waitpid)(pid_t pid, int *status, int options); //static void (*orig_sys_icache_invalidate)(void *start, size_t len); @@ -100,7 +103,7 @@ void init_hookFunctions() { // Jailed only: hook some functions for symlinked JRE home dir int retval = rebind_symbols((struct rebinding[3]){ {"dladdr", hooked_dladdr, (void *)&orig_dladdr}, - {"dlopen", hooked_dlopen, (void *)&orig_dlopen}, + {"dlopen", hooked_dlopen, (void *)&orig_dlopen}, //{"realpath", hooked_realpath, (void *)&orig_realpath}, {"realpath$DARWIN_EXTSN", hooked_realpath, (void *)&orig_realpath} //{"mmap", hooked_mmap, (void *)&orig_mmap},