]> vaikene.ee Git - evaf/blob - src/apps/PswGen/CLI/cli.cpp
Warning fixes and copyright update.
[evaf] / src / apps / PswGen / CLI / cli.cpp
1 /**
2 * @file PswGen/CLI/cli.cpp
3 * @brief Command line interface for the PswGen application
4 * @author Enar Vaikene
5 *
6 * Copyright (c) 2011-2019 Enar Vaikene
7 *
8 * This file is part of the eVaf C++ cross-platform application development framework.
9 *
10 * This file can be used under the terms of the GNU General Public License
11 * version 3.0 as published by the Free Software Foundation and appearing in
12 * the file LICENSE included in the packaging of this file. Please review the
13 * the following information to ensure the GNU General Public License version
14 * 3.0 requirements will be met: http://www.gnu.org/copyleft/gpl.html.
15 *
16 * Alternatively, this file may be used in accordance with the Commercial License
17 * Agreement provided with the Software.
18 */
19
20 #include "cli.h"
21
22 #include <Generator/iGenerator>
23 #include <Storage/iStorage>
24
25 #include <Common/Globals>
26 #include <Common/iLogger>
27 #include <Common/iRegistry>
28 #include <Common/iEventQueue>
29 #include <Common/iApp>
30 #include <Common/Event>
31 #include <Common/Util>
32
33 #include <QtCore>
34
35 #if defined(Q_OS_LINUX) || defined(Q_OS_MACOS)
36 # include <termios.h>
37 # include <unistd.h>
38 #endif
39 #ifdef Q_OS_WIN32
40 # include <windows.h>
41 #endif
42
43 VER_EXPORT_VERSION_INFO()
44
45
46 //-------------------------------------------------------------------
47
48 using namespace eVaf;
49 using namespace eVaf::PswGen::CLI;
50
51 int const Module::DefaultPasswordLength = 16;
52
53 Module::Module()
54 : Plugins::iPlugin()
55 , mReady(false)
56 , mGenerator(nullptr)
57 , mStorage(nullptr)
58 , mEvReady(0)
59 {
60 setObjectName(QString("%1-Module").arg(VER_MODULE_NAME_STR));
61 EVAF_INFO("%s created", qPrintable(objectName()));
62 }
63
64 Module::~Module()
65 {
66 EVAF_INFO("%s destroyed", qPrintable(objectName()));
67 }
68
69 bool Module::init(QString const & args)
70 {
71 Q_UNUSED(args)
72
73 // Get the iGenerator interface
74 EVAF_TEST_X((mGenerator = evafQueryInterface<PswGen::iGenerator>("iGenerator")), "No iGenerator interface")
75
76 // Get the optional iStorage interface
77 mStorage = evafQueryInterface<PswGen::iStorage>("iStorage");
78 if (!mStorage)
79 EVAF_WARNING("No iStorage interface");
80
81 // Get the iEventQueue interface and subscribe to the 'ready' event
82 Common::iEventQueue * eventQueue = evafQueryInterface<Common::iEventQueue>("iEventQueue");
83 EVAF_TEST_X(eventQueue, "No iEventQueue interface")
84
85 // Subscribe to the 'ready' event
86 EVAF_TEST_X((mEvReady = eventQueue->subscribeEvent(eventQueue->queryEvent(Common::iApp::EV_READY), this)), "No 'ready' event")
87
88 mReady = true;
89
90 EVAF_INFO("%s initialized", qPrintable(objectName()));
91
92 return true;
93 }
94
95 void Module::done()
96 {
97 mReady = false;
98
99 EVAF_INFO("%s finalized", qPrintable(objectName()));
100 }
101
102 bool Module::event(QEvent * e)
103 {
104 if (e->type() == Common::Event::eVafEvent) {
105 Common::Event * event = static_cast<Common::Event *>(e);
106
107 if (event->id() == mEvReady) {
108
109 // Generate the password
110 generatePassword();
111
112 // Quit the application
113 Common::iApp::instance()->quit();
114 }
115
116 return false;
117 }
118 else
119 return Plugins::iPlugin::event(e);
120 }
121
122 QString Module::readPassword()
123 {
124 bool noEcho = false;
125 #if defined(Q_OS_LINUX) || defined(Q_OS_MACOS)
126 termios oldt;
127 tcgetattr(STDIN_FILENO, &oldt);
128 termios newt = oldt;
129 newt.c_lflag &= ~ECHO;
130 tcsetattr(STDIN_FILENO, TCSANOW, &newt);
131 noEcho = true;
132 #elif defined Q_OS_WIN32
133 HANDLE hStdin = GetStdHandle(STD_INPUT_HANDLE);
134 DWORD mode = 0;
135 GetConsoleMode(hStdin, &mode);
136 SetConsoleMode(hStdin, mode & (~ENABLE_ECHO_INPUT));
137 noEcho = true;
138 #endif
139
140 QTextStream cin(stdin);
141 QString rval = cin.readLine();
142
143 if (noEcho) {
144 QTextStream cout(stdout);
145 cout << endl;
146 }
147
148 #if defined(Q_OS_LINUX) || defined(Q_OS_MACOS)
149 tcsetattr(STDIN_FILENO, TCSANOW, &oldt);
150 #elif defined Q_OS_WIN32
151 SetConsoleMode(hStdin, mode);
152 #endif
153
154 return rval;
155 }
156
157 void Module::generatePassword()
158 {
159 QString masterPassword;
160 QString appName;
161 QString suffix;
162 int passwordLength = 0;
163 uint flags = 0;
164 int alnum = -1;
165
166 // Process command-line arguments
167 QStringList args = QCoreApplication::arguments();
168 for (int i = 0; i < args.size(); ++i) {
169 QStringList arg = args.at(i).simplified().split('=');
170
171 if (QRegExp("-[-]?p(assword)?").exactMatch(arg.at(0)) && arg.size() > 1)
172 masterPassword = arg.at(1);
173 else if (QRegExp("-[-]?n(ame)?").exactMatch(arg.at(0)) && arg.size() > 1)
174 appName = arg.at(1);
175 else if (QRegExp("-[-]?s(uffix)?").exactMatch(arg.at(0)) && arg.size() > 1)
176 suffix = arg.at(1);
177 else if (QRegExp("-[-]?a(lphanumeric)?").exactMatch(arg.at(0))) {
178 if (arg.size() > 1) {
179 if (Common::isTrue(arg.at(1)))
180 alnum = 1;
181 else if (Common::isFalse(arg.at(1)))
182 alnum = 0;
183 }
184 else
185 alnum = 1;
186 }
187 else if (QRegExp("-[-]?l(ength)?").exactMatch(arg.at(0)) && arg.size() > 1) {
188 bool ok;
189 int t = arg.at(1).toInt(&ok);
190 if (!ok) {
191 EVAF_FATAL_ERROR("Invalid argument : %s", qPrintable(args.at(i)));
192 return;
193 }
194 passwordLength = t;
195 }
196 }
197
198 // Set flags
199 if (alnum != -1) {
200 if (alnum == 1)
201 flags |= uint(iGenerator::ALPHANUMERIC);
202 else
203 flags &= ~uint(iGenerator::ALPHANUMERIC);
204 }
205
206 QTextStream cin(stdin);
207 QTextStream cout(stdout);
208
209 // Get missing arguments
210 while (masterPassword.isEmpty()) {
211 cout << tr("Master password : ") << flush;
212 masterPassword = readPassword();
213 }
214
215 while (appName.isEmpty()) {
216 cout << tr("Application name : ") << flush;
217 cin >> appName;
218 }
219
220 // Get more arguments from the storage
221 QExplicitlySharedDataPointer<PswGen::Storage::Data> data;
222 if (mStorage) {
223 data = mStorage->query(appName);
224 if (data) {
225 if (passwordLength == 0)
226 passwordLength = data->length();
227 if (suffix.isEmpty())
228 suffix = data->suffix();
229 if (alnum == -1)
230 flags = data->flags();
231 }
232 }
233
234 // If the length argument is still not initialized, use the default length value
235 if (!passwordLength)
236 passwordLength = DefaultPasswordLength;
237
238 // Generate password
239 QString password = mGenerator->generatePassword(appName + suffix, masterPassword, passwordLength);
240 cout << "Generated password : " << password << endl;
241
242 // Store arguments for this password
243 if (mStorage) {
244 if (!data)
245 data = new Storage::Data(appName, suffix, passwordLength);
246 else {
247 data->setSuffix(suffix);
248 data->setLength(passwordLength);
249 }
250 mStorage->save(appName, data);
251 }
252 }