Imported Upstream version 1.14.0
[platform/upstream/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, unsigned int flags)
567 {
568     d->lastop = Private::Export;
569     Data::Private *const dp = keyData.impl();
570     return Error(d->lasterr = gpgme_op_export(d->ctx, pattern, flags, dp ? dp->data : nullptr));
571 }
572
573 Error Context::exportPublicKeys(const char *patterns[], Data &keyData, unsigned int flags)
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, flags);
580     }
581 #endif
582     Data::Private *const dp = keyData.impl();
583     return Error(d->lasterr = gpgme_op_export_ext(d->ctx, patterns, flags, dp ? dp->data : nullptr));
584 }
585
586 Error Context::startPublicKeyExport(const char *pattern, Data &keyData, unsigned int flags)
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, flags, dp ? dp->data : nullptr));
591 }
592
593 Error Context::startPublicKeyExport(const char *patterns[], Data &keyData, unsigned int flags)
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, flags);
600     }
601 #endif
602     Data::Private *const dp = keyData.impl();
603     return Error(d->lasterr = gpgme_op_export_ext_start(d->ctx, patterns, flags, dp ? dp->data : nullptr));
604 }
605
606
607 /* Same as above but without flags  */
608 Error Context::exportPublicKeys(const char *pattern, Data &keyData)
609 {
610     return exportPublicKeys(pattern, keyData, 0);
611 }
612
613 Error Context::exportPublicKeys(const char *patterns[], Data &keyData)
614 {
615     return exportPublicKeys(patterns, keyData, 0);
616 }
617
618 Error Context::startPublicKeyExport(const char *pattern, Data &keyData)
619 {
620     return startPublicKeyExport(pattern, keyData, 0);
621 }
622
623 Error Context::startPublicKeyExport(const char *patterns[], Data &keyData)
624 {
625     return startPublicKeyExport(patterns, keyData, 0);
626 }
627
628 ImportResult Context::importKeys(const Data &data)
629 {
630     d->lastop = Private::Import;
631     const Data::Private *const dp = data.impl();
632     d->lasterr = gpgme_op_import(d->ctx, dp ? dp->data : nullptr);
633     return ImportResult(d->ctx, Error(d->lasterr));
634 }
635
636 ImportResult Context::importKeys(const std::vector<Key> &kk)
637 {
638     d->lastop = Private::Import;
639     d->lasterr = make_error(GPG_ERR_NOT_IMPLEMENTED);
640
641     bool shouldHaveResult = false;
642     gpgme_key_t * const keys = new gpgme_key_t[ kk.size() + 1 ];
643     gpgme_key_t *keys_it = &keys[0];
644     for (std::vector<Key>::const_iterator it = kk.begin(), end = kk.end() ; it != end ; ++it) {
645         if (it->impl()) {
646             *keys_it++ = it->impl();
647         }
648     }
649     *keys_it++ = nullptr;
650     d->lasterr = gpgme_op_import_keys(d->ctx, keys);
651     shouldHaveResult = true;
652     if ((gpgme_err_code(d->lasterr) == GPG_ERR_NOT_IMPLEMENTED ||
653             gpgme_err_code(d->lasterr) == GPG_ERR_NOT_SUPPORTED) &&
654             protocol() == CMS) {
655         // ok, try the workaround (export+import):
656         std::vector<const char *> fprs;
657         for (std::vector<Key>::const_iterator it = kk.begin(), end = kk.end() ; it != end ; ++it) {
658             if (const char *fpr = it->primaryFingerprint()) {
659                 if (*fpr) {
660                     fprs.push_back(fpr);
661                 }
662             } else if (const char *keyid = it->keyID()) {
663                 if (*keyid) {
664                     fprs.push_back(keyid);
665                 }
666             }
667         }
668         fprs.push_back(nullptr);
669         Data data;
670         Data::Private *const dp = data.impl();
671         const gpgme_keylist_mode_t oldMode = gpgme_get_keylist_mode(d->ctx);
672         gpgme_set_keylist_mode(d->ctx, GPGME_KEYLIST_MODE_EXTERN);
673         d->lasterr = gpgme_op_export_ext(d->ctx, &fprs[0], 0, dp ? dp->data : nullptr);
674         gpgme_set_keylist_mode(d->ctx, oldMode);
675         if (!d->lasterr) {
676             data.seek(0, SEEK_SET);
677             d->lasterr = gpgme_op_import(d->ctx, dp ? dp->data : nullptr);
678             shouldHaveResult = true;
679         }
680     }
681     delete[] keys;
682     if (shouldHaveResult) {
683         return ImportResult(d->ctx, Error(d->lasterr));
684     } else {
685         return ImportResult(Error(d->lasterr));
686     }
687 }
688
689 Error Context::startKeyImport(const Data &data)
690 {
691     d->lastop = Private::Import;
692     const Data::Private *const dp = data.impl();
693     return Error(d->lasterr = gpgme_op_import_start(d->ctx, dp ? dp->data : nullptr));
694 }
695
696 Error Context::startKeyImport(const std::vector<Key> &kk)
697 {
698     d->lastop = Private::Import;
699     gpgme_key_t * const keys = new gpgme_key_t[ kk.size() + 1 ];
700     gpgme_key_t *keys_it = &keys[0];
701     for (std::vector<Key>::const_iterator it = kk.begin(), end = kk.end() ; it != end ; ++it) {
702         if (it->impl()) {
703             *keys_it++ = it->impl();
704         }
705     }
706     *keys_it++ = nullptr;
707     Error err = Error(d->lasterr = gpgme_op_import_keys_start(d->ctx, keys));
708     delete[] keys;
709     return err;
710 }
711
712 ImportResult Context::importResult() const
713 {
714     if (d->lastop & Private::Import) {
715         return ImportResult(d->ctx, Error(d->lasterr));
716     } else {
717         return ImportResult();
718     }
719 }
720
721 Error Context::deleteKey(const Key &key, bool allowSecretKeyDeletion)
722 {
723     d->lastop = Private::Delete;
724     return Error(d->lasterr = gpgme_op_delete(d->ctx, key.impl(), int(allowSecretKeyDeletion)));
725 }
726
727 Error Context::startKeyDeletion(const Key &key, bool allowSecretKeyDeletion)
728 {
729     d->lastop = Private::Delete;
730     return Error(d->lasterr = gpgme_op_delete_start(d->ctx, key.impl(), int(allowSecretKeyDeletion)));
731 }
732
733 Error Context::passwd(const Key &key)
734 {
735     d->lastop = Private::Passwd;
736     return Error(d->lasterr = gpgme_op_passwd(d->ctx, key.impl(), 0U));
737 }
738
739 Error Context::startPasswd(const Key &key)
740 {
741     d->lastop = Private::Passwd;
742     return Error(d->lasterr = gpgme_op_passwd_start(d->ctx, key.impl(), 0U));
743 }
744
745
746 #pragma GCC diagnostic push
747 #pragma GCC diagnostic ignored "-Wdeprecated-declarations"
748
749 Error Context::edit(const Key &key, std::unique_ptr<EditInteractor> func, Data &data)
750 {
751     d->lastop = Private::Edit;
752     d->lastEditInteractor = std::move(func);
753     Data::Private *const dp = data.impl();
754     return Error(d->lasterr = gpgme_op_edit(d->ctx, key.impl(),
755                                             d->lastEditInteractor.get() ? edit_interactor_callback : nullptr,
756                                             d->lastEditInteractor.get() ? d->lastEditInteractor->d : nullptr,
757                                             dp ? dp->data : nullptr));
758 }
759
760
761 Error Context::startEditing(const Key &key, std::unique_ptr<EditInteractor> func, Data &data)
762 {
763     d->lastop = Private::Edit;
764     d->lastEditInteractor = std::move(func);
765     Data::Private *const dp = data.impl();
766     return Error(d->lasterr = gpgme_op_edit_start(d->ctx, key.impl(),
767                               d->lastEditInteractor.get() ? edit_interactor_callback : nullptr,
768                               d->lastEditInteractor.get() ? d->lastEditInteractor->d : nullptr,
769                               dp ? dp->data : nullptr));
770 }
771
772
773 EditInteractor *Context::lastEditInteractor() const
774 {
775     return d->lastEditInteractor.get();
776 }
777
778 std::unique_ptr<EditInteractor> Context::takeLastEditInteractor()
779 {
780     return std::move(d->lastEditInteractor);
781 }
782
783
784 Error Context::cardEdit(const Key &key, std::unique_ptr<EditInteractor> func, Data &data)
785 {
786     d->lastop = Private::CardEdit;
787     d->lastCardEditInteractor = std::move(func);
788     Data::Private *const dp = data.impl();
789     return Error(d->lasterr = gpgme_op_card_edit(d->ctx, key.impl(),
790                               d->lastCardEditInteractor.get() ? edit_interactor_callback : nullptr,
791                               d->lastCardEditInteractor.get() ? d->lastCardEditInteractor->d : nullptr,
792                               dp ? dp->data : nullptr));
793 }
794
795 Error Context::startCardEditing(const Key &key, std::unique_ptr<EditInteractor> func, Data &data)
796 {
797     d->lastop = Private::CardEdit;
798     d->lastCardEditInteractor = std::move(func);
799     Data::Private *const dp = data.impl();
800     return Error(d->lasterr = gpgme_op_card_edit_start(d->ctx, key.impl(),
801                               d->lastCardEditInteractor.get() ? edit_interactor_callback : nullptr,
802                               d->lastCardEditInteractor.get() ? d->lastCardEditInteractor->d : nullptr,
803                               dp ? dp->data : nullptr));
804 }
805
806 #pragma GCC diagnostic pop
807
808 EditInteractor *Context::lastCardEditInteractor() const
809 {
810     return d->lastCardEditInteractor.get();
811 }
812
813 std::unique_ptr<EditInteractor> Context::takeLastCardEditInteractor()
814 {
815     return std::move(d->lastCardEditInteractor);
816 }
817
818 Error Context::startTrustItemListing(const char *pattern, int maxLevel)
819 {
820     d->lastop = Private::TrustList;
821     return Error(d->lasterr = gpgme_op_trustlist_start(d->ctx, pattern, maxLevel));
822 }
823
824 TrustItem Context::nextTrustItem(Error &e)
825 {
826     gpgme_trust_item_t ti = nullptr;
827     e = Error(d->lasterr = gpgme_op_trustlist_next(d->ctx, &ti));
828     return TrustItem(ti);
829 }
830
831 Error Context::endTrustItemListing()
832 {
833     return Error(d->lasterr = gpgme_op_trustlist_end(d->ctx));
834 }
835
836 static gpgme_error_t assuan_transaction_data_callback(void *opaque, const void *data, size_t datalen)
837 {
838     assert(opaque);
839     AssuanTransaction *t = static_cast<AssuanTransaction *>(opaque);
840     return t->data(static_cast<const char *>(data), datalen).encodedError();
841 }
842
843 static gpgme_error_t assuan_transaction_inquire_callback(void *opaque, const char *name, const char *args, gpgme_data_t *r_data)
844 {
845     assert(opaque);
846     Context::Private *p = static_cast<Context::Private *>(opaque);
847     AssuanTransaction *t = p->lastAssuanTransaction.get();
848     assert(t);
849     Error err;
850     if (name) {
851         p->lastAssuanInquireData = t->inquire(name, args, err);
852     } else {
853         p->lastAssuanInquireData = Data::null;
854     }
855     if (!p->lastAssuanInquireData.isNull()) {
856         *r_data = p->lastAssuanInquireData.impl()->data;
857     }
858     return err.encodedError();
859 }
860
861 static gpgme_error_t assuan_transaction_status_callback(void *opaque, const char *status, const char *args)
862 {
863     assert(opaque);
864     AssuanTransaction *t = static_cast<AssuanTransaction *>(opaque);
865     std::string a = args;
866     percent_unescape(a, true);   // ### why doesn't gpgme do this??
867     return t->status(status, a.c_str()).encodedError();
868 }
869
870 Error Context::assuanTransact(const char *command)
871 {
872     return assuanTransact(command, std::unique_ptr<AssuanTransaction>(new DefaultAssuanTransaction));
873 }
874
875 Error Context::assuanTransact(const char *command, std::unique_ptr<AssuanTransaction> transaction)
876 {
877     gpgme_error_t err, operr;
878
879     d->lastop = Private::AssuanTransact;
880     d->lastAssuanTransaction = std::move(transaction);
881     if (!d->lastAssuanTransaction.get()) {
882         return Error(d->lasterr = make_error(GPG_ERR_INV_ARG));
883     }
884     err = gpgme_op_assuan_transact_ext
885       (d->ctx,
886        command,
887        assuan_transaction_data_callback,
888        d->lastAssuanTransaction.get(),
889        assuan_transaction_inquire_callback,
890        d,
891        assuan_transaction_status_callback,
892        d->lastAssuanTransaction.get(),
893        &operr);
894
895     if (!err)
896       err = operr;
897     d->lasterr = err;
898
899     return Error(d->lasterr);
900 }
901
902 Error Context::startAssuanTransaction(const char *command)
903 {
904     return startAssuanTransaction(command, std::unique_ptr<AssuanTransaction>(new DefaultAssuanTransaction));
905 }
906
907 Error Context::startAssuanTransaction(const char *command, std::unique_ptr<AssuanTransaction> transaction)
908 {
909     gpgme_error_t err;
910
911     d->lastop = Private::AssuanTransact;
912     d->lastAssuanTransaction = std::move(transaction);
913     if (!d->lastAssuanTransaction.get()) {
914         return Error(d->lasterr = make_error(GPG_ERR_INV_ARG));
915     }
916     err = gpgme_op_assuan_transact_start
917       (d->ctx,
918        command,
919        assuan_transaction_data_callback,
920        d->lastAssuanTransaction.get(),
921        assuan_transaction_inquire_callback,
922        d,
923        assuan_transaction_status_callback,
924        d->lastAssuanTransaction.get());
925
926     d->lasterr = err;
927
928     return Error(d->lasterr);
929 }
930
931 AssuanTransaction *Context::lastAssuanTransaction() const
932 {
933     return d->lastAssuanTransaction.get();
934 }
935
936 std::unique_ptr<AssuanTransaction> Context::takeLastAssuanTransaction()
937 {
938     return std::move(d->lastAssuanTransaction);
939 }
940
941 DecryptionResult Context::decrypt(const Data &cipherText, Data &plainText, const DecryptionFlags flags)
942 {
943     d->lastop = Private::Decrypt;
944     const Data::Private *const cdp = cipherText.impl();
945     Data::Private *const pdp = plainText.impl();
946     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);
947     return DecryptionResult(d->ctx, Error(d->lasterr));
948 }
949
950 DecryptionResult Context::decrypt(const Data &cipherText, Data &plainText)
951 {
952     return decrypt(cipherText, plainText, DecryptNone);
953 }
954
955 Error Context::startDecryption(const Data &cipherText, Data &plainText, const DecryptionFlags flags)
956 {
957     d->lastop = Private::Decrypt;
958     const Data::Private *const cdp = cipherText.impl();
959     Data::Private *const pdp = plainText.impl();
960     return Error(d->lasterr = gpgme_op_decrypt_ext_start(d->ctx, static_cast<gpgme_decrypt_flags_t> (d->decryptFlags | flags),
961                  cdp ? cdp->data : nullptr, pdp ? pdp->data : nullptr));
962 }
963
964 Error Context::startDecryption(const Data &cipherText, Data &plainText)
965 {
966     return startDecryption(cipherText, plainText, DecryptNone);
967 }
968
969 DecryptionResult Context::decryptionResult() const
970 {
971     if (d->lastop & Private::Decrypt) {
972         return DecryptionResult(d->ctx, Error(d->lasterr));
973     } else {
974         return DecryptionResult();
975     }
976 }
977
978 VerificationResult Context::verifyDetachedSignature(const Data &signature, const Data &signedText)
979 {
980     d->lastop = Private::Verify;
981     const Data::Private *const sdp = signature.impl();
982     const Data::Private *const tdp = signedText.impl();
983     d->lasterr = gpgme_op_verify(d->ctx, sdp ? sdp->data : nullptr, tdp ? tdp->data : nullptr, nullptr);
984     return VerificationResult(d->ctx, Error(d->lasterr));
985 }
986
987 VerificationResult Context::verifyOpaqueSignature(const Data &signedData, Data &plainText)
988 {
989     d->lastop = Private::Verify;
990     const Data::Private *const sdp = signedData.impl();
991     Data::Private *const pdp = plainText.impl();
992     d->lasterr = gpgme_op_verify(d->ctx, sdp ? sdp->data : nullptr, nullptr, pdp ? pdp->data : nullptr);
993     return VerificationResult(d->ctx, Error(d->lasterr));
994 }
995
996 Error Context::startDetachedSignatureVerification(const Data &signature, const Data &signedText)
997 {
998     d->lastop = Private::Verify;
999     const Data::Private *const sdp = signature.impl();
1000     const Data::Private *const tdp = signedText.impl();
1001     return Error(d->lasterr = gpgme_op_verify_start(d->ctx, sdp ? sdp->data : nullptr, tdp ? tdp->data : nullptr, nullptr));
1002 }
1003
1004 Error Context::startOpaqueSignatureVerification(const Data &signedData, Data &plainText)
1005 {
1006     d->lastop = Private::Verify;
1007     const Data::Private *const sdp = signedData.impl();
1008     Data::Private *const pdp = plainText.impl();
1009     return Error(d->lasterr = gpgme_op_verify_start(d->ctx, sdp ? sdp->data : nullptr, nullptr, pdp ? pdp->data : nullptr));
1010 }
1011
1012 VerificationResult Context::verificationResult() const
1013 {
1014     if (d->lastop & Private::Verify) {
1015         return VerificationResult(d->ctx, Error(d->lasterr));
1016     } else {
1017         return VerificationResult();
1018     }
1019 }
1020
1021 std::pair<DecryptionResult, VerificationResult> Context::decryptAndVerify(const Data &cipherText, Data &plainText, DecryptionFlags flags)
1022 {
1023     d->lastop = Private::DecryptAndVerify;
1024     const Data::Private *const cdp = cipherText.impl();
1025     Data::Private *const pdp = plainText.impl();
1026     d->lasterr = gpgme_op_decrypt_ext(d->ctx, static_cast<gpgme_decrypt_flags_t> (d->decryptFlags | flags | DecryptVerify),
1027                                       cdp ? cdp->data : nullptr, pdp ? pdp->data : nullptr);
1028     return std::make_pair(DecryptionResult(d->ctx, Error(d->lasterr)),
1029                           VerificationResult(d->ctx, Error(d->lasterr)));
1030 }
1031
1032 std::pair<DecryptionResult, VerificationResult> Context::decryptAndVerify(const Data &cipherText, Data &plainText)
1033 {
1034     return decryptAndVerify(cipherText, plainText, DecryptNone);
1035 }
1036
1037 Error Context::startCombinedDecryptionAndVerification(const Data &cipherText, Data &plainText, DecryptionFlags flags)
1038 {
1039     d->lastop = Private::DecryptAndVerify;
1040     const Data::Private *const cdp = cipherText.impl();
1041     Data::Private *const pdp = plainText.impl();
1042     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));
1043 }
1044
1045 Error Context::startCombinedDecryptionAndVerification(const Data &cipherText, Data &plainText)
1046 {
1047     return startCombinedDecryptionAndVerification(cipherText, plainText, DecryptNone);
1048 }
1049
1050 unsigned int to_auditlog_flags(unsigned int flags)
1051 {
1052     unsigned int result = 0;
1053     if (flags & Context::HtmlAuditLog) {
1054         result |= GPGME_AUDITLOG_HTML;
1055     }
1056     if (flags & Context::AuditLogWithHelp) {
1057         result |= GPGME_AUDITLOG_WITH_HELP;
1058     }
1059     if (flags & Context::DiagnosticAuditLog) {
1060         result |= GPGME_AUDITLOG_DIAG;
1061     }
1062     return result;
1063 }
1064
1065 Error Context::startGetAuditLog(Data &output, unsigned int flags)
1066 {
1067     d->lastop = Private::GetAuditLog;
1068     Data::Private *const odp = output.impl();
1069     return Error(d->lasterr = gpgme_op_getauditlog_start(d->ctx, odp ? odp->data : nullptr, to_auditlog_flags(flags)));
1070 }
1071
1072 Error Context::getAuditLog(Data &output, unsigned int flags)
1073 {
1074     d->lastop = Private::GetAuditLog;
1075     Data::Private *const odp = output.impl();
1076     return Error(d->lasterr = gpgme_op_getauditlog(d->ctx, odp ? odp->data : nullptr, to_auditlog_flags(flags)));
1077 }
1078
1079 void Context::clearSigningKeys()
1080 {
1081     gpgme_signers_clear(d->ctx);
1082 }
1083
1084 Error Context::addSigningKey(const Key &key)
1085 {
1086     return Error(d->lasterr = gpgme_signers_add(d->ctx, key.impl()));
1087 }
1088
1089 Key Context::signingKey(unsigned int idx) const
1090 {
1091     gpgme_key_t key = gpgme_signers_enum(d->ctx, idx);
1092     return Key(key, false);
1093 }
1094
1095 std::vector<Key> Context::signingKeys() const
1096 {
1097     std::vector<Key> result;
1098     gpgme_key_t key = nullptr;
1099     for (unsigned int i = 0 ; (key = gpgme_signers_enum(d->ctx, i)) ; ++i) {
1100         result.push_back(Key(key, false));
1101     }
1102     return result;
1103 }
1104
1105 void Context::clearSignatureNotations()
1106 {
1107     gpgme_sig_notation_clear(d->ctx);
1108 }
1109
1110 GpgME::Error Context::addSignatureNotation(const char *name, const char *value, unsigned int flags)
1111 {
1112     return Error(gpgme_sig_notation_add(d->ctx, name, value, add_to_gpgme_sig_notation_flags_t(0, flags)));
1113 }
1114
1115 GpgME::Error Context::addSignaturePolicyURL(const char *url, bool critical)
1116 {
1117     return Error(gpgme_sig_notation_add(d->ctx, nullptr, url, critical ? GPGME_SIG_NOTATION_CRITICAL : 0));
1118 }
1119
1120 const char *Context::signaturePolicyURL() const
1121 {
1122     for (gpgme_sig_notation_t n = gpgme_sig_notation_get(d->ctx) ; n ; n = n->next) {
1123         if (!n->name) {
1124             return n->value;
1125         }
1126     }
1127     return nullptr;
1128 }
1129
1130 Notation Context::signatureNotation(unsigned int idx) const
1131 {
1132     for (gpgme_sig_notation_t n = gpgme_sig_notation_get(d->ctx) ; n ; n = n->next) {
1133         if (n->name) {
1134             if (idx-- == 0) {
1135                 return Notation(n);
1136             }
1137         }
1138     }
1139     return Notation();
1140 }
1141
1142 std::vector<Notation> Context::signatureNotations() const
1143 {
1144     std::vector<Notation> result;
1145     for (gpgme_sig_notation_t n = gpgme_sig_notation_get(d->ctx) ; n ; n = n->next) {
1146         if (n->name) {
1147             result.push_back(Notation(n));
1148         }
1149     }
1150     return result;
1151 }
1152
1153 static gpgme_sig_mode_t sigmode2sigmode(SignatureMode mode)
1154 {
1155     switch (mode) {
1156     default:
1157     case NormalSignatureMode: return GPGME_SIG_MODE_NORMAL;
1158     case Detached:            return GPGME_SIG_MODE_DETACH;
1159     case Clearsigned:         return GPGME_SIG_MODE_CLEAR;
1160     }
1161 }
1162
1163 SigningResult Context::sign(const Data &plainText, Data &signature, SignatureMode mode)
1164 {
1165     d->lastop = Private::Sign;
1166     const Data::Private *const pdp = plainText.impl();
1167     Data::Private *const sdp = signature.impl();
1168     d->lasterr = gpgme_op_sign(d->ctx, pdp ? pdp->data : nullptr, sdp ? sdp->data : nullptr, sigmode2sigmode(mode));
1169     return SigningResult(d->ctx, Error(d->lasterr));
1170 }
1171
1172 Error Context::startSigning(const Data &plainText, Data &signature, SignatureMode mode)
1173 {
1174     d->lastop = Private::Sign;
1175     const Data::Private *const pdp = plainText.impl();
1176     Data::Private *const sdp = signature.impl();
1177     return Error(d->lasterr = gpgme_op_sign_start(d->ctx, pdp ? pdp->data : nullptr, sdp ? sdp->data : nullptr, sigmode2sigmode(mode)));
1178 }
1179
1180 SigningResult Context::signingResult() const
1181 {
1182     if (d->lastop & Private::Sign) {
1183         return SigningResult(d->ctx, Error(d->lasterr));
1184     } else {
1185         return SigningResult();
1186     }
1187 }
1188
1189 static gpgme_encrypt_flags_t encryptflags2encryptflags(Context::EncryptionFlags flags)
1190 {
1191     unsigned int result = 0;
1192     if (flags & Context::AlwaysTrust) {
1193         result |= GPGME_ENCRYPT_ALWAYS_TRUST;
1194     }
1195     if (flags & Context::NoEncryptTo) {
1196         result |= GPGME_ENCRYPT_NO_ENCRYPT_TO;
1197     }
1198     if (flags & Context::Prepare) {
1199         result |= GPGME_ENCRYPT_PREPARE;
1200     }
1201     if (flags & Context::ExpectSign) {
1202         result |= GPGME_ENCRYPT_EXPECT_SIGN;
1203     }
1204     if (flags & Context::NoCompress) {
1205         result |= GPGME_ENCRYPT_NO_COMPRESS;
1206     }
1207     if (flags & Context::Symmetric) {
1208         result |= GPGME_ENCRYPT_SYMMETRIC;
1209     }
1210     return static_cast<gpgme_encrypt_flags_t>(result);
1211 }
1212
1213 gpgme_key_t *Context::getKeysFromRecipients(const std::vector<Key> &recipients)
1214 {
1215     if (recipients.empty()) {
1216         return nullptr;
1217     }
1218     gpgme_key_t *ret = new gpgme_key_t[ recipients.size() + 1 ];
1219     gpgme_key_t *keys_it = ret;
1220     for (std::vector<Key>::const_iterator it = recipients.begin() ; it != recipients.end() ; ++it) {
1221         if (it->impl()) {
1222             *keys_it++ = it->impl();
1223         }
1224     }
1225     *keys_it++ = nullptr;
1226     return ret;
1227 }
1228
1229 EncryptionResult Context::encrypt(const std::vector<Key> &recipients, const Data &plainText, Data &cipherText, EncryptionFlags flags)
1230 {
1231     d->lastop = Private::Encrypt;
1232     if (flags & NoEncryptTo) {
1233         return EncryptionResult(Error(d->lasterr = make_error(GPG_ERR_NOT_IMPLEMENTED)));
1234     }
1235     const Data::Private *const pdp = plainText.impl();
1236     Data::Private *const cdp = cipherText.impl();
1237     gpgme_key_t *const keys = getKeysFromRecipients(recipients);
1238     d->lasterr = gpgme_op_encrypt(d->ctx, keys, encryptflags2encryptflags(flags),
1239                                   pdp ? pdp->data : nullptr, cdp ? cdp->data : nullptr);
1240     if (keys) {
1241         delete[] keys;
1242     }
1243     return EncryptionResult(d->ctx, Error(d->lasterr));
1244 }
1245
1246 Error Context::encryptSymmetrically(const Data &plainText, Data &cipherText)
1247 {
1248     d->lastop = Private::Encrypt;
1249     const Data::Private *const pdp = plainText.impl();
1250     Data::Private *const cdp = cipherText.impl();
1251     return Error(d->lasterr = gpgme_op_encrypt(d->ctx, nullptr, (gpgme_encrypt_flags_t)0,
1252                               pdp ? pdp->data : nullptr, cdp ? cdp->data : nullptr));
1253 }
1254
1255 Error Context::startEncryption(const std::vector<Key> &recipients, const Data &plainText, Data &cipherText, EncryptionFlags flags)
1256 {
1257     d->lastop = Private::Encrypt;
1258     if (flags & NoEncryptTo) {
1259         return Error(d->lasterr = make_error(GPG_ERR_NOT_IMPLEMENTED));
1260     }
1261     const Data::Private *const pdp = plainText.impl();
1262     Data::Private *const cdp = cipherText.impl();
1263     gpgme_key_t *const keys = getKeysFromRecipients(recipients);
1264     d->lasterr = gpgme_op_encrypt_start(d->ctx, keys, encryptflags2encryptflags(flags),
1265                                         pdp ? pdp->data : nullptr, cdp ? cdp->data : nullptr);
1266     if (keys) {
1267         delete[] keys;
1268     }
1269     return Error(d->lasterr);
1270 }
1271
1272 EncryptionResult Context::encryptionResult() const
1273 {
1274     if (d->lastop & Private::Encrypt) {
1275         return EncryptionResult(d->ctx, Error(d->lasterr));
1276     } else {
1277         return EncryptionResult();
1278     }
1279 }
1280
1281 std::pair<SigningResult, EncryptionResult> Context::signAndEncrypt(const std::vector<Key> &recipients, const Data &plainText, Data &cipherText, EncryptionFlags flags)
1282 {
1283     d->lastop = Private::SignAndEncrypt;
1284     const Data::Private *const pdp = plainText.impl();
1285     Data::Private *const cdp = cipherText.impl();
1286     gpgme_key_t *const keys = getKeysFromRecipients(recipients);
1287     d->lasterr = gpgme_op_encrypt_sign(d->ctx, keys, encryptflags2encryptflags(flags),
1288                                        pdp ? pdp->data : nullptr, cdp ? cdp->data : nullptr);
1289     if (keys) {
1290         delete[] keys;
1291     }
1292     return std::make_pair(SigningResult(d->ctx, Error(d->lasterr)),
1293                           EncryptionResult(d->ctx, Error(d->lasterr)));
1294 }
1295
1296 Error Context::startCombinedSigningAndEncryption(const std::vector<Key> &recipients, const Data &plainText, Data &cipherText, EncryptionFlags flags)
1297 {
1298     d->lastop = Private::SignAndEncrypt;
1299     const Data::Private *const pdp = plainText.impl();
1300     Data::Private *const cdp = cipherText.impl();
1301     gpgme_key_t *const keys = getKeysFromRecipients(recipients);
1302     d->lasterr = gpgme_op_encrypt_sign_start(d->ctx, keys, encryptflags2encryptflags(flags),
1303                  pdp ? pdp->data : nullptr, cdp ? cdp->data : nullptr);
1304     if (keys) {
1305         delete[] keys;
1306     }
1307     return Error(d->lasterr);
1308 }
1309
1310 Error Context::createVFS(const char *containerFile, const std::vector< Key > &recipients)
1311 {
1312     d->lastop = Private::CreateVFS;
1313     gpgme_key_t *const keys = new gpgme_key_t[ recipients.size() + 1 ];
1314     gpgme_key_t *keys_it = keys;
1315     for (std::vector<Key>::const_iterator it = recipients.begin() ; it != recipients.end() ; ++it) {
1316         if (it->impl()) {
1317             *keys_it++ = it->impl();
1318         }
1319     }
1320     *keys_it++ = nullptr;
1321
1322     gpgme_error_t op_err;
1323     d->lasterr = gpgme_op_vfs_create(d->ctx, keys, containerFile, 0, &op_err);
1324     delete[] keys;
1325     Error error(d->lasterr);
1326     if (error) {
1327         return error;
1328     }
1329     return Error(d->lasterr = op_err);
1330 }
1331
1332 VfsMountResult Context::mountVFS(const char *containerFile, const char *mountDir)
1333 {
1334     d->lastop = Private::MountVFS;
1335     gpgme_error_t op_err;
1336     d->lasterr = gpgme_op_vfs_mount(d->ctx, containerFile, mountDir, 0, &op_err);
1337     return VfsMountResult(d->ctx, Error(d->lasterr), Error(op_err));
1338 }
1339
1340 Error Context::cancelPendingOperation()
1341 {
1342     return Error(gpgme_cancel_async(d->ctx));
1343 }
1344
1345 bool Context::poll()
1346 {
1347     gpgme_error_t e = GPG_ERR_NO_ERROR;
1348     const bool finished = gpgme_wait(d->ctx, &e, 0);
1349     if (finished) {
1350         d->lasterr = e;
1351     }
1352     return finished;
1353 }
1354
1355 Error Context::wait()
1356 {
1357     gpgme_error_t e = GPG_ERR_NO_ERROR;
1358     gpgme_wait(d->ctx, &e, 1);
1359     return Error(d->lasterr = e);
1360 }
1361
1362 Error Context::lastError() const
1363 {
1364     return Error(d->lasterr);
1365 }
1366
1367 Context::PinentryMode Context::pinentryMode() const
1368 {
1369     switch (gpgme_get_pinentry_mode (d->ctx)) {
1370         case GPGME_PINENTRY_MODE_ASK:
1371             return PinentryAsk;
1372         case GPGME_PINENTRY_MODE_CANCEL:
1373             return PinentryCancel;
1374         case GPGME_PINENTRY_MODE_ERROR:
1375             return PinentryError;
1376         case GPGME_PINENTRY_MODE_LOOPBACK:
1377             return PinentryLoopback;
1378         case GPGME_PINENTRY_MODE_DEFAULT:
1379         default:
1380             return PinentryDefault;
1381     }
1382 }
1383
1384 Error Context::setPinentryMode(PinentryMode which)
1385 {
1386     gpgme_pinentry_mode_t mode;
1387     switch (which) {
1388         case PinentryAsk:
1389             mode = GPGME_PINENTRY_MODE_ASK;
1390             break;
1391         case PinentryCancel:
1392             mode = GPGME_PINENTRY_MODE_CANCEL;
1393             break;
1394         case PinentryError:
1395             mode = GPGME_PINENTRY_MODE_ERROR;
1396             break;
1397         case PinentryLoopback:
1398             mode = GPGME_PINENTRY_MODE_LOOPBACK;
1399             break;
1400         case PinentryDefault:
1401         default:
1402             mode = GPGME_PINENTRY_MODE_DEFAULT;
1403     }
1404     return Error(d->lasterr = gpgme_set_pinentry_mode(d->ctx, mode));
1405 }
1406
1407 static gpgme_tofu_policy_t to_tofu_policy_t(unsigned int policy)
1408 {
1409     switch (policy) {
1410         case TofuInfo::PolicyNone:
1411             return GPGME_TOFU_POLICY_NONE;
1412         case TofuInfo::PolicyAuto:
1413             return GPGME_TOFU_POLICY_AUTO;
1414         case TofuInfo::PolicyGood:
1415             return GPGME_TOFU_POLICY_GOOD;
1416         case TofuInfo::PolicyBad:
1417             return GPGME_TOFU_POLICY_BAD;
1418         case TofuInfo::PolicyAsk:
1419             return GPGME_TOFU_POLICY_ASK;
1420         case TofuInfo::PolicyUnknown:
1421         default:
1422             return GPGME_TOFU_POLICY_UNKNOWN;
1423     }
1424 }
1425
1426 Error Context::setTofuPolicy(const Key &k, unsigned int policy)
1427 {
1428     return Error(d->lasterr = gpgme_op_tofu_policy(d->ctx,
1429                  k.impl(), to_tofu_policy_t(policy)));
1430 }
1431
1432 Error Context::setTofuPolicyStart(const Key &k, unsigned int policy)
1433 {
1434     return Error(d->lasterr = gpgme_op_tofu_policy_start(d->ctx,
1435                  k.impl(), to_tofu_policy_t(policy)));
1436 }
1437
1438 Error Context::startCreateKey (const char *userid,
1439                                const char *algo,
1440                                unsigned long reserved,
1441                                unsigned long expires,
1442                                const Key &certkey,
1443                                unsigned int flags)
1444 {
1445     return Error(d->lasterr = gpgme_op_createkey_start(d->ctx,
1446                  userid,
1447                  algo,
1448                  reserved,
1449                  expires,
1450                  certkey.impl(),
1451                  flags));
1452 }
1453
1454 Error Context::createKey (const char *userid,
1455                           const char *algo,
1456                           unsigned long reserved,
1457                           unsigned long expires,
1458                           const Key &certkey,
1459                           unsigned int flags)
1460 {
1461     return Error(d->lasterr = gpgme_op_createkey(d->ctx,
1462                  userid,
1463                  algo,
1464                  reserved,
1465                  expires,
1466                  certkey.impl(),
1467                  flags));
1468 }
1469
1470 KeyGenerationResult Context::createKeyEx (const char *userid,
1471                                           const char *algo,
1472                                           unsigned long reserved,
1473                                           unsigned long expires,
1474                                           const Key &certkey,
1475                                           unsigned int flags)
1476 {
1477     d->lasterr = gpgme_op_createkey(d->ctx,
1478                  userid,
1479                  algo,
1480                  reserved,
1481                  expires,
1482                  certkey.impl(),
1483                  flags);
1484     return KeyGenerationResult(d->ctx, Error(d->lasterr));
1485 }
1486
1487 Error Context::addUid(const Key &k, const char *userid)
1488 {
1489     return Error(d->lasterr = gpgme_op_adduid(d->ctx,
1490                  k.impl(), userid, 0));
1491 }
1492
1493 Error Context::startAddUid(const Key &k, const char *userid)
1494 {
1495     return Error(d->lasterr = gpgme_op_adduid_start(d->ctx,
1496                  k.impl(), userid, 0));
1497 }
1498
1499 Error Context::revUid(const Key &k, const char *userid)
1500 {
1501     return Error(d->lasterr = gpgme_op_revuid(d->ctx,
1502                  k.impl(), userid, 0));
1503 }
1504
1505 Error Context::startRevUid(const Key &k, const char *userid)
1506 {
1507     return Error(d->lasterr = gpgme_op_revuid_start(d->ctx,
1508                  k.impl(), userid, 0));
1509 }
1510
1511 Error Context::createSubkey(const Key &k, const char *algo,
1512                             unsigned long reserved,
1513                             unsigned long expires,
1514                             unsigned int flags)
1515 {
1516     return Error(d->lasterr = gpgme_op_createsubkey(d->ctx,
1517                  k.impl(), algo, reserved, expires, flags));
1518 }
1519
1520 Error Context::startCreateSubkey(const Key &k, const char *algo,
1521                                  unsigned long reserved,
1522                                  unsigned long expires,
1523                                  unsigned int flags)
1524 {
1525     return Error(d->lasterr = gpgme_op_createsubkey_start(d->ctx,
1526                  k.impl(), algo, reserved, expires, flags));
1527 }
1528
1529 Error Context::setFlag(const char *name, const char *value)
1530 {
1531   return Error(d->lasterr = gpgme_set_ctx_flag(d->ctx, name, value));
1532 }
1533
1534 const char *Context::getFlag(const char *name) const
1535 {
1536   return gpgme_get_ctx_flag(d->ctx, name);
1537 }
1538
1539 // Engine Spawn stuff
1540 Error Context::spawn(const char *file, const char *argv[],
1541                      Data &input, Data &output, Data &err,
1542                      SpawnFlags flags)
1543 {
1544     return Error(d->lasterr = gpgme_op_spawn (d->ctx, file, argv,
1545         input.impl() ? input.impl()->data : nullptr,
1546         output.impl() ? output.impl()->data : nullptr,
1547         err.impl() ? err.impl()->data : nullptr,
1548         static_cast<int>(flags)));
1549 }
1550
1551 Error Context::spawnAsync(const char *file, const char *argv[],
1552                           Data &input, Data &output, Data &err,
1553                           SpawnFlags flags)
1554 {
1555     return Error(d->lasterr = gpgme_op_spawn_start (d->ctx, file, argv,
1556         input.impl() ? input.impl()->data : nullptr,
1557         output.impl() ? output.impl()->data : nullptr,
1558         err.impl() ? err.impl()->data : nullptr,
1559         static_cast<int>(flags)));
1560 }
1561
1562 std::ostream &operator<<(std::ostream &os, Protocol proto)
1563 {
1564     os << "GpgME::Protocol(";
1565     switch (proto) {
1566     case OpenPGP:
1567         os << "OpenPGP";
1568         break;
1569     case CMS:
1570         os << "CMS";
1571         break;
1572     default:
1573     case UnknownProtocol:
1574         os << "UnknownProtocol";
1575         break;
1576     }
1577     return os << ')';
1578 }
1579
1580 std::ostream &operator<<(std::ostream &os, Engine eng)
1581 {
1582     os << "GpgME::Engine(";
1583     switch (eng) {
1584     case GpgEngine:
1585         os << "GpgEngine";
1586         break;
1587     case GpgSMEngine:
1588         os << "GpgSMEngine";
1589         break;
1590     case GpgConfEngine:
1591         os << "GpgConfEngine";
1592         break;
1593     case AssuanEngine:
1594         os << "AssuanEngine";
1595         break;
1596     case SpawnEngine:
1597         os << "SpawnEngine";
1598         break;
1599     default:
1600     case UnknownEngine:
1601         os << "UnknownEngine";
1602         break;
1603     }
1604     return os << ')';
1605 }
1606
1607 std::ostream &operator<<(std::ostream &os, Context::CertificateInclusion incl)
1608 {
1609     os << "GpgME::Context::CertificateInclusion(" << static_cast<int>(incl);
1610     switch (incl) {
1611     case Context::DefaultCertificates:
1612         os << "(DefaultCertificates)";
1613         break;
1614     case Context::AllCertificatesExceptRoot:
1615         os << "(AllCertificatesExceptRoot)";
1616         break;
1617     case Context::AllCertificates:
1618         os << "(AllCertificates)";
1619         break;
1620     case Context::NoCertificates:
1621         os << "(NoCertificates)";
1622         break;
1623     case Context::OnlySenderCertificate:
1624         os << "(OnlySenderCertificate)";
1625         break;
1626     }
1627     return os << ')';
1628 }
1629
1630 std::ostream &operator<<(std::ostream &os, KeyListMode mode)
1631 {
1632     os << "GpgME::KeyListMode(";
1633 #define CHECK( x ) if ( !(mode & (x)) ) {} else do { os << #x " "; } while (0)
1634     CHECK(Local);
1635     CHECK(Extern);
1636     CHECK(Signatures);
1637     CHECK(Validate);
1638     CHECK(Ephemeral);
1639     CHECK(WithTofu);
1640     CHECK(WithKeygrip);
1641 #undef CHECK
1642     return os << ')';
1643 }
1644
1645 std::ostream &operator<<(std::ostream &os, SignatureMode mode)
1646 {
1647     os << "GpgME::SignatureMode(";
1648     switch (mode) {
1649 #define CHECK( x ) case x: os << #x; break
1650         CHECK(NormalSignatureMode);
1651         CHECK(Detached);
1652         CHECK(Clearsigned);
1653 #undef CHECK
1654     default:
1655         os << "???" "(" << static_cast<int>(mode) << ')';
1656         break;
1657     }
1658     return os << ')';
1659 }
1660
1661 std::ostream &operator<<(std::ostream &os, Context::EncryptionFlags flags)
1662 {
1663     os << "GpgME::Context::EncryptionFlags(";
1664 #define CHECK( x ) if ( !(flags & (Context::x)) ) {} else do { os << #x " "; } while (0)
1665     CHECK(AlwaysTrust);
1666     CHECK(NoEncryptTo);
1667     CHECK(Prepare);
1668     CHECK(ExpectSign);
1669     CHECK(NoCompress);
1670     CHECK(Symmetric);
1671 #undef CHECK
1672     return os << ')';
1673 }
1674
1675 std::ostream &operator<<(std::ostream &os, Context::AuditLogFlags flags)
1676 {
1677     os << "GpgME::Context::AuditLogFlags(";
1678 #define CHECK( x ) if ( !(flags & (Context::x)) ) {} else do { os << #x " "; } while (0)
1679     CHECK(HtmlAuditLog);
1680     CHECK(AuditLogWithHelp);
1681 #undef CHECK
1682     return os << ')';
1683 }
1684
1685 } // namespace GpgME
1686
1687 GpgME::Error GpgME::setDefaultLocale(int cat, const char *val)
1688 {
1689     return Error(gpgme_set_locale(nullptr, cat, val));
1690 }
1691
1692 GpgME::EngineInfo GpgME::engineInfo(GpgME::Protocol proto)
1693 {
1694     gpgme_engine_info_t ei = nullptr;
1695     if (gpgme_get_engine_info(&ei)) {
1696         return EngineInfo();
1697     }
1698
1699     const gpgme_protocol_t p = proto == CMS ? GPGME_PROTOCOL_CMS : GPGME_PROTOCOL_OpenPGP ;
1700
1701     for (gpgme_engine_info_t i = ei ; i ; i = i->next) {
1702         if (i->protocol == p) {
1703             return EngineInfo(i);
1704         }
1705     }
1706
1707     return EngineInfo();
1708 }
1709
1710 const char *GpgME::dirInfo(const char *what)
1711 {
1712     return gpgme_get_dirinfo(what);
1713 }
1714
1715 GpgME::Error GpgME::checkEngine(GpgME::Protocol proto)
1716 {
1717     const gpgme_protocol_t p = proto == CMS ? GPGME_PROTOCOL_CMS : GPGME_PROTOCOL_OpenPGP ;
1718
1719     return Error(gpgme_engine_check_version(p));
1720 }
1721
1722 static const gpgme_protocol_t UNKNOWN_PROTOCOL = static_cast<gpgme_protocol_t>(255);
1723
1724 static gpgme_protocol_t engine2protocol(const GpgME::Engine engine)
1725 {
1726     switch (engine) {
1727     case GpgME::GpgEngine:   return GPGME_PROTOCOL_OpenPGP;
1728     case GpgME::GpgSMEngine: return GPGME_PROTOCOL_CMS;
1729     case GpgME::GpgConfEngine:
1730         return GPGME_PROTOCOL_GPGCONF;
1731     case GpgME::AssuanEngine:
1732         return GPGME_PROTOCOL_ASSUAN;
1733     case GpgME::G13Engine:
1734         return GPGME_PROTOCOL_G13;
1735     case GpgME::SpawnEngine:
1736         return GPGME_PROTOCOL_SPAWN;
1737     case GpgME::UnknownEngine:
1738         ;
1739     }
1740     return UNKNOWN_PROTOCOL;
1741 }
1742
1743 GpgME::EngineInfo GpgME::engineInfo(GpgME::Engine engine)
1744 {
1745     gpgme_engine_info_t ei = nullptr;
1746     if (gpgme_get_engine_info(&ei)) {
1747         return EngineInfo();
1748     }
1749
1750     const gpgme_protocol_t p = engine2protocol(engine);
1751
1752     for (gpgme_engine_info_t i = ei ; i ; i = i->next) {
1753         if (i->protocol == p) {
1754             return EngineInfo(i);
1755         }
1756     }
1757
1758     return EngineInfo();
1759 }
1760
1761 GpgME::Error GpgME::checkEngine(GpgME::Engine engine)
1762 {
1763     const gpgme_protocol_t p = engine2protocol(engine);
1764
1765     return Error(gpgme_engine_check_version(p));
1766 }
1767
1768 static const unsigned long supported_features = 0
1769         | GpgME::ValidatingKeylistModeFeature
1770         | GpgME::CancelOperationFeature
1771         | GpgME::WrongKeyUsageFeature
1772         | GpgME::DefaultCertificateInclusionFeature
1773         | GpgME::GetSetEngineInfoFeature
1774         | GpgME::ClearAddGetSignatureNotationsFeature
1775         | GpgME::SetDataFileNameFeeature
1776         | GpgME::SignatureNotationsKeylistModeFeature
1777         | GpgME::KeySignatureNotationsFeature
1778         | GpgME::KeyIsQualifiedFeature
1779         | GpgME::SignatureNotationsCriticalFlagFeature
1780         | GpgME::SignatureNotationsFlagsFeature
1781         | GpgME::SignatureNotationsHumanReadableFlagFeature
1782         | GpgME::SubkeyIsQualifiedFeature
1783         | GpgME::EngineInfoHomeDirFeature
1784         | GpgME::DecryptionResultFileNameFeature
1785         | GpgME::DecryptionResultRecipientsFeature
1786         | GpgME::VerificationResultFileNameFeature
1787         | GpgME::SignaturePkaFieldsFeature
1788         | GpgME::SignatureAlgorithmFieldsFeature
1789         | GpgME::FdPointerFeature
1790         | GpgME::AuditLogFeature
1791         | GpgME::GpgConfEngineFeature
1792         | GpgME::CancelOperationAsyncFeature
1793         | GpgME::NoEncryptToEncryptionFlagFeature
1794         | GpgME::CardKeyFeature
1795         | GpgME::AssuanEngineFeature
1796         | GpgME::EphemeralKeylistModeFeature
1797         | GpgME::ImportFromKeyserverFeature
1798         | GpgME::G13VFSFeature
1799         | GpgME::PasswdFeature
1800         ;
1801
1802 static const unsigned long supported_features2 = 0
1803         | GpgME::BinaryAndFineGrainedIdentify
1804         ;
1805
1806 bool GpgME::hasFeature(unsigned long features)
1807 {
1808     return features == (features & supported_features);
1809 }
1810
1811 bool GpgME::hasFeature(unsigned long features, unsigned long features2)
1812 {
1813     return features  == (features  & supported_features)
1814            && features2 == (features2 & supported_features2)
1815            ;
1816 }
1817
1818 int GpgME::setGlobalFlag(const char *name, const char *value)
1819 {
1820     return gpgme_set_global_flag(name, value);
1821 }