diff --git a/HMCL/src/main/java/org/jackhuang/hmcl/game/HMCLGameRepository.java b/HMCL/src/main/java/org/jackhuang/hmcl/game/HMCLGameRepository.java index 44f3fceed..4bdf941ed 100644 --- a/HMCL/src/main/java/org/jackhuang/hmcl/game/HMCLGameRepository.java +++ b/HMCL/src/main/java/org/jackhuang/hmcl/game/HMCLGameRepository.java @@ -1,6 +1,6 @@ /* * Hello Minecraft! Launcher - * Copyright (C) 2020 huangyuhui and contributors + * Copyright (C) 2021 huangyuhui and contributors * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by @@ -37,6 +37,7 @@ import org.jackhuang.hmcl.util.StringUtils; import org.jackhuang.hmcl.util.gson.JsonUtils; import org.jackhuang.hmcl.util.io.FileUtils; import org.jackhuang.hmcl.util.platform.JavaVersion; +import org.jackhuang.hmcl.util.platform.OperatingSystem; import java.io.File; import java.io.IOException; @@ -283,10 +284,6 @@ public class HMCLGameRepository extends DefaultGameRepository { vs.setUsesGlobal(true); } - public boolean forbidsVersion(String id) { - return FORBIDDEN.contains(id); - } - public LaunchOptions getLaunchOptions(String version, File gameDir, boolean checkJava) throws InterruptedException { VersionSetting vs = getVersionSetting(version); @@ -368,7 +365,38 @@ public class HMCLGameRepository extends DefaultGameRepository { .setPrettyPrinting() .create(); - private static final HashSet FORBIDDEN = new HashSet<>(Arrays.asList("modpack", "minecraftinstance", "manifest")); - private static final String PROFILE = "{\"selectedProfile\": \"(Default)\",\"profiles\": {\"(Default)\": {\"name\": \"(Default)\"}},\"clientToken\": \"88888888-8888-8888-8888-888888888888\"}"; + + + // These version ids are forbidden because they may conflict with modpack configuration filenames + private static final Set FORBIDDEN_VERSION_IDS = new HashSet<>(Arrays.asList( + "modpack", "minecraftinstance", "manifest")); + + public static boolean isValidVersionId(String id) { + if (FORBIDDEN_VERSION_IDS.contains(id)) + return false; + + if (OperatingSystem.CURRENT_OS == OperatingSystem.WINDOWS && + FORBIDDEN_VERSION_IDS.contains(id.toLowerCase())) + return false; + + return OperatingSystem.isNameValid(id); + } + + /** + * Returns true if the given version id conflicts with an existing version. + */ + public boolean versionIdConflicts(String id) { + if (OperatingSystem.CURRENT_OS == OperatingSystem.WINDOWS) { + // on Windows, filenames are case-insensitive + for (String existingId : versions.keySet()) { + if (existingId.equalsIgnoreCase(id)) { + return true; + } + } + return false; + } else { + return versions.containsKey(id); + } + } } diff --git a/HMCL/src/main/java/org/jackhuang/hmcl/ui/construct/RequiredValidator.java b/HMCL/src/main/java/org/jackhuang/hmcl/ui/construct/RequiredValidator.java index f7f4642ec..959773074 100644 --- a/HMCL/src/main/java/org/jackhuang/hmcl/ui/construct/RequiredValidator.java +++ b/HMCL/src/main/java/org/jackhuang/hmcl/ui/construct/RequiredValidator.java @@ -1,13 +1,34 @@ +/* + * Hello Minecraft! Launcher + * Copyright (C) 2021 huangyuhui and contributors + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ package org.jackhuang.hmcl.ui.construct; import com.jfoenix.validation.base.ValidatorBase; import javafx.beans.NamedArg; import javafx.scene.control.TextInputControl; + import org.jackhuang.hmcl.util.StringUtils; +import static org.jackhuang.hmcl.util.i18n.I18n.i18n; + public class RequiredValidator extends ValidatorBase { public RequiredValidator() { + this(i18n("input.not_empty")); } public RequiredValidator(@NamedArg("message") String message) { diff --git a/HMCL/src/main/java/org/jackhuang/hmcl/ui/download/AdditionalInstallersPage.java b/HMCL/src/main/java/org/jackhuang/hmcl/ui/download/AdditionalInstallersPage.java index c780ab917..01d59f2ad 100644 --- a/HMCL/src/main/java/org/jackhuang/hmcl/ui/download/AdditionalInstallersPage.java +++ b/HMCL/src/main/java/org/jackhuang/hmcl/ui/download/AdditionalInstallersPage.java @@ -1,6 +1,6 @@ /* * Hello Minecraft! Launcher - * Copyright (C) 2020 huangyuhui and contributors + * Copyright (C) 2021 huangyuhui and contributors * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by @@ -23,6 +23,7 @@ import javafx.beans.property.SimpleBooleanProperty; import org.jackhuang.hmcl.download.LibraryAnalyzer; import org.jackhuang.hmcl.download.RemoteVersion; import org.jackhuang.hmcl.game.GameRepository; +import org.jackhuang.hmcl.game.HMCLGameRepository; import org.jackhuang.hmcl.game.Version; import org.jackhuang.hmcl.ui.InstallerItem; import org.jackhuang.hmcl.ui.wizard.WizardController; @@ -40,7 +41,7 @@ class AdditionalInstallersPage extends InstallersPage { protected final String gameVersion; protected final Version version; - public AdditionalInstallersPage(String gameVersion, Version version, WizardController controller, GameRepository repository, InstallerWizardDownloadProvider downloadProvider) { + public AdditionalInstallersPage(String gameVersion, Version version, WizardController controller, HMCLGameRepository repository, InstallerWizardDownloadProvider downloadProvider) { super(controller, repository, gameVersion, downloadProvider); this.gameVersion = gameVersion; this.version = version; diff --git a/HMCL/src/main/java/org/jackhuang/hmcl/ui/download/InstallersPage.java b/HMCL/src/main/java/org/jackhuang/hmcl/ui/download/InstallersPage.java index 0dd7bfd6b..95f493fff 100644 --- a/HMCL/src/main/java/org/jackhuang/hmcl/ui/download/InstallersPage.java +++ b/HMCL/src/main/java/org/jackhuang/hmcl/ui/download/InstallersPage.java @@ -1,6 +1,6 @@ /* * Hello Minecraft! Launcher - * Copyright (C) 2020 huangyuhui and contributors + * Copyright (C) 2021 huangyuhui and contributors * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by @@ -19,7 +19,6 @@ package org.jackhuang.hmcl.ui.download; import com.jfoenix.controls.JFXButton; import com.jfoenix.controls.JFXTextField; -import javafx.beans.binding.Bindings; import javafx.beans.property.*; import javafx.fxml.FXML; import javafx.geometry.Insets; @@ -32,16 +31,16 @@ import javafx.scene.layout.BorderPane; import javafx.scene.layout.HBox; import javafx.scene.layout.VBox; import org.jackhuang.hmcl.download.RemoteVersion; -import org.jackhuang.hmcl.game.GameRepository; +import org.jackhuang.hmcl.game.HMCLGameRepository; import org.jackhuang.hmcl.ui.InstallerItem; +import org.jackhuang.hmcl.ui.construct.RequiredValidator; import org.jackhuang.hmcl.ui.construct.Validator; import org.jackhuang.hmcl.ui.wizard.WizardController; import org.jackhuang.hmcl.ui.wizard.WizardPage; -import org.jackhuang.hmcl.util.StringUtils; -import org.jackhuang.hmcl.util.platform.OperatingSystem; import java.util.Map; +import static javafx.beans.binding.Bindings.createBooleanBinding; import static org.jackhuang.hmcl.util.i18n.I18n.i18n; public class InstallersPage extends Control implements WizardPage { @@ -51,16 +50,14 @@ public class InstallersPage extends Control implements WizardPage { protected JFXTextField txtName = new JFXTextField(); protected BooleanProperty installable = new SimpleBooleanProperty(); - public InstallersPage(WizardController controller, GameRepository repository, String gameVersion, InstallerWizardDownloadProvider downloadProvider) { + public InstallersPage(WizardController controller, HMCLGameRepository repository, String gameVersion, InstallerWizardDownloadProvider downloadProvider) { this.controller = controller; - Validator hasVersion = new Validator(s -> !repository.hasVersion(s) && StringUtils.isNotBlank(s)); - hasVersion.setMessage(i18n("install.new_game.already_exists")); - Validator nameValidator = new Validator(OperatingSystem::isNameValid); - nameValidator.setMessage(i18n("install.new_game.malformed")); - txtName.getValidators().addAll(hasVersion, nameValidator); - installable.bind(Bindings.createBooleanBinding(() -> txtName.validate(), - txtName.textProperty())); + txtName.getValidators().addAll( + new RequiredValidator(), + new Validator(i18n("install.new_game.already_exists"), str -> !repository.versionIdConflicts(str)), + new Validator(i18n("install.new_game.malformed"), HMCLGameRepository::isValidVersionId)); + installable.bind(createBooleanBinding(txtName::validate, txtName.textProperty())); txtName.setText(gameVersion); group.game.installable.setValue(false); diff --git a/HMCL/src/main/java/org/jackhuang/hmcl/ui/download/LocalModpackPage.java b/HMCL/src/main/java/org/jackhuang/hmcl/ui/download/LocalModpackPage.java index 1793c4c33..3369429ba 100644 --- a/HMCL/src/main/java/org/jackhuang/hmcl/ui/download/LocalModpackPage.java +++ b/HMCL/src/main/java/org/jackhuang/hmcl/ui/download/LocalModpackPage.java @@ -20,12 +20,13 @@ package org.jackhuang.hmcl.ui.download; import com.jfoenix.controls.JFXButton; import com.jfoenix.controls.JFXTextField; import javafx.application.Platform; -import javafx.beans.binding.Bindings; import javafx.fxml.FXML; import javafx.scene.control.Label; import javafx.scene.layout.Region; import javafx.scene.layout.StackPane; import javafx.stage.FileChooser; + +import org.jackhuang.hmcl.game.HMCLGameRepository; import org.jackhuang.hmcl.game.ModpackHelper; import org.jackhuang.hmcl.mod.Modpack; import org.jackhuang.hmcl.setting.Profile; @@ -35,17 +36,18 @@ import org.jackhuang.hmcl.ui.Controllers; import org.jackhuang.hmcl.ui.FXUtils; import org.jackhuang.hmcl.ui.WebStage; import org.jackhuang.hmcl.ui.construct.MessageDialogPane.MessageType; +import org.jackhuang.hmcl.ui.construct.RequiredValidator; import org.jackhuang.hmcl.ui.construct.SpinnerPane; import org.jackhuang.hmcl.ui.construct.Validator; import org.jackhuang.hmcl.ui.wizard.WizardController; import org.jackhuang.hmcl.ui.wizard.WizardPage; -import org.jackhuang.hmcl.util.StringUtils; import org.jackhuang.hmcl.util.io.CompressingUtils; import java.io.File; import java.util.Map; import java.util.Optional; +import static javafx.beans.binding.Bindings.createBooleanBinding; import static org.jackhuang.hmcl.util.Lang.tryCast; import static org.jackhuang.hmcl.util.i18n.I18n.i18n; @@ -93,15 +95,14 @@ public final class LocalModpackPage extends StackPane implements WizardPage { txtModpackName.setDisable(true); } else { txtModpackName.getValidators().addAll( - new Validator(i18n("install.new_game.already_exists"), str -> !profile.getRepository().hasVersion(str) && StringUtils.isNotBlank(str)), - new Validator(i18n("version.forbidden_name"), str -> !profile.getRepository().forbidsVersion(str)) - ); + new RequiredValidator(), + new Validator(i18n("install.new_game.already_exists"), str -> !profile.getRepository().versionIdConflicts(str)), + new Validator(i18n("install.new_game.malformed"), HMCLGameRepository::isValidVersionId)); + btnInstall.disableProperty().bind( + createBooleanBinding(txtModpackName::validate, txtModpackName.textProperty()) + .not()); } - btnInstall.disableProperty().bind(Bindings.createBooleanBinding( - () -> !txtModpackName.validate(), - txtModpackName.textProperty())); - Optional filePath = tryCast(controller.getSettings().get(MODPACK_FILE), File.class); if (filePath.isPresent()) { selectedFile = filePath.get(); diff --git a/HMCL/src/main/java/org/jackhuang/hmcl/ui/download/RemoteModpackPage.java b/HMCL/src/main/java/org/jackhuang/hmcl/ui/download/RemoteModpackPage.java index fc5fe659c..fb865e030 100644 --- a/HMCL/src/main/java/org/jackhuang/hmcl/ui/download/RemoteModpackPage.java +++ b/HMCL/src/main/java/org/jackhuang/hmcl/ui/download/RemoteModpackPage.java @@ -24,21 +24,24 @@ import javafx.fxml.FXML; import javafx.scene.control.Label; import javafx.scene.layout.Region; import javafx.scene.layout.StackPane; + +import org.jackhuang.hmcl.game.HMCLGameRepository; import org.jackhuang.hmcl.mod.server.ServerModpackManifest; import org.jackhuang.hmcl.setting.Profile; import org.jackhuang.hmcl.ui.Controllers; import org.jackhuang.hmcl.ui.FXUtils; import org.jackhuang.hmcl.ui.WebStage; import org.jackhuang.hmcl.ui.construct.MessageDialogPane; +import org.jackhuang.hmcl.ui.construct.RequiredValidator; import org.jackhuang.hmcl.ui.construct.SpinnerPane; import org.jackhuang.hmcl.ui.construct.Validator; import org.jackhuang.hmcl.ui.wizard.WizardController; import org.jackhuang.hmcl.ui.wizard.WizardPage; -import org.jackhuang.hmcl.util.StringUtils; import java.io.IOException; import java.util.Map; import java.util.Optional; +import static javafx.beans.binding.Bindings.createBooleanBinding; import static org.jackhuang.hmcl.util.Lang.tryCast; import static org.jackhuang.hmcl.util.i18n.I18n.i18n; @@ -104,10 +107,12 @@ public class RemoteModpackPage extends StackPane implements WizardPage { // trim: https://github.com/huanghongxun/HMCL/issues/962 txtModpackName.setText(manifest.getName().trim()); txtModpackName.getValidators().addAll( - new Validator(i18n("install.new_game.already_exists"), str -> !profile.getRepository().hasVersion(str) && StringUtils.isNotBlank(str)), - new Validator(i18n("version.forbidden_name"), str -> !profile.getRepository().forbidsVersion(str)) - ); - txtModpackName.textProperty().addListener(e -> btnInstall.setDisable(!txtModpackName.validate())); + new RequiredValidator(), + new Validator(i18n("install.new_game.already_exists"), str -> !profile.getRepository().versionIdConflicts(str)), + new Validator(i18n("install.new_game.malformed"), HMCLGameRepository::isValidVersionId)); + btnInstall.disableProperty().bind( + createBooleanBinding(txtModpackName::validate, txtModpackName.textProperty()) + .not()); } } diff --git a/HMCL/src/main/java/org/jackhuang/hmcl/ui/export/ModpackInfoPage.java b/HMCL/src/main/java/org/jackhuang/hmcl/ui/export/ModpackInfoPage.java index 1bf590650..5b5a52b32 100644 --- a/HMCL/src/main/java/org/jackhuang/hmcl/ui/export/ModpackInfoPage.java +++ b/HMCL/src/main/java/org/jackhuang/hmcl/ui/export/ModpackInfoPage.java @@ -1,6 +1,6 @@ /* * Hello Minecraft! Launcher - * Copyright (C) 2020 huangyuhui and contributors + * Copyright (C) 2021 huangyuhui and contributors * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by @@ -215,7 +215,7 @@ public final class ModpackInfoPage extends Control implements WizardPage { txtModpackName.textProperty().bindBidirectional(skinnable.name); txtModpackName.setLabelFloat(true); txtModpackName.setPromptText(i18n("modpack.name")); - txtModpackName.getValidators().add(new RequiredValidator(i18n("modpack.not_a_valid_name"))); + txtModpackName.getValidators().add(new RequiredValidator()); StackPane.setMargin(txtModpackName, insets); list.getContent().add(txtModpackName); diff --git a/HMCL/src/main/resources/assets/fxml/account-add.fxml b/HMCL/src/main/resources/assets/fxml/account-add.fxml index e3587f613..c47e55a63 100644 --- a/HMCL/src/main/resources/assets/fxml/account-add.fxml +++ b/HMCL/src/main/resources/assets/fxml/account-add.fxml @@ -52,8 +52,7 @@ - - + @@ -62,8 +61,7 @@ - - + diff --git a/HMCL/src/main/resources/assets/lang/I18N.properties b/HMCL/src/main/resources/assets/lang/I18N.properties index bee189a4c..ce34ee043 100644 --- a/HMCL/src/main/resources/assets/lang/I18N.properties +++ b/HMCL/src/main/resources/assets/lang/I18N.properties @@ -525,7 +525,6 @@ version.cannot_read=Unable to find the game version. Cannot continue automatic i version.empty=No game version.empty.add=Install new version version.empty.launch=No version to launch, please install a version via version list page. -version.forbidden_name=Forbidden name please do not use that name. version.game.old=Old version.game.release=Releases version.game.snapshot=Snapshots diff --git a/HMCL/src/main/resources/assets/lang/I18N_es.properties b/HMCL/src/main/resources/assets/lang/I18N_es.properties index 04d43767a..94c86ba03 100644 --- a/HMCL/src/main/resources/assets/lang/I18N_es.properties +++ b/HMCL/src/main/resources/assets/lang/I18N_es.properties @@ -420,7 +420,6 @@ version.cannot_read=No se pudo encontrar la versión de juego. Descontinuando au version.empty=No hay juego version.empty.add=Instalar juego en lista de juegos version.empty.launch=No hay juego para iniciar, por favor instale juego nuevo via la lista. -version.forbidden_name=Nombre prohibido. version.game.old=Viejo version.game.release=Release version.game.snapshot=Snapshot diff --git a/HMCL/src/main/resources/assets/lang/I18N_ru.properties b/HMCL/src/main/resources/assets/lang/I18N_ru.properties index 20cdd75af..da810b441 100644 --- a/HMCL/src/main/resources/assets/lang/I18N_ru.properties +++ b/HMCL/src/main/resources/assets/lang/I18N_ru.properties @@ -437,7 +437,6 @@ version.cannot_read=Невозможно найти версию игры. Не version.empty=Нет установленных version.empty.add=Установить новую версию version.empty.launch=Нет версии для запуска, установите версию на странице списка версий. -version.forbidden_name=Запрещённое название, не используйте его. version.game.old=Старые version.game.release=Релизы version.game.snapshot=Snapshots diff --git a/HMCL/src/main/resources/assets/lang/I18N_zh.properties b/HMCL/src/main/resources/assets/lang/I18N_zh.properties index 0d04c75f0..355b27298 100644 --- a/HMCL/src/main/resources/assets/lang/I18N_zh.properties +++ b/HMCL/src/main/resources/assets/lang/I18N_zh.properties @@ -443,7 +443,6 @@ version.cannot_read=讀取遊戲版本失敗,無法進行自動安裝 version.empty=無遊戲版本 version.empty.add=進入遊戲列表安裝 version.empty.launch=沒有可啟動的遊戲,你可以點選左側遊戲欄內的設定按鈕進入遊戲列表安裝遊戲 -version.forbidden_name=此版本名稱不受支援,請換一個名稱 version.game.old=老舊版本 version.game.release=穩定版本 version.game.snapshot=測試版本 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 c5d3354f8..4162b4fdd 100644 --- a/HMCL/src/main/resources/assets/lang/I18N_zh_CN.properties +++ b/HMCL/src/main/resources/assets/lang/I18N_zh_CN.properties @@ -529,7 +529,6 @@ version.cannot_read=读取游戏版本失败,无法进行自动安装 version.empty=没有游戏版本 version.empty.add=进入版本列表安装 version.empty.launch=没有可启动的游戏,你可以点击左侧游戏栏内的设置按钮进入版本列表安装游戏 -version.forbidden_name=此版本名称不受支持,请换一个名字 version.game.old=远古版 version.game.release=正式版 version.game.snapshot=测试版 diff --git a/HMCLCore/src/main/java/org/jackhuang/hmcl/util/platform/OperatingSystem.java b/HMCLCore/src/main/java/org/jackhuang/hmcl/util/platform/OperatingSystem.java index 78a352e2f..5182dbcb4 100644 --- a/HMCLCore/src/main/java/org/jackhuang/hmcl/util/platform/OperatingSystem.java +++ b/HMCLCore/src/main/java/org/jackhuang/hmcl/util/platform/OperatingSystem.java @@ -1,6 +1,6 @@ /* * Hello Minecraft! Launcher - * Copyright (C) 2020 huangyuhui and contributors + * Copyright (C) 2021 huangyuhui and contributors * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by @@ -118,12 +118,12 @@ public enum OperatingSystem { if (CURRENT_OS == WINDOWS) { // valid names and characters taken from http://msdn.microsoft.com/library/default.asp?url=/library/en-us/fileio/fs/naming_a_file.asp INVALID_RESOURCE_CHARACTERS = Pattern.compile("[/\"<>|?*:\\\\]"); - INVALID_RESOURCE_BASENAMES = new String[]{"aux", "com1", "com2", "com3", "com4", //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$ //$NON-NLS-4$ //$NON-NLS-5$ - "com5", "com6", "com7", "com8", "com9", "con", "lpt1", "lpt2", //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$ //$NON-NLS-4$ //$NON-NLS-5$ //$NON-NLS-6$ //$NON-NLS-7$ //$NON-NLS-8$ - "lpt3", "lpt4", "lpt5", "lpt6", "lpt7", "lpt8", "lpt9", "nul", "prn"}; //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$ //$NON-NLS-4$ //$NON-NLS-5$ //$NON-NLS-6$ //$NON-NLS-7$ //$NON-NLS-8$ //$NON-NLS-9$ + INVALID_RESOURCE_BASENAMES = new String[]{"aux", "com1", "com2", "com3", "com4", + "com5", "com6", "com7", "com8", "com9", "con", "lpt1", "lpt2", + "lpt3", "lpt4", "lpt5", "lpt6", "lpt7", "lpt8", "lpt9", "nul", "prn"}; Arrays.sort(INVALID_RESOURCE_BASENAMES); //CLOCK$ may be used if an extension is provided - INVALID_RESOURCE_FULLNAMES = new String[]{"clock$"}; //$NON-NLS-1$ + INVALID_RESOURCE_FULLNAMES = new String[]{"clock$"}; } else { //only front slash and null char are invalid on UNIXes //taken from http://www.faqs.org/faqs/unix-faq/faq/part2/section-2.html @@ -168,19 +168,22 @@ public enum OperatingSystem { } /** - * Returns true if the given name is a valid resource name on this operating system, + * Returns true if the given name is a valid file name on this operating system, * and false otherwise. */ public static boolean isNameValid(String name) { - //. and .. have special meaning on all platforms - if (name.equals(".") || name.equals("..") || name.indexOf('/') == 0 || name.indexOf('\0') >= 0) //$NON-NLS-1$ //$NON-NLS-2$ + // empty filename is not allowed + if (name.isEmpty()) return false; - if (CURRENT_OS == WINDOWS) { - //empty names are not valid - final int length = name.length(); - if (length == 0) - return false; - final char lastChar = name.charAt(length - 1); + // . and .. have special meaning on all platforms + if (name.isEmpty() || name.equals(".")) + return false; + // \0 and / are forbidden on all platforms + if (name.indexOf('/') != -1 || name.indexOf('\0') != -1) + return false; + + if (CURRENT_OS == WINDOWS) { // Windows only + char lastChar = name.charAt(name.length() - 1); // filenames ending in dot are not valid if (lastChar == '.') return false; @@ -194,7 +197,7 @@ public enum OperatingSystem { return false; if (Arrays.binarySearch(INVALID_RESOURCE_FULLNAMES, name.toLowerCase()) >= 0) return false; - if (INVALID_RESOURCE_CHARACTERS != null && INVALID_RESOURCE_CHARACTERS.matcher(name).find()) + if (INVALID_RESOURCE_CHARACTERS.matcher(name).find()) return false; }