From 4bb971789143aae84531b689fba516303e6b6eda Mon Sep 17 00:00:00 2001 From: Kevin Froman Date: Sat, 23 May 2020 04:51:17 -0500 Subject: [PATCH] lots of work on cli UI --- cli/{Main.cs => Program.cs} | 0 cli/cli.csproj | 1 + cli/translations/spanish.cs | 27 ++++++++++++ cli/translations/text.cs | 23 ++++++---- cli/ui/interfaces/encrypt.cs | 55 +++++++++++++++++++++++ cli/ui/interfaces/getmessage.cs | 28 ++++++++++++ cli/ui/menus/EncryptMenu.cs | 61 ++++++++++++++++++++++++++ cli/{Menu.cs => ui/menus/MainMenu.cs} | 7 ++- tests/simplepackTest.cs | 49 +++++++++++++++++++++ treasurechest/simplepack/exceptions.cs | 23 ++++++++++ treasurechest/simplepack/pack.cs | 37 ++++++++++++++++ treasurechest/treasurechest.csproj | 1 + 12 files changed, 301 insertions(+), 11 deletions(-) rename cli/{Main.cs => Program.cs} (100%) create mode 100644 cli/translations/spanish.cs create mode 100644 cli/ui/interfaces/encrypt.cs create mode 100644 cli/ui/interfaces/getmessage.cs create mode 100644 cli/ui/menus/EncryptMenu.cs rename cli/{Menu.cs => ui/menus/MainMenu.cs} (90%) create mode 100644 tests/simplepackTest.cs create mode 100644 treasurechest/simplepack/exceptions.cs create mode 100644 treasurechest/simplepack/pack.cs diff --git a/cli/Main.cs b/cli/Program.cs similarity index 100% rename from cli/Main.cs rename to cli/Program.cs diff --git a/cli/cli.csproj b/cli/cli.csproj index bcdfb9e..aa96f51 100644 --- a/cli/cli.csproj +++ b/cli/cli.csproj @@ -7,6 +7,7 @@ + diff --git a/cli/translations/spanish.cs b/cli/translations/spanish.cs new file mode 100644 index 0000000..9b49155 --- /dev/null +++ b/cli/translations/spanish.cs @@ -0,0 +1,27 @@ +using treasurechest; + +namespace treasurechestCLI { + namespace translations { + + internal class Spanish { + + internal static void load(Strings stringInst){ + stringInst.WELCOME = treasurechest.Version.NAME + " - Protege tu valiosa información"; + stringInst.HELP_TEXT = "Ejecuta help para más opciones"; + stringInst.EXIT = "Salir de la aplicación"; + stringInst.MAIN_MENU_ENCRYPT = "Encriptar"; + stringInst.MAIN_MENU_DECRYPT = "Desencriptar"; + stringInst.INVALID_OPTION = "Opción inválida"; + stringInst.MAIN_MENU_SELECT_INTEGER = "Ingrese un número entero desde el menú"; + stringInst.RETURN_TO_PREVIOUS_MENU = "Menú anterior"; + stringInst.ENCRYPT_MENU_ENCRYPT_MESSAGE = "Cifrar texto"; + stringInst.ENCRYPT_MENU_ENCRYPT_FILE = "Cifrar archivo"; + stringInst.ENCRYPT_MENU_USE_PASSPHRASE = "Usar frase de contraseña"; + stringInst.ENCRYPT_MENU_USE_PUBKEY = "Usar clave pública"; + stringInst.ENTER_MESSAGE_UNTIL_DONE = "Ingrese su mensaje y termine con -q en una nueva línea."; + } + + } + + } +} \ No newline at end of file diff --git a/cli/translations/text.cs b/cli/translations/text.cs index a877fb0..821f42d 100644 --- a/cli/translations/text.cs +++ b/cli/translations/text.cs @@ -15,30 +15,35 @@ namespace treasurechestCLI { public string MAIN_MENU_DECRYPT; public string INVALID_OPTION; public string MAIN_MENU_SELECT_INTEGER; + public string RETURN_TO_PREVIOUS_MENU; + public string ENCRYPT_MENU_ENCRYPT_MESSAGE; + public string ENCRYPT_MENU_ENCRYPT_FILE; + public string ENCRYPT_MENU_USE_PASSPHRASE; + public string ENCRYPT_MENU_USE_PUBKEY; + public string ENTER_MESSAGE_UNTIL_DONE; public Strings(){ switch (GetLanguage.language){ case "es": - WELCOME = treasurechest.Version.NAME + " - Protege tu valiosa información"; - HELP_TEXT = "Ejecuta help para más opciones"; - EXIT = "Salida"; - MAIN_MENU_ENCRYPT = "Encriptar"; - MAIN_MENU_DECRYPT = "Desencriptar"; - INVALID_OPTION = "Opción inválida"; - MAIN_MENU_SELECT_INTEGER = "Ingrese un número entero desde el menú"; - + Spanish.load(this); break; case "en": default: WELCOME = treasurechest.Version.NAME + " - Protect your treasured information"; HELP_TEXT = "Run with help for more options"; - EXIT = "Exit"; + EXIT = "Exit application"; MAIN_MENU_ENCRYPT = "Encrypt"; MAIN_MENU_DECRYPT = "Decrypt"; INVALID_OPTION = "Invalid option"; MAIN_MENU_SELECT_INTEGER = "Enter an integer from the menu"; + RETURN_TO_PREVIOUS_MENU = "Previous menu"; + ENCRYPT_MENU_ENCRYPT_MESSAGE = "Encrypt text"; + ENCRYPT_MENU_ENCRYPT_FILE = "Encrypt file"; + ENCRYPT_MENU_USE_PASSPHRASE = "Use passphrase"; + ENCRYPT_MENU_USE_PUBKEY = "Use public key"; + ENTER_MESSAGE_UNTIL_DONE = "Enter your message and finish with -q on a new line."; break; } diff --git a/cli/ui/interfaces/encrypt.cs b/cli/ui/interfaces/encrypt.cs new file mode 100644 index 0000000..b4a0a26 --- /dev/null +++ b/cli/ui/interfaces/encrypt.cs @@ -0,0 +1,55 @@ +using System; +using treasurechest.STDIOWrapper; + +namespace treasurechestCLI{ + + internal class EncryptMessageInterface{ + public static void EncryptMessage(){ + int choice = 0; + int counter = 1; + translations.Strings strings = new translations.Strings(); + + string[] encryptMenuOptions = + { + strings.ENCRYPT_MENU_USE_PASSPHRASE, + strings.ENCRYPT_MENU_USE_PUBKEY, + strings.RETURN_TO_PREVIOUS_MENU + }; + while(true){ + foreach(string option in encryptMenuOptions){ + STDIO.O(counter.ToString() + ". " + option); + counter += 1; + } + try{ + choice = Int32.Parse(System.Console.ReadLine()); + } + catch (System.OverflowException){ + // User being silly with input + STDIO.O(strings.MAIN_MENU_SELECT_INTEGER); + counter = 1; + } + catch(System.FormatException){ + // Too lazy to check strings, force them to use int from menu which is faster anyway + STDIO.O(strings.MAIN_MENU_SELECT_INTEGER); + counter = 1; + } + catch(System.ArgumentNullException){ + // Can happen when stream closes (e.g. ctrl-d) + // since menu is intended to be directly human interfaced, user probably wants to exit + choice = encryptMenuOptions.Length; + } + if (choice == 1){ + GetMessage.getTypedMessage(); + } + else if (choice == encryptMenuOptions.Length){ + break; + } + counter = 1; + + } + + } + + } + +} \ No newline at end of file diff --git a/cli/ui/interfaces/getmessage.cs b/cli/ui/interfaces/getmessage.cs new file mode 100644 index 0000000..3d818eb --- /dev/null +++ b/cli/ui/interfaces/getmessage.cs @@ -0,0 +1,28 @@ +using treasurechest.STDIOWrapper; +using System; + +namespace treasurechestCLI{ + + + internal class GetMessage{ + + internal static string getTypedMessage(){ + + translations.Strings strings = new translations.Strings(); + string message = ""; + string line = ""; + STDIO.O(strings.ENTER_MESSAGE_UNTIL_DONE); + while (true){ + line = Console.ReadLine(); + if (line.Equals("-q")){ + break; + } + message += line; + } + return message; + } + + } + + +} \ No newline at end of file diff --git a/cli/ui/menus/EncryptMenu.cs b/cli/ui/menus/EncryptMenu.cs new file mode 100644 index 0000000..cd54496 --- /dev/null +++ b/cli/ui/menus/EncryptMenu.cs @@ -0,0 +1,61 @@ +using System; +using treasurechest.STDIOWrapper; +using treasurechest; + +namespace treasurechestCLI +{ + + internal class EncryptMenu{ + + public static void enterMenu(translations.Strings strings) { + int choice = 0; + int counter = 1; + string[] encryptMenuOptions = + { + strings.ENCRYPT_MENU_ENCRYPT_MESSAGE, + strings.ENCRYPT_MENU_ENCRYPT_FILE, + strings.RETURN_TO_PREVIOUS_MENU, + strings.EXIT + }; + + while (true){ + foreach (string option in encryptMenuOptions){ + STDIO.O(counter.ToString() + ". " + option); + counter += 1; + } + try{ + choice = Int32.Parse(System.Console.ReadLine()); + } + catch (System.OverflowException){ + // User being silly with input + STDIO.O(strings.MAIN_MENU_SELECT_INTEGER); + counter = 1; + } + catch(System.FormatException){ + // Too lazy to check strings, force them to use int from menu which is faster anyway + STDIO.O(strings.MAIN_MENU_SELECT_INTEGER); + counter = 1; + } + catch(System.ArgumentNullException){ + // Can happen when stream closes (e.g. ctrl-d) + // since menu is intended to be directly human interfaced, user probably wants to exit + choice = encryptMenuOptions.Length; + } + if (choice == 1){ + EncryptMessageInterface.EncryptMessage(); + } + else if (choice == encryptMenuOptions.Length - 1){ + return; + } + else if (choice == encryptMenuOptions.Length){ + System.Environment.Exit(0); + } + counter = 1; + } + + } + + } + + +} \ No newline at end of file diff --git a/cli/Menu.cs b/cli/ui/menus/MainMenu.cs similarity index 90% rename from cli/Menu.cs rename to cli/ui/menus/MainMenu.cs index a5fb48e..dc6ef92 100644 --- a/cli/Menu.cs +++ b/cli/ui/menus/MainMenu.cs @@ -1,5 +1,4 @@ using System; -using CommandLine; using treasurechest.STDIOWrapper; using treasurechest; @@ -45,7 +44,11 @@ namespace treasurechestCLI // since menu is intended to be directly human interfaced, user probably wants to exit choice = mainMenuOptionsSize; } - if (choice == mainMenuOptionsSize){ + if (choice == 1){ + EncryptMenu.enterMenu(strings); + } + else if (choice == mainMenuOptionsSize){ + // Exit is final option break; } else{ diff --git a/tests/simplepackTest.cs b/tests/simplepackTest.cs new file mode 100644 index 0000000..3b6c9bf --- /dev/null +++ b/tests/simplepackTest.cs @@ -0,0 +1,49 @@ +using NUnit.Framework; +using chestcrypto; +using System; + +namespace simplepackTests +{ + public class Tests + { + [SetUp] + public void Setup() + { + } + + [Test] + public void TestPackUnpackString() + { + string message = "hello world"; + string packed; + packed = chestcrypto.simplepack.SimplePack.pack(message); + Assert.AreEqual(message, chestcrypto.simplepack.SimplePack.unpack(packed)); + } + [Test] + public void TestPackUnpackBytes() + { + byte[] message = System.Text.Encoding.UTF8.GetBytes("hello world"); + string packed; + packed = chestcrypto.simplepack.SimplePack.pack(message); + Assert.AreEqual(message, chestcrypto.simplepack.SimplePack.unpack(packed)); + } + [Test] + public void TestPackUnpackInvalid(){ + byte[] message = System.Text.Encoding.UTF8.GetBytes("hello world"); + string packed; + packed = chestcrypto.simplepack.SimplePack.pack(message).Remove(1); + bool success = false; + try{ + chestcrypto.simplepack.SimplePack.unpack(packed); + } + catch(chestcrypto.exceptions.InvalidSimplePackMessage){ + success = true; + } + if (! success){ + Assert.Fail(); + } + } + + + } +} \ No newline at end of file diff --git a/treasurechest/simplepack/exceptions.cs b/treasurechest/simplepack/exceptions.cs new file mode 100644 index 0000000..ffec12c --- /dev/null +++ b/treasurechest/simplepack/exceptions.cs @@ -0,0 +1,23 @@ +using System; +namespace chestcrypto{ + + namespace exceptions{ + public class InvalidSimplePackMessage : Exception + { + public InvalidSimplePackMessage() + { + } + + public InvalidSimplePackMessage(string message) + : base(message) + { + } + + public InvalidSimplePackMessage(string message, Exception inner) + : base(message, inner) + { + } + } + } + +} \ No newline at end of file diff --git a/treasurechest/simplepack/pack.cs b/treasurechest/simplepack/pack.cs new file mode 100644 index 0000000..a6b3768 --- /dev/null +++ b/treasurechest/simplepack/pack.cs @@ -0,0 +1,37 @@ +using Base58Check; +using System; + +namespace chestcrypto{ + + namespace simplepack{ + + public class SimplePack{ + + private const string header = "CHEST-MESSAGE"; + private const string footer = "END-CHEST-MESSAGE."; + + public static string pack(byte[] data){ + return header + Base58CheckEncoding.Encode(data) + footer; + } + + public static string pack(string data){ + return pack(System.Text.Encoding.UTF8.GetBytes(data)); + } + + public static byte[] unpack(string checkedBase58String){ + if (! checkedBase58String.Contains(header) | ! checkedBase58String.Contains(footer)){ + throw new exceptions.InvalidSimplePackMessage("Message does not have valid header and footer"); + } + string encodedMessage = ""; + for (int i = header.Length; i < checkedBase58String.Length - footer.Length; i++){ + encodedMessage += checkedBase58String[i]; + } + return Base58CheckEncoding.Decode(encodedMessage); + + } + + } + + } + +} diff --git a/treasurechest/treasurechest.csproj b/treasurechest/treasurechest.csproj index b43ae8a..e9003db 100644 --- a/treasurechest/treasurechest.csproj +++ b/treasurechest/treasurechest.csproj @@ -5,6 +5,7 @@ +