diff options
-rw-r--r-- | .travis.yml | 16 | ||||
-rw-r--r-- | CMakeLists.txt | 41 | ||||
-rw-r--r-- | java/constants.h | 8 | ||||
-rw-r--r-- | java/javautils.cpp | 108 | ||||
-rw-r--r-- | java/javautils.h | 25 | ||||
-rw-r--r-- | libmultimc/include/minecraftprocess.h | 2 | ||||
-rw-r--r-- | libmultimc/src/minecraftprocess.cpp | 2 | ||||
-rw-r--r-- | libsettings/include/keyring.h | 85 | ||||
-rw-r--r-- | libsettings/src/keyring.cpp | 63 | ||||
-rw-r--r-- | libsettings/src/stubkeyring.cpp | 96 | ||||
-rw-r--r-- | libsettings/src/stubkeyring.h | 42 | ||||
-rw-r--r-- | libutil/include/cmdutils.h | 17 | ||||
-rw-r--r-- | libutil/src/cmdutils.cpp | 16 | ||||
-rw-r--r-- | test.cpp | 60 |
14 files changed, 493 insertions, 88 deletions
diff --git a/.travis.yml b/.travis.yml new file mode 100644 index 00000000..c94982f2 --- /dev/null +++ b/.travis.yml @@ -0,0 +1,16 @@ +language: cpp +compiler: + - gcc + +before_script: + - sudo apt-add-repository -y ppa:czchen/travis-ci + - sudo add-apt-repository -y ppa:ubuntu-sdk-team/ppa + - sudo add-apt-repository -y ppa:canonical-qt5-edgers/qt5-proper + - sudo apt-get update -yqq + - sudo apt-get install -yqq cmake + - sudo apt-get install -yqq ubuntu-sdk + +script: "cmake . && make -j4" + +notifications: + irc: "irc.esper.net#MultiMC" diff --git a/CMakeLists.txt b/CMakeLists.txt index fad09575..742f47f6 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -47,6 +47,7 @@ find_package(ZLIB REQUIRED) # Add quazip add_subdirectory(quazip) +include_directories(quazip) # Add bspatch add_subdirectory(patchlib) @@ -85,7 +86,7 @@ add_subdirectory(plugins/stdinstance) INCLUDE(TestBigEndian) TEST_BIG_ENDIAN(BIGENDIAN) IF(${BIGENDIAN}) - ADD_DEFINITIONS(-DMULTIMC_BIG_ENDIAN) + ADD_DEFINITIONS(-DMULTIMC_BIG_ENDIAN) ENDIF(${BIGENDIAN}) @@ -126,7 +127,7 @@ IF(DEFINED MultiMC_BUILD_TAG) MESSAGE(STATUS "Build tag: ${MultiMC_BUILD_TAG}") ELSE() MESSAGE(STATUS "No build tag specified.") - SET(MultiMC_BUILD_TAG custom) + SET(MultiMC_BUILD_TAG custom) ENDIF() # Architecture detection @@ -148,13 +149,13 @@ ENDIF() # Jenkins URL SET(MultiMC_JOB_URL "http://ci.forkk.net/job/${MultiMC_JOB_NAME}/arch=${MultiMC_ARCH}${MultiMC_Extra_Label}/" - CACHE STRING "URL of the jenkins job to pull updates from.") + CACHE STRING "URL of the jenkins job to pull updates from.") MESSAGE(STATUS "Job URL: ${MultiMC_JOB_URL}") ######## Configure header ######## configure_file("${PROJECT_SOURCE_DIR}/config.h.in" - "${PROJECT_BINARY_DIR}/include/config.h") -include_directories(${PROJECT_BINARY_DIR}/include) + "${PROJECT_BINARY_DIR}/include/config.h") + ################################ FILES ################################ @@ -238,9 +239,9 @@ ENDIF(APPLE) # Link additional libraries IF(WIN32) - SET(MultiMC_LINK_ADDITIONAL_LIBS ${MultiMC_LINK_ADDITIONAL_LIBS} - Qt5::WinMain # Link WinMain - ) + SET(MultiMC_LINK_ADDITIONAL_LIBS ${MultiMC_LINK_ADDITIONAL_LIBS} + Qt5::WinMain # Link WinMain + ) ENDIF(WIN32) # Tell CMake that MultiMCLauncher.jar is generated. @@ -261,11 +262,17 @@ libUtil libSettings libMultiMC libGroupView ${MultiMC_LINK_ADDITIONAL_LIBS}) ADD_DEPENDENCIES(MultiMC MultiMCLauncher libUtil libSettings libMultiMC libGroupView) +IF(DEFINED MMC_KEYRING_TEST) +# test.cpp +ADD_EXECUTABLE(Test test.cpp) +QT5_USE_MODULES(Test Core) +TARGET_LINK_LIBRARIES(Test libmmcutil libmmcsettings) +ENDIF() ################################ INSTALLATION AND PACKAGING ################################ # use QtCreator's QTDIR var IF(DEFINED ENV{QTDIR}) - SET(Qt5_DIR $ENV{QTDIR}) + SET(Qt5_DIR $ENV{QTDIR}) ENDIF() ######## Plugin and library folders ######## @@ -283,7 +290,7 @@ ENDIF() IF(APPLE) SET(PLUGIN_DEST_DIR MultiMC.app/Contents/MacOS) SET(QTCONF_DEST_DIR MultiMC.app/Contents/Resources) - SET(APPS "\${CMAKE_INSTALL_PREFIX}/MultiMC.app") + SET(APPS "\${CMAKE_INSTALL_PREFIX}/MultiMC.app") ENDIF() SET(QT_PLUGINS_DIR ${Qt5_DIR}/plugins) @@ -354,13 +361,13 @@ INSTALL(CODE " # Package with CPack IF(UNIX) - if(APPLE) - SET(CPACK_GENERATOR "ZIP") - else() - SET(CPACK_GENERATOR "TGZ") - endif() + if(APPLE) + SET(CPACK_GENERATOR "ZIP") + else() + SET(CPACK_GENERATOR "TGZ") + endif() ELSEIF(WIN32) - SET(CPACK_GENERATOR "ZIP") + SET(CPACK_GENERATOR "ZIP") ENDIF() SET(CPACK_INCLUDE_TOPLEVEL_DIRECTORY 0) @@ -383,3 +390,5 @@ SET(CPACK_PACKAGE_INSTALL_DIRECTORY "MultiMC 5") ENDIF() INCLUDE(CPack) + +include_directories(${PROJECT_BINARY_DIR}/include) diff --git a/java/constants.h b/java/constants.h index 2f968d2e..61aa5687 100644 --- a/java/constants.h +++ b/java/constants.h @@ -7,7 +7,7 @@ namespace java class constant { public: - enum type_t:uint8_t + enum type_t : uint8_t { j_hole = 0, // HACK: this is a hole in the array, because java is crazy j_string_data = 1, @@ -22,6 +22,7 @@ namespace java j_interface_methodref = 11, j_nameandtype = 12 } type; + constant(util::membuffer & buf ) { buf.read(type); @@ -66,10 +67,12 @@ namespace java break; } } + constant(int fake) { type = j_hole; } + std::string toString() { std::ostringstream ss; @@ -143,6 +146,7 @@ namespace java } name_and_type; }; }; + /** * A helper class that represents the custom container used in Java class file for storage of constants */ @@ -181,7 +185,7 @@ namespace java index++; } } - }; + } typedef std::vector<java::constant> container_type; /** * Access constants based on jar file index numbers (index of the first element is 1) diff --git a/java/javautils.cpp b/java/javautils.cpp index a07d1541..4a359031 100644 --- a/java/javautils.cpp +++ b/java/javautils.cpp @@ -1,69 +1,81 @@ +/* Copyright 2013 MultiMC Contributors + * + * Authors: Orochimarufan <orochimarufan.x3@gmail.com> + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ #include "multimc_pragma.h" #include "classfile.h" #include "javautils.h" -//#include <wx/zipstrm.h> -#include <memory> -//#include <wx/wfstream.h> -//#include "mcversionlist.h" + +#include <QFile> +#include <quazipfile.h> namespace javautils { -QString GetMinecraftJarVersion(QString jar) + +QString GetMinecraftJarVersion(QString jarName) { - return "Unknown"; - /* - wxString fullpath = jar.GetFullPath(); - wxString version = MCVer_Unknown; - if(!jar.FileExists()) + QString version = MCVer_Unknown; + + // check if minecraft.jar exists + QFile jar(jarName); + if (!jar.exists()) return version; - std::auto_ptr<wxZipEntry> entry; - // convert the local name we are looking for into the internal format - wxString name = wxZipEntry::GetInternalName("net/minecraft/client/Minecraft.class",wxPATH_UNIX); - // open the zip - wxFFileInputStream inStream(jar.GetFullPath()); - wxZipInputStream zipIn(inStream); + // open minecraft.jar + QuaZip zip(&jar); + if (!zip.open(QuaZip::mdUnzip)) + return version; - // call GetNextEntry() until the required internal name is found - do - { - entry.reset(zipIn.GetNextEntry()); - } - while (entry.get() != NULL && entry->GetInternalName() != name); - auto myentry = entry.get(); - if (myentry == NULL) + // open Minecraft.class + zip.setCurrentFile("net/minecraft/client/Minecraft.class", QuaZip::csSensitive); + QuaZipFile Minecraft(&zip); + if (!Minecraft.open(QuaZipFile::ReadOnly)) return version; - - // we got the entry, read the data - std::size_t size = myentry->GetSize(); - char *classdata = new char[size]; - zipIn.Read(classdata,size); - try - { - char * temp = classdata; - java::classfile Minecraft_jar(temp,size); - auto cnst = Minecraft_jar.constants; - auto iter = cnst.begin(); - while (iter != cnst.end()) + + // read Minecraft.class + qint64 size = Minecraft.size(); + char *classfile = new char[size]; + Minecraft.read(classfile, size); + + // parse Minecraft.class + try { + char *temp = classfile; + java::classfile MinecraftClass(temp, size); + java::constant_pool constants = MinecraftClass.constants; + for(java::constant_pool::container_type::const_iterator iter=constants.begin(); + iter != constants.end(); iter++) { const java::constant & constant = *iter; - if(constant.type != java::constant::j_string_data) - { - iter++; + if (constant.type != java::constant::j_string_data) continue; - } - auto & str = constant.str_data; - const char * lookfor = "Minecraft Minecraft "; // length = 20 - if(str.compare(0,20,lookfor) == 0) + const std::string & str = constant.str_data; + if (str.compare(0, 20, "Minecraft Minecraft ") == 0) { version = str.substr(20).data(); break; } - iter++; } - } catch(java::classfile_exception &){} - delete[] classdata; + } catch(java::classfile_exception &) {} + + // clean up + delete[] classfile; + Minecraft.close(); + zip.close(); + jar.close(); + return version; - */ } -}
\ No newline at end of file + +} diff --git a/java/javautils.h b/java/javautils.h index c8b5a793..883eff1d 100644 --- a/java/javautils.h +++ b/java/javautils.h @@ -1,9 +1,28 @@ +/* Copyright 2013 MultiMC Contributors + * + * Authors: Orochimarufan <orochimarufan.x3@gmail.com> + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ #pragma once #include <QString> + +#define MCVer_Unknown "Unknown" + namespace javautils { - /* - * Get the version from a minecraft.jar by parsing its class files. Expensive! + /** + * @brief Get the version from a minecraft.jar by parsing its class files. Expensive! */ QString GetMinecraftJarVersion(QString jar); -}
\ No newline at end of file +} diff --git a/libmultimc/include/minecraftprocess.h b/libmultimc/include/minecraftprocess.h index 8986f7ad..d6b9f612 100644 --- a/libmultimc/include/minecraftprocess.h +++ b/libmultimc/include/minecraftprocess.h @@ -85,7 +85,7 @@ protected: QStringList m_arguments; void genArgs(); - void log(QString text); + void log(QString text, ConsoleWindow::WriteMode mode = ConsoleWindow::MULTIMC); protected slots: void finish(int, QProcess::ExitStatus status); diff --git a/libmultimc/src/minecraftprocess.cpp b/libmultimc/src/minecraftprocess.cpp index 943d76b1..3aecb1ee 100644 --- a/libmultimc/src/minecraftprocess.cpp +++ b/libmultimc/src/minecraftprocess.cpp @@ -197,6 +197,8 @@ void MinecraftProcess::launch() start(m_instance->settings().get("JavaPath").toString(), m_arguments); if (!waitForStarted()) { + log("Could not launch minecraft!", ConsoleWindow::ERROR); + return; //TODO: error handling } diff --git a/libsettings/include/keyring.h b/libsettings/include/keyring.h new file mode 100644 index 00000000..afdc3bba --- /dev/null +++ b/libsettings/include/keyring.h @@ -0,0 +1,85 @@ +/* Copyright 2013 MultiMC Contributors + * + * Authors: Orochimarufan <orochimarufan.x3@gmail.com> + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef KEYRING_H +#define KEYRING_H + +#include <QObject> + +#include "libsettings_config.h" + +/** + * @file libsettings/include/keyring.h + * Access to System Keyrings + */ + +/** + * @brief The Keyring class + * the System Keyring/Keychain/Wallet/Vault/etc + */ +class LIBMMCSETTINGS_EXPORT Keyring : public QObject +{ + Q_OBJECT +public: + /** + * @brief the System Keyring instance + * @return the Keyring instance + */ + static Keyring *instance(); + + /** + * @brief store a password in the Keyring + * @param service the service name + * @param username the account name + * @param password the password to store + * @return success + */ + virtual bool storePassword(QString service, QString username, QString password) = 0; + + /** + * @brief get a password from the Keyring + * @param service the service name + * @param username the account name + * @return the password (success=!isNull()) + */ + virtual QString getPassword(QString service, QString username) = 0; + + /** + * @brief lookup a password + * @param service the service name + * @param username the account name + * @return wether the password is available + */ + virtual bool hasPassword(QString service, QString username) = 0; + + /** + * @brief get a list of all stored accounts. + * @param service the service name + * @return + */ + virtual QStringList getStoredAccounts(QString service) = 0; + +protected: + /// fall back to StubKeyring if false + virtual bool isValid() { return false; } + +private: + static Keyring *m_instance; + static void destroy(); +}; + +#endif // KEYRING_H diff --git a/libsettings/src/keyring.cpp b/libsettings/src/keyring.cpp new file mode 100644 index 00000000..9eaba684 --- /dev/null +++ b/libsettings/src/keyring.cpp @@ -0,0 +1,63 @@ +/* Copyright 2013 MultiMC Contributors + * + * Authors: Orochimarufan <orochimarufan.x3@gmail.com> + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include "include/keyring.h" + +#include "osutils.h" + +#include "stubkeyring.h" + +// system specific keyrings +/*#if defined(OSX) +class OSXKeychain; +#define KEYRING OSXKeychain +#elif defined(LINUX) +class XDGKeyring; +#define KEYRING XDGKeyring +#elif defined(WINDOWS) +class Win32Keystore; +#define KEYRING Win32Keystore +#else +#pragma message Keyrings are not supported on your os. Falling back to the insecure StubKeyring +#endif*/ + +Keyring *Keyring::instance() +{ + if (m_instance == nullptr) + { +#ifdef KEYRING + m_instance = new KEYRING(); + if (!m_instance->isValid()) + { + qWarning("Could not create SystemKeyring! falling back to StubKeyring."); + m_instance = new StubKeyring(); + } +#else + qWarning("Keyrings are not supported on your OS. Fallback StubKeyring is insecure!"); + m_instance = new StubKeyring(); +#endif + atexit(Keyring::destroy); + } + return m_instance; +} + +void Keyring::destroy() +{ + delete m_instance; +} + +Keyring *Keyring::m_instance; diff --git a/libsettings/src/stubkeyring.cpp b/libsettings/src/stubkeyring.cpp new file mode 100644 index 00000000..963f3dd9 --- /dev/null +++ b/libsettings/src/stubkeyring.cpp @@ -0,0 +1,96 @@ +/* Copyright 2013 MultiMC Contributors + * + * Authors: Orochimarufan <orochimarufan.x3@gmail.com> + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include "stubkeyring.h" + +#include <QStringList> + +// Scrambling +// this is NOT SAFE, but it's not plain either. +int scrambler = 0x9586309; + +QString scramble(QString in_) +{ + QByteArray in = in_.toUtf8(); + QByteArray out; + for (int i = 0; i<in.length(); i++) + out.append(in.at(i) ^ scrambler); + return QString::fromUtf8(out); +} + +inline QString base64(QString in) +{ + return QString(in.toUtf8().toBase64()); +} +inline QString unbase64(QString in) +{ + return QString::fromUtf8(QByteArray::fromBase64(in.toLatin1())); +} + +inline QString scramble64(QString in) +{ + return base64(scramble(in)); +} +inline QString unscramble64(QString in) +{ + return scramble(unbase64(in)); +} + +// StubKeyring implementation +inline QString generateKey(QString service, QString username) +{ + return QString("%1/%2").arg(base64(service)).arg(scramble64(username)); +} + +bool StubKeyring::storePassword(QString service, QString username, QString password) +{ + m_settings.setValue(generateKey(service, username), scramble64(password)); + return true; +} + +QString StubKeyring::getPassword(QString service, QString username) +{ + QString key = generateKey(service, username); + if (!m_settings.contains(key)) + return QString(); + return unscramble64(m_settings.value(key).toString()); +} + +bool StubKeyring::hasPassword(QString service, QString username) +{ + return m_settings.contains(generateKey(service, username)); +} + +QStringList StubKeyring::getStoredAccounts(QString service) +{ + service = base64(service).append('/'); + QStringList out; + QStringList in(m_settings.allKeys()); + QStringListIterator it(in); + while(it.hasNext()) + { + QString c = it.next(); + if (c.startsWith(service)) + out << unscramble64(c.mid(service.length())); + } + return out; +} + +StubKeyring::StubKeyring() : + m_settings(QSettings::UserScope, "Orochimarufan", "Keyring") +{ +} diff --git a/libsettings/src/stubkeyring.h b/libsettings/src/stubkeyring.h new file mode 100644 index 00000000..0566d5ab --- /dev/null +++ b/libsettings/src/stubkeyring.h @@ -0,0 +1,42 @@ +/* Copyright 2013 MultiMC Contributors + * + * Authors: Orochimarufan <orochimarufan.x3@gmail.com> + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef STUBKEYRING_H +#define STUBKEYRING_H + +#include "include/keyring.h" + +#include <QSettings> + +class StubKeyring : public Keyring +{ + Q_OBJECT +public: + virtual bool storePassword(QString service, QString username, QString password); + virtual QString getPassword(QString service, QString username); + virtual bool hasPassword(QString service, QString username); + virtual QStringList getStoredAccounts(QString service); + +private: + friend class Keyring; + explicit StubKeyring(); + virtual bool isValid() { return true; } + + QSettings m_settings; +}; + +#endif // STUBKEYRING_H diff --git a/libutil/include/cmdutils.h b/libutil/include/cmdutils.h index 32261dd7..83397e73 100644 --- a/libutil/include/cmdutils.h +++ b/libutil/include/cmdutils.h @@ -73,15 +73,6 @@ enum LIBUTIL_EXPORT Enum }; } -namespace OptionType -{ -enum LIBUTIL_EXPORT Enum -{ - Switch, - Option -}; -} - /** * @brief The ParsingError class */ @@ -210,6 +201,12 @@ public: private: FlagStyle::Enum m_flagStyle; ArgumentStyle::Enum m_argStyle; + + enum OptionType + { + otSwitch, + otOption + }; // Important: the common part MUST BE COMMON ON ALL THREE structs struct CommonDef { @@ -226,7 +223,7 @@ private: QString metavar; QVariant def; // option - OptionType::Enum type; + OptionType type; QChar flag; }; diff --git a/libutil/src/cmdutils.cpp b/libutil/src/cmdutils.cpp index 3bf4e872..13db503d 100644 --- a/libutil/src/cmdutils.cpp +++ b/libutil/src/cmdutils.cpp @@ -56,7 +56,7 @@ void Parser::addSwitch(QString name, bool def) throw "Name not unique"; OptionDef *param = new OptionDef; - param->type = OptionType::Switch; + param->type = otSwitch; param->name = name; param->metavar = QString("<%1>").arg(name); param->def = def; @@ -72,7 +72,7 @@ void Parser::addOption(QString name, QVariant def) throw "Name not unique"; OptionDef *param = new OptionDef; - param->type = OptionType::Option; + param->type = otOption; param->name = name; param->metavar = QString("<%1>").arg(name); param->def = def; @@ -161,7 +161,7 @@ QString Parser::compileHelp(QString progName, int helpIndent, bool useFlags) help << flagPrefix << option->flag << ", "; } help << optPrefix << option->name; - if (option->type == OptionType::Option) + if (option->type == otOption) { QString arg = QString("%1%2").arg(((m_argStyle == ArgumentStyle::Equals) ? "=" : " "), option->metavar); nameLength += arg.length(); @@ -193,7 +193,7 @@ QString Parser::compileUsage(QString progName, bool useFlags) usage << flagPrefix << option->flag; else usage << optPrefix << option->name; - if (option->type == OptionType::Option) + if (option->type == otOption) usage << ((m_argStyle == ArgumentStyle::Equals) ? "=" : " ") << option->metavar; usage << "]"; } @@ -265,9 +265,9 @@ QHash<QString, QVariant> Parser::parse(QStringList argv) throw ParsingError(QString("Option %2%1 was given multiple times").arg(name, optionPrefix)); OptionDef *option = m_options[name]; - if (option->type == OptionType::Switch) + if (option->type == otSwitch) map[name] = true; - else //if (option->type == OptionType::Option) + else //if (option->type == otOption) { if (m_argStyle == ArgumentStyle::Space) expecting.append(name); @@ -312,9 +312,9 @@ QHash<QString, QVariant> Parser::parse(QStringList argv) if (map.contains(option->name)) throw ParsingError(QString("Option %2%1 was given multiple times").arg(option->name, optionPrefix)); - if (option->type == OptionType::Switch) + if (option->type == otSwitch) map[option->name] = true; - else //if (option->type == OptionType::Option) + else //if (option->type == otOption) { if (m_argStyle == ArgumentStyle::Space) expecting.append(option->name); diff --git a/test.cpp b/test.cpp new file mode 100644 index 00000000..2b015454 --- /dev/null +++ b/test.cpp @@ -0,0 +1,60 @@ + +#include <iostream> + +#include "keyring.h" +#include "cmdutils.h" + +using namespace Util::Commandline; + +#include <QCoreApplication> + +int main(int argc, char **argv) +{ + QCoreApplication app(argc, argv); + app.setApplicationName("MMC Keyring test"); + app.setOrganizationName("Orochimarufan"); + + Parser p; + p.addArgument("user", false); + p.addArgument("password", false); + p.addSwitch("set"); + p.addSwitch("get"); + p.addSwitch("list"); + p.addOption("service", "Test"); + p.addShortOpt("service", 's'); + + QHash<QString, QVariant> args; + try { + args = p.parse(app.arguments()); + } catch (ParsingError) { + std::cout << "Syntax error." << std::endl; + return 1; + } + + if (args["set"].toBool()) { + if (args["user"].isNull() || args["password"].isNull()) { + std::cout << "set operation needs bot user and password set" << std::endl; + return 1; + } + + return Keyring::instance()->storePassword(args["service"].toString(), + args["user"].toString(), args["password"].toString()); + } else if (args["get"].toBool()) { + if (args["user"].isNull()) { + std::cout << "get operation needs user set" << std::endl; + return 1; + } + + std::cout << "Password: " << qPrintable(Keyring::instance()->getPassword(args["service"].toString(), + args["user"].toString())) << std::endl; + return 0; + } else if (args["list"].toBool()) { + QStringList accounts = Keyring::instance()->getStoredAccounts(args["service"].toString()); + std::cout << "stored accounts:" << std::endl << '\t' << qPrintable(accounts.join("\n\t")) << std::endl; + return 0; + } else { + std::cout << "No operation given!" << std::endl; + std::cout << qPrintable(p.compileHelp(argv[0])) << std::endl; + return 1; + } +} |