2 context.cpp - wraps a gpgme key context
3 Copyright (C) 2003, 2007 Klarälvdalens Datakonsult AB
5 This file is part of GPGME++.
7 GPGME++ is free software; you can redistribute it and/or
8 modify it under the terms of the GNU Library General Public
9 License as published by the Free Software Foundation; either
10 version 2 of the License, or (at your option) any later version.
12 GPGME++ is distributed in the hope that it will be useful,
13 but WITHOUT ANY WARRANTY; without even the implied warranty of
14 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 GNU Library General Public License for more details.
17 You should have received a copy of the GNU Library General Public License
18 along with GPGME++; see the file COPYING.LIB. If not, write to the
19 Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
20 Boston, MA 02110-1301, USA.
28 #include <eventloopinteractor.h>
29 #include <trustitem.h>
30 #include <keylistresult.h>
31 #include <keygenerationresult.h>
32 #include <importresult.h>
33 #include <decryptionresult.h>
34 #include <verificationresult.h>
35 #include <signingresult.h>
36 #include <encryptionresult.h>
37 #include <engineinfo.h>
38 #include <editinteractor.h>
39 #include <vfsmountresult.h>
41 #include <interfaces/assuantransaction.h>
42 #include <defaultassuantransaction.h>
44 #include "callbacks.h"
46 #include "context_p.h"
64 static inline unsigned int xtoi_1(const char *str)
66 const unsigned int ch = *str;
67 const unsigned int result =
68 ch <= '9' ? ch - '0' :
69 ch <= 'F' ? ch - 'A' + 10 :
70 /* else */ ch - 'a' + 10 ;
71 return result < 16 ? result : 0 ;
73 static inline int xtoi_2(const char *str)
75 return xtoi_1(str) * 16U + xtoi_1(str + 1);
78 static void percent_unescape(std::string &s, bool plus2space)
80 std::string::iterator src = s.begin(), dest = s.begin(), end = s.end();
82 if (*src == '%' && end - src > 2) {
83 *dest++ = xtoi_2(&*++src);
85 } else if (*src == '+' && plus2space) {
95 void initializeLibrary()
97 gpgme_check_version(0);
100 Error initializeLibrary(int)
102 if (gpgme_check_version(GPGME_VERSION)) {
105 return Error::fromCode(GPG_ERR_USER_1);
109 static void format_error(gpgme_error_t err, std::string &str)
112 gpgme_strerror_r(err, buffer, sizeof buffer);
113 buffer[ sizeof buffer - 1 ] = '\0';
117 const char *Error::source() const
119 return gpgme_strsource((gpgme_error_t)mErr);
122 const char *Error::asString() const
124 if (mMessage.empty()) {
125 format_error(static_cast<gpgme_error_t>(mErr), mMessage);
127 return mMessage.c_str();
130 int Error::code() const
132 return gpgme_err_code(mErr);
135 int Error::sourceID() const
137 return gpgme_err_source(mErr);
140 bool Error::isCanceled() const
142 return code() == GPG_ERR_CANCELED;
145 int Error::toErrno() const
147 //#ifdef HAVE_GPGME_GPG_ERROR_WRAPPERS
148 return gpgme_err_code_to_errno(static_cast<gpgme_err_code_t>(code()));
150 // return gpg_err_code_to_errno( static_cast<gpg_err_code_t>( code() ) );
155 bool Error::hasSystemError()
157 return gpgme_err_code_from_syserror() == GPG_ERR_MISSING_ERRNO ;
161 void Error::setSystemError(gpg_err_code_t err)
163 setErrno(gpgme_err_code_to_errno(err));
167 void Error::setErrno(int err)
169 gpgme_err_set_errno(err);
173 Error Error::fromSystemError(unsigned int src)
175 return Error(gpgme_err_make(static_cast<gpgme_err_source_t>(src), gpgme_err_code_from_syserror()));
179 Error Error::fromErrno(int err, unsigned int src)
181 return Error(gpgme_err_make(static_cast<gpgme_err_source_t>(src), gpgme_err_code_from_errno(err)));
185 Error Error::fromCode(unsigned int err, unsigned int src)
187 return Error(gpgme_err_make(static_cast<gpgme_err_source_t>(src), static_cast<gpgme_err_code_t>(err)));
190 std::ostream &operator<<(std::ostream &os, const Error &err)
192 return os << "GpgME::Error(" << err.encodedError() << " (" << err.asString() << "))";
195 Context::Context(gpgme_ctx_t ctx) : d(new Private(ctx))
204 Context *Context::createForProtocol(Protocol proto)
207 if (gpgme_new(&ctx) != 0) {
213 if (gpgme_set_protocol(ctx, GPGME_PROTOCOL_OpenPGP) != 0) {
219 if (gpgme_set_protocol(ctx, GPGME_PROTOCOL_CMS) != 0) {
228 return new Context(ctx);
231 std::unique_ptr<Context> Context::createForEngine(Engine eng, Error *error)
234 if (const gpgme_error_t err = gpgme_new(&ctx)) {
238 return std::unique_ptr<Context>();
243 if (const gpgme_error_t err = gpgme_set_protocol(ctx, GPGME_PROTOCOL_ASSUAN)) {
248 return std::unique_ptr<Context>();
252 if (const gpgme_error_t err = gpgme_set_protocol(ctx, GPGME_PROTOCOL_G13)) {
257 return std::unique_ptr<Context>();
261 if (const gpgme_error_t err = gpgme_set_protocol(ctx, GPGME_PROTOCOL_SPAWN)) {
266 return std::unique_ptr<Context>();
271 *error = Error::fromCode(GPG_ERR_INV_ARG);
273 return std::unique_ptr<Context>();
280 return std::unique_ptr<Context>(new Context(ctx));
283 void Context::setDecryptionFlags(DecryptionFlags flags)
285 d->decryptFlags = flags;
294 Context::Private::Private(gpgme_ctx_t c)
298 lasterr(GPG_ERR_NO_ERROR),
299 lastAssuanInquireData(Data::null),
300 lastAssuanTransaction(),
301 lastEditInteractor(),
302 lastCardEditInteractor(),
303 decryptFlags(DecryptNone)
308 Context::Private::~Private()
319 // Context attributes:
323 Protocol Context::protocol() const
325 gpgme_protocol_t p = gpgme_get_protocol(d->ctx);
327 case GPGME_PROTOCOL_OpenPGP: return OpenPGP;
328 case GPGME_PROTOCOL_CMS: return CMS;
329 default: return UnknownProtocol;
333 void Context::setArmor(bool useArmor)
335 gpgme_set_armor(d->ctx, int(useArmor));
337 bool Context::armor() const
339 return gpgme_get_armor(d->ctx);
342 void Context::setTextMode(bool useTextMode)
344 gpgme_set_textmode(d->ctx, int(useTextMode));
346 bool Context::textMode() const
348 return gpgme_get_textmode(d->ctx);
351 void Context::setOffline(bool useOfflineMode)
353 gpgme_set_offline(d->ctx, int(useOfflineMode));
355 bool Context::offline() const
357 return gpgme_get_offline(d->ctx);
360 void Context::setIncludeCertificates(int which)
362 if (which == DefaultCertificates) {
363 which = GPGME_INCLUDE_CERTS_DEFAULT;
365 gpgme_set_include_certs(d->ctx, which);
368 int Context::includeCertificates() const
370 return gpgme_get_include_certs(d->ctx);
373 void Context::setKeyListMode(unsigned int mode)
375 gpgme_set_keylist_mode(d->ctx, add_to_gpgme_keylist_mode_t(0, mode));
378 void Context::addKeyListMode(unsigned int mode)
380 const unsigned int cur = gpgme_get_keylist_mode(d->ctx);
381 gpgme_set_keylist_mode(d->ctx, add_to_gpgme_keylist_mode_t(cur, mode));
384 unsigned int Context::keyListMode() const
386 return convert_from_gpgme_keylist_mode_t(gpgme_get_keylist_mode(d->ctx));
389 void Context::setProgressProvider(ProgressProvider *provider)
391 gpgme_set_progress_cb(d->ctx, provider ? &progress_callback : 0, provider);
393 ProgressProvider *Context::progressProvider() const
396 gpgme_progress_cb_t pcb = &progress_callback;
397 gpgme_get_progress_cb(d->ctx, &pcb, &pp);
398 return static_cast<ProgressProvider *>(pp);
401 void Context::setPassphraseProvider(PassphraseProvider *provider)
403 gpgme_set_passphrase_cb(d->ctx, provider ? &passphrase_callback : 0, provider);
406 PassphraseProvider *Context::passphraseProvider() const
409 gpgme_passphrase_cb_t pcb = &passphrase_callback;
410 gpgme_get_passphrase_cb(d->ctx, &pcb, &pp);
411 return static_cast<PassphraseProvider *>(pp);
414 void Context::setManagedByEventLoopInteractor(bool manage)
416 if (!EventLoopInteractor::instance()) {
418 cerr << "Context::setManagedByEventLoopInteractor(): "
419 "You must create an instance of EventLoopInteractor "
420 "before using anything that needs one." << endl;
425 EventLoopInteractor::instance()->manage(this);
427 EventLoopInteractor::instance()->unmanage(this);
430 bool Context::managedByEventLoopInteractor() const
432 return d->iocbs != 0;
435 void Context::installIOCallbacks(gpgme_io_cbs *iocbs)
438 uninstallIOCallbacks();
441 gpgme_set_io_cbs(d->ctx, iocbs);
442 delete d->iocbs; d->iocbs = iocbs;
445 void Context::uninstallIOCallbacks()
447 static gpgme_io_cbs noiocbs = { 0, 0, 0, 0, 0 };
448 // io.add == 0 means disable io callbacks:
449 gpgme_set_io_cbs(d->ctx, &noiocbs);
450 delete d->iocbs; d->iocbs = 0;
453 Error Context::setLocale(int cat, const char *val)
455 return Error(d->lasterr = gpgme_set_locale(d->ctx, cat, val));
458 EngineInfo Context::engineInfo() const
460 return EngineInfo(gpgme_ctx_get_engine_info(d->ctx));
463 Error Context::setEngineFileName(const char *filename)
465 const char *const home_dir = engineInfo().homeDirectory();
466 return Error(gpgme_ctx_set_engine_info(d->ctx, gpgme_get_protocol(d->ctx), filename, home_dir));
469 Error Context::setEngineHomeDirectory(const char *home_dir)
471 const char *const filename = engineInfo().fileName();
472 return Error(gpgme_ctx_set_engine_info(d->ctx, gpgme_get_protocol(d->ctx), filename, home_dir));
475 Error Context::setSender (const char *sender)
477 return Error(gpgme_set_sender(d->ctx, sender));
480 const char *Context::getSender ()
482 return gpgme_get_sender(d->ctx);
491 Error Context::startKeyListing(const char *pattern, bool secretOnly)
493 d->lastop = Private::KeyList;
494 return Error(d->lasterr = gpgme_op_keylist_start(d->ctx, pattern, int(secretOnly)));
497 Error Context::startKeyListing(const char *patterns[], bool secretOnly)
499 d->lastop = Private::KeyList;
500 #ifndef HAVE_GPGME_EXT_KEYLIST_MODE_EXTERNAL_NONBROKEN
501 if (!patterns || !patterns[0] || !patterns[1]) {
502 // max. one pattern -> use the non-ext version
503 return startKeyListing(patterns ? patterns[0] : 0, secretOnly);
506 return Error(d->lasterr = gpgme_op_keylist_ext_start(d->ctx, patterns, int(secretOnly), 0));
509 Key Context::nextKey(GpgME::Error &e)
511 d->lastop = Private::KeyList;
513 e = Error(d->lasterr = gpgme_op_keylist_next(d->ctx, &key));
514 return Key(key, false);
517 KeyListResult Context::endKeyListing()
519 d->lasterr = gpgme_op_keylist_end(d->ctx);
520 return keyListResult();
523 KeyListResult Context::keyListResult() const
525 return KeyListResult(d->ctx, Error(d->lasterr));
528 Key Context::key(const char *fingerprint, GpgME::Error &e , bool secret /*, bool forceUpdate*/)
530 d->lastop = Private::KeyList;
532 e = Error(d->lasterr = gpgme_get_key(d->ctx, fingerprint, &key, int(secret)/*, int( forceUpdate )*/));
533 return Key(key, false);
536 KeyGenerationResult Context::generateKey(const char *parameters, Data &pubKey)
538 d->lastop = Private::KeyGen;
539 Data::Private *const dp = pubKey.impl();
540 d->lasterr = gpgme_op_genkey(d->ctx, parameters, dp ? dp->data : 0, 0);
541 return KeyGenerationResult(d->ctx, Error(d->lasterr));
544 Error Context::startKeyGeneration(const char *parameters, Data &pubKey)
546 d->lastop = Private::KeyGen;
547 Data::Private *const dp = pubKey.impl();
548 return Error(d->lasterr = gpgme_op_genkey_start(d->ctx, parameters, dp ? dp->data : 0, 0));
551 KeyGenerationResult Context::keyGenerationResult() const
553 if (d->lastop & Private::KeyGen) {
554 return KeyGenerationResult(d->ctx, Error(d->lasterr));
556 return KeyGenerationResult();
560 Error Context::exportPublicKeys(const char *pattern, Data &keyData)
562 d->lastop = Private::Export;
563 Data::Private *const dp = keyData.impl();
564 return Error(d->lasterr = gpgme_op_export(d->ctx, pattern, 0, dp ? dp->data : 0));
567 Error Context::exportPublicKeys(const char *patterns[], Data &keyData)
569 d->lastop = Private::Export;
570 #ifndef HAVE_GPGME_EXT_KEYLIST_MODE_EXTERNAL_NONBROKEN
571 if (!patterns || !patterns[0] || !patterns[1]) {
572 // max. one pattern -> use the non-ext version
573 return exportPublicKeys(patterns ? patterns[0] : 0, keyData);
576 Data::Private *const dp = keyData.impl();
577 return Error(d->lasterr = gpgme_op_export_ext(d->ctx, patterns, 0, dp ? dp->data : 0));
580 Error Context::startPublicKeyExport(const char *pattern, Data &keyData)
582 d->lastop = Private::Export;
583 Data::Private *const dp = keyData.impl();
584 return Error(d->lasterr = gpgme_op_export_start(d->ctx, pattern, 0, dp ? dp->data : 0));
587 Error Context::startPublicKeyExport(const char *patterns[], Data &keyData)
589 d->lastop = Private::Export;
590 #ifndef HAVE_GPGME_EXT_KEYLIST_MODE_EXTERNAL_NONBROKEN
591 if (!patterns || !patterns[0] || !patterns[1]) {
592 // max. one pattern -> use the non-ext version
593 return startPublicKeyExport(patterns ? patterns[0] : 0, keyData);
596 Data::Private *const dp = keyData.impl();
597 return Error(d->lasterr = gpgme_op_export_ext_start(d->ctx, patterns, 0, dp ? dp->data : 0));
600 ImportResult Context::importKeys(const Data &data)
602 d->lastop = Private::Import;
603 const Data::Private *const dp = data.impl();
604 d->lasterr = gpgme_op_import(d->ctx, dp ? dp->data : 0);
605 return ImportResult(d->ctx, Error(d->lasterr));
608 ImportResult Context::importKeys(const std::vector<Key> &kk)
610 d->lastop = Private::Import;
611 d->lasterr = make_error(GPG_ERR_NOT_IMPLEMENTED);
613 bool shouldHaveResult = false;
614 gpgme_key_t * const keys = new gpgme_key_t[ kk.size() + 1 ];
615 gpgme_key_t *keys_it = &keys[0];
616 for (std::vector<Key>::const_iterator it = kk.begin(), end = kk.end() ; it != end ; ++it) {
618 *keys_it++ = it->impl();
622 d->lasterr = gpgme_op_import_keys(d->ctx, keys);
623 shouldHaveResult = true;
624 if ((gpgme_err_code(d->lasterr) == GPG_ERR_NOT_IMPLEMENTED ||
625 gpgme_err_code(d->lasterr) == GPG_ERR_NOT_SUPPORTED) &&
627 // ok, try the workaround (export+import):
628 std::vector<const char *> fprs;
629 for (std::vector<Key>::const_iterator it = kk.begin(), end = kk.end() ; it != end ; ++it) {
630 if (const char *fpr = it->primaryFingerprint()) {
634 } else if (const char *keyid = it->keyID()) {
636 fprs.push_back(keyid);
642 Data::Private *const dp = data.impl();
643 const gpgme_keylist_mode_t oldMode = gpgme_get_keylist_mode(d->ctx);
644 gpgme_set_keylist_mode(d->ctx, GPGME_KEYLIST_MODE_EXTERN);
645 d->lasterr = gpgme_op_export_ext(d->ctx, &fprs[0], 0, dp ? dp->data : 0);
646 gpgme_set_keylist_mode(d->ctx, oldMode);
648 data.seek(0, SEEK_SET);
649 d->lasterr = gpgme_op_import(d->ctx, dp ? dp->data : 0);
650 shouldHaveResult = true;
654 if (shouldHaveResult) {
655 return ImportResult(d->ctx, Error(d->lasterr));
657 return ImportResult(Error(d->lasterr));
661 Error Context::startKeyImport(const Data &data)
663 d->lastop = Private::Import;
664 const Data::Private *const dp = data.impl();
665 return Error(d->lasterr = gpgme_op_import_start(d->ctx, dp ? dp->data : 0));
668 Error Context::startKeyImport(const std::vector<Key> &kk)
670 d->lastop = Private::Import;
671 gpgme_key_t * const keys = new gpgme_key_t[ kk.size() + 1 ];
672 gpgme_key_t *keys_it = &keys[0];
673 for (std::vector<Key>::const_iterator it = kk.begin(), end = kk.end() ; it != end ; ++it) {
675 *keys_it++ = it->impl();
679 Error err = Error(d->lasterr = gpgme_op_import_keys_start(d->ctx, keys));
684 ImportResult Context::importResult() const
686 if (d->lastop & Private::Import) {
687 return ImportResult(d->ctx, Error(d->lasterr));
689 return ImportResult();
693 Error Context::deleteKey(const Key &key, bool allowSecretKeyDeletion)
695 d->lastop = Private::Delete;
696 return Error(d->lasterr = gpgme_op_delete(d->ctx, key.impl(), int(allowSecretKeyDeletion)));
699 Error Context::startKeyDeletion(const Key &key, bool allowSecretKeyDeletion)
701 d->lastop = Private::Delete;
702 return Error(d->lasterr = gpgme_op_delete_start(d->ctx, key.impl(), int(allowSecretKeyDeletion)));
705 Error Context::passwd(const Key &key)
707 d->lastop = Private::Passwd;
708 return Error(d->lasterr = gpgme_op_passwd(d->ctx, key.impl(), 0U));
711 Error Context::startPasswd(const Key &key)
713 d->lastop = Private::Passwd;
714 return Error(d->lasterr = gpgme_op_passwd_start(d->ctx, key.impl(), 0U));
718 #pragma GCC diagnostic push
719 #pragma GCC diagnostic ignored "-Wdeprecated-declarations"
721 Error Context::edit(const Key &key, std::unique_ptr<EditInteractor> func, Data &data)
723 d->lastop = Private::Edit;
724 d->lastEditInteractor = std::move(func);
725 Data::Private *const dp = data.impl();
726 return Error(d->lasterr = gpgme_op_edit(d->ctx, key.impl(),
727 d->lastEditInteractor.get() ? edit_interactor_callback : 0,
728 d->lastEditInteractor.get() ? d->lastEditInteractor->d : 0,
733 Error Context::startEditing(const Key &key, std::unique_ptr<EditInteractor> func, Data &data)
735 d->lastop = Private::Edit;
736 d->lastEditInteractor = std::move(func);
737 Data::Private *const dp = data.impl();
738 return Error(d->lasterr = gpgme_op_edit_start(d->ctx, key.impl(),
739 d->lastEditInteractor.get() ? edit_interactor_callback : 0,
740 d->lastEditInteractor.get() ? d->lastEditInteractor->d : 0,
745 EditInteractor *Context::lastEditInteractor() const
747 return d->lastEditInteractor.get();
750 std::unique_ptr<EditInteractor> Context::takeLastEditInteractor()
752 return std::move(d->lastEditInteractor);
756 Error Context::cardEdit(const Key &key, std::unique_ptr<EditInteractor> func, Data &data)
758 d->lastop = Private::CardEdit;
759 d->lastCardEditInteractor = std::move(func);
760 Data::Private *const dp = data.impl();
761 return Error(d->lasterr = gpgme_op_card_edit(d->ctx, key.impl(),
762 d->lastCardEditInteractor.get() ? edit_interactor_callback : 0,
763 d->lastCardEditInteractor.get() ? d->lastCardEditInteractor->d : 0,
767 Error Context::startCardEditing(const Key &key, std::unique_ptr<EditInteractor> func, Data &data)
769 d->lastop = Private::CardEdit;
770 d->lastCardEditInteractor = std::move(func);
771 Data::Private *const dp = data.impl();
772 return Error(d->lasterr = gpgme_op_card_edit_start(d->ctx, key.impl(),
773 d->lastCardEditInteractor.get() ? edit_interactor_callback : 0,
774 d->lastCardEditInteractor.get() ? d->lastCardEditInteractor->d : 0,
778 #pragma GCC diagnostic pop
780 EditInteractor *Context::lastCardEditInteractor() const
782 return d->lastCardEditInteractor.get();
785 std::unique_ptr<EditInteractor> Context::takeLastCardEditInteractor()
787 return std::move(d->lastCardEditInteractor);
790 Error Context::startTrustItemListing(const char *pattern, int maxLevel)
792 d->lastop = Private::TrustList;
793 return Error(d->lasterr = gpgme_op_trustlist_start(d->ctx, pattern, maxLevel));
796 TrustItem Context::nextTrustItem(Error &e)
798 gpgme_trust_item_t ti = 0;
799 e = Error(d->lasterr = gpgme_op_trustlist_next(d->ctx, &ti));
800 return TrustItem(ti);
803 Error Context::endTrustItemListing()
805 return Error(d->lasterr = gpgme_op_trustlist_end(d->ctx));
808 static gpgme_error_t assuan_transaction_data_callback(void *opaque, const void *data, size_t datalen)
811 AssuanTransaction *t = static_cast<AssuanTransaction *>(opaque);
812 return t->data(static_cast<const char *>(data), datalen).encodedError();
815 static gpgme_error_t assuan_transaction_inquire_callback(void *opaque, const char *name, const char *args, gpgme_data_t *r_data)
818 Context::Private *p = static_cast<Context::Private *>(opaque);
819 AssuanTransaction *t = p->lastAssuanTransaction.get();
823 p->lastAssuanInquireData = t->inquire(name, args, err);
825 p->lastAssuanInquireData = Data::null;
827 if (!p->lastAssuanInquireData.isNull()) {
828 *r_data = p->lastAssuanInquireData.impl()->data;
830 return err.encodedError();
833 static gpgme_error_t assuan_transaction_status_callback(void *opaque, const char *status, const char *args)
836 AssuanTransaction *t = static_cast<AssuanTransaction *>(opaque);
837 std::string a = args;
838 percent_unescape(a, true); // ### why doesn't gpgme do this??
839 return t->status(status, a.c_str()).encodedError();
842 Error Context::assuanTransact(const char *command)
844 return assuanTransact(command, std::unique_ptr<AssuanTransaction>(new DefaultAssuanTransaction));
847 Error Context::assuanTransact(const char *command, std::unique_ptr<AssuanTransaction> transaction)
849 gpgme_error_t err, operr;
851 d->lastop = Private::AssuanTransact;
852 d->lastAssuanTransaction = std::move(transaction);
853 if (!d->lastAssuanTransaction.get()) {
854 return Error(d->lasterr = make_error(GPG_ERR_INV_ARG));
856 err = gpgme_op_assuan_transact_ext
859 assuan_transaction_data_callback,
860 d->lastAssuanTransaction.get(),
861 assuan_transaction_inquire_callback,
863 assuan_transaction_status_callback,
864 d->lastAssuanTransaction.get(),
871 return Error(d->lasterr);
874 Error Context::startAssuanTransaction(const char *command)
876 return startAssuanTransaction(command, std::unique_ptr<AssuanTransaction>(new DefaultAssuanTransaction));
879 Error Context::startAssuanTransaction(const char *command, std::unique_ptr<AssuanTransaction> transaction)
883 d->lastop = Private::AssuanTransact;
884 d->lastAssuanTransaction = std::move(transaction);
885 if (!d->lastAssuanTransaction.get()) {
886 return Error(d->lasterr = make_error(GPG_ERR_INV_ARG));
888 err = gpgme_op_assuan_transact_start
891 assuan_transaction_data_callback,
892 d->lastAssuanTransaction.get(),
893 assuan_transaction_inquire_callback,
895 assuan_transaction_status_callback,
896 d->lastAssuanTransaction.get());
900 return Error(d->lasterr);
903 AssuanTransaction *Context::lastAssuanTransaction() const
905 return d->lastAssuanTransaction.get();
908 std::unique_ptr<AssuanTransaction> Context::takeLastAssuanTransaction()
910 return std::move(d->lastAssuanTransaction);
913 DecryptionResult Context::decrypt(const Data &cipherText, Data &plainText, const DecryptionFlags flags)
915 d->lastop = Private::Decrypt;
916 const Data::Private *const cdp = cipherText.impl();
917 Data::Private *const pdp = plainText.impl();
918 d->lasterr = gpgme_op_decrypt_ext(d->ctx, static_cast<gpgme_decrypt_flags_t> (d->decryptFlags | flags), cdp ? cdp->data : 0, pdp ? pdp->data : 0);
919 return DecryptionResult(d->ctx, Error(d->lasterr));
922 DecryptionResult Context::decrypt(const Data &cipherText, Data &plainText)
924 return decrypt(cipherText, plainText, DecryptNone);
927 Error Context::startDecryption(const Data &cipherText, Data &plainText, const DecryptionFlags flags)
929 d->lastop = Private::Decrypt;
930 const Data::Private *const cdp = cipherText.impl();
931 Data::Private *const pdp = plainText.impl();
932 return Error(d->lasterr = gpgme_op_decrypt_ext_start(d->ctx, static_cast<gpgme_decrypt_flags_t> (d->decryptFlags | flags),
933 cdp ? cdp->data : 0, pdp ? pdp->data : 0));
936 Error Context::startDecryption(const Data &cipherText, Data &plainText)
938 return startDecryption(cipherText, plainText, DecryptNone);
941 DecryptionResult Context::decryptionResult() const
943 if (d->lastop & Private::Decrypt) {
944 return DecryptionResult(d->ctx, Error(d->lasterr));
946 return DecryptionResult();
950 VerificationResult Context::verifyDetachedSignature(const Data &signature, const Data &signedText)
952 d->lastop = Private::Verify;
953 const Data::Private *const sdp = signature.impl();
954 const Data::Private *const tdp = signedText.impl();
955 d->lasterr = gpgme_op_verify(d->ctx, sdp ? sdp->data : 0, tdp ? tdp->data : 0, 0);
956 return VerificationResult(d->ctx, Error(d->lasterr));
959 VerificationResult Context::verifyOpaqueSignature(const Data &signedData, Data &plainText)
961 d->lastop = Private::Verify;
962 const Data::Private *const sdp = signedData.impl();
963 Data::Private *const pdp = plainText.impl();
964 d->lasterr = gpgme_op_verify(d->ctx, sdp ? sdp->data : 0, 0, pdp ? pdp->data : 0);
965 return VerificationResult(d->ctx, Error(d->lasterr));
968 Error Context::startDetachedSignatureVerification(const Data &signature, const Data &signedText)
970 d->lastop = Private::Verify;
971 const Data::Private *const sdp = signature.impl();
972 const Data::Private *const tdp = signedText.impl();
973 return Error(d->lasterr = gpgme_op_verify_start(d->ctx, sdp ? sdp->data : 0, tdp ? tdp->data : 0, 0));
976 Error Context::startOpaqueSignatureVerification(const Data &signedData, Data &plainText)
978 d->lastop = Private::Verify;
979 const Data::Private *const sdp = signedData.impl();
980 Data::Private *const pdp = plainText.impl();
981 return Error(d->lasterr = gpgme_op_verify_start(d->ctx, sdp ? sdp->data : 0, 0, pdp ? pdp->data : 0));
984 VerificationResult Context::verificationResult() const
986 if (d->lastop & Private::Verify) {
987 return VerificationResult(d->ctx, Error(d->lasterr));
989 return VerificationResult();
993 std::pair<DecryptionResult, VerificationResult> Context::decryptAndVerify(const Data &cipherText, Data &plainText, DecryptionFlags flags)
995 d->lastop = Private::DecryptAndVerify;
996 const Data::Private *const cdp = cipherText.impl();
997 Data::Private *const pdp = plainText.impl();
998 d->lasterr = gpgme_op_decrypt_ext(d->ctx, static_cast<gpgme_decrypt_flags_t> (d->decryptFlags | flags | DecryptVerify),
999 cdp ? cdp->data : 0, pdp ? pdp->data : 0);
1000 return std::make_pair(DecryptionResult(d->ctx, Error(d->lasterr)),
1001 VerificationResult(d->ctx, Error(d->lasterr)));
1004 std::pair<DecryptionResult, VerificationResult> Context::decryptAndVerify(const Data &cipherText, Data &plainText)
1006 return decryptAndVerify(cipherText, plainText, DecryptNone);
1009 Error Context::startCombinedDecryptionAndVerification(const Data &cipherText, Data &plainText, DecryptionFlags flags)
1011 d->lastop = Private::DecryptAndVerify;
1012 const Data::Private *const cdp = cipherText.impl();
1013 Data::Private *const pdp = plainText.impl();
1014 return Error(d->lasterr = gpgme_op_decrypt_ext_start(d->ctx, static_cast<gpgme_decrypt_flags_t> (d->decryptFlags | flags | DecryptVerify), cdp ? cdp->data : 0, pdp ? pdp->data : 0));
1017 Error Context::startCombinedDecryptionAndVerification(const Data &cipherText, Data &plainText)
1019 return startCombinedDecryptionAndVerification(cipherText, plainText, DecryptNone);
1022 unsigned int to_auditlog_flags(unsigned int flags)
1024 unsigned int result = 0;
1025 if (flags & Context::HtmlAuditLog) {
1026 result |= GPGME_AUDITLOG_HTML;
1028 if (flags & Context::AuditLogWithHelp) {
1029 result |= GPGME_AUDITLOG_WITH_HELP;
1034 Error Context::startGetAuditLog(Data &output, unsigned int flags)
1036 d->lastop = Private::GetAuditLog;
1037 Data::Private *const odp = output.impl();
1038 return Error(d->lasterr = gpgme_op_getauditlog_start(d->ctx, odp ? odp->data : 0, to_auditlog_flags(flags)));
1041 Error Context::getAuditLog(Data &output, unsigned int flags)
1043 d->lastop = Private::GetAuditLog;
1044 Data::Private *const odp = output.impl();
1045 return Error(d->lasterr = gpgme_op_getauditlog(d->ctx, odp ? odp->data : 0, to_auditlog_flags(flags)));
1048 void Context::clearSigningKeys()
1050 gpgme_signers_clear(d->ctx);
1053 Error Context::addSigningKey(const Key &key)
1055 return Error(d->lasterr = gpgme_signers_add(d->ctx, key.impl()));
1058 Key Context::signingKey(unsigned int idx) const
1060 gpgme_key_t key = gpgme_signers_enum(d->ctx, idx);
1061 return Key(key, false);
1064 std::vector<Key> Context::signingKeys() const
1066 std::vector<Key> result;
1068 for (unsigned int i = 0 ; (key = gpgme_signers_enum(d->ctx, i)) ; ++i) {
1069 result.push_back(Key(key, false));
1074 void Context::clearSignatureNotations()
1076 gpgme_sig_notation_clear(d->ctx);
1079 GpgME::Error Context::addSignatureNotation(const char *name, const char *value, unsigned int flags)
1081 return Error(gpgme_sig_notation_add(d->ctx, name, value, add_to_gpgme_sig_notation_flags_t(0, flags)));
1084 GpgME::Error Context::addSignaturePolicyURL(const char *url, bool critical)
1086 return Error(gpgme_sig_notation_add(d->ctx, 0, url, critical ? GPGME_SIG_NOTATION_CRITICAL : 0));
1089 const char *Context::signaturePolicyURL() const
1091 for (gpgme_sig_notation_t n = gpgme_sig_notation_get(d->ctx) ; n ; n = n->next) {
1099 Notation Context::signatureNotation(unsigned int idx) const
1101 for (gpgme_sig_notation_t n = gpgme_sig_notation_get(d->ctx) ; n ; n = n->next) {
1111 std::vector<Notation> Context::signatureNotations() const
1113 std::vector<Notation> result;
1114 for (gpgme_sig_notation_t n = gpgme_sig_notation_get(d->ctx) ; n ; n = n->next) {
1116 result.push_back(Notation(n));
1122 static gpgme_sig_mode_t sigmode2sigmode(SignatureMode mode)
1126 case NormalSignatureMode: return GPGME_SIG_MODE_NORMAL;
1127 case Detached: return GPGME_SIG_MODE_DETACH;
1128 case Clearsigned: return GPGME_SIG_MODE_CLEAR;
1132 SigningResult Context::sign(const Data &plainText, Data &signature, SignatureMode mode)
1134 d->lastop = Private::Sign;
1135 const Data::Private *const pdp = plainText.impl();
1136 Data::Private *const sdp = signature.impl();
1137 d->lasterr = gpgme_op_sign(d->ctx, pdp ? pdp->data : 0, sdp ? sdp->data : 0, sigmode2sigmode(mode));
1138 return SigningResult(d->ctx, Error(d->lasterr));
1141 Error Context::startSigning(const Data &plainText, Data &signature, SignatureMode mode)
1143 d->lastop = Private::Sign;
1144 const Data::Private *const pdp = plainText.impl();
1145 Data::Private *const sdp = signature.impl();
1146 return Error(d->lasterr = gpgme_op_sign_start(d->ctx, pdp ? pdp->data : 0, sdp ? sdp->data : 0, sigmode2sigmode(mode)));
1149 SigningResult Context::signingResult() const
1151 if (d->lastop & Private::Sign) {
1152 return SigningResult(d->ctx, Error(d->lasterr));
1154 return SigningResult();
1158 static gpgme_encrypt_flags_t encryptflags2encryptflags(Context::EncryptionFlags flags)
1160 unsigned int result = 0;
1161 if (flags & Context::AlwaysTrust) {
1162 result |= GPGME_ENCRYPT_ALWAYS_TRUST;
1164 if (flags & Context::NoEncryptTo) {
1165 result |= GPGME_ENCRYPT_NO_ENCRYPT_TO;
1167 if (flags & Context::Prepare) {
1168 result |= GPGME_ENCRYPT_PREPARE;
1170 if (flags & Context::ExpectSign) {
1171 result |= GPGME_ENCRYPT_EXPECT_SIGN;
1173 if (flags & Context::NoCompress) {
1174 result |= GPGME_ENCRYPT_NO_COMPRESS;
1176 if (flags & Context::Symmetric) {
1177 result |= GPGME_ENCRYPT_SYMMETRIC;
1179 return static_cast<gpgme_encrypt_flags_t>(result);
1182 gpgme_key_t *Context::getKeysFromRecipients(const std::vector<Key> &recipients)
1184 if (recipients.empty()) {
1187 gpgme_key_t *ret = new gpgme_key_t[ recipients.size() + 1 ];
1188 gpgme_key_t *keys_it = ret;
1189 for (std::vector<Key>::const_iterator it = recipients.begin() ; it != recipients.end() ; ++it) {
1191 *keys_it++ = it->impl();
1198 EncryptionResult Context::encrypt(const std::vector<Key> &recipients, const Data &plainText, Data &cipherText, EncryptionFlags flags)
1200 d->lastop = Private::Encrypt;
1201 if (flags & NoEncryptTo) {
1202 return EncryptionResult(Error(d->lasterr = make_error(GPG_ERR_NOT_IMPLEMENTED)));
1204 const Data::Private *const pdp = plainText.impl();
1205 Data::Private *const cdp = cipherText.impl();
1206 gpgme_key_t *const keys = getKeysFromRecipients(recipients);
1207 d->lasterr = gpgme_op_encrypt(d->ctx, keys, encryptflags2encryptflags(flags),
1208 pdp ? pdp->data : 0, cdp ? cdp->data : 0);
1212 return EncryptionResult(d->ctx, Error(d->lasterr));
1215 Error Context::encryptSymmetrically(const Data &plainText, Data &cipherText)
1217 d->lastop = Private::Encrypt;
1218 const Data::Private *const pdp = plainText.impl();
1219 Data::Private *const cdp = cipherText.impl();
1220 return Error(d->lasterr = gpgme_op_encrypt(d->ctx, 0, (gpgme_encrypt_flags_t)0,
1221 pdp ? pdp->data : 0, cdp ? cdp->data : 0));
1224 Error Context::startEncryption(const std::vector<Key> &recipients, const Data &plainText, Data &cipherText, EncryptionFlags flags)
1226 d->lastop = Private::Encrypt;
1227 if (flags & NoEncryptTo) {
1228 return Error(d->lasterr = make_error(GPG_ERR_NOT_IMPLEMENTED));
1230 const Data::Private *const pdp = plainText.impl();
1231 Data::Private *const cdp = cipherText.impl();
1232 gpgme_key_t *const keys = getKeysFromRecipients(recipients);
1233 d->lasterr = gpgme_op_encrypt_start(d->ctx, keys, encryptflags2encryptflags(flags),
1234 pdp ? pdp->data : 0, cdp ? cdp->data : 0);
1238 return Error(d->lasterr);
1241 EncryptionResult Context::encryptionResult() const
1243 if (d->lastop & Private::Encrypt) {
1244 return EncryptionResult(d->ctx, Error(d->lasterr));
1246 return EncryptionResult();
1250 std::pair<SigningResult, EncryptionResult> Context::signAndEncrypt(const std::vector<Key> &recipients, const Data &plainText, Data &cipherText, EncryptionFlags flags)
1252 d->lastop = Private::SignAndEncrypt;
1253 const Data::Private *const pdp = plainText.impl();
1254 Data::Private *const cdp = cipherText.impl();
1255 gpgme_key_t *const keys = getKeysFromRecipients(recipients);
1256 d->lasterr = gpgme_op_encrypt_sign(d->ctx, keys, encryptflags2encryptflags(flags),
1257 pdp ? pdp->data : 0, cdp ? cdp->data : 0);
1261 return std::make_pair(SigningResult(d->ctx, Error(d->lasterr)),
1262 EncryptionResult(d->ctx, Error(d->lasterr)));
1265 Error Context::startCombinedSigningAndEncryption(const std::vector<Key> &recipients, const Data &plainText, Data &cipherText, EncryptionFlags flags)
1267 d->lastop = Private::SignAndEncrypt;
1268 const Data::Private *const pdp = plainText.impl();
1269 Data::Private *const cdp = cipherText.impl();
1270 gpgme_key_t *const keys = getKeysFromRecipients(recipients);
1271 d->lasterr = gpgme_op_encrypt_sign_start(d->ctx, keys, encryptflags2encryptflags(flags),
1272 pdp ? pdp->data : 0, cdp ? cdp->data : 0);
1276 return Error(d->lasterr);
1279 Error Context::createVFS(const char *containerFile, const std::vector< Key > &recipients)
1281 d->lastop = Private::CreateVFS;
1282 gpgme_key_t *const keys = new gpgme_key_t[ recipients.size() + 1 ];
1283 gpgme_key_t *keys_it = keys;
1284 for (std::vector<Key>::const_iterator it = recipients.begin() ; it != recipients.end() ; ++it) {
1286 *keys_it++ = it->impl();
1291 gpgme_error_t op_err;
1292 d->lasterr = gpgme_op_vfs_create(d->ctx, keys, containerFile, 0, &op_err);
1294 Error error(d->lasterr);
1298 return Error(d->lasterr = op_err);
1301 VfsMountResult Context::mountVFS(const char *containerFile, const char *mountDir)
1303 d->lastop = Private::MountVFS;
1304 gpgme_error_t op_err;
1305 d->lasterr = gpgme_op_vfs_mount(d->ctx, containerFile, mountDir, 0, &op_err);
1306 return VfsMountResult(d->ctx, Error(d->lasterr), Error(op_err));
1309 Error Context::cancelPendingOperation()
1311 return Error(gpgme_cancel_async(d->ctx));
1314 bool Context::poll()
1316 gpgme_error_t e = GPG_ERR_NO_ERROR;
1317 const bool finished = gpgme_wait(d->ctx, &e, 0);
1324 Error Context::wait()
1326 gpgme_error_t e = GPG_ERR_NO_ERROR;
1327 gpgme_wait(d->ctx, &e, 1);
1328 return Error(d->lasterr = e);
1331 Error Context::lastError() const
1333 return Error(d->lasterr);
1336 Context::PinentryMode Context::pinentryMode() const
1338 switch (gpgme_get_pinentry_mode (d->ctx)) {
1339 case GPGME_PINENTRY_MODE_ASK:
1341 case GPGME_PINENTRY_MODE_CANCEL:
1342 return PinentryCancel;
1343 case GPGME_PINENTRY_MODE_ERROR:
1344 return PinentryError;
1345 case GPGME_PINENTRY_MODE_LOOPBACK:
1346 return PinentryLoopback;
1347 case GPGME_PINENTRY_MODE_DEFAULT:
1349 return PinentryDefault;
1353 Error Context::setPinentryMode(PinentryMode which)
1355 gpgme_pinentry_mode_t mode;
1358 mode = GPGME_PINENTRY_MODE_ASK;
1360 case PinentryCancel:
1361 mode = GPGME_PINENTRY_MODE_CANCEL;
1364 mode = GPGME_PINENTRY_MODE_ERROR;
1366 case PinentryLoopback:
1367 mode = GPGME_PINENTRY_MODE_LOOPBACK;
1369 case PinentryDefault:
1371 mode = GPGME_PINENTRY_MODE_DEFAULT;
1373 return Error(d->lasterr = gpgme_set_pinentry_mode(d->ctx, mode));
1376 static gpgme_tofu_policy_t to_tofu_policy_t(unsigned int policy)
1379 case TofuInfo::PolicyNone:
1380 return GPGME_TOFU_POLICY_NONE;
1381 case TofuInfo::PolicyAuto:
1382 return GPGME_TOFU_POLICY_AUTO;
1383 case TofuInfo::PolicyGood:
1384 return GPGME_TOFU_POLICY_GOOD;
1385 case TofuInfo::PolicyBad:
1386 return GPGME_TOFU_POLICY_BAD;
1387 case TofuInfo::PolicyAsk:
1388 return GPGME_TOFU_POLICY_ASK;
1389 case TofuInfo::PolicyUnknown:
1391 return GPGME_TOFU_POLICY_UNKNOWN;
1395 Error Context::setTofuPolicy(const Key &k, unsigned int policy)
1397 return Error(d->lasterr = gpgme_op_tofu_policy(d->ctx,
1398 k.impl(), to_tofu_policy_t(policy)));
1401 Error Context::setTofuPolicyStart(const Key &k, unsigned int policy)
1403 return Error(d->lasterr = gpgme_op_tofu_policy_start(d->ctx,
1404 k.impl(), to_tofu_policy_t(policy)));
1407 Error Context::startCreateKey (const char *userid,
1409 unsigned long reserved,
1410 unsigned long expires,
1414 return Error(d->lasterr = gpgme_op_createkey_start(d->ctx,
1423 Error Context::createKey (const char *userid,
1425 unsigned long reserved,
1426 unsigned long expires,
1430 return Error(d->lasterr = gpgme_op_createkey(d->ctx,
1439 Error Context::addUid(const Key &k, const char *userid)
1441 return Error(d->lasterr = gpgme_op_adduid(d->ctx,
1442 k.impl(), userid, 0));
1445 Error Context::startAddUid(const Key &k, const char *userid)
1447 return Error(d->lasterr = gpgme_op_adduid_start(d->ctx,
1448 k.impl(), userid, 0));
1451 Error Context::revUid(const Key &k, const char *userid)
1453 return Error(d->lasterr = gpgme_op_revuid(d->ctx,
1454 k.impl(), userid, 0));
1457 Error Context::startRevUid(const Key &k, const char *userid)
1459 return Error(d->lasterr = gpgme_op_revuid_start(d->ctx,
1460 k.impl(), userid, 0));
1463 Error Context::createSubkey(const Key &k, const char *algo,
1464 unsigned long reserved,
1465 unsigned long expires,
1468 return Error(d->lasterr = gpgme_op_createsubkey(d->ctx,
1469 k.impl(), algo, reserved, expires, flags));
1472 Error Context::startCreateSubkey(const Key &k, const char *algo,
1473 unsigned long reserved,
1474 unsigned long expires,
1477 return Error(d->lasterr = gpgme_op_createsubkey_start(d->ctx,
1478 k.impl(), algo, reserved, expires, flags));
1481 // Engine Spawn stuff
1482 Error Context::spawn(const char *file, const char *argv[],
1483 Data &input, Data &output, Data &err,
1486 return Error(d->lasterr = gpgme_op_spawn (d->ctx, file, argv,
1487 input.impl() ? input.impl()->data : nullptr,
1488 output.impl() ? output.impl()->data : nullptr,
1489 err.impl() ? err.impl()->data : nullptr,
1490 static_cast<int>(flags)));
1493 Error Context::spawnAsync(const char *file, const char *argv[],
1494 Data &input, Data &output, Data &err,
1497 return Error(d->lasterr = gpgme_op_spawn_start (d->ctx, file, argv,
1498 input.impl() ? input.impl()->data : nullptr,
1499 output.impl() ? output.impl()->data : nullptr,
1500 err.impl() ? err.impl()->data : nullptr,
1501 static_cast<int>(flags)));
1504 std::ostream &operator<<(std::ostream &os, Protocol proto)
1506 os << "GpgME::Protocol(";
1515 case UnknownProtocol:
1516 os << "UnknownProtocol";
1522 std::ostream &operator<<(std::ostream &os, Engine eng)
1524 os << "GpgME::Engine(";
1530 os << "GpgSMEngine";
1533 os << "GpgConfEngine";
1536 os << "AssuanEngine";
1539 os << "SpawnEngine";
1543 os << "UnknownEngine";
1549 std::ostream &operator<<(std::ostream &os, Context::CertificateInclusion incl)
1551 os << "GpgME::Context::CertificateInclusion(" << static_cast<int>(incl);
1553 case Context::DefaultCertificates:
1554 os << "(DefaultCertificates)";
1556 case Context::AllCertificatesExceptRoot:
1557 os << "(AllCertificatesExceptRoot)";
1559 case Context::AllCertificates:
1560 os << "(AllCertificates)";
1562 case Context::NoCertificates:
1563 os << "(NoCertificates)";
1565 case Context::OnlySenderCertificate:
1566 os << "(OnlySenderCertificate)";
1572 std::ostream &operator<<(std::ostream &os, KeyListMode mode)
1574 os << "GpgME::KeyListMode(";
1575 #define CHECK( x ) if ( !(mode & (x)) ) {} else do { os << #x " "; } while (0)
1586 std::ostream &operator<<(std::ostream &os, SignatureMode mode)
1588 os << "GpgME::SignatureMode(";
1590 #define CHECK( x ) case x: os << #x; break
1591 CHECK(NormalSignatureMode);
1596 os << "???" "(" << static_cast<int>(mode) << ')';
1602 std::ostream &operator<<(std::ostream &os, Context::EncryptionFlags flags)
1604 os << "GpgME::Context::EncryptionFlags(";
1605 #define CHECK( x ) if ( !(flags & (Context::x)) ) {} else do { os << #x " "; } while (0)
1616 std::ostream &operator<<(std::ostream &os, Context::AuditLogFlags flags)
1618 os << "GpgME::Context::AuditLogFlags(";
1619 #define CHECK( x ) if ( !(flags & (Context::x)) ) {} else do { os << #x " "; } while (0)
1620 CHECK(HtmlAuditLog);
1621 CHECK(AuditLogWithHelp);
1626 } // namespace GpgME
1628 GpgME::Error GpgME::setDefaultLocale(int cat, const char *val)
1630 return Error(gpgme_set_locale(0, cat, val));
1633 GpgME::EngineInfo GpgME::engineInfo(GpgME::Protocol proto)
1635 gpgme_engine_info_t ei = 0;
1636 if (gpgme_get_engine_info(&ei)) {
1637 return EngineInfo();
1640 const gpgme_protocol_t p = proto == CMS ? GPGME_PROTOCOL_CMS : GPGME_PROTOCOL_OpenPGP ;
1642 for (gpgme_engine_info_t i = ei ; i ; i = i->next) {
1643 if (i->protocol == p) {
1644 return EngineInfo(i);
1648 return EngineInfo();
1651 const char *GpgME::dirInfo(const char *what)
1653 return gpgme_get_dirinfo(what);
1656 GpgME::Error GpgME::checkEngine(GpgME::Protocol proto)
1658 const gpgme_protocol_t p = proto == CMS ? GPGME_PROTOCOL_CMS : GPGME_PROTOCOL_OpenPGP ;
1660 return Error(gpgme_engine_check_version(p));
1663 static const gpgme_protocol_t UNKNOWN_PROTOCOL = static_cast<gpgme_protocol_t>(255);
1665 static gpgme_protocol_t engine2protocol(const GpgME::Engine engine)
1668 case GpgME::GpgEngine: return GPGME_PROTOCOL_OpenPGP;
1669 case GpgME::GpgSMEngine: return GPGME_PROTOCOL_CMS;
1670 case GpgME::GpgConfEngine:
1671 return GPGME_PROTOCOL_GPGCONF;
1672 case GpgME::AssuanEngine:
1673 return GPGME_PROTOCOL_ASSUAN;
1674 case GpgME::G13Engine:
1675 return GPGME_PROTOCOL_G13;
1676 case GpgME::SpawnEngine:
1677 return GPGME_PROTOCOL_SPAWN;
1678 case GpgME::UnknownEngine:
1681 return UNKNOWN_PROTOCOL;
1684 GpgME::EngineInfo GpgME::engineInfo(GpgME::Engine engine)
1686 gpgme_engine_info_t ei = 0;
1687 if (gpgme_get_engine_info(&ei)) {
1688 return EngineInfo();
1691 const gpgme_protocol_t p = engine2protocol(engine);
1693 for (gpgme_engine_info_t i = ei ; i ; i = i->next) {
1694 if (i->protocol == p) {
1695 return EngineInfo(i);
1699 return EngineInfo();
1702 GpgME::Error GpgME::checkEngine(GpgME::Engine engine)
1704 const gpgme_protocol_t p = engine2protocol(engine);
1706 return Error(gpgme_engine_check_version(p));
1709 static const unsigned long supported_features = 0
1710 | GpgME::ValidatingKeylistModeFeature
1711 | GpgME::CancelOperationFeature
1712 | GpgME::WrongKeyUsageFeature
1713 | GpgME::DefaultCertificateInclusionFeature
1714 | GpgME::GetSetEngineInfoFeature
1715 | GpgME::ClearAddGetSignatureNotationsFeature
1716 | GpgME::SetDataFileNameFeeature
1717 | GpgME::SignatureNotationsKeylistModeFeature
1718 | GpgME::KeySignatureNotationsFeature
1719 | GpgME::KeyIsQualifiedFeature
1720 | GpgME::SignatureNotationsCriticalFlagFeature
1721 | GpgME::SignatureNotationsFlagsFeature
1722 | GpgME::SignatureNotationsHumanReadableFlagFeature
1723 | GpgME::SubkeyIsQualifiedFeature
1724 | GpgME::EngineInfoHomeDirFeature
1725 | GpgME::DecryptionResultFileNameFeature
1726 | GpgME::DecryptionResultRecipientsFeature
1727 | GpgME::VerificationResultFileNameFeature
1728 | GpgME::SignaturePkaFieldsFeature
1729 | GpgME::SignatureAlgorithmFieldsFeature
1730 | GpgME::FdPointerFeature
1731 | GpgME::AuditLogFeature
1732 | GpgME::GpgConfEngineFeature
1733 | GpgME::CancelOperationAsyncFeature
1734 | GpgME::NoEncryptToEncryptionFlagFeature
1735 | GpgME::CardKeyFeature
1736 | GpgME::AssuanEngineFeature
1737 | GpgME::EphemeralKeylistModeFeature
1738 | GpgME::ImportFromKeyserverFeature
1739 | GpgME::G13VFSFeature
1740 | GpgME::PasswdFeature
1743 static const unsigned long supported_features2 = 0
1744 | GpgME::BinaryAndFineGrainedIdentify
1747 bool GpgME::hasFeature(unsigned long features)
1749 return features == (features & supported_features);
1752 bool GpgME::hasFeature(unsigned long features, unsigned long features2)
1754 return features == (features & supported_features)
1755 && features2 == (features2 & supported_features2)