cpp: Add get / set Sender API
[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 //
284 //
285 // Context::Private
286 //
287 //
288
289 Context::Private::Private(gpgme_ctx_t c)
290     : ctx(c),
291       iocbs(0),
292       lastop(None),
293       lasterr(GPG_ERR_NO_ERROR),
294       lastAssuanInquireData(Data::null),
295       lastAssuanTransaction(),
296       lastEditInteractor(),
297       lastCardEditInteractor()
298 {
299
300 }
301
302 Context::Private::~Private()
303 {
304     if (ctx) {
305         gpgme_release(ctx);
306     }
307     ctx = 0;
308     delete iocbs;
309 }
310
311 //
312 //
313 // Context attributes:
314 //
315 //
316
317 Protocol Context::protocol() const
318 {
319     gpgme_protocol_t p = gpgme_get_protocol(d->ctx);
320     switch (p) {
321     case GPGME_PROTOCOL_OpenPGP: return OpenPGP;
322     case GPGME_PROTOCOL_CMS:     return CMS;
323     default:                     return UnknownProtocol;
324     }
325 }
326
327 void Context::setArmor(bool useArmor)
328 {
329     gpgme_set_armor(d->ctx, int(useArmor));
330 }
331 bool Context::armor() const
332 {
333     return gpgme_get_armor(d->ctx);
334 }
335
336 void Context::setTextMode(bool useTextMode)
337 {
338     gpgme_set_textmode(d->ctx, int(useTextMode));
339 }
340 bool Context::textMode() const
341 {
342     return gpgme_get_textmode(d->ctx);
343 }
344
345 void Context::setOffline(bool useOfflineMode)
346 {
347     gpgme_set_offline(d->ctx, int(useOfflineMode));
348 }
349 bool Context::offline() const
350 {
351     return gpgme_get_offline(d->ctx);
352 }
353
354 void Context::setIncludeCertificates(int which)
355 {
356     if (which == DefaultCertificates) {
357         which = GPGME_INCLUDE_CERTS_DEFAULT;
358     }
359     gpgme_set_include_certs(d->ctx, which);
360 }
361
362 int Context::includeCertificates() const
363 {
364     return gpgme_get_include_certs(d->ctx);
365 }
366
367 void Context::setKeyListMode(unsigned int mode)
368 {
369     gpgme_set_keylist_mode(d->ctx, add_to_gpgme_keylist_mode_t(0, mode));
370 }
371
372 void Context::addKeyListMode(unsigned int mode)
373 {
374     const unsigned int cur = gpgme_get_keylist_mode(d->ctx);
375     gpgme_set_keylist_mode(d->ctx, add_to_gpgme_keylist_mode_t(cur, mode));
376 }
377
378 unsigned int Context::keyListMode() const
379 {
380     return convert_from_gpgme_keylist_mode_t(gpgme_get_keylist_mode(d->ctx));
381 }
382
383 void Context::setProgressProvider(ProgressProvider *provider)
384 {
385     gpgme_set_progress_cb(d->ctx, provider ? &progress_callback : 0, provider);
386 }
387 ProgressProvider *Context::progressProvider() const
388 {
389     void *pp = 0;
390     gpgme_progress_cb_t pcb = &progress_callback;
391     gpgme_get_progress_cb(d->ctx, &pcb, &pp);
392     return static_cast<ProgressProvider *>(pp);
393 }
394
395 void Context::setPassphraseProvider(PassphraseProvider *provider)
396 {
397     gpgme_set_passphrase_cb(d->ctx, provider ? &passphrase_callback : 0, provider);
398 }
399
400 PassphraseProvider *Context::passphraseProvider() const
401 {
402     void *pp = 0;
403     gpgme_passphrase_cb_t pcb = &passphrase_callback;
404     gpgme_get_passphrase_cb(d->ctx, &pcb, &pp);
405     return static_cast<PassphraseProvider *>(pp);
406 }
407
408 void Context::setManagedByEventLoopInteractor(bool manage)
409 {
410     if (!EventLoopInteractor::instance()) {
411 #ifndef NDEBUG
412         cerr << "Context::setManagedByEventLoopInteractor(): "
413              "You must create an instance of EventLoopInteractor "
414              "before using anything that needs one." << endl;
415 #endif
416         return;
417     }
418     if (manage) {
419         EventLoopInteractor::instance()->manage(this);
420     } else {
421         EventLoopInteractor::instance()->unmanage(this);
422     }
423 }
424 bool Context::managedByEventLoopInteractor() const
425 {
426     return d->iocbs != 0;
427 }
428
429 void Context::installIOCallbacks(gpgme_io_cbs *iocbs)
430 {
431     if (!iocbs) {
432         uninstallIOCallbacks();
433         return;
434     }
435     gpgme_set_io_cbs(d->ctx, iocbs);
436     delete d->iocbs; d->iocbs = iocbs;
437 }
438
439 void Context::uninstallIOCallbacks()
440 {
441     static gpgme_io_cbs noiocbs = { 0, 0, 0, 0, 0 };
442     // io.add == 0 means disable io callbacks:
443     gpgme_set_io_cbs(d->ctx, &noiocbs);
444     delete d->iocbs; d->iocbs = 0;
445 }
446
447 Error Context::setLocale(int cat, const char *val)
448 {
449     return Error(d->lasterr = gpgme_set_locale(d->ctx, cat, val));
450 }
451
452 EngineInfo Context::engineInfo() const
453 {
454     return EngineInfo(gpgme_ctx_get_engine_info(d->ctx));
455 }
456
457 Error Context::setEngineFileName(const char *filename)
458 {
459     const char *const home_dir = engineInfo().homeDirectory();
460     return Error(gpgme_ctx_set_engine_info(d->ctx, gpgme_get_protocol(d->ctx), filename, home_dir));
461 }
462
463 Error Context::setEngineHomeDirectory(const char *home_dir)
464 {
465     const char *const filename = engineInfo().fileName();
466     return Error(gpgme_ctx_set_engine_info(d->ctx, gpgme_get_protocol(d->ctx), filename, home_dir));
467 }
468
469 Error Context::setSender (const char *sender)
470 {
471     return Error(gpgme_set_sender(d->ctx, sender));
472 }
473
474 const char *Context::getSender ()
475 {
476     return gpgme_get_sender(d->ctx);
477 }
478
479 //
480 //
481 // Key Management
482 //
483 //
484
485 Error Context::startKeyListing(const char *pattern, bool secretOnly)
486 {
487     d->lastop = Private::KeyList;
488     return Error(d->lasterr = gpgme_op_keylist_start(d->ctx, pattern, int(secretOnly)));
489 }
490
491 Error Context::startKeyListing(const char *patterns[], bool secretOnly)
492 {
493     d->lastop = Private::KeyList;
494 #ifndef HAVE_GPGME_EXT_KEYLIST_MODE_EXTERNAL_NONBROKEN
495     if (!patterns || !patterns[0] || !patterns[1]) {
496         // max. one pattern -> use the non-ext version
497         return startKeyListing(patterns ? patterns[0] : 0, secretOnly);
498     }
499 #endif
500     return Error(d->lasterr = gpgme_op_keylist_ext_start(d->ctx, patterns, int(secretOnly), 0));
501 }
502
503 Key Context::nextKey(GpgME::Error &e)
504 {
505     d->lastop = Private::KeyList;
506     gpgme_key_t key;
507     e = Error(d->lasterr = gpgme_op_keylist_next(d->ctx, &key));
508     return Key(key, false);
509 }
510
511 KeyListResult Context::endKeyListing()
512 {
513     d->lasterr = gpgme_op_keylist_end(d->ctx);
514     return keyListResult();
515 }
516
517 KeyListResult Context::keyListResult() const
518 {
519     return KeyListResult(d->ctx, Error(d->lasterr));
520 }
521
522 Key Context::key(const char *fingerprint, GpgME::Error &e , bool secret /*, bool forceUpdate*/)
523 {
524     d->lastop = Private::KeyList;
525     gpgme_key_t key;
526     e = Error(d->lasterr = gpgme_get_key(d->ctx, fingerprint, &key, int(secret)/*, int( forceUpdate )*/));
527     return Key(key, false);
528 }
529
530 KeyGenerationResult Context::generateKey(const char *parameters, Data &pubKey)
531 {
532     d->lastop = Private::KeyGen;
533     Data::Private *const dp = pubKey.impl();
534     d->lasterr = gpgme_op_genkey(d->ctx, parameters, dp ? dp->data : 0, 0);
535     return KeyGenerationResult(d->ctx, Error(d->lasterr));
536 }
537
538 Error Context::startKeyGeneration(const char *parameters, Data &pubKey)
539 {
540     d->lastop = Private::KeyGen;
541     Data::Private *const dp = pubKey.impl();
542     return Error(d->lasterr = gpgme_op_genkey_start(d->ctx, parameters, dp ? dp->data : 0, 0));
543 }
544
545 KeyGenerationResult Context::keyGenerationResult() const
546 {
547     if (d->lastop & Private::KeyGen) {
548         return KeyGenerationResult(d->ctx, Error(d->lasterr));
549     } else {
550         return KeyGenerationResult();
551     }
552 }
553
554 Error Context::exportPublicKeys(const char *pattern, Data &keyData)
555 {
556     d->lastop = Private::Export;
557     Data::Private *const dp = keyData.impl();
558     return Error(d->lasterr = gpgme_op_export(d->ctx, pattern, 0, dp ? dp->data : 0));
559 }
560
561 Error Context::exportPublicKeys(const char *patterns[], Data &keyData)
562 {
563     d->lastop = Private::Export;
564 #ifndef HAVE_GPGME_EXT_KEYLIST_MODE_EXTERNAL_NONBROKEN
565     if (!patterns || !patterns[0] || !patterns[1]) {
566         // max. one pattern -> use the non-ext version
567         return exportPublicKeys(patterns ? patterns[0] : 0, keyData);
568     }
569 #endif
570     Data::Private *const dp = keyData.impl();
571     return Error(d->lasterr = gpgme_op_export_ext(d->ctx, patterns, 0, dp ? dp->data : 0));
572 }
573
574 Error Context::startPublicKeyExport(const char *pattern, Data &keyData)
575 {
576     d->lastop = Private::Export;
577     Data::Private *const dp = keyData.impl();
578     return Error(d->lasterr = gpgme_op_export_start(d->ctx, pattern, 0, dp ? dp->data : 0));
579 }
580
581 Error Context::startPublicKeyExport(const char *patterns[], Data &keyData)
582 {
583     d->lastop = Private::Export;
584 #ifndef HAVE_GPGME_EXT_KEYLIST_MODE_EXTERNAL_NONBROKEN
585     if (!patterns || !patterns[0] || !patterns[1]) {
586         // max. one pattern -> use the non-ext version
587         return startPublicKeyExport(patterns ? patterns[0] : 0, keyData);
588     }
589 #endif
590     Data::Private *const dp = keyData.impl();
591     return Error(d->lasterr = gpgme_op_export_ext_start(d->ctx, patterns, 0, dp ? dp->data : 0));
592 }
593
594 ImportResult Context::importKeys(const Data &data)
595 {
596     d->lastop = Private::Import;
597     const Data::Private *const dp = data.impl();
598     d->lasterr = gpgme_op_import(d->ctx, dp ? dp->data : 0);
599     return ImportResult(d->ctx, Error(d->lasterr));
600 }
601
602 ImportResult Context::importKeys(const std::vector<Key> &kk)
603 {
604     d->lastop = Private::Import;
605     d->lasterr = make_error(GPG_ERR_NOT_IMPLEMENTED);
606
607     bool shouldHaveResult = false;
608     gpgme_key_t * const keys = new gpgme_key_t[ kk.size() + 1 ];
609     gpgme_key_t *keys_it = &keys[0];
610     for (std::vector<Key>::const_iterator it = kk.begin(), end = kk.end() ; it != end ; ++it) {
611         if (it->impl()) {
612             *keys_it++ = it->impl();
613         }
614     }
615     *keys_it++ = 0;
616     d->lasterr = gpgme_op_import_keys(d->ctx, keys);
617     shouldHaveResult = true;
618     if ((gpgme_err_code(d->lasterr) == GPG_ERR_NOT_IMPLEMENTED ||
619             gpgme_err_code(d->lasterr) == GPG_ERR_NOT_SUPPORTED) &&
620             protocol() == CMS) {
621         // ok, try the workaround (export+import):
622         std::vector<const char *> fprs;
623         for (std::vector<Key>::const_iterator it = kk.begin(), end = kk.end() ; it != end ; ++it) {
624             if (const char *fpr = it->primaryFingerprint()) {
625                 if (*fpr) {
626                     fprs.push_back(fpr);
627                 }
628             } else if (const char *keyid = it->keyID()) {
629                 if (*keyid) {
630                     fprs.push_back(keyid);
631                 }
632             }
633         }
634         fprs.push_back(0);
635         Data data;
636         Data::Private *const dp = data.impl();
637         const gpgme_keylist_mode_t oldMode = gpgme_get_keylist_mode(d->ctx);
638         gpgme_set_keylist_mode(d->ctx, GPGME_KEYLIST_MODE_EXTERN);
639         d->lasterr = gpgme_op_export_ext(d->ctx, &fprs[0], 0, dp ? dp->data : 0);
640         gpgme_set_keylist_mode(d->ctx, oldMode);
641         if (!d->lasterr) {
642             data.seek(0, SEEK_SET);
643             d->lasterr = gpgme_op_import(d->ctx, dp ? dp->data : 0);
644             shouldHaveResult = true;
645         }
646     }
647     delete[] keys;
648     if (shouldHaveResult) {
649         return ImportResult(d->ctx, Error(d->lasterr));
650     } else {
651         return ImportResult(Error(d->lasterr));
652     }
653 }
654
655 Error Context::startKeyImport(const Data &data)
656 {
657     d->lastop = Private::Import;
658     const Data::Private *const dp = data.impl();
659     return Error(d->lasterr = gpgme_op_import_start(d->ctx, dp ? dp->data : 0));
660 }
661
662 Error Context::startKeyImport(const std::vector<Key> &kk)
663 {
664     d->lastop = Private::Import;
665     gpgme_key_t * const keys = new gpgme_key_t[ kk.size() + 1 ];
666     gpgme_key_t *keys_it = &keys[0];
667     for (std::vector<Key>::const_iterator it = kk.begin(), end = kk.end() ; it != end ; ++it) {
668         if (it->impl()) {
669             *keys_it++ = it->impl();
670         }
671     }
672     *keys_it++ = 0;
673     Error err = Error(d->lasterr = gpgme_op_import_keys_start(d->ctx, keys));
674     delete[] keys;
675     return err;
676 }
677
678 ImportResult Context::importResult() const
679 {
680     if (d->lastop & Private::Import) {
681         return ImportResult(d->ctx, Error(d->lasterr));
682     } else {
683         return ImportResult();
684     }
685 }
686
687 Error Context::deleteKey(const Key &key, bool allowSecretKeyDeletion)
688 {
689     d->lastop = Private::Delete;
690     return Error(d->lasterr = gpgme_op_delete(d->ctx, key.impl(), int(allowSecretKeyDeletion)));
691 }
692
693 Error Context::startKeyDeletion(const Key &key, bool allowSecretKeyDeletion)
694 {
695     d->lastop = Private::Delete;
696     return Error(d->lasterr = gpgme_op_delete_start(d->ctx, key.impl(), int(allowSecretKeyDeletion)));
697 }
698
699 Error Context::passwd(const Key &key)
700 {
701     d->lastop = Private::Passwd;
702     return Error(d->lasterr = gpgme_op_passwd(d->ctx, key.impl(), 0U));
703 }
704
705 Error Context::startPasswd(const Key &key)
706 {
707     d->lastop = Private::Passwd;
708     return Error(d->lasterr = gpgme_op_passwd_start(d->ctx, key.impl(), 0U));
709 }
710
711
712 #pragma GCC diagnostic push
713 #pragma GCC diagnostic ignored "-Wdeprecated-declarations"
714
715 Error Context::edit(const Key &key, std::unique_ptr<EditInteractor> func, Data &data)
716 {
717     d->lastop = Private::Edit;
718     d->lastEditInteractor = std::move(func);
719     Data::Private *const dp = data.impl();
720     return Error(d->lasterr = gpgme_op_edit(d->ctx, key.impl(),
721                                             d->lastEditInteractor.get() ? edit_interactor_callback : 0,
722                                             d->lastEditInteractor.get() ? d->lastEditInteractor->d : 0,
723                                             dp ? dp->data : 0));
724 }
725
726
727 Error Context::startEditing(const Key &key, std::unique_ptr<EditInteractor> func, Data &data)
728 {
729     d->lastop = Private::Edit;
730     d->lastEditInteractor = std::move(func);
731     Data::Private *const dp = data.impl();
732     return Error(d->lasterr = gpgme_op_edit_start(d->ctx, key.impl(),
733                               d->lastEditInteractor.get() ? edit_interactor_callback : 0,
734                               d->lastEditInteractor.get() ? d->lastEditInteractor->d : 0,
735                               dp ? dp->data : 0));
736 }
737
738
739 EditInteractor *Context::lastEditInteractor() const
740 {
741     return d->lastEditInteractor.get();
742 }
743
744 std::unique_ptr<EditInteractor> Context::takeLastEditInteractor()
745 {
746     return std::move(d->lastEditInteractor);
747 }
748
749
750 Error Context::cardEdit(const Key &key, std::unique_ptr<EditInteractor> func, Data &data)
751 {
752     d->lastop = Private::CardEdit;
753     d->lastCardEditInteractor = std::move(func);
754     Data::Private *const dp = data.impl();
755     return Error(d->lasterr = gpgme_op_card_edit(d->ctx, key.impl(),
756                               d->lastCardEditInteractor.get() ? edit_interactor_callback : 0,
757                               d->lastCardEditInteractor.get() ? d->lastCardEditInteractor->d : 0,
758                               dp ? dp->data : 0));
759 }
760
761 Error Context::startCardEditing(const Key &key, std::unique_ptr<EditInteractor> func, Data &data)
762 {
763     d->lastop = Private::CardEdit;
764     d->lastCardEditInteractor = std::move(func);
765     Data::Private *const dp = data.impl();
766     return Error(d->lasterr = gpgme_op_card_edit_start(d->ctx, key.impl(),
767                               d->lastCardEditInteractor.get() ? edit_interactor_callback : 0,
768                               d->lastCardEditInteractor.get() ? d->lastCardEditInteractor->d : 0,
769                               dp ? dp->data : 0));
770 }
771
772 #pragma GCC diagnostic pop
773
774 EditInteractor *Context::lastCardEditInteractor() const
775 {
776     return d->lastCardEditInteractor.get();
777 }
778
779 std::unique_ptr<EditInteractor> Context::takeLastCardEditInteractor()
780 {
781     return std::move(d->lastCardEditInteractor);
782 }
783
784 Error Context::startTrustItemListing(const char *pattern, int maxLevel)
785 {
786     d->lastop = Private::TrustList;
787     return Error(d->lasterr = gpgme_op_trustlist_start(d->ctx, pattern, maxLevel));
788 }
789
790 TrustItem Context::nextTrustItem(Error &e)
791 {
792     gpgme_trust_item_t ti = 0;
793     e = Error(d->lasterr = gpgme_op_trustlist_next(d->ctx, &ti));
794     return TrustItem(ti);
795 }
796
797 Error Context::endTrustItemListing()
798 {
799     return Error(d->lasterr = gpgme_op_trustlist_end(d->ctx));
800 }
801
802 static gpgme_error_t assuan_transaction_data_callback(void *opaque, const void *data, size_t datalen)
803 {
804     assert(opaque);
805     AssuanTransaction *t = static_cast<AssuanTransaction *>(opaque);
806     return t->data(static_cast<const char *>(data), datalen).encodedError();
807 }
808
809 static gpgme_error_t assuan_transaction_inquire_callback(void *opaque, const char *name, const char *args, gpgme_data_t *r_data)
810 {
811     assert(opaque);
812     Context::Private *p = static_cast<Context::Private *>(opaque);
813     AssuanTransaction *t = p->lastAssuanTransaction.get();
814     assert(t);
815     Error err;
816     if (name) {
817         p->lastAssuanInquireData = t->inquire(name, args, err);
818     } else {
819         p->lastAssuanInquireData = Data::null;
820     }
821     if (!p->lastAssuanInquireData.isNull()) {
822         *r_data = p->lastAssuanInquireData.impl()->data;
823     }
824     return err.encodedError();
825 }
826
827 static gpgme_error_t assuan_transaction_status_callback(void *opaque, const char *status, const char *args)
828 {
829     assert(opaque);
830     AssuanTransaction *t = static_cast<AssuanTransaction *>(opaque);
831     std::string a = args;
832     percent_unescape(a, true);   // ### why doesn't gpgme do this??
833     return t->status(status, a.c_str()).encodedError();
834 }
835
836 Error Context::assuanTransact(const char *command)
837 {
838     return assuanTransact(command, std::unique_ptr<AssuanTransaction>(new DefaultAssuanTransaction));
839 }
840
841 Error Context::assuanTransact(const char *command, std::unique_ptr<AssuanTransaction> transaction)
842 {
843     gpgme_error_t err, operr;
844
845     d->lastop = Private::AssuanTransact;
846     d->lastAssuanTransaction = std::move(transaction);
847     if (!d->lastAssuanTransaction.get()) {
848         return Error(d->lasterr = make_error(GPG_ERR_INV_ARG));
849     }
850     err = gpgme_op_assuan_transact_ext
851       (d->ctx,
852        command,
853        assuan_transaction_data_callback,
854        d->lastAssuanTransaction.get(),
855        assuan_transaction_inquire_callback,
856        d,
857        assuan_transaction_status_callback,
858        d->lastAssuanTransaction.get(),
859        &operr);
860
861     if (!err)
862       err = operr;
863     d->lasterr = err;
864
865     return Error(d->lasterr);
866 }
867
868 Error Context::startAssuanTransaction(const char *command)
869 {
870     return startAssuanTransaction(command, std::unique_ptr<AssuanTransaction>(new DefaultAssuanTransaction));
871 }
872
873 Error Context::startAssuanTransaction(const char *command, std::unique_ptr<AssuanTransaction> transaction)
874 {
875     gpgme_error_t err;
876
877     d->lastop = Private::AssuanTransact;
878     d->lastAssuanTransaction = std::move(transaction);
879     if (!d->lastAssuanTransaction.get()) {
880         return Error(d->lasterr = make_error(GPG_ERR_INV_ARG));
881     }
882     err = gpgme_op_assuan_transact_start
883       (d->ctx,
884        command,
885        assuan_transaction_data_callback,
886        d->lastAssuanTransaction.get(),
887        assuan_transaction_inquire_callback,
888        d,
889        assuan_transaction_status_callback,
890        d->lastAssuanTransaction.get());
891
892     d->lasterr = err;
893
894     return Error(d->lasterr);
895 }
896
897 AssuanTransaction *Context::lastAssuanTransaction() const
898 {
899     return d->lastAssuanTransaction.get();
900 }
901
902 std::unique_ptr<AssuanTransaction> Context::takeLastAssuanTransaction()
903 {
904     return std::move(d->lastAssuanTransaction);
905 }
906
907 DecryptionResult Context::decrypt(const Data &cipherText, Data &plainText)
908 {
909     d->lastop = Private::Decrypt;
910     const Data::Private *const cdp = cipherText.impl();
911     Data::Private *const pdp = plainText.impl();
912     d->lasterr = gpgme_op_decrypt(d->ctx, cdp ? cdp->data : 0, pdp ? pdp->data : 0);
913     return DecryptionResult(d->ctx, Error(d->lasterr));
914 }
915
916 Error Context::startDecryption(const Data &cipherText, Data &plainText)
917 {
918     d->lastop = Private::Decrypt;
919     const Data::Private *const cdp = cipherText.impl();
920     Data::Private *const pdp = plainText.impl();
921     return Error(d->lasterr = gpgme_op_decrypt_start(d->ctx, cdp ? cdp->data : 0, pdp ? pdp->data : 0));
922 }
923
924 DecryptionResult Context::decryptionResult() const
925 {
926     if (d->lastop & Private::Decrypt) {
927         return DecryptionResult(d->ctx, Error(d->lasterr));
928     } else {
929         return DecryptionResult();
930     }
931 }
932
933 VerificationResult Context::verifyDetachedSignature(const Data &signature, const Data &signedText)
934 {
935     d->lastop = Private::Verify;
936     const Data::Private *const sdp = signature.impl();
937     const Data::Private *const tdp = signedText.impl();
938     d->lasterr = gpgme_op_verify(d->ctx, sdp ? sdp->data : 0, tdp ? tdp->data : 0, 0);
939     return VerificationResult(d->ctx, Error(d->lasterr));
940 }
941
942 VerificationResult Context::verifyOpaqueSignature(const Data &signedData, Data &plainText)
943 {
944     d->lastop = Private::Verify;
945     const Data::Private *const sdp = signedData.impl();
946     Data::Private *const pdp = plainText.impl();
947     d->lasterr = gpgme_op_verify(d->ctx, sdp ? sdp->data : 0, 0, pdp ? pdp->data : 0);
948     return VerificationResult(d->ctx, Error(d->lasterr));
949 }
950
951 Error Context::startDetachedSignatureVerification(const Data &signature, const Data &signedText)
952 {
953     d->lastop = Private::Verify;
954     const Data::Private *const sdp = signature.impl();
955     const Data::Private *const tdp = signedText.impl();
956     return Error(d->lasterr = gpgme_op_verify_start(d->ctx, sdp ? sdp->data : 0, tdp ? tdp->data : 0, 0));
957 }
958
959 Error Context::startOpaqueSignatureVerification(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     return Error(d->lasterr = gpgme_op_verify_start(d->ctx, sdp ? sdp->data : 0, 0, pdp ? pdp->data : 0));
965 }
966
967 VerificationResult Context::verificationResult() const
968 {
969     if (d->lastop & Private::Verify) {
970         return VerificationResult(d->ctx, Error(d->lasterr));
971     } else {
972         return VerificationResult();
973     }
974 }
975
976 std::pair<DecryptionResult, VerificationResult> Context::decryptAndVerify(const Data &cipherText, Data &plainText)
977 {
978     d->lastop = Private::DecryptAndVerify;
979     const Data::Private *const cdp = cipherText.impl();
980     Data::Private *const pdp = plainText.impl();
981     d->lasterr = gpgme_op_decrypt_verify(d->ctx, cdp ? cdp->data : 0, pdp ? pdp->data : 0);
982     return std::make_pair(DecryptionResult(d->ctx, Error(d->lasterr)),
983                           VerificationResult(d->ctx, Error(d->lasterr)));
984 }
985
986 Error Context::startCombinedDecryptionAndVerification(const Data &cipherText, Data &plainText)
987 {
988     d->lastop = Private::DecryptAndVerify;
989     const Data::Private *const cdp = cipherText.impl();
990     Data::Private *const pdp = plainText.impl();
991     return Error(d->lasterr = gpgme_op_decrypt_verify_start(d->ctx, cdp ? cdp->data : 0, pdp ? pdp->data : 0));
992 }
993
994 unsigned int to_auditlog_flags(unsigned int flags)
995 {
996     unsigned int result = 0;
997     if (flags & Context::HtmlAuditLog) {
998         result |= GPGME_AUDITLOG_HTML;
999     }
1000     if (flags & Context::AuditLogWithHelp) {
1001         result |= GPGME_AUDITLOG_WITH_HELP;
1002     }
1003     return result;
1004 }
1005
1006 Error Context::startGetAuditLog(Data &output, unsigned int flags)
1007 {
1008     d->lastop = Private::GetAuditLog;
1009     Data::Private *const odp = output.impl();
1010     return Error(d->lasterr = gpgme_op_getauditlog_start(d->ctx, odp ? odp->data : 0, to_auditlog_flags(flags)));
1011 }
1012
1013 Error Context::getAuditLog(Data &output, unsigned int flags)
1014 {
1015     d->lastop = Private::GetAuditLog;
1016     Data::Private *const odp = output.impl();
1017     return Error(d->lasterr = gpgme_op_getauditlog(d->ctx, odp ? odp->data : 0, to_auditlog_flags(flags)));
1018 }
1019
1020 void Context::clearSigningKeys()
1021 {
1022     gpgme_signers_clear(d->ctx);
1023 }
1024
1025 Error Context::addSigningKey(const Key &key)
1026 {
1027     return Error(d->lasterr = gpgme_signers_add(d->ctx, key.impl()));
1028 }
1029
1030 Key Context::signingKey(unsigned int idx) const
1031 {
1032     gpgme_key_t key = gpgme_signers_enum(d->ctx, idx);
1033     return Key(key, false);
1034 }
1035
1036 std::vector<Key> Context::signingKeys() const
1037 {
1038     std::vector<Key> result;
1039     gpgme_key_t key;
1040     for (unsigned int i = 0 ; (key = gpgme_signers_enum(d->ctx, i)) ; ++i) {
1041         result.push_back(Key(key, false));
1042     }
1043     return result;
1044 }
1045
1046 void Context::clearSignatureNotations()
1047 {
1048     gpgme_sig_notation_clear(d->ctx);
1049 }
1050
1051 GpgME::Error Context::addSignatureNotation(const char *name, const char *value, unsigned int flags)
1052 {
1053     return Error(gpgme_sig_notation_add(d->ctx, name, value, add_to_gpgme_sig_notation_flags_t(0, flags)));
1054 }
1055
1056 GpgME::Error Context::addSignaturePolicyURL(const char *url, bool critical)
1057 {
1058     return Error(gpgme_sig_notation_add(d->ctx, 0, url, critical ? GPGME_SIG_NOTATION_CRITICAL : 0));
1059 }
1060
1061 const char *Context::signaturePolicyURL() const
1062 {
1063     for (gpgme_sig_notation_t n = gpgme_sig_notation_get(d->ctx) ; n ; n = n->next) {
1064         if (!n->name) {
1065             return n->value;
1066         }
1067     }
1068     return nullptr;
1069 }
1070
1071 Notation Context::signatureNotation(unsigned int idx) const
1072 {
1073     for (gpgme_sig_notation_t n = gpgme_sig_notation_get(d->ctx) ; n ; n = n->next) {
1074         if (n->name) {
1075             if (idx-- == 0) {
1076                 return Notation(n);
1077             }
1078         }
1079     }
1080     return Notation();
1081 }
1082
1083 std::vector<Notation> Context::signatureNotations() const
1084 {
1085     std::vector<Notation> result;
1086     for (gpgme_sig_notation_t n = gpgme_sig_notation_get(d->ctx) ; n ; n = n->next) {
1087         if (n->name) {
1088             result.push_back(Notation(n));
1089         }
1090     }
1091     return result;
1092 }
1093
1094 static gpgme_sig_mode_t sigmode2sigmode(SignatureMode mode)
1095 {
1096     switch (mode) {
1097     default:
1098     case NormalSignatureMode: return GPGME_SIG_MODE_NORMAL;
1099     case Detached:            return GPGME_SIG_MODE_DETACH;
1100     case Clearsigned:         return GPGME_SIG_MODE_CLEAR;
1101     }
1102 }
1103
1104 SigningResult Context::sign(const Data &plainText, Data &signature, SignatureMode mode)
1105 {
1106     d->lastop = Private::Sign;
1107     const Data::Private *const pdp = plainText.impl();
1108     Data::Private *const sdp = signature.impl();
1109     d->lasterr = gpgme_op_sign(d->ctx, pdp ? pdp->data : 0, sdp ? sdp->data : 0, sigmode2sigmode(mode));
1110     return SigningResult(d->ctx, Error(d->lasterr));
1111 }
1112
1113 Error Context::startSigning(const Data &plainText, Data &signature, SignatureMode mode)
1114 {
1115     d->lastop = Private::Sign;
1116     const Data::Private *const pdp = plainText.impl();
1117     Data::Private *const sdp = signature.impl();
1118     return Error(d->lasterr = gpgme_op_sign_start(d->ctx, pdp ? pdp->data : 0, sdp ? sdp->data : 0, sigmode2sigmode(mode)));
1119 }
1120
1121 SigningResult Context::signingResult() const
1122 {
1123     if (d->lastop & Private::Sign) {
1124         return SigningResult(d->ctx, Error(d->lasterr));
1125     } else {
1126         return SigningResult();
1127     }
1128 }
1129
1130 static gpgme_encrypt_flags_t encryptflags2encryptflags(Context::EncryptionFlags flags)
1131 {
1132     unsigned int result = 0;
1133     if (flags & Context::AlwaysTrust) {
1134         result |= GPGME_ENCRYPT_ALWAYS_TRUST;
1135     }
1136     if (flags & Context::NoEncryptTo) {
1137         result |= GPGME_ENCRYPT_NO_ENCRYPT_TO;
1138     }
1139     if (flags & Context::Prepare) {
1140         result |= GPGME_ENCRYPT_PREPARE;
1141     }
1142     if (flags & Context::ExpectSign) {
1143         result |= GPGME_ENCRYPT_EXPECT_SIGN;
1144     }
1145     if (flags & Context::NoCompress) {
1146         result |= GPGME_ENCRYPT_NO_COMPRESS;
1147     }
1148     if (flags & Context::Symmetric) {
1149         result |= GPGME_ENCRYPT_SYMMETRIC;
1150     }
1151     return static_cast<gpgme_encrypt_flags_t>(result);
1152 }
1153
1154 gpgme_key_t *Context::getKeysFromRecipients(const std::vector<Key> &recipients)
1155 {
1156     if (recipients.empty()) {
1157         return nullptr;
1158     }
1159     gpgme_key_t *ret = new gpgme_key_t[ recipients.size() + 1 ];
1160     gpgme_key_t *keys_it = ret;
1161     for (std::vector<Key>::const_iterator it = recipients.begin() ; it != recipients.end() ; ++it) {
1162         if (it->impl()) {
1163             *keys_it++ = it->impl();
1164         }
1165     }
1166     *keys_it++ = 0;
1167     return ret;
1168 }
1169
1170 EncryptionResult Context::encrypt(const std::vector<Key> &recipients, const Data &plainText, Data &cipherText, EncryptionFlags flags)
1171 {
1172     d->lastop = Private::Encrypt;
1173     if (flags & NoEncryptTo) {
1174         return EncryptionResult(Error(d->lasterr = make_error(GPG_ERR_NOT_IMPLEMENTED)));
1175     }
1176     const Data::Private *const pdp = plainText.impl();
1177     Data::Private *const cdp = cipherText.impl();
1178     gpgme_key_t *const keys = getKeysFromRecipients(recipients);
1179     d->lasterr = gpgme_op_encrypt(d->ctx, keys, encryptflags2encryptflags(flags),
1180                                   pdp ? pdp->data : 0, cdp ? cdp->data : 0);
1181     if (keys) {
1182         delete[] keys;
1183     }
1184     return EncryptionResult(d->ctx, Error(d->lasterr));
1185 }
1186
1187 Error Context::encryptSymmetrically(const Data &plainText, Data &cipherText)
1188 {
1189     d->lastop = Private::Encrypt;
1190     const Data::Private *const pdp = plainText.impl();
1191     Data::Private *const cdp = cipherText.impl();
1192     return Error(d->lasterr = gpgme_op_encrypt(d->ctx, 0, (gpgme_encrypt_flags_t)0,
1193                               pdp ? pdp->data : 0, cdp ? cdp->data : 0));
1194 }
1195
1196 Error Context::startEncryption(const std::vector<Key> &recipients, const Data &plainText, Data &cipherText, EncryptionFlags flags)
1197 {
1198     d->lastop = Private::Encrypt;
1199     if (flags & NoEncryptTo) {
1200         return Error(d->lasterr = make_error(GPG_ERR_NOT_IMPLEMENTED));
1201     }
1202     const Data::Private *const pdp = plainText.impl();
1203     Data::Private *const cdp = cipherText.impl();
1204     gpgme_key_t *const keys = getKeysFromRecipients(recipients);
1205     d->lasterr = gpgme_op_encrypt_start(d->ctx, keys, encryptflags2encryptflags(flags),
1206                                         pdp ? pdp->data : 0, cdp ? cdp->data : 0);
1207     if (keys) {
1208         delete[] keys;
1209     }
1210     return Error(d->lasterr);
1211 }
1212
1213 EncryptionResult Context::encryptionResult() const
1214 {
1215     if (d->lastop & Private::Encrypt) {
1216         return EncryptionResult(d->ctx, Error(d->lasterr));
1217     } else {
1218         return EncryptionResult();
1219     }
1220 }
1221
1222 std::pair<SigningResult, EncryptionResult> Context::signAndEncrypt(const std::vector<Key> &recipients, const Data &plainText, Data &cipherText, EncryptionFlags flags)
1223 {
1224     d->lastop = Private::SignAndEncrypt;
1225     const Data::Private *const pdp = plainText.impl();
1226     Data::Private *const cdp = cipherText.impl();
1227     gpgme_key_t *const keys = getKeysFromRecipients(recipients);
1228     d->lasterr = gpgme_op_encrypt_sign(d->ctx, keys, encryptflags2encryptflags(flags),
1229                                        pdp ? pdp->data : 0, cdp ? cdp->data : 0);
1230     if (keys) {
1231         delete[] keys;
1232     }
1233     return std::make_pair(SigningResult(d->ctx, Error(d->lasterr)),
1234                           EncryptionResult(d->ctx, Error(d->lasterr)));
1235 }
1236
1237 Error Context::startCombinedSigningAndEncryption(const std::vector<Key> &recipients, const Data &plainText, Data &cipherText, EncryptionFlags flags)
1238 {
1239     d->lastop = Private::SignAndEncrypt;
1240     const Data::Private *const pdp = plainText.impl();
1241     Data::Private *const cdp = cipherText.impl();
1242     gpgme_key_t *const keys = getKeysFromRecipients(recipients);
1243     d->lasterr = gpgme_op_encrypt_sign_start(d->ctx, keys, encryptflags2encryptflags(flags),
1244                  pdp ? pdp->data : 0, cdp ? cdp->data : 0);
1245     if (keys) {
1246         delete[] keys;
1247     }
1248     return Error(d->lasterr);
1249 }
1250
1251 Error Context::createVFS(const char *containerFile, const std::vector< Key > &recipients)
1252 {
1253     d->lastop = Private::CreateVFS;
1254     gpgme_key_t *const keys = new gpgme_key_t[ recipients.size() + 1 ];
1255     gpgme_key_t *keys_it = keys;
1256     for (std::vector<Key>::const_iterator it = recipients.begin() ; it != recipients.end() ; ++it) {
1257         if (it->impl()) {
1258             *keys_it++ = it->impl();
1259         }
1260     }
1261     *keys_it++ = 0;
1262
1263     gpgme_error_t op_err;
1264     d->lasterr = gpgme_op_vfs_create(d->ctx, keys, containerFile, 0, &op_err);
1265     delete[] keys;
1266     Error error(d->lasterr);
1267     if (error) {
1268         return error;
1269     }
1270     return Error(d->lasterr = op_err);
1271 }
1272
1273 VfsMountResult Context::mountVFS(const char *containerFile, const char *mountDir)
1274 {
1275     d->lastop = Private::MountVFS;
1276     gpgme_error_t op_err;
1277     d->lasterr = gpgme_op_vfs_mount(d->ctx, containerFile, mountDir, 0, &op_err);
1278     return VfsMountResult(d->ctx, Error(d->lasterr), Error(op_err));
1279 }
1280
1281 Error Context::cancelPendingOperation()
1282 {
1283     return Error(gpgme_cancel_async(d->ctx));
1284 }
1285
1286 bool Context::poll()
1287 {
1288     gpgme_error_t e = GPG_ERR_NO_ERROR;
1289     const bool finished = gpgme_wait(d->ctx, &e, 0);
1290     if (finished) {
1291         d->lasterr = e;
1292     }
1293     return finished;
1294 }
1295
1296 Error Context::wait()
1297 {
1298     gpgme_error_t e = GPG_ERR_NO_ERROR;
1299     gpgme_wait(d->ctx, &e, 1);
1300     return Error(d->lasterr = e);
1301 }
1302
1303 Error Context::lastError() const
1304 {
1305     return Error(d->lasterr);
1306 }
1307
1308 Context::PinentryMode Context::pinentryMode() const
1309 {
1310     switch (gpgme_get_pinentry_mode (d->ctx)) {
1311         case GPGME_PINENTRY_MODE_ASK:
1312             return PinentryAsk;
1313         case GPGME_PINENTRY_MODE_CANCEL:
1314             return PinentryCancel;
1315         case GPGME_PINENTRY_MODE_ERROR:
1316             return PinentryError;
1317         case GPGME_PINENTRY_MODE_LOOPBACK:
1318             return PinentryLoopback;
1319         case GPGME_PINENTRY_MODE_DEFAULT:
1320         default:
1321             return PinentryDefault;
1322     }
1323 }
1324
1325 Error Context::setPinentryMode(PinentryMode which)
1326 {
1327     gpgme_pinentry_mode_t mode;
1328     switch (which) {
1329         case PinentryAsk:
1330             mode = GPGME_PINENTRY_MODE_ASK;
1331             break;
1332         case PinentryCancel:
1333             mode = GPGME_PINENTRY_MODE_CANCEL;
1334             break;
1335         case PinentryError:
1336             mode = GPGME_PINENTRY_MODE_ERROR;
1337             break;
1338         case PinentryLoopback:
1339             mode = GPGME_PINENTRY_MODE_LOOPBACK;
1340             break;
1341         case PinentryDefault:
1342         default:
1343             mode = GPGME_PINENTRY_MODE_DEFAULT;
1344     }
1345     return Error(d->lasterr = gpgme_set_pinentry_mode(d->ctx, mode));
1346 }
1347
1348 static gpgme_tofu_policy_t to_tofu_policy_t(unsigned int policy)
1349 {
1350     switch (policy) {
1351         case TofuInfo::PolicyNone:
1352             return GPGME_TOFU_POLICY_NONE;
1353         case TofuInfo::PolicyAuto:
1354             return GPGME_TOFU_POLICY_AUTO;
1355         case TofuInfo::PolicyGood:
1356             return GPGME_TOFU_POLICY_GOOD;
1357         case TofuInfo::PolicyBad:
1358             return GPGME_TOFU_POLICY_BAD;
1359         case TofuInfo::PolicyAsk:
1360             return GPGME_TOFU_POLICY_ASK;
1361         case TofuInfo::PolicyUnknown:
1362         default:
1363             return GPGME_TOFU_POLICY_UNKNOWN;
1364     }
1365 }
1366
1367 Error Context::setTofuPolicy(const Key &k, unsigned int policy)
1368 {
1369     return Error(d->lasterr = gpgme_op_tofu_policy(d->ctx,
1370                  k.impl(), to_tofu_policy_t(policy)));
1371 }
1372
1373 Error Context::setTofuPolicyStart(const Key &k, unsigned int policy)
1374 {
1375     return Error(d->lasterr = gpgme_op_tofu_policy_start(d->ctx,
1376                  k.impl(), to_tofu_policy_t(policy)));
1377 }
1378
1379 // Engine Spawn stuff
1380 Error Context::spawn(const char *file, const char *argv[],
1381                      Data &input, Data &output, Data &err,
1382                      SpawnFlags flags)
1383 {
1384     return Error(d->lasterr = gpgme_op_spawn (d->ctx, file, argv,
1385         input.impl() ? input.impl()->data : nullptr,
1386         output.impl() ? output.impl()->data : nullptr,
1387         err.impl() ? err.impl()->data : nullptr,
1388         static_cast<int>(flags)));
1389 }
1390
1391 Error Context::spawnAsync(const char *file, const char *argv[],
1392                           Data &input, Data &output, Data &err,
1393                           SpawnFlags flags)
1394 {
1395     return Error(d->lasterr = gpgme_op_spawn_start (d->ctx, file, argv,
1396         input.impl() ? input.impl()->data : nullptr,
1397         output.impl() ? output.impl()->data : nullptr,
1398         err.impl() ? err.impl()->data : nullptr,
1399         static_cast<int>(flags)));
1400 }
1401
1402 std::ostream &operator<<(std::ostream &os, Protocol proto)
1403 {
1404     os << "GpgME::Protocol(";
1405     switch (proto) {
1406     case OpenPGP:
1407         os << "OpenPGP";
1408         break;
1409     case CMS:
1410         os << "CMS";
1411         break;
1412     default:
1413     case UnknownProtocol:
1414         os << "UnknownProtocol";
1415         break;
1416     }
1417     return os << ')';
1418 }
1419
1420 std::ostream &operator<<(std::ostream &os, Engine eng)
1421 {
1422     os << "GpgME::Engine(";
1423     switch (eng) {
1424     case GpgEngine:
1425         os << "GpgEngine";
1426         break;
1427     case GpgSMEngine:
1428         os << "GpgSMEngine";
1429         break;
1430     case GpgConfEngine:
1431         os << "GpgConfEngine";
1432         break;
1433     case AssuanEngine:
1434         os << "AssuanEngine";
1435         break;
1436     case SpawnEngine:
1437         os << "SpawnEngine";
1438         break;
1439     default:
1440     case UnknownEngine:
1441         os << "UnknownEngine";
1442         break;
1443     }
1444     return os << ')';
1445 }
1446
1447 std::ostream &operator<<(std::ostream &os, Context::CertificateInclusion incl)
1448 {
1449     os << "GpgME::Context::CertificateInclusion(" << static_cast<int>(incl);
1450     switch (incl) {
1451     case Context::DefaultCertificates:
1452         os << "(DefaultCertificates)";
1453         break;
1454     case Context::AllCertificatesExceptRoot:
1455         os << "(AllCertificatesExceptRoot)";
1456         break;
1457     case Context::AllCertificates:
1458         os << "(AllCertificates)";
1459         break;
1460     case Context::NoCertificates:
1461         os << "(NoCertificates)";
1462         break;
1463     case Context::OnlySenderCertificate:
1464         os << "(OnlySenderCertificate)";
1465         break;
1466     }
1467     return os << ')';
1468 }
1469
1470 std::ostream &operator<<(std::ostream &os, KeyListMode mode)
1471 {
1472     os << "GpgME::KeyListMode(";
1473 #define CHECK( x ) if ( !(mode & (x)) ) {} else do { os << #x " "; } while (0)
1474     CHECK(Local);
1475     CHECK(Extern);
1476     CHECK(Signatures);
1477     CHECK(Validate);
1478     CHECK(Ephemeral);
1479     CHECK(WithTofu);
1480 #undef CHECK
1481     return os << ')';
1482 }
1483
1484 std::ostream &operator<<(std::ostream &os, SignatureMode mode)
1485 {
1486     os << "GpgME::SignatureMode(";
1487     switch (mode) {
1488 #define CHECK( x ) case x: os << #x; break
1489         CHECK(NormalSignatureMode);
1490         CHECK(Detached);
1491         CHECK(Clearsigned);
1492 #undef CHECK
1493     default:
1494         os << "???" "(" << static_cast<int>(mode) << ')';
1495         break;
1496     }
1497     return os << ')';
1498 }
1499
1500 std::ostream &operator<<(std::ostream &os, Context::EncryptionFlags flags)
1501 {
1502     os << "GpgME::Context::EncryptionFlags(";
1503 #define CHECK( x ) if ( !(flags & (Context::x)) ) {} else do { os << #x " "; } while (0)
1504     CHECK(AlwaysTrust);
1505     CHECK(NoEncryptTo);
1506     CHECK(Prepare);
1507     CHECK(ExpectSign);
1508     CHECK(NoCompress);
1509     CHECK(Symmetric);
1510 #undef CHECK
1511     return os << ')';
1512 }
1513
1514 std::ostream &operator<<(std::ostream &os, Context::AuditLogFlags flags)
1515 {
1516     os << "GpgME::Context::AuditLogFlags(";
1517 #define CHECK( x ) if ( !(flags & (Context::x)) ) {} else do { os << #x " "; } while (0)
1518     CHECK(HtmlAuditLog);
1519     CHECK(AuditLogWithHelp);
1520 #undef CHECK
1521     return os << ')';
1522 }
1523
1524 } // namespace GpgME
1525
1526 GpgME::Error GpgME::setDefaultLocale(int cat, const char *val)
1527 {
1528     return Error(gpgme_set_locale(0, cat, val));
1529 }
1530
1531 GpgME::EngineInfo GpgME::engineInfo(GpgME::Protocol proto)
1532 {
1533     gpgme_engine_info_t ei = 0;
1534     if (gpgme_get_engine_info(&ei)) {
1535         return EngineInfo();
1536     }
1537
1538     const gpgme_protocol_t p = proto == CMS ? GPGME_PROTOCOL_CMS : GPGME_PROTOCOL_OpenPGP ;
1539
1540     for (gpgme_engine_info_t i = ei ; i ; i = i->next) {
1541         if (i->protocol == p) {
1542             return EngineInfo(i);
1543         }
1544     }
1545
1546     return EngineInfo();
1547 }
1548
1549 const char *GpgME::dirInfo(const char *what)
1550 {
1551     return gpgme_get_dirinfo(what);
1552 }
1553
1554 GpgME::Error GpgME::checkEngine(GpgME::Protocol proto)
1555 {
1556     const gpgme_protocol_t p = proto == CMS ? GPGME_PROTOCOL_CMS : GPGME_PROTOCOL_OpenPGP ;
1557
1558     return Error(gpgme_engine_check_version(p));
1559 }
1560
1561 static const gpgme_protocol_t UNKNOWN_PROTOCOL = static_cast<gpgme_protocol_t>(255);
1562
1563 static gpgme_protocol_t engine2protocol(const GpgME::Engine engine)
1564 {
1565     switch (engine) {
1566     case GpgME::GpgEngine:   return GPGME_PROTOCOL_OpenPGP;
1567     case GpgME::GpgSMEngine: return GPGME_PROTOCOL_CMS;
1568     case GpgME::GpgConfEngine:
1569         return GPGME_PROTOCOL_GPGCONF;
1570     case GpgME::AssuanEngine:
1571         return GPGME_PROTOCOL_ASSUAN;
1572     case GpgME::G13Engine:
1573         return GPGME_PROTOCOL_G13;
1574     case GpgME::SpawnEngine:
1575         return GPGME_PROTOCOL_SPAWN;
1576     case GpgME::UnknownEngine:
1577         ;
1578     }
1579     return UNKNOWN_PROTOCOL;
1580 }
1581
1582 GpgME::EngineInfo GpgME::engineInfo(GpgME::Engine engine)
1583 {
1584     gpgme_engine_info_t ei = 0;
1585     if (gpgme_get_engine_info(&ei)) {
1586         return EngineInfo();
1587     }
1588
1589     const gpgme_protocol_t p = engine2protocol(engine);
1590
1591     for (gpgme_engine_info_t i = ei ; i ; i = i->next) {
1592         if (i->protocol == p) {
1593             return EngineInfo(i);
1594         }
1595     }
1596
1597     return EngineInfo();
1598 }
1599
1600 GpgME::Error GpgME::checkEngine(GpgME::Engine engine)
1601 {
1602     const gpgme_protocol_t p = engine2protocol(engine);
1603
1604     return Error(gpgme_engine_check_version(p));
1605 }
1606
1607 static const unsigned long supported_features = 0
1608         | GpgME::ValidatingKeylistModeFeature
1609         | GpgME::CancelOperationFeature
1610         | GpgME::WrongKeyUsageFeature
1611         | GpgME::DefaultCertificateInclusionFeature
1612         | GpgME::GetSetEngineInfoFeature
1613         | GpgME::ClearAddGetSignatureNotationsFeature
1614         | GpgME::SetDataFileNameFeeature
1615         | GpgME::SignatureNotationsKeylistModeFeature
1616         | GpgME::KeySignatureNotationsFeature
1617         | GpgME::KeyIsQualifiedFeature
1618         | GpgME::SignatureNotationsCriticalFlagFeature
1619         | GpgME::SignatureNotationsFlagsFeature
1620         | GpgME::SignatureNotationsHumanReadableFlagFeature
1621         | GpgME::SubkeyIsQualifiedFeature
1622         | GpgME::EngineInfoHomeDirFeature
1623         | GpgME::DecryptionResultFileNameFeature
1624         | GpgME::DecryptionResultRecipientsFeature
1625         | GpgME::VerificationResultFileNameFeature
1626         | GpgME::SignaturePkaFieldsFeature
1627         | GpgME::SignatureAlgorithmFieldsFeature
1628         | GpgME::FdPointerFeature
1629         | GpgME::AuditLogFeature
1630         | GpgME::GpgConfEngineFeature
1631         | GpgME::CancelOperationAsyncFeature
1632         | GpgME::NoEncryptToEncryptionFlagFeature
1633         | GpgME::CardKeyFeature
1634         | GpgME::AssuanEngineFeature
1635         | GpgME::EphemeralKeylistModeFeature
1636         | GpgME::ImportFromKeyserverFeature
1637         | GpgME::G13VFSFeature
1638         | GpgME::PasswdFeature
1639         ;
1640
1641 static const unsigned long supported_features2 = 0
1642         | GpgME::BinaryAndFineGrainedIdentify
1643         ;
1644
1645 bool GpgME::hasFeature(unsigned long features)
1646 {
1647     return features == (features & supported_features);
1648 }
1649
1650 bool GpgME::hasFeature(unsigned long features, unsigned long features2)
1651 {
1652     return features  == (features  & supported_features)
1653            && features2 == (features2 & supported_features2)
1654            ;
1655 }