Blame lang/cpp/src/configuration.cpp

Packit d7e8d0
/*
Packit d7e8d0
  configuration.cpp - wraps gpgme configuration components
Packit d7e8d0
  Copyright (C) 2010 Klarälvdalens Datakonsult AB
Packit d7e8d0
  2016 Bundesamt für Sicherheit in der Informationstechnik
Packit d7e8d0
  Software engineering by Intevation GmbH
Packit d7e8d0
Packit d7e8d0
  This file is part of GPGME++.
Packit d7e8d0
Packit d7e8d0
  GPGME++ is free software; you can redistribute it and/or
Packit d7e8d0
  modify it under the terms of the GNU Library General Public
Packit d7e8d0
  License as published by the Free Software Foundation; either
Packit d7e8d0
  version 2 of the License, or (at your option) any later version.
Packit d7e8d0
Packit d7e8d0
  GPGME++ 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
Packit d7e8d0
  GNU Library General Public License for more details.
Packit d7e8d0
Packit d7e8d0
  You should have received a copy of the GNU Library General Public License
Packit d7e8d0
  along with GPGME++; see the file COPYING.LIB.  If not, write to the
Packit d7e8d0
  Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
Packit d7e8d0
  Boston, MA 02110-1301, USA.
Packit d7e8d0
*/
Packit d7e8d0
Packit d7e8d0
#ifdef HAVE_CONFIG_H
Packit d7e8d0
 #include "config.h"
Packit d7e8d0
#endif
Packit d7e8d0
Packit d7e8d0
#include "configuration.h"
Packit d7e8d0
#include "error.h"
Packit d7e8d0
#include "util.h"
Packit d7e8d0
Packit d7e8d0
#include <gpgme.h>
Packit d7e8d0
Packit d7e8d0
#include <iterator>
Packit d7e8d0
#include <algorithm>
Packit d7e8d0
#include <ostream>
Packit d7e8d0
#include <cstring>
Packit d7e8d0
#include <assert.h>
Packit d7e8d0
Packit d7e8d0
using namespace GpgME;
Packit d7e8d0
using namespace GpgME::Configuration;
Packit d7e8d0
Packit d7e8d0
typedef std::shared_ptr< std::remove_pointer<gpgme_conf_opt_t>::type > shared_gpgme_conf_opt_t;
Packit d7e8d0
typedef std::weak_ptr< std::remove_pointer<gpgme_conf_opt_t>::type > weak_gpgme_conf_opt_t;
Packit d7e8d0
Packit d7e8d0
typedef std::shared_ptr< std::remove_pointer<gpgme_conf_arg_t>::type > shared_gpgme_conf_arg_t;
Packit d7e8d0
typedef std::weak_ptr< std::remove_pointer<gpgme_conf_arg_t>::type > weak_gpgme_conf_arg_t;
Packit d7e8d0
Packit d7e8d0
typedef std::shared_ptr< std::remove_pointer<gpgme_ctx_t>::type > shared_gpgme_ctx_t;
Packit d7e8d0
typedef std::weak_ptr< std::remove_pointer<gpgme_ctx_t>::type > weak_gpgme_ctx_t;
Packit d7e8d0
Packit d7e8d0
namespace
Packit d7e8d0
{
Packit d7e8d0
struct nodelete {
Packit d7e8d0
    template <typename T> void operator()(T *) {}
Packit d7e8d0
};
Packit d7e8d0
}
Packit d7e8d0
Packit d7e8d0
// static
Packit d7e8d0
std::vector<Component> Component::load(Error &returnedError)
Packit d7e8d0
{
Packit d7e8d0
Packit d7e8d0
    //
Packit d7e8d0
    // 1. get a context:
Packit d7e8d0
    //
Packit d7e8d0
    gpgme_ctx_t ctx_native = 0;
Packit d7e8d0
    if (const gpgme_error_t err = gpgme_new(&ctx_native)) {
Packit d7e8d0
        returnedError = Error(err);
Packit d7e8d0
        return std::vector<Component>();
Packit d7e8d0
    }
Packit d7e8d0
    const shared_gpgme_ctx_t ctx(ctx_native, &gpgme_release);
Packit d7e8d0
Packit d7e8d0
    //
Packit d7e8d0
    // 2. load the config:
Packit d7e8d0
    //
Packit d7e8d0
    gpgme_conf_comp_t conf_list_native = 0;
Packit d7e8d0
    if (const gpgme_error_t err = gpgme_op_conf_load(ctx_native, &conf_list_native)) {
Packit d7e8d0
        returnedError = Error(err);
Packit d7e8d0
        return std::vector<Component>();
Packit d7e8d0
    }
Packit d7e8d0
    shared_gpgme_conf_comp_t head(conf_list_native, &gpgme_conf_release);
Packit d7e8d0
Packit d7e8d0
    //
Packit d7e8d0
    // 3. convert to vector<Component>:
Packit d7e8d0
    //
Packit d7e8d0
    std::vector<Component> result;
Packit d7e8d0
Packit d7e8d0
    while (head) {
Packit d7e8d0
        // secure 'head->next' (if any) against memleaks:
Packit d7e8d0
        shared_gpgme_conf_comp_t next;
Packit d7e8d0
        if (head->next) {
Packit d7e8d0
            next.reset(head->next, &gpgme_conf_release);
Packit d7e8d0
        }
Packit d7e8d0
Packit d7e8d0
        // now prevent double-free of next.get() and following:
Packit d7e8d0
        head->next = 0;
Packit d7e8d0
Packit d7e8d0
        // now add a new Component to 'result' (may throw):
Packit d7e8d0
        result.resize(result.size() + 1);
Packit d7e8d0
        result.back().comp.swap(head);   // .comp = std::move( head );
Packit d7e8d0
        head.swap(next);                 //  head = std::move( next );
Packit d7e8d0
    }
Packit d7e8d0
Packit d7e8d0
    return result;
Packit d7e8d0
}
Packit d7e8d0
Packit d7e8d0
Error Component::save() const
Packit d7e8d0
{
Packit d7e8d0
Packit d7e8d0
    if (isNull()) {
Packit d7e8d0
        return Error(make_error(GPG_ERR_INV_ARG));
Packit d7e8d0
    }
Packit d7e8d0
Packit d7e8d0
    //
Packit d7e8d0
    // 1. get a context:
Packit d7e8d0
    //
Packit d7e8d0
    gpgme_ctx_t ctx_native = 0;
Packit d7e8d0
    if (const gpgme_error_t err = gpgme_new(&ctx_native)) {
Packit d7e8d0
        return Error(err);
Packit d7e8d0
    }
Packit d7e8d0
    const shared_gpgme_ctx_t ctx(ctx_native, &gpgme_release);
Packit d7e8d0
Packit d7e8d0
    //
Packit d7e8d0
    // 2. save the config:
Packit d7e8d0
    //
Packit d7e8d0
    return Error(gpgme_op_conf_save(ctx.get(), comp.get()));
Packit d7e8d0
}
Packit d7e8d0
Packit d7e8d0
const char *Component::name() const
Packit d7e8d0
{
Packit d7e8d0
    return comp ? comp->name : 0 ;
Packit d7e8d0
}
Packit d7e8d0
Packit d7e8d0
const char *Component::description() const
Packit d7e8d0
{
Packit d7e8d0
    return comp ? comp->description : 0 ;
Packit d7e8d0
}
Packit d7e8d0
Packit d7e8d0
const char *Component::programName() const
Packit d7e8d0
{
Packit d7e8d0
    return comp ? comp->program_name : 0 ;
Packit d7e8d0
}
Packit d7e8d0
Packit d7e8d0
Option Component::option(unsigned int idx) const
Packit d7e8d0
{
Packit d7e8d0
    gpgme_conf_opt_t opt = 0;
Packit d7e8d0
    if (comp) {
Packit d7e8d0
        opt = comp->options;
Packit d7e8d0
    }
Packit d7e8d0
    while (opt && idx) {
Packit d7e8d0
        opt = opt->next;
Packit d7e8d0
        --idx;
Packit d7e8d0
    }
Packit d7e8d0
    if (opt) {
Packit d7e8d0
        return Option(comp, opt);
Packit d7e8d0
    }
Packit d7e8d0
    return Option();
Packit d7e8d0
}
Packit d7e8d0
Packit d7e8d0
Option Component::option(const char *name) const
Packit d7e8d0
{
Packit d7e8d0
    gpgme_conf_opt_t opt = 0;
Packit d7e8d0
    if (comp) {
Packit d7e8d0
        opt = comp->options;
Packit d7e8d0
    }
Packit d7e8d0
    using namespace std; // for strcmp
Packit d7e8d0
    while (opt && strcmp(name, opt->name) != 0) {
Packit d7e8d0
        opt = opt->next;
Packit d7e8d0
    }
Packit d7e8d0
    if (opt) {
Packit d7e8d0
        return Option(comp, opt);
Packit d7e8d0
    }
Packit d7e8d0
    return Option();
Packit d7e8d0
}
Packit d7e8d0
Packit d7e8d0
unsigned int Component::numOptions() const
Packit d7e8d0
{
Packit d7e8d0
    unsigned int result = 0;
Packit d7e8d0
    for (gpgme_conf_opt_t opt = comp ? comp->options : 0 ; opt ; opt = opt->next) {
Packit d7e8d0
        ++result;
Packit d7e8d0
    }
Packit d7e8d0
    return result;
Packit d7e8d0
}
Packit d7e8d0
Packit d7e8d0
std::vector<Option> Component::options() const
Packit d7e8d0
{
Packit d7e8d0
    std::vector<Option> result;
Packit d7e8d0
    for (gpgme_conf_opt_t opt = comp ? comp->options : 0 ; opt ; opt = opt->next) {
Packit d7e8d0
        result.push_back(Option(comp, opt));
Packit d7e8d0
    }
Packit d7e8d0
    return result;
Packit d7e8d0
}
Packit d7e8d0
Packit d7e8d0
static gpgme_conf_arg_t mygpgme_conf_arg_copy(gpgme_conf_arg_t other, gpgme_conf_type_t type)
Packit d7e8d0
{
Packit d7e8d0
    gpgme_conf_arg_t result = 0, last = 0;
Packit d7e8d0
    for (gpgme_conf_arg_t a = other ; a ; a = a->next) {
Packit d7e8d0
        gpgme_conf_arg_t arg = 0;
Packit d7e8d0
        const gpgme_error_t err
Packit d7e8d0
            = gpgme_conf_arg_new(&arg, type,
Packit d7e8d0
                                 a->no_arg                 ? 0 :
Packit d7e8d0
                                 type == GPGME_CONF_STRING ? a->value.string :
Packit d7e8d0
                                 /* else */                  static_cast<void *>(&a->value));
Packit d7e8d0
        if (err) {
Packit d7e8d0
            gpgme_conf_arg_release(result, type);
Packit d7e8d0
            return 0;
Packit d7e8d0
        }
Packit d7e8d0
        assert(arg);
Packit d7e8d0
        if (result) {
Packit d7e8d0
            last->next = arg;
Packit d7e8d0
        } else {
Packit d7e8d0
            result = arg;
Packit d7e8d0
        }
Packit d7e8d0
        last = arg;
Packit d7e8d0
    }
Packit d7e8d0
    return result;
Packit d7e8d0
}
Packit d7e8d0
Packit d7e8d0
Component Option::parent() const
Packit d7e8d0
{
Packit d7e8d0
    return Component(comp.lock());
Packit d7e8d0
}
Packit d7e8d0
Packit d7e8d0
unsigned int Option::flags() const
Packit d7e8d0
{
Packit d7e8d0
    return isNull() ? 0 : opt->flags;
Packit d7e8d0
}
Packit d7e8d0
Packit d7e8d0
Level Option::level() const
Packit d7e8d0
{
Packit d7e8d0
    return isNull() ? Internal : static_cast<Level>(opt->level) ;
Packit d7e8d0
}
Packit d7e8d0
Packit d7e8d0
const char *Option::name() const
Packit d7e8d0
{
Packit d7e8d0
    return isNull() ? 0 : opt->name ;
Packit d7e8d0
}
Packit d7e8d0
Packit d7e8d0
const char *Option::description() const
Packit d7e8d0
{
Packit d7e8d0
    return isNull() ? 0 : opt->description ;
Packit d7e8d0
}
Packit d7e8d0
Packit d7e8d0
const char *Option::argumentName() const
Packit d7e8d0
{
Packit d7e8d0
    return isNull() ? 0 : opt->argname ;
Packit d7e8d0
}
Packit d7e8d0
Packit d7e8d0
Type Option::type() const
Packit d7e8d0
{
Packit d7e8d0
    return isNull() ? NoType : static_cast<Type>(opt->type) ;
Packit d7e8d0
}
Packit d7e8d0
Packit d7e8d0
Type Option::alternateType() const
Packit d7e8d0
{
Packit d7e8d0
    return isNull() ? NoType : static_cast<Type>(opt->alt_type) ;
Packit d7e8d0
}
Packit d7e8d0
Packit d7e8d0
#if 0
Packit d7e8d0
static Option::Variant argument_to_variant(gpgme_conf_type_t type, bool list, gpgme_conf_arg_t arg)
Packit d7e8d0
{
Packit d7e8d0
    assert(arg);
Packit d7e8d0
    switch (type) {
Packit d7e8d0
    case GPGME_CONF_NONE:
Packit d7e8d0
        if (list) {
Packit d7e8d0
            // return the count (number of times set):
Packit d7e8d0
            return arg->value.count;
Packit d7e8d0
        } else {
Packit d7e8d0
            return none;
Packit d7e8d0
        }
Packit d7e8d0
    case GPGME_CONF_INT32:
Packit d7e8d0
        if (list) {
Packit d7e8d0
            std::vector<int> result;
Packit d7e8d0
            for (gpgme_conf_arg_t a = arg ; a ; a = a->next) {
Packit d7e8d0
                result.push_back(a->value.int32);
Packit d7e8d0
            }
Packit d7e8d0
            return result;
Packit d7e8d0
        } else {
Packit d7e8d0
            return arg->value.int32;
Packit d7e8d0
        }
Packit d7e8d0
    case GPGME_CONF_UINT32:
Packit d7e8d0
        if (list) {
Packit d7e8d0
            std::vector<unsigned int> result;
Packit d7e8d0
            for (gpgme_conf_arg_t a = arg ; a ; a = a->next) {
Packit d7e8d0
                result.push_back(a->value.uint32);
Packit d7e8d0
            }
Packit d7e8d0
            return result;
Packit d7e8d0
        } else {
Packit d7e8d0
            return arg->value.uint32;
Packit d7e8d0
        }
Packit d7e8d0
    case GPGME_CONF_FILENAME:
Packit d7e8d0
    case GPGME_CONF_LDAP_SERVER:
Packit d7e8d0
    case GPGME_CONF_KEY_FPR:
Packit d7e8d0
    case GPGME_CONF_PUB_KEY:
Packit d7e8d0
    case GPGME_CONF_SEC_KEY:
Packit d7e8d0
    case GPGME_CONF_ALIAS_LIST:
Packit d7e8d0
    // these should not happen in alt_type, but fall through
Packit d7e8d0
    case GPGME_CONF_STRING:
Packit d7e8d0
        if (list) {
Packit d7e8d0
            std::vector<const char *> result;
Packit d7e8d0
            for (gpgme_conf_arg_t a = arg ; a ; a = a->next) {
Packit d7e8d0
                result.push_back(a->value.string);
Packit d7e8d0
            }
Packit d7e8d0
            return result;
Packit d7e8d0
        } else {
Packit d7e8d0
            return arg->value.string;
Packit d7e8d0
        }
Packit d7e8d0
    }
Packit d7e8d0
    assert(!"Option: unknown alt_type!");
Packit d7e8d0
    return Option::Variant();
Packit d7e8d0
}
Packit d7e8d0
Packit d7e8d0
namespace
Packit d7e8d0
{
Packit d7e8d0
inline const void *to_void_star(const char *s)
Packit d7e8d0
{
Packit d7e8d0
    return s;
Packit d7e8d0
}
Packit d7e8d0
inline const void *to_void_star(const std::string &s)
Packit d7e8d0
{
Packit d7e8d0
    return s.c_str();
Packit d7e8d0
}
Packit d7e8d0
inline const void *to_void_star(const int &i)
Packit d7e8d0
{
Packit d7e8d0
    return &i;    // const-&: sic!
Packit d7e8d0
}
Packit d7e8d0
inline const void *to_void_star(const unsigned int &i)
Packit d7e8d0
{
Packit d7e8d0
    return &i;    // const-&: sic!
Packit d7e8d0
}
Packit d7e8d0
Packit d7e8d0
struct VariantToArgumentVisitor : boost::static_visitor<gpgme_conf_arg_t> {
Packit d7e8d0
    static gpgme_conf_arg_t make_argument(gpgme_conf_type_t type, const void *value)
Packit d7e8d0
    {
Packit d7e8d0
        gpgme_conf_arg_t arg = 0;
Packit d7e8d0
#ifdef HAVE_GPGME_CONF_ARG_NEW_WITH_CONST_VALUE
Packit d7e8d0
        if (const gpgme_error_t err = gpgme_conf_arg_new(&arg, type, value)) {
Packit d7e8d0
            return 0;
Packit d7e8d0
        }
Packit d7e8d0
#else
Packit d7e8d0
        if (const gpgme_error_t err = gpgme_conf_arg_new(&arg, type, const_cast<void *>(value))) {
Packit d7e8d0
            return 0;
Packit d7e8d0
        }
Packit d7e8d0
#endif
Packit d7e8d0
        else {
Packit d7e8d0
            return arg;
Packit d7e8d0
        }
Packit d7e8d0
    }
Packit d7e8d0
Packit d7e8d0
    gpgme_conf_arg_t operator()(bool v) const
Packit d7e8d0
    {
Packit d7e8d0
        return v ? make_argument(0) : 0 ;
Packit d7e8d0
    }
Packit d7e8d0
Packit d7e8d0
    gpgme_conf_arg_t operator()(const char *s) const
Packit d7e8d0
    {
Packit d7e8d0
        return make_argument(s ? s : "");
Packit d7e8d0
    }
Packit d7e8d0
Packit d7e8d0
    gpgme_conf_arg_t operator()(const std::string &s) const
Packit d7e8d0
    {
Packit d7e8d0
        return operator()(s.c_str());
Packit d7e8d0
    }
Packit d7e8d0
Packit d7e8d0
    gpgme_conf_arg_t operator()(int i) const
Packit d7e8d0
    {
Packit d7e8d0
        return make_argument(&i);
Packit d7e8d0
    }
Packit d7e8d0
Packit d7e8d0
    gpgme_conf_arg_t operator()(unsigned int i) const
Packit d7e8d0
    {
Packit d7e8d0
        return make_argument(&i);
Packit d7e8d0
    }
Packit d7e8d0
Packit d7e8d0
    template <typename T>
Packit d7e8d0
    gpgme_conf_arg_t operator()(const std::vector<T> &value) const
Packit d7e8d0
    {
Packit d7e8d0
        gpgme_conf_arg_t result = 0;
Packit d7e8d0
        gpgme_conf_arg_t last = 0;
Packit d7e8d0
        for (typename std::vector<T>::const_iterator it = value.begin(), end = value.end() ; it != end ; ++it) {
Packit d7e8d0
            if (gpgme_conf_arg_t arg = make_argument(to_void_star(*it))) {
Packit d7e8d0
                if (last) {
Packit d7e8d0
                    last = last->next = arg;
Packit d7e8d0
                } else {
Packit d7e8d0
                    result = last = arg;
Packit d7e8d0
                }
Packit d7e8d0
            }
Packit d7e8d0
        }
Packit d7e8d0
        return result;
Packit d7e8d0
    }
Packit d7e8d0
Packit d7e8d0
};
Packit d7e8d0
}
Packit d7e8d0
Packit d7e8d0
static gpgme_conf_arg_t variant_to_argument(const Option::Variant &value)
Packit d7e8d0
{
Packit d7e8d0
    VariantToArgumentVisitor v;
Packit d7e8d0
    return apply_visitor(v, value);
Packit d7e8d0
}
Packit d7e8d0
Packit d7e8d0
optional<Option::Variant> Option::defaultValue() const
Packit d7e8d0
{
Packit d7e8d0
    if (isNull()) {
Packit d7e8d0
        return optional<Variant>();
Packit d7e8d0
    } else {
Packit d7e8d0
        return argument_to_variant(opt->alt_type, opt->flags & GPGME_CONF_LIST, opt->default_value);
Packit d7e8d0
    }
Packit d7e8d0
}
Packit d7e8d0
#endif
Packit d7e8d0
Packit d7e8d0
Argument Option::defaultValue() const
Packit d7e8d0
{
Packit d7e8d0
    if (isNull()) {
Packit d7e8d0
        return Argument();
Packit d7e8d0
    } else {
Packit d7e8d0
        return Argument(comp.lock(), opt, opt->default_value, false);
Packit d7e8d0
    }
Packit d7e8d0
}
Packit d7e8d0
Packit d7e8d0
const char *Option::defaultDescription() const
Packit d7e8d0
{
Packit d7e8d0
    return isNull() ? 0 : opt->default_description ;
Packit d7e8d0
}
Packit d7e8d0
Packit d7e8d0
Argument Option::noArgumentValue() const
Packit d7e8d0
{
Packit d7e8d0
    if (isNull()) {
Packit d7e8d0
        return Argument();
Packit d7e8d0
    } else {
Packit d7e8d0
        return Argument(comp.lock(), opt, opt->no_arg_value, false);
Packit d7e8d0
    }
Packit d7e8d0
}
Packit d7e8d0
Packit d7e8d0
const char *Option::noArgumentDescription() const
Packit d7e8d0
{
Packit d7e8d0
    return isNull() ? 0 : opt->no_arg_description ;
Packit d7e8d0
}
Packit d7e8d0
Packit d7e8d0
Argument Option::activeValue() const
Packit d7e8d0
{
Packit d7e8d0
    if (isNull()) {
Packit d7e8d0
        return Argument();
Packit d7e8d0
    } else {
Packit d7e8d0
        return Argument(comp.lock(), opt, opt->value, false);
Packit d7e8d0
    }
Packit d7e8d0
}
Packit d7e8d0
Packit d7e8d0
Argument Option::currentValue() const
Packit d7e8d0
{
Packit d7e8d0
    if (isNull()) {
Packit d7e8d0
        return Argument();
Packit d7e8d0
    }
Packit d7e8d0
    const gpgme_conf_arg_t arg =
Packit d7e8d0
        opt->change_value ? opt->new_value ? opt->new_value : opt->default_value :
Packit d7e8d0
        opt->value        ? opt->value :
Packit d7e8d0
        /* else */          opt->default_value ;
Packit d7e8d0
    return Argument(comp.lock(), opt, arg, false);
Packit d7e8d0
}
Packit d7e8d0
Packit d7e8d0
Argument Option::newValue() const
Packit d7e8d0
{
Packit d7e8d0
    if (isNull()) {
Packit d7e8d0
        return Argument();
Packit d7e8d0
    } else {
Packit d7e8d0
        return Argument(comp.lock(), opt, opt->new_value, false);
Packit d7e8d0
    }
Packit d7e8d0
}
Packit d7e8d0
Packit d7e8d0
bool Option::set() const
Packit d7e8d0
{
Packit d7e8d0
    if (isNull()) {
Packit d7e8d0
        return false;
Packit d7e8d0
    } else if (opt->change_value) {
Packit d7e8d0
        return opt->new_value;
Packit d7e8d0
    } else {
Packit d7e8d0
        return opt->value;
Packit d7e8d0
    }
Packit d7e8d0
}
Packit d7e8d0
Packit d7e8d0
bool Option::dirty() const
Packit d7e8d0
{
Packit d7e8d0
    return !isNull() && opt->change_value ;
Packit d7e8d0
}
Packit d7e8d0
Packit d7e8d0
Error Option::setNewValue(const Argument &argument)
Packit d7e8d0
{
Packit d7e8d0
    if (isNull()) {
Packit d7e8d0
        return Error(make_error(GPG_ERR_INV_ARG));
Packit d7e8d0
    } else if (argument.isNull()) {
Packit d7e8d0
        return resetToDefaultValue();
Packit d7e8d0
    } else if (const gpgme_conf_arg_t arg = mygpgme_conf_arg_copy(argument.arg, opt->alt_type)) {
Packit d7e8d0
        return Error(gpgme_conf_opt_change(opt, 0, arg));
Packit d7e8d0
    } else {
Packit d7e8d0
        return Error(make_error(GPG_ERR_ENOMEM));
Packit d7e8d0
    }
Packit d7e8d0
}
Packit d7e8d0
Packit d7e8d0
Error Option::resetToActiveValue()
Packit d7e8d0
{
Packit d7e8d0
    if (isNull()) {
Packit d7e8d0
        return Error(make_error(GPG_ERR_INV_ARG));
Packit d7e8d0
    } else {
Packit d7e8d0
        return Error(gpgme_conf_opt_change(opt, 1, 0));
Packit d7e8d0
    }
Packit d7e8d0
}
Packit d7e8d0
Packit d7e8d0
Error Option::resetToDefaultValue()
Packit d7e8d0
{
Packit d7e8d0
    if (isNull()) {
Packit d7e8d0
        return Error(make_error(GPG_ERR_INV_ARG));
Packit d7e8d0
    } else {
Packit d7e8d0
        return Error(gpgme_conf_opt_change(opt, 0, 0));
Packit d7e8d0
    }
Packit d7e8d0
}
Packit d7e8d0
Packit d7e8d0
static gpgme_conf_arg_t make_argument(gpgme_conf_type_t type, const void *value)
Packit d7e8d0
{
Packit d7e8d0
    gpgme_conf_arg_t arg = 0;
Packit d7e8d0
    if (const gpgme_error_t err = gpgme_conf_arg_new(&arg, type, value)) {
Packit d7e8d0
        return 0;
Packit d7e8d0
    } else {
Packit d7e8d0
        return arg;
Packit d7e8d0
    }
Packit d7e8d0
}
Packit d7e8d0
Packit d7e8d0
Argument Option::createNoneArgument(bool set) const
Packit d7e8d0
{
Packit d7e8d0
    if (isNull() || alternateType() != NoType) {
Packit d7e8d0
        return Argument();
Packit d7e8d0
    } else {
Packit d7e8d0
        if (set) {
Packit d7e8d0
            return createNoneListArgument(1);
Packit d7e8d0
        }
Packit d7e8d0
    }
Packit d7e8d0
    return Argument();
Packit d7e8d0
}
Packit d7e8d0
Packit d7e8d0
Argument Option::createStringArgument(const char *value) const
Packit d7e8d0
{
Packit d7e8d0
    if (isNull() || alternateType() != StringType) {
Packit d7e8d0
        return Argument();
Packit d7e8d0
    } else {
Packit d7e8d0
        return Argument(comp.lock(), opt, make_argument(GPGME_CONF_STRING, value), true);
Packit d7e8d0
    }
Packit d7e8d0
}
Packit d7e8d0
Packit d7e8d0
Argument Option::createStringArgument(const std::string &value) const
Packit d7e8d0
{
Packit d7e8d0
    if (isNull() || alternateType() != StringType) {
Packit d7e8d0
        return Argument();
Packit d7e8d0
    } else {
Packit d7e8d0
        return Argument(comp.lock(), opt, make_argument(GPGME_CONF_STRING, value.c_str()), true);
Packit d7e8d0
    }
Packit d7e8d0
}
Packit d7e8d0
Packit d7e8d0
Argument Option::createIntArgument(int value) const
Packit d7e8d0
{
Packit d7e8d0
    if (isNull() || alternateType() != IntegerType) {
Packit d7e8d0
        return Argument();
Packit d7e8d0
    } else {
Packit d7e8d0
        return Argument(comp.lock(), opt, make_argument(GPGME_CONF_INT32, &value), true);
Packit d7e8d0
    }
Packit d7e8d0
}
Packit d7e8d0
Packit d7e8d0
Argument Option::createUIntArgument(unsigned int value) const
Packit d7e8d0
{
Packit d7e8d0
    if (isNull() || alternateType() != UnsignedIntegerType) {
Packit d7e8d0
        return Argument();
Packit d7e8d0
    } else {
Packit d7e8d0
        return Argument(comp.lock(), opt, make_argument(GPGME_CONF_UINT32, &value), true);
Packit d7e8d0
    }
Packit d7e8d0
}
Packit d7e8d0
Packit d7e8d0
namespace
Packit d7e8d0
{
Packit d7e8d0
const void *to_void_star(const char *s)
Packit d7e8d0
{
Packit d7e8d0
    return s;
Packit d7e8d0
}
Packit d7e8d0
const void *to_void_star(const std::string &s)
Packit d7e8d0
{
Packit d7e8d0
    return s.c_str();
Packit d7e8d0
}
Packit d7e8d0
const void *to_void_star(const int &i)
Packit d7e8d0
{
Packit d7e8d0
    return &i;    // const-&: sic!
Packit d7e8d0
}
Packit d7e8d0
const void *to_void_star(const unsigned int &i)
Packit d7e8d0
{
Packit d7e8d0
    return &i;    // const-&: sic!
Packit d7e8d0
}
Packit d7e8d0
Packit d7e8d0
template <typename T>
Packit d7e8d0
gpgme_conf_arg_t make_argument(gpgme_conf_type_t type, const std::vector<T> &value)
Packit d7e8d0
{
Packit d7e8d0
    gpgme_conf_arg_t result = 0;
Packit d7e8d0
    gpgme_conf_arg_t last = 0;
Packit d7e8d0
    for (typename std::vector<T>::const_iterator it = value.begin(), end = value.end() ; it != end ; ++it) {
Packit d7e8d0
        if (gpgme_conf_arg_t arg = make_argument(type, to_void_star(*it))) {
Packit d7e8d0
            if (last) {
Packit d7e8d0
                last = last->next = arg;
Packit d7e8d0
            } else {
Packit d7e8d0
                result = last = arg;
Packit d7e8d0
            }
Packit d7e8d0
        }
Packit d7e8d0
    }
Packit d7e8d0
    return result;
Packit d7e8d0
}
Packit d7e8d0
}
Packit d7e8d0
Packit d7e8d0
Argument Option::createNoneListArgument(unsigned int value) const
Packit d7e8d0
{
Packit d7e8d0
    if (value) {
Packit d7e8d0
        return Argument(comp.lock(), opt, make_argument(GPGME_CONF_NONE, &value), true);
Packit d7e8d0
    }
Packit d7e8d0
    return Argument();
Packit d7e8d0
}
Packit d7e8d0
Packit d7e8d0
Argument Option::createStringListArgument(const std::vector<const char *> &value) const
Packit d7e8d0
{
Packit d7e8d0
    return Argument(comp.lock(), opt, make_argument(GPGME_CONF_STRING, value), true);
Packit d7e8d0
}
Packit d7e8d0
Packit d7e8d0
Argument Option::createStringListArgument(const std::vector<std::string> &value) const
Packit d7e8d0
{
Packit d7e8d0
    return Argument(comp.lock(), opt, make_argument(GPGME_CONF_STRING, value), true);
Packit d7e8d0
}
Packit d7e8d0
Packit d7e8d0
Argument Option::createIntListArgument(const std::vector<int> &value) const
Packit d7e8d0
{
Packit d7e8d0
    return Argument(comp.lock(), opt, make_argument(GPGME_CONF_INT32, value), true);
Packit d7e8d0
}
Packit d7e8d0
Packit d7e8d0
Argument Option::createUIntListArgument(const std::vector<unsigned int> &value) const
Packit d7e8d0
{
Packit d7e8d0
    return Argument(comp.lock(), opt, make_argument(GPGME_CONF_UINT32, value), true);
Packit d7e8d0
}
Packit d7e8d0
Packit d7e8d0
Argument::Argument(const shared_gpgme_conf_comp_t &comp, gpgme_conf_opt_t opt, gpgme_conf_arg_t arg, bool owns)
Packit d7e8d0
    : comp(comp),
Packit d7e8d0
      opt(opt),
Packit d7e8d0
      arg(owns ? arg : mygpgme_conf_arg_copy(arg, opt ? opt->alt_type : GPGME_CONF_NONE))
Packit d7e8d0
{
Packit d7e8d0
Packit d7e8d0
}
Packit d7e8d0
Packit d7e8d0
#if 0
Packit d7e8d0
Argument::Argument(const shared_gpgme_conf_comp_t &comp, gpgme_conf_opt_t opt, gpgme_conf_arg_t arg)
Packit d7e8d0
    : comp(comp),
Packit d7e8d0
      opt(opt),
Packit d7e8d0
      arg(mygpgme_conf_arg_copy(arg, opt ? opt->alt_type : GPGME_CONF_NONE))
Packit d7e8d0
{
Packit d7e8d0
Packit d7e8d0
}
Packit d7e8d0
#endif
Packit d7e8d0
Packit d7e8d0
Argument::Argument(const Argument &other)
Packit d7e8d0
    : comp(other.comp),
Packit d7e8d0
      opt(other.opt),
Packit d7e8d0
      arg(mygpgme_conf_arg_copy(other.arg, opt ? opt->alt_type : GPGME_CONF_NONE))
Packit d7e8d0
{
Packit d7e8d0
Packit d7e8d0
}
Packit d7e8d0
Packit d7e8d0
Argument::~Argument()
Packit d7e8d0
{
Packit d7e8d0
    gpgme_conf_arg_release(arg, opt ? opt->alt_type : GPGME_CONF_NONE);
Packit d7e8d0
}
Packit d7e8d0
Packit d7e8d0
Option Argument::parent() const
Packit d7e8d0
{
Packit d7e8d0
    return Option(comp.lock(), opt);
Packit d7e8d0
}
Packit d7e8d0
Packit d7e8d0
bool Argument::boolValue() const
Packit d7e8d0
{
Packit d7e8d0
    return numberOfTimesSet();
Packit d7e8d0
}
Packit d7e8d0
Packit d7e8d0
unsigned int Argument::numElements() const
Packit d7e8d0
{
Packit d7e8d0
    if (isNull()) {
Packit d7e8d0
        return 0;
Packit d7e8d0
    }
Packit d7e8d0
    unsigned int result = 0;
Packit d7e8d0
    for (gpgme_conf_arg_t a = arg ; a ; a = a->next) {
Packit d7e8d0
        ++result;
Packit d7e8d0
    }
Packit d7e8d0
    return result;
Packit d7e8d0
}
Packit d7e8d0
Packit d7e8d0
const char *Argument::stringValue(unsigned int idx) const
Packit d7e8d0
{
Packit d7e8d0
    if (isNull() || opt->alt_type != GPGME_CONF_STRING) {
Packit d7e8d0
        return 0;
Packit d7e8d0
    }
Packit d7e8d0
    gpgme_conf_arg_t a = arg;
Packit d7e8d0
    while (a && idx) {
Packit d7e8d0
        a = a->next;
Packit d7e8d0
        --idx;
Packit d7e8d0
    }
Packit d7e8d0
    return a ? a->value.string : 0 ;
Packit d7e8d0
}
Packit d7e8d0
Packit d7e8d0
int Argument::intValue(unsigned int idx) const
Packit d7e8d0
{
Packit d7e8d0
    if (isNull() || opt->alt_type != GPGME_CONF_INT32) {
Packit d7e8d0
        return 0;
Packit d7e8d0
    }
Packit d7e8d0
    gpgme_conf_arg_t a = arg;
Packit d7e8d0
    while (a && idx) {
Packit d7e8d0
        a = a->next;
Packit d7e8d0
        --idx;
Packit d7e8d0
    }
Packit d7e8d0
    return a ? a->value.int32 : 0 ;
Packit d7e8d0
}
Packit d7e8d0
Packit d7e8d0
unsigned int Argument::uintValue(unsigned int idx) const
Packit d7e8d0
{
Packit d7e8d0
    if (isNull() || opt->alt_type != GPGME_CONF_UINT32) {
Packit d7e8d0
        return 0;
Packit d7e8d0
    }
Packit d7e8d0
    gpgme_conf_arg_t a = arg;
Packit d7e8d0
    while (a && idx) {
Packit d7e8d0
        a = a->next;
Packit d7e8d0
        --idx;
Packit d7e8d0
    }
Packit d7e8d0
    return a ? a->value.uint32 : 0 ;
Packit d7e8d0
}
Packit d7e8d0
Packit d7e8d0
unsigned int Argument::numberOfTimesSet() const
Packit d7e8d0
{
Packit d7e8d0
    if (isNull() || opt->alt_type != GPGME_CONF_NONE) {
Packit d7e8d0
        return 0;
Packit d7e8d0
    }
Packit d7e8d0
    return arg->value.count;
Packit d7e8d0
}
Packit d7e8d0
Packit d7e8d0
std::vector<const char *> Argument::stringValues() const
Packit d7e8d0
{
Packit d7e8d0
    if (isNull() || opt->alt_type != GPGME_CONF_STRING) {
Packit d7e8d0
        return std::vector<const char *>();
Packit d7e8d0
    }
Packit d7e8d0
    std::vector<const char *> result;
Packit d7e8d0
    for (gpgme_conf_arg_t a = arg ; a ; a = a->next) {
Packit d7e8d0
        result.push_back(a->value.string);
Packit d7e8d0
    }
Packit d7e8d0
    return result;
Packit d7e8d0
}
Packit d7e8d0
Packit d7e8d0
std::vector<int> Argument::intValues() const
Packit d7e8d0
{
Packit d7e8d0
    if (isNull() || opt->alt_type != GPGME_CONF_INT32) {
Packit d7e8d0
        return std::vector<int>();
Packit d7e8d0
    }
Packit d7e8d0
    std::vector<int> result;
Packit d7e8d0
    for (gpgme_conf_arg_t a = arg ; a ; a = a->next) {
Packit d7e8d0
        result.push_back(a->value.int32);
Packit d7e8d0
    }
Packit d7e8d0
    return result;
Packit d7e8d0
}
Packit d7e8d0
Packit d7e8d0
std::vector<unsigned int> Argument::uintValues() const
Packit d7e8d0
{
Packit d7e8d0
    if (isNull() || opt->alt_type != GPGME_CONF_UINT32) {
Packit d7e8d0
        return std::vector<unsigned int>();
Packit d7e8d0
    }
Packit d7e8d0
    std::vector<unsigned int> result;
Packit d7e8d0
    for (gpgme_conf_arg_t a = arg ; a ; a = a->next) {
Packit d7e8d0
        result.push_back(a->value.uint32);
Packit d7e8d0
    }
Packit d7e8d0
    return result;
Packit d7e8d0
}
Packit d7e8d0
Packit d7e8d0
std::ostream &Configuration::operator<<(std::ostream &os, Level level)
Packit d7e8d0
{
Packit d7e8d0
    switch (level) {
Packit d7e8d0
    case Basic:     return os << "Basic";
Packit d7e8d0
    case Advanced:  return os << "Advanced";
Packit d7e8d0
    case Expert:    return os << "Expert";
Packit d7e8d0
    case Invisible: return os << "Invisible";
Packit d7e8d0
    case Internal:  return os << "Internal";
Packit d7e8d0
    case NumLevels: ;
Packit d7e8d0
    }
Packit d7e8d0
    return os << "<unknown>";
Packit d7e8d0
}
Packit d7e8d0
Packit d7e8d0
std::ostream &Configuration::operator<<(std::ostream &os, Type type)
Packit d7e8d0
{
Packit d7e8d0
    switch (type) {
Packit d7e8d0
    case NoType:              return os << "None";
Packit d7e8d0
    case StringType:          return os << "String";
Packit d7e8d0
    case IntegerType:         return os << "Integer";
Packit d7e8d0
    case UnsignedIntegerType: return os << "UnsignedInteger";
Packit d7e8d0
    case FilenameType:        return os << "Filename";
Packit d7e8d0
    case LdapServerType:      return os << "LdapServer";
Packit d7e8d0
    case KeyFingerprintType:  return os << "KeyFingerprint";
Packit d7e8d0
    case PublicKeyType:       return os << "PublicKey";
Packit d7e8d0
    case SecretKeyType:       return os << "SecretKey";
Packit d7e8d0
    case AliasListType:       return os << "AliasList";
Packit d7e8d0
    case MaxType: ;
Packit d7e8d0
    }
Packit d7e8d0
    return os << "<unknown>";
Packit d7e8d0
}
Packit d7e8d0
Packit d7e8d0
std::ostream &Configuration::operator<<(std::ostream &os, Flag f)
Packit d7e8d0
{
Packit d7e8d0
    unsigned int flags = f;
Packit d7e8d0
    std::vector<const char *> s;
Packit d7e8d0
    if (flags & Group) {
Packit d7e8d0
        s.push_back("Group");
Packit d7e8d0
    }
Packit d7e8d0
    if (flags & Optional) {
Packit d7e8d0
        s.push_back("Optional");
Packit d7e8d0
    }
Packit d7e8d0
    if (flags & List) {
Packit d7e8d0
        s.push_back("List");
Packit d7e8d0
    }
Packit d7e8d0
    if (flags & Runtime) {
Packit d7e8d0
        s.push_back("Runtime");
Packit d7e8d0
    }
Packit d7e8d0
    if (flags & Default) {
Packit d7e8d0
        s.push_back("Default");
Packit d7e8d0
    }
Packit d7e8d0
    if (flags & DefaultDescription) {
Packit d7e8d0
        s.push_back("DefaultDescription");
Packit d7e8d0
    }
Packit d7e8d0
    if (flags & NoArgumentDescription) {
Packit d7e8d0
        s.push_back("NoArgumentDescription");
Packit d7e8d0
    }
Packit d7e8d0
    if (flags & NoChange) {
Packit d7e8d0
        s.push_back("NoChange");
Packit d7e8d0
    }
Packit d7e8d0
    flags &= ~(Group | Optional | List | Runtime | Default | DefaultDescription | NoArgumentDescription | NoChange);
Packit d7e8d0
    if (flags) {
Packit d7e8d0
        s.push_back("other flags(");
Packit d7e8d0
    }
Packit d7e8d0
    std::copy(s.begin(), s.end(),
Packit d7e8d0
              std::ostream_iterator<const char *>(os, "|"));
Packit d7e8d0
    if (flags) {
Packit d7e8d0
        os << flags << ')';
Packit d7e8d0
    }
Packit d7e8d0
    return os;
Packit d7e8d0
}
Packit d7e8d0
Packit d7e8d0
std::ostream &Configuration::operator<<(std::ostream &os, const Component &c)
Packit d7e8d0
{
Packit d7e8d0
    os << "Component["
Packit d7e8d0
       << "\n  name       : " << protect(c.name())
Packit d7e8d0
       << "\n  description: " << protect(c.description())
Packit d7e8d0
       << "\n  programName: " << protect(c.programName())
Packit d7e8d0
       << "\n  options    : \n";
Packit d7e8d0
    const std::vector<Option> options = c.options();
Packit d7e8d0
    std::copy(options.begin(), options.end(),
Packit d7e8d0
              std::ostream_iterator<Option>(os, "\n"));
Packit d7e8d0
    os << "\n]";
Packit d7e8d0
    return os;
Packit d7e8d0
}
Packit d7e8d0
Packit d7e8d0
std::ostream &Configuration::operator<<(std::ostream &os, const Option &o)
Packit d7e8d0
{
Packit d7e8d0
    return os << "Option["
Packit d7e8d0
           << "\n  name:       : " << protect(o.name())
Packit d7e8d0
           << "\n  description : " << protect(o.description())
Packit d7e8d0
           << "\n  argName     : " << protect(o.argumentName())
Packit d7e8d0
           << "\n  flags       : " << static_cast<Flag>(o.flags())
Packit d7e8d0
           << "\n  level       : " << o.level()
Packit d7e8d0
           << "\n  type        : " << o.type()
Packit d7e8d0
           << "\n  alt_type    : " << o.alternateType()
Packit d7e8d0
           << "\n  default_val : " << o.defaultValue()
Packit d7e8d0
           << "\n  default_desc: " << protect(o.defaultDescription())
Packit d7e8d0
           << "\n  no_arg_value: " << o.noArgumentValue()
Packit d7e8d0
           << "\n  no_arg_desc : " << protect(o.noArgumentDescription())
Packit d7e8d0
           << "\n  active_value: " << o.activeValue()
Packit d7e8d0
           << "\n  new_value   : " << o.newValue()
Packit d7e8d0
           << "\n  --> cur_val : " << o.currentValue()
Packit d7e8d0
           << "\n  set         : " << o.set()
Packit d7e8d0
           << "\n  dirty       : " << o.dirty()
Packit d7e8d0
           << "\n]"
Packit d7e8d0
           ;
Packit d7e8d0
}
Packit d7e8d0
Packit d7e8d0
std::ostream &Configuration::operator<<(std::ostream &os, const Argument &a)
Packit d7e8d0
{
Packit d7e8d0
    const Option o = a.parent();
Packit d7e8d0
    const bool list = o.flags() & List;
Packit d7e8d0
    os << "Argument[";
Packit d7e8d0
    if (a) {
Packit d7e8d0
        switch (o.alternateType()) {
Packit d7e8d0
        case NoType:
Packit d7e8d0
            if (list) {
Packit d7e8d0
                os << a.numberOfTimesSet() << 'x';
Packit d7e8d0
            } else {
Packit d7e8d0
                os << a.boolValue();
Packit d7e8d0
            }
Packit d7e8d0
            break;
Packit d7e8d0
        default:
Packit d7e8d0
        case StringType:
Packit d7e8d0
            if (list) {
Packit d7e8d0
                const std::vector<const char *> v = a.stringValues();
Packit d7e8d0
                os << v.size() << ':';
Packit d7e8d0
                // can't use std::copy + ostream_iterator here, since we need the protect() call
Packit d7e8d0
                bool first = true;
Packit d7e8d0
                std::for_each(v.begin(), v.end(), [&first, &os](const char *s) {
Packit d7e8d0
                    if (first) {
Packit d7e8d0
                        first = false;
Packit d7e8d0
                    } else {
Packit d7e8d0
                        os << ',';
Packit d7e8d0
                    }
Packit d7e8d0
                    os << protect(s);
Packit d7e8d0
                });
Packit d7e8d0
            } else {
Packit d7e8d0
                os << protect(a.stringValue());
Packit d7e8d0
            }
Packit d7e8d0
            break;
Packit d7e8d0
        case IntegerType:
Packit d7e8d0
            if (list) {
Packit d7e8d0
                const std::vector<int> v = a.intValues();
Packit d7e8d0
                os << v.size() << ':';
Packit d7e8d0
                std::copy(v.begin(), v.end(),
Packit d7e8d0
                          std::ostream_iterator<int>(os, ","));
Packit d7e8d0
            } else {
Packit d7e8d0
                os << a.intValue();
Packit d7e8d0
            }
Packit d7e8d0
            break;
Packit d7e8d0
        case UnsignedIntegerType:
Packit d7e8d0
            if (list) {
Packit d7e8d0
                const std::vector<unsigned int> v = a.uintValues();
Packit d7e8d0
                os << v.size() << ':';
Packit d7e8d0
                std::copy(v.begin(), v.end(),
Packit d7e8d0
                          std::ostream_iterator<unsigned int>(os, ","));
Packit d7e8d0
            } else {
Packit d7e8d0
                os << a.intValue();
Packit d7e8d0
            }
Packit d7e8d0
            break;
Packit d7e8d0
        }
Packit d7e8d0
    }
Packit d7e8d0
    return os << ']';
Packit d7e8d0
}