From 1ddd50e5df930d57ab1a797ac64cd970b5522099 Mon Sep 17 00:00:00 2001 From: EpicKnarvik97 Date: Wed, 1 Sep 2021 23:02:54 +0200 Subject: [PATCH] Moves book to text code to its own class, and moves lots of encryption code to the encryption helper --- .../BooksWithoutBorders.java | 423 ++---------------- .../command/CommandDecrypt.java | 4 +- .../command/CommandEncrypt.java | 3 +- .../BooksWithoutBordersListener.java | 7 +- .../utility/BookToFromTextHelper.java | 161 +++++++ .../utility/EncryptionHelper.java | 259 +++++++++++ 6 files changed, 471 insertions(+), 386 deletions(-) rename src/main/java/net/knarcraft/bookswithoutborders/{ => listener}/BooksWithoutBordersListener.java (98%) create mode 100644 src/main/java/net/knarcraft/bookswithoutborders/utility/BookToFromTextHelper.java diff --git a/src/main/java/net/knarcraft/bookswithoutborders/BooksWithoutBorders.java b/src/main/java/net/knarcraft/bookswithoutborders/BooksWithoutBorders.java index bcb7359..ed8c69d 100644 --- a/src/main/java/net/knarcraft/bookswithoutborders/BooksWithoutBorders.java +++ b/src/main/java/net/knarcraft/bookswithoutborders/BooksWithoutBorders.java @@ -1,25 +1,30 @@ package net.knarcraft.bookswithoutborders; -import java.io.BufferedReader; -import java.io.File; -import java.io.FileReader; -import java.io.FileWriter; -import java.io.IOException; -import java.io.PrintWriter; -import java.util.ArrayList; -import java.util.Arrays; -import java.util.HashMap; -import java.util.List; -import java.util.Map; -import java.util.Objects; - -import net.knarcraft.bookswithoutborders.command.*; -import net.knarcraft.bookswithoutborders.state.EncryptionStyle; +import net.knarcraft.bookswithoutborders.command.CommandBooksWithoutBorders; +import net.knarcraft.bookswithoutborders.command.CommandCopy; +import net.knarcraft.bookswithoutborders.command.CommandDecrypt; +import net.knarcraft.bookswithoutborders.command.CommandDelete; +import net.knarcraft.bookswithoutborders.command.CommandDeletePublic; +import net.knarcraft.bookswithoutborders.command.CommandEncrypt; +import net.knarcraft.bookswithoutborders.command.CommandGive; +import net.knarcraft.bookswithoutborders.command.CommandGivePublic; +import net.knarcraft.bookswithoutborders.command.CommandGroupEncrypt; +import net.knarcraft.bookswithoutborders.command.CommandLoad; +import net.knarcraft.bookswithoutborders.command.CommandLoadPublic; +import net.knarcraft.bookswithoutborders.command.CommandReload; +import net.knarcraft.bookswithoutborders.command.CommandSave; +import net.knarcraft.bookswithoutborders.command.CommandSavePublic; +import net.knarcraft.bookswithoutborders.command.CommandSetAuthor; +import net.knarcraft.bookswithoutborders.command.CommandSetBookPrice; +import net.knarcraft.bookswithoutborders.command.CommandSetLore; +import net.knarcraft.bookswithoutborders.command.CommandSetTitle; +import net.knarcraft.bookswithoutborders.command.CommandUnSign; +import net.knarcraft.bookswithoutborders.command.GiveTabCompleter; +import net.knarcraft.bookswithoutborders.listener.BooksWithoutBordersListener; import net.knarcraft.bookswithoutborders.utility.BookFormatter; -import net.knarcraft.bookswithoutborders.utility.EncryptionHelper; +import net.knarcraft.bookswithoutborders.utility.BookToFromTextHelper; import net.knarcraft.bookswithoutborders.utility.FileHelper; import net.knarcraft.bookswithoutborders.utility.InputCleaningHelper; -import net.knarcraft.bookswithoutborders.utility.InventoryHelper; import net.milkbowl.vault.economy.Economy; import org.bukkit.ChatColor; import org.bukkit.Material; @@ -40,6 +45,19 @@ import org.bukkit.plugin.Plugin; import org.bukkit.plugin.RegisteredServiceProvider; import org.bukkit.plugin.java.JavaPlugin; +import java.io.BufferedReader; +import java.io.File; +import java.io.FileReader; +import java.io.FileWriter; +import java.io.IOException; +import java.io.PrintWriter; +import java.util.ArrayList; +import java.util.Arrays; +import java.util.HashMap; +import java.util.List; +import java.util.Map; +import java.util.Objects; + import static net.knarcraft.bookswithoutborders.utility.InputCleaningHelper.cleanString; import static net.knarcraft.bookswithoutborders.utility.InputCleaningHelper.fixName; @@ -49,20 +67,20 @@ public class BooksWithoutBorders extends JavaPlugin { public static String titleAuthorSeparator; public static String loreSeparator; public static final String SLASH = System.getProperty("file.separator"); - protected static List firstBooks; - protected static String welcomeMessage; + public static List firstBooks; + public static String welcomeMessage; protected static List existingPlayers; public static Economy eco; public static Material bookPriceType = null; public static double bookPriceQuantity; public static boolean authorOnlyCopy; - protected static boolean useYml; + public static boolean useYml; public static boolean adminDecrypt; protected static ItemFactory itemFactory; public static Map> loadList; public static BooksWithoutBorders bwb; protected static BooksWithoutBordersListener bL; - protected static ConsoleCommandSender consoleSender; + public static ConsoleCommandSender consoleSender; public static String bookFolder; public static final ChatColor errorColor = ChatColor.RED; public static final ChatColor successColor = ChatColor.GREEN; @@ -323,7 +341,7 @@ public class BooksWithoutBorders extends JavaPlugin { } } - protected boolean hasPlayedBefore(String playerName) { + public boolean hasPlayedBefore(String playerName) { if (!existingPlayers.contains(playerName)) { addExistingPlayer(playerName); return false; @@ -332,110 +350,6 @@ public class BooksWithoutBorders extends JavaPlugin { return true; } - protected void bookToYml(String path, String fileName, BookMeta book) throws IOException { - FileConfiguration bookYml = YamlConfiguration.loadConfiguration(new File(path, "blank")); - - if (book.hasTitle()) - bookYml.set("Title", book.getTitle()); - if (book.hasAuthor()) - bookYml.set("Author", book.getAuthor()); - if (book.hasPages()) - bookYml.set("Pages", book.getPages()); - if (book.hasLore()) - bookYml.set("Lore", book.getLore()); - - bookYml.save(path + fileName + ".yml"); - } - - protected BookMeta bookFromYml(File file, BookMeta bDat) { - //Handles old style loading - if (file.getName().substring(file.getName().lastIndexOf(".")).equals(".txt")) - bDat = bookFromTXT(file.getName(), file, bDat); - else { - try { - FileConfiguration bookYml = YamlConfiguration.loadConfiguration(file); - - bDat.setTitle(bookYml.getString("Title", "Untitled")); - bDat.setAuthor(bookYml.getString("Author", "Unknown")); - bDat.setPages(bookYml.getStringList("Pages")); - bDat.setLore(bookYml.getStringList("Lore")); - } catch (IllegalArgumentException e) { - return null; - } - } - - return bDat; - } - - protected void bookToTXT(String path, String fileName, BookMeta book) throws IOException { - FileWriter fw = new FileWriter(path + fileName + ".txt"); - PrintWriter pw = new PrintWriter(fw); - List pages = book.getPages(); - - pw.println("[Book]"); - for (String page : pages) { - pw.println(page); - } - pw.close(); - } - - protected BookMeta bookFromTXT(String fileName, File file, BookMeta bDat) { - String author; - String title; - if (fileName.contains(titleAuthorSeparator)) { - author = fileName.substring(fileName.indexOf(titleAuthorSeparator) + 1, fileName.length() - 4); - title = fileName.substring(0, fileName.indexOf(titleAuthorSeparator)); - } else { - author = "Unknown"; - title = fileName.substring(0, fileName.length() - 4); - } - - title = fixName(title, true); - - List rawPages = new ArrayList<>(); - String nullCheck; - - try { - FileReader fileReader = new FileReader(file); - BufferedReader bufferedReader = new BufferedReader(fileReader); - - rawPages.add(bufferedReader.readLine()); - - if (rawPages.get(0) == null) { - bufferedReader.close(); - return null; - } - - //If a book is being loaded its content need not be adjusted - if (rawPages.get(0).equalsIgnoreCase("[Book]")) { - rawPages.remove(0); - nullCheck = bufferedReader.readLine(); - while (nullCheck != null) { - rawPages.add(nullCheck); - nullCheck = bufferedReader.readLine(); - } - } else { - //Adjusts content to page length - while (rawPages.get(rawPages.size() - 1) != null) { - BookFormatter.formatLastPage(rawPages); - rawPages.add(bufferedReader.readLine()); - } - } - bufferedReader.close(); - } catch (IOException e) { - e.printStackTrace(); - return null; - } - - List pages = new ArrayList<>(InputCleaningHelper.cleanList(rawPages)); - - bDat.setAuthor(author); - bDat.setTitle(title); - bDat.setPages(pages); - - return bDat; - } - /** * Saves a book to a file * @@ -512,9 +426,9 @@ public class BooksWithoutBorders extends JavaPlugin { try { if (useYml) { - bookToYml(savePath, fileName, book); + BookToFromTextHelper.bookToYml(savePath, fileName, book); } else { - bookToTXT(savePath, fileName, book); + BookToFromTextHelper.bookToTXT(savePath, fileName, book); } sendSuccessMessage(player, "Book Saved as \"" + fileName + "\""); @@ -564,7 +478,7 @@ public class BooksWithoutBorders extends JavaPlugin { book = new ItemStack(Material.WRITABLE_BOOK); } - bookFromYml(file, bookMetadata); + BookToFromTextHelper.bookFromYml(file, bookMetadata); if (bookMetadata == null) { sendErrorMessage(sender, "File was blank!!"); return null; @@ -665,152 +579,6 @@ public class BooksWithoutBorders extends JavaPlugin { } } - /** - * Saves an encrypted book to be decryptable for the given user - * - * @param player

The player encrypting the book

- * @param bookMetaData

Metadata for the book to encrypt

- * @param key

The key to use for encryption

- * @return

The new encrypted metadata for the book, or null if encryption failed

- */ - protected Boolean saveEncryptedBook(Player player, BookMeta bookMetaData, String key) { - String path = bookFolder + "Encrypted" + SLASH; - String fileName = (!bookMetaData.hasTitle()) ? "Untitled," + player.getName() : - bookMetaData.getTitle() + titleAuthorSeparator + bookMetaData.getAuthor(); - - fileName = "[" + key + "]" + fileName; - fileName = cleanString(fileName); - fileName = fixName(fileName, false); - - //cancels saving if file is already encrypted - File file = (useYml) ? new File(path + fileName + ".yml") : new File(path + fileName + ".txt"); - if (file.isFile()) { - return true; - } - - try { - bookToYml(path, fileName, bookMetaData); - } catch (IOException e) { - e.printStackTrace(); - sendErrorMessage(player, "Encryption failed!"); - return false; - } - return true; - } - - /** - * Saves an encrypted book to be decryptable for the given group - * - * @param player

The player trying to encrypt the book

- * @param bookMetadata

Metadata for the book to encrypt

- * @param groupName

The group which should be able to decrypt the book

- * @return

The new encrypted metadata for the book, or null if encryption failed

- */ - protected BookMeta saveEncryptedBookForGroup(Player player, BookMeta bookMetadata, String groupName) { - String path = bookFolder + "Encrypted" + SLASH + cleanString(groupName) + SLASH; - File dirTest = new File(path); - //Creates group dir - if (!dirTest.exists()) { - try { - if (!dirTest.mkdir()) { - sendErrorMessage(consoleSender, "Unable to create encryption group folder!"); - return null; - } - } catch (Exception e) { - e.printStackTrace(); - return null; - } - } - //Creates file - String fileName = (!bookMetadata.hasTitle()) ? "Untitled," + player.getName() : - bookMetadata.getTitle() + titleAuthorSeparator + bookMetadata.getAuthor(); - - fileName = cleanString(fileName); - fileName = fixName(fileName, false); - - List newLore = new ArrayList<>(); - newLore.add(ChatColor.GRAY + "[" + groupName + " encrypted]"); - if (bookMetadata.hasLore()) { - List oldLore = bookMetadata.getLore(); - if (oldLore != null) { - newLore.addAll(oldLore); - } - } - bookMetadata.setLore(newLore); - - //Save file - File file = (useYml) ? new File(path + fileName + ".yml") : new File(path + fileName + ".txt"); - if (!file.isFile()) { - try { - bookToYml(path, fileName, bookMetadata); - } catch (IOException e) { - e.printStackTrace(); - sendErrorMessage(player, "Group encrypted failed!"); - return null; - } - } - - return bookMetadata; - } - - /** - * Loads an encrypted book - * - * @param player

The player trying to load the book

- * @param key

The encryption key/password for decryption

- * @param deleteEncryptedFile

Whether to delete the plaintext file after decryption is finished

- * @return

The loaded book, or null if no book could be loaded

- */ - public ItemStack loadEncryptedBook(Player player, String key, boolean deleteEncryptedFile) { - ItemStack heldBook = InventoryHelper.getHeldBook(player, true); - BookMeta bookMetadata = (BookMeta) heldBook.getItemMeta(); - String path = bookFolder + "Encrypted" + SLASH; - - if (bookMetadata == null) { - return null; - } - - String fileName = (!bookMetadata.hasTitle()) ? "Untitled," + player.getName() : bookMetadata.getTitle() + - titleAuthorSeparator + bookMetadata.getAuthor(); - fileName = "[" + key + "]" + fileName; - fileName = cleanString(fileName); - fileName = fixName(fileName, false); - - File file = new File(path + fileName + ".yml"); - if (!file.isFile()) { - file = new File(path + fileName + ".txt"); - - if (!file.isFile()) { - sendErrorMessage(player, "Incorrect decryption key!"); - return null; - } - } else { - try { - bookMetadata = bookFromYml(file, bookMetadata); - } catch (Exception e) { - sendErrorMessage(player, "Decryption failed!"); - return null; - } - } - - if (deleteEncryptedFile) { - try { - if (!file.delete()) { - sendErrorMessage(consoleSender, "Book encryption data failed to delete upon decryption!"); - sendErrorMessage(consoleSender, "File location:" + file.getPath()); - } - } catch (Exception e) { - sendErrorMessage(consoleSender, "Book encryption data failed to delete upon decryption!"); - sendErrorMessage(consoleSender, "File location:" + file.getPath()); - } - } - - ItemStack newBook = new ItemStack(Material.WRITTEN_BOOK);//Book(book.getAuthor(), book.getTitle(), pages, 1, 387); - newBook.setItemMeta(bookMetadata); - newBook.setAmount(InventoryHelper.getHeldBook(player, true).getAmount()); - return newBook; - } - /** * Lists available files * @@ -829,111 +597,6 @@ public class BooksWithoutBorders extends JavaPlugin { return FileHelper.listFiles(sender, file, silent); } - /** - * Encrypts a book - * - * @param player

The player encrypting the book

- * @param mainHand

Whether the player is holding the book in its main hand

- * @param key

The key/password to use for encryption

- * @param style

The encryption style to use

- * @return

An encrypted version of the book

- */ - protected ItemStack encryptBook(Player player, boolean mainHand, String key, EncryptionStyle style) { - return encryptBook(player, mainHand, key, style, ""); - } - - /** - * Encrypts a book - * - * @param player

The player encrypting the book

- * @param mainHand

Whether the player is holding the book in its main hand

- * @param key

The key/password to use for encryption

- * @param style

The encryption style to use

- * @param groupName

The name of the group to encrypt for, or "" otherwise

- * @return

An encrypted version of the book

- */ - public ItemStack encryptBook(Player player, boolean mainHand, String key, EncryptionStyle style, String groupName) { - //converts user supplied key into integer form - String integerKey = EncryptionHelper.getNumberKeyFromStringKey(key); - - BookMeta book = InventoryHelper.getHeldBookMetadata(player, mainHand); - - if (!book.hasPages()) { - sendErrorMessage(player, "Book is empty!"); - return null; - } - - //Save the book's un-encrypted contents to a file - BookMeta newMetadata = saveBookPlaintext(groupName, player, book, integerKey); - if (newMetadata == null) { - return null; - } - - //Get the encrypted pages - List encryptedPages = EncryptionHelper.encryptBookPages(book, style, integerKey, player); - if (encryptedPages == null) { - return null; - } - - //Format the last page just in case - BookFormatter.formatLastPage(encryptedPages); - //Remove empty pages - List newPages = InputCleaningHelper.cleanList(encryptedPages); - - ItemStack encryptedBook = createEncryptedBook(book, newPages, player, newMetadata); - - sendSuccessMessage(player, "Book encrypted!"); - return encryptedBook; - } - - /** - * Creates a new encrypted book - * - * @param book

The book to encrypt

- * @param newPages

The new encrypted pages

- * @param player

The player encrypting the book

- * @param newMetadata

The new metadata of the book

- * @return

An encrypted version of the book

- */ - private ItemStack createEncryptedBook(BookMeta book, List newPages, Player player, BookMeta newMetadata) { - //Create the encrypted book - ItemStack encryptedBook = new ItemStack(Material.WRITTEN_BOOK); - book.setPages(newPages); - encryptedBook.setItemMeta(book); - - //Update item amount - encryptedBook.setAmount(InventoryHelper.getHeldBook(player, true).getAmount()); - //Set new item metadata - encryptedBook.setItemMeta(newMetadata); - - return encryptedBook; - } - - /** - * Saves a book's plain text to a file - * - * @param groupName

The group who's allowed to decrypt the book, or ""

- * @param player

The player trying to encrypt the book

- * @param book

The book to encrypt

- * @param integerKey

The key used to encrypt the book

- * @return

The new metadata for the book, or null if it could not be saved

- */ - private BookMeta saveBookPlaintext(String groupName, Player player, BookMeta book, String integerKey) { - BookMeta newMetadata = book; - boolean wasSaved; - if (groupName.trim().isEmpty()) { - wasSaved = saveEncryptedBook(player, book, integerKey); - } else { - newMetadata = saveEncryptedBookForGroup(player, book, groupName); - wasSaved = newMetadata != null; - } - if (wasSaved) { - return newMetadata; - } else { - return null; - } - } - /** * Sends a success message to a command sender (player or a console) * diff --git a/src/main/java/net/knarcraft/bookswithoutborders/command/CommandDecrypt.java b/src/main/java/net/knarcraft/bookswithoutborders/command/CommandDecrypt.java index 29a4cea..aaaec59 100644 --- a/src/main/java/net/knarcraft/bookswithoutborders/command/CommandDecrypt.java +++ b/src/main/java/net/knarcraft/bookswithoutborders/command/CommandDecrypt.java @@ -71,7 +71,7 @@ public class CommandDecrypt implements CommandExecutor { if (!key.equalsIgnoreCase("")) { //Decrypt the book - ItemStack book = booksWithoutBorders.loadEncryptedBook(player, key, false); + ItemStack book = EncryptionHelper.loadEncryptedBook(player, key, false); if (book != null) { InventoryHelper.setHeldWrittenBook(player, book); BooksWithoutBorders.sendSuccessMessage(player, "Book auto-decrypted!"); @@ -91,7 +91,7 @@ public class CommandDecrypt implements CommandExecutor { String key = EncryptionHelper.getNumberKeyFromStringKey(args[0]); //Decrypt the book - ItemStack book = booksWithoutBorders.loadEncryptedBook(player, key, true); + ItemStack book = EncryptionHelper.loadEncryptedBook(player, key, true); if (book != null) { InventoryHelper.setHeldWrittenBook(player, book); BooksWithoutBorders.sendSuccessMessage(player, "Book decrypted!"); diff --git a/src/main/java/net/knarcraft/bookswithoutborders/command/CommandEncrypt.java b/src/main/java/net/knarcraft/bookswithoutborders/command/CommandEncrypt.java index ef69cbc..e90bd48 100644 --- a/src/main/java/net/knarcraft/bookswithoutborders/command/CommandEncrypt.java +++ b/src/main/java/net/knarcraft/bookswithoutborders/command/CommandEncrypt.java @@ -2,6 +2,7 @@ package net.knarcraft.bookswithoutborders.command; import net.knarcraft.bookswithoutborders.BooksWithoutBorders; import net.knarcraft.bookswithoutborders.state.EncryptionStyle; +import net.knarcraft.bookswithoutborders.utility.EncryptionHelper; import net.knarcraft.bookswithoutborders.utility.InventoryHelper; import org.bukkit.command.Command; import org.bukkit.command.CommandExecutor; @@ -83,7 +84,7 @@ public class CommandEncrypt implements CommandExecutor { * @return

True if the book was encrypted successfully

*/ boolean encryptBook(EncryptionStyle encryptionStyle, Player player, String key, String group) { - ItemStack encryptedBook = booksWithoutBorders.encryptBook(player, true, key, encryptionStyle, group); + ItemStack encryptedBook = EncryptionHelper.encryptBook(player, true, key, encryptionStyle, group); if (encryptedBook != null) { InventoryHelper.setHeldWrittenBook(player, encryptedBook); diff --git a/src/main/java/net/knarcraft/bookswithoutborders/BooksWithoutBordersListener.java b/src/main/java/net/knarcraft/bookswithoutborders/listener/BooksWithoutBordersListener.java similarity index 98% rename from src/main/java/net/knarcraft/bookswithoutborders/BooksWithoutBordersListener.java rename to src/main/java/net/knarcraft/bookswithoutborders/listener/BooksWithoutBordersListener.java index f6b45ee..20c77d6 100644 --- a/src/main/java/net/knarcraft/bookswithoutborders/BooksWithoutBordersListener.java +++ b/src/main/java/net/knarcraft/bookswithoutborders/listener/BooksWithoutBordersListener.java @@ -1,9 +1,10 @@ -package net.knarcraft.bookswithoutborders; +package net.knarcraft.bookswithoutborders.listener; import java.io.File; import java.util.List; import java.util.Objects; +import net.knarcraft.bookswithoutborders.BooksWithoutBorders; import net.knarcraft.bookswithoutborders.state.EncryptionStyle; import net.knarcraft.bookswithoutborders.utility.EncryptionHelper; import net.knarcraft.bookswithoutborders.utility.FileHelper; @@ -390,7 +391,7 @@ public class BooksWithoutBordersListener implements Listener { boolean mainHand = hand == EquipmentSlot.HAND; if (heldItemType == Material.WRITTEN_BOOK) { player.closeInventory(); - eBook = BooksWithoutBorders.bwb.encryptBook(player, mainHand, ChatColor.stripColor(lines[2]), + eBook = EncryptionHelper.encryptBook(player, mainHand, ChatColor.stripColor(lines[2]), EncryptionStyle.getFromString(ChatColor.stripColor(lines[3]))); if (eBook != null) { player.getInventory().setItem(hand, eBook); @@ -447,7 +448,7 @@ public class BooksWithoutBordersListener implements Listener { String lineText = ChatColor.stripColor(sign.getLine(2)); String key = EncryptionHelper.getNumberKeyFromStringKey(lineText); - ItemStack book = BooksWithoutBorders.bwb.loadEncryptedBook(player, key, false); + ItemStack book = EncryptionHelper.loadEncryptedBook(player, key, false); if (book != null) { player.getInventory().setItem(hand, book); player.sendMessage(ChatColor.GREEN + "Book decrypted!"); diff --git a/src/main/java/net/knarcraft/bookswithoutborders/utility/BookToFromTextHelper.java b/src/main/java/net/knarcraft/bookswithoutborders/utility/BookToFromTextHelper.java new file mode 100644 index 0000000..dc952ba --- /dev/null +++ b/src/main/java/net/knarcraft/bookswithoutborders/utility/BookToFromTextHelper.java @@ -0,0 +1,161 @@ +package net.knarcraft.bookswithoutborders.utility; + +import net.knarcraft.bookswithoutborders.BooksWithoutBorders; +import org.bukkit.configuration.file.FileConfiguration; +import org.bukkit.configuration.file.YamlConfiguration; +import org.bukkit.inventory.meta.BookMeta; + +import java.io.BufferedReader; +import java.io.File; +import java.io.FileReader; +import java.io.FileWriter; +import java.io.IOException; +import java.io.PrintWriter; +import java.util.ArrayList; +import java.util.List; + +import static net.knarcraft.bookswithoutborders.utility.InputCleaningHelper.fixName; + +/** + * Helper class for converting books to and from text/yml files + */ +public final class BookToFromTextHelper { + + private BookToFromTextHelper() {} + + /** + * Saves a book's contents to a .yml file + * @param path

The path of the folder to save to. Must end with a slash

+ * @param fileName

The name of the file to load to

+ * @param bookMetadata

Metadata about the book to save

+ * @throws IOException

If unable to save the book

+ */ + public static void bookToYml(String path, String fileName, BookMeta bookMetadata) throws IOException { + FileConfiguration bookYml = YamlConfiguration.loadConfiguration(new File(path, "blank")); + + if (bookMetadata.hasTitle()) { + bookYml.set("Title", bookMetadata.getTitle()); + } + if (bookMetadata.hasAuthor()) { + bookYml.set("Author", bookMetadata.getAuthor()); + } + if (bookMetadata.hasPages()) { + bookYml.set("Pages", bookMetadata.getPages()); + } + if (bookMetadata.hasLore()) { + bookYml.set("Lore", bookMetadata.getLore()); + } + + bookYml.save(path + fileName + ".yml"); + } + + /** + * 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

+ * @return

Metadata for the loaded book

+ */ + public static BookMeta bookFromYml(File file, BookMeta bookMetadata) { + //Handles old style loading + if (file.getName().substring(file.getName().lastIndexOf(".")).equals(".txt")) + bookMetadata = bookFromTXT(file.getName(), file, bookMetadata); + else { + try { + FileConfiguration bookYml = YamlConfiguration.loadConfiguration(file); + + bookMetadata.setTitle(bookYml.getString("Title", "Untitled")); + bookMetadata.setAuthor(bookYml.getString("Author", "Unknown")); + bookMetadata.setPages(bookYml.getStringList("Pages")); + bookMetadata.setLore(bookYml.getStringList("Lore")); + } catch (IllegalArgumentException e) { + return null; + } + } + + return bookMetadata; + } + + /** + * Saves a book's contents to a text file + * @param folderPath

The folder path to save to. Must end with a slash

+ * @param fileName

The name of the file to save to

+ * @param bookMetadata

Metadata about the book to save

+ * @throws IOException

If unable to save the book

+ */ + public static void bookToTXT(String folderPath, String fileName, BookMeta bookMetadata) throws IOException { + FileWriter fileWriter = new FileWriter(folderPath + fileName + ".txt"); + PrintWriter printWriter = new PrintWriter(fileWriter); + List pages = bookMetadata.getPages(); + + printWriter.println("[Book]"); + for (String page : pages) { + printWriter.println(page); + } + printWriter.close(); + } + + /** + * Loads a book from a text file + * @param fileName

The name of the file to load. Used to create author and title

+ * @param file

The file to load

+ * @param bookMetadata

Metadata which will be altered with the book's contents

+ * @return

Metadata for the loaded book

+ */ + private static BookMeta bookFromTXT(String fileName, File file, BookMeta bookMetadata) { + String author; + String title; + if (fileName.contains(BooksWithoutBorders.titleAuthorSeparator)) { + author = fileName.substring(fileName.indexOf(BooksWithoutBorders.titleAuthorSeparator) + 1, fileName.length() - 4); + title = fileName.substring(0, fileName.indexOf(BooksWithoutBorders.titleAuthorSeparator)); + } else { + author = "Unknown"; + title = fileName.substring(0, fileName.length() - 4); + } + + title = fixName(title, true); + + List rawPages = new ArrayList<>(); + String nullCheck; + + try { + FileReader fileReader = new FileReader(file); + BufferedReader bufferedReader = new BufferedReader(fileReader); + + rawPages.add(bufferedReader.readLine()); + + if (rawPages.get(0) == null) { + bufferedReader.close(); + return null; + } + + //If a book is being loaded its content need not be adjusted + if (rawPages.get(0).equalsIgnoreCase("[Book]")) { + rawPages.remove(0); + nullCheck = bufferedReader.readLine(); + while (nullCheck != null) { + rawPages.add(nullCheck); + nullCheck = bufferedReader.readLine(); + } + } else { + //Adjusts content to page length + while (rawPages.get(rawPages.size() - 1) != null) { + BookFormatter.formatLastPage(rawPages); + rawPages.add(bufferedReader.readLine()); + } + } + bufferedReader.close(); + } catch (IOException e) { + e.printStackTrace(); + return null; + } + + List pages = new ArrayList<>(InputCleaningHelper.cleanList(rawPages)); + + bookMetadata.setAuthor(author); + bookMetadata.setTitle(title); + bookMetadata.setPages(pages); + + 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 3527433..d59db4e 100644 --- a/src/main/java/net/knarcraft/bookswithoutborders/utility/EncryptionHelper.java +++ b/src/main/java/net/knarcraft/bookswithoutborders/utility/EncryptionHelper.java @@ -4,12 +4,20 @@ import net.knarcraft.bookswithoutborders.BooksWithoutBorders; import net.knarcraft.bookswithoutborders.state.EncryptionStyle; import net.knarcraft.bookswithoutborders.GenenCrypt; import net.knarcraft.bookswithoutborders.SubstitutionCipher; +import org.bukkit.ChatColor; +import org.bukkit.Material; import org.bukkit.entity.Player; +import org.bukkit.inventory.ItemStack; import org.bukkit.inventory.meta.BookMeta; +import java.io.File; +import java.io.IOException; import java.util.ArrayList; import java.util.List; +import static net.knarcraft.bookswithoutborders.utility.InputCleaningHelper.cleanString; +import static net.knarcraft.bookswithoutborders.utility.InputCleaningHelper.fixName; + public class EncryptionHelper { /** @@ -56,4 +64,255 @@ public class EncryptionHelper { } } + /** + * Encrypts a book + * + * @param player

The player encrypting the book

+ * @param mainHand

Whether the player is holding the book in its main hand

+ * @param key

The key/password to use for encryption

+ * @param style

The encryption style to use

+ * @return

An encrypted version of the book

+ */ + public static ItemStack encryptBook(Player player, boolean mainHand, String key, EncryptionStyle style) { + return encryptBook(player, mainHand, key, style, ""); + } + + /** + * Encrypts a book + * + * @param player

The player encrypting the book

+ * @param mainHand

Whether the player is holding the book in its main hand

+ * @param key

The key/password to use for encryption

+ * @param style

The encryption style to use

+ * @param groupName

The name of the group to encrypt for, or "" otherwise

+ * @return

An encrypted version of the book

+ */ + public static ItemStack encryptBook(Player player, boolean mainHand, String key, EncryptionStyle style, String groupName) { + //converts user supplied key into integer form + String integerKey = EncryptionHelper.getNumberKeyFromStringKey(key); + + BookMeta book = InventoryHelper.getHeldBookMetadata(player, mainHand); + + if (!book.hasPages()) { + BooksWithoutBorders.sendErrorMessage(player, "Book is empty!"); + return null; + } + + //Save the book's un-encrypted contents to a file + BookMeta newMetadata = saveBookPlaintext(groupName, player, book, integerKey); + if (newMetadata == null) { + return null; + } + + //Get the encrypted pages + List encryptedPages = EncryptionHelper.encryptBookPages(book, style, integerKey, player); + if (encryptedPages == null) { + return null; + } + + //Format the last page just in case + BookFormatter.formatLastPage(encryptedPages); + //Remove empty pages + List newPages = InputCleaningHelper.cleanList(encryptedPages); + + ItemStack encryptedBook = createEncryptedBook(book, newPages, player, newMetadata); + + BooksWithoutBorders.sendSuccessMessage(player, "Book encrypted!"); + return encryptedBook; + } + + /** + * Creates a new encrypted book + * + * @param book

The book to encrypt

+ * @param newPages

The new encrypted pages

+ * @param player

The player encrypting the book

+ * @param newMetadata

The new metadata of the book

+ * @return

An encrypted version of the book

+ */ + private static ItemStack createEncryptedBook(BookMeta book, List newPages, Player player, BookMeta newMetadata) { + //Create the encrypted book + ItemStack encryptedBook = new ItemStack(Material.WRITTEN_BOOK); + book.setPages(newPages); + encryptedBook.setItemMeta(book); + + //Update item amount + encryptedBook.setAmount(InventoryHelper.getHeldBook(player, true).getAmount()); + //Set new item metadata + encryptedBook.setItemMeta(newMetadata); + + return encryptedBook; + } + + /** + * Saves a book's plain text to a file + * + * @param groupName

The group who's allowed to decrypt the book, or ""

+ * @param player

The player trying to encrypt the book

+ * @param book

The book to encrypt

+ * @param integerKey

The key used to encrypt the book

+ * @return

The new metadata for the book, or null if it could not be saved

+ */ + private static BookMeta saveBookPlaintext(String groupName, Player player, BookMeta book, String integerKey) { + BookMeta newMetadata = book; + boolean wasSaved; + if (groupName.trim().isEmpty()) { + wasSaved = saveEncryptedBook(player, book, integerKey); + } else { + newMetadata = saveEncryptedBookForGroup(player, book, groupName); + wasSaved = newMetadata != null; + } + if (wasSaved) { + return newMetadata; + } else { + return null; + } + } + + /** + * Loads an encrypted book + * + * @param player

The player trying to load the book

+ * @param key

The encryption key/password for decryption

+ * @param deleteEncryptedFile

Whether to delete the plaintext file after decryption is finished

+ * @return

The loaded book, or null if no book could be loaded

+ */ + public static ItemStack loadEncryptedBook(Player player, String key, boolean deleteEncryptedFile) { + ItemStack heldBook = InventoryHelper.getHeldBook(player, true); + BookMeta bookMetadata = (BookMeta) heldBook.getItemMeta(); + String path = BooksWithoutBorders.bookFolder + "Encrypted" + BooksWithoutBorders.SLASH; + + if (bookMetadata == null) { + return null; + } + + String fileName = (!bookMetadata.hasTitle()) ? "Untitled," + player.getName() : bookMetadata.getTitle() + + BooksWithoutBorders.titleAuthorSeparator + bookMetadata.getAuthor(); + fileName = "[" + key + "]" + fileName; + fileName = cleanString(fileName); + fileName = fixName(fileName, false); + + File file = new File(path + fileName + ".yml"); + if (!file.isFile()) { + file = new File(path + fileName + ".txt"); + + if (!file.isFile()) { + BooksWithoutBorders.sendErrorMessage(player, "Incorrect decryption key!"); + return null; + } + } else { + try { + bookMetadata = BookToFromTextHelper.bookFromYml(file, bookMetadata); + } catch (Exception e) { + BooksWithoutBorders.sendErrorMessage(player, "Decryption failed!"); + return null; + } + } + + if (deleteEncryptedFile) { + try { + if (!file.delete()) { + BooksWithoutBorders.sendErrorMessage(BooksWithoutBorders.consoleSender, "Book encryption data failed to delete upon decryption!"); + BooksWithoutBorders.sendErrorMessage(BooksWithoutBorders.consoleSender, "File location:" + file.getPath()); + } + } catch (Exception e) { + BooksWithoutBorders.sendErrorMessage(BooksWithoutBorders.consoleSender, "Book encryption data failed to delete upon decryption!"); + BooksWithoutBorders.sendErrorMessage(BooksWithoutBorders.consoleSender, "File location:" + file.getPath()); + } + } + + ItemStack newBook = new ItemStack(Material.WRITTEN_BOOK);//Book(book.getAuthor(), book.getTitle(), pages, 1, 387); + newBook.setItemMeta(bookMetadata); + newBook.setAmount(InventoryHelper.getHeldBook(player, true).getAmount()); + return newBook; + } + + /** + * Saves an encrypted book to be decryptable for the given group + * + * @param player

The player trying to encrypt the book

+ * @param bookMetadata

Metadata for the book to encrypt

+ * @param groupName

The group which should be able to decrypt the book

+ * @return

The new encrypted metadata for the book, or null if encryption failed

+ */ + protected static BookMeta saveEncryptedBookForGroup(Player player, BookMeta bookMetadata, String groupName) { + String path = BooksWithoutBorders.bookFolder + "Encrypted" + BooksWithoutBorders.SLASH + cleanString(groupName) + BooksWithoutBorders.SLASH; + File dirTest = new File(path); + //Creates group dir + if (!dirTest.exists()) { + try { + if (!dirTest.mkdir()) { + BooksWithoutBorders.sendErrorMessage(BooksWithoutBorders.consoleSender, "Unable to create encryption group folder!"); + return null; + } + } catch (Exception e) { + e.printStackTrace(); + return null; + } + } + //Creates file + String fileName = (!bookMetadata.hasTitle()) ? "Untitled," + player.getName() : + bookMetadata.getTitle() + BooksWithoutBorders.titleAuthorSeparator + bookMetadata.getAuthor(); + + fileName = cleanString(fileName); + fileName = fixName(fileName, false); + + List newLore = new ArrayList<>(); + newLore.add(ChatColor.GRAY + "[" + groupName + " encrypted]"); + if (bookMetadata.hasLore()) { + List oldLore = bookMetadata.getLore(); + if (oldLore != null) { + newLore.addAll(oldLore); + } + } + bookMetadata.setLore(newLore); + + //Save file + File file = (BooksWithoutBorders.useYml) ? new File(path + fileName + ".yml") : new File(path + fileName + ".txt"); + if (!file.isFile()) { + try { + BookToFromTextHelper.bookToYml(path, fileName, bookMetadata); + } catch (IOException e) { + e.printStackTrace(); + BooksWithoutBorders.sendErrorMessage(player, "Group encrypted failed!"); + return null; + } + } + + return bookMetadata; + } + + /** + * Saves an encrypted book to be decryptable for the given user + * + * @param player

The player encrypting the book

+ * @param bookMetaData

Metadata for the book to encrypt

+ * @param key

The key to use for encryption

+ * @return

The new encrypted metadata for the book, or null if encryption failed

+ */ + protected static Boolean saveEncryptedBook(Player player, BookMeta bookMetaData, String key) { + String path = BooksWithoutBorders.bookFolder + "Encrypted" + BooksWithoutBorders.SLASH; + String fileName = (!bookMetaData.hasTitle()) ? "Untitled," + player.getName() : + bookMetaData.getTitle() + BooksWithoutBorders.titleAuthorSeparator + bookMetaData.getAuthor(); + + fileName = "[" + key + "]" + fileName; + fileName = cleanString(fileName); + fileName = fixName(fileName, false); + + //cancels saving if file is already encrypted + File file = (BooksWithoutBorders.useYml) ? new File(path + fileName + ".yml") : new File(path + fileName + ".txt"); + if (file.isFile()) { + return true; + } + + try { + BookToFromTextHelper.bookToYml(path, fileName, bookMetaData); + } catch (IOException e) { + e.printStackTrace(); + BooksWithoutBorders.sendErrorMessage(player, "Encryption failed!"); + return false; + } + return true; + } + }