Blame lang/qt/src/qgpgmenewcryptoconfig.cpp

Packit d7e8d0
/*
Packit d7e8d0
    qgpgmenewcryptoconfig.cpp
Packit d7e8d0
Packit d7e8d0
    This file is part of qgpgme, the Qt API binding for gpgme
Packit d7e8d0
    Copyright (c) 2010 Klarälvdalens Datakonsult AB
Packit d7e8d0
    Copyright (c) 2016 by Bundesamt für Sicherheit in der Informationstechnik
Packit d7e8d0
    Software engineering by Intevation GmbH
Packit d7e8d0
Packit d7e8d0
    QGpgME is free software; you can redistribute it and/or
Packit d7e8d0
    modify it under the terms of the GNU General Public License as
Packit d7e8d0
    published by the Free Software Foundation; either version 2 of the
Packit d7e8d0
    License, or (at your option) any later version.
Packit d7e8d0
Packit d7e8d0
    QGpgME is distributed in the hope that it will be useful,
Packit d7e8d0
    but WITHOUT ANY WARRANTY; without even the implied warranty of
Packit d7e8d0
    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
Packit d7e8d0
    General Public License for more details.
Packit d7e8d0
Packit d7e8d0
    You should have received a copy of the GNU General Public License
Packit d7e8d0
    along with this program; if not, write to the Free Software
Packit d7e8d0
    Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
Packit d7e8d0
Packit d7e8d0
    In addition, as a special exception, the copyright holders give
Packit d7e8d0
    permission to link the code of this program with any edition of
Packit d7e8d0
    the Qt library by Trolltech AS, Norway (or with modified versions
Packit d7e8d0
    of Qt that use the same license as Qt), and distribute linked
Packit d7e8d0
    combinations including the two.  You must obey the GNU General
Packit d7e8d0
    Public License in all respects for all of the code used other than
Packit d7e8d0
    Qt.  If you modify this file, you may extend this exception to
Packit d7e8d0
    your version of the file, but you are not obligated to do so.  If
Packit d7e8d0
    you do not wish to do so, delete this exception statement from
Packit d7e8d0
    your version.
Packit d7e8d0
*/
Packit d7e8d0
Packit d7e8d0
#ifdef HAVE_CONFIG_H
Packit d7e8d0
 #include "config.h"
Packit d7e8d0
#endif
Packit d7e8d0
Packit d7e8d0
#include "qgpgmenewcryptoconfig.h"
Packit d7e8d0
Packit d7e8d0
#include <QDebug>
Packit d7e8d0
#include "gpgme_backend_debug.h"
Packit d7e8d0
Packit d7e8d0
#include <QFile>
Packit d7e8d0
Packit d7e8d0
#include "global.h"
Packit d7e8d0
#include "error.h"
Packit d7e8d0
Packit d7e8d0
Packit d7e8d0
#include <sstream>
Packit d7e8d0
#include <string>
Packit d7e8d0
#include <functional>
Packit d7e8d0
#include <cassert>
Packit d7e8d0
#include <functional>
Packit d7e8d0
Packit d7e8d0
using namespace QGpgME;
Packit d7e8d0
using namespace GpgME;
Packit d7e8d0
using namespace GpgME::Configuration;
Packit d7e8d0
Packit d7e8d0
namespace
Packit d7e8d0
{
Packit d7e8d0
struct Select1St {
Packit d7e8d0
    template <typename U, typename V>
Packit d7e8d0
    const U &operator()(const std::pair<U, V> &p) const
Packit d7e8d0
    {
Packit d7e8d0
        return p.first;
Packit d7e8d0
    }
Packit d7e8d0
    template <typename U, typename V>
Packit d7e8d0
    const U &operator()(const QPair<U, V> &p) const
Packit d7e8d0
    {
Packit d7e8d0
        return p.first;
Packit d7e8d0
    }
Packit d7e8d0
};
Packit d7e8d0
}
Packit d7e8d0
Packit d7e8d0
// Just for the Q_ASSERT in the dtor. Not thread-safe, but who would
Packit d7e8d0
// have 2 threads talking to gpgconf anyway? :)
Packit d7e8d0
static bool s_duringClear = false;
Packit d7e8d0
Packit d7e8d0
QGpgMENewCryptoConfig::QGpgMENewCryptoConfig()
Packit d7e8d0
    :  m_parsed(false)
Packit d7e8d0
{
Packit d7e8d0
}
Packit d7e8d0
Packit d7e8d0
QGpgMENewCryptoConfig::~QGpgMENewCryptoConfig()
Packit d7e8d0
{
Packit d7e8d0
    clear();
Packit d7e8d0
}
Packit d7e8d0
Packit d7e8d0
void QGpgMENewCryptoConfig::reloadConfiguration(bool)
Packit d7e8d0
{
Packit d7e8d0
    clear();
Packit d7e8d0
Packit d7e8d0
    Error error;
Packit d7e8d0
    const std::vector<Component> components = Component::load(error);
Packit d7e8d0
#ifndef NDEBUG
Packit d7e8d0
    {
Packit d7e8d0
        std::stringstream ss;
Packit d7e8d0
        ss << "error: " << error
Packit d7e8d0
           << "components:\n";
Packit d7e8d0
        std::copy(components.begin(), components.end(),
Packit d7e8d0
                  std::ostream_iterator<Component>(ss, "\n"));
Packit d7e8d0
        qCDebug(GPGPME_BACKEND_LOG) << ss.str().c_str();
Packit d7e8d0
    }
Packit d7e8d0
#endif
Packit d7e8d0
#if 0
Packit d7e8d0
    TODO port?
Packit d7e8d0
    if (error && showErrors) {
Packit d7e8d0
        const QString wmsg = i18n("<qt>Failed to execute gpgconf:

%1

</qt>", QString::fromLocal8Bit(error.asString()));
Packit d7e8d0
        qCWarning(GPGPME_BACKEND_LOG) << wmsg; // to see it from test_cryptoconfig.cpp
Packit d7e8d0
        KMessageBox::error(0, wmsg);
Packit d7e8d0
    }
Packit d7e8d0
#endif
Packit d7e8d0
    Q_FOREACH(const Component & c, components) {
Packit d7e8d0
        const std::shared_ptr<QGpgMENewCryptoConfigComponent> comp(new QGpgMENewCryptoConfigComponent);
Packit d7e8d0
        comp->setComponent(c);
Packit d7e8d0
        m_componentsByName[ comp->name() ] = comp;
Packit d7e8d0
    }
Packit d7e8d0
    m_parsed = true;
Packit d7e8d0
}
Packit d7e8d0
Packit d7e8d0
QStringList QGpgMENewCryptoConfig::componentList() const
Packit d7e8d0
{
Packit d7e8d0
    if (!m_parsed) {
Packit d7e8d0
        const_cast<QGpgMENewCryptoConfig *>(this)->reloadConfiguration(true);
Packit d7e8d0
    }
Packit d7e8d0
    QStringList result;
Packit d7e8d0
    std::transform(m_componentsByName.begin(), m_componentsByName.end(),
Packit d7e8d0
                   std::back_inserter(result),
Packit d7e8d0
                   mem_fn(&QGpgMENewCryptoConfigComponent::name));
Packit d7e8d0
    return result;
Packit d7e8d0
}
Packit d7e8d0
Packit d7e8d0
QGpgMENewCryptoConfigComponent *QGpgMENewCryptoConfig::component(const QString &name) const
Packit d7e8d0
{
Packit d7e8d0
    if (!m_parsed) {
Packit d7e8d0
        const_cast<QGpgMENewCryptoConfig *>(this)->reloadConfiguration(false);
Packit d7e8d0
    }
Packit d7e8d0
    return m_componentsByName.value(name).get();
Packit d7e8d0
}
Packit d7e8d0
Packit d7e8d0
void QGpgMENewCryptoConfig::sync(bool runtime)
Packit d7e8d0
{
Packit d7e8d0
    Q_FOREACH(const std::shared_ptr<QGpgMENewCryptoConfigComponent> &c, m_componentsByName)
Packit d7e8d0
    c->sync(runtime);
Packit d7e8d0
}
Packit d7e8d0
Packit d7e8d0
void QGpgMENewCryptoConfig::clear()
Packit d7e8d0
{
Packit d7e8d0
    s_duringClear = true;
Packit d7e8d0
    m_componentsByName.clear();
Packit d7e8d0
    s_duringClear = false;
Packit d7e8d0
    m_parsed = false; // next call to componentList/component will need to run gpgconf again
Packit d7e8d0
}
Packit d7e8d0
Packit d7e8d0
////
Packit d7e8d0
Packit d7e8d0
QGpgMENewCryptoConfigComponent::QGpgMENewCryptoConfigComponent()
Packit d7e8d0
    : CryptoConfigComponent(),
Packit d7e8d0
      m_component()
Packit d7e8d0
{
Packit d7e8d0
Packit d7e8d0
}
Packit d7e8d0
Packit d7e8d0
void QGpgMENewCryptoConfigComponent::setComponent(const Component &component)
Packit d7e8d0
{
Packit d7e8d0
    m_component = component;
Packit d7e8d0
    m_groupsByName.clear();
Packit d7e8d0
Packit d7e8d0
    std::shared_ptr<QGpgMENewCryptoConfigGroup> group;
Packit d7e8d0
Packit d7e8d0
    const std::vector<Option> options = m_component.options();
Packit d7e8d0
    Q_FOREACH(const Option & o, options)
Packit d7e8d0
    if (o.flags() & Group) {
Packit d7e8d0
        if (group) {
Packit d7e8d0
            m_groupsByName[group->name()] = group;
Packit d7e8d0
        }
Packit d7e8d0
        group.reset(new QGpgMENewCryptoConfigGroup(shared_from_this(), o));
Packit d7e8d0
    } else if (group) {
Packit d7e8d0
        const std::shared_ptr<QGpgMENewCryptoConfigEntry> entry(new QGpgMENewCryptoConfigEntry(group, o));
Packit d7e8d0
        const QString name = entry->name();
Packit d7e8d0
        group->m_entryNames.push_back(name);
Packit d7e8d0
        group->m_entriesByName[name] = entry;
Packit d7e8d0
    } else {
Packit d7e8d0
        qCWarning(GPGPME_BACKEND_LOG) << "found no group for entry" << o.name() << "of component" << name();
Packit d7e8d0
    }
Packit d7e8d0
    if (group) {
Packit d7e8d0
        m_groupsByName[group->name()] = group;
Packit d7e8d0
    }
Packit d7e8d0
Packit d7e8d0
}
Packit d7e8d0
Packit d7e8d0
QGpgMENewCryptoConfigComponent::~QGpgMENewCryptoConfigComponent() {}
Packit d7e8d0
Packit d7e8d0
QString QGpgMENewCryptoConfigComponent::name() const
Packit d7e8d0
{
Packit d7e8d0
    return QString::fromUtf8(m_component.name());
Packit d7e8d0
}
Packit d7e8d0
Packit d7e8d0
QString QGpgMENewCryptoConfigComponent::description() const
Packit d7e8d0
{
Packit d7e8d0
    return QString::fromUtf8(m_component.description());
Packit d7e8d0
}
Packit d7e8d0
Packit d7e8d0
QStringList QGpgMENewCryptoConfigComponent::groupList() const
Packit d7e8d0
{
Packit d7e8d0
    QStringList result;
Packit d7e8d0
    result.reserve(m_groupsByName.size());
Packit d7e8d0
    std::transform(m_groupsByName.begin(), m_groupsByName.end(),
Packit d7e8d0
                   std::back_inserter(result),
Packit d7e8d0
                   std::mem_fn(&QGpgMENewCryptoConfigGroup::name));
Packit d7e8d0
    return result;
Packit d7e8d0
}
Packit d7e8d0
Packit d7e8d0
QGpgMENewCryptoConfigGroup *QGpgMENewCryptoConfigComponent::group(const QString &name) const
Packit d7e8d0
{
Packit d7e8d0
    return m_groupsByName.value(name).get();
Packit d7e8d0
}
Packit d7e8d0
Packit d7e8d0
void QGpgMENewCryptoConfigComponent::sync(bool runtime)
Packit d7e8d0
{
Packit d7e8d0
    Q_UNUSED(runtime) // runtime is always set by engine_gpgconf
Packit d7e8d0
    if (const Error err = m_component.save()) {
Packit d7e8d0
        qCWarning(GPGPME_BACKEND_LOG) << ":"
Packit d7e8d0
            << "Error from gpgconf while saving configuration: %1"
Packit d7e8d0
            << QString::fromLocal8Bit(err.asString());
Packit d7e8d0
    }
Packit d7e8d0
}
Packit d7e8d0
Packit d7e8d0
////
Packit d7e8d0
Packit d7e8d0
QGpgMENewCryptoConfigGroup::QGpgMENewCryptoConfigGroup(const std::shared_ptr<QGpgMENewCryptoConfigComponent> &comp, const Option &option)
Packit d7e8d0
    : CryptoConfigGroup(),
Packit d7e8d0
      m_component(comp),
Packit d7e8d0
      m_option(option)
Packit d7e8d0
{
Packit d7e8d0
}
Packit d7e8d0
Packit d7e8d0
QGpgMENewCryptoConfigGroup::~QGpgMENewCryptoConfigGroup() {}
Packit d7e8d0
Packit d7e8d0
QString QGpgMENewCryptoConfigGroup::name() const
Packit d7e8d0
{
Packit d7e8d0
    return QString::fromUtf8(m_option.name());
Packit d7e8d0
}
Packit d7e8d0
Packit d7e8d0
QString QGpgMENewCryptoConfigGroup::description() const
Packit d7e8d0
{
Packit d7e8d0
    return QString::fromUtf8(m_option.description());
Packit d7e8d0
}
Packit d7e8d0
Packit d7e8d0
QString QGpgMENewCryptoConfigGroup::path() const
Packit d7e8d0
{
Packit d7e8d0
    if (const std::shared_ptr<QGpgMENewCryptoConfigComponent> c = m_component.lock()) {
Packit d7e8d0
        return c->name() + QLatin1Char('/') + name();
Packit d7e8d0
    } else {
Packit d7e8d0
        return QString();
Packit d7e8d0
    }
Packit d7e8d0
}
Packit d7e8d0
Packit d7e8d0
CryptoConfigEntry::Level QGpgMENewCryptoConfigGroup::level() const
Packit d7e8d0
{
Packit d7e8d0
    // two casts to make SunCC happy:
Packit d7e8d0
    return static_cast<CryptoConfigEntry::Level>(static_cast<unsigned int>(m_option.level()));
Packit d7e8d0
}
Packit d7e8d0
Packit d7e8d0
QStringList QGpgMENewCryptoConfigGroup::entryList() const
Packit d7e8d0
{
Packit d7e8d0
    return m_entryNames;
Packit d7e8d0
}
Packit d7e8d0
Packit d7e8d0
QGpgMENewCryptoConfigEntry *QGpgMENewCryptoConfigGroup::entry(const QString &name) const
Packit d7e8d0
{
Packit d7e8d0
    return m_entriesByName.value(name).get();
Packit d7e8d0
}
Packit d7e8d0
Packit d7e8d0
static QString urlpart_encode(const QString &str)
Packit d7e8d0
{
Packit d7e8d0
    QString enc(str);
Packit d7e8d0
    enc.replace(QLatin1Char('%'), QStringLiteral("%25"));   // first!
Packit d7e8d0
    enc.replace(QLatin1Char(':'), QStringLiteral("%3a"));
Packit d7e8d0
    //qCDebug(GPGPME_BACKEND_LOG) <<"  urlpart_encode:" << str <<" ->" << enc;
Packit d7e8d0
    return enc;
Packit d7e8d0
}
Packit d7e8d0
Packit d7e8d0
static QString urlpart_decode(const QString &str)
Packit d7e8d0
{
Packit d7e8d0
    return QUrl::fromPercentEncoding(str.toLatin1());
Packit d7e8d0
}
Packit d7e8d0
Packit d7e8d0
// gpgconf arg type number -> NewCryptoConfigEntry arg type enum mapping
Packit d7e8d0
static QGpgME::CryptoConfigEntry::ArgType knownArgType(int argType, bool &ok)
Packit d7e8d0
{
Packit d7e8d0
    ok = true;
Packit d7e8d0
    switch (argType) {
Packit d7e8d0
    case 0: // none
Packit d7e8d0
        return QGpgME::CryptoConfigEntry::ArgType_None;
Packit d7e8d0
    case 1: // string
Packit d7e8d0
        return QGpgME::CryptoConfigEntry::ArgType_String;
Packit d7e8d0
    case 2: // int32
Packit d7e8d0
        return QGpgME::CryptoConfigEntry::ArgType_Int;
Packit d7e8d0
    case 3: // uint32
Packit d7e8d0
        return QGpgME::CryptoConfigEntry::ArgType_UInt;
Packit d7e8d0
    case 32: // pathname
Packit d7e8d0
        return QGpgME::CryptoConfigEntry::ArgType_Path;
Packit d7e8d0
    case 33: // ldap server
Packit d7e8d0
        return QGpgME::CryptoConfigEntry::ArgType_LDAPURL;
Packit d7e8d0
    default:
Packit d7e8d0
        ok = false;
Packit d7e8d0
        return QGpgME::CryptoConfigEntry::ArgType_None;
Packit d7e8d0
    }
Packit d7e8d0
}
Packit d7e8d0
Packit d7e8d0
QGpgMENewCryptoConfigEntry::QGpgMENewCryptoConfigEntry(const std::shared_ptr<QGpgMENewCryptoConfigGroup> &group, const Option &option)
Packit d7e8d0
    : m_group(group), m_option(option)
Packit d7e8d0
{
Packit d7e8d0
}
Packit d7e8d0
Packit d7e8d0
#if 0
Packit d7e8d0
QVariant QGpgMENewCryptoConfigEntry::stringToValue(const QString &str, bool unescape) const
Packit d7e8d0
{
Packit d7e8d0
    const bool isString = isStringType();
Packit d7e8d0
Packit d7e8d0
    if (isList()) {
Packit d7e8d0
        if (argType() == ArgType_None) {
Packit d7e8d0
            bool ok = true;
Packit d7e8d0
            const QVariant v = str.isEmpty() ? 0U : str.toUInt(&ok;;
Packit d7e8d0
            if (!ok) {
Packit d7e8d0
                qCWarning(GPGPME_BACKEND_LOG) << "list-of-none should have an unsigned int as value:" << str;
Packit d7e8d0
            }
Packit d7e8d0
            return v;
Packit d7e8d0
        }
Packit d7e8d0
        QList<QVariant> lst;
Packit d7e8d0
        QStringList items = str.split(',', QString::SkipEmptyParts);
Packit d7e8d0
        for (QStringList::const_iterator valit = items.constBegin(); valit != items.constEnd(); ++valit) {
Packit d7e8d0
            QString val = *valit;
Packit d7e8d0
            if (isString) {
Packit d7e8d0
                if (val.isEmpty()) {
Packit d7e8d0
                    lst << QVariant(QString());
Packit d7e8d0
                    continue;
Packit d7e8d0
                } else if (unescape) {
Packit d7e8d0
                    if (val[0] != '"') { // see README.gpgconf
Packit d7e8d0
                        qCWarning(GPGPME_BACKEND_LOG) << "String value should start with '\"' :" << val;
Packit d7e8d0
                    }
Packit d7e8d0
                    val = val.mid(1);
Packit d7e8d0
                }
Packit d7e8d0
            }
Packit d7e8d0
            lst << QVariant(unescape ? gpgconf_unescape(val) : val);
Packit d7e8d0
        }
Packit d7e8d0
        return lst;
Packit d7e8d0
    } else { // not a list
Packit d7e8d0
        QString val(str);
Packit d7e8d0
        if (isString) {
Packit d7e8d0
            if (val.isEmpty()) {
Packit d7e8d0
                return QVariant(QString());    // not set  [ok with lists too?]
Packit d7e8d0
            } else if (unescape) {
Packit d7e8d0
                if (val[0] != '"') { // see README.gpgconf
Packit d7e8d0
                    qCWarning(GPGPME_BACKEND_LOG) << "String value should start with '\"' :" << val;
Packit d7e8d0
                }
Packit d7e8d0
                val = val.mid(1);
Packit d7e8d0
            }
Packit d7e8d0
        }
Packit d7e8d0
        return QVariant(unescape ? gpgconf_unescape(val) : val);
Packit d7e8d0
    }
Packit d7e8d0
}
Packit d7e8d0
#endif
Packit d7e8d0
Packit d7e8d0
QGpgMENewCryptoConfigEntry::~QGpgMENewCryptoConfigEntry()
Packit d7e8d0
{
Packit d7e8d0
#ifndef NDEBUG
Packit d7e8d0
    if (!s_duringClear && m_option.dirty())
Packit d7e8d0
        qCWarning(GPGPME_BACKEND_LOG) << "Deleting a QGpgMENewCryptoConfigEntry that was modified (" << m_option.description() << ")"
Packit d7e8d0
                                      << "You forgot to call sync() (to commit) or clear() (to discard)";
Packit d7e8d0
#endif
Packit d7e8d0
}
Packit d7e8d0
Packit d7e8d0
QString QGpgMENewCryptoConfigEntry::name() const
Packit d7e8d0
{
Packit d7e8d0
    return QString::fromUtf8(m_option.name());
Packit d7e8d0
}
Packit d7e8d0
Packit d7e8d0
QString QGpgMENewCryptoConfigEntry::description() const
Packit d7e8d0
{
Packit d7e8d0
    return QString::fromUtf8(m_option.description());
Packit d7e8d0
}
Packit d7e8d0
Packit d7e8d0
QString QGpgMENewCryptoConfigEntry::path() const
Packit d7e8d0
{
Packit d7e8d0
    if (const std::shared_ptr<QGpgMENewCryptoConfigGroup> g = m_group.lock()) {
Packit d7e8d0
        return g->path() + QLatin1Char('/') + name();
Packit d7e8d0
    } else {
Packit d7e8d0
        return QString();
Packit d7e8d0
    }
Packit d7e8d0
}
Packit d7e8d0
Packit d7e8d0
bool QGpgMENewCryptoConfigEntry::isOptional() const
Packit d7e8d0
{
Packit d7e8d0
    return m_option.flags() & Optional;
Packit d7e8d0
}
Packit d7e8d0
Packit d7e8d0
bool QGpgMENewCryptoConfigEntry::isReadOnly() const
Packit d7e8d0
{
Packit d7e8d0
    return m_option.flags() & NoChange;
Packit d7e8d0
}
Packit d7e8d0
Packit d7e8d0
bool QGpgMENewCryptoConfigEntry::isList() const
Packit d7e8d0
{
Packit d7e8d0
    return m_option.flags() & List;
Packit d7e8d0
}
Packit d7e8d0
Packit d7e8d0
bool QGpgMENewCryptoConfigEntry::isRuntime() const
Packit d7e8d0
{
Packit d7e8d0
    return m_option.flags() & Runtime;
Packit d7e8d0
}
Packit d7e8d0
Packit d7e8d0
CryptoConfigEntry::Level QGpgMENewCryptoConfigEntry::level() const
Packit d7e8d0
{
Packit d7e8d0
    // two casts to make SunCC happy:
Packit d7e8d0
    return static_cast<Level>(static_cast<unsigned int>(m_option.level()));
Packit d7e8d0
}
Packit d7e8d0
Packit d7e8d0
CryptoConfigEntry::ArgType QGpgMENewCryptoConfigEntry::argType() const
Packit d7e8d0
{
Packit d7e8d0
    bool ok = false;
Packit d7e8d0
    const ArgType type = knownArgType(m_option.type(), ok);
Packit d7e8d0
    if (ok) {
Packit d7e8d0
        return type;
Packit d7e8d0
    } else {
Packit d7e8d0
        return knownArgType(m_option.alternateType(), ok);
Packit d7e8d0
    }
Packit d7e8d0
}
Packit d7e8d0
Packit d7e8d0
bool QGpgMENewCryptoConfigEntry::isSet() const
Packit d7e8d0
{
Packit d7e8d0
    return m_option.set();
Packit d7e8d0
}
Packit d7e8d0
Packit d7e8d0
bool QGpgMENewCryptoConfigEntry::boolValue() const
Packit d7e8d0
{
Packit d7e8d0
    Q_ASSERT(m_option.alternateType() == NoType);
Packit d7e8d0
    Q_ASSERT(!isList());
Packit d7e8d0
    return m_option.currentValue().boolValue();
Packit d7e8d0
}
Packit d7e8d0
Packit d7e8d0
QString QGpgMENewCryptoConfigEntry::stringValue() const
Packit d7e8d0
{
Packit d7e8d0
    //return toString( false );
Packit d7e8d0
    Q_ASSERT(m_option.alternateType() == StringType);
Packit d7e8d0
    Q_ASSERT(!isList());
Packit d7e8d0
    return QString::fromUtf8(m_option.currentValue().stringValue());
Packit d7e8d0
}
Packit d7e8d0
Packit d7e8d0
int QGpgMENewCryptoConfigEntry::intValue() const
Packit d7e8d0
{
Packit d7e8d0
    Q_ASSERT(m_option.alternateType() == IntegerType);
Packit d7e8d0
    Q_ASSERT(!isList());
Packit d7e8d0
    return m_option.currentValue().intValue();
Packit d7e8d0
}
Packit d7e8d0
Packit d7e8d0
unsigned int QGpgMENewCryptoConfigEntry::uintValue() const
Packit d7e8d0
{
Packit d7e8d0
    Q_ASSERT(m_option.alternateType() == UnsignedIntegerType);
Packit d7e8d0
    Q_ASSERT(!isList());
Packit d7e8d0
    return m_option.currentValue().uintValue();
Packit d7e8d0
}
Packit d7e8d0
Packit d7e8d0
static QUrl parseURL(int mRealArgType, const QString &str)
Packit d7e8d0
{
Packit d7e8d0
    if (mRealArgType == 33) {   // LDAP server
Packit d7e8d0
        // The format is HOSTNAME:PORT:USERNAME:PASSWORD:BASE_DN
Packit d7e8d0
        QStringList items = str.split(QLatin1Char(':'));
Packit d7e8d0
        if (items.count() == 5) {
Packit d7e8d0
            QStringList::const_iterator it = items.constBegin();
Packit d7e8d0
            QUrl url;
Packit d7e8d0
            url.setScheme(QStringLiteral("ldap"));
Packit d7e8d0
            url.setHost(urlpart_decode(*it++));
Packit d7e8d0
Packit d7e8d0
            bool ok;
Packit d7e8d0
            const int port = (*it++).toInt(&ok;;
Packit d7e8d0
            if (ok) {
Packit d7e8d0
                url.setPort(port);
Packit d7e8d0
            } else if (!it->isEmpty()) {
Packit d7e8d0
                qCWarning(GPGPME_BACKEND_LOG) << "parseURL: malformed LDAP server port, ignoring: \"" << *it << "\"";
Packit d7e8d0
            }
Packit d7e8d0
Packit d7e8d0
            const QString userName = urlpart_decode(*it++);
Packit d7e8d0
            if (!userName.isEmpty()) {
Packit d7e8d0
                url.setUserName(userName);
Packit d7e8d0
            }
Packit d7e8d0
            const QString passWord = urlpart_decode(*it++);
Packit d7e8d0
            if (!passWord.isEmpty()) {
Packit d7e8d0
                url.setPassword(passWord);
Packit d7e8d0
            }
Packit d7e8d0
            url.setQuery(urlpart_decode(*it));
Packit d7e8d0
            return url;
Packit d7e8d0
        } else {
Packit d7e8d0
            qCWarning(GPGPME_BACKEND_LOG) << "parseURL: malformed LDAP server:" << str;
Packit d7e8d0
        }
Packit d7e8d0
    }
Packit d7e8d0
    // other URLs : assume wellformed URL syntax.
Packit d7e8d0
    return QUrl(str);
Packit d7e8d0
}
Packit d7e8d0
Packit d7e8d0
// The opposite of parseURL
Packit d7e8d0
static QString splitURL(int mRealArgType, const QUrl &url)
Packit d7e8d0
{
Packit d7e8d0
    if (mRealArgType == 33) {   // LDAP server
Packit d7e8d0
        // The format is HOSTNAME:PORT:USERNAME:PASSWORD:BASE_DN
Packit d7e8d0
        Q_ASSERT(url.scheme() == QLatin1String("ldap"));
Packit d7e8d0
        return urlpart_encode(url.host()) + QLatin1Char(':') +
Packit d7e8d0
               (url.port() != -1 ? QString::number(url.port()) : QString()) + QLatin1Char(':') +     // -1 is used for default ports, omit
Packit d7e8d0
               urlpart_encode(url.userName()) + QLatin1Char(':') +
Packit d7e8d0
               urlpart_encode(url.password()) + QLatin1Char(':') +
Packit d7e8d0
               urlpart_encode(url.query());
Packit d7e8d0
    }
Packit d7e8d0
    return url.path();
Packit d7e8d0
}
Packit d7e8d0
Packit d7e8d0
QUrl QGpgMENewCryptoConfigEntry::urlValue() const
Packit d7e8d0
{
Packit d7e8d0
    const Type type = m_option.type();
Packit d7e8d0
    Q_ASSERT(type == FilenameType || type == LdapServerType);
Packit d7e8d0
    Q_ASSERT(!isList());
Packit d7e8d0
    if (type == FilenameType) {
Packit d7e8d0
        QUrl url;
Packit d7e8d0
        url.setPath(QFile::decodeName(m_option.currentValue().stringValue()));
Packit d7e8d0
        return url;
Packit d7e8d0
    }
Packit d7e8d0
    return parseURL(type, stringValue());
Packit d7e8d0
}
Packit d7e8d0
Packit d7e8d0
unsigned int QGpgMENewCryptoConfigEntry::numberOfTimesSet() const
Packit d7e8d0
{
Packit d7e8d0
    Q_ASSERT(m_option.alternateType() == NoType);
Packit d7e8d0
    Q_ASSERT(isList());
Packit d7e8d0
    return m_option.currentValue().uintValue();
Packit d7e8d0
}
Packit d7e8d0
Packit d7e8d0
std::vector<int> QGpgMENewCryptoConfigEntry::intValueList() const
Packit d7e8d0
{
Packit d7e8d0
    Q_ASSERT(m_option.alternateType() == IntegerType);
Packit d7e8d0
    Q_ASSERT(isList());
Packit d7e8d0
    return m_option.currentValue().intValues();
Packit d7e8d0
}
Packit d7e8d0
Packit d7e8d0
std::vector<unsigned int> QGpgMENewCryptoConfigEntry::uintValueList() const
Packit d7e8d0
{
Packit d7e8d0
    Q_ASSERT(m_option.alternateType() == UnsignedIntegerType);
Packit d7e8d0
    Q_ASSERT(isList());
Packit d7e8d0
    return m_option.currentValue().uintValues();
Packit d7e8d0
}
Packit d7e8d0
Packit d7e8d0
QStringList QGpgMENewCryptoConfigEntry::stringValueList() const
Packit d7e8d0
{
Packit d7e8d0
    Q_ASSERT(isList());
Packit d7e8d0
    const Argument arg = m_option.currentValue();
Packit d7e8d0
    const std::vector<const char *> values = arg.stringValues();
Packit d7e8d0
    QStringList ret;
Packit d7e8d0
    for(const char *value: values) {
Packit d7e8d0
        ret << QString::fromUtf8(value);
Packit d7e8d0
    }
Packit d7e8d0
    return ret;
Packit d7e8d0
}
Packit d7e8d0
Packit d7e8d0
QList<QUrl> QGpgMENewCryptoConfigEntry::urlValueList() const
Packit d7e8d0
{
Packit d7e8d0
    const Type type = m_option.type();
Packit d7e8d0
    Q_ASSERT(type == FilenameType || type == LdapServerType);
Packit d7e8d0
    Q_ASSERT(isList());
Packit d7e8d0
    const Argument arg = m_option.currentValue();
Packit d7e8d0
    const std::vector<const char *> values = arg.stringValues();
Packit d7e8d0
    QList<QUrl> ret;
Packit d7e8d0
    Q_FOREACH(const char *value, values)
Packit d7e8d0
    if (type == FilenameType) {
Packit d7e8d0
        QUrl url;
Packit d7e8d0
        url.setPath(QFile::decodeName(value));
Packit d7e8d0
        ret << url;
Packit d7e8d0
    } else {
Packit d7e8d0
        ret << parseURL(type, QString::fromUtf8(value));
Packit d7e8d0
    }
Packit d7e8d0
    return ret;
Packit d7e8d0
}
Packit d7e8d0
Packit d7e8d0
void QGpgMENewCryptoConfigEntry::resetToDefault()
Packit d7e8d0
{
Packit d7e8d0
    m_option.resetToDefaultValue();
Packit d7e8d0
}
Packit d7e8d0
Packit d7e8d0
void QGpgMENewCryptoConfigEntry::setBoolValue(bool b)
Packit d7e8d0
{
Packit d7e8d0
    Q_ASSERT(m_option.alternateType() == NoType);
Packit d7e8d0
    Q_ASSERT(!isList());
Packit d7e8d0
    // A "no arg" option is either set or not set.
Packit d7e8d0
    // Being set means createNoneArgument(), being unset means resetToDefault()
Packit d7e8d0
    m_option.setNewValue(m_option.createNoneArgument(b));
Packit d7e8d0
}
Packit d7e8d0
Packit d7e8d0
void QGpgMENewCryptoConfigEntry::setStringValue(const QString &str)
Packit d7e8d0
{
Packit d7e8d0
    Q_ASSERT(m_option.alternateType() == StringType);
Packit d7e8d0
    Q_ASSERT(!isList());
Packit d7e8d0
    const Type type = m_option.type();
Packit d7e8d0
    // When setting a string to empty (and there's no default), we need to act like resetToDefault
Packit d7e8d0
    // Otherwise we try e.g. "ocsp-responder:0:" and gpgconf answers:
Packit d7e8d0
    // "gpgconf: argument required for option ocsp-responder"
Packit d7e8d0
    if (str.isEmpty() && !isOptional()) {
Packit d7e8d0
        m_option.resetToDefaultValue();
Packit d7e8d0
    } else if (type == FilenameType) {
Packit d7e8d0
        m_option.setNewValue(m_option.createStringArgument(QFile::encodeName(str).constData()));
Packit d7e8d0
    } else {
Packit d7e8d0
        m_option.setNewValue(m_option.createStringArgument(str.toUtf8().constData()));
Packit d7e8d0
    }
Packit d7e8d0
}
Packit d7e8d0
Packit d7e8d0
void QGpgMENewCryptoConfigEntry::setIntValue(int i)
Packit d7e8d0
{
Packit d7e8d0
    Q_ASSERT(m_option.alternateType() == IntegerType);
Packit d7e8d0
    Q_ASSERT(!isList());
Packit d7e8d0
    m_option.setNewValue(m_option.createIntArgument(i));
Packit d7e8d0
}
Packit d7e8d0
Packit d7e8d0
void QGpgMENewCryptoConfigEntry::setUIntValue(unsigned int i)
Packit d7e8d0
{
Packit d7e8d0
    Q_ASSERT(m_option.alternateType() == UnsignedIntegerType);
Packit d7e8d0
    Q_ASSERT(!isList());
Packit d7e8d0
    m_option.setNewValue(m_option.createUIntArgument(i));
Packit d7e8d0
}
Packit d7e8d0
Packit d7e8d0
void QGpgMENewCryptoConfigEntry::setURLValue(const QUrl &url)
Packit d7e8d0
{
Packit d7e8d0
    const Type type = m_option.type();
Packit d7e8d0
    Q_ASSERT(type == FilenameType || type == LdapServerType);
Packit d7e8d0
    Q_ASSERT(!isList());
Packit d7e8d0
    const QString str = splitURL(type, url);
Packit d7e8d0
    // cf. setStringValue()
Packit d7e8d0
    if (str.isEmpty() && !isOptional()) {
Packit d7e8d0
        m_option.resetToDefaultValue();
Packit d7e8d0
    } else if (type == FilenameType) {
Packit d7e8d0
        m_option.setNewValue(m_option.createStringArgument(QFile::encodeName(str).constData()));
Packit d7e8d0
    } else {
Packit d7e8d0
        m_option.setNewValue(m_option.createStringArgument(str.toUtf8().constData()));
Packit d7e8d0
    }
Packit d7e8d0
}
Packit d7e8d0
Packit d7e8d0
void QGpgMENewCryptoConfigEntry::setNumberOfTimesSet(unsigned int i)
Packit d7e8d0
{
Packit d7e8d0
    Q_ASSERT(m_option.alternateType() == NoType);
Packit d7e8d0
    Q_ASSERT(isList());
Packit d7e8d0
    m_option.setNewValue(m_option.createNoneListArgument(i));
Packit d7e8d0
}
Packit d7e8d0
Packit d7e8d0
void QGpgMENewCryptoConfigEntry::setIntValueList(const std::vector<int> &lst)
Packit d7e8d0
{
Packit d7e8d0
    Q_ASSERT(m_option.alternateType() == IntegerType);
Packit d7e8d0
    Q_ASSERT(isList());
Packit d7e8d0
    m_option.setNewValue(m_option.createIntListArgument(lst));
Packit d7e8d0
}
Packit d7e8d0
Packit d7e8d0
void QGpgMENewCryptoConfigEntry::setUIntValueList(const std::vector<unsigned int> &lst)
Packit d7e8d0
{
Packit d7e8d0
    Q_ASSERT(m_option.alternateType() == UnsignedIntegerType);
Packit d7e8d0
    Q_ASSERT(isList());
Packit d7e8d0
    m_option.setNewValue(m_option.createUIntListArgument(lst));
Packit d7e8d0
}
Packit d7e8d0
Packit d7e8d0
void QGpgMENewCryptoConfigEntry::setURLValueList(const QList<QUrl> &urls)
Packit d7e8d0
{
Packit d7e8d0
    const Type type = m_option.type();
Packit d7e8d0
    Q_ASSERT(m_option.alternateType() == StringType);
Packit d7e8d0
    Q_ASSERT(isList());
Packit d7e8d0
    std::vector<std::string> values;
Packit d7e8d0
    values.reserve(urls.size());
Packit d7e8d0
    Q_FOREACH (const QUrl &url, urls)
Packit d7e8d0
        if (type == FilenameType) {
Packit d7e8d0
            values.push_back(QFile::encodeName(url.path()).constData());
Packit d7e8d0
        } else {
Packit d7e8d0
            values.push_back(splitURL(type, url).toUtf8().constData());
Packit d7e8d0
        }
Packit d7e8d0
    m_option.setNewValue(m_option.createStringListArgument(values));
Packit d7e8d0
}
Packit d7e8d0
Packit d7e8d0
bool QGpgMENewCryptoConfigEntry::isDirty() const
Packit d7e8d0
{
Packit d7e8d0
    return m_option.dirty();
Packit d7e8d0
}
Packit d7e8d0
Packit d7e8d0
#if 0
Packit d7e8d0
QString QGpgMENewCryptoConfigEntry::toString(bool escape) const
Packit d7e8d0
{
Packit d7e8d0
    // Basically the opposite of stringToValue
Packit d7e8d0
    if (isStringType()) {
Packit d7e8d0
        if (mValue.isNull()) {
Packit d7e8d0
            return QString();
Packit d7e8d0
        } else if (isList()) { // string list
Packit d7e8d0
            QStringList lst = mValue.toStringList();
Packit d7e8d0
            if (escape) {
Packit d7e8d0
                for (QStringList::iterator it = lst.begin(); it != lst.end(); ++it) {
Packit d7e8d0
                    if (!(*it).isNull()) {
Packit d7e8d0
                        *it = gpgconf_escape(*it).prepend("\"");
Packit d7e8d0
                    }
Packit d7e8d0
                }
Packit d7e8d0
            }
Packit d7e8d0
            QString res = lst.join(",");
Packit d7e8d0
            //qCDebug(GPGPME_BACKEND_LOG) <<"toString:" << res;
Packit d7e8d0
            return res;
Packit d7e8d0
        } else { // normal string
Packit d7e8d0
            QString res = mValue.toString();
Packit d7e8d0
            if (escape) {
Packit d7e8d0
                res = gpgconf_escape(res).prepend("\"");
Packit d7e8d0
            }
Packit d7e8d0
            return res;
Packit d7e8d0
        }
Packit d7e8d0
    }
Packit d7e8d0
    if (!isList()) { // non-list non-string
Packit d7e8d0
        if (mArgType == ArgType_None) {
Packit d7e8d0
            return mValue.toBool() ? QString::fromLatin1("1") : QString();
Packit d7e8d0
        } else { // some int
Packit d7e8d0
            Q_ASSERT(mArgType == ArgType_Int || mArgType == ArgType_UInt);
Packit d7e8d0
            return mValue.toString(); // int to string conversion
Packit d7e8d0
        }
Packit d7e8d0
    }
Packit d7e8d0
Packit d7e8d0
    // Lists (of other types than strings)
Packit d7e8d0
    if (mArgType == ArgType_None) {
Packit d7e8d0
        return QString::number(numberOfTimesSet());
Packit d7e8d0
    }
Packit d7e8d0
    QStringList ret;
Packit d7e8d0
    QList<QVariant> lst = mValue.toList();
Packit d7e8d0
    for (QList<QVariant>::const_iterator it = lst.constBegin(); it != lst.constEnd(); ++it) {
Packit d7e8d0
        ret << (*it).toString(); // QVariant does the conversion
Packit d7e8d0
    }
Packit d7e8d0
    return ret.join(",");
Packit d7e8d0
}
Packit d7e8d0
Packit d7e8d0
QString QGpgMENewCryptoConfigEntry::outputString() const
Packit d7e8d0
{
Packit d7e8d0
    Q_ASSERT(mSet);
Packit d7e8d0
    return toString(true);
Packit d7e8d0
}
Packit d7e8d0
Packit d7e8d0
bool QGpgMENewCryptoConfigEntry::isStringType() const
Packit d7e8d0
{
Packit d7e8d0
    return (mArgType == QGpgME::NewCryptoConfigEntry::ArgType_String
Packit d7e8d0
            || mArgType == QGpgME::NewCryptoConfigEntry::ArgType_Path
Packit d7e8d0
            || mArgType == QGpgME::NewCryptoConfigEntry::ArgType_URL
Packit d7e8d0
            || mArgType == QGpgME::NewCryptoConfigEntry::ArgType_LDAPURL);
Packit d7e8d0
}
Packit d7e8d0
Packit d7e8d0
void QGpgMENewCryptoConfigEntry::setDirty(bool b)
Packit d7e8d0
{
Packit d7e8d0
    mDirty = b;
Packit d7e8d0
}
Packit d7e8d0
#endif