From 0c0cd97a6ec365bd8e3295fda8afd4b3d14c681a Mon Sep 17 00:00:00 2001 From: Glavo Date: Sat, 7 Jan 2023 21:36:10 +0800 Subject: [PATCH] Check whether HMCL is in temporary path when starting (#1960) * Check whether HMCL is in temporary path when starting * Update the path of the trash folder on Linux --- .../java/org/jackhuang/hmcl/Launcher.java | 128 +++++++++++++----- .../jackhuang/hmcl/setting/ConfigHolder.java | 6 +- .../resources/assets/lang/I18N.properties | 3 + .../resources/assets/lang/I18N_zh.properties | 1 + .../assets/lang/I18N_zh_CN.properties | 1 + 5 files changed, 99 insertions(+), 40 deletions(-) diff --git a/HMCL/src/main/java/org/jackhuang/hmcl/Launcher.java b/HMCL/src/main/java/org/jackhuang/hmcl/Launcher.java index 03b1f60a7..b98db3843 100644 --- a/HMCL/src/main/java/org/jackhuang/hmcl/Launcher.java +++ b/HMCL/src/main/java/org/jackhuang/hmcl/Launcher.java @@ -39,6 +39,7 @@ import org.jackhuang.hmcl.util.platform.Architecture; import org.jackhuang.hmcl.util.platform.CommandBuilder; import org.jackhuang.hmcl.util.platform.OperatingSystem; +import java.io.File; import java.io.IOException; import java.lang.management.ManagementFactory; import java.net.CookieHandler; @@ -71,45 +72,12 @@ public final class Launcher extends Application { Main.showWarningAndContinue(i18n("fatal.samba")); } catch (IOException e) { LOG.log(Level.SEVERE, "Failed to load config", e); - - try { - if (OperatingSystem.CURRENT_OS != OperatingSystem.WINDOWS) { - String owner = Files.getOwner(ConfigHolder.configLocation()).getName(); - String userName = System.getProperty("user.name"); - if (!Files.isWritable(ConfigHolder.configLocation()) - && !userName.equals("root") - && !userName.equals(owner)) { - - ArrayList files = new ArrayList<>(); - { - files.add(ConfigHolder.configLocation().toString()); - if (Files.exists(Metadata.HMCL_DIRECTORY)) - files.add(Metadata.HMCL_DIRECTORY.toString()); - - Path mcDir = Paths.get(".minecraft").toAbsolutePath().normalize(); - if (Files.exists(mcDir)) - files.add(mcDir.toString()); - } - - String command = new CommandBuilder().add("sudo", "chown", "-R", userName).addAll(files).toString(); - ButtonType copyAndExit = new ButtonType(i18n("button.copy_and_exit")); - - ButtonType res = new Alert(Alert.AlertType.ERROR, i18n("fatal.config_loading_failure.unix", owner, command), copyAndExit, ButtonType.CLOSE) - .showAndWait() - .orElse(null); - if (res == copyAndExit) { - Clipboard.getSystemClipboard() - .setContent(Collections.singletonMap(DataFormat.PLAIN_TEXT, command)); - } - System.exit(1); - } - } - } catch (IOException ioe) { - LOG.log(Level.WARNING, "Failed to get file owner", ioe); - } - Main.showErrorAndExit(i18n("fatal.config_loading_failure", Paths.get("").toAbsolutePath().normalize().toString())); + checkConfigInTempDir(); + checkConfigOwner(); + Main.showErrorAndExit(i18n("fatal.config_loading_failure", ConfigHolder.configLocation().getParent())); } + checkConfigInTempDir(); if (ConfigHolder.isOwnerChanged()) { ButtonType res = new Alert(Alert.AlertType.WARNING, i18n("fatal.config_change_owner_root"), ButtonType.YES, ButtonType.NO) .showAndWait() @@ -138,6 +106,92 @@ public final class Launcher extends Application { } } + private static boolean isConfigInTempDir() { + String configPath = ConfigHolder.configLocation().toString(); + + String tmpdir = System.getProperty("java.io.tmpdir"); + if (StringUtils.isNotBlank(tmpdir) && configPath.startsWith(tmpdir)) + return true; + + String[] tempFolderNames = {"Temp", "Cache", "Caches"}; + for (String name : tempFolderNames) { + if (configPath.contains(File.separator + name + File.separator)) + return true; + } + + if (OperatingSystem.CURRENT_OS == OperatingSystem.WINDOWS) { + return configPath.contains("\\Temporary Internet Files\\") + || configPath.contains("\\INetCache\\") + || configPath.contains("\\$Recycle.Bin\\") + || configPath.contains("\\recycler\\"); + } else if (OperatingSystem.CURRENT_OS == OperatingSystem.LINUX) { + return configPath.startsWith("/tmp/") + || configPath.startsWith("/var/tmp/") + || configPath.startsWith("/var/cache/") + || configPath.startsWith("/dev/shm/") + || configPath.contains("/Trash/"); + } else if (OperatingSystem.CURRENT_OS == OperatingSystem.OSX) { + return configPath.startsWith("/var/folders/") + || configPath.startsWith("/private/var/folders/") + || configPath.startsWith("/tmp/") + || configPath.startsWith("/private/tmp/") + || configPath.startsWith("/var/tmp/") + || configPath.startsWith("/private/var/tmp/") + || configPath.contains("/.Trash/"); + } else { + return false; + } + } + + private static void checkConfigInTempDir() { + if (ConfigHolder.isNewlyCreated() && isConfigInTempDir()) { + ButtonType res = new Alert(Alert.AlertType.WARNING, i18n("fatal.config_in_temp_dir"), ButtonType.YES, ButtonType.NO) + .showAndWait() + .orElse(null); + if (res == ButtonType.NO) { + System.exit(0); + } + } + } + + private static void checkConfigOwner() { + if (OperatingSystem.CURRENT_OS == OperatingSystem.WINDOWS) + return; + + String userName = System.getProperty("user.name"); + String owner; + try { + owner = Files.getOwner(ConfigHolder.configLocation()).getName(); + } catch (IOException ioe) { + LOG.log(Level.WARNING, "Failed to get file owner", ioe); + return; + } + + if (Files.isWritable(ConfigHolder.configLocation()) || userName.equals("root") || userName.equals(owner)) + return; + + ArrayList files = new ArrayList<>(); + files.add(ConfigHolder.configLocation().toString()); + if (Files.exists(Metadata.HMCL_DIRECTORY)) + files.add(Metadata.HMCL_DIRECTORY.toString()); + + Path mcDir = Paths.get(".minecraft").toAbsolutePath().normalize(); + if (Files.exists(mcDir)) + files.add(mcDir.toString()); + + String command = new CommandBuilder().add("sudo", "chown", "-R", userName).addAll(files).toString(); + ButtonType copyAndExit = new ButtonType(i18n("button.copy_and_exit")); + + ButtonType res = new Alert(Alert.AlertType.ERROR, i18n("fatal.config_loading_failure.unix", owner, command), copyAndExit, ButtonType.CLOSE) + .showAndWait() + .orElse(null); + if (res == copyAndExit) { + Clipboard.getSystemClipboard() + .setContent(Collections.singletonMap(DataFormat.PLAIN_TEXT, command)); + } + System.exit(1); + } + @Override public void stop() throws Exception { super.stop(); diff --git a/HMCL/src/main/java/org/jackhuang/hmcl/setting/ConfigHolder.java b/HMCL/src/main/java/org/jackhuang/hmcl/setting/ConfigHolder.java index f39bf3cca..e94bd2bec 100644 --- a/HMCL/src/main/java/org/jackhuang/hmcl/setting/ConfigHolder.java +++ b/HMCL/src/main/java/org/jackhuang/hmcl/setting/ConfigHolder.java @@ -23,6 +23,7 @@ import org.jackhuang.hmcl.Metadata; import org.jackhuang.hmcl.util.InvocationDispatcher; import org.jackhuang.hmcl.util.Lang; import org.jackhuang.hmcl.util.io.FileUtils; +import org.jackhuang.hmcl.util.io.JarUtils; import org.jackhuang.hmcl.util.platform.OperatingSystem; import java.io.IOException; @@ -120,9 +121,8 @@ public final class ConfigHolder { private static Path locateConfig() { Path exePath = Paths.get("").toAbsolutePath(); try { - Path jarPath = Paths.get(ConfigHolder.class.getProtectionDomain().getCodeSource().getLocation() - .toURI()).toAbsolutePath(); - if (Files.isRegularFile(jarPath) && Files.isWritable(jarPath)) { + Path jarPath = JarUtils.thisJar().orElse(null); + if (jarPath != null && Files.isRegularFile(jarPath) && Files.isWritable(jarPath)) { jarPath = jarPath.getParent(); exePath = jarPath; diff --git a/HMCL/src/main/resources/assets/lang/I18N.properties b/HMCL/src/main/resources/assets/lang/I18N.properties index 49d19154d..64742a100 100644 --- a/HMCL/src/main/resources/assets/lang/I18N.properties +++ b/HMCL/src/main/resources/assets/lang/I18N.properties @@ -360,6 +360,9 @@ Please update your Java version to at least 8u101 to fix this issue. # ' fatal.config_change_owner_root=You are using the root account to start Hello Minecraft! Launcher, this may cause you to fail to start Hello Minecraft! Launcher with other account in the future.\n\ Do you still want to continue? +fatal.config_in_temp_dir=You are start Hello Minecraft! Launcher in a temporary directory, your settings and game data may be lost.\n\ +It is recommended to move HMCL to another location and restart it.\n\ +Do you still want to continue? fatal.config_loading_failure=Cannot load configuration files.\n\ Please make sure that "Hello Minecraft! Launcher" has read and write access to "%s" and the files in it. fatal.config_loading_failure.unix=Hello Minecraft! Launcher could not load the profile because the profile was created by user %1$s. \n\ diff --git a/HMCL/src/main/resources/assets/lang/I18N_zh.properties b/HMCL/src/main/resources/assets/lang/I18N_zh.properties index cdc76a16a..64c4d58ab 100644 --- a/HMCL/src/main/resources/assets/lang/I18N_zh.properties +++ b/HMCL/src/main/resources/assets/lang/I18N_zh.properties @@ -334,6 +334,7 @@ fatal.javafx.incompatible.loongson=缺少 JavaFX 運行環境。\n請使龍芯 J fatal.javafx.missing=找不到 JavaFX。\n如果您使用的是 Java 11 或更高版本,請降級到 Oracle JRE 8,或者安裝 BellSoft Liberica Full JRE。\n如果您使用的是其他 OpenJDK 构建,請確保其包含 OpenJFX。 fatal.missing_dst_root_ca_x3=目前的 Java 平台缺少 DST Root CA X3 憑證。\n您依然可以使用 Hello Minecraft! Launcher,但會無法連線到部分網站 (如使用 Lets Encrypt 憑證的站台),這可能會使 Hello Minecraft! Launcher 無法正常運作。\n請將您的 Java 升級到 8u101 以上來解決此問題。 fatal.config_change_owner_root=你正在使用 root 帳戶啟動 Hello Minecraft! Launcher,這可能導致你未來無法使用其他帳戶正常啟動 Hello Minecraft! Launcher。\n是否繼續啟動? +fatal.config_in_temp_dir=你正在臨時資料夾中啟動 Hello Minecraft! Launcher,你的設定和遊戲數據可能會遺失,建議將 HMCL 移動至其他位置再啟動。\n是否繼續啟動? fatal.config_loading_failure=Hello Minecraft! Launcher 無法載入設定檔案。\n請確保 Hello Minecraft! Launcher 對 "%s" 目錄及該目錄下的檔案擁有讀寫權限。 fatal.config_loading_failure.unix=Hello Minecraft! Launcher 無法載入設定檔案,因為設定檔案是由用戶 %1$s 創建的。\n請使用 root 帳戶啟動 HMCL (不推薦),或在終端中執行以下命令將設定檔案的所有權變更為當前用戶: \n%2$s fatal.migration_requires_manual_reboot=Hello Minecraft! Launcher 即將升級完成,請重新開啟 Hello Minecraft! Launcher。 diff --git a/HMCL/src/main/resources/assets/lang/I18N_zh_CN.properties b/HMCL/src/main/resources/assets/lang/I18N_zh_CN.properties index 2b6e79c65..e1ffbb2ca 100644 --- a/HMCL/src/main/resources/assets/lang/I18N_zh_CN.properties +++ b/HMCL/src/main/resources/assets/lang/I18N_zh_CN.properties @@ -334,6 +334,7 @@ fatal.javafx.incompatible.loongson=缺少 JavaFX 运行环境。\n请使用龙 fatal.javafx.missing=缺少 JavaFX 运行环境。\n如果您使用的是 Java 11 或更高版本,请降级到 Oracle JRE 8(java.com),或者安装 BellSoft Liberica Full JRE(bell-sw.com/pages/downloads/?package=jre-full)。\n如果您使用的是其他 OpenJDK 构建,请确保其包含 OpenJFX! fatal.missing_dst_root_ca_x3=当前 Java 平台缺少 DST Root CA X3 证书。\n您依然可以使用 Hello Minecraft! Launcher,但将无法连接到部分站点(如使用 Lets Encrypt 证书的站点),这可能会使 HMCL 无法正常工作。\n请将您的 Java 升级到 8u101 以上以解决此问题。 fatal.config_change_owner_root=你正在使用 root 账户启动 Hello Minecraft! Launcher, 这可能导致你未来无法正常使用其他账户正常启动 Hello Minecraft! Launcher。\n是否继续启动? +fatal.config_in_temp_dir=你正在临时文件夹中启动 Hello Minecraft! Launcher, 你的设置和游戏数据可能会丢失,建议将 HMCL 移动至其他位置再启动。\n是否继续启动? fatal.config_loading_failure=Hello Minecraft! Launcher 无法加载配置文件\n请确保 Hello Minecraft! Launcher 对 "%s" 目录及该目录下的文件拥有读写权限。 fatal.config_loading_failure.unix=Hello Minecraft! Launcher 无法加载配置文件,因为配置文件是由用户 %1$s 创建的。\n请使用 root 账户启动 HMCL (不推荐),或在终端中执行以下命令将配置文件的所有权变更为当前用户:\n%2$s fatal.migration_requires_manual_reboot=Hello Minecraft! Launcher 即将完成升级,请重新打开 Hello Minecraft! Launcher。