/* 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 #include "configuration.h" #include "error.h" #include "util.h" #include #include #include #include #include #include using namespace GpgME; using namespace GpgME::Configuration; typedef boost::shared_ptr< boost::remove_pointer::type > shared_gpgme_conf_opt_t; typedef boost::weak_ptr< boost::remove_pointer::type > weak_gpgme_conf_opt_t; typedef boost::shared_ptr< boost::remove_pointer::type > shared_gpgme_conf_arg_t; typedef boost::weak_ptr< boost::remove_pointer::type > weak_gpgme_conf_arg_t; typedef boost::shared_ptr< boost::remove_pointer::type > shared_gpgme_ctx_t; typedef boost::weak_ptr< boost::remove_pointer::type > weak_gpgme_ctx_t; namespace { struct nodelete { template void operator()( T * ) {} }; } // static std::vector 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(); } 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(); } shared_gpgme_conf_comp_t head( conf_list_native, &gpgme_conf_release ); // // 3. convert to vector: // std::vector 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(); #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