Compare commits

...

621 Commits

Author SHA1 Message Date
Ingo Klöcker
5c095553e4
build,qt: Fix include path in CMake files
* lang/qt/src/Makefile.am (QGpgmeConfig.cmake, QGpgmeQt6Config.cmake):
Use new variables includeprefix{5,6} instead of replaced variable
includeprefix.
--

GnuPG-bug-id: 7205
2024-07-22 10:32:00 +02:00
Ingo Klöcker
9ab2ce36f9
build,qt: Don't put generated camel-case headers in tarball
* lang/qt/src/Makefile.am: Change camelcase5include_HEADERS to
nodist_camelcase5include_HEADERS. Change camelcase6include_HEADERS to
nodist_camelcase6include_HEADERS.
--
2024-07-18 16:16:33 +02:00
Ingo Klöcker
c69240c843
core: Remove obsolete source files
* src/isascii.c, src/putc_unlocked.c: Remove.
--

I noticed those files when I compared the content of the dist tarball
with the repo.
2024-07-18 15:51:44 +02:00
Ingo Klöcker
42e151b34b
build,qt: Allow building Qt 5 bindings and Qt 6 bindings
* configure.ac: Remove "qt" from default_languages. Add "qt5 qt6" to
default_languages. Remove "qt" from help for --enable-languages. Don't
fail anymore if "qt5" and "qt6" are enabled. Warn that "qt" is
deprecated if it was enabled.
* lang/qt/src/Makefile.am (libqgpgme_la, libqgpgmeqt6_la): New.
(lib_LTLIBRARIES): Set Qt 5 and/or Qt 6 variant of libqgpgme.
(AM_CPPFLAGS): Replace with libqgpgme_la_CPPFLAGS for Qt 5 and
libqgpgmeqt6_la_CPPFLAGS for Qt 6.
--

This makes it possible to build QGpgME simultaneously for Qt 5 and Qt 6.
By default, QGpgME is now built for all versions of Qt that are found.
Specifying "qt" as language is deprecated.

GnuPG-bug-id: 7205
2024-07-18 14:42:30 +02:00
Ingo Klöcker
e6830b58b6
build,qt: Decouple generation of moc files
* m4/qt5.m4: Export moc for Qt 5 in variable MOC5. Unset temporary MOC2.
* m4/qt6.m4: Export moc for Qt 6 in variable MOC6.
* lang/qt/src/Makefile.am: Generate .moc5 files from .h files. Generate
.moc forwarding headers in moc5 subfolder. Add moc5 subfolder to include
paths for Qt 5-based qgpgme library. Ditto for Qt 6. Clean up moc5 and
moc6 subfolders.
* lang/qt/tests/Makefile.am: List tests and test runners for Qt 5 and
Qt 6. Generate .moc5 files from .cpp files of tests. Generate .moc
forwarding headers in moc5 subfolder. Generate .hmoc file from
t-support.h directly in moc5 subfolder. Add moc5 subfolder to include
paths for all Qt 5-based tests and runners. Ditto for Qt 6. Specify
sources, LDADD and CPPFLAGS for all tests and test runners for Qt 5 and
Qt 6. Clean up moc5 and moc6 subfolders.
--

The output of Qt 5's moc and Qt 6's moc is incompatible. Therefore, we
need to generate different .moc files for Qt 5 and Qt 6 to support
co-building of the Qt 5 and Qt 6 bindings. The duplication of the
listing of the tests couldn't be avoided because automake doesn't
understand `the_tests5 = $(the_tests:%=%5)` and couldn't match the
tests with their _SOURCES. Maybe some m4 programming would have helped,
but that would have made the Makefiles even more unreadable.

GnuPG-bug-id: 7205
2024-07-18 14:41:52 +02:00
Ingo Klöcker
899a572b33
build,qt: Remove include directories on uninstall
* lang/qt/src/Makefile.am (uninstall-include-dirs-qt5,
uninstall-include-dirs-qt6): New targets.
(uninstall_include_dirs_qt5, uninstall_include_dirs_qt6): New variables.
(uninstall-local): Replace with...
(uninstall-hook): ...this. Add new uninstall_include_dirs_qt* variables.
--

We have to use uninstall-hook because uninstall-local runs before the
header files have been removed from the include folders we want to
remove.

GnuPG-bug-id: 7205
2024-07-18 14:41:32 +02:00
Ingo Klöcker
69558f2c0b
build,qt: Decouple handling of include headers
* lang/qt/src/Makefile.am (includeprefix): Replace with...
(includeprefix5, includeprefix6): ...these.
(qgpgmeincludedir): Replace with...
(qgpgme5includedir, qgpgme6includedir): ...these.
(qgpgmeinclude_HEADERS): Replace with...
(qgpgme5include_HEADERS, qgpgme6include_HEADERS): ...these.
(nodist_qgpgmeinclude_HEADERS): Replace with...
(nodist_qgpgme5include_HEADERS, nodist_qgpgme6include_HEADERS): ..these.
(camelcaseincludedir): Replace with...
(camelcase5includedir, camelcase6includedir): ...these.
(camelcaseinclude_HEADERS): Replace with...
(camelcase5include_HEADERS, camelcase6include_HEADERS): ...these.
--

This prepares the code for the case that WANT_QT5 and WANT_QT6 are both
true.

GnuPG-bug-id: 7205
2024-07-18 14:40:37 +02:00
Ingo Klöcker
576d2db9dd
build,qt: Decouple (un)install of CMake files
* lang/qt/src/Makefile.am (install-cmake-files): Rename target to
install-cmake-files-qt5 and install-cmake-files-qt6.
(uninstall-cmake-files): Rename target to uninstall-cmake-files-qt5 and
uninstall-cmake-files-qt6.
(install_cmake_files_qt5, uninstall_cmake_files_qt5,
install_cmake_files_qt6, uninstall_cmake_files_qt6): New variables.
(install-data-local): Depend on both install-cmake-files-qt* targets.
(uninstall-local): Depend on both uninstall-cmake-files-qt* targets.
--

This prepares the targets for the case that WANT_QT5 and WANT_QT6 are
both true.

GnuPG-bug-id: 7205
2024-07-18 14:35:46 +02:00
Ingo Klöcker
aa15a664b3
core: Support all keylist modes and fix possible overrun
* src/gpgme-tool.c (gt_get_keylist_mode): Increase NR_KEYLIST_MODES to
number of keylist modes. Add support for GPGME_KEYLIST_MODE_WITH_TOFU,
GPGME_KEYLIST_MODE_WITH_KEYGRIP, GPGME_KEYLIST_MODE_WITH_V5FPR. Write
all modes.
(hlp_keylist_mode): List all supported keylist modes.
(cmd_keylist_mode): Add support for GPGME_KEYLIST_MODE_WITH_TOFU,
GPGME_KEYLIST_MODE_WITH_KEYGRIP, GPGME_KEYLIST_MODE_WITH_V5FPR.
--

This fixes the possible overrun reported by Michal Hlavinka and adds
support for all keylist modes.
2024-07-15 22:19:13 +02:00
Ingo Klöcker
e46748a0d1
build,cpp: Fix include paths in forwarding headers in gpgme++ folder
* lang/cpp/src/Makefile.am (build rule for copied headers): Write
abs_srcdir instead of srcdir in the generated headers.
--

The generated include paths lacked a "../" if srcdir was relative. This
lead to self-including includes for in-source builds. Including the real
headers with their absolute paths fixes this.

GnuPG-bug-id: 7110
2024-07-10 23:28:27 +02:00
Ingo Klöcker
f6d020e24f
qt: Replace usage of deprecated Error::asString
* lang/qt/src/debug.cpp (operator<<): Use Error::asStdString instead of
Error::asString.
* lang/qt/src/qgpgmedecryptverifyjob.cpp (decrypt_verify),
lang/qt/src/qgpgmenewcryptoconfig.cpp
(QGpgMENewCryptoConfigComponent::sync),
lang/qt/src/qgpgmewkdlookupjob.cpp (startDirmngr): Use QDebug operator
for Error instead of Error::asString.
* lang/qt/src/threadedjobmixin.cpp (_detail::audit_log_as_html): Use
errorAsString instead of Error::asString.
* lang/qt/src/util.h (errorAsString): New.

* lang/qt/tests/run-decryptverifyarchivejob.cpp (main),
lang/qt/tests/run-decryptverifyjob.cpp (main),
lang/qt/tests/run-encryptarchivejob.cpp (main),
lang/qt/tests/run-encryptjob.cpp (main),
lang/qt/tests/run-exportjob.cpp (main),
lang/qt/tests/run-importjob.cpp (main),
lang/qt/tests/run-receivekeysjob.cpp (main),
lang/qt/tests/run-refreshkeysjob.cpp (main),
lang/qt/tests/run-signarchivejob.cpp (main),
lang/qt/tests/run-signjob.cpp (main),
lang/qt/tests/run-verifydetachedjob.cpp (main),
lang/qt/tests/run-verifyopaquejob.cpp (main),
lang/qt/tests/run-wkdrefreshjob.cpp (main),
lang/qt/tests/t-ownertrust.cpp (testChangeOwnerTrust),
lang/qt/tests/t-remarks.cpp (testRemarkOwnKey),
lang/qt/tests/t-tofuinfo.cpp (testTofuPolicy): Use QDebug operator for
Error instead of Error::asString.
* lang/qt/tests/t-changeexpiryjob.cpp (all test functions),
lang/qt/tests/t-trustsignatures.cpp (all test functions),
lang/qt/tests/t-various.cpp (testSignKeyWithoutExpiration,
testSignKeyWithExpiration): Use errorAsString instead of
Error::asString.
--

GnuPG-bug-id: 7188
2024-07-05 10:05:51 +02:00
Ingo Klöcker
28542b14c4
cpp: Deprecate Error::asString and update users
* lang/cpp/src/error.h (Error::asString): Mark as deprecated.
* lang/cpp/src/context.cpp (operator<<),
lang/cpp/src/editinteractor.cpp (edit_interactor_callback_impl),
lang/cpp/tests/run-getkey.cpp (main),
lang/cpp/tests/run-keylist.cpp (main),
lang/cpp/tests/run-wkdlookup.cpp (main): Use Error::asStdString instead
of Error::asString.
--

GnuPG-bug-id: 7188
2024-07-05 10:05:51 +02:00
Ingo Klöcker
2656d3ee5b
cpp: Add safer member function returning text describing an error
* lang/cpp/src/error.h, lang/cpp/src/context.cpp (class Error): New
member function asStdString.
--

Unlike asString the new function doesn't cache the value returned by
gpgme_strerror_r. This ensures that on Windows the UTF-8 encoded text
is returned for the main thread even if the function was called before
for another thread. For other threads asStdString will still return the
natively encoded error description until UTF-8 encoded error
descriptions can be enabled for all threads (T7185).

GnuPG-bug-id: 7188
2024-07-05 10:05:51 +02:00
Ingo Klöcker
acf574af64
qt: Always include C++ binding headers with gpgme++/ prefix
* lang/qt/src/Makefile.am, lang/qt/tests/Makefile.am (AM_CPPFLAGS):
Add builddir instead of srcdir of C++ bindings as include path.
* lang/qt/src/changeexpiryjob.cpp, lang/qt/src/changeexpiryjob.h,
lang/qt/src/changeownertrustjob.h, lang/qt/src/dataprovider.cpp,
lang/qt/src/dataprovider.h, lang/qt/src/debug.cpp,
lang/qt/src/decryptverifyarchivejob.cpp,
lang/qt/src/decryptverifyarchivejob.h,
lang/qt/src/encryptarchivejob.cpp, lang/qt/src/encryptarchivejob.h,
lang/qt/src/encryptjob.h, lang/qt/src/encryptjob_p.h,
lang/qt/src/filelistdataprovider.cpp,
lang/qt/src/filelistdataprovider.h,
lang/qt/src/hierarchicalkeylistjob.h, lang/qt/src/importjob.cpp,
lang/qt/src/importjob.h, lang/qt/src/importjob_p.h, lang/qt/src/job.h,
lang/qt/src/keyformailboxjob.h, lang/qt/src/keylistjob.h,
lang/qt/src/listallkeysjob.h, lang/qt/src/multideletejob.cpp,
lang/qt/src/qgpgmeaddexistingsubkeyjob.cpp,
lang/qt/src/qgpgmeadduseridjob.cpp, lang/qt/src/qgpgmebackend.cpp,
lang/qt/src/qgpgmechangeexpiryjob.cpp,
lang/qt/src/qgpgmechangeownertrustjob.cpp,
lang/qt/src/qgpgmechangepasswdjob.cpp, lang/qt/src/qgpgmedecryptjob.cpp,
lang/qt/src/qgpgmedecryptjob.h,
lang/qt/src/qgpgmedecryptverifyarchivejob.cpp,
lang/qt/src/qgpgmedecryptverifyarchivejob.h,
lang/qt/src/qgpgmedecryptverifyjob.cpp,
lang/qt/src/qgpgmedecryptverifyjob.h, lang/qt/src/qgpgmedeletejob.cpp,
lang/qt/src/qgpgmedownloadjob.cpp,
lang/qt/src/qgpgmeencryptarchivejob.cpp,
lang/qt/src/qgpgmeencryptarchivejob.h, lang/qt/src/qgpgmeencryptjob.cpp,
lang/qt/src/qgpgmeencryptjob.h, lang/qt/src/qgpgmeexportjob.cpp,
lang/qt/src/qgpgmeimportfromkeyserverjob.cpp,
lang/qt/src/qgpgmeimportfromkeyserverjob.h,
lang/qt/src/qgpgmeimportjob.cpp, lang/qt/src/qgpgmeimportjob.h,
lang/qt/src/qgpgmekeyformailboxjob.h,
lang/qt/src/qgpgmekeygenerationjob.cpp,
lang/qt/src/qgpgmekeygenerationjob.h, lang/qt/src/qgpgmekeylistjob.cpp,
lang/qt/src/qgpgmekeylistjob.h, lang/qt/src/qgpgmelistallkeysjob.cpp,
lang/qt/src/qgpgmelistallkeysjob.h,
lang/qt/src/qgpgmenewcryptoconfig.cpp,
lang/qt/src/qgpgmenewcryptoconfig.h, lang/qt/src/qgpgmequickjob.cpp,
lang/qt/src/qgpgmereceivekeysjob.h,
lang/qt/src/qgpgmerefreshsmimekeysjob.cpp,
lang/qt/src/qgpgmerefreshsmimekeysjob.h,
lang/qt/src/qgpgmerevokekeyjob.cpp,
lang/qt/src/qgpgmesetprimaryuseridjob.cpp,
lang/qt/src/qgpgmesignarchivejob.cpp,
lang/qt/src/qgpgmesignarchivejob.h,
lang/qt/src/qgpgmesignencryptarchivejob.cpp,
lang/qt/src/qgpgmesignencryptarchivejob.h,
lang/qt/src/qgpgmesignencryptjob.cpp,
lang/qt/src/qgpgmesignencryptjob.h, lang/qt/src/qgpgmesignjob.cpp,
lang/qt/src/qgpgmesignjob.h, lang/qt/src/qgpgmesignkeyjob.cpp,
lang/qt/src/qgpgmetofupolicyjob.cpp,
lang/qt/src/qgpgmeverifydetachedjob.cpp,
lang/qt/src/qgpgmeverifydetachedjob.h,
lang/qt/src/qgpgmeverifyopaquejob.cpp,
lang/qt/src/qgpgmeverifyopaquejob.h, lang/qt/src/qgpgmewkdlookupjob.cpp,
lang/qt/src/qgpgmewkdrefreshjob.cpp, lang/qt/src/qgpgmewkdrefreshjob.h,
lang/qt/src/qgpgmewkspublishjob.cpp, lang/qt/src/quickjob.h,
lang/qt/src/signarchivejob.cpp, lang/qt/src/signarchivejob.h,
lang/qt/src/signencryptarchivejob.cpp,
lang/qt/src/signencryptarchivejob.h, lang/qt/src/signencryptjob.h,
lang/qt/src/signencryptjob_p.h, lang/qt/src/signjob.h,
lang/qt/src/signjob_p.h, lang/qt/src/threadedjobmixin.cpp,
lang/qt/src/threadedjobmixin.h, lang/qt/src/tofupolicyjob.h,
lang/qt/src/util.cpp, lang/qt/src/wkdlookupresult.cpp,
lang/qt/src/wkdlookupresult.h, lang/qt/src/wkdrefreshjob_p.h,
lang/qt/tests/run-decryptverifyarchivejob.cpp,
lang/qt/tests/run-decryptverifyjob.cpp,
lang/qt/tests/run-encryptarchivejob.cpp,
lang/qt/tests/run-encryptjob.cpp, lang/qt/tests/run-exportjob.cpp,
lang/qt/tests/run-importjob.cpp, lang/qt/tests/run-keyformailboxjob.cpp,
lang/qt/tests/run-receivekeysjob.cpp,
lang/qt/tests/run-refreshkeysjob.cpp,
lang/qt/tests/run-signarchivejob.cpp, lang/qt/tests/run-signjob.cpp,
lang/qt/tests/run-verifydetachedjob.cpp,
lang/qt/tests/run-verifyopaquejob.cpp,
lang/qt/tests/run-wkdrefreshjob.cpp,
lang/qt/tests/t-addexistingsubkey.cpp,
lang/qt/tests/t-changeexpiryjob.cpp, lang/qt/tests/t-config.cpp,
lang/qt/tests/t-decryptverify.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-revokekey.cpp,
lang/qt/tests/t-setprimaryuserid.cpp, lang/qt/tests/t-support.cpp,
lang/qt/tests/t-support.h, lang/qt/tests/t-tofuinfo.cpp,
lang/qt/tests/t-trustsignatures.cpp, lang/qt/tests/t-various.cpp,
lang/qt/tests/t-verify.cpp, lang/qt/tests/t-wkdlookup.cpp,
lang/qt/tests/t-wkspublish.cpp: Include GpgME++ headers with gpgme++/
prefix.
--

This prepares the Qt bindings for building them separately from the C++
bindings.

GnuPG-bug-id: 7110
2024-07-05 10:05:50 +02:00
Ingo Klöcker
b7435b31f6
build,cpp: Create forwarding headers in a gpgme++ folder
* lang/cpp/src/Makefile.am (copied_headers): New.
(build rule for all copied headers): New.
(BUILT_SOURCES): New.
(CLEANFILES): Add copied_headers.
--

The forwarding headers make it easier to use the headers from the Qt
bindings when building them against the built but not installed C++
bindings because we can always include the C++ headers with gpgme++/
prefix. This also helps to avoid including a C++ header with the same
name as a header in the Qt bindings (e.g. util.h).

GnuPG-bug-id: 7110
2024-07-05 10:02:45 +02:00
NIIBE Yutaka
95bd4fa813
Fix calling CancelSynchronousIo.
* src/w32-util.c (_gpgme_w32_cancel_synchronous_io): Use HANDLE.

--

GnuPG-bug-id: 6634
Signed-off-by: NIIBE Yutaka <gniibe@fsij.org>
2024-07-05 13:52:33 +09:00
NIIBE Yutaka
de60684500
Fix printing size_t and off_t value for LLP64 Windows.
* src/debug.h (_trace_sysres_off_t): Use 'z' length specifier.
* src/w32-io.c (_gpgme_io_read): Likewise.
(writer, _gpgme_io_write): Likewise.

--

GnuPG-bug-id: 7187
Signed-off-by: NIIBE Yutaka <gniibe@fsij.org>
2024-07-05 13:49:26 +09:00
NIIBE Yutaka
8b4171680c
Remove ath.h and ath.c.
* src/Makefile.am (system_components): We don't use ath.h any more.
(main_sources): Remove ath.h and ath.c.

--

Signed-off-by: NIIBE Yutaka <gniibe@fsij.org>
2024-07-05 11:48:11 +09:00
NIIBE Yutaka
9c276e762a
Don't use ath_self, but get thread ID directly.
* src/debug.c [HAVE_W32_SYSTEM or __linux] (tid_log_callback): Use
native thread ID call for Windows and Linux, ifdef-out-ed.
(debug_init): Only call gpgrt_log_set_pid_suffix_cb for relevant
systems.

--

Signed-off-by: NIIBE Yutaka <gniibe@fsij.org>
2024-07-05 11:36:26 +09:00
NIIBE Yutaka
ec2c6dd8bc
Use gpgrt_b64dec in libgpg-error.
* src/b64dec.c: Remove.
* src/Makefile.am (main_sources): Remove b64dec.c.
* src/data-identify.c (pgp_binary_detection): Use gpgrt_b64dec in
libgpg-error.

--

gpgrt_b64dec is available in libgpg-error 1.27 and it is already in
use by JSON support.

GnuPG-bug-id: 7180
Signed-off-by: NIIBE Yutaka <gniibe@fsij.org>
2024-07-01 11:52:25 +09:00
Ingo Klöcker
6ed5c9a38a
cpp: Remove obsolete files
* lang/cpp/src/context_glib.cpp, lang/cpp/src/context_qt.cpp: Remove.
--

These files have never been used since gpgmepp was imported into this
repo.
2024-06-28 11:11:14 +02:00
Ingo Klöcker
7d5df0bf0d
qt: Allow appending a detached signature to an existing file
* lang/qt/src/qgpgmesignjob.cpp (sign_to_filename): Add argument
"appendSignature". Append new detached signature to an existing file if
requested.
* lang/qt/src/signjob.cpp, lang/qt/src/signjob.h (class SignJob): Add
member functions setAppendSignature, appendSignatureEnabled.
* lang/qt/src/signjob_p.h (struct SignJobPrivate): Add member
m_appendSignature.

* lang/qt/tests/run-signjob.cpp (struct CommandLineOptions): Add members
signingFlags, appendSignature. Initialize armor.
(parseCommandLine): Add command line options --detach-sign and --append.
(main): Do not exit if output file exists and append is enabled.
Pass new options to the job.
--

This change simplifies cross-signing a document by appending additional
detached signatures to a file with already existing detached signatures.

GnuPG-bug-id: 6867
2024-06-18 16:36:40 +02:00
Ingo Klöcker
09827ffc77
qt,build: Install headers for Qt 5 and Qt 6 in different locations
* lang/qt/src/Makefile.am (includeprefix): New.
(qgpgmeincludedir, camelcaseincludedir): Add $(includeprefix).
(QGpgmeConfig.cmake, QGpgmeQt6Config.cmake): Add $(includeprefix) to
replacement for @resolved_includedir@.
--

This installs the headers for Qt 5 in $(includedir)/qgpgme-qt5 and the
headers for Qt 6 in $(includedir)/qgpgme-qt6. For users of the CMake
files the change will be transparent, i.e. they don't have to do
anything. Packagers will have to change their scripts but in the end
this change will make their lifes easier.

GnuPG-bug-id: 7161
2024-06-17 11:55:26 +02:00
NIIBE Yutaka
53c367629a
Update gpg-error.m4 again for spell fix.
Signed-off-by: NIIBE Yutaka <gniibe@fsij.org>
2024-06-14 13:52:19 +09:00
Ingo Klöcker
c52e1943a7
qt,tests: Fix deprecation warnings (in Qt 6 build)
* lang/qt/tests/t-tofuinfo.cpp (TofuInfoTest::signAndVerify,
TofuInfoTest::testTofuPolicy): Use range-based for loop instead of Qt's
deprecated foreach.
--
2024-06-13 10:23:49 +02:00
Ingo Klöcker
60b96d149c
qt: Specify import options as list of strings instead of as string
* lang/qt/src/importjob.cpp, lang/qt/src/importjob.h (setImportOptions):
Change type of argument "options" to QStringList.
(importOptions): Change return type to QStringList.
* lang/qt/src/importjob_p.h (struct ImportJobPrivate): Change type of
member m_importOptions to QStringList.
* lang/qt/src/qgpgmeimportjob.cpp (import_qba): Change type of argument
"importOptions" to QStringList. Join list of import options with ','
when setting the "import-options" context flag.

* lang/qt/tests/t-import.cpp (ImportTest::testImportWithImportOptions):
Adapt to API change.
--

This makes the API that was introduced with the previous commit easier
to use.

GnuPG-bug-id: 7152
2024-06-13 10:05:44 +02:00
NIIBE Yutaka
6c90ec7be2
m4: Update m4 files.
* m4/gpg-error.m4: Update libgpg-error master.
* m4/libassuan.m4: Update libassuan master.

--

Signed-off-by: NIIBE Yutaka <gniibe@fsij.org>
2024-06-13 14:47:39 +09:00
NIIBE Yutaka
14b035034a
gpgme.m4: Fix setting/using GPG_ERROR_CONFIG.
gpgm4.m4 (_AM_PATH_GPGRT_CONFIG): Don't set GPG_ERROR_CONFIG and
gpg_error_config_version.

--

Signed-off-by: NIIBE Yutaka <gniibe@fsij.org>
2024-06-13 14:46:08 +09:00
Ingo Klöcker
2187a4de8c
qt: Allow specifying import options when importing keys
* lang/qt/src/importjob.cpp, lang/qt/src/importjob.h (class ImportJob):
Add member functions setImportOptions and importOptions.
* lang/qt/src/importjob_p.h (struct ImportJobPrivate): Add member
m_importOptions.
* lang/qt/src/qgpgmeimportjob.cpp (import_qba): Add arg importOptions
and adjust the callers. Set import options context flag.

* lang/qt/tests/t-import.cpp (ImportTest): Add member function
testImportWithImportOptions.
--

GnuPG-bug-id: 7152
2024-06-12 11:34:41 +02:00
Ingo Klöcker
5b73b0722a
tests: Add --import-filter option to usage info of run-import
* tests/run-import.c (show_usage): Add option --import-filter.
--
2024-06-12 10:48:34 +02:00
Ingo Klöcker
3b9815bd8a
core: Allow setting import options when importing keys
* src/context.h (struct gpgme_context): New field import_options.
* src/engine-backend.h (struct engine_ops): Add arg import_options to
field 'import'.
* src/engine-gpg.c (gpg_import): Add arg import_options and pass option
--import-options with argument value to gpg.
* src/engine-gpgsm.c (gpgsm_import): Add dummy arg import_options.
* src/engine.c (_gpgme_engine_op_import): Add arg import_options and
pass option to import function of engine.
* src/engine.h (_gpgme_engine_op_import): Add arg import_options.
* src/gpgme.c (gpgme_release): Free 'import_options'.
(gpgme_set_ctx_flag, gpgme_get_ctx_flag): New flag "import-options".
* src/import.c (_gpgme_op_import_start, _gpgme_op_import_keys_start,
_gpgme_op_receive_keys_start): Pass import options stored in context to
_gpgme_engine_op_import.

* tests/run-import.c (show_usage, main): Add option --import-options.
--

This makes the --import-options option available in the GPGME API for
key imports.

GnuPG-bug-id: 7152
2024-06-12 10:45:11 +02:00
Ingo Klöcker
307256d277
qt,doc: Fix typos
* lang/qt/README: Fix typos.
--
2024-06-12 09:09:18 +02:00
Ingo Klöcker
87319b3fc7
qt: Align license of some Makefiles with license of other Makefiles
* lang/qt/doc/Makefile.am, lang/qt/tests/Makefile.am: Change license
from LGPL to GPL.
--

Both files are part of QGpgME (as lang/qt/Makefile.am and
lang/qt/src/Makefile.am). Hence, they should be licensed as other parts
of QGpgME.
2024-06-10 14:56:02 +02:00
Ingo Klöcker
29be63ae37
qt: Fix license headers of Makefiles
* lang/qt/Makefile.am, lang/qt/src/Makefile.am: Files are part of
QGpgme. Fix wrong package name (GPGME-CL -> QGpgME). Replace references
to LGPL with references to GPL.
--

The files were already licensed under the GPL but the license headers
contained multiple (copy&paste?) errors.
2024-06-10 14:55:50 +02:00
Ingo Klöcker
09cc0c81f7
qt: Fix license headers of CMake config files
* lang/qt/src/QGpgmeConfig-w32.cmake.in.in,
lang/qt/src/QGpgmeConfig.cmake.in.in,
lang/qt/src/QGpgmeConfigVersion.cmake.in: Files are part of QGpgME.
Fix copy&paste error (GPGME-CL -> QGpgME). Fix reference to license
to check for details.
* lang/qt/src/QGpgmeQt6Config-w32.cmake.in.in,
lang/qt/src/QGpgmeQt6Config.cmake.in.in,
lang/qt/src/QGpgmeQt6ConfigVersion.cmake.in: Files are part of QGpgME.
Fix reference to license to check for details.
--

The files were already licensed under the GPL but the license headers
contained multiple (copy&paste?) errors.
2024-06-10 14:55:42 +02:00
Ingo Klöcker
967b6b726e
qt: Fix license headers of dataprovider.*
* lang/qt/src/dataprovider.cpp, lang/qt/src/dataprovider.h: Change
license header from LGPL to GPL.
--

QGpgME is released under the GPL. As part of QGpgME these files (that
were originally licensed under the LGPL) are released under the GPL.
2024-06-10 14:55:26 +02:00
Ingo Klöcker
4136928f0d
cpp: Remove commented out and disabled code
* lang/cpp/src/configuration.cpp: Remove disabled, abandoned code.
* lang/cpp/src/context.cpp: Remove commented out, obsolete code.
--
2024-06-10 14:54:48 +02:00
Werner Koch
5d9269cb4f
doc: Extend description for GPGME_CREATE_ADSK
--
2024-06-05 13:50:17 +02:00
Ingo Klöcker
25dd284b0c
core,w32: Pass file names with forward slashes to gpg and gpgtar
src/conversion.c, src/util.h (_gpgme_replace_backslashes): New.
src/engine-gpg.c (_add_arg): Add argument file_name. On Windows, replace
backslashes in file name arguments with forward slashes.
(add_arg_ext, add_arg_with_locp, add_arg, add_arg_pfx, add_gpg_arg,
add_gpg_arg_with_value, add_arg_len): Adjust call of _add_arg.
(add_file_name_arg, add_file_name_arg_len, add_gpg_arg_with_file_name):
New.
(add_file_name_arg_or_data): Call add_file_name_arg for file name.
(gpg_new): Call add_gpg_arg_with_file_name for home directory.
(gpg_decrypt): Call add_file_name_arg for output directory and output
file name.
(append_args_from_recipients_string): Call add_file_name_arg_len for
recipients file name.
(gpg_encrypt): Call add_file_name_arg for output file name, base
directory and input file name. Call add_gpg_arg_with_file_name to set
file name stored in message.
(gpg_encrypt_sign): Call add_file_name_arg for output file name, base
directory and input file name. Call add_gpg_arg_with_file_name to set
file name stored in message.
(gpg_sign): Call add_file_name_arg for output file name, base directory
and input file name. Call add_gpg_arg_with_file_name to set file name
stored in message.
(gpg_verify): Call add_file_name_arg for output directory and output
file name.
--

By passing all file names with forward slashes to gpg and gpgtar we
avoid problems caused by the quoting of backslashes.

GnuPG-bug-id: 7141
2024-06-04 16:52:24 +02:00
Ingo Klöcker
1245b09012
build,python: Fix make distcheck for Python 3.9+
* lang/python/Makefile.am (uninstall-local): Remove installed .egg
folders.
--

Python 3.9+ install the module into a gpg-*.egg folder instead of in
"gpg" with accompanying gpg-*.egg-info file. Moreover, Python 3.9+
normalize version numbers, e.g. the version 1.24.0_beta576 is normalized
as 1.24.0b576.
2024-05-29 17:13:30 +02:00
Ingo Klöcker
09d81da665
build,python: Remove support for Python 3.4, 3.5, 3.7
* configure.ac: Don't look for Python 3.4, 3.5, 3.7 anymore.
--

This complements the previous commit where those versions where removed
from python.m4.
2024-05-29 17:06:16 +02:00
Ben Greiner
5844d9e700
build,python: Build Python bindings without distutils
* m4/python.m4: Add python3.12 and 3.11 as valid interpreters, remove
EOL 3.4, 3.5, 3.7 (keep 3.6 because some distributions still ship and
maintain it).
* lang/python/Makefile.am (clean-local): Remove dist and gpg.egg-info
created by Python 3.9+ on make install.
* lang/python/setup.py.in: switch from distutils to setuptools where
possible, remove obsolete and deprecated -py3 option of swig, add
classifiers up to 3.12, remove 3.4, 3.5, 3.7.
* lang/python/doc/src/gpgme-python-howto.org: replace distutils with
setuptools
* lang/python/examples/howto/advanced/cython/setup.py: replace distutils
with setuptools
--

This fixes building the Python bindings for Python 3.12 where distutils
has been removed.

Based on D545
2024-05-29 17:04:10 +02:00
Ingo Klöcker
986c5f0b94
tests: Add new files to distribution
* tests/json/Makefile.am (EXTRA_DIST): Add files added with f2575b63.
--

Fixes-commit: f2575b6313
GnuPG-bug-id: 7118
2024-05-24 13:46:55 +02:00
Ingo Klöcker
6aa359b1e8
cpp: Fix includes in public headers
* lang/cpp/src/defaultassuantransaction.h,
lang/cpp/src/gpgadduserideditinteractor.h,
lang/cpp/src/gpgagentgetinfoassuantransaction.h,
lang/cpp/src/gpggencardkeyinteractor.h,
lang/cpp/src/gpgsetexpirytimeeditinteractor.h,
lang/cpp/src/gpgsetownertrusteditinteractor.h,
lang/cpp/src/gpgsignkeyeditinteractor.h,
lang/cpp/src/interfaces/assuantransaction.h,
lang/cpp/src/interfaces/dataprovider.h,
lang/cpp/src/interfaces/statusconsumer.h,
lang/cpp/src/scdgetinfoassuantransaction.h,
lang/cpp/src/statusconsumerassuantransaction.h,
lang/cpp/src/trustitem.h: Use #include "foo.h" instead of
#include <foo.h> for own headers.
--

This fixes the build for projects that include the headers (as intended)
with #include <gpgme++/...> and that don't add the gpgme++ subdirectory
to the list of include paths for the compiler.

GnuPG-bug-id: 7110
2024-05-24 10:51:32 +02:00
Ingo Klöcker
f0d1f2c4c7
Merge branch 'ikloecker/t7118-revkeys' 2024-05-24 10:47:15 +02:00
Tobias Fella
15718cb295
qt,cpp: Implement adding ADSKs to existing keys
* lang/cpp/src/context.cpp: Add functions for adding ADSKs.
* lang/cpp/src/context.h: Ditto.
* lang/qt/src/qgpgmequickjob.cpp: Add implementation of ADSK job.
* lang/qt/src/qgpgmequickjob.h: Ditto.
* lang/qt/src/quickjob.h: Add job for adding ADSKs.
2024-05-22 13:08:50 +02:00
Tobias Fella
e42b72bc2b
core: Implement adding ADSKs through gpgme_createsubkey
* src/engine-gpg.c: Add and use function for adding ADSKs.
* src/genkey.c: Prevent error due to no status line.
* src/gpgme.h.in: Add flag GPGME_CREATE_ADSK
* doc/gpgme.texi: Add documentation for ADSKs
* tests/run-genkey.c: Add test for adding ADSKs
--

This adds the ability to add ADSKs through
the gpgme_createsubkey interface.
The function must be called with NULL userid,
the ADSK fingerprint in algo
and the GPGME_CREATE_ADSK flag.
2024-05-22 10:16:19 +02:00
Ingo Klöcker
90eb80134b
cpp: Add information about revocation keys to Key
* lang/cpp/src/gpgmefw.h (gpgme_revocation_key_t): New forward
declaration.
* lang/cpp/src/key.cpp, lang/cpp/src/key.h (class Key): New methods
revocationKey, numRevocationKeys, revocationKeys.
(class RevocationKey): New.
(swap): New overload for RevocationKey.
(operator<<): New overload for RevocationKey.
* lang/cpp/src/key.cpp (operator<<): Add information about revocation
keys to the output stream for Key.

* lang/cpp/tests/run-keylist.cpp (main): Don't output Key if nextKey
failed, e.g. at the end of the key listing.
--

GnuPG-bug-id: 7118
2024-05-21 16:38:59 +02:00
Ingo Klöcker
f2575b6313
json: Add information about revocation keys to key list result
* src/gpgme-json.c (revocation_key_to_json): New.
(key_to_json): Add list of revocation keys.

* tests/json/Makefile.am (pubring-stamp): Import new pub key.
* tests/json/key-with-revokers.asc: New.
* tests/json/t-json.c (tests): Add "t-keylist-revokers".
* tests/json/t-keylist-revokers.in.json,
tests/json/t-keylist-revokers.in.json: New.
--

GnuPG-bug-id: 7118
2024-05-21 16:38:59 +02:00
Ingo Klöcker
adadfac997
core: Add information about revocation keys to keys
* src/gpgme.h.in (struct _gpgme_revocation_key,
gpgme_revocation_key_t): New.
(struct _gpgme_key): Add fields 'revkeys', '_last_revkey'.
* src/key.c (_gpgme_key_add_rev_key): New.
(gpgme_key_unref): Free revkeys.
* src/keylist.c (keylist_colon_handler): Parse rvk lines.
* src/ops.h (_gpgme_key_add_rev_key): New.

* tests/run-keylist.c (main): Print revocation key info.
--

GnuPG-bug-id: 7118
2024-05-21 16:38:59 +02:00
Werner Koch
ac4bf86bb6
tests: Fix segv in t-json.c
* tests/json/t-json.c (test_contains): Avoid calling recusivly with no
child.
2024-05-21 14:36:07 +02:00
Werner Koch
55a1ae4163
tests: Avoid some compiler warnings.
* tests/gpg/t-support.h (fail_with_syserr): New.
(check_data): Use it to avoid compiler warnings.
* tests/run-support.h (fail_with_syserr): New.
--

I don't think that there is a way to tell gcc that
gpgme_err_code_from_errno will never return 0.  Thus we better use a
different macro.
2024-05-21 13:45:02 +02:00
Ingo Klöcker
c933269d3a
qt: Avoid bogus stringop-overread warning
* lang/qt/src/threadedjobmixin.cpp (_detail::audit_log_as_html): Use
QByteArray overload of QString::fromUtf8.
--

There's no need to make the code more complicated than necessary. Unless
we want to provoke weird compiler warnings. :-)
2024-05-21 12:36:11 +02:00
Ingo Klöcker
333241b286
qt: Fix warning about missing return
* lang/qt/src/qgpgmeexportjob.cpp (ExportJob::exec): Return a value and
remove unused argument names.
--

ExportJob::exec is never executed because its virtual overload is always
used. Therefore it doesn't matter what value we return.
2024-05-21 12:24:31 +02:00
Werner Koch
73403a8ba0
core: speedup gpgme_get_key
* src/engine.c (_gpgme_set_engine_info): Change engine_get_version.
--

GnuPG-bug-id: 6369
2024-05-21 10:59:43 +02:00
NIIBE Yutaka
0f5e8182e7
m4: Update libassuan.m4 from master.
* m4/libassuan.m4: Update.

--

Signed-off-by: NIIBE Yutaka <gniibe@fsij.org>
2024-05-17 14:22:36 +09:00
Ingo Klöcker
3e3db5784f
Require at least libgpg-error 1.47
* configure.ac (NEED_GPG_ERROR_VERSION): Require 1.47.
--

Libgpg-error 1.47 has been released more than 1 year ago and we use a
new error code defined in this version.

GnuPG-bug-id: 6971
2024-05-16 10:29:50 +02:00
NIIBE Yutaka
87061c0260
gpgme.m4: Set $host correctly always.
* src/gpgme.m4 (AM_PATH_GPGME): Add AC_CANONICAL_HOST.

--

GnuPG-bug-id: 7114
Reported-by: Andreas Metzler
Signed-off-by: NIIBE Yutaka <gniibe@fsij.org>
2024-05-16 09:27:58 +09:00
Ingo Klöcker
a73a41109f
tests: Fix test after changed behavior of gpgme_op_verify
* tests/gpg/t-verify.c (main): Change assertion of test.
--

The change introduced with 1dc44b7c makes gpg abort the verification
of a clear-signed message if it encounters garbage following the
signed data. We have to adapt the test to this change.

GnuPG-bug-id: 6907
2024-05-15 11:53:06 +02:00
NIIBE Yutaka
06db03ea9b
doc: Update use of Autoconf with PKG_CHECK_MODULES.
--

Signed-off-by: NIIBE Yutaka <gniibe@fsij.org>
2024-05-14 11:42:24 +09:00
NIIBE Yutaka
882ccc8ea7
gpgme.m4: Update _AM_PATH_GPGRT_CONFIG macro from gpg-error.m4.
* src/gpgme.m4 (_AM_PATH_GPGRT_CONFIG): Update.

--

Signed-off-by: NIIBE Yutaka <gniibe@fsij.org>
2024-05-14 10:30:47 +09:00
Ingo Klöcker
e4a95746ad
cpp: Handle smart card op failure status messages
* lang/cpp/src/editinteractor.cpp (parse_sc_op_failure): New.
(CallbackHelper::edit_interactor_callback_impl): Parse failure code on
GPGME_STATUS_SC_OP_FAILURE status.
(sc_op_failure_to_error): New.
--

This converts a SC_OP_FAILURE status message logged by gpg to a
corresponding error. Unfortunately, GPG_ERR_BAD_PIN and
GPG_ERR_BAD_RESET_CODE are mapped to the same SC_OP_FAILURE code, so
that we had to choose one.

GnuPG-bug-id: 6971
2024-04-05 15:08:01 +02:00
Andre Heinecke
67057d83f5
Qt: Fix windows build of new jobs
--
See git log for changes.
2024-03-13 13:15:41 +01:00
Ingo Klöcker
7158397c09
core: Check STATUS_FAILURE in import operations.
* src/import.c (op_data_t): Add failure_code.
(_gpgme_import_status_handler): Set it. Return it on EOF.
--

GnuPG-bug-id: 7036
2024-03-11 13:53:18 +01:00
Tobias Fella
47f3d92bf3
qt: Add function for synchronously executing ExportJob
* lang/qt/src/exportjob: Add exec function.
* lang/qt/src/qgpgmeexportjob.cpp: Implement exec function.
* lang/qt/src/qgpgmeexportjob.h: Override exec function.

--

GnuPG-Bug-Id: 6893
2024-01-22 11:24:49 +01:00
Ingo Klöcker
0011412193
qt: Remove superfluous virtual overrides and member variables
* lang/qt/src/qgpgmeaddexistingsubkeyjob.cpp
(QGpgMEAddExistingSubkeyJob::exec): Remove call of resultHook.
* lang/qt/src/qgpgmedecryptjob.cpp (QGpgMEDecryptJob::exec): Remove
call of resultHook.
(QGpgMEDecryptJob::resultHook): Remove.
* lang/qt/src/qgpgmedecryptjob.h (QGpgMEDecryptJob): Remove resultHook
override. Remove member mResult.
* lang/qt/src/qgpgmedecryptverifyjob.cpp (QGpgMEDecryptVerifyJob::exec):
Remove call of resultHook.
(QGpgMEDecryptVerifyJob::resultHook): Remove.
* lang/qt/src/qgpgmedecryptverifyjob.h (QGpgMEDecryptVerifyJob): Remove
resultHook override. Remove member mResult.
* lang/qt/src/qgpgmeencryptjob.cpp (QGpgMEEncryptJob::exec): Remove
call of resultHook.
(QGpgMEEncryptJob::resultHook): Remove.
* lang/qt/src/qgpgmeencryptjob.h (QGpgMEEncryptJob): Remove resultHook
override. Remove member mResult.
* lang/qt/src/qgpgmegpgcardjob.cpp (QGpgMEGpgCardJob::exec): Remove
call of resultHook.
* lang/qt/src/qgpgmeimportfromkeyserverjob.cpp
(QGpgMEImportFromKeyserverJob::exec): Remove call of resultHook.
(QGpgMEImportFromKeyserverJob::resultHook): Remove.
* lang/qt/src/qgpgmeimportfromkeyserverjob.h
(QGpgMEImportFromKeyserverJob): Remove resultHook override. Remove
member mResult.
* lang/qt/src/qgpgmeimportjob.cpp (QGpgMEImportJob::exec): Remove call
of resultHook.
(QGpgMEImportJob::resultHook): Remove.
* lang/qt/src/qgpgmeimportjob.h (QGpgMEImportJob): Remove resultHook
override. Remove member mResult.
* lang/qt/src/qgpgmekeyformailboxjob.cpp (QGpgMEKeyForMailboxJob::exec):
Remove call of resultHook.
* lang/qt/src/qgpgmekeylistjob.cpp (QGpgMEKeyListJob::QGpgMEKeyListJob):
Remove initialization of mResult.
(QGpgMEKeyListJob::resultHook): Do not set (removed) mResult.
* lang/qt/src/qgpgmekeylistjob.h (QGpgMEKeyListJob): Remove member
mResult.
* lang/qt/src/qgpgmelistallkeysjob.cpp
(QGpgMEListAllKeysJob::QGpgMEListAllKeysJob): Remove initialization of
mResult.
(QGpgMEListAllKeysJob::exec): Remove call of resultHook.
(QGpgMEListAllKeysJob::resultHook): Remove.
* lang/qt/src/qgpgmelistallkeysjob.h (QGpgMEListAllKeysJob): Remove
resultHook override. Remove member mResult.
* lang/qt/src/qgpgmereceivekeysjob.cpp (QGpgMEReceiveKeysJob::exec):
Remove call of resultHook.
(QGpgMEReceiveKeysJob::resultHook): Remove.
* lang/qt/src/qgpgmereceivekeysjob.h (QGpgMEReceiveKeysJob): Remove
resultHook override. Remove member mResult.
* lang/qt/src/qgpgmerevokekeyjob.cpp (QGpgMERevokeKeyJob::exec): Remove
call of resultHook.
* lang/qt/src/qgpgmesignencryptjob.cpp (QGpgMESignEncryptJob::exec):
Remove call of resultHook.
(QGpgMESignEncryptJob::resultHook): Remove.
* lang/qt/src/qgpgmesignencryptjob.h (QGpgMESignEncryptJob): Remove
resultHook override. Remove member mResult.
* lang/qt/src/qgpgmesignjob.cpp (QGpgMESignJob::exec): Remove call of
resultHook.
(QGpgMESignJob::resultHook): Remove.
* lang/qt/src/qgpgmesignjob.h (QGpgMESignJob): Remove resultHook
override. Remove member mResult.
* lang/qt/src/qgpgmeverifydetachedjob.cpp
(QGpgMEVerifyDetachedJob::exec): Remove call of resultHook.
(QGpgMEVerifyDetachedJob::resultHook): Remove.
* lang/qt/src/qgpgmeverifydetachedjob.h (QGpgMEVerifyDetachedJob):
Remove resultHook override. Remove member mResult.
* lang/qt/src/qgpgmeverifyopaquejob.cpp (QGpgMEVerifyOpaqueJob::exec):
Remove call of resultHook.
(QGpgMEVerifyOpaqueJob::resultHook): Remove.
* lang/qt/src/qgpgmeverifyopaquejob.h (QGpgMEVerifyOpaqueJob): Remove
resultHook override. Remove member mResult.
* lang/qt/src/qgpgmewkdlookupjob.cpp (QGpgMEWKDLookupJob::exec):
Remove call of resultHook.
--

All overrides of resultHook (except for the one of QGpgMEKeyListJob)
are superfluous. All the resultHook overrides do is store the result in
a member variable which is then returned in exec() (which just before
returning calls resultHook). The member variable the result is stored in
is only ever used by exec(). So exec() can simply return the result
directly. Some Job subclasses call resultHook without overriding it.
That's equally useless because the default implementation of resultHook
is empty. The only resultHook override that does anything useful is the
one of QGpgMEKeyListJob.
2024-01-19 16:07:14 +01:00
Ingo Klöcker
eae22d9a48
qt: Remove left-over mentions of showErrorDialog
* lang/qt/src/qgpgmedecryptjob.cpp,
lang/qt/src/qgpgmeimportfromkeyserverjob.cpp,
lang/qt/src/qgpgmeimportjob.cpp: Remove obsolete comment.
* lang/qt/src/qgpgmekeylistjob.cpp,
lang/qt/src/qgpgmelistallkeysjob.cpp: Remove long obsolete, #if 0'ed out
definitions of showErrorDialog.
--

Informing the users about errors is the responsibility of the users of
the QGpgME Job API since a long time.
2024-01-19 15:44:22 +01:00
Ingo Klöcker
cc1f2b5acb
build: Re-add still needed custom changes to Python autoconf macro
* m4/ax_python_devel.m4: Do not emit 'HAVE_PYTHON'.
--

This reapplies the changes made with 5189c08 that are still needed for
detecting multiple Python versions.
2024-01-16 09:58:33 +01:00
Ingo Klöcker
e3ae88267f
build: Update Python autoconf macro
* configure.ac: Call AX_PYTHON_DEVEL with new "optional" argument.
* m4/ax_python_devel.m4: Replace with current version from the autoconf
archive.
--

The new "optional" argument allows us to leave out one of our custom
changes.
2024-01-16 09:53:39 +01:00
Werner Koch
18388f93ab
doc: Add a deprecated warning to gpgme_op_delete. 2024-01-15 11:12:29 +01:00
Werner Koch
b37efb11be
doc: Fix minor typo.
--

Reported-by: Ming Kuang
2024-01-15 08:30:01 +01:00
Ingo Klöcker
85c7a94d63
cpp,tests: Launch dirmngr with gpg-conf
* lang/cpp/tests/run-wkdlookup.cpp (main): Replace backslashes with
forward slashes in homedir returned by GpgME::dirInfo. Use "gpgconf
--launch dirmngr" to start dirmngr.
--

With this change the same code as by QGpgMEWKDLookupJob is again used to
launch dirmngr. It also fixes the bad example of starting dirmngr
without the help of gpgconf.

GnuPG-bug-id: 6833
2024-01-09 11:22:43 +01:00
Ingo Klöcker
7e520213c0
qt: Pass home directory with forward slashes when launching dirmngr
* lang/qt/src/qgpgmewkdlookupjob.cpp (startDirmngr): Replace backslashes
with forward slashes in homedir returned by GpgME::dirInfo.
--

This works around a bug which causes backslashes to be escaped (doubled)
twice on Windows, once by gpgme_op_spawn and once by the spawn helper
gpgme-w32spawn. The next versions of GnuPG 2.2 and 2.4 also have a
workaround for this.

GnuPG-bug-id: 6833
2024-01-09 11:13:51 +01:00
Tobias Fella
d60d1b7f79
qt: Fix validity for (sub)keys generated using QGpgMEQuickJob
* lang/qt/src/qgpgmequickjob.cpp: Fix expiration calculation
--

The job calculates the validity as the seconds since epoch,
while GPG expects the seconds since the current time.
This leads to the validity being significantly longer than expected.

GnuPG-Bug-Id: 6889
2024-01-08 14:36:26 +01:00
Ingo Klöcker
18a0d72b1b
doc: Update NEWS
--

GnuPG-bug-id: 6550
2024-01-05 13:48:22 +01:00
Ingo Klöcker
c631622484
qt: Support verification of detached signatures directly from files
* lang/qt/src/Makefile.am: Add new files.
* lang/qt/src/job.cpp (VerifyDetachedJob): Move definition of
constructor and destructor and inclusion of the moc file to the
corresponding .cpp file.
* lang/qt/src/verifydetachedjob.cpp: New.
* lang/qt/src/verifydetachedjob.h (VerifyDetachedJob): Add member
functions setSignatureFile, signatureFile, setSignedFile, signedFile.
* lang/qt/src/verifydetachedjob_p.h: New.
* lang/qt/src/qgpgmeverifydetachedjob.cpp (class
QGpgMEVerifyDetachedJobPrivate): New.
(QGpgMEVerifyDetachedJob::QGpgMEVerifyDetachedJob): Instantiate private
job class.
(verify_from_filename): New.

* lang/qt/tests/Makefile.am: Add new test program.
* lang/qt/tests/run-verifydetachedjob.cpp: New.
--

This makes it possible to tell gpg to read the input directly from the
specified files bypassing GpgME's Data IO when verifying a detached
signature.

GnuPG-bug-id: 6550
2024-01-05 12:10:22 +01:00
Ingo Klöcker
1dc44b7c5b
core: Tell gpg that we want to verify signed data
* src/engine-gpg.c (gpg_verify): Add "--verify" to command line.
--

Since GnuPG 2.1.16 --verify writes the signed data to the file specified
by --output. Explicitly telling gpg that we want to verify signed data
frees gpg from guessing what we want and avoids the corresponding
warning "no command supplied.  Trying to guess what you mean ..."

GnuPG-bug-id: 6907
2023-12-22 10:37:34 +01:00
Ingo Klöcker
0b3c8709f7
qt,doc: Document that Job::startIt() doesn't self-destruct Job on error
--
GnuPG-bug-id: 6550
2023-12-22 10:35:15 +01:00
Ingo Klöcker
e77a8ac0cc
qt: Support verification of opaque signed data directly to/from files
* lang/qt/src/Makefile.am: Add new files.
* lang/qt/src/job.cpp (VerifyOpaqueJob): Move definition of constructor
and destructor and inclusion of the moc file to the corresponding .cpp
file.
* lang/qt/src/verifyopaquejob.cpp: New.
* lang/qt/src/verifyopaquejob.h (VerifyOpaqueJob): Add member
functions setInputFile, inputFile, setOutputFile, outputFile.
* lang/qt/src/verifyopaquejob_p.h: New.
* lang/qt/src/qgpgmeverifyopaquejob.cpp (class
QGpgMEVerifyOpaqueJobPrivate): New.
(QGpgMEVerifyOpaqueJob::QGpgMEVerifyOpaqueJob): Instantiate private
job class.
(verify_from_filename): New.

* lang/qt/tests/Makefile.am: Add new test program.
* lang/qt/tests/run-verifyopaquejob.cpp: New.
--

This makes it possible to tell gpg to read the input and write the
output directly to a specified file bypassing GpgME's Data IO when
verifying an opaque signed (or clear signed) file.

GnuPG-bug-id: 6550
2023-12-22 10:05:16 +01:00
Ingo Klöcker
20b32e0350
qt: Support decryption (with verification) directly to/from files
* lang/qt/src/Makefile.am: Add new files.
* lang/qt/src/job.cpp (DecryptVerifyJob): Move definition of constructor
and destructor and inclusion of the moc file to the corresponding .cpp
file.
* lang/qt/src/decryptverifyjob.cpp: New.
* lang/qt/src/decryptverifyjob.h (DecryptVerifyJob): Add member
functions setInputFile, inputFile, setOutputFile, outputFile.
* lang/qt/src/decryptverifyjob_p.h: New.
* lang/qt/src/qgpgmedecryptverifyjob.cpp (class
QGpgMEDecryptVerifyJobPrivate): New.
(QGpgMEDecryptVerifyJob::QGpgMEDecryptVerifyJob): Instantiate private
job class.
(decrypt_verify_from_filename): New.

* lang/qt/tests/Makefile.am: Add new test program.
* lang/qt/tests/run-decryptverifyjob.cpp: New.
--

This makes it possible to tell gpg to read the input and write the
output directly to a specified file bypassing GpgME's Data IO when
decrypting (and verifying) a file.

GnuPG-bug-id: 6550
2023-12-22 10:01:17 +01:00
Ingo Klöcker
a44d84772d
qt: Support writing/reading signed/encrypted files directly to/from file
* lang/qt/src/Makefile.am: Add new files.
* lang/qt/src/job.cpp (EncryptJob, SignJob, SignEncryptJob): Move
definition of constructor and destructor and inclusion of the moc file
to the corresponding .cpp files.
* lang/qt/src/encryptjob.cpp (EncryptJob): Define constructor. Define
destructor as default. Include moc file.
* lang/qt/src/encryptjob.cpp, lang/qt/src/encryptjob.h (EncryptJob):
Add member functions setRecipients, recipients, setInputFile, inputFile,
setOutputFile, outputFile, setEncryptionFlags, encryptionFlags.
* lang/qt/src/encryptjob_p.h (EncryptJobPrivate): Add members
m_recipients, m_inputFilePath, m_outputFilePath, m_encryptionFlags.
* lang/qt/src/qgpgmeencryptjob.cpp (encrypt_to_filename): New.
(QGpgMEEncryptJobPrivate::startIt): Start the job with the values
from the member variables.
* lang/qt/src/qgpgmesignencryptjob.cpp (sign_encrypt_to_filename): New.
(QGpgMESignEncryptJobPrivate::startIt): Start the job with the values
from the member variables.
* lang/qt/src/qgpgmesignjob.cpp (class QGpgMESignJobPrivate): New.
(QGpgMESignJob::QGpgMESignJob): Instantiate private job class.
(sign_to_filename): New.
* lang/qt/src/signencryptjob.cpp (SignEncryptJob): Define constructor.
Define destructor as default. Include moc file.
* lang/qt/src/signencryptjob.cpp, lang/qt/src/signencryptjob.h
(SignEncryptJob): Add member functions setSigners, signers,
setRecipients, recipients, setInputFile, inputFile, setOutputFile,
outputFile, setEncryptionFlags, encryptionFlags.
* lang/qt/src/signencryptjob_p.h (SignEncryptJobPrivate): Add members
m_signers, m_recipients, m_inputFilePath, m_outputFilePath,
m_encryptionFlags.
* lang/qt/src/signjob.cpp: New.
* lang/qt/src/signjob.h (SignJob): Add member functions setSigners,
signers, setInputFile, inputFile, setOutputFile, outputFile,
setSigningFlags, signingFlags.
* lang/qt/src/signjob_p.h: New.
* lang/qt/tests/Makefile.am: Add new test programs.
* lang/qt/tests/run-encryptjob.cpp: New.
* lang/qt/tests/run-signjob.cpp: New.
--

This makes it possible to tell gpg to read the input and write the
output directly to a specified file bypassing GpgME's Data IO when
signing and/or encrypting a file.

GnuPG-bug-id: 6550
2023-12-21 11:49:23 +01:00
Ingo Klöcker
b166958b86
qt: Remove dead code
* lang/qt/src/qgpgmeencryptjob.cpp,
lang/qt/src/qgpgmesignencryptjob.cpp, lang/qt/src/qgpgmesignjob.cpp:
Remove long commented out showErrorDialog member function definitions.
--

Displaying error messages is delegated to the job users since ages.
2023-12-21 09:12:43 +01:00
Ingo Klöcker
60c0fd7c95
cpp: Support new flags for direct signing/encryption of files
* lang/cpp/src/context.h (enum EncryptionFlags): Add constant
EncryptFile.
* lang/cpp/src/global.h (enum SignatureMode): Add constant SignFile.
* lang/cpp/src/context.cpp (sigflags2sigflags): Handle new flag
SignFile.
(encryptflags2encryptflags): Handle new flag EncryptFile.
(operator<<): Add new flags to the corresponding debug streams.
* lang/cpp/src/signingresult.cpp (CreatedSignature::mode): Handle
new flag SignFile (even if it cannot occur).
--

GnuPG-bug-id: 6550
2023-12-19 14:01:18 +01:00
Ingo Klöcker
5efd3486a9
core: Support writing the decrypt/verify output directly to a file
* src/engine-gpg.c (gpg_decrypt): Pass output file name to gpg if output
has file name set.
(gpg_verify): Ditto.

* tests/run-decrypt.c (show_usage): New option --output.
(main): Parse new option. Set file name on output if --output is given.
Do not print output if --output is given.
* tests/run-verify.c (show_usage): New option --output.
(main): Parse new option. Set file name on output if --output is given.
--

This change makes it possible to tell gpg to write the output (i.e. the
decrypted/verified data) directly to a file with given file name instead
of piping the output back to gpgme.

GnuPG-bug-id: 6550
2023-12-19 13:12:59 +01:00
Ingo Klöcker
963ace1f9f
core: Support direct signing of file with gpg
* src/gpgme.h.in (GPGME_SIG_MODE_FILE): New signature mode flag.
* src/engine-gpg.c (gpg_sign): Separate signature mode from additional
flags. Check for incompatible flags. Explicitly set output to stdout if
no output file is used. Pass filename instead of fd to gpg when new flag
is set.
* src/engine-gpgsm.c (gpgsm_sign): Return error if new flag is set.
* src/engine-uiserver.c (uiserver_sign): Ditto.
* src/sign.c (sign_start): Consider new flag on check for invalid flags.

* tests/run-sign.c (show_usage): New options --detach and
--direct-file-io.
(main): Parse new options. Create a detached signature if --detach is
given. Make gpg read the input file itself if --direct-file-io is given.
--

With this change the gpgme_op_sign* functions gain the possibility to
make gpg read the data to sign directly from a file instead of from an
input FD to which it is written by gpgme.

GnuPG-bug-id: 6550
2023-12-19 13:09:33 +01:00
Ingo Klöcker
0221d7f28a
core: Support direct encryption of file with gpg
* src/gpgme.h.in (GPGME_ENCRYPT_FILE): New encryption flag.
* src/engine-gpg.c (gpg_encrypt, gpg_encrypt_sign): Check for
incompatible flags. Pass filename instead of fd to gpg when new flag is
set.
* src/engine-gpgsm.c (gpgsm_encrypt): Return error if new flag is set.
* src/engine-uiserver.c (uiserver_encrypt): Ditto.

* tests/run-encrypt.c (show_usage): New option --direct-file-io.
(main): Parse new option. Make gpg read the input file itself if the
option is given.
--

With this change the gpgme_op_encrypt* and gpgme_op_encrypt_sign*
functions gain the possibility to make gpg read the data to (sign and)
encrypt directly from a file instead of from an input FD to which it is
written by gpgme.

GnuPG-bug-id: 6550
2023-12-19 13:07:45 +01:00
Ingo Klöcker
b35bcf0040
doc: Fix documentation for creating encrypted/signed archive
--

The previous paragraph already explains where/how the result is stored.
In particular, it's not always "returned in the data object ...".
2023-12-14 09:29:43 +01:00
Ingo Klöcker
d5dafb2ae3
qt: Replace Q_FOREACH with range-for
* lang/qt/src/qgpgmekeyformailboxjob.cpp (do_work): Replace Q_FOREACH
with range-for.
* lang/qt/src/qgpgmekeylistjob.cpp (QGpgMEKeyListJob::resultHook):
Ditto.
* lang/qt/src/threadedjobmixin.cpp (_detail::audit_log_as_html): Ditto.
* lang/qt/tests/t-keylist.cpp (KeyListTest::testPubkeyAlgoAsString):
Ditto.
* lang/qt/tests/t-keylocate.cpp (KeyLocateTest::testDaneKeyLocate,
KeyLocateTest::testKeyLocateSingle): Ditto.
* lang/qt/src/qgpgmesignencryptjob.cpp (sign_encrypt): Replace Q_FOREACH
with range-for. Add braces around single statement blocks.
* lang/qt/src/qgpgmesignjob.cpp (sign): Ditto.
* lang/qt/src/qgpgmenewcryptoconfig.cpp
(QGpgMENewCryptoConfig::reloadConfiguration,
QGpgMENewCryptoConfig::sync,
QGpgMENewCryptoConfigComponent::setComponent,
QGpgMENewCryptoConfigEntry::urlValueList,
QGpgMENewCryptoConfigEntry::setURLValueList): Replace Q_FOREACH with
range-for. Fix indentation. Add braces around single statement blocks.
--

Where necessary the iterated object is wrapped with qAsConst to avoid
deep copies of the iterated object.
2023-12-13 13:16:21 +01:00
Ingo Klöcker
f7d69de030
qt: Replace Q_NULLPTR with nullptr
* lang/qt/src/defaultkeygenerationjob.h, lang/qt/src/qgpgmebackend.h,
lang/qt/src/quickjob.h, lang/qt/src/threadedjobmixin.h: Replace all
occurrences of Q_NULLPTR with nullptr.
--
2023-12-13 13:04:32 +01:00
Andre Heinecke
6baccdc0c3
core: percent decode filename
* src/op-support.c (_gpgme_parse_plaintext): Decode filename
as percent string.

--
From gnupg/doc/DETAILS:

    If a filename is available it gets printed as the third
    argument, percent-escaped as usual.

so we can use the usual percent decode function here.

GnuPG-Bug-Id: T6852
2023-11-30 00:06:08 +01:00
Werner Koch
f212de4a9e
Post release updates
--
2023-11-28 16:48:37 +01:00
Werner Koch
1a26db7175
Release 1.23.2 2023-11-28 16:42:59 +01:00
Ingo Klöcker
1bbe2d4b70
qt: Start dirmngr with gpgconf to avoid multiple instances
* lang/qt/src/qgpgmewkdlookupjob.cpp (startDirmngr): Use "gpgconf
--launch dirmngr" to start dirmngr.
--

Using gpgconf to start dirmngr prevents multiple instances to be started
by the concurrently running keyserver lookup and WKD lookup.

GnuPG-bug-id: 6833
2023-11-23 16:13:39 +01:00
Ingo Klöcker
618fea9e20
qt: On Windows, use UTF-8 when logging the error text
* lang/qt/src/debug.cpp (operator<<): On Windows, interpret the error
text as UTF-8 instead of local 8-bit encoding.
--

GnuPG-bug-id: 5960
2023-11-15 11:57:18 +01:00
Ingo Klöcker
278f92b189
qt: Remove left-over partial files more persistently
* lang/qt/src/Makefile.am: Add new files.
* lang/qt/src/cleaner.cpp, lang/qt/src/cleaner.h: New.
* lang/qt/src/util.cpp (PartialFileGuard::~PartialFileGuard): Call
Cleaner::removeFile instead of removeFile.
* lang/qt/src/util.cpp, lang/qt/src/util.h (removeFile): Remove.
--

If the initial attempt to remove the file fails then a Cleaner is
created that tries to remove the file at regular intervals (10 s)
and on destruction (which happens on application shutdown).

GnuPG-bug-id: 6584
2023-11-15 11:57:18 +01:00
NIIBE Yutaka
185ab7d7ba
doc: Fix for e.g. and i.e.
--

Signed-off-by: NIIBE Yutaka <gniibe@fsij.org>
2023-11-15 15:21:07 +09:00
Ingo Klöcker
77e982579c
core: Preserve more specific existing failure code
* src/decrypt.c (_gpgme_decrypt_status_handler): Ignore received failure
code if we already have a specific failure code.
* src/encrypt.c (_gpgme_encrypt_status_handler): Ditto.
* src/export.c (export_status_handler): Ditto.
* src/genkey.c (genkey_status_handler): Ditto.
* src/keylist.c (keylist_status_handler): Ditto.
* src/keysign.c (keysign_status_handler): Ditto.
* src/passwd.c (passwd_status_handler): Ditto.
* src/revsig.c (revsig_status_handler): Ditto.
* src/setexpire.c (setexpire_status_handler): Ditto.
* src/sign.c (_gpgme_sign_status_handler): Ditto.
* src/tofupolicy.c (tofu_policy_status_handler): Ditto.
* src/verify.c (_gpgme_verify_status_handler): Ditto.
--

Usually, a process emits at most one failure code. But some operations
like the creation of an encrypted archive involve multiple chained
processes, so that multiple failure codes can be received. We want to
keep the first specific failure code we received. Further failure codes
are only parsed if we received just an unspecific "general error" so
far.

GnuPG-bug-id: 6575
2023-11-14 13:51:24 +01:00
Werner Koch
1bfd5e92d0
tests: Add option --chain to run-keylist
* tests/run-keylist.c (xstrdup): New.
(main): Add option.
--

This allows to list the entire chain.
2023-11-10 09:45:35 +01:00
Ingo Klöcker
52d59d75ca
qt: Deprecate DefaultKeyGenerationJob
* lang/qt/src/defaultkeygenerationjob.h (class DefaultKeyGenerationJob):
Deprecate.
--

GnuPG generates Ed25519 keys by default and has switched to 3072 bits as
default for RSA keys. DefaultKeyGenerationJob always generates RSA 2048
keys and uses the old parameter file API of GnuPG. It shouldn't be used
anymore.

GnuPG-bug-id: 6805
2023-11-10 08:55:07 +01:00
Ingo Klöcker
ae332749ee
build,qt: Build Qt with -fPIC if required or requested
* configure.ac: Add option to enable building the Qt 6 binding with
-fPIC. Fix typo and mention default for --enable-no-direct-extern-access
option.
* m4/qt6.m4: Add -fPIC to GPGME_QT6_CFLAGS if requested or if Qt 6 was
built with reduce_relocations.
--

GnuPG-bug-id: 6781
2023-10-30 09:42:09 +01:00
Ingo Klöcker
cf88690cf4
Update NEWS
--
2023-10-27 16:14:01 +02:00
Ingo Klöcker
46f5d5eeb3
qt: Use temporary .part file names when creating archives
* lang/qt/src/util.h, lang/qt/src/util.cpp (class PartialFileGuard):
New.
* lang/qt/src/util.cpp (getRandomCharacters, createPartFileName): New.
* lang/qt/src/qgpgmeencryptarchivejob.cpp (encrypt_to_filename): Use
PartialFileGuard.
* lang/qt/src/qgpgmesignarchivejob.cpp (sign_to_filename): Ditto.
* lang/qt/src/qgpgmesignencryptarchivejob.cpp
(sign_encrypt_to_filename): Ditto.
--

When creating signed and/or encrypted archives, gpgtar now writes the
result to a temporary file name. On success, the archive is renamed to
the final file name. Otherwise, the (partially written) temporary file
is removed (if possible).

GnuPG-bug-id: 6721
2023-10-27 16:07:34 +02:00
Ingo Klöcker
8d8985bda1
qt: Refactor removal of output file on cancel or error
* lang/qt/src/util.h, lang/qt/src/util.cpp (removeFile): New.
* lang/qt/src/qgpgmeencryptarchivejob.cpp (encrypt): Move removal of
output file from here
(encrypt_to_filename): ... to here and use new function.
* lang/qt/src/qgpgmesignarchivejob.cpp (sign): Move removal of output
file from here
(sign_to_filename): ... to here and use new function.
* lang/qt/src/qgpgmesignencryptarchivejob.cpp (sign_encrypt): Move
removal of output file from here
(sign_encrypt_to_filename): ... to here and use new function.
--

GnuPG-bug-id: 6721
2023-10-27 16:07:34 +02:00
Werner Koch
0a0a5906d5
Post release updates
--
2023-10-27 14:41:52 +02:00
Werner Koch
cadcb38469
Release 1.23.1
--

This is minor fix to the spawn helper.  No change to the library code.

GnuPG-bug-id: 6774
2023-10-27 14:36:15 +02:00
Andre Heinecke
a0a4cd411c
Change gpgme-w32-spawn to unicode
* src/Makefile.am (gpgme_w32spawn_CFLAGS): Add -municode.
* src/gpgme-w32-spawn.c (build_commandline, my_spawn)
(translate_handles): Convert to wchar_t API.
(main): Use wmain instead.

--
Some time ago we introduced an inconsistency that w32-util called
gpgme-w32-spawn through CreateProcessW but since gpgme-w32-spawn
internally worked with 8 bit the chars were mangled and the
arguments not passed correctly through the CreateProcessA of the
child process. Since the GnuPG processes use GetCommandLineW
this is the proper way to pass on Unicode command line arguments.

Please note that we did not pass UTF-8 before this patch but
rather some broken native encoding where Windows replaces
unicode characters with question marks etc.

GnuPG-Bug-Id: T6728
2023-10-25 17:42:27 +02:00
Werner Koch
8faaf7b72b
Post release updates
--
2023-10-25 11:16:19 +02:00
Werner Koch
aae967ec9c
Release 1.23.0 2023-10-25 11:05:29 +02:00
Andre Heinecke
ab25df8328
qt: Handle cancel in changeexpiryjob
* lang/qt/src/qgpgmechangeexpiryjob.cpp (change_expiry): Return
cancel error.

--
The classical "cancel is not an error" problem.
GnuPG-Bug-Id: T6754
2023-10-18 11:13:35 +02:00
Ingo Klöcker
5c7e4d252a
qt,doc: Fix typos in source code comments
--

Anonymous contribution

Signed-off-by: Ingo Klöcker <dev@ingo-kloecker.de>
2023-10-13 09:23:24 +02:00
Ingo Klöcker
131384b107
python,doc: Fix typos in documentation and source code comments
--

Anonymous contribution

Signed-off-by: Ingo Klöcker <dev@ingo-kloecker.de>
2023-10-13 09:22:36 +02:00
Ingo Klöcker
bd448c9cbf
cpp,doc: Fix typos in API documentation and source code comments
--

Anonymous contribution

Signed-off-by: Ingo Klöcker <dev@ingo-kloecker.de>
2023-10-13 09:21:47 +02:00
Ingo Klöcker
57205c1dfa
doc: Fix typos in documentation and source code comments
--

Anonymous contribution

Signed-off-by: Ingo Klöcker <dev@ingo-kloecker.de>
2023-10-13 09:18:12 +02:00
Marius P
959f976dfc
python,examples: Add missing word "License"
* lang/python/examples/howto/add-userid.py,
lang/python/examples/howto/clear-sign-file.py,
lang/python/examples/howto/create-key.py,
lang/python/examples/howto/decrypt-file.py,
lang/python/examples/howto/detach-sign-file.py,
lang/python/examples/howto/encrypt-file.py,
lang/python/examples/howto/encrypt-sign-file.py,
lang/python/examples/howto/encrypt-to-group-gullible.py,
lang/python/examples/howto/encrypt-to-group-trustno1.py,
lang/python/examples/howto/encrypt-to-group.py,
lang/python/examples/howto/export-key.py,
lang/python/examples/howto/export-minimised-key.py,
lang/python/examples/howto/export-secret-key.py,
lang/python/examples/howto/export-secret-keys.py,
lang/python/examples/howto/groups.py,
lang/python/examples/howto/import-key.py,
lang/python/examples/howto/import-keybasekey.py,
lang/python/examples/howto/import-keys-hkp.py,
lang/python/examples/howto/import-keys.py,
lang/python/examples/howto/import-mailvelope-keys.py,
lang/python/examples/howto/keycount.py,
lang/python/examples/howto/local-sign-group.py,
lang/python/examples/howto/mutt-groups.py,
lang/python/examples/howto/pmkey-import-alt.py,
lang/python/examples/howto/pmkey-import-hkp-alt.py,
lang/python/examples/howto/pmkey-import-hkp.py,
lang/python/examples/howto/pmkey-import.py,
lang/python/examples/howto/revoke-userid.py,
lang/python/examples/howto/send-key-to-keyserver.py,
lang/python/examples/howto/sign-file.py,
lang/python/examples/howto/sign-key.py,
lang/python/examples/howto/symcrypt-file.py,
lang/python/examples/howto/temp-homedir-config.py,
lang/python/examples/howto/verify-signatures.py,
lang/python/examples/howto/verify-signed-file.py: Add "License" after
"Lesser General Public"
--

Anonymous contribution

Signed-off-by: Ingo Klöcker <dev@ingo-kloecker.de>
2023-10-13 09:08:39 +02:00
Ingo Klöcker
a9e5a25b56
cpp: Support new key capability flags
* lang/cpp/src/key.cpp, lang/cpp/src/key.h (class Key): New methods
hasCertify, hasSign, hasEncrypt, hasAuthenticate.
--

GnuPG-bug-id: 6748
2023-10-05 15:27:52 +02:00
Ingo Klöcker
0132a1089f
doc: Fix typo
--
2023-10-05 15:12:29 +02:00
Werner Koch
b63d203d3b
core: Add key capability flags has_encrypt etc.
* src/gpgme.h.in (struct _gpgme_key): Add flags has_encrypt,
has_certify, has_sign, and has_authenticate.
* src/keylist.c (finish_key): Set these flags.
* tests/run-keylist.c (main): Print them.
--

GnuPG-bug-id: 6748
2023-10-05 14:18:03 +02:00
Werner Koch
349a69b5ea
core: Check STATUS_FAILURE in export operations.
* src/export.c (op_data_t): Add failure_code.
(export_status_handler): Set it.
(gpgme_op_export_ext, gpgme_op_export_keys): Also check the failure
code.
--

That is just in case we missed an error code.  For example with older
gpg versions (e.g. 2.3.8) and exporting to a keyserver.
2023-10-05 14:17:21 +02:00
NIIBE Yutaka
8ad22290df
gpgme-tool: Support use of Windows HANDLE for INPUT/OUTPUT/MESSAGE.
* src/gpgme-tool.c [HAVE_W32_SYSTEM] (server_data_obj): Implement for
Windows HANDLE.

--

GnuPG-bug-id: 6634
Signed-off-by: NIIBE Yutaka <gniibe@fsij.org>
2023-09-29 11:12:13 +09:00
Ingo Klöcker
d43d787e9a
qt: Use UTF-8 for file names on Windows
* lang/qt/src/qgpgmedecryptverifyarchivejob.cpp
(decrypt_verify_from_file_name): On Windows, convert Unicode file name
to UTF-8.
* lang/qt/src/qgpgmeencryptarchivejob.cpp (encrypt,
encrypt_to_filename): On Windows, convert Unicode file name from/to
UTF-8.
* lang/qt/src/qgpgmesignarchivejob.cpp (sign, sign_to_filename): Ditto.
* lang/qt/src/qgpgmesignencryptarchivejob.cpp (sign_encrypt,
sign_encrypt_to_filename): Ditto.
--

On Windows, GnuPG expects file names to be UTF-8-encoded. This fixes
encrypting and decrypting folders with umlauts in the folder name and
in the file name of the archive. Encrypting and decrypting folders
with kanji still fails.

GnuPG-bug-id: 6728
2023-09-22 10:22:18 +02:00
Ingo Klöcker
4e321a0f06
build,qt: Autodetect whether Qt was built with -mno-direct-extern-access
* m4/qt6.m4: Check the build configuration of Qt 6 for
no_direct_extern_access.
--

If building with -mno-direct-extern-access has been neither enabled nor
disabled explicitly, then check whether Qt 6 was built with this flag.
The check is skipped, if we build for Windows.

GnuPG-bug-id: 6696
2023-09-21 22:53:00 +02:00
Ingo Klöcker
927f129663
build,qt: Optionally build Qt 6 bindings with -mno-direct-extern-access
* configure.ac: Check if C++ compiler supports
-mno-direct-extern-access. Add option to enable building with
-mno-direct-extern-access.
* m4/ax_check_compile_flag.m4: New.
* m4/qt6.m4: Add -mno-direct-extern-access to GPGME_QT6_CFLAGS if
supported and requested.
--

This adds the possibility to build the Qt 6 bindings with the
-mno-direct-extern-access flag. This is required if Qt 6 was built with
this flag. This is a workaround for the lack of Qt 6's pkgconfig files
providing this flag if needed.

GnuPG-bug-id: 6696
2023-09-21 10:58:27 +02:00
Ingo Klöcker
3e64856208
build,qt: Drop broken check for -fPIC
* m4/qt6.m4: Remove attempt to build a Qt program with -fPIC.
--

libtool already takes care of adding -fPIC. Moreover, building without
-fPIC succeeded even if Qt was built with -fPIC, i.e. the check didn't
work as intended.

GnuPG-bug-id: 6696
2023-09-21 10:45:09 +02:00
Ingo Klöcker
8fde9cbe22
tests: Re-add --with-secret option
* tests/run-keylist.c (main): Handle option --with-secret again.
--

Re-add handling of --with-secret option that was accidentally removed
with the previous commit.

GnuPG-bug-id: 6705
2023-09-04 17:31:18 +02:00
Werner Koch
e36b2d1bce
New mode to list a v5 fingerprint for v4 packets.
* src/gpgme.h.in (GPGME_KEYLIST_MODE_WITH_V5FPR): New.
(struct _gpgme_subkey): Add field v5fpr.
* src/engine-gpg.c (gpg_keylist_build_options): Pass new option to
gpg.
* src/key.c (gpgme_key_unref): Free new field.
* src/keylist.c (op_data_t): Parse and add "fp2" line.

* tests/run-keylist.c (show_usage): Add option --v5fpr.

* src/keylist.c (op_data_t): Add field failure_code.
(keylist_status_handler): Handle special value.
(gpgme_op_keylist_end): Return an error if a FAILURE line has been
seen.
--

Note that the failure code part has been added to better diagnose
problems if a wrong gpg version is used.  If verything works right we
should not get this because we check that the gnupg version sis either
>= 2.4.4 or less than 2.3 and >= 2.2.42.

Note further that the v5fpr field may also be used to get the SHA-256
fingerprint of X.509 certificates (even without passing the new mode
flag).

GnuPG-bug-id: 6705
2023-09-04 17:03:52 +02:00
NIIBE Yutaka
b80d52a1f7
build: Change the default for --with-libtool-modification.
* configure.ac (--with-libtool-modification): default=never.

--

GnuPG-bug-id: 6619
Signed-off-by: NIIBE Yutaka <gniibe@fsij.org>
2023-09-01 14:06:25 +09:00
Werner Koch
d75b2a9151
Support GPGME_ENCRYPT_ALWAYS_TRUST also for S/MIME.
* src/engine-gpgsm.c (gpgsm_encrypt): Send the always-trust options.

* tests/run-encrypt.c: Add option --always-trust.
--

Note that the run-encrypt test tool used to assume always-trust for
OpenPGP since 1.7.0 This bug has also been fixed by introducing the
explicit option.

GnuPG-bug-id: 6559
2023-08-31 12:02:02 +02:00
Ingo Klöcker
3f297387bf
qt: Allow specifying user IDs to use when refreshing keys via WKD
* lang/qt/src/wkdrefreshjob.h, lang/qt/src/wkdrefreshjob.cpp
(WKDRefreshJob::start): New overload.
* lang/qt/src/wkdrefreshjob_p.h (WKDRefreshJobPrivate): Add field
m_userIds.
* lang/qt/src/qgpgmewkdrefreshjob.cpp (toEmailAddresses): New.
(locate_external_keys): Change return type and arguments.
(refresh_keys): Remove.
(QGpgMEWKDRefreshJobPrivate::startIt): Get emails from keys or user IDs.
Remove duplicates. Call locate_external_keys instead of refresh_keys.

* lang/qt/tests/run-wkdrefreshjob.cpp (CommandLineOptions,
parseCommandLine): New.
(main): Support new option --all-userids.
--

The new start() overload allows to specify the user IDs to use for the
WKD lookup explicitly. This allows updating user IDs via WKD which were
originally not retrieved via WKD.

GnuPG-bug-id: 6672
2023-08-23 12:00:26 +02:00
Christian Hesse
aee18a2ab2
qt,tests: Fix build in source directory, part 2
* lang/qt/tests/Makefile.am (AM_CPPFLAGS): Include Qt binding sources
before C++ binding sources and C sources.
--

This fixes the problem that the debug.h in the C sources was found
before the one in the Qt bindings.

Commit d23528cadf fixed it for Qt5, we
need Qt6 as well.

GnuPG-bug-id: 6673
2023-08-22 11:15:01 +02:00
Ingo Klöcker
24a8c279da
build: Suggest out-of-source build
* autogen.rc (final_info): Suggest to run configure from a build
subdirectory.
--

We recommend out-of-source builds. The suggestion what to do next shown
by autogen.sh should reflect this.

GnuPG-bug-id: 6673
2023-08-21 21:32:40 +02:00
Ingo Klöcker
d23528cadf
qt,tests: Fix build in source directory
* lang/qt/tests/Makefile.am (AM_CPPFLAGS): Include Qt binding sources
before C++ binding sources and C sources.
--

This fixes the problem that the debug.h in the C sources was found
before the one in the Qt bindings.

GnuPG-bug-id: 6673
2023-08-21 21:08:01 +02:00
Ingo Klöcker
2ad36f7114
qt: Add job for refreshing OpenPGP keys via WKD
* lang/qt/src/wkdrefreshjob.cpp, lang/qt/src/wkdrefreshjob.h,
lang/qt/src/wkdrefreshjob_p.h, lang/qt/src/qgpgmewkdrefreshjob.cpp,
lang/qt/src/qgpgmewkdrefreshjob.h: New.
* lang/qt/src/protocol.h (class Protocol): Add pure virtual member
function wkdRefreshJob
* lang/qt/src/protocol_p.h (Protocol::wkdRefreshJob): ... and
implement it.
* lang/qt/src/Makefile.am: Update accordingly.

* lang/qt/tests/run-wkdrefreshjob.cpp: New.
* lang/qt/tests/Makefile.am: Add new test runner.
--

This job allows updating keys via WKD. Only user IDs that were
originally retrieved via WKD (i.e. which have origin WKD) are
considered.

GnuPG-bug-id: 6672
2023-08-21 18:06:52 +02:00
Ingo Klöcker
fb03a5b3df
doc: Fix interface changes
--

toLogString is in the QGpgME namespace (as everything else in the qt
bindings).
2023-08-21 10:19:09 +02:00
Werner Koch
cfeb62d358
Post release updates
--
2023-08-21 09:54:04 +02:00
Werner Koch
8ea7015a23
Release 1.22.0 2023-08-21 09:41:39 +02:00
NIIBE Yutaka
dacbd51c3f
build: New configure option --with-libtool-modification.
* Makefile.am (EXTRA_DIST): Add build-aux/libtool-patch.sed.
* build-aux/libtool-patch.sed: New.
* configure.ac (--with-libtool-modification): New.
* build-aux/ltmain.sh: Revert our own local modification.

--

Fixes-commit: e622e36f1f
GnuPG-bug-id: 6619
Signed-off-by: NIIBE Yutaka <gniibe@fsij.org>
2023-08-17 14:03:09 +09:00
Ingo Klöcker
40ca3d5896
qt: Clean up after failure or cancel of sign/encrypt archive operation
* lang/qt/src/qgpgmeencryptarchivejob.cpp (encrypt): Remove output file
if operation was canceled or failed.
* lang/qt/src/qgpgmesignarchivejob.cpp (sign): Ditto.
* lang/qt/src/qgpgmesignencryptarchivejob.cpp (sign_encrypt): Ditto.

* lang/qt/tests/run-encryptarchivejob.cpp (CommandLineOptions): Add
field cancelTimeout.
(parseCommandLine): Add option --cancel-after. Parse option value.
(main): Check for invalid cancel timeout. Start timer for canceling
the job.
* lang/qt/tests/run-signarchivejob.cpp (CommandLineOptions): Add
field cancelTimeout.
(parseCommandLine): Add option --cancel-after. Parse option value.
(main): Check for invalid cancel timeout. Start timer for canceling
the job.
--

This change ensures that the output file is removed if the creation of
a signed or encrypted archive was canceled or failed. The new option
of the test runners enables testing the cancelation of the jobs.

GnuPG-bug-id: 6584
2023-08-16 14:23:15 +02:00
Ingo Klöcker
c3171d0cf1
qt: Make toLogString helper public
* lang/qt/src/util.h: Move toLogString ...
* lang/qt/src/debug.h: ... here.
* lang/qt/tests/run-importjob.cpp (main): Use toLogString.
--

This allows using the helper in dependent projects without duplicating
it everywhere.

GnuPG-bug-id: 6584
2023-08-15 11:56:40 +02:00
Ingo Klöcker
7a2a3f317b
cpp: Remove unused include
--
2023-08-15 11:50:28 +02:00
Ingo Klöcker
150a2f9e4e
tests: Support offline mode in run-import
* tests/run-import.c (show_usage): New option --offline.
(main): Parse new option. Set offline mode accordingly.
--

This allows testing gpgme_op_import with (and without) offline mode.

GnuPG-bug-id: 6648
2023-08-14 14:04:44 +02:00
Ingo Klöcker
bc98f01c85
core: Use offline mode for all operations of gpgsm engine
* src/engine-backend.h (keylist, keylist_ext): Remove engine_flags.
* src/engine-gpg.c (gpg_keylist, gpg_keylist_ext): Ditto.
* src/engine.c, src/engine.h (_gpgme_engine_op_keylist): Ditto.
(_gpgme_engine_op_keylist_ext): Ditto.
* src/engine.h (GPGME_ENGINE_FLAG_OFFLINE): Remove.
* src/engine-gpgsm.c (struct engine_gpgsm): New field flags with offline
flag.
(have_gpgsm_version): New.
(gpg_set_engine_flags): Set the offline flag.
(start): Send OPTION "offline".
(gpgsm_keylist, gpgsm_keylist_ext): Remove engine_flags.  Remove
sending of OPTION "offline".
* src/keylist.c (gpgme_op_keylist_start, gpgme_op_keylist_ext_start):
Remove setting of offline flag.
--

GnuPG-bug-id: 6648
2023-08-14 12:24:00 +02:00
Ingo Klöcker
d72811a2c0
core: Store engine's version string in gpgsm engine
* src/engine-gpgsm.c (struct engine_gpgsm): Add field 'version'.
(gpgsm_new): Copy version string.
(gpgsm_release): Free VERSION.
--

GnuPG-bug-id: 6648
2023-08-14 12:23:55 +02:00
Carl Schwan
8701e98937
cpp: Expose gpgme_decrypt_result_t.is_mime through cpp API
* lang/cpp/src/descriptionresult.cpp (DescriptionResult::isMime): New.
* lang/cpp/src/descriptionresult.h: Update accordingly.

--
This exposes the is_mime metadata from a decryption result to users
of the C++ library.

GnuPG-bug-id: 6199
Signed-off-by: Carl Schwan <carl.schwan@gnupg.com>
2023-08-04 11:34:27 +02:00
Carl Schwan
d91d037fc1
qt: Add setInputEncoding to QGpgMe::EncryptJob
* lang/qt/src/encryptjob.cpp, lang/qt/src/encryptjob.h,
lang/qt/src/encryptjob_p.h: Add inputEncoding/setInputEncoding
to EncryptJob
* lang/qt/src/qgpgmeencryptjob.cpp: Use newly added inputEncoding
to set encoding hint of the encrypted content
--

This allows applications like KMail to set the input encoding of the
encrypted content, which simplify and improve the performance of
identifying the content type then decrypting it.

GnuPG-bug-id: 6616
Signed-off-by: Carl Schwan <carl.schwan@gnupg.com>
2023-08-03 11:53:06 +02:00
Ingo Klöcker
a9b28c79e9
core: Prevent wrong plaintext when verifying clearsigned signature
* src/engine-gpg.c (gpg_verify): Use a separate pipe instead of stdout
for reading the plaintext.

* tests/gpg/t-support.h (PGM): Define if undefined.
(print_data): Undefine BUF_SIZE.
(check_data): New.
* tests/gpg/t-verify.c (clearsigned_plus_key_block): New.
(main): Add test.
--

Reading the plaintext from stdout is a bad idea because gpg can also
print other stuff on stdout, e.g. the keys contained in a public key
block. This is fixed by reading the plaintext via a special pipe.

GnuPG-bug-id: 6622
2023-07-28 16:15:12 +02:00
Ingo Klöcker
777cf7f2d1
core: Return bad data error instead of general error on unexpected data
* src/verify.c (_gpgme_verify_status_handler): Return GPG_ERR_BAD_DATA
instead of GPG_ERR_GENERAL.
--

This gives users trying to decrypt and/or verify for example a public
key block a more useful error.

GnuPG-bug-id: 6617
2023-07-28 14:18:21 +02:00
NIIBE Yutaka
0518ed32e2
build: Update libassuan.m4 for libassuan version 3 in future.
* m4/libassuan.m4: Update from libassuan master.

--

New libassuan 3 has backward compatible API.

Signed-off-by: NIIBE Yutaka <gniibe@fsij.org>
2023-07-28 14:07:06 +09:00
Ingo Klöcker
e3defc0adf
qt: Ensure that we check the correct paths
* lang/qt/src/QGpgmeConfig-w32.cmake.in.in,
lang/qt/src/QGpgmeQt6Config-w32.cmake.in.in: Get paths to check from
the target properties.
--

This avoids the error present in an older version where the files to
check used the correct path, but a wrong path of the DLL was set in the
target properties.
2023-07-08 21:49:12 +02:00
Ingo Klöcker
be0e653ce3
qt: Fix DLL version in cmake config files
* lang/qt/src/QGpgmeConfig-w32.cmake.in.in,
lang/qt/src/QGpgmeQt6Config-w32.cmake.in.in: Fix name and path of DLL.
--

Co-authored-by: Biswapriyo Nath <nathbappai@gmail.com>
Signed-off-by: Ingo Klöcker <dev@ingo-kloecker.de>
2023-07-08 21:49:12 +02:00
Ingo Klöcker
ad34fcbbec
qt: Fix check for required files
* lang/qt/src/QGpgmeConfig-w32.cmake.in.in: Fix typos in variable names.
--

Because of those typos the loop over the files to check was an empty
loops and therefore the wrong name of the DLL was never noticed.
2023-07-08 21:49:12 +02:00
Werner Koch
546d3a982d
Post release updates
--
2023-07-07 14:01:51 +02:00
Werner Koch
5bf3e6d075
Release 1.21.0 2023-07-07 13:35:14 +02:00
NIIBE Yutaka
05ac1ce09f
build: Add BUILT_SOURCE for better dependency.
* Makefile.am (BUILT_SOURCE): Add conf/config.h.

--

GnuPG-bug-id: 6547
Signed-off-by: NIIBE Yutaka <gniibe@fsij.org>
2023-06-23 10:38:24 +09:00
Ingo Klöcker
1c2459a592
qt: Support reading signed/encrypted archives directly from a file
* lang/qt/src/decryptverifyarchivejob.cpp,
lang/qt/src/decryptverifyarchivejob.h (DecryptVerifyArchiveJob): Add
member functions setInputFile, inputFile.
* lang/qt/src/decryptverifyarchivejob_p.h
(DecryptVerifyArchiveJobPrivate): Add member m_inputFilePath.
* lang/qt/src/qgpgmedecryptverifyarchivejob.cpp (decrypt_verify): Move
creation of indata to decrypt_verify_from_io_device.
(decrypt_verify_from_io_device, decrypt_verify_from_file_name): New.
(QGpgMEDecryptVerifyArchiveJob::start): Use
decrypt_verify_from_io_device instead of decrypt_verify.
(QGpgMEDecryptVerifyArchiveJobPrivate::startIt): Start the job with the
values from member variables.

* lang/qt/tests/run-decryptverifyarchivejob.cpp (createInput): Remove.
(main): Remove creation of input. Make the job read the archive directly
from the given archive name.
--

This makes it possible to tell gpgtar to read the signed/encrypted
archive directly from a specified file bypassing GpgME's Data IO.

GnuPG-bug-id: 6530
2023-06-21 15:25:11 +02:00
Ingo Klöcker
1a9f192ab4
core: Support reading the archive to decrypt/verify directly from a file
* src/engine-gpg.c (add_file_name_arg_or_data): New.
(gpg_decrypt): Use add_file_name_arg_or_data instead of add_data for the
ciphertext.
(gpg_verify): Use add_file_name_arg_or_data instead of add_data for the
signature and the signed text.

* tests/run-decrypt.c (show_usage): New option --direct-file-io.
(main): Parse new option. If option is given, then don't open input
file, create simple data object instead of data object from stream and
set input file name on input data.
* tests/run-verify.c (show_usage): New option --direct-file-io.
(main): Parse new option. If option is given, then don't open input
files, create simple data objects instead of data objects from stream
and set input file names on input data objects.
--

This change makes it possible to tell gpg (and gpgtar) to read the
input (i.e. the signed/encrypted data or the signature or the created
archive) directly from the files with given file names instead of from
streams piped through GpgME's Data IO.

GnuPG-bug-id: 6530
2023-06-21 14:38:50 +02:00
Ingo Klöcker
e608315392
qt: Support writing signed/encrypted archives directly to a file
* lang/qt/src/encryptarchivejob.cpp, lang/qt/src/encryptarchivejob.h
(EncryptArchiveJob): Add member functions setRecipients, recipients,
setInputPaths, inputPaths, setOutputFile, outputFile,
setEncryptionFlags, encryptionFlags.
* lang/qt/src/encryptarchivejob_p.h (EncryptArchiveJobPrivate): Add
members m_recipients, m_inputPaths, m_outputFilePath, m_encryptionFlags.
* lang/qt/src/qgpgmeencryptarchivejob.cpp (encrypt): Move creation of
outdata to encrypt_to_io_device.
(encrypt_to_io_device, encrypt_to_filename): New.
(QGpgMEEncryptArchiveJob::start): Use encrypt_to_io_device instead of
encrypt.
(QGpgMEEncryptArchiveJobPrivate::startIt): Start the job with the
values from member variables.
* lang/qt/src/qgpgmesignarchivejob.cpp (sign): Move creation of
outdata to sign_to_io_device.
(sign_to_io_device, sign_to_filename): New.
(QGpgMESignArchiveJob::start): Use sign_to_io_device instead of sign.
(QGpgMESignArchiveJobPrivate::startIt): Start the job with the
values from member variables.
* lang/qt/src/qgpgmesignencryptarchivejob.cpp (sign_encrypt): Move
creation of outdata to sign_encrypt_to_io_device.
(sign_encrypt_to_io_device, sign_encrypt_to_filename): New.
(QGpgMESignEncryptArchiveJob::start): Use sign_encrypt_to_io_device
instead of sign_encrypt.
(QGpgMESignEncryptArchiveJobPrivate::startIt): Start the job with the
values from member variables.
* lang/qt/src/signarchivejob.cpp, lang/qt/src/signarchivejob.h
(SignArchiveJob): Add member functions setSigner, signers,
setInputPaths, inputPaths, setOutputFile, outputFile.
* lang/qt/src/signarchivejob_p.h (SignArchiveJobPrivate): Add
members m_signers, m_inputPaths, m_outputFilePath.
* lang/qt/src/signencryptarchivejob.cpp,
lang/qt/src/signencryptarchivejob.h (SignEncryptArchiveJob): Add
member functions setSigner, signers, setRecipients, recipients,
setInputPaths, inputPaths, setOutputFile, outputFile,
setEncryptionFlags, encryptionFlags.
* lang/qt/src/signencryptarchivejob_p.h (SignEncryptArchiveJobPrivate):
Add members m_signers, m_recipients, m_inputPaths, m_outputFilePath,
m_encryptionFlags.

* lang/qt/tests/run-encryptarchivejob.cpp (createOutput): Remove.
(checkOutputFilePath): New.
(main): Create file output writing to stdout if no archive name (or "-")
is given. Exit if file with given archive name already exists. Make
the jobs write the created archive directly to the given archive name.
* lang/qt/tests/run-signarchivejob.cpp (createOutput): Remove.
(checkOutputFilePath): New.
(main): Create file output writing to stdout if no archive name (or "-")
is given. Exit if file with given archive name already exists. Make
the jobs write the created archive directly to the given archive name.
--

This makes it possible to tell gpgtar to write the created archive
directly to a specified file bypassing GpgME's Data IO.

GnuPG-bug-id: 6530
2023-06-19 18:21:46 +02:00
Ingo Klöcker
c38b620039
core: Support writing the sign/encrypt output directly to a file
* src/engine-gpg.c (gpg_encrypt): Pass output file name to gpg if output
has file name set.
(gpg_encrypt_sign): Ditto.
(gpg_sign): Ditto.

* tests/run-encrypt.c (show_usage): New option --output.
(main): Parse new option. Set file name on output if --output is given.
Do not print output if --output is given.
* tests/run-sign.c (show_usage): New option --output.
(main): Parse new option. Set file name on output if --output is given.
Do not print output if --output is given.
--

This change makes it possible to tell gpg (and gpgtar) to write the
output (i.e. the signed/encrypted data or the signature or the created
archive) directly to a file with given file name instead of piping
the output back to gpgme.

GnuPG-bug-id: 6530
2023-06-19 18:08:47 +02:00
Ingo Klöcker
8b9fabf5d5
qt: Add a generic hook to start a job
* lang/qt/src/job.cpp, lang/qt/src/job.h (Job::startIt): New method.
* lang/qt/src/job_p.h (JobPrivate::startIt): New pure virtual method.
* lang/qt/src/qgpgmechangeexpiryjob.cpp
(QGpgMEChangeExpiryJobPrivate::startIt): New.
* lang/qt/src/qgpgmedecryptverifyarchivejob.cpp
(QGpgMEDecryptVerifyArchiveJobPrivate::startIt): New.
* lang/qt/src/qgpgmeencryptarchivejob.cpp
(QGpgMEEncryptArchiveJobPrivate::startIt): New.
* lang/qt/src/qgpgmeencryptjob.cpp (QGpgMEEncryptJobPrivate::startIt):
New.
* lang/qt/src/qgpgmeimportjob.cpp (QGpgMEImportJobPrivate::startIt):
New.
* lang/qt/src/qgpgmelistallkeysjob.cpp
(QGpgMEListAllKeysJobPrivate::startIt): New.
* lang/qt/src/qgpgmesignarchivejob.cpp
(QGpgMESignArchiveJobPrivate::startIt): New.
* lang/qt/src/qgpgmesignencryptarchivejob.cpp
(QGpgMESignEncryptArchiveJobPrivate::startIt): New.
* lang/qt/src/qgpgmesignencryptjob.cpp
(QGpgMESignEncryptJobPrivate::startIt): New.
--

startIt() starts a job if the necessary values have been set before.
This makes it possible to extend jobs with additional ways to start them
without having to worry about overloading existing virtual start()
methods. This will be used first for the different archive jobs.

GnuPG-bug-id: 6530
2023-06-19 18:08:47 +02:00
Ingo Klöcker
23526c3ff2
qt: Make the run methods of ThreadedJobMixin public
* lang/qt/src/threadedjobmixin.h (ThreadedJobMixin::run): Make all
overloads public.
--

This allows calling the run() functions from the JobPrivate subclasses.

GnuPG-bug-id: 6530
2023-06-19 17:58:23 +02:00
Ingo Klöcker
4655b2dc6b
qt: Rename JobPrivate::start to JobPrivate::startNow
* lang/qt/src/job_p.h (JobPrivate::start): Rename to startNow.
* lang/qt/src/job.cpp (Job::startNow): Adapt function call.
* lang/qt/src/qgpgmechangeexpiryjob.cpp
(QGpgMEChangeExpiryJobPrivate::start): Rename to startNow.
* lang/qt/src/qgpgmedecryptverifyarchivejob.cpp
(QGpgMEDecryptVerifyArchiveJobPrivate::start): Rename to startNow.
* lang/qt/src/qgpgmeencryptarchivejob.cpp
(QGpgMEEncryptArchiveJobPrivate::start): Rename to startNow.
* lang/qt/src/qgpgmeencryptjob.cpp (QGpgMEEncryptJobPrivate::start):
Rename to startNow.
* lang/qt/src/qgpgmeimportjob.cpp (QGpgMEImportJobPrivate::start):
Rename to startNow.
* lang/qt/src/qgpgmelistallkeysjob.cpp
(QGpgMEListAllKeysJobPrivate::start): Rename to startNow.
* lang/qt/src/qgpgmesignarchivejob.cpp
(QGpgMESignArchiveJobPrivate::start): Rename to startNow.
* lang/qt/src/qgpgmesignencryptarchivejob.cpp
(QGpgMESignEncryptArchiveJobPrivate::start): Rename to startNow.
* lang/qt/src/qgpgmesignencryptjob.cpp
(QGpgMESignEncryptJobPrivate::start): Rename to startNow.
--

Using the same name for the public and the private method avoids
confusion.

GnuPG-bug-id: 6530
2023-06-19 17:58:23 +02:00
Ingo Klöcker
6f6b35df50
qt: Return const pointer to JobPrivate class for const pointer to Job
* lang/qt/src/job.cpp, lang/qt/src/job_p.h (getJobPrivate): Replace with
two overloads for non-const pointer and const pointer to Job.
* lang/qt/src/job_p.h (jobPrivate): Replace with two template functions
for non-const pointer and const pointer to Job.
--

This helps avoid changing values stored in the JobPrivate class in
const functions (e.g. getters) of Job classes.

GnuPG-bug-id: 6530
2023-06-19 17:58:23 +02:00
Andre Heinecke
5811d069d3
qt, cpp: Support larger size-hint on 32 bit builds
* NEWS: Mention this.
* lang/cpp/src/data.h, lang/cpp/src/data.cpp (Data::setSizeHint): New.
* lang/qt/src/qgpgmedecryptjob.cpp,
 lang/qt/src/qgpgmedecryptverifyarchivejob.cpp,
 lang/qt/src/qgpgmedecryptverifyjob.cpp,
 lang/qt/src/qgpgmeencryptjob.cpp,
 lang/qt/src/qgpgmesignencryptjob.cpp,
 lang/qt/src/qgpgmesignjob.cpp,
 lang/qt/src/qgpgmeverifydetachedjob.cpp,
 lang/qt/src/qgpgmeverifyopaquejob.cpp: Set size for input IODevice.

--
This fixes the case where the old detection of the size of QIOdevice
using seek would overflow and instead explicitly uses QIODevice::size
to check for the size and pass it through as an uint64.

GnuPG-Bug-Id: T6534
2023-06-16 14:33:19 +02:00
Andre Heinecke
cbcea4a09b
cpp: Expose gpgme_data_set_flag through cpp API
* lang/cpp/src/data.cpp (Data::setFlag): New.
* lang/cpp/src/data.h: Update accordingly.
* NEWS: Mention this.

--
This exposes the generic flag mechanism for data to users
of the C++ library. It is similar to Context::setFlag but
has no getter.
2023-06-16 12:35:36 +02:00
Werner Koch
91bbb1e482
core: Send a input-size-hint for gpgsm.
* src/engine-gpgsm.c (send_input_size_hint): New.
(gpgsm_decrypt): Send hint.
(gpgsm_encrypt): Send hint.
(gpgsm_sign): Send hint.
(gpgsm_verify): Send hint.
--
GnuPG-bug-id: 6534
2023-06-15 13:00:01 +02:00
Werner Koch
8796456d23
tests: Add option --cancel to run-encrypt.
* tests/run-encrypt.c (cancel_after_progress): New.
(progress_cb): Take care of it.
(main): Add option --cancel.
--

This tool may now be used to test gpgme_cancel_async.
Releated to
GnuPG-bug-id: 6534
2023-06-15 11:01:46 +02:00
Werner Koch
eb68948c43
core: Use 64 bit instead of gpgme_off_t for some internal functions.
* src/conversion.c (_gpgme_string_to_off): Return an u64 value.
* src/data.c (_gpgme_data_get_size_hint): Ditto.
(gpgme_data_set_flag): Use u64 for io-buffer-size due to string_to_off
change.
* src/data.h (struct gpgme_data): Change size_hint to u64.
* src/engine-gpg.c (add_input_size_hint): Replace gpgme_off_t by u64.
--

GnuPG-bug-id: 6534
2023-06-15 11:01:46 +02:00
Andre Heinecke
7e6d51aa6f
Fix definition of GPG_ERR_ENABLE_GETTEXT_MACROS
* configure.ac: Add missing value.

--
Otherwise it would not be included in config.h
2023-06-13 12:45:08 +02:00
Ingo Klöcker
7990f70107
doc,cpp: Treat GPG_ERR_FULLY_CANCELED as canceled
* doc/gpgme.texi (GPG_ERR_FULLY_CANCELED): New.
* lang/cpp/src/context.cpp (Error::isCanceled): Also return true for
GPG_ERR_FULLY_CANCELED.
--

For internal purposes, GnuPG sometimes uses the error code
GPG_ERR_FULLY_CANCELED instead of GPG_ERR_CANCELED. From a user
perspective both values mean the same thing and should therefore be
treated identically.

GnuPG-bug-id: 6510
2023-06-01 09:37:41 +02:00
Biswapriyo Nath
e2103be390
cpp,python: Respect --disable-gpg-test for tests
lang/cpp/Makefile.am (SUBDIRS): Depend tests in RUN_GPG_TESTS.
lang/python/Makefile.am (SUBDIRS): Ditto.
--

This is similar to the core and qt switch to disable the tests.

Signed-off-by: Biswapriyo Nath <nathbappai@gmail.com>
ChangeLog entries added by wk.
2023-05-30 11:44:17 +02:00
Werner Koch
fbc3963d62
core: For key signing and uid revoking allow an empty user id.
* src/engine-gpg.c (gpg_keysign): Required USERID to be non-empty.
--

For some language bindings it is easier if the engine considers an
empty user id to be equivalent to NULL.
2023-05-30 11:20:34 +02:00
Werner Koch
36a68bc530
python: Fix wrong use of write.
* lang/python/helpers.c (pyPassphraseCb): Use gpgme_io_writen.
(_gpg_interact_cb): Ditto.
* lang/python/helpers.h (write) [W32]: Remove bad write macro.
--
GnuPG-bug-id: T6501

Using write(2) without checking for EINTR is a not a good idea.
Futher gpgme_io_writen is the correct way to send data from a
callback.  This also fixed the wrong use of a simple macro for
Windows.
2023-05-23 15:52:25 +02:00
NIIBE Yutaka
e622e36f1f
build: Sync to libtool from libgpg-error for 64-bit Windows.
* build-aux/ltmain.hs: Update from libgpg-error.

--

GnuPG-bug-id: 6484
Signed-off-by: NIIBE Yutaka <gniibe@fsij.org>
2023-05-16 10:52:51 +09:00
NIIBE Yutaka
d44a473e27
doc: Fix Python example code.
* lang/python/doc/src/gpgme-python-howto.org: Fix chmod race.
* lang/python/examples/howto/export-secret-key.py: Likewise.
* lang/python/examples/howto/export-secret-keys.py: Likewise.
* lang/python/examples/howto/temp-homedir-config.py: Likewise.

--

It's not for Python 2.7.

GnuPG-bug-id: 6466
Reported-by: Hanno Böck
Co-authored-by: Ingo Klöcker
Signed-off-by: NIIBE Yutaka <gniibe@fsij.org>
2023-04-26 08:46:45 +09:00
Werner Koch
d99156ff08
Post release updates
--
2023-04-20 14:02:34 +02:00
Werner Koch
451ed47434
Release 1.20.0 2023-04-20 13:48:17 +02:00
Werner Koch
7351ef32ce
core: Support the new macOS Homebrew location.
* src/posix-util.c (find_executable): Extend the path.
--

GnuPG-bug-id: 6440
2023-04-20 13:35:50 +02:00
Ingo Klöcker
a14155d2c1
build,qt: Simplify check for moc
m4/qt6.m4: Remove alternative checks for moc that were taken over from
Qt 5 and that are obsolete for Qt 6.
--
2023-04-19 09:23:05 +02:00
Ingo Klöcker
e80bf34bf8
Update NEWS
* NEWS: Add news for recent changes
--

GnuPG-bug-id: 5960, 6456
2023-04-19 09:18:04 +02:00
Ingo Klöcker
5bd84cfd3f
cpp: Fix Key::canSign()
* lang/cpp/src/key.h (canReallySign): Deprecate.
* lang/cpp/src/key.cpp (canSign): Remove workaround. Use implementation
of canReallySign.
(canReallySign): Use canSign().
(operator<<): Use canSign().
--

The workaround in canSign was added 19 years ago and canReallySign, the
workaround for the workaround, was added 13 years ago. Time to get rid
of those workarounds for a bug in gpgme which has been fixed long ago
and which cause bugs for any unsuspecting user of Key::canSign().

GnuPG-bug-id: 6456
2023-04-18 13:16:22 +02:00
Werner Koch
7d1159c1e9
core: Avoid printf format warnings due to gpgme_ssize_t.
* src/debug.h (_trace_sysres_ssize_t): Cast arg.
2023-04-17 15:05:22 +02:00
Werner Koch
0c29119e06
core,w32: Fix invocation of gpgtar
* src/dirinfo.c (EXEEXT_S): New.
(get_gpgconf_item): Append ".exe" to gpg-wks-client and gpgtar.

* src/gpgme-w32spawn.c (mystderr): Add code to ease debugging.
2023-04-17 14:05:35 +02:00
NIIBE Yutaka
806a5d18b9
build: Update gpg-error.m4.
* m4/gpg-error.m4: Update from libgpg-error master.

--

Signed-off-by: NIIBE Yutaka <gniibe@fsij.org>
2023-04-06 08:40:12 +09:00
Ingo Klöcker
d256ba7cc5
w32: Always use UTF-8 for localized texts
* configure.ac: Define GPG_ERR_ENABLE_GETTEXT_MACROS.
* src/version.c (do_subsystem_inits) [W32]: Switch gettext to UTF-8.
--

On Windows, applications using GpgME can now rely on localized texts
returned by GpgME, e.g. the texts for error codes, to be UTF-8 encoded.
In particular, this saves a useless and possibly lossy conversion to
native encoding and back to UTF-8. On other OSes, where we use the
system provided gettext, we assume that UTF-8 is used nowadays.

GnuPG-bug-id: 5960
2023-04-04 12:11:15 +02:00
Werner Koch
34cc7daba1
core: Minor code cleanup.
* src/engine-gpg.c (build_argv): Remove superfluous tes.
--

gpg_error_from_syserror is guaranteed not to return 0 even if errno is
not set.
2023-03-27 16:56:29 +02:00
Ingo Klöcker
b608c084b9
core: Initialize error variable
* src/engine-gpg.c (build_argv): Initialize err.
--

Fixes-commit: fbce7deb3b
2023-03-27 16:49:24 +02:00
Werner Koch
6d21256c92
core,cpp: Add new key flags to gpgme_subkey_t
* src/gpgme.h.in (struct _gpgme_subkey): Add bit flags can_renc,
can_timestamp, adn is_group_owned. Reduce size of _unused.
* src/keylist.c (set_subkey_capability): Set them.
* tests/run-keylist.c (main): Print them.

* lang/cpp/src/key.h (Subkey::canRenc): New.
(Subkey::canTimestamp): New.
(Subkey::isGroupOwned): New.
* lang/cpp/src/key.cpp: Implement new methods.
(Subkey::isQualified): Print them.
(std::ostream &operator<<): Print them.
--

GnuPG-bug-id: 6395
2023-03-21 08:37:47 +01:00
Werner Koch
18e09b15d5
Post release updates
--
2023-03-17 11:42:33 +01:00
Werner Koch
96a30fdf30
Release 1.19.0 2023-03-17 10:34:42 +01:00
Ben Greiner (bnavigator)
d086653cc3
python: Update python.m4 configure script.
* configure.ac: Unset PYTHON_LIBS.  Support python 3.10.
* m4/python.m4: Find correct version string for python >= 3.10.
--

See-also: https://dev.gnupg.org/D546

Also test for 3.11 and 3.12 (wk).
2023-03-17 10:06:55 +01:00
Ingo Klöcker
e50724e1bb
tests: Package the ownertrust file
tests/gpg/Makefile.am (EXTRA_DIST): Add ownertrust.txt.
--

This fixes `make distcheck`.

GnuPG-bug-id: 6342
2023-03-17 09:20:08 +01:00
Werner Koch
98a159eb5e
build: Update autogen.sh from libgpg-error
--

This fixes hopefully issues with the beta numbering.  Also removes the
Windows-CE support
2023-03-15 16:07:57 +01:00
Werner Koch
c1f6535f14
core: Also detect legacy X.509 v0 certificates.
* src/data-identify.c (basic_detection): Loose the detection of X.509
certs.
2023-03-08 15:54:54 +01:00
Werner Koch
76351c4877
tests: Add option --binary to run-verify
* tests/run-verify.c (main): Set encoding.
--

gpgsm usually used autodetection of the input format.  But sometimes
it is required to tell gpgsm that the input is binary encoded.  In
particular, this allows to strip trailing zeroes from a detached
signature.
2023-03-08 10:50:15 +01:00
Ingo Klöcker
73e46b3465
qt: Add signals for file-based and data-based progress
* lang/qt/src/decryptverifyarchivejob.h (DecryptVerifyArchiveJob): Add
signals fileProgress and dataProgress.
* lang/qt/src/encryptarchivejob.h (EncryptArchiveJob): Ditto.
* lang/qt/src/signarchivejob.h (SignArchiveJob): Ditto.
* lang/qt/src/signencryptarchivejob.h (SignEncryptArchiveJob): Ditto.
* lang/qt/src/job_p.h (emitArchiveProgressSignals): New.
* lang/qt/src/qgpgmedecryptverifyarchivejob.cpp
(QGpgMEDecryptVerifyArchiveJob::QGpgMEDecryptVerifyArchiveJob): Emit
appropriate signal when receiving Job::rawProgress signal.
* lang/qt/src/qgpgmeencryptarchivejob.cpp
(QGpgMEEncryptArchiveJob::QGpgMEEncryptArchiveJob): Ditto.
* lang/qt/src/qgpgmesignarchivejob.cpp
(QGpgMESignArchiveJob::QGpgMESignArchiveJob): Ditto.
* lang/qt/src/qgpgmesignencryptarchivejob.cpp
(QGpgMESignEncryptArchiveJob::QGpgMESignEncryptArchiveJob): Ditto.
--

GnuPG-bug-id: 6342
2023-02-14 09:25:21 +01:00
Ingo Klöcker
ccff6a96fc
qt: Remove commented out code
--

GnuPG-bug-id: 6342
2023-02-14 09:25:21 +01:00
Ingo Klöcker
ea6f15ed60
qt: Add simple and extended progress signals replacing old signal
* lang/qt/src/job.h (Job): Add signals jobProgress and rawProgress.
Deprecate signal progress.
* lang/qt/src/multideletejob.cpp (MultiDeleteJob::slotResult): Emit
new progress signals.
* lang/qt/src/qgpgmerefreshsmimekeysjob.cpp
(QGpgMERefreshSMIMEKeysJob::slotStatus): Ditto.
* lang/qt/src/threadedjobmixin.h (ThreadedJobMixin::showProgress): Use
modern overload of QMetaObject::invokeMethod to forward the progress
signal and add the value of what. Add forwarding of progress to the new
signals.

* lang/qt/tests/t-encrypt.cpp (EncryptionTest::testProgress): Test
the new signals instead of the deprecated one.
--

The new signal jobProgress omits the what value which is useless for
most consumers. The new signal rawProgress makes all information
provided by the backend available to consumers. The latter is not
really meant to be used by users of gpgme. It will be used by the
archive jobs to provide more user-friendly signals.

GnuPG-bug-id: 6342
2023-02-14 09:25:21 +01:00
Werner Koch
9c5506fde7
core: Switch to logging via gpgrt
* src/debug.c (errfp): Remove.
(debug_init): Factor some code out to ...
(safe_to_use_debug_file): new.
(tid_log_callback): New.
(debug_init): Rewrite to make use of gpgrt logging.
(_gpgme_debug): Ditto.
(_gpgme_debug_end): Remove extra LF testing code.
* src/dirinfo.c (get_gpgconf_item): Remove now unneeded LFs.  Realign
output.
2023-02-10 11:12:52 +01:00
Werner Koch
c0da6f77c6
core: Update copyright notices
--
2023-02-10 11:12:52 +01:00
Ingo Klöcker
21283dfd1b
tests: Fix cleaning up at the end of the test
* tests/gpg/t-import.c (main): Unref key and release context.
--

This fixes leaks found with -fsanitize=address.
2023-02-10 10:00:56 +01:00
Ingo Klöcker
41dc3bd22a
core: Allow finalization of signature verification of unencrypted data
* src/decrypt-verify.c (decrypt_verify_status_handler): Call
_gpgme_verify_status_handler on EOF even if
_gpgme_decrypt_status_handler returned NO DATA error.

* tests/gpg/t-decrypt-verify.c (normal_signed_message): New.
(main): Add test with signed, but not encrypted data.
--

This allows the verify status handler to finalize the verification of
the last signature even if the decrypt status handler returned a NO DATA
error because the input data wasn't encrypted.

GnuPG-bug-id: 6368
2023-02-10 09:54:03 +01:00
Ingo Klöcker
3aaed9cfbf
cpp: Improve debug output of some enums
* lang/cpp/src/verificationresult.cpp (operator<<): Fix output of
Signature::PKAStatus which doesn't represent flags. Print corresponding
name of enum value if Signature::Summary or Notation::Flags are 0.
--

GnuPG-bug-id: 6368
2023-02-09 09:56:18 +01:00
Ingo Klöcker
7098c14b23
tests: Stop daemons after setting up test environment
* lang/python/tests/Makefile.am, lang/qt/tests/Makefile.am,
tests/gpg/Makefile.am, tests/json/Makefile.am (pubring-stamp): Call
`gpgconf --kill all` after importing test keys.
--

This ensures that no gpg-agents or other daemons are running after
"make".
2023-02-09 09:33:07 +01:00
Ingo Klöcker
fcefc78f74
tests: Extend tests with an ultimately trusted key
* tests/gpg/Makefile.am (gpg-sample.stamp, pubring-stamp): Unify usage
of tabs.
(pubring-stamp): Import owner trust values.
* tests/gpg/ownertrust.txt: New.
* tests/gpg/t-decrypt-verify.c, tests/gpg/t-verify.c: Update expected
values for signature summary and validity.
* tests/gpg/t-keylist-secret-sig.c, tests/gpg/t-keylist-sig.c,
tests/gpg/t-keylist.c: Update expected values of owner trust and uid
validity.
--

This change marks the "Alpha Test" test key as ultimately trusted which
makes it possible to check for correct values derived from this, i.e.
key owner trust, user id validity, signature summary and signature
validity.

GnuPG-bug-id: 6342
2023-02-08 13:46:17 +01:00
Ingo Klöcker
844e6cd3b9
tests: Make t-edit-sign idempotent
* tests/gpg/t-edit-sign.c (test_key, test_key_fpr, import_key,
delete_key): New.
(main): Remove key_fpr. Import test key to sign. Delete test key after
test.
--

Using a dedicated test key for testing key signing, which is imported
before the test and deleted after the test, makes sure that the
keys in the test key ring don't change. This is important for stable
results of the key listing tests.

GnuPG-bug-id: 6342
2023-02-08 13:25:27 +01:00
Ingo Klöcker
e0778ed910
doc: Add new flags
--

GnuPG-bug-id: 6342
2023-02-02 12:22:00 +01:00
Ingo Klöcker
52fd0bcde4
qt,tests: Add test for the previous commit
* lang/qt/tests/t-decryptverify.cpp: New.
* lang/qt/tests/Makefile.am: Add new test.
--

GnuPG-bug-id: 6342
2023-02-02 12:11:30 +01:00
Ingo Klöcker
1698eec2ae
cpp: Return successful verification for signed but not encrypted data
* lang/cpp/src/context.cpp (Context::decrypt): Use decryptionResult().
(Context::verifyDetachedSignature, Context::verifyOpaqueSignature):
Use verificationResult().
(Context::verificationResult): Ignore "no data" error for signed but
not encrypted data.
(Context::decryptAndVerify): Use decryptionResult() and
verificationResult().
--

gpgme's decrypt operations set the error to GPG_ERR_NO_DATA if no
encrypted data was found. It makes sense to use this error for the
encryption result, but it doesn't make sense to use it also for the
verfication result if signed data was found.
This way using the combined decrypt-verify operations on data that
may be encrypted and/or signed doesn't produce confusing results.

GnuPG-bug-id: 6342
2023-02-02 12:11:29 +01:00
Ingo Klöcker
c407728064
qt: Add job for extracting encrypted and signed archives
* lang/qt/src/decryptverifyarchivejob.cpp,
lang/qt/src/decryptverifyarchivejob.h,
lang/qt/src/decryptverifyarchivejob_p.h,
lang/qt/src/qgpgmedecryptverifyarchivejob.cpp,
lang/qt/src/qgpgmedecryptverifyarchivejob.h: New.
* lang/qt/src/protocol.h (class Protocol): Add pure virtual member
function decryptVerifyArchiveJob
* lang/qt/src/protocol_p.h (Protocol::decryptVerifyArchiveJob): ... and
implement it.
* lang/qt/src/Makefile.am: Update accordingly.

* lang/qt/tests/run-decryptverifyarchivejob.cpp: New.
* lang/qt/tests/Makefile.am: Add new test runner.
--

GnuPG-bug-id: 6342
2023-02-02 12:11:29 +01:00
Ingo Klöcker
7ad717f6ba
core: Make usage of input size hint compatible with gpgtar
* src/engine-gpg.c (add_input_size_hint): Use add_gpg_arg_with_value
to add the --input-size-hint option.
--

GnuPG-bug-id: 6342
2023-02-02 09:59:01 +01:00
Ingo Klöcker
b3bdf14b37
cpp: Update decryption flags
* lang/cpp/src/context.h (DecryptArchive): New flag.
--

This flag corresponds to the GPGME_DECRYPT_ARCHIVE flag in gpgme.

GnuPG-bug-id: 6342
2023-02-02 09:56:22 +01:00
Ingo Klöcker
55c948866f
qt: Allow checking if the sign/encrypt archive jobs are supported
* lang/qt/src/encryptarchivejob.cpp, lang/qt/src/encryptarchivejob.h
(isSupported): New.
* lang/qt/src/signarchivejob.cpp, lang/qt/src/signarchivejob.h
(isSupported): New.
* lang/qt/src/signencryptarchivejob.cpp,
lang/qt/src/signencryptarchivejob.h (isSupported): New.

* lang/qt/tests/run-encryptarchivejob.cpp (main),
lang/qt/tests/run-signarchivejob.cpp (main): Check if jobs are
supported.
--

GnuPG-bug-id: 6342
2023-02-02 09:47:11 +01:00
Ingo Klöcker
8478064691
cpp: Add const-overloads of version comparison operators
* lang/cpp/src/engineinfo.h (EngineInfo::Version): Add const-overloads
of all comparison operators.
--

We keep the non-const overloads for binary compatibility.

GnuPG-bug-id: 6342
2023-02-02 09:47:10 +01:00
Ingo Klöcker
7f541547fc
core: Allow usage of gpgtar also for new enough gpg 2.2
* src/engine-gpg.c (have_usable_gpgtar): New.
(start): Always pass --status-fd to the called process.
(gpg_decrypt, gpg_encrypt, gpg_encrypt_sign, gpg_sign, gpg_verify):
Use have_usable_gpgtar() to check for suitable gpg.
--

The version check in start() is not needed because versions of gpg
that are unsuitable for the usage of gpgtar are rejected already by
the callers.

GnuPG-bug-id: 6342
2023-02-02 09:47:10 +01:00
Werner Koch
5ab9c234d6
core,w32: More robust detection of GnuPG Desktop dir layout
* src/w32-util.c (INST_TYPE_GPG4WIN, INST_TYPE_GPGDESK): New to
replace the numeric constants.
(find_version_file): New.
(_gpgme_get_gpgconf_path): Guess a default for inst_type.
--

GnuPG-bug-id: 6362
2023-02-01 17:29:24 +01:00
Ingo Klöcker
343fb33bf0
qt: Fix build without installed gpgme++ headers
* lang/qt/src/filelistdataprovider.cpp: Include error.h without
folder prefix.
--

GnuPG-bug-id: 6342
2023-01-31 21:13:07 +01:00
Ingo Klöcker
472f109138
doc: Update "since" version
--
2023-01-31 12:13:29 +01:00
Ingo Klöcker
7b2188aca1
doc: Update NEWS
--

GnuPG-bug-id: 6342
2023-01-31 12:01:33 +01:00
Ingo Klöcker
d3a8c2c8b6
qt: Remove unused and commented-out code
* lang/qt/src/qgpgmeencryptarchivejob.cpp,
lang/qt/src/qgpgmeencryptarchivejob.h (QGpgMEEncryptArchiveJob):
Remove member function resultHook and member mResult.
* lang/qt/src/qgpgmesignarchivejob.cpp,
lang/qt/src/qgpgmesignarchivejob.h (QGpgMESignArchiveJob):
Remove member function resultHook and member mResult.
--

GnuPG-bug-id: 6342
2023-01-31 12:01:33 +01:00
Ingo Klöcker
41a30f6d9f
cpp: Fix debug output of SignatureMode
* lang/cpp/src/context.cpp (operator<<): Treat signature mode as
combination of a 2-bit flag and a 1-bit flag.
--

This fixes the output for normal signature mode.

GnuPG-bug-id: 6342
2023-01-31 12:01:33 +01:00
Ingo Klöcker
8c4436e73a
qt: Add job for creating encrypted signed archives
* lang/qt/src/signencryptarchivejob.cpp,
lang/qt/src/signencryptarchivejob.h,
lang/qt/src/signencryptarchivejob_p.h,
lang/qt/src/qgpgmesignencryptarchivejob.cpp,
lang/qt/src/qgpgmesignencryptarchivejob.h: New.
* lang/qt/src/protocol.h (class Protocol): Add pure virtual member
function signEncryptArchiveJob
* lang/qt/src/protocol_p.h (Protocol::signEncryptArchiveJob): ... and
implement it.
* lang/qt/src/Makefile.am: Update accordingly.

* lang/qt/tests/run-encryptarchivejob.cpp (displayName): Remove.
(CommandLineOptions): Initialize member armor. Add member sign.
(parseCommandLine): Update application description. Add and parse option
-s/--sign.
(main): Use SignEncryptArchiveJob if sign option is set.
--

GnuPG-bug-id: 6342
2023-01-31 12:01:33 +01:00
Ingo Klöcker
2b98585c89
qt,tests: Avoid leaking Context
* lang/qt/tests/t-import.cpp: Wrap Context*s in unique_ptr.
--

This fixes leaks found with -fsanitize=address.
2023-01-31 12:01:33 +01:00
Werner Koch
5d07f8db77
doc: Fix description of gpgme_data_identify
--
GnuPG-bug-id: 5887
2023-01-31 09:53:20 +01:00
Werner Koch
359378c5b3
json: New operation "identify" and convenience option --identify.
* src/gpgme-json.c (data_type_to_string): New.
(op_identify): New.
(process_request): Add to command list.
(cmd_identify): New.
(main): Add option --identify.
--
2023-01-31 09:52:04 +01:00
Werner Koch
577562dd4c
Update NEWS and set version to 1.19.0
--
2023-01-31 08:10:29 +01:00
Werner Koch
3cdcfa33f7
Merge branch 'ikloecker/t6342-gpgtar' into master
--
Solved conflicts:
	NEWS
	lang/cpp/src/context.cpp
	lang/cpp/src/context.h
2023-01-31 07:59:50 +01:00
Ingo Klöcker
8d672b3b7e
qt: Add job for creating signed archives
* lang/qt/src/signarchivejob.cpp, lang/qt/src/signarchivejob.h,
lang/qt/src/signarchivejob_p.h,
lang/qt/src/qgpgmesignarchivejob.cpp,
lang/qt/src/qgpgmesignarchivejob.h: New.
* lang/qt/src/protocol.h (class Protocol): Add pure virtual member
function signArchiveJob
* lang/qt/src/protocol_p.h (Protocol::signArchiveJob): ... and
implement it.
* lang/qt/src/Makefile.am: Update accordingly.

* lang/qt/tests/run-signarchivejob.cpp: New.
* lang/qt/tests/Makefile.am: Add new test runner.
--

GnuPG-bug-id: 6342
2023-01-30 12:56:54 +01:00
Ingo Klöcker
2faa031af2
cpp: Support new archive signing flag
* lang/cpp/src/global.h (enum SignatureMode): Add constant SignArchive.
* lang/cpp/src/context.cpp (sigmode2sigmode): Rename to
sigflags2sigflags
(sigflags2sigflags): ... and rename argument mode to flags and treat
it as flags. Adjust the callers.
(operator<<): Change local CHECK macro to handle flags. Add new flag
to debug stream.
* lang/cpp/src/signingresult.cpp (CreatedSignature::mode): Handle
new flags (even if it cannot occur currently).
--

GnuPG-bug-id: 6342
2023-01-30 12:49:12 +01:00
Ingo Klöcker
48b11f5762
core: Use signature modes as flags
* src/engine-backend.h (engine_ops.sign): Rename argument mode to
flags.
* src/engine-gpg.c (gpg_sign): Rename argument mode to flags. Check
for invalid combination of flags.
* src/engine-gpgsm.c (gpgsm_sign): Rename argument mode to flags.
Check for unsupported flags.
* src/engine-uiserver.c (gpgsm_sign): Rename argument mode to flags.
Check for unsupported flags.
* src/engine.c, src/engine.h (_gpgme_engine_op_sign): Rename argument
mode to flags.
* src/gpgme.h.in (GPGME_SIG_MODE_ARCHIVE): Change value to 4.
(gpgme_op_sign_start, gpgme_op_sign): Rename argument mode to flags.
* src/sign.c (sign_start): Rename argument mode to flags. Adjust
check for invalid flags.
(gpgme_op_sign_start, gpgme_op_sign): Rename argument mode to flags.
--

Using the signature mode constants as flags is more natural, even if
currently all flags are mutually exclusive, because archives are
signed with a normal signature.

GnuPG-bug-id: 6342
2023-01-30 12:49:11 +01:00
Ingo Klöcker
7afd135cce
qt: Add job for creating encrypted archives
* lang/qt/src/encryptarchivejob.cpp, lang/qt/src/encryptarchivejob.h,
lang/qt/src/encryptarchivejob_p.h,
lang/qt/src/qgpgmeencryptarchivejob.cpp,
lang/qt/src/qgpgmeencryptarchivejob.h: New.
* lang/qt/src/protocol.h (class Protocol): Add pure virtual member
function encryptArchiveJob
* lang/qt/src/protocol_p.h (Protocol::encryptArchiveJob): ... and
implement it.
* lang/qt/src/Makefile.am: Update accordingly.

* lang/qt/tests/run-encryptarchivejob.cpp: New.
* lang/qt/tests/Makefile.am: Add new test runner.
--

GnuPG-bug-id: 6342
2023-01-27 12:20:53 +01:00
Ingo Klöcker
275a3a2c16
qt: Add data provider for list of file names
* lang/qt/src/Makefile.am: Add new files and corresponding camel-case
header.
* lang/qt/src/dataprovider.h: Include interface from gpgme++ when
not building.
* lang/qt/src/filelistdataprovider.cpp,
lang/qt/src/filelistdataprovider.h: New.
--

The new data provider simplifies providing a nul-separated list of
UTF-8-encoded filenames, e.g. for creating signed or encrypted
archives. It is a simple read-only proxy for QByteArrayDataProvider.

GnuPG-bug-id: 6342
2023-01-27 12:17:09 +01:00
Ingo Klöcker
d28ea8c6b3
cpp: Support new archive encryption flag
* lang/cpp/src/context.h (EncryptArchive): New flag.
* lang/cpp/src/context.cpp (encryptflags2encryptflags): Convert
EncryptArchive to corresponding gpgme encrypt flags.
(operator<<): Add new flag to debug stream.
--

GnuPG-bug-id: 6342
2023-01-27 12:16:02 +01:00
Ingo Klöcker
261245a2e0
cpp: Add convenience overload to set file name
* lang/cpp/src/data.h, lang/cpp/src/data.cpp (setFileName): Add
overload.
--

GnuPG-bug-id: 6342
2023-01-27 12:14:10 +01:00
Ingo Klöcker
1328a57586
doc: Fix syntax errors
--

GnuPG-bug-id: 6342
2023-01-27 12:11:21 +01:00
Ingo Klöcker
3e31f648e5
cpp: Support all encryption flags
* lang/cpp/src/context.h (WantAddress): New flag.
* lang/cpp/src/context.cpp (encryptflags2encryptflags): Convert
WantAddress to corresponding gpgme encrypt flags.
(operator<<): Add new flag to debug stream.
--

GnuPG-bug-id: 6359
2023-01-26 12:01:28 +01:00
Ingo Klöcker
70aaf05a6a
cpp: Pass ThrowKeyIds and EncryptWrap flags to GpgME
* lang/cpp/src/context.cpp (encryptflags2encryptflags): Convert
ThrowKeyIds and EncryptWrap to corresponding gpgme encrypt flags.
(operator<<): Add flags to debug stream.
--

GnuPG-bug-id: 6359
2023-01-26 12:01:10 +01:00
Ingo Klöcker
3580bb139b
core: Update required GnuPG version for new archive features
* src/engine-gpg.c (gpg_decrypt, gpg_encrypt, gpg_encrypt_sign,
gpg_sign, gpg_verify): Require gpg 2.4.1.

--

To work properly the archive feature needs a fix added in GnuPG 2.4.1.

GnuPG-bug-id: 6342
2023-01-26 09:52:11 +01:00
Ingo Klöcker
ab7146aa61
doc: Update NEWS and API documentation
--

GnuPG-bug-id: 6342
2023-01-25 12:17:05 +01:00
Ingo Klöcker
5b79b32397
core: Support usage of gpgtar for verifying a signed archive
* src/gpgme.h.in (gpgme_verify_flags_t): New enum.
(GPGME_VERIFY_ARCHIVE): New const.
(gpgme_op_verify_ext_start): New func.
(gpgme_op_verify_ext): New func.
* src/gpgme.def, src/libgpgme.vers: Add new functions.
* src/verify.c (gpgme_op_verify_ext_start): New.
(gpgme_op_verify_ext): New.
(verify_start): Add arg FLAGS.  Pass the flags to
_gpgme_engine_op_verify.
(gpgme_op_verify_start): Call gpgme_op_verify_ext_start with 0 for
FLAGS.
(gpgme_op_verify): Call gpgme_op_verify_ext with 0 for FLAGS.
* src/engine.c, src/engine.h (_gpgme_engine_op_verify): Add arg FLAGS.
* src/engine-backend.h (struct engine_ops): Add FLAGS to 'verify'.
* src/engine-gpg.c (gpg_verify): Add arg FLAGS. Set use_gpgtar engine
flag if GPGME_VERIFY_ARCHIVE flag is set. Check for new enough gpg. Use
add_gpg_arg for gpg-only options without a value. Set extra options for
gpgtar and pass input data to stdin when using gpgtar.
* src/engine-gpgsm.c (gpgsm_verify): Add arg FLAGS. Return error if
GPGME_VERIFY_ARCHIVE flag is set.
* src/engine-uiserver.c (uiserver_verify): Ditto.

* tests/run-verify.c (show_usage): New options --archive, --directory,
and --diagnostics.
(main): Parse new options. Verify and extract with gpgtar if --archive
is given. Set file name of output data to value of --directory option.
Print stderr of gpg/gpgtar if --diagnostics is given.
--

GnuPG-bug-id: 6342
2023-01-25 11:26:34 +01:00
Ingo Klöcker
95ea3bf831
core: Support usage of gpgtar for decrypting an encrypted archive
* src/gpgme.h.in (GPGME_DECRYPT_ARCHIVE): New decryption flag.
* src/engine-gpg.c (gpg_decrypt): Set use_gpgtar engine flag if
GPGME_DECRYPT_ARCHIVE flag is set. Check for new enough gpg and
incompatible flags. Use add_gpg_arg_with_value for gpg-only options
with a value and add_gpg_arg for gpg-only options without a value.
Set extra options for gpgtar and pass input data to stdin when using
gpgtar.

* tests/run-decrypt.c (show_usage): New options --archive and
--directory.
(main): Parse new options. Decrypt with gpgtar if --archive is given.
Set file name of output data to value of --directory option.
--

GnuPG-bug-id: 6342
2023-01-24 12:32:23 +01:00
Ingo Klöcker
419adf41af
core: Allow setting the base directory when creating an archive
* src/engine-gpg.c (gpg_encrypt, gpg_encrypt_sign, gpg_sign): Pass
file name set in data with --directory option to gpgtar.

* tests/run-encrypt.c (show_usage): New option --directory.
(main): Parse new option. Set file name of input data to option value.
* tests/run-sign.c (show_usage): New option --directory.
(main): Parse new option. Set file name of input data to option value.
--

GnuPG-bug-id: 6342
2023-01-23 12:17:22 +01:00
Ingo Klöcker
4c872b6741
doc: Update NEWS and API documentation
--

GnuPG-bug-id: 6342
2023-01-19 12:08:35 +01:00
Ingo Klöcker
29cfcd316d
core: Support usage of gpgtar for creating an encrypted signed archive
* src/engine-gpg.c (gpg_encrypt_sign): Set use_gpgtar engine flag if
GPGME_ENCRYPT_ARCHIVE mode is set. Check for new enough gpg. Use
add_gpg_arg_with_value for gpg-only options with a value and
add_gpg_arg for gpg-only options without a value. Set extra options for
gpgtar and pass input data to stdin when using gpgtar.

* tests/run-encrypt.c (print_result): Rename to print_encrypt_result.
Print header.
(print_sign_result): New.
(show_usage): New option --sign.
(main): Parse new option. Sign and encrypt --sign is given.
Print results of signing additionally to results of encryption.
--

With this change the gpgme_op_encrypt_sign* functions get support for
creating an encrypted and signed archive from files and/or directories
passed as NUL-separated list in the "plain" data with gpgtar.

GnuPG-bug-id: 6342
2023-01-19 11:08:42 +01:00
Ingo Klöcker
0ca45e48b4
core: Support usage of gpgtar for creating a signed archive
* src/gpgme.h.in (GPGME_SIG_MODE_ARCHIVE): New signature mode.
* src/engine-gpg.c (append_args_from_sender,
append_args_from_sig_notations): Use add_gpg_arg_with_value
for gpg-only options with a value.
(gpg_sign): Set use_gpgtar engine flag if GPGME_SIG_MODE_ARCHIVE mode
is set. Check for new enough gpg. Use add_gpg_arg_with_value for
gpg-only options with a value and add_gpg_arg for gpg-only options
without a value. Set extra options for gpgtar and pass input data to
stdin when using gpgtar.
* src/sign.c (sign_start): Add GPGME_SIG_MODE_ARCHIVE as valid mode.

* tests/run-sign.c (show_usage): New options --archive and
--diagnostics.
(main): Parse new options. Sign with gpgtar if --archive is given.
Print stderr of gpg/gpgtar if --diagnostics is given.
--

With this change the gpgme_op_sign* functions get support for
creating a signed archive from files and/or directories passed as
NUL-separated list in the "in" data with gpgtar.

GnuPG-bug-id: 6342
2023-01-19 10:45:04 +01:00
Ingo Klöcker
aa201b0bb6
core: Fix --set-filename argument
* src/engine-gpg.c (gpg_encrypt): Append equal sign to argument name.
--

GnuPG-bug-id: 6342
2023-01-19 10:29:56 +01:00
Ingo Klöcker
5d8316da1d
core: Support usage of gpgtar for encryption
* src/gpgme.h.in (GPGME_ENCRYPT_ARCHIVE): New encryption flag.
* src/engine-gpg.c (arg_and_data_s): New field gpg_arg.
(engine_gpg): New flag use_gpgtar.
(_add_arg): Add argument gpg_arg and set it.
(add_arg_ext, add_arg_with_locp, add_arg, add_arg_pfx, add_arg_len):
Adjust call of _add_arg.
(add_arg_with_locp): Add argument front.
(add_gpg_arg, add_gpg_arg_with_value): New.
(gpg_new): Use add_gpg_arg_with_value for gpg-only options with a value
and add_gpg_arg for gpg-only options without.
(build_argv): Consider usage of gpgtar when counting arguments to pass
to gpg/gpgtar. Prepend "--gpg-args" to all gpg-only arguments if gpgtar
is used.
(start): Set program to use. Read diagnostics output from stderr when
using gpgtar. Do not pass --status-fd to gpgtar for gpg < 2.4.1. Use
add_gpg_arg_with_value for --lc-ctype and --lc-messages.
(gpg_encrypt): Set use_gpgtar engine flag if GPGME_ENCRYPT_ARCHIVE flag
is set. Check for new enough gpg and incompatible flags. Use
add_gpg_arg_with_value for gpg-only options with a value and
add_gpg_arg for gpg-only options without a value. Set extra options
for gpgtar and pass input data to stdin when using gpgtar.
* src/engine-gpgsm.c (gpgsm_encrypt): Return error if new flag is set.
* src/engine-uiserver.c (uiserver_encrypt): Ditto.

* tests/run-encrypt.c (show_usage): New options --archive and
--diagnostics.
(main): Parse new options. Encrypt with gpgtar if --archive is given.
Print stderr of gpg/gpgtar if --diagnostics is given.
--

With this change the gpgme_op_encrypt* functions get support for
encrypting a list of files and/or directories passed as NUL-separated
list in "plain" data with gpgtar.

GnuPG-bug-id: 6342
2023-01-18 11:48:02 +01:00
Ingo Klöcker
d56b3bc1cf
core: Defer adding --status-fd and --logger-fd to argument list
* src/engine-gpg.c (_append_to_arglist, _prepend_to_arglist): New.
(_add_arg): Use _append_to_arglist and _prepend_to_arglist.
(add_data_ext): New. Extends add_data.
(add_data): Uses add_data_ext.
(gpg_new): Do not add --status-fd and --logger-fd to argument list.
(start): Prepend --logger-fd and --status-fd to the argument list.
--

This change makes it possible to handle those two arguments differently
if gpgtar is used instead of gpg.

GnuPG-bug-id: 6342
2023-01-18 10:54:39 +01:00
Ingo Klöcker
7a68a1ca64
doc: Document socketdir value of gpgme_get_dirinfo
--
2023-01-18 10:37:39 +01:00
Ingo Klöcker
1a9dfdfccb
cpp,doc: Update list of allowed values for dirInfo
--

GnuPG-bug-id: 6342
2023-01-18 10:33:54 +01:00
Ingo Klöcker
12e490d97f
core: Extend gpgme_get_dirinfo to return the gpgtar name
* src/dirinfo.c (WANT_GPGTAR_NAME): New.
(dirinfo): Add field gpgtar_name.
(get_gpgconf_item): Build gpgtar_name on demand and return it.
(_gpgme_get_default_gpgtar_name) : New.
(gpgme_get_dirinfo): New value "gpgtar-name" for WHAT.
* src/util.h (_gpgme_get_default_gpgtar_name): New.

* tests/t-engine-info.c (main): Add gpgtar-name to the output.

GnuPG-bug-id: 6342
2023-01-18 10:30:17 +01:00
Ingo Klöcker
fbce7deb3b
core: Use "goto leave" pattern to clean up resources
* src/engine-gpg.c (build_argv): Initialize fd_data_map and argv. Goto
leave on error. Free fd_data_map and argv on error.
--

This will make it easier to add an additional "--with-gpg-args" option
where needed.

GnuPG-bug-id: 6342
2023-01-17 09:31:38 +01:00
Ingo Klöcker
984ff7e3a2
core: Do not add obsolete --no-sk-comments to command line
* src/engine-gpg.c (build_argv): Don't add "--no-sk-comments" to argv.
--

This option is a no-op since 1.4.3 and 1.4.23 is the latest 1.4 release.

GnuPG-bug-id: 6342
2023-01-16 12:28:13 +01:00
Ingo Klöcker
64da77620a
qt: Fix comparisons of integer expressions of different signedness
* lang/qt/tests/t-import.cpp (ImportTest::testImportWithImportFilter):
Make integer literal unsigned.
--
2023-01-05 20:33:45 +01:00
Ingo Klöcker
2e9d72a0be
cpp: Fix comparisons of integer expressions of different signedness
* lang/cpp/src/gpgrevokekeyeditinteractor.cpp
(GpgRevokeKeyEditInteractor::Private::nextState): Cast signed nextLine
value to std::size_t.
--
2023-01-05 20:29:27 +01:00
Ingo Klöcker
dc9cc9aa07
cpp: Expliticly declare compiler generated copy constructors
* lang/cpp/src/configuration.h (Component, Option),
lang/cpp/src/data.h (Data),
lang/cpp/src/decryptionresult.h (DecryptionResult,
DecryptionResult::Recipient),
lang/cpp/src/encryptionresult.h (EncryptionResult, InvalidRecipient),
lang/cpp/src/engineinfo.h (EngineInfo),
lang/cpp/src/importresult.h (ImportResult, Import),
lang/cpp/src/key.h (Key, Subkey, UserID, UserID::Signature),
lang/cpp/src/keygenerationresult.h (KeyGenerationResult),
lang/cpp/src/keylistresult.h (KeyListResult),
lang/cpp/src/notation.h (Notation),
lang/cpp/src/signingresult.h (SigningResult, InvalidSigningKey,
CreatedSignature),
lang/cpp/src/swdbresult.h (SwdbResult),
lang/cpp/src/tofuinfo.h (TofuInfo),
lang/cpp/src/verificationresult.h (VerificationResult, Signature),
lang/cpp/src/vfsmountresult.h (VfsMountResult): Explitily declare
compiler generated copy constructor.
--

This fixes "implicitly-declared copy constructor is deprecated"
warnings.
2023-01-05 20:17:57 +01:00
Ingo Klöcker
e16c368758
qt: Replace Q_DECL_OVERRIDE with override
* lang/qt/src/defaultkeygenerationjob.h,
lang/qt/src/hierarchicalkeylistjob.h, lang/qt/src/multideletejob.h,
lang/qt/src/protocol_p.h, lang/qt/src/qgpgmeadduseridjob.h,
lang/qt/src/qgpgmechangeexpiryjob.h,
lang/qt/src/qgpgmechangeownertrustjob.h,
lang/qt/src/qgpgmechangepasswdjob.h, lang/qt/src/qgpgmedecryptjob.h,
lang/qt/src/qgpgmedecryptverifyjob.h, lang/qt/src/qgpgmedeletejob.h,
lang/qt/src/qgpgmedownloadjob.h, lang/qt/src/qgpgmeencryptjob.h,
lang/qt/src/qgpgmeexportjob.h, lang/qt/src/qgpgmegpgcardjob.h,
lang/qt/src/qgpgmeimportfromkeyserverjob.h,
lang/qt/src/qgpgmeimportjob.h, lang/qt/src/qgpgmekeyformailboxjob.h,
lang/qt/src/qgpgmekeygenerationjob.h, lang/qt/src/qgpgmekeylistjob.h,
lang/qt/src/qgpgmelistallkeysjob.h, lang/qt/src/qgpgmenewcryptoconfig.h,
lang/qt/src/qgpgmequickjob.h, lang/qt/src/qgpgmerefreshsmimekeysjob.h,
lang/qt/src/qgpgmesignencryptjob.h, lang/qt/src/qgpgmesignjob.h,
lang/qt/src/qgpgmesignkeyjob.h, lang/qt/src/qgpgmetofupolicyjob.h,
lang/qt/src/qgpgmeverifydetachedjob.h,
lang/qt/src/qgpgmeverifyopaquejob.h, lang/qt/src/qgpgmewkdlookupjob.h,
lang/qt/src/qgpgmewkspublishjob.h, lang/qt/src/threadedjobmixin.h,
lang/qt/tests/t-support.h: Replace Q_DECL_OVERRIDE with override
--

We require C++11 since a long time.
2023-01-05 18:03:33 +01:00
Ingo Klöcker
398375a0ab
qt: Allow deferred start of import job
* lang/qt/src/importjob.h (ImportJob::startLater): New pure virtual
method.
* lang/qt/src/qgpgmeimportjob.cpp, lang/qt/src/qgpgmeimportjob.h
(QGpgMEImportJob::startLater): New method.

* lang/qt/tests/t-import.cpp (ImportTest::testDeferredStart): New.
--

This makes it possible to prepare an import job for a deferred start.

GnuPG-bug-id: 6323
2023-01-05 14:24:31 +01:00
Ingo Klöcker
18c2c0b250
qt: Support deferred start of jobs
* lang/qt/src/job.cpp, lang/qt/src/job.h (Job::startNow): New method.
* lang/qt/src/job_p.h (JobPrivate::start): New pure virtual method.
* lang/qt/src/qgpgmechangeexpiryjob.cpp
(QGpgMEChangeExpiryJobPrivate::start): New.
* lang/qt/src/qgpgmeencryptjob.cpp (QGpgMEEncryptJobPrivate::start):
New.
* lang/qt/src/qgpgmeimportjob.cpp (QGpgMEImportJobPrivate::start): New.
* lang/qt/src/qgpgmelistallkeysjob.cpp
(QGpgMEListAllKeysJobPrivate::start): New.
* lang/qt/src/qgpgmesignencryptjob.cpp
(QGpgMESignEncryptJobPrivate::start): New.
* lang/qt/src/threadedjobmixin.h (Thread::hasFunction): New method.
(ThreadedJobMixin::run, ThreadedJobMixin::setWorkerFunction): New
methods.
--

startNow() starts a deferred job for which the worker function has been
set before.

GnuPG-bug-id: 6323
2023-01-04 12:16:04 +01:00
Ingo Klöcker
270d752300
qt: Explicitly instantiate private job classes
* lang/qt/src/Makefile.am: Add new files.
* lang/qt/src/changeexpiryjob_p.h, lang/qt/src/encryptjob_p.h,
lang/qt/src/importjob_p.h, lang/qt/src/listallkeysjob_p.h,
lang/qt/src/signencryptjob_p.h: New.
* lang/qt/src/changeexpiryjob.cpp, lang/qt/src/encryptjob.cpp,
lang/qt/src/importjob.cpp, lang/qt/src/listallkeysjob.cpp,
lang/qt/src/signencryptjob.cpp: Move JobPrivate subclasses to the new
private header files.
* lang/qt/src/job_p.h (jobPrivate): Remove lazy instantiation of private
job classes.
* lang/qt/src/qgpgmechangeexpiryjob.cpp (class
QGpgMEChangeExpiryJobPrivate): New.
(QGpgMEChangeExpiryJob::QGpgMEChangeExpiryJob): Instantiate private job
class.
* lang/qt/src/qgpgmeencryptjob.cpp (class
QGpgMEEncryptJobPrivate): New.
(QGpgMEEncryptJob::QGpgMEEncryptJob): Instantiate private job
class.
* lang/qt/src/qgpgmeimportjob.cpp (class
QGpgMEImportJobPrivate): New.
(QGpgMEImportJob::QGpgMEImportJob): Instantiate private job
class.
* lang/qt/src/qgpgmelistallkeysjob.cpp (class
QGpgMEListAllKeysJobPrivate): New.
(QGpgMEListAllKeysJob::QGpgMEListAllKeysJob): Instantiate private job
class.
* lang/qt/src/qgpgmesignencryptjob.cpp (class
QGpgMESignEncryptJobPrivate): New.
(QGpgMESignEncryptJob::QGpgMESignEncryptJob): Instantiate private job
class.
--

We need private job classes corresponding to the concrete leaf classes.
This makes the lazy instantiation of the private classes by the job
interface classes impossible.

GnuPG-bug-id: 6323
2023-01-04 11:37:11 +01:00
NIIBE Yutaka
2ba11f9bfb
doc:python: Replace gpgme-config to pkg-config.
--

Signed-off-by: NIIBE Yutaka <gniibe@fsij.org>
2022-12-14 15:12:41 +09:00
Ingo Klöcker
e7953dcf13
cpp: Handle status errors in the base edit interactor
* lang/cpp/src/editinteractor.cpp (edit_interactor_callback_impl):
Handle status errors.
* lang/cpp/src/gpgrevokekeyeditinteractor.cpp
(GpgRevokeKeyEditInteractor::Private::nextState): Remove handling of
status errors.
--

With this change status errors are handled for all interactors. In
particular, this makes all edit interactors handle canceled password
prompts correctly.

GnuPG-bug-id: 6305
2022-12-08 15:31:37 +01:00
Ingo Klöcker
c419376b85
cpp: Handle statuses that need no response in the base edit interactor
* lang/cpp/src/editinteractor.cpp (edit_interactor_callback_impl): Do
not call nextState() if status needs no response.
* lang/cpp/src/gpgaddexistingsubkeyeditinteractor.cpp
(GpgAddExistingSubkeyEditInteractor::Private::nextState),
lang/cpp/src/gpgadduserideditinteractor.cpp
(GpgAddUserIDEditInteractor::nextState),
lang/cpp/src/gpggencardkeyinteractor.cpp
(GpgGenCardKeyInteractor::nextState),
lang/cpp/src/gpgrevokekeyeditinteractor.cpp
(GpgRevokeKeyEditInteractor::Private::nextState),
lang/cpp/src/gpgsetexpirytimeeditinteractor.cpp
(GpgSetExpiryTimeEditInteractor::nextState),
lang/cpp/src/gpgsetownertrusteditinteractor.cpp
(GpgSetOwnerTrustEditInteractor::nextState),
lang/cpp/src/gpgsignkeyeditinteractor.cpp
(GpgSignKeyEditInteractor::nextState): Remove handling of statuses that
need no response.
--

This change removes superfluous code duplication.

GnuPG-bug-id: 6305
2022-12-08 15:31:21 +01:00
Ingo Klöcker
d04d7b174f
qt: Write path values with Unix directory separators
* lang/qt/src/qgpgmenewcryptoconfig.cpp
(QGpgMENewCryptoConfigEntry::setURLValue): Remove conversion to native
directory separators.
--

Even on Windows Unix directory separators work with all API calls. And
some path values also allow "URLs" like tcp://1.2.3.4:10001 which must
use '/'.

GnuPG-bug-id: 4518
2022-12-06 08:12:00 +01:00
NIIBE Yutaka
a9921d797b
doc: Don't use AM_PATH_GPGME_PTHREAD any more.
--

GnuPG-bug-id: 6285
Signed-off-by: NIIBE Yutaka <gniibe@fsij.org>
2022-11-29 11:18:40 +09:00
NIIBE Yutaka
f9cbf2c8a8
gpgme.m4: Fix AM_PATH_GPGME_PTHREAD.
* src/gpgme.m4 (AM_PATH_GPGME_PTHREAD): It's deprecated, since gpgme
supports threads and GNU C library has integrated pthread features.

--

GnuPG-bug-id: 6285
Signed-off-by: NIIBE Yutaka <gniibe@fsij.org>
2022-11-25 15:37:23 +09:00
Ingo Klöcker
5903fa454a
core: Allow nullptr for key on card-edit
* src/edit.c (interact_start, edit_start): Return error if key is null
on edit-key.
--

In case of card-edit, key is typically null.
2022-11-15 10:03:23 +01:00
NIIBE Yutaka
ae2057e601
doc: Update documentation for gpgme.pc and pkg-config.
--

GnuPG-bug-id: 6274
Signed-off-by: NIIBE Yutaka <gniibe@fsij.org>
2022-11-15 14:25:26 +09:00
NIIBE Yutaka
abd51848bd
gpgme.m4: Include _AM_PATH_GPGRT_CONFIG implementation.
* src/gpgme.m4 (_AM_PATH_GPGRT_CONFIG): New.
(_AM_PATH_GPGME_CONFIG): Require _AM_PATH_GPGRT_CONFIG.

--

GnuPG-bug-id: 6273
Signed-off-by: NIIBE Yutaka <gniibe@fsij.org>
2022-11-15 13:40:57 +09:00
NIIBE Yutaka
2b7fcbf2f2
m4: Update gpg-error.m4.
* m4/gpg-error.m4: Update from libgpg-error master.

--

GnuPG-bug-id: 6273
Signed-off-by: NIIBE Yutaka <gniibe@fsij.org>
2022-11-15 13:39:56 +09:00
Ingo Klöcker
6bcfbb3498
core: Check for nullptr
* src/edit.c (interact_start, edit_start): Return error if key is null.
--

This prevents a crash further down the road.
2022-11-11 11:46:11 +01:00
Ingo Klöcker
b6593bda1f
qt: Allow disabling automatic trust database check on key listing
* lang/qt/src/Makefile.am (qgpgme_sources): Add listallkeysjob.cpp.
* lang/qt/src/listallkeysjob.cpp: New.
* lang/qt/src/listallkeysjob.h (enum ListAllKeysJob::Option,
typedef ListAllKeysJob::Options, ListAllKeysJob::setOptions,
ListAllKeysJob::options): New.
* lang/qt/src/qgpgmelistallkeysjob.cpp (list_keys): Set context flag
"no-auto-check-trustdb" if requested.
(QGpgMEListAllKeysJob::start, QGpgMEListAllKeysJob::exec): Add options
to call of list_keys.
--

GnuPG-bug-id: 6261
2022-11-04 10:44:07 +01:00
Ingo Klöcker
4f874ea431
core: New context flag "no-auto-check-trustdb"
* src/context.h (gpgme_context): Add field no_auto_check_trustdb.
* src/gpgme.c (gpgme_set_ctx_flag, gpgme_get_ctx_flag): Add flag
"no-auto-check-trustdb".
* src/engine-gpg.c (engine_gpg): Add flags.no_auto_check_trustdb.
(gpg_set_engine_flags): Set the flag.
(build_argv): Pass option to gpg.

* tests/run-keylist.c (show_usage, main): Add option --no-trust-check.
--

This makes the --no-auto-check-trustdb option available in the GPGME API
to disable the potentially expensive automatic trust database check.

GnuPG-bug-id: 6261
2022-11-04 10:38:41 +01:00
NIIBE Yutaka
9f5e117292
build: Update libassuan.m4.
* m4/libassuan.m4: Update from libassuan master.

--

GnuPG-bug-id: 5034
Signed-off-by: NIIBE Yutaka <gniibe@fsij.org>
2022-11-02 10:12:48 +09:00
NIIBE Yutaka
9f55dceca0
build: Prefer gpgrt-config when available.
* src/gpgme.m4: Overriding the decision by --with-gpgme-prefix,
use gpgrt-config gpgme when gpgrt-config is available.

--

This may offer better migration.

GnuPG-bug-id: 5034
Signed-off-by: NIIBE Yutaka <gniibe@fsij.org>
2022-11-02 10:12:46 +09:00
Werner Koch
1c9694f8d5
core: New global flags "inst-type".
* src/gpgme.c (gpgme_set_global_flag): Add flag "inst-type".
* src/w32-util.c (_gpgme_set_get_inst_type): New.
(INST_TYPE_GPG4WIN_DIR): New.
(INST_TYPE_GPGDESK_DIR): New.
(_gpgme_get_gpgconf_path): Implement this flag.  Replace fixed strings
by the macros.
* src/posix-util.c (_gpgme_set_get_inst_type): New dummy.
--

This is intended for use by Kleopatra to reliable find the expected
GnuPG installation.
2022-10-26 12:10:57 +02:00
NIIBE Yutaka
f1802682c3
python: Fix configure generating setup.py.
* lang/python/setup.py.in: Handle the case, when substitutions
may be empty.

--

Reported-by: Andreas Metzler
Fixes-commit: ae9258fbf3
GnuPG-bug-id: 6204
Signed-off-by: NIIBE Yutaka <gniibe@fsij.org>
2022-10-26 11:02:36 +09:00
Werner Koch
830e017e5d
core: Protect against a theoretical integer overflow in parsetlv.c
* src/parsetlv.c (_gpgme_parse_tlv): Detect integer overflow.
--

Although there is no concrete case where we use for example
(to.nhdr+ti.length), it feels safer to protect against this anyway.
2022-10-24 13:50:41 +02:00
Ingo Klöcker
d9ac138595
cpp: Allow setting the curve to use when generating ECC keys
lang/cpp/src/gpggencardkeyinteractor.h (class GpgGenCardKeyInteractor):
Add enum Curve. Add member function setCurve.
lang/cpp/src/gpggencardkeyinteractor.cpp
(class GpgGenCardKeyInteractor::Private): Initialize simple members
in-class. Add member curve.
(GpgGenCardKeyInteractor::~GpgGenCardKeyInteractor): Use default d'tor.
(GpgGenCardKeyInteractor::setCurve): New.
(GpgGenCardKeyInteractor::action): Return curve defaulting to
Curve25519.
--

This enables users of this interactor to request the generation of
ECC keys with a specific curve as smart card keys. It's up to the user
to specify a curve that is actually supported by the smart card.

GnuPG-bug-id: 4429
2022-10-24 12:22:09 +02:00
NIIBE Yutaka
d36905bb80
build: Update gpg-error.m4.
* m4/gpg-error.m4: Update from libgpg-error 1.46.

--

Signed-off-by: NIIBE Yutaka <gniibe@fsij.org>
2022-10-24 12:10:39 +09:00
Ingo Klöcker
2ff09f474f
build,qt: Check whether building with -fPIC is needed
m4/qt6.m4: Use build test to check whether -fPIC is needed for building
a Qt application.
--
2022-10-14 14:16:47 +02:00
Ingo Klöcker
1792db5834
build,qt: Fail check for Qt if moc wasn't found
* m4/qt5.m4, m4/qt6.m4: Perform build test only if moc was found.
--

If moc wasn't found but the build test (which doesn't require moc)
succeeded, then success was reported.
2022-10-14 14:02:26 +02:00
Ingo Klöcker
55e660ee94
doc: Update NEWS
--
2022-10-14 10:34:34 +02:00
Ingo Klöcker
f7a4671428
build,qt: Always compile the Qt 6 test application with -fpic
* m4/qt6.m4: Do not add -fpic to GPGME_QT6_CFLAGS. Add -fpic to CPPFLAGS
used for build test of simple Qt 6 application.
--

The pkgconfig files of Qt6Core do not contain the qt_config variable,
so that we cannot easily check whether Qt6 was compiled with pic. For
simplicity we always compile the test application with -fpic to avoid
a build failure if Qt6 was actually compiled with pic.
For the actual build of QGpgME libtool automatically uses -fPIC, so that
we don't have to add it to the GPGME_QT6_CFLAGS.
2022-10-14 09:31:18 +02:00
Ingo Klöcker
e6a1b241b4
build,qt: Clean up all generated files
* lang/qt/src/Makefile.am (CLEANFILES): Add QGpgmeConfig-w32.cmake.in
and QGpgmeQt6Config-w32.cmake.in.
--
2022-10-11 11:00:15 +02:00
Ingo Klöcker
b2fb26baea
qt,tests: Port test to QRegularExpression.
* lang/qt/tests/t-trustsignatures.cpp: Use QRegularExpression instead of
QRegExp.
--

This allows building with Qt 6 without Core5Compat.
2022-10-11 11:00:15 +02:00
Ingo Klöcker
4938c24a46
qt: Remove obsolete code.
* lang/qt/src/qgpgmenewcryptoconfig.cpp (struct Select1St): Remove.
--

This struct was never used in this implementation of the crypto config
classes and it causes a build error with Qt 6 where QPair is an alias
for std::pair.
2022-10-11 11:00:15 +02:00
Ingo Klöcker
8d019bbb8d
build,qt: Allow building QGpgME for Qt 6
* configure.ac: Look for Qt 5 and/or Qt 6. Require C++17 if Qt 6 binding
is built. Build cmake files QGpgmeConfig* for Qt 5 and QGpgmeQt6Config*
for Qt 6.
(available_languages): Add "qt5" and "qt6".
(WANT_QT5, WANT_QT6): New conditionals.
* lang/qt/src/Makefile.am: Keep building libqgpgme for Qt 5. Build
libqgpgmeqt6 for Qt 6.
* lang/qt/tests/Makefile.am: Build tests for Qt 5 or Qt 6.
* lang/qt/src/QGpgmeQt6Config-w32.cmake.in.in,
lang/qt/src/QGpgmeQt6Config.cmake.in.in,
lang/qt/src/QGpgmeQt6ConfigVersion.cmake.in, m4/qt6.m4: New.
--

This makes it possible to build QGpgME optionally for Qt 6.4.0 or later.
By default or if the language "qt" is enabled, then QGpgME is built
either for Qt 5 (if found) or Qt 6. A build for Qt 5 or Qt 6 can be
requested by explicitly enabling the language "qt5" or "qt6". Building
QGpgME for Qt 5 and Qt 6 simultaneously is not supported.
2022-10-11 11:00:14 +02:00
Ingo Klöcker
8e908029ff
build,qt: Explicitly namespace a few Qt variables for Qt5
m4/qt.m4: Rename to
m4/qt5.m4: this.
(FIND_QT): Rename to FIND_QT5.
(GPGME_QT): Change variable prefix to GPGME_QT5.
(GPGME_QTTEST: Change variable prefix to GPGME_QT5TEST.
configure.ac, lang/qt/src/Makefile.am, lang/qt/tests/Makefile.am:
Adjust accordingly.
--

In preparation to adding support for building qgpgme for Qt6, add the
version number to a few variables to avoid confusion.
2022-10-10 14:46:39 +02:00
Werner Koch
b1e5f3b183
core: Fix SIG_CREATED status parsing for 0x1F sigs
* src/sign.c (parse_sig_created): Special case the rfc4880 "1F" status.
--

This has always been wrong but we can't simply force strtol to assume
hex.  Patch compiles but has received no specific test.  For details
see
GnuPG-bug-id: 6223
2022-09-29 09:59:27 +02:00
NIIBE Yutaka
ae9258fbf3
build:python: Don't use gpg-error-config/gpgme-config.
* lang/python/setup.py.in: Use @prefix@, @GPGME_CONFIG_LIBS@,
@GPGME_CONFIG_CFLAGS@, and @GPG_ERROR_CFLAGS@ of configure.

--

GnuPG-bug-id: 6204
Signed-off-by: NIIBE Yutaka <gniibe@fsij.org>
2022-09-15 13:46:23 +09:00
NIIBE Yutaka
fbd9407646
Fix for modern compiler.
* src/argparse.c (show_version): It's no args.

--

Signed-off-by: NIIBE Yutaka <gniibe@fsij.org>
2022-09-15 13:45:35 +09:00
Ingo Klöcker
eedaaf7016
cpp: Reject signing expired keys
* lang/cpp/src/gpgsignkeyeditinteractor.cpp (enum SignKeyState): Add
new state REJECT_SIGN_EXPIRED.
(makeTable): Add entries for new state to transition map.
(GpgSignKeyEditInteractor::action): Handle new state.
--

With this change the edit interactor aborts the key signing operation
with a "key expired" error instead of with a "general error".

GnuPG-bug-id: 6155
2022-09-14 10:41:38 +02:00
NIIBE Yutaka
80670f60ba Fix parsing import status for invalid fingerprint.
* src/import.c (parse_import): Handle invalid fingerprint case.

--

GnuPG-bug-id: 6187
Signed-off-by: NIIBE Yutaka <gniibe@fsij.org>
2022-09-07 11:27:32 +09:00
Ingo Klöcker
1522813888 build: Omit -I... and -L... for standard paths in pkgconfig file
* configure.ac (GPGME_CONFIG_CFLAGS): Prefix with -I${includedir} for
non-standard include paths.
(GPGME_CONFIG_LIBS): Prefix with -L${libdir} for non-standard library
paths.
* src/gpgme.pc.in (Cflags): Remove hard-coded -I${includedir}.
(Libs): Remove hard-coded -L${libdir}.
--

This helps prevent problems when building/linking something that depends
on gpgme (installed in standard path) and some other library (installed
in a standard path and a custom path).

See T6136 for related changes in libgpg-error.
2022-08-22 19:09:54 +02:00
Ingo Klöcker
73e96bfaa8 build: Update ax_cxx_compile_stdcxx macro
* m4/ax_cxx_compile_stdcxx.m4: Replace with current version from the
autoconf archive.
--

This fixes the problem that the switch -std=c++11 was omitted if the
compiler supported C++11 features by default. This made gcc happily
compile C++14 code. Now C++11 is enforced by gcc.

GnuPG-bug-id: 6141
2022-08-22 15:04:32 +02:00
Ingo Klöcker
83176ad7d3 qt: Fix building with C++11
* lang/qt/src/qgpgmerefreshsmimekeysjob.cpp
(QGpgMERefreshSMIMEKeysJob::start): Replace 'auto' in lambda with the
actual type.
* lang/qt/src/qgpgmesignkeyjob.cpp (class TrustSignatureProperties): Add
default c'tor and c'tor initializing all members.
* lang/qt/src/util.cpp (toFingerprints): Replace 'auto' in lambda with
the actual type.
* lang/qt/tests/run-exportjob.cpp (createExportJob): Replace 'auto'
return type with actual type.
--

This fixes compilation with strict C++11.

GnuPG-bug-id: 6141
2022-08-22 14:39:22 +02:00
Ingo Klöcker
0566180684 qt: Fix building with Qt6
* lang/qt/src/util.cpp, lang/qt/src/util.h: Replace forward declaration
with include.
--

Based on patch by Laurent Montel
2022-08-22 09:30:14 +02:00
Ingo Klöcker
f02c20cc9c cpp: Fix building with C++11
* lang/cpp/src/importresult.cpp (ImportResult::mergeWith): Replace
'auto' in lambdas with the actual type.
--

Generic lambdas require C++14.

GnuPG-bug-id: 6141
2022-08-19 11:05:37 +02:00
Ingo Klöcker
2e7a61b898 qt,tests: Make test pass on 32-bit systems
* lang/qt/tests/t-addexistingsubkey.cpp
(AddExistingSubkeyJobTest::testAddExistingSubkeyWithExpiration): Handle
negative expiration date.
--

On 32-bit systems the expiration date of the test key overflows. This
will cause the AddExistingSubkeyJob to fail. We expect it to fail with
an "invalid time" error.

GnuPG-bug-id: 6137
2022-08-18 10:55:09 +02:00
Ingo Klöcker
2fa5c80aeb cpp: Fix handling of "no key" or "invalid time" situations
* lang/cpp/src/gpgaddexistingsubkeyeditinteractor.cpp
(GpgAddExistingSubkeyEditInteractor::Private::nextState): Fix inverted
logic of string comparisons.
--

This fixes the problem that the interactor didn't return the proper
error code if gpg didn't accept the key grip or the expiration date.

GnuPG-bug-id: 6137
2022-08-18 10:43:19 +02:00
Ingo Klöcker
f2b48de26b qt,tests: Make sure expiration time is interpreted as unsigned number
* lang/qt/tests/t-addexistingsubkey.cpp,
lang/qt/tests/t-changeexpiryjob.cpp: Convert expiration time to
uint_least32_t.
--

This doesn't change the outcome of the tests (they also pass without
this change because of the expiration dates of the test keys), but it's
still good practise to treat the expiration time as an unsigned number
if the assertions check that the expiration time is in some range.

GnuPG-bug-id: 6137
2022-08-17 15:22:29 +02:00
Ingo Klöcker
81d4b7f2d7 qt,tests: Log the actual error code if the assertion fails
* lang/qt/tests/t-addexistingsubkey.cpp (
AddExistingSubkeyJobTest::testAddExistingSubkeyAsync,
AddExistingSubkeyJobTest::testAddExistingSubkeySync,
AddExistingSubkeyJobTest::testAddExistingSubkeyWithExpiration): Use
QCOMPARE instead of QVERIFY for asserting equality.
--

GnuPG-bug-id: 6137
2022-08-17 14:56:13 +02:00
Ingo Klöcker
c977424a1d qt: Make sure expiration time is interpreted as unsigned number
* lang/qt/src/qgpgmeaddexistingsubkeyjob.cpp (add_subkey): Convert
expiration time to uint_least32_t.
--

This fixes the corresponding test on 32-bit systems where time_t (the
return type of expirationTime()) is a signed 32-bit integer type.

GnuPG-bug-id: 6137
2022-08-17 14:52:04 +02:00
Andre Heinecke
5f51a9b458
w32: Add another fallback to look for gpgconf.exe
* src/w32-util.c (_gpgme_get_gpgconf_path): Add fallback for
GnuPG VS-Desktop install scheme.

--
GnuPG VS-Desktop has the install layout:

%PROGRAMFILES%\GnuPG VS-Desktop\bin\libgpgme.dll
%PROGRAMFILES%\GnuPG VS-Desktop\GnuPG\bin\gpgconf.exe

This fallback is of course only required if the registry
string pointing to the correct install directory is
broken.

GnuPG-Bug-Id: T6131
2022-08-12 15:16:36 +02:00
Andre Heinecke
586846209b
Qt: Fix working with no gpgconf in CryptoConfig
* lang/qt/src/cryptoconfig.cpp (CryptoConfig::entry): Add nullptr
  checks.

--
This fixes a crash when gpgconf is not found. When every return
value is NULL.

GnuPG-Bug-Id: T6131
2022-08-11 11:39:10 +02:00
Werner Koch
7e2ef54b9c
Post release updates
--
2022-08-10 15:33:02 +02:00
Werner Koch
26ff163bd6
Release 1.18.0 2022-08-10 12:37:47 +02:00
Werner Koch
9ee74b68e6
tests: Make t-edit-sign more robust.
* tests/gpg/t-edit-sign.c (interact_fnc): Provide the default answer.
--

A default answer to prompts should always be given.
2022-08-10 12:34:12 +02:00
Ingo Klöcker
5d91182c95 qt: Add missing include
* lang/qt/tests/t-revokekey.cpp: Include QDebug.
--

Doesn't seem to matter with Qt 5.15.5, but seems to be needed for older
versions of Qt.
2022-08-10 12:00:10 +02:00
Ingo Klöcker
99c1b14470 doc: Update NEWS
--

GnuPG-bug-id: 5951, 6056
2022-08-10 10:15:34 +02:00
Ingo Klöcker
db7d79063f qt: Add job to set the primary user ID of OpenPGP keys
* lang/qt/src/qgpgmesetprimaryuseridjob.cpp,
lang/qt/src/qgpgmesetprimaryuseridjob.h,
lang/qt/src/setprimaryuseridjob.h: New.
* lang/qt/src/protocol.h (class Protocol): Add pure virtual member
function setPrimaryUserIDJob.
* lang/qt/src/protocol_p.h (Protocol::setPrimaryUserIDJob): New.
* lang/qt/src/job.cpp, lang/qt/src/Makefile.am: Update accordingly.

* lang/qt/tests/t-setprimaryuserid.cpp: New.
* lang/qt/tests/Makefile.am: Add new test.
--

GnuPG-bug-id: 5938
2022-08-09 14:52:42 +02:00
Ingo Klöcker
125867f268 cpp: Add support for gpgme_op_set_uid_flag
* lang/cpp/src/context.cpp, lang/cpp/src/context.h
(Context::setPrimaryUid, Context::startSetPrimaryUid): New.
--

GnuPG-bug-id: 5938
2022-08-09 14:52:42 +02:00
NIIBE Yutaka
f8d99bb9e4 python: Don't call __del__ from __exit__ method.
* lang/python/src/core.py (Context, Data): Don't call __del__
from __exit__ method, as the object may be still in use.
* lang/python/tests/t-idiomatic.py: Fix the test.

--

GnuPG-bug-id: 6060
Signed-off-by: NIIBE Yutaka <gniibe@fsij.org>
2022-08-09 09:57:28 +09:00
NIIBE Yutaka
180899c7c3 python: Don't access gpgme with wrapped=None.
* lang/python/src/core.py (GpgmeWrapper, Context): Check self.wrapped
is valid.

--

GnuPG-bug-id: 6060
Signed-off-by: NIIBE Yutaka <gniibe@fsij.org>
2022-08-05 14:57:32 +09:00
Jasper Spaans
b2f224a471 python: Reset passphrase callback correctly.
* lang/python/src/core.py (Context(GpgmeWrapper)): Reset passphrase
callback correctly, for encrypt, decrypt, create_key, and
create_subkey methods.

--

Signed-off-by: Jasper Spaans <jasper@startmail.com>
2022-08-05 11:02:44 +09:00
Ingo Klöcker
c3b183831d qt: Remove job for refreshing OpenPGP keys
* lang/qt/src/qgpgmerefreshopenpgpkeysjob.cpp,
lang/qt/src/qgpgmerefreshopenpgpkeysjob.h,
lang/qt/src/refreshopenpgpkeysjob.h: Remove.
* lang/qt/src/Makefile.am, lang/qt/src/job.cpp: Update accordingly.
* lang/qt/src/protocol.h (class Protocol): Remove pure virtual member
function refreshOpenPGPKeysJob.
* lang/qt/src/protocol_p.h (Protocol::refreshOpenPGPKeysJob): Remove.

* lang/qt/tests/run-refreshkeysjob.cpp (main): Use ReceiveKeysJob for
OpenPGP keys.
--

The RefreshOpenPGPKeysJob did more than it was intended to do, e.g. it
imported new keys with the email addresses of the key to be refreshed
via the configured auto-key-locate methods, but only a refresh from the
key servers is wanted. For this we can use the ReceiveKeysJob.

This commit mostly reverts the commits
e12861f18c
c64a8daf50

The changes are source- and binary-compatible to the last release.

GnuPG-bug-id: 5951
2022-08-04 12:06:15 +02:00
NIIBE Yutaka
cc37447b62 build: Update config.guess and config.sub.
* build-aux/config.guess: Update from upstream.
* build-aux/config.sub: Ditto.

--

GnuPG-bug-id: 6078
Signed-off-by: NIIBE Yutaka <gniibe@fsij.org>
2022-07-21 13:47:51 +09:00
NIIBE Yutaka
16020c5fd9 build: Fix for modern Autoconf.
* m4/glib-2.0.m4: Use AC_RUN_IFELSE and AC_LINK_IFELSE.

--

Signed-off-by: NIIBE Yutaka <gniibe@fsij.org>
2022-07-21 13:47:06 +09:00
Ingo Klöcker
5436b309fe qt: Allow setting the file name of signed and encrypted data
* lang/qt/src/Makefile.am (qgpgme_sources): Add signencryptjob.cpp.
* lang/qt/src/signencryptjob.cpp: New.
* lang/qt/src/signencryptjob.h (class SignEncryptJob): Add member
functions setFileName, fileName.
* lang/qt/src/qgpgmesignencryptjob.cpp (sign_encrypt): Set file name of
input.
(sign_encrypt_qba, QGpgMESignEncryptJob::exec,
QGpgMESignEncryptJob::start): Pass file name to sign_encrypt resp.
sign_encrypt_qba.
--

This makes it possible to store the original name of a signed and
encrypted file in the resulting data.

GnuPG-bug-id: 6056
2022-07-05 18:13:01 +02:00
Ingo Klöcker
bc10169724 qt: Allow setting the file name of encrypted data
* lang/qt/src/Makefile.am (qgpgme_sources): Add encryptjob.cpp.
* lang/qt/src/encryptjob.cpp: New.
* lang/qt/src/encryptjob.h (class EncryptJob): Add member functions
setFileName, fileName.
* lang/qt/src/qgpgmeencryptjob.cpp (encrypt): Set file name of input.
(encrypt_qba, QGpgMEEncryptJob::exec, QGpgMEEncryptJob::start): Pass
file name to encrypt resp. encrypt_qba.
--

This makes it possible to store the original name of an encrypted file
in the encryption result.

GnuPG-bug-id: 6056
2022-07-05 18:10:08 +02:00
Ingo Klöcker
31423945d2 qt: Fix filename of cmake config files for w32
* lang/qt/src/Makefile.am (EXTRA_DIST): Add
QGpgmeConfig-w32.cmake.in.in.
--
2022-07-04 17:10:31 +02:00
Laurent Montel
d42323f902 qt: Add #include <QStringList> needed for building against qt6
* lang/qt/src/downloadjob.h, lang/qt/src/exportjob.h,
lang/qt/src/keylistjob.h lang/qt/src/refreshkeysjob.h: in qt6 we need
to use #include <QStringList>
--

It fixes some compile qt6 compile error.

Signed-off-by: Laurent Montel <montel@kde.org>
2022-07-04 16:58:59 +02:00
Ingo Klöcker
6e45da30ae cpp: Remove obsolete compatibility with KF5 variants
* lang/cpp/src/GpgmeppConfig-w32.cmake.in.in,
lang/cpp/src/GpgmeppConfig.cmake.in.in: Remove find_package() call.
--

The KF5 variants have been removed years ago with revision
a3cf30f894.
2022-06-30 12:30:15 +02:00
NIIBE Yutaka
02a2f35035 build: When no gpg-error-config, not install gpgme-config.
* configure.ac (USE_GPGRT_CONFIG): New.
* src/Makefile.am [USE_GPGRT_CONFIG]: Conditionalize the install
of gpgme-config.

--

When system will migrate use of gpgrt-config and removal of
gpg-error-config, gpgme-config will not be installed (but use gpgme.pc
by gpgrt-config).

Signed-off-by: NIIBE Yutaka <gniibe@fsij.org>
2022-06-28 11:28:12 +09:00
NIIBE Yutaka
aa94b4cee5 build: Update gpg-error.m4
* m4/gpg-error.m4: Update from libgpg-error.

--

Signed-off-by: NIIBE Yutaka <gniibe@fsij.org>
2022-06-28 11:28:06 +09:00
Ingo Klöcker
d59cf17257 tests: Add support for clear text signatures to test runner
* tests/run-sign.c (show_usage): Add new argument "--clear".
(main): Handle new argument "--clear".
--

GnuPG-bug-id: 6028
2022-06-14 10:10:57 +02:00
Ingo Klöcker
fd813f5c39 qt,tests: Allow 1-day-offset for expiration date
* lang/qt/tests/t-various.cpp (TestVarious::testSignKeyWithExpiration):
Assert that the expiration date is either 2106-02-05 or 2106-02-04.

--

This avoids a test failure if the test is run at 00:xx:xx in a location
that uses DST.

GnuPG-bug-id: 5991
2022-06-10 12:03:39 +02:00
Ingo Klöcker
7870fdbfef qt: Prevent u32 overflow when calculating expiration date
* lang/qt/src/qgpgmesignkeyjob.cpp (sign_key): Change maxAllowedDate to
2106-02-05. Change log-level from warning to debug.
* lang/qt/tests/t-various.cpp (TestVarious::testSignKeyWithExpiration):
Remove check for warning. Adapt assertion.
--

Capping the expiration date at 2106-02-05 prevents a u32 overflow when
adding the number of days until the maximal date to the current time.

GnuPG-bug-id: 5991
2022-06-10 11:54:03 +02:00
Ingo Klöcker
918afc809d Revert "tests: Avoid problems with local time across a day boundary."
This reverts commit 5ba0e454a3.
2022-06-09 15:43:24 +02:00
Ingo Klöcker
5d19eb4ad5 core: Handle import status lines during keylist operation
* src/keylist.c (gpgme_op_keylist_from_data_start): Call
_gpgme_op_import_init_result.
--

This fixes a crash when importing keys from data. Initializing the
import result was missing for this keylist operation.

Fixes-commit: f3ca57dfd7
GnuPG-bug-id: 5951
2022-06-09 15:30:14 +02:00
Werner Koch
5ba0e454a3
tests: Avoid problems with local time across a day boundary.
--

GnuPG-bug-id: 5991
2022-05-23 08:20:04 +02:00
Andre Heinecke
f3011b5a19
cpp: Export KeyListModeSaver
* lang/cpp/src/context.h (Context::KeyListModeSaver): Add Export.

--
This is required for Windows.
2022-05-12 09:34:15 +02:00
Ingo Klöcker
f72cf726ca core: Set SECRET flag of subkeys stored on smart cards
* src/keylist.c (parse_sec_field15): Set SECRET flag.
--

Explicitly setting the SECRET flag for subkeys stored on smart cards
makes sure that the flag is also set if GPGME_KEYLIST_MODE_WITH_SECRET
is used when listing OpenPGP keys (as documented in the API
documentation). If secret keys are listed, then the flag is already set
when the packet type is parsed.

GnuPG-bug-id: 5965
2022-05-06 09:34:18 +02:00
Ingo Klöcker
306fd9c915 cpp: Output more properties of a subkey
* lang/cpp/src/key.cpp (ostream operator<< for Subkey): Fix wrong output
of isInvalid and isDisabled flags. Add output of key grip, card serial
number and the flags isSecret, isQualified, isDeVs, and isCardKey.
--

This makes it easier to check those properties for different keys, e.g.
with the run-keylist test program.

GnuPG-bug-id: 5965
2022-05-05 17:25:47 +02:00
Ingo Klöcker
e029fd2735 cpp,tests: Actually parse the --with-secret option
* lang/cpp/tests/run-keylist.cpp (main): Handle --with-secret option.
Print error for unknown option.
--

The --with-secret option was already listed in the help. Now it also
works.

GnuPG-bug-id: 5965
2022-05-05 17:24:59 +02:00
Ingo Klöcker
9e8c8e448e qt: Revert change of result signal of RefreshKeysJob
* lang/qt/src/refreshkeysjob.h (RefreshKeysJob::result): Remove optional
parameters auditLogAsHtml and auditLogError.
* lang/qt/tests/run-refreshkeysjob.cpp (main): Update accordingly.
--

This reverts f4c3560925. The reason for
the previous change does no longer apply.

GnuPG-bug-id: 5951
2022-05-05 10:39:26 +02:00
Ingo Klöcker
15a4940aa7 qt: Use lambda instead of std::bind
* lang/qt/src/qgpgmerefreshopenpgpkeysjob.cpp
(QGpgMERefreshOpenPGPKeysJob::start): Replace std::bind call with a
lambda.
--

GnuPG-bug-id: 5951
2022-05-05 10:32:34 +02:00
Ingo Klöcker
c64a8daf50 qt: Emit import result when refreshing OpenPGP keys
* lang/qt/src/refreshopenpgpkeysjob.h: New.
* lang/qt/src/Makefile.am, lang/qt/src/job.cpp: Update accordingly.
* lang/qt/src/qgpgmerefreshopenpgpkeysjob.h (class
QGpgMERefreshOpenPGPKeysJob): Derive from RefreshOpenPGPKeysJob with
result ImportResult. Remove unused start overload.
* lang/qt/src/qgpgmerefreshopenpgpkeysjob.cpp (locate_external_keys):
Ignore result of KeyListJob. Return import result.
(receive_keys): Return import result.
(refresh_keys): Merge the two import results and return the result.
* lang/qt/src/protocol.h (class Protocol): Add pure virtual member
function refreshOpenPGPKeysJob.
* lang/qt/src/protocol_p.h (Protocol::refreshKeysJob): Return nullptr
for OpenPGP protocol.
(Protocol::refreshOpenPGPKeysJob): New.

* lang/qt/tests/run-refreshkeysjob.cpp (main): Use appropriate job
for the protocol of the key to refresh.
--

This adds RefreshOpenPGPKeysJob complementing RefreshKeysJob (for S/MIME
keys). Changing the result type of RefreshKeysJob would break the ABI.
Therefore we have to introduce a new base class for the refresh job for
OpenPGP. We derive this base class from AbstractImportJob because we
want to return an import result.

GnuPG-bug-id: 5951
2022-05-04 14:51:50 +02:00
Ingo Klöcker
3519d61173 cpp: Allow retrieving import result of key listing with locate mode
* lang/cpp/src/context_p.h (enum Context::Private::Operation): Add
value KeyListWithImport.
* lang/cpp/src/context.cpp (Context::startKeyListing, Context::nextKey):
Set lastop to KeyListWithImport if keylist mode includes Locate.
--

Adding Import to lastop for keylist operations that perform a locate
allows retrieving the import result with Context::importResult.

GnuPG-bug-id: 5951
2022-05-04 14:31:03 +02:00
Ingo Klöcker
f3ca57dfd7 core: Handle import status lines during keylist operation
* src/import.c (import_status_handler): Rename to ...
(_gpgme_import_status_handler): this. Make non-static.
(_gpgme_op_import_init_result): New.
(_gpgme_op_import_start, _gpgme_op_import_keys_start,
_gpgme_op_receive_keys_start): Call _gpgme_op_import_init_result.
* src/keylist.c (keylist_status_handler): Call
_gpgme_import_status_handler to handle import status lines.
(gpgme_op_keylist_start, gpgme_op_keylist_ext_start): Call
_gpgme_op_import_init_result.
* src/ops.h (_gpgme_op_import_init_result,
_gpgme_import_status_handler): New prototypes.
--

If a keylist operation with keylist mode GPGME_KEYLIST_MODE_LOCATE is
run, then gpg emits import status lines. Handling those status lines
allows users to retrieve the result of a --locate-(external)-keys
command.

GnuPG-bug-id: 5951
2022-05-04 14:23:42 +02:00
Ingo Klöcker
d911a15364 cpp: Allow merging the results of two imports
* lang/cpp/src/importresult.h, lang/cpp/src/importresult.cpp (class
ImportResult): Add member function mergeWith.
--

This allows creating a consolidated result of several independent
imports. If the import results to merge considered the same keys, then
not all counts can be consolidated correctly, but the important numbers
like the number of considered keys, the number of imported keys, the
number of unchanged keys and the numbers of new user IDs, subkeys,
signatures and revocations should be correct.

GnuPG-bug-id: 5951
2022-05-04 12:37:47 +02:00
Ingo Klöcker
f1a354fd57 qt: Apply compiler hint
* lang/qt/tests/t-verify.cpp (VerifyTest::testSignatureKey): Use
reference type to prevent copying.
--
2022-05-02 16:04:28 +02:00
Ingo Klöcker
540e7bf3d4 qt: Use GpgME::Locate alias
* lang/qt/src/protocol_p.h (Protocol::locateKeysJob): Use Locate alias
instead of Extern|Local.
* lang/qt/src/qgpgmekeyformailboxjob.cpp (do_work): Ditto.
--
2022-05-02 16:00:43 +02:00
Ingo Klöcker
e12861f18c qt: Add job for refreshing OpenPGP keys
* lang/qt/src/qgpgmerefreshopenpgpkeysjob.h,
lang/qt/src/qgpgmerefreshopenpgpkeysjob.cpp: New.
* lang/qt/src/Makefile.am: Add new files.
* lang/qt/src/protocol_p.h (Protocol::refreshKeysJob): Add support for
OpenPGP protocol.
--

The new job performs a --locate-external-keys for the email addresses
of all not revoked user IDs of the given keys, and it performs a
--recv-keys for the fingerprints of the given keys. The former may
import new keys from WKD or an LDAP server or via some other
(hopefully trusted) auto-key-locate mechanism.

GnuPG-bug-id: 5951
2022-05-02 15:51:44 +02:00
Ingo Klöcker
34786132fe cpp: Add RAII class for saving/restoring the key list mode
* lang/cpp/src/context.h, lang/cpp/src/context.cpp (class Context):
Add nested class KeyListModeSaver.
--

This RAII-style class can be used to save the currently used key list
mode in case it needs to be changed temporarily. On destruction, it
will restore the key list mode that was active at construction time.

GnuPG-bug-id: 5951
2022-05-02 15:51:44 +02:00
Ingo Klöcker
99fd565889 qt: Add debug helper for Result classes with output stream operator
* lang/qt/src/util.h (toLogString): New.
--

GnuPG-bug-id: 5951
2022-05-02 15:06:56 +02:00
Ingo Klöcker
0c304beeaa qt: Factor out helper for getting the fingerprints of some keys
* lang/qt/src/util.h, lang/qt/src/util.cpp (toFingerprints): New.
* lang/qt/src/qgpgmerefreshsmimekeysjob.cpp: Use the helper.
--

GnuPG-bug-id: 5951
2022-05-02 15:04:37 +02:00
Ingo Klöcker
97e09fb964 qt,doc: Fix some API documentation
--

Fix or remove API documentation that has been copied and pasted from
other jobs.
2022-05-02 14:58:21 +02:00
Ingo Klöcker
54c4fd16d1 qt: Fix connection to readyReadStandardOutput signal
* lang/qt/src/qgpgmerefreshsmimekeysjob.h,
lang/qt/src/qgpgmerefreshsmimekeysjob.cpp
(QGpgMERefreshSMIMEKeysJob::slotStderr): Remove.
* lang/qt/src/qgpgmerefreshsmimekeysjob.cpp
(QGpgMERefreshSMIMEKeysJob::startAProcess): Handle
readyReadStandardOutput and readyReadStandardError signals with lambdas.
--

For now output stdout and stderr of gpgsm process as debug log. In
particular, this "adds" the missing slot slotStdout.

GnuPG-bug-id: 5951
2022-04-29 11:55:47 +02:00
Ingo Klöcker
9686258bd1 qt: Add test runner for refresh job
* lang/qt/tests/run-refreshkeysjob.cpp: New.
* lang/qt/tests/Makefile.am (run_refreshkeysjob_SOURCES): New.
(noinst_PROGRAMS): Add new build artifact.
--

GnuPG-bug-id: 5951
2022-04-29 11:44:30 +02:00
Ingo Klöcker
f4c3560925 qt: Make RefreshKeysJob result compatible with standard job result
* lang/qt/src/refreshkeysjob.h (RefreshKeysJob::result): Add optional
parameters auditLogAsHtml and auditLogError.
--

This is necessary for the OpenPGP-implementation of this job.

GnuPG-bug-id: 5951
2022-04-29 11:24:36 +02:00
Ingo Klöcker
fd97cbaa44 qt: Allow refreshing a list of keys
* lang/qt/src/refreshkeysjob.h (class RefreshKeysJob): Add pure virtual
member function start taking a list of keys.
* lang/qt/src/qgpgmerefreshsmimekeysjob.h,
lang/qt/src/qgpgmerefreshsmimekeysjob.cpp (class
QGpgMERefreshSMIMEKeysJob): Implement new member function.
--

The new overload makes it easier to refresh some keys if one does
already have Keys.

GnuPG-bug-id: 5951
2022-04-29 10:50:31 +02:00
Ingo Klöcker
62e7709717 qt: Minor refactoring
* lang/qt/src/qgpgmerefreshsmimekeysjob.cpp: Use namespace QGpgME.
--

GnuPG-bug-id: 5951
2022-04-29 10:46:23 +02:00
Ingo Klöcker
f47bc992ae qt: Rename QGpgMERefreshKeysJob to QGpgMERefreshSMIMEKeysJob
* lang/qt/src/qgpgmerefreshkeysjob.h,
lang/qt/src/qgpgmerefreshkeysjob.cpp: Change name to
* lang/qt/src/qgpgmerefreshsmimekeysjob.h,
lang/qt/src/qgpgmerefreshsmimekeysjob.cpp: ... this, and adapt the
include guard.
(class QGpgMERefreshKeysJob): Rename to QGpgMERefreshSMIMEKeysJob.
* lang/qt/src/Makefile.am: Adapt mentioned file names accordingly.
* lang/qt/src/protocol_p.h (Protocol::refreshKeysJob): Use renamed
class.
--

To avoid confusion with a similar job for OpenPGP keys with a completely
different implementation, we rename this class to make clear that it is
specific for S/MIME keys.

GnuPG-bug-id: 5951
2022-04-29 10:39:38 +02:00
Ingo Klöcker
359906c8bc cpp,tests: Verify that requested keylist mode is used
* lang/cpp/tests/run-getkey.cpp, lang/cpp/tests/run-keylist.cpp (main):
Check used keylist mode.
--

Since Context::setKeyListMode() does not return the error returned by
gpgme, we need to verify explicitly that the keylist mode was set
successfully.

GnuPG-bug-id: 5951
2022-04-28 10:33:23 +02:00
Ingo Klöcker
dea872f21f cpp: Support new keylist modes
* lang/cpp/src/global.h (ForceExtern, LocateExternal, KeyListModeMask):
New.
* lang/cpp/src/context.cpp (operator<<): Add check.
* lang/cpp/src/util.h (gpgme_keylist_mode_t,
convert_from_gpgme_keylist_mode_t): Handle ForceExtern.
* lang/cpp/tests/run-getkey.cpp (show_usage, main): Add arguments
--force-extern and --locate-external.
* lang/cpp/tests/run-keylist.cpp (show_usage, main): Ditto.
--

GnuPG-bug-id: 5951
2022-04-27 17:21:04 +02:00
Ingo Klöcker
aff9aaac68 core: Support --locate-external-keys command of gpg
* src/gpgme.h.in (GPGME_KEYLIST_MODE_FORCE_EXTERN): New.
(GPGME_KEYLIST_MODE_LOCATE_EXTERNAL): New.
* src/gpgme.c (gpgme_set_keylist_mode): Check for invalid mode.
* src/engine-gpg.c (gpg_keylist_build_options): Use
"--locate-external-keys" instead of "--locate-keys" if flag is set.
* src/gpgme-json.c (op_keylist): New flag "force-extern".
* src/gpgme-tool.c (gt_get_keylist_mode, cmd_keylist_mode): Handle
new mode.
--

GnuPG-bug-id: 5951
2022-04-27 16:57:17 +02:00
Ingo Klöcker
512f11b458 qt: Rely on the bad passphrase error reported by gpg
* lang/qt/src/qgpgmedecryptverifyjob.cpp (patch_decryption_result):
Removed.
(decrypt_verify): Remove usage of patch_decryption_result.
--

This reverts most of revision d8e5871dca.

GnuPG-bug-id: 5939
2022-04-25 12:18:17 +02:00
Ingo Klöcker
e21c3b559d core: Return BAD_PASSPHRASE error code on symmetric decryption.
* src/decrypt.c (op_data_t): Add field symdecrypt_failed.
(parse_status_error): Handle BAD_PASSPHRASE error code.
(_gpgme_decrypt_status_handler): Consult new field.
--

Return a bad passphrase error if the failure during symmetric decryption
is likely caused by the user entering a wrong passphrase. The special
error code of a failed public key decryption takes precedence.

GnuPG-bug-id: 5939
2022-04-25 12:14:42 +02:00
Ingo Klöcker
d8e5871dca qt: Report better error if decryption failed because of bad passphrase
* lang/qt/src/qgpgmedecryptverifyjob.cpp (patch_decryption_result): New.
(decrypt_verify): Call patch_decryption_result.
--

Replace the generic "decryption failed" error with the more specific
"bad passphrase" error if the audit log indicates that a wrong symmetric
password caused the decryption to fail.

GnuPG-bug-id: 5939
2022-04-22 17:34:41 +02:00
Ingo Klöcker
321c8a0254 cpp: Allow changing the error of a result
* lang/cpp/src/result.h (class Result): Add member function setError.
--

This can be used to replace the error of a result with a more suitable
error.

GnuPG-bug-id: 5939
2022-04-22 17:30:59 +02:00
NIIBE Yutaka
b10791b055 doc: Remove explanation about AM_PATH_GPGME_PTH for GNU Pth.
--

The commit 3ddf4c3d40 in 2011 removed
the support.

Signed-off-by: NIIBE Yutaka <gniibe@fsij.org>
2022-04-08 09:19:19 +09:00
Ingo Klöcker
102024f7e6 qt,doc: Fix typo and grammar in API documentation
--
2022-04-05 10:17:39 +02:00
Ingo Klöcker
28cdbfdccb cpp: Handle canceling of an edit operation
* lang/cpp/src/editinteractor.cpp
(CallbackHelper::edit_interactor_callback_impl): Check for error _or_
canceled state.
--

Without this canceling an edit operation resulted in a "General error".

GnuPG-bug-id: 5904
2022-04-05 10:17:39 +02:00
Ingo Klöcker
db532eca8e cpp: Return actual error if revocation fails
* lang/cpp/src/editinteractor.cpp, lang/cpp/src/editinteractor.h
(EditInteractor::parseStatusError): New.
* lang/cpp/src/gpgrevokekeyeditinteractor.cpp
(GpgRevokeKeyEditInteractor::Private::nextState): Handle status
error.
--

With this change the interactor returns a proper error like "Bad
Passphrase" or "Empty Passphrase" instead of an unspecific "General
Error" if a status error occurred.

GnuPG-bug-id: 5904
2022-04-05 10:15:07 +02:00
Ingo Klöcker
c965b45bcd cpp: Add internal utility function for splitting strings
* lang/cpp/src/util.h (split): New.
--

This function splits a given string using the given delimiter into
several strings.

GnuPG-bug-id: 5904
2022-04-05 10:05:43 +02:00
Ingo Klöcker
4beb6f4199 cpp: Do not export symbols of the Private class
* lang/cpp/src/gpgrevokekeyeditinteractor.h (class
GpgRevokeKeyEditInteractor): Mark nested class Private as hidden.
--

GnuPG-bug-id: 5904
2022-04-05 10:05:43 +02:00
NIIBE Yutaka
a36d71a8e3 core: Don't use internal __assuan functions.
* configure.ac (nanosleep): Detect.
* src/assuan-support.c: Don't use __assuan_usleep.
(my_socketpair): Don't use __assuan_socketpair.

--

Signed-off-by: NIIBE Yutaka <gniibe@fsij.org>
2022-04-05 14:42:59 +09:00
NIIBE Yutaka
110a375401 core: Don't keep using deprecated ath_ API.
* src/posix-io.c: Don't include ath.h.
(_gpgme_io_read): Call read directly.
(_gpgme_io_write): Call write directly.
(_gpgme_io_waitpid): Call waitpid directly.
(_gpgme_io_select_select): Call select directly.
(_gpgme_io_recvmsg): Call recvmsg directly.
(_gpgme_io_sendmsg): Call sendmsg directly.
(_gpgme_io_connect): Call connect directly.
* src/assuan-support.c: Don't include ath.h.
(my_waitpid): Call waitpid directly.

--

Signed-off-by: NIIBE Yutaka <gniibe@fsij.org>
2022-04-05 14:25:00 +09:00
Ingo Klöcker
7f089165e3 qt: Check arguments passed to the revoke key job
* lang/qt/src/qgpgmerevokekeyjob.cpp (check_arguments): New.
(QGpgMERevokeKeyJob::start, QGpgMERevokeKeyJob::exec): Call
check_arguments.
* lang/qt/tests/t-revokekey.cpp (RevokeKeyJobTest): Add member functions
testErrorHandling_nullKey, testErrorHandling_invalidReason,
testErrorHandling_invalidDescription.
--

Check that the key is not a null key, that the reason has a valid
value, and that the description lines do not contain endline characters
and are not empty.

GnuPG-bug-id: 5904
2022-03-31 18:39:19 +02:00
Ingo Klöcker
3856ae8621 qt,tests: Verify reason code and description of revocation
* lang/qt/tests/t-revokekey.cpp (RevokeKeyJobTest::testRevokeKeyAsync,
RevokeKeyJobTest::testRevokeKeySync_noReasonDescription,
RevokeKeyJobTest::testRevokeKeySync_oneLineReasonDescription,
RevokeKeyJobTest::testRevokeKeySync_twoLinesReasonDescription): Call
verifyReason.
(class RevokeKeyJobTest): Add private member function verifyReason.
--

gpgme doesn't parse the information, so we run gpg manually to verify
the revocation reason and the description.

GnuPG-bug-id: 5904
2022-03-30 12:29:28 +02:00
Ingo Klöcker
41297520da qt: Add job to revoke own OpenPGP keys
* lang/qt/src/revokekeyjob.h, lang/qt/src/qgpgmerevokekeyjob.h,
lang/qt/src/qgpgmerevokekeyjob.cpp: New.
* lang/qt/src/protocol.h (class Protocol): Add pure virtual member
function revokeKeyJob.
* lang/qt/src/protocol_p.h (Protocol::revokeKeyJob): New.
* 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_revokekey_SOURCES): New.
* lang/qt/tests/t-revokekey.cpp: New.
--

The new job allows revoking own OpenPGP keys as with the "revkey"
edit-key command of gpg.

GnuPG-bug-id: 5904
2022-03-30 12:29:28 +02:00
Ingo Klöcker
d96e8a7a6b cpp: Add interactor to revoke a key
* lang/cpp/src/global.h (enum class RevocationReason): New.
* lang/cpp/src/gpgrevokekeyeditinteractor.cpp,
lang/cpp/src/gpgrevokekeyeditinteractor.h: New.
* lang/cpp/src/Makefile.am: Add new files.
--

GnuPG-bug-id: 5904
2022-03-30 12:05:26 +02:00
Ingo Klöcker
7317139ef9 doc: Update NEWS
--

GnuPG-bug-id: 5906
2022-03-29 15:14:12 +02:00
Ingo Klöcker
3b3b36a607 qt: Set default visibility of all symbols to hidden
* configure.ac: Add -fvisibility=hidden to GPGME_QT_CFLAGS if gcc
supports the flag.
--

With this change all defined symbols are hidden by default, so that they
are not exported anymore. All symbols that are part of the ABI and that
shall still be exported are already marked as having default visibility.

GnuPG-bug-id: 5906
2022-03-28 17:22:48 +02:00
Ingo Klöcker
fe588fef09 cpp: Set default visibility of all symbols to hidden
* configure.ac: Add -fvisibility=hidden to GPGME_CPP_CFLAGS if gcc
supports the flag.
* lang/cpp/src/Makefile.am (AM_CPPFLAGS): Add GPGME_CPP_CFLAGS.
* m4/ax_gcc_func_attribute.m4: New.
--

With this change all defined symbols are hidden by default, so that they
are not exported anymore. All symbols that are part of the ABI and that
shall still be exported are already marked as having default visibility.

The m4 macro was taken from the website mentioned in the License header
of the file.

GnuPG-bug-id: 5906
2022-03-28 17:22:48 +02:00
Ingo Klöcker
92139e7b6b cpp: Put local helper function into unnamed namespace
lang/cpp/src/context.cpp (to_auditlog_flags): Wrap in unnamed namespace.
--

GnuPG-bug-id: 5906
2022-03-28 17:22:48 +02:00
Ingo Klöcker
ff3c93881a doc: Remove bogus documentation
--

These lines were accidentally added with the documentation for
gpgme_op_setexpire. The actual documentation for gpgme_op_revuid_start
is a bit further down.
2022-03-28 17:22:48 +02:00
NIIBE Yutaka
b2a2158384 core: Support keylist mode for op_keylist_from_data.
* src/engine-backend.h (keylist_data): Add MODE argument.
* src/engine-gpg.c (gpg_keylist_data): Add MODE argument.
* src/engine.c (_gpgme_engine_op_keylist_data): Likewise.
* src/engine.h (_gpgme_engine_op_keylist_data): Declaration.
* src/keylist.c (gpgme_op_keylist_from_data_start): Call
_gpgme_engine_op_keylist_data with ctx->keylist_mode.

--

GnuPG-bug-id: 5438
Signed-off-by: NIIBE Yutaka <gniibe@fsij.org>
2022-03-16 16:19:50 +09:00
Ingo Klöcker
55861ba9cc qt: Add missing include of config.h
* lang/qt/src/util.cpp: Include config.h.
--

GnuPG-bug-id: 5871
2022-03-07 09:28:09 +01:00
Ingo Klöcker
5a5a748e23 qt,doc: Remove comments about throwing exceptions
--

The jobs do not throw GpgME::Exception anymore since a long time.
2022-03-07 09:28:09 +01:00
Ingo Klöcker
71d4c9f452 doc: Update NEWS
--

Add a few more changes in version 1.17.0.
2022-03-07 09:28:09 +01:00
Werner Koch
f61a14f189
Post release updates 2022-03-06 18:02:42 +01:00
Werner Koch
ee50a38823
Release 1.17.1
* configure.ac: Bump QT LT version to C15/A0/R0.
2022-03-06 17:48:47 +01:00
Ingo Klöcker
ad3aabdd8a qt: Fix ABI compatibility with 1.16.0
* lang/qt/src/protocol.h (class Protocol): Move new virtual methods to
the end of the class.
--

This makes the vtable offsets of the old virtual methods match those
in 1.16.0 again.

GnuPG-bug-id: 5834
2022-02-17 09:54:45 +01:00
Werner Koch
fb5369161f
Post release updates
--
2022-02-07 18:09:06 +01:00
Werner Koch
72bb46b34f
Release 1.17.0 2022-02-07 15:02:49 +01:00
Werner Koch
451a42f0d2
qt: Fix build for older Qt versions.
* lang/qt/src/util.cpp: Include <functional>.
2022-02-07 13:10:13 +01:00
Ingo Klöcker
ca1c30b6fa qt: Add job to import keys given by key ids
* 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.
--

This job allows importing keys that are given by their key ids (or
fingerprints) from keyservers as with gpg's recv-keys command.

GnuPG-bug-id: 5808
2022-02-03 15:56:30 +01:00
Ingo Klöcker
ec8d1ee13f qt: Add helper for converting QStringList to vector of strings
* lang/qt/src/util.h, lang/qt/src/util.cpp: New.
* lang/qt/src/Makefile.am (qgpgme_sources, private_qgpgme_headers):
Add new files.
--

Additionally to the internal helper function toStrings(), this adds
a copy of the internal make_error helper of GpgME++ which is used
in a few places by QGpgME. We use the same error source id as GpgME++.

GnuPG-bug-id: 5808
2022-02-03 15:56:30 +01:00
Ingo Klöcker
bbaeeb5b9d cpp: Allow import of keys given by key ids
* 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.
--

GnuPG-bug-id: 5808
2022-02-03 15:56:30 +01:00
Ingo Klöcker
3d7810e8d9 cpp: Add internal adapter for passing a vector of strings to gpgme
* lang/cpp/src/util.h (class StringsToCStrings): New.
* lang/cpp/src/util.cpp: New.
* lang/cpp/src/Makefile.am: Add new file.
--

This adapter simplifies passing a vector of strings as NULL-terminated
array of const char* to the C-interface of gpgme.

GnuPG-bug-id: 5808
2022-02-03 15:56:30 +01:00
Ingo Klöcker
3c2cff74b5 core: New function gpgme_op_receive_keys
* 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.
--

The new function allows importing keys given by their key ids or
fingerprints from a keyserver (like gpg's --recv-keys command).

GnuPG-bug-id: 5808
2022-02-03 15:56:30 +01:00
Werner Koch
5bb4174efa
doc: Fixed type of an object member
--

GnuPG-bug-id: 5719
2022-01-20 20:36:03 +01:00
Ingo Klöcker
ec71eb1d7d qt: Remove superfluous include
* lang/qt/src/importjob.h: Remove include of QByteArray.
--

QByteArray is included by other headers already. Besides: Qt headers
shouldn't be included with the package/module prefixes.
2022-01-17 14:44:57 +01:00
Ingo Klöcker
9c03bde06b qt: Fix build without installed GpgME++ headers
* 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-17 14:41:17 +01:00
Ingo Klöcker
e16729edcb tests: Fix generation of keys without expiration
* 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.
--

This makes the parsing of different values for expiration match the
parsing done by gpg's --quick-gen-key. In particular, this makes it
possible again to generate keys without expiration.
2022-01-13 16:30:56 +01:00
Ingo Klöcker
e4625885a8 tests: Remove unsupported option --status from usage help
* tests/run-swdb.c (show_usage): Remove option --status.
--

run-swdb does not support the option --status.
2022-01-13 15:23:43 +01:00
Ingo Klöcker
4d913a8aa5 qt: Add job to add existing subkeys to other keys
* 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.
--

The new job allows adding existing subkeys to other keys as with the
"addkey" edit-key command of gpg. The added subkey will have the same
expiration date (+/- 1 second) as the original subkey.

GnuPG-bug-id: 5770
2022-01-13 15:18:12 +01:00
Ingo Klöcker
d308910cdf qt,tests: Add helper to hook up the test passphrase provider
* 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.
--

GnuPG-bug-id: 5770
2022-01-13 12:40:35 +01:00
Ingo Klöcker
a54402fc2d qt,tests: Add asyncDone signal to base class of all tests
* 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.
--

This reduces duplication and makes it possible to use the signal in
the base class.

GnuPG-bug-id: 5770
2022-01-13 11:36:35 +01:00
Ingo Klöcker
a4dcb17486 cpp: Add interactor to add existing subkeys to other keys
* lang/cpp/src/gpgaddexistingsubkeyeditinteractor.cpp,
lang/cpp/src/gpgaddexistingsubkeyeditinteractor.h: New.
* lang/cpp/src/Makefile.am: Add new files.
--

GnuPG-bug-id: 5770
2022-01-12 16:38:58 +01:00
Ingo Klöcker
a527bd7cf5 core: Return an error for secret key export operations
src/export.c (export_status_handler): Handle "export_keys.secret".
--

This allows callers of the synchronous export operations to react
properly to errors (e.g. wrong passphrase) during the export of secret
keys.

GnuPG-bug-id: 5766
2022-01-10 12:34:49 +01:00
Ingo Klöcker
062e4b1f0f doc: Update NEWS
--

GnuPG-bug-id: 5757
2022-01-04 16:08:35 +01:00
Ingo Klöcker
04723a6e96 qt: Add factory function for secret subkey export job
* 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.
--

GnuPG-bug-id: 5757
2022-01-04 15:56:34 +01:00
Ingo Klöcker
e5c7fc3e02 cpp: Allow export of secret subkeys
* 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.
--

GnuPG-bug-id: 5757
2022-01-04 15:50:59 +01:00
Ingo Klöcker
88ad37ea96 qt: Remove obsolete QGpgMESecretKeyExportJob
* lang/qt/src/Makefile.am: Remove all occurrences of
qgpgmesecretkeyexportjob.*.
* lang/qt/src/qgpgmesecretkeyexportjob.cpp,
lang/qt/src/qgpgmesecretkeyexportjob.h: Remove.
--

QGpgMESecretKeyExportJob is an internal class, so that we can safely
remove it.

GnuPG-bug-id: 5757
2022-01-04 15:45:59 +01:00
Ingo Klöcker
4e80563fab qt: Use QGpgMEExportJob also for export of secret keys
* 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.
--

This change makes it possible to export secret OpenPGP keys.

GnuPG-bug-id: 5757
2022-01-04 15:44:16 +01:00
Ingo Klöcker
3da06d1096 cpp: Allow export of secret keys
* 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.
--

This adds export functions for secret key exports and generic export
functions that can be used for any key export supported by
gpgme_op_export[_ext][_start].

GnuPG-bug-id: 5757
2022-01-04 15:44:16 +01:00
Ingo Klöcker
4888191014 cpp: Mark ExportNoUID flag as obsolete
* lang/cpp/src/context.h (enum Context::ExportMode): Mark value
ExportNoUID as obsolete
--

GnuPG-bug-id: 5757
2022-01-04 14:55:30 +01:00
Ingo Klöcker
2752e81f89 core: Add new option --secret-subkey to help texts.
* src/gpgme-tool.c (hlp_export): Add new option.
* tests/run-export.c (show_usage): Print new option.
--

GnuPG-bug-id: 5757
2022-01-04 12:30:22 +01:00
Ingo Klöcker
fa5f1b57cc cpp: Remove obsolete workaround
* lang/cpp/src/context.cpp (Context::startKeyListing,
Context::exportPublicKeys, Context::startPublicKeyExport): Remove
workaround.
--

gpgme_op_keylist_ext[_start] supports GPGME_KEYLIST_MODE_EXTERN
since a long time. And the export doesn't use a keylisting (anymore),
so that the keylisting mode is irrelevant for the export.

GnuPG-bug-id: 5757
2022-01-04 09:56:46 +01:00
Ingo Klöcker
0e19c48791 core: New export mode to export secret subkeys.
* 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.
--

This adds support for exporting secret subkeys (via gpg's
--export-secret-subkeys) to gpgme_op_export[_ext][_start].
The flag is not supported by gpgme_op_export_keys[_start] because
there is no way to specify which subkey(s) to export with these
functions.

GnuPG-bug-id: 5757
2022-01-04 09:23:40 +01:00
Ingo Klöcker
414bbdd53c doc: Remove documentation of obsolete export mode flag
* doc/gpgme.texi: Remove GPGME_EXPORT_MODE_NOUID.
--

Support for this experimental flag has been removed with revision
c8fd8870b3.

GnuPG-bug-id: 5757
2022-01-04 09:23:27 +01:00
Ingo Klöcker
c710af223c core: Check for unsupported export mode flags
src/engine-gpgsm.c (gpgsm_export, gpgsm_export_ext): Return error if an
unsupported mode flag is set.
--

The minimal mode flag has no effect for X.509 certificates, but we still
treat it as supported (as documented in the API documentation).

GnuPG-bug-id: 5757
2022-01-04 09:22:46 +01:00
Ingo Klöcker
c0581adabe core: Check for combination of ssh mode with other mode flags
* src/export.c (check_mode): Return error if ssh mode is combined with
another mode flag.
--

The SSH mode flag cannot be used in combination with other flags.

GnuPG-bug-id: 5757
2022-01-04 09:22:25 +01:00
Ingo Klöcker
3268575115 core: Factor out the check for valid export mode flags.
* src/export.c (check_mode): New.
(export_start, export_ext_start): Call check_mode.
--

GnuPG-bug-id: 5757
2022-01-04 09:21:37 +01:00
Ingo Klöcker
82f43455e9 qt: Detect an import error caused by a wrong password
* lang/qt/src/qgpgmeimportjob.cpp (import_qba): Check import statuses of
import result for bad passphrase errors.
--

To allow users of the import job to handle a failed import caused by
a wrong password more gracefully, check if all import statuses of the
import result have a bad passphrase error and return a bad passphrase
error as import result in this case.

GnuPG-bug-id: 5713
2021-12-22 15:25:42 +01:00
Ingo Klöcker
f99451e20f qt,tests: Add test runner for testing the import job
* lang/qt/tests/Makefile.am (run_importjob_SOURCES): New.
(noinst_PROGRAMS): Add run-importjob.
* lang/qt/tests/run-importjob.cpp: New.
--

GnuPG-bug-id: 5713
2021-12-22 15:25:42 +01:00
Ingo Klöcker
300776f391 cpp: Check fpr of import status for NULL
* lang/cpp/src/importresult.cpp (GpgME::ImportResult::Private): Check
fpr for NULL.
--

GnuPG-bug-id: 5713
2021-12-22 15:25:42 +01:00
Ingo Klöcker
305d8668ca core: Detect bad passphrase error on certificate import
* 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.
--

When importing an encrypted certificate a wrong passphrase may be
entered. In this case gpgsm emits a status line with a bad passphrase
error and an "invalid object" error. To make it possible for callers
to handle a wrong passphrase error more gracefully, an import status
with bad passphrase error is added to the import result for each
status line with bad passphrase error.

GnuPG-bug-id: 5713
2021-12-22 15:25:42 +01:00
NIIBE Yutaka
0636e229d7 build: Update for newer autoconf.
* configure.ac (AC_PREREQ): Require >= 2.69.
(AC_CONFIG_HEADERS): Use it instead of AC_CONFIG_HEADER.

--

Signed-off-by: NIIBE Yutaka <gniibe@fsij.org>
2021-12-22 09:27:06 +09:00
Ingo Klöcker
619579bb17 qt: Allow specifying an import filter when importing keys
* 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.
--

GnuPG-bug-id: 5739
2021-12-15 15:00:07 +01:00
Ingo Klöcker
3e81a4a336 qt: Avoid test failure when test is run multiple times
* lang/qt/tests/t-import.cpp (ImportTest): Add member tempGpgHome and
member function initTestCase.
(keyFpr, keyData): Move to ImportTest::testImportWithKeyOrigin.
--

Use different temporary GNUPGHOME's when running the test. This ensures
that the import in the test is always done with a new keyring.

GnuPG-bug-id: 5733
2021-12-15 12:21:28 +01:00
Ingo Klöcker
3c770013d7 qt: Fix erroneous reuse of JobPrivate objects
* lang/qt/src/job.cpp (Job::~Job): Destroy JobPrivate object belonging
to destroyed job.
--

In some tests different Job objects reused the same JobPrivate object
because they were created with the same memory address. Obviously, this
shouldn't happen.

GnuPG-bug-id: 5739
2021-12-15 12:00:51 +01:00
Ingo Klöcker
d35d44efaf core: Allow setting import filters when importing keys
* 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.
--

This makes the --import-filter option available in the GPGME API for
key imports.

GnuPG-bug-id: 5739
2021-12-14 15:44:37 +01:00
Ingo Klöcker
af820811ec qt: Add pattern used for WKD lookup to result
* 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.
--

GnuPG-bug-id: 5728
2021-12-14 14:49:39 +01:00
Ingo Klöcker
fd680254da core: Set --key-origin option only if supported by gpg
* src/engine-gpg.c (gpg_import): Do not pass --key-origin option to
gpg if gpg is too old.
--

GnuPG-bug-id: 5733
2021-12-14 14:41:23 +01:00
Ingo Klöcker
fd6bec617d qt: Allow setting key origin when importing keys
* 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.
--

GnuPG-bug-id: 5733
2021-12-14 11:47:09 +01:00
Ingo Klöcker
3a43d9dc67 qt,tests: Skip WKD lookup tests by default
* 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.
--

GnuPG-bug-id: 5728
2021-12-14 11:04:03 +01:00
Ingo Klöcker
60880adafa core: Allow specifiying a key origin when importing keys
* 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.
--

This makes the --key-origin option available in the GPGME API for
key imports.

GnuPG-bug-id: 5733
2021-12-13 16:52:23 +01:00
Ingo Klöcker
c89226d47f doc: Fix a few errors in the documentation of gpgme_op_import_*
--
2021-12-13 16:07:54 +01:00
Ingo Klöcker
ed7e7df2e1 qt: Support WKD lookup without implicit import
* 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.
--

The new WKDLookupJob allows running a WKD lookup without implicit
import of the retrieved key. This makes it possible to do WKD lookups
similar to keyserver lookups (aka external keylistings).

The new final.test pseudo test stops a dirmngr that may have been
started by the tests. The toString() template specialization enables
printing of the actual and expected values in case of failed QCOMPARE.

GnuPG-bug-id: 5728
2021-12-13 10:48:52 +01:00
Ingo Klöcker
0e70a2313a qt: Fix example for using the asynchronous job API
* lang/qt/src/protocol.h (class Protocol): Fix API documentation.
--
2021-12-13 09:24:30 +01:00
Ingo Klöcker
f3177d3ee0 cpp,tests: Add test runner for doing a WKD lookup without import
* lang/cpp/tests/Makefile.am (run_wkdlookup_SOURCES, programs_unix):
New.
(noinst_PROGRAMS): Add $(programs_unix).
* lang/cpp/tests/run-wkdlookup.cpp: New.
--

This test runner is a prototype for doing a WKD lookup without implicit
import of the found key(s).

Building this test runner is disabled on Windows because it may not
work there. Feel free to enable it on Windows if the test runner works
there.

GnuPG-bug-id: 5728
2021-12-10 12:51:36 +01:00
Ingo Klöcker
5f1ba40116 cpp: Add new supported components to API docs of dirInfo()
lang/cpp/src/global.h: Update API doc of dirInfo().
--

GnuPG-bug-id: 5727
2021-12-10 12:10:13 +01:00
Ingo Klöcker
0ac3679a74 core: Support all components with dirinfo()
* 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.
--

GnuPG-bug-id: 5727
2021-12-10 12:04:05 +01:00
Ingo Klöcker
0eddc867c3 cpp: Return engine info for engine used by the context
lang/cpp/src/context.cpp (Context::engineInfo()): Return engine info
for protocol of context.
--

This change also fixes Context::setEngineFileName() and
Context::setEngineHomeDirectory() which overwrote home dir resp.
file name of the engine info for the protocol of context with the
corresponding value of the "first" engine info (i.e. engine info for
gpg) instead of keeping the current home dir resp. file name.

GnuPG-bug-id: 5722
2021-12-07 11:14:32 +01:00
Ingo Klöcker
1a1e914587 cpp: Factor out common code of GpgME::engineInfo() overloads
* 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().
--

GnuPG-bug-id: 5722
2021-12-07 11:14:32 +01:00
Werner Koch
b8b49c11e9
core: Make the gpgconf option parsing of string types more robust
* src/engine-gpgconf.c (gpgconf_parse_option): Skip the string
indicator if it is not the empty string.
--

Some versions of GnuPG (~2.2.28 to 2.2.33) returned a compliance
indicator which should be an int but actually used string as type.
Simply skipping the indicator without checking that this is the
indicator does not allow to work around this type mismatch by the
gpgme users.
2021-11-25 11:48:11 +01:00
Werner Koch
43de18a292
tests: Silence libtool warning on Windows.
* tests/Makefile.am (AM_LDFLAGS): Use --no-fast-install on Windows.
2021-11-25 11:43:33 +01:00
Werner Koch
eb37d6469e
core: Support dirinfo("socketdir")
* 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.
--

GnuPG-bug-id: 5613

This is not strictly necessary because we could deduce this from one
of the other socket info items but it is more clean to have a
dedicated info item.  The socketdir item is available for 5 years now
(GnuPG commit 8e3fa5a4b205c534de2142e5d071712f957cf06a)
2021-11-25 11:40:59 +01:00
NIIBE Yutaka
8148237cb4 posix: Use poll instead, when available, removing use of select.
* 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.

--

GnuPG-bug-id: 2385
Signed-off-by: NIIBE Yutaka <gniibe@fsij.org>
2021-11-25 11:13:17 +09:00
NIIBE Yutaka
4583ab77e5 gpgme.pc: Fix library dependency and use of includedir, libdir.
* src/gpgme.pc.in (Require): Move gpg-error, libassuan to...
(Requires.private): ... here.
(Cflags): Add -I${includedir}.
(Libs): Add -L${libdir}.

--

This will result better library dependency for applications using
gpgme.  It will break build of an application which directly uses
gpg-error or libassuan without specifying them (which means, depending
on redundant/wrong gpgme.pc).

Signed-off-by: NIIBE Yutaka <gniibe@fsij.org>
2021-11-12 11:05:53 +09:00
NIIBE Yutaka
1cedac2bba tests: Build using GPG_ERROR_MT_LIBS for thread use.
* 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.

--

For library dependency at runtime, it's not 100% right to use
GPG_ERROR_MT_LIBS here, because those test programs don't use
libgpg-error directly at runtime.  But, it's OK, because these are
test programs, which don't need specifying minimum library dependency.

It would be too much for configure of gpgme, to check how threaded
application should be built, just for these test programs.

Co-authored-by: Ben Kibbey <bjk@luxsci.net>
Signed-off-by: NIIBE Yutaka <gniibe@fsij.org>
2021-11-12 10:22:21 +09:00
NIIBE Yutaka
8cd2fe7b3d tests: Use GPG_ERROR_MT_LIBS for a test with threads.
* tests/Makefile.am (run_threaded_CPPFLAGS): New.
(run_threaded_LDADD): Replace GPG_ERROR_LIBS to GPG_ERROR_MT_LIBS.

--

Reported-by: Ben Kibbey <bjk@luxsci.net>
Fixes-commit: d0402f886b
Signed-off-by: NIIBE Yutaka <gniibe@fsij.org>
2021-11-11 10:08:59 +09:00
NIIBE Yutaka
50daf3d75d libtool: Link without -flat_namespace for macOS.
* 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.

--

Original patch was by: Jeremy Huddleston Sequoia <jeremyhu@apple.com>
in

    https://lists.gnu.org/archive/html/libtool-patches/
    2020-06/msg00001.html

Reported-by: Aleix Conchillo Flaque
GnuPG-bug-id: 5610
Signed-off-by: NIIBE Yutaka <gniibe@fsij.org>
2021-11-10 11:06:34 +09:00
Ingo Klöcker
ab9bca09eb qt: Fix build against Qt 5.9
* 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.
--

Qt 5.9 does not yet have the generic qCompare helper which supports
arguments of any type that can be compared with ==.

GnuPG-bug-id: 5592
2021-09-13 17:30:49 +02:00
Werner Koch
aaf448b1e8
build: Fix make distcheck problem.
* tests/start-stop-agent: Use -f with rm.  Also use cat instead of cp.
--

Also shorted some lines.
2021-08-27 14:13:36 +02:00
Andre Heinecke
8fe1546282
qt: Expect UTF-8 on stderr on Windows
* lang/qt/src/threadedjobmixin.cpp (stringFromGpgOutput): Expect
UTF-8.

--
In recent versions more and more output was changed to be
UTF-8 on Windows. Werner advised to always expect UTF-8
diagnostics.
2021-08-27 13:01:17 +02:00
Andre Heinecke
bc774104bb
Add missing files for distribution
* lang/qt/src/Makefile.am (private_qgpgme_headers): Add job_p.h
* tests/gpg/Makefile.am (EXTRA_DIST): Add gpg.conf.in
2021-08-27 12:58:27 +02:00
NIIBE Yutaka
3c1c98a434 core: Use flexible array member if compiler has support.
* 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.

--

Before this fix, GCC 11 warns (with its bound checking feature).

Signed-off-by: NIIBE Yutaka <gniibe@fsij.org>
2021-08-13 14:52:03 +09:00
Ingo Klöcker
7cfc93193d core: Fix results returned by gpgme_data_* functions
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.
--

This change adds tracing macros for results of system functions of
type __off_t and __ssize_t.

GnuPG-bug-id: 5481
2021-08-03 12:13:27 +02:00
Jiri Kucera
4b64774b6d
core: Support closefrom also for glibc.
* src/posix-io.c (_gpgme_io_spawn): Use glibc's closefrom.
--

Since 2.34, glibc introduces closefrom (the implementation
follows *BSD standard).

Signed-off-by: Werner Koch <wk@gnupg.org>
2021-07-27 10:52:13 +02:00
Ingo Klöcker
a5662a801f core: Ensure gpg.conf for tests is recreated if necessary
* tests/gpg/gpg.conf.in: New.
* tests/gpg/Makefile.am (gpg.conf): Copy gpg.conf.in instead of using
echo to fill gpg.conf.
--

This change ensures that gpg.conf is updated whenever new options are
added for some tests.
2021-07-08 12:18:45 +02:00
Ingo Klöcker
6a79e90ded Make sure expiration time is interpreted as unsigned number
* lang/qt/tests/t-various.cpp (testSignKeyWithExpiration): Convert
expiration time to uint_least32_t.
--

This fixes the test on 32-bit systems where time_t (the return type of
expirationTime()) is a signed 32-bit integer type.

GnuPG-bug-id: 5522
2021-07-08 11:54:06 +02:00
Ingo Klöcker
12006a7829 qt: Allow retrieving the default value of a config entry
* 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.
--

GnuPG-bug-id: 5515
2021-06-29 12:12:33 +02:00
Ingo Klöcker
d8638ed0aa Update NEWS.
* NEWS: Add changes of ChangeExpiryJob.
--

GnuPG-bug-id: 4717
2021-06-28 12:13:27 +02:00
Ingo Klöcker
9d2b876093 qt: Fix filenames in copyright headers
* lang/qt/src/qgpgmechangeownertrustjob.h,
lang/qt/tests/t-trustsignatures.cpp: Use correct filenames.
2021-06-28 11:56:12 +02:00
Ingo Klöcker
801acd89b2 qt: Add test for ChangeExpiryJob
* lang/qt/tests/Makefile.am (TESTS, moc_files, noinst_PROGRAMS): Add
new test.
(t_changeexpiryjob_SOURCES): New.
* lang/qt/tests/t-changeexpiryjob.cpp: New.
--

GnuPG-bug-id: 4717
2021-06-28 11:56:12 +02:00
Ingo Klöcker
144d580607 qt: Allow changing expiration date of primary key and all subkeys
* 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.
--

Additionally, to the default behavior (update expiration of primary
key if no subkeys are specified resp. update expiration of specified
subkeys) it is now possible to update the expiration of the primary key
_and_ the specified/all subkeys.

GnuPG-bug-id: 4717
2021-06-28 11:56:12 +02:00
Ingo Klöcker
3503816570 qt: Add mechanism for missing d-pointer in Job
* lang/qt/src/job_p.h: New.
* lang/qt/src/job.cpp (typedef JobPrivateHash, d_func, setJobPrivate,
getJobPrivate): New.
--

Because of ABI compatibility requirements we cannot add a d-pointer
to Job. Therefore we store the d-pointers in a global static. This
mechanism will allow Job subclasses to store additional data without
breaking the ABI.

GnuPG-bug-id: 4717
2021-06-28 11:56:12 +02:00
Ingo Klöcker
ade95b25ce qt: Remove superfluous trailing ';'
lang/qt/src/signkeyjob.h (class SignKeyJob): Remove trailing ';' from
inline implemented member functions
2021-06-26 18:03:37 +02:00
Ingo Klöcker
81a33ea5e1 core: Fix use-after-free issue in test
* tests/gpg/t-edit-sign.c (sign_key, verify_key_signature): New.
(main): Factored out signing and verifying the result.
--

Factoring the two steps of the test into different functions fixes the
use-after-free issue that was caused by accidentaly using a variable
of the first step in the second step.

GnuPG-bug-id: 5509
2021-06-26 18:03:37 +02:00
Werner Koch
e8e055e682
Post release updates
--
2021-06-24 19:36:47 +02:00
Werner Koch
1021c86455
Release 1.16.0 2021-06-24 19:03:35 +02:00
Werner Koch
768b7892e3
python: Do not include the full file names in the docs.
--

GnuPG-bug-id: 5299
2021-06-24 18:13:00 +02:00
Jasper Spaans
14b148b7d3
python: Allow returning signatures made by unknown keys in decrypt
--
This functionality got dropped somewhere after 1.12, as part of the
cleanup of the `Context.decrypt` call signature. Reintroduce it again,
now using an explicit keyword argument `filter_signatures` (which
defaults to hiding signatures by unknown keys).

GnuPG-bug-id: 5292
2021-06-24 18:09:55 +02:00
Ingo Klöcker
ac4536990a qt: Extend SignKeyJob to create signatures with expiration date
* lang/qt/src/signkeyjob.h (SignKeyJob::setExpirationDate): New.
* lang/qt/src/qgpgmesignkeyjob.h, lang/qt/src/qgpgmesignkeyjob.cpp
(QGpgMESignKeyJob::setExpirationDate): New.
* lang/qt/src/qgpgmesignkeyjob.cpp (QGpgMESignKeyJob::Private): Add
member m_expiration.
(sign_key): Handle expiration date.
(QGpgMESignKeyJob::start): Pass expiration date to sign_key.

* lang/qt/tests/t-various.cpp
(TestVarious::testSignKeyWithoutExpiration,
TestVarious::testSignKeyWithExpiration): New.
(TestVarious::initTestCase): Add "allow-weak-key-signatures" to
gpg.conf.
--

This allows Kleopatra (and other users of QGpgme) to create key
signatures with expiration date.

GnuPG-bug-id: 5336, 5506
2021-06-22 18:49:45 +02:00
Ingo Klöcker
34d9defc42 core: Allow specifying an expiration date for key signatures
* src/context.h (struct gpgme_context): Add 'cert_expire'.
* src/engine-gpg.c (append_args_from_cert_expire): New.
(gpg_edit): Set option according to the new flag.
* src/gpgme.c (gpgme_release): Free 'cert_expire'.
(gpgme_set_ctx_flag, gpgme_get_ctx_flag): Add "cert-expire".

* tests/gpg/Makefile.am (c_tests): Add new test.
(gpg.conf): Write "allow-weak-key-signatures" to gpg.conf.
* tests/gpg/t-edit-sign.c: New.
--

The new context flag "cert-expire" allows setting the expiration date
for key signatures created with gpgme_op_interact.

GnuPG-bug-id: 5336, 5505
2021-06-22 16:35:03 +02:00
Ingo Klöcker
ab1d4ef580 Update NEWS.
* NEWS: Add news for recent changes
--

GnuPG-bug-id: 5421, 5217
2021-06-21 10:48:06 +02:00
Ingo Klöcker
5340bb7ccf qt: Add missing }
* lang/qt/src/qgpgmenewcryptoconfig.cpp (parseURL): Add missing }.
--

Fixes-commit: 1dca8c2b3c
GnuPG-bug-id: 5465
2021-06-18 12:33:06 +02:00
Ingo Klöcker
72de06417e qt: Add some error logging
* lang/qt/src/qgpgmenewcryptoconfig.cpp (setURLValueList): Log error
if setting config value failed.
--

GnuPG-bug-id: 5465
2021-06-17 09:41:22 +02:00
Ingo Klöcker
1dca8c2b3c qt: Do not set empty base DN as query of keyserver URL
* lang/qt/src/qgpgmenewcryptoconfig.cpp (parseURL): Only set non-empty
base DN as URL query.
--

This makes it possible to differentiate an unset query from an empty
query.

GnuPG-bug-id: 5465
2021-06-17 09:38:33 +02:00
Ingo Klöcker
0d03f31e07 qt: Fix API documentation
* lang/qt/src/signkeyjob.h (SignKeyJob::start,
SignKeyJob::setUserIDsToSign, SignKeyJob::setCheckLevel): Fix
documentation of parameters.
--

GnuPG-bug-id: 5245
2021-06-17 09:13:59 +02:00
Werner Koch
fde20940b5
core: New data flags "io-buffer-size" and "sensitive".
* src/data.c (_gpgme_data_release): Free buffers.
(gpgme_data_seek): Adjust from renamed fields.
(gpgme_data_set_flag): Implement new flags.
(_gpgme_data_inbound_handler): Allow the use of a malloced buffer.
(_gpgme_data_outbound_handler): Ditto.
* src/data.h (BUFFER_SIZE): Move out of the struct definition.
(struct gpgme_data): Remove pending filed and introduce inbound and
outbound fields.

* src/conversion.c (_gpgme_wipememory): New.  Taken from GnuPG.
* src/cJSON.c (wipememory): Use this here too.

* tests/run-decrypt.c (main): Add options "--large-buffers" and
"--sensitive".
--

GnuPG-bug-id: 5478
Signed-off-by: Werner Koch <wk@gnupg.org>
2021-06-14 19:51:28 +02:00
Werner Koch
ea290108e4
core: Also detect AuthEnvelopedData (AEAD for CMS)
* src/data-identify.c (basic_detection): Add OID.

Signed-off-by: Werner Koch <wk@gnupg.org>
2021-06-14 17:10:49 +02:00
Andre Heinecke
b3b75c37e2
qt: Flush output after write for QProcess output
* lang/qt/src/dataprovider.cpp (QIODeviceDataProvider::write): Call
waitForBytesWritten.

--
The problem here is that QProcess writes into an internal buffer
which is written to stdin of the process triggered by a
signal/slot connection. That connection is broken when we move
the QProcess into our GPGME thread and only restablished when
our Job is finished. This caused Kleopatra to basically keep
everything when decrypting a large archive in memory and
only write it out to the unpack process once the decryption
was finished.

GnuPG-Bug-Id: T5475
2021-06-10 15:36:26 +02:00
Andre Heinecke
ceb8387460
core,w32: Increase BUFFER_SIZE to 4096
* src/data.h (BUFFER_SIZE): Increase to 4096 for Windows.

--
This brings it in line to the PIPE_BUF size on desktop Linux
systems. This should increase performance when working with
large files on Windows a bit.

GnuPG-Bug-Id: T5478
2021-06-10 15:33:51 +02:00
Andre Heinecke
e6095e5471
qt: Explicitly link libgpg-error
* lang/qt/src/Makefile.am (libqgpgme_la_LIBADD): Explicitly link
gpg-error.

--
Previously this was implicit from the libassuan flags.
2021-06-09 10:53:28 +02:00
Andre Heinecke
4041e2c62a
core: Explicitly add GPG_ERROR_CFLAGS
* src/Makefile.am (AM_CFLAGS): Add GPG_ERROR_CFLAGS

--
This fixes the include directory for libgpg error if
it is installed in a different prefix then libassuan. Previously
libassuan provided the include directory also implicitly.
2021-06-09 10:47:05 +02:00
Ingo Klöcker
5bc4e23a57 qt: Add separate logging category for result of config loading
* lang/qt/src/qgpgme_debug.h: Make include guard match file name.
* lang/qt/src/qgpgme_debug.h, lang/qt/src/qgpgme_debug.cpp
(QGPGME_CONFIG_LOADING_LOG): New.
* lang/qt/src/qgpgmenewcryptoconfig.cpp
(QGpgMENewCryptoConfig::reloadConfiguration): Use new logging category.
--

Use a separate logging category for the extremely noisy logging of
the result of config loading to make debug logging more useful.

GnuPG-bug-id: 5217
2021-06-02 10:56:52 +02:00
Ingo Klöcker
5512133de4 core: Fix a few checks for number of fields in keylist result parser.
* src/keylist.c (keylist_colon_handler): Check for correct number of
fields.
--

This prevents NULL pointer dereferencing with older versions of gpg
that may output less fields.
2021-06-02 10:20:26 +02:00
Ingo Klöcker
27aa7c4a0f qt: Add support for flags in LDAP server options
* lang/qt/src/qgpgmenewcryptoconfig.cpp (parseURL): Handle extended
LDAP server option syntax.
(portToString): New.
(splitURL): Append flags to LDAP server option.
--

This adds support for the extended syntax of LDAP server options
introduced in gpg 2.2.18/2.3. The flags are stored as fragment of a
QUrl.

GnuPG-bug-id: 5217
2021-06-01 15:29:03 +02:00
Werner Koch
31eb45f016
tests: Improve the output of the run-keylist helper.
* tests/run-keylist.c (main): Print all infos from the primary key.
--

The test tool printed only the computed infos for the key and not the
detailed one fro the primary key.  The new output better reflects the
data structure.

Related to
GnuPG-bug-id: 5454
2021-05-28 18:31:43 +02:00
NIIBE Yutaka
367b9e7488 build: _DARWIN_C_SOURCE should be 1.
* configure.ac (*-apple-darwin*): Set _DARWIN_C_SOURCE 1.

--

GnuPG-bug-id: 5440
Reported-by: Jay Freeman
Signed-off-by: NIIBE Yutaka <gniibe@fsij.org>
2021-05-27 13:36:29 +09:00
NIIBE Yutaka
792a7e7f04 build: Update gpg-error.m4
* m4/gpg-error.m4: Update from libgpg-error.

--

Signed-off-by: NIIBE Yutaka <gniibe@fsij.org>
2021-05-27 13:35:38 +09:00
Werner Koch
aa98081356
core: Allow for older compilers.
* tests/run-verify.c (main): Remove C99-only syntax.
* tests/run-threaded.c (start_keylistings): Ditto.
--

Older gcc's do not grok this and there is no real need for it.

  run-verify.c:324: error: ‘for’ loop initial declarations are only
  allowed in C99 mode
  run-verify.c:324: note: use option -std=c99 or -std=gnu99 to compile
  your code

Reported-by: Lars Hecking
2021-05-12 08:50:04 +02:00
Werner Koch
88db69e1a9
core: Make sure to stay ABI compatible.
* src/gpgme.h.in (struct _gpgme_key_sig): Move trust_scope to the end
of the struct.
--

Fixes-commit: 276187f6b6

Note that we assume that splitting a reserved 28 bit field into 3
fields does not change the ABI.
2021-05-12 08:48:26 +02:00
Ingo Klöcker
58a217b108 cpp: Do not close stdout/stderr when destroying EditInteractor
* lang/cpp/src/editinteractor.cpp (EditInteractor::Private): Initialize
members 'state' and 'debug' in-class. Add member 'debugNeedsClosing'.
(EditInteractor::Private::Private): Remove members initializers.
Remember if 'debug' needs to be closed.
(EditInteractor::Private::~Private): Only close 'debug' if it needs to
be closed.
--

This fixes the problem that after destroying an edit interactor all
debug output went to /dev/null instead of stderr (or stdout) if one
enabled debugging of the edit interactors with GPGMEPP_INTERACTOR_DEBUG
set to stderr (or stdout).
2021-05-06 10:14:44 +02:00
Ingo Klöcker
f0858e45b0 qt: Extend SignKeyJob to create trust signatures
* lang/qt/src/signkeyjob.h (SignKeyJob::setTrustSignature): New.
* lang/qt/src/qgpgmesignkeyjob.h, lang/qt/src/qgpgmesignkeyjob.cpp
(QGpgMESignKeyJob::setTrustSignature): New.
* lang/qt/src/qgpgmesignkeyjob.cpp (sign_key): Handle trust signatures.
(QGpgMESignKeyJob::start): Pass trust signature attributes to sign_key.
(QGpgMESignKeyJob::setTrustSignature): New.
--

This allows Kleopatra to create trust signatures for trusted
introducers.

GnuPG-bug-id: 5245, 5421
2021-05-05 19:26:33 +02:00
Ingo Klöcker
dae01f8185 qt: Pimpl QGpgMESignKeyJob
* lang/qt/src/qgpgmesignkeyjob.h: Remove unneeded includes. Include
<memory>.
(QGpgMESignKeyJob): Remove all member variables. Add pimpl pointer.
* lang/qt/src/qgpgmesignkeyjob.cpp: Include <QString>. Don't include
<memory>.
(QGpgMESignKeyJob::Private): New.
(QGpgMESignKeyJob::QGpgMESignKeyJob): Remove initialization of removed
members. Initialize d.
(QGpgMESignKeyJob::start, QGpgMESignKeyJob::setUserIDsToSign,
QGpgMESignKeyJob::setCheckLevel, QGpgMESignKeyJob::setExportable,
QGpgMESignKeyJob::setSigningKey, QGpgMESignKeyJob::setNonRevocable,
QGpgMESignKeyJob::setRemark, QGpgMESignKeyJob::setDupeOk): Adapt to move
of member variables to pimpl.
--

GnuPG-bug-id: 5245, 5421
2021-05-05 19:26:19 +02:00
Ingo Klöcker
a8d7b9d167 cpp: Add support for trust signatures to sign key edit interactor
* lang/cpp/src/gpgsignkeyeditinteractor.h,
lang/cpp/src/gpgsignkeyeditinteractor.cpp
(GpgSignKeyEditInteractor::setTrustSignatureTrust): New.
(GpgSignKeyEditInteractor::setTrustSignatureDepth): New.
(GpgSignKeyEditInteractor::setTrustSignatureScope): New.
* lang/cpp/src/gpgsignkeyeditinteractor.cpp
(GpgSignKeyEditInteractor::Private::Private): Initialize new member.
(makeTable): Add new transition. Fix typos in existing transitions.
(GpgSignKeyEditInteractor::action): Handle SET_TRUST_VALUE,
SET_TRUST_DEPTH, and SET_TRUST_REGEXP.
--

GnuPG-bug-id: 5245, 5421
2021-05-05 19:26:03 +02:00
Ingo Klöcker
e391a08c6f cpp: Add getters for the attributes of a trust signature
* lang/cpp/src/key.h (TrustSignatureTrust): New enum.
* lang/cpp/src/key.h, lang/cpp/src/key.cpp
(UserID::Signature::isTrustSignature): New.
(UserID::Signature::trustValue): New.
(UserID::Signature::trustDepth): New.
(UserID::Signature::trustScope): New.
--

GnuPG-bug-id: 5245, 5420
2021-05-05 19:25:48 +02:00
Ingo Klöcker
276187f6b6 core: Extend gpgme_key_sig_t with trust signature members.
* src/gpgme.h.in (struct _gpgme_key_sig): Add fields 'trust_depth',
'trust_value', and 'trust_scope'.
* src/key.c (gpgme_key_unref): Free trust_scope.
* src/keylist.c (keylist_colon_handler): Set the fields.
* tests/run-keylist.c (main): Print the fields.
--

The trust signature values are part of gpg's output since the year 2003.
This now adds support to gpgme.

GnuPG-bug-id: 5245, 5419
2021-05-05 19:23:48 +02:00
Werner Koch
3ffd7bd403
doc: Add MIT license notice.
* LICENSES: New.
--

Suggested-by: Jiri Kucera <sanczes@gmail.com>
2021-03-11 13:49:31 +01:00
Werner Koch
0821e2b149
core: New flag GPGME_KEYSIGN_FORCE.
* src/gpgme.h.in (GPGME_KEYSIGN_FORCE): New.
* src/engine-gpg.c (gpg_keysign): Implement.

* tests/run-keysign.c (show_usage): Add option --force
--

GnuPG-bug-id: 4584
2021-03-11 11:49:07 +01:00
Ingo Klöcker
fe900a41bf qt: Add method for getting config entries for components by entry name
* lang/qt/src/cryptoconfig.h, lang/qt/src/cryptoconfig.cpp
(CryptoConfig::entry): Move implementation to cpp. Add overload not
requiring a group name.
--

The group name is not needed for identifying a config entry because the
groups only provide a logical grouping of config entry for user
interfaces. To improve usability entries are sometimes moved to a
different group, but this shouldn't break existing applications trying
to access those entries. The new group-agnostic overload makes
applications robust against regrouping of config entries.

GnuPG-bug-id: 5217
2021-03-05 09:24:01 +01:00
Werner Koch
c8fd8870b3
core: Remove experimental feature GPGME_EXPORT_MODE_NOUID.
* src/export.c (export_start): Remove GPGME_EXPORT_MODE_NOUID check.
* src/engine-gpg.c (export_common): Ditto.
--

Note that this constant was never announed and used only for internal
tests.  It made it into some release only by accident.

The constants is kept in gpgme.h to not break any code but it is
non-fucntionals.  We do not consider this an ABI break.

GnuPG-bug-id: 5284
2021-02-01 16:48:30 +01:00
Werner Koch
13221933ed
Post release updates
--
2021-01-08 19:01:50 +01:00
Werner Koch
bb9880778f
Release 1.15.1 2021-01-08 18:14:33 +01:00
Werner Koch
133050b3fa
Make distcheck make target a bit more reliable.
* Makefile.am (release): Do not pass --parallel
2021-01-08 18:12:59 +01:00
Ingo Klöcker
5137d7fc21 core: Make listing of signatures work if only secret keys are listed
* src/engine-gpg.c (gpg_keylist_build_options): Add "--with-sig-check"
argument if signatures shall be listed.
* tests/gpg/t-keylist-secret-sig.c: New.
* tests/gpg/Makefile.am (c_tests): Add new test.
--

GnuPG-bug-id: 3580
2021-01-05 17:44:16 +01:00
Ingo Klöcker
a6220adf30 cpp: Add const-overload of UserID::Signature::operator<
lang/cpp/src/key.h, lang/cpp/src/key.cpp (UserID::Signature::operator<):
Add const-overload. Deprecate non-const overload.

--

This fixes compilation on FreeBSD with clang 10.
2021-01-04 16:30:41 +01:00
Andre Heinecke
543e210638
Qt: Undeprecate QByteArray based start functs
* lang/qt/src/encryptjob.h, lang/qt/src/signjob.h (start):
Undeprecate QByteArray based functions.

--
While the QIODevice access might avoid a copy it is more
difficult to manage the data and lifetime of the
QIODevices in calling code. The QByteArray calls are
convienient for small data objects like mails where
an in memory copy is not really expensive anymore.
2021-01-04 13:35:24 +01:00
NIIBE Yutaka
7a4fe82a01 python: Fix key_export*.
* lang/python/src/core.py (key_export): Just raise an error.
(key_export_minimal, key_export_secret): Ditto.

--

GnuPG-bug-id: 5149
Fixes-commit: 7faef33d13
Signed-off-by: NIIBE Yutaka <gniibe@fsij.org>
2020-12-03 11:35:24 +09:00
NIIBE Yutaka
53ac732bae core: Call _gpgme_passphrase_status_handler when exporting keys.
* src/export.c (export_status_handler): Call the handler.

--

Fixes-commit: 3382ecb17e
Signed-off-by: NIIBE Yutaka <gniibe@fsij.org>
2020-11-24 15:00:27 +09:00
Andre Heinecke
a5c4b03025
Revert "cpp: Use portable off_t size_t"
This reverts commit 88294023c1.

--
This commit was too early and i needed to test more
this is breaking more then it helps so for now
revert it before we can do a proper solution.
2020-11-20 10:10:32 +01:00
NIIBE Yutaka
4c6fd36159 m4: Update with newer autoconf constructs.
* src/gpgme.m4: Replace AC_HELP_STRING to AS_HELP_STRING.

Signed-off-by: NIIBE Yutaka <gniibe@fsij.org>
2020-11-20 12:07:33 +09:00
Andre Heinecke
88294023c1
cpp: Use portable off_t size_t
* configure.ac: Configure cpp data.h.in
* lang/cpp/src/Makefile.am: Generate data.h
* lang/cpp/src/data.cpp, lang/cpp/src/data.h: Use portable
types.
* lang/qt/src/Makefile.am: Include build dir.
* lang/qt/tests/makefile.am: Include build dir.

--
These kind of patches have been around for a while, IMO this
should not create an ABI incompatbility for cases where
it already works because the types should be the same
so I think this is not an interface break.

GnuPG-Bug-Id: T3996
2020-11-18 15:14:56 +01:00
Ingo Klöcker
3c185c2159 qt: Avoid empty "rem@gnupg.org" signature notations
* lang/qt/src/qgpgmesignkeyjob.cpp (sign_key): Check remark for being
an empty string instead of a null QString.
--

GnuPG-bug-id: 5142
Co-authored-by: Daniel Kahn Gillmor
2020-11-18 12:43:45 +01:00
NIIBE Yutaka
223779dfde build: Update with newer autoconf constructs.
* configure.ac: Use AC_USE_SYSTEM_EXTENSIONS instead of AC_GNU_SOURCE.
Use AS_HELP_STRING instead of AC_HELP_STRING.
* m4/libtool.m4: Update from libgpg-error.
* m4/gpg-error.m4: Update from libgpg-error.
* m4/libassuan.m4: Update from libassuan.

Signed-off-by: NIIBE Yutaka <gniibe@fsij.org>
2020-11-18 14:34:52 +09:00
Andre Heinecke
df5a89e692
qt: Fix export of qDebug GpgME::Error overload
* lang/qt/src/debug.cpp: Include debug.h to get the export decl.
2020-11-12 16:07:14 +01:00
Werner Koch
27abdac25d
build: Use ~/.gnupg-autogen.sh for the release targets
* Makefile.am (sign-release): Use global config vars.
2020-11-12 11:10:00 +01:00
Werner Koch
01a0d8ec1a
Post release updates 2020-11-12 11:02:58 +01:00
Werner Koch
feea38c89d
Release 1.15.0
* configure.ac: Bump LT versions to c=C35/A24/R0, cpp=C18/A13/R0,
qt=C12/A5/R0.
--

GnuPG-bug-id: 5131
2020-11-12 10:24:22 +01:00
NIIBE Yutaka
3382ecb17e core: Support exporting secret keys.
* src/export.c (export_start): Set command handler for passphrase
interaction for the case when it's secret keys.
(export_ext_start): Likewise.

--

GnuPG-bug-id: 5046
Co-authored-by: Louis Dupré Bertoni
Signed-off-by: NIIBE Yutaka <gniibe@fsij.org>
2020-11-12 13:11:08 +09:00
NIIBE Yutaka
7139afc5cd python: Fix a test for newer GnuPG (>= 2.3).
* lang/python/tests/t-quick-subkey-creation.py: Specify RSA.

--

Using GnuPG 2.3, a key with default (ed25519/cv25519) cannot have some
combination of capabilities (e.g., "encr auth").

Signed-off-by: NIIBE Yutaka <gniibe@fsij.org>
2020-11-12 11:11:36 +09:00
Andre Heinecke
81f0dc7293
qt: Add export macro for QDebug operator
* lang/qt/src/debug.h: Add export macro.

--
This is public API so it should be exported. This did not
resolve a link issue for Windows that I've experienced
when building. But this might be to some uncleanlyness
in my build environment.
2020-11-11 18:12:20 +01:00
NIIBE Yutaka
276f3390e1 qt: Allow build with older GnuPG (< 2.2.18).
* lang/qt/tests/t-remarks.cpp (initTestCase): Check gpg for
allow-weak-key-signatures option.

Signed-off-by: NIIBE Yutaka <gniibe@fsij.org>
2020-11-11 11:58:28 +09:00
Werner Koch
eb99e8c483
Require at least libgpg-error 1.36
* configure.ac (NEED_GPG_ERROR_VERSION): Require 1.36.
* src/cJSON.c: Remove code for older version.
* src/engine.c (gpgme_get_engine_info): Ditto.
* src/gpgme-json.c: Ditto.
* src/op-support.c: Ditto.
* src/util.h: Ditto.
--

Libgpg-error 1.36 has been released more than 18 months ago so it is
time to avoid hacks and require this verion.  This will for example
help Kleopatra to support PIV cards and improves the gpgme-json.

Signed-off-by: Werner Koch <wk@gnupg.org>
2020-11-09 11:50:46 +01:00
Ben Kibbey
35ca460019 Parse STATUS_CANCELED_BY_USER.
* src/gpgme.h.in (GPGME_STATUS_CANCELED_BY_USER): New.
* src/status-table.c (status_table_s): Add "CANCELED_BY_USER".
* src/passphrase.c (_gpgme_passphrase_status_handler): Return
GPG_ERR_CANCELED during GPGME_STATUS_CANCELED_BY_USER.

Signed-off-by: Ben Kibbey <bjk@luxsci.net>
2020-11-03 17:47:44 -08:00
Ingo Klöcker
0fee135997 qt: Make audit parameters of result signal optional
lang/qt/src/quickjob.h (QuickJob::result): Make parameters
auditLogAsHtml and audigLogError optional.
--

This aligns the signature of QuickJob's result signal with the result
signals of the other Job subclasses.

GnuPG-bug-id: 5094
2020-11-03 13:50:53 +01:00
Ingo Klöcker
b41f5fec1c cpp: Mark helper functions as static
lang/cpp/src/key.cpp (find_subkey, verify_subkey, find_uid, verify_uid,
find_signature, verify_signature): Mark as static.
2020-11-03 09:01:32 +01:00
Ingo Klöcker
6a6d2a2764 cpp: Make signatures belonging to the same user ID sortable
lang/cpp/src/key.h, lang/cpp/src/key.cpp (UserID::Signature::operator<):
New.
lang/cpp/src/key.cpp (signature_index): New.
--

operator< defines a canonical sort order for signatures belonging to
the same user ID. It is based on the sort order defined by
cmp_signodes() in g10/keylist.c of gnupg. In particular, the ordering
of signatures made with the same key by creation time allows to see
easily whether the most recent signature is a certification or a
revocation.

GnuPG-bug-id: 5094
recent
2020-11-03 08:59:54 +01:00
Ingo Klöcker
f042739d3a qt: Add support for revoke signature quick command
* lang/qt/src/quickjob.h (QuickJob::startRevokeSignature): New.
* lang/qt/src/qgpgmequickjob.h, lang/qt/src/qgpgmequickjob.cpp
(QGpgMEQuickJob::startRevokeSignature): New.
* lang/qt/src/qgpgmequickjob.cpp (revokeSignatureWorker): New.
--

GnuPG-bug-id: 5094
2020-10-29 12:57:10 +01:00
Ingo Klöcker
60328c4690 qt: Some minor cleanups
* lang/qt/src/qgpgmequickjob.h: (GpgME::Key, QDateTime, QString):
Remove superfluous forward declarations.
(QGpgMEQuickJob): Remove superfluous second template argument. It is
identical to the default.
(QGpgMEQuickJob::result): Remove. It is already defined in the base
class.
2020-10-29 12:57:10 +01:00
Ingo Klöcker
4166d263e4 cpp: Add support for gpgme_op_revsig
* lang/cpp/src/context.cpp, lang/cpp/src/context.h
(Context::revokeSignature, Context::startRevokeSignature): New.
* lang/cpp/src/context.cpp
(getLFSeparatedListOfStrings, getLFSeparatedListOfUserIds): New.
(getLFSeparatedListOfFingerprintsFromSubkeys): Extracted second part
of function to getLFSeparatedListOfStrings.
--

GnuPG-bug-id: 5094
2020-10-29 12:57:10 +01:00
Ingo Klöcker
f3407d0ee4 core: New function gpgme_op_revsig.
* src/gpgme.h.in (gpgme_op_revsig_start, gpgme_op_revsig): New.
(GPGME_REVSIG_LFSEP): New.
* src/context.h (ctx_op_data_id_t): Add OPDATA_REVSIG.
* src/revsig.c: New.
* src/Makefile.am (main_sources): Add revsig.
* src/libgpgme.vers, src/gpgme.def: Add gpgme_op_revsig and
gpgme_op_revsig_start.
* src/engine.h, src/engine.c: (_gpgme_engine_op_revsig): New.
* src/engine-backend.h (engine_ops): Add 'revsig' and adjust all
engine initializers.
* src/engine-gpg.c (gpg_revsig): New.
(_gpgme_engine_ops_gpg): Set revsig to gpg_revsig.
* doc/gpgme.texi: Document new functions.
* tests/run-keysign.c: Add option --revoke.
--

This extends GPGME to support the --quick-revoke-sig command
added by GnuPG 2.2.24. This allows revoking key signatures.

GnuPG-bug-id: 5094
2020-10-29 12:57:10 +01:00
NIIBE Yutaka
089164a0c0 python: Handle the when case __doc__ is None.
* lang/python/src/core.py (GpgmeWrapper): Check if None.

--

GnuPG-bug-id: 5075
Signed-off-by: NIIBE Yutaka <gniibe@fsij.org>
2020-10-28 08:49:33 +09:00
Ingo Klöcker
74c8131d80 cpp: Add support for gpgme_cancel
* lang/cpp/src/context.cpp, lang/cpp/context.h
(Context::cancelPendingOperationImmediately): New.
* NEWS: Mention added API
--

This allows immediate canceling of running operations, e.g. when a
thread with a long running operation (like SCD DEVINFO --watch) is
going to be terminated (on application shutdown).

GnuPG-bug-id: 5066
2020-10-23 13:50:16 +02:00
Ingo Klöcker
ff23e24063 Add Assuan transaction that forwards status lines to another object
* lang/cpp/src/Makefile.am: Add new files.
* lang/cpp/src/interfaces/statusconsumer.h,
lang/cpp/src/statusconsumerassuantransaction.cpp,
lang/cpp/src/statusconsumerassuantransaction.h: New.
* NEWS: Mention new API.
--

This Assuan transaction is useful for long running Assuan commands.
Classes implementing the StatusConsumer interface can process received
status lines while the Assuan command is still running.

GnuPG-bug-id: 5066
2020-10-23 13:50:16 +02:00
Ingo Klöcker
b21cabb311 qt: Add QDebug stream operator for GpgME::Error
* lang/qt/src/Makefile.am: Add new files.
* lang/qt/src/debug.h, lang/qt/src/debug.cpp: New.
* NEWS: Mention it.
--

This was previously implemented in Kleopatra, but it makes sense for
all users of qgpgme.
2020-10-23 13:50:16 +02:00
Ingo Klöcker
c3406462d1 cpp, qt: Add missing comparison operators for version info comparison
* lang/cpp/src/engineinfo.h (EngineInfo::Version::operator<=,
EngineInfo::Version::operator>=, EngineInfo::Version::operator!=):
New.
* lang/qt/tests/t-various.cpp (TestVarious::testVersion): Add tests for
new comparison operators.
* NEWS: Mention added API
2020-10-23 13:50:16 +02:00
Ingo Klöcker
2f53a2f4be cpp, qt: Fix version info comparison
* lang/cpp/src/engineinfo.h
(EngineInfo::Version::operator>(const Version &)): Fix logic.
(EngineInfo::Version::operator>(const char *)): Use Version-overload of
operator>.

* lang/qt/tests/t-various.cpp: Add test.
--

This fixes a logic error that 2.0.0 > 2.0.0 would return true.
2020-10-23 13:50:16 +02:00
Werner Koch
25e2d717f4
tests: Fix gcc incompatibility
* tests/json/t-json.c: Remove var definitions inside a for statement.
--

This useful C99 feature seems to work only in recent gcc versions.  We
can't use it; see gnupg/doc/HACKING.

GnuPG-bug-id: 5088
2020-10-03 19:54:00 +02:00
NIIBE Yutaka
fd904f87f8 gpgsm: Fix leaked fd.
* src/engine-gpgsm.c (gpgsm_new): Close gpgsm->diag_cb.server_fd.

--

GnuPG-bug-id: 5074
Reported by: VladislavGrudinin
Fixes-commit: dd21ec997c
Signed-off-by: NIIBE Yutaka <gniibe@fsij.org>
2020-10-01 11:18:50 +09:00
Werner Koch
e4ee706e27
core: Fully implement the inquire callback for assuan_transact
* src/engine-assuan.c (inquire_cb): Implement returning data.

* tests/opassuan/t-command.c (inq_cb): Send some test data.
--

The old code only allowed to send an empty response which was good
enough for scdaemon's KNOWNCARDP inquire but not to send actual data.
A quick test using a test smartcard might be

 ./t-command 'scd setattr --inquire PRIVATE-DO-1'

and then reading the data back using

  gpg-connect-agent 'scd getattr PRIVATE-DO-1' /bye

Signed-off-by: Werner Koch <wk@gnupg.org>
2020-09-09 12:13:20 +02:00
Ingo Klöcker
973c8116c8 qt: Update the documentation of ListAllKeysJob
* lang/qt/src/listallkeysjob.h (ListAllKeysJob::start): Document that
the mergeKeys argument is ignored with gpg >= 2.1.
--

GnuPG-bug-id: 4794
2020-09-08 15:38:00 +02:00
Ingo Klöcker
3dd7377e12 cpp: Update key with --with-secret instead of updating it twice
* lang/cpp/src/key.cpp (Key::update): Call Context::key() only once
with KeyListMode::WithSecret.
--

With gpg >= 2.1, get the key with --with-secret instead of first trying
to get the secret key and, if that fails, getting the public key.

GnuPG-bug-id: 4794
2020-09-08 14:55:20 +02:00
Ingo Klöcker
13bcc6680a qt: List keys once with --with-secret instead of twice
* lang/qt/src/qgpgmelistallkeysjob.cpp
(do_list_keys): Rename to do_list_keys_legacy and put into unnamed
namespace.
(merge_keys): Put into unnamed namespace.
(list_keys): Rename to list_keys_legacy and put into unnamed namespace.
(do_list_keys, list_keys): New.
* lang/qt/tests/t-keylist.cpp (testListAllKeysSync): New.
--

With gpg >= 2.1, list keys once with --with-secret instead of listing
public keys and secret keys and then merging (part of) the information
about the keys.

GnuPG-bug-id: 4794
2020-09-07 12:02:29 +02:00
Ingo Klöcker
188cc9e9b5 cpp: Add keylist mode WithSecret
* lang/cpp/src/global.h (WithSecret): New.
* lang/cpp/src/context.cpp (operator<<): Handle WithSecret.
* lang/cpp/src/util.h (add_to_gpgme_keylist_mode_t,
convert_from_gpgme_keylist_mode_t): Ditto.
--

GnuPG-bug-id: 4794
2020-09-07 11:55:07 +02:00
Ingo Klöcker
b714a6bbc8 cpp: Add missing keylist modes
* lang/cpp/src/util.h
(add_to_gpgme_keylist_mode_t): Sort modes as in enum definition and
add missing modes to check.
(convert_from_gpgme_keylist_mode_t): Add missing handling of
GPGME_KEYLIST_MODE_WITH_TOFU and GPGME_KEYLIST_MODE_WITH_KEYGRIP.
2020-09-07 11:36:11 +02:00
Ingo Klöcker
4d87ea2851 cpp: Copy some more subkey properties when merging keys
* lang/cpp/src/key.cpp (Key::mergeWith): Also merge secret flag and
keygrip
--

The keygrip was lost if the result of a public key listing was merged
with the result of a secret key listing as done by QGpgMEListAllKeysJob.

GnuPG-bug-id: 4794
2020-09-03 12:24:21 +02:00
Werner Koch
b088d81cef
qt: Fix an rfc2253 parser flaw
* lang/qt/src/dn.cpp (parse_dn_part): Fix parser.

--

This could in theory result in reading bytes after a after Nul in a
string and thus possible segv on unallocated memory or reading other
parts of the memory.  However, it is harmless because the rfc2253
strings have been received from GnuPG which is expected to emit
correct syntax.

GnuPG-bug-id: 5037
2020-08-28 09:13:35 +02:00
Ingo Klöcker
f66f856c89 core: Add error handling to setexpire
* src/genkey.c (setexpire, gpgme_op_setexpire_start,
gpgme_op_setexpire): Move to ...
* src/setexpire.c: New.
* src/Makefile.am (main_sources): Add that file.
* src/context.h (ctx_op_data_id_t): Add OPDATA_SETEXPIRE.

* lang/qt/tests/t-various.cpp (testSetExpire): Test error handling.
--

Errors (and failures) emitted via status-fd need to be handled
explicitly, i.e. we need to provide an appropriate status handler with
corresponding op_data_t. Additionally, we need to set a passphrase
command handler if a passphrase callback is set in the context, e.g.
during tests.

GnuPG-bug-id: 4395
2020-08-14 11:11:23 +02:00
Ingo Klöcker
4f2cd3a0c6 qt: Support changing expiry of subkeys
* lang/qt/src/changeexpiryjob.h (ChangeExpiryJob::start): New overload
that accepts subkeys (with empty implementation).
* lang/qt/src/qgpgmechangeexpiryjob.h,
lang/qt/src/qgpgmechangeexpiryjob.cpp (QGpgMEChangeExpiryJob::start):
New overload that accepts subkeys.
--

This adds the possibility to change the expiry of subkeys.

GnuPG-bug-id: 4717
2020-08-11 17:02:25 +02:00
Ingo Klöcker
c813734c9c cpp: Make private helper a file static
* lang/cpp/src/context.h, lang/cpp/src/context.cpp
(Context::getLFSeparatedListOfFingerprintsFromSubkeys): Remove
from Context; make it a static function instead
--

GnuPG-bug-id: 5003
2020-08-10 11:06:13 +02:00
Andre Heinecke
0676d41ef5
cpp: Use cstdlib getenv for portability
* lang/cpp/src/editinteractor.cpp (EditInteractor::Private::Private):
Use std::getenv.

--
This should fix compiling on MacOS X

GnuPG-Bug-Id: T5013
2020-08-06 09:50:16 +02:00
Ingo Klöcker
8950150913 qt: Port to new setExpire()
* lang/qt/src/qgpgmechangeexpiryjob.cpp (change_expiry): Use new
setExpire() instead of edit() with GpgSetExpiryTimeEditInteractor
--

Using the new setExpire() (which uses --quick-set-expire) is a lot less
complex than using gpg's edit interface. It also feels faster. Next,
I'll add support for changing the expiration time of subkeys.

GnuPG-bug-id: 5003
2020-08-05 16:49:18 +02:00
Ingo Klöcker
84c6b6e2fe qt: Add test for setExpire
* lang/qt/tests/t-various.cpp (TestVarious::testSetExpire): New.
--

GnuPG-bug-id: 5003
2020-08-04 16:53:57 +02:00
Ingo Klöcker
aa03205fe5 cpp: Add support for gpgme_op_setexpire
* lang/cpp/src/context.cpp
(Context::setExpire, Context::startSetExpire): New.
(Context::getLFSeparatedListOfFingerprintsFromSubkeys):
New helper.
* lang/cpp/src/context.h
(Context::SetExpireFlags): New enum.
(Context::setExpire, Context::startSetExpire): Add
prototypes.
(Context::getLFSeparatedListOfFingerprintsFromSubkeys):
Add as private helper.
--

GnuPG-bug-id: 5003
2020-08-04 16:53:29 +02:00
Ingo Klöcker
197ba151e7 cpp: Add ostream operator for subkey
* lang/cpp/src/key.cpp (Subkey): Add ostream operator.
* lang/cpp/src/key.h: Update accordingly.
--

This is helpful for debugging / showing the state of a subkey.
2020-08-04 16:53:28 +02:00
Ingo Klöcker
db82e99a8a core: New function gpgme_op_setexpire.
* src/gpgme.h.in (gpgme_op_setexpire_start, gpgme_op_setexpire): New.
* src/libgpgme.vers, src/gpgme.def: Add new functions.
* src/genkey.c (setexpire): New.
(gpgme_op_setexpire_start, gpgme_op_setexpire): New.
* src/engine.h, src/engine.c: (_gpgme_engine_op_setexpire): New.
* src/engine-backend.h (engine_ops): Add 'setexpire' and adjust all
engine initializers.
* src/engine-gpg.c (gpg_setexpire): New.
(_gpgme_engine_ops_gpg): Set setexpire to gpg_setexpire.
* doc/gpgme.texi: Document new functions.
* tests/run-genkey.c: Add option --setexpire.
--

This extends GPGME to support the --quick-set-expire command
added by GnuPG 2.1.22. This allows changing subkeys expiry
date without going through the editinteractor interface.

Co-authored-by: Andre Heinecke <aheinecke@gnupg.org>
GnuPG-bug-id: 4999
2020-08-04 16:51:56 +02:00
Werner Koch
81db412245
Post release updates
--
2020-07-16 17:33:34 +02:00
Werner Koch
6d7bf78ca5
Release 1.14.0
* configure.ac: Bump LT versions to c=C34/A23/R0 cpp=C17/A11/R0
qt=C11/A4/R0.
--
GnuPG-bug-id: 4996
2020-07-16 17:17:34 +02:00
Andre Heinecke
690d967196
qt, cpp: Support export modes
* lang/cpp/context.cpp, lang/cpp/context.h
(Context::startPublicKeyExport, Context::exportPublicKeys): Extend
with flags paramenter.
(Context::ExportMode): New.
* lang/qt/src/exportjob.h (ExportJob::setExportMode): New.
* lang/qt/src/qgpgmeexportjob.cpp, lang/qt/src/qgpgmeexportjob.h:
Update accordingly.

--
This adds the C++ and Qt API for export modes.
2020-07-16 17:00:28 +02:00
Werner Koch
dfeedcc28d
core: Also allow GPGME_EXPORT_MODE_SSH for gpgme_op_export.
* src/export.c (export_start): Allow that mode.
--

The test tools uses gpgme_op-export_ext and thus did not caught it.

Signed-off-by: Werner Koch <wk@gnupg.org>
2020-07-16 16:47:31 +02:00
Werner Koch
7f9e0ca57b
core: New export mode to export as OpenSSH public key.
* src/gpgme.h.in (GPGME_EXPORT_MODE_SSH): New.
* src/export.c (export_ext_start): Allow for new mode.
* src/engine-gpg.c (export_common): Implement.
* tests/run-export.c (status_cb): New.
(main): New options --status and --ssh.
--

GnuPG-bug-id: 4310
Signed-off-by: Werner Koch <wk@gnupg.org>
2020-07-16 12:00:46 +02:00
Werner Koch
8589091682
core: Deprecate the non-working trustlist functions.
* src/gpgme.h.in: Clarify that the trustlist function should not be
used.
* src/engine.c (_gpgme_engine_op_trustlist): Always return an error.
* src/engine-backend.h (struct engine_ops): Remove trustlist member.
* src/engine-gpg.c (gpg_trustlist): Remove.
(struct engine_ops): Remove that member.  Also in all other engines.
* tests/gpg/t-trustlist.c: Remove.
* lang/python/tests/t-trustlist.py: Remove.
--

This never worked in reality because the required feature has been
removed from GnuPG version 1.3.2 soon after introduction of this
feature in gpgme - 17 years ago.  It was anyway marked as
experimental.  We keep the API and ABI, though.

GnuPG-bug-id: 4834
Signed-off-by: Werner Koch <wk@gnupg.org>
2020-07-15 16:34:24 +02:00
Werner Koch
c8048bf8eb
core: New keylist mode GPGME_KEYLIST_MODE_WITH_KEYGRIP.
* src/gpgme.h.in (GPGME_KEYLIST_MODE_WITH_KEYGRIP): New.
* src/gpgme-json.c (op_keylist): New flag "keygrip".
* src/engine-gpg.c (gpg_keylist_build_options): Pass the options.

* lang/cpp/src/global.h (WithKeygrip): New.
* lang/cpp/src/context.cpp: Add check.
* lang/cpp/src/key.cpp (Key::update): Handle WithKeygrip.
* lang/cpp/src/verificationresult.cpp: Ditto.
* lang/cpp/src/util.h (add_to_gpgme_keylist_mode_t): Ditto.
--

GnuPG-bug-id: 4939
Signed-off-by: Werner Koch <wk@gnupg.org>
2020-07-15 14:11:17 +02:00
Werner Koch
32b80cf3c7
python: Workaround for a regression in GnuPG 2.2.21
* lang/python/tests/support.py (is_gpg_version): New.
* lang/python/tests/t-encrypt-sym.py: Add workaround.
--

GnuPG-bug-id: 4991
Signed-off-by: Werner Koch <wk@gnupg.org>
2020-07-14 14:48:01 +02:00
Andre Heinecke
88f3202521
doc: Explain verify_result_t.status == 0 more
* doc/gpgme.texi (gpgme_verify_result_t): Explain
GPGME_STATUS_NO_ERROR more clearly.

--
This might help to avoid misunderstandings how the
status can be interpreted and explains why a verify
of unsigned PGP Data returns no error.

As a reaction to CVE-2020-10759 discovered by Justin Steven.
2020-06-09 10:22:27 +02:00
Werner Koch
728ead8ebd
core: Fix setting of the chain_model signature result.
* src/verify.c (parse_trust): Fix detection of "chain" keyword.
--

Fixes-commit: da6f3dc0c5
from 2007 shortly after introducing this.  I doubt that this info has
ever been used (it is for qualified signatures, which are only
supported using the legacy German RegTP rules for them which were soon
overturned by the commercial CAs).

Signed-off-by: Werner Koch <wk@gnupg.org>
2020-06-05 14:46:56 +02:00
NIIBE Yutaka
0cc040e82f tests: Remove/change tests for GnuPG 2.3 with no gpg.keyserver.
* lang/qt/tests/t-config.cpp (testKeyserver): Remove.
* tests/gpg/t-gpgconf.c (main): Test with dirmngr.keyserver.

Signed-off-by: NIIBE Yutaka <gniibe@fsij.org>
2020-05-11 14:20:48 +09:00
Andre Heinecke
52f930c1ed
w32: Explicitly link ws2_32
* src/Makefile.am (gpgme_w32_extra_libs): New.
(libgpgme_la_LIBADD, libgpgme_glib_la_LIBADD): Use it.

--
Since w32-io.c directly uses functions from ws2_32 it should
not rely on libgpg-error to pull in this dependency.
2020-05-08 16:38:19 +02:00
dupgit
49c13854f3
GPGME_CREATE_NOEXPIRE is only available since 1.9.0
* doc/gpgme.texi: Fixes version number from 1.8.0 to
   1.9.0 for GPGME_CREATE_NOEXPIRE.

GnuPG-Bug-Id: T4922
Signed-off-by: dupgit <olivier.delhomme@free.fr>
2020-05-08 12:34:20 +02:00
Werner Koch
004fdf61c8
core: Make sure the keygrip is available in WITH_SECRET mode.
* src/engine-gpg.c (gpg_keylist_build_options): Send --with-keygrip
if --with-secret is used.
--

Since GnuPG 2.2.19 the keygrip was not anymore send if only
--with-secret was used in a public key listing.  Given that
--with-secret requires computation of the keygrip anyway, there is no
point in not requesting the keyrip in this case.

GnuPG-bug-id: 4820
2020-05-08 11:18:42 +02:00
Andre Heinecke
5c0d1c7f76
tests, json: Do not check for keygrip of pubkeys
* tests/json/t-keylist-secret.out.json: Do not check for keygrip
of bravo key.

--
Since GnuPG 2.2.19 the keygrip is not emitted for public keys
in a keylisting --with-secret.

As the GPGME test suite should pass with several versions
the json test cannot test this as the suite does not allow
version checks for different output.

What the intended behavior is might still be up for discussion,
always adding --with-keygip is not a good solution because
it slows down keylistings for large keyrings.

GnuPG-Bug-Id: T4820
2020-05-08 10:30:53 +02:00
NIIBE Yutaka
3658e2df65 tests: Add ECC key generation for tests/gpgsm.
* tests/gpgsm/t-genkey.c (check_result): New.

Signed-off-by: NIIBE Yutaka <gniibe@fsij.org>
2020-03-27 19:50:24 +09:00
NIIBE Yutaka
71ef398bfd build: Fix library dependency.
* src/Makefile.am (gpgme_tool_LDADD): Add @GPG_ERROR_LIBS@.

--

Since gpgme-tool uses gpg_strerror, it should be linked
to -lgpg-error.

Signed-off-by: NIIBE Yutaka <gniibe@fsij.org>
2020-03-27 16:24:13 +09:00
Werner Koch
3afa534645
core: New context flags "include-key-block" and "auto-key-import".
* src/gpgme.c (gpgme_set_ctx_flag): Add flags "include-key-block" and
"auto-key-import".
(gpgme_get_ctx_flag): Ditto.
* src/context.h (struct gpgme_context): Add flags include_key_block
and auto_key_import.
* src/engine-gpg.c (struct engine_gpg): Likewise.
(gpg_set_engine_flags): Set the flags for gpg versions >= 2.2.20.
(gpg_decrypt): Set option according to the new flags.
(gpg_encrypt): Ditto.
(gpg_encrypt_sign): Ditto.
(gpg_sign): Ditto.
(gpg_verify): Ditto.

tests/run-verify: Add option --auto-key-import.
tests/run-sign: add option --include-key-block.
--

GnuPG-bug-id: 4856
Signed-off-by: Werner Koch <wk@gnupg.org>
2020-03-17 17:24:21 +01:00
Bernhard Reiter
11edc073a3
python: fix minor typo in howto 2020-03-03 08:52:54 +01:00
Andre Heinecke
ec9690cf5c
qt: Change logging category
* lang/qt/src/*: Change logging category to macro to QGPGME_LOG.

--
The old logging category macro had a typo and this way we
are more consistent with other logging rules. For example
you could write gpg.* in the logging conf.
2020-02-19 11:15:54 +01:00
Andre Heinecke
ba08aadfa7
qt: Log execution args of gpg-card
* lang/qt/src/qgpgmegpgcardjob.cpp (do_work): Log call.
2020-02-19 11:15:54 +01:00
Werner Koch
2b8680aba9
python: Also detect python 3.9.
--

Signed-off-by: Werner Koch <wk@gnupg.org>
2020-02-14 13:16:01 +01:00
Andre Heinecke
9ca679c150
qt: Add dummy context to make mixin happy
* lang/qt/qgpgmegpgcardjob.cpp (QGpgMEGpgCardJob): Add context.
--
Otherwise it fails with an assert.
2020-02-12 15:50:36 +01:00
Andre Heinecke
77feaa4510
qt: Add GpgCardJob following the job pattern
* lang/qt/src/Makefile.am: Add new files.
* lang/qt/src/job.cpp (GpgCardJob): Add impl stuff.
* lang/qt/src/protocol.h (gpgCardJob): Get one.
* lang/qt/src/qgpgmebackend.cpp,
lang/qt/src/qgpgmebackend.h: Add helpers to get the job.
* lang/qt/src/qgpgmegpgcardjob.cpp,
lang/qt/src/gpgcardjob.h,
lang/qt/src/qgpgmegpgcardjob.h: New.

--
This is annoyingly complex to add a simple new job.
In the future we should implement something like this
without the threadedjobmixin stuff. But the idea was
to follow the usual job pattern.

GnuPG-Bug-Id: T4794
2020-02-12 11:57:09 +01:00
Andre Heinecke
cff600f1f6
Do not test for a bug in older GnuPG versions
* tests/json/t-keylist-secret.out.json

--
Since at least 2.2.19 GnuPG no longer emits secret = true
for keys where it does not have a secret. To avoid
failures with older versions we remove the check altogether.

GnuPG-Bug-Id: T4820
2020-01-29 11:01:10 +01:00
Daniel Kahn Gillmor
414938cfed m4/python: Scan for python 3.8 as well
* m4/python.m4: Scan for python 3.8 as well.

--

It's not clear to me why python3.8 should be commented out of the
python path search.  This change simplifies and normalizes the search
for modern versions of python 3.

Signed-Off-By: Daniel Kahn Gillmor <dkg@fifthhorseman.net>
2020-01-23 18:26:48 -05:00
Andre Heinecke
39052913f2
core: Add MacOS fallbacks to look for binaries
* src/posix-util.c (find_executable): New.
(walk_path_str): Factored out from walk_path.
(walk_path): Replaced by find_executable.
(_gpgme_get_gpg_path, _gpgme_get_gpgconf_path): Use find_executable.

--
This should help to locate GnuPG on MacOS systems where
it is not part of the PATH environment variable and
should reduce the need to have fixed path known
at GPGME compile time.

mailvelope/issue699
2020-01-17 12:42:56 +01:00
Andre Heinecke
194272dbc3
cpp, qt: Use uidhash to select uids for signing
* lang/cpp/src/gpgsignkeyeditinteractor.cpp (action):
Use uidhash instead of number.
(GpgSignKeyEditInteractor::setKey): New.
* lang/cpp/src/gpgsignkeyeditinteractor.h: Update accordingly.
* lang/cpp/src/key.h, lang/cpp/src/key.cpp: Wrap uidhash.
* lang/qt/src/qgpgmesignkeyjob.cpp: Set the key.

--
Using the uidhash avoids problems when the user ids
on --edit-key are different ones then the uids
captured by gpgme when listing keys. Or if
they are in a different order. This can happen
with cached keys or keys with user attributes.
2019-12-13 18:06:00 +01:00
Werner Koch
5eeae535ee
core: Extend gpgme_user_id_t with uidhash member.
* src/gpgme.h.in (struct _gpgme_user_id): Add field 'uidhash'.
* src/key.c (gpgme_key_unref): Free it.
* src/keylist.c (keylist_colon_handler): Set it.
* tests/run-keylist.c (main): Print it.
--

The uidhash value is part of gpg's output since the year 2005.  This
now adds support to gpgme.  The application for uidhash is to select
a user id in an edit interactor: Instead of giving the number of the
user id, the uidhash value can be be used to avoid tracking the user
id numbers.

Signed-off-by: Werner Koch <wk@gnupg.org>
2019-12-13 15:11:00 +01:00
Andre Heinecke
7e7eaf4342
Revert "doc: Remove UI Server documentation"
This reverts commit 1b2ad3b73c.

--
Just removing the documentation was not the right way as
this is still in use.
2019-12-11 10:30:41 +01:00
Daniel Kahn Gillmor
ae4d7761a1 gpg: Avoid error diagnostics with --override-session-key when verifying
* src/engine-gpg.c (gpg_decrypt): only send --no-keyring when we are
not verifying.

--

Without this change, the signature verification would fail.  This
problem was introduced in bded8ebc59 in
an attempt to avoid an error when *not* verifying.  Clearly more test
suite coverage is needed to avoid introducing this sort of problem in
the future.

GnuPG-bug-id: 3464
Signed-off-by: Daniel Kahn Gillmor <dkg@fifthhorseman.net>
2019-12-06 10:41:44 +09:00
Daniel Kahn Gillmor
c0c97dbbe6 gpgme-tool: Fix help text for INCLUDE_CERTS.
* src/gpgme-tool.c (hlp_include_certs): added missing newline.

Signed-off-by: Daniel Kahn Gillmor <dkg@fifthhorseman.net>
2019-12-03 18:42:07 -05:00
Werner Koch
d480a3c8f3
core,w32: Silence compiler warnings.
* src/w32-util.c (_gpgme_w32_cancel_synchronous_io): Add some casts.
--

Signed-off-by: Werner Koch <wk@gnupg.org>
2019-11-27 20:40:39 +01:00
Andre Heinecke
1b2ad3b73c
doc: Remove UI Server documentation
* doc/Makefile.am: Remove uiserver.texi
* doc/gpgme.texi: Remove UI-Server mentions.
* doc/uiserver.texi: Removed.

--
This prepares the removal of UI Server from implementing
applications like Kleopatra.
The only user of the UI Server is GpgEX and even that
does not need it at all and is better served with process
calls.

GnuPG-Bug-Id: T4030
2019-11-12 11:04:11 +01:00
NIIBE Yutaka
c493242007 qt,tests: Take care for old DSA key using deprecated digest algo.
* lang/qt/tests/t-remarks.cpp (initTestCase): Supply
allow-weak-key-signatures flag for GnuPG 2.3, which
normally rejects use of SHA1 digest.

Signed-off-by: NIIBE Yutaka <gniibe@fsij.org>
2019-11-08 08:07:33 +09:00
Andre Heinecke
e7b5c6405d
qt, tests: Add check for supported versions
* lang/qt/tests/t-encrypt.cpp (decryptSupported): Moved to
t-support as loopbackSupported.
* lang/qt/tests/t-remarks.cpp: Check for loopbackSupported.
* lang/qt/tests/t-support.cpp, lang/qt/tests/t-support.h
(loopbackSupported): New.

--
This ensures that the tests do not fail with GnuPG 2.0.x
2019-11-06 09:21:02 +01:00
Andre Heinecke
024edbbd3c
qt, tests: Replace accidentally commited assert
* lang/qt/test/t-remarks.cpp (testRemarkReplaceSingleUIDExportable):
Use QVERIFY instead of assert.

--
An assert causes the temp directory not to be cleaned up. I
use this to analyze test failures.
If you want to see the tests home directory after a failure you
can just change a failing verify to an assert.
2019-11-06 09:12:09 +01:00
Andre Heinecke
a56f6015e9
qt,tests: Add test to add an exportable certify
* lang/qt/test/t-remarks.cpp (testRemarkReplaceSingleUIDExportable):
New.

--
Just checking in case the edit-key offers new states for that.
2019-11-06 09:10:03 +01:00
NIIBE Yutaka
1b840a151a python: Fix how to generate documentation.
* lang/python/doc/Makefile.am: Explicitly write rules to generate rst
and texinfo files.

Fixes-commit: 36428d8cf1
Signed-off-by: NIIBE Yutaka <gniibe@fsij.org>
2019-11-06 10:30:16 +09:00
Andre Heinecke
9cf4db1e52
qt, tests: Add testcase for multiple remarsk
* lang/qt/tests/t-remarks.cpp (testMultipleRemarks): New.
2019-11-04 13:56:14 +01:00
Andre Heinecke
cb7668caeb
cpp: Add API to obtain mutliple remarks
* lang/cpp/src/key.cpp, lang/cpp/src/key.h (UserID::remarks): New.
* NEWS: Mention this.

--
This can be useful if we want to show remarks made by others, too.

For:
GnuPG-Bug-Id: T4734
2019-11-04 13:54:55 +01:00
Andre Heinecke
db888b1cc0
qt,tests: Move remarks test out and extend it
* lang/qt/tests/t-various.cpp (testRemarks): Move out.
* lang/qt/tests/t-remarks.cpp: New.
* lang/qt/tests/Makefile.am: Update accordingly.
--
While t-various is nice to add a quick test for more
extensive stuff it is better to move it in its own test.

This also tests with a key that has only a single uid.
2019-11-04 11:18:35 +01:00
Andre Heinecke
08933c183a
cpp: Fix dupe_ok state for single uid
* lang/cpp/src/gpgsignkeyeditinteractor.cpp (makeTable):
Add transition from command to dupe_ok
2019-11-04 11:17:27 +01:00
Werner Koch
067b1a73d9
doc: Note the need for a base tag.
--
2019-11-04 09:15:43 +01:00
Andre Heinecke
d61491dd25
qt: Allow adding empty remarks
* lang/qt/src/qgpgmesignkeyjob.cpp (sign_key): Allow empty
remarks.
2019-11-01 12:05:47 +01:00
Andre Heinecke
174caaa6f5
cpp: Minor optimization in remark lookup
* lang/cpp/src/key.cpp (UserID::remark): Use C-API.

--
The other parts of that function already use the C API
so we can also avoid function calls for the keyListMode.
2019-11-01 12:04:41 +01:00
Andre Heinecke
266e05eee8
cpp: Fix adding duplicated sigs on multiple uids
* lang/cpp/src/gpgsignkeyeditinteractor.cpp: Add another
state DUPE_OK2 to allow gpg looping over all uids.

--
When duplicated signatures should be added to multiple
user ids GnuPG will ask for each uid so we have to
add a transition for that.

GnuPG-Bug-Id: T4734
2019-11-01 12:02:07 +01:00
Andre Heinecke
a4d5394b46
cpp: Add env var to control editinteractor debug
* lang/cpp/src/editinteractor.cpp (EditInteractor::Private::Private):
Read "GPGMEPP_INTERACTOR_DEBUG" env var.
(EditInteractor::Private::~Private): Close debug file.

--
While it was possible for the application to control the
debug through setDebugChannel it is often times helpful
to just debug without changing the application using
GPGME
2019-11-01 12:00:18 +01:00
Andre Heinecke
1242c6c93a
core: Fix parsing of userid sigs after a subpkg
* src/keylist.c (keylist_colon_handler): Do not clear
out the tmp_uid when a subpacket line is encountered.

--
When the uid is cleared no more signatures following
the subpacket are parsed, so we now no longer clear
it when a subpacket is encountered.
2019-10-29 16:43:37 +01:00
Andre Heinecke
1f3ca698f1
qt,tests: Add test for remarks
* lang/qt/tests/t-various.cpp (testRemark): New.
2019-10-29 16:36:45 +01:00
Andre Heinecke
373acd6923
qt: Extend signkeyjob to handle remarks and dups
* lang/qt/src/qgpgmesignkeyjob.cpp: Handle remarks and
dupeOK.
* lang/qt/src/signkeyjob.h (SignKeyJob::setDupeOk),
(SignKeyJob::setRemark): New.

--
This API makes it easy for Kleopatra to add remarks for:
GnuPG-Bug-Id: T4734
2019-10-29 16:33:58 +01:00
Andre Heinecke
36f7f7a478
cpp: Add support for multiple keysigs in edit
* lang/cpp/src/gpgsignkeyeditinteractor.cpp
(GpgSignKeyEditInteractor::setDupeOk): New.
(makeTable): Add new tansitions.
(SignKeyState): Add DUPE_OK Status.
(GpgSignKeyEditInteractor::action): Handle DUPE_OK.
(GpgSignKeyEditInteractor::Private::Private): Carry flag.

--
When extended-edit is enabled this can be used to answer
the "dupe_ok" query from the edit-key with yes.

This is for:
GnuPG-Bug-Id: T4734
2019-10-29 16:31:20 +01:00
Andre Heinecke
83ecf1686a
cpp: Add convenience API to obtain remarks
* lang/cpp/src/key.h, lang/cpp/src/key.cpp (UserID::remark): New.

--
A remark made by one key on another is a signature notation on
a user id certification signature with the name "rem@gnupg.org".

This helps with:
GnuPG-Bug-Id: T4734
2019-10-29 16:24:01 +01:00
Andre Heinecke
0224408c63
core: Add cert-notation support and extended-edit
* src/context.h (gpgme_context): Add new flag for extended-edit.
* src/engine-gpg.c (append_args_from_sig_notations): Add flags to
control the kind of notations.
(gpg_edit): Respect extended-edit and notations.
(gpg_encrypt_sign, gpg_sign): Update call to
append_args_from_sig_notations.
* src/gpgme.c (gpgme_set_ctx_flag, gpgme_get_ctx_flag): Support
extended-edit.
* NEWS, doc/gpgme.texi: Mention extended-edit.

--
This provides a way to get the extended key-edit interface without
breaking bad state machines that rely on the current command flow.

A use case for this is to enable multiple local signatures, which
can be used together with annotations for:

GnuPG-Bug-Id: T4734
2019-10-29 16:11:54 +01:00
Andre Heinecke
9d83698818
cpp: Minor coding style fix
--
2019-10-29 11:04:41 +01:00
Andre Heinecke
fe2892618c
core,w32: Initialize dbg_help for socket debugging
* src/w32-io.c (_gpgme_io_select): Initialize dbg_help.

--
This fixes a crash on Windows because dbg_help might
be used unitialized.
2019-10-28 16:02:22 +01:00
Werner Koch
2b2977c215
doc: Remove cruft from a doc entry.
--

Reported-by: dkg@fifthhorseman.net
2019-10-01 08:08:17 +02:00
NIIBE Yutaka
b97434fbf0 json: Fix t-decrypt-verify.out for GnuPG >= 2.3.
* tests/json/t-decrypt-verify.out.json: Remove check with key of
04071FB807287134.

--

GnuPG 2.3 changes how public key decryption works; It collects list of
PUBKEY_ENC packets and then processes an ENCRYPTED* packet.  At the
stage of processing an ENCRYPTED* packet, it checks if private keys
can decrypt any of PUBKEY_ENC packets.  It does not necessarily
examine all of PUBKEY_ENC packets.  Only when it finds a PUBKEY_ENC
packet cannot be decrypted, it reports STATUS_NO_SECKEY with keyid of
that packet.

GnuPG 2.2 or older tries PUBKEY_ENC packets in order, and the first
successful PUBKEY_ENC packet is used.  Rest of PUBKEY_ENC packets are
not examined, but STATUS_NO_SECKEY with keyid is reported even when
there is a valid private key.

Signed-off-by: NIIBE Yutaka <gniibe@fsij.org>
2019-08-06 11:19:59 +09:00
Andre Heinecke
6f4a886b30
core: Fix arg counting in enginge-gpg
* src/engine-gpg.c (build_argv): Properly check for all
arguments and allocate memory for them.

--
This fixes a potential buffer overflow which could be created
by using unusual and partially contradictory options.
Like offline and auto-key-locate together while
using ignore-mdc-error.
As the list of arguments should not be user controlled the
impact of this is very low.

To ensure that this does not happen in the future an
assert is also added with this patch.
2019-07-16 11:39:29 +02:00
NIIBE Yutaka
36428d8cf1 python: doc: Remove generated files, put rules in Makefile.
* lang/python/doc/Makefile.am (EXTRA_DIST): Remove files not
distributed like files under meta.
* Add rules to generate .rst and .texi files.
* lang/python/doc/rst: Remove .rst files to be generated.
* lang/python/doc/texinfo: Remove .texi files to be generated.

GnuPG-bug-id: 4275
Signed-off-by: NIIBE Yutaka <gniibe@fsij.org>
2019-07-12 14:53:55 +09:00
NIIBE Yutaka
d9387650ff python: doc: Add suffix for org files.
Signed-off-by: NIIBE Yutaka <gniibe@fsij.org>
2019-07-12 14:53:31 +09:00
Maximilian Krambach
ed1dffb474 js: improve connection check
--

* Connection.js: In some cases, the browser disconnect does not
  happen inmediately (e.g. wrong extension for the app). I added a
  delay of 25 ms to see if the connection was closed by the browser.
  Also, I tried to make the checkConnection more readable.
2019-07-03 16:19:44 +02:00
Maximilian Krambach
f5e27a12d3 js: Error handling for browser errors
--

* Connection.js
  - Add some meaningful nativeMessaging feedback for failing
    communication due to misconfiguration or other browser-originated
    fails
  - add an "isDisconnected" property
  - "isNativeHostUnknown" tries to match browser's feedback string if
    the browser does not find gpgme-json
* init.js
  - initialization will now reject with a more meaningful error if the
    configuration is not set up or other browser-based errors
    (chrome.runtime.lastError) are present. This should speed up
    the normal initialization (not having to waiting for a timeout
    any more in case of improper setup)
* errors.js
  - CONN_NATIVEMESSAGE: New error that passes the browser's
    nativeMessaging error
  - CONN_NO_CONFIG: native messaging error indicating that the
    nativeMessaging host was not set up properly
* unittests.js:
  - added the "isDisconnected" property to the startup tests
  - added tests for proper behavior of connection checks
2019-06-19 12:58:44 +02:00
Werner Koch
44cedf9796
Post release updates
--
2019-06-13 15:35:58 +02:00
Werner Koch
ea11c2a13c
Release 1.13.1
* configure.ac: Bump LT versions to c=C33/A22/R1 cpp=C16/A10/R0
qt=C10/A3/R4.

Signed-off-by: Werner Koch <wk@gnupg.org>
2019-06-13 15:18:38 +02:00
Werner Koch
7d0a979c07
python: Fix regression in t-decrypt-verify test.
* lang/python/tests/t-decrypt-verify.py: Comment recent changes.
--

Fixes-commit: bd2d282e57
GnuPG-bug-id: 4276
2019-06-13 15:18:36 +02:00
Werner Koch
ad1395f210
python: Set a default-key into gpg.conf for the tests.
* lang/python/tests/Makefile.am (gpg.conf): Set a default key.

--

It seems we need to set a default key because at least t-sign.py does
not specify the key to use and we do not want to rely on the order of
keys in the keyring.

Also
Fixes-commit: f3ca2c9ce9

gpg 2.0 is end-of-life and we don't need these extra options anymore.
In fact they for the use of some gpg version and don't use the version
gpgconf knows about.  This also aligns the python tests to what we use
for the C test suite.

Signed-off-by: Werner Koch <wk@gnupg.org>
2019-06-13 11:56:08 +02:00
Werner Koch
4f11210b21
core: At debug levels up to 9 print only an ascii dump.
* src/debug.c (_gpgme_debug_buffer): Switch between two output
formats.
--

The new format is much more practical than the bunch of hex digits
followed by just 16 ascii chars.  To get the old behaviour use a debug
level of 10.

Signed-off-by: Werner Koch <wk@gnupg.org>
2019-06-13 08:46:16 +02:00
489 changed files with 30530 additions and 15057 deletions

16
AUTHORS
View File

@ -9,20 +9,24 @@ License (software): LGPL-2.1-or-later
License (manual+tools): GPL-3.0-or-later License (manual+tools): GPL-3.0-or-later
GPGME is free software. See the files COPYING for copying conditions. GPGME is free software. See the files COPYING.LESSER and COPYING for
License copyright years may be listed using range notation, e.g., copying conditions, , and LICENSES for notices about contributions
2000-2013, indicating that every year in the range, inclusive, is a that require these additional notices to be distributed. License
copyrightable year that would otherwise be listed individually. copyright years may be listed using range notation, e.g., 2000-2013,
indicating that every year in the range, inclusive, is a copyrightable
year that would otherwise be listed individually.
List of Copyright holders List of Copyright holders
========================= =========================
Copyright (C) 1991-2013 Free Software Foundation, Inc. Copyright (C) 1991-2013 Free Software Foundation, Inc.
Copyright (C) 2000-2001 Werner Koch Copyright (C) 2000-2001 Werner Koch
Copyright (C) 2001-2018 g10 Code GmbH Copyright (C) 2001-2023 g10 Code GmbH
Copyright (C) 2002 Klarälvdalens Datakonsult AB Copyright (C) 2002 Klarälvdalens Datakonsult AB
Copyright (C) 2004-2008 Igor Belyi Copyright (C) 2004-2008 Igor Belyi
Copyright (C) 2002 John Goerzen Copyright (C) 2002 John Goerzen
Copyright (c) 2009 Dave Gamble
Copyright (C) 2014, 2015 Martin Albrecht Copyright (C) 2014, 2015 Martin Albrecht
Copyright (C) 2015, 2018 Ben McGinnes Copyright (C) 2015, 2018 Ben McGinnes
Copyright (C) 2015, 2016, 2018 Copyright (C) 2015, 2016, 2018
@ -39,7 +43,7 @@ FSF <gnu@gnu.org>
src/stpcpy.c, src/w32-ce.c. src/stpcpy.c, src/w32-ce.c.
g10 Code GmbH <code@g10code.com> g10 Code GmbH <code@g10code.com>
- All stuff since mid march 2001. - All stuff since mid March 2001.
Werner Koch <wk@gnupg.org> Werner Koch <wk@gnupg.org>
- Design and most stuff. - Design and most stuff.

38
LICENSES Normal file
View File

@ -0,0 +1,38 @@
Additional license notices for GPGME. -*- org -*-
This file contains the copying permission notices for various files in
the GPGME distribution which are not covered by the GNU Lesser
General Public License (LGPL) or the GNU General Public License (GPL).
These notices all require that a copy of the notice be included
in the accompanying documentation and be distributed with binary
distributions of the code, so be sure to include this file along
with any binary distributions derived from the GNU C Library.
* MIT License
For files:
- cJSON.c, cJSON.h
#+begin_quote
Copyright (c) 2009 Dave Gamble
Permission is hereby granted, free of charge, to any person obtaining
a opy of this software and associated documentation files (the
"Software"), to eal in the Software without restriction, including
without limitation the ights to use, copy, modify, merge, publish,
distribute, sublicense, and/or sell copies of the Software, and to
permit persons to whom the Software is furnished to do so, subject to
the following conditions:
The above copyright notice and this permission notice shall be
included in all copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
OF CONTRACT, TORT OR OTHERWISE, ARISING ROM, OUT OF OR IN CONNECTION
WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
#+end_quote

View File

@ -20,14 +20,14 @@
## Process this file with automake to produce Makefile.in ## Process this file with automake to produce Makefile.in
# Location of the released tarball archives. Note that this is an # Location of the released tarball archives. This is prefixed by
# internal archive and before uploading this to the public server, # the variable RELEASE_ARCHIVE in ~/.gnupg-autogen.rc. For example:
# manual tests should be run and the git release tat set and pushed. # RELEASE_ARCHIVE=user@host:archive/tarballs
# Adjust as needed. RELEASE_ARCHIVE_SUFFIX = gpgme
RELEASE_ARCHIVE_DIR = wk@vigenere:tarballs/gpgme/ # The variable RELEASE_SIGNKEY in ~/.gnupg-autogen.rc is used
# to specify the key for signing. For example:
# RELEASE_SIGNKEY=D8692123C4065DEA5E0F3AB5249B39D24F25E3B6
# The key used to sign the released sources. Adjust as needed.
RELEASE_SIGNING_KEY = D8692123C4065DEA5E0F3AB5249B39D24F25E3B6
# Autoconf flags # Autoconf flags
ACLOCAL_AMFLAGS = -I m4 ACLOCAL_AMFLAGS = -I m4
@ -36,8 +36,11 @@ DISTCHECK_CONFIGURE_FLAGS =
EXTRA_DIST = autogen.sh autogen.rc gpgme.spec.in \ EXTRA_DIST = autogen.sh autogen.rc gpgme.spec.in \
ChangeLog-2011 m4/ChangeLog-2011 \ ChangeLog-2011 m4/ChangeLog-2011 \
conf/whatisthis VERSION build-aux/libtool-patch.sed \
conf/whatisthis VERSION LICENSES
# This artificial line is to put a dependency to conf/config.h for 'all'
BUILT_SOURCES = conf/config.h
if RUN_GPG_TESTS if RUN_GPG_TESTS
tests = tests tests = tests
@ -97,7 +100,7 @@ release:
cd $(abs_top_builddir); \ cd $(abs_top_builddir); \
rm -rf dist; mkdir dist ; cd dist ; \ rm -rf dist; mkdir dist ; cd dist ; \
$(abs_top_srcdir)/configure --enable-maintainer-mode; \ $(abs_top_srcdir)/configure --enable-maintainer-mode; \
$(MAKE) distcheck TESTFLAGS=--parallel; \ $(MAKE) distcheck; \
echo "/* Build finished at $$(date -uIseconds) */" ;\ echo "/* Build finished at $$(date -uIseconds) */" ;\
echo "/*" ;\ echo "/*" ;\
echo " * Please run the final step interactively:" ;\ echo " * Please run the final step interactively:" ;\
@ -107,20 +110,32 @@ release:
sign-release: sign-release:
+(set -e; \ +(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; \
exit 2;\
fi;\
myarchive="$$x/$(RELEASE_ARCHIVE_SUFFIX)";\
x=$$(grep '^RELEASE_SIGNKEY=' $$HOME/.gnupg-autogen.rc|cut -d= -f2);\
if [ -z "$$x" ]; then \
echo "error: RELEASE_SIGNKEY missing in ~/.gnupg-autogen.rc">&2; \
exit 2;\
fi;\
mysignkey="$$x";\
files1="$(RELEASE_NAME).tar.bz2" ;\ files1="$(RELEASE_NAME).tar.bz2" ;\
files2="$(RELEASE_NAME).tar.bz2.sig \ files2="$(RELEASE_NAME).tar.bz2.sig \
$(RELEASE_NAME).swdb \ $(RELEASE_NAME).swdb \
$(RELEASE_NAME).buildlog" ;\ $(RELEASE_NAME).buildlog" ;\
echo "/* Signing the source tarball ..." ;\ echo "/* Signing the source tarball ..." ;\
gpg -sbu $(RELEASE_SIGNING_KEY) $(RELEASE_NAME).tar.bz2 ;\ gpg -sbu $$mysignkey $(RELEASE_NAME).tar.bz2 ;\
cat $(RELEASE_NAME).swdb >swdb.snippet;\ cat $(RELEASE_NAME).swdb >swdb.snippet;\
echo >>swdb.snippet ;\ echo >>swdb.snippet ;\
sha1sum $${files1} >>swdb.snippet ;\ sha1sum $${files1} >>swdb.snippet ;\
cat "../$(RELEASE_NAME).buildlog" swdb.snippet \ cat "../$(RELEASE_NAME).buildlog" swdb.snippet \
| gzip >$(RELEASE_NAME).buildlog ;\ | gzip >$(RELEASE_NAME).buildlog ;\
echo "Copying to local archive ..." ;\ echo "Copying to local archive ..." ;\
scp -p $${files1} $${files2} $(RELEASE_ARCHIVE_DIR)/ || true;\ scp -p $${files1} $${files2} $$myarchive/ || true;\
echo "Uploading documentation ..." ;\ echo "Uploading documentation ..." ;\
$(MAKE) -C doc online; \ $(MAKE) -C doc online; \
echo '/*' ;\ echo '/*' ;\

716
NEWS
View File

@ -1,34 +1,714 @@
Noteworthy changes in version 1.13.1 (unreleased) Noteworthy changes in version 1.24.0 (unrelease)
------------------------------------------------- -------------------------------------------------
* Python: Fix DecryptionError Exception. [#4478] * Extended gpgme_op_decrypt* and gpgme_op_verify* to allow writing the
output directly to a file. [T6550]
* Python: No longer raises BadSignatures from * Extended gpgme_op_encrypt*, gpgme_op_encrypt_sign*, and gpgme_op_sign*
decrypt(verify=True). [#4276] to allow reading the input data directly from a file. [T6550]
* cpp: gpgme_set_global_flag is now wrapped. * Add information about designated revocation keys. [T7118]
[#4471]
* Fixed a crash introduced in 1.13.0 when working * New context flag "import-options". [T7152]
with S/MIME. [#4456]
* w32: Improved handling of unicode install paths. * cpp: Provide information about designated revocation keys for a Key.
[#4453] [T7118]
* w32: The gpgme_io_spawn error message is now * cpp: Add safer member function returning text describing an error.
only shown once. [#4453] [T5960]
* w32: Fixed format string errors introduced in * qt: Build QGpgME for Qt 5 and Qt 6 simultaneously. [T7205]
1.13.0 that could cause crashes. [#4440]
* w32: Fixed an error in the new diagnostic * qt: Install headers for Qt 5 and Qt 6 in separate folders. [T7161]
gpgsm support introduced in 1.13.0 that caused
crashes in low fd scenarios. [#4439] * qt: Allow reading the data to decrypt/encrypt/sign/verify directly from
files. [T6550]
* qt: Allow writing the decrypted/encrypted/signed/verified data directly
to files. [T6550]
* qt: Allow specifying import options when importing keys. [T7152]
* qt: Allow appending a detached signature to an existing file. [T6867]
* Interface changes relative to the 1.23.2 release:
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
GPGME_ENCRYPT_FILE NEW.
GPGME_SIG_MODE_FILE NEW.
gpgme_key_t EXTENDED: New field 'revkeys'.
gpgme_revocation_key_t NEW.
gpgme_set_ctx_flag EXTENDED: New flag 'import-options'.
cpp: Context::EncryptFile NEW.
cpp: SignatureMode::SignFile NEW.
cpp: RevocationKey NEW.
cpp: Key::revocationKey NEW.
cpp: Key::numRevocationKeys NEW.
cpp: Key::revocationKeys NEW.
cpp: Error::asStdString NEW.
cpp: Error::asString DEPRECATED.
qt: DecryptVerifyJob::setInputFile NEW.
qt: DecryptVerifyJob::inputFile NEW.
qt: DecryptVerifyJob::setOutputFile NEW.
qt: DecryptVerifyJob::outputFile NEW.
qt: EncryptJob::setRecipients NEW.
qt: EncryptJob::recipients NEW.
qt: EncryptJob::setInputFile NEW.
qt: EncryptJob::inputFile NEW.
qt: EncryptJob::setOutputFile NEW.
qt: EncryptJob::outputFile NEW.
qt: EncryptJob::setEncryptionFlags NEW.
qt: EncryptJob::encryptionFlags NEW.
qt: SignEncryptJob::setSigners NEW.
qt: SignEncryptJob::signers NEW.
qt: SignEncryptJob::setRecipients NEW.
qt: SignEncryptJob::recipients NEW.
qt: SignEncryptJob::setInputFile NEW.
qt: SignEncryptJob::inputFile NEW.
qt: SignEncryptJob::setOutputFile NEW.
qt: SignEncryptJob::outputFile NEW.
qt: SignEncryptJob::setEncryptionFlags NEW.
qt: SignEncryptJob::encryptionFlags NEW.
qt: SignJob::setSigners NEW.
qt: SignJob::signers NEW.
qt: SignJob::setInputFile NEW.
qt: SignJob::inputFile NEW.
qt: SignJob::setOutputFile NEW.
qt: SignJob::outputFile NEW.
qt: SignJob::setSigningFlags NEW.
qt: SignJob::signingFlags NEW.
qt: SignJob::setAppendSignature NEW.
qt: SignJob::appendSignatureEnabled NEW.
qt: VerifyDetachedJob::setSignatureFile NEW.
qt: VerifyDetachedJob::signatureFile NEW.
qt: VerifyDetachedJob::setSignedFile NEW.
qt: VerifyDetachedJob::signedFile NEW.
qt: VerifyOpaqueJob::setInputFile NEW.
qt: VerifyOpaqueJob::inputFile NEW.
qt: VerifyOpaqueJob::setOutputFile NEW.
qt: VerifyOpaqueJob::outputFile NEW.
qt: ImportJob::setImportOptions NEW.
qt: ImportJob::importOptions NEW.
Noteworthy changes in version 1.23.2 (2023-11-28)
-------------------------------------------------
* Preserve more specific existing failure code. [T6575]
* qt: Start dirmngr with gpgconf to avoid multiple instances. [T6833]
* qt: On Windows, use UTF-8 when logging the error text. [T5960]
* qt: Remove left-over partial files more persistently. [T6584]
* qt: Use a temporary file name when creating signed or encrypted
archives. [T6721]
* qt: Build Qt 6 bindings with -fPIC if requested or Qt 6 was built with
this flag. [T6781]
Notes:
~~~~~~
qt: DefaultKeyGenerationJob DEPRECATED.
[c=C43/A32/R1 cpp=C26/A20/R1 qt=C20/A5/R1]
Release-info: https://dev.gnupg.org/T6782
Noteworthy changes in version 1.23.1 (2023-10-27)
-------------------------------------------------
* w32: Change gpgme-w32-spawn to use Unicode arguments. [T6728]
[c=C43/A32/R0 cpp=C26/A20/R0 qt=C20/A5/R0]
Release-info: https://dev.gnupg.org/T6774
Noteworthy changes in version 1.23.0 (2023-10-25)
-------------------------------------------------
* Support GPGME_ENCRYPT_ALWAYS_TRUST also for S/MIME. [T6559]
* New keylist mode GPGME_KEYLIST_MODE_WITH_V5FPR. [T6705]
* New key capability flags has_*. [T6748]
* gpgme-tool: Support use of Windows HANDLE. [T6634]
* qt: Support refreshing keys via WKD. [T6672]
* qt: Handle cancel in changeexpiryjob. [T6754]
* Interface changes relative to the 1.22.0 release:
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
GPGME_KEYLIST_MODE_WITH_V5FPR NEW.
gpgme_key_t EXTENDED: New field has_encrypt.
gpgme_key_t EXTENDED: New field has_sign.
gpgme_key_t EXTENDED: New field has_certify.
gpgme_key_t EXTENDED: New field has_authenticate.
cpp: Key::canCertify NEW.
cpp: Key::canSign NEW.
cpp: Key::canEncrypt NEW.
cpp: Key::canAuthenticate NEW.
qt: Protocol::wkdRefreshJob NEW.
qt: WKDRefreshJob NEW.
[c=C43/A32/R0 cpp=C26/A20/R0 qt=C20/A5/R0]
Release-info: https://dev.gnupg.org/T6774
Noteworthy changes in version 1.22.0 (2023-08-21)
-------------------------------------------------
* Prevent wrong plaintext when verifying clearsigned signature. [T6622]
* Return bad data error instead of general error on unexpected data.
[T6617]
* Take care of offline mode for all operations of gpgsm engine.
[T6648]
* Prepare the use of the forthcoming libassuan version 3.
* New configure option --with-libtool-modification. [T6619]
* cpp: Expose gpgme_decrypt_result_t.is_mime. [T6199]
* qt: Clean up after failure or cancel of sign/encrypt archive
operation. [T6584]
* qt: Add setInputEncoding to QGpgMe::EncryptJob. [T6166]
* qt: Make toLogString helper public. [T6584]
* Interface changes relative to the 1.21.0 release:
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
qt: EncryptJob::setInputEncoding NEW.
qt: DecryptionResult::isMime NEW.
qt: toLogString NEW.
[c=C42/A31/R0 cpp=C25/A19/R0 qt=C19/A4/R0]
Release-info: https://dev.gnupg.org/T6668
Noteworthy changes in version 1.21.0 (2023-07-07)
-------------------------------------------------
* Extended gpgme_op_encrypt, gpgme_op_encrypt_sign, and gpgme_op_sign
to allow writing the output directly to a file. [T6530]
* Extended gpgme_op_decrypt and gpgme_op_verify to allow reading the
input data directly from files. [T6530]
* For key signing and uid revoking allow an empty user id.
[rMfbc3963d62]
* Pass an input-size-hint also to the gpgsm engine. [T6534]
* qt: Allow writing the created archives directly to a
file. [T6530]
* qt: Allow reading the signed/encrypted archive to decrypt
or verify directly from a file. [T6530]
* qt: Qt Jobs working with QIODeviceDataProvider now properly
handle input-size hints and progress for files larger.
2^32 bytes in 32 bit builds. [T6534]
* cpp: Error::isCanceled now also returns true for error code
GPG_ERR_FULLY_CANCELED. [T6510]
* python: Fix wrong use of write. [T6501]
* Interface changes relative to the 1.20.0 release:
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
cpp: Data::setFlag NEW.
cpp: Data::setSizeHint NEW.
qt: Job::startIt NEW.
qt: DecryptVerifyArchiveJob::setInputFile NEW.
qt: DecryptVerifyArchiveJob::inputFile NEW.
qt: EncryptArchiveJob::setRecipients NEW.
qt: EncryptArchiveJob::recipients NEW.
qt: EncryptArchiveJob::setInputPaths NEW.
qt: EncryptArchiveJob::inputPaths NEW.
qt: EncryptArchiveJob::setOutputFile NEW.
qt: EncryptArchiveJob::outputFile NEW.
qt: EncryptArchiveJob::setEncryptionFlags NEW.
qt: EncryptArchiveJob::encryptionFlags NEW.
qt: SignArchiveJob::setSigners NEW.
qt: SignArchiveJob::signers NEW.
qt: SignArchiveJob::setInputPaths NEW.
qt: SignArchiveJob::inputPaths NEW.
qt: SignArchiveJob::setOutputFile NEW.
qt: SignArchiveJob::outputFile NEW.
qt: SignEncryptArchiveJob::setSigners NEW.
qt: SignEncryptArchiveJob::signers NEW.
qt: SignEncryptArchiveJob::setRecipients NEW.
qt: SignEncryptArchiveJob::recipients NEW.
qt: SignEncryptArchiveJob::setInputPaths NEW.
qt: SignEncryptArchiveJob::inputPaths NEW.
qt: SignEncryptArchiveJob::setOutputFile NEW.
qt: SignEncryptArchiveJob::outputFile NEW.
qt: SignEncryptArchiveJob::setEncryptionFlags NEW.
qt: SignEncryptArchiveJob::encryptionFlags NEW.
[c=C41/A30/R0 cpp=C24/A18/R0 qt=C18/A3/R0]
Release-info: https://dev.gnupg.org/T6585
Noteworthy changes in version 1.20.0 (2023-04-20)
-------------------------------------------------
* On Windows, the gettext functions provided by gpgrt are switched
into utf8 mode, so that all localized texts returned by GpgME or
gpgrt, e.g. the texts for error codes are now UTF-8 encoded.
[T5960]
* Key::canSign now returns false for OpenPGP keys without signing
(sub)key. [T6456]
* The new macOS Homebrew location is now by default supported.
[T6440]
* Fix regression in 1.19.0. [rMb608c084b9]
* Fix invocation of gpgtar on Windows. [rM0c29119e06]
* Interface changes relative to the 1.19.0 release:
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
gpgme_subkey_t EXTENDED: New field 'can_renc'.
gpgme_subkey_t EXTENDED: New field 'can_timestamp'.
gpgme_subkey_t EXTENDED: New field 'is_group_owned'.
cpp: Subkey::canRenc NEW.
cpp: Subkey::canTimestamp NEW.
cpp: Subkey::isGroupOwned NEW.
cpp: Key::canReallySign DEPRECATED.
[c=C40/A29/R0 cpp=C23/A17/R0 qt=C17/A2/R1]
Release-info: https://dev.gnupg.org/T6463
Noteworthy changes in version 1.19.0 (2023-03-17)
-------------------------------------------------
* New convenience option --identify for gpgme-json.
* New context flag "no-auto-check-trustdb". [T6261]
* Optionally, build QGpgME for Qt 6
* Support component "gpgtar-name" in gpgme_get_dirinfo. [T6342]
* Extended gpgme_op_encrypt*, gpgme_op_encrypt_sign*, and
gpgme_op_sign* to allow creating an encrypted and/or signed
archive. [T6342]
* Extended gpgme_op_decrypt*, gpgme_op_decrypt_verify*, and gpgme_op_verify*
to allow extracting an encrypted and/or signed archive. [T6342]
* cpp: Handle error when trying to sign expired keys. [T6155]
* cpp: Support encryption flags ThrowKeyIds, EncryptWrap, and WantAddress.
[T6359]
* cpp, qt: Fix building with C++11. [T6141]
* qt: Fix problem with expiration dates after 2038-01-19 on 32-bit systems
when adding an existing subkey to another key. [T6137]
* cpp: Allow setting the curve to use when generating ECC keys
for smart cards. [T4429]
* qt: Extend ListAllKeysJob to allow disabling the automatic trust database
check when listing all keys. [T6261]
* qt: Allow deferred start of import jobs. [T6323]
* qt: Support creating and extracting signed and encrypted archives. [T6342]
* Interface changes relative to the 1.18.0 release:
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
gpgme_get_ctx_flag EXTENDED: New flag 'no-auto-check-trustdb'.
gpgme_set_ctx_flag EXTENDED: New flag 'no-auto-check-trustdb'.
GPGME_DECRYPT_ARCHIVE NEW.
GPGME_ENCRYPT_ARCHIVE NEW.
GPGME_SIG_MODE_ARCHIVE NEW.
GPGME_VERIFY_ARCHIVE NEW.
gpgme_verify_flags_t NEW.
gpgme_op_verify_ext_start NEW.
gpgme_op_verify_ext NEW.
cpp: GpgGenCardKeyInteractor::Curve NEW.
cpp: GpgGenCardKeyInteractor::setCurve NEW.
cpp: Context::WantAddress NEW.
cpp: Context::DecryptArchive NEW.
cpp: Context::EncryptArchive NEW.
cpp: SignArchive NEW.
cpp: Data::setFileName EXTENDED: New overload
qt: ListAllKeysJob::Option NEW.
qt: ListAllKeysJob::Options NEW.
qt: ListAllKeysJob::setOptions NEW.
qt: ListAllKeysJob::options NEW.
qt: Job::startNow NEW.
qt: ImportJob::startLater NEW.
qt: FileListDataProvider NEW.
qt: DecryptVerifyArchiveJob NEW.
qt: EncryptArchiveJob NEW.
qt: SignArchiveJob NEW.
qt: SignEncryptArchiveJob NEW.
qt: Protocol::decryptVerifyArchiveJob NEW.
qt: Protocol::encryptArchiveJob NEW.
qt: Protocol::signArchiveJob NEW.
qt: Protocol::signEncryptArchiveJob NEW.
qt: Job::jobProgress NEW.
qt: Job::rawProgress NEW.
qt: Job::progress DEPRECATED.
[c=C39/A28/R0 cpp=C22/A16/R0 qt=C17/A2/R0]
Release-info: https://dev.gnupg.org/T6341
Noteworthy changes in version 1.18.0 (2022-08-10)
-------------------------------------------------
* New keylist mode to force refresh via external methods. [T5951]
* The keylist operations now create an import result to report the
result of the locate keylist modes. [T5951]
* core: Return BAD_PASSPHRASE error code on symmetric decryption
failure. [T5939]
* cpp, qt: Do not export internal symbols anymore. [T5906]
* cpp, qt: Support revocation of own OpenPGP keys. [T5904]
* qt: The file name of (signed and) encrypted data can now be set. [T6056]
* cpp, qt: Support setting the primary user ID. [T5938]
* python: Fix segv(NULL) when inspecting contect after exeception. [T6060]
* Interface changes relative to the 1.17.1 release:
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
GPGME_KEYLIST_MODE_FORCE_EXTERN NEW.
GPGME_KEYLIST_MODE_LOCATE_EXTERNAL NEW.
cpp: RevocationReason NEW.
cpp: GpgRevokeKeyEditInteractor NEW.
cpp: Result::setError NEW.
cpp: KeyListMode::ForceExtern NEW.
cpp: KeyListMode::LocateExternal NEW.
cpp: KeyListMode::KeyListModeMask NEW.
cpp: ImportResult::mergeWith NEW.
cpp: KeyListModeSaver NEW.
cpp: Context::setPrimaryUid NEW.
cpp: Context::startSetPrimaryUid NEW.
qt: RevokeKeyJob NEW.
qt: Protocol::revokeKeyJob NEW.
qt: EncryptJob::setFileName NEW.
qt: EncryptJob::fileName NEW.
qt: SignEncryptJob::setFileName NEW.
qt: SignEncryptJob::fileName NEW.
qt: SetPrimaryUserIDJob NEW.
qt: Protocol::setPrimaryUserIDJob NEW.
[c=C38/A27/R0 cpp=C21/A15/R0 qt=C16/A1/R0]
Release-info: https://dev.gnupg.org/T6128
Noteworthy changes in version 1.17.1 (2022-03-06)
-------------------------------------------------
* qt: Fix a bug in the ABI compatibility of 1.17.0. [T5834]
[c=C37/A26/R0 cpp=C20/A14/R0 qt=C15/A0/R0]
Release-info: https://dev.gnupg.org/T5872
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: Support WKD lookup without implicit import. [#5728]
* qt: Allow specifying an import filter when importing keys. [#5739]
* 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: CryptoConfigEntry::defaultValue NEW.
qt: WKDLookupJob NEW.
qt: WKDLookupResult NEW.
qt: Protocol::wkdLookupJob NEW.
qt: ImportJob::setKeyOrigin NEW.
qt: ImportJob::keyOrigin NEW.
qt: ImportJob::keyOriginUrl NEW.
qt: setImportFilter NEW.
qt: importFilter 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)
-------------------------------------------------
* New context flag "cert-expire". [#5505]
* New data flags "io-buffer-size" and "sensitive". [#5478]
* Increase I/O buffer size from 512 to 4k under Windows.
* cpp,qt: Add support for trust signatures. [#5421]
* qt: Add support for flags in LDAP server options. [#5217]
* qt: Fix too high memory consumption due to QProcess. [#5475]
* qt: Do not set empty base DN as query of keyserver URL. [#5465]
* qt: Extend SignKeyJob to create signatures with expiration date.
[5506]
* python: New optional parameter filter_signatures for decrypt.
[#5292]
* Interface changes relative to the 1.15.1 release:
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
gpgme_set_ctx_flag EXTENDED: New flag 'cert-expire'.
cpp: SignKeyJob::setTrustSignature NEW.
cpp: TrustSignatureTrust NEW.
cpp: GpgSignKeyEditInteractor::setTrustSignatureTrust NEW.
cpp: GpgSignKeyEditInteractor::setTrustSignatureDepth NEW.
cpp: GpgSignKeyEditInteractor::setTrustSignatureScope NEW.
cpp: UserID::Signature::isTrustSignature NEW.
cpp: UserID::Signature::trustValue NEW.
cpp: UserID::Signature::trustDepth NEW.
cpp: UserID::Signature::trustScope NEW.
gpgme_key_sig_t EXTENDED: New field 'trust_depth'.
gpgme_key_sig_t EXTENDED: New field 'trust_value'.
gpgme_key_sig_t EXTENDED: New field 'trust_scope'.
GPGME_KEYSIGN_FORCE NEW.
qt: CryptoConfig::entry CHANGED: Added overload; deprecated old
[c=C36/A25/R0 cpp=C19/A13/R0 qt=C13/A6/R0]
Release-info: https://dev.gnupg.org/T5499
Noteworthy changes in version 1.15.1 (2021-01-08)
-------------------------------------------------
* Fix another bug in the secret key export. [#5046]
* Make listing of signatures work if only secret keys are listed. [#3580]
* Fix build problem on FreeBSD. [a6220adf30]
* qt: Avoid empty "rem@gnupg.org" signature notations. [#5142]
* python: Fix key_export functions. [#5149]
[c=C35/A24/R1 cpp=C18/A12/R1 qt=C12/A5/R1]
Release-info: https://dev.gnupg.org/T5225
Noteworthy changes in version 1.15.0 (2020-11-12)
-------------------------------------------------
* New function gpgme_op_setexpire to make changing the expiration
easier (requires GnuPG 2.1.22). [#4999]
* New function gpgme_op_revsig to revoke key signatures (requires
GnuPG 2.2.24). [#5094]
* Support exporting secret keys. [#5046]
* cpp: Support for set expire operations in the C++ bindings. [#5003]
* cpp: Support for revoking key signatures in the C++ bindings. [#5094]
* qt: Extended ChangeExpiryJob to support changing the expiry of
subkeys. [#4717]
* qt: Extended QuickJob to support revoking of key signatures. [#5094]
* qt: Added QDebug stream operator for GpgME::Error.
* Require a somewhat newer version of libgpg-error (1.36).
* Interface changes relative to the 1.14.0 release:
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
gpgme_op_setexpire_start NEW.
gpgme_op_setexpire NEW.
gpgme_op_revsig_start NEW.
gpgme_op_revsig NEW.
GPGME_REVSIG_LFSEP NEW.
cpp: Context::setExpire NEW.
cpp: Context::startSetExpire NEW.
cpp: EngineInfo::Version::operator<= NEW.
cpp: EngineInfo::Version::operator>= NEW.
cpp: EngineInfo::Version::operator!= NEW.
cpp: StatusConsumer NEW.
cpp: StatusConsumerAssuanTransaction NEW.
cpp: Context::cancelPendingOperationImmediately NEW.
cpp: Context::revokeSignature NEW.
cpp: Context::startRevokeSignature NEW.
cpp: UserID::Signature::operator< NEW.
qt: operator<<(QDebug debug, const GpgME::Error &err) NEW.
qt: QuickJob::startRevokeSignature NEW.
qt: QuickJob::result CHANGED: Made params 'auditLogAsHtml'
and 'auditLogError' optional.
[c=C35/A24/R0 cpp=C18/A12/R0 qt=C12/A5/R0]
Release-info: https://dev.gnupg.org/T5131
Noteworthy changes in version 1.14.0 (2020-07-16)
-------------------------------------------------
* New keylist mode to force the engine to return the keygrip. [#4820]
* New export mode to export as OpenSSH public key. [#4310]
* New context flag "extended-edit" to enable expert key edit. [#4734]
* Deprecate the anyway non working trustlist functions. [#4834]
* cpp: Add convenience API to obtain remarks. [#4734]
* cpp: The sign key edit-interactor now supports multiple signatures
from the same key. [#4734]
* qt: Extended signkeyjob to handle remarks and multiple signatures.
[#4734]
* qt: Added job API for gpg-card.
* qt: The logging category has been changed to gpg.qgpgme to be more
consistent with other qt logging categories.
* Interface changes relative to the 1.13.1 release:
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
GPGME_KEYLIST_MODE_WITH_KEYGRIP NEW.
GPGME_EXPORT_MODE_SSH NEW.
gpgme_user_id_t EXTENDED: New field 'uidhash'.
cpp: UserID::remark NEW.
cpp: UserID::remarks NEW.
cpp: GpgSignKeyEditInteractor::setDupeOk NEW.
cpp: Context::exportPublicKeys EXTENDED: New param 'flags'.
cpp: Context::startPublicKeyExport EXTENDED: New param 'flags'.
cpp: Context::ExportMode NEW.
qt: SignKeyJob::setDupeOk NEW.
qt: SignKeyJob::setRemark NEW.
qt: GpgCardJob NEW.
qt: ExportJob::setExportFlags NEW.
[c=C34/A23/R0 cpp=C17/A11/R0 qt=C11/A4/R0]
Release-info: https://dev.gnupg.org/T4996
Noteworthy changes in version 1.13.1 (2019-06-13)
-------------------------------------------------
* cpp: gpgme_set_global_flag is now wrapped. [#4471]
* w32: Improved handling of unicode install paths. [#4453]
* w32: The gpgme_io_spawn error message is now only shown once. [#4453]
* Fixed a crash introduced in 1.13.0 when working with S/MIME. [#4556]
* w32: Fixed format string errors introduced in 1.13.0 that could
cause crashes. [#4440]
* w32: Fixed an error in the new diagnostic gpgsm support introduced
in 1.13.0 that caused crashes in low fd scenarios. [#4439]
* python: Fixed a DecryptionError Exception. [#4478]
* python: No longer raises BadSignatures from decrypt(verify=True).
[#4276]
* Interface changes relative to the 1.13.0 release: * Interface changes relative to the 1.13.0 release:
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
cpp: setGlobalFlag NEW. cpp: setGlobalFlag NEW.
[c=C33/A22/R1 cpp=C16/A10/R0 qt=C10/A3/R4]
Release-info: https://dev.gnupg.org/T4551
Noteworthy changes in version 1.13.0 (2019-03-26) Noteworthy changes in version 1.13.0 (2019-03-26)
------------------------------------------------- -------------------------------------------------
@ -63,7 +743,7 @@ Noteworthy changes in version 1.13.0 (2019-03-26)
* Several fixes to the Common Lisp bindings. * Several fixes to the Common Lisp bindings.
* Fixed minor bugs in gpgme-json. [#4331,#4341,#4342,#4343 * Fixed minor bugs in gpgme-json. [#4331,#4341,#4342,#4343]
* Require trace level 8 to dump all I/O data. * Require trace level 8 to dump all I/O data.

8
README
View File

@ -1,7 +1,7 @@
GPGME - GnuPG Made Easy GPGME - GnuPG Made Easy
--------------------------- ---------------------------
Copyright 2001-2018 g10 Code GmbH Copyright 2001-2023 g10 Code GmbH
This file is free software; as a special exception the author gives This file is free software; as a special exception the author gives
unlimited permission to copy and/or distribute it, with or without unlimited permission to copy and/or distribute it, with or without
@ -41,11 +41,11 @@ See the file INSTALL for generic installation instructions.
Check that you have unmodified sources. See below on how to do this. Check that you have unmodified sources. See below on how to do this.
Don't skip it - this is an important step! Don't skip it - this is an important step!
To build GPGME, you need to install libgpg-error (>= 1.24) and To build GPGME, you need to install libgpg-error (>= 1.36) and
Libassuan (>= 2.4.2). Libassuan (>= 2.4.2).
For support of the OpenPGP and the CMS protocols, you should use the For support of the OpenPGP and the CMS protocols, you should use at
latest version of GnuPG (>= 2.1.18) , available at: least GnuPG version 2.2.41 or 2.4.3, available at:
https://gnupg.org/ftp/gcrypt/gnupg/. https://gnupg.org/ftp/gcrypt/gnupg/.
For building the Git version of GPGME please see the file README.GIT For building the Git version of GPGME please see the file README.GIT

View File

@ -11,4 +11,4 @@ case "$myhost" in
esac esac
final_info="./configure --enable-maintainer-mode && make" final_info="mkdir build && cd build && ../configure --enable-maintainer-mode && make"

View File

@ -1,6 +1,6 @@
#! /bin/sh #! /bin/sh
# autogen.sh # autogen.sh
# Copyright (C) 2003, 2014, 2017, 2018 g10 Code GmbH # Copyright (C) 2003, 2014, 2017, 2018, 2022 g10 Code GmbH
# #
# This file is free software; as a special exception the author gives # This file is free software; as a special exception the author gives
# unlimited permission to copy and/or distribute it, with or without # unlimited permission to copy and/or distribute it, with or without
@ -15,7 +15,7 @@
# configure it for the respective package. It is maintained as part of # configure it for the respective package. It is maintained as part of
# GnuPG and source copied by other packages. # GnuPG and source copied by other packages.
# #
# Version: 2018-07-10 # Version: 2023-03-15
configure_ac="configure.ac" configure_ac="configure.ac"
@ -137,8 +137,6 @@ extraoptions=
# List of optional variables sourced from autogen.rc and ~/.gnupg-autogen.rc # List of optional variables sourced from autogen.rc and ~/.gnupg-autogen.rc
w32_toolprefixes= w32_toolprefixes=
w32_extraoptions= w32_extraoptions=
w32ce_toolprefixes=
w32ce_extraoptions=
w64_toolprefixes= w64_toolprefixes=
w64_extraoptions= w64_extraoptions=
amd64_toolprefixes= amd64_toolprefixes=
@ -146,7 +144,6 @@ amd64_toolprefixes=
# What follows are variables which are sourced but default to # What follows are variables which are sourced but default to
# environment variables or lacking them hardcoded values. # environment variables or lacking them hardcoded values.
#w32root= #w32root=
#w32ce_root=
#w64root= #w64root=
#amd64root= #amd64root=
@ -167,11 +164,6 @@ case "$1" in
myhost="w32" myhost="w32"
shift shift
;; ;;
--build-w32ce)
myhost="w32"
myhostsub="ce"
shift
;;
--build-w64) --build-w64)
myhost="w32" myhost="w32"
myhostsub="64" myhostsub="64"
@ -203,7 +195,7 @@ if [ "$myhost" = "git-build" ]; then
die_p die_p
make || fatal "error running make" make || fatal "error running make"
die_p die_p
make check || fatal "error running male check" make check || fatal "error running make check"
die_p die_p
exit 0 exit 0
fi fi
@ -241,10 +233,12 @@ if [ "$myhost" = "find-version" ]; then
if [ -z "$micro" ]; then if [ -z "$micro" ]; then
matchstr1="$package-$major.[0-9]*" matchstr1="$package-$major.[0-9]*"
matchstr2="$package-$major-base" matchstr2="$package-$major-base"
matchstr3=""
vers="$major.$minor" vers="$major.$minor"
else else
matchstr1="$package-$major.$minor.[0-9]*" matchstr1="$package-$major.$minor.[0-9]*"
matchstr2="$package-$major.$minor-base" matchstr2="$package-$major.[0-9]*-base"
matchstr3="$package-$major-base"
vers="$major.$minor.$micro" vers="$major.$minor.$micro"
fi fi
@ -252,13 +246,22 @@ if [ "$myhost" = "find-version" ]; then
if [ -e .git ]; then if [ -e .git ]; then
ingit=yes ingit=yes
tmp=$(git describe --match "${matchstr1}" --long 2>/dev/null) tmp=$(git describe --match "${matchstr1}" --long 2>/dev/null)
tmp=$(echo "$tmp" | sed s/^"$package"//)
if [ -n "$tmp" ]; then if [ -n "$tmp" ]; then
tmp=$(echo "$tmp" | sed s/^"$package"// \ tmp=$(echo "$tmp" | sed s/^"$package"// \
| awk -F- '$3!=0 && $3 !~ /^beta/ {print"-beta"$3}') | awk -F- '$3!=0 && $3 !~ /^beta/ {print"-beta"$3}')
else else
tmp=$(git describe --match "${matchstr2}" --long 2>/dev/null \ # (due tof "-base" in the tag we need to take the 4th field)
| awk -F- '$4!=0{print"-beta"$4}') tmp=$(git describe --match "${matchstr2}" --long 2>/dev/null)
if [ -n "$tmp" ]; then
tmp=$(echo "$tmp" | sed s/^"$package"// \
| awk -F- '$4!=0 && $4 !~ /^beta/ {print"-beta"$4}')
elif [ -n "${matchstr3}" ]; then
tmp=$(git describe --match "${matchstr3}" --long 2>/dev/null)
if [ -n "$tmp" ]; then
tmp=$(echo "$tmp" | sed s/^"$package"// \
| awk -F- '$4!=0 && $4 !~ /^beta/ {print"-beta"$4}')
fi
fi
fi fi
[ -n "$tmp" ] && beta=yes [ -n "$tmp" ] && beta=yes
rev=$(git rev-parse --short HEAD | tr -d '\n\r') rev=$(git rev-parse --short HEAD | tr -d '\n\r')
@ -294,12 +297,6 @@ fi
# ****************** # ******************
if [ "$myhost" = "w32" ]; then if [ "$myhost" = "w32" ]; then
case $myhostsub in case $myhostsub in
ce)
w32root="$w32ce_root"
[ -z "$w32root" ] && w32root="$HOME/w32ce_root"
toolprefixes="$w32ce_toolprefixes arm-mingw32ce"
extraoptions="$extraoptions $w32ce_extraoptions"
;;
64) 64)
w32root="$w64root" w32root="$w64root"
[ -z "$w32root" ] && w32root="$HOME/w64root" [ -z "$w32root" ] && w32root="$HOME/w64root"

1612
build-aux/config.guess vendored

File diff suppressed because it is too large Load Diff

2979
build-aux/config.sub vendored

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,68 @@
#
# This is a sed script to patch the generated libtool,
# which works well against both of libtool 2.4.2 and 2.4.7.
#
# You may use this work under the terms of a Creative Commons CC0 1.0
# License/Waiver.
#
# CC0 Public Domain Dedication
# https://creativecommons.org/publicdomain/zero/1.0/
#
# This sed script applys two hunks of the patch:
#
# Part1: after the comment "# bleh windows"
# Part2: after the comment "#extension on DOS 8.3..."
#
# Only when those two parts are patched correctly, it exits with 0 or
# else, it exits with 1
#
# Find the part 1, by the comment
/^[ \t]*# bleh windows$/b part1_start
# Not found the part1, raise an error
$ q1
b
:part1_start
n
# The first line in the part 1 must be the begining of the case statement.
/^[ \t]*case \$host in$/! q1
n
# Insert the entry for x86_64-*mingw32*, for modified versuffix.
i\
x86_64-*mingw32*)
i\
func_arith $current - $age
i\
major=$func_arith_result
i\
versuffix="6-$major"
i\
;;
:part1_0
# Find the end of the case statement
/^[ \t]*esac$/b find_part2
# Not found the end of the case statement, raise an error
$ q1
n
b part1_0
:find_part2
/^[ \t]*# extension on DOS 8.3 file.*systems.$/b part2_process
# Not found the part2, raise an error
$ q1
n
b find_part2
:part2_process
$ q1
s/^[ \t]*\(versuffix=\)\(.*\)\(-$major\)\(.*\)$/\t case \$host in\n\t x86_64-*mingw32*)\n\t \1\26\3\4\n\t ;;\n\t *)\n\t \1\2\3\4\n\t ;;\n\t esac/
t part2_done
n
b part2_process
:part2_done
$ q0
n
b part2_done

View File

@ -482,7 +482,7 @@
% \def\foo{\parsearg\Xfoo} % \def\foo{\parsearg\Xfoo}
% \def\Xfoo#1{...} % \def\Xfoo#1{...}
% %
% Actually, I use \csname\string\foo\endcsname, ie. \\foo, as it is my % Actually, I use \csname\string\foo\endcsname, i.e. \\foo, as it is my
% favourite TeX trick. --kasal, 16nov03 % favourite TeX trick. --kasal, 16nov03
\def\parseargdef#1{% \def\parseargdef#1{%

View File

@ -1,6 +1,6 @@
# configure.ac for GPGME # configure.ac for GPGME
# Copyright (C) 2000 Werner Koch (dd9jn) # Copyright (C) 2000 Werner Koch (dd9jn)
# Copyright (C) 2001-2018 g10 Code GmbH # Copyright (C) 2001-2021 g10 Code GmbH
# #
# This file is part of GPGME. # This file is part of GPGME.
# #
@ -19,18 +19,20 @@
# SPDX-License-Identifier: LGPL-2.1-or-later # SPDX-License-Identifier: LGPL-2.1-or-later
# (Process this file with autoconf to produce a configure script.) # (Process this file with autoconf to produce a configure script.)
AC_PREREQ(2.59) AC_PREREQ([2.69])
min_automake_version="1.14" min_automake_version="1.14"
# To build a release you need to create a tag with the version number # To build a release you need to create a tag with the version number
# (git tag -s gpgme-n.m.k) and run "./autogen.sh --force". Please # "gpgme-n.m.k" and run "./autogen.sh --force". Please bump the
# bump the version number immediately after the release and do another # version number immediately after the release and do another commit
# commit and push so that the git magic is able to work. See below # and push so that the git magic is able to work. If you start a new
# series by bumping the minor (m) remember to also create a tag named
# "gpgme-n.m-base" as the start point for beta numbering. See below
# for the LT versions. # for the LT versions.
m4_define([mym4_package],[gpgme]) m4_define([mym4_package],[gpgme])
m4_define([mym4_major], [1]) m4_define([mym4_major], [1])
m4_define([mym4_minor], [13]) m4_define([mym4_minor], [24])
m4_define([mym4_micro], [1]) m4_define([mym4_micro], [0])
# Below is m4 magic to extract and compute the git revision number, # Below is m4 magic to extract and compute the git revision number,
# the decimalized short revision number, a beta version string and a # the decimalized short revision number, a beta version string and a
@ -43,7 +45,7 @@ m4_define([mym4_version], m4_argn(4, mym4_verslist))
m4_define([mym4_revision], m4_argn(7, mym4_verslist)) m4_define([mym4_revision], m4_argn(7, mym4_verslist))
m4_define([mym4_revision_dec], m4_argn(8, mym4_verslist)) m4_define([mym4_revision_dec], m4_argn(8, mym4_verslist))
m4_esyscmd([echo ]mym4_version[>VERSION]) m4_esyscmd([echo ]mym4_version[>VERSION])
AC_INIT([mym4_package],[mym4_version], [https://bugs.gnupg.org]) AC_INIT([mym4_package],[mym4_version],[https://bugs.gnupg.org])
# LT Version numbers, remember to change them just *before* a release. # LT Version numbers, remember to change them just *before* a release.
# (Code changed: REVISION++) # (Code changed: REVISION++)
@ -51,20 +53,20 @@ AC_INIT([mym4_package],[mym4_version], [https://bugs.gnupg.org])
# (Interfaces added: AGE++) # (Interfaces added: AGE++)
# (Interfaces removed: AGE=0) # (Interfaces removed: AGE=0)
# #
LIBGPGME_LT_CURRENT=33 LIBGPGME_LT_CURRENT=43
LIBGPGME_LT_AGE=22 LIBGPGME_LT_AGE=32
LIBGPGME_LT_REVISION=0 LIBGPGME_LT_REVISION=1
# If there is an ABI break in gpgmepp or qgpgme also bump the # If there is an ABI break in gpgmepp or qgpgme also bump the
# version in IMPORTED_LOCATION in the GpgmeppConfig-w32.cmake.in.in # version in IMPORTED_LOCATION in the GpgmeppConfig-w32.cmake.in.in
LIBGPGMEPP_LT_CURRENT=15 LIBGPGMEPP_LT_CURRENT=26
LIBGPGMEPP_LT_AGE=9 LIBGPGMEPP_LT_AGE=20
LIBGPGMEPP_LT_REVISION=0 LIBGPGMEPP_LT_REVISION=1
LIBQGPGME_LT_CURRENT=10 LIBQGPGME_LT_CURRENT=20
LIBQGPGME_LT_AGE=3 LIBQGPGME_LT_AGE=5
LIBQGPGME_LT_REVISION=3 LIBQGPGME_LT_REVISION=1
################################################ ################################################
AC_SUBST(LIBGPGME_LT_CURRENT) AC_SUBST(LIBGPGME_LT_CURRENT)
@ -83,7 +85,7 @@ AC_SUBST(LIBQGPGME_LT_REVISION)
GPGME_CONFIG_API_VERSION=1 GPGME_CONFIG_API_VERSION=1
############################################## ##############################################
NEED_GPG_ERROR_VERSION=1.24 NEED_GPG_ERROR_VERSION=1.47
NEED_LIBASSUAN_API=2 NEED_LIBASSUAN_API=2
NEED_LIBASSUAN_VERSION=2.4.2 NEED_LIBASSUAN_VERSION=2.4.2
@ -94,8 +96,8 @@ VERSION_MICRO=mym4_micro
AC_CONFIG_AUX_DIR([build-aux]) AC_CONFIG_AUX_DIR([build-aux])
AC_CONFIG_MACRO_DIR([m4]) AC_CONFIG_MACRO_DIR([m4])
AC_CONFIG_SRCDIR(src/gpgme.h.in) AC_CONFIG_SRCDIR([src/gpgme.h.in])
AC_CONFIG_HEADER(conf/config.h) AC_CONFIG_HEADERS([conf/config.h])
AM_INIT_AUTOMAKE([serial-tests dist-bzip2 no-dist-gzip]) AM_INIT_AUTOMAKE([serial-tests dist-bzip2 no-dist-gzip])
AM_MAINTAINER_MODE AM_MAINTAINER_MODE
AC_CANONICAL_HOST AC_CANONICAL_HOST
@ -103,7 +105,7 @@ AM_SILENT_RULES
AC_ARG_VAR(SYSROOT,[locate config scripts also below that directory]) AC_ARG_VAR(SYSROOT,[locate config scripts also below that directory])
# Enable GNU extensions on systems that have them. # Enable GNU extensions on systems that have them.
AC_GNU_SOURCE AC_USE_SYSTEM_EXTENSIONS
# Taken from mpfr-4.0.1, then modified for LDADD_FOR_TESTS_KLUDGE # Taken from mpfr-4.0.1, then modified for LDADD_FOR_TESTS_KLUDGE
dnl Under Linux, make sure that the old dtags are used if LD_LIBRARY_PATH dnl Under Linux, make sure that the old dtags are used if LD_LIBRARY_PATH
@ -196,7 +198,7 @@ case "${host}" in
have_ld_version_script=yes have_ld_version_script=yes
;; ;;
*-apple-darwin*) *-apple-darwin*)
AC_DEFINE(_DARWIN_C_SOURCE, 900000L, AC_DEFINE(_DARWIN_C_SOURCE, 1,
Expose all libc features (__DARWIN_C_FULL).) Expose all libc features (__DARWIN_C_FULL).)
AC_DEFINE(_XOPEN_SOURCE, 500, Activate POSIX interface on MacOS X) AC_DEFINE(_XOPEN_SOURCE, 500, Activate POSIX interface on MacOS X)
;; ;;
@ -204,6 +206,44 @@ esac
AM_CONDITIONAL(HAVE_LD_VERSION_SCRIPT, test "$have_ld_version_script" = "yes") AM_CONDITIONAL(HAVE_LD_VERSION_SCRIPT, test "$have_ld_version_script" = "yes")
#
# Specify how we support our local modification of libtool for Windows
# 64-bit. Options are:
#
# (1) apply: when appying patch fails, it results failure of entire build
# (2) never: never apply the patch (no try)
# (3) try: use patched if it goes well, use original if fails
#
AC_ARG_WITH([libtool-modification],
AS_HELP_STRING([--with-libtool-modification=apply|never|try],
[how to handle libtool modification (default=never)]),
build_libtool_modification=$withval,
build_libtool_modification=never)
#
# Apply a patch (locally maintained one of ours) to libtool
#
case $host in
x86_64-*mingw32*)
AC_CONFIG_COMMANDS([libtool-patch],[[
if test "$build_selection" = never; then
echo "patch not applied"
elif (mv -f libtool libtool.orig; \
sed -f $srcdir/build-aux/libtool-patch.sed libtool.orig >libtool); then
echo "applied successfully"
elif test "$build_selection" = try; then
mv -f libtool.orig libtool
echo "patch failed, thus, using original"
else
echo "patch failed"
as_fn_exit 1
fi
]],[build_selection=$build_libtool_modification])
;;
*)
;;
esac
GPG_DEFAULT=no GPG_DEFAULT=no
GPGSM_DEFAULT=no GPGSM_DEFAULT=no
GPGCONF_DEFAULT=no GPGCONF_DEFAULT=no
@ -216,8 +256,8 @@ have_w64_system=no
have_macos_system=no have_macos_system=no
build_w32_glib=no build_w32_glib=no
build_w32_qt=no build_w32_qt=no
available_languages="cl cpp python qt" available_languages="cl cpp python qt qt5 qt6"
default_languages="cl cpp python qt" default_languages="cl cpp python qt5 qt6"
case "${host}" in case "${host}" in
x86_64-*mingw32*) x86_64-*mingw32*)
have_w64_system=yes have_w64_system=yes
@ -241,7 +281,7 @@ case "${host}" in
AM_PATH_GLIB_2_0 AM_PATH_GLIB_2_0
AC_ARG_ENABLE(w32-glib, AC_ARG_ENABLE(w32-glib,
AC_HELP_STRING([--enable-w32-glib], [build GPGME Glib for W32]), AS_HELP_STRING([--enable-w32-glib],[build GPGME Glib for W32]),
build_w32_glib=$enableval) build_w32_glib=$enableval)
;; ;;
*) *)
@ -289,7 +329,7 @@ AM_CONDITIONAL(BUILD_W32_GLIB, test "$build_w32_glib" = yes)
AC_ARG_ENABLE([fixed-path], AC_ARG_ENABLE([fixed-path],
AC_HELP_STRING([--enable-fixed-path=PATH], AS_HELP_STRING([--enable-fixed-path=PATH],
[locate binaries only via this PATH]), [locate binaries only via this PATH]),
[fixed_search_path="$enableval"], [fixed_search_path="$enableval"],
[fixed_search_path=""]) [fixed_search_path=""])
@ -298,12 +338,44 @@ if test x$fixed_search_path != x ; then
[Locate binaries only via this PATH]) [Locate binaries only via this PATH])
fi fi
# Option --enable-reduce-relocations
#
# Allow building the Qt 6 bindings explicitly with -fPIC if the automatic
# detection fails. Note: We assume that this flag is always available (unless
# we built for Windows).
AC_ARG_ENABLE([reduce-relocations],
AS_HELP_STRING([--enable-reduce-relocations],
[build Qt 6 bindings with -fPIC (default is
auto)]),
[use_reduce_relocations="$enableval"],
[use_reduce_relocations=""])
# Option --enable-no-direct-extern-access
#
# Some distributions build Qt 6 with -mno-direct-extern-access. Libraries and
# applications using Qt then must also be build with this flag. As workaround
# for a bug in Qt's pkgconfig files which don't have this flag we allow
# building with this flag explicitly.
AC_LANG_PUSH(C++)
AX_CHECK_COMPILE_FLAG([-mno-direct-extern-access],
[have_no_direct_extern_access="yes"],
[have_no_direct_extern_access="no"],
[-Werror])
AC_LANG_POP()
AC_ARG_ENABLE([no-direct-extern-access],
AS_HELP_STRING([--enable-no-direct-extern-access],
[build Qt 6 bindings with
-mno-direct-extern-access (default is auto)]),
[use_no_direct_extern_access="$enableval"],
[use_no_direct_extern_access=""])
# Note: You need to declare all possible languages also in # Note: You need to declare all possible languages also in
# lang/Makefile.am's DIST_SUBDIRS. # lang/Makefile.am's DIST_SUBDIRS.
AC_ARG_ENABLE([languages], AC_ARG_ENABLE([languages],
AC_HELP_STRING([--enable-languages=languages], AS_HELP_STRING([--enable-languages=languages],
[enable only specific language bindings]), [enable only specific language bindings:
cl cpp python qt5 qt6]),
[enabled_languages=`echo $enableval | \ [enabled_languages=`echo $enableval | \
tr ',:' ' ' | tr '[A-Z]' '[a-z]' | \ tr ',:' ' ' | tr '[A-Z]' '[a-z]' | \
sed 's/c++/cpp/'`], sed 's/c++/cpp/'`],
@ -329,69 +401,182 @@ for language in $enabled_languages; do
fi fi
done done
# Check whether qt5 and/or qt6 are enabled
want_qt5="no"
# Enable C++ 11 if cpp language is requested LIST_MEMBER("qt5", $enabled_languages)
LIST_MEMBER("cpp", $enabled_languages)
if test "$found" = "1"; then if test "$found" = "1"; then
if test "$explicit_languages" = "1"; then
want_qt5="yes"
else
want_qt5="maybe"
fi
# Remove qt5; further down qt will be added
enabled_languages=$(echo $enabled_languages | sed 's/qt5//')
fi
want_qt6="no"
LIST_MEMBER("qt6", $enabled_languages)
if test "$found" = "1"; then
if test "$explicit_languages" = "1"; then
want_qt6="yes"
else
want_qt6="maybe"
fi
# Remove qt6; further down qt will be added
enabled_languages=$(echo $enabled_languages | sed 's/qt6//')
fi
# Check whether qt is enabled; if yes then it has been enabled explicitly
want_qt="no"
LIST_MEMBER("qt", $enabled_languages)
if test "$found" = "1"; then
# Ignore qt if specified together with qt5 or qt6
if test "$want_qt5" = "no" -a "$want_qt6" = "no"; then
want_qt="yes"
fi
# Remove qt
enabled_languages=$(echo $enabled_languages | sed 's/qt//')
AC_MSG_WARN([[
***
*** Language binding "qt" is deprecated and will be removed in a future version.
*** Use "qt5" and/or "qt6" instead.
***]])
fi
# Ensure that pkg-config is available for all calls of FIND_QT5/FIND_QT6
PKG_PROG_PKG_CONFIG
# Check for Qt 5 (if qt5 or qt is enabled)
if test "$want_qt" = "yes"; then
want_qt5="maybe"
fi
if test "$want_qt5" != "no"; then
FIND_QT5
if test "$have_qt5_libs" = "yes"; then
want_qt5="yes"
elif test "$want_qt5" = "yes"; then
AC_MSG_ERROR([[
***
*** Qt5 (Qt5Core) is required for the Qt 5 binding.
***]])
else
want_qt5="no"
fi
fi
# Check for Qt 6 (if qt6 is enabled or if qt is enabled and Qt 5 wasn't found)
if test "$want_qt" = "yes" -a "$have_qt5_libs" != "yes"; then
want_qt6="maybe"
fi
if test "$want_qt6" != "no"; then
FIND_QT6
if test "$have_qt6_libs" = "yes"; then
want_qt6="yes";
elif test "$want_qt6" = "yes"; then
AC_MSG_ERROR([[
***
*** Qt6 (Qt6Core) is required for the Qt 6 binding.
***]])
else
want_qt6="no"
fi
fi
# Check if any Qt was found (if qt is enabled)
if test "$want_qt" = "yes" -a "$have_qt5_libs" != "yes" -a "$have_qt6_libs" != "yes"; then
AC_MSG_ERROR([[
***
*** Qt5 (Qt5Core) or Qt6 (Qt6Core) is required for the Qt bindings.
***]])
fi
# Check that cpp is enabled if qt5 or qt6 is enabled and was found
if test "$want_qt5" = "yes" -o "$want_qt6" = "yes"; then
LIST_MEMBER("cpp", $enabled_languages)
if test "$found" = "0"; then
AC_MSG_ERROR([[
***
*** The Qt bindings depend on the C++ binding.
***]])
fi
fi
# Enable C++ 17 if qt6 is requested
if test "$want_qt6" = "yes"; then
AX_CXX_COMPILE_STDCXX(17, noext, optional)
if test "$HAVE_CXX17" != "1"; then
if test "$explicit_languages" = "1"; then
AC_MSG_ERROR([[
***
*** A compiler with c++17 support is required for the Qt 6 binding.
***]])
else
want_qt6="no"
AC_MSG_WARN([[
***
*** No c++17 support detected. Qt 6 binding will be disabled.
***]])
fi
fi
fi
# Enable C++ 11 if cpp is requested (unless C++ 17 was already enabled)
LIST_MEMBER("cpp", $enabled_languages)
if test "$found" = "1" -a "$HAVE_CXX17" != "1"; then
AX_CXX_COMPILE_STDCXX(11, noext, optional) AX_CXX_COMPILE_STDCXX(11, noext, optional)
if test "$HAVE_CXX11" != "1"; then if test "$HAVE_CXX11" != "1"; then
if test "$explicit_languages" = "1"; then if test "$explicit_languages" = "1"; then
AC_MSG_ERROR([[ AC_MSG_ERROR([[
*** ***
*** A compiler with c++11 support is required for the c++ binding. *** A compiler with c++11 support is required for the C++ binding.
***]]) ***]])
else else
enabled_languages=$(echo $enabled_languages | sed 's/cpp//') enabled_languages=$(echo $enabled_languages | sed 's/cpp//')
enabled_languages=$(echo $enabled_languages | sed 's/qt//') want_qt5="no"
AC_MSG_WARN([[ AC_MSG_WARN([[
*** ***
*** No c++11 support detected. C++ and Qt bindings will be disabled. *** No c++11 support detected. C++ and Qt 5 bindings will be disabled.
***]]) ***]])
fi fi
fi fi
fi fi
# Check that if qt is enabled cpp also is enabled # Now append qt to the list of language bindings (to enable the subdir in lang)
LIST_MEMBER("qt", $enabled_languages) if test "$want_qt5" = "yes" -o "$want_qt6" = "yes"; then
enabled_languages=$(echo $enabled_languages qt)
fi
# Check whether compiler supports visibility attribute (if cpp language is enabled)
LIST_MEMBER("cpp", $enabled_languages)
if test "$found" = "1"; then if test "$found" = "1"; then
# We need to ensure that in the language order qt comes after cpp AX_GCC_FUNC_ATTRIBUTE(visibility)
# so we remove qt first and explicitly add it as last list member. if test "$ax_cv_have_func_attribute_visibility" = "yes"; then
enabled_languages=$(echo $enabled_languages | sed 's/qt//') GPGME_CPP_CFLAGS="$GPGME_CPP_CFLAGS -fvisibility=hidden"
LIST_MEMBER("cpp", $enabled_languages) if test "$want_qt5" = "yes"; then
if test "$found" = "0"; then GPGME_QT5_CFLAGS="$GPGME_QT5_CFLAGS -fvisibility=hidden"
AC_MSG_ERROR([[
***
*** Qt language binding depends on cpp binding.
***]])
fi
FIND_QT
if test "$have_qt5_libs" != "yes"; then
if test "$explicit_languages" = "1"; then
AC_MSG_ERROR([[
***
*** Qt5 (Qt5Core) is required for Qt binding.
***]])
else
AC_MSG_WARN([[
***
*** Qt5 (Qt5Core) not found Qt Binding will be disabled.
***]])
fi fi
else if test "$want_qt6" = "yes"; then
enabled_languages=`echo $enabled_languages qt` GPGME_QT6_CFLAGS="$GPGME_QT6_CFLAGS -fvisibility=hidden"
AC_CHECK_PROGS([DOXYGEN], [doxygen])
if test -z "$DOXYGEN";
# This is not highlighted because it's not really important.
then AC_MSG_WARN([Doxygen not found - Qt binding doc will not be built.])
fi
AC_CHECK_PROGS([GRAPHVIZ], [dot])
if test -z "$GRAPHVIZ";
then AC_MSG_WARN([Graphviz not found - Qt binding doc will not have diagrams.])
fi fi
fi fi
fi fi
AC_SUBST(GPGME_CPP_CFLAGS)
AM_CONDITIONAL(WANT_QT5, test "$want_qt5" = yes)
AM_CONDITIONAL(WANT_QT6, test "$want_qt6" = yes)
# Check for tools for building the Qt binding docs
if test "$want_qt5" = "yes" -o "$want_qt6" = "yes"; then
AC_CHECK_PROGS([DOXYGEN], [doxygen])
if test -z "$DOXYGEN"; then
# This is not highlighted because it's not really important.
AC_MSG_WARN([Doxygen not found - Qt binding doc will not be built.])
fi
AC_CHECK_PROGS([GRAPHVIZ], [dot])
if test -z "$GRAPHVIZ"; then
AC_MSG_WARN([Graphviz not found - Qt binding doc will not have diagrams.])
fi
fi
AM_CONDITIONAL([HAVE_DOXYGEN], AM_CONDITIONAL([HAVE_DOXYGEN],
[test -n "$DOXYGEN"]) [test -n "$DOXYGEN"])
if test -n "$GRAPHVIZ"; then if test -n "$GRAPHVIZ"; then
@ -423,11 +608,12 @@ if test "$found_py" = "1"; then
if test "$found_py" = "1" -o "$found_py3" = "1"; then if test "$found_py" = "1" -o "$found_py3" = "1"; then
# Reset everything, so that we can look for another Python. # Reset everything, so that we can look for another Python.
m4_foreach([mym4pythonver], m4_foreach([mym4pythonver],
[[2.7],[3.4],[3.5],[3.6],[3.7],[3.8],[all]], [[2.7],[3.6],[3.8],[3.9],[3.10],[3.11],[3.12],[all]],
[unset PYTHON [unset PYTHON
unset PYTHON_VERSION unset PYTHON_VERSION
unset PYTHON_CPPFLAGS unset PYTHON_CPPFLAGS
unset PYTHON_LDFLAGS unset PYTHON_LDFLAGS
unset PYTHON_LIBS
unset PYTHON_SITE_PKG unset PYTHON_SITE_PKG
unset PYTHON_EXTRA_LIBS unset PYTHON_EXTRA_LIBS
unset PYTHON_EXTRA_LDFLAGS unset PYTHON_EXTRA_LDFLAGS
@ -438,7 +624,7 @@ if test "$found_py" = "1"; then
unset am_cv_python_pythondir unset am_cv_python_pythondir
unset am_cv_python_pyexecdir unset am_cv_python_pyexecdir
AM_PATH_PYTHON(mym4pythonver, [ AM_PATH_PYTHON(mym4pythonver, [
AX_PYTHON_DEVEL AX_PYTHON_DEVEL([], [true])
if test "$PYTHON_VERSION"; then if test "$PYTHON_VERSION"; then
PYTHONS="$(echo $PYTHONS $PYTHON)" PYTHONS="$(echo $PYTHONS $PYTHON)"
PYTHON_VERSIONS="$(echo $PYTHON_VERSIONS $PYTHON_VERSION)" PYTHON_VERSIONS="$(echo $PYTHON_VERSIONS $PYTHON_VERSION)"
@ -492,7 +678,7 @@ AC_SUBST(BUILD_VERSION)
AC_SUBST(BUILD_FILEVERSION) AC_SUBST(BUILD_FILEVERSION)
AC_ARG_ENABLE([build-timestamp], AC_ARG_ENABLE([build-timestamp],
AC_HELP_STRING([--enable-build-timestamp], AS_HELP_STRING([--enable-build-timestamp],
[set an explicit build timestamp for reproducibility. [set an explicit build timestamp for reproducibility.
(default is the current time in ISO-8601 format)]), (default is the current time in ISO-8601 format)]),
[if test "$enableval" = "yes"; then [if test "$enableval" = "yes"; then
@ -511,36 +697,37 @@ AC_DEFINE_UNQUOTED(BUILD_TIMESTAMP, "$BUILD_TIMESTAMP",
# #
run_gpgconf_test="yes" run_gpgconf_test="yes"
AC_ARG_ENABLE(gpgconf-test, AC_ARG_ENABLE(gpgconf-test,
AC_HELP_STRING([--disable-gpgconf-test], [disable GPGCONF regression test]), AS_HELP_STRING([--disable-gpgconf-test],[disable GPGCONF regression test]),
run_gpgconf_test=$enableval) run_gpgconf_test=$enableval)
AM_CONDITIONAL(RUN_GPGCONF_TESTS, test "$run_gpgconf_test" = "yes") AM_CONDITIONAL(RUN_GPGCONF_TESTS, test "$run_gpgconf_test" = "yes")
run_gpg_test="yes" run_gpg_test="yes"
AC_ARG_ENABLE(gpg-test, AC_ARG_ENABLE(gpg-test,
AC_HELP_STRING([--disable-gpg-test], [disable GPG regression test]), AS_HELP_STRING([--disable-gpg-test],[disable GPG regression test]),
run_gpg_test=$enableval) run_gpg_test=$enableval)
AM_CONDITIONAL(RUN_GPG_TESTS, test "$run_gpg_test" = "yes") AM_CONDITIONAL(RUN_GPG_TESTS, test "$run_gpg_test" = "yes")
run_gpgsm_test="yes" run_gpgsm_test="yes"
AC_ARG_ENABLE(gpgsm-test, AC_ARG_ENABLE(gpgsm-test,
AC_HELP_STRING([--disable-gpgsm-test], [disable GPGSM regression test]), AS_HELP_STRING([--disable-gpgsm-test],[disable GPGSM regression test]),
run_gpgsm_test=$enableval) run_gpgsm_test=$enableval)
AM_CONDITIONAL(RUN_GPGSM_TESTS, test "$run_gpgsm_test" = "yes") AM_CONDITIONAL(RUN_GPGSM_TESTS, test "$run_gpgsm_test" = "yes")
run_g13_test="yes" run_g13_test="yes"
AC_ARG_ENABLE(g13-test, AC_ARG_ENABLE(g13-test,
AC_HELP_STRING([--disable-g13-test], [disable G13 regression test]), AS_HELP_STRING([--disable-g13-test],[disable G13 regression test]),
run_g13_test=$enableval) run_g13_test=$enableval)
AM_CONDITIONAL(RUN_G13_TESTS, test "$run_g13_test" = "yes") AM_CONDITIONAL(RUN_G13_TESTS, test "$run_g13_test" = "yes")
# Checks for header files. # Checks for header files.
AC_CHECK_HEADERS_ONCE([locale.h sys/select.h sys/uio.h argp.h stdint.h 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. # Type checks.
AC_C_INLINE AC_C_INLINE
AC_C_FLEXIBLE_ARRAY_MEMBER
AC_CHECK_SIZEOF(unsigned int) AC_CHECK_SIZEOF(unsigned int)
AC_SYS_LARGEFILE AC_SYS_LARGEFILE
AC_TYPE_OFF_T AC_TYPE_OFF_T
@ -703,6 +890,9 @@ AM_PATH_GPG_ERROR("$NEED_GPG_ERROR_VERSION",
AC_DEFINE(GPG_ERR_SOURCE_DEFAULT, GPG_ERR_SOURCE_GPGME, AC_DEFINE(GPG_ERR_SOURCE_DEFAULT, GPG_ERR_SOURCE_GPGME,
[The default error source for GPGME.]) [The default error source for GPGME.])
AM_CONDITIONAL(USE_GPGRT_CONFIG, [test -n "$GPGRT_CONFIG" \
-a "$ac_cv_path_GPG_ERROR_CONFIG" = no])
# And for libassuan. # And for libassuan.
have_libassuan=no have_libassuan=no
AM_PATH_LIBASSUAN("$NEED_LIBASSUAN_API:$NEED_LIBASSUAN_VERSION", AM_PATH_LIBASSUAN("$NEED_LIBASSUAN_API:$NEED_LIBASSUAN_VERSION",
@ -718,7 +908,7 @@ fi
# #
# Check for getgid etc # Check for getgid etc
AC_CHECK_FUNCS(getgid getegid closefrom) AC_CHECK_FUNCS(getgid getegid closefrom nanosleep)
# Replacement functions. # Replacement functions.
@ -748,7 +938,7 @@ AC_CHECK_MEMBER(struct cmsghdr.cmsg_len,
use_descriptor_passing=yes use_descriptor_passing=yes
AC_ARG_ENABLE(fd-passing, AC_ARG_ENABLE(fd-passing,
AC_HELP_STRING([--disable-fd-passing], [do not use FD passing]), AS_HELP_STRING([--disable-fd-passing],[do not use FD passing]),
use_descriptor_passing=$enableval) use_descriptor_passing=$enableval)
if test "$supports_descriptor_passing" != "yes"; then if test "$supports_descriptor_passing" != "yes"; then
@ -780,7 +970,7 @@ AM_CONDITIONAL(HAVE_UISERVER, test "$uiserver" != "no")
# before an exec. This option allows to switch this optimization off. # before an exec. This option allows to switch this optimization off.
use_linux_getdents=yes use_linux_getdents=yes
AC_ARG_ENABLE(linux-getdents, AC_ARG_ENABLE(linux-getdents,
AC_HELP_STRING([--disable-linux-getdents], AS_HELP_STRING([--disable-linux-getdents],
[do not use SYS_getdents on Linux]), [do not use SYS_getdents on Linux]),
use_linux_getdents=$enableval) use_linux_getdents=$enableval)
if test "$use_linux_getdents" = "yes"; then if test "$use_linux_getdents" = "yes"; then
@ -818,19 +1008,56 @@ AH_BOTTOM([
# define GPGME_GCC_A_PURE # define GPGME_GCC_A_PURE
#endif #endif
/* Under Windows we use the gettext code from gpgrt. */
#define GPG_ERR_ENABLE_GETTEXT_MACROS 1
/* Under WindowsCE we need gpg-error's strerror macro. */ /* Under WindowsCE we need gpg-error's strerror macro. */
#define GPG_ERR_ENABLE_ERRNO_MACROS 1 #define GPG_ERR_ENABLE_ERRNO_MACROS 1
#define CRIGHTBLURB "Copyright (C) 2000 Werner Koch\n" \ #define CRIGHTBLURB "Copyright (C) 2000 Werner Koch\n" \
"Copyright (C) 2001--2018 g10 Code GmbH\n" "Copyright (C) 2001--2021 g10 Code GmbH\n"
]) ])
# Substitution used for gpgme-config # Substitution used for gpgme-config and gpgme.pc
GPGME_CONFIG_LIBS="-lgpgme" GPGME_CONFIG_LIBS="-lgpgme"
GPGME_CONFIG_CFLAGS="" GPGME_CONFIG_CFLAGS=""
GPGME_CONFIG_HOST="$host" GPGME_CONFIG_HOST="$host"
GPGME_CONFIG_AVAIL_LANG="$enabled_languages" GPGME_CONFIG_AVAIL_LANG="$enabled_languages"
case "$includedir" in
/usr/include|/include) ;;
'${prefix}/include')
if test "$prefix" != / -a "$prefix" != /usr; then
if test -z "$GPGME_CONFIG_CFLAGS"; then
GPGME_CONFIG_CFLAGS="-I\${includedir}"
else
GPGME_CONFIG_CFLAGS="-I\${includedir} $GPGME_CONFIG_CFLAGS"
fi
fi
;;
*)
if test -z "$GPGME_CONFIG_CFLAGS"; then
GPGME_CONFIG_CFLAGS="-I\${includedir}"
else
GPGME_CONFIG_CFLAGS="-I\${includedir} $GPGME_CONFIG_CFLAGS"
fi
;;
esac
case "$libdir" in
/usr/lib|/usr/lib64|/lib|/lib64) ;;
'${exec_prefix}/lib'|'${exec_prefix}/lib64')
if test "$exec_prefix" = "NONE"; then
if test "$prefix" != / -a "$prefix" != /usr; then
GPGME_CONFIG_LIBS="-L\${libdir} $GPGME_CONFIG_LIBS"
fi
elif test "$exec_prefix" != / -a "$exec_prefix" != /usr; then
GPGME_CONFIG_LIBS="-L\${libdir} $GPGME_CONFIG_LIBS"
fi
;;
*) GPGME_CONFIG_LIBS="-L\${libdir} $GPGME_CONFIG_LIBS" ;;
esac
AC_SUBST(GPGME_CONFIG_API_VERSION) AC_SUBST(GPGME_CONFIG_API_VERSION)
AC_SUBST(GPGME_CONFIG_LIBS) AC_SUBST(GPGME_CONFIG_LIBS)
AC_SUBST(GPGME_CONFIG_CFLAGS) AC_SUBST(GPGME_CONFIG_CFLAGS)
@ -909,9 +1136,16 @@ AC_CONFIG_FILES(lang/cpp/src/GpgmeppConfig.cmake.in)
AC_CONFIG_FILES(lang/cpp/src/GpgmeppConfigVersion.cmake) AC_CONFIG_FILES(lang/cpp/src/GpgmeppConfigVersion.cmake)
AC_CONFIG_FILES(lang/cpp/src/gpgmepp_version.h) AC_CONFIG_FILES(lang/cpp/src/gpgmepp_version.h)
AC_CONFIG_FILES(lang/qt/Makefile lang/qt/src/Makefile) AC_CONFIG_FILES(lang/qt/Makefile lang/qt/src/Makefile)
AC_CONFIG_FILES(lang/qt/src/QGpgmeConfig-w32.cmake.in) if test "$want_qt5" = "yes"; then
AC_CONFIG_FILES(lang/qt/src/QGpgmeConfig.cmake.in) AC_CONFIG_FILES(lang/qt/src/QGpgmeConfig-w32.cmake.in)
AC_CONFIG_FILES(lang/qt/src/QGpgmeConfigVersion.cmake) AC_CONFIG_FILES(lang/qt/src/QGpgmeConfig.cmake.in)
AC_CONFIG_FILES(lang/qt/src/QGpgmeConfigVersion.cmake)
fi
if test "$want_qt6" = "yes"; then
AC_CONFIG_FILES(lang/qt/src/QGpgmeQt6Config-w32.cmake.in)
AC_CONFIG_FILES(lang/qt/src/QGpgmeQt6Config.cmake.in)
AC_CONFIG_FILES(lang/qt/src/QGpgmeQt6ConfigVersion.cmake)
fi
AC_CONFIG_FILES(lang/qt/tests/Makefile) AC_CONFIG_FILES(lang/qt/tests/Makefile)
AC_CONFIG_FILES(lang/qt/src/qgpgme_version.h) AC_CONFIG_FILES(lang/qt/src/qgpgme_version.h)
AC_CONFIG_FILES([lang/Makefile lang/cl/Makefile lang/cl/gpgme.asd]) AC_CONFIG_FILES([lang/Makefile lang/cl/Makefile lang/cl/gpgme.asd])
@ -929,6 +1163,14 @@ AC_CONFIG_FILES([lang/python/Makefile
AC_CONFIG_FILES([lang/python/setup.py], [chmod a+x lang/python/setup.py]) AC_CONFIG_FILES([lang/python/setup.py], [chmod a+x lang/python/setup.py])
AC_OUTPUT AC_OUTPUT
if test "$want_qt5" = "yes" -a "$want_qt6" = "yes"; then
enabled_languages_v=$(echo ${enabled_languages_v:-$enabled_languages} | sed "s/qt/qt (Qt 5, Qt 6)/")
elif test "$want_qt5" = "yes"; then
enabled_languages_v=$(echo ${enabled_languages_v:-$enabled_languages} | sed "s/qt/qt (Qt 5)/")
elif test "$want_qt6" = "yes"; then
enabled_languages_v=$(echo ${enabled_languages_v:-$enabled_languages} | sed "s/qt/qt (Qt 6)/")
fi
echo " echo "
GPGME v${VERSION} has been configured as follows: GPGME v${VERSION} has been configured as follows:

File diff suppressed because it is too large Load Diff

View File

@ -498,7 +498,7 @@
% \def\foo{\parsearg\Xfoo} % \def\foo{\parsearg\Xfoo}
% \def\Xfoo#1{...} % \def\Xfoo#1{...}
% %
% Actually, I use \csname\string\foo\endcsname, ie. \\foo, as it is my % Actually, I use \csname\string\foo\endcsname, i.e. \\foo, as it is my
% favourite TeX trick. --kasal, 16nov03 % favourite TeX trick. --kasal, 16nov03
\def\parseargdef#1{% \def\parseargdef#1{%

View File

@ -18,6 +18,12 @@
# License along with this program; if not, see <https://gnu.org/licenses/>. # License along with this program; if not, see <https://gnu.org/licenses/>.
# SPDX-License-Identifier: LGPL-2.1-or-later # SPDX-License-Identifier: LGPL-2.1-or-later
SUBDIRS = src tests if RUN_GPG_TESTS
tests = tests
else
tests =
endif
SUBDIRS = src ${tests}
EXTRA_DIST = README EXTRA_DIST = README

View File

@ -97,7 +97,3 @@ unset(_IMPORT_CHECK_TARGETS)
# Commands beyond this point should not need to know the version. # Commands beyond this point should not need to know the version.
set(CMAKE_IMPORT_FILE_VERSION) set(CMAKE_IMPORT_FILE_VERSION)
cmake_policy(POP) cmake_policy(POP)
get_filename_component(QGpgme_DIR "${CMAKE_CURRENT_LIST_FILE}" PATH)
# Pull in QGpgme for compatibility with KF5 variant.
find_package(QGpgme CONFIG)

View File

@ -93,7 +93,3 @@ unset(_IMPORT_CHECK_TARGETS)
# Commands beyond this point should not need to know the version. # Commands beyond this point should not need to know the version.
set(CMAKE_IMPORT_FILE_VERSION) set(CMAKE_IMPORT_FILE_VERSION)
cmake_policy(POP) cmake_policy(POP)
get_filename_component(QGpgme_DIR "${CMAKE_CURRENT_LIST_FILE}" PATH)
# Pull in QGpgme for compatibility with KF5 variant.
find_package(QGpgme CONFIG)

View File

@ -33,9 +33,13 @@ main_sources = \
engineinfo.cpp gpgsetexpirytimeeditinteractor.cpp \ engineinfo.cpp gpgsetexpirytimeeditinteractor.cpp \
gpgsetownertrusteditinteractor.cpp gpgsignkeyeditinteractor.cpp \ gpgsetownertrusteditinteractor.cpp gpgsignkeyeditinteractor.cpp \
gpgadduserideditinteractor.cpp gpggencardkeyinteractor.cpp \ gpgadduserideditinteractor.cpp gpggencardkeyinteractor.cpp \
gpgaddexistingsubkeyeditinteractor.cpp \
gpgrevokekeyeditinteractor.cpp \
defaultassuantransaction.cpp \ defaultassuantransaction.cpp \
scdgetinfoassuantransaction.cpp gpgagentgetinfoassuantransaction.cpp \ scdgetinfoassuantransaction.cpp gpgagentgetinfoassuantransaction.cpp \
vfsmountresult.cpp configuration.cpp tofuinfo.cpp swdbresult.cpp statusconsumerassuantransaction.cpp \
vfsmountresult.cpp configuration.cpp tofuinfo.cpp swdbresult.cpp \
util.cpp
gpgmepp_headers = \ gpgmepp_headers = \
configuration.h context.h data.h decryptionresult.h \ configuration.h context.h data.h decryptionresult.h \
@ -45,8 +49,11 @@ gpgmepp_headers = \
gpgmefw.h gpgsetexpirytimeeditinteractor.h \ gpgmefw.h gpgsetexpirytimeeditinteractor.h \
gpgsetownertrusteditinteractor.h gpgsignkeyeditinteractor.h \ gpgsetownertrusteditinteractor.h gpgsignkeyeditinteractor.h \
gpggencardkeyinteractor.h \ gpggencardkeyinteractor.h \
gpgaddexistingsubkeyeditinteractor.h \
gpgrevokekeyeditinteractor.h \
importresult.h keygenerationresult.h key.h keylistresult.h \ importresult.h keygenerationresult.h key.h keylistresult.h \
notation.h result.h scdgetinfoassuantransaction.h signingresult.h \ notation.h result.h scdgetinfoassuantransaction.h signingresult.h \
statusconsumerassuantransaction.h \
trustitem.h verificationresult.h vfsmountresult.h gpgmepp_export.h \ trustitem.h verificationresult.h vfsmountresult.h gpgmepp_export.h \
tofuinfo.h swdbresult.h tofuinfo.h swdbresult.h
@ -55,7 +62,8 @@ private_gpgmepp_headers = \
interface_headers= \ interface_headers= \
interfaces/assuantransaction.h interfaces/dataprovider.h \ interfaces/assuantransaction.h interfaces/dataprovider.h \
interfaces/passphraseprovider.h interfaces/progressprovider.h interfaces/passphraseprovider.h interfaces/progressprovider.h \
interfaces/statusconsumer.h
gpgmeppincludedir = $(includedir)/gpgme++ gpgmeppincludedir = $(includedir)/gpgme++
gpgmeppinclude_HEADERS = $(gpgmepp_headers) gpgmeppinclude_HEADERS = $(gpgmepp_headers)
@ -65,7 +73,8 @@ nodist_gpgmeppinclude_HEADERS = gpgmepp_version.h
libgpgmepp_la_SOURCES = $(main_sources) $(gpgmepp_headers) context_vanilla.cpp \ libgpgmepp_la_SOURCES = $(main_sources) $(gpgmepp_headers) context_vanilla.cpp \
$(interface_headers) $(private_gpgmepp_headers) $(interface_headers) $(private_gpgmepp_headers)
AM_CPPFLAGS = -I$(top_builddir)/src @GPG_ERROR_CFLAGS@ @LIBASSUAN_CFLAGS@ \ AM_CPPFLAGS = -I$(top_builddir)/src \
@GPGME_CPP_CFLAGS@ @GPG_ERROR_CFLAGS@ @LIBASSUAN_CFLAGS@ \
-DBUILDING_GPGMEPP -Wsuggest-override \ -DBUILDING_GPGMEPP -Wsuggest-override \
-Wzero-as-null-pointer-constant -Wzero-as-null-pointer-constant
@ -79,6 +88,14 @@ else
libsuffix=.so libsuffix=.so
endif endif
copied_headers = $(gpgmepp_headers:%=gpgme++/%) $(interface_headers:%=gpgme++/%)
$(copied_headers): Makefile.am
mkdir -p $(builddir)/gpgme++/interfaces
echo -n "#include \"$(abs_srcdir)" > "$@"
echo -n "$@" | sed "s/gpgme++//" >> "$@"
echo "\"" >> "$@"
if HAVE_W32_SYSTEM if HAVE_W32_SYSTEM
GpgmeppConfig.cmake: GpgmeppConfig-w32.cmake.in GpgmeppConfig.cmake: GpgmeppConfig-w32.cmake.in
sed -e 's|[@]resolved_bindir@|$(bindir)|g' < "$<" | \ sed -e 's|[@]resolved_bindir@|$(bindir)|g' < "$<" | \
@ -106,5 +123,8 @@ install-data-local: install-cmake-files
uninstall-local: uninstall-cmake-files uninstall-local: uninstall-cmake-files
BUILT_SOURCES = $(copied_headers)
CLEANFILES = GpgmeppConfig.cmake GpgmeppConfigVersion.cmake \ CLEANFILES = GpgmeppConfig.cmake GpgmeppConfigVersion.cmake \
gpgmepp_version.h GpgmeppConfig.cmake.in gpgmepp_version.h GpgmeppConfig.cmake.in \
$(copied_headers)

View File

@ -257,158 +257,6 @@ Type Option::alternateType() const
return isNull() ? NoType : static_cast<Type>(opt->alt_type) ; return isNull() ? NoType : static_cast<Type>(opt->alt_type) ;
} }
#if 0
static Option::Variant argument_to_variant(gpgme_conf_type_t type, bool list, gpgme_conf_arg_t arg)
{
assert(arg);
switch (type) {
case GPGME_CONF_NONE:
if (list) {
// return the count (number of times set):
return arg->value.count;
} else {
return none;
}
case GPGME_CONF_INT32:
if (list) {
std::vector<int> result;
for (gpgme_conf_arg_t a = arg ; a ; a = a->next) {
result.push_back(a->value.int32);
}
return result;
} else {
return arg->value.int32;
}
case GPGME_CONF_UINT32:
if (list) {
std::vector<unsigned int> result;
for (gpgme_conf_arg_t a = arg ; a ; a = a->next) {
result.push_back(a->value.uint32);
}
return result;
} else {
return arg->value.uint32;
}
case GPGME_CONF_FILENAME:
case GPGME_CONF_LDAP_SERVER:
case GPGME_CONF_KEY_FPR:
case GPGME_CONF_PUB_KEY:
case GPGME_CONF_SEC_KEY:
case GPGME_CONF_ALIAS_LIST:
// these should not happen in alt_type, but fall through
case GPGME_CONF_STRING:
if (list) {
std::vector<const char *> result;
for (gpgme_conf_arg_t a = arg ; a ; a = a->next) {
result.push_back(a->value.string);
}
return result;
} else {
return arg->value.string;
}
}
assert(!"Option: unknown alt_type!");
return Option::Variant();
}
namespace
{
inline const void *to_void_star(const char *s)
{
return s;
}
inline const void *to_void_star(const std::string &s)
{
return s.c_str();
}
inline const void *to_void_star(const int &i)
{
return &i; // const-&: sic!
}
inline const void *to_void_star(const unsigned int &i)
{
return &i; // const-&: sic!
}
struct VariantToArgumentVisitor : boost::static_visitor<gpgme_conf_arg_t> {
static gpgme_conf_arg_t make_argument(gpgme_conf_type_t type, const void *value)
{
gpgme_conf_arg_t arg = 0;
#ifdef HAVE_GPGME_CONF_ARG_NEW_WITH_CONST_VALUE
if (const gpgme_error_t err = gpgme_conf_arg_new(&arg, type, value)) {
return 0;
}
#else
if (const gpgme_error_t err = gpgme_conf_arg_new(&arg, type, const_cast<void *>(value))) {
return 0;
}
#endif
else {
return arg;
}
}
gpgme_conf_arg_t operator()(bool v) const
{
return v ? make_argument(0) : 0 ;
}
gpgme_conf_arg_t operator()(const char *s) const
{
return make_argument(s ? s : "");
}
gpgme_conf_arg_t operator()(const std::string &s) const
{
return operator()(s.c_str());
}
gpgme_conf_arg_t operator()(int i) const
{
return make_argument(&i);
}
gpgme_conf_arg_t operator()(unsigned int i) const
{
return make_argument(&i);
}
template <typename T>
gpgme_conf_arg_t operator()(const std::vector<T> &value) const
{
gpgme_conf_arg_t result = 0;
gpgme_conf_arg_t last = 0;
for (typename std::vector<T>::const_iterator it = value.begin(), end = value.end() ; it != end ; ++it) {
if (gpgme_conf_arg_t arg = make_argument(to_void_star(*it))) {
if (last) {
last = last->next = arg;
} else {
result = last = arg;
}
}
}
return result;
}
};
}
static gpgme_conf_arg_t variant_to_argument(const Option::Variant &value)
{
VariantToArgumentVisitor v;
return apply_visitor(v, value);
}
optional<Option::Variant> Option::defaultValue() const
{
if (isNull()) {
return optional<Variant>();
} else {
return argument_to_variant(opt->alt_type, opt->flags & GPGME_CONF_LIST, opt->default_value);
}
}
#endif
Argument Option::defaultValue() const Argument Option::defaultValue() const
{ {
if (isNull()) { if (isNull()) {

View File

@ -98,8 +98,7 @@ public:
explicit Component(const shared_gpgme_conf_comp_t &gpgme_comp) explicit Component(const shared_gpgme_conf_comp_t &gpgme_comp)
: comp(gpgme_comp) {} : comp(gpgme_comp) {}
// copy ctor is ok Component(const Component &other) = default;
const Component &operator=(const Component &other) const Component &operator=(const Component &other)
{ {
if (this != &other) { if (this != &other) {
@ -149,6 +148,7 @@ public:
Option(const shared_gpgme_conf_comp_t &gpgme_comp, gpgme_conf_opt_t gpgme_opt) Option(const shared_gpgme_conf_comp_t &gpgme_comp, gpgme_conf_opt_t gpgme_opt)
: comp(gpgme_comp), opt(gpgme_opt) {} : comp(gpgme_comp), opt(gpgme_opt) {}
Option(const Option &other) = default;
const Option &operator=(const Option &other) const Option &operator=(const Option &other)
{ {
if (this != &other) { if (this != &other) {
@ -190,7 +190,7 @@ public:
/*! The value that is in the config file (or null, if it's not set). */ /*! The value that is in the config file (or null, if it's not set). */
Argument activeValue() const; Argument activeValue() const;
/*! The value that is in this object, ie. either activeValue(), newValue(), or defaultValue() */ /*! The value that is in this object, i.e. either activeValue(), newValue(), or defaultValue() */
Argument currentValue() const; Argument currentValue() const;
Argument newValue() const; Argument newValue() const;

View File

@ -50,7 +50,9 @@
#include <gpgme.h> #include <gpgme.h>
#include <functional>
#include <istream> #include <istream>
#include <numeric>
#ifndef NDEBUG #ifndef NDEBUG
#include <iostream> #include <iostream>
using std::cerr; using std::cerr;
@ -128,6 +130,13 @@ const char *Error::asString() const
return mMessage.c_str(); return mMessage.c_str();
} }
std::string Error::asStdString() const
{
std::string message;
format_error(static_cast<gpgme_error_t>(mErr), message);
return message;
}
int Error::code() const int Error::code() const
{ {
return gpgme_err_code(mErr); return gpgme_err_code(mErr);
@ -140,16 +149,12 @@ int Error::sourceID() const
bool Error::isCanceled() const bool Error::isCanceled() const
{ {
return code() == GPG_ERR_CANCELED; return code() == GPG_ERR_CANCELED || code() == GPG_ERR_FULLY_CANCELED;
} }
int Error::toErrno() const int Error::toErrno() const
{ {
//#ifdef HAVE_GPGME_GPG_ERROR_WRAPPERS
return gpgme_err_code_to_errno(static_cast<gpgme_err_code_t>(code())); return gpgme_err_code_to_errno(static_cast<gpgme_err_code_t>(code()));
//#else
// return gpg_err_code_to_errno( static_cast<gpg_err_code_t>( code() ) );
//#endif
} }
// static // static
@ -190,7 +195,20 @@ Error Error::fromCode(unsigned int err, unsigned int src)
std::ostream &operator<<(std::ostream &os, const Error &err) std::ostream &operator<<(std::ostream &os, const Error &err)
{ {
return os << "GpgME::Error(" << err.encodedError() << " (" << err.asString() << "))"; return os << "GpgME::Error(" << err.encodedError() << " (" << err.asStdString() << "))";
}
Context::KeyListModeSaver::KeyListModeSaver(Context *ctx)
: mCtx{ctx}
, mKeyListMode{ctx ? ctx->keyListMode() : 0}
{
}
Context::KeyListModeSaver::~KeyListModeSaver()
{
if (mCtx) {
mCtx->setKeyListMode(mKeyListMode);
}
} }
Context::Context(gpgme_ctx_t ctx) : d(new Private(ctx)) Context::Context(gpgme_ctx_t ctx) : d(new Private(ctx))
@ -461,9 +479,33 @@ Error Context::setLocale(int cat, const char *val)
return Error(d->lasterr = gpgme_set_locale(d->ctx, cat, 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 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) Error Context::setEngineFileName(const char *filename)
@ -496,25 +538,25 @@ const char *Context::getSender ()
Error Context::startKeyListing(const char *pattern, bool secretOnly) Error Context::startKeyListing(const char *pattern, bool secretOnly)
{ {
d->lastop = Private::KeyList; d->lastop = (((keyListMode() & GpgME::Locate) == GpgME::Locate)
? Private::KeyListWithImport
: Private::KeyList);
return Error(d->lasterr = gpgme_op_keylist_start(d->ctx, pattern, int(secretOnly))); return Error(d->lasterr = gpgme_op_keylist_start(d->ctx, pattern, int(secretOnly)));
} }
Error Context::startKeyListing(const char *patterns[], bool secretOnly) Error Context::startKeyListing(const char *patterns[], bool secretOnly)
{ {
d->lastop = Private::KeyList; d->lastop = (((keyListMode() & GpgME::Locate) == GpgME::Locate)
#ifndef HAVE_GPGME_EXT_KEYLIST_MODE_EXTERNAL_NONBROKEN ? Private::KeyListWithImport
if (!patterns || !patterns[0] || !patterns[1]) { : Private::KeyList);
// 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)); return Error(d->lasterr = gpgme_op_keylist_ext_start(d->ctx, patterns, int(secretOnly), 0));
} }
Key Context::nextKey(GpgME::Error &e) Key Context::nextKey(GpgME::Error &e)
{ {
d->lastop = Private::KeyList; d->lastop = (((keyListMode() & GpgME::Locate) == GpgME::Locate)
? Private::KeyListWithImport
: Private::KeyList);
gpgme_key_t key = nullptr; gpgme_key_t key = nullptr;
e = Error(d->lasterr = gpgme_op_keylist_next(d->ctx, &key)); e = Error(d->lasterr = gpgme_op_keylist_next(d->ctx, &key));
return Key(key, false); return Key(key, false);
@ -563,44 +605,137 @@ KeyGenerationResult Context::keyGenerationResult() const
} }
} }
Error Context::exportPublicKeys(const char *pattern, Data &keyData) Error Context::exportKeys(const char *pattern, Data &keyData, unsigned int mode)
{ {
d->lastop = Private::Export; d->lastop = Private::Export;
Data::Private *const dp = keyData.impl(); Data::Private *const dp = keyData.impl();
return Error(d->lasterr = gpgme_op_export(d->ctx, pattern, 0, dp ? dp->data : nullptr)); return Error(d->lasterr = gpgme_op_export(d->ctx, pattern, mode, dp ? dp->data : nullptr));
}
Error Context::exportKeys(const char *patterns[], Data &keyData, unsigned int mode)
{
d->lastop = Private::Export;
Data::Private *const dp = keyData.impl();
return Error(d->lasterr = gpgme_op_export_ext(d->ctx, patterns, mode, dp ? dp->data : nullptr));
}
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, mode, dp ? dp->data : nullptr));
}
Error Context::startKeyExport(const char *patterns[], Data &keyData, unsigned int mode)
{
d->lastop = Private::Export;
Data::Private *const dp = keyData.impl();
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 mode */
Error Context::exportPublicKeys(const char *pattern, Data &keyData)
{
return exportPublicKeys(pattern, keyData, 0);
} }
Error Context::exportPublicKeys(const char *patterns[], Data &keyData) Error Context::exportPublicKeys(const char *patterns[], Data &keyData)
{ {
d->lastop = Private::Export; return exportPublicKeys(patterns, keyData, 0);
#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);
}
#endif
Data::Private *const dp = keyData.impl();
return Error(d->lasterr = gpgme_op_export_ext(d->ctx, patterns, 0, dp ? dp->data : nullptr));
} }
Error Context::startPublicKeyExport(const char *pattern, Data &keyData) Error Context::startPublicKeyExport(const char *pattern, Data &keyData)
{ {
d->lastop = Private::Export; return startPublicKeyExport(pattern, keyData, 0);
Data::Private *const dp = keyData.impl();
return Error(d->lasterr = gpgme_op_export_start(d->ctx, pattern, 0, dp ? dp->data : nullptr));
} }
Error Context::startPublicKeyExport(const char *patterns[], Data &keyData) Error Context::startPublicKeyExport(const char *patterns[], Data &keyData)
{ {
d->lastop = Private::Export; return startPublicKeyExport(patterns, keyData, 0);
#ifndef HAVE_GPGME_EXT_KEYLIST_MODE_EXTERNAL_NONBROKEN }
if (!patterns || !patterns[0] || !patterns[1]) {
// max. one pattern -> use the non-ext version Error Context::exportSecretKeys(const char *pattern, Data &keyData, unsigned int mode)
return startPublicKeyExport(patterns ? patterns[0] : nullptr, keyData); {
if (mode & ExportSecretSubkey) {
return Error::fromCode(GPG_ERR_INV_FLAG);
} }
#endif return exportKeys(pattern, keyData, mode|ExportSecret);
Data::Private *const dp = keyData.impl(); }
return Error(d->lasterr = gpgme_op_export_ext_start(d->ctx, patterns, 0, dp ? dp->data : nullptr));
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) ImportResult Context::importKeys(const Data &data)
@ -687,6 +822,22 @@ Error Context::startKeyImport(const std::vector<Key> &kk)
return err; 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 ImportResult Context::importResult() const
{ {
if (d->lastop & Private::Import) { if (d->lastop & Private::Import) {
@ -922,7 +1073,7 @@ DecryptionResult Context::decrypt(const Data &cipherText, Data &plainText, const
const Data::Private *const cdp = cipherText.impl(); const Data::Private *const cdp = cipherText.impl();
Data::Private *const pdp = plainText.impl(); Data::Private *const pdp = plainText.impl();
d->lasterr = gpgme_op_decrypt_ext(d->ctx, static_cast<gpgme_decrypt_flags_t> (d->decryptFlags | flags), cdp ? cdp->data : nullptr, pdp ? pdp->data : nullptr); d->lasterr = gpgme_op_decrypt_ext(d->ctx, static_cast<gpgme_decrypt_flags_t> (d->decryptFlags | flags), cdp ? cdp->data : nullptr, pdp ? pdp->data : nullptr);
return DecryptionResult(d->ctx, Error(d->lasterr)); return decryptionResult();
} }
DecryptionResult Context::decrypt(const Data &cipherText, Data &plainText) DecryptionResult Context::decrypt(const Data &cipherText, Data &plainText)
@ -959,7 +1110,7 @@ VerificationResult Context::verifyDetachedSignature(const Data &signature, const
const Data::Private *const sdp = signature.impl(); const Data::Private *const sdp = signature.impl();
const Data::Private *const tdp = signedText.impl(); const Data::Private *const tdp = signedText.impl();
d->lasterr = gpgme_op_verify(d->ctx, sdp ? sdp->data : nullptr, tdp ? tdp->data : nullptr, nullptr); d->lasterr = gpgme_op_verify(d->ctx, sdp ? sdp->data : nullptr, tdp ? tdp->data : nullptr, nullptr);
return VerificationResult(d->ctx, Error(d->lasterr)); return verificationResult();
} }
VerificationResult Context::verifyOpaqueSignature(const Data &signedData, Data &plainText) VerificationResult Context::verifyOpaqueSignature(const Data &signedData, Data &plainText)
@ -968,7 +1119,7 @@ VerificationResult Context::verifyOpaqueSignature(const Data &signedData, Data &
const Data::Private *const sdp = signedData.impl(); const Data::Private *const sdp = signedData.impl();
Data::Private *const pdp = plainText.impl(); Data::Private *const pdp = plainText.impl();
d->lasterr = gpgme_op_verify(d->ctx, sdp ? sdp->data : nullptr, nullptr, pdp ? pdp->data : nullptr); d->lasterr = gpgme_op_verify(d->ctx, sdp ? sdp->data : nullptr, nullptr, pdp ? pdp->data : nullptr);
return VerificationResult(d->ctx, Error(d->lasterr)); return verificationResult();
} }
Error Context::startDetachedSignatureVerification(const Data &signature, const Data &signedText) Error Context::startDetachedSignatureVerification(const Data &signature, const Data &signedText)
@ -990,9 +1141,18 @@ Error Context::startOpaqueSignatureVerification(const Data &signedData, Data &pl
VerificationResult Context::verificationResult() const VerificationResult Context::verificationResult() const
{ {
if (d->lastop & Private::Verify) { if (d->lastop & Private::Verify) {
return VerificationResult(d->ctx, Error(d->lasterr)); const auto res = VerificationResult{d->ctx, Error(d->lasterr)};
if ((d->lastop == Private::DecryptAndVerify)
&& (res.error().code() == GPG_ERR_NO_DATA)
&& (res.numSignatures() > 0)) {
// ignore "no data" error for verification if there are signatures and
// the operation was a combined (tentative) decryption and verification
// because then "no data" just indicates that there was nothing to decrypt
return VerificationResult{d->ctx, Error{}};
}
return res;
} else { } else {
return VerificationResult(); return {};
} }
} }
@ -1003,8 +1163,7 @@ std::pair<DecryptionResult, VerificationResult> Context::decryptAndVerify(const
Data::Private *const pdp = plainText.impl(); Data::Private *const pdp = plainText.impl();
d->lasterr = gpgme_op_decrypt_ext(d->ctx, static_cast<gpgme_decrypt_flags_t> (d->decryptFlags | flags | DecryptVerify), d->lasterr = gpgme_op_decrypt_ext(d->ctx, static_cast<gpgme_decrypt_flags_t> (d->decryptFlags | flags | DecryptVerify),
cdp ? cdp->data : nullptr, pdp ? pdp->data : nullptr); cdp ? cdp->data : nullptr, pdp ? pdp->data : nullptr);
return std::make_pair(DecryptionResult(d->ctx, Error(d->lasterr)), return std::make_pair(decryptionResult(), verificationResult());
VerificationResult(d->ctx, Error(d->lasterr)));
} }
std::pair<DecryptionResult, VerificationResult> Context::decryptAndVerify(const Data &cipherText, Data &plainText) std::pair<DecryptionResult, VerificationResult> Context::decryptAndVerify(const Data &cipherText, Data &plainText)
@ -1025,6 +1184,7 @@ Error Context::startCombinedDecryptionAndVerification(const Data &cipherText, Da
return startCombinedDecryptionAndVerification(cipherText, plainText, DecryptNone); return startCombinedDecryptionAndVerification(cipherText, plainText, DecryptNone);
} }
namespace {
unsigned int to_auditlog_flags(unsigned int flags) unsigned int to_auditlog_flags(unsigned int flags)
{ {
unsigned int result = 0; unsigned int result = 0;
@ -1039,6 +1199,7 @@ unsigned int to_auditlog_flags(unsigned int flags)
} }
return result; return result;
} }
}
Error Context::startGetAuditLog(Data &output, unsigned int flags) Error Context::startGetAuditLog(Data &output, unsigned int flags)
{ {
@ -1128,14 +1289,25 @@ std::vector<Notation> Context::signatureNotations() const
return result; return result;
} }
static gpgme_sig_mode_t sigmode2sigmode(SignatureMode mode) static gpgme_sig_mode_t sigflags2sigflags(SignatureMode flags)
{ {
switch (mode) { unsigned int result = 0;
default: if (flags & SignatureMode::NormalSignatureMode) {
case NormalSignatureMode: return GPGME_SIG_MODE_NORMAL; result |= GPGME_SIG_MODE_NORMAL;
case Detached: return GPGME_SIG_MODE_DETACH;
case Clearsigned: return GPGME_SIG_MODE_CLEAR;
} }
if (flags & SignatureMode::Detached) {
result |= GPGME_SIG_MODE_DETACH;
}
if (flags & SignatureMode::Clearsigned) {
result |= GPGME_SIG_MODE_CLEAR;
}
if (flags & SignatureMode::SignArchive) {
result |= GPGME_SIG_MODE_ARCHIVE;
}
if (flags & SignatureMode::SignFile) {
result |= GPGME_SIG_MODE_FILE;
}
return static_cast<gpgme_sig_mode_t>(result);
} }
SigningResult Context::sign(const Data &plainText, Data &signature, SignatureMode mode) SigningResult Context::sign(const Data &plainText, Data &signature, SignatureMode mode)
@ -1143,7 +1315,7 @@ SigningResult Context::sign(const Data &plainText, Data &signature, SignatureMod
d->lastop = Private::Sign; d->lastop = Private::Sign;
const Data::Private *const pdp = plainText.impl(); const Data::Private *const pdp = plainText.impl();
Data::Private *const sdp = signature.impl(); Data::Private *const sdp = signature.impl();
d->lasterr = gpgme_op_sign(d->ctx, pdp ? pdp->data : nullptr, sdp ? sdp->data : nullptr, sigmode2sigmode(mode)); d->lasterr = gpgme_op_sign(d->ctx, pdp ? pdp->data : nullptr, sdp ? sdp->data : nullptr, sigflags2sigflags(mode));
return SigningResult(d->ctx, Error(d->lasterr)); return SigningResult(d->ctx, Error(d->lasterr));
} }
@ -1152,7 +1324,7 @@ Error Context::startSigning(const Data &plainText, Data &signature, SignatureMod
d->lastop = Private::Sign; d->lastop = Private::Sign;
const Data::Private *const pdp = plainText.impl(); const Data::Private *const pdp = plainText.impl();
Data::Private *const sdp = signature.impl(); Data::Private *const sdp = signature.impl();
return Error(d->lasterr = gpgme_op_sign_start(d->ctx, pdp ? pdp->data : nullptr, sdp ? sdp->data : nullptr, sigmode2sigmode(mode))); return Error(d->lasterr = gpgme_op_sign_start(d->ctx, pdp ? pdp->data : nullptr, sdp ? sdp->data : nullptr, sigflags2sigflags(mode)));
} }
SigningResult Context::signingResult() const SigningResult Context::signingResult() const
@ -1185,6 +1357,21 @@ static gpgme_encrypt_flags_t encryptflags2encryptflags(Context::EncryptionFlags
if (flags & Context::Symmetric) { if (flags & Context::Symmetric) {
result |= GPGME_ENCRYPT_SYMMETRIC; result |= GPGME_ENCRYPT_SYMMETRIC;
} }
if (flags & Context::ThrowKeyIds) {
result |= GPGME_ENCRYPT_THROW_KEYIDS;
}
if (flags & Context::EncryptWrap) {
result |= GPGME_ENCRYPT_WRAP;
}
if (flags & Context::WantAddress) {
result |= GPGME_ENCRYPT_WANT_ADDRESS;
}
if (flags & Context::EncryptArchive) {
result |= GPGME_ENCRYPT_ARCHIVE;
}
if (flags & Context::EncryptFile) {
result |= GPGME_ENCRYPT_FILE;
}
return static_cast<gpgme_encrypt_flags_t>(result); return static_cast<gpgme_encrypt_flags_t>(result);
} }
@ -1320,6 +1507,11 @@ Error Context::cancelPendingOperation()
return Error(gpgme_cancel_async(d->ctx)); return Error(gpgme_cancel_async(d->ctx));
} }
Error Context::cancelPendingOperationImmediately()
{
return Error(gpgme_cancel(d->ctx));
}
bool Context::poll() bool Context::poll()
{ {
gpgme_error_t e = GPG_ERR_NO_ERROR; gpgme_error_t e = GPG_ERR_NO_ERROR;
@ -1486,6 +1678,16 @@ Error Context::startRevUid(const Key &k, const char *userid)
k.impl(), userid, 0)); k.impl(), userid, 0));
} }
Error Context::setPrimaryUid(const Key &k, const char *userid)
{
return Error(d->lasterr = gpgme_op_set_uid_flag(d->ctx, k.impl(), userid, "primary", nullptr));
}
Error Context::startSetPrimaryUid(const Key &k, const char *userid)
{
return Error(d->lasterr = gpgme_op_set_uid_flag_start(d->ctx, k.impl(), userid, "primary", nullptr));
}
Error Context::createSubkey(const Key &k, const char *algo, Error Context::createSubkey(const Key &k, const char *algo,
unsigned long reserved, unsigned long reserved,
unsigned long expires, unsigned long expires,
@ -1504,6 +1706,112 @@ Error Context::startCreateSubkey(const Key &k, const char *algo,
k.impl(), algo, reserved, expires, flags)); k.impl(), algo, reserved, expires, flags));
} }
static std::string getLFSeparatedListOfStrings(const std::vector<std::string> &strings)
{
if (strings.empty()) {
return std::string();
}
return std::accumulate(
std::next(strings.begin()),
strings.end(),
strings[0],
[](const std::string &a, const std::string &b) {
return a + '\n' + b;
}
);
}
static std::string getLFSeparatedListOfFingerprintsFromSubkeys(const std::vector<Subkey> &subkeys)
{
if (subkeys.empty()) {
return std::string();
}
std::vector<std::string> fprs;
fprs.reserve(subkeys.size());
for (auto &it : subkeys) {
if (it.fingerprint()) {
fprs.push_back(std::string(it.fingerprint()));
}
}
return getLFSeparatedListOfStrings(fprs);
}
Error Context::setExpire(const Key &k, unsigned long expires,
const std::vector<Subkey> &subkeys,
const Context::SetExpireFlags flags)
{
std::string subfprs;
if (flags & Context::SetExpireAllSubkeys) {
subfprs = "*";
} else {
subfprs = getLFSeparatedListOfFingerprintsFromSubkeys(subkeys);
}
return Error(d->lasterr = gpgme_op_setexpire(d->ctx,
k.impl(), expires, subfprs.c_str(), 0));
}
Error Context::startSetExpire(const Key &k, unsigned long expires,
const std::vector<Subkey> &subkeys,
const Context::SetExpireFlags flags)
{
std::string subfprs;
if (flags & Context::SetExpireAllSubkeys) {
subfprs = "*";
} else {
subfprs = getLFSeparatedListOfFingerprintsFromSubkeys(subkeys);
}
return Error(d->lasterr = gpgme_op_setexpire_start(d->ctx,
k.impl(), expires, subfprs.c_str(), 0));
}
static std::string getLFSeparatedListOfUserIds(const std::vector<UserID> &userIds)
{
if (userIds.empty()) {
return std::string();
}
std::vector<std::string> uids;
uids.reserve(userIds.size());
for (auto &userId : userIds) {
if (userId.id()) {
uids.push_back(std::string(userId.id()));
}
}
return getLFSeparatedListOfStrings(uids);
}
Error Context::revokeSignature(const Key &key, const Key &signingKey,
const std::vector<UserID> &userIds)
{
const unsigned int flags = userIds.size() > 1 ? GPGME_REVSIG_LFSEP : 0;
const std::string uids = getLFSeparatedListOfUserIds(userIds);
return Error(d->lasterr = gpgme_op_revsig(d->ctx,
key.impl(), signingKey.impl(), uids.c_str(), flags));
}
Error Context::startRevokeSignature(const Key &key, const Key &signingKey,
const std::vector<UserID> &userIds)
{
const unsigned int flags = userIds.size() > 1 ? GPGME_REVSIG_LFSEP : 0;
const std::string uids = getLFSeparatedListOfUserIds(userIds);
return Error(d->lasterr = gpgme_op_revsig_start(d->ctx,
key.impl(), signingKey.impl(), uids.c_str(), flags));
}
Error Context::addAdsk(const Key &k, const char *adsk)
{
return Error(d->lasterr = gpgme_op_createsubkey(d->ctx, k.impl(), adsk, 0, 0, GPGME_CREATE_ADSK));
}
Error Context::startAddAdsk(const Key &k, const char *adsk)
{
return Error(d->lasterr = gpgme_op_createsubkey_start(d->ctx, k.impl(), adsk, 0, 0, GPGME_CREATE_ADSK));
}
Error Context::setFlag(const char *name, const char *value) Error Context::setFlag(const char *name, const char *value)
{ {
return Error(d->lasterr = gpgme_set_ctx_flag(d->ctx, name, value)); return Error(d->lasterr = gpgme_set_ctx_flag(d->ctx, name, value));
@ -1615,6 +1923,9 @@ std::ostream &operator<<(std::ostream &os, KeyListMode mode)
CHECK(Validate); CHECK(Validate);
CHECK(Ephemeral); CHECK(Ephemeral);
CHECK(WithTofu); CHECK(WithTofu);
CHECK(WithKeygrip);
CHECK(WithSecret);
CHECK(ForceExtern);
#undef CHECK #undef CHECK
return os << ')'; return os << ')';
} }
@ -1622,7 +1933,8 @@ std::ostream &operator<<(std::ostream &os, KeyListMode mode)
std::ostream &operator<<(std::ostream &os, SignatureMode mode) std::ostream &operator<<(std::ostream &os, SignatureMode mode)
{ {
os << "GpgME::SignatureMode("; os << "GpgME::SignatureMode(";
switch (mode) { #undef CHECK
switch (mode & (NormalSignatureMode|Detached|Clearsigned)) {
#define CHECK( x ) case x: os << #x; break #define CHECK( x ) case x: os << #x; break
CHECK(NormalSignatureMode); CHECK(NormalSignatureMode);
CHECK(Detached); CHECK(Detached);
@ -1632,6 +1944,10 @@ std::ostream &operator<<(std::ostream &os, SignatureMode mode)
os << "???" "(" << static_cast<int>(mode) << ')'; os << "???" "(" << static_cast<int>(mode) << ')';
break; break;
} }
#define CHECK( x ) if ( !(mode & (x)) ) {} else do { os << #x " "; } while (0)
CHECK(SignArchive);
CHECK(SignFile);
#undef CHECK
return os << ')'; return os << ')';
} }
@ -1645,6 +1961,11 @@ std::ostream &operator<<(std::ostream &os, Context::EncryptionFlags flags)
CHECK(ExpectSign); CHECK(ExpectSign);
CHECK(NoCompress); CHECK(NoCompress);
CHECK(Symmetric); CHECK(Symmetric);
CHECK(ThrowKeyIds);
CHECK(EncryptWrap);
CHECK(WantAddress);
CHECK(EncryptArchive);
CHECK(EncryptFile);
#undef CHECK #undef CHECK
return os << ')'; return os << ')';
} }
@ -1668,20 +1989,7 @@ GpgME::Error GpgME::setDefaultLocale(int cat, const char *val)
GpgME::EngineInfo GpgME::engineInfo(GpgME::Protocol proto) GpgME::EngineInfo GpgME::engineInfo(GpgME::Protocol proto)
{ {
gpgme_engine_info_t ei = nullptr; return get_static_engine_info(proto == CMS ? GPGME_PROTOCOL_CMS : GPGME_PROTOCOL_OpenPGP);
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();
} }
const char *GpgME::dirInfo(const char *what) const char *GpgME::dirInfo(const char *what)
@ -1719,20 +2027,7 @@ static gpgme_protocol_t engine2protocol(const GpgME::Engine engine)
GpgME::EngineInfo GpgME::engineInfo(GpgME::Engine engine) GpgME::EngineInfo GpgME::engineInfo(GpgME::Engine engine)
{ {
gpgme_engine_info_t ei = nullptr; return get_static_engine_info(engine2protocol(engine));
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();
} }
GpgME::Error GpgME::checkEngine(GpgME::Engine engine) GpgME::Error GpgME::checkEngine(GpgME::Engine engine)

View File

@ -27,9 +27,11 @@
#include "global.h" #include "global.h"
#include "error.h" #include "error.h"
#include "key.h"
#include "verificationresult.h" // for Signature::Notation #include "verificationresult.h" // for Signature::Notation
#include <memory> #include <memory>
#include <string>
#include <vector> #include <vector>
#include <utility> #include <utility>
#include <iosfwd> #include <iosfwd>
@ -37,7 +39,6 @@
namespace GpgME namespace GpgME
{ {
class Key;
class Data; class Data;
class TrustItem; class TrustItem;
class ProgressProvider; class ProgressProvider;
@ -63,6 +64,17 @@ class GPGMEPP_EXPORT Context
public: public:
//using GpgME::Protocol; //using GpgME::Protocol;
/// RAII-style class for saving/restoring the key list mode.
class GPGMEPP_EXPORT KeyListModeSaver
{
public:
explicit KeyListModeSaver(Context *ctx);
~KeyListModeSaver();
private:
Context *mCtx;
unsigned int mKeyListMode;
};
// //
// Creation and destruction: // Creation and destruction:
// //
@ -182,11 +194,42 @@ public:
// //
// Key Export // Key Export
// //
enum ExportMode {
ExportDefault = 0,
ExportExtern = 2,
ExportMinimal = 4,
ExportSecret = 16,
ExportRaw = 32,
ExportPKCS12 = 64,
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);
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);
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);
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);
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 // Key Import
@ -194,8 +237,10 @@ public:
ImportResult importKeys(const Data &data); ImportResult importKeys(const Data &data);
ImportResult importKeys(const std::vector<Key> &keys); 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 Data &data);
GpgME::Error startKeyImport(const std::vector<Key> &keys); GpgME::Error startKeyImport(const std::vector<Key> &keys);
GpgME::Error startKeyImport(const std::vector<std::string> &keyIds);
ImportResult importResult() const; ImportResult importResult() const;
// //
@ -250,6 +295,9 @@ public:
Error revUid(const Key &key, const char *userid); Error revUid(const Key &key, const char *userid);
Error startRevUid(const Key &key, const char *userid); Error startRevUid(const Key &key, const char *userid);
Error setPrimaryUid(const Key &key, const char *userid);
Error startSetPrimaryUid(const Key &key, const char *userid);
Error createSubkey(const Key &key, const char *algo, Error createSubkey(const Key &key, const char *algo,
unsigned long reserved = 0, unsigned long reserved = 0,
unsigned long expires = 0, unsigned long expires = 0,
@ -259,6 +307,26 @@ public:
unsigned long expires = 0, unsigned long expires = 0,
unsigned int flags = 0); unsigned int flags = 0);
enum SetExpireFlags {
SetExpireDefault = 0,
SetExpireAllSubkeys = 1
};
Error setExpire(const Key &k, unsigned long expires,
const std::vector<Subkey> &subkeys = std::vector<Subkey>(),
const SetExpireFlags flags = SetExpireDefault);
Error startSetExpire(const Key &k, unsigned long expires,
const std::vector<Subkey> &subkeys = std::vector<Subkey>(),
const SetExpireFlags flags = SetExpireDefault);
Error revokeSignature(const Key &key, const Key &signingKey,
const std::vector<UserID> &userIds = std::vector<UserID>());
Error startRevokeSignature(const Key &key, const Key &signingKey,
const std::vector<UserID> &userIds = std::vector<UserID>());
Error addAdsk(const Key &k, const char *adsk);
Error startAddAdsk(const Key &k, const char *adsk);
// using TofuInfo::Policy // using TofuInfo::Policy
Error setTofuPolicy(const Key &k, unsigned int policy); Error setTofuPolicy(const Key &k, unsigned int policy);
Error setTofuPolicyStart(const Key &k, unsigned int policy); Error setTofuPolicyStart(const Key &k, unsigned int policy);
@ -305,6 +373,7 @@ public:
// Keep in line with core's flags // Keep in line with core's flags
DecryptNone = 0, DecryptNone = 0,
DecryptVerify = 1, DecryptVerify = 1,
DecryptArchive = 2,
DecryptUnwrap = 128, DecryptUnwrap = 128,
DecryptMaxValue = 0x80000000 DecryptMaxValue = 0x80000000
}; };
@ -382,7 +451,10 @@ public:
NoCompress = 16, NoCompress = 16,
Symmetric = 32, Symmetric = 32,
ThrowKeyIds = 64, ThrowKeyIds = 64,
EncryptWrap = 128 EncryptWrap = 128,
WantAddress = 256,
EncryptArchive = 512,
EncryptFile = 1024
}; };
EncryptionResult encrypt(const std::vector<Key> &recipients, const Data &plainText, Data &cipherText, EncryptionFlags flags); EncryptionResult encrypt(const std::vector<Key> &recipients, const Data &plainText, Data &cipherText, EncryptionFlags flags);
GpgME::Error encryptSymmetrically(const Data &plainText, Data &cipherText); GpgME::Error encryptSymmetrically(const Data &plainText, Data &cipherText);
@ -458,6 +530,7 @@ public:
GpgME::Error wait(); GpgME::Error wait();
GpgME::Error lastError() const; GpgME::Error lastError() const;
GpgME::Error cancelPendingOperation(); GpgME::Error cancelPendingOperation();
GpgME::Error cancelPendingOperationImmediately();
class Private; class Private;
const Private *impl() const const Private *impl() const

View File

@ -53,6 +53,7 @@ public:
KeyGen = 0x080, KeyGen = 0x080,
KeyList = 0x100, KeyList = 0x100,
KeyListWithImport = KeyList | Import, // gpgme_keylist_result_t and gpgme_import_result_t
TrustList = 0x200, // no gpgme_trustlist_result_t, but nevertheless... TrustList = 0x200, // no gpgme_trustlist_result_t, but nevertheless...
Edit = 0x400, // no gpgme_edit_result_t, but nevertheless... Edit = 0x400, // no gpgme_edit_result_t, but nevertheless...

View File

@ -217,6 +217,11 @@ GpgME::Error GpgME::Data::setFileName(const char *name)
return Error(gpgme_data_set_file_name(d->data, name)); return Error(gpgme_data_set_file_name(d->data, name));
} }
GpgME::Error GpgME::Data::setFileName(const std::string &name)
{
return Error(gpgme_data_set_file_name(d->data, name.c_str()));
}
ssize_t GpgME::Data::read(void *buffer, size_t length) ssize_t GpgME::Data::read(void *buffer, size_t length)
{ {
return gpgme_data_read(d->data, buffer, length); return gpgme_data_read(d->data, buffer, length);
@ -275,3 +280,14 @@ std::string GpgME::Data::toString()
seek (0, SEEK_SET); seek (0, SEEK_SET);
return ret; return ret;
} }
GpgME::Error GpgME::Data::setFlag(const char *name, const char *value)
{
return Error(gpgme_data_set_flag(d->data, name, value));
}
GpgME::Error GpgME::Data::setSizeHint(uint64_t size)
{
const std::string val = std::to_string(size);
return Error(gpgme_data_set_flag(d->data, "size-hint", val.c_str()));
}

View File

@ -27,6 +27,7 @@
#include "key.h" #include "key.h"
#include <sys/types.h> // for size_t, off_t #include <sys/types.h> // for size_t, off_t
#include <cstdint> // unit64_t
#include <cstdio> // FILE #include <cstdio> // FILE
#include <algorithm> #include <algorithm>
#include <memory> #include <memory>
@ -60,6 +61,7 @@ public:
static const Null null; static const Null null;
Data(const Data &other) = default;
const Data &operator=(Data other) const Data &operator=(Data other)
{ {
swap(other); swap(other);
@ -105,6 +107,7 @@ public:
char *fileName() const; char *fileName() const;
Error setFileName(const char *name); Error setFileName(const char *name);
Error setFileName(const std::string &name);
ssize_t read(void *buffer, size_t length); ssize_t read(void *buffer, size_t length);
ssize_t write(const void *buffer, size_t length); ssize_t write(const void *buffer, size_t length);
@ -120,6 +123,12 @@ public:
/** Return a copy of the data as std::string. Sets seek pos to 0 */ /** Return a copy of the data as std::string. Sets seek pos to 0 */
std::string toString(); std::string toString();
/** See gpgme_data_set_flag */
Error setFlag(const char *name, const char *value);
/** Set a size hint for this data e.g. for progress calculations. */
Error setSizeHint(uint64_t size);
class Private; class Private;
Private *impl() Private *impl()
{ {

View File

@ -122,6 +122,11 @@ bool GpgME::DecryptionResult::isDeVs() const
return d && d->res.is_de_vs; return d && d->res.is_de_vs;
} }
bool GpgME::DecryptionResult::isMime() const
{
return d && d->res.is_mime;
}
const char *GpgME::DecryptionResult::fileName() const const char *GpgME::DecryptionResult::fileName() const
{ {
return d ? d->res.file_name : nullptr ; return d ? d->res.file_name : nullptr ;

View File

@ -47,6 +47,7 @@ public:
DecryptionResult(gpgme_ctx_t ctx, const Error &err); DecryptionResult(gpgme_ctx_t ctx, const Error &err);
explicit DecryptionResult(const Error &err); explicit DecryptionResult(const Error &err);
DecryptionResult(const DecryptionResult &other) = default;
const DecryptionResult &operator=(DecryptionResult other) const DecryptionResult &operator=(DecryptionResult other)
{ {
swap(other); swap(other);
@ -74,6 +75,7 @@ public:
} }
bool isWrongKeyUsage() const; bool isWrongKeyUsage() const;
bool isDeVs() const; bool isDeVs() const;
bool isMime() const;
const char *fileName() const; const char *fileName() const;
@ -103,6 +105,7 @@ public:
Recipient(); Recipient();
explicit Recipient(gpgme_recipient_t reci); explicit Recipient(gpgme_recipient_t reci);
Recipient(const Recipient &other) = default;
const Recipient &operator=(Recipient other) const Recipient &operator=(Recipient other)
{ {
swap(other); swap(other);

View File

@ -30,8 +30,6 @@
#include "error.h" #include "error.h"
#include "data.h" #include "data.h"
#include <sstream>
using namespace GpgME; using namespace GpgME;
DefaultAssuanTransaction::DefaultAssuanTransaction() DefaultAssuanTransaction::DefaultAssuanTransaction()

View File

@ -25,7 +25,7 @@
#ifndef __GPGMEPP_DEFAULTASSUANTRANSACTION_H__ #ifndef __GPGMEPP_DEFAULTASSUANTRANSACTION_H__
#define __GPGMEPP_DEFAULTASSUANTRANSACTION_H__ #define __GPGMEPP_DEFAULTASSUANTRANSACTION_H__
#include <interfaces/assuantransaction.h> #include "interfaces/assuantransaction.h"
#include <string> #include <string>
#include <vector> #include <vector>

View File

@ -29,6 +29,7 @@
#include "editinteractor.h" #include "editinteractor.h"
#include "callbacks.h" #include "callbacks.h"
#include "error.h" #include "error.h"
#include "util.h"
#include <gpgme.h> #include <gpgme.h>
@ -41,6 +42,7 @@
#include <cerrno> #include <cerrno>
#include <cstring> #include <cstring>
#include <cstdlib>
#ifndef GPG_ERR_ALREADY_SIGNED #ifndef GPG_ERR_ALREADY_SIGNED
# define GPG_ERR_ALREADY_SIGNED GPG_ERR_USER_1 # define GPG_ERR_ALREADY_SIGNED GPG_ERR_USER_1
@ -50,6 +52,7 @@ using namespace GpgME;
static const char *status_to_string(unsigned int status); static const char *status_to_string(unsigned int status);
static Error status_to_error(unsigned int status); static Error status_to_error(unsigned int status);
static Error parse_sc_op_failure(const char *args);
class EditInteractor::Private class EditInteractor::Private
{ {
@ -61,9 +64,10 @@ public:
~Private(); ~Private();
private: private:
unsigned int state; unsigned int state = StartState;
Error error; Error error;
std::FILE *debug; std::FILE *debug = nullptr;
bool debugNeedsClosing = false;
}; };
class GpgME::CallbackHelper class GpgME::CallbackHelper
@ -93,12 +97,24 @@ public:
// advance to next state based on input: // advance to next state based on input:
const unsigned int oldState = ei->state; const unsigned int oldState = ei->state;
ei->state = ei->q->nextState(status, args, err);
if (ei->q->needsNoResponse(status)) {
// keep state
} else if (status == GPGME_STATUS_ERROR) {
err = ei->q->parseStatusError(args);
ei->state = EditInteractor::ErrorState;
} else if (status == GPGME_STATUS_SC_OP_FAILURE) {
err = parse_sc_op_failure(args);
ei->state = EditInteractor::ErrorState;
} else {
ei->state = ei->q->nextState(status, args, err);
}
if (ei->debug) { if (ei->debug) {
std::fprintf(ei->debug, "EditInteractor: %u -> nextState( %s, %s ) -> %u\n", std::fprintf(ei->debug, "EditInteractor: %u -> nextState( %s, %s ) -> %u\n",
oldState, status_to_string(status), args ? args : "<null>", ei->state); oldState, status_to_string(status), args ? args : "<null>", ei->state);
} }
if (err) { if (err || err.isCanceled()) {
ei->state = oldState; ei->state = oldState;
goto error; goto error;
} }
@ -122,7 +138,7 @@ public:
if (writeAll(fd, result, len) != len) { if (writeAll(fd, result, len) != len) {
err = Error::fromSystemError(); err = Error::fromSystemError();
if (ei->debug) { if (ei->debug) {
std::fprintf(ei->debug, "EditInteractor: Could not write to fd %d (%s)\n", fd, err.asString()); std::fprintf(ei->debug, "EditInteractor: Could not write to fd %d (%s)\n", fd, err.asStdString().c_str());
} }
goto error; goto error;
} }
@ -131,7 +147,7 @@ public:
if (writeAll(fd, "\n", 1) != 1) { if (writeAll(fd, "\n", 1) != 1) {
err = Error::fromSystemError(); err = Error::fromSystemError();
if (ei->debug) { if (ei->debug) {
std::fprintf(ei->debug, "EditInteractor: Could not write to fd %d (%s)\n", fd, err.asString()); std::fprintf(ei->debug, "EditInteractor: Could not write to fd %d (%s)\n", fd, err.asStdString().c_str());
} }
goto error; goto error;
} }
@ -151,7 +167,7 @@ public:
} }
error: error:
if (err) { if (err || err.isCanceled()) {
ei->error = err; ei->error = err;
ei->state = EditInteractor::ErrorState; ei->state = EditInteractor::ErrorState;
} }
@ -173,15 +189,28 @@ static gpgme_error_t edit_interactor_callback(void *opaque, gpgme_status_code_t
const gpgme_edit_cb_t GpgME::edit_interactor_callback = ::edit_interactor_callback; const gpgme_edit_cb_t GpgME::edit_interactor_callback = ::edit_interactor_callback;
EditInteractor::Private::Private(EditInteractor *qq) EditInteractor::Private::Private(EditInteractor *qq)
: q(qq), : q(qq)
state(StartState),
error(),
debug(nullptr)
{ {
const char *debug_env = std::getenv("GPGMEPP_INTERACTOR_DEBUG");
if (!debug_env) {
return;
}
if (!strcmp(debug_env, "stdout")) {
debug = stdout;
} else if (!strcmp(debug_env, "stderr")) {
debug = stderr;
} else if (debug_env) {
debug = std::fopen(debug_env, "a+");
debugNeedsClosing = true;
}
} }
EditInteractor::Private::~Private() {} EditInteractor::Private::~Private()
{
if (debug && debugNeedsClosing) {
std::fclose(debug);
}
}
EditInteractor::EditInteractor() EditInteractor::EditInteractor()
: d(new Private(this)) : d(new Private(this))
@ -241,6 +270,52 @@ void EditInteractor::setDebugChannel(std::FILE *debug)
d->debug = debug; d->debug = debug;
} }
GpgME::Error EditInteractor::parseStatusError(const char *args)
{
Error err;
const auto fields = split(args, ' ');
if (fields.size() >= 2) {
err = Error{static_cast<unsigned int>(std::stoul(fields[1]))};
} else {
err = Error::fromCode(GPG_ERR_GENERAL);
}
return err;
}
static Error sc_op_failure_to_error(unsigned int status)
{
switch (status) {
case 1:
// GPG_ERR_CANCELED or GPG_ERR_FULLY_CANCELED
return Error::fromCode(GPG_ERR_CANCELED);
case 2:
// GPG_ERR_BAD_PIN or GPG_ERR_BAD_RESET_CODE [sic]
return Error::fromCode(GPG_ERR_BAD_PIN);
case 3:
return Error::fromCode(GPG_ERR_PIN_BLOCKED);
case 4:
return Error::fromCode(GPG_ERR_NO_RESET_CODE);
}
return Error::fromCode(GPG_ERR_CARD);
}
// static
Error parse_sc_op_failure(const char *args)
{
Error err;
const auto fields = split(args, ' ');
if (fields.size() >= 1) {
err = sc_op_failure_to_error(static_cast<unsigned int>(std::stoul(fields[0])));
} else {
err = Error::fromCode(GPG_ERR_CARD);
}
return err;
}
static const char *const status_strings[] = { static const char *const status_strings[] = {
"EOF", "EOF",
/* mkstatus processing starts here */ /* mkstatus processing starts here */

View File

@ -60,6 +60,9 @@ public:
void setDebugChannel(std::FILE *file); void setDebugChannel(std::FILE *file);
protected:
Error parseStatusError(const char *args);
private: private:
class Private; class Private;
Private *const d; Private *const d;

View File

@ -48,6 +48,7 @@ public:
EncryptionResult(gpgme_ctx_t ctx, const Error &error); EncryptionResult(gpgme_ctx_t ctx, const Error &error);
EncryptionResult(const Error &err); EncryptionResult(const Error &err);
EncryptionResult(const EncryptionResult &other) = default;
const EncryptionResult &operator=(EncryptionResult other) const EncryptionResult &operator=(EncryptionResult other)
{ {
swap(other); swap(other);
@ -83,6 +84,7 @@ class GPGMEPP_EXPORT InvalidRecipient
public: public:
InvalidRecipient(); InvalidRecipient();
InvalidRecipient(const InvalidRecipient &other) = default;
const InvalidRecipient &operator=(InvalidRecipient other) const InvalidRecipient &operator=(InvalidRecipient other)
{ {
swap(other); swap(other);

View File

@ -69,6 +69,76 @@ public:
} }
} }
bool operator < (const Version& other) const
{
if (major > other.major ||
(major == other.major && minor > other.minor) ||
(major == other.major && minor == other.minor && patch > other.patch) ||
(major >= other.major && minor >= other.minor && patch >= other.patch)) {
return false;
}
return true;
}
bool operator < (const char* other) const
{
return operator<(Version(other));
}
bool operator <= (const Version &other) const
{
return !operator>(other);
}
bool operator <= (const char *other) const
{
return operator<=(Version(other));
}
bool operator > (const char* other) const
{
return operator>(Version(other));
}
bool operator > (const Version & other) const
{
return !operator<(other) && !operator==(other);
}
bool operator >= (const Version &other) const
{
return !operator<(other);
}
bool operator >= (const char *other) const
{
return operator>=(Version(other));
}
bool operator == (const Version& other) const
{
return major == other.major
&& minor == other.minor
&& patch == other.patch;
}
bool operator == (const char* other) const
{
return operator==(Version(other));
}
bool operator != (const Version &other) const
{
return !operator==(other);
}
bool operator != (const char *other) const
{
return operator!=(Version(other));
}
// the non-const overloads of the comparison operators are kept for
// binary compatibility
bool operator < (const Version& other) bool operator < (const Version& other)
{ {
if (major > other.major || if (major > other.major ||
@ -85,15 +155,36 @@ public:
return operator<(Version(other)); return operator<(Version(other));
} }
bool operator <= (const Version &other)
{
return !operator>(other);
}
bool operator <= (const char *other)
{
return operator<=(Version(other));
}
bool operator > (const char* other) bool operator > (const char* other)
{ {
return !operator<(Version(other)); return operator>(Version(other));
} }
bool operator > (const Version & other) bool operator > (const Version & other)
{
return !operator<(other) && !operator==(other);
}
bool operator >= (const Version &other)
{ {
return !operator<(other); return !operator<(other);
} }
bool operator >= (const char *other)
{
return operator>=(Version(other));
}
bool operator == (const Version& other) bool operator == (const Version& other)
{ {
return major == other.major return major == other.major
@ -106,6 +197,16 @@ public:
return operator==(Version(other)); return operator==(Version(other));
} }
bool operator != (const Version &other)
{
return !operator==(other);
}
bool operator != (const char *other)
{
return operator!=(Version(other));
}
friend std::ostream& operator << (std::ostream& stream, const Version& ver) friend std::ostream& operator << (std::ostream& stream, const Version& ver)
{ {
stream << ver.major; stream << ver.major;
@ -120,6 +221,7 @@ public:
EngineInfo(); EngineInfo();
explicit EngineInfo(gpgme_engine_info_t engine); explicit EngineInfo(gpgme_engine_info_t engine);
EngineInfo(const EngineInfo &other) = default;
const EngineInfo &operator=(EngineInfo other) const EngineInfo &operator=(EngineInfo other)
{ {
swap(other); swap(other);

View File

@ -47,7 +47,11 @@ public:
explicit Error(unsigned int e) : mErr(e), mMessage() {} explicit Error(unsigned int e) : mErr(e), mMessage() {}
const char *source() const; const char *source() const;
const char *asString() const; /* This function is deprecated. Use asStdString() instead. asString() may
* return wrongly encoded (i.e. not UTF-8) results on Windows for the main
* thread if the function was first called from a secondary thread. */
GPGMEPP_DEPRECATED const char *asString() const;
std::string asStdString() const;
int code() const; int code() const;
int sourceID() const; int sourceID() const;

View File

@ -60,15 +60,34 @@ enum Engine { GpgEngine, GpgSMEngine, GpgConfEngine, UnknownEngine, AssuanEngine
enum KeyListMode { enum KeyListMode {
Local = 0x1, Local = 0x1,
Extern = 0x2, Extern = 0x2,
Locate = 0x3, Locate = Local|Extern,
Signatures = 0x4, Signatures = 0x4,
SignatureNotations = 0x8, SignatureNotations = 0x8,
Validate = 0x10, Validate = 0x10,
Ephemeral = 0x20, Ephemeral = 0x20,
WithTofu = 0x40 WithTofu = 0x40,
WithKeygrip = 0x80,
WithSecret = 0x100,
ForceExtern = 0x200,
LocateExternal = Locate|ForceExtern,
KeyListModeMask = 0x3ff
}; };
enum SignatureMode { NormalSignatureMode, Detached, Clearsigned }; enum SignatureMode {
NormalSignatureMode = 0,
Detached = 1,
Clearsigned = 2,
SignArchive = 4,
SignFile = 8,
};
enum class RevocationReason {
Unspecified = 0,
Compromised = 1,
Superseded = 2,
NoLongerUsed = 3
};
GPGMEPP_EXPORT std::ostream &operator<<(std::ostream &os, Protocol proto); GPGMEPP_EXPORT std::ostream &operator<<(std::ostream &os, Protocol proto);
GPGMEPP_EXPORT std::ostream &operator<<(std::ostream &os, Engine eng); GPGMEPP_EXPORT std::ostream &operator<<(std::ostream &os, Engine eng);
@ -89,7 +108,8 @@ GPGMEPP_EXPORT EngineInfo engineInfo(Engine engine);
homedir, sysconfdir, bindir, libexecdir, libdir, homedir, sysconfdir, bindir, libexecdir, libdir,
datadir, localedir, agent-socket, agent-ssh-socket, datadir, localedir, agent-socket, agent-ssh-socket,
dirmngr-socket, uiserver-socket, gpgconf-name, gpg-name, 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, gpg-wks-client-name, gpgtar-name.
This may be extended in the future. This may be extended in the future.
*/ */

View File

@ -0,0 +1,205 @@
/*
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);
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") == 0) {
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") == 0) {
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);
}

View File

@ -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__

View File

@ -120,10 +120,6 @@ unsigned int GpgAddUserIDEditInteractor::nextState(unsigned int status, const ch
static const Error INV_EMAIL_ERROR = Error::fromCode(GPG_ERR_INV_USER_ID); static const Error INV_EMAIL_ERROR = Error::fromCode(GPG_ERR_INV_USER_ID);
static const Error INV_COMMENT_ERROR = Error::fromCode(GPG_ERR_INV_USER_ID); static const Error INV_COMMENT_ERROR = Error::fromCode(GPG_ERR_INV_USER_ID);
if (needsNoResponse(status)) {
return state();
}
using namespace GpgAddUserIDEditInteractor_Private; using namespace GpgAddUserIDEditInteractor_Private;
switch (state()) { switch (state()) {

View File

@ -25,7 +25,7 @@
#ifndef __GPGMEPP_GPGADDUSERIDEDITINTERACTOR_H__ #ifndef __GPGMEPP_GPGADDUSERIDEDITINTERACTOR_H__
#define __GPGMEPP_GPGADDUSERIDEDITINTERACTOR_H__ #define __GPGMEPP_GPGADDUSERIDEDITINTERACTOR_H__
#include <editinteractor.h> #include "editinteractor.h"
#include <string> #include <string>

View File

@ -33,8 +33,6 @@
#include <assert.h> #include <assert.h>
#include <sstream>
using namespace GpgME; using namespace GpgME;
GpgAgentGetInfoAssuanTransaction::GpgAgentGetInfoAssuanTransaction(InfoItem item) GpgAgentGetInfoAssuanTransaction::GpgAgentGetInfoAssuanTransaction(InfoItem item)

View File

@ -25,7 +25,7 @@
#ifndef __GPGMEPP_GPGAGENTGETINFOASSUANTRANSACTION_H__ #ifndef __GPGMEPP_GPGAGENTGETINFOASSUANTRANSACTION_H__
#define __GPGMEPP_GPGAGENTGETINFOASSUANTRANSACTION_H__ #define __GPGMEPP_GPGAGENTGETINFOASSUANTRANSACTION_H__
#include <interfaces/assuantransaction.h> #include "interfaces/assuantransaction.h"
#include <string> #include <string>
#include <vector> #include <vector>

View File

@ -36,16 +36,17 @@ using namespace GpgME;
class GpgGenCardKeyInteractor::Private class GpgGenCardKeyInteractor::Private
{ {
public: public:
Private() : keysize("2048"), backup(false), algo(RSA) Private() : keysize("2048")
{ {
} }
std::string name, email, backupFileName, expiry, serial, keysize; std::string name, email, backupFileName, expiry, serial, keysize;
bool backup; bool backup = false;
Algo algo; Algo algo = RSA;
std::string curve;
}; };
GpgGenCardKeyInteractor::~GpgGenCardKeyInteractor() {} GpgGenCardKeyInteractor::~GpgGenCardKeyInteractor() = default;
GpgGenCardKeyInteractor::GpgGenCardKeyInteractor(const std::string &serial): GpgGenCardKeyInteractor::GpgGenCardKeyInteractor(const std::string &serial):
d(new Private) d(new Private)
@ -88,6 +89,15 @@ void GpgGenCardKeyInteractor::setAlgo(Algo algo)
d->algo = algo; d->algo = algo;
} }
void GpgGenCardKeyInteractor::setCurve(Curve curve)
{
if (curve == DefaultCurve) {
d->curve.clear();
} else if (curve >= 1 && curve <= LastCurve) {
d->curve = std::to_string(static_cast<int>(curve));
}
}
namespace GpgGenCardKeyInteractor_Private namespace GpgGenCardKeyInteractor_Private
{ {
enum { enum {
@ -141,7 +151,7 @@ const char *GpgGenCardKeyInteractor::action(Error &err) const
case KEY_CURVE1: case KEY_CURVE1:
case KEY_CURVE2: case KEY_CURVE2:
case KEY_CURVE3: case KEY_CURVE3:
return "1"; // Only cv25519 supported. return d->curve.empty() ? "1" : d->curve.c_str(); // default is Curve25519
case NAME: case NAME:
return d->name.c_str(); return d->name.c_str();
case EMAIL: case EMAIL:
@ -182,10 +192,6 @@ unsigned int GpgGenCardKeyInteractor::nextState(unsigned int status, const char
static const Error INV_EMAIL_ERROR = Error::fromCode(GPG_ERR_INV_USER_ID); static const Error INV_EMAIL_ERROR = Error::fromCode(GPG_ERR_INV_USER_ID);
static const Error INV_COMMENT_ERROR = Error::fromCode(GPG_ERR_INV_USER_ID); static const Error INV_COMMENT_ERROR = Error::fromCode(GPG_ERR_INV_USER_ID);
if (needsNoResponse(status)) {
return state();
}
using namespace GpgGenCardKeyInteractor_Private; using namespace GpgGenCardKeyInteractor_Private;
switch (state()) { switch (state()) {

View File

@ -24,7 +24,7 @@
#ifndef __GPGMEPP_GPGGENCARDKEYEDITINTERACTOR_H__ #ifndef __GPGMEPP_GPGGENCARDKEYEDITINTERACTOR_H__
#define __GPGMEPP_GPGGENCARDKEYEDITINTERACTOR_H__ #define __GPGMEPP_GPGGENCARDKEYEDITINTERACTOR_H__
#include <editinteractor.h> #include "editinteractor.h"
#include <string> #include <string>
#include <memory> #include <memory>
@ -58,10 +58,27 @@ public:
enum Algo { enum Algo {
RSA = 1, RSA = 1,
ECC = 2 ECC = 2,
}; };
void setAlgo(Algo algo); void setAlgo(Algo algo);
// the enum values minus 1 have to match the indexes of the curves used by
// ask_curve() in gnupg's g10/keygen.c
enum Curve {
DefaultCurve = 0, // currently Curve25519
Curve25519 = 1,
Curve448,
NISTP256,
NISTP384,
NISTP521,
BrainpoolP256,
BrainpoolP384,
BrainpoolP512,
Secp256k1,
LastCurve = Secp256k1,
};
void setCurve(Curve curve);
std::string backupFileName() const; std::string backupFileName() const;
private: private:

View File

@ -75,4 +75,7 @@ typedef struct _gpgme_tofu_info *gpgme_tofu_info_t;
struct _gpgme_op_query_swdb_result; struct _gpgme_op_query_swdb_result;
typedef struct _gpgme_op_query_swdb_result *gpgme_query_swdb_result_t; typedef struct _gpgme_op_query_swdb_result *gpgme_query_swdb_result_t;
struct _gpgme_revocation_key;
typedef struct _gpgme_revocation_key *gpgme_revocation_key_t;
#endif // __GPGMEPP_GPGMEFW_H__ #endif // __GPGMEPP_GPGMEFW_H__

View File

@ -0,0 +1,207 @@
/*
gpgrevokekeyeditinteractor.cpp - Edit Interactor to revoke own OpenPGP keys
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 "gpgrevokekeyeditinteractor.h"
#include "error.h"
#include <gpgme.h>
#include <vector>
// avoid conflict (msvc)
#ifdef ERROR
# undef ERROR
#endif
using namespace GpgME;
class GpgRevokeKeyEditInteractor::Private
{
enum {
START = EditInteractor::StartState,
COMMAND,
CONFIRM_REVOKING_ENTIRE_KEY,
REASON_CODE,
REASON_TEXT,
// all these free slots belong to REASON_TEXT, too; we increase state()
// by one for each line of text, so that action() is called
REASON_TEXT_DONE = REASON_TEXT + 1000,
CONFIRM_REASON,
QUIT,
CONFIRM_SAVE,
ERROR = EditInteractor::ErrorState
};
GpgRevokeKeyEditInteractor *const q = nullptr;
public:
Private(GpgRevokeKeyEditInteractor *q)
: q{q}
, reasonCode{"0"}
{
}
const char *action(Error &err) const;
unsigned int nextState(unsigned int statusCode, const char *args, Error &err);
std::string reasonCode;
std::vector<std::string> reasonLines;
int nextLine = -1;
};
const char *GpgRevokeKeyEditInteractor::Private::action(Error &err) const
{
switch (const auto state = q->state()) {
case COMMAND:
return "revkey";
case CONFIRM_REVOKING_ENTIRE_KEY:
return "Y";
case REASON_CODE:
return reasonCode.c_str();
case REASON_TEXT_DONE:
return "";
case CONFIRM_REASON:
return "Y";
case QUIT:
return "quit";
case CONFIRM_SAVE:
return "Y";
case START:
return nullptr;
default:
if (state >= REASON_TEXT && state < REASON_TEXT_DONE) {
return reasonLines[nextLine].c_str();
}
// fall through
case ERROR:
err = Error::fromCode(GPG_ERR_GENERAL);
return nullptr;
}
}
unsigned int GpgRevokeKeyEditInteractor::Private::nextState(unsigned int status, const char *args, Error &err)
{
using std::strcmp;
static const Error GENERAL_ERROR = Error::fromCode(GPG_ERR_GENERAL);
switch (const auto state = 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_BOOL &&
strcmp(args, "keyedit.revoke.subkey.okay") == 0) {
return CONFIRM_REVOKING_ENTIRE_KEY;
}
err = GENERAL_ERROR;
return ERROR;
case CONFIRM_REVOKING_ENTIRE_KEY:
if (status == GPGME_STATUS_GET_LINE &&
strcmp(args, "ask_revocation_reason.code") == 0) {
return REASON_CODE;
}
err = GENERAL_ERROR;
return ERROR;
case REASON_CODE:
if (status == GPGME_STATUS_GET_LINE &&
strcmp(args, "ask_revocation_reason.text") == 0) {
nextLine++;
return static_cast<std::size_t>(nextLine) < reasonLines.size() ? REASON_TEXT : REASON_TEXT_DONE;
}
err = GENERAL_ERROR;
return ERROR;
default:
if (state >= REASON_TEXT && state < REASON_TEXT_DONE) {
if (status == GPGME_STATUS_GET_LINE &&
strcmp(args, "ask_revocation_reason.text") == 0) {
nextLine++;
return static_cast<std::size_t>(nextLine) < reasonLines.size() ? state + 1 : REASON_TEXT_DONE;
}
}
err = GENERAL_ERROR;
return ERROR;
case REASON_TEXT_DONE:
if (status == GPGME_STATUS_GET_BOOL &&
strcmp(args, "ask_revocation_reason.okay") == 0) {
return CONFIRM_REASON;
}
err = GENERAL_ERROR;
return ERROR;
case CONFIRM_REASON:
if (status == GPGME_STATUS_GET_LINE &&
strcmp(args, "keyedit.prompt") == 0) {
return QUIT;
}
err = GENERAL_ERROR;
return ERROR;
case QUIT:
if (status == GPGME_STATUS_GET_BOOL &&
strcmp(args, "keyedit.save.okay") == 0) {
return CONFIRM_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;
}
}
GpgRevokeKeyEditInteractor::GpgRevokeKeyEditInteractor()
: EditInteractor{}
, d{new Private{this}}
{
}
GpgRevokeKeyEditInteractor::~GpgRevokeKeyEditInteractor() = default;
void GpgRevokeKeyEditInteractor::setReason(RevocationReason reason, const std::vector<std::string> &description)
{
d->reasonCode = std::to_string(static_cast<int>(reason));
d->reasonLines = description;
}
const char *GpgRevokeKeyEditInteractor::action(Error &err) const
{
return d->action(err);
}
unsigned int GpgRevokeKeyEditInteractor::nextState(unsigned int status, const char *args, Error &err) const
{
return d->nextState(status, args, err);
}

View File

@ -0,0 +1,62 @@
/*
gpgrevokekeyeditinteractor.h - Edit Interactor to revoke own OpenPGP keys
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_GPGREVOKEKEYEDITINTERACTOR_H__
#define __GPGMEPP_GPGREVOKEKEYEDITINTERACTOR_H__
#include "editinteractor.h"
#include "global.h"
#include <memory>
#include <vector>
namespace GpgME
{
/** Edit interactor to revoke the key a key edit operation is working on.
* Supports revocation of own keys only. */
class GPGMEPP_EXPORT GpgRevokeKeyEditInteractor : public EditInteractor
{
public:
GpgRevokeKeyEditInteractor();
~GpgRevokeKeyEditInteractor() override;
/** Sets the reason for the revocation. The reason defaults to \c Unspecified.
* \a description can be used for adding a comment for the revocation. The
* individual elements of \a description must be non-empty strings and they
* must not contain any endline characters.
*/
void setReason(RevocationReason reason, const std::vector<std::string> &description = {});
private:
const char *action(Error &err) const override;
unsigned int nextState(unsigned int statusCode, const char *args, Error &err) const override;
private:
class GPGMEPP_NO_EXPORT Private;
const std::unique_ptr<Private> d;
};
} // namespace GpgME
#endif // __GPGMEPP_GPGREVOKEKEYEDITINTERACTOR_H__

View File

@ -94,10 +94,6 @@ unsigned int GpgSetExpiryTimeEditInteractor::nextState(unsigned int status, cons
static const Error GENERAL_ERROR = Error::fromCode(GPG_ERR_GENERAL); static const Error GENERAL_ERROR = Error::fromCode(GPG_ERR_GENERAL);
static const Error INV_TIME_ERROR = Error::fromCode(GPG_ERR_INV_TIME); static const Error INV_TIME_ERROR = Error::fromCode(GPG_ERR_INV_TIME);
if (needsNoResponse(status)) {
return state();
}
using namespace GpgSetExpiryTimeEditInteractor_Private; using namespace GpgSetExpiryTimeEditInteractor_Private;
switch (state()) { switch (state()) {

View File

@ -25,7 +25,7 @@
#ifndef __GPGMEPP_GPGSETEXPIRYTIMEEDITINTERACTOR_H__ #ifndef __GPGMEPP_GPGSETEXPIRYTIMEEDITINTERACTOR_H__
#define __GPGMEPP_GPGSETEXPIRYTIMEEDITINTERACTOR_H__ #define __GPGMEPP_GPGSETEXPIRYTIMEEDITINTERACTOR_H__
#include <editinteractor.h> #include "editinteractor.h"
#include <string> #include <string>

View File

@ -98,10 +98,6 @@ unsigned int GpgSetOwnerTrustEditInteractor::nextState(unsigned int status, cons
static const Error GENERAL_ERROR = Error::fromCode(GPG_ERR_GENERAL); static const Error GENERAL_ERROR = Error::fromCode(GPG_ERR_GENERAL);
//static const Error INV_TIME_ERROR = Error::fromCode( GPG_ERR_INV_TIME ); //static const Error INV_TIME_ERROR = Error::fromCode( GPG_ERR_INV_TIME );
if (needsNoResponse(status)) {
return state();
}
using namespace GpgSetOwnerTrustEditInteractor_Private; using namespace GpgSetOwnerTrustEditInteractor_Private;
switch (state()) { switch (state()) {

View File

@ -25,8 +25,8 @@
#ifndef __GPGMEPP_GPGSETOWNERTRUSTEDITINTERACTOR_H__ #ifndef __GPGMEPP_GPGSETOWNERTRUSTEDITINTERACTOR_H__
#define __GPGMEPP_GPGSETOWNERTRUSTEDITINTERACTOR_H__ #define __GPGMEPP_GPGSETOWNERTRUSTEDITINTERACTOR_H__
#include <editinteractor.h> #include "editinteractor.h"
#include <key.h> #include "key.h"
#include <string> #include <string>

View File

@ -64,6 +64,13 @@ public:
std::vector<unsigned int> userIDs; std::vector<unsigned int> userIDs;
std::vector<unsigned int>::const_iterator currentId, nextId; std::vector<unsigned int>::const_iterator currentId, nextId;
unsigned int checkLevel; unsigned int checkLevel;
bool dupeOk;
Key key;
struct {
TrustSignatureTrust trust;
std::string depth;
std::string scope;
} trustSignature;
const char *command() const const char *command() const
{ {
@ -126,7 +133,9 @@ GpgSignKeyEditInteractor::Private::Private()
userIDs(), userIDs(),
currentId(), currentId(),
nextId(), nextId(),
checkLevel(0) checkLevel(0),
dupeOk(false),
trustSignature{TrustSignatureTrust::None, "0", {}}
{ {
} }
@ -159,6 +168,9 @@ enum SignKeyState {
SET_TRUST_REGEXP, SET_TRUST_REGEXP,
CONFIRM, CONFIRM,
CONFIRM2, CONFIRM2,
DUPE_OK,
DUPE_OK2,
REJECT_SIGN_EXPIRED,
QUIT, QUIT,
SAVE, SAVE,
ERROR = EditInteractor::ErrorState ERROR = EditInteractor::ErrorState
@ -182,30 +194,43 @@ static GpgSignKeyEditInteractor_Private::TransitionMap makeTable()
#define addEntry( s1, status, str, s2 ) tab[std::make_tuple( s1, status, str)] = s2 #define addEntry( s1, status, str, s2 ) tab[std::make_tuple( s1, status, str)] = s2
addEntry(START, GET_LINE, "keyedit.prompt", COMMAND); addEntry(START, GET_LINE, "keyedit.prompt", COMMAND);
addEntry(COMMAND, GET_BOOL, "keyedit.sign_all.okay", UIDS_ANSWER_SIGN_ALL); addEntry(COMMAND, GET_BOOL, "keyedit.sign_all.okay", UIDS_ANSWER_SIGN_ALL);
addEntry(COMMAND, GET_BOOL, "sign_uid.expired_okay", REJECT_SIGN_EXPIRED);
addEntry(COMMAND, GET_BOOL, "sign_uid.okay", CONFIRM); addEntry(COMMAND, GET_BOOL, "sign_uid.okay", CONFIRM);
addEntry(COMMAND, GET_BOOL, "sign_uid.local_promote_okay", CONFIRM2); addEntry(COMMAND, GET_BOOL, "sign_uid.local_promote_okay", CONFIRM2);
addEntry(COMMAND, GET_BOOL, "sign_uid.dupe_okay", DUPE_OK);
addEntry(COMMAND, GET_LINE, "trustsig_prompt.trust_value", SET_TRUST_VALUE);
addEntry(UIDS_ANSWER_SIGN_ALL, GET_BOOL, "sign_uid.okay", CONFIRM); addEntry(UIDS_ANSWER_SIGN_ALL, GET_BOOL, "sign_uid.okay", CONFIRM);
addEntry(UIDS_ANSWER_SIGN_ALL, GET_BOOL, "sign_uid.dupe_okay", DUPE_OK);
addEntry(UIDS_ANSWER_SIGN_ALL, GET_LINE, "sign_uid.expire", SET_EXPIRE); addEntry(UIDS_ANSWER_SIGN_ALL, GET_LINE, "sign_uid.expire", SET_EXPIRE);
addEntry(UIDS_ANSWER_SIGN_ALL, GET_LINE, "sign_uid.class", SET_CHECK_LEVEL); addEntry(UIDS_ANSWER_SIGN_ALL, GET_LINE, "sign_uid.class", SET_CHECK_LEVEL);
addEntry(SET_TRUST_VALUE, GET_LINE, "trustsign_prompt.trust_depth", SET_TRUST_DEPTH); addEntry(UIDS_ANSWER_SIGN_ALL, GET_LINE, "trustsig_prompt.trust_value", SET_TRUST_VALUE);
addEntry(SET_TRUST_DEPTH, GET_LINE, "trustsign_prompt.trust_regexp", SET_TRUST_REGEXP); addEntry(SET_TRUST_VALUE, GET_LINE, "trustsig_prompt.trust_depth", SET_TRUST_DEPTH);
addEntry(SET_TRUST_REGEXP, GET_LINE, "sign_uid.okay", CONFIRM); addEntry(SET_TRUST_DEPTH, GET_LINE, "trustsig_prompt.trust_regexp", SET_TRUST_REGEXP);
addEntry(SET_TRUST_REGEXP, GET_BOOL, "sign_uid.okay", CONFIRM);
addEntry(SET_CHECK_LEVEL, GET_BOOL, "sign_uid.okay", CONFIRM); addEntry(SET_CHECK_LEVEL, GET_BOOL, "sign_uid.okay", CONFIRM);
addEntry(SET_EXPIRE, GET_BOOL, "sign_uid.class", SET_CHECK_LEVEL); addEntry(SET_EXPIRE, GET_BOOL, "sign_uid.class", SET_CHECK_LEVEL);
addEntry(CONFIRM, GET_BOOL, "sign_uid.local_promote_okay", CONFIRM); addEntry(CONFIRM, GET_BOOL, "sign_uid.local_promote_okay", CONFIRM);
addEntry(DUPE_OK, GET_BOOL, "sign_uid.okay", CONFIRM);
addEntry(DUPE_OK2, GET_BOOL, "sign_uid.okay", CONFIRM);
addEntry(DUPE_OK, GET_LINE, "trustsig_prompt.trust_value", SET_TRUST_VALUE);
addEntry(DUPE_OK2, GET_LINE, "trustsig_prompt.trust_value", SET_TRUST_VALUE);
addEntry(CONFIRM, GET_BOOL, "sign_uid.okay", CONFIRM); addEntry(CONFIRM, GET_BOOL, "sign_uid.okay", CONFIRM);
addEntry(CONFIRM2, GET_BOOL, "sign_uid.okay", CONFIRM); addEntry(CONFIRM2, GET_BOOL, "sign_uid.okay", CONFIRM);
addEntry(CONFIRM, GET_LINE, "keyedit.prompt", COMMAND); addEntry(CONFIRM, GET_LINE, "keyedit.prompt", COMMAND);
addEntry(CONFIRM, GET_LINE, "trustsign_prompt.trust_value", SET_TRUST_VALUE); addEntry(CONFIRM, GET_LINE, "trustsig_prompt.trust_value", SET_TRUST_VALUE);
addEntry(CONFIRM, GET_LINE, "sign_uid.expire", SET_EXPIRE); addEntry(CONFIRM, GET_LINE, "sign_uid.expire", SET_EXPIRE);
addEntry(CONFIRM, GET_LINE, "sign_uid.class", SET_CHECK_LEVEL); addEntry(CONFIRM, GET_LINE, "sign_uid.class", SET_CHECK_LEVEL);
addEntry(UIDS_LIST_SEPARATELY_DONE, GET_BOOL, "sign_uid.local_promote_okay", CONFIRM); addEntry(UIDS_LIST_SEPARATELY_DONE, GET_BOOL, "sign_uid.local_promote_okay", CONFIRM);
addEntry(UIDS_LIST_SEPARATELY_DONE, GET_LINE, "keyedit.prompt", COMMAND); addEntry(UIDS_LIST_SEPARATELY_DONE, GET_LINE, "keyedit.prompt", COMMAND);
addEntry(UIDS_LIST_SEPARATELY_DONE, GET_LINE, "trustsign_prompt.trust_value", SET_TRUST_VALUE); addEntry(UIDS_LIST_SEPARATELY_DONE, GET_LINE, "trustsig_prompt.trust_value", SET_TRUST_VALUE);
addEntry(UIDS_LIST_SEPARATELY_DONE, GET_LINE, "sign_uid.expire", SET_EXPIRE); addEntry(UIDS_LIST_SEPARATELY_DONE, GET_LINE, "sign_uid.expire", SET_EXPIRE);
addEntry(UIDS_LIST_SEPARATELY_DONE, GET_LINE, "sign_uid.class", SET_CHECK_LEVEL); addEntry(UIDS_LIST_SEPARATELY_DONE, GET_LINE, "sign_uid.class", SET_CHECK_LEVEL);
addEntry(UIDS_LIST_SEPARATELY_DONE, GET_BOOL, "sign_uid.okay", CONFIRM); addEntry(UIDS_LIST_SEPARATELY_DONE, GET_BOOL, "sign_uid.okay", CONFIRM);
addEntry(UIDS_LIST_SEPARATELY_DONE, GET_BOOL, "sign_uid.dupe_okay", DUPE_OK);
addEntry(DUPE_OK, GET_BOOL, "sign_uid.dupe_okay", DUPE_OK2);
addEntry(DUPE_OK2, GET_BOOL, "sign_uid.dupe_okay", DUPE_OK);
addEntry(CONFIRM, GET_LINE, "keyedit.prompt", QUIT); addEntry(CONFIRM, GET_LINE, "keyedit.prompt", QUIT);
addEntry(REJECT_SIGN_EXPIRED, GET_LINE, "keyedit.prompt", QUIT);
addEntry(ERROR, GET_LINE, "keyedit.prompt", QUIT); addEntry(ERROR, GET_LINE, "keyedit.prompt", QUIT);
addEntry(QUIT, GET_BOOL, "keyedit.save.okay", SAVE); addEntry(QUIT, GET_BOOL, "keyedit.save.okay", SAVE);
#undef addEntry #undef addEntry
@ -228,17 +253,22 @@ const char *GpgSignKeyEditInteractor::action(Error &err) const
case SET_EXPIRE: case SET_EXPIRE:
return answer(true); return answer(true);
case SET_TRUST_VALUE: case SET_TRUST_VALUE:
// TODO return d->trustSignature.trust == TrustSignatureTrust::Partial ? "1" : "2";
case SET_TRUST_DEPTH: case SET_TRUST_DEPTH:
//TODO return d->trustSignature.depth.c_str();
case SET_TRUST_REGEXP: case SET_TRUST_REGEXP:
//TODO return d->trustSignature.scope.c_str();
return nullptr;
case SET_CHECK_LEVEL: case SET_CHECK_LEVEL:
return check_level_strings[d->checkLevel]; return check_level_strings[d->checkLevel];
case DUPE_OK:
case DUPE_OK2:
return answer(d->dupeOk);
case CONFIRM2: case CONFIRM2:
case CONFIRM: case CONFIRM:
return answer(true); return answer(true);
case REJECT_SIGN_EXPIRED:
err = Error::fromCode(GPG_ERR_KEY_EXPIRED);
return answer(false);
case QUIT: case QUIT:
return "quit"; return "quit";
case SAVE: case SAVE:
@ -246,7 +276,17 @@ const char *GpgSignKeyEditInteractor::action(Error &err) const
default: default:
if (st >= UIDS_LIST_SEPARATELY && st < UIDS_LIST_SEPARATELY_DONE) { if (st >= UIDS_LIST_SEPARATELY && st < UIDS_LIST_SEPARATELY_DONE) {
std::stringstream ss; std::stringstream ss;
ss << d->nextUserID(); auto nextID = d->nextUserID();
const char *hash;
assert (nextID);
if (!d->key.isNull() && (hash = d->key.userID(nextID - 1).uidhash())) {
/* Prefer uidhash if it is available as it might happen
* that uidattrs break the ordering of the uids in the
* edit-key interface */
ss << "uid " << hash;
} else {
ss << nextID;
}
d->scratch = ss.str(); d->scratch = ss.str();
return d->scratch.c_str(); return d->scratch.c_str();
} }
@ -264,9 +304,6 @@ unsigned int GpgSignKeyEditInteractor::nextState(unsigned int status, const char
static const Error GENERAL_ERROR = Error::fromCode(GPG_ERR_GENERAL); static const Error GENERAL_ERROR = Error::fromCode(GPG_ERR_GENERAL);
//static const Error INV_TIME_ERROR = Error::fromCode( GPG_ERR_INV_TIME ); //static const Error INV_TIME_ERROR = Error::fromCode( GPG_ERR_INV_TIME );
static const TransitionMap table(makeTable()); static const TransitionMap table(makeTable());
if (needsNoResponse(status)) {
return state();
}
using namespace GpgSignKeyEditInteractor_Private; using namespace GpgSignKeyEditInteractor_Private;
@ -305,6 +342,10 @@ unsigned int GpgSignKeyEditInteractor::nextState(unsigned int status, const char
err = GENERAL_ERROR; err = GENERAL_ERROR;
return ERROR; return ERROR;
} }
void GpgSignKeyEditInteractor::setKey(const Key &key)
{
d->key = key;
}
void GpgSignKeyEditInteractor::setCheckLevel(unsigned int checkLevel) void GpgSignKeyEditInteractor::setCheckLevel(unsigned int checkLevel)
{ {
@ -326,3 +367,29 @@ void GpgSignKeyEditInteractor::setSigningOptions(int options)
assert(!d->started); assert(!d->started);
d->options = options; d->options = options;
} }
void GpgSignKeyEditInteractor::setDupeOk(bool value)
{
assert(!d->started);
d->dupeOk = value;
}
void GpgSignKeyEditInteractor::setTrustSignatureTrust(GpgME::TrustSignatureTrust trust)
{
assert(!d->started);
assert(trust != TrustSignatureTrust::None);
d->trustSignature.trust = trust;
}
void GpgSignKeyEditInteractor::setTrustSignatureDepth(unsigned short depth)
{
assert(!d->started);
assert(depth <= 255);
d->trustSignature.depth = std::to_string(depth);
}
void GpgSignKeyEditInteractor::setTrustSignatureScope(const std::string &scope)
{
assert(!d->started);
d->trustSignature.scope = scope;
}

View File

@ -25,7 +25,7 @@
#ifndef __GPGMEPP_GPGSIGNKEYEDITINTERACTOR_H__ #ifndef __GPGMEPP_GPGSIGNKEYEDITINTERACTOR_H__
#define __GPGMEPP_GPGSIGNKEYEDITINTERACTOR_H__ #define __GPGMEPP_GPGSIGNKEYEDITINTERACTOR_H__
#include <editinteractor.h> #include "editinteractor.h"
#include <string> #include <string>
#include <vector> #include <vector>
@ -35,6 +35,7 @@ namespace GpgME
class Key; class Key;
class UserID; class UserID;
enum class TrustSignatureTrust : char;
class GPGMEPP_EXPORT GpgSignKeyEditInteractor : public EditInteractor class GPGMEPP_EXPORT GpgSignKeyEditInteractor : public EditInteractor
{ {
@ -50,8 +51,18 @@ public:
void setCheckLevel(unsigned int checkLevel); void setCheckLevel(unsigned int checkLevel);
void setUserIDsToSign(const std::vector<unsigned int> &userIDsToSign); void setUserIDsToSign(const std::vector<unsigned int> &userIDsToSign);
void setKey(const Key &key);
void setSigningOptions(int options); void setSigningOptions(int options);
/* Set this if it is ok to overwrite an existing signature. In that
* case the context has to have the flag "extended-edit" set to 1 through
* Context::setFlag before calling edit.*/
void setDupeOk(bool value);
void setTrustSignatureTrust(TrustSignatureTrust trust);
void setTrustSignatureDepth(unsigned short depth);
void setTrustSignatureScope(const std::string &scope);
private: private:
const char *action(Error &err) const override; const char *action(Error &err) const override;
unsigned int nextState(unsigned int statusCode, const char *args, Error &err) const override; unsigned int nextState(unsigned int statusCode, const char *args, Error &err) const override;

View File

@ -48,7 +48,9 @@ public:
// We just need to handle the pointers in the structs: // We just need to handle the pointers in the structs:
for (gpgme_import_status_t is = r.imports ; is ; is = is->next) { for (gpgme_import_status_t is = r.imports ; is ; is = is->next) {
gpgme_import_status_t copy = new _gpgme_import_status(*is); 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; copy->next = nullptr;
imports.push_back(copy); imports.push_back(copy);
} }
@ -92,6 +94,131 @@ void GpgME::ImportResult::init(gpgme_ctx_t ctx)
make_standard_stuff(ImportResult) make_standard_stuff(ImportResult)
void GpgME::ImportResult::mergeWith(const ImportResult &other)
{
if (other.isNull()) {
return;
}
if (isNull()) { // just assign
operator=(other);
return;
}
// Add the numbers of considered keys; the number will be corrected when
// merging the imports to account for duplicates
d->res.considered += other.d->res.considered;
// Add the numbers of keys without user ID; may count duplicates
d->res.no_user_id += other.d->res.no_user_id;
// Add the numbers of imported keys
d->res.imported += other.d->res.imported;
// Add the numbers of imported RSA keys
d->res.imported_rsa += other.d->res.imported_rsa;
// Add the numbers of unchanged keys; the number will be corrected when
// merging the imports to account for keys changed by this import
d->res.unchanged += other.d->res.unchanged;
// Add the numbers of new user IDs
d->res.new_user_ids += other.d->res.new_user_ids;
// Add the numbers of new subkeys
d->res.new_sub_keys += other.d->res.new_sub_keys;
// Add the numbers of new signatures
d->res.new_signatures += other.d->res.new_signatures;
// Add the numbers of new revocations
d->res.new_revocations += other.d->res.new_revocations;
// Add the numbers of considered secret keys; the number will be corrected when
// merging the imports to account for duplicates
d->res.secret_read += other.d->res.secret_read;
// Add the numbers of imported secret keys
d->res.secret_imported += other.d->res.secret_imported;
// Add the numbers of unchanged secret keys; the number will be corrected when
// merging the imports to account for keys changed by this import
d->res.secret_unchanged += other.d->res.secret_unchanged;
// Add the numbers of new keys that were skipped; may count duplicates
d->res.skipped_new_keys += other.d->res.skipped_new_keys;
// Add the numbers of keys that were not imported; may count duplicates
d->res.not_imported += other.d->res.not_imported;
// Add the numbers of v3 keys that were skipped; may count duplicates
d->res.skipped_v3_keys += other.d->res.skipped_v3_keys;
// Look at the list of keys for which an import was attempted during the
// other import to correct some of the consolidated numbers
for (auto it = std::begin(other.d->imports), end = std::end(other.d->imports); it != end; ++it) {
const char *fpr = (*it)->fpr;
if (!fpr || !*fpr) {
// we cannot derive any useful information about an import if the
// fingerprint is null or empty
continue;
}
// was this key also considered during the first import
const auto consideredInFirstImports =
std::any_of(std::begin(d->imports), std::end(d->imports), [fpr](const gpgme_import_status_t i) {
return i->fpr && !strcmp(i->fpr, fpr);
});
// did we see this key already in the list of keys of the other import
const auto consideredInPreviousOtherImports =
std::any_of(std::begin(other.d->imports), it, [fpr](const gpgme_import_status_t i) {
return i->fpr && !strcmp(i->fpr, fpr);
});
// was anything added to this key during the other import
const auto changedInOtherImports =
std::any_of(std::begin(other.d->imports), std::end(other.d->imports), [fpr](const gpgme_import_status_t i) {
return i->fpr && !strcmp(i->fpr, fpr) && (i->status != 0);
});
if (consideredInFirstImports && !consideredInPreviousOtherImports) {
// key was also considered during first import, but not before in the list of other imports
d->res.considered -= 1;
if (!changedInOtherImports) {
// key was (most likely) counted as unchanged in the second import;
// this needs to be corrected (regardless of whether it was changed in the first import)
d->res.unchanged -= 1;
}
}
// now do the same for the secret key counts
const auto secretKeyConsideredInFirstImports =
std::any_of(std::begin(d->imports), std::end(d->imports), [fpr](const gpgme_import_status_t i) {
return i->fpr && !strcmp(i->fpr, fpr) && (i->status & GPGME_IMPORT_SECRET);
});
const auto secretKeyConsideredInPreviousOtherImports =
std::any_of(std::begin(other.d->imports), it, [fpr](const gpgme_import_status_t i) {
return i->fpr && !strcmp(i->fpr, fpr) && (i->status & GPGME_IMPORT_SECRET);
});
const auto secretKeyChangedInOtherImports =
std::any_of(std::begin(other.d->imports), std::end(other.d->imports), [fpr](const gpgme_import_status_t i) {
return i->fpr && !strcmp(i->fpr, fpr) && (i->status & GPGME_IMPORT_SECRET) && (i->status != GPGME_IMPORT_SECRET);
});
if (secretKeyConsideredInFirstImports && !secretKeyConsideredInPreviousOtherImports) {
// key was also considered during first import, but not before in the list of other imports
d->res.secret_read -= 1;
if (!secretKeyChangedInOtherImports) {
// key was (most likely) counted as unchanged in the second import;
// this needs to be corrected (regardless of whether it was changed in the first import)
d->res.secret_unchanged -= 1;
}
}
}
// Now append the list of keys for which an import was attempted during the
// other import
d->imports.reserve(d->imports.size() + other.d->imports.size());
std::transform(std::begin(other.d->imports), std::end(other.d->imports),
std::back_inserter(d->imports),
[](const gpgme_import_status_t import) {
gpgme_import_status_t copy = new _gpgme_import_status{*import};
if (import->fpr) {
copy->fpr = strdup(import->fpr);
}
copy->next = nullptr; // should already be null, but better safe than sorry
return copy;
});
// Finally, merge the error if there was none yet
if (!bool(error())) {
Result::operator=(other);
}
}
int GpgME::ImportResult::numConsidered() const int GpgME::ImportResult::numConsidered() const
{ {
return d ? d->res.considered : 0 ; return d ? d->res.considered : 0 ;

View File

@ -47,6 +47,7 @@ public:
ImportResult(gpgme_ctx_t ctx, const Error &error); ImportResult(gpgme_ctx_t ctx, const Error &error);
explicit ImportResult(const Error &error); explicit ImportResult(const Error &error);
ImportResult(const ImportResult &other) = default;
const ImportResult &operator=(ImportResult other) const ImportResult &operator=(ImportResult other)
{ {
swap(other); swap(other);
@ -60,6 +61,16 @@ public:
swap(this->d, other.d); swap(this->d, other.d);
} }
/**
* Merges the result @p other into this result (and all of its copies).
*
* @note The merge algorithm assumes that @p other is the result of an
* import that was performed after the import of this result.
* @note Some numbers cannot be consolidated reliably, e.g. the number of
* keys without user ID.
*/
void mergeWith(const ImportResult &other);
bool isNull() const; bool isNull() const;
int numConsidered() const; int numConsidered() const;
@ -96,6 +107,7 @@ class GPGMEPP_EXPORT Import
public: public:
Import(); Import();
Import(const Import &other) = default;
const Import &operator=(Import other) const Import &operator=(Import other)
{ {
swap(other); swap(other);

View File

@ -26,7 +26,7 @@
#ifndef __GPGMEPP_INTERFACES_ASSUANTRANSACTION_H__ #ifndef __GPGMEPP_INTERFACES_ASSUANTRANSACTION_H__
#define __GPGMEPP_INTERFACES_ASSUANTRANSACTION_H__ #define __GPGMEPP_INTERFACES_ASSUANTRANSACTION_H__
#include "gpgmepp_export.h" #include "../gpgmepp_export.h"
#include <stddef.h> #include <stddef.h>

View File

@ -27,7 +27,7 @@
#include <sys/types.h> #include <sys/types.h>
#include "gpgmepp_export.h" #include "../gpgmepp_export.h"
#include <gpg-error.h> #include <gpg-error.h>

View File

@ -1,8 +1,7 @@
/* /*
context_glib.cpp - wraps a gpgme key context, gpgme-glib-specific functions statusconsumer.h - Interface for status callbacks
Copyright (C) 2007 Klarälvdalens Datakonsult AB Copyright (c) 2020 g10 Code GmbH
2016 Bundesamt für Sicherheit in der Informationstechnik Software engineering by Ingo Klöcker <dev@ingo-kloecker.de>
Software engineering by Intevation GmbH
This file is part of GPGME++. This file is part of GPGME++.
@ -22,20 +21,22 @@
Boston, MA 02110-1301, USA. Boston, MA 02110-1301, USA.
*/ */
#ifdef HAVE_CONFIG_H #ifndef __GPGMEPP_INTERFACES_STATUSCONSUMER_H__
#include "config.h" #define __GPGMEPP_INTERFACES_STATUSCONSUMER_H__
#endif
#include <global.h> #include "../gpgmepp_export.h"
extern "C" GIOChannel *gpgme_get_fdptr(int); namespace GpgME
GIOChannel *GpgME::getGIOChannel(int fd)
{ {
return gpgme_get_fdptr(fd);
}
QIODevice *GpgME::getQIODevice(int fd) class GPGMEPP_EXPORT StatusConsumer
{ {
return 0; public:
} virtual ~StatusConsumer() {}
virtual void status(const char *status, const char *details) = 0;
};
} // namespace GpgME
#endif // __GPGMEPP_INTERFACES_STATUSCONSUMER_H__

View File

@ -29,11 +29,13 @@
#include "util.h" #include "util.h"
#include "tofuinfo.h" #include "tofuinfo.h"
#include "context.h" #include "context.h"
#include "engineinfo.h"
#include <gpgme.h> #include <gpgme.h>
#include <string.h> #include <string.h>
#include <strings.h> #include <strings.h>
#include <cassert>
#include <istream> #include <istream>
#include <iterator> #include <iterator>
@ -120,6 +122,37 @@ std::vector<Subkey> Key::subkeys() const
return v; return v;
} }
RevocationKey Key::revocationKey(unsigned int index) const
{
return RevocationKey(key, index);
}
unsigned int Key::numRevocationKeys() const
{
if (!key) {
return 0;
}
unsigned int count = 0;
for (auto revkey = key->revocation_keys; revkey; revkey = revkey->next) {
++count;
}
return count;
}
std::vector<RevocationKey> Key::revocationKeys() const
{
if (!key) {
return std::vector<RevocationKey>();
}
std::vector<RevocationKey> v;
v.reserve(numRevocationKeys());
for (auto revkey = key->revocation_keys; revkey; revkey = revkey->next) {
v.push_back(RevocationKey(key, revkey));
}
return v;
}
Key::OwnerTrust Key::ownerTrust() const Key::OwnerTrust Key::ownerTrust() const
{ {
if (!key) { if (!key) {
@ -206,17 +239,12 @@ bool Key::canEncrypt() const
bool Key::canSign() const bool Key::canSign() const
{ {
#ifndef GPGME_CAN_SIGN_ON_SECRET_OPENPGP_KEYLISTING_NOT_BROKEN return key && key->can_sign;
if (key && key->protocol == GPGME_PROTOCOL_OpenPGP) {
return true;
}
#endif
return canReallySign();
} }
bool Key::canReallySign() const bool Key::canReallySign() const
{ {
return key && key->can_sign; return canSign();
} }
bool Key::canCertify() const bool Key::canCertify() const
@ -250,6 +278,26 @@ bool Key::isDeVs() const
return true; return true;
} }
bool Key::hasCertify() const
{
return key && key->has_certify;
}
bool Key::hasSign() const
{
return key && key->has_sign;
}
bool Key::hasEncrypt() const
{
return key && key->has_encrypt;
}
bool Key::hasAuthenticate() const
{
return key && key->has_authenticate;
}
const char *Key::issuerSerial() const const char *Key::issuerSerial() const
{ {
return key ? key->issuer_serial : nullptr ; return key ? key->issuer_serial : nullptr ;
@ -337,6 +385,10 @@ const Key &Key::mergeWith(const Key &other)
for (gpgme_sub_key_t hissk = him->subkeys ; hissk ; hissk = hissk->next) { for (gpgme_sub_key_t hissk = him->subkeys ; hissk ; hissk = hissk->next) {
if (strcmp(mysk->fpr, hissk->fpr) == 0) { if (strcmp(mysk->fpr, hissk->fpr) == 0) {
mysk->is_cardkey |= hissk->is_cardkey; mysk->is_cardkey |= hissk->is_cardkey;
mysk->secret |= hissk->secret;
if (hissk->keygrip && !mysk->keygrip) {
mysk->keygrip = strdup(hissk->keygrip);
}
break; break;
} }
} }
@ -358,20 +410,25 @@ void Key::update()
KeyListMode::Signatures | KeyListMode::Signatures |
KeyListMode::SignatureNotations | KeyListMode::SignatureNotations |
KeyListMode::Validate | KeyListMode::Validate |
KeyListMode::WithTofu); KeyListMode::WithTofu |
KeyListMode::WithKeygrip |
KeyListMode::WithSecret);
Error err; Error err;
auto newKey = ctx->key(primaryFingerprint(), err, true); Key newKey;
// Not secret so we get the information from the pubring. if (GpgME::engineInfo(GpgME::GpgEngine).engineVersion() < "2.1.0") {
if (newKey.isNull()) newKey = ctx->key(primaryFingerprint(), err, true);
{ // Not secret so we get the information from the pubring.
if (newKey.isNull()) {
newKey = ctx->key(primaryFingerprint(), err, false);
}
} else {
newKey = ctx->key(primaryFingerprint(), err, false); newKey = ctx->key(primaryFingerprint(), err, false);
} }
delete ctx; delete ctx;
if (err) { if (err) {
return; return;
} }
swap(newKey); swap(newKey);
return;
} }
// static // static
@ -401,7 +458,7 @@ Key Key::locate(const char *mbox)
// //
// //
gpgme_sub_key_t find_subkey(const shared_gpgme_key_t &key, unsigned int idx) static gpgme_sub_key_t find_subkey(const shared_gpgme_key_t &key, unsigned int idx)
{ {
if (key) { if (key) {
for (gpgme_sub_key_t s = key->subkeys ; s ; s = s->next, --idx) { for (gpgme_sub_key_t s = key->subkeys ; s ; s = s->next, --idx) {
@ -413,7 +470,7 @@ gpgme_sub_key_t find_subkey(const shared_gpgme_key_t &key, unsigned int idx)
return nullptr; return nullptr;
} }
gpgme_sub_key_t verify_subkey(const shared_gpgme_key_t &key, gpgme_sub_key_t subkey) static gpgme_sub_key_t verify_subkey(const shared_gpgme_key_t &key, gpgme_sub_key_t subkey)
{ {
if (key) { if (key) {
for (gpgme_sub_key_t s = key->subkeys ; s ; s = s->next) { for (gpgme_sub_key_t s = key->subkeys ; s ; s = s->next) {
@ -504,6 +561,21 @@ bool Subkey::canAuthenticate() const
return subkey && subkey->can_authenticate; return subkey && subkey->can_authenticate;
} }
bool Subkey::canRenc() const
{
return subkey && subkey->can_renc;
}
bool Subkey::canTimestamp() const
{
return subkey && subkey->can_timestamp;
}
bool Subkey::isGroupOwned() const
{
return subkey && subkey->is_group_owned;
}
bool Subkey::isQualified() const bool Subkey::isQualified() const
{ {
return subkey && subkey->is_qualified; return subkey && subkey->is_qualified;
@ -580,7 +652,7 @@ bool Subkey::isDisabled() const
// //
// //
gpgme_user_id_t find_uid(const shared_gpgme_key_t &key, unsigned int idx) static gpgme_user_id_t find_uid(const shared_gpgme_key_t &key, unsigned int idx)
{ {
if (key) { if (key) {
for (gpgme_user_id_t u = key->uids ; u ; u = u->next, --idx) { for (gpgme_user_id_t u = key->uids ; u ; u = u->next, --idx) {
@ -592,7 +664,7 @@ gpgme_user_id_t find_uid(const shared_gpgme_key_t &key, unsigned int idx)
return nullptr; return nullptr;
} }
gpgme_user_id_t verify_uid(const shared_gpgme_key_t &key, gpgme_user_id_t uid) static gpgme_user_id_t verify_uid(const shared_gpgme_key_t &key, gpgme_user_id_t uid)
{ {
if (key) { if (key) {
for (gpgme_user_id_t u = key->uids ; u ; u = u->next) { for (gpgme_user_id_t u = key->uids ; u ; u = u->next) {
@ -674,6 +746,11 @@ const char *UserID::comment() const
return uid ? uid->comment : nullptr ; return uid ? uid->comment : nullptr ;
} }
const char *UserID::uidhash() const
{
return uid ? uid->uidhash : nullptr ;
}
UserID::Validity UserID::validity() const UserID::Validity UserID::validity() const
{ {
if (!uid) { if (!uid) {
@ -724,13 +801,83 @@ TofuInfo UserID::tofuInfo() const
return TofuInfo(uid->tofu); return TofuInfo(uid->tofu);
} }
static gpgme_key_sig_t find_last_valid_sig_for_keyid (gpgme_user_id_t uid,
const char *keyid)
{
if (!keyid) {
return nullptr;
}
gpgme_key_sig_t ret = NULL;
for (gpgme_key_sig_t s = uid->signatures ; s ; s = s->next) {
if (s->keyid && !strcmp(keyid, s->keyid)) {
if (!s->expired && !s->revoked && !s->invalid && !s->status) {
if (!ret) {
ret = s;
} else if (ret && ret->timestamp <= s->timestamp) {
/* Equals because when the timestamps are the same we prefer
the last in the list */
ret = s;
}
}
}
}
return ret;
}
const char *UserID::remark(const Key &remarker, Error &err) const
{
if (!uid || remarker.isNull()) {
err = Error::fromCode(GPG_ERR_GENERAL);
return nullptr;
}
if (key->protocol != GPGME_PROTOCOL_OpenPGP) {
return nullptr;
}
if (!(key->keylist_mode & GPGME_KEYLIST_MODE_SIG_NOTATIONS) ||
!(key->keylist_mode & GPGME_KEYLIST_MODE_SIGS)) {
err = Error::fromCode(GPG_ERR_NO_DATA);
return nullptr;
}
gpgme_key_sig_t s = find_last_valid_sig_for_keyid(uid, remarker.keyID());
if (!s) {
return nullptr;
}
for (gpgme_sig_notation_t n = s->notations; n ; n = n->next) {
if (n->name && !strcmp(n->name, "rem@gnupg.org")) {
return n->value;
}
}
return nullptr;
}
std::vector<std::string> UserID::remarks(std::vector<Key> keys, Error &err) const
{
std::vector<std::string> ret;
for (const auto &key: keys) {
const char *rem = remark(key, err);
if (err) {
return ret;
}
if (rem) {
ret.push_back(rem);
}
}
return ret;
}
// //
// //
// class Signature // class Signature
// //
// //
gpgme_key_sig_t find_signature(gpgme_user_id_t uid, unsigned int idx) static gpgme_key_sig_t find_signature(gpgme_user_id_t uid, unsigned int idx)
{ {
if (uid) { if (uid) {
for (gpgme_key_sig_t s = uid->signatures ; s ; s = s->next, --idx) { for (gpgme_key_sig_t s = uid->signatures ; s ; s = s->next, --idx) {
@ -742,7 +889,7 @@ gpgme_key_sig_t find_signature(gpgme_user_id_t uid, unsigned int idx)
return nullptr; return nullptr;
} }
gpgme_key_sig_t verify_signature(gpgme_user_id_t uid, gpgme_key_sig_t sig) static gpgme_key_sig_t verify_signature(gpgme_user_id_t uid, gpgme_key_sig_t sig)
{ {
if (uid) { if (uid) {
for (gpgme_key_sig_t s = uid->signatures ; s ; s = s->next) { for (gpgme_key_sig_t s = uid->signatures ; s ; s = s->next) {
@ -754,18 +901,82 @@ gpgme_key_sig_t verify_signature(gpgme_user_id_t uid, gpgme_key_sig_t sig)
return nullptr; return nullptr;
} }
static int signature_index(gpgme_user_id_t uid, gpgme_key_sig_t sig)
{
if (uid) {
int i = 0;
for (gpgme_key_sig_t s = uid->signatures ; s ; s = s->next, ++i) {
if (s == sig) {
return i;
}
}
}
return -1;
}
UserID::Signature::Signature() : key(), uid(nullptr), sig(nullptr) {} UserID::Signature::Signature() : key(), uid(nullptr), sig(nullptr) {}
UserID::Signature::Signature(const shared_gpgme_key_t &k, gpgme_user_id_t u, unsigned int idx) UserID::Signature::Signature(const shared_gpgme_key_t &k, gpgme_user_id_t u, unsigned int idx)
: key(k), uid(verify_uid(k, u)), sig(find_signature(uid, idx)) : key(k), uid(verify_uid(k, u)), sig(find_signature(uid, idx))
{ {
} }
UserID::Signature::Signature(const shared_gpgme_key_t &k, gpgme_user_id_t u, gpgme_key_sig_t s) UserID::Signature::Signature(const shared_gpgme_key_t &k, gpgme_user_id_t u, gpgme_key_sig_t s)
: key(k), uid(verify_uid(k, u)), sig(verify_signature(uid, s)) : key(k), uid(verify_uid(k, u)), sig(verify_signature(uid, s))
{ {
}
bool UserID::Signature::operator<(const Signature &other)
{
// kept for binary compatibility
return static_cast<const UserID::Signature *>(this)->operator<(other);
}
bool UserID::Signature::operator<(const Signature &other) const
{
// based on cmp_signodes() in g10/keylist.c
// both signatures must belong to the same user ID
assert(uid == other.uid);
// self-signatures are ordered first
const char *primaryKeyId = parent().parent().keyID();
const bool thisIsSelfSignature = strcmp(signerKeyID(), primaryKeyId) == 0;
const bool otherIsSelfSignature = strcmp(other.signerKeyID(), primaryKeyId) == 0;
if (thisIsSelfSignature && !otherIsSelfSignature) {
return true;
}
if (otherIsSelfSignature && !thisIsSelfSignature) {
return false;
}
// then sort by signer key ID (which are or course the same for self-sigs)
const int keyIdComparison = strcmp(signerKeyID(), other.signerKeyID());
if (keyIdComparison < 0) {
return true;
}
if (keyIdComparison > 0) {
return false;
}
// followed by creation time
if (creationTime() < other.creationTime()) {
return true;
}
if (creationTime() > other.creationTime()) {
return false;
}
// followed by the class in a way that a rev comes first
if (certClass() < other.certClass()) {
return true;
}
if (certClass() > other.certClass()) {
return false;
}
// to make the sort stable we compare the indexes of the signatures as last resort
return signature_index(uid, sig) < signature_index(uid, other.sig);
} }
UserID UserID::Signature::parent() const UserID UserID::Signature::parent() const
@ -933,6 +1144,29 @@ const char *UserID::Signature::policyURL() const
return nullptr; return nullptr;
} }
bool UserID::Signature::isTrustSignature() const
{
return sig && sig->trust_depth > 0;
}
TrustSignatureTrust UserID::Signature::trustValue() const
{
if (!sig || !isTrustSignature()) {
return TrustSignatureTrust::None;
}
return sig->trust_value >= 120 ? TrustSignatureTrust::Complete : TrustSignatureTrust::Partial;
}
unsigned int UserID::Signature::trustDepth() const
{
return sig ? sig->trust_depth : 0;
}
const char *UserID::Signature::trustScope() const
{
return sig ? sig->trust_scope : nullptr;
}
std::string UserID::addrSpecFromString(const char *userid) std::string UserID::addrSpecFromString(const char *userid)
{ {
if (!userid) { if (!userid) {
@ -1053,6 +1287,68 @@ bool UserID::Signature::isBad() const
return isNull() || isExpired() || isInvalid(); return isNull() || isExpired() || isInvalid();
} }
//
//
// class RevocationKey
//
//
static gpgme_revocation_key_t find_revkey(const shared_gpgme_key_t &key, unsigned int idx)
{
if (key) {
for (gpgme_revocation_key_t s = key->revocation_keys; s; s = s->next, --idx) {
if (idx == 0) {
return s;
}
}
}
return nullptr;
}
static gpgme_revocation_key_t verify_revkey(const shared_gpgme_key_t &key, gpgme_revocation_key_t revkey)
{
if (key) {
for (gpgme_revocation_key_t s = key->revocation_keys; s; s = s->next) {
if (s == revkey) {
return revkey;
}
}
}
return nullptr;
}
RevocationKey::RevocationKey() : key(), revkey(nullptr) {}
RevocationKey::RevocationKey(const shared_gpgme_key_t &k, unsigned int idx)
: key(k), revkey(find_revkey(k, idx))
{
}
RevocationKey::RevocationKey(const shared_gpgme_key_t &k, gpgme_revocation_key_t sk)
: key(k), revkey(verify_revkey(k, sk))
{
}
Key RevocationKey::parent() const
{
return Key(key);
}
const char *RevocationKey::fingerprint() const
{
return revkey ? revkey->fpr : nullptr;
}
bool RevocationKey::isSensitive() const
{
return revkey ? revkey->sensitive : false;
}
int RevocationKey::algorithm() const
{
return revkey ? revkey->pubkey_algo : 0;
}
std::ostream &operator<<(std::ostream &os, const UserID &uid) std::ostream &operator<<(std::ostream &os, const UserID &uid)
{ {
os << "GpgME::UserID("; os << "GpgME::UserID(";
@ -1072,6 +1368,34 @@ std::ostream &operator<<(std::ostream &os, const UserID &uid)
return os << ')'; return os << ')';
} }
std::ostream &operator<<(std::ostream &os, const Subkey &subkey)
{
os << "GpgME::Subkey(";
if (!subkey.isNull()) {
os << "\n fingerprint: " << protect(subkey.fingerprint())
<< "\n keyGrip: " << protect(subkey.keyGrip())
<< "\n creationTime: " << subkey.creationTime()
<< "\n expirationTime:" << subkey.expirationTime()
<< "\n isRevoked: " << subkey.isRevoked()
<< "\n isExpired: " << subkey.isExpired()
<< "\n isInvalid: " << subkey.isInvalid()
<< "\n isDisabled: " << subkey.isDisabled()
<< "\n canSign: " << subkey.canSign()
<< "\n canEncrypt: " << subkey.canEncrypt()
<< "\n canCertify: " << subkey.canCertify()
<< "\n canAuth: " << subkey.canAuthenticate()
<< "\n canRenc: " << subkey.canRenc()
<< "\n canTimestanp: " << subkey.canTimestamp()
<< "\n isSecret: " << subkey.isSecret()
<< "\n isGroupOwned: " << subkey.isGroupOwned()
<< "\n isQualified: " << subkey.isQualified()
<< "\n isDeVs: " << subkey.isDeVs()
<< "\n isCardKey: " << subkey.isCardKey()
<< "\n cardSerialNumber:" << protect(subkey.cardSerialNumber());
}
return os << ')';
}
std::ostream &operator<<(std::ostream &os, const Key &key) std::ostream &operator<<(std::ostream &os, const Key &key)
{ {
os << "GpgME::Key("; os << "GpgME::Key(";
@ -1081,7 +1405,7 @@ std::ostream &operator<<(std::ostream &os, const Key &key)
<< "\n issuer: " << protect(key.issuerName()) << "\n issuer: " << protect(key.issuerName())
<< "\n fingerprint:" << protect(key.primaryFingerprint()) << "\n fingerprint:" << protect(key.primaryFingerprint())
<< "\n listmode: " << key.keyListMode() << "\n listmode: " << key.keyListMode()
<< "\n canSign: " << key.canReallySign() << "\n canSign: " << key.canSign()
<< "\n canEncrypt: " << key.canEncrypt() << "\n canEncrypt: " << key.canEncrypt()
<< "\n canCertify: " << key.canCertify() << "\n canCertify: " << key.canCertify()
<< "\n canAuth: " << key.canAuthenticate() << "\n canAuth: " << key.canAuthenticate()
@ -1091,6 +1415,23 @@ std::ostream &operator<<(std::ostream &os, const Key &key)
const std::vector<UserID> uids = key.userIDs(); const std::vector<UserID> uids = key.userIDs();
std::copy(uids.begin(), uids.end(), std::copy(uids.begin(), uids.end(),
std::ostream_iterator<UserID>(os, "\n")); std::ostream_iterator<UserID>(os, "\n"));
const std::vector<Subkey> subkeys = key.subkeys();
std::copy(subkeys.begin(), subkeys.end(),
std::ostream_iterator<Subkey>(os, "\n"));
os << " revocationKeys:\n";
const std::vector<RevocationKey> revkeys = key.revocationKeys();
std::copy(revkeys.begin(), revkeys.end(),
std::ostream_iterator<RevocationKey>(os, "\n"));
}
return os << ')';
}
std::ostream &operator<<(std::ostream &os, const RevocationKey &revkey)
{
os << "GpgME::RevocationKey(";
if (!revkey.isNull()) {
os << "\n fingerprint: " << protect(revkey.fingerprint())
<< "\n isSensitive: " << revkey.isSensitive();
} }
return os << ')'; return os << ')';
} }

View File

@ -44,9 +44,16 @@ class Context;
class Subkey; class Subkey;
class UserID; class UserID;
class TofuInfo; class TofuInfo;
class RevocationKey;
typedef std::shared_ptr< std::remove_pointer<gpgme_key_t>::type > shared_gpgme_key_t; typedef std::shared_ptr< std::remove_pointer<gpgme_key_t>::type > shared_gpgme_key_t;
enum class TrustSignatureTrust : char {
None = 0,
Partial,
Complete,
};
// //
// class Key // class Key
// //
@ -65,6 +72,7 @@ public:
static const Null null; static const Null null;
Key(const Key &other) = default;
const Key &operator=(Key other) const Key &operator=(Key other)
{ {
swap(other); swap(other);
@ -93,6 +101,10 @@ public:
std::vector<UserID> userIDs() const; std::vector<UserID> userIDs() const;
std::vector<Subkey> subkeys() const; std::vector<Subkey> subkeys() const;
RevocationKey revocationKey(unsigned int index) const;
unsigned int numRevocationKeys() const;
std::vector<RevocationKey> revocationKeys() const;
bool isRevoked() const; bool isRevoked() const;
bool isExpired() const; bool isExpired() const;
bool isDisabled() const; bool isDisabled() const;
@ -102,22 +114,31 @@ public:
* isDisabled || isInvalid */ * isDisabled || isInvalid */
bool isBad() const; bool isBad() const;
/** Returns true, if the key can be used for encryption (i.e. it's not bad
* and has an encryption subkey) or if the primary subkey can encrypt. */
bool canEncrypt() const; bool canEncrypt() const;
/*! /** Returns true, if the key can be used for signing (i.e. it's not bad
This function contains a workaround for old gpgme's: all secret * and has a signing subkey) or if the primary subkey can sign. */
OpenPGP keys canSign() == true, which canReallySign() doesn't
have. I don't have time to find what breaks when I remove this
workaround, but since Kleopatra merges secret into public keys,
the workaround is not necessary there (and actively harms), I've
added a new function instead.
*/
bool canSign() const; bool canSign() const;
bool canReallySign() const; GPGMEPP_DEPRECATED bool canReallySign() const;
/** Returns true, if the key can be used for certification (i.e. it's not bad
* and has a certification subkey) or if the primary subkey can certify. */
bool canCertify() const; bool canCertify() const;
/** Returns true, if the key can be used for authentication (i.e. it's not bad
* and has a authentication subkey) or if the primary subkey can authenticate. */
bool canAuthenticate() const; bool canAuthenticate() const;
bool isQualified() const; bool isQualified() const;
bool isDeVs() const; bool isDeVs() const;
/** Returns true, if the key has a certification subkey. */
bool hasCertify() const;
/** Returns true, if the key has a signing subkey. */
bool hasSign() const;
/** Returns true, if the key has an encryption subkey. */
bool hasEncrypt() const;
/** Returns true, if the key has an authentication subkey. */
bool hasAuthenticate() const;
bool hasSecret() const; bool hasSecret() const;
GPGMEPP_DEPRECATED bool isSecret() const GPGMEPP_DEPRECATED bool isSecret() const
{ {
@ -222,6 +243,7 @@ public:
Subkey(const shared_gpgme_key_t &key, gpgme_sub_key_t subkey); Subkey(const shared_gpgme_key_t &key, gpgme_sub_key_t subkey);
Subkey(const shared_gpgme_key_t &key, unsigned int idx); Subkey(const shared_gpgme_key_t &key, unsigned int idx);
Subkey(const Subkey &other) = default;
const Subkey &operator=(Subkey other) const Subkey &operator=(Subkey other)
{ {
swap(other); swap(other);
@ -262,6 +284,9 @@ public:
bool canSign() const; bool canSign() const;
bool canCertify() const; bool canCertify() const;
bool canAuthenticate() const; bool canAuthenticate() const;
bool canRenc() const;
bool canTimestamp() const;
bool isGroupOwned() const;
bool isQualified() const; bool isQualified() const;
bool isDeVs() const; bool isDeVs() const;
bool isCardKey() const; bool isCardKey() const;
@ -335,6 +360,7 @@ public:
UserID(const shared_gpgme_key_t &key, gpgme_user_id_t uid); UserID(const shared_gpgme_key_t &key, gpgme_user_id_t uid);
UserID(const shared_gpgme_key_t &key, unsigned int idx); UserID(const shared_gpgme_key_t &key, unsigned int idx);
UserID(const UserID &other) = default;
const UserID &operator=(UserID other) const UserID &operator=(UserID other)
{ {
swap(other); swap(other);
@ -363,6 +389,7 @@ public:
const char *name() const; const char *name() const;
const char *email() const; const char *email() const;
const char *comment() const; const char *comment() const;
const char *uidhash() const;
enum Validity { Unknown = 0, Undefined = 1, Never = 2, enum Validity { Unknown = 0, Undefined = 1, Never = 2,
Marginal = 3, Full = 4, Ultimate = 5 Marginal = 3, Full = 4, Ultimate = 5
@ -413,6 +440,27 @@ public:
* *
* @returns the last update time. */ * @returns the last update time. */
time_t lastUpdate() const; time_t lastUpdate() const;
/*! Get a remark made by the key provided.
* A remark is a signature notation on
* this user id made by the key with the
* name "rem@gnupg.org". Returns an error if the
* parent key of this user id was not listed with the
* keylist mode flags for signatures and signature notations.
*
* @param key The key for which comments should be searched.
* @param error Set to GPG_ERR_NO_DATA if the keylist did
* not include signature notations.
*
* @returns The value of the comment or NULL if none exists.
**/
const char *remark(const Key &key,
Error &error) const;
/*! Get multiple remarks made by potentially multiple keys. */
std::vector <std::string> remarks(std::vector<GpgME::Key> remarkers,
Error &error) const;
private: private:
shared_gpgme_key_t key; shared_gpgme_key_t key;
gpgme_user_id_t uid; gpgme_user_id_t uid;
@ -431,6 +479,7 @@ public:
Signature(const shared_gpgme_key_t &key, gpgme_user_id_t uid, gpgme_key_sig_t sig); Signature(const shared_gpgme_key_t &key, gpgme_user_id_t uid, gpgme_key_sig_t sig);
Signature(const shared_gpgme_key_t &key, gpgme_user_id_t uid, unsigned int idx); Signature(const shared_gpgme_key_t &key, gpgme_user_id_t uid, unsigned int idx);
Signature(const Signature &other) = default;
const Signature &operator=(Signature other) const Signature &operator=(Signature other)
{ {
swap(other); swap(other);
@ -445,6 +494,11 @@ public:
swap(this->sig, other.sig); swap(this->sig, other.sig);
} }
/*! Defines a canonical sort order for signatures of the same user ID. */
bool operator<(const Signature &other) const;
GPGMEPP_DEPRECATED bool operator<(const Signature &other);
bool isNull() const bool isNull() const
{ {
return !sig || !uid || !key ; return !sig || !uid || !key ;
@ -487,14 +541,64 @@ public:
GpgME::Notation notation(unsigned int idx) const; GpgME::Notation notation(unsigned int idx) const;
std::vector<GpgME::Notation> notations() const; std::vector<GpgME::Notation> notations() const;
bool isTrustSignature() const;
TrustSignatureTrust trustValue() const;
unsigned int trustDepth() const;
const char *trustScope() const;
private: private:
shared_gpgme_key_t key; shared_gpgme_key_t key;
gpgme_user_id_t uid; gpgme_user_id_t uid;
gpgme_key_sig_t sig; gpgme_key_sig_t sig;
}; };
//
// class RevocationKey
//
class GPGMEPP_EXPORT RevocationKey
{
public:
RevocationKey();
RevocationKey(const shared_gpgme_key_t &key, gpgme_revocation_key_t revkey);
RevocationKey(const shared_gpgme_key_t &key, unsigned int idx);
// Rule of Zero
void swap(RevocationKey &other)
{
using std::swap;
swap(this->key, other.key);
swap(this->revkey, other.revkey);
}
bool isNull() const
{
return !key || !revkey;
}
Key parent() const;
const char *fingerprint() const;
bool isSensitive() const;
int algorithm() const;
private:
shared_gpgme_key_t key;
gpgme_revocation_key_t revkey;
};
inline void swap(RevocationKey& v1, RevocationKey& v2)
{
v1.swap(v2);
}
GPGMEPP_EXPORT std::ostream &operator<<(std::ostream &os, const UserID &uid); GPGMEPP_EXPORT std::ostream &operator<<(std::ostream &os, const UserID &uid);
GPGMEPP_EXPORT std::ostream &operator<<(std::ostream &os, const Subkey &subkey);
GPGMEPP_EXPORT std::ostream &operator<<(std::ostream &os, const Key &key); GPGMEPP_EXPORT std::ostream &operator<<(std::ostream &os, const Key &key);
GPGMEPP_EXPORT std::ostream &operator<<(std::ostream &os, const RevocationKey &revkey);
} // namespace GpgME } // namespace GpgME

View File

@ -44,6 +44,7 @@ public:
KeyGenerationResult(gpgme_ctx_t ctx, const Error &error); KeyGenerationResult(gpgme_ctx_t ctx, const Error &error);
explicit KeyGenerationResult(const Error &err); explicit KeyGenerationResult(const Error &err);
KeyGenerationResult(const KeyGenerationResult &other) = default;
const KeyGenerationResult &operator=(KeyGenerationResult other) const KeyGenerationResult &operator=(KeyGenerationResult other)
{ {
swap(other); swap(other);

View File

@ -45,6 +45,7 @@ public:
explicit KeyListResult(const Error &err); explicit KeyListResult(const Error &err);
KeyListResult(const Error &err, const _gpgme_op_keylist_result &res); KeyListResult(const Error &err, const _gpgme_op_keylist_result &res);
KeyListResult(const KeyListResult &other) = default;
const KeyListResult &operator=(KeyListResult other) const KeyListResult &operator=(KeyListResult other)
{ {
swap(other); swap(other);

View File

@ -44,6 +44,7 @@ public:
Notation(); Notation();
explicit Notation(gpgme_sig_notation_t nota); explicit Notation(gpgme_sig_notation_t nota);
Notation(const Notation &other) = default;
const Notation &operator=(Notation other) const Notation &operator=(Notation other)
{ {
swap(other); swap(other);

View File

@ -50,6 +50,14 @@ public:
{ {
return mError; return mError;
} }
/**
* Replaces the error set during construction with \p error.
* Use with care, e.g. to set a more suitable error.
*/
void setError(const Error &error)
{
mError = error;
}
protected: protected:
Error mError; Error mError;

View File

@ -31,7 +31,6 @@
#include "data.h" #include "data.h"
#include "util.h" #include "util.h"
#include <sstream>
#include <assert.h> #include <assert.h>
using namespace GpgME; using namespace GpgME;

View File

@ -25,7 +25,7 @@
#ifndef __GPGMEPP_SCDGETINFOASSUANTRANSACTION_H__ #ifndef __GPGMEPP_SCDGETINFOASSUANTRANSACTION_H__
#define __GPGMEPP_SCDGETINFOASSUANTRANSACTION_H__ #define __GPGMEPP_SCDGETINFOASSUANTRANSACTION_H__
#include <interfaces/assuantransaction.h> #include "interfaces/assuantransaction.h"
#include <string> #include <string>
#include <vector> #include <vector>

View File

@ -199,6 +199,8 @@ GpgME::SignatureMode GpgME::CreatedSignature::mode() const
case GPGME_SIG_MODE_NORMAL: return NormalSignatureMode; case GPGME_SIG_MODE_NORMAL: return NormalSignatureMode;
case GPGME_SIG_MODE_DETACH: return Detached; case GPGME_SIG_MODE_DETACH: return Detached;
case GPGME_SIG_MODE_CLEAR: return Clearsigned; case GPGME_SIG_MODE_CLEAR: return Clearsigned;
case GPGME_SIG_MODE_ARCHIVE: return SignArchive; // cannot happen
case GPGME_SIG_MODE_FILE: return SignFile; // cannot happen
} }
} }

View File

@ -50,6 +50,7 @@ public:
SigningResult(gpgme_ctx_t ctx, const Error &error); SigningResult(gpgme_ctx_t ctx, const Error &error);
explicit SigningResult(const Error &err); explicit SigningResult(const Error &err);
SigningResult(const SigningResult &other) = default;
const SigningResult &operator=(SigningResult other) const SigningResult &operator=(SigningResult other)
{ {
swap(other); swap(other);
@ -86,6 +87,7 @@ class GPGMEPP_EXPORT InvalidSigningKey
public: public:
InvalidSigningKey(); InvalidSigningKey();
InvalidSigningKey(const InvalidSigningKey &other) = default;
const InvalidSigningKey &operator=(InvalidSigningKey other) const InvalidSigningKey &operator=(InvalidSigningKey other)
{ {
swap(other); swap(other);
@ -119,6 +121,7 @@ public:
CreatedSignature(); CreatedSignature();
CreatedSignature(const CreatedSignature &other) = default;
const CreatedSignature &operator=(CreatedSignature other) const CreatedSignature &operator=(CreatedSignature other)
{ {
swap(other); swap(other);

View File

@ -0,0 +1,67 @@
/*
statusconsumerassuantransaction.cpp
Copyright (c) 2020 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 "statusconsumerassuantransaction.h"
#include "data.h"
#include "error.h"
#include "interfaces/statusconsumer.h"
using namespace GpgME;
StatusConsumerAssuanTransaction::StatusConsumerAssuanTransaction(StatusConsumer *statusConsumer)
: AssuanTransaction()
, m_consumer(statusConsumer)
{
}
StatusConsumerAssuanTransaction::~StatusConsumerAssuanTransaction()
{
}
Error StatusConsumerAssuanTransaction::data(const char *data, size_t datalen)
{
(void) data;
(void) datalen;
return Error();
}
Data StatusConsumerAssuanTransaction::inquire(const char *name, const char *args, Error &err)
{
(void)name;
(void)args;
(void)err;
return Data::null;
}
Error StatusConsumerAssuanTransaction::status(const char *status, const char *args)
{
m_consumer->status(status, args);
return Error();
}

View File

@ -0,0 +1,51 @@
/*
statusconsumerassuantransaction.h - Assuan transaction that forwards status lines to a consumer
Copyright (c) 2020 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_STATUSCONSUMERASSUANTRANSACTION_H__
#define __GPGMEPP_STATUSCONSUMERASSUANTRANSACTION_H__
#include "interfaces/assuantransaction.h"
namespace GpgME
{
class StatusConsumer;
class GPGMEPP_EXPORT StatusConsumerAssuanTransaction: public AssuanTransaction
{
public:
explicit StatusConsumerAssuanTransaction(StatusConsumer *statusConsumer);
~StatusConsumerAssuanTransaction();
private:
Error data(const char *data, size_t datalen) override;
Data inquire(const char *name, const char *args, Error &err) override;
Error status(const char *status, const char *args) override;
private:
StatusConsumer *m_consumer;
};
} // namespace GpgME
#endif // __GPGMEPP_STATUSCONSUMERASSUANTRANSACTION_H__

View File

@ -62,6 +62,7 @@ public:
const char *iversion = NULL, const char *iversion = NULL,
Error *err = NULL); Error *err = NULL);
SwdbResult(const SwdbResult &other) = default;
const SwdbResult &operator=(SwdbResult other) const SwdbResult &operator=(SwdbResult other)
{ {
swap(other); swap(other);

View File

@ -39,6 +39,7 @@ public:
TofuInfo(); TofuInfo();
explicit TofuInfo(gpgme_tofu_info_t info); explicit TofuInfo(gpgme_tofu_info_t info);
TofuInfo(const TofuInfo &other) = default;
const TofuInfo &operator=(TofuInfo other) const TofuInfo &operator=(TofuInfo other)
{ {
swap(other); swap(other);

View File

@ -27,7 +27,7 @@
#define __GPGMEPP_TRUSTITEM_H__ #define __GPGMEPP_TRUSTITEM_H__
#include "gpgmefw.h" #include "gpgmefw.h"
#include <key.h> #include "key.h"
#include "gpgmepp_export.h" #include "gpgmepp_export.h"
#include <algorithm> #include <algorithm>

View File

@ -1,8 +1,7 @@
/* /*
context_qt.cpp - wraps a gpgme key context, gpgme-qt-specific functions util.cpp - some internal helpers
Copyright (C) 2007 Klarälvdalens Datakonsult AB Copyright (c) 2022 g10 Code GmbH
2016 Bundesamt für Sicherheit in der Informationstechnik Software engineering by Ingo Klöcker <dev@ingo-kloecker.de>
Software engineering by Intevation GmbH
This file is part of GPGME++. This file is part of GPGME++.
@ -26,16 +25,23 @@
#include "config.h" #include "config.h"
#endif #endif
#include <global.h> #include "util.h"
extern "C" QIODevice *gpgme_get_fdptr(int); #include <functional>
GIOChannel *GpgME::getGIOChannel(int) StringsToCStrings::StringsToCStrings(const std::vector<std::string>& v)
: m_strings{v}
{ {
return 0;
} }
QIODevice *GpgME::getQIODevice(int fd) const char **StringsToCStrings::c_strs() const
{ {
return gpgme_get_fdptr(fd); 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();
} }

View File

@ -1,8 +1,10 @@
/* /*
util.h - some inline helper functions util.h - some internal helpers
Copyright (C) 2004 Klarälvdalens Datakonsult AB Copyright (C) 2004 Klarälvdalens Datakonsult AB
2016 Bundesamt für Sicherheit in der Informationstechnik 2016 Bundesamt für Sicherheit in der Informationstechnik
Software engineering by Intevation GmbH 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++. This file is part of GPGME++.
@ -72,19 +74,30 @@ static inline gpgme_keylist_mode_t add_to_gpgme_keylist_mode_t(unsigned int oldm
if (newmodes & GpgME::SignatureNotations) { if (newmodes & GpgME::SignatureNotations) {
oldmode |= GPGME_KEYLIST_MODE_SIG_NOTATIONS; oldmode |= GPGME_KEYLIST_MODE_SIG_NOTATIONS;
} }
if (newmodes & GpgME::Ephemeral) {
oldmode |= GPGME_KEYLIST_MODE_EPHEMERAL;
}
if (newmodes & GpgME::Validate) { if (newmodes & GpgME::Validate) {
oldmode |= GPGME_KEYLIST_MODE_VALIDATE; oldmode |= GPGME_KEYLIST_MODE_VALIDATE;
} }
if (newmodes & GpgME::Ephemeral) {
oldmode |= GPGME_KEYLIST_MODE_EPHEMERAL;
}
if (newmodes & GpgME::WithTofu) { if (newmodes & GpgME::WithTofu) {
oldmode |= GPGME_KEYLIST_MODE_WITH_TOFU; oldmode |= GPGME_KEYLIST_MODE_WITH_TOFU;
} }
if (newmodes & GpgME::WithKeygrip) {
oldmode |= GPGME_KEYLIST_MODE_WITH_KEYGRIP;
}
if (newmodes & GpgME::WithSecret) {
oldmode |= GPGME_KEYLIST_MODE_WITH_SECRET;
}
if (newmodes & GpgME::ForceExtern) {
oldmode |= GPGME_KEYLIST_MODE_FORCE_EXTERN;
}
#ifndef NDEBUG #ifndef NDEBUG
if (newmodes & ~(GpgME::Local | GpgME::Extern | GpgME::Signatures | GpgME::SignatureNotations | GpgME::Ephemeral | GpgME::Validate)) { if (newmodes & ~(GpgME::KeyListModeMask)) {
//std::cerr << "GpgME::Context: keylist mode must be one of Local, " //std::cerr << "GpgME::Context: keylist mode must be one of Local, "
//"Extern, Signatures, SignatureNotations, or Validate, or a combination thereof!" << std::endl; //"Extern, Signatures, SignatureNotations, Validate, Ephemeral, WithTofu, "
//"WithKeygrip, WithSecret, ForceExtern, or a combination thereof!"
//<< std::endl;
} }
#endif #endif
return static_cast<gpgme_keylist_mode_t>(oldmode); return static_cast<gpgme_keylist_mode_t>(oldmode);
@ -105,19 +118,35 @@ static inline unsigned int convert_from_gpgme_keylist_mode_t(unsigned int mode)
if (mode & GPGME_KEYLIST_MODE_SIG_NOTATIONS) { if (mode & GPGME_KEYLIST_MODE_SIG_NOTATIONS) {
result |= GpgME::SignatureNotations; result |= GpgME::SignatureNotations;
} }
if (mode & GPGME_KEYLIST_MODE_WITH_SECRET) {
result |= GpgME::WithSecret;
}
if (mode & GPGME_KEYLIST_MODE_WITH_TOFU) {
result |= GpgME::WithTofu;
}
if (mode & GPGME_KEYLIST_MODE_WITH_KEYGRIP) {
result |= GpgME::WithKeygrip;
}
if (mode & GPGME_KEYLIST_MODE_EPHEMERAL) { if (mode & GPGME_KEYLIST_MODE_EPHEMERAL) {
result |= GpgME::Ephemeral; result |= GpgME::Ephemeral;
} }
if (mode & GPGME_KEYLIST_MODE_VALIDATE) { if (mode & GPGME_KEYLIST_MODE_VALIDATE) {
result |= GpgME::Validate; result |= GpgME::Validate;
} }
if (mode & GPGME_KEYLIST_MODE_FORCE_EXTERN) {
result |= GpgME::ForceExtern;
}
#ifndef NDEBUG #ifndef NDEBUG
if (mode & ~(GPGME_KEYLIST_MODE_LOCAL | if (mode & ~(GPGME_KEYLIST_MODE_LOCAL |
GPGME_KEYLIST_MODE_EXTERN | GPGME_KEYLIST_MODE_EXTERN |
GPGME_KEYLIST_MODE_SIGS |
GPGME_KEYLIST_MODE_SIG_NOTATIONS | GPGME_KEYLIST_MODE_SIG_NOTATIONS |
GPGME_KEYLIST_MODE_WITH_SECRET |
GPGME_KEYLIST_MODE_WITH_TOFU |
GPGME_KEYLIST_MODE_WITH_KEYGRIP |
GPGME_KEYLIST_MODE_EPHEMERAL | GPGME_KEYLIST_MODE_EPHEMERAL |
GPGME_KEYLIST_MODE_VALIDATE | GPGME_KEYLIST_MODE_VALIDATE |
GPGME_KEYLIST_MODE_SIGS)) { GPGME_KEYLIST_MODE_FORCE_EXTERN)) {
//std::cerr << "GpgME: WARNING: gpgme_get_keylist_mode() returned an unknown flag!" << std::endl; //std::cerr << "GpgME: WARNING: gpgme_get_keylist_mode() returned an unknown flag!" << std::endl;
} }
#endif // NDEBUG #endif // NDEBUG
@ -148,4 +177,38 @@ static inline gpgme_sig_notation_flags_t add_to_gpgme_sig_notation_flags_t(unsi
return static_cast<gpgme_sig_notation_flags_t>(result); return static_cast<gpgme_sig_notation_flags_t>(result);
} }
static inline std::vector<std::string> split(const std::string &text, char delimiter)
{
std::vector<std::string> result;
if (!text.empty()) {
std::istringstream stream{text};
std::string line;
while (std::getline(stream, line, delimiter)) {
result.push_back(line);
}
}
return 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__ #endif // __GPGMEPP_UTIL_H__

View File

@ -413,7 +413,8 @@ GpgME::Key GpgME::Signature::key(bool search, bool update) const
KeyListMode::Signatures | KeyListMode::Signatures |
KeyListMode::SignatureNotations | KeyListMode::SignatureNotations |
KeyListMode::Validate | KeyListMode::Validate |
KeyListMode::WithTofu); KeyListMode::WithTofu |
KeyListMode::WithKeygrip);
Error e; Error e;
ret = d->keys[idx] = ctx->key(fingerprint(), e, false); ret = d->keys[idx] = ctx->key(fingerprint(), e, false);
delete ctx; delete ctx;
@ -543,32 +544,41 @@ std::ostream &GpgME::operator<<(std::ostream &os, const VerificationResult &resu
std::ostream &GpgME::operator<<(std::ostream &os, Signature::PKAStatus pkaStatus) std::ostream &GpgME::operator<<(std::ostream &os, Signature::PKAStatus pkaStatus)
{ {
#define OUTPUT( x ) if ( !(pkaStatus & (GpgME::Signature:: x)) ) {} else do { os << #x " "; } while(0)
os << "GpgME::Signature::PKAStatus("; os << "GpgME::Signature::PKAStatus(";
OUTPUT(UnknownPKAStatus); switch (pkaStatus) {
OUTPUT(PKAVerificationFailed); #define OUTPUT( x ) case GpgME::Signature:: x: os << #x; break
OUTPUT(PKAVerificationSucceeded); OUTPUT(UnknownPKAStatus);
OUTPUT(PKAVerificationFailed);
OUTPUT(PKAVerificationSucceeded);
#undef OUTPUT #undef OUTPUT
default:
os << "??? (" << static_cast<int>(pkaStatus) << ')';
break;
}
return os << ')'; return os << ')';
} }
std::ostream &GpgME::operator<<(std::ostream &os, Signature::Summary summary) std::ostream &GpgME::operator<<(std::ostream &os, Signature::Summary summary)
{ {
#define OUTPUT( x ) if ( !(summary & (GpgME::Signature:: x)) ) {} else do { os << #x " "; } while(0)
os << "GpgME::Signature::Summary("; os << "GpgME::Signature::Summary(";
OUTPUT(Valid); if (summary == Signature::None) {
OUTPUT(Green); os << "None";
OUTPUT(Red); } else {
OUTPUT(KeyRevoked); #define OUTPUT( x ) if ( !(summary & (GpgME::Signature:: x)) ) {} else do { os << #x " "; } while(0)
OUTPUT(KeyExpired); OUTPUT(Valid);
OUTPUT(SigExpired); OUTPUT(Green);
OUTPUT(KeyMissing); OUTPUT(Red);
OUTPUT(CrlMissing); OUTPUT(KeyRevoked);
OUTPUT(CrlTooOld); OUTPUT(KeyExpired);
OUTPUT(BadPolicy); OUTPUT(SigExpired);
OUTPUT(SysError); OUTPUT(KeyMissing);
OUTPUT(TofuConflict); OUTPUT(CrlMissing);
OUTPUT(CrlTooOld);
OUTPUT(BadPolicy);
OUTPUT(SysError);
OUTPUT(TofuConflict);
#undef OUTPUT #undef OUTPUT
}
return os << ')'; return os << ')';
} }
@ -602,10 +612,14 @@ std::ostream &GpgME::operator<<(std::ostream &os, const Signature &sig)
std::ostream &GpgME::operator<<(std::ostream &os, Notation::Flags flags) std::ostream &GpgME::operator<<(std::ostream &os, Notation::Flags flags)
{ {
os << "GpgME::Notation::Flags("; os << "GpgME::Notation::Flags(";
if (flags == Notation::NoFlags) {
os << "NoFlags";
} else {
#define OUTPUT( x ) if ( !(flags & (GpgME::Notation:: x)) ) {} else do { os << #x " "; } while(0) #define OUTPUT( x ) if ( !(flags & (GpgME::Notation:: x)) ) {} else do { os << #x " "; } while(0)
OUTPUT(HumanReadable); OUTPUT(HumanReadable);
OUTPUT(Critical); OUTPUT(Critical);
#undef OUTPUT #undef OUTPUT
}
return os << ')'; return os << ')';
} }

View File

@ -52,6 +52,7 @@ public:
VerificationResult(gpgme_ctx_t ctx, const Error &error); VerificationResult(gpgme_ctx_t ctx, const Error &error);
explicit VerificationResult(const Error &err); explicit VerificationResult(const Error &err);
VerificationResult(const VerificationResult &other) = default;
const VerificationResult &operator=(VerificationResult other) const VerificationResult &operator=(VerificationResult other)
{ {
swap(other); swap(other);
@ -90,6 +91,7 @@ public:
Signature(); Signature();
Signature(const Signature &other) = default;
const Signature &operator=(Signature other) const Signature &operator=(Signature other)
{ {
swap(other); swap(other);

View File

@ -45,6 +45,7 @@ public:
VfsMountResult(gpgme_ctx_t ctx, const Error &error, const Error &opError); VfsMountResult(gpgme_ctx_t ctx, const Error &error, const Error &opError);
explicit VfsMountResult(const Error &err); explicit VfsMountResult(const Error &err);
VfsMountResult(const VfsMountResult &other) = default;
const VfsMountResult &operator=(VfsMountResult other) const VfsMountResult &operator=(VfsMountResult other)
{ {
swap(other); swap(other);

View File

@ -32,5 +32,14 @@ AM_CPPFLAGS = -I$(top_srcdir)/lang/cpp/src -I$(top_builddir)/src \
run_getkey_SOURCES = run-getkey.cpp run_getkey_SOURCES = run-getkey.cpp
run_keylist_SOURCES = run-keylist.cpp run_keylist_SOURCES = run-keylist.cpp
run_verify_SOURCES = run-verify.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)

View File

@ -60,6 +60,8 @@ show_usage (int ex)
" --ephemeral use GPGME_KEYLIST_MODE_EPHEMERAL\n" " --ephemeral use GPGME_KEYLIST_MODE_EPHEMERAL\n"
" --validate use GPGME_KEYLIST_MODE_VALIDATE\n" " --validate use GPGME_KEYLIST_MODE_VALIDATE\n"
" --locate use GPGME_KEYLIST_MODE_LOCATE\n" " --locate use GPGME_KEYLIST_MODE_LOCATE\n"
" --force-extern use GPGME_KEYLIST_MODE_FORCE_EXTERN\n"
" --locate-external use GPGME_KEYLIST_MODE_LOCATE_EXTERNAL\n"
, stderr); , stderr);
exit (ex); exit (ex);
} }
@ -116,6 +118,12 @@ main (int argc, char **argv)
} else if (!strcmp (*argv, "--locate")) { } else if (!strcmp (*argv, "--locate")) {
argc--; argv++; argc--; argv++;
mode |= KeyListMode::Locate; mode |= KeyListMode::Locate;
} else if (!strcmp (*argv, "--force-extern")) {
argc--; argv++;
mode |= KeyListMode::ForceExtern;
} else if (!strcmp (*argv, "--locate-external")) {
argc--; argv++;
mode |= KeyListMode::LocateExternal;
} else if (!strncmp (*argv, "--", 2)) { } else if (!strncmp (*argv, "--", 2)) {
show_usage (1); show_usage (1);
} }
@ -132,11 +140,17 @@ main (int argc, char **argv)
return -1; return -1;
} }
ctx->setKeyListMode (mode); ctx->setKeyListMode (mode);
if (ctx->keyListMode() != mode) {
// unfortunately, Context::setKeyListMode() does not return the error
// returned by gpgme
std::cerr << "Failed to set keylist mode. You may have used an invalid combination of options.";
return -1;
}
Error err; Error err;
const GpgME::Key key = ctx->key (*argv, err, only_secret); const GpgME::Key key = ctx->key (*argv, err, only_secret);
std::stringstream ss; std::stringstream ss;
ss << "Key " << key << " Err: " << err.asString() << "\n"; ss << "Key " << key << " Err: " << err.asStdString() << "\n";
std::cout << ss.str(); std::cout << ss.str();

View File

@ -61,6 +61,8 @@ show_usage (int ex)
" --ephemeral use GPGME_KEYLIST_MODE_EPHEMERAL\n" " --ephemeral use GPGME_KEYLIST_MODE_EPHEMERAL\n"
" --validate use GPGME_KEYLIST_MODE_VALIDATE\n" " --validate use GPGME_KEYLIST_MODE_VALIDATE\n"
" --locate use GPGME_KEYLIST_MODE_LOCATE\n" " --locate use GPGME_KEYLIST_MODE_LOCATE\n"
" --force-extern use GPGME_KEYLIST_MODE_FORCE_EXTERN\n"
" --locate-external use GPGME_KEYLIST_MODE_LOCATE_EXTERNAL\n"
, stderr); , stderr);
exit (ex); exit (ex);
} }
@ -117,7 +119,17 @@ main (int argc, char **argv)
} else if (!strcmp (*argv, "--locate")) { } else if (!strcmp (*argv, "--locate")) {
argc--; argv++; argc--; argv++;
mode |= KeyListMode::Locate; mode |= KeyListMode::Locate;
} else if (!strcmp (*argv, "--with-secret")) {
argc--; argv++;
mode |= KeyListMode::WithSecret;
} else if (!strcmp (*argv, "--force-extern")) {
argc--; argv++;
mode |= KeyListMode::ForceExtern;
} else if (!strcmp (*argv, "--locate-external")) {
argc--; argv++;
mode |= KeyListMode::LocateExternal;
} else if (!strncmp (*argv, "--", 2)) { } else if (!strncmp (*argv, "--", 2)) {
std::cerr << "Error: Unknown option: " << *argv << std::endl;
show_usage (1); show_usage (1);
} }
} }
@ -133,16 +145,25 @@ main (int argc, char **argv)
return -1; return -1;
} }
ctx->setKeyListMode (mode); ctx->setKeyListMode (mode);
if (ctx->keyListMode() != mode) {
// unfortunately, Context::setKeyListMode() does not return the error
// returned by gpgme
std::cerr << "Failed to set keylist mode. You may have used an invalid combination of options.\n";
return -1;
}
Error err = ctx->startKeyListing (*argv, only_secret); Error err = ctx->startKeyListing (*argv, only_secret);
if (err) { if (err) {
std::cout << "Error: " << err.asString() << "\n"; std::cout << "Error: " << err.asStdString() << "\n";
return -1; return -1;
} }
GpgME::Key key; GpgME::Key key;
std::stringstream ss; std::stringstream ss;
do { do {
key = ctx->nextKey(err); key = ctx->nextKey(err);
ss << key << "\n\n"; if (!err)
{
ss << key << "\n\n";
}
} while (!err && !key.isNull()); } while (!err && !key.isNull());
std::cout << ss.str(); std::cout << ss.str();

View File

@ -38,7 +38,6 @@
#include "verificationresult.h" #include "verificationresult.h"
#include <memory> #include <memory>
#include <sstream>
#include <iostream> #include <iostream>
using namespace GpgME; using namespace GpgME;

View File

@ -0,0 +1,158 @@
/*
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 <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.asStdString() << ")\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.asStdString() << ")\n";
return -1;
}
if ((err = ctx->setEngineHomeDirectory(""))) {
std::cerr << "Failed to set engine home directory (Error: " << err.asStdString() << ")\n";
return -1;
}
// try to 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.asStdString() << ")\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.asStdString() << ")\n";
return -1;
}
const auto gpgconfProgram = GpgME::dirInfo("gpgconf-name");
// replace backslashes with forward slashes in homedir to work around bug T6833
std::string homedir{GpgME::dirInfo("homedir")};
std::replace(homedir.begin(), homedir.end(), '\\', '/');
const char *argv[] = {
gpgconfProgram,
"--homedir",
homedir.c_str(),
"--launch",
"dirmngr",
NULL
};
auto ignoreIO = Data{Data::null};
err = spawnCtx->spawn(gpgconfProgram, argv,
ignoreIO, ignoreIO, ignoreIO,
Context::SpawnDetached);
if (err) {
std::cerr << "Failed to start dirmngr (Error: " << err.asStdString() << ")\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.asStdString() << "\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;
}

View File

@ -44,4 +44,16 @@ describe('GPGME context', function (){
done(); done();
}); });
}); });
it('Error message on unsuccessful connection (timeout)', function (done) {
let prm = Gpgmejs.init({ timeout: 1 });
prm.then(
null,
function (error){
expect(error).to.be.an('error');
expect(error.code).to.equal('CONN_TIMEOUT');
done();
}
);
});
}); });

View File

@ -40,7 +40,15 @@ import { decode, atobArray, Utf8ArrayToStr } from './Helpers';
export class Connection{ export class Connection{
constructor (){ constructor (){
this._connectionError = null;
this._connection = chrome.runtime.connectNative('gpgmejson'); this._connection = chrome.runtime.connectNative('gpgmejson');
this._connection.onDisconnect.addListener(() => {
if (chrome.runtime.lastError) {
this._connectionError = chrome.runtime.lastError.message;
} else {
this._connectionError = 'Disconnected without error message';
}
});
} }
/** /**
@ -50,9 +58,16 @@ export class Connection{
if (this._connection){ if (this._connection){
this._connection.disconnect(); this._connection.disconnect();
this._connection = null; this._connection = null;
this._connectionError = 'Disconnect requested by gpgmejs';
} }
} }
/**
* Checks if the connection terminated with an error state
*/
get isDisconnected (){
return this._connectionError !== null;
}
/** /**
* @typedef {Object} backEndDetails * @typedef {Object} backEndDetails
@ -84,25 +99,29 @@ export class Connection{
timeout = 1000; timeout = 1000;
} }
const msg = createMessage('version'); const msg = createMessage('version');
if (details === true) { const prm = Promise.race([
return this.post(msg); this.post(msg),
} else { new Promise(function (resolve, reject){
let me = this; setTimeout(function (){
return new Promise(function (resolve) { reject(gpgme_error('CONN_TIMEOUT'));
Promise.race([ }, timeout);
me.post(msg), })
new Promise(function (resolve, reject){ ]);
setTimeout(function (){ return new Promise( function (resolve, reject) {
reject(gpgme_error('CONN_TIMEOUT')); prm.then(function (success){
}, timeout); if (details === true ) {
}) resolve(success);
]).then(function (){ // success } else {
resolve(true); resolve(true);
}, function (){ // failure }
}, function (error) {
if (details === true ) {
reject(error);
} else {
resolve(false); resolve(false);
}); }
}); });
} });
} }
/** /**
@ -128,7 +147,7 @@ export class Connection{
} }
let chunksize = message.chunksize; let chunksize = message.chunksize;
const me = this; const me = this;
return new Promise(function (resolve, reject){ const nativeCommunication = new Promise(function (resolve, reject){
let answer = new Answer(message); let answer = new Answer(message);
let listener = function (msg) { let listener = function (msg) {
if (!msg){ if (!msg){
@ -161,29 +180,35 @@ export class Connection{
} }
}; };
me._connection.onMessage.addListener(listener); me._connection.onMessage.addListener(listener);
if (permittedOperations[message.operation].pinentry){ me._connection.postMessage(message.message);
return me._connection.postMessage(message.message);
} else { // check for browser messaging errors after a while
return Promise.race([ // (browsers' extension permission checks take some time)
me._connection.postMessage(message.message), setTimeout( () => {
function (resolve, reject){ if (me.isDisconnected) {
setTimeout(function (){ if ( me.isNativeHostUnknown === true) {
me._connection.disconnect(); return reject(gpgme_error('CONN_NO_CONFIG'));
reject(gpgme_error('CONN_TIMEOUT'));
}, 5000);
}
]).then(function (result){
return result;
}, function (reject){
if (!(reject instanceof Error)) {
me._connection.disconnect();
return gpgme_error('GNUPG_ERROR', reject);
} else { } else {
return reject; return reject(gpgme_error(
'CONN_NO_CONNECT', me._connectionError));
} }
}); }
} }, 25);
}); });
if (permittedOperations[message.operation].pinentry === true) {
return nativeCommunication;
} else {
return Promise.race([
nativeCommunication,
new Promise(function (resolve, reject){
setTimeout(function (){
me.disconnect();
reject(gpgme_error('CONN_TIMEOUT'));
}, 5000);
})
]);
}
} }
} }
@ -212,6 +237,13 @@ class Answer{
return this._expected; return this._expected;
} }
/**
* Checks if an error matching browsers 'host not known' messages occurred
*/
get isNativeHostUnknown () {
return this._connectionError === 'Specified native messaging host not found.';
}
/** /**
* Adds incoming base64 encoded data to the existing response * Adds incoming base64 encoded data to the existing response
* @param {*} msg base64 encoded data. * @param {*} msg base64 encoded data.

View File

@ -35,6 +35,14 @@ export const err_list = {
msg: 'The nativeMessaging answer was empty.', msg: 'The nativeMessaging answer was empty.',
type: 'error' type: 'error'
}, },
'CONN_NO_CONFIG':{
msg: 'The browser does not recognize the nativeMessaging host.',
type: 'error'
},
'CONN_NATIVEMESSAGE':{
msg: 'The native messaging was not successful.',
type: 'error'
},
'CONN_TIMEOUT': { 'CONN_TIMEOUT': {
msg: 'A connection timeout was exceeded.', msg: 'A connection timeout was exceeded.',
type: 'error' type: 'error'
@ -156,8 +164,8 @@ export function gpgme_error (code = 'GENERIC_ERROR', info){
*/ */
class GPGME_Error extends Error{ class GPGME_Error extends Error{
constructor (code = 'GENERIC_ERROR', msg=''){ constructor (code = 'GENERIC_ERROR', msg=''){
const verboseErrors = ['GNUPG_ERROR', 'CONN_NATIVEMESSAGE'];
if (code === 'GNUPG_ERROR' && typeof (msg) === 'string'){ if (verboseErrors.includes(code) && typeof (msg) === 'string'){
super(msg); super(msg);
} else if (err_list.hasOwnProperty(code)){ } else if (err_list.hasOwnProperty(code)){
if (msg){ if (msg){

View File

@ -33,7 +33,7 @@ import { Connection } from './Connection';
* An unsuccessful attempt will reject as a GPGME_Error. * An unsuccessful attempt will reject as a GPGME_Error.
* @param {Object} config (optional) configuration options * @param {Object} config (optional) configuration options
* @param {Number} config.timeout set the timeout for the initial connection * @param {Number} config.timeout set the timeout for the initial connection
* check. On some machines and operating systems a default timeout of 500 ms is * check. On some machines and operating systems a default timeout of 1000 ms is
* too low, so a higher number might be attempted. * too low, so a higher number might be attempted.
* @returns {Promise<GpgME>} * @returns {Promise<GpgME>}
* @async * @async
@ -46,7 +46,17 @@ function init ({ timeout = 1000 } = {}){
if (result === true) { if (result === true) {
resolve(new GpgME()); resolve(new GpgME());
} else { } else {
reject(gpgme_error('CONN_NO_CONNECT')); if (connection._connectionError) {
if (connection.isNativeHostUnknown){
reject(gpgme_error('CONN_NO_CONFIG'));
} else {
reject(gpgme_error('CONN_NATIVEMESSAGE',
connection._connectionError)
);
}
} else {
reject(gpgme_error('CONN_TIMEOUT'));
}
} }
}, function (){ // unspecific connection error. Should not happen }, function (){ // unspecific connection error. Should not happen
reject(gpgme_error('CONN_NO_CONNECT')); reject(gpgme_error('CONN_NO_CONNECT'));

View File

@ -49,11 +49,42 @@ function unittests (){
expect(answer.info).to.be.an('Array'); expect(answer.info).to.be.an('Array');
expect(conn0.disconnect).to.be.a('function'); expect(conn0.disconnect).to.be.a('function');
expect(conn0.post).to.be.a('function'); expect(conn0.post).to.be.a('function');
expect(conn0.isDisconnected).to.be.false;
done(); done();
}); });
}); });
it('Simple connection check', function (done) {
let conn0 = new Connection;
conn0.checkConnection(false, connectionTimeout).then(
function (answer) {
expect(answer).to.be.true;
expect(conn0.isDisconnected).to.be.false;
done();
});
});
it('Connection check with backend information', function (done) {
let conn0 = new Connection;
conn0.checkConnection(true, connectionTimeout).then(
function (answer) {
expect(answer).to.be.an('Object');
expect(answer.gpgme).to.be.a('String');
expect(answer.info).to.be.an('Array');
expect(answer.info.length).to.be.above(0);
for (const item of answer.info) {
expect(item).to.have.property('protocol');
expect(item).to.have.property('fname');
expect(item).to.have.property('version');
expect(item).to.have.property('req_version');
expect(item).to.have.property('homedir');
}
expect(conn0.isDisconnected).to.be.false;
done();
});
});
it('Disconnecting', function (done) { it('Disconnecting', function (done) {
let conn0 = new Connection; let conn0 = new Connection;
conn0.checkConnection(false, connectionTimeout).then( conn0.checkConnection(false, connectionTimeout).then(
@ -63,6 +94,7 @@ function unittests (){
conn0.checkConnection(false, connectionTimeout).then( conn0.checkConnection(false, connectionTimeout).then(
function (result) { function (result) {
expect(result).to.be.false; expect(result).to.be.false;
expect(conn0.isDisconnected).to.be.true;
done(); done();
}); });
}); });

View File

@ -23,7 +23,13 @@ EXTRA_DIST = \
gpgme.i \ gpgme.i \
helpers.c helpers.h private.h helpers.c helpers.h private.h
SUBDIRS = . tests examples doc src if RUN_GPG_TESTS
tests = tests
else
tests =
endif
SUBDIRS = . ${tests} examples doc src
.PHONY: prepare .PHONY: prepare
prepare: copystamp prepare: copystamp
@ -74,7 +80,7 @@ CLEANFILES = copystamp \
# 'make distclean' clears the write bit, breaking rm -rf. Fix the # 'make distclean' clears the write bit, breaking rm -rf. Fix the
# permissions. # permissions.
clean-local: clean-local:
rm -rf -- build rm -rf -- build dist gpg.egg-info
for PYTHON in $(PYTHONS); do \ for PYTHON in $(PYTHONS); do \
find "$$(basename "$${PYTHON}")-gpg" -type d ! -perm -200 -exec chmod u+w {} ';' ; \ find "$$(basename "$${PYTHON}")-gpg" -type d ! -perm -200 -exec chmod u+w {} ';' ; \
rm -rf -- "$$(basename "$${PYTHON}")-gpg" ; \ rm -rf -- "$$(basename "$${PYTHON}")-gpg" ; \
@ -95,8 +101,12 @@ install-exec-local:
done done
uninstall-local: uninstall-local:
set -x; GV=$$(echo $(VERSION) | tr - _); for PYTHON in $(PYTHONS); do \ set -x; \
GV=$$(echo $(VERSION) | tr - _); \
normalizedGV=$$(echo $$GV | sed s/_beta/b/); \
for PYTHON in $(PYTHONS); do \
PLATLIB="$(prefix)/$$("$${PYTHON}" -c 'import sysconfig, os; print(os.path.relpath(sysconfig.get_path("platlib", scheme="posix_prefix"), sysconfig.get_config_var("prefix")))')" ; \ PLATLIB="$(prefix)/$$("$${PYTHON}" -c 'import sysconfig, os; print(os.path.relpath(sysconfig.get_path("platlib", scheme="posix_prefix"), sysconfig.get_config_var("prefix")))')" ; \
rm -rf -- "$(DESTDIR)$${PLATLIB}/gpg" \ rm -rf -- "$(DESTDIR)$${PLATLIB}/gpg" \
"$(DESTDIR)$${PLATLIB}"/gpg-$$GV-py*.egg-info ; \ "$(DESTDIR)$${PLATLIB}"/gpg-$$GV-py*.egg-info \
"$(DESTDIR)$${PLATLIB}"/gpg-$$normalizedGV-py*.egg ; \
done done

View File

@ -17,32 +17,45 @@
# License along with this program; if not, see <https://gnu.org/licenses/>. # License along with this program; if not, see <https://gnu.org/licenses/>.
# SPDX-License-Identifier: LGPL-2.1-or-later # SPDX-License-Identifier: LGPL-2.1-or-later
# Created by: EXTRA_DIST = README rst src texinfo
# find . -type f -print | sed 's/^.\// /;$q;s/$/ \\/' | sort
EXTRA_DIST = texinfo/what-was-new.texi \ if MAINTAINER_MODE
meta/old-commits.log \
meta/TODO.org \ ORGSRCS = index.org gpgme-python-howto.org maintenance-mode.org \
README \ short-history.org what-is-new.org what-was-new.org
rst/_build/README \
rst/conf.py \ # Make sure we have 'rst' and 'texinfo' dirs in build directory
rst/gpgme-python-howto.rst \ .PHONY: the_doc_dirs gen_rst gen_texi
rst/index.rst \
rst/maintenance-mode.rst \ the_doc_dirs:
rst/short-history.rst \ @if test ! -d rst; then echo $(MKDIR_P) rst; $(MKDIR_P) rst; fi
rst/_static/README \ @if test ! -d texinfo; then echo $(MKDIR_P) texinfo; $(MKDIR_P) texinfo; fi
rst/_templates/README \
rst/what-is-new.rst \ # Generate RST files from ORG
rst/what-was-new.rst \ gen_rst:
src/gpgme-python-howto \ @for f in $(ORGSRCS); do if test ! -e rst/$${f%.org}.rst \
src/index \ -o rst/$${f%.org}.rst -ot $(srcdir)/src/$$f; then \
src/maintenance-mode \ echo pandoc -f org -t rst $(srcdir)/src/$$f -o rst/$${f%.org}.rst; \
src/short-history \ pandoc -f org -t rst $(srcdir)/src/$$f -o rst/$${f%.org}.rst; \
src/what-is-new \ fi; \
src/what-was-new \ done
texinfo/gpgme-python-howto.texi \
texinfo/index.texi \ # Generate Texinfo files from ORG
texinfo/maintenance-mode.texi \ gen_texi:
texinfo/short-history.texi \ @for f in $(ORGSRCS); do if test ! -e texinfo/$${f%.org}.texi \
texinfo/texinfo.tex \ -o texinfo/$${f%.org}.texi -ot $(srcdir)/src/$$f; then \
texinfo/what-is-new.texi \ echo pandoc -f org -t texinfo $(srcdir)/src/$$f -o texinfo/$${f%.org}.texi; \
texinfo/what-was-new.texi pandoc -f org -t texinfo $(srcdir)/src/$$f -o texinfo/$${f%.org}.texi; \
fi; \
done
all-local: gen_rst gen_texi
gen_rst gen_texi: the_doc_dirs
maintainer-clean-local:
@for f in $(ORGSRCS); do \
echo rm -f rst/$${f%.org}.rst texinfo/$${f%.org}.texi; \
rm -f rst/$${f%.org}.rst texinfo/$${f%.org}.texi; \
done
endif

File diff suppressed because it is too large Load Diff

View File

@ -1,22 +0,0 @@
.. GPGME Python Bindings documentation master file, created by
sphinx-quickstart on Wed Dec 5 09:04:47 2018.
You can adapt this file completely to your liking, but it should at least
contain the root `toctree` directive.
GPGME Python Bindings
=====================
.. toctree::
:maxdepth: 3
:caption: Contents:
Contents
--------
- `A short history of the project <short-history>`__
- `What\'s New <what-is-new>`__
- `Maintenance Mode <maintenance-mode>`__ (from January, 2019)
- `What Was New <what-was-new>`__
- `GPGME Python Bindings HOWTO <gpgme-python-howto>`__

View File

@ -1,133 +0,0 @@
.. _maintenance-mode:
Maintenance Mode from 2019
==========================
+-----------------+------------------------------------------+
| Version: | 0.0.1 |
+-----------------+------------------------------------------+
| GPGME Version: | 1.13.0 |
+-----------------+------------------------------------------+
| Author: | Ben McGinnes <ben@gnupg.org> |
+-----------------+------------------------------------------+
| Author GPG Key: | DB4724E6FA4286C92B4E55C4321E4E2373590E5D |
+-----------------+------------------------------------------+
| Language: | Australian English, British English |
+-----------------+------------------------------------------+
| xml:lang: | en-AU, en-GB, en |
+-----------------+------------------------------------------+
From the beginning of 2019 the Python bindings to GPGME will enter
maintenance mode, meaning that new features will not be added and only
bug fixes and security fixes will be made. This also means that
documentation beyond that existing at the end of 2018 will not be
developed further except to correct errors.
Though use of these bindings appears to have been quite well received,
there has been no indication of what demand there is, if any for either
financial backing of the current Python bindings development or support
contracts with g10code GmbH citing the necessity of including the
bindings.
.. _maintenance-mode-bm:
Maintainer from 2019 onward
---------------------------
How does this affect the position of GnuPG Python Bindings Maintainer?
Well, I will remain as maintainer of the bindings; but without funding
for that position, the amount of time I will be able to dedicate solely
to this task will be limited and reduced to volunteered time. As with
all volunteered time and effort in free software projects, this will be
subject to numerous external imperatives.
.. _maintenance-mode-blade-runner:
Using the Python Bindings from 2019 and beyond
----------------------------------------------
For most, if not all, Python developers using these bindings; they will
continue to "just work" the same as they always have. Expansions of
GPGME itself are usually handled by SWIG with the existing code and thus
bindings are generated properly when the bindings are installed
alongside GPGME and when the latter is built from source.
In the rare circumstances where that is not enough to address some new
addition to GPGME, then that is a bug and thus subject to the
maintenance mode provisions (i.e. it will be fixed following a bug
report being raised and your humble author will need to remember where
the timesheet template was filed, depending on how many years off such
an event is).
All the GPGME functionality will continue to be accessible via the lower
level, dynamically generated methods which match the GPGME C
documentation. While the more intuitively Pythonic higher level layer
already covers the vast majority of functionality people require with
key generation, signatures, certifications (key signing), encryption,
decryption, verification, validation, trust levels and so on.
Any wanted features lacking in the Python bindings are usually lacking
because they are missing from GPGME itself (e.g. revoking keys via the
API) and in such cases they are usually deliberately excluded. More
discussion of these issues can be found in the archives of the
`gnupg-devel mailing
list <https://lists.gnupg.org/mailman/listinfo/gnupg-devel>`__.
Any features existing in the dynamically generated layer for which
people want a specific, higher level function included to make it more
Pythonic (e.g. to avoid needing to learn or memorise cryptographic mode
values or GnuPG status code numbers), would be a feature request and
*not* a bug.
It is still worthwhile requesting it, but the addition of such a feature
would not be guaranteed and provided on a purely volunteer basis.
Expediting such a request would require funding that request.
Those with a commercial interest in expediting such a feature request
already know how to `expedite
it <https://gnupg.org/cgi-bin/procdonate.cgi?mode=preset>`__ (use the
message field to state what feature is being requested).
.. _docs:
Documentation formats
---------------------
The documentation has been written in Org mode for GNU Emacs, with both
Texinfo and reStructuredText formats generated from that. The Texinfo
files are intended for use with the rest of the GnuPG documentation;
while the reStructuredText files are intended for use with Docutils and
Sphinx, as with other Python projects.
.. _sphinx-made-epubs-suck:
Cautionary Notes regarding Sphinx and EPUB
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
Though Python\'s Docutils in conjunction with Sphinx is capable of
generating some very useful HTML sites, as proven by `Read the
Docs <https://readthedocs.org/>`__ and the `Python
documentation <https://docs.python.org/>`__, there are a number of
output formats it does not handle well. At the top of the list of things
it manages to break so atrociously as to be embarassing is the `EPUB
3 <http://idpf.org/epub>`__ format.
The automatically generated EPUB of the CPython documentation always
contains hundreds of validation errors and even the modest amount of
documentation here `produced a
file <https://files.au.adversary.org.s3.amazonaws.com/crypto/gpgme-python/rst/epub/GPGMEPythonBindings.epub>`__
with approximately thirty validation errors. As the volume of
documentation content increases, so does the induced errors. Whereas
Texinfo doesn\'t produce EPUB output at all, nor does Org-mode.
Should there ever be genuine demand for this format, lodge a `feature
request <https://dev.gnupg.org/maniphest/task/edit/form/4/>`__ case
marked for `my <https://dev.gnupg.org/p/BenM/>`__ attention. The means
of generating such files flawlessly is already available, but is not yet
part of the GnuPG build system. Nor is it integrated with a means of
converting Org mode input files to the relevant base format
automatically, as can already be done when converting Org to
reStructuredText or Org to Texinfo. As a certain amount of work would be
required to get it done, there would need to be clear demand for that
work to be done.

View File

@ -1,166 +0,0 @@
Overview
========
+-----------------+------------------------------------------+
| Version: | 0.0.1 |
+-----------------+------------------------------------------+
| GPGME Version: | 1.13.0 |
+-----------------+------------------------------------------+
| Author: | Ben McGinnes <ben@gnupg.org> |
+-----------------+------------------------------------------+
| Author GPG Key: | DB4724E6FA4286C92B4E55C4321E4E2373590E5D |
+-----------------+------------------------------------------+
| Language: | Australian English, British English |
+-----------------+------------------------------------------+
| xml:lang: | en-AU, en-GB, en |
+-----------------+------------------------------------------+
The GPGME Python bindings passed through many hands and numerous phases
before, after a fifteen year journey, coming full circle to return to
the source. This is a short explanation of that journey.
.. _in-the-begining:
In the beginning
----------------
In 2002 John Goerzen released PyME; Python bindings for the GPGME module
which utilised the current release of Python of the time and SWIG. [1]_
Shortly after creating it and ensuring it worked he stopped supporting
it, though he left his work available on his Gopher site.
Keeping the flame alive
-----------------------
A couple of years later the project was picked up by Igor Belyi and
actively developed and maintained by him from 2004 to 2008. Igor\'s
whereabouts at the time of this document\'s creation are unknown, but
the current authors do hope he is well. We\'re assuming (or hoping) that
life did what life does and made continuing untenable.
Passing the torch
-----------------
In 2014 Martin Albrecht wanted to patch a bug in the PyME code and
discovered the absence of Igor. Following a discussion on the PyME
mailing list he became the new maintainer for PyME, releasing version
0.9.0 in May of that year. He remains the maintainer of the original
PyME release in Python 2.6 and 2.7 (available via PyPI).
.. _ouroboros:
Coming full circle
------------------
In 2015 Ben McGinnes approached Martin about a Python 3 version, while
investigating how complex a task this would be the task ended up being
completed. A subsequent discussion with Werner Koch led to the decision
to fold the Python 3 port back into the original GPGME release in the
languages subdirectory for non-C bindings under the module name of
``pyme3``.
In 2016 this PyME module was integrated back into the GPGME project by
Justus Winter. During the course of this work Justus adjusted the port
to restore limited support for Python 2, but not as many minor point
releases as the original PyME package supports. During the course of
this integration the package was renamed to more accurately reflect its
status as a component of GPGME. The ``pyme3`` module was renamed to
``gpg`` and adopted by the upstream GnuPG team.
In 2017 Justus departed G10code and the GnuPG team. Following this Ben
returned to maintain of gpgme Python bindings and continue building them
from that point.
.. _relics-past:
Relics of the past
==================
There are a few things, in addition to code specific factors, such as
SWIG itself, which are worth noting here.
The Annoyances of Git
---------------------
As anyone who has ever worked with git knows, submodules are horrible
way to deal with pretty much anything. In the interests of avoiding
migraines, that was skipped with addition of the PyME code to GPGME.
Instead the files were added to a subdirectory of the ``lang/``
directory, along with a copy of the entire git log up to that point as a
separate file within the ``lang/python/docs/`` directory. [2]_ As the
log for PyME is nearly 100KB and the log for GPGME is approximately 1MB,
this would cause considerable bloat, as well as some confusion, should
the two be merged.
Hence the unfortunate, but necessary, step to simply move the files. A
regular repository version has been maintained should it be possible to
implement this better in the future.
The Perils of PyPI
------------------
The early port of the Python 2 ``pyme`` module as ``pyme3`` was never
added to PyPI while the focus remained on development and testing during
2015 and early 2016. Later in 2016, however, when Justus completed his
major integration work and subsequently renamed the module from
``pyme3`` to ``gpg``, some prior releases were also provided through
PyPI.
Since these bindings require a matching release of the GPGME libraries
in order to function, it was determined that there was little benefit in
also providing a copy through PyPI since anyone obtaining the GPGME
source code would obtain the Python bindings source code at the same
time. Whereas there was the potential to sew confusion amongst Python
users installing the module from PyPI, only to discover that without the
relevant C files, header files or SWIG compiled binaries, the Python
module did them little good.
There are only two files on PyPI which might turn up in a search for
this module or a sample of its content:
#. gpg (1.8.0) - Python bindings for GPGME GnuPG cryptography library
#. pyme (0.9.0) - Python support for GPGME GnuPG cryptography library
.. _pypi-gpgme-180:
GPG 1·8·0 - Python bindings for GPGME GnuPG cryptography library
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
This is the most recent version to reach PyPI and is the version of the
official Pyhon bindings which shipped with GPGME 1.8.0. If you have
GPGME 1.8.0 installed and *only* 1.8.0 installed, then it is probably
safe to use this copy from PyPI.
As there have been a lot of changes since the release of GPGME 1.8.0,
the GnuPG Project recommends not using this version of the module and
instead installing the current version of GPGME along with the Python
bindings included with that package.
.. _pypi-gpgme-90:
PyME 0·9·0 - Python support for GPGME GnuPG cryptography library
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
This is the last release of the PyME bindings maintained by Martin
Albrecht and is only compatible with Python 2, it will not work with
Python 3. This is the version of the software from which the port from
Python 2 to Python 3 code was made in 2015.
Users of the more recent Python bindings will recognise numerous points
of similarity, but also significant differences. It is likely that the
more recent official bindings will feel \"more pythonic.\"
For those using Python 2, there is essentially no harm in using this
module, but it may lack a number of more recent features added to GPGME.
Footnotes
=========
.. [1]
In all likelihood this would have been Python 2.2 or possibly Python
2.3.
.. [2]
The entire PyME git log and other preceding VCS logs are located in
the ``gpgme/lang/python/docs/old-commits.log`` file.

View File

@ -1,50 +0,0 @@
.. _new-stuff:
What\'s New
===========
+-----------------+------------------------------------------+
| Version: | 0.0.1 |
+-----------------+------------------------------------------+
| GPGME Version: | 1.13.0 |
+-----------------+------------------------------------------+
| Author: | Ben McGinnes <ben@gnupg.org> |
+-----------------+------------------------------------------+
| Author GPG Key: | DB4724E6FA4286C92B4E55C4321E4E2373590E5D |
+-----------------+------------------------------------------+
| Language: | Australian English, British English |
+-----------------+------------------------------------------+
| xml:lang: | en-AU, en-GB, en |
+-----------------+------------------------------------------+
Last time the most obviously new thing was adding the *What\'s New*
section to the HOWTO. Now it\'s moving it out of the HOWTO.
.. _new-stuff-1-13-0:
New in GPGME 1·13·0
-------------------
Additions since GPGME 1.12.0 include:
- Moving the *What\'s New* section out of the basic
`HOWTO <gpgme-python-howto.org>`__ document and into its own file so
as to more readily include other documents beyond that HOWTO.
- Moving the preceding, archival, segments into `another
file <what-was-new.org>`__.
- Added ``gpg.version.versionintlist`` to make it easier for Python
developers to check for a specific version number, even with beta
versions (it will drop the \"-betaN\" part).
- Added expanded detail on issues pertaining to installing for Windows
users.
- Bindings enter `maintenance mode <maintenance-mode>`__ from January,
2019.
- Added documentation on maintenance mode and what changes can be made
to the code when in that status. Essentially that boils down to bug
fixes only and no feature requests.
- The import-keys-hkp.py example script, which uses the ``hkp4py``
module to search the SKS servers for a key, has been tightened up to
search for both hexadecimal key IDs and user ID strings with reduced
chance of unnecessary repitition. There may still be some repetition
if a key includes a user ID matching the hexadecimal value of a key
ID.

View File

@ -1,111 +0,0 @@
.. _new-stuff:
What Was New
============
+-----------------+------------------------------------------+
| Version: | 0.0.1 |
+-----------------+------------------------------------------+
| GPGME Version: | 1.13.0 |
+-----------------+------------------------------------------+
| Author: | Ben McGinnes <ben@gnupg.org> |
+-----------------+------------------------------------------+
| Author GPG Key: | DB4724E6FA4286C92B4E55C4321E4E2373590E5D |
+-----------------+------------------------------------------+
| Language: | Australian English, British English |
+-----------------+------------------------------------------+
| xml:lang: | en-AU, en-GB, en |
+-----------------+------------------------------------------+
The following are all the past *What\'s New* sections for the Python
Bindings HOWTO and other documentation.
.. _gpgme-1-12-0:
What Was New in GPGME 1·12·0
----------------------------
The most obviously new point for those reading this guide is this
section on other new things, but that's hardly important. Not given all
the other things which spurred the need for adding this section and its
subsections.
.. _new-stuff-1-12-0:
New in GPGME 1·12·0
~~~~~~~~~~~~~~~~~~~
There have been quite a number of additions to GPGME and the Python
bindings to it since the last release of GPGME with versions 1.11.0 and
1.11.1 in April, 2018.
The bullet points of new additiions are:
- an expanded section on
`installing <gpgme-python-howto#installation>`__ and
`troubleshooting <gpgme-python-howto#snafu>`__ the Python bindings.
- The release of Python 3.7.0; which appears to be working just fine
with our bindings, in spite of intermittent reports of problems for
many other Python projects with that new release.
- Python 3.7 has been moved to the head of the specified python
versions list in the build process.
- In order to fix some other issues, there are certain underlying
functions which are more exposed through the
`gpg.Context() <gpgme-python-howto#howto-get-context>`__, but ongoing
documentation ought to clarify that or otherwise provide the best
means of using the bindings. Some additions to ``gpg.core`` and the
``Context()``, however, were intended (see below).
- Continuing work in identifying and confirming the cause of
oft-reported `problems installing the Python bindings on
Windows <gpgme-python-howto#snafu-runtime-not-funtime>`__.
- GSOC: Google\'s Surreptitiously Ordered Conscription ... erm ... oh,
right; Google\'s Summer of Code. Though there were two hopeful
candidates this year; only one ended up involved with the GnuPG
Project directly, the other concentrated on an unrelated third party
project with closer ties to one of the GNU/Linux distributions than
to the GnuPG Project. Thus the Python bindings benefited from GSOC
participant Jacob Adams, who added the key\ :sub:`import` function;
building on prior work by Tobias Mueller.
- Several new methods functions were added to the gpg.Context(),
including: `key\ import <gpgme-python-howto#howto-import-key>`__,
`key\ export <gpgme-python-howto#howto-export-key>`__,
`key\ exportminimal <gpgme-python-howto#howto-export-public-key>`__
and
`key\ exportsecret <gpgme-python-howto#howto-export-secret-key>`__.
- Importing and exporting examples include versions integrated with
Marcel Fest\'s recently released `HKP for
Python <https://github.com/Selfnet/hkp4py>`__ module. Some
`additional notes on this module <gpgme-python-howto#hkp4py>`__ are
included at the end of the HOWTO.
- Instructions for dealing with semi-walled garden implementations like
ProtonMail are also included. This is intended to make things a
little easier when communicating with users of ProtonMail\'s services
and should not be construed as an endorsement of said service. The
GnuPG Project neither favours, nor disfavours ProtonMail and the
majority of this deals with interacting with the ProtonMail
keyserver.
- Semi-formalised the location where `draft
versions <gpgme-python-howto#draft-editions>`__ of this HOWTO may
periodically be accessible. This is both for the reference of others
and testing the publishing of the document itself. Renamed this file
at around the same time.
- The Texinfo documentation build configuration has been replicated
from the parent project in order to make to maintain consistency with
that project (and actually ship with each release).
- a reStructuredText (``.rst``) version is also generated for Python
developers more used to and comfortable with that format as it is the
standard Python documentation format and Python developers may wish
to use it with Sphinx. Please note that there has been no testing of
the reStructuredText version with Sphinx at all. The reST file was
generated by the simple expedient of using
`Pandoc <https://pandoc.org/>`__.
- Added a new section for `advanced or experimental
use <gpgme-python-howto#advanced-use>`__.
- Began the advanced use cases with `a
section <gpgme-python-howto#cython>`__ on using the module with
`Cython <https://cython.org/>`__.
- Added a number of new scripts to the ``example/howto/`` directory;
some of which may be in advance of their planned sections of the
HOWTO (and some are just there because it seemed like a good idea at
the time).
- Cleaned up a lot of things under the hood.

View File

@ -464,8 +464,8 @@ case in most, if not all, cases.
Note that from GPGME [[https://dev.gnupg.org/rMff6ff616aea6f59b7f2ce1176492850ecdf3851e][1.12.1]] the default installation installs to each Note that from GPGME [[https://dev.gnupg.org/rMff6ff616aea6f59b7f2ce1176492850ecdf3851e][1.12.1]] the default installation installs to each
version of Python it can find first. That is that it will currently version of Python it can find first. That is that it will currently
install for the first copies of Python versions 2.7, 3.4, 3.5, 3.6, install for the first copies of Python versions 2.7, 3.4, 3.5, and so on
3.7 and 3.8 (dev branch) that it finds. Usually this will be in the up until the current dev branch that it finds. Usually this will be in the
same prefix as GPGME itself, but is dictated by the =$PATH= when the same prefix as GPGME itself, but is dictated by the =$PATH= when the
installation is performed. The above instructions can still be installation is performed. The above instructions can still be
performed on other python installations which the installer does not performed on other python installations which the installer does not
@ -1612,6 +1612,7 @@ of the entire public keybox.
#+BEGIN_SRC python -i #+BEGIN_SRC python -i
import gpg import gpg
import os
import os.path import os.path
import sys import sys
@ -1619,6 +1620,9 @@ print("""
This script exports one or more public keys in minimised form. This script exports one or more public keys in minimised form.
""") """)
def open_0o600(path, flags):
return os.open(path, flags, mode=0o600)
c = gpg.Context(armor=True) c = gpg.Context(armor=True)
if len(sys.argv) >= 4: if len(sys.argv) >= 4:
@ -1654,7 +1658,7 @@ except:
result = c.key_export_minimal(pattern=None) result = c.key_export_minimal(pattern=None)
if result is not None: if result is not None:
with open(keyfile, "wb") as f: with open(keyfile, "wb", opener=open_0o600) as f:
f.write(result) f.write(result)
else: else:
pass pass
@ -1686,6 +1690,9 @@ This script exports one or more secret keys.
The gpg-agent and pinentry are invoked to authorise the export. The gpg-agent and pinentry are invoked to authorise the export.
""") """)
def open_0o600(path, flags):
return os.open(path, flags, mode=0o600)
c = gpg.Context(armor=True) c = gpg.Context(armor=True)
if len(sys.argv) >= 4: if len(sys.argv) >= 4:
@ -1735,9 +1742,8 @@ except:
result = c.key_export_secret(pattern=None) result = c.key_export_secret(pattern=None)
if result is not None: if result is not None:
with open(keyfile, "wb") as f: with open(keyfile, "wb", opener=open_0o600)) as f:
f.write(result) f.write(result)
os.chmod(keyfile, 0o600)
else: else:
pass pass
#+END_SRC #+END_SRC
@ -2939,7 +2945,7 @@ Save that into a file called =keycount.pyx= and then create a
=setup.py= file which contains this: =setup.py= file which contains this:
#+BEGIN_SRC python -i #+BEGIN_SRC python -i
from distutils.core import setup from setuptools import setup
from Cython.Build import cythonize from Cython.Build import cythonize
setup( setup(
@ -3124,7 +3130,7 @@ minimum required version of GPGME is in use.
For the most part the =gpg.version.versionstr= and For the most part the =gpg.version.versionstr= and
=gpg.version.versionlist= methods have been quite sufficient. The =gpg.version.versionlist= methods have been quite sufficient. The
former returns the same string as =gpgme-config --version=, while the former returns the same string as =pkg-config gpgme --modversion=, while the
latter returns the major, minor and patch values in a list. latter returns the major, minor and patch values in a list.
To check if the installed bindings have actually been built against To check if the installed bindings have actually been built against
@ -3135,7 +3141,7 @@ import gpg
import subprocess import subprocess
import sys import sys
gpgme_version_call = subprocess.Popen(["gpgme-config", "--version"], gpgme_version_call = subprocess.Popen(["pkg-config", "gpgme", "--modversion"],
stdout=subprocess.PIPE, stdout=subprocess.PIPE,
stderr=subprocess.PIPE) stderr=subprocess.PIPE)
gpgme_version_str = gpgme_version_call.communicate() gpgme_version_str = gpgme_version_call.communicate()

Some files were not shown because too many files have changed in this diff Show More