From 2558e6db79f1bf5320f20ea25eac8a73783009cc Mon Sep 17 00:00:00 2001 From: Florian Geyer Date: Fri, 29 Mar 2013 20:35:54 +0100 Subject: [PATCH] First draft of an argument parser. Possibility to set custom config path. --- src/CMakeLists.txt | 1 + src/core/ArgumentParser.cpp | 51 +++++++++++++++++++++++++ src/core/ArgumentParser.h | 34 +++++++++++++++++ src/core/Config.cpp | 6 +++ src/core/Config.h | 1 + src/main.cpp | 25 +++++-------- tests/CMakeLists.txt | 3 ++ tests/TestArgumentParser.cpp | 72 ++++++++++++++++++++++++++++++++++++ tests/TestArgumentParser.h | 42 +++++++++++++++++++++ 9 files changed, 219 insertions(+), 16 deletions(-) create mode 100644 src/core/ArgumentParser.cpp create mode 100644 src/core/ArgumentParser.h create mode 100644 tests/TestArgumentParser.cpp create mode 100644 tests/TestArgumentParser.h diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt index 2d7e364fe..3bb4da99d 100644 --- a/src/CMakeLists.txt +++ b/src/CMakeLists.txt @@ -27,6 +27,7 @@ set(keepassx_SOURCES autotype/WildcardMatcher.cpp autotype/WindowSelectComboBox.cpp autotype/test/AutoTypeTestInterface.h + core/ArgumentParser.cpp core/AutoTypeAssociations.cpp core/Config.cpp core/Database.cpp diff --git a/src/core/ArgumentParser.cpp b/src/core/ArgumentParser.cpp new file mode 100644 index 000000000..d76df7562 --- /dev/null +++ b/src/core/ArgumentParser.cpp @@ -0,0 +1,51 @@ +/* + * Copyright (C) 2013 Florian Geyer + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 2 or (at your option) + * version 3 of the License. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + +#include "ArgumentParser.h" + +QHash ArgumentParser::parseArguments(const QStringList& args) +{ + QStringList argumentKeys = QStringList() << "password" << "config" << "filename"; + + QHash argumentMap; + + // TODO: needs refactoring, too much nesting + for (int i = 1; i < args.size(); i++) { + if (args[i].startsWith("--")) { + if (args.size() > (i + 1)) { + QString argument(args[i].mid(2)); + if (argumentKeys.contains(argument)) { + argumentMap.insert(argument, args[i + 1]); + } + else { + qWarning("Unknown option \"%s\" with value \"%s\"", qPrintable(args[i]), qPrintable(args[i+1])); + } + i++; + } else { + qWarning("No value given for option \"%s\"", qPrintable(args[i])); + } + } + else if (!args[i].startsWith("-")) { + argumentMap.insert("filename", args[i]); + } + else { + qWarning("Unknown argument \"%s\"", qPrintable(args[i])); + } + } + + return argumentMap; +} diff --git a/src/core/ArgumentParser.h b/src/core/ArgumentParser.h new file mode 100644 index 000000000..c594d51a6 --- /dev/null +++ b/src/core/ArgumentParser.h @@ -0,0 +1,34 @@ +/* + * Copyright (C) 2013 Florian Geyer + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 2 or (at your option) + * version 3 of the License. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + +#ifndef KEEPASSX_ARGUMENT_PARSER_H +#define KEEPASSX_ARGUMENT_PARSER_H + +#include "core/Global.h" + +#include +#include + +class ArgumentParser +{ + +public: + static QHash parseArguments(const QStringList& args); + +}; + +#endif // KEEPASSX_ARGUMENT_PARSER_H diff --git a/src/core/Config.cpp b/src/core/Config.cpp index fba625299..047f4d670 100644 --- a/src/core/Config.cpp +++ b/src/core/Config.cpp @@ -105,6 +105,12 @@ Config* Config::instance() return m_instance; } +void Config::createConfigFromFile(QString file) +{ + Q_ASSERT(!m_instance); + m_instance = new Config(file, qApp); +} + void Config::createTempFileInstance() { Q_ASSERT(!m_instance); diff --git a/src/core/Config.h b/src/core/Config.h index eab86699e..0a775bdfc 100644 --- a/src/core/Config.h +++ b/src/core/Config.h @@ -36,6 +36,7 @@ public: void set(const QString& key, const QVariant& value); static Config* instance(); + static void createConfigFromFile(QString file); static void createTempFileInstance(); private: diff --git a/src/main.cpp b/src/main.cpp index 2ab8f211f..a113a8a82 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -17,6 +17,8 @@ #include +#include "core/ArgumentParser.h" +#include "core/Config.h" #include "core/Tools.h" #include "crypto/Crypto.h" #include "gui/Application.h" @@ -34,21 +36,11 @@ int main(int argc, char** argv) Crypto::init(); - QString filename; - QString password; - const QStringList args = app.arguments(); - for (int i = 1; i < args.size(); i++) { - if (args[i] == "--password" && args.size() > (i + 1)) { - password = args[i + 1]; - i++; - } - else if (!args[i].startsWith("-") && QFile::exists(args[i])) { - filename = args[i]; - } - else { - qWarning("Unknown argument \"%s\"", qPrintable(args[i])); - } + QHash argumentMap = ArgumentParser::parseArguments(args); + + if (!argumentMap.value("config").isEmpty()) { + Config::createConfigFromFile(argumentMap.value("config")); } MainWindow mainWindow; @@ -56,8 +48,9 @@ int main(int argc, char** argv) QObject::connect(&app, SIGNAL(openFile(QString)), &mainWindow, SLOT(openDatabase(QString))); - if (!filename.isEmpty()) { - mainWindow.openDatabase(filename, password, QString()); + QString filename(argumentMap.value("filename")); + if (!filename.isEmpty() && QFile::exists(filename)) { + mainWindow.openDatabase(filename, argumentMap.value("password"), QString()); } return app.exec(); diff --git a/tests/CMakeLists.txt b/tests/CMakeLists.txt index 02fa1029e..38c931eb7 100644 --- a/tests/CMakeLists.txt +++ b/tests/CMakeLists.txt @@ -159,6 +159,9 @@ set_target_properties(testautotype PROPERTIES ENABLE_EXPORTS ON) add_unit_test(NAME testentry SOURCES TestEntry.cpp MOCS TestEntry.h LIBS ${TEST_LIBRARIES}) +add_unit_test(NAME testargumentparser SOURCES TestArgumentParser.cpp MOCS TestArgumentParser.h + LIBS ${TEST_LIBRARIES}) + if(WITH_GUI_TESTS) add_subdirectory(gui) endif(WITH_GUI_TESTS) diff --git a/tests/TestArgumentParser.cpp b/tests/TestArgumentParser.cpp new file mode 100644 index 000000000..95bfb3420 --- /dev/null +++ b/tests/TestArgumentParser.cpp @@ -0,0 +1,72 @@ +/* + * Copyright (C) 2013 Felix Geyer + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 2 or (at your option) + * version 3 of the License. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + +#include "TestArgumentParser.h" + +#include + +#include "tests.h" +#include "core/ArgumentParser.h" + +// TODO: test qWarning with own message handler? + +void TestArgumentParser::testNoArguments() +{ + parse(QStringList()); + + QVERIFY(argumentMap.isEmpty()); +} + +void TestArgumentParser::testUnknownArgument() +{ + parse(QStringList() << "--foo" << "bar"); + + QVERIFY(argumentMap.isEmpty()); +} + +void TestArgumentParser::testFilename() +{ + parse(QStringList() << "--filename" << "foo"); + + QCOMPARE(argumentMap.size(), 1); + QCOMPARE(argumentMap.value("filename"), QString("foo")); +} + +void TestArgumentParser::testMultipleArguments() +{ + parse(QStringList() << "--config" << "myconfig.ini" << "--filename" << "myfilename" << "--password" << "mypassword"); + + QCOMPARE(argumentMap.size(), 3); + QCOMPARE(argumentMap.value("config"), QString("myconfig.ini")); + QCOMPARE(argumentMap.value("filename"), QString("myfilename")); + QCOMPARE(argumentMap.value("password"), QString("mypassword")); +} + +void TestArgumentParser::testFilenameWithoutOption() +{ + parse(QStringList() << "foo"); + + QCOMPARE(argumentMap.size(), 1); + QCOMPARE(argumentMap.value("filename"), QString("foo")); +} + +void TestArgumentParser::parse(const QStringList& arguments) +{ + argumentMap = ArgumentParser::parseArguments(QStringList() << "keepassx" << arguments); +} + +QTEST_GUILESS_MAIN(TestArgumentParser) diff --git a/tests/TestArgumentParser.h b/tests/TestArgumentParser.h new file mode 100644 index 000000000..7b4940e54 --- /dev/null +++ b/tests/TestArgumentParser.h @@ -0,0 +1,42 @@ +/* + * Copyright (C) 2013 Felix Geyer + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 2 or (at your option) + * version 3 of the License. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + +#ifndef KEEPASSX_TEST_ARGUMENT_PARSER_H +#define KEEPASSX_TEST_ARGUMENT_PARSER_H + +#include +#include + +class TestArgumentParser : public QObject +{ + Q_OBJECT + +private Q_SLOTS: + void testNoArguments(); + void testUnknownArgument(); + void testFilename(); + void testMultipleArguments(); + void testFilenameWithoutOption(); + +private: + void parse(const QStringList& arguments); + + QHash argumentMap; + +}; + +#endif // KEEPASSX_TEST_ARGUMENT_PARSER_H