diff --git a/src/main/java/net/knarcraft/bookswithoutborders/command/CommandDecrypt.java b/src/main/java/net/knarcraft/bookswithoutborders/command/CommandDecrypt.java index bdef43d..224dc55 100644 --- a/src/main/java/net/knarcraft/bookswithoutborders/command/CommandDecrypt.java +++ b/src/main/java/net/knarcraft/bookswithoutborders/command/CommandDecrypt.java @@ -113,8 +113,10 @@ public class CommandDecrypt implements TabExecutor { String key = ""; for (String encryptedFile : encryptedFiles) { if (encryptedFile.contains(BookHelper.getBookFile(bookMetadata, player, true).replace(" ", "_"))) { - key = encryptedFile.substring(encryptedFile.indexOf("[") + 1, encryptedFile.indexOf("]")); - break; + key = EncryptionHelper.extractLegacyKey(encryptedFile); + if (!key.isBlank()) { + break; + } } } diff --git a/src/main/java/net/knarcraft/bookswithoutborders/command/CommandGive.java b/src/main/java/net/knarcraft/bookswithoutborders/command/CommandGive.java index e6e336c..9b97915 100644 --- a/src/main/java/net/knarcraft/bookswithoutborders/command/CommandGive.java +++ b/src/main/java/net/knarcraft/bookswithoutborders/command/CommandGive.java @@ -111,7 +111,7 @@ public class CommandGive implements TabExecutor { try { return loadAndGiveBook(bookIdentifier, sender, receivingPlayer, isSigned, folder, copies); } catch (NumberFormatException e) { - stringFormatter.displayErrorMessage(sender, Translatable.ERROR_GIVE_INVALID_COPIES_AMOUNT); + stringFormatter.displayErrorMessage(sender, Translatable.ERROR_INVALID_COPIES_AMOUNT); return false; } } diff --git a/src/main/java/net/knarcraft/bookswithoutborders/command/CommandGroupEncrypt.java b/src/main/java/net/knarcraft/bookswithoutborders/command/CommandGroupEncrypt.java index 9a31785..6a247ee 100644 --- a/src/main/java/net/knarcraft/bookswithoutborders/command/CommandGroupEncrypt.java +++ b/src/main/java/net/knarcraft/bookswithoutborders/command/CommandGroupEncrypt.java @@ -1,7 +1,9 @@ package net.knarcraft.bookswithoutborders.command; import net.knarcraft.bookswithoutborders.BooksWithoutBorders; +import net.knarcraft.bookswithoutborders.config.Translatable; import net.knarcraft.bookswithoutborders.encryption.EncryptionStyle; +import net.knarcraft.knarlib.formatting.StringFormatter; import org.bukkit.command.Command; import org.bukkit.command.CommandSender; import org.bukkit.command.TabExecutor; @@ -19,8 +21,14 @@ public class CommandGroupEncrypt extends CommandEncrypt implements TabExecutor { @Override public boolean onCommand(@NotNull CommandSender sender, @NotNull Command command, @NotNull String label, @NotNull String[] arguments) { + StringFormatter stringFormatter = BooksWithoutBorders.getStringFormatter(); + if (!(sender instanceof Player player)) { + stringFormatter.displayErrorMessage(sender, Translatable.ERROR_PLAYER_ONLY); + return false; + } + BookMeta bookMetadata = performPreChecks(sender, arguments, 2, - "You must specify a group name and key to encrypt a book!"); + stringFormatter.getUnFormattedColoredMessage(Translatable.ERROR_GROUP_ENCRYPT_ARGUMENTS_MISSING)); if (bookMetadata == null) { return false; @@ -29,12 +37,12 @@ public class CommandGroupEncrypt extends CommandEncrypt implements TabExecutor { //Check if book is already group encrypted List lore = bookMetadata.getLore(); if (bookMetadata.hasLore() && lore != null && lore.get(0).contains(" encrypted]")) { - BooksWithoutBorders.sendErrorMessage(sender, "Book is already group encrypted!"); + stringFormatter.displayErrorMessage(sender, Translatable.ERROR_GROUP_ENCRYPTED_ALREADY); return false; } EncryptionStyle encryptionStyle = arguments.length == 3 ? EncryptionStyle.getFromString(arguments[2]) : EncryptionStyle.SUBSTITUTION; - return encryptBook(encryptionStyle, (Player) sender, arguments[1], arguments[0]); + return encryptBook(encryptionStyle, player, arguments[1], arguments[0]); } @Override diff --git a/src/main/java/net/knarcraft/bookswithoutborders/command/CommandLoad.java b/src/main/java/net/knarcraft/bookswithoutborders/command/CommandLoad.java index 09f5803..703270f 100644 --- a/src/main/java/net/knarcraft/bookswithoutborders/command/CommandLoad.java +++ b/src/main/java/net/knarcraft/bookswithoutborders/command/CommandLoad.java @@ -1,10 +1,12 @@ package net.knarcraft.bookswithoutborders.command; import net.knarcraft.bookswithoutborders.BooksWithoutBorders; +import net.knarcraft.bookswithoutborders.config.Translatable; import net.knarcraft.bookswithoutborders.gui.PagedBookIndex; import net.knarcraft.bookswithoutborders.utility.BookLoader; import net.knarcraft.bookswithoutborders.utility.InputCleaningHelper; import net.knarcraft.bookswithoutborders.utility.TabCompletionTypeHelper; +import net.knarcraft.knarlib.formatting.StringFormatter; import net.knarcraft.knarlib.util.TabCompletionHelper; import org.bukkit.command.Command; import org.bukkit.command.CommandSender; @@ -38,13 +40,14 @@ public class CommandLoad implements TabExecutor { */ public boolean loadBook(@NotNull CommandSender sender, @NotNull String[] arguments, @NotNull String directory, boolean loadPublic) { + StringFormatter stringFormatter = BooksWithoutBorders.getStringFormatter(); if (!(sender instanceof Player player)) { - BooksWithoutBorders.sendErrorMessage(sender, "This command can only be used by a player!"); + stringFormatter.displayErrorMessage(sender, Translatable.ERROR_PLAYER_ONLY); return false; } if (player.getInventory().firstEmpty() == -1) { - BooksWithoutBorders.sendErrorMessage(player, "You must have space in your inventory to load books!"); + stringFormatter.displayErrorMessage(player, Translatable.ERROR_INVENTORY_FULL); return false; } @@ -60,6 +63,7 @@ public class CommandLoad implements TabExecutor { String copies = "1"; String isSigned = "true"; + // Parse arguments at the end of the command, and treat the rest as the book name if (argumentCount > 1) { if (argumentCount > 2 && InputCleaningHelper.isInt(arguments[argumentCount - 2]) && InputCleaningHelper.isBoolean(arguments[argumentCount - 1])) { @@ -90,14 +94,14 @@ public class CommandLoad implements TabExecutor { ItemStack newBook = BookLoader.loadBook(player, bookToLoad, isSigned, directory, Integer.parseInt(copies)); if (newBook != null) { player.getInventory().addItem(newBook); - BooksWithoutBorders.sendSuccessMessage(player, "Book created!"); + stringFormatter.displaySuccessMessage(player, Translatable.SUCCESS_BOOK_LOADED); return true; } else { - BooksWithoutBorders.sendErrorMessage(player, "Book failed to load!"); + stringFormatter.displayErrorMessage(player, Translatable.ERROR_LOAD_FAILED); return false; } } catch (NumberFormatException e) { - BooksWithoutBorders.sendErrorMessage(player, "Invalid number of book copies specified!"); + stringFormatter.displayErrorMessage(player, Translatable.ERROR_INVALID_COPIES_AMOUNT); return false; } } diff --git a/src/main/java/net/knarcraft/bookswithoutborders/command/CommandMigrate.java b/src/main/java/net/knarcraft/bookswithoutborders/command/CommandMigrate.java index f3313a7..2d79b1b 100644 --- a/src/main/java/net/knarcraft/bookswithoutborders/command/CommandMigrate.java +++ b/src/main/java/net/knarcraft/bookswithoutborders/command/CommandMigrate.java @@ -4,6 +4,7 @@ import net.knarcraft.bookswithoutborders.BooksWithoutBorders; import net.knarcraft.bookswithoutborders.config.Translatable; import net.knarcraft.bookswithoutborders.container.MigrationRequest; import net.knarcraft.bookswithoutborders.thread.MigrationQueueThread; +import net.knarcraft.knarlib.formatting.StringFormatter; import org.bukkit.command.Command; import org.bukkit.command.CommandSender; import org.bukkit.command.TabExecutor; @@ -25,12 +26,13 @@ public class CommandMigrate implements TabExecutor { @Override public boolean onCommand(@NotNull CommandSender sender, @NotNull Command command, @NotNull String s, @NotNull String[] arguments) { + StringFormatter stringFormatter = BooksWithoutBorders.getStringFormatter(); if (!(sender instanceof Player player)) { BooksWithoutBorders.getStringFormatter().displayErrorMessage(sender, Translatable.ERROR_PLAYER_ONLY); return false; } File bookDirectory = new File(BooksWithoutBorders.getConfiguration().getBookFolder()); - BooksWithoutBorders.sendSuccessMessage(player, "Starting book migration..."); + stringFormatter.displaySuccessMessage(player, Translatable.SUCCESS_MIGRATION_STARTED); Queue filesToMigrate = new LinkedList<>(); findFilesToMigrate(bookDirectory, filesToMigrate, player); BooksWithoutBorders.getMigrationQueue().addAll(filesToMigrate); diff --git a/src/main/java/net/knarcraft/bookswithoutborders/config/Translatable.java b/src/main/java/net/knarcraft/bookswithoutborders/config/Translatable.java index 6853b7d..00979f6 100644 --- a/src/main/java/net/knarcraft/bookswithoutborders/config/Translatable.java +++ b/src/main/java/net/knarcraft/bookswithoutborders/config/Translatable.java @@ -58,6 +58,16 @@ public enum Translatable implements TranslatableMessage { */ SUCCESS_PAGE_DELETED, + /** + * The success message displayed after a book has been loaded + */ + SUCCESS_BOOK_LOADED, + + /** + * The success message displayed after book migration has started + */ + SUCCESS_MIGRATION_STARTED, + /** * The error to display when the console attempts to run a player-only command */ @@ -186,7 +196,7 @@ public enum Translatable implements TranslatableMessage { /** * The error displayed when using the give command with an invalid number of copies (unlikely to ever happen) */ - ERROR_GIVE_INVALID_COPIES_AMOUNT, + ERROR_INVALID_COPIES_AMOUNT, /** * The error displayed when a book is not properly loaded when using the give command @@ -213,6 +223,21 @@ public enum Translatable implements TranslatableMessage { */ ERROR_OUT_OF_RANGE_BOOK_PAGE, + /** + * The error displayed when a player fails to provide necessary arguments for group encryption + */ + ERROR_GROUP_ENCRYPT_ARGUMENTS_MISSING, + + /** + * The error displayed when trying to attempt a group encrypted book twice + */ + ERROR_GROUP_ENCRYPTED_ALREADY, + + /** + * The error displayed when a book fails to be loaded + */ + ERROR_LOAD_FAILED, + /** * The header displayed before printing all commands */ diff --git a/src/main/java/net/knarcraft/bookswithoutborders/listener/PlayerEventListener.java b/src/main/java/net/knarcraft/bookswithoutborders/listener/PlayerEventListener.java index 9d63f61..835bf02 100644 --- a/src/main/java/net/knarcraft/bookswithoutborders/listener/PlayerEventListener.java +++ b/src/main/java/net/knarcraft/bookswithoutborders/listener/PlayerEventListener.java @@ -28,9 +28,9 @@ public class PlayerEventListener implements Listener { //If a book directory exists with this player's name, move it to this player's UUID String bookFolder = config.getBookFolder(); - File file = new File(bookFolder + InputCleaningHelper.cleanString(player.getName())); + File file = new File(bookFolder, InputCleaningHelper.cleanString(player.getName())); if (file.exists()) { - if (!file.renameTo(new File(bookFolder + player.getUniqueId()))) { + if (!file.renameTo(new File(bookFolder, player.getUniqueId().toString()))) { BooksWithoutBorders.log(Level.WARNING, "Unable to migrate player book " + "directory for player " + player.getName()); } diff --git a/src/main/java/net/knarcraft/bookswithoutborders/thread/MigrationQueueThread.java b/src/main/java/net/knarcraft/bookswithoutborders/thread/MigrationQueueThread.java index 9963a5d..4fef364 100644 --- a/src/main/java/net/knarcraft/bookswithoutborders/thread/MigrationQueueThread.java +++ b/src/main/java/net/knarcraft/bookswithoutborders/thread/MigrationQueueThread.java @@ -5,6 +5,7 @@ import net.knarcraft.bookswithoutborders.container.MigrationRequest; import net.knarcraft.bookswithoutborders.utility.BookFileHelper; import net.knarcraft.bookswithoutborders.utility.BookHelper; import net.knarcraft.bookswithoutborders.utility.BookToFromTextHelper; +import net.knarcraft.bookswithoutborders.utility.EncryptionHelper; import org.bukkit.Bukkit; import org.bukkit.Material; import org.bukkit.OfflinePlayer; @@ -88,6 +89,7 @@ public class MigrationQueueThread implements Runnable { if (bookMeta == null) { return false; } + BookMeta loadedBook; String extension = BookFileHelper.getExtensionFromPath(file.getName()); if (extension.equalsIgnoreCase("yml")) { @@ -116,6 +118,13 @@ public class MigrationQueueThread implements Runnable { try { String newName = BookHelper.getBookFile(loadedBook, author, isPublic); + + // Retain legacy key + String key = EncryptionHelper.extractLegacyKey(file.getName()); + if (!key.isBlank()) { + newName = "[" + key + "]" + newName; + } + return saveBook(file.getParentFile(), newName, loadedBook, file); } catch (IllegalArgumentException exception) { BooksWithoutBorders.sendErrorMessage(player, "Failed to migrate book: " + file.getName() + " Cause:"); diff --git a/src/main/java/net/knarcraft/bookswithoutborders/utility/BookToFromTextHelper.java b/src/main/java/net/knarcraft/bookswithoutborders/utility/BookToFromTextHelper.java index 417565a..d2c3edf 100644 --- a/src/main/java/net/knarcraft/bookswithoutborders/utility/BookToFromTextHelper.java +++ b/src/main/java/net/knarcraft/bookswithoutborders/utility/BookToFromTextHelper.java @@ -163,7 +163,6 @@ public final class BookToFromTextHelper { userKey = realKey; } if (!userKey.equals(realKey)) { - BooksWithoutBorders.log(Level.INFO, "Supplied key: " + userKey + " does not match real key: " + realKey); return null; } diff --git a/src/main/java/net/knarcraft/bookswithoutborders/utility/EncryptionHelper.java b/src/main/java/net/knarcraft/bookswithoutborders/utility/EncryptionHelper.java index 0ba12b9..7fdf10c 100644 --- a/src/main/java/net/knarcraft/bookswithoutborders/utility/EncryptionHelper.java +++ b/src/main/java/net/knarcraft/bookswithoutborders/utility/EncryptionHelper.java @@ -351,6 +351,21 @@ public final class EncryptionHelper { return newBook; } + /** + * Attempts to extract a legacy password key from a filename + * + * @param fileName

The filename to get the legacy key from

+ * @return

The legacy key, or an empty string if not found

+ */ + @NotNull + public static String extractLegacyKey(@NotNull String fileName) { + if (fileName.matches("^\\[[0-9]+].*")) { + return fileName.substring(fileName.indexOf("[") + 1, fileName.indexOf("]")); + } else { + return ""; + } + } + /** * Converts a byte array to a hexadecimal string * diff --git a/src/main/resources/strings.yml b/src/main/resources/strings.yml index 3beb64d..84797f6 100644 --- a/src/main/resources/strings.yml +++ b/src/main/resources/strings.yml @@ -10,17 +10,19 @@ en: SUCCESS_GIVE_RECEIVED: "Book received!" SUCCESS_TITLE_PAGE_ADDED: "Title page added!" SUCCESS_PAGE_DELETED: "Page deleted!" - ERROR_PLAYER_ONLY: "This command can only be used by a player!" - ERROR_NOT_HOLDING_WRITTEN_BOOK: "You must be holding a written book to {action} it!" - ERROR_NOT_HOLDING_WRITABLE_BOOK: "You must be holding a writable book to {action} it!" - ERROR_NOT_HOLDING_ANY_BOOK: "You must be holding a book to perform this command" - ERROR_ONLY_ONE_BOOK: "You cannot {action} two books at once!" + SUCCESS_BOOK_LOADED: "Book created!" + SUCCESS_MIGRATION_STARTED: "Starting book migration..." ACTION_COPY: "copy" ACTION_CLEAR: "clear" ACTION_DECRYPT: "decrypt" ACTION_ENCRYPT: "encrypt" ACTION_FORMAT: "format" ACTION_ADD_TITLE_AUTHOR_PAGE: "add an author title page to" + ERROR_PLAYER_ONLY: "This command can only be used by a player!" + ERROR_NOT_HOLDING_WRITTEN_BOOK: "You must be holding a written book to {action} it!" + ERROR_NOT_HOLDING_WRITABLE_BOOK: "You must be holding a writable book to {action} it!" + ERROR_NOT_HOLDING_ANY_BOOK: "You must be holding a book to perform this command" + ERROR_ONLY_ONE_BOOK: "You cannot {action} two books at once!" ERROR_COPY_COUNT_NOT_SPECIFIED: "You must specify the number of copies to be made!" ERROR_COPY_NEGATIVE_AMOUNT: "Number of copies must be larger than 0!" ERROR_COPY_INVALID_AMOUNT: | @@ -44,11 +46,14 @@ en: ERROR_GIVE_NO_RECIPIENT: "You have not specified the recipient of the book!" ERROR_GIVE_RECIPIENT_UNKNOWN: "Player not found!" ERROR_GIVE_RECIPIENT_FULL: "Receiving player must have space in their inventory to receive books!" - ERROR_GIVE_INVALID_COPIES_AMOUNT: "Invalid number of book copies specified!" + ERROR_INVALID_COPIES_AMOUNT: "Invalid number of book copies specified!" ERROR_GIVE_LOAD_FAILED: "Book failed to load!" ERROR_INVALID_BOOK_PAGE: "Invalid page index given!" ERROR_OUT_OF_RANGE_BOOK_PAGE: "The given page index is out of bounds!" ERROR_NO_BOOK_PAGE: "You must supply a page index" + ERROR_GROUP_ENCRYPT_ARGUMENTS_MISSING: "You must specify a group name and key to encrypt a book!" + ERROR_GROUP_ENCRYPTED_ALREADY: "Book is already group encrypted!" + ERROR_LOAD_FAILED: "Book failed to load!" NEUTRAL_COMMANDS_HEADER: | &e[] denote optional parameters <> denote required parameters