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