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