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