forked from zybbigpy/Day-5-Starter-Repo
-
Notifications
You must be signed in to change notification settings - Fork 0
/
mpags-cipher.cpp
143 lines (122 loc) · 4.72 KB
/
mpags-cipher.cpp
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
// Standard Library includes
#include <fstream>
#include <iostream>
#include <string>
#include <vector>
// Our project headers
#include "CipherMode.hpp"
#include "CipherType.hpp"
#include "TransformChar.hpp"
#include "ProcessCommandLine.hpp"
#include "CaesarCipher.hpp"
#include "PlayfairCipher.hpp"
// Main function of the mpags-cipher program
int main(int argc, char* argv[])
{
// Convert the command-line arguments into a more easily usable form
const std::vector<std::string> cmdLineArgs {argv, argv+argc};
// Options that might be set by the command-line arguments
ProgramSettings settings { false, false, "", "", "", CipherMode::Encrypt, CipherType::Caesar };
// Process command line arguments
bool cmdLineStatus { processCommandLine(cmdLineArgs, settings) };
// Any failure in the argument processing means we can't continue
// Use a non-zero return value to indicate failure
if( !cmdLineStatus ) {
return 1;
}
// Handle help, if requested
if (settings.helpRequested) {
// Line splitting for readability
std::cout
<< "Usage: mpags-cipher [-i/--infile <file>] [-o/--outfile <file>] [-c/--cipher <cipher>] [-k/--key <key>] [--encrypt/--decrypt]\n\n"
<< "Encrypts/Decrypts input alphanumeric text using classical ciphers\n\n"
<< "Available options:\n\n"
<< " -h|--help\n"
<< " Print this help message and exit\n\n"
<< " -v|--version\n"
<< " Print version information\n\n"
<< " -i|--infile FILE\n"
<< " Read text to be processed from FILE\n"
<< " Stdin will be used if not supplied\n\n"
<< " -o|--outfile FILE\n"
<< " Write processed text to FILE\n"
<< " Stdout will be used if not supplied\n\n"
<< " -c|--cipher CIPHER\n"
<< " Specify the cipher to be used to perform the encryption/decryption\n"
<< " CIPHER can either be caesar or playfair - caesar is the default\n\n"
<< " -k|--key KEY\n"
<< " Specify the cipher KEY\n"
<< " A null key, i.e. no encryption, is used if not supplied\n\n"
<< " --encrypt\n"
<< " Will use the cipher to encrypt the input text (default behaviour)\n\n"
<< " --decrypt\n"
<< " Will use the cipher to decrypt the input text\n\n";
// Help requires no further action, so return from main,
// with 0 used to indicate success
return 0;
}
// Handle version, if requested
if (settings.versionRequested) {
std::cout << "0.2.0" << std::endl;
// Like help, requires no further action, so return from main,
// with 0 used to indicate success
return 0;
}
// Initialise variables for processing input text
char inputChar {'x'};
std::string inputText {""};
// Read in user input from stdin/file
if (!settings.inputFile.empty()) {
// Open the file and check that we can read from it
std::ifstream inputStream(settings.inputFile);
if (!inputStream.good()) {
std::cerr << "[error] failed to create istream on file '" << settings.inputFile << "'" << std::endl;
return 1;
}
// Loop over each character from the file
while(inputStream >> inputChar)
{
inputText += transformChar(inputChar);
}
} else {
// Loop over each character from user input
// (until Return then CTRL-D (EOF) pressed)
while(std::cin >> inputChar)
{
inputText += transformChar(inputChar);
}
}
std::string outputText {""};
switch ( settings.cipherType ) {
case CipherType::Caesar :
{
// Run the Caesar cipher (using the specified key and encrypt/decrypt flag) on the input text
CaesarCipher cipher { settings.cipherKey };
outputText = cipher.applyCipher( inputText, settings.cipherMode );
break;
}
case CipherType::Playfair :
{
PlayfairCipher cipher { settings.cipherKey };
outputText = cipher.applyCipher( inputText, settings.cipherMode );
break;
}
}
// Output the transliterated text
if (!settings.outputFile.empty()) {
// Open the file and check that we can write to it
std::ofstream outputStream(settings.outputFile);
if (!outputStream.good()) {
std::cerr << "[error] failed to create ostream on file '" << settings.outputFile << "'" << std::endl;
return 1;
}
// Print the transliterated text to the file
outputStream << outputText << std::endl;
} else {
// Print the transliterated text to the screen
std::cout << outputText << std::endl;
}
// No requirement to return from main, but we do so for clarity
// and for consistency with other functions
return 0;
}