diff options
| author | Andre Heinecke <[email protected]> | 2016-02-22 17:28:08 +0000 | 
|---|---|---|
| committer | Andre Heinecke <[email protected]> | 2016-02-22 18:01:37 +0000 | 
| commit | 0855a1296a1908016f011eb5e6552854ac53e63a (patch) | |
| tree | ae662e7201a7d60d0e7733532ebded629cfacb94 /lang/cpp/src/configuration.cpp | |
| parent | Fix possible _SC_OPEN_MAX max problem on AIX. (diff) | |
| download | gpgme-0855a1296a1908016f011eb5e6552854ac53e63a.tar.gz gpgme-0855a1296a1908016f011eb5e6552854ac53e63a.zip | |
Initial checkin of gpgmepp sources
Based on git.kde.org/pim/gpgmepp rev. 0e3ebc02
* lang/cpp/src/assuanresult.cpp,
 lang/cpp/src/assuanresult.h,
 lang/cpp/src/callbacks.cpp,
 lang/cpp/src/callbacks.h,
 lang/cpp/src/configuration.cpp,
 lang/cpp/src/configuration.h,
 lang/cpp/src/context.cpp,
 lang/cpp/src/context.h,
 lang/cpp/src/context_glib.cpp,
 lang/cpp/src/context_p.h,
 lang/cpp/src/context_qt.cpp,
 lang/cpp/src/context_vanilla.cpp,
 lang/cpp/src/data.cpp,
 lang/cpp/src/data.h,
 lang/cpp/src/data_p.h,
 lang/cpp/src/decryptionresult.cpp,
 lang/cpp/src/decryptionresult.h,
 lang/cpp/src/defaultassuantransaction.cpp,
 lang/cpp/src/defaultassuantransaction.h,
 lang/cpp/src/editinteractor.cpp,
 lang/cpp/src/editinteractor.h,
 lang/cpp/src/encryptionresult.cpp,
 lang/cpp/src/encryptionresult.h,
 lang/cpp/src/engineinfo.cpp,
 lang/cpp/src/engineinfo.h,
 lang/cpp/src/error.h,
 lang/cpp/src/eventloopinteractor.cpp,
 lang/cpp/src/eventloopinteractor.h,
 lang/cpp/src/exception.cpp,
 lang/cpp/src/exception.h,
 lang/cpp/src/global.h,
 lang/cpp/src/gpgadduserideditinteractor.cpp,
 lang/cpp/src/gpgadduserideditinteractor.h,
 lang/cpp/src/gpgagentgetinfoassuantransaction.cpp,
 lang/cpp/src/gpgagentgetinfoassuantransaction.h,
 lang/cpp/src/gpgmefw.h,
 lang/cpp/src/gpgmepp_export.h,
 lang/cpp/src/gpgsetexpirytimeeditinteractor.cpp,
 lang/cpp/src/gpgsetexpirytimeeditinteractor.h,
 lang/cpp/src/gpgsetownertrusteditinteractor.cpp,
 lang/cpp/src/gpgsetownertrusteditinteractor.h,
 lang/cpp/src/gpgsignkeyeditinteractor.cpp,
 lang/cpp/src/gpgsignkeyeditinteractor.h,
 lang/cpp/src/importresult.cpp,
 lang/cpp/src/importresult.h,
 lang/cpp/src/key.cpp,
 lang/cpp/src/key.h,
 lang/cpp/src/keygenerationresult.cpp,
 lang/cpp/src/keygenerationresult.h,
 lang/cpp/src/keylistresult.cpp,
 lang/cpp/src/keylistresult.h,
 lang/cpp/src/notation.h,
 lang/cpp/src/result.h,
 lang/cpp/src/result_p.h,
 lang/cpp/src/scdgetinfoassuantransaction.cpp,
 lang/cpp/src/scdgetinfoassuantransaction.h,
 lang/cpp/src/signingresult.cpp,
 lang/cpp/src/signingresult.h,
 lang/cpp/src/trustitem.cpp,
 lang/cpp/src/trustitem.h,
 lang/cpp/src/util.h,
 lang/cpp/src/verificationresult.cpp,
 lang/cpp/src/verificationresult.h,
 lang/cpp/src/vfsmountresult.cpp,
 lang/cpp/src/vfsmountresult.h,
 lang/cpp/src/interfaces/assuantransaction.h,
 lang/cpp/src/interfaces/dataprovider.h,
 lang/cpp/src/interfaces/passphraseprovider.h,
 lang/cpp/src/interfaces/progressprovider.h: New.
Diffstat (limited to '')
| -rw-r--r-- | lang/cpp/src/configuration.cpp | 1139 | 
1 files changed, 1139 insertions, 0 deletions
| diff --git a/lang/cpp/src/configuration.cpp b/lang/cpp/src/configuration.cpp new file mode 100644 index 00000000..fc19020e --- /dev/null +++ b/lang/cpp/src/configuration.cpp @@ -0,0 +1,1139 @@ +/* +  configuration.cpp - wraps gpgme configuration components +  Copyright (C) 2010 Klarälvdalens Datakonsult AB + +  This file is part of GPGME++. + +  GPGME++ is free software; you can redistribute it and/or +  modify it under the terms of the GNU Library General Public +  License as published by the Free Software Foundation; either +  version 2 of the License, or (at your option) any later version. + +  GPGME++ 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 Library General Public License for more details. + +  You should have received a copy of the GNU Library General Public License +  along with GPGME++; see the file COPYING.LIB.  If not, write to the +  Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, +  Boston, MA 02110-1301, USA. +*/ + +#include <config-gpgme++.h> + +#include "configuration.h" +#include "error.h" +#include "util.h" + +#include <gpgme.h> + +#include <boost/foreach.hpp> + +#include <iterator> +#include <algorithm> +#include <ostream> +#include <cstring> + +using namespace GpgME; +using namespace GpgME::Configuration; + +typedef boost::shared_ptr< boost::remove_pointer<gpgme_conf_opt_t>::type > shared_gpgme_conf_opt_t; +typedef boost::weak_ptr< boost::remove_pointer<gpgme_conf_opt_t>::type > weak_gpgme_conf_opt_t; + +typedef boost::shared_ptr< boost::remove_pointer<gpgme_conf_arg_t>::type > shared_gpgme_conf_arg_t; +typedef boost::weak_ptr< boost::remove_pointer<gpgme_conf_arg_t>::type > weak_gpgme_conf_arg_t; + +typedef boost::shared_ptr< boost::remove_pointer<gpgme_ctx_t>::type > shared_gpgme_ctx_t; +typedef boost::weak_ptr< boost::remove_pointer<gpgme_ctx_t>::type > weak_gpgme_ctx_t; + +namespace +{ +struct nodelete { +    template <typename T> void operator()(T *) {} +}; +} + +// static +std::vector<Component> Component::load(Error &returnedError) +{ + +#ifdef HAVE_GPGME_PROTOCOL_GPGCONF +    // +    // 1. get a context: +    // +    gpgme_ctx_t ctx_native = 0; +    if (const gpgme_error_t err = gpgme_new(&ctx_native)) { +        returnedError = Error(err); +        return std::vector<Component>(); +    } +    const shared_gpgme_ctx_t ctx(ctx_native, &gpgme_release); + +    // +    // 2. load the config: +    // +    gpgme_conf_comp_t conf_list_native = 0; +    if (const gpgme_error_t err = gpgme_op_conf_load(ctx_native, &conf_list_native)) { +        returnedError = Error(err); +        return std::vector<Component>(); +    } +    shared_gpgme_conf_comp_t head(conf_list_native, &gpgme_conf_release); + +    // +    // 3. convert to vector<Component>: +    // +    std::vector<Component> result; + +    while (head) { +        // secure 'head->next' (if any) against memleaks: +        shared_gpgme_conf_comp_t next; +        if (head->next) { +            next.reset(head->next, &gpgme_conf_release); +        } + +        // now prevent double-free of next.get() and following: +        head->next = 0; + +        // now add a new Component to 'result' (may throw): +        result.resize(result.size() + 1); +        result.back().comp.swap(head);   // .comp = std::move( head ); +        head.swap(next);                 //  head = std::move( next ); +    } + +    return result; +#else +    returnedError = Error(make_error(GPG_ERR_NOT_SUPPORTED)); +    return std::vector<Component>(); +#endif +} + +Error Component::save() const +{ + +#ifdef HAVE_GPGME_PROTOCOL_GPGCONF +    if (isNull()) { +        return Error(make_error(GPG_ERR_INV_ARG)); +    } + +    // +    // 1. get a context: +    // +    gpgme_ctx_t ctx_native = 0; +    if (const gpgme_error_t err = gpgme_new(&ctx_native)) { +        return Error(err); +    } +    const shared_gpgme_ctx_t ctx(ctx_native, &gpgme_release); + +    // +    // 2. save the config: +    // +    return Error(gpgme_op_conf_save(ctx.get(), comp.get())); +#else +    return Error(make_error(GPG_ERR_NOT_SUPPORTED)); +#endif +} + +const char *Component::name() const +{ +#ifdef HAVE_GPGME_PROTOCOL_GPGCONF +    return comp ? comp->name : 0 ; +#else +    return 0; +#endif +} + +const char *Component::description() const +{ +#ifdef HAVE_GPGME_PROTOCOL_GPGCONF +    return comp ? comp->description : 0 ; +#else +    return 0; +#endif +} + +const char *Component::programName() const +{ +#ifdef HAVE_GPGME_PROTOCOL_GPGCONF +    return comp ? comp->program_name : 0 ; +#else +    return 0; +#endif +} + +Option Component::option(unsigned int idx) const +{ +#ifdef HAVE_GPGME_PROTOCOL_GPGCONF +    gpgme_conf_opt_t opt = 0; +    if (comp) { +        opt = comp->options; +    } +    while (opt && idx) { +        opt = opt->next; +        --idx; +    } +    if (opt) { +        return Option(comp, opt); +    } else { +#endif +        return Option(); +#ifdef HAVE_GPGME_PROTOCOL_GPGCONF +    } +#endif +} + +Option Component::option(const char *name) const +{ +#ifdef HAVE_GPGME_PROTOCOL_GPGCONF +    gpgme_conf_opt_t opt = 0; +    if (comp) { +        opt = comp->options; +    } +    using namespace std; // for strcmp +    while (opt && strcmp(name, opt->name) != 0) { +        opt = opt->next; +    } +    if (opt) { +        return Option(comp, opt); +    } else { +#endif +        return Option(); +#ifdef HAVE_GPGME_PROTOCOL_GPGCONF +    } +#endif +} + +unsigned int Component::numOptions() const +{ +    unsigned int result = 0; +#ifdef HAVE_GPGME_PROTOCOL_GPGCONF +    for (gpgme_conf_opt_t opt = comp ? comp->options : 0 ; opt ; opt = opt->next) { +        ++result; +    } +#endif +    return result; +} + +std::vector<Option> Component::options() const +{ +    std::vector<Option> result; +#ifdef HAVE_GPGME_PROTOCOL_GPGCONF +    for (gpgme_conf_opt_t opt = comp ? comp->options : 0 ; opt ; opt = opt->next) { +        result.push_back(Option(comp, opt)); +    } +#endif +    return result; +} + +#ifdef HAVE_GPGME_PROTOCOL_GPGCONF +static gpgme_conf_arg_t mygpgme_conf_arg_copy(gpgme_conf_arg_t other, gpgme_conf_type_t type) +{ +    gpgme_conf_arg_t result = 0, last = 0; +    for (gpgme_conf_arg_t a = other ; a ; a = a->next) { +        gpgme_conf_arg_t arg = 0; +        const gpgme_error_t err +            = gpgme_conf_arg_new(&arg, type, +                                 a->no_arg                 ? 0 : +                                 type == GPGME_CONF_STRING ? a->value.string : +                                 /* else */                  static_cast<void *>(&a->value)); +        if (err) { +            gpgme_conf_arg_release(result, type); +            return 0; +        } +        assert(arg); +        if (result) { +            last->next = arg; +        } else { +            result = arg; +        } +        last = arg; +    } +    return result; +} +#endif + +Component Option::parent() const +{ +    return Component(comp.lock()); +} + +unsigned int Option::flags() const +{ +#ifdef HAVE_GPGME_PROTOCOL_GPGCONF +    return isNull() ? 0 : opt->flags; +#else +    return 0; +#endif +} + +Level Option::level() const +{ +#ifdef HAVE_GPGME_PROTOCOL_GPGCONF +    return isNull() ? Internal : static_cast<Level>(opt->level) ; +#else +    return Internal; +#endif +} + +const char *Option::name() const +{ +#ifdef HAVE_GPGME_PROTOCOL_GPGCONF +    return isNull() ? 0 : opt->name ; +#else +    return 0; +#endif +} + +const char *Option::description() const +{ +#ifdef HAVE_GPGME_PROTOCOL_GPGCONF +    return isNull() ? 0 : opt->description ; +#else +    return 0; +#endif +} + +const char *Option::argumentName() const +{ +#ifdef HAVE_GPGME_PROTOCOL_GPGCONF +    return isNull() ? 0 : opt->argname ; +#else +    return 0; +#endif +} + +Type Option::type() const +{ +#ifdef HAVE_GPGME_PROTOCOL_GPGCONF +    return isNull() ? NoType : static_cast<Type>(opt->type) ; +#else +    return NoType; +#endif +} + +Type Option::alternateType() const +{ +#ifdef HAVE_GPGME_PROTOCOL_GPGCONF +    return isNull() ? NoType : static_cast<Type>(opt->alt_type) ; +#else +    return NoType; +#endif +} + +#if 0 +static Option::Variant argument_to_variant(gpgme_conf_type_t type, bool list, gpgme_conf_arg_t arg) +{ +    assert(arg); +    switch (type) { +    case GPGME_CONF_NONE: +        if (list) { +            // return the count (number of times set): +            return arg->value.count; +        } else { +            return none; +        } +    case GPGME_CONF_INT32: +        if (list) { +            std::vector<int> result; +            for (gpgme_conf_arg_t a = arg ; a ; a = a->next) { +                result.push_back(a->value.int32); +            } +            return result; +        } else { +            return arg->value.int32; +        } +    case GPGME_CONF_UINT32: +        if (list) { +            std::vector<unsigned int> result; +            for (gpgme_conf_arg_t a = arg ; a ; a = a->next) { +                result.push_back(a->value.uint32); +            } +            return result; +        } else { +            return arg->value.uint32; +        } +    case GPGME_CONF_FILENAME: +    case GPGME_CONF_LDAP_SERVER: +    case GPGME_CONF_KEY_FPR: +    case GPGME_CONF_PUB_KEY: +    case GPGME_CONF_SEC_KEY: +    case GPGME_CONF_ALIAS_LIST: +    // these should not happen in alt_type, but fall through +    case GPGME_CONF_STRING: +        if (list) { +            std::vector<const char *> result; +            for (gpgme_conf_arg_t a = arg ; a ; a = a->next) { +                result.push_back(a->value.string); +            } +            return result; +        } else { +            return arg->value.string; +        } +    } +    assert(!"Option: unknown alt_type!"); +    return Option::Variant(); +} + +namespace +{ +inline const void *to_void_star(const char *s) +{ +    return s; +} +inline const void *to_void_star(const std::string &s) +{ +    return s.c_str(); +} +inline const void *to_void_star(const int &i) +{ +    return &i;    // const-&: sic! +} +inline const void *to_void_star(const unsigned int &i) +{ +    return &i;    // const-&: sic! +} + +struct VariantToArgumentVisitor : boost::static_visitor<gpgme_conf_arg_t> { +    static gpgme_conf_arg_t make_argument(gpgme_conf_type_t type, const void *value) +    { +        gpgme_conf_arg_t arg = 0; +#ifdef HAVE_GPGME_CONF_ARG_NEW_WITH_CONST_VALUE +        if (const gpgme_error_t err = gpgme_conf_arg_new(&arg, type, value)) { +            return 0; +        } +#else +        if (const gpgme_error_t err = gpgme_conf_arg_new(&arg, type, const_cast<void *>(value))) { +            return 0; +        } +#endif +        else { +            return arg; +        } +    } + +    gpgme_conf_arg_t operator()(bool v) const +    { +        return v ? make_argument(0) : 0 ; +    } + +    gpgme_conf_arg_t operator()(const char *s) const +    { +        return make_argument(s ? s : ""); +    } + +    gpgme_conf_arg_t operator()(const std::string &s) const +    { +        return operator()(s.c_str()); +    } + +    gpgme_conf_arg_t operator()(int i) const +    { +        return make_argument(&i); +    } + +    gpgme_conf_arg_t operator()(unsigned int i) const +    { +        return make_argument(&i); +    } + +    template <typename T> +    gpgme_conf_arg_t operator()(const std::vector<T> &value) const +    { +        gpgme_conf_arg_t result = 0; +        gpgme_conf_arg_t last = 0; +        for (typename std::vector<T>::const_iterator it = value.begin(), end = value.end() ; it != end ; ++it) { +            if (gpgme_conf_arg_t arg = make_argument(to_void_star(*it))) { +                if (last) { +                    last = last->next = arg; +                } else { +                    result = last = arg; +                } +            } +        } +        return result; +    } + +}; +} + +static gpgme_conf_arg_t variant_to_argument(const Option::Variant &value) +{ +    VariantToArgumentVisitor v; +    return apply_visitor(v, value); +} + +optional<Option::Variant> Option::defaultValue() const +{ +    if (isNull()) { +        return optional<Variant>(); +    } else { +        return argument_to_variant(opt->alt_type, opt->flags & GPGME_CONF_LIST, opt->default_value); +    } +} +#endif + +Argument Option::defaultValue() const +{ +#ifdef HAVE_GPGME_PROTOCOL_GPGCONF +    if (isNull()) { +        return Argument(); +    } else { +        return Argument(comp.lock(), opt, opt->default_value, false); +    } +#else +    return Argument(); +#endif +} + +const char *Option::defaultDescription() const +{ +#ifdef HAVE_GPGME_PROTOCOL_GPGCONF +    return isNull() ? 0 : opt->default_description ; +#else +    return 0; +#endif +} + +Argument Option::noArgumentValue() const +{ +#ifdef HAVE_GPGME_PROTOCOL_GPGCONF +    if (isNull()) { +        return Argument(); +    } else { +        return Argument(comp.lock(), opt, opt->no_arg_value, false); +    } +#else +    return Argument(); +#endif +} + +const char *Option::noArgumentDescription() const +{ +#ifdef HAVE_GPGME_PROTOCOL_GPGCONF +    return isNull() ? 0 : opt->no_arg_description ; +#else +    return 0; +#endif +} + +Argument Option::activeValue() const +{ +#ifdef HAVE_GPGME_PROTOCOL_GPGCONF +    if (isNull()) { +        return Argument(); +    } else { +        return Argument(comp.lock(), opt, opt->value, false); +    } +#else +    return Argument(); +#endif +} + +Argument Option::currentValue() const +{ +#ifdef HAVE_GPGME_PROTOCOL_GPGCONF +    if (isNull()) { +        return Argument(); +    } +    const gpgme_conf_arg_t arg = +        opt->change_value ? opt->new_value ? opt->new_value : opt->default_value : +        opt->value        ? opt->value : +        /* else */          opt->default_value ; +    return Argument(comp.lock(), opt, arg, false); +#else +    return Argument(); +#endif +} + +Argument Option::newValue() const +{ +#ifdef HAVE_GPGME_PROTOCOL_GPGCONF +    if (isNull()) { +        return Argument(); +    } else { +        return Argument(comp.lock(), opt, opt->new_value, false); +    } +#else +    return Argument(); +#endif +} + +bool Option::set() const +{ +#ifdef HAVE_GPGME_PROTOCOL_GPGCONF +    if (isNull()) { +        return false; +    } else if (opt->change_value) { +        return opt->new_value; +    } else { +        return opt->value; +    } +#else +    return false; +#endif +} + +bool Option::dirty() const +{ +#ifdef HAVE_GPGME_PROTOCOL_GPGCONF +    return !isNull() && opt->change_value ; +#else +    return false; +#endif +} + +Error Option::setNewValue(const Argument &argument) +{ +#ifdef HAVE_GPGME_PROTOCOL_GPGCONF +    if (isNull()) { +        return Error(make_error(GPG_ERR_INV_ARG)); +    } else if (argument.isNull()) { +        return resetToDefaultValue(); +    } else if (const gpgme_conf_arg_t arg = mygpgme_conf_arg_copy(argument.arg, opt->alt_type)) { +        return Error(gpgme_conf_opt_change(opt, 0, arg)); +    } else { +        return Error(make_error(GPG_ERR_ENOMEM)); +    } +#else +    return Error(make_error(GPG_ERR_NOT_SUPPORTED)); +#endif +} + +Error Option::resetToActiveValue() +{ +#ifdef HAVE_GPGME_PROTOCOL_GPGCONF +    if (isNull()) { +        return Error(make_error(GPG_ERR_INV_ARG)); +    } else { +        return Error(gpgme_conf_opt_change(opt, 1, 0)); +    } +#else +    return Error(make_error(GPG_ERR_NOT_SUPPORTED)); +#endif +} + +Error Option::resetToDefaultValue() +{ +#ifdef HAVE_GPGME_PROTOCOL_GPGCONF +    if (isNull()) { +        return Error(make_error(GPG_ERR_INV_ARG)); +    } else { +        return Error(gpgme_conf_opt_change(opt, 0, 0)); +    } +#else +    return Error(make_error(GPG_ERR_NOT_SUPPORTED)); +#endif +} + +#ifdef HAVE_GPGME_PROTOCOL_GPGCONF +static gpgme_conf_arg_t make_argument(gpgme_conf_type_t type, const void *value) +{ +    gpgme_conf_arg_t arg = 0; +#ifdef HAVE_GPGME_CONF_ARG_NEW_WITH_CONST_VALUE +    if (const gpgme_error_t err = gpgme_conf_arg_new(&arg, type, value)) { +        return 0; +    } +#else +    if (const gpgme_error_t err = gpgme_conf_arg_new(&arg, type, const_cast<void *>(value))) { +        return 0; +    } +#endif +    else { +        return arg; +    } +} +#endif + +Argument Option::createNoneArgument(bool set) const +{ +#ifdef HAVE_GPGME_PROTOCOL_GPGCONF +    if (isNull() || alternateType() != NoType) { +        return Argument(); +    } else { +        if (set) { +            return createNoneListArgument(1); +        } else { +#endif +            return Argument(); +#ifdef HAVE_GPGME_PROTOCOL_GPGCONF +        } +    } +#endif +} + +Argument Option::createStringArgument(const char *value) const +{ +#ifdef HAVE_GPGME_PROTOCOL_GPGCONF +    if (isNull() || alternateType() != StringType) { +        return Argument(); +    } else { +        return Argument(comp.lock(), opt, make_argument(GPGME_CONF_STRING, value), true); +    } +#else +    return Argument(); +#endif +} + +Argument Option::createStringArgument(const std::string &value) const +{ +#ifdef HAVE_GPGME_PROTOCOL_GPGCONF +    if (isNull() || alternateType() != StringType) { +        return Argument(); +    } else { +        return Argument(comp.lock(), opt, make_argument(GPGME_CONF_STRING, value.c_str()), true); +    } +#else +    return Argument(); +#endif +} + +Argument Option::createIntArgument(int value) const +{ +#ifdef HAVE_GPGME_PROTOCOL_GPGCONF +    if (isNull() || alternateType() != IntegerType) { +        return Argument(); +    } else { +        return Argument(comp.lock(), opt, make_argument(GPGME_CONF_INT32, &value), true); +    } +#else +    return Argument(); +#endif +} + +Argument Option::createUIntArgument(unsigned int value) const +{ +#ifdef HAVE_GPGME_PROTOCOL_GPGCONF +    if (isNull() || alternateType() != UnsignedIntegerType) { +        return Argument(); +    } else { +        return Argument(comp.lock(), opt, make_argument(GPGME_CONF_UINT32, &value), true); +    } +#else +    return Argument(); +#endif +} + +#ifdef HAVE_GPGME_PROTOCOL_GPGCONF +namespace +{ +const void *to_void_star(const char *s) +{ +    return s; +} +const void *to_void_star(const std::string &s) +{ +    return s.c_str(); +} +const void *to_void_star(const int &i) +{ +    return &i;    // const-&: sic! +} +const void *to_void_star(const unsigned int &i) +{ +    return &i;    // const-&: sic! +} + +template <typename T> +gpgme_conf_arg_t make_argument(gpgme_conf_type_t type, const std::vector<T> &value) +{ +    gpgme_conf_arg_t result = 0; +    gpgme_conf_arg_t last = 0; +    for (typename std::vector<T>::const_iterator it = value.begin(), end = value.end() ; it != end ; ++it) { +        if (gpgme_conf_arg_t arg = make_argument(type, to_void_star(*it))) { +            if (last) { +                last = last->next = arg; +            } else { +                result = last = arg; +            } +        } +    } +    return result; +} +} +#endif + +Argument Option::createNoneListArgument(unsigned int value) const +{ +#ifdef HAVE_GPGME_PROTOCOL_GPGCONF +    if (value) { +        return Argument(comp.lock(), opt, make_argument(GPGME_CONF_NONE, &value), true); +    } else { +#endif +        return Argument(); +#ifdef HAVE_GPGME_PROTOCOL_GPGCONF +    } +#endif +} + +Argument Option::createStringListArgument(const std::vector<const char *> &value) const +{ +#ifdef HAVE_GPGME_PROTOCOL_GPGCONF +    return Argument(comp.lock(), opt, make_argument(GPGME_CONF_STRING, value), true); +#else +    return Argument(); +#endif +} + +Argument Option::createStringListArgument(const std::vector<std::string> &value) const +{ +#ifdef HAVE_GPGME_PROTOCOL_GPGCONF +    return Argument(comp.lock(), opt, make_argument(GPGME_CONF_STRING, value), true); +#else +    return Argument(); +#endif +} + +Argument Option::createIntListArgument(const std::vector<int> &value) const +{ +#ifdef HAVE_GPGME_PROTOCOL_GPGCONF +    return Argument(comp.lock(), opt, make_argument(GPGME_CONF_INT32, value), true); +#else +    return Argument(); +#endif +} + +Argument Option::createUIntListArgument(const std::vector<unsigned int> &value) const +{ +#ifdef HAVE_GPGME_PROTOCOL_GPGCONF +    return Argument(comp.lock(), opt, make_argument(GPGME_CONF_UINT32, value), true); +#else +    return Argument(); +#endif +} + +Argument::Argument(const shared_gpgme_conf_comp_t &comp, gpgme_conf_opt_t opt, gpgme_conf_arg_t arg, bool owns) +    : comp(comp), +      opt(opt), +#ifdef HAVE_GPGME_PROTOCOL_GPGCONF +      arg(owns ? arg : mygpgme_conf_arg_copy(arg, opt ? opt->alt_type : GPGME_CONF_NONE)) +#else +      arg(0) +#endif +{ + +} + +#if 0 +Argument::Argument(const shared_gpgme_conf_comp_t &comp, gpgme_conf_opt_t opt, gpgme_conf_arg_t arg) +    : comp(comp), +      opt(opt), +      arg(mygpgme_conf_arg_copy(arg, opt ? opt->alt_type : GPGME_CONF_NONE)) +{ + +} +#endif + +Argument::Argument(const Argument &other) +    : comp(other.comp), +      opt(other.opt), +#ifdef HAVE_GPGME_PROTOCOL_GPGCONF +      arg(mygpgme_conf_arg_copy(other.arg, opt ? opt->alt_type : GPGME_CONF_NONE)) +#else +      arg(0) +#endif +{ + +} + +Argument::~Argument() +{ +#ifdef HAVE_GPGME_PROTOCOL_GPGCONF +    gpgme_conf_arg_release(arg, opt ? opt->alt_type : GPGME_CONF_NONE); +#endif +} + +Option Argument::parent() const +{ +    return Option(comp.lock(), opt); +} + +bool Argument::boolValue() const +{ +    return numberOfTimesSet(); +} + +unsigned int Argument::numElements() const +{ +    if (isNull()) { +        return 0; +    } +    unsigned int result = 0; +#ifdef HAVE_GPGME_PROTOCOL_GPGCONF +    for (gpgme_conf_arg_t a = arg ; a ; a = a->next) { +        ++result; +    } +#endif +    return result; +} + +const char *Argument::stringValue(unsigned int idx) const +{ +#ifdef HAVE_GPGME_PROTOCOL_GPGCONF +    if (isNull() || opt->alt_type != GPGME_CONF_STRING) { +        return 0; +    } +    gpgme_conf_arg_t a = arg; +    while (a && idx) { +        a = a->next; +        --idx; +    } +    return a ? a->value.string : 0 ; +#else +    return 0; +#endif +} + +int Argument::intValue(unsigned int idx) const +{ +#ifdef HAVE_GPGME_PROTOCOL_GPGCONF +    if (isNull() || opt->alt_type != GPGME_CONF_INT32) { +        return 0; +    } +    gpgme_conf_arg_t a = arg; +    while (a && idx) { +        a = a->next; +        --idx; +    } +    return a ? a->value.int32 : 0 ; +#else +    return 0; +#endif +} + +unsigned int Argument::uintValue(unsigned int idx) const +{ +#ifdef HAVE_GPGME_PROTOCOL_GPGCONF +    if (isNull() || opt->alt_type != GPGME_CONF_UINT32) { +        return 0; +    } +    gpgme_conf_arg_t a = arg; +    while (a && idx) { +        a = a->next; +        --idx; +    } +    return a ? a->value.uint32 : 0 ; +#else +    return 0; +#endif +} + +unsigned int Argument::numberOfTimesSet() const +{ +#ifdef HAVE_GPGME_PROTOCOL_GPGCONF +    if (isNull() || opt->alt_type != GPGME_CONF_NONE) { +        return 0; +    } +    return arg->value.count; +#else +    return 0; +#endif +} + +std::vector<const char *> Argument::stringValues() const +{ +    if (isNull() || opt->alt_type != GPGME_CONF_STRING) { +        return std::vector<const char *>(); +    } +    std::vector<const char *> result; +    for (gpgme_conf_arg_t a = arg ; a ; a = a->next) { +        result.push_back(a->value.string); +    } +    return result; +} + +std::vector<int> Argument::intValues() const +{ +#ifdef HAVE_GPGME_PROTOCOL_GPGCONF +    if (isNull() || opt->alt_type != GPGME_CONF_INT32) { +        return std::vector<int>(); +    } +#endif +    std::vector<int> result; +#ifdef HAVE_GPGME_PROTOCOL_GPGCONF +    for (gpgme_conf_arg_t a = arg ; a ; a = a->next) { +        result.push_back(a->value.int32); +    } +#endif +    return result; +} + +std::vector<unsigned int> Argument::uintValues() const +{ +#ifdef HAVE_GPGME_PROTOCOL_GPGCONF +    if (isNull() || opt->alt_type != GPGME_CONF_UINT32) { +        return std::vector<unsigned int>(); +    } +#endif +    std::vector<unsigned int> result; +#ifdef HAVE_GPGME_PROTOCOL_GPGCONF +    for (gpgme_conf_arg_t a = arg ; a ; a = a->next) { +        result.push_back(a->value.uint32); +    } +#endif +    return result; +} + +std::ostream &Configuration::operator<<(std::ostream &os, Level level) +{ +    switch (level) { +    case Basic:     return os << "Basic"; +    case Advanced:  return os << "Advanced"; +    case Expert:    return os << "Expert"; +    case Invisible: return os << "Invisible"; +    case Internal:  return os << "Internal"; +    case NumLevels: ; +    } +    return os << "<unknown>"; +} + +std::ostream &Configuration::operator<<(std::ostream &os, Type type) +{ +    switch (type) { +    case NoType:              return os << "None"; +    case StringType:          return os << "String"; +    case IntegerType:         return os << "Integer"; +    case UnsignedIntegerType: return os << "UnsignedInteger"; +    case FilenameType:        return os << "Filename"; +    case LdapServerType:      return os << "LdapServer"; +    case KeyFingerprintType:  return os << "KeyFingerprint"; +    case PublicKeyType:       return os << "PublicKey"; +    case SecretKeyType:       return os << "SecretKey"; +    case AliasListType:       return os << "AliasList"; +    case MaxType: ; +    } +    return os << "<unknown>"; +} + +std::ostream &Configuration::operator<<(std::ostream &os, Flag f) +{ +    unsigned int flags = f; +    std::vector<const char *> s; +    if (flags & Group) { +        s.push_back("Group"); +    } +    if (flags & Optional) { +        s.push_back("Optional"); +    } +    if (flags & List) { +        s.push_back("List"); +    } +    if (flags & Runtime) { +        s.push_back("Runtime"); +    } +    if (flags & Default) { +        s.push_back("Default"); +    } +    if (flags & DefaultDescription) { +        s.push_back("DefaultDescription"); +    } +    if (flags & NoArgumentDescription) { +        s.push_back("NoArgumentDescription"); +    } +    if (flags & NoChange) { +        s.push_back("NoChange"); +    } +    flags &= ~(Group | Optional | List | Runtime | Default | DefaultDescription | NoArgumentDescription | NoChange); +    if (flags) { +        s.push_back("other flags("); +    } +    std::copy(s.begin(), s.end(), +              std::ostream_iterator<const char *>(os, "|")); +    if (flags) { +        os << flags << ')'; +    } +    return os; +} + +std::ostream &Configuration::operator<<(std::ostream &os, const Component &c) +{ +    os << "Component[" +       << "\n  name       : " << protect(c.name()) +       << "\n  description: " << protect(c.description()) +       << "\n  programName: " << protect(c.programName()) +       << "\n  options    : \n"; +    const std::vector<Option> options = c.options(); +    std::copy(options.begin(), options.end(), +              std::ostream_iterator<Option>(os, "\n")); +    os << "\n]"; +    return os; +} + +std::ostream &Configuration::operator<<(std::ostream &os, const Option &o) +{ +    return os << "Option[" +           << "\n  name:       : " << protect(o.name()) +           << "\n  description : " << protect(o.description()) +           << "\n  argName     : " << protect(o.argumentName()) +           << "\n  flags       : " << static_cast<Flag>(o.flags()) +           << "\n  level       : " << o.level() +           << "\n  type        : " << o.type() +           << "\n  alt_type    : " << o.alternateType() +           << "\n  default_val : " << o.defaultValue() +           << "\n  default_desc: " << protect(o.defaultDescription()) +           << "\n  no_arg_value: " << o.noArgumentValue() +           << "\n  no_arg_desc : " << protect(o.noArgumentDescription()) +           << "\n  active_value: " << o.activeValue() +           << "\n  new_value   : " << o.newValue() +           << "\n  --> cur_val : " << o.currentValue() +           << "\n  set         : " << o.set() +           << "\n  dirty       : " << o.dirty() +           << "\n]" +           ; +} + +std::ostream &Configuration::operator<<(std::ostream &os, const Argument &a) +{ +    const Option o = a.parent(); +    const bool list = o.flags() & List; +    os << "Argument["; +    if (a) { +        switch (o.alternateType()) { +        case NoType: +            if (list) { +                os << a.numberOfTimesSet() << 'x'; +            } else { +                os << a.boolValue(); +            } +            break; +        default: +        case StringType: +            if (list) { +                const std::vector<const char *> v = a.stringValues(); +                os << v.size() << ':'; +                // can't use std::copy + ostream_iterator here, since we need the protect() call +                bool first = true; +                BOOST_FOREACH(const char *s, v) { +                    if (first) { +                        first = false; +                    } else { +                        os << ','; +                    } +                    os << protect(s); +                } +            } else { +                os << protect(a.stringValue()); +            } +            break; +        case IntegerType: +            if (list) { +                const std::vector<int> v = a.intValues(); +                os << v.size() << ':'; +                std::copy(v.begin(), v.end(), +                          std::ostream_iterator<int>(os, ",")); +            } else { +                os << a.intValue(); +            } +            break; +        case UnsignedIntegerType: +            if (list) { +                const std::vector<unsigned int> v = a.uintValues(); +                os << v.size() << ':'; +                std::copy(v.begin(), v.end(), +                          std::ostream_iterator<unsigned int>(os, ",")); +            } else { +                os << a.intValue(); +            } +            break; +        } +    } +    return os << ']'; +} | 
