LCOV - code coverage report
Current view: top level - lang/cpp/src - configuration.cpp (source / functions) Hit Total Coverage
Test: coverage.info Lines: 198 375 52.8 %
Date: 2017-03-02 17:11:10 Functions: 40 71 56.3 %

          Line data    Source code
       1             : /*
       2             :   configuration.cpp - wraps gpgme configuration components
       3             :   Copyright (C) 2010 Klarälvdalens Datakonsult AB
       4             : 
       5             :   This file is part of GPGME++.
       6             : 
       7             :   GPGME++ is free software; you can redistribute it and/or
       8             :   modify it under the terms of the GNU Library General Public
       9             :   License as published by the Free Software Foundation; either
      10             :   version 2 of the License, or (at your option) any later version.
      11             : 
      12             :   GPGME++ is distributed in the hope that it will be useful,
      13             :   but WITHOUT ANY WARRANTY; without even the implied warranty of
      14             :   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
      15             :   GNU Library General Public License for more details.
      16             : 
      17             :   You should have received a copy of the GNU Library General Public License
      18             :   along with GPGME++; see the file COPYING.LIB.  If not, write to the
      19             :   Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
      20             :   Boston, MA 02110-1301, USA.
      21             : */
      22             : 
      23             : #ifdef HAVE_CONFIG_H
      24             :  #include "config.h"
      25             : #endif
      26             : 
      27             : #include "configuration.h"
      28             : #include "error.h"
      29             : #include "util.h"
      30             : 
      31             : #include <gpgme.h>
      32             : 
      33             : #include <iterator>
      34             : #include <algorithm>
      35             : #include <ostream>
      36             : #include <cstring>
      37             : #include <assert.h>
      38             : 
      39             : using namespace GpgME;
      40             : using namespace GpgME::Configuration;
      41             : 
      42             : typedef std::shared_ptr< std::remove_pointer<gpgme_conf_opt_t>::type > shared_gpgme_conf_opt_t;
      43             : typedef std::weak_ptr< std::remove_pointer<gpgme_conf_opt_t>::type > weak_gpgme_conf_opt_t;
      44             : 
      45             : typedef std::shared_ptr< std::remove_pointer<gpgme_conf_arg_t>::type > shared_gpgme_conf_arg_t;
      46             : typedef std::weak_ptr< std::remove_pointer<gpgme_conf_arg_t>::type > weak_gpgme_conf_arg_t;
      47             : 
      48             : typedef std::shared_ptr< std::remove_pointer<gpgme_ctx_t>::type > shared_gpgme_ctx_t;
      49             : typedef std::weak_ptr< std::remove_pointer<gpgme_ctx_t>::type > weak_gpgme_ctx_t;
      50             : 
      51             : namespace
      52             : {
      53             : struct nodelete {
      54             :     template <typename T> void operator()(T *) {}
      55             : };
      56             : }
      57             : 
      58             : // static
      59          21 : std::vector<Component> Component::load(Error &returnedError)
      60             : {
      61             : 
      62             :     //
      63             :     // 1. get a context:
      64             :     //
      65          21 :     gpgme_ctx_t ctx_native = 0;
      66          21 :     if (const gpgme_error_t err = gpgme_new(&ctx_native)) {
      67           0 :         returnedError = Error(err);
      68           0 :         return std::vector<Component>();
      69             :     }
      70          42 :     const shared_gpgme_ctx_t ctx(ctx_native, &gpgme_release);
      71             : 
      72             :     //
      73             :     // 2. load the config:
      74             :     //
      75          21 :     gpgme_conf_comp_t conf_list_native = 0;
      76          21 :     if (const gpgme_error_t err = gpgme_op_conf_load(ctx_native, &conf_list_native)) {
      77           0 :         returnedError = Error(err);
      78           0 :         return std::vector<Component>();
      79             :     }
      80          42 :     shared_gpgme_conf_comp_t head(conf_list_native, &gpgme_conf_release);
      81             : 
      82             :     //
      83             :     // 3. convert to vector<Component>:
      84             :     //
      85          42 :     std::vector<Component> result;
      86             : 
      87         273 :     while (head) {
      88             :         // secure 'head->next' (if any) against memleaks:
      89         252 :         shared_gpgme_conf_comp_t next;
      90         126 :         if (head->next) {
      91         105 :             next.reset(head->next, &gpgme_conf_release);
      92             :         }
      93             : 
      94             :         // now prevent double-free of next.get() and following:
      95         126 :         head->next = 0;
      96             : 
      97             :         // now add a new Component to 'result' (may throw):
      98         126 :         result.resize(result.size() + 1);
      99         126 :         result.back().comp.swap(head);   // .comp = std::move( head );
     100         126 :         head.swap(next);                 //  head = std::move( next );
     101             :     }
     102             : 
     103          21 :     return result;
     104             : }
     105             : 
     106         120 : Error Component::save() const
     107             : {
     108             : 
     109         120 :     if (isNull()) {
     110           0 :         return Error(make_error(GPG_ERR_INV_ARG));
     111             :     }
     112             : 
     113             :     //
     114             :     // 1. get a context:
     115             :     //
     116         120 :     gpgme_ctx_t ctx_native = 0;
     117         120 :     if (const gpgme_error_t err = gpgme_new(&ctx_native)) {
     118           0 :         return Error(err);
     119             :     }
     120         240 :     const shared_gpgme_ctx_t ctx(ctx_native, &gpgme_release);
     121             : 
     122             :     //
     123             :     // 2. save the config:
     124             :     //
     125         120 :     return Error(gpgme_op_conf_save(ctx.get(), comp.get()));
     126             : }
     127             : 
     128         252 : const char *Component::name() const
     129             : {
     130         252 :     return comp ? comp->name : 0 ;
     131             : }
     132             : 
     133         126 : const char *Component::description() const
     134             : {
     135         126 :     return comp ? comp->description : 0 ;
     136             : }
     137             : 
     138         126 : const char *Component::programName() const
     139             : {
     140         126 :     return comp ? comp->program_name : 0 ;
     141             : }
     142             : 
     143           0 : Option Component::option(unsigned int idx) const
     144             : {
     145           0 :     gpgme_conf_opt_t opt = 0;
     146           0 :     if (comp) {
     147           0 :         opt = comp->options;
     148             :     }
     149           0 :     while (opt && idx) {
     150           0 :         opt = opt->next;
     151           0 :         --idx;
     152             :     }
     153           0 :     if (opt) {
     154           0 :         return Option(comp, opt);
     155             :     }
     156           0 :     return Option();
     157             : }
     158             : 
     159           0 : Option Component::option(const char *name) const
     160             : {
     161           0 :     gpgme_conf_opt_t opt = 0;
     162           0 :     if (comp) {
     163           0 :         opt = comp->options;
     164             :     }
     165             :     using namespace std; // for strcmp
     166           0 :     while (opt && strcmp(name, opt->name) != 0) {
     167           0 :         opt = opt->next;
     168             :     }
     169           0 :     if (opt) {
     170           0 :         return Option(comp, opt);
     171             :     }
     172           0 :     return Option();
     173             : }
     174             : 
     175           0 : unsigned int Component::numOptions() const
     176             : {
     177           0 :     unsigned int result = 0;
     178           0 :     for (gpgme_conf_opt_t opt = comp ? comp->options : 0 ; opt ; opt = opt->next) {
     179           0 :         ++result;
     180             :     }
     181           0 :     return result;
     182             : }
     183             : 
     184         252 : std::vector<Option> Component::options() const
     185             : {
     186         252 :     std::vector<Option> result;
     187        5250 :     for (gpgme_conf_opt_t opt = comp ? comp->options : 0 ; opt ; opt = opt->next) {
     188        4998 :         result.push_back(Option(comp, opt));
     189             :     }
     190         252 :     return result;
     191             : }
     192             : 
     193       12525 : static gpgme_conf_arg_t mygpgme_conf_arg_copy(gpgme_conf_arg_t other, gpgme_conf_type_t type)
     194             : {
     195       12525 :     gpgme_conf_arg_t result = 0, last = 0;
     196       13573 :     for (gpgme_conf_arg_t a = other ; a ; a = a->next) {
     197        1048 :         gpgme_conf_arg_t arg = 0;
     198             :         const gpgme_error_t err
     199        2096 :             = gpgme_conf_arg_new(&arg, type,
     200        2096 :                                  a->no_arg                 ? 0 :
     201             :                                  type == GPGME_CONF_STRING ? a->value.string :
     202        1048 :                                  /* else */                  static_cast<void *>(&a->value));
     203        1048 :         if (err) {
     204           0 :             gpgme_conf_arg_release(result, type);
     205           0 :             return 0;
     206             :         }
     207        1048 :         assert(arg);
     208        1048 :         if (result) {
     209          42 :             last->next = arg;
     210             :         } else {
     211        1006 :             result = arg;
     212             :         }
     213        1048 :         last = arg;
     214             :     }
     215       12525 :     return result;
     216             : }
     217             : 
     218           0 : Component Option::parent() const
     219             : {
     220           0 :     return Component(comp.lock());
     221             : }
     222             : 
     223       17543 : unsigned int Option::flags() const
     224             : {
     225       17543 :     return isNull() ? 0 : opt->flags;
     226             : }
     227             : 
     228        2499 : Level Option::level() const
     229             : {
     230        2499 :     return isNull() ? Internal : static_cast<Level>(opt->level) ;
     231             : }
     232             : 
     233        4998 : const char *Option::name() const
     234             : {
     235        4998 :     return isNull() ? 0 : opt->name ;
     236             : }
     237             : 
     238        2499 : const char *Option::description() const
     239             : {
     240        2499 :     return isNull() ? 0 : opt->description ;
     241             : }
     242             : 
     243        2499 : const char *Option::argumentName() const
     244             : {
     245        2499 :     return isNull() ? 0 : opt->argname ;
     246             : }
     247             : 
     248        2519 : Type Option::type() const
     249             : {
     250        2519 :     return isNull() ? NoType : static_cast<Type>(opt->type) ;
     251             : }
     252             : 
     253        3535 : Type Option::alternateType() const
     254             : {
     255        3535 :     return isNull() ? NoType : static_cast<Type>(opt->alt_type) ;
     256             : }
     257             : 
     258             : #if 0
     259             : static Option::Variant argument_to_variant(gpgme_conf_type_t type, bool list, gpgme_conf_arg_t arg)
     260             : {
     261             :     assert(arg);
     262             :     switch (type) {
     263             :     case GPGME_CONF_NONE:
     264             :         if (list) {
     265             :             // return the count (number of times set):
     266             :             return arg->value.count;
     267             :         } else {
     268             :             return none;
     269             :         }
     270             :     case GPGME_CONF_INT32:
     271             :         if (list) {
     272             :             std::vector<int> result;
     273             :             for (gpgme_conf_arg_t a = arg ; a ; a = a->next) {
     274             :                 result.push_back(a->value.int32);
     275             :             }
     276             :             return result;
     277             :         } else {
     278             :             return arg->value.int32;
     279             :         }
     280             :     case GPGME_CONF_UINT32:
     281             :         if (list) {
     282             :             std::vector<unsigned int> result;
     283             :             for (gpgme_conf_arg_t a = arg ; a ; a = a->next) {
     284             :                 result.push_back(a->value.uint32);
     285             :             }
     286             :             return result;
     287             :         } else {
     288             :             return arg->value.uint32;
     289             :         }
     290             :     case GPGME_CONF_FILENAME:
     291             :     case GPGME_CONF_LDAP_SERVER:
     292             :     case GPGME_CONF_KEY_FPR:
     293             :     case GPGME_CONF_PUB_KEY:
     294             :     case GPGME_CONF_SEC_KEY:
     295             :     case GPGME_CONF_ALIAS_LIST:
     296             :     // these should not happen in alt_type, but fall through
     297             :     case GPGME_CONF_STRING:
     298             :         if (list) {
     299             :             std::vector<const char *> result;
     300             :             for (gpgme_conf_arg_t a = arg ; a ; a = a->next) {
     301             :                 result.push_back(a->value.string);
     302             :             }
     303             :             return result;
     304             :         } else {
     305             :             return arg->value.string;
     306             :         }
     307             :     }
     308             :     assert(!"Option: unknown alt_type!");
     309             :     return Option::Variant();
     310             : }
     311             : 
     312             : namespace
     313             : {
     314             : inline const void *to_void_star(const char *s)
     315             : {
     316             :     return s;
     317             : }
     318             : inline const void *to_void_star(const std::string &s)
     319             : {
     320             :     return s.c_str();
     321             : }
     322             : inline const void *to_void_star(const int &i)
     323             : {
     324             :     return &i;    // const-&: sic!
     325             : }
     326             : inline const void *to_void_star(const unsigned int &i)
     327             : {
     328             :     return &i;    // const-&: sic!
     329             : }
     330             : 
     331             : struct VariantToArgumentVisitor : boost::static_visitor<gpgme_conf_arg_t> {
     332             :     static gpgme_conf_arg_t make_argument(gpgme_conf_type_t type, const void *value)
     333             :     {
     334             :         gpgme_conf_arg_t arg = 0;
     335             : #ifdef HAVE_GPGME_CONF_ARG_NEW_WITH_CONST_VALUE
     336             :         if (const gpgme_error_t err = gpgme_conf_arg_new(&arg, type, value)) {
     337             :             return 0;
     338             :         }
     339             : #else
     340             :         if (const gpgme_error_t err = gpgme_conf_arg_new(&arg, type, const_cast<void *>(value))) {
     341             :             return 0;
     342             :         }
     343             : #endif
     344             :         else {
     345             :             return arg;
     346             :         }
     347             :     }
     348             : 
     349             :     gpgme_conf_arg_t operator()(bool v) const
     350             :     {
     351             :         return v ? make_argument(0) : 0 ;
     352             :     }
     353             : 
     354             :     gpgme_conf_arg_t operator()(const char *s) const
     355             :     {
     356             :         return make_argument(s ? s : "");
     357             :     }
     358             : 
     359             :     gpgme_conf_arg_t operator()(const std::string &s) const
     360             :     {
     361             :         return operator()(s.c_str());
     362             :     }
     363             : 
     364             :     gpgme_conf_arg_t operator()(int i) const
     365             :     {
     366             :         return make_argument(&i);
     367             :     }
     368             : 
     369             :     gpgme_conf_arg_t operator()(unsigned int i) const
     370             :     {
     371             :         return make_argument(&i);
     372             :     }
     373             : 
     374             :     template <typename T>
     375             :     gpgme_conf_arg_t operator()(const std::vector<T> &value) const
     376             :     {
     377             :         gpgme_conf_arg_t result = 0;
     378             :         gpgme_conf_arg_t last = 0;
     379             :         for (typename std::vector<T>::const_iterator it = value.begin(), end = value.end() ; it != end ; ++it) {
     380             :             if (gpgme_conf_arg_t arg = make_argument(to_void_star(*it))) {
     381             :                 if (last) {
     382             :                     last = last->next = arg;
     383             :                 } else {
     384             :                     result = last = arg;
     385             :                 }
     386             :             }
     387             :         }
     388             :         return result;
     389             :     }
     390             : 
     391             : };
     392             : }
     393             : 
     394             : static gpgme_conf_arg_t variant_to_argument(const Option::Variant &value)
     395             : {
     396             :     VariantToArgumentVisitor v;
     397             :     return apply_visitor(v, value);
     398             : }
     399             : 
     400             : optional<Option::Variant> Option::defaultValue() const
     401             : {
     402             :     if (isNull()) {
     403             :         return optional<Variant>();
     404             :     } else {
     405             :         return argument_to_variant(opt->alt_type, opt->flags & GPGME_CONF_LIST, opt->default_value);
     406             :     }
     407             : }
     408             : #endif
     409             : 
     410        2499 : Argument Option::defaultValue() const
     411             : {
     412        2499 :     if (isNull()) {
     413           0 :         return Argument();
     414             :     } else {
     415        2499 :         return Argument(comp.lock(), opt, opt->default_value, false);
     416             :     }
     417             : }
     418             : 
     419        2499 : const char *Option::defaultDescription() const
     420             : {
     421        2499 :     return isNull() ? 0 : opt->default_description ;
     422             : }
     423             : 
     424        2499 : Argument Option::noArgumentValue() const
     425             : {
     426        2499 :     if (isNull()) {
     427           0 :         return Argument();
     428             :     } else {
     429        2499 :         return Argument(comp.lock(), opt, opt->no_arg_value, false);
     430             :     }
     431             : }
     432             : 
     433        2499 : const char *Option::noArgumentDescription() const
     434             : {
     435        2499 :     return isNull() ? 0 : opt->no_arg_description ;
     436             : }
     437             : 
     438        2499 : Argument Option::activeValue() const
     439             : {
     440        2499 :     if (isNull()) {
     441           0 :         return Argument();
     442             :     } else {
     443        2499 :         return Argument(comp.lock(), opt, opt->value, false);
     444             :     }
     445             : }
     446             : 
     447        2519 : Argument Option::currentValue() const
     448             : {
     449        2519 :     if (isNull()) {
     450           0 :         return Argument();
     451             :     }
     452             :     const gpgme_conf_arg_t arg =
     453        5038 :         opt->change_value ? opt->new_value ? opt->new_value : opt->default_value :
     454        5018 :         opt->value        ? opt->value :
     455        5018 :         /* else */          opt->default_value ;
     456        2519 :     return Argument(comp.lock(), opt, arg, false);
     457             : }
     458             : 
     459        2499 : Argument Option::newValue() const
     460             : {
     461        2499 :     if (isNull()) {
     462           0 :         return Argument();
     463             :     } else {
     464        2499 :         return Argument(comp.lock(), opt, opt->new_value, false);
     465             :     }
     466             : }
     467             : 
     468        2499 : bool Option::set() const
     469             : {
     470        2499 :     if (isNull()) {
     471           0 :         return false;
     472        2499 :     } else if (opt->change_value) {
     473           0 :         return opt->new_value;
     474             :     } else {
     475        2499 :         return opt->value;
     476             :     }
     477             : }
     478             : 
     479        2499 : bool Option::dirty() const
     480             : {
     481        2499 :     return !isNull() && opt->change_value ;
     482             : }
     483             : 
     484          10 : Error Option::setNewValue(const Argument &argument)
     485             : {
     486          10 :     if (isNull()) {
     487           0 :         return Error(make_error(GPG_ERR_INV_ARG));
     488          10 :     } else if (argument.isNull()) {
     489           0 :         return resetToDefaultValue();
     490          10 :     } else if (const gpgme_conf_arg_t arg = mygpgme_conf_arg_copy(argument.arg, opt->alt_type)) {
     491          10 :         return Error(gpgme_conf_opt_change(opt, 0, arg));
     492             :     } else {
     493           0 :         return Error(make_error(GPG_ERR_ENOMEM));
     494             :     }
     495             : }
     496             : 
     497           0 : Error Option::resetToActiveValue()
     498             : {
     499           0 :     if (isNull()) {
     500           0 :         return Error(make_error(GPG_ERR_INV_ARG));
     501             :     } else {
     502           0 :         return Error(gpgme_conf_opt_change(opt, 1, 0));
     503             :     }
     504             : }
     505             : 
     506          10 : Error Option::resetToDefaultValue()
     507             : {
     508          10 :     if (isNull()) {
     509           0 :         return Error(make_error(GPG_ERR_INV_ARG));
     510             :     } else {
     511          10 :         return Error(gpgme_conf_opt_change(opt, 0, 0));
     512             :     }
     513             : }
     514             : 
     515          10 : static gpgme_conf_arg_t make_argument(gpgme_conf_type_t type, const void *value)
     516             : {
     517          10 :     gpgme_conf_arg_t arg = 0;
     518          10 :     if (const gpgme_error_t err = gpgme_conf_arg_new(&arg, type, value)) {
     519           0 :         return 0;
     520             :     } else {
     521          10 :         return arg;
     522             :     }
     523             : }
     524             : 
     525           0 : Argument Option::createNoneArgument(bool set) const
     526             : {
     527           0 :     if (isNull() || alternateType() != NoType) {
     528           0 :         return Argument();
     529             :     } else {
     530           0 :         if (set) {
     531           0 :             return createNoneListArgument(1);
     532             :         }
     533             :     }
     534           0 :     return Argument();
     535             : }
     536             : 
     537          10 : Argument Option::createStringArgument(const char *value) const
     538             : {
     539          10 :     if (isNull() || alternateType() != StringType) {
     540           0 :         return Argument();
     541             :     } else {
     542          10 :         return Argument(comp.lock(), opt, make_argument(GPGME_CONF_STRING, value), true);
     543             :     }
     544             : }
     545             : 
     546           0 : Argument Option::createStringArgument(const std::string &value) const
     547             : {
     548           0 :     if (isNull() || alternateType() != StringType) {
     549           0 :         return Argument();
     550             :     } else {
     551           0 :         return Argument(comp.lock(), opt, make_argument(GPGME_CONF_STRING, value.c_str()), true);
     552             :     }
     553             : }
     554             : 
     555           0 : Argument Option::createIntArgument(int value) const
     556             : {
     557           0 :     if (isNull() || alternateType() != IntegerType) {
     558           0 :         return Argument();
     559             :     } else {
     560           0 :         return Argument(comp.lock(), opt, make_argument(GPGME_CONF_INT32, &value), true);
     561             :     }
     562             : }
     563             : 
     564           0 : Argument Option::createUIntArgument(unsigned int value) const
     565             : {
     566           0 :     if (isNull() || alternateType() != UnsignedIntegerType) {
     567           0 :         return Argument();
     568             :     } else {
     569           0 :         return Argument(comp.lock(), opt, make_argument(GPGME_CONF_UINT32, &value), true);
     570             :     }
     571             : }
     572             : 
     573             : namespace
     574             : {
     575           0 : const void *to_void_star(const char *s)
     576             : {
     577           0 :     return s;
     578             : }
     579           0 : const void *to_void_star(const std::string &s)
     580             : {
     581           0 :     return s.c_str();
     582             : }
     583           0 : const void *to_void_star(const int &i)
     584             : {
     585           0 :     return &i;    // const-&: sic!
     586             : }
     587           0 : const void *to_void_star(const unsigned int &i)
     588             : {
     589           0 :     return &i;    // const-&: sic!
     590             : }
     591             : 
     592             : template <typename T>
     593           0 : gpgme_conf_arg_t make_argument(gpgme_conf_type_t type, const std::vector<T> &value)
     594             : {
     595           0 :     gpgme_conf_arg_t result = 0;
     596           0 :     gpgme_conf_arg_t last = 0;
     597           0 :     for (typename std::vector<T>::const_iterator it = value.begin(), end = value.end() ; it != end ; ++it) {
     598           0 :         if (gpgme_conf_arg_t arg = make_argument(type, to_void_star(*it))) {
     599           0 :             if (last) {
     600           0 :                 last = last->next = arg;
     601             :             } else {
     602           0 :                 result = last = arg;
     603             :             }
     604             :         }
     605             :     }
     606           0 :     return result;
     607             : }
     608             : }
     609             : 
     610           0 : Argument Option::createNoneListArgument(unsigned int value) const
     611             : {
     612           0 :     if (value) {
     613           0 :         return Argument(comp.lock(), opt, make_argument(GPGME_CONF_NONE, &value), true);
     614             :     }
     615           0 :     return Argument();
     616             : }
     617             : 
     618           0 : Argument Option::createStringListArgument(const std::vector<const char *> &value) const
     619             : {
     620           0 :     return Argument(comp.lock(), opt, make_argument(GPGME_CONF_STRING, value), true);
     621             : }
     622             : 
     623           0 : Argument Option::createStringListArgument(const std::vector<std::string> &value) const
     624             : {
     625           0 :     return Argument(comp.lock(), opt, make_argument(GPGME_CONF_STRING, value), true);
     626             : }
     627             : 
     628           0 : Argument Option::createIntListArgument(const std::vector<int> &value) const
     629             : {
     630           0 :     return Argument(comp.lock(), opt, make_argument(GPGME_CONF_INT32, value), true);
     631             : }
     632             : 
     633           0 : Argument Option::createUIntListArgument(const std::vector<unsigned int> &value) const
     634             : {
     635           0 :     return Argument(comp.lock(), opt, make_argument(GPGME_CONF_UINT32, value), true);
     636             : }
     637             : 
     638       12525 : Argument::Argument(const shared_gpgme_conf_comp_t &comp, gpgme_conf_opt_t opt, gpgme_conf_arg_t arg, bool owns)
     639             :     : comp(comp),
     640             :       opt(opt),
     641       12525 :       arg(owns ? arg : mygpgme_conf_arg_copy(arg, opt ? opt->alt_type : GPGME_CONF_NONE))
     642             : {
     643             : 
     644       12525 : }
     645             : 
     646             : #if 0
     647             : Argument::Argument(const shared_gpgme_conf_comp_t &comp, gpgme_conf_opt_t opt, gpgme_conf_arg_t arg)
     648             :     : comp(comp),
     649             :       opt(opt),
     650             :       arg(mygpgme_conf_arg_copy(arg, opt ? opt->alt_type : GPGME_CONF_NONE))
     651             : {
     652             : 
     653             : }
     654             : #endif
     655             : 
     656           0 : Argument::Argument(const Argument &other)
     657             :     : comp(other.comp),
     658           0 :       opt(other.opt),
     659           0 :       arg(mygpgme_conf_arg_copy(other.arg, opt ? opt->alt_type : GPGME_CONF_NONE))
     660             : {
     661             : 
     662           0 : }
     663             : 
     664       25050 : Argument::~Argument()
     665             : {
     666       12525 :     gpgme_conf_arg_release(arg, opt ? opt->alt_type : GPGME_CONF_NONE);
     667       12525 : }
     668             : 
     669       12495 : Option Argument::parent() const
     670             : {
     671       12495 :     return Option(comp.lock(), opt);
     672             : }
     673             : 
     674           0 : bool Argument::boolValue() const
     675             : {
     676           0 :     return numberOfTimesSet();
     677             : }
     678             : 
     679           0 : unsigned int Argument::numElements() const
     680             : {
     681           0 :     if (isNull()) {
     682           0 :         return 0;
     683             :     }
     684           0 :     unsigned int result = 0;
     685           0 :     for (gpgme_conf_arg_t a = arg ; a ; a = a->next) {
     686           0 :         ++result;
     687             :     }
     688           0 :     return result;
     689             : }
     690             : 
     691         460 : const char *Argument::stringValue(unsigned int idx) const
     692             : {
     693         460 :     if (isNull() || opt->alt_type != GPGME_CONF_STRING) {
     694          10 :         return 0;
     695             :     }
     696         450 :     gpgme_conf_arg_t a = arg;
     697         450 :     while (a && idx) {
     698           0 :         a = a->next;
     699           0 :         --idx;
     700             :     }
     701         450 :     return a ? a->value.string : 0 ;
     702             : }
     703             : 
     704         546 : int Argument::intValue(unsigned int idx) const
     705             : {
     706         546 :     if (isNull() || opt->alt_type != GPGME_CONF_INT32) {
     707         462 :         return 0;
     708             :     }
     709          84 :     gpgme_conf_arg_t a = arg;
     710          84 :     while (a && idx) {
     711           0 :         a = a->next;
     712           0 :         --idx;
     713             :     }
     714          84 :     return a ? a->value.int32 : 0 ;
     715             : }
     716             : 
     717           0 : unsigned int Argument::uintValue(unsigned int idx) const
     718             : {
     719           0 :     if (isNull() || opt->alt_type != GPGME_CONF_UINT32) {
     720           0 :         return 0;
     721             :     }
     722           0 :     gpgme_conf_arg_t a = arg;
     723           0 :     while (a && idx) {
     724           0 :         a = a->next;
     725           0 :         --idx;
     726             :     }
     727           0 :     return a ? a->value.uint32 : 0 ;
     728             : }
     729             : 
     730           0 : unsigned int Argument::numberOfTimesSet() const
     731             : {
     732           0 :     if (isNull() || opt->alt_type != GPGME_CONF_NONE) {
     733           0 :         return 0;
     734             :     }
     735           0 :     return arg->value.count;
     736             : }
     737             : 
     738           0 : std::vector<const char *> Argument::stringValues() const
     739             : {
     740           0 :     if (isNull() || opt->alt_type != GPGME_CONF_STRING) {
     741           0 :         return std::vector<const char *>();
     742             :     }
     743           0 :     std::vector<const char *> result;
     744           0 :     for (gpgme_conf_arg_t a = arg ; a ; a = a->next) {
     745           0 :         result.push_back(a->value.string);
     746             :     }
     747           0 :     return result;
     748             : }
     749             : 
     750           0 : std::vector<int> Argument::intValues() const
     751             : {
     752           0 :     if (isNull() || opt->alt_type != GPGME_CONF_INT32) {
     753           0 :         return std::vector<int>();
     754             :     }
     755           0 :     std::vector<int> result;
     756           0 :     for (gpgme_conf_arg_t a = arg ; a ; a = a->next) {
     757           0 :         result.push_back(a->value.int32);
     758             :     }
     759           0 :     return result;
     760             : }
     761             : 
     762           0 : std::vector<unsigned int> Argument::uintValues() const
     763             : {
     764           0 :     if (isNull() || opt->alt_type != GPGME_CONF_UINT32) {
     765           0 :         return std::vector<unsigned int>();
     766             :     }
     767           0 :     std::vector<unsigned int> result;
     768           0 :     for (gpgme_conf_arg_t a = arg ; a ; a = a->next) {
     769           0 :         result.push_back(a->value.uint32);
     770             :     }
     771           0 :     return result;
     772             : }
     773             : 
     774        2499 : std::ostream &Configuration::operator<<(std::ostream &os, Level level)
     775             : {
     776        2499 :     switch (level) {
     777        1134 :     case Basic:     return os << "Basic";
     778         861 :     case Advanced:  return os << "Advanced";
     779         315 :     case Expert:    return os << "Expert";
     780         189 :     case Invisible: return os << "Invisible";
     781           0 :     case Internal:  return os << "Internal";
     782             :     case NumLevels: ;
     783             :     }
     784           0 :     return os << "<unknown>";
     785             : }
     786             : 
     787        4998 : std::ostream &Configuration::operator<<(std::ostream &os, Type type)
     788             : {
     789        4998 :     switch (type) {
     790        2940 :     case NoType:              return os << "None";
     791        1281 :     case StringType:          return os << "String";
     792          84 :     case IntegerType:         return os << "Integer";
     793         504 :     case UnsignedIntegerType: return os << "UnsignedInteger";
     794         126 :     case FilenameType:        return os << "Filename";
     795          42 :     case LdapServerType:      return os << "LdapServer";
     796           0 :     case KeyFingerprintType:  return os << "KeyFingerprint";
     797           0 :     case PublicKeyType:       return os << "PublicKey";
     798           0 :     case SecretKeyType:       return os << "SecretKey";
     799          21 :     case AliasListType:       return os << "AliasList";
     800             :     case MaxType: ;
     801             :     }
     802           0 :     return os << "<unknown>";
     803             : }
     804             : 
     805        2499 : std::ostream &Configuration::operator<<(std::ostream &os, Flag f)
     806             : {
     807        2499 :     unsigned int flags = f;
     808        4998 :     std::vector<const char *> s;
     809        2499 :     if (flags & Group) {
     810         567 :         s.push_back("Group");
     811             :     }
     812        2499 :     if (flags & Optional) {
     813         168 :         s.push_back("Optional");
     814             :     }
     815        2499 :     if (flags & List) {
     816         168 :         s.push_back("List");
     817             :     }
     818        2499 :     if (flags & Runtime) {
     819         693 :         s.push_back("Runtime");
     820             :     }
     821        2499 :     if (flags & Default) {
     822         567 :         s.push_back("Default");
     823             :     }
     824        2499 :     if (flags & DefaultDescription) {
     825           0 :         s.push_back("DefaultDescription");
     826             :     }
     827        2499 :     if (flags & NoArgumentDescription) {
     828           0 :         s.push_back("NoArgumentDescription");
     829             :     }
     830        2499 :     if (flags & NoChange) {
     831          42 :         s.push_back("NoChange");
     832             :     }
     833        2499 :     flags &= ~(Group | Optional | List | Runtime | Default | DefaultDescription | NoArgumentDescription | NoChange);
     834        2499 :     if (flags) {
     835           0 :         s.push_back("other flags(");
     836             :     }
     837             :     std::copy(s.begin(), s.end(),
     838        2499 :               std::ostream_iterator<const char *>(os, "|"));
     839        2499 :     if (flags) {
     840           0 :         os << flags << ')';
     841             :     }
     842        4998 :     return os;
     843             : }
     844             : 
     845         126 : std::ostream &Configuration::operator<<(std::ostream &os, const Component &c)
     846             : {
     847             :     os << "Component["
     848             :        << "\n  name       : " << protect(c.name())
     849             :        << "\n  description: " << protect(c.description())
     850             :        << "\n  programName: " << protect(c.programName())
     851         126 :        << "\n  options    : \n";
     852         252 :     const std::vector<Option> options = c.options();
     853             :     std::copy(options.begin(), options.end(),
     854         126 :               std::ostream_iterator<Option>(os, "\n"));
     855         126 :     os << "\n]";
     856         252 :     return os;
     857             : }
     858             : 
     859        2499 : std::ostream &Configuration::operator<<(std::ostream &os, const Option &o)
     860             : {
     861             :     return os << "Option["
     862             :            << "\n  name:       : " << protect(o.name())
     863             :            << "\n  description : " << protect(o.description())
     864             :            << "\n  argName     : " << protect(o.argumentName())
     865        2499 :            << "\n  flags       : " << static_cast<Flag>(o.flags())
     866        4998 :            << "\n  level       : " << o.level()
     867        4998 :            << "\n  type        : " << o.type()
     868        4998 :            << "\n  alt_type    : " << o.alternateType()
     869        7497 :            << "\n  default_val : " << o.defaultValue()
     870             :            << "\n  default_desc: " << protect(o.defaultDescription())
     871        7497 :            << "\n  no_arg_value: " << o.noArgumentValue()
     872             :            << "\n  no_arg_desc : " << protect(o.noArgumentDescription())
     873        7497 :            << "\n  active_value: " << o.activeValue()
     874        7497 :            << "\n  new_value   : " << o.newValue()
     875        7497 :            << "\n  --> cur_val : " << o.currentValue()
     876        4998 :            << "\n  set         : " << o.set()
     877        4998 :            << "\n  dirty       : " << o.dirty()
     878        4998 :            << "\n]"
     879             :            ;
     880             : }
     881             : 
     882       12495 : std::ostream &Configuration::operator<<(std::ostream &os, const Argument &a)
     883             : {
     884       24990 :     const Option o = a.parent();
     885       12495 :     const bool list = o.flags() & List;
     886       12495 :     os << "Argument[";
     887       12495 :     if (a) {
     888         986 :         switch (o.alternateType()) {
     889             :         case NoType:
     890           0 :             if (list) {
     891           0 :                 os << a.numberOfTimesSet() << 'x';
     892             :             } else {
     893           0 :                 os << a.boolValue();
     894             :             }
     895           0 :             break;
     896             :         default:
     897             :         case StringType:
     898         440 :             if (list) {
     899           0 :                 const std::vector<const char *> v = a.stringValues();
     900           0 :                 os << v.size() << ':';
     901             :                 // can't use std::copy + ostream_iterator here, since we need the protect() call
     902           0 :                 bool first = true;
     903           0 :                 std::for_each(v.begin(), v.end(), [&first, &os](const char *s) {
     904           0 :                     if (first) {
     905           0 :                         first = false;
     906             :                     } else {
     907           0 :                         os << ',';
     908             :                     }
     909           0 :                     os << protect(s);
     910           0 :                 });
     911             :             } else {
     912         440 :                 os << protect(a.stringValue());
     913             :             }
     914         440 :             break;
     915             :         case IntegerType:
     916          84 :             if (list) {
     917           0 :                 const std::vector<int> v = a.intValues();
     918           0 :                 os << v.size() << ':';
     919             :                 std::copy(v.begin(), v.end(),
     920           0 :                           std::ostream_iterator<int>(os, ","));
     921             :             } else {
     922          84 :                 os << a.intValue();
     923             :             }
     924          84 :             break;
     925             :         case UnsignedIntegerType:
     926         462 :             if (list) {
     927           0 :                 const std::vector<unsigned int> v = a.uintValues();
     928           0 :                 os << v.size() << ':';
     929             :                 std::copy(v.begin(), v.end(),
     930           0 :                           std::ostream_iterator<unsigned int>(os, ","));
     931             :             } else {
     932         462 :                 os << a.intValue();
     933             :             }
     934         462 :             break;
     935             :         }
     936             :     }
     937       24990 :     return os << ']';
     938          24 : }

Generated by: LCOV version 1.13