summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorJinWang An <jinwang.an@samsung.com>2023-01-30 13:26:32 +0900
committerJinWang An <jinwang.an@samsung.com>2023-01-30 13:26:32 +0900
commit7068c0ead0c25a9a1fd3ce0b486636d74350e7ca (patch)
tree732edf51b955fd198e4bb7ef46a0782fb3ea1d12
parentd19c360948ede5ffe5974de8abc9da44be617ca1 (diff)
downloadgpgme-7068c0ead0c25a9a1fd3ce0b486636d74350e7ca.tar.gz
gpgme-7068c0ead0c25a9a1fd3ce0b486636d74350e7ca.tar.bz2
gpgme-7068c0ead0c25a9a1fd3ce0b486636d74350e7ca.zip
Imported Upstream version 1.17.0upstream/1.17.0
-rw-r--r--ChangeLog662
-rw-r--r--Makefile.am2
-rw-r--r--Makefile.in2
-rw-r--r--NEWS70
-rw-r--r--VERSION2
-rw-r--r--conf/config.h.in12
-rwxr-xr-xconfigure100
-rw-r--r--configure.ac23
-rw-r--r--doc/defsincdate2
-rw-r--r--doc/gpgme.info244
-rw-r--r--doc/gpgme.info-1155
-rw-r--r--doc/gpgme.info-279
-rw-r--r--doc/gpgme.texi89
-rw-r--r--gpgme.spec2
-rw-r--r--lang/cl/gpgme.asd2
-rw-r--r--lang/cpp/src/Makefile.am5
-rw-r--r--lang/cpp/src/Makefile.in18
-rw-r--r--lang/cpp/src/context.cpp192
-rw-r--r--lang/cpp/src/context.h30
-rw-r--r--lang/cpp/src/global.h3
-rw-r--r--lang/cpp/src/gpgaddexistingsubkeyeditinteractor.cpp209
-rw-r--r--lang/cpp/src/gpgaddexistingsubkeyeditinteractor.h59
-rw-r--r--lang/cpp/src/importresult.cpp4
-rw-r--r--lang/cpp/src/util.cpp47
-rw-r--r--lang/cpp/src/util.h25
-rw-r--r--lang/cpp/tests/Makefile.am11
-rw-r--r--lang/cpp/tests/Makefile.in27
-rw-r--r--lang/cpp/tests/run-wkdlookup.cpp156
-rw-r--r--lang/qt/src/AddExistingSubkeyJob1
-rw-r--r--lang/qt/src/Makefile.am34
-rw-r--r--lang/qt/src/Makefile.in103
-rw-r--r--lang/qt/src/ReceiveKeysJob1
-rw-r--r--lang/qt/src/WKDLookupJob1
-rw-r--r--lang/qt/src/WKDLookupResult1
-rw-r--r--lang/qt/src/addexistingsubkeyjob.h79
-rw-r--r--lang/qt/src/changeexpiryjob.cpp76
-rw-r--r--lang/qt/src/changeexpiryjob.h13
-rw-r--r--lang/qt/src/cryptoconfig.cpp9
-rw-r--r--lang/qt/src/cryptoconfig.h7
-rw-r--r--lang/qt/src/importjob.cpp91
-rw-r--r--lang/qt/src/importjob.h15
-rw-r--r--lang/qt/src/job.cpp32
-rw-r--r--lang/qt/src/job_p.h70
-rw-r--r--lang/qt/src/protocol.h14
-rw-r--r--lang/qt/src/protocol_p.h64
-rw-r--r--lang/qt/src/qgpgmeaddexistingsubkeyjob.cpp96
-rw-r--r--lang/qt/src/qgpgmeaddexistingsubkeyjob.h68
-rw-r--r--lang/qt/src/qgpgmechangeexpiryjob.cpp32
-rw-r--r--lang/qt/src/qgpgmechangeownertrustjob.h2
-rw-r--r--lang/qt/src/qgpgmeexportjob.cpp24
-rw-r--r--lang/qt/src/qgpgmeexportjob.h14
-rw-r--r--lang/qt/src/qgpgmeimportjob.cpp64
-rw-r--r--lang/qt/src/qgpgmenewcryptoconfig.cpp52
-rw-r--r--lang/qt/src/qgpgmenewcryptoconfig.h1
-rw-r--r--lang/qt/src/qgpgmereceivekeysjob.cpp79
-rw-r--r--lang/qt/src/qgpgmereceivekeysjob.h (renamed from lang/qt/src/qgpgmesecretkeyexportjob.h)61
-rw-r--r--lang/qt/src/qgpgmesecretkeyexportjob.cpp147
-rw-r--r--lang/qt/src/qgpgmewkdlookupjob.cpp183
-rw-r--r--lang/qt/src/qgpgmewkdlookupjob.h70
-rw-r--r--lang/qt/src/receivekeysjob.h66
-rw-r--r--lang/qt/src/signkeyjob.h6
-rw-r--r--lang/qt/src/threadedjobmixin.cpp45
-rw-r--r--lang/qt/src/util.cpp47
-rw-r--r--lang/qt/src/util.h51
-rw-r--r--lang/qt/src/wkdlookupjob.h78
-rw-r--r--lang/qt/src/wkdlookupresult.cpp117
-rw-r--r--lang/qt/src/wkdlookupresult.h88
-rw-r--r--lang/qt/tests/Makefile.am36
-rw-r--r--lang/qt/tests/Makefile.in184
-rwxr-xr-xlang/qt/tests/final.test6
-rw-r--r--lang/qt/tests/run-exportjob.cpp119
-rw-r--r--lang/qt/tests/run-importjob.cpp99
-rw-r--r--lang/qt/tests/run-receivekeysjob.cpp65
-rw-r--r--lang/qt/tests/t-addexistingsubkey.cpp260
-rw-r--r--lang/qt/tests/t-changeexpiryjob.cpp396
-rw-r--r--lang/qt/tests/t-config.cpp19
-rw-r--r--lang/qt/tests/t-encrypt.cpp34
-rw-r--r--lang/qt/tests/t-import.cpp169
-rw-r--r--lang/qt/tests/t-keylist.cpp7
-rw-r--r--lang/qt/tests/t-keylocate.cpp3
-rw-r--r--lang/qt/tests/t-ownertrust.cpp3
-rw-r--r--lang/qt/tests/t-remarks.cpp68
-rw-r--r--lang/qt/tests/t-support.cpp52
-rw-r--r--lang/qt/tests/t-support.h60
-rw-r--r--lang/qt/tests/t-tofuinfo.cpp7
-rw-r--r--lang/qt/tests/t-trustsignatures.cpp61
-rw-r--r--lang/qt/tests/t-various.cpp29
-rw-r--r--lang/qt/tests/t-wkdlookup.cpp155
-rw-r--r--lang/qt/tests/t-wkspublish.cpp3
-rw-r--r--m4/libtool.m413
-rw-r--r--src/ath.c15
-rw-r--r--src/ath.h13
-rw-r--r--src/context.h6
-rw-r--r--src/data.c6
-rw-r--r--src/debug.h34
-rw-r--r--src/dirinfo.c66
-rw-r--r--src/engine-backend.h5
-rw-r--r--src/engine-gpg.c59
-rw-r--r--src/engine-gpgconf.c6
-rw-r--r--src/engine-gpgsm.c22
-rw-r--r--src/engine.c6
-rw-r--r--src/engine.h5
-rw-r--r--src/export.c88
-rw-r--r--src/gpgme-tool.c5
-rw-r--r--src/gpgme.c24
-rw-r--r--src/gpgme.def3
-rw-r--r--src/gpgme.h.in7
-rw-r--r--src/gpgme.pc.in6
-rw-r--r--src/import.c148
-rw-r--r--src/libgpgme.vers3
-rw-r--r--src/posix-io.c127
-rw-r--r--src/w32-util.c21
-rw-r--r--tests/Makefile.am14
-rw-r--r--tests/Makefile.in60
-rw-r--r--tests/gpg/Makefile.am30
-rw-r--r--tests/gpg/Makefile.in160
-rw-r--r--tests/gpg/gpg.conf.in5
-rw-r--r--tests/gpg/t-cancel.c67
-rw-r--r--tests/gpg/t-edit-sign.c54
-rw-r--r--tests/gpg/t-eventloop.c63
-rw-r--r--tests/gpg/t-import.c32
-rw-r--r--tests/run-export.c16
-rw-r--r--tests/run-genkey.c24
-rw-r--r--tests/run-import.c30
-rw-r--r--tests/run-receive-keys.c129
-rw-r--r--tests/run-swdb.c1
-rw-r--r--tests/run-threaded.c3
-rwxr-xr-xtests/start-stop-agent4
-rw-r--r--tests/t-engine-info.c6
129 files changed, 6370 insertions, 1085 deletions
diff --git a/ChangeLog b/ChangeLog
index ba800db..23c536e 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,3 +1,665 @@
+2022-02-07 Werner Koch <wk@gnupg.org>
+
+ Release 1.17.0.
+ + commit 72bb46b34f5191f672a5356e2f152e6ad9440554
+
+
+ qt: Fix build for older Qt versions.
+ + commit 451a42f0d21c5a402d455c78d63eeaaa139e56cc
+ * lang/qt/src/util.cpp: Include <functional>.
+
+2022-02-03 Ingo Klöcker <dev@ingo-kloecker.de>
+
+ qt: Add job to import keys given by key ids.
+ + commit ca1c30b6fa29a7a1f18ecda14375b47893a0c1a3
+ * lang/qt/src/receivekeysjob.h, lang/qt/src/qgpgmereceivekeysjob.h,
+ lang/qt/src/qgpgmereceivekeysjob.cpp: New.
+ * lang/qt/src/protocol.h (class Protocol): Add pure virtual member
+ function receiveKeysJob.
+ * lang/qt/src/protocol_p.h (Protocol::receiveKeysJob): Implement it.
+ * lang/qt/src/job.cpp, lang/qt/src/Makefile.am: Update accordingly.
+
+ * lang/qt/tests/run-receivekeysjob.cpp: New.
+ * lang/qt/tests/Makefile.am: Add new test runner.
+
+ qt: Add helper for converting QStringList to vector of strings.
+ + commit ec8d1ee13fce21a1f52b084212827914dfcd0db6
+ * lang/qt/src/util.h, lang/qt/src/util.cpp: New.
+ * lang/qt/src/Makefile.am (qgpgme_sources, private_qgpgme_headers):
+ Add new files.
+
+ cpp: Allow import of keys given by key ids.
+ + commit bbaeeb5b9d5cca99c332cb88c7ae5f14e8745427
+ * lang/cpp/src/context.h (class Context): Add overloads of member
+ functions importKeys and startKeyImport
+ * lang/cpp/src/context.cpp (class Context): ... and implement them.
+
+ cpp: Add internal adapter for passing a vector of strings to gpgme.
+ + commit 3d7810e8d940229435feb8f9811607ee831abf4b
+ * lang/cpp/src/util.h (class StringsToCStrings): New.
+ * lang/cpp/src/util.cpp: New.
+ * lang/cpp/src/Makefile.am: Add new file.
+
+ core: New function gpgme_op_receive_keys.
+ + commit 3c2cff74b535422532e1256ee8177fa9c03eaf18
+ * src/gpgme.h.in (gpgme_op_receive_keys_start, gpgme_op_receive_keys):
+ New.
+ * src/gpgme.def, src/libgpgme.vers: Add them.
+ * src/engine-backend.h (struct engine_ops): Add arg keyids to field
+ 'import'.
+ * src/engine.h, src/engine.c (_gpgme_engine_op_import): Add arg keyids.
+ * src/engine.c (_gpgme_engine_op_import): Forward new arg keyids.
+ * src/import.c: (_gpgme_op_import_start, _gpgme_op_import_keys_start):
+ Pass NULL to new arg of _gpgme_op_import_start.
+ (_gpgme_op_receive_keys_start, gpgme_op_receive_keys_start,
+ gpgme_op_receive_keys): New.
+ * src/engine-gpg.c (gpg_import): Add arg keyids. Extend check for
+ valid arguments. Build command line if keyids are given.
+ * src/engine-gpgsm.c (gpgsm_import): Add arg keyids. Return error if
+ keyids is not NULL.
+
+ tests/run-receive-keys.c: New.
+ tests/Makefile.am (noinst_PROGRAMS): Add new test runner.
+
+2022-01-17 Ingo Klöcker <dev@ingo-kloecker.de>
+
+ qt: Remove superfluous include.
+ + commit ec71eb1d7d9f1156cc48d1c9959b07981ecd16e5
+ * lang/qt/src/importjob.h: Remove include of QByteArray.
+
+ qt: Fix build without installed GpgME++ headers.
+ + commit 9c03bde06be97403a8c392a3befc6c203bcdce6d
+ * lang/qt/src/importjob.h, lang/qt/src/wkdlookupresult.h: Include
+ headers of GpgME++ without "gpgme++/" prefix when building QGpgme.
+ * lang/qt/src/qgpgmeimportjob.cpp, lang/qt/src/qgpgmewkdlookupjob.cpp,
+ lang/qt/src/wkdlookupresult.cpp, lang/qt/tests/t-import.cpp: Include
+ headers of GpgME++ without "gpgme++/" prefix.
+
+2022-01-13 Ingo Klöcker <dev@ingo-kloecker.de>
+
+ tests: Fix generation of keys without expiration.
+ + commit e16729edcbdf2c35e3729b6d54c21b9b27250326
+ * tests/run-genkey.c (parse_expire_string): Support default expiration
+ and no expiration. Set flag for no expiration.
+ (main): Allow update of flags when generating new key.
+
+ tests: Remove unsupported option --status from usage help.
+ + commit e4625885a851112a15636727388f11146be17f15
+ * tests/run-swdb.c (show_usage): Remove option --status.
+
+ qt: Add job to add existing subkeys to other keys.
+ + commit 4d913a8aa5dad1327bed5987dada89e9d7c5d292
+ * lang/qt/src/addexistingsubkeyjob.h,
+ lang/qt/src/qgpgmeaddexistingsubkeyjob.cpp,
+ lang/qt/src/qgpgmeaddexistingsubkeyjob.h: New.
+ * lang/qt/src/protocol.h (class Protocol): Add pure virtual member
+ function addExistingSubkeyJob.
+ * lang/qt/src/protocol_p.h (Protocol::addExistingSubkeyJob): Implement.
+ * lang/qt/src/job.cpp, lang/qt/src/Makefile.am: Update accordingly.
+
+ * lang/qt/tests/Makefile.am (the_tests, moc_files, noinst_PROGRAMS):
+ Add new test.
+ (t_addexistingsubkey_SOURCES): New.
+ * lang/qt/tests/t-addexistingsubkey.cpp: New.
+ * lang/qt/tests/t-support.h (VERIFY_OR_RETURN_VALUE,
+ COMPARE_OR_RETURN_VALUE, VERIFY_OR_OBJECT, COMPARE_OR_OBJECT,
+ VERIFY_OR_FALSE, COMPARE_OR_FALSE): New.
+ * lang/qt/tests/t-support.h, lang/qt/tests/t-support.cpp
+ (class QQGpgMETest): New member function importSecretKeys.
+
+ qt,tests: Add helper to hook up the test passphrase provider.
+ + commit d308910cdfb31accae7cf790a956eb2f3cc6ae71
+ * lang/qt/tests/t-support.h, lang/qt/tests/t-support.cpp
+ (class QGpgMETest): Add member function hookUpPassphraseProvider.
+ Add member mPassphraseProvider.
+ * lang/qt/tests/t-changeexpiryjob.cpp,
+ lang/qt/tests/t-encrypt.cpp,
+ lang/qt/tests/t-remarks.cpp,
+ lang/qt/tests/t-tofuinfo.cpp,
+ lang/qt/tests/t-trustsignatures.cpp,
+ lang/qt/tests/t-various.cpp: Use new helper.
+
+ qt,tests: Add asyncDone signal to base class of all tests.
+ + commit a54402fc2d1c1364843d3c88b5b07dbb7fc007d1
+ * lang/qt/tests/t-support.h (class QGpgMETest): Add signal asyncDone.
+ * lang/qt/tests/t-changeexpiryjob.cpp,
+ lang/qt/tests/t-encrypt.cpp,
+ lang/qt/tests/t-import.cpp,
+ lang/qt/tests/t-keylist.cpp,
+ lang/qt/tests/t-keylocate.cpp,
+ lang/qt/tests/t-ownertrust.cpp,
+ lang/qt/tests/t-remarks.cpp,
+ lang/qt/tests/t-tofuinfo.cpp,
+ lang/qt/tests/t-trustsignatures.cpp,
+ lang/qt/tests/t-various.cpp,
+ lang/qt/tests/t-wkdlookup.cpp,
+ lang/qt/tests/t-wkspublish.cpp: Remove signal asyncDone from the test
+ classes.
+
+2022-01-12 Ingo Klöcker <dev@ingo-kloecker.de>
+
+ cpp: Add interactor to add existing subkeys to other keys.
+ + commit a4dcb17486bb42890ffe6453eeb2c6f301dc1fae
+ * lang/cpp/src/gpgaddexistingsubkeyeditinteractor.cpp,
+ lang/cpp/src/gpgaddexistingsubkeyeditinteractor.h: New.
+ * lang/cpp/src/Makefile.am: Add new files.
+
+2022-01-10 Ingo Klöcker <dev@ingo-kloecker.de>
+
+ core: Return an error for secret key export operations.
+ + commit a527bd7cf58563d07c89bec458c8967ab1b3e60f
+ src/export.c (export_status_handler): Handle "export_keys.secret".
+
+2022-01-04 Ingo Klöcker <dev@ingo-kloecker.de>
+
+ qt: Add factory function for secret subkey export job.
+ + commit 04723a6e96be77dbc43bf71c54e268424a1823ba
+ * lang/qt/src/protocol.h (class Protocol): Add member function
+ secretSubkeyExportJob.
+ * lang/qt/src/protocol_p.h (Protocol::secretSubkeyExportJob): Implement.
+
+ * lang/qt/tests/run-exportjob.cpp (showUsageAndExitWithCode): Print
+ new option.
+ (createExportJob): Create secret subkey export job if requested.
+ (main): New option --secret-subkey.
+
+ cpp: Allow export of secret subkeys.
+ + commit e5c7fc3e022841be8f68fad8b9b64dd601b89ba7
+ * lang/cpp/src/context.h (enum Context::ExportMode): Add value
+ ExportSecretSubkey.
+ (class Context): Add member functions exportSecretSubkeys and
+ startSecretSubkeyExport.
+ * lang/cpp/src/context.cpp (Context::exportPublicKeys,
+ Context::startPublicKeyExport): Return error if ExportSecretSubkey
+ mode flag is set.
+ (Context::exportSecretSubkeys, Context::startSecretSubkeyExport):
+ Implement.
+
+ qt: Remove obsolete QGpgMESecretKeyExportJob.
+ + commit 88ad37ea96e4645a9e23aac9eae0d8da747559b8
+ * lang/qt/src/Makefile.am: Remove all occurrences of
+ qgpgmesecretkeyexportjob.*.
+ * lang/qt/src/qgpgmesecretkeyexportjob.cpp,
+ lang/qt/src/qgpgmesecretkeyexportjob.h: Remove.
+
+ qt: Use QGpgMEExportJob also for export of secret keys.
+ + commit 4e80563fabfdf1d1c136d65252e5353fdd1e9092
+ * lang/qt/src/protocol.h (Protocol::secretKeyExportJob): Document
+ charset argument as ignored.
+ * lang/qt/src/protocol_p.h (Protocol::secretKeyExportJob): Use
+ QGpgMEExportJob instead of QGpgMESecretKeyExportJob.
+ * lang/qt/src/qgpgmeexportjob.h (class QGpgMEExportJob): Add c'tor
+ taking an export mode. Add member m_exportMode. Rename member m_flags to
+ m_additionalExportModeFlags.
+ (QGpgMEExportJob::~QGpgMEExportJob): Mark as override.
+ * lang/qt/src/qgpgmeexportjob.cpp (QGpgMEExportJob::QGpgMEExportJob):
+ Delegate to new c'tor. Implement new c'tor.
+ (QGpgMEExportJob::~QGpgMEExportJob): Use default.
+ (export_qba): Rename argument flags to mode.
+ (QGpgMEExportJob::start): Pass combination of export mode and additional
+ mode flags to export_qba.
+ (QGpgMEExportJob::setExportFlags): Adapt to renaming of member.
+
+ * lang/qt/tests/run-exportjob.cpp: New.
+
+ cpp: Allow export of secret keys.
+ + commit 3da06d1096ee29d70656f07edcabc3bc4351104e
+ * lang/cpp/src/context.h (class Context): New member functions
+ exportSecretKeys, startSecretKeyExport, exportKeys, startKeyExport.
+ (Context::exportPublicKeys, Context::startPublicKeyExport): Rename
+ argument flags/export_mode to mode.
+ * lang/cpp/src/context.cpp (Context::exportPublicKeys): Return error if
+ ExportSecret mode flag is set. Call exportKeys().
+ (Context::startPublicKeyExport): Return error if
+ ExportSecret mode flag is set. Call startKeyExport().
+ (Context::exportSecretKeys, Context::startSecretKeyExport,
+ Context::exportKeys, Context::startKeyExport): Implement.
+
+ cpp: Mark ExportNoUID flag as obsolete.
+ + commit 4888191014c24d5954685814e06c9ff0ee38739f
+ * lang/cpp/src/context.h (enum Context::ExportMode): Mark value
+ ExportNoUID as obsolete
+
+ core: Add new option --secret-subkey to help texts.
+ + commit 2752e81f892568a9725fdd8d6a997a1cc80d2f88
+ * src/gpgme-tool.c (hlp_export): Add new option.
+ * tests/run-export.c (show_usage): Print new option.
+
+ cpp: Remove obsolete workaround.
+ + commit fa5f1b57cc12f9305d112f11c2c2d95751ed1a25
+ * lang/cpp/src/context.cpp (Context::startKeyListing,
+ Context::exportPublicKeys, Context::startPublicKeyExport): Remove
+ workaround.
+
+ core: New export mode to export secret subkeys.
+ + commit 0e19c4879193ed7fa61ad5d488f237b2b5b5d1d7
+ * src/gpgme.h.in (GPGME_EXPORT_MODE_SECRET_SUBKEY): New.
+ * src/export.c (check_mode): Allow new mode and check for invalid
+ combinations.
+ (export_keys_start): Return error if new mode flag is set.
+ * src/engine-gpg.c (export_common): Implement.
+ * src/gpgme-tool.c (cmd_export): New option --secret-subkey.
+ * tests/run-export.c (main): New option --secret-subkey.
+
+ doc: Remove documentation of obsolete export mode flag.
+ + commit 414bbdd53c380018621a2a5800e9a9c46869a56e
+ * doc/gpgme.texi: Remove GPGME_EXPORT_MODE_NOUID.
+
+ core: Check for unsupported export mode flags.
+ + commit c710af223cc2476d5f4d46c00d8e0521f6c13211
+ src/engine-gpgsm.c (gpgsm_export, gpgsm_export_ext): Return error if an
+ unsupported mode flag is set.
+
+ core: Check for combination of ssh mode with other mode flags.
+ + commit c0581adabe7f5f63c0b96dac449790aa6ac4c291
+ * src/export.c (check_mode): Return error if ssh mode is combined with
+ another mode flag.
+
+ core: Factor out the check for valid export mode flags.
+ + commit 326857511587fa7878757d3884f91bf7eb86771c
+ * src/export.c (check_mode): New.
+ (export_start, export_ext_start): Call check_mode.
+
+2021-12-22 Ingo Klöcker <dev@ingo-kloecker.de>
+
+ qt: Detect an import error caused by a wrong password.
+ + commit 82f43455e9412d8b4792b35371e0b6704a619d07
+ * lang/qt/src/qgpgmeimportjob.cpp (import_qba): Check import statuses of
+ import result for bad passphrase errors.
+
+ qt,tests: Add test runner for testing the import job.
+ + commit f99451e20fd2f84ac653aa6021a475026a9d4dc9
+ * lang/qt/tests/Makefile.am (run_importjob_SOURCES): New.
+ (noinst_PROGRAMS): Add run-importjob.
+ * lang/qt/tests/run-importjob.cpp: New.
+
+ cpp: Check fpr of import status for NULL.
+ + commit 300776f39165da068757864e9cb3029f06f3be5b
+ * lang/cpp/src/importresult.cpp (GpgME::ImportResult::Private): Check
+ fpr for NULL.
+
+ core: Detect bad passphrase error on certificate import.
+ + commit 305d8668ca724982c50fe4e05315c48a20cc33e5
+ * src/import.c (gpgme_op_import_result): Check fpr for NULL.
+ (parse_error): New.
+ (import_status_handler): Handle error status line.
+
+ * doc/gpgme.texi (gpgme_import_status_t): Mention that fpr can be NULL.
+
+ * tests/gpg/t-import.c (check_result): Check fpr for NULL.
+ * tests/run-threaded.c (delete_impres): Check fpr for NULL.
+
+2021-12-22 NIIBE Yutaka <gniibe@fsij.org>
+
+ build: Update for newer autoconf.
+ + commit 0636e229d7edfcb0a357ffcce62079488be32495
+ * configure.ac (AC_PREREQ): Require >= 2.69.
+ (AC_CONFIG_HEADERS): Use it instead of AC_CONFIG_HEADER.
+
+2021-12-15 Ingo Klöcker <dev@ingo-kloecker.de>
+
+ qt: Allow specifying an import filter when importing keys.
+ + commit 619579bb172579d766956b5d1690d18934fd5986
+ * lang/qt/src/importjob.cpp (struct ImportJobPrivate): Add member
+ m_importFilter.
+ * lang/qt/src/importjob.cpp, lang/qt/src/importjob.h (class ImportJob):
+ Add member functions setImportFilter and importFilter.
+ * lang/qt/src/qgpgmeimportjob.cpp (import_qba): Add arg importFilter
+ and adjust the callers. Set import filter context flag.
+
+ * lang/qt/tests/t-import.cpp (ImportTest): Add member function
+ testImportWithImportFilter.
+
+ qt: Avoid test failure when test is run multiple times.
+ + commit 3e81a4a336e093d075f83afe3e1bd26493e64cac
+ * lang/qt/tests/t-import.cpp (ImportTest): Add member tempGpgHome and
+ member function initTestCase.
+ (keyFpr, keyData): Move to ImportTest::testImportWithKeyOrigin.
+
+ qt: Fix erroneous reuse of JobPrivate objects.
+ + commit 3c770013d7233cb0a803251af54c0a2c1fb61e35
+ * lang/qt/src/job.cpp (Job::~Job): Destroy JobPrivate object belonging
+ to destroyed job.
+
+2021-12-14 Ingo Klöcker <dev@ingo-kloecker.de>
+
+ core: Allow setting import filters when importing keys.
+ + commit d35d44efaf72f90ee4f92af8382c4bcb9982da3f
+ * src/context.h (struct gpgme_context): New field import_filter.
+ * src/engine-backend.h (struct engine_ops): Add arg import_filter to
+ field 'import'.
+ * src/engine-gpg.c (gpg_import): Add arg import_filter and pass option
+ --import-filter with argument value to gpg. Adjust all callers.
+ * src/engine-gpgsm.c (gpgsm_import): Add dummy arg import_filter.
+ * src/gpgme.c (gpgme_release): Free 'import_filter'.
+ (gpgme_set_ctx_flag, gpgme_get_ctx_flag): New flag "import-filter".
+
+ * tests/run-import.c (main): Add option --import-filter.
+
+ qt: Add pattern used for WKD lookup to result.
+ + commit af820811ec7d0818f988cd728d745cede88ab45f
+ * lang/qt/src/qgpgmewkdlookupjob.cpp (run_wkd_get): Change type of
+ arg email.
+ (lookup_keys): Add pattern to result.
+ * lang/qt/src/wkdlookupresult.h (class WKDLookupResult): Add arg
+ pattern to c'tors. Add member function pattern.
+ * lang/qt/src/wkdlookupresult.cpp (class WKDLookupResult::Private):
+ Add field pattern.
+ (WKDLookupResult::WKDLookupResult): Pass pattern to pimpl.
+ (WKDLookupResult::pattern): New.
+
+ * lang/qt/tests/t-wkdlookup.cpp (testWKDLookupAsync, testWKDLookupSync,
+ testLookupWithNoResultAsync): Check pattern.
+
+ core: Set --key-origin option only if supported by gpg.
+ + commit fd680254dae58a6bf6fb83688bf7c849257688a4
+ * src/engine-gpg.c (gpg_import): Do not pass --key-origin option to
+ gpg if gpg is too old.
+
+ qt: Allow setting key origin when importing keys.
+ + commit fd6bec617d8fb6ddcbc622a5d8cf94594a7d5520
+ * lang/qt/src/Makefile.am (qgpgme_sources): Add importjob.cpp.
+ * lang/qt/src/importjob.cpp: New.
+ * lang/qt/src/importjob.h (class ImportJob): Add member functions
+ setKeyOrigin, keyOrigin, keyOriginUrl.
+ * lang/qt/src/qgpgmeimportjob.cpp (originToString): New.
+ (import_qba): Set key origin context flag.
+ (QGpgMEImportJob::start, QGpgMEImportJob::exec): Add options to call
+ of import_qba.
+
+ * lang/qt/tests/Makefile.am (the_tests, moc_files, noinst_PROGRAMS):
+ Add new test.
+ (t_import_SOURCES): New.
+ * lang/qt/tests/t-import.cpp: New.
+
+ qt,tests: Skip WKD lookup tests by default.
+ + commit 3a43d9dc67970db323c3e49eb964d52c4eb3ac6c
+ * lang/qt/tests/t-support.cpp, lang/qt/tests/t-support.h
+ (class QGpgMETest): Add member function doOnlineTests.
+ * lang/qt/tests/t-wkdlookup.cpp (testWKDLookupAsync, testWKDLookupSync,
+ testLookupWithNoResultAsync): Skip tests if online tests are not
+ enabled.
+
+2021-12-13 Ingo Klöcker <dev@ingo-kloecker.de>
+
+ core: Allow specifiying a key origin when importing keys.
+ + commit 60880adafa93e1a1e8e9fecf03c14d56bbd55345
+ * src/context.h (struct gpgme_context): New field key_origin.
+ * src/engine-backend.h (struct engine_ops): Add arg key_origin to
+ field 'import'.
+ * src/engine-gpg.c (gpg_import): Add arg key_origin and pass option
+ --key-origin with argument value to gpg. Adjust all callers.
+ * src/engine-gpgsm.c (gpgsm_import): Add dummy arg key_origin.
+ * src/gpgme.c (gpgme_release): Free 'key_origin'.
+ (gpgme_set_ctx_flag, gpgme_get_ctx_flag): New flag "key-origin".
+
+ * tests/run-import.c (main): Add option --key-origin.
+ * tests/gpg/t-import.c (main): Set and verify key origin.
+
+ qt: Support WKD lookup without implicit import.
+ + commit ed7e7df2e14feb443e84d87e518ff61b1f7aa6d8
+ * lang/qt/src/Makefile.am (qgpgme_sources): Add qgpgmewkdlookupjob.cpp,
+ wkdlookupresult.cpp.
+ (qgpgme_headers): Add wkdlookupjob.h, wkdlookupresult.h.
+ (camelcase_headers): Add WKDLookupJob, WKDLookupResult.
+ (private_qgpgme_headers): Add qgpgmewkdlookupjob.h.
+ (qgpgme_moc_sources): Add qgpgmewkdlookupjob.moc, wkdlookupjob.moc.
+ * lang/qt/src/job.cpp: Define c'tor and d'tor of WKDLookupJob.
+ * lang/qt/src/protocol.h (Protocol::wkdLookupJob): New.
+ * lang/qt/src/protocol_p.h (Protocol::wkdLookupJob): New.
+ * lang/qt/src/qgpgmewkdlookupjob.cpp, lang/qt/src/qgpgmewkdlookupjob.h,
+ lang/qt/src/wkdlookupjob.h, lang/qt/src/wkdlookupresult.cpp,
+ lang/qt/src/wkdlookupresult.h: New.
+
+ * lang/qt/tests/Makefile.am (EXTRA_DIST): Add final.test.
+ (the_tests): New.
+ (TESTS): Remove all t-*. Add $(the_tests) and final.test.
+ (moc_files): Add t-wkdlookup.moc.
+ (t_wkdlookup_SOURCES): New.
+ (noinst_PROGRAMS): Add t-wkdlookup.
+ * lang/qt/tests/final.test: New.
+ * lang/qt/tests/t-support.h (QTest::toString): New template
+ specialization for std::string.
+ * lang/qt/tests/t-wkdlookup.cpp: New.
+
+ qt: Fix example for using the asynchronous job API.
+ + commit 0e70a2313afbbaaec6859a1edb478587ff82a6b5
+ * lang/qt/src/protocol.h (class Protocol): Fix API documentation.
+
+2021-12-10 Ingo Klöcker <dev@ingo-kloecker.de>
+
+ cpp,tests: Add test runner for doing a WKD lookup without import.
+ + commit f3177d3ee0a1d30e15f33ff226b5e4c96b7610db
+ * lang/cpp/tests/Makefile.am (run_wkdlookup_SOURCES, programs_unix):
+ New.
+ (noinst_PROGRAMS): Add $(programs_unix).
+ * lang/cpp/tests/run-wkdlookup.cpp: New.
+
+ cpp: Add new supported components to API docs of dirInfo()
+ + commit 5f1ba40116199cd77987c3c2797d600f6df018c2
+ lang/cpp/src/global.h: Update API doc of dirInfo().
+
+ core: Support all components with dirinfo()
+ + commit 0ac3679a74505b782388402b3743ee65c271340f
+ * src/dirinfo.c (WANT_KEYBOXD_NAME, WANT_AGENT_NAME, WANT_SCDAEMON_NAME,
+ WANT_DIRMNGR_NAME, WANT_PINENTRY_NAME): New.
+ (dirinfo): Add fields keyboxd_name, agent_name, scdaemon_name,
+ dirmngr_name, pinentry_name.
+ (parse_output): Support "keyboxd", "gpg-agent", "scdaemon", "dirmngr",
+ "pinentry".
+ (get_gpgconf_item): Return new components.
+
+ tests/t-engine-info.c (main): Add new components to the output.
+
+2021-12-07 Ingo Klöcker <dev@ingo-kloecker.de>
+
+ cpp: Return engine info for engine used by the context.
+ + commit 0eddc867c31dd7239a1a9c4196bf8dc1372ea4b1
+ lang/cpp/src/context.cpp (Context::engineInfo()): Return engine info
+ for protocol of context.
+
+ cpp: Factor out common code of GpgME::engineInfo() overloads.
+ + commit 1a1e9145877a60632346ae3ab68b1ae9d722a867
+ * lang/cpp/src/context.cpp (get_engine_info, get_static_engine_info):
+ New.
+ (GpgME::engineInfo(GpgME::Protocol), GpgME::engineInfo(GpgME::Engine)):
+ Use get_static_engine_info().
+
+2021-11-25 Werner Koch <wk@gnupg.org>
+
+ core: Make the gpgconf option parsing of string types more robust.
+ + commit b8b49c11e95fd978a8a2eed23f191d087ab056da
+ * src/engine-gpgconf.c (gpgconf_parse_option): Skip the string
+ indicator if it is not the empty string.
+
+ tests: Silence libtool warning on Windows.
+ + commit 43de18a292b29436783127bd6c275817f0cd86b7
+ * tests/Makefile.am (AM_LDFLAGS): Use --no-fast-install on Windows.
+
+ core: Support dirinfo("socketdir")
+ + commit eb37d6469e722ae5ff187962c216474b5ec476de
+ * src/dirinfo.c (WANT_SOCKETDIR): New.
+ (dirinfo): Add field socketdir.
+ (parse_output): Support "socketdir".
+ (get_gpgconf_item): Return socketdir.
+
+ * tests/t-engine-info.c (main): Add socketdir to the output.
+
+ * src/w32-util.c (_gpgme_create_process_utf8): Fix indentation.
+
+2021-11-25 NIIBE Yutaka <gniibe@fsij.org>
+
+ posix: Use poll instead, when available, removing use of select.
+ + commit 8148237cb4ae20755c06a44d71761c7030973c3d
+ * configure.ac (HAVE_POLL_H): Add the check.
+ * src/ath.c [!HAVE_POLL_H] (ath_select): Enable conditionally.
+ * src/posix-io.c [HAVE_POLL_H] (_gpgme_io_select_poll): Use poll.
+ * tests/gpg/t-cancel.c [HAVE_POLL_H] (do_select): Use poll.
+ * tests/gpg/t-eventloop.c [HAVE_POLL_H] (do_select): Use poll.
+
+2021-11-12 NIIBE Yutaka <gniibe@fsij.org>
+
+ gpgme.pc: Fix library dependency and use of includedir, libdir.
+ + commit 4583ab77e5af3f0da5b307a169d07b58dddf652f
+ * src/gpgme.pc.in (Require): Move gpg-error, libassuan to...
+ (Requires.private): ... here.
+ (Cflags): Add -I${includedir}.
+ (Libs): Add -L${libdir}.
+
+2021-11-12 NIIBE Yutaka <gniibe@fsij.org>
+ Ben Kibbey <bjk@luxsci.net>
+
+ tests: Build using GPG_ERROR_MT_LIBS for thread use.
+ + commit 1cedac2bba246ff411843aaef10ca8ea0a0756cf
+ * tests/gpg/Makefile.am (WITH_THREAD_CPPFLAGS): New.
+ (WITH_THREAD_LDADD): New.
+ (t_thread1_CPPFLAGS, t_thread_keylist_CPPFLAGS)
+ (t_thread_keylist_verify_CPPFLAGS)
+ (t_cancel_CPPFLAGS): Use WITH_THREAD_CPPFLAGS.
+ (t_thread1_LDADD, t_thread_keylist_LDADD)
+ (t_thread_keylist_verify_LDADD)
+ (t_cancel_LDADD): Use WITH_THREAD_LDADD.
+
+2021-11-11 NIIBE Yutaka <gniibe@fsij.org>
+
+ tests: Use GPG_ERROR_MT_LIBS for a test with threads.
+ + commit 8cd2fe7b3de4abd2331bcb637b7e2c26ce4faa29
+ * tests/Makefile.am (run_threaded_CPPFLAGS): New.
+ (run_threaded_LDADD): Replace GPG_ERROR_LIBS to GPG_ERROR_MT_LIBS.
+
+2021-11-10 NIIBE Yutaka <gniibe@fsij.org>
+
+ libtool: Link without -flat_namespace for macOS.
+ + commit 50daf3d75d666d34fecc0dbecc31c51a7989eda3
+ * m4/libtool.m4: Not setting 10.0 to MACOSX_DEPLOYMENT_TARGET when not
+ defined. Only specify -flat_namespace to linker for specific
+ (older) versions and hosts.
+
+2021-09-13 Ingo Klöcker <dev@ingo-kloecker.de>
+
+ qt: Fix build against Qt 5.9.
+ + commit ab9bca09eb869b2013c85fee232f1e62aed925f6
+ * lang/qt/tests/t-keylist.cpp (KeyListTest::testListAllKeysSync):
+ Ensure same type for both arguments of QCOMPARE.
+ * lang/qt/tests/t-various.cpp (TestVarious::testSetExpire):
+ Ensure same type for both arguments of QCOMPARE.
+
+2021-08-27 Werner Koch <wk@gnupg.org>
+
+ build: Fix make distcheck problem.
+ + commit aaf448b1e81e7421e539ac2deb9dc9d3d1459016
+ * tests/start-stop-agent: Use -f with rm. Also use cat instead of cp.
+
+2021-08-27 Andre Heinecke <aheinecke@gnupg.org>
+
+ qt: Expect UTF-8 on stderr on Windows.
+ + commit 8fe15462829b5049137b3f631564b72c4f63c5e2
+ * lang/qt/src/threadedjobmixin.cpp (stringFromGpgOutput): Expect
+ UTF-8.
+
+ Add missing files for distribution.
+ + commit bc774104bbf461805f875c2bfd2d02aa6dd0945d
+ * lang/qt/src/Makefile.am (private_qgpgme_headers): Add job_p.h
+ * tests/gpg/Makefile.am (EXTRA_DIST): Add gpg.conf.in
+
+2021-08-13 NIIBE Yutaka <gniibe@fsij.org>
+
+ core: Use flexible array member if compiler has support.
+ + commit 3c1c98a43413e429459ca7d3615659f8149534b8
+ * configure.ac (AC_C_FLEXIBLE_ARRAY_MEMBER): Add.
+ * src/engine-gpg.c (struct arg_and_data_s): Use FLEXIBLE_ARRAY_MEMBER.
+ (_add_arg): Use offsetof instead of sizeof.
+ (add_data): Likewise.
+
+2021-08-03 Ingo Klöcker <dev@ingo-kloecker.de>
+
+ core: Fix results returned by gpgme_data_* functions.
+ + commit 7cfc93193d535ec5037e48b86544e1b4dbf949f6
+ src/debug.h (TRACE_SYSRES_OFF_T, _trace_sysres_off_t,
+ TRACE_SYSRES_SSIZE_T, _trace_sysres_ssize_t): New.
+ src/data.c (gpgme_data_read, gpgme_data_write, gpgme_data_seek): Use
+ appropriate new tracing macros instead of casting the results to int.
+
+2021-07-27 Jiri Kucera <sanczes@gmail.com>
+
+ core: Support closefrom also for glibc.
+ + commit 4b64774b6d13ffa4f59dddf947a97d61bcfa2f2e
+ * src/posix-io.c (_gpgme_io_spawn): Use glibc's closefrom.
+
+2021-07-08 Ingo Klöcker <dev@ingo-kloecker.de>
+
+ core: Ensure gpg.conf for tests is recreated if necessary.
+ + commit a5662a801fc11a533fb3b1a69a17e119064972a3
+ * tests/gpg/gpg.conf.in: New.
+ * tests/gpg/Makefile.am (gpg.conf): Copy gpg.conf.in instead of using
+ echo to fill gpg.conf.
+
+ Make sure expiration time is interpreted as unsigned number.
+ + commit 6a79e90dedc19877ae1c520fed875b57089a5425
+ * lang/qt/tests/t-various.cpp (testSignKeyWithExpiration): Convert
+ expiration time to uint_least32_t.
+
+2021-06-29 Ingo Klöcker <dev@ingo-kloecker.de>
+
+ qt: Allow retrieving the default value of a config entry.
+ + commit 12006a782900687a7f0158a3f931528cfc5ff451
+ * lang/qt/src/cryptoconfig.cpp, lang/qt/src/cryptoconfig.h
+ (CryptoConfigEntry::defaultValue): New.
+ * lang/qt/src/qgpgmenewcryptoconfig.cpp,
+ lang/qt/src/qgpgmenewcryptoconfig.h
+ (QGpgMENewCryptoConfigEntry::defaultValue): New.
+ * lang/qt/tests/t-config.cpp (CryptoConfigTest::testDefault()):
+ Add test of CryptoConfigEntry::defaultValue(). Port away from deprecated
+ CryptoConfig::entry overload.
+
+2021-06-28 Ingo Klöcker <dev@ingo-kloecker.de>
+
+ Update NEWS.
+ + commit d8638ed0aa5bf7f970787155a35d37a4f5d320f8
+ * NEWS: Add changes of ChangeExpiryJob.
+
+ qt: Fix filenames in copyright headers.
+ + commit 9d2b876093c25f604d9efe2775143c8f0361916d
+ * lang/qt/src/qgpgmechangeownertrustjob.h,
+ lang/qt/tests/t-trustsignatures.cpp: Use correct filenames.
+
+ qt: Add test for ChangeExpiryJob.
+ + commit 801acd89b234fcd7226f3fb39ec01634460cfa50
+ * lang/qt/tests/Makefile.am (TESTS, moc_files, noinst_PROGRAMS): Add
+ new test.
+ (t_changeexpiryjob_SOURCES): New.
+ * lang/qt/tests/t-changeexpiryjob.cpp: New.
+
+ qt: Allow changing expiration date of primary key and all subkeys.
+ + commit 144d580607dd0b70bb20542e2f457153b9cc4ecb
+ * lang/qt/src/Makefile.am (qgpgme_sources): Add changeexpiryjob.cpp.
+ * lang/qt/src/changeexpiryjob.cpp: New.
+ * lang/qt/src/changeexpiryjob.h (enum ChangeExpiryJob::Option,
+ typedef ChangeExpiryJob::Options, ChangeExpiryJob::setOptions,
+ ChangeExpiryJob::options): New.
+ * lang/qt/src/qgpgmechangeexpiryjob.cpp (change_expiry): Update the
+ expiration date of primary key and/or some/all subkeys.
+ (QGpgMEChangeExpiryJob::start): Add options to call of change_expiry.
+ (ChangeExpiryJob::start): Moved implementation to changeexpiryjob.cpp.
+
+ qt: Add mechanism for missing d-pointer in Job.
+ + commit 3503816570a19352e4b8a81d1cd0f3a9337b8c55
+ * lang/qt/src/job_p.h: New.
+ * lang/qt/src/job.cpp (typedef JobPrivateHash, d_func, setJobPrivate,
+ getJobPrivate): New.
+
+2021-06-26 Ingo Klöcker <dev@ingo-kloecker.de>
+
+ qt: Remove superfluous trailing ';'
+ + commit ade95b25ce473a3c9ebcb77b7bd76a2fa6ed2805
+ lang/qt/src/signkeyjob.h (class SignKeyJob): Remove trailing ';' from
+ inline implemented member functions
+
+ core: Fix use-after-free issue in test.
+ + commit 81a33ea5e1b86d586b956e893a5b25c4cd41c969
+ * tests/gpg/t-edit-sign.c (sign_key, verify_key_signature): New.
+ (main): Factored out signing and verifying the result.
+
2021-06-24 Werner Koch <wk@gnupg.org>
Release 1.16.0.
diff --git a/Makefile.am b/Makefile.am
index 914d418..2bee07c 100644
--- a/Makefile.am
+++ b/Makefile.am
@@ -107,7 +107,7 @@ release:
sign-release:
+(set -e; \
- cd dist; \
+ test $$(pwd | sed 's,.*/,,') = dist || cd dist; \
x=$$(grep '^RELEASE_ARCHIVE=' $$HOME/.gnupg-autogen.rc|cut -d= -f2);\
if [ -z "$$x" ]; then \
echo "error: RELEASE_ARCHIVE missing in ~/.gnupg-autogen.rc">&2; \
diff --git a/Makefile.in b/Makefile.in
index bcc36e5..739a66b 100644
--- a/Makefile.in
+++ b/Makefile.in
@@ -1013,7 +1013,7 @@ release:
sign-release:
+(set -e; \
- cd dist; \
+ test $$(pwd | sed 's,.*/,,') = dist || cd dist; \
x=$$(grep '^RELEASE_ARCHIVE=' $$HOME/.gnupg-autogen.rc|cut -d= -f2);\
if [ -z "$$x" ]; then \
echo "error: RELEASE_ARCHIVE missing in ~/.gnupg-autogen.rc">&2; \
diff --git a/NEWS b/NEWS
index 0cae3f2..87ae6ab 100644
--- a/NEWS
+++ b/NEWS
@@ -1,3 +1,73 @@
+Noteworthy changes in version 1.17.0 (2022-02-07)
+-------------------------------------------------
+
+ * New context flag "key-origin". [#5733]
+
+ * New context flag "import-filter". [#5739]
+
+ * New export mode to export secret subkeys. [#5757]
+
+ * Detect errors during the export of secret keys. [#5766]
+
+ * New function gpgme_op_receive_keys to import keys from a keyserver
+ without first running a key listing. [#5808]
+
+ * Detect bad passphrase error in certificate import. [T5713]
+
+ * Allow setting --key-origin when importing keys. [T5733]
+
+ * Support components "keyboxd", "gpg-agent", "scdaemon", "dirmngr",
+ "pinentry", and "socketdir" in gpgme_get_dirinfo. [T5727,T5613]
+
+ * Under Unix use poll(2) instead of select(2), when available.
+ [T2385]
+
+ * Do not use --flat_namespace when linking for macOS. [T5610]
+
+ * Fix results returned by gpgme_data_* functions. [T5481]
+
+ * Support closefrom also for glibc. [rM4b64774b6d]
+
+ * cpp,qt: Add support for export of secret keys and secret subkeys.
+ [#5757]
+
+ * cpp,qt: Support for adding existing subkeys to other keys. [#5770]
+
+ * qt: Extend ChangeExpiryJob to change expiration of primary key
+ and of subkeys at the same time. [#4717]
+
+ * qt: Expect UTF-8 on stderr on Windows. [rM8fe1546282]
+
+ * qt: Allow retrieving the default value of a config entry. [T5515]
+
+ * Interface changes relative to the 1.16.0 release:
+ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+ gpgme_op_receive_keys NEW.
+ gpgme_op_receive_keys_start NEW.
+ qt: Protocol::secretSubkeyExportJob NEW.
+ cpp: Context::exportSecretSubkeys NEW.
+ cpp: Context::startSecretSubkeyExport NEW.
+ qt: Protocol::secretKeyExportJob CHANGED: Param 'charset' is ignored.
+ cpp: Context::exportKeys NEW.
+ cpp: Context::startKeyExport NEW.
+ cpp: Context::exportSecretKeys NEW.
+ cpp: Context::startSecretKeyExport NEW.
+ cpp: GpgAddExistingSubkeyEditInteractor NEW.
+ GPGME_EXPORT_MODE_SECRET_SUBKEY NEW.
+ gpgme_set_ctx_flag EXTENDED: New flag 'key-origin'.
+ gpgme_set_ctx_flag EXTENDED: New flag 'import-filter'.
+ qt: ChangeExpiryJob::Option NEW.
+ qt: ChangeExpiryJob::Options NEW.
+ qt: ChangeExpiryJob::setOptions NEW.
+ qt: ChangeExpiryJob::options NEW.
+ qt: AddExistingSubkeyJob NEW.
+ qt: Protocol::addExistingSubkeyJob NEW.
+
+ [c=C37/A26/R0 cpp=C20/A14/R0 qt=C14/A7/R0]
+
+ Release-info: https://dev.gnupg.org/T5819
+
+
Noteworthy changes in version 1.16.0 (2021-06-24)
-------------------------------------------------
diff --git a/VERSION b/VERSION
index 15b989e..092afa1 100644
--- a/VERSION
+++ b/VERSION
@@ -1 +1 @@
-1.16.0
+1.17.0
diff --git a/conf/config.h.in b/conf/config.h.in
index b89676c..3176adc 100644
--- a/conf/config.h.in
+++ b/conf/config.h.in
@@ -12,6 +12,15 @@
/* Locate binaries only via this PATH */
#undef FIXED_SEARCH_PATH
+/* Define to nothing if C supports flexible array members, and to 1 if it does
+ not. That way, with a declaration like `struct s { int n; double
+ d[FLEXIBLE_ARRAY_MEMBER]; };', the struct hack can be used with pre-C99
+ compilers. When computing the size of such an object, don't use 'sizeof
+ (struct s)' as it overestimates the size. Use 'offsetof (struct s, d)'
+ instead. Don't use 'offsetof (struct s, d[0])', as this doesn't work with
+ MSVC and with C++ compilers. */
+#undef FLEXIBLE_ARRAY_MEMBER
+
/* version of the libassuan library */
#undef GPGME_LIBASSUAN_VERSION
@@ -71,6 +80,9 @@
/* Define to 1 if you have the <memory.h> header file. */
#undef HAVE_MEMORY_H
+/* Define to 1 if you have the <poll.h> header file. */
+#undef HAVE_POLL_H
+
/* Define if the ttyname_r function has a POSIX compliant declaration. */
#undef HAVE_POSIXDECL_TTYNAME_R
diff --git a/configure b/configure
index f307736..91b16e3 100755
--- a/configure
+++ b/configure
@@ -1,6 +1,6 @@
#! /bin/sh
# Guess values for system-dependent variables and create Makefiles.
-# Generated by GNU Autoconf 2.69 for gpgme 1.16.0.
+# Generated by GNU Autoconf 2.69 for gpgme 1.17.0.
#
# Report bugs to <https://bugs.gnupg.org>.
#
@@ -590,8 +590,8 @@ MAKEFLAGS=
# Identity of this package.
PACKAGE_NAME='gpgme'
PACKAGE_TARNAME='gpgme'
-PACKAGE_VERSION='1.16.0'
-PACKAGE_STRING='gpgme 1.16.0'
+PACKAGE_VERSION='1.17.0'
+PACKAGE_STRING='gpgme 1.17.0'
PACKAGE_BUGREPORT='https://bugs.gnupg.org'
PACKAGE_URL=''
@@ -1469,7 +1469,7 @@ if test "$ac_init_help" = "long"; then
# Omit some internal or obsolete options to make the list less imposing.
# This message is too long to be a string in the A/UX 3.1 sh.
cat <<_ACEOF
-\`configure' configures gpgme 1.16.0 to adapt to many kinds of systems.
+\`configure' configures gpgme 1.17.0 to adapt to many kinds of systems.
Usage: $0 [OPTION]... [VAR=VALUE]...
@@ -1540,7 +1540,7 @@ fi
if test -n "$ac_init_help"; then
case $ac_init_help in
- short | recursive ) echo "Configuration of gpgme 1.16.0:";;
+ short | recursive ) echo "Configuration of gpgme 1.17.0:";;
esac
cat <<\_ACEOF
@@ -1690,7 +1690,7 @@ fi
test -n "$ac_init_help" && exit $ac_status
if $ac_init_version; then
cat <<\_ACEOF
-gpgme configure 1.16.0
+gpgme configure 1.17.0
generated by GNU Autoconf 2.69
Copyright (C) 2012 Free Software Foundation, Inc.
@@ -2520,7 +2520,7 @@ cat >config.log <<_ACEOF
This file contains any messages produced by compilers while
running configure, to aid debugging if configure makes a mistake.
-It was created by gpgme $as_me 1.16.0, which was
+It was created by gpgme $as_me 1.17.0, which was
generated by GNU Autoconf 2.69. Invocation command line was
$ $0 $@
@@ -2806,6 +2806,7 @@ as_fn_append ac_header_list " sys/uio.h"
as_fn_append ac_header_list " argp.h"
as_fn_append ac_header_list " stdint.h"
as_fn_append ac_header_list " unistd.h"
+as_fn_append ac_header_list " poll.h"
as_fn_append ac_header_list " sys/time.h"
as_fn_append ac_header_list " sys/types.h"
as_fn_append ac_header_list " sys/stat.h"
@@ -2884,19 +2885,19 @@ ac_compiler_gnu=$ac_cv_c_compiler_gnu
# (Interfaces added: AGE++)
# (Interfaces removed: AGE=0)
#
-LIBGPGME_LT_CURRENT=36
-LIBGPGME_LT_AGE=25
+LIBGPGME_LT_CURRENT=37
+LIBGPGME_LT_AGE=26
LIBGPGME_LT_REVISION=0
# If there is an ABI break in gpgmepp or qgpgme also bump the
# version in IMPORTED_LOCATION in the GpgmeppConfig-w32.cmake.in.in
-LIBGPGMEPP_LT_CURRENT=19
-LIBGPGMEPP_LT_AGE=13
+LIBGPGMEPP_LT_CURRENT=20
+LIBGPGMEPP_LT_AGE=14
LIBGPGMEPP_LT_REVISION=0
-LIBQGPGME_LT_CURRENT=13
-LIBQGPGME_LT_AGE=6
+LIBQGPGME_LT_CURRENT=14
+LIBQGPGME_LT_AGE=7
LIBQGPGME_LT_REVISION=0
################################################
@@ -2922,7 +2923,7 @@ NEED_LIBASSUAN_VERSION=2.4.2
VERSION_MAJOR=1
-VERSION_MINOR=16
+VERSION_MINOR=17
VERSION_MICRO=0
ac_aux_dir=
@@ -3439,7 +3440,7 @@ fi
# Define the identity of the package.
PACKAGE='gpgme'
- VERSION='1.16.0'
+ VERSION='1.17.0'
cat >>confdefs.h <<_ACEOF
@@ -6499,7 +6500,7 @@ test -n "$GITLOG_TO_CHANGELOG" || GITLOG_TO_CHANGELOG="gitlog-to-changelog"
-VERSION_NUMBER=0x011000
+VERSION_NUMBER=0x011100
# We need to compile and run a program on the build machine. A
@@ -9584,16 +9585,11 @@ $as_echo "$lt_cv_ld_force_load" >&6; }
_lt_dar_allow_undefined='${wl}-undefined ${wl}suppress' ;;
darwin1.*)
_lt_dar_allow_undefined='${wl}-flat_namespace ${wl}-undefined ${wl}suppress' ;;
- darwin*) # darwin 5.x on
- # if running on 10.5 or later, the deployment target defaults
- # to the OS version, if on x86, and 10.4, the deployment
- # target defaults to 10.4. Don't you love it?
- case ${MACOSX_DEPLOYMENT_TARGET-10.0},$host in
- 10.0,*86*-darwin8*|10.0,*-darwin[91]*)
- _lt_dar_allow_undefined='${wl}-undefined ${wl}dynamic_lookup' ;;
- 10.[012]*)
+ darwin*)
+ case ${MACOSX_DEPLOYMENT_TARGET},$host in
+ 10.[012]*,*|,*powerpc*)
_lt_dar_allow_undefined='${wl}-flat_namespace ${wl}-undefined ${wl}suppress' ;;
- 10.*)
+ *)
_lt_dar_allow_undefined='${wl}-undefined ${wl}dynamic_lookup' ;;
esac
;;
@@ -24566,7 +24562,7 @@ ENABLED_LANGUAGES=$enabled_languages
#
# Provide information about the build.
#
-BUILD_REVISION="1021c864"
+BUILD_REVISION="72bb46b3"
cat >>confdefs.h <<_ACEOF
@@ -24575,7 +24571,7 @@ _ACEOF
BUILD_VERSION=`echo "$PACKAGE_VERSION" | sed 's/\([0-9.]*\).*/\1./'`
-BUILD_VERSION="${BUILD_VERSION}4129"
+BUILD_VERSION="${BUILD_VERSION}29371"
BUILD_FILEVERSION=`echo "${BUILD_VERSION}" | tr . ,`
@@ -24702,6 +24698,8 @@ done
+
+
# Type checks.
{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for inline" >&5
$as_echo_n "checking for inline... " >&6; }
@@ -24745,6 +24743,48 @@ _ACEOF
;;
esac
+
+ { $as_echo "$as_me:${as_lineno-$LINENO}: checking for flexible array members" >&5
+$as_echo_n "checking for flexible array members... " >&6; }
+if ${ac_cv_c_flexmember+:} false; then :
+ $as_echo_n "(cached) " >&6
+else
+ cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h. */
+#include <stdlib.h>
+ #include <stdio.h>
+ #include <stddef.h>
+ struct s { int n; double d[]; };
+int
+main ()
+{
+int m = getchar ();
+ struct s *p = malloc (offsetof (struct s, d)
+ + m * sizeof (double));
+ p->d[0] = 0.0;
+ return p->d != (double *) NULL;
+ ;
+ return 0;
+}
+_ACEOF
+if ac_fn_c_try_compile "$LINENO"; then :
+ ac_cv_c_flexmember=yes
+else
+ ac_cv_c_flexmember=no
+fi
+rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
+fi
+{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_c_flexmember" >&5
+$as_echo "$ac_cv_c_flexmember" >&6; }
+ if test $ac_cv_c_flexmember = yes; then
+
+$as_echo "#define FLEXIBLE_ARRAY_MEMBER /**/" >>confdefs.h
+
+ else
+ $as_echo "#define FLEXIBLE_ARRAY_MEMBER 1" >>confdefs.h
+
+ fi
+
# The cast to long int works around a bug in the HP C Compiler
# version HP92453-01 B.11.11.23709.GP, which incorrectly rejects
# declarations like `int a3[[(sizeof (unsigned char)) >= 0]];'.
@@ -26928,7 +26968,7 @@ cat >>$CONFIG_STATUS <<\_ACEOF || ac_write_fail=1
# report actual input values of CONFIG_FILES etc. instead of their
# values after options handling.
ac_log="
-This file was extended by gpgme $as_me 1.16.0, which was
+This file was extended by gpgme $as_me 1.17.0, which was
generated by GNU Autoconf 2.69. Invocation command line was
CONFIG_FILES = $CONFIG_FILES
@@ -26994,7 +27034,7 @@ _ACEOF
cat >>$CONFIG_STATUS <<_ACEOF || ac_write_fail=1
ac_cs_config="`$as_echo "$ac_configure_args" | sed 's/^ //; s/[\\""\`\$]/\\\\&/g'`"
ac_cs_version="\\
-gpgme config.status 1.16.0
+gpgme config.status 1.17.0
configured by $0, generated by GNU Autoconf 2.69,
with options \\"\$ac_cs_config\\"
@@ -29320,7 +29360,7 @@ fi
echo "
GPGME v${VERSION} has been configured as follows:
- Revision: 1021c864 (4129)
+ Revision: 72bb46b3 (29371)
Platform: $host
UI Server: $uiserver
diff --git a/configure.ac b/configure.ac
index 4d32366..80ce79c 100644
--- a/configure.ac
+++ b/configure.ac
@@ -19,7 +19,7 @@
# SPDX-License-Identifier: LGPL-2.1-or-later
# (Process this file with autoconf to produce a configure script.)
-AC_PREREQ([2.59])
+AC_PREREQ([2.69])
min_automake_version="1.14"
# To build a release you need to create a tag with the version number
@@ -31,7 +31,7 @@ min_automake_version="1.14"
# for the LT versions.
m4_define([mym4_package],[gpgme])
m4_define([mym4_major], [1])
-m4_define([mym4_minor], [16])
+m4_define([mym4_minor], [17])
m4_define([mym4_micro], [0])
# Below is m4 magic to extract and compute the git revision number,
@@ -53,19 +53,19 @@ AC_INIT([mym4_package],[mym4_version],[https://bugs.gnupg.org])
# (Interfaces added: AGE++)
# (Interfaces removed: AGE=0)
#
-LIBGPGME_LT_CURRENT=36
-LIBGPGME_LT_AGE=25
+LIBGPGME_LT_CURRENT=37
+LIBGPGME_LT_AGE=26
LIBGPGME_LT_REVISION=0
# If there is an ABI break in gpgmepp or qgpgme also bump the
# version in IMPORTED_LOCATION in the GpgmeppConfig-w32.cmake.in.in
-LIBGPGMEPP_LT_CURRENT=19
-LIBGPGMEPP_LT_AGE=13
+LIBGPGMEPP_LT_CURRENT=20
+LIBGPGMEPP_LT_AGE=14
LIBGPGMEPP_LT_REVISION=0
-LIBQGPGME_LT_CURRENT=13
-LIBQGPGME_LT_AGE=6
+LIBQGPGME_LT_CURRENT=14
+LIBQGPGME_LT_AGE=7
LIBQGPGME_LT_REVISION=0
################################################
@@ -96,8 +96,8 @@ VERSION_MICRO=mym4_micro
AC_CONFIG_AUX_DIR([build-aux])
AC_CONFIG_MACRO_DIR([m4])
-AC_CONFIG_SRCDIR(src/gpgme.h.in)
-AC_CONFIG_HEADER(conf/config.h)
+AC_CONFIG_SRCDIR([src/gpgme.h.in])
+AC_CONFIG_HEADERS([conf/config.h])
AM_INIT_AUTOMAKE([serial-tests dist-bzip2 no-dist-gzip])
AM_MAINTAINER_MODE
AC_CANONICAL_HOST
@@ -538,11 +538,12 @@ AM_CONDITIONAL(RUN_G13_TESTS, test "$run_g13_test" = "yes")
# Checks for header files.
AC_CHECK_HEADERS_ONCE([locale.h sys/select.h sys/uio.h argp.h stdint.h
- unistd.h sys/time.h sys/types.h sys/stat.h])
+ unistd.h poll.h sys/time.h sys/types.h sys/stat.h])
# Type checks.
AC_C_INLINE
+AC_C_FLEXIBLE_ARRAY_MEMBER
AC_CHECK_SIZEOF(unsigned int)
AC_SYS_LARGEFILE
AC_TYPE_OFF_T
diff --git a/doc/defsincdate b/doc/defsincdate
index 683840f..b8cb3c6 100644
--- a/doc/defsincdate
+++ b/doc/defsincdate
@@ -1 +1 @@
-1624372503
+1643900190
diff --git a/doc/gpgme.info b/doc/gpgme.info
index 0008e70..4c70883 100644
--- a/doc/gpgme.info
+++ b/doc/gpgme.info
@@ -19,8 +19,8 @@ END-INFO-DIR-ENTRY
This file documents the GPGME library.
- This is Edition 1.15.2-beta35, last updated 13 December 2019, of ‘The
-‘GnuPG Made Easy’ Reference Manual’, for Version 1.15.2-beta35.
+ This is Edition 1.17.0, last updated 3 February 2022, of ‘The ‘GnuPG
+Made Easy’ Reference Manual’, for Version 1.17.0.
Copyright © 2002–2008, 2010, 2012–2018 g10 Code GmbH.
@@ -37,129 +37,129 @@ Public License for more details.

Indirect:
-gpgme.info-1: 1688
-gpgme.info-2: 303542
+gpgme.info-1: 1673
+gpgme.info-2: 303842

Tag Table:
(Indirect)
-Node: Top1688
-Node: Introduction9067
-Node: Getting Started9857
-Node: Features11318
-Node: Overview12630
-Node: Preparation13739
-Node: Header14736
-Node: Building the Source15483
-Node: Largefile Support (LFS)17627
-Node: Using Automake23043
-Node: Using Libtool25596
-Node: Library Version Check25958
-Node: Signal Handling32018
-Node: Multi-Threading33288
-Ref: Multi-Threading-Footnote-134704
-Node: Protocols and Engines35127
-Node: Engine Version Check37878
-Node: Engine Information40401
-Node: Engine Configuration44261
-Node: OpenPGP45565
-Node: Cryptographic Message Syntax45905
-Node: Assuan46218
-Node: Algorithms46592
-Ref: Algorithms-Footnote-147071
-Node: Public Key Algorithms47199
-Node: Hash Algorithms49801
-Node: Error Handling51015
-Node: Error Values52889
-Node: Error Sources58092
-Node: Error Codes60532
-Node: Error Strings65325
-Node: Exchanging Data67132
-Node: Creating Data Buffers69017
-Node: Memory Based Data Buffers69533
-Node: File Based Data Buffers72966
-Node: Callback Based Data Buffers76079
-Node: Destroying Data Buffers80270
-Node: Manipulating Data Buffers81777
-Node: Data Buffer I/O Operations82269
-Node: Data Buffer Meta-Data84642
-Node: Data Buffer Convenience89961
-Node: Contexts92181
-Node: Creating Contexts93300
-Node: Destroying Contexts94147
-Node: Result Management94486
-Node: Context Attributes96067
-Node: Protocol Selection97234
-Node: Crypto Engine98280
-Node: Setting the Sender100169
-Node: ASCII Armor101682
-Node: Text Mode102311
-Node: Offline Mode103245
-Node: Pinentry Mode104743
-Node: Included Certificates106637
-Node: Key Listing Mode108083
-Node: Passphrase Callback113207
-Node: Progress Meter Callback116769
-Node: Status Message Callback118754
-Node: Context Flags120519
-Node: Locale127446
-Node: Additional Logs129038
-Node: Key Management131236
-Node: Key objects132460
-Node: Listing Keys147464
-Node: Information About Keys156117
-Node: Manipulating Keys157425
-Node: Generating Keys160323
-Node: Signing Keys178643
-Node: Exporting Keys184402
-Node: Importing Keys191682
-Ref: Importing Keys-Footnote-1199085
-Node: Deleting Keys199213
-Node: Changing Passphrases201493
-Node: Changing TOFU Data202820
-Node: Advanced Key Editing204928
-Node: Crypto Operations207661
-Node: Decrypt208918
-Node: Verify216198
-Node: Decrypt and Verify229291
-Node: Sign232146
-Node: Selecting Signers232710
-Node: Creating a Signature234116
-Node: Signature Notation Data238886
-Node: Encrypt241171
-Node: Encrypting a Plaintext241527
-Node: Miscellaneous255939
-Node: Running other Programs256351
-Node: Using the Assuan protocol258514
-Node: Checking for updates261312
-Node: Run Control266129
-Node: Waiting For Completion266873
-Node: Using External Event Loops268998
-Node: I/O Callback Interface270970
-Node: Registering I/O Callbacks275898
-Node: I/O Callback Example277937
-Node: I/O Callback Example GTK+284562
-Node: I/O Callback Example GDK286351
-Node: I/O Callback Example Qt287993
-Node: Cancellation290281
-Node: UI Server Protocol292589
-Ref: UI Server Protocol-Footnote-1294024
-Node: UI Server Encrypt294143
-Node: UI Server Sign299501
-Node: UI Server Decrypt303542
-Node: UI Server Verify305197
-Node: UI Server Set Input Files308769
-Node: UI Server Sign/Encrypt Files309839
-Node: UI Server Verify/Decrypt Files311647
-Node: UI Server Import/Export Keys313523
-Node: UI Server Checksum Files314585
-Node: Miscellaneous UI Server Commands316803
-Ref: command SENDER318734
-Node: Debugging320436
-Node: Deprecated Functions322185
-Node: Library Copying345194
-Node: Copying373414
-Node: Concept Index411164
-Node: Function and Data Index425876
+Node: Top1673
+Node: Introduction9037
+Node: Getting Started9827
+Node: Features11288
+Node: Overview12600
+Node: Preparation13709
+Node: Header14706
+Node: Building the Source15453
+Node: Largefile Support (LFS)17597
+Node: Using Automake23013
+Node: Using Libtool25566
+Node: Library Version Check25928
+Node: Signal Handling31988
+Node: Multi-Threading33258
+Ref: Multi-Threading-Footnote-134674
+Node: Protocols and Engines35097
+Node: Engine Version Check37848
+Node: Engine Information40731
+Node: Engine Configuration44591
+Node: OpenPGP45895
+Node: Cryptographic Message Syntax46235
+Node: Assuan46548
+Node: Algorithms46922
+Ref: Algorithms-Footnote-147401
+Node: Public Key Algorithms47529
+Node: Hash Algorithms50131
+Node: Error Handling51345
+Node: Error Values53219
+Node: Error Sources58422
+Node: Error Codes60862
+Node: Error Strings65655
+Node: Exchanging Data67462
+Node: Creating Data Buffers69347
+Node: Memory Based Data Buffers69863
+Node: File Based Data Buffers73296
+Node: Callback Based Data Buffers76409
+Node: Destroying Data Buffers80600
+Node: Manipulating Data Buffers82107
+Node: Data Buffer I/O Operations82599
+Node: Data Buffer Meta-Data84972
+Node: Data Buffer Convenience90291
+Node: Contexts92511
+Node: Creating Contexts93630
+Node: Destroying Contexts94477
+Node: Result Management94816
+Node: Context Attributes96397
+Node: Protocol Selection97564
+Node: Crypto Engine98610
+Node: Setting the Sender100499
+Node: ASCII Armor102012
+Node: Text Mode102641
+Node: Offline Mode103575
+Node: Pinentry Mode105073
+Node: Included Certificates106967
+Node: Key Listing Mode108413
+Node: Passphrase Callback113537
+Node: Progress Meter Callback117099
+Node: Status Message Callback119084
+Node: Context Flags120849
+Node: Locale128340
+Node: Additional Logs129932
+Node: Key Management132130
+Node: Key objects133354
+Node: Listing Keys148360
+Node: Information About Keys157013
+Node: Manipulating Keys158321
+Node: Generating Keys161219
+Node: Signing Keys179539
+Node: Exporting Keys185298
+Node: Importing Keys192887
+Ref: Importing Keys-Footnote-1201753
+Node: Deleting Keys201881
+Node: Changing Passphrases204161
+Node: Changing TOFU Data205488
+Node: Advanced Key Editing207596
+Node: Crypto Operations210329
+Node: Decrypt211586
+Node: Verify218866
+Node: Decrypt and Verify231959
+Node: Sign234814
+Node: Selecting Signers235378
+Node: Creating a Signature236784
+Node: Signature Notation Data241554
+Node: Encrypt243839
+Node: Encrypting a Plaintext244195
+Node: Miscellaneous258607
+Node: Running other Programs259019
+Node: Using the Assuan protocol261182
+Node: Checking for updates263980
+Node: Run Control268797
+Node: Waiting For Completion269541
+Node: Using External Event Loops271666
+Node: I/O Callback Interface273638
+Node: Registering I/O Callbacks278566
+Node: I/O Callback Example280605
+Node: I/O Callback Example GTK+287230
+Node: I/O Callback Example GDK289019
+Node: I/O Callback Example Qt290661
+Node: Cancellation292949
+Node: UI Server Protocol295257
+Ref: UI Server Protocol-Footnote-1296692
+Node: UI Server Encrypt296811
+Node: UI Server Sign303842
+Node: UI Server Decrypt306195
+Node: UI Server Verify307850
+Node: UI Server Set Input Files311422
+Node: UI Server Sign/Encrypt Files312492
+Node: UI Server Verify/Decrypt Files314300
+Node: UI Server Import/Export Keys316176
+Node: UI Server Checksum Files317238
+Node: Miscellaneous UI Server Commands319456
+Ref: command SENDER321387
+Node: Debugging323089
+Node: Deprecated Functions324838
+Node: Library Copying347847
+Node: Copying376067
+Node: Concept Index413817
+Node: Function and Data Index428529

End Tag Table
diff --git a/doc/gpgme.info-1 b/doc/gpgme.info-1
index 2014184..03fb2f5 100644
--- a/doc/gpgme.info-1
+++ b/doc/gpgme.info-1
@@ -19,8 +19,8 @@ END-INFO-DIR-ENTRY
This file documents the GPGME library.
- This is Edition 1.15.2-beta35, last updated 13 December 2019, of ‘The
-‘GnuPG Made Easy’ Reference Manual’, for Version 1.15.2-beta35.
+ This is Edition 1.17.0, last updated 3 February 2022, of ‘The ‘GnuPG
+Made Easy’ Reference Manual’, for Version 1.17.0.
Copyright © 2002–2008, 2010, 2012–2018 g10 Code GmbH.
@@ -41,9 +41,8 @@ File: gpgme.info, Node: Top, Next: Introduction, Up: (dir)
Main Menu
*********
-This is Edition 1.15.2-beta35, last updated 13 December 2019, of ‘The
-‘GnuPG Made Easy’ Reference Manual’, for Version 1.15.2-beta35 of the
-GPGME library.
+This is Edition 1.17.0, last updated 3 February 2022, of ‘The ‘GnuPG
+Made Easy’ Reference Manual’, for Version 1.17.0 of the GPGME library.
* Menu:
@@ -905,6 +904,21 @@ File: gpgme.info, Node: Engine Version Check, Next: Engine Information, Up: P
‘g13-name’
Return the name of the file container encryption engine.
+ ‘keyboxd-name’
+ Return the name of the key database daemon.
+
+ ‘agent-name’
+ Return the name of gpg-agent.
+
+ ‘scdaemon-name’
+ Return the name of the smart card daemon.
+
+ ‘dirmngr-name’
+ Return the name of dirmngr.
+
+ ‘pinentry-name’
+ Return the name of the pinentry program.
+
‘gpg-wks-client-name’
Return the name of the Web Key Service tool.
@@ -2990,6 +3004,18 @@ File: gpgme.info, Node: Context Flags, Next: Locale, Prev: Status Message Cal
expiration. Valid values are documented in the GnuPG manual
and the gpg man page under the option ‘--default-cert-expire’.
+ ‘"key-origin"’
+ SINCE: 1.16.1 The string given in VALUE is passed to the GnuPG
+ engine to set the origin of imported keys. Valid values are
+ documented in the GnuPG manual and the gpg man page under the
+ option ‘--key-origin’.
+
+ ‘"import-filter"’
+ SINCE: 1.16.1 The string given in VALUE is passed to the GnuPG
+ engine to use as filter when importing keys. Valid values are
+ documented in the GnuPG manual and the gpg man page under the
+ option ‘--import-filter’.
+
This function returns ‘0’ on success.
-- Function: const char * gpgme_get_ctx_flag (gpgme_ctx_t CTX,
@@ -3421,7 +3447,7 @@ long as the key object itself is valid.
The tofu info structure has the following members:
- ‘gpgme_key_sig_t next’
+ ‘gpgme_tofu_info_t next’
This is a pointer to the next tofu info structure in the
linked list, or ‘NULL’ if this is the last element.
@@ -4459,6 +4485,16 @@ or-ed together.
This may not be combined with ‘GPGME_EXPORT_MODE_EXTERN’. For
X.509 the export format is PKCS#8.
+‘GPGME_EXPORT_MODE_SECRET_SUBKEY’
+ SINCE: 1.17.0
+
+ If this bit is set, then a secret subkey is exported. The subkey
+ to export must be specified with fingerprint pattern with an
+ appended exclamation mark. This is currently only allowed for
+ OpenPGP keys. This flag may not be combined with
+ ‘GPGME_EXPORT_MODE_EXTERN’. This flag is not supported by the
+ export functions that take an array of keys.
+
‘GPGME_EXPORT_MODE_RAW’
SINCE: 1.6.0
@@ -4473,10 +4509,6 @@ or-ed together.
key the export format will be changed to PKCS#12 which also
includes the certificate. This flag may not be used with OpenPGP.
-‘GPGME_EXPORT_MODE_NOUID’
- SINCE: 1.12.0 - experimental Do not export user ids. Works only
- with certain gpg version.
-
-- Function: gpgme_error_t gpgme_op_export (gpgme_ctx_t CTX,
const char *PATTERN, gpgme_export_mode_t MODE,
gpgme_data_t KEYDATA)
@@ -4600,9 +4632,9 @@ Importing keys means the same as running ‘gpg’ with the command
retrieved with ‘gpgme_op_import_result’.
The function returns the error code ‘GPG_ERR_NO_ERROR’ if the
- import was completed successfully, ‘GPG_ERR_INV_VALUE’ if KEYDATA
- if CTX or KEYDATA is not a valid pointer, and ‘GPG_ERR_NO_DATA’ if
- KEYDATA is an empty data buffer.
+ import was completed successfully, ‘GPG_ERR_INV_VALUE’ if CTX or
+ KEYDATA is not a valid pointer, and ‘GPG_ERR_NO_DATA’ if KEYDATA is
+ an empty data buffer.
-- Function: gpgme_error_t gpgme_op_import_start (gpgme_ctx_t CTX,
gpgme_data_t KEYDATA)
@@ -4642,8 +4674,8 @@ Importing keys means the same as running ‘gpg’ with the command
The function returns the error code ‘GPG_ERR_NO_ERROR’ if the
import was completed successfully, ‘GPG_ERR_INV_VALUE’ if CTX is
not a valid pointer, ‘GPG_ERR_CONFLICT’ if the key listing mode
- does not match, and ‘GPG_ERR_NO_DATA’ if no keys are considered for
- export.
+ does not match, and ‘GPG_ERR_NO_DATA’ if no keys were considered
+ for import.
-- Function: gpgme_error_t gpgme_op_import_keys_start (gpgme_ctx_t CTX,
gpgme_key_t *KEYS)
@@ -4654,10 +4686,40 @@ Importing keys means the same as running ‘gpg’ with the command
‘gpgme_wait’ on the context. *Note Waiting For Completion::.
The function returns the error code ‘GPG_ERR_NO_ERROR’ if the
- import was completed successfully, ‘GPG_ERR_INV_VALUE’ if KEYDATA
- if CTX or KEYDATA is not a valid pointer, ‘GPG_ERR_CONFLICT’ if the
- key listing mode does not match, and ‘GPG_ERR_NO_DATA’ if no keys
- are considered for export.
+ import was started successfully, ‘GPG_ERR_INV_VALUE’ if CTX is not
+ a valid pointer, ‘GPG_ERR_CONFLICT’ if the key listing mode does
+ not match, and ‘GPG_ERR_NO_DATA’ if no keys were considered for
+ import.
+
+ -- Function: gpgme_error_t gpgme_op_receive_keys (gpgme_ctx_t CTX,
+ const char *KEYIDS[])
+ SINCE: 1.17.0
+
+ The function ‘gpgme_op_receive_keys’ adds the keys described by the
+ ‘NULL’ terminated array KEYIDS to the key ring of the crypto engine
+ used by CTX. It is used to retrieve and import keys from an
+ external source. This function currently works only for OpenPGP.
+
+ After the operation completed successfully, the result can be
+ retrieved with ‘gpgme_op_import_result’.
+
+ The function returns the error code ‘GPG_ERR_NO_ERROR’ if the
+ import was completed successfully, ‘GPG_ERR_INV_VALUE’ if CTX is
+ not a valid pointer, and ‘GPG_ERR_NO_DATA’ if no keys were
+ considered for import.
+
+ -- Function: gpgme_error_t gpgme_op_receive_keys_start
+ (gpgme_ctx_t CTX, const char *KEYIDS[])
+ SINCE: 1.17.0
+
+ The function ‘gpgme_op_receive_keys_start’ initiates a
+ ‘gpgme_op_receive_keys’ operation. It can be completed by calling
+ ‘gpgme_wait’ on the context. *Note Waiting For Completion::.
+
+ The function returns the error code ‘GPG_ERR_NO_ERROR’ if the
+ import was started successfully, ‘GPG_ERR_INV_VALUE’ if CTX is not
+ a valid pointer, and ‘GPG_ERR_NO_DATA’ if no keys were considered
+ for import.
-- Data type: gpgme_import_status_t
This is a pointer to a structure used to store a part of the result
@@ -4670,7 +4732,9 @@ Importing keys means the same as running ‘gpg’ with the command
list, or ‘NULL’ if this is the last element.
‘char *fpr’
- This is the fingerprint of the key that was considered.
+ This is the fingerprint of the key that was considered, or
+ ‘NULL’ if the fingerprint of the key is not known, e.g.
+ because the key to import was encrypted and decryption failed.
‘gpgme_error_t result’
If the import was not successful, this is the error value that
@@ -7248,54 +7312,3 @@ indicated by a C:, server responses by C::
C: ENCRYPT
S: OK
-
-File: gpgme.info, Node: UI Server Sign, Next: UI Server Decrypt, Prev: UI Server Encrypt, Up: UI Server Protocol
-
-A.2 UI Server: Sign a Message
-=============================
-
-The server needs to implement opaque signing as well as detached
-signing. Due to the nature of OpenPGP messages it is always required to
-send the entire message to the server; sending just the hash is not
-possible. The following two commands are required to set the input and
-output file descriptors:
-
- -- Command: INPUT FD=N
- Set the file descriptor for the message to be signed to N. The
- message send to the server is binary encoded. For details on the
- file descriptor, see the description of ‘INPUT’ in the ‘ENCRYPT’
- section.
-
- -- Command: OUTPUT FD=N [--binary]
- Set the file descriptor to be used for the output. The output is
- either the complete signed message or in case of a detached
- signature just that detached signature. If the option ‘--binary’
- is given the output shall be in binary format; if not given, the
- output for OpenPGP needs to be ASCII armored and for CMS Base-64
- encoded. For details on the file descriptor, see the ‘INPUT’
- command.
-
-To allow the server the selection of a non-default signing key the
-client may optionally use the ‘SENDER’ command, see *note command
-SENDER::.
-
-The signing operation is then initiated by:
-
- -- Command: SIGN --protocol=NAME [--detached]
- Sign the data set with the ‘INPUT’ command and write it to the sink
- set by OUTPUT. NAME is the signing protocol used for the message.
- For a description of the allowed protocols see the ‘ENCRYPT’
- command. With option ‘--detached’ given, a detached signature is
- created; this is actually the usual way the command is used.
-
-The client expects the server to send at least this status information
-before the final OK response:
-
- -- Status line: MICALG STRING
- The STRING represents the hash algorithm used to create the
- signature. It is used with RFC-1847 style signature messages and
- defined by PGP/MIME (RFC-3156) and S/MIME (RFC-3851). The GPGME
- library has a supporting function ‘gpgme_hash_algo_name’ to return
- the algorithm name as a string. This string needs to be lowercased
- and for OpenPGP prefixed with "‘pgp-’".
-
diff --git a/doc/gpgme.info-2 b/doc/gpgme.info-2
index c88c51f..641052c 100644
--- a/doc/gpgme.info-2
+++ b/doc/gpgme.info-2
@@ -19,8 +19,8 @@ END-INFO-DIR-ENTRY
This file documents the GPGME library.
- This is Edition 1.15.2-beta35, last updated 13 December 2019, of ‘The
-‘GnuPG Made Easy’ Reference Manual’, for Version 1.15.2-beta35.
+ This is Edition 1.17.0, last updated 3 February 2022, of ‘The ‘GnuPG
+Made Easy’ Reference Manual’, for Version 1.17.0.
Copyright © 2002–2008, 2010, 2012–2018 g10 Code GmbH.
@@ -36,6 +36,57 @@ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General
Public License for more details.

+File: gpgme.info, Node: UI Server Sign, Next: UI Server Decrypt, Prev: UI Server Encrypt, Up: UI Server Protocol
+
+A.2 UI Server: Sign a Message
+=============================
+
+The server needs to implement opaque signing as well as detached
+signing. Due to the nature of OpenPGP messages it is always required to
+send the entire message to the server; sending just the hash is not
+possible. The following two commands are required to set the input and
+output file descriptors:
+
+ -- Command: INPUT FD=N
+ Set the file descriptor for the message to be signed to N. The
+ message send to the server is binary encoded. For details on the
+ file descriptor, see the description of ‘INPUT’ in the ‘ENCRYPT’
+ section.
+
+ -- Command: OUTPUT FD=N [--binary]
+ Set the file descriptor to be used for the output. The output is
+ either the complete signed message or in case of a detached
+ signature just that detached signature. If the option ‘--binary’
+ is given the output shall be in binary format; if not given, the
+ output for OpenPGP needs to be ASCII armored and for CMS Base-64
+ encoded. For details on the file descriptor, see the ‘INPUT’
+ command.
+
+To allow the server the selection of a non-default signing key the
+client may optionally use the ‘SENDER’ command, see *note command
+SENDER::.
+
+The signing operation is then initiated by:
+
+ -- Command: SIGN --protocol=NAME [--detached]
+ Sign the data set with the ‘INPUT’ command and write it to the sink
+ set by OUTPUT. NAME is the signing protocol used for the message.
+ For a description of the allowed protocols see the ‘ENCRYPT’
+ command. With option ‘--detached’ given, a detached signature is
+ created; this is actually the usual way the command is used.
+
+The client expects the server to send at least this status information
+before the final OK response:
+
+ -- Status line: MICALG STRING
+ The STRING represents the hash algorithm used to create the
+ signature. It is used with RFC-1847 style signature messages and
+ defined by PGP/MIME (RFC-3156) and S/MIME (RFC-3851). The GPGME
+ library has a supporting function ‘gpgme_hash_algo_name’ to return
+ the algorithm name as a string. This string needs to be lowercased
+ and for OpenPGP prefixed with "‘pgp-’".
+
+
File: gpgme.info, Node: UI Server Decrypt, Next: UI Server Verify, Prev: UI Server Sign, Up: UI Server Protocol
A.3 UI Server: Decrypt a Message
@@ -2603,7 +2654,7 @@ Function and Data Index
* gpgme_encrypt_result_t: Encrypting a Plaintext.
(line 241)
* gpgme_engine_check_version: Engine Version Check.
- (line 67)
+ (line 82)
* gpgme_engine_info_t: Engine Information. (line 6)
* gpgme_error: Error Values. (line 65)
* gpgme_error_from_errno: Error Values. (line 89)
@@ -2642,7 +2693,7 @@ Function and Data Index
(line 25)
* gpgme_genkey_result_t: Generating Keys. (line 381)
* gpgme_get_armor: ASCII Armor. (line 13)
-* gpgme_get_ctx_flag: Context Flags. (line 141)
+* gpgme_get_ctx_flag: Context Flags. (line 153)
* gpgme_get_dirinfo: Engine Version Check.
(line 6)
* gpgme_get_engine_info: Engine Information. (line 46)
@@ -2674,8 +2725,8 @@ Function and Data Index
* gpgme_get_textmode: Text Mode. (line 20)
* gpgme_hash_algo_name: Hash Algorithms. (line 30)
* gpgme_hash_algo_t: Hash Algorithms. (line 10)
-* gpgme_import_result_t: Importing Keys. (line 118)
-* gpgme_import_status_t: Importing Keys. (line 80)
+* gpgme_import_result_t: Importing Keys. (line 150)
+* gpgme_import_status_t: Importing Keys. (line 110)
* gpgme_interact_cb_t: Advanced Key Editing.
(line 11)
* gpgme_invalid_key_t: Crypto Operations. (line 10)
@@ -2747,12 +2798,12 @@ Function and Data Index
(line 274)
* gpgme_op_encrypt_start: Encrypting a Plaintext.
(line 113)
-* gpgme_op_export: Exporting Keys. (line 59)
-* gpgme_op_export_ext: Exporting Keys. (line 92)
-* gpgme_op_export_ext_start: Exporting Keys. (line 114)
-* gpgme_op_export_keys: Exporting Keys. (line 126)
-* gpgme_op_export_keys_start: Exporting Keys. (line 153)
-* gpgme_op_export_start: Exporting Keys. (line 80)
+* gpgme_op_export: Exporting Keys. (line 65)
+* gpgme_op_export_ext: Exporting Keys. (line 98)
+* gpgme_op_export_ext_start: Exporting Keys. (line 120)
+* gpgme_op_export_keys: Exporting Keys. (line 132)
+* gpgme_op_export_keys_start: Exporting Keys. (line 159)
+* gpgme_op_export_start: Exporting Keys. (line 86)
* gpgme_op_genkey: Generating Keys. (line 304)
* gpgme_op_genkey_result: Generating Keys. (line 418)
* gpgme_op_genkey_start: Generating Keys. (line 369)
@@ -2763,7 +2814,7 @@ Function and Data Index
(line 18)
* gpgme_op_import_keys: Importing Keys. (line 35)
* gpgme_op_import_keys_start: Importing Keys. (line 65)
-* gpgme_op_import_result: Importing Keys. (line 174)
+* gpgme_op_import_result: Importing Keys. (line 206)
* gpgme_op_import_start: Importing Keys. (line 24)
* gpgme_op_interact: Advanced Key Editing.
(line 23)
@@ -2785,6 +2836,8 @@ Function and Data Index
(line 68)
* gpgme_op_query_swdb_result: Checking for updates.
(line 80)
+* gpgme_op_receive_keys: Importing Keys. (line 80)
+* gpgme_op_receive_keys_start: Importing Keys. (line 97)
* gpgme_op_revsig: Signing Keys. (line 89)
* gpgme_op_revsig_start: Signing Keys. (line 124)
* gpgme_op_revuid: Generating Keys. (line 224)
diff --git a/doc/gpgme.texi b/doc/gpgme.texi
index 4a705b1..9590ce8 100644
--- a/doc/gpgme.texi
+++ b/doc/gpgme.texi
@@ -990,6 +990,21 @@ Return the file name of the CMS engine.
@item g13-name
Return the name of the file container encryption engine.
+@item keyboxd-name
+Return the name of the key database daemon.
+
+@item agent-name
+Return the name of gpg-agent.
+
+@item scdaemon-name
+Return the name of the smart card daemon.
+
+@item dirmngr-name
+Return the name of dirmngr.
+
+@item pinentry-name
+Return the name of the pinentry program.
+
@item gpg-wks-client-name
Return the name of the Web Key Service tool.
@@ -3186,6 +3201,17 @@ the expiration time to use for key signature expiration. Valid values
are documented in the GnuPG manual and the gpg man page under
the option @option{--default-cert-expire}.
+@item "key-origin"
+@since{1.16.1}
+The string given in @var{value} is passed to the GnuPG engine to set
+the origin of imported keys. Valid values are documented in the GnuPG
+manual and the gpg man page under the option @option{--key-origin}.
+
+@item "import-filter"
+@since{1.16.1}
+The string given in @var{value} is passed to the GnuPG engine to use as
+filter when importing keys. Valid values are documented in the GnuPG
+manual and the gpg man page under the option @option{--import-filter}.
@end table
@@ -3636,7 +3662,7 @@ database pertaining to the user ID.
The tofu info structure has the following members:
@table @code
-@item gpgme_key_sig_t next
+@item gpgme_tofu_info_t next
This is a pointer to the next tofu info structure in the linked
list, or @code{NULL} if this is the last element.
@@ -4867,7 +4893,6 @@ OpenPGP key is exported in the OpenSSH public key format. This
accepts just a single key; to force the export of a specific subkey
a fingerprint pattern with an appended exclamation mark may be used.
-
@item GPGME_EXPORT_MODE_SECRET
@since{1.6.0}
@@ -4875,6 +4900,16 @@ Instead of exporting the public key, the secret key is exported. This
may not be combined with @code{GPGME_EXPORT_MODE_EXTERN}. For X.509
the export format is PKCS#8.
+@item GPGME_EXPORT_MODE_SECRET_SUBKEY
+@since{1.17.0}
+
+If this bit is set, then a secret subkey is exported. The subkey to
+export must be specified with fingerprint pattern with an appended
+exclamation mark. This is currently only allowed for OpenPGP keys.
+This flag may not be combined with @code{GPGME_EXPORT_MODE_EXTERN}.
+This flag is not supported by the export functions that take an array
+of keys.
+
@item GPGME_EXPORT_MODE_RAW
@since{1.6.0}
@@ -4889,10 +4924,6 @@ If this flag is used with @code{GPGME_EXPORT_MODE_SECRET} for an X.509
key the export format will be changed to PKCS#12 which also includes
the certificate. This flag may not be used with OpenPGP.
-@item GPGME_EXPORT_MODE_NOUID
-@since{1.12.0 - experimental}
-Do not export user ids. Works only with certain gpg version.
-
@end table
@@ -5016,7 +5047,7 @@ retrieved with @code{gpgme_op_import_result}.
The function returns the error code @code{GPG_ERR_NO_ERROR} if the
import was completed successfully, @code{GPG_ERR_INV_VALUE} if
-@var{keydata} if @var{ctx} or @var{keydata} is not a valid pointer,
+@var{ctx} or @var{keydata} is not a valid pointer,
and @code{GPG_ERR_NO_DATA} if @var{keydata} is an empty data buffer.
@end deftypefun
@@ -5059,8 +5090,8 @@ keydata using @code{gpgme_op_export} and @code{gpgme_op_import}.
The function returns the error code @code{GPG_ERR_NO_ERROR} if the
import was completed successfully, @code{GPG_ERR_INV_VALUE} if
@var{ctx} is not a valid pointer, @code{GPG_ERR_CONFLICT} if the key
-listing mode does not match, and @code{GPG_ERR_NO_DATA} if no keys are
-considered for export.
+listing mode does not match, and @code{GPG_ERR_NO_DATA} if no keys were
+considered for import.
@end deftypefun
@deftypefun gpgme_error_t gpgme_op_import_keys_start (@w{gpgme_ctx_t @var{ctx}}, @w{gpgme_key_t *@var{keys}})
@@ -5071,10 +5102,40 @@ The function @code{gpgme_op_import_keys_start} initiates a
@code{gpgme_wait} on the context. @xref{Waiting For Completion}.
The function returns the error code @code{GPG_ERR_NO_ERROR} if the
+import was started successfully, @code{GPG_ERR_INV_VALUE} if
+@var{ctx} is not a valid pointer, @code{GPG_ERR_CONFLICT} if the key
+listing mode does not match, and @code{GPG_ERR_NO_DATA} if no keys were
+considered for import.
+@end deftypefun
+
+@deftypefun gpgme_error_t gpgme_op_receive_keys (@w{gpgme_ctx_t @var{ctx}}, @w{const char *@var{keyids}[]})
+@since{1.17.0}
+
+The function @code{gpgme_op_receive_keys} adds the keys described by
+the @code{NULL} terminated array @var{keyids} to the key ring of the
+crypto engine used by @var{ctx}. It is used to retrieve and import keys
+from an external source. This function currently works only for OpenPGP.
+
+After the operation completed successfully, the result can be
+retrieved with @code{gpgme_op_import_result}.
+
+The function returns the error code @code{GPG_ERR_NO_ERROR} if the
import was completed successfully, @code{GPG_ERR_INV_VALUE} if
-@var{keydata} if @var{ctx} or @var{keydata} is not a valid pointer,
-@code{GPG_ERR_CONFLICT} if the key listing mode does not match, and
-@code{GPG_ERR_NO_DATA} if no keys are considered for export.
+@var{ctx} is not a valid pointer, and @code{GPG_ERR_NO_DATA} if no keys
+were considered for import.
+@end deftypefun
+
+@deftypefun gpgme_error_t gpgme_op_receive_keys_start (@w{gpgme_ctx_t @var{ctx}}, @w{const char *@var{keyids}[]})
+@since{1.17.0}
+
+The function @code{gpgme_op_receive_keys_start} initiates a
+@code{gpgme_op_receive_keys} operation. It can be completed by calling
+@code{gpgme_wait} on the context. @xref{Waiting For Completion}.
+
+The function returns the error code @code{GPG_ERR_NO_ERROR} if the
+import was started successfully, @code{GPG_ERR_INV_VALUE} if
+@var{ctx} is not a valid pointer, and @code{GPG_ERR_NO_DATA} if no keys
+were considered for import.
@end deftypefun
@deftp {Data type} {gpgme_import_status_t}
@@ -5089,7 +5150,9 @@ This is a pointer to the next status structure in the linked list, or
@code{NULL} if this is the last element.
@item char *fpr
-This is the fingerprint of the key that was considered.
+This is the fingerprint of the key that was considered, or @code{NULL}
+if the fingerprint of the key is not known, e.g. because the key to
+import was encrypted and decryption failed.
@item gpgme_error_t result
If the import was not successful, this is the error value that caused
diff --git a/gpgme.spec b/gpgme.spec
index 32d4439..b8a3c19 100644
--- a/gpgme.spec
+++ b/gpgme.spec
@@ -1,7 +1,7 @@
# This is a template. The dist target uses it to create the real file.
Summary: GPGME - GnuPG Made Easy
Name: gpgme
-Version: 1.16.0
+Version: 1.17.0
Release: 1
URL: https://gnupg.org/gpgme.html
Source: https://www.gnupg.org/ftp/gcrypt/gpgme/%{name}-%{version}.tar.gz
diff --git a/lang/cl/gpgme.asd b/lang/cl/gpgme.asd
index f0a15d8..d0569cd 100644
--- a/lang/cl/gpgme.asd
+++ b/lang/cl/gpgme.asd
@@ -27,7 +27,7 @@
(defsystem gpgme
:description "GnuPG Made Easy."
:author "g10 Code GmbH"
- :version "1.16.0"
+ :version "1.17.0"
:licence "GPL"
:defsystem-depends-on ("cffi-grovel")
:depends-on ("cffi" "gpg-error" "trivial-garbage")
diff --git a/lang/cpp/src/Makefile.am b/lang/cpp/src/Makefile.am
index 32e3045..ba8a7fb 100644
--- a/lang/cpp/src/Makefile.am
+++ b/lang/cpp/src/Makefile.am
@@ -33,10 +33,12 @@ main_sources = \
engineinfo.cpp gpgsetexpirytimeeditinteractor.cpp \
gpgsetownertrusteditinteractor.cpp gpgsignkeyeditinteractor.cpp \
gpgadduserideditinteractor.cpp gpggencardkeyinteractor.cpp \
+ gpgaddexistingsubkeyeditinteractor.cpp \
defaultassuantransaction.cpp \
scdgetinfoassuantransaction.cpp gpgagentgetinfoassuantransaction.cpp \
statusconsumerassuantransaction.cpp \
- vfsmountresult.cpp configuration.cpp tofuinfo.cpp swdbresult.cpp
+ vfsmountresult.cpp configuration.cpp tofuinfo.cpp swdbresult.cpp \
+ util.cpp
gpgmepp_headers = \
configuration.h context.h data.h decryptionresult.h \
@@ -46,6 +48,7 @@ gpgmepp_headers = \
gpgmefw.h gpgsetexpirytimeeditinteractor.h \
gpgsetownertrusteditinteractor.h gpgsignkeyeditinteractor.h \
gpggencardkeyinteractor.h \
+ gpgaddexistingsubkeyeditinteractor.h \
importresult.h keygenerationresult.h key.h keylistresult.h \
notation.h result.h scdgetinfoassuantransaction.h signingresult.h \
statusconsumerassuantransaction.h \
diff --git a/lang/cpp/src/Makefile.in b/lang/cpp/src/Makefile.in
index 5dc6fcc..f5e859a 100644
--- a/lang/cpp/src/Makefile.in
+++ b/lang/cpp/src/Makefile.in
@@ -173,10 +173,11 @@ am__objects_1 = exception.lo context.lo key.lo trustitem.lo data.lo \
gpgsetexpirytimeeditinteractor.lo \
gpgsetownertrusteditinteractor.lo gpgsignkeyeditinteractor.lo \
gpgadduserideditinteractor.lo gpggencardkeyinteractor.lo \
+ gpgaddexistingsubkeyeditinteractor.lo \
defaultassuantransaction.lo scdgetinfoassuantransaction.lo \
gpgagentgetinfoassuantransaction.lo \
statusconsumerassuantransaction.lo vfsmountresult.lo \
- configuration.lo tofuinfo.lo swdbresult.lo
+ configuration.lo tofuinfo.lo swdbresult.lo util.lo
am__objects_2 =
am_libgpgmepp_la_OBJECTS = $(am__objects_1) $(am__objects_2) \
context_vanilla.lo $(am__objects_2) $(am__objects_2)
@@ -212,6 +213,7 @@ am__depfiles_remade = ./$(DEPDIR)/callbacks.Plo \
./$(DEPDIR)/editinteractor.Plo \
./$(DEPDIR)/encryptionresult.Plo ./$(DEPDIR)/engineinfo.Plo \
./$(DEPDIR)/eventloopinteractor.Plo ./$(DEPDIR)/exception.Plo \
+ ./$(DEPDIR)/gpgaddexistingsubkeyeditinteractor.Plo \
./$(DEPDIR)/gpgadduserideditinteractor.Plo \
./$(DEPDIR)/gpgagentgetinfoassuantransaction.Plo \
./$(DEPDIR)/gpggencardkeyinteractor.Plo \
@@ -225,7 +227,8 @@ am__depfiles_remade = ./$(DEPDIR)/callbacks.Plo \
./$(DEPDIR)/signingresult.Plo \
./$(DEPDIR)/statusconsumerassuantransaction.Plo \
./$(DEPDIR)/swdbresult.Plo ./$(DEPDIR)/tofuinfo.Plo \
- ./$(DEPDIR)/trustitem.Plo ./$(DEPDIR)/verificationresult.Plo \
+ ./$(DEPDIR)/trustitem.Plo ./$(DEPDIR)/util.Plo \
+ ./$(DEPDIR)/verificationresult.Plo \
./$(DEPDIR)/vfsmountresult.Plo
am__mv = mv -f
CXXCOMPILE = $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) \
@@ -509,10 +512,12 @@ main_sources = \
engineinfo.cpp gpgsetexpirytimeeditinteractor.cpp \
gpgsetownertrusteditinteractor.cpp gpgsignkeyeditinteractor.cpp \
gpgadduserideditinteractor.cpp gpggencardkeyinteractor.cpp \
+ gpgaddexistingsubkeyeditinteractor.cpp \
defaultassuantransaction.cpp \
scdgetinfoassuantransaction.cpp gpgagentgetinfoassuantransaction.cpp \
statusconsumerassuantransaction.cpp \
- vfsmountresult.cpp configuration.cpp tofuinfo.cpp swdbresult.cpp
+ vfsmountresult.cpp configuration.cpp tofuinfo.cpp swdbresult.cpp \
+ util.cpp
gpgmepp_headers = \
configuration.h context.h data.h decryptionresult.h \
@@ -522,6 +527,7 @@ gpgmepp_headers = \
gpgmefw.h gpgsetexpirytimeeditinteractor.h \
gpgsetownertrusteditinteractor.h gpgsignkeyeditinteractor.h \
gpggencardkeyinteractor.h \
+ gpgaddexistingsubkeyeditinteractor.h \
importresult.h keygenerationresult.h key.h keylistresult.h \
notation.h result.h scdgetinfoassuantransaction.h signingresult.h \
statusconsumerassuantransaction.h \
@@ -654,6 +660,7 @@ distclean-compile:
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/engineinfo.Plo@am__quote@ # am--include-marker
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/eventloopinteractor.Plo@am__quote@ # am--include-marker
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/exception.Plo@am__quote@ # am--include-marker
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/gpgaddexistingsubkeyeditinteractor.Plo@am__quote@ # am--include-marker
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/gpgadduserideditinteractor.Plo@am__quote@ # am--include-marker
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/gpgagentgetinfoassuantransaction.Plo@am__quote@ # am--include-marker
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/gpggencardkeyinteractor.Plo@am__quote@ # am--include-marker
@@ -670,6 +677,7 @@ distclean-compile:
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/swdbresult.Plo@am__quote@ # am--include-marker
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/tofuinfo.Plo@am__quote@ # am--include-marker
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/trustitem.Plo@am__quote@ # am--include-marker
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/util.Plo@am__quote@ # am--include-marker
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/verificationresult.Plo@am__quote@ # am--include-marker
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/vfsmountresult.Plo@am__quote@ # am--include-marker
@@ -913,6 +921,7 @@ distclean: distclean-am
-rm -f ./$(DEPDIR)/engineinfo.Plo
-rm -f ./$(DEPDIR)/eventloopinteractor.Plo
-rm -f ./$(DEPDIR)/exception.Plo
+ -rm -f ./$(DEPDIR)/gpgaddexistingsubkeyeditinteractor.Plo
-rm -f ./$(DEPDIR)/gpgadduserideditinteractor.Plo
-rm -f ./$(DEPDIR)/gpgagentgetinfoassuantransaction.Plo
-rm -f ./$(DEPDIR)/gpggencardkeyinteractor.Plo
@@ -929,6 +938,7 @@ distclean: distclean-am
-rm -f ./$(DEPDIR)/swdbresult.Plo
-rm -f ./$(DEPDIR)/tofuinfo.Plo
-rm -f ./$(DEPDIR)/trustitem.Plo
+ -rm -f ./$(DEPDIR)/util.Plo
-rm -f ./$(DEPDIR)/verificationresult.Plo
-rm -f ./$(DEPDIR)/vfsmountresult.Plo
-rm -f Makefile
@@ -990,6 +1000,7 @@ maintainer-clean: maintainer-clean-am
-rm -f ./$(DEPDIR)/engineinfo.Plo
-rm -f ./$(DEPDIR)/eventloopinteractor.Plo
-rm -f ./$(DEPDIR)/exception.Plo
+ -rm -f ./$(DEPDIR)/gpgaddexistingsubkeyeditinteractor.Plo
-rm -f ./$(DEPDIR)/gpgadduserideditinteractor.Plo
-rm -f ./$(DEPDIR)/gpgagentgetinfoassuantransaction.Plo
-rm -f ./$(DEPDIR)/gpggencardkeyinteractor.Plo
@@ -1006,6 +1017,7 @@ maintainer-clean: maintainer-clean-am
-rm -f ./$(DEPDIR)/swdbresult.Plo
-rm -f ./$(DEPDIR)/tofuinfo.Plo
-rm -f ./$(DEPDIR)/trustitem.Plo
+ -rm -f ./$(DEPDIR)/util.Plo
-rm -f ./$(DEPDIR)/verificationresult.Plo
-rm -f ./$(DEPDIR)/vfsmountresult.Plo
-rm -f Makefile
diff --git a/lang/cpp/src/context.cpp b/lang/cpp/src/context.cpp
index 44587a5..5072681 100644
--- a/lang/cpp/src/context.cpp
+++ b/lang/cpp/src/context.cpp
@@ -50,6 +50,7 @@
#include <gpgme.h>
+#include <functional>
#include <istream>
#include <numeric>
#ifndef NDEBUG
@@ -462,9 +463,33 @@ Error Context::setLocale(int cat, const char *val)
return Error(d->lasterr = gpgme_set_locale(d->ctx, cat, val));
}
+static GpgME::EngineInfo get_engine_info(gpgme_engine_info_t engineInfos, gpgme_protocol_t protocol)
+{
+ if (!engineInfos) {
+ return EngineInfo{};
+ }
+
+ for (gpgme_engine_info_t i = engineInfos ; i ; i = i->next) {
+ if (i->protocol == protocol) {
+ return EngineInfo{i};
+ }
+ }
+
+ return EngineInfo{};
+}
+
+static GpgME::EngineInfo get_static_engine_info(gpgme_protocol_t protocol)
+{
+ gpgme_engine_info_t ei = nullptr;
+ if (gpgme_get_engine_info(&ei)) {
+ return EngineInfo{};
+ }
+ return get_engine_info(ei, protocol);
+}
+
EngineInfo Context::engineInfo() const
{
- return EngineInfo(gpgme_ctx_get_engine_info(d->ctx));
+ return get_engine_info(gpgme_ctx_get_engine_info(d->ctx), gpgme_get_protocol(d->ctx));
}
Error Context::setEngineFileName(const char *filename)
@@ -504,12 +529,6 @@ Error Context::startKeyListing(const char *pattern, bool secretOnly)
Error Context::startKeyListing(const char *patterns[], bool secretOnly)
{
d->lastop = Private::KeyList;
-#ifndef HAVE_GPGME_EXT_KEYLIST_MODE_EXTERNAL_NONBROKEN
- if (!patterns || !patterns[0] || !patterns[1]) {
- // max. one pattern -> use the non-ext version
- return startKeyListing(patterns ? patterns[0] : nullptr, secretOnly);
- }
-#endif
return Error(d->lasterr = gpgme_op_keylist_ext_start(d->ctx, patterns, int(secretOnly), 0));
}
@@ -564,48 +583,67 @@ KeyGenerationResult Context::keyGenerationResult() const
}
}
-Error Context::exportPublicKeys(const char *pattern, Data &keyData, unsigned int flags)
+Error Context::exportKeys(const char *pattern, Data &keyData, unsigned int mode)
{
d->lastop = Private::Export;
Data::Private *const dp = keyData.impl();
- return Error(d->lasterr = gpgme_op_export(d->ctx, pattern, flags, dp ? dp->data : nullptr));
+ return Error(d->lasterr = gpgme_op_export(d->ctx, pattern, mode, dp ? dp->data : nullptr));
}
-Error Context::exportPublicKeys(const char *patterns[], Data &keyData, unsigned int flags)
+Error Context::exportKeys(const char *patterns[], Data &keyData, unsigned int mode)
{
d->lastop = Private::Export;
-#ifndef HAVE_GPGME_EXT_KEYLIST_MODE_EXTERNAL_NONBROKEN
- if (!patterns || !patterns[0] || !patterns[1]) {
- // max. one pattern -> use the non-ext version
- return exportPublicKeys(patterns ? patterns[0] : nullptr, keyData, flags);
- }
-#endif
Data::Private *const dp = keyData.impl();
- return Error(d->lasterr = gpgme_op_export_ext(d->ctx, patterns, flags, dp ? dp->data : nullptr));
+ return Error(d->lasterr = gpgme_op_export_ext(d->ctx, patterns, mode, dp ? dp->data : nullptr));
}
-Error Context::startPublicKeyExport(const char *pattern, Data &keyData, unsigned int flags)
+Error Context::startKeyExport(const char *pattern, Data &keyData, unsigned int mode)
{
d->lastop = Private::Export;
Data::Private *const dp = keyData.impl();
- return Error(d->lasterr = gpgme_op_export_start(d->ctx, pattern, flags, dp ? dp->data : nullptr));
+ return Error(d->lasterr = gpgme_op_export_start(d->ctx, pattern, mode, dp ? dp->data : nullptr));
}
-Error Context::startPublicKeyExport(const char *patterns[], Data &keyData, unsigned int flags)
+Error Context::startKeyExport(const char *patterns[], Data &keyData, unsigned int mode)
{
d->lastop = Private::Export;
-#ifndef HAVE_GPGME_EXT_KEYLIST_MODE_EXTERNAL_NONBROKEN
- if (!patterns || !patterns[0] || !patterns[1]) {
- // max. one pattern -> use the non-ext version
- return startPublicKeyExport(patterns ? patterns[0] : nullptr, keyData, flags);
- }
-#endif
Data::Private *const dp = keyData.impl();
- return Error(d->lasterr = gpgme_op_export_ext_start(d->ctx, patterns, flags, dp ? dp->data : nullptr));
+ return Error(d->lasterr = gpgme_op_export_ext_start(d->ctx, patterns, mode, dp ? dp->data : nullptr));
+}
+
+Error Context::exportPublicKeys(const char *pattern, Data &keyData, unsigned int mode)
+{
+ if (mode & (ExportSecret | ExportSecretSubkey)) {
+ return Error::fromCode(GPG_ERR_INV_FLAG);
+ }
+ return exportKeys(pattern, keyData, mode);
+}
+
+Error Context::exportPublicKeys(const char *patterns[], Data &keyData, unsigned int mode)
+{
+ if (mode & (ExportSecret | ExportSecretSubkey)) {
+ return Error::fromCode(GPG_ERR_INV_FLAG);
+ }
+ return exportKeys(patterns, keyData, mode);
+}
+
+Error Context::startPublicKeyExport(const char *pattern, Data &keyData, unsigned int mode)
+{
+ if (mode & (ExportSecret | ExportSecretSubkey)) {
+ return Error::fromCode(GPG_ERR_INV_FLAG);
+ }
+ return startKeyExport(pattern, keyData, mode);
}
+Error Context::startPublicKeyExport(const char *patterns[], Data &keyData, unsigned int mode)
+{
+ if (mode & (ExportSecret | ExportSecretSubkey)) {
+ return Error::fromCode(GPG_ERR_INV_FLAG);
+ }
+ return startKeyExport(patterns, keyData, mode);
+}
-/* Same as above but without flags */
+/* Same as above but without mode */
Error Context::exportPublicKeys(const char *pattern, Data &keyData)
{
return exportPublicKeys(pattern, keyData, 0);
@@ -626,6 +664,58 @@ Error Context::startPublicKeyExport(const char *patterns[], Data &keyData)
return startPublicKeyExport(patterns, keyData, 0);
}
+Error Context::exportSecretKeys(const char *pattern, Data &keyData, unsigned int mode)
+{
+ if (mode & ExportSecretSubkey) {
+ return Error::fromCode(GPG_ERR_INV_FLAG);
+ }
+ return exportKeys(pattern, keyData, mode|ExportSecret);
+}
+
+Error Context::exportSecretKeys(const char *patterns[], Data &keyData, unsigned int mode)
+{
+ if (mode & ExportSecretSubkey) {
+ return Error::fromCode(GPG_ERR_INV_FLAG);
+ }
+ return exportKeys(patterns, keyData, mode|ExportSecret);
+}
+
+Error Context::startSecretKeyExport(const char *pattern, Data &keyData, unsigned int mode)
+{
+ if (mode & ExportSecretSubkey) {
+ return Error::fromCode(GPG_ERR_INV_FLAG);
+ }
+ return startKeyExport(pattern, keyData, mode|ExportSecret);
+}
+
+Error Context::startSecretKeyExport(const char *patterns[], Data &keyData, unsigned int mode)
+{
+ if (mode & ExportSecretSubkey) {
+ return Error::fromCode(GPG_ERR_INV_FLAG);
+ }
+ return startKeyExport(patterns, keyData, mode|ExportSecret);
+}
+
+Error Context::exportSecretSubkeys(const char *pattern, Data &keyData, unsigned int mode)
+{
+ return exportKeys(pattern, keyData, mode|ExportSecretSubkey);
+}
+
+Error Context::exportSecretSubkeys(const char *patterns[], Data &keyData, unsigned int mode)
+{
+ return exportKeys(patterns, keyData, mode|ExportSecretSubkey);
+}
+
+Error Context::startSecretSubkeyExport(const char *pattern, Data &keyData, unsigned int mode)
+{
+ return startKeyExport(pattern, keyData, mode|ExportSecretSubkey);
+}
+
+Error Context::startSecretSubkeyExport(const char *patterns[], Data &keyData, unsigned int mode)
+{
+ return startKeyExport(patterns, keyData, mode|ExportSecretSubkey);
+}
+
ImportResult Context::importKeys(const Data &data)
{
d->lastop = Private::Import;
@@ -710,6 +800,22 @@ Error Context::startKeyImport(const std::vector<Key> &kk)
return err;
}
+ImportResult Context::importKeys(const std::vector<std::string> &keyIds)
+{
+ d->lastop = Private::Import;
+ const StringsToCStrings keyids{keyIds};
+ d->lasterr = gpgme_op_receive_keys(d->ctx, keyids.c_strs());
+ return ImportResult(d->ctx, Error(d->lasterr));
+}
+
+Error Context::startKeyImport(const std::vector<std::string> &keyIds)
+{
+ d->lastop = Private::Import;
+ const StringsToCStrings keyids{keyIds};
+ d->lasterr = gpgme_op_receive_keys_start(d->ctx, keyids.c_strs());
+ return Error(d->lasterr);
+}
+
ImportResult Context::importResult() const
{
if (d->lastop & Private::Import) {
@@ -1794,20 +1900,7 @@ GpgME::Error GpgME::setDefaultLocale(int cat, const char *val)
GpgME::EngineInfo GpgME::engineInfo(GpgME::Protocol proto)
{
- gpgme_engine_info_t ei = nullptr;
- if (gpgme_get_engine_info(&ei)) {
- return EngineInfo();
- }
-
- const gpgme_protocol_t p = proto == CMS ? GPGME_PROTOCOL_CMS : GPGME_PROTOCOL_OpenPGP ;
-
- for (gpgme_engine_info_t i = ei ; i ; i = i->next) {
- if (i->protocol == p) {
- return EngineInfo(i);
- }
- }
-
- return EngineInfo();
+ return get_static_engine_info(proto == CMS ? GPGME_PROTOCOL_CMS : GPGME_PROTOCOL_OpenPGP);
}
const char *GpgME::dirInfo(const char *what)
@@ -1845,20 +1938,7 @@ static gpgme_protocol_t engine2protocol(const GpgME::Engine engine)
GpgME::EngineInfo GpgME::engineInfo(GpgME::Engine engine)
{
- gpgme_engine_info_t ei = nullptr;
- if (gpgme_get_engine_info(&ei)) {
- return EngineInfo();
- }
-
- const gpgme_protocol_t p = engine2protocol(engine);
-
- for (gpgme_engine_info_t i = ei ; i ; i = i->next) {
- if (i->protocol == p) {
- return EngineInfo(i);
- }
- }
-
- return EngineInfo();
+ return get_static_engine_info(engine2protocol(engine));
}
GpgME::Error GpgME::checkEngine(GpgME::Engine engine)
diff --git a/lang/cpp/src/context.h b/lang/cpp/src/context.h
index bcb2017..9c2b2a5 100644
--- a/lang/cpp/src/context.h
+++ b/lang/cpp/src/context.h
@@ -31,6 +31,7 @@
#include "verificationresult.h" // for Signature::Notation
#include <memory>
+#include <string>
#include <vector>
#include <utility>
#include <iosfwd>
@@ -189,18 +190,35 @@ public:
ExportSecret = 16,
ExportRaw = 32,
ExportPKCS12 = 64,
- ExportNoUID = 128,
+ ExportNoUID = 128, // obsolete; has no effect
ExportSSH = 256,
+ ExportSecretSubkey = 512,
};
GpgME::Error exportPublicKeys(const char *pattern, Data &keyData);
- GpgME::Error exportPublicKeys(const char *pattern, Data &keyData, unsigned int flags);
+ GpgME::Error exportPublicKeys(const char *pattern, Data &keyData, unsigned int mode);
GpgME::Error exportPublicKeys(const char *pattern[], Data &keyData);
- GpgME::Error exportPublicKeys(const char *pattern[], Data &keyData, unsigned int export_mode);
+ GpgME::Error exportPublicKeys(const char *pattern[], Data &keyData, unsigned int mode);
GpgME::Error startPublicKeyExport(const char *pattern, Data &keyData);
- GpgME::Error startPublicKeyExport(const char *pattern, Data &keyData, unsigned int flags);
+ GpgME::Error startPublicKeyExport(const char *pattern, Data &keyData, unsigned int mode);
GpgME::Error startPublicKeyExport(const char *pattern[], Data &keyData);
- GpgME::Error startPublicKeyExport(const char *pattern[], Data &keyData, unsigned int export_mode);
+ GpgME::Error startPublicKeyExport(const char *pattern[], Data &keyData, unsigned int mode);
+
+ GpgME::Error exportSecretKeys(const char *pattern, Data &keyData, unsigned int mode = ExportSecret);
+ GpgME::Error exportSecretKeys(const char *pattern[], Data &keyData, unsigned int mode = ExportSecret);
+ GpgME::Error startSecretKeyExport(const char *pattern, Data &keyData, unsigned int mode = ExportSecret);
+ GpgME::Error startSecretKeyExport(const char *pattern[], Data &keyData, unsigned int mode = ExportSecret);
+
+ GpgME::Error exportSecretSubkeys(const char *pattern, Data &keyData, unsigned int mode = ExportSecretSubkey);
+ GpgME::Error exportSecretSubkeys(const char *pattern[], Data &keyData, unsigned int mode = ExportSecretSubkey);
+ GpgME::Error startSecretSubkeyExport(const char *pattern, Data &keyData, unsigned int mode = ExportSecretSubkey);
+ GpgME::Error startSecretSubkeyExport(const char *pattern[], Data &keyData, unsigned int mode = ExportSecretSubkey);
+
+ // generic export functions; prefer using the specific public/secret key export functions
+ GpgME::Error exportKeys(const char *pattern, Data &keyData, unsigned int mode = ExportDefault);
+ GpgME::Error exportKeys(const char *pattern[], Data &keyData, unsigned int mode = ExportDefault);
+ GpgME::Error startKeyExport(const char *pattern, Data &keyData, unsigned int mode = ExportDefault);
+ GpgME::Error startKeyExport(const char *pattern[], Data &keyData, unsigned int mode = ExportDefault);
//
// Key Import
@@ -208,8 +226,10 @@ public:
ImportResult importKeys(const Data &data);
ImportResult importKeys(const std::vector<Key> &keys);
+ ImportResult importKeys(const std::vector<std::string> &keyIds);
GpgME::Error startKeyImport(const Data &data);
GpgME::Error startKeyImport(const std::vector<Key> &keys);
+ GpgME::Error startKeyImport(const std::vector<std::string> &keyIds);
ImportResult importResult() const;
//
diff --git a/lang/cpp/src/global.h b/lang/cpp/src/global.h
index 7d9f9d6..a25b46c 100644
--- a/lang/cpp/src/global.h
+++ b/lang/cpp/src/global.h
@@ -91,7 +91,8 @@ GPGMEPP_EXPORT EngineInfo engineInfo(Engine engine);
homedir, sysconfdir, bindir, libexecdir, libdir,
datadir, localedir, agent-socket, agent-ssh-socket,
dirmngr-socket, uiserver-socket, gpgconf-name, gpg-name,
-gpgsm-name, g13-name
+gpgsm-name, g13-name, keyboxd-name, agent-name, scdaemon-name,
+dirmngr-name, pinentry-name, socketdir.
This may be extended in the future.
*/
diff --git a/lang/cpp/src/gpgaddexistingsubkeyeditinteractor.cpp b/lang/cpp/src/gpgaddexistingsubkeyeditinteractor.cpp
new file mode 100644
index 0000000..547e613
--- /dev/null
+++ b/lang/cpp/src/gpgaddexistingsubkeyeditinteractor.cpp
@@ -0,0 +1,209 @@
+/*
+ gpgaddexistingsubkeyeditinteractor.cpp - Edit Interactor to add an existing subkey to an OpenPGP key
+ Copyright (c) 2022 g10 Code GmbH
+ Software engineering by Ingo Klöcker <dev@ingo-kloecker.de>
+
+ This file is part of GPGME++.
+
+ GPGME++ is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Library General Public
+ License as published by the Free Software Foundation; either
+ version 2 of the License, or (at your option) any later version.
+
+ GPGME++ is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU Library General Public License for more details.
+
+ You should have received a copy of the GNU Library General Public License
+ along with GPGME++; see the file COPYING.LIB. If not, write to the
+ Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+ Boston, MA 02110-1301, USA.
+*/
+
+#ifdef HAVE_CONFIG_H
+ #include "config.h"
+#endif
+
+#include "gpgaddexistingsubkeyeditinteractor.h"
+
+#include "error.h"
+
+#include <gpgme.h>
+
+// avoid conflict (msvc)
+#ifdef ERROR
+# undef ERROR
+#endif
+
+using namespace GpgME;
+
+class GpgAddExistingSubkeyEditInteractor::Private
+{
+ enum {
+ START = EditInteractor::StartState,
+ COMMAND,
+ ADD_EXISTING_KEY,
+ KEYGRIP,
+ FLAGS,
+ VALID,
+ KEY_CREATED,
+ QUIT,
+ SAVE,
+
+ ERROR = EditInteractor::ErrorState
+ };
+
+ GpgAddExistingSubkeyEditInteractor *const q = nullptr;
+
+public:
+ Private(GpgAddExistingSubkeyEditInteractor *q, const std::string &keygrip)
+ : q{q}
+ , keygrip{keygrip}
+ {
+ }
+
+ const char *action(Error &err) const;
+ unsigned int nextState(unsigned int statusCode, const char *args, Error &err) const;
+
+ std::string keygrip;
+ std::string expiry;
+};
+
+const char *GpgAddExistingSubkeyEditInteractor::Private::action(Error &err) const
+{
+ switch (q->state()) {
+ case COMMAND:
+ return "addkey";
+ case ADD_EXISTING_KEY:
+ return "keygrip";
+ case KEYGRIP:
+ return keygrip.c_str();
+ case FLAGS:
+ return "Q"; // do not toggle any usage flags
+ case VALID:
+ return expiry.empty() ? "0" : expiry.c_str();
+ case QUIT:
+ return "quit";
+ case SAVE:
+ return "Y";
+ case START:
+ case KEY_CREATED:
+ case ERROR:
+ return nullptr;
+ default:
+ err = Error::fromCode(GPG_ERR_GENERAL);
+ return nullptr;
+ }
+}
+
+unsigned int GpgAddExistingSubkeyEditInteractor::Private::nextState(unsigned int status, const char *args, Error &err) const
+{
+ using std::strcmp;
+
+ static const Error GENERAL_ERROR = Error::fromCode(GPG_ERR_GENERAL);
+ static const Error NO_KEY_ERROR = Error::fromCode(GPG_ERR_NO_KEY);
+ static const Error INV_TIME_ERROR = Error::fromCode(GPG_ERR_INV_TIME);
+
+ if (q->needsNoResponse(status)) {
+ return q->state();
+ }
+
+ switch (q->state()) {
+ case START:
+ if (status == GPGME_STATUS_GET_LINE &&
+ strcmp(args, "keyedit.prompt") == 0) {
+ return COMMAND;
+ }
+ err = GENERAL_ERROR;
+ return ERROR;
+ case COMMAND:
+ if (status == GPGME_STATUS_GET_LINE &&
+ strcmp(args, "keygen.algo") == 0) {
+ return ADD_EXISTING_KEY;
+ }
+ err = GENERAL_ERROR;
+ return ERROR;
+ case ADD_EXISTING_KEY:
+ if (status == GPGME_STATUS_GET_LINE &&
+ strcmp(args, "keygen.keygrip") == 0) {
+ return KEYGRIP;
+ }
+ err = GENERAL_ERROR;
+ return ERROR;
+ case KEYGRIP:
+ if (status == GPGME_STATUS_GET_LINE &&
+ strcmp(args, "keygen.flags") == 0) {
+ return FLAGS;
+ } else if (status == GPGME_STATUS_GET_LINE &&
+ strcmp(args, "keygen.keygrip")) {
+ err = NO_KEY_ERROR;
+ return ERROR;
+ }
+ err = GENERAL_ERROR;
+ return ERROR;
+ case FLAGS:
+ if (status == GPGME_STATUS_GET_LINE &&
+ strcmp(args, "keygen.valid") == 0) {
+ return VALID;
+ }
+ err = GENERAL_ERROR;
+ return ERROR;
+ case VALID:
+ if (status == GPGME_STATUS_KEY_CREATED) {
+ return KEY_CREATED;
+ }
+ if (status == GPGME_STATUS_GET_LINE &&
+ strcmp(args, "keyedit.prompt") == 0) {
+ return QUIT;
+ } else if (status == GPGME_STATUS_GET_LINE &&
+ strcmp(args, "keygen.valid")) {
+ err = INV_TIME_ERROR;
+ return ERROR;
+ }
+ err = GENERAL_ERROR;
+ return ERROR;
+ case KEY_CREATED:
+ return QUIT;
+ case QUIT:
+ if (status == GPGME_STATUS_GET_BOOL &&
+ strcmp(args, "keyedit.save.okay") == 0) {
+ return SAVE;
+ }
+ err = GENERAL_ERROR;
+ return ERROR;
+ case ERROR:
+ if (status == GPGME_STATUS_GET_LINE &&
+ strcmp(args, "keyedit.prompt") == 0) {
+ return QUIT;
+ }
+ err = q->lastError();
+ return ERROR;
+ default:
+ err = GENERAL_ERROR;
+ return ERROR;
+ }
+}
+
+GpgAddExistingSubkeyEditInteractor::GpgAddExistingSubkeyEditInteractor(const std::string &keygrip)
+ : EditInteractor{}
+ , d{new Private{this, keygrip}}
+{
+}
+
+GpgAddExistingSubkeyEditInteractor::~GpgAddExistingSubkeyEditInteractor() = default;
+
+void GpgAddExistingSubkeyEditInteractor::setExpiry(const std::string &timeString)
+{
+ d->expiry = timeString;
+}
+
+const char *GpgAddExistingSubkeyEditInteractor::action(Error &err) const
+{
+ return d->action(err);
+}
+
+unsigned int GpgAddExistingSubkeyEditInteractor::nextState(unsigned int status, const char *args, Error &err) const
+{
+ return d->nextState(status, args, err);
+}
diff --git a/lang/cpp/src/gpgaddexistingsubkeyeditinteractor.h b/lang/cpp/src/gpgaddexistingsubkeyeditinteractor.h
new file mode 100644
index 0000000..c30f18e
--- /dev/null
+++ b/lang/cpp/src/gpgaddexistingsubkeyeditinteractor.h
@@ -0,0 +1,59 @@
+/*
+ gpgaddexistingsubkeyeditinteractor.h - Edit Interactor to add an existing subkey to an OpenPGP key
+ Copyright (c) 2022 g10 Code GmbH
+ Software engineering by Ingo Klöcker <dev@ingo-kloecker.de>
+
+ This file is part of GPGME++.
+
+ GPGME++ is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Library General Public
+ License as published by the Free Software Foundation; either
+ version 2 of the License, or (at your option) any later version.
+
+ GPGME++ is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU Library General Public License for more details.
+
+ You should have received a copy of the GNU Library General Public License
+ along with GPGME++; see the file COPYING.LIB. If not, write to the
+ Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+ Boston, MA 02110-1301, USA.
+*/
+
+#ifndef __GPGMEPP_GPGADDEXISTINGSUBKEYEDITINTERACTOR_H__
+#define __GPGMEPP_GPGADDEXISTINGSUBKEYEDITINTERACTOR_H__
+
+#include "editinteractor.h"
+
+#include <memory>
+
+namespace GpgME
+{
+
+class GPGMEPP_EXPORT GpgAddExistingSubkeyEditInteractor : public EditInteractor
+{
+public:
+ /** Edit interactor to add the existing subkey with keygrip \a keygrip
+ * to the key a key edit operation is working on.
+ **/
+ explicit GpgAddExistingSubkeyEditInteractor(const std::string &keygrip);
+ ~GpgAddExistingSubkeyEditInteractor() override;
+
+ /** Sets the validity period of the added subkey. Use "0" for no expiration
+ * or a simplified ISO date string ("yyyymmddThhmmss") for setting an
+ * expiration date. */
+ void setExpiry(const std::string &timeString);
+
+private:
+ const char *action(Error &err) const override;
+ unsigned int nextState(unsigned int statusCode, const char *args, Error &err) const override;
+
+private:
+ class Private;
+ const std::unique_ptr<Private> d;
+};
+
+} // namespace GpgME
+
+#endif // __GPGMEPP_GPGADDEXISTINGSUBKEYEDITINTERACTOR_H__
diff --git a/lang/cpp/src/importresult.cpp b/lang/cpp/src/importresult.cpp
index 20a3174..803c34d 100644
--- a/lang/cpp/src/importresult.cpp
+++ b/lang/cpp/src/importresult.cpp
@@ -48,7 +48,9 @@ public:
// We just need to handle the pointers in the structs:
for (gpgme_import_status_t is = r.imports ; is ; is = is->next) {
gpgme_import_status_t copy = new _gpgme_import_status(*is);
- copy->fpr = strdup(is->fpr);
+ if (is->fpr) {
+ copy->fpr = strdup(is->fpr);
+ }
copy->next = nullptr;
imports.push_back(copy);
}
diff --git a/lang/cpp/src/util.cpp b/lang/cpp/src/util.cpp
new file mode 100644
index 0000000..9104435
--- /dev/null
+++ b/lang/cpp/src/util.cpp
@@ -0,0 +1,47 @@
+/*
+ util.cpp - some internal helpers
+ Copyright (c) 2022 g10 Code GmbH
+ Software engineering by Ingo Klöcker <dev@ingo-kloecker.de>
+
+ This file is part of GPGME++.
+
+ GPGME++ is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Library General Public
+ License as published by the Free Software Foundation; either
+ version 2 of the License, or (at your option) any later version.
+
+ GPGME++ is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU Library General Public License for more details.
+
+ You should have received a copy of the GNU Library General Public License
+ along with GPGME++; see the file COPYING.LIB. If not, write to the
+ Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+ Boston, MA 02110-1301, USA.
+*/
+
+#ifdef HAVE_CONFIG_H
+ #include "config.h"
+#endif
+
+#include "util.h"
+
+#include <functional>
+
+StringsToCStrings::StringsToCStrings(const std::vector<std::string>& v)
+ : m_strings{v}
+{
+}
+
+const char **StringsToCStrings::c_strs() const
+{
+ if (m_cstrings.empty()) {
+ m_cstrings.reserve(m_strings.size() + 1);
+ std::transform(std::begin(m_strings), std::end(m_strings),
+ std::back_inserter(m_cstrings),
+ std::mem_fn(&std::string::c_str));
+ m_cstrings.push_back(nullptr);
+ }
+ return m_cstrings.data();
+}
diff --git a/lang/cpp/src/util.h b/lang/cpp/src/util.h
index e04115b..b6f9ca5 100644
--- a/lang/cpp/src/util.h
+++ b/lang/cpp/src/util.h
@@ -1,8 +1,10 @@
/*
- util.h - some inline helper functions
+ util.h - some internal helpers
Copyright (C) 2004 Klarälvdalens Datakonsult AB
2016 Bundesamt für Sicherheit in der Informationstechnik
Software engineering by Intevation GmbH
+ Copyright (c) 2022 g10 Code GmbH
+ Software engineering by Ingo Klöcker <dev@ingo-kloecker.de>
This file is part of GPGME++.
@@ -175,4 +177,25 @@ static inline gpgme_sig_notation_flags_t add_to_gpgme_sig_notation_flags_t(unsi
return static_cast<gpgme_sig_notation_flags_t>(result);
}
+/**
+ * Adapter for passing a vector of strings as NULL-terminated array of
+ * const char* to the C-interface of gpgme.
+ */
+class StringsToCStrings
+{
+public:
+ explicit StringsToCStrings(const std::vector<std::string> &v);
+ ~StringsToCStrings() = default;
+
+ StringsToCStrings(const StringsToCStrings &) = delete;
+ StringsToCStrings &operator=(const StringsToCStrings &) = delete;
+ StringsToCStrings(StringsToCStrings &&) = delete;
+ StringsToCStrings &operator=(StringsToCStrings &&) = delete;
+
+ const char **c_strs() const;
+private:
+ const std::vector<std::string> m_strings;
+ mutable std::vector<const char *> m_cstrings;
+};
+
#endif // __GPGMEPP_UTIL_H__
diff --git a/lang/cpp/tests/Makefile.am b/lang/cpp/tests/Makefile.am
index 0b27595..9e67dff 100644
--- a/lang/cpp/tests/Makefile.am
+++ b/lang/cpp/tests/Makefile.am
@@ -32,5 +32,14 @@ AM_CPPFLAGS = -I$(top_srcdir)/lang/cpp/src -I$(top_builddir)/src \
run_getkey_SOURCES = run-getkey.cpp
run_keylist_SOURCES = run-keylist.cpp
run_verify_SOURCES = run-verify.cpp
+if !HAVE_W32_SYSTEM
+run_wkdlookup_SOURCES = run-wkdlookup.cpp
+endif
-noinst_PROGRAMS = run-getkey run-keylist run-verify
+if HAVE_W32_SYSTEM
+programs_unix =
+else
+programs_unix = run-wkdlookup
+endif
+
+noinst_PROGRAMS = run-getkey run-keylist run-verify $(programs_unix)
diff --git a/lang/cpp/tests/Makefile.in b/lang/cpp/tests/Makefile.in
index a675bf1..280ffec 100644
--- a/lang/cpp/tests/Makefile.in
+++ b/lang/cpp/tests/Makefile.in
@@ -107,7 +107,7 @@ POST_UNINSTALL = :
build_triplet = @build@
host_triplet = @host@
noinst_PROGRAMS = run-getkey$(EXEEXT) run-keylist$(EXEEXT) \
- run-verify$(EXEEXT)
+ run-verify$(EXEEXT) $(am__EXEEXT_1)
subdir = lang/cpp/tests
ACLOCAL_M4 = $(top_srcdir)/aclocal.m4
am__aclocal_m4_deps = $(top_srcdir)/m4/ax_cxx_compile_stdcxx.m4 \
@@ -128,6 +128,7 @@ mkinstalldirs = $(SHELL) $(top_srcdir)/build-aux/mkinstalldirs
CONFIG_HEADER = $(top_builddir)/conf/config.h
CONFIG_CLEAN_FILES =
CONFIG_CLEAN_VPATH_FILES =
+@HAVE_W32_SYSTEM_FALSE@am__EXEEXT_1 = run-wkdlookup$(EXEEXT)
PROGRAMS = $(noinst_PROGRAMS)
am_run_getkey_OBJECTS = run-getkey.$(OBJEXT)
run_getkey_OBJECTS = $(am_run_getkey_OBJECTS)
@@ -148,6 +149,13 @@ run_verify_OBJECTS = $(am_run_verify_OBJECTS)
run_verify_LDADD = $(LDADD)
run_verify_DEPENDENCIES = ../../cpp/src/libgpgmepp.la \
../../../src/libgpgme.la
+am__run_wkdlookup_SOURCES_DIST = run-wkdlookup.cpp
+@HAVE_W32_SYSTEM_FALSE@am_run_wkdlookup_OBJECTS = \
+@HAVE_W32_SYSTEM_FALSE@ run-wkdlookup.$(OBJEXT)
+run_wkdlookup_OBJECTS = $(am_run_wkdlookup_OBJECTS)
+run_wkdlookup_LDADD = $(LDADD)
+run_wkdlookup_DEPENDENCIES = ../../cpp/src/libgpgmepp.la \
+ ../../../src/libgpgme.la
AM_V_P = $(am__v_P_@AM_V@)
am__v_P_ = $(am__v_P_@AM_DEFAULT_V@)
am__v_P_0 = false
@@ -164,7 +172,8 @@ DEFAULT_INCLUDES = -I.@am__isrc@ -I$(top_builddir)/conf
depcomp = $(SHELL) $(top_srcdir)/build-aux/depcomp
am__maybe_remake_depfiles = depfiles
am__depfiles_remade = ./$(DEPDIR)/run-getkey.Po \
- ./$(DEPDIR)/run-keylist.Po ./$(DEPDIR)/run-verify.Po
+ ./$(DEPDIR)/run-keylist.Po ./$(DEPDIR)/run-verify.Po \
+ ./$(DEPDIR)/run-wkdlookup.Po
am__mv = mv -f
CXXCOMPILE = $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) \
$(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS)
@@ -185,9 +194,9 @@ am__v_CXXLD_ = $(am__v_CXXLD_@AM_DEFAULT_V@)
am__v_CXXLD_0 = @echo " CXXLD " $@;
am__v_CXXLD_1 =
SOURCES = $(run_getkey_SOURCES) $(run_keylist_SOURCES) \
- $(run_verify_SOURCES)
+ $(run_verify_SOURCES) $(run_wkdlookup_SOURCES)
DIST_SOURCES = $(run_getkey_SOURCES) $(run_keylist_SOURCES) \
- $(run_verify_SOURCES)
+ $(run_verify_SOURCES) $(am__run_wkdlookup_SOURCES_DIST)
am__can_run_installinfo = \
case $$AM_UPDATE_INFO_DIR in \
n|no|NO) false;; \
@@ -427,6 +436,9 @@ AM_CPPFLAGS = -I$(top_srcdir)/lang/cpp/src -I$(top_builddir)/src \
run_getkey_SOURCES = run-getkey.cpp
run_keylist_SOURCES = run-keylist.cpp
run_verify_SOURCES = run-verify.cpp
+@HAVE_W32_SYSTEM_FALSE@run_wkdlookup_SOURCES = run-wkdlookup.cpp
+@HAVE_W32_SYSTEM_FALSE@programs_unix = run-wkdlookup
+@HAVE_W32_SYSTEM_TRUE@programs_unix =
all: all-am
.SUFFIXES:
@@ -482,6 +494,10 @@ run-verify$(EXEEXT): $(run_verify_OBJECTS) $(run_verify_DEPENDENCIES) $(EXTRA_ru
@rm -f run-verify$(EXEEXT)
$(AM_V_CXXLD)$(CXXLINK) $(run_verify_OBJECTS) $(run_verify_LDADD) $(LIBS)
+run-wkdlookup$(EXEEXT): $(run_wkdlookup_OBJECTS) $(run_wkdlookup_DEPENDENCIES) $(EXTRA_run_wkdlookup_DEPENDENCIES)
+ @rm -f run-wkdlookup$(EXEEXT)
+ $(AM_V_CXXLD)$(CXXLINK) $(run_wkdlookup_OBJECTS) $(run_wkdlookup_LDADD) $(LIBS)
+
mostlyclean-compile:
-rm -f *.$(OBJEXT)
@@ -491,6 +507,7 @@ distclean-compile:
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/run-getkey.Po@am__quote@ # am--include-marker
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/run-keylist.Po@am__quote@ # am--include-marker
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/run-verify.Po@am__quote@ # am--include-marker
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/run-wkdlookup.Po@am__quote@ # am--include-marker
$(am__depfiles_remade):
@$(MKDIR_P) $(@D)
@@ -653,6 +670,7 @@ distclean: distclean-am
-rm -f ./$(DEPDIR)/run-getkey.Po
-rm -f ./$(DEPDIR)/run-keylist.Po
-rm -f ./$(DEPDIR)/run-verify.Po
+ -rm -f ./$(DEPDIR)/run-wkdlookup.Po
-rm -f Makefile
distclean-am: clean-am distclean-compile distclean-generic \
distclean-tags
@@ -701,6 +719,7 @@ maintainer-clean: maintainer-clean-am
-rm -f ./$(DEPDIR)/run-getkey.Po
-rm -f ./$(DEPDIR)/run-keylist.Po
-rm -f ./$(DEPDIR)/run-verify.Po
+ -rm -f ./$(DEPDIR)/run-wkdlookup.Po
-rm -f Makefile
maintainer-clean-am: distclean-am maintainer-clean-generic
diff --git a/lang/cpp/tests/run-wkdlookup.cpp b/lang/cpp/tests/run-wkdlookup.cpp
new file mode 100644
index 0000000..71c4e70
--- /dev/null
+++ b/lang/cpp/tests/run-wkdlookup.cpp
@@ -0,0 +1,156 @@
+/*
+ run-wkdlookup.cpp
+
+ This file is part of GpgMEpp's test suite.
+ Copyright (c) 2021 g10 Code GmbH
+ Software engineering by Ingo Klöcker <dev@ingo-kloecker.de>
+
+ GPGME++ is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Library General Public
+ License as published by the Free Software Foundation; either
+ version 2 of the License, or (at your option) any later version.
+
+ GPGME++ is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU Library General Public License for more details.
+
+ You should have received a copy of the GNU Library General Public License
+ along with GPGME++; see the file COPYING.LIB. If not, write to the
+ Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+ Boston, MA 02110-1301, USA.
+*/
+
+#ifdef HAVE_CONFIG_H
+ #include "config.h"
+#endif
+
+#include "context.h"
+#include "data.h"
+#include "defaultassuantransaction.h"
+#include "key.h"
+
+#include <memory>
+#include <sstream>
+#include <iostream>
+#include <thread>
+
+using namespace GpgME;
+
+static int
+show_usage (int ex)
+{
+ fputs ("usage: run-wkdlookup <email address>\n\n"
+ , stderr);
+ exit (ex);
+}
+
+int
+main (int argc, char **argv)
+{
+ int last_argc = -1;
+
+ if (argc) {
+ argc--; argv++;
+ }
+
+ while (argc && last_argc != argc ) {
+ last_argc = argc;
+ if (!strcmp (*argv, "--")) {
+ argc--; argv++;
+ break;
+ } else if (!strcmp (*argv, "--help")) {
+ show_usage (0);
+ } else if (!strncmp (*argv, "--", 2)) {
+ show_usage (1);
+ }
+ }
+
+ if (argc != 1) {
+ show_usage (1);
+ }
+
+ const std::string email{*argv};
+
+ GpgME::initializeLibrary();
+ Error err;
+ auto ctx = std::unique_ptr<Context>{Context::createForEngine(AssuanEngine, &err)};
+ if (!ctx) {
+ std::cerr << "Failed to get context (Error: " << err.asString() << ")\n";
+ return -1;
+ }
+
+ const std::string dirmngrSocket = GpgME::dirInfo("dirmngr-socket");
+ if ((err = ctx->setEngineFileName(dirmngrSocket.c_str()))) {
+ std::cerr << "Failed to set engine file name (Error: " << err.asString() << ")\n";
+ return -1;
+ }
+ if ((err = ctx->setEngineHomeDirectory(""))) {
+ std::cerr << "Failed to set engine home directory (Error: " << err.asString() << ")\n";
+ return -1;
+ }
+
+ // try do connect to dirmngr
+ err = ctx->assuanTransact("GETINFO version");
+ if (err && err.code() != GPG_ERR_ASS_CONNECT_FAILED) {
+ std::cerr << "Failed to start assuan transaction (Error: " << err.asString() << ")\n";
+ return -1;
+ }
+ if (err.code() == GPG_ERR_ASS_CONNECT_FAILED) {
+ std::cerr << "Starting dirmngr ...\n";
+ auto spawnCtx = std::unique_ptr<Context>{Context::createForEngine(SpawnEngine, &err)};
+ if (!spawnCtx) {
+ std::cerr << "Failed to get context for spawn engine (Error: " << err.asString() << ")\n";
+ return -1;
+ }
+
+ const auto dirmngrProgram = GpgME::dirInfo("dirmngr-name");
+ const auto homedir = GpgME::dirInfo("homedir");
+ const char *argv[] = {
+ dirmngrProgram,
+ "--homedir",
+ homedir,
+ "--daemon",
+ NULL
+ };
+ auto ignoreIO = Data{Data::null};
+ err = spawnCtx->spawnAsync(dirmngrProgram, argv,
+ ignoreIO, ignoreIO, ignoreIO,
+ Context::SpawnDetached);
+ if (err) {
+ std::cerr << "Failed to start dirmngr (Error: " << err.asString() << ")\n";
+ return -1;
+ }
+
+ // wait for socket to become available
+ int cnt = 0;
+ do {
+ ++cnt;
+ std::cerr << "Waiting for dirmngr to start ...\n";
+ std::this_thread::sleep_for(std::chrono::milliseconds{250 * cnt});
+ err = ctx->assuanTransact("GETINFO version");
+ } while (err.code() == GPG_ERR_ASS_CONNECT_FAILED && cnt < 5);
+ }
+
+ const auto cmd = std::string{"WKD_GET "} + email;
+ err = ctx->assuanTransact(cmd.c_str());
+ if (err && err.code() != GPG_ERR_NO_NAME && err.code() != GPG_ERR_NO_DATA) {
+ std::cerr << "Error: WKD_GET returned " << err.asString() << "\n";
+ return -1;
+ }
+
+ const auto transaction = std::unique_ptr<DefaultAssuanTransaction>(dynamic_cast<DefaultAssuanTransaction*>(ctx->takeLastAssuanTransaction().release()));
+ const auto source = transaction->firstStatusLine("SOURCE");
+ const auto rawData = transaction->data();
+ if (rawData.size() == 0) {
+ std::cout << "No key found for " << email << "\n";
+ } else {
+ const auto data = GpgME::Data{rawData.c_str(), rawData.size()};
+ const auto keys = data.toKeys(GpgME::OpenPGP);
+ for (const auto &key : keys) {
+ std::cout << "Found key for " << email << " at " << source << ":\n" << key << "\n";
+ }
+ }
+
+ return 0;
+}
diff --git a/lang/qt/src/AddExistingSubkeyJob b/lang/qt/src/AddExistingSubkeyJob
new file mode 100644
index 0000000..72e02f8
--- /dev/null
+++ b/lang/qt/src/AddExistingSubkeyJob
@@ -0,0 +1 @@
+#include "qgpgme/addexistingsubkeyjob.h"
diff --git a/lang/qt/src/Makefile.am b/lang/qt/src/Makefile.am
index 683b44c..d47da89 100644
--- a/lang/qt/src/Makefile.am
+++ b/lang/qt/src/Makefile.am
@@ -27,25 +27,29 @@ qgpgme_sources = \
dataprovider.cpp \
debug.cpp \
job.cpp multideletejob.cpp qgpgmeadduseridjob.cpp \
+ qgpgmeaddexistingsubkeyjob.cpp \
qgpgmebackend.cpp qgpgmechangeexpiryjob.cpp qgpgmechangeownertrustjob.cpp \
qgpgmechangepasswdjob.cpp qgpgmedecryptjob.cpp \
qgpgmedecryptverifyjob.cpp qgpgmedeletejob.cpp qgpgmedownloadjob.cpp \
qgpgmeencryptjob.cpp qgpgmeexportjob.cpp qgpgmeimportfromkeyserverjob.cpp \
qgpgmeimportjob.cpp qgpgmekeygenerationjob.cpp qgpgmekeylistjob.cpp \
qgpgmelistallkeysjob.cpp qgpgmenewcryptoconfig.cpp \
+ qgpgmereceivekeysjob.cpp \
qgpgmerefreshkeysjob.cpp \
- qgpgmesecretkeyexportjob.cpp qgpgmesignencryptjob.cpp \
+ qgpgmesignencryptjob.cpp \
qgpgmesignjob.cpp qgpgmesignkeyjob.cpp qgpgmeverifydetachedjob.cpp \
- qgpgmeverifyopaquejob.cpp threadedjobmixin.cpp \
+ qgpgmeverifyopaquejob.cpp qgpgmewkdlookupjob.cpp threadedjobmixin.cpp \
qgpgmekeyformailboxjob.cpp qgpgme_debug.cpp \
qgpgmetofupolicyjob.cpp qgpgmequickjob.cpp \
defaultkeygenerationjob.cpp qgpgmewkspublishjob.cpp \
- qgpgmegpgcardjob.cpp \
- dn.cpp cryptoconfig.cpp
+ qgpgmegpgcardjob.cpp changeexpiryjob.cpp importjob.cpp \
+ dn.cpp cryptoconfig.cpp wkdlookupresult.cpp \
+ util.cpp
# If you add one here make sure that you also add one in camelcase
qgpgme_headers= \
abstractimportjob.h \
+ addexistingsubkeyjob.h \
adduseridjob.h \
changeexpiryjob.h \
changeownertrustjob.h \
@@ -65,6 +69,7 @@ qgpgme_headers= \
qgpgme_export.h \
qgpgmenewcryptoconfig.h \
quickjob.h \
+ receivekeysjob.h \
specialjob.h \
signjob.h \
signkeyjob.h \
@@ -81,11 +86,14 @@ qgpgme_headers= \
verifydetachedjob.h \
defaultkeygenerationjob.h \
tofupolicyjob.h \
+ wkdlookupjob.h \
+ wkdlookupresult.h \
wkspublishjob.h \
gpgcardjob.h \
dn.h
camelcase_headers= \
+ AddExistingSubkeyJob \
AddUserIDJob \
AbstractImportJob \
ChangeExpiryJob \
@@ -105,6 +113,7 @@ camelcase_headers= \
Protocol \
QGpgMENewCryptoConfig \
QuickJob \
+ ReceiveKeysJob \
SpecialJob \
SignJob \
SignKeyJob \
@@ -121,6 +130,8 @@ camelcase_headers= \
VerifyDetachedJob \
KeyForMailboxJob \
DefaultKeyGenerationJob \
+ WKDLookupJob \
+ WKDLookupResult \
WKSPublishJob \
TofuPolicyJob \
GpgCardJob
@@ -128,6 +139,8 @@ camelcase_headers= \
private_qgpgme_headers = \
qgpgme_export.h \
protocol_p.h \
+ job_p.h \
+ qgpgmeaddexistingsubkeyjob.h \
qgpgmeadduseridjob.h \
qgpgmebackend.h \
qgpgmechangeexpiryjob.h \
@@ -144,22 +157,25 @@ private_qgpgme_headers = \
qgpgmekeygenerationjob.h \
qgpgmekeylistjob.h \
qgpgmelistallkeysjob.h \
+ qgpgmereceivekeysjob.h \
qgpgmerefreshkeysjob.h \
- qgpgmesecretkeyexportjob.h \
qgpgmesignencryptjob.h \
qgpgmesignjob.h \
qgpgmesignkeyjob.h \
qgpgmeverifydetachedjob.h \
qgpgmeverifyopaquejob.h \
+ qgpgmewkdlookupjob.h \
qgpgmekeyformailboxjob.h \
qgpgmewkspublishjob.h \
qgpgmetofupolicyjob.h \
qgpgmegpgcardjob.h \
qgpgmequickjob.h \
- threadedjobmixin.h
+ threadedjobmixin.h \
+ util.h
qgpgme_moc_sources = \
abstractimportjob.moc \
+ addexistingsubkeyjob.moc \
adduseridjob.moc \
changeexpiryjob.moc \
changeownertrustjob.moc \
@@ -178,6 +194,7 @@ qgpgme_moc_sources = \
keylistjob.moc \
listallkeysjob.moc \
multideletejob.moc \
+ qgpgmeaddexistingsubkeyjob.moc \
qgpgmeadduseridjob.moc \
qgpgmechangeexpiryjob.moc \
qgpgmechangeownertrustjob.moc \
@@ -193,16 +210,18 @@ qgpgme_moc_sources = \
qgpgmekeygenerationjob.moc \
qgpgmekeylistjob.moc \
qgpgmelistallkeysjob.moc \
+ qgpgmereceivekeysjob.moc \
qgpgmerefreshkeysjob.moc \
- qgpgmesecretkeyexportjob.moc \
qgpgmesignencryptjob.moc \
qgpgmesignjob.moc \
qgpgmesignkeyjob.moc \
qgpgmeverifydetachedjob.moc \
qgpgmeverifyopaquejob.moc \
+ qgpgmewkdlookupjob.moc \
qgpgmewkspublishjob.moc \
tofupolicyjob.moc \
qgpgmetofupolicyjob.moc \
+ receivekeysjob.moc \
refreshkeysjob.moc \
signencryptjob.moc \
signjob.moc \
@@ -210,6 +229,7 @@ qgpgme_moc_sources = \
specialjob.moc \
verifydetachedjob.moc \
verifyopaquejob.moc \
+ wkdlookupjob.moc \
keyformailboxjob.moc \
wkspublishjob.moc \
qgpgmekeyformailboxjob.moc \
diff --git a/lang/qt/src/Makefile.in b/lang/qt/src/Makefile.in
index 8e37198..2f09648 100644
--- a/lang/qt/src/Makefile.in
+++ b/lang/qt/src/Makefile.in
@@ -146,21 +146,24 @@ LTLIBRARIES = $(lib_LTLIBRARIES)
libqgpgme_la_DEPENDENCIES = ../../cpp/src/libgpgmepp.la \
../../../src/libgpgme.la
am__objects_1 = dataprovider.lo debug.lo job.lo multideletejob.lo \
- qgpgmeadduseridjob.lo qgpgmebackend.lo \
- qgpgmechangeexpiryjob.lo qgpgmechangeownertrustjob.lo \
- qgpgmechangepasswdjob.lo qgpgmedecryptjob.lo \
- qgpgmedecryptverifyjob.lo qgpgmedeletejob.lo \
- qgpgmedownloadjob.lo qgpgmeencryptjob.lo qgpgmeexportjob.lo \
- qgpgmeimportfromkeyserverjob.lo qgpgmeimportjob.lo \
- qgpgmekeygenerationjob.lo qgpgmekeylistjob.lo \
- qgpgmelistallkeysjob.lo qgpgmenewcryptoconfig.lo \
- qgpgmerefreshkeysjob.lo qgpgmesecretkeyexportjob.lo \
- qgpgmesignencryptjob.lo qgpgmesignjob.lo qgpgmesignkeyjob.lo \
+ qgpgmeadduseridjob.lo qgpgmeaddexistingsubkeyjob.lo \
+ qgpgmebackend.lo qgpgmechangeexpiryjob.lo \
+ qgpgmechangeownertrustjob.lo qgpgmechangepasswdjob.lo \
+ qgpgmedecryptjob.lo qgpgmedecryptverifyjob.lo \
+ qgpgmedeletejob.lo qgpgmedownloadjob.lo qgpgmeencryptjob.lo \
+ qgpgmeexportjob.lo qgpgmeimportfromkeyserverjob.lo \
+ qgpgmeimportjob.lo qgpgmekeygenerationjob.lo \
+ qgpgmekeylistjob.lo qgpgmelistallkeysjob.lo \
+ qgpgmenewcryptoconfig.lo qgpgmereceivekeysjob.lo \
+ qgpgmerefreshkeysjob.lo qgpgmesignencryptjob.lo \
+ qgpgmesignjob.lo qgpgmesignkeyjob.lo \
qgpgmeverifydetachedjob.lo qgpgmeverifyopaquejob.lo \
- threadedjobmixin.lo qgpgmekeyformailboxjob.lo qgpgme_debug.lo \
+ qgpgmewkdlookupjob.lo threadedjobmixin.lo \
+ qgpgmekeyformailboxjob.lo qgpgme_debug.lo \
qgpgmetofupolicyjob.lo qgpgmequickjob.lo \
defaultkeygenerationjob.lo qgpgmewkspublishjob.lo \
- qgpgmegpgcardjob.lo dn.lo cryptoconfig.lo
+ qgpgmegpgcardjob.lo changeexpiryjob.lo importjob.lo dn.lo \
+ cryptoconfig.lo wkdlookupresult.lo util.lo
am__objects_2 =
am_libqgpgme_la_OBJECTS = $(am__objects_1) $(am__objects_2) \
$(am__objects_2)
@@ -189,11 +192,13 @@ am__v_at_1 =
DEFAULT_INCLUDES = -I.@am__isrc@ -I$(top_builddir)/conf
depcomp = $(SHELL) $(top_srcdir)/build-aux/depcomp
am__maybe_remake_depfiles = depfiles
-am__depfiles_remade = ./$(DEPDIR)/cryptoconfig.Plo \
- ./$(DEPDIR)/dataprovider.Plo ./$(DEPDIR)/debug.Plo \
- ./$(DEPDIR)/defaultkeygenerationjob.Plo ./$(DEPDIR)/dn.Plo \
+am__depfiles_remade = ./$(DEPDIR)/changeexpiryjob.Plo \
+ ./$(DEPDIR)/cryptoconfig.Plo ./$(DEPDIR)/dataprovider.Plo \
+ ./$(DEPDIR)/debug.Plo ./$(DEPDIR)/defaultkeygenerationjob.Plo \
+ ./$(DEPDIR)/dn.Plo ./$(DEPDIR)/importjob.Plo \
./$(DEPDIR)/job.Plo ./$(DEPDIR)/multideletejob.Plo \
./$(DEPDIR)/qgpgme_debug.Plo \
+ ./$(DEPDIR)/qgpgmeaddexistingsubkeyjob.Plo \
./$(DEPDIR)/qgpgmeadduseridjob.Plo \
./$(DEPDIR)/qgpgmebackend.Plo \
./$(DEPDIR)/qgpgmechangeexpiryjob.Plo \
@@ -214,15 +219,17 @@ am__depfiles_remade = ./$(DEPDIR)/cryptoconfig.Plo \
./$(DEPDIR)/qgpgmelistallkeysjob.Plo \
./$(DEPDIR)/qgpgmenewcryptoconfig.Plo \
./$(DEPDIR)/qgpgmequickjob.Plo \
+ ./$(DEPDIR)/qgpgmereceivekeysjob.Plo \
./$(DEPDIR)/qgpgmerefreshkeysjob.Plo \
- ./$(DEPDIR)/qgpgmesecretkeyexportjob.Plo \
./$(DEPDIR)/qgpgmesignencryptjob.Plo \
./$(DEPDIR)/qgpgmesignjob.Plo ./$(DEPDIR)/qgpgmesignkeyjob.Plo \
./$(DEPDIR)/qgpgmetofupolicyjob.Plo \
./$(DEPDIR)/qgpgmeverifydetachedjob.Plo \
./$(DEPDIR)/qgpgmeverifyopaquejob.Plo \
+ ./$(DEPDIR)/qgpgmewkdlookupjob.Plo \
./$(DEPDIR)/qgpgmewkspublishjob.Plo \
- ./$(DEPDIR)/threadedjobmixin.Plo
+ ./$(DEPDIR)/threadedjobmixin.Plo ./$(DEPDIR)/util.Plo \
+ ./$(DEPDIR)/wkdlookupresult.Plo
am__mv = mv -f
CXXCOMPILE = $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) \
$(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS)
@@ -523,26 +530,30 @@ qgpgme_sources = \
dataprovider.cpp \
debug.cpp \
job.cpp multideletejob.cpp qgpgmeadduseridjob.cpp \
+ qgpgmeaddexistingsubkeyjob.cpp \
qgpgmebackend.cpp qgpgmechangeexpiryjob.cpp qgpgmechangeownertrustjob.cpp \
qgpgmechangepasswdjob.cpp qgpgmedecryptjob.cpp \
qgpgmedecryptverifyjob.cpp qgpgmedeletejob.cpp qgpgmedownloadjob.cpp \
qgpgmeencryptjob.cpp qgpgmeexportjob.cpp qgpgmeimportfromkeyserverjob.cpp \
qgpgmeimportjob.cpp qgpgmekeygenerationjob.cpp qgpgmekeylistjob.cpp \
qgpgmelistallkeysjob.cpp qgpgmenewcryptoconfig.cpp \
+ qgpgmereceivekeysjob.cpp \
qgpgmerefreshkeysjob.cpp \
- qgpgmesecretkeyexportjob.cpp qgpgmesignencryptjob.cpp \
+ qgpgmesignencryptjob.cpp \
qgpgmesignjob.cpp qgpgmesignkeyjob.cpp qgpgmeverifydetachedjob.cpp \
- qgpgmeverifyopaquejob.cpp threadedjobmixin.cpp \
+ qgpgmeverifyopaquejob.cpp qgpgmewkdlookupjob.cpp threadedjobmixin.cpp \
qgpgmekeyformailboxjob.cpp qgpgme_debug.cpp \
qgpgmetofupolicyjob.cpp qgpgmequickjob.cpp \
defaultkeygenerationjob.cpp qgpgmewkspublishjob.cpp \
- qgpgmegpgcardjob.cpp \
- dn.cpp cryptoconfig.cpp
+ qgpgmegpgcardjob.cpp changeexpiryjob.cpp importjob.cpp \
+ dn.cpp cryptoconfig.cpp wkdlookupresult.cpp \
+ util.cpp
# If you add one here make sure that you also add one in camelcase
qgpgme_headers = \
abstractimportjob.h \
+ addexistingsubkeyjob.h \
adduseridjob.h \
changeexpiryjob.h \
changeownertrustjob.h \
@@ -562,6 +573,7 @@ qgpgme_headers = \
qgpgme_export.h \
qgpgmenewcryptoconfig.h \
quickjob.h \
+ receivekeysjob.h \
specialjob.h \
signjob.h \
signkeyjob.h \
@@ -578,11 +590,14 @@ qgpgme_headers = \
verifydetachedjob.h \
defaultkeygenerationjob.h \
tofupolicyjob.h \
+ wkdlookupjob.h \
+ wkdlookupresult.h \
wkspublishjob.h \
gpgcardjob.h \
dn.h
camelcase_headers = \
+ AddExistingSubkeyJob \
AddUserIDJob \
AbstractImportJob \
ChangeExpiryJob \
@@ -602,6 +617,7 @@ camelcase_headers = \
Protocol \
QGpgMENewCryptoConfig \
QuickJob \
+ ReceiveKeysJob \
SpecialJob \
SignJob \
SignKeyJob \
@@ -618,6 +634,8 @@ camelcase_headers = \
VerifyDetachedJob \
KeyForMailboxJob \
DefaultKeyGenerationJob \
+ WKDLookupJob \
+ WKDLookupResult \
WKSPublishJob \
TofuPolicyJob \
GpgCardJob
@@ -625,6 +643,8 @@ camelcase_headers = \
private_qgpgme_headers = \
qgpgme_export.h \
protocol_p.h \
+ job_p.h \
+ qgpgmeaddexistingsubkeyjob.h \
qgpgmeadduseridjob.h \
qgpgmebackend.h \
qgpgmechangeexpiryjob.h \
@@ -641,22 +661,25 @@ private_qgpgme_headers = \
qgpgmekeygenerationjob.h \
qgpgmekeylistjob.h \
qgpgmelistallkeysjob.h \
+ qgpgmereceivekeysjob.h \
qgpgmerefreshkeysjob.h \
- qgpgmesecretkeyexportjob.h \
qgpgmesignencryptjob.h \
qgpgmesignjob.h \
qgpgmesignkeyjob.h \
qgpgmeverifydetachedjob.h \
qgpgmeverifyopaquejob.h \
+ qgpgmewkdlookupjob.h \
qgpgmekeyformailboxjob.h \
qgpgmewkspublishjob.h \
qgpgmetofupolicyjob.h \
qgpgmegpgcardjob.h \
qgpgmequickjob.h \
- threadedjobmixin.h
+ threadedjobmixin.h \
+ util.h
qgpgme_moc_sources = \
abstractimportjob.moc \
+ addexistingsubkeyjob.moc \
adduseridjob.moc \
changeexpiryjob.moc \
changeownertrustjob.moc \
@@ -675,6 +698,7 @@ qgpgme_moc_sources = \
keylistjob.moc \
listallkeysjob.moc \
multideletejob.moc \
+ qgpgmeaddexistingsubkeyjob.moc \
qgpgmeadduseridjob.moc \
qgpgmechangeexpiryjob.moc \
qgpgmechangeownertrustjob.moc \
@@ -690,16 +714,18 @@ qgpgme_moc_sources = \
qgpgmekeygenerationjob.moc \
qgpgmekeylistjob.moc \
qgpgmelistallkeysjob.moc \
+ qgpgmereceivekeysjob.moc \
qgpgmerefreshkeysjob.moc \
- qgpgmesecretkeyexportjob.moc \
qgpgmesignencryptjob.moc \
qgpgmesignjob.moc \
qgpgmesignkeyjob.moc \
qgpgmeverifydetachedjob.moc \
qgpgmeverifyopaquejob.moc \
+ qgpgmewkdlookupjob.moc \
qgpgmewkspublishjob.moc \
tofupolicyjob.moc \
qgpgmetofupolicyjob.moc \
+ receivekeysjob.moc \
refreshkeysjob.moc \
signencryptjob.moc \
signjob.moc \
@@ -707,6 +733,7 @@ qgpgme_moc_sources = \
specialjob.moc \
verifydetachedjob.moc \
verifyopaquejob.moc \
+ wkdlookupjob.moc \
keyformailboxjob.moc \
wkspublishjob.moc \
qgpgmekeyformailboxjob.moc \
@@ -828,14 +855,17 @@ mostlyclean-compile:
distclean-compile:
-rm -f *.tab.c
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/changeexpiryjob.Plo@am__quote@ # am--include-marker
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/cryptoconfig.Plo@am__quote@ # am--include-marker
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/dataprovider.Plo@am__quote@ # am--include-marker
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/debug.Plo@am__quote@ # am--include-marker
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/defaultkeygenerationjob.Plo@am__quote@ # am--include-marker
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/dn.Plo@am__quote@ # am--include-marker
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/importjob.Plo@am__quote@ # am--include-marker
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/job.Plo@am__quote@ # am--include-marker
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/multideletejob.Plo@am__quote@ # am--include-marker
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/qgpgme_debug.Plo@am__quote@ # am--include-marker
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/qgpgmeaddexistingsubkeyjob.Plo@am__quote@ # am--include-marker
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/qgpgmeadduseridjob.Plo@am__quote@ # am--include-marker
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/qgpgmebackend.Plo@am__quote@ # am--include-marker
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/qgpgmechangeexpiryjob.Plo@am__quote@ # am--include-marker
@@ -856,16 +886,19 @@ distclean-compile:
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/qgpgmelistallkeysjob.Plo@am__quote@ # am--include-marker
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/qgpgmenewcryptoconfig.Plo@am__quote@ # am--include-marker
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/qgpgmequickjob.Plo@am__quote@ # am--include-marker
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/qgpgmereceivekeysjob.Plo@am__quote@ # am--include-marker
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/qgpgmerefreshkeysjob.Plo@am__quote@ # am--include-marker
-@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/qgpgmesecretkeyexportjob.Plo@am__quote@ # am--include-marker
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/qgpgmesignencryptjob.Plo@am__quote@ # am--include-marker
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/qgpgmesignjob.Plo@am__quote@ # am--include-marker
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/qgpgmesignkeyjob.Plo@am__quote@ # am--include-marker
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/qgpgmetofupolicyjob.Plo@am__quote@ # am--include-marker
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/qgpgmeverifydetachedjob.Plo@am__quote@ # am--include-marker
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/qgpgmeverifyopaquejob.Plo@am__quote@ # am--include-marker
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/qgpgmewkdlookupjob.Plo@am__quote@ # am--include-marker
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/qgpgmewkspublishjob.Plo@am__quote@ # am--include-marker
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/threadedjobmixin.Plo@am__quote@ # am--include-marker
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/util.Plo@am__quote@ # am--include-marker
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/wkdlookupresult.Plo@am__quote@ # am--include-marker
$(am__depfiles_remade):
@$(MKDIR_P) $(@D)
@@ -1096,14 +1129,17 @@ clean-am: clean-generic clean-libLTLIBRARIES clean-libtool \
mostlyclean-am
distclean: distclean-am
- -rm -f ./$(DEPDIR)/cryptoconfig.Plo
+ -rm -f ./$(DEPDIR)/changeexpiryjob.Plo
+ -rm -f ./$(DEPDIR)/cryptoconfig.Plo
-rm -f ./$(DEPDIR)/dataprovider.Plo
-rm -f ./$(DEPDIR)/debug.Plo
-rm -f ./$(DEPDIR)/defaultkeygenerationjob.Plo
-rm -f ./$(DEPDIR)/dn.Plo
+ -rm -f ./$(DEPDIR)/importjob.Plo
-rm -f ./$(DEPDIR)/job.Plo
-rm -f ./$(DEPDIR)/multideletejob.Plo
-rm -f ./$(DEPDIR)/qgpgme_debug.Plo
+ -rm -f ./$(DEPDIR)/qgpgmeaddexistingsubkeyjob.Plo
-rm -f ./$(DEPDIR)/qgpgmeadduseridjob.Plo
-rm -f ./$(DEPDIR)/qgpgmebackend.Plo
-rm -f ./$(DEPDIR)/qgpgmechangeexpiryjob.Plo
@@ -1124,16 +1160,19 @@ distclean: distclean-am
-rm -f ./$(DEPDIR)/qgpgmelistallkeysjob.Plo
-rm -f ./$(DEPDIR)/qgpgmenewcryptoconfig.Plo
-rm -f ./$(DEPDIR)/qgpgmequickjob.Plo
+ -rm -f ./$(DEPDIR)/qgpgmereceivekeysjob.Plo
-rm -f ./$(DEPDIR)/qgpgmerefreshkeysjob.Plo
- -rm -f ./$(DEPDIR)/qgpgmesecretkeyexportjob.Plo
-rm -f ./$(DEPDIR)/qgpgmesignencryptjob.Plo
-rm -f ./$(DEPDIR)/qgpgmesignjob.Plo
-rm -f ./$(DEPDIR)/qgpgmesignkeyjob.Plo
-rm -f ./$(DEPDIR)/qgpgmetofupolicyjob.Plo
-rm -f ./$(DEPDIR)/qgpgmeverifydetachedjob.Plo
-rm -f ./$(DEPDIR)/qgpgmeverifyopaquejob.Plo
+ -rm -f ./$(DEPDIR)/qgpgmewkdlookupjob.Plo
-rm -f ./$(DEPDIR)/qgpgmewkspublishjob.Plo
-rm -f ./$(DEPDIR)/threadedjobmixin.Plo
+ -rm -f ./$(DEPDIR)/util.Plo
+ -rm -f ./$(DEPDIR)/wkdlookupresult.Plo
-rm -f Makefile
distclean-am: clean-am distclean-compile distclean-generic \
distclean-tags
@@ -1181,14 +1220,17 @@ install-ps-am:
installcheck-am:
maintainer-clean: maintainer-clean-am
- -rm -f ./$(DEPDIR)/cryptoconfig.Plo
+ -rm -f ./$(DEPDIR)/changeexpiryjob.Plo
+ -rm -f ./$(DEPDIR)/cryptoconfig.Plo
-rm -f ./$(DEPDIR)/dataprovider.Plo
-rm -f ./$(DEPDIR)/debug.Plo
-rm -f ./$(DEPDIR)/defaultkeygenerationjob.Plo
-rm -f ./$(DEPDIR)/dn.Plo
+ -rm -f ./$(DEPDIR)/importjob.Plo
-rm -f ./$(DEPDIR)/job.Plo
-rm -f ./$(DEPDIR)/multideletejob.Plo
-rm -f ./$(DEPDIR)/qgpgme_debug.Plo
+ -rm -f ./$(DEPDIR)/qgpgmeaddexistingsubkeyjob.Plo
-rm -f ./$(DEPDIR)/qgpgmeadduseridjob.Plo
-rm -f ./$(DEPDIR)/qgpgmebackend.Plo
-rm -f ./$(DEPDIR)/qgpgmechangeexpiryjob.Plo
@@ -1209,16 +1251,19 @@ maintainer-clean: maintainer-clean-am
-rm -f ./$(DEPDIR)/qgpgmelistallkeysjob.Plo
-rm -f ./$(DEPDIR)/qgpgmenewcryptoconfig.Plo
-rm -f ./$(DEPDIR)/qgpgmequickjob.Plo
+ -rm -f ./$(DEPDIR)/qgpgmereceivekeysjob.Plo
-rm -f ./$(DEPDIR)/qgpgmerefreshkeysjob.Plo
- -rm -f ./$(DEPDIR)/qgpgmesecretkeyexportjob.Plo
-rm -f ./$(DEPDIR)/qgpgmesignencryptjob.Plo
-rm -f ./$(DEPDIR)/qgpgmesignjob.Plo
-rm -f ./$(DEPDIR)/qgpgmesignkeyjob.Plo
-rm -f ./$(DEPDIR)/qgpgmetofupolicyjob.Plo
-rm -f ./$(DEPDIR)/qgpgmeverifydetachedjob.Plo
-rm -f ./$(DEPDIR)/qgpgmeverifyopaquejob.Plo
+ -rm -f ./$(DEPDIR)/qgpgmewkdlookupjob.Plo
-rm -f ./$(DEPDIR)/qgpgmewkspublishjob.Plo
-rm -f ./$(DEPDIR)/threadedjobmixin.Plo
+ -rm -f ./$(DEPDIR)/util.Plo
+ -rm -f ./$(DEPDIR)/wkdlookupresult.Plo
-rm -f Makefile
maintainer-clean-am: distclean-am maintainer-clean-generic
diff --git a/lang/qt/src/ReceiveKeysJob b/lang/qt/src/ReceiveKeysJob
new file mode 100644
index 0000000..4ee4735
--- /dev/null
+++ b/lang/qt/src/ReceiveKeysJob
@@ -0,0 +1 @@
+#include "qgpgme/receivekeysjob.h"
diff --git a/lang/qt/src/WKDLookupJob b/lang/qt/src/WKDLookupJob
new file mode 100644
index 0000000..3b67494
--- /dev/null
+++ b/lang/qt/src/WKDLookupJob
@@ -0,0 +1 @@
+#include "qgpgme/wkdlookupjob.h"
diff --git a/lang/qt/src/WKDLookupResult b/lang/qt/src/WKDLookupResult
new file mode 100644
index 0000000..8833683
--- /dev/null
+++ b/lang/qt/src/WKDLookupResult
@@ -0,0 +1 @@
+#include "qgpgme/wkdlookupresult.h"
diff --git a/lang/qt/src/addexistingsubkeyjob.h b/lang/qt/src/addexistingsubkeyjob.h
new file mode 100644
index 0000000..5465778
--- /dev/null
+++ b/lang/qt/src/addexistingsubkeyjob.h
@@ -0,0 +1,79 @@
+/*
+ addexistingsubkeyjob.h
+
+ This file is part of qgpgme, the Qt API binding for gpgme
+ Copyright (c) 2022 g10 Code GmbH
+ Software engineering by Ingo Klöcker <dev@ingo-kloecker.de>
+
+ QGpgME is free software; you can redistribute it and/or
+ modify it under the terms of the GNU General Public License as
+ published by the Free Software Foundation; either version 2 of the
+ License, or (at your option) any later version.
+
+ QGpgME is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
+
+ In addition, as a special exception, the copyright holders give
+ permission to link the code of this program with any edition of
+ the Qt library by Trolltech AS, Norway (or with modified versions
+ of Qt that use the same license as Qt), and distribute linked
+ combinations including the two. You must obey the GNU General
+ Public License in all respects for all of the code used other than
+ Qt. If you modify this file, you may extend this exception to
+ your version of the file, but you are not obligated to do so. If
+ you do not wish to do so, delete this exception statement from
+ your version.
+*/
+
+#ifndef __QGPGME_ADDEXISTINGSUBKEYJOB_H__
+#define __QGPGME_ADDEXISTINGSUBKEYJOB_H__
+
+#include "job.h"
+#include "qgpgme_export.h"
+
+class QString;
+
+namespace GpgME
+{
+class Error;
+class Key;
+class Subkey;
+}
+
+namespace QGpgME
+{
+
+class QGPGME_EXPORT AddExistingSubkeyJob : public Job
+{
+ Q_OBJECT
+protected:
+ explicit AddExistingSubkeyJob(QObject *parent);
+
+public:
+ ~AddExistingSubkeyJob();
+
+ /**
+ Starts the operation. \a key is the key to add the subkey \a subkey to.
+
+ The job deletes itself after it has completed the operation.
+ */
+ virtual GpgME::Error start(const GpgME::Key &key, const GpgME::Subkey &subkey) = 0;
+
+ /**
+ Runs the operation. \a key is the key to add the subkey \a subkey to.
+ */
+ virtual GpgME::Error exec(const GpgME::Key &key, const GpgME::Subkey &subkey) = 0;
+
+Q_SIGNALS:
+ void result(const GpgME::Error &result, const QString &auditLogAsHtml = {}, const GpgME::Error &auditLogError = {});
+};
+
+}
+
+#endif // __QGPGME_ADDEXISTINGSUBKEYJOB_H__
diff --git a/lang/qt/src/changeexpiryjob.cpp b/lang/qt/src/changeexpiryjob.cpp
new file mode 100644
index 0000000..49f68cc
--- /dev/null
+++ b/lang/qt/src/changeexpiryjob.cpp
@@ -0,0 +1,76 @@
+/*
+ changeexpiryjob.cpp
+
+ This file is part of qgpgme, the Qt API binding for gpgme
+ Copyright (c) 2021 g10 Code GmbH
+ Software engineering by Ingo Klöcker <dev@ingo-kloecker.de>
+
+ QGpgME is free software; you can redistribute it and/or
+ modify it under the terms of the GNU General Public License as
+ published by the Free Software Foundation; either version 2 of the
+ License, or (at your option) any later version.
+
+ QGpgME is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
+
+ In addition, as a special exception, the copyright holders give
+ permission to link the code of this program with any edition of
+ the Qt library by Trolltech AS, Norway (or with modified versions
+ of Qt that use the same license as Qt), and distribute linked
+ combinations including the two. You must obey the GNU General
+ Public License in all respects for all of the code used other than
+ Qt. If you modify this file, you may extend this exception to
+ your version of the file, but you are not obligated to do so. If
+ you do not wish to do so, delete this exception statement from
+ your version.
+*/
+
+#ifdef HAVE_CONFIG_H
+ #include "config.h"
+#endif
+
+#include "changeexpiryjob.h"
+#include "job_p.h"
+
+#include <context.h>
+
+using namespace GpgME;
+using namespace QGpgME;
+
+namespace
+{
+struct ChangeExpiryJobPrivate : public JobPrivate
+{
+ ChangeExpiryJobPrivate()
+ {
+ }
+
+ ~ChangeExpiryJobPrivate() override = default;
+
+ ChangeExpiryJob::Options m_options = ChangeExpiryJob::Default;
+};
+}
+
+void ChangeExpiryJob::setOptions(ChangeExpiryJob::Options options)
+{
+ auto d = jobPrivate<ChangeExpiryJobPrivate>(this);
+ d->m_options = options;
+}
+
+ChangeExpiryJob::Options ChangeExpiryJob::options() const
+{
+ auto d = jobPrivate<ChangeExpiryJobPrivate>(this);
+ return d->m_options;
+}
+
+/* For ABI compat not pure virtual. */
+Error ChangeExpiryJob::start(const Key &, const QDateTime &, const std::vector<Subkey> &)
+{
+ return {};
+}
diff --git a/lang/qt/src/changeexpiryjob.h b/lang/qt/src/changeexpiryjob.h
index 39ed52e..0c5e1b2 100644
--- a/lang/qt/src/changeexpiryjob.h
+++ b/lang/qt/src/changeexpiryjob.h
@@ -71,11 +71,22 @@ namespace QGpgME
class QGPGME_EXPORT ChangeExpiryJob : public Job
{
Q_OBJECT
+public:
+ enum Option {
+ Default = 0x00,
+ UpdatePrimaryKey = 0x01,
+ UpdateAllSubkeys = 0x02,
+ };
+ Q_DECLARE_FLAGS(Options, Option)
+
protected:
explicit ChangeExpiryJob(QObject *parent);
public:
~ChangeExpiryJob();
+ void setOptions(Options options);
+ Options options() const;
+
/**
Starts the change-expiry operation. \a key is the key to change
the expiry of. \a expiry is the new expiry time. If \a expiry
@@ -97,6 +108,8 @@ Q_SIGNALS:
void result(const GpgME::Error &result, const QString &auditLogAsHtml = QString(), const GpgME::Error &auditLogError = GpgME::Error());
};
+Q_DECLARE_OPERATORS_FOR_FLAGS(ChangeExpiryJob::Options)
+
}
#endif // __KLEO_CHANGEEXPIRYJOB_H__
diff --git a/lang/qt/src/cryptoconfig.cpp b/lang/qt/src/cryptoconfig.cpp
index d52dce7..4f13d3f 100644
--- a/lang/qt/src/cryptoconfig.cpp
+++ b/lang/qt/src/cryptoconfig.cpp
@@ -44,6 +44,15 @@ QStringList CryptoConfigEntry::stringValueList() const
return entry->stringValueList();
}
+QVariant CryptoConfigEntry::defaultValue() const
+{
+ const QGpgMENewCryptoConfigEntry *entry = dynamic_cast <const QGpgMENewCryptoConfigEntry*>(this);
+ if (!entry) {
+ return {};
+ }
+ return entry->defaultValue();
+}
+
QGpgME::CryptoConfigEntry *CryptoConfig::entry(const QString &componentName, const QString &entryName) const
{
const CryptoConfigComponent *comp = component(componentName);
diff --git a/lang/qt/src/cryptoconfig.h b/lang/qt/src/cryptoconfig.h
index 651e2af..d87f7d4 100644
--- a/lang/qt/src/cryptoconfig.h
+++ b/lang/qt/src/cryptoconfig.h
@@ -44,6 +44,8 @@
#include <vector>
+class QVariant;
+
/* Start reading this file from the bottom up :) */
namespace QGpgME
@@ -258,6 +260,11 @@ public:
* @return a stringValueList.
*/
QStringList stringValueList() const;
+
+ /**
+ * Return the default value as a variant (available for all argtypes).
+ */
+ QVariant defaultValue() const;
};
/**
diff --git a/lang/qt/src/importjob.cpp b/lang/qt/src/importjob.cpp
new file mode 100644
index 0000000..4f40d9b
--- /dev/null
+++ b/lang/qt/src/importjob.cpp
@@ -0,0 +1,91 @@
+/*
+ importjob.cpp
+
+ This file is part of qgpgme, the Qt API binding for gpgme
+ Copyright (c) 2021 g10 Code GmbH
+ Software engineering by Ingo Klöcker <dev@ingo-kloecker.de>
+
+ QGpgME is free software; you can redistribute it and/or
+ modify it under the terms of the GNU General Public License as
+ published by the Free Software Foundation; either version 2 of the
+ License, or (at your option) any later version.
+
+ QGpgME is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
+
+ In addition, as a special exception, the copyright holders give
+ permission to link the code of this program with any edition of
+ the Qt library by Trolltech AS, Norway (or with modified versions
+ of Qt that use the same license as Qt), and distribute linked
+ combinations including the two. You must obey the GNU General
+ Public License in all respects for all of the code used other than
+ Qt. If you modify this file, you may extend this exception to
+ your version of the file, but you are not obligated to do so. If
+ you do not wish to do so, delete this exception statement from
+ your version.
+*/
+
+#ifdef HAVE_CONFIG_H
+ #include "config.h"
+#endif
+
+#include "importjob.h"
+#include "job_p.h"
+
+#include <context.h>
+
+using namespace GpgME;
+using namespace QGpgME;
+
+namespace
+{
+struct ImportJobPrivate : public JobPrivate
+{
+ ImportJobPrivate()
+ {
+ }
+
+ ~ImportJobPrivate() override = default;
+
+ QString m_importFilter;
+ Key::Origin m_keyOrigin = Key::OriginUnknown;
+ QString m_keyOriginUrl;
+};
+}
+
+void QGpgME::ImportJob::setImportFilter(const QString &filter)
+{
+ const auto d = jobPrivate<ImportJobPrivate>(this);
+ d->m_importFilter = filter;
+}
+
+QString QGpgME::ImportJob::importFilter() const
+{
+ const auto d = jobPrivate<ImportJobPrivate>(this);
+ return d->m_importFilter;
+}
+
+void ImportJob::setKeyOrigin(GpgME::Key::Origin origin, const QString &url)
+{
+ const auto d = jobPrivate<ImportJobPrivate>(this);
+ d->m_keyOrigin = origin;
+ d->m_keyOriginUrl = url;
+}
+
+GpgME::Key::Origin ImportJob::keyOrigin() const
+{
+ const auto d = jobPrivate<ImportJobPrivate>(this);
+ return d->m_keyOrigin;
+}
+
+QString ImportJob::keyOriginUrl() const
+{
+ const auto d = jobPrivate<ImportJobPrivate>(this);
+ return d->m_keyOriginUrl;
+}
diff --git a/lang/qt/src/importjob.h b/lang/qt/src/importjob.h
index 7437fbd..a81dcf2 100644
--- a/lang/qt/src/importjob.h
+++ b/lang/qt/src/importjob.h
@@ -38,7 +38,11 @@
#include "abstractimportjob.h"
#include "qgpgme_export.h"
-#include <QtCore/QByteArray>
+#ifdef BUILDING_QGPGME
+# include <key.h>
+#else
+# include <gpgme++/key.h>
+#endif
namespace GpgME
{
@@ -68,7 +72,14 @@ class QGPGME_EXPORT ImportJob : public AbstractImportJob
protected:
explicit ImportJob(QObject *parent);
public:
- ~ImportJob();
+ ~ImportJob() override;
+
+ void setImportFilter(const QString &filter);
+ QString importFilter() const;
+
+ void setKeyOrigin(GpgME::Key::Origin origin, const QString &url = {});
+ GpgME::Key::Origin keyOrigin() const;
+ QString keyOriginUrl() const;
/**
Starts the importing operation. \a keyData contains the data to
diff --git a/lang/qt/src/job.cpp b/lang/qt/src/job.cpp
index 8ed0b57..a9edc8e 100644
--- a/lang/qt/src/job.cpp
+++ b/lang/qt/src/job.cpp
@@ -5,6 +5,8 @@
Copyright (c) 2004,2005 Klarälvdalens Datakonsult AB
Copyright (c) 2016 by Bundesamt für Sicherheit in der Informationstechnik
Software engineering by Intevation GmbH
+ Copyright (c) 2021 g10 Code GmbH
+ Software engineering by Ingo Klöcker <dev@ingo-kloecker.de>
QGpgME is free software; you can redistribute it and/or
modify it under the terms of the GNU General Public License as
@@ -37,6 +39,7 @@
#endif
#include "job.h"
+#include "job_p.h"
#include "keylistjob.h"
#include "listallkeysjob.h"
@@ -58,20 +61,42 @@
#include "downloadjob.h"
#include "deletejob.h"
#include "refreshkeysjob.h"
+#include "addexistingsubkeyjob.h"
#include "adduseridjob.h"
#include "specialjob.h"
#include "keyformailboxjob.h"
+#include "wkdlookupjob.h"
#include "wkspublishjob.h"
#include "tofupolicyjob.h"
#include "threadedjobmixin.h"
#include "quickjob.h"
#include "gpgcardjob.h"
+#include "receivekeysjob.h"
#include <QCoreApplication>
#include <QDebug>
#include <gpg-error.h>
+#include <unordered_map>
+
+namespace
+{
+typedef std::unordered_map<const QGpgME::Job*, std::unique_ptr<QGpgME::JobPrivate>> JobPrivateHash;
+Q_GLOBAL_STATIC(JobPrivateHash, d_func)
+}
+
+void QGpgME::setJobPrivate(const Job *job, std::unique_ptr<JobPrivate> d)
+{
+ auto &ref = d_func()->operator[](job);
+ ref = std::move(d);
+}
+
+QGpgME::JobPrivate *QGpgME::getJobPrivate(const Job *job)
+{
+ return d_func()->operator[](job).get();
+}
+
QGpgME::Job::Job(QObject *parent)
: QObject(parent)
{
@@ -82,6 +107,7 @@ QGpgME::Job::Job(QObject *parent)
QGpgME::Job::~Job()
{
+ ::d_func()->erase(this);
}
QString QGpgME::Job::auditLogAsHtml() const
@@ -129,6 +155,7 @@ make_job_subclass(KeyGenerationJob)
make_job_subclass(AbstractImportJob)
make_job_subclass_ext(ImportJob, AbstractImportJob)
make_job_subclass_ext(ImportFromKeyserverJob, AbstractImportJob)
+make_job_subclass_ext(ReceiveKeysJob, AbstractImportJob)
make_job_subclass(ExportJob)
make_job_subclass(ChangeExpiryJob)
make_job_subclass(ChangeOwnerTrustJob)
@@ -136,9 +163,11 @@ make_job_subclass(ChangePasswdJob)
make_job_subclass(DownloadJob)
make_job_subclass(DeleteJob)
make_job_subclass(RefreshKeysJob)
+make_job_subclass(AddExistingSubkeyJob)
make_job_subclass(AddUserIDJob)
make_job_subclass(SpecialJob)
make_job_subclass(KeyForMailboxJob)
+make_job_subclass(WKDLookupJob)
make_job_subclass(WKSPublishJob)
make_job_subclass(TofuPolicyJob)
make_job_subclass(QuickJob)
@@ -169,10 +198,13 @@ make_job_subclass(GpgCardJob)
#include "downloadjob.moc"
#include "deletejob.moc"
#include "refreshkeysjob.moc"
+#include "addexistingsubkeyjob.moc"
#include "adduseridjob.moc"
#include "specialjob.moc"
#include "keyformailboxjob.moc"
+#include "wkdlookupjob.moc"
#include "wkspublishjob.moc"
#include "tofupolicyjob.moc"
#include "quickjob.moc"
#include "gpgcardjob.moc"
+#include "receivekeysjob.moc"
diff --git a/lang/qt/src/job_p.h b/lang/qt/src/job_p.h
new file mode 100644
index 0000000..3bce4cf
--- /dev/null
+++ b/lang/qt/src/job_p.h
@@ -0,0 +1,70 @@
+/*
+ job_p.h
+
+ This file is part of qgpgme, the Qt API binding for gpgme
+ Copyright (c) 2021 g10 Code GmbH
+ Software engineering by Ingo Klöcker <dev@ingo-kloecker.de>
+
+ QGpgME is free software; you can redistribute it and/or
+ modify it under the terms of the GNU General Public License as
+ published by the Free Software Foundation; either version 2 of the
+ License, or (at your option) any later version.
+
+ QGpgME is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
+
+ In addition, as a special exception, the copyright holders give
+ permission to link the code of this program with any edition of
+ the Qt library by Trolltech AS, Norway (or with modified versions
+ of Qt that use the same license as Qt), and distribute linked
+ combinations including the two. You must obey the GNU General
+ Public License in all respects for all of the code used other than
+ Qt. If you modify this file, you may extend this exception to
+ your version of the file, but you are not obligated to do so. If
+ you do not wish to do so, delete this exception statement from
+ your version.
+*/
+
+#ifndef __QGPGME_JOB_P_H__
+#define __QGPGME_JOB_P_H__
+
+#include "job.h"
+
+#include <memory>
+
+namespace QGpgME
+{
+
+// Base class for pimpl classes for Job subclasses
+class JobPrivate
+{
+public:
+ virtual ~JobPrivate() {}
+};
+
+// Setter and getters for the externally stored pimpl instances of jobs
+// BCI: Add a real d-pointer to Job
+void setJobPrivate(const Job *job, std::unique_ptr<JobPrivate> d);
+
+JobPrivate *getJobPrivate(const Job *job);
+
+template <typename T>
+static T *jobPrivate(const Job *job) {
+ auto d = getJobPrivate(job);
+ if (!d) {
+ std::unique_ptr<T> ref{new T};
+ d = ref.get();
+ setJobPrivate(job, std::move(ref));
+ }
+ return dynamic_cast<T *>(d);
+}
+
+}
+
+#endif // __QGPGME_JOB_P_H__
diff --git a/lang/qt/src/protocol.h b/lang/qt/src/protocol.h
index 17db68a..25c71ef 100644
--- a/lang/qt/src/protocol.h
+++ b/lang/qt/src/protocol.h
@@ -40,6 +40,7 @@
#include "qgpgme_export.h"
namespace QGpgME {
+class AddExistingSubkeyJob;
class CryptoConfig;
class KeyListJob;
class ListAllKeysJob;
@@ -64,10 +65,12 @@ class ChangePasswdJob;
class AddUserIDJob;
class SpecialJob;
class KeyForMailboxJob;
+class WKDLookupJob;
class WKSPublishJob;
class TofuPolicyJob;
class QuickJob;
class GpgCardJob;
+class ReceiveKeysJob;
/** The main entry point for QGpgME Comes in OpenPGP and SMIME(CMS) flavors.
*
@@ -92,6 +95,7 @@ class GpgCardJob;
* {
* // keys and resuls can now be used.
* });
+ * job->start({QStringLiteral("alfa@example.net")}, false);
* \endcode
*
* \code
@@ -123,9 +127,11 @@ public:
virtual KeyGenerationJob *keyGenerationJob() const = 0;
virtual ImportJob *importJob() const = 0;
virtual ImportFromKeyserverJob *importFromKeyserverJob() const = 0;
+ virtual ReceiveKeysJob *receiveKeysJob() const = 0;
virtual ExportJob *publicKeyExportJob(bool armor = false) const = 0;
- // @param charset the encoding of the passphrase in the exported file
- virtual ExportJob *secretKeyExportJob(bool armor = false, const QString &charset = QString()) const = 0;
+ // the second parameter is ignored; the passphrase in the exported file is always utf-8 encoded
+ virtual ExportJob *secretKeyExportJob(bool armor = false, const QString & = QString()) const = 0;
+ virtual ExportJob *secretSubkeyExportJob(bool armor = false) const = 0;
virtual DownloadJob *downloadJob(bool armor = false) const = 0;
virtual DeleteJob *deleteJob() const = 0;
virtual SignEncryptJob *signEncryptJob(bool armor = false, bool textMode = false) const = 0;
@@ -135,6 +141,7 @@ public:
virtual SignKeyJob *signKeyJob() const = 0;
virtual ChangePasswdJob *changePasswdJob() const = 0;
virtual ChangeOwnerTrustJob *changeOwnerTrustJob() const = 0;
+ virtual AddExistingSubkeyJob *addExistingSubkeyJob() const = 0;
virtual AddUserIDJob *addUserIDJob() const = 0;
virtual SpecialJob *specialJob(const char *type, const QMap<QString, QVariant> &args) const = 0;
@@ -154,6 +161,9 @@ public:
/** Find the best key to use for a mailbox. */
virtual KeyForMailboxJob *keyForMailboxJob() const = 0;
+ /** This job looks up a key via WKD without importing it. */
+ virtual WKDLookupJob *wkdLookupJob() const = 0;
+
/** A Job for interacting with gnupg's wks tools. */
virtual WKSPublishJob *wksPublishJob() const = 0;
diff --git a/lang/qt/src/protocol_p.h b/lang/qt/src/protocol_p.h
index 57c1ed8..4211e00 100644
--- a/lang/qt/src/protocol_p.h
+++ b/lang/qt/src/protocol_p.h
@@ -5,6 +5,8 @@
Copyright (c) 2004,2005 Klarälvdalens Datakonsult AB
Copyright (c) 2016 by Bundesamt für Sicherheit in der Informationstechnik
Software engineering by Intevation GmbH
+ Copyright (c) 2022 by g10 Code GmbH
+ Software engineering by Ingo Klöcker <dev@ingo-kloecker.de>
QGpgME is free software; you can redistribute it and/or
modify it under the terms of the GNU General Public License as
@@ -42,7 +44,6 @@
#include "qgpgmedecryptverifyjob.h"
#include "qgpgmerefreshkeysjob.h"
#include "qgpgmedeletejob.h"
-#include "qgpgmesecretkeyexportjob.h"
#include "qgpgmedownloadjob.h"
#include "qgpgmesignencryptjob.h"
#include "qgpgmeencryptjob.h"
@@ -56,11 +57,14 @@
#include "qgpgmechangeexpiryjob.h"
#include "qgpgmechangeownertrustjob.h"
#include "qgpgmechangepasswdjob.h"
+#include "qgpgmeaddexistingsubkeyjob.h"
#include "qgpgmeadduseridjob.h"
#include "qgpgmekeyformailboxjob.h"
+#include "qgpgmewkdlookupjob.h"
#include "qgpgmewkspublishjob.h"
#include "qgpgmetofupolicyjob.h"
#include "qgpgmequickjob.h"
+#include "qgpgmereceivekeysjob.h"
namespace
{
@@ -230,6 +234,19 @@ public:
return new QGpgME::QGpgMEImportFromKeyserverJob(context);
}
+ QGpgME::ReceiveKeysJob *receiveKeysJob() const override
+ {
+ if (mProtocol != GpgME::OpenPGP) {
+ return nullptr;
+ }
+
+ GpgME::Context *context = GpgME::Context::createForProtocol(mProtocol);
+ if (!context) {
+ return nullptr;
+ }
+ return new QGpgME::QGpgMEReceiveKeysJob{context};
+ }
+
QGpgME::ExportJob *publicKeyExportJob(bool armor) const Q_DECL_OVERRIDE
{
GpgME::Context *context = GpgME::Context::createForProtocol(mProtocol);
@@ -241,14 +258,26 @@ public:
return new QGpgME::QGpgMEExportJob(context);
}
- QGpgME::ExportJob *secretKeyExportJob(bool armor, const QString &charset) const Q_DECL_OVERRIDE
+ QGpgME::ExportJob *secretKeyExportJob(bool armor, const QString &) const Q_DECL_OVERRIDE
{
- if (mProtocol != GpgME::CMS) { // fixme: add support for gpg, too
+ GpgME::Context *context = GpgME::Context::createForProtocol(mProtocol);
+ if (!context) {
return nullptr;
}
- // this operation is not supported by gpgme, so we have to call gpgsm ourselves:
- return new QGpgME::QGpgMESecretKeyExportJob(armor, charset);
+ context->setArmor(armor);
+ return new QGpgME::QGpgMEExportJob(context, GpgME::Context::ExportSecret);
+ }
+
+ QGpgME::ExportJob *secretSubkeyExportJob(bool armor) const Q_DECL_OVERRIDE
+ {
+ GpgME::Context *context = GpgME::Context::createForProtocol(mProtocol);
+ if (!context) {
+ return nullptr;
+ }
+
+ context->setArmor(armor);
+ return new QGpgME::QGpgMEExportJob(context, GpgME::Context::ExportSecretSubkey);
}
QGpgME::RefreshKeysJob *refreshKeysJob() const Q_DECL_OVERRIDE
@@ -357,6 +386,19 @@ public:
return new QGpgME::QGpgMEChangeOwnerTrustJob(context);
}
+ QGpgME:: AddExistingSubkeyJob *addExistingSubkeyJob() const override
+ {
+ if (mProtocol != GpgME::OpenPGP) {
+ return nullptr; // only supported by gpg
+ }
+
+ GpgME::Context *context = GpgME::Context::createForProtocol(mProtocol);
+ if (!context) {
+ return nullptr;
+ }
+ return new QGpgME::QGpgMEAddExistingSubkeyJob{context};
+ }
+
QGpgME::AddUserIDJob *addUserIDJob() const Q_DECL_OVERRIDE
{
if (mProtocol != GpgME::OpenPGP) {
@@ -392,6 +434,18 @@ public:
return new QGpgME::QGpgMEKeyForMailboxJob(context);
}
+ QGpgME::WKDLookupJob *wkdLookupJob() const Q_DECL_OVERRIDE
+ {
+ if (mProtocol != GpgME::OpenPGP) {
+ return nullptr;
+ }
+ auto context = GpgME::Context::createForEngine(GpgME::AssuanEngine);
+ if (!context) {
+ return nullptr;
+ }
+ return new QGpgME::QGpgMEWKDLookupJob(context.release());
+ }
+
QGpgME::WKSPublishJob *wksPublishJob() const Q_DECL_OVERRIDE
{
if (mProtocol != GpgME::OpenPGP) {
diff --git a/lang/qt/src/qgpgmeaddexistingsubkeyjob.cpp b/lang/qt/src/qgpgmeaddexistingsubkeyjob.cpp
new file mode 100644
index 0000000..32e2c29
--- /dev/null
+++ b/lang/qt/src/qgpgmeaddexistingsubkeyjob.cpp
@@ -0,0 +1,96 @@
+/*
+ qgpgmeaddexistingsubkeyjob.cpp
+
+ This file is part of qgpgme, the Qt API binding for gpgme
+ Copyright (c) 2022 g10 Code GmbH
+ Software engineering by Ingo Klöcker <dev@ingo-kloecker.de>
+
+ QGpgME is free software; you can redistribute it and/or
+ modify it under the terms of the GNU General Public License as
+ published by the Free Software Foundation; either version 2 of the
+ License, or (at your option) any later version.
+
+ QGpgME is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
+
+ In addition, as a special exception, the copyright holders give
+ permission to link the code of this program with any edition of
+ the Qt library by Trolltech AS, Norway (or with modified versions
+ of Qt that use the same license as Qt), and distribute linked
+ combinations including the two. You must obey the GNU General
+ Public License in all respects for all of the code used other than
+ Qt. If you modify this file, you may extend this exception to
+ your version of the file, but you are not obligated to do so. If
+ you do not wish to do so, delete this exception statement from
+ your version.
+*/
+
+#ifdef HAVE_CONFIG_H
+ #include "config.h"
+#endif
+
+#include "qgpgmeaddexistingsubkeyjob.h"
+
+#include "dataprovider.h"
+
+#include <QDateTime>
+
+#include "context.h"
+#include "data.h"
+#include "gpgaddexistingsubkeyeditinteractor.h"
+#include "key.h"
+
+#include <gpg-error.h>
+
+using namespace QGpgME;
+using namespace GpgME;
+
+QGpgMEAddExistingSubkeyJob::QGpgMEAddExistingSubkeyJob(Context *context)
+ : mixin_type{context}
+{
+ lateInitialization();
+}
+
+QGpgMEAddExistingSubkeyJob::~QGpgMEAddExistingSubkeyJob() = default;
+
+static QGpgMEAddExistingSubkeyJob::result_type add_subkey(Context *ctx, const Key &key, const Subkey &subkey)
+{
+ std::unique_ptr<GpgAddExistingSubkeyEditInteractor> interactor{new GpgAddExistingSubkeyEditInteractor{subkey.keyGrip()}};
+
+ if (!subkey.neverExpires()) {
+ const auto expiry = QDateTime::fromSecsSinceEpoch(subkey.expirationTime(), Qt::UTC).toString(u"yyyyMMdd'T'hhmmss").toStdString();
+ interactor->setExpiry(expiry);
+ }
+
+ QGpgME::QByteArrayDataProvider dp;
+ Data data(&dp);
+ assert(!data.isNull());
+
+ ctx->setFlag("extended-edit", "1");
+
+ const Error err = ctx->edit(key, std::unique_ptr<EditInteractor>(interactor.release()), data);
+ Error ae;
+ const QString log = _detail::audit_log_as_html(ctx, ae);
+ return std::make_tuple(err, log, ae);
+}
+
+Error QGpgMEAddExistingSubkeyJob::start(const GpgME::Key &key, const GpgME::Subkey &subkey)
+{
+ run(std::bind(&add_subkey, std::placeholders::_1, key, subkey));
+ return {};
+}
+
+Error QGpgMEAddExistingSubkeyJob::exec(const GpgME::Key &key, const GpgME::Subkey &subkey)
+{
+ const result_type r = add_subkey(context(), key, subkey);
+ resultHook(r);
+ return std::get<0>(r);
+}
+
+#include "qgpgmeaddexistingsubkeyjob.moc"
diff --git a/lang/qt/src/qgpgmeaddexistingsubkeyjob.h b/lang/qt/src/qgpgmeaddexistingsubkeyjob.h
new file mode 100644
index 0000000..1572755
--- /dev/null
+++ b/lang/qt/src/qgpgmeaddexistingsubkeyjob.h
@@ -0,0 +1,68 @@
+/*
+ qgpgmeaddexistingsubkeyjob.h
+
+ This file is part of qgpgme, the Qt API binding for gpgme
+ Copyright (c) 2022 g10 Code GmbH
+ Software engineering by Ingo Klöcker <dev@ingo-kloecker.de>
+
+ QGpgME is free software; you can redistribute it and/or
+ modify it under the terms of the GNU General Public License as
+ published by the Free Software Foundation; either version 2 of the
+ License, or (at your option) any later version.
+
+ QGpgME is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
+
+ In addition, as a special exception, the copyright holders give
+ permission to link the code of this program with any edition of
+ the Qt library by Trolltech AS, Norway (or with modified versions
+ of Qt that use the same license as Qt), and distribute linked
+ combinations including the two. You must obey the GNU General
+ Public License in all respects for all of the code used other than
+ Qt. If you modify this file, you may extend this exception to
+ your version of the file, but you are not obligated to do so. If
+ you do not wish to do so, delete this exception statement from
+ your version.
+*/
+
+#ifndef __QGPGME_QGPGMEADDEXISTINGSUBKEYJOB_H__
+#define __QGPGME_QGPGMEADDEXISTINGSUBKEYJOB_H__
+
+#include "threadedjobmixin.h"
+#include "addexistingsubkeyjob.h"
+
+namespace QGpgME
+{
+
+class QGpgMEAddExistingSubkeyJob
+#ifdef Q_MOC_RUN
+ : public AddExistingSubkeyJob
+#else
+ : public _detail::ThreadedJobMixin<AddExistingSubkeyJob>
+#endif
+{
+ Q_OBJECT
+#ifdef Q_MOC_RUN
+public Q_SLOTS:
+ void slotFinished();
+#endif
+public:
+ explicit QGpgMEAddExistingSubkeyJob(GpgME::Context *context);
+ ~QGpgMEAddExistingSubkeyJob();
+
+ /* from AddExistingSubkeyJob */
+ GpgME::Error start(const GpgME::Key &key, const GpgME::Subkey &subkey) override;
+
+ /* from AddExistingSubkeyJob */
+ GpgME::Error exec(const GpgME::Key &key, const GpgME::Subkey &subkey) override;
+};
+
+}
+
+#endif // __QGPGME_QGPGMEADDEXISTINGSUBKEYJOB_H__
diff --git a/lang/qt/src/qgpgmechangeexpiryjob.cpp b/lang/qt/src/qgpgmechangeexpiryjob.cpp
index 68591b7..5d4e836 100644
--- a/lang/qt/src/qgpgmechangeexpiryjob.cpp
+++ b/lang/qt/src/qgpgmechangeexpiryjob.cpp
@@ -5,6 +5,8 @@
Copyright (c) 2008 Klarälvdalens Datakonsult AB
Copyright (c) 2016 by Bundesamt für Sicherheit in der Informationstechnik
Software engineering by Intevation GmbH
+ Copyright (c) 2021 g10 Code GmbH
+ Software engineering by Ingo Klöcker <dev@ingo-kloecker.de>
QGpgME is free software; you can redistribute it and/or
modify it under the terms of the GNU General Public License as
@@ -55,14 +57,32 @@ QGpgMEChangeExpiryJob::QGpgMEChangeExpiryJob(Context *context)
QGpgMEChangeExpiryJob::~QGpgMEChangeExpiryJob() {}
static QGpgMEChangeExpiryJob::result_type change_expiry(Context *ctx, const Key &key, const QDateTime &expiry,
- const std::vector<Subkey> &subkeys)
+ const std::vector<Subkey> &subkeys, ChangeExpiryJob::Options options)
{
// convert expiry to "seconds from now"; use 1 second from now if expiry is before the current datetime
const unsigned long expires = expiry.isValid()
? std::max<qint64>(QDateTime::currentDateTime().secsTo(expiry), 1)
: 0;
- auto err = ctx->setExpire(key, expires, subkeys);
+ // updating the expiration date of the primary key and the subkeys needs to be done in two steps
+ // because --quick-set-expire does not support updating the expiration date of both at the same time
+
+ if (subkeys.empty() || (options & ChangeExpiryJob::UpdatePrimaryKey)) {
+ // update the expiration date of the primary key
+ auto err = ctx->setExpire(key, expires);
+ if (err) {
+ return std::make_tuple(err, QString(), Error());
+ }
+ }
+
+ GpgME::Error err;
+ if (!subkeys.empty()) {
+ // update the expiration date of the specified subkeys
+ err = ctx->setExpire(key, expires, subkeys);
+ } else if (options & ChangeExpiryJob::UpdateAllSubkeys) {
+ // update the expiration date of all subkeys
+ err = ctx->setExpire(key, expires, {}, Context::SetExpireAllSubkeys);
+ }
return std::make_tuple(err, QString(), Error());
}
@@ -73,13 +93,7 @@ Error QGpgMEChangeExpiryJob::start(const Key &key, const QDateTime &expiry)
Error QGpgMEChangeExpiryJob::start(const Key &key, const QDateTime &expiry, const std::vector<Subkey> &subkeys)
{
- run(std::bind(&change_expiry, std::placeholders::_1, key, expiry, subkeys));
- return Error();
-}
-
-/* For ABI compat not pure virtual. */
-Error ChangeExpiryJob::start(const Key &, const QDateTime &, const std::vector<Subkey> &)
-{
+ run(std::bind(&change_expiry, std::placeholders::_1, key, expiry, subkeys, options()));
return Error();
}
diff --git a/lang/qt/src/qgpgmechangeownertrustjob.h b/lang/qt/src/qgpgmechangeownertrustjob.h
index 80dc0e4..0f4dbe6 100644
--- a/lang/qt/src/qgpgmechangeownertrustjob.h
+++ b/lang/qt/src/qgpgmechangeownertrustjob.h
@@ -1,5 +1,5 @@
/*
- qgpgmechangeexpiryjob.h
+ qgpgmechangeownertrustjob.h
This file is part of qgpgme, the Qt API binding for gpgme
Copyright (c) 2008 Klarälvdalens Datakonsult AB
diff --git a/lang/qt/src/qgpgmeexportjob.cpp b/lang/qt/src/qgpgmeexportjob.cpp
index bf3297a..e9bc0a4 100644
--- a/lang/qt/src/qgpgmeexportjob.cpp
+++ b/lang/qt/src/qgpgmeexportjob.cpp
@@ -5,6 +5,8 @@
Copyright (c) 2004,2008 Klarälvdalens Datakonsult AB
Copyright (c) 2016 by Bundesamt für Sicherheit in der Informationstechnik
Software engineering by Intevation GmbH
+ Copyright (c) 2022 by g10 Code GmbH
+ Software engineering by Ingo Klöcker <dev@ingo-kloecker.de>
QGpgME is free software; you can redistribute it and/or
modify it under the terms of the GNU General Public License as
@@ -52,23 +54,28 @@ using namespace QGpgME;
using namespace GpgME;
QGpgMEExportJob::QGpgMEExportJob(Context *context)
- : mixin_type(context),
- m_flags(0)
+ : QGpgMEExportJob{context, 0}
+{
+}
+
+QGpgMEExportJob::QGpgMEExportJob(Context *context, unsigned int forcedMode)
+ : mixin_type{context}
+ , m_exportMode{forcedMode}
+ , m_additionalExportModeFlags{0}
{
lateInitialization();
}
-QGpgMEExportJob::~QGpgMEExportJob() {}
+QGpgMEExportJob::~QGpgMEExportJob() = default;
-static QGpgMEExportJob::result_type export_qba(Context *ctx, const QStringList &patterns, unsigned int flags)
+static QGpgMEExportJob::result_type export_qba(Context *ctx, const QStringList &patterns, unsigned int mode)
{
-
const _detail::PatternConverter pc(patterns);
QGpgME::QByteArrayDataProvider dp;
Data data(&dp);
- const Error err = ctx->exportPublicKeys(pc.patterns(), data, flags);
+ const Error err = ctx->exportKeys(pc.patterns(), data, mode);
Error ae;
const QString log = _detail::audit_log_as_html(ctx, ae);
return std::make_tuple(err, dp.data(), log, ae);
@@ -76,13 +83,14 @@ static QGpgMEExportJob::result_type export_qba(Context *ctx, const QStringList &
Error QGpgMEExportJob::start(const QStringList &patterns)
{
- run(std::bind(&export_qba, std::placeholders::_1, patterns, m_flags));
+ auto mode = m_exportMode | m_additionalExportModeFlags;
+ run(std::bind(&export_qba, std::placeholders::_1, patterns, mode));
return Error();
}
void QGpgMEExportJob::setExportFlags(unsigned int flags)
{
- m_flags = flags;
+ m_additionalExportModeFlags = flags;
}
/* For ABI compat not pure virtual. */
diff --git a/lang/qt/src/qgpgmeexportjob.h b/lang/qt/src/qgpgmeexportjob.h
index 3f6bd0e..b77bad1 100644
--- a/lang/qt/src/qgpgmeexportjob.h
+++ b/lang/qt/src/qgpgmeexportjob.h
@@ -5,6 +5,8 @@
Copyright (c) 2004,2008 Klarälvdalens Datakonsult AB
Copyright (c) 2016 by Bundesamt für Sicherheit in der Informationstechnik
Software engineering by Intevation GmbH
+ Copyright (c) 2022 by g10 Code GmbH
+ Software engineering by Ingo Klöcker <dev@ingo-kloecker.de>
QGpgME is free software; you can redistribute it and/or
modify it under the terms of the GNU General Public License as
@@ -56,15 +58,21 @@ public Q_SLOTS:
#endif
public:
explicit QGpgMEExportJob(GpgME::Context *context);
- ~QGpgMEExportJob();
+ // Creates an export job with forced export mode @p exportMode. The
+ // export mode flags set with @p exportMode cannot be overridden with
+ // setExportFlags.
+ explicit QGpgMEExportJob(GpgME::Context *context, unsigned int exportMode);
+ ~QGpgMEExportJob() Q_DECL_OVERRIDE;
/* from ExportJob */
- void setExportFlags (unsigned int flags) Q_DECL_OVERRIDE;
+ void setExportFlags(unsigned int flags) Q_DECL_OVERRIDE;
/* from ExportJob */
GpgME::Error start(const QStringList &patterns) Q_DECL_OVERRIDE;
+
private:
- unsigned int m_flags;
+ unsigned int m_exportMode;
+ unsigned int m_additionalExportModeFlags;
};
}
diff --git a/lang/qt/src/qgpgmeimportjob.cpp b/lang/qt/src/qgpgmeimportjob.cpp
index a62d05f..d609c5f 100644
--- a/lang/qt/src/qgpgmeimportjob.cpp
+++ b/lang/qt/src/qgpgmeimportjob.cpp
@@ -40,11 +40,9 @@
#include "dataprovider.h"
-#include "context.h"
-#include "data.h"
-#include "key.h"
-
-#include <cassert>
+#include <context.h>
+#include <data.h>
+#include <key.h>
using namespace QGpgME;
using namespace GpgME;
@@ -55,14 +53,60 @@ QGpgMEImportJob::QGpgMEImportJob(Context *context)
lateInitialization();
}
-QGpgMEImportJob::~QGpgMEImportJob() {}
+QGpgMEImportJob::~QGpgMEImportJob() = default;
-static QGpgMEImportJob::result_type import_qba(Context *ctx, const QByteArray &certData)
+static const char *originToString(Key::Origin origin)
{
+ static const std::map<Key::Origin, const char *> mapping = {
+ { Key::OriginUnknown, "unknown" },
+ { Key::OriginKS, "ks" },
+ { Key::OriginDane, "dane" },
+ { Key::OriginWKD, "wkd" },
+ { Key::OriginURL, "url" },
+ { Key::OriginFile, "file" },
+ { Key::OriginSelf, "self" },
+ };
+ const auto it = mapping.find(origin);
+ return (it != std::end(mapping)) ? it->second : nullptr;
+}
+
+static QGpgMEImportJob::result_type import_qba(Context *ctx, const QByteArray &certData, const QString &importFilter,
+ Key::Origin keyOrigin, const QString &keyOriginUrl)
+{
+ if (!importFilter.isEmpty()) {
+ ctx->setFlag("import-filter", importFilter.toStdString().c_str());
+ }
+ if (keyOrigin != Key::OriginUnknown) {
+ if (const auto origin = originToString(keyOrigin)) {
+ std::string value{origin};
+ if (!keyOriginUrl.isEmpty()) {
+ value += ",";
+ value += keyOriginUrl.toStdString();
+ }
+ ctx->setFlag("key-origin", value.c_str());
+ }
+ }
+
QGpgME::QByteArrayDataProvider dp(certData);
Data data(&dp);
- const ImportResult res = ctx->importKeys(data);
+ ImportResult res = ctx->importKeys(data);
+ // HACK: If the import failed with an error, then check if res.imports()
+ // contains only import statuses with "bad passphrase" error; if yes, this
+ // means that the user probably entered a wrong password to decrypt an
+ // encrypted key for import. In this case, return a result with "bad
+ // passphrase" error instead of the original error.
+ // We check if all import statuses instead of any import status has a
+ // "bad passphrase" error to avoid breaking imports that partially worked.
+ // See https://dev.gnupg.org/T5713.
+ const auto imports = res.imports();
+ if (res.error() && !imports.empty()
+ && std::all_of(std::begin(imports), std::end(imports),
+ [](const Import &import) {
+ return import.error().code() == GPG_ERR_BAD_PASSPHRASE;
+ })) {
+ res = ImportResult{Error{GPG_ERR_BAD_PASSPHRASE}};
+ }
Error ae;
const QString log = _detail::audit_log_as_html(ctx, ae);
return std::make_tuple(res, log, ae);
@@ -70,13 +114,13 @@ static QGpgMEImportJob::result_type import_qba(Context *ctx, const QByteArray &c
Error QGpgMEImportJob::start(const QByteArray &certData)
{
- run(std::bind(&import_qba, std::placeholders::_1, certData));
+ run(std::bind(&import_qba, std::placeholders::_1, certData, importFilter(), keyOrigin(), keyOriginUrl()));
return Error();
}
GpgME::ImportResult QGpgME::QGpgMEImportJob::exec(const QByteArray &keyData)
{
- const result_type r = import_qba(context(), keyData);
+ const result_type r = import_qba(context(), keyData, importFilter(), keyOrigin(), keyOriginUrl());
resultHook(r);
return mResult;
}
diff --git a/lang/qt/src/qgpgmenewcryptoconfig.cpp b/lang/qt/src/qgpgmenewcryptoconfig.cpp
index b93db76..32bf888 100644
--- a/lang/qt/src/qgpgmenewcryptoconfig.cpp
+++ b/lang/qt/src/qgpgmenewcryptoconfig.cpp
@@ -43,6 +43,7 @@
#include <QFile>
#include <QDir>
+#include <QList>
#include "global.h"
#include "error.h"
@@ -710,6 +711,57 @@ bool QGpgMENewCryptoConfigEntry::isDirty() const
return m_option.dirty();
}
+QVariant QGpgMENewCryptoConfigEntry::defaultValue() const
+{
+ const auto defaultValue = m_option.defaultValue();
+ if (defaultValue.isNull() || defaultValue.numElements() == 0) {
+ return {};
+ }
+ if (defaultValue.numElements() == 1) {
+ switch (m_option.alternateType()) {
+ case NoType:
+ return QVariant{defaultValue.boolValue()};
+ case StringType:
+ return QVariant{QString::fromUtf8(defaultValue.stringValue())};
+ case IntegerType:
+ return QVariant{defaultValue.intValue()};
+ case UnsignedIntegerType:
+ return QVariant{defaultValue.uintValue()};
+ default:
+ // alternateType should always be one of the above four types
+ qCWarning(QGPGME_LOG) << __func__ << ": unsupported alternateType" << m_option.alternateType();
+ }
+ } else {
+ QList<QVariant> list;
+ switch (m_option.alternateType()) {
+ case StringType: {
+ const auto values = defaultValue.stringValues();
+ std::transform(std::begin(values), std::end(values), std::back_inserter(list),
+ [] (const char *value) { return QVariant{QString::fromUtf8(value)}; });
+ break;
+ }
+ case IntegerType: {
+ const auto values = defaultValue.intValues();
+ std::transform(std::begin(values), std::end(values), std::back_inserter(list),
+ [] (int value) { return QVariant{value}; });
+ break;
+ }
+ case UnsignedIntegerType: {
+ const auto values = defaultValue.uintValues();
+ std::transform(std::begin(values), std::end(values), std::back_inserter(list),
+ [] (unsigned int value) { return QVariant{value}; });
+ break;
+ }
+ default:
+ // alternateType should always be one of the above four types
+ qCWarning(QGPGME_LOG) << __func__ << ": unsupported alternateType" << m_option.alternateType() << "for list";
+ }
+ return QVariant{list};
+ }
+
+ return {};
+}
+
#if 0
QString QGpgMENewCryptoConfigEntry::toString(bool escape) const
{
diff --git a/lang/qt/src/qgpgmenewcryptoconfig.h b/lang/qt/src/qgpgmenewcryptoconfig.h
index eade8eb..15579fd 100644
--- a/lang/qt/src/qgpgmenewcryptoconfig.h
+++ b/lang/qt/src/qgpgmenewcryptoconfig.h
@@ -95,6 +95,7 @@ public:
bool isDirty() const Q_DECL_OVERRIDE;
QStringList stringValueList() const;
+ QVariant defaultValue() const;
#if 0
void setDirty(bool b);
diff --git a/lang/qt/src/qgpgmereceivekeysjob.cpp b/lang/qt/src/qgpgmereceivekeysjob.cpp
new file mode 100644
index 0000000..bedf7a2
--- /dev/null
+++ b/lang/qt/src/qgpgmereceivekeysjob.cpp
@@ -0,0 +1,79 @@
+/*
+ qgpgmereceivekeysjob.cpp
+
+ This file is part of qgpgme, the Qt API binding for gpgme
+ Copyright (c) 2022 g10 Code GmbH
+ Software engineering by Ingo Klöcker <dev@ingo-kloecker.de>
+
+ QGpgME is free software; you can redistribute it and/or
+ modify it under the terms of the GNU General Public License as
+ published by the Free Software Foundation; either version 2 of the
+ License, or (at your option) any later version.
+
+ QGpgME is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
+
+ In addition, as a special exception, the copyright holders give
+ permission to link the code of this program with any edition of
+ the Qt library by Trolltech AS, Norway (or with modified versions
+ of Qt that use the same license as Qt), and distribute linked
+ combinations including the two. You must obey the GNU General
+ Public License in all respects for all of the code used other than
+ Qt. If you modify this file, you may extend this exception to
+ your version of the file, but you are not obligated to do so. If
+ you do not wish to do so, delete this exception statement from
+ your version.
+*/
+
+#ifdef HAVE_CONFIG_H
+# include "config.h"
+#endif
+
+#include "qgpgmereceivekeysjob.h"
+
+#include "util.h"
+
+using namespace QGpgME;
+using namespace GpgME;
+
+QGpgMEReceiveKeysJob::QGpgMEReceiveKeysJob(Context *context)
+ : mixin_type{context}
+{
+ lateInitialization();
+}
+
+QGpgMEReceiveKeysJob::~QGpgMEReceiveKeysJob() = default;
+
+static QGpgMEReceiveKeysJob::result_type importfromkeyserver(Context *ctx, const QStringList &keyIds)
+{
+ const ImportResult res = ctx->importKeys(toStrings(keyIds));
+ Error ae;
+ const QString log = _detail::audit_log_as_html(ctx, ae);
+ return std::make_tuple(res, log, ae);
+}
+
+Error QGpgMEReceiveKeysJob::start(const QStringList &keyIds)
+{
+ run(std::bind(&importfromkeyserver, std::placeholders::_1, keyIds));
+ return Error();
+}
+
+GpgME::ImportResult QGpgME::QGpgMEReceiveKeysJob::exec(const QStringList &keyIds)
+{
+ const result_type r = importfromkeyserver(context(), keyIds);
+ resultHook(r);
+ return mResult;
+}
+
+void QGpgME::QGpgMEReceiveKeysJob::resultHook(const result_type &tuple)
+{
+ mResult = std::get<0>(tuple);
+}
+
+#include "qgpgmereceivekeysjob.moc"
diff --git a/lang/qt/src/qgpgmesecretkeyexportjob.h b/lang/qt/src/qgpgmereceivekeysjob.h
index 78e4d77..96628df 100644
--- a/lang/qt/src/qgpgmesecretkeyexportjob.h
+++ b/lang/qt/src/qgpgmereceivekeysjob.h
@@ -1,10 +1,9 @@
/*
- qgpgmesecretkeyexportjob.h
+ qgpgmereceivekeysjob.h
This file is part of qgpgme, the Qt API binding for gpgme
- Copyright (c) 2004 Klarälvdalens Datakonsult AB
- Copyright (c) 2016 by Bundesamt für Sicherheit in der Informationstechnik
- Software engineering by Intevation GmbH
+ Copyright (c) 2022 g10 Code GmbH
+ Software engineering by Ingo Klöcker <dev@ingo-kloecker.de>
QGpgME is free software; you can redistribute it and/or
modify it under the terms of the GNU General Public License as
@@ -32,51 +31,49 @@
your version.
*/
-#ifndef __QGPGME_QGPGMESECRETKEYEXPORTJOB_H__
-#define __QGPGME_QGPGMESECRETKEYEXPORTJOB_H__
+#ifndef __QGPGME_QGPGMERECEIVEKEYSJOB_H__
+#define __QGPGME_QGPGMERECEIVEKEYSJOB_H__
+
+#include "receivekeysjob.h"
+
+#include "threadedjobmixin.h"
-#include "exportjob.h"
#ifdef BUILDING_QGPGME
-# include "context.h"
+# include "importresult.h"
#else
-#include "gpgme++/context.h"
+# include <gpgme++/importresult.h>
#endif
-#include <QProcess>
-
-namespace GpgME
-{
-class Data;
-}
namespace QGpgME
{
-class QGpgMESecretKeyExportJob : public ExportJob
+class QGpgMEReceiveKeysJob
+#ifdef Q_MOC_RUN
+ : public ReceiveKeysJob
+#else
+ : public _detail::ThreadedJobMixin<ReceiveKeysJob, std::tuple<GpgME::ImportResult, QString, GpgME::Error>>
+#endif
{
Q_OBJECT
+#ifdef Q_MOC_RUN
+public Q_SLOTS:
+ void slotFinished();
+#endif
public:
- QGpgMESecretKeyExportJob(bool armour, const QString &charset);
- ~QGpgMESecretKeyExportJob();
+ explicit QGpgMEReceiveKeysJob(GpgME::Context *context);
+ ~QGpgMEReceiveKeysJob() override;
- /* from ExportJob */
- GpgME::Error start(const QStringList &patterns) Q_DECL_OVERRIDE;
+ GpgME::Error start(const QStringList &keyIds) override;
-private Q_SLOTS:
- /* from Job */
- void slotCancel() Q_DECL_OVERRIDE;
+ GpgME::ImportResult exec(const QStringList &keyIds) override;
- void slotStdout();
- void slotStderr();
- void slotProcessExited(int exitCode, QProcess::ExitStatus exitStatus);
+ /* from ThreadedJobMixin */
+ void resultHook(const result_type &r) override;
private:
- QProcess *mProcess;
- QByteArray mKeyData;
- GpgME::Error mError;
- bool mArmour;
- QString mCharset;
+ GpgME::ImportResult mResult;
};
}
-#endif // __QGPGME_QGPGMESECRETKEYEXPORTJOB_H__
+#endif // __QGPGME_QGPGMERECEIVEKEYSJOB_H__
diff --git a/lang/qt/src/qgpgmesecretkeyexportjob.cpp b/lang/qt/src/qgpgmesecretkeyexportjob.cpp
deleted file mode 100644
index d472bc4..0000000
--- a/lang/qt/src/qgpgmesecretkeyexportjob.cpp
+++ /dev/null
@@ -1,147 +0,0 @@
-/*
- qgpgmesecretexportjob.cpp
-
- This file is part of qgpgme, the Qt API binding for gpgme
- Copyright (c) 2004 Klarävdalens Datakonsult AB
- Copyright (c) 2016 by Bundesamt für Sicherheit in der Informationstechnik
- Software engineering by Intevation GmbH
-
- QGpgME is free software; you can redistribute it and/or
- modify it under the terms of the GNU General Public License as
- published by the Free Software Foundation; either version 2 of the
- License, or (at your option) any later version.
-
- QGpgME is distributed in the hope that it will be useful,
- but WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- General Public License for more details.
-
- You should have received a copy of the GNU General Public License
- along with this program; if not, write to the Free Software
- Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
-
- In addition, as a special exception, the copyright holders give
- permission to link the code of this program with any edition of
- the Qt library by Trolltech AS, Norway (or with modified versions
- of Qt that use the same license as Qt), and distribute linked
- combinations including the two. You must obey the GNU General
- Public License in all respects for all of the code used other than
- Qt. If you modify this file, you may extend this exception to
- your version of the file, but you are not obligated to do so. If
- you do not wish to do so, delete this exception statement from
- your version.
-*/
-
-#ifdef HAVE_CONFIG_H
- #include "config.h"
-#endif
-
-#include "qgpgmesecretkeyexportjob.h"
-
-#include <QDebug>
-#include "qgpgme_debug.h"
-
-#include "context.h"
-#include "data.h"
-
-#include <QStringList>
-
-#include <gpg-error.h>
-
-#include <string.h>
-#include <assert.h>
-
-QGpgME::QGpgMESecretKeyExportJob::QGpgMESecretKeyExportJob(bool armour, const QString &charset)
- : ExportJob(nullptr),
- mProcess(nullptr),
- mError(0),
- mArmour(armour),
- mCharset(charset)
-{
-
-}
-
-QGpgME::QGpgMESecretKeyExportJob::~QGpgMESecretKeyExportJob()
-{
-
-}
-
-GpgME::Error QGpgME::QGpgMESecretKeyExportJob::start(const QStringList &patterns)
-{
- assert(mKeyData.isEmpty());
-
- if (patterns.size() != 1 || patterns.front().isEmpty()) {
- deleteLater();
- return mError = GpgME::Error::fromCode(GPG_ERR_INV_VALUE, GPG_ERR_SOURCE_GPGSM);
- }
-
- // create and start gpgsm process:
- mProcess = new QProcess(this);
- mProcess->setObjectName(QStringLiteral("gpgsm --export-secret-key-p12"));
-
- // FIXME: obtain the path to gpgsm from gpgme, so we use the same instance.
- mProcess->setProgram("gpgsm");
- QStringList arguments;
- arguments << QStringLiteral("--export-secret-key-p12");
- if (mArmour) {
- arguments << QStringLiteral("--armor");
- }
- if (!mCharset.isEmpty()) {
- arguments << QStringLiteral("--p12-charset") << mCharset;
- }
- arguments << QLatin1String(patterns.front().toUtf8());
-
- mProcess->setArguments(arguments);
- connect(mProcess, SIGNAL(finished(int,QProcess::ExitStatus)),
- SLOT(slotProcessExited(int,QProcess::ExitStatus)));
- connect(mProcess, &QProcess::readyReadStandardOutput,
- this, &QGpgMESecretKeyExportJob::slotStdout);
- connect(mProcess, &QProcess::readyReadStandardError,
- this, &QGpgMESecretKeyExportJob::slotStderr);
-
- mProcess->start();
- if (!mProcess->waitForStarted()) {
- mError = GpgME::Error::fromCode(GPG_ERR_ENOENT, GPG_ERR_SOURCE_GPGSM); // what else?
- deleteLater();
- return mError;
- } else {
- return GpgME::Error();
- }
-}
-
-void QGpgME::QGpgMESecretKeyExportJob::slotCancel()
-{
- if (mProcess) {
- mProcess->kill();
- }
- mProcess = nullptr;
- mError = GpgME::Error::fromCode(GPG_ERR_CANCELED, GPG_ERR_SOURCE_GPGSM);
-}
-
-void QGpgME::QGpgMESecretKeyExportJob::slotStdout()
-{
- QString line = QString::fromLocal8Bit(mProcess->readLine());
- if (!line.isEmpty()) {
- return;
- }
- const unsigned int oldlen = mKeyData.size();
- mKeyData.resize(oldlen + line.length());
- memcpy(mKeyData.data() + oldlen, line.toLatin1(), line.length());
-}
-
-void QGpgME::QGpgMESecretKeyExportJob::slotStderr()
-{
- // implement? or not?
-}
-
-void QGpgME::QGpgMESecretKeyExportJob::slotProcessExited(int exitCode, QProcess::ExitStatus exitStatus)
-{
- Q_EMIT done();
- if (!mError &&
- (exitStatus != QProcess::NormalExit || exitCode != 0)) {
- mError = GpgME::Error::fromCode(GPG_ERR_GENERAL, GPG_ERR_SOURCE_GPGSM);
- }
- Q_EMIT result(mError, mKeyData);
- deleteLater();
-}
-#include "qgpgmesecretkeyexportjob.moc"
diff --git a/lang/qt/src/qgpgmewkdlookupjob.cpp b/lang/qt/src/qgpgmewkdlookupjob.cpp
new file mode 100644
index 0000000..266da0d
--- /dev/null
+++ b/lang/qt/src/qgpgmewkdlookupjob.cpp
@@ -0,0 +1,183 @@
+/*
+ qgpgmewkdlookupjob.cpp
+
+ This file is part of qgpgme, the Qt API binding for gpgme
+ Copyright (c) 2021 g10 Code GmbH
+ Software engineering by Ingo Klöcker <dev@ingo-kloecker.de>
+
+ QGpgME is free software; you can redistribute it and/or
+ modify it under the terms of the GNU General Public License as
+ published by the Free Software Foundation; either version 2 of the
+ License, or (at your option) any later version.
+
+ QGpgME is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
+
+ In addition, as a special exception, the copyright holders give
+ permission to link the code of this program with any edition of
+ the Qt library by Trolltech AS, Norway (or with modified versions
+ of Qt that use the same license as Qt), and distribute linked
+ combinations including the two. You must obey the GNU General
+ Public License in all respects for all of the code used other than
+ Qt. If you modify this file, you may extend this exception to
+ your version of the file, but you are not obligated to do so. If
+ you do not wish to do so, delete this exception statement from
+ your version.
+*/
+
+#ifdef HAVE_CONFIG_H
+ #include "config.h"
+#endif
+
+#include "qgpgmewkdlookupjob.h"
+
+#include "qgpgme_debug.h"
+
+#include <context.h>
+#include <data.h>
+#include <defaultassuantransaction.h>
+
+#include <gpg-error.h>
+
+using namespace QGpgME;
+using namespace GpgME;
+
+QGpgMEWKDLookupJob::QGpgMEWKDLookupJob(Context *context)
+ : mixin_type{context}
+{
+ lateInitialization();
+}
+
+QGpgMEWKDLookupJob::~QGpgMEWKDLookupJob() = default;
+
+static GpgME::Error startDirmngr(Context *assuanCtx)
+{
+ Error err;
+
+ auto spawnCtx = std::unique_ptr<Context>{Context::createForEngine(SpawnEngine, &err)};
+ if (err) {
+ qCDebug(QGPGME_LOG) << "Error: Failed to get context for spawn engine (" << err.asString() << ")";
+ }
+
+ const auto dirmngrProgram = GpgME::dirInfo("dirmngr-name");
+ const auto homedir = GpgME::dirInfo("homedir");
+ const char *argv[] = {
+ dirmngrProgram,
+ "--homedir",
+ homedir,
+ "--daemon",
+ NULL
+ };
+ auto ignoreIO = Data{Data::null};
+ if (!err) {
+ qCDebug(QGPGME_LOG) << "Starting dirmngr ...";
+ err = spawnCtx->spawnAsync(dirmngrProgram, argv,
+ ignoreIO, ignoreIO, ignoreIO,
+ Context::SpawnDetached);
+ }
+
+ if (!err) {
+ // wait for socket to become available
+ int cnt = 0;
+ do {
+ ++cnt;
+ qCDebug(QGPGME_LOG) << "Waiting for dirmngr to start ...";
+ QThread::msleep(250 * cnt);
+ err = assuanCtx->assuanTransact("GETINFO version");
+ } while (err.code() == GPG_ERR_ASS_CONNECT_FAILED && cnt < 5);
+ }
+
+ return err;
+}
+
+static GpgME::Error setUpDirmngrAssuanConnection(Context *ctx)
+{
+ Error err;
+
+ const std::string dirmngrSocket = GpgME::dirInfo("dirmngr-socket");
+ err = ctx->setEngineFileName(dirmngrSocket.c_str());
+
+ if (!err) {
+ err = ctx->setEngineHomeDirectory("");
+ }
+
+ if (!err) {
+ // try do connect to dirmngr
+ err = ctx->assuanTransact("GETINFO version");
+ if (err.code() == GPG_ERR_ASS_CONNECT_FAILED) {
+ err = startDirmngr(ctx);
+ }
+ }
+
+ return err;
+}
+
+static GpgME::Error run_wkd_get(Context *ctx, const std::string &email)
+{
+ Error err;
+
+ const auto cmd = std::string{"WKD_GET "} + email;
+ err = ctx->assuanTransact(cmd.c_str());
+ if (err.code() == GPG_ERR_NO_NAME || err.code() == GPG_ERR_NO_DATA) {
+ // ignore those benign errors; GPG_ERR_NO_NAME indicates that the domain
+ // doesn't exist (on first request); GPG_ERR_NO_DATA indicates that
+ // no key for email is available via WKD or that the domain doesn't
+ // support WKD or that the domain doesn't exist (on subsequent requests
+ // using dirmngr's internal cache)
+ qCDebug(QGPGME_LOG) << "WKD_GET returned" << err.asString() << "; ignoring...";
+ err = {};
+ }
+ if (err) {
+ qCDebug(QGPGME_LOG) << "WKD_GET failed with" << err.asString();
+ }
+
+ return err;
+}
+
+static QGpgMEWKDLookupJob::result_type lookup_keys(Context *ctx, const QString &email)
+{
+ WKDLookupResult result;
+
+ Error err = setUpDirmngrAssuanConnection(ctx);
+
+ const auto pattern = email.toUtf8().toStdString();
+ if (!err) {
+ err = run_wkd_get(ctx, pattern);
+ }
+
+ if (!err) {
+ const auto transaction = std::unique_ptr<DefaultAssuanTransaction>(dynamic_cast<DefaultAssuanTransaction*>(ctx->takeLastAssuanTransaction().release()));
+ const auto source = transaction->firstStatusLine("SOURCE");
+ const auto rawData = transaction->data();
+ if (rawData.size() == 0) {
+ qCDebug(QGPGME_LOG) << "No key found for" << email;
+ result = WKDLookupResult{pattern, GpgME::Data::null, {}, {}};
+ } else {
+ qCDebug(QGPGME_LOG) << "Found key for" << email << "at" << source.c_str();
+ result = WKDLookupResult{pattern, GpgME::Data{rawData.c_str(), rawData.size()}, source, {}};
+ }
+ }
+
+ return std::make_tuple(err ? WKDLookupResult{pattern, err} : result, QString{}, Error{});
+}
+
+Error QGpgMEWKDLookupJob::start(const QString &email)
+{
+ run(std::bind(&lookup_keys, std::placeholders::_1, email));
+ return Error();
+}
+
+WKDLookupResult QGpgMEWKDLookupJob::exec(const QString &email)
+{
+ const result_type r = lookup_keys(context(), email);
+ resultHook(r);
+ return std::get<0>(r);
+}
+
+#include "qgpgmewkdlookupjob.moc"
diff --git a/lang/qt/src/qgpgmewkdlookupjob.h b/lang/qt/src/qgpgmewkdlookupjob.h
new file mode 100644
index 0000000..61f9465
--- /dev/null
+++ b/lang/qt/src/qgpgmewkdlookupjob.h
@@ -0,0 +1,70 @@
+/*
+ qgpgmewkdlookupjob.h
+
+ This file is part of qgpgme, the Qt API binding for gpgme
+ Copyright (c) 2021 g10 Code GmbH
+ Software engineering by Ingo Klöcker <dev@ingo-kloecker.de>
+
+ QGpgME is free software; you can redistribute it and/or
+ modify it under the terms of the GNU General Public License as
+ published by the Free Software Foundation; either version 2 of the
+ License, or (at your option) any later version.
+
+ QGpgME is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
+
+ In addition, as a special exception, the copyright holders give
+ permission to link the code of this program with any edition of
+ the Qt library by Trolltech AS, Norway (or with modified versions
+ of Qt that use the same license as Qt), and distribute linked
+ combinations including the two. You must obey the GNU General
+ Public License in all respects for all of the code used other than
+ Qt. If you modify this file, you may extend this exception to
+ your version of the file, but you are not obligated to do so. If
+ you do not wish to do so, delete this exception statement from
+ your version.
+*/
+
+#ifndef __QGPGME_QGPGMEWKDLOOKUPJOB_H__
+#define __QGPGME_QGPGMEWKDLOOKUPJOB_H__
+
+#include "threadedjobmixin.h"
+#include "wkdlookupjob.h"
+#include "wkdlookupresult.h"
+
+namespace QGpgME
+{
+class WKDLookupResult;
+
+class QGpgMEWKDLookupJob
+#ifdef Q_MOC_RUN
+ : public WKDLookupJob
+#else
+ : public _detail::ThreadedJobMixin<WKDLookupJob, std::tuple<WKDLookupResult, QString, GpgME::Error> >
+#endif
+{
+ Q_OBJECT
+#ifdef Q_MOC_RUN
+public Q_SLOTS:
+ void slotFinished();
+#endif
+public:
+ explicit QGpgMEWKDLookupJob(GpgME::Context *context);
+ ~QGpgMEWKDLookupJob();
+
+ /* from WKDLookupJob */
+ GpgME::Error start(const QString &email) Q_DECL_OVERRIDE;
+
+ /* from WKDLookupJob */
+ WKDLookupResult exec(const QString &email) Q_DECL_OVERRIDE;
+};
+
+}
+
+#endif // __QGPGME_QGPGMEWKDLOOKUPJOB_H__
diff --git a/lang/qt/src/receivekeysjob.h b/lang/qt/src/receivekeysjob.h
new file mode 100644
index 0000000..3f85792
--- /dev/null
+++ b/lang/qt/src/receivekeysjob.h
@@ -0,0 +1,66 @@
+/*
+ receivekeysjob.h
+
+ This file is part of qgpgme, the Qt API binding for gpgme
+ Copyright (c) 2022 g10 Code GmbH
+ Software engineering by Ingo Klöcker <dev@ingo-kloecker.de>
+
+ QGpgME is free software; you can redistribute it and/or
+ modify it under the terms of the GNU General Public License as
+ published by the Free Software Foundation; either version 2 of the
+ License, or (at your option) any later version.
+
+ QGpgME is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
+
+ In addition, as a special exception, the copyright holders give
+ permission to link the code of this program with any edition of
+ the Qt library by Trolltech AS, Norway (or with modified versions
+ of Qt that use the same license as Qt), and distribute linked
+ combinations including the two. You must obey the GNU General
+ Public License in all respects for all of the code used other than
+ Qt. If you modify this file, you may extend this exception to
+ your version of the file, but you are not obligated to do so. If
+ you do not wish to do so, delete this exception statement from
+ your version.
+*/
+
+#ifndef __QGPGME_RECEIVEKEYSJOB_H__
+#define __QGPGME_RECEIVEKEYSJOB_H__
+
+#include "abstractimportjob.h"
+#include "qgpgme_export.h"
+
+namespace QGpgME
+{
+
+class QGPGME_EXPORT ReceiveKeysJob : public AbstractImportJob
+{
+ Q_OBJECT
+protected:
+ explicit ReceiveKeysJob(QObject *parent);
+public:
+ ~ReceiveKeysJob() override;
+
+ /**
+ Starts the import of keys from a keyserver. \a keyIds is a list of
+ key ids and/or fingerprints specifying the keys to import.
+ */
+ virtual GpgME::Error start(const QStringList &keyIds) = 0;
+
+ /**
+ Runs the import of keys from a keyserver. \a keyIds is a list of
+ key ids and/or fingerprints specifying the keys to import.
+ */
+ virtual GpgME::ImportResult exec(const QStringList &keyIds) = 0;
+};
+
+}
+
+#endif // __QGPGME_RECEIVEKEYSJOB_H__
diff --git a/lang/qt/src/signkeyjob.h b/lang/qt/src/signkeyjob.h
index 666af92..f4b3ed8 100644
--- a/lang/qt/src/signkeyjob.h
+++ b/lang/qt/src/signkeyjob.h
@@ -117,14 +117,14 @@ public:
*
* Not pure virtual for ABI compatibility.
**/
- virtual void setDupeOk(bool) {};
+ virtual void setDupeOk(bool) {}
/**
* Add a remark to the signature. This uses rem@gnupg.org as a notation.
*
* Not pure virtual for ABI compatibility.
**/
- virtual void setRemark(const QString &) {};
+ virtual void setRemark(const QString &) {}
/**
* If set, then the created signature will be a trust signature. By default,
@@ -143,7 +143,7 @@ public:
*
* Not pure virtual for ABI compatibility.
**/
- virtual void setTrustSignature(GpgME::TrustSignatureTrust trust, unsigned short depth, const QString &scope) { Q_UNUSED(trust); Q_UNUSED(depth); Q_UNUSED(scope); };
+ virtual void setTrustSignature(GpgME::TrustSignatureTrust trust, unsigned short depth, const QString &scope) { Q_UNUSED(trust); Q_UNUSED(depth); Q_UNUSED(scope); }
/**
* Sets the expiration date of the key signature to @a expiration. By default,
diff --git a/lang/qt/src/threadedjobmixin.cpp b/lang/qt/src/threadedjobmixin.cpp
index 3302918..92e6384 100644
--- a/lang/qt/src/threadedjobmixin.cpp
+++ b/lang/qt/src/threadedjobmixin.cpp
@@ -53,53 +53,10 @@
using namespace QGpgME;
using namespace GpgME;
-#ifdef Q_OS_WIN
-#include <windows.h>
-
-static QString fromEncoding (unsigned int src_encoding, const char *data)
-{
- int n = MultiByteToWideChar(src_encoding, 0, data, -1, NULL, 0);
- if (n < 0) {
- return QString();
- }
-
- wchar_t *result = (wchar_t *) malloc ((n+1) * sizeof *result);
-
- n = MultiByteToWideChar(src_encoding, 0, data, -1, result, n);
- if (n < 0) {
- free(result);
- return QString();
- }
- const auto ret = QString::fromWCharArray(result, n);
- free(result);
- return ret;
-}
-#endif
-
static QString stringFromGpgOutput(const QByteArray &ba)
{
#ifdef Q_OS_WIN
- /* Qt on Windows uses GetACP while GnuPG prefers
- * GetConsoleOutputCP.
- *
- * As we are not a console application GetConsoleOutputCP
- * usually returns 0.
- * From experience the closest thing that let's us guess
- * what GetConsoleOutputCP returns for a console application
- * it appears to be the OEMCP.
- */
- unsigned int cpno = GetConsoleOutputCP ();
- if (!cpno) {
- cpno = GetOEMCP();
- }
- if (!cpno) {
- cpno = GetACP();
- }
- if (!cpno) {
- return QString();
- }
-
- return fromEncoding(cpno, ba.constData());
+ return QString::fromUtf8(ba);
#else
return QString::fromLocal8Bit(ba);
#endif
diff --git a/lang/qt/src/util.cpp b/lang/qt/src/util.cpp
new file mode 100644
index 0000000..3d10e2f
--- /dev/null
+++ b/lang/qt/src/util.cpp
@@ -0,0 +1,47 @@
+/*
+ util.cpp
+
+ This file is part of qgpgme, the Qt API binding for gpgme
+ Copyright (c) 2022 g10 Code GmbH
+ Software engineering by Ingo Klöcker <dev@ingo-kloecker.de>
+
+ QGpgME is free software; you can redistribute it and/or
+ modify it under the terms of the GNU General Public License as
+ published by the Free Software Foundation; either version 2 of the
+ License, or (at your option) any later version.
+
+ QGpgME is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
+
+ In addition, as a special exception, the copyright holders give
+ permission to link the code of this program with any edition of
+ the Qt library by Trolltech AS, Norway (or with modified versions
+ of Qt that use the same license as Qt), and distribute linked
+ combinations including the two. You must obey the GNU General
+ Public License in all respects for all of the code used other than
+ Qt. If you modify this file, you may extend this exception to
+ your version of the file, but you are not obligated to do so. If
+ you do not wish to do so, delete this exception statement from
+ your version.
+*/
+
+#include "util.h"
+
+#include <QStringList>
+#include <functional>
+
+std::vector<std::string> toStrings(const QStringList &l)
+{
+ std::vector<std::string> v;
+ v.reserve(l.size());
+ std::transform(std::begin(l), std::end(l),
+ std::back_inserter(v),
+ std::mem_fn(&QString::toStdString));
+ return v;
+}
diff --git a/lang/qt/src/util.h b/lang/qt/src/util.h
new file mode 100644
index 0000000..94c9733
--- /dev/null
+++ b/lang/qt/src/util.h
@@ -0,0 +1,51 @@
+/*
+ util.h - some internal helpers
+
+ This file is part of qgpgme, the Qt API binding for gpgme
+ Copyright (c) 2022 g10 Code GmbH
+ Software engineering by Ingo Klöcker <dev@ingo-kloecker.de>
+
+ QGpgME is free software; you can redistribute it and/or
+ modify it under the terms of the GNU General Public License as
+ published by the Free Software Foundation; either version 2 of the
+ License, or (at your option) any later version.
+
+ QGpgME is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
+
+ In addition, as a special exception, the copyright holders give
+ permission to link the code of this program with any edition of
+ the Qt library by Trolltech AS, Norway (or with modified versions
+ of Qt that use the same license as Qt), and distribute linked
+ combinations including the two. You must obey the GNU General
+ Public License in all respects for all of the code used other than
+ Qt. If you modify this file, you may extend this exception to
+ your version of the file, but you are not obligated to do so. If
+ you do not wish to do so, delete this exception statement from
+ your version.
+*/
+
+#ifndef __QGPGME_UTIL_H__
+#define __QGPGME_UTIL_H__
+
+#include <gpgme.h>
+
+#include <string>
+#include <vector>
+
+class QStringList;
+
+static inline gpgme_error_t make_error(gpgme_err_code_t code)
+{
+ return gpgme_err_make((gpgme_err_source_t)22, code);
+}
+
+std::vector<std::string> toStrings(const QStringList &l);
+
+#endif // __QGPGME_UTIL_H__
diff --git a/lang/qt/src/wkdlookupjob.h b/lang/qt/src/wkdlookupjob.h
new file mode 100644
index 0000000..ae22874
--- /dev/null
+++ b/lang/qt/src/wkdlookupjob.h
@@ -0,0 +1,78 @@
+/*
+ wkdlookupjob.h
+
+ This file is part of qgpgme, the Qt API binding for gpgme
+ Copyright (c) 2021 g10 Code GmbH
+ Software engineering by Ingo Klöcker <dev@ingo-kloecker.de>
+
+ QGpgME is free software; you can redistribute it and/or
+ modify it under the terms of the GNU General Public License as
+ published by the Free Software Foundation; either version 2 of the
+ License, or (at your option) any later version.
+
+ QGpgME is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
+
+ In addition, as a special exception, the copyright holders give
+ permission to link the code of this program with any edition of
+ the Qt library by Trolltech AS, Norway (or with modified versions
+ of Qt that use the same license as Qt), and distribute linked
+ combinations including the two. You must obey the GNU General
+ Public License in all respects for all of the code used other than
+ Qt. If you modify this file, you may extend this exception to
+ your version of the file, but you are not obligated to do so. If
+ you do not wish to do so, delete this exception statement from
+ your version.
+*/
+
+#ifndef __QGPGME_WKDLOOKUPJOB_H__
+#define __QGPGME_WKDLOOKUPJOB_H__
+
+#include "job.h"
+#include "qgpgme_export.h"
+
+class QString;
+
+namespace GpgME
+{
+class Data;
+class Error;
+}
+
+namespace QGpgME
+{
+
+class WKDLookupResult;
+
+class QGPGME_EXPORT WKDLookupJob : public Job
+{
+ Q_OBJECT
+protected:
+ explicit WKDLookupJob(QObject *parent);
+
+public:
+ ~WKDLookupJob();
+
+ /**
+ Starts a key lookup operation for the email address \a email via WKD.
+ */
+ virtual GpgME::Error start(const QString &email) = 0;
+
+ /**
+ Runs a key lookup operation for the email address \a email via WKD.
+ */
+ virtual WKDLookupResult exec(const QString &email) = 0;
+
+Q_SIGNALS:
+ void result(const WKDLookupResult &result, const QString &auditLogAsHtml = {}, const GpgME::Error &auditLogError = {});
+};
+
+}
+
+#endif // __QGPGME_WKDLOOKUPJOB_H__
diff --git a/lang/qt/src/wkdlookupresult.cpp b/lang/qt/src/wkdlookupresult.cpp
new file mode 100644
index 0000000..c44b737
--- /dev/null
+++ b/lang/qt/src/wkdlookupresult.cpp
@@ -0,0 +1,117 @@
+/*
+ wkdlookupresult.cpp - wraps the result of a WKDLookupJob
+
+ This file is part of qgpgme, the Qt API binding for gpgme
+ Copyright (c) 2021 g10 Code GmbH
+ Software engineering by Ingo Klöcker <dev@ingo-kloecker.de>
+
+ QGpgME is free software; you can redistribute it and/or
+ modify it under the terms of the GNU General Public License as
+ published by the Free Software Foundation; either version 2 of the
+ License, or (at your option) any later version.
+
+ QGpgME is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
+
+ In addition, as a special exception, the copyright holders give
+ permission to link the code of this program with any edition of
+ the Qt library by Trolltech AS, Norway (or with modified versions
+ of Qt that use the same license as Qt), and distribute linked
+ combinations including the two. You must obey the GNU General
+ Public License in all respects for all of the code used other than
+ Qt. If you modify this file, you may extend this exception to
+ your version of the file, but you are not obligated to do so. If
+ you do not wish to do so, delete this exception statement from
+ your version.
+*/
+
+#ifdef HAVE_CONFIG_H
+ #include "config.h"
+#endif
+
+#include "wkdlookupresult.h"
+
+#include <data.h>
+
+using namespace QGpgME;
+using namespace GpgME;
+
+class WKDLookupResult::Private
+{
+public:
+ std::string pattern;
+ GpgME::Data keyData;
+ std::string source;
+};
+
+WKDLookupResult::WKDLookupResult() = default;
+
+WKDLookupResult::~WKDLookupResult() = default;
+
+WKDLookupResult::WKDLookupResult(const std::string &pattern, const Error &error)
+ : Result{error}
+ , d{new Private{pattern, {}, {}}}
+{
+}
+
+WKDLookupResult::WKDLookupResult(const std::string &pattern, const Data &keyData, const std::string &source, const Error &error)
+ : Result{error}
+ , d{new Private{pattern, keyData, source}}
+{
+}
+
+WKDLookupResult::WKDLookupResult(const WKDLookupResult &other)
+ : Result{other}
+{
+ if (other.d) {
+ d.reset(new Private{*other.d});
+ }
+}
+
+WKDLookupResult &WKDLookupResult::operator=(const WKDLookupResult &other)
+{
+ auto tmp = other;
+ swap(tmp);
+ return *this;
+}
+
+WKDLookupResult::WKDLookupResult(WKDLookupResult &&other) = default;
+
+WKDLookupResult &WKDLookupResult::operator=(WKDLookupResult &&other) = default;
+
+void WKDLookupResult::swap(WKDLookupResult &other) noexcept
+{
+ Result::swap(other);
+ std::swap(this->d, other.d);
+}
+
+bool WKDLookupResult::isNull() const
+{
+ return !d && !bool(error());
+}
+
+std::string WKDLookupResult::pattern() const
+{
+ return d ? d->pattern : std::string{};
+}
+
+Data WKDLookupResult::keyData() const
+{
+ return d ? d->keyData : Data{};
+}
+
+std::string WKDLookupResult::source() const
+{
+ return d ? d->source : std::string{};
+}
+
+void QGpgME::swap(WKDLookupResult &a, WKDLookupResult &b)
+{
+ a.swap(b);
+}
diff --git a/lang/qt/src/wkdlookupresult.h b/lang/qt/src/wkdlookupresult.h
new file mode 100644
index 0000000..1e91d05
--- /dev/null
+++ b/lang/qt/src/wkdlookupresult.h
@@ -0,0 +1,88 @@
+/*
+ wkdlookupresult.h - wraps the result of a WKDLookupJob
+
+ This file is part of qgpgme, the Qt API binding for gpgme
+ Copyright (c) 2021 g10 Code GmbH
+ Software engineering by Ingo Klöcker <dev@ingo-kloecker.de>
+
+ QGpgME is free software; you can redistribute it and/or
+ modify it under the terms of the GNU General Public License as
+ published by the Free Software Foundation; either version 2 of the
+ License, or (at your option) any later version.
+
+ QGpgME is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
+
+ In addition, as a special exception, the copyright holders give
+ permission to link the code of this program with any edition of
+ the Qt library by Trolltech AS, Norway (or with modified versions
+ of Qt that use the same license as Qt), and distribute linked
+ combinations including the two. You must obey the GNU General
+ Public License in all respects for all of the code used other than
+ Qt. If you modify this file, you may extend this exception to
+ your version of the file, but you are not obligated to do so. If
+ you do not wish to do so, delete this exception statement from
+ your version.
+*/
+
+#ifndef __QGPGME_WKDLOOKUPRESULT_H__
+#define __QGPGME_WKDLOOKUPRESULT_H__
+
+#include "qgpgme_export.h"
+
+#ifdef BUILDING_QGPGME
+# include <result.h>
+#else
+# include <gpgme++/result.h>
+#endif
+
+#include <memory>
+
+namespace GpgME
+{
+class Data;
+class Error;
+}
+
+namespace QGpgME
+{
+
+class QGPGME_EXPORT WKDLookupResult : public GpgME::Result
+{
+public:
+ WKDLookupResult();
+ ~WKDLookupResult();
+
+ explicit WKDLookupResult(const std::string &pattern, const GpgME::Error &err);
+ explicit WKDLookupResult(const std::string &pattern, const GpgME::Data &keyData, const std::string &source, const GpgME::Error &err);
+
+ WKDLookupResult(const WKDLookupResult &other);
+ WKDLookupResult &operator=(const WKDLookupResult &other);
+
+ WKDLookupResult(WKDLookupResult &&other);
+ WKDLookupResult &operator=(WKDLookupResult &&other);
+
+ void swap(WKDLookupResult &other) noexcept;
+
+ bool isNull() const;
+
+ std::string pattern() const;
+ GpgME::Data keyData() const;
+ std::string source() const;
+
+private:
+ class Private;
+ std::unique_ptr<Private> d;
+};
+
+QGPGME_EXPORT void swap(WKDLookupResult &a, WKDLookupResult &b);
+
+}
+
+#endif // __QGPGME_WKDLOOKUPRESULT_H__
diff --git a/lang/qt/tests/Makefile.am b/lang/qt/tests/Makefile.am
index 41ea808..6c082b0 100644
--- a/lang/qt/tests/Makefile.am
+++ b/lang/qt/tests/Makefile.am
@@ -24,14 +24,22 @@ GPG = gpg
GNUPGHOME=$(abs_builddir)
TESTS_ENVIRONMENT = GNUPGHOME=$(GNUPGHOME)
-EXTRA_DIST = initial.test
+EXTRA_DIST = initial.test final.test
-TESTS = initial.test t-keylist t-keylocate t-ownertrust t-tofuinfo \
- t-encrypt t-verify t-various t-config t-remarks t-trustsignatures
+the_tests = \
+ t-addexistingsubkey \
+ t-keylist t-keylocate t-ownertrust t-tofuinfo \
+ t-encrypt t-verify t-various t-config t-remarks t-trustsignatures \
+ t-changeexpiryjob t-wkdlookup t-import
-moc_files = t-keylist.moc t-keylocate.moc t-ownertrust.moc t-tofuinfo.moc \
- t-encrypt.moc t-support.hmoc t-wkspublish.moc t-verify.moc \
- t-various.moc t-config.moc t-remarks.moc t-trustsignatures.moc
+TESTS = initial.test $(the_tests) final.test
+
+moc_files = \
+ t-addexistingsubkey.moc \
+ t-keylist.moc t-keylocate.moc t-ownertrust.moc t-tofuinfo.moc \
+ t-encrypt.moc t-support.hmoc t-wkspublish.moc t-verify.moc \
+ t-various.moc t-config.moc t-remarks.moc t-trustsignatures.moc \
+ t-changeexpiryjob.moc t-wkdlookup.moc t-import.moc
AM_LDFLAGS = -no-install
@@ -47,6 +55,7 @@ AM_CPPFLAGS = -I$(top_srcdir)/lang/cpp/src -I$(top_builddir)/src \
support_src = t-support.h t-support.cpp
+t_addexistingsubkey_SOURCES = t-addexistingsubkey.cpp $(support_src)
t_keylist_SOURCES = t-keylist.cpp $(support_src)
t_keylocate_SOURCES = t-keylocate.cpp $(support_src)
t_ownertrust_SOURCES = t-ownertrust.cpp $(support_src)
@@ -58,15 +67,24 @@ t_various_SOURCES = t-various.cpp $(support_src)
t_config_SOURCES = t-config.cpp $(support_src)
t_remarks_SOURCES = t-remarks.cpp $(support_src)
t_trustsignatures_SOURCES = t-trustsignatures.cpp $(support_src)
+t_changeexpiryjob_SOURCES = t-changeexpiryjob.cpp $(support_src)
+t_wkdlookup_SOURCES = t-wkdlookup.cpp $(support_src)
+t_import_SOURCES = t-import.cpp $(support_src)
+run_exportjob_SOURCES = run-exportjob.cpp
+run_importjob_SOURCES = run-importjob.cpp
run_keyformailboxjob_SOURCES = run-keyformailboxjob.cpp
+run_receivekeysjob_SOURCES = run-receivekeysjob.cpp
nodist_t_keylist_SOURCES = $(moc_files)
BUILT_SOURCES = $(moc_files) pubring-stamp
-noinst_PROGRAMS = t-keylist t-keylocate t-ownertrust t-tofuinfo t-encrypt \
- run-keyformailboxjob t-wkspublish t-verify t-various t-config t-remarks \
- t-trustsignatures
+noinst_PROGRAMS = \
+ t-addexistingsubkey \
+ t-keylist t-keylocate t-ownertrust t-tofuinfo t-encrypt \
+ run-keyformailboxjob t-wkspublish t-verify t-various t-config t-remarks \
+ t-trustsignatures t-changeexpiryjob t-wkdlookup t-import run-importjob \
+ run-exportjob run-receivekeysjob
CLEANFILES = secring.gpg pubring.gpg pubring.kbx trustdb.gpg dirmngr.conf \
gpg-agent.conf pubring.kbx~ S.gpg-agent gpg.conf pubring.gpg~ \
diff --git a/lang/qt/tests/Makefile.in b/lang/qt/tests/Makefile.in
index 2b0e0ee..89fad15 100644
--- a/lang/qt/tests/Makefile.in
+++ b/lang/qt/tests/Makefile.in
@@ -107,15 +107,15 @@ PRE_UNINSTALL = :
POST_UNINSTALL = :
build_triplet = @build@
host_triplet = @host@
-TESTS = initial.test t-keylist$(EXEEXT) t-keylocate$(EXEEXT) \
- t-ownertrust$(EXEEXT) t-tofuinfo$(EXEEXT) t-encrypt$(EXEEXT) \
- t-verify$(EXEEXT) t-various$(EXEEXT) t-config$(EXEEXT) \
- t-remarks$(EXEEXT) t-trustsignatures$(EXEEXT)
-noinst_PROGRAMS = t-keylist$(EXEEXT) t-keylocate$(EXEEXT) \
- t-ownertrust$(EXEEXT) t-tofuinfo$(EXEEXT) t-encrypt$(EXEEXT) \
- run-keyformailboxjob$(EXEEXT) t-wkspublish$(EXEEXT) \
- t-verify$(EXEEXT) t-various$(EXEEXT) t-config$(EXEEXT) \
- t-remarks$(EXEEXT) t-trustsignatures$(EXEEXT)
+TESTS = initial.test $(am__EXEEXT_1) final.test
+noinst_PROGRAMS = t-addexistingsubkey$(EXEEXT) t-keylist$(EXEEXT) \
+ t-keylocate$(EXEEXT) t-ownertrust$(EXEEXT) t-tofuinfo$(EXEEXT) \
+ t-encrypt$(EXEEXT) run-keyformailboxjob$(EXEEXT) \
+ t-wkspublish$(EXEEXT) t-verify$(EXEEXT) t-various$(EXEEXT) \
+ t-config$(EXEEXT) t-remarks$(EXEEXT) \
+ t-trustsignatures$(EXEEXT) t-changeexpiryjob$(EXEEXT) \
+ t-wkdlookup$(EXEEXT) t-import$(EXEEXT) run-importjob$(EXEEXT) \
+ run-exportjob$(EXEEXT) run-receivekeysjob$(EXEEXT)
subdir = lang/qt/tests
ACLOCAL_M4 = $(top_srcdir)/aclocal.m4
am__aclocal_m4_deps = $(top_srcdir)/m4/ax_cxx_compile_stdcxx.m4 \
@@ -137,16 +137,43 @@ CONFIG_HEADER = $(top_builddir)/conf/config.h
CONFIG_CLEAN_FILES =
CONFIG_CLEAN_VPATH_FILES =
PROGRAMS = $(noinst_PROGRAMS)
-am_run_keyformailboxjob_OBJECTS = run-keyformailboxjob.$(OBJEXT)
-run_keyformailboxjob_OBJECTS = $(am_run_keyformailboxjob_OBJECTS)
-run_keyformailboxjob_LDADD = $(LDADD)
-run_keyformailboxjob_DEPENDENCIES = ../../cpp/src/libgpgmepp.la \
+am_run_exportjob_OBJECTS = run-exportjob.$(OBJEXT)
+run_exportjob_OBJECTS = $(am_run_exportjob_OBJECTS)
+run_exportjob_LDADD = $(LDADD)
+run_exportjob_DEPENDENCIES = ../../cpp/src/libgpgmepp.la \
../src/libqgpgme.la ../../../src/libgpgme.la
AM_V_lt = $(am__v_lt_@AM_V@)
am__v_lt_ = $(am__v_lt_@AM_DEFAULT_V@)
am__v_lt_0 = --silent
am__v_lt_1 =
+am_run_importjob_OBJECTS = run-importjob.$(OBJEXT)
+run_importjob_OBJECTS = $(am_run_importjob_OBJECTS)
+run_importjob_LDADD = $(LDADD)
+run_importjob_DEPENDENCIES = ../../cpp/src/libgpgmepp.la \
+ ../src/libqgpgme.la ../../../src/libgpgme.la
+am_run_keyformailboxjob_OBJECTS = run-keyformailboxjob.$(OBJEXT)
+run_keyformailboxjob_OBJECTS = $(am_run_keyformailboxjob_OBJECTS)
+run_keyformailboxjob_LDADD = $(LDADD)
+run_keyformailboxjob_DEPENDENCIES = ../../cpp/src/libgpgmepp.la \
+ ../src/libqgpgme.la ../../../src/libgpgme.la
+am_run_receivekeysjob_OBJECTS = run-receivekeysjob.$(OBJEXT)
+run_receivekeysjob_OBJECTS = $(am_run_receivekeysjob_OBJECTS)
+run_receivekeysjob_LDADD = $(LDADD)
+run_receivekeysjob_DEPENDENCIES = ../../cpp/src/libgpgmepp.la \
+ ../src/libqgpgme.la ../../../src/libgpgme.la
am__objects_1 = t-support.$(OBJEXT)
+am_t_addexistingsubkey_OBJECTS = t-addexistingsubkey.$(OBJEXT) \
+ $(am__objects_1)
+t_addexistingsubkey_OBJECTS = $(am_t_addexistingsubkey_OBJECTS)
+t_addexistingsubkey_LDADD = $(LDADD)
+t_addexistingsubkey_DEPENDENCIES = ../../cpp/src/libgpgmepp.la \
+ ../src/libqgpgme.la ../../../src/libgpgme.la
+am_t_changeexpiryjob_OBJECTS = t-changeexpiryjob.$(OBJEXT) \
+ $(am__objects_1)
+t_changeexpiryjob_OBJECTS = $(am_t_changeexpiryjob_OBJECTS)
+t_changeexpiryjob_LDADD = $(LDADD)
+t_changeexpiryjob_DEPENDENCIES = ../../cpp/src/libgpgmepp.la \
+ ../src/libqgpgme.la ../../../src/libgpgme.la
am_t_config_OBJECTS = t-config.$(OBJEXT) $(am__objects_1)
t_config_OBJECTS = $(am_t_config_OBJECTS)
t_config_LDADD = $(LDADD)
@@ -157,6 +184,11 @@ t_encrypt_OBJECTS = $(am_t_encrypt_OBJECTS)
t_encrypt_LDADD = $(LDADD)
t_encrypt_DEPENDENCIES = ../../cpp/src/libgpgmepp.la \
../src/libqgpgme.la ../../../src/libgpgme.la
+am_t_import_OBJECTS = t-import.$(OBJEXT) $(am__objects_1)
+t_import_OBJECTS = $(am_t_import_OBJECTS)
+t_import_LDADD = $(LDADD)
+t_import_DEPENDENCIES = ../../cpp/src/libgpgmepp.la \
+ ../src/libqgpgme.la ../../../src/libgpgme.la
am_t_keylist_OBJECTS = t-keylist.$(OBJEXT) $(am__objects_1)
am__objects_2 =
nodist_t_keylist_OBJECTS = $(am__objects_2)
@@ -201,6 +233,11 @@ t_verify_OBJECTS = $(am_t_verify_OBJECTS)
t_verify_LDADD = $(LDADD)
t_verify_DEPENDENCIES = ../../cpp/src/libgpgmepp.la \
../src/libqgpgme.la ../../../src/libgpgme.la
+am_t_wkdlookup_OBJECTS = t-wkdlookup.$(OBJEXT) $(am__objects_1)
+t_wkdlookup_OBJECTS = $(am_t_wkdlookup_OBJECTS)
+t_wkdlookup_LDADD = $(LDADD)
+t_wkdlookup_DEPENDENCIES = ../../cpp/src/libgpgmepp.la \
+ ../src/libqgpgme.la ../../../src/libgpgme.la
am_t_wkspublish_OBJECTS = t-wkspublish.$(OBJEXT) $(am__objects_1)
t_wkspublish_OBJECTS = $(am_t_wkspublish_OBJECTS)
t_wkspublish_LDADD = $(LDADD)
@@ -221,13 +258,19 @@ am__v_at_1 =
DEFAULT_INCLUDES = -I.@am__isrc@ -I$(top_builddir)/conf
depcomp = $(SHELL) $(top_srcdir)/build-aux/depcomp
am__maybe_remake_depfiles = depfiles
-am__depfiles_remade = ./$(DEPDIR)/run-keyformailboxjob.Po \
- ./$(DEPDIR)/t-config.Po ./$(DEPDIR)/t-encrypt.Po \
+am__depfiles_remade = ./$(DEPDIR)/run-exportjob.Po \
+ ./$(DEPDIR)/run-importjob.Po \
+ ./$(DEPDIR)/run-keyformailboxjob.Po \
+ ./$(DEPDIR)/run-receivekeysjob.Po \
+ ./$(DEPDIR)/t-addexistingsubkey.Po \
+ ./$(DEPDIR)/t-changeexpiryjob.Po ./$(DEPDIR)/t-config.Po \
+ ./$(DEPDIR)/t-encrypt.Po ./$(DEPDIR)/t-import.Po \
./$(DEPDIR)/t-keylist.Po ./$(DEPDIR)/t-keylocate.Po \
./$(DEPDIR)/t-ownertrust.Po ./$(DEPDIR)/t-remarks.Po \
./$(DEPDIR)/t-support.Po ./$(DEPDIR)/t-tofuinfo.Po \
./$(DEPDIR)/t-trustsignatures.Po ./$(DEPDIR)/t-various.Po \
- ./$(DEPDIR)/t-verify.Po ./$(DEPDIR)/t-wkspublish.Po
+ ./$(DEPDIR)/t-verify.Po ./$(DEPDIR)/t-wkdlookup.Po \
+ ./$(DEPDIR)/t-wkspublish.Po
am__mv = mv -f
CXXCOMPILE = $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) \
$(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS)
@@ -265,19 +308,25 @@ AM_V_CCLD = $(am__v_CCLD_@AM_V@)
am__v_CCLD_ = $(am__v_CCLD_@AM_DEFAULT_V@)
am__v_CCLD_0 = @echo " CCLD " $@;
am__v_CCLD_1 =
-SOURCES = $(run_keyformailboxjob_SOURCES) $(t_config_SOURCES) \
- $(t_encrypt_SOURCES) $(t_keylist_SOURCES) \
- $(nodist_t_keylist_SOURCES) $(t_keylocate_SOURCES) \
- $(t_ownertrust_SOURCES) $(t_remarks_SOURCES) \
- $(t_tofuinfo_SOURCES) $(t_trustsignatures_SOURCES) \
- $(t_various_SOURCES) $(t_verify_SOURCES) \
- $(t_wkspublish_SOURCES)
-DIST_SOURCES = $(run_keyformailboxjob_SOURCES) $(t_config_SOURCES) \
- $(t_encrypt_SOURCES) $(t_keylist_SOURCES) \
+SOURCES = $(run_exportjob_SOURCES) $(run_importjob_SOURCES) \
+ $(run_keyformailboxjob_SOURCES) $(run_receivekeysjob_SOURCES) \
+ $(t_addexistingsubkey_SOURCES) $(t_changeexpiryjob_SOURCES) \
+ $(t_config_SOURCES) $(t_encrypt_SOURCES) $(t_import_SOURCES) \
+ $(t_keylist_SOURCES) $(nodist_t_keylist_SOURCES) \
$(t_keylocate_SOURCES) $(t_ownertrust_SOURCES) \
$(t_remarks_SOURCES) $(t_tofuinfo_SOURCES) \
$(t_trustsignatures_SOURCES) $(t_various_SOURCES) \
- $(t_verify_SOURCES) $(t_wkspublish_SOURCES)
+ $(t_verify_SOURCES) $(t_wkdlookup_SOURCES) \
+ $(t_wkspublish_SOURCES)
+DIST_SOURCES = $(run_exportjob_SOURCES) $(run_importjob_SOURCES) \
+ $(run_keyformailboxjob_SOURCES) $(run_receivekeysjob_SOURCES) \
+ $(t_addexistingsubkey_SOURCES) $(t_changeexpiryjob_SOURCES) \
+ $(t_config_SOURCES) $(t_encrypt_SOURCES) $(t_import_SOURCES) \
+ $(t_keylist_SOURCES) $(t_keylocate_SOURCES) \
+ $(t_ownertrust_SOURCES) $(t_remarks_SOURCES) \
+ $(t_tofuinfo_SOURCES) $(t_trustsignatures_SOURCES) \
+ $(t_various_SOURCES) $(t_verify_SOURCES) \
+ $(t_wkdlookup_SOURCES) $(t_wkspublish_SOURCES)
am__can_run_installinfo = \
case $$AM_UPDATE_INFO_DIR in \
n|no|NO) false;; \
@@ -324,6 +373,12 @@ am__tty_colors = { \
std=''; \
fi; \
}
+am__EXEEXT_1 = t-addexistingsubkey$(EXEEXT) t-keylist$(EXEEXT) \
+ t-keylocate$(EXEEXT) t-ownertrust$(EXEEXT) t-tofuinfo$(EXEEXT) \
+ t-encrypt$(EXEEXT) t-verify$(EXEEXT) t-various$(EXEEXT) \
+ t-config$(EXEEXT) t-remarks$(EXEEXT) \
+ t-trustsignatures$(EXEEXT) t-changeexpiryjob$(EXEEXT) \
+ t-wkdlookup$(EXEEXT) t-import$(EXEEXT)
am__DIST_COMMON = $(srcdir)/Makefile.in \
$(top_srcdir)/build-aux/depcomp \
$(top_srcdir)/build-aux/mkinstalldirs
@@ -529,10 +584,19 @@ top_srcdir = @top_srcdir@
GPG = gpg
GNUPGHOME = $(abs_builddir)
TESTS_ENVIRONMENT = GNUPGHOME=$(GNUPGHOME)
-EXTRA_DIST = initial.test
-moc_files = t-keylist.moc t-keylocate.moc t-ownertrust.moc t-tofuinfo.moc \
- t-encrypt.moc t-support.hmoc t-wkspublish.moc t-verify.moc \
- t-various.moc t-config.moc t-remarks.moc t-trustsignatures.moc
+EXTRA_DIST = initial.test final.test
+the_tests = \
+ t-addexistingsubkey \
+ t-keylist t-keylocate t-ownertrust t-tofuinfo \
+ t-encrypt t-verify t-various t-config t-remarks t-trustsignatures \
+ t-changeexpiryjob t-wkdlookup t-import
+
+moc_files = \
+ t-addexistingsubkey.moc \
+ t-keylist.moc t-keylocate.moc t-ownertrust.moc t-tofuinfo.moc \
+ t-encrypt.moc t-support.hmoc t-wkspublish.moc t-verify.moc \
+ t-various.moc t-config.moc t-remarks.moc t-trustsignatures.moc \
+ t-changeexpiryjob.moc t-wkdlookup.moc t-import.moc
AM_LDFLAGS = -no-install
LDADD = ../../cpp/src/libgpgmepp.la ../src/libqgpgme.la \
@@ -546,6 +610,7 @@ AM_CPPFLAGS = -I$(top_srcdir)/lang/cpp/src -I$(top_builddir)/src \
-DTOP_SRCDIR="$(top_srcdir)"
support_src = t-support.h t-support.cpp
+t_addexistingsubkey_SOURCES = t-addexistingsubkey.cpp $(support_src)
t_keylist_SOURCES = t-keylist.cpp $(support_src)
t_keylocate_SOURCES = t-keylocate.cpp $(support_src)
t_ownertrust_SOURCES = t-ownertrust.cpp $(support_src)
@@ -557,7 +622,13 @@ t_various_SOURCES = t-various.cpp $(support_src)
t_config_SOURCES = t-config.cpp $(support_src)
t_remarks_SOURCES = t-remarks.cpp $(support_src)
t_trustsignatures_SOURCES = t-trustsignatures.cpp $(support_src)
+t_changeexpiryjob_SOURCES = t-changeexpiryjob.cpp $(support_src)
+t_wkdlookup_SOURCES = t-wkdlookup.cpp $(support_src)
+t_import_SOURCES = t-import.cpp $(support_src)
+run_exportjob_SOURCES = run-exportjob.cpp
+run_importjob_SOURCES = run-importjob.cpp
run_keyformailboxjob_SOURCES = run-keyformailboxjob.cpp
+run_receivekeysjob_SOURCES = run-receivekeysjob.cpp
nodist_t_keylist_SOURCES = $(moc_files)
BUILT_SOURCES = $(moc_files) pubring-stamp
CLEANFILES = secring.gpg pubring.gpg pubring.kbx trustdb.gpg dirmngr.conf \
@@ -609,10 +680,30 @@ clean-noinstPROGRAMS:
echo " rm -f" $$list; \
rm -f $$list
+run-exportjob$(EXEEXT): $(run_exportjob_OBJECTS) $(run_exportjob_DEPENDENCIES) $(EXTRA_run_exportjob_DEPENDENCIES)
+ @rm -f run-exportjob$(EXEEXT)
+ $(AM_V_CXXLD)$(CXXLINK) $(run_exportjob_OBJECTS) $(run_exportjob_LDADD) $(LIBS)
+
+run-importjob$(EXEEXT): $(run_importjob_OBJECTS) $(run_importjob_DEPENDENCIES) $(EXTRA_run_importjob_DEPENDENCIES)
+ @rm -f run-importjob$(EXEEXT)
+ $(AM_V_CXXLD)$(CXXLINK) $(run_importjob_OBJECTS) $(run_importjob_LDADD) $(LIBS)
+
run-keyformailboxjob$(EXEEXT): $(run_keyformailboxjob_OBJECTS) $(run_keyformailboxjob_DEPENDENCIES) $(EXTRA_run_keyformailboxjob_DEPENDENCIES)
@rm -f run-keyformailboxjob$(EXEEXT)
$(AM_V_CXXLD)$(CXXLINK) $(run_keyformailboxjob_OBJECTS) $(run_keyformailboxjob_LDADD) $(LIBS)
+run-receivekeysjob$(EXEEXT): $(run_receivekeysjob_OBJECTS) $(run_receivekeysjob_DEPENDENCIES) $(EXTRA_run_receivekeysjob_DEPENDENCIES)
+ @rm -f run-receivekeysjob$(EXEEXT)
+ $(AM_V_CXXLD)$(CXXLINK) $(run_receivekeysjob_OBJECTS) $(run_receivekeysjob_LDADD) $(LIBS)
+
+t-addexistingsubkey$(EXEEXT): $(t_addexistingsubkey_OBJECTS) $(t_addexistingsubkey_DEPENDENCIES) $(EXTRA_t_addexistingsubkey_DEPENDENCIES)
+ @rm -f t-addexistingsubkey$(EXEEXT)
+ $(AM_V_CXXLD)$(CXXLINK) $(t_addexistingsubkey_OBJECTS) $(t_addexistingsubkey_LDADD) $(LIBS)
+
+t-changeexpiryjob$(EXEEXT): $(t_changeexpiryjob_OBJECTS) $(t_changeexpiryjob_DEPENDENCIES) $(EXTRA_t_changeexpiryjob_DEPENDENCIES)
+ @rm -f t-changeexpiryjob$(EXEEXT)
+ $(AM_V_CXXLD)$(CXXLINK) $(t_changeexpiryjob_OBJECTS) $(t_changeexpiryjob_LDADD) $(LIBS)
+
t-config$(EXEEXT): $(t_config_OBJECTS) $(t_config_DEPENDENCIES) $(EXTRA_t_config_DEPENDENCIES)
@rm -f t-config$(EXEEXT)
$(AM_V_CXXLD)$(CXXLINK) $(t_config_OBJECTS) $(t_config_LDADD) $(LIBS)
@@ -621,6 +712,10 @@ t-encrypt$(EXEEXT): $(t_encrypt_OBJECTS) $(t_encrypt_DEPENDENCIES) $(EXTRA_t_enc
@rm -f t-encrypt$(EXEEXT)
$(AM_V_CXXLD)$(CXXLINK) $(t_encrypt_OBJECTS) $(t_encrypt_LDADD) $(LIBS)
+t-import$(EXEEXT): $(t_import_OBJECTS) $(t_import_DEPENDENCIES) $(EXTRA_t_import_DEPENDENCIES)
+ @rm -f t-import$(EXEEXT)
+ $(AM_V_CXXLD)$(CXXLINK) $(t_import_OBJECTS) $(t_import_LDADD) $(LIBS)
+
t-keylist$(EXEEXT): $(t_keylist_OBJECTS) $(t_keylist_DEPENDENCIES) $(EXTRA_t_keylist_DEPENDENCIES)
@rm -f t-keylist$(EXEEXT)
$(AM_V_CXXLD)$(CXXLINK) $(t_keylist_OBJECTS) $(t_keylist_LDADD) $(LIBS)
@@ -653,6 +748,10 @@ t-verify$(EXEEXT): $(t_verify_OBJECTS) $(t_verify_DEPENDENCIES) $(EXTRA_t_verify
@rm -f t-verify$(EXEEXT)
$(AM_V_CXXLD)$(CXXLINK) $(t_verify_OBJECTS) $(t_verify_LDADD) $(LIBS)
+t-wkdlookup$(EXEEXT): $(t_wkdlookup_OBJECTS) $(t_wkdlookup_DEPENDENCIES) $(EXTRA_t_wkdlookup_DEPENDENCIES)
+ @rm -f t-wkdlookup$(EXEEXT)
+ $(AM_V_CXXLD)$(CXXLINK) $(t_wkdlookup_OBJECTS) $(t_wkdlookup_LDADD) $(LIBS)
+
t-wkspublish$(EXEEXT): $(t_wkspublish_OBJECTS) $(t_wkspublish_DEPENDENCIES) $(EXTRA_t_wkspublish_DEPENDENCIES)
@rm -f t-wkspublish$(EXEEXT)
$(AM_V_CXXLD)$(CXXLINK) $(t_wkspublish_OBJECTS) $(t_wkspublish_LDADD) $(LIBS)
@@ -663,9 +762,15 @@ mostlyclean-compile:
distclean-compile:
-rm -f *.tab.c
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/run-exportjob.Po@am__quote@ # am--include-marker
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/run-importjob.Po@am__quote@ # am--include-marker
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/run-keyformailboxjob.Po@am__quote@ # am--include-marker
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/run-receivekeysjob.Po@am__quote@ # am--include-marker
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/t-addexistingsubkey.Po@am__quote@ # am--include-marker
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/t-changeexpiryjob.Po@am__quote@ # am--include-marker
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/t-config.Po@am__quote@ # am--include-marker
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/t-encrypt.Po@am__quote@ # am--include-marker
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/t-import.Po@am__quote@ # am--include-marker
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/t-keylist.Po@am__quote@ # am--include-marker
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/t-keylocate.Po@am__quote@ # am--include-marker
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/t-ownertrust.Po@am__quote@ # am--include-marker
@@ -675,6 +780,7 @@ distclean-compile:
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/t-trustsignatures.Po@am__quote@ # am--include-marker
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/t-various.Po@am__quote@ # am--include-marker
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/t-verify.Po@am__quote@ # am--include-marker
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/t-wkdlookup.Po@am__quote@ # am--include-marker
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/t-wkspublish.Po@am__quote@ # am--include-marker
$(am__depfiles_remade):
@@ -934,9 +1040,15 @@ clean-am: clean-generic clean-libtool clean-local clean-noinstPROGRAMS \
mostlyclean-am
distclean: distclean-am
- -rm -f ./$(DEPDIR)/run-keyformailboxjob.Po
+ -rm -f ./$(DEPDIR)/run-exportjob.Po
+ -rm -f ./$(DEPDIR)/run-importjob.Po
+ -rm -f ./$(DEPDIR)/run-keyformailboxjob.Po
+ -rm -f ./$(DEPDIR)/run-receivekeysjob.Po
+ -rm -f ./$(DEPDIR)/t-addexistingsubkey.Po
+ -rm -f ./$(DEPDIR)/t-changeexpiryjob.Po
-rm -f ./$(DEPDIR)/t-config.Po
-rm -f ./$(DEPDIR)/t-encrypt.Po
+ -rm -f ./$(DEPDIR)/t-import.Po
-rm -f ./$(DEPDIR)/t-keylist.Po
-rm -f ./$(DEPDIR)/t-keylocate.Po
-rm -f ./$(DEPDIR)/t-ownertrust.Po
@@ -946,6 +1058,7 @@ distclean: distclean-am
-rm -f ./$(DEPDIR)/t-trustsignatures.Po
-rm -f ./$(DEPDIR)/t-various.Po
-rm -f ./$(DEPDIR)/t-verify.Po
+ -rm -f ./$(DEPDIR)/t-wkdlookup.Po
-rm -f ./$(DEPDIR)/t-wkspublish.Po
-rm -f Makefile
distclean-am: clean-am distclean-compile distclean-generic \
@@ -992,9 +1105,15 @@ install-ps-am:
installcheck-am:
maintainer-clean: maintainer-clean-am
- -rm -f ./$(DEPDIR)/run-keyformailboxjob.Po
+ -rm -f ./$(DEPDIR)/run-exportjob.Po
+ -rm -f ./$(DEPDIR)/run-importjob.Po
+ -rm -f ./$(DEPDIR)/run-keyformailboxjob.Po
+ -rm -f ./$(DEPDIR)/run-receivekeysjob.Po
+ -rm -f ./$(DEPDIR)/t-addexistingsubkey.Po
+ -rm -f ./$(DEPDIR)/t-changeexpiryjob.Po
-rm -f ./$(DEPDIR)/t-config.Po
-rm -f ./$(DEPDIR)/t-encrypt.Po
+ -rm -f ./$(DEPDIR)/t-import.Po
-rm -f ./$(DEPDIR)/t-keylist.Po
-rm -f ./$(DEPDIR)/t-keylocate.Po
-rm -f ./$(DEPDIR)/t-ownertrust.Po
@@ -1004,6 +1123,7 @@ maintainer-clean: maintainer-clean-am
-rm -f ./$(DEPDIR)/t-trustsignatures.Po
-rm -f ./$(DEPDIR)/t-various.Po
-rm -f ./$(DEPDIR)/t-verify.Po
+ -rm -f ./$(DEPDIR)/t-wkdlookup.Po
-rm -f ./$(DEPDIR)/t-wkspublish.Po
-rm -f Makefile
maintainer-clean-am: distclean-am maintainer-clean-generic
diff --git a/lang/qt/tests/final.test b/lang/qt/tests/final.test
new file mode 100755
index 0000000..f28aaa4
--- /dev/null
+++ b/lang/qt/tests/final.test
@@ -0,0 +1,6 @@
+#!/bin/sh
+
+# stop the dirmngr that may have been started
+gpgconf --kill dirmngr
+
+exit 0
diff --git a/lang/qt/tests/run-exportjob.cpp b/lang/qt/tests/run-exportjob.cpp
new file mode 100644
index 0000000..0f8fd8f
--- /dev/null
+++ b/lang/qt/tests/run-exportjob.cpp
@@ -0,0 +1,119 @@
+/*
+ run-exportjob.cpp
+
+ This file is part of QGpgME's test suite.
+ Copyright (c) 2022 by g10 Code GmbH
+ Software engineering by Ingo Klöcker <dev@ingo-kloecker.de>
+
+ QGpgME is free software; you can redistribute it and/or
+ modify it under the terms of the GNU General Public License,
+ version 2, as published by the Free Software Foundation.
+
+ QGpgME is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
+
+ In addition, as a special exception, the copyright holders give
+ permission to link the code of this program with any edition of
+ the Qt library by Trolltech AS, Norway (or with modified versions
+ of Qt that use the same license as Qt), and distribute linked
+ combinations including the two. You must obey the GNU General
+ Public License in all respects for all of the code used other than
+ Qt. If you modify this file, you may extend this exception to
+ your version of the file, but you are not obligated to do so. If
+ you do not wish to do so, delete this exception statement from
+ your version.
+*/
+
+#ifdef HAVE_CONFIG_H
+ #include "config.h"
+#endif
+
+#include <exportjob.h>
+#include <protocol.h>
+
+#include <context.h>
+
+#include <QCoreApplication>
+
+#include <iostream>
+
+using namespace GpgME;
+using std::cout;
+using std::cerr;
+
+static void showUsageAndExitWithCode(int exitCode)
+{
+ cerr << "Usage: run-exportjob [OPTION]... [PATTERN]...\n"
+ "Options:\n"
+ " --secret export secret keys instead of public keys\n"
+ " --secret-subkey export secret subkeys instead of public keys\n";
+
+ exit(exitCode);
+}
+
+static auto createExportJob(unsigned int mode)
+{
+ if (mode & Context::ExportSecretSubkey) {
+ return QGpgME::openpgp()->secretSubkeyExportJob(/*armor=*/true);
+ } else if (mode & Context::ExportSecret) {
+ return QGpgME::openpgp()->secretKeyExportJob(/*armor=*/true);
+ }
+ return QGpgME::openpgp()->publicKeyExportJob(/*armor=*/true);
+}
+
+int main(int argc, char *argv[])
+{
+ GpgME::initializeLibrary();
+
+ QCoreApplication app{argc, argv};
+
+ unsigned int exportMode = 0;
+
+ auto arguments = app.arguments();
+ if (!arguments.isEmpty()) {
+ arguments.pop_front(); // remove program name
+ }
+ while (!arguments.isEmpty()) {
+ const auto &arg = arguments.front();
+ if (!arg.startsWith(QLatin1String{"--"})) {
+ break;
+ }
+ if (arg == QLatin1String{"--"}) {
+ arguments.pop_front();
+ break;
+ }
+ if (arg == QLatin1String{"--help"}) {
+ showUsageAndExitWithCode(0);
+ } else if (arg == QLatin1String{"--secret"}) {
+ exportMode = Context::ExportSecret;
+ arguments.pop_front();
+ } else if (arg == QLatin1String{"--secret-subkey"}) {
+ exportMode = Context::ExportSecretSubkey;
+ arguments.pop_front();
+ } else {
+ cerr << "Error: Invalid option " << arg.toStdString() << std::endl;
+ showUsageAndExitWithCode(1);
+ }
+ }
+
+ auto job = createExportJob(exportMode);
+ QObject::connect(job, &QGpgME::ExportJob::result,
+ &app, [&app] (const GpgME::Error &err, const QByteArray &keyData, const QString &, const GpgME::Error &) {
+ if (err) {
+ cerr << "The ChangeExpiryJob failed with" << err.asString() << ".";
+ app.exit(1);
+ return;
+ }
+ cout << "Begin Result:\n" << keyData.toStdString() << "End Result:\n";
+ app.exit();
+ });
+ job->start(arguments);
+
+ return app.exec();
+}
diff --git a/lang/qt/tests/run-importjob.cpp b/lang/qt/tests/run-importjob.cpp
new file mode 100644
index 0000000..b1814fa
--- /dev/null
+++ b/lang/qt/tests/run-importjob.cpp
@@ -0,0 +1,99 @@
+/*
+ run-importjob.cpp
+
+ This file is part of QGpgME's test suite.
+ Copyright (c) 2021 by g10 Code GmbH
+ Software engineering by Ingo Klöcker <dev@ingo-kloecker.de>
+
+ QGpgME is free software; you can redistribute it and/or
+ modify it under the terms of the GNU General Public License,
+ version 2, as published by the Free Software Foundation.
+
+ QGpgME is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
+
+ In addition, as a special exception, the copyright holders give
+ permission to link the code of this program with any edition of
+ the Qt library by Trolltech AS, Norway (or with modified versions
+ of Qt that use the same license as Qt), and distribute linked
+ combinations including the two. You must obey the GNU General
+ Public License in all respects for all of the code used other than
+ Qt. If you modify this file, you may extend this exception to
+ your version of the file, but you are not obligated to do so. If
+ you do not wish to do so, delete this exception statement from
+ your version.
+*/
+
+#ifdef HAVE_CONFIG_H
+ #include "config.h"
+#endif
+
+#include <importjob.h>
+#include <importresult.h>
+#include <protocol.h>
+
+#include <QFile>
+#include <QFileInfo>
+
+#include <QDebug>
+
+#include <set>
+#include <sstream>
+
+GpgME::Protocol guessProtocol(const QString &filename)
+{
+ static const std::set<QString> cmsExtensions = {"cer", "crt", "der", "p12", "p7c", "pem", "pfx"};
+ static const std::set<QString> pgpExtensions = {"asc", "gpg", "pgp"};
+
+ const auto extension = QFileInfo{filename}.suffix();
+ if (cmsExtensions.find(extension) != cmsExtensions.end()) {
+ return GpgME::CMS;
+ } else if (pgpExtensions.find(extension) != pgpExtensions.end()) {
+ return GpgME::OpenPGP;
+ }
+ qDebug() << "Unknown file name extension" << extension;
+ return GpgME::UnknownProtocol;
+}
+
+int main(int argc, char **argv)
+{
+ GpgME::initializeLibrary();
+
+ if (argc != 2) {
+ qInfo().noquote() << "Usage:" << argv[0] << "<certificate file>";
+ return 1;
+ }
+ const auto filename = QString::fromLocal8Bit(argv[1]);
+
+ QFile f{filename};
+ if (!f.exists()) {
+ qWarning() << "Error: File not found" << filename;
+ return 1;
+ }
+ const auto protocol = guessProtocol(filename);
+ if (protocol == GpgME::UnknownProtocol) {
+ qWarning() << "Error: Unknown file type";
+ return 1;
+ }
+ if (!f.open(QIODevice::ReadOnly)) {
+ qWarning() << "Error: Failed to open file" << filename << "for reading.";
+ return 1;
+ }
+
+ const auto keyData = f.readAll();
+ auto job = (protocol == GpgME::CMS ? QGpgME::smime() : QGpgME::openpgp())->importJob();
+ const auto result = job->exec(keyData);
+ qDebug() << "Result error:" << result.error().asString();
+ std::ostringstream ostr;
+ ostr << result;
+ for (const auto &line : QString::fromStdString(ostr.str()).split('\n')) {
+ qDebug().noquote() << line;
+ }
+ return 0;
+}
diff --git a/lang/qt/tests/run-receivekeysjob.cpp b/lang/qt/tests/run-receivekeysjob.cpp
new file mode 100644
index 0000000..0dc1575
--- /dev/null
+++ b/lang/qt/tests/run-receivekeysjob.cpp
@@ -0,0 +1,65 @@
+/*
+ run-receivekeysjob.cpp
+
+ This file is part of QGpgME's test suite.
+ Copyright (c) 2022 by g10 Code GmbH
+ Software engineering by Ingo Klöcker <dev@ingo-kloecker.de>
+
+ QGpgME is free software; you can redistribute it and/or
+ modify it under the terms of the GNU General Public License,
+ version 2, as published by the Free Software Foundation.
+
+ QGpgME is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
+
+ In addition, as a special exception, the copyright holders give
+ permission to link the code of this program with any edition of
+ the Qt library by Trolltech AS, Norway (or with modified versions
+ of Qt that use the same license as Qt), and distribute linked
+ combinations including the two. You must obey the GNU General
+ Public License in all respects for all of the code used other than
+ Qt. If you modify this file, you may extend this exception to
+ your version of the file, but you are not obligated to do so. If
+ you do not wish to do so, delete this exception statement from
+ your version.
+*/
+
+#ifdef HAVE_CONFIG_H
+ #include "config.h"
+#endif
+
+#include <importresult.h>
+#include <protocol.h>
+#include <receivekeysjob.h>
+
+#include <QCoreApplication>
+#include <QDebug>
+
+#include <iostream>
+
+int main(int argc, char **argv)
+{
+ GpgME::initializeLibrary();
+
+ if (argc < 2) {
+ std::cerr << "Usage: " << argv[0] << " KEYID..." << std::endl;
+ return 1;
+ }
+
+ QCoreApplication app(argc, argv);
+ const QStringList keyIds = qApp->arguments().mid(1);
+
+ auto job = QGpgME::openpgp()->receiveKeysJob();
+ const auto result = job->exec(keyIds);
+
+ std::cout << "Result: " << result.error().asString() << std::endl;
+ std::cout << "Details:\n" << result << std::endl;
+
+ return 0;
+}
diff --git a/lang/qt/tests/t-addexistingsubkey.cpp b/lang/qt/tests/t-addexistingsubkey.cpp
new file mode 100644
index 0000000..589c90b
--- /dev/null
+++ b/lang/qt/tests/t-addexistingsubkey.cpp
@@ -0,0 +1,260 @@
+/* t-addexistingsubkey.cpp
+
+ This file is part of qgpgme, the Qt API binding for gpgme
+ Copyright (c) 2022 g10 Code GmbH
+ Software engineering by Ingo Klöcker <dev@ingo-kloecker.de>
+
+ QGpgME is free software; you can redistribute it and/or
+ modify it under the terms of the GNU General Public License as
+ published by the Free Software Foundation; either version 2 of the
+ License, or (at your option) any later version.
+
+ QGpgME is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
+
+ In addition, as a special exception, the copyright holders give
+ permission to link the code of this program with any edition of
+ the Qt library by Trolltech AS, Norway (or with modified versions
+ of Qt that use the same license as Qt), and distribute linked
+ combinations including the two. You must obey the GNU General
+ Public License in all respects for all of the code used other than
+ Qt. If you modify this file, you may extend this exception to
+ your version of the file, but you are not obligated to do so. If
+ you do not wish to do so, delete this exception statement from
+ your version.
+*/
+#ifdef HAVE_CONFIG_H
+ #include "config.h"
+#endif
+
+#include "t-support.h"
+
+#include "addexistingsubkeyjob.h"
+#include "protocol.h"
+
+#include <QSignalSpy>
+#include <QTest>
+
+#include "context.h"
+#include "data.h"
+#include "engineinfo.h"
+
+#include <algorithm>
+
+using namespace QGpgME;
+using namespace GpgME;
+
+static const char *requiredVersion = "2.3.5";
+
+/* Test keys
+ sec# ed25519 2022-01-13 [SC]
+ 1CB8C6A0317AA83F44FE009932392C82B814C8E0
+ uid [ unknown] source-key@example.net
+ ssb cv25519 2022-01-13 [E]
+ ssb cv25519 2022-01-13 [E] [expires: 2100-01-01]
+
+ sec ed25519 2022-01-13 [SC]
+ C3C87F0A3920B01F9E4450EA2B79F21D4DD10BFC
+ uid [ unknown] target-key@example.net
+ ssb cv25519 2022-01-13 [E]
+ * generated with
+export GNUPGHOME=$(mktemp -d)
+gpg -K
+gpg --batch --pinentry-mode loopback --passphrase abc --quick-gen-key source-key@example.net default default never
+fpr=$(gpg -k --with-colons source-key@example.net | grep ^fpr | head -1 | cut -d ':' -f 10)
+gpg --batch --pinentry-mode loopback --passphrase abc --quick-add-key ${fpr} default default 21000101T120000
+gpg --batch --pinentry-mode loopback --passphrase abc --quick-gen-key target-key@example.net default default never
+gpg -K
+gpg --export-secret-subkeys --armor --batch --pinentry-mode loopback --passphrase abc --comment source-key@example.net source-key@example.net | sed 's/\(.*\)/ "\1\\n"/'
+gpg --export-secret-keys --armor --batch --pinentry-mode loopback --passphrase abc --comment target-key@example.net target-key@example.net | sed 's/\(.*\)/ "\1\\n"/'
+#rm -rf ${GNUPGHOME}
+unset GNUPGHOME
+*/
+static const char *testKeyData =
+ "-----BEGIN PGP PRIVATE KEY BLOCK-----\n"
+ "Comment: source-key@example.net\n"
+ "\n"
+ "lDsEYd/ujBYJKwYBBAHaRw8BAQdAwiZPINTcrpgmu6ZWSaPZlcRSd4nDuofVMhe7\n"
+ "c2XrFyT/AGUAR05VAbQWc291cmNlLWtleUBleGFtcGxlLm5ldIiUBBMWCgA8FiEE\n"
+ "HLjGoDF6qD9E/gCZMjksgrgUyOAFAmHf7owCGwMFCwkIBwIDIgIBBhUKCQgLAgQW\n"
+ "AgMBAh4HAheAAAoJEDI5LIK4FMjgupIA/Au2YEAT9dYdJd0eJCJerG5YAeoB+uBs\n"
+ "mBkgr6xXE0bIAP43b6u1Jtvf/Wm3BhRbLd5Tg67Ba4CIZ8ZLGng73FBoBpyLBGHf\n"
+ "7owSCisGAQQBl1UBBQEBB0Cpg8Qof/WShxROZZtmPnw24vTk0R8nIAF1CZJ0bG/C\n"
+ "SwMBCAf+BwMCtzxziVxQEor8w/VVzHp4/hVSCUyrpiX7Djf04cIMs2bFPduZLgxb\n"
+ "c1SXhlgiqU0YBNntbGGNdKjTP6FMbYWq1+NwQm6ZXtC76LPG7syM94h4BBgWCgAg\n"
+ "FiEEHLjGoDF6qD9E/gCZMjksgrgUyOAFAmHf7owCGwwACgkQMjksgrgUyOCI0wEA\n"
+ "+f56fkvDDUwMOMw7n4+GKpfJXpWhVL08ttccbBOa/9IA/2HYA/78ZaD8E5EyqAEK\n"
+ "Aj9Au+2oJu9V5qo92QEoqwYHnIsEYd/vgxIKKwYBBAGXVQEFAQEHQBa9FxJkm/9D\n"
+ "xABildkaYMrbJbu8BPk6uv9V8aLmv9FnAwEIB/4HAwIPhcbN8s6OzPz8/g78TrCh\n"
+ "xqQb2kygCEj+OQ4/XXU3lus2b5xS5h44LGt99Wisqx+wVPDXmPDJOaxjhHXDmJxd\n"
+ "/LplIEhykojSm3uUDxERiH4EGBYKACYWIQQcuMagMXqoP0T+AJkyOSyCuBTI4AUC\n"
+ "Yd/vgwIbDAUJkqcQPQAKCRAyOSyCuBTI4IUjAP9BTfOD+jy6lLmzNO9pquRSAxi/\n"
+ "PQuglGtpS0LQEJMEOwD+PFnsMe2EtQ+WVSDBeB7O0m61EXeY+RhpuhNtsNXVuwc=\n"
+ "=wIPU\n"
+ "-----END PGP PRIVATE KEY BLOCK-----\n"
+ "-----BEGIN PGP PRIVATE KEY BLOCK-----\n"
+ "Comment: target-key@example.net\n"
+ "\n"
+ "lIYEYd/v/RYJKwYBBAHaRw8BAQdAKoILWXG3yaLb2EniNKQLUjwsrvy5vgAN299J\n"
+ "W5cFbrz+BwMC/uKbCq3sK5H8QVtEQ/IxGmjWNBpy6c8EDlOG4APi4o4VE+bEYD8w\n"
+ "J3Kk/lzSm6ZT5vC6DDASks797omjXD+J7zZ0vtTPvheYi/nsVz2UebQWdGFyZ2V0\n"
+ "LWtleUBleGFtcGxlLm5ldIiUBBMWCgA8FiEEw8h/CjkgsB+eRFDqK3nyHU3RC/wF\n"
+ "AmHf7/0CGwMFCwkIBwIDIgIBBhUKCQgLAgQWAgMBAh4HAheAAAoJECt58h1N0Qv8\n"
+ "rXcBAPxnkXqpp4IY3iTKV5XAdo7Uys7U/joUD73rj2XEvgI1AQDhKK4PLxPhf3ki\n"
+ "FKU0RA7itxzOH+F8bQ5BdYS49jDPCpyLBGHf7/0SCisGAQQBl1UBBQEBB0Dq9rwA\n"
+ "hAA2UFJShFsLFp7+g4uhWDfuDa3VjeIQRM+9QgMBCAf+BwMCMfCTl0LNqsn836t5\n"
+ "f2ZHBuMcNs4JWYmdLAIVaewEHq7zhOsX3iB+/yxwu9g2mXc4XUJ1iQzXLOYwgGov\n"
+ "8jIovrr01hDkSg4rvM9JKMWdd4h4BBgWCgAgFiEEw8h/CjkgsB+eRFDqK3nyHU3R\n"
+ "C/wFAmHf7/0CGwwACgkQK3nyHU3RC/xyfAEAqnMdSv6FTAwAWrYvJqJtSVoEhjMn\n"
+ "3c2qMsu34Bk86/MBAKHbLFmdyePvHaxKeO8CkQDoJzK8rYzw3RAmq/5JsQkL\n"
+ "=rOVf\n"
+ "-----END PGP PRIVATE KEY BLOCK-----\n";
+
+class AddExistingSubkeyJobTest : public QGpgMETest
+{
+ Q_OBJECT
+
+private Q_SLOTS:
+
+ void initTestCase()
+ {
+ QGpgMETest::initTestCase();
+
+ // set up the test fixture for this test
+ qputenv("GNUPGHOME", mGnupgHomeTestFixture.path().toUtf8());
+ QVERIFY(importSecretKeys(testKeyData, 2));
+ }
+
+ void init()
+ {
+ if (GpgME::engineInfo(GpgME::GpgEngine).engineVersion() < requiredVersion) {
+ QSKIP("gpg does not yet support adding an existing subkey to another key via the command API");
+ }
+
+ // set up a copy of the test fixture for each test function
+ mGnupgHomeTestCopy.reset(new QTemporaryDir{});
+ QVERIFY(copyKeyrings(mGnupgHomeTestFixture.path(), mGnupgHomeTestCopy->path()));
+ qputenv("GNUPGHOME", mGnupgHomeTestCopy->path().toUtf8());
+ }
+
+ void testAddExistingSubkeyAsync()
+ {
+ // Get the key the subkey should be added to
+ auto key = getTestKey("target-key@example.net");
+ QVERIFY(!key.isNull());
+
+ // Get the key with the subkey to add
+ auto sourceKey = getTestKey("source-key@example.net", 3);
+ QVERIFY(!sourceKey.isNull());
+
+ auto job = std::unique_ptr<AddExistingSubkeyJob>{openpgp()->addExistingSubkeyJob()};
+ hookUpPassphraseProvider(job.get());
+
+ Error result;
+ connect(job.get(), &AddExistingSubkeyJob::result,
+ job.get(), [this, &result](const Error &result_) {
+ result = result_;
+ Q_EMIT asyncDone();
+ });
+ QVERIFY(!job->start(key, sourceKey.subkey(1)));
+ job.release(); // after the job has been started it's on its own
+
+ QSignalSpy spy (this, SIGNAL(asyncDone()));
+ QVERIFY(spy.wait(QSIGNALSPY_TIMEOUT));
+
+ QVERIFY(result.code() == GPG_ERR_NO_ERROR);
+ key.update();
+ QCOMPARE(key.numSubkeys(), 3u);
+ }
+
+ void testAddExistingSubkeySync()
+ {
+ // Get the key the subkey should be added to
+ auto key = getTestKey("target-key@example.net");
+ QVERIFY(!key.isNull());
+
+ // Get the key with the subkey to add
+ auto sourceKey = getTestKey("source-key@example.net", 3);
+ QVERIFY(!sourceKey.isNull());
+ auto sourceSubkey = sourceKey.subkey(1);
+ QVERIFY(sourceSubkey.expirationTime() == 0);
+
+ auto job = std::unique_ptr<AddExistingSubkeyJob>{openpgp()->addExistingSubkeyJob()};
+ hookUpPassphraseProvider(job.get());
+
+ const auto result = job->exec(key, sourceSubkey);
+
+ QVERIFY(result.code() == GPG_ERR_NO_ERROR);
+ key.update();
+ QCOMPARE(key.numSubkeys(), 3u);
+ QCOMPARE(key.subkey(2).expirationTime(), 0);
+ }
+
+ void testAddExistingSubkeyWithExpiration()
+ {
+ // Get the key the subkey should be added to
+ auto key = getTestKey("target-key@example.net");
+ QVERIFY(!key.isNull());
+
+ // Get the key with the subkey to add
+ auto sourceKey = getTestKey("source-key@example.net", 3);
+ QVERIFY(!sourceKey.isNull());
+ auto sourceSubkey = sourceKey.subkey(2);
+ QVERIFY(sourceSubkey.expirationTime() != 0);
+
+ auto job = std::unique_ptr<AddExistingSubkeyJob>{openpgp()->addExistingSubkeyJob()};
+ hookUpPassphraseProvider(job.get());
+
+ const auto result = job->exec(key, sourceSubkey);
+
+ QVERIFY(result.code() == GPG_ERR_NO_ERROR);
+ key.update();
+ QCOMPARE(key.numSubkeys(), 3u);
+
+ // allow 1 second different expiration because gpg calculates with
+ // expiration as difference to current time and takes current time
+ // several times
+ const auto allowedDeltaTSeconds = 1;
+ const auto expectedExpirationRange = std::make_pair(
+ sourceSubkey.expirationTime() - allowedDeltaTSeconds,
+ sourceSubkey.expirationTime() + allowedDeltaTSeconds);
+ const auto actualExpiration = key.subkey(2).expirationTime();
+ QVERIFY2(actualExpiration >= expectedExpirationRange.first,
+ ("actual: " + std::to_string(actualExpiration) +
+ "; expected: " + std::to_string(expectedExpirationRange.first)).c_str());
+ QVERIFY2(actualExpiration <= expectedExpirationRange.second,
+ ("actual: " + std::to_string(actualExpiration) +
+ "; expected: " + std::to_string(expectedExpirationRange.second)).c_str());
+ }
+
+private:
+ Key getTestKey(const char *pattern, unsigned int expectedSubkeys = 2)
+ {
+ auto ctx = Context::create(OpenPGP);
+ VERIFY_OR_OBJECT(ctx);
+
+ Error err;
+ auto key = ctx->key(pattern, err, /*secret=*/true);
+ VERIFY_OR_OBJECT(!err);
+ VERIFY_OR_OBJECT(!key.isNull());
+ COMPARE_OR_OBJECT(key.numSubkeys(), expectedSubkeys);
+ for (unsigned int i = 0; i < key.numSubkeys(); ++i) {
+ VERIFY_OR_OBJECT(!key.subkey(i).isNull());
+ }
+ return key;
+ }
+
+private:
+ QTemporaryDir mGnupgHomeTestFixture;
+ std::unique_ptr<QTemporaryDir> mGnupgHomeTestCopy;
+};
+
+QTEST_MAIN(AddExistingSubkeyJobTest)
+
+#include "t-addexistingsubkey.moc"
diff --git a/lang/qt/tests/t-changeexpiryjob.cpp b/lang/qt/tests/t-changeexpiryjob.cpp
new file mode 100644
index 0000000..090002f
--- /dev/null
+++ b/lang/qt/tests/t-changeexpiryjob.cpp
@@ -0,0 +1,396 @@
+/* t-changeexpiryjob.cpp
+
+ This file is part of qgpgme, the Qt API binding for gpgme
+ Copyright (c) 2021 g10 Code GmbH
+ Software engineering by Ingo Klöcker <dev@ingo-kloecker.de>
+
+ QGpgME is free software; you can redistribute it and/or
+ modify it under the terms of the GNU General Public License as
+ published by the Free Software Foundation; either version 2 of the
+ License, or (at your option) any later version.
+
+ QGpgME is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
+
+ In addition, as a special exception, the copyright holders give
+ permission to link the code of this program with any edition of
+ the Qt library by Trolltech AS, Norway (or with modified versions
+ of Qt that use the same license as Qt), and distribute linked
+ combinations including the two. You must obey the GNU General
+ Public License in all respects for all of the code used other than
+ Qt. If you modify this file, you may extend this exception to
+ your version of the file, but you are not obligated to do so. If
+ you do not wish to do so, delete this exception statement from
+ your version.
+*/
+
+#ifdef HAVE_CONFIG_H
+ #include "config.h"
+#endif
+
+#include "t-support.h"
+
+#include "changeexpiryjob.h"
+#include "context.h"
+#include "engineinfo.h"
+#include "protocol.h"
+
+#include <QSignalSpy>
+#include <QTemporaryDir>
+#include <QTest>
+
+using namespace QGpgME;
+using namespace GpgME;
+
+class TestChangeExpiryJob: public QGpgMETest
+{
+ Q_OBJECT
+
+private Q_SLOTS:
+ void test_change_expiration_default_without_subkeys()
+ {
+ Error err;
+
+ if (!loopbackSupported()) {
+ return;
+ }
+
+ auto ctx = Context::create(OpenPGP);
+ QVERIFY(ctx);
+
+ // Get the key (alfa@example.net)
+ auto key = ctx->key("A0FF4590BB6122EDEF6E3C542D727CC768697734", err, true);
+ QVERIFY(!err);
+ QVERIFY(!key.isNull());
+ QVERIFY(!key.subkey(0).isNull());
+ QVERIFY(!key.subkey(1).isNull());
+ const auto subkeyExpiration = key.subkey(1).expirationTime();
+
+ {
+ // Create the job
+ auto job = std::unique_ptr<ChangeExpiryJob>{openpgp()->changeExpiryJob()};
+ QVERIFY(job);
+ hookUpPassphraseProvider(job.get());
+
+ // Use defaults of job
+
+ connect(job.get(), &ChangeExpiryJob::result,
+ this, [this] (const GpgME::Error &err2, const QString &, const GpgME::Error &) {
+ Q_EMIT asyncDone();
+ if (err2) {
+ QFAIL(qPrintable(QString("The ChangeExpiryJob failed with '%1'.").arg(err2.asString())));
+ }
+ });
+
+ const auto newExpirationDate = QDateTime::currentDateTime().addDays(1);
+ job->start(key, newExpirationDate);
+ QSignalSpy spy (this, SIGNAL(asyncDone()));
+ QVERIFY(spy.wait(QSIGNALSPY_TIMEOUT));
+
+ // At this point the expiration date should have been changed.
+ key.update();
+
+ // allow a few seconds earlier expiration because job calculates "seconds from now" passed to gpg after it was started
+ const auto expectedExpirationRange = std::make_pair(
+ newExpirationDate.toSecsSinceEpoch() - 10,
+ QDateTime::currentDateTime().addDays(1).toSecsSinceEpoch());
+ {
+ const auto actualExpiration = key.subkey(0).expirationTime();
+ QVERIFY2(actualExpiration >= expectedExpirationRange.first,
+ ("actual: " + std::to_string(actualExpiration) +
+ "; expected: " + std::to_string(expectedExpirationRange.first)).c_str());
+ QVERIFY2(actualExpiration <= expectedExpirationRange.second,
+ ("actual: " + std::to_string(actualExpiration) +
+ "; expected: " + std::to_string(expectedExpirationRange.second)).c_str());
+ }
+ {
+ const auto actualExpiration = key.subkey(1).expirationTime();
+ QCOMPARE(actualExpiration, subkeyExpiration); // unchanged
+ }
+ }
+ }
+
+ void test_change_expiration_default_with_subkeys()
+ {
+ Error err;
+
+ if (!loopbackSupported()) {
+ return;
+ }
+
+ auto ctx = Context::create(OpenPGP);
+ QVERIFY(ctx);
+
+ // Get the key (alfa@example.net)
+ auto key = ctx->key("A0FF4590BB6122EDEF6E3C542D727CC768697734", err, true);
+ QVERIFY(!err);
+ QVERIFY(!key.isNull());
+ QVERIFY(!key.subkey(0).isNull());
+ QVERIFY(!key.subkey(1).isNull());
+ const auto primaryKeyExpiration = key.subkey(0).expirationTime();
+
+ {
+ // Create the job
+ auto job = std::unique_ptr<ChangeExpiryJob>{openpgp()->changeExpiryJob()};
+ QVERIFY(job);
+ hookUpPassphraseProvider(job.get());
+
+ // Use defaults of job
+
+ connect(job.get(), &ChangeExpiryJob::result,
+ this, [this] (const GpgME::Error &err2, const QString &, const GpgME::Error &) {
+ Q_EMIT asyncDone();
+ if (err2) {
+ QFAIL(qPrintable(QString("The ChangeExpiryJob failed with '%1'.").arg(err2.asString())));
+ }
+ });
+
+ const auto newExpirationDate = QDateTime::currentDateTime().addDays(2);
+ job->start(key, newExpirationDate, {key.subkey(1)});
+ QSignalSpy spy (this, SIGNAL(asyncDone()));
+ QVERIFY(spy.wait(QSIGNALSPY_TIMEOUT));
+
+ // At this point the expiration date should have been changed.
+ key.update();
+
+ // allow a few seconds earlier expiration because job calculates "seconds from now" passed to gpg after it was started
+ const auto expectedExpirationRange = std::make_pair(
+ newExpirationDate.toSecsSinceEpoch() - 10,
+ QDateTime::currentDateTime().addDays(2).toSecsSinceEpoch());
+ {
+ const auto actualExpiration = key.subkey(0).expirationTime();
+ QCOMPARE(actualExpiration, primaryKeyExpiration); // unchanged
+ }
+ {
+ const auto actualExpiration = key.subkey(1).expirationTime();
+ QVERIFY2(actualExpiration >= expectedExpirationRange.first,
+ ("actual: " + std::to_string(actualExpiration) +
+ "; expected: " + std::to_string(expectedExpirationRange.first)).c_str());
+ QVERIFY2(actualExpiration <= expectedExpirationRange.second,
+ ("actual: " + std::to_string(actualExpiration) +
+ "; expected: " + std::to_string(expectedExpirationRange.second)).c_str());
+ }
+ }
+ }
+
+ void test_change_expiration_update_primary_key_without_subkeys()
+ {
+ Error err;
+
+ if (!loopbackSupported()) {
+ return;
+ }
+
+ auto ctx = Context::create(OpenPGP);
+ QVERIFY(ctx);
+
+ // Get the key (alfa@example.net)
+ auto key = ctx->key("A0FF4590BB6122EDEF6E3C542D727CC768697734", err, true);
+ QVERIFY(!err);
+ QVERIFY(!key.isNull());
+ QVERIFY(!key.subkey(0).isNull());
+ QVERIFY(!key.subkey(1).isNull());
+ const auto subkeyExpiration = key.subkey(1).expirationTime();
+
+ {
+ // Create the job
+ auto job = std::unique_ptr<ChangeExpiryJob>{openpgp()->changeExpiryJob()};
+ QVERIFY(job);
+ hookUpPassphraseProvider(job.get());
+
+ // Set up the job
+ job->setOptions(ChangeExpiryJob::UpdatePrimaryKey);
+
+ connect(job.get(), &ChangeExpiryJob::result,
+ this, [this] (const GpgME::Error &err2, const QString &, const GpgME::Error &) {
+ Q_EMIT asyncDone();
+ if (err2) {
+ QFAIL(qPrintable(QString("The ChangeExpiryJob failed with '%1'.").arg(err2.asString())));
+ }
+ });
+
+ const auto newExpirationDate = QDateTime::currentDateTime().addDays(3);
+ job->start(key, newExpirationDate, {});
+ QSignalSpy spy (this, SIGNAL(asyncDone()));
+ QVERIFY(spy.wait(QSIGNALSPY_TIMEOUT));
+
+ // At this point the expiration date should have been changed.
+ key.update();
+
+ // allow a few seconds earlier expiration because job calculates "seconds from now" passed to gpg after it was started
+ const auto expectedExpirationRange = std::make_pair(
+ newExpirationDate.toSecsSinceEpoch() - 10,
+ QDateTime::currentDateTime().addDays(3).toSecsSinceEpoch());
+ {
+ const auto actualExpiration = key.subkey(0).expirationTime();
+ QVERIFY2(actualExpiration >= expectedExpirationRange.first,
+ ("actual: " + std::to_string(actualExpiration) +
+ "; expected: " + std::to_string(expectedExpirationRange.first)).c_str());
+ QVERIFY2(actualExpiration <= expectedExpirationRange.second,
+ ("actual: " + std::to_string(actualExpiration) +
+ "; expected: " + std::to_string(expectedExpirationRange.second)).c_str());
+ }
+ {
+ const auto actualExpiration = key.subkey(1).expirationTime();
+ QCOMPARE(actualExpiration, subkeyExpiration); // unchanged
+ }
+ }
+ }
+
+ void test_change_expiration_update_primary_key_with_subkeys()
+ {
+ Error err;
+
+ if (!loopbackSupported()) {
+ return;
+ }
+
+ auto ctx = Context::create(OpenPGP);
+ QVERIFY(ctx);
+
+ // Get the key (alfa@example.net)
+ auto key = ctx->key("A0FF4590BB6122EDEF6E3C542D727CC768697734", err, true);
+ QVERIFY(!err);
+ QVERIFY(!key.isNull());
+ QVERIFY(!key.subkey(0).isNull());
+ QVERIFY(!key.subkey(1).isNull());
+
+ {
+ // Create the job
+ auto job = std::unique_ptr<ChangeExpiryJob>{openpgp()->changeExpiryJob()};
+ QVERIFY(job);
+ hookUpPassphraseProvider(job.get());
+
+ // Set up the job
+ job->setOptions(ChangeExpiryJob::UpdatePrimaryKey);
+
+ connect(job.get(), &ChangeExpiryJob::result,
+ this, [this] (const GpgME::Error &err2, const QString &, const GpgME::Error &) {
+ Q_EMIT asyncDone();
+ if (err2) {
+ QFAIL(qPrintable(QString("The ChangeExpiryJob failed with '%1'.").arg(err2.asString())));
+ }
+ });
+
+ const auto newExpirationDate = QDateTime::currentDateTime().addDays(4);
+ job->start(key, newExpirationDate, {key.subkey(1)});
+ QSignalSpy spy (this, SIGNAL(asyncDone()));
+ QVERIFY(spy.wait(QSIGNALSPY_TIMEOUT));
+
+ // At this point the expiration date should have been changed.
+ key.update();
+
+ // allow a few seconds earlier expiration because job calculates "seconds from now" passed to gpg after it was started
+ const auto expectedExpirationRange = std::make_pair(
+ newExpirationDate.toSecsSinceEpoch() - 10,
+ QDateTime::currentDateTime().addDays(4).toSecsSinceEpoch());
+ {
+ const auto actualExpiration = key.subkey(0).expirationTime();
+ QVERIFY2(actualExpiration >= expectedExpirationRange.first,
+ ("actual: " + std::to_string(actualExpiration) +
+ "; expected: " + std::to_string(expectedExpirationRange.first)).c_str());
+ QVERIFY2(actualExpiration <= expectedExpirationRange.second,
+ ("actual: " + std::to_string(actualExpiration) +
+ "; expected: " + std::to_string(expectedExpirationRange.second)).c_str());
+ }
+ {
+ const auto actualExpiration = key.subkey(1).expirationTime();
+ QVERIFY2(actualExpiration >= expectedExpirationRange.first,
+ ("actual: " + std::to_string(actualExpiration) +
+ "; expected: " + std::to_string(expectedExpirationRange.first)).c_str());
+ QVERIFY2(actualExpiration <= expectedExpirationRange.second,
+ ("actual: " + std::to_string(actualExpiration) +
+ "; expected: " + std::to_string(expectedExpirationRange.second)).c_str());
+ }
+ }
+ }
+
+ void test_change_expiration_update_primary_key_and_all_subkeys()
+ {
+ Error err;
+
+ if (!loopbackSupported()) {
+ return;
+ }
+
+ auto ctx = Context::create(OpenPGP);
+ QVERIFY(ctx);
+
+ // Get the key (alfa@example.net)
+ auto key = ctx->key("A0FF4590BB6122EDEF6E3C542D727CC768697734", err, true);
+ QVERIFY(!err);
+ QVERIFY(!key.isNull());
+ QVERIFY(!key.subkey(0).isNull());
+ QVERIFY(!key.subkey(1).isNull());
+
+ {
+ // Create the job
+ auto job = std::unique_ptr<ChangeExpiryJob>{openpgp()->changeExpiryJob()};
+ QVERIFY(job);
+ hookUpPassphraseProvider(job.get());
+
+ // Set up the job
+ job->setOptions(ChangeExpiryJob::UpdatePrimaryKey | ChangeExpiryJob::UpdateAllSubkeys);
+
+ connect(job.get(), &ChangeExpiryJob::result,
+ this, [this] (const GpgME::Error &err2, const QString &, const GpgME::Error &) {
+ Q_EMIT asyncDone();
+ if (err2) {
+ QFAIL(qPrintable(QString("The ChangeExpiryJob failed with '%1'.").arg(err2.asString())));
+ }
+ });
+
+ const auto newExpirationDate = QDateTime::currentDateTime().addDays(5);
+ job->start(key, newExpirationDate);
+ QSignalSpy spy (this, SIGNAL(asyncDone()));
+ QVERIFY(spy.wait(QSIGNALSPY_TIMEOUT));
+
+ // At this point the expiration date should have been changed.
+ key.update();
+
+ // allow a few seconds earlier expiration because job calculates "seconds from now" passed to gpg after it was started
+ const auto expectedExpirationRange = std::make_pair(
+ newExpirationDate.toSecsSinceEpoch() - 10,
+ QDateTime::currentDateTime().addDays(5).toSecsSinceEpoch());
+ {
+ const auto actualExpiration = key.subkey(0).expirationTime();
+ QVERIFY2(actualExpiration >= expectedExpirationRange.first,
+ ("actual: " + std::to_string(actualExpiration) +
+ "; expected: " + std::to_string(expectedExpirationRange.first)).c_str());
+ QVERIFY2(actualExpiration <= expectedExpirationRange.second,
+ ("actual: " + std::to_string(actualExpiration) +
+ "; expected: " + std::to_string(expectedExpirationRange.second)).c_str());
+ }
+ {
+ const auto actualExpiration = key.subkey(1).expirationTime();
+ QVERIFY2(actualExpiration >= expectedExpirationRange.first,
+ ("actual: " + std::to_string(actualExpiration) +
+ "; expected: " + std::to_string(expectedExpirationRange.first)).c_str());
+ QVERIFY2(actualExpiration <= expectedExpirationRange.second,
+ ("actual: " + std::to_string(actualExpiration) +
+ "; expected: " + std::to_string(expectedExpirationRange.second)).c_str());
+ }
+ }
+ }
+
+ void initTestCase()
+ {
+ QGpgMETest::initTestCase();
+ const QString gpgHome = qgetenv("GNUPGHOME");
+ QVERIFY(copyKeyrings(gpgHome, mDir.path()));
+ qputenv("GNUPGHOME", mDir.path().toUtf8());
+ }
+
+private:
+ QTemporaryDir mDir;
+};
+
+QTEST_MAIN(TestChangeExpiryJob)
+
+#include "t-changeexpiryjob.moc"
diff --git a/lang/qt/tests/t-config.cpp b/lang/qt/tests/t-config.cpp
index 9ec9566..b84dbfd 100644
--- a/lang/qt/tests/t-config.cpp
+++ b/lang/qt/tests/t-config.cpp
@@ -57,27 +57,24 @@ private Q_SLOTS:
// be unsupported in older versions.
return;
}
- // First set compliance to de-vs
auto conf = cryptoConfig();
QVERIFY(conf);
- auto entry = conf->entry(QStringLiteral("gpg"),
- QStringLiteral("Configuration"),
- QStringLiteral("compliance"));
+ auto entry = conf->entry(QStringLiteral("gpg"), QStringLiteral("compliance"));
QVERIFY(entry);
+ const auto defaultValue = entry->defaultValue().toString();
+ QCOMPARE(defaultValue, QStringLiteral("gnupg"));
+
entry->setStringValue("de-vs");
conf->sync(true);
conf->clear();
- entry = conf->entry(QStringLiteral("gpg"),
- QStringLiteral("Configuration"),
- QStringLiteral("compliance"));
+ entry = conf->entry(QStringLiteral("gpg"), QStringLiteral("compliance"));
QCOMPARE(entry->stringValue(), QStringLiteral("de-vs"));
+
entry->resetToDefault();
conf->sync(true);
conf->clear();
- entry = conf->entry(QStringLiteral("gpg"),
- QStringLiteral("Configuration"),
- QStringLiteral("compliance"));
- QCOMPARE(entry->stringValue(), QStringLiteral("gnupg"));
+ entry = conf->entry(QStringLiteral("gpg"), QStringLiteral("compliance"));
+ QCOMPARE(entry->stringValue(), defaultValue);
}
void initTestCase()
diff --git a/lang/qt/tests/t-encrypt.cpp b/lang/qt/tests/t-encrypt.cpp
index 9ad1033..6a4c68e 100644
--- a/lang/qt/tests/t-encrypt.cpp
+++ b/lang/qt/tests/t-encrypt.cpp
@@ -63,9 +63,6 @@ class EncryptionTest : public QGpgMETest
{
Q_OBJECT
-Q_SIGNALS:
- void asyncDone();
-
private Q_SLOTS:
void testSimpleEncryptDecrypt()
@@ -92,10 +89,7 @@ private Q_SLOTS:
return;
}
auto decJob = openpgp()->decryptJob();
- auto ctx = Job::context(decJob);
- TestPassphraseProvider provider;
- ctx->setPassphraseProvider(&provider);
- ctx->setPinentryMode(Context::PinentryLoopback);
+ hookUpPassphraseProvider(decJob);
QByteArray plainText;
auto decResult = decJob->exec(cipherText, plainText);
QVERIFY(!decResult.error());
@@ -163,10 +157,8 @@ private Q_SLOTS:
return;
}
auto job = openpgp()->encryptJob();
+ hookUpPassphraseProvider(job);
auto ctx = Job::context(job);
- TestPassphraseProvider provider;
- ctx->setPassphraseProvider(&provider);
- ctx->setPinentryMode(Context::PinentryLoopback);
ctx->setArmor(true);
ctx->setTextMode(true);
QByteArray cipherText;
@@ -179,9 +171,7 @@ private Q_SLOTS:
killAgent(mDir.path());
auto decJob = openpgp()->decryptJob();
- auto ctx2 = Job::context(decJob);
- ctx2->setPassphraseProvider(&provider);
- ctx2->setPinentryMode(Context::PinentryLoopback);
+ hookUpPassphraseProvider(decJob);
QByteArray plainText;
auto decResult = decJob->exec(cipherText, plainText);
QVERIFY(!result.error());
@@ -204,13 +194,9 @@ private Q_SLOTS:
delete listjob;
auto job = openpgp()->signEncryptJob(/*ASCII Armor */true, /* Textmode */ true);
-
- auto encSignCtx = Job::context(job);
- TestPassphraseProvider provider1;
- encSignCtx->setPassphraseProvider(&provider1);
- encSignCtx->setPinentryMode(Context::PinentryLoopback);
-
QVERIFY(job);
+ hookUpPassphraseProvider(job);
+
QByteArray cipherText;
auto result = job->exec(keys, keys, QStringLiteral("Hello World").toUtf8(), Context::AlwaysTrust, cipherText);
delete job;
@@ -225,10 +211,8 @@ private Q_SLOTS:
}
auto decJob = openpgp()->decryptJob();
+ hookUpPassphraseProvider(decJob);
auto ctx = Job::context(decJob);
- TestPassphraseProvider provider;
- ctx->setPassphraseProvider(&provider);
- ctx->setPinentryMode(Context::PinentryLoopback);
ctx->setDecryptionFlags(Context::DecryptUnwrap);
QByteArray plainText;
@@ -269,9 +253,8 @@ private:
delete listjob;
auto job = openpgp()->encryptJob();
+ hookUpPassphraseProvider(job);
auto ctx = Job::context(job);
- ctx->setPassphraseProvider(new TestPassphraseProvider);
- ctx->setPinentryMode(Context::PinentryLoopback);
ctx->setArmor(true);
ctx->setTextMode(true);
QByteArray cipherText;
@@ -297,9 +280,8 @@ private:
agentConf.close();
auto decJob = openpgp()->decryptJob();
+ hookUpPassphraseProvider(decJob);
auto ctx2 = Job::context(decJob);
- ctx2->setPassphraseProvider(new TestPassphraseProvider);
- ctx2->setPinentryMode(Context::PinentryLoopback);
ctx2->setTextMode(true);
QByteArray plainText;
auto decResult = decJob->exec(cipherText, plainText);
diff --git a/lang/qt/tests/t-import.cpp b/lang/qt/tests/t-import.cpp
new file mode 100644
index 0000000..33e242f
--- /dev/null
+++ b/lang/qt/tests/t-import.cpp
@@ -0,0 +1,169 @@
+/* t-import.cpp
+
+ This file is part of qgpgme, the Qt API binding for gpgme
+ Copyright (c) 2021 g10 Code GmbH
+ Software engineering by Ingo Klöcker <dev@ingo-kloecker.de>
+
+ QGpgME is free software; you can redistribute it and/or
+ modify it under the terms of the GNU General Public License as
+ published by the Free Software Foundation; either version 2 of the
+ License, or (at your option) any later version.
+
+ QGpgME is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
+
+ In addition, as a special exception, the copyright holders give
+ permission to link the code of this program with any edition of
+ the Qt library by Trolltech AS, Norway (or with modified versions
+ of Qt that use the same license as Qt), and distribute linked
+ combinations including the two. You must obey the GNU General
+ Public License in all respects for all of the code used other than
+ Qt. If you modify this file, you may extend this exception to
+ your version of the file, but you are not obligated to do so. If
+ you do not wish to do so, delete this exception statement from
+ your version.
+*/
+
+#ifdef HAVE_CONFIG_H
+ #include "config.h"
+#endif
+
+#include "t-support.h"
+
+#include "context.h"
+#include "engineinfo.h"
+#include "protocol.h"
+#include "importjob.h"
+
+#include <importresult.h>
+
+#include <QDebug>
+#include <QSignalSpy>
+#include <QTemporaryDir>
+#include <QTest>
+
+using namespace QGpgME;
+using namespace GpgME;
+
+class ImportTest : public QGpgMETest
+{
+ Q_OBJECT
+
+private:
+ QTemporaryDir tempGpgHome;
+
+private Q_SLOTS:
+ void initTestCase()
+ {
+ QGpgMETest::initTestCase();
+ QVERIFY2(tempGpgHome.isValid(), "Failed to create temporary GNUPGHOME");
+ qputenv("GNUPGHOME", tempGpgHome.path().toLocal8Bit());
+ }
+
+ void testImportWithImportFilter()
+ {
+ if (GpgME::engineInfo(GpgME::GpgEngine).engineVersion() < "2.1.14") {
+ QSKIP("gpg does not yet support the --import-filter option");
+ }
+
+ // pub ed25519 2021-12-15 [SC]
+ // E7A0841292ACC9465D3142652FB3A6F51FBF28A2
+ // uid [ultimate] importWithImportFilter@example.com
+ // uid [ultimate] importWithImportFilter@example.net
+ // sub cv25519 2021-12-15 [E]
+ static const char keyFpr[] = "E7A0841292ACC9465D3142652FB3A6F51FBF28A2";
+ static const char keyData[] =
+ "-----BEGIN PGP PUBLIC KEY BLOCK-----\n"
+ "\n"
+ "mDMEYbm2PhYJKwYBBAHaRw8BAQdACzxBWtNNsmJ6rzpZkjh1yBe+Ajsk9NR8umEu\n"
+ "Da3HLgG0ImltcG9ydFdpdGhJbXBvcnRGaWx0ZXJAZXhhbXBsZS5uZXSIlAQTFgoA\n"
+ "PBYhBOeghBKSrMlGXTFCZS+zpvUfvyiiBQJhubY+AhsDBQsJCAcCAyICAQYVCgkI\n"
+ "CwIEFgIDAQIeBwIXgAAKCRAvs6b1H78oosRgAQCc/ke6q076nvzIE2UzT83JK/B6\n"
+ "lxSV7Fb8bKltOMpvsAD+Phap3EzA8jdMyKoO0FM926bw5lX7QROfeZ/JBYqyPwC0\n"
+ "ImltcG9ydFdpdGhJbXBvcnRGaWx0ZXJAZXhhbXBsZS5jb22IlAQTFgoAPBYhBOeg\n"
+ "hBKSrMlGXTFCZS+zpvUfvyiiBQJhubZlAhsDBQsJCAcCAyICAQYVCgkICwIEFgID\n"
+ "AQIeBwIXgAAKCRAvs6b1H78oohPWAQC/u9UXzkxRkrB2huaTZCsyimWEGZIMmxWd\n"
+ "tE+vN9/IvQD/Yzia+xRS6yca3Yz6iW8xS844ZqRxvkUEHjtJXSOzagm4OARhubY+\n"
+ "EgorBgEEAZdVAQUBAQdANQFjmDctY3N0/ELPZtj9tapwFs4vrmTVpx/SCfZmihkD\n"
+ "AQgHiHgEGBYKACAWIQTnoIQSkqzJRl0xQmUvs6b1H78oogUCYbm2PgIbDAAKCRAv\n"
+ "s6b1H78oovGyAP41ySzvvDpV7XDJBOAFxvWLmywa5IcO7Lrg7y1efoWj0AD+Kk/B\n"
+ "s7jGLdoG51h670h50MMoYCANB6MwAdSP+qZUlQg=\n"
+ "=/3O0\n"
+ "-----END PGP PUBLIC KEY BLOCK-----\n";
+
+ auto *job = openpgp()->importJob();
+ job->setImportFilter(QLatin1String{"keep-uid=mbox = importWithImportFilter@example.net"});
+ connect(job, &ImportJob::result, this,
+ [this](ImportResult result, QString, Error)
+ {
+ QVERIFY(!result.error());
+ QVERIFY(!result.imports().empty());
+ QVERIFY(result.numImported());
+ Q_EMIT asyncDone();
+ });
+ job->start(QByteArray{keyData});
+ QSignalSpy spy (this, SIGNAL(asyncDone()));
+ QVERIFY(spy.wait());
+
+ auto ctx = Context::createForProtocol(GpgME::OpenPGP);
+ GpgME::Error err;
+ const auto key = ctx->key(keyFpr, err, false);
+ QVERIFY(!key.isNull());
+ QCOMPARE(key.numUserIDs(), 1);
+ QCOMPARE(key.userID(0).id(), "importWithImportFilter@example.net");
+ }
+
+ void testImportWithKeyOrigin()
+ {
+ if (GpgME::engineInfo(GpgME::GpgEngine).engineVersion() < "2.1.22") {
+ QSKIP("gpg does not yet support the --key-origin option");
+ }
+
+ static const char keyFpr[] = "5C5C428FABCC20F6913464BCCA6FB442887289B3";
+ static const char keyData[] =
+ "-----BEGIN PGP PUBLIC KEY BLOCK-----\n"
+ "\n"
+ "mDMEYbhuixYJKwYBBAHaRw8BAQdAulOM3IksCjdOJluEVlwalD8oZ5oa6wCw3EgW\n"
+ "NswXXb60H2ltcG9ydFdpdGhLZXlPcmlnaW5AZXhhbXBsZS5uZXSIlAQTFgoAPBYh\n"
+ "BFxcQo+rzCD2kTRkvMpvtEKIcomzBQJhuG6LAhsDBQsJCAcCAyICAQYVCgkICwIE\n"
+ "FgIDAQIeBwIXgAAKCRDKb7RCiHKJs+cIAQDaeoOw1OCAGpZQb8xJmLJHul5dLLzU\n"
+ "RBdHauMx9NROmQEA23QUVedc7walQjNKFzyIJA/YqRdbAKPiLonRBmxk9Ay4OARh\n"
+ "uG6LEgorBgEEAZdVAQUBAQdAMVdO9mNWIP/q8PtNOnBGlPyhx/vs07sF5sXk50A+\n"
+ "61QDAQgHiHgEGBYKACAWIQRcXEKPq8wg9pE0ZLzKb7RCiHKJswUCYbhuiwIbDAAK\n"
+ "CRDKb7RCiHKJs/x6AP0SEbZqW4iLCz2i1JntQghK5qpSZOVqsBTcARd6pcJ/cwEA\n"
+ "mrwskWazuS9+GVbHT5RATWOXnGaj+AICSDPE6qHtGgA=\n"
+ "=putz\n"
+ "-----END PGP PUBLIC KEY BLOCK-----\n";
+
+ auto *job = openpgp()->importJob();
+ job->setKeyOrigin(GpgME::Key::OriginWKD, "https://example.net");
+ connect(job, &ImportJob::result, this,
+ [this](ImportResult result, QString, Error)
+ {
+ QVERIFY(!result.error());
+ QVERIFY(!result.imports().empty());
+ QVERIFY(result.numImported());
+ Q_EMIT asyncDone();
+ });
+ job->start(QByteArray{keyData});
+ QSignalSpy spy (this, SIGNAL(asyncDone()));
+ QVERIFY(spy.wait());
+
+ auto ctx = Context::createForProtocol(GpgME::OpenPGP);
+ GpgME::Error err;
+ const auto key = ctx->key(keyFpr, err, false);
+ QVERIFY(!key.isNull());
+ QVERIFY(key.origin() == Key::OriginWKD);
+ // the origin URL is currently not available in GpgME
+ }
+};
+
+QTEST_MAIN(ImportTest)
+
+#include "t-import.moc"
diff --git a/lang/qt/tests/t-keylist.cpp b/lang/qt/tests/t-keylist.cpp
index 5875dfb..e481dfe 100644
--- a/lang/qt/tests/t-keylist.cpp
+++ b/lang/qt/tests/t-keylist.cpp
@@ -57,9 +57,6 @@ class KeyListTest : public QGpgMETest
{
Q_OBJECT
-Q_SIGNALS:
- void asyncDone();
-
private Q_SLOTS:
void testSingleKeyListSync()
{
@@ -151,7 +148,7 @@ private Q_SLOTS:
delete job;
QVERIFY(!result.error());
- QCOMPARE(secKeys.size(), 2u);
+ QCOMPARE(secKeys.size(), static_cast<decltype(secKeys.size())>(2));
std::vector<std::string> secKeyFingerprints = std::accumulate(secKeys.begin(), secKeys.end(), std::vector<std::string>(), accumulateFingerprints);
QCOMPARE(secKeyFingerprints, std::vector<std::string>({
"23FD347A419429BACCD5E72D6BC4778054ACD246",
@@ -162,7 +159,7 @@ private Q_SLOTS:
QVERIFY(secKeys[0].subkeys()[0].keyGrip());
}
- QCOMPARE(pubKeys.size(), 26u);
+ QCOMPARE(pubKeys.size(), static_cast<decltype(pubKeys.size())>(26));
std::vector<std::string> pubKeyFingerprints = std::accumulate(pubKeys.begin(), pubKeys.end(), std::vector<std::string>(), accumulateFingerprints);
QCOMPARE(pubKeyFingerprints, std::vector<std::string>({
"045B2334ADD69FC221076841A5E67F7FA3AE3EA1",
diff --git a/lang/qt/tests/t-keylocate.cpp b/lang/qt/tests/t-keylocate.cpp
index 6d00da3..d84249c 100644
--- a/lang/qt/tests/t-keylocate.cpp
+++ b/lang/qt/tests/t-keylocate.cpp
@@ -51,9 +51,6 @@ class KeyLocateTest : public QGpgMETest
{
Q_OBJECT
-Q_SIGNALS:
- void asyncDone();
-
private Q_SLOTS:
#ifdef DO_ONLINE_TESTS
diff --git a/lang/qt/tests/t-ownertrust.cpp b/lang/qt/tests/t-ownertrust.cpp
index 093c21e..31d2247 100644
--- a/lang/qt/tests/t-ownertrust.cpp
+++ b/lang/qt/tests/t-ownertrust.cpp
@@ -51,9 +51,6 @@ class ChangeOwnerTrustTest: public QGpgMETest
{
Q_OBJECT
-Q_SIGNALS:
- void asyncDone();
-
private Q_SLOTS:
void testChangeOwnerTrust()
diff --git a/lang/qt/tests/t-remarks.cpp b/lang/qt/tests/t-remarks.cpp
index c1880a7..f9a901a 100644
--- a/lang/qt/tests/t-remarks.cpp
+++ b/lang/qt/tests/t-remarks.cpp
@@ -54,9 +54,6 @@ class TestRemarks: public QGpgMETest
{
Q_OBJECT
-Q_SIGNALS:
- void asyncDone();
-
public:
// This test is disabled (no slot) because the behavior
// is not clearly defined. Better to prevent that
@@ -77,12 +74,7 @@ public:
// Create the job
auto job = openpgp()->signKeyJob();
QVERIFY (job);
-
- // Hack in the passphrase provider
- auto jobCtx = Job::context(job);
- TestPassphraseProvider provider;
- jobCtx->setPassphraseProvider(&provider);
- jobCtx->setPinentryMode(Context::PinentryLoopback);
+ hookUpPassphraseProvider(job);
// Setup the job
job->setExportable(false);
@@ -133,12 +125,7 @@ private Q_SLOTS:
// Create the job
auto job = openpgp()->signKeyJob();
QVERIFY (job);
-
- // Hack in the passphrase provider
- auto jobCtx = Job::context(job);
- TestPassphraseProvider provider;
- jobCtx->setPassphraseProvider(&provider);
- jobCtx->setPinentryMode(Context::PinentryLoopback);
+ hookUpPassphraseProvider(job);
// Setup the job
job->setExportable(true);
@@ -170,11 +157,7 @@ private Q_SLOTS:
// Now replace the remark
auto job3 = openpgp()->signKeyJob();
QVERIFY (job3);
-
- // Hack in the passphrase provider
- auto jobCtx3 = Job::context(job3);
- jobCtx3->setPassphraseProvider(&provider);
- jobCtx3->setPinentryMode(Context::PinentryLoopback);
+ hookUpPassphraseProvider(job3);
// Setup the job
job3->setExportable(false);
@@ -229,12 +212,7 @@ private Q_SLOTS:
// Create the job
auto job = openpgp()->signKeyJob();
QVERIFY (job);
-
- // Hack in the passphrase provider
- auto jobCtx = Job::context(job);
- TestPassphraseProvider provider;
- jobCtx->setPassphraseProvider(&provider);
- jobCtx->setPinentryMode(Context::PinentryLoopback);
+ hookUpPassphraseProvider(job);
// Setup the first job
job->setExportable(false);
@@ -257,11 +235,7 @@ private Q_SLOTS:
// Now another remark from zulu
auto job3 = openpgp()->signKeyJob();
QVERIFY (job3);
-
- // Hack in the passphrase provider
- auto jobCtx3 = Job::context(job3);
- jobCtx3->setPassphraseProvider(&provider);
- jobCtx3->setPinentryMode(Context::PinentryLoopback);
+ hookUpPassphraseProvider(job3);
// Setup the job
job3->setExportable(false);
@@ -315,12 +289,7 @@ private Q_SLOTS:
// Create the job
auto job = openpgp()->signKeyJob();
QVERIFY (job);
-
- // Hack in the passphrase provider
- auto jobCtx = Job::context(job);
- TestPassphraseProvider provider;
- jobCtx->setPassphraseProvider(&provider);
- jobCtx->setPinentryMode(Context::PinentryLoopback);
+ hookUpPassphraseProvider(job);
// Setup the job
job->setExportable(false);
@@ -352,11 +321,7 @@ private Q_SLOTS:
// Now replace the remark
auto job3 = openpgp()->signKeyJob();
QVERIFY (job3);
-
- // Hack in the passphrase provider
- auto jobCtx3 = Job::context(job3);
- jobCtx3->setPassphraseProvider(&provider);
- jobCtx3->setPinentryMode(Context::PinentryLoopback);
+ hookUpPassphraseProvider(job3);
// Setup the job
job3->setExportable(false);
@@ -405,12 +370,7 @@ private Q_SLOTS:
// Create the job
auto job = openpgp()->signKeyJob();
QVERIFY (job);
-
- // Hack in the passphrase provider
- auto jobCtx = Job::context(job);
- TestPassphraseProvider provider;
- jobCtx->setPassphraseProvider(&provider);
- jobCtx->setPinentryMode(Context::PinentryLoopback);
+ hookUpPassphraseProvider(job);
// Setup the job
job->setExportable(false);
@@ -441,11 +401,7 @@ private Q_SLOTS:
// Try to replace it without dupeOK
auto job2 = openpgp()->signKeyJob();
QVERIFY (job2);
-
- // Hack in the passphrase provider
- auto jobCtx2 = Job::context(job2);
- jobCtx2->setPassphraseProvider(&provider);
- jobCtx2->setPinentryMode(Context::PinentryLoopback);
+ hookUpPassphraseProvider(job2);
// Setup the job
job2->setExportable(false);
@@ -466,11 +422,7 @@ private Q_SLOTS:
// Now replace the remark
auto job3 = openpgp()->signKeyJob();
QVERIFY (job3);
-
- // Hack in the passphrase provider
- auto jobCtx3 = Job::context(job3);
- jobCtx3->setPassphraseProvider(&provider);
- jobCtx3->setPinentryMode(Context::PinentryLoopback);
+ hookUpPassphraseProvider(job3);
// Setup the job
job3->setExportable(false);
diff --git a/lang/qt/tests/t-support.cpp b/lang/qt/tests/t-support.cpp
index 7b16ccc..6db082f 100644
--- a/lang/qt/tests/t-support.cpp
+++ b/lang/qt/tests/t-support.cpp
@@ -35,7 +35,10 @@
#endif
#include "t-support.h"
-#include "context.h"
+
+#include "importjob.h"
+#include "job.h"
+#include "protocol.h"
#include <QTest>
@@ -43,8 +46,14 @@
#include <QCoreApplication>
#include <QObject>
#include <QDir>
+#include <QSignalSpy>
+#include "context.h"
#include "engineinfo.h"
+#include "importresult.h"
+
+using namespace GpgME;
+using namespace QGpgME;
void QGpgMETest::initTestCase()
{
@@ -59,6 +68,12 @@ void QGpgMETest::cleanupTestCase()
killAgent();
}
+// static
+bool QGpgMETest::doOnlineTests()
+{
+ return !qgetenv("DO_ONLINE_TESTS").isEmpty();
+}
+
bool QGpgMETest::copyKeyrings(const QString &src, const QString &dest)
{
bool is21dir = QFileInfo(src + QDir::separator() + QStringLiteral("pubring.kbx")).exists();
@@ -86,6 +101,41 @@ bool QGpgMETest::copyKeyrings(const QString &src, const QString &dest)
return true;
}
+bool QGpgMETest::importSecretKeys(const char *keyData, int expectedKeys)
+{
+ auto job = std::unique_ptr<ImportJob>{openpgp()->importJob()};
+ VERIFY_OR_FALSE(job);
+ hookUpPassphraseProvider(job.get());
+
+ ImportResult result;
+ connect(job.get(), &ImportJob::result,
+ this, [this, &result](const ImportResult &result_) {
+ result = result_;
+ Q_EMIT asyncDone();
+ });
+ VERIFY_OR_FALSE(!job->start(keyData));
+ job.release(); // after the job has been started it's on its own
+
+ QSignalSpy spy (this, SIGNAL(asyncDone()));
+ VERIFY_OR_FALSE(spy.wait(QSIGNALSPY_TIMEOUT));
+ VERIFY_OR_FALSE(!result.error());
+ VERIFY_OR_FALSE(!result.imports().empty());
+ COMPARE_OR_FALSE(result.numSecretKeysImported(), expectedKeys);
+
+ return true;
+}
+
+void QGpgMETest::hookUpPassphraseProvider(GpgME::Context *context)
+{
+ context->setPassphraseProvider(&mPassphraseProvider);
+ context->setPinentryMode(Context::PinentryLoopback);
+}
+
+void QGpgMETest::hookUpPassphraseProvider(QGpgME::Job *job)
+{
+ hookUpPassphraseProvider(Job::context(job));
+}
+
void killAgent(const QString& dir)
{
QProcess proc;
diff --git a/lang/qt/tests/t-support.h b/lang/qt/tests/t-support.h
index 77bef56..ecafe2f 100644
--- a/lang/qt/tests/t-support.h
+++ b/lang/qt/tests/t-support.h
@@ -34,11 +34,57 @@
#include "interfaces/passphraseprovider.h"
#include <QObject>
+#include <QTest>
#include <gpg-error.h>
namespace GpgME
{
+class Context;
+}
+
+namespace QGpgME
+{
+class Job;
+}
+
+/// generic variant of QVERIFY returning \a returnValue on failure
+#define VERIFY_OR_RETURN_VALUE(statement, returnValue) \
+do {\
+ if (!QTest::qVerify(static_cast<bool>(statement), #statement, "", __FILE__, __LINE__))\
+ return returnValue;\
+} while (false)
+
+/// generic variant of QCOMPARE returning \a returnValue on failure
+#define COMPARE_OR_RETURN_VALUE(actual, expected, returnValue) \
+do {\
+ if (!QTest::qCompare(actual, expected, #actual, #expected, __FILE__, __LINE__))\
+ return returnValue;\
+} while (false)
+
+/// variant of QVERIFY returning a default constructed object on failure
+#define VERIFY_OR_OBJECT(statement) VERIFY_OR_RETURN_VALUE(statement, {})
+
+/// variant of QCOMPARE returning a default constructed object on failure
+#define COMPARE_OR_OBJECT(actual, expected) COMPARE_OR_RETURN_VALUE(actual, expected, {})
+
+/// variant of QVERIFY returning \c false on failure
+#define VERIFY_OR_FALSE(statement) VERIFY_OR_RETURN_VALUE(statement, false)
+
+/// variant of QCOMPARE returning \c false on failure
+#define COMPARE_OR_FALSE(actual, expected) COMPARE_OR_RETURN_VALUE(actual, expected, false)
+
+namespace QTest
+{
+template <>
+inline char *toString(const std::string &s)
+{
+ return QTest::toString(s.c_str());
+}
+}
+
+namespace GpgME
+{
class TestPassphraseProvider : public PassphraseProvider
{
public:
@@ -59,12 +105,26 @@ bool loopbackSupported();
class QGpgMETest : public QObject
{
Q_OBJECT
+
+Q_SIGNALS:
+ void asyncDone();
+
protected:
+ static bool doOnlineTests();
+
bool copyKeyrings(const QString &from, const QString& to);
+ bool importSecretKeys(const char *keyData, int expectedKeys = 1);
+
+ void hookUpPassphraseProvider(GpgME::Context *context);
+ void hookUpPassphraseProvider(QGpgME::Job *job);
+
public Q_SLOTS:
void initTestCase();
void cleanupTestCase();
+
+private:
+ GpgME::TestPassphraseProvider mPassphraseProvider;
};
/* Timeout, in milliseconds, for use with QSignalSpy to wait on
diff --git a/lang/qt/tests/t-tofuinfo.cpp b/lang/qt/tests/t-tofuinfo.cpp
index 2d88106..a1871c4 100644
--- a/lang/qt/tests/t-tofuinfo.cpp
+++ b/lang/qt/tests/t-tofuinfo.cpp
@@ -116,8 +116,6 @@ static const char conflictMsg2[] = "-----BEGIN PGP MESSAGE-----\n"
class TofuInfoTest: public QGpgMETest
{
Q_OBJECT
-Q_SIGNALS:
- void asyncDone();
private:
bool testSupported()
@@ -155,10 +153,7 @@ private:
void signAndVerify(const QString &what, const GpgME::Key &key, int expected)
{
auto job = openpgp()->signJob();
- auto ctx = Job::context(job);
- TestPassphraseProvider provider;
- ctx->setPassphraseProvider(&provider);
- ctx->setPinentryMode(Context::PinentryLoopback);
+ hookUpPassphraseProvider(job);
std::vector<Key> keys;
keys.push_back(key);
diff --git a/lang/qt/tests/t-trustsignatures.cpp b/lang/qt/tests/t-trustsignatures.cpp
index d392b2f..6f7ad82 100644
--- a/lang/qt/tests/t-trustsignatures.cpp
+++ b/lang/qt/tests/t-trustsignatures.cpp
@@ -1,4 +1,4 @@
-/* t-remarks.cpp
+/* t-trustsignatures.cpp
This file is part of qgpgme, the Qt API binding for gpgme
Copyright (c) 2021 g10 Code GmbH
@@ -52,9 +52,6 @@ class TestTrustSignatures: public QGpgMETest
{
Q_OBJECT
-Q_SIGNALS:
- void asyncDone();
-
private Q_SLOTS:
void test_tsign_single_uid_key_and_then_tsign_it_again()
{
@@ -83,12 +80,7 @@ private Q_SLOTS:
// Create the job
auto job = std::unique_ptr<SignKeyJob>{openpgp()->signKeyJob()};
QVERIFY(job);
-
- // Hack in the passphrase provider
- auto jobCtx = Job::context(job.get());
- TestPassphraseProvider provider;
- jobCtx->setPassphraseProvider(&provider);
- jobCtx->setPinentryMode(Context::PinentryLoopback);
+ hookUpPassphraseProvider(job.get());
// Setup the job
job->setExportable(true);
@@ -131,12 +123,7 @@ private Q_SLOTS:
// Create the job
auto job = std::unique_ptr<SignKeyJob>{openpgp()->signKeyJob()};
QVERIFY(job);
-
- // Hack in the passphrase provider
- auto jobCtx = Job::context(job.get());
- TestPassphraseProvider provider;
- jobCtx->setPassphraseProvider(&provider);
- jobCtx->setPinentryMode(Context::PinentryLoopback);
+ hookUpPassphraseProvider(job.get());
// Setup the job
job->setExportable(true);
@@ -204,12 +191,7 @@ private Q_SLOTS:
// Create the job
auto job = openpgp()->signKeyJob();//std::unique_ptr<SignKeyJob>{openpgp()->signKeyJob()};
QVERIFY(job);
-
- // Hack in the passphrase provider
- auto jobCtx = Job::context(job);
- TestPassphraseProvider provider;
- jobCtx->setPassphraseProvider(&provider);
- jobCtx->setPinentryMode(Context::PinentryLoopback);
+ hookUpPassphraseProvider(job);
// Setup the job
job->setExportable(true);
@@ -252,12 +234,7 @@ private Q_SLOTS:
// Create the job
auto job = openpgp()->signKeyJob();//std::unique_ptr<SignKeyJob>{openpgp()->signKeyJob()};
QVERIFY(job);
-
- // Hack in the passphrase provider
- auto jobCtx = Job::context(job);
- TestPassphraseProvider provider;
- jobCtx->setPassphraseProvider(&provider);
- jobCtx->setPinentryMode(Context::PinentryLoopback);
+ hookUpPassphraseProvider(job);
// Setup the job
job->setExportable(true);
@@ -325,12 +302,7 @@ private Q_SLOTS:
// Create the job
auto job = openpgp()->signKeyJob();//std::unique_ptr<SignKeyJob>{openpgp()->signKeyJob()};
QVERIFY(job);
-
- // Hack in the passphrase provider
- auto jobCtx = Job::context(job);
- TestPassphraseProvider provider;
- jobCtx->setPassphraseProvider(&provider);
- jobCtx->setPinentryMode(Context::PinentryLoopback);
+ hookUpPassphraseProvider(job);
// Setup the job
job->setExportable(true);
@@ -374,12 +346,7 @@ private Q_SLOTS:
// Create the job
auto job = openpgp()->signKeyJob();//std::unique_ptr<SignKeyJob>{openpgp()->signKeyJob()};
QVERIFY(job);
-
- // Hack in the passphrase provider
- auto jobCtx = Job::context(job);
- TestPassphraseProvider provider;
- jobCtx->setPassphraseProvider(&provider);
- jobCtx->setPinentryMode(Context::PinentryLoopback);
+ hookUpPassphraseProvider(job);
// Setup the job
job->setExportable(true);
@@ -447,12 +414,7 @@ private Q_SLOTS:
// Create the job
auto job = openpgp()->signKeyJob();//std::unique_ptr<SignKeyJob>{openpgp()->signKeyJob()};
QVERIFY(job);
-
- // Hack in the passphrase provider
- auto jobCtx = Job::context(job);
- TestPassphraseProvider provider;
- jobCtx->setPassphraseProvider(&provider);
- jobCtx->setPinentryMode(Context::PinentryLoopback);
+ hookUpPassphraseProvider(job);
// Setup the job
job->setExportable(true);
@@ -495,12 +457,7 @@ private Q_SLOTS:
// Create the job
auto job = openpgp()->signKeyJob();//std::unique_ptr<SignKeyJob>{openpgp()->signKeyJob()};
QVERIFY(job);
-
- // Hack in the passphrase provider
- auto jobCtx = Job::context(job);
- TestPassphraseProvider provider;
- jobCtx->setPassphraseProvider(&provider);
- jobCtx->setPinentryMode(Context::PinentryLoopback);
+ hookUpPassphraseProvider(job);
// Setup the job
job->setExportable(true);
diff --git a/lang/qt/tests/t-various.cpp b/lang/qt/tests/t-various.cpp
index 8563b68..b630350 100644
--- a/lang/qt/tests/t-various.cpp
+++ b/lang/qt/tests/t-various.cpp
@@ -71,9 +71,6 @@ class TestVarious: public QGpgMETest
{
Q_OBJECT
-Q_SIGNALS:
- void asyncDone();
-
private Q_SLOTS:
void testDN()
{
@@ -137,9 +134,7 @@ private Q_SLOTS:
auto ctx = Context::createForProtocol(key.protocol());
QVERIFY (ctx);
- TestPassphraseProvider provider;
- ctx->setPassphraseProvider(&provider);
- ctx->setPinentryMode(Context::PinentryLoopback);
+ hookUpPassphraseProvider(ctx);
QVERIFY(!ctx->addUid(key, uid));
delete ctx;
@@ -190,9 +185,7 @@ private Q_SLOTS:
auto ctx = Context::createForProtocol(key.protocol());
QVERIFY (ctx);
- TestPassphraseProvider provider;
- ctx->setPassphraseProvider(&provider);
- ctx->setPinentryMode(Context::PinentryLoopback);
+ hookUpPassphraseProvider(ctx);
// change expiration of the main key
QVERIFY(!ctx->setExpire(key, 1000));
@@ -230,7 +223,7 @@ private Q_SLOTS:
std::vector<Subkey> primaryKey;
primaryKey.push_back(key.subkey(0));
const auto err = ctx->setExpire(key, 3000, primaryKey);
- QCOMPARE(err.code(), GPG_ERR_NOT_FOUND);
+ QCOMPARE(err.code(), static_cast<int>(GPG_ERR_NOT_FOUND));
delete ctx;
}
@@ -259,12 +252,7 @@ private Q_SLOTS:
// Create the job
auto job = std::unique_ptr<SignKeyJob>{openpgp()->signKeyJob()};
QVERIFY(job);
-
- // Hack in the passphrase provider
- auto jobCtx = Job::context(job.get());
- TestPassphraseProvider provider;
- jobCtx->setPassphraseProvider(&provider);
- jobCtx->setPinentryMode(Context::PinentryLoopback);
+ hookUpPassphraseProvider(job.get());
// Setup the job
job->setExportable(true);
@@ -319,12 +307,7 @@ private Q_SLOTS:
// Create the job
auto job = std::unique_ptr<SignKeyJob>{openpgp()->signKeyJob()};
QVERIFY(job);
-
- // Hack in the passphrase provider
- auto jobCtx = Job::context(job.get());
- TestPassphraseProvider provider;
- jobCtx->setPassphraseProvider(&provider);
- jobCtx->setPinentryMode(Context::PinentryLoopback);
+ hookUpPassphraseProvider(job.get());
// Setup the job
job->setExportable(true);
@@ -355,7 +338,7 @@ private Q_SLOTS:
target.update();
const auto keySignature = target.userID(0).signature(target.userID(0).numSignatures() - 1);
QVERIFY(!keySignature.neverExpires());
- const auto expirationDate = QDateTime::fromSecsSinceEpoch(keySignature.expirationTime()).date();
+ const auto expirationDate = QDateTime::fromSecsSinceEpoch(uint_least32_t(keySignature.expirationTime())).date();
QCOMPARE(expirationDate, QDate(2106, 2, 6)); // expiration date is capped at 2106-02-06
}
diff --git a/lang/qt/tests/t-wkdlookup.cpp b/lang/qt/tests/t-wkdlookup.cpp
new file mode 100644
index 0000000..5c2816c
--- /dev/null
+++ b/lang/qt/tests/t-wkdlookup.cpp
@@ -0,0 +1,155 @@
+/* t-wkdlookup.cpp
+
+ This file is part of qgpgme, the Qt API binding for gpgme
+ Copyright (c) 2021 g10 Code GmbH
+ Software engineering by Ingo Klöcker <dev@ingo-kloecker.de>
+
+ QGpgME is free software; you can redistribute it and/or
+ modify it under the terms of the GNU General Public License as
+ published by the Free Software Foundation; either version 2 of the
+ License, or (at your option) any later version.
+
+ QGpgME is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
+
+ In addition, as a special exception, the copyright holders give
+ permission to link the code of this program with any edition of
+ the Qt library by Trolltech AS, Norway (or with modified versions
+ of Qt that use the same license as Qt), and distribute linked
+ combinations including the two. You must obey the GNU General
+ Public License in all respects for all of the code used other than
+ Qt. If you modify this file, you may extend this exception to
+ your version of the file, but you are not obligated to do so. If
+ you do not wish to do so, delete this exception statement from
+ your version.
+*/
+#ifdef HAVE_CONFIG_H
+ #include "config.h"
+#endif
+
+#include "t-support.h"
+
+#include "data.h"
+#include "engineinfo.h"
+#include "protocol.h"
+#include "wkdlookupjob.h"
+#include "wkdlookupresult.h"
+
+#include <QDebug>
+#include <QSignalSpy>
+#include <QTest>
+
+#include <algorithm>
+
+using namespace QGpgME;
+using namespace GpgME;
+
+static const char *requiredVersion = "2.1.12";
+
+namespace
+{
+bool keyHasUserIDWithMatchingEmailAddress(const Key &key, const QString &expectedEmailAddress)
+{
+ const auto email = expectedEmailAddress.toLower();
+ const auto userIds = key.userIDs();
+ return std::any_of(
+ std::begin(userIds), std::end(userIds),
+ [email](const UserID &uid) {
+ return email == QString::fromUtf8(uid.email()).toLower();
+ });
+}
+}
+
+class WKDLookupTest : public QGpgMETest
+{
+ Q_OBJECT
+
+private Q_SLOTS:
+
+ void testWKDLookupAsync()
+ {
+ if (GpgME::engineInfo(GpgME::GpgEngine).engineVersion() < requiredVersion) {
+ QSKIP("dirmngr does not yet support WKD lookup");
+ }
+ if (!doOnlineTests()) {
+ QSKIP("Set DO_ONLINE_TESTS environment variable to run this test.");
+ }
+ const QString email = QLatin1String{"wk@gnupg.org"};
+
+ WKDLookupResult result;
+ auto *job = openpgp()->wkdLookupJob();
+ connect(job, &WKDLookupJob::result, job, [this, &result](const WKDLookupResult &result_, const QString &, const Error &)
+ {
+ result = result_;
+ Q_EMIT asyncDone();
+ });
+ job->start(email);
+ QSignalSpy spy (this, SIGNAL(asyncDone()));
+ QVERIFY(spy.wait(QSIGNALSPY_TIMEOUT));
+
+ QVERIFY(result.error().code() == GPG_ERR_NO_ERROR);
+ QCOMPARE(result.pattern(), "wk@gnupg.org");
+ QCOMPARE(result.source(), "https://openpgpkey.gnupg.org");
+ const auto keys = result.keyData().toKeys(GpgME::OpenPGP);
+ QVERIFY(keys.size() == 1);
+ QVERIFY(keyHasUserIDWithMatchingEmailAddress(keys.front(), email));
+ }
+
+ void testWKDLookupSync()
+ {
+ if (GpgME::engineInfo(GpgME::GpgEngine).engineVersion() < requiredVersion) {
+ QSKIP("dirmngr does not yet support WKD lookup");
+ }
+ if (!doOnlineTests()) {
+ QSKIP("Set DO_ONLINE_TESTS environment variable to run this test.");
+ }
+ const QString email = QLatin1String{"wk@gnupg.org"};
+
+ auto *job = openpgp()->wkdLookupJob();
+ const auto result = job->exec(email);
+
+ QVERIFY(result.error().code() == GPG_ERR_NO_ERROR);
+ QCOMPARE(result.pattern(), "wk@gnupg.org");
+ QCOMPARE(result.source(), "https://openpgpkey.gnupg.org");
+ const auto keys = result.keyData().toKeys(GpgME::OpenPGP);
+ QVERIFY(keys.size() == 1);
+ QVERIFY(keyHasUserIDWithMatchingEmailAddress(keys.front(), email));
+ }
+
+ void testLookupWithNoResultAsync()
+ {
+ if (GpgME::engineInfo(GpgME::GpgEngine).engineVersion() < requiredVersion) {
+ QSKIP("dirmngr does not yet support WKD lookup");
+ }
+ if (!doOnlineTests()) {
+ QSKIP("Set DO_ONLINE_TESTS environment variable to run this test.");
+ }
+ const QString email = QLatin1String{"alfa@example.net"};
+
+ WKDLookupResult result;
+ auto *job = openpgp()->wkdLookupJob();
+ connect(job, &WKDLookupJob::result, job, [this, &result](const WKDLookupResult &result_, const QString &, const Error &)
+ {
+ result = result_;
+ Q_EMIT asyncDone();
+ });
+ job->start(email);
+ QSignalSpy spy (this, SIGNAL(asyncDone()));
+ QVERIFY(spy.wait(QSIGNALSPY_TIMEOUT));
+
+ QVERIFY(result.error().code() == GPG_ERR_NO_ERROR);
+ QCOMPARE(result.pattern(), "alfa@example.net");
+ QCOMPARE(result.source(), "");
+ QVERIFY(result.keyData().isNull());
+ }
+};
+
+QTEST_MAIN(WKDLookupTest)
+
+#include "t-wkdlookup.moc"
diff --git a/lang/qt/tests/t-wkspublish.cpp b/lang/qt/tests/t-wkspublish.cpp
index b389194..618f0b4 100644
--- a/lang/qt/tests/t-wkspublish.cpp
+++ b/lang/qt/tests/t-wkspublish.cpp
@@ -118,9 +118,6 @@ class WKSPublishTest : public QGpgMETest
{
Q_OBJECT
-Q_SIGNALS:
- void asyncDone();
-
private Q_SLOTS:
void testUnsupported()
{
diff --git a/m4/libtool.m4 b/m4/libtool.m4
index 8795701..c6f534e 100644
--- a/m4/libtool.m4
+++ b/m4/libtool.m4
@@ -1045,16 +1045,11 @@ _LT_EOF
_lt_dar_allow_undefined='${wl}-undefined ${wl}suppress' ;;
darwin1.*)
_lt_dar_allow_undefined='${wl}-flat_namespace ${wl}-undefined ${wl}suppress' ;;
- darwin*) # darwin 5.x on
- # if running on 10.5 or later, the deployment target defaults
- # to the OS version, if on x86, and 10.4, the deployment
- # target defaults to 10.4. Don't you love it?
- case ${MACOSX_DEPLOYMENT_TARGET-10.0},$host in
- 10.0,*86*-darwin8*|10.0,*-darwin[[91]]*)
- _lt_dar_allow_undefined='${wl}-undefined ${wl}dynamic_lookup' ;;
- 10.[[012]]*)
+ darwin*)
+ case ${MACOSX_DEPLOYMENT_TARGET},$host in
+ 10.[[012]]*,*|,*powerpc*)
_lt_dar_allow_undefined='${wl}-flat_namespace ${wl}-undefined ${wl}suppress' ;;
- 10.*)
+ *)
_lt_dar_allow_undefined='${wl}-undefined ${wl}dynamic_lookup' ;;
esac
;;
diff --git a/src/ath.c b/src/ath.c
index 6cc84aa..996143d 100644
--- a/src/ath.c
+++ b/src/ath.c
@@ -26,11 +26,15 @@
#ifdef HAVE_UNISTD_H
# include <unistd.h>
#endif
-#ifdef HAVE_SYS_SELECT_H
-# include <sys/select.h>
+#ifdef HAVE_POLL_H
+# include <poll.h>
#else
-# ifdef HAVE_SYS_TIME_H
-# include <sys/time.h>
+# ifdef HAVE_SYS_SELECT_H
+# include <sys/select.h>
+# else
+# ifdef HAVE_SYS_TIME_H
+# include <sys/time.h>
+# endif
# endif
#endif
#ifdef HAVE_SYS_TYPES_H
@@ -89,6 +93,7 @@ ath_write (int fd, const void *buf, size_t nbytes)
}
+#if !defined(HAVE_POLL_H)
gpgme_ssize_t
ath_select (int nfd, fd_set *rset, fd_set *wset, fd_set *eset,
struct timeval *timeout)
@@ -99,7 +104,7 @@ ath_select (int nfd, fd_set *rset, fd_set *wset, fd_set *eset,
return select (nfd, rset, wset, eset, timeout);
#endif
}
-
+#endif
gpgme_ssize_t
ath_waitpid (pid_t pid, int *status, int options)
diff --git a/src/ath.h b/src/ath.h
index d4c1c6f..8243864 100644
--- a/src/ath.h
+++ b/src/ath.h
@@ -32,12 +32,15 @@
# include <io.h>
#else /*!HAVE_W32_SYSTEM*/
-
-# ifdef HAVE_SYS_SELECT_H
-# include <sys/select.h>
+# ifdef HAVE_POLL_H
+# include <poll.h>
# else
-# ifdef HAVE_SYS_TIME_H
-# include <sys/time.h>
+# ifdef HAVE_SYS_SELECT_H
+# include <sys/select.h>
+# else
+# ifdef HAVE_SYS_TIME_H
+# include <sys/time.h>
+# endif
# endif
# endif
# ifdef HAVE_SYS_TYPES_H
diff --git a/src/context.h b/src/context.h
index 2792a16..e976ba3 100644
--- a/src/context.h
+++ b/src/context.h
@@ -177,6 +177,12 @@ struct gpgme_context
/* The optional expiration date of a certification. */
char *cert_expire;
+ /* The optional key origin. */
+ char *key_origin;
+
+ /* The optional import filter. */
+ char *import_filter;
+
/* The operation data hooked into the context. */
ctx_op_data_t op_data;
diff --git a/src/data.c b/src/data.c
index 62b7231..e2de9f6 100644
--- a/src/data.c
+++ b/src/data.c
@@ -391,7 +391,7 @@ gpgme_data_read (gpgme_data_t dh, void *buffer, size_t size)
while (res < 0 && errno == EINTR);
}
- return TRACE_SYSRES ((int)res);
+ return TRACE_SYSRES_SSIZE_T (res);
}
@@ -419,7 +419,7 @@ gpgme_data_write (gpgme_data_t dh, const void *buffer, size_t size)
res = (*dh->cbs->write) (dh, buffer, size);
while (res < 0 && errno == EINTR);
- return TRACE_SYSRES ((int)res);
+ return TRACE_SYSRES_SSIZE_T (res);
}
@@ -452,7 +452,7 @@ gpgme_data_seek (gpgme_data_t dh, gpgme_off_t offset, int whence)
if (offset >= 0)
dh->outbound_pending = 0;
- return TRACE_SYSRES ((int)offset);
+ return TRACE_SYSRES_OFF_T (offset);
}
diff --git a/src/debug.h b/src/debug.h
index fa0bfc6..7b823ee 100644
--- a/src/debug.h
+++ b/src/debug.h
@@ -141,7 +141,7 @@ _trace_err (gpg_error_t err, int lvl, const char *func, int line)
return err;
}
-/* Trace a system call result and return it. */
+/* Trace a system call result of type int and return it. */
#define TRACE_SYSRES(res) \
_trace_sysres ((res), _gpgme_trace_level, _gpgme_trace_func, __LINE__)
static inline int
@@ -157,6 +157,38 @@ _trace_sysres (int res, int lvl, const char *func, int line)
return res;
}
+/* Trace a system call result of type gpgme_off_t and return it. */
+#define TRACE_SYSRES_OFF_T(res) \
+ _trace_sysres_off_t ((res), _gpgme_trace_level, _gpgme_trace_func, __LINE__)
+static inline gpgme_off_t
+_trace_sysres_off_t (gpgme_off_t res, int lvl, const char *func, int line)
+{
+ if (res >= 0)
+ _gpgme_debug (NULL, lvl, 3, func, NULL, NULL, "result=%ld", res);
+ else
+ _gpgme_debug (NULL, lvl, -1, NULL, NULL, NULL,
+ "%s:%d: error: %s (%d)\n",
+ func, line, strerror (errno), errno);
+ _gpgme_debug_frame_end ();
+ return res;
+}
+
+/* Trace a system call result of type gpgme_ssize_t and return it. */
+#define TRACE_SYSRES_SSIZE_T(res) \
+ _trace_sysres_ssize_t ((res), _gpgme_trace_level, _gpgme_trace_func, __LINE__)
+static inline gpgme_ssize_t
+_trace_sysres_ssize_t (gpgme_ssize_t res, int lvl, const char *func, int line)
+{
+ if (res >= 0)
+ _gpgme_debug (NULL, lvl, 3, func, NULL, NULL, "result=%zd", res);
+ else
+ _gpgme_debug (NULL, lvl, -1, NULL, NULL, NULL,
+ "%s:%d: error: %s (%d)\n",
+ func, line, strerror (errno), errno);
+ _gpgme_debug_frame_end ();
+ return res;
+}
+
/* Trace a system call error and return it. */
#define TRACE_SYSERR(rc) \
_trace_syserr ((rc), _gpgme_trace_level, _gpgme_trace_func, __LINE__)
diff --git a/src/dirinfo.c b/src/dirinfo.c
index c4f0e4a..8ea15d8 100644
--- a/src/dirinfo.c
+++ b/src/dirinfo.c
@@ -44,6 +44,7 @@ enum
WANT_LIBDIR,
WANT_DATADIR,
WANT_LOCALEDIR,
+ WANT_SOCKETDIR,
WANT_AGENT_SOCKET,
WANT_AGENT_SSH_SOCKET,
WANT_DIRMNGR_SOCKET,
@@ -52,6 +53,11 @@ enum
WANT_GPG_NAME,
WANT_GPGSM_NAME,
WANT_G13_NAME,
+ WANT_KEYBOXD_NAME,
+ WANT_AGENT_NAME,
+ WANT_SCDAEMON_NAME,
+ WANT_DIRMNGR_NAME,
+ WANT_PINENTRY_NAME,
WANT_GPG_WKS_CLIENT_NAME,
WANT_GPG_ONE_MODE
};
@@ -67,6 +73,7 @@ static struct {
char *libdir;
char *datadir;
char *localedir;
+ char *socketdir;
char *agent_socket;
char *agent_ssh_socket;
char *dirmngr_socket;
@@ -75,6 +82,11 @@ static struct {
char *gpg_name;
char *gpgsm_name;
char *g13_name;
+ char *keyboxd_name;
+ char *agent_name;
+ char *scdaemon_name;
+ char *dirmngr_name;
+ char *pinentry_name;
char *gpg_wks_client_name;
int gpg_one_mode; /* System is in gpg1 mode. */
} dirinfo;
@@ -135,6 +147,16 @@ parse_output (char *line, int components)
dirinfo.gpgsm_name = strdup (value);
else if (!strcmp (line, "g13") && !dirinfo.g13_name)
dirinfo.g13_name = strdup (value);
+ else if (!strcmp (line, "keyboxd") && !dirinfo.keyboxd_name)
+ dirinfo.keyboxd_name = strdup (value);
+ else if (!strcmp (line, "gpg-agent") && !dirinfo.agent_name)
+ dirinfo.agent_name = strdup (value);
+ else if (!strcmp (line, "scdaemon") && !dirinfo.scdaemon_name)
+ dirinfo.scdaemon_name = strdup (value);
+ else if (!strcmp (line, "dirmngr") && !dirinfo.dirmngr_name)
+ dirinfo.dirmngr_name = strdup (value);
+ else if (!strcmp (line, "pinentry") && !dirinfo.pinentry_name)
+ dirinfo.pinentry_name = strdup (value);
}
else
{
@@ -152,6 +174,8 @@ parse_output (char *line, int components)
dirinfo.datadir = strdup (value);
else if (!strcmp (line, "localedir") && !dirinfo.localedir)
dirinfo.localedir = strdup (value);
+ else if (!strcmp (line, "socketdir") && !dirinfo.socketdir)
+ dirinfo.socketdir = strdup (value);
else if (!strcmp (line, "agent-socket") && !dirinfo.agent_socket)
{
const char name[] = "S.uiserver";
@@ -306,10 +330,34 @@ get_gpgconf_item (int what)
_gpgme_debug (NULL, DEBUG_INIT, -1, NULL, NULL, NULL,
"gpgme-dinfo: gpgsm='%s'\n",
dirinfo.gpgsm_name);
+ if (dirinfo.keyboxd_name)
+ _gpgme_debug (NULL, DEBUG_INIT, -1, NULL, NULL, NULL,
+ "gpgme-dinfo: keyboxd='%s'\n",
+ dirinfo.keyboxd_name);
+ if (dirinfo.agent_name)
+ _gpgme_debug (NULL, DEBUG_INIT, -1, NULL, NULL, NULL,
+ "gpgme-dinfo: gpg-agent='%s'\n",
+ dirinfo.agent_name);
+ if (dirinfo.scdaemon_name)
+ _gpgme_debug (NULL, DEBUG_INIT, -1, NULL, NULL, NULL,
+ "gpgme-dinfo: scdaemon='%s'\n",
+ dirinfo.scdaemon_name);
+ if (dirinfo.dirmngr_name)
+ _gpgme_debug (NULL, DEBUG_INIT, -1, NULL, NULL, NULL,
+ "gpgme-dinfo: dirmngr='%s'\n",
+ dirinfo.dirmngr_name);
+ if (dirinfo.pinentry_name)
+ _gpgme_debug (NULL, DEBUG_INIT, -1, NULL, NULL, NULL,
+ "gpgme-dinfo: pinentry='%s'\n",
+ dirinfo.pinentry_name);
if (dirinfo.homedir)
_gpgme_debug (NULL, DEBUG_INIT, -1, NULL, NULL, NULL,
"gpgme-dinfo: homedir='%s'\n",
dirinfo.homedir);
+ if (dirinfo.socketdir)
+ _gpgme_debug (NULL, DEBUG_INIT, -1, NULL, NULL, NULL,
+ "gpgme-dinfo: sockdir='%s'\n",
+ dirinfo.socketdir);
if (dirinfo.agent_socket)
_gpgme_debug (NULL,DEBUG_INIT, -1, NULL, NULL, NULL,
"gpgme-dinfo: agent='%s'\n",
@@ -336,6 +384,7 @@ get_gpgconf_item (int what)
case WANT_LIBDIR: result = dirinfo.libdir; break;
case WANT_DATADIR: result = dirinfo.datadir; break;
case WANT_LOCALEDIR: result = dirinfo.localedir; break;
+ case WANT_SOCKETDIR: result = dirinfo.socketdir; break;
case WANT_AGENT_SOCKET: result = dirinfo.agent_socket; break;
case WANT_AGENT_SSH_SOCKET: result = dirinfo.agent_ssh_socket; break;
case WANT_DIRMNGR_SOCKET: result = dirinfo.dirmngr_socket; break;
@@ -343,6 +392,11 @@ get_gpgconf_item (int what)
case WANT_GPG_NAME: result = dirinfo.gpg_name; break;
case WANT_GPGSM_NAME: result = dirinfo.gpgsm_name; break;
case WANT_G13_NAME: result = dirinfo.g13_name; break;
+ case WANT_KEYBOXD_NAME: result = dirinfo.keyboxd_name; break;
+ case WANT_AGENT_NAME: result = dirinfo.agent_name; break;
+ case WANT_SCDAEMON_NAME: result = dirinfo.scdaemon_name; break;
+ case WANT_DIRMNGR_NAME: result = dirinfo.dirmngr_name; break;
+ case WANT_PINENTRY_NAME: result = dirinfo.pinentry_name; break;
case WANT_UISRV_SOCKET: result = dirinfo.uisrv_socket; break;
case WANT_GPG_ONE_MODE: result = dirinfo.gpg_one_mode? "1":NULL; break;
case WANT_GPG_WKS_CLIENT_NAME:
@@ -458,6 +512,16 @@ gpgme_get_dirinfo (const char *what)
return get_gpgconf_item (WANT_GPGSM_NAME);
else if (!strcmp (what, "g13-name"))
return get_gpgconf_item (WANT_G13_NAME);
+ else if (!strcmp (what, "keyboxd-name"))
+ return get_gpgconf_item (WANT_KEYBOXD_NAME);
+ else if (!strcmp (what, "agent-name"))
+ return get_gpgconf_item (WANT_AGENT_NAME);
+ else if (!strcmp (what, "scdaemon-name"))
+ return get_gpgconf_item (WANT_SCDAEMON_NAME);
+ else if (!strcmp (what, "dirmngr-name"))
+ return get_gpgconf_item (WANT_DIRMNGR_NAME);
+ else if (!strcmp (what, "pinentry-name"))
+ return get_gpgconf_item (WANT_PINENTRY_NAME);
else if (!strcmp (what, "gpg-wks-client-name"))
return get_gpgconf_item (WANT_GPG_WKS_CLIENT_NAME);
else if (!strcmp (what, "agent-ssh-socket"))
@@ -476,6 +540,8 @@ gpgme_get_dirinfo (const char *what)
return get_gpgconf_item (WANT_DATADIR);
else if (!strcmp (what, "localedir"))
return get_gpgconf_item (WANT_LOCALEDIR);
+ else if (!strcmp (what, "socketdir"))
+ return get_gpgconf_item (WANT_SOCKETDIR);
else
return NULL;
}
diff --git a/src/engine-backend.h b/src/engine-backend.h
index 8f90b6c..9b755a3 100644
--- a/src/engine-backend.h
+++ b/src/engine-backend.h
@@ -95,7 +95,10 @@ struct engine_ops
unsigned int extraflags,
gpgme_data_t pubkey, gpgme_data_t seckey);
gpgme_error_t (*import) (void *engine, gpgme_data_t keydata,
- gpgme_key_t *keyarray);
+ gpgme_key_t *keyarray,
+ const char *keyids[],
+ const char *import_filter,
+ const char *key_origin);
gpgme_error_t (*keylist) (void *engine, const char *pattern,
int secret_only, gpgme_keylist_mode_t mode,
int engine_flags);
diff --git a/src/engine-gpg.c b/src/engine-gpg.c
index b51ea17..88a248d 100644
--- a/src/engine-gpg.c
+++ b/src/engine-gpg.c
@@ -59,7 +59,7 @@ struct arg_and_data_s
int print_fd; /* Print the fd number and not the special form of it. */
int *arg_locp; /* Write back the argv idx of this argument when
building command line to this location. */
- char arg[1]; /* Used if data above is not used. */
+ char arg[FLEXIBLE_ARRAY_MEMBER]; /* Used if data above is not used. */
};
@@ -233,7 +233,7 @@ _add_arg (engine_gpg_t gpg, const char *prefix, const char *arg, size_t arglen,
assert (gpg);
assert (arg);
- a = malloc (sizeof *a + prefixlen + arglen);
+ a = malloc (offsetof (struct arg_and_data_s, arg) + prefixlen + arglen + 1);
if (!a)
return gpg_error_from_syserror ();
@@ -307,7 +307,7 @@ add_data (engine_gpg_t gpg, gpgme_data_t data, int dup_to, int inbound)
assert (gpg);
assert (data);
- a = malloc (sizeof *a - 1);
+ a = malloc (offsetof (struct arg_and_data_s, arg));
if (!a)
return gpg_error_from_syserror ();
a->next = NULL;
@@ -2354,7 +2354,8 @@ export_common (engine_gpg_t gpg, gpgme_export_mode_t mode,
if ((mode & ~(GPGME_EXPORT_MODE_EXTERN
|GPGME_EXPORT_MODE_MINIMAL
|GPGME_EXPORT_MODE_SSH
- |GPGME_EXPORT_MODE_SECRET)))
+ |GPGME_EXPORT_MODE_SECRET
+ |GPGME_EXPORT_MODE_SECRET_SUBKEY)))
return gpg_error (GPG_ERR_NOT_SUPPORTED);
if ((mode & GPGME_EXPORT_MODE_MINIMAL))
@@ -2379,7 +2380,9 @@ export_common (engine_gpg_t gpg, gpgme_export_mode_t mode,
}
else
{
- if ((mode & GPGME_EXPORT_MODE_SECRET))
+ if ((mode & GPGME_EXPORT_MODE_SECRET_SUBKEY))
+ err = add_arg (gpg, "--export-secret-subkeys");
+ else if ((mode & GPGME_EXPORT_MODE_SECRET))
err = add_arg (gpg, "--export-secret-keys");
else
err = add_arg (gpg, "--export");
@@ -2766,21 +2769,43 @@ string_from_data (gpgme_data_t data, int delim,
static gpgme_error_t
-gpg_import (void *engine, gpgme_data_t keydata, gpgme_key_t *keyarray)
+gpg_import (void *engine, gpgme_data_t keydata, gpgme_key_t *keyarray,
+ const char *keyids[], const char *import_filter,
+ const char *key_origin)
{
engine_gpg_t gpg = engine;
gpgme_error_t err;
int idx;
gpgme_data_encoding_t dataenc;
- if (keydata && keyarray)
+ if ((keydata && keyarray) || (keydata && keyids) || (keyarray && keyids))
return gpg_error (GPG_ERR_INV_VALUE); /* Only one is allowed. */
dataenc = gpgme_data_get_encoding (keydata);
- if (keyarray)
+ if (keyids)
{
err = add_arg (gpg, "--recv-keys");
+ if (!err && import_filter && have_gpg_version (gpg, "2.1.14"))
+ {
+ err = add_arg (gpg, "--import-filter");
+ if (!err)
+ err = add_arg (gpg, import_filter);
+ }
+ if (!err)
+ err = add_arg (gpg, "--");
+ while (!err && *keyids && **keyids)
+ err = add_arg (gpg, *(keyids++));
+ }
+ else if (keyarray)
+ {
+ err = add_arg (gpg, "--recv-keys");
+ if (!err && import_filter && have_gpg_version (gpg, "2.1.14"))
+ {
+ err = add_arg (gpg, "--import-filter");
+ if (!err)
+ err = add_arg (gpg, import_filter);
+ }
if (!err)
err = add_arg (gpg, "--");
for (idx=0; !err && keyarray[idx]; idx++)
@@ -2812,6 +2837,12 @@ gpg_import (void *engine, gpgme_data_t keydata, gpgme_key_t *keyarray)
should use an option to gpg to modify such commands (ala
--multifile). */
err = add_arg (gpg, "--fetch-keys");
+ if (!err && import_filter && have_gpg_version (gpg, "2.1.14"))
+ {
+ err = add_arg (gpg, "--import-filter");
+ if (!err)
+ err = add_arg (gpg, import_filter);
+ }
if (!err)
err = add_arg (gpg, "--");
helpptr = NULL;
@@ -2830,6 +2861,18 @@ gpg_import (void *engine, gpgme_data_t keydata, gpgme_key_t *keyarray)
else
{
err = add_arg (gpg, "--import");
+ if (!err && import_filter && have_gpg_version (gpg, "2.1.14"))
+ {
+ err = add_arg (gpg, "--import-filter");
+ if (!err)
+ err = add_arg (gpg, import_filter);
+ }
+ if (!err && key_origin && have_gpg_version (gpg, "2.1.22"))
+ {
+ err = add_arg (gpg, "--key-origin");
+ if (!err)
+ err = add_arg (gpg, key_origin);
+ }
if (!err)
err = add_arg (gpg, "--");
if (!err)
diff --git a/src/engine-gpgconf.c b/src/engine-gpgconf.c
index 28f9115..caf4d78 100644
--- a/src/engine-gpgconf.c
+++ b/src/engine-gpgconf.c
@@ -445,8 +445,10 @@ gpgconf_parse_option (gpgme_conf_opt_t opt,
case GPGME_CONF_PUB_KEY:
case GPGME_CONF_SEC_KEY:
case GPGME_CONF_ALIAS_LIST:
- /* Skip quote character. */
- line++;
+ /* Skip quote character. It is required by specs but
+ * technically not always needed. */
+ if (*line == '\"' && line[1])
+ line++;
err = _gpgme_decode_percent_string (line, &arg->value.string,
0, 0);
diff --git a/src/engine-gpgsm.c b/src/engine-gpgsm.c
index d5f0d7a..9ab0555 100644
--- a/src/engine-gpgsm.c
+++ b/src/engine-gpgsm.c
@@ -1512,6 +1512,12 @@ gpgsm_export (void *engine, const char *pattern, gpgme_export_mode_t mode,
if (!gpgsm)
return gpg_error (GPG_ERR_INV_VALUE);
+ if ((mode & ~(GPGME_EXPORT_MODE_SECRET
+ |GPGME_EXPORT_MODE_MINIMAL
+ |GPGME_EXPORT_MODE_RAW
+ |GPGME_EXPORT_MODE_PKCS12)))
+ return gpg_error (GPG_ERR_NOT_SUPPORTED);
+
if (!pattern)
pattern = "";
@@ -1559,6 +1565,12 @@ gpgsm_export_ext (void *engine, const char *pattern[], gpgme_export_mode_t mode,
if (!gpgsm)
return gpg_error (GPG_ERR_INV_VALUE);
+ if ((mode & ~(GPGME_EXPORT_MODE_SECRET
+ |GPGME_EXPORT_MODE_MINIMAL
+ |GPGME_EXPORT_MODE_RAW
+ |GPGME_EXPORT_MODE_PKCS12)))
+ return gpg_error (GPG_ERR_NOT_SUPPORTED);
+
if (pattern && *pattern)
{
const char **pat = pattern;
@@ -1696,16 +1708,24 @@ gpgsm_genkey (void *engine,
static gpgme_error_t
-gpgsm_import (void *engine, gpgme_data_t keydata, gpgme_key_t *keyarray)
+gpgsm_import (void *engine, gpgme_data_t keydata, gpgme_key_t *keyarray,
+ const char *keyids[], const char *import_filter,
+ const char *key_origin)
{
engine_gpgsm_t gpgsm = engine;
gpgme_error_t err;
gpgme_data_encoding_t dataenc;
int idx;
+ (void)import_filter;
+ (void)key_origin;
+
if (!gpgsm)
return gpg_error (GPG_ERR_INV_VALUE);
+ if (keyids)
+ return gpg_error (GPG_ERR_NOT_IMPLEMENTED);
+
if (keydata && keyarray)
return gpg_error (GPG_ERR_INV_VALUE); /* Only one is allowed. */
diff --git a/src/engine.c b/src/engine.c
index 96b8d3a..db594cb 100644
--- a/src/engine.c
+++ b/src/engine.c
@@ -850,7 +850,8 @@ _gpgme_engine_op_tofu_policy (engine_t engine,
gpgme_error_t
_gpgme_engine_op_import (engine_t engine, gpgme_data_t keydata,
- gpgme_key_t *keyarray)
+ gpgme_key_t *keyarray, const char *keyids[],
+ const char *import_filter, const char *key_origin)
{
if (!engine)
return gpg_error (GPG_ERR_INV_VALUE);
@@ -858,7 +859,8 @@ _gpgme_engine_op_import (engine_t engine, gpgme_data_t keydata,
if (!engine->ops->import)
return gpg_error (GPG_ERR_NOT_IMPLEMENTED);
- return (*engine->ops->import) (engine->engine, keydata, keyarray);
+ return (*engine->ops->import) (engine->engine, keydata, keyarray, keyids,
+ import_filter, key_origin);
}
diff --git a/src/engine.h b/src/engine.h
index d7ff542..8b45e13 100644
--- a/src/engine.h
+++ b/src/engine.h
@@ -141,7 +141,10 @@ gpgme_error_t _gpgme_engine_op_tofu_policy (engine_t engine,
gpgme_tofu_policy_t policy);
gpgme_error_t _gpgme_engine_op_import (engine_t engine,
gpgme_data_t keydata,
- gpgme_key_t *keyarray);
+ gpgme_key_t *keyarray,
+ const char *keyids[],
+ const char *import_filter,
+ const char *key_origin);
gpgme_error_t _gpgme_engine_op_keylist (engine_t engine,
const char *pattern,
int secret_only,
diff --git a/src/export.c b/src/export.c
index 4cee0ef..155085f 100644
--- a/src/export.c
+++ b/src/export.c
@@ -105,7 +105,8 @@ export_status_handler (void *priv, gpgme_status_code_t code, char *args)
return err;
else if (opd->err)
; /* We only want to report the first error. */
- else if (!strcmp (loc, "keyserver_send"))
+ else if (!strcmp (loc, "keyserver_send")
+ || !strcmp (loc, "export_keys.secret"))
opd->err = err;
break;
@@ -117,21 +118,29 @@ export_status_handler (void *priv, gpgme_status_code_t code, char *args)
static gpgme_error_t
-export_start (gpgme_ctx_t ctx, int synchronous, const char *pattern,
- gpgme_export_mode_t mode, gpgme_data_t keydata)
+check_mode (gpgme_export_mode_t mode, gpgme_protocol_t protocol,
+ gpgme_data_t keydata)
{
- gpgme_error_t err;
- void *hook;
- op_data_t opd;
-
if ((mode & ~(GPGME_EXPORT_MODE_EXTERN
|GPGME_EXPORT_MODE_MINIMAL
|GPGME_EXPORT_MODE_SECRET
|GPGME_EXPORT_MODE_SSH
|GPGME_EXPORT_MODE_RAW
- |GPGME_EXPORT_MODE_PKCS12)))
+ |GPGME_EXPORT_MODE_PKCS12
+ |GPGME_EXPORT_MODE_SECRET_SUBKEY)))
return gpg_error (GPG_ERR_INV_VALUE); /* Invalid flags in MODE. */
+ if ((mode & GPGME_EXPORT_MODE_SSH))
+ {
+ if ((mode & (GPGME_EXPORT_MODE_EXTERN
+ |GPGME_EXPORT_MODE_MINIMAL
+ |GPGME_EXPORT_MODE_SECRET
+ |GPGME_EXPORT_MODE_RAW
+ |GPGME_EXPORT_MODE_PKCS12
+ |GPGME_EXPORT_MODE_SECRET_SUBKEY)))
+ return gpg_error (GPG_ERR_INV_FLAG); /* Combination not allowed. */
+ }
+
if ((mode & GPGME_EXPORT_MODE_SECRET))
{
if ((mode & GPGME_EXPORT_MODE_EXTERN))
@@ -140,11 +149,17 @@ export_start (gpgme_ctx_t ctx, int synchronous, const char *pattern,
&& (mode & GPGME_EXPORT_MODE_PKCS12))
return gpg_error (GPG_ERR_INV_FLAG); /* Combination not allowed. */
- if (ctx->protocol != GPGME_PROTOCOL_CMS
+ if (protocol != GPGME_PROTOCOL_CMS
&& (mode & (GPGME_EXPORT_MODE_RAW|GPGME_EXPORT_MODE_PKCS12)))
return gpg_error (GPG_ERR_INV_FLAG); /* Only supported for X.509. */
}
+ if ((mode & GPGME_EXPORT_MODE_SECRET_SUBKEY))
+ {
+ if ((mode & GPGME_EXPORT_MODE_EXTERN))
+ return gpg_error (GPG_ERR_INV_FLAG); /* Combination not allowed. */
+ }
+
if ((mode & GPGME_EXPORT_MODE_EXTERN))
{
if (keydata)
@@ -156,6 +171,22 @@ export_start (gpgme_ctx_t ctx, int synchronous, const char *pattern,
return gpg_error (GPG_ERR_INV_VALUE);
}
+ return 0;
+}
+
+
+static gpgme_error_t
+export_start (gpgme_ctx_t ctx, int synchronous, const char *pattern,
+ gpgme_export_mode_t mode, gpgme_data_t keydata)
+{
+ gpgme_error_t err;
+ void *hook;
+ op_data_t opd;
+
+ err = check_mode (mode, ctx->protocol, keydata);
+ if (err)
+ return err;
+
err = _gpgme_op_reset (ctx, synchronous);
if (err)
return err;
@@ -227,37 +258,9 @@ export_ext_start (gpgme_ctx_t ctx, int synchronous, const char *pattern[],
void *hook;
op_data_t opd;
- if ((mode & ~(GPGME_EXPORT_MODE_EXTERN
- |GPGME_EXPORT_MODE_MINIMAL
- |GPGME_EXPORT_MODE_SECRET
- |GPGME_EXPORT_MODE_SSH
- |GPGME_EXPORT_MODE_RAW
- |GPGME_EXPORT_MODE_PKCS12)))
- return gpg_error (GPG_ERR_INV_VALUE); /* Invalid flags in MODE. */
-
- if ((mode & GPGME_EXPORT_MODE_SECRET))
- {
- if ((mode & GPGME_EXPORT_MODE_EXTERN))
- return gpg_error (GPG_ERR_INV_FLAG); /* Combination not allowed. */
- if ((mode & GPGME_EXPORT_MODE_RAW)
- && (mode & GPGME_EXPORT_MODE_PKCS12))
- return gpg_error (GPG_ERR_INV_FLAG); /* Combination not allowed. */
-
- if (ctx->protocol != GPGME_PROTOCOL_CMS
- && (mode & (GPGME_EXPORT_MODE_RAW|GPGME_EXPORT_MODE_PKCS12)))
- return gpg_error (GPG_ERR_INV_FLAG); /* Only supported for X.509. */
- }
-
- if ((mode & GPGME_EXPORT_MODE_EXTERN))
- {
- if (keydata)
- return gpg_error (GPG_ERR_INV_VALUE);
- }
- else
- {
- if (!keydata)
- return gpg_error (GPG_ERR_INV_VALUE);
- }
+ err = check_mode (mode, ctx->protocol, keydata);
+ if (err)
+ return err;
err = _gpgme_op_reset (ctx, synchronous);
if (err)
@@ -375,6 +378,11 @@ export_keys_start (gpgme_ctx_t ctx, int synchronous, gpgme_key_t keys[],
if (!keys)
return gpg_error (GPG_ERR_INV_VALUE);
+ if ((mode & GPGME_EXPORT_MODE_SECRET_SUBKEY))
+ {
+ return gpg_error (GPG_ERR_INV_FLAG);
+ }
+
/* Create a list of pattern from the keys. */
for (idx=nkeys=0; keys[idx]; idx++)
if (keys[idx]->protocol == ctx->protocol)
diff --git a/src/gpgme-tool.c b/src/gpgme-tool.c
index 0dbc4a9..e45ea12 100644
--- a/src/gpgme-tool.c
+++ b/src/gpgme-tool.c
@@ -2658,7 +2658,8 @@ cmd_import (assuan_context_t ctx, char *line)
static const char hlp_export[] =
- "EXPORT [--extern] [--minimal] [--secret [--pkcs12] [--raw]] [<pattern>]\n"
+ "EXPORT [--extern] [--minimal]\n"
+ " [--secret [--pkcs12] [--raw]|--secret-subkey] [<pattern>]\n"
"\n"
"Export the keys described by PATTERN. Write the\n"
"the output to the object set by the last OUTPUT command.";
@@ -2688,6 +2689,8 @@ cmd_export (assuan_context_t ctx, char *line)
mode |= GPGME_EXPORT_MODE_MINIMAL;
if (has_option (line, "--secret"))
mode |= GPGME_EXPORT_MODE_SECRET;
+ if (has_option (line, "--secret-subkey"))
+ mode |= GPGME_EXPORT_MODE_SECRET_SUBKEY;
if (has_option (line, "--raw"))
mode |= GPGME_EXPORT_MODE_RAW;
if (has_option (line, "--pkcs12"))
diff --git a/src/gpgme.c b/src/gpgme.c
index 255d116..6a5232e 100644
--- a/src/gpgme.c
+++ b/src/gpgme.c
@@ -254,6 +254,8 @@ gpgme_release (gpgme_ctx_t ctx)
free (ctx->auto_key_locate);
free (ctx->trust_model);
free (ctx->cert_expire);
+ free (ctx->key_origin);
+ free (ctx->import_filter);
_gpgme_engine_info_release (ctx->engine_info);
ctx->engine_info = NULL;
DESTROY_LOCK (ctx->lock);
@@ -586,6 +588,20 @@ gpgme_set_ctx_flag (gpgme_ctx_t ctx, const char *name, const char *value)
if (!ctx->cert_expire)
err = gpg_error_from_syserror ();
}
+ else if (!strcmp (name, "key-origin"))
+ {
+ free (ctx->key_origin);
+ ctx->key_origin = strdup (value);
+ if (!ctx->key_origin)
+ err = gpg_error_from_syserror ();
+ }
+ else if (!strcmp (name, "import-filter"))
+ {
+ free (ctx->import_filter);
+ ctx->import_filter = strdup (value);
+ if (!ctx->import_filter)
+ err = gpg_error_from_syserror ();
+ }
else
err = gpg_error (GPG_ERR_UNKNOWN_NAME);
@@ -659,6 +675,14 @@ gpgme_get_ctx_flag (gpgme_ctx_t ctx, const char *name)
{
return ctx->cert_expire? ctx->cert_expire : "";
}
+ else if (!strcmp (name, "key-origin"))
+ {
+ return ctx->key_origin? ctx->key_origin : "";
+ }
+ else if (!strcmp (name, "import-filter"))
+ {
+ return ctx->import_filter? ctx->import_filter : "";
+ }
else
return NULL;
}
diff --git a/src/gpgme.def b/src/gpgme.def
index 6644cae..d8ccd4c 100644
--- a/src/gpgme.def
+++ b/src/gpgme.def
@@ -280,5 +280,8 @@ EXPORTS
gpgme_op_revsig @207
gpgme_op_revsig_start @208
+ gpgme_op_receive_keys @209
+ gpgme_op_receive_keys_start @210
+
; END
diff --git a/src/gpgme.h.in b/src/gpgme.h.in
index 5c74afd..0f7c361 100644
--- a/src/gpgme.h.in
+++ b/src/gpgme.h.in
@@ -407,6 +407,7 @@ gpgme_pinentry_mode_t;
#define GPGME_EXPORT_MODE_RAW 32
#define GPGME_EXPORT_MODE_PKCS12 64
#define GPGME_EXPORT_MODE_SSH 256
+#define GPGME_EXPORT_MODE_SECRET_SUBKEY 512
typedef unsigned int gpgme_export_mode_t;
@@ -1737,6 +1738,12 @@ gpgme_error_t gpgme_op_import (gpgme_ctx_t ctx, gpgme_data_t keydata);
gpgme_error_t gpgme_op_import_keys_start (gpgme_ctx_t ctx, gpgme_key_t keys[]);
gpgme_error_t gpgme_op_import_keys (gpgme_ctx_t ctx, gpgme_key_t keys[]);
+/* Import the keys given by the array KEYIDS from a keyserver into the
+ * keyring. */
+gpgme_error_t gpgme_op_receive_keys_start (gpgme_ctx_t ctx,
+ const char *keyids[]);
+gpgme_error_t gpgme_op_receive_keys (gpgme_ctx_t ctx, const char *keyids[]);
+
/* Export the keys found by PATTERN into KEYDATA. */
gpgme_error_t gpgme_op_export_start (gpgme_ctx_t ctx, const char *pattern,
diff --git a/src/gpgme.pc.in b/src/gpgme.pc.in
index be288b8..80d59de 100644
--- a/src/gpgme.pc.in
+++ b/src/gpgme.pc.in
@@ -7,8 +7,8 @@ api_version=@GPGME_CONFIG_API_VERSION@
Name: gpgme
Description: GnuPG Made Easy to access GnuPG
-Requires: gpg-error, libassuan
+Requires.private: gpg-error, libassuan
Version: @PACKAGE_VERSION@
-Cflags: @GPGME_CONFIG_CFLAGS@
-Libs: @GPGME_CONFIG_LIBS@
+Cflags: -I${includedir} @GPGME_CONFIG_CFLAGS@
+Libs: -L${libdir} @GPGME_CONFIG_LIBS@
URL: https://www.gnupg.org/software/gpgme/index.html
diff --git a/src/import.c b/src/import.c
index 2834aec..85c459b 100644
--- a/src/import.c
+++ b/src/import.c
@@ -103,7 +103,7 @@ gpgme_op_import_result (gpgme_ctx_t ctx)
while (impstat)
{
TRACE_LOG ("import[%i] for %s = 0x%x (%s)",
- i, impstat->fpr, impstat->status,
+ i, impstat->fpr ? impstat->fpr : "null", impstat->status,
gpgme_strerror (impstat->result));
impstat = impstat->next;
i++;
@@ -223,6 +223,49 @@ parse_import_res (char *args, gpgme_import_result_t result)
}
+/* Parses an error on a status line and adds a corresponding import status.
+ Currently, only supports "import.parsep12 11". */
+static gpgme_error_t
+parse_error (char *args, gpgme_import_status_t *import_status)
+{
+ gpgme_import_status_t import;
+ char *tail;
+ long int nr;
+
+ tail = strchr (args, ' ');
+ if (!tail)
+ return 0;
+
+ *tail = '\0';
+ if (strcmp( args, "import.parsep12" ))
+ return 0;
+
+ args = tail + 1;
+
+ gpg_err_set_errno (0);
+ nr = strtol (args, &tail, 0);
+ if (errno || args == tail || !(*tail == ' ' || !*tail))
+ {
+ /* The crypto backend does not behave. */
+ return trace_gpg_error (GPG_ERR_INV_ENGINE);
+ }
+ if (nr != GPG_ERR_BAD_PASSPHRASE)
+ return 0;
+
+ import = malloc (sizeof (*import));
+ if (!import)
+ return gpg_error_from_syserror ();
+ import->next = NULL;
+
+ import->result = gpg_error (GPG_ERR_BAD_PASSPHRASE);
+ import->status = 0;
+ import->fpr = 0;
+
+ *import_status = import;
+ return 0;
+}
+
+
static gpgme_error_t
import_status_handler (void *priv, gpgme_status_code_t code, char *args)
{
@@ -252,6 +295,15 @@ import_status_handler (void *priv, gpgme_status_code_t code, char *args)
err = parse_import_res (args, &opd->result);
break;
+ case GPGME_STATUS_ERROR:
+ err = parse_error (args, opd->lastp);
+ if (err)
+ return err;
+
+ if (*opd->lastp)
+ opd->lastp = &(*opd->lastp)->next;
+ break;
+
default:
break;
}
@@ -282,7 +334,8 @@ _gpgme_op_import_start (gpgme_ctx_t ctx, int synchronous, gpgme_data_t keydata)
_gpgme_engine_set_status_handler (ctx->engine, import_status_handler, ctx);
- return _gpgme_engine_op_import (ctx->engine, keydata, NULL);
+ return _gpgme_engine_op_import (ctx->engine, keydata, NULL, NULL,
+ ctx->import_filter, ctx->key_origin);
}
@@ -365,7 +418,8 @@ _gpgme_op_import_keys_start (gpgme_ctx_t ctx, int synchronous,
_gpgme_engine_set_status_handler (ctx->engine, import_status_handler, ctx);
- return _gpgme_engine_op_import (ctx->engine, NULL, keys);
+ return _gpgme_engine_op_import (ctx->engine, NULL, keys, NULL,
+ ctx->import_filter, ctx->key_origin);
}
@@ -438,6 +492,94 @@ gpgme_op_import_keys (gpgme_ctx_t ctx, gpgme_key_t *keys)
}
+static gpgme_error_t
+_gpgme_op_receive_keys_start (gpgme_ctx_t ctx, int synchronous, const char *keyids[])
+{
+ gpgme_error_t err;
+ void *hook;
+ op_data_t opd;
+
+ err = _gpgme_op_reset (ctx, synchronous);
+ if (err)
+ return err;
+
+ err = _gpgme_op_data_lookup (ctx, OPDATA_IMPORT, &hook,
+ sizeof (*opd), release_op_data);
+ opd = hook;
+ if (err)
+ return err;
+ opd->lastp = &opd->result.imports;
+
+ if (!keyids || !*keyids)
+ return gpg_error (GPG_ERR_NO_DATA);
+
+ _gpgme_engine_set_status_handler (ctx->engine, import_status_handler, ctx);
+
+ return _gpgme_engine_op_import (ctx->engine, NULL, NULL, keyids,
+ ctx->import_filter, ctx->key_origin);
+}
+
+
+/* Asynchronous version of gpgme_op_receive_keys. */
+gpgme_error_t
+gpgme_op_receive_keys_start (gpgme_ctx_t ctx, const char *keyids[])
+{
+ gpgme_error_t err;
+
+ TRACE_BEG (DEBUG_CTX, "gpgme_op_receive_keys_start", ctx, "");
+
+ if (!ctx)
+ return TRACE_ERR (gpg_error (GPG_ERR_INV_VALUE));
+
+ if (_gpgme_debug_trace () && keyids)
+ {
+ int i = 0;
+
+ while (keyids[i] && *keyids[i])
+ {
+ TRACE_LOG ("keyids[%i] = %s", i, keyids[i]);
+ i++;
+ }
+ }
+
+ err = _gpgme_op_receive_keys_start (ctx, 1, keyids);
+ return TRACE_ERR (err);
+}
+
+
+/* Retrieve the keys from the array KEYIDS from a keyserver and import
+ them into the keyring.
+
+ KEYIDS is a NULL terminated array of . The result
+ is the usual import result structure. */
+gpgme_error_t
+gpgme_op_receive_keys (gpgme_ctx_t ctx, const char *keyids[])
+{
+ gpgme_error_t err;
+
+ TRACE_BEG (DEBUG_CTX, "gpgme_op_receive_keys", ctx, "");
+
+ if (!ctx)
+ return TRACE_ERR (gpg_error (GPG_ERR_INV_VALUE));
+
+ if (_gpgme_debug_trace () && keyids)
+ {
+ int i = 0;
+
+ while (keyids[i] && *keyids[i])
+ {
+ TRACE_LOG ("keyids[%i] = %s", i, keyids[i]);
+ i++;
+ }
+ }
+
+ err = _gpgme_op_receive_keys_start (ctx, 1, keyids);
+ if (!err)
+ err = _gpgme_wait_one (ctx);
+ return TRACE_ERR (err);
+}
+
+
/* Deprecated interface. */
gpgme_error_t
gpgme_op_import_ext (gpgme_ctx_t ctx, gpgme_data_t keydata, int *nr)
diff --git a/src/libgpgme.vers b/src/libgpgme.vers
index 8e86e4e..86d2a5d 100644
--- a/src/libgpgme.vers
+++ b/src/libgpgme.vers
@@ -279,6 +279,9 @@ GPGME_1.0 {
gpgme_op_revsig;
gpgme_op_revsig_start;
+ gpgme_op_receive_keys;
+ gpgme_op_receive_keys_start;
+
local:
*;
diff --git a/src/posix-io.c b/src/posix-io.c
index e712ef2..5c6cf1d 100644
--- a/src/posix-io.c
+++ b/src/posix-io.c
@@ -570,7 +570,7 @@ _gpgme_io_spawn (const char *path, char *const argv[], unsigned int flags,
if (fd_list[i].fd > fd)
fd = fd_list[i].fd;
fd++;
-#if defined(__sun) || defined(__FreeBSD__)
+#if defined(__sun) || defined(__FreeBSD__) || defined(__GLIBC__)
closefrom (fd);
max_fds = fd;
#else /*!__sun */
@@ -691,8 +691,119 @@ _gpgme_io_spawn (const char *path, char *const argv[], unsigned int flags,
/* Select on the list of fds. Returns: -1 = error, 0 = timeout or
nothing to select, > 0 = number of signaled fds. */
-int
-_gpgme_io_select (struct io_select_fd_s *fds, size_t nfds, int nonblock)
+#ifdef HAVE_POLL_H
+static int
+_gpgme_io_select_poll (struct io_select_fd_s *fds, size_t nfds, int nonblock)
+{
+ struct pollfd *poll_fds = NULL;
+ nfds_t poll_nfds;
+ /* Use a 1s timeout. */
+ int timeout = 1000;
+ unsigned int i;
+ int any;
+ int count;
+ void *dbg_help = NULL;
+ TRACE_BEG (DEBUG_SYSIO, "_gpgme_io_select", NULL,
+ "nfds=%zu, nonblock=%u", nfds, nonblock);
+
+
+ if (nonblock)
+ timeout = 0;
+
+ poll_fds = malloc (sizeof (*poll_fds)*nfds);
+ if (!poll_fds)
+ return -1;
+
+ poll_nfds = 0;
+
+ TRACE_SEQ (dbg_help, "poll on [ ");
+
+ any = 0;
+ for (i = 0; i < nfds; i++)
+ {
+ if (fds[i].fd == -1)
+ continue;
+ if (fds[i].for_read || fds[i].for_write)
+ {
+ poll_fds[poll_nfds].fd = fds[i].fd;
+ poll_fds[poll_nfds].events = 0;
+ poll_fds[poll_nfds].revents = 0;
+ if (fds[i].for_read)
+ {
+ poll_fds[poll_nfds].events |= POLLIN;
+ TRACE_ADD1 (dbg_help, "r=%d ", fds[i].fd);
+ }
+ if (fds[i].for_write)
+ {
+ poll_fds[poll_nfds].events |= POLLOUT;
+ TRACE_ADD1 (dbg_help, "w=%d ", fds[i].fd);
+ }
+ poll_nfds++;
+ any = 1;
+ }
+ fds[i].signaled = 0;
+ }
+ TRACE_END (dbg_help, "]");
+ if (!any)
+ {
+ free (poll_fds);
+ return TRACE_SYSRES (0);
+ }
+
+ do
+ count = poll (poll_fds, poll_nfds, timeout);
+ while (count < 0 && (errno == EINTR || errno == EAGAIN));
+ if (count < 0)
+ {
+ int save_errno = errno;
+ free (poll_fds);
+ errno = save_errno;
+ return TRACE_SYSRES (-1);
+ }
+
+ TRACE_SEQ (dbg_help, "poll OK [ ");
+ if (TRACE_ENABLED (dbg_help))
+ {
+ poll_nfds = 0;
+ for (i = 0; i < nfds; i++)
+ {
+ if (fds[i].fd == -1)
+ continue;
+ if ((poll_fds[poll_nfds].revents & (POLLIN|POLLHUP)))
+ TRACE_ADD1 (dbg_help, "r=%d ", i);
+ if ((poll_fds[poll_nfds].revents & POLLOUT))
+ TRACE_ADD1 (dbg_help, "w=%d ", i);
+ poll_nfds++;
+ }
+ TRACE_END (dbg_help, "]");
+ }
+
+ poll_nfds = 0;
+ for (i = 0; i < nfds; i++)
+ {
+ if (fds[i].fd == -1)
+ continue;
+ if (fds[i].for_read || fds[i].for_write)
+ {
+ short events_to_be_checked = 0;
+
+ if (fds[i].for_read)
+ events_to_be_checked |= (POLLIN|POLLHUP);
+ if (fds[i].for_write)
+ events_to_be_checked |= POLLOUT;
+ if ((poll_fds[poll_nfds].revents & events_to_be_checked))
+ fds[i].signaled = 1;
+
+ poll_nfds++;
+ }
+ }
+
+ free (poll_fds);
+ return TRACE_SYSRES (count);
+}
+#else
+static int
+_gpgme_io_select_select (struct io_select_fd_s *fds, size_t nfds, int nonblock)
{
fd_set readfds;
fd_set writefds;
@@ -802,7 +913,17 @@ _gpgme_io_select (struct io_select_fd_s *fds, size_t nfds, int nonblock)
}
return TRACE_SYSRES (count);
}
+#endif
+int
+_gpgme_io_select (struct io_select_fd_s *fds, size_t nfds, int nonblock)
+{
+#ifdef HAVE_POLL_H
+ return _gpgme_io_select_poll (fds, nfds, nonblock);
+#else
+ return _gpgme_io_select_select (fds, nfds, nonblock);
+#endif
+}
int
_gpgme_io_recvmsg (int fd, struct msghdr *msg, int flags)
diff --git a/src/w32-util.c b/src/w32-util.c
index 2631ae7..e4757a2 100644
--- a/src/w32-util.c
+++ b/src/w32-util.c
@@ -841,16 +841,17 @@ _gpgme_access (const char *path, int mode)
/* Like CreateProcessA but mapping the arguments to wchar API */
-int _gpgme_create_process_utf8 (const char *application_name_utf8,
- char *command_line_utf8,
- LPSECURITY_ATTRIBUTES lpProcessAttributes,
- LPSECURITY_ATTRIBUTES lpThreadAttributes,
- BOOL bInheritHandles,
- DWORD dwCreationFlags,
- void *lpEnvironment,
- char *working_directory_utf8,
- LPSTARTUPINFOA si,
- LPPROCESS_INFORMATION lpProcessInformation)
+int
+_gpgme_create_process_utf8 (const char *application_name_utf8,
+ char *command_line_utf8,
+ LPSECURITY_ATTRIBUTES lpProcessAttributes,
+ LPSECURITY_ATTRIBUTES lpThreadAttributes,
+ BOOL bInheritHandles,
+ DWORD dwCreationFlags,
+ void *lpEnvironment,
+ char *working_directory_utf8,
+ LPSTARTUPINFOA si,
+ LPPROCESS_INFORMATION lpProcessInformation)
{
BOOL ret;
wchar_t *application_name = utf8_to_wchar0 (application_name_utf8);
diff --git a/tests/Makefile.am b/tests/Makefile.am
index 8950e96..99b6fb4 100644
--- a/tests/Makefile.am
+++ b/tests/Makefile.am
@@ -28,17 +28,25 @@ TESTS = t-version t-data t-engine-info
EXTRA_DIST = start-stop-agent t-data-1.txt t-data-2.txt ChangeLog-2011
AM_CPPFLAGS = -I$(top_builddir)/src @GPG_ERROR_CFLAGS@
+
+if HAVE_W32_SYSTEM
+AM_LDFLAGS = -no-fast-install
+else
AM_LDFLAGS = -no-install
+endif
+
LDADD = ../src/libgpgme.la @GPG_ERROR_LIBS@ @LDADD_FOR_TESTS_KLUDGE@
noinst_HEADERS = run-support.h
noinst_PROGRAMS = $(TESTS) run-keylist run-export run-import run-sign \
run-verify run-encrypt run-identify run-decrypt run-genkey \
- run-keysign run-tofu run-swdb run-threaded
+ run-keysign run-tofu run-swdb run-threaded \
+ run-receive-keys
-run_threaded_LDADD = ../src/libgpgme.la -lpthread @GPG_ERROR_LIBS@ \
- @LDADD_FOR_TESTS_KLUDGE@
+run_threaded_CPPFLAGS = -I$(top_builddir)/src @GPG_ERROR_MT_CFLAGS@
+run_threaded_LDADD = ../src/libgpgme.la \
+ @GPG_ERROR_MT_LIBS@ @LDADD_FOR_TESTS_KLUDGE@
if RUN_GPG_TESTS
gpgtests = gpg json
diff --git a/tests/Makefile.in b/tests/Makefile.in
index abf1aae..2eeeb6c 100644
--- a/tests/Makefile.in
+++ b/tests/Makefile.in
@@ -114,7 +114,8 @@ noinst_PROGRAMS = $(am__EXEEXT_1) run-keylist$(EXEEXT) \
run-export$(EXEEXT) run-import$(EXEEXT) run-sign$(EXEEXT) \
run-verify$(EXEEXT) run-encrypt$(EXEEXT) run-identify$(EXEEXT) \
run-decrypt$(EXEEXT) run-genkey$(EXEEXT) run-keysign$(EXEEXT) \
- run-tofu$(EXEEXT) run-swdb$(EXEEXT) run-threaded$(EXEEXT)
+ run-tofu$(EXEEXT) run-swdb$(EXEEXT) run-threaded$(EXEEXT) \
+ run-receive-keys$(EXEEXT)
subdir = tests
ACLOCAL_M4 = $(top_srcdir)/aclocal.m4
am__aclocal_m4_deps = $(top_srcdir)/m4/ax_cxx_compile_stdcxx.m4 \
@@ -175,6 +176,10 @@ run_keysign_SOURCES = run-keysign.c
run_keysign_OBJECTS = run-keysign.$(OBJEXT)
run_keysign_LDADD = $(LDADD)
run_keysign_DEPENDENCIES = ../src/libgpgme.la
+run_receive_keys_SOURCES = run-receive-keys.c
+run_receive_keys_OBJECTS = run-receive-keys.$(OBJEXT)
+run_receive_keys_LDADD = $(LDADD)
+run_receive_keys_DEPENDENCIES = ../src/libgpgme.la
run_sign_SOURCES = run-sign.c
run_sign_OBJECTS = run-sign.$(OBJEXT)
run_sign_LDADD = $(LDADD)
@@ -184,7 +189,7 @@ run_swdb_OBJECTS = run-swdb.$(OBJEXT)
run_swdb_LDADD = $(LDADD)
run_swdb_DEPENDENCIES = ../src/libgpgme.la
run_threaded_SOURCES = run-threaded.c
-run_threaded_OBJECTS = run-threaded.$(OBJEXT)
+run_threaded_OBJECTS = run_threaded-run-threaded.$(OBJEXT)
run_threaded_DEPENDENCIES = ../src/libgpgme.la
run_tofu_SOURCES = run-tofu.c
run_tofu_OBJECTS = run-tofu.$(OBJEXT)
@@ -225,11 +230,11 @@ am__depfiles_remade = ./$(DEPDIR)/run-decrypt.Po \
./$(DEPDIR)/run-encrypt.Po ./$(DEPDIR)/run-export.Po \
./$(DEPDIR)/run-genkey.Po ./$(DEPDIR)/run-identify.Po \
./$(DEPDIR)/run-import.Po ./$(DEPDIR)/run-keylist.Po \
- ./$(DEPDIR)/run-keysign.Po ./$(DEPDIR)/run-sign.Po \
- ./$(DEPDIR)/run-swdb.Po ./$(DEPDIR)/run-threaded.Po \
+ ./$(DEPDIR)/run-keysign.Po ./$(DEPDIR)/run-receive-keys.Po \
+ ./$(DEPDIR)/run-sign.Po ./$(DEPDIR)/run-swdb.Po \
./$(DEPDIR)/run-tofu.Po ./$(DEPDIR)/run-verify.Po \
- ./$(DEPDIR)/t-data.Po ./$(DEPDIR)/t-engine-info.Po \
- ./$(DEPDIR)/t-version.Po
+ ./$(DEPDIR)/run_threaded-run-threaded.Po ./$(DEPDIR)/t-data.Po \
+ ./$(DEPDIR)/t-engine-info.Po ./$(DEPDIR)/t-version.Po
am__mv = mv -f
COMPILE = $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) \
$(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS)
@@ -251,12 +256,12 @@ am__v_CCLD_0 = @echo " CCLD " $@;
am__v_CCLD_1 =
SOURCES = run-decrypt.c run-encrypt.c run-export.c run-genkey.c \
run-identify.c run-import.c run-keylist.c run-keysign.c \
- run-sign.c run-swdb.c run-threaded.c run-tofu.c run-verify.c \
- t-data.c t-engine-info.c t-version.c
+ run-receive-keys.c run-sign.c run-swdb.c run-threaded.c \
+ run-tofu.c run-verify.c t-data.c t-engine-info.c t-version.c
DIST_SOURCES = run-decrypt.c run-encrypt.c run-export.c run-genkey.c \
run-identify.c run-import.c run-keylist.c run-keysign.c \
- run-sign.c run-swdb.c run-threaded.c run-tofu.c run-verify.c \
- t-data.c t-engine-info.c t-version.c
+ run-receive-keys.c run-sign.c run-swdb.c run-threaded.c \
+ run-tofu.c run-verify.c t-data.c t-engine-info.c t-version.c
RECURSIVE_TARGETS = all-recursive check-recursive cscopelist-recursive \
ctags-recursive dvi-recursive html-recursive info-recursive \
install-data-recursive install-dvi-recursive \
@@ -552,11 +557,13 @@ GNUPGHOME = $(abs_builddir)
TESTS_ENVIRONMENT = GNUPGHOME=$(GNUPGHOME)
EXTRA_DIST = start-stop-agent t-data-1.txt t-data-2.txt ChangeLog-2011
AM_CPPFLAGS = -I$(top_builddir)/src @GPG_ERROR_CFLAGS@
-AM_LDFLAGS = -no-install
+@HAVE_W32_SYSTEM_FALSE@AM_LDFLAGS = -no-install
+@HAVE_W32_SYSTEM_TRUE@AM_LDFLAGS = -no-fast-install
LDADD = ../src/libgpgme.la @GPG_ERROR_LIBS@ @LDADD_FOR_TESTS_KLUDGE@
noinst_HEADERS = run-support.h
-run_threaded_LDADD = ../src/libgpgme.la -lpthread @GPG_ERROR_LIBS@ \
- @LDADD_FOR_TESTS_KLUDGE@
+run_threaded_CPPFLAGS = -I$(top_builddir)/src @GPG_ERROR_MT_CFLAGS@
+run_threaded_LDADD = ../src/libgpgme.la \
+ @GPG_ERROR_MT_LIBS@ @LDADD_FOR_TESTS_KLUDGE@
@RUN_GPG_TESTS_FALSE@gpgtests =
@RUN_GPG_TESTS_TRUE@gpgtests = gpg json
@@ -638,6 +645,10 @@ run-keysign$(EXEEXT): $(run_keysign_OBJECTS) $(run_keysign_DEPENDENCIES) $(EXTRA
@rm -f run-keysign$(EXEEXT)
$(AM_V_CCLD)$(LINK) $(run_keysign_OBJECTS) $(run_keysign_LDADD) $(LIBS)
+run-receive-keys$(EXEEXT): $(run_receive_keys_OBJECTS) $(run_receive_keys_DEPENDENCIES) $(EXTRA_run_receive_keys_DEPENDENCIES)
+ @rm -f run-receive-keys$(EXEEXT)
+ $(AM_V_CCLD)$(LINK) $(run_receive_keys_OBJECTS) $(run_receive_keys_LDADD) $(LIBS)
+
run-sign$(EXEEXT): $(run_sign_OBJECTS) $(run_sign_DEPENDENCIES) $(EXTRA_run_sign_DEPENDENCIES)
@rm -f run-sign$(EXEEXT)
$(AM_V_CCLD)$(LINK) $(run_sign_OBJECTS) $(run_sign_LDADD) $(LIBS)
@@ -684,11 +695,12 @@ distclean-compile:
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/run-import.Po@am__quote@ # am--include-marker
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/run-keylist.Po@am__quote@ # am--include-marker
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/run-keysign.Po@am__quote@ # am--include-marker
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/run-receive-keys.Po@am__quote@ # am--include-marker
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/run-sign.Po@am__quote@ # am--include-marker
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/run-swdb.Po@am__quote@ # am--include-marker
-@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/run-threaded.Po@am__quote@ # am--include-marker
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/run-tofu.Po@am__quote@ # am--include-marker
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/run-verify.Po@am__quote@ # am--include-marker
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/run_threaded-run-threaded.Po@am__quote@ # am--include-marker
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/t-data.Po@am__quote@ # am--include-marker
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/t-engine-info.Po@am__quote@ # am--include-marker
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/t-version.Po@am__quote@ # am--include-marker
@@ -720,6 +732,20 @@ am--depfiles: $(am__depfiles_remade)
@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LTCOMPILE) -c -o $@ $<
+run_threaded-run-threaded.o: run-threaded.c
+@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(run_threaded_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT run_threaded-run-threaded.o -MD -MP -MF $(DEPDIR)/run_threaded-run-threaded.Tpo -c -o run_threaded-run-threaded.o `test -f 'run-threaded.c' || echo '$(srcdir)/'`run-threaded.c
+@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/run_threaded-run-threaded.Tpo $(DEPDIR)/run_threaded-run-threaded.Po
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='run-threaded.c' object='run_threaded-run-threaded.o' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(run_threaded_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o run_threaded-run-threaded.o `test -f 'run-threaded.c' || echo '$(srcdir)/'`run-threaded.c
+
+run_threaded-run-threaded.obj: run-threaded.c
+@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(run_threaded_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT run_threaded-run-threaded.obj -MD -MP -MF $(DEPDIR)/run_threaded-run-threaded.Tpo -c -o run_threaded-run-threaded.obj `if test -f 'run-threaded.c'; then $(CYGPATH_W) 'run-threaded.c'; else $(CYGPATH_W) '$(srcdir)/run-threaded.c'; fi`
+@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/run_threaded-run-threaded.Tpo $(DEPDIR)/run_threaded-run-threaded.Po
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='run-threaded.c' object='run_threaded-run-threaded.obj' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(run_threaded_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o run_threaded-run-threaded.obj `if test -f 'run-threaded.c'; then $(CYGPATH_W) 'run-threaded.c'; else $(CYGPATH_W) '$(srcdir)/run-threaded.c'; fi`
+
mostlyclean-libtool:
-rm -f *.lo
@@ -1026,11 +1052,12 @@ distclean: distclean-recursive
-rm -f ./$(DEPDIR)/run-import.Po
-rm -f ./$(DEPDIR)/run-keylist.Po
-rm -f ./$(DEPDIR)/run-keysign.Po
+ -rm -f ./$(DEPDIR)/run-receive-keys.Po
-rm -f ./$(DEPDIR)/run-sign.Po
-rm -f ./$(DEPDIR)/run-swdb.Po
- -rm -f ./$(DEPDIR)/run-threaded.Po
-rm -f ./$(DEPDIR)/run-tofu.Po
-rm -f ./$(DEPDIR)/run-verify.Po
+ -rm -f ./$(DEPDIR)/run_threaded-run-threaded.Po
-rm -f ./$(DEPDIR)/t-data.Po
-rm -f ./$(DEPDIR)/t-engine-info.Po
-rm -f ./$(DEPDIR)/t-version.Po
@@ -1087,11 +1114,12 @@ maintainer-clean: maintainer-clean-recursive
-rm -f ./$(DEPDIR)/run-import.Po
-rm -f ./$(DEPDIR)/run-keylist.Po
-rm -f ./$(DEPDIR)/run-keysign.Po
+ -rm -f ./$(DEPDIR)/run-receive-keys.Po
-rm -f ./$(DEPDIR)/run-sign.Po
-rm -f ./$(DEPDIR)/run-swdb.Po
- -rm -f ./$(DEPDIR)/run-threaded.Po
-rm -f ./$(DEPDIR)/run-tofu.Po
-rm -f ./$(DEPDIR)/run-verify.Po
+ -rm -f ./$(DEPDIR)/run_threaded-run-threaded.Po
-rm -f ./$(DEPDIR)/t-data.Po
-rm -f ./$(DEPDIR)/t-engine-info.Po
-rm -f ./$(DEPDIR)/t-version.Po
diff --git a/tests/gpg/Makefile.am b/tests/gpg/Makefile.am
index d24a312..6d99539 100644
--- a/tests/gpg/Makefile.am
+++ b/tests/gpg/Makefile.am
@@ -38,8 +38,8 @@ endif
c_tests = \
t-encrypt t-encrypt-sym t-encrypt-sign t-sign t-signers \
t-decrypt t-verify t-decrypt-verify t-sig-notation t-export \
- t-import t-edit t-keylist t-keylist-sig t-keylist-secret-sig t-wait \
- t-encrypt-large t-file-name t-gpgconf t-encrypt-mixed t-edit-sign \
+ t-import t-edit t-keylist t-keylist-sig t-keylist-secret-sig t-wait \
+ t-encrypt-large t-file-name t-gpgconf t-encrypt-mixed t-edit-sign \
$(tests_unix)
TESTS = initial.test $(c_tests) final.test
@@ -60,17 +60,26 @@ private_keys = \
EXTRA_DIST = initial.test final.test \
pubdemo.asc secdemo.asc cipher-1.asc cipher-2.asc \
cipher-3.asc cipher-no-sig.asc \
- geheim.txt pubkey-1.asc seckey-1.asc pinentry $(private_keys)
+ geheim.txt pubkey-1.asc seckey-1.asc pinentry $(private_keys) \
+ gpg.conf.in
BUILT_SOURCES = gpg.conf gpg-agent.conf pubring-stamp \
gpg-sample.stamp
AM_CPPFLAGS = -I$(top_builddir)/src @GPG_ERROR_CFLAGS@
AM_LDFLAGS = -no-install
LDADD = ../../src/libgpgme.la @LDADD_FOR_TESTS_KLUDGE@
-t_thread1_LDADD = ../../src/libgpgme.la -lpthread @LDADD_FOR_TESTS_KLUDGE@
-t_thread_keylist_LDADD = ../../src/libgpgme.la -lpthread @LDADD_FOR_TESTS_KLUDGE@
-t_thread_keylist_verify_LDADD = ../../src/libgpgme.la -lpthread @LDADD_FOR_TESTS_KLUDGE@
-t_cancel_LDADD = ../../src/libgpgme.la -lpthread @LDADD_FOR_TESTS_KLUDGE@
+
+WITH_THREAD_CPPFLAGS = -I$(top_builddir)/src @GPG_ERROR_MT_CFLAGS@
+WITH_THREAD_LDADD = ../../src/libgpgme.la \
+ @GPG_ERROR_MT_LIBS@ @LDADD_FOR_TESTS_KLUDGE@
+t_thread1_CPPFLAGS = $(WITH_THREAD_CPPFLAGS)
+t_thread1_LDADD = $(WITH_THREAD_LDADD)
+t_thread_keylist_CPPFLAGS = $(WITH_THREAD_CPPFLAGS)
+t_thread_keylist_LDADD = $(WITH_THREAD_LDADD)
+t_thread_keylist_verify_CPPFLAGS = $(WITH_THREAD_CPPFLAGS)
+t_thread_keylist_verify_LDADD = $(WITH_THREAD_LDADD)
+t_cancel_CPPFLAGS = $(WITH_THREAD_CPPFLAGS)
+t_cancel_LDADD = $(WITH_THREAD_LDADD)
# We don't run t-genkey and t-cancel in the test suite, because it
# takes too long
@@ -101,11 +110,8 @@ pubring-stamp: $(srcdir)/pubdemo.asc gpg-sample.stamp
--import $(srcdir)/secdemo.asc
echo x > ./pubring-stamp
-gpg.conf:
-# This is required for t-sig-notations.
- echo no-force-v3-sigs > ./gpg.conf
-# This is required for t-edit-sign.
- echo allow-weak-key-signatures >> ./gpg.conf
+gpg.conf: $(srcdir)/gpg.conf.in
+ cp $(srcdir)/gpg.conf.in gpg.conf
gpg-agent.conf:
# This is required for gpg2, which does not support command fd for the
diff --git a/tests/gpg/Makefile.in b/tests/gpg/Makefile.in
index 9fcd92b..f24fffa 100644
--- a/tests/gpg/Makefile.in
+++ b/tests/gpg/Makefile.in
@@ -149,8 +149,9 @@ am__EXEEXT_2 = t-encrypt$(EXEEXT) t-encrypt-sym$(EXEEXT) \
am__EXEEXT_4 = t-genkey$(EXEEXT) $(am__EXEEXT_3)
PROGRAMS = $(noinst_PROGRAMS)
t_cancel_SOURCES = t-cancel.c
-t_cancel_OBJECTS = t-cancel.$(OBJEXT)
-t_cancel_DEPENDENCIES = ../../src/libgpgme.la
+t_cancel_OBJECTS = t_cancel-t-cancel.$(OBJEXT)
+am__DEPENDENCIES_1 = ../../src/libgpgme.la
+t_cancel_DEPENDENCIES = $(am__DEPENDENCIES_1)
AM_V_lt = $(am__v_lt_@AM_V@)
am__v_lt_ = $(am__v_lt_@AM_DEFAULT_V@)
am__v_lt_0 = --silent
@@ -240,14 +241,16 @@ t_signers_OBJECTS = t-signers.$(OBJEXT)
t_signers_LDADD = $(LDADD)
t_signers_DEPENDENCIES = ../../src/libgpgme.la
t_thread_keylist_SOURCES = t-thread-keylist.c
-t_thread_keylist_OBJECTS = t-thread-keylist.$(OBJEXT)
-t_thread_keylist_DEPENDENCIES = ../../src/libgpgme.la
+t_thread_keylist_OBJECTS = \
+ t_thread_keylist-t-thread-keylist.$(OBJEXT)
+t_thread_keylist_DEPENDENCIES = $(am__DEPENDENCIES_1)
t_thread_keylist_verify_SOURCES = t-thread-keylist-verify.c
-t_thread_keylist_verify_OBJECTS = t-thread-keylist-verify.$(OBJEXT)
-t_thread_keylist_verify_DEPENDENCIES = ../../src/libgpgme.la
+t_thread_keylist_verify_OBJECTS = \
+ t_thread_keylist_verify-t-thread-keylist-verify.$(OBJEXT)
+t_thread_keylist_verify_DEPENDENCIES = $(am__DEPENDENCIES_1)
t_thread1_SOURCES = t-thread1.c
-t_thread1_OBJECTS = t-thread1.$(OBJEXT)
-t_thread1_DEPENDENCIES = ../../src/libgpgme.la
+t_thread1_OBJECTS = t_thread1-t-thread1.$(OBJEXT)
+t_thread1_DEPENDENCIES = $(am__DEPENDENCIES_1)
t_verify_SOURCES = t-verify.c
t_verify_OBJECTS = t-verify.$(OBJEXT)
t_verify_LDADD = $(LDADD)
@@ -271,21 +274,22 @@ am__v_at_1 =
DEFAULT_INCLUDES = -I.@am__isrc@ -I$(top_builddir)/conf
depcomp = $(SHELL) $(top_srcdir)/build-aux/depcomp
am__maybe_remake_depfiles = depfiles
-am__depfiles_remade = ./$(DEPDIR)/t-cancel.Po \
- ./$(DEPDIR)/t-decrypt-verify.Po ./$(DEPDIR)/t-decrypt.Po \
- ./$(DEPDIR)/t-edit-sign.Po ./$(DEPDIR)/t-edit.Po \
- ./$(DEPDIR)/t-encrypt-large.Po ./$(DEPDIR)/t-encrypt-mixed.Po \
- ./$(DEPDIR)/t-encrypt-sign.Po ./$(DEPDIR)/t-encrypt-sym.Po \
- ./$(DEPDIR)/t-encrypt.Po ./$(DEPDIR)/t-eventloop.Po \
- ./$(DEPDIR)/t-export.Po ./$(DEPDIR)/t-file-name.Po \
- ./$(DEPDIR)/t-genkey.Po ./$(DEPDIR)/t-gpgconf.Po \
- ./$(DEPDIR)/t-import.Po ./$(DEPDIR)/t-keylist-secret-sig.Po \
+am__depfiles_remade = ./$(DEPDIR)/t-decrypt-verify.Po \
+ ./$(DEPDIR)/t-decrypt.Po ./$(DEPDIR)/t-edit-sign.Po \
+ ./$(DEPDIR)/t-edit.Po ./$(DEPDIR)/t-encrypt-large.Po \
+ ./$(DEPDIR)/t-encrypt-mixed.Po ./$(DEPDIR)/t-encrypt-sign.Po \
+ ./$(DEPDIR)/t-encrypt-sym.Po ./$(DEPDIR)/t-encrypt.Po \
+ ./$(DEPDIR)/t-eventloop.Po ./$(DEPDIR)/t-export.Po \
+ ./$(DEPDIR)/t-file-name.Po ./$(DEPDIR)/t-genkey.Po \
+ ./$(DEPDIR)/t-gpgconf.Po ./$(DEPDIR)/t-import.Po \
+ ./$(DEPDIR)/t-keylist-secret-sig.Po \
./$(DEPDIR)/t-keylist-sig.Po ./$(DEPDIR)/t-keylist.Po \
./$(DEPDIR)/t-sig-notation.Po ./$(DEPDIR)/t-sign.Po \
- ./$(DEPDIR)/t-signers.Po \
- ./$(DEPDIR)/t-thread-keylist-verify.Po \
- ./$(DEPDIR)/t-thread-keylist.Po ./$(DEPDIR)/t-thread1.Po \
- ./$(DEPDIR)/t-verify.Po ./$(DEPDIR)/t-wait.Po
+ ./$(DEPDIR)/t-signers.Po ./$(DEPDIR)/t-verify.Po \
+ ./$(DEPDIR)/t-wait.Po ./$(DEPDIR)/t_cancel-t-cancel.Po \
+ ./$(DEPDIR)/t_thread1-t-thread1.Po \
+ ./$(DEPDIR)/t_thread_keylist-t-thread-keylist.Po \
+ ./$(DEPDIR)/t_thread_keylist_verify-t-thread-keylist-verify.Po
am__mv = mv -f
COMPILE = $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) \
$(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS)
@@ -582,8 +586,8 @@ noinst_HEADERS = t-support.h
c_tests = \
t-encrypt t-encrypt-sym t-encrypt-sign t-sign t-signers \
t-decrypt t-verify t-decrypt-verify t-sig-notation t-export \
- t-import t-edit t-keylist t-keylist-sig t-keylist-secret-sig t-wait \
- t-encrypt-large t-file-name t-gpgconf t-encrypt-mixed t-edit-sign \
+ t-import t-edit t-keylist t-keylist-sig t-keylist-secret-sig t-wait \
+ t-encrypt-large t-file-name t-gpgconf t-encrypt-mixed t-edit-sign \
$(tests_unix)
CLEANFILES = secring.gpg pubring.gpg pubring.kbx trustdb.gpg dirmngr.conf \
@@ -601,7 +605,8 @@ private_keys = \
EXTRA_DIST = initial.test final.test \
pubdemo.asc secdemo.asc cipher-1.asc cipher-2.asc \
cipher-3.asc cipher-no-sig.asc \
- geheim.txt pubkey-1.asc seckey-1.asc pinentry $(private_keys)
+ geheim.txt pubkey-1.asc seckey-1.asc pinentry $(private_keys) \
+ gpg.conf.in
BUILT_SOURCES = gpg.conf gpg-agent.conf pubring-stamp \
gpg-sample.stamp
@@ -609,10 +614,18 @@ BUILT_SOURCES = gpg.conf gpg-agent.conf pubring-stamp \
AM_CPPFLAGS = -I$(top_builddir)/src @GPG_ERROR_CFLAGS@
AM_LDFLAGS = -no-install
LDADD = ../../src/libgpgme.la @LDADD_FOR_TESTS_KLUDGE@
-t_thread1_LDADD = ../../src/libgpgme.la -lpthread @LDADD_FOR_TESTS_KLUDGE@
-t_thread_keylist_LDADD = ../../src/libgpgme.la -lpthread @LDADD_FOR_TESTS_KLUDGE@
-t_thread_keylist_verify_LDADD = ../../src/libgpgme.la -lpthread @LDADD_FOR_TESTS_KLUDGE@
-t_cancel_LDADD = ../../src/libgpgme.la -lpthread @LDADD_FOR_TESTS_KLUDGE@
+WITH_THREAD_CPPFLAGS = -I$(top_builddir)/src @GPG_ERROR_MT_CFLAGS@
+WITH_THREAD_LDADD = ../../src/libgpgme.la \
+ @GPG_ERROR_MT_LIBS@ @LDADD_FOR_TESTS_KLUDGE@
+
+t_thread1_CPPFLAGS = $(WITH_THREAD_CPPFLAGS)
+t_thread1_LDADD = $(WITH_THREAD_LDADD)
+t_thread_keylist_CPPFLAGS = $(WITH_THREAD_CPPFLAGS)
+t_thread_keylist_LDADD = $(WITH_THREAD_LDADD)
+t_thread_keylist_verify_CPPFLAGS = $(WITH_THREAD_CPPFLAGS)
+t_thread_keylist_verify_LDADD = $(WITH_THREAD_LDADD)
+t_cancel_CPPFLAGS = $(WITH_THREAD_CPPFLAGS)
+t_cancel_LDADD = $(WITH_THREAD_LDADD)
# We don't run t-genkey and t-cancel in the test suite, because it
# takes too long
@@ -775,7 +788,6 @@ mostlyclean-compile:
distclean-compile:
-rm -f *.tab.c
-@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/t-cancel.Po@am__quote@ # am--include-marker
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/t-decrypt-verify.Po@am__quote@ # am--include-marker
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/t-decrypt.Po@am__quote@ # am--include-marker
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/t-edit-sign.Po@am__quote@ # am--include-marker
@@ -797,11 +809,12 @@ distclean-compile:
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/t-sig-notation.Po@am__quote@ # am--include-marker
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/t-sign.Po@am__quote@ # am--include-marker
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/t-signers.Po@am__quote@ # am--include-marker
-@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/t-thread-keylist-verify.Po@am__quote@ # am--include-marker
-@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/t-thread-keylist.Po@am__quote@ # am--include-marker
-@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/t-thread1.Po@am__quote@ # am--include-marker
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/t-verify.Po@am__quote@ # am--include-marker
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/t-wait.Po@am__quote@ # am--include-marker
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/t_cancel-t-cancel.Po@am__quote@ # am--include-marker
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/t_thread1-t-thread1.Po@am__quote@ # am--include-marker
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/t_thread_keylist-t-thread-keylist.Po@am__quote@ # am--include-marker
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/t_thread_keylist_verify-t-thread-keylist-verify.Po@am__quote@ # am--include-marker
$(am__depfiles_remade):
@$(MKDIR_P) $(@D)
@@ -830,6 +843,62 @@ am--depfiles: $(am__depfiles_remade)
@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LTCOMPILE) -c -o $@ $<
+t_cancel-t-cancel.o: t-cancel.c
+@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(t_cancel_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT t_cancel-t-cancel.o -MD -MP -MF $(DEPDIR)/t_cancel-t-cancel.Tpo -c -o t_cancel-t-cancel.o `test -f 't-cancel.c' || echo '$(srcdir)/'`t-cancel.c
+@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/t_cancel-t-cancel.Tpo $(DEPDIR)/t_cancel-t-cancel.Po
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='t-cancel.c' object='t_cancel-t-cancel.o' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(t_cancel_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o t_cancel-t-cancel.o `test -f 't-cancel.c' || echo '$(srcdir)/'`t-cancel.c
+
+t_cancel-t-cancel.obj: t-cancel.c
+@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(t_cancel_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT t_cancel-t-cancel.obj -MD -MP -MF $(DEPDIR)/t_cancel-t-cancel.Tpo -c -o t_cancel-t-cancel.obj `if test -f 't-cancel.c'; then $(CYGPATH_W) 't-cancel.c'; else $(CYGPATH_W) '$(srcdir)/t-cancel.c'; fi`
+@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/t_cancel-t-cancel.Tpo $(DEPDIR)/t_cancel-t-cancel.Po
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='t-cancel.c' object='t_cancel-t-cancel.obj' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(t_cancel_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o t_cancel-t-cancel.obj `if test -f 't-cancel.c'; then $(CYGPATH_W) 't-cancel.c'; else $(CYGPATH_W) '$(srcdir)/t-cancel.c'; fi`
+
+t_thread_keylist-t-thread-keylist.o: t-thread-keylist.c
+@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(t_thread_keylist_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT t_thread_keylist-t-thread-keylist.o -MD -MP -MF $(DEPDIR)/t_thread_keylist-t-thread-keylist.Tpo -c -o t_thread_keylist-t-thread-keylist.o `test -f 't-thread-keylist.c' || echo '$(srcdir)/'`t-thread-keylist.c
+@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/t_thread_keylist-t-thread-keylist.Tpo $(DEPDIR)/t_thread_keylist-t-thread-keylist.Po
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='t-thread-keylist.c' object='t_thread_keylist-t-thread-keylist.o' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(t_thread_keylist_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o t_thread_keylist-t-thread-keylist.o `test -f 't-thread-keylist.c' || echo '$(srcdir)/'`t-thread-keylist.c
+
+t_thread_keylist-t-thread-keylist.obj: t-thread-keylist.c
+@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(t_thread_keylist_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT t_thread_keylist-t-thread-keylist.obj -MD -MP -MF $(DEPDIR)/t_thread_keylist-t-thread-keylist.Tpo -c -o t_thread_keylist-t-thread-keylist.obj `if test -f 't-thread-keylist.c'; then $(CYGPATH_W) 't-thread-keylist.c'; else $(CYGPATH_W) '$(srcdir)/t-thread-keylist.c'; fi`
+@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/t_thread_keylist-t-thread-keylist.Tpo $(DEPDIR)/t_thread_keylist-t-thread-keylist.Po
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='t-thread-keylist.c' object='t_thread_keylist-t-thread-keylist.obj' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(t_thread_keylist_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o t_thread_keylist-t-thread-keylist.obj `if test -f 't-thread-keylist.c'; then $(CYGPATH_W) 't-thread-keylist.c'; else $(CYGPATH_W) '$(srcdir)/t-thread-keylist.c'; fi`
+
+t_thread_keylist_verify-t-thread-keylist-verify.o: t-thread-keylist-verify.c
+@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(t_thread_keylist_verify_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT t_thread_keylist_verify-t-thread-keylist-verify.o -MD -MP -MF $(DEPDIR)/t_thread_keylist_verify-t-thread-keylist-verify.Tpo -c -o t_thread_keylist_verify-t-thread-keylist-verify.o `test -f 't-thread-keylist-verify.c' || echo '$(srcdir)/'`t-thread-keylist-verify.c
+@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/t_thread_keylist_verify-t-thread-keylist-verify.Tpo $(DEPDIR)/t_thread_keylist_verify-t-thread-keylist-verify.Po
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='t-thread-keylist-verify.c' object='t_thread_keylist_verify-t-thread-keylist-verify.o' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(t_thread_keylist_verify_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o t_thread_keylist_verify-t-thread-keylist-verify.o `test -f 't-thread-keylist-verify.c' || echo '$(srcdir)/'`t-thread-keylist-verify.c
+
+t_thread_keylist_verify-t-thread-keylist-verify.obj: t-thread-keylist-verify.c
+@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(t_thread_keylist_verify_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT t_thread_keylist_verify-t-thread-keylist-verify.obj -MD -MP -MF $(DEPDIR)/t_thread_keylist_verify-t-thread-keylist-verify.Tpo -c -o t_thread_keylist_verify-t-thread-keylist-verify.obj `if test -f 't-thread-keylist-verify.c'; then $(CYGPATH_W) 't-thread-keylist-verify.c'; else $(CYGPATH_W) '$(srcdir)/t-thread-keylist-verify.c'; fi`
+@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/t_thread_keylist_verify-t-thread-keylist-verify.Tpo $(DEPDIR)/t_thread_keylist_verify-t-thread-keylist-verify.Po
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='t-thread-keylist-verify.c' object='t_thread_keylist_verify-t-thread-keylist-verify.obj' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(t_thread_keylist_verify_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o t_thread_keylist_verify-t-thread-keylist-verify.obj `if test -f 't-thread-keylist-verify.c'; then $(CYGPATH_W) 't-thread-keylist-verify.c'; else $(CYGPATH_W) '$(srcdir)/t-thread-keylist-verify.c'; fi`
+
+t_thread1-t-thread1.o: t-thread1.c
+@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(t_thread1_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT t_thread1-t-thread1.o -MD -MP -MF $(DEPDIR)/t_thread1-t-thread1.Tpo -c -o t_thread1-t-thread1.o `test -f 't-thread1.c' || echo '$(srcdir)/'`t-thread1.c
+@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/t_thread1-t-thread1.Tpo $(DEPDIR)/t_thread1-t-thread1.Po
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='t-thread1.c' object='t_thread1-t-thread1.o' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(t_thread1_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o t_thread1-t-thread1.o `test -f 't-thread1.c' || echo '$(srcdir)/'`t-thread1.c
+
+t_thread1-t-thread1.obj: t-thread1.c
+@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(t_thread1_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT t_thread1-t-thread1.obj -MD -MP -MF $(DEPDIR)/t_thread1-t-thread1.Tpo -c -o t_thread1-t-thread1.obj `if test -f 't-thread1.c'; then $(CYGPATH_W) 't-thread1.c'; else $(CYGPATH_W) '$(srcdir)/t-thread1.c'; fi`
+@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/t_thread1-t-thread1.Tpo $(DEPDIR)/t_thread1-t-thread1.Po
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='t-thread1.c' object='t_thread1-t-thread1.obj' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(t_thread1_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o t_thread1-t-thread1.obj `if test -f 't-thread1.c'; then $(CYGPATH_W) 't-thread1.c'; else $(CYGPATH_W) '$(srcdir)/t-thread1.c'; fi`
+
mostlyclean-libtool:
-rm -f *.lo
@@ -1060,8 +1129,7 @@ clean-am: clean-generic clean-libtool clean-local clean-noinstPROGRAMS \
mostlyclean-am
distclean: distclean-am
- -rm -f ./$(DEPDIR)/t-cancel.Po
- -rm -f ./$(DEPDIR)/t-decrypt-verify.Po
+ -rm -f ./$(DEPDIR)/t-decrypt-verify.Po
-rm -f ./$(DEPDIR)/t-decrypt.Po
-rm -f ./$(DEPDIR)/t-edit-sign.Po
-rm -f ./$(DEPDIR)/t-edit.Po
@@ -1082,11 +1150,12 @@ distclean: distclean-am
-rm -f ./$(DEPDIR)/t-sig-notation.Po
-rm -f ./$(DEPDIR)/t-sign.Po
-rm -f ./$(DEPDIR)/t-signers.Po
- -rm -f ./$(DEPDIR)/t-thread-keylist-verify.Po
- -rm -f ./$(DEPDIR)/t-thread-keylist.Po
- -rm -f ./$(DEPDIR)/t-thread1.Po
-rm -f ./$(DEPDIR)/t-verify.Po
-rm -f ./$(DEPDIR)/t-wait.Po
+ -rm -f ./$(DEPDIR)/t_cancel-t-cancel.Po
+ -rm -f ./$(DEPDIR)/t_thread1-t-thread1.Po
+ -rm -f ./$(DEPDIR)/t_thread_keylist-t-thread-keylist.Po
+ -rm -f ./$(DEPDIR)/t_thread_keylist_verify-t-thread-keylist-verify.Po
-rm -f Makefile
distclean-am: clean-am distclean-compile distclean-generic \
distclean-tags
@@ -1132,8 +1201,7 @@ install-ps-am:
installcheck-am:
maintainer-clean: maintainer-clean-am
- -rm -f ./$(DEPDIR)/t-cancel.Po
- -rm -f ./$(DEPDIR)/t-decrypt-verify.Po
+ -rm -f ./$(DEPDIR)/t-decrypt-verify.Po
-rm -f ./$(DEPDIR)/t-decrypt.Po
-rm -f ./$(DEPDIR)/t-edit-sign.Po
-rm -f ./$(DEPDIR)/t-edit.Po
@@ -1154,11 +1222,12 @@ maintainer-clean: maintainer-clean-am
-rm -f ./$(DEPDIR)/t-sig-notation.Po
-rm -f ./$(DEPDIR)/t-sign.Po
-rm -f ./$(DEPDIR)/t-signers.Po
- -rm -f ./$(DEPDIR)/t-thread-keylist-verify.Po
- -rm -f ./$(DEPDIR)/t-thread-keylist.Po
- -rm -f ./$(DEPDIR)/t-thread1.Po
-rm -f ./$(DEPDIR)/t-verify.Po
-rm -f ./$(DEPDIR)/t-wait.Po
+ -rm -f ./$(DEPDIR)/t_cancel-t-cancel.Po
+ -rm -f ./$(DEPDIR)/t_thread1-t-thread1.Po
+ -rm -f ./$(DEPDIR)/t_thread_keylist-t-thread-keylist.Po
+ -rm -f ./$(DEPDIR)/t_thread_keylist_verify-t-thread-keylist-verify.Po
-rm -f Makefile
maintainer-clean-am: distclean-am maintainer-clean-generic
@@ -1216,11 +1285,8 @@ pubring-stamp: $(srcdir)/pubdemo.asc gpg-sample.stamp
--import $(srcdir)/secdemo.asc
echo x > ./pubring-stamp
-gpg.conf:
-# This is required for t-sig-notations.
- echo no-force-v3-sigs > ./gpg.conf
-# This is required for t-edit-sign.
- echo allow-weak-key-signatures >> ./gpg.conf
+gpg.conf: $(srcdir)/gpg.conf.in
+ cp $(srcdir)/gpg.conf.in gpg.conf
gpg-agent.conf:
# This is required for gpg2, which does not support command fd for the
diff --git a/tests/gpg/gpg.conf.in b/tests/gpg/gpg.conf.in
new file mode 100644
index 0000000..ab05c17
--- /dev/null
+++ b/tests/gpg/gpg.conf.in
@@ -0,0 +1,5 @@
+# This is required for t-sig-notations.
+no-force-v3-sigs
+
+# This is required for t-edit-sign.
+allow-weak-key-signatures
diff --git a/tests/gpg/t-cancel.c b/tests/gpg/t-cancel.c
index 48158fb..d5fb666 100644
--- a/tests/gpg/t-cancel.c
+++ b/tests/gpg/t-cancel.c
@@ -38,8 +38,16 @@
#include <sys/types.h>
#include <unistd.h>
#include <pthread.h>
-#ifdef HAVE_SYS_SELECT_H
-# include <sys/select.h>
+#ifdef HAVE_POLL_H
+# include <poll.h>
+#else
+# ifdef HAVE_SYS_SELECT_H
+# include <sys/select.h>
+# else
+# ifdef HAVE_SYS_TIME_H
+# include <sys/time.h>
+# endif
+# endif
#endif
#include <gpgme.h>
@@ -116,6 +124,60 @@ io_event (void *data, gpgme_event_io_t type, void *type_data)
}
+#ifdef HAVE_POLL_H
+static int
+do_select (void)
+{
+ struct pollfd poll_fds[FDLIST_MAX];
+ nfds_t poll_nfds;
+ int i, n;
+ int any = 0;
+
+ pthread_mutex_lock (&lock);
+ poll_nfds = 0;
+ for (i = 0; i < FDLIST_MAX; i++)
+ if (fdlist[i].fd != -1)
+ {
+ poll_fds[poll_nfds].fd = fdlist[i].fd;
+ poll_fds[poll_nfds].events = 0;
+ poll_fds[poll_nfds].revents = 0;
+ if (fdlist[i].dir)
+ poll_fds[poll_nfds].events |= POLLIN;
+ else
+ poll_fds[poll_nfds].events |= POLLOUT;
+ poll_nfds++;
+ }
+ pthread_mutex_unlock (&lock);
+
+ do
+ {
+ n = poll (poll_fds, poll_nfds, 1000);
+ }
+ while (n < 0 && (errno == EINTR || errno == EAGAIN));
+
+ if (n < 0)
+ return n; /* Error or timeout. */
+
+ pthread_mutex_lock (&lock);
+ poll_nfds = 0;
+ for (i = 0; i < FDLIST_MAX && n; i++)
+ {
+ if (fdlist[i].fd != -1)
+ {
+ if ((poll_fds[poll_nfds++].revents
+ & (fdlist[i].dir ? (POLLIN|POLLHUP) : POLLOUT)))
+ {
+ assert (n);
+ n--;
+ any = 1;
+ (*fdlist[i].fnc) (fdlist[i].fnc_data, fdlist[i].fd);
+ }
+ }
+ }
+ pthread_mutex_unlock (&lock);
+ return any;
+}
+#else
static int
do_select (void)
{
@@ -162,6 +224,7 @@ do_select (void)
pthread_mutex_unlock (&lock);
return any;
}
+#endif
static int
my_wait (void)
diff --git a/tests/gpg/t-edit-sign.c b/tests/gpg/t-edit-sign.c
index 2f98362..e0494c5 100644
--- a/tests/gpg/t-edit-sign.c
+++ b/tests/gpg/t-edit-sign.c
@@ -107,31 +107,19 @@ interact_fnc (void *opaque, const char *status, const char *args, int fd)
}
-int
-main (int argc, char **argv)
+void
+sign_key (const char *key_fpr, const char *signer_fpr)
{
gpgme_ctx_t ctx;
gpgme_error_t err;
gpgme_data_t out = NULL;
- const char *signer_fpr = "A0FF4590BB6122EDEF6E3C542D727CC768697734"; /* Alpha Test */
gpgme_key_t signing_key = NULL;
- const char *key_fpr = "D695676BDCEDCC2CDD6152BCFE180B1DA9E3B0B2"; /* Bravo Test */
gpgme_key_t key = NULL;
- gpgme_key_t signed_key = NULL;
- gpgme_user_id_t signed_uid = NULL;
- gpgme_key_sig_t key_sig = NULL;
char *agent_info;
- int mode;
-
- (void)argc;
- (void)argv;
-
- init_gpgme (GPGME_PROTOCOL_OpenPGP);
err = gpgme_new (&ctx);
fail_if_err (err);
- /* Sign the key */
agent_info = getenv("GPG_AGENT_INFO");
if (!(agent_info && strchr (agent_info, ':')))
gpgme_set_passphrase_cb (ctx, passphrase_cb, 0);
@@ -159,8 +147,23 @@ main (int argc, char **argv)
gpgme_data_release (out);
gpgme_key_unref (key);
gpgme_key_unref (signing_key);
+ gpgme_release (ctx);
+}
+
+
+void
+verify_key_signature (const char *key_fpr, const char *signer_keyid)
+{
+ gpgme_ctx_t ctx;
+ gpgme_error_t err;
+ gpgme_key_t signed_key = NULL;
+ gpgme_user_id_t signed_uid = NULL;
+ gpgme_key_sig_t key_sig = NULL;
+ int mode;
+
+ err = gpgme_new (&ctx);
+ fail_if_err (err);
- /* Verify the key signature */
mode = gpgme_get_keylist_mode (ctx);
mode |= GPGME_KEYLIST_MODE_SIGS;
err = gpgme_set_keylist_mode (ctx, mode);
@@ -168,7 +171,7 @@ main (int argc, char **argv)
err = gpgme_get_key (ctx, key_fpr, &signed_key, 0);
fail_if_err (err);
- signed_uid = key->uids;
+ signed_uid = signed_key->uids;
if (!signed_uid)
{
fprintf (stderr, "Signed key has no user IDs\n");
@@ -180,7 +183,7 @@ main (int argc, char **argv)
exit (1);
}
key_sig = signed_uid->signatures->next;
- if (strcmp ("2D727CC768697734", key_sig->keyid))
+ if (strcmp (signer_keyid, key_sig->keyid))
{
fprintf (stderr, "Unexpected key ID in second user ID sig: %s\n",
key_sig->keyid);
@@ -196,6 +199,23 @@ main (int argc, char **argv)
gpgme_key_unref (signed_key);
gpgme_release (ctx);
+}
+
+
+int
+main (int argc, char **argv)
+{
+ const char *signer_fpr = "A0FF4590BB6122EDEF6E3C542D727CC768697734"; /* Alpha Test */
+ const char *signer_keyid = signer_fpr + strlen(signer_fpr) - 16;
+ const char *key_fpr = "D695676BDCEDCC2CDD6152BCFE180B1DA9E3B0B2"; /* Bravo Test */
+
+ (void)argc;
+ (void)argv;
+
+ init_gpgme (GPGME_PROTOCOL_OpenPGP);
+
+ sign_key (key_fpr, signer_fpr);
+ verify_key_signature (key_fpr, signer_keyid);
return 0;
}
diff --git a/tests/gpg/t-eventloop.c b/tests/gpg/t-eventloop.c
index b31764e..0106670 100644
--- a/tests/gpg/t-eventloop.c
+++ b/tests/gpg/t-eventloop.c
@@ -31,7 +31,17 @@
#include <assert.h>
#include <errno.h>
#include <sys/types.h>
-#include <sys/select.h>
+#ifdef HAVE_POLL_H
+# include <poll.h>
+#else
+# ifdef HAVE_SYS_SELECT_H
+# include <sys/select.h>
+# else
+# ifdef HAVE_SYS_TIME_H
+# include <sys/time.h>
+# endif
+# endif
+#endif
#include <gpgme.h>
@@ -104,6 +114,56 @@ io_event (void *data, gpgme_event_io_t type, void *type_data)
}
+#ifdef HAVE_POLL_H
+int
+do_select (void)
+{
+ struct pollfd poll_fds[FDLIST_MAX];
+ nfds_t poll_nfds;
+ int i, n;
+ int any = 0;
+
+ poll_nfds = 0;
+ for (i = 0; i < FDLIST_MAX; i++)
+ if (fdlist[i].fd != -1)
+ {
+ poll_fds[poll_nfds].fd = fdlist[i].fd;
+ poll_fds[poll_nfds].events = 0;
+ poll_fds[poll_nfds].revents = 0;
+ if (fdlist[i].dir)
+ poll_fds[poll_nfds].events |= POLLIN;
+ else
+ poll_fds[poll_nfds].events |= POLLOUT;
+ poll_nfds++;
+ }
+
+ do
+ {
+ n = poll (poll_fds, poll_nfds, 1000);
+ }
+ while (n < 0 && (errno == EINTR || errno == EAGAIN));
+
+ if (n < 0)
+ return n; /* Error or timeout. */
+
+ poll_nfds = 0;
+ for (i = 0; i < FDLIST_MAX && n; i++)
+ {
+ if (fdlist[i].fd != -1)
+ {
+ if ((poll_fds[poll_nfds++].revents
+ & (fdlist[i].dir ? (POLLIN|POLLHUP) : POLLOUT)))
+ {
+ assert (n);
+ n--;
+ any = 1;
+ (*fdlist[i].fnc) (fdlist[i].fnc_data, fdlist[i].fd);
+ }
+ }
+ }
+ return any;
+}
+#else
int
do_select (void)
{
@@ -146,6 +206,7 @@ do_select (void)
}
return any;
}
+#endif
int
my_wait (void)
diff --git a/tests/gpg/t-import.c b/tests/gpg/t-import.c
index ae82263..1f7fdbc 100644
--- a/tests/gpg/t-import.c
+++ b/tests/gpg/t-import.c
@@ -149,16 +149,17 @@ check_result (gpgme_import_result_t result, const char *fpr, int secret)
exit (1);
}
}
- if (strcmp (fpr, result->imports->fpr))
+ if (!result->imports->fpr || strcmp (fpr, result->imports->fpr))
{
fprintf (stderr, "Unexpected fingerprint %s\n",
- result->imports->fpr);
+ result->imports->fpr ? result->imports->fpr : "null");
exit (1);
}
- if (result->imports->next && strcmp (fpr, result->imports->next->fpr))
+ if (result->imports->next
+ && (!result->imports->next->fpr || strcmp (fpr, result->imports->next->fpr)))
{
fprintf (stderr, "Unexpected fingerprint on second status %s\n",
- result->imports->next->fpr);
+ result->imports->next->fpr ? result->imports->next->fpr : "null");
exit (1);
}
if (result->imports->result != 0)
@@ -214,6 +215,7 @@ main (int argc, char *argv[])
gpgme_error_t err;
gpgme_data_t in;
gpgme_import_result_t result;
+ gpgme_key_t key;
char *pubkey_1_asc = make_filename ("pubkey-1.asc");
char *seckey_1_asc = make_filename ("seckey-1.asc");
@@ -225,6 +227,9 @@ main (int argc, char *argv[])
err = gpgme_new (&ctx);
fail_if_err (err);
+ err = gpgme_set_ctx_flag (ctx, "key-origin", "wkd,https://openpgpkey.gnupg.org");
+ fail_if_err (err);
+
err = gpgme_data_new_from_file (&in, pubkey_1_asc, 1);
free (pubkey_1_asc);
fail_if_err (err);
@@ -246,5 +251,24 @@ main (int argc, char *argv[])
gpgme_data_release (in);
gpgme_release (ctx);
+
+ err = gpgme_new (&ctx);
+ fail_if_err (err);
+
+ err = gpgme_get_key (ctx, "0xADAB7FCC1F4DE2616ECFA402AF82244F9CD9FD55", &key, 0);
+ fail_if_err (err);
+
+ if (!key)
+ {
+ fprintf (stderr, "Imported key not found\n");
+ exit (1);
+ }
+ if (key->origin != GPGME_KEYORG_WKD)
+ {
+ fprintf (stderr, "Key has unexpected origin: %d\n", key->origin);
+ exit (1);
+ }
+
+
return 0;
}
diff --git a/tests/run-export.c b/tests/run-export.c
index 623c733..3e32882 100644
--- a/tests/run-export.c
+++ b/tests/run-export.c
@@ -59,6 +59,7 @@ show_usage (int ex)
" --ssh export as ssh public key\n"
" --extern send keys to the keyserver (TAKE CARE!)\n"
" --secret export secret keys instead of public keys\n"
+ " --secret-subkey export secret subkeys instead of public keys\n"
" --raw use PKCS#1 as secret key format\n"
" --pkcs12 use PKCS#12 as secret key format\n"
, stderr);
@@ -128,6 +129,11 @@ main (int argc, char **argv)
mode |= GPGME_EXPORT_MODE_SECRET;
argc--; argv++;
}
+ else if (!strcmp (*argv, "--secret-subkey"))
+ {
+ mode |= GPGME_EXPORT_MODE_SECRET_SUBKEY;
+ argc--; argv++;
+ }
else if (!strcmp (*argv, "--raw"))
{
mode |= GPGME_EXPORT_MODE_RAW;
@@ -168,6 +174,16 @@ main (int argc, char **argv)
err = gpgme_op_export_ext (ctx, (const char**)argv, mode, out);
fail_if_err (err);
}
+ else if ((mode & GPGME_EXPORT_MODE_SECRET_SUBKEY))
+ {
+ keyarray[0] = NULL;
+
+ printf ("exporting secret subkeys!\n");
+
+ gpgme_set_armor (ctx, 1);
+ err = gpgme_op_export_ext (ctx, (const char**)argv, mode, out);
+ fail_if_err (err);
+ }
else
{
/* Lookup the keys as required by the export_keys function. */
diff --git a/tests/run-genkey.c b/tests/run-genkey.c
index f0f6e30..8572db2 100644
--- a/tests/run-genkey.c
+++ b/tests/run-genkey.c
@@ -131,15 +131,23 @@ progress_cb (void *opaque, const char *what, int type, int current, int total)
static unsigned long
-parse_expire_string (const char *string)
+parse_expire_string (const char *string, unsigned int *flags)
{
- unsigned long seconds;
+ unsigned long seconds = 0;
- if (!string || !*string || !strcmp (string, "none")
- || !strcmp (string, "never") || !strcmp (string, "-"))
- seconds = 0;
+ if (!string || !*string || !strcmp (string, "-"))
+ ;
+ else if (!strcmp (string, "none") || !strcmp (string, "never"))
+ {
+ if (flags)
+ *flags |= GPGME_CREATE_NOEXPIRE;
+ }
else if (strspn (string, "01234567890") == strlen (string))
- seconds = strtoul (string, NULL, 10);
+ {
+ seconds = strtoul (string, NULL, 10);
+ if (!seconds && flags)
+ *flags |= GPGME_CREATE_NOEXPIRE;
+ }
else
{
fprintf (stderr, PGM ": invalid value '%s'\n", string);
@@ -370,7 +378,7 @@ main (int argc, char **argv)
}
userid = argv[0];
argc--; argv++;
- expire = parse_expire_string (argv[0]);
+ expire = parse_expire_string (argv[0], NULL);
argc--; argv++;
if (argc > 1)
{
@@ -414,7 +422,7 @@ main (int argc, char **argv)
if (argc > 2)
flags |= parse_usage_string (argv[2]);
if (argc > 3)
- expire = parse_expire_string (argv[3]);
+ expire = parse_expire_string (argv[3], &flags);
}
init_gpgme (protocol);
diff --git a/tests/run-import.c b/tests/run-import.c
index 36d9a0d..931a8d6 100644
--- a/tests/run-import.c
+++ b/tests/run-import.c
@@ -46,6 +46,7 @@ show_usage (int ex)
" --verbose run in verbose mode\n"
" --openpgp use the OpenPGP protocol (default)\n"
" --cms use the CMS protocol\n"
+ " --key-origin use the specified key origin\n"
" --url import from given URLs\n"
" -0 URLs are delimited by a nul\n"
, stderr);
@@ -63,6 +64,8 @@ main (int argc, char **argv)
gpgme_import_result_t impres;
gpgme_data_t data;
gpgme_protocol_t protocol = GPGME_PROTOCOL_OpenPGP;
+ char *import_filter = NULL;
+ char *key_origin = NULL;
if (argc)
{ argc--; argv++; }
@@ -101,6 +104,22 @@ main (int argc, char **argv)
protocol = GPGME_PROTOCOL_CMS;
argc--; argv++;
}
+ else if (!strcmp (*argv, "--import-filter"))
+ {
+ argc--; argv++;
+ if (!argc)
+ show_usage (1);
+ import_filter = strdup (*argv);
+ argc--; argv++;
+ }
+ else if (!strcmp (*argv, "--key-origin"))
+ {
+ argc--; argv++;
+ if (!argc)
+ show_usage (1);
+ key_origin = strdup (*argv);
+ argc--; argv++;
+ }
else if (!strncmp (*argv, "--", 2))
show_usage (1);
@@ -115,6 +134,17 @@ main (int argc, char **argv)
fail_if_err (err);
gpgme_set_protocol (ctx, protocol);
+ if (import_filter)
+ {
+ err = gpgme_set_ctx_flag (ctx, "import-filter", import_filter);
+ fail_if_err (err);
+ }
+ if (key_origin)
+ {
+ err = gpgme_set_ctx_flag (ctx, "key-origin", key_origin);
+ fail_if_err (err);
+ }
+
for (; argc; argc--, argv++)
{
printf ("reading file `%s'\n", *argv);
diff --git a/tests/run-receive-keys.c b/tests/run-receive-keys.c
new file mode 100644
index 0000000..6b55b81
--- /dev/null
+++ b/tests/run-receive-keys.c
@@ -0,0 +1,129 @@
+/* run-keylist.c - Helper to show a key listing.
+ * Copyright (C) 2008, 2009 g10 Code GmbH
+ *
+ * This file is part of GPGME.
+ *
+ * GPGME is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU Lesser General Public License as
+ * published by the Free Software Foundation; either version 2.1 of
+ * the License, or (at your option) any later version.
+ *
+ * GPGME is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this program; if not, see <https://gnu.org/licenses/>.
+ * SPDX-License-Identifier: LGPL-2.1-or-later
+ */
+
+/* We need to include config.h so that we know whether we are building
+ with large file system (LFS) support. */
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+#endif
+
+#include <stdlib.h>
+#include <stdio.h>
+#include <string.h>
+#include <time.h>
+
+#include <gpgme.h>
+
+#define PGM "run-receive-keys"
+
+#include "run-support.h"
+
+
+static int verbose;
+
+
+static int
+show_usage (int ex)
+{
+ fputs ("usage: " PGM " [options] [KEYIDs_or_FINGERPRINTs]\n\n"
+ "Options:\n"
+ " --verbose run in verbose mode\n"
+ , stderr);
+ exit (ex);
+}
+
+
+int
+main (int argc, char **argv)
+{
+ int last_argc = -1;
+ gpgme_error_t err;
+ gpgme_ctx_t ctx;
+ const char *keyids[100];
+ const char **keyid = NULL;
+ gpgme_protocol_t protocol = GPGME_PROTOCOL_OpenPGP;
+ gpgme_import_result_t impres;
+
+
+ if (argc)
+ { argc--; argv++; }
+
+ while (argc && last_argc != argc)
+ {
+ last_argc = argc;
+ if (!strcmp (*argv, "--"))
+ {
+ argc--; argv++;
+ break;
+ }
+ else if (!strcmp (*argv, "--help"))
+ show_usage (0);
+ else if (!strcmp (*argv, "--verbose"))
+ {
+ verbose = 1;
+ argc--; argv++;
+ }
+ else if (!strncmp (*argv, "--", 2))
+ show_usage (1);
+ }
+
+ if (!argc)
+ show_usage (1);
+ if (argc > 99) {
+ argc = 99;
+ }
+ for (keyid = keyids; argc; argc--, argv++, keyid++) {
+ *keyid = *argv;
+ }
+ *keyid = NULL;
+
+ init_gpgme (protocol);
+
+ err = gpgme_new (&ctx);
+ fail_if_err (err);
+ gpgme_set_protocol (ctx, protocol);
+
+ err = gpgme_op_receive_keys (ctx, keyids);
+ fail_if_err (err);
+ impres = gpgme_op_import_result (ctx);
+ if (!impres)
+ {
+ fprintf (stderr, PGM ": no import result returned\n");
+ exit (1);
+ }
+ print_import_result (impres);
+
+ if (verbose)
+ {
+ gpgme_data_t log;
+ char *buf;
+ size_t len;
+
+ gpgme_data_new (&log);
+ err = gpgme_op_getauditlog (ctx, log, GPGME_AUDITLOG_DIAG);
+ fail_if_err (err);
+ buf = gpgme_data_release_and_get_mem (log, &len);
+ printf ("\nDiagnostic output:\n%.*s\n", (int)len, buf);
+ free (buf);
+ }
+
+ gpgme_release (ctx);
+ return 0;
+}
diff --git a/tests/run-swdb.c b/tests/run-swdb.c
index a8d55b7..3f8736a 100644
--- a/tests/run-swdb.c
+++ b/tests/run-swdb.c
@@ -64,7 +64,6 @@ show_usage (int ex)
fputs ("usage: " PGM " [options] NAME [VERSION]\n\n"
"Options:\n"
" --verbose run in verbose mode\n"
- " --status print status lines from the backend\n"
, stderr);
exit (ex);
}
diff --git a/tests/run-threaded.c b/tests/run-threaded.c
index c0e033b..634b681 100644
--- a/tests/run-threaded.c
+++ b/tests/run-threaded.c
@@ -517,7 +517,8 @@ delete_impres (gpgme_import_result_t r, gpgme_protocol_t proto)
for (st=r->imports; st; st = st->next)
{
- delete_fpr (st->fpr, proto);
+ if (st->fpr)
+ delete_fpr (st->fpr, proto);
}
}
diff --git a/tests/start-stop-agent b/tests/start-stop-agent
index 7901374..9b08b55 100755
--- a/tests/start-stop-agent
+++ b/tests/start-stop-agent
@@ -36,10 +36,10 @@ for F in gpg.conf gpgsm.conf
do
if test -f "$GNUPGHOME/$F"
then
- mv "$GNUPGHOME/$F" "$GNUPGHOME/$F~"
+ cat "$GNUPGHOME/$F" > "$GNUPGHOME/$F~"
sed -e "s#^agent-program.*#agent-program ${GPG_AGENT}|--debug-quick-random#" \
>"$GNUPGHOME/$F" <"$GNUPGHOME/$F~"
- rm "$GNUPGHOME/$F~"
+ rm -f "$GNUPGHOME/$F~"
fi
done
diff --git a/tests/t-engine-info.c b/tests/t-engine-info.c
index db46bf8..3f8d003 100644
--- a/tests/t-engine-info.c
+++ b/tests/t-engine-info.c
@@ -118,6 +118,7 @@ main (int argc, char **argv )
"libdir",
"datadir",
"localedir",
+ "socketdir",
"agent-socket",
"agent-ssh-socket",
"dirmngr-socket",
@@ -126,6 +127,11 @@ main (int argc, char **argv )
"gpg-name",
"gpgsm-name",
"g13-name",
+ "keyboxd-name",
+ "agent-name",
+ "scdaemon-name",
+ "dirmngr-name",
+ "pinentry-name",
"gpg-wks-client-name",
NULL };
const char *s;