aboutsummaryrefslogtreecommitdiffstats
path: root/lang/qt/src/qgpgmecryptoconfig.cpp
diff options
context:
space:
mode:
Diffstat (limited to '')
-rw-r--r--lang/qt/src/qgpgmecryptoconfig.cpp948
1 files changed, 0 insertions, 948 deletions
diff --git a/lang/qt/src/qgpgmecryptoconfig.cpp b/lang/qt/src/qgpgmecryptoconfig.cpp
deleted file mode 100644
index fe3e54f3..00000000
--- a/lang/qt/src/qgpgmecryptoconfig.cpp
+++ /dev/null
@@ -1,948 +0,0 @@
-/*
- qgpgmecryptoconfig.cpp
-
- This file is part of qgpgme, the Qt API binding for gpgme
- Copyright (c) 2004 Klarälvdalens Datakonsult AB
- Copyright (c) 2016 Intevation GmbH
-
- Libkleopatra 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 of the
- License, or (at your option) any later version.
-
- Libkleopatra 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, write to the Free Software
- Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
-
- In addition, as a special exception, the copyright holders give
- permission to link the code of this program with any edition of
- the Qt library by Trolltech AS, Norway (or with modified versions
- of Qt that use the same license as Qt), and distribute linked
- combinations including the two. You must obey the GNU General
- Public License in all respects for all of the code used other than
- Qt. If you modify this file, you may extend this exception to
- your version of the file, but you are not obligated to do so. If
- you do not wish to do so, delete this exception statement from
- your version.
-*/
-
-#include "qgpgmecryptoconfig.h"
-
-#include <QList>
-#include <QByteArray>
-#include <errno.h>
-#include "gpgme_backend_debug.h"
-
-#include "engineinfo.h"
-#include "global.h"
-
-#include <cassert>
-#include <QTemporaryFile>
-#include <QFile>
-#include <cstdlib>
-#include <iterator>
-#include <QStandardPaths>
-
-// Just for the Q_ASSERT in the dtor. Not thread-safe, but who would
-// have 2 threads talking to gpgconf anyway? :)
-static bool s_duringClear = false;
-
-static const int GPGCONF_FLAG_GROUP = 1;
-static const int GPGCONF_FLAG_OPTIONAL = 2;
-static const int GPGCONF_FLAG_LIST = 4;
-static const int GPGCONF_FLAG_RUNTIME = 8;
-static const int GPGCONF_FLAG_DEFAULT = 16; // fixed default value available
-//static const int GPGCONF_FLAG_DEFAULT_DESC = 32; // runtime default value available
-//static const int GPGCONF_FLAG_NOARG_DESC = 64; // option with optional arg; special meaning if no arg set
-static const int GPGCONF_FLAG_NO_CHANGE = 128; // readonly
-// Change size of mFlags bitfield if adding new values here
-
-QString QGpgMECryptoConfig::gpgConfPath()
-{
- const GpgME::EngineInfo info = GpgME::engineInfo(GpgME::GpgConfEngine);
- return info.fileName() ? QFile::decodeName(info.fileName()) : QStandardPaths::findExecutable(QStringLiteral("gpgconf"));
-}
-
-QGpgMECryptoConfig::QGpgMECryptoConfig()
- : mParsed(false)
-{
-}
-
-QGpgMECryptoConfig::~QGpgMECryptoConfig()
-{
- clear();
-}
-
-void QGpgMECryptoConfig::runGpgConf(bool showErrors)
-{
- // Run gpgconf --list-components to make the list of components
- KProcess process;
-
- process << gpgConfPath();
- process << QStringLiteral("--list-components");
-
- connect(&process, &KProcess::readyReadStandardOutput, this, &QGpgMECryptoConfig::slotCollectStdOut);
-
- // run the process:
- int rc = 0;
- process.setOutputChannelMode(KProcess::OnlyStdoutChannel);
- process.start();
- if (!process.waitForFinished()) {
- rc = -2;
- } else if (process.exitStatus() == QProcess::NormalExit) {
- rc = process.exitCode();
- } else {
- rc = -1;
- }
-
- // handle errors, if any (and if requested)
- if (showErrors && rc != 0) {
- QString reason;
- if (rc == -1) {
- reason = i18n("program terminated unexpectedly");
- } else if (rc == -2) {
- reason = i18n("program not found or cannot be started");
- } else {
- reason = QString::fromLocal8Bit(strerror(rc)); // XXX errno as an exit code?
- }
- QString wmsg = i18n("<qt>Failed to execute gpgconf:<p>%1</p></qt>", reason);
- qCWarning(GPGPME_BACKEND_LOG) << wmsg; // to see it from test_cryptoconfig.cpp
- KMessageBox::error(0, wmsg);
- }
- mParsed = true;
-}
-
-void QGpgMECryptoConfig::slotCollectStdOut()
-{
- assert(qobject_cast<KProcess *>(QObject::sender()));
- KProcess *const proc = static_cast<KProcess *>(QObject::sender());
- while (proc->canReadLine()) {
- QString line = QString::fromUtf8(proc->readLine());
- if (line.endsWith(QLatin1Char('\n'))) {
- line.chop(1);
- }
- if (line.endsWith(QLatin1Char('\r'))) {
- line.chop(1);
- }
- //qCDebug(GPGPME_BACKEND_LOG) <<"GOT LINE:" << line;
- // Format: NAME:DESCRIPTION
- const QStringList lst = line.split(QLatin1Char(':'));
- if (lst.count() >= 2) {
- const std::pair<QString, QGpgMECryptoConfigComponent *> pair(lst[0], new QGpgMECryptoConfigComponent(this, lst[0], lst[1]));
- mComponentsNaturalOrder.push_back(pair);
- mComponentsByName[pair.first] = pair.second;
- } else {
- qCWarning(GPGPME_BACKEND_LOG) << "Parse error on gpgconf --list-components output:" << line;
- }
- }
-}
-
-namespace
-{
-struct Select1St {
- template <typename U, typename V>
- const U &operator()(const std::pair<U, V> &p) const
- {
- return p.first;
- }
- template <typename U, typename V>
- const U &operator()(const QPair<U, V> &p) const
- {
- return p.first;
- }
-};
-}
-
-QStringList QGpgMECryptoConfig::componentList() const
-{
- if (!mParsed) {
- const_cast<QGpgMECryptoConfig *>(this)->runGpgConf(true);
- }
- QStringList result;
- std::transform(mComponentsNaturalOrder.begin(), mComponentsNaturalOrder.end(),
- std::back_inserter(result), Select1St());
- return result;
-}
-
-QGpgME::CryptoConfigComponent *QGpgMECryptoConfig::component(const QString &name) const
-{
- if (!mParsed) {
- const_cast<QGpgMECryptoConfig *>(this)->runGpgConf(false);
- }
- return mComponentsByName.value(name);
-}
-
-void QGpgMECryptoConfig::sync(bool runtime)
-{
- Q_FOREACH (QGpgMECryptoConfigComponent *it, mComponentsByName) {
- it->sync(runtime);
- }
-}
-
-void QGpgMECryptoConfig::clear()
-{
- s_duringClear = true;
- mComponentsNaturalOrder.clear();
- qDeleteAll(mComponentsByName);
- mComponentsByName.clear();
- s_duringClear = false;
- mParsed = false; // next call to componentList/component will need to run gpgconf again
-}
-
-////
-
-QGpgMECryptoConfigComponent::QGpgMECryptoConfigComponent(QGpgMECryptoConfig *, const QString &name, const QString &description)
- : mName(name), mDescription(description)
-{
- runGpgConf();
-}
-
-QGpgMECryptoConfigComponent::~QGpgMECryptoConfigComponent()
-{
- mGroupsNaturalOrder.clear();
- qDeleteAll(mGroupsByName);
- mGroupsByName.clear();
-}
-
-void QGpgMECryptoConfigComponent::runGpgConf()
-{
- const QString gpgconf = QGpgMECryptoConfig::gpgConfPath();
- if (gpgconf.isEmpty()) {
- qCWarning(GPGPME_BACKEND_LOG) << "Can't get path to gpgconf executable...";
- return;
- }
-
- // Run gpgconf --list-options <component>, and create all groups and entries for that component
- KProcess proc;
- proc << gpgconf;
- proc << QStringLiteral("--list-options");
- proc << mName;
-
- //qCDebug(GPGPME_BACKEND_LOG) <<"Running gpgconf --list-options" << mName;
-
- connect(&proc, &KProcess::readyReadStandardOutput, this, &QGpgMECryptoConfigComponent::slotCollectStdOut);
- mCurrentGroup = 0;
-
- // run the process:
- int rc = 0;
- proc.setOutputChannelMode(KProcess::OnlyStdoutChannel);
- proc.start();
- if (!proc.waitForFinished()) {
- rc = -2;
- } else if (proc.exitStatus() == QProcess::NormalExit) {
- rc = proc.exitCode();
- } else {
- rc = -1;
- }
-
- if (rc != 0) { // can happen when using the wrong version of gpg...
- qCWarning(GPGPME_BACKEND_LOG) << "Running 'gpgconf --list-options" << mName << "' failed." << strerror(rc) << ", but try that command to see the real output";
- } else {
- if (mCurrentGroup && !mCurrentGroup->mEntriesNaturalOrder.empty()) { // only add non-empty groups
- mGroupsByName.insert(mCurrentGroupName, mCurrentGroup);
- mGroupsNaturalOrder.push_back(std::make_pair(mCurrentGroupName, mCurrentGroup));
- }
- }
-}
-
-void QGpgMECryptoConfigComponent::slotCollectStdOut()
-{
- assert(qobject_cast<KProcess *>(QObject::sender()));
- KProcess *const proc = static_cast<KProcess *>(QObject::sender());
- while (proc->canReadLine()) {
- QString line = QString::fromUtf8(proc->readLine());
- if (line.endsWith(QLatin1Char('\n'))) {
- line.chop(1);
- }
- if (line.endsWith(QLatin1Char('\r'))) {
- line.chop(1);
- }
- //qCDebug(GPGPME_BACKEND_LOG) <<"GOT LINE:" << line;
- // Format: NAME:FLAGS:LEVEL:DESCRIPTION:TYPE:ALT-TYPE:ARGNAME:DEFAULT:ARGDEF:VALUE
- const QStringList lst = line.split(QLatin1Char(':'));
- if (lst.count() >= 10) {
- const int flags = lst[1].toInt();
- const int level = lst[2].toInt();
- if (level > 2) { // invisible or internal -> skip it;
- continue;
- }
- if (flags & GPGCONF_FLAG_GROUP) {
- if (mCurrentGroup && !mCurrentGroup->mEntriesNaturalOrder.empty()) { // only add non-empty groups
- mGroupsByName.insert(mCurrentGroupName, mCurrentGroup);
- mGroupsNaturalOrder.push_back(std::make_pair(mCurrentGroupName, mCurrentGroup));
- }
- //else
- // qCDebug(GPGPME_BACKEND_LOG) <<"Discarding empty group" << mCurrentGroupName;
- mCurrentGroup = new QGpgMECryptoConfigGroup(this, lst[0], lst[3], level);
- mCurrentGroupName = lst[0];
- } else {
- // normal entry
- if (!mCurrentGroup) { // first toplevel entry -> create toplevel group
- mCurrentGroup = new QGpgMECryptoConfigGroup(this, QStringLiteral("<nogroup>"), QString(), 0);
- mCurrentGroupName = QStringLiteral("<nogroup>");
- }
- const QString &name = lst[0];
- QGpgMECryptoConfigEntry *value = new QGpgMECryptoConfigEntry(mCurrentGroup, lst);
- mCurrentGroup->mEntriesByName.insert(name, value);
- mCurrentGroup->mEntriesNaturalOrder.push_back(std::make_pair(name, value));
- }
- } else {
- // This happens on lines like
- // dirmngr[31465]: error opening `/home/dfaure/.gnupg/dirmngr_ldapservers.conf': No such file or directory
- // so let's not bother the user with it.
- //qCWarning(GPGPME_BACKEND_LOG) <<"Parse error on gpgconf --list-options output:" << line;
- }
- }
-}
-
-QStringList QGpgMECryptoConfigComponent::groupList() const
-{
- QStringList result;
- std::transform(mGroupsNaturalOrder.begin(), mGroupsNaturalOrder.end(),
- std::back_inserter(result), Select1St());
- return result;
-}
-
-QGpgME::CryptoConfigGroup *QGpgMECryptoConfigComponent::group(const QString &name) const
-{
- return mGroupsByName.value(name);
-}
-
-void QGpgMECryptoConfigComponent::sync(bool runtime)
-{
- QTemporaryFile tmpFile;
- tmpFile.open();
-
- QList<QGpgMECryptoConfigEntry *> dirtyEntries;
-
- // Collect all dirty entries
- const QList<QString> keylist = mGroupsByName.uniqueKeys();
- Q_FOREACH (const QString &key, keylist) {
- const QHash<QString, QGpgMECryptoConfigEntry *> entry = mGroupsByName[key]->mEntriesByName;
- const QList<QString> keylistentry = entry.uniqueKeys();
- Q_FOREACH (const QString &keyentry, keylistentry) {
- if (entry[keyentry]->isDirty()) {
- // OK, we can set it.currentKey() to it.current()->outputString()
- QString line = keyentry;
- if (entry[keyentry]->isSet()) { // set option
- line += QLatin1String(":0:");
- line += entry[keyentry]->outputString();
- } else { // unset option
- line += QLatin1String(":16:");
- }
-#ifdef Q_OS_WIN
- line += QLatin1Char('\r');
-#endif
- line += QLatin1Char('\n');
- const QByteArray line8bit = line.toUtf8(); // encode with utf8, and K3ProcIO uses utf8 when reading.
- tmpFile.write(line8bit);
- dirtyEntries.append(entry[keyentry]);
-
- }
- }
- }
-
- tmpFile.flush();
- if (dirtyEntries.isEmpty()) {
- return;
- }
-
- // Call gpgconf --change-options <component>
- const QString gpgconf = QGpgMECryptoConfig::gpgConfPath();
- QString commandLine = gpgconf.isEmpty()
- ? QStringLiteral("gpgconf")
- : KShell::quoteArg(gpgconf);
- if (runtime) {
- commandLine += QLatin1String(" --runtime");
- }
- commandLine += QLatin1String(" --change-options ");
- commandLine += KShell::quoteArg(mName);
- commandLine += QLatin1String(" < ");
- commandLine += KShell::quoteArg(tmpFile.fileName());
-
- //qCDebug(GPGPME_BACKEND_LOG) << commandLine;
- //system( QCString( "cat " ) + tmpFile.name().toLatin1() ); // DEBUG
-
- KProcess proc;
- proc.setShellCommand(commandLine);
-
- // run the process:
- int rc = proc.execute();
-
- if (rc == -2) {
- QString wmsg = i18n("Could not start gpgconf.\nCheck that gpgconf is in the PATH and that it can be started.");
- qCWarning(GPGPME_BACKEND_LOG) << wmsg;
- KMessageBox::error(0, wmsg);
- } else if (rc != 0) { // Happens due to bugs in gpgconf (e.g. issues 104/115)
- QString wmsg = i18n("Error from gpgconf while saving configuration: %1", QString::fromLocal8Bit(strerror(rc)));
- qCWarning(GPGPME_BACKEND_LOG) << ":" << strerror(rc);
- KMessageBox::error(0, wmsg);
- } else {
- QList<QGpgMECryptoConfigEntry *>::const_iterator it = dirtyEntries.constBegin();
- for (; it != dirtyEntries.constEnd(); ++it) {
- (*it)->setDirty(false);
- }
- }
-}
-
-////
-
-QGpgMECryptoConfigGroup::QGpgMECryptoConfigGroup(QGpgMECryptoConfigComponent *comp, const QString &name, const QString &description, int level)
- :
- mComponent(comp),
- mName(name),
- mDescription(description),
- mLevel(static_cast<QGpgME::CryptoConfigEntry::Level>(level))
-{
-}
-
-QGpgMECryptoConfigGroup::~QGpgMECryptoConfigGroup()
-{
- mEntriesNaturalOrder.clear();
- qDeleteAll(mEntriesByName);
- mEntriesByName.clear();
-}
-
-QStringList QGpgMECryptoConfigGroup::entryList() const
-{
- QStringList result;
- std::transform(mEntriesNaturalOrder.begin(), mEntriesNaturalOrder.end(),
- std::back_inserter(result), Select1St());
- return result;
-}
-
-QGpgME::CryptoConfigEntry *QGpgMECryptoConfigGroup::entry(const QString &name) const
-{
- return mEntriesByName.value(name);
-}
-
-////
-
-static QString gpgconf_unescape(const QString &str, bool handleComma = true)
-{
- /* See gpgconf_escape */
- QString dec(str);
- dec.replace(QStringLiteral("%25"), QStringLiteral("%"));
- dec.replace(QStringLiteral("%3a"), QStringLiteral(":"));
- if (handleComma) {
- dec.replace(QStringLiteral("%2c"), QStringLiteral(","));
- }
- return dec;
-}
-
-static QString gpgconf_escape(const QString &str, bool handleComma = true)
-{
- /* Gpgconf does not really percent encode. It just
- * encodes , % and : characters. It expects all other
- * chars to be UTF-8 encoded.
- * Except in the Base-DN part where a , may not be percent
- * escaped.
- */
- QString esc(str);
- esc.replace(QLatin1Char('%'), QStringLiteral("%25"));
- esc.replace(QLatin1Char(':'), QStringLiteral("%3a"));
- if (handleComma) {
- esc.replace(QLatin1Char(','), QStringLiteral("%2c"));
- }
- return esc;
-}
-
-static QString urlpart_escape(const QString &str)
-{
- /* We need to double escape here, as a username or password
- * or an LDAP Base-DN may contain : or , and in that
- * case we would break gpgconf's format if we only escaped
- * the : once. As an escaped : is used internaly to split
- * the parts of an url. */
-
- return gpgconf_escape(gpgconf_escape(str, false), false);
-}
-
-static QString urlpart_unescape(const QString &str)
-{
- /* See urlpart_escape */
- return gpgconf_unescape(gpgconf_unescape(str, false), false);
-}
-
-// gpgconf arg type number -> CryptoConfigEntry arg type enum mapping
-static QGpgME::CryptoConfigEntry::ArgType knownArgType(int argType, bool &ok)
-{
- ok = true;
- switch (argType) {
- case 0: // none
- return QGpgME::CryptoConfigEntry::ArgType_None;
- case 1: // string
- return QGpgME::CryptoConfigEntry::ArgType_String;
- case 2: // int32
- return QGpgME::CryptoConfigEntry::ArgType_Int;
- case 3: // uint32
- return QGpgME::CryptoConfigEntry::ArgType_UInt;
- case 32: // pathname
- return QGpgME::CryptoConfigEntry::ArgType_Path;
- case 33: // ldap server
- return QGpgME::CryptoConfigEntry::ArgType_LDAPURL;
- default:
- ok = false;
- return QGpgME::CryptoConfigEntry::ArgType_None;
- }
-}
-
-QGpgMECryptoConfigEntry::QGpgMECryptoConfigEntry(QGpgMECryptoConfigGroup *group, const QStringList &parsedLine)
- : mGroup(group)
-{
- // Format: NAME:FLAGS:LEVEL:DESCRIPTION:TYPE:ALT-TYPE:ARGNAME:DEFAULT:ARGDEF:VALUE
- assert(parsedLine.count() >= 10); // called checked for it already
- QStringList::const_iterator it = parsedLine.constBegin();
- mName = *it++;
- mFlags = (*it++).toInt();
- mLevel = (*it++).toInt();
- mDescription = *it++;
- bool ok;
- // we keep the real (int) arg type, since it influences the parsing (e.g. for ldap urls)
- mRealArgType = (*it++).toInt();
- mArgType = knownArgType(mRealArgType, ok);
- if (!ok && !(*it).isEmpty()) {
- // use ALT-TYPE
- mRealArgType = (*it).toInt();
- mArgType = knownArgType(mRealArgType, ok);
- }
- if (!ok) {
- qCWarning(GPGPME_BACKEND_LOG) << "Unsupported datatype:" << parsedLine[4] << " :" << *it << " for" << parsedLine[0];
- }
- ++it; // done with alt-type
- ++it; // skip argname (not useful in GUIs)
-
- mSet = false;
- QString value;
- if (mFlags & GPGCONF_FLAG_DEFAULT) {
- value = *it; // get default value
- mDefaultValue = stringToValue(value, true);
- }
- ++it; // done with DEFAULT
- ++it; // ### skip ARGDEF for now. It's only for options with an "optional arg"
- //qCDebug(GPGPME_BACKEND_LOG) <<"Entry" << parsedLine[0] <<" val=" << *it;
-
- if (!(*it).isEmpty()) { // a real value was set
- mSet = true;
- value = *it;
- mValue = stringToValue(value, true);
- } else {
- mValue = mDefaultValue;
- }
-
- mDirty = false;
-}
-
-QVariant QGpgMECryptoConfigEntry::stringToValue(const QString &str, bool unescape) const
-{
- const bool isString = isStringType();
-
- if (isList()) {
- if (argType() == ArgType_None) {
- bool ok = true;
- const QVariant v = str.isEmpty() ? 0U : str.toUInt(&ok);
- if (!ok) {
- qCWarning(GPGPME_BACKEND_LOG) << "list-of-none should have an unsigned int as value:" << str;
- }
- return v;
- }
- QList<QVariant> lst;
- QStringList items = str.split(QLatin1Char(','), QString::SkipEmptyParts);
- for (QStringList::const_iterator valit = items.constBegin(); valit != items.constEnd(); ++valit) {
- QString val = *valit;
- if (isString) {
- if (val.isEmpty()) {
- lst << QVariant(QString());
- continue;
- } else if (unescape) {
- if (val[0] != QLatin1Char('"')) { // see README.gpgconf
- qCWarning(GPGPME_BACKEND_LOG) << "String value should start with '\"' :" << val;
- }
- val = val.mid(1);
- }
- }
- lst << QVariant(unescape ? gpgconf_unescape(val) : val);
- }
- return lst;
- } else { // not a list
- QString val(str);
- if (isString) {
- if (val.isEmpty()) {
- return QVariant(QString()); // not set [ok with lists too?]
- } else if (unescape) {
- if (val[0] != QLatin1Char('"')) { // see README.gpgconf
- qCWarning(GPGPME_BACKEND_LOG) << "String value should start with '\"' :" << val;
- }
- val = val.mid(1);
- }
- }
- return QVariant(unescape ? gpgconf_unescape(val) : val);
- }
-}
-
-QGpgMECryptoConfigEntry::~QGpgMECryptoConfigEntry()
-{
-#ifndef NDEBUG
- if (!s_duringClear && mDirty)
- qCWarning(GPGPME_BACKEND_LOG) << "Deleting a QGpgMECryptoConfigEntry that was modified (" << mDescription << ")"
- << "You forgot to call sync() (to commit) or clear() (to discard)";
-#endif
-}
-
-bool QGpgMECryptoConfigEntry::isOptional() const
-{
- return mFlags & GPGCONF_FLAG_OPTIONAL;
-}
-
-bool QGpgMECryptoConfigEntry::isReadOnly() const
-{
- return mFlags & GPGCONF_FLAG_NO_CHANGE;
-}
-
-bool QGpgMECryptoConfigEntry::isList() const
-{
- return mFlags & GPGCONF_FLAG_LIST;
-}
-
-bool QGpgMECryptoConfigEntry::isRuntime() const
-{
- return mFlags & GPGCONF_FLAG_RUNTIME;
-}
-
-bool QGpgMECryptoConfigEntry::isSet() const
-{
- return mSet;
-}
-
-bool QGpgMECryptoConfigEntry::boolValue() const
-{
- Q_ASSERT(mArgType == ArgType_None);
- Q_ASSERT(!isList());
- return mValue.toBool();
-}
-
-QString QGpgMECryptoConfigEntry::stringValue() const
-{
- return toString(false);
-}
-
-int QGpgMECryptoConfigEntry::intValue() const
-{
- Q_ASSERT(mArgType == ArgType_Int);
- Q_ASSERT(!isList());
- return mValue.toInt();
-}
-
-unsigned int QGpgMECryptoConfigEntry::uintValue() const
-{
- Q_ASSERT(mArgType == ArgType_UInt);
- Q_ASSERT(!isList());
- return mValue.toUInt();
-}
-
-static QUrl parseURL(int mRealArgType, const QString &str)
-{
- if (mRealArgType == 33) { // LDAP server
- // The format is HOSTNAME:PORT:USERNAME:PASSWORD:BASE_DN
- QStringList items = str.split(QLatin1Char(':'));
- if (items.count() == 5) {
- QStringList::const_iterator it = items.constBegin();
- QUrl url;
- url.setScheme(QStringLiteral("ldap"));
- url.setHost(gpgconf_unescape(*it++));
-
- bool ok;
- const int port = (*it++).toInt(&ok);
- if (ok) {
- url.setPort(port);
- } else if (!it->isEmpty()) {
- qCWarning(GPGPME_BACKEND_LOG) << "parseURL: malformed LDAP server port, ignoring: \"" << *it << "\"";
- }
-
- const QString userName = urlpart_unescape(*it++);
- if (!userName.isEmpty()) {
- url.setUserName(userName);
- }
- const QString passWord = urlpart_unescape(*it++);
- if (!passWord.isEmpty()) {
- url.setPassword(passWord);
- }
- url.setQuery(urlpart_unescape(*it));
- return url;
- } else {
- qCWarning(GPGPME_BACKEND_LOG) << "parseURL: malformed LDAP server:" << str;
- }
- }
- // other URLs : assume wellformed URL syntax.
- return QUrl(str);
-}
-
-// The opposite of parseURL
-static QString splitURL(int mRealArgType, const QUrl &url)
-{
- if (mRealArgType == 33) { // LDAP server
- // The format is HOSTNAME:PORT:USERNAME:PASSWORD:BASE_DN
- Q_ASSERT(url.scheme() == QLatin1String("ldap"));
- return gpgconf_escape(url.host()) + QLatin1Char(':') +
- (url.port() != -1 ? QString::number(url.port()) : QString()) + QLatin1Char(':') + // -1 is used for default ports, omit
- urlpart_escape(url.userName()) + QLatin1Char(':') +
- urlpart_escape(url.password()) + QLatin1Char(':') +
- urlpart_escape(url.query());
- }
- return url.path();
-}
-
-QUrl QGpgMECryptoConfigEntry::urlValue() const
-{
- Q_ASSERT(mArgType == ArgType_Path || mArgType == ArgType_LDAPURL);
- Q_ASSERT(!isList());
- QString str = mValue.toString();
- if (mArgType == ArgType_Path) {
- QUrl url = QUrl::fromUserInput(str, QString(), QUrl::AssumeLocalFile);
- return url;
- }
- return parseURL(mRealArgType, str);
-}
-
-unsigned int QGpgMECryptoConfigEntry::numberOfTimesSet() const
-{
- Q_ASSERT(mArgType == ArgType_None);
- Q_ASSERT(isList());
- return mValue.toUInt();
-}
-
-std::vector<int> QGpgMECryptoConfigEntry::intValueList() const
-{
- Q_ASSERT(mArgType == ArgType_Int);
- Q_ASSERT(isList());
- std::vector<int> ret;
- QList<QVariant> lst = mValue.toList();
- ret.reserve(lst.size());
- for (QList<QVariant>::const_iterator it = lst.constBegin(); it != lst.constEnd(); ++it) {
- ret.push_back((*it).toInt());
- }
- return ret;
-}
-
-std::vector<unsigned int> QGpgMECryptoConfigEntry::uintValueList() const
-{
- Q_ASSERT(mArgType == ArgType_UInt);
- Q_ASSERT(isList());
- std::vector<unsigned int> ret;
- QList<QVariant> lst = mValue.toList();
- ret.reserve(lst.size());
- for (QList<QVariant>::const_iterator it = lst.constBegin(); it != lst.constEnd(); ++it) {
- ret.push_back((*it).toUInt());
- }
- return ret;
-}
-
-QList<QUrl> QGpgMECryptoConfigEntry::urlValueList() const
-{
- Q_ASSERT(mArgType == ArgType_Path || mArgType == ArgType_LDAPURL);
- Q_ASSERT(isList());
- QStringList lst = mValue.toStringList();
-
- QList<QUrl> ret;
- for (QStringList::const_iterator it = lst.constBegin(); it != lst.constEnd(); ++it) {
- if (mArgType == ArgType_Path) {
- QUrl url = QUrl::fromUserInput(*it, QString(), QUrl::AssumeLocalFile);
- } else {
- ret << parseURL(mRealArgType, *it);
- }
- }
- return ret;
-}
-
-void QGpgMECryptoConfigEntry::resetToDefault()
-{
- mSet = false;
- mDirty = true;
- if (mFlags & GPGCONF_FLAG_DEFAULT) {
- mValue = mDefaultValue;
- } else if (mArgType == ArgType_None) {
- if (isList()) {
- mValue = 0U;
- } else {
- mValue = false;
- }
- }
-}
-
-void QGpgMECryptoConfigEntry::setBoolValue(bool b)
-{
- Q_ASSERT(mArgType == ArgType_None);
- Q_ASSERT(!isList());
- // A "no arg" option is either set or not set.
- // Being set means mSet==true + mValue==true, being unset means resetToDefault(), i.e. both false
- mValue = b;
- mSet = b;
- mDirty = true;
-}
-
-void QGpgMECryptoConfigEntry::setStringValue(const QString &str)
-{
- mValue = stringToValue(str, false);
- // When setting a string to empty (and there's no default), we need to act like resetToDefault
- // Otherwise we try e.g. "ocsp-responder:0:" and gpgconf answers:
- // "gpgconf: argument required for option ocsp-responder"
- if (str.isEmpty() && !isOptional()) {
- mSet = false;
- } else {
- mSet = true;
- }
- mDirty = true;
-}
-
-void QGpgMECryptoConfigEntry::setIntValue(int i)
-{
- Q_ASSERT(mArgType == ArgType_Int);
- Q_ASSERT(!isList());
- mValue = i;
- mSet = true;
- mDirty = true;
-}
-
-void QGpgMECryptoConfigEntry::setUIntValue(unsigned int i)
-{
- mValue = i;
- mSet = true;
- mDirty = true;
-}
-
-void QGpgMECryptoConfigEntry::setURLValue(const QUrl &url)
-{
- QString str = splitURL(mRealArgType, url);
- if (str.isEmpty() && !isOptional()) {
- mSet = false;
- } else {
- mSet = true;
- }
- mValue = str;
- mDirty = true;
-}
-
-void QGpgMECryptoConfigEntry::setNumberOfTimesSet(unsigned int i)
-{
- Q_ASSERT(mArgType == ArgType_None);
- Q_ASSERT(isList());
- mValue = i;
- mSet = i > 0;
- mDirty = true;
-}
-
-void QGpgMECryptoConfigEntry::setIntValueList(const std::vector<int> &lst)
-{
- QList<QVariant> ret;
- for (std::vector<int>::const_iterator it = lst.begin(); it != lst.end(); ++it) {
- ret << QVariant(*it);
- }
- mValue = ret;
- if (ret.isEmpty() && !isOptional()) {
- mSet = false;
- } else {
- mSet = true;
- }
- mDirty = true;
-}
-
-void QGpgMECryptoConfigEntry::setUIntValueList(const std::vector<unsigned int> &lst)
-{
- QList<QVariant> ret;
- for (std::vector<unsigned int>::const_iterator it = lst.begin(); it != lst.end(); ++it) {
- ret << QVariant(*it);
- }
- if (ret.isEmpty() && !isOptional()) {
- mSet = false;
- } else {
- mSet = true;
- }
- mValue = ret;
- mDirty = true;
-}
-
-void QGpgMECryptoConfigEntry::setURLValueList(const QList<QUrl> &urls)
-{
- QStringList lst;
- for (QList<QUrl>::const_iterator it = urls.constBegin(); it != urls.constEnd(); ++it) {
- lst << splitURL(mRealArgType, *it);
- }
- mValue = lst;
- if (lst.isEmpty() && !isOptional()) {
- mSet = false;
- } else {
- mSet = true;
- }
- mDirty = true;
-}
-
-QString QGpgMECryptoConfigEntry::toString(bool escape) const
-{
- // Basically the opposite of stringToValue
- if (isStringType()) {
- if (mValue.isNull()) {
- return QString();
- } else if (isList()) { // string list
- QStringList lst = mValue.toStringList();
- if (escape) {
- for (QStringList::iterator it = lst.begin(); it != lst.end(); ++it) {
- if (!(*it).isNull()) {
- *it = gpgconf_escape(*it).prepend(QLatin1String("\""));
- }
- }
- }
- const QString res = lst.join(QStringLiteral(","));
- //qCDebug(GPGPME_BACKEND_LOG) <<"toString:" << res;
- return res;
- } else { // normal string
- QString res = mValue.toString();
- if (escape) {
- res = gpgconf_escape(res).prepend(QLatin1String("\""));
- }
- return res;
- }
- }
- if (!isList()) { // non-list non-string
- if (mArgType == ArgType_None) {
- return mValue.toBool() ? QStringLiteral("1") : QString();
- } else { // some int
- Q_ASSERT(mArgType == ArgType_Int || mArgType == ArgType_UInt);
- return mValue.toString(); // int to string conversion
- }
- }
-
- // Lists (of other types than strings)
- if (mArgType == ArgType_None) {
- return QString::number(numberOfTimesSet());
- }
-
- QStringList ret;
- QList<QVariant> lst = mValue.toList();
- for (QList<QVariant>::const_iterator it = lst.constBegin(); it != lst.constEnd(); ++it) {
- ret << (*it).toString(); // QVariant does the conversion
- }
- return ret.join(QStringLiteral(","));
-}
-
-QString QGpgMECryptoConfigEntry::outputString() const
-{
- Q_ASSERT(mSet);
- return toString(true);
-}
-
-bool QGpgMECryptoConfigEntry::isStringType() const
-{
- return (mArgType == QGpgME::CryptoConfigEntry::ArgType_String
- || mArgType == QGpgME::CryptoConfigEntry::ArgType_Path
- || mArgType == QGpgME::CryptoConfigEntry::ArgType_LDAPURL);
-}
-
-void QGpgMECryptoConfigEntry::setDirty(bool b)
-{
- mDirty = b;
-}