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