diff options
author | JinWang An <jinwang.an@samsung.com> | 2023-01-30 13:26:32 +0900 |
---|---|---|
committer | JinWang An <jinwang.an@samsung.com> | 2023-01-30 13:26:32 +0900 |
commit | 7068c0ead0c25a9a1fd3ce0b486636d74350e7ca (patch) | |
tree | 732edf51b955fd198e4bb7ef46a0782fb3ea1d12 /lang/qt | |
parent | d19c360948ede5ffe5974de8abc9da44be617ca1 (diff) | |
download | gpgme-7068c0ead0c25a9a1fd3ce0b486636d74350e7ca.tar.gz gpgme-7068c0ead0c25a9a1fd3ce0b486636d74350e7ca.tar.bz2 gpgme-7068c0ead0c25a9a1fd3ce0b486636d74350e7ca.zip |
Imported Upstream version 1.17.0upstream/1.17.0
Diffstat (limited to 'lang/qt')
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='[m'; \ 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() { |