Moves book to text code to its own class, and moves lots of encryption code to the encryption helper

This commit is contained in:
Kristian Knarvik 2021-09-01 23:02:54 +02:00
parent 8defb301bc
commit 1ddd50e5df
6 changed files with 471 additions and 386 deletions

View File

@ -1,25 +1,30 @@
package net.knarcraft.bookswithoutborders; package net.knarcraft.bookswithoutborders;
import java.io.BufferedReader; import net.knarcraft.bookswithoutborders.command.CommandBooksWithoutBorders;
import java.io.File; import net.knarcraft.bookswithoutborders.command.CommandCopy;
import java.io.FileReader; import net.knarcraft.bookswithoutborders.command.CommandDecrypt;
import java.io.FileWriter; import net.knarcraft.bookswithoutborders.command.CommandDelete;
import java.io.IOException; import net.knarcraft.bookswithoutborders.command.CommandDeletePublic;
import java.io.PrintWriter; import net.knarcraft.bookswithoutborders.command.CommandEncrypt;
import java.util.ArrayList; import net.knarcraft.bookswithoutborders.command.CommandGive;
import java.util.Arrays; import net.knarcraft.bookswithoutborders.command.CommandGivePublic;
import java.util.HashMap; import net.knarcraft.bookswithoutborders.command.CommandGroupEncrypt;
import java.util.List; import net.knarcraft.bookswithoutborders.command.CommandLoad;
import java.util.Map; import net.knarcraft.bookswithoutborders.command.CommandLoadPublic;
import java.util.Objects; import net.knarcraft.bookswithoutborders.command.CommandReload;
import net.knarcraft.bookswithoutborders.command.CommandSave;
import net.knarcraft.bookswithoutborders.command.*; import net.knarcraft.bookswithoutborders.command.CommandSavePublic;
import net.knarcraft.bookswithoutborders.state.EncryptionStyle; 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.BookFormatter;
import net.knarcraft.bookswithoutborders.utility.EncryptionHelper; import net.knarcraft.bookswithoutborders.utility.BookToFromTextHelper;
import net.knarcraft.bookswithoutborders.utility.FileHelper; import net.knarcraft.bookswithoutborders.utility.FileHelper;
import net.knarcraft.bookswithoutborders.utility.InputCleaningHelper; import net.knarcraft.bookswithoutborders.utility.InputCleaningHelper;
import net.knarcraft.bookswithoutborders.utility.InventoryHelper;
import net.milkbowl.vault.economy.Economy; import net.milkbowl.vault.economy.Economy;
import org.bukkit.ChatColor; import org.bukkit.ChatColor;
import org.bukkit.Material; import org.bukkit.Material;
@ -40,6 +45,19 @@ import org.bukkit.plugin.Plugin;
import org.bukkit.plugin.RegisteredServiceProvider; import org.bukkit.plugin.RegisteredServiceProvider;
import org.bukkit.plugin.java.JavaPlugin; 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.cleanString;
import static net.knarcraft.bookswithoutborders.utility.InputCleaningHelper.fixName; import static net.knarcraft.bookswithoutborders.utility.InputCleaningHelper.fixName;
@ -49,20 +67,20 @@ public class BooksWithoutBorders extends JavaPlugin {
public static String titleAuthorSeparator; public static String titleAuthorSeparator;
public static String loreSeparator; public static String loreSeparator;
public static final String SLASH = System.getProperty("file.separator"); public static final String SLASH = System.getProperty("file.separator");
protected static List<String> firstBooks; public static List<String> firstBooks;
protected static String welcomeMessage; public static String welcomeMessage;
protected static List<String> existingPlayers; protected static List<String> existingPlayers;
public static Economy eco; public static Economy eco;
public static Material bookPriceType = null; public static Material bookPriceType = null;
public static double bookPriceQuantity; public static double bookPriceQuantity;
public static boolean authorOnlyCopy; public static boolean authorOnlyCopy;
protected static boolean useYml; public static boolean useYml;
public static boolean adminDecrypt; public static boolean adminDecrypt;
protected static ItemFactory itemFactory; protected static ItemFactory itemFactory;
public static Map<String, List<String>> loadList; public static Map<String, List<String>> loadList;
public static BooksWithoutBorders bwb; public static BooksWithoutBorders bwb;
protected static BooksWithoutBordersListener bL; protected static BooksWithoutBordersListener bL;
protected static ConsoleCommandSender consoleSender; public static ConsoleCommandSender consoleSender;
public static String bookFolder; public static String bookFolder;
public static final ChatColor errorColor = ChatColor.RED; public static final ChatColor errorColor = ChatColor.RED;
public static final ChatColor successColor = ChatColor.GREEN; 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)) { if (!existingPlayers.contains(playerName)) {
addExistingPlayer(playerName); addExistingPlayer(playerName);
return false; return false;
@ -332,110 +350,6 @@ public class BooksWithoutBorders extends JavaPlugin {
return true; 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<String> 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<String> 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<String> pages = new ArrayList<>(InputCleaningHelper.cleanList(rawPages));
bDat.setAuthor(author);
bDat.setTitle(title);
bDat.setPages(pages);
return bDat;
}
/** /**
* Saves a book to a file * Saves a book to a file
* *
@ -512,9 +426,9 @@ public class BooksWithoutBorders extends JavaPlugin {
try { try {
if (useYml) { if (useYml) {
bookToYml(savePath, fileName, book); BookToFromTextHelper.bookToYml(savePath, fileName, book);
} else { } else {
bookToTXT(savePath, fileName, book); BookToFromTextHelper.bookToTXT(savePath, fileName, book);
} }
sendSuccessMessage(player, "Book Saved as \"" + fileName + "\""); sendSuccessMessage(player, "Book Saved as \"" + fileName + "\"");
@ -564,7 +478,7 @@ public class BooksWithoutBorders extends JavaPlugin {
book = new ItemStack(Material.WRITABLE_BOOK); book = new ItemStack(Material.WRITABLE_BOOK);
} }
bookFromYml(file, bookMetadata); BookToFromTextHelper.bookFromYml(file, bookMetadata);
if (bookMetadata == null) { if (bookMetadata == null) {
sendErrorMessage(sender, "File was blank!!"); sendErrorMessage(sender, "File was blank!!");
return null; return null;
@ -665,152 +579,6 @@ public class BooksWithoutBorders extends JavaPlugin {
} }
} }
/**
* Saves an encrypted book to be decryptable for the given user
*
* @param player <p>The player encrypting the book</p>
* @param bookMetaData <p>Metadata for the book to encrypt</p>
* @param key <p>The key to use for encryption</p>
* @return <p>The new encrypted metadata for the book, or null if encryption failed</p>
*/
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 <p>The player trying to encrypt the book</p>
* @param bookMetadata <p>Metadata for the book to encrypt</p>
* @param groupName <p>The group which should be able to decrypt the book</p>
* @return <p>The new encrypted metadata for the book, or null if encryption failed</p>
*/
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<String> newLore = new ArrayList<>();
newLore.add(ChatColor.GRAY + "[" + groupName + " encrypted]");
if (bookMetadata.hasLore()) {
List<String> 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 <p>The player trying to load the book</p>
* @param key <p>The encryption key/password for decryption</p>
* @param deleteEncryptedFile <p>Whether to delete the plaintext file after decryption is finished</p>
* @return <p>The loaded book, or null if no book could be loaded</p>
*/
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 * Lists available files
* *
@ -829,111 +597,6 @@ public class BooksWithoutBorders extends JavaPlugin {
return FileHelper.listFiles(sender, file, silent); return FileHelper.listFiles(sender, file, silent);
} }
/**
* Encrypts a book
*
* @param player <p>The player encrypting the book</p>
* @param mainHand <p>Whether the player is holding the book in its main hand</p>
* @param key <p>The key/password to use for encryption</p>
* @param style <p>The encryption style to use</p>
* @return <p>An encrypted version of the book</p>
*/
protected ItemStack encryptBook(Player player, boolean mainHand, String key, EncryptionStyle style) {
return encryptBook(player, mainHand, key, style, "");
}
/**
* Encrypts a book
*
* @param player <p>The player encrypting the book</p>
* @param mainHand <p>Whether the player is holding the book in its main hand</p>
* @param key <p>The key/password to use for encryption</p>
* @param style <p>The encryption style to use</p>
* @param groupName <p>The name of the group to encrypt for, or "" otherwise</p>
* @return <p>An encrypted version of the book</p>
*/
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<String> 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<String> newPages = InputCleaningHelper.cleanList(encryptedPages);
ItemStack encryptedBook = createEncryptedBook(book, newPages, player, newMetadata);
sendSuccessMessage(player, "Book encrypted!");
return encryptedBook;
}
/**
* Creates a new encrypted book
*
* @param book <p>The book to encrypt</p>
* @param newPages <p>The new encrypted pages</p>
* @param player <p>The player encrypting the book</p>
* @param newMetadata <p>The new metadata of the book</p>
* @return <p>An encrypted version of the book</p>
*/
private ItemStack createEncryptedBook(BookMeta book, List<String> 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 <p>The group who's allowed to decrypt the book, or ""</p>
* @param player <p>The player trying to encrypt the book</p>
* @param book <p>The book to encrypt</p>
* @param integerKey <p>The key used to encrypt the book</p>
* @return <p>The new metadata for the book, or null if it could not be saved</p>
*/
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) * Sends a success message to a command sender (player or a console)
* *

View File

@ -71,7 +71,7 @@ public class CommandDecrypt implements CommandExecutor {
if (!key.equalsIgnoreCase("")) { if (!key.equalsIgnoreCase("")) {
//Decrypt the book //Decrypt the book
ItemStack book = booksWithoutBorders.loadEncryptedBook(player, key, false); ItemStack book = EncryptionHelper.loadEncryptedBook(player, key, false);
if (book != null) { if (book != null) {
InventoryHelper.setHeldWrittenBook(player, book); InventoryHelper.setHeldWrittenBook(player, book);
BooksWithoutBorders.sendSuccessMessage(player, "Book auto-decrypted!"); BooksWithoutBorders.sendSuccessMessage(player, "Book auto-decrypted!");
@ -91,7 +91,7 @@ public class CommandDecrypt implements CommandExecutor {
String key = EncryptionHelper.getNumberKeyFromStringKey(args[0]); String key = EncryptionHelper.getNumberKeyFromStringKey(args[0]);
//Decrypt the book //Decrypt the book
ItemStack book = booksWithoutBorders.loadEncryptedBook(player, key, true); ItemStack book = EncryptionHelper.loadEncryptedBook(player, key, true);
if (book != null) { if (book != null) {
InventoryHelper.setHeldWrittenBook(player, book); InventoryHelper.setHeldWrittenBook(player, book);
BooksWithoutBorders.sendSuccessMessage(player, "Book decrypted!"); BooksWithoutBorders.sendSuccessMessage(player, "Book decrypted!");

View File

@ -2,6 +2,7 @@ package net.knarcraft.bookswithoutborders.command;
import net.knarcraft.bookswithoutborders.BooksWithoutBorders; import net.knarcraft.bookswithoutborders.BooksWithoutBorders;
import net.knarcraft.bookswithoutborders.state.EncryptionStyle; import net.knarcraft.bookswithoutborders.state.EncryptionStyle;
import net.knarcraft.bookswithoutborders.utility.EncryptionHelper;
import net.knarcraft.bookswithoutborders.utility.InventoryHelper; import net.knarcraft.bookswithoutborders.utility.InventoryHelper;
import org.bukkit.command.Command; import org.bukkit.command.Command;
import org.bukkit.command.CommandExecutor; import org.bukkit.command.CommandExecutor;
@ -83,7 +84,7 @@ public class CommandEncrypt implements CommandExecutor {
* @return <p>True if the book was encrypted successfully</p> * @return <p>True if the book was encrypted successfully</p>
*/ */
boolean encryptBook(EncryptionStyle encryptionStyle, Player player, String key, String group) { 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) { if (encryptedBook != null) {
InventoryHelper.setHeldWrittenBook(player, encryptedBook); InventoryHelper.setHeldWrittenBook(player, encryptedBook);

View File

@ -1,9 +1,10 @@
package net.knarcraft.bookswithoutborders; package net.knarcraft.bookswithoutborders.listener;
import java.io.File; import java.io.File;
import java.util.List; import java.util.List;
import java.util.Objects; import java.util.Objects;
import net.knarcraft.bookswithoutborders.BooksWithoutBorders;
import net.knarcraft.bookswithoutborders.state.EncryptionStyle; import net.knarcraft.bookswithoutborders.state.EncryptionStyle;
import net.knarcraft.bookswithoutborders.utility.EncryptionHelper; import net.knarcraft.bookswithoutborders.utility.EncryptionHelper;
import net.knarcraft.bookswithoutborders.utility.FileHelper; import net.knarcraft.bookswithoutborders.utility.FileHelper;
@ -390,7 +391,7 @@ public class BooksWithoutBordersListener implements Listener {
boolean mainHand = hand == EquipmentSlot.HAND; boolean mainHand = hand == EquipmentSlot.HAND;
if (heldItemType == Material.WRITTEN_BOOK) { if (heldItemType == Material.WRITTEN_BOOK) {
player.closeInventory(); 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]))); EncryptionStyle.getFromString(ChatColor.stripColor(lines[3])));
if (eBook != null) { if (eBook != null) {
player.getInventory().setItem(hand, eBook); player.getInventory().setItem(hand, eBook);
@ -447,7 +448,7 @@ public class BooksWithoutBordersListener implements Listener {
String lineText = ChatColor.stripColor(sign.getLine(2)); String lineText = ChatColor.stripColor(sign.getLine(2));
String key = EncryptionHelper.getNumberKeyFromStringKey(lineText); String key = EncryptionHelper.getNumberKeyFromStringKey(lineText);
ItemStack book = BooksWithoutBorders.bwb.loadEncryptedBook(player, key, false); ItemStack book = EncryptionHelper.loadEncryptedBook(player, key, false);
if (book != null) { if (book != null) {
player.getInventory().setItem(hand, book); player.getInventory().setItem(hand, book);
player.sendMessage(ChatColor.GREEN + "Book decrypted!"); player.sendMessage(ChatColor.GREEN + "Book decrypted!");

View File

@ -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 <p>The path of the folder to save to. Must end with a slash</p>
* @param fileName <p>The name of the file to load to</p>
* @param bookMetadata <p>Metadata about the book to save</p>
* @throws IOException <p>If unable to save the book</p>
*/
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 <p>The path of the file to load</p>
* @param bookMetadata <p>Metadata which will be altered with the book's contents</p>
* @return <p>Metadata for the loaded book</p>
*/
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 <p>The folder path to save to. Must end with a slash</p>
* @param fileName <p>The name of the file to save to</p>
* @param bookMetadata <p>Metadata about the book to save</p>
* @throws IOException <p>If unable to save the book</p>
*/
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<String> pages = bookMetadata.getPages();
printWriter.println("[Book]");
for (String page : pages) {
printWriter.println(page);
}
printWriter.close();
}
/**
* Loads a book from a text file
* @param fileName <p>The name of the file to load. Used to create author and title</p>
* @param file <p>The file to load</p>
* @param bookMetadata <p>Metadata which will be altered with the book's contents</p>
* @return <p>Metadata for the loaded book</p>
*/
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<String> 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<String> pages = new ArrayList<>(InputCleaningHelper.cleanList(rawPages));
bookMetadata.setAuthor(author);
bookMetadata.setTitle(title);
bookMetadata.setPages(pages);
return bookMetadata;
}
}

View File

@ -4,12 +4,20 @@ import net.knarcraft.bookswithoutborders.BooksWithoutBorders;
import net.knarcraft.bookswithoutborders.state.EncryptionStyle; import net.knarcraft.bookswithoutborders.state.EncryptionStyle;
import net.knarcraft.bookswithoutborders.GenenCrypt; import net.knarcraft.bookswithoutborders.GenenCrypt;
import net.knarcraft.bookswithoutborders.SubstitutionCipher; import net.knarcraft.bookswithoutborders.SubstitutionCipher;
import org.bukkit.ChatColor;
import org.bukkit.Material;
import org.bukkit.entity.Player; import org.bukkit.entity.Player;
import org.bukkit.inventory.ItemStack;
import org.bukkit.inventory.meta.BookMeta; import org.bukkit.inventory.meta.BookMeta;
import java.io.File;
import java.io.IOException;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.List; import java.util.List;
import static net.knarcraft.bookswithoutborders.utility.InputCleaningHelper.cleanString;
import static net.knarcraft.bookswithoutborders.utility.InputCleaningHelper.fixName;
public class EncryptionHelper { public class EncryptionHelper {
/** /**
@ -56,4 +64,255 @@ public class EncryptionHelper {
} }
} }
/**
* Encrypts a book
*
* @param player <p>The player encrypting the book</p>
* @param mainHand <p>Whether the player is holding the book in its main hand</p>
* @param key <p>The key/password to use for encryption</p>
* @param style <p>The encryption style to use</p>
* @return <p>An encrypted version of the book</p>
*/
public static ItemStack encryptBook(Player player, boolean mainHand, String key, EncryptionStyle style) {
return encryptBook(player, mainHand, key, style, "");
}
/**
* Encrypts a book
*
* @param player <p>The player encrypting the book</p>
* @param mainHand <p>Whether the player is holding the book in its main hand</p>
* @param key <p>The key/password to use for encryption</p>
* @param style <p>The encryption style to use</p>
* @param groupName <p>The name of the group to encrypt for, or "" otherwise</p>
* @return <p>An encrypted version of the book</p>
*/
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<String> 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<String> 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 <p>The book to encrypt</p>
* @param newPages <p>The new encrypted pages</p>
* @param player <p>The player encrypting the book</p>
* @param newMetadata <p>The new metadata of the book</p>
* @return <p>An encrypted version of the book</p>
*/
private static ItemStack createEncryptedBook(BookMeta book, List<String> 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 <p>The group who's allowed to decrypt the book, or ""</p>
* @param player <p>The player trying to encrypt the book</p>
* @param book <p>The book to encrypt</p>
* @param integerKey <p>The key used to encrypt the book</p>
* @return <p>The new metadata for the book, or null if it could not be saved</p>
*/
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 <p>The player trying to load the book</p>
* @param key <p>The encryption key/password for decryption</p>
* @param deleteEncryptedFile <p>Whether to delete the plaintext file after decryption is finished</p>
* @return <p>The loaded book, or null if no book could be loaded</p>
*/
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 <p>The player trying to encrypt the book</p>
* @param bookMetadata <p>Metadata for the book to encrypt</p>
* @param groupName <p>The group which should be able to decrypt the book</p>
* @return <p>The new encrypted metadata for the book, or null if encryption failed</p>
*/
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<String> newLore = new ArrayList<>();
newLore.add(ChatColor.GRAY + "[" + groupName + " encrypted]");
if (bookMetadata.hasLore()) {
List<String> 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 <p>The player encrypting the book</p>
* @param bookMetaData <p>Metadata for the book to encrypt</p>
* @param key <p>The key to use for encryption</p>
* @return <p>The new encrypted metadata for the book, or null if encryption failed</p>
*/
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;
}
} }