LCOV - code coverage report
Current view: top level - lang/cpp/src - context.cpp (source / functions) Hit Total Coverage
Test: coverage.info Lines: 222 883 25.1 %
Date: 2018-11-14 16:53:58 Functions: 56 177 31.6 %

          Line data    Source code
       1             : /*
       2             :   context.cpp - wraps a gpgme key context
       3             :   Copyright (C) 2003, 2007 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 <context.h>
      28             : #include <eventloopinteractor.h>
      29             : #include <trustitem.h>
      30             : #include <keylistresult.h>
      31             : #include <keygenerationresult.h>
      32             : #include <importresult.h>
      33             : #include <decryptionresult.h>
      34             : #include <verificationresult.h>
      35             : #include <signingresult.h>
      36             : #include <encryptionresult.h>
      37             : #include <engineinfo.h>
      38             : #include <editinteractor.h>
      39             : #include <vfsmountresult.h>
      40             : 
      41             : #include <interfaces/assuantransaction.h>
      42             : #include <defaultassuantransaction.h>
      43             : 
      44             : #include "callbacks.h"
      45             : #include "data_p.h"
      46             : #include "context_p.h"
      47             : #include "util.h"
      48             : #include "tofuinfo.h"
      49             : 
      50             : #include <gpgme.h>
      51             : 
      52             : #include <istream>
      53             : #ifndef NDEBUG
      54             : #include <iostream>
      55             : using std::cerr;
      56             : using std::endl;
      57             : #endif
      58             : 
      59             : #include <cassert>
      60             : 
      61             : namespace GpgME
      62             : {
      63             : 
      64           0 : static inline unsigned int xtoi_1(const char *str)
      65             : {
      66           0 :     const unsigned int ch = *str;
      67             :     const unsigned int result =
      68           0 :         ch <= '9' ? ch - '0' :
      69           0 :         ch <= 'F' ? ch - 'A' + 10 :
      70           0 :         /* else */  ch - 'a' + 10 ;
      71           0 :     return result < 16 ? result : 0 ;
      72             : }
      73           0 : static inline int xtoi_2(const char *str)
      74             : {
      75           0 :     return xtoi_1(str) * 16U + xtoi_1(str + 1);
      76             : }
      77             : 
      78           0 : static void percent_unescape(std::string &s, bool plus2space)
      79             : {
      80           0 :     std::string::iterator src = s.begin(), dest = s.begin(), end = s.end();
      81           0 :     while (src != end) {
      82           0 :         if (*src == '%' && end - src > 2) {
      83           0 :             *dest++ = xtoi_2(&*++src);
      84           0 :             src += 2;
      85           0 :         } else if (*src == '+' && plus2space) {
      86           0 :             *dest++ = ' ';
      87           0 :             ++src;
      88             :         } else {
      89           0 :             *dest++ = *src++;
      90             :         }
      91             :     }
      92           0 :     s.erase(dest, end);
      93           0 : }
      94             : 
      95          16 : void initializeLibrary()
      96             : {
      97          16 :     gpgme_check_version(0);
      98          16 : }
      99             : 
     100           0 : Error initializeLibrary(int)
     101             : {
     102           0 :     if (gpgme_check_version(GPGME_VERSION)) {
     103           0 :         return Error();
     104             :     } else {
     105           0 :         return Error::fromCode(GPG_ERR_USER_1);
     106             :     }
     107             : }
     108             : 
     109          25 : static void format_error(gpgme_error_t err, std::string &str)
     110             : {
     111             :     char buffer[ 1024 ];
     112          25 :     gpgme_strerror_r(err, buffer, sizeof buffer);
     113          25 :     buffer[ sizeof buffer - 1 ] = '\0';
     114          25 :     str = buffer;
     115          25 : }
     116             : 
     117           0 : const char *Error::source() const
     118             : {
     119           0 :     return gpgme_strsource((gpgme_error_t)mErr);
     120             : }
     121             : 
     122          25 : const char *Error::asString() const
     123             : {
     124          25 :     if (mMessage.empty()) {
     125          25 :         format_error(static_cast<gpgme_error_t>(mErr), mMessage);
     126             :     }
     127          25 :     return mMessage.c_str();
     128             : }
     129             : 
     130          26 : int Error::code() const
     131             : {
     132          26 :     return gpgme_err_code(mErr);
     133             : }
     134             : 
     135           0 : int Error::sourceID() const
     136             : {
     137           0 :     return gpgme_err_source(mErr);
     138             : }
     139             : 
     140          19 : bool Error::isCanceled() const
     141             : {
     142          19 :     return code() == GPG_ERR_CANCELED;
     143             : }
     144             : 
     145           0 : int Error::toErrno() const
     146             : {
     147             : //#ifdef HAVE_GPGME_GPG_ERROR_WRAPPERS
     148           0 :     return gpgme_err_code_to_errno(static_cast<gpgme_err_code_t>(code()));
     149             : //#else
     150             : //    return gpg_err_code_to_errno( static_cast<gpg_err_code_t>( code() ) );
     151             : //#endif
     152             : }
     153             : 
     154             : // static
     155           0 : bool Error::hasSystemError()
     156             : {
     157           0 :     return gpgme_err_code_from_syserror() == GPG_ERR_MISSING_ERRNO ;
     158             : }
     159             : 
     160             : // static
     161           0 : void Error::setSystemError(gpg_err_code_t err)
     162             : {
     163           0 :     setErrno(gpgme_err_code_to_errno(err));
     164           0 : }
     165             : 
     166             : // static
     167           0 : void Error::setErrno(int err)
     168             : {
     169           0 :     gpgme_err_set_errno(err);
     170           0 : }
     171             : 
     172             : // static
     173           0 : Error Error::fromSystemError(unsigned int src)
     174             : {
     175           0 :     return Error(gpgme_err_make(static_cast<gpgme_err_source_t>(src), gpgme_err_code_from_syserror()));
     176             : }
     177             : 
     178             : // static
     179           0 : Error Error::fromErrno(int err, unsigned int src)
     180             : {
     181           0 :     return Error(gpgme_err_make(static_cast<gpgme_err_source_t>(src), gpgme_err_code_from_errno(err)));
     182             : }
     183             : 
     184             : // static
     185           1 : Error Error::fromCode(unsigned int err, unsigned int src)
     186             : {
     187           1 :     return Error(gpgme_err_make(static_cast<gpgme_err_source_t>(src), static_cast<gpgme_err_code_t>(err)));
     188             : }
     189             : 
     190          23 : std::ostream &operator<<(std::ostream &os, const Error &err)
     191             : {
     192          23 :     return os << "GpgME::Error(" << err.encodedError() << " (" << err.asString() << "))";
     193             : }
     194             : 
     195          61 : Context::Context(gpgme_ctx_t ctx) : d(new Private(ctx))
     196             : {
     197          61 : }
     198             : 
     199         183 : Context::~Context()
     200             : {
     201          61 :     delete d;
     202         122 : }
     203             : 
     204          61 : Context *Context::createForProtocol(Protocol proto)
     205             : {
     206          61 :     gpgme_ctx_t ctx = 0;
     207          61 :     if (gpgme_new(&ctx) != 0) {
     208           0 :         return 0;
     209             :     }
     210             : 
     211          61 :     switch (proto) {
     212             :     case OpenPGP:
     213          61 :         if (gpgme_set_protocol(ctx, GPGME_PROTOCOL_OpenPGP) != 0) {
     214           0 :             gpgme_release(ctx);
     215           0 :             return 0;
     216             :         }
     217          61 :         break;
     218             :     case CMS:
     219           0 :         if (gpgme_set_protocol(ctx, GPGME_PROTOCOL_CMS) != 0) {
     220           0 :             gpgme_release(ctx);
     221           0 :             return 0;
     222             :         }
     223           0 :         break;
     224             :     default:
     225           0 :         return 0;
     226             :     }
     227             : 
     228          61 :     return new Context(ctx);
     229             : }
     230             : 
     231           0 : std::unique_ptr<Context> Context::create(Protocol proto)
     232             : {
     233           0 :   return std::unique_ptr <Context> (createForProtocol(proto));
     234             : }
     235             : 
     236           0 : std::unique_ptr<Context> Context::createForEngine(Engine eng, Error *error)
     237             : {
     238           0 :     gpgme_ctx_t ctx = 0;
     239           0 :     if (const gpgme_error_t err = gpgme_new(&ctx)) {
     240           0 :         if (error) {
     241           0 :             *error = Error(err);
     242             :         }
     243           0 :         return std::unique_ptr<Context>();
     244             :     }
     245             : 
     246           0 :     switch (eng) {
     247             :     case AssuanEngine:
     248           0 :         if (const gpgme_error_t err = gpgme_set_protocol(ctx, GPGME_PROTOCOL_ASSUAN)) {
     249           0 :             gpgme_release(ctx);
     250           0 :             if (error) {
     251           0 :                 *error = Error(err);
     252             :             }
     253           0 :             return std::unique_ptr<Context>();
     254             :         }
     255           0 :         break;
     256             :     case G13Engine:
     257           0 :         if (const gpgme_error_t err = gpgme_set_protocol(ctx, GPGME_PROTOCOL_G13)) {
     258           0 :             gpgme_release(ctx);
     259           0 :             if (error) {
     260           0 :                 *error = Error(err);
     261             :             }
     262           0 :             return std::unique_ptr<Context>();
     263             :         }
     264           0 :         break;
     265             :     case SpawnEngine:
     266           0 :         if (const gpgme_error_t err = gpgme_set_protocol(ctx, GPGME_PROTOCOL_SPAWN)) {
     267           0 :             gpgme_release(ctx);
     268           0 :             if (error) {
     269           0 :                 *error = Error(err);
     270             :             }
     271           0 :             return std::unique_ptr<Context>();
     272             :         }
     273           0 :         break;
     274             :     default:
     275           0 :         if (error) {
     276           0 :             *error = Error::fromCode(GPG_ERR_INV_ARG);
     277             :         }
     278           0 :         return std::unique_ptr<Context>();
     279             :     }
     280             : 
     281           0 :     if (error) {
     282           0 :         *error = Error();
     283             :     }
     284             : 
     285           0 :     return std::unique_ptr<Context>(new Context(ctx));
     286             : }
     287             : 
     288           1 : void Context::setDecryptionFlags(DecryptionFlags flags)
     289             : {
     290           1 :     d->decryptFlags = flags;
     291           1 : }
     292             : 
     293             : //
     294             : //
     295             : // Context::Private
     296             : //
     297             : //
     298             : 
     299          61 : Context::Private::Private(gpgme_ctx_t c)
     300             :     : ctx(c),
     301             :       iocbs(0),
     302             :       lastop(None),
     303             :       lasterr(GPG_ERR_NO_ERROR),
     304             :       lastAssuanInquireData(Data::null),
     305             :       lastAssuanTransaction(),
     306             :       lastEditInteractor(),
     307             :       lastCardEditInteractor(),
     308          61 :       decryptFlags(DecryptNone)
     309             : {
     310             : 
     311          61 : }
     312             : 
     313         122 : Context::Private::~Private()
     314             : {
     315          61 :     if (ctx) {
     316          61 :         gpgme_release(ctx);
     317             :     }
     318          61 :     ctx = 0;
     319          61 :     delete iocbs;
     320          61 : }
     321             : 
     322             : //
     323             : //
     324             : // Context attributes:
     325             : //
     326             : //
     327             : 
     328          30 : Protocol Context::protocol() const
     329             : {
     330          30 :     gpgme_protocol_t p = gpgme_get_protocol(d->ctx);
     331          30 :     switch (p) {
     332          30 :     case GPGME_PROTOCOL_OpenPGP: return OpenPGP;
     333           0 :     case GPGME_PROTOCOL_CMS:     return CMS;
     334           0 :     default:                     return UnknownProtocol;
     335             :     }
     336             : }
     337             : 
     338          11 : void Context::setArmor(bool useArmor)
     339             : {
     340          11 :     gpgme_set_armor(d->ctx, int(useArmor));
     341          11 : }
     342           0 : bool Context::armor() const
     343             : {
     344           0 :     return gpgme_get_armor(d->ctx);
     345             : }
     346             : 
     347          24 : void Context::setTextMode(bool useTextMode)
     348             : {
     349          24 :     gpgme_set_textmode(d->ctx, int(useTextMode));
     350          24 : }
     351           0 : bool Context::textMode() const
     352             : {
     353           0 :     return gpgme_get_textmode(d->ctx);
     354             : }
     355             : 
     356           0 : void Context::setOffline(bool useOfflineMode)
     357             : {
     358           0 :     gpgme_set_offline(d->ctx, int(useOfflineMode));
     359           0 : }
     360           0 : bool Context::offline() const
     361             : {
     362           0 :     return gpgme_get_offline(d->ctx);
     363             : }
     364             : 
     365           0 : void Context::setIncludeCertificates(int which)
     366             : {
     367           0 :     if (which == DefaultCertificates) {
     368           0 :         which = GPGME_INCLUDE_CERTS_DEFAULT;
     369             :     }
     370           0 :     gpgme_set_include_certs(d->ctx, which);
     371           0 : }
     372             : 
     373           0 : int Context::includeCertificates() const
     374             : {
     375           0 :     return gpgme_get_include_certs(d->ctx);
     376             : }
     377             : 
     378          25 : void Context::setKeyListMode(unsigned int mode)
     379             : {
     380          25 :     gpgme_set_keylist_mode(d->ctx, add_to_gpgme_keylist_mode_t(0, mode));
     381          25 : }
     382             : 
     383           4 : void Context::addKeyListMode(unsigned int mode)
     384             : {
     385           4 :     const unsigned int cur = gpgme_get_keylist_mode(d->ctx);
     386           4 :     gpgme_set_keylist_mode(d->ctx, add_to_gpgme_keylist_mode_t(cur, mode));
     387           4 : }
     388             : 
     389          14 : unsigned int Context::keyListMode() const
     390             : {
     391          14 :     return convert_from_gpgme_keylist_mode_t(gpgme_get_keylist_mode(d->ctx));
     392             : }
     393             : 
     394          46 : void Context::setProgressProvider(ProgressProvider *provider)
     395             : {
     396          46 :     gpgme_set_progress_cb(d->ctx, provider ? &progress_callback : 0, provider);
     397          46 : }
     398           0 : ProgressProvider *Context::progressProvider() const
     399             : {
     400           0 :     void *pp = 0;
     401           0 :     gpgme_progress_cb_t pcb = &progress_callback;
     402           0 :     gpgme_get_progress_cb(d->ctx, &pcb, &pp);
     403           0 :     return static_cast<ProgressProvider *>(pp);
     404             : }
     405             : 
     406          12 : void Context::setPassphraseProvider(PassphraseProvider *provider)
     407             : {
     408          12 :     gpgme_set_passphrase_cb(d->ctx, provider ? &passphrase_callback : 0, provider);
     409          12 : }
     410             : 
     411           0 : PassphraseProvider *Context::passphraseProvider() const
     412             : {
     413           0 :     void *pp = 0;
     414           0 :     gpgme_passphrase_cb_t pcb = &passphrase_callback;
     415           0 :     gpgme_get_passphrase_cb(d->ctx, &pcb, &pp);
     416           0 :     return static_cast<PassphraseProvider *>(pp);
     417             : }
     418             : 
     419           0 : void Context::setManagedByEventLoopInteractor(bool manage)
     420             : {
     421           0 :     if (!EventLoopInteractor::instance()) {
     422             : #ifndef NDEBUG
     423             :         cerr << "Context::setManagedByEventLoopInteractor(): "
     424             :              "You must create an instance of EventLoopInteractor "
     425           0 :              "before using anything that needs one." << endl;
     426             : #endif
     427           0 :         return;
     428             :     }
     429           0 :     if (manage) {
     430           0 :         EventLoopInteractor::instance()->manage(this);
     431             :     } else {
     432           0 :         EventLoopInteractor::instance()->unmanage(this);
     433             :     }
     434             : }
     435           0 : bool Context::managedByEventLoopInteractor() const
     436             : {
     437           0 :     return d->iocbs != 0;
     438             : }
     439             : 
     440           0 : void Context::installIOCallbacks(gpgme_io_cbs *iocbs)
     441             : {
     442           0 :     if (!iocbs) {
     443           0 :         uninstallIOCallbacks();
     444           0 :         return;
     445             :     }
     446           0 :     gpgme_set_io_cbs(d->ctx, iocbs);
     447           0 :     delete d->iocbs; d->iocbs = iocbs;
     448             : }
     449             : 
     450           0 : void Context::uninstallIOCallbacks()
     451             : {
     452             :     static gpgme_io_cbs noiocbs = { 0, 0, 0, 0, 0 };
     453             :     // io.add == 0 means disable io callbacks:
     454           0 :     gpgme_set_io_cbs(d->ctx, &noiocbs);
     455           0 :     delete d->iocbs; d->iocbs = 0;
     456           0 : }
     457             : 
     458           0 : Error Context::setLocale(int cat, const char *val)
     459             : {
     460           0 :     return Error(d->lasterr = gpgme_set_locale(d->ctx, cat, val));
     461             : }
     462             : 
     463           0 : EngineInfo Context::engineInfo() const
     464             : {
     465           0 :     return EngineInfo(gpgme_ctx_get_engine_info(d->ctx));
     466             : }
     467             : 
     468           0 : Error Context::setEngineFileName(const char *filename)
     469             : {
     470           0 :     const char *const home_dir = engineInfo().homeDirectory();
     471           0 :     return Error(gpgme_ctx_set_engine_info(d->ctx, gpgme_get_protocol(d->ctx), filename, home_dir));
     472             : }
     473             : 
     474           0 : Error Context::setEngineHomeDirectory(const char *home_dir)
     475             : {
     476           0 :     const char *const filename = engineInfo().fileName();
     477           0 :     return Error(gpgme_ctx_set_engine_info(d->ctx, gpgme_get_protocol(d->ctx), filename, home_dir));
     478             : }
     479             : 
     480           1 : Error Context::setSender (const char *sender)
     481             : {
     482           1 :     return Error(gpgme_set_sender(d->ctx, sender));
     483             : }
     484             : 
     485           0 : const char *Context::getSender ()
     486             : {
     487           0 :     return gpgme_get_sender(d->ctx);
     488             : }
     489             : 
     490             : //
     491             : //
     492             : // Key Management
     493             : //
     494             : //
     495             : 
     496          17 : Error Context::startKeyListing(const char *pattern, bool secretOnly)
     497             : {
     498          17 :     d->lastop = Private::KeyList;
     499          17 :     return Error(d->lasterr = gpgme_op_keylist_start(d->ctx, pattern, int(secretOnly)));
     500             : }
     501             : 
     502          17 : Error Context::startKeyListing(const char *patterns[], bool secretOnly)
     503             : {
     504          17 :     d->lastop = Private::KeyList;
     505             : #ifndef HAVE_GPGME_EXT_KEYLIST_MODE_EXTERNAL_NONBROKEN
     506          17 :     if (!patterns || !patterns[0] || !patterns[1]) {
     507             :         // max. one pattern -> use the non-ext version
     508          17 :         return startKeyListing(patterns ? patterns[0] : 0, secretOnly);
     509             :     }
     510             : #endif
     511           0 :     return Error(d->lasterr = gpgme_op_keylist_ext_start(d->ctx, patterns, int(secretOnly), 0));
     512             : }
     513             : 
     514          34 : Key Context::nextKey(GpgME::Error &e)
     515             : {
     516          34 :     d->lastop = Private::KeyList;
     517          34 :     gpgme_key_t key = nullptr;
     518          34 :     e = Error(d->lasterr = gpgme_op_keylist_next(d->ctx, &key));
     519          34 :     return Key(key, false);
     520             : }
     521             : 
     522          17 : KeyListResult Context::endKeyListing()
     523             : {
     524          17 :     d->lasterr = gpgme_op_keylist_end(d->ctx);
     525          17 :     return keyListResult();
     526             : }
     527             : 
     528          17 : KeyListResult Context::keyListResult() const
     529             : {
     530          17 :     return KeyListResult(d->ctx, Error(d->lasterr));
     531             : }
     532             : 
     533          10 : Key Context::key(const char *fingerprint, GpgME::Error &e , bool secret /*, bool forceUpdate*/)
     534             : {
     535          10 :     d->lastop = Private::KeyList;
     536          10 :     gpgme_key_t key = nullptr;
     537          10 :     e = Error(d->lasterr = gpgme_get_key(d->ctx, fingerprint, &key, int(secret)/*, int( forceUpdate )*/));
     538          10 :     return Key(key, false);
     539             : }
     540             : 
     541           0 : KeyGenerationResult Context::generateKey(const char *parameters, Data &pubKey)
     542             : {
     543           0 :     d->lastop = Private::KeyGen;
     544           0 :     Data::Private *const dp = pubKey.impl();
     545           0 :     d->lasterr = gpgme_op_genkey(d->ctx, parameters, dp ? dp->data : 0, 0);
     546           0 :     return KeyGenerationResult(d->ctx, Error(d->lasterr));
     547             : }
     548             : 
     549           0 : Error Context::startKeyGeneration(const char *parameters, Data &pubKey)
     550             : {
     551           0 :     d->lastop = Private::KeyGen;
     552           0 :     Data::Private *const dp = pubKey.impl();
     553           0 :     return Error(d->lasterr = gpgme_op_genkey_start(d->ctx, parameters, dp ? dp->data : 0, 0));
     554             : }
     555             : 
     556           0 : KeyGenerationResult Context::keyGenerationResult() const
     557             : {
     558           0 :     if (d->lastop & Private::KeyGen) {
     559           0 :         return KeyGenerationResult(d->ctx, Error(d->lasterr));
     560             :     } else {
     561           0 :         return KeyGenerationResult();
     562             :     }
     563             : }
     564             : 
     565           0 : Error Context::exportPublicKeys(const char *pattern, Data &keyData)
     566             : {
     567           0 :     d->lastop = Private::Export;
     568           0 :     Data::Private *const dp = keyData.impl();
     569           0 :     return Error(d->lasterr = gpgme_op_export(d->ctx, pattern, 0, dp ? dp->data : 0));
     570             : }
     571             : 
     572           0 : Error Context::exportPublicKeys(const char *patterns[], Data &keyData)
     573             : {
     574           0 :     d->lastop = Private::Export;
     575             : #ifndef HAVE_GPGME_EXT_KEYLIST_MODE_EXTERNAL_NONBROKEN
     576           0 :     if (!patterns || !patterns[0] || !patterns[1]) {
     577             :         // max. one pattern -> use the non-ext version
     578           0 :         return exportPublicKeys(patterns ? patterns[0] : 0, keyData);
     579             :     }
     580             : #endif
     581           0 :     Data::Private *const dp = keyData.impl();
     582           0 :     return Error(d->lasterr = gpgme_op_export_ext(d->ctx, patterns, 0, dp ? dp->data : 0));
     583             : }
     584             : 
     585           0 : Error Context::startPublicKeyExport(const char *pattern, Data &keyData)
     586             : {
     587           0 :     d->lastop = Private::Export;
     588           0 :     Data::Private *const dp = keyData.impl();
     589           0 :     return Error(d->lasterr = gpgme_op_export_start(d->ctx, pattern, 0, dp ? dp->data : 0));
     590             : }
     591             : 
     592           0 : Error Context::startPublicKeyExport(const char *patterns[], Data &keyData)
     593             : {
     594           0 :     d->lastop = Private::Export;
     595             : #ifndef HAVE_GPGME_EXT_KEYLIST_MODE_EXTERNAL_NONBROKEN
     596           0 :     if (!patterns || !patterns[0] || !patterns[1]) {
     597             :         // max. one pattern -> use the non-ext version
     598           0 :         return startPublicKeyExport(patterns ? patterns[0] : 0, keyData);
     599             :     }
     600             : #endif
     601           0 :     Data::Private *const dp = keyData.impl();
     602           0 :     return Error(d->lasterr = gpgme_op_export_ext_start(d->ctx, patterns, 0, dp ? dp->data : 0));
     603             : }
     604             : 
     605           2 : ImportResult Context::importKeys(const Data &data)
     606             : {
     607           2 :     d->lastop = Private::Import;
     608           2 :     const Data::Private *const dp = data.impl();
     609           2 :     d->lasterr = gpgme_op_import(d->ctx, dp ? dp->data : 0);
     610           2 :     return ImportResult(d->ctx, Error(d->lasterr));
     611             : }
     612             : 
     613           0 : ImportResult Context::importKeys(const std::vector<Key> &kk)
     614             : {
     615           0 :     d->lastop = Private::Import;
     616           0 :     d->lasterr = make_error(GPG_ERR_NOT_IMPLEMENTED);
     617             : 
     618           0 :     bool shouldHaveResult = false;
     619           0 :     gpgme_key_t * const keys = new gpgme_key_t[ kk.size() + 1 ];
     620           0 :     gpgme_key_t *keys_it = &keys[0];
     621           0 :     for (std::vector<Key>::const_iterator it = kk.begin(), end = kk.end() ; it != end ; ++it) {
     622           0 :         if (it->impl()) {
     623           0 :             *keys_it++ = it->impl();
     624             :         }
     625             :     }
     626           0 :     *keys_it++ = 0;
     627           0 :     d->lasterr = gpgme_op_import_keys(d->ctx, keys);
     628           0 :     shouldHaveResult = true;
     629           0 :     if ((gpgme_err_code(d->lasterr) == GPG_ERR_NOT_IMPLEMENTED ||
     630           0 :             gpgme_err_code(d->lasterr) == GPG_ERR_NOT_SUPPORTED) &&
     631           0 :             protocol() == CMS) {
     632             :         // ok, try the workaround (export+import):
     633           0 :         std::vector<const char *> fprs;
     634           0 :         for (std::vector<Key>::const_iterator it = kk.begin(), end = kk.end() ; it != end ; ++it) {
     635           0 :             if (const char *fpr = it->primaryFingerprint()) {
     636           0 :                 if (*fpr) {
     637           0 :                     fprs.push_back(fpr);
     638             :                 }
     639           0 :             } else if (const char *keyid = it->keyID()) {
     640           0 :                 if (*keyid) {
     641           0 :                     fprs.push_back(keyid);
     642             :                 }
     643             :             }
     644             :         }
     645           0 :         fprs.push_back(0);
     646           0 :         Data data;
     647           0 :         Data::Private *const dp = data.impl();
     648           0 :         const gpgme_keylist_mode_t oldMode = gpgme_get_keylist_mode(d->ctx);
     649           0 :         gpgme_set_keylist_mode(d->ctx, GPGME_KEYLIST_MODE_EXTERN);
     650           0 :         d->lasterr = gpgme_op_export_ext(d->ctx, &fprs[0], 0, dp ? dp->data : 0);
     651           0 :         gpgme_set_keylist_mode(d->ctx, oldMode);
     652           0 :         if (!d->lasterr) {
     653           0 :             data.seek(0, SEEK_SET);
     654           0 :             d->lasterr = gpgme_op_import(d->ctx, dp ? dp->data : 0);
     655           0 :             shouldHaveResult = true;
     656             :         }
     657             :     }
     658           0 :     delete[] keys;
     659           0 :     if (shouldHaveResult) {
     660           0 :         return ImportResult(d->ctx, Error(d->lasterr));
     661             :     } else {
     662           0 :         return ImportResult(Error(d->lasterr));
     663             :     }
     664             : }
     665             : 
     666           0 : Error Context::startKeyImport(const Data &data)
     667             : {
     668           0 :     d->lastop = Private::Import;
     669           0 :     const Data::Private *const dp = data.impl();
     670           0 :     return Error(d->lasterr = gpgme_op_import_start(d->ctx, dp ? dp->data : 0));
     671             : }
     672             : 
     673           0 : Error Context::startKeyImport(const std::vector<Key> &kk)
     674             : {
     675           0 :     d->lastop = Private::Import;
     676           0 :     gpgme_key_t * const keys = new gpgme_key_t[ kk.size() + 1 ];
     677           0 :     gpgme_key_t *keys_it = &keys[0];
     678           0 :     for (std::vector<Key>::const_iterator it = kk.begin(), end = kk.end() ; it != end ; ++it) {
     679           0 :         if (it->impl()) {
     680           0 :             *keys_it++ = it->impl();
     681             :         }
     682             :     }
     683           0 :     *keys_it++ = 0;
     684           0 :     Error err = Error(d->lasterr = gpgme_op_import_keys_start(d->ctx, keys));
     685           0 :     delete[] keys;
     686           0 :     return err;
     687             : }
     688             : 
     689           0 : ImportResult Context::importResult() const
     690             : {
     691           0 :     if (d->lastop & Private::Import) {
     692           0 :         return ImportResult(d->ctx, Error(d->lasterr));
     693             :     } else {
     694           0 :         return ImportResult();
     695             :     }
     696             : }
     697             : 
     698           0 : Error Context::deleteKey(const Key &key, bool allowSecretKeyDeletion)
     699             : {
     700           0 :     d->lastop = Private::Delete;
     701           0 :     return Error(d->lasterr = gpgme_op_delete(d->ctx, key.impl(), int(allowSecretKeyDeletion)));
     702             : }
     703             : 
     704           0 : Error Context::startKeyDeletion(const Key &key, bool allowSecretKeyDeletion)
     705             : {
     706           0 :     d->lastop = Private::Delete;
     707           0 :     return Error(d->lasterr = gpgme_op_delete_start(d->ctx, key.impl(), int(allowSecretKeyDeletion)));
     708             : }
     709             : 
     710           0 : Error Context::passwd(const Key &key)
     711             : {
     712           0 :     d->lastop = Private::Passwd;
     713           0 :     return Error(d->lasterr = gpgme_op_passwd(d->ctx, key.impl(), 0U));
     714             : }
     715             : 
     716           0 : Error Context::startPasswd(const Key &key)
     717             : {
     718           0 :     d->lastop = Private::Passwd;
     719           0 :     return Error(d->lasterr = gpgme_op_passwd_start(d->ctx, key.impl(), 0U));
     720             : }
     721             : 
     722             : 
     723             : #pragma GCC diagnostic push
     724             : #pragma GCC diagnostic ignored "-Wdeprecated-declarations"
     725             : 
     726           2 : Error Context::edit(const Key &key, std::unique_ptr<EditInteractor> func, Data &data)
     727             : {
     728           2 :     d->lastop = Private::Edit;
     729           2 :     d->lastEditInteractor = std::move(func);
     730           2 :     Data::Private *const dp = data.impl();
     731          10 :     return Error(d->lasterr = gpgme_op_edit(d->ctx, key.impl(),
     732           2 :                                             d->lastEditInteractor.get() ? edit_interactor_callback : 0,
     733           4 :                                             d->lastEditInteractor.get() ? d->lastEditInteractor->d : 0,
     734           4 :                                             dp ? dp->data : 0));
     735             : }
     736             : 
     737             : 
     738           0 : Error Context::startEditing(const Key &key, std::unique_ptr<EditInteractor> func, Data &data)
     739             : {
     740           0 :     d->lastop = Private::Edit;
     741           0 :     d->lastEditInteractor = std::move(func);
     742           0 :     Data::Private *const dp = data.impl();
     743           0 :     return Error(d->lasterr = gpgme_op_edit_start(d->ctx, key.impl(),
     744           0 :                               d->lastEditInteractor.get() ? edit_interactor_callback : 0,
     745           0 :                               d->lastEditInteractor.get() ? d->lastEditInteractor->d : 0,
     746           0 :                               dp ? dp->data : 0));
     747             : }
     748             : 
     749             : 
     750           0 : EditInteractor *Context::lastEditInteractor() const
     751             : {
     752           0 :     return d->lastEditInteractor.get();
     753             : }
     754             : 
     755           0 : std::unique_ptr<EditInteractor> Context::takeLastEditInteractor()
     756             : {
     757           0 :     return std::move(d->lastEditInteractor);
     758             : }
     759             : 
     760             : 
     761           0 : Error Context::cardEdit(const Key &key, std::unique_ptr<EditInteractor> func, Data &data)
     762             : {
     763           0 :     d->lastop = Private::CardEdit;
     764           0 :     d->lastCardEditInteractor = std::move(func);
     765           0 :     Data::Private *const dp = data.impl();
     766           0 :     return Error(d->lasterr = gpgme_op_card_edit(d->ctx, key.impl(),
     767           0 :                               d->lastCardEditInteractor.get() ? edit_interactor_callback : 0,
     768           0 :                               d->lastCardEditInteractor.get() ? d->lastCardEditInteractor->d : 0,
     769           0 :                               dp ? dp->data : 0));
     770             : }
     771             : 
     772           0 : Error Context::startCardEditing(const Key &key, std::unique_ptr<EditInteractor> func, Data &data)
     773             : {
     774           0 :     d->lastop = Private::CardEdit;
     775           0 :     d->lastCardEditInteractor = std::move(func);
     776           0 :     Data::Private *const dp = data.impl();
     777           0 :     return Error(d->lasterr = gpgme_op_card_edit_start(d->ctx, key.impl(),
     778           0 :                               d->lastCardEditInteractor.get() ? edit_interactor_callback : 0,
     779           0 :                               d->lastCardEditInteractor.get() ? d->lastCardEditInteractor->d : 0,
     780           0 :                               dp ? dp->data : 0));
     781             : }
     782             : 
     783             : #pragma GCC diagnostic pop
     784             : 
     785           0 : EditInteractor *Context::lastCardEditInteractor() const
     786             : {
     787           0 :     return d->lastCardEditInteractor.get();
     788             : }
     789             : 
     790           0 : std::unique_ptr<EditInteractor> Context::takeLastCardEditInteractor()
     791             : {
     792           0 :     return std::move(d->lastCardEditInteractor);
     793             : }
     794             : 
     795           0 : Error Context::startTrustItemListing(const char *pattern, int maxLevel)
     796             : {
     797           0 :     d->lastop = Private::TrustList;
     798           0 :     return Error(d->lasterr = gpgme_op_trustlist_start(d->ctx, pattern, maxLevel));
     799             : }
     800             : 
     801           0 : TrustItem Context::nextTrustItem(Error &e)
     802             : {
     803           0 :     gpgme_trust_item_t ti = 0;
     804           0 :     e = Error(d->lasterr = gpgme_op_trustlist_next(d->ctx, &ti));
     805           0 :     return TrustItem(ti);
     806             : }
     807             : 
     808           0 : Error Context::endTrustItemListing()
     809             : {
     810           0 :     return Error(d->lasterr = gpgme_op_trustlist_end(d->ctx));
     811             : }
     812             : 
     813           0 : static gpgme_error_t assuan_transaction_data_callback(void *opaque, const void *data, size_t datalen)
     814             : {
     815           0 :     assert(opaque);
     816           0 :     AssuanTransaction *t = static_cast<AssuanTransaction *>(opaque);
     817           0 :     return t->data(static_cast<const char *>(data), datalen).encodedError();
     818             : }
     819             : 
     820           0 : static gpgme_error_t assuan_transaction_inquire_callback(void *opaque, const char *name, const char *args, gpgme_data_t *r_data)
     821             : {
     822           0 :     assert(opaque);
     823           0 :     Context::Private *p = static_cast<Context::Private *>(opaque);
     824           0 :     AssuanTransaction *t = p->lastAssuanTransaction.get();
     825           0 :     assert(t);
     826           0 :     Error err;
     827           0 :     if (name) {
     828           0 :         p->lastAssuanInquireData = t->inquire(name, args, err);
     829             :     } else {
     830           0 :         p->lastAssuanInquireData = Data::null;
     831             :     }
     832           0 :     if (!p->lastAssuanInquireData.isNull()) {
     833           0 :         *r_data = p->lastAssuanInquireData.impl()->data;
     834             :     }
     835           0 :     return err.encodedError();
     836             : }
     837             : 
     838           0 : static gpgme_error_t assuan_transaction_status_callback(void *opaque, const char *status, const char *args)
     839             : {
     840           0 :     assert(opaque);
     841           0 :     AssuanTransaction *t = static_cast<AssuanTransaction *>(opaque);
     842           0 :     std::string a = args;
     843           0 :     percent_unescape(a, true);   // ### why doesn't gpgme do this??
     844           0 :     return t->status(status, a.c_str()).encodedError();
     845             : }
     846             : 
     847           0 : Error Context::assuanTransact(const char *command)
     848             : {
     849           0 :     return assuanTransact(command, std::unique_ptr<AssuanTransaction>(new DefaultAssuanTransaction));
     850             : }
     851             : 
     852           0 : Error Context::assuanTransact(const char *command, std::unique_ptr<AssuanTransaction> transaction)
     853             : {
     854             :     gpgme_error_t err, operr;
     855             : 
     856           0 :     d->lastop = Private::AssuanTransact;
     857           0 :     d->lastAssuanTransaction = std::move(transaction);
     858           0 :     if (!d->lastAssuanTransaction.get()) {
     859           0 :         return Error(d->lasterr = make_error(GPG_ERR_INV_ARG));
     860             :     }
     861             :     err = gpgme_op_assuan_transact_ext
     862           0 :       (d->ctx,
     863             :        command,
     864             :        assuan_transaction_data_callback,
     865           0 :        d->lastAssuanTransaction.get(),
     866             :        assuan_transaction_inquire_callback,
     867           0 :        d,
     868             :        assuan_transaction_status_callback,
     869           0 :        d->lastAssuanTransaction.get(),
     870           0 :        &operr);
     871             : 
     872           0 :     if (!err)
     873           0 :       err = operr;
     874           0 :     d->lasterr = err;
     875             : 
     876           0 :     return Error(d->lasterr);
     877             : }
     878             : 
     879           0 : Error Context::startAssuanTransaction(const char *command)
     880             : {
     881           0 :     return startAssuanTransaction(command, std::unique_ptr<AssuanTransaction>(new DefaultAssuanTransaction));
     882             : }
     883             : 
     884           0 : Error Context::startAssuanTransaction(const char *command, std::unique_ptr<AssuanTransaction> transaction)
     885             : {
     886             :     gpgme_error_t err;
     887             : 
     888           0 :     d->lastop = Private::AssuanTransact;
     889           0 :     d->lastAssuanTransaction = std::move(transaction);
     890           0 :     if (!d->lastAssuanTransaction.get()) {
     891           0 :         return Error(d->lasterr = make_error(GPG_ERR_INV_ARG));
     892             :     }
     893             :     err = gpgme_op_assuan_transact_start
     894           0 :       (d->ctx,
     895             :        command,
     896             :        assuan_transaction_data_callback,
     897           0 :        d->lastAssuanTransaction.get(),
     898             :        assuan_transaction_inquire_callback,
     899           0 :        d,
     900             :        assuan_transaction_status_callback,
     901           0 :        d->lastAssuanTransaction.get());
     902             : 
     903           0 :     d->lasterr = err;
     904             : 
     905           0 :     return Error(d->lasterr);
     906             : }
     907             : 
     908           0 : AssuanTransaction *Context::lastAssuanTransaction() const
     909             : {
     910           0 :     return d->lastAssuanTransaction.get();
     911             : }
     912             : 
     913           0 : std::unique_ptr<AssuanTransaction> Context::takeLastAssuanTransaction()
     914             : {
     915           0 :     return std::move(d->lastAssuanTransaction);
     916             : }
     917             : 
     918           3 : DecryptionResult Context::decrypt(const Data &cipherText, Data &plainText, const DecryptionFlags flags)
     919             : {
     920           3 :     d->lastop = Private::Decrypt;
     921           3 :     const Data::Private *const cdp = cipherText.impl();
     922           3 :     Data::Private *const pdp = plainText.impl();
     923           3 :     d->lasterr = gpgme_op_decrypt_ext(d->ctx, static_cast<gpgme_decrypt_flags_t> (d->decryptFlags | flags), cdp ? cdp->data : 0, pdp ? pdp->data : 0);
     924           3 :     return DecryptionResult(d->ctx, Error(d->lasterr));
     925             : }
     926             : 
     927           3 : DecryptionResult Context::decrypt(const Data &cipherText, Data &plainText)
     928             : {
     929           3 :     return decrypt(cipherText, plainText, DecryptNone);
     930             : }
     931             : 
     932           0 : Error Context::startDecryption(const Data &cipherText, Data &plainText, const DecryptionFlags flags)
     933             : {
     934           0 :     d->lastop = Private::Decrypt;
     935           0 :     const Data::Private *const cdp = cipherText.impl();
     936           0 :     Data::Private *const pdp = plainText.impl();
     937           0 :     return Error(d->lasterr = gpgme_op_decrypt_ext_start(d->ctx, static_cast<gpgme_decrypt_flags_t> (d->decryptFlags | flags),
     938           0 :                  cdp ? cdp->data : 0, pdp ? pdp->data : 0));
     939             : }
     940             : 
     941           0 : Error Context::startDecryption(const Data &cipherText, Data &plainText)
     942             : {
     943           0 :     return startDecryption(cipherText, plainText, DecryptNone);
     944             : }
     945             : 
     946           0 : DecryptionResult Context::decryptionResult() const
     947             : {
     948           0 :     if (d->lastop & Private::Decrypt) {
     949           0 :         return DecryptionResult(d->ctx, Error(d->lasterr));
     950             :     } else {
     951           0 :         return DecryptionResult();
     952             :     }
     953             : }
     954             : 
     955           0 : VerificationResult Context::verifyDetachedSignature(const Data &signature, const Data &signedText)
     956             : {
     957           0 :     d->lastop = Private::Verify;
     958           0 :     const Data::Private *const sdp = signature.impl();
     959           0 :     const Data::Private *const tdp = signedText.impl();
     960           0 :     d->lasterr = gpgme_op_verify(d->ctx, sdp ? sdp->data : 0, tdp ? tdp->data : 0, 0);
     961           0 :     return VerificationResult(d->ctx, Error(d->lasterr));
     962             : }
     963             : 
     964          13 : VerificationResult Context::verifyOpaqueSignature(const Data &signedData, Data &plainText)
     965             : {
     966          13 :     d->lastop = Private::Verify;
     967          13 :     const Data::Private *const sdp = signedData.impl();
     968          13 :     Data::Private *const pdp = plainText.impl();
     969          13 :     d->lasterr = gpgme_op_verify(d->ctx, sdp ? sdp->data : 0, 0, pdp ? pdp->data : 0);
     970          13 :     return VerificationResult(d->ctx, Error(d->lasterr));
     971             : }
     972             : 
     973           0 : Error Context::startDetachedSignatureVerification(const Data &signature, const Data &signedText)
     974             : {
     975           0 :     d->lastop = Private::Verify;
     976           0 :     const Data::Private *const sdp = signature.impl();
     977           0 :     const Data::Private *const tdp = signedText.impl();
     978           0 :     return Error(d->lasterr = gpgme_op_verify_start(d->ctx, sdp ? sdp->data : 0, tdp ? tdp->data : 0, 0));
     979             : }
     980             : 
     981           0 : Error Context::startOpaqueSignatureVerification(const Data &signedData, Data &plainText)
     982             : {
     983           0 :     d->lastop = Private::Verify;
     984           0 :     const Data::Private *const sdp = signedData.impl();
     985           0 :     Data::Private *const pdp = plainText.impl();
     986           0 :     return Error(d->lasterr = gpgme_op_verify_start(d->ctx, sdp ? sdp->data : 0, 0, pdp ? pdp->data : 0));
     987             : }
     988             : 
     989           0 : VerificationResult Context::verificationResult() const
     990             : {
     991           0 :     if (d->lastop & Private::Verify) {
     992           0 :         return VerificationResult(d->ctx, Error(d->lasterr));
     993             :     } else {
     994           0 :         return VerificationResult();
     995             :     }
     996             : }
     997             : 
     998           0 : std::pair<DecryptionResult, VerificationResult> Context::decryptAndVerify(const Data &cipherText, Data &plainText, DecryptionFlags flags)
     999             : {
    1000           0 :     d->lastop = Private::DecryptAndVerify;
    1001           0 :     const Data::Private *const cdp = cipherText.impl();
    1002           0 :     Data::Private *const pdp = plainText.impl();
    1003           0 :     d->lasterr = gpgme_op_decrypt_ext(d->ctx, static_cast<gpgme_decrypt_flags_t> (d->decryptFlags | flags | DecryptVerify),
    1004             :                                       cdp ? cdp->data : 0, pdp ? pdp->data : 0);
    1005           0 :     return std::make_pair(DecryptionResult(d->ctx, Error(d->lasterr)),
    1006           0 :                           VerificationResult(d->ctx, Error(d->lasterr)));
    1007             : }
    1008             : 
    1009           0 : std::pair<DecryptionResult, VerificationResult> Context::decryptAndVerify(const Data &cipherText, Data &plainText)
    1010             : {
    1011           0 :     return decryptAndVerify(cipherText, plainText, DecryptNone);
    1012             : }
    1013             : 
    1014           0 : Error Context::startCombinedDecryptionAndVerification(const Data &cipherText, Data &plainText, DecryptionFlags flags)
    1015             : {
    1016           0 :     d->lastop = Private::DecryptAndVerify;
    1017           0 :     const Data::Private *const cdp = cipherText.impl();
    1018           0 :     Data::Private *const pdp = plainText.impl();
    1019           0 :     return Error(d->lasterr = gpgme_op_decrypt_ext_start(d->ctx, static_cast<gpgme_decrypt_flags_t> (d->decryptFlags | flags | DecryptVerify), cdp ? cdp->data : 0, pdp ? pdp->data : 0));
    1020             : }
    1021             : 
    1022           0 : Error Context::startCombinedDecryptionAndVerification(const Data &cipherText, Data &plainText)
    1023             : {
    1024           0 :     return startCombinedDecryptionAndVerification(cipherText, plainText, DecryptNone);
    1025             : }
    1026             : 
    1027          30 : unsigned int to_auditlog_flags(unsigned int flags)
    1028             : {
    1029          30 :     unsigned int result = 0;
    1030          30 :     if (flags & Context::HtmlAuditLog) {
    1031           0 :         result |= GPGME_AUDITLOG_HTML;
    1032             :     }
    1033          30 :     if (flags & Context::AuditLogWithHelp) {
    1034           0 :         result |= GPGME_AUDITLOG_WITH_HELP;
    1035             :     }
    1036          30 :     if (flags & Context::DiagnosticAuditLog) {
    1037          30 :         result |= GPGME_AUDITLOG_DIAG;
    1038             :     }
    1039          30 :     return result;
    1040             : }
    1041             : 
    1042           0 : Error Context::startGetAuditLog(Data &output, unsigned int flags)
    1043             : {
    1044           0 :     d->lastop = Private::GetAuditLog;
    1045           0 :     Data::Private *const odp = output.impl();
    1046           0 :     return Error(d->lasterr = gpgme_op_getauditlog_start(d->ctx, odp ? odp->data : 0, to_auditlog_flags(flags)));
    1047             : }
    1048             : 
    1049          30 : Error Context::getAuditLog(Data &output, unsigned int flags)
    1050             : {
    1051          30 :     d->lastop = Private::GetAuditLog;
    1052          30 :     Data::Private *const odp = output.impl();
    1053          30 :     return Error(d->lasterr = gpgme_op_getauditlog(d->ctx, odp ? odp->data : 0, to_auditlog_flags(flags)));
    1054             : }
    1055             : 
    1056           7 : void Context::clearSigningKeys()
    1057             : {
    1058           7 :     gpgme_signers_clear(d->ctx);
    1059           7 : }
    1060             : 
    1061           7 : Error Context::addSigningKey(const Key &key)
    1062             : {
    1063           7 :     return Error(d->lasterr = gpgme_signers_add(d->ctx, key.impl()));
    1064             : }
    1065             : 
    1066           0 : Key Context::signingKey(unsigned int idx) const
    1067             : {
    1068           0 :     gpgme_key_t key = gpgme_signers_enum(d->ctx, idx);
    1069           0 :     return Key(key, false);
    1070             : }
    1071             : 
    1072           0 : std::vector<Key> Context::signingKeys() const
    1073             : {
    1074           0 :     std::vector<Key> result;
    1075           0 :     gpgme_key_t key = nullptr;
    1076           0 :     for (unsigned int i = 0 ; (key = gpgme_signers_enum(d->ctx, i)) ; ++i) {
    1077           0 :         result.push_back(Key(key, false));
    1078             :     }
    1079           0 :     return result;
    1080             : }
    1081             : 
    1082           0 : void Context::clearSignatureNotations()
    1083             : {
    1084           0 :     gpgme_sig_notation_clear(d->ctx);
    1085           0 : }
    1086             : 
    1087           0 : GpgME::Error Context::addSignatureNotation(const char *name, const char *value, unsigned int flags)
    1088             : {
    1089           0 :     return Error(gpgme_sig_notation_add(d->ctx, name, value, add_to_gpgme_sig_notation_flags_t(0, flags)));
    1090             : }
    1091             : 
    1092           0 : GpgME::Error Context::addSignaturePolicyURL(const char *url, bool critical)
    1093             : {
    1094           0 :     return Error(gpgme_sig_notation_add(d->ctx, 0, url, critical ? GPGME_SIG_NOTATION_CRITICAL : 0));
    1095             : }
    1096             : 
    1097           0 : const char *Context::signaturePolicyURL() const
    1098             : {
    1099           0 :     for (gpgme_sig_notation_t n = gpgme_sig_notation_get(d->ctx) ; n ; n = n->next) {
    1100           0 :         if (!n->name) {
    1101           0 :             return n->value;
    1102             :         }
    1103             :     }
    1104           0 :     return nullptr;
    1105             : }
    1106             : 
    1107           0 : Notation Context::signatureNotation(unsigned int idx) const
    1108             : {
    1109           0 :     for (gpgme_sig_notation_t n = gpgme_sig_notation_get(d->ctx) ; n ; n = n->next) {
    1110           0 :         if (n->name) {
    1111           0 :             if (idx-- == 0) {
    1112           0 :                 return Notation(n);
    1113             :             }
    1114             :         }
    1115             :     }
    1116           0 :     return Notation();
    1117             : }
    1118             : 
    1119           0 : std::vector<Notation> Context::signatureNotations() const
    1120             : {
    1121           0 :     std::vector<Notation> result;
    1122           0 :     for (gpgme_sig_notation_t n = gpgme_sig_notation_get(d->ctx) ; n ; n = n->next) {
    1123           0 :         if (n->name) {
    1124           0 :             result.push_back(Notation(n));
    1125             :         }
    1126             :     }
    1127           0 :     return result;
    1128             : }
    1129             : 
    1130           6 : static gpgme_sig_mode_t sigmode2sigmode(SignatureMode mode)
    1131             : {
    1132           6 :     switch (mode) {
    1133             :     default:
    1134           6 :     case NormalSignatureMode: return GPGME_SIG_MODE_NORMAL;
    1135           0 :     case Detached:            return GPGME_SIG_MODE_DETACH;
    1136           0 :     case Clearsigned:         return GPGME_SIG_MODE_CLEAR;
    1137             :     }
    1138             : }
    1139             : 
    1140           6 : SigningResult Context::sign(const Data &plainText, Data &signature, SignatureMode mode)
    1141             : {
    1142           6 :     d->lastop = Private::Sign;
    1143           6 :     const Data::Private *const pdp = plainText.impl();
    1144           6 :     Data::Private *const sdp = signature.impl();
    1145           6 :     d->lasterr = gpgme_op_sign(d->ctx, pdp ? pdp->data : 0, sdp ? sdp->data : 0, sigmode2sigmode(mode));
    1146           6 :     return SigningResult(d->ctx, Error(d->lasterr));
    1147             : }
    1148             : 
    1149           0 : Error Context::startSigning(const Data &plainText, Data &signature, SignatureMode mode)
    1150             : {
    1151           0 :     d->lastop = Private::Sign;
    1152           0 :     const Data::Private *const pdp = plainText.impl();
    1153           0 :     Data::Private *const sdp = signature.impl();
    1154           0 :     return Error(d->lasterr = gpgme_op_sign_start(d->ctx, pdp ? pdp->data : 0, sdp ? sdp->data : 0, sigmode2sigmode(mode)));
    1155             : }
    1156             : 
    1157           0 : SigningResult Context::signingResult() const
    1158             : {
    1159           0 :     if (d->lastop & Private::Sign) {
    1160           0 :         return SigningResult(d->ctx, Error(d->lasterr));
    1161             :     } else {
    1162           0 :         return SigningResult();
    1163             :     }
    1164             : }
    1165             : 
    1166           4 : static gpgme_encrypt_flags_t encryptflags2encryptflags(Context::EncryptionFlags flags)
    1167             : {
    1168           4 :     unsigned int result = 0;
    1169           4 :     if (flags & Context::AlwaysTrust) {
    1170           4 :         result |= GPGME_ENCRYPT_ALWAYS_TRUST;
    1171             :     }
    1172           4 :     if (flags & Context::NoEncryptTo) {
    1173           0 :         result |= GPGME_ENCRYPT_NO_ENCRYPT_TO;
    1174             :     }
    1175           4 :     if (flags & Context::Prepare) {
    1176           0 :         result |= GPGME_ENCRYPT_PREPARE;
    1177             :     }
    1178           4 :     if (flags & Context::ExpectSign) {
    1179           0 :         result |= GPGME_ENCRYPT_EXPECT_SIGN;
    1180             :     }
    1181           4 :     if (flags & Context::NoCompress) {
    1182           0 :         result |= GPGME_ENCRYPT_NO_COMPRESS;
    1183             :     }
    1184           4 :     if (flags & Context::Symmetric) {
    1185           0 :         result |= GPGME_ENCRYPT_SYMMETRIC;
    1186             :     }
    1187           4 :     return static_cast<gpgme_encrypt_flags_t>(result);
    1188             : }
    1189             : 
    1190           4 : gpgme_key_t *Context::getKeysFromRecipients(const std::vector<Key> &recipients)
    1191             : {
    1192           4 :     if (recipients.empty()) {
    1193           1 :         return nullptr;
    1194             :     }
    1195           3 :     gpgme_key_t *ret = new gpgme_key_t[ recipients.size() + 1 ];
    1196           3 :     gpgme_key_t *keys_it = ret;
    1197           6 :     for (std::vector<Key>::const_iterator it = recipients.begin() ; it != recipients.end() ; ++it) {
    1198           3 :         if (it->impl()) {
    1199           3 :             *keys_it++ = it->impl();
    1200             :         }
    1201             :     }
    1202           3 :     *keys_it++ = 0;
    1203           3 :     return ret;
    1204             : }
    1205             : 
    1206           3 : EncryptionResult Context::encrypt(const std::vector<Key> &recipients, const Data &plainText, Data &cipherText, EncryptionFlags flags)
    1207             : {
    1208           3 :     d->lastop = Private::Encrypt;
    1209           3 :     if (flags & NoEncryptTo) {
    1210           0 :         return EncryptionResult(Error(d->lasterr = make_error(GPG_ERR_NOT_IMPLEMENTED)));
    1211             :     }
    1212           3 :     const Data::Private *const pdp = plainText.impl();
    1213           3 :     Data::Private *const cdp = cipherText.impl();
    1214           3 :     gpgme_key_t *const keys = getKeysFromRecipients(recipients);
    1215           3 :     d->lasterr = gpgme_op_encrypt(d->ctx, keys, encryptflags2encryptflags(flags),
    1216             :                                   pdp ? pdp->data : 0, cdp ? cdp->data : 0);
    1217           3 :     if (keys) {
    1218           2 :         delete[] keys;
    1219             :     }
    1220           3 :     return EncryptionResult(d->ctx, Error(d->lasterr));
    1221             : }
    1222             : 
    1223           0 : Error Context::encryptSymmetrically(const Data &plainText, Data &cipherText)
    1224             : {
    1225           0 :     d->lastop = Private::Encrypt;
    1226           0 :     const Data::Private *const pdp = plainText.impl();
    1227           0 :     Data::Private *const cdp = cipherText.impl();
    1228           0 :     return Error(d->lasterr = gpgme_op_encrypt(d->ctx, 0, (gpgme_encrypt_flags_t)0,
    1229           0 :                               pdp ? pdp->data : 0, cdp ? cdp->data : 0));
    1230             : }
    1231             : 
    1232           0 : Error Context::startEncryption(const std::vector<Key> &recipients, const Data &plainText, Data &cipherText, EncryptionFlags flags)
    1233             : {
    1234           0 :     d->lastop = Private::Encrypt;
    1235           0 :     if (flags & NoEncryptTo) {
    1236           0 :         return Error(d->lasterr = make_error(GPG_ERR_NOT_IMPLEMENTED));
    1237             :     }
    1238           0 :     const Data::Private *const pdp = plainText.impl();
    1239           0 :     Data::Private *const cdp = cipherText.impl();
    1240           0 :     gpgme_key_t *const keys = getKeysFromRecipients(recipients);
    1241           0 :     d->lasterr = gpgme_op_encrypt_start(d->ctx, keys, encryptflags2encryptflags(flags),
    1242             :                                         pdp ? pdp->data : 0, cdp ? cdp->data : 0);
    1243           0 :     if (keys) {
    1244           0 :         delete[] keys;
    1245             :     }
    1246           0 :     return Error(d->lasterr);
    1247             : }
    1248             : 
    1249           0 : EncryptionResult Context::encryptionResult() const
    1250             : {
    1251           0 :     if (d->lastop & Private::Encrypt) {
    1252           0 :         return EncryptionResult(d->ctx, Error(d->lasterr));
    1253             :     } else {
    1254           0 :         return EncryptionResult();
    1255             :     }
    1256             : }
    1257             : 
    1258           1 : std::pair<SigningResult, EncryptionResult> Context::signAndEncrypt(const std::vector<Key> &recipients, const Data &plainText, Data &cipherText, EncryptionFlags flags)
    1259             : {
    1260           1 :     d->lastop = Private::SignAndEncrypt;
    1261           1 :     const Data::Private *const pdp = plainText.impl();
    1262           1 :     Data::Private *const cdp = cipherText.impl();
    1263           1 :     gpgme_key_t *const keys = getKeysFromRecipients(recipients);
    1264           1 :     d->lasterr = gpgme_op_encrypt_sign(d->ctx, keys, encryptflags2encryptflags(flags),
    1265             :                                        pdp ? pdp->data : 0, cdp ? cdp->data : 0);
    1266           1 :     if (keys) {
    1267           1 :         delete[] keys;
    1268             :     }
    1269           2 :     return std::make_pair(SigningResult(d->ctx, Error(d->lasterr)),
    1270           3 :                           EncryptionResult(d->ctx, Error(d->lasterr)));
    1271             : }
    1272             : 
    1273           0 : Error Context::startCombinedSigningAndEncryption(const std::vector<Key> &recipients, const Data &plainText, Data &cipherText, EncryptionFlags flags)
    1274             : {
    1275           0 :     d->lastop = Private::SignAndEncrypt;
    1276           0 :     const Data::Private *const pdp = plainText.impl();
    1277           0 :     Data::Private *const cdp = cipherText.impl();
    1278           0 :     gpgme_key_t *const keys = getKeysFromRecipients(recipients);
    1279           0 :     d->lasterr = gpgme_op_encrypt_sign_start(d->ctx, keys, encryptflags2encryptflags(flags),
    1280             :                  pdp ? pdp->data : 0, cdp ? cdp->data : 0);
    1281           0 :     if (keys) {
    1282           0 :         delete[] keys;
    1283             :     }
    1284           0 :     return Error(d->lasterr);
    1285             : }
    1286             : 
    1287           0 : Error Context::createVFS(const char *containerFile, const std::vector< Key > &recipients)
    1288             : {
    1289           0 :     d->lastop = Private::CreateVFS;
    1290           0 :     gpgme_key_t *const keys = new gpgme_key_t[ recipients.size() + 1 ];
    1291           0 :     gpgme_key_t *keys_it = keys;
    1292           0 :     for (std::vector<Key>::const_iterator it = recipients.begin() ; it != recipients.end() ; ++it) {
    1293           0 :         if (it->impl()) {
    1294           0 :             *keys_it++ = it->impl();
    1295             :         }
    1296             :     }
    1297           0 :     *keys_it++ = 0;
    1298             : 
    1299             :     gpgme_error_t op_err;
    1300           0 :     d->lasterr = gpgme_op_vfs_create(d->ctx, keys, containerFile, 0, &op_err);
    1301           0 :     delete[] keys;
    1302           0 :     Error error(d->lasterr);
    1303           0 :     if (error) {
    1304           0 :         return error;
    1305             :     }
    1306           0 :     return Error(d->lasterr = op_err);
    1307             : }
    1308             : 
    1309           0 : VfsMountResult Context::mountVFS(const char *containerFile, const char *mountDir)
    1310             : {
    1311           0 :     d->lastop = Private::MountVFS;
    1312             :     gpgme_error_t op_err;
    1313           0 :     d->lasterr = gpgme_op_vfs_mount(d->ctx, containerFile, mountDir, 0, &op_err);
    1314           0 :     return VfsMountResult(d->ctx, Error(d->lasterr), Error(op_err));
    1315             : }
    1316             : 
    1317          17 : Error Context::cancelPendingOperation()
    1318             : {
    1319          17 :     return Error(gpgme_cancel_async(d->ctx));
    1320             : }
    1321             : 
    1322           0 : bool Context::poll()
    1323             : {
    1324           0 :     gpgme_error_t e = GPG_ERR_NO_ERROR;
    1325           0 :     const bool finished = gpgme_wait(d->ctx, &e, 0);
    1326           0 :     if (finished) {
    1327           0 :         d->lasterr = e;
    1328             :     }
    1329           0 :     return finished;
    1330             : }
    1331             : 
    1332           0 : Error Context::wait()
    1333             : {
    1334           0 :     gpgme_error_t e = GPG_ERR_NO_ERROR;
    1335           0 :     gpgme_wait(d->ctx, &e, 1);
    1336           0 :     return Error(d->lasterr = e);
    1337             : }
    1338             : 
    1339           0 : Error Context::lastError() const
    1340             : {
    1341           0 :     return Error(d->lasterr);
    1342             : }
    1343             : 
    1344           0 : Context::PinentryMode Context::pinentryMode() const
    1345             : {
    1346           0 :     switch (gpgme_get_pinentry_mode (d->ctx)) {
    1347             :         case GPGME_PINENTRY_MODE_ASK:
    1348           0 :             return PinentryAsk;
    1349             :         case GPGME_PINENTRY_MODE_CANCEL:
    1350           0 :             return PinentryCancel;
    1351             :         case GPGME_PINENTRY_MODE_ERROR:
    1352           0 :             return PinentryError;
    1353             :         case GPGME_PINENTRY_MODE_LOOPBACK:
    1354           0 :             return PinentryLoopback;
    1355             :         case GPGME_PINENTRY_MODE_DEFAULT:
    1356             :         default:
    1357           0 :             return PinentryDefault;
    1358             :     }
    1359             : }
    1360             : 
    1361          12 : Error Context::setPinentryMode(PinentryMode which)
    1362             : {
    1363             :     gpgme_pinentry_mode_t mode;
    1364          12 :     switch (which) {
    1365             :         case PinentryAsk:
    1366           0 :             mode = GPGME_PINENTRY_MODE_ASK;
    1367           0 :             break;
    1368             :         case PinentryCancel:
    1369           0 :             mode = GPGME_PINENTRY_MODE_CANCEL;
    1370           0 :             break;
    1371             :         case PinentryError:
    1372           0 :             mode = GPGME_PINENTRY_MODE_ERROR;
    1373           0 :             break;
    1374             :         case PinentryLoopback:
    1375          12 :             mode = GPGME_PINENTRY_MODE_LOOPBACK;
    1376          12 :             break;
    1377             :         case PinentryDefault:
    1378             :         default:
    1379           0 :             mode = GPGME_PINENTRY_MODE_DEFAULT;
    1380             :     }
    1381          12 :     return Error(d->lasterr = gpgme_set_pinentry_mode(d->ctx, mode));
    1382             : }
    1383             : 
    1384           2 : static gpgme_tofu_policy_t to_tofu_policy_t(unsigned int policy)
    1385             : {
    1386           2 :     switch (policy) {
    1387             :         case TofuInfo::PolicyNone:
    1388           0 :             return GPGME_TOFU_POLICY_NONE;
    1389             :         case TofuInfo::PolicyAuto:
    1390           0 :             return GPGME_TOFU_POLICY_AUTO;
    1391             :         case TofuInfo::PolicyGood:
    1392           1 :             return GPGME_TOFU_POLICY_GOOD;
    1393             :         case TofuInfo::PolicyBad:
    1394           1 :             return GPGME_TOFU_POLICY_BAD;
    1395             :         case TofuInfo::PolicyAsk:
    1396           0 :             return GPGME_TOFU_POLICY_ASK;
    1397             :         case TofuInfo::PolicyUnknown:
    1398             :         default:
    1399           0 :             return GPGME_TOFU_POLICY_UNKNOWN;
    1400             :     }
    1401             : }
    1402             : 
    1403           2 : Error Context::setTofuPolicy(const Key &k, unsigned int policy)
    1404             : {
    1405           4 :     return Error(d->lasterr = gpgme_op_tofu_policy(d->ctx,
    1406           4 :                  k.impl(), to_tofu_policy_t(policy)));
    1407             : }
    1408             : 
    1409           0 : Error Context::setTofuPolicyStart(const Key &k, unsigned int policy)
    1410             : {
    1411           0 :     return Error(d->lasterr = gpgme_op_tofu_policy_start(d->ctx,
    1412           0 :                  k.impl(), to_tofu_policy_t(policy)));
    1413             : }
    1414             : 
    1415           0 : Error Context::startCreateKey (const char *userid,
    1416             :                                const char *algo,
    1417             :                                unsigned long reserved,
    1418             :                                unsigned long expires,
    1419             :                                const Key &certkey,
    1420             :                                unsigned int flags)
    1421             : {
    1422           0 :     return Error(d->lasterr = gpgme_op_createkey_start(d->ctx,
    1423             :                  userid,
    1424             :                  algo,
    1425             :                  reserved,
    1426             :                  expires,
    1427             :                  certkey.impl(),
    1428           0 :                  flags));
    1429             : }
    1430             : 
    1431           0 : Error Context::createKey (const char *userid,
    1432             :                           const char *algo,
    1433             :                           unsigned long reserved,
    1434             :                           unsigned long expires,
    1435             :                           const Key &certkey,
    1436             :                           unsigned int flags)
    1437             : {
    1438           0 :     return Error(d->lasterr = gpgme_op_createkey(d->ctx,
    1439             :                  userid,
    1440             :                  algo,
    1441             :                  reserved,
    1442             :                  expires,
    1443             :                  certkey.impl(),
    1444           0 :                  flags));
    1445             : }
    1446             : 
    1447           0 : KeyGenerationResult Context::createKeyEx (const char *userid,
    1448             :                                           const char *algo,
    1449             :                                           unsigned long reserved,
    1450             :                                           unsigned long expires,
    1451             :                                           const Key &certkey,
    1452             :                                           unsigned int flags)
    1453             : {
    1454           0 :     d->lasterr = gpgme_op_createkey(d->ctx,
    1455             :                  userid,
    1456             :                  algo,
    1457             :                  reserved,
    1458             :                  expires,
    1459             :                  certkey.impl(),
    1460             :                  flags);
    1461           0 :     return KeyGenerationResult(d->ctx, Error(d->lasterr));
    1462             : }
    1463             : 
    1464           1 : Error Context::addUid(const Key &k, const char *userid)
    1465             : {
    1466           2 :     return Error(d->lasterr = gpgme_op_adduid(d->ctx,
    1467           2 :                  k.impl(), userid, 0));
    1468             : }
    1469             : 
    1470           0 : Error Context::startAddUid(const Key &k, const char *userid)
    1471             : {
    1472           0 :     return Error(d->lasterr = gpgme_op_adduid_start(d->ctx,
    1473           0 :                  k.impl(), userid, 0));
    1474             : }
    1475             : 
    1476           1 : Error Context::revUid(const Key &k, const char *userid)
    1477             : {
    1478           2 :     return Error(d->lasterr = gpgme_op_revuid(d->ctx,
    1479           2 :                  k.impl(), userid, 0));
    1480             : }
    1481             : 
    1482           0 : Error Context::startRevUid(const Key &k, const char *userid)
    1483             : {
    1484           0 :     return Error(d->lasterr = gpgme_op_revuid_start(d->ctx,
    1485           0 :                  k.impl(), userid, 0));
    1486             : }
    1487             : 
    1488           0 : Error Context::createSubkey(const Key &k, const char *algo,
    1489             :                             unsigned long reserved,
    1490             :                             unsigned long expires,
    1491             :                             unsigned int flags)
    1492             : {
    1493           0 :     return Error(d->lasterr = gpgme_op_createsubkey(d->ctx,
    1494           0 :                  k.impl(), algo, reserved, expires, flags));
    1495             : }
    1496             : 
    1497           0 : Error Context::startCreateSubkey(const Key &k, const char *algo,
    1498             :                                  unsigned long reserved,
    1499             :                                  unsigned long expires,
    1500             :                                  unsigned int flags)
    1501             : {
    1502           0 :     return Error(d->lasterr = gpgme_op_createsubkey_start(d->ctx,
    1503           0 :                  k.impl(), algo, reserved, expires, flags));
    1504             : }
    1505             : 
    1506           0 : Error Context::setFlag(const char *name, const char *value)
    1507             : {
    1508           0 :   return Error(d->lasterr = gpgme_set_ctx_flag(d->ctx, name, value));
    1509             : }
    1510             : 
    1511           0 : const char *Context::getFlag(const char *name) const
    1512             : {
    1513           0 :   return gpgme_get_ctx_flag(d->ctx, name);
    1514             : }
    1515             : 
    1516             : // Engine Spawn stuff
    1517           0 : Error Context::spawn(const char *file, const char *argv[],
    1518             :                      Data &input, Data &output, Data &err,
    1519             :                      SpawnFlags flags)
    1520             : {
    1521           0 :     return Error(d->lasterr = gpgme_op_spawn (d->ctx, file, argv,
    1522           0 :         input.impl() ? input.impl()->data : nullptr,
    1523           0 :         output.impl() ? output.impl()->data : nullptr,
    1524           0 :         err.impl() ? err.impl()->data : nullptr,
    1525           0 :         static_cast<int>(flags)));
    1526             : }
    1527             : 
    1528           0 : Error Context::spawnAsync(const char *file, const char *argv[],
    1529             :                           Data &input, Data &output, Data &err,
    1530             :                           SpawnFlags flags)
    1531             : {
    1532           0 :     return Error(d->lasterr = gpgme_op_spawn_start (d->ctx, file, argv,
    1533           0 :         input.impl() ? input.impl()->data : nullptr,
    1534           0 :         output.impl() ? output.impl()->data : nullptr,
    1535           0 :         err.impl() ? err.impl()->data : nullptr,
    1536           0 :         static_cast<int>(flags)));
    1537             : }
    1538             : 
    1539           0 : std::ostream &operator<<(std::ostream &os, Protocol proto)
    1540             : {
    1541           0 :     os << "GpgME::Protocol(";
    1542           0 :     switch (proto) {
    1543             :     case OpenPGP:
    1544           0 :         os << "OpenPGP";
    1545           0 :         break;
    1546             :     case CMS:
    1547           0 :         os << "CMS";
    1548           0 :         break;
    1549             :     default:
    1550             :     case UnknownProtocol:
    1551           0 :         os << "UnknownProtocol";
    1552           0 :         break;
    1553             :     }
    1554           0 :     return os << ')';
    1555             : }
    1556             : 
    1557           0 : std::ostream &operator<<(std::ostream &os, Engine eng)
    1558             : {
    1559           0 :     os << "GpgME::Engine(";
    1560           0 :     switch (eng) {
    1561             :     case GpgEngine:
    1562           0 :         os << "GpgEngine";
    1563           0 :         break;
    1564             :     case GpgSMEngine:
    1565           0 :         os << "GpgSMEngine";
    1566           0 :         break;
    1567             :     case GpgConfEngine:
    1568           0 :         os << "GpgConfEngine";
    1569           0 :         break;
    1570             :     case AssuanEngine:
    1571           0 :         os << "AssuanEngine";
    1572           0 :         break;
    1573             :     case SpawnEngine:
    1574           0 :         os << "SpawnEngine";
    1575           0 :         break;
    1576             :     default:
    1577             :     case UnknownEngine:
    1578           0 :         os << "UnknownEngine";
    1579           0 :         break;
    1580             :     }
    1581           0 :     return os << ')';
    1582             : }
    1583             : 
    1584           0 : std::ostream &operator<<(std::ostream &os, Context::CertificateInclusion incl)
    1585             : {
    1586           0 :     os << "GpgME::Context::CertificateInclusion(" << static_cast<int>(incl);
    1587           0 :     switch (incl) {
    1588             :     case Context::DefaultCertificates:
    1589           0 :         os << "(DefaultCertificates)";
    1590           0 :         break;
    1591             :     case Context::AllCertificatesExceptRoot:
    1592           0 :         os << "(AllCertificatesExceptRoot)";
    1593           0 :         break;
    1594             :     case Context::AllCertificates:
    1595           0 :         os << "(AllCertificates)";
    1596           0 :         break;
    1597             :     case Context::NoCertificates:
    1598           0 :         os << "(NoCertificates)";
    1599           0 :         break;
    1600             :     case Context::OnlySenderCertificate:
    1601           0 :         os << "(OnlySenderCertificate)";
    1602           0 :         break;
    1603             :     }
    1604           0 :     return os << ')';
    1605             : }
    1606             : 
    1607           0 : std::ostream &operator<<(std::ostream &os, KeyListMode mode)
    1608             : {
    1609           0 :     os << "GpgME::KeyListMode(";
    1610             : #define CHECK( x ) if ( !(mode & (x)) ) {} else do { os << #x " "; } while (0)
    1611           0 :     CHECK(Local);
    1612           0 :     CHECK(Extern);
    1613           0 :     CHECK(Signatures);
    1614           0 :     CHECK(Validate);
    1615           0 :     CHECK(Ephemeral);
    1616           0 :     CHECK(WithTofu);
    1617             : #undef CHECK
    1618           0 :     return os << ')';
    1619             : }
    1620             : 
    1621           0 : std::ostream &operator<<(std::ostream &os, SignatureMode mode)
    1622             : {
    1623           0 :     os << "GpgME::SignatureMode(";
    1624           0 :     switch (mode) {
    1625             : #define CHECK( x ) case x: os << #x; break
    1626           0 :         CHECK(NormalSignatureMode);
    1627           0 :         CHECK(Detached);
    1628           0 :         CHECK(Clearsigned);
    1629             : #undef CHECK
    1630             :     default:
    1631           0 :         os << "???" "(" << static_cast<int>(mode) << ')';
    1632           0 :         break;
    1633             :     }
    1634           0 :     return os << ')';
    1635             : }
    1636             : 
    1637           0 : std::ostream &operator<<(std::ostream &os, Context::EncryptionFlags flags)
    1638             : {
    1639           0 :     os << "GpgME::Context::EncryptionFlags(";
    1640             : #define CHECK( x ) if ( !(flags & (Context::x)) ) {} else do { os << #x " "; } while (0)
    1641           0 :     CHECK(AlwaysTrust);
    1642           0 :     CHECK(NoEncryptTo);
    1643           0 :     CHECK(Prepare);
    1644           0 :     CHECK(ExpectSign);
    1645           0 :     CHECK(NoCompress);
    1646           0 :     CHECK(Symmetric);
    1647             : #undef CHECK
    1648           0 :     return os << ')';
    1649             : }
    1650             : 
    1651           0 : std::ostream &operator<<(std::ostream &os, Context::AuditLogFlags flags)
    1652             : {
    1653           0 :     os << "GpgME::Context::AuditLogFlags(";
    1654             : #define CHECK( x ) if ( !(flags & (Context::x)) ) {} else do { os << #x " "; } while (0)
    1655           0 :     CHECK(HtmlAuditLog);
    1656           0 :     CHECK(AuditLogWithHelp);
    1657             : #undef CHECK
    1658           0 :     return os << ')';
    1659             : }
    1660             : 
    1661             : } // namespace GpgME
    1662             : 
    1663           0 : GpgME::Error GpgME::setDefaultLocale(int cat, const char *val)
    1664             : {
    1665           0 :     return Error(gpgme_set_locale(0, cat, val));
    1666             : }
    1667             : 
    1668           0 : GpgME::EngineInfo GpgME::engineInfo(GpgME::Protocol proto)
    1669             : {
    1670           0 :     gpgme_engine_info_t ei = 0;
    1671           0 :     if (gpgme_get_engine_info(&ei)) {
    1672           0 :         return EngineInfo();
    1673             :     }
    1674             : 
    1675           0 :     const gpgme_protocol_t p = proto == CMS ? GPGME_PROTOCOL_CMS : GPGME_PROTOCOL_OpenPGP ;
    1676             : 
    1677           0 :     for (gpgme_engine_info_t i = ei ; i ; i = i->next) {
    1678           0 :         if (i->protocol == p) {
    1679           0 :             return EngineInfo(i);
    1680             :         }
    1681             :     }
    1682             : 
    1683           0 :     return EngineInfo();
    1684             : }
    1685             : 
    1686           0 : const char *GpgME::dirInfo(const char *what)
    1687             : {
    1688           0 :     return gpgme_get_dirinfo(what);
    1689             : }
    1690             : 
    1691           7 : GpgME::Error GpgME::checkEngine(GpgME::Protocol proto)
    1692             : {
    1693           7 :     const gpgme_protocol_t p = proto == CMS ? GPGME_PROTOCOL_CMS : GPGME_PROTOCOL_OpenPGP ;
    1694             : 
    1695           7 :     return Error(gpgme_engine_check_version(p));
    1696             : }
    1697             : 
    1698             : static const gpgme_protocol_t UNKNOWN_PROTOCOL = static_cast<gpgme_protocol_t>(255);
    1699             : 
    1700           9 : static gpgme_protocol_t engine2protocol(const GpgME::Engine engine)
    1701             : {
    1702           9 :     switch (engine) {
    1703           9 :     case GpgME::GpgEngine:   return GPGME_PROTOCOL_OpenPGP;
    1704           0 :     case GpgME::GpgSMEngine: return GPGME_PROTOCOL_CMS;
    1705             :     case GpgME::GpgConfEngine:
    1706           0 :         return GPGME_PROTOCOL_GPGCONF;
    1707             :     case GpgME::AssuanEngine:
    1708           0 :         return GPGME_PROTOCOL_ASSUAN;
    1709             :     case GpgME::G13Engine:
    1710           0 :         return GPGME_PROTOCOL_G13;
    1711             :     case GpgME::SpawnEngine:
    1712           0 :         return GPGME_PROTOCOL_SPAWN;
    1713             :     case GpgME::UnknownEngine:
    1714             :         ;
    1715             :     }
    1716           0 :     return UNKNOWN_PROTOCOL;
    1717             : }
    1718             : 
    1719           9 : GpgME::EngineInfo GpgME::engineInfo(GpgME::Engine engine)
    1720             : {
    1721           9 :     gpgme_engine_info_t ei = 0;
    1722           9 :     if (gpgme_get_engine_info(&ei)) {
    1723           0 :         return EngineInfo();
    1724             :     }
    1725             : 
    1726           9 :     const gpgme_protocol_t p = engine2protocol(engine);
    1727             : 
    1728           9 :     for (gpgme_engine_info_t i = ei ; i ; i = i->next) {
    1729           9 :         if (i->protocol == p) {
    1730           9 :             return EngineInfo(i);
    1731             :         }
    1732             :     }
    1733             : 
    1734           0 :     return EngineInfo();
    1735             : }
    1736             : 
    1737           0 : GpgME::Error GpgME::checkEngine(GpgME::Engine engine)
    1738             : {
    1739           0 :     const gpgme_protocol_t p = engine2protocol(engine);
    1740             : 
    1741           0 :     return Error(gpgme_engine_check_version(p));
    1742             : }
    1743             : 
    1744             : static const unsigned long supported_features = 0
    1745             :         | GpgME::ValidatingKeylistModeFeature
    1746             :         | GpgME::CancelOperationFeature
    1747             :         | GpgME::WrongKeyUsageFeature
    1748             :         | GpgME::DefaultCertificateInclusionFeature
    1749             :         | GpgME::GetSetEngineInfoFeature
    1750             :         | GpgME::ClearAddGetSignatureNotationsFeature
    1751             :         | GpgME::SetDataFileNameFeeature
    1752             :         | GpgME::SignatureNotationsKeylistModeFeature
    1753             :         | GpgME::KeySignatureNotationsFeature
    1754             :         | GpgME::KeyIsQualifiedFeature
    1755             :         | GpgME::SignatureNotationsCriticalFlagFeature
    1756             :         | GpgME::SignatureNotationsFlagsFeature
    1757             :         | GpgME::SignatureNotationsHumanReadableFlagFeature
    1758             :         | GpgME::SubkeyIsQualifiedFeature
    1759             :         | GpgME::EngineInfoHomeDirFeature
    1760             :         | GpgME::DecryptionResultFileNameFeature
    1761             :         | GpgME::DecryptionResultRecipientsFeature
    1762             :         | GpgME::VerificationResultFileNameFeature
    1763             :         | GpgME::SignaturePkaFieldsFeature
    1764             :         | GpgME::SignatureAlgorithmFieldsFeature
    1765             :         | GpgME::FdPointerFeature
    1766             :         | GpgME::AuditLogFeature
    1767             :         | GpgME::GpgConfEngineFeature
    1768             :         | GpgME::CancelOperationAsyncFeature
    1769             :         | GpgME::NoEncryptToEncryptionFlagFeature
    1770             :         | GpgME::CardKeyFeature
    1771             :         | GpgME::AssuanEngineFeature
    1772             :         | GpgME::EphemeralKeylistModeFeature
    1773             :         | GpgME::ImportFromKeyserverFeature
    1774             :         | GpgME::G13VFSFeature
    1775             :         | GpgME::PasswdFeature
    1776             :         ;
    1777             : 
    1778             : static const unsigned long supported_features2 = 0
    1779             :         | GpgME::BinaryAndFineGrainedIdentify
    1780             :         ;
    1781             : 
    1782           0 : bool GpgME::hasFeature(unsigned long features)
    1783             : {
    1784           0 :     return features == (features & supported_features);
    1785             : }
    1786             : 
    1787           1 : bool GpgME::hasFeature(unsigned long features, unsigned long features2)
    1788             : {
    1789           1 :     return features  == (features  & supported_features)
    1790           1 :            && features2 == (features2 & supported_features2)
    1791             :            ;
    1792          24 : }

Generated by: LCOV version 1.13