summaryrefslogtreecommitdiff
path: root/lang/qt
diff options
context:
space:
mode:
authorJinWang An <jinwang.an@samsung.com>2023-01-30 13:26:32 +0900
committerJinWang An <jinwang.an@samsung.com>2023-01-30 13:26:32 +0900
commit7068c0ead0c25a9a1fd3ce0b486636d74350e7ca (patch)
tree732edf51b955fd198e4bb7ef46a0782fb3ea1d12 /lang/qt
parentd19c360948ede5ffe5974de8abc9da44be617ca1 (diff)
downloadgpgme-7068c0ead0c25a9a1fd3ce0b486636d74350e7ca.tar.gz
gpgme-7068c0ead0c25a9a1fd3ce0b486636d74350e7ca.tar.bz2
gpgme-7068c0ead0c25a9a1fd3ce0b486636d74350e7ca.zip
Imported Upstream version 1.17.0upstream/1.17.0
Diffstat (limited to 'lang/qt')
-rw-r--r--lang/qt/src/AddExistingSubkeyJob1
-rw-r--r--lang/qt/src/Makefile.am34
-rw-r--r--lang/qt/src/Makefile.in103
-rw-r--r--lang/qt/src/ReceiveKeysJob1
-rw-r--r--lang/qt/src/WKDLookupJob1
-rw-r--r--lang/qt/src/WKDLookupResult1
-rw-r--r--lang/qt/src/addexistingsubkeyjob.h79
-rw-r--r--lang/qt/src/changeexpiryjob.cpp76
-rw-r--r--lang/qt/src/changeexpiryjob.h13
-rw-r--r--lang/qt/src/cryptoconfig.cpp9
-rw-r--r--lang/qt/src/cryptoconfig.h7
-rw-r--r--lang/qt/src/importjob.cpp91
-rw-r--r--lang/qt/src/importjob.h15
-rw-r--r--lang/qt/src/job.cpp32
-rw-r--r--lang/qt/src/job_p.h70
-rw-r--r--lang/qt/src/protocol.h14
-rw-r--r--lang/qt/src/protocol_p.h64
-rw-r--r--lang/qt/src/qgpgmeaddexistingsubkeyjob.cpp96
-rw-r--r--lang/qt/src/qgpgmeaddexistingsubkeyjob.h68
-rw-r--r--lang/qt/src/qgpgmechangeexpiryjob.cpp32
-rw-r--r--lang/qt/src/qgpgmechangeownertrustjob.h2
-rw-r--r--lang/qt/src/qgpgmeexportjob.cpp24
-rw-r--r--lang/qt/src/qgpgmeexportjob.h14
-rw-r--r--lang/qt/src/qgpgmeimportjob.cpp64
-rw-r--r--lang/qt/src/qgpgmenewcryptoconfig.cpp52
-rw-r--r--lang/qt/src/qgpgmenewcryptoconfig.h1
-rw-r--r--lang/qt/src/qgpgmereceivekeysjob.cpp79
-rw-r--r--lang/qt/src/qgpgmereceivekeysjob.h (renamed from lang/qt/src/qgpgmesecretkeyexportjob.h)61
-rw-r--r--lang/qt/src/qgpgmesecretkeyexportjob.cpp147
-rw-r--r--lang/qt/src/qgpgmewkdlookupjob.cpp183
-rw-r--r--lang/qt/src/qgpgmewkdlookupjob.h70
-rw-r--r--lang/qt/src/receivekeysjob.h66
-rw-r--r--lang/qt/src/signkeyjob.h6
-rw-r--r--lang/qt/src/threadedjobmixin.cpp45
-rw-r--r--lang/qt/src/util.cpp47
-rw-r--r--lang/qt/src/util.h51
-rw-r--r--lang/qt/src/wkdlookupjob.h78
-rw-r--r--lang/qt/src/wkdlookupresult.cpp117
-rw-r--r--lang/qt/src/wkdlookupresult.h88
-rw-r--r--lang/qt/tests/Makefile.am36
-rw-r--r--lang/qt/tests/Makefile.in184
-rwxr-xr-xlang/qt/tests/final.test6
-rw-r--r--lang/qt/tests/run-exportjob.cpp119
-rw-r--r--lang/qt/tests/run-importjob.cpp99
-rw-r--r--lang/qt/tests/run-receivekeysjob.cpp65
-rw-r--r--lang/qt/tests/t-addexistingsubkey.cpp260
-rw-r--r--lang/qt/tests/t-changeexpiryjob.cpp396
-rw-r--r--lang/qt/tests/t-config.cpp19
-rw-r--r--lang/qt/tests/t-encrypt.cpp34
-rw-r--r--lang/qt/tests/t-import.cpp169
-rw-r--r--lang/qt/tests/t-keylist.cpp7
-rw-r--r--lang/qt/tests/t-keylocate.cpp3
-rw-r--r--lang/qt/tests/t-ownertrust.cpp3
-rw-r--r--lang/qt/tests/t-remarks.cpp68
-rw-r--r--lang/qt/tests/t-support.cpp52
-rw-r--r--lang/qt/tests/t-support.h60
-rw-r--r--lang/qt/tests/t-tofuinfo.cpp7
-rw-r--r--lang/qt/tests/t-trustsignatures.cpp61
-rw-r--r--lang/qt/tests/t-various.cpp29
-rw-r--r--lang/qt/tests/t-wkdlookup.cpp155
-rw-r--r--lang/qt/tests/t-wkspublish.cpp3
61 files changed, 3303 insertions, 534 deletions
diff --git a/lang/qt/src/AddExistingSubkeyJob b/lang/qt/src/AddExistingSubkeyJob
new file mode 100644
index 0000000..72e02f8
--- /dev/null
+++ b/lang/qt/src/AddExistingSubkeyJob
@@ -0,0 +1 @@
+#include "qgpgme/addexistingsubkeyjob.h"
diff --git a/lang/qt/src/Makefile.am b/lang/qt/src/Makefile.am
index 683b44c..d47da89 100644
--- a/lang/qt/src/Makefile.am
+++ b/lang/qt/src/Makefile.am
@@ -27,25 +27,29 @@ qgpgme_sources = \
dataprovider.cpp \
debug.cpp \
job.cpp multideletejob.cpp qgpgmeadduseridjob.cpp \
+ qgpgmeaddexistingsubkeyjob.cpp \
qgpgmebackend.cpp qgpgmechangeexpiryjob.cpp qgpgmechangeownertrustjob.cpp \
qgpgmechangepasswdjob.cpp qgpgmedecryptjob.cpp \
qgpgmedecryptverifyjob.cpp qgpgmedeletejob.cpp qgpgmedownloadjob.cpp \
qgpgmeencryptjob.cpp qgpgmeexportjob.cpp qgpgmeimportfromkeyserverjob.cpp \
qgpgmeimportjob.cpp qgpgmekeygenerationjob.cpp qgpgmekeylistjob.cpp \
qgpgmelistallkeysjob.cpp qgpgmenewcryptoconfig.cpp \
+ qgpgmereceivekeysjob.cpp \
qgpgmerefreshkeysjob.cpp \
- qgpgmesecretkeyexportjob.cpp qgpgmesignencryptjob.cpp \
+ qgpgmesignencryptjob.cpp \
qgpgmesignjob.cpp qgpgmesignkeyjob.cpp qgpgmeverifydetachedjob.cpp \
- qgpgmeverifyopaquejob.cpp threadedjobmixin.cpp \
+ qgpgmeverifyopaquejob.cpp qgpgmewkdlookupjob.cpp threadedjobmixin.cpp \
qgpgmekeyformailboxjob.cpp qgpgme_debug.cpp \
qgpgmetofupolicyjob.cpp qgpgmequickjob.cpp \
defaultkeygenerationjob.cpp qgpgmewkspublishjob.cpp \
- qgpgmegpgcardjob.cpp \
- dn.cpp cryptoconfig.cpp
+ qgpgmegpgcardjob.cpp changeexpiryjob.cpp importjob.cpp \
+ dn.cpp cryptoconfig.cpp wkdlookupresult.cpp \
+ util.cpp
# If you add one here make sure that you also add one in camelcase
qgpgme_headers= \
abstractimportjob.h \
+ addexistingsubkeyjob.h \
adduseridjob.h \
changeexpiryjob.h \
changeownertrustjob.h \
@@ -65,6 +69,7 @@ qgpgme_headers= \
qgpgme_export.h \
qgpgmenewcryptoconfig.h \
quickjob.h \
+ receivekeysjob.h \
specialjob.h \
signjob.h \
signkeyjob.h \
@@ -81,11 +86,14 @@ qgpgme_headers= \
verifydetachedjob.h \
defaultkeygenerationjob.h \
tofupolicyjob.h \
+ wkdlookupjob.h \
+ wkdlookupresult.h \
wkspublishjob.h \
gpgcardjob.h \
dn.h
camelcase_headers= \
+ AddExistingSubkeyJob \
AddUserIDJob \
AbstractImportJob \
ChangeExpiryJob \
@@ -105,6 +113,7 @@ camelcase_headers= \
Protocol \
QGpgMENewCryptoConfig \
QuickJob \
+ ReceiveKeysJob \
SpecialJob \
SignJob \
SignKeyJob \
@@ -121,6 +130,8 @@ camelcase_headers= \
VerifyDetachedJob \
KeyForMailboxJob \
DefaultKeyGenerationJob \
+ WKDLookupJob \
+ WKDLookupResult \
WKSPublishJob \
TofuPolicyJob \
GpgCardJob
@@ -128,6 +139,8 @@ camelcase_headers= \
private_qgpgme_headers = \
qgpgme_export.h \
protocol_p.h \
+ job_p.h \
+ qgpgmeaddexistingsubkeyjob.h \
qgpgmeadduseridjob.h \
qgpgmebackend.h \
qgpgmechangeexpiryjob.h \
@@ -144,22 +157,25 @@ private_qgpgme_headers = \
qgpgmekeygenerationjob.h \
qgpgmekeylistjob.h \
qgpgmelistallkeysjob.h \
+ qgpgmereceivekeysjob.h \
qgpgmerefreshkeysjob.h \
- qgpgmesecretkeyexportjob.h \
qgpgmesignencryptjob.h \
qgpgmesignjob.h \
qgpgmesignkeyjob.h \
qgpgmeverifydetachedjob.h \
qgpgmeverifyopaquejob.h \
+ qgpgmewkdlookupjob.h \
qgpgmekeyformailboxjob.h \
qgpgmewkspublishjob.h \
qgpgmetofupolicyjob.h \
qgpgmegpgcardjob.h \
qgpgmequickjob.h \
- threadedjobmixin.h
+ threadedjobmixin.h \
+ util.h
qgpgme_moc_sources = \
abstractimportjob.moc \
+ addexistingsubkeyjob.moc \
adduseridjob.moc \
changeexpiryjob.moc \
changeownertrustjob.moc \
@@ -178,6 +194,7 @@ qgpgme_moc_sources = \
keylistjob.moc \
listallkeysjob.moc \
multideletejob.moc \
+ qgpgmeaddexistingsubkeyjob.moc \
qgpgmeadduseridjob.moc \
qgpgmechangeexpiryjob.moc \
qgpgmechangeownertrustjob.moc \
@@ -193,16 +210,18 @@ qgpgme_moc_sources = \
qgpgmekeygenerationjob.moc \
qgpgmekeylistjob.moc \
qgpgmelistallkeysjob.moc \
+ qgpgmereceivekeysjob.moc \
qgpgmerefreshkeysjob.moc \
- qgpgmesecretkeyexportjob.moc \
qgpgmesignencryptjob.moc \
qgpgmesignjob.moc \
qgpgmesignkeyjob.moc \
qgpgmeverifydetachedjob.moc \
qgpgmeverifyopaquejob.moc \
+ qgpgmewkdlookupjob.moc \
qgpgmewkspublishjob.moc \
tofupolicyjob.moc \
qgpgmetofupolicyjob.moc \
+ receivekeysjob.moc \
refreshkeysjob.moc \
signencryptjob.moc \
signjob.moc \
@@ -210,6 +229,7 @@ qgpgme_moc_sources = \
specialjob.moc \
verifydetachedjob.moc \
verifyopaquejob.moc \
+ wkdlookupjob.moc \
keyformailboxjob.moc \
wkspublishjob.moc \
qgpgmekeyformailboxjob.moc \
diff --git a/lang/qt/src/Makefile.in b/lang/qt/src/Makefile.in
index 8e37198..2f09648 100644
--- a/lang/qt/src/Makefile.in
+++ b/lang/qt/src/Makefile.in
@@ -146,21 +146,24 @@ LTLIBRARIES = $(lib_LTLIBRARIES)
libqgpgme_la_DEPENDENCIES = ../../cpp/src/libgpgmepp.la \
../../../src/libgpgme.la
am__objects_1 = dataprovider.lo debug.lo job.lo multideletejob.lo \
- qgpgmeadduseridjob.lo qgpgmebackend.lo \
- qgpgmechangeexpiryjob.lo qgpgmechangeownertrustjob.lo \
- qgpgmechangepasswdjob.lo qgpgmedecryptjob.lo \
- qgpgmedecryptverifyjob.lo qgpgmedeletejob.lo \
- qgpgmedownloadjob.lo qgpgmeencryptjob.lo qgpgmeexportjob.lo \
- qgpgmeimportfromkeyserverjob.lo qgpgmeimportjob.lo \
- qgpgmekeygenerationjob.lo qgpgmekeylistjob.lo \
- qgpgmelistallkeysjob.lo qgpgmenewcryptoconfig.lo \
- qgpgmerefreshkeysjob.lo qgpgmesecretkeyexportjob.lo \
- qgpgmesignencryptjob.lo qgpgmesignjob.lo qgpgmesignkeyjob.lo \
+ qgpgmeadduseridjob.lo qgpgmeaddexistingsubkeyjob.lo \
+ qgpgmebackend.lo qgpgmechangeexpiryjob.lo \
+ qgpgmechangeownertrustjob.lo qgpgmechangepasswdjob.lo \
+ qgpgmedecryptjob.lo qgpgmedecryptverifyjob.lo \
+ qgpgmedeletejob.lo qgpgmedownloadjob.lo qgpgmeencryptjob.lo \
+ qgpgmeexportjob.lo qgpgmeimportfromkeyserverjob.lo \
+ qgpgmeimportjob.lo qgpgmekeygenerationjob.lo \
+ qgpgmekeylistjob.lo qgpgmelistallkeysjob.lo \
+ qgpgmenewcryptoconfig.lo qgpgmereceivekeysjob.lo \
+ qgpgmerefreshkeysjob.lo qgpgmesignencryptjob.lo \
+ qgpgmesignjob.lo qgpgmesignkeyjob.lo \
qgpgmeverifydetachedjob.lo qgpgmeverifyopaquejob.lo \
- threadedjobmixin.lo qgpgmekeyformailboxjob.lo qgpgme_debug.lo \
+ qgpgmewkdlookupjob.lo threadedjobmixin.lo \
+ qgpgmekeyformailboxjob.lo qgpgme_debug.lo \
qgpgmetofupolicyjob.lo qgpgmequickjob.lo \
defaultkeygenerationjob.lo qgpgmewkspublishjob.lo \
- qgpgmegpgcardjob.lo dn.lo cryptoconfig.lo
+ qgpgmegpgcardjob.lo changeexpiryjob.lo importjob.lo dn.lo \
+ cryptoconfig.lo wkdlookupresult.lo util.lo
am__objects_2 =
am_libqgpgme_la_OBJECTS = $(am__objects_1) $(am__objects_2) \
$(am__objects_2)
@@ -189,11 +192,13 @@ am__v_at_1 =
DEFAULT_INCLUDES = -I.@am__isrc@ -I$(top_builddir)/conf
depcomp = $(SHELL) $(top_srcdir)/build-aux/depcomp
am__maybe_remake_depfiles = depfiles
-am__depfiles_remade = ./$(DEPDIR)/cryptoconfig.Plo \
- ./$(DEPDIR)/dataprovider.Plo ./$(DEPDIR)/debug.Plo \
- ./$(DEPDIR)/defaultkeygenerationjob.Plo ./$(DEPDIR)/dn.Plo \
+am__depfiles_remade = ./$(DEPDIR)/changeexpiryjob.Plo \
+ ./$(DEPDIR)/cryptoconfig.Plo ./$(DEPDIR)/dataprovider.Plo \
+ ./$(DEPDIR)/debug.Plo ./$(DEPDIR)/defaultkeygenerationjob.Plo \
+ ./$(DEPDIR)/dn.Plo ./$(DEPDIR)/importjob.Plo \
./$(DEPDIR)/job.Plo ./$(DEPDIR)/multideletejob.Plo \
./$(DEPDIR)/qgpgme_debug.Plo \
+ ./$(DEPDIR)/qgpgmeaddexistingsubkeyjob.Plo \
./$(DEPDIR)/qgpgmeadduseridjob.Plo \
./$(DEPDIR)/qgpgmebackend.Plo \
./$(DEPDIR)/qgpgmechangeexpiryjob.Plo \
@@ -214,15 +219,17 @@ am__depfiles_remade = ./$(DEPDIR)/cryptoconfig.Plo \
./$(DEPDIR)/qgpgmelistallkeysjob.Plo \
./$(DEPDIR)/qgpgmenewcryptoconfig.Plo \
./$(DEPDIR)/qgpgmequickjob.Plo \
+ ./$(DEPDIR)/qgpgmereceivekeysjob.Plo \
./$(DEPDIR)/qgpgmerefreshkeysjob.Plo \
- ./$(DEPDIR)/qgpgmesecretkeyexportjob.Plo \
./$(DEPDIR)/qgpgmesignencryptjob.Plo \
./$(DEPDIR)/qgpgmesignjob.Plo ./$(DEPDIR)/qgpgmesignkeyjob.Plo \
./$(DEPDIR)/qgpgmetofupolicyjob.Plo \
./$(DEPDIR)/qgpgmeverifydetachedjob.Plo \
./$(DEPDIR)/qgpgmeverifyopaquejob.Plo \
+ ./$(DEPDIR)/qgpgmewkdlookupjob.Plo \
./$(DEPDIR)/qgpgmewkspublishjob.Plo \
- ./$(DEPDIR)/threadedjobmixin.Plo
+ ./$(DEPDIR)/threadedjobmixin.Plo ./$(DEPDIR)/util.Plo \
+ ./$(DEPDIR)/wkdlookupresult.Plo
am__mv = mv -f
CXXCOMPILE = $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) \
$(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS)
@@ -523,26 +530,30 @@ qgpgme_sources = \
dataprovider.cpp \
debug.cpp \
job.cpp multideletejob.cpp qgpgmeadduseridjob.cpp \
+ qgpgmeaddexistingsubkeyjob.cpp \
qgpgmebackend.cpp qgpgmechangeexpiryjob.cpp qgpgmechangeownertrustjob.cpp \
qgpgmechangepasswdjob.cpp qgpgmedecryptjob.cpp \
qgpgmedecryptverifyjob.cpp qgpgmedeletejob.cpp qgpgmedownloadjob.cpp \
qgpgmeencryptjob.cpp qgpgmeexportjob.cpp qgpgmeimportfromkeyserverjob.cpp \
qgpgmeimportjob.cpp qgpgmekeygenerationjob.cpp qgpgmekeylistjob.cpp \
qgpgmelistallkeysjob.cpp qgpgmenewcryptoconfig.cpp \
+ qgpgmereceivekeysjob.cpp \
qgpgmerefreshkeysjob.cpp \
- qgpgmesecretkeyexportjob.cpp qgpgmesignencryptjob.cpp \
+ qgpgmesignencryptjob.cpp \
qgpgmesignjob.cpp qgpgmesignkeyjob.cpp qgpgmeverifydetachedjob.cpp \
- qgpgmeverifyopaquejob.cpp threadedjobmixin.cpp \
+ qgpgmeverifyopaquejob.cpp qgpgmewkdlookupjob.cpp threadedjobmixin.cpp \
qgpgmekeyformailboxjob.cpp qgpgme_debug.cpp \
qgpgmetofupolicyjob.cpp qgpgmequickjob.cpp \
defaultkeygenerationjob.cpp qgpgmewkspublishjob.cpp \
- qgpgmegpgcardjob.cpp \
- dn.cpp cryptoconfig.cpp
+ qgpgmegpgcardjob.cpp changeexpiryjob.cpp importjob.cpp \
+ dn.cpp cryptoconfig.cpp wkdlookupresult.cpp \
+ util.cpp
# If you add one here make sure that you also add one in camelcase
qgpgme_headers = \
abstractimportjob.h \
+ addexistingsubkeyjob.h \
adduseridjob.h \
changeexpiryjob.h \
changeownertrustjob.h \
@@ -562,6 +573,7 @@ qgpgme_headers = \
qgpgme_export.h \
qgpgmenewcryptoconfig.h \
quickjob.h \
+ receivekeysjob.h \
specialjob.h \
signjob.h \
signkeyjob.h \
@@ -578,11 +590,14 @@ qgpgme_headers = \
verifydetachedjob.h \
defaultkeygenerationjob.h \
tofupolicyjob.h \
+ wkdlookupjob.h \
+ wkdlookupresult.h \
wkspublishjob.h \
gpgcardjob.h \
dn.h
camelcase_headers = \
+ AddExistingSubkeyJob \
AddUserIDJob \
AbstractImportJob \
ChangeExpiryJob \
@@ -602,6 +617,7 @@ camelcase_headers = \
Protocol \
QGpgMENewCryptoConfig \
QuickJob \
+ ReceiveKeysJob \
SpecialJob \
SignJob \
SignKeyJob \
@@ -618,6 +634,8 @@ camelcase_headers = \
VerifyDetachedJob \
KeyForMailboxJob \
DefaultKeyGenerationJob \
+ WKDLookupJob \
+ WKDLookupResult \
WKSPublishJob \
TofuPolicyJob \
GpgCardJob
@@ -625,6 +643,8 @@ camelcase_headers = \
private_qgpgme_headers = \
qgpgme_export.h \
protocol_p.h \
+ job_p.h \
+ qgpgmeaddexistingsubkeyjob.h \
qgpgmeadduseridjob.h \
qgpgmebackend.h \
qgpgmechangeexpiryjob.h \
@@ -641,22 +661,25 @@ private_qgpgme_headers = \
qgpgmekeygenerationjob.h \
qgpgmekeylistjob.h \
qgpgmelistallkeysjob.h \
+ qgpgmereceivekeysjob.h \
qgpgmerefreshkeysjob.h \
- qgpgmesecretkeyexportjob.h \
qgpgmesignencryptjob.h \
qgpgmesignjob.h \
qgpgmesignkeyjob.h \
qgpgmeverifydetachedjob.h \
qgpgmeverifyopaquejob.h \
+ qgpgmewkdlookupjob.h \
qgpgmekeyformailboxjob.h \
qgpgmewkspublishjob.h \
qgpgmetofupolicyjob.h \
qgpgmegpgcardjob.h \
qgpgmequickjob.h \
- threadedjobmixin.h
+ threadedjobmixin.h \
+ util.h
qgpgme_moc_sources = \
abstractimportjob.moc \
+ addexistingsubkeyjob.moc \
adduseridjob.moc \
changeexpiryjob.moc \
changeownertrustjob.moc \
@@ -675,6 +698,7 @@ qgpgme_moc_sources = \
keylistjob.moc \
listallkeysjob.moc \
multideletejob.moc \
+ qgpgmeaddexistingsubkeyjob.moc \
qgpgmeadduseridjob.moc \
qgpgmechangeexpiryjob.moc \
qgpgmechangeownertrustjob.moc \
@@ -690,16 +714,18 @@ qgpgme_moc_sources = \
qgpgmekeygenerationjob.moc \
qgpgmekeylistjob.moc \
qgpgmelistallkeysjob.moc \
+ qgpgmereceivekeysjob.moc \
qgpgmerefreshkeysjob.moc \
- qgpgmesecretkeyexportjob.moc \
qgpgmesignencryptjob.moc \
qgpgmesignjob.moc \
qgpgmesignkeyjob.moc \
qgpgmeverifydetachedjob.moc \
qgpgmeverifyopaquejob.moc \
+ qgpgmewkdlookupjob.moc \
qgpgmewkspublishjob.moc \
tofupolicyjob.moc \
qgpgmetofupolicyjob.moc \
+ receivekeysjob.moc \
refreshkeysjob.moc \
signencryptjob.moc \
signjob.moc \
@@ -707,6 +733,7 @@ qgpgme_moc_sources = \
specialjob.moc \
verifydetachedjob.moc \
verifyopaquejob.moc \
+ wkdlookupjob.moc \
keyformailboxjob.moc \
wkspublishjob.moc \
qgpgmekeyformailboxjob.moc \
@@ -828,14 +855,17 @@ mostlyclean-compile:
distclean-compile:
-rm -f *.tab.c
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/changeexpiryjob.Plo@am__quote@ # am--include-marker
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/cryptoconfig.Plo@am__quote@ # am--include-marker
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/dataprovider.Plo@am__quote@ # am--include-marker
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/debug.Plo@am__quote@ # am--include-marker
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/defaultkeygenerationjob.Plo@am__quote@ # am--include-marker
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/dn.Plo@am__quote@ # am--include-marker
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/importjob.Plo@am__quote@ # am--include-marker
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/job.Plo@am__quote@ # am--include-marker
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/multideletejob.Plo@am__quote@ # am--include-marker
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/qgpgme_debug.Plo@am__quote@ # am--include-marker
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/qgpgmeaddexistingsubkeyjob.Plo@am__quote@ # am--include-marker
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/qgpgmeadduseridjob.Plo@am__quote@ # am--include-marker
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/qgpgmebackend.Plo@am__quote@ # am--include-marker
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/qgpgmechangeexpiryjob.Plo@am__quote@ # am--include-marker
@@ -856,16 +886,19 @@ distclean-compile:
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/qgpgmelistallkeysjob.Plo@am__quote@ # am--include-marker
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/qgpgmenewcryptoconfig.Plo@am__quote@ # am--include-marker
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/qgpgmequickjob.Plo@am__quote@ # am--include-marker
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/qgpgmereceivekeysjob.Plo@am__quote@ # am--include-marker
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/qgpgmerefreshkeysjob.Plo@am__quote@ # am--include-marker
-@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/qgpgmesecretkeyexportjob.Plo@am__quote@ # am--include-marker
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/qgpgmesignencryptjob.Plo@am__quote@ # am--include-marker
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/qgpgmesignjob.Plo@am__quote@ # am--include-marker
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/qgpgmesignkeyjob.Plo@am__quote@ # am--include-marker
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/qgpgmetofupolicyjob.Plo@am__quote@ # am--include-marker
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/qgpgmeverifydetachedjob.Plo@am__quote@ # am--include-marker
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/qgpgmeverifyopaquejob.Plo@am__quote@ # am--include-marker
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/qgpgmewkdlookupjob.Plo@am__quote@ # am--include-marker
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/qgpgmewkspublishjob.Plo@am__quote@ # am--include-marker
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/threadedjobmixin.Plo@am__quote@ # am--include-marker
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/util.Plo@am__quote@ # am--include-marker
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/wkdlookupresult.Plo@am__quote@ # am--include-marker
$(am__depfiles_remade):
@$(MKDIR_P) $(@D)
@@ -1096,14 +1129,17 @@ clean-am: clean-generic clean-libLTLIBRARIES clean-libtool \
mostlyclean-am
distclean: distclean-am
- -rm -f ./$(DEPDIR)/cryptoconfig.Plo
+ -rm -f ./$(DEPDIR)/changeexpiryjob.Plo
+ -rm -f ./$(DEPDIR)/cryptoconfig.Plo
-rm -f ./$(DEPDIR)/dataprovider.Plo
-rm -f ./$(DEPDIR)/debug.Plo
-rm -f ./$(DEPDIR)/defaultkeygenerationjob.Plo
-rm -f ./$(DEPDIR)/dn.Plo
+ -rm -f ./$(DEPDIR)/importjob.Plo
-rm -f ./$(DEPDIR)/job.Plo
-rm -f ./$(DEPDIR)/multideletejob.Plo
-rm -f ./$(DEPDIR)/qgpgme_debug.Plo
+ -rm -f ./$(DEPDIR)/qgpgmeaddexistingsubkeyjob.Plo
-rm -f ./$(DEPDIR)/qgpgmeadduseridjob.Plo
-rm -f ./$(DEPDIR)/qgpgmebackend.Plo
-rm -f ./$(DEPDIR)/qgpgmechangeexpiryjob.Plo
@@ -1124,16 +1160,19 @@ distclean: distclean-am
-rm -f ./$(DEPDIR)/qgpgmelistallkeysjob.Plo
-rm -f ./$(DEPDIR)/qgpgmenewcryptoconfig.Plo
-rm -f ./$(DEPDIR)/qgpgmequickjob.Plo
+ -rm -f ./$(DEPDIR)/qgpgmereceivekeysjob.Plo
-rm -f ./$(DEPDIR)/qgpgmerefreshkeysjob.Plo
- -rm -f ./$(DEPDIR)/qgpgmesecretkeyexportjob.Plo
-rm -f ./$(DEPDIR)/qgpgmesignencryptjob.Plo
-rm -f ./$(DEPDIR)/qgpgmesignjob.Plo
-rm -f ./$(DEPDIR)/qgpgmesignkeyjob.Plo
-rm -f ./$(DEPDIR)/qgpgmetofupolicyjob.Plo
-rm -f ./$(DEPDIR)/qgpgmeverifydetachedjob.Plo
-rm -f ./$(DEPDIR)/qgpgmeverifyopaquejob.Plo
+ -rm -f ./$(DEPDIR)/qgpgmewkdlookupjob.Plo
-rm -f ./$(DEPDIR)/qgpgmewkspublishjob.Plo
-rm -f ./$(DEPDIR)/threadedjobmixin.Plo
+ -rm -f ./$(DEPDIR)/util.Plo
+ -rm -f ./$(DEPDIR)/wkdlookupresult.Plo
-rm -f Makefile
distclean-am: clean-am distclean-compile distclean-generic \
distclean-tags
@@ -1181,14 +1220,17 @@ install-ps-am:
installcheck-am:
maintainer-clean: maintainer-clean-am
- -rm -f ./$(DEPDIR)/cryptoconfig.Plo
+ -rm -f ./$(DEPDIR)/changeexpiryjob.Plo
+ -rm -f ./$(DEPDIR)/cryptoconfig.Plo
-rm -f ./$(DEPDIR)/dataprovider.Plo
-rm -f ./$(DEPDIR)/debug.Plo
-rm -f ./$(DEPDIR)/defaultkeygenerationjob.Plo
-rm -f ./$(DEPDIR)/dn.Plo
+ -rm -f ./$(DEPDIR)/importjob.Plo
-rm -f ./$(DEPDIR)/job.Plo
-rm -f ./$(DEPDIR)/multideletejob.Plo
-rm -f ./$(DEPDIR)/qgpgme_debug.Plo
+ -rm -f ./$(DEPDIR)/qgpgmeaddexistingsubkeyjob.Plo
-rm -f ./$(DEPDIR)/qgpgmeadduseridjob.Plo
-rm -f ./$(DEPDIR)/qgpgmebackend.Plo
-rm -f ./$(DEPDIR)/qgpgmechangeexpiryjob.Plo
@@ -1209,16 +1251,19 @@ maintainer-clean: maintainer-clean-am
-rm -f ./$(DEPDIR)/qgpgmelistallkeysjob.Plo
-rm -f ./$(DEPDIR)/qgpgmenewcryptoconfig.Plo
-rm -f ./$(DEPDIR)/qgpgmequickjob.Plo
+ -rm -f ./$(DEPDIR)/qgpgmereceivekeysjob.Plo
-rm -f ./$(DEPDIR)/qgpgmerefreshkeysjob.Plo
- -rm -f ./$(DEPDIR)/qgpgmesecretkeyexportjob.Plo
-rm -f ./$(DEPDIR)/qgpgmesignencryptjob.Plo
-rm -f ./$(DEPDIR)/qgpgmesignjob.Plo
-rm -f ./$(DEPDIR)/qgpgmesignkeyjob.Plo
-rm -f ./$(DEPDIR)/qgpgmetofupolicyjob.Plo
-rm -f ./$(DEPDIR)/qgpgmeverifydetachedjob.Plo
-rm -f ./$(DEPDIR)/qgpgmeverifyopaquejob.Plo
+ -rm -f ./$(DEPDIR)/qgpgmewkdlookupjob.Plo
-rm -f ./$(DEPDIR)/qgpgmewkspublishjob.Plo
-rm -f ./$(DEPDIR)/threadedjobmixin.Plo
+ -rm -f ./$(DEPDIR)/util.Plo
+ -rm -f ./$(DEPDIR)/wkdlookupresult.Plo
-rm -f Makefile
maintainer-clean-am: distclean-am maintainer-clean-generic
diff --git a/lang/qt/src/ReceiveKeysJob b/lang/qt/src/ReceiveKeysJob
new file mode 100644
index 0000000..4ee4735
--- /dev/null
+++ b/lang/qt/src/ReceiveKeysJob
@@ -0,0 +1 @@
+#include "qgpgme/receivekeysjob.h"
diff --git a/lang/qt/src/WKDLookupJob b/lang/qt/src/WKDLookupJob
new file mode 100644
index 0000000..3b67494
--- /dev/null
+++ b/lang/qt/src/WKDLookupJob
@@ -0,0 +1 @@
+#include "qgpgme/wkdlookupjob.h"
diff --git a/lang/qt/src/WKDLookupResult b/lang/qt/src/WKDLookupResult
new file mode 100644
index 0000000..8833683
--- /dev/null
+++ b/lang/qt/src/WKDLookupResult
@@ -0,0 +1 @@
+#include "qgpgme/wkdlookupresult.h"
diff --git a/lang/qt/src/addexistingsubkeyjob.h b/lang/qt/src/addexistingsubkeyjob.h
new file mode 100644
index 0000000..5465778
--- /dev/null
+++ b/lang/qt/src/addexistingsubkeyjob.h
@@ -0,0 +1,79 @@
+/*
+ addexistingsubkeyjob.h
+
+ This file is part of qgpgme, the Qt API binding for gpgme
+ Copyright (c) 2022 g10 Code GmbH
+ Software engineering by Ingo Klöcker <dev@ingo-kloecker.de>
+
+ QGpgME is free software; you can redistribute it and/or
+ modify it under the terms of the GNU General Public License as
+ published by the Free Software Foundation; either version 2 of the
+ License, or (at your option) any later version.
+
+ QGpgME is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
+
+ In addition, as a special exception, the copyright holders give
+ permission to link the code of this program with any edition of
+ the Qt library by Trolltech AS, Norway (or with modified versions
+ of Qt that use the same license as Qt), and distribute linked
+ combinations including the two. You must obey the GNU General
+ Public License in all respects for all of the code used other than
+ Qt. If you modify this file, you may extend this exception to
+ your version of the file, but you are not obligated to do so. If
+ you do not wish to do so, delete this exception statement from
+ your version.
+*/
+
+#ifndef __QGPGME_ADDEXISTINGSUBKEYJOB_H__
+#define __QGPGME_ADDEXISTINGSUBKEYJOB_H__
+
+#include "job.h"
+#include "qgpgme_export.h"
+
+class QString;
+
+namespace GpgME
+{
+class Error;
+class Key;
+class Subkey;
+}
+
+namespace QGpgME
+{
+
+class QGPGME_EXPORT AddExistingSubkeyJob : public Job
+{
+ Q_OBJECT
+protected:
+ explicit AddExistingSubkeyJob(QObject *parent);
+
+public:
+ ~AddExistingSubkeyJob();
+
+ /**
+ Starts the operation. \a key is the key to add the subkey \a subkey to.
+
+ The job deletes itself after it has completed the operation.
+ */
+ virtual GpgME::Error start(const GpgME::Key &key, const GpgME::Subkey &subkey) = 0;
+
+ /**
+ Runs the operation. \a key is the key to add the subkey \a subkey to.
+ */
+ virtual GpgME::Error exec(const GpgME::Key &key, const GpgME::Subkey &subkey) = 0;
+
+Q_SIGNALS:
+ void result(const GpgME::Error &result, const QString &auditLogAsHtml = {}, const GpgME::Error &auditLogError = {});
+};
+
+}
+
+#endif // __QGPGME_ADDEXISTINGSUBKEYJOB_H__
diff --git a/lang/qt/src/changeexpiryjob.cpp b/lang/qt/src/changeexpiryjob.cpp
new file mode 100644
index 0000000..49f68cc
--- /dev/null
+++ b/lang/qt/src/changeexpiryjob.cpp
@@ -0,0 +1,76 @@
+/*
+ changeexpiryjob.cpp
+
+ This file is part of qgpgme, the Qt API binding for gpgme
+ Copyright (c) 2021 g10 Code GmbH
+ Software engineering by Ingo Klöcker <dev@ingo-kloecker.de>
+
+ QGpgME is free software; you can redistribute it and/or
+ modify it under the terms of the GNU General Public License as
+ published by the Free Software Foundation; either version 2 of the
+ License, or (at your option) any later version.
+
+ QGpgME is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
+
+ In addition, as a special exception, the copyright holders give
+ permission to link the code of this program with any edition of
+ the Qt library by Trolltech AS, Norway (or with modified versions
+ of Qt that use the same license as Qt), and distribute linked
+ combinations including the two. You must obey the GNU General
+ Public License in all respects for all of the code used other than
+ Qt. If you modify this file, you may extend this exception to
+ your version of the file, but you are not obligated to do so. If
+ you do not wish to do so, delete this exception statement from
+ your version.
+*/
+
+#ifdef HAVE_CONFIG_H
+ #include "config.h"
+#endif
+
+#include "changeexpiryjob.h"
+#include "job_p.h"
+
+#include <context.h>
+
+using namespace GpgME;
+using namespace QGpgME;
+
+namespace
+{
+struct ChangeExpiryJobPrivate : public JobPrivate
+{
+ ChangeExpiryJobPrivate()
+ {
+ }
+
+ ~ChangeExpiryJobPrivate() override = default;
+
+ ChangeExpiryJob::Options m_options = ChangeExpiryJob::Default;
+};
+}
+
+void ChangeExpiryJob::setOptions(ChangeExpiryJob::Options options)
+{
+ auto d = jobPrivate<ChangeExpiryJobPrivate>(this);
+ d->m_options = options;
+}
+
+ChangeExpiryJob::Options ChangeExpiryJob::options() const
+{
+ auto d = jobPrivate<ChangeExpiryJobPrivate>(this);
+ return d->m_options;
+}
+
+/* For ABI compat not pure virtual. */
+Error ChangeExpiryJob::start(const Key &, const QDateTime &, const std::vector<Subkey> &)
+{
+ return {};
+}
diff --git a/lang/qt/src/changeexpiryjob.h b/lang/qt/src/changeexpiryjob.h
index 39ed52e..0c5e1b2 100644
--- a/lang/qt/src/changeexpiryjob.h
+++ b/lang/qt/src/changeexpiryjob.h
@@ -71,11 +71,22 @@ namespace QGpgME
class QGPGME_EXPORT ChangeExpiryJob : public Job
{
Q_OBJECT
+public:
+ enum Option {
+ Default = 0x00,
+ UpdatePrimaryKey = 0x01,
+ UpdateAllSubkeys = 0x02,
+ };
+ Q_DECLARE_FLAGS(Options, Option)
+
protected:
explicit ChangeExpiryJob(QObject *parent);
public:
~ChangeExpiryJob();
+ void setOptions(Options options);
+ Options options() const;
+
/**
Starts the change-expiry operation. \a key is the key to change
the expiry of. \a expiry is the new expiry time. If \a expiry
@@ -97,6 +108,8 @@ Q_SIGNALS:
void result(const GpgME::Error &result, const QString &auditLogAsHtml = QString(), const GpgME::Error &auditLogError = GpgME::Error());
};
+Q_DECLARE_OPERATORS_FOR_FLAGS(ChangeExpiryJob::Options)
+
}
#endif // __KLEO_CHANGEEXPIRYJOB_H__
diff --git a/lang/qt/src/cryptoconfig.cpp b/lang/qt/src/cryptoconfig.cpp
index d52dce7..4f13d3f 100644
--- a/lang/qt/src/cryptoconfig.cpp
+++ b/lang/qt/src/cryptoconfig.cpp
@@ -44,6 +44,15 @@ QStringList CryptoConfigEntry::stringValueList() const
return entry->stringValueList();
}
+QVariant CryptoConfigEntry::defaultValue() const
+{
+ const QGpgMENewCryptoConfigEntry *entry = dynamic_cast <const QGpgMENewCryptoConfigEntry*>(this);
+ if (!entry) {
+ return {};
+ }
+ return entry->defaultValue();
+}
+
QGpgME::CryptoConfigEntry *CryptoConfig::entry(const QString &componentName, const QString &entryName) const
{
const CryptoConfigComponent *comp = component(componentName);
diff --git a/lang/qt/src/cryptoconfig.h b/lang/qt/src/cryptoconfig.h
index 651e2af..d87f7d4 100644
--- a/lang/qt/src/cryptoconfig.h
+++ b/lang/qt/src/cryptoconfig.h
@@ -44,6 +44,8 @@
#include <vector>
+class QVariant;
+
/* Start reading this file from the bottom up :) */
namespace QGpgME
@@ -258,6 +260,11 @@ public:
* @return a stringValueList.
*/
QStringList stringValueList() const;
+
+ /**
+ * Return the default value as a variant (available for all argtypes).
+ */
+ QVariant defaultValue() const;
};
/**
diff --git a/lang/qt/src/importjob.cpp b/lang/qt/src/importjob.cpp
new file mode 100644
index 0000000..4f40d9b
--- /dev/null
+++ b/lang/qt/src/importjob.cpp
@@ -0,0 +1,91 @@
+/*
+ importjob.cpp
+
+ This file is part of qgpgme, the Qt API binding for gpgme
+ Copyright (c) 2021 g10 Code GmbH
+ Software engineering by Ingo Klöcker <dev@ingo-kloecker.de>
+
+ QGpgME is free software; you can redistribute it and/or
+ modify it under the terms of the GNU General Public License as
+ published by the Free Software Foundation; either version 2 of the
+ License, or (at your option) any later version.
+
+ QGpgME is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
+
+ In addition, as a special exception, the copyright holders give
+ permission to link the code of this program with any edition of
+ the Qt library by Trolltech AS, Norway (or with modified versions
+ of Qt that use the same license as Qt), and distribute linked
+ combinations including the two. You must obey the GNU General
+ Public License in all respects for all of the code used other than
+ Qt. If you modify this file, you may extend this exception to
+ your version of the file, but you are not obligated to do so. If
+ you do not wish to do so, delete this exception statement from
+ your version.
+*/
+
+#ifdef HAVE_CONFIG_H
+ #include "config.h"
+#endif
+
+#include "importjob.h"
+#include "job_p.h"
+
+#include <context.h>
+
+using namespace GpgME;
+using namespace QGpgME;
+
+namespace
+{
+struct ImportJobPrivate : public JobPrivate
+{
+ ImportJobPrivate()
+ {
+ }
+
+ ~ImportJobPrivate() override = default;
+
+ QString m_importFilter;
+ Key::Origin m_keyOrigin = Key::OriginUnknown;
+ QString m_keyOriginUrl;
+};
+}
+
+void QGpgME::ImportJob::setImportFilter(const QString &filter)
+{
+ const auto d = jobPrivate<ImportJobPrivate>(this);
+ d->m_importFilter = filter;
+}
+
+QString QGpgME::ImportJob::importFilter() const
+{
+ const auto d = jobPrivate<ImportJobPrivate>(this);
+ return d->m_importFilter;
+}
+
+void ImportJob::setKeyOrigin(GpgME::Key::Origin origin, const QString &url)
+{
+ const auto d = jobPrivate<ImportJobPrivate>(this);
+ d->m_keyOrigin = origin;
+ d->m_keyOriginUrl = url;
+}
+
+GpgME::Key::Origin ImportJob::keyOrigin() const
+{
+ const auto d = jobPrivate<ImportJobPrivate>(this);
+ return d->m_keyOrigin;
+}
+
+QString ImportJob::keyOriginUrl() const
+{
+ const auto d = jobPrivate<ImportJobPrivate>(this);
+ return d->m_keyOriginUrl;
+}
diff --git a/lang/qt/src/importjob.h b/lang/qt/src/importjob.h
index 7437fbd..a81dcf2 100644
--- a/lang/qt/src/importjob.h
+++ b/lang/qt/src/importjob.h
@@ -38,7 +38,11 @@
#include "abstractimportjob.h"
#include "qgpgme_export.h"
-#include <QtCore/QByteArray>
+#ifdef BUILDING_QGPGME
+# include <key.h>
+#else
+# include <gpgme++/key.h>
+#endif
namespace GpgME
{
@@ -68,7 +72,14 @@ class QGPGME_EXPORT ImportJob : public AbstractImportJob
protected:
explicit ImportJob(QObject *parent);
public:
- ~ImportJob();
+ ~ImportJob() override;
+
+ void setImportFilter(const QString &filter);
+ QString importFilter() const;
+
+ void setKeyOrigin(GpgME::Key::Origin origin, const QString &url = {});
+ GpgME::Key::Origin keyOrigin() const;
+ QString keyOriginUrl() const;
/**
Starts the importing operation. \a keyData contains the data to
diff --git a/lang/qt/src/job.cpp b/lang/qt/src/job.cpp
index 8ed0b57..a9edc8e 100644
--- a/lang/qt/src/job.cpp
+++ b/lang/qt/src/job.cpp
@@ -5,6 +5,8 @@
Copyright (c) 2004,2005 Klarälvdalens Datakonsult AB
Copyright (c) 2016 by Bundesamt für Sicherheit in der Informationstechnik
Software engineering by Intevation GmbH
+ Copyright (c) 2021 g10 Code GmbH
+ Software engineering by Ingo Klöcker <dev@ingo-kloecker.de>
QGpgME is free software; you can redistribute it and/or
modify it under the terms of the GNU General Public License as
@@ -37,6 +39,7 @@
#endif
#include "job.h"
+#include "job_p.h"
#include "keylistjob.h"
#include "listallkeysjob.h"
@@ -58,20 +61,42 @@
#include "downloadjob.h"
#include "deletejob.h"
#include "refreshkeysjob.h"
+#include "addexistingsubkeyjob.h"
#include "adduseridjob.h"
#include "specialjob.h"
#include "keyformailboxjob.h"
+#include "wkdlookupjob.h"
#include "wkspublishjob.h"
#include "tofupolicyjob.h"
#include "threadedjobmixin.h"
#include "quickjob.h"
#include "gpgcardjob.h"
+#include "receivekeysjob.h"
#include <QCoreApplication>
#include <QDebug>
#include <gpg-error.h>
+#include <unordered_map>
+
+namespace
+{
+typedef std::unordered_map<const QGpgME::Job*, std::unique_ptr<QGpgME::JobPrivate>> JobPrivateHash;
+Q_GLOBAL_STATIC(JobPrivateHash, d_func)
+}
+
+void QGpgME::setJobPrivate(const Job *job, std::unique_ptr<JobPrivate> d)
+{
+ auto &ref = d_func()->operator[](job);
+ ref = std::move(d);
+}
+
+QGpgME::JobPrivate *QGpgME::getJobPrivate(const Job *job)
+{
+ return d_func()->operator[](job).get();
+}
+
QGpgME::Job::Job(QObject *parent)
: QObject(parent)
{
@@ -82,6 +107,7 @@ QGpgME::Job::Job(QObject *parent)
QGpgME::Job::~Job()
{
+ ::d_func()->erase(this);
}
QString QGpgME::Job::auditLogAsHtml() const
@@ -129,6 +155,7 @@ make_job_subclass(KeyGenerationJob)
make_job_subclass(AbstractImportJob)
make_job_subclass_ext(ImportJob, AbstractImportJob)
make_job_subclass_ext(ImportFromKeyserverJob, AbstractImportJob)
+make_job_subclass_ext(ReceiveKeysJob, AbstractImportJob)
make_job_subclass(ExportJob)
make_job_subclass(ChangeExpiryJob)
make_job_subclass(ChangeOwnerTrustJob)
@@ -136,9 +163,11 @@ make_job_subclass(ChangePasswdJob)
make_job_subclass(DownloadJob)
make_job_subclass(DeleteJob)
make_job_subclass(RefreshKeysJob)
+make_job_subclass(AddExistingSubkeyJob)
make_job_subclass(AddUserIDJob)
make_job_subclass(SpecialJob)
make_job_subclass(KeyForMailboxJob)
+make_job_subclass(WKDLookupJob)
make_job_subclass(WKSPublishJob)
make_job_subclass(TofuPolicyJob)
make_job_subclass(QuickJob)
@@ -169,10 +198,13 @@ make_job_subclass(GpgCardJob)
#include "downloadjob.moc"
#include "deletejob.moc"
#include "refreshkeysjob.moc"
+#include "addexistingsubkeyjob.moc"
#include "adduseridjob.moc"
#include "specialjob.moc"
#include "keyformailboxjob.moc"
+#include "wkdlookupjob.moc"
#include "wkspublishjob.moc"
#include "tofupolicyjob.moc"
#include "quickjob.moc"
#include "gpgcardjob.moc"
+#include "receivekeysjob.moc"
diff --git a/lang/qt/src/job_p.h b/lang/qt/src/job_p.h
new file mode 100644
index 0000000..3bce4cf
--- /dev/null
+++ b/lang/qt/src/job_p.h
@@ -0,0 +1,70 @@
+/*
+ job_p.h
+
+ This file is part of qgpgme, the Qt API binding for gpgme
+ Copyright (c) 2021 g10 Code GmbH
+ Software engineering by Ingo Klöcker <dev@ingo-kloecker.de>
+
+ QGpgME is free software; you can redistribute it and/or
+ modify it under the terms of the GNU General Public License as
+ published by the Free Software Foundation; either version 2 of the
+ License, or (at your option) any later version.
+
+ QGpgME is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
+
+ In addition, as a special exception, the copyright holders give
+ permission to link the code of this program with any edition of
+ the Qt library by Trolltech AS, Norway (or with modified versions
+ of Qt that use the same license as Qt), and distribute linked
+ combinations including the two. You must obey the GNU General
+ Public License in all respects for all of the code used other than
+ Qt. If you modify this file, you may extend this exception to
+ your version of the file, but you are not obligated to do so. If
+ you do not wish to do so, delete this exception statement from
+ your version.
+*/
+
+#ifndef __QGPGME_JOB_P_H__
+#define __QGPGME_JOB_P_H__
+
+#include "job.h"
+
+#include <memory>
+
+namespace QGpgME
+{
+
+// Base class for pimpl classes for Job subclasses
+class JobPrivate
+{
+public:
+ virtual ~JobPrivate() {}
+};
+
+// Setter and getters for the externally stored pimpl instances of jobs
+// BCI: Add a real d-pointer to Job
+void setJobPrivate(const Job *job, std::unique_ptr<JobPrivate> d);
+
+JobPrivate *getJobPrivate(const Job *job);
+
+template <typename T>
+static T *jobPrivate(const Job *job) {
+ auto d = getJobPrivate(job);
+ if (!d) {
+ std::unique_ptr<T> ref{new T};
+ d = ref.get();
+ setJobPrivate(job, std::move(ref));
+ }
+ return dynamic_cast<T *>(d);
+}
+
+}
+
+#endif // __QGPGME_JOB_P_H__
diff --git a/lang/qt/src/protocol.h b/lang/qt/src/protocol.h
index 17db68a..25c71ef 100644
--- a/lang/qt/src/protocol.h
+++ b/lang/qt/src/protocol.h
@@ -40,6 +40,7 @@
#include "qgpgme_export.h"
namespace QGpgME {
+class AddExistingSubkeyJob;
class CryptoConfig;
class KeyListJob;
class ListAllKeysJob;
@@ -64,10 +65,12 @@ class ChangePasswdJob;
class AddUserIDJob;
class SpecialJob;
class KeyForMailboxJob;
+class WKDLookupJob;
class WKSPublishJob;
class TofuPolicyJob;
class QuickJob;
class GpgCardJob;
+class ReceiveKeysJob;
/** The main entry point for QGpgME Comes in OpenPGP and SMIME(CMS) flavors.
*
@@ -92,6 +95,7 @@ class GpgCardJob;
* {
* // keys and resuls can now be used.
* });
+ * job->start({QStringLiteral("alfa@example.net")}, false);
* \endcode
*
* \code
@@ -123,9 +127,11 @@ public:
virtual KeyGenerationJob *keyGenerationJob() const = 0;
virtual ImportJob *importJob() const = 0;
virtual ImportFromKeyserverJob *importFromKeyserverJob() const = 0;
+ virtual ReceiveKeysJob *receiveKeysJob() const = 0;
virtual ExportJob *publicKeyExportJob(bool armor = false) const = 0;
- // @param charset the encoding of the passphrase in the exported file
- virtual ExportJob *secretKeyExportJob(bool armor = false, const QString &charset = QString()) const = 0;
+ // the second parameter is ignored; the passphrase in the exported file is always utf-8 encoded
+ virtual ExportJob *secretKeyExportJob(bool armor = false, const QString & = QString()) const = 0;
+ virtual ExportJob *secretSubkeyExportJob(bool armor = false) const = 0;
virtual DownloadJob *downloadJob(bool armor = false) const = 0;
virtual DeleteJob *deleteJob() const = 0;
virtual SignEncryptJob *signEncryptJob(bool armor = false, bool textMode = false) const = 0;
@@ -135,6 +141,7 @@ public:
virtual SignKeyJob *signKeyJob() const = 0;
virtual ChangePasswdJob *changePasswdJob() const = 0;
virtual ChangeOwnerTrustJob *changeOwnerTrustJob() const = 0;
+ virtual AddExistingSubkeyJob *addExistingSubkeyJob() const = 0;
virtual AddUserIDJob *addUserIDJob() const = 0;
virtual SpecialJob *specialJob(const char *type, const QMap<QString, QVariant> &args) const = 0;
@@ -154,6 +161,9 @@ public:
/** Find the best key to use for a mailbox. */
virtual KeyForMailboxJob *keyForMailboxJob() const = 0;
+ /** This job looks up a key via WKD without importing it. */
+ virtual WKDLookupJob *wkdLookupJob() const = 0;
+
/** A Job for interacting with gnupg's wks tools. */
virtual WKSPublishJob *wksPublishJob() const = 0;
diff --git a/lang/qt/src/protocol_p.h b/lang/qt/src/protocol_p.h
index 57c1ed8..4211e00 100644
--- a/lang/qt/src/protocol_p.h
+++ b/lang/qt/src/protocol_p.h
@@ -5,6 +5,8 @@
Copyright (c) 2004,2005 Klarälvdalens Datakonsult AB
Copyright (c) 2016 by Bundesamt für Sicherheit in der Informationstechnik
Software engineering by Intevation GmbH
+ Copyright (c) 2022 by g10 Code GmbH
+ Software engineering by Ingo Klöcker <dev@ingo-kloecker.de>
QGpgME is free software; you can redistribute it and/or
modify it under the terms of the GNU General Public License as
@@ -42,7 +44,6 @@
#include "qgpgmedecryptverifyjob.h"
#include "qgpgmerefreshkeysjob.h"
#include "qgpgmedeletejob.h"
-#include "qgpgmesecretkeyexportjob.h"
#include "qgpgmedownloadjob.h"
#include "qgpgmesignencryptjob.h"
#include "qgpgmeencryptjob.h"
@@ -56,11 +57,14 @@
#include "qgpgmechangeexpiryjob.h"
#include "qgpgmechangeownertrustjob.h"
#include "qgpgmechangepasswdjob.h"
+#include "qgpgmeaddexistingsubkeyjob.h"
#include "qgpgmeadduseridjob.h"
#include "qgpgmekeyformailboxjob.h"
+#include "qgpgmewkdlookupjob.h"
#include "qgpgmewkspublishjob.h"
#include "qgpgmetofupolicyjob.h"
#include "qgpgmequickjob.h"
+#include "qgpgmereceivekeysjob.h"
namespace
{
@@ -230,6 +234,19 @@ public:
return new QGpgME::QGpgMEImportFromKeyserverJob(context);
}
+ QGpgME::ReceiveKeysJob *receiveKeysJob() const override
+ {
+ if (mProtocol != GpgME::OpenPGP) {
+ return nullptr;
+ }
+
+ GpgME::Context *context = GpgME::Context::createForProtocol(mProtocol);
+ if (!context) {
+ return nullptr;
+ }
+ return new QGpgME::QGpgMEReceiveKeysJob{context};
+ }
+
QGpgME::ExportJob *publicKeyExportJob(bool armor) const Q_DECL_OVERRIDE
{
GpgME::Context *context = GpgME::Context::createForProtocol(mProtocol);
@@ -241,14 +258,26 @@ public:
return new QGpgME::QGpgMEExportJob(context);
}
- QGpgME::ExportJob *secretKeyExportJob(bool armor, const QString &charset) const Q_DECL_OVERRIDE
+ QGpgME::ExportJob *secretKeyExportJob(bool armor, const QString &) const Q_DECL_OVERRIDE
{
- if (mProtocol != GpgME::CMS) { // fixme: add support for gpg, too
+ GpgME::Context *context = GpgME::Context::createForProtocol(mProtocol);
+ if (!context) {
return nullptr;
}
- // this operation is not supported by gpgme, so we have to call gpgsm ourselves:
- return new QGpgME::QGpgMESecretKeyExportJob(armor, charset);
+ context->setArmor(armor);
+ return new QGpgME::QGpgMEExportJob(context, GpgME::Context::ExportSecret);
+ }
+
+ QGpgME::ExportJob *secretSubkeyExportJob(bool armor) const Q_DECL_OVERRIDE
+ {
+ GpgME::Context *context = GpgME::Context::createForProtocol(mProtocol);
+ if (!context) {
+ return nullptr;
+ }
+
+ context->setArmor(armor);
+ return new QGpgME::QGpgMEExportJob(context, GpgME::Context::ExportSecretSubkey);
}
QGpgME::RefreshKeysJob *refreshKeysJob() const Q_DECL_OVERRIDE
@@ -357,6 +386,19 @@ public:
return new QGpgME::QGpgMEChangeOwnerTrustJob(context);
}
+ QGpgME:: AddExistingSubkeyJob *addExistingSubkeyJob() const override
+ {
+ if (mProtocol != GpgME::OpenPGP) {
+ return nullptr; // only supported by gpg
+ }
+
+ GpgME::Context *context = GpgME::Context::createForProtocol(mProtocol);
+ if (!context) {
+ return nullptr;
+ }
+ return new QGpgME::QGpgMEAddExistingSubkeyJob{context};
+ }
+
QGpgME::AddUserIDJob *addUserIDJob() const Q_DECL_OVERRIDE
{
if (mProtocol != GpgME::OpenPGP) {
@@ -392,6 +434,18 @@ public:
return new QGpgME::QGpgMEKeyForMailboxJob(context);
}
+ QGpgME::WKDLookupJob *wkdLookupJob() const Q_DECL_OVERRIDE
+ {
+ if (mProtocol != GpgME::OpenPGP) {
+ return nullptr;
+ }
+ auto context = GpgME::Context::createForEngine(GpgME::AssuanEngine);
+ if (!context) {
+ return nullptr;
+ }
+ return new QGpgME::QGpgMEWKDLookupJob(context.release());
+ }
+
QGpgME::WKSPublishJob *wksPublishJob() const Q_DECL_OVERRIDE
{
if (mProtocol != GpgME::OpenPGP) {
diff --git a/lang/qt/src/qgpgmeaddexistingsubkeyjob.cpp b/lang/qt/src/qgpgmeaddexistingsubkeyjob.cpp
new file mode 100644
index 0000000..32e2c29
--- /dev/null
+++ b/lang/qt/src/qgpgmeaddexistingsubkeyjob.cpp
@@ -0,0 +1,96 @@
+/*
+ qgpgmeaddexistingsubkeyjob.cpp
+
+ This file is part of qgpgme, the Qt API binding for gpgme
+ Copyright (c) 2022 g10 Code GmbH
+ Software engineering by Ingo Klöcker <dev@ingo-kloecker.de>
+
+ QGpgME is free software; you can redistribute it and/or
+ modify it under the terms of the GNU General Public License as
+ published by the Free Software Foundation; either version 2 of the
+ License, or (at your option) any later version.
+
+ QGpgME is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
+
+ In addition, as a special exception, the copyright holders give
+ permission to link the code of this program with any edition of
+ the Qt library by Trolltech AS, Norway (or with modified versions
+ of Qt that use the same license as Qt), and distribute linked
+ combinations including the two. You must obey the GNU General
+ Public License in all respects for all of the code used other than
+ Qt. If you modify this file, you may extend this exception to
+ your version of the file, but you are not obligated to do so. If
+ you do not wish to do so, delete this exception statement from
+ your version.
+*/
+
+#ifdef HAVE_CONFIG_H
+ #include "config.h"
+#endif
+
+#include "qgpgmeaddexistingsubkeyjob.h"
+
+#include "dataprovider.h"
+
+#include <QDateTime>
+
+#include "context.h"
+#include "data.h"
+#include "gpgaddexistingsubkeyeditinteractor.h"
+#include "key.h"
+
+#include <gpg-error.h>
+
+using namespace QGpgME;
+using namespace GpgME;
+
+QGpgMEAddExistingSubkeyJob::QGpgMEAddExistingSubkeyJob(Context *context)
+ : mixin_type{context}
+{
+ lateInitialization();
+}
+
+QGpgMEAddExistingSubkeyJob::~QGpgMEAddExistingSubkeyJob() = default;
+
+static QGpgMEAddExistingSubkeyJob::result_type add_subkey(Context *ctx, const Key &key, const Subkey &subkey)
+{
+ std::unique_ptr<GpgAddExistingSubkeyEditInteractor> interactor{new GpgAddExistingSubkeyEditInteractor{subkey.keyGrip()}};
+
+ if (!subkey.neverExpires()) {
+ const auto expiry = QDateTime::fromSecsSinceEpoch(subkey.expirationTime(), Qt::UTC).toString(u"yyyyMMdd'T'hhmmss").toStdString();
+ interactor->setExpiry(expiry);
+ }
+
+ QGpgME::QByteArrayDataProvider dp;
+ Data data(&dp);
+ assert(!data.isNull());
+
+ ctx->setFlag("extended-edit", "1");
+
+ const Error err = ctx->edit(key, std::unique_ptr<EditInteractor>(interactor.release()), data);
+ Error ae;
+ const QString log = _detail::audit_log_as_html(ctx, ae);
+ return std::make_tuple(err, log, ae);
+}
+
+Error QGpgMEAddExistingSubkeyJob::start(const GpgME::Key &key, const GpgME::Subkey &subkey)
+{
+ run(std::bind(&add_subkey, std::placeholders::_1, key, subkey));
+ return {};
+}
+
+Error QGpgMEAddExistingSubkeyJob::exec(const GpgME::Key &key, const GpgME::Subkey &subkey)
+{
+ const result_type r = add_subkey(context(), key, subkey);
+ resultHook(r);
+ return std::get<0>(r);
+}
+
+#include "qgpgmeaddexistingsubkeyjob.moc"
diff --git a/lang/qt/src/qgpgmeaddexistingsubkeyjob.h b/lang/qt/src/qgpgmeaddexistingsubkeyjob.h
new file mode 100644
index 0000000..1572755
--- /dev/null
+++ b/lang/qt/src/qgpgmeaddexistingsubkeyjob.h
@@ -0,0 +1,68 @@
+/*
+ qgpgmeaddexistingsubkeyjob.h
+
+ This file is part of qgpgme, the Qt API binding for gpgme
+ Copyright (c) 2022 g10 Code GmbH
+ Software engineering by Ingo Klöcker <dev@ingo-kloecker.de>
+
+ QGpgME is free software; you can redistribute it and/or
+ modify it under the terms of the GNU General Public License as
+ published by the Free Software Foundation; either version 2 of the
+ License, or (at your option) any later version.
+
+ QGpgME is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
+
+ In addition, as a special exception, the copyright holders give
+ permission to link the code of this program with any edition of
+ the Qt library by Trolltech AS, Norway (or with modified versions
+ of Qt that use the same license as Qt), and distribute linked
+ combinations including the two. You must obey the GNU General
+ Public License in all respects for all of the code used other than
+ Qt. If you modify this file, you may extend this exception to
+ your version of the file, but you are not obligated to do so. If
+ you do not wish to do so, delete this exception statement from
+ your version.
+*/
+
+#ifndef __QGPGME_QGPGMEADDEXISTINGSUBKEYJOB_H__
+#define __QGPGME_QGPGMEADDEXISTINGSUBKEYJOB_H__
+
+#include "threadedjobmixin.h"
+#include "addexistingsubkeyjob.h"
+
+namespace QGpgME
+{
+
+class QGpgMEAddExistingSubkeyJob
+#ifdef Q_MOC_RUN
+ : public AddExistingSubkeyJob
+#else
+ : public _detail::ThreadedJobMixin<AddExistingSubkeyJob>
+#endif
+{
+ Q_OBJECT
+#ifdef Q_MOC_RUN
+public Q_SLOTS:
+ void slotFinished();
+#endif
+public:
+ explicit QGpgMEAddExistingSubkeyJob(GpgME::Context *context);
+ ~QGpgMEAddExistingSubkeyJob();
+
+ /* from AddExistingSubkeyJob */
+ GpgME::Error start(const GpgME::Key &key, const GpgME::Subkey &subkey) override;
+
+ /* from AddExistingSubkeyJob */
+ GpgME::Error exec(const GpgME::Key &key, const GpgME::Subkey &subkey) override;
+};
+
+}
+
+#endif // __QGPGME_QGPGMEADDEXISTINGSUBKEYJOB_H__
diff --git a/lang/qt/src/qgpgmechangeexpiryjob.cpp b/lang/qt/src/qgpgmechangeexpiryjob.cpp
index 68591b7..5d4e836 100644
--- a/lang/qt/src/qgpgmechangeexpiryjob.cpp
+++ b/lang/qt/src/qgpgmechangeexpiryjob.cpp
@@ -5,6 +5,8 @@
Copyright (c) 2008 Klarälvdalens Datakonsult AB
Copyright (c) 2016 by Bundesamt für Sicherheit in der Informationstechnik
Software engineering by Intevation GmbH
+ Copyright (c) 2021 g10 Code GmbH
+ Software engineering by Ingo Klöcker <dev@ingo-kloecker.de>
QGpgME is free software; you can redistribute it and/or
modify it under the terms of the GNU General Public License as
@@ -55,14 +57,32 @@ QGpgMEChangeExpiryJob::QGpgMEChangeExpiryJob(Context *context)
QGpgMEChangeExpiryJob::~QGpgMEChangeExpiryJob() {}
static QGpgMEChangeExpiryJob::result_type change_expiry(Context *ctx, const Key &key, const QDateTime &expiry,
- const std::vector<Subkey> &subkeys)
+ const std::vector<Subkey> &subkeys, ChangeExpiryJob::Options options)
{
// convert expiry to "seconds from now"; use 1 second from now if expiry is before the current datetime
const unsigned long expires = expiry.isValid()
? std::max<qint64>(QDateTime::currentDateTime().secsTo(expiry), 1)
: 0;
- auto err = ctx->setExpire(key, expires, subkeys);
+ // updating the expiration date of the primary key and the subkeys needs to be done in two steps
+ // because --quick-set-expire does not support updating the expiration date of both at the same time
+
+ if (subkeys.empty() || (options & ChangeExpiryJob::UpdatePrimaryKey)) {
+ // update the expiration date of the primary key
+ auto err = ctx->setExpire(key, expires);
+ if (err) {
+ return std::make_tuple(err, QString(), Error());
+ }
+ }
+
+ GpgME::Error err;
+ if (!subkeys.empty()) {
+ // update the expiration date of the specified subkeys
+ err = ctx->setExpire(key, expires, subkeys);
+ } else if (options & ChangeExpiryJob::UpdateAllSubkeys) {
+ // update the expiration date of all subkeys
+ err = ctx->setExpire(key, expires, {}, Context::SetExpireAllSubkeys);
+ }
return std::make_tuple(err, QString(), Error());
}
@@ -73,13 +93,7 @@ Error QGpgMEChangeExpiryJob::start(const Key &key, const QDateTime &expiry)
Error QGpgMEChangeExpiryJob::start(const Key &key, const QDateTime &expiry, const std::vector<Subkey> &subkeys)
{
- run(std::bind(&change_expiry, std::placeholders::_1, key, expiry, subkeys));
- return Error();
-}
-
-/* For ABI compat not pure virtual. */
-Error ChangeExpiryJob::start(const Key &, const QDateTime &, const std::vector<Subkey> &)
-{
+ run(std::bind(&change_expiry, std::placeholders::_1, key, expiry, subkeys, options()));
return Error();
}
diff --git a/lang/qt/src/qgpgmechangeownertrustjob.h b/lang/qt/src/qgpgmechangeownertrustjob.h
index 80dc0e4..0f4dbe6 100644
--- a/lang/qt/src/qgpgmechangeownertrustjob.h
+++ b/lang/qt/src/qgpgmechangeownertrustjob.h
@@ -1,5 +1,5 @@
/*
- qgpgmechangeexpiryjob.h
+ qgpgmechangeownertrustjob.h
This file is part of qgpgme, the Qt API binding for gpgme
Copyright (c) 2008 Klarälvdalens Datakonsult AB
diff --git a/lang/qt/src/qgpgmeexportjob.cpp b/lang/qt/src/qgpgmeexportjob.cpp
index bf3297a..e9bc0a4 100644
--- a/lang/qt/src/qgpgmeexportjob.cpp
+++ b/lang/qt/src/qgpgmeexportjob.cpp
@@ -5,6 +5,8 @@
Copyright (c) 2004,2008 Klarälvdalens Datakonsult AB
Copyright (c) 2016 by Bundesamt für Sicherheit in der Informationstechnik
Software engineering by Intevation GmbH
+ Copyright (c) 2022 by g10 Code GmbH
+ Software engineering by Ingo Klöcker <dev@ingo-kloecker.de>
QGpgME is free software; you can redistribute it and/or
modify it under the terms of the GNU General Public License as
@@ -52,23 +54,28 @@ using namespace QGpgME;
using namespace GpgME;
QGpgMEExportJob::QGpgMEExportJob(Context *context)
- : mixin_type(context),
- m_flags(0)
+ : QGpgMEExportJob{context, 0}
+{
+}
+
+QGpgMEExportJob::QGpgMEExportJob(Context *context, unsigned int forcedMode)
+ : mixin_type{context}
+ , m_exportMode{forcedMode}
+ , m_additionalExportModeFlags{0}
{
lateInitialization();
}
-QGpgMEExportJob::~QGpgMEExportJob() {}
+QGpgMEExportJob::~QGpgMEExportJob() = default;
-static QGpgMEExportJob::result_type export_qba(Context *ctx, const QStringList &patterns, unsigned int flags)
+static QGpgMEExportJob::result_type export_qba(Context *ctx, const QStringList &patterns, unsigned int mode)
{
-
const _detail::PatternConverter pc(patterns);
QGpgME::QByteArrayDataProvider dp;
Data data(&dp);
- const Error err = ctx->exportPublicKeys(pc.patterns(), data, flags);
+ const Error err = ctx->exportKeys(pc.patterns(), data, mode);
Error ae;
const QString log = _detail::audit_log_as_html(ctx, ae);
return std::make_tuple(err, dp.data(), log, ae);
@@ -76,13 +83,14 @@ static QGpgMEExportJob::result_type export_qba(Context *ctx, const QStringList &
Error QGpgMEExportJob::start(const QStringList &patterns)
{
- run(std::bind(&export_qba, std::placeholders::_1, patterns, m_flags));
+ auto mode = m_exportMode | m_additionalExportModeFlags;
+ run(std::bind(&export_qba, std::placeholders::_1, patterns, mode));
return Error();
}
void QGpgMEExportJob::setExportFlags(unsigned int flags)
{
- m_flags = flags;
+ m_additionalExportModeFlags = flags;
}
/* For ABI compat not pure virtual. */
diff --git a/lang/qt/src/qgpgmeexportjob.h b/lang/qt/src/qgpgmeexportjob.h
index 3f6bd0e..b77bad1 100644
--- a/lang/qt/src/qgpgmeexportjob.h
+++ b/lang/qt/src/qgpgmeexportjob.h
@@ -5,6 +5,8 @@
Copyright (c) 2004,2008 Klarälvdalens Datakonsult AB
Copyright (c) 2016 by Bundesamt für Sicherheit in der Informationstechnik
Software engineering by Intevation GmbH
+ Copyright (c) 2022 by g10 Code GmbH
+ Software engineering by Ingo Klöcker <dev@ingo-kloecker.de>
QGpgME is free software; you can redistribute it and/or
modify it under the terms of the GNU General Public License as
@@ -56,15 +58,21 @@ public Q_SLOTS:
#endif
public:
explicit QGpgMEExportJob(GpgME::Context *context);
- ~QGpgMEExportJob();
+ // Creates an export job with forced export mode @p exportMode. The
+ // export mode flags set with @p exportMode cannot be overridden with
+ // setExportFlags.
+ explicit QGpgMEExportJob(GpgME::Context *context, unsigned int exportMode);
+ ~QGpgMEExportJob() Q_DECL_OVERRIDE;
/* from ExportJob */
- void setExportFlags (unsigned int flags) Q_DECL_OVERRIDE;
+ void setExportFlags(unsigned int flags) Q_DECL_OVERRIDE;
/* from ExportJob */
GpgME::Error start(const QStringList &patterns) Q_DECL_OVERRIDE;
+
private:
- unsigned int m_flags;
+ unsigned int m_exportMode;
+ unsigned int m_additionalExportModeFlags;
};
}
diff --git a/lang/qt/src/qgpgmeimportjob.cpp b/lang/qt/src/qgpgmeimportjob.cpp
index a62d05f..d609c5f 100644
--- a/lang/qt/src/qgpgmeimportjob.cpp
+++ b/lang/qt/src/qgpgmeimportjob.cpp
@@ -40,11 +40,9 @@
#include "dataprovider.h"
-#include "context.h"
-#include "data.h"
-#include "key.h"
-
-#include <cassert>
+#include <context.h>
+#include <data.h>
+#include <key.h>
using namespace QGpgME;
using namespace GpgME;
@@ -55,14 +53,60 @@ QGpgMEImportJob::QGpgMEImportJob(Context *context)
lateInitialization();
}
-QGpgMEImportJob::~QGpgMEImportJob() {}
+QGpgMEImportJob::~QGpgMEImportJob() = default;
-static QGpgMEImportJob::result_type import_qba(Context *ctx, const QByteArray &certData)
+static const char *originToString(Key::Origin origin)
{
+ static const std::map<Key::Origin, const char *> mapping = {
+ { Key::OriginUnknown, "unknown" },
+ { Key::OriginKS, "ks" },
+ { Key::OriginDane, "dane" },
+ { Key::OriginWKD, "wkd" },
+ { Key::OriginURL, "url" },
+ { Key::OriginFile, "file" },
+ { Key::OriginSelf, "self" },
+ };
+ const auto it = mapping.find(origin);
+ return (it != std::end(mapping)) ? it->second : nullptr;
+}
+
+static QGpgMEImportJob::result_type import_qba(Context *ctx, const QByteArray &certData, const QString &importFilter,
+ Key::Origin keyOrigin, const QString &keyOriginUrl)
+{
+ if (!importFilter.isEmpty()) {
+ ctx->setFlag("import-filter", importFilter.toStdString().c_str());
+ }
+ if (keyOrigin != Key::OriginUnknown) {
+ if (const auto origin = originToString(keyOrigin)) {
+ std::string value{origin};
+ if (!keyOriginUrl.isEmpty()) {
+ value += ",";
+ value += keyOriginUrl.toStdString();
+ }
+ ctx->setFlag("key-origin", value.c_str());
+ }
+ }
+
QGpgME::QByteArrayDataProvider dp(certData);
Data data(&dp);
- const ImportResult res = ctx->importKeys(data);
+ ImportResult res = ctx->importKeys(data);
+ // HACK: If the import failed with an error, then check if res.imports()
+ // contains only import statuses with "bad passphrase" error; if yes, this
+ // means that the user probably entered a wrong password to decrypt an
+ // encrypted key for import. In this case, return a result with "bad
+ // passphrase" error instead of the original error.
+ // We check if all import statuses instead of any import status has a
+ // "bad passphrase" error to avoid breaking imports that partially worked.
+ // See https://dev.gnupg.org/T5713.
+ const auto imports = res.imports();
+ if (res.error() && !imports.empty()
+ && std::all_of(std::begin(imports), std::end(imports),
+ [](const Import &import) {
+ return import.error().code() == GPG_ERR_BAD_PASSPHRASE;
+ })) {
+ res = ImportResult{Error{GPG_ERR_BAD_PASSPHRASE}};
+ }
Error ae;
const QString log = _detail::audit_log_as_html(ctx, ae);
return std::make_tuple(res, log, ae);
@@ -70,13 +114,13 @@ static QGpgMEImportJob::result_type import_qba(Context *ctx, const QByteArray &c
Error QGpgMEImportJob::start(const QByteArray &certData)
{
- run(std::bind(&import_qba, std::placeholders::_1, certData));
+ run(std::bind(&import_qba, std::placeholders::_1, certData, importFilter(), keyOrigin(), keyOriginUrl()));
return Error();
}
GpgME::ImportResult QGpgME::QGpgMEImportJob::exec(const QByteArray &keyData)
{
- const result_type r = import_qba(context(), keyData);
+ const result_type r = import_qba(context(), keyData, importFilter(), keyOrigin(), keyOriginUrl());
resultHook(r);
return mResult;
}
diff --git a/lang/qt/src/qgpgmenewcryptoconfig.cpp b/lang/qt/src/qgpgmenewcryptoconfig.cpp
index b93db76..32bf888 100644
--- a/lang/qt/src/qgpgmenewcryptoconfig.cpp
+++ b/lang/qt/src/qgpgmenewcryptoconfig.cpp
@@ -43,6 +43,7 @@
#include <QFile>
#include <QDir>
+#include <QList>
#include "global.h"
#include "error.h"
@@ -710,6 +711,57 @@ bool QGpgMENewCryptoConfigEntry::isDirty() const
return m_option.dirty();
}
+QVariant QGpgMENewCryptoConfigEntry::defaultValue() const
+{
+ const auto defaultValue = m_option.defaultValue();
+ if (defaultValue.isNull() || defaultValue.numElements() == 0) {
+ return {};
+ }
+ if (defaultValue.numElements() == 1) {
+ switch (m_option.alternateType()) {
+ case NoType:
+ return QVariant{defaultValue.boolValue()};
+ case StringType:
+ return QVariant{QString::fromUtf8(defaultValue.stringValue())};
+ case IntegerType:
+ return QVariant{defaultValue.intValue()};
+ case UnsignedIntegerType:
+ return QVariant{defaultValue.uintValue()};
+ default:
+ // alternateType should always be one of the above four types
+ qCWarning(QGPGME_LOG) << __func__ << ": unsupported alternateType" << m_option.alternateType();
+ }
+ } else {
+ QList<QVariant> list;
+ switch (m_option.alternateType()) {
+ case StringType: {
+ const auto values = defaultValue.stringValues();
+ std::transform(std::begin(values), std::end(values), std::back_inserter(list),
+ [] (const char *value) { return QVariant{QString::fromUtf8(value)}; });
+ break;
+ }
+ case IntegerType: {
+ const auto values = defaultValue.intValues();
+ std::transform(std::begin(values), std::end(values), std::back_inserter(list),
+ [] (int value) { return QVariant{value}; });
+ break;
+ }
+ case UnsignedIntegerType: {
+ const auto values = defaultValue.uintValues();
+ std::transform(std::begin(values), std::end(values), std::back_inserter(list),
+ [] (unsigned int value) { return QVariant{value}; });
+ break;
+ }
+ default:
+ // alternateType should always be one of the above four types
+ qCWarning(QGPGME_LOG) << __func__ << ": unsupported alternateType" << m_option.alternateType() << "for list";
+ }
+ return QVariant{list};
+ }
+
+ return {};
+}
+
#if 0
QString QGpgMENewCryptoConfigEntry::toString(bool escape) const
{
diff --git a/lang/qt/src/qgpgmenewcryptoconfig.h b/lang/qt/src/qgpgmenewcryptoconfig.h
index eade8eb..15579fd 100644
--- a/lang/qt/src/qgpgmenewcryptoconfig.h
+++ b/lang/qt/src/qgpgmenewcryptoconfig.h
@@ -95,6 +95,7 @@ public:
bool isDirty() const Q_DECL_OVERRIDE;
QStringList stringValueList() const;
+ QVariant defaultValue() const;
#if 0
void setDirty(bool b);
diff --git a/lang/qt/src/qgpgmereceivekeysjob.cpp b/lang/qt/src/qgpgmereceivekeysjob.cpp
new file mode 100644
index 0000000..bedf7a2
--- /dev/null
+++ b/lang/qt/src/qgpgmereceivekeysjob.cpp
@@ -0,0 +1,79 @@
+/*
+ qgpgmereceivekeysjob.cpp
+
+ This file is part of qgpgme, the Qt API binding for gpgme
+ Copyright (c) 2022 g10 Code GmbH
+ Software engineering by Ingo Klöcker <dev@ingo-kloecker.de>
+
+ QGpgME is free software; you can redistribute it and/or
+ modify it under the terms of the GNU General Public License as
+ published by the Free Software Foundation; either version 2 of the
+ License, or (at your option) any later version.
+
+ QGpgME is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
+
+ In addition, as a special exception, the copyright holders give
+ permission to link the code of this program with any edition of
+ the Qt library by Trolltech AS, Norway (or with modified versions
+ of Qt that use the same license as Qt), and distribute linked
+ combinations including the two. You must obey the GNU General
+ Public License in all respects for all of the code used other than
+ Qt. If you modify this file, you may extend this exception to
+ your version of the file, but you are not obligated to do so. If
+ you do not wish to do so, delete this exception statement from
+ your version.
+*/
+
+#ifdef HAVE_CONFIG_H
+# include "config.h"
+#endif
+
+#include "qgpgmereceivekeysjob.h"
+
+#include "util.h"
+
+using namespace QGpgME;
+using namespace GpgME;
+
+QGpgMEReceiveKeysJob::QGpgMEReceiveKeysJob(Context *context)
+ : mixin_type{context}
+{
+ lateInitialization();
+}
+
+QGpgMEReceiveKeysJob::~QGpgMEReceiveKeysJob() = default;
+
+static QGpgMEReceiveKeysJob::result_type importfromkeyserver(Context *ctx, const QStringList &keyIds)
+{
+ const ImportResult res = ctx->importKeys(toStrings(keyIds));
+ Error ae;
+ const QString log = _detail::audit_log_as_html(ctx, ae);
+ return std::make_tuple(res, log, ae);
+}
+
+Error QGpgMEReceiveKeysJob::start(const QStringList &keyIds)
+{
+ run(std::bind(&importfromkeyserver, std::placeholders::_1, keyIds));
+ return Error();
+}
+
+GpgME::ImportResult QGpgME::QGpgMEReceiveKeysJob::exec(const QStringList &keyIds)
+{
+ const result_type r = importfromkeyserver(context(), keyIds);
+ resultHook(r);
+ return mResult;
+}
+
+void QGpgME::QGpgMEReceiveKeysJob::resultHook(const result_type &tuple)
+{
+ mResult = std::get<0>(tuple);
+}
+
+#include "qgpgmereceivekeysjob.moc"
diff --git a/lang/qt/src/qgpgmesecretkeyexportjob.h b/lang/qt/src/qgpgmereceivekeysjob.h
index 78e4d77..96628df 100644
--- a/lang/qt/src/qgpgmesecretkeyexportjob.h
+++ b/lang/qt/src/qgpgmereceivekeysjob.h
@@ -1,10 +1,9 @@
/*
- qgpgmesecretkeyexportjob.h
+ qgpgmereceivekeysjob.h
This file is part of qgpgme, the Qt API binding for gpgme
- Copyright (c) 2004 Klarälvdalens Datakonsult AB
- Copyright (c) 2016 by Bundesamt für Sicherheit in der Informationstechnik
- Software engineering by Intevation GmbH
+ Copyright (c) 2022 g10 Code GmbH
+ Software engineering by Ingo Klöcker <dev@ingo-kloecker.de>
QGpgME is free software; you can redistribute it and/or
modify it under the terms of the GNU General Public License as
@@ -32,51 +31,49 @@
your version.
*/
-#ifndef __QGPGME_QGPGMESECRETKEYEXPORTJOB_H__
-#define __QGPGME_QGPGMESECRETKEYEXPORTJOB_H__
+#ifndef __QGPGME_QGPGMERECEIVEKEYSJOB_H__
+#define __QGPGME_QGPGMERECEIVEKEYSJOB_H__
+
+#include "receivekeysjob.h"
+
+#include "threadedjobmixin.h"
-#include "exportjob.h"
#ifdef BUILDING_QGPGME
-# include "context.h"
+# include "importresult.h"
#else
-#include "gpgme++/context.h"
+# include <gpgme++/importresult.h>
#endif
-#include <QProcess>
-
-namespace GpgME
-{
-class Data;
-}
namespace QGpgME
{
-class QGpgMESecretKeyExportJob : public ExportJob
+class QGpgMEReceiveKeysJob
+#ifdef Q_MOC_RUN
+ : public ReceiveKeysJob
+#else
+ : public _detail::ThreadedJobMixin<ReceiveKeysJob, std::tuple<GpgME::ImportResult, QString, GpgME::Error>>
+#endif
{
Q_OBJECT
+#ifdef Q_MOC_RUN
+public Q_SLOTS:
+ void slotFinished();
+#endif
public:
- QGpgMESecretKeyExportJob(bool armour, const QString &charset);
- ~QGpgMESecretKeyExportJob();
+ explicit QGpgMEReceiveKeysJob(GpgME::Context *context);
+ ~QGpgMEReceiveKeysJob() override;
- /* from ExportJob */
- GpgME::Error start(const QStringList &patterns) Q_DECL_OVERRIDE;
+ GpgME::Error start(const QStringList &keyIds) override;
-private Q_SLOTS:
- /* from Job */
- void slotCancel() Q_DECL_OVERRIDE;
+ GpgME::ImportResult exec(const QStringList &keyIds) override;
- void slotStdout();
- void slotStderr();
- void slotProcessExited(int exitCode, QProcess::ExitStatus exitStatus);
+ /* from ThreadedJobMixin */
+ void resultHook(const result_type &r) override;
private:
- QProcess *mProcess;
- QByteArray mKeyData;
- GpgME::Error mError;
- bool mArmour;
- QString mCharset;
+ GpgME::ImportResult mResult;
};
}
-#endif // __QGPGME_QGPGMESECRETKEYEXPORTJOB_H__
+#endif // __QGPGME_QGPGMERECEIVEKEYSJOB_H__
diff --git a/lang/qt/src/qgpgmesecretkeyexportjob.cpp b/lang/qt/src/qgpgmesecretkeyexportjob.cpp
deleted file mode 100644
index d472bc4..0000000
--- a/lang/qt/src/qgpgmesecretkeyexportjob.cpp
+++ /dev/null
@@ -1,147 +0,0 @@
-/*
- qgpgmesecretexportjob.cpp
-
- This file is part of qgpgme, the Qt API binding for gpgme
- Copyright (c) 2004 Klarävdalens Datakonsult AB
- Copyright (c) 2016 by Bundesamt für Sicherheit in der Informationstechnik
- Software engineering by Intevation GmbH
-
- QGpgME is free software; you can redistribute it and/or
- modify it under the terms of the GNU General Public License as
- published by the Free Software Foundation; either version 2 of the
- License, or (at your option) any later version.
-
- QGpgME is distributed in the hope that it will be useful,
- but WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- General Public License for more details.
-
- You should have received a copy of the GNU General Public License
- along with this program; if not, write to the Free Software
- Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
-
- In addition, as a special exception, the copyright holders give
- permission to link the code of this program with any edition of
- the Qt library by Trolltech AS, Norway (or with modified versions
- of Qt that use the same license as Qt), and distribute linked
- combinations including the two. You must obey the GNU General
- Public License in all respects for all of the code used other than
- Qt. If you modify this file, you may extend this exception to
- your version of the file, but you are not obligated to do so. If
- you do not wish to do so, delete this exception statement from
- your version.
-*/
-
-#ifdef HAVE_CONFIG_H
- #include "config.h"
-#endif
-
-#include "qgpgmesecretkeyexportjob.h"
-
-#include <QDebug>
-#include "qgpgme_debug.h"
-
-#include "context.h"
-#include "data.h"
-
-#include <QStringList>
-
-#include <gpg-error.h>
-
-#include <string.h>
-#include <assert.h>
-
-QGpgME::QGpgMESecretKeyExportJob::QGpgMESecretKeyExportJob(bool armour, const QString &charset)
- : ExportJob(nullptr),
- mProcess(nullptr),
- mError(0),
- mArmour(armour),
- mCharset(charset)
-{
-
-}
-
-QGpgME::QGpgMESecretKeyExportJob::~QGpgMESecretKeyExportJob()
-{
-
-}
-
-GpgME::Error QGpgME::QGpgMESecretKeyExportJob::start(const QStringList &patterns)
-{
- assert(mKeyData.isEmpty());
-
- if (patterns.size() != 1 || patterns.front().isEmpty()) {
- deleteLater();
- return mError = GpgME::Error::fromCode(GPG_ERR_INV_VALUE, GPG_ERR_SOURCE_GPGSM);
- }
-
- // create and start gpgsm process:
- mProcess = new QProcess(this);
- mProcess->setObjectName(QStringLiteral("gpgsm --export-secret-key-p12"));
-
- // FIXME: obtain the path to gpgsm from gpgme, so we use the same instance.
- mProcess->setProgram("gpgsm");
- QStringList arguments;
- arguments << QStringLiteral("--export-secret-key-p12");
- if (mArmour) {
- arguments << QStringLiteral("--armor");
- }
- if (!mCharset.isEmpty()) {
- arguments << QStringLiteral("--p12-charset") << mCharset;
- }
- arguments << QLatin1String(patterns.front().toUtf8());
-
- mProcess->setArguments(arguments);
- connect(mProcess, SIGNAL(finished(int,QProcess::ExitStatus)),
- SLOT(slotProcessExited(int,QProcess::ExitStatus)));
- connect(mProcess, &QProcess::readyReadStandardOutput,
- this, &QGpgMESecretKeyExportJob::slotStdout);
- connect(mProcess, &QProcess::readyReadStandardError,
- this, &QGpgMESecretKeyExportJob::slotStderr);
-
- mProcess->start();
- if (!mProcess->waitForStarted()) {
- mError = GpgME::Error::fromCode(GPG_ERR_ENOENT, GPG_ERR_SOURCE_GPGSM); // what else?
- deleteLater();
- return mError;
- } else {
- return GpgME::Error();
- }
-}
-
-void QGpgME::QGpgMESecretKeyExportJob::slotCancel()
-{
- if (mProcess) {
- mProcess->kill();
- }
- mProcess = nullptr;
- mError = GpgME::Error::fromCode(GPG_ERR_CANCELED, GPG_ERR_SOURCE_GPGSM);
-}
-
-void QGpgME::QGpgMESecretKeyExportJob::slotStdout()
-{
- QString line = QString::fromLocal8Bit(mProcess->readLine());
- if (!line.isEmpty()) {
- return;
- }
- const unsigned int oldlen = mKeyData.size();
- mKeyData.resize(oldlen + line.length());
- memcpy(mKeyData.data() + oldlen, line.toLatin1(), line.length());
-}
-
-void QGpgME::QGpgMESecretKeyExportJob::slotStderr()
-{
- // implement? or not?
-}
-
-void QGpgME::QGpgMESecretKeyExportJob::slotProcessExited(int exitCode, QProcess::ExitStatus exitStatus)
-{
- Q_EMIT done();
- if (!mError &&
- (exitStatus != QProcess::NormalExit || exitCode != 0)) {
- mError = GpgME::Error::fromCode(GPG_ERR_GENERAL, GPG_ERR_SOURCE_GPGSM);
- }
- Q_EMIT result(mError, mKeyData);
- deleteLater();
-}
-#include "qgpgmesecretkeyexportjob.moc"
diff --git a/lang/qt/src/qgpgmewkdlookupjob.cpp b/lang/qt/src/qgpgmewkdlookupjob.cpp
new file mode 100644
index 0000000..266da0d
--- /dev/null
+++ b/lang/qt/src/qgpgmewkdlookupjob.cpp
@@ -0,0 +1,183 @@
+/*
+ qgpgmewkdlookupjob.cpp
+
+ This file is part of qgpgme, the Qt API binding for gpgme
+ Copyright (c) 2021 g10 Code GmbH
+ Software engineering by Ingo Klöcker <dev@ingo-kloecker.de>
+
+ QGpgME is free software; you can redistribute it and/or
+ modify it under the terms of the GNU General Public License as
+ published by the Free Software Foundation; either version 2 of the
+ License, or (at your option) any later version.
+
+ QGpgME is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
+
+ In addition, as a special exception, the copyright holders give
+ permission to link the code of this program with any edition of
+ the Qt library by Trolltech AS, Norway (or with modified versions
+ of Qt that use the same license as Qt), and distribute linked
+ combinations including the two. You must obey the GNU General
+ Public License in all respects for all of the code used other than
+ Qt. If you modify this file, you may extend this exception to
+ your version of the file, but you are not obligated to do so. If
+ you do not wish to do so, delete this exception statement from
+ your version.
+*/
+
+#ifdef HAVE_CONFIG_H
+ #include "config.h"
+#endif
+
+#include "qgpgmewkdlookupjob.h"
+
+#include "qgpgme_debug.h"
+
+#include <context.h>
+#include <data.h>
+#include <defaultassuantransaction.h>
+
+#include <gpg-error.h>
+
+using namespace QGpgME;
+using namespace GpgME;
+
+QGpgMEWKDLookupJob::QGpgMEWKDLookupJob(Context *context)
+ : mixin_type{context}
+{
+ lateInitialization();
+}
+
+QGpgMEWKDLookupJob::~QGpgMEWKDLookupJob() = default;
+
+static GpgME::Error startDirmngr(Context *assuanCtx)
+{
+ Error err;
+
+ auto spawnCtx = std::unique_ptr<Context>{Context::createForEngine(SpawnEngine, &err)};
+ if (err) {
+ qCDebug(QGPGME_LOG) << "Error: Failed to get context for spawn engine (" << err.asString() << ")";
+ }
+
+ const auto dirmngrProgram = GpgME::dirInfo("dirmngr-name");
+ const auto homedir = GpgME::dirInfo("homedir");
+ const char *argv[] = {
+ dirmngrProgram,
+ "--homedir",
+ homedir,
+ "--daemon",
+ NULL
+ };
+ auto ignoreIO = Data{Data::null};
+ if (!err) {
+ qCDebug(QGPGME_LOG) << "Starting dirmngr ...";
+ err = spawnCtx->spawnAsync(dirmngrProgram, argv,
+ ignoreIO, ignoreIO, ignoreIO,
+ Context::SpawnDetached);
+ }
+
+ if (!err) {
+ // wait for socket to become available
+ int cnt = 0;
+ do {
+ ++cnt;
+ qCDebug(QGPGME_LOG) << "Waiting for dirmngr to start ...";
+ QThread::msleep(250 * cnt);
+ err = assuanCtx->assuanTransact("GETINFO version");
+ } while (err.code() == GPG_ERR_ASS_CONNECT_FAILED && cnt < 5);
+ }
+
+ return err;
+}
+
+static GpgME::Error setUpDirmngrAssuanConnection(Context *ctx)
+{
+ Error err;
+
+ const std::string dirmngrSocket = GpgME::dirInfo("dirmngr-socket");
+ err = ctx->setEngineFileName(dirmngrSocket.c_str());
+
+ if (!err) {
+ err = ctx->setEngineHomeDirectory("");
+ }
+
+ if (!err) {
+ // try do connect to dirmngr
+ err = ctx->assuanTransact("GETINFO version");
+ if (err.code() == GPG_ERR_ASS_CONNECT_FAILED) {
+ err = startDirmngr(ctx);
+ }
+ }
+
+ return err;
+}
+
+static GpgME::Error run_wkd_get(Context *ctx, const std::string &email)
+{
+ Error err;
+
+ const auto cmd = std::string{"WKD_GET "} + email;
+ err = ctx->assuanTransact(cmd.c_str());
+ if (err.code() == GPG_ERR_NO_NAME || err.code() == GPG_ERR_NO_DATA) {
+ // ignore those benign errors; GPG_ERR_NO_NAME indicates that the domain
+ // doesn't exist (on first request); GPG_ERR_NO_DATA indicates that
+ // no key for email is available via WKD or that the domain doesn't
+ // support WKD or that the domain doesn't exist (on subsequent requests
+ // using dirmngr's internal cache)
+ qCDebug(QGPGME_LOG) << "WKD_GET returned" << err.asString() << "; ignoring...";
+ err = {};
+ }
+ if (err) {
+ qCDebug(QGPGME_LOG) << "WKD_GET failed with" << err.asString();
+ }
+
+ return err;
+}
+
+static QGpgMEWKDLookupJob::result_type lookup_keys(Context *ctx, const QString &email)
+{
+ WKDLookupResult result;
+
+ Error err = setUpDirmngrAssuanConnection(ctx);
+
+ const auto pattern = email.toUtf8().toStdString();
+ if (!err) {
+ err = run_wkd_get(ctx, pattern);
+ }
+
+ if (!err) {
+ const auto transaction = std::unique_ptr<DefaultAssuanTransaction>(dynamic_cast<DefaultAssuanTransaction*>(ctx->takeLastAssuanTransaction().release()));
+ const auto source = transaction->firstStatusLine("SOURCE");
+ const auto rawData = transaction->data();
+ if (rawData.size() == 0) {
+ qCDebug(QGPGME_LOG) << "No key found for" << email;
+ result = WKDLookupResult{pattern, GpgME::Data::null, {}, {}};
+ } else {
+ qCDebug(QGPGME_LOG) << "Found key for" << email << "at" << source.c_str();
+ result = WKDLookupResult{pattern, GpgME::Data{rawData.c_str(), rawData.size()}, source, {}};
+ }
+ }
+
+ return std::make_tuple(err ? WKDLookupResult{pattern, err} : result, QString{}, Error{});
+}
+
+Error QGpgMEWKDLookupJob::start(const QString &email)
+{
+ run(std::bind(&lookup_keys, std::placeholders::_1, email));
+ return Error();
+}
+
+WKDLookupResult QGpgMEWKDLookupJob::exec(const QString &email)
+{
+ const result_type r = lookup_keys(context(), email);
+ resultHook(r);
+ return std::get<0>(r);
+}
+
+#include "qgpgmewkdlookupjob.moc"
diff --git a/lang/qt/src/qgpgmewkdlookupjob.h b/lang/qt/src/qgpgmewkdlookupjob.h
new file mode 100644
index 0000000..61f9465
--- /dev/null
+++ b/lang/qt/src/qgpgmewkdlookupjob.h
@@ -0,0 +1,70 @@
+/*
+ qgpgmewkdlookupjob.h
+
+ This file is part of qgpgme, the Qt API binding for gpgme
+ Copyright (c) 2021 g10 Code GmbH
+ Software engineering by Ingo Klöcker <dev@ingo-kloecker.de>
+
+ QGpgME is free software; you can redistribute it and/or
+ modify it under the terms of the GNU General Public License as
+ published by the Free Software Foundation; either version 2 of the
+ License, or (at your option) any later version.
+
+ QGpgME is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
+
+ In addition, as a special exception, the copyright holders give
+ permission to link the code of this program with any edition of
+ the Qt library by Trolltech AS, Norway (or with modified versions
+ of Qt that use the same license as Qt), and distribute linked
+ combinations including the two. You must obey the GNU General
+ Public License in all respects for all of the code used other than
+ Qt. If you modify this file, you may extend this exception to
+ your version of the file, but you are not obligated to do so. If
+ you do not wish to do so, delete this exception statement from
+ your version.
+*/
+
+#ifndef __QGPGME_QGPGMEWKDLOOKUPJOB_H__
+#define __QGPGME_QGPGMEWKDLOOKUPJOB_H__
+
+#include "threadedjobmixin.h"
+#include "wkdlookupjob.h"
+#include "wkdlookupresult.h"
+
+namespace QGpgME
+{
+class WKDLookupResult;
+
+class QGpgMEWKDLookupJob
+#ifdef Q_MOC_RUN
+ : public WKDLookupJob
+#else
+ : public _detail::ThreadedJobMixin<WKDLookupJob, std::tuple<WKDLookupResult, QString, GpgME::Error> >
+#endif
+{
+ Q_OBJECT
+#ifdef Q_MOC_RUN
+public Q_SLOTS:
+ void slotFinished();
+#endif
+public:
+ explicit QGpgMEWKDLookupJob(GpgME::Context *context);
+ ~QGpgMEWKDLookupJob();
+
+ /* from WKDLookupJob */
+ GpgME::Error start(const QString &email) Q_DECL_OVERRIDE;
+
+ /* from WKDLookupJob */
+ WKDLookupResult exec(const QString &email) Q_DECL_OVERRIDE;
+};
+
+}
+
+#endif // __QGPGME_QGPGMEWKDLOOKUPJOB_H__
diff --git a/lang/qt/src/receivekeysjob.h b/lang/qt/src/receivekeysjob.h
new file mode 100644
index 0000000..3f85792
--- /dev/null
+++ b/lang/qt/src/receivekeysjob.h
@@ -0,0 +1,66 @@
+/*
+ receivekeysjob.h
+
+ This file is part of qgpgme, the Qt API binding for gpgme
+ Copyright (c) 2022 g10 Code GmbH
+ Software engineering by Ingo Klöcker <dev@ingo-kloecker.de>
+
+ QGpgME is free software; you can redistribute it and/or
+ modify it under the terms of the GNU General Public License as
+ published by the Free Software Foundation; either version 2 of the
+ License, or (at your option) any later version.
+
+ QGpgME is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
+
+ In addition, as a special exception, the copyright holders give
+ permission to link the code of this program with any edition of
+ the Qt library by Trolltech AS, Norway (or with modified versions
+ of Qt that use the same license as Qt), and distribute linked
+ combinations including the two. You must obey the GNU General
+ Public License in all respects for all of the code used other than
+ Qt. If you modify this file, you may extend this exception to
+ your version of the file, but you are not obligated to do so. If
+ you do not wish to do so, delete this exception statement from
+ your version.
+*/
+
+#ifndef __QGPGME_RECEIVEKEYSJOB_H__
+#define __QGPGME_RECEIVEKEYSJOB_H__
+
+#include "abstractimportjob.h"
+#include "qgpgme_export.h"
+
+namespace QGpgME
+{
+
+class QGPGME_EXPORT ReceiveKeysJob : public AbstractImportJob
+{
+ Q_OBJECT
+protected:
+ explicit ReceiveKeysJob(QObject *parent);
+public:
+ ~ReceiveKeysJob() override;
+
+ /**
+ Starts the import of keys from a keyserver. \a keyIds is a list of
+ key ids and/or fingerprints specifying the keys to import.
+ */
+ virtual GpgME::Error start(const QStringList &keyIds) = 0;
+
+ /**
+ Runs the import of keys from a keyserver. \a keyIds is a list of
+ key ids and/or fingerprints specifying the keys to import.
+ */
+ virtual GpgME::ImportResult exec(const QStringList &keyIds) = 0;
+};
+
+}
+
+#endif // __QGPGME_RECEIVEKEYSJOB_H__
diff --git a/lang/qt/src/signkeyjob.h b/lang/qt/src/signkeyjob.h
index 666af92..f4b3ed8 100644
--- a/lang/qt/src/signkeyjob.h
+++ b/lang/qt/src/signkeyjob.h
@@ -117,14 +117,14 @@ public:
*
* Not pure virtual for ABI compatibility.
**/
- virtual void setDupeOk(bool) {};
+ virtual void setDupeOk(bool) {}
/**
* Add a remark to the signature. This uses rem@gnupg.org as a notation.
*
* Not pure virtual for ABI compatibility.
**/
- virtual void setRemark(const QString &) {};
+ virtual void setRemark(const QString &) {}
/**
* If set, then the created signature will be a trust signature. By default,
@@ -143,7 +143,7 @@ public:
*
* Not pure virtual for ABI compatibility.
**/
- virtual void setTrustSignature(GpgME::TrustSignatureTrust trust, unsigned short depth, const QString &scope) { Q_UNUSED(trust); Q_UNUSED(depth); Q_UNUSED(scope); };
+ virtual void setTrustSignature(GpgME::TrustSignatureTrust trust, unsigned short depth, const QString &scope) { Q_UNUSED(trust); Q_UNUSED(depth); Q_UNUSED(scope); }
/**
* Sets the expiration date of the key signature to @a expiration. By default,
diff --git a/lang/qt/src/threadedjobmixin.cpp b/lang/qt/src/threadedjobmixin.cpp
index 3302918..92e6384 100644
--- a/lang/qt/src/threadedjobmixin.cpp
+++ b/lang/qt/src/threadedjobmixin.cpp
@@ -53,53 +53,10 @@
using namespace QGpgME;
using namespace GpgME;
-#ifdef Q_OS_WIN
-#include <windows.h>
-
-static QString fromEncoding (unsigned int src_encoding, const char *data)
-{
- int n = MultiByteToWideChar(src_encoding, 0, data, -1, NULL, 0);
- if (n < 0) {
- return QString();
- }
-
- wchar_t *result = (wchar_t *) malloc ((n+1) * sizeof *result);
-
- n = MultiByteToWideChar(src_encoding, 0, data, -1, result, n);
- if (n < 0) {
- free(result);
- return QString();
- }
- const auto ret = QString::fromWCharArray(result, n);
- free(result);
- return ret;
-}
-#endif
-
static QString stringFromGpgOutput(const QByteArray &ba)
{
#ifdef Q_OS_WIN
- /* Qt on Windows uses GetACP while GnuPG prefers
- * GetConsoleOutputCP.
- *
- * As we are not a console application GetConsoleOutputCP
- * usually returns 0.
- * From experience the closest thing that let's us guess
- * what GetConsoleOutputCP returns for a console application
- * it appears to be the OEMCP.
- */
- unsigned int cpno = GetConsoleOutputCP ();
- if (!cpno) {
- cpno = GetOEMCP();
- }
- if (!cpno) {
- cpno = GetACP();
- }
- if (!cpno) {
- return QString();
- }
-
- return fromEncoding(cpno, ba.constData());
+ return QString::fromUtf8(ba);
#else
return QString::fromLocal8Bit(ba);
#endif
diff --git a/lang/qt/src/util.cpp b/lang/qt/src/util.cpp
new file mode 100644
index 0000000..3d10e2f
--- /dev/null
+++ b/lang/qt/src/util.cpp
@@ -0,0 +1,47 @@
+/*
+ util.cpp
+
+ This file is part of qgpgme, the Qt API binding for gpgme
+ Copyright (c) 2022 g10 Code GmbH
+ Software engineering by Ingo Klöcker <dev@ingo-kloecker.de>
+
+ QGpgME is free software; you can redistribute it and/or
+ modify it under the terms of the GNU General Public License as
+ published by the Free Software Foundation; either version 2 of the
+ License, or (at your option) any later version.
+
+ QGpgME is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
+
+ In addition, as a special exception, the copyright holders give
+ permission to link the code of this program with any edition of
+ the Qt library by Trolltech AS, Norway (or with modified versions
+ of Qt that use the same license as Qt), and distribute linked
+ combinations including the two. You must obey the GNU General
+ Public License in all respects for all of the code used other than
+ Qt. If you modify this file, you may extend this exception to
+ your version of the file, but you are not obligated to do so. If
+ you do not wish to do so, delete this exception statement from
+ your version.
+*/
+
+#include "util.h"
+
+#include <QStringList>
+#include <functional>
+
+std::vector<std::string> toStrings(const QStringList &l)
+{
+ std::vector<std::string> v;
+ v.reserve(l.size());
+ std::transform(std::begin(l), std::end(l),
+ std::back_inserter(v),
+ std::mem_fn(&QString::toStdString));
+ return v;
+}
diff --git a/lang/qt/src/util.h b/lang/qt/src/util.h
new file mode 100644
index 0000000..94c9733
--- /dev/null
+++ b/lang/qt/src/util.h
@@ -0,0 +1,51 @@
+/*
+ util.h - some internal helpers
+
+ This file is part of qgpgme, the Qt API binding for gpgme
+ Copyright (c) 2022 g10 Code GmbH
+ Software engineering by Ingo Klöcker <dev@ingo-kloecker.de>
+
+ QGpgME is free software; you can redistribute it and/or
+ modify it under the terms of the GNU General Public License as
+ published by the Free Software Foundation; either version 2 of the
+ License, or (at your option) any later version.
+
+ QGpgME is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
+
+ In addition, as a special exception, the copyright holders give
+ permission to link the code of this program with any edition of
+ the Qt library by Trolltech AS, Norway (or with modified versions
+ of Qt that use the same license as Qt), and distribute linked
+ combinations including the two. You must obey the GNU General
+ Public License in all respects for all of the code used other than
+ Qt. If you modify this file, you may extend this exception to
+ your version of the file, but you are not obligated to do so. If
+ you do not wish to do so, delete this exception statement from
+ your version.
+*/
+
+#ifndef __QGPGME_UTIL_H__
+#define __QGPGME_UTIL_H__
+
+#include <gpgme.h>
+
+#include <string>
+#include <vector>
+
+class QStringList;
+
+static inline gpgme_error_t make_error(gpgme_err_code_t code)
+{
+ return gpgme_err_make((gpgme_err_source_t)22, code);
+}
+
+std::vector<std::string> toStrings(const QStringList &l);
+
+#endif // __QGPGME_UTIL_H__
diff --git a/lang/qt/src/wkdlookupjob.h b/lang/qt/src/wkdlookupjob.h
new file mode 100644
index 0000000..ae22874
--- /dev/null
+++ b/lang/qt/src/wkdlookupjob.h
@@ -0,0 +1,78 @@
+/*
+ wkdlookupjob.h
+
+ This file is part of qgpgme, the Qt API binding for gpgme
+ Copyright (c) 2021 g10 Code GmbH
+ Software engineering by Ingo Klöcker <dev@ingo-kloecker.de>
+
+ QGpgME is free software; you can redistribute it and/or
+ modify it under the terms of the GNU General Public License as
+ published by the Free Software Foundation; either version 2 of the
+ License, or (at your option) any later version.
+
+ QGpgME is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
+
+ In addition, as a special exception, the copyright holders give
+ permission to link the code of this program with any edition of
+ the Qt library by Trolltech AS, Norway (or with modified versions
+ of Qt that use the same license as Qt), and distribute linked
+ combinations including the two. You must obey the GNU General
+ Public License in all respects for all of the code used other than
+ Qt. If you modify this file, you may extend this exception to
+ your version of the file, but you are not obligated to do so. If
+ you do not wish to do so, delete this exception statement from
+ your version.
+*/
+
+#ifndef __QGPGME_WKDLOOKUPJOB_H__
+#define __QGPGME_WKDLOOKUPJOB_H__
+
+#include "job.h"
+#include "qgpgme_export.h"
+
+class QString;
+
+namespace GpgME
+{
+class Data;
+class Error;
+}
+
+namespace QGpgME
+{
+
+class WKDLookupResult;
+
+class QGPGME_EXPORT WKDLookupJob : public Job
+{
+ Q_OBJECT
+protected:
+ explicit WKDLookupJob(QObject *parent);
+
+public:
+ ~WKDLookupJob();
+
+ /**
+ Starts a key lookup operation for the email address \a email via WKD.
+ */
+ virtual GpgME::Error start(const QString &email) = 0;
+
+ /**
+ Runs a key lookup operation for the email address \a email via WKD.
+ */
+ virtual WKDLookupResult exec(const QString &email) = 0;
+
+Q_SIGNALS:
+ void result(const WKDLookupResult &result, const QString &auditLogAsHtml = {}, const GpgME::Error &auditLogError = {});
+};
+
+}
+
+#endif // __QGPGME_WKDLOOKUPJOB_H__
diff --git a/lang/qt/src/wkdlookupresult.cpp b/lang/qt/src/wkdlookupresult.cpp
new file mode 100644
index 0000000..c44b737
--- /dev/null
+++ b/lang/qt/src/wkdlookupresult.cpp
@@ -0,0 +1,117 @@
+/*
+ wkdlookupresult.cpp - wraps the result of a WKDLookupJob
+
+ This file is part of qgpgme, the Qt API binding for gpgme
+ Copyright (c) 2021 g10 Code GmbH
+ Software engineering by Ingo Klöcker <dev@ingo-kloecker.de>
+
+ QGpgME is free software; you can redistribute it and/or
+ modify it under the terms of the GNU General Public License as
+ published by the Free Software Foundation; either version 2 of the
+ License, or (at your option) any later version.
+
+ QGpgME is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
+
+ In addition, as a special exception, the copyright holders give
+ permission to link the code of this program with any edition of
+ the Qt library by Trolltech AS, Norway (or with modified versions
+ of Qt that use the same license as Qt), and distribute linked
+ combinations including the two. You must obey the GNU General
+ Public License in all respects for all of the code used other than
+ Qt. If you modify this file, you may extend this exception to
+ your version of the file, but you are not obligated to do so. If
+ you do not wish to do so, delete this exception statement from
+ your version.
+*/
+
+#ifdef HAVE_CONFIG_H
+ #include "config.h"
+#endif
+
+#include "wkdlookupresult.h"
+
+#include <data.h>
+
+using namespace QGpgME;
+using namespace GpgME;
+
+class WKDLookupResult::Private
+{
+public:
+ std::string pattern;
+ GpgME::Data keyData;
+ std::string source;
+};
+
+WKDLookupResult::WKDLookupResult() = default;
+
+WKDLookupResult::~WKDLookupResult() = default;
+
+WKDLookupResult::WKDLookupResult(const std::string &pattern, const Error &error)
+ : Result{error}
+ , d{new Private{pattern, {}, {}}}
+{
+}
+
+WKDLookupResult::WKDLookupResult(const std::string &pattern, const Data &keyData, const std::string &source, const Error &error)
+ : Result{error}
+ , d{new Private{pattern, keyData, source}}
+{
+}
+
+WKDLookupResult::WKDLookupResult(const WKDLookupResult &other)
+ : Result{other}
+{
+ if (other.d) {
+ d.reset(new Private{*other.d});
+ }
+}
+
+WKDLookupResult &WKDLookupResult::operator=(const WKDLookupResult &other)
+{
+ auto tmp = other;
+ swap(tmp);
+ return *this;
+}
+
+WKDLookupResult::WKDLookupResult(WKDLookupResult &&other) = default;
+
+WKDLookupResult &WKDLookupResult::operator=(WKDLookupResult &&other) = default;
+
+void WKDLookupResult::swap(WKDLookupResult &other) noexcept
+{
+ Result::swap(other);
+ std::swap(this->d, other.d);
+}
+
+bool WKDLookupResult::isNull() const
+{
+ return !d && !bool(error());
+}
+
+std::string WKDLookupResult::pattern() const
+{
+ return d ? d->pattern : std::string{};
+}
+
+Data WKDLookupResult::keyData() const
+{
+ return d ? d->keyData : Data{};
+}
+
+std::string WKDLookupResult::source() const
+{
+ return d ? d->source : std::string{};
+}
+
+void QGpgME::swap(WKDLookupResult &a, WKDLookupResult &b)
+{
+ a.swap(b);
+}
diff --git a/lang/qt/src/wkdlookupresult.h b/lang/qt/src/wkdlookupresult.h
new file mode 100644
index 0000000..1e91d05
--- /dev/null
+++ b/lang/qt/src/wkdlookupresult.h
@@ -0,0 +1,88 @@
+/*
+ wkdlookupresult.h - wraps the result of a WKDLookupJob
+
+ This file is part of qgpgme, the Qt API binding for gpgme
+ Copyright (c) 2021 g10 Code GmbH
+ Software engineering by Ingo Klöcker <dev@ingo-kloecker.de>
+
+ QGpgME is free software; you can redistribute it and/or
+ modify it under the terms of the GNU General Public License as
+ published by the Free Software Foundation; either version 2 of the
+ License, or (at your option) any later version.
+
+ QGpgME is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
+
+ In addition, as a special exception, the copyright holders give
+ permission to link the code of this program with any edition of
+ the Qt library by Trolltech AS, Norway (or with modified versions
+ of Qt that use the same license as Qt), and distribute linked
+ combinations including the two. You must obey the GNU General
+ Public License in all respects for all of the code used other than
+ Qt. If you modify this file, you may extend this exception to
+ your version of the file, but you are not obligated to do so. If
+ you do not wish to do so, delete this exception statement from
+ your version.
+*/
+
+#ifndef __QGPGME_WKDLOOKUPRESULT_H__
+#define __QGPGME_WKDLOOKUPRESULT_H__
+
+#include "qgpgme_export.h"
+
+#ifdef BUILDING_QGPGME
+# include <result.h>
+#else
+# include <gpgme++/result.h>
+#endif
+
+#include <memory>
+
+namespace GpgME
+{
+class Data;
+class Error;
+}
+
+namespace QGpgME
+{
+
+class QGPGME_EXPORT WKDLookupResult : public GpgME::Result
+{
+public:
+ WKDLookupResult();
+ ~WKDLookupResult();
+
+ explicit WKDLookupResult(const std::string &pattern, const GpgME::Error &err);
+ explicit WKDLookupResult(const std::string &pattern, const GpgME::Data &keyData, const std::string &source, const GpgME::Error &err);
+
+ WKDLookupResult(const WKDLookupResult &other);
+ WKDLookupResult &operator=(const WKDLookupResult &other);
+
+ WKDLookupResult(WKDLookupResult &&other);
+ WKDLookupResult &operator=(WKDLookupResult &&other);
+
+ void swap(WKDLookupResult &other) noexcept;
+
+ bool isNull() const;
+
+ std::string pattern() const;
+ GpgME::Data keyData() const;
+ std::string source() const;
+
+private:
+ class Private;
+ std::unique_ptr<Private> d;
+};
+
+QGPGME_EXPORT void swap(WKDLookupResult &a, WKDLookupResult &b);
+
+}
+
+#endif // __QGPGME_WKDLOOKUPRESULT_H__
diff --git a/lang/qt/tests/Makefile.am b/lang/qt/tests/Makefile.am
index 41ea808..6c082b0 100644
--- a/lang/qt/tests/Makefile.am
+++ b/lang/qt/tests/Makefile.am
@@ -24,14 +24,22 @@ GPG = gpg
GNUPGHOME=$(abs_builddir)
TESTS_ENVIRONMENT = GNUPGHOME=$(GNUPGHOME)
-EXTRA_DIST = initial.test
+EXTRA_DIST = initial.test final.test
-TESTS = initial.test t-keylist t-keylocate t-ownertrust t-tofuinfo \
- t-encrypt t-verify t-various t-config t-remarks t-trustsignatures
+the_tests = \
+ t-addexistingsubkey \
+ t-keylist t-keylocate t-ownertrust t-tofuinfo \
+ t-encrypt t-verify t-various t-config t-remarks t-trustsignatures \
+ t-changeexpiryjob t-wkdlookup t-import
-moc_files = t-keylist.moc t-keylocate.moc t-ownertrust.moc t-tofuinfo.moc \
- t-encrypt.moc t-support.hmoc t-wkspublish.moc t-verify.moc \
- t-various.moc t-config.moc t-remarks.moc t-trustsignatures.moc
+TESTS = initial.test $(the_tests) final.test
+
+moc_files = \
+ t-addexistingsubkey.moc \
+ t-keylist.moc t-keylocate.moc t-ownertrust.moc t-tofuinfo.moc \
+ t-encrypt.moc t-support.hmoc t-wkspublish.moc t-verify.moc \
+ t-various.moc t-config.moc t-remarks.moc t-trustsignatures.moc \
+ t-changeexpiryjob.moc t-wkdlookup.moc t-import.moc
AM_LDFLAGS = -no-install
@@ -47,6 +55,7 @@ AM_CPPFLAGS = -I$(top_srcdir)/lang/cpp/src -I$(top_builddir)/src \
support_src = t-support.h t-support.cpp
+t_addexistingsubkey_SOURCES = t-addexistingsubkey.cpp $(support_src)
t_keylist_SOURCES = t-keylist.cpp $(support_src)
t_keylocate_SOURCES = t-keylocate.cpp $(support_src)
t_ownertrust_SOURCES = t-ownertrust.cpp $(support_src)
@@ -58,15 +67,24 @@ t_various_SOURCES = t-various.cpp $(support_src)
t_config_SOURCES = t-config.cpp $(support_src)
t_remarks_SOURCES = t-remarks.cpp $(support_src)
t_trustsignatures_SOURCES = t-trustsignatures.cpp $(support_src)
+t_changeexpiryjob_SOURCES = t-changeexpiryjob.cpp $(support_src)
+t_wkdlookup_SOURCES = t-wkdlookup.cpp $(support_src)
+t_import_SOURCES = t-import.cpp $(support_src)
+run_exportjob_SOURCES = run-exportjob.cpp
+run_importjob_SOURCES = run-importjob.cpp
run_keyformailboxjob_SOURCES = run-keyformailboxjob.cpp
+run_receivekeysjob_SOURCES = run-receivekeysjob.cpp
nodist_t_keylist_SOURCES = $(moc_files)
BUILT_SOURCES = $(moc_files) pubring-stamp
-noinst_PROGRAMS = t-keylist t-keylocate t-ownertrust t-tofuinfo t-encrypt \
- run-keyformailboxjob t-wkspublish t-verify t-various t-config t-remarks \
- t-trustsignatures
+noinst_PROGRAMS = \
+ t-addexistingsubkey \
+ t-keylist t-keylocate t-ownertrust t-tofuinfo t-encrypt \
+ run-keyformailboxjob t-wkspublish t-verify t-various t-config t-remarks \
+ t-trustsignatures t-changeexpiryjob t-wkdlookup t-import run-importjob \
+ run-exportjob run-receivekeysjob
CLEANFILES = secring.gpg pubring.gpg pubring.kbx trustdb.gpg dirmngr.conf \
gpg-agent.conf pubring.kbx~ S.gpg-agent gpg.conf pubring.gpg~ \
diff --git a/lang/qt/tests/Makefile.in b/lang/qt/tests/Makefile.in
index 2b0e0ee..89fad15 100644
--- a/lang/qt/tests/Makefile.in
+++ b/lang/qt/tests/Makefile.in
@@ -107,15 +107,15 @@ PRE_UNINSTALL = :
POST_UNINSTALL = :
build_triplet = @build@
host_triplet = @host@
-TESTS = initial.test t-keylist$(EXEEXT) t-keylocate$(EXEEXT) \
- t-ownertrust$(EXEEXT) t-tofuinfo$(EXEEXT) t-encrypt$(EXEEXT) \
- t-verify$(EXEEXT) t-various$(EXEEXT) t-config$(EXEEXT) \
- t-remarks$(EXEEXT) t-trustsignatures$(EXEEXT)
-noinst_PROGRAMS = t-keylist$(EXEEXT) t-keylocate$(EXEEXT) \
- t-ownertrust$(EXEEXT) t-tofuinfo$(EXEEXT) t-encrypt$(EXEEXT) \
- run-keyformailboxjob$(EXEEXT) t-wkspublish$(EXEEXT) \
- t-verify$(EXEEXT) t-various$(EXEEXT) t-config$(EXEEXT) \
- t-remarks$(EXEEXT) t-trustsignatures$(EXEEXT)
+TESTS = initial.test $(am__EXEEXT_1) final.test
+noinst_PROGRAMS = t-addexistingsubkey$(EXEEXT) t-keylist$(EXEEXT) \
+ t-keylocate$(EXEEXT) t-ownertrust$(EXEEXT) t-tofuinfo$(EXEEXT) \
+ t-encrypt$(EXEEXT) run-keyformailboxjob$(EXEEXT) \
+ t-wkspublish$(EXEEXT) t-verify$(EXEEXT) t-various$(EXEEXT) \
+ t-config$(EXEEXT) t-remarks$(EXEEXT) \
+ t-trustsignatures$(EXEEXT) t-changeexpiryjob$(EXEEXT) \
+ t-wkdlookup$(EXEEXT) t-import$(EXEEXT) run-importjob$(EXEEXT) \
+ run-exportjob$(EXEEXT) run-receivekeysjob$(EXEEXT)
subdir = lang/qt/tests
ACLOCAL_M4 = $(top_srcdir)/aclocal.m4
am__aclocal_m4_deps = $(top_srcdir)/m4/ax_cxx_compile_stdcxx.m4 \
@@ -137,16 +137,43 @@ CONFIG_HEADER = $(top_builddir)/conf/config.h
CONFIG_CLEAN_FILES =
CONFIG_CLEAN_VPATH_FILES =
PROGRAMS = $(noinst_PROGRAMS)
-am_run_keyformailboxjob_OBJECTS = run-keyformailboxjob.$(OBJEXT)
-run_keyformailboxjob_OBJECTS = $(am_run_keyformailboxjob_OBJECTS)
-run_keyformailboxjob_LDADD = $(LDADD)
-run_keyformailboxjob_DEPENDENCIES = ../../cpp/src/libgpgmepp.la \
+am_run_exportjob_OBJECTS = run-exportjob.$(OBJEXT)
+run_exportjob_OBJECTS = $(am_run_exportjob_OBJECTS)
+run_exportjob_LDADD = $(LDADD)
+run_exportjob_DEPENDENCIES = ../../cpp/src/libgpgmepp.la \
../src/libqgpgme.la ../../../src/libgpgme.la
AM_V_lt = $(am__v_lt_@AM_V@)
am__v_lt_ = $(am__v_lt_@AM_DEFAULT_V@)
am__v_lt_0 = --silent
am__v_lt_1 =
+am_run_importjob_OBJECTS = run-importjob.$(OBJEXT)
+run_importjob_OBJECTS = $(am_run_importjob_OBJECTS)
+run_importjob_LDADD = $(LDADD)
+run_importjob_DEPENDENCIES = ../../cpp/src/libgpgmepp.la \
+ ../src/libqgpgme.la ../../../src/libgpgme.la
+am_run_keyformailboxjob_OBJECTS = run-keyformailboxjob.$(OBJEXT)
+run_keyformailboxjob_OBJECTS = $(am_run_keyformailboxjob_OBJECTS)
+run_keyformailboxjob_LDADD = $(LDADD)
+run_keyformailboxjob_DEPENDENCIES = ../../cpp/src/libgpgmepp.la \
+ ../src/libqgpgme.la ../../../src/libgpgme.la
+am_run_receivekeysjob_OBJECTS = run-receivekeysjob.$(OBJEXT)
+run_receivekeysjob_OBJECTS = $(am_run_receivekeysjob_OBJECTS)
+run_receivekeysjob_LDADD = $(LDADD)
+run_receivekeysjob_DEPENDENCIES = ../../cpp/src/libgpgmepp.la \
+ ../src/libqgpgme.la ../../../src/libgpgme.la
am__objects_1 = t-support.$(OBJEXT)
+am_t_addexistingsubkey_OBJECTS = t-addexistingsubkey.$(OBJEXT) \
+ $(am__objects_1)
+t_addexistingsubkey_OBJECTS = $(am_t_addexistingsubkey_OBJECTS)
+t_addexistingsubkey_LDADD = $(LDADD)
+t_addexistingsubkey_DEPENDENCIES = ../../cpp/src/libgpgmepp.la \
+ ../src/libqgpgme.la ../../../src/libgpgme.la
+am_t_changeexpiryjob_OBJECTS = t-changeexpiryjob.$(OBJEXT) \
+ $(am__objects_1)
+t_changeexpiryjob_OBJECTS = $(am_t_changeexpiryjob_OBJECTS)
+t_changeexpiryjob_LDADD = $(LDADD)
+t_changeexpiryjob_DEPENDENCIES = ../../cpp/src/libgpgmepp.la \
+ ../src/libqgpgme.la ../../../src/libgpgme.la
am_t_config_OBJECTS = t-config.$(OBJEXT) $(am__objects_1)
t_config_OBJECTS = $(am_t_config_OBJECTS)
t_config_LDADD = $(LDADD)
@@ -157,6 +184,11 @@ t_encrypt_OBJECTS = $(am_t_encrypt_OBJECTS)
t_encrypt_LDADD = $(LDADD)
t_encrypt_DEPENDENCIES = ../../cpp/src/libgpgmepp.la \
../src/libqgpgme.la ../../../src/libgpgme.la
+am_t_import_OBJECTS = t-import.$(OBJEXT) $(am__objects_1)
+t_import_OBJECTS = $(am_t_import_OBJECTS)
+t_import_LDADD = $(LDADD)
+t_import_DEPENDENCIES = ../../cpp/src/libgpgmepp.la \
+ ../src/libqgpgme.la ../../../src/libgpgme.la
am_t_keylist_OBJECTS = t-keylist.$(OBJEXT) $(am__objects_1)
am__objects_2 =
nodist_t_keylist_OBJECTS = $(am__objects_2)
@@ -201,6 +233,11 @@ t_verify_OBJECTS = $(am_t_verify_OBJECTS)
t_verify_LDADD = $(LDADD)
t_verify_DEPENDENCIES = ../../cpp/src/libgpgmepp.la \
../src/libqgpgme.la ../../../src/libgpgme.la
+am_t_wkdlookup_OBJECTS = t-wkdlookup.$(OBJEXT) $(am__objects_1)
+t_wkdlookup_OBJECTS = $(am_t_wkdlookup_OBJECTS)
+t_wkdlookup_LDADD = $(LDADD)
+t_wkdlookup_DEPENDENCIES = ../../cpp/src/libgpgmepp.la \
+ ../src/libqgpgme.la ../../../src/libgpgme.la
am_t_wkspublish_OBJECTS = t-wkspublish.$(OBJEXT) $(am__objects_1)
t_wkspublish_OBJECTS = $(am_t_wkspublish_OBJECTS)
t_wkspublish_LDADD = $(LDADD)
@@ -221,13 +258,19 @@ am__v_at_1 =
DEFAULT_INCLUDES = -I.@am__isrc@ -I$(top_builddir)/conf
depcomp = $(SHELL) $(top_srcdir)/build-aux/depcomp
am__maybe_remake_depfiles = depfiles
-am__depfiles_remade = ./$(DEPDIR)/run-keyformailboxjob.Po \
- ./$(DEPDIR)/t-config.Po ./$(DEPDIR)/t-encrypt.Po \
+am__depfiles_remade = ./$(DEPDIR)/run-exportjob.Po \
+ ./$(DEPDIR)/run-importjob.Po \
+ ./$(DEPDIR)/run-keyformailboxjob.Po \
+ ./$(DEPDIR)/run-receivekeysjob.Po \
+ ./$(DEPDIR)/t-addexistingsubkey.Po \
+ ./$(DEPDIR)/t-changeexpiryjob.Po ./$(DEPDIR)/t-config.Po \
+ ./$(DEPDIR)/t-encrypt.Po ./$(DEPDIR)/t-import.Po \
./$(DEPDIR)/t-keylist.Po ./$(DEPDIR)/t-keylocate.Po \
./$(DEPDIR)/t-ownertrust.Po ./$(DEPDIR)/t-remarks.Po \
./$(DEPDIR)/t-support.Po ./$(DEPDIR)/t-tofuinfo.Po \
./$(DEPDIR)/t-trustsignatures.Po ./$(DEPDIR)/t-various.Po \
- ./$(DEPDIR)/t-verify.Po ./$(DEPDIR)/t-wkspublish.Po
+ ./$(DEPDIR)/t-verify.Po ./$(DEPDIR)/t-wkdlookup.Po \
+ ./$(DEPDIR)/t-wkspublish.Po
am__mv = mv -f
CXXCOMPILE = $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) \
$(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS)
@@ -265,19 +308,25 @@ AM_V_CCLD = $(am__v_CCLD_@AM_V@)
am__v_CCLD_ = $(am__v_CCLD_@AM_DEFAULT_V@)
am__v_CCLD_0 = @echo " CCLD " $@;
am__v_CCLD_1 =
-SOURCES = $(run_keyformailboxjob_SOURCES) $(t_config_SOURCES) \
- $(t_encrypt_SOURCES) $(t_keylist_SOURCES) \
- $(nodist_t_keylist_SOURCES) $(t_keylocate_SOURCES) \
- $(t_ownertrust_SOURCES) $(t_remarks_SOURCES) \
- $(t_tofuinfo_SOURCES) $(t_trustsignatures_SOURCES) \
- $(t_various_SOURCES) $(t_verify_SOURCES) \
- $(t_wkspublish_SOURCES)
-DIST_SOURCES = $(run_keyformailboxjob_SOURCES) $(t_config_SOURCES) \
- $(t_encrypt_SOURCES) $(t_keylist_SOURCES) \
+SOURCES = $(run_exportjob_SOURCES) $(run_importjob_SOURCES) \
+ $(run_keyformailboxjob_SOURCES) $(run_receivekeysjob_SOURCES) \
+ $(t_addexistingsubkey_SOURCES) $(t_changeexpiryjob_SOURCES) \
+ $(t_config_SOURCES) $(t_encrypt_SOURCES) $(t_import_SOURCES) \
+ $(t_keylist_SOURCES) $(nodist_t_keylist_SOURCES) \
$(t_keylocate_SOURCES) $(t_ownertrust_SOURCES) \
$(t_remarks_SOURCES) $(t_tofuinfo_SOURCES) \
$(t_trustsignatures_SOURCES) $(t_various_SOURCES) \
- $(t_verify_SOURCES) $(t_wkspublish_SOURCES)
+ $(t_verify_SOURCES) $(t_wkdlookup_SOURCES) \
+ $(t_wkspublish_SOURCES)
+DIST_SOURCES = $(run_exportjob_SOURCES) $(run_importjob_SOURCES) \
+ $(run_keyformailboxjob_SOURCES) $(run_receivekeysjob_SOURCES) \
+ $(t_addexistingsubkey_SOURCES) $(t_changeexpiryjob_SOURCES) \
+ $(t_config_SOURCES) $(t_encrypt_SOURCES) $(t_import_SOURCES) \
+ $(t_keylist_SOURCES) $(t_keylocate_SOURCES) \
+ $(t_ownertrust_SOURCES) $(t_remarks_SOURCES) \
+ $(t_tofuinfo_SOURCES) $(t_trustsignatures_SOURCES) \
+ $(t_various_SOURCES) $(t_verify_SOURCES) \
+ $(t_wkdlookup_SOURCES) $(t_wkspublish_SOURCES)
am__can_run_installinfo = \
case $$AM_UPDATE_INFO_DIR in \
n|no|NO) false;; \
@@ -324,6 +373,12 @@ am__tty_colors = { \
std=''; \
fi; \
}
+am__EXEEXT_1 = t-addexistingsubkey$(EXEEXT) t-keylist$(EXEEXT) \
+ t-keylocate$(EXEEXT) t-ownertrust$(EXEEXT) t-tofuinfo$(EXEEXT) \
+ t-encrypt$(EXEEXT) t-verify$(EXEEXT) t-various$(EXEEXT) \
+ t-config$(EXEEXT) t-remarks$(EXEEXT) \
+ t-trustsignatures$(EXEEXT) t-changeexpiryjob$(EXEEXT) \
+ t-wkdlookup$(EXEEXT) t-import$(EXEEXT)
am__DIST_COMMON = $(srcdir)/Makefile.in \
$(top_srcdir)/build-aux/depcomp \
$(top_srcdir)/build-aux/mkinstalldirs
@@ -529,10 +584,19 @@ top_srcdir = @top_srcdir@
GPG = gpg
GNUPGHOME = $(abs_builddir)
TESTS_ENVIRONMENT = GNUPGHOME=$(GNUPGHOME)
-EXTRA_DIST = initial.test
-moc_files = t-keylist.moc t-keylocate.moc t-ownertrust.moc t-tofuinfo.moc \
- t-encrypt.moc t-support.hmoc t-wkspublish.moc t-verify.moc \
- t-various.moc t-config.moc t-remarks.moc t-trustsignatures.moc
+EXTRA_DIST = initial.test final.test
+the_tests = \
+ t-addexistingsubkey \
+ t-keylist t-keylocate t-ownertrust t-tofuinfo \
+ t-encrypt t-verify t-various t-config t-remarks t-trustsignatures \
+ t-changeexpiryjob t-wkdlookup t-import
+
+moc_files = \
+ t-addexistingsubkey.moc \
+ t-keylist.moc t-keylocate.moc t-ownertrust.moc t-tofuinfo.moc \
+ t-encrypt.moc t-support.hmoc t-wkspublish.moc t-verify.moc \
+ t-various.moc t-config.moc t-remarks.moc t-trustsignatures.moc \
+ t-changeexpiryjob.moc t-wkdlookup.moc t-import.moc
AM_LDFLAGS = -no-install
LDADD = ../../cpp/src/libgpgmepp.la ../src/libqgpgme.la \
@@ -546,6 +610,7 @@ AM_CPPFLAGS = -I$(top_srcdir)/lang/cpp/src -I$(top_builddir)/src \
-DTOP_SRCDIR="$(top_srcdir)"
support_src = t-support.h t-support.cpp
+t_addexistingsubkey_SOURCES = t-addexistingsubkey.cpp $(support_src)
t_keylist_SOURCES = t-keylist.cpp $(support_src)
t_keylocate_SOURCES = t-keylocate.cpp $(support_src)
t_ownertrust_SOURCES = t-ownertrust.cpp $(support_src)
@@ -557,7 +622,13 @@ t_various_SOURCES = t-various.cpp $(support_src)
t_config_SOURCES = t-config.cpp $(support_src)
t_remarks_SOURCES = t-remarks.cpp $(support_src)
t_trustsignatures_SOURCES = t-trustsignatures.cpp $(support_src)
+t_changeexpiryjob_SOURCES = t-changeexpiryjob.cpp $(support_src)
+t_wkdlookup_SOURCES = t-wkdlookup.cpp $(support_src)
+t_import_SOURCES = t-import.cpp $(support_src)
+run_exportjob_SOURCES = run-exportjob.cpp
+run_importjob_SOURCES = run-importjob.cpp
run_keyformailboxjob_SOURCES = run-keyformailboxjob.cpp
+run_receivekeysjob_SOURCES = run-receivekeysjob.cpp
nodist_t_keylist_SOURCES = $(moc_files)
BUILT_SOURCES = $(moc_files) pubring-stamp
CLEANFILES = secring.gpg pubring.gpg pubring.kbx trustdb.gpg dirmngr.conf \
@@ -609,10 +680,30 @@ clean-noinstPROGRAMS:
echo " rm -f" $$list; \
rm -f $$list
+run-exportjob$(EXEEXT): $(run_exportjob_OBJECTS) $(run_exportjob_DEPENDENCIES) $(EXTRA_run_exportjob_DEPENDENCIES)
+ @rm -f run-exportjob$(EXEEXT)
+ $(AM_V_CXXLD)$(CXXLINK) $(run_exportjob_OBJECTS) $(run_exportjob_LDADD) $(LIBS)
+
+run-importjob$(EXEEXT): $(run_importjob_OBJECTS) $(run_importjob_DEPENDENCIES) $(EXTRA_run_importjob_DEPENDENCIES)
+ @rm -f run-importjob$(EXEEXT)
+ $(AM_V_CXXLD)$(CXXLINK) $(run_importjob_OBJECTS) $(run_importjob_LDADD) $(LIBS)
+
run-keyformailboxjob$(EXEEXT): $(run_keyformailboxjob_OBJECTS) $(run_keyformailboxjob_DEPENDENCIES) $(EXTRA_run_keyformailboxjob_DEPENDENCIES)
@rm -f run-keyformailboxjob$(EXEEXT)
$(AM_V_CXXLD)$(CXXLINK) $(run_keyformailboxjob_OBJECTS) $(run_keyformailboxjob_LDADD) $(LIBS)
+run-receivekeysjob$(EXEEXT): $(run_receivekeysjob_OBJECTS) $(run_receivekeysjob_DEPENDENCIES) $(EXTRA_run_receivekeysjob_DEPENDENCIES)
+ @rm -f run-receivekeysjob$(EXEEXT)
+ $(AM_V_CXXLD)$(CXXLINK) $(run_receivekeysjob_OBJECTS) $(run_receivekeysjob_LDADD) $(LIBS)
+
+t-addexistingsubkey$(EXEEXT): $(t_addexistingsubkey_OBJECTS) $(t_addexistingsubkey_DEPENDENCIES) $(EXTRA_t_addexistingsubkey_DEPENDENCIES)
+ @rm -f t-addexistingsubkey$(EXEEXT)
+ $(AM_V_CXXLD)$(CXXLINK) $(t_addexistingsubkey_OBJECTS) $(t_addexistingsubkey_LDADD) $(LIBS)
+
+t-changeexpiryjob$(EXEEXT): $(t_changeexpiryjob_OBJECTS) $(t_changeexpiryjob_DEPENDENCIES) $(EXTRA_t_changeexpiryjob_DEPENDENCIES)
+ @rm -f t-changeexpiryjob$(EXEEXT)
+ $(AM_V_CXXLD)$(CXXLINK) $(t_changeexpiryjob_OBJECTS) $(t_changeexpiryjob_LDADD) $(LIBS)
+
t-config$(EXEEXT): $(t_config_OBJECTS) $(t_config_DEPENDENCIES) $(EXTRA_t_config_DEPENDENCIES)
@rm -f t-config$(EXEEXT)
$(AM_V_CXXLD)$(CXXLINK) $(t_config_OBJECTS) $(t_config_LDADD) $(LIBS)
@@ -621,6 +712,10 @@ t-encrypt$(EXEEXT): $(t_encrypt_OBJECTS) $(t_encrypt_DEPENDENCIES) $(EXTRA_t_enc
@rm -f t-encrypt$(EXEEXT)
$(AM_V_CXXLD)$(CXXLINK) $(t_encrypt_OBJECTS) $(t_encrypt_LDADD) $(LIBS)
+t-import$(EXEEXT): $(t_import_OBJECTS) $(t_import_DEPENDENCIES) $(EXTRA_t_import_DEPENDENCIES)
+ @rm -f t-import$(EXEEXT)
+ $(AM_V_CXXLD)$(CXXLINK) $(t_import_OBJECTS) $(t_import_LDADD) $(LIBS)
+
t-keylist$(EXEEXT): $(t_keylist_OBJECTS) $(t_keylist_DEPENDENCIES) $(EXTRA_t_keylist_DEPENDENCIES)
@rm -f t-keylist$(EXEEXT)
$(AM_V_CXXLD)$(CXXLINK) $(t_keylist_OBJECTS) $(t_keylist_LDADD) $(LIBS)
@@ -653,6 +748,10 @@ t-verify$(EXEEXT): $(t_verify_OBJECTS) $(t_verify_DEPENDENCIES) $(EXTRA_t_verify
@rm -f t-verify$(EXEEXT)
$(AM_V_CXXLD)$(CXXLINK) $(t_verify_OBJECTS) $(t_verify_LDADD) $(LIBS)
+t-wkdlookup$(EXEEXT): $(t_wkdlookup_OBJECTS) $(t_wkdlookup_DEPENDENCIES) $(EXTRA_t_wkdlookup_DEPENDENCIES)
+ @rm -f t-wkdlookup$(EXEEXT)
+ $(AM_V_CXXLD)$(CXXLINK) $(t_wkdlookup_OBJECTS) $(t_wkdlookup_LDADD) $(LIBS)
+
t-wkspublish$(EXEEXT): $(t_wkspublish_OBJECTS) $(t_wkspublish_DEPENDENCIES) $(EXTRA_t_wkspublish_DEPENDENCIES)
@rm -f t-wkspublish$(EXEEXT)
$(AM_V_CXXLD)$(CXXLINK) $(t_wkspublish_OBJECTS) $(t_wkspublish_LDADD) $(LIBS)
@@ -663,9 +762,15 @@ mostlyclean-compile:
distclean-compile:
-rm -f *.tab.c
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/run-exportjob.Po@am__quote@ # am--include-marker
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/run-importjob.Po@am__quote@ # am--include-marker
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/run-keyformailboxjob.Po@am__quote@ # am--include-marker
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/run-receivekeysjob.Po@am__quote@ # am--include-marker
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/t-addexistingsubkey.Po@am__quote@ # am--include-marker
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/t-changeexpiryjob.Po@am__quote@ # am--include-marker
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/t-config.Po@am__quote@ # am--include-marker
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/t-encrypt.Po@am__quote@ # am--include-marker
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/t-import.Po@am__quote@ # am--include-marker
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/t-keylist.Po@am__quote@ # am--include-marker
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/t-keylocate.Po@am__quote@ # am--include-marker
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/t-ownertrust.Po@am__quote@ # am--include-marker
@@ -675,6 +780,7 @@ distclean-compile:
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/t-trustsignatures.Po@am__quote@ # am--include-marker
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/t-various.Po@am__quote@ # am--include-marker
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/t-verify.Po@am__quote@ # am--include-marker
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/t-wkdlookup.Po@am__quote@ # am--include-marker
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/t-wkspublish.Po@am__quote@ # am--include-marker
$(am__depfiles_remade):
@@ -934,9 +1040,15 @@ clean-am: clean-generic clean-libtool clean-local clean-noinstPROGRAMS \
mostlyclean-am
distclean: distclean-am
- -rm -f ./$(DEPDIR)/run-keyformailboxjob.Po
+ -rm -f ./$(DEPDIR)/run-exportjob.Po
+ -rm -f ./$(DEPDIR)/run-importjob.Po
+ -rm -f ./$(DEPDIR)/run-keyformailboxjob.Po
+ -rm -f ./$(DEPDIR)/run-receivekeysjob.Po
+ -rm -f ./$(DEPDIR)/t-addexistingsubkey.Po
+ -rm -f ./$(DEPDIR)/t-changeexpiryjob.Po
-rm -f ./$(DEPDIR)/t-config.Po
-rm -f ./$(DEPDIR)/t-encrypt.Po
+ -rm -f ./$(DEPDIR)/t-import.Po
-rm -f ./$(DEPDIR)/t-keylist.Po
-rm -f ./$(DEPDIR)/t-keylocate.Po
-rm -f ./$(DEPDIR)/t-ownertrust.Po
@@ -946,6 +1058,7 @@ distclean: distclean-am
-rm -f ./$(DEPDIR)/t-trustsignatures.Po
-rm -f ./$(DEPDIR)/t-various.Po
-rm -f ./$(DEPDIR)/t-verify.Po
+ -rm -f ./$(DEPDIR)/t-wkdlookup.Po
-rm -f ./$(DEPDIR)/t-wkspublish.Po
-rm -f Makefile
distclean-am: clean-am distclean-compile distclean-generic \
@@ -992,9 +1105,15 @@ install-ps-am:
installcheck-am:
maintainer-clean: maintainer-clean-am
- -rm -f ./$(DEPDIR)/run-keyformailboxjob.Po
+ -rm -f ./$(DEPDIR)/run-exportjob.Po
+ -rm -f ./$(DEPDIR)/run-importjob.Po
+ -rm -f ./$(DEPDIR)/run-keyformailboxjob.Po
+ -rm -f ./$(DEPDIR)/run-receivekeysjob.Po
+ -rm -f ./$(DEPDIR)/t-addexistingsubkey.Po
+ -rm -f ./$(DEPDIR)/t-changeexpiryjob.Po
-rm -f ./$(DEPDIR)/t-config.Po
-rm -f ./$(DEPDIR)/t-encrypt.Po
+ -rm -f ./$(DEPDIR)/t-import.Po
-rm -f ./$(DEPDIR)/t-keylist.Po
-rm -f ./$(DEPDIR)/t-keylocate.Po
-rm -f ./$(DEPDIR)/t-ownertrust.Po
@@ -1004,6 +1123,7 @@ maintainer-clean: maintainer-clean-am
-rm -f ./$(DEPDIR)/t-trustsignatures.Po
-rm -f ./$(DEPDIR)/t-various.Po
-rm -f ./$(DEPDIR)/t-verify.Po
+ -rm -f ./$(DEPDIR)/t-wkdlookup.Po
-rm -f ./$(DEPDIR)/t-wkspublish.Po
-rm -f Makefile
maintainer-clean-am: distclean-am maintainer-clean-generic
diff --git a/lang/qt/tests/final.test b/lang/qt/tests/final.test
new file mode 100755
index 0000000..f28aaa4
--- /dev/null
+++ b/lang/qt/tests/final.test
@@ -0,0 +1,6 @@
+#!/bin/sh
+
+# stop the dirmngr that may have been started
+gpgconf --kill dirmngr
+
+exit 0
diff --git a/lang/qt/tests/run-exportjob.cpp b/lang/qt/tests/run-exportjob.cpp
new file mode 100644
index 0000000..0f8fd8f
--- /dev/null
+++ b/lang/qt/tests/run-exportjob.cpp
@@ -0,0 +1,119 @@
+/*
+ run-exportjob.cpp
+
+ This file is part of QGpgME's test suite.
+ Copyright (c) 2022 by g10 Code GmbH
+ Software engineering by Ingo Klöcker <dev@ingo-kloecker.de>
+
+ QGpgME is free software; you can redistribute it and/or
+ modify it under the terms of the GNU General Public License,
+ version 2, as published by the Free Software Foundation.
+
+ QGpgME is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
+
+ In addition, as a special exception, the copyright holders give
+ permission to link the code of this program with any edition of
+ the Qt library by Trolltech AS, Norway (or with modified versions
+ of Qt that use the same license as Qt), and distribute linked
+ combinations including the two. You must obey the GNU General
+ Public License in all respects for all of the code used other than
+ Qt. If you modify this file, you may extend this exception to
+ your version of the file, but you are not obligated to do so. If
+ you do not wish to do so, delete this exception statement from
+ your version.
+*/
+
+#ifdef HAVE_CONFIG_H
+ #include "config.h"
+#endif
+
+#include <exportjob.h>
+#include <protocol.h>
+
+#include <context.h>
+
+#include <QCoreApplication>
+
+#include <iostream>
+
+using namespace GpgME;
+using std::cout;
+using std::cerr;
+
+static void showUsageAndExitWithCode(int exitCode)
+{
+ cerr << "Usage: run-exportjob [OPTION]... [PATTERN]...\n"
+ "Options:\n"
+ " --secret export secret keys instead of public keys\n"
+ " --secret-subkey export secret subkeys instead of public keys\n";
+
+ exit(exitCode);
+}
+
+static auto createExportJob(unsigned int mode)
+{
+ if (mode & Context::ExportSecretSubkey) {
+ return QGpgME::openpgp()->secretSubkeyExportJob(/*armor=*/true);
+ } else if (mode & Context::ExportSecret) {
+ return QGpgME::openpgp()->secretKeyExportJob(/*armor=*/true);
+ }
+ return QGpgME::openpgp()->publicKeyExportJob(/*armor=*/true);
+}
+
+int main(int argc, char *argv[])
+{
+ GpgME::initializeLibrary();
+
+ QCoreApplication app{argc, argv};
+
+ unsigned int exportMode = 0;
+
+ auto arguments = app.arguments();
+ if (!arguments.isEmpty()) {
+ arguments.pop_front(); // remove program name
+ }
+ while (!arguments.isEmpty()) {
+ const auto &arg = arguments.front();
+ if (!arg.startsWith(QLatin1String{"--"})) {
+ break;
+ }
+ if (arg == QLatin1String{"--"}) {
+ arguments.pop_front();
+ break;
+ }
+ if (arg == QLatin1String{"--help"}) {
+ showUsageAndExitWithCode(0);
+ } else if (arg == QLatin1String{"--secret"}) {
+ exportMode = Context::ExportSecret;
+ arguments.pop_front();
+ } else if (arg == QLatin1String{"--secret-subkey"}) {
+ exportMode = Context::ExportSecretSubkey;
+ arguments.pop_front();
+ } else {
+ cerr << "Error: Invalid option " << arg.toStdString() << std::endl;
+ showUsageAndExitWithCode(1);
+ }
+ }
+
+ auto job = createExportJob(exportMode);
+ QObject::connect(job, &QGpgME::ExportJob::result,
+ &app, [&app] (const GpgME::Error &err, const QByteArray &keyData, const QString &, const GpgME::Error &) {
+ if (err) {
+ cerr << "The ChangeExpiryJob failed with" << err.asString() << ".";
+ app.exit(1);
+ return;
+ }
+ cout << "Begin Result:\n" << keyData.toStdString() << "End Result:\n";
+ app.exit();
+ });
+ job->start(arguments);
+
+ return app.exec();
+}
diff --git a/lang/qt/tests/run-importjob.cpp b/lang/qt/tests/run-importjob.cpp
new file mode 100644
index 0000000..b1814fa
--- /dev/null
+++ b/lang/qt/tests/run-importjob.cpp
@@ -0,0 +1,99 @@
+/*
+ run-importjob.cpp
+
+ This file is part of QGpgME's test suite.
+ Copyright (c) 2021 by g10 Code GmbH
+ Software engineering by Ingo Klöcker <dev@ingo-kloecker.de>
+
+ QGpgME is free software; you can redistribute it and/or
+ modify it under the terms of the GNU General Public License,
+ version 2, as published by the Free Software Foundation.
+
+ QGpgME is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
+
+ In addition, as a special exception, the copyright holders give
+ permission to link the code of this program with any edition of
+ the Qt library by Trolltech AS, Norway (or with modified versions
+ of Qt that use the same license as Qt), and distribute linked
+ combinations including the two. You must obey the GNU General
+ Public License in all respects for all of the code used other than
+ Qt. If you modify this file, you may extend this exception to
+ your version of the file, but you are not obligated to do so. If
+ you do not wish to do so, delete this exception statement from
+ your version.
+*/
+
+#ifdef HAVE_CONFIG_H
+ #include "config.h"
+#endif
+
+#include <importjob.h>
+#include <importresult.h>
+#include <protocol.h>
+
+#include <QFile>
+#include <QFileInfo>
+
+#include <QDebug>
+
+#include <set>
+#include <sstream>
+
+GpgME::Protocol guessProtocol(const QString &filename)
+{
+ static const std::set<QString> cmsExtensions = {"cer", "crt", "der", "p12", "p7c", "pem", "pfx"};
+ static const std::set<QString> pgpExtensions = {"asc", "gpg", "pgp"};
+
+ const auto extension = QFileInfo{filename}.suffix();
+ if (cmsExtensions.find(extension) != cmsExtensions.end()) {
+ return GpgME::CMS;
+ } else if (pgpExtensions.find(extension) != pgpExtensions.end()) {
+ return GpgME::OpenPGP;
+ }
+ qDebug() << "Unknown file name extension" << extension;
+ return GpgME::UnknownProtocol;
+}
+
+int main(int argc, char **argv)
+{
+ GpgME::initializeLibrary();
+
+ if (argc != 2) {
+ qInfo().noquote() << "Usage:" << argv[0] << "<certificate file>";
+ return 1;
+ }
+ const auto filename = QString::fromLocal8Bit(argv[1]);
+
+ QFile f{filename};
+ if (!f.exists()) {
+ qWarning() << "Error: File not found" << filename;
+ return 1;
+ }
+ const auto protocol = guessProtocol(filename);
+ if (protocol == GpgME::UnknownProtocol) {
+ qWarning() << "Error: Unknown file type";
+ return 1;
+ }
+ if (!f.open(QIODevice::ReadOnly)) {
+ qWarning() << "Error: Failed to open file" << filename << "for reading.";
+ return 1;
+ }
+
+ const auto keyData = f.readAll();
+ auto job = (protocol == GpgME::CMS ? QGpgME::smime() : QGpgME::openpgp())->importJob();
+ const auto result = job->exec(keyData);
+ qDebug() << "Result error:" << result.error().asString();
+ std::ostringstream ostr;
+ ostr << result;
+ for (const auto &line : QString::fromStdString(ostr.str()).split('\n')) {
+ qDebug().noquote() << line;
+ }
+ return 0;
+}
diff --git a/lang/qt/tests/run-receivekeysjob.cpp b/lang/qt/tests/run-receivekeysjob.cpp
new file mode 100644
index 0000000..0dc1575
--- /dev/null
+++ b/lang/qt/tests/run-receivekeysjob.cpp
@@ -0,0 +1,65 @@
+/*
+ run-receivekeysjob.cpp
+
+ This file is part of QGpgME's test suite.
+ Copyright (c) 2022 by g10 Code GmbH
+ Software engineering by Ingo Klöcker <dev@ingo-kloecker.de>
+
+ QGpgME is free software; you can redistribute it and/or
+ modify it under the terms of the GNU General Public License,
+ version 2, as published by the Free Software Foundation.
+
+ QGpgME is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
+
+ In addition, as a special exception, the copyright holders give
+ permission to link the code of this program with any edition of
+ the Qt library by Trolltech AS, Norway (or with modified versions
+ of Qt that use the same license as Qt), and distribute linked
+ combinations including the two. You must obey the GNU General
+ Public License in all respects for all of the code used other than
+ Qt. If you modify this file, you may extend this exception to
+ your version of the file, but you are not obligated to do so. If
+ you do not wish to do so, delete this exception statement from
+ your version.
+*/
+
+#ifdef HAVE_CONFIG_H
+ #include "config.h"
+#endif
+
+#include <importresult.h>
+#include <protocol.h>
+#include <receivekeysjob.h>
+
+#include <QCoreApplication>
+#include <QDebug>
+
+#include <iostream>
+
+int main(int argc, char **argv)
+{
+ GpgME::initializeLibrary();
+
+ if (argc < 2) {
+ std::cerr << "Usage: " << argv[0] << " KEYID..." << std::endl;
+ return 1;
+ }
+
+ QCoreApplication app(argc, argv);
+ const QStringList keyIds = qApp->arguments().mid(1);
+
+ auto job = QGpgME::openpgp()->receiveKeysJob();
+ const auto result = job->exec(keyIds);
+
+ std::cout << "Result: " << result.error().asString() << std::endl;
+ std::cout << "Details:\n" << result << std::endl;
+
+ return 0;
+}
diff --git a/lang/qt/tests/t-addexistingsubkey.cpp b/lang/qt/tests/t-addexistingsubkey.cpp
new file mode 100644
index 0000000..589c90b
--- /dev/null
+++ b/lang/qt/tests/t-addexistingsubkey.cpp
@@ -0,0 +1,260 @@
+/* t-addexistingsubkey.cpp
+
+ This file is part of qgpgme, the Qt API binding for gpgme
+ Copyright (c) 2022 g10 Code GmbH
+ Software engineering by Ingo Klöcker <dev@ingo-kloecker.de>
+
+ QGpgME is free software; you can redistribute it and/or
+ modify it under the terms of the GNU General Public License as
+ published by the Free Software Foundation; either version 2 of the
+ License, or (at your option) any later version.
+
+ QGpgME is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
+
+ In addition, as a special exception, the copyright holders give
+ permission to link the code of this program with any edition of
+ the Qt library by Trolltech AS, Norway (or with modified versions
+ of Qt that use the same license as Qt), and distribute linked
+ combinations including the two. You must obey the GNU General
+ Public License in all respects for all of the code used other than
+ Qt. If you modify this file, you may extend this exception to
+ your version of the file, but you are not obligated to do so. If
+ you do not wish to do so, delete this exception statement from
+ your version.
+*/
+#ifdef HAVE_CONFIG_H
+ #include "config.h"
+#endif
+
+#include "t-support.h"
+
+#include "addexistingsubkeyjob.h"
+#include "protocol.h"
+
+#include <QSignalSpy>
+#include <QTest>
+
+#include "context.h"
+#include "data.h"
+#include "engineinfo.h"
+
+#include <algorithm>
+
+using namespace QGpgME;
+using namespace GpgME;
+
+static const char *requiredVersion = "2.3.5";
+
+/* Test keys
+ sec# ed25519 2022-01-13 [SC]
+ 1CB8C6A0317AA83F44FE009932392C82B814C8E0
+ uid [ unknown] source-key@example.net
+ ssb cv25519 2022-01-13 [E]
+ ssb cv25519 2022-01-13 [E] [expires: 2100-01-01]
+
+ sec ed25519 2022-01-13 [SC]
+ C3C87F0A3920B01F9E4450EA2B79F21D4DD10BFC
+ uid [ unknown] target-key@example.net
+ ssb cv25519 2022-01-13 [E]
+ * generated with
+export GNUPGHOME=$(mktemp -d)
+gpg -K
+gpg --batch --pinentry-mode loopback --passphrase abc --quick-gen-key source-key@example.net default default never
+fpr=$(gpg -k --with-colons source-key@example.net | grep ^fpr | head -1 | cut -d ':' -f 10)
+gpg --batch --pinentry-mode loopback --passphrase abc --quick-add-key ${fpr} default default 21000101T120000
+gpg --batch --pinentry-mode loopback --passphrase abc --quick-gen-key target-key@example.net default default never
+gpg -K
+gpg --export-secret-subkeys --armor --batch --pinentry-mode loopback --passphrase abc --comment source-key@example.net source-key@example.net | sed 's/\(.*\)/ "\1\\n"/'
+gpg --export-secret-keys --armor --batch --pinentry-mode loopback --passphrase abc --comment target-key@example.net target-key@example.net | sed 's/\(.*\)/ "\1\\n"/'
+#rm -rf ${GNUPGHOME}
+unset GNUPGHOME
+*/
+static const char *testKeyData =
+ "-----BEGIN PGP PRIVATE KEY BLOCK-----\n"
+ "Comment: source-key@example.net\n"
+ "\n"
+ "lDsEYd/ujBYJKwYBBAHaRw8BAQdAwiZPINTcrpgmu6ZWSaPZlcRSd4nDuofVMhe7\n"
+ "c2XrFyT/AGUAR05VAbQWc291cmNlLWtleUBleGFtcGxlLm5ldIiUBBMWCgA8FiEE\n"
+ "HLjGoDF6qD9E/gCZMjksgrgUyOAFAmHf7owCGwMFCwkIBwIDIgIBBhUKCQgLAgQW\n"
+ "AgMBAh4HAheAAAoJEDI5LIK4FMjgupIA/Au2YEAT9dYdJd0eJCJerG5YAeoB+uBs\n"
+ "mBkgr6xXE0bIAP43b6u1Jtvf/Wm3BhRbLd5Tg67Ba4CIZ8ZLGng73FBoBpyLBGHf\n"
+ "7owSCisGAQQBl1UBBQEBB0Cpg8Qof/WShxROZZtmPnw24vTk0R8nIAF1CZJ0bG/C\n"
+ "SwMBCAf+BwMCtzxziVxQEor8w/VVzHp4/hVSCUyrpiX7Djf04cIMs2bFPduZLgxb\n"
+ "c1SXhlgiqU0YBNntbGGNdKjTP6FMbYWq1+NwQm6ZXtC76LPG7syM94h4BBgWCgAg\n"
+ "FiEEHLjGoDF6qD9E/gCZMjksgrgUyOAFAmHf7owCGwwACgkQMjksgrgUyOCI0wEA\n"
+ "+f56fkvDDUwMOMw7n4+GKpfJXpWhVL08ttccbBOa/9IA/2HYA/78ZaD8E5EyqAEK\n"
+ "Aj9Au+2oJu9V5qo92QEoqwYHnIsEYd/vgxIKKwYBBAGXVQEFAQEHQBa9FxJkm/9D\n"
+ "xABildkaYMrbJbu8BPk6uv9V8aLmv9FnAwEIB/4HAwIPhcbN8s6OzPz8/g78TrCh\n"
+ "xqQb2kygCEj+OQ4/XXU3lus2b5xS5h44LGt99Wisqx+wVPDXmPDJOaxjhHXDmJxd\n"
+ "/LplIEhykojSm3uUDxERiH4EGBYKACYWIQQcuMagMXqoP0T+AJkyOSyCuBTI4AUC\n"
+ "Yd/vgwIbDAUJkqcQPQAKCRAyOSyCuBTI4IUjAP9BTfOD+jy6lLmzNO9pquRSAxi/\n"
+ "PQuglGtpS0LQEJMEOwD+PFnsMe2EtQ+WVSDBeB7O0m61EXeY+RhpuhNtsNXVuwc=\n"
+ "=wIPU\n"
+ "-----END PGP PRIVATE KEY BLOCK-----\n"
+ "-----BEGIN PGP PRIVATE KEY BLOCK-----\n"
+ "Comment: target-key@example.net\n"
+ "\n"
+ "lIYEYd/v/RYJKwYBBAHaRw8BAQdAKoILWXG3yaLb2EniNKQLUjwsrvy5vgAN299J\n"
+ "W5cFbrz+BwMC/uKbCq3sK5H8QVtEQ/IxGmjWNBpy6c8EDlOG4APi4o4VE+bEYD8w\n"
+ "J3Kk/lzSm6ZT5vC6DDASks797omjXD+J7zZ0vtTPvheYi/nsVz2UebQWdGFyZ2V0\n"
+ "LWtleUBleGFtcGxlLm5ldIiUBBMWCgA8FiEEw8h/CjkgsB+eRFDqK3nyHU3RC/wF\n"
+ "AmHf7/0CGwMFCwkIBwIDIgIBBhUKCQgLAgQWAgMBAh4HAheAAAoJECt58h1N0Qv8\n"
+ "rXcBAPxnkXqpp4IY3iTKV5XAdo7Uys7U/joUD73rj2XEvgI1AQDhKK4PLxPhf3ki\n"
+ "FKU0RA7itxzOH+F8bQ5BdYS49jDPCpyLBGHf7/0SCisGAQQBl1UBBQEBB0Dq9rwA\n"
+ "hAA2UFJShFsLFp7+g4uhWDfuDa3VjeIQRM+9QgMBCAf+BwMCMfCTl0LNqsn836t5\n"
+ "f2ZHBuMcNs4JWYmdLAIVaewEHq7zhOsX3iB+/yxwu9g2mXc4XUJ1iQzXLOYwgGov\n"
+ "8jIovrr01hDkSg4rvM9JKMWdd4h4BBgWCgAgFiEEw8h/CjkgsB+eRFDqK3nyHU3R\n"
+ "C/wFAmHf7/0CGwwACgkQK3nyHU3RC/xyfAEAqnMdSv6FTAwAWrYvJqJtSVoEhjMn\n"
+ "3c2qMsu34Bk86/MBAKHbLFmdyePvHaxKeO8CkQDoJzK8rYzw3RAmq/5JsQkL\n"
+ "=rOVf\n"
+ "-----END PGP PRIVATE KEY BLOCK-----\n";
+
+class AddExistingSubkeyJobTest : public QGpgMETest
+{
+ Q_OBJECT
+
+private Q_SLOTS:
+
+ void initTestCase()
+ {
+ QGpgMETest::initTestCase();
+
+ // set up the test fixture for this test
+ qputenv("GNUPGHOME", mGnupgHomeTestFixture.path().toUtf8());
+ QVERIFY(importSecretKeys(testKeyData, 2));
+ }
+
+ void init()
+ {
+ if (GpgME::engineInfo(GpgME::GpgEngine).engineVersion() < requiredVersion) {
+ QSKIP("gpg does not yet support adding an existing subkey to another key via the command API");
+ }
+
+ // set up a copy of the test fixture for each test function
+ mGnupgHomeTestCopy.reset(new QTemporaryDir{});
+ QVERIFY(copyKeyrings(mGnupgHomeTestFixture.path(), mGnupgHomeTestCopy->path()));
+ qputenv("GNUPGHOME", mGnupgHomeTestCopy->path().toUtf8());
+ }
+
+ void testAddExistingSubkeyAsync()
+ {
+ // Get the key the subkey should be added to
+ auto key = getTestKey("target-key@example.net");
+ QVERIFY(!key.isNull());
+
+ // Get the key with the subkey to add
+ auto sourceKey = getTestKey("source-key@example.net", 3);
+ QVERIFY(!sourceKey.isNull());
+
+ auto job = std::unique_ptr<AddExistingSubkeyJob>{openpgp()->addExistingSubkeyJob()};
+ hookUpPassphraseProvider(job.get());
+
+ Error result;
+ connect(job.get(), &AddExistingSubkeyJob::result,
+ job.get(), [this, &result](const Error &result_) {
+ result = result_;
+ Q_EMIT asyncDone();
+ });
+ QVERIFY(!job->start(key, sourceKey.subkey(1)));
+ job.release(); // after the job has been started it's on its own
+
+ QSignalSpy spy (this, SIGNAL(asyncDone()));
+ QVERIFY(spy.wait(QSIGNALSPY_TIMEOUT));
+
+ QVERIFY(result.code() == GPG_ERR_NO_ERROR);
+ key.update();
+ QCOMPARE(key.numSubkeys(), 3u);
+ }
+
+ void testAddExistingSubkeySync()
+ {
+ // Get the key the subkey should be added to
+ auto key = getTestKey("target-key@example.net");
+ QVERIFY(!key.isNull());
+
+ // Get the key with the subkey to add
+ auto sourceKey = getTestKey("source-key@example.net", 3);
+ QVERIFY(!sourceKey.isNull());
+ auto sourceSubkey = sourceKey.subkey(1);
+ QVERIFY(sourceSubkey.expirationTime() == 0);
+
+ auto job = std::unique_ptr<AddExistingSubkeyJob>{openpgp()->addExistingSubkeyJob()};
+ hookUpPassphraseProvider(job.get());
+
+ const auto result = job->exec(key, sourceSubkey);
+
+ QVERIFY(result.code() == GPG_ERR_NO_ERROR);
+ key.update();
+ QCOMPARE(key.numSubkeys(), 3u);
+ QCOMPARE(key.subkey(2).expirationTime(), 0);
+ }
+
+ void testAddExistingSubkeyWithExpiration()
+ {
+ // Get the key the subkey should be added to
+ auto key = getTestKey("target-key@example.net");
+ QVERIFY(!key.isNull());
+
+ // Get the key with the subkey to add
+ auto sourceKey = getTestKey("source-key@example.net", 3);
+ QVERIFY(!sourceKey.isNull());
+ auto sourceSubkey = sourceKey.subkey(2);
+ QVERIFY(sourceSubkey.expirationTime() != 0);
+
+ auto job = std::unique_ptr<AddExistingSubkeyJob>{openpgp()->addExistingSubkeyJob()};
+ hookUpPassphraseProvider(job.get());
+
+ const auto result = job->exec(key, sourceSubkey);
+
+ QVERIFY(result.code() == GPG_ERR_NO_ERROR);
+ key.update();
+ QCOMPARE(key.numSubkeys(), 3u);
+
+ // allow 1 second different expiration because gpg calculates with
+ // expiration as difference to current time and takes current time
+ // several times
+ const auto allowedDeltaTSeconds = 1;
+ const auto expectedExpirationRange = std::make_pair(
+ sourceSubkey.expirationTime() - allowedDeltaTSeconds,
+ sourceSubkey.expirationTime() + allowedDeltaTSeconds);
+ const auto actualExpiration = key.subkey(2).expirationTime();
+ QVERIFY2(actualExpiration >= expectedExpirationRange.first,
+ ("actual: " + std::to_string(actualExpiration) +
+ "; expected: " + std::to_string(expectedExpirationRange.first)).c_str());
+ QVERIFY2(actualExpiration <= expectedExpirationRange.second,
+ ("actual: " + std::to_string(actualExpiration) +
+ "; expected: " + std::to_string(expectedExpirationRange.second)).c_str());
+ }
+
+private:
+ Key getTestKey(const char *pattern, unsigned int expectedSubkeys = 2)
+ {
+ auto ctx = Context::create(OpenPGP);
+ VERIFY_OR_OBJECT(ctx);
+
+ Error err;
+ auto key = ctx->key(pattern, err, /*secret=*/true);
+ VERIFY_OR_OBJECT(!err);
+ VERIFY_OR_OBJECT(!key.isNull());
+ COMPARE_OR_OBJECT(key.numSubkeys(), expectedSubkeys);
+ for (unsigned int i = 0; i < key.numSubkeys(); ++i) {
+ VERIFY_OR_OBJECT(!key.subkey(i).isNull());
+ }
+ return key;
+ }
+
+private:
+ QTemporaryDir mGnupgHomeTestFixture;
+ std::unique_ptr<QTemporaryDir> mGnupgHomeTestCopy;
+};
+
+QTEST_MAIN(AddExistingSubkeyJobTest)
+
+#include "t-addexistingsubkey.moc"
diff --git a/lang/qt/tests/t-changeexpiryjob.cpp b/lang/qt/tests/t-changeexpiryjob.cpp
new file mode 100644
index 0000000..090002f
--- /dev/null
+++ b/lang/qt/tests/t-changeexpiryjob.cpp
@@ -0,0 +1,396 @@
+/* t-changeexpiryjob.cpp
+
+ This file is part of qgpgme, the Qt API binding for gpgme
+ Copyright (c) 2021 g10 Code GmbH
+ Software engineering by Ingo Klöcker <dev@ingo-kloecker.de>
+
+ QGpgME is free software; you can redistribute it and/or
+ modify it under the terms of the GNU General Public License as
+ published by the Free Software Foundation; either version 2 of the
+ License, or (at your option) any later version.
+
+ QGpgME is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
+
+ In addition, as a special exception, the copyright holders give
+ permission to link the code of this program with any edition of
+ the Qt library by Trolltech AS, Norway (or with modified versions
+ of Qt that use the same license as Qt), and distribute linked
+ combinations including the two. You must obey the GNU General
+ Public License in all respects for all of the code used other than
+ Qt. If you modify this file, you may extend this exception to
+ your version of the file, but you are not obligated to do so. If
+ you do not wish to do so, delete this exception statement from
+ your version.
+*/
+
+#ifdef HAVE_CONFIG_H
+ #include "config.h"
+#endif
+
+#include "t-support.h"
+
+#include "changeexpiryjob.h"
+#include "context.h"
+#include "engineinfo.h"
+#include "protocol.h"
+
+#include <QSignalSpy>
+#include <QTemporaryDir>
+#include <QTest>
+
+using namespace QGpgME;
+using namespace GpgME;
+
+class TestChangeExpiryJob: public QGpgMETest
+{
+ Q_OBJECT
+
+private Q_SLOTS:
+ void test_change_expiration_default_without_subkeys()
+ {
+ Error err;
+
+ if (!loopbackSupported()) {
+ return;
+ }
+
+ auto ctx = Context::create(OpenPGP);
+ QVERIFY(ctx);
+
+ // Get the key (alfa@example.net)
+ auto key = ctx->key("A0FF4590BB6122EDEF6E3C542D727CC768697734", err, true);
+ QVERIFY(!err);
+ QVERIFY(!key.isNull());
+ QVERIFY(!key.subkey(0).isNull());
+ QVERIFY(!key.subkey(1).isNull());
+ const auto subkeyExpiration = key.subkey(1).expirationTime();
+
+ {
+ // Create the job
+ auto job = std::unique_ptr<ChangeExpiryJob>{openpgp()->changeExpiryJob()};
+ QVERIFY(job);
+ hookUpPassphraseProvider(job.get());
+
+ // Use defaults of job
+
+ connect(job.get(), &ChangeExpiryJob::result,
+ this, [this] (const GpgME::Error &err2, const QString &, const GpgME::Error &) {
+ Q_EMIT asyncDone();
+ if (err2) {
+ QFAIL(qPrintable(QString("The ChangeExpiryJob failed with '%1'.").arg(err2.asString())));
+ }
+ });
+
+ const auto newExpirationDate = QDateTime::currentDateTime().addDays(1);
+ job->start(key, newExpirationDate);
+ QSignalSpy spy (this, SIGNAL(asyncDone()));
+ QVERIFY(spy.wait(QSIGNALSPY_TIMEOUT));
+
+ // At this point the expiration date should have been changed.
+ key.update();
+
+ // allow a few seconds earlier expiration because job calculates "seconds from now" passed to gpg after it was started
+ const auto expectedExpirationRange = std::make_pair(
+ newExpirationDate.toSecsSinceEpoch() - 10,
+ QDateTime::currentDateTime().addDays(1).toSecsSinceEpoch());
+ {
+ const auto actualExpiration = key.subkey(0).expirationTime();
+ QVERIFY2(actualExpiration >= expectedExpirationRange.first,
+ ("actual: " + std::to_string(actualExpiration) +
+ "; expected: " + std::to_string(expectedExpirationRange.first)).c_str());
+ QVERIFY2(actualExpiration <= expectedExpirationRange.second,
+ ("actual: " + std::to_string(actualExpiration) +
+ "; expected: " + std::to_string(expectedExpirationRange.second)).c_str());
+ }
+ {
+ const auto actualExpiration = key.subkey(1).expirationTime();
+ QCOMPARE(actualExpiration, subkeyExpiration); // unchanged
+ }
+ }
+ }
+
+ void test_change_expiration_default_with_subkeys()
+ {
+ Error err;
+
+ if (!loopbackSupported()) {
+ return;
+ }
+
+ auto ctx = Context::create(OpenPGP);
+ QVERIFY(ctx);
+
+ // Get the key (alfa@example.net)
+ auto key = ctx->key("A0FF4590BB6122EDEF6E3C542D727CC768697734", err, true);
+ QVERIFY(!err);
+ QVERIFY(!key.isNull());
+ QVERIFY(!key.subkey(0).isNull());
+ QVERIFY(!key.subkey(1).isNull());
+ const auto primaryKeyExpiration = key.subkey(0).expirationTime();
+
+ {
+ // Create the job
+ auto job = std::unique_ptr<ChangeExpiryJob>{openpgp()->changeExpiryJob()};
+ QVERIFY(job);
+ hookUpPassphraseProvider(job.get());
+
+ // Use defaults of job
+
+ connect(job.get(), &ChangeExpiryJob::result,
+ this, [this] (const GpgME::Error &err2, const QString &, const GpgME::Error &) {
+ Q_EMIT asyncDone();
+ if (err2) {
+ QFAIL(qPrintable(QString("The ChangeExpiryJob failed with '%1'.").arg(err2.asString())));
+ }
+ });
+
+ const auto newExpirationDate = QDateTime::currentDateTime().addDays(2);
+ job->start(key, newExpirationDate, {key.subkey(1)});
+ QSignalSpy spy (this, SIGNAL(asyncDone()));
+ QVERIFY(spy.wait(QSIGNALSPY_TIMEOUT));
+
+ // At this point the expiration date should have been changed.
+ key.update();
+
+ // allow a few seconds earlier expiration because job calculates "seconds from now" passed to gpg after it was started
+ const auto expectedExpirationRange = std::make_pair(
+ newExpirationDate.toSecsSinceEpoch() - 10,
+ QDateTime::currentDateTime().addDays(2).toSecsSinceEpoch());
+ {
+ const auto actualExpiration = key.subkey(0).expirationTime();
+ QCOMPARE(actualExpiration, primaryKeyExpiration); // unchanged
+ }
+ {
+ const auto actualExpiration = key.subkey(1).expirationTime();
+ QVERIFY2(actualExpiration >= expectedExpirationRange.first,
+ ("actual: " + std::to_string(actualExpiration) +
+ "; expected: " + std::to_string(expectedExpirationRange.first)).c_str());
+ QVERIFY2(actualExpiration <= expectedExpirationRange.second,
+ ("actual: " + std::to_string(actualExpiration) +
+ "; expected: " + std::to_string(expectedExpirationRange.second)).c_str());
+ }
+ }
+ }
+
+ void test_change_expiration_update_primary_key_without_subkeys()
+ {
+ Error err;
+
+ if (!loopbackSupported()) {
+ return;
+ }
+
+ auto ctx = Context::create(OpenPGP);
+ QVERIFY(ctx);
+
+ // Get the key (alfa@example.net)
+ auto key = ctx->key("A0FF4590BB6122EDEF6E3C542D727CC768697734", err, true);
+ QVERIFY(!err);
+ QVERIFY(!key.isNull());
+ QVERIFY(!key.subkey(0).isNull());
+ QVERIFY(!key.subkey(1).isNull());
+ const auto subkeyExpiration = key.subkey(1).expirationTime();
+
+ {
+ // Create the job
+ auto job = std::unique_ptr<ChangeExpiryJob>{openpgp()->changeExpiryJob()};
+ QVERIFY(job);
+ hookUpPassphraseProvider(job.get());
+
+ // Set up the job
+ job->setOptions(ChangeExpiryJob::UpdatePrimaryKey);
+
+ connect(job.get(), &ChangeExpiryJob::result,
+ this, [this] (const GpgME::Error &err2, const QString &, const GpgME::Error &) {
+ Q_EMIT asyncDone();
+ if (err2) {
+ QFAIL(qPrintable(QString("The ChangeExpiryJob failed with '%1'.").arg(err2.asString())));
+ }
+ });
+
+ const auto newExpirationDate = QDateTime::currentDateTime().addDays(3);
+ job->start(key, newExpirationDate, {});
+ QSignalSpy spy (this, SIGNAL(asyncDone()));
+ QVERIFY(spy.wait(QSIGNALSPY_TIMEOUT));
+
+ // At this point the expiration date should have been changed.
+ key.update();
+
+ // allow a few seconds earlier expiration because job calculates "seconds from now" passed to gpg after it was started
+ const auto expectedExpirationRange = std::make_pair(
+ newExpirationDate.toSecsSinceEpoch() - 10,
+ QDateTime::currentDateTime().addDays(3).toSecsSinceEpoch());
+ {
+ const auto actualExpiration = key.subkey(0).expirationTime();
+ QVERIFY2(actualExpiration >= expectedExpirationRange.first,
+ ("actual: " + std::to_string(actualExpiration) +
+ "; expected: " + std::to_string(expectedExpirationRange.first)).c_str());
+ QVERIFY2(actualExpiration <= expectedExpirationRange.second,
+ ("actual: " + std::to_string(actualExpiration) +
+ "; expected: " + std::to_string(expectedExpirationRange.second)).c_str());
+ }
+ {
+ const auto actualExpiration = key.subkey(1).expirationTime();
+ QCOMPARE(actualExpiration, subkeyExpiration); // unchanged
+ }
+ }
+ }
+
+ void test_change_expiration_update_primary_key_with_subkeys()
+ {
+ Error err;
+
+ if (!loopbackSupported()) {
+ return;
+ }
+
+ auto ctx = Context::create(OpenPGP);
+ QVERIFY(ctx);
+
+ // Get the key (alfa@example.net)
+ auto key = ctx->key("A0FF4590BB6122EDEF6E3C542D727CC768697734", err, true);
+ QVERIFY(!err);
+ QVERIFY(!key.isNull());
+ QVERIFY(!key.subkey(0).isNull());
+ QVERIFY(!key.subkey(1).isNull());
+
+ {
+ // Create the job
+ auto job = std::unique_ptr<ChangeExpiryJob>{openpgp()->changeExpiryJob()};
+ QVERIFY(job);
+ hookUpPassphraseProvider(job.get());
+
+ // Set up the job
+ job->setOptions(ChangeExpiryJob::UpdatePrimaryKey);
+
+ connect(job.get(), &ChangeExpiryJob::result,
+ this, [this] (const GpgME::Error &err2, const QString &, const GpgME::Error &) {
+ Q_EMIT asyncDone();
+ if (err2) {
+ QFAIL(qPrintable(QString("The ChangeExpiryJob failed with '%1'.").arg(err2.asString())));
+ }
+ });
+
+ const auto newExpirationDate = QDateTime::currentDateTime().addDays(4);
+ job->start(key, newExpirationDate, {key.subkey(1)});
+ QSignalSpy spy (this, SIGNAL(asyncDone()));
+ QVERIFY(spy.wait(QSIGNALSPY_TIMEOUT));
+
+ // At this point the expiration date should have been changed.
+ key.update();
+
+ // allow a few seconds earlier expiration because job calculates "seconds from now" passed to gpg after it was started
+ const auto expectedExpirationRange = std::make_pair(
+ newExpirationDate.toSecsSinceEpoch() - 10,
+ QDateTime::currentDateTime().addDays(4).toSecsSinceEpoch());
+ {
+ const auto actualExpiration = key.subkey(0).expirationTime();
+ QVERIFY2(actualExpiration >= expectedExpirationRange.first,
+ ("actual: " + std::to_string(actualExpiration) +
+ "; expected: " + std::to_string(expectedExpirationRange.first)).c_str());
+ QVERIFY2(actualExpiration <= expectedExpirationRange.second,
+ ("actual: " + std::to_string(actualExpiration) +
+ "; expected: " + std::to_string(expectedExpirationRange.second)).c_str());
+ }
+ {
+ const auto actualExpiration = key.subkey(1).expirationTime();
+ QVERIFY2(actualExpiration >= expectedExpirationRange.first,
+ ("actual: " + std::to_string(actualExpiration) +
+ "; expected: " + std::to_string(expectedExpirationRange.first)).c_str());
+ QVERIFY2(actualExpiration <= expectedExpirationRange.second,
+ ("actual: " + std::to_string(actualExpiration) +
+ "; expected: " + std::to_string(expectedExpirationRange.second)).c_str());
+ }
+ }
+ }
+
+ void test_change_expiration_update_primary_key_and_all_subkeys()
+ {
+ Error err;
+
+ if (!loopbackSupported()) {
+ return;
+ }
+
+ auto ctx = Context::create(OpenPGP);
+ QVERIFY(ctx);
+
+ // Get the key (alfa@example.net)
+ auto key = ctx->key("A0FF4590BB6122EDEF6E3C542D727CC768697734", err, true);
+ QVERIFY(!err);
+ QVERIFY(!key.isNull());
+ QVERIFY(!key.subkey(0).isNull());
+ QVERIFY(!key.subkey(1).isNull());
+
+ {
+ // Create the job
+ auto job = std::unique_ptr<ChangeExpiryJob>{openpgp()->changeExpiryJob()};
+ QVERIFY(job);
+ hookUpPassphraseProvider(job.get());
+
+ // Set up the job
+ job->setOptions(ChangeExpiryJob::UpdatePrimaryKey | ChangeExpiryJob::UpdateAllSubkeys);
+
+ connect(job.get(), &ChangeExpiryJob::result,
+ this, [this] (const GpgME::Error &err2, const QString &, const GpgME::Error &) {
+ Q_EMIT asyncDone();
+ if (err2) {
+ QFAIL(qPrintable(QString("The ChangeExpiryJob failed with '%1'.").arg(err2.asString())));
+ }
+ });
+
+ const auto newExpirationDate = QDateTime::currentDateTime().addDays(5);
+ job->start(key, newExpirationDate);
+ QSignalSpy spy (this, SIGNAL(asyncDone()));
+ QVERIFY(spy.wait(QSIGNALSPY_TIMEOUT));
+
+ // At this point the expiration date should have been changed.
+ key.update();
+
+ // allow a few seconds earlier expiration because job calculates "seconds from now" passed to gpg after it was started
+ const auto expectedExpirationRange = std::make_pair(
+ newExpirationDate.toSecsSinceEpoch() - 10,
+ QDateTime::currentDateTime().addDays(5).toSecsSinceEpoch());
+ {
+ const auto actualExpiration = key.subkey(0).expirationTime();
+ QVERIFY2(actualExpiration >= expectedExpirationRange.first,
+ ("actual: " + std::to_string(actualExpiration) +
+ "; expected: " + std::to_string(expectedExpirationRange.first)).c_str());
+ QVERIFY2(actualExpiration <= expectedExpirationRange.second,
+ ("actual: " + std::to_string(actualExpiration) +
+ "; expected: " + std::to_string(expectedExpirationRange.second)).c_str());
+ }
+ {
+ const auto actualExpiration = key.subkey(1).expirationTime();
+ QVERIFY2(actualExpiration >= expectedExpirationRange.first,
+ ("actual: " + std::to_string(actualExpiration) +
+ "; expected: " + std::to_string(expectedExpirationRange.first)).c_str());
+ QVERIFY2(actualExpiration <= expectedExpirationRange.second,
+ ("actual: " + std::to_string(actualExpiration) +
+ "; expected: " + std::to_string(expectedExpirationRange.second)).c_str());
+ }
+ }
+ }
+
+ void initTestCase()
+ {
+ QGpgMETest::initTestCase();
+ const QString gpgHome = qgetenv("GNUPGHOME");
+ QVERIFY(copyKeyrings(gpgHome, mDir.path()));
+ qputenv("GNUPGHOME", mDir.path().toUtf8());
+ }
+
+private:
+ QTemporaryDir mDir;
+};
+
+QTEST_MAIN(TestChangeExpiryJob)
+
+#include "t-changeexpiryjob.moc"
diff --git a/lang/qt/tests/t-config.cpp b/lang/qt/tests/t-config.cpp
index 9ec9566..b84dbfd 100644
--- a/lang/qt/tests/t-config.cpp
+++ b/lang/qt/tests/t-config.cpp
@@ -57,27 +57,24 @@ private Q_SLOTS:
// be unsupported in older versions.
return;
}
- // First set compliance to de-vs
auto conf = cryptoConfig();
QVERIFY(conf);
- auto entry = conf->entry(QStringLiteral("gpg"),
- QStringLiteral("Configuration"),
- QStringLiteral("compliance"));
+ auto entry = conf->entry(QStringLiteral("gpg"), QStringLiteral("compliance"));
QVERIFY(entry);
+ const auto defaultValue = entry->defaultValue().toString();
+ QCOMPARE(defaultValue, QStringLiteral("gnupg"));
+
entry->setStringValue("de-vs");
conf->sync(true);
conf->clear();
- entry = conf->entry(QStringLiteral("gpg"),
- QStringLiteral("Configuration"),
- QStringLiteral("compliance"));
+ entry = conf->entry(QStringLiteral("gpg"), QStringLiteral("compliance"));
QCOMPARE(entry->stringValue(), QStringLiteral("de-vs"));
+
entry->resetToDefault();
conf->sync(true);
conf->clear();
- entry = conf->entry(QStringLiteral("gpg"),
- QStringLiteral("Configuration"),
- QStringLiteral("compliance"));
- QCOMPARE(entry->stringValue(), QStringLiteral("gnupg"));
+ entry = conf->entry(QStringLiteral("gpg"), QStringLiteral("compliance"));
+ QCOMPARE(entry->stringValue(), defaultValue);
}
void initTestCase()
diff --git a/lang/qt/tests/t-encrypt.cpp b/lang/qt/tests/t-encrypt.cpp
index 9ad1033..6a4c68e 100644
--- a/lang/qt/tests/t-encrypt.cpp
+++ b/lang/qt/tests/t-encrypt.cpp
@@ -63,9 +63,6 @@ class EncryptionTest : public QGpgMETest
{
Q_OBJECT
-Q_SIGNALS:
- void asyncDone();
-
private Q_SLOTS:
void testSimpleEncryptDecrypt()
@@ -92,10 +89,7 @@ private Q_SLOTS:
return;
}
auto decJob = openpgp()->decryptJob();
- auto ctx = Job::context(decJob);
- TestPassphraseProvider provider;
- ctx->setPassphraseProvider(&provider);
- ctx->setPinentryMode(Context::PinentryLoopback);
+ hookUpPassphraseProvider(decJob);
QByteArray plainText;
auto decResult = decJob->exec(cipherText, plainText);
QVERIFY(!decResult.error());
@@ -163,10 +157,8 @@ private Q_SLOTS:
return;
}
auto job = openpgp()->encryptJob();
+ hookUpPassphraseProvider(job);
auto ctx = Job::context(job);
- TestPassphraseProvider provider;
- ctx->setPassphraseProvider(&provider);
- ctx->setPinentryMode(Context::PinentryLoopback);
ctx->setArmor(true);
ctx->setTextMode(true);
QByteArray cipherText;
@@ -179,9 +171,7 @@ private Q_SLOTS:
killAgent(mDir.path());
auto decJob = openpgp()->decryptJob();
- auto ctx2 = Job::context(decJob);
- ctx2->setPassphraseProvider(&provider);
- ctx2->setPinentryMode(Context::PinentryLoopback);
+ hookUpPassphraseProvider(decJob);
QByteArray plainText;
auto decResult = decJob->exec(cipherText, plainText);
QVERIFY(!result.error());
@@ -204,13 +194,9 @@ private Q_SLOTS:
delete listjob;
auto job = openpgp()->signEncryptJob(/*ASCII Armor */true, /* Textmode */ true);
-
- auto encSignCtx = Job::context(job);
- TestPassphraseProvider provider1;
- encSignCtx->setPassphraseProvider(&provider1);
- encSignCtx->setPinentryMode(Context::PinentryLoopback);
-
QVERIFY(job);
+ hookUpPassphraseProvider(job);
+
QByteArray cipherText;
auto result = job->exec(keys, keys, QStringLiteral("Hello World").toUtf8(), Context::AlwaysTrust, cipherText);
delete job;
@@ -225,10 +211,8 @@ private Q_SLOTS:
}
auto decJob = openpgp()->decryptJob();
+ hookUpPassphraseProvider(decJob);
auto ctx = Job::context(decJob);
- TestPassphraseProvider provider;
- ctx->setPassphraseProvider(&provider);
- ctx->setPinentryMode(Context::PinentryLoopback);
ctx->setDecryptionFlags(Context::DecryptUnwrap);
QByteArray plainText;
@@ -269,9 +253,8 @@ private:
delete listjob;
auto job = openpgp()->encryptJob();
+ hookUpPassphraseProvider(job);
auto ctx = Job::context(job);
- ctx->setPassphraseProvider(new TestPassphraseProvider);
- ctx->setPinentryMode(Context::PinentryLoopback);
ctx->setArmor(true);
ctx->setTextMode(true);
QByteArray cipherText;
@@ -297,9 +280,8 @@ private:
agentConf.close();
auto decJob = openpgp()->decryptJob();
+ hookUpPassphraseProvider(decJob);
auto ctx2 = Job::context(decJob);
- ctx2->setPassphraseProvider(new TestPassphraseProvider);
- ctx2->setPinentryMode(Context::PinentryLoopback);
ctx2->setTextMode(true);
QByteArray plainText;
auto decResult = decJob->exec(cipherText, plainText);
diff --git a/lang/qt/tests/t-import.cpp b/lang/qt/tests/t-import.cpp
new file mode 100644
index 0000000..33e242f
--- /dev/null
+++ b/lang/qt/tests/t-import.cpp
@@ -0,0 +1,169 @@
+/* t-import.cpp
+
+ This file is part of qgpgme, the Qt API binding for gpgme
+ Copyright (c) 2021 g10 Code GmbH
+ Software engineering by Ingo Klöcker <dev@ingo-kloecker.de>
+
+ QGpgME is free software; you can redistribute it and/or
+ modify it under the terms of the GNU General Public License as
+ published by the Free Software Foundation; either version 2 of the
+ License, or (at your option) any later version.
+
+ QGpgME is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
+
+ In addition, as a special exception, the copyright holders give
+ permission to link the code of this program with any edition of
+ the Qt library by Trolltech AS, Norway (or with modified versions
+ of Qt that use the same license as Qt), and distribute linked
+ combinations including the two. You must obey the GNU General
+ Public License in all respects for all of the code used other than
+ Qt. If you modify this file, you may extend this exception to
+ your version of the file, but you are not obligated to do so. If
+ you do not wish to do so, delete this exception statement from
+ your version.
+*/
+
+#ifdef HAVE_CONFIG_H
+ #include "config.h"
+#endif
+
+#include "t-support.h"
+
+#include "context.h"
+#include "engineinfo.h"
+#include "protocol.h"
+#include "importjob.h"
+
+#include <importresult.h>
+
+#include <QDebug>
+#include <QSignalSpy>
+#include <QTemporaryDir>
+#include <QTest>
+
+using namespace QGpgME;
+using namespace GpgME;
+
+class ImportTest : public QGpgMETest
+{
+ Q_OBJECT
+
+private:
+ QTemporaryDir tempGpgHome;
+
+private Q_SLOTS:
+ void initTestCase()
+ {
+ QGpgMETest::initTestCase();
+ QVERIFY2(tempGpgHome.isValid(), "Failed to create temporary GNUPGHOME");
+ qputenv("GNUPGHOME", tempGpgHome.path().toLocal8Bit());
+ }
+
+ void testImportWithImportFilter()
+ {
+ if (GpgME::engineInfo(GpgME::GpgEngine).engineVersion() < "2.1.14") {
+ QSKIP("gpg does not yet support the --import-filter option");
+ }
+
+ // pub ed25519 2021-12-15 [SC]
+ // E7A0841292ACC9465D3142652FB3A6F51FBF28A2
+ // uid [ultimate] importWithImportFilter@example.com
+ // uid [ultimate] importWithImportFilter@example.net
+ // sub cv25519 2021-12-15 [E]
+ static const char keyFpr[] = "E7A0841292ACC9465D3142652FB3A6F51FBF28A2";
+ static const char keyData[] =
+ "-----BEGIN PGP PUBLIC KEY BLOCK-----\n"
+ "\n"
+ "mDMEYbm2PhYJKwYBBAHaRw8BAQdACzxBWtNNsmJ6rzpZkjh1yBe+Ajsk9NR8umEu\n"
+ "Da3HLgG0ImltcG9ydFdpdGhJbXBvcnRGaWx0ZXJAZXhhbXBsZS5uZXSIlAQTFgoA\n"
+ "PBYhBOeghBKSrMlGXTFCZS+zpvUfvyiiBQJhubY+AhsDBQsJCAcCAyICAQYVCgkI\n"
+ "CwIEFgIDAQIeBwIXgAAKCRAvs6b1H78oosRgAQCc/ke6q076nvzIE2UzT83JK/B6\n"
+ "lxSV7Fb8bKltOMpvsAD+Phap3EzA8jdMyKoO0FM926bw5lX7QROfeZ/JBYqyPwC0\n"
+ "ImltcG9ydFdpdGhJbXBvcnRGaWx0ZXJAZXhhbXBsZS5jb22IlAQTFgoAPBYhBOeg\n"
+ "hBKSrMlGXTFCZS+zpvUfvyiiBQJhubZlAhsDBQsJCAcCAyICAQYVCgkICwIEFgID\n"
+ "AQIeBwIXgAAKCRAvs6b1H78oohPWAQC/u9UXzkxRkrB2huaTZCsyimWEGZIMmxWd\n"
+ "tE+vN9/IvQD/Yzia+xRS6yca3Yz6iW8xS844ZqRxvkUEHjtJXSOzagm4OARhubY+\n"
+ "EgorBgEEAZdVAQUBAQdANQFjmDctY3N0/ELPZtj9tapwFs4vrmTVpx/SCfZmihkD\n"
+ "AQgHiHgEGBYKACAWIQTnoIQSkqzJRl0xQmUvs6b1H78oogUCYbm2PgIbDAAKCRAv\n"
+ "s6b1H78oovGyAP41ySzvvDpV7XDJBOAFxvWLmywa5IcO7Lrg7y1efoWj0AD+Kk/B\n"
+ "s7jGLdoG51h670h50MMoYCANB6MwAdSP+qZUlQg=\n"
+ "=/3O0\n"
+ "-----END PGP PUBLIC KEY BLOCK-----\n";
+
+ auto *job = openpgp()->importJob();
+ job->setImportFilter(QLatin1String{"keep-uid=mbox = importWithImportFilter@example.net"});
+ connect(job, &ImportJob::result, this,
+ [this](ImportResult result, QString, Error)
+ {
+ QVERIFY(!result.error());
+ QVERIFY(!result.imports().empty());
+ QVERIFY(result.numImported());
+ Q_EMIT asyncDone();
+ });
+ job->start(QByteArray{keyData});
+ QSignalSpy spy (this, SIGNAL(asyncDone()));
+ QVERIFY(spy.wait());
+
+ auto ctx = Context::createForProtocol(GpgME::OpenPGP);
+ GpgME::Error err;
+ const auto key = ctx->key(keyFpr, err, false);
+ QVERIFY(!key.isNull());
+ QCOMPARE(key.numUserIDs(), 1);
+ QCOMPARE(key.userID(0).id(), "importWithImportFilter@example.net");
+ }
+
+ void testImportWithKeyOrigin()
+ {
+ if (GpgME::engineInfo(GpgME::GpgEngine).engineVersion() < "2.1.22") {
+ QSKIP("gpg does not yet support the --key-origin option");
+ }
+
+ static const char keyFpr[] = "5C5C428FABCC20F6913464BCCA6FB442887289B3";
+ static const char keyData[] =
+ "-----BEGIN PGP PUBLIC KEY BLOCK-----\n"
+ "\n"
+ "mDMEYbhuixYJKwYBBAHaRw8BAQdAulOM3IksCjdOJluEVlwalD8oZ5oa6wCw3EgW\n"
+ "NswXXb60H2ltcG9ydFdpdGhLZXlPcmlnaW5AZXhhbXBsZS5uZXSIlAQTFgoAPBYh\n"
+ "BFxcQo+rzCD2kTRkvMpvtEKIcomzBQJhuG6LAhsDBQsJCAcCAyICAQYVCgkICwIE\n"
+ "FgIDAQIeBwIXgAAKCRDKb7RCiHKJs+cIAQDaeoOw1OCAGpZQb8xJmLJHul5dLLzU\n"
+ "RBdHauMx9NROmQEA23QUVedc7walQjNKFzyIJA/YqRdbAKPiLonRBmxk9Ay4OARh\n"
+ "uG6LEgorBgEEAZdVAQUBAQdAMVdO9mNWIP/q8PtNOnBGlPyhx/vs07sF5sXk50A+\n"
+ "61QDAQgHiHgEGBYKACAWIQRcXEKPq8wg9pE0ZLzKb7RCiHKJswUCYbhuiwIbDAAK\n"
+ "CRDKb7RCiHKJs/x6AP0SEbZqW4iLCz2i1JntQghK5qpSZOVqsBTcARd6pcJ/cwEA\n"
+ "mrwskWazuS9+GVbHT5RATWOXnGaj+AICSDPE6qHtGgA=\n"
+ "=putz\n"
+ "-----END PGP PUBLIC KEY BLOCK-----\n";
+
+ auto *job = openpgp()->importJob();
+ job->setKeyOrigin(GpgME::Key::OriginWKD, "https://example.net");
+ connect(job, &ImportJob::result, this,
+ [this](ImportResult result, QString, Error)
+ {
+ QVERIFY(!result.error());
+ QVERIFY(!result.imports().empty());
+ QVERIFY(result.numImported());
+ Q_EMIT asyncDone();
+ });
+ job->start(QByteArray{keyData});
+ QSignalSpy spy (this, SIGNAL(asyncDone()));
+ QVERIFY(spy.wait());
+
+ auto ctx = Context::createForProtocol(GpgME::OpenPGP);
+ GpgME::Error err;
+ const auto key = ctx->key(keyFpr, err, false);
+ QVERIFY(!key.isNull());
+ QVERIFY(key.origin() == Key::OriginWKD);
+ // the origin URL is currently not available in GpgME
+ }
+};
+
+QTEST_MAIN(ImportTest)
+
+#include "t-import.moc"
diff --git a/lang/qt/tests/t-keylist.cpp b/lang/qt/tests/t-keylist.cpp
index 5875dfb..e481dfe 100644
--- a/lang/qt/tests/t-keylist.cpp
+++ b/lang/qt/tests/t-keylist.cpp
@@ -57,9 +57,6 @@ class KeyListTest : public QGpgMETest
{
Q_OBJECT
-Q_SIGNALS:
- void asyncDone();
-
private Q_SLOTS:
void testSingleKeyListSync()
{
@@ -151,7 +148,7 @@ private Q_SLOTS:
delete job;
QVERIFY(!result.error());
- QCOMPARE(secKeys.size(), 2u);
+ QCOMPARE(secKeys.size(), static_cast<decltype(secKeys.size())>(2));
std::vector<std::string> secKeyFingerprints = std::accumulate(secKeys.begin(), secKeys.end(), std::vector<std::string>(), accumulateFingerprints);
QCOMPARE(secKeyFingerprints, std::vector<std::string>({
"23FD347A419429BACCD5E72D6BC4778054ACD246",
@@ -162,7 +159,7 @@ private Q_SLOTS:
QVERIFY(secKeys[0].subkeys()[0].keyGrip());
}
- QCOMPARE(pubKeys.size(), 26u);
+ QCOMPARE(pubKeys.size(), static_cast<decltype(pubKeys.size())>(26));
std::vector<std::string> pubKeyFingerprints = std::accumulate(pubKeys.begin(), pubKeys.end(), std::vector<std::string>(), accumulateFingerprints);
QCOMPARE(pubKeyFingerprints, std::vector<std::string>({
"045B2334ADD69FC221076841A5E67F7FA3AE3EA1",
diff --git a/lang/qt/tests/t-keylocate.cpp b/lang/qt/tests/t-keylocate.cpp
index 6d00da3..d84249c 100644
--- a/lang/qt/tests/t-keylocate.cpp
+++ b/lang/qt/tests/t-keylocate.cpp
@@ -51,9 +51,6 @@ class KeyLocateTest : public QGpgMETest
{
Q_OBJECT
-Q_SIGNALS:
- void asyncDone();
-
private Q_SLOTS:
#ifdef DO_ONLINE_TESTS
diff --git a/lang/qt/tests/t-ownertrust.cpp b/lang/qt/tests/t-ownertrust.cpp
index 093c21e..31d2247 100644
--- a/lang/qt/tests/t-ownertrust.cpp
+++ b/lang/qt/tests/t-ownertrust.cpp
@@ -51,9 +51,6 @@ class ChangeOwnerTrustTest: public QGpgMETest
{
Q_OBJECT
-Q_SIGNALS:
- void asyncDone();
-
private Q_SLOTS:
void testChangeOwnerTrust()
diff --git a/lang/qt/tests/t-remarks.cpp b/lang/qt/tests/t-remarks.cpp
index c1880a7..f9a901a 100644
--- a/lang/qt/tests/t-remarks.cpp
+++ b/lang/qt/tests/t-remarks.cpp
@@ -54,9 +54,6 @@ class TestRemarks: public QGpgMETest
{
Q_OBJECT
-Q_SIGNALS:
- void asyncDone();
-
public:
// This test is disabled (no slot) because the behavior
// is not clearly defined. Better to prevent that
@@ -77,12 +74,7 @@ public:
// Create the job
auto job = openpgp()->signKeyJob();
QVERIFY (job);
-
- // Hack in the passphrase provider
- auto jobCtx = Job::context(job);
- TestPassphraseProvider provider;
- jobCtx->setPassphraseProvider(&provider);
- jobCtx->setPinentryMode(Context::PinentryLoopback);
+ hookUpPassphraseProvider(job);
// Setup the job
job->setExportable(false);
@@ -133,12 +125,7 @@ private Q_SLOTS:
// Create the job
auto job = openpgp()->signKeyJob();
QVERIFY (job);
-
- // Hack in the passphrase provider
- auto jobCtx = Job::context(job);
- TestPassphraseProvider provider;
- jobCtx->setPassphraseProvider(&provider);
- jobCtx->setPinentryMode(Context::PinentryLoopback);
+ hookUpPassphraseProvider(job);
// Setup the job
job->setExportable(true);
@@ -170,11 +157,7 @@ private Q_SLOTS:
// Now replace the remark
auto job3 = openpgp()->signKeyJob();
QVERIFY (job3);
-
- // Hack in the passphrase provider
- auto jobCtx3 = Job::context(job3);
- jobCtx3->setPassphraseProvider(&provider);
- jobCtx3->setPinentryMode(Context::PinentryLoopback);
+ hookUpPassphraseProvider(job3);
// Setup the job
job3->setExportable(false);
@@ -229,12 +212,7 @@ private Q_SLOTS:
// Create the job
auto job = openpgp()->signKeyJob();
QVERIFY (job);
-
- // Hack in the passphrase provider
- auto jobCtx = Job::context(job);
- TestPassphraseProvider provider;
- jobCtx->setPassphraseProvider(&provider);
- jobCtx->setPinentryMode(Context::PinentryLoopback);
+ hookUpPassphraseProvider(job);
// Setup the first job
job->setExportable(false);
@@ -257,11 +235,7 @@ private Q_SLOTS:
// Now another remark from zulu
auto job3 = openpgp()->signKeyJob();
QVERIFY (job3);
-
- // Hack in the passphrase provider
- auto jobCtx3 = Job::context(job3);
- jobCtx3->setPassphraseProvider(&provider);
- jobCtx3->setPinentryMode(Context::PinentryLoopback);
+ hookUpPassphraseProvider(job3);
// Setup the job
job3->setExportable(false);
@@ -315,12 +289,7 @@ private Q_SLOTS:
// Create the job
auto job = openpgp()->signKeyJob();
QVERIFY (job);
-
- // Hack in the passphrase provider
- auto jobCtx = Job::context(job);
- TestPassphraseProvider provider;
- jobCtx->setPassphraseProvider(&provider);
- jobCtx->setPinentryMode(Context::PinentryLoopback);
+ hookUpPassphraseProvider(job);
// Setup the job
job->setExportable(false);
@@ -352,11 +321,7 @@ private Q_SLOTS:
// Now replace the remark
auto job3 = openpgp()->signKeyJob();
QVERIFY (job3);
-
- // Hack in the passphrase provider
- auto jobCtx3 = Job::context(job3);
- jobCtx3->setPassphraseProvider(&provider);
- jobCtx3->setPinentryMode(Context::PinentryLoopback);
+ hookUpPassphraseProvider(job3);
// Setup the job
job3->setExportable(false);
@@ -405,12 +370,7 @@ private Q_SLOTS:
// Create the job
auto job = openpgp()->signKeyJob();
QVERIFY (job);
-
- // Hack in the passphrase provider
- auto jobCtx = Job::context(job);
- TestPassphraseProvider provider;
- jobCtx->setPassphraseProvider(&provider);
- jobCtx->setPinentryMode(Context::PinentryLoopback);
+ hookUpPassphraseProvider(job);
// Setup the job
job->setExportable(false);
@@ -441,11 +401,7 @@ private Q_SLOTS:
// Try to replace it without dupeOK
auto job2 = openpgp()->signKeyJob();
QVERIFY (job2);
-
- // Hack in the passphrase provider
- auto jobCtx2 = Job::context(job2);
- jobCtx2->setPassphraseProvider(&provider);
- jobCtx2->setPinentryMode(Context::PinentryLoopback);
+ hookUpPassphraseProvider(job2);
// Setup the job
job2->setExportable(false);
@@ -466,11 +422,7 @@ private Q_SLOTS:
// Now replace the remark
auto job3 = openpgp()->signKeyJob();
QVERIFY (job3);
-
- // Hack in the passphrase provider
- auto jobCtx3 = Job::context(job3);
- jobCtx3->setPassphraseProvider(&provider);
- jobCtx3->setPinentryMode(Context::PinentryLoopback);
+ hookUpPassphraseProvider(job3);
// Setup the job
job3->setExportable(false);
diff --git a/lang/qt/tests/t-support.cpp b/lang/qt/tests/t-support.cpp
index 7b16ccc..6db082f 100644
--- a/lang/qt/tests/t-support.cpp
+++ b/lang/qt/tests/t-support.cpp
@@ -35,7 +35,10 @@
#endif
#include "t-support.h"
-#include "context.h"
+
+#include "importjob.h"
+#include "job.h"
+#include "protocol.h"
#include <QTest>
@@ -43,8 +46,14 @@
#include <QCoreApplication>
#include <QObject>
#include <QDir>
+#include <QSignalSpy>
+#include "context.h"
#include "engineinfo.h"
+#include "importresult.h"
+
+using namespace GpgME;
+using namespace QGpgME;
void QGpgMETest::initTestCase()
{
@@ -59,6 +68,12 @@ void QGpgMETest::cleanupTestCase()
killAgent();
}
+// static
+bool QGpgMETest::doOnlineTests()
+{
+ return !qgetenv("DO_ONLINE_TESTS").isEmpty();
+}
+
bool QGpgMETest::copyKeyrings(const QString &src, const QString &dest)
{
bool is21dir = QFileInfo(src + QDir::separator() + QStringLiteral("pubring.kbx")).exists();
@@ -86,6 +101,41 @@ bool QGpgMETest::copyKeyrings(const QString &src, const QString &dest)
return true;
}
+bool QGpgMETest::importSecretKeys(const char *keyData, int expectedKeys)
+{
+ auto job = std::unique_ptr<ImportJob>{openpgp()->importJob()};
+ VERIFY_OR_FALSE(job);
+ hookUpPassphraseProvider(job.get());
+
+ ImportResult result;
+ connect(job.get(), &ImportJob::result,
+ this, [this, &result](const ImportResult &result_) {
+ result = result_;
+ Q_EMIT asyncDone();
+ });
+ VERIFY_OR_FALSE(!job->start(keyData));
+ job.release(); // after the job has been started it's on its own
+
+ QSignalSpy spy (this, SIGNAL(asyncDone()));
+ VERIFY_OR_FALSE(spy.wait(QSIGNALSPY_TIMEOUT));
+ VERIFY_OR_FALSE(!result.error());
+ VERIFY_OR_FALSE(!result.imports().empty());
+ COMPARE_OR_FALSE(result.numSecretKeysImported(), expectedKeys);
+
+ return true;
+}
+
+void QGpgMETest::hookUpPassphraseProvider(GpgME::Context *context)
+{
+ context->setPassphraseProvider(&mPassphraseProvider);
+ context->setPinentryMode(Context::PinentryLoopback);
+}
+
+void QGpgMETest::hookUpPassphraseProvider(QGpgME::Job *job)
+{
+ hookUpPassphraseProvider(Job::context(job));
+}
+
void killAgent(const QString& dir)
{
QProcess proc;
diff --git a/lang/qt/tests/t-support.h b/lang/qt/tests/t-support.h
index 77bef56..ecafe2f 100644
--- a/lang/qt/tests/t-support.h
+++ b/lang/qt/tests/t-support.h
@@ -34,11 +34,57 @@
#include "interfaces/passphraseprovider.h"
#include <QObject>
+#include <QTest>
#include <gpg-error.h>
namespace GpgME
{
+class Context;
+}
+
+namespace QGpgME
+{
+class Job;
+}
+
+/// generic variant of QVERIFY returning \a returnValue on failure
+#define VERIFY_OR_RETURN_VALUE(statement, returnValue) \
+do {\
+ if (!QTest::qVerify(static_cast<bool>(statement), #statement, "", __FILE__, __LINE__))\
+ return returnValue;\
+} while (false)
+
+/// generic variant of QCOMPARE returning \a returnValue on failure
+#define COMPARE_OR_RETURN_VALUE(actual, expected, returnValue) \
+do {\
+ if (!QTest::qCompare(actual, expected, #actual, #expected, __FILE__, __LINE__))\
+ return returnValue;\
+} while (false)
+
+/// variant of QVERIFY returning a default constructed object on failure
+#define VERIFY_OR_OBJECT(statement) VERIFY_OR_RETURN_VALUE(statement, {})
+
+/// variant of QCOMPARE returning a default constructed object on failure
+#define COMPARE_OR_OBJECT(actual, expected) COMPARE_OR_RETURN_VALUE(actual, expected, {})
+
+/// variant of QVERIFY returning \c false on failure
+#define VERIFY_OR_FALSE(statement) VERIFY_OR_RETURN_VALUE(statement, false)
+
+/// variant of QCOMPARE returning \c false on failure
+#define COMPARE_OR_FALSE(actual, expected) COMPARE_OR_RETURN_VALUE(actual, expected, false)
+
+namespace QTest
+{
+template <>
+inline char *toString(const std::string &s)
+{
+ return QTest::toString(s.c_str());
+}
+}
+
+namespace GpgME
+{
class TestPassphraseProvider : public PassphraseProvider
{
public:
@@ -59,12 +105,26 @@ bool loopbackSupported();
class QGpgMETest : public QObject
{
Q_OBJECT
+
+Q_SIGNALS:
+ void asyncDone();
+
protected:
+ static bool doOnlineTests();
+
bool copyKeyrings(const QString &from, const QString& to);
+ bool importSecretKeys(const char *keyData, int expectedKeys = 1);
+
+ void hookUpPassphraseProvider(GpgME::Context *context);
+ void hookUpPassphraseProvider(QGpgME::Job *job);
+
public Q_SLOTS:
void initTestCase();
void cleanupTestCase();
+
+private:
+ GpgME::TestPassphraseProvider mPassphraseProvider;
};
/* Timeout, in milliseconds, for use with QSignalSpy to wait on
diff --git a/lang/qt/tests/t-tofuinfo.cpp b/lang/qt/tests/t-tofuinfo.cpp
index 2d88106..a1871c4 100644
--- a/lang/qt/tests/t-tofuinfo.cpp
+++ b/lang/qt/tests/t-tofuinfo.cpp
@@ -116,8 +116,6 @@ static const char conflictMsg2[] = "-----BEGIN PGP MESSAGE-----\n"
class TofuInfoTest: public QGpgMETest
{
Q_OBJECT
-Q_SIGNALS:
- void asyncDone();
private:
bool testSupported()
@@ -155,10 +153,7 @@ private:
void signAndVerify(const QString &what, const GpgME::Key &key, int expected)
{
auto job = openpgp()->signJob();
- auto ctx = Job::context(job);
- TestPassphraseProvider provider;
- ctx->setPassphraseProvider(&provider);
- ctx->setPinentryMode(Context::PinentryLoopback);
+ hookUpPassphraseProvider(job);
std::vector<Key> keys;
keys.push_back(key);
diff --git a/lang/qt/tests/t-trustsignatures.cpp b/lang/qt/tests/t-trustsignatures.cpp
index d392b2f..6f7ad82 100644
--- a/lang/qt/tests/t-trustsignatures.cpp
+++ b/lang/qt/tests/t-trustsignatures.cpp
@@ -1,4 +1,4 @@
-/* t-remarks.cpp
+/* t-trustsignatures.cpp
This file is part of qgpgme, the Qt API binding for gpgme
Copyright (c) 2021 g10 Code GmbH
@@ -52,9 +52,6 @@ class TestTrustSignatures: public QGpgMETest
{
Q_OBJECT
-Q_SIGNALS:
- void asyncDone();
-
private Q_SLOTS:
void test_tsign_single_uid_key_and_then_tsign_it_again()
{
@@ -83,12 +80,7 @@ private Q_SLOTS:
// Create the job
auto job = std::unique_ptr<SignKeyJob>{openpgp()->signKeyJob()};
QVERIFY(job);
-
- // Hack in the passphrase provider
- auto jobCtx = Job::context(job.get());
- TestPassphraseProvider provider;
- jobCtx->setPassphraseProvider(&provider);
- jobCtx->setPinentryMode(Context::PinentryLoopback);
+ hookUpPassphraseProvider(job.get());
// Setup the job
job->setExportable(true);
@@ -131,12 +123,7 @@ private Q_SLOTS:
// Create the job
auto job = std::unique_ptr<SignKeyJob>{openpgp()->signKeyJob()};
QVERIFY(job);
-
- // Hack in the passphrase provider
- auto jobCtx = Job::context(job.get());
- TestPassphraseProvider provider;
- jobCtx->setPassphraseProvider(&provider);
- jobCtx->setPinentryMode(Context::PinentryLoopback);
+ hookUpPassphraseProvider(job.get());
// Setup the job
job->setExportable(true);
@@ -204,12 +191,7 @@ private Q_SLOTS:
// Create the job
auto job = openpgp()->signKeyJob();//std::unique_ptr<SignKeyJob>{openpgp()->signKeyJob()};
QVERIFY(job);
-
- // Hack in the passphrase provider
- auto jobCtx = Job::context(job);
- TestPassphraseProvider provider;
- jobCtx->setPassphraseProvider(&provider);
- jobCtx->setPinentryMode(Context::PinentryLoopback);
+ hookUpPassphraseProvider(job);
// Setup the job
job->setExportable(true);
@@ -252,12 +234,7 @@ private Q_SLOTS:
// Create the job
auto job = openpgp()->signKeyJob();//std::unique_ptr<SignKeyJob>{openpgp()->signKeyJob()};
QVERIFY(job);
-
- // Hack in the passphrase provider
- auto jobCtx = Job::context(job);
- TestPassphraseProvider provider;
- jobCtx->setPassphraseProvider(&provider);
- jobCtx->setPinentryMode(Context::PinentryLoopback);
+ hookUpPassphraseProvider(job);
// Setup the job
job->setExportable(true);
@@ -325,12 +302,7 @@ private Q_SLOTS:
// Create the job
auto job = openpgp()->signKeyJob();//std::unique_ptr<SignKeyJob>{openpgp()->signKeyJob()};
QVERIFY(job);
-
- // Hack in the passphrase provider
- auto jobCtx = Job::context(job);
- TestPassphraseProvider provider;
- jobCtx->setPassphraseProvider(&provider);
- jobCtx->setPinentryMode(Context::PinentryLoopback);
+ hookUpPassphraseProvider(job);
// Setup the job
job->setExportable(true);
@@ -374,12 +346,7 @@ private Q_SLOTS:
// Create the job
auto job = openpgp()->signKeyJob();//std::unique_ptr<SignKeyJob>{openpgp()->signKeyJob()};
QVERIFY(job);
-
- // Hack in the passphrase provider
- auto jobCtx = Job::context(job);
- TestPassphraseProvider provider;
- jobCtx->setPassphraseProvider(&provider);
- jobCtx->setPinentryMode(Context::PinentryLoopback);
+ hookUpPassphraseProvider(job);
// Setup the job
job->setExportable(true);
@@ -447,12 +414,7 @@ private Q_SLOTS:
// Create the job
auto job = openpgp()->signKeyJob();//std::unique_ptr<SignKeyJob>{openpgp()->signKeyJob()};
QVERIFY(job);
-
- // Hack in the passphrase provider
- auto jobCtx = Job::context(job);
- TestPassphraseProvider provider;
- jobCtx->setPassphraseProvider(&provider);
- jobCtx->setPinentryMode(Context::PinentryLoopback);
+ hookUpPassphraseProvider(job);
// Setup the job
job->setExportable(true);
@@ -495,12 +457,7 @@ private Q_SLOTS:
// Create the job
auto job = openpgp()->signKeyJob();//std::unique_ptr<SignKeyJob>{openpgp()->signKeyJob()};
QVERIFY(job);
-
- // Hack in the passphrase provider
- auto jobCtx = Job::context(job);
- TestPassphraseProvider provider;
- jobCtx->setPassphraseProvider(&provider);
- jobCtx->setPinentryMode(Context::PinentryLoopback);
+ hookUpPassphraseProvider(job);
// Setup the job
job->setExportable(true);
diff --git a/lang/qt/tests/t-various.cpp b/lang/qt/tests/t-various.cpp
index 8563b68..b630350 100644
--- a/lang/qt/tests/t-various.cpp
+++ b/lang/qt/tests/t-various.cpp
@@ -71,9 +71,6 @@ class TestVarious: public QGpgMETest
{
Q_OBJECT
-Q_SIGNALS:
- void asyncDone();
-
private Q_SLOTS:
void testDN()
{
@@ -137,9 +134,7 @@ private Q_SLOTS:
auto ctx = Context::createForProtocol(key.protocol());
QVERIFY (ctx);
- TestPassphraseProvider provider;
- ctx->setPassphraseProvider(&provider);
- ctx->setPinentryMode(Context::PinentryLoopback);
+ hookUpPassphraseProvider(ctx);
QVERIFY(!ctx->addUid(key, uid));
delete ctx;
@@ -190,9 +185,7 @@ private Q_SLOTS:
auto ctx = Context::createForProtocol(key.protocol());
QVERIFY (ctx);
- TestPassphraseProvider provider;
- ctx->setPassphraseProvider(&provider);
- ctx->setPinentryMode(Context::PinentryLoopback);
+ hookUpPassphraseProvider(ctx);
// change expiration of the main key
QVERIFY(!ctx->setExpire(key, 1000));
@@ -230,7 +223,7 @@ private Q_SLOTS:
std::vector<Subkey> primaryKey;
primaryKey.push_back(key.subkey(0));
const auto err = ctx->setExpire(key, 3000, primaryKey);
- QCOMPARE(err.code(), GPG_ERR_NOT_FOUND);
+ QCOMPARE(err.code(), static_cast<int>(GPG_ERR_NOT_FOUND));
delete ctx;
}
@@ -259,12 +252,7 @@ private Q_SLOTS:
// Create the job
auto job = std::unique_ptr<SignKeyJob>{openpgp()->signKeyJob()};
QVERIFY(job);
-
- // Hack in the passphrase provider
- auto jobCtx = Job::context(job.get());
- TestPassphraseProvider provider;
- jobCtx->setPassphraseProvider(&provider);
- jobCtx->setPinentryMode(Context::PinentryLoopback);
+ hookUpPassphraseProvider(job.get());
// Setup the job
job->setExportable(true);
@@ -319,12 +307,7 @@ private Q_SLOTS:
// Create the job
auto job = std::unique_ptr<SignKeyJob>{openpgp()->signKeyJob()};
QVERIFY(job);
-
- // Hack in the passphrase provider
- auto jobCtx = Job::context(job.get());
- TestPassphraseProvider provider;
- jobCtx->setPassphraseProvider(&provider);
- jobCtx->setPinentryMode(Context::PinentryLoopback);
+ hookUpPassphraseProvider(job.get());
// Setup the job
job->setExportable(true);
@@ -355,7 +338,7 @@ private Q_SLOTS:
target.update();
const auto keySignature = target.userID(0).signature(target.userID(0).numSignatures() - 1);
QVERIFY(!keySignature.neverExpires());
- const auto expirationDate = QDateTime::fromSecsSinceEpoch(keySignature.expirationTime()).date();
+ const auto expirationDate = QDateTime::fromSecsSinceEpoch(uint_least32_t(keySignature.expirationTime())).date();
QCOMPARE(expirationDate, QDate(2106, 2, 6)); // expiration date is capped at 2106-02-06
}
diff --git a/lang/qt/tests/t-wkdlookup.cpp b/lang/qt/tests/t-wkdlookup.cpp
new file mode 100644
index 0000000..5c2816c
--- /dev/null
+++ b/lang/qt/tests/t-wkdlookup.cpp
@@ -0,0 +1,155 @@
+/* t-wkdlookup.cpp
+
+ This file is part of qgpgme, the Qt API binding for gpgme
+ Copyright (c) 2021 g10 Code GmbH
+ Software engineering by Ingo Klöcker <dev@ingo-kloecker.de>
+
+ QGpgME is free software; you can redistribute it and/or
+ modify it under the terms of the GNU General Public License as
+ published by the Free Software Foundation; either version 2 of the
+ License, or (at your option) any later version.
+
+ QGpgME is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
+
+ In addition, as a special exception, the copyright holders give
+ permission to link the code of this program with any edition of
+ the Qt library by Trolltech AS, Norway (or with modified versions
+ of Qt that use the same license as Qt), and distribute linked
+ combinations including the two. You must obey the GNU General
+ Public License in all respects for all of the code used other than
+ Qt. If you modify this file, you may extend this exception to
+ your version of the file, but you are not obligated to do so. If
+ you do not wish to do so, delete this exception statement from
+ your version.
+*/
+#ifdef HAVE_CONFIG_H
+ #include "config.h"
+#endif
+
+#include "t-support.h"
+
+#include "data.h"
+#include "engineinfo.h"
+#include "protocol.h"
+#include "wkdlookupjob.h"
+#include "wkdlookupresult.h"
+
+#include <QDebug>
+#include <QSignalSpy>
+#include <QTest>
+
+#include <algorithm>
+
+using namespace QGpgME;
+using namespace GpgME;
+
+static const char *requiredVersion = "2.1.12";
+
+namespace
+{
+bool keyHasUserIDWithMatchingEmailAddress(const Key &key, const QString &expectedEmailAddress)
+{
+ const auto email = expectedEmailAddress.toLower();
+ const auto userIds = key.userIDs();
+ return std::any_of(
+ std::begin(userIds), std::end(userIds),
+ [email](const UserID &uid) {
+ return email == QString::fromUtf8(uid.email()).toLower();
+ });
+}
+}
+
+class WKDLookupTest : public QGpgMETest
+{
+ Q_OBJECT
+
+private Q_SLOTS:
+
+ void testWKDLookupAsync()
+ {
+ if (GpgME::engineInfo(GpgME::GpgEngine).engineVersion() < requiredVersion) {
+ QSKIP("dirmngr does not yet support WKD lookup");
+ }
+ if (!doOnlineTests()) {
+ QSKIP("Set DO_ONLINE_TESTS environment variable to run this test.");
+ }
+ const QString email = QLatin1String{"wk@gnupg.org"};
+
+ WKDLookupResult result;
+ auto *job = openpgp()->wkdLookupJob();
+ connect(job, &WKDLookupJob::result, job, [this, &result](const WKDLookupResult &result_, const QString &, const Error &)
+ {
+ result = result_;
+ Q_EMIT asyncDone();
+ });
+ job->start(email);
+ QSignalSpy spy (this, SIGNAL(asyncDone()));
+ QVERIFY(spy.wait(QSIGNALSPY_TIMEOUT));
+
+ QVERIFY(result.error().code() == GPG_ERR_NO_ERROR);
+ QCOMPARE(result.pattern(), "wk@gnupg.org");
+ QCOMPARE(result.source(), "https://openpgpkey.gnupg.org");
+ const auto keys = result.keyData().toKeys(GpgME::OpenPGP);
+ QVERIFY(keys.size() == 1);
+ QVERIFY(keyHasUserIDWithMatchingEmailAddress(keys.front(), email));
+ }
+
+ void testWKDLookupSync()
+ {
+ if (GpgME::engineInfo(GpgME::GpgEngine).engineVersion() < requiredVersion) {
+ QSKIP("dirmngr does not yet support WKD lookup");
+ }
+ if (!doOnlineTests()) {
+ QSKIP("Set DO_ONLINE_TESTS environment variable to run this test.");
+ }
+ const QString email = QLatin1String{"wk@gnupg.org"};
+
+ auto *job = openpgp()->wkdLookupJob();
+ const auto result = job->exec(email);
+
+ QVERIFY(result.error().code() == GPG_ERR_NO_ERROR);
+ QCOMPARE(result.pattern(), "wk@gnupg.org");
+ QCOMPARE(result.source(), "https://openpgpkey.gnupg.org");
+ const auto keys = result.keyData().toKeys(GpgME::OpenPGP);
+ QVERIFY(keys.size() == 1);
+ QVERIFY(keyHasUserIDWithMatchingEmailAddress(keys.front(), email));
+ }
+
+ void testLookupWithNoResultAsync()
+ {
+ if (GpgME::engineInfo(GpgME::GpgEngine).engineVersion() < requiredVersion) {
+ QSKIP("dirmngr does not yet support WKD lookup");
+ }
+ if (!doOnlineTests()) {
+ QSKIP("Set DO_ONLINE_TESTS environment variable to run this test.");
+ }
+ const QString email = QLatin1String{"alfa@example.net"};
+
+ WKDLookupResult result;
+ auto *job = openpgp()->wkdLookupJob();
+ connect(job, &WKDLookupJob::result, job, [this, &result](const WKDLookupResult &result_, const QString &, const Error &)
+ {
+ result = result_;
+ Q_EMIT asyncDone();
+ });
+ job->start(email);
+ QSignalSpy spy (this, SIGNAL(asyncDone()));
+ QVERIFY(spy.wait(QSIGNALSPY_TIMEOUT));
+
+ QVERIFY(result.error().code() == GPG_ERR_NO_ERROR);
+ QCOMPARE(result.pattern(), "alfa@example.net");
+ QCOMPARE(result.source(), "");
+ QVERIFY(result.keyData().isNull());
+ }
+};
+
+QTEST_MAIN(WKDLookupTest)
+
+#include "t-wkdlookup.moc"
diff --git a/lang/qt/tests/t-wkspublish.cpp b/lang/qt/tests/t-wkspublish.cpp
index b389194..618f0b4 100644
--- a/lang/qt/tests/t-wkspublish.cpp
+++ b/lang/qt/tests/t-wkspublish.cpp
@@ -118,9 +118,6 @@ class WKSPublishTest : public QGpgMETest
{
Q_OBJECT
-Q_SIGNALS:
- void asyncDone();
-
private Q_SLOTS:
void testUnsupported()
{