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