//Ciphers/helperFunctions.hpp //Matthew Ellison // Created: 4-29-18 //Modified: 5-8-18 //This file contains the driver function and the test functions for the Cipher program //This program will use some simple ciphers that are no longer widely used but still fun to play with #ifndef HELPER_FUNCTIONS_HPP #define HELPER_FUNCTIONS_HPP #include "Headers/Caesar.hpp" #include "Headers/Playfair.hpp" #include "Headers/Vigenere.hpp" #include "Headers/Atbash.hpp" #include "Headers/Morse.hpp" #include "Headers/Autokey.hpp" #include #include #include enum CipherFlagLocation { CAESAR, PLAYFAIR, VIGENERE, ATBASH, MORSE, AUTOKEY, NUM_CIPHERS, ENCODE, DECODE, INPUT_FILE, OUTPUT_FILE, SIZE }; std::string flagStrings[SIZE]; //Error handling bool failFlag = false; //Set if something fails //For the getCipher function typedef std::string (*Fn)(std::ifstream&, bool); /** * @brief Takes all of the arguments that were given to the program and sets boolean flags inside the program that will change behavior * * @param argc The number of arguments given * @param argv The arguments given * @param cipherFlags The array of booleans that represent the possible options passed in * @param inputFileString The name of the input file, if given * @param outputFileString The name of the output file if given */ void getFlags(int argc, char** argv, bool cipherFlags[], std::string& inputFileString, std::string& outputFileString){ //Cycle through every argument bool valid = false; for(int cnt = 1;cnt < argc;++cnt){ //Step through every element in the flagStrings and compare the flags. If the flags do not match or you go out of bounds in argv throw an error for(int stringcnt = 0;stringcnt < SIZE;++stringcnt){ if(argv[cnt] == flagStrings[stringcnt]){ valid = cipherFlags[stringcnt] = true; //If the flag showed an input file get the file name if possible if(stringcnt == INPUT_FILE){ //Make sure there is enough room in argv for the file name if((cnt + 1) < argc){ inputFileString = argv[++cnt]; } } //If the flag showed an output file get the file name if possible else if(stringcnt == OUTPUT_FILE){ //Make sure there is enough room in argv for the file name if((cnt + 1) < argc){ outputFileString = argv[++cnt]; } } break; } } //If the flag was not valid throw an error if(!valid){ std::cout << argv[cnt] << " is an invalid flag" << std::endl; return; } valid = false; } } /** * @brief Checks that the flags given are valid * * @param flags All of the flags that the program can have * @return true If valid options were chosen * @return false If invalid options were chosen */ bool checkFlags(bool flags[]){ int counter = 0; bool correct = false; //Run through each flag and counter how many are true for(int cnt = 0;cnt < NUM_CIPHERS;++cnt){ if(flags[cnt]){ ++counter; } } //Check if a valid number of flags were true if(counter == 1){ correct = true; } //Check if either encode or decode is set, but not both if((flags[ENCODE] && flags[DECODE]) || (!flags[ENCODE] && !flags[DECODE])){ correct = false; } return correct; } /** * @brief Set the array of strings that controls what each flag should look * */ void setFlagStrings(){ flagStrings[CAESAR] = "-c"; flagStrings[PLAYFAIR] = "-p"; flagStrings[VIGENERE] = "-v"; flagStrings[ATBASH] = "-a"; flagStrings[MORSE] = "-m"; flagStrings[AUTOKEY] = "-u"; flagStrings[ENCODE] = "-e"; flagStrings[DECODE] = "-d"; flagStrings[INPUT_FILE] = "-i"; flagStrings[OUTPUT_FILE] = "-o"; } /** * @brief Run the appropriate commands to use a Caesar cipher * * @param infile The input file if one was provided * @param encode Whether the encoding flag was set. True if encoding, false if decoding * @return The new message */ std::string runCaesar(std::ifstream& infile, bool encode){ std::string inputString, cipherString; int offset; Caesar cipher; //Check if the input file is open if(infile.is_open()){ infile >> offset; infile.ignore(10000, '\n'); //Get rid of the \n that is right after the offset std::getline(infile, inputString); if(infile.fail()){ failFlag = true; cipherString = "Input file has an incorrect format\n"; } } //Otherwise prompt for the appropriate strings else{ std::cout << "Enter the cipher offset: "; std::cin >> offset; if(std::cin.fail()){ std::cin.ignore(10000, '\n'); std::cin.clear(); std::cout << "That is an invalid offset\nEnter the cipher offset: "; std::cin >> offset; } std::cout << "Enter the input string: "; std::cin.ignore(10000, '\n'); std::getline(std::cin, inputString); } //Check if there was an error reading the file if(failFlag){ return cipherString; } //Run the correct cipher if(encode){ cipherString = cipher.encode(offset, inputString); } else{ cipherString = cipher.decode(offset, inputString); } return cipherString; } /** * @brief Run the appropriate commands to use a Playfair cipher * * @param infile The input file if one was provided * @param encode Whether the encoding flag was set. True if encoding, false if decoding * @return The new message */ std::string runPlayfair(std::ifstream& infile, bool encode){ std::string keyword, inputString, cipherString; Playfair cipher; //Check if the input file is open if(infile.is_open()){ std::getline(infile, keyword); std::getline(infile, inputString); if(infile.fail()){ failFlag = true; cipherString = "Input file has an incorrect format\n"; } } //Otherwise prompt for the appropriate strings else{ std::cout << "Enter the keyword: "; std::getline(std::cin, keyword); std::cout << "Enter the input string: "; std::getline(std::cin, inputString); } //Check if there was an error reading the file if(failFlag){ return cipherString; } //Run the correct cipher if(encode){ cipherString = cipher.encode(keyword, inputString); } else{ cipherString = cipher.decode(keyword, inputString); } return cipherString; } /** * @brief Run the appropriate commands to use a Vigenere cipher * * @param infile The input file if one was provided * @param encode Whether the encoding flag was set. True if encoding, false if decoding * @return The new message */ std::string runVigenere(std::ifstream& infile, bool encode){ std::string keyword, inputString, cipherString; Vigenere cipher; //Check if the input file is open if(infile.is_open()){ std::getline(infile, keyword); std::getline(infile, inputString); if(infile.fail()){ failFlag = true; cipherString = "Input file has an incorrect format\n"; } } //Otherwise prompt for the appropriate strings else{ std::cout << "Enter the keyword: "; std::getline(std::cin, keyword); std::cout << "Enter the input string: "; std::getline(std::cin, inputString); } //Check if there was an error reading the file if(failFlag){ return cipherString; } //Run the correct cipher if(encode){ cipherString = cipher.encode(keyword, inputString); } else{ cipherString = cipher.decode(keyword, inputString); } return cipherString; } /** * @brief Run the appropriate commands to use an Atbash cipher * * @param infile The input file if one was provided * @param encode Whether the encoding flag was set. True if encoding, false if decoding * @return The new message */ std::string runAtbash(std::ifstream& infile, bool encode){ std::string inputString, cipherString; Atbash cipher; //Check if the input file is open if(infile.is_open()){ std::getline(infile, inputString); if(infile.fail()){ failFlag = true; cipherString = "Input file has an incorrect format\n"; } } //Otherwise prompt for the appropriate strings else{ std::cout << "Enter the input string: "; std::getline(std::cin, inputString); } //Check if there was an error reading the file if(failFlag){ return cipherString; } //Run the correct cipher if(encode){ cipherString = cipher.encode(inputString); } else{ cipherString = cipher.decode(inputString); } return cipherString; } /** * @brief Run the appropriate commands to use Morse code * * @param infile The input file if one was provided * @param encode Whether the encoding flag was set. True if encoding, false if decoding * @return The new message */ std::string runMorse(std::ifstream& infile, bool encode){ std::string inputString, cipherString; Morse cipher; //Check if the input file is open if(infile.is_open()){ std::getline(infile, inputString); if(infile.fail()){ failFlag = true; cipherString = "Input file has an incorrect format\n"; } } //Otherwise prompt for the appropriate strings else{ std::cout << "Enter the input string: "; std::getline(std::cin, inputString); } //Check if there was an error reading the file if(failFlag){ return cipherString; } //Run the correct cipher if(encode){ cipherString = cipher.encode(inputString); } else{ cipherString = cipher.decode(inputString); } return cipherString; } /** * @brief Run the appropriate commands to use an Autokey cipher * * @param infile The input file if one was provided * @param encode Whether the encoding flag was set. True if encoding, false if decoding * @return The new message */ std::string runAutokey(std::ifstream& infile, bool encode){ std::string keyword, inputString, cipherString; Autokey cipher; //Check if the input file is open if(infile.is_open()){ std::getline(infile, keyword); std::getline(infile, inputString); if(infile.fail()){ failFlag = true; cipherString = "Input file has an incorrect format\n"; } } //Otherwise prompt for the appropriate strings else{ std::cout << "Enter the keyword: "; std::getline(std::cin, keyword); std::cout << "Enter the input string: "; std::getline(std::cin, inputString); } //Check if there was an error reading the file if(failFlag){ return cipherString; } //Run the correct cipher if(encode){ cipherString = cipher.encode(keyword, inputString); } else{ cipherString = cipher.decode(keyword, inputString); } return cipherString; } /** * @brief Uses the flags to determine which cipher needs to be run * * @param cipherFlags The possible flags given to the program * @return The appropriate run___ function based on the flags */ //Returns the correct function for the flags that are set Fn getCipher(const bool cipherFlags[]){ if(cipherFlags[CAESAR]){ return runCaesar; } else if(cipherFlags[PLAYFAIR]){ return runPlayfair; } else if(cipherFlags[VIGENERE]){ return runVigenere; } else if(cipherFlags[ATBASH]){ return runAtbash; } else if(cipherFlags[MORSE]){ return runMorse; } else if(cipherFlags[AUTOKEY]){ return runAutokey; } //If it didn't trip one of the flags, there was an error before this else{ std::cout << "There was an error selecting the appropriate function"; exit(0); } } #endif //HELPER_FUNCTIONS_HPP