2 context.cpp - wraps a gpgme key context
3 Copyright (C) 2003, 2007 Klarälvdalens Datakonsult AB
4 2017, 2018 Intevation GmbH
6 This file is part of GPGME++.
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.
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.
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.
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>
42 #include <interfaces/assuantransaction.h>
43 #include <defaultassuantransaction.h>
45 #include "callbacks.h"
47 #include "context_p.h"
65 static inline unsigned int xtoi_1(const char *str)
67 const unsigned int ch = *str;
68 const unsigned int result =
69 ch <= '9' ? ch - '0' :
70 ch <= 'F' ? ch - 'A' + 10 :
71 /* else */ ch - 'a' + 10 ;
72 return result < 16 ? result : 0 ;
74 static inline int xtoi_2(const char *str)
76 return xtoi_1(str) * 16U + xtoi_1(str + 1);
79 static void percent_unescape(std::string &s, bool plus2space)
81 std::string::iterator src = s.begin(), dest = s.begin(), end = s.end();
83 if (*src == '%' && end - src > 2) {
84 *dest++ = xtoi_2(&*++src);
86 } else if (*src == '+' && plus2space) {
96 void initializeLibrary()
98 gpgme_check_version(nullptr);
101 Error initializeLibrary(int)
103 if (gpgme_check_version(GPGME_VERSION)) {
106 return Error::fromCode(GPG_ERR_USER_1);
110 static void format_error(gpgme_error_t err, std::string &str)
113 gpgme_strerror_r(err, buffer, sizeof buffer);
114 buffer[ sizeof buffer - 1 ] = '\0';
118 const char *Error::source() const
120 return gpgme_strsource((gpgme_error_t)mErr);
123 const char *Error::asString() const
125 if (mMessage.empty()) {
126 format_error(static_cast<gpgme_error_t>(mErr), mMessage);
128 return mMessage.c_str();
131 int Error::code() const
133 return gpgme_err_code(mErr);
136 int Error::sourceID() const
138 return gpgme_err_source(mErr);
141 bool Error::isCanceled() const
143 return code() == GPG_ERR_CANCELED;
146 int Error::toErrno() const
148 //#ifdef HAVE_GPGME_GPG_ERROR_WRAPPERS
149 return gpgme_err_code_to_errno(static_cast<gpgme_err_code_t>(code()));
151 // return gpg_err_code_to_errno( static_cast<gpg_err_code_t>( code() ) );
156 bool Error::hasSystemError()
158 return gpgme_err_code_from_syserror() != GPG_ERR_MISSING_ERRNO ;
162 void Error::setSystemError(gpg_err_code_t err)
164 setErrno(gpgme_err_code_to_errno(err));
168 void Error::setErrno(int err)
170 gpgme_err_set_errno(err);
174 Error Error::fromSystemError(unsigned int src)
176 return Error(gpgme_err_make(static_cast<gpgme_err_source_t>(src), gpgme_err_code_from_syserror()));
180 Error Error::fromErrno(int err, unsigned int src)
182 return Error(gpgme_err_make(static_cast<gpgme_err_source_t>(src), gpgme_err_code_from_errno(err)));
186 Error Error::fromCode(unsigned int err, unsigned int src)
188 return Error(gpgme_err_make(static_cast<gpgme_err_source_t>(src), static_cast<gpgme_err_code_t>(err)));
191 std::ostream &operator<<(std::ostream &os, const Error &err)
193 return os << "GpgME::Error(" << err.encodedError() << " (" << err.asString() << "))";
196 Context::Context(gpgme_ctx_t ctx) : d(new Private(ctx))
205 Context *Context::createForProtocol(Protocol proto)
207 gpgme_ctx_t ctx = nullptr;
208 if (gpgme_new(&ctx) != 0) {
214 if (gpgme_set_protocol(ctx, GPGME_PROTOCOL_OpenPGP) != 0) {
220 if (gpgme_set_protocol(ctx, GPGME_PROTOCOL_CMS) != 0) {
229 return new Context(ctx);
232 std::unique_ptr<Context> Context::create(Protocol proto)
234 return std::unique_ptr <Context> (createForProtocol(proto));
237 std::unique_ptr<Context> Context::createForEngine(Engine eng, Error *error)
239 gpgme_ctx_t ctx = nullptr;
240 if (const gpgme_error_t err = gpgme_new(&ctx)) {
244 return std::unique_ptr<Context>();
249 if (const gpgme_error_t err = gpgme_set_protocol(ctx, GPGME_PROTOCOL_ASSUAN)) {
254 return std::unique_ptr<Context>();
258 if (const gpgme_error_t err = gpgme_set_protocol(ctx, GPGME_PROTOCOL_G13)) {
263 return std::unique_ptr<Context>();
267 if (const gpgme_error_t err = gpgme_set_protocol(ctx, GPGME_PROTOCOL_SPAWN)) {
272 return std::unique_ptr<Context>();
277 *error = Error::fromCode(GPG_ERR_INV_ARG);
279 return std::unique_ptr<Context>();
286 return std::unique_ptr<Context>(new Context(ctx));
289 void Context::setDecryptionFlags(DecryptionFlags flags)
291 d->decryptFlags = flags;
300 Context::Private::Private(gpgme_ctx_t c)
304 lasterr(GPG_ERR_NO_ERROR),
305 lastAssuanInquireData(Data::null),
306 lastAssuanTransaction(),
307 lastEditInteractor(),
308 lastCardEditInteractor(),
309 decryptFlags(DecryptNone)
314 Context::Private::~Private()
325 // Context attributes:
329 Protocol Context::protocol() const
331 gpgme_protocol_t p = gpgme_get_protocol(d->ctx);
333 case GPGME_PROTOCOL_OpenPGP: return OpenPGP;
334 case GPGME_PROTOCOL_CMS: return CMS;
335 default: return UnknownProtocol;
339 void Context::setArmor(bool useArmor)
341 gpgme_set_armor(d->ctx, int(useArmor));
343 bool Context::armor() const
345 return gpgme_get_armor(d->ctx);
348 void Context::setTextMode(bool useTextMode)
350 gpgme_set_textmode(d->ctx, int(useTextMode));
352 bool Context::textMode() const
354 return gpgme_get_textmode(d->ctx);
357 void Context::setOffline(bool useOfflineMode)
359 gpgme_set_offline(d->ctx, int(useOfflineMode));
361 bool Context::offline() const
363 return gpgme_get_offline(d->ctx);
366 void Context::setIncludeCertificates(int which)
368 if (which == DefaultCertificates) {
369 which = GPGME_INCLUDE_CERTS_DEFAULT;
371 gpgme_set_include_certs(d->ctx, which);
374 int Context::includeCertificates() const
376 return gpgme_get_include_certs(d->ctx);
379 void Context::setKeyListMode(unsigned int mode)
381 gpgme_set_keylist_mode(d->ctx, add_to_gpgme_keylist_mode_t(0, mode));
384 void Context::addKeyListMode(unsigned int mode)
386 const unsigned int cur = gpgme_get_keylist_mode(d->ctx);
387 gpgme_set_keylist_mode(d->ctx, add_to_gpgme_keylist_mode_t(cur, mode));
390 unsigned int Context::keyListMode() const
392 return convert_from_gpgme_keylist_mode_t(gpgme_get_keylist_mode(d->ctx));
395 void Context::setProgressProvider(ProgressProvider *provider)
397 gpgme_set_progress_cb(d->ctx, provider ? &progress_callback : nullptr, provider);
399 ProgressProvider *Context::progressProvider() const
402 gpgme_progress_cb_t pcb = &progress_callback;
403 gpgme_get_progress_cb(d->ctx, &pcb, &pp);
404 return static_cast<ProgressProvider *>(pp);
407 void Context::setPassphraseProvider(PassphraseProvider *provider)
409 gpgme_set_passphrase_cb(d->ctx, provider ? &passphrase_callback : nullptr, provider);
412 PassphraseProvider *Context::passphraseProvider() const
415 gpgme_passphrase_cb_t pcb = &passphrase_callback;
416 gpgme_get_passphrase_cb(d->ctx, &pcb, &pp);
417 return static_cast<PassphraseProvider *>(pp);
420 void Context::setManagedByEventLoopInteractor(bool manage)
422 if (!EventLoopInteractor::instance()) {
424 cerr << "Context::setManagedByEventLoopInteractor(): "
425 "You must create an instance of EventLoopInteractor "
426 "before using anything that needs one." << endl;
431 EventLoopInteractor::instance()->manage(this);
433 EventLoopInteractor::instance()->unmanage(this);
436 bool Context::managedByEventLoopInteractor() const
438 return d->iocbs != nullptr;
441 void Context::installIOCallbacks(gpgme_io_cbs *iocbs)
444 uninstallIOCallbacks();
447 gpgme_set_io_cbs(d->ctx, iocbs);
448 delete d->iocbs; d->iocbs = iocbs;
451 void Context::uninstallIOCallbacks()
453 static gpgme_io_cbs noiocbs = { nullptr, nullptr, nullptr, nullptr, nullptr };
454 // io.add == 0 means disable io callbacks:
455 gpgme_set_io_cbs(d->ctx, &noiocbs);
456 delete d->iocbs; d->iocbs = nullptr;
459 Error Context::setLocale(int cat, const char *val)
461 return Error(d->lasterr = gpgme_set_locale(d->ctx, cat, val));
464 EngineInfo Context::engineInfo() const
466 return EngineInfo(gpgme_ctx_get_engine_info(d->ctx));
469 Error Context::setEngineFileName(const char *filename)
471 const char *const home_dir = engineInfo().homeDirectory();
472 return Error(gpgme_ctx_set_engine_info(d->ctx, gpgme_get_protocol(d->ctx), filename, home_dir));
475 Error Context::setEngineHomeDirectory(const char *home_dir)
477 const char *const filename = engineInfo().fileName();
478 return Error(gpgme_ctx_set_engine_info(d->ctx, gpgme_get_protocol(d->ctx), filename, home_dir));
481 Error Context::setSender (const char *sender)
483 return Error(gpgme_set_sender(d->ctx, sender));
486 const char *Context::getSender ()
488 return gpgme_get_sender(d->ctx);
497 Error Context::startKeyListing(const char *pattern, bool secretOnly)
499 d->lastop = Private::KeyList;
500 return Error(d->lasterr = gpgme_op_keylist_start(d->ctx, pattern, int(secretOnly)));
503 Error Context::startKeyListing(const char *patterns[], bool secretOnly)
505 d->lastop = Private::KeyList;
506 #ifndef HAVE_GPGME_EXT_KEYLIST_MODE_EXTERNAL_NONBROKEN
507 if (!patterns || !patterns[0] || !patterns[1]) {
508 // max. one pattern -> use the non-ext version
509 return startKeyListing(patterns ? patterns[0] : nullptr, secretOnly);
512 return Error(d->lasterr = gpgme_op_keylist_ext_start(d->ctx, patterns, int(secretOnly), 0));
515 Key Context::nextKey(GpgME::Error &e)
517 d->lastop = Private::KeyList;
518 gpgme_key_t key = nullptr;
519 e = Error(d->lasterr = gpgme_op_keylist_next(d->ctx, &key));
520 return Key(key, false);
523 KeyListResult Context::endKeyListing()
525 d->lasterr = gpgme_op_keylist_end(d->ctx);
526 return keyListResult();
529 KeyListResult Context::keyListResult() const
531 return KeyListResult(d->ctx, Error(d->lasterr));
534 Key Context::key(const char *fingerprint, GpgME::Error &e , bool secret /*, bool forceUpdate*/)
536 d->lastop = Private::KeyList;
537 gpgme_key_t key = nullptr;
538 e = Error(d->lasterr = gpgme_get_key(d->ctx, fingerprint, &key, int(secret)/*, int( forceUpdate )*/));
539 return Key(key, false);
542 KeyGenerationResult Context::generateKey(const char *parameters, Data &pubKey)
544 d->lastop = Private::KeyGen;
545 Data::Private *const dp = pubKey.impl();
546 d->lasterr = gpgme_op_genkey(d->ctx, parameters, dp ? dp->data : nullptr, nullptr);
547 return KeyGenerationResult(d->ctx, Error(d->lasterr));
550 Error Context::startKeyGeneration(const char *parameters, Data &pubKey)
552 d->lastop = Private::KeyGen;
553 Data::Private *const dp = pubKey.impl();
554 return Error(d->lasterr = gpgme_op_genkey_start(d->ctx, parameters, dp ? dp->data : nullptr, nullptr));
557 KeyGenerationResult Context::keyGenerationResult() const
559 if (d->lastop & Private::KeyGen) {
560 return KeyGenerationResult(d->ctx, Error(d->lasterr));
562 return KeyGenerationResult();
566 Error Context::exportPublicKeys(const char *pattern, Data &keyData, unsigned int flags)
568 d->lastop = Private::Export;
569 Data::Private *const dp = keyData.impl();
570 return Error(d->lasterr = gpgme_op_export(d->ctx, pattern, flags, dp ? dp->data : nullptr));
573 Error Context::exportPublicKeys(const char *patterns[], Data &keyData, unsigned int flags)
575 d->lastop = Private::Export;
576 #ifndef HAVE_GPGME_EXT_KEYLIST_MODE_EXTERNAL_NONBROKEN
577 if (!patterns || !patterns[0] || !patterns[1]) {
578 // max. one pattern -> use the non-ext version
579 return exportPublicKeys(patterns ? patterns[0] : nullptr, keyData, flags);
582 Data::Private *const dp = keyData.impl();
583 return Error(d->lasterr = gpgme_op_export_ext(d->ctx, patterns, flags, dp ? dp->data : nullptr));
586 Error Context::startPublicKeyExport(const char *pattern, Data &keyData, unsigned int flags)
588 d->lastop = Private::Export;
589 Data::Private *const dp = keyData.impl();
590 return Error(d->lasterr = gpgme_op_export_start(d->ctx, pattern, flags, dp ? dp->data : nullptr));
593 Error Context::startPublicKeyExport(const char *patterns[], Data &keyData, unsigned int flags)
595 d->lastop = Private::Export;
596 #ifndef HAVE_GPGME_EXT_KEYLIST_MODE_EXTERNAL_NONBROKEN
597 if (!patterns || !patterns[0] || !patterns[1]) {
598 // max. one pattern -> use the non-ext version
599 return startPublicKeyExport(patterns ? patterns[0] : nullptr, keyData, flags);
602 Data::Private *const dp = keyData.impl();
603 return Error(d->lasterr = gpgme_op_export_ext_start(d->ctx, patterns, flags, dp ? dp->data : nullptr));
607 /* Same as above but without flags */
608 Error Context::exportPublicKeys(const char *pattern, Data &keyData)
610 return exportPublicKeys(pattern, keyData, 0);
613 Error Context::exportPublicKeys(const char *patterns[], Data &keyData)
615 return exportPublicKeys(patterns, keyData, 0);
618 Error Context::startPublicKeyExport(const char *pattern, Data &keyData)
620 return startPublicKeyExport(pattern, keyData, 0);
623 Error Context::startPublicKeyExport(const char *patterns[], Data &keyData)
625 return startPublicKeyExport(patterns, keyData, 0);
628 ImportResult Context::importKeys(const Data &data)
630 d->lastop = Private::Import;
631 const Data::Private *const dp = data.impl();
632 d->lasterr = gpgme_op_import(d->ctx, dp ? dp->data : nullptr);
633 return ImportResult(d->ctx, Error(d->lasterr));
636 ImportResult Context::importKeys(const std::vector<Key> &kk)
638 d->lastop = Private::Import;
639 d->lasterr = make_error(GPG_ERR_NOT_IMPLEMENTED);
641 bool shouldHaveResult = false;
642 gpgme_key_t * const keys = new gpgme_key_t[ kk.size() + 1 ];
643 gpgme_key_t *keys_it = &keys[0];
644 for (std::vector<Key>::const_iterator it = kk.begin(), end = kk.end() ; it != end ; ++it) {
646 *keys_it++ = it->impl();
649 *keys_it++ = nullptr;
650 d->lasterr = gpgme_op_import_keys(d->ctx, keys);
651 shouldHaveResult = true;
652 if ((gpgme_err_code(d->lasterr) == GPG_ERR_NOT_IMPLEMENTED ||
653 gpgme_err_code(d->lasterr) == GPG_ERR_NOT_SUPPORTED) &&
655 // ok, try the workaround (export+import):
656 std::vector<const char *> fprs;
657 for (std::vector<Key>::const_iterator it = kk.begin(), end = kk.end() ; it != end ; ++it) {
658 if (const char *fpr = it->primaryFingerprint()) {
662 } else if (const char *keyid = it->keyID()) {
664 fprs.push_back(keyid);
668 fprs.push_back(nullptr);
670 Data::Private *const dp = data.impl();
671 const gpgme_keylist_mode_t oldMode = gpgme_get_keylist_mode(d->ctx);
672 gpgme_set_keylist_mode(d->ctx, GPGME_KEYLIST_MODE_EXTERN);
673 d->lasterr = gpgme_op_export_ext(d->ctx, &fprs[0], 0, dp ? dp->data : nullptr);
674 gpgme_set_keylist_mode(d->ctx, oldMode);
676 data.seek(0, SEEK_SET);
677 d->lasterr = gpgme_op_import(d->ctx, dp ? dp->data : nullptr);
678 shouldHaveResult = true;
682 if (shouldHaveResult) {
683 return ImportResult(d->ctx, Error(d->lasterr));
685 return ImportResult(Error(d->lasterr));
689 Error Context::startKeyImport(const Data &data)
691 d->lastop = Private::Import;
692 const Data::Private *const dp = data.impl();
693 return Error(d->lasterr = gpgme_op_import_start(d->ctx, dp ? dp->data : nullptr));
696 Error Context::startKeyImport(const std::vector<Key> &kk)
698 d->lastop = Private::Import;
699 gpgme_key_t * const keys = new gpgme_key_t[ kk.size() + 1 ];
700 gpgme_key_t *keys_it = &keys[0];
701 for (std::vector<Key>::const_iterator it = kk.begin(), end = kk.end() ; it != end ; ++it) {
703 *keys_it++ = it->impl();
706 *keys_it++ = nullptr;
707 Error err = Error(d->lasterr = gpgme_op_import_keys_start(d->ctx, keys));
712 ImportResult Context::importResult() const
714 if (d->lastop & Private::Import) {
715 return ImportResult(d->ctx, Error(d->lasterr));
717 return ImportResult();
721 Error Context::deleteKey(const Key &key, bool allowSecretKeyDeletion)
723 d->lastop = Private::Delete;
724 return Error(d->lasterr = gpgme_op_delete(d->ctx, key.impl(), int(allowSecretKeyDeletion)));
727 Error Context::startKeyDeletion(const Key &key, bool allowSecretKeyDeletion)
729 d->lastop = Private::Delete;
730 return Error(d->lasterr = gpgme_op_delete_start(d->ctx, key.impl(), int(allowSecretKeyDeletion)));
733 Error Context::passwd(const Key &key)
735 d->lastop = Private::Passwd;
736 return Error(d->lasterr = gpgme_op_passwd(d->ctx, key.impl(), 0U));
739 Error Context::startPasswd(const Key &key)
741 d->lastop = Private::Passwd;
742 return Error(d->lasterr = gpgme_op_passwd_start(d->ctx, key.impl(), 0U));
746 #pragma GCC diagnostic push
747 #pragma GCC diagnostic ignored "-Wdeprecated-declarations"
749 Error Context::edit(const Key &key, std::unique_ptr<EditInteractor> func, Data &data)
751 d->lastop = Private::Edit;
752 d->lastEditInteractor = std::move(func);
753 Data::Private *const dp = data.impl();
754 return Error(d->lasterr = gpgme_op_edit(d->ctx, key.impl(),
755 d->lastEditInteractor.get() ? edit_interactor_callback : nullptr,
756 d->lastEditInteractor.get() ? d->lastEditInteractor->d : nullptr,
757 dp ? dp->data : nullptr));
761 Error Context::startEditing(const Key &key, std::unique_ptr<EditInteractor> func, Data &data)
763 d->lastop = Private::Edit;
764 d->lastEditInteractor = std::move(func);
765 Data::Private *const dp = data.impl();
766 return Error(d->lasterr = gpgme_op_edit_start(d->ctx, key.impl(),
767 d->lastEditInteractor.get() ? edit_interactor_callback : nullptr,
768 d->lastEditInteractor.get() ? d->lastEditInteractor->d : nullptr,
769 dp ? dp->data : nullptr));
773 EditInteractor *Context::lastEditInteractor() const
775 return d->lastEditInteractor.get();
778 std::unique_ptr<EditInteractor> Context::takeLastEditInteractor()
780 return std::move(d->lastEditInteractor);
784 Error Context::cardEdit(const Key &key, std::unique_ptr<EditInteractor> func, Data &data)
786 d->lastop = Private::CardEdit;
787 d->lastCardEditInteractor = std::move(func);
788 Data::Private *const dp = data.impl();
789 return Error(d->lasterr = gpgme_op_card_edit(d->ctx, key.impl(),
790 d->lastCardEditInteractor.get() ? edit_interactor_callback : nullptr,
791 d->lastCardEditInteractor.get() ? d->lastCardEditInteractor->d : nullptr,
792 dp ? dp->data : nullptr));
795 Error Context::startCardEditing(const Key &key, std::unique_ptr<EditInteractor> func, Data &data)
797 d->lastop = Private::CardEdit;
798 d->lastCardEditInteractor = std::move(func);
799 Data::Private *const dp = data.impl();
800 return Error(d->lasterr = gpgme_op_card_edit_start(d->ctx, key.impl(),
801 d->lastCardEditInteractor.get() ? edit_interactor_callback : nullptr,
802 d->lastCardEditInteractor.get() ? d->lastCardEditInteractor->d : nullptr,
803 dp ? dp->data : nullptr));
806 #pragma GCC diagnostic pop
808 EditInteractor *Context::lastCardEditInteractor() const
810 return d->lastCardEditInteractor.get();
813 std::unique_ptr<EditInteractor> Context::takeLastCardEditInteractor()
815 return std::move(d->lastCardEditInteractor);
818 Error Context::startTrustItemListing(const char *pattern, int maxLevel)
820 d->lastop = Private::TrustList;
821 return Error(d->lasterr = gpgme_op_trustlist_start(d->ctx, pattern, maxLevel));
824 TrustItem Context::nextTrustItem(Error &e)
826 gpgme_trust_item_t ti = nullptr;
827 e = Error(d->lasterr = gpgme_op_trustlist_next(d->ctx, &ti));
828 return TrustItem(ti);
831 Error Context::endTrustItemListing()
833 return Error(d->lasterr = gpgme_op_trustlist_end(d->ctx));
836 static gpgme_error_t assuan_transaction_data_callback(void *opaque, const void *data, size_t datalen)
839 AssuanTransaction *t = static_cast<AssuanTransaction *>(opaque);
840 return t->data(static_cast<const char *>(data), datalen).encodedError();
843 static gpgme_error_t assuan_transaction_inquire_callback(void *opaque, const char *name, const char *args, gpgme_data_t *r_data)
846 Context::Private *p = static_cast<Context::Private *>(opaque);
847 AssuanTransaction *t = p->lastAssuanTransaction.get();
851 p->lastAssuanInquireData = t->inquire(name, args, err);
853 p->lastAssuanInquireData = Data::null;
855 if (!p->lastAssuanInquireData.isNull()) {
856 *r_data = p->lastAssuanInquireData.impl()->data;
858 return err.encodedError();
861 static gpgme_error_t assuan_transaction_status_callback(void *opaque, const char *status, const char *args)
864 AssuanTransaction *t = static_cast<AssuanTransaction *>(opaque);
865 std::string a = args;
866 percent_unescape(a, true); // ### why doesn't gpgme do this??
867 return t->status(status, a.c_str()).encodedError();
870 Error Context::assuanTransact(const char *command)
872 return assuanTransact(command, std::unique_ptr<AssuanTransaction>(new DefaultAssuanTransaction));
875 Error Context::assuanTransact(const char *command, std::unique_ptr<AssuanTransaction> transaction)
877 gpgme_error_t err, operr;
879 d->lastop = Private::AssuanTransact;
880 d->lastAssuanTransaction = std::move(transaction);
881 if (!d->lastAssuanTransaction.get()) {
882 return Error(d->lasterr = make_error(GPG_ERR_INV_ARG));
884 err = gpgme_op_assuan_transact_ext
887 assuan_transaction_data_callback,
888 d->lastAssuanTransaction.get(),
889 assuan_transaction_inquire_callback,
891 assuan_transaction_status_callback,
892 d->lastAssuanTransaction.get(),
899 return Error(d->lasterr);
902 Error Context::startAssuanTransaction(const char *command)
904 return startAssuanTransaction(command, std::unique_ptr<AssuanTransaction>(new DefaultAssuanTransaction));
907 Error Context::startAssuanTransaction(const char *command, std::unique_ptr<AssuanTransaction> transaction)
911 d->lastop = Private::AssuanTransact;
912 d->lastAssuanTransaction = std::move(transaction);
913 if (!d->lastAssuanTransaction.get()) {
914 return Error(d->lasterr = make_error(GPG_ERR_INV_ARG));
916 err = gpgme_op_assuan_transact_start
919 assuan_transaction_data_callback,
920 d->lastAssuanTransaction.get(),
921 assuan_transaction_inquire_callback,
923 assuan_transaction_status_callback,
924 d->lastAssuanTransaction.get());
928 return Error(d->lasterr);
931 AssuanTransaction *Context::lastAssuanTransaction() const
933 return d->lastAssuanTransaction.get();
936 std::unique_ptr<AssuanTransaction> Context::takeLastAssuanTransaction()
938 return std::move(d->lastAssuanTransaction);
941 DecryptionResult Context::decrypt(const Data &cipherText, Data &plainText, const DecryptionFlags flags)
943 d->lastop = Private::Decrypt;
944 const Data::Private *const cdp = cipherText.impl();
945 Data::Private *const pdp = plainText.impl();
946 d->lasterr = gpgme_op_decrypt_ext(d->ctx, static_cast<gpgme_decrypt_flags_t> (d->decryptFlags | flags), cdp ? cdp->data : nullptr, pdp ? pdp->data : nullptr);
947 return DecryptionResult(d->ctx, Error(d->lasterr));
950 DecryptionResult Context::decrypt(const Data &cipherText, Data &plainText)
952 return decrypt(cipherText, plainText, DecryptNone);
955 Error Context::startDecryption(const Data &cipherText, Data &plainText, const DecryptionFlags flags)
957 d->lastop = Private::Decrypt;
958 const Data::Private *const cdp = cipherText.impl();
959 Data::Private *const pdp = plainText.impl();
960 return Error(d->lasterr = gpgme_op_decrypt_ext_start(d->ctx, static_cast<gpgme_decrypt_flags_t> (d->decryptFlags | flags),
961 cdp ? cdp->data : nullptr, pdp ? pdp->data : nullptr));
964 Error Context::startDecryption(const Data &cipherText, Data &plainText)
966 return startDecryption(cipherText, plainText, DecryptNone);
969 DecryptionResult Context::decryptionResult() const
971 if (d->lastop & Private::Decrypt) {
972 return DecryptionResult(d->ctx, Error(d->lasterr));
974 return DecryptionResult();
978 VerificationResult Context::verifyDetachedSignature(const Data &signature, const Data &signedText)
980 d->lastop = Private::Verify;
981 const Data::Private *const sdp = signature.impl();
982 const Data::Private *const tdp = signedText.impl();
983 d->lasterr = gpgme_op_verify(d->ctx, sdp ? sdp->data : nullptr, tdp ? tdp->data : nullptr, nullptr);
984 return VerificationResult(d->ctx, Error(d->lasterr));
987 VerificationResult Context::verifyOpaqueSignature(const Data &signedData, Data &plainText)
989 d->lastop = Private::Verify;
990 const Data::Private *const sdp = signedData.impl();
991 Data::Private *const pdp = plainText.impl();
992 d->lasterr = gpgme_op_verify(d->ctx, sdp ? sdp->data : nullptr, nullptr, pdp ? pdp->data : nullptr);
993 return VerificationResult(d->ctx, Error(d->lasterr));
996 Error Context::startDetachedSignatureVerification(const Data &signature, const Data &signedText)
998 d->lastop = Private::Verify;
999 const Data::Private *const sdp = signature.impl();
1000 const Data::Private *const tdp = signedText.impl();
1001 return Error(d->lasterr = gpgme_op_verify_start(d->ctx, sdp ? sdp->data : nullptr, tdp ? tdp->data : nullptr, nullptr));
1004 Error Context::startOpaqueSignatureVerification(const Data &signedData, Data &plainText)
1006 d->lastop = Private::Verify;
1007 const Data::Private *const sdp = signedData.impl();
1008 Data::Private *const pdp = plainText.impl();
1009 return Error(d->lasterr = gpgme_op_verify_start(d->ctx, sdp ? sdp->data : nullptr, nullptr, pdp ? pdp->data : nullptr));
1012 VerificationResult Context::verificationResult() const
1014 if (d->lastop & Private::Verify) {
1015 return VerificationResult(d->ctx, Error(d->lasterr));
1017 return VerificationResult();
1021 std::pair<DecryptionResult, VerificationResult> Context::decryptAndVerify(const Data &cipherText, Data &plainText, DecryptionFlags flags)
1023 d->lastop = Private::DecryptAndVerify;
1024 const Data::Private *const cdp = cipherText.impl();
1025 Data::Private *const pdp = plainText.impl();
1026 d->lasterr = gpgme_op_decrypt_ext(d->ctx, static_cast<gpgme_decrypt_flags_t> (d->decryptFlags | flags | DecryptVerify),
1027 cdp ? cdp->data : nullptr, pdp ? pdp->data : nullptr);
1028 return std::make_pair(DecryptionResult(d->ctx, Error(d->lasterr)),
1029 VerificationResult(d->ctx, Error(d->lasterr)));
1032 std::pair<DecryptionResult, VerificationResult> Context::decryptAndVerify(const Data &cipherText, Data &plainText)
1034 return decryptAndVerify(cipherText, plainText, DecryptNone);
1037 Error Context::startCombinedDecryptionAndVerification(const Data &cipherText, Data &plainText, DecryptionFlags flags)
1039 d->lastop = Private::DecryptAndVerify;
1040 const Data::Private *const cdp = cipherText.impl();
1041 Data::Private *const pdp = plainText.impl();
1042 return Error(d->lasterr = gpgme_op_decrypt_ext_start(d->ctx, static_cast<gpgme_decrypt_flags_t> (d->decryptFlags | flags | DecryptVerify), cdp ? cdp->data : nullptr, pdp ? pdp->data : nullptr));
1045 Error Context::startCombinedDecryptionAndVerification(const Data &cipherText, Data &plainText)
1047 return startCombinedDecryptionAndVerification(cipherText, plainText, DecryptNone);
1050 unsigned int to_auditlog_flags(unsigned int flags)
1052 unsigned int result = 0;
1053 if (flags & Context::HtmlAuditLog) {
1054 result |= GPGME_AUDITLOG_HTML;
1056 if (flags & Context::AuditLogWithHelp) {
1057 result |= GPGME_AUDITLOG_WITH_HELP;
1059 if (flags & Context::DiagnosticAuditLog) {
1060 result |= GPGME_AUDITLOG_DIAG;
1065 Error Context::startGetAuditLog(Data &output, unsigned int flags)
1067 d->lastop = Private::GetAuditLog;
1068 Data::Private *const odp = output.impl();
1069 return Error(d->lasterr = gpgme_op_getauditlog_start(d->ctx, odp ? odp->data : nullptr, to_auditlog_flags(flags)));
1072 Error Context::getAuditLog(Data &output, unsigned int flags)
1074 d->lastop = Private::GetAuditLog;
1075 Data::Private *const odp = output.impl();
1076 return Error(d->lasterr = gpgme_op_getauditlog(d->ctx, odp ? odp->data : nullptr, to_auditlog_flags(flags)));
1079 void Context::clearSigningKeys()
1081 gpgme_signers_clear(d->ctx);
1084 Error Context::addSigningKey(const Key &key)
1086 return Error(d->lasterr = gpgme_signers_add(d->ctx, key.impl()));
1089 Key Context::signingKey(unsigned int idx) const
1091 gpgme_key_t key = gpgme_signers_enum(d->ctx, idx);
1092 return Key(key, false);
1095 std::vector<Key> Context::signingKeys() const
1097 std::vector<Key> result;
1098 gpgme_key_t key = nullptr;
1099 for (unsigned int i = 0 ; (key = gpgme_signers_enum(d->ctx, i)) ; ++i) {
1100 result.push_back(Key(key, false));
1105 void Context::clearSignatureNotations()
1107 gpgme_sig_notation_clear(d->ctx);
1110 GpgME::Error Context::addSignatureNotation(const char *name, const char *value, unsigned int flags)
1112 return Error(gpgme_sig_notation_add(d->ctx, name, value, add_to_gpgme_sig_notation_flags_t(0, flags)));
1115 GpgME::Error Context::addSignaturePolicyURL(const char *url, bool critical)
1117 return Error(gpgme_sig_notation_add(d->ctx, nullptr, url, critical ? GPGME_SIG_NOTATION_CRITICAL : 0));
1120 const char *Context::signaturePolicyURL() const
1122 for (gpgme_sig_notation_t n = gpgme_sig_notation_get(d->ctx) ; n ; n = n->next) {
1130 Notation Context::signatureNotation(unsigned int idx) const
1132 for (gpgme_sig_notation_t n = gpgme_sig_notation_get(d->ctx) ; n ; n = n->next) {
1142 std::vector<Notation> Context::signatureNotations() const
1144 std::vector<Notation> result;
1145 for (gpgme_sig_notation_t n = gpgme_sig_notation_get(d->ctx) ; n ; n = n->next) {
1147 result.push_back(Notation(n));
1153 static gpgme_sig_mode_t sigmode2sigmode(SignatureMode mode)
1157 case NormalSignatureMode: return GPGME_SIG_MODE_NORMAL;
1158 case Detached: return GPGME_SIG_MODE_DETACH;
1159 case Clearsigned: return GPGME_SIG_MODE_CLEAR;
1163 SigningResult Context::sign(const Data &plainText, Data &signature, SignatureMode mode)
1165 d->lastop = Private::Sign;
1166 const Data::Private *const pdp = plainText.impl();
1167 Data::Private *const sdp = signature.impl();
1168 d->lasterr = gpgme_op_sign(d->ctx, pdp ? pdp->data : nullptr, sdp ? sdp->data : nullptr, sigmode2sigmode(mode));
1169 return SigningResult(d->ctx, Error(d->lasterr));
1172 Error Context::startSigning(const Data &plainText, Data &signature, SignatureMode mode)
1174 d->lastop = Private::Sign;
1175 const Data::Private *const pdp = plainText.impl();
1176 Data::Private *const sdp = signature.impl();
1177 return Error(d->lasterr = gpgme_op_sign_start(d->ctx, pdp ? pdp->data : nullptr, sdp ? sdp->data : nullptr, sigmode2sigmode(mode)));
1180 SigningResult Context::signingResult() const
1182 if (d->lastop & Private::Sign) {
1183 return SigningResult(d->ctx, Error(d->lasterr));
1185 return SigningResult();
1189 static gpgme_encrypt_flags_t encryptflags2encryptflags(Context::EncryptionFlags flags)
1191 unsigned int result = 0;
1192 if (flags & Context::AlwaysTrust) {
1193 result |= GPGME_ENCRYPT_ALWAYS_TRUST;
1195 if (flags & Context::NoEncryptTo) {
1196 result |= GPGME_ENCRYPT_NO_ENCRYPT_TO;
1198 if (flags & Context::Prepare) {
1199 result |= GPGME_ENCRYPT_PREPARE;
1201 if (flags & Context::ExpectSign) {
1202 result |= GPGME_ENCRYPT_EXPECT_SIGN;
1204 if (flags & Context::NoCompress) {
1205 result |= GPGME_ENCRYPT_NO_COMPRESS;
1207 if (flags & Context::Symmetric) {
1208 result |= GPGME_ENCRYPT_SYMMETRIC;
1210 return static_cast<gpgme_encrypt_flags_t>(result);
1213 gpgme_key_t *Context::getKeysFromRecipients(const std::vector<Key> &recipients)
1215 if (recipients.empty()) {
1218 gpgme_key_t *ret = new gpgme_key_t[ recipients.size() + 1 ];
1219 gpgme_key_t *keys_it = ret;
1220 for (std::vector<Key>::const_iterator it = recipients.begin() ; it != recipients.end() ; ++it) {
1222 *keys_it++ = it->impl();
1225 *keys_it++ = nullptr;
1229 EncryptionResult Context::encrypt(const std::vector<Key> &recipients, const Data &plainText, Data &cipherText, EncryptionFlags flags)
1231 d->lastop = Private::Encrypt;
1232 if (flags & NoEncryptTo) {
1233 return EncryptionResult(Error(d->lasterr = make_error(GPG_ERR_NOT_IMPLEMENTED)));
1235 const Data::Private *const pdp = plainText.impl();
1236 Data::Private *const cdp = cipherText.impl();
1237 gpgme_key_t *const keys = getKeysFromRecipients(recipients);
1238 d->lasterr = gpgme_op_encrypt(d->ctx, keys, encryptflags2encryptflags(flags),
1239 pdp ? pdp->data : nullptr, cdp ? cdp->data : nullptr);
1243 return EncryptionResult(d->ctx, Error(d->lasterr));
1246 Error Context::encryptSymmetrically(const Data &plainText, Data &cipherText)
1248 d->lastop = Private::Encrypt;
1249 const Data::Private *const pdp = plainText.impl();
1250 Data::Private *const cdp = cipherText.impl();
1251 return Error(d->lasterr = gpgme_op_encrypt(d->ctx, nullptr, (gpgme_encrypt_flags_t)0,
1252 pdp ? pdp->data : nullptr, cdp ? cdp->data : nullptr));
1255 Error Context::startEncryption(const std::vector<Key> &recipients, const Data &plainText, Data &cipherText, EncryptionFlags flags)
1257 d->lastop = Private::Encrypt;
1258 if (flags & NoEncryptTo) {
1259 return Error(d->lasterr = make_error(GPG_ERR_NOT_IMPLEMENTED));
1261 const Data::Private *const pdp = plainText.impl();
1262 Data::Private *const cdp = cipherText.impl();
1263 gpgme_key_t *const keys = getKeysFromRecipients(recipients);
1264 d->lasterr = gpgme_op_encrypt_start(d->ctx, keys, encryptflags2encryptflags(flags),
1265 pdp ? pdp->data : nullptr, cdp ? cdp->data : nullptr);
1269 return Error(d->lasterr);
1272 EncryptionResult Context::encryptionResult() const
1274 if (d->lastop & Private::Encrypt) {
1275 return EncryptionResult(d->ctx, Error(d->lasterr));
1277 return EncryptionResult();
1281 std::pair<SigningResult, EncryptionResult> Context::signAndEncrypt(const std::vector<Key> &recipients, const Data &plainText, Data &cipherText, EncryptionFlags flags)
1283 d->lastop = Private::SignAndEncrypt;
1284 const Data::Private *const pdp = plainText.impl();
1285 Data::Private *const cdp = cipherText.impl();
1286 gpgme_key_t *const keys = getKeysFromRecipients(recipients);
1287 d->lasterr = gpgme_op_encrypt_sign(d->ctx, keys, encryptflags2encryptflags(flags),
1288 pdp ? pdp->data : nullptr, cdp ? cdp->data : nullptr);
1292 return std::make_pair(SigningResult(d->ctx, Error(d->lasterr)),
1293 EncryptionResult(d->ctx, Error(d->lasterr)));
1296 Error Context::startCombinedSigningAndEncryption(const std::vector<Key> &recipients, const Data &plainText, Data &cipherText, EncryptionFlags flags)
1298 d->lastop = Private::SignAndEncrypt;
1299 const Data::Private *const pdp = plainText.impl();
1300 Data::Private *const cdp = cipherText.impl();
1301 gpgme_key_t *const keys = getKeysFromRecipients(recipients);
1302 d->lasterr = gpgme_op_encrypt_sign_start(d->ctx, keys, encryptflags2encryptflags(flags),
1303 pdp ? pdp->data : nullptr, cdp ? cdp->data : nullptr);
1307 return Error(d->lasterr);
1310 Error Context::createVFS(const char *containerFile, const std::vector< Key > &recipients)
1312 d->lastop = Private::CreateVFS;
1313 gpgme_key_t *const keys = new gpgme_key_t[ recipients.size() + 1 ];
1314 gpgme_key_t *keys_it = keys;
1315 for (std::vector<Key>::const_iterator it = recipients.begin() ; it != recipients.end() ; ++it) {
1317 *keys_it++ = it->impl();
1320 *keys_it++ = nullptr;
1322 gpgme_error_t op_err;
1323 d->lasterr = gpgme_op_vfs_create(d->ctx, keys, containerFile, 0, &op_err);
1325 Error error(d->lasterr);
1329 return Error(d->lasterr = op_err);
1332 VfsMountResult Context::mountVFS(const char *containerFile, const char *mountDir)
1334 d->lastop = Private::MountVFS;
1335 gpgme_error_t op_err;
1336 d->lasterr = gpgme_op_vfs_mount(d->ctx, containerFile, mountDir, 0, &op_err);
1337 return VfsMountResult(d->ctx, Error(d->lasterr), Error(op_err));
1340 Error Context::cancelPendingOperation()
1342 return Error(gpgme_cancel_async(d->ctx));
1345 bool Context::poll()
1347 gpgme_error_t e = GPG_ERR_NO_ERROR;
1348 const bool finished = gpgme_wait(d->ctx, &e, 0);
1355 Error Context::wait()
1357 gpgme_error_t e = GPG_ERR_NO_ERROR;
1358 gpgme_wait(d->ctx, &e, 1);
1359 return Error(d->lasterr = e);
1362 Error Context::lastError() const
1364 return Error(d->lasterr);
1367 Context::PinentryMode Context::pinentryMode() const
1369 switch (gpgme_get_pinentry_mode (d->ctx)) {
1370 case GPGME_PINENTRY_MODE_ASK:
1372 case GPGME_PINENTRY_MODE_CANCEL:
1373 return PinentryCancel;
1374 case GPGME_PINENTRY_MODE_ERROR:
1375 return PinentryError;
1376 case GPGME_PINENTRY_MODE_LOOPBACK:
1377 return PinentryLoopback;
1378 case GPGME_PINENTRY_MODE_DEFAULT:
1380 return PinentryDefault;
1384 Error Context::setPinentryMode(PinentryMode which)
1386 gpgme_pinentry_mode_t mode;
1389 mode = GPGME_PINENTRY_MODE_ASK;
1391 case PinentryCancel:
1392 mode = GPGME_PINENTRY_MODE_CANCEL;
1395 mode = GPGME_PINENTRY_MODE_ERROR;
1397 case PinentryLoopback:
1398 mode = GPGME_PINENTRY_MODE_LOOPBACK;
1400 case PinentryDefault:
1402 mode = GPGME_PINENTRY_MODE_DEFAULT;
1404 return Error(d->lasterr = gpgme_set_pinentry_mode(d->ctx, mode));
1407 static gpgme_tofu_policy_t to_tofu_policy_t(unsigned int policy)
1410 case TofuInfo::PolicyNone:
1411 return GPGME_TOFU_POLICY_NONE;
1412 case TofuInfo::PolicyAuto:
1413 return GPGME_TOFU_POLICY_AUTO;
1414 case TofuInfo::PolicyGood:
1415 return GPGME_TOFU_POLICY_GOOD;
1416 case TofuInfo::PolicyBad:
1417 return GPGME_TOFU_POLICY_BAD;
1418 case TofuInfo::PolicyAsk:
1419 return GPGME_TOFU_POLICY_ASK;
1420 case TofuInfo::PolicyUnknown:
1422 return GPGME_TOFU_POLICY_UNKNOWN;
1426 Error Context::setTofuPolicy(const Key &k, unsigned int policy)
1428 return Error(d->lasterr = gpgme_op_tofu_policy(d->ctx,
1429 k.impl(), to_tofu_policy_t(policy)));
1432 Error Context::setTofuPolicyStart(const Key &k, unsigned int policy)
1434 return Error(d->lasterr = gpgme_op_tofu_policy_start(d->ctx,
1435 k.impl(), to_tofu_policy_t(policy)));
1438 Error Context::startCreateKey (const char *userid,
1440 unsigned long reserved,
1441 unsigned long expires,
1445 return Error(d->lasterr = gpgme_op_createkey_start(d->ctx,
1454 Error Context::createKey (const char *userid,
1456 unsigned long reserved,
1457 unsigned long expires,
1461 return Error(d->lasterr = gpgme_op_createkey(d->ctx,
1470 KeyGenerationResult Context::createKeyEx (const char *userid,
1472 unsigned long reserved,
1473 unsigned long expires,
1477 d->lasterr = gpgme_op_createkey(d->ctx,
1484 return KeyGenerationResult(d->ctx, Error(d->lasterr));
1487 Error Context::addUid(const Key &k, const char *userid)
1489 return Error(d->lasterr = gpgme_op_adduid(d->ctx,
1490 k.impl(), userid, 0));
1493 Error Context::startAddUid(const Key &k, const char *userid)
1495 return Error(d->lasterr = gpgme_op_adduid_start(d->ctx,
1496 k.impl(), userid, 0));
1499 Error Context::revUid(const Key &k, const char *userid)
1501 return Error(d->lasterr = gpgme_op_revuid(d->ctx,
1502 k.impl(), userid, 0));
1505 Error Context::startRevUid(const Key &k, const char *userid)
1507 return Error(d->lasterr = gpgme_op_revuid_start(d->ctx,
1508 k.impl(), userid, 0));
1511 Error Context::createSubkey(const Key &k, const char *algo,
1512 unsigned long reserved,
1513 unsigned long expires,
1516 return Error(d->lasterr = gpgme_op_createsubkey(d->ctx,
1517 k.impl(), algo, reserved, expires, flags));
1520 Error Context::startCreateSubkey(const Key &k, const char *algo,
1521 unsigned long reserved,
1522 unsigned long expires,
1525 return Error(d->lasterr = gpgme_op_createsubkey_start(d->ctx,
1526 k.impl(), algo, reserved, expires, flags));
1529 Error Context::setFlag(const char *name, const char *value)
1531 return Error(d->lasterr = gpgme_set_ctx_flag(d->ctx, name, value));
1534 const char *Context::getFlag(const char *name) const
1536 return gpgme_get_ctx_flag(d->ctx, name);
1539 // Engine Spawn stuff
1540 Error Context::spawn(const char *file, const char *argv[],
1541 Data &input, Data &output, Data &err,
1544 return Error(d->lasterr = gpgme_op_spawn (d->ctx, file, argv,
1545 input.impl() ? input.impl()->data : nullptr,
1546 output.impl() ? output.impl()->data : nullptr,
1547 err.impl() ? err.impl()->data : nullptr,
1548 static_cast<int>(flags)));
1551 Error Context::spawnAsync(const char *file, const char *argv[],
1552 Data &input, Data &output, Data &err,
1555 return Error(d->lasterr = gpgme_op_spawn_start (d->ctx, file, argv,
1556 input.impl() ? input.impl()->data : nullptr,
1557 output.impl() ? output.impl()->data : nullptr,
1558 err.impl() ? err.impl()->data : nullptr,
1559 static_cast<int>(flags)));
1562 std::ostream &operator<<(std::ostream &os, Protocol proto)
1564 os << "GpgME::Protocol(";
1573 case UnknownProtocol:
1574 os << "UnknownProtocol";
1580 std::ostream &operator<<(std::ostream &os, Engine eng)
1582 os << "GpgME::Engine(";
1588 os << "GpgSMEngine";
1591 os << "GpgConfEngine";
1594 os << "AssuanEngine";
1597 os << "SpawnEngine";
1601 os << "UnknownEngine";
1607 std::ostream &operator<<(std::ostream &os, Context::CertificateInclusion incl)
1609 os << "GpgME::Context::CertificateInclusion(" << static_cast<int>(incl);
1611 case Context::DefaultCertificates:
1612 os << "(DefaultCertificates)";
1614 case Context::AllCertificatesExceptRoot:
1615 os << "(AllCertificatesExceptRoot)";
1617 case Context::AllCertificates:
1618 os << "(AllCertificates)";
1620 case Context::NoCertificates:
1621 os << "(NoCertificates)";
1623 case Context::OnlySenderCertificate:
1624 os << "(OnlySenderCertificate)";
1630 std::ostream &operator<<(std::ostream &os, KeyListMode mode)
1632 os << "GpgME::KeyListMode(";
1633 #define CHECK( x ) if ( !(mode & (x)) ) {} else do { os << #x " "; } while (0)
1645 std::ostream &operator<<(std::ostream &os, SignatureMode mode)
1647 os << "GpgME::SignatureMode(";
1649 #define CHECK( x ) case x: os << #x; break
1650 CHECK(NormalSignatureMode);
1655 os << "???" "(" << static_cast<int>(mode) << ')';
1661 std::ostream &operator<<(std::ostream &os, Context::EncryptionFlags flags)
1663 os << "GpgME::Context::EncryptionFlags(";
1664 #define CHECK( x ) if ( !(flags & (Context::x)) ) {} else do { os << #x " "; } while (0)
1675 std::ostream &operator<<(std::ostream &os, Context::AuditLogFlags flags)
1677 os << "GpgME::Context::AuditLogFlags(";
1678 #define CHECK( x ) if ( !(flags & (Context::x)) ) {} else do { os << #x " "; } while (0)
1679 CHECK(HtmlAuditLog);
1680 CHECK(AuditLogWithHelp);
1685 } // namespace GpgME
1687 GpgME::Error GpgME::setDefaultLocale(int cat, const char *val)
1689 return Error(gpgme_set_locale(nullptr, cat, val));
1692 GpgME::EngineInfo GpgME::engineInfo(GpgME::Protocol proto)
1694 gpgme_engine_info_t ei = nullptr;
1695 if (gpgme_get_engine_info(&ei)) {
1696 return EngineInfo();
1699 const gpgme_protocol_t p = proto == CMS ? GPGME_PROTOCOL_CMS : GPGME_PROTOCOL_OpenPGP ;
1701 for (gpgme_engine_info_t i = ei ; i ; i = i->next) {
1702 if (i->protocol == p) {
1703 return EngineInfo(i);
1707 return EngineInfo();
1710 const char *GpgME::dirInfo(const char *what)
1712 return gpgme_get_dirinfo(what);
1715 GpgME::Error GpgME::checkEngine(GpgME::Protocol proto)
1717 const gpgme_protocol_t p = proto == CMS ? GPGME_PROTOCOL_CMS : GPGME_PROTOCOL_OpenPGP ;
1719 return Error(gpgme_engine_check_version(p));
1722 static const gpgme_protocol_t UNKNOWN_PROTOCOL = static_cast<gpgme_protocol_t>(255);
1724 static gpgme_protocol_t engine2protocol(const GpgME::Engine engine)
1727 case GpgME::GpgEngine: return GPGME_PROTOCOL_OpenPGP;
1728 case GpgME::GpgSMEngine: return GPGME_PROTOCOL_CMS;
1729 case GpgME::GpgConfEngine:
1730 return GPGME_PROTOCOL_GPGCONF;
1731 case GpgME::AssuanEngine:
1732 return GPGME_PROTOCOL_ASSUAN;
1733 case GpgME::G13Engine:
1734 return GPGME_PROTOCOL_G13;
1735 case GpgME::SpawnEngine:
1736 return GPGME_PROTOCOL_SPAWN;
1737 case GpgME::UnknownEngine:
1740 return UNKNOWN_PROTOCOL;
1743 GpgME::EngineInfo GpgME::engineInfo(GpgME::Engine engine)
1745 gpgme_engine_info_t ei = nullptr;
1746 if (gpgme_get_engine_info(&ei)) {
1747 return EngineInfo();
1750 const gpgme_protocol_t p = engine2protocol(engine);
1752 for (gpgme_engine_info_t i = ei ; i ; i = i->next) {
1753 if (i->protocol == p) {
1754 return EngineInfo(i);
1758 return EngineInfo();
1761 GpgME::Error GpgME::checkEngine(GpgME::Engine engine)
1763 const gpgme_protocol_t p = engine2protocol(engine);
1765 return Error(gpgme_engine_check_version(p));
1768 static const unsigned long supported_features = 0
1769 | GpgME::ValidatingKeylistModeFeature
1770 | GpgME::CancelOperationFeature
1771 | GpgME::WrongKeyUsageFeature
1772 | GpgME::DefaultCertificateInclusionFeature
1773 | GpgME::GetSetEngineInfoFeature
1774 | GpgME::ClearAddGetSignatureNotationsFeature
1775 | GpgME::SetDataFileNameFeeature
1776 | GpgME::SignatureNotationsKeylistModeFeature
1777 | GpgME::KeySignatureNotationsFeature
1778 | GpgME::KeyIsQualifiedFeature
1779 | GpgME::SignatureNotationsCriticalFlagFeature
1780 | GpgME::SignatureNotationsFlagsFeature
1781 | GpgME::SignatureNotationsHumanReadableFlagFeature
1782 | GpgME::SubkeyIsQualifiedFeature
1783 | GpgME::EngineInfoHomeDirFeature
1784 | GpgME::DecryptionResultFileNameFeature
1785 | GpgME::DecryptionResultRecipientsFeature
1786 | GpgME::VerificationResultFileNameFeature
1787 | GpgME::SignaturePkaFieldsFeature
1788 | GpgME::SignatureAlgorithmFieldsFeature
1789 | GpgME::FdPointerFeature
1790 | GpgME::AuditLogFeature
1791 | GpgME::GpgConfEngineFeature
1792 | GpgME::CancelOperationAsyncFeature
1793 | GpgME::NoEncryptToEncryptionFlagFeature
1794 | GpgME::CardKeyFeature
1795 | GpgME::AssuanEngineFeature
1796 | GpgME::EphemeralKeylistModeFeature
1797 | GpgME::ImportFromKeyserverFeature
1798 | GpgME::G13VFSFeature
1799 | GpgME::PasswdFeature
1802 static const unsigned long supported_features2 = 0
1803 | GpgME::BinaryAndFineGrainedIdentify
1806 bool GpgME::hasFeature(unsigned long features)
1808 return features == (features & supported_features);
1811 bool GpgME::hasFeature(unsigned long features, unsigned long features2)
1813 return features == (features & supported_features)
1814 && features2 == (features2 & supported_features2)
1818 int GpgME::setGlobalFlag(const char *name, const char *value)
1820 return gpgme_set_global_flag(name, value);