From e342f4cff58325d183d09721c050001b26565112 Mon Sep 17 00:00:00 2001 From: EpicKnarvik97 Date: Fri, 22 Aug 2025 00:11:29 +0200 Subject: [PATCH] Fixes incorrect migration of legacy encrypted books --- .../command/CommandGroupEncrypt.java | 2 +- .../config/StaticMessage.java | 4 +- .../thread/MigrationQueueThread.java | 17 +++-- .../utility/BookToFromTextHelper.java | 67 ++++++++++++------- .../utility/EncryptionHelper.java | 2 +- 5 files changed, 60 insertions(+), 32 deletions(-) diff --git a/src/main/java/net/knarcraft/bookswithoutborders/command/CommandGroupEncrypt.java b/src/main/java/net/knarcraft/bookswithoutborders/command/CommandGroupEncrypt.java index a0b3219..66c0288 100644 --- a/src/main/java/net/knarcraft/bookswithoutborders/command/CommandGroupEncrypt.java +++ b/src/main/java/net/knarcraft/bookswithoutborders/command/CommandGroupEncrypt.java @@ -41,7 +41,7 @@ public class CommandGroupEncrypt extends CommandEncrypt implements TabExecutor { return false; } - EncryptionStyle encryptionStyle = arguments.length == 3 ? EncryptionStyle.getFromString(arguments[2]) : EncryptionStyle.SUBSTITUTION; + EncryptionStyle encryptionStyle = arguments.length == 3 ? EncryptionStyle.getFromString(arguments[2]) : EncryptionStyle.AES; return encryptBook(encryptionStyle, player, arguments[1], arguments[0], false); } diff --git a/src/main/java/net/knarcraft/bookswithoutborders/config/StaticMessage.java b/src/main/java/net/knarcraft/bookswithoutborders/config/StaticMessage.java index 6861faf..cb23807 100644 --- a/src/main/java/net/knarcraft/bookswithoutborders/config/StaticMessage.java +++ b/src/main/java/net/knarcraft/bookswithoutborders/config/StaticMessage.java @@ -28,7 +28,9 @@ public enum StaticMessage { WARNING_USER_BOOK_MIGRATION_IMPOSSIBLE("Unable to migrate player book directory for player {player}"), EXCEPTION_BOOK_LOAD_NULL("Text file's first line was null"), EXCEPTION_BOOK_LOAD_FAILED("Unable to read text file"), - EXCEPTION_BOOK_UNKNOWN_EXTENSION("Trying to load a book file with an unrecognized extension"); + EXCEPTION_BOOK_UNKNOWN_EXTENSION("Trying to load a book file with an unrecognized extension"), + EXCEPTION_UNEXPECTED_ENCRYPTED_BOOK("Attempted to load a normal book, but found an encrypted book instead"), + ; private final @NotNull String messageString; diff --git a/src/main/java/net/knarcraft/bookswithoutborders/thread/MigrationQueueThread.java b/src/main/java/net/knarcraft/bookswithoutborders/thread/MigrationQueueThread.java index 9291640..f3a83b0 100644 --- a/src/main/java/net/knarcraft/bookswithoutborders/thread/MigrationQueueThread.java +++ b/src/main/java/net/knarcraft/bookswithoutborders/thread/MigrationQueueThread.java @@ -95,16 +95,23 @@ public class MigrationQueueThread implements Runnable { EncryptedBook encryptedBook = null; BookMeta loadedBook = null; String extension = BookFileHelper.getExtensionFromPath(file.getName()); + + if (!extension.equalsIgnoreCase("txt") && !extension.equalsIgnoreCase("yml")) { + BooksWithoutBorders.log(Level.WARNING, "File with unexpected extension " + extension + " encountered!"); + return true; + } + + // Attempt loading an encrypted book if necessary if (file.getAbsolutePath().contains("Books" + slash + "Encrypted")) { - encryptedBook = BookToFromTextHelper.encryptedBookFromYml(file, bookMeta, "", true); + encryptedBook = BookToFromTextHelper.encryptedBookFromYml(file, bookMeta, "", true, true); if (encryptedBook != null) { loadedBook = encryptedBook.bookMeta(); } - } else if (extension.equalsIgnoreCase("txt") || extension.equalsIgnoreCase("yml")) { + } + + // Attempt to load the book normally + if (loadedBook == null) { loadedBook = BookToFromTextHelper.bookFromFile(file, bookMeta); - } else { - BooksWithoutBorders.log(Level.WARNING, "File with unexpected extension " + extension + " encountered!"); - return true; } if (loadedBook == null) { diff --git a/src/main/java/net/knarcraft/bookswithoutborders/utility/BookToFromTextHelper.java b/src/main/java/net/knarcraft/bookswithoutborders/utility/BookToFromTextHelper.java index 56b3b42..ac8234b 100644 --- a/src/main/java/net/knarcraft/bookswithoutborders/utility/BookToFromTextHelper.java +++ b/src/main/java/net/knarcraft/bookswithoutborders/utility/BookToFromTextHelper.java @@ -44,7 +44,7 @@ public final class BookToFromTextHelper { if (file.getName().endsWith(".txt")) { return bookFromTXT(file, bookMetadata); } else if (file.getName().endsWith(".yml")) { - return bookFromYml(file, bookMetadata); + return bookFromYml(file, bookMetadata, false); } else { throw new IllegalArgumentException(StaticMessage.EXCEPTION_BOOK_UNKNOWN_EXTENSION.toString()); } @@ -100,7 +100,8 @@ public final class BookToFromTextHelper { } // Make sure the plaintext cannot simply be seen in the file - if (BooksWithoutBorders.getConfiguration().useRealEncryption()) { + if (BooksWithoutBorders.getConfiguration().useRealEncryption() && + encryptedBook.encryptionStyle() == EncryptionStyle.AES) { bookYml.set("Pages", null); } @@ -110,19 +111,21 @@ public final class BookToFromTextHelper { /** * Loads a book from a .yml file * - * @param file

The path of the file to load

- * @param bookMetadata

Metadata which will be altered with the book's contents

- * @param userKey

The user-supplied decryption key

- * @param forceDecrypt

Whether to use the saved key for decryption, ignoring the supplied key

+ * @param file

The path of the file to load

+ * @param bookMetadata

Metadata which will be altered with the book's contents

+ * @param userKey

The user-supplied decryption key

+ * @param forceDecrypt

Whether to use the saved key for decryption, ignoring the supplied key

+ * @param loadEncrypted

Whether to load the book in its encrypted form, even if it cannot be admin decrypted

* @return

Metadata for the loaded book

*/ @Nullable public static EncryptedBook encryptedBookFromYml(@NotNull File file, @NotNull BookMeta bookMetadata, - @NotNull String userKey, boolean forceDecrypt) { + @NotNull String userKey, boolean forceDecrypt, + boolean loadEncrypted) { BookMeta meta; try { - meta = bookFromYml(file, bookMetadata); + meta = bookFromYml(file, bookMetadata, true); if (meta == null) { return null; } @@ -146,8 +149,12 @@ public final class BookToFromTextHelper { List data = bookYml.getStringList("Encryption.Data"); - EncryptionStyle encryptionStyle = EncryptionStyle.getFromString(bookYml.getString("Encryption.Style", - EncryptionStyle.SUBSTITUTION.toString())); + // If encryption style is null, that means the book was not encrypted in a way this can decrypt + String encryptionStyleName = bookYml.getString("Encryption.Style"); + if (encryptionStyleName == null) { + return null; + } + EncryptionStyle encryptionStyle = EncryptionStyle.getFromString(encryptionStyleName); AESConfiguration aesConfiguration = null; if (encryptionStyle == EncryptionStyle.AES) { @@ -174,11 +181,12 @@ public final class BookToFromTextHelper { userKey, false); if (decryptedPages != null && !decryptedPages.isEmpty()) { meta.setPages(decryptedPages); + return encryptedBook; + } else if (loadEncrypted) { + return encryptedBook; } else { return null; } - - return encryptedBook; } /** @@ -218,25 +226,36 @@ public final class BookToFromTextHelper { * * @param file

The path of the file to load

* @param bookMetadata

Metadata which will be altered with the book's contents

+ * @param isEncrypted

Whether the book is expected to be encrypted

* @return

Metadata for the loaded book

*/ @Nullable - private static BookMeta bookFromYml(@NotNull File file, @NotNull BookMeta bookMetadata) { + private static BookMeta bookFromYml(@NotNull File file, @NotNull BookMeta bookMetadata, boolean isEncrypted) { StringFormatter stringFormatter = BooksWithoutBorders.getStringFormatter(); - try { - FileConfiguration bookYml = YamlConfiguration.loadConfiguration(file); - bookMetadata.setGeneration(BookMeta.Generation.valueOf(bookYml.getString("Generation", "ORIGINAL"))); - bookMetadata.setTitle(bookYml.getString("Title", - stringFormatter.getUnFormattedColoredMessage(Formatting.NEUTRAL_UNKNOWN_TITLE))); - bookMetadata.setAuthor(authorFromUUID(bookYml.getString("Author", - stringFormatter.getUnFormattedColoredMessage(Formatting.NEUTRAL_UNKNOWN_AUTHOR)))); - bookMetadata.setPages(bookYml.getStringList("Pages")); - bookMetadata.setLore(bookYml.getStringList("Lore")); - bookMetadata.setDisplayName(bookYml.getString("DisplayName")); - } catch (IllegalArgumentException exception) { + FileConfiguration bookYml = YamlConfiguration.loadConfiguration(file); + + // Don't allow encrypted books to be loaded unless known to be encrypted + String encryptionStyleName = bookYml.getString("Encryption.Style"); + if (!isEncrypted && encryptionStyleName != null) { + BooksWithoutBorders.log(Level.WARNING, StaticMessage.EXCEPTION_UNEXPECTED_ENCRYPTED_BOOK.toString()); return null; } + + try { + bookMetadata.setGeneration(BookMeta.Generation.valueOf(bookYml.getString("Generation", "ORIGINAL"))); + } catch (IllegalArgumentException exception) { + BooksWithoutBorders.log(Level.FINE, exception.getMessage()); + return null; + } + + bookMetadata.setTitle(bookYml.getString("Title", + stringFormatter.getUnFormattedColoredMessage(Formatting.NEUTRAL_UNKNOWN_TITLE))); + bookMetadata.setAuthor(authorFromUUID(bookYml.getString("Author", + stringFormatter.getUnFormattedColoredMessage(Formatting.NEUTRAL_UNKNOWN_AUTHOR)))); + bookMetadata.setPages(bookYml.getStringList("Pages")); + bookMetadata.setLore(bookYml.getStringList("Lore")); + bookMetadata.setDisplayName(bookYml.getString("DisplayName")); return bookMetadata; } diff --git a/src/main/java/net/knarcraft/bookswithoutborders/utility/EncryptionHelper.java b/src/main/java/net/knarcraft/bookswithoutborders/utility/EncryptionHelper.java index 03daa15..42ea4d5 100644 --- a/src/main/java/net/knarcraft/bookswithoutborders/utility/EncryptionHelper.java +++ b/src/main/java/net/knarcraft/bookswithoutborders/utility/EncryptionHelper.java @@ -275,7 +275,7 @@ public final class EncryptionHelper { return null; } else { try { - EncryptedBook book = BookToFromTextHelper.encryptedBookFromYml(file, bookMetadata, key, forceDecrypt); + EncryptedBook book = BookToFromTextHelper.encryptedBookFromYml(file, bookMetadata, key, forceDecrypt, false); if (book == null) { throw new IllegalArgumentException(); } else {