/* 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 "configuration.h" #include "error.h" #include "util.h" #include #include #include #include #include #include using namespace GpgME; using namespace GpgME::Configuration; typedef std::shared_ptr< std::remove_pointer::type > shared_gpgme_conf_opt_t; typedef std::weak_ptr< std::remove_pointer::type > weak_gpgme_conf_opt_t; typedef std::shared_ptr< std::remove_pointer::type > shared_gpgme_conf_arg_t; typedef std::weak_ptr< std::remove_pointer::type > weak_gpgme_conf_arg_t; typedef std::shared_ptr< std::remove_pointer::type > shared_gpgme_ctx_t; typedef std::weak_ptr< std::remove_pointer::type > weak_gpgme_ctx_t; namespace { struct nodelete { template void operator()(T *) {} }; } // static std::vector Component::load(Error &returnedError) { // // 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; } Error Component::save() const { 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())); } const char *Component::name() const { return comp ? comp->name : 0 ; } const char *Component::description() const { return comp ? comp->description : 0 ; } const char *Component::programName() const { return comp ? comp->program_name : 0 ; } Option Component::option(unsigned int idx) const { gpgme_conf_opt_t opt = 0; if (comp) { opt = comp->options; } while (opt && idx) { opt = opt->next; --idx; } if (opt) { return Option(comp, opt); } return Option(); } Option Component::option(const char *name) const { 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); } return Option(); } unsigned int Component::numOptions() const { unsigned int result = 0; for (gpgme_conf_opt_t opt = comp ? comp->options : 0 ; opt ; opt = opt->next) { ++result; } return result; } std::vector