From 0d4595d511514b82a03bcbd105d8ba16c03b880f Mon Sep 17 00:00:00 2001 From: benwoo1110 <30431861+benwoo1110@users.noreply.github.com> Date: Mon, 8 Mar 2021 18:03:35 +0800 Subject: [PATCH] Implement new WorldNameChecker for better preliminary checks of world name. --- .../commands/ImportCommand.java | 27 +-- .../MultiverseCore/utils/WorldManager.java | 21 +-- .../utils/WorldNameChecker.java | 159 ++++++++++++++++++ 3 files changed, 166 insertions(+), 41 deletions(-) create mode 100644 src/main/java/com/onarandombox/MultiverseCore/utils/WorldNameChecker.java diff --git a/src/main/java/com/onarandombox/MultiverseCore/commands/ImportCommand.java b/src/main/java/com/onarandombox/MultiverseCore/commands/ImportCommand.java index b16bf239..e2a6b581 100644 --- a/src/main/java/com/onarandombox/MultiverseCore/commands/ImportCommand.java +++ b/src/main/java/com/onarandombox/MultiverseCore/commands/ImportCommand.java @@ -10,6 +10,7 @@ package com.onarandombox.MultiverseCore.commands; import com.onarandombox.MultiverseCore.MultiverseCore; import com.onarandombox.MultiverseCore.api.MVWorldManager; import com.onarandombox.MultiverseCore.api.MultiverseWorld; +import com.onarandombox.MultiverseCore.utils.WorldNameChecker; import com.pneumaticraft.commandhandler.CommandHandler; import org.bukkit.ChatColor; import org.bukkit.World.Environment; @@ -45,28 +46,6 @@ public class ImportCommand extends MultiverseCommand { this.worldManager = this.plugin.getMVWorldManager(); } - /** - * A very basic check to see if a folder has a level.dat file. - * If it does, we can safely assume it's a world folder. - * - * @param worldFolder The File that may be a world. - * @return True if it looks like a world, false if not. - */ - private static boolean checkIfIsWorld(File worldFolder) { - if (worldFolder.isDirectory()) { - File[] files = worldFolder.listFiles(new FilenameFilter() { - @Override - public boolean accept(File file, String name) { - return name.toLowerCase().endsWith(".dat"); - } - }); - if (files != null && files.length > 0) { - return true; - } - } - return false; - } - private String getPotentialWorlds() { File worldFolder = this.plugin.getServer().getWorldContainer(); if (worldFolder == null) { @@ -84,7 +63,7 @@ public class ImportCommand extends MultiverseCommand { } ChatColor currColor = ChatColor.WHITE; for (File file : files) { - if (file.isDirectory() && checkIfIsWorld(file) && !worldStrings.contains(file.getName())) { + if (file.isDirectory() && WorldNameChecker.isValidWorldFolder(file) && !worldStrings.contains(file.getName())) { worldList += currColor + file.getName() + " "; if (currColor == ChatColor.WHITE) { currColor = ChatColor.YELLOW; @@ -152,7 +131,7 @@ public class ImportCommand extends MultiverseCommand { String worldList = this.getPotentialWorlds(); sender.sendMessage("That world folder does not exist. These look like worlds to me:"); sender.sendMessage(worldList); - } else if (!checkIfIsWorld(worldFile)) { + } else if (!WorldNameChecker.isValidWorldFolder(worldFile)) { sender.sendMessage(ChatColor.RED + "FAILED."); sender.sendMessage(String.format("'%s' does not appear to be a world. It is lacking a .dat file.", worldName)); diff --git a/src/main/java/com/onarandombox/MultiverseCore/utils/WorldManager.java b/src/main/java/com/onarandombox/MultiverseCore/utils/WorldManager.java index f951fe98..3979b7cb 100644 --- a/src/main/java/com/onarandombox/MultiverseCore/utils/WorldManager.java +++ b/src/main/java/com/onarandombox/MultiverseCore/utils/WorldManager.java @@ -130,7 +130,7 @@ public class WorldManager implements MVWorldManager { } // Check for valid world name - if (!(isValidWorldName(oldName) && isValidWorldName(newName))) { + if (!(WorldNameChecker.isValidWorldName(oldName) && WorldNameChecker.isValidWorldName(oldName))) { return false; } @@ -238,7 +238,9 @@ public class WorldManager implements MVWorldManager { return false; } - if (!isValidWorldName(name)) { + if (!WorldNameChecker.isValidWorldName(name)) { + Logging.warning("Invalid world name '" + name + "'"); + Logging.warning("World name should not contain spaces or special characters!"); return false; } @@ -424,21 +426,6 @@ public class WorldManager implements MVWorldManager { } } - /** - * Check if the world name is allowed - * - * @param name Name of the world - * @return True if the world world name is valid based on regex - */ - private boolean isValidWorldName(String name) { - if (!worldNamePattern.matcher(name).matches()) { - Logging.warning("Invalid world name '" + name + "'"); - Logging.warning("World name should not contain spaces or special characters!"); - return false; - } - return true; - } - private void brokenWorld(String name) { Logging.severe("The world '" + name + "' could NOT be loaded because it contains errors and is probably corrupt!"); Logging.severe("Try using Minecraft Region Fixer to repair your world! '" + name + "'"); diff --git a/src/main/java/com/onarandombox/MultiverseCore/utils/WorldNameChecker.java b/src/main/java/com/onarandombox/MultiverseCore/utils/WorldNameChecker.java new file mode 100644 index 00000000..7e484167 --- /dev/null +++ b/src/main/java/com/onarandombox/MultiverseCore/utils/WorldNameChecker.java @@ -0,0 +1,159 @@ +package com.onarandombox.MultiverseCore.utils; + +import org.bukkit.Bukkit; +import org.jetbrains.annotations.NotNull; +import org.jetbrains.annotations.Nullable; + +import java.io.File; +import java.util.Collections; +import java.util.HashSet; +import java.util.Set; +import java.util.regex.Pattern; + +/** + *

Utility class in helping to check the status of a world name and it's associated world folder.

+ * + *

Note this is for preliminary checks and better command output. A valid result will suggest but not + * 100% determine that a world name can be created, loaded or imported.

+ */ +public class WorldNameChecker { + + private static final Pattern WORLD_NAME_PATTERN = Pattern.compile("[a-zA-Z0-9/._-]+"); + private static final Set BLACKLIST_NAMES = Collections.unmodifiableSet(new HashSet() {{ + add("plugins"); + add("logs"); + add("cache"); + add("crash-reports"); + }}); + + /** + * Checks if a world name is valid. + * + * @param worldName The world name to check on. + * @return True if check result is valid, else false. + */ + public static boolean isValidWorldName(@Nullable String worldName) { + return checkName(worldName) == NameStatus.VALID; + } + + /** + * Checks the current validity status of a world name. + * + * @param worldName The world name to check on. + * @return The resulting name status. + */ + @NotNull + public static NameStatus checkName(@Nullable String worldName) { + if (BLACKLIST_NAMES.contains(worldName)) { + return NameStatus.BLACKLISTED; + } + if (worldName == null || !WORLD_NAME_PATTERN.matcher(worldName).matches()) { + return NameStatus.INVALID_CHARS; + } + return NameStatus.VALID; + } + + /** + * Checks if a world name has a valid world folder. + * + * @param worldName The world name to check on. + * @return True if check result is valid, else false. + */ + public static boolean isValidWorldFolder(@Nullable String worldName) { + return checkFolder(worldName) == FolderStatus.VALID; + } + + /** + * Checks if a world folder is valid. + * + * @param worldFolder The world folder to check on. + * @return True if check result is valid, else false. + */ + public static boolean isValidWorldFolder(@Nullable File worldFolder) { + return checkFolder(worldFolder) == FolderStatus.VALID; + } + + /** + * Checks the current folder status for a world name. + * + * @param worldName The world name to check on. + * @return The resulting folder status. + */ + @NotNull + public static FolderStatus checkFolder(@Nullable String worldName) { + if (worldName == null) { + return FolderStatus.DOES_NOT_EXIST; + } + File worldFolder = new File(Bukkit.getWorldContainer(), worldName); + return checkFolder(worldFolder); + } + + /** + * Checks the current folder status. + * + * @param worldFolder The world folder to check on. + * @return The resulting folder status. + */ + @NotNull + public static FolderStatus checkFolder(@Nullable File worldFolder) { + if (worldFolder == null || !worldFolder.exists() || !worldFolder.isDirectory()) { + return FolderStatus.DOES_NOT_EXIST; + } + if (!folderHasDat(worldFolder)) { + return FolderStatus.NOT_A_WORLD; + } + return FolderStatus.VALID; + } + + /** + * A very basic check to see if a folder has a level.dat file. If it does, we can safely assume + * it's a world folder. + * + * @param worldFolder The File that may be a world. + * @return True if it looks like a world, else false. + */ + private static boolean folderHasDat(@NotNull File worldFolder) { + File[] files = worldFolder.listFiles((file, name) -> name.toLowerCase().endsWith(".dat")); + return files != null && files.length > 0; + } + + /** + * Result after checking validity of world name. + */ + public enum NameStatus { + /** + * Name is valid. + */ + VALID, + + /** + * Name not valid as it contains invalid characters. + */ + INVALID_CHARS, + + /** + * Name not valid as it is deemed blacklisted. + */ + BLACKLISTED + } + + /** + * Result after checking validity of world folder. + */ + public enum FolderStatus { + /** + * Folder is valid. + */ + VALID, + + /** + * Folder exist, but contents in it doesnt look like a world. + */ + NOT_A_WORLD, + + /** + * Folder does not exist. + */ + DOES_NOT_EXIST + } +}