summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorJinWang An <jinwang.an@samsung.com>2021-12-01 16:54:36 +0900
committerJinWang An <jinwang.an@samsung.com>2021-12-01 16:54:36 +0900
commite158cb38f461261d019c653a5f5e0ca9ddab8d6d (patch)
tree3872a21bc5b5797ee3c705509aace3393b0de251
parentfd5caec0dccd1229c2b9dd5220c8e2b1ef966d0e (diff)
downloadgpgme-e158cb38f461261d019c653a5f5e0ca9ddab8d6d.tar.gz
gpgme-e158cb38f461261d019c653a5f5e0ca9ddab8d6d.tar.bz2
gpgme-e158cb38f461261d019c653a5f5e0ca9ddab8d6d.zip
Imported Upstream version 1.7.0upstream/1.7.0
-rw-r--r--AUTHORS2
-rw-r--r--ChangeLog2771
-rw-r--r--Makefile.am18
-rw-r--r--Makefile.in76
-rw-r--r--NEWS105
-rw-r--r--README46
-rw-r--r--VERSION2
-rw-r--r--acinclude.m416
-rw-r--r--aclocal.m4277
-rwxr-xr-xautogen.sh2
-rwxr-xr-xbuild-aux/config.guess159
-rwxr-xr-xbuild-aux/config.sub46
-rw-r--r--config.h.in8
-rwxr-xr-xconfigure3262
-rw-r--r--configure.ac306
-rw-r--r--doc/Makefile.am28
-rw-r--r--doc/Makefile.in147
-rw-r--r--doc/defsincdate1
-rw-r--r--doc/gpgme.info243
-rw-r--r--doc/gpgme.info-12939
-rw-r--r--doc/gpgme.info-2741
-rw-r--r--doc/gpgme.texi2471
-rw-r--r--doc/mkdefsinc.c310
-rw-r--r--doc/stamp-vti4
-rw-r--r--doc/version.texi4
-rw-r--r--gpgme.spec2
-rw-r--r--lang/Makefile.am3
-rw-r--r--lang/Makefile.in54
-rw-r--r--lang/README3
-rw-r--r--lang/cl/Makefile.in50
-rw-r--r--lang/cl/gpgme.asd2
-rw-r--r--lang/cpp/Makefile.am23
-rw-r--r--lang/cpp/Makefile.in709
-rw-r--r--lang/cpp/README101
-rw-r--r--lang/cpp/src/GpgmeppConfig.cmake.in.in108
-rw-r--r--lang/cpp/src/GpgmeppConfigVersion.cmake.in31
-rw-r--r--lang/cpp/src/Makefile.am99
-rw-r--r--lang/cpp/src/Makefile.in955
-rw-r--r--lang/cpp/src/callbacks.cpp149
-rw-r--r--lang/cpp/src/callbacks.h45
-rw-r--r--lang/cpp/src/configuration.cpp934
-rw-r--r--lang/cpp/src/configuration.h290
-rw-r--r--lang/cpp/src/context.cpp1639
-rw-r--r--lang/cpp/src/context.h420
-rw-r--r--lang/cpp/src/context_p.h84
-rw-r--r--lang/cpp/src/context_vanilla.cpp33
-rw-r--r--lang/cpp/src/data.cpp222
-rw-r--r--lang/cpp/src/data.h126
-rw-r--r--lang/cpp/src/data_p.h40
-rw-r--r--lang/cpp/src/decryptionresult.cpp240
-rw-r--r--lang/cpp/src/decryptionresult.h130
-rw-r--r--lang/cpp/src/defaultassuantransaction.cpp78
-rw-r--r--lang/cpp/src/defaultassuantransaction.h65
-rw-r--r--lang/cpp/src/editinteractor.cpp339
-rw-r--r--lang/cpp/src/editinteractor.h68
-rw-r--r--lang/cpp/src/encryptionresult.cpp159
-rw-r--r--lang/cpp/src/encryptionresult.h113
-rw-r--r--lang/cpp/src/engineinfo.cpp88
-rw-r--r--lang/cpp/src/engineinfo.h126
-rw-r--r--lang/cpp/src/error.h78
-rw-r--r--lang/cpp/src/eventloopinteractor.cpp199
-rw-r--r--lang/cpp/src/eventloopinteractor.h156
-rw-r--r--lang/cpp/src/exception.cpp58
-rw-r--r--lang/cpp/src/exception.h68
-rw-r--r--lang/cpp/src/global.h218
-rw-r--r--lang/cpp/src/gpgadduserideditinteractor.cpp189
-rw-r--r--lang/cpp/src/gpgadduserideditinteractor.h67
-rw-r--r--lang/cpp/src/gpgagentgetinfoassuantransaction.cpp119
-rw-r--r--lang/cpp/src/gpgagentgetinfoassuantransaction.h73
-rw-r--r--lang/cpp/src/gpgmefw.h70
-rw-r--r--lang/cpp/src/gpgmepp_export.h73
-rw-r--r--lang/cpp/src/gpgmepp_version.h.in32
-rw-r--r--lang/cpp/src/gpgsetexpirytimeeditinteractor.cpp141
-rw-r--r--lang/cpp/src/gpgsetexpirytimeeditinteractor.h49
-rw-r--r--lang/cpp/src/gpgsetownertrusteditinteractor.cpp151
-rw-r--r--lang/cpp/src/gpgsetownertrusteditinteractor.h50
-rw-r--r--lang/cpp/src/gpgsignkeyeditinteractor.cpp318
-rw-r--r--lang/cpp/src/gpgsignkeyeditinteractor.h64
-rw-r--r--lang/cpp/src/importresult.cpp215
-rw-r--r--lang/cpp/src/importresult.h134
-rw-r--r--lang/cpp/src/interfaces/assuantransaction.h49
-rw-r--r--lang/cpp/src/interfaces/dataprovider.h53
-rw-r--r--lang/cpp/src/interfaces/passphraseprovider.h40
-rw-r--r--lang/cpp/src/interfaces/progressprovider.h40
-rw-r--r--lang/cpp/src/key.cpp912
-rw-r--r--lang/cpp/src/key.h415
-rw-r--r--lang/cpp/src/keygenerationresult.cpp92
-rw-r--r--lang/cpp/src/keygenerationresult.h82
-rw-r--r--lang/cpp/src/keylistresult.cpp107
-rw-r--r--lang/cpp/src/keylistresult.h81
-rw-r--r--lang/cpp/src/notation.h84
-rw-r--r--lang/cpp/src/result.h58
-rw-r--r--lang/cpp/src/result_p.h43
-rw-r--r--lang/cpp/src/scdgetinfoassuantransaction.cpp156
-rw-r--r--lang/cpp/src/scdgetinfoassuantransaction.h76
-rw-r--r--lang/cpp/src/signingresult.cpp265
-rw-r--r--lang/cpp/src/signingresult.h162
-rw-r--r--lang/cpp/src/tofuinfo.cpp167
-rw-r--r--lang/cpp/src/tofuinfo.h124
-rw-r--r--lang/cpp/src/trustitem.cpp114
-rw-r--r--lang/cpp/src/trustitem.h81
-rw-r--r--lang/cpp/src/util.h149
-rw-r--r--lang/cpp/src/verificationresult.cpp575
-rw-r--r--lang/cpp/src/verificationresult.h180
-rw-r--r--lang/cpp/src/vfsmountresult.cpp90
-rw-r--r--lang/cpp/src/vfsmountresult.h76
-rw-r--r--lang/python/MANIFEST.in4
-rw-r--r--lang/python/Makefile.am106
-rw-r--r--lang/python/Makefile.in798
-rw-r--r--lang/python/README59
-rw-r--r--lang/python/examples/assuan.py28
-rw-r--r--lang/python/examples/decryption-filter.py32
-rwxr-xr-xlang/python/examples/delkey.py33
-rwxr-xr-xlang/python/examples/encrypt-to-all.py53
-rwxr-xr-xlang/python/examples/exportimport.py61
-rwxr-xr-xlang/python/examples/genkey.py44
-rw-r--r--lang/python/examples/inter-edit.py56
-rwxr-xr-xlang/python/examples/sign.py28
-rwxr-xr-xlang/python/examples/signverify.py41
-rwxr-xr-xlang/python/examples/simple.py47
-rw-r--r--lang/python/examples/testCMSgetkey.py35
-rwxr-xr-xlang/python/examples/verifydetails.py79
-rwxr-xr-xlang/python/gpgme-h-clean.py53
-rw-r--r--lang/python/gpgme.i625
-rw-r--r--lang/python/helpers.c1169
-rw-r--r--lang/python/helpers.h39
-rw-r--r--lang/python/private.h54
-rw-r--r--lang/python/pyme/__init__.py125
-rw-r--r--lang/python/pyme/__pycache__/__init__.cpython-34.pycbin0 -> 4633 bytes
-rw-r--r--lang/python/pyme/__pycache__/version.cpython-34.pycbin0 -> 1997 bytes
-rw-r--r--lang/python/pyme/callbacks.py49
-rw-r--r--lang/python/pyme/constants/__init__.py114
-rw-r--r--lang/python/pyme/constants/data/__init__.py6
-rw-r--r--lang/python/pyme/constants/data/encoding.py22
-rw-r--r--lang/python/pyme/constants/event.py22
-rw-r--r--lang/python/pyme/constants/import.py22
-rw-r--r--lang/python/pyme/constants/keylist/__init__.py6
-rw-r--r--lang/python/pyme/constants/keylist/mode.py22
-rw-r--r--lang/python/pyme/constants/md.py22
-rw-r--r--lang/python/pyme/constants/pk.py22
-rw-r--r--lang/python/pyme/constants/protocol.py22
-rw-r--r--lang/python/pyme/constants/sig/__init__.py6
-rw-r--r--lang/python/pyme/constants/sig/mode.py22
-rw-r--r--lang/python/pyme/constants/sigsum.py22
-rw-r--r--lang/python/pyme/constants/status.py124
-rw-r--r--lang/python/pyme/constants/validity.py22
-rw-r--r--lang/python/pyme/core.py1145
-rw-r--r--lang/python/pyme/errors.py111
-rw-r--r--lang/python/pyme/gpgme.py125
-rw-r--r--lang/python/pyme/results.py118
-rw-r--r--lang/python/pyme/util.py53
-rw-r--r--lang/python/pyme/version.py68
-rw-r--r--lang/python/pyme/version.py.in68
-rwxr-xr-xlang/python/setup.py.in190
-rw-r--r--lang/python/tests/Makefile.am114
-rw-r--r--lang/python/tests/Makefile.in620
-rw-r--r--lang/python/tests/encrypt-only.asc33
-rwxr-xr-xlang/python/tests/final.py27
-rwxr-xr-xlang/python/tests/initial.py41
-rw-r--r--lang/python/tests/run-tests.py90
-rw-r--r--lang/python/tests/sign-only.asc33
-rw-r--r--lang/python/tests/support.py69
-rwxr-xr-xlang/python/tests/t-callbacks.py257
-rwxr-xr-xlang/python/tests/t-data.py129
-rwxr-xr-xlang/python/tests/t-decrypt-verify.py77
-rwxr-xr-xlang/python/tests/t-decrypt.py45
-rwxr-xr-xlang/python/tests/t-edit.py72
-rwxr-xr-xlang/python/tests/t-encrypt-large.py66
-rwxr-xr-xlang/python/tests/t-encrypt-sign.py98
-rwxr-xr-xlang/python/tests/t-encrypt-sym.py86
-rwxr-xr-xlang/python/tests/t-encrypt.py65
-rwxr-xr-xlang/python/tests/t-export.py40
-rwxr-xr-xlang/python/tests/t-file-name.py45
-rwxr-xr-xlang/python/tests/t-idiomatic.py84
-rwxr-xr-xlang/python/tests/t-import.py79
-rwxr-xr-xlang/python/tests/t-keylist.py246
-rwxr-xr-xlang/python/tests/t-protocol-assuan.py69
-rwxr-xr-xlang/python/tests/t-sig-notation.py79
-rwxr-xr-xlang/python/tests/t-sign.py122
-rwxr-xr-xlang/python/tests/t-signers.py98
-rwxr-xr-xlang/python/tests/t-trustlist.py43
-rwxr-xr-xlang/python/tests/t-verify.py195
-rwxr-xr-xlang/python/tests/t-wait.py45
-rwxr-xr-xlang/python/tests/t-wrapper.py25
-rw-r--r--lang/qt/Makefile.am23
-rw-r--r--lang/qt/Makefile.in709
-rw-r--r--lang/qt/README130
-rw-r--r--lang/qt/doc/Doxyfile.in2352
-rw-r--r--lang/qt/doc/Makefile.am31
-rw-r--r--lang/qt/doc/Makefile.in540
-rw-r--r--lang/qt/src/AddUserIDJob1
-rw-r--r--lang/qt/src/ChangeExpiryJob1
-rw-r--r--lang/qt/src/ChangeOwnerTrustJob1
-rw-r--r--lang/qt/src/ChangePasswdJob1
-rw-r--r--lang/qt/src/CryptoConfig1
-rw-r--r--lang/qt/src/DataProvider1
-rw-r--r--lang/qt/src/DecryptJob1
-rw-r--r--lang/qt/src/DecryptVerifyJob1
-rw-r--r--lang/qt/src/DefaultKeyGenerationJob1
-rw-r--r--lang/qt/src/DeleteJob1
-rw-r--r--lang/qt/src/DownloadJob1
-rw-r--r--lang/qt/src/EncryptJob1
-rw-r--r--lang/qt/src/ExportJob1
-rw-r--r--lang/qt/src/HierarchicalKeyKistJob1
-rw-r--r--lang/qt/src/ImportFromKeyserverJob1
-rw-r--r--lang/qt/src/ImportJob1
-rw-r--r--lang/qt/src/Job1
-rw-r--r--lang/qt/src/KeyForMailboxJob1
-rw-r--r--lang/qt/src/KeyGenerationJob1
-rw-r--r--lang/qt/src/KeyListJob1
-rw-r--r--lang/qt/src/ListAllKeysJob1
-rw-r--r--lang/qt/src/Makefile.am256
-rw-r--r--lang/qt/src/Makefile.in1123
-rw-r--r--lang/qt/src/MultiDeleteJob1
-rw-r--r--lang/qt/src/Protocol1
-rw-r--r--lang/qt/src/QGpgMENewCryptoConfig1
-rw-r--r--lang/qt/src/QGpgmeConfig.cmake.in.in107
-rw-r--r--lang/qt/src/QGpgmeConfigVersion.cmake.in31
-rw-r--r--lang/qt/src/RefreshKeysJob1
-rw-r--r--lang/qt/src/SignEncryptJob1
-rw-r--r--lang/qt/src/SignJob1
-rw-r--r--lang/qt/src/SignKeyJob1
-rw-r--r--lang/qt/src/TofuPolicyJob1
-rw-r--r--lang/qt/src/VerifyDetachedJob1
-rw-r--r--lang/qt/src/VerifyOpaqueJob1
-rw-r--r--lang/qt/src/WKSPublishJob1
-rw-r--r--lang/qt/src/abstractimportjob.h64
-rw-r--r--lang/qt/src/adduseridjob.h84
-rw-r--r--lang/qt/src/changeexpiryjob.h84
-rw-r--r--lang/qt/src/changeownertrustjob.h81
-rw-r--r--lang/qt/src/changepasswdjob.h82
-rw-r--r--lang/qt/src/cryptoconfig.h400
-rw-r--r--lang/qt/src/dataprovider.cpp282
-rw-r--r--lang/qt/src/dataprovider.h95
-rw-r--r--lang/qt/src/decryptjob.h100
-rw-r--r--lang/qt/src/decryptverifyjob.h105
-rw-r--r--lang/qt/src/defaultkeygenerationjob.cpp125
-rw-r--r--lang/qt/src/defaultkeygenerationjob.h76
-rw-r--r--lang/qt/src/deletejob.h83
-rw-r--r--lang/qt/src/downloadjob.h103
-rw-r--r--lang/qt/src/encryptjob.h136
-rw-r--r--lang/qt/src/exportjob.h87
-rw-r--r--lang/qt/src/gpgme_backend_debug.cpp10
-rw-r--r--lang/qt/src/gpgme_backend_debug.h11
-rw-r--r--lang/qt/src/hierarchicalkeylistjob.h125
-rw-r--r--lang/qt/src/importfromkeyserverjob.h84
-rw-r--r--lang/qt/src/importjob.h83
-rw-r--r--lang/qt/src/job.cpp159
-rw-r--r--lang/qt/src/job.h92
-rw-r--r--lang/qt/src/keyformailboxjob.h106
-rw-r--r--lang/qt/src/keygenerationjob.h85
-rw-r--r--lang/qt/src/keylistjob.h109
-rw-r--r--lang/qt/src/listallkeysjob.h104
-rw-r--r--lang/qt/src/multideletejob.h107
-rw-r--r--lang/qt/src/protocol.h183
-rw-r--r--lang/qt/src/protocol_p.h419
-rw-r--r--lang/qt/src/qgpgme_export.h73
-rw-r--r--lang/qt/src/qgpgme_version.h.in32
-rw-r--r--lang/qt/src/qgpgmeadduseridjob.cpp80
-rw-r--r--lang/qt/src/qgpgmeadduseridjob.h65
-rw-r--r--lang/qt/src/qgpgmebackend.cpp203
-rw-r--r--lang/qt/src/qgpgmebackend.h92
-rw-r--r--lang/qt/src/qgpgmechangeexpiryjob.cpp80
-rw-r--r--lang/qt/src/qgpgmechangeexpiryjob.h66
-rw-r--r--lang/qt/src/qgpgmechangeownertrustjob.cpp76
-rw-r--r--lang/qt/src/qgpgmechangeownertrustjob.h65
-rw-r--r--lang/qt/src/qgpgmechangepasswdjob.cpp79
-rw-r--r--lang/qt/src/qgpgmechangepasswdjob.h66
-rw-r--r--lang/qt/src/qgpgmedecryptjob.cpp128
-rw-r--r--lang/qt/src/qgpgmedecryptjob.h84
-rw-r--r--lang/qt/src/qgpgmedecryptverifyjob.cpp135
-rw-r--r--lang/qt/src/qgpgmedecryptverifyjob.h89
-rw-r--r--lang/qt/src/qgpgmedeletejob.cpp65
-rw-r--r--lang/qt/src/qgpgmedeletejob.h71
-rw-r--r--lang/qt/src/qgpgmedownloadjob.cpp100
-rw-r--r--lang/qt/src/qgpgmedownloadjob.h69
-rw-r--r--lang/qt/src/qgpgmeencryptjob.cpp170
-rw-r--r--lang/qt/src/qgpgmeencryptjob.h109
-rw-r--r--lang/qt/src/qgpgmeexportjob.cpp76
-rw-r--r--lang/qt/src/qgpgmeexportjob.h66
-rw-r--r--lang/qt/src/qgpgmeimportfromkeyserverjob.cpp82
-rw-r--r--lang/qt/src/qgpgmeimportfromkeyserverjob.h81
-rw-r--r--lang/qt/src/qgpgmeimportjob.cpp85
-rw-r--r--lang/qt/src/qgpgmeimportjob.h81
-rw-r--r--lang/qt/src/qgpgmekeyformailboxjob.cpp138
-rw-r--r--lang/qt/src/qgpgmekeyformailboxjob.h84
-rw-r--r--lang/qt/src/qgpgmekeygenerationjob.cpp71
-rw-r--r--lang/qt/src/qgpgmekeygenerationjob.h72
-rw-r--r--lang/qt/src/qgpgmekeylistjob.cpp172
-rw-r--r--lang/qt/src/qgpgmekeylistjob.h88
-rw-r--r--lang/qt/src/qgpgmelistallkeysjob.cpp168
-rw-r--r--lang/qt/src/qgpgmelistallkeysjob.h86
-rw-r--r--lang/qt/src/qgpgmenewcryptoconfig.cpp738
-rw-r--r--lang/qt/src/qgpgmenewcryptoconfig.h189
-rw-r--r--lang/qt/src/qgpgmerefreshkeysjob.cpp225
-rw-r--r--lang/qt/src/qgpgmerefreshkeysjob.h79
-rw-r--r--lang/qt/src/qgpgmesecretkeyexportjob.cpp142
-rw-r--r--lang/qt/src/qgpgmesecretkeyexportjob.h81
-rw-r--r--lang/qt/src/qgpgmesignencryptjob.cpp171
-rw-r--r--lang/qt/src/qgpgmesignencryptjob.h121
-rw-r--r--lang/qt/src/qgpgmesignjob.cpp163
-rw-r--r--lang/qt/src/qgpgmesignjob.h101
-rw-r--r--lang/qt/src/qgpgmesignkeyjob.cpp125
-rw-r--r--lang/qt/src/qgpgmesignkeyjob.h94
-rw-r--r--lang/qt/src/qgpgmetofupolicyjob.cpp65
-rw-r--r--lang/qt/src/qgpgmetofupolicyjob.h65
-rw-r--r--lang/qt/src/qgpgmeverifydetachedjob.cpp118
-rw-r--r--lang/qt/src/qgpgmeverifydetachedjob.h85
-rw-r--r--lang/qt/src/qgpgmeverifyopaquejob.cpp125
-rw-r--r--lang/qt/src/qgpgmeverifyopaquejob.h84
-rw-r--r--lang/qt/src/qgpgmewkspublishjob.cpp189
-rw-r--r--lang/qt/src/qgpgmewkspublishjob.h70
-rw-r--r--lang/qt/src/refreshkeysjob.h94
-rw-r--r--lang/qt/src/signencryptjob.h153
-rw-r--r--lang/qt/src/signjob.h122
-rw-r--r--lang/qt/src/signkeyjob.h117
-rw-r--r--lang/qt/src/specialjob.h91
-rw-r--r--lang/qt/src/threadedjobmixin.cpp110
-rw-r--r--lang/qt/src/threadedjobmixin.h272
-rw-r--r--lang/qt/src/tofupolicyjob.h80
-rw-r--r--lang/qt/src/verifydetachedjob.h99
-rw-r--r--lang/qt/src/verifyopaquejob.h101
-rw-r--r--lang/qt/src/wkspublishjob.h101
-rw-r--r--lang/qt/tests/Makefile.am95
-rw-r--r--lang/qt/tests/Makefile.in951
-rwxr-xr-xlang/qt/tests/initial.test2
-rw-r--r--lang/qt/tests/run-keyformailboxjob.cpp56
-rw-r--r--lang/qt/tests/t-encrypt.cpp254
-rw-r--r--lang/qt/tests/t-keylist.cpp107
-rw-r--r--lang/qt/tests/t-keylocate.cpp130
-rw-r--r--lang/qt/tests/t-ownertrust.cpp107
-rw-r--r--lang/qt/tests/t-support.cpp95
-rw-r--r--lang/qt/tests/t-support.h63
-rw-r--r--lang/qt/tests/t-tofuinfo.cpp367
-rw-r--r--lang/qt/tests/t-wkspublish.cpp278
-rw-r--r--m4/ax_cxx_compile_stdcxx.m4558
-rw-r--r--m4/ax_pkg_swig.m4135
-rw-r--r--m4/ax_python_devel.m4323
-rw-r--r--m4/pkg.m4157
-rw-r--r--m4/qt.m480
-rw-r--r--src/Makefile.am42
-rw-r--r--src/Makefile.in272
-rw-r--r--src/argparse.c1610
-rw-r--r--src/argparse.h203
-rw-r--r--src/assuan-support.c17
-rw-r--r--src/b64dec.c251
-rw-r--r--src/context.h11
-rw-r--r--src/conversion.c67
-rw-r--r--src/data-compat.c6
-rw-r--r--src/data-identify.c279
-rw-r--r--src/data-mem.c3
-rw-r--r--src/data.c32
-rw-r--r--src/data.h6
-rw-r--r--src/decrypt.c2
-rw-r--r--src/delete.c38
-rw-r--r--src/dirinfo.c103
-rw-r--r--src/edit.c113
-rw-r--r--src/encrypt-sign.c2
-rw-r--r--src/encrypt.c38
-rw-r--r--src/engine-assuan.c34
-rw-r--r--src/engine-backend.h18
-rw-r--r--src/engine-g13.c31
-rw-r--r--src/engine-gpg.c552
-rw-r--r--src/engine-gpgconf.c18
-rw-r--r--src/engine-gpgsm.c170
-rw-r--r--src/engine-spawn.c11
-rw-r--r--src/engine-uiserver.c97
-rw-r--r--src/engine.c138
-rw-r--r--src/engine.h24
-rw-r--r--src/export.c2
-rw-r--r--src/funopen.c2
-rw-r--r--src/genkey.c401
-rw-r--r--src/getauditlog.c3
-rw-r--r--src/gpgme-config.in35
-rw-r--r--src/gpgme-tool.c611
-rw-r--r--src/gpgme.c120
-rw-r--r--src/gpgme.def21
-rw-r--r--src/gpgme.h.in429
-rw-r--r--src/kdpipeiodevice.cpp951
-rw-r--r--src/kdpipeiodevice.h73
-rw-r--r--src/kdpipeiodevice.moc183
-rw-r--r--src/key.c31
-rw-r--r--src/keylist.c150
-rw-r--r--src/keysign.c218
-rw-r--r--src/libgpgme.vers19
-rw-r--r--src/mbox-util.c257
-rw-r--r--src/mbox-util.h29
-rw-r--r--src/moc_kdpipeiodevice.cpp60
-rw-r--r--src/op-support.c73
-rw-r--r--src/ops.h12
-rw-r--r--src/passphrase.c11
-rw-r--r--src/passwd.c8
-rw-r--r--src/posix-io.c81
-rw-r--r--src/posix-util.c11
-rw-r--r--src/sign.c27
-rw-r--r--src/status-table.c17
-rw-r--r--src/sys-util.h1
-rw-r--r--src/tofupolicy.c184
-rw-r--r--src/trustlist.c3
-rw-r--r--src/util.h38
-rw-r--r--src/verify.c294
-rw-r--r--src/version.c6
-rw-r--r--src/versioninfo.rc.in2
-rw-r--r--src/vfs-create.c2
-rw-r--r--src/vfs-mount.c2
-rw-r--r--src/w32-glib-io.c2
-rw-r--r--src/w32-io.c37
-rw-r--r--src/w32-qt-io.cpp700
-rw-r--r--src/w32-util.c60
-rw-r--r--src/wait-global.c4
-rw-r--r--src/wait-private.c6
-rw-r--r--src/wait-user.c2
-rw-r--r--tests/Makefile.am3
-rw-r--r--tests/Makefile.in128
-rw-r--r--tests/gpg/Makefile.am8
-rw-r--r--tests/gpg/Makefile.in89
-rw-r--r--tests/gpg/t-decrypt-verify.c49
-rw-r--r--tests/gpg/t-decrypt.c18
-rw-r--r--tests/gpg/t-edit.c29
-rw-r--r--tests/gpg/t-encrypt-large.c21
-rw-r--r--tests/gpg/t-encrypt-mixed.c129
-rw-r--r--tests/gpg/t-encrypt-sign.c3
-rw-r--r--tests/gpg/t-encrypt-sym.c12
-rw-r--r--tests/gpg/t-encrypt.c13
-rw-r--r--tests/gpg/t-eventloop.c12
-rw-r--r--tests/gpg/t-export.c17
-rw-r--r--tests/gpg/t-file-name.c14
-rw-r--r--tests/gpg/t-genkey.c15
-rw-r--r--tests/gpg/t-gpgconf.c18
-rw-r--r--tests/gpg/t-import.c19
-rw-r--r--tests/gpg/t-keylist-sig.c20
-rw-r--r--tests/gpg/t-keylist.c27
-rw-r--r--tests/gpg/t-sig-notation.c53
-rw-r--r--tests/gpg/t-sign.c17
-rw-r--r--tests/gpg/t-signers.c19
-rw-r--r--tests/gpg/t-support.h26
-rw-r--r--tests/gpg/t-thread1.c25
-rw-r--r--tests/gpg/t-trustlist.c11
-rw-r--r--tests/gpg/t-verify.c18
-rw-r--r--tests/gpg/t-wait.c10
-rw-r--r--tests/gpgsm/Makefile.in50
-rw-r--r--tests/gpgsm/t-decrypt.c12
-rw-r--r--tests/gpgsm/t-encrypt.c12
-rw-r--r--tests/gpgsm/t-export.c12
-rw-r--r--tests/gpgsm/t-genkey.c14
-rw-r--r--tests/gpgsm/t-import.c26
-rw-r--r--tests/gpgsm/t-keylist.c25
-rw-r--r--tests/gpgsm/t-sign.c14
-rw-r--r--tests/gpgsm/t-support.h19
-rw-r--r--tests/gpgsm/t-verify.c16
-rw-r--r--tests/opassuan/Makefile.in50
-rw-r--r--tests/opassuan/t-command.c23
-rw-r--r--tests/run-decrypt.c189
-rw-r--r--tests/run-encrypt.c293
-rw-r--r--tests/run-genkey.c439
-rw-r--r--tests/run-identify.c129
-rw-r--r--tests/run-keylist.c108
-rw-r--r--tests/run-keysign.c261
-rw-r--r--tests/run-sign.c2
-rw-r--r--tests/run-support.h16
-rw-r--r--tests/run-tofu.c178
-rw-r--r--tests/run-verify.c115
-rw-r--r--tests/t-data.c16
-rw-r--r--tests/t-engine-info.c16
464 files changed, 63967 insertions, 6099 deletions
diff --git a/AUTHORS b/AUTHORS
index dd4b492..bbf1576 100644
--- a/AUTHORS
+++ b/AUTHORS
@@ -1,5 +1,5 @@
Package: gpgme
-Homepage: http://www.gnupg.org/related_software/gpgme/
+Homepage: https://gnupg.org/related_software/gpgme/
Download: ftp://ftp.gnupg.org/gcrypt/gpgme/
Repository: git://git.gnupg.org/gpgme.git
Maintainer: Werner Koch <wk@gnupg.org>
diff --git a/ChangeLog b/ChangeLog
index b1a8397..239b3a3 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,3 +1,2683 @@
+2016-09-21 Werner Koch <wk@gnupg.org>
+
+ Release 1.7.0.
+ * configure.ac: Bump LT vesion to C26/A15/R0.
+
+ python: Create install dir.
+ * lang/python/Makefile.am (install-exec-local): Create dir.
+
+2016-09-20 Werner Koch <wk@gnupg.org>
+
+ tests: Make "make -j distcheck" work in Python.
+ * lang/python/Makefile.am (SUBDIRS): Make current dir fist.
+ * lang/python/tests/Makefile.am (xcheck): Depend on pubring-stamp.
+ (CLEANFILES): Remove private-keys-v1.d/gpg-sample.stamp.
+ (check-local): Remove.
+ (initial.py): Remove dependency.
+ (./pubring-stamp): Depend on conf files and the
+ private-keys-v1.d/gpg-sample.stamp file. Also replace use of
+ basename.
+
+ tests: Use --batch for gpg import.
+ * lang/python/tests/Makefile.am (./pubring-stamp): Use --batch with
+ GPG to avoid Pinentries during import when using GnuPG >= 2.1.
+ Replace touch by echo.
+ * tests/gpg/Makefile.am (./pubring-stamp): Ditto.
+
+ tests: Improve portability.
+ * lang/qt/tests/Makefile.am (clean-local): Avoid non-portable "--"
+ * lang/python/Makefile.am (copystamp): Use well defined cp -R instead
+ of cp -r.
+
+ build: Create swdb file.
+ * Makefile.am (distcheck-hook): New.
+ (dist-hook): s/VERSION/PACKAGE_VERSION/ for future compatibility.
+
+2016-09-20 Justus Winter <justus@g10code.com>
+
+ python: Fix detection of Python available versions.
+ * configure.ac: Test for 'PYTHON_VERSION' as 'AX_PYTHON_DEVEL' sets
+ 'PYTHON' but clears the former.
+
+ Fixes-commit: 99db3512
+
+2016-09-19 Andre Heinecke <aheinecke@intevation.de>
+
+ core: Remove moc artifact.
+ * src/moc_kdpipeiodevice.cpp: Removed.
+ * src/Makefile.am (EXTRA_DIST): Remove moc_kdpipeiodevice.cpp.
+
+ qt: Improve README.
+ * lang/qt/README: Add more content. Clearly note license difference.
+
+ cpp: Improve README.
+ * lang/cpp/README: Add more content, move license to bottom.
+
+ qt: Add debug output for testTofuPolicy.
+ * lang/qt/tests/t-tofuinfo.cpp (testTofuPolicy): Add
+ debug output.
+
+2016-09-19 Ben Kibbey <bjk@luxsci.net>
+
+ core: Check for GPG_TTY as well as DISPLAY.
+ * src/engine-assuan.c (llass_new): Update --ttyname from GPG_TTY.
+ * src/engine-g13.c (g13_new): Ditto.
+ * src/engine-gpg.c (gpg_new): Ditto.
+ * src/engine-uiserver.c (uiserver_new): Ditto.
+ * src/engine-gpgsm.c (gpgsm_new): Ditto.
+
+2016-09-16 Andre Heinecke <aheinecke@intevation.de>
+
+ qt: Add test for setting tofu policy.
+ * lang/qt/tests/t-tofuinfo.cpp (testTofuPolicy): New.
+
+ qt: Add job for tofupolicy.
+ * lang/qt/src/job.cpp, lang/qt/src/protocol.h,
+ lang/qt/src/protocol_p.h: Register job.
+ * lang/qt/src/qgpgmetofupolicyjob.cpp,
+ lang/qt/src/qgpgmetofupolicyjob.h,
+ lang/qt/src/tofupolicyjob.h: New.
+ * lang/qt/src/Makefile.am: Update accordingly.
+
+ cpp: Add support for gpgme_op_tofu_policy.
+ * src/context.cpp, src/context.h (setTofuPolicy, setTofuPolicyStart):
+ New.
+
+ cpp: Declare sizes of tofu-info enums.
+ * lang/cpp/src/tofuinfo.h (Policy, Validity): Declare sizes.
+
+2016-09-16 Werner Koch <wk@gnupg.org>
+
+ cpp: Silence use of deprecated function warning.
+ * lang/cpp/src/context.cpp (GpgME): Use pragma to silence wardning.
+
+ core: Document the version a function has been deprecated.
+ * src/gpgme.h.in (_GPGME_DEPRECATED): Change to take versio numbers
+ for documentation. Change all places.
+ (_GPGME_DEPRECATED_OUTSIDE_GPGME): Ditto.
+ * lang/python/gpgme-h-clean.py: Adjust RE.
+
+ core: Map GPGME_STATUS_EOF to the empty string.
+ * src/status-table.c (_gpgme_status_to_string): Return "" for EOF.
+ * src/engine-gpg.c (read_status): Ditto. The old code accidently used
+ GPGME_STATUS_EOF which is the integer 0 and neiteyr NULL nor a string.
+
+2016-09-16 Justus Winter <justus@g10code.com>
+ Kai Michaelis <kai@gnupg.org>
+
+ python: Release the GIL during calls into GPGME.
+ * lang/python/helpers.c (pyme_raise_callback_exception): Re-acquire
+ the Global Interpreter Lock.
+ (pyPassphraseCb, pyme_set_passphrase_cb, pyProgressCb,
+ pyme_set_progress_cb, pyStatusCb, pyme_set_status_cb,
+ _pyme_interact_cb, pyDataReadCb, pyDataWriteCb, pyDataSeekCb,
+ pyDataReleaseCb, pyme_data_new_from_cbs, _pyme_assuan_data_cb,
+ _pyme_assuan_inquire_cb, _pyme_assuan_status_cb): Likewise.
+ * lang/python/setup.py.in: Make 'gpgme-config' emit the correct
+ cflags, and SWIG generate code to release the GIL before calling us.
+
+2016-09-16 Justus Winter <justus@g10code.com>
+
+ python: Adapt to 'gpgme_op_interact'.
+ * lang/python/examples/inter-edit.py: Update example.
+ * lang/python/gpgme.i (gpgme_edit_cb_t): Turn into
+ 'gpgme_interact_cb_t'.
+ * lang/python/helpers.c (_pyme_edit_cb): Turn into
+ '_pyme_interact_cb_t'.
+ * lang/python/private.h (_pyme_edit_cb): Likewise.
+ * lang/python/pyme/constants/__init__.py: Replace numeric status codes
+ with the keywords.
+ * lang/python/pyme/constants/status.py: Likewise.
+ * lang/python/pyme/core.py (Context.interact): New method.
+ (Context.op_edit): Deprecate, update docstring, implement using
+ Context.interact.
+ * lang/python/tests/t-edit.py: Test both interfaces.
+
+2016-09-16 Werner Koch <wk@gnupg.org>
+
+ core: Remove stub to try implementing gpg < 2.1 support for createkey.
+ * src/engine-gpg.c (gpg_createkey_legacy): Remove.
+ (gpg_genkey): Remove call.
+
+ core: Fix setting og the verification result.
+ * src/verify.c (parse_new_sig): Proberly handle the RC in an ERRSIG
+ status.
+
+2016-09-15 Werner Koch <wk@gnupg.org>
+
+ core: New function gpgme_op_interact, deprecate gpgme_op_edit.
+ * src/gpgme.h.in (gpgme_interact_cb_t): New.
+ (GPGME_INTERACT_CARD): New.
+ (gpgme_op_interact_start, gpgme_op_interact): New.
+ * src/libgpgme.vers, src/gpgme.def: Add new functions.
+ * src/edit.c (op_data_t): Rename fnc to fnc_old and change users. Add
+ fnc.
+ (edit_status_handler): Call old or new callback.
+ (command_handler): Ditto.
+ (interact_start): New.
+ (gpgme_op_interact_start, gpgme_op_interact_start): New.
+ * src/status-table.c (_gpgme_status_to_string): New.
+
+ * tests/gpg/t-edit.c (edit_fnc): Rename to interact_fnc and change
+ type of STATUS. Use gpgme_io_writen.
+ (main): s/gpgme_op_edit/gpgme_op_interact/.
+
+ core: Minor change of the gpgme_op_edit semantics.
+ * src/edit.c (command_handler): Handle special error code.
+ * src/engine-gpg.c (read_status): Ditto.
+ * src/engine-gpgsm.c (status_handler): Ditto.
+ * src/engine-uiserver.c (status_handler): Ditto.
+ * src/util.h (GPG_ERR_FALSE): Define for older libgpg-error versions.
+
+2016-09-14 Werner Koch <wk@gnupg.org>
+
+ core: New function gpgme_op_tofu_policy.
+ * src/gpgme.h.in (gpgme_op_tofu_policy_start): New function.
+ (gpgme_op_tofu_policy): New function.
+ * src/libgpgme.vers, src/gpgme.def: Add new functions.
+ * src/tofupolicy.c: New.
+ * src/Makefile.am (main_sources): Add that file.
+ * src/context.h (ctx_op_data_id_t): Add OPDATA_TOFU_POLICY.
+ * src/engine.c (_gpgme_engine_op_tofu_policy): New.
+ * src/engine-backend.h (engine_ops): Add funcptr 'tofu_policy'.
+ Adjust all engine initializations.
+ * src/engine-gpg.c (gpg_tofu_policy): New.
+ (_gpgme_engine_ops_gpg): Register this function.
+
+ * tests/run-tofu.c: New.
+ * tests/Makefile.am (noinst_PROGRAMS): Add it.
+
+ core: Defer implementation of gpgme_op_createkey with gpg < 2.1.
+ * src/engine-gpg.c (gpg_createkey_legacy): Mark unused variables.
+
+ core: New function gpgme_op_keysign.
+ * src/gpgme.h.in (gpgme_op_keysign_start, gpgme_op_keysign): New.
+ (GPGME_KEYSIGN_LOCAL): New.
+ (GPGME_KEYSIGN_LFSEP): New.
+ (GPGME_KEYSIGN_NOEXPIRE): New.
+ * src/context.h (ctx_op_data_id_t): Add OPDATA_KEYSIGN.
+ * src/keysign.c: New.
+ * src/Makefile.am (main_sources): Add keysig.
+ * src/libgpgme.vers, src/gpgme.def: Add gpgme_op_keysign_start.
+ * src/engine.c (_gpgme_engine_op_keysign): New.
+ * src/engine-backend.h (engine_ops): Add 'keysign' and adjust all
+ engine initializers.
+ * src/engine-gpg.c (_add_arg): Add args PREFIX and ARGLEN and change
+ callers to set them.
+ (add_arg_pfx): New.
+ (add_arg_len): New.
+ (gpg_keysign): New.
+ (_gpgme_engine_ops_gpg): Set keysign to gpg_keysign.
+ * tests/run-keysign.c: New.
+ * tests/Makefile.am (noinst_PROGRAMS): Add run-keysign.
+
+2016-09-14 Justus Winter <justus@g10code.com>
+
+ python: Clarify that we support Python 2.7 too.
+ * lang/python/README: Use 'Python' instead of 'Python 3'.
+ * lang/python/pyme/version.py.in: Likewise.
+ * lang/python/setup.py.in: Add classifier for 2.7, drop 3 only.
+
+ python: Trim imports.
+ * lang/python/examples/encrypt-to-all.py: Drop unused import of 'os'.
+ * lang/python/examples/signverify.py: Likewise.
+ * lang/python/examples/simple.py: Likewise.
+ * lang/python/examples/verifydetails.py: Likewise.
+
+ python: Improve error handling.
+ * lang/python/gpgme.i (gpgme_engine_info_t): Improve error handling.
+
+ python: Adapt to TOFU changes.
+ * lang/python/pyme/results.py (TofuInfo): Drop.
+ (Signature): The TOFU information moved to the key.
+
+ python: Improve build system integration.
+ * configure.ac: Try to compile a Python module for each version.
+ * m4/m4_ax_swig_python.m4: Drop unused file.
+
+2016-09-14 Werner Koch <wk@gnupg.org>
+
+ core: New function gpgme_op_revuid.
+ * src/engine.h (GENKEY_EXTRAFLAG_REVOKE): New.
+ * src/genkey.c (adduid_start): Rename to addrevuid_start. Add arg
+ REVOKE and pass it as extraflags. Remove useless ARMOR extraflag.
+ Adjust callers.
+ (gpgme_op_revuid_start, gpgme_op_revuid): New.
+ * src/gpgme.def, src/libgpgme.vers: Add them.
+
+ * tests/run-genkey.c: Add option --revuid.
+
+ core: Change a parameter for the engine's genkey function.
+ * src/engine.h (GENKEY_EXTRAFLAG_ARMOR): New.
+ * src/engine-backend.h (engine_ops): Rename USE_ARMOR in genkey to
+ EXTRAFLAGS.
+ * src/engine.c (_gpgme_engine_op_genkey): Ditto.
+ * src/engine-gpg.c (gpg_createkey_from_param): Ditto and test the
+ flags.
+ (gpg_createkey_legacy): Ditto.
+ (gpg_createkey): Ditto.
+ (gpg_addkey): Ditto.
+ (gpg_genkey): Ditto.
+
+2016-09-14 Justus Winter <justus@g10code.com>
+
+ python: Build for both Python2 and Python3.
+ * NEWS: Update.
+ * configure.ac: Check for multiple Python versions.
+ * lang/python/Makefile.am: Build and install for both Python versions.
+ * lang/python/tests/Makefile.am: Test both versions.
+ * lang/python/tests/run-tests.py: New test runner.
+
+2016-09-14 Werner Koch <wk@gnupg.org>
+
+ core: New function gpgme_op_adduid.
+ * src/genkey.c: Replace most error codes GPG_ERR_INV_VALUE by
+ GPG_ERR_INV_ARG.
+ (struct op_data_t): Add field UIDMODE.
+ (genkey_status_handler): Use UIDMODE.
+ (adduid_start): New.
+ (gpgme_op_adduid_start, gpgme_op_adduid): New.
+ * src/gpgme.def, src/libgpgme.vers: Add them.
+ * tests/run-genkey.c: Add option --adduid.
+
+ core: New function gpgme_op_createsubkey.
+ * src/genkey.c (createsubkey_start): New.
+ (gpgme_op_createsubkey_start, gpgme_op_createsubkey): New.
+ * src/gpgme.def, src/libgpgme.vers: Add them.
+ * src/engine-gpg.c (gpg_createkey): Factor some code out to ...
+ (gpg_add_algo_usage_expire): new.
+ (gpg_addkey): Implement.
+ * tests/run-genkey.c: Add option --addkey.
+
+2016-09-13 Werner Koch <wk@gnupg.org>
+
+ core: Use const char * where appropriate.
+
+ core: Cast away the common const problem with spawn and argv.
+ * src/dirinfo.c (read_gpgconf_dirs): Use a cast to assignd to ARGV.
+
+ core: Fix condition-always-true warning in trace macro.
+ * src/data-compat.c (old_user_read): Cast AMT.
+
+ core: Mark unused function args.
+
+ tests: Mark lots of unused vars and fix const mismatches.
+
+ tests: Use gpgme_io_write in passhrase callbacks.
+ * tests/gpg/t-support.h (passphrase_cb): Use gpgme_io_write.
+ * tests/gpgsm/t-support.h (passphrase_cb): Ditto.
+ * tests/run-support.h (passphrase_cb): Ditto.
+
+ core: Do not pass const char* to functions taking a char*.
+
+ build: Use more compiler warnings.
+ * configure.ac: Add useful compiler warnings.
+
+ core: New function gpgme_op_create_key.
+ * src/engine-backend.h (engine_ops): Change prototype of genkey.
+ * src/engine-gpgsm.c (gpgsm_genkey): Change accordingly.
+ * src/engine-gpg.c (gpg_genkey): Change it to a dispatcher.
+ (gpg_createkey_from_param): New for the old functionality.
+ (gpg_createkey_legacy): New. Stub for now.
+ (gpg_createkey): New.
+ (gpg_addkey): New. Stub for now.
+ (gpg_adduid): New. Stub for now.
+ * src/engine.c (_gpgme_engine_op_genkey): Add new args.
+ * src/genkey.c (op_data_t): Add field ERROR_CODE.
+ (parse_error): New.
+ (genkey_status_handler): Parse ERROR status line.
+ (genkey_start): Use NULL/0 for the new args.
+ (createkey_start): New.
+ (gpgme_op_createkey_start, gpgme_op_createkey): New.
+ * src/gpgme.def, src/libgpgme.vers: Add gpgme_op_createkey_start and
+ gpgme_op_createkey.
+ * src/gpgme.h.in (_gpgme_op_genkey_result): Add fields PUBKEY and
+ SECKEY.
+ (GPGME_CREATE_SIGN): New.
+ (GPGME_CREATE_ENCR): New.
+ (GPGME_CREATE_CERT): New.
+ (GPGME_CREATE_AUTH): New.
+ (GPGME_CREATE_NOPASSWD): New.
+ (GPGME_CREATE_SELFSIGNED): New.
+ (GPGME_CREATE_NOSTORE): New.
+ (GPGME_CREATE_WANTPUB): New.
+ (GPGME_CREATE_WANTSEC): New.
+ (GPGME_CREATE_FORCE): New.
+
+ * tests/run-genkey.c: New.
+ * tests/Makefile.am (noinst_PROGRAMS): Add it.
+
+2016-09-13 Justus Winter <justus@g10code.com>
+
+ python: Handle slight differences between Python 2 and 3.
+ * lang/python/helpers.c (pyDataWriteCb): Handle Python integers being
+ returned on Python 2.
+ (pyDataSeekCb): Likewise.
+ * lang/python/pyme/core.py (Data.__init__): Fix testing for string
+ argument.
+ (Data.new_from_filepart): Likewise.
+ * lang/python/pyme/util.py (is_a_string): New function.
+ * lang/python/tests/t-encrypt-large.py (read_cb): Force evaluation of
+ generator.
+ * lang/python/tests/t-idiomatic.py: Partly skip test on Python 2.
+ * lang/python/tests/t-verify.py (check_result): Here, the difference
+ between 2 and 3 really matters. We cannot change the char *
+ conversion in Python 2 without breaking all existing applications, and
+ using bytestrings in Python 3 would be very inconvenient.
+
+ python: Fix types and error handling.
+ * lang/python/helpers.c (_pyme_edit_cb): Drop the const.
+ (_pyme_assuan_{data,inquire,status}_cb): Fix error handling.
+
+2016-09-12 Justus Winter <justus@g10code.com>
+
+ python: Avoid Python3-only form of super().
+ * lang/python/pyme/core.py (GpgmeWrapper.__repr__): Use more
+ compatible form of super.
+ (GpgmeWrapper.__setattr__): Likewise.
+ (Context.__init__): Likewise.
+ (Data.__init__): Likewise.
+
+ python: Make type translation compatible with Python 2.7.
+ * lang/python/gpgme.i: Avoid functions not available in Python 2.7.
+ * lang/python/helpers.c: Likewise.
+
+ python: Avoid hardcoding the interpreter.
+ * lang/python/setup.py.in: Avoid hardcoding the interpreter.
+
+ python: Do not rely on subprocess.DEVNULL.
+ * lang/python/setup.py.in: Do not rely on subprocess.DEVNULL.
+
+ tests: Fix version comparison.
+ * tests/gpg/t-sig-notation.c: Fix version comparison.
+
+ Fixes-commit: a0263ad2
+
+ tests: Make signature notation test compatible with older GnuPGs.
+ * lang/python/tests/t-sig-notation.py: Only check the critical flag
+ when GnuPG >= 2.1.13 is used.
+ * tests/gpg/t-sig-notation.c: Likewise.
+
+ Fixes-commit: c88c9ef3
+
+2016-09-12 Andre Heinecke <aheinecke@intevation.de>
+
+ qt: Fix some includes.
+ * lang/qt/src/qgpgmekeyformailboxjob.cpp: Explicitly include
+ QStringList.
+ * lang/qt/tests/t-support.h, lang/qt/tests/t-support.cpp: Move
+ includes into impl. Explicitly include QDir.
+
+2016-09-12 Justus Winter <justus@g10code.com>
+
+ qt: Fix tofu test.
+ * lang/qt/tests/t-tofuinfo.cpp: Adjust member names.
+
+ Fixes-commit: 120b1478
+
+2016-09-07 Werner Koch <wk@gnupg.org>
+
+ core,cpp: Extend the TOFU information.
+ * src/gpgme.h.in (struct _gpeme_tofu_info): Rename FIRSTSEEN to
+ SIGNFIRST and LASTSEEN to SIGNLAST. Add ENCRFIST and ENCRLAST.
+ * src/keylist.c (parse_tfs_record): Parse to ENCRFIRST and ENCRLAST.
+ * src/verify.c (parse_tofu_stats): Ditto.
+ * tests/run-keylist.c (main): Adjust and print encrypt stats.
+ * tests/run-verify.c (print_result): Ditto.
+
+ * lang/cpp/src/tofuinfo.h (TofuInfo): Rename firstSeen to signFirst
+ and lastSeen to signLast. Add encrCount, encrFirst and encrLast.
+ * lang/cpp/src/tofuinfo.cpp (encrCount, encrFirst, encrLast): New.
+
+2016-09-06 Andre Heinecke <aheinecke@intevation.de>
+
+ tests: Set passphrase cb in t-encrypt-mixed.
+ * tests/gpg/t-encrypt-mixed.c (main): Set passphrase cb.
+
+ core: Check for gpg version for loopback mode.
+ * src/engine-gpg.c (build_argv): Check for version 2.1.0
+ before adding pinentry-mode.
+
+ core: Fix passphrase cb for mixed sym encrypt.
+ * src/encrypt.c (encrypt_start): Handle SYMMETRIC flag.
+ * src/encrypt-sign.c (encrypt_sign_start): Ditto.
+
+2016-09-05 Andre Heinecke <aheinecke@intevation.de>
+
+ qt: Clarify comment and strings in tofuinfo test.
+ * lang/qt/tests/t-tofuinfo.cpp (testTofuSignCount)
+ (testTofuKeyList): Ensure distinct messages. Clarify comment.
+
+ qt: Enable signcount checks in tofuinfo test.
+ * lang/qt/tests/t-tofuinfo.cpp: Enable checks for signcount.
+
+ cpp: Add convenience update function to a key.
+ * lang/cpp/src/key.cpp (Key::update): New.
+ * lang/cpp/src/key.h: Update accordingly.
+
+ cpp: Add ostream operators for key and uid.
+ * lang/cpp/src/key.cpp (Key, UserID): Add ostream operator.
+ * lang/cpp/src/key.h: Update accordingly.
+
+ qt: Add missing header redirection.
+ * lang/qt/src/keyformailboxjob.h,
+ lang/qt/src/qgpgmekeyformailboxjob.h: Fix includes.
+
+ qt: Include cpp before core directory.
+ * lang/qt/src/Makefile.am (AM_CPPFLAGS): Include cpp before core.
+
+2016-08-25 Andre Heinecke <aheinecke@intevation.de>
+
+ qt: Fix 2.1 t-support copy.
+ * lang/qt/src/t-support.cpp (copyKeyring): Fix seckey copy.
+
+ qt: Fix and extend TofuInfo test.
+ * lang/qt/tests/t-tofuinfo.cpp: Delete executed jobs.
+ (testTofuKeyList): New.
+ (testSupported): Activate for 2.1.16
+ (signAndVerify): Disable sigcount tests.
+
+ qt: Fix keyring copy in tests.
+ * lang/qt/test/t-encrypt.cpp,
+ lang/qt/test/t-tofuinfo.cpp: Assert on copy failure.
+ * lang/qt/test/t-support.cpp (copyKeyrings): Fix path.
+
+ qt: Add generic flag support for keylistjobs.
+ * lang/qt/src/keylistjob.h (addMode): New.
+ * lang/qt/src/qgpgmekeylistjob.h (addMode): New.
+ * lang/qt/src/qgpgmekeylistjob.cpp (addMode: New.
+
+ qt: Ensure that current src dir is included first.
+ * lang/qt/src/Makefile.am: Reorder include directives.
+
+ cpp: Add WithTofu Keylist Mode.
+ * lang/cpp/src/context.cpp: Handle WithTofu.
+ * lang/cpp/src/global.h (KeyListMode): Add WithTofu.
+ * lang/cpp/src/util.h (add_to_gpgme_keylist_mode_t): Handle WithTofu.
+
+ qt: Fix tofuinfo test when gpg is gpg2.
+ * lang/qt/tests/t-support.cpp (QGpgMETest::copyKeyrings): New helper.
+ * lang/qt/tests/t-support.h: Declare.
+ * lang/qt/tests/t-encrypt.cpp: use it
+ * lang/qt/tests/t-tofuinbo.cpp: ditto.
+
+ qt: Remove unused variable in test.
+ * t-wkspublish.cpp (testWKSPublishCreate): Remove context.
+
+ qt: Add test for wkspublishjob.
+ * lang/qt/tests/t-wkspublish.cpp: New.
+ * lang/qt/tests/Makefile.am: Update accordingly.
+
+ qt: Add WKSPublishJob.
+ * lang/qt/src/Makefile.am: Add new files.
+ * lang/qt/src/job.cpp: Include moc / subclass stub.
+ * lang/qt/src/protocol.h: Add virtual for new job.
+ * lang/qt/src/protocol_p.h: Add job.
+ * lang/qt/src/wkspublishjob.h: Interface for WKSPublishJob.
+ * lang/qt/src/qgpgmewkspublishjob.cpp,
+ lang/qt/src/qgpgmewkspublishjob.h: New.
+
+ Cpp: Change firstSeen / lastSeen return values.
+ * lang/cpp/src/tofuinfo.cpp,
+ lang/cpp/src/tofuinfo.h (TofuInfo::firstSeen, TofuInfo::lastSeen):
+ Change return values to unsigned long and update doc.
+
+ Cpp: Add wrapper for gpgme_get_dirinfo.
+ * lang/cpp/src/context.cpp (dirInfo): New.
+ * lang/cpp/src/global.h (dirInfo): New.
+
+ Cpp: Add support for spawn engine.
+ * lang/cpp/src/context.cpp (Context::spawn, Context::spawnAsync): New.
+ * lang/cpp/src/context.h: Add prototypes.
+ (SpawnFlags): New.
+ * lang/cpp/src/global.h (SpawnEngine): Added.
+
+2016-08-25 Werner Koch <wk@gnupg.org>
+
+ core: Add GPGME_KEYLIST_MODE_WITH_TOFU.
+ * src/gpgme.h.in (GPGME_KEYLIST_MODE_WITH_TOFU): New.
+ * src/engine-gpg.c (gpg_keylist_build_options): Use that.
+ * src/keylist.c: Include limits.h.
+ (parse_tfs_record): New.
+ (keylist_colon_handler): Support TFS record.
+ * tests/run-keylist.c: Include time.h.
+ (isotimestr): New.
+ (main): Add option --tofu. Print TOFU info.
+ * tests/run-verify.c: Include time.h.
+ (isotimestr): New.
+ (print_result): Use isotimestr for TOFU dates.
+
+2016-08-24 Werner Koch <wk@gnupg.org>
+
+ core: Adjust for TOFU_STATS change in gnupg 2.1.16.
+ * src/gpgme.h.in (_gpgme_tofu_info): Change 'firstseen' and 'lastseen'
+ to a timestamp value.
+ * src/verify.c (parse_tofu_stats): Do not cap these values at UINT_MAX.
+
+ core: Set the 'encrcount' field in gpgme_tofu_info_t.
+ * src/verify.c (parse_tofu_stats): Set ENCRCOUNT field.
+
+ cpp: Get rid of AssuanResult due to its deprecation.
+ * lang/cpp/src/assuanresult.cpp: Remove.
+ * lang/cpp/src/assuanresult.h: Remove.
+ * lang/cpp/src/Makefile.am: Remove these files.
+ * lang/cpp/src/context.cpp: Remove header assuanresult.h
+ (assuanTransact): Change return type to Error. Use
+ gpgme_op_assuan_transact_ext.
+ (startAssuanTransaction): Change return type to Error.
+ (assuanResult): Remove
+ * lang/cpp/src/context.h (assuanResult): Adjust for changes.
+
+2016-08-24 Andre Heinecke <aheinecke@intevation.de>
+
+ Qt: Adapt (disabled) tofuinfo test to new API.
+ * lang/qt/tests/t-tofuinfo.cpp: Switch to UID based API.
+
+ Cpp: Add Key to signature.
+ * lang/cpp/src/verificationresult.cpp,
+ lang/cpp/src/verificationresult.h (Signature::key): New.
+
+ Cpp: Use fpr field for primaryFingerprint.
+ * lang/cpp/src/key.cpp (Key::primaryFingerprint): Return
+ fpr value if available.
+
+2016-08-23 Andre Heinecke <aheinecke@intevation.de>
+
+ Cpp: Move tofuinfo from signature to userid.
+ * lang/cpp/src/key.cpp (UserID::tofuInfo): New.
+ * lang/cpp/src/key.h: Update accordingly.
+ * lang/cpp/src/tofuinfo.cpp: Remove dropped fields.
+ * lang/cpp/src/tofuinfo.h: Update accordingly.
+ * lang/cpp/src/verificationresult.cpp,
+ lang/cpp/src/verificationresult.h: Remove tofu info.
+ * lang/qt/tests/t-tofuinfo.cpp: Disable for now.
+
+2016-08-23 Werner Koch <wk@gnupg.org>
+
+ core: Put the protocol into a TOFU created key object.
+ * src/verify.c (parse_tofu_user): Add arg 'protocol' and store it in
+ the KEY.
+ (_gpgme_verify_status_handler): Pass protocol.
+
+ core: Change the way TOFU information are represented.
+ * src/gpgme.h.in (struct _gpgme_signature): Remove field 'tofu'. Add
+ field 'key'.
+ (struct _gpgme_key): Add field 'fpr'.
+ (struct _gpgme_user_id): Add field 'tofu'.
+ (struct _gpgme_tofu_info): Remove fields 'address' and 'fpr'.
+ * src/key.c (gpgme_key_unref): Release TOFU and FPR.
+ * src/keylist.c (keylist_colon_handler): Store the fingerprint of the
+ first subkey also in KEY.
+ * src/verify.c (release_tofu_info): Remove.
+ (release_op_data): Release KEY.
+ (parse_tofu_user): Rewrite for new data structure.
+ (parse_tofu_stats): Ditto.
+ (parse_tofu_stats_long): Ditto.
+ * tests/run-verify.c (print_result): Ditto.
+ * tests/run-keylist.c (main): Print more fields.
+
+ core: Extend gpgme_user_id_t with 'address'.
+ * src/mbox-util.c, src/mbox-util.h: Adjust for use in gpgme.
+ * src/Makefile.am (main_sources): Add mbox-util.
+ * src/key.c (_gpgme_key_append_name): Set 'address' field of uid.
+ (gpgme_key_unref): Free it.
+
+2016-08-22 Werner Koch <wk@gnupg.org>
+
+ core: New code for parsing mail addresses.
+ * src/mbox-util.c: New.
+ * src/mbox-util.h: New.
+
+ core: Add new items for gpgme_get_dirinfo.
+ * src/dirinfo.c (WANT_SYSCONFDIR, WANT_LIBEXECDIR, WANT_LIBDIR): New.
+ (WANT_DATADIR, WANT_LCOALEDIR, WANT_AGENT_SSH_SOCKET): New
+ (WANT_DIRMNGR_SOCKET): New.
+ (dirinfo): Add fields 'sysconfdir', 'bindir', 'libexecdir', 'libdir',
+ 'datadir', 'localedir', 'agent_ssh_socket', and 'dirmngr_socket'.
+ (parse_output): Set these fields.
+ (get_gpgconf_item): Return them.
+ (gpgme_get_dirinfo): Likewise.
+
+ core: Base gpgme_get_dirinfo(uiserver-socket) on the socket dir.
+ * src/dirinfo.c (dirname_len): New.
+ (parse_output): Change computation of UISRV_SOCKET.
+
+2016-08-21 Werner Koch <wk@gnupg.org>
+
+ core: New commands --lang and --have-lang for gpgme-config.
+ * configure.ac (GPGME_CONFIG_AVAIL_LANG): New ac_subst.
+ * src/gpgme-config.in (avail_lang): Add commands --lang and
+ --have-lang.
+
+2016-08-18 Andre Heinecke <aheinecke@intevation.de>
+
+ core: Remove (now) useless diagnostic.
+ * src/w32-io.c(_gpgme_io_spawn): Remove spawnhelper not found
+ diagnostic.
+
+ core: Fail loudly in case w32 spawner not found.
+ * src/w32-io.c (_gpgme_io_spawn): Show a message box in
+ case gpgme-w32spawn.exe not found.
+
+2016-08-17 Andre Heinecke <aheinecke@intevation.de>
+
+ Cpp: Fix some pedantic warnings.
+ * lang/cpp/src/context.cpp,
+ lang/cpp/src/context.h (Context::getKeysFromRecipients): Remove
+ ignored / invalid const qualifier.
+ * lang/cpp/src/result.h: Don't shadow error function in ctor.
+
+2016-08-16 Werner Koch <wk@gnupg.org>
+
+ core: New global flag "require-gnupg".
+ * src/gpgme.c (gpgme_set_global_flag): Add flag.
+ * src/engine.c (engine_minimal_version): New variable.
+ (_gpgme_set_engine_minimal_version): New function.
+ (gpgme_get_engine_info): Check that flag.
+
+ * tests/run-keylist.c (main): New option --require-gnupg.
+
+ core: Simplify setting of dummy versions.
+ * src/engine.c (_gpgme_engine_info_release): Do not assert but free
+ FILE_NAME.
+ (gpgme_get_engine_info): Provide default for VERSION and REQ_VERSION.
+ Use calloc instead of malloc.
+ (_gpgme_set_engine_info): Ditto.
+ * src/engine-assuan.c (llass_get_version): Return NULL.
+ (llass_get_req_version): Ditto.
+ * src/engine-spawn.c (engspawn_get_version): Ditto.
+ (engspawn_get_req_version): Ditto.
+ * src/engine-uiserver.c (uiserver_get_version): Ditto.
+ (uiserver_get_req_version): Ditto.
+
+2016-08-12 Andre Heinecke <aheinecke@intevation.de>
+
+ Qt: Add test for progress signal of encryptjob.
+ * lang/qt/tests/t-encrypt.cpp (testProgress): New.
+
+ Cpp: Provide size-hint for seekable and mem data.
+ * lang/cpp/src/data.cpp (GpgME::Data::Data): Set size-hint for
+ mem and DataProvider based Data.
+
+2016-08-12 Werner Koch <wk@gnupg.org>
+
+ core: Make use of the "size-hint" in engine-gpg.
+ * src/engine-gpg.c: Include data.h.
+ (add_input_size_hint): New.
+ (gpg_decrypt, gpg_encrypt, gpg_encrypt_sign, gpg_sign)
+ (gpg_verify): Call new function,
+
+ * tests/run-encrypt.c (status_cb): Print to stderr.
+ (progress_cb): New.o
+ (main): Add option --progress. Print full-status lines. Provide a
+ size for the input data.
+
+ core: Add gpgme_data_set_flag to add more meta data to data objects.
+ * src/gpgme.h.in (gpgme_data_set_flag): New public function.
+ * src/data.c (gpgme_data_set_flag): New.
+ (_gpgme_data_get_size_hint): New.
+ * src/data.h (strucy gpgme_data): Add field 'size_hint'.
+ * src/gpgme.def, src/libgpgme.vers: Add new function.
+ * src/conversion.c (_gpgme_string_to_off): New.
+
+2016-08-12 Andre Heinecke <aheinecke@intevation.de>
+
+ Qt: Fix defaultkeygenerationjob build.
+ * lang/qt/src/defaultkeygenerationjob.cpp: Include moc.
+
+2016-08-11 Andre Heinecke <aheinecke@intevation.de>
+
+ Qt: Add DefaultKeyGenerationJob.
+ * lang/qt/src/defaultkeygenerationjob.cpp,
+ lang/qt/src/defaultkeygenerationjob.h: New.
+ * lang/qt/src/Makefile.am: Update accordingly.
+
+ Qt: Ensure all public classes are exported.
+ * src/abstractimportjob.h,
+ src/cryptoconfig.h,
+ src/deletejob.h,
+ src/exportjob.h,
+ src/importfromkeyserverjob.h,
+ src/importjob.h,
+ src/keygenerationjob.h,
+ src/keylistjob.h,
+ src/listallkeysjob.h,
+ src/refreshkeysjob.h,
+ src/signencryptjob.h,
+ src/specialjob.h,
+ src/verifydetachedjob.h: Export classes.
+
+ Qt: Add KeyForMailboxJob.
+ * lang/qt/src/job.cpp: Include moc and make subclass.
+ * lang/qt/src/keyformailboxjob.h,
+ lang/qt/src/qgpgmekeyformailboxjob.cpp,
+ lang/qt/src/qgpgmekeyformailboxjob.h: New.
+ * lang/qt/tests/run-keyformailboxjob.cpp: New manual test.
+ * lang/qt/tests/Makefile.am: Add run-keyformailboxjob.
+ * lang/qt/src/Makefile.am: Update accordingly.
+ * lang/qt/src/protocol.h, lang/qt/src/protocol_p.h: Add
+ keyformailboxjob.
+
+2016-08-10 Werner Koch <wk@gnupg.org>
+
+ doc: Get rid of version.texi.
+ * configure.ac (CC_FOR_BUILD): New.
+ * doc/mkdefsinc.c: New. Taken from GnuPG and modified for gpgme.
+ * doc/Makefile.am (EXTRA_DIST): Add defsincdate and mkdefsinc.c
+ (BUILT_SOURCES): new.
+ (gpgme.texi): New dependency.
+ (mkdefsinc, defsincdate, defs.inc): New rules.
+ (dist-hook): New.
+ * doc/gpgme.texi: Include defs.inc. Remove version.texi.
+
+ build: Declare all languages for make dist.
+ * lang/Makefile.am (DIST_SUBDIRS): New.
+
+ core: Do not identify PNG files as PGP signatures.
+ * src/data-identify.c (next_openpgp_packet): Blacklist PNG files.
+
+2016-08-10 Andre Heinecke <aheinecke@intevation.de>
+
+ Cpp: Handle empty recipients consistently.
+ * lang/cpp/src/context.cpp (Context::getKeysFromRecipients):
+ New helper.
+ (Context::encrypt, Context::startEncryption, Context::signAndEncrypt)
+ (Context::startCombinedSigningAndEncryption): Use new helper.
+ * lang/cpp/src/context.h (Context::getKeysFromRecipients): Add
+ as private helper.
+
+ core: Handle ENCRYPT_SYMMETRIC also for sig & enc.
+ * src/engine-gpg.c (gpg_encrypt_sign): Handle ENCRYPT_SYMMETRIC
+ flag.
+
+ Qt: Remove unused variable.
+ * lang/qt/src/qgpgmerefreshkeysjob.cpp (slotStatus): Remove
+ unused variable typ.
+
+ Qt: Create TestPassphraseProvider on stack.
+ * lang/qt/tests/t-encrypt.cpp, lang/qt/tests/t-tofuinfo.cpp: Create
+ TestPassphraseProvider on stack.
+
+ Cpp: Clarify ownership of provider classes.
+ * lang/cpp/src/context.h: Note that the context does not take
+ ownership of providers.
+
+2016-08-10 Justus Winter <justus@g10code.com>
+
+ tests: Fix memory leak.
+ * tests/gpg/t-encrypt-mixed.c (main): Free 'text2'.
+
+2016-08-10 Andre Heinecke <aheinecke@intevation.de>
+
+ core: Ensure err is initalized in gpg_encrypt.
+ * src/engine-gpg.c (gpg_encrypt): Initialize err.
+
+ Qt: Fix t-keylist moc include.
+ * lang/qt/tests/t-keylist.cpp: Don't include t-support.moc
+
+2016-08-09 Andre Heinecke <aheinecke@intevation.de>
+
+ Qt: Clean up debug output in tests.
+ * lang/qt/tests/t-support.cpp: Remove accidentally commited
+ debug output.
+
+ Qt: Add encryption test and refactor testsuite.
+ * lang/qt/tests/Makefile.am: Add t-encrypt and t-support.
+ * lang/qt/tests/t-support.cpp, lang/qt/tests/t-support.c (QGpgMETest):
+ New. Class to handle common cleanup / init.
+ * lang/qt/tests/t-keylist.cpp,
+ lang/qt/tests/t-keylocate.cpp,
+ lang/qt/tests/t-ownertrust.cpp,
+ lang/qt/tests/t-tofuinfo.cpp: Inherit QGpgMETest.
+ * lang/qt/tests/t-encrypt.cpp: New. Test Symetric and Asymectric
+ encryption. Mixed encryption test is disabled.
+
+ Qt: Add support for EncryptJobs with generic flags.
+ * lang/qt/src/encryptjob.h, lang/qt/src/signencryptjob.h,
+ lang/qt/src/qgpgmeencryptjob.h, lang/qt/src/qgpgmeencryptjob.cpp,
+ lang/qt/src/qgpgmesignencryptjob.cpp,
+ lang/qt/src/qgpgmeencryptjob.cpp: Add start and exec overloads
+ that accept generic EncryptFlags.
+
+ Cpp: Add support for all EncryptionFlags.
+ * lang/cpp/src/context.h (EncryptionFlags): Extend.
+ * lang/cpp/src/context.cpp (encryptflags2encryptflags): Ditto.
+
+ Cpp: Fix simple symmetric encryption.
+ * lang/cpp/src/context.cpp (Context::encrypt): If no recipients
+ are provided encrypt with NULL and not an empty array.
+
+ core: Add support for mixed symmetric and asym enc.
+ * src/gpgme.h.in (gpgme_encrypt_flags_t): New flag
+ GPGME_ENCRYPT_SYMMETRIC.
+ * src/engine-gpg.c (gpg_encrypt): Also add --symmetric if the flag
+ is given.
+ * NEWS: Mention new flag.
+ * tests/run-encrypt.c (show_usage): Extend for --symmetric.
+ (main): Handle --symmetric.
+ (main): Set passphrase_cb in loopback mode.
+ (main): Fix encrypt call if no recipients are given.
+ * tests/gpg/t-encrypt-mixed.c: New.
+ * tests/gpg/Makefile.am (c_tests): Add new test.
+ * doc/gpgme.texi: Document new flag.
+
+2016-08-08 Werner Koch <wk@gnupg.org>
+
+ core: Let GPGME_PROTOCOL_ASSUAN pass Assuan comments through.
+ * src/engine-assuan.c (llass_new): Set ASSUAN_CONVEY_COMMENTS,
+
+2016-08-08 Andre Heinecke <aheinecke@intevation.de>
+
+ Prepend LD_LIBRARY_PATH for python tests.
+ * lang/python/tests/Makefile.am (TESTS_ENVIRONMENT): Prepend path
+ instead of setting the value.
+
+2016-08-05 Justus Winter <justus@g10code.com>
+
+ python: Clean up and modernize examples.
+ * lang/python/examples/Examples.rst: Delete file.
+ * lang/python/examples/t-edit.py: Likewise. This is actually a test
+ case and has been moved to 'tests'.
+ * lang/python/examples/assuan.py: New file.
+ * lang/python/examples/decryption-filter.py: Likewise.
+ * lang/python/examples/delkey.py: Modernize.
+ * lang/python/examples/encrypt-to-all.py: Likewise.
+ * lang/python/examples/exportimport.py: Likewise.
+ * lang/python/examples/genkey.py: Likewise.
+ * lang/python/examples/inter-edit.py: Likewise.
+ * lang/python/examples/sign.py: Likewise.
+ * lang/python/examples/signverify.py: Likewise.
+ * lang/python/examples/simple.py: Likewise.
+ * lang/python/examples/testCMSgetkey.py: Likewise.
+ * lang/python/examples/verifydetails.py: Likewise.
+
+2016-08-04 Werner Koch <wk@gnupg.org>
+
+ core: Extend gpgme_subkey_t to carry the keygrip.
+ * src/gpgme.h.in (struct _gpgme_subkey): Add file 'keygrip'.
+ * src/key.c (gpgme_key_unref): Free KEYGRIP.
+ * src/keylist.c (keylist_colon_handler): Parse GRP records.
+ * src/engine-gpg.c (gpg_keylist_build_options): Do not use
+ --with-fingerprint options for gpg versions >= 2.1.15.
+
+ * tests/run-keylist.c (main): Print subkeys and keygrips.
+
+2016-08-03 Justus Winter <justus@g10code.com>
+
+ python: Add a nicer interface to list keys.
+ * lang/python/pyme/core.py (Context.keylist): New method.
+ * lang/python/tests/t-keylist.py: Test new method.
+
+2016-08-02 Justus Winter <justus@g10code.com>
+
+ python: Add a flag identifying in-tree builds.
+ * lang/python/helpers.c (pyme_in_tree_build): New variable.
+ * lang/python/helpers.h (pyme_in_tree_build): New declaration.
+ * lang/python/pyme/version.py.in (in_tree_build): New variable.
+ * lang/python/setup.py.in: Rework macro handling, set 'IN_TREE_BUILD'
+ as appropriate.
+
+ python: Fix build system integration.
+ * lang/python/Makefile.am: Be more careful when cleaning the build
+ directory, we must not delete the generated file 'pyme/version.py'.
+
+ doc: Document the Assuan protocol.
+ * doc/gpgme.texi: Document the Assuan protocol.
+
+ GnuPG-bug-id: 2407
+
+2016-07-28 Justus Winter <justus@g10code.com>
+
+ python: Fix out-of-tree build.
+ * lang/python/MANIFEST.in: Add 'private.h'.
+
+ Fixes-commit: 3d4dc3f0
+
+ python: Improve error handling.
+ * lang/python/pyme/core.py (Context.protocol): Check that the engine
+ is usable before setting the protocol.
+ (Context._errorcheck): Add missing functions.
+
+ src: Fix dummy engine versions.
+ Previously, 'gpgme_engine_check_version' failed for these protocols
+ because the version parser failed to parse the dummy versions.
+
+ * src/engine-assuan.c (llass_get_version): Use a version triple that
+ the parser can understand.
+ (llass_get_req_version): Likewise.
+ * src/engine-spawn.c (engspawn_get_version): Likewise.
+ (engspawn_get_req_version): Likewise.
+ * src/engine-uiserver.c (uiserver_get_version): Likewise.
+ (uiserver_get_req_version): Likewise.
+
+ python: Drop superfluous imports and trim public interface.
+ * lang/python/pyme/__init__.py: Avoid leaking low-level 'gpgme', make
+ sure the main module looks nice and tidy, appease pyflakes.
+ * lang/python/pyme/errors.py: Appease pyflakes.
+ * lang/python/pyme/util.py: Avoid leaking low-level 'gpgme' into the
+ module namespace.
+ * lang/python/pyme/version.py.in: Likewise.
+ * lang/python/tests/t-keylist.py: Drop superfluous imports.
+ * lang/python/tests/t-sig-notation.py: Likewise.
+ * lang/python/tests/t-sign.py: Likewise.
+ * lang/python/tests/t-signers.py: Likewise.
+
+ python: Rename compiled SWIG module.
+ Avoid the name pygpgme, as this is the name of another popular Python
+ binding for GPGME.
+
+ This commit renames the compiled Python module produced by SWIG.
+
+ * lang/python/Makefile.am: Rename the compiled Python module.
+ * lang/python/gpgme.i: Likewise.
+ * lang/python/pyme/core.py: Likewise.
+ * lang/python/pyme/errors.py: Likewise.
+ * lang/python/pyme/util.py: Likewise.
+ * lang/python/pyme/version.py.in: Likewise.
+ * lang/python/setup.py.in: Likewise.
+
+ python: Rename exported functions.
+ Avoid the name pygpgme, as this is the name of another popular Python
+ binding for GPGME.
+
+ This commit renames all functions that are exported to the Python
+ world.
+
+ * lang/python/helpers.c: Rename all exported functions.
+ * lang/python/helpers.h: Likewise.
+ * lang/python/pyme/core.py: Likewise.
+
+ python: Rename private functions.
+ Avoid the name pygpgme, as this is the name of another popular Python
+ binding for GPGME.
+
+ This commit renames all functions that are not exported to the Python
+ world.
+
+ * lang/python/gpgme.i: Rename all private functions.
+ * lang/python/helpers.c: Likewise.
+ * lang/python/helpers.h: Likewise.
+ * lang/python/private.h: Likewise. Also move the SWIG runtime helper
+ prototypes here.
+
+ python: Support the Assuan engine.
+ * lang/python/gpgme.i: Add typemaps for the Assuan protocol callbacks.
+ * lang/python/helpers.c (_pyme_assuan_{data,inquire,status}_cb): New
+ functions.
+ * lang/python/private.h (_pyme_assuan_{data,inquire,status}_cb): New
+ prototypes.
+ * lang/python/pyme/core.py (Context.assuan_transact): New method.
+ * lang/python/pyme/util.py (percent_escape): New function.
+ * lang/python/tests/Makefile.am (py_tests): Add new test.
+ * lang/python/tests/t-protocol-assuan.py: New file.
+
+ python: Improve engine information handling.
+ * lang/python/gpgme.i (gpgme_engine_info_t): Wrap engine infos.
+ * lang/python/pyme/core.py (Context.engine_info): New property.
+ (Context.{g,s}et_engine_info): Improve docstrings.
+ * lang/python/pyme/results.py (EngineInfo): New class.
+
+ python: Add accessors for the protocol.
+ * lang/python/pyme/core.py (Context.__init__): Add 'protocol'
+ parameter.
+ (Context.protocol): New accessors.
+
+ python: Expose less functions to the Python world.
+ * lang/python/Makefile.am (EXTRA_DIST, COPY_FILES): Add new file.
+ * lang/python/gpgme.i: Include new file and add comments.
+ * lang/python/helpers.c: Include new file.
+ * lang/python/helpers.h: Move functions we do not need to expose...
+ * lang/python/private.h: ... here.
+
+2016-07-19 Ben Kibbey <bjk@luxsci.net>
+
+ Fix including nil bytes in keylist output.
+ * src/gpgme-tool.c (cmd_keylist,gt_result): use strlen().
+
+2016-07-15 Justus Winter <justus@g10code.com>
+
+ python: Make GPGME's version easily accessible.
+ * lang/python/pyme/version.py.in (gpgme_versionstr): New variable.
+
+ python: Add an idiomatic interface.
+ * configure.ac: Bump required Python version.
+ * lang/python/pyme/__init__.py: Update docstring. Import Context and
+ Data.
+ * lang/python/pyme/core.py (Context.encrypt): New function.
+ (Context.decrypt): Likewise.
+ (Context.sign): Likewise.
+ (Context.verify): Likewise.
+ * lang/python/pyme/errors.py: Add new errors.
+ * lang/python/pyme/util.py (process_constants): Rework and return the
+ inserted keys.
+ * lang/python/tests/Makefile.am (EXTRA_DIST): Add new keys.
+ * lang/python/tests/encrypt-only.asc: New file.
+ * lang/python/tests/sign-only.asc: Likewise.
+ * lang/python/tests/initial.py: Mark key 'Alpha' as trusted, import
+ new keys.
+ * lang/python/tests/support.py: Add fingerprints of known keys.
+ (in_srcdir): New function.
+ (print_data): Handle bytes too.
+ (mark_key_trusted): New function.
+ * lang/python/tests/t-decrypt-verify.py: Adjust test. Test idiomatic
+ interface.
+ * lang/python/tests/t-decrypt.py: Test idiomatic interface.
+ * lang/python/tests/t-encrypt-sign.py: Likewise.
+ * lang/python/tests/t-encrypt-sym.py: Likewise.
+ * lang/python/tests/t-encrypt.py: Likewise.
+ * lang/python/tests/t-idiomatic.py: Simplify.
+ * lang/python/tests/t-keylist.py: Adjust to newly trusted key.
+ * lang/python/tests/t-sign.py: Likewise. Test idiomatic interface.
+ * lang/python/tests/t-signers.py: Likewise.
+ * lang/python/tests/t-verify.py: Likewise.
+
+2016-07-14 Andre Heinecke <aheinecke@intevation.de>
+
+ Qt: Disable keylocate test for gnupg < 2.0.10.
+ * lang/qt/tests/t-keylocate.cpp: Disable test for gnupg < 2.0.10
+
+ Cpp: Add EngineInfo::Version class.
+ * lang/cpp/src/engineinfo.cpp (EngineInfo::engineVersion): New.
+ * lang/cpp/src/engineinfo.h (EngineInfo::engineVersion): Declare.
+ (EngineInfo::Version): Small helper to work with versions.
+
+ Qt: Fix usage of ignore-invalid-option in tests.
+ * Makefile.am (pubring-stamp): Fix config.
+
+ Qt: Fix tests if gpg2 is gpg.
+ * lang/qt/tests/Makefile.am (pubring-stamp): Loopback and provide
+ passphrase on command line when importing.
+
+2016-07-14 Justus Winter <justus@g10code.com>
+
+ python: Fix test.
+ * lang/python/tests/t-keylist.py: Do not assume key alpha is trusted
+ yet.
+
+2016-07-13 Werner Koch <wk@gnupg.org>
+
+ build: Update config.{guess,sub} to {2016-05-15,2016-06-20}.
+ * build-aux/config.guess: Update.
+ * build-aux/config.sub: Update.
+
+ core: New GPGME_DATA_ENCODING_MIME.
+ * src/gpgme.h.in (GPGME_DATA_ENCODING_MIME): New.
+ * src/data.c (gpgme_data_set_encoding): Adjust check.
+ * src/engine-gpg.c (have_gpg_version): New.
+ (gpg_encrypt, gpg_encrypt_sign): Pass flag '--mimemode'.
+ (gpg_sign): Ditto.
+
+ * lang/cpp/src/data.h (GpgME): Add MimeEncoding.
+ * lang/cpp/src/data.cpp (encoding, setEncoding): Support MimeEncoding.
+
+ * src/gpgme-tool.c (server_data_encoding): Add flag --mime.
+
+ core: Pass the engine's version string to the engine's new function.
+ * src/engine-backend.h (engine_ops): Add arg 'version' to NEW.
+ * src/engine-assuan.c (llass_new): Add dummy arg 'version'.
+ * src/engine-g13.c (g13_new): Ditto.
+ * src/engine-gpgconf.c (gpgconf_new): Ditto.
+ * src/engine-gpgsm.c (gpgsm_new): Ditto.
+ * src/engine-spawn.c (engspawn_new): Ditto.
+ * src/engine-uiserver.c (uiserver_new): Ditto.
+ * src/engine.c (_gpgme_engine_new): Pass version string to the new
+ function.
+ * src/engine-gpg.c (struct engine_gpg): Add field 'version'.
+ (gpg_new): Add arg 'version'.
+ (gpg_release): Free VERSION.
+
+2016-07-13 Andre Heinecke <aheinecke@intevation.de>
+
+ Cpp: Add feature enum for new identify.
+ * lang/cpp/src/context.cpp (supported_features2): Add
+ BinaryAndFineGrainedIdentify
+ * lang/cpp/src/global.h (Feature2): ditto.
+
+2016-07-12 Justus Winter <justus@g10code.com>
+
+ python: Port more tests.
+ * lang/python/pyme/core.py (Context.op_keylist_all): Add missing
+ 'op_keylist_end'.
+ (Context.op_trustlist_all): Fix function. Add missing
+ 'op_trustlist_end'.
+ * lang/python/tests/Makefile.am (pytests): Add new files.
+ * lang/python/tests/t-import.py: New file.
+ * lang/python/tests/t-keylist.py: Likewise.
+ * lang/python/tests/t-trustlist.py: Check alternate interface.
+
+ python: Improve python packaging.
+ * lang/python/Makefile.am: Sign source releases, and upload them.
+ * lang/python/setup.py.in: Add categories.
+
+2016-07-12 Andre Heinecke <aheinecke@intevation.de>
+
+ m4: Don't set fpic for qt on windows.
+ * m4/qt.m4 (FIND_QT): Do not set fpic for windows.
+
+ m4: Use LIBS instead of LDFLAGS for Qt libs.
+ * m4/qt.m4: Modify LIBS instead of LDFLAGS for link test.
+
+ Bump version to 1.7.0.
+ * configure.ac(mym4_version_minor),
+ (mym4_version_micro): Next release will be 1.7.0
+
+ Qt: Install CamelCase forward includes.
+ * lang/qt/src/Makefile.am (camelcase_headers): New. Create and install
+ CamelCase headers.
+
+ Qt: Export VerifyDetachedJob.
+ * lang/qt/src/verifydetachedjob.h (VerifyDetachedJob): Export it.
+
+ Qt/Cpp: Add version headers.
+ * lang/cpp/src/gpgmepp_version.h.in,
+ lang/qt/src/qgpgme_version.h.in: New. Version information.
+ * lang/qt/src/Makefile.am, lang/cpp/src/Makefile.am: Add them.
+ * configure.ac: Configure them.
+
+ Qt/Cpp: Add license blurb to export headers.
+ * lang/cpp/src/gpgmepp_export.h,
+ lang/qt/src/qgpgme_export.h: Add license blurb.
+
+2016-07-11 Justus Winter <justus@g10code.com>
+
+ python: Fix distcheck.
+ * lang/python/Makefile.am (EXTRA_DIST): Add missing files.
+
+2016-07-11 Andre Heinecke <aheinecke@intevation.de>
+
+ m4: Add compile / link check for qt.
+ * m4/qt.m4 (FIND_QT): Check if a qt application can be compiled and
+ linked.
+
+2016-07-11 Justus Winter <justus@g10code.com>
+
+ python: Enable out-of-tree build of pyme bindings.
+ * lang/python/MANIFEST.in: Update manifest template.
+ * lang/python/Makefile.am: Copy more files, move generation of files
+ to Python build script, add 'sdist' target to build a Python source
+ distribution.
+ * lang/python/gpgme-h-clean.py: Add code to build 'errors.i'.
+ * lang/python/setup.py.in: Generate files, enable out-of-tree builds.
+
+ python: Do not depend on access to internal data structures.
+ * lang/python/gpgme.i (gpgme_data_t): Rework so that it works without
+ access to the definition of 'struct gpgme_data'.
+ * lang/python/helpers.c (object_to_gpgme_data_t): Add assertion.
+
+ python: Make result wrapping backwards compatible.
+ * lang/python/pyme/results.py (Result.__init__): Skip missing fields.
+
+2016-07-11 Andre Heinecke <aheinecke@intevation.de>
+
+ Qt: Fix memleaks in tests.
+ * lang/qt/tests/t-keylist.cpp(cleanupTestCase): Ensure that
+ posted events are handled for autodeletion.
+ (testSingleKeylistSync): delete job.
+ * lang/qt/tests/t-ownertrust.cpp(cleanupTestCase): Ditto
+ * lang/qt/tests/t-ownertrust.cpp(testChangeOwnerTrust): Delete
+ keylistjobs.
+ * lang/qt/tests/t-keylocate.cpp(cleanupTestCase): Ditto
+
+ Qt: Add some general Protocol documentation.
+ * lang/qt/src/protocol.h (Protocol): Add doc.
+
+ Qt: Disable t-tofuinfo tests.
+ * lang/qt/tests/t-tofuinfo.cpp: Disable tests.
+
+2016-07-08 Justus Winter <justus@g10code.com>
+
+ src: Fix error handling.
+ * src/encrypt.c (encrypt_status_handler): Fix error handling, ||
+ conflates errors.
+
+ python: Fix raising stashed exceptions.
+ Fixes an issue with newer versions of Python.
+
+ * lang/python/helpers.c (pygpgme_raise_callback_exception): Be more
+ careful when restoring the exception.
+
+2016-07-07 Justus Winter <justus@g10code.com>
+
+ python: Fix distcheck.
+ * lang/python/INSTALL: Drop obsolete file.
+ * lang/python/Makefile.am (EXTRA_DIST): Add missing files.
+ (CLEANFILES): Remove generated files.
+ (clean-local): Fix permissions of copied files.
+ * lang/python/tests/Makefile.am (TESTS): Use our own setup and
+ teardown scripts.
+ (EXTRA_DIST): Add missing files.
+ * lang/python/tests/final.py: New file.
+ * lang/python/tests/initial.py: Likewise.
+
+ qt: Fix distcheck.
+ * lang/qt/src/Makefile.am (qgpgme_headers): Add missing file.
+ (CLEANFILES): Add generated file.
+ * lang/qt/tests/Makefile.am (clean-local): Remove private keys.
+
+ cpp: Fix distcheck.
+ * lang/cpp/src/Makefile.am (CLEANFILES): Remove generated file.
+
+2016-07-06 Andre Heinecke <aheinecke@intevation.de>
+
+ Qt: Add test for publicKeyAlgorithmAsString.
+ * lang/qt/tests/t-keylist.cpp (testPubkeyAlgoAsString): New.
+
+ Cpp: Expose gpgme_pubkey_algo_name.
+ * lang/cpp/src/key.cpp (Subkey::publicKeyAlgorithmAsString): New
+ static variant.
+ * lang/cpp/src/key.h: Declare function. Clarify comment about name
+ mismatch.
+
+ Qt: Add check for pubkeyAlgo in t-keylist.
+ * lang/qt/tests/t-keylist.cpp (testSingleKeyListSync): Check
+ pubkeyAlgo.
+
+ Cpp: Add PubkeyAlgo enum.
+ * lang/cpp/src/key.h (Subkey::PubkeyAlgo): New enum.
+ (Subkey::publicKeyAlgorithm): Change return type.
+ * lang/cpp/src/key.cpp (Subkey::publicKeyAlgorithm): Use enum.
+
+ Qt: Fix include order when buildin test.
+ * lang/qt/tests/Makefile.am (AM_CPPFLAGS): Include cpp before
+ gpgme src directory.
+
+ Revert "Qt: More robust lookup of Cpp's context.h"
+ * lang/qt/src/threadedjobmixin.h: Revert using full path
+ for context.h
+
+2016-07-05 Andre Heinecke <aheinecke@intevation.de>
+
+ Qt: Fix test build with Qt < 5.4.0.
+ * lang/qt/tests/t-keylist.cpp,
+ lang/qt/tests/t-keylocate.cpp,
+ lang/qt/tests/t-ownertrust.cpp: Use old style SIGNAl syntax for
+ QSignalSpy
+
+ Qt: More robust lookup of Cpp's context.h.
+ * lang/qt/src/threadedjobmixin.h: When building qgpgme look for
+ context.h in the full cpp subdirectory.
+
+ w32: Fallback to 2.1 reg key for gpgconf search.
+ * src/w32-util.c (_gpgme_get_gpgconf_path): Fallback to 2.1 installer
+ registry key.
+
+2016-07-04 Andre Heinecke <aheinecke@intevation.de>
+
+ Doc: Document pinentry mode.
+ * doc/gpgme.texi (Passphrase Callback): Document as context
+ attribute.
+ (gpgme_set_passphrase_cb): Note that this requires LOOPBACK mode
+ with GnuPG 2.1.
+
+ Qt: Add testTofuSignCount.
+ * src/lang/qt/tests/t-tofuinfo.cpp(testTofuSignCount): New.
+ (initTestCase): Set gpg-agent loopback pinentry config.
+ (signAndVerify): Helper for tofuTestSignCount.
+
+ Qt: Add test passphrase provider.
+ * lang/qt/tests/t-support.h (TestPassphraseProvider): New.
+ * lang/qt/tests/Makefile.am (t_tofuinfo_SOURCES): Add t-support.h
+
+ Cpp: Add support for TOFU_CONFLICT sigsum.
+ * lang/cpp/src/verificationresult.cpp (GpgME::Signature::Summary):
+ Handle TOFU_CONFLICT.
+ * lang/cpp/src/verificationresult.h (Summary): Add TofuConflict.
+
+ Cpp: Add support for pinentry_mode.
+ * lang/cpp/src/context.cpp (Context::pinentryMode): Return mode.
+ (Context::setPinentryMode): Set mode.
+ * lang/cpp/src/context.h (PinentryMode): Add enum.
+
+2016-07-01 Andre Heinecke <aheinecke@intevation.de>
+
+ Qt: Add test for TofuInfo.
+ * lang/qt/tests/t-tofuinfo.cpp: New.
+ * lang/qt/tests/Makefile.am: Update accordingly.
+
+ Cpp: Add TofuInfo to signatures.
+ * lang/cpp/src/tofuinfo.cpp, lang/cpp/src/tofuinfo.h: New class.
+ * lang/cpp/src/verificationresult.cpp (Signature::tofuInfo): New.
+ (VerificationResult::Private): Handle tofu info.
+ (GpgME::operator<<(std::ostream &os, const Signature &sig)): Include
+ TofuInfo in dump.
+ * lang/cpp/src/verificationresult.h (Signature::tofuInfo): New.
+ * lang/cpp/src/Makefile.am (main_sources, gpgmepp_headers): Add
+ new files.
+ * configure.ac (LIBGPGMEPP_LT_REVISION): Bump for new API.
+
+ core: Clarify documentation of tofu_stats address.
+ * src/gpgme.h.in: Mention that Address is not always in addr-spec.
+
+ core: Fix identify for armored detached sigs.
+ * src/data-identify.c (basic_detection): Return signature for
+ signature.
+
+2016-06-27 Andre Heinecke <aheinecke@intevation.de>
+
+ Cpp: Expose new data_identify values.
+ * lang/cpp/src/data.cpp (GpgME::Data::type): Handle PGP Encrypted
+ and Signature.
+ * lang/cpp/src/data.h: Add values accordingly.
+
+ Cpp: Do not treat KEYEXPIRED as error.
+ * lang/cpp/src/editinteractor.cpp (status_to_error): No error
+ for KEYEXPIRED.
+
+2016-06-24 Andre Heinecke <aheinecke@intevation.de>
+
+ tests: Add new test tool run-decrypt.
+ * tests/run-decrypt.c: New.
+ * tests/Makefile.am (noinst_PROGRAMS): Add run-decrypt.
+
+2016-06-23 Werner Koch <wk@gnupg.org>
+
+ core: Add closer inspection of "PGP MESSAGE".
+ * src/data-identify.c (inspect_pgp_message): New.
+ (basic_detection): Un-const arg DATA. Call inspect_pgp_message.
+
+ core: Add a base 64 decoder.
+ * src/b64dec.c: New. Taken from gnupg. Prefix function names with
+ _gpgme_ and change to use standard C malloc functions.
+ * src/util.h.h (struct b64state): New.
+ * src/Makefile.am (main_sources): Add file.
+
+2016-06-22 Werner Koch <wk@gnupg.org>
+
+ core: Detect compressed signed OpenPGP data.
+ * src/data-identify.c (next_openpgp_packet): Allow partial encoding.
+ (pgp_binary_detection): Handle compressed packets.
+
+2016-06-21 Werner Koch <wk@gnupg.org>
+
+ tests: Add new test tool run-identify.
+ * src/gpgme-tool.c (gt_identify): Add new strings.
+ * tests/run-identify.c: New.
+ * tests/Makefile.am (noinst_PROGRAMS): Add run-identify.
+
+ core: Enhance gpgme_data_identify to detect binary PGP messages.
+ * src/gpgme.h.in (GPGME_DATA_TYPE_PGP_ENCRYPTED): New.
+ (GPGME_DATA_TYPE_PGP_SIGNATURE): New.
+ * src/data-identify.c: Add enum for OpenPGP packet types.
+ (buf32_to_ulong): New.
+ (next_openpgp_packet): New. Based on the gnupg/kbx/keybox-openpgp.c
+ implementation and relicensed to LGPL by g10 Code.
+ (pgp_binary_detection): New.
+ (basic_detection): Call pgp_binary_detection instead of returning
+ unknown.
+
+2016-06-16 Justus Winter <justus@g10code.com>
+
+ python: Improve autmatically generated docstrings.
+ * lang/python/gpgme.i: Add comment.
+ * lang/python/pyme/core.py (__getattr__): Rewrite automatically
+ generated doctrings for the wrapper methods.
+
+ python: Make result objects more robust.
+ Results returned by the GPGME are fragile, i.e. they are only valid
+ until the next operation is performed in the context.
+
+ We cannot arbitrarily constrain the lifetime of Python objects, we
+ therefore create deep copies of the results.
+
+ * lang/python/gpgme.i (gpgme_tofu_info_t): Turn these into a list.
+ (gpgme_*_result_t): Create deep copies of these objects.
+ * lang/python/helpers.c (pygpgme_wrap_fragile_result): New function.
+ * lang/python/helpers.h (pygpgme_wrap_fragile_result): New prototype.
+ * lang/python/pyme/results.py: New file.
+
+ python: Avoid creating SWIG proxy classes.
+ * lang/python/Makefile.am (gpgme_wrap.c): Use '-builtin' to make SWIG
+ generate builtin types for c types.
+ * lang/python/gpgme.i (pygpgme_wrap_gpgme_data_t): Adapt slightly.
+
+ python: Simplify wrapping glue.
+ * lang/python/pyme/core.py: Rename '_getctype' to '_ctype' and turn it
+ into a string. Likewise rename '_getnameprepend' to '_cprefix'.
+ * lang/python/helpers.c: Adapt accordingly.
+
+ python: Rework callbacks.
+ Simplify how the lifetime of callback arguments is managed.
+
+ * lang/python/gpgme.i (gpgme_edit_cb_t): Check arguments.
+ (PyObject_p_p, void_p_p): Drop rather dangerous interface.
+ (pygpgme_unwrap_gpgme_ctx_t): New function.
+ * lang/python/helpers.c (pygpgme_clear_generic_cb): Drop dangerous
+ function.
+ (pyPassphraseCb): Assert contract.
+ (pygpgme_set_passphrase_cb): Use Python's calling convention so that
+ we can raise exceptions. Hand in 'self', get the wrapped object, and
+ simply store the hook data as attribute of the wrapper object.
+ (pyProgressCb, pygpgme_set_progress_cb): Likewise.
+ (pygpgme_set_status_cb): Likewise.
+ (pygpgme_data_new_from_cbs): Likewise.
+ * lang/python/helpers.h (pygpgme_clear_generic_cb): Drop prototype.
+ (pygpgme_set_passphrase_cb): Update prototype.
+ (pygpgme_set_progress_cb): Likewise.
+ (pygpgme_set_status_cb): Likewise.
+ (pygpgme_data_new_from_cbs): Likewise.
+ (pygpgme_unwrap_gpgme_ctx_t): New prottotype.
+ * lang/python/pyme/core.py (Context, Data): Update callsites.
+
+ python: Wrap objects implementing the buffer protocol.
+ * lang/python/Makefile.am: Add the toplevel source directory to CFLAGS
+ when compiling the bindings so that we can use private header files.
+ * lang/python/gpgme.i (gpgme_data_t): Rework the object wrapping. Do
+ not create a Python wrapper object, merely a gpgme_data_t object, and
+ keep references to buffer objects, if any. If necessary, update the
+ buffer after the function call.
+ (pygpgme_wrap_gpgme_data_t): New function.
+ * lang/python/helpers.c (object_to_gpgme_data_t): Rework object
+ wrapping. Also wrap objects implementing the buffer protocol.
+ * lang/python/helpers.h (object_to_gpgme_data_t): Update prototype.
+ (pygpgme_wrap_gpgme_data_t): New prototype.
+ * lang/python/tests/t-idiomatic.py: Demonstrate this.
+
+ python: Add properties to wrapped object.
+ * lang/python/pyme/core.py (GpgmeWrapper.__repr__): Saner
+ representation.
+ (GpgmeWrapper.__str__): Construct a nicer human readable string.
+ (GpgmeWrapper._boolean_properties): New field.
+ (GpgmeWrapper.__wrap_boolean_property): New function.
+ (GpgmeWrapper.__getattr__): Wrap functions using properties.
+ (GpgmeWrapper.__setattr__): New method. Likewise wrap functions.
+ (Context.signers): New property.
+ (Context.pinentry_mode): Likewise.
+ (Context._boolean_properties): List boolean properties.
+ (Context.__init__): Add keyword arguments for properties and apply
+ them.
+
+ python: Improve the documentation.
+ * lang/python/Makefile.am: Copy the README file.
+ * lang/python/README: Rename, convert to org, and update.
+ * lang/python/pyme/__init__.py: Move license out of the docstring,
+ update docstring.
+ * lang/python/pyme/core.py: Add and update docstrings.
+
+ python: Get version information from the build system.
+ * configure.ac: Generate 'setup.py' and 'version.py'.
+ * lang/python/Makefile.am: Use generated setup script.
+ * lang/python/pyme/version.py: Turn it into a template, and get
+ version information from the build system. Also drop some variables.
+ * lang/python/setup.py: Likewise. This way we can avoid importing the
+ version module, which is frowned upon and actually caused a problem.
+
+ python: Fix exception leak.
+ * lang/python/helpers.c (pygpgme_stash_callback_exception): Fix leak.
+
+ python: Fix license.
+ Other parts of the build system are also LGPLed.
+
+ * lang/python/Makefile.am: Fix license.
+
+2016-06-14 Werner Koch <wk@gnupg.org>
+
+ core: Make sure FD_SET is not used with an out of range fd.
+ * src/posix-io.c (_gpgme_io_select): Check for FD out of range.
+
+2016-06-08 Justus Winter <justus@g10code.com>
+
+ python: Improve error handling.
+ * lang/python/helpers.c (pyPassphraseCb): Handle write errors.
+ (pyEditCb): Likewise.
+
+ python: Add function to raise exceptions from c.
+ * lang/python/helpers.c (pygpgme_raise_exception): New function.
+
+ python: Fix stripping deprecated functionality.
+ * lang/python/Makefile.am (gpgme.h): Add script as input.
+ * lang/python/gpgme-h-clean.py (deprec_func): Also match struct
+ members.
+ (line_break): Fix matching on struct members.
+
+ python: Fix type.
+ * lang/python/gpgme.i: Use correct Python type for size.
+
+ python: Implement the context manager protocol.
+ * lang/python/pyme/core.py (Context.__del__): Make function
+ idemptotent.
+ (Context.{__enter__,__exit__}): Implement the context manager
+ protocol.
+ (Data.__del__): Make function idemptotent, drop debug print.
+ (Data.{__enter__,__exit__}): Implement the context manager
+ protocol.
+ * lang/python/tests/t-idiomatic.py: Demonstrate this.
+
+2016-06-07 Justus Winter <justus@g10code.com>
+
+ python: Fix error handling.
+ * lang/python/gpgme.i: Fix freeing an uninitialized pointer in the
+ error handling of generated wrapper functions by explicitly storing
+ the pointer in a local variable which can be initialized.
+
+2016-06-06 Justus Winter <justus@g10code.com>
+
+ python: Wrap file-like objects on demand.
+ * lang/python/gpgme.i (gpgme_data_t): Use new function to create
+ wrapper objects if necessary, and deallocate them after the function
+ call.
+ * lang/python/helpers.c (object_to_gpgme_data_t): New function.
+ * lang/python/helpers.h (object_to_gpgme_data_t): New prototype.
+ * lang/python/tests/Makefile.am (pytests): Add new test.
+ * lang/python/tests/t-idiomatic.py: New file.
+
+ python: Move helper function.
+ * lang/python/gpgme.i (object_to_gpgme_t): Move...
+ * lang/python/helpers.c: ... here.
+ * lang/python/helpers.h (object_to_gpgme_t): New prototype.
+
+ python: Fix error handling.
+ * lang/python/gpgme.i (object_to_gpgme_t): Properly propagate
+ exceptions.
+
+ python: Initialize GPGME for the user.
+ * lang/python/pyme/core.py: Call 'check_version' and explain why.
+ * lang/python/tests/support.py (init_gpgme): Drop call here.
+
+2016-06-01 Justus Winter <justus@g10code.com>
+
+ python: Fix test suite with GnuPG prior to 2.1.12.
+ * lang/python/tests/Makefile.am (gpg-agent.conf): Use
+ 'allow-loopback-pinentry'.
+
+ python: Make Python detection more robust.
+ Previously, missing Python development packages made configure fail
+ instead of merely disabling the bindings.
+
+ * configure.ac: Check for 'PYTHON_VERSION'.
+ * m4/ax_python_devel.m4: Make test non-fatal.
+
+ python: Improve build system integration, fix warnings.
+ * lang/python/Makefile.am: Pass CFLAGS to python build system.
+ * lang/python/helpers.c (pyPassphraseCb): Use correct type for length.
+ (pygpgme_data_new_from_cbs): Drop unused variable.
+
+2016-06-01 Andre Heinecke <aheinecke@intevation.de>
+
+ Cpp: Use whitelist for status messages.
+ * lang/cpp/src/editinteractor.cpp (EditInteractor::needsNoResponse):
+ Use whitelist instead of blacklist.
+
+ Qt: Fix debug output in t-ownertrust.
+ * lang/qt/tests/t-ownertrust.cpp (testChangeOwnerTrust): Remove
+ general debug of trust level. Add debug output for error.
+
+2016-06-01 Justus Winter <justus@gnupg.org>
+
+ tests: Fix notation tests.
+ * lang/python/tests/t-sig-notation.py (check_result): Check critical
+ flag.
+ * tests/gpg/t-sig-notation.c (check_result): Likewise.
+
+ Fixes-commit: 1cacd7d0
+
+2016-06-01 Werner Koch <wk@gnupg.org>
+
+ core: Set notation flags for verify.
+ * src/gpgme.h.in (GPGME_STATUS_NOTATION_FLAGS): New.
+ * src/status-table.c (status_table): Add new status.
+ * src/verify.c (parse_notation): Handle flags. Also fix NOTATION_DATA
+ in case gpg would not percent-escape spaces.
+ (_gpgme_verify_status_handler): Handle flags.
+ * tests/run-verify.c (print_result): Print notaion data.
+
+2016-05-31 Tobias Mueller <muelli@cryptobitch.de>
+
+ python: use GPG_ERROR_CONFIG variable.
+ instead of calling gpg-error-config.
+ This is useful when configuring with --with-gpgerror-prefix
+ because then GPG_ERROR_CONFIG contains the correct
+ /path/to/bin/gpg-error-config whereas calling gpg-error-config
+ directly would look in the user's PATH (and not in the prefix
+ where gpg-error-config was installed).
+
+2016-05-31 Justus Winter <justus@gnupg.org>
+
+ python: Port more tests.
+ * lang/python/gpgme.i: Hide length fields of notations.
+ * lang/python/tests/Makefile.am (pytests): Add new tests.
+ * lang/python/tests/t-decrypt-verify.py: New file.
+ * lang/python/tests/t-sig-notation.py: Likewise.
+ * lang/python/tests/t-verify.py: Likewise.
+
+2016-05-27 Werner Koch <wk@gnupg.org>
+
+ Speedup closing of fds before exec.
+ * src/posix-io.c [__linux__]: Include dirent.h.
+ (get_max_fds) [__linux__]: Try to figure out the highest used fd.
+
+2016-05-27 Justus Winter <justus@gnupg.org>
+
+ python: Port more tests.
+ * lang/python/pyme/core.py (Data._error_check): Add
+ 'gpgme_data_get_file_name' to the list of functions not returning an
+ error code.
+ * lang/python/tests/Makefile.am (pytests): Add new tests.
+ * lang/python/tests/support.py (verbose): New variable.
+ * lang/python/tests/t-data.py: Test setting and getting the filename.
+ * lang/python/tests/t-encrypt-large.py: New file.
+ * lang/python/tests/t-file-name.py: Likewise.
+ * lang/python/tests/t-trustlist.py: Likewise.
+
+ python: Implement data callbacks.
+ * lang/python/gpgme.i (object_to_gpgme_t): Set exception on error.
+ * lang/python/helpers.c (pyDataReadCb): New function.
+ (pyDataWriteCb): Likewise.
+ (pyDataSeekCb): Likewise.
+ (pyDataReleaseCb): Likewise.
+ (pygpgme_data_new_from_cbs): Likewise.
+ * lang/python/helpers.h (pygpgme_data_new_from_cbs): New prototype.
+ * lang/python/pyme/core.py (Data.__init__): Fix docstring, fix read
+ callbacks.
+ (Data.__del__): Fix read callbacks.
+ (Data._free_readcb): Drop function.
+ (Data._free_datacbs): New function.
+ (Data.new_from_cbs): Fix setting the callbacks.
+ (Data.write): Raise stashed exceptions.
+ (Data.read): Likewise.
+ * lang/python/tests/t-callbacks.py: Test new functionality.
+ * lang/python/tests/t-data.py: Likewise.
+
+ python: Fix object deallocation.
+ Handing a reference to the wrapper object created a non-trivial
+ circular reference that Pythons garbage collector is unable to break.
+ Explicitly break it by using a weak reference.
+
+ * lang/python/helpers.c (pygpgme_stash_callback_exception): Retrieve
+ object from weak reference.
+ * lang/python/pyme/core.py (Context.__del__): Free status callback.
+ (Context.set_passphrase_cb): Use a weak reference.
+ (Context.set_progress_cb): Likewise.
+ (Context.set_status_cb): Likewise.
+ (Context.op_edit): Likewise.
+
+ Improve comments.
+ * src/gpgme.h.in (gpgme_data_seek_cb_t, gpgme_data_seek): Clarify that
+ these functions return the new offset.
+ (gpgme_data_release_cb_t): Fix name of parameter.
+
+ python: Fix reading data from existing files.
+ * lang/python/pyme/core.py (Data.__init__): Add 'copy' kwargument, and
+ pass it to functions supporting it. PEP8 fix.
+ (Data.new_from_fd): PEP8 fix.
+ (Data.new_from_file): Give a more helpful error message if copy is
+ False. PEP8 fix.
+ (Data.new_from_fd): Hand the file descriptor to
+ 'gpgme_data_new_from_fd', not a stream. Fix docstring.
+ * lang/python/tests/t-data.py: Add tests for this.
+
+2016-05-25 Justus Winter <justus@gnupg.org>
+
+ src: Fix trace string.
+ * src/data-compat.c (gpgme_data_new_from_file): Fix trace string.
+
+2016-05-24 Justus Winter <justus@gnupg.org>
+
+ python: Improve and test Context.wait.
+ * lang/python/pyme/core.py (Context.wait): Improve docstring. As the
+ context passed to 'gpgme_wait' is never NULL, it is pointless to look
+ at the returned context. Always raise exceptions.
+ * lang/python/tests/Makefile.am (pytests): Add new test.
+ * lang/python/tests/t-wait.py: New file.
+
+ python: Make all GnuPG errors available.
+ * lang/python/Makefile.am (errors.i): Generate file.
+ * lang/python/gpgme.i: Include generated file.
+ * lang/python/pyme/errors.py: Pull in all errors and error sources.
+
+ python: Move the base wrapper class.
+ * python/lang/pyme/util.py (GpgmeWrapper): Move...
+ * python/lang/pyme/core.py: ... here.
+
+ python: Support status callbacks.
+ * lang/python/helpers.c (pyStatusCb): New function.
+ (pygpgme_set_status_cb): Likewise.
+ * lang/python/helpers.h (pygpgme_set_status_cb): New prototype.
+ * lang/python/pyme/core.py (Context.__init__): Initialize
+ 'last_statuscb'.
+ (Context._free_statuscb): New function.
+ (Context.set_status_cb): Likewise.
+ * lang/python/tests/t-callbacks.py: Test status callbacks.
+
+ python: Improve docstring.
+ * lang/python/pyme/core.py (Context.set_progress_cb): Improve
+ docstring.
+
+2016-05-24 Andre Heinecke <aheinecke@intevation.de>
+
+ Qt: Fix test build with clang.
+ * lang/qt/tests/Makefile.am (LDADD): Explicitly add -lstdc++
+
+ Cpp: Set -std=c++11 also if CXXCPP is already set.
+ * m4/ax_cxx_compile_stdxx.m4 (AX_CXX_COMPILE_STDCXX): Set CXXCPP if
+ neccessary.
+
+2016-05-24 Justus Winter <justus@gnupg.org>
+
+ python: Improve support for edit callbacks.
+ * lang/python/helpers.c (pyEditCb): Stash exceptions.
+ * lang/python/pyme/core.py (Context.op_edit): Hand in 'self'.
+ * lang/python/tests/Makefile.am (py_tests): Add new test.
+ * lang/python/tests/t-callbacks.py: Test edit callbacks.
+ * lang/python/tests/t-edit.py: New file.
+
+2016-05-23 Justus Winter <justus@gnupg.org>
+
+ python: Fix hook.
+ * lang/python/helpers.c (pyProgressCb): Fix getting hook data.
+ * lang/python/tests/t-callbacks.py: Show that this works.
+
+ python: Move edit callback function.
+ * lang/python/gpgme.i (pyEditCb): Move...
+ * lang/python/helpers.c: ... here.
+ * lang/python/helpers.h (pyEditCb): New prototype.
+
+ python: Port more tests.
+ * lang/python/tests/Makefile.am (TESTS_ENVIRONMENT): Set
+ LD_LIBRARY_PATH.
+ (pytests): Add new tests.
+ * lang/python/tests/t-callbacks.py: Trim imports.
+ * lang/python/tests/t-encrypt-sign.py: New file.
+ * lang/python/tests/t-export.py: Likewise.
+ * lang/python/tests/t-signers.py: Likewise.
+
+ python: Translate list of strings.
+ * lang/python/gpgme.i: Add typemap translating list of strings.
+
+2016-05-21 Werner Koch <wk@gnupg.org>
+
+ api: Return Tofu info for signatures.
+ * src/gpgme.h.in (gpgme_tofu_policy_t): New.
+ (gpgme_status_code_t): Add status codes for TOFU.
+ (struct _gpgme_tofu_info, gpgme_tofu_info_t): New.
+ (struct _gpgme_signature): Add field 'tofu'.
+ * src/status-table.c (status_table): Add new codes.
+ * src/verify.c: Include limits.h.
+ (release_tofu_info): New.
+ (release_op_data): Call that.
+ (parse_tofu_user): New.
+ (parse_tofu_stats): New.
+ (parse_tofu_stats_long): New.
+ (_gpgme_verify_status_handler): Handle TOFU status lines.
+
+ * tests/run-verify.c (print_description): New.
+ (print_result): print tofu info.
+
+ api: Add new context flag "raw-description".
+ * src/context.h (struct gpgme_context): Add field raw_description.
+ * src/gpgme.c (gpgme_set_ctx_flag): New flag.
+
+ core: New functions to help parsing of status lines.
+ * src/conversion.c (_gpgme_split_fields): New.
+ (_gpgme_strtoul_field): New.
+
+2016-05-20 Andre Heinecke <aheinecke@intevation.de>
+
+ Qt: Add test for changeownertrust.
+ * lang/qt/tests/t-ownertrust.cpp: New test.
+ * lang/qt/tests/Makefile.am: Add test.
+
+ Cpp: Ignore STATUS_KEY_CONSIDERED when editing.
+ * lang/cpp/src/editinteractor.cpp (EditInteractor::needsNoResponse):
+ Handle GPGME_STATUS_KEY_CONSIDERED.
+
+2016-05-19 Werner Koch <wk@gnupg.org>
+
+ api: Add new function gpgme_set_ctx_flag.
+ * src/gpgme.h.in (gpgme_set_ctx_flag): New prototype.
+ * src/gpgme.c (gpgme_set_ctx_flag): New.
+ * src/gpgme.def, src/libgpgme.vers: Add new function.
+ * src/context.h (struct gpgme_context): Add FULL_STATUS.
+ * src/decrypt.c (_gpgme_decrypt_status_handler): Do not call the
+ status callback if FULL_STATUS is set.
+ * src/genkey.c (genkey_status_handler): Ditto.
+ * src/passphrase.c (_gpgme_passphrase_status_handler): Ditto.
+ * src/sign.c (_gpgme_sign_status_handler): Ditto.
+
+ * src/engine-backend.h (struct engine_ops): Add SET_STATUS_CB and add
+ adjust all definitions of that variable.
+ * src/engine.c (_gpgme_engine_set_status_cb): New.
+ * src/op-support.c (_gpgme_op_reset): Call this function.
+
+ * src/engine-gpg.c (struct engine_gpg): Add fields MON_CB and
+ MON_CB_VALUE.
+ (gpg_set_status_cb): New.
+ (_gpgme_engine_ops_gpg): Register that function.
+ (read_status): Call the monitor callback.
+
+ * src/engine-gpgsm.c (struct engine_gpgsm): Add fields MON_CB and
+ MON_CB_VALUE.
+ (_gpgme_engine_ops_gpgsm): Register that function.
+ (gpgsm_assuan_simple_command): Change first arg to be an engine
+ context and adjust call callers. Call the monitor callback.
+
+ * src/engine-uiserver.c (struct engine_uiserver): Add fields MON_CB
+ and MON_CB_VALUE.
+ (_gpgme_engine_ops_uiserver): Register that function.
+ (uiserver_assuan_simple_command): Change first arg to be an engine
+ context and adjust call callers. Call the monitor callback.
+
+ * tests/run-verify.c (status_cb): New.
+ (print_result): Print algo names.
+ (main): Add option --status.
+
+ api: Remove arbitrary restriction from gpgme_op_verify.
+ * src/verify.c (verify_start): Do not return GPG_ERR_INV_VALUES when
+ when SIGNED_TEXT is not given.
+
+2016-05-19 Justus Winter <justus@gnupg.org>
+
+ python: Improve progress callbacks.
+ * lang/python/helpers.c (pyProgressCb): Stash python errors, convert
+ 'what' to Unicode object.
+ * lang/python/pyme/core.py (Context.set_progress_cb): Hand in 'self'.
+ * lang/python/tests/t-callbacks.py: Test progress callbacks.
+
+ python: Robust exception handling in callbacks.
+ * lang/python/helpers.c (pygpgme_stash_callback_exception): New
+ function.
+ (pygpgme_raise_callback_exception): Likewise.
+ (pyPassphraseCb): Stash python errors.
+ * lang/python/helpers.h (pygpgme_raise_callback_exception): New
+ prototype.
+ * lang/python/pyme/core.py ({Context,Data}.__init__): Move common
+ initialization to superclass.
+ (Context.set_progress_cb): Hand in 'self'.
+ * lang/python/pyme/util.py (GpgmeWrapper.__init__): New function.
+ (GpgmeWrapper.__getattr__): Raise stashed exceptions.
+ * lang/python/tests/Makefile.am (py_tests): Add new test.
+ * lang/python/tests/t-callbacks.py: New file.
+
+2016-05-19 Andre Heinecke <aheinecke@intevation.de>
+
+ Qt: Check for graphviz and set HAVE_DOT correctly.
+ * configure.ac: Check for graphviz and define HAVE_DOT.
+ * lang/qt/doc/Doxyfile.in (HAVE_DOT): Use variable.
+
+2016-05-19 Justus Winter <justus@gnupg.org>
+
+ python: Add more tests.
+ * lang/python/tests/Makefile.am (py_tests): Add new tests.
+ * lang/python/tests/support.py (print_data): New function.
+ * lang/python/tests/t-decrypt.py: Use new function.
+ * lang/python/tests/t-encrypt.py: Likewise.
+ * lang/python/tests/t-sign.py: New file.
+ * lang/python/tests/t-encrypt-sym.py: Likewise.
+
+ python: More type conversion fixes.
+ * lang/python/helpers.c (pyPassphraseCb): Cope with 'uid_hint' being
+ NULL, convert it to an Unicode object, and cope with the callback
+ returning both Unicode and bytes objects.
+
+ python: Fix import.
+ * lang/python/helpers.c (pygpgme_exception_init): Make module import
+ relative.
+
+2016-05-19 Andre Heinecke <aheinecke@intevation.de>
+
+ Qt: Fix compilation of unit tests.
+ * lang/qt/tests/Makefile.am (AM_CPPFLAGS): Add -DBUILDING_QGPGME.
+
+2016-05-18 Justus Winter <justus@gnupg.org>
+
+ python: Various fixes.
+ * configure.ac: Fix SWIG detection, bump required Python version.
+ * lang/python/Makefile.am: Portability fix.
+
+2016-05-18 Andre Heinecke <aheinecke@intevation.de>
+
+ Fix typo in compatibility declaration.
+ * src/op-support.c (GPG_ERR_SUBKEYS_EXP_REV): Change to
+ GPG_ERR_SUBKEYS_EXP_OR_REV.
+
+2016-05-17 Werner Koch <wk@gnupg.org>
+
+ tests: New maintenance helper run-encrypt.
+ * tests/run-encrypt.c: New.
+
+ Return dedicated error code for all subkeys expired or revoked.
+ * src/gpgme.h.in (GPGME_STATUS_KEY_CONSIDERED): New.
+ (GPGME_SIGSUM_TOFU_CONFLICT): New.
+ * src/status-table.c (KEY_CONSIDERED): New.
+ * src/op-support.c (_gpgme_parse_inv_recp): Add argc KC_FPR and
+ KC_FLAGS. Use calloc. Detect all expired or revoked subkeys.
+ (_gpgme_parse_key_considered): New.
+ * src/sign.c (op_data_t): Add fields KC_FPR and KC_FLAGS.
+ (release_op_data): Free KC_FPR.
+ (_gpgme_sign_status_handler): Handle STATUS_KEY_CONSIDERED.
+ * src/encrypt.c (op_data_t): Add fields KC_FPR and KC_FLAGS.
+ (release_op_data): Free KC_FPR.
+ (_gpgme_encrypt_status_handler): Handle STATUS_KEY_CONSIDERED.
+
+2016-05-17 Andre Heinecke <aheinecke@intevation.de>
+
+ Qt / Cpp: Port auto_ptr to unique_ptr.
+ * lang/cpp/src/context.cpp,
+ lang/cpp/src/context.h,
+ lang/cpp/src/context_p.h (Context::createForEngine),
+ (Context::edit, Context::startEditing),
+ (Context::takeLastEditInteractor, Context::cardEdit),
+ (Context::startCardEditing, Context::takeLastCardEditInteractor),
+ (Context::assuanTransact, Context::startAssuanTransaction),
+ (Context::takeLastAssuanTransaction): Port to unique_ptr.
+ * lang/qt/src/qgpgmeadduseridjob.cpp,
+ lang/qt/src/qgpgmechangeexpiryjob.cpp,
+ lang/qt/src/qgpgmechangeownertrustjob.cpp,
+ lang/qt/src/qgpgmechangepasswdjob.cpp,
+ lang/qt/src/qgpgmesignkeyjob.cpp: Update accordingly.
+
+2016-05-17 Justus Winter <justus@gnupg.org>
+
+ build: Add python autoconf macro.
+ * m4/ax_python_devel.m4: New file.
+
+ python: Clean up examples.
+ * lang/python/examples/delkey.py: Clean up example.
+ * lang/python/examples/encrypt-to-all.py: Likewise.
+ * lang/python/examples/genkey.py: Likewise.
+ * lang/python/examples/inter-edit.py: Likewise.
+ * lang/python/examples/sign.py: Likewise.
+ * lang/python/examples/signverify.py: Likewise.
+ * lang/python/examples/simple.py: Likewise.
+ * lang/python/examples/t-edit.py: Likewise.
+ * lang/python/examples/verifydetails.py: Likewise.
+ * lang/python/pyme/__init__.py: Likewise.
+
+ python: Import GPGMEError.
+ * pyme/core.py: Import GPGMEError.
+
+ Fixes c5d118b2.
+
+ python: Port more tests.
+ * lang/python/Makefile.am: Add bits from the c test suite.
+ * lang/python/support.py: New file.
+ * lang/python/t-decrypt.py: Likewise.
+ * lang/python/t-encrypt.py: Likewise.
+
+2016-05-13 Andre Heinecke <aheinecke@intevation.de>
+
+ Qt: Add keyLocateJob and test for it.
+ * configure.ac (LIBQGPGME_LT_REVISION): Bump.
+ * lang/qt/src/protocol.h (locateKeysJob): Add Job.
+ * lang/qt/src/protocol_p.h (locateKeysJob): Implement.
+ * lang/qt/tests/Makefile.am: Add t-keylocate.
+ * lang/qt/tests/t-keylocate.cpp: New.
+
+ Qt: Add missing copyright header in test.
+ * lang/qt/tests/t-keylist.cpp: Add copyright header.
+
+2016-05-12 Justus Winter <justus@gnupg.org>
+
+ python: Share generated methods between objects.
+ * lang/python/pyme/util.py (GpgmeWrapper.__getattr__): Monkey-patch
+ the class.
+ * lang/python/tests/t-wrapper.py: Demonstrate the sharing.
+
+ python: Raise exceptions on write errors.
+ * lang/python/pyme/core.py (Data.write): Handle errors.
+ * lang/python/pyme/errors.py (GPGMEError.fromSyserror): New function.
+
+ python: Fix writing to data buffers.
+ * lang/python/gpgme.i: Add typemap for buffers.
+ * lang/python/pyme/core.py (Data.write): Fix function.
+ * lang/python/tests/Makefile.am: Add new test.
+ * lang/python/tests/t-data.py: New file.
+
+ python: Add a test suite.
+ * configure.ac: Add new Makefile.
+ * lang/python/Makefile.am: Add subdirectory.
+ * lang/python/tests/Makefile.am: New file.
+ * lang/python/tests/t-wrapper.py: Likewise.
+
+ python: Cache generated wrapper functions.
+ * lang/python/util.py (GpgmeWrap.__getattr__): Cache generated wrapper
+ functions.
+
+ python: Fix function invocation.
+ * lang/python/pyme/core.py (Data.new_from_fd): Fix function
+ invocation.
+
+ python: Fix name of exception, make slot methods explicit.
+ * lang/python/pyme/util.py (GpgmeWrapper._getctype): Fix exception,
+ add docstring.
+ (GpgmeWrapper._getnameprepend): New function.
+ (GpgmeWrapper._errorcheck): Likewise.
+
+ python: Handle interpreter shutdown.
+ * lang/python/pyme/core.py: Avoid races at interpreter shutdown. This
+ silences the most annoying occurrences, however this problem also
+ affects the SWIG generated code, which might indicate that the real
+ problem is somewhere else. If so, this change can be easily reverted.
+
+ python: Make test case more robust.
+ * lang/python/examples/t-edit.py: Check if key is found.
+
+ python: Fix type translation.
+ * lang/python/gpgme.i: Adjust to Python3's string type being
+ 'Unicode', not 'bytes'. Fix type checking.
+ * lang/python/core.py (Data.write): Add docstring mentioning the
+ expected type of parameter 'buffer'.
+ (Data.read): Adjust read loop. Also, use a saner chunk size, and join
+ all chunks at the end instead of adding them.
+ * lang/python/examples/simple.py: Adjust example.
+
+2016-05-11 Andre Heinecke <aheinecke@intevation.de>
+
+ Cpp: Ensure gpgme.h is taken from current build.
+ * lang/cpp/src/Makefile.am (AM_CPPFLAGS): Add gpgme.h location.
+
+2016-05-11 Justus Winter <justus@gnupg.org>
+
+ python: Fix simple example.
+ * lang/python/examples/simple.py: Flush stdout, encode name as
+ UTF-8 before passing it to GPGME.
+
+ python: Integrate into the build system.
+ * configure.ac: Make Python bindings configurable, add new Makefile.
+ * lang/python/Makefile.am: New file.
+ * lang/python/setup.py: Integrate into the build system.
+ * m4/ax_pkg_swig.m4: New file from the autoconf archive.
+ * m4/m4_ax_swig_python.m4: Likewise.
+
+2016-05-10 Andre Heinecke <aheinecke@intevation.de>
+
+ Qt / Cpp: Fix make dist.
+ * lang/cpp/src/Makefile.am (EXTRA_DIST): Fix typo.
+ (private_gpgmepp_headers): New. Private headers.
+ (libgpgmepp_la_SOURCES): Add private headers.
+ * lang/qt/src/Makefile.am (t_keylist_SOURCES): Remove non existent
+ header.
+
+2016-05-10 Justus Winter <justus@gnupg.org>
+
+ python: PEP8 fixes.
+ Cherry picked from 0267c151.
+
+2016-05-10 Andre Heinecke <aheinecke@intevation.de>
+
+ Qt: Make Protocol class public API.
+ * lang/qt/src/Makefile.am (qgpgme_headers): Add protocol.h
+ (private_qgpgme_headers): Add protocol_p.h
+ * lang/qt/src/protocol.h: New. From QGpgMEBackend.
+ * lang/qt/src/protocol_p.h: New. From QGpgMEBackend.
+ * lang/qt/src/qgpgmebackend.h,
+ lang/qt/src/qgpgmebackend.cpp (Protocol): Removed.
+
+ Qt: Make doxygen quieter.
+ * lang/qt/doc/Doxyfile.in: Quiet and no undocumented warnings.
+
+ Qt: Only install public headers.
+ * lang/qt/src/Makefile.am: Do not install all headers.
+
+ Qt: Add test for async keylisting.
+ * src/lang/qt/tests/t-keylist.cpp(KeyListTest::testKeyListAsync): New.
+
+2016-05-10 Werner Koch <wk@gnupg.org>
+
+ Allow cc to detect missing cases in a switch.
+ * src/delete.c (delete_status_handler): Remove default case from a
+ switch so that cc can check the use of all enum values.
+
+2016-05-06 Andre Heinecke <aheinecke@intevation.de>
+
+ Use common error message style for qt lang checks.
+ * configure.ac: Use common error highliting for qt lang options.
+
+ Qt: Fix license mentioned in README.
+ * lang/qt/README: License is GPLv2+ and not LGPL.
+
+ Add maybe mode for langs and default to it.
+ * configure.ac (languages): Warn and disable langs for which
+ requirements are not met.
+
+ Cpp: Handle PINENTRY_LAUNCHED status line.
+ * lang/cpp/src/editinteractor.cpp (EditInteractor::needsNoResponse):
+ Add GPGME_STATUS_PINENTRY_LAUNCHED.
+
+2016-04-12 Andre Heinecke <aheinecke@intevation.de>
+
+ Cpp: Add support for pubkey_algo_name.
+ * lang/cpp/src/key.cpp (Subkey::algoName): New.
+ * lang/cpp/src/key.h: Declare.
+
+ Cpp: Add support for gpgme_data_identify.
+ * lang/cpp/src/data.cpp (Data::type): New.
+ * lang/cpp/src/data.h (Data::Type): New enum mapping.
+
+ Fix configuration without Qt language.
+ * configure.ac: Define HAVE_DOXYGEN also if qt should not be built.
+
+2016-04-11 Andre Heinecke <aheinecke@intevation.de>
+
+ Qt/Cpp: Bump so version to 6.
+ * configure.ac (LIBGPGMEPP_LT_CURRENT, LIBQGPGME_LT_CURRENT): Bump.
+
+ Qt / Cpp: Mention coding style in READMES.
+ * src/lang/cpp/README, src/lang/qt/README: Add hacking note.
+
+ Qt: Add doc generation with doxygen.
+ * configure.ac: Look for doxygen if qt is built.
+ Configure new files.
+ * lang/qt/doc/Doxyfile.in: New.
+ * lang/qt/doc/Makefile.am: New.
+ * lang/qt/README: Update.
+
+ Qt: Fix unit test by adding initial.test dep.
+ * lang/qt/tests/t-keylist.cpp: Verify that GNUPGHOME is set.
+ * lang/qt/tests/initial.test: New dummy test.
+ * lang/qt/tests/Makefile.am: Add dependency to initial.test
+
+ Qt: Remove remaining boost usage.
+ * lang/qt/src/dataprovider.h,
+ lang/qt/src/decryptjob.h,
+ lang/qt/src/decryptverifyjob.h,
+ lang/qt/src/encryptjob.h,
+ lang/qt/src/qgpgmeadduseridjob.cpp,
+ lang/qt/src/qgpgmechangeexpiryjob.cpp,
+ lang/qt/src/qgpgmechangeownertrustjob.cpp,
+ lang/qt/src/qgpgmechangepasswdjob.cpp,
+ lang/qt/src/qgpgmedecryptjob.cpp,
+ lang/qt/src/qgpgmedecryptverifyjob.cpp,
+ lang/qt/src/qgpgmedeletejob.cpp,
+ lang/qt/src/qgpgmedownloadjob.cpp,
+ lang/qt/src/qgpgmeencryptjob.cpp,
+ lang/qt/src/qgpgmeexportjob.cpp,
+ lang/qt/src/qgpgmeimportfromkeyserverjob.cpp,
+ lang/qt/src/qgpgmeimportjob.cpp,
+ lang/qt/src/qgpgmekeygenerationjob.cpp,
+ lang/qt/src/qgpgmekeylistjob.cpp,
+ lang/qt/src/qgpgmenewcryptoconfig.cpp,
+ lang/qt/src/qgpgmenewcryptoconfig.h,
+ lang/qt/src/qgpgmesignencryptjob.cpp,
+ lang/qt/src/qgpgmesignjob.cpp,
+ lang/qt/src/qgpgmesignkeyjob.cpp,
+ lang/qt/src/qgpgmeverifydetachedjob.cpp,
+ lang/qt/src/qgpgmeverifyopaquejob.cpp,
+ lang/qt/src/signencryptjob.h,
+ lang/qt/src/signjob.h,
+ lang/qt/src/threadedjobmixin.cpp,
+ lang/qt/src/threadedjobmixin.h,
+ lang/qt/src/verifydetachedjob.h,
+ lang/qt/src/verifyopaquejob.h: Remove boost usage.
+
+ Qt: Remove predicates.h and stl_util.h.
+ * src/lang/qt/predicates.h, src/lang/qt/stl_util.h: Removed.
+
+ Qt: Remove usage of stl_util.h and predicates.h.
+ * src/lang/qt/qgpgmelistallkeysjob.cpp: Use comperators from
+ gpgmepp instead of detail. Remove boost usage.
+
+ Cpp: Add string comparators for keys.
+ * lang/cpp/src/global.h (GPGMEPP_MAKE_STRCMP): New.
+ (_gpgmepp_strcmp): NULL save wrapper around std::strcmp.
+ * lang/cpp/src/key.h: Add comparators for various attributes.
+
+ Cpp: Remove last usages of boost.
+ * lang/cpp/src/configuration.cpp: Use std::remove_pointer.
+ (Configuration::operator<<): std::for_each.
+ * lang/cpp/src/context.cpp: Delete manually instead of scoped ptr.
+ * lang/cpp/src/scdgetinfoassuantransaction.cpp: Use static_assert.
+ (to_reader_list): Tokenize with getline.
+
+2016-04-04 Andre Heinecke <aheinecke@intevation.de>
+
+ Add pthread in gpgmepp config.
+ * lang/cpp/src/GpgmeppConfig.cmake.in.in: Add pthread.
+
+2016-04-03 Andre Heinecke <aheinecke@intevation.de>
+
+ Cpp / Qt: Reduce boost usage (memory and tuple)
+ * cpp/src/assuanresult.h,
+ cpp/src/configuration.cpp,
+ cpp/src/configuration.h,
+ cpp/src/data.h,
+ cpp/src/decryptionresult.h,
+ cpp/src/defaultassuantransaction.cpp,
+ cpp/src/encryptionresult.cpp,
+ cpp/src/encryptionresult.h,
+ cpp/src/engineinfo.h,
+ cpp/src/gpgagentgetinfoassuantransaction.cpp,
+ cpp/src/gpgsignkeyeditinteractor.cpp,
+ cpp/src/importresult.cpp,
+ cpp/src/importresult.h,
+ cpp/src/key.h,
+ cpp/src/keygenerationresult.h,
+ cpp/src/keylistresult.h,
+ cpp/src/notation.h,
+ cpp/src/signingresult.cpp,
+ cpp/src/signingresult.h,
+ cpp/src/verificationresult.cpp,
+ cpp/src/verificationresult.h,
+ cpp/src/vfsmountresult.h,
+ qt/src/dataprovider.cpp,
+ qt/src/dataprovider.h,
+ qt/src/decryptjob.h,
+ qt/src/decryptverifyjob.h,
+ qt/src/downloadjob.h,
+ qt/src/encryptjob.h,
+ qt/src/qgpgmeadduseridjob.cpp,
+ qt/src/qgpgmechangeexpiryjob.cpp,
+ qt/src/qgpgmechangeownertrustjob.cpp,
+ qt/src/qgpgmechangepasswdjob.cpp,
+ qt/src/qgpgmedecryptjob.cpp,
+ qt/src/qgpgmedecryptjob.h,
+ qt/src/qgpgmedecryptverifyjob.cpp,
+ qt/src/qgpgmedecryptverifyjob.h,
+ qt/src/qgpgmedeletejob.cpp,
+ qt/src/qgpgmedownloadjob.cpp,
+ qt/src/qgpgmedownloadjob.h,
+ qt/src/qgpgmeencryptjob.cpp,
+ qt/src/qgpgmeencryptjob.h,
+ qt/src/qgpgmeexportjob.cpp,
+ qt/src/qgpgmeexportjob.h,
+ qt/src/qgpgmeimportfromkeyserverjob.cpp,
+ qt/src/qgpgmeimportfromkeyserverjob.h,
+ qt/src/qgpgmeimportjob.cpp,
+ qt/src/qgpgmeimportjob.h,
+ qt/src/qgpgmekeygenerationjob.cpp,
+ qt/src/qgpgmekeygenerationjob.h,
+ qt/src/qgpgmekeylistjob.cpp,
+ qt/src/qgpgmekeylistjob.h,
+ qt/src/qgpgmelistallkeysjob.cpp,
+ qt/src/qgpgmelistallkeysjob.h,
+ qt/src/qgpgmenewcryptoconfig.cpp,
+ qt/src/qgpgmenewcryptoconfig.h,
+ qt/src/qgpgmesignencryptjob.cpp,
+ qt/src/qgpgmesignencryptjob.h,
+ qt/src/qgpgmesignjob.cpp,
+ qt/src/qgpgmesignjob.h,
+ qt/src/qgpgmesignkeyjob.cpp,
+ qt/src/qgpgmeverifydetachedjob.cpp,
+ qt/src/qgpgmeverifydetachedjob.h,
+ qt/src/qgpgmeverifyopaquejob.cpp,
+ qt/src/qgpgmeverifyopaquejob.h,
+ qt/src/signencryptjob.h,
+ qt/src/signjob.h,
+ qt/src/threadedjobmixin.h,
+ qt/src/verifydetachedjob.h,
+ qt/src/verifyopaquejob.h: Reduce boost usage.
+
+ Cpp: Require c++ 11 if cpp binding requested.
+ * configure.ac: Call ax_cxx_compile_stdcxx
+ * m4/ax_cxx_compile_stdcxx.m4
+
+ Qt: Add static factor methods for protocol.
+ * lang/qt/src/qgpgmebackend.cpp (QGpgME::openpgp, QGpgME::smime): New.
+ * lang/qt/src/qgpgmebackend.h: Declare.
+ * lang/qt/tests/t-keylist.cpp (KeyListTest::testSingleKeyListSync):
+ Use new functions.
+
+ Qt: Add a unit test for qgpgme.
+ * configure.ac: Configure test Makefile.
+ * m4/qt.m4: Look up Qt5Test flags.
+ * lang/qt/tests/t-keylist.cpp: New. Simple keylist check.
+ * lang/qt/tests/Makefile.am: New. General test framework.
+
+ Qt: Add missing MOC includes.
+ * qgpgmeadduseridjob.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,
+ qgpgmerefreshkeysjob.cpp,
+ qgpgmesecretkeyexportjob.cpp,
+ qgpgmesignencryptjob.cpp,
+ qgpgmesignjob.cpp,
+ qgpgmesignkeyjob.cpp,
+ qgpgmeverifydetachedjob.cpp,
+ qgpgmeverifyopaquejob.cpp: Add missing MOC includes.
+
+ Qt: Declare pure virtuals as such.
+ * lang/qt/src/qgpgmebackend.h (Protocol): Make all functions
+ pure virtual.
+
+ Qt: Don't declare showErrorDialog anymore.
+ * cpp/qt/src/job.h: Remove showErrorDialog.
+
+ Qt: Only use GpgME based config class.
+ * lang/qt/src/qgpgmecryptoconfig.cpp,
+ lang/qt/src/qgpgmecryptoconfig.h: Removed.
+ * lang/qt/src/qgpgmebackend.cpp: Return newcryptoconfig.
+
+2016-04-02 Andre Heinecke <aheinecke@intevation.de>
+
+ Add additional include path in config files.
+ * lang/cpp/src/GpgmeppConfig.cmake.in.in
+ lang/qt/src/QGpgmeConfig.cmake.in.in: Include directory above headers.
+
+ Qt: Fix library name in nodist variable.
+ * lang/qt/Makefile.am (nodist_qgpgme_SOURCES): Change to real name.
+
+ Add missing files to QGpgME.
+ * lang/qt/src/gpgme_backend_debug.cpp,
+ lang/qt/src/gpgme_backend_debug.h,
+ lang/qt/src/predicates.h,
+ lang/qt/src/stl_util.h: New.
+
+ Add QGpgME code from libkleo.
+ * lang/qt/src/Makefile.am,
+ lang/qt/src/abstractimportjob.h,
+ lang/qt/src/adduseridjob.h,
+ lang/qt/src/changeexpiryjob.h,
+ lang/qt/src/changeownertrustjob.h,
+ lang/qt/src/changepasswdjob.h,
+ lang/qt/src/cryptoconfig.h,
+ lang/qt/src/decryptjob.h,
+ lang/qt/src/decryptverifyjob.h,
+ lang/qt/src/deletejob.h,
+ lang/qt/src/downloadjob.h,
+ lang/qt/src/encryptjob.h,
+ lang/qt/src/exportjob.h,
+ lang/qt/src/hierarchicalkeylistjob.h,
+ lang/qt/src/importfromkeyserverjob.h,
+ lang/qt/src/importjob.h,
+ lang/qt/src/job.cpp,
+ lang/qt/src/job.h,
+ lang/qt/src/keygenerationjob.h,
+ lang/qt/src/keylistjob.h,
+ lang/qt/src/listallkeysjob.h,
+ lang/qt/src/multideletejob.h,
+ lang/qt/src/qgpgmeadduseridjob.cpp,
+ lang/qt/src/qgpgmeadduseridjob.h,
+ lang/qt/src/qgpgmebackend.cpp,
+ lang/qt/src/qgpgmebackend.h,
+ lang/qt/src/qgpgmechangeexpiryjob.cpp,
+ lang/qt/src/qgpgmechangeexpiryjob.h,
+ lang/qt/src/qgpgmechangeownertrustjob.cpp,
+ lang/qt/src/qgpgmechangeownertrustjob.h,
+ lang/qt/src/qgpgmechangepasswdjob.cpp,
+ lang/qt/src/qgpgmechangepasswdjob.h,
+ lang/qt/src/qgpgmecryptoconfig.cpp,
+ lang/qt/src/qgpgmecryptoconfig.h,
+ lang/qt/src/qgpgmedecryptjob.cpp,
+ lang/qt/src/qgpgmedecryptjob.h,
+ lang/qt/src/qgpgmedecryptverifyjob.cpp,
+ lang/qt/src/qgpgmedecryptverifyjob.h,
+ lang/qt/src/qgpgmedeletejob.cpp,
+ lang/qt/src/qgpgmedeletejob.h,
+ lang/qt/src/qgpgmedownloadjob.cpp,
+ lang/qt/src/qgpgmedownloadjob.h,
+ lang/qt/src/qgpgmeencryptjob.cpp,
+ lang/qt/src/qgpgmeencryptjob.h,
+ lang/qt/src/qgpgmeexportjob.cpp,
+ lang/qt/src/qgpgmeexportjob.h,
+ lang/qt/src/qgpgmeimportfromkeyserverjob.cpp,
+ lang/qt/src/qgpgmeimportfromkeyserverjob.h,
+ lang/qt/src/qgpgmeimportjob.cpp,
+ lang/qt/src/qgpgmeimportjob.h,
+ lang/qt/src/qgpgmekeygenerationjob.cpp,
+ lang/qt/src/qgpgmekeygenerationjob.h,
+ lang/qt/src/qgpgmekeylistjob.cpp,
+ lang/qt/src/qgpgmekeylistjob.h,
+ lang/qt/src/qgpgmelistallkeysjob.cpp,
+ lang/qt/src/qgpgmelistallkeysjob.h,
+ lang/qt/src/qgpgmenewcryptoconfig.cpp,
+ lang/qt/src/qgpgmenewcryptoconfig.h,
+ lang/qt/src/qgpgmerefreshkeysjob.cpp,
+ lang/qt/src/qgpgmerefreshkeysjob.h,
+ lang/qt/src/qgpgmesecretkeyexportjob.cpp,
+ lang/qt/src/qgpgmesecretkeyexportjob.h,
+ lang/qt/src/qgpgmesignencryptjob.cpp,
+ lang/qt/src/qgpgmesignencryptjob.h,
+ lang/qt/src/qgpgmesignjob.cpp,
+ lang/qt/src/qgpgmesignjob.h,
+ lang/qt/src/qgpgmesignkeyjob.cpp,
+ lang/qt/src/qgpgmesignkeyjob.h,
+ lang/qt/src/qgpgmeverifydetachedjob.cpp,
+ lang/qt/src/qgpgmeverifydetachedjob.h,
+ lang/qt/src/qgpgmeverifyopaquejob.cpp,
+ lang/qt/src/qgpgmeverifyopaquejob.h,
+ lang/qt/src/refreshkeysjob.h,
+ lang/qt/src/signencryptjob.h,
+ lang/qt/src/signjob.h,
+ lang/qt/src/signkeyjob.h,
+ lang/qt/src/specialjob.h,
+ lang/qt/src/threadedjobmixin.cpp,
+ lang/qt/src/threadedjobmixin.h,
+ lang/qt/src/verifydetachedjob.h,
+ lang/qt/src/verifyopaquejob.h: New.
+ * lang/qt/src/Makefile.am:
+
+2016-03-08 Andre Heinecke <aheinecke@intevation.de>
+
+ Add qgpgme as qt language binding.
+ * configure.ac: Add version defines. Check for qt if neccessary.
+ * lang/README: Mention qt
+ * lang/cpp/src/GpgmeppConfig.cmake.in.in: Remove comment. Find qgpgme.
+ * lang/qt/src/Makefile.am: New. Build qgpgme.
+ * lang/qt/README,
+ lang/qt/src/Makefile.am,
+ lang/qt/src/QGpgmeConfig.cmake.in.in,
+ lang/qt/src/QGpgmeConfigVersion.cmake.in,
+ lang/qt/src/dataprovider.cpp,
+ lang/qt/src/dataprovider.h,
+ lang/qt/src/qgpgme_export.h,
+ m4/qt.m4: New.
+ * lang/cpp/src/GpgmeppConfig.cmake.in.in,
+ lang/cpp/src/Makefile.am: Fix generated config file.
+
+ Remove obsolete w32-qt code.
+ * configure.ac (w32-qt): Remove option and Qt checks.
+ * src/Makefile.am: Remove BUILD_W32_QT handling.
+ * src/kdpipeiodevice.cpp,
+ src/kdpipeiodevice.h,
+ src/kdpipeiodevice.moc,
+ src/w32-qt-io.cpp: Removed.
+
+2016-03-02 Andre Heinecke <aheinecke@intevation.de>
+
+ Add version info for gpgmepp.
+ * lang/cpp/src/Makefile.am (libgpgmepp_la_LDFLAGS): Add version info.
+
+ Add cmake configuration files.
+ * configure.ac: Add libgpgmepp version. Configure cmake files.
+ * lang/cpp/src/Makefile.am: Add targets for cmake files.
+ (EXTRA_DIST): Add cmake files.
+
+ Fix export header and windows export macros.
+ * lang/cpp/src/gpgme_export.h: Fix variable name. Add Windows ifdefs.
+
+ Add header installation.
+ * lang/cpp/src/Makefile.am: Add headers as deps and install them.
+ (AM_CPPFLAGS): Add BUILDING_GPGMEPP to be used in export macros.
+
+ Add enable-languages build option.
+ * acinclude.m4 (LIST_MEMBER): New macro.
+ * configure.ac (enable-languages): New option. Add info output.
+ * lang/Makefile.am: Only add enabled language subdirs.
+
+2016-02-22 Andre Heinecke <aheinecke@intevation.de>
+
+ Add README for gpgmepp.
+ * lang/README: Note down cpp.
+ * cpp/README: Add README based on original repo version.
+
+ Add buildsystem for Gpgmepp.
+ * configure.ac: Configure Makefiles.
+ * lang/Makefile.am: Add cpp subdir
+ * lang/cpp/Makefile.am: New. Add src subdir.
+ * lang/cpp/src/Makefile.am: New. Basic buildsystem.
+
+ Remove feature check ifdefs.
+ * lang/cpp/src/assuanresult.cpp,
+ lang/cpp/src/callbacks.cpp,
+ lang/cpp/src/configuration.cpp,
+ lang/cpp/src/context.cpp,
+ lang/cpp/src/context_glib.cpp,
+ lang/cpp/src/context_qt.cpp,
+ lang/cpp/src/context_vanilla.cpp,
+ lang/cpp/src/data.cpp,
+ lang/cpp/src/decryptionresult.cpp,
+ lang/cpp/src/defaultassuantransaction.cpp,
+ lang/cpp/src/editinteractor.cpp,
+ lang/cpp/src/encryptionresult.cpp,
+ lang/cpp/src/engineinfo.cpp,
+ lang/cpp/src/eventloopinteractor.cpp,
+ lang/cpp/src/global.h,
+ lang/cpp/src/gpgagentgetinfoassuantransaction.cpp,
+ lang/cpp/src/importresult.cpp,
+ lang/cpp/src/interfaces/assuantransaction.h,
+ lang/cpp/src/key.cpp,
+ lang/cpp/src/keygenerationresult.cpp,
+ lang/cpp/src/keylistresult.cpp,
+ lang/cpp/src/scdgetinfoassuantransaction.cpp,
+ lang/cpp/src/signingresult.cpp,
+ lang/cpp/src/trustitem.cpp,
+ lang/cpp/src/util.h,
+ lang/cpp/src/verificationresult.cpp,
+ lang/cpp/src/vfsmountresult.cpp: Remove feature checks.
+
+ Initial checkin of gpgmepp sources.
+ Based on git.kde.org/pim/gpgmepp rev. 0e3ebc02
+
+ * lang/cpp/src/assuanresult.cpp,
+ lang/cpp/src/assuanresult.h,
+ lang/cpp/src/callbacks.cpp,
+ lang/cpp/src/callbacks.h,
+ lang/cpp/src/configuration.cpp,
+ lang/cpp/src/configuration.h,
+ lang/cpp/src/context.cpp,
+ lang/cpp/src/context.h,
+ lang/cpp/src/context_glib.cpp,
+ lang/cpp/src/context_p.h,
+ lang/cpp/src/context_qt.cpp,
+ lang/cpp/src/context_vanilla.cpp,
+ lang/cpp/src/data.cpp,
+ lang/cpp/src/data.h,
+ lang/cpp/src/data_p.h,
+ lang/cpp/src/decryptionresult.cpp,
+ lang/cpp/src/decryptionresult.h,
+ lang/cpp/src/defaultassuantransaction.cpp,
+ lang/cpp/src/defaultassuantransaction.h,
+ lang/cpp/src/editinteractor.cpp,
+ lang/cpp/src/editinteractor.h,
+ lang/cpp/src/encryptionresult.cpp,
+ lang/cpp/src/encryptionresult.h,
+ lang/cpp/src/engineinfo.cpp,
+ lang/cpp/src/engineinfo.h,
+ lang/cpp/src/error.h,
+ lang/cpp/src/eventloopinteractor.cpp,
+ lang/cpp/src/eventloopinteractor.h,
+ lang/cpp/src/exception.cpp,
+ lang/cpp/src/exception.h,
+ lang/cpp/src/global.h,
+ lang/cpp/src/gpgadduserideditinteractor.cpp,
+ lang/cpp/src/gpgadduserideditinteractor.h,
+ lang/cpp/src/gpgagentgetinfoassuantransaction.cpp,
+ lang/cpp/src/gpgagentgetinfoassuantransaction.h,
+ lang/cpp/src/gpgmefw.h,
+ lang/cpp/src/gpgmepp_export.h,
+ lang/cpp/src/gpgsetexpirytimeeditinteractor.cpp,
+ lang/cpp/src/gpgsetexpirytimeeditinteractor.h,
+ lang/cpp/src/gpgsetownertrusteditinteractor.cpp,
+ lang/cpp/src/gpgsetownertrusteditinteractor.h,
+ lang/cpp/src/gpgsignkeyeditinteractor.cpp,
+ lang/cpp/src/gpgsignkeyeditinteractor.h,
+ lang/cpp/src/importresult.cpp,
+ lang/cpp/src/importresult.h,
+ lang/cpp/src/key.cpp,
+ lang/cpp/src/key.h,
+ lang/cpp/src/keygenerationresult.cpp,
+ lang/cpp/src/keygenerationresult.h,
+ lang/cpp/src/keylistresult.cpp,
+ lang/cpp/src/keylistresult.h,
+ lang/cpp/src/notation.h,
+ lang/cpp/src/result.h,
+ lang/cpp/src/result_p.h,
+ lang/cpp/src/scdgetinfoassuantransaction.cpp,
+ lang/cpp/src/scdgetinfoassuantransaction.h,
+ lang/cpp/src/signingresult.cpp,
+ lang/cpp/src/signingresult.h,
+ lang/cpp/src/trustitem.cpp,
+ lang/cpp/src/trustitem.h,
+ lang/cpp/src/util.h,
+ lang/cpp/src/verificationresult.cpp,
+ lang/cpp/src/verificationresult.h,
+ lang/cpp/src/vfsmountresult.cpp,
+ lang/cpp/src/vfsmountresult.h,
+ lang/cpp/src/interfaces/assuantransaction.h,
+ lang/cpp/src/interfaces/dataprovider.h,
+ lang/cpp/src/interfaces/passphraseprovider.h,
+ lang/cpp/src/interfaces/progressprovider.h: New.
+
+2016-01-15 Werner Koch <wk@gnupg.org>
+
+ Fix possible _SC_OPEN_MAX max problem on AIX.
+ * src/posix-io.c [HAVE_STDINT_H]: Include stdint.h.
+ (get_max_fds): Limit returned value for too high values.
+
+2015-12-09 Werner Koch <wk@gnupg.org>
+
+ w32: Avoid conflict with Mingw-w64 version 4.0.4-1.
+ * src/w32-util.c (mkstemp): Rename to my_mkstemp. Change caller.
+
+2015-12-04 Daiki Ueno <ueno@gnu.org>
+
+ Return on user cancellation of delete operation.
+ * src/delete.c (delete_status_handler): Return on ERROR status, if the
+ error location is set to "delete_key.secret" and the code is either
+ CANCELED or FULLY_CANCELED, which indicates a situation that the user
+ selected "No" on the confirmation dialog.
+
+ doc: Fix minor errors.
+ * doc/gpgme.texi: Fix errors and typos in the cancellation and
+ gpgme_import_result_t documentation.
+
+2015-10-29 Ben Kibbey <bjk@luxsci.net>
+
+ Make use of user passphrase handler during passwd.
+ * src/passwd.c (passwd_start): set engine passphrase command handler.
+
+2015-10-28 Werner Koch <wk@gnupg.org>
+
+ w32: Add extra diagnostic about possible missing gpgme-w32spawn.exe.
+ * src/w32-io.c (_gpgme_io_spawn): Add a new diagnostic.
+
+ w32: Improve locating gpgconf on 64 bit systems.
+ * src/w32-util.c (find_program_at_standard_place): Fallback to
+ CSIDL_PROGRAM_FILESX86.
+
+ w32: Add new global flag "w32-inst-dir".
+ * src/gpgme.c (gpgme_set_global_flag): Add flag "w32-inst-dir";
+ * src/posix-util.c (_gpgme_set_override_inst_dir): New stub.
+ * src/w32-util.c (override_inst_dir): New var.
+ (_gpgme_get_inst_dir): Return this var is set.
+ (_gpgme_set_override_inst_dir): New.
+
+2015-10-16 NIIBE Yutaka <gniibe@fsij.org>
+
+ cleanup: Fix type mismatch around gpgme_error_t.
+ * src/data-compat.c (gpgme_error_to_errno): Use gpg_err_code
+ to get error code from gpgme_error_t.
+ * src/gpgme.c (gpgme_new): Don't use gpgme_error.
+
+2015-08-31 Werner Koch <wk@gnupg.org>
+
+ gpgme-tool: Switch to argparse.c for option parsing.
+ * src/argparse.c, src/argparse.h: New. Taken from current gnupg.
+ * src/Makefile.am (gpgme_tool_SOURCES): New.
+ * src/gpgme-tool.c: Remove all argp.h stuff.
+ (my_strusage): New.
+ (main): Change to use argparse.
+
+2015-08-30 Werner Koch <wk@gnupg.org>
+
+ Add gpgme_pubkey_algo_string.
+ * src/gpgme.h.in (GPGME_PK_EDDSA): New.
+ (gpgme_pubkey_algo_string): New.
+ * src/conversion.c (_gpgme_map_pk_algo): Add new algo.
+ * src/gpgme.c (gpgme_pubkey_algo_string): New.
+ (gpgme_pubkey_algo_name): Reformat.
+
2015-08-26 Werner Koch <wk@gnupg.org>
Release 1.6.0.
@@ -135,6 +2815,18 @@
* src/engine-gpg.c (gpg_decrypt, gpg_delete, gpg_passwd): Check return
value of start().
+2015-08-02 Ben McGinnes <ben@adversary.org>
+
+ More GTK2 removal.
+ * Missed a couple of files, these 2 go for the same reason as the
+ previous 3.
+
+ Removed GUI examples.
+ * GUI examples written with pygtk, which has not been ported to Python
+ 3 and won't be as it is for GTK2 and GNOME is moving to GTK3.
+ * New GUI examples may be required in future using any of several GUI
+ frameworks (e.g. wxPython, PyQt, PySide, PyGObject, etc.).
+
2015-07-31 Andre Heinecke <aheinecke@intevation.de>
Add offline mode support for CMS keylisting.
@@ -210,6 +2902,85 @@
* src/engine-gpg.c (gpg_keylist_preprocess): Increment SRC for a
backslash.
+2015-05-16 Ben McGinnes <ben@adversary.org>
+
+ Python 3 port of PyME.
+ * Port of PyME 0.9.0 for Python 2 to Python 3 along with most of the
+ example scripts.
+ * Intended to be developed in parallel with the original Python 2
+ version until such time as a rewrite of GPGME leads to developing an
+ IO API in Python 3 from scratch.
+ * Python 3 PyME and API maintainer has entered, stage left with current
+ GPG key ID 0x321E4E2373590E5D, primary fingerprint is "DB47 24E6 FA42
+ 86C9 2B4E 55C4 321E 4E23 7359 0E5D" and signing subkey fingerprint is
+ "B7F0 FE75 9387 430D D0C5 8BDB 7FF2 D371 35C7 553C" for future
+ reference with git commit signatures.
+
+ Explaining why not all scripts work.
+ * Some of them cannot be properly tested on OS X, especially with GTK in
+ the mix (it works on OS X, but is unlikely to be as easily accessible
+ as Cocoa or Qt).
+ * Most major functions are showcased and do work, albeit sometimes with
+ false positives of error messages, at least on OS X.
+
+ Byte encoding.
+ * More string updates.
+ * verifydetails.py still fails, but as Bernhard is still contactable, it
+ might be worth him checking on it instead.
+
+ No change, note added to explain why.
+
+ Strings vs. Bytes.
+ * CLI input must be byte encoded.
+
+ More byte changes and passphrase changes.
+ * exportimport works, but will still segfault for an as yet unknown
+ reason.
+ * genkey produces a traceback error, but does create the key as
+ intended.
+ * matched passphrase in signverify.
+
+ More bytes good.
+ * Another string to byte change.
+
+ Updated encrypt-to-all.
+ * Changed plaintext string to byte literal.
+ * Nested key selection in a try/except statement in case of
+ UnicodeEncodeError instances.
+ * Tested successfully on over 9,000 keys.
+
+ Passphrase update.
+ * Changed example passphrase to something that meets the current minimum
+ requirements.
+
+ example email.
+ * changed joe@foo.bar to joe@example.org as it is only a matter of time
+ before ICANN actually creates bar as a gTLD, if they haven't already.
+
+ Updated string and key data.
+ * Text changed to byte literals.
+ * Changed key type to RSA/RSA.
+ * Changed expiry to the future (2020).
+
+2015-05-08 Ben McGinnes <ben@adversary.org>
+
+ String type.
+ * the plain text string must be bytes and not unicode.
+ * Expect most of the example code to have similar issues at present.
+
+2015-05-05 Ben McGinnes <ben@adversary.org>
+
+ Python 3 port of PyME.
+ * The entirety of the Python 3 port of PyME up to commit
+ 2145348ec54c6027f2ea20f695de0277e2871405
+ * The old commit log has been saved as
+ lang/py3-pyme/docs/old-commits.log
+ * Can be viewed as a normal (separate) git repository at
+ https://github.com/adversary-org/pyme3
+ * Utilising the submodule feature of git was deliberately skipped on
+ humanitarian grounds (in order to prevent pain and suffering on the
+ part of anyone having to manage this repository).
+
2015-04-13 Werner Koch <wk@gnupg.org>
Release 1.5.4.
diff --git a/Makefile.am b/Makefile.am
index cb22a91..72b8ee9 100644
--- a/Makefile.am
+++ b/Makefile.am
@@ -39,9 +39,23 @@ SUBDIRS = src ${tests} doc lang
# to be used for patch's Prereq: feature.
dist-hook: gen-ChangeLog
@set -e; \
- sed -e 's/@pkg_version@/$(VERSION)/g' \
+ sed -e 's/@pkg_version@/$(PACKAGE_VERSION)/g' \
$(top_srcdir)/gpgme.spec.in > $(distdir)/gpgme.spec
- echo "$(VERSION)" > $(distdir)/VERSION
+ echo "$(PACKAGE_VERSION)" > $(distdir)/VERSION
+
+distcheck-hook:
+ set -e; ( \
+ pref="#+macro: gpgme_" ;\
+ reldate="$$(date -u +%Y-%m-%d)" ;\
+ echo "$${pref}ver $(PACKAGE_VERSION)" ;\
+ echo "$${pref}date $${reldate}" ;\
+ list='$(DIST_ARCHIVES)'; for i in $$list; do \
+ case "$$i" in *.tar.bz2) \
+ echo "$${pref}size $$(wc -c <$$i|awk '{print int($$1/1024)}')k" ;\
+ echo "$${pref}sha1 $$(sha1sum <$$i|cut -d' ' -f1)" ;\
+ echo "$${pref}sha2 $$(sha256sum <$$i|cut -d' ' -f1)" ;;\
+ esac;\
+ done ) | tee $(distdir).swdb
gen_start_date = 2011-12-01T00:00:00
diff --git a/Makefile.in b/Makefile.in
index d469e6a..20f5005 100644
--- a/Makefile.in
+++ b/Makefile.in
@@ -101,7 +101,8 @@ DIST_COMMON = INSTALL NEWS README AUTHORS ChangeLog \
$(srcdir)/Makefile.in $(srcdir)/Makefile.am \
$(top_srcdir)/configure $(am__configure_deps) \
$(srcdir)/config.h.in $(top_srcdir)/build-aux/mkinstalldirs \
- COPYING COPYING.LESSER THANKS TODO build-aux/compile \
+ $(top_srcdir)/lang/python/pyme/version.py.in COPYING \
+ COPYING.LESSER THANKS TODO build-aux/compile \
build-aux/config.guess build-aux/config.sub build-aux/depcomp \
build-aux/install-sh build-aux/mdate-sh missing \
build-aux/missing build-aux/mkinstalldirs \
@@ -113,12 +114,16 @@ DIST_COMMON = INSTALL NEWS README AUTHORS ChangeLog \
$(top_srcdir)/build-aux/ltmain.sh \
$(top_srcdir)/build-aux/missing
ACLOCAL_M4 = $(top_srcdir)/aclocal.m4
-am__aclocal_m4_deps = $(top_srcdir)/m4/glib-2.0.m4 \
- $(top_srcdir)/m4/glibc21.m4 $(top_srcdir)/m4/gnupg-ttyname.m4 \
+am__aclocal_m4_deps = $(top_srcdir)/m4/ax_cxx_compile_stdcxx.m4 \
+ $(top_srcdir)/m4/ax_pkg_swig.m4 \
+ $(top_srcdir)/m4/ax_python_devel.m4 \
+ $(top_srcdir)/m4/glib-2.0.m4 $(top_srcdir)/m4/glibc21.m4 \
+ $(top_srcdir)/m4/gnupg-ttyname.m4 \
$(top_srcdir)/m4/gpg-error.m4 $(top_srcdir)/m4/libassuan.m4 \
$(top_srcdir)/m4/libtool.m4 $(top_srcdir)/m4/ltoptions.m4 \
$(top_srcdir)/m4/ltsugar.m4 $(top_srcdir)/m4/ltversion.m4 \
- $(top_srcdir)/m4/lt~obsolete.m4 $(top_srcdir)/acinclude.m4 \
+ $(top_srcdir)/m4/lt~obsolete.m4 $(top_srcdir)/m4/pkg.m4 \
+ $(top_srcdir)/m4/qt.m4 $(top_srcdir)/acinclude.m4 \
$(top_srcdir)/configure.ac
am__configure_deps = $(am__aclocal_m4_deps) $(CONFIGURE_DEPENDENCIES) \
$(ACLOCAL_M4)
@@ -126,7 +131,7 @@ am__CONFIG_DISTCLEAN_FILES = config.status config.cache config.log \
configure.lineno config.status.lineno
mkinstalldirs = $(SHELL) $(top_srcdir)/build-aux/mkinstalldirs
CONFIG_HEADER = config.h
-CONFIG_CLEAN_FILES =
+CONFIG_CLEAN_FILES = lang/python/pyme/version.py
CONFIG_CLEAN_VPATH_FILES =
AM_V_P = $(am__v_P_@AM_V@)
am__v_P_ = $(am__v_P_@AM_DEFAULT_V@)
@@ -241,6 +246,7 @@ BUILD_REVISION = @BUILD_REVISION@
BUILD_TIMESTAMP = @BUILD_TIMESTAMP@
CC = @CC@
CCDEPMODE = @CCDEPMODE@
+CC_FOR_BUILD = @CC_FOR_BUILD@
CFLAGS = @CFLAGS@
CPP = @CPP@
CPPFLAGS = @CPPFLAGS@
@@ -252,12 +258,14 @@ CYGPATH_W = @CYGPATH_W@
DEFS = @DEFS@
DEPDIR = @DEPDIR@
DLLTOOL = @DLLTOOL@
+DOXYGEN = @DOXYGEN@
DSYMUTIL = @DSYMUTIL@
DUMPBIN = @DUMPBIN@
ECHO_C = @ECHO_C@
ECHO_N = @ECHO_N@
ECHO_T = @ECHO_T@
EGREP = @EGREP@
+ENABLED_LANGUAGES = @ENABLED_LANGUAGES@
EXEEXT = @EXEEXT@
FGREP = @FGREP@
GITLOG_TO_CHANGELOG = @GITLOG_TO_CHANGELOG@
@@ -268,15 +276,23 @@ GLIB_LIBS = @GLIB_LIBS@
GLIB_MKENUMS = @GLIB_MKENUMS@
GOBJECT_QUERY = @GOBJECT_QUERY@
GPGME_CONFIG_API_VERSION = @GPGME_CONFIG_API_VERSION@
+GPGME_CONFIG_AVAIL_LANG = @GPGME_CONFIG_AVAIL_LANG@
GPGME_CONFIG_CFLAGS = @GPGME_CONFIG_CFLAGS@
GPGME_CONFIG_HOST = @GPGME_CONFIG_HOST@
GPGME_CONFIG_LIBS = @GPGME_CONFIG_LIBS@
+GPGME_QTTEST_CFLAGS = @GPGME_QTTEST_CFLAGS@
+GPGME_QTTEST_LIBS = @GPGME_QTTEST_LIBS@
+GPGME_QT_CFLAGS = @GPGME_QT_CFLAGS@
+GPGME_QT_LIBS = @GPGME_QT_LIBS@
GPG_ERROR_CFLAGS = @GPG_ERROR_CFLAGS@
GPG_ERROR_CONFIG = @GPG_ERROR_CONFIG@
GPG_ERROR_LIBS = @GPG_ERROR_LIBS@
GPG_ERROR_MT_CFLAGS = @GPG_ERROR_MT_CFLAGS@
GPG_ERROR_MT_LIBS = @GPG_ERROR_MT_LIBS@
+GRAPHVIZ = @GRAPHVIZ@
GREP = @GREP@
+HAVE_CXX11 = @HAVE_CXX11@
+HAVE_DOT = @HAVE_DOT@
INSTALL = @INSTALL@
INSTALL_DATA = @INSTALL_DATA@
INSTALL_PROGRAM = @INSTALL_PROGRAM@
@@ -287,10 +303,16 @@ LDFLAGS = @LDFLAGS@
LIBASSUAN_CFLAGS = @LIBASSUAN_CFLAGS@
LIBASSUAN_CONFIG = @LIBASSUAN_CONFIG@
LIBASSUAN_LIBS = @LIBASSUAN_LIBS@
+LIBGPGMEPP_LT_AGE = @LIBGPGMEPP_LT_AGE@
+LIBGPGMEPP_LT_CURRENT = @LIBGPGMEPP_LT_CURRENT@
+LIBGPGMEPP_LT_REVISION = @LIBGPGMEPP_LT_REVISION@
LIBGPGME_LT_AGE = @LIBGPGME_LT_AGE@
LIBGPGME_LT_CURRENT = @LIBGPGME_LT_CURRENT@
LIBGPGME_LT_REVISION = @LIBGPGME_LT_REVISION@
LIBOBJS = @LIBOBJS@
+LIBQGPGME_LT_AGE = @LIBQGPGME_LT_AGE@
+LIBQGPGME_LT_CURRENT = @LIBQGPGME_LT_CURRENT@
+LIBQGPGME_LT_REVISION = @LIBQGPGME_LT_REVISION@
LIBS = @LIBS@
LIBTOOL = @LIBTOOL@
LIPO = @LIPO@
@@ -300,6 +322,8 @@ MAINT = @MAINT@
MAKEINFO = @MAKEINFO@
MANIFEST_TOOL = @MANIFEST_TOOL@
MKDIR_P = @MKDIR_P@
+MOC = @MOC@
+MOC2 = @MOC2@
NEED__FILE_OFFSET_BITS = @NEED__FILE_OFFSET_BITS@
NM = @NM@
NMEDIT = @NMEDIT@
@@ -316,14 +340,27 @@ PACKAGE_URL = @PACKAGE_URL@
PACKAGE_VERSION = @PACKAGE_VERSION@
PATH_SEPARATOR = @PATH_SEPARATOR@
PKG_CONFIG = @PKG_CONFIG@
-QT4_CORE_CFLAGS = @QT4_CORE_CFLAGS@
-QT4_CORE_LIBS = @QT4_CORE_LIBS@
+PYTHON = @PYTHON@
+PYTHONS = @PYTHONS@
+PYTHON_CPPFLAGS = @PYTHON_CPPFLAGS@
+PYTHON_EXEC_PREFIX = @PYTHON_EXEC_PREFIX@
+PYTHON_EXTRA_LDFLAGS = @PYTHON_EXTRA_LDFLAGS@
+PYTHON_EXTRA_LIBS = @PYTHON_EXTRA_LIBS@
+PYTHON_LDFLAGS = @PYTHON_LDFLAGS@
+PYTHON_PLATFORM = @PYTHON_PLATFORM@
+PYTHON_PREFIX = @PYTHON_PREFIX@
+PYTHON_SITE_PKG = @PYTHON_SITE_PKG@
+PYTHON_VERSION = @PYTHON_VERSION@
+PYTHON_VERSIONS = @PYTHON_VERSIONS@
+QTCHOOSER = @QTCHOOSER@
RANLIB = @RANLIB@
RC = @RC@
SED = @SED@
SET_MAKE = @SET_MAKE@
SHELL = @SHELL@
STRIP = @STRIP@
+SWIG = @SWIG@
+SWIG_LIB = @SWIG_LIB@
SYSROOT = @SYSROOT@
VERSION = @VERSION@
VERSION_NUMBER = @VERSION_NUMBER@
@@ -372,9 +409,13 @@ mandir = @mandir@
mkdir_p = @mkdir_p@
oldincludedir = @oldincludedir@
pdfdir = @pdfdir@
+pkgpyexecdir = @pkgpyexecdir@
+pkgpythondir = @pkgpythondir@
prefix = @prefix@
program_transform_name = @program_transform_name@
psdir = @psdir@
+pyexecdir = @pyexecdir@
+pythondir = @pythondir@
sbindir = @sbindir@
sharedstatedir = @sharedstatedir@
srcdir = @srcdir@
@@ -445,6 +486,8 @@ $(srcdir)/config.h.in: @MAINTAINER_MODE_TRUE@ $(am__configure_deps)
distclean-hdr:
-rm -f config.h stamp-h1
+lang/python/pyme/version.py: $(top_builddir)/config.status $(top_srcdir)/lang/python/pyme/version.py.in
+ cd $(top_builddir) && $(SHELL) ./config.status $@
mostlyclean-libtool:
-rm -f *.lo
@@ -693,6 +736,7 @@ distcheck: dist
test -d $(distdir)/_build || exit 0; \
dc_install_base=`$(am__cd) $(distdir)/_inst && pwd | sed -e 's,^[^:\\/]:[\\/],/,'` \
&& dc_destdir="$${TMPDIR-/tmp}/am-dc-$$$$/" \
+ && $(MAKE) $(AM_MAKEFLAGS) distcheck-hook \
&& am__cwd=`pwd` \
&& $(am__cd) $(distdir)/_build \
&& ../configure \
@@ -880,9 +924,23 @@ uninstall-am:
# to be used for patch's Prereq: feature.
dist-hook: gen-ChangeLog
@set -e; \
- sed -e 's/@pkg_version@/$(VERSION)/g' \
+ sed -e 's/@pkg_version@/$(PACKAGE_VERSION)/g' \
$(top_srcdir)/gpgme.spec.in > $(distdir)/gpgme.spec
- echo "$(VERSION)" > $(distdir)/VERSION
+ echo "$(PACKAGE_VERSION)" > $(distdir)/VERSION
+
+distcheck-hook:
+ set -e; ( \
+ pref="#+macro: gpgme_" ;\
+ reldate="$$(date -u +%Y-%m-%d)" ;\
+ echo "$${pref}ver $(PACKAGE_VERSION)" ;\
+ echo "$${pref}date $${reldate}" ;\
+ list='$(DIST_ARCHIVES)'; for i in $$list; do \
+ case "$$i" in *.tar.bz2) \
+ echo "$${pref}size $$(wc -c <$$i|awk '{print int($$1/1024)}')k" ;\
+ echo "$${pref}sha1 $$(sha1sum <$$i|cut -d' ' -f1)" ;\
+ echo "$${pref}sha2 $$(sha256sum <$$i|cut -d' ' -f1)" ;;\
+ esac;\
+ done ) | tee $(distdir).swdb
.PHONY: gen-ChangeLog
gen-ChangeLog:
if test -d $(top_srcdir)/.git; then \
diff --git a/NEWS b/NEWS
index 8518dae..e4966e8 100644
--- a/NEWS
+++ b/NEWS
@@ -1,3 +1,108 @@
+Noteworthy changes in version 1.7.0 (2016-09-21) [C26/A15/R0]
+------------------------------------------------
+
+ * New language bindings for Python 2 and 3.
+
+ * New language Bindings for C++ and the Qt-Framework API.
+
+ * New functions gpgme_op_createkey and gpgme_op_createsubkey to make
+ key creation easier (requires GnuPG 2.1).
+
+ * New functions gpgme_op_adduid and gpgme_op_revuid to make user id
+ management easier (requires GnuPG 2.1).
+
+ * New function gpgme_op_keysign to make key signing easier (requires
+ GnuPG 2.1).
+
+ * New function gpgme_op_interact to replace the now deprecated
+ functions gpgme_op_edit and gpgme_op_card_edit.
+
+ * New function gpgme_pubkey_algo_string to convert a public key
+ algorithm into a GnuPG 2.1 style string.
+
+ * Support for GnuPG 2.1's TOFU trust model.
+
+ * Notation flags are now correctly set on verify.
+
+ * New global flag "require-gnupg" to set a minimal gnupg version.
+
+ * More supported items in gpgme_get_dirinfo.
+
+ * New function gpgme_data_set_flag and flag "size-hint".
+
+ * New function gpgme_set_ctx_flag and flags "full-status" and
+ "raw-description".
+
+ * Improved gpgme_data_identify to distinguish more file types.
+
+ * New flag GPGME_ENCRYPT_SYMMETRIC for gpgme_op_encrypt to allow
+ mixed public key and symmetric encryption.
+
+ * New field KEYGRIP in gpgme_subkey_t. New fields FPR in gpgme_key_t.
+
+ * New flag GPGME_DATA_ENCODING_MIME to declare that the encrypted or
+ signed data is a valid MIME part. This is to support future GnuPG
+ versions.
+
+ * Interface changes relative to the 1.6.0 release:
+ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+ gpgme_pubkey_algo_string NEW.
+ GPGME_PK_EDDSA NEW.
+ gpgme_set_ctx_flag NEW.
+ gpgme_data_set_flag NEW.
+ gpgme_op_createkey NEW.
+ gpgme_op_createkey_start NEW.
+ gpgme_op_createsubkey NEW.
+ gpgme_op_createsubkey_start NEW.
+ gpgme_op_adduid_start NEW.
+ gpgme_op_adduid NEW.
+ gpgme_op_revuid_start NEW.
+ gpgme_op_revuid NEW.
+ gpgme_op_keysign_start NEW.
+ gpgme_op_keysign NEW.
+ gpgme_op_tofu_policy_start NEW.
+ gpgme_op_tofu_policy NEW.
+ gpgme_op_interact_start NEW.
+ gpgme_op_interact NEW.
+ gpgme_interact_cb_t NEW.
+ gpgme_op_edit_start DEPRECATED.
+ gpgme_op_edit DEPRECATED.
+ gpgme_op_card_edit_start DEPRECATED.
+ gpgme_op_card_edit DEPRECATED.
+ gpgme_edit_cb_t DEPRECATED.
+ gpgme_status_code_t DEPRECATED.
+ gpgme_genkey_result_t EXTENDED: New fields pubkey and seckey.
+ gpgme_signature_t EXTENDED: New field key.
+ gpgme_key_t EXTENDED: New field fpr.
+ gpgme_subkey_t EXTENDED: New field keygrip.
+ gpgme_user_id_t EXTENDED: New field tofu.
+ gpgme_tofu_policy_t NEW.
+ gpgme_tofu_info_t NEW.
+ GPGME_STATUS_KEY_CONSIDERED NEW.
+ GPGME_STATUS_TOFU_USER NEW.
+ GPGME_STATUS_TOFU_STATS NEW.
+ GPGME_STATUS_TOFU_STATS_LONG NEW.
+ GPGME_STATUS_NOTATION_FLAGS NEW.
+ GPGME_KEYLIST_MODE_WITH_TOFU NEW.
+ GPGME_DATA_TYPE_PGP_ENCRYPTED NEW.
+ GPGME_DATA_TYPE_PGP_SIGNATURE NEW.
+ GPGME_DATA_ENCODING_MIME NEW.
+ GPGME_ENCRYPT_SYMMETRIC NEW.
+ GPGME_CREATE_SIGN NEW.
+ GPGME_CREATE_ENCR NEW.
+ GPGME_CREATE_CERT NEW.
+ GPGME_CREATE_AUTH NEW.
+ GPGME_CREATE_NOPASSWD NEW.
+ GPGME_CREATE_SELFSIGNED NEW.
+ GPGME_CREATE_NOSTORE NEW.
+ GPGME_CREATE_WANTPUB NEW.
+ GPGME_CREATE_WANTSEC NEW.
+ GPGME_CREATE_FORCE NEW.
+ GPGME_KEYSIGN_LOCAL NEW.
+ GPGME_KEYSIGN_LFSEP NEW.
+ GPGME_INTERACT_CARD NEW.
+
+
Noteworthy changes in version 1.6.0 (2015-08-26) [C25/A14/R0]
------------------------------------------------
diff --git a/README b/README
index 6da94e5..90f2e39 100644
--- a/README
+++ b/README
@@ -1,7 +1,7 @@
- GPGME - GnuPG Made Easy
- ---------------------------
+ GPGME - GnuPG Made Easy
+ ---------------------------
- Copyright 2004, 2006, 2010, 2012, 2013, 2014, 2015 g10 Code GmbH
+ Copyright 2001-2016 g10 Code GmbH
This file is free software; as a special exception the author gives
unlimited permission to copy and/or distribute it, with or without
@@ -22,12 +22,12 @@ to public key crypto engines like GnuPG or GpgSM easier for
applications. GPGME provides a high-level crypto API for encryption,
decryption, signing, signature verification and key management.
+GPGME comes with language bindings for Common Lisp, C++, QT, Python2
+and Python 3.
+
GPGME uses GnuPG and GpgSM as its backends to support OpenPGP and the
Cryptographic Message Syntax (CMS).
-GPGME runs best on GNU/Linux or *BSD systems. Other Unices may
-require small portability fixes, please send us your patches.
-
See the files COPYING, COPYING.LESSER, and each file for copyright and
warranty information. The file AUTHORS has a list of authors and
useful web and mail addresses.
@@ -70,18 +70,32 @@ a) If you have a trusted Version of GnuPG installed, you can simply check
indeed a a signature of gpgme-x.y.z.tar.gz. The key used to create
this signature is either of:
- "pub 2048R/4F25E3B6 2011-01-12 Werner Koch (dist sig)"
- "pub 1024D/87978569 1999-05-13
- Marcus Brinkmann <Marcus.Brinkmann@ruhr-uni-bochum.de>
- Marcus Brinkmann <mb@g10code.com>"
+ 2048R/4F25E3B6 2011-01-12 [expires: 2019-12-31]
+ Key fingerprint = D869 2123 C406 5DEA 5E0F 3AB5 249B 39D2 4F25 E3B6
+ Werner Koch (dist sig)
+
+ rsa2048/E0856959 2014-10-29 [expires: 2019-12-31]
+ Key fingerprint = 46CC 7308 65BB 5C78 EBAB ADCF 0437 6F3E E085 6959
+ David Shaw (GnuPG Release Signing Key) <dshaw 'at' jabberwocky.com>
+
+ rsa2048/33BD3F06 2014-10-29 [expires: 2016-10-28]
+ Key fingerprint = 031E C253 6E58 0D8E A286 A9F2 2071 B08A 33BD 3F06
+ NIIBE Yutaka (GnuPG Release Key) <gniibe 'at' fsij.org>
+
+ rsa2048/7EFD60D9 2014-10-19 [expires: 2020-12-31]
+ Key fingerprint = D238 EA65 D64C 67ED 4C30 73F2 8A86 1B1C 7EFD 60D9
+ Werner Koch (Release Signing Key)
- If you do not have this key, you can get it from any keyserver. You
- have to make sure that this is really the key and not a faked one.
- You can do this by comparing the output of:
+ You may retrieve these files from the keyservers using this command
- $ gpg --fingerprint 0x4F25E3B6
+ gpg --recv-keys 249B39D24F25E3B6 04376F3EE0856959 \
+ 2071B08A33BD3F06 8A861B1C7EFD60D9
- with the fingerprint published elsewhere.
+ The keys are also available at https://gnupg.org/signature_key.html
+ and in released GnuPG tarballs in the file g10/distsigkey.gpg .
+ You have to make sure that these are really the desired keys and
+ not faked one. You should do this by comparing the fingerprints
+ with the fingerprints published elsewhere.
b) If you don't have any of the above programs, you have to verify
the SHA1 checksum:
@@ -101,7 +115,7 @@ Documentation
For information how to use the library you can read the info manual,
which is also a reference book, in the doc/ directory. The programs
-in the tests/gpg/ directory may also prove useful.
+in the tests/ directory may also prove useful.
Please subscribe to the gnupg-devel@gnupg.org mailing list if you want
to do serious work.
diff --git a/VERSION b/VERSION
index dc1e644..bd8bf88 100644
--- a/VERSION
+++ b/VERSION
@@ -1 +1 @@
-1.6.0
+1.7.0
diff --git a/acinclude.m4 b/acinclude.m4
index cdfe6e4..575e526 100644
--- a/acinclude.m4
+++ b/acinclude.m4
@@ -58,3 +58,19 @@ AC_DEFUN([GNUPG_CHECK_VA_COPY],
AC_MSG_RESULT($gnupg_cv_must_copy_va_byval)
fi
])
+
+dnl LIST_MEMBER()
+dnl Check wether an element ist contained in a list. Set `found' to
+dnl `1' if the element is found in the list, to `0' otherwise.
+AC_DEFUN([LIST_MEMBER],
+[
+name=$1
+list=$2
+found=0
+
+for n in $list; do
+ if test "x$name" = "x$n"; then
+ found=1
+ fi
+done
+])
diff --git a/aclocal.m4 b/aclocal.m4
index 149aed2..16ee295 100644
--- a/aclocal.m4
+++ b/aclocal.m4
@@ -108,6 +108,43 @@ AC_DEFUN([AM_AUX_DIR_EXPAND],
am_aux_dir=`cd "$ac_aux_dir" && pwd`
])
+# AM_COND_IF -*- Autoconf -*-
+
+# Copyright (C) 2008-2013 Free Software Foundation, Inc.
+#
+# This file is free software; the Free Software Foundation
+# gives unlimited permission to copy and/or distribute it,
+# with or without modifications, as long as this notice is preserved.
+
+# _AM_COND_IF
+# _AM_COND_ELSE
+# _AM_COND_ENDIF
+# --------------
+# These macros are only used for tracing.
+m4_define([_AM_COND_IF])
+m4_define([_AM_COND_ELSE])
+m4_define([_AM_COND_ENDIF])
+
+# AM_COND_IF(COND, [IF-TRUE], [IF-FALSE])
+# ---------------------------------------
+# If the shell condition COND is true, execute IF-TRUE, otherwise execute
+# IF-FALSE. Allow automake to learn about conditional instantiating macros
+# (the AC_CONFIG_FOOS).
+AC_DEFUN([AM_COND_IF],
+[m4_ifndef([_AM_COND_VALUE_$1],
+ [m4_fatal([$0: no such condition "$1"])])dnl
+_AM_COND_IF([$1])dnl
+if test -z "$$1_TRUE"; then :
+ m4_n([$2])[]dnl
+m4_ifval([$3],
+[_AM_COND_ELSE([$1])dnl
+else
+ $3
+])dnl
+_AM_COND_ENDIF([$1])dnl
+fi[]dnl
+])
+
# AM_CONDITIONAL -*- Autoconf -*-
# Copyright (C) 1997-2013 Free Software Foundation, Inc.
@@ -845,6 +882,241 @@ AC_LANG_POP([C])])
# For backward compatibility.
AC_DEFUN_ONCE([AM_PROG_CC_C_O], [AC_REQUIRE([AC_PROG_CC])])
+# Copyright (C) 1999-2013 Free Software Foundation, Inc.
+#
+# This file is free software; the Free Software Foundation
+# gives unlimited permission to copy and/or distribute it,
+# with or without modifications, as long as this notice is preserved.
+
+
+# AM_PATH_PYTHON([MINIMUM-VERSION], [ACTION-IF-FOUND], [ACTION-IF-NOT-FOUND])
+# ---------------------------------------------------------------------------
+# Adds support for distributing Python modules and packages. To
+# install modules, copy them to $(pythondir), using the python_PYTHON
+# automake variable. To install a package with the same name as the
+# automake package, install to $(pkgpythondir), or use the
+# pkgpython_PYTHON automake variable.
+#
+# The variables $(pyexecdir) and $(pkgpyexecdir) are provided as
+# locations to install python extension modules (shared libraries).
+# Another macro is required to find the appropriate flags to compile
+# extension modules.
+#
+# If your package is configured with a different prefix to python,
+# users will have to add the install directory to the PYTHONPATH
+# environment variable, or create a .pth file (see the python
+# documentation for details).
+#
+# If the MINIMUM-VERSION argument is passed, AM_PATH_PYTHON will
+# cause an error if the version of python installed on the system
+# doesn't meet the requirement. MINIMUM-VERSION should consist of
+# numbers and dots only.
+AC_DEFUN([AM_PATH_PYTHON],
+ [
+ dnl Find a Python interpreter. Python versions prior to 2.0 are not
+ dnl supported. (2.0 was released on October 16, 2000).
+ m4_define_default([_AM_PYTHON_INTERPRETER_LIST],
+[python python2 python3 python3.3 python3.2 python3.1 python3.0 python2.7 dnl
+ python2.6 python2.5 python2.4 python2.3 python2.2 python2.1 python2.0])
+
+ AC_ARG_VAR([PYTHON], [the Python interpreter])
+
+ m4_if([$1],[],[
+ dnl No version check is needed.
+ # Find any Python interpreter.
+ if test -z "$PYTHON"; then
+ AC_PATH_PROGS([PYTHON], _AM_PYTHON_INTERPRETER_LIST, :)
+ fi
+ am_display_PYTHON=python
+ ], [
+ dnl A version check is needed.
+ if test -n "$PYTHON"; then
+ # If the user set $PYTHON, use it and don't search something else.
+ AC_MSG_CHECKING([whether $PYTHON version is >= $1])
+ AM_PYTHON_CHECK_VERSION([$PYTHON], [$1],
+ [AC_MSG_RESULT([yes])],
+ [AC_MSG_RESULT([no])
+ AC_MSG_ERROR([Python interpreter is too old])])
+ am_display_PYTHON=$PYTHON
+ else
+ # Otherwise, try each interpreter until we find one that satisfies
+ # VERSION.
+ AC_CACHE_CHECK([for a Python interpreter with version >= $1],
+ [am_cv_pathless_PYTHON],[
+ for am_cv_pathless_PYTHON in _AM_PYTHON_INTERPRETER_LIST none; do
+ test "$am_cv_pathless_PYTHON" = none && break
+ AM_PYTHON_CHECK_VERSION([$am_cv_pathless_PYTHON], [$1], [break])
+ done])
+ # Set $PYTHON to the absolute path of $am_cv_pathless_PYTHON.
+ if test "$am_cv_pathless_PYTHON" = none; then
+ PYTHON=:
+ else
+ AC_PATH_PROG([PYTHON], [$am_cv_pathless_PYTHON])
+ fi
+ am_display_PYTHON=$am_cv_pathless_PYTHON
+ fi
+ ])
+
+ if test "$PYTHON" = :; then
+ dnl Run any user-specified action, or abort.
+ m4_default([$3], [AC_MSG_ERROR([no suitable Python interpreter found])])
+ else
+
+ dnl Query Python for its version number. Getting [:3] seems to be
+ dnl the best way to do this; it's what "site.py" does in the standard
+ dnl library.
+
+ AC_CACHE_CHECK([for $am_display_PYTHON version], [am_cv_python_version],
+ [am_cv_python_version=`$PYTHON -c "import sys; sys.stdout.write(sys.version[[:3]])"`])
+ AC_SUBST([PYTHON_VERSION], [$am_cv_python_version])
+
+ dnl Use the values of $prefix and $exec_prefix for the corresponding
+ dnl values of PYTHON_PREFIX and PYTHON_EXEC_PREFIX. These are made
+ dnl distinct variables so they can be overridden if need be. However,
+ dnl general consensus is that you shouldn't need this ability.
+
+ AC_SUBST([PYTHON_PREFIX], ['${prefix}'])
+ AC_SUBST([PYTHON_EXEC_PREFIX], ['${exec_prefix}'])
+
+ dnl At times (like when building shared libraries) you may want
+ dnl to know which OS platform Python thinks this is.
+
+ AC_CACHE_CHECK([for $am_display_PYTHON platform], [am_cv_python_platform],
+ [am_cv_python_platform=`$PYTHON -c "import sys; sys.stdout.write(sys.platform)"`])
+ AC_SUBST([PYTHON_PLATFORM], [$am_cv_python_platform])
+
+ # Just factor out some code duplication.
+ am_python_setup_sysconfig="\
+import sys
+# Prefer sysconfig over distutils.sysconfig, for better compatibility
+# with python 3.x. See automake bug#10227.
+try:
+ import sysconfig
+except ImportError:
+ can_use_sysconfig = 0
+else:
+ can_use_sysconfig = 1
+# Can't use sysconfig in CPython 2.7, since it's broken in virtualenvs:
+# <https://github.com/pypa/virtualenv/issues/118>
+try:
+ from platform import python_implementation
+ if python_implementation() == 'CPython' and sys.version[[:3]] == '2.7':
+ can_use_sysconfig = 0
+except ImportError:
+ pass"
+
+ dnl Set up 4 directories:
+
+ dnl pythondir -- where to install python scripts. This is the
+ dnl site-packages directory, not the python standard library
+ dnl directory like in previous automake betas. This behavior
+ dnl is more consistent with lispdir.m4 for example.
+ dnl Query distutils for this directory.
+ AC_CACHE_CHECK([for $am_display_PYTHON script directory],
+ [am_cv_python_pythondir],
+ [if test "x$prefix" = xNONE
+ then
+ am_py_prefix=$ac_default_prefix
+ else
+ am_py_prefix=$prefix
+ fi
+ am_cv_python_pythondir=`$PYTHON -c "
+$am_python_setup_sysconfig
+if can_use_sysconfig:
+ sitedir = sysconfig.get_path('purelib', vars={'base':'$am_py_prefix'})
+else:
+ from distutils import sysconfig
+ sitedir = sysconfig.get_python_lib(0, 0, prefix='$am_py_prefix')
+sys.stdout.write(sitedir)"`
+ case $am_cv_python_pythondir in
+ $am_py_prefix*)
+ am__strip_prefix=`echo "$am_py_prefix" | sed 's|.|.|g'`
+ am_cv_python_pythondir=`echo "$am_cv_python_pythondir" | sed "s,^$am__strip_prefix,$PYTHON_PREFIX,"`
+ ;;
+ *)
+ case $am_py_prefix in
+ /usr|/System*) ;;
+ *)
+ am_cv_python_pythondir=$PYTHON_PREFIX/lib/python$PYTHON_VERSION/site-packages
+ ;;
+ esac
+ ;;
+ esac
+ ])
+ AC_SUBST([pythondir], [$am_cv_python_pythondir])
+
+ dnl pkgpythondir -- $PACKAGE directory under pythondir. Was
+ dnl PYTHON_SITE_PACKAGE in previous betas, but this naming is
+ dnl more consistent with the rest of automake.
+
+ AC_SUBST([pkgpythondir], [\${pythondir}/$PACKAGE])
+
+ dnl pyexecdir -- directory for installing python extension modules
+ dnl (shared libraries)
+ dnl Query distutils for this directory.
+ AC_CACHE_CHECK([for $am_display_PYTHON extension module directory],
+ [am_cv_python_pyexecdir],
+ [if test "x$exec_prefix" = xNONE
+ then
+ am_py_exec_prefix=$am_py_prefix
+ else
+ am_py_exec_prefix=$exec_prefix
+ fi
+ am_cv_python_pyexecdir=`$PYTHON -c "
+$am_python_setup_sysconfig
+if can_use_sysconfig:
+ sitedir = sysconfig.get_path('platlib', vars={'platbase':'$am_py_prefix'})
+else:
+ from distutils import sysconfig
+ sitedir = sysconfig.get_python_lib(1, 0, prefix='$am_py_prefix')
+sys.stdout.write(sitedir)"`
+ case $am_cv_python_pyexecdir in
+ $am_py_exec_prefix*)
+ am__strip_prefix=`echo "$am_py_exec_prefix" | sed 's|.|.|g'`
+ am_cv_python_pyexecdir=`echo "$am_cv_python_pyexecdir" | sed "s,^$am__strip_prefix,$PYTHON_EXEC_PREFIX,"`
+ ;;
+ *)
+ case $am_py_exec_prefix in
+ /usr|/System*) ;;
+ *)
+ am_cv_python_pyexecdir=$PYTHON_EXEC_PREFIX/lib/python$PYTHON_VERSION/site-packages
+ ;;
+ esac
+ ;;
+ esac
+ ])
+ AC_SUBST([pyexecdir], [$am_cv_python_pyexecdir])
+
+ dnl pkgpyexecdir -- $(pyexecdir)/$(PACKAGE)
+
+ AC_SUBST([pkgpyexecdir], [\${pyexecdir}/$PACKAGE])
+
+ dnl Run any user-specified action.
+ $2
+ fi
+
+])
+
+
+# AM_PYTHON_CHECK_VERSION(PROG, VERSION, [ACTION-IF-TRUE], [ACTION-IF-FALSE])
+# ---------------------------------------------------------------------------
+# Run ACTION-IF-TRUE if the Python interpreter PROG has version >= VERSION.
+# Run ACTION-IF-FALSE otherwise.
+# This test uses sys.hexversion instead of the string equivalent (first
+# word of sys.version), in order to cope with versions such as 2.2c1.
+# This supports Python 2.0 or higher. (2.0 was released on October 16, 2000).
+AC_DEFUN([AM_PYTHON_CHECK_VERSION],
+ [prog="import sys
+# split strings by '.' and convert to numeric. Append some zeros
+# because we need at least 4 digits for the hex conversion.
+# map returns an iterator in Python 3.0 and a list in 2.x
+minver = list(map(int, '$2'.split('.'))) + [[0, 0, 0]]
+minverhex = 0
+# xrange is not present in Python 3.0 and range returns an iterator
+for i in list(range(0, 4)): minverhex = (minverhex << 8) + minver[[i]]
+sys.exit(sys.hexversion < minverhex)"
+ AS_IF([AM_RUN_LOG([$1 -c "$prog"])], [$3], [$4])])
+
# Copyright (C) 2001-2013 Free Software Foundation, Inc.
#
# This file is free software; the Free Software Foundation
@@ -1183,6 +1455,9 @@ AC_SUBST([am__tar])
AC_SUBST([am__untar])
]) # _AM_PROG_TAR
+m4_include([m4/ax_cxx_compile_stdcxx.m4])
+m4_include([m4/ax_pkg_swig.m4])
+m4_include([m4/ax_python_devel.m4])
m4_include([m4/glib-2.0.m4])
m4_include([m4/glibc21.m4])
m4_include([m4/gnupg-ttyname.m4])
@@ -1193,4 +1468,6 @@ m4_include([m4/ltoptions.m4])
m4_include([m4/ltsugar.m4])
m4_include([m4/ltversion.m4])
m4_include([m4/lt~obsolete.m4])
+m4_include([m4/pkg.m4])
+m4_include([m4/qt.m4])
m4_include([acinclude.m4])
diff --git a/autogen.sh b/autogen.sh
index 471193c..24da40c 100755
--- a/autogen.sh
+++ b/autogen.sh
@@ -347,7 +347,7 @@ if [ -d .git ]; then
[ -z "${SILENT}" ] && cat <<EOF
*** Activating trailing whitespace git pre-commit hook. ***
For more information see this thread:
- http://mail.gnome.org/archives/desktop-devel-list/2009-May/msg00084html
+ http://mail.gnome.org/archives/desktop-devel-list/2009-May/msg00084.html
To deactivate this pre-commit hook again move .git/hooks/pre-commit
and .git/hooks/pre-commit.sample out of the way.
EOF
diff --git a/build-aux/config.guess b/build-aux/config.guess
index dbfb978..c4bd827 100755
--- a/build-aux/config.guess
+++ b/build-aux/config.guess
@@ -1,8 +1,8 @@
#! /bin/sh
# Attempt to guess a canonical system name.
-# Copyright 1992-2015 Free Software Foundation, Inc.
+# Copyright 1992-2016 Free Software Foundation, Inc.
-timestamp='2015-01-01'
+timestamp='2016-05-15'
# This file is free software; you can redistribute it and/or modify it
# under the terms of the GNU General Public License as published by
@@ -27,7 +27,7 @@ timestamp='2015-01-01'
# Originally written by Per Bothner; maintained since 2000 by Ben Elliston.
#
# You can get the latest version of this script from:
-# http://git.savannah.gnu.org/gitweb/?p=config.git;a=blob_plain;f=config.guess;hb=HEAD
+# http://git.savannah.gnu.org/gitweb/?p=config.git;a=blob_plain;f=config.guess
#
# Please send patches to <config-patches@gnu.org>.
@@ -50,7 +50,7 @@ version="\
GNU config.guess ($timestamp)
Originally written by Per Bothner.
-Copyright 1992-2015 Free Software Foundation, Inc.
+Copyright 1992-2016 Free Software Foundation, Inc.
This is free software; see the source for copying conditions. There is NO
warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE."
@@ -168,19 +168,29 @@ case "${UNAME_MACHINE}:${UNAME_SYSTEM}:${UNAME_RELEASE}:${UNAME_VERSION}" in
# Note: NetBSD doesn't particularly care about the vendor
# portion of the name. We always set it to "unknown".
sysctl="sysctl -n hw.machine_arch"
- UNAME_MACHINE_ARCH=`(/sbin/$sysctl 2>/dev/null || \
- /usr/sbin/$sysctl 2>/dev/null || echo unknown)`
+ UNAME_MACHINE_ARCH=`(uname -p 2>/dev/null || \
+ /sbin/$sysctl 2>/dev/null || \
+ /usr/sbin/$sysctl 2>/dev/null || \
+ echo unknown)`
case "${UNAME_MACHINE_ARCH}" in
armeb) machine=armeb-unknown ;;
arm*) machine=arm-unknown ;;
sh3el) machine=shl-unknown ;;
sh3eb) machine=sh-unknown ;;
sh5el) machine=sh5le-unknown ;;
+ earmv*)
+ arch=`echo ${UNAME_MACHINE_ARCH} | sed -e 's,^e\(armv[0-9]\).*$,\1,'`
+ endian=`echo ${UNAME_MACHINE_ARCH} | sed -ne 's,^.*\(eb\)$,\1,p'`
+ machine=${arch}${endian}-unknown
+ ;;
*) machine=${UNAME_MACHINE_ARCH}-unknown ;;
esac
# The Operating System including object format, if it has switched
- # to ELF recently, or will in the future.
+ # to ELF recently (or will in the future) and ABI.
case "${UNAME_MACHINE_ARCH}" in
+ earm*)
+ os=netbsdelf
+ ;;
arm*|i386|m68k|ns32k|sh3*|sparc|vax)
eval $set_cc_for_build
if echo __ELF__ | $CC_FOR_BUILD -E - 2>/dev/null \
@@ -197,6 +207,13 @@ case "${UNAME_MACHINE}:${UNAME_SYSTEM}:${UNAME_RELEASE}:${UNAME_VERSION}" in
os=netbsd
;;
esac
+ # Determine ABI tags.
+ case "${UNAME_MACHINE_ARCH}" in
+ earm*)
+ expr='s/^earmv[0-9]/-eabi/;s/eb$//'
+ abi=`echo ${UNAME_MACHINE_ARCH} | sed -e "$expr"`
+ ;;
+ esac
# The OS release
# Debian GNU/NetBSD machines have a different userland, and
# thus, need a distinct triplet. However, they do not need
@@ -207,13 +224,13 @@ case "${UNAME_MACHINE}:${UNAME_SYSTEM}:${UNAME_RELEASE}:${UNAME_VERSION}" in
release='-gnu'
;;
*)
- release=`echo ${UNAME_RELEASE}|sed -e 's/[-_].*/\./'`
+ release=`echo ${UNAME_RELEASE} | sed -e 's/[-_].*//' | cut -d. -f1,2`
;;
esac
# Since CPU_TYPE-MANUFACTURER-KERNEL-OPERATING_SYSTEM:
# contains redundant information, the shorter form:
# CPU_TYPE-MANUFACTURER-OPERATING_SYSTEM is used.
- echo "${machine}-${os}${release}"
+ echo "${machine}-${os}${release}${abi}"
exit ;;
*:Bitrig:*:*)
UNAME_MACHINE_ARCH=`arch | sed 's/Bitrig.//'`
@@ -223,6 +240,10 @@ case "${UNAME_MACHINE}:${UNAME_SYSTEM}:${UNAME_RELEASE}:${UNAME_VERSION}" in
UNAME_MACHINE_ARCH=`arch | sed 's/OpenBSD.//'`
echo ${UNAME_MACHINE_ARCH}-unknown-openbsd${UNAME_RELEASE}
exit ;;
+ *:LibertyBSD:*:*)
+ UNAME_MACHINE_ARCH=`arch | sed 's/^.*BSD\.//'`
+ echo ${UNAME_MACHINE_ARCH}-unknown-libertybsd${UNAME_RELEASE}
+ exit ;;
*:ekkoBSD:*:*)
echo ${UNAME_MACHINE}-unknown-ekkobsd${UNAME_RELEASE}
exit ;;
@@ -235,6 +256,9 @@ case "${UNAME_MACHINE}:${UNAME_SYSTEM}:${UNAME_RELEASE}:${UNAME_VERSION}" in
*:MirBSD:*:*)
echo ${UNAME_MACHINE}-unknown-mirbsd${UNAME_RELEASE}
exit ;;
+ *:Sortix:*:*)
+ echo ${UNAME_MACHINE}-unknown-sortix
+ exit ;;
alpha:OSF1:*:*)
case $UNAME_RELEASE in
*4.0)
@@ -251,42 +275,42 @@ case "${UNAME_MACHINE}:${UNAME_SYSTEM}:${UNAME_RELEASE}:${UNAME_VERSION}" in
ALPHA_CPU_TYPE=`/usr/sbin/psrinfo -v | sed -n -e 's/^ The alpha \(.*\) processor.*$/\1/p' | head -n 1`
case "$ALPHA_CPU_TYPE" in
"EV4 (21064)")
- UNAME_MACHINE="alpha" ;;
+ UNAME_MACHINE=alpha ;;
"EV4.5 (21064)")
- UNAME_MACHINE="alpha" ;;
+ UNAME_MACHINE=alpha ;;
"LCA4 (21066/21068)")
- UNAME_MACHINE="alpha" ;;
+ UNAME_MACHINE=alpha ;;
"EV5 (21164)")
- UNAME_MACHINE="alphaev5" ;;
+ UNAME_MACHINE=alphaev5 ;;
"EV5.6 (21164A)")
- UNAME_MACHINE="alphaev56" ;;
+ UNAME_MACHINE=alphaev56 ;;
"EV5.6 (21164PC)")
- UNAME_MACHINE="alphapca56" ;;
+ UNAME_MACHINE=alphapca56 ;;
"EV5.7 (21164PC)")
- UNAME_MACHINE="alphapca57" ;;
+ UNAME_MACHINE=alphapca57 ;;
"EV6 (21264)")
- UNAME_MACHINE="alphaev6" ;;
+ UNAME_MACHINE=alphaev6 ;;
"EV6.7 (21264A)")
- UNAME_MACHINE="alphaev67" ;;
+ UNAME_MACHINE=alphaev67 ;;
"EV6.8CB (21264C)")
- UNAME_MACHINE="alphaev68" ;;
+ UNAME_MACHINE=alphaev68 ;;
"EV6.8AL (21264B)")
- UNAME_MACHINE="alphaev68" ;;
+ UNAME_MACHINE=alphaev68 ;;
"EV6.8CX (21264D)")
- UNAME_MACHINE="alphaev68" ;;
+ UNAME_MACHINE=alphaev68 ;;
"EV6.9A (21264/EV69A)")
- UNAME_MACHINE="alphaev69" ;;
+ UNAME_MACHINE=alphaev69 ;;
"EV7 (21364)")
- UNAME_MACHINE="alphaev7" ;;
+ UNAME_MACHINE=alphaev7 ;;
"EV7.9 (21364A)")
- UNAME_MACHINE="alphaev79" ;;
+ UNAME_MACHINE=alphaev79 ;;
esac
# A Pn.n version is a patched version.
# A Vn.n version is a released version.
# A Tn.n version is a released field test version.
# A Xn.n version is an unreleased experimental baselevel.
# 1.2 uses "1.2" for uname -r.
- echo ${UNAME_MACHINE}-dec-osf`echo ${UNAME_RELEASE} | sed -e 's/^[PVTX]//' | tr 'ABCDEFGHIJKLMNOPQRSTUVWXYZ' 'abcdefghijklmnopqrstuvwxyz'`
+ echo ${UNAME_MACHINE}-dec-osf`echo ${UNAME_RELEASE} | sed -e 's/^[PVTX]//' | tr ABCDEFGHIJKLMNOPQRSTUVWXYZ abcdefghijklmnopqrstuvwxyz`
# Reset EXIT trap before exiting to avoid spurious non-zero exit code.
exitcode=$?
trap '' 0
@@ -359,16 +383,16 @@ case "${UNAME_MACHINE}:${UNAME_SYSTEM}:${UNAME_RELEASE}:${UNAME_VERSION}" in
exit ;;
i86pc:SunOS:5.*:* | i86xen:SunOS:5.*:*)
eval $set_cc_for_build
- SUN_ARCH="i386"
+ SUN_ARCH=i386
# If there is a compiler, see if it is configured for 64-bit objects.
# Note that the Sun cc does not turn __LP64__ into 1 like gcc does.
# This test works for both compilers.
- if [ "$CC_FOR_BUILD" != 'no_compiler_found' ]; then
+ if [ "$CC_FOR_BUILD" != no_compiler_found ]; then
if (echo '#ifdef __amd64'; echo IS_64BIT_ARCH; echo '#endif') | \
- (CCOPTS= $CC_FOR_BUILD -E - 2>/dev/null) | \
+ (CCOPTS="" $CC_FOR_BUILD -E - 2>/dev/null) | \
grep IS_64BIT_ARCH >/dev/null
then
- SUN_ARCH="x86_64"
+ SUN_ARCH=x86_64
fi
fi
echo ${SUN_ARCH}-pc-solaris2`echo ${UNAME_RELEASE}|sed -e 's/[^.]*//'`
@@ -393,7 +417,7 @@ case "${UNAME_MACHINE}:${UNAME_SYSTEM}:${UNAME_RELEASE}:${UNAME_VERSION}" in
exit ;;
sun*:*:4.2BSD:*)
UNAME_RELEASE=`(sed 1q /etc/motd | awk '{print substr($5,1,3)}') 2>/dev/null`
- test "x${UNAME_RELEASE}" = "x" && UNAME_RELEASE=3
+ test "x${UNAME_RELEASE}" = x && UNAME_RELEASE=3
case "`/bin/arch`" in
sun3)
echo m68k-sun-sunos${UNAME_RELEASE}
@@ -618,13 +642,13 @@ EOF
sc_cpu_version=`/usr/bin/getconf SC_CPU_VERSION 2>/dev/null`
sc_kernel_bits=`/usr/bin/getconf SC_KERNEL_BITS 2>/dev/null`
case "${sc_cpu_version}" in
- 523) HP_ARCH="hppa1.0" ;; # CPU_PA_RISC1_0
- 528) HP_ARCH="hppa1.1" ;; # CPU_PA_RISC1_1
+ 523) HP_ARCH=hppa1.0 ;; # CPU_PA_RISC1_0
+ 528) HP_ARCH=hppa1.1 ;; # CPU_PA_RISC1_1
532) # CPU_PA_RISC2_0
case "${sc_kernel_bits}" in
- 32) HP_ARCH="hppa2.0n" ;;
- 64) HP_ARCH="hppa2.0w" ;;
- '') HP_ARCH="hppa2.0" ;; # HP-UX 10.20
+ 32) HP_ARCH=hppa2.0n ;;
+ 64) HP_ARCH=hppa2.0w ;;
+ '') HP_ARCH=hppa2.0 ;; # HP-UX 10.20
esac ;;
esac
fi
@@ -663,11 +687,11 @@ EOF
exit (0);
}
EOF
- (CCOPTS= $CC_FOR_BUILD -o $dummy $dummy.c 2>/dev/null) && HP_ARCH=`$dummy`
+ (CCOPTS="" $CC_FOR_BUILD -o $dummy $dummy.c 2>/dev/null) && HP_ARCH=`$dummy`
test -z "$HP_ARCH" && HP_ARCH=hppa
fi ;;
esac
- if [ ${HP_ARCH} = "hppa2.0w" ]
+ if [ ${HP_ARCH} = hppa2.0w ]
then
eval $set_cc_for_build
@@ -680,12 +704,12 @@ EOF
# $ CC_FOR_BUILD="cc +DA2.0w" ./config.guess
# => hppa64-hp-hpux11.23
- if echo __LP64__ | (CCOPTS= $CC_FOR_BUILD -E - 2>/dev/null) |
+ if echo __LP64__ | (CCOPTS="" $CC_FOR_BUILD -E - 2>/dev/null) |
grep -q __LP64__
then
- HP_ARCH="hppa2.0w"
+ HP_ARCH=hppa2.0w
else
- HP_ARCH="hppa64"
+ HP_ARCH=hppa64
fi
fi
echo ${HP_ARCH}-hp-hpux${HPUX_REV}
@@ -790,14 +814,14 @@ EOF
echo craynv-cray-unicosmp${UNAME_RELEASE} | sed -e 's/\.[^.]*$/.X/'
exit ;;
F30[01]:UNIX_System_V:*:* | F700:UNIX_System_V:*:*)
- FUJITSU_PROC=`uname -m | tr 'ABCDEFGHIJKLMNOPQRSTUVWXYZ' 'abcdefghijklmnopqrstuvwxyz'`
- FUJITSU_SYS=`uname -p | tr 'ABCDEFGHIJKLMNOPQRSTUVWXYZ' 'abcdefghijklmnopqrstuvwxyz' | sed -e 's/\///'`
+ FUJITSU_PROC=`uname -m | tr ABCDEFGHIJKLMNOPQRSTUVWXYZ abcdefghijklmnopqrstuvwxyz`
+ FUJITSU_SYS=`uname -p | tr ABCDEFGHIJKLMNOPQRSTUVWXYZ abcdefghijklmnopqrstuvwxyz | sed -e 's/\///'`
FUJITSU_REL=`echo ${UNAME_RELEASE} | sed -e 's/ /_/'`
echo "${FUJITSU_PROC}-fujitsu-${FUJITSU_SYS}${FUJITSU_REL}"
exit ;;
5000:UNIX_System_V:4.*:*)
- FUJITSU_SYS=`uname -p | tr 'ABCDEFGHIJKLMNOPQRSTUVWXYZ' 'abcdefghijklmnopqrstuvwxyz' | sed -e 's/\///'`
- FUJITSU_REL=`echo ${UNAME_RELEASE} | tr 'ABCDEFGHIJKLMNOPQRSTUVWXYZ' 'abcdefghijklmnopqrstuvwxyz' | sed -e 's/ /_/'`
+ FUJITSU_SYS=`uname -p | tr ABCDEFGHIJKLMNOPQRSTUVWXYZ abcdefghijklmnopqrstuvwxyz | sed -e 's/\///'`
+ FUJITSU_REL=`echo ${UNAME_RELEASE} | tr ABCDEFGHIJKLMNOPQRSTUVWXYZ abcdefghijklmnopqrstuvwxyz | sed -e 's/ /_/'`
echo "sparc-fujitsu-${FUJITSU_SYS}${FUJITSU_REL}"
exit ;;
i*86:BSD/386:*:* | i*86:BSD/OS:*:* | *:Ascend\ Embedded/OS:*:*)
@@ -879,7 +903,7 @@ EOF
exit ;;
*:GNU/*:*:*)
# other systems with GNU libc and userland
- echo ${UNAME_MACHINE}-unknown-`echo ${UNAME_SYSTEM} | sed 's,^[^/]*/,,' | tr '[A-Z]' '[a-z]'``echo ${UNAME_RELEASE}|sed -e 's/[-(].*//'`-${LIBC}
+ echo ${UNAME_MACHINE}-unknown-`echo ${UNAME_SYSTEM} | sed 's,^[^/]*/,,' | tr "[:upper:]" "[:lower:]"``echo ${UNAME_RELEASE}|sed -e 's/[-(].*//'`-${LIBC}
exit ;;
i*86:Minix:*:*)
echo ${UNAME_MACHINE}-pc-minix
@@ -902,7 +926,7 @@ EOF
EV68*) UNAME_MACHINE=alphaev68 ;;
esac
objdump --private-headers /bin/sh | grep -q ld.so.1
- if test "$?" = 0 ; then LIBC="gnulibc1" ; fi
+ if test "$?" = 0 ; then LIBC=gnulibc1 ; fi
echo ${UNAME_MACHINE}-unknown-linux-${LIBC}
exit ;;
arc:Linux:*:* | arceb:Linux:*:*)
@@ -933,6 +957,9 @@ EOF
crisv32:Linux:*:*)
echo ${UNAME_MACHINE}-axis-linux-${LIBC}
exit ;;
+ e2k:Linux:*:*)
+ echo ${UNAME_MACHINE}-unknown-linux-${LIBC}
+ exit ;;
frv:Linux:*:*)
echo ${UNAME_MACHINE}-unknown-linux-${LIBC}
exit ;;
@@ -945,6 +972,9 @@ EOF
ia64:Linux:*:*)
echo ${UNAME_MACHINE}-unknown-linux-${LIBC}
exit ;;
+ k1om:Linux:*:*)
+ echo ${UNAME_MACHINE}-unknown-linux-${LIBC}
+ exit ;;
m32r*:Linux:*:*)
echo ${UNAME_MACHINE}-unknown-linux-${LIBC}
exit ;;
@@ -1021,7 +1051,7 @@ EOF
echo ${UNAME_MACHINE}-dec-linux-${LIBC}
exit ;;
x86_64:Linux:*:*)
- echo ${UNAME_MACHINE}-unknown-linux-${LIBC}
+ echo ${UNAME_MACHINE}-pc-linux-${LIBC}
exit ;;
xtensa*:Linux:*:*)
echo ${UNAME_MACHINE}-unknown-linux-${LIBC}
@@ -1100,7 +1130,7 @@ EOF
# uname -m prints for DJGPP always 'pc', but it prints nothing about
# the processor, so we play safe by assuming i586.
# Note: whatever this is, it MUST be the same as what config.sub
- # prints for the "djgpp" host, or else GDB configury will decide that
+ # prints for the "djgpp" host, or else GDB configure will decide that
# this is a cross-build.
echo i586-pc-msdosdjgpp
exit ;;
@@ -1249,6 +1279,9 @@ EOF
SX-8R:SUPER-UX:*:*)
echo sx8r-nec-superux${UNAME_RELEASE}
exit ;;
+ SX-ACE:SUPER-UX:*:*)
+ echo sxace-nec-superux${UNAME_RELEASE}
+ exit ;;
Power*:Rhapsody:*:*)
echo powerpc-apple-rhapsody${UNAME_RELEASE}
exit ;;
@@ -1262,9 +1295,9 @@ EOF
UNAME_PROCESSOR=powerpc
fi
if test `echo "$UNAME_RELEASE" | sed -e 's/\..*//'` -le 10 ; then
- if [ "$CC_FOR_BUILD" != 'no_compiler_found' ]; then
+ if [ "$CC_FOR_BUILD" != no_compiler_found ]; then
if (echo '#ifdef __LP64__'; echo IS_64BIT_ARCH; echo '#endif') | \
- (CCOPTS= $CC_FOR_BUILD -E - 2>/dev/null) | \
+ (CCOPTS="" $CC_FOR_BUILD -E - 2>/dev/null) | \
grep IS_64BIT_ARCH >/dev/null
then
case $UNAME_PROCESSOR in
@@ -1286,7 +1319,7 @@ EOF
exit ;;
*:procnto*:*:* | *:QNX:[0123456789]*:*)
UNAME_PROCESSOR=`uname -p`
- if test "$UNAME_PROCESSOR" = "x86"; then
+ if test "$UNAME_PROCESSOR" = x86; then
UNAME_PROCESSOR=i386
UNAME_MACHINE=pc
fi
@@ -1317,7 +1350,7 @@ EOF
# "uname -m" is not consistent, so use $cputype instead. 386
# is converted to i386 for consistency with other x86
# operating systems.
- if test "$cputype" = "386"; then
+ if test "$cputype" = 386; then
UNAME_MACHINE=i386
else
UNAME_MACHINE="$cputype"
@@ -1359,7 +1392,7 @@ EOF
echo i386-pc-xenix
exit ;;
i*86:skyos:*:*)
- echo ${UNAME_MACHINE}-pc-skyos`echo ${UNAME_RELEASE}` | sed -e 's/ .*$//'
+ echo ${UNAME_MACHINE}-pc-skyos`echo ${UNAME_RELEASE} | sed -e 's/ .*$//'`
exit ;;
i*86:rdos:*:*)
echo ${UNAME_MACHINE}-pc-rdos
@@ -1370,23 +1403,25 @@ EOF
x86_64:VMkernel:*:*)
echo ${UNAME_MACHINE}-unknown-esx
exit ;;
+ amd64:Isilon\ OneFS:*:*)
+ echo x86_64-unknown-onefs
+ exit ;;
esac
cat >&2 <<EOF
$0: unable to guess system type
-This script, last modified $timestamp, has failed to recognize
-the operating system you are using. It is advised that you
-download the most up to date version of the config scripts from
+This script (version $timestamp), has failed to recognize the
+operating system you are using. If your script is old, overwrite
+config.guess and config.sub with the latest versions from:
- http://git.savannah.gnu.org/gitweb/?p=config.git;a=blob_plain;f=config.guess;hb=HEAD
+ http://git.savannah.gnu.org/gitweb/?p=config.git;a=blob_plain;f=config.guess
and
- http://git.savannah.gnu.org/gitweb/?p=config.git;a=blob_plain;f=config.sub;hb=HEAD
+ http://git.savannah.gnu.org/gitweb/?p=config.git;a=blob_plain;f=config.sub
-If the version you run ($0) is already up to date, please
-send the following data and any information you think might be
-pertinent to <config-patches@gnu.org> in order to provide the needed
-information to handle your system.
+If $0 has already been updated, send the following data and any
+information you think might be pertinent to config-patches@gnu.org to
+provide the necessary information to handle your system.
config.guess timestamp = $timestamp
diff --git a/build-aux/config.sub b/build-aux/config.sub
index 6d2e94c..9feb73b 100755
--- a/build-aux/config.sub
+++ b/build-aux/config.sub
@@ -1,8 +1,8 @@
#! /bin/sh
# Configuration validation subroutine script.
-# Copyright 1992-2015 Free Software Foundation, Inc.
+# Copyright 1992-2016 Free Software Foundation, Inc.
-timestamp='2015-01-01'
+timestamp='2016-06-20'
# This file is free software; you can redistribute it and/or modify it
# under the terms of the GNU General Public License as published by
@@ -33,7 +33,7 @@ timestamp='2015-01-01'
# Otherwise, we print the canonical config type on stdout and succeed.
# You can get the latest version of this script from:
-# http://git.savannah.gnu.org/gitweb/?p=config.git;a=blob_plain;f=config.sub;hb=HEAD
+# http://git.savannah.gnu.org/gitweb/?p=config.git;a=blob_plain;f=config.sub
# This file is supposed to be the same for all GNU packages
# and recognize all the CPU types, system types and aliases
@@ -53,8 +53,7 @@ timestamp='2015-01-01'
me=`echo "$0" | sed -e 's,.*/,,'`
usage="\
-Usage: $0 [OPTION] CPU-MFR-OPSYS
- $0 [OPTION] ALIAS
+Usage: $0 [OPTION] CPU-MFR-OPSYS or ALIAS
Canonicalize a configuration name.
@@ -68,7 +67,7 @@ Report bugs and patches to <config-patches@gnu.org>."
version="\
GNU config.sub ($timestamp)
-Copyright 1992-2015 Free Software Foundation, Inc.
+Copyright 1992-2016 Free Software Foundation, Inc.
This is free software; see the source for copying conditions. There is NO
warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE."
@@ -117,7 +116,7 @@ maybe_os=`echo $1 | sed 's/^\(.*\)-\([^-]*-[^-]*\)$/\2/'`
case $maybe_os in
nto-qnx* | linux-gnu* | linux-android* | linux-dietlibc | linux-newlib* | \
linux-musl* | linux-uclibc* | uclinux-uclibc* | uclinux-gnu* | kfreebsd*-gnu* | \
- knetbsd*-gnu* | netbsd*-gnu* | \
+ knetbsd*-gnu* | netbsd*-gnu* | netbsd*-eabi* | \
kopensolaris*-gnu* | \
storm-chaos* | os2-emx* | rtmk-nova*)
os=-$maybe_os
@@ -255,11 +254,12 @@ case $basic_machine in
| arc | arceb \
| arm | arm[bl]e | arme[lb] | armv[2-8] | armv[3-8][lb] | armv7[arm] \
| avr | avr32 \
+ | ba \
| be32 | be64 \
| bfin \
| c4x | c8051 | clipper \
| d10v | d30v | dlx | dsp16xx \
- | epiphany \
+ | e2k | epiphany \
| fido | fr30 | frv | ft32 \
| h8300 | h8500 | hppa | hppa1.[01] | hppa2.0 | hppa2.0[nw] | hppa64 \
| hexagon \
@@ -305,7 +305,7 @@ case $basic_machine in
| riscv32 | riscv64 \
| rl78 | rx \
| score \
- | sh | sh[1234] | sh[24]a | sh[24]aeb | sh[23]e | sh[34]eb | sheb | shbe | shle | sh[1234]le | sh3ele \
+ | sh | sh[1234] | sh[24]a | sh[24]aeb | sh[23]e | sh[234]eb | sheb | shbe | shle | sh[1234]le | sh3ele \
| sh64 | sh64le \
| sparc | sparc64 | sparc64b | sparc64v | sparc86x | sparclet | sparclite \
| sparcv8 | sparcv9 | sparcv9b | sparcv9v \
@@ -376,12 +376,13 @@ case $basic_machine in
| alphapca5[67]-* | alpha64pca5[67]-* | arc-* | arceb-* \
| arm-* | armbe-* | armle-* | armeb-* | armv*-* \
| avr-* | avr32-* \
+ | ba-* \
| be32-* | be64-* \
| bfin-* | bs2000-* \
| c[123]* | c30-* | [cjt]90-* | c4x-* \
| c8051-* | clipper-* | craynv-* | cydra-* \
| d10v-* | d30v-* | dlx-* \
- | elxsi-* \
+ | e2k-* | elxsi-* \
| f30[01]-* | f700-* | fido-* | fr30-* | frv-* | fx80-* \
| h8300-* | h8500-* \
| hppa-* | hppa1.[01]-* | hppa2.0-* | hppa2.0[nw]-* | hppa64-* \
@@ -428,12 +429,13 @@ case $basic_machine in
| pdp10-* | pdp11-* | pj-* | pjl-* | pn-* | power-* \
| powerpc-* | powerpc64-* | powerpc64le-* | powerpcle-* \
| pyramid-* \
+ | riscv32-* | riscv64-* \
| rl78-* | romp-* | rs6000-* | rx-* \
| sh-* | sh[1234]-* | sh[24]a-* | sh[24]aeb-* | sh[23]e-* | sh[34]eb-* | sheb-* | shbe-* \
| shle-* | sh[1234]le-* | sh3ele-* | sh64-* | sh64le-* \
| sparc-* | sparc64-* | sparc64b-* | sparc64v-* | sparc86x-* | sparclet-* \
| sparclite-* \
- | sparcv8-* | sparcv9-* | sparcv9b-* | sparcv9v-* | sv1-* | sx?-* \
+ | sparcv8-* | sparcv9-* | sparcv9b-* | sparcv9v-* | sv1-* | sx*-* \
| tahoe-* \
| tic30-* | tic4x-* | tic54x-* | tic55x-* | tic6x-* | tic80-* \
| tile*-* \
@@ -518,6 +520,9 @@ case $basic_machine in
basic_machine=i386-pc
os=-aros
;;
+ asmjs)
+ basic_machine=asmjs-unknown
+ ;;
aux)
basic_machine=m68k-apple
os=-aux
@@ -638,6 +643,14 @@ case $basic_machine in
basic_machine=m68k-bull
os=-sysv3
;;
+ e500v[12])
+ basic_machine=powerpc-unknown
+ os=$os"spe"
+ ;;
+ e500v[12]-*)
+ basic_machine=powerpc-`echo $basic_machine | sed 's/^[^-]*-//'`
+ os=$os"spe"
+ ;;
ebmon29k)
basic_machine=a29k-amd
os=-ebmon
@@ -1373,18 +1386,18 @@ case $os in
| -hpux* | -unos* | -osf* | -luna* | -dgux* | -auroraux* | -solaris* \
| -sym* | -kopensolaris* | -plan9* \
| -amigaos* | -amigados* | -msdos* | -newsos* | -unicos* | -aof* \
- | -aos* | -aros* \
+ | -aos* | -aros* | -cloudabi* | -sortix* \
| -nindy* | -vxsim* | -vxworks* | -ebmon* | -hms* | -mvs* \
| -clix* | -riscos* | -uniplus* | -iris* | -rtu* | -xenix* \
| -hiux* | -386bsd* | -knetbsd* | -mirbsd* | -netbsd* \
- | -bitrig* | -openbsd* | -solidbsd* \
+ | -bitrig* | -openbsd* | -solidbsd* | -libertybsd* \
| -ekkobsd* | -kfreebsd* | -freebsd* | -riscix* | -lynxos* \
| -bosx* | -nextstep* | -cxux* | -aout* | -elf* | -oabi* \
| -ptx* | -coff* | -ecoff* | -winnt* | -domain* | -vsta* \
| -udi* | -eabi* | -lites* | -ieee* | -go32* | -aux* \
| -chorusos* | -chorusrdb* | -cegcc* \
| -cygwin* | -msys* | -pe* | -psos* | -moss* | -proelf* | -rtems* \
- | -mingw32* | -mingw64* | -linux-gnu* | -linux-android* \
+ | -midipix* | -mingw32* | -mingw64* | -linux-gnu* | -linux-android* \
| -linux-newlib* | -linux-musl* | -linux-uclibc* \
| -uxpv* | -beos* | -mpeix* | -udk* | -moxiebox* \
| -interix* | -uwin* | -mks* | -rhapsody* | -darwin* | -opened* \
@@ -1393,7 +1406,8 @@ case $os in
| -os2* | -vos* | -palmos* | -uclinux* | -nucleus* \
| -morphos* | -superux* | -rtmk* | -rtmk-nova* | -windiss* \
| -powermax* | -dnix* | -nx6 | -nx7 | -sei* | -dragonfly* \
- | -skyos* | -haiku* | -rdos* | -toppers* | -drops* | -es* | -tirtos*)
+ | -skyos* | -haiku* | -rdos* | -toppers* | -drops* | -es* \
+ | -onefs* | -tirtos* | -phoenix*)
# Remember, each alternative MUST END IN *, to match a version number.
;;
-qnx*)
@@ -1525,6 +1539,8 @@ case $os in
;;
-nacl*)
;;
+ -ios)
+ ;;
-none)
;;
*)
diff --git a/config.h.in b/config.h.in
index 2bbae90..505fe26 100644
--- a/config.h.in
+++ b/config.h.in
@@ -27,6 +27,9 @@
/* Define if ttyname_r is does not work with small buffers */
#undef HAVE_BROKEN_TTYNAME_R
+/* define if the compiler supports basic C++11 syntax */
+#undef HAVE_CXX11
+
/* Define to 1 if you have the declaration of `ttyname_r', and to 0 if you
don't. */
#undef HAVE_DECL_TTYNAME_R
@@ -74,6 +77,9 @@
/* Define if we have pthread. */
#undef HAVE_PTHREAD
+/* If available, contains the Python version number currently in use. */
+#undef HAVE_PYTHON
+
/* Define to 1 if you have the `setenv' function. */
#undef HAVE_SETENV
@@ -281,5 +287,5 @@
#define GPG_ERR_ENABLE_ERRNO_MACROS 1
#define CRIGHTBLURB "Copyright (C) 2000 Werner Koch\n" \
- "Copyright (C) 2001--2015 g10 Code GmbH\n"
+ "Copyright (C) 2001--2016 g10 Code GmbH\n"
diff --git a/configure b/configure
index cf0c337..bcfe006 100755
--- a/configure
+++ b/configure
@@ -1,6 +1,6 @@
#! /bin/sh
# Guess values for system-dependent variables and create Makefiles.
-# Generated by GNU Autoconf 2.69 for gpgme 1.6.0.
+# Generated by GNU Autoconf 2.69 for gpgme 1.7.0.
#
# Report bugs to <http://bugs.gnupg.org>.
#
@@ -590,8 +590,8 @@ MAKEFLAGS=
# Identity of this package.
PACKAGE_NAME='gpgme'
PACKAGE_TARNAME='gpgme'
-PACKAGE_VERSION='1.6.0'
-PACKAGE_STRING='gpgme 1.6.0'
+PACKAGE_VERSION='1.7.0'
+PACKAGE_STRING='gpgme 1.7.0'
PACKAGE_BUGREPORT='http://bugs.gnupg.org'
PACKAGE_URL=''
@@ -639,6 +639,7 @@ emacs_local_vars_end
emacs_local_vars_read_only
emacs_local_vars_begin
LTLIBOBJS
+GPGME_CONFIG_AVAIL_LANG
GPGME_CONFIG_HOST
GPGME_CONFIG_CFLAGS
GPGME_CONFIG_LIBS
@@ -672,10 +673,40 @@ RUN_GPGCONF_TESTS_TRUE
BUILD_TIMESTAMP
BUILD_FILEVERSION
BUILD_REVISION
+ENABLED_LANGUAGES
+PYTHON_VERSIONS
+PYTHONS
+PYTHON_EXTRA_LDFLAGS
+PYTHON_EXTRA_LIBS
+PYTHON_SITE_PKG
+PYTHON_LDFLAGS
+PYTHON_CPPFLAGS
+pkgpyexecdir
+pyexecdir
+pkgpythondir
+pythondir
+PYTHON_PLATFORM
+PYTHON_EXEC_PREFIX
+PYTHON_PREFIX
+PYTHON_VERSION
+PYTHON
+SWIG_LIB
+SWIG
+HAVE_DOT
+HAVE_DOXYGEN_FALSE
+HAVE_DOXYGEN_TRUE
+GRAPHVIZ
+DOXYGEN
+QTCHOOSER
+MOC2
+MOC
+GPGME_QTTEST_LIBS
+GPGME_QTTEST_CFLAGS
+GPGME_QT_LIBS
+GPGME_QT_CFLAGS
+HAVE_CXX11
HAVE_PTHREAD_FALSE
HAVE_PTHREAD_TRUE
-BUILD_W32_QT_FALSE
-BUILD_W32_QT_TRUE
BUILD_W32_GLIB_FALSE
BUILD_W32_GLIB_TRUE
HAVE_ANDROID_SYSTEM_FALSE
@@ -688,8 +719,6 @@ HAVE_W32_SYSTEM_FALSE
HAVE_W32_SYSTEM_TRUE
HAVE_DOSISH_SYSTEM_FALSE
HAVE_DOSISH_SYSTEM_TRUE
-QT4_CORE_LIBS
-QT4_CORE_CFLAGS
GLIB_MKENUMS
GOBJECT_QUERY
GLIB_GENMARSHAL
@@ -720,7 +749,14 @@ LIBTOOL
OBJDUMP
DLLTOOL
AS
+CC_FOR_BUILD
VERSION_NUMBER
+LIBQGPGME_LT_REVISION
+LIBQGPGME_LT_AGE
+LIBQGPGME_LT_CURRENT
+LIBGPGMEPP_LT_REVISION
+LIBGPGMEPP_LT_AGE
+LIBGPGMEPP_LT_CURRENT
LIBGPGME_LT_REVISION
LIBGPGME_LT_AGE
LIBGPGME_LT_CURRENT
@@ -843,8 +879,8 @@ with_sysroot
enable_libtool_lock
enable_glibtest
enable_w32_glib
-enable_w32_qt
enable_fixed_path
+enable_languages
enable_build_timestamp
enable_gpgconf_test
enable_gpg_test
@@ -869,7 +905,15 @@ CPP
CXX
CXXFLAGS
CCC
-CXXCPP'
+CC_FOR_BUILD
+CXXCPP
+PKG_CONFIG
+GPGME_QT_CFLAGS
+GPGME_QT_LIBS
+GPGME_QTTEST_CFLAGS
+GPGME_QTTEST_LIBS
+PYTHON
+PYTHON_VERSION'
# Initialize some variables set by options.
@@ -1410,7 +1454,7 @@ if test "$ac_init_help" = "long"; then
# Omit some internal or obsolete options to make the list less imposing.
# This message is too long to be a string in the A/UX 3.1 sh.
cat <<_ACEOF
-\`configure' configures gpgme 1.6.0 to adapt to many kinds of systems.
+\`configure' configures gpgme 1.7.0 to adapt to many kinds of systems.
Usage: $0 [OPTION]... [VAR=VALUE]...
@@ -1480,7 +1524,7 @@ fi
if test -n "$ac_init_help"; then
case $ac_init_help in
- short | recursive ) echo "Configuration of gpgme 1.6.0:";;
+ short | recursive ) echo "Configuration of gpgme 1.7.0:";;
esac
cat <<\_ACEOF
@@ -1504,9 +1548,10 @@ Optional Features:
--disable-libtool-lock avoid locking (might break parallel builds)
--disable-glibtest do not try to compile and run a test GLIB program
--enable-w32-glib build GPGME Glib for W32
- --enable-w32-qt build GPGME Qt for W32
--enable-fixed-path=PATH
locate binaries only via this PATH
+ --enable-languages=languages
+ enable only specific language bindings
--enable-build-timestamp
set an explicit build timestamp for reproducibility.
(default is the current time in ISO-8601 format)
@@ -1543,7 +1588,23 @@ Some influential environment variables:
CPP C preprocessor
CXX C++ compiler command
CXXFLAGS C++ compiler flags
+ CC_FOR_BUILD
+ build system C compiler
CXXCPP C++ preprocessor
+ PKG_CONFIG path to pkg-config utility
+ GPGME_QT_CFLAGS
+ C compiler flags for GPGME_QT, overriding pkg-config
+ GPGME_QT_LIBS
+ linker flags for GPGME_QT, overriding pkg-config
+ GPGME_QTTEST_CFLAGS
+ C compiler flags for GPGME_QTTEST, overriding pkg-config
+ GPGME_QTTEST_LIBS
+ linker flags for GPGME_QTTEST, overriding pkg-config
+ PYTHON the Python interpreter
+ PYTHON_VERSION
+ The installed Python version to use, for example '2.3'. This
+ string will be appended to the Python interpreter canonical
+ name.
Use these variables to override the choices made by `configure' or to help
it to find libraries and programs with nonstandard names/locations.
@@ -1611,7 +1672,7 @@ fi
test -n "$ac_init_help" && exit $ac_status
if $ac_init_version; then
cat <<\_ACEOF
-gpgme configure 1.6.0
+gpgme configure 1.7.0
generated by GNU Autoconf 2.69
Copyright (C) 2012 Free Software Foundation, Inc.
@@ -2441,7 +2502,7 @@ cat >config.log <<_ACEOF
This file contains any messages produced by compilers while
running configure, to aid debugging if configure makes a mistake.
-It was created by gpgme $as_me 1.6.0, which was
+It was created by gpgme $as_me 1.7.0, which was
generated by GNU Autoconf 2.69. Invocation command line was
$ $0 $@
@@ -2804,12 +2865,20 @@ ac_compiler_gnu=$ac_cv_c_compiler_gnu
# (Interfaces added: AGE++)
# (Interfaces removed/changed: AGE=0)
#
-LIBGPGME_LT_CURRENT=25
+LIBGPGME_LT_CURRENT=26
# Subtract 2 from this value if you want to make the LFS transition an
# ABI break. [Note to self: Remove this comment with the next regular break.]
-LIBGPGME_LT_AGE=14
+LIBGPGME_LT_AGE=15
LIBGPGME_LT_REVISION=0
+LIBGPGMEPP_LT_CURRENT=6
+LIBGPGMEPP_LT_AGE=0
+LIBGPGMEPP_LT_REVISION=1
+
+LIBQGPGME_LT_CURRENT=6
+LIBQGPGME_LT_AGE=0
+LIBQGPGME_LT_REVISION=1
+
# If the API is changed in an incompatible way: increment the next counter.
GPGME_CONFIG_API_VERSION=1
##############################################
@@ -3341,7 +3410,7 @@ fi
# Define the identity of the package.
PACKAGE='gpgme'
- VERSION='1.6.0'
+ VERSION='1.7.0'
cat >>confdefs.h <<_ACEOF
@@ -6236,6 +6305,12 @@ test -n "$GITLOG_TO_CHANGELOG" || GITLOG_TO_CHANGELOG="gitlog-to-changelog"
+
+
+
+
+
+
cat >>confdefs.h <<_ACEOF
#define PACKAGE "$PACKAGE"
_ACEOF
@@ -6245,7 +6320,25 @@ cat >>confdefs.h <<_ACEOF
#define VERSION "$VERSION"
_ACEOF
-VERSION_NUMBER=0x010600
+VERSION_NUMBER=0x010700
+
+
+# We need to compile and run a program on the build machine. A
+# comment in libgpg-error says that the AC_PROG_CC_FOR_BUILD macro in
+# the AC archive is broken for autoconf 2.57. Given that there is no
+# newer version of that macro, we assume that it is also broken for
+# autoconf 2.61 and thus we use a simple but usually sufficient
+# approach.
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for cc for build" >&5
+$as_echo_n "checking for cc for build... " >&6; }
+if test "$cross_compiling" = "yes"; then
+ CC_FOR_BUILD="${CC_FOR_BUILD-cc}"
+else
+ CC_FOR_BUILD="${CC_FOR_BUILD-$CC}"
+fi
+{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $CC_FOR_BUILD" >&5
+$as_echo "$CC_FOR_BUILD" >&6; }
+
# Don't default to build static libs.
@@ -17099,6 +17192,8 @@ have_w32_system=no
have_w64_system=no
build_w32_glib=no
build_w32_qt=no
+available_languages="cl cpp python python2 python3 qt"
+default_languages="cl cpp python qt"
case "${host}" in
x86_64-*mingw32*)
have_w64_system=yes
@@ -17403,22 +17498,9 @@ if test "${enable_w32_glib+set}" = set; then :
enableval=$enable_w32_glib; build_w32_glib=$enableval
fi
-
- # Check disabled, because the qt-dev packages in gpg4win do
- # not provide any support for cross compilation.
- # PKG_CHECK_MODULES(QT4_CORE, QtCore)
-
- # Use it like this:
- # ./configure --enable-w32-qt QT4_CORE_CFLAGS="..." QT4_CORE_LIBS="..."
-
-
- # Check whether --enable-w32-qt was given.
-if test "${enable_w32_qt+set}" = set; then :
- enableval=$enable_w32_qt; build_w32_qt=$enableval
-fi
-
- ;;
+ ;;
*)
+
{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for pthread_create in -lpthread" >&5
$as_echo_n "checking for pthread_create in -lpthread... " >&6; }
if ${ac_cv_lib_pthread_pthread_create+:} false; then :
@@ -17551,14 +17633,6 @@ else
BUILD_W32_GLIB_FALSE=
fi
- if test "$build_w32_qt" = yes; then
- BUILD_W32_QT_TRUE=
- BUILD_W32_QT_FALSE='#'
-else
- BUILD_W32_QT_TRUE='#'
- BUILD_W32_QT_FALSE=
-fi
-
if test "$have_pthread" = "yes"; then
HAVE_PTHREAD_TRUE=
@@ -17586,10 +17660,2977 @@ _ACEOF
fi
+# Note: You need to declare all possible langauges also in
+# lang/Makefile.am's DIST_SUBDIRS.
+# Check whether --enable-languages was given.
+if test "${enable_languages+set}" = set; then :
+ enableval=$enable_languages; enabled_languages=`echo $enableval | \
+ tr ',:' ' ' | tr 'A-Z' 'a-z' | \
+ sed 's/c++/cpp/'`
+else
+ enabled_languages="maybe"
+fi
+
+if test "x$enabled_languages" = "x" \
+ -o "$enabled_languages" = "no"; then
+ enabled_languages=
+fi
+
+# If languages are explicitly set missing requirements
+# for the languages are treated as errors otherwise
+# there will be a warning.
+explicit_languages=1
+if test "x$enabled_languages" = "xmaybe"; then
+ explicit_languages=0
+ enabled_languages="$default_languages"
+fi
+
+for language in $enabled_languages; do
+
+name=$language
+list=$available_languages
+found=0
+
+for n in $list; do
+ if test "x$name" = "x$n"; then
+ found=1
+ fi
+done
+
+ if test "$found" = "0"; then
+ as_fn_error $? "unsupported language binding specified" "$LINENO" 5
+ fi
+done
+
+
+
+# Enable C++ 11 if cpp language is requested
+
+name="cpp"
+list=$enabled_languages
+found=0
+
+for n in $list; do
+ if test "x$name" = "x$n"; then
+ found=1
+ fi
+done
+
+if test "$found" = "1"; then
+ ax_cxx_compile_cxx11_required=false
+ ac_ext=cpp
+ac_cpp='$CXXCPP $CPPFLAGS'
+ac_compile='$CXX -c $CXXFLAGS $CPPFLAGS conftest.$ac_ext >&5'
+ac_link='$CXX -o conftest$ac_exeext $CXXFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5'
+ac_compiler_gnu=$ac_cv_cxx_compiler_gnu
+ ac_success=no
+ { $as_echo "$as_me:${as_lineno-$LINENO}: checking whether $CXX supports C++11 features by default" >&5
+$as_echo_n "checking whether $CXX supports C++11 features by default... " >&6; }
+if ${ax_cv_cxx_compile_cxx11+:} false; then :
+ $as_echo_n "(cached) " >&6
+else
+ cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h. */
+
+
+// If the compiler admits that it is not ready for C++11, why torture it?
+// Hopefully, this will speed up the test.
+
+#ifndef __cplusplus
+
+#error "This is not a C++ compiler"
+
+#elif __cplusplus < 201103L
+
+#error "This is not a C++11 compiler"
+
+#else
+
+namespace cxx11
+{
+
+ namespace test_static_assert
+ {
+
+ template <typename T>
+ struct check
+ {
+ static_assert(sizeof(int) <= sizeof(T), "not big enough");
+ };
+
+ }
+
+ namespace test_final_override
+ {
+
+ struct Base
+ {
+ virtual void f() {}
+ };
+
+ struct Derived : public Base
+ {
+ virtual void f() override {}
+ };
+
+ }
+
+ namespace test_double_right_angle_brackets
+ {
+
+ template < typename T >
+ struct check {};
+
+ typedef check<void> single_type;
+ typedef check<check<void>> double_type;
+ typedef check<check<check<void>>> triple_type;
+ typedef check<check<check<check<void>>>> quadruple_type;
+
+ }
+
+ namespace test_decltype
+ {
+
+ int
+ f()
+ {
+ int a = 1;
+ decltype(a) b = 2;
+ return a + b;
+ }
+
+ }
+
+ namespace test_type_deduction
+ {
+
+ template < typename T1, typename T2 >
+ struct is_same
+ {
+ static const bool value = false;
+ };
+
+ template < typename T >
+ struct is_same<T, T>
+ {
+ static const bool value = true;
+ };
+
+ template < typename T1, typename T2 >
+ auto
+ add(T1 a1, T2 a2) -> decltype(a1 + a2)
+ {
+ return a1 + a2;
+ }
+
+ int
+ test(const int c, volatile int v)
+ {
+ static_assert(is_same<int, decltype(0)>::value == true, "");
+ static_assert(is_same<int, decltype(c)>::value == false, "");
+ static_assert(is_same<int, decltype(v)>::value == false, "");
+ auto ac = c;
+ auto av = v;
+ auto sumi = ac + av + 'x';
+ auto sumf = ac + av + 1.0;
+ static_assert(is_same<int, decltype(ac)>::value == true, "");
+ static_assert(is_same<int, decltype(av)>::value == true, "");
+ static_assert(is_same<int, decltype(sumi)>::value == true, "");
+ static_assert(is_same<int, decltype(sumf)>::value == false, "");
+ static_assert(is_same<int, decltype(add(c, v))>::value == true, "");
+ return (sumf > 0.0) ? sumi : add(c, v);
+ }
+
+ }
+
+ namespace test_noexcept
+ {
+
+ int f() { return 0; }
+ int g() noexcept { return 0; }
+
+ static_assert(noexcept(f()) == false, "");
+ static_assert(noexcept(g()) == true, "");
+
+ }
+
+ namespace test_constexpr
+ {
+
+ template < typename CharT >
+ unsigned long constexpr
+ strlen_c_r(const CharT *const s, const unsigned long acc) noexcept
+ {
+ return *s ? strlen_c_r(s + 1, acc + 1) : acc;
+ }
+
+ template < typename CharT >
+ unsigned long constexpr
+ strlen_c(const CharT *const s) noexcept
+ {
+ return strlen_c_r(s, 0UL);
+ }
+
+ static_assert(strlen_c("") == 0UL, "");
+ static_assert(strlen_c("1") == 1UL, "");
+ static_assert(strlen_c("example") == 7UL, "");
+ static_assert(strlen_c("another\0example") == 7UL, "");
+
+ }
+
+ namespace test_rvalue_references
+ {
+
+ template < int N >
+ struct answer
+ {
+ static constexpr int value = N;
+ };
+
+ answer<1> f(int&) { return answer<1>(); }
+ answer<2> f(const int&) { return answer<2>(); }
+ answer<3> f(int&&) { return answer<3>(); }
+
+ void
+ test()
+ {
+ int i = 0;
+ const int c = 0;
+ static_assert(decltype(f(i))::value == 1, "");
+ static_assert(decltype(f(c))::value == 2, "");
+ static_assert(decltype(f(0))::value == 3, "");
+ }
+
+ }
+
+ namespace test_uniform_initialization
+ {
+
+ struct test
+ {
+ static const int zero {};
+ static const int one {1};
+ };
+
+ static_assert(test::zero == 0, "");
+ static_assert(test::one == 1, "");
+
+ }
+
+ namespace test_lambdas
+ {
+
+ void
+ test1()
+ {
+ auto lambda1 = [](){};
+ auto lambda2 = lambda1;
+ lambda1();
+ lambda2();
+ }
+
+ int
+ test2()
+ {
+ auto a = [](int i, int j){ return i + j; }(1, 2);
+ auto b = []() -> int { return '0'; }();
+ auto c = [=](){ return a + b; }();
+ auto d = [&](){ return c; }();
+ auto e = [a, &b](int x) mutable {
+ const auto identity = [](int y){ return y; };
+ for (auto i = 0; i < a; ++i)
+ a += b--;
+ return x + identity(a + b);
+ }(0);
+ return a + b + c + d + e;
+ }
+
+ int
+ test3()
+ {
+ const auto nullary = [](){ return 0; };
+ const auto unary = [](int x){ return x; };
+ using nullary_t = decltype(nullary);
+ using unary_t = decltype(unary);
+ const auto higher1st = [](nullary_t f){ return f(); };
+ const auto higher2nd = [unary](nullary_t f1){
+ return [unary, f1](unary_t f2){ return f2(unary(f1())); };
+ };
+ return higher1st(nullary) + higher2nd(nullary)(unary);
+ }
+
+ }
+
+ namespace test_variadic_templates
+ {
+
+ template <int...>
+ struct sum;
+
+ template <int N0, int... N1toN>
+ struct sum<N0, N1toN...>
+ {
+ static constexpr auto value = N0 + sum<N1toN...>::value;
+ };
+
+ template <>
+ struct sum<>
+ {
+ static constexpr auto value = 0;
+ };
+
+ static_assert(sum<>::value == 0, "");
+ static_assert(sum<1>::value == 1, "");
+ static_assert(sum<23>::value == 23, "");
+ static_assert(sum<1, 2>::value == 3, "");
+ static_assert(sum<5, 5, 11>::value == 21, "");
+ static_assert(sum<2, 3, 5, 7, 11, 13>::value == 41, "");
+
+ }
+
+ // http://stackoverflow.com/questions/13728184/template-aliases-and-sfinae
+ // Clang 3.1 fails with headers of libstd++ 4.8.3 when using std::function
+ // because of this.
+ namespace test_template_alias_sfinae
+ {
+
+ struct foo {};
+
+ template<typename T>
+ using member = typename T::member_type;
+
+ template<typename T>
+ void func(...) {}
+
+ template<typename T>
+ void func(member<T>*) {}
+
+ void test();
+
+ void test() { func<foo>(0); }
+
+ }
+
+} // namespace cxx11
+
+#endif // __cplusplus >= 201103L
+
+
+
+_ACEOF
+if ac_fn_cxx_try_compile "$LINENO"; then :
+ ax_cv_cxx_compile_cxx11=yes
+else
+ ax_cv_cxx_compile_cxx11=no
+fi
+rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
+fi
+{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ax_cv_cxx_compile_cxx11" >&5
+$as_echo "$ax_cv_cxx_compile_cxx11" >&6; }
+ if test x$ax_cv_cxx_compile_cxx11 = xyes; then
+ ac_success=yes
+ fi
+
+
+
+ if test x$ac_success = xno; then
+ for switch in -std=c++11 -std=c++0x +std=c++11 "-h std=c++11"; do
+ cachevar=`$as_echo "ax_cv_cxx_compile_cxx11_$switch" | $as_tr_sh`
+ { $as_echo "$as_me:${as_lineno-$LINENO}: checking whether $CXX supports C++11 features with $switch" >&5
+$as_echo_n "checking whether $CXX supports C++11 features with $switch... " >&6; }
+if eval \${$cachevar+:} false; then :
+ $as_echo_n "(cached) " >&6
+else
+ ac_save_CXX="$CXX"
+ CXX="$CXX $switch"
+ cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h. */
+
+
+// If the compiler admits that it is not ready for C++11, why torture it?
+// Hopefully, this will speed up the test.
+
+#ifndef __cplusplus
+
+#error "This is not a C++ compiler"
+
+#elif __cplusplus < 201103L
+
+#error "This is not a C++11 compiler"
+
+#else
+
+namespace cxx11
+{
+
+ namespace test_static_assert
+ {
+
+ template <typename T>
+ struct check
+ {
+ static_assert(sizeof(int) <= sizeof(T), "not big enough");
+ };
+
+ }
+
+ namespace test_final_override
+ {
+
+ struct Base
+ {
+ virtual void f() {}
+ };
+
+ struct Derived : public Base
+ {
+ virtual void f() override {}
+ };
+
+ }
+
+ namespace test_double_right_angle_brackets
+ {
+
+ template < typename T >
+ struct check {};
+
+ typedef check<void> single_type;
+ typedef check<check<void>> double_type;
+ typedef check<check<check<void>>> triple_type;
+ typedef check<check<check<check<void>>>> quadruple_type;
+
+ }
+
+ namespace test_decltype
+ {
+
+ int
+ f()
+ {
+ int a = 1;
+ decltype(a) b = 2;
+ return a + b;
+ }
+
+ }
+
+ namespace test_type_deduction
+ {
+
+ template < typename T1, typename T2 >
+ struct is_same
+ {
+ static const bool value = false;
+ };
+
+ template < typename T >
+ struct is_same<T, T>
+ {
+ static const bool value = true;
+ };
+
+ template < typename T1, typename T2 >
+ auto
+ add(T1 a1, T2 a2) -> decltype(a1 + a2)
+ {
+ return a1 + a2;
+ }
+
+ int
+ test(const int c, volatile int v)
+ {
+ static_assert(is_same<int, decltype(0)>::value == true, "");
+ static_assert(is_same<int, decltype(c)>::value == false, "");
+ static_assert(is_same<int, decltype(v)>::value == false, "");
+ auto ac = c;
+ auto av = v;
+ auto sumi = ac + av + 'x';
+ auto sumf = ac + av + 1.0;
+ static_assert(is_same<int, decltype(ac)>::value == true, "");
+ static_assert(is_same<int, decltype(av)>::value == true, "");
+ static_assert(is_same<int, decltype(sumi)>::value == true, "");
+ static_assert(is_same<int, decltype(sumf)>::value == false, "");
+ static_assert(is_same<int, decltype(add(c, v))>::value == true, "");
+ return (sumf > 0.0) ? sumi : add(c, v);
+ }
+
+ }
+
+ namespace test_noexcept
+ {
+
+ int f() { return 0; }
+ int g() noexcept { return 0; }
+
+ static_assert(noexcept(f()) == false, "");
+ static_assert(noexcept(g()) == true, "");
+
+ }
+
+ namespace test_constexpr
+ {
+
+ template < typename CharT >
+ unsigned long constexpr
+ strlen_c_r(const CharT *const s, const unsigned long acc) noexcept
+ {
+ return *s ? strlen_c_r(s + 1, acc + 1) : acc;
+ }
+
+ template < typename CharT >
+ unsigned long constexpr
+ strlen_c(const CharT *const s) noexcept
+ {
+ return strlen_c_r(s, 0UL);
+ }
+
+ static_assert(strlen_c("") == 0UL, "");
+ static_assert(strlen_c("1") == 1UL, "");
+ static_assert(strlen_c("example") == 7UL, "");
+ static_assert(strlen_c("another\0example") == 7UL, "");
+
+ }
+
+ namespace test_rvalue_references
+ {
+
+ template < int N >
+ struct answer
+ {
+ static constexpr int value = N;
+ };
+
+ answer<1> f(int&) { return answer<1>(); }
+ answer<2> f(const int&) { return answer<2>(); }
+ answer<3> f(int&&) { return answer<3>(); }
+
+ void
+ test()
+ {
+ int i = 0;
+ const int c = 0;
+ static_assert(decltype(f(i))::value == 1, "");
+ static_assert(decltype(f(c))::value == 2, "");
+ static_assert(decltype(f(0))::value == 3, "");
+ }
+
+ }
+
+ namespace test_uniform_initialization
+ {
+
+ struct test
+ {
+ static const int zero {};
+ static const int one {1};
+ };
+
+ static_assert(test::zero == 0, "");
+ static_assert(test::one == 1, "");
+
+ }
+
+ namespace test_lambdas
+ {
+
+ void
+ test1()
+ {
+ auto lambda1 = [](){};
+ auto lambda2 = lambda1;
+ lambda1();
+ lambda2();
+ }
+
+ int
+ test2()
+ {
+ auto a = [](int i, int j){ return i + j; }(1, 2);
+ auto b = []() -> int { return '0'; }();
+ auto c = [=](){ return a + b; }();
+ auto d = [&](){ return c; }();
+ auto e = [a, &b](int x) mutable {
+ const auto identity = [](int y){ return y; };
+ for (auto i = 0; i < a; ++i)
+ a += b--;
+ return x + identity(a + b);
+ }(0);
+ return a + b + c + d + e;
+ }
+
+ int
+ test3()
+ {
+ const auto nullary = [](){ return 0; };
+ const auto unary = [](int x){ return x; };
+ using nullary_t = decltype(nullary);
+ using unary_t = decltype(unary);
+ const auto higher1st = [](nullary_t f){ return f(); };
+ const auto higher2nd = [unary](nullary_t f1){
+ return [unary, f1](unary_t f2){ return f2(unary(f1())); };
+ };
+ return higher1st(nullary) + higher2nd(nullary)(unary);
+ }
+
+ }
+
+ namespace test_variadic_templates
+ {
+
+ template <int...>
+ struct sum;
+
+ template <int N0, int... N1toN>
+ struct sum<N0, N1toN...>
+ {
+ static constexpr auto value = N0 + sum<N1toN...>::value;
+ };
+
+ template <>
+ struct sum<>
+ {
+ static constexpr auto value = 0;
+ };
+
+ static_assert(sum<>::value == 0, "");
+ static_assert(sum<1>::value == 1, "");
+ static_assert(sum<23>::value == 23, "");
+ static_assert(sum<1, 2>::value == 3, "");
+ static_assert(sum<5, 5, 11>::value == 21, "");
+ static_assert(sum<2, 3, 5, 7, 11, 13>::value == 41, "");
+
+ }
+
+ // http://stackoverflow.com/questions/13728184/template-aliases-and-sfinae
+ // Clang 3.1 fails with headers of libstd++ 4.8.3 when using std::function
+ // because of this.
+ namespace test_template_alias_sfinae
+ {
+
+ struct foo {};
+
+ template<typename T>
+ using member = typename T::member_type;
+
+ template<typename T>
+ void func(...) {}
+
+ template<typename T>
+ void func(member<T>*) {}
+
+ void test();
+
+ void test() { func<foo>(0); }
+
+ }
+
+} // namespace cxx11
+
+#endif // __cplusplus >= 201103L
+
+
+
+_ACEOF
+if ac_fn_cxx_try_compile "$LINENO"; then :
+ eval $cachevar=yes
+else
+ eval $cachevar=no
+fi
+rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
+ CXX="$ac_save_CXX"
+fi
+eval ac_res=\$$cachevar
+ { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_res" >&5
+$as_echo "$ac_res" >&6; }
+ if eval test x\$$cachevar = xyes; then
+ CXX="$CXX $switch"
+ CXXCPP="$CXXCPP $switch"
+ ac_success=yes
+ break
+ fi
+ done
+ fi
+ ac_ext=c
+ac_cpp='$CPP $CPPFLAGS'
+ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5'
+ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5'
+ac_compiler_gnu=$ac_cv_c_compiler_gnu
+
+ if test x$ax_cxx_compile_cxx11_required = xtrue; then
+ if test x$ac_success = xno; then
+ as_fn_error $? "*** A compiler with support for C++11 language features is required." "$LINENO" 5
+ fi
+ fi
+ if test x$ac_success = xno; then
+ HAVE_CXX11=0
+ { $as_echo "$as_me:${as_lineno-$LINENO}: No compiler with C++11 support was found" >&5
+$as_echo "$as_me: No compiler with C++11 support was found" >&6;}
+ else
+ HAVE_CXX11=1
+
+$as_echo "#define HAVE_CXX11 1" >>confdefs.h
+
+ fi
+
+
+ if test "$HAVE_CXX11" != "1"; then
+ if test "$explicit_languages" = "1"; then
+ as_fn_error $? "
+***
+*** A compiler with c++11 support is required for the c++ binding.
+***" "$LINENO" 5
+ else
+ enabled_languages=$(echo $enabled_languages | sed 's/cpp//')
+ enabled_languages=$(echo $enabled_languages | sed 's/qt//')
+ { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING:
+***
+*** No c++11 support detected. C++ and Qt bindings will be disabled.
+***" >&5
+$as_echo "$as_me: WARNING:
+***
+*** No c++11 support detected. C++ and Qt bindings will be disabled.
+***" >&2;}
+ fi
+ fi
+fi
+
+# Check that if qt is enabled cpp also is enabled
+
+name="qt"
+list=$enabled_languages
+found=0
+
+for n in $list; do
+ if test "x$name" = "x$n"; then
+ found=1
+ fi
+done
+
+if test "$found" = "1"; then
+ # We need to ensure that in the langauge order qt comes after cpp
+ # so we remove qt first and explicitly add it as last list member.
+ enabled_languages=$(echo $enabled_languages | sed 's/qt//')
+
+name="cpp"
+list=$enabled_languages
+found=0
+
+for n in $list; do
+ if test "x$name" = "x$n"; then
+ found=1
+ fi
+done
+
+ if test "$found" = "0"; then
+ as_fn_error $? "
+***
+*** Qt language binding depends on cpp binding.
+***" "$LINENO" 5
+ fi
+
+
+if test "x$ac_cv_env_PKG_CONFIG_set" != "xset"; then
+ if test -n "$ac_tool_prefix"; then
+ # Extract the first word of "${ac_tool_prefix}pkg-config", so it can be a program name with args.
+set dummy ${ac_tool_prefix}pkg-config; ac_word=$2
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5
+$as_echo_n "checking for $ac_word... " >&6; }
+if ${ac_cv_path_PKG_CONFIG+:} false; then :
+ $as_echo_n "(cached) " >&6
+else
+ case $PKG_CONFIG in
+ [\\/]* | ?:[\\/]*)
+ ac_cv_path_PKG_CONFIG="$PKG_CONFIG" # Let the user override the test with a path.
+ ;;
+ *)
+ as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
+for as_dir in $PATH
+do
+ IFS=$as_save_IFS
+ test -z "$as_dir" && as_dir=.
+ for ac_exec_ext in '' $ac_executable_extensions; do
+ if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then
+ ac_cv_path_PKG_CONFIG="$as_dir/$ac_word$ac_exec_ext"
+ $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5
+ break 2
+ fi
+done
+ done
+IFS=$as_save_IFS
+
+ ;;
+esac
+fi
+PKG_CONFIG=$ac_cv_path_PKG_CONFIG
+if test -n "$PKG_CONFIG"; then
+ { $as_echo "$as_me:${as_lineno-$LINENO}: result: $PKG_CONFIG" >&5
+$as_echo "$PKG_CONFIG" >&6; }
+else
+ { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
+$as_echo "no" >&6; }
+fi
+
+
+fi
+if test -z "$ac_cv_path_PKG_CONFIG"; then
+ ac_pt_PKG_CONFIG=$PKG_CONFIG
+ # Extract the first word of "pkg-config", so it can be a program name with args.
+set dummy pkg-config; ac_word=$2
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5
+$as_echo_n "checking for $ac_word... " >&6; }
+if ${ac_cv_path_ac_pt_PKG_CONFIG+:} false; then :
+ $as_echo_n "(cached) " >&6
+else
+ case $ac_pt_PKG_CONFIG in
+ [\\/]* | ?:[\\/]*)
+ ac_cv_path_ac_pt_PKG_CONFIG="$ac_pt_PKG_CONFIG" # Let the user override the test with a path.
+ ;;
+ *)
+ as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
+for as_dir in $PATH
+do
+ IFS=$as_save_IFS
+ test -z "$as_dir" && as_dir=.
+ for ac_exec_ext in '' $ac_executable_extensions; do
+ if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then
+ ac_cv_path_ac_pt_PKG_CONFIG="$as_dir/$ac_word$ac_exec_ext"
+ $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5
+ break 2
+ fi
+done
+ done
+IFS=$as_save_IFS
+
+ ;;
+esac
+fi
+ac_pt_PKG_CONFIG=$ac_cv_path_ac_pt_PKG_CONFIG
+if test -n "$ac_pt_PKG_CONFIG"; then
+ { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_pt_PKG_CONFIG" >&5
+$as_echo "$ac_pt_PKG_CONFIG" >&6; }
+else
+ { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
+$as_echo "no" >&6; }
+fi
+
+ if test "x$ac_pt_PKG_CONFIG" = x; then
+ PKG_CONFIG=""
+ else
+ case $cross_compiling:$ac_tool_warned in
+yes:)
+{ $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: using cross tools not prefixed with host triplet" >&5
+$as_echo "$as_me: WARNING: using cross tools not prefixed with host triplet" >&2;}
+ac_tool_warned=yes ;;
+esac
+ PKG_CONFIG=$ac_pt_PKG_CONFIG
+ fi
+else
+ PKG_CONFIG="$ac_cv_path_PKG_CONFIG"
+fi
+
+fi
+if test -n "$PKG_CONFIG"; then
+ _pkg_min_version=0.9.0
+ { $as_echo "$as_me:${as_lineno-$LINENO}: checking pkg-config is at least version $_pkg_min_version" >&5
+$as_echo_n "checking pkg-config is at least version $_pkg_min_version... " >&6; }
+ if $PKG_CONFIG --atleast-pkgconfig-version $_pkg_min_version; then
+ { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5
+$as_echo "yes" >&6; }
+ else
+ { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
+$as_echo "no" >&6; }
+ PKG_CONFIG=""
+ fi
+
+fi
+
+ have_qt5_libs="no";
+
+
+pkg_failed=no
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for GPGME_QT" >&5
+$as_echo_n "checking for GPGME_QT... " >&6; }
+
+if test -n "$PKG_CONFIG"; then
+ if test -n "$GPGME_QT_CFLAGS"; then
+ pkg_cv_GPGME_QT_CFLAGS="$GPGME_QT_CFLAGS"
+ else
+ if test -n "$PKG_CONFIG" && \
+ { { $as_echo "$as_me:${as_lineno-$LINENO}: \$PKG_CONFIG --exists --print-errors \"Qt5Core >= 5.0.0\""; } >&5
+ ($PKG_CONFIG --exists --print-errors "Qt5Core >= 5.0.0") 2>&5
+ ac_status=$?
+ $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5
+ test $ac_status = 0; }; then
+ pkg_cv_GPGME_QT_CFLAGS=`$PKG_CONFIG --cflags "Qt5Core >= 5.0.0" 2>/dev/null`
+else
+ pkg_failed=yes
+fi
+ fi
+else
+ pkg_failed=untried
+fi
+if test -n "$PKG_CONFIG"; then
+ if test -n "$GPGME_QT_LIBS"; then
+ pkg_cv_GPGME_QT_LIBS="$GPGME_QT_LIBS"
+ else
+ if test -n "$PKG_CONFIG" && \
+ { { $as_echo "$as_me:${as_lineno-$LINENO}: \$PKG_CONFIG --exists --print-errors \"Qt5Core >= 5.0.0\""; } >&5
+ ($PKG_CONFIG --exists --print-errors "Qt5Core >= 5.0.0") 2>&5
+ ac_status=$?
+ $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5
+ test $ac_status = 0; }; then
+ pkg_cv_GPGME_QT_LIBS=`$PKG_CONFIG --libs "Qt5Core >= 5.0.0" 2>/dev/null`
+else
+ pkg_failed=yes
+fi
+ fi
+else
+ pkg_failed=untried
+fi
+
+
+
+if test $pkg_failed = yes; then
+
+if $PKG_CONFIG --atleast-pkgconfig-version 0.20; then
+ _pkg_short_errors_supported=yes
+else
+ _pkg_short_errors_supported=no
+fi
+ if test $_pkg_short_errors_supported = yes; then
+ GPGME_QT_PKG_ERRORS=`$PKG_CONFIG --short-errors --errors-to-stdout --print-errors "Qt5Core >= 5.0.0"`
+ else
+ GPGME_QT_PKG_ERRORS=`$PKG_CONFIG --errors-to-stdout --print-errors "Qt5Core >= 5.0.0"`
+ fi
+ # Put the nasty error message in config.log where it belongs
+ echo "$GPGME_QT_PKG_ERRORS" >&5
+
+ { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
+$as_echo "no" >&6; }
+ have_qt5_libs="no"
+elif test $pkg_failed = untried; then
+ have_qt5_libs="no"
+else
+ GPGME_QT_CFLAGS=$pkg_cv_GPGME_QT_CFLAGS
+ GPGME_QT_LIBS=$pkg_cv_GPGME_QT_LIBS
+ { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5
+$as_echo "yes" >&6; }
+ have_qt5_libs="yes"
+fi
+
+
+pkg_failed=no
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for GPGME_QTTEST" >&5
+$as_echo_n "checking for GPGME_QTTEST... " >&6; }
+
+if test -n "$PKG_CONFIG"; then
+ if test -n "$GPGME_QTTEST_CFLAGS"; then
+ pkg_cv_GPGME_QTTEST_CFLAGS="$GPGME_QTTEST_CFLAGS"
+ else
+ if test -n "$PKG_CONFIG" && \
+ { { $as_echo "$as_me:${as_lineno-$LINENO}: \$PKG_CONFIG --exists --print-errors \"Qt5Test >= 5.0.0\""; } >&5
+ ($PKG_CONFIG --exists --print-errors "Qt5Test >= 5.0.0") 2>&5
+ ac_status=$?
+ $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5
+ test $ac_status = 0; }; then
+ pkg_cv_GPGME_QTTEST_CFLAGS=`$PKG_CONFIG --cflags "Qt5Test >= 5.0.0" 2>/dev/null`
+else
+ pkg_failed=yes
+fi
+ fi
+else
+ pkg_failed=untried
+fi
+if test -n "$PKG_CONFIG"; then
+ if test -n "$GPGME_QTTEST_LIBS"; then
+ pkg_cv_GPGME_QTTEST_LIBS="$GPGME_QTTEST_LIBS"
+ else
+ if test -n "$PKG_CONFIG" && \
+ { { $as_echo "$as_me:${as_lineno-$LINENO}: \$PKG_CONFIG --exists --print-errors \"Qt5Test >= 5.0.0\""; } >&5
+ ($PKG_CONFIG --exists --print-errors "Qt5Test >= 5.0.0") 2>&5
+ ac_status=$?
+ $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5
+ test $ac_status = 0; }; then
+ pkg_cv_GPGME_QTTEST_LIBS=`$PKG_CONFIG --libs "Qt5Test >= 5.0.0" 2>/dev/null`
+else
+ pkg_failed=yes
+fi
+ fi
+else
+ pkg_failed=untried
+fi
+
+
+
+if test $pkg_failed = yes; then
+
+if $PKG_CONFIG --atleast-pkgconfig-version 0.20; then
+ _pkg_short_errors_supported=yes
+else
+ _pkg_short_errors_supported=no
+fi
+ if test $_pkg_short_errors_supported = yes; then
+ GPGME_QTTEST_PKG_ERRORS=`$PKG_CONFIG --short-errors --errors-to-stdout --print-errors "Qt5Test >= 5.0.0"`
+ else
+ GPGME_QTTEST_PKG_ERRORS=`$PKG_CONFIG --errors-to-stdout --print-errors "Qt5Test >= 5.0.0"`
+ fi
+ # Put the nasty error message in config.log where it belongs
+ echo "$GPGME_QTTEST_PKG_ERRORS" >&5
+
+ { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
+$as_echo "no" >&6; }
+ have_qt5test_libs="no"
+elif test $pkg_failed = untried; then
+ have_qt5test_libs="no"
+else
+ GPGME_QTTEST_CFLAGS=$pkg_cv_GPGME_QTTEST_CFLAGS
+ GPGME_QTTEST_LIBS=$pkg_cv_GPGME_QTTEST_LIBS
+ { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5
+$as_echo "yes" >&6; }
+ have_qt5test_libs="yes"
+fi
+
+ if ! test "$have_w32_system" = yes; then
+ if "$PKG_CONFIG" --variable qt_config Qt5Core | grep -q "reduce_relocations"; then
+ GPGME_QT_CFLAGS="$GPGME_QT_CFLAGS -fpic"
+ fi
+ fi
+ if test "$have_qt5_libs" = "yes"; then
+ if test -n "$ac_tool_prefix"; then
+ # Extract the first word of "${ac_tool_prefix}moc", so it can be a program name with args.
+set dummy ${ac_tool_prefix}moc; ac_word=$2
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5
+$as_echo_n "checking for $ac_word... " >&6; }
+if ${ac_cv_prog_MOC+:} false; then :
+ $as_echo_n "(cached) " >&6
+else
+ if test -n "$MOC"; then
+ ac_cv_prog_MOC="$MOC" # Let the user override the test.
+else
+as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
+for as_dir in $PATH
+do
+ IFS=$as_save_IFS
+ test -z "$as_dir" && as_dir=.
+ for ac_exec_ext in '' $ac_executable_extensions; do
+ if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then
+ ac_cv_prog_MOC="${ac_tool_prefix}moc"
+ $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5
+ break 2
+ fi
+done
+ done
+IFS=$as_save_IFS
+
+fi
+fi
+MOC=$ac_cv_prog_MOC
+if test -n "$MOC"; then
+ { $as_echo "$as_me:${as_lineno-$LINENO}: result: $MOC" >&5
+$as_echo "$MOC" >&6; }
+else
+ { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
+$as_echo "no" >&6; }
+fi
+
+
+fi
+if test -z "$ac_cv_prog_MOC"; then
+ ac_ct_MOC=$MOC
+ # Extract the first word of "moc", so it can be a program name with args.
+set dummy moc; ac_word=$2
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5
+$as_echo_n "checking for $ac_word... " >&6; }
+if ${ac_cv_prog_ac_ct_MOC+:} false; then :
+ $as_echo_n "(cached) " >&6
+else
+ if test -n "$ac_ct_MOC"; then
+ ac_cv_prog_ac_ct_MOC="$ac_ct_MOC" # Let the user override the test.
+else
+as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
+for as_dir in $PATH
+do
+ IFS=$as_save_IFS
+ test -z "$as_dir" && as_dir=.
+ for ac_exec_ext in '' $ac_executable_extensions; do
+ if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then
+ ac_cv_prog_ac_ct_MOC="moc"
+ $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5
+ break 2
+ fi
+done
+ done
+IFS=$as_save_IFS
+
+fi
+fi
+ac_ct_MOC=$ac_cv_prog_ac_ct_MOC
+if test -n "$ac_ct_MOC"; then
+ { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_ct_MOC" >&5
+$as_echo "$ac_ct_MOC" >&6; }
+else
+ { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
+$as_echo "no" >&6; }
+fi
+
+ if test "x$ac_ct_MOC" = x; then
+ MOC=""
+ else
+ case $cross_compiling:$ac_tool_warned in
+yes:)
+{ $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: using cross tools not prefixed with host triplet" >&5
+$as_echo "$as_me: WARNING: using cross tools not prefixed with host triplet" >&2;}
+ac_tool_warned=yes ;;
+esac
+ MOC=$ac_ct_MOC
+ fi
+else
+ MOC="$ac_cv_prog_MOC"
+fi
+
+ { $as_echo "$as_me:${as_lineno-$LINENO}: checking moc version" >&5
+$as_echo_n "checking moc version... " >&6; }
+ mocversion=`$MOC -v 2>&1`
+ mocversiongrep=`echo $mocversion | grep "Qt 5\|moc 5"`
+ if test x"$mocversiongrep" != x"$mocversion"; then
+ { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
+$as_echo "no" >&6; }
+ # moc was not the qt5 one, try with moc-qt5
+ if test -n "$ac_tool_prefix"; then
+ # Extract the first word of "${ac_tool_prefix}moc-qt5", so it can be a program name with args.
+set dummy ${ac_tool_prefix}moc-qt5; ac_word=$2
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5
+$as_echo_n "checking for $ac_word... " >&6; }
+if ${ac_cv_prog_MOC2+:} false; then :
+ $as_echo_n "(cached) " >&6
+else
+ if test -n "$MOC2"; then
+ ac_cv_prog_MOC2="$MOC2" # Let the user override the test.
+else
+as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
+for as_dir in $PATH
+do
+ IFS=$as_save_IFS
+ test -z "$as_dir" && as_dir=.
+ for ac_exec_ext in '' $ac_executable_extensions; do
+ if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then
+ ac_cv_prog_MOC2="${ac_tool_prefix}moc-qt5"
+ $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5
+ break 2
+ fi
+done
+ done
+IFS=$as_save_IFS
+
+fi
+fi
+MOC2=$ac_cv_prog_MOC2
+if test -n "$MOC2"; then
+ { $as_echo "$as_me:${as_lineno-$LINENO}: result: $MOC2" >&5
+$as_echo "$MOC2" >&6; }
+else
+ { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
+$as_echo "no" >&6; }
+fi
+
+
+fi
+if test -z "$ac_cv_prog_MOC2"; then
+ ac_ct_MOC2=$MOC2
+ # Extract the first word of "moc-qt5", so it can be a program name with args.
+set dummy moc-qt5; ac_word=$2
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5
+$as_echo_n "checking for $ac_word... " >&6; }
+if ${ac_cv_prog_ac_ct_MOC2+:} false; then :
+ $as_echo_n "(cached) " >&6
+else
+ if test -n "$ac_ct_MOC2"; then
+ ac_cv_prog_ac_ct_MOC2="$ac_ct_MOC2" # Let the user override the test.
+else
+as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
+for as_dir in $PATH
+do
+ IFS=$as_save_IFS
+ test -z "$as_dir" && as_dir=.
+ for ac_exec_ext in '' $ac_executable_extensions; do
+ if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then
+ ac_cv_prog_ac_ct_MOC2="moc-qt5"
+ $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5
+ break 2
+ fi
+done
+ done
+IFS=$as_save_IFS
+
+fi
+fi
+ac_ct_MOC2=$ac_cv_prog_ac_ct_MOC2
+if test -n "$ac_ct_MOC2"; then
+ { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_ct_MOC2" >&5
+$as_echo "$ac_ct_MOC2" >&6; }
+else
+ { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
+$as_echo "no" >&6; }
+fi
+
+ if test "x$ac_ct_MOC2" = x; then
+ MOC2=""
+ else
+ case $cross_compiling:$ac_tool_warned in
+yes:)
+{ $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: using cross tools not prefixed with host triplet" >&5
+$as_echo "$as_me: WARNING: using cross tools not prefixed with host triplet" >&2;}
+ac_tool_warned=yes ;;
+esac
+ MOC2=$ac_ct_MOC2
+ fi
+else
+ MOC2="$ac_cv_prog_MOC2"
+fi
+
+ mocversion=`$MOC2 -v 2>&1`
+ mocversiongrep=`echo $mocversion | grep "Qt 5\|moc-qt5 5\|moc 5"`
+ if test x"$mocversiongrep" != x"$mocversion"; then
+ if test -n "$ac_tool_prefix"; then
+ # Extract the first word of "${ac_tool_prefix}qtchooser", so it can be a program name with args.
+set dummy ${ac_tool_prefix}qtchooser; ac_word=$2
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5
+$as_echo_n "checking for $ac_word... " >&6; }
+if ${ac_cv_prog_QTCHOOSER+:} false; then :
+ $as_echo_n "(cached) " >&6
+else
+ if test -n "$QTCHOOSER"; then
+ ac_cv_prog_QTCHOOSER="$QTCHOOSER" # Let the user override the test.
+else
+as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
+for as_dir in $PATH
+do
+ IFS=$as_save_IFS
+ test -z "$as_dir" && as_dir=.
+ for ac_exec_ext in '' $ac_executable_extensions; do
+ if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then
+ ac_cv_prog_QTCHOOSER="${ac_tool_prefix}qtchooser"
+ $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5
+ break 2
+ fi
+done
+ done
+IFS=$as_save_IFS
+
+fi
+fi
+QTCHOOSER=$ac_cv_prog_QTCHOOSER
+if test -n "$QTCHOOSER"; then
+ { $as_echo "$as_me:${as_lineno-$LINENO}: result: $QTCHOOSER" >&5
+$as_echo "$QTCHOOSER" >&6; }
+else
+ { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
+$as_echo "no" >&6; }
+fi
+
+
+fi
+if test -z "$ac_cv_prog_QTCHOOSER"; then
+ ac_ct_QTCHOOSER=$QTCHOOSER
+ # Extract the first word of "qtchooser", so it can be a program name with args.
+set dummy qtchooser; ac_word=$2
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5
+$as_echo_n "checking for $ac_word... " >&6; }
+if ${ac_cv_prog_ac_ct_QTCHOOSER+:} false; then :
+ $as_echo_n "(cached) " >&6
+else
+ if test -n "$ac_ct_QTCHOOSER"; then
+ ac_cv_prog_ac_ct_QTCHOOSER="$ac_ct_QTCHOOSER" # Let the user override the test.
+else
+as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
+for as_dir in $PATH
+do
+ IFS=$as_save_IFS
+ test -z "$as_dir" && as_dir=.
+ for ac_exec_ext in '' $ac_executable_extensions; do
+ if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then
+ ac_cv_prog_ac_ct_QTCHOOSER="qtchooser"
+ $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5
+ break 2
+ fi
+done
+ done
+IFS=$as_save_IFS
+
+fi
+fi
+ac_ct_QTCHOOSER=$ac_cv_prog_ac_ct_QTCHOOSER
+if test -n "$ac_ct_QTCHOOSER"; then
+ { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_ct_QTCHOOSER" >&5
+$as_echo "$ac_ct_QTCHOOSER" >&6; }
+else
+ { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
+$as_echo "no" >&6; }
+fi
+
+ if test "x$ac_ct_QTCHOOSER" = x; then
+ QTCHOOSER=""
+ else
+ case $cross_compiling:$ac_tool_warned in
+yes:)
+{ $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: using cross tools not prefixed with host triplet" >&5
+$as_echo "$as_me: WARNING: using cross tools not prefixed with host triplet" >&2;}
+ac_tool_warned=yes ;;
+esac
+ QTCHOOSER=$ac_ct_QTCHOOSER
+ fi
+else
+ QTCHOOSER="$ac_cv_prog_QTCHOOSER"
+fi
+
+ qt5tooldir=`QT_SELECT=qt5 qtchooser -print-env | grep QTTOOLDIR | cut -d '=' -f 2 | cut -d \" -f 2`
+ mocversion=`$qt5tooldir/moc -v 2>&1`
+ mocversiongrep=`echo $mocversion | grep "Qt 5\|moc 5"`
+ if test x"$mocversiongrep" != x"$mocversion"; then
+ # no valid moc found
+ have_qt5_libs="no";
+ else
+ MOC=$qt5tooldir/moc
+ fi
+ else
+ MOC=$MOC2
+ fi
+ fi
+ { $as_echo "$as_me:${as_lineno-$LINENO}: result: $mocversion" >&5
+$as_echo "$mocversion" >&6; }
+ OLDCPPFLAGS=$CPPFLAGS
+ CPPFLAGS=$GPGME_QT_CFLAGS
+ OLDLIBS=$LIBS
+ LIBS=$GPGME_QT_LIBS
+ ac_ext=cpp
+ac_cpp='$CXXCPP $CPPFLAGS'
+ac_compile='$CXX -c $CXXFLAGS $CPPFLAGS conftest.$ac_ext >&5'
+ac_link='$CXX -o conftest$ac_exeext $CXXFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5'
+ac_compiler_gnu=$ac_cv_cxx_compiler_gnu
+
+ { $as_echo "$as_me:${as_lineno-$LINENO}: checking whether a simple qt program can be built" >&5
+$as_echo_n "checking whether a simple qt program can be built... " >&6; }
+ cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h. */
+
+ #include <QCoreApplication>
+ int main (int argc, char **argv) {
+ QCoreApplication app(argc, argv);
+ app.exec();
+ }
+_ACEOF
+if ac_fn_cxx_try_link "$LINENO"; then :
+ have_qt5_libs='yes'
+else
+ have_qt5_libs='no'
+fi
+rm -f core conftest.err conftest.$ac_objext \
+ conftest$ac_exeext conftest.$ac_ext
+ { $as_echo "$as_me:${as_lineno-$LINENO}: result: $have_qt5_libs" >&5
+$as_echo "$have_qt5_libs" >&6; }
+ ac_ext=c
+ac_cpp='$CPP $CPPFLAGS'
+ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5'
+ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5'
+ac_compiler_gnu=$ac_cv_c_compiler_gnu
+
+ CPPFLAGS=$OLDCPPFLAGS
+ LIBS=$OLDLIBS
+ fi
+
+ if test "$have_qt5_libs" != "yes"; then
+ if test "$explicit_languages" = "1"; then
+ as_fn_error $? "
+***
+*** Qt5 (Qt5Core) is required for Qt binding.
+***" "$LINENO" 5
+ else
+ { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING:
+***
+*** Qt5 (Qt5Core) not found Qt Binding will be disabled.
+***" >&5
+$as_echo "$as_me: WARNING:
+***
+*** Qt5 (Qt5Core) not found Qt Binding will be disabled.
+***" >&2;}
+ fi
+ else
+ enabled_languages=`echo $enabled_languages qt`
+
+ for ac_prog in doxygen
+do
+ # Extract the first word of "$ac_prog", so it can be a program name with args.
+set dummy $ac_prog; ac_word=$2
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5
+$as_echo_n "checking for $ac_word... " >&6; }
+if ${ac_cv_prog_DOXYGEN+:} false; then :
+ $as_echo_n "(cached) " >&6
+else
+ if test -n "$DOXYGEN"; then
+ ac_cv_prog_DOXYGEN="$DOXYGEN" # Let the user override the test.
+else
+as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
+for as_dir in $PATH
+do
+ IFS=$as_save_IFS
+ test -z "$as_dir" && as_dir=.
+ for ac_exec_ext in '' $ac_executable_extensions; do
+ if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then
+ ac_cv_prog_DOXYGEN="$ac_prog"
+ $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5
+ break 2
+ fi
+done
+ done
+IFS=$as_save_IFS
+
+fi
+fi
+DOXYGEN=$ac_cv_prog_DOXYGEN
+if test -n "$DOXYGEN"; then
+ { $as_echo "$as_me:${as_lineno-$LINENO}: result: $DOXYGEN" >&5
+$as_echo "$DOXYGEN" >&6; }
+else
+ { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
+$as_echo "no" >&6; }
+fi
+
+
+ test -n "$DOXYGEN" && break
+done
+
+ if test -z "$DOXYGEN";
+ # This is not highlighted becase it's not really important.
+ then { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: Doxygen not found - Qt binding doc will not be built." >&5
+$as_echo "$as_me: WARNING: Doxygen not found - Qt binding doc will not be built." >&2;}
+ fi
+ for ac_prog in dot
+do
+ # Extract the first word of "$ac_prog", so it can be a program name with args.
+set dummy $ac_prog; ac_word=$2
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5
+$as_echo_n "checking for $ac_word... " >&6; }
+if ${ac_cv_prog_GRAPHVIZ+:} false; then :
+ $as_echo_n "(cached) " >&6
+else
+ if test -n "$GRAPHVIZ"; then
+ ac_cv_prog_GRAPHVIZ="$GRAPHVIZ" # Let the user override the test.
+else
+as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
+for as_dir in $PATH
+do
+ IFS=$as_save_IFS
+ test -z "$as_dir" && as_dir=.
+ for ac_exec_ext in '' $ac_executable_extensions; do
+ if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then
+ ac_cv_prog_GRAPHVIZ="$ac_prog"
+ $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5
+ break 2
+ fi
+done
+ done
+IFS=$as_save_IFS
+
+fi
+fi
+GRAPHVIZ=$ac_cv_prog_GRAPHVIZ
+if test -n "$GRAPHVIZ"; then
+ { $as_echo "$as_me:${as_lineno-$LINENO}: result: $GRAPHVIZ" >&5
+$as_echo "$GRAPHVIZ" >&6; }
+else
+ { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
+$as_echo "no" >&6; }
+fi
+
+
+ test -n "$GRAPHVIZ" && break
+done
+
+ if test -z "$GRAPHVIZ";
+ then { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: Graphviz not found - Qt binding doc will not have diagrams." >&5
+$as_echo "$as_me: WARNING: Graphviz not found - Qt binding doc will not have diagrams." >&2;}
+ fi
+ fi
+fi
+ if test -n "$DOXYGEN"; then
+ HAVE_DOXYGEN_TRUE=
+ HAVE_DOXYGEN_FALSE='#'
+else
+ HAVE_DOXYGEN_TRUE='#'
+ HAVE_DOXYGEN_FALSE=
+fi
+
+if test -n "$GRAPHVIZ"; then
+ HAVE_DOT="YES"
+else
+ HAVE_DOT="NO"
+fi
+
+
+# Python bindings.
+
+name="python2"
+list=$enabled_languages
+found=0
+
+for n in $list; do
+ if test "x$name" = "x$n"; then
+ found=1
+ fi
+done
+
+found_py2=$found
+
+name="python3"
+list=$enabled_languages
+found=0
+
+for n in $list; do
+ if test "x$name" = "x$n"; then
+ found=1
+ fi
+done
+
+found_py3=$found
+
+name="python"
+list=$enabled_languages
+found=0
+
+for n in $list; do
+ if test "x$name" = "x$n"; then
+ found=1
+ fi
+done
+
+found_py=$found
+if test "$found_py" = "1" -o "$found_py2" = "1" -o "$found_py3" = "1"; then
+
+ # Ubuntu has swig 2.0 as /usr/bin/swig2.0
+ for ac_prog in swig swig2.0
+do
+ # Extract the first word of "$ac_prog", so it can be a program name with args.
+set dummy $ac_prog; ac_word=$2
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5
+$as_echo_n "checking for $ac_word... " >&6; }
+if ${ac_cv_path_SWIG+:} false; then :
+ $as_echo_n "(cached) " >&6
+else
+ case $SWIG in
+ [\\/]* | ?:[\\/]*)
+ ac_cv_path_SWIG="$SWIG" # Let the user override the test with a path.
+ ;;
+ *)
+ as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
+for as_dir in $PATH
+do
+ IFS=$as_save_IFS
+ test -z "$as_dir" && as_dir=.
+ for ac_exec_ext in '' $ac_executable_extensions; do
+ if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then
+ ac_cv_path_SWIG="$as_dir/$ac_word$ac_exec_ext"
+ $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5
+ break 2
+ fi
+done
+ done
+IFS=$as_save_IFS
+
+ ;;
+esac
+fi
+SWIG=$ac_cv_path_SWIG
+if test -n "$SWIG"; then
+ { $as_echo "$as_me:${as_lineno-$LINENO}: result: $SWIG" >&5
+$as_echo "$SWIG" >&6; }
+else
+ { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
+$as_echo "no" >&6; }
+fi
+
+
+ test -n "$SWIG" && break
+done
+
+ if test -z "$SWIG" ; then
+ :
+ elif test -n "" ; then
+ { $as_echo "$as_me:${as_lineno-$LINENO}: checking SWIG version" >&5
+$as_echo_n "checking SWIG version... " >&6; }
+ swig_version=`$SWIG -version 2>&1 | grep 'SWIG Version' | sed 's/.*\([0-9][0-9]*\.[0-9][0-9]*\.[0-9][0-9]*\).*/\1/g'`
+ { $as_echo "$as_me:${as_lineno-$LINENO}: result: $swig_version" >&5
+$as_echo "$swig_version" >&6; }
+ if test -n "$swig_version" ; then
+ # Calculate the required version number components
+ required=
+ required_major=`echo $required | sed 's/[^0-9].*//'`
+ if test -z "$required_major" ; then
+ required_major=0
+ fi
+ required=`echo $required | sed 's/[0-9]*[^0-9]//'`
+ required_minor=`echo $required | sed 's/[^0-9].*//'`
+ if test -z "$required_minor" ; then
+ required_minor=0
+ fi
+ required=`echo $required | sed 's/[0-9]*[^0-9]//'`
+ required_patch=`echo $required | sed 's/[^0-9].*//'`
+ if test -z "$required_patch" ; then
+ required_patch=0
+ fi
+ # Calculate the available version number components
+ available=$swig_version
+ available_major=`echo $available | sed 's/[^0-9].*//'`
+ if test -z "$available_major" ; then
+ available_major=0
+ fi
+ available=`echo $available | sed 's/[0-9]*[^0-9]//'`
+ available_minor=`echo $available | sed 's/[^0-9].*//'`
+ if test -z "$available_minor" ; then
+ available_minor=0
+ fi
+ available=`echo $available | sed 's/[0-9]*[^0-9]//'`
+ available_patch=`echo $available | sed 's/[^0-9].*//'`
+ if test -z "$available_patch" ; then
+ available_patch=0
+ fi
+ # Convert the version tuple into a single number for easier comparison.
+ # Using base 100 should be safe since SWIG internally uses BCD values
+ # to encode its version number.
+ required_swig_vernum=`expr $required_major \* 10000 \
+ \+ $required_minor \* 100 \+ $required_patch`
+ available_swig_vernum=`expr $available_major \* 10000 \
+ \+ $available_minor \* 100 \+ $available_patch`
+
+ if test $available_swig_vernum -lt $required_swig_vernum; then
+ { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: SWIG version >= is required. You have $swig_version." >&5
+$as_echo "$as_me: WARNING: SWIG version >= is required. You have $swig_version." >&2;}
+ SWIG=''
+
+ else
+ { $as_echo "$as_me:${as_lineno-$LINENO}: checking for SWIG library" >&5
+$as_echo_n "checking for SWIG library... " >&6; }
+ SWIG_LIB=`$SWIG -swiglib`
+ { $as_echo "$as_me:${as_lineno-$LINENO}: result: $SWIG_LIB" >&5
+$as_echo "$SWIG_LIB" >&6; }
+
+ fi
+ else
+ { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: cannot determine SWIG version" >&5
+$as_echo "$as_me: WARNING: cannot determine SWIG version" >&2;}
+ SWIG=''
+
+ fi
+ fi
+
+
+ if test -z "$SWIG"; then
+ if test "$explicit_languages" = "1"; then
+ as_fn_error $? "
+***
+*** You need SWIG to build the Python bindings.
+***" "$LINENO" 5
+ else
+ enabled_languages=$(echo $enabled_languages | sed 's/python//')
+ fi
+ else
+ # Reset all the stuff, just to be sure.
+ PYTHONS=
+ PYTHON_VERSIONS=
+ unset PYTHON
+ unset PYTHON_VERSION
+ unset PYTHON_CPPFLAGS
+ unset PYTHON_LDFLAGS
+ unset PYTHON_SITE_PKG
+ unset PYTHON_EXTRA_LIBS
+ unset PYTHON_EXTRA_LDFLAGS
+ unset ac_cv_path_PYTHON
+ unset am_cv_pathless_PYTHON
+ unset am_cv_python_version
+ unset am_cv_python_platform
+ unset am_cv_python_pythondir
+ unset am_cv_python_pyexecdir
+
+ if test "$found_py" = "1" -o "$found_py2" = "1"; then
+
+
+
+
+
+
+ if test -n "$PYTHON"; then
+ # If the user set $PYTHON, use it and don't search something else.
+ { $as_echo "$as_me:${as_lineno-$LINENO}: checking whether $PYTHON version is >= 2.7" >&5
+$as_echo_n "checking whether $PYTHON version is >= 2.7... " >&6; }
+ prog="import sys
+# split strings by '.' and convert to numeric. Append some zeros
+# because we need at least 4 digits for the hex conversion.
+# map returns an iterator in Python 3.0 and a list in 2.x
+minver = list(map(int, '2.7'.split('.'))) + [0, 0, 0]
+minverhex = 0
+# xrange is not present in Python 3.0 and range returns an iterator
+for i in list(range(0, 4)): minverhex = (minverhex << 8) + minver[i]
+sys.exit(sys.hexversion < minverhex)"
+ if { echo "$as_me:$LINENO: $PYTHON -c "$prog"" >&5
+ ($PYTHON -c "$prog") >&5 2>&5
+ ac_status=$?
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); }; then :
+ { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5
+$as_echo "yes" >&6; }
+else
+ { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
+$as_echo "no" >&6; }
+ as_fn_error $? "Python interpreter is too old" "$LINENO" 5
+fi
+ am_display_PYTHON=$PYTHON
+ else
+ # Otherwise, try each interpreter until we find one that satisfies
+ # VERSION.
+ { $as_echo "$as_me:${as_lineno-$LINENO}: checking for a Python interpreter with version >= 2.7" >&5
+$as_echo_n "checking for a Python interpreter with version >= 2.7... " >&6; }
+if ${am_cv_pathless_PYTHON+:} false; then :
+ $as_echo_n "(cached) " >&6
+else
+
+ for am_cv_pathless_PYTHON in python python2 python3 python3.3 python3.2 python3.1 python3.0 python2.7 python2.6 python2.5 python2.4 python2.3 python2.2 python2.1 python2.0 none; do
+ test "$am_cv_pathless_PYTHON" = none && break
+ prog="import sys
+# split strings by '.' and convert to numeric. Append some zeros
+# because we need at least 4 digits for the hex conversion.
+# map returns an iterator in Python 3.0 and a list in 2.x
+minver = list(map(int, '2.7'.split('.'))) + [0, 0, 0]
+minverhex = 0
+# xrange is not present in Python 3.0 and range returns an iterator
+for i in list(range(0, 4)): minverhex = (minverhex << 8) + minver[i]
+sys.exit(sys.hexversion < minverhex)"
+ if { echo "$as_me:$LINENO: $am_cv_pathless_PYTHON -c "$prog"" >&5
+ ($am_cv_pathless_PYTHON -c "$prog") >&5 2>&5
+ ac_status=$?
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); }; then :
+ break
+fi
+ done
+fi
+{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $am_cv_pathless_PYTHON" >&5
+$as_echo "$am_cv_pathless_PYTHON" >&6; }
+ # Set $PYTHON to the absolute path of $am_cv_pathless_PYTHON.
+ if test "$am_cv_pathless_PYTHON" = none; then
+ PYTHON=:
+ else
+ # Extract the first word of "$am_cv_pathless_PYTHON", so it can be a program name with args.
+set dummy $am_cv_pathless_PYTHON; ac_word=$2
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5
+$as_echo_n "checking for $ac_word... " >&6; }
+if ${ac_cv_path_PYTHON+:} false; then :
+ $as_echo_n "(cached) " >&6
+else
+ case $PYTHON in
+ [\\/]* | ?:[\\/]*)
+ ac_cv_path_PYTHON="$PYTHON" # Let the user override the test with a path.
+ ;;
+ *)
+ as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
+for as_dir in $PATH
+do
+ IFS=$as_save_IFS
+ test -z "$as_dir" && as_dir=.
+ for ac_exec_ext in '' $ac_executable_extensions; do
+ if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then
+ ac_cv_path_PYTHON="$as_dir/$ac_word$ac_exec_ext"
+ $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5
+ break 2
+ fi
+done
+ done
+IFS=$as_save_IFS
+
+ ;;
+esac
+fi
+PYTHON=$ac_cv_path_PYTHON
+if test -n "$PYTHON"; then
+ { $as_echo "$as_me:${as_lineno-$LINENO}: result: $PYTHON" >&5
+$as_echo "$PYTHON" >&6; }
+else
+ { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
+$as_echo "no" >&6; }
+fi
+
+
+ fi
+ am_display_PYTHON=$am_cv_pathless_PYTHON
+ fi
+
+
+ if test "$PYTHON" = :; then
+ as_fn_error $? "no suitable Python interpreter found" "$LINENO" 5
+ else
+
+
+ { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $am_display_PYTHON version" >&5
+$as_echo_n "checking for $am_display_PYTHON version... " >&6; }
+if ${am_cv_python_version+:} false; then :
+ $as_echo_n "(cached) " >&6
+else
+ am_cv_python_version=`$PYTHON -c "import sys; sys.stdout.write(sys.version[:3])"`
+fi
+{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $am_cv_python_version" >&5
+$as_echo "$am_cv_python_version" >&6; }
+ PYTHON_VERSION=$am_cv_python_version
+
+
+
+ PYTHON_PREFIX='${prefix}'
+
+ PYTHON_EXEC_PREFIX='${exec_prefix}'
+
+
+
+ { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $am_display_PYTHON platform" >&5
+$as_echo_n "checking for $am_display_PYTHON platform... " >&6; }
+if ${am_cv_python_platform+:} false; then :
+ $as_echo_n "(cached) " >&6
+else
+ am_cv_python_platform=`$PYTHON -c "import sys; sys.stdout.write(sys.platform)"`
+fi
+{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $am_cv_python_platform" >&5
+$as_echo "$am_cv_python_platform" >&6; }
+ PYTHON_PLATFORM=$am_cv_python_platform
+
+
+ # Just factor out some code duplication.
+ am_python_setup_sysconfig="\
+import sys
+# Prefer sysconfig over distutils.sysconfig, for better compatibility
+# with python 3.x. See automake bug#10227.
+try:
+ import sysconfig
+except ImportError:
+ can_use_sysconfig = 0
+else:
+ can_use_sysconfig = 1
+# Can't use sysconfig in CPython 2.7, since it's broken in virtualenvs:
+# <https://github.com/pypa/virtualenv/issues/118>
+try:
+ from platform import python_implementation
+ if python_implementation() == 'CPython' and sys.version[:3] == '2.7':
+ can_use_sysconfig = 0
+except ImportError:
+ pass"
+
+
+ { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $am_display_PYTHON script directory" >&5
+$as_echo_n "checking for $am_display_PYTHON script directory... " >&6; }
+if ${am_cv_python_pythondir+:} false; then :
+ $as_echo_n "(cached) " >&6
+else
+ if test "x$prefix" = xNONE
+ then
+ am_py_prefix=$ac_default_prefix
+ else
+ am_py_prefix=$prefix
+ fi
+ am_cv_python_pythondir=`$PYTHON -c "
+$am_python_setup_sysconfig
+if can_use_sysconfig:
+ sitedir = sysconfig.get_path('purelib', vars={'base':'$am_py_prefix'})
+else:
+ from distutils import sysconfig
+ sitedir = sysconfig.get_python_lib(0, 0, prefix='$am_py_prefix')
+sys.stdout.write(sitedir)"`
+ case $am_cv_python_pythondir in
+ $am_py_prefix*)
+ am__strip_prefix=`echo "$am_py_prefix" | sed 's|.|.|g'`
+ am_cv_python_pythondir=`echo "$am_cv_python_pythondir" | sed "s,^$am__strip_prefix,$PYTHON_PREFIX,"`
+ ;;
+ *)
+ case $am_py_prefix in
+ /usr|/System*) ;;
+ *)
+ am_cv_python_pythondir=$PYTHON_PREFIX/lib/python$PYTHON_VERSION/site-packages
+ ;;
+ esac
+ ;;
+ esac
+
+fi
+{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $am_cv_python_pythondir" >&5
+$as_echo "$am_cv_python_pythondir" >&6; }
+ pythondir=$am_cv_python_pythondir
+
+
+
+ pkgpythondir=\${pythondir}/$PACKAGE
+
+
+ { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $am_display_PYTHON extension module directory" >&5
+$as_echo_n "checking for $am_display_PYTHON extension module directory... " >&6; }
+if ${am_cv_python_pyexecdir+:} false; then :
+ $as_echo_n "(cached) " >&6
+else
+ if test "x$exec_prefix" = xNONE
+ then
+ am_py_exec_prefix=$am_py_prefix
+ else
+ am_py_exec_prefix=$exec_prefix
+ fi
+ am_cv_python_pyexecdir=`$PYTHON -c "
+$am_python_setup_sysconfig
+if can_use_sysconfig:
+ sitedir = sysconfig.get_path('platlib', vars={'platbase':'$am_py_prefix'})
+else:
+ from distutils import sysconfig
+ sitedir = sysconfig.get_python_lib(1, 0, prefix='$am_py_prefix')
+sys.stdout.write(sitedir)"`
+ case $am_cv_python_pyexecdir in
+ $am_py_exec_prefix*)
+ am__strip_prefix=`echo "$am_py_exec_prefix" | sed 's|.|.|g'`
+ am_cv_python_pyexecdir=`echo "$am_cv_python_pyexecdir" | sed "s,^$am__strip_prefix,$PYTHON_EXEC_PREFIX,"`
+ ;;
+ *)
+ case $am_py_exec_prefix in
+ /usr|/System*) ;;
+ *)
+ am_cv_python_pyexecdir=$PYTHON_EXEC_PREFIX/lib/python$PYTHON_VERSION/site-packages
+ ;;
+ esac
+ ;;
+ esac
+
+fi
+{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $am_cv_python_pyexecdir" >&5
+$as_echo "$am_cv_python_pyexecdir" >&6; }
+ pyexecdir=$am_cv_python_pyexecdir
+
+
+
+ pkgpyexecdir=\${pyexecdir}/$PACKAGE
+
+
+
+ fi
+
+
+
+ #
+ # Allow the use of a (user set) custom python version
+ #
+
+
+ # Extract the first word of "python[$PYTHON_VERSION]", so it can be a program name with args.
+set dummy python$PYTHON_VERSION; ac_word=$2
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5
+$as_echo_n "checking for $ac_word... " >&6; }
+if ${ac_cv_path_PYTHON+:} false; then :
+ $as_echo_n "(cached) " >&6
+else
+ case $PYTHON in
+ [\\/]* | ?:[\\/]*)
+ ac_cv_path_PYTHON="$PYTHON" # Let the user override the test with a path.
+ ;;
+ *)
+ as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
+for as_dir in $PATH
+do
+ IFS=$as_save_IFS
+ test -z "$as_dir" && as_dir=.
+ for ac_exec_ext in '' $ac_executable_extensions; do
+ if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then
+ ac_cv_path_PYTHON="$as_dir/$ac_word$ac_exec_ext"
+ $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5
+ break 2
+ fi
+done
+ done
+IFS=$as_save_IFS
+
+ ;;
+esac
+fi
+PYTHON=$ac_cv_path_PYTHON
+if test -n "$PYTHON"; then
+ { $as_echo "$as_me:${as_lineno-$LINENO}: result: $PYTHON" >&5
+$as_echo "$PYTHON" >&6; }
+else
+ { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
+$as_echo "no" >&6; }
+fi
+
+
+ if test -z "$PYTHON"; then
+ as_fn_error $? "Cannot find python$PYTHON_VERSION in your system path" "$LINENO" 5
+ PYTHON_VERSION=""
+ fi
+
+ #
+ # Check for a version of Python >= 2.1.0
+ #
+ { $as_echo "$as_me:${as_lineno-$LINENO}: checking for a version of Python >= '2.1.0'" >&5
+$as_echo_n "checking for a version of Python >= '2.1.0'... " >&6; }
+ ac_supports_python_ver=`$PYTHON -c "import sys; \
+ ver = sys.version.split ()[0]; \
+ print (ver >= '2.1.0')"`
+ if test "$ac_supports_python_ver" != "True"; then
+ if test -z "$PYTHON_NOVERSIONCHECK"; then
+ { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
+$as_echo "no" >&6; }
+ { { $as_echo "$as_me:${as_lineno-$LINENO}: error: in \`$ac_pwd':" >&5
+$as_echo "$as_me: error: in \`$ac_pwd':" >&2;}
+as_fn_error $? "
+This version of the AC_PYTHON_DEVEL macro
+doesn't work properly with versions of Python before
+2.1.0. You may need to re-run configure, setting the
+variables PYTHON_CPPFLAGS, PYTHON_LDFLAGS, PYTHON_SITE_PKG,
+PYTHON_EXTRA_LIBS and PYTHON_EXTRA_LDFLAGS by hand.
+Moreover, to disable this check, set PYTHON_NOVERSIONCHECK
+to something else than an empty string.
+
+See \`config.log' for more details" "$LINENO" 5; }
+ else
+ { $as_echo "$as_me:${as_lineno-$LINENO}: result: skip at user request" >&5
+$as_echo "skip at user request" >&6; }
+ fi
+ else
+ { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5
+$as_echo "yes" >&6; }
+ fi
+
+ #
+ # if the macro parameter ``version'' is set, honour it
+ #
+ if test -n ""; then
+ { $as_echo "$as_me:${as_lineno-$LINENO}: checking for a version of Python " >&5
+$as_echo_n "checking for a version of Python ... " >&6; }
+ ac_supports_python_ver=`$PYTHON -c "import sys; \
+ ver = sys.version.split ()[0]; \
+ print (ver )"`
+ if test "$ac_supports_python_ver" = "True"; then
+ { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5
+$as_echo "yes" >&6; }
+ else
+ { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
+$as_echo "no" >&6; }
+ as_fn_error $? "this package requires Python .
+If you have it installed, but it isn't the default Python
+interpreter in your system path, please pass the PYTHON_VERSION
+variable to configure. See \`\`configure --help'' for reference.
+" "$LINENO" 5
+ PYTHON_VERSION=""
+ fi
+ fi
+
+ #
+ # Check if you have distutils, else fail
+ #
+ { $as_echo "$as_me:${as_lineno-$LINENO}: checking for the distutils Python package" >&5
+$as_echo_n "checking for the distutils Python package... " >&6; }
+ ac_distutils_result=`$PYTHON -c "import distutils" 2>&1`
+ if test -z "$ac_distutils_result"; then
+ { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5
+$as_echo "yes" >&6; }
+ else
+ { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
+$as_echo "no" >&6; }
+ as_fn_error $? "cannot import Python module \"distutils\".
+Please check your Python installation. The error was:
+$ac_distutils_result" "$LINENO" 5
+ PYTHON_VERSION=""
+ fi
+
+ #
+ # Check for Python include path
+ #
+ { $as_echo "$as_me:${as_lineno-$LINENO}: checking for Python include path" >&5
+$as_echo_n "checking for Python include path... " >&6; }
+ if test -z "$PYTHON_CPPFLAGS"; then
+ python_path=`$PYTHON -c "import distutils.sysconfig; \
+ print (distutils.sysconfig.get_python_inc ());"`
+ plat_python_path=`$PYTHON -c "import distutils.sysconfig; \
+ print (distutils.sysconfig.get_python_inc (plat_specific=1));"`
+ if test -n "${python_path}"; then
+ if test "${plat_python_path}" != "${python_path}"; then
+ python_path="-I$python_path -I$plat_python_path"
+ else
+ python_path="-I$python_path"
+ fi
+ fi
+ PYTHON_CPPFLAGS=$python_path
+ fi
+ { $as_echo "$as_me:${as_lineno-$LINENO}: result: $PYTHON_CPPFLAGS" >&5
+$as_echo "$PYTHON_CPPFLAGS" >&6; }
+
+
+ #
+ # Check for Python library path
+ #
+ { $as_echo "$as_me:${as_lineno-$LINENO}: checking for Python library path" >&5
+$as_echo_n "checking for Python library path... " >&6; }
+ if test -z "$PYTHON_LDFLAGS"; then
+ # (makes two attempts to ensure we've got a version number
+ # from the interpreter)
+ ac_python_version=`cat<<EOD | $PYTHON -
+
+# join all versioning strings, on some systems
+# major/minor numbers could be in different list elements
+from distutils.sysconfig import *
+e = get_config_var('VERSION')
+if e is not None:
+ print(e)
+EOD`
+
+ if test -z "$ac_python_version"; then
+ if test -n "$PYTHON_VERSION"; then
+ ac_python_version=$PYTHON_VERSION
+ else
+ ac_python_version=`$PYTHON -c "import sys; \
+ print (sys.version[:3])"`
+ fi
+ fi
+
+ # Make the versioning information available to the compiler
+
+cat >>confdefs.h <<_ACEOF
+#define HAVE_PYTHON "$ac_python_version"
+_ACEOF
+
+
+ # First, the library directory:
+ ac_python_libdir=`cat<<EOD | $PYTHON -
+
+# There should be only one
+import distutils.sysconfig
+e = distutils.sysconfig.get_config_var('LIBDIR')
+if e is not None:
+ print (e)
+EOD`
+
+ # Now, for the library:
+ ac_python_library=`cat<<EOD | $PYTHON -
+
+import distutils.sysconfig
+c = distutils.sysconfig.get_config_vars()
+if 'LDVERSION' in c:
+ print ('python'+c['LDVERSION'])
+else:
+ print ('python'+c['VERSION'])
+EOD`
+
+ # This small piece shamelessly adapted from PostgreSQL python macro;
+ # credits goes to momjian, I think. I'd like to put the right name
+ # in the credits, if someone can point me in the right direction... ?
+ #
+ if test -n "$ac_python_libdir" -a -n "$ac_python_library"
+ then
+ # use the official shared library
+ ac_python_library=`echo "$ac_python_library" | sed "s/^lib//"`
+ PYTHON_LDFLAGS="-L$ac_python_libdir -l$ac_python_library"
+ else
+ # old way: use libpython from python_configdir
+ ac_python_libdir=`$PYTHON -c \
+ "from distutils.sysconfig import get_python_lib as f; \
+ import os; \
+ print (os.path.join(f(plat_specific=1, standard_lib=1), 'config'));"`
+ PYTHON_LDFLAGS="-L$ac_python_libdir -lpython$ac_python_version"
+ fi
+
+ if test -z "PYTHON_LDFLAGS"; then
+ as_fn_error $? "
+ Cannot determine location of your Python DSO. Please check it was installed with
+ dynamic libraries enabled, or try setting PYTHON_LDFLAGS by hand.
+ " "$LINENO" 5
+ fi
+ fi
+ { $as_echo "$as_me:${as_lineno-$LINENO}: result: $PYTHON_LDFLAGS" >&5
+$as_echo "$PYTHON_LDFLAGS" >&6; }
+
+
+ #
+ # Check for site packages
+ #
+ { $as_echo "$as_me:${as_lineno-$LINENO}: checking for Python site-packages path" >&5
+$as_echo_n "checking for Python site-packages path... " >&6; }
+ if test -z "$PYTHON_SITE_PKG"; then
+ PYTHON_SITE_PKG=`$PYTHON -c "import distutils.sysconfig; \
+ print (distutils.sysconfig.get_python_lib(0,0));"`
+ fi
+ { $as_echo "$as_me:${as_lineno-$LINENO}: result: $PYTHON_SITE_PKG" >&5
+$as_echo "$PYTHON_SITE_PKG" >&6; }
+
+
+ #
+ # libraries which must be linked in when embedding
+ #
+ { $as_echo "$as_me:${as_lineno-$LINENO}: checking python extra libraries" >&5
+$as_echo_n "checking python extra libraries... " >&6; }
+ if test -z "$PYTHON_EXTRA_LIBS"; then
+ PYTHON_EXTRA_LIBS=`$PYTHON -c "import distutils.sysconfig; \
+ conf = distutils.sysconfig.get_config_var; \
+ print (conf('LIBS') + ' ' + conf('SYSLIBS'))"`
+ fi
+ { $as_echo "$as_me:${as_lineno-$LINENO}: result: $PYTHON_EXTRA_LIBS" >&5
+$as_echo "$PYTHON_EXTRA_LIBS" >&6; }
+
+
+ #
+ # linking flags needed when embedding
+ #
+ { $as_echo "$as_me:${as_lineno-$LINENO}: checking python extra linking flags" >&5
+$as_echo_n "checking python extra linking flags... " >&6; }
+ if test -z "$PYTHON_EXTRA_LDFLAGS"; then
+ PYTHON_EXTRA_LDFLAGS=`$PYTHON -c "import distutils.sysconfig; \
+ conf = distutils.sysconfig.get_config_var; \
+ print (conf('LINKFORSHARED'))"`
+ fi
+ { $as_echo "$as_me:${as_lineno-$LINENO}: result: $PYTHON_EXTRA_LDFLAGS" >&5
+$as_echo "$PYTHON_EXTRA_LDFLAGS" >&6; }
+
+
+ #
+ # final check to see if everything compiles alright
+ #
+ { $as_echo "$as_me:${as_lineno-$LINENO}: checking consistency of all components of python development environment" >&5
+$as_echo_n "checking consistency of all components of python development environment... " >&6; }
+ # save current global flags
+ ac_save_LIBS="$LIBS"
+ ac_save_CPPFLAGS="$CPPFLAGS"
+ LIBS="$ac_save_LIBS $PYTHON_LDFLAGS $PYTHON_EXTRA_LDFLAGS $PYTHON_EXTRA_LIBS"
+ CPPFLAGS="$ac_save_CPPFLAGS $PYTHON_CPPFLAGS"
+ ac_ext=c
+ac_cpp='$CPP $CPPFLAGS'
+ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5'
+ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5'
+ac_compiler_gnu=$ac_cv_c_compiler_gnu
+
+ cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h. */
+
+ #include <Python.h>
+int
+main ()
+{
+Py_Initialize();
+ ;
+ return 0;
+}
+
+_ACEOF
+if ac_fn_c_try_link "$LINENO"; then :
+ pythonexists=yes
+else
+ pythonexists=no
+fi
+rm -f core conftest.err conftest.$ac_objext \
+ conftest$ac_exeext conftest.$ac_ext
+ ac_ext=c
+ac_cpp='$CPP $CPPFLAGS'
+ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5'
+ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5'
+ac_compiler_gnu=$ac_cv_c_compiler_gnu
+
+ # turn back to default flags
+ CPPFLAGS="$ac_save_CPPFLAGS"
+ LIBS="$ac_save_LIBS"
+
+ { $as_echo "$as_me:${as_lineno-$LINENO}: result: $pythonexists" >&5
+$as_echo "$pythonexists" >&6; }
+
+ if test ! "x$pythonexists" = "xyes"; then
+ { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING:
+ Could not link test program to Python. Maybe the main Python library has been
+ installed in some non-standard library path. If so, pass it to configure,
+ via the LDFLAGS environment variable.
+ Example: ./configure LDFLAGS=\"-L/usr/non-standard-path/python/lib\"
+ ============================================================================
+ You probably have to install the development version of the Python package
+ for your distribution. The exact name of this package varies among them.
+ ============================================================================
+ " >&5
+$as_echo "$as_me: WARNING:
+ Could not link test program to Python. Maybe the main Python library has been
+ installed in some non-standard library path. If so, pass it to configure,
+ via the LDFLAGS environment variable.
+ Example: ./configure LDFLAGS=\"-L/usr/non-standard-path/python/lib\"
+ ============================================================================
+ You probably have to install the development version of the Python package
+ for your distribution. The exact name of this package varies among them.
+ ============================================================================
+ " >&2;}
+ PYTHON_VERSION=""
+ fi
+
+ #
+ # all done!
+ #
+
+ if test "$PYTHON_VERSION"; then
+ PYTHONS="$(echo $PYTHONS $PYTHON)"
+ PYTHON_VERSIONS="$(echo $PYTHON_VERSIONS $PYTHON_VERSION)"
+ fi
+ fi
+
+ if test "$found_py" = "1" -o "$found_py3" = "1"; then
+ # Reset everything, so that we can look for another Python.
+ unset PYTHON
+ unset PYTHON_VERSION
+ unset PYTHON_CPPFLAGS
+ unset PYTHON_LDFLAGS
+ unset PYTHON_SITE_PKG
+ unset PYTHON_EXTRA_LIBS
+ unset PYTHON_EXTRA_LDFLAGS
+ unset ac_cv_path_PYTHON
+ unset am_cv_pathless_PYTHON
+ unset am_cv_python_version
+ unset am_cv_python_platform
+ unset am_cv_python_pythondir
+ unset am_cv_python_pyexecdir
+
+
+
+
+
+
+ if test -n "$PYTHON"; then
+ # If the user set $PYTHON, use it and don't search something else.
+ { $as_echo "$as_me:${as_lineno-$LINENO}: checking whether $PYTHON version is >= 3.4" >&5
+$as_echo_n "checking whether $PYTHON version is >= 3.4... " >&6; }
+ prog="import sys
+# split strings by '.' and convert to numeric. Append some zeros
+# because we need at least 4 digits for the hex conversion.
+# map returns an iterator in Python 3.0 and a list in 2.x
+minver = list(map(int, '3.4'.split('.'))) + [0, 0, 0]
+minverhex = 0
+# xrange is not present in Python 3.0 and range returns an iterator
+for i in list(range(0, 4)): minverhex = (minverhex << 8) + minver[i]
+sys.exit(sys.hexversion < minverhex)"
+ if { echo "$as_me:$LINENO: $PYTHON -c "$prog"" >&5
+ ($PYTHON -c "$prog") >&5 2>&5
+ ac_status=$?
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); }; then :
+ { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5
+$as_echo "yes" >&6; }
+else
+ { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
+$as_echo "no" >&6; }
+ as_fn_error $? "Python interpreter is too old" "$LINENO" 5
+fi
+ am_display_PYTHON=$PYTHON
+ else
+ # Otherwise, try each interpreter until we find one that satisfies
+ # VERSION.
+ { $as_echo "$as_me:${as_lineno-$LINENO}: checking for a Python interpreter with version >= 3.4" >&5
+$as_echo_n "checking for a Python interpreter with version >= 3.4... " >&6; }
+if ${am_cv_pathless_PYTHON+:} false; then :
+ $as_echo_n "(cached) " >&6
+else
+
+ for am_cv_pathless_PYTHON in python python2 python3 python3.3 python3.2 python3.1 python3.0 python2.7 python2.6 python2.5 python2.4 python2.3 python2.2 python2.1 python2.0 none; do
+ test "$am_cv_pathless_PYTHON" = none && break
+ prog="import sys
+# split strings by '.' and convert to numeric. Append some zeros
+# because we need at least 4 digits for the hex conversion.
+# map returns an iterator in Python 3.0 and a list in 2.x
+minver = list(map(int, '3.4'.split('.'))) + [0, 0, 0]
+minverhex = 0
+# xrange is not present in Python 3.0 and range returns an iterator
+for i in list(range(0, 4)): minverhex = (minverhex << 8) + minver[i]
+sys.exit(sys.hexversion < minverhex)"
+ if { echo "$as_me:$LINENO: $am_cv_pathless_PYTHON -c "$prog"" >&5
+ ($am_cv_pathless_PYTHON -c "$prog") >&5 2>&5
+ ac_status=$?
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); }; then :
+ break
+fi
+ done
+fi
+{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $am_cv_pathless_PYTHON" >&5
+$as_echo "$am_cv_pathless_PYTHON" >&6; }
+ # Set $PYTHON to the absolute path of $am_cv_pathless_PYTHON.
+ if test "$am_cv_pathless_PYTHON" = none; then
+ PYTHON=:
+ else
+ # Extract the first word of "$am_cv_pathless_PYTHON", so it can be a program name with args.
+set dummy $am_cv_pathless_PYTHON; ac_word=$2
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5
+$as_echo_n "checking for $ac_word... " >&6; }
+if ${ac_cv_path_PYTHON+:} false; then :
+ $as_echo_n "(cached) " >&6
+else
+ case $PYTHON in
+ [\\/]* | ?:[\\/]*)
+ ac_cv_path_PYTHON="$PYTHON" # Let the user override the test with a path.
+ ;;
+ *)
+ as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
+for as_dir in $PATH
+do
+ IFS=$as_save_IFS
+ test -z "$as_dir" && as_dir=.
+ for ac_exec_ext in '' $ac_executable_extensions; do
+ if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then
+ ac_cv_path_PYTHON="$as_dir/$ac_word$ac_exec_ext"
+ $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5
+ break 2
+ fi
+done
+ done
+IFS=$as_save_IFS
+
+ ;;
+esac
+fi
+PYTHON=$ac_cv_path_PYTHON
+if test -n "$PYTHON"; then
+ { $as_echo "$as_me:${as_lineno-$LINENO}: result: $PYTHON" >&5
+$as_echo "$PYTHON" >&6; }
+else
+ { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
+$as_echo "no" >&6; }
+fi
+
+
+ fi
+ am_display_PYTHON=$am_cv_pathless_PYTHON
+ fi
+
+
+ if test "$PYTHON" = :; then
+ as_fn_error $? "no suitable Python interpreter found" "$LINENO" 5
+ else
+
+
+ { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $am_display_PYTHON version" >&5
+$as_echo_n "checking for $am_display_PYTHON version... " >&6; }
+if ${am_cv_python_version+:} false; then :
+ $as_echo_n "(cached) " >&6
+else
+ am_cv_python_version=`$PYTHON -c "import sys; sys.stdout.write(sys.version[:3])"`
+fi
+{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $am_cv_python_version" >&5
+$as_echo "$am_cv_python_version" >&6; }
+ PYTHON_VERSION=$am_cv_python_version
+
+
+
+ PYTHON_PREFIX='${prefix}'
+
+ PYTHON_EXEC_PREFIX='${exec_prefix}'
+
+
+
+ { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $am_display_PYTHON platform" >&5
+$as_echo_n "checking for $am_display_PYTHON platform... " >&6; }
+if ${am_cv_python_platform+:} false; then :
+ $as_echo_n "(cached) " >&6
+else
+ am_cv_python_platform=`$PYTHON -c "import sys; sys.stdout.write(sys.platform)"`
+fi
+{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $am_cv_python_platform" >&5
+$as_echo "$am_cv_python_platform" >&6; }
+ PYTHON_PLATFORM=$am_cv_python_platform
+
+
+ # Just factor out some code duplication.
+ am_python_setup_sysconfig="\
+import sys
+# Prefer sysconfig over distutils.sysconfig, for better compatibility
+# with python 3.x. See automake bug#10227.
+try:
+ import sysconfig
+except ImportError:
+ can_use_sysconfig = 0
+else:
+ can_use_sysconfig = 1
+# Can't use sysconfig in CPython 2.7, since it's broken in virtualenvs:
+# <https://github.com/pypa/virtualenv/issues/118>
+try:
+ from platform import python_implementation
+ if python_implementation() == 'CPython' and sys.version[:3] == '2.7':
+ can_use_sysconfig = 0
+except ImportError:
+ pass"
+
+
+ { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $am_display_PYTHON script directory" >&5
+$as_echo_n "checking for $am_display_PYTHON script directory... " >&6; }
+if ${am_cv_python_pythondir+:} false; then :
+ $as_echo_n "(cached) " >&6
+else
+ if test "x$prefix" = xNONE
+ then
+ am_py_prefix=$ac_default_prefix
+ else
+ am_py_prefix=$prefix
+ fi
+ am_cv_python_pythondir=`$PYTHON -c "
+$am_python_setup_sysconfig
+if can_use_sysconfig:
+ sitedir = sysconfig.get_path('purelib', vars={'base':'$am_py_prefix'})
+else:
+ from distutils import sysconfig
+ sitedir = sysconfig.get_python_lib(0, 0, prefix='$am_py_prefix')
+sys.stdout.write(sitedir)"`
+ case $am_cv_python_pythondir in
+ $am_py_prefix*)
+ am__strip_prefix=`echo "$am_py_prefix" | sed 's|.|.|g'`
+ am_cv_python_pythondir=`echo "$am_cv_python_pythondir" | sed "s,^$am__strip_prefix,$PYTHON_PREFIX,"`
+ ;;
+ *)
+ case $am_py_prefix in
+ /usr|/System*) ;;
+ *)
+ am_cv_python_pythondir=$PYTHON_PREFIX/lib/python$PYTHON_VERSION/site-packages
+ ;;
+ esac
+ ;;
+ esac
+
+fi
+{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $am_cv_python_pythondir" >&5
+$as_echo "$am_cv_python_pythondir" >&6; }
+ pythondir=$am_cv_python_pythondir
+
+
+
+ pkgpythondir=\${pythondir}/$PACKAGE
+
+
+ { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $am_display_PYTHON extension module directory" >&5
+$as_echo_n "checking for $am_display_PYTHON extension module directory... " >&6; }
+if ${am_cv_python_pyexecdir+:} false; then :
+ $as_echo_n "(cached) " >&6
+else
+ if test "x$exec_prefix" = xNONE
+ then
+ am_py_exec_prefix=$am_py_prefix
+ else
+ am_py_exec_prefix=$exec_prefix
+ fi
+ am_cv_python_pyexecdir=`$PYTHON -c "
+$am_python_setup_sysconfig
+if can_use_sysconfig:
+ sitedir = sysconfig.get_path('platlib', vars={'platbase':'$am_py_prefix'})
+else:
+ from distutils import sysconfig
+ sitedir = sysconfig.get_python_lib(1, 0, prefix='$am_py_prefix')
+sys.stdout.write(sitedir)"`
+ case $am_cv_python_pyexecdir in
+ $am_py_exec_prefix*)
+ am__strip_prefix=`echo "$am_py_exec_prefix" | sed 's|.|.|g'`
+ am_cv_python_pyexecdir=`echo "$am_cv_python_pyexecdir" | sed "s,^$am__strip_prefix,$PYTHON_EXEC_PREFIX,"`
+ ;;
+ *)
+ case $am_py_exec_prefix in
+ /usr|/System*) ;;
+ *)
+ am_cv_python_pyexecdir=$PYTHON_EXEC_PREFIX/lib/python$PYTHON_VERSION/site-packages
+ ;;
+ esac
+ ;;
+ esac
+
+fi
+{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $am_cv_python_pyexecdir" >&5
+$as_echo "$am_cv_python_pyexecdir" >&6; }
+ pyexecdir=$am_cv_python_pyexecdir
+
+
+
+ pkgpyexecdir=\${pyexecdir}/$PACKAGE
+
+
+
+ fi
+
+
+
+ #
+ # Allow the use of a (user set) custom python version
+ #
+
+
+ # Extract the first word of "python[$PYTHON_VERSION]", so it can be a program name with args.
+set dummy python$PYTHON_VERSION; ac_word=$2
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5
+$as_echo_n "checking for $ac_word... " >&6; }
+if ${ac_cv_path_PYTHON+:} false; then :
+ $as_echo_n "(cached) " >&6
+else
+ case $PYTHON in
+ [\\/]* | ?:[\\/]*)
+ ac_cv_path_PYTHON="$PYTHON" # Let the user override the test with a path.
+ ;;
+ *)
+ as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
+for as_dir in $PATH
+do
+ IFS=$as_save_IFS
+ test -z "$as_dir" && as_dir=.
+ for ac_exec_ext in '' $ac_executable_extensions; do
+ if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then
+ ac_cv_path_PYTHON="$as_dir/$ac_word$ac_exec_ext"
+ $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5
+ break 2
+ fi
+done
+ done
+IFS=$as_save_IFS
+
+ ;;
+esac
+fi
+PYTHON=$ac_cv_path_PYTHON
+if test -n "$PYTHON"; then
+ { $as_echo "$as_me:${as_lineno-$LINENO}: result: $PYTHON" >&5
+$as_echo "$PYTHON" >&6; }
+else
+ { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
+$as_echo "no" >&6; }
+fi
+
+
+ if test -z "$PYTHON"; then
+ as_fn_error $? "Cannot find python$PYTHON_VERSION in your system path" "$LINENO" 5
+ PYTHON_VERSION=""
+ fi
+
+ #
+ # Check for a version of Python >= 2.1.0
+ #
+ { $as_echo "$as_me:${as_lineno-$LINENO}: checking for a version of Python >= '2.1.0'" >&5
+$as_echo_n "checking for a version of Python >= '2.1.0'... " >&6; }
+ ac_supports_python_ver=`$PYTHON -c "import sys; \
+ ver = sys.version.split ()[0]; \
+ print (ver >= '2.1.0')"`
+ if test "$ac_supports_python_ver" != "True"; then
+ if test -z "$PYTHON_NOVERSIONCHECK"; then
+ { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
+$as_echo "no" >&6; }
+ { { $as_echo "$as_me:${as_lineno-$LINENO}: error: in \`$ac_pwd':" >&5
+$as_echo "$as_me: error: in \`$ac_pwd':" >&2;}
+as_fn_error $? "
+This version of the AC_PYTHON_DEVEL macro
+doesn't work properly with versions of Python before
+2.1.0. You may need to re-run configure, setting the
+variables PYTHON_CPPFLAGS, PYTHON_LDFLAGS, PYTHON_SITE_PKG,
+PYTHON_EXTRA_LIBS and PYTHON_EXTRA_LDFLAGS by hand.
+Moreover, to disable this check, set PYTHON_NOVERSIONCHECK
+to something else than an empty string.
+
+See \`config.log' for more details" "$LINENO" 5; }
+ else
+ { $as_echo "$as_me:${as_lineno-$LINENO}: result: skip at user request" >&5
+$as_echo "skip at user request" >&6; }
+ fi
+ else
+ { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5
+$as_echo "yes" >&6; }
+ fi
+
+ #
+ # if the macro parameter ``version'' is set, honour it
+ #
+ if test -n ""; then
+ { $as_echo "$as_me:${as_lineno-$LINENO}: checking for a version of Python " >&5
+$as_echo_n "checking for a version of Python ... " >&6; }
+ ac_supports_python_ver=`$PYTHON -c "import sys; \
+ ver = sys.version.split ()[0]; \
+ print (ver )"`
+ if test "$ac_supports_python_ver" = "True"; then
+ { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5
+$as_echo "yes" >&6; }
+ else
+ { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
+$as_echo "no" >&6; }
+ as_fn_error $? "this package requires Python .
+If you have it installed, but it isn't the default Python
+interpreter in your system path, please pass the PYTHON_VERSION
+variable to configure. See \`\`configure --help'' for reference.
+" "$LINENO" 5
+ PYTHON_VERSION=""
+ fi
+ fi
+
+ #
+ # Check if you have distutils, else fail
+ #
+ { $as_echo "$as_me:${as_lineno-$LINENO}: checking for the distutils Python package" >&5
+$as_echo_n "checking for the distutils Python package... " >&6; }
+ ac_distutils_result=`$PYTHON -c "import distutils" 2>&1`
+ if test -z "$ac_distutils_result"; then
+ { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5
+$as_echo "yes" >&6; }
+ else
+ { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
+$as_echo "no" >&6; }
+ as_fn_error $? "cannot import Python module \"distutils\".
+Please check your Python installation. The error was:
+$ac_distutils_result" "$LINENO" 5
+ PYTHON_VERSION=""
+ fi
+
+ #
+ # Check for Python include path
+ #
+ { $as_echo "$as_me:${as_lineno-$LINENO}: checking for Python include path" >&5
+$as_echo_n "checking for Python include path... " >&6; }
+ if test -z "$PYTHON_CPPFLAGS"; then
+ python_path=`$PYTHON -c "import distutils.sysconfig; \
+ print (distutils.sysconfig.get_python_inc ());"`
+ plat_python_path=`$PYTHON -c "import distutils.sysconfig; \
+ print (distutils.sysconfig.get_python_inc (plat_specific=1));"`
+ if test -n "${python_path}"; then
+ if test "${plat_python_path}" != "${python_path}"; then
+ python_path="-I$python_path -I$plat_python_path"
+ else
+ python_path="-I$python_path"
+ fi
+ fi
+ PYTHON_CPPFLAGS=$python_path
+ fi
+ { $as_echo "$as_me:${as_lineno-$LINENO}: result: $PYTHON_CPPFLAGS" >&5
+$as_echo "$PYTHON_CPPFLAGS" >&6; }
+
+
+ #
+ # Check for Python library path
+ #
+ { $as_echo "$as_me:${as_lineno-$LINENO}: checking for Python library path" >&5
+$as_echo_n "checking for Python library path... " >&6; }
+ if test -z "$PYTHON_LDFLAGS"; then
+ # (makes two attempts to ensure we've got a version number
+ # from the interpreter)
+ ac_python_version=`cat<<EOD | $PYTHON -
+
+# join all versioning strings, on some systems
+# major/minor numbers could be in different list elements
+from distutils.sysconfig import *
+e = get_config_var('VERSION')
+if e is not None:
+ print(e)
+EOD`
+
+ if test -z "$ac_python_version"; then
+ if test -n "$PYTHON_VERSION"; then
+ ac_python_version=$PYTHON_VERSION
+ else
+ ac_python_version=`$PYTHON -c "import sys; \
+ print (sys.version[:3])"`
+ fi
+ fi
+
+ # Make the versioning information available to the compiler
+
+cat >>confdefs.h <<_ACEOF
+#define HAVE_PYTHON "$ac_python_version"
+_ACEOF
+
+
+ # First, the library directory:
+ ac_python_libdir=`cat<<EOD | $PYTHON -
+
+# There should be only one
+import distutils.sysconfig
+e = distutils.sysconfig.get_config_var('LIBDIR')
+if e is not None:
+ print (e)
+EOD`
+
+ # Now, for the library:
+ ac_python_library=`cat<<EOD | $PYTHON -
+
+import distutils.sysconfig
+c = distutils.sysconfig.get_config_vars()
+if 'LDVERSION' in c:
+ print ('python'+c['LDVERSION'])
+else:
+ print ('python'+c['VERSION'])
+EOD`
+
+ # This small piece shamelessly adapted from PostgreSQL python macro;
+ # credits goes to momjian, I think. I'd like to put the right name
+ # in the credits, if someone can point me in the right direction... ?
+ #
+ if test -n "$ac_python_libdir" -a -n "$ac_python_library"
+ then
+ # use the official shared library
+ ac_python_library=`echo "$ac_python_library" | sed "s/^lib//"`
+ PYTHON_LDFLAGS="-L$ac_python_libdir -l$ac_python_library"
+ else
+ # old way: use libpython from python_configdir
+ ac_python_libdir=`$PYTHON -c \
+ "from distutils.sysconfig import get_python_lib as f; \
+ import os; \
+ print (os.path.join(f(plat_specific=1, standard_lib=1), 'config'));"`
+ PYTHON_LDFLAGS="-L$ac_python_libdir -lpython$ac_python_version"
+ fi
+
+ if test -z "PYTHON_LDFLAGS"; then
+ as_fn_error $? "
+ Cannot determine location of your Python DSO. Please check it was installed with
+ dynamic libraries enabled, or try setting PYTHON_LDFLAGS by hand.
+ " "$LINENO" 5
+ fi
+ fi
+ { $as_echo "$as_me:${as_lineno-$LINENO}: result: $PYTHON_LDFLAGS" >&5
+$as_echo "$PYTHON_LDFLAGS" >&6; }
+
+
+ #
+ # Check for site packages
+ #
+ { $as_echo "$as_me:${as_lineno-$LINENO}: checking for Python site-packages path" >&5
+$as_echo_n "checking for Python site-packages path... " >&6; }
+ if test -z "$PYTHON_SITE_PKG"; then
+ PYTHON_SITE_PKG=`$PYTHON -c "import distutils.sysconfig; \
+ print (distutils.sysconfig.get_python_lib(0,0));"`
+ fi
+ { $as_echo "$as_me:${as_lineno-$LINENO}: result: $PYTHON_SITE_PKG" >&5
+$as_echo "$PYTHON_SITE_PKG" >&6; }
+
+
+ #
+ # libraries which must be linked in when embedding
+ #
+ { $as_echo "$as_me:${as_lineno-$LINENO}: checking python extra libraries" >&5
+$as_echo_n "checking python extra libraries... " >&6; }
+ if test -z "$PYTHON_EXTRA_LIBS"; then
+ PYTHON_EXTRA_LIBS=`$PYTHON -c "import distutils.sysconfig; \
+ conf = distutils.sysconfig.get_config_var; \
+ print (conf('LIBS') + ' ' + conf('SYSLIBS'))"`
+ fi
+ { $as_echo "$as_me:${as_lineno-$LINENO}: result: $PYTHON_EXTRA_LIBS" >&5
+$as_echo "$PYTHON_EXTRA_LIBS" >&6; }
+
+
+ #
+ # linking flags needed when embedding
+ #
+ { $as_echo "$as_me:${as_lineno-$LINENO}: checking python extra linking flags" >&5
+$as_echo_n "checking python extra linking flags... " >&6; }
+ if test -z "$PYTHON_EXTRA_LDFLAGS"; then
+ PYTHON_EXTRA_LDFLAGS=`$PYTHON -c "import distutils.sysconfig; \
+ conf = distutils.sysconfig.get_config_var; \
+ print (conf('LINKFORSHARED'))"`
+ fi
+ { $as_echo "$as_me:${as_lineno-$LINENO}: result: $PYTHON_EXTRA_LDFLAGS" >&5
+$as_echo "$PYTHON_EXTRA_LDFLAGS" >&6; }
+
+
+ #
+ # final check to see if everything compiles alright
+ #
+ { $as_echo "$as_me:${as_lineno-$LINENO}: checking consistency of all components of python development environment" >&5
+$as_echo_n "checking consistency of all components of python development environment... " >&6; }
+ # save current global flags
+ ac_save_LIBS="$LIBS"
+ ac_save_CPPFLAGS="$CPPFLAGS"
+ LIBS="$ac_save_LIBS $PYTHON_LDFLAGS $PYTHON_EXTRA_LDFLAGS $PYTHON_EXTRA_LIBS"
+ CPPFLAGS="$ac_save_CPPFLAGS $PYTHON_CPPFLAGS"
+ ac_ext=c
+ac_cpp='$CPP $CPPFLAGS'
+ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5'
+ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5'
+ac_compiler_gnu=$ac_cv_c_compiler_gnu
+
+ cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h. */
+
+ #include <Python.h>
+int
+main ()
+{
+Py_Initialize();
+ ;
+ return 0;
+}
+
+_ACEOF
+if ac_fn_c_try_link "$LINENO"; then :
+ pythonexists=yes
+else
+ pythonexists=no
+fi
+rm -f core conftest.err conftest.$ac_objext \
+ conftest$ac_exeext conftest.$ac_ext
+ ac_ext=c
+ac_cpp='$CPP $CPPFLAGS'
+ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5'
+ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5'
+ac_compiler_gnu=$ac_cv_c_compiler_gnu
+
+ # turn back to default flags
+ CPPFLAGS="$ac_save_CPPFLAGS"
+ LIBS="$ac_save_LIBS"
+
+ { $as_echo "$as_me:${as_lineno-$LINENO}: result: $pythonexists" >&5
+$as_echo "$pythonexists" >&6; }
+
+ if test ! "x$pythonexists" = "xyes"; then
+ { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING:
+ Could not link test program to Python. Maybe the main Python library has been
+ installed in some non-standard library path. If so, pass it to configure,
+ via the LDFLAGS environment variable.
+ Example: ./configure LDFLAGS=\"-L/usr/non-standard-path/python/lib\"
+ ============================================================================
+ You probably have to install the development version of the Python package
+ for your distribution. The exact name of this package varies among them.
+ ============================================================================
+ " >&5
+$as_echo "$as_me: WARNING:
+ Could not link test program to Python. Maybe the main Python library has been
+ installed in some non-standard library path. If so, pass it to configure,
+ via the LDFLAGS environment variable.
+ Example: ./configure LDFLAGS=\"-L/usr/non-standard-path/python/lib\"
+ ============================================================================
+ You probably have to install the development version of the Python package
+ for your distribution. The exact name of this package varies among them.
+ ============================================================================
+ " >&2;}
+ PYTHON_VERSION=""
+ fi
+
+ #
+ # all done!
+ #
+
+ if test "$PYTHON_VERSION"; then
+ PYTHONS="$(echo $PYTHONS $PYTHON)"
+ PYTHON_VERSIONS="$(echo $PYTHON_VERSIONS $PYTHON_VERSION)"
+ fi
+ fi
+
+ if test "$PYTHON_VERSIONS"; then
+ enabled_languages_v=$(echo $enabled_languages | sed "s/python\([23]\)\?/python ($PYTHON_VERSIONS)/")
+ enabled_languages=$(echo $enabled_languages | sed "s/python\([23]\)\?/python/")
+ else
+ if test "$explicit_languages" = "1"; then
+ as_fn_error $? "
+***
+*** Please install the python development packages.
+***" "$LINENO" 5
+ else
+ enabled_languages=$(echo $enabled_languages | sed 's/python//')
+ fi
+ fi
+
+ PYTHONS=$PYTHONS
+
+ PYTHON_VERSIONS=$PYTHON_VERSIONS
+
+ fi
+fi
+
+ENABLED_LANGUAGES=$enabled_languages
+
+
#
# Provide information about the build.
#
-BUILD_REVISION="107bff7"
+BUILD_REVISION="e7ab753"
cat >>confdefs.h <<_ACEOF
@@ -17598,7 +20639,7 @@ _ACEOF
BUILD_FILEVERSION=`echo "$PACKAGE_VERSION"|sed 's/\([0-9.]*\).*/\1./;s/\./,/g'`
-BUILD_FILEVERSION="${BUILD_FILEVERSION}4219"
+BUILD_FILEVERSION="${BUILD_FILEVERSION}59307"
# Check whether --enable-build-timestamp was given.
@@ -18090,6 +21131,71 @@ fi
# Checks for compiler features.
if test "$GCC" = yes; then
CFLAGS="$CFLAGS -Wall -Wcast-align -Wshadow -Wstrict-prototypes"
+ if test "$USE_MAINTAINER_MODE" = "yes"; then
+ CFLAGS="$CFLAGS -Wformat -Wno-format-y2k -Wformat-security"
+
+ # If -Wno-missing-field-initializers is supported we can enable a
+ # a bunch of really useful warnings.
+ { $as_echo "$as_me:${as_lineno-$LINENO}: checking if gcc supports -Wno-missing-field-initializers" >&5
+$as_echo_n "checking if gcc supports -Wno-missing-field-initializers... " >&6; }
+ _gcc_cflags_save=$CFLAGS
+ CFLAGS="-Wno-missing-field-initializers"
+ cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h. */
+
+int
+main ()
+{
+
+ ;
+ return 0;
+}
+_ACEOF
+if ac_fn_c_try_compile "$LINENO"; then :
+ _gcc_wopt=yes
+else
+ _gcc_wopt=no
+fi
+rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
+ { $as_echo "$as_me:${as_lineno-$LINENO}: result: $_gcc_wopt" >&5
+$as_echo "$_gcc_wopt" >&6; }
+ CFLAGS=$_gcc_cflags_save;
+ if test x"$_gcc_wopt" = xyes ; then
+ CFLAGS="$CFLAGS -W -Wextra -Wbad-function-cast"
+ CFLAGS="$CFLAGS -Wwrite-strings"
+ CFLAGS="$CFLAGS -Wdeclaration-after-statement"
+ CFLAGS="$CFLAGS -Wno-missing-field-initializers"
+ CFLAGS="$CFLAGS -Wno-sign-compare"
+ fi
+
+ { $as_echo "$as_me:${as_lineno-$LINENO}: checking if gcc supports -Wpointer-arith" >&5
+$as_echo_n "checking if gcc supports -Wpointer-arith... " >&6; }
+ _gcc_cflags_save=$CFLAGS
+ CFLAGS="-Wpointer-arith"
+ cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h. */
+
+int
+main ()
+{
+
+ ;
+ return 0;
+}
+_ACEOF
+if ac_fn_c_try_compile "$LINENO"; then :
+ _gcc_wopt=yes
+else
+ _gcc_wopt=no
+fi
+rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
+ { $as_echo "$as_me:${as_lineno-$LINENO}: result: $_gcc_wopt" >&5
+$as_echo "$_gcc_wopt" >&6; }
+ CFLAGS=$_gcc_cflags_save;
+ if test x"$_gcc_wopt" = xyes ; then
+ CFLAGS="$CFLAGS -Wpointer-arith"
+ fi
+ fi
if test "$have_w32_system" = yes; then
CFLAGS="$CFLAGS -mms-bitfields"
fi
@@ -19163,6 +22269,8 @@ fi
GPGME_CONFIG_LIBS="-lgpgme"
GPGME_CONFIG_CFLAGS=""
GPGME_CONFIG_HOST="$host"
+GPGME_CONFIG_AVAIL_LANG="$enabled_languages"
+
@@ -19200,7 +22308,6 @@ emacs_local_vars_read_only='buffer-read-only: t'
emacs_local_vars_end='End:'
-
# Last check.
die=no
if test "$have_gpg_error" = "no"; then
@@ -19254,8 +22361,34 @@ ac_config_files="$ac_config_files Makefile src/Makefile tests/Makefile tests/gpg
ac_config_files="$ac_config_files src/gpgme-config"
+ac_config_files="$ac_config_files lang/cpp/Makefile lang/cpp/src/Makefile"
+
+ac_config_files="$ac_config_files lang/cpp/src/GpgmeppConfig.cmake.in"
+
+ac_config_files="$ac_config_files lang/cpp/src/GpgmeppConfigVersion.cmake"
+
+ac_config_files="$ac_config_files lang/cpp/src/gpgmepp_version.h"
+
+ac_config_files="$ac_config_files lang/qt/Makefile lang/qt/src/Makefile"
+
+ac_config_files="$ac_config_files lang/qt/src/QGpgmeConfig.cmake.in"
+
+ac_config_files="$ac_config_files lang/qt/src/QGpgmeConfigVersion.cmake"
+
+ac_config_files="$ac_config_files lang/qt/tests/Makefile"
+
+ac_config_files="$ac_config_files lang/qt/src/qgpgme_version.h"
+
ac_config_files="$ac_config_files lang/Makefile lang/cl/Makefile lang/cl/gpgme.asd"
+if test -z "$HAVE_DOXYGEN_TRUE"; then :
+ ac_config_files="$ac_config_files lang/qt/doc/Doxyfile"
+
+fi
+ac_config_files="$ac_config_files lang/qt/doc/Makefile"
+
+ac_config_files="$ac_config_files lang/python/Makefile lang/python/setup.py lang/python/pyme/version.py lang/python/tests/Makefile"
+
cat >confcache <<\_ACEOF
# This file is a shell script that caches the results of configure
# tests run on this system so they can be shared between configure
@@ -19429,14 +22562,14 @@ if test -z "${BUILD_W32_GLIB_TRUE}" && test -z "${BUILD_W32_GLIB_FALSE}"; then
as_fn_error $? "conditional \"BUILD_W32_GLIB\" was never defined.
Usually this means the macro was only invoked conditionally." "$LINENO" 5
fi
-if test -z "${BUILD_W32_QT_TRUE}" && test -z "${BUILD_W32_QT_FALSE}"; then
- as_fn_error $? "conditional \"BUILD_W32_QT\" was never defined.
-Usually this means the macro was only invoked conditionally." "$LINENO" 5
-fi
if test -z "${HAVE_PTHREAD_TRUE}" && test -z "${HAVE_PTHREAD_FALSE}"; then
as_fn_error $? "conditional \"HAVE_PTHREAD\" was never defined.
Usually this means the macro was only invoked conditionally." "$LINENO" 5
fi
+if test -z "${HAVE_DOXYGEN_TRUE}" && test -z "${HAVE_DOXYGEN_FALSE}"; then
+ as_fn_error $? "conditional \"HAVE_DOXYGEN\" was never defined.
+Usually this means the macro was only invoked conditionally." "$LINENO" 5
+fi
if test -z "${RUN_GPGCONF_TESTS_TRUE}" && test -z "${RUN_GPGCONF_TESTS_FALSE}"; then
as_fn_error $? "conditional \"RUN_GPGCONF_TESTS\" was never defined.
Usually this means the macro was only invoked conditionally." "$LINENO" 5
@@ -19858,7 +22991,7 @@ cat >>$CONFIG_STATUS <<\_ACEOF || ac_write_fail=1
# report actual input values of CONFIG_FILES etc. instead of their
# values after options handling.
ac_log="
-This file was extended by gpgme $as_me 1.6.0, which was
+This file was extended by gpgme $as_me 1.7.0, which was
generated by GNU Autoconf 2.69. Invocation command line was
CONFIG_FILES = $CONFIG_FILES
@@ -19924,7 +23057,7 @@ _ACEOF
cat >>$CONFIG_STATUS <<_ACEOF || ac_write_fail=1
ac_cs_config="`$as_echo "$ac_configure_args" | sed 's/^ //; s/[\\""\`\$]/\\\\&/g'`"
ac_cs_version="\\
-gpgme config.status 1.6.0
+gpgme config.status 1.7.0
configured by $0, generated by GNU Autoconf 2.69,
with options \\"\$ac_cs_config\\"
@@ -20529,9 +23662,26 @@ do
"src/versioninfo.rc") CONFIG_FILES="$CONFIG_FILES src/versioninfo.rc" ;;
"src/gpgme.h") CONFIG_FILES="$CONFIG_FILES src/gpgme.h" ;;
"src/gpgme-config") CONFIG_FILES="$CONFIG_FILES src/gpgme-config" ;;
+ "lang/cpp/Makefile") CONFIG_FILES="$CONFIG_FILES lang/cpp/Makefile" ;;
+ "lang/cpp/src/Makefile") CONFIG_FILES="$CONFIG_FILES lang/cpp/src/Makefile" ;;
+ "lang/cpp/src/GpgmeppConfig.cmake.in") CONFIG_FILES="$CONFIG_FILES lang/cpp/src/GpgmeppConfig.cmake.in" ;;
+ "lang/cpp/src/GpgmeppConfigVersion.cmake") CONFIG_FILES="$CONFIG_FILES lang/cpp/src/GpgmeppConfigVersion.cmake" ;;
+ "lang/cpp/src/gpgmepp_version.h") CONFIG_FILES="$CONFIG_FILES lang/cpp/src/gpgmepp_version.h" ;;
+ "lang/qt/Makefile") CONFIG_FILES="$CONFIG_FILES lang/qt/Makefile" ;;
+ "lang/qt/src/Makefile") CONFIG_FILES="$CONFIG_FILES lang/qt/src/Makefile" ;;
+ "lang/qt/src/QGpgmeConfig.cmake.in") CONFIG_FILES="$CONFIG_FILES lang/qt/src/QGpgmeConfig.cmake.in" ;;
+ "lang/qt/src/QGpgmeConfigVersion.cmake") CONFIG_FILES="$CONFIG_FILES lang/qt/src/QGpgmeConfigVersion.cmake" ;;
+ "lang/qt/tests/Makefile") CONFIG_FILES="$CONFIG_FILES lang/qt/tests/Makefile" ;;
+ "lang/qt/src/qgpgme_version.h") CONFIG_FILES="$CONFIG_FILES lang/qt/src/qgpgme_version.h" ;;
"lang/Makefile") CONFIG_FILES="$CONFIG_FILES lang/Makefile" ;;
"lang/cl/Makefile") CONFIG_FILES="$CONFIG_FILES lang/cl/Makefile" ;;
"lang/cl/gpgme.asd") CONFIG_FILES="$CONFIG_FILES lang/cl/gpgme.asd" ;;
+ "lang/qt/doc/Doxyfile") CONFIG_FILES="$CONFIG_FILES lang/qt/doc/Doxyfile" ;;
+ "lang/qt/doc/Makefile") CONFIG_FILES="$CONFIG_FILES lang/qt/doc/Makefile" ;;
+ "lang/python/Makefile") CONFIG_FILES="$CONFIG_FILES lang/python/Makefile" ;;
+ "lang/python/setup.py") CONFIG_FILES="$CONFIG_FILES lang/python/setup.py" ;;
+ "lang/python/pyme/version.py") CONFIG_FILES="$CONFIG_FILES lang/python/pyme/version.py" ;;
+ "lang/python/tests/Makefile") CONFIG_FILES="$CONFIG_FILES lang/python/tests/Makefile" ;;
*) as_fn_error $? "invalid argument: \`$ac_config_target'" "$LINENO" 5;;
esac
@@ -22216,12 +25366,14 @@ fi
echo "
GPGME v${VERSION} has been configured as follows:
- Revision: 107bff7 (4219)
- Platform: $host
+ Revision: e7ab753 (59307)
+ Platform: $host
+
+ UI Server: $uiserver
+ FD Passing: $use_descriptor_passing
+ GPGME Pthread: $have_pthread
- UI Server: $uiserver
- FD Passing: $use_descriptor_passing
- GPGME Pthread: $have_pthread
+ Language bindings: ${enabled_languages_v:-$enabled_languages}
"
if test "x${gpg_config_script_warn}" != x; then
cat <<G10EOF
diff --git a/configure.ac b/configure.ac
index 015ed46..c9d16af 100644
--- a/configure.ac
+++ b/configure.ac
@@ -28,7 +28,7 @@ min_automake_version="1.14"
# commit and push so that the git magic is able to work. See below
# for the LT versions.
m4_define(mym4_version_major, [1])
-m4_define(mym4_version_minor, [6])
+m4_define(mym4_version_minor, [7])
m4_define(mym4_version_micro, [0])
# Below is m4 magic to extract and compute the revision number, the
@@ -55,12 +55,20 @@ AC_INIT([gpgme],[mym4_full_version],[http://bugs.gnupg.org])
# (Interfaces added: AGE++)
# (Interfaces removed/changed: AGE=0)
#
-LIBGPGME_LT_CURRENT=25
+LIBGPGME_LT_CURRENT=26
# Subtract 2 from this value if you want to make the LFS transition an
# ABI break. [Note to self: Remove this comment with the next regular break.]
-LIBGPGME_LT_AGE=14
+LIBGPGME_LT_AGE=15
LIBGPGME_LT_REVISION=0
+LIBGPGMEPP_LT_CURRENT=6
+LIBGPGMEPP_LT_AGE=0
+LIBGPGMEPP_LT_REVISION=1
+
+LIBQGPGME_LT_CURRENT=6
+LIBQGPGME_LT_AGE=0
+LIBQGPGME_LT_REVISION=1
+
# If the API is changed in an incompatible way: increment the next counter.
GPGME_CONFIG_API_VERSION=1
##############################################
@@ -104,6 +112,12 @@ AC_CHECK_PROGS(GITLOG_TO_CHANGELOG, gitlog-to-changelog, [gitlog-to-changelog])
AC_SUBST(LIBGPGME_LT_CURRENT)
AC_SUBST(LIBGPGME_LT_AGE)
AC_SUBST(LIBGPGME_LT_REVISION)
+AC_SUBST(LIBGPGMEPP_LT_CURRENT)
+AC_SUBST(LIBGPGMEPP_LT_AGE)
+AC_SUBST(LIBGPGMEPP_LT_REVISION)
+AC_SUBST(LIBQGPGME_LT_CURRENT)
+AC_SUBST(LIBQGPGME_LT_AGE)
+AC_SUBST(LIBQGPGME_LT_REVISION)
AC_SUBST(PACKAGE)
AC_SUBST(VERSION)
@@ -113,6 +127,22 @@ VERSION_NUMBER=m4_esyscmd(printf "0x%02x%02x%02x" mym4_version_major \
mym4_version_minor mym4_version_micro)
AC_SUBST(VERSION_NUMBER)
+# We need to compile and run a program on the build machine. A
+# comment in libgpg-error says that the AC_PROG_CC_FOR_BUILD macro in
+# the AC archive is broken for autoconf 2.57. Given that there is no
+# newer version of that macro, we assume that it is also broken for
+# autoconf 2.61 and thus we use a simple but usually sufficient
+# approach.
+AC_MSG_CHECKING(for cc for build)
+if test "$cross_compiling" = "yes"; then
+ CC_FOR_BUILD="${CC_FOR_BUILD-cc}"
+else
+ CC_FOR_BUILD="${CC_FOR_BUILD-$CC}"
+fi
+AC_MSG_RESULT($CC_FOR_BUILD)
+AC_ARG_VAR(CC_FOR_BUILD,[build system C compiler])
+
+
# Don't default to build static libs.
LT_PREREQ([2.2.6])
LT_INIT([win32-dll disable-static])
@@ -146,6 +176,8 @@ have_w32_system=no
have_w64_system=no
build_w32_glib=no
build_w32_qt=no
+available_languages="cl cpp python python2 python3 qt"
+default_languages="cl cpp python qt"
case "${host}" in
x86_64-*mingw32*)
have_w64_system=yes
@@ -171,20 +203,9 @@ case "${host}" in
AC_ARG_ENABLE(w32-glib,
AC_HELP_STRING([--enable-w32-glib], [build GPGME Glib for W32]),
build_w32_glib=$enableval)
-
- # Check disabled, because the qt-dev packages in gpg4win do
- # not provide any support for cross compilation.
- # PKG_CHECK_MODULES(QT4_CORE, QtCore)
-
- # Use it like this:
- # ./configure --enable-w32-qt QT4_CORE_CFLAGS="..." QT4_CORE_LIBS="..."
- AC_SUBST(QT4_CORE_CFLAGS)
- AC_SUBST(QT4_CORE_LIBS)
- AC_ARG_ENABLE(w32-qt,
- AC_HELP_STRING([--enable-w32-qt], [build GPGME Qt for W32]),
- build_w32_qt=$enableval)
- ;;
+ ;;
*)
+
AC_CHECK_LIB(pthread,pthread_create,have_pthread=yes)
if test "$have_pthread" = yes; then
AC_DEFINE(HAVE_PTHREAD, ,[Define if we have pthread.])
@@ -230,7 +251,6 @@ fi
AM_CONDITIONAL(HAVE_ANDROID_SYSTEM, test "$have_android_system" = yes)
AM_CONDITIONAL(BUILD_W32_GLIB, test "$build_w32_glib" = yes)
-AM_CONDITIONAL(BUILD_W32_QT, test "$build_w32_qt" = yes)
AM_CONDITIONAL(HAVE_PTHREAD, test "$have_pthread" = "yes")
@@ -246,6 +266,197 @@ if test x$fixed_search_path != x ; then
fi
+# Note: You need to declare all possible langauges also in
+# lang/Makefile.am's DIST_SUBDIRS.
+AC_ARG_ENABLE([languages],
+ AC_HELP_STRING([--enable-languages=languages],
+ [enable only specific language bindings]),
+ [enabled_languages=`echo $enableval | \
+ tr ',:' ' ' | tr '[A-Z]' '[a-z]' | \
+ sed 's/c++/cpp/'`],
+ [enabled_languages="maybe"])
+if test "x$enabled_languages" = "x" \
+ -o "$enabled_languages" = "no"; then
+ enabled_languages=
+fi
+
+# If languages are explicitly set missing requirements
+# for the languages are treated as errors otherwise
+# there will be a warning.
+explicit_languages=1
+if test "x$enabled_languages" = "xmaybe"; then
+ explicit_languages=0
+ enabled_languages="$default_languages"
+fi
+
+for language in $enabled_languages; do
+ LIST_MEMBER($language, $available_languages)
+ if test "$found" = "0"; then
+ AC_MSG_ERROR([unsupported language binding specified])
+ fi
+done
+
+
+
+# Enable C++ 11 if cpp language is requested
+LIST_MEMBER("cpp", $enabled_languages)
+if test "$found" = "1"; then
+ AX_CXX_COMPILE_STDCXX(11, noext, optional)
+ if test "$HAVE_CXX11" != "1"; then
+ if test "$explicit_languages" = "1"; then
+ AC_MSG_ERROR([[
+***
+*** A compiler with c++11 support is required for the c++ binding.
+***]])
+ else
+ enabled_languages=$(echo $enabled_languages | sed 's/cpp//')
+ enabled_languages=$(echo $enabled_languages | sed 's/qt//')
+ AC_MSG_WARN([[
+***
+*** No c++11 support detected. C++ and Qt bindings will be disabled.
+***]])
+ fi
+ fi
+fi
+
+# Check that if qt is enabled cpp also is enabled
+LIST_MEMBER("qt", $enabled_languages)
+if test "$found" = "1"; then
+ # We need to ensure that in the langauge order qt comes after cpp
+ # so we remove qt first and explicitly add it as last list member.
+ enabled_languages=$(echo $enabled_languages | sed 's/qt//')
+ LIST_MEMBER("cpp", $enabled_languages)
+ if test "$found" = "0"; then
+ AC_MSG_ERROR([[
+***
+*** Qt language binding depends on cpp binding.
+***]])
+ fi
+ FIND_QT
+ if test "$have_qt5_libs" != "yes"; then
+ if test "$explicit_languages" = "1"; then
+ AC_MSG_ERROR([[
+***
+*** Qt5 (Qt5Core) is required for Qt binding.
+***]])
+ else
+ AC_MSG_WARN([[
+***
+*** Qt5 (Qt5Core) not found Qt Binding will be disabled.
+***]])
+ fi
+ else
+ enabled_languages=`echo $enabled_languages qt`
+
+ AC_CHECK_PROGS([DOXYGEN], [doxygen])
+ if test -z "$DOXYGEN";
+ # This is not highlighted becase it's not really important.
+ then AC_MSG_WARN([Doxygen not found - Qt binding doc will not be built.])
+ fi
+ AC_CHECK_PROGS([GRAPHVIZ], [dot])
+ if test -z "$GRAPHVIZ";
+ then AC_MSG_WARN([Graphviz not found - Qt binding doc will not have diagrams.])
+ fi
+ fi
+fi
+AM_CONDITIONAL([HAVE_DOXYGEN],
+ [test -n "$DOXYGEN"])
+if test -n "$GRAPHVIZ"; then
+ HAVE_DOT="YES"
+else
+ HAVE_DOT="NO"
+fi
+AC_SUBST(HAVE_DOT)
+
+# Python bindings.
+LIST_MEMBER("python2", $enabled_languages)
+found_py2=$found
+LIST_MEMBER("python3", $enabled_languages)
+found_py3=$found
+LIST_MEMBER("python", $enabled_languages)
+found_py=$found
+if test "$found_py" = "1" -o "$found_py2" = "1" -o "$found_py3" = "1"; then
+ AX_PKG_SWIG
+ if test -z "$SWIG"; then
+ if test "$explicit_languages" = "1"; then
+ AC_MSG_ERROR([[
+***
+*** You need SWIG to build the Python bindings.
+***]])
+ else
+ enabled_languages=$(echo $enabled_languages | sed 's/python//')
+ fi
+ else
+ # Reset all the stuff, just to be sure.
+ PYTHONS=
+ PYTHON_VERSIONS=
+ unset PYTHON
+ unset PYTHON_VERSION
+ unset PYTHON_CPPFLAGS
+ unset PYTHON_LDFLAGS
+ unset PYTHON_SITE_PKG
+ unset PYTHON_EXTRA_LIBS
+ unset PYTHON_EXTRA_LDFLAGS
+ unset ac_cv_path_PYTHON
+ unset am_cv_pathless_PYTHON
+ unset am_cv_python_version
+ unset am_cv_python_platform
+ unset am_cv_python_pythondir
+ unset am_cv_python_pyexecdir
+
+ if test "$found_py" = "1" -o "$found_py2" = "1"; then
+ AM_PATH_PYTHON([2.7])
+ AX_PYTHON_DEVEL
+ if test "$PYTHON_VERSION"; then
+ PYTHONS="$(echo $PYTHONS $PYTHON)"
+ PYTHON_VERSIONS="$(echo $PYTHON_VERSIONS $PYTHON_VERSION)"
+ fi
+ fi
+
+ if test "$found_py" = "1" -o "$found_py3" = "1"; then
+ # Reset everything, so that we can look for another Python.
+ unset PYTHON
+ unset PYTHON_VERSION
+ unset PYTHON_CPPFLAGS
+ unset PYTHON_LDFLAGS
+ unset PYTHON_SITE_PKG
+ unset PYTHON_EXTRA_LIBS
+ unset PYTHON_EXTRA_LDFLAGS
+ unset ac_cv_path_PYTHON
+ unset am_cv_pathless_PYTHON
+ unset am_cv_python_version
+ unset am_cv_python_platform
+ unset am_cv_python_pythondir
+ unset am_cv_python_pyexecdir
+ AM_PATH_PYTHON([3.4])
+ AX_PYTHON_DEVEL
+ if test "$PYTHON_VERSION"; then
+ PYTHONS="$(echo $PYTHONS $PYTHON)"
+ PYTHON_VERSIONS="$(echo $PYTHON_VERSIONS $PYTHON_VERSION)"
+ fi
+ fi
+
+ if test "$PYTHON_VERSIONS"; then
+ enabled_languages_v=$(echo $enabled_languages | sed "s/python\([[23]]\)\?/python ($PYTHON_VERSIONS)/")
+ enabled_languages=$(echo $enabled_languages | sed "s/python\([[23]]\)\?/python/")
+ else
+ if test "$explicit_languages" = "1"; then
+ AC_MSG_ERROR([[
+***
+*** Please install the python development packages.
+***]])
+ else
+ enabled_languages=$(echo $enabled_languages | sed 's/python//')
+ fi
+ fi
+
+ AC_SUBST(PYTHONS, $PYTHONS)
+ AC_SUBST(PYTHON_VERSIONS, $PYTHON_VERSIONS)
+ fi
+fi
+
+AC_SUBST(ENABLED_LANGUAGES, $enabled_languages)
+
#
# Provide information about the build.
#
@@ -359,6 +570,35 @@ AM_SUBST_NOTMAKE(API__SSIZE_T)
# Checks for compiler features.
if test "$GCC" = yes; then
CFLAGS="$CFLAGS -Wall -Wcast-align -Wshadow -Wstrict-prototypes"
+ if test "$USE_MAINTAINER_MODE" = "yes"; then
+ CFLAGS="$CFLAGS -Wformat -Wno-format-y2k -Wformat-security"
+
+ # If -Wno-missing-field-initializers is supported we can enable a
+ # a bunch of really useful warnings.
+ AC_MSG_CHECKING([if gcc supports -Wno-missing-field-initializers])
+ _gcc_cflags_save=$CFLAGS
+ CFLAGS="-Wno-missing-field-initializers"
+ AC_COMPILE_IFELSE([AC_LANG_PROGRAM([],[])],_gcc_wopt=yes,_gcc_wopt=no)
+ AC_MSG_RESULT($_gcc_wopt)
+ CFLAGS=$_gcc_cflags_save;
+ if test x"$_gcc_wopt" = xyes ; then
+ CFLAGS="$CFLAGS -W -Wextra -Wbad-function-cast"
+ CFLAGS="$CFLAGS -Wwrite-strings"
+ CFLAGS="$CFLAGS -Wdeclaration-after-statement"
+ CFLAGS="$CFLAGS -Wno-missing-field-initializers"
+ CFLAGS="$CFLAGS -Wno-sign-compare"
+ fi
+
+ AC_MSG_CHECKING([if gcc supports -Wpointer-arith])
+ _gcc_cflags_save=$CFLAGS
+ CFLAGS="-Wpointer-arith"
+ AC_COMPILE_IFELSE([AC_LANG_PROGRAM([],[])],_gcc_wopt=yes,_gcc_wopt=no)
+ AC_MSG_RESULT($_gcc_wopt)
+ CFLAGS=$_gcc_cflags_save;
+ if test x"$_gcc_wopt" = xyes ; then
+ CFLAGS="$CFLAGS -Wpointer-arith"
+ fi
+ fi
if test "$have_w32_system" = yes; then
CFLAGS="$CFLAGS -mms-bitfields"
fi
@@ -556,7 +796,7 @@ AH_BOTTOM([
#define GPG_ERR_ENABLE_ERRNO_MACROS 1
#define CRIGHTBLURB "Copyright (C) 2000 Werner Koch\n" \
- "Copyright (C) 2001--2015 g10 Code GmbH\n"
+ "Copyright (C) 2001--2016 g10 Code GmbH\n"
])
@@ -564,10 +804,12 @@ AH_BOTTOM([
GPGME_CONFIG_LIBS="-lgpgme"
GPGME_CONFIG_CFLAGS=""
GPGME_CONFIG_HOST="$host"
+GPGME_CONFIG_AVAIL_LANG="$enabled_languages"
AC_SUBST(GPGME_CONFIG_API_VERSION)
AC_SUBST(GPGME_CONFIG_LIBS)
AC_SUBST(GPGME_CONFIG_CFLAGS)
AC_SUBST(GPGME_CONFIG_HOST)
+AC_SUBST(GPGME_CONFIG_AVAIL_LANG)
# Frob'da Variables
LTLIBOBJS=`echo "$LIB@&t@OBJS" |
@@ -587,7 +829,6 @@ AC_SUBST(emacs_local_vars_begin, [['Local][ ][Variables:']])
AC_SUBST(emacs_local_vars_read_only, ['buffer-read-only: t'])
AC_SUBST(emacs_local_vars_end, ['End:'])
-
# Last check.
die=no
if test "$have_gpg_error" = "no"; then
@@ -632,18 +873,35 @@ AC_CONFIG_FILES(Makefile src/Makefile
src/versioninfo.rc
src/gpgme.h)
AC_CONFIG_FILES(src/gpgme-config, chmod +x src/gpgme-config)
+AC_CONFIG_FILES(lang/cpp/Makefile lang/cpp/src/Makefile)
+AC_CONFIG_FILES(lang/cpp/src/GpgmeppConfig.cmake.in)
+AC_CONFIG_FILES(lang/cpp/src/GpgmeppConfigVersion.cmake)
+AC_CONFIG_FILES(lang/cpp/src/gpgmepp_version.h)
+AC_CONFIG_FILES(lang/qt/Makefile lang/qt/src/Makefile)
+AC_CONFIG_FILES(lang/qt/src/QGpgmeConfig.cmake.in)
+AC_CONFIG_FILES(lang/qt/src/QGpgmeConfigVersion.cmake)
+AC_CONFIG_FILES(lang/qt/tests/Makefile)
+AC_CONFIG_FILES(lang/qt/src/qgpgme_version.h)
AC_CONFIG_FILES([lang/Makefile lang/cl/Makefile lang/cl/gpgme.asd])
+AM_COND_IF([HAVE_DOXYGEN], [AC_CONFIG_FILES([lang/qt/doc/Doxyfile])])
+AC_CONFIG_FILES(lang/qt/doc/Makefile)
+AC_CONFIG_FILES([lang/python/Makefile
+ lang/python/setup.py
+ lang/python/pyme/version.py
+ lang/python/tests/Makefile])
AC_OUTPUT
echo "
GPGME v${VERSION} has been configured as follows:
- Revision: mym4_revision (mym4_revision_dec)
- Platform: $host
+ Revision: mym4_revision (mym4_revision_dec)
+ Platform: $host
+
+ UI Server: $uiserver
+ FD Passing: $use_descriptor_passing
+ GPGME Pthread: $have_pthread
- UI Server: $uiserver
- FD Passing: $use_descriptor_passing
- GPGME Pthread: $have_pthread
+ Language bindings: ${enabled_languages_v:-$enabled_languages}
"
if test "x${gpg_config_script_warn}" != x; then
cat <<G10EOF
diff --git a/doc/Makefile.am b/doc/Makefile.am
index 2df35b4..905f953 100644
--- a/doc/Makefile.am
+++ b/doc/Makefile.am
@@ -20,12 +20,38 @@
## Process this file with automake to produce Makefile.in
DISTCLEANFILES = gpgme.tmp
+CLEANFILES = mkdefsinc defs.inc
+
+EXTRA_DIST = module-overview.sk HACKING DCO ChangeLog-2011 \
+ mkdefsinc.c defsincdate
+
+BUILT_SOURCES = defsincdate defs.inc
-EXTRA_DIST = module-overview.sk HACKING DCO ChangeLog-2011
info_TEXINFOS = gpgme.texi
gpgme_TEXINFOS = uiserver.texi lesser.texi gpl.texi
+gpgme.texi : defs.inc
+
+mkdefsinc: mkdefsinc.c Makefile ../config.h
+ $(CC_FOR_BUILD) -I. -I.. -I$(srcdir) $(AM_CPPFLAGS) \
+ -o $@ $(srcdir)/mkdefsinc.c
+
+dist-hook: defsincdate
+
+defsincdate: $(gpgme_TEXINFOS)
+ : >defsincdate ; \
+ if test -e $(top_srcdir)/.git; then \
+ (cd $(srcdir) && git log -1 --format='%ct' -- \
+ $(info_TEXINFOS) $(gpgme_TEXINFOS) 2>/dev/null) >>defsincdate; \
+ fi
+
+defs.inc: defsincdate Makefile mkdefsinc
+ incd="`test -f defsincdate || echo '$(srcdir)/'`defsincdate"; \
+ ./mkdefsinc -C $(srcdir) --date "`cat $$incd 2>/dev/null`" \
+ $(info_TEXINFOS) $(gpgme_TEXINFOS) >$@
+
+
online: gpgme.html gpgme.pdf
set -e; \
echo "Uploading current manuals to www.gnupg.org ..."; \
diff --git a/doc/Makefile.in b/doc/Makefile.in
index fc1301b..90fa2b8 100644
--- a/doc/Makefile.in
+++ b/doc/Makefile.in
@@ -99,16 +99,18 @@ host_triplet = @host@
subdir = doc
DIST_COMMON = $(srcdir)/Makefile.in $(srcdir)/Makefile.am \
$(top_srcdir)/build-aux/mkinstalldirs $(gpgme_TEXINFOS) \
- $(top_srcdir)/build-aux/mdate-sh $(srcdir)/version.texi \
- $(srcdir)/stamp-vti $(top_srcdir)/build-aux/texinfo.tex \
- mdate-sh texinfo.tex
+ $(top_srcdir)/build-aux/texinfo.tex mdate-sh texinfo.tex
ACLOCAL_M4 = $(top_srcdir)/aclocal.m4
-am__aclocal_m4_deps = $(top_srcdir)/m4/glib-2.0.m4 \
- $(top_srcdir)/m4/glibc21.m4 $(top_srcdir)/m4/gnupg-ttyname.m4 \
+am__aclocal_m4_deps = $(top_srcdir)/m4/ax_cxx_compile_stdcxx.m4 \
+ $(top_srcdir)/m4/ax_pkg_swig.m4 \
+ $(top_srcdir)/m4/ax_python_devel.m4 \
+ $(top_srcdir)/m4/glib-2.0.m4 $(top_srcdir)/m4/glibc21.m4 \
+ $(top_srcdir)/m4/gnupg-ttyname.m4 \
$(top_srcdir)/m4/gpg-error.m4 $(top_srcdir)/m4/libassuan.m4 \
$(top_srcdir)/m4/libtool.m4 $(top_srcdir)/m4/ltoptions.m4 \
$(top_srcdir)/m4/ltsugar.m4 $(top_srcdir)/m4/ltversion.m4 \
- $(top_srcdir)/m4/lt~obsolete.m4 $(top_srcdir)/acinclude.m4 \
+ $(top_srcdir)/m4/lt~obsolete.m4 $(top_srcdir)/m4/pkg.m4 \
+ $(top_srcdir)/m4/qt.m4 $(top_srcdir)/acinclude.m4 \
$(top_srcdir)/configure.ac
am__configure_deps = $(am__aclocal_m4_deps) $(CONFIGURE_DEPENDENCIES) \
$(ACLOCAL_M4)
@@ -220,6 +222,7 @@ BUILD_REVISION = @BUILD_REVISION@
BUILD_TIMESTAMP = @BUILD_TIMESTAMP@
CC = @CC@
CCDEPMODE = @CCDEPMODE@
+CC_FOR_BUILD = @CC_FOR_BUILD@
CFLAGS = @CFLAGS@
CPP = @CPP@
CPPFLAGS = @CPPFLAGS@
@@ -231,12 +234,14 @@ CYGPATH_W = @CYGPATH_W@
DEFS = @DEFS@
DEPDIR = @DEPDIR@
DLLTOOL = @DLLTOOL@
+DOXYGEN = @DOXYGEN@
DSYMUTIL = @DSYMUTIL@
DUMPBIN = @DUMPBIN@
ECHO_C = @ECHO_C@
ECHO_N = @ECHO_N@
ECHO_T = @ECHO_T@
EGREP = @EGREP@
+ENABLED_LANGUAGES = @ENABLED_LANGUAGES@
EXEEXT = @EXEEXT@
FGREP = @FGREP@
GITLOG_TO_CHANGELOG = @GITLOG_TO_CHANGELOG@
@@ -247,15 +252,23 @@ GLIB_LIBS = @GLIB_LIBS@
GLIB_MKENUMS = @GLIB_MKENUMS@
GOBJECT_QUERY = @GOBJECT_QUERY@
GPGME_CONFIG_API_VERSION = @GPGME_CONFIG_API_VERSION@
+GPGME_CONFIG_AVAIL_LANG = @GPGME_CONFIG_AVAIL_LANG@
GPGME_CONFIG_CFLAGS = @GPGME_CONFIG_CFLAGS@
GPGME_CONFIG_HOST = @GPGME_CONFIG_HOST@
GPGME_CONFIG_LIBS = @GPGME_CONFIG_LIBS@
+GPGME_QTTEST_CFLAGS = @GPGME_QTTEST_CFLAGS@
+GPGME_QTTEST_LIBS = @GPGME_QTTEST_LIBS@
+GPGME_QT_CFLAGS = @GPGME_QT_CFLAGS@
+GPGME_QT_LIBS = @GPGME_QT_LIBS@
GPG_ERROR_CFLAGS = @GPG_ERROR_CFLAGS@
GPG_ERROR_CONFIG = @GPG_ERROR_CONFIG@
GPG_ERROR_LIBS = @GPG_ERROR_LIBS@
GPG_ERROR_MT_CFLAGS = @GPG_ERROR_MT_CFLAGS@
GPG_ERROR_MT_LIBS = @GPG_ERROR_MT_LIBS@
+GRAPHVIZ = @GRAPHVIZ@
GREP = @GREP@
+HAVE_CXX11 = @HAVE_CXX11@
+HAVE_DOT = @HAVE_DOT@
INSTALL = @INSTALL@
INSTALL_DATA = @INSTALL_DATA@
INSTALL_PROGRAM = @INSTALL_PROGRAM@
@@ -266,10 +279,16 @@ LDFLAGS = @LDFLAGS@
LIBASSUAN_CFLAGS = @LIBASSUAN_CFLAGS@
LIBASSUAN_CONFIG = @LIBASSUAN_CONFIG@
LIBASSUAN_LIBS = @LIBASSUAN_LIBS@
+LIBGPGMEPP_LT_AGE = @LIBGPGMEPP_LT_AGE@
+LIBGPGMEPP_LT_CURRENT = @LIBGPGMEPP_LT_CURRENT@
+LIBGPGMEPP_LT_REVISION = @LIBGPGMEPP_LT_REVISION@
LIBGPGME_LT_AGE = @LIBGPGME_LT_AGE@
LIBGPGME_LT_CURRENT = @LIBGPGME_LT_CURRENT@
LIBGPGME_LT_REVISION = @LIBGPGME_LT_REVISION@
LIBOBJS = @LIBOBJS@
+LIBQGPGME_LT_AGE = @LIBQGPGME_LT_AGE@
+LIBQGPGME_LT_CURRENT = @LIBQGPGME_LT_CURRENT@
+LIBQGPGME_LT_REVISION = @LIBQGPGME_LT_REVISION@
LIBS = @LIBS@
LIBTOOL = @LIBTOOL@
LIPO = @LIPO@
@@ -279,6 +298,8 @@ MAINT = @MAINT@
MAKEINFO = @MAKEINFO@
MANIFEST_TOOL = @MANIFEST_TOOL@
MKDIR_P = @MKDIR_P@
+MOC = @MOC@
+MOC2 = @MOC2@
NEED__FILE_OFFSET_BITS = @NEED__FILE_OFFSET_BITS@
NM = @NM@
NMEDIT = @NMEDIT@
@@ -295,14 +316,27 @@ PACKAGE_URL = @PACKAGE_URL@
PACKAGE_VERSION = @PACKAGE_VERSION@
PATH_SEPARATOR = @PATH_SEPARATOR@
PKG_CONFIG = @PKG_CONFIG@
-QT4_CORE_CFLAGS = @QT4_CORE_CFLAGS@
-QT4_CORE_LIBS = @QT4_CORE_LIBS@
+PYTHON = @PYTHON@
+PYTHONS = @PYTHONS@
+PYTHON_CPPFLAGS = @PYTHON_CPPFLAGS@
+PYTHON_EXEC_PREFIX = @PYTHON_EXEC_PREFIX@
+PYTHON_EXTRA_LDFLAGS = @PYTHON_EXTRA_LDFLAGS@
+PYTHON_EXTRA_LIBS = @PYTHON_EXTRA_LIBS@
+PYTHON_LDFLAGS = @PYTHON_LDFLAGS@
+PYTHON_PLATFORM = @PYTHON_PLATFORM@
+PYTHON_PREFIX = @PYTHON_PREFIX@
+PYTHON_SITE_PKG = @PYTHON_SITE_PKG@
+PYTHON_VERSION = @PYTHON_VERSION@
+PYTHON_VERSIONS = @PYTHON_VERSIONS@
+QTCHOOSER = @QTCHOOSER@
RANLIB = @RANLIB@
RC = @RC@
SED = @SED@
SET_MAKE = @SET_MAKE@
SHELL = @SHELL@
STRIP = @STRIP@
+SWIG = @SWIG@
+SWIG_LIB = @SWIG_LIB@
SYSROOT = @SYSROOT@
VERSION = @VERSION@
VERSION_NUMBER = @VERSION_NUMBER@
@@ -351,9 +385,13 @@ mandir = @mandir@
mkdir_p = @mkdir_p@
oldincludedir = @oldincludedir@
pdfdir = @pdfdir@
+pkgpyexecdir = @pkgpyexecdir@
+pkgpythondir = @pkgpythondir@
prefix = @prefix@
program_transform_name = @program_transform_name@
psdir = @psdir@
+pyexecdir = @pyexecdir@
+pythondir = @pythondir@
sbindir = @sbindir@
sharedstatedir = @sharedstatedir@
srcdir = @srcdir@
@@ -363,10 +401,15 @@ top_build_prefix = @top_build_prefix@
top_builddir = @top_builddir@
top_srcdir = @top_srcdir@
DISTCLEANFILES = gpgme.tmp
-EXTRA_DIST = module-overview.sk HACKING DCO ChangeLog-2011
+CLEANFILES = mkdefsinc defs.inc
+EXTRA_DIST = module-overview.sk HACKING DCO ChangeLog-2011 \
+ mkdefsinc.c defsincdate
+
+BUILT_SOURCES = defsincdate defs.inc
info_TEXINFOS = gpgme.texi
gpgme_TEXINFOS = uiserver.texi lesser.texi gpl.texi
-all: all-am
+all: $(BUILT_SOURCES)
+ $(MAKE) $(AM_MAKEFLAGS) all-am
.SUFFIXES:
.SUFFIXES: .dvi .html .info .pdf .ps .texi
@@ -450,29 +493,10 @@ clean-libtool:
else \
rm -rf $(@:.html=.htp); exit 1; \
fi
-$(srcdir)/gpgme.info: gpgme.texi $(srcdir)/version.texi $(gpgme_TEXINFOS)
-gpgme.dvi: gpgme.texi $(srcdir)/version.texi $(gpgme_TEXINFOS)
-gpgme.pdf: gpgme.texi $(srcdir)/version.texi $(gpgme_TEXINFOS)
-gpgme.html: gpgme.texi $(srcdir)/version.texi $(gpgme_TEXINFOS)
-$(srcdir)/version.texi: @MAINTAINER_MODE_TRUE@ $(srcdir)/stamp-vti
-$(srcdir)/stamp-vti: gpgme.texi $(top_srcdir)/configure
- @(dir=.; test -f ./gpgme.texi || dir=$(srcdir); \
- set `$(SHELL) $(top_srcdir)/build-aux/mdate-sh $$dir/gpgme.texi`; \
- echo "@set UPDATED $$1 $$2 $$3"; \
- echo "@set UPDATED-MONTH $$2 $$3"; \
- echo "@set EDITION $(VERSION)"; \
- echo "@set VERSION $(VERSION)") > vti.tmp
- @cmp -s vti.tmp $(srcdir)/version.texi \
- || (echo "Updating $(srcdir)/version.texi"; \
- cp vti.tmp $(srcdir)/version.texi)
- -@rm -f vti.tmp
- @cp $(srcdir)/version.texi $@
-
-mostlyclean-vti:
- -rm -f vti.tmp
-
-maintainer-clean-vti:
-@MAINTAINER_MODE_TRUE@ -rm -f $(srcdir)/stamp-vti $(srcdir)/version.texi
+$(srcdir)/gpgme.info: gpgme.texi $(gpgme_TEXINFOS)
+gpgme.dvi: gpgme.texi $(gpgme_TEXINFOS)
+gpgme.pdf: gpgme.texi $(gpgme_TEXINFOS)
+gpgme.html: gpgme.texi $(gpgme_TEXINFOS)
.dvi.ps:
$(AM_V_DVIPS)TEXINPUTS="$(am__TEXINFO_TEX_DIR)$(PATH_SEPARATOR)$$TEXINPUTS" \
$(DVIPS) $(AM_V_texinfo) -o $@ $<
@@ -605,15 +629,17 @@ distdir: $(DISTFILES)
done
$(MAKE) $(AM_MAKEFLAGS) \
top_distdir="$(top_distdir)" distdir="$(distdir)" \
- dist-info
+ dist-info dist-hook
check-am: all-am
-check: check-am
+check: $(BUILT_SOURCES)
+ $(MAKE) $(AM_MAKEFLAGS) check-am
all-am: Makefile $(INFO_DEPS)
installdirs:
for dir in "$(DESTDIR)$(infodir)"; do \
test -z "$$dir" || $(MKDIR_P) "$$dir"; \
done
-install: install-am
+install: $(BUILT_SOURCES)
+ $(MAKE) $(AM_MAKEFLAGS) install-am
install-exec: install-exec-am
install-data: install-data-am
uninstall: uninstall-am
@@ -635,6 +661,7 @@ install-strip:
mostlyclean-generic:
clean-generic:
+ -test -z "$(CLEANFILES)" || rm -f $(CLEANFILES)
distclean-generic:
-test -z "$(CONFIG_CLEAN_FILES)" || rm -f $(CONFIG_CLEAN_FILES)
@@ -644,6 +671,7 @@ distclean-generic:
maintainer-clean-generic:
@echo "This command is intended for maintainers to use"
@echo "it deletes files that may require special tools to rebuild."
+ -test -z "$(BUILT_SOURCES)" || rm -f $(BUILT_SOURCES)
clean: clean-am
clean-am: clean-aminfo clean-generic clean-libtool mostlyclean-am
@@ -786,12 +814,12 @@ installcheck-am:
maintainer-clean: maintainer-clean-am
-rm -f Makefile
maintainer-clean-am: distclean-am maintainer-clean-aminfo \
- maintainer-clean-generic maintainer-clean-vti
+ maintainer-clean-generic
mostlyclean: mostlyclean-am
mostlyclean-am: mostlyclean-aminfo mostlyclean-generic \
- mostlyclean-libtool mostlyclean-vti
+ mostlyclean-libtool
pdf: pdf-am
@@ -804,25 +832,44 @@ ps-am: $(PSS)
uninstall-am: uninstall-dvi-am uninstall-html-am uninstall-info-am \
uninstall-pdf-am uninstall-ps-am
-.MAKE: install-am install-strip
+.MAKE: all check install install-am install-strip
.PHONY: all all-am check check-am clean clean-aminfo clean-generic \
- clean-libtool cscopelist-am ctags-am dist-info distclean \
- distclean-generic distclean-libtool distdir dvi dvi-am html \
- html-am info info-am install install-am install-data \
- install-data-am install-dvi install-dvi-am install-exec \
- install-exec-am install-html install-html-am install-info \
- install-info-am install-man install-pdf install-pdf-am \
- install-ps install-ps-am install-strip installcheck \
- installcheck-am installdirs maintainer-clean \
- maintainer-clean-aminfo maintainer-clean-generic \
- maintainer-clean-vti mostlyclean mostlyclean-aminfo \
- mostlyclean-generic mostlyclean-libtool mostlyclean-vti pdf \
+ clean-libtool cscopelist-am ctags-am dist-hook dist-info \
+ distclean distclean-generic distclean-libtool distdir dvi \
+ dvi-am html html-am info info-am install install-am \
+ install-data install-data-am install-dvi install-dvi-am \
+ install-exec install-exec-am install-html install-html-am \
+ install-info install-info-am install-man install-pdf \
+ install-pdf-am install-ps install-ps-am install-strip \
+ installcheck installcheck-am installdirs maintainer-clean \
+ maintainer-clean-aminfo maintainer-clean-generic mostlyclean \
+ mostlyclean-aminfo mostlyclean-generic mostlyclean-libtool pdf \
pdf-am ps ps-am tags-am uninstall uninstall-am \
uninstall-dvi-am uninstall-html-am uninstall-info-am \
uninstall-pdf-am uninstall-ps-am
+gpgme.texi : defs.inc
+
+mkdefsinc: mkdefsinc.c Makefile ../config.h
+ $(CC_FOR_BUILD) -I. -I.. -I$(srcdir) $(AM_CPPFLAGS) \
+ -o $@ $(srcdir)/mkdefsinc.c
+
+dist-hook: defsincdate
+
+defsincdate: $(gpgme_TEXINFOS)
+ : >defsincdate ; \
+ if test -e $(top_srcdir)/.git; then \
+ (cd $(srcdir) && git log -1 --format='%ct' -- \
+ $(info_TEXINFOS) $(gpgme_TEXINFOS) 2>/dev/null) >>defsincdate; \
+ fi
+
+defs.inc: defsincdate Makefile mkdefsinc
+ incd="`test -f defsincdate || echo '$(srcdir)/'`defsincdate"; \
+ ./mkdefsinc -C $(srcdir) --date "`cat $$incd 2>/dev/null`" \
+ $(info_TEXINFOS) $(gpgme_TEXINFOS) >$@
+
online: gpgme.html gpgme.pdf
set -e; \
echo "Uploading current manuals to www.gnupg.org ..."; \
diff --git a/doc/defsincdate b/doc/defsincdate
new file mode 100644
index 0000000..0df13bf
--- /dev/null
+++ b/doc/defsincdate
@@ -0,0 +1 @@
+1440576360
diff --git a/doc/gpgme.info b/doc/gpgme.info
index 793c20b..2702f0a 100644
--- a/doc/gpgme.info
+++ b/doc/gpgme.info
@@ -1,7 +1,6 @@
This is gpgme.info, produced by makeinfo version 5.2 from gpgme.texi.
-Copyright © 2002, 2003, 2004, 2005, 2006, 2007, 2008, 2010, 2012, 2013,
-2014 g10 Code GmbH.
+Copyright © 2002–2008, 2010, 2012–2016 g10 Code GmbH.
Permission is granted to copy, distribute and/or modify this
document under the terms of the GNU General Public License as
@@ -20,11 +19,10 @@ END-INFO-DIR-ENTRY
This file documents the GPGME library.
- This is Edition 1.6.0, last updated 26 August 2015, of ‘The ‘GnuPG
-Made Easy’ Reference Manual’, for Version 1.6.0.
+ This is Edition 1.7.0-beta361, last updated 26 August 2015, of ‘The
+‘GnuPG Made Easy’ Reference Manual’, for Version 1.7.0-beta361.
- Copyright © 2002, 2003, 2004, 2005, 2006, 2007, 2008, 2010, 2012,
-2013, 2014 g10 Code GmbH.
+ Copyright © 2002–2008, 2010, 2012–2016 g10 Code GmbH.
Permission is granted to copy, distribute and/or modify this
document under the terms of the GNU General Public License as
@@ -39,123 +37,128 @@ Public License for more details.

Indirect:
-gpgme.info-1: 1738
-gpgme.info-2: 302237
+gpgme.info-1: 1686
+gpgme.info-2: 304664

Tag Table:
(Indirect)
-Node: Top1738
-Node: Introduction8990
-Node: Getting Started9780
-Node: Features10905
-Node: Overview12061
-Node: Preparation13170
-Node: Header14167
-Node: Building the Source14914
-Node: Largefile Support (LFS)17087
-Node: Using Automake22501
-Node: Using Libtool24947
-Node: Library Version Check25309
-Node: Signal Handling30403
-Node: Multi Threading31673
-Ref: Multi Threading-Footnote-133907
-Node: Protocols and Engines34330
-Node: Engine Version Check36819
-Node: Engine Information38445
-Node: Engine Configuration42305
-Node: OpenPGP43589
-Node: Cryptographic Message Syntax43929
-Node: Algorithms44227
-Ref: Algorithms-Footnote-144706
-Node: Public Key Algorithms44834
-Node: Hash Algorithms46811
-Node: Error Handling48001
-Node: Error Values49875
-Node: Error Sources55078
-Node: Error Codes57518
-Node: Error Strings62309
-Node: Exchanging Data64116
-Node: Creating Data Buffers65982
-Node: Memory Based Data Buffers66498
-Node: File Based Data Buffers69931
-Node: Callback Based Data Buffers72133
-Node: Destroying Data Buffers77820
-Node: Manipulating Data Buffers79211
-Node: Data Buffer I/O Operations79703
-Node: Data Buffer Meta-Data82430
-Node: Data Buffer Convenience85898
-Node: Contexts87875
-Node: Creating Contexts89061
-Node: Destroying Contexts89908
-Node: Result Management90247
-Node: Context Attributes91676
-Node: Protocol Selection92582
-Node: Crypto Engine93614
-Node: ASCII Armor95457
-Node: Text Mode96081
-Node: Offline Mode97015
-Node: Included Certificates98095
-Node: Key Listing Mode99516
-Node: Passphrase Callback103390
-Node: Progress Meter Callback106602
-Node: Status Message Callback108585
-Node: Locale110305
-Node: Key Management111864
-Node: Listing Keys122757
-Node: Information About Keys130183
-Node: Key Signatures138514
-Node: Manipulating Keys142650
-Node: Generating Keys143510
-Node: Exporting Keys148234
-Node: Importing Keys154934
-Ref: Importing Keys-Footnote-1162371
-Node: Deleting Keys162499
-Node: Changing Passphrases163944
-Node: Advanced Key Editing165233
-Node: Trust Item Management168415
-Node: Listing Trust Items169527
-Node: Information About Trust Items171893
-Node: Manipulating Trust Items173822
-Node: Crypto Operations174801
-Node: Decrypt176065
-Node: Verify179935
-Node: Decrypt and Verify198312
-Node: Sign200380
-Node: Selecting Signers200944
-Node: Creating a Signature202116
-Node: Signature Notation Data206886
-Node: Encrypt209114
-Node: Encrypting a Plaintext209470
-Node: Miscellaneous216144
-Node: Running other Programs216432
-Node: Run Control218456
-Node: Waiting For Completion219200
-Node: Using External Event Loops221318
-Node: I/O Callback Interface223290
-Node: Registering I/O Callbacks228528
-Node: I/O Callback Example230566
-Node: I/O Callback Example GTK+236783
-Node: I/O Callback Example GDK238572
-Node: I/O Callback Example Qt240214
-Node: Cancellation242502
-Node: UI Server Protocol244795
-Ref: UI Server Protocol-Footnote-1246230
-Node: UI Server Encrypt246349
-Node: UI Server Sign251494
-Node: UI Server Decrypt253847
-Node: UI Server Verify255313
-Node: UI Server Set Input Files258885
-Node: UI Server Sign/Encrypt Files259955
-Node: UI Server Verify/Decrypt Files261763
-Node: UI Server Import/Export Keys263639
-Node: UI Server Checksum Files264701
-Node: Miscellaneous UI Server Commands266917
-Ref: command SENDER268848
-Node: Debugging270550
-Node: Library Copying272294
-Node: Copying302237
-Node: Concept Index339983
-Node: Function and Data Index354540
+Node: Top1686
+Node: Introduction9093
+Node: Getting Started9883
+Node: Features11344
+Node: Overview12656
+Node: Preparation13765
+Node: Header14762
+Node: Building the Source15509
+Node: Largefile Support (LFS)17919
+Node: Using Automake23333
+Node: Using Libtool25779
+Node: Library Version Check26141
+Node: Signal Handling32153
+Node: Multi Threading33423
+Ref: Multi Threading-Footnote-135657
+Node: Protocols and Engines36080
+Node: Engine Version Check38725
+Node: Engine Information41142
+Node: Engine Configuration45002
+Node: OpenPGP46286
+Node: Cryptographic Message Syntax46626
+Node: Assuan46939
+Node: Algorithms47313
+Ref: Algorithms-Footnote-147792
+Node: Public Key Algorithms47920
+Node: Hash Algorithms50407
+Node: Error Handling51597
+Node: Error Values53471
+Node: Error Sources58674
+Node: Error Codes61114
+Node: Error Strings65905
+Node: Exchanging Data67712
+Node: Creating Data Buffers69578
+Node: Memory Based Data Buffers70094
+Node: File Based Data Buffers73527
+Node: Callback Based Data Buffers75729
+Node: Destroying Data Buffers79920
+Node: Manipulating Data Buffers81408
+Node: Data Buffer I/O Operations81900
+Node: Data Buffer Meta-Data84273
+Node: Data Buffer Convenience88639
+Node: Contexts90616
+Node: Creating Contexts91802
+Node: Destroying Contexts92649
+Node: Result Management92988
+Node: Context Attributes94417
+Node: Protocol Selection95385
+Node: Crypto Engine96417
+Node: ASCII Armor98260
+Node: Text Mode98884
+Node: Offline Mode99818
+Node: Pinentry Mode100890
+Node: Included Certificates102575
+Node: Key Listing Mode103997
+Node: Passphrase Callback108089
+Node: Progress Meter Callback111474
+Node: Status Message Callback113459
+Node: Locale116077
+Node: Key Management117636
+Node: Key objects118864
+Node: Listing Keys129864
+Node: Information About Keys137310
+Node: Manipulating Keys138618
+Node: Generating Keys139188
+Node: Signing Keys154662
+Node: Exporting Keys158260
+Node: Importing Keys164953
+Ref: Importing Keys-Footnote-1171858
+Node: Deleting Keys171986
+Node: Changing Passphrases173431
+Node: Changing TOFU Data174720
+Node: Advanced Key Editing176771
+Node: Trust Item Management179420
+Node: Listing Trust Items180456
+Node: Manipulating Trust Items182817
+Node: Crypto Operations183460
+Node: Decrypt184724
+Node: Verify188594
+Node: Decrypt and Verify200554
+Node: Sign202622
+Node: Selecting Signers203186
+Node: Creating a Signature204573
+Node: Signature Notation Data209343
+Node: Encrypt211571
+Node: Encrypting a Plaintext211927
+Node: Miscellaneous218890
+Node: Running other Programs219236
+Node: Using the Assuan protocol221312
+Node: Run Control224005
+Node: Waiting For Completion224749
+Node: Using External Event Loops226867
+Node: I/O Callback Interface228839
+Node: Registering I/O Callbacks234077
+Node: I/O Callback Example236115
+Node: I/O Callback Example GTK+242332
+Node: I/O Callback Example GDK244121
+Node: I/O Callback Example Qt245763
+Node: Cancellation248051
+Node: UI Server Protocol250315
+Ref: UI Server Protocol-Footnote-1251750
+Node: UI Server Encrypt251869
+Node: UI Server Sign257014
+Node: UI Server Decrypt259367
+Node: UI Server Verify260833
+Node: UI Server Set Input Files264405
+Node: UI Server Sign/Encrypt Files265475
+Node: UI Server Verify/Decrypt Files267283
+Node: UI Server Import/Export Keys269159
+Node: UI Server Checksum Files270221
+Node: Miscellaneous UI Server Commands272437
+Ref: command SENDER274368
+Node: Debugging276070
+Node: Deprecated Functions277819
+Node: Library Copying304664
+Node: Copying332880
+Node: Concept Index370626
+Node: Function and Data Index385186

End Tag Table
diff --git a/doc/gpgme.info-1 b/doc/gpgme.info-1
index 26184d8..839678b 100644
--- a/doc/gpgme.info-1
+++ b/doc/gpgme.info-1
@@ -1,7 +1,6 @@
This is gpgme.info, produced by makeinfo version 5.2 from gpgme.texi.
-Copyright © 2002, 2003, 2004, 2005, 2006, 2007, 2008, 2010, 2012, 2013,
-2014 g10 Code GmbH.
+Copyright © 2002–2008, 2010, 2012–2016 g10 Code GmbH.
Permission is granted to copy, distribute and/or modify this
document under the terms of the GNU General Public License as
@@ -20,11 +19,10 @@ END-INFO-DIR-ENTRY
This file documents the GPGME library.
- This is Edition 1.6.0, last updated 26 August 2015, of ‘The ‘GnuPG
-Made Easy’ Reference Manual’, for Version 1.6.0.
+ This is Edition 1.7.0-beta361, last updated 26 August 2015, of ‘The
+‘GnuPG Made Easy’ Reference Manual’, for Version 1.7.0-beta361.
- Copyright © 2002, 2003, 2004, 2005, 2006, 2007, 2008, 2010, 2012,
-2013, 2014 g10 Code GmbH.
+ Copyright © 2002–2008, 2010, 2012–2016 g10 Code GmbH.
Permission is granted to copy, distribute and/or modify this
document under the terms of the GNU General Public License as
@@ -43,8 +41,9 @@ File: gpgme.info, Node: Top, Next: Introduction, Up: (dir)
Main Menu
*********
-This is Edition 1.6.0, last updated 26 August 2015, of ‘The ‘GnuPG Made
-Easy’ Reference Manual’, for Version 1.6.0 of the GPGME library.
+This is Edition 1.7.0-beta361, last updated 26 August 2015, of ‘The
+‘GnuPG Made Easy’ Reference Manual’, for Version 1.7.0-beta361 of the
+GPGME library.
* Menu:
@@ -60,6 +59,7 @@ Appendices
* UI Server Protocol:: The GnuPG UI Server Protocol.
* Debugging:: How to solve problems.
+* Deprecated Functions:: Documentation of deprecated functions.
* Library Copying:: The GNU Lesser General Public License says
how you can copy and share ‘GnuPG Made Easy’.
@@ -156,21 +156,22 @@ Context Attributes
Key Management
+* Key objects:: Description of the key structures.
* Listing Keys:: Browsing the list of available keys.
* Information About Keys:: Requesting detailed information about keys.
-* Key Signatures:: Listing the signatures on a key.
* Manipulating Keys:: Operations on keys.
* Generating Keys:: Creating new key pairs.
+* Signing Keys:: Adding key signatures to public keys.
* Exporting Keys:: Retrieving key data from the key ring.
* Importing Keys:: Adding keys to the key ring.
* Deleting Keys:: Removing keys from the key ring.
* Changing Passphrases:: Change the passphrase of a key.
+* Changing TOFU Data:: Changing data pertaining to TOFU.
* Advanced Key Editing:: Advanced key edit operation.
Trust Item Management
* Listing Trust Items:: Browsing the list of available trust items.
-* Information About Trust Items:: Requesting information about trust items.
* Manipulating Trust Items:: Operations on trust items.
Crypto Operations
@@ -256,6 +257,12 @@ library. Experienced programmers might want to start looking at the
examples at the end of the manual, and then only read up those parts of
the interface which are unclear.
+ The documentation for the language bindings is currently not included
+in this manual. Those languages bindings follow the general programming
+model of GPGME but may provide some extra high level abstraction on top
+of the GPGME style API. For now please see the README files in the
+‘lang/’ directory of the source distribution.
+

File: gpgme.info, Node: Features, Next: Overview, Prev: Getting Started, Up: Introduction
@@ -284,6 +291,10 @@ it’s easy
GPGME has been added to a program, it is easy to add support for
other crypto protocols once GPGME backends provide them.
+it’s language friendly
+ GPGME comes with languages bindings for several common programming
+ languages: Common Lisp, C++, Python 2, and Python 3.
+

File: gpgme.info, Node: Overview, Prev: Features, Up: Introduction
@@ -401,6 +412,15 @@ must specify the ‘--thread’ option before any other option to select the
thread package you want to link with. Supported thread packages are
‘--thread=pth’ and ‘--thread=pthread’.
+ If you need to detect the installed language bindings you can use
+list them using:
+
+ gpgme-config --print-lang
+
+ or test for the availability using
+
+ gpgme-config --have-lang=python && echo 'Bindings for Pythons available'
+

File: gpgme.info, Node: Largefile Support (LFS), Next: Using Automake, Prev: Building the Source, Up: Preparation
@@ -616,12 +636,12 @@ File: gpgme.info, Node: Library Version Check, Next: Signal Handling, Prev: U
called as early as possible — even before ‘gpgme_check_version’.
The features are identified by the following values for NAME:
- ‘"debug"’
+ ‘debug’
To enable debugging use the string “debug†for NAME and VALUE
identical to the value used with the environment variable
‘GPGME_DEBUG’.
- ‘"disable-gpgconf"’
+ ‘disable-gpgconf’
Using this feature with any VALUE disables the detection of
the gpgconf program and thus forces GPGME to fallback into the
simple OpenPGP only mode. It may be used to force the use of
@@ -629,8 +649,8 @@ File: gpgme.info, Node: Library Version Check, Next: Signal Handling, Prev: U
Note that in general the use of ‘gpgme_set_engine_info’ is a
better way to select a specific engine version.
- ‘"gpgconf-name"’
- ‘"gpg-name"’
+ ‘gpgconf-name’
+ ‘gpg-name’
Set the name of the gpgconf respective gpg binary. The
defaults are ‘GNU/GnuPG/gpgconf’ and ‘GNU/GnuPG/gpg’. Under
Unix the leading directory part is ignored. Under Windows the
@@ -638,6 +658,23 @@ File: gpgme.info, Node: Library Version Check, Next: Signal Handling, Prev: U
directory; the ‘.exe’ suffix is added by GPGME. Use forward
slashed even under Windows.
+ ‘require-gnupg’
+ Set the mimimum version of the required GnuPG engine. If that
+ version is not met, GPGME fails early instead of trying to use
+ the existant version. The given version must be a string with
+ major, minor, and micro number. Example: "2.1.0".
+
+ ‘w32-inst-dir’
+ On Windows GPGME needs to know its installation directory to
+ find its spawn helper. This is in general no problem because
+ a DLL has this information. Some applications however link
+ statically to GPGME and thus GPGME can only figure out the
+ installation directory of this application which may be wrong
+ in certain cases. By supplying an installation directory as
+ value to this flag, GPGME will assume that that directory is
+ the installation directory. This flag has no effect on
+ non-Windows platforms.
+
This function returns ‘0’ on success. In contrast to other
functions the non-zero return value on failure does not convey any
error code. For setting “debug†the only possible error cause is
@@ -775,10 +812,13 @@ further interfaces.
‘GPGME_PROTOCOL_CMS’
This specifies the Cryptographic Message Syntax.
- ‘GPGME_PROTOCOL_ASSUAN’
+ ‘GPGME_PROTOCOL_GPGCONF’
Under development. Please ask on <gnupg-devel@gnupg.org> for
help.
+ ‘GPGME_PROTOCOL_ASSUAN’
+ This specifies the raw Assuan protocol.
+
‘GPGME_PROTOCOL_G13’
Under development. Please ask on <gnupg-devel@gnupg.org> for
help.
@@ -809,6 +849,7 @@ further interfaces.
* Engine Configuration:: Changing the engine configuration.
* OpenPGP:: Support for the OpenPGP protocol.
* Cryptographic Message Syntax:: Support for the CMS.
+* Assuan:: Support for the raw Assuan protocol.

File: gpgme.info, Node: Engine Version Check, Next: Engine Information, Up: Protocols and Engines
@@ -826,9 +867,36 @@ File: gpgme.info, Node: Engine Version Check, Next: Engine Information, Up: P
‘homedir’
Return the default home directory.
+ ‘sysconfdir’
+ Return the name of the system configuration directory
+
+ ‘bindir’
+ Return the name of the directory with GnuPG program files.
+
+ ‘libdir’
+ Return the name of the directory with GnuPG related library
+ files.
+
+ ‘libexecdir’
+ Return the name of the directory with GnuPG helper program
+ files.
+
+ ‘datadir’
+ Return the name of the directory with GnuPG shared data.
+
+ ‘localedir’
+ Return the name of the directory with GnuPG locale data.
+
‘agent-socket’
Return the name of the socket to connect to the gpg-agent.
+ ‘agent-ssh-socket’
+ Return the name of the socket to connect to the ssh-agent
+ component of gpg-agent.
+
+ ‘dirmngr-socket’
+ Return the name of the socket to connect to the dirmngr.
+
‘uiserver-socket’
Return the name of the socket to connect to the user interface
server.
@@ -989,7 +1057,7 @@ first protocol that was supported by GPGME.
The OpenPGP protocol is specified by ‘GPGME_PROTOCOL_OpenPGP’.

-File: gpgme.info, Node: Cryptographic Message Syntax, Prev: OpenPGP, Up: Protocols and Engines
+File: gpgme.info, Node: Cryptographic Message Syntax, Next: Assuan, Prev: OpenPGP, Up: Protocols and Engines
3.5 Cryptographic Message Syntax
================================
@@ -999,6 +1067,18 @@ CMS is implemented by GpgSM, the S/MIME implementation for GnuPG.
The CMS protocol is specified by ‘GPGME_PROTOCOL_CMS’.

+File: gpgme.info, Node: Assuan, Prev: Cryptographic Message Syntax, Up: Protocols and Engines
+
+3.6 Assuan
+==========
+
+Assuan is the RPC library used by the various GnuPG components. The
+Assuan protocol allows one to talk to arbitrary Assuan servers using
+GPGME. *Note Using the Assuan protocol::.
+
+ The ASSUAN protocol is specified by ‘GPGME_PROTOCOL_ASSUAN’.
+
+
File: gpgme.info, Node: Algorithms, Next: Error Handling, Prev: Protocols and Engines, Up: Top
4 Algorithms
@@ -1065,6 +1145,9 @@ verification of signatures.
This value indicates ECDH, the Eliptic Curve Diffie-Hellmann
encryption algorithm as defined by RFC-6637.
+ ‘GPGME_PK_EDDSA’
+ This value indicates the EdDSA algorithm.
+
-- Function: const char * gpgme_pubkey_algo_name
(gpgme_pubkey_algo_t ALGO)
The function ‘gpgme_pubkey_algo_name’ returns a pointer to a
@@ -1074,6 +1157,13 @@ verification of signatures.
If ALGO is not a valid public key algorithm, ‘NULL’ is returned.
+ -- Function: char * gpgme_pubkey_algo_string (gpgme_subkey_t KEY)
+ The function ‘gpgme_pubkey_algo_string’ is a convenience function
+ to build and return an algorithm string in the same way GnuPG does
+ (e.g. “rsa2048†or “ed25519â€). The caller must free the result
+ using ‘gpgme_free’. On error (e.g. invalid argument or memory
+ exhausted), the function returns NULL and sets ‘ERRNO’.
+

File: gpgme.info, Node: Hash Algorithms, Prev: Public Key Algorithms, Up: Algorithms
@@ -1764,33 +1854,6 @@ yourself and create a data object from these callback functions.
object was successfully created, and ‘GPG_ERR_ENOMEM’ if not enough
memory is available.
- The following interface is deprecated and only provided for backward
-compatibility. Don’t use it. It will be removed in a future version of
-GPGME.
-
- -- Function: gpgme_error_t gpgme_data_new_with_read_cb
- (gpgme_data_t *DH, int (*READFUNC) (void *HOOK, char *BUFFER,
- size_t COUNT, size_t *NREAD), void *HOOK_VALUE)
- The function ‘gpgme_data_new_with_read_cb’ creates a new
- ‘gpgme_data_t’ object and uses the callback function READFUNC to
- retrieve the data on demand. As the callback function can supply
- the data in any way it wants, this is the most flexible data type
- GPGME provides. However, it can not be used to write data.
-
- The callback function receives HOOK_VALUE as its first argument
- whenever it is invoked. It should return up to COUNT bytes in
- BUFFER, and return the number of bytes actually read in NREAD. It
- may return ‘0’ in NREAD if no data is currently available. To
- indicate ‘EOF’ the function should return with an error code of
- ‘-1’ and set NREAD to ‘0’. The callback function may support to
- reset its internal read pointer if it is invoked with BUFFER and
- NREAD being ‘NULL’ and COUNT being ‘0’.
-
- The function returns the error code ‘GPG_ERR_NO_ERROR’ if the data
- object was successfully created, ‘GPG_ERR_INV_VALUE’ if DH or
- READFUNC is not a valid pointer, and ‘GPG_ERR_ENOMEM’ if not enough
- memory is available.
-

File: gpgme.info, Node: Destroying Data Buffers, Next: Manipulating Data Buffers, Prev: Creating Data Buffers, Up: Exchanging Data
@@ -1818,9 +1881,10 @@ File: gpgme.info, Node: Destroying Data Buffers, Next: Manipulating Data Buffe
-- Function: void gpgme_free (void *BUFFER)
The function ‘gpgme_free’ releases the memory returned by
- ‘gpgme_data_release_and_get_mem’. It should be used instead of the
- system libraries ‘free’ function in case different allocators are
- used in a single program.
+ ‘gpgme_data_release_and_get_mem’ and ‘gpgme_pubkey_algo_string’.
+ It should be used instead of the system libraries ‘free’ function
+ in case different allocators are used by a program. This is often
+ the case if gpgme is used under Windows as a DLL.

File: gpgme.info, Node: Manipulating Data Buffers, Prev: Destroying Data Buffers, Up: Exchanging Data
@@ -1894,15 +1958,6 @@ File: gpgme.info, Node: Data Buffer I/O Operations, Next: Data Buffer Meta-Dat
If the function fails, -1 is returned and ERRNO is set.
- The following function is deprecated and should not be used. It will
-be removed in a future version of GPGME.
-
- -- Function: gpgme_error_t gpgme_data_rewind (gpgme_data_t DH)
- The function ‘gpgme_data_rewind’ is equivalent to:
-
- return (gpgme_data_seek (dh, 0, SEEK_SET) == -1)
- ? gpgme_error_from_errno (errno) : 0;
-

File: gpgme.info, Node: Data Buffer Meta-Data, Next: Data Buffer Convenience, Prev: Data Buffer I/O Operations, Up: Manipulating Data Buffers
@@ -1956,6 +2011,9 @@ File: gpgme.info, Node: Data Buffer Meta-Data, Next: Data Buffer Convenience,
This specifies that the data is encoded in an armored form as
used by OpenPGP and PEM.
+ ‘GPGME_DATA_ENCODING_MIME’
+ This specifies that the data is encoded as a MIME part.
+
‘GPGME_DATA_ENCODING_URL’
The data is a list of linefeed delimited URLs. This is only
useful with ‘gpgme_op_import’.
@@ -1980,6 +2038,24 @@ File: gpgme.info, Node: Data Buffer Meta-Data, Next: Data Buffer Convenience,
The function ‘gpgme_data_set_encoding’ changes the encoding of the
data object with the handle DH to ENC.
+ -- Function: gpgme_error_t gpgme_data_set_flag (gpgme_data_t DH,
+ const char *NAME, const char *VALUE)
+
+ Some minor properties of the data object can be controlled with
+ flags set by this function. The properties are identified by the
+ following values for NAME:
+
+ ‘size-hint’
+ The value is a decimal number with the length gpgme shall
+ assume for this data object. This is useful if the data is
+ provided by callbacks or via file descriptors but the
+ applications knows the total size of the data. If this is set
+ the OpenPGP engine may use this to decide on buffer allocation
+ strategies and to provide a total value for its progress
+ information.
+
+ This function returns ‘0’ on success.
+

File: gpgme.info, Node: Data Buffer Convenience, Prev: Data Buffer Meta-Data, Up: Manipulating Data Buffers
@@ -2126,6 +2202,7 @@ File: gpgme.info, Node: Context Attributes, Next: Key Management, Prev: Resul
* ASCII Armor:: Requesting ASCII armored output.
* Text Mode:: Choosing canonical text mode.
* Offline Mode:: Choosing offline mode.
+* Pinentry Mode:: Choosing the pinentry mode.
* Included Certificates:: Including a number of certificates.
* Key Listing Mode:: Selecting key listing mode.
* Passphrase Callback:: Getting the passphrase from the user.
@@ -2244,7 +2321,7 @@ File: gpgme.info, Node: Text Mode, Next: Offline Mode, Prev: ASCII Armor, Up
is enabled, and ‘0’ if it is not, or if CTX is not a valid pointer.

-File: gpgme.info, Node: Offline Mode, Next: Included Certificates, Prev: Text Mode, Up: Context Attributes
+File: gpgme.info, Node: Offline Mode, Next: Pinentry Mode, Prev: Text Mode, Up: Context Attributes
7.4.5 Offline Mode
------------------
@@ -2271,9 +2348,54 @@ File: gpgme.info, Node: Offline Mode, Next: Included Certificates, Prev: Text
enabled, and ‘0’ if it is not, or if CTX is not a valid pointer.

-File: gpgme.info, Node: Included Certificates, Next: Key Listing Mode, Prev: Offline Mode, Up: Context Attributes
+File: gpgme.info, Node: Pinentry Mode, Next: Included Certificates, Prev: Offline Mode, Up: Context Attributes
+
+7.4.6 Pinentry Mode
+-------------------
+
+ -- Function: gpgme_error_t gpgme_set_pinentry_mode (gpgme_ctx_t CTX,
+ gpgme_pinentry_mode_t MODE) The function ‘gpgme_set_pinentry_mode’
+ specifies the pinentry mode to be used.
+
+ For GnuPG >= 2.1 this option is required to be set to
+ ‘GPGME_PINENTRY_MODE_LOOPBACK’ to enable the passphrase callback
+ mechanism in GPGME through ‘gpgme_set_passphrase_cb’.
+
+ -- Function: gpgme_pinentry_mode_t gpgme_get_pinentry_mode
+ (gpgme_ctx_t CTX)
+ The function ‘gpgme_get_pinenty_mode’ returns the mode set for the
+ context.
+
+ -- Data type: enum gpgme_pinentry_mode_t
+ The ‘gpgme_minentry_mode_t’ type specifies the set of possible
+ pinentry modes that are supported by GPGME if GnuPG >= 2.1 is used.
+ The following modes are supported:
+
+ ‘GPGME_PINENTRY_MODE_DEFAULT’
+ Use the default of the agent, which is ask.
+
+ ‘GPGME_PINENTRY_MODE_ASK’
+ Force the use of the Pinentry.
+
+ ‘GPGME_PINENTRY_MODE_CANCEL’
+ Emulate use of Pinentry’s cancel button.
+
+ ‘GPGME_PINENTRY_MODE_ERROR’
+ Return a Pinentry error ‘No Pinentry’.
+
+ ‘GPGME_PINENTRY_MODE_LOOPBACK’
+ Redirect Pinentry queries to the caller. This enables the use
+ of ‘gpgme_set_passphrase_cb’ whis pinentry queries redirected
+ to gpgme.
+
+ Note: This mode requires ‘allow-loopback-pinentry’ to be
+ enabled in the ‘gpg-agent.conf’ or an agent started with that
+ option.
+
+
+File: gpgme.info, Node: Included Certificates, Next: Key Listing Mode, Prev: Pinentry Mode, Up: Context Attributes
-7.4.6 Included Certificates
+7.4.7 Included Certificates
---------------------------
-- Function: void gpgme_set_include_certs (gpgme_ctx_t CTX,
@@ -2311,7 +2433,7 @@ File: gpgme.info, Node: Included Certificates, Next: Key Listing Mode, Prev:

File: gpgme.info, Node: Key Listing Mode, Next: Passphrase Callback, Prev: Included Certificates, Up: Context Attributes
-7.4.7 Key Listing Mode
+7.4.8 Key Listing Mode
----------------------
-- Function: gpgme_error_t gpgme_set_keylist_mode (gpgme_ctx_t CTX,
@@ -2343,6 +2465,11 @@ File: gpgme.info, Node: Key Listing Mode, Next: Passphrase Callback, Prev: In
in the listed keys. This only works if
‘GPGME_KEYLIST_MODE_SIGS’ is also enabled.
+ ‘GPGME_KEYLIST_MODE_WITH_TOFU’
+ The ‘GPGME_KEYLIST_MODE_WITH_TOFU’ symbol specifies that
+ information pertaining to the TOFU trust model should be
+ included in the listed keys.
+
‘GPGME_KEYLIST_MODE_WITH_SECRET’
The ‘GPGME_KEYLIST_MODE_WITH_SECRET’ returns information about
the presence of a corresponding secret key in a public key
@@ -2389,7 +2516,7 @@ File: gpgme.info, Node: Key Listing Mode, Next: Passphrase Callback, Prev: In

File: gpgme.info, Node: Passphrase Callback, Next: Progress Meter Callback, Prev: Key Listing Mode, Up: Context Attributes
-7.4.8 Passphrase Callback
+7.4.9 Passphrase Callback
-------------------------
-- Data type: gpgme_error_t (*gpgme_passphrase_cb_t)(void *HOOK, const
@@ -2437,6 +2564,10 @@ File: gpgme.info, Node: Passphrase Callback, Next: Progress Meter Callback, P
even support an external passphrase callback at all, in this case
the error code ‘GPG_ERR_NOT_SUPPORTED’ is returned.
+ For GnuPG >= 2.1 the pinentry mode has to be set to
+ ‘GPGME_PINENTRY_MODE_LOOPBACK’ to enable the passphrase callback.
+ See ‘gpgme_set_pinentry_mode’.
+
The user can disable the use of a passphrase callback function by
calling ‘gpgme_set_passphrase_cb’ with PASSFUNC being ‘NULL’.
@@ -2454,8 +2585,8 @@ File: gpgme.info, Node: Passphrase Callback, Next: Progress Meter Callback, P

File: gpgme.info, Node: Progress Meter Callback, Next: Status Message Callback, Prev: Passphrase Callback, Up: Context Attributes
-7.4.9 Progress Meter Callback
------------------------------
+7.4.10 Progress Meter Callback
+------------------------------
-- Data type: void (*gpgme_progress_cb_t)(void *HOOK, const char *WHAT,
int TYPE, int CURRENT, int TOTAL)
@@ -2496,7 +2627,7 @@ File: gpgme.info, Node: Progress Meter Callback, Next: Status Message Callback

File: gpgme.info, Node: Status Message Callback, Next: Locale, Prev: Progress Meter Callback, Up: Context Attributes
-7.4.10 Status Message Callback
+7.4.11 Status Message Callback
------------------------------
-- Data type: gpgme_error_t (*gpgme_status_cb_t)(void *HOOK, const char
@@ -2530,10 +2661,31 @@ File: gpgme.info, Node: Status Message Callback, Next: Locale, Prev: Progress
message callback is set, or CTX is not a valid pointer, ‘NULL’ is
returned in both variables.
+ -- Function: gpgme_error_t gpgme_set_ctx_flag (gpgme_ctx_t CTX,
+ const char *NAME, const char *VALUE)
+
+ Some minor properties of the context can be controlled with flags
+ set by this function. The properties are identified by the
+ following values for NAME:
+
+ ‘"full-status"’
+ Using a VALUE of "1" the status callback set by
+ gpgme_set_status_cb returns all status lines with the
+ exception of PROGRESS lines. With the default of "0" the
+ status callback is only called in certain situations.
+
+ ‘"raw-description"’
+ Setting the VALUE to "1" returns human readable strings in a
+ raw format. For example the non breaking space characters
+ ("~") will not be removed from the ‘description’ field of the
+ ‘gpgme_tofu_info_t’ object.
+
+ This function returns ‘0’ on success.
+

File: gpgme.info, Node: Locale, Prev: Status Message Callback, Up: Context Attributes
-7.4.11 Locale
+7.4.12 Locale
-------------
A locale setting can be associated with a context. This locale is
@@ -2578,13 +2730,123 @@ are specified. This is always done by specifying the respective keys
that should be used for the operation. The following section describes
how such keys can be selected and manipulated.
+* Menu:
+
+* Key objects:: Description of the key structures.
+* Listing Keys:: Browsing the list of available keys.
+* Information About Keys:: Requesting detailed information about keys.
+* Manipulating Keys:: Operations on keys.
+* Generating Keys:: Creating new key pairs.
+* Signing Keys:: Adding key signatures to public keys.
+* Exporting Keys:: Retrieving key data from the key ring.
+* Importing Keys:: Adding keys to the key ring.
+* Deleting Keys:: Removing keys from the key ring.
+* Changing Passphrases:: Change the passphrase of a key.
+* Changing TOFU Data:: Changing data pertaining to TOFU.
+* Advanced Key Editing:: Advanced key edit operation.
+
+
+File: gpgme.info, Node: Key objects, Next: Listing Keys, Up: Key Management
+
+7.5.1 Key objects
+-----------------
+
+The keys are represented in GPGME by structures which may only be read
+by the application but never be allocated or changed. They are valid as
+long as the key object itself is valid.
+
+ -- Data type: gpgme_key_t
+
+ The ‘gpgme_key_t’ type is a pointer to a key object. It has the
+ following members:
+
+ ‘gpgme_keylist_mode_t keylist_mode’
+ The keylist mode that was active when the key was retrieved.
+
+ ‘unsigned int revoked : 1’
+ This is true if the key is revoked.
+
+ ‘unsigned int expired : 1’
+ This is true if the key is expired.
+
+ ‘unsigned int disabled : 1’
+ This is true if the key is disabled.
+
+ ‘unsigned int invalid : 1’
+ This is true if the key is invalid. This might have several
+ reasons, for a example for the S/MIME backend, it will be set
+ during key listings if the key could not be validated due to
+ missing certificates or unmatched policies.
+
+ ‘unsigned int can_encrypt : 1’
+ This is true if the key (ie one of its subkeys) can be used
+ for encryption.
+
+ ‘unsigned int can_sign : 1’
+ This is true if the key (ie one of its subkeys) can be used to
+ create data signatures.
+
+ ‘unsigned int can_certify : 1’
+ This is true if the key (ie one of its subkeys) can be used to
+ create key certificates.
+
+ ‘unsigned int can_authenticate : 1’
+ This is true if the key (ie one of its subkeys) can be used
+ for authentication.
+
+ ‘unsigned int is_qualified : 1’
+ This is true if the key can be used for qualified signatures
+ according to local government regulations.
+
+ ‘unsigned int secret : 1’
+ This is true if the key is a secret key. Note, that this will
+ always be true even if the corresponding subkey flag may be
+ false (offline/stub keys). This is only set if a listing of
+ secret keys has been requested or if
+ ‘GPGME_KEYLIST_MODE_WITH_SECRET’ is active.
+
+ ‘gpgme_protocol_t protocol’
+ This is the protocol supported by this key.
+
+ ‘char *issuer_serial’
+ If ‘protocol’ is ‘GPGME_PROTOCOL_CMS’, then this is the issuer
+ serial.
+
+ ‘char *issuer_name’
+ If ‘protocol’ is ‘GPGME_PROTOCOL_CMS’, then this is the issuer
+ name.
+
+ ‘char *chain_id’
+ If ‘protocol’ is ‘GPGME_PROTOCOL_CMS’, then this is the chain
+ ID, which can be used to built the certificate chain.
+
+ ‘gpgme_validity_t owner_trust’
+ If ‘protocol’ is ‘GPGME_PROTOCOL_OpenPGP’, then this is the
+ owner trust.
+
+ ‘gpgme_subkey_t subkeys’
+ This is a linked list with the subkeys of the key. The first
+ subkey in the list is the primary key and usually available.
+
+ ‘gpgme_user_id_t uids’
+ This is a linked list with the user IDs of the key. The first
+ user ID in the list is the main (or primary) user ID.
+
+ ‘char *fpr’
+ This field gives the fingerprint of the primary key. Note
+ that this is a copy of the fingerprint of the first subkey.
+ For an incomplete key (for example from a verification result)
+ a subkey may be missing but this field may be set
+ nevertheless.
+
-- Data type: gpgme_subkey_t
- The ‘gpgme_subkey_t’ type is a pointer to a subkey structure. Sub
- keys are one component of a ‘gpgme_key_t’ object. In fact, subkeys
- are those parts that contains the real information about the
- individual cryptographic keys that belong to the same key object.
- One ‘gpgme_key_t’ can contain several subkeys. The first subkey in
- the linked list is also called the primary key.
+
+ The ‘gpgme_subkey_t’ type is a pointer to a subkey structure.
+ Subkeys are one component of a ‘gpgme_key_t’ object. In fact,
+ subkeys are those parts that contains the real information about
+ the individual cryptographic keys that belong to the same key
+ object. One ‘gpgme_key_t’ can contain several subkeys. The first
+ subkey in the linked list is also called the primary key.
The subkey structure has the following members:
@@ -2642,6 +2904,10 @@ how such keys can be selected and manipulated.
This is the fingerprint of the subkey in hexadecimal digits,
if available.
+ ‘char *keygrip’
+ The keygrip of the subkey in hex digit form or ‘NULL’ if not
+ availabale.
+
‘long int timestamp’
This is the creation timestamp of the subkey. This is -1 if
the timestamp is invalid, and 0 if it is not available.
@@ -2657,12 +2923,59 @@ how such keys can be selected and manipulated.
The serial number of a smart card holding this key or ‘NULL’.
‘char *curve’
- For ECC algoritms the name of the curve.
+ For ECC algorithms the name of the curve.
+
+ -- Data type: gpgme_user_id_t
+
+ A user ID is a component of a ‘gpgme_key_t’ object. One key can
+ have many user IDs. The first one in the list is the main (or
+ primary) user ID.
+
+ The user ID structure has the following members.
+
+ ‘gpgme_user_id_t next’
+ This is a pointer to the next user ID structure in the linked
+ list, or ‘NULL’ if this is the last element.
+
+ ‘unsigned int revoked : 1’
+ This is true if the user ID is revoked.
+
+ ‘unsigned int invalid : 1’
+ This is true if the user ID is invalid.
+
+ ‘gpgme_validity_t validity’
+ This specifies the validity of the user ID.
+
+ ‘char *uid’
+ This is the user ID string.
+
+ ‘char *name’
+ This is the name component of ‘uid’, if available.
+
+ ‘char *comment’
+ This is the comment component of ‘uid’, if available.
+
+ ‘char *email’
+ This is the email component of ‘uid’, if available.
+
+ ‘char *address;’
+ The mail address (addr-spec from RFC-5322) of the user ID
+ string. This is general the same as the ‘email’ part of this
+ structure but might be slightly different. If no mail address
+ is available ‘NULL’ is stored.
+
+ ‘gpgme_tofu_info_t tofu’
+ If not ‘NULL’ information from the TOFU database pertaining to
+ this user id.
+
+ ‘gpgme_key_sig_t signatures’
+ This is a linked list with the signatures on this user ID.
-- Data type: gpgme_key_sig_t
+
The ‘gpgme_key_sig_t’ type is a pointer to a key signature
structure. Key signatures are one component of a ‘gpgme_key_t’
- object, and validate user IDs on the key.
+ object, and validate user IDs on the key in the OpenPGP protocol.
The signatures on a key are only available if the key was retrieved
via a listing operation with the ‘GPGME_KEYLIST_MODE_SIGS’ mode
@@ -2732,134 +3045,10 @@ how such keys can be selected and manipulated.
‘gpgme_sig_notation_t notations’
This is a linked list with the notation data and policy URLs.
- -- Data type: gpgme_user_id_t
- A user ID is a component of a ‘gpgme_key_t’ object. One key can
- have many user IDs. The first one in the list is the main (or
- primary) user ID.
-
- The user ID structure has the following members.
-
- ‘gpgme_user_id_t next’
- This is a pointer to the next user ID structure in the linked
- list, or ‘NULL’ if this is the last element.
-
- ‘unsigned int revoked : 1’
- This is true if the user ID is revoked.
-
- ‘unsigned int invalid : 1’
- This is true if the user ID is invalid.
-
- ‘gpgme_validity_t validity’
- This specifies the validity of the user ID.
-
- ‘char *uid’
- This is the user ID string.
-
- ‘char *name’
- This is the name component of ‘uid’, if available.
-
- ‘char *comment’
- This is the comment component of ‘uid’, if available.
-
- ‘char *email’
- This is the email component of ‘uid’, if available.
-
- ‘gpgme_key_sig_t signatures’
- This is a linked list with the signatures on this user ID.
-
- -- Data type: gpgme_key_t
- The ‘gpgme_key_t’ type is a pointer to a key object. It has the
- following members:
-
- ‘gpgme_keylist_mode_t keylist_mode’
- The keylist mode that was active when the key was retrieved.
-
- ‘unsigned int revoked : 1’
- This is true if the key is revoked.
-
- ‘unsigned int expired : 1’
- This is true if the key is expired.
-
- ‘unsigned int disabled : 1’
- This is true if the key is disabled.
-
- ‘unsigned int invalid : 1’
- This is true if the key is invalid. This might have several
- reasons, for a example for the S/MIME backend, it will be set
- in during key listsing if the key could not be validated due
- to a missing certificates or unmatched policies.
-
- ‘unsigned int can_encrypt : 1’
- This is true if the key (ie one of its subkeys) can be used
- for encryption.
-
- ‘unsigned int can_sign : 1’
- This is true if the key (ie one of its subkeys) can be used to
- create data signatures.
-
- ‘unsigned int can_certify : 1’
- This is true if the key (ie one of its subkeys) can be used to
- create key certificates.
-
- ‘unsigned int can_authenticate : 1’
- This is true if the key (ie one of its subkeys) can be used
- for authentication.
-
- ‘unsigned int is_qualified : 1’
- This is true if the key can be used for qualified signatures
- according to local government regulations.
-
- ‘unsigned int secret : 1’
- This is true if the key is a secret key. Note, that this will
- always be true even if the corresponding subkey flag may be
- false (offline/stub keys). This is only set if a listing of
- secret keys has been requested or if
- ‘GPGME_KEYLIST_MODE_WITH_SECRET’ is active.
-
- ‘gpgme_protocol_t protocol’
- This is the protocol supported by this key.
-
- ‘char *issuer_serial’
- If ‘protocol’ is ‘GPGME_PROTOCOL_CMS’, then this is the issuer
- serial.
-
- ‘char *issuer_name’
- If ‘protocol’ is ‘GPGME_PROTOCOL_CMS’, then this is the issuer
- name.
-
- ‘char *chain_id’
- If ‘protocol’ is ‘GPGME_PROTOCOL_CMS’, then this is the chain
- ID, which can be used to built the certificate chain.
-
- ‘gpgme_validity_t owner_trust’
- If ‘protocol’ is ‘GPGME_PROTOCOL_OpenPGP’, then this is the
- owner trust.
-
- ‘gpgme_subkey_t subkeys’
- This is a linked list with the subkeys of the key. The first
- subkey in the list is the primary key and usually available.
-
- ‘gpgme_user_id_t uids’
- This is a linked list with the user IDs of the key. The first
- user ID in the list is the main (or primary) user ID.
-
-* Menu:
-
-* Listing Keys:: Browsing the list of available keys.
-* Information About Keys:: Requesting detailed information about keys.
-* Key Signatures:: Listing the signatures on a key.
-* Manipulating Keys:: Operations on keys.
-* Generating Keys:: Creating new key pairs.
-* Exporting Keys:: Retrieving key data from the key ring.
-* Importing Keys:: Adding keys to the key ring.
-* Deleting Keys:: Removing keys from the key ring.
-* Changing Passphrases:: Change the passphrase of a key.
-* Advanced Key Editing:: Advanced key edit operation.
-

-File: gpgme.info, Node: Listing Keys, Next: Information About Keys, Up: Key Management
+File: gpgme.info, Node: Listing Keys, Next: Information About Keys, Prev: Key objects, Up: Key Management
-7.5.1 Listing Keys
+7.5.2 Listing Keys
------------------
-- Function: gpgme_error_t gpgme_op_keylist_start (gpgme_ctx_t CTX,
@@ -3020,9 +3209,9 @@ the following function can be used to retrieve a single key.
operation there was not enough memory available.

-File: gpgme.info, Node: Information About Keys, Next: Key Signatures, Prev: Listing Keys, Up: Key Management
+File: gpgme.info, Node: Information About Keys, Next: Manipulating Keys, Prev: Listing Keys, Up: Key Management
-7.5.2 Information About Keys
+7.5.3 Information About Keys
----------------------------
Please see the beginning of this section for more information about
@@ -3056,281 +3245,8 @@ Please see the beginning of this section for more information about
The user ID is ultimately valid. The string representation of
this validity is “uâ€.
- The following interfaces are deprecated and only provided for
-backward compatibility. Don’t use them. They will be removed in a
-future version of GPGME.
-
- -- Data type: gpgme_attr_t
- The ‘gpgme_attr_t’ type is used to specify a key or trust item
- attribute. The following attributes are defined:
-
- ‘GPGME_ATTR_KEYID’
- This is the key ID of a sub key. It is representable as a
- string.
-
- For trust items, the trust item refers to the key with this
- ID.
-
- ‘GPGME_ATTR_FPR’
- This is the fingerprint of a sub key. It is representable as
- a string.
-
- ‘GPGME_ATTR_ALGO’
- This is the crypto algorithm for which the sub key can be
- used. It is representable as a string and as a number. The
- numbers correspond to the ‘enum gcry_pk_algos’ values in the
- gcrypt library.
-
- ‘GPGME_ATTR_LEN’
- This is the key length of a sub key. It is representable as a
- number.
-
- ‘GPGME_ATTR_CREATED’
- This is the timestamp at creation time of a sub key. It is
- representable as a number.
-
- ‘GPGME_ATTR_EXPIRE’
- This is the expiration time of a sub key. It is representable
- as a number.
-
- ‘GPGME_ATTR_OTRUST’
- XXX FIXME (also for trust items)
-
- ‘GPGME_ATTR_USERID’
- This is a user ID. There can be more than one user IDs in a
- GPGME_KEY_T object. The first one (with index 0) is the
- primary user ID. The user ID is representable as a number.
-
- For trust items, this is the user ID associated with this
- trust item.
-
- ‘GPGME_ATTR_NAME’
- This is the name belonging to a user ID. It is representable
- as a string.
-
- ‘GPGME_ATTR_EMAIL’
- This is the email address belonging to a user ID. It is
- representable as a string.
-
- ‘GPGME_ATTR_COMMENT’
- This is the comment belonging to a user ID. It is
- representable as a string.
-
- ‘GPGME_ATTR_VALIDITY’
- This is the validity belonging to a user ID. It is
- representable as a string and as a number. See below for a
- list of available validities.
-
- For trust items, this is the validity that is associated with
- this trust item.
-
- ‘GPGME_ATTR_UID_REVOKED’
- This specifies if a user ID is revoked. It is representable
- as a number, and is ‘1’ if the user ID is revoked, and ‘0’
- otherwise.
-
- ‘GPGME_ATTR_UID_INVALID’
- This specifies if a user ID is invalid. It is representable
- as a number, and is ‘1’ if the user ID is invalid, and ‘0’
- otherwise.
-
- ‘GPGME_ATTR_LEVEL’
- This is the trust level of a trust item.
-
- ‘GPGME_ATTR_TYPE’
- This returns information about the type of key. For the
- string function this will eother be "PGP" or "X.509". The
- integer function returns 0 for PGP and 1 for X.509. It is
- also used for the type of a trust item.
-
- ‘GPGME_ATTR_IS_SECRET’
- This specifies if the key is a secret key. It is
- representable as a number, and is ‘1’ if the key is revoked,
- and ‘0’ otherwise.
-
- ‘GPGME_ATTR_KEY_REVOKED’
- This specifies if a sub key is revoked. It is representable
- as a number, and is ‘1’ if the key is revoked, and ‘0’
- otherwise.
-
- ‘GPGME_ATTR_KEY_INVALID’
- This specifies if a sub key is invalid. It is representable
- as a number, and is ‘1’ if the key is invalid, and ‘0’
- otherwise.
-
- ‘GPGME_ATTR_KEY_EXPIRED’
- This specifies if a sub key is expired. It is representable
- as a number, and is ‘1’ if the key is expired, and ‘0’
- otherwise.
-
- ‘GPGME_ATTR_KEY_DISABLED’
- This specifies if a sub key is disabled. It is representable
- as a number, and is ‘1’ if the key is disabled, and ‘0’
- otherwise.
-
- ‘GPGME_ATTR_KEY_CAPS’
- This is a description of the capabilities of a sub key. It is
- representable as a string. The string contains the letter “eâ€
- if the key can be used for encryption, “s†if the key can be
- used for signatures, and “c†if the key can be used for
- certifications.
-
- ‘GPGME_ATTR_CAN_ENCRYPT’
- This specifies if a sub key can be used for encryption. It is
- representable as a number, and is ‘1’ if the sub key can be
- used for encryption, and ‘0’ otherwise.
-
- ‘GPGME_ATTR_CAN_SIGN’
- This specifies if a sub key can be used to create data
- signatures. It is representable as a number, and is ‘1’ if
- the sub key can be used for signatures, and ‘0’ otherwise.
-
- ‘GPGME_ATTR_CAN_CERTIFY’
- This specifies if a sub key can be used to create key
- certificates. It is representable as a number, and is ‘1’ if
- the sub key can be used for certifications, and ‘0’ otherwise.
-
- ‘GPGME_ATTR_SERIAL’
- The X.509 issuer serial attribute of the key. It is
- representable as a string.
-
- ‘GPGME_ATTR_ISSUE’
- The X.509 issuer name attribute of the key. It is
- representable as a string.
-
- ‘GPGME_ATTR_CHAINID’
- The X.509 chain ID can be used to build the certification
- chain. It is representable as a string.
-
- -- Function: const char * gpgme_key_get_string_attr (gpgme_key_t KEY,
- gpgme_attr_t WHAT, const void *RESERVED, int IDX)
- The function ‘gpgme_key_get_string_attr’ returns the value of the
- string-representable attribute WHAT of key KEY. If the attribute
- is an attribute of a sub key or an user ID, IDX specifies the sub
- key or user ID of which the attribute value is returned. The
- argument RESERVED is reserved for later use and should be ‘NULL’.
-
- The string returned is only valid as long as the key is valid.
-
- The function returns ‘0’ if an attribute can’t be returned as a
- string, KEY is not a valid pointer, IDX out of range, or RESERVED
- not ‘NULL’.
-
- -- Function: unsigned long gpgme_key_get_ulong_attr (gpgme_key_t KEY,
- gpgme_attr_t WHAT, const void *RESERVED, int IDX)
- The function ‘gpgme_key_get_ulong_attr’ returns the value of the
- number-representable attribute WHAT of key KEY. If the attribute
- is an attribute of a sub key or an user ID, IDX specifies the sub
- key or user ID of which the attribute value is returned. The
- argument RESERVED is reserved for later use and should be ‘NULL’.
-
- The function returns ‘0’ if the attribute can’t be returned as a
- number, KEY is not a valid pointer, IDX out of range, or RESERVED
- not ‘NULL’.
-
-
-File: gpgme.info, Node: Key Signatures, Next: Manipulating Keys, Prev: Information About Keys, Up: Key Management
-
-7.5.3 Key Signatures
---------------------
-
-The following interfaces are deprecated and only provided for backward
-compatibility. Don’t use them. They will be removed in a future
-version of GPGME.
-
- The signatures on a key are only available if the key was retrieved
-via a listing operation with the ‘GPGME_KEYLIST_MODE_SIGS’ mode enabled,
-because it is expensive to retrieve all signatures of a key.
-
- So, before using the below interfaces to retrieve the signatures on a
-key, you have to make sure that the key was listed with signatures
-enabled. One convenient, but blocking, way to do this is to use the
-function ‘gpgme_get_key’.
-
- -- Data type: gpgme_attr_t
- The ‘gpgme_attr_t’ type is used to specify a key signature
- attribute. The following attributes are defined:
-
- ‘GPGME_ATTR_KEYID’
- This is the key ID of the key which was used for the
- signature. It is representable as a string.
-
- ‘GPGME_ATTR_ALGO’
- This is the crypto algorithm used to create the signature. It
- is representable as a string and as a number. The numbers
- correspond to the ‘enum gcry_pk_algos’ values in the gcrypt
- library.
-
- ‘GPGME_ATTR_CREATED’
- This is the timestamp at creation time of the signature. It
- is representable as a number.
-
- ‘GPGME_ATTR_EXPIRE’
- This is the expiration time of the signature. It is
- representable as a number.
-
- ‘GPGME_ATTR_USERID’
- This is the user ID associated with the signing key. The user
- ID is representable as a number.
-
- ‘GPGME_ATTR_NAME’
- This is the name belonging to a user ID. It is representable
- as a string.
-
- ‘GPGME_ATTR_EMAIL’
- This is the email address belonging to a user ID. It is
- representable as a string.
-
- ‘GPGME_ATTR_COMMENT’
- This is the comment belonging to a user ID. It is
- representable as a string.
-
- ‘GPGME_ATTR_KEY_REVOKED’
- This specifies if a key signature is a revocation signature.
- It is representable as a number, and is ‘1’ if the key is
- revoked, and ‘0’ otherwise.
-
- ‘GPGME_ATTR_SIG_CLASS’
- This specifies the signature class of a key signature. It is
- representable as a number. The meaning is specific to the
- crypto engine.
-
- ‘GPGME_ATTR_SIG_CLASS’
- This specifies the signature class of a key signature. It is
- representable as a number. The meaning is specific to the
- crypto engine.
-
- ‘GPGME_ATTR_SIG_STATUS’
- This is the same value as returned by ‘gpgme_get_sig_status’.
-
- -- Function: const char * gpgme_key_sig_get_string_attr
- (gpgme_key_t KEY, int UID_IDX, gpgme_attr_t WHAT,
- const void *RESERVED, int IDX)
- The function ‘gpgme_key_sig_get_string_attr’ returns the value of
- the string-representable attribute WHAT of the signature IDX on the
- user ID UID_IDX in the key KEY. The argument RESERVED is reserved
- for later use and should be ‘NULL’.
-
- The string returned is only valid as long as the key is valid.
-
- The function returns ‘0’ if an attribute can’t be returned as a
- string, KEY is not a valid pointer, UID_IDX or IDX out of range, or
- RESERVED not ‘NULL’.
-
- -- Function: unsigned long gpgme_key_sig_get_ulong_attr
- (gpgme_key_t KEY, int UID_IDX, gpgme_attr_t WHAT,
- const void *RESERVED, int IDX)
- The function ‘gpgme_key_sig_get_ulong_attr’ returns the value of
- the number-representable attribute WHAT of the signature IDX on the
- user ID UID_IDX in the key KEY. The argument RESERVED is reserved
- for later use and should be ‘NULL’.
-
- The function returns ‘0’ if an attribute can’t be returned as a
- string, KEY is not a valid pointer, UID_IDX or IDX out of range, or
- RESERVED not ‘NULL’.
-

-File: gpgme.info, Node: Manipulating Keys, Next: Generating Keys, Prev: Key Signatures, Up: Key Management
+File: gpgme.info, Node: Manipulating Keys, Next: Generating Keys, Prev: Information About Keys, Up: Key Management
7.5.4 Manipulating Keys
-----------------------
@@ -3344,27 +3260,239 @@ File: gpgme.info, Node: Manipulating Keys, Next: Generating Keys, Prev: Key S
KEY. If this was the last reference, the key will be destroyed and
all resources associated to it will be released.
- The following interface is deprecated and only provided for backward
-compatibility. Don’t use it. It will be removed in a future version of
-GPGME.
-
- -- Function: void gpgme_key_release (gpgme_key_t KEY)
- The function ‘gpgme_key_release’ is equivalent to
- ‘gpgme_key_unref’.
-

-File: gpgme.info, Node: Generating Keys, Next: Exporting Keys, Prev: Manipulating Keys, Up: Key Management
+File: gpgme.info, Node: Generating Keys, Next: Signing Keys, Prev: Manipulating Keys, Up: Key Management
7.5.5 Generating Keys
---------------------
+GPGME provides a set of functions to create public key pairs. Most of
+these functions require the use of GnuPG 2.1 and later; for older GnuPG
+versions the ‘gpgme_op_genkey’ function can be used. Existing code
+which wants to update to the new functions or new code which shall
+supports older GnuPG versions may try the new functions first and
+provide a fallback to the old function if the error code
+‘GPG_ERR_NOT_SUPPORTED’ is received.
+
+ -- Function: gpgme_error_t gpgme_op_createkey (gpgme_ctx_t CTX,
+ const char *USERID, const char *ALGO, unsigned long RESERVED,
+ unsigned long EXPIRES, gpgme_key_t EXTRAKEY,
+ unsigned int FLAGS);
+
+ The function ‘gpgme_op_createkey’ generates a new key for the
+ procotol active in the context CTX. As of now this function does
+ only work for OpenPGP and requires at least version 2.1.13 of
+ GnuPG.
+
+ USERID is commonly the mail address associated with the key. GPGME
+ does not require a specificy syntax but if more than a mail address
+ is given, RFC-822 style format is suggested. The value is expected
+ to be in UTF-8 encoding (i.e. no IDN encoding for mail addresses).
+ This is a required parameter.
+
+ ALGO specifies the algorithm for the new key (actually a keypair of
+ public and private key). For a list of supported algorithms, see
+ the GnuPG manual. If ALGO is ‘NULL’ or the string "default", the
+ key is generated using the default algorithm of the engine. If the
+ string "future-default" is used the engine may use an algorithm
+ which is planned to be the default in a future release of the
+ engine; however existing implementation of the protocol may not be
+ able to already handle such future algorithms. For the OpenPGP
+ protocol, the specification of a default algorithm, without
+ requesting a non-default usage via FLAGS, triggers the creation of
+ a primary key plus a secondary key (subkey).
+
+ RESERVED must be set to zero.
+
+ EXPIRES can be set to the number of seconds since Epoch of the
+ desired expiration date in UTC for the new key. Using 0 does not
+ set an expiration date. Note that this parameter takes an unsigned
+ long value and not a ‘time_t’ to avoid problems on systems which
+ use a signed 32 bit ‘time_t’. Note further that the OpenPGP
+ protocol uses 32 bit values for timestamps and thus can only encode
+ dates up to the year 2106.
+
+ EXTRAKEY is currently not used and must be set to ‘NULL’. A future
+ version of GPGME may use this parameter to create X.509 keys.
+
+ FLAGS can be set to the bit-wise OR of the following flags:
+
+ ‘GPGME_CREATE_SIGN’
+ ‘GPGME_CREATE_ENCR’
+ ‘GPGME_CREATE_CERT’
+ ‘GPGME_CREATE_AUTH’
+ Do not create the key with the default capabilities (key
+ usage) of the requested algorithm but use those explicitly
+ given by these flags: “signingâ€, “encryptionâ€,
+ “certificationâ€, or “authenticationâ€. The allowed
+ combinations depend on the algorithm.
+
+ If any of these flags are set and a default algorithm has been
+ selected only one key is created in the case of the OpenPGP
+ protocol.
+
+ ‘GPGME_CREATE_NOPASSWD’
+ Request generation of the key without password protection.
+
+ ‘GPGME_CREATE_SELFSIGNED’
+ For an X.509 key do not create a CSR but a self-signed
+ certificate. This has not yet been implemented.
+
+ ‘GPGME_CREATE_NOSTORE’
+ Do not store the created key in the local key database. This
+ has not yet been implemented.
+
+ ‘GPGME_CREATE_WANTPUB’
+ ‘GPGME_CREATE_WANTSEC’
+ Return the public or secret key as part of the result
+ structure. This has not yet been implemented.
+
+ ‘GPGME_CREATE_FORCE’
+ The engine does not allow the creation of a key with a user ID
+ already existing in the local key database. This flag can be
+ used to override this check.
+
+ After the operation completed successfully, information about the
+ created key can be retrieved with ‘gpgme_op_genkey_result’.
+
+ The function returns zero on success, ‘GPG_ERR_NOT_SUPPORTED’ if
+ the engine does not support the command, or a bunch of other error
+ codes.
+
+ -- Function: gpgme_error_t gpgme_op_createkey_start (gpgme_ctx_t CTX,
+ const char *USERID, const char *ALGO, unsigned long RESERVED,
+ unsigned long EXPIRES, gpgme_key_t EXTRAKEY,
+ unsigned int FLAGS);
+
+ The function ‘gpgme_op_createkey_start’ initiates a
+ ‘gpgme_op_createkey’ operation; see there for details. It must be
+ completed by calling ‘gpgme_wait’ on the context. *Note Waiting
+ For Completion::.
+
+ -- Function: gpgme_error_t gpgme_op_createsubkey (gpgme_ctx_t CTX,
+ gpgme_key_t KEY, const char *ALGO, unsigned long RESERVED,
+ unsigned long EXPIRES, unsigned int FLAGS);
+
+ The function ‘gpgme_op_createsubkey’ creates and adds a new subkey
+ to the primary OpenPGP key given by KEY. The only allowed protocol
+ in CTX is ‘GPGME_PROTOCOL_OPENPGP’. Subkeys (aka secondary keys)
+ are a concept in the OpenPGP protocol to bind several keys to a
+ primary key. As of now this function requires at least version
+ 2.1.13 of GnuPG.
+
+ KEY specifies the key to operate on.
+
+ ALGO specifies the algorithm for the new subkey. For a list of
+ supported algorithms, see the GnuPG manual. If ALGO is ‘NULL’ or
+ the string "default", the subkey is generated using the default
+ algorithm for an encryption subkey of the engine. If the string
+ "future-default" is used the engine may use an encryption algorithm
+ which is planned to be the default in a future release of the
+ engine; however existing implementation of the protocol may not be
+ able to already handle such future algorithms.
+
+ RESERVED must be set to zero.
+
+ EXPIRES can be set to the number of seconds since Epoch of the
+ desired expiration date in UTC for the new subkey. Using 0 does
+ not set an expiration date. Note that this parameter takes an
+ unsigned long value and not a ‘time_t’ to avoid problems on systems
+ which use a signed 32 bit ‘time_t’. Note further that the OpenPGP
+ protocol uses 32 bit values for timestamps and thus can only encode
+ dates up to the year 2106.
+
+ FLAGS takes the same values as described above for
+ ‘gpgme_op_createkey’.
+
+ After the operation completed successfully, information about the
+ created key can be retrieved with ‘gpgme_op_genkey_result’.
+
+ The function returns zero on success, ‘GPG_ERR_NOT_SUPPORTED’ if
+ the engine does not support the command, or a bunch of other error
+ codes.
+
+ -- Function: gpgme_error_t gpgme_op_createsubkey_start
+ (gpgme_ctx_t CTX, gpgme_key_t KEY, const char *ALGO,
+ unsigned long RESERVED, unsigned long EXPIRES,
+ unsigned int FLAGS);
+
+ The function ‘gpgme_op_createsubkey_start’ initiates a
+ ‘gpgme_op_createsubkey’ operation; see there for details. It must
+ be completed by calling ‘gpgme_wait’ on the context. *Note Waiting
+ For Completion::.
+
+ -- Function: gpgme_error_t gpgme_op_adduid (gpgme_ctx_t CTX,
+ gpgme_key_t KEY, const char *USERID, unsigned int FLAGS);
+
+ The function ‘gpgme_op_adduid’ adds a new user ID to the OpenPGP
+ key given by KEY. Adding additional user IDs after key creation is
+ a feature of the OpenPGP protocol and thus the protocol for the
+ context CTX must be set to OpenPGP. As of now this function
+ requires at least version 2.1.13 of GnuPG.
+
+ KEY specifies the key to operate on.
+
+ USERID is the user ID to add to the key. A user ID is commonly the
+ mail address to be associated with the key. GPGME does not require
+ a specificy syntax but if more than a mail address is given,
+ RFC-822 style format is suggested. The value is expected to be in
+ UTF-8 encoding (i.e. no IDN encoding for mail addresses). This is
+ a required parameter.
+
+ FLAGS are currently not used and must be set to zero.
+
+ The function returns zero on success, ‘GPG_ERR_NOT_SUPPORTED’ if
+ the engine does not support the command, or a bunch of other error
+ codes.
+
+ -- Function: gpgme_error_t gpgme_op_adduid_start (gpgme_ctx_t CTX,
+ gpgme_key_t KEY, const char *USERID, unsigned int FLAGS);
+
+ The function ‘gpgme_op_adduid_start’ initiates a ‘gpgme_op_adduid’
+ operation; see there for details. It must be completed by calling
+ ‘gpgme_wait’ on the context. *Note Waiting For Completion::.
+
+ -- Function: gpgme_error_t gpgme_op_revuid (gpgme_ctx_t CTX,
+ gpgme_key_t KEY, const char *USERID, unsigned int FLAGS);
+
+ The function ‘gpgme_op_revuid’ revokes a user ID from the OpenPGP
+ key given by KEY. Revoking user IDs after key creation is a
+ feature of the OpenPGP protocol and thus the protocol for the
+ context CTX must be set to OpenPGP. As of now this function
+ requires at least version 2.1.13 of GnuPG.
+
+ KEY specifies the key to operate on.
+
+ USERID is the user ID to be revoked from the key. The user ID must
+ be given verbatim because the engine does an exact and case
+ sensitive match. Thus the ‘uid’ field from the user ID object
+ (‘gpgme_user_id_t’) is to be used. This is a required parameter.
+
+ FLAGS are currently not used and must be set to zero.
+
+ Note that the engine won’t allow to revoke the last valid user ID.
+ To change a user ID is better to first add the new user ID, then
+ revoke the old one, and finally publish the key.
+
+ The function returns zero on success, ‘GPG_ERR_NOT_SUPPORTED’ if
+ the engine does not support the command, or a bunch of other error
+ codes.
+
+ -- Function: gpgme_error_t gpgme_op_revuid_start (gpgme_ctx_t CTX,
+ gpgme_key_t KEY, const char *USERID, unsigned int FLAGS);
+
+ The function ‘gpgme_op_revuid_start’ initiates a ‘gpgme_op_revuid’
+ operation; see there for details. It must be completed by calling
+ ‘gpgme_wait’ on the context. *Note Waiting For Completion::.
+
-- Function: gpgme_error_t gpgme_op_genkey (gpgme_ctx_t CTX,
const char *PARMS, gpgme_data_t PUBLIC, gpgme_data_t SECRET)
+
The function ‘gpgme_op_genkey’ generates a new key pair in the
context CTX. The meaning of PUBLIC and SECRET depends on the
crypto backend.
- GnuPG does not support PUBLIC and SECRET, they should be ‘NULL’.
+ GPG does not support PUBLIC and SECRET, they should be ‘NULL’.
GnuPG will generate a key pair and add it to the standard key ring.
The fingerprint of the generated key is available with
‘gpgme_op_genkey_result’.
@@ -3417,6 +3545,7 @@ File: gpgme.info, Node: Generating Keys, Next: Exporting Keys, Prev: Manipula
-- Function: gpgme_error_t gpgme_op_genkey_start (gpgme_ctx_t CTX,
const char *PARMS, gpgme_data_t PUBLIC, gpgme_data_t SECRET)
+
The function ‘gpgme_op_genkey_start’ initiates a ‘gpgme_op_genkey’
operation. It can be completed by calling ‘gpgme_wait’ on the
context. *Note Waiting For Completion::.
@@ -3427,6 +3556,7 @@ File: gpgme.info, Node: Generating Keys, Next: Exporting Keys, Prev: Manipula
PUBLIC or SECRET is not ‘NULL’.
-- Data type: gpgme_genkey_result_t
+
This is a pointer to a structure used to store the result of a
‘gpgme_op_genkey’ operation. After successfully generating a key,
you can retrieve the pointer to the result with
@@ -3434,21 +3564,33 @@ File: gpgme.info, Node: Generating Keys, Next: Exporting Keys, Prev: Manipula
members:
‘unsigned int primary : 1’
- This is a flag that is set to 1 if a primary key was created
- and to 0 if not.
+ This flag is set to 1 if a primary key was created and to 0 if
+ not.
‘unsigned int sub : 1’
- This is a flag that is set to 1 if a subkey was created and to
- 0 if not.
+ This flag is set to 1 if a subkey was created and to 0 if not.
+
+ ‘unsigned int uid : 1’
+ This flag is set to 1 if a user ID was created and to 0 if
+ not.
‘char *fpr’
This is the fingerprint of the key that was created. If both
- a primary and a sub key were generated, the fingerprint of the
+ a primary and a subkey were generated, the fingerprint of the
primary key will be returned. If the crypto engine does not
provide the fingerprint, ‘fpr’ will be a null pointer.
+ ‘gpgme_data_t pubkey’
+ This will eventually be used to return the public key. It is
+ currently not used.
+
+ ‘gpgme_data_t seckey’
+ This will eventually be used to return the secret key. It is
+ currently not used.
+
-- Function: gpgme_genkey_result_t gpgme_op_genkey_result
(gpgme_ctx_t CTX)
+
The function ‘gpgme_op_genkey_result’ returns a
‘gpgme_genkey_result_t’ pointer to a structure holding the result
of a ‘gpgme_op_genkey’ operation. The pointer is only valid if the
@@ -3458,9 +3600,86 @@ File: gpgme.info, Node: Generating Keys, Next: Exporting Keys, Prev: Manipula
operation is started on the context.

-File: gpgme.info, Node: Exporting Keys, Next: Importing Keys, Prev: Generating Keys, Up: Key Management
+File: gpgme.info, Node: Signing Keys, Next: Exporting Keys, Prev: Generating Keys, Up: Key Management
-7.5.6 Exporting Keys
+7.5.6 Signing Keys
+------------------
+
+Key signatures are a unique concept of the OpenPGP protocol. They can
+be used to certify the validity of a key and are used to create the
+Web-of-Trust (WoT). Instead of using the ‘gpgme_op_interact’ function
+along with a finite state machine, GPGME provides a convenient function
+to create key signatures when using modern GnuPG versions.
+
+ -- Function: gpgme_error_t gpgme_op_keysign (gpgme_ctx_t CTX,
+ gpgme_key_t KEY, const char *USERID, unsigned long EXPIRES,
+ unsigned int FLAGS);
+
+ The function ‘gpgme_op_keysign’ adds a new key signature to the
+ public key KEY. This function requires at least version 2.1.12 of
+ GnuPG.
+
+ CTX is the usual context which describes the protocol to use (which
+ must be OpenPGP) and has also the list of signer keys to be used
+ for the signature. The common case is to use the default key for
+ signing other keys. If another key or more than one key shall be
+ used for a key signature, ‘gpgme_signers_add’ can be used. *Note
+ Selecting Signers::.
+
+ KEY specifies the key to operate on.
+
+ USERID selects the user ID or user IDs to be signed. If USERID is
+ set to ‘NULL’ all valid user IDs are signed. The user ID must be
+ given verbatim because the engine does an exact and case sensitive
+ match. Thus the ‘uid’ field from the user ID object
+ (‘gpgme_user_id_t’) is to be used. To select more than one user ID
+ put them all into one string separated by linefeeds characters
+ (‘\n’) and set the flag ‘GPGME_KEYSIGN_LFSEP’.
+
+ EXPIRES can be set to the number of seconds since Epoch of the
+ desired expiration date in UTC for the new signature. The common
+ case is to use 0 to not set an expiration date. However, if the
+ configuration of the engine defines a default expiration for key
+ signatures, that is still used unless the flag
+ ‘GPGME_KEYSIGN_NOEXPIRE’ is used. Note that this parameter takes
+ an unsigned long value and not a ‘time_t’ to avoid problems on
+ systems which use a signed 32 bit ‘time_t’. Note further that the
+ OpenPGP protocol uses 32 bit values for timestamps and thus can
+ only encode dates up to the year 2106.
+
+ FLAGS can be set to the bit-wise OR of the following flags:
+
+ ‘GPGME_KEYSIGN_LOCAL’
+ Instead of creating an exportable key signature, create a key
+ signature which is is marked as non-exportable.
+
+ ‘GPGME_KEYSIGN_LFSEP’
+ Although linefeeds are uncommon in user IDs this flag is
+ required to explicitly declare that USERID may contain several
+ linefeed separated user IDs.
+
+ ‘GPGME_KEYSIGN_NOEXPIRE’
+ Force the creation of a key signature without an expiration
+ date. This overrides EXPIRE and any local configuration of
+ the engine.
+
+ The function returns zero on success, ‘GPG_ERR_NOT_SUPPORTED’ if
+ the engine does not support the command, or a bunch of other error
+ codes.
+
+ -- Function: gpgme_error_t gpgme_op_keysign_start (gpgme_ctx_t CTX,
+ gpgme_key_t KEY, const char *USERID, unsigned long EXPIRES,
+ unsigned int FLAGS);
+
+ The function ‘gpgme_op_keysign_start’ initiates a
+ ‘gpgme_op_keysign’ operation; see there for details. It must be
+ completed by calling ‘gpgme_wait’ on the context. *Note Waiting
+ For Completion::.
+
+
+File: gpgme.info, Node: Exporting Keys, Next: Importing Keys, Prev: Signing Keys, Up: Key Management
+
+7.5.7 Exporting Keys
--------------------
Exporting keys means the same as running ‘gpg’ with the command
@@ -3568,10 +3787,10 @@ or-ed together.
specified for KEYDATA.
The keys to export are taken form the ‘NULL’ terminated array KEYS.
- Only keys of the the currently selected protocol of CTX which do
- have a fingerprint set are considered for export. Other keys
- specified by the KEYS are ignored. In particular OpenPGP keys
- retrieved via an external key listing are not included.
+ Only keys of the currently selected protocol of CTX which do have a
+ fingerprint set are considered for export. Other keys specified by
+ the KEYS are ignored. In particular OpenPGP keys retrieved via an
+ external key listing are not included.
MODE is usually 0; other values are described above.
@@ -3597,7 +3816,7 @@ or-ed together.

File: gpgme.info, Node: Importing Keys, Next: Deleting Keys, Prev: Exporting Keys, Up: Key Management
-7.5.7 Importing Keys
+7.5.8 Importing Keys
--------------------
Importing keys means the same as running ‘gpg’ with the command
@@ -3639,11 +3858,10 @@ Importing keys means the same as running ‘gpg’ with the command
which have been retrieved from an external source (i.e. using
‘GPGME_KEYLIST_MODE_EXTERN’). (1)
- Only keys of the the currently selected protocol of CTX are
- considered for import. Other keys specified by the KEYS are
- ignored. As of now all considered keys must have been retrieved
- using the same method, that is the used key listing mode must be
- identical.
+ Only keys of the currently selected protocol of CTX are considered
+ for import. Other keys specified by the KEYS are ignored. As of
+ now all considered keys must have been retrieved using the same
+ method, that is the used key listing mode must be identical.
After the operation completed successfully, the result can be
retrieved with ‘gpgme_op_import_result’.
@@ -3720,34 +3938,34 @@ Importing keys means the same as running ‘gpg’ with the command
‘int imported’
The total number of imported keys.
- ‘imported_rsa’
+ ‘int imported_rsa’
The number of imported RSA keys.
- ‘unchanged’
+ ‘int unchanged’
The number of unchanged keys.
- ‘new_user_ids’
+ ‘int new_user_ids’
The number of new user IDs.
- ‘new_sub_keys’
+ ‘int new_sub_keys’
The number of new sub keys.
- ‘new_signatures’
+ ‘int new_signatures’
The number of new signatures.
- ‘new_revocations’
+ ‘int new_revocations’
The number of new revocations.
- ‘secret_read’
+ ‘int secret_read’
The total number of secret keys read.
- ‘secret_imported’
+ ‘int secret_imported’
The number of imported secret keys.
- ‘secret_unchanged’
+ ‘int secret_unchanged’
The number of unchanged secret keys.
- ‘not_imported’
+ ‘int not_imported’
The number of keys not imported.
‘gpgme_import_status_t imports’
@@ -3764,21 +3982,6 @@ Importing keys means the same as running ‘gpg’ with the command
successfully. The returned pointer is only valid until the next
operation is started on the context.
- The following interface is deprecated and only provided for backward
-compatibility. Don’t use it. It will be removed in a future version of
-GPGME.
-
- -- Function: gpgme_error_t gpgme_op_import_ext (gpgme_ctx_t CTX,
- gpgme_data_t KEYDATA, int *NR)
- The function ‘gpgme_op_import_ext’ is equivalent to:
-
- gpgme_error_t err = gpgme_op_import (ctx, keydata);
- if (!err)
- {
- gpgme_import_result_t result = gpgme_op_import_result (ctx);
- *nr = result->considered;
- }
-
---------- Footnotes ----------
(1) Thus it is a replacement for the usual workaround of exporting
@@ -3787,7 +3990,7 @@ and then importing a key to make an X.509 key permanent.

File: gpgme.info, Node: Deleting Keys, Next: Changing Passphrases, Prev: Importing Keys, Up: Key Management
-7.5.8 Deleting Keys
+7.5.9 Deleting Keys
-------------------
-- Function: gpgme_error_t gpgme_op_delete (gpgme_ctx_t CTX,
@@ -3815,10 +4018,10 @@ File: gpgme.info, Node: Deleting Keys, Next: Changing Passphrases, Prev: Impo
or KEY is not a valid pointer.

-File: gpgme.info, Node: Changing Passphrases, Next: Advanced Key Editing, Prev: Deleting Keys, Up: Key Management
+File: gpgme.info, Node: Changing Passphrases, Next: Changing TOFU Data, Prev: Deleting Keys, Up: Key Management
-7.5.9 Changing Passphrases
---------------------------
+7.5.10 Changing Passphrases
+---------------------------
-- Function: gpgme_error_t gpgme_op_passwd (gpgme_ctx_t CTX,
const gpgme_key_t KEY, unsigned int FLAGS)
@@ -3845,69 +4048,109 @@ File: gpgme.info, Node: Changing Passphrases, Next: Advanced Key Editing, Pre
oepration could not be started.

-File: gpgme.info, Node: Advanced Key Editing, Prev: Changing Passphrases, Up: Key Management
+File: gpgme.info, Node: Changing TOFU Data, Next: Advanced Key Editing, Prev: Changing Passphrases, Up: Key Management
-7.5.10 Advanced Key Editing
----------------------------
+7.5.11 Changing TOFU Data
+-------------------------
- -- Data type: gpgme_error_t (*gpgme_edit_cb_t) (void *HANDLE,
- gpgme_status_code_t STATUS, const char *ARGS, int FD)
- The ‘gpgme_edit_cb_t’ type is the type of functions which GPGME
- calls if it a key edit operation is on-going. The status code
- STATUS and the argument line ARGS are passed through by GPGME from
- the crypto engine. The file descriptor FD is -1 for normal status
- messages. If STATUS indicates a command rather than a status
- message, the response to the command should be written to FD. The
- HANDLE is provided by the user at start of operation.
+The OpenPGP engine features a Trust-On-First-Use (TOFU) key validation
+model. For resolving clonflics it is necessary to declare the policy
+for a key. See the GnuPG manual for details on the TOFU implementation.
- The function should return ‘GPG_ERR_NO_ERROR’ or an error value.
+ -- Data type: enum gpgme_tofu_policy_t
+ The ‘gpgme_tofu_policy_t’ type specifies the set of possible policy
+ values that are supported by GPGME:
- -- Function: gpgme_error_t gpgme_op_edit (gpgme_ctx_t CTX,
- gpgme_key_t KEY, gpgme_edit_cb_t FNC, void *HANDLE,
- gpgme_data_t OUT)
- The function ‘gpgme_op_edit’ processes the key KEY interactively,
- using the edit callback function FNC with the handle HANDLE. The
- callback is invoked for every status and command request from the
- crypto engine. The output of the crypto engine is written to the
- data object OUT.
+ ‘GPGME_TOFU_POLICY_AUTO’
+ Set the policy to “autoâ€.
+ ‘GPGME_TOFU_POLICY_GOOD’
+ Set the policy to “googâ€.
+ ‘GPGME_TOFU_POLICY_BAD’
+ Set the policy to “badâ€.
+ ‘GPGME_TOFU_POLICY_ASK’
+ Set the policy to “askâ€.
+ ‘GPGME_TOFU_POLICY_UNKNOWN’
+ Set the policy to “unknownâ€.
+
+ To change the policy for a key the following functions can be used:
+
+ -- Function: gpgme_error_t gpgme_op_tofu_policy (gpgme_ctx_t CTX,
+ const gpgme_key_t KEY, gpgme_tofu_policy_t POLICY)
+
+ The function ‘gpgme_op_tofu_policy’ changes the TOFU policy of KEY.
+ The valid values for POLICY are listed above. As of now this
+ function does only work for OpenPGP and requires at least version
+ 2.1.10 of GnuPG.
+
+ The function returns zero on success, ‘GPG_ERR_NOT_SUPPORTED’ if
+ the engine does not support the command, or a bunch of other error
+ codes.
+
+ -- Function: gpgme_error_t gpgme_op_tofu_policy_start (gpgme_ctx_t CTX,
+ const gpgme_key_t KEY, gpgme_tofu_policy_t POLICY)
+
+ The function ‘gpgme_op_tofu_policy_start’ initiates a
+ ‘gpgme_op_tofu_policy’ operation. It can be completed by calling
+ ‘gpgme_wait’ on the context. *Note Waiting For Completion::.
+
+ The function returns ‘0’ if the operation was started successfully,
+ and an error code if one of the arguments is not valid or the
+ oepration could not be started.
+
+
+File: gpgme.info, Node: Advanced Key Editing, Prev: Changing TOFU Data, Up: Key Management
+
+7.5.12 Advanced Key Editing
+---------------------------
+
+ -- Data type: gpgme_error_t (*gpgme_interact_cb_t) (void *HANDLE,
+ const char *STATUS, const char *ARGS, int FD)
+ The ‘gpgme_interact_cb_t’ type is the type of functions which GPGME
+ calls if it a key interact operation is on-going. The status
+ keyword STATUS and the argument line ARGS are passed through by
+ GPGME from the crypto engine. An empty string represents EOF. The
+ file descriptor FD is -1 for normal status messages. If STATUS
+ indicates a command rather than a status message, the response to
+ the command should be written to FD. The HANDLE is provided by the
+ user at start of operation.
+
+ The function should return ‘GPG_ERR_FALSE’ if it did not handle the
+ status code, ‘0’ for success, or any other error value.
+
+ -- Function: gpgme_error_t gpgme_op_interact (gpgme_ctx_t CTX,
+ gpgme_key_t KEY, unsigned int FLAGS, gpgme_interact_cb_t FNC,
+ void *HANDLE, gpgme_data_t OUT)
+ The function ‘gpgme_op_interact’ processes the key KEY
+ interactively, using the interact callback function FNC with the
+ handle HANDLE. The callback is invoked for every status and
+ command request from the crypto engine. The output of the crypto
+ engine is written to the data object OUT.
Note that the protocol between the callback function and the crypto
engine is specific to the crypto engine and no further support in
implementing this protocol correctly is provided by GPGME.
- The function returns the error code ‘GPG_ERR_NO_ERROR’ if the edit
- operation completes successfully, ‘GPG_ERR_INV_VALUE’ if CTX or KEY
- is not a valid pointer, and any error returned by the crypto engine
- or the edit callback handler.
+ FLAGS modifies the behaviour of the function; the only defined bit
+ value is:
- -- Function: gpgme_error_t gpgme_op_edit_start (gpgme_ctx_t CTX,
- gpgme_key_t KEY, gpgme_edit_cb_t FNC, void *HANDLE,
- gpgme_data_t OUT)
- The function ‘gpgme_op_edit_start’ initiates a ‘gpgme_op_edit’
- operation. It can be completed by calling ‘gpgme_wait’ on the
- context. *Note Waiting For Completion::.
-
- The function returns the error code ‘GPG_ERR_NO_ERROR’ if the
- operation was started successfully, and ‘GPG_ERR_INV_VALUE’ if CTX
- or KEY is not a valid pointer.
+ ‘GPGME_INTERACT_CARD’
+ This is used for smartcard based keys and uses gpg’s
+ ‘--card-edit’ command.
- -- Function: gpgme_error_t gpgme_op_card_edit (gpgme_ctx_t CTX,
- gpgme_key_t KEY, gpgme_edit_cb_t FNC, void *HANDLE,
- gpgme_data_t OUT)
- The function ‘gpgme_op_card_edit’ is analogous to ‘gpgme_op_edit’,
- but should be used to process the smart card corresponding to the
- key KEY.
+ The function returns ‘0’ if the edit operation completes
+ successfully, ‘GPG_ERR_INV_VALUE’ if CTX or KEY is not a valid
+ pointer, and any error returned by the crypto engine or the edit
+ callback handler.
- -- Function: gpgme_error_t gpgme_op_card_edit_start (gpgme_ctx_t CTX,
- gpgme_key_t KEY, gpgme_edit_cb_t FNC, void *HANDLE,
- gpgme_data_t OUT)
- The function ‘gpgme_op_card_edit_start’ initiates a
- ‘gpgme_op_card_edit’ operation. It can be completed by calling
+ -- Function: gpgme_error_t gpgme_op_interact_start (gpgme_ctx_t CTX,
+ gpgme_key_t KEY, unsigned int FLAGS, gpgme_interact_cb_t FNC,
+ void *HANDLE, gpgme_data_t OUT)
+ The function ‘gpgme_op_interact_start’ initiates a
+ ‘gpgme_op_interact’ operation. It can be completed by calling
‘gpgme_wait’ on the context. *Note Waiting For Completion::.
- The function returns the error code ‘GPG_ERR_NO_ERROR’ if the
- operation was started successfully, and ‘GPG_ERR_INV_VALUE’ if CTX
- or KEY is not a valid pointer.
+ The function returns ‘0’ if the operation was started successfully,
+ and ‘GPG_ERR_INV_VALUE’ if CTX or KEY is not a valid pointer.

File: gpgme.info, Node: Trust Item Management, Next: Crypto Operations, Prev: Key Management, Up: Contexts
@@ -3944,11 +4187,10 @@ File: gpgme.info, Node: Trust Item Management, Next: Crypto Operations, Prev:
* Menu:
* Listing Trust Items:: Browsing the list of available trust items.
-* Information About Trust Items:: Requesting information about trust items.
* Manipulating Trust Items:: Operations on trust items.

-File: gpgme.info, Node: Listing Trust Items, Next: Information About Trust Items, Up: Trust Item Management
+File: gpgme.info, Node: Listing Trust Items, Next: Manipulating Trust Items, Up: Trust Item Management
7.6.1 Listing Trust Items
-------------------------
@@ -4000,51 +4242,9 @@ File: gpgme.info, Node: Listing Trust Items, Next: Information About Trust Ite
the operation there was not enough memory available.

-File: gpgme.info, Node: Information About Trust Items, Next: Manipulating Trust Items, Prev: Listing Trust Items, Up: Trust Item Management
-
-7.6.2 Information About Trust Items
------------------------------------
-
-The following interfaces are deprecated and only provided for backward
-compatibility. Don’t use them. They will be removed in a future
-version of GPGME.
+File: gpgme.info, Node: Manipulating Trust Items, Prev: Listing Trust Items, Up: Trust Item Management
- Trust items have attributes which can be queried using the interfaces
-below. The attribute identifiers are shared with those for key
-attributes. *Note Information About Keys::.
-
- -- Function: const char * gpgme_trust_item_get_string_attr
- (gpgme_trust_item_t ITEM, gpgme_attr_t WHAT,
- const void *RESERVED, int IDX)
- The function ‘gpgme_trust_item_get_string_attr’ returns the value
- of the string-representable attribute WHAT of trust item ITEM. The
- arguments IDX and RESERVED are reserved for later use and should be
- ‘0’ and ‘NULL’ respectively.
-
- The string returned is only valid as long as the key is valid.
-
- The function returns ‘0’ if an attribute can’t be returned as a
- string, KEY is not a valid pointer, IDX out of range, or RESERVED
- not ‘NULL’.
-
- -- Function: int gpgme_trust_item_get_int_attr
- (gpgme_trust_item_t ITEM, gpgme_attr_t WHAT,
- const void *RESERVED, int IDX)
- The function ‘gpgme_trust_item_get_int_attr’ returns the value of
- the number-representable attribute WHAT of trust item ITEM. If the
- attribute occurs more than once in the trust item, the index is
- specified by IDX. However, currently no such attribute exists, so
- IDX should be ‘0’. The argument RESERVED is reserved for later use
- and should be ‘NULL’.
-
- The function returns ‘0’ if the attribute can’t be returned as a
- number, KEY is not a valid pointer, IDX out of range, or RESERVED
- not ‘NULL’.
-
-
-File: gpgme.info, Node: Manipulating Trust Items, Prev: Information About Trust Items, Up: Trust Item Management
-
-7.6.3 Manipulating Trust Items
+7.6.2 Manipulating Trust Items
------------------------------
-- Function: void gpgme_trust_item_ref (gpgme_trust_item_t ITEM)
@@ -4057,14 +4257,6 @@ File: gpgme.info, Node: Manipulating Trust Items, Prev: Information About Trus
will be destroyed and all resources associated to it will be
released.
- The following interface is deprecated and only provided for backward
-compatibility. Don’t use it. It will be removed in a future version of
-GPGME.
-
- -- Function: void gpgme_trust_item_release (gpgme_trust_item_t ITEM)
- The function ‘gpgme_trust_item_release’ is an alias for
- ‘gpgme_trust_item_unref’.
-

File: gpgme.info, Node: Crypto Operations, Next: Miscellaneous, Prev: Trust Item Management, Up: Contexts
@@ -4426,6 +4618,12 @@ File: gpgme.info, Node: Verify, Next: Decrypt and Verify, Prev: Decrypt, Up:
‘char *pka_address’
The mailbox from the PKA information or ‘NULL’.
+ ‘gpgme_key_t key’
+ An object describing the key used to create the signature.
+ This key object may be incomplete in that it only conveys
+ information availabale directly with a signature. It may also
+ be ‘NULL’ if such information is not readily available.
+
-- Data type: gpgme_verify_result_t
This is a pointer to a structure used to store the result of a
‘gpgme_op_verify’ operation. After verifying a signature, you can
@@ -4454,229 +4652,6 @@ File: gpgme.info, Node: Verify, Next: Decrypt and Verify, Prev: Decrypt, Up:
counts as successful in this context). The returned pointer is
only valid until the next operation is started on the context.
- The following interfaces are deprecated and only provided for
-backward compatibility. Don’t use them. They will be removed in a
-future version of GPGME.
-
- -- Data type: enum gpgme_sig_stat_t
- The ‘gpgme_sig_stat_t’ type holds the result of a signature check,
- or the combined result of all signatures. The following results
- are possible:
-
- ‘GPGME_SIG_STAT_NONE’
- This status should not occur in normal operation.
-
- ‘GPGME_SIG_STAT_GOOD’
- This status indicates that the signature is valid. For the
- combined result this status means that all signatures are
- valid.
-
- ‘GPGME_SIG_STAT_GOOD_EXP’
- This status indicates that the signature is valid but expired.
- For the combined result this status means that all signatures
- are valid and expired.
-
- ‘GPGME_SIG_STAT_GOOD_EXPKEY’
- This status indicates that the signature is valid but the key
- used to verify the signature has expired. For the combined
- result this status means that all signatures are valid and all
- keys are expired.
-
- ‘GPGME_SIG_STAT_BAD’
- This status indicates that the signature is invalid. For the
- combined result this status means that all signatures are
- invalid.
-
- ‘GPGME_SIG_STAT_NOKEY’
- This status indicates that the signature could not be verified
- due to a missing key. For the combined result this status
- means that all signatures could not be checked due to missing
- keys.
-
- ‘GPGME_SIG_STAT_NOSIG’
- This status indicates that the signature data provided was not
- a real signature.
-
- ‘GPGME_SIG_STAT_ERROR’
- This status indicates that there was some other error which
- prevented the signature verification.
-
- ‘GPGME_SIG_STAT_DIFF’
- For the combined result this status means that at least two
- signatures have a different status. You can get each key’s
- status with ‘gpgme_get_sig_status’.
-
- -- Function: const char * gpgme_get_sig_status (gpgme_ctx_t CTX,
- int IDX, gpgme_sig_stat_t *R_STAT, time_t *R_CREATED)
- The function ‘gpgme_get_sig_status’ is equivalent to:
-
- gpgme_verify_result_t result;
- gpgme_signature_t sig;
-
- result = gpgme_op_verify_result (ctx);
- sig = result->signatures;
-
- while (sig && idx)
- {
- sig = sig->next;
- idx--;
- }
- if (!sig || idx)
- return NULL;
-
- if (r_stat)
- {
- switch (gpg_err_code (sig->status))
- {
- case GPG_ERR_NO_ERROR:
- *r_stat = GPGME_SIG_STAT_GOOD;
- break;
-
- case GPG_ERR_BAD_SIGNATURE:
- *r_stat = GPGME_SIG_STAT_BAD;
- break;
-
- case GPG_ERR_NO_PUBKEY:
- *r_stat = GPGME_SIG_STAT_NOKEY;
- break;
-
- case GPG_ERR_NO_DATA:
- *r_stat = GPGME_SIG_STAT_NOSIG;
- break;
-
- case GPG_ERR_SIG_EXPIRED:
- *r_stat = GPGME_SIG_STAT_GOOD_EXP;
- break;
-
- case GPG_ERR_KEY_EXPIRED:
- *r_stat = GPGME_SIG_STAT_GOOD_EXPKEY;
- break;
-
- default:
- *r_stat = GPGME_SIG_STAT_ERROR;
- break;
- }
- }
- if (r_created)
- *r_created = sig->timestamp;
- return sig->fpr;
-
- -- Function: const char * gpgme_get_sig_string_attr (gpgme_ctx_t CTX,
- int IDX, gpgme_attr_t WHAT, int WHATIDX)
- The function ‘gpgme_get_sig_string_attr’ is equivalent to:
-
- gpgme_verify_result_t result;
- gpgme_signature_t sig;
-
- result = gpgme_op_verify_result (ctx);
- sig = result->signatures;
-
- while (sig && idx)
- {
- sig = sig->next;
- idx--;
- }
- if (!sig || idx)
- return NULL;
-
- switch (what)
- {
- case GPGME_ATTR_FPR:
- return sig->fpr;
-
- case GPGME_ATTR_ERRTOK:
- if (whatidx == 1)
- return sig->wrong_key_usage ? "Wrong_Key_Usage" : "";
- else
- return "";
- default:
- break;
- }
-
- return NULL;
-
- -- Function: const char * gpgme_get_sig_ulong_attr (gpgme_ctx_t CTX,
- int IDX, gpgme_attr_t WAHT, int WHATIDX)
- The function ‘gpgme_get_sig_ulong_attr’ is equivalent to:
-
- gpgme_verify_result_t result;
- gpgme_signature_t sig;
-
- result = gpgme_op_verify_result (ctx);
- sig = result->signatures;
-
- while (sig && idx)
- {
- sig = sig->next;
- idx--;
- }
- if (!sig || idx)
- return 0;
-
- switch (what)
- {
- case GPGME_ATTR_CREATED:
- return sig->timestamp;
-
- case GPGME_ATTR_EXPIRE:
- return sig->exp_timestamp;
-
- case GPGME_ATTR_VALIDITY:
- return (unsigned long) sig->validity;
-
- case GPGME_ATTR_SIG_STATUS:
- switch (sig->status)
- {
- case GPG_ERR_NO_ERROR:
- return GPGME_SIG_STAT_GOOD;
-
- case GPG_ERR_BAD_SIGNATURE:
- return GPGME_SIG_STAT_BAD;
-
- case GPG_ERR_NO_PUBKEY:
- return GPGME_SIG_STAT_NOKEY;
-
- case GPG_ERR_NO_DATA:
- return GPGME_SIG_STAT_NOSIG;
-
- case GPG_ERR_SIG_EXPIRED:
- return GPGME_SIG_STAT_GOOD_EXP;
-
- case GPG_ERR_KEY_EXPIRED:
- return GPGME_SIG_STAT_GOOD_EXPKEY;
-
- default:
- return GPGME_SIG_STAT_ERROR;
- }
-
- case GPGME_ATTR_SIG_SUMMARY:
- return sig->summary;
-
- default:
- break;
- }
- return 0;
-
- -- Function: const char * gpgme_get_sig_key (gpgme_ctx_t CTX, int IDX,
- gpgme_key_t *R_KEY)
- The function ‘gpgme_get_sig_key’ is equivalent to:
-
- gpgme_verify_result_t result;
- gpgme_signature_t sig;
-
- result = gpgme_op_verify_result (ctx);
- sig = result->signatures;
-
- while (sig && idx)
- {
- sig = sig->next;
- idx--;
- }
- if (!sig || idx)
- return gpg_error (GPG_ERR_EOF);
-
- return gpgme_get_key (ctx, sig->fpr, r_key, 0);
-

File: gpgme.info, Node: Decrypt and Verify, Next: Sign, Prev: Verify, Up: Crypto Operations
@@ -4742,6 +4717,11 @@ File: gpgme.info, Node: Selecting Signers, Next: Creating a Signature, Up: Si
7.7.4.1 Selecting Signers
.........................
+The key or the keys used to create a signature are stored in the
+context. The following functions can be used to manipulate this list.
+If no signer has been set into the context a default key is used for
+signing.
+
-- Function: void gpgme_signers_clear (gpgme_ctx_t CTX)
The function ‘gpgme_signers_clear’ releases a reference for each
key on the signers list and removes the list of signers from the
@@ -4990,6 +4970,12 @@ File: gpgme.info, Node: Encrypting a Plaintext, Up: Encrypt
‘PREP_ENCRYPT’ command). With the ‘GPGME_ENCRYPT_EXPECT_SIGN’
symbol the UI Server is advised to also expect a sign command.
+ ‘GPGME_ENCRYPT_SYMMETRIC’
+ The ‘GPGME_ENCRYPT_SYMMETRIC’ symbol specifies that the output
+ should be additionally encrypted symmetically even if
+ recipients are provided. This feature is only supported for
+ for the OpenPGP crypto engine.
+
If ‘GPG_ERR_UNUSABLE_PUBKEY’ is returned, some recipients in RECP
are invalid, but not all. In this case the plaintext might be
encrypted for all valid recipients and returned in CIPHER (if this
@@ -5082,9 +5068,10 @@ Here are some support functions which are sometimes useful.
* Menu:
* Running other Programs:: Running other Programs
+* Using the Assuan protocol:: Using the Assuan protocol

-File: gpgme.info, Node: Running other Programs, Up: Miscellaneous
+File: gpgme.info, Node: Running other Programs, Next: Using the Assuan protocol, Up: Miscellaneous
7.8.1 Running other Programs
----------------------------
@@ -5096,10 +5083,10 @@ cryptographic features. It may for example be used to run tools which
are part of the GnuPG system but are not directly accessible with the
GPGME API.
- -- Function: gpgme_error_t gpgme_op_spawn
- (gpgme_ctx_t CTX, const char *FILE, const char *ARGV[],
- gpgme_data_t DATAIN, gpgme_data_t DATAOUT, gpgme_data_t DATAERR,
- unsigned int FLAGS)
+ -- Function: gpgme_error_t gpgme_op_spawn (gpgme_ctx_t CTX,
+ const char *FILE, const char *ARGV[], gpgme_data_t DATAIN,
+ gpgme_data_t DATAOUT, gpgme_data_t DATAERR,
+ unsigned int FLAGS)
The function ‘gpgme_op_spawn’ runs the program FILE with the
arguments taken from the NULL terminated array ARGV. If no
@@ -5121,14 +5108,78 @@ GPGME API.
Under Windows this flag allows the called program to put
itself into the foreground.
- -- Function: gpgme_error_t gpgme_op_spawn_start
- (gpgme_ctx_t CTX, const char *FILE, const char *ARGV[],
- gpgme_data_t DATAIN, gpgme_data_t DATAOUT, gpgme_data_t DATAERR,
- unsigned int FLAGS)
+ -- Function: gpgme_error_t gpgme_op_spawn_start (gpgme_ctx_t CTX,
+ const char *FILE, const char *ARGV[], gpgme_data_t DATAIN,
+ gpgme_data_t DATAOUT, gpgme_data_t DATAERR,
+ unsigned int FLAGS)
This is the asynchronous variant of ‘gpgme_op_spawn’.

+File: gpgme.info, Node: Using the Assuan protocol, Prev: Running other Programs, Up: Miscellaneous
+
+7.8.2 Using the Assuan protocol
+-------------------------------
+
+The Assuan protocol can be used to talk to arbitrary Assuan servers. By
+default it is connected to the GnuPG agent, but it may be connected to
+arbitrary servers by using ‘gpgme_ctx_set_engine_info’, passing the
+location of the servers socket as FILE_NAME argument, and an empty
+string as HOME_DIR argument.
+
+ The Assuan protocol functions use three kinds of callbacks to
+transfer data:
+
+ -- Data type: gpgme_error_t (*gpgme_assuan_data_cb_t) (void *OPAQUE,
+ const void *DATA, size_t DATALEN)
+
+ This callback receives any data sent by the server. OPAQUE is the
+ pointer passed to ‘gpgme_op_assuan_transact_start’, DATA of length
+ DATALEN refers to the data sent.
+
+ -- Data type: gpgme_error_t (*gpgme_assuan_inquire_cb_t) (void *OPAQUE,
+ const char *NAME, const char *ARGS, gpgme_data_t *R_DATA)
+
+ This callback is used to provide additional data to the Assuan
+ server. OPAQUE is the pointer passed to
+ ‘gpgme_op_assuan_transact_start’, NAME and ARGS specify what kind
+ of data the server requested, and R_DATA is used to return the
+ actual data.
+
+ Note: Returning data is currently not implemented in GPGME.
+
+ -- Data type: gpgme_error_t (*gpgme_assuan_status_cb_t) (void *OPAQUE,
+ const char *STATUS, const char *ARGS)
+
+ This callback receives any status lines sent by the server. OPAQUE
+ is the pointer passed to ‘gpgme_op_assuan_transact_start’, STATUS
+ and ARGS denote the status update sent.
+
+ -- Function: gpgme_error_t gpgme_op_assuan_transact_start
+ (gpgme_ctx_t CTX, const char *COMMAND,
+ gpgme_assuan_data_cb_t DATA_CB, void * DATA_CB_VALUE,
+ gpgme_assuan_inquire_cb_t INQUIRE_CB, void * INQUIRE_CB_VALUE,
+ gpgme_assuan_status_cb_t STATUS_CB, void * STATUS_CB_VALUE)
+
+ Send the Assuan COMMAND and return results via the callbacks. Any
+ callback may be ‘NULL’. The result of the operation may be
+ retrieved using ‘gpgme_wait_ext’.
+
+ Asynchronous variant.
+
+ -- Function: gpgme_error_t gpgme_op_assuan_transact_ext
+ (gpgme_ctx_t CTX, const char *COMMAND,
+ gpgme_assuan_data_cb_t DATA_CB, void * DATA_CB_VALUE,
+ gpgme_assuan_inquire_cb_t INQUIRE_CB, void * INQUIRE_CB_VALUE,
+ gpgme_assuan_status_cb_t STATUS_CB, void * STATUS_CB_VALUE,
+ gpgme_error_t *OP_ERR)
+
+ Send the Assuan COMMAND and return results via the callbacks. The
+ result of the operation is returned in OP_ERR.
+
+ Synchronous variant.
+
+
File: gpgme.info, Node: Run Control, Prev: Miscellaneous, Up: Contexts
7.9 Run Control
@@ -5807,18 +5858,17 @@ I/O occurs in the target context).
in the context CTX. This only works if you use the global event
loop or your own event loop.
- If you use the global event loop, you must not call ‘gpgme_wait’ or
- ‘gpgme_wait’ during cancellation. After successful cancellation,
- you can call ‘gpgme_wait’ (optionally waiting on CTX), and the
- context CTX will appear as if it had finished with the error code
- ‘GPG_ERR_CANCEL’.
+ If you use the global event loop, you must not call ‘gpgme_wait’
+ during cancellation. After successful cancellation, you can call
+ ‘gpgme_wait’ (optionally waiting on CTX), and the context CTX will
+ appear as if it had finished with the error code ‘GPG_ERR_CANCEL’.
- If you use your an external event loop, you must ensure that no I/O
+ If you use an external event loop, you must ensure that no I/O
callbacks are invoked for this context (for example by halting the
event loop). On successful cancellation, all registered I/O
callbacks for this context will be unregistered, and a
‘GPGME_EVENT_DONE’ event with the error code ‘GPG_ERR_CANCEL’ will
- be signaled.
+ be signalled.
The function returns an error code if the cancellation failed (in
this case the state of CTX is not modified).
@@ -6388,7 +6438,7 @@ associate operations the server MAY support the command:
the last command. A ‘RESET’ undoes the effect of this command.

-File: gpgme.info, Node: Debugging, Next: Library Copying, Prev: UI Server Protocol, Up: Top
+File: gpgme.info, Node: Debugging, Next: Deprecated Functions, Prev: UI Server Protocol, Up: Top
Appendix B How to solve problems
********************************
@@ -6424,526 +6474,647 @@ application. If you are asked to send a log file, make sure that you
run your tests only with play data.

-File: gpgme.info, Node: Library Copying, Next: Copying, Prev: Debugging, Up: Top
-
-GNU Lesser General Public License
-*********************************
-
- Version 2.1, February 1999
-
- Copyright © 1991, 1999 Free Software Foundation, Inc.
- 59 Temple Place – Suite 330, Boston, MA 02111-1307, USA
-
- Everyone is permitted to copy and distribute verbatim copies
- of this license document, but changing it is not allowed.
-
- [This is the first released version of the Lesser GPL. It also counts
- as the successor of the GNU Library Public License, version 2, hence the
- version number 2.1.]
-
-Preamble
-========
-
-The licenses for most software are designed to take away your freedom to
-share and change it. By contrast, the GNU General Public Licenses are
-intended to guarantee your freedom to share and change free software—to
-make sure the software is free for all its users.
-
- This license, the Lesser General Public License, applies to some
-specially designated software—typically libraries—of the Free Software
-Foundation and other authors who decide to use it. You can use it too,
-but we suggest you first think carefully about whether this license or
-the ordinary General Public License is the better strategy to use in any
-particular case, based on the explanations below.
-
- When we speak of free software, we are referring to freedom of use,
-not price. Our General Public Licenses are designed to make sure that
-you have the freedom to distribute copies of free software (and charge
-for this service if you wish); that you receive source code or can get
-it if you want it; that you can change the software and use pieces of it
-in new free programs; and that you are informed that you can do these
-things.
-
- To protect your rights, we need to make restrictions that forbid
-distributors to deny you these rights or to ask you to surrender these
-rights. These restrictions translate to certain responsibilities for
-you if you distribute copies of the library or if you modify it.
-
- For example, if you distribute copies of the library, whether gratis
-or for a fee, you must give the recipients all the rights that we gave
-you. You must make sure that they, too, receive or can get the source
-code. If you link other code with the library, you must provide
-complete object files to the recipients, so that they can relink them
-with the library after making changes to the library and recompiling it.
-And you must show them these terms so they know their rights.
-
- We protect your rights with a two-step method: (1) we copyright the
-library, and (2) we offer you this license, which gives you legal
-permission to copy, distribute and/or modify the library.
-
- To protect each distributor, we want to make it very clear that there
-is no warranty for the free library. Also, if the library is modified
-by someone else and passed on, the recipients should know that what they
-have is not the original version, so that the original author’s
-reputation will not be affected by problems that might be introduced by
-others.
-
- Finally, software patents pose a constant threat to the existence of
-any free program. We wish to make sure that a company cannot
-effectively restrict the users of a free program by obtaining a
-restrictive license from a patent holder. Therefore, we insist that any
-patent license obtained for a version of the library must be consistent
-with the full freedom of use specified in this license.
-
- Most GNU software, including some libraries, is covered by the
-ordinary GNU General Public License. This license, the GNU Lesser
-General Public License, applies to certain designated libraries, and is
-quite different from the ordinary General Public License. We use this
-license for certain libraries in order to permit linking those libraries
-into non-free programs.
-
- When a program is linked with a library, whether statically or using
-a shared library, the combination of the two is legally speaking a
-combined work, a derivative of the original library. The ordinary
-General Public License therefore permits such linking only if the entire
-combination fits its criteria of freedom. The Lesser General Public
-License permits more lax criteria for linking other code with the
-library.
-
- We call this license the "Lesser" General Public License because it
-does _Less_ to protect the user’s freedom than the ordinary General
-Public License. It also provides other free software developers Less of
-an advantage over competing non-free programs. These disadvantages are
-the reason we use the ordinary General Public License for many
-libraries. However, the Lesser license provides advantages in certain
-special circumstances.
-
- For example, on rare occasions, there may be a special need to
-encourage the widest possible use of a certain library, so that it
-becomes a de-facto standard. To achieve this, non-free programs must be
-allowed to use the library. A more frequent case is that a free library
-does the same job as widely used non-free libraries. In this case,
-there is little to gain by limiting the free library to free software
-only, so we use the Lesser General Public License.
-
- In other cases, permission to use a particular library in non-free
-programs enables a greater number of people to use a large body of free
-software. For example, permission to use the GNU C Library in non-free
-programs enables many more people to use the whole GNU operating system,
-as well as its variant, the GNU/Linux operating system.
-
- Although the Lesser General Public License is Less protective of the
-users’ freedom, it does ensure that the user of a program that is linked
-with the Library has the freedom and the wherewithal to run that program
-using a modified version of the Library.
-
- The precise terms and conditions for copying, distribution and
-modification follow. Pay close attention to the difference between a
-“work based on the library†and a “work that uses the libraryâ€. The
-former contains code derived from the library, whereas the latter must
-be combined with the library in order to run.
-
- GNU LESSER GENERAL PUBLIC LICENSE
- TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION
-
- 0. This License Agreement applies to any software library or other
- program which contains a notice placed by the copyright holder or
- other authorized party saying it may be distributed under the terms
- of this Lesser General Public License (also called “this Licenseâ€).
- Each licensee is addressed as “youâ€.
-
- A “library†means a collection of software functions and/or data
- prepared so as to be conveniently linked with application programs
- (which use some of those functions and data) to form executables.
-
- The “Libraryâ€, below, refers to any such software library or work
- which has been distributed under these terms. A “work based on the
- Library†means either the Library or any derivative work under
- copyright law: that is to say, a work containing the Library or a
- portion of it, either verbatim or with modifications and/or
- translated straightforwardly into another language. (Hereinafter,
- translation is included without limitation in the term
- “modificationâ€.)
-
- “Source code†for a work means the preferred form of the work for
- making modifications to it. For a library, complete source code
- means all the source code for all modules it contains, plus any
- associated interface definition files, plus the scripts used to
- control compilation and installation of the library.
-
- Activities other than copying, distribution and modification are
- not covered by this License; they are outside its scope. The act
- of running a program using the Library is not restricted, and
- output from such a program is covered only if its contents
- constitute a work based on the Library (independent of the use of
- the Library in a tool for writing it). Whether that is true
- depends on what the Library does and what the program that uses the
- Library does.
-
- 1. You may copy and distribute verbatim copies of the Library’s
- complete source code as you receive it, in any medium, provided
- that you conspicuously and appropriately publish on each copy an
- appropriate copyright notice and disclaimer of warranty; keep
- intact all the notices that refer to this License and to the
- absence of any warranty; and distribute a copy of this License
- along with the Library.
-
- You may charge a fee for the physical act of transferring a copy,
- and you may at your option offer warranty protection in exchange
- for a fee.
-
- 2. You may modify your copy or copies of the Library or any portion of
- it, thus forming a work based on the Library, and copy and
- distribute such modifications or work under the terms of Section 1
- above, provided that you also meet all of these conditions:
-
- a. The modified work must itself be a software library.
-
- b. You must cause the files modified to carry prominent notices
- stating that you changed the files and the date of any change.
-
- c. You must cause the whole of the work to be licensed at no
- charge to all third parties under the terms of this License.
-
- d. If a facility in the modified Library refers to a function or
- a table of data to be supplied by an application program that
- uses the facility, other than as an argument passed when the
- facility is invoked, then you must make a good faith effort to
- ensure that, in the event an application does not supply such
- function or table, the facility still operates, and performs
- whatever part of its purpose remains meaningful.
-
- (For example, a function in a library to compute square roots
- has a purpose that is entirely well-defined independent of the
- application. Therefore, Subsection 2d requires that any
- application-supplied function or table used by this function
- must be optional: if the application does not supply it, the
- square root function must still compute square roots.)
-
- These requirements apply to the modified work as a whole. If
- identifiable sections of that work are not derived from the
- Library, and can be reasonably considered independent and separate
- works in themselves, then this License, and its terms, do not apply
- to those sections when you distribute them as separate works. But
- when you distribute the same sections as part of a whole which is a
- work based on the Library, the distribution of the whole must be on
- the terms of this License, whose permissions for other licensees
- extend to the entire whole, and thus to each and every part
- regardless of who wrote it.
-
- Thus, it is not the intent of this section to claim rights or
- contest your rights to work written entirely by you; rather, the
- intent is to exercise the right to control the distribution of
- derivative or collective works based on the Library.
-
- In addition, mere aggregation of another work not based on the
- Library with the Library (or with a work based on the Library) on a
- volume of a storage or distribution medium does not bring the other
- work under the scope of this License.
-
- 3. You may opt to apply the terms of the ordinary GNU General Public
- License instead of this License to a given copy of the Library. To
- do this, you must alter all the notices that refer to this License,
- so that they refer to the ordinary GNU General Public License,
- version 2, instead of to this License. (If a newer version than
- version 2 of the ordinary GNU General Public License has appeared,
- then you can specify that version instead if you wish.) Do not
- make any other change in these notices.
-
- Once this change is made in a given copy, it is irreversible for
- that copy, so the ordinary GNU General Public License applies to
- all subsequent copies and derivative works made from that copy.
-
- This option is useful when you wish to copy part of the code of the
- Library into a program that is not a library.
-
- 4. You may copy and distribute the Library (or a portion or derivative
- of it, under Section 2) in object code or executable form under the
- terms of Sections 1 and 2 above provided that you accompany it with
- the complete corresponding machine-readable source code, which must
- be distributed under the terms of Sections 1 and 2 above on a
- medium customarily used for software interchange.
-
- If distribution of object code is made by offering access to copy
- from a designated place, then offering equivalent access to copy
- the source code from the same place satisfies the requirement to
- distribute the source code, even though third parties are not
- compelled to copy the source along with the object code.
-
- 5. A program that contains no derivative of any portion of the
- Library, but is designed to work with the Library by being compiled
- or linked with it, is called a “work that uses the Libraryâ€. Such
- a work, in isolation, is not a derivative work of the Library, and
- therefore falls outside the scope of this License.
-
- However, linking a “work that uses the Library†with the Library
- creates an executable that is a derivative of the Library (because
- it contains portions of the Library), rather than a “work that uses
- the libraryâ€. The executable is therefore covered by this License.
- Section 6 states terms for distribution of such executables.
-
- When a “work that uses the Library†uses material from a header
- file that is part of the Library, the object code for the work may
- be a derivative work of the Library even though the source code is
- not. Whether this is true is especially significant if the work
- can be linked without the Library, or if the work is itself a
- library. The threshold for this to be true is not precisely
- defined by law.
-
- If such an object file uses only numerical parameters, data
- structure layouts and accessors, and small macros and small inline
- functions (ten lines or less in length), then the use of the object
- file is unrestricted, regardless of whether it is legally a
- derivative work. (Executables containing this object code plus
- portions of the Library will still fall under Section 6.)
-
- Otherwise, if the work is a derivative of the Library, you may
- distribute the object code for the work under the terms of Section
- 6. Any executables containing that work also fall under Section 6,
- whether or not they are linked directly with the Library itself.
-
- 6. As an exception to the Sections above, you may also combine or link
- a “work that uses the Library†with the Library to produce a work
- containing portions of the Library, and distribute that work under
- terms of your choice, provided that the terms permit modification
- of the work for the customer’s own use and reverse engineering for
- debugging such modifications.
-
- You must give prominent notice with each copy of the work that the
- Library is used in it and that the Library and its use are covered
- by this License. You must supply a copy of this License. If the
- work during execution displays copyright notices, you must include
- the copyright notice for the Library among them, as well as a
- reference directing the user to the copy of this License. Also,
- you must do one of these things:
-
- a. Accompany the work with the complete corresponding
- machine-readable source code for the Library including
- whatever changes were used in the work (which must be
- distributed under Sections 1 and 2 above); and, if the work is
- an executable linked with the Library, with the complete
- machine-readable “work that uses the Libraryâ€, as object code
- and/or source code, so that the user can modify the Library
- and then relink to produce a modified executable containing
- the modified Library. (It is understood that the user who
- changes the contents of definitions files in the Library will
- not necessarily be able to recompile the application to use
- the modified definitions.)
-
- b. Use a suitable shared library mechanism for linking with the
- Library. A suitable mechanism is one that (1) uses at run
- time a copy of the library already present on the user’s
- computer system, rather than copying library functions into
- the executable, and (2) will operate properly with a modified
- version of the library, if the user installs one, as long as
- the modified version is interface-compatible with the version
- that the work was made with.
-
- c. Accompany the work with a written offer, valid for at least
- three years, to give the same user the materials specified in
- Subsection 6a, above, for a charge no more than the cost of
- performing this distribution.
-
- d. If distribution of the work is made by offering access to copy
- from a designated place, offer equivalent access to copy the
- above specified materials from the same place.
-
- e. Verify that the user has already received a copy of these
- materials or that you have already sent this user a copy.
-
- For an executable, the required form of the “work that uses the
- Library†must include any data and utility programs needed for
- reproducing the executable from it. However, as a special
- exception, the materials to be distributed need not include
- anything that is normally distributed (in either source or binary
- form) with the major components (compiler, kernel, and so on) of
- the operating system on which the executable runs, unless that
- component itself accompanies the executable.
-
- It may happen that this requirement contradicts the license
- restrictions of other proprietary libraries that do not normally
- accompany the operating system. Such a contradiction means you
- cannot use both them and the Library together in an executable that
- you distribute.
-
- 7. You may place library facilities that are a work based on the
- Library side-by-side in a single library together with other
- library facilities not covered by this License, and distribute such
- a combined library, provided that the separate distribution of the
- work based on the Library and of the other library facilities is
- otherwise permitted, and provided that you do these two things:
-
- a. Accompany the combined library with a copy of the same work
- based on the Library, uncombined with any other library
- facilities. This must be distributed under the terms of the
- Sections above.
-
- b. Give prominent notice with the combined library of the fact
- that part of it is a work based on the Library, and explaining
- where to find the accompanying uncombined form of the same
- work.
-
- 8. You may not copy, modify, sublicense, link with, or distribute the
- Library except as expressly provided under this License. Any
- attempt otherwise to copy, modify, sublicense, link with, or
- distribute the Library is void, and will automatically terminate
- your rights under this License. However, parties who have received
- copies, or rights, from you under this License will not have their
- licenses terminated so long as such parties remain in full
- compliance.
-
- 9. You are not required to accept this License, since you have not
- signed it. However, nothing else grants you permission to modify
- or distribute the Library or its derivative works. These actions
- are prohibited by law if you do not accept this License.
- Therefore, by modifying or distributing the Library (or any work
- based on the Library), you indicate your acceptance of this License
- to do so, and all its terms and conditions for copying,
- distributing or modifying the Library or works based on it.
-
- 10. Each time you redistribute the Library (or any work based on the
- Library), the recipient automatically receives a license from the
- original licensor to copy, distribute, link with or modify the
- Library subject to these terms and conditions. You may not impose
- any further restrictions on the recipients’ exercise of the rights
- granted herein. You are not responsible for enforcing compliance
- by third parties with this License.
-
- 11. If, as a consequence of a court judgment or allegation of patent
- infringement or for any other reason (not limited to patent
- issues), conditions are imposed on you (whether by court order,
- agreement or otherwise) that contradict the conditions of this
- License, they do not excuse you from the conditions of this
- License. If you cannot distribute so as to satisfy simultaneously
- your obligations under this License and any other pertinent
- obligations, then as a consequence you may not distribute the
- Library at all. For example, if a patent license would not permit
- royalty-free redistribution of the Library by all those who receive
- copies directly or indirectly through you, then the only way you
- could satisfy both it and this License would be to refrain entirely
- from distribution of the Library.
-
- If any portion of this section is held invalid or unenforceable
- under any particular circumstance, the balance of the section is
- intended to apply, and the section as a whole is intended to apply
- in other circumstances.
-
- It is not the purpose of this section to induce you to infringe any
- patents or other property right claims or to contest validity of
- any such claims; this section has the sole purpose of protecting
- the integrity of the free software distribution system which is
- implemented by public license practices. Many people have made
- generous contributions to the wide range of software distributed
- through that system in reliance on consistent application of that
- system; it is up to the author/donor to decide if he or she is
- willing to distribute software through any other system and a
- licensee cannot impose that choice.
-
- This section is intended to make thoroughly clear what is believed
- to be a consequence of the rest of this License.
-
- 12. If the distribution and/or use of the Library is restricted in
- certain countries either by patents or by copyrighted interfaces,
- the original copyright holder who places the Library under this
- License may add an explicit geographical distribution limitation
- excluding those countries, so that distribution is permitted only
- in or among countries not thus excluded. In such case, this
- License incorporates the limitation as if written in the body of
- this License.
-
- 13. The Free Software Foundation may publish revised and/or new
- versions of the Lesser General Public License from time to time.
- Such new versions will be similar in spirit to the present version,
- but may differ in detail to address new problems or concerns.
-
- Each version is given a distinguishing version number. If the
- Library specifies a version number of this License which applies to
- it and “any later versionâ€, you have the option of following the
- terms and conditions either of that version or of any later version
- published by the Free Software Foundation. If the Library does not
- specify a license version number, you may choose any version ever
- published by the Free Software Foundation.
-
- 14. If you wish to incorporate parts of the Library into other free
- programs whose distribution conditions are incompatible with these,
- write to the author to ask for permission. For software which is
- copyrighted by the Free Software Foundation, write to the Free
- Software Foundation; we sometimes make exceptions for this. Our
- decision will be guided by the two goals of preserving the free
- status of all derivatives of our free software and of promoting the
- sharing and reuse of software generally.
-
- NO WARRANTY
-
- 15. BECAUSE THE LIBRARY IS LICENSED FREE OF CHARGE, THERE IS NO
- WARRANTY FOR THE LIBRARY, TO THE EXTENT PERMITTED BY APPLICABLE
- LAW. EXCEPT WHEN OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS
- AND/OR OTHER PARTIES PROVIDE THE LIBRARY “AS IS†WITHOUT WARRANTY
- OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, BUT NOT
- LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
- FOR A PARTICULAR PURPOSE. THE ENTIRE RISK AS TO THE QUALITY AND
- PERFORMANCE OF THE LIBRARY IS WITH YOU. SHOULD THE LIBRARY PROVE
- DEFECTIVE, YOU ASSUME THE COST OF ALL NECESSARY SERVICING, REPAIR
- OR CORRECTION.
-
- 16. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN
- WRITING WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY
- MODIFY AND/OR REDISTRIBUTE THE LIBRARY AS PERMITTED ABOVE, BE
- LIABLE TO YOU FOR DAMAGES, INCLUDING ANY GENERAL, SPECIAL,
- INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING OUT OF THE USE OR
- INABILITY TO USE THE LIBRARY (INCLUDING BUT NOT LIMITED TO LOSS OF
- DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY YOU
- OR THIRD PARTIES OR A FAILURE OF THE LIBRARY TO OPERATE WITH ANY
- OTHER SOFTWARE), EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN
- ADVISED OF THE POSSIBILITY OF SUCH DAMAGES.
-
- END OF TERMS AND CONDITIONS
-
-How to Apply These Terms to Your New Libraries
-==============================================
+File: gpgme.info, Node: Deprecated Functions, Next: Library Copying, Prev: Debugging, Up: Top
+
+Appendix C Deprecated Functions
+*******************************
+
+For backward compatibility GPGME has a number of functions, data types
+and constants which are deprecated and should not be used anymore. We
+document here those which are really old to help understanding old code
+and to allow migration to their modern counterparts.
+
+ *Warning:* These interfaces will be removed in a future version of
+GPGME.
+
+ -- Function: void gpgme_key_release (gpgme_key_t KEY)
+ The function ‘gpgme_key_release’ is equivalent to
+ ‘gpgme_key_unref’.
+
+ -- Function: void gpgme_trust_item_release (gpgme_trust_item_t ITEM)
+ The function ‘gpgme_trust_item_release’ is an alias for
+ ‘gpgme_trust_item_unref’.
+
+ -- Function: gpgme_error_t gpgme_op_import_ext (gpgme_ctx_t CTX,
+ gpgme_data_t KEYDATA, int *NR)
+ The function ‘gpgme_op_import_ext’ is equivalent to:
+
+ gpgme_error_t err = gpgme_op_import (ctx, keydata);
+ if (!err)
+ {
+ gpgme_import_result_t result = gpgme_op_import_result (ctx);
+ *nr = result->considered;
+ }
+
+ -- Data type: gpgme_error_t (*gpgme_edit_cb_t) (void *HANDLE,
+ gpgme_status_code_t STATUS, const char *ARGS, int FD)
+ The ‘gpgme_edit_cb_t’ type is the type of functions which GPGME
+ calls if it a key edit operation is on-going. The status code
+ STATUS and the argument line ARGS are passed through by GPGME from
+ the crypto engine. The file descriptor FD is -1 for normal status
+ messages. If STATUS indicates a command rather than a status
+ message, the response to the command should be written to FD. The
+ HANDLE is provided by the user at start of operation.
+
+ The function should return ‘GPG_ERR_FALSE’ if it did not handle the
+ status code, ‘0’ for success, or any other error value.
+
+ -- Function: gpgme_error_t gpgme_op_edit (gpgme_ctx_t CTX,
+ gpgme_key_t KEY, gpgme_edit_cb_t FNC, void *HANDLE,
+ gpgme_data_t OUT)
+ Note: This function is deprecated, please use ‘gpgme_op_interact’
+ instead.
+
+ The function ‘gpgme_op_edit’ processes the key KEY interactively,
+ using the edit callback function FNC with the handle HANDLE. The
+ callback is invoked for every status and command request from the
+ crypto engine. The output of the crypto engine is written to the
+ data object OUT.
+
+ Note that the protocol between the callback function and the crypto
+ engine is specific to the crypto engine and no further support in
+ implementing this protocol correctly is provided by GPGME.
+
+ The function returns the error code ‘GPG_ERR_NO_ERROR’ if the edit
+ operation completes successfully, ‘GPG_ERR_INV_VALUE’ if CTX or KEY
+ is not a valid pointer, and any error returned by the crypto engine
+ or the edit callback handler.
+
+ -- Function: gpgme_error_t gpgme_op_edit_start (gpgme_ctx_t CTX,
+ gpgme_key_t KEY, gpgme_edit_cb_t FNC, void *HANDLE,
+ gpgme_data_t OUT)
+ Note: This function is deprecated, please use
+ ‘gpgme_op_interact_start’ instead.
+
+ The function ‘gpgme_op_edit_start’ initiates a ‘gpgme_op_edit’
+ operation. It can be completed by calling ‘gpgme_wait’ on the
+ context. *Note Waiting For Completion::.
+
+ The function returns the error code ‘GPG_ERR_NO_ERROR’ if the
+ operation was started successfully, and ‘GPG_ERR_INV_VALUE’ if CTX
+ or KEY is not a valid pointer.
+
+ -- Function: gpgme_error_t gpgme_op_card_edit (gpgme_ctx_t CTX,
+ gpgme_key_t KEY, gpgme_edit_cb_t FNC, void *HANDLE,
+ gpgme_data_t OUT)
+ Note: This function is deprecated, please use ‘gpgme_op_interact’
+ with the flag ‘GPGME_INTERACT_CARD’ instead.
+
+ The function ‘gpgme_op_card_edit’ is analogous to ‘gpgme_op_edit’,
+ but should be used to process the smart card corresponding to the
+ key KEY.
+
+ -- Function: gpgme_error_t gpgme_op_card_edit_start (gpgme_ctx_t CTX,
+ gpgme_key_t KEY, gpgme_edit_cb_t FNC, void *HANDLE,
+ gpgme_data_t OUT)
+ Note: This function is deprecated, please use
+ ‘gpgme_op_interact_start’ with the flag ‘GPGME_INTERACT_CARD’
+ instead.
+
+ The function ‘gpgme_op_card_edit_start’ initiates a
+ ‘gpgme_op_card_edit’ operation. It can be completed by calling
+ ‘gpgme_wait’ on the context. *Note Waiting For Completion::.
+
+ The function returns the error code ‘GPG_ERR_NO_ERROR’ if the
+ operation was started successfully, and ‘GPG_ERR_INV_VALUE’ if CTX
+ or KEY is not a valid pointer.
+
+ -- Function: gpgme_error_t gpgme_data_new_with_read_cb
+ (gpgme_data_t *DH, int (*READFUNC) (void *HOOK, char *BUFFER,
+ size_t COUNT, size_t *NREAD), void *HOOK_VALUE)
+ The function ‘gpgme_data_new_with_read_cb’ creates a new
+ ‘gpgme_data_t’ object and uses the callback function READFUNC to
+ retrieve the data on demand. As the callback function can supply
+ the data in any way it wants, this is the most flexible data type
+ GPGME provides. However, it can not be used to write data.
+
+ The callback function receives HOOK_VALUE as its first argument
+ whenever it is invoked. It should return up to COUNT bytes in
+ BUFFER, and return the number of bytes actually read in NREAD. It
+ may return ‘0’ in NREAD if no data is currently available. To
+ indicate ‘EOF’ the function should return with an error code of
+ ‘-1’ and set NREAD to ‘0’. The callback function may support to
+ reset its internal read pointer if it is invoked with BUFFER and
+ NREAD being ‘NULL’ and COUNT being ‘0’.
+
+ The function returns the error code ‘GPG_ERR_NO_ERROR’ if the data
+ object was successfully created, ‘GPG_ERR_INV_VALUE’ if DH or
+ READFUNC is not a valid pointer, and ‘GPG_ERR_ENOMEM’ if not enough
+ memory is available.
+
+ -- Function: gpgme_error_t gpgme_data_rewind (gpgme_data_t DH)
+ The function ‘gpgme_data_rewind’ is equivalent to:
+
+ return (gpgme_data_seek (dh, 0, SEEK_SET) == -1)
+ ? gpgme_error_from_errno (errno) : 0;
+
+ -- Data type: gpgme_attr_t
+ The ‘gpgme_attr_t’ type is used to specify a key or trust item
+ attribute. The following attributes are defined:
+
+ ‘GPGME_ATTR_KEYID’
+ This is the key ID of a sub key. It is representable as a
+ string.
+
+ For trust items, the trust item refers to the key with this
+ ID.
+
+ ‘GPGME_ATTR_FPR’
+ This is the fingerprint of a sub key. It is representable as
+ a string.
+
+ ‘GPGME_ATTR_ALGO’
+ This is the crypto algorithm for which the sub key can be
+ used. It is representable as a string and as a number. The
+ numbers correspond to the ‘enum gcry_pk_algos’ values in the
+ gcrypt library.
+
+ ‘GPGME_ATTR_LEN’
+ This is the key length of a sub key. It is representable as a
+ number.
+
+ ‘GPGME_ATTR_CREATED’
+ This is the timestamp at creation time of a sub key. It is
+ representable as a number.
+
+ ‘GPGME_ATTR_EXPIRE’
+ This is the expiration time of a sub key. It is representable
+ as a number.
+
+ ‘GPGME_ATTR_OTRUST’
+ XXX FIXME (also for trust items)
+
+ ‘GPGME_ATTR_USERID’
+ This is a user ID. There can be more than one user IDs in a
+ GPGME_KEY_T object. The first one (with index 0) is the
+ primary user ID. The user ID is representable as a number.
+
+ For trust items, this is the user ID associated with this
+ trust item.
+
+ ‘GPGME_ATTR_NAME’
+ This is the name belonging to a user ID. It is representable
+ as a string.
+
+ ‘GPGME_ATTR_EMAIL’
+ This is the email address belonging to a user ID. It is
+ representable as a string.
+
+ ‘GPGME_ATTR_COMMENT’
+ This is the comment belonging to a user ID. It is
+ representable as a string.
+
+ ‘GPGME_ATTR_VALIDITY’
+ This is the validity belonging to a user ID. It is
+ representable as a string and as a number. See below for a
+ list of available validities.
+
+ For trust items, this is the validity that is associated with
+ this trust item.
+
+ ‘GPGME_ATTR_UID_REVOKED’
+ This specifies if a user ID is revoked. It is representable
+ as a number, and is ‘1’ if the user ID is revoked, and ‘0’
+ otherwise.
+
+ ‘GPGME_ATTR_UID_INVALID’
+ This specifies if a user ID is invalid. It is representable
+ as a number, and is ‘1’ if the user ID is invalid, and ‘0’
+ otherwise.
+
+ ‘GPGME_ATTR_LEVEL’
+ This is the trust level of a trust item.
+
+ ‘GPGME_ATTR_TYPE’
+ This returns information about the type of key. For the
+ string function this will eother be "PGP" or "X.509". The
+ integer function returns 0 for PGP and 1 for X.509. It is
+ also used for the type of a trust item.
+
+ ‘GPGME_ATTR_IS_SECRET’
+ This specifies if the key is a secret key. It is
+ representable as a number, and is ‘1’ if the key is revoked,
+ and ‘0’ otherwise.
+
+ ‘GPGME_ATTR_KEY_REVOKED’
+ This specifies if a sub key is revoked. It is representable
+ as a number, and is ‘1’ if the key is revoked, and ‘0’
+ otherwise.
+
+ ‘GPGME_ATTR_KEY_INVALID’
+ This specifies if a sub key is invalid. It is representable
+ as a number, and is ‘1’ if the key is invalid, and ‘0’
+ otherwise.
+
+ ‘GPGME_ATTR_KEY_EXPIRED’
+ This specifies if a sub key is expired. It is representable
+ as a number, and is ‘1’ if the key is expired, and ‘0’
+ otherwise.
+
+ ‘GPGME_ATTR_KEY_DISABLED’
+ This specifies if a sub key is disabled. It is representable
+ as a number, and is ‘1’ if the key is disabled, and ‘0’
+ otherwise.
+
+ ‘GPGME_ATTR_KEY_CAPS’
+ This is a description of the capabilities of a sub key. It is
+ representable as a string. The string contains the letter “eâ€
+ if the key can be used for encryption, “s†if the key can be
+ used for signatures, and “c†if the key can be used for
+ certifications.
+
+ ‘GPGME_ATTR_CAN_ENCRYPT’
+ This specifies if a sub key can be used for encryption. It is
+ representable as a number, and is ‘1’ if the sub key can be
+ used for encryption, and ‘0’ otherwise.
+
+ ‘GPGME_ATTR_CAN_SIGN’
+ This specifies if a sub key can be used to create data
+ signatures. It is representable as a number, and is ‘1’ if
+ the sub key can be used for signatures, and ‘0’ otherwise.
+
+ ‘GPGME_ATTR_CAN_CERTIFY’
+ This specifies if a sub key can be used to create key
+ certificates. It is representable as a number, and is ‘1’ if
+ the sub key can be used for certifications, and ‘0’ otherwise.
+
+ ‘GPGME_ATTR_SERIAL’
+ The X.509 issuer serial attribute of the key. It is
+ representable as a string.
+
+ ‘GPGME_ATTR_ISSUE’
+ The X.509 issuer name attribute of the key. It is
+ representable as a string.
+
+ ‘GPGME_ATTR_CHAINID’
+ The X.509 chain ID can be used to build the certification
+ chain. It is representable as a string.
+
+ -- Function: const char * gpgme_key_get_string_attr (gpgme_key_t KEY,
+ gpgme_attr_t WHAT, const void *RESERVED, int IDX)
+ The function ‘gpgme_key_get_string_attr’ returns the value of the
+ string-representable attribute WHAT of key KEY. If the attribute
+ is an attribute of a sub key or an user ID, IDX specifies the sub
+ key or user ID of which the attribute value is returned. The
+ argument RESERVED is reserved for later use and should be ‘NULL’.
+
+ The string returned is only valid as long as the key is valid.
+
+ The function returns ‘0’ if an attribute can’t be returned as a
+ string, KEY is not a valid pointer, IDX out of range, or RESERVED
+ not ‘NULL’.
+
+ -- Function: unsigned long gpgme_key_get_ulong_attr (gpgme_key_t KEY,
+ gpgme_attr_t WHAT, const void *RESERVED, int IDX)
+ The function ‘gpgme_key_get_ulong_attr’ returns the value of the
+ number-representable attribute WHAT of key KEY. If the attribute
+ is an attribute of a sub key or an user ID, IDX specifies the sub
+ key or user ID of which the attribute value is returned. The
+ argument RESERVED is reserved for later use and should be ‘NULL’.
+
+ The function returns ‘0’ if the attribute can’t be returned as a
+ number, KEY is not a valid pointer, IDX out of range, or RESERVED
+ not ‘NULL’.
+
+ The signatures on a key are only available if the key was retrieved
+via a listing operation with the ‘GPGME_KEYLIST_MODE_SIGS’ mode enabled,
+because it is expensive to retrieve all signatures of a key.
+
+ So, before using the below interfaces to retrieve the signatures on a
+key, you have to make sure that the key was listed with signatures
+enabled. One convenient, but blocking, way to do this is to use the
+function ‘gpgme_get_key’.
+
+ -- Data type: gpgme_attr_t
+ The ‘gpgme_attr_t’ type is used to specify a key signature
+ attribute. The following attributes are defined:
+
+ ‘GPGME_ATTR_KEYID’
+ This is the key ID of the key which was used for the
+ signature. It is representable as a string.
+
+ ‘GPGME_ATTR_ALGO’
+ This is the crypto algorithm used to create the signature. It
+ is representable as a string and as a number. The numbers
+ correspond to the ‘enum gcry_pk_algos’ values in the gcrypt
+ library.
+
+ ‘GPGME_ATTR_CREATED’
+ This is the timestamp at creation time of the signature. It
+ is representable as a number.
+
+ ‘GPGME_ATTR_EXPIRE’
+ This is the expiration time of the signature. It is
+ representable as a number.
+
+ ‘GPGME_ATTR_USERID’
+ This is the user ID associated with the signing key. The user
+ ID is representable as a number.
+
+ ‘GPGME_ATTR_NAME’
+ This is the name belonging to a user ID. It is representable
+ as a string.
+
+ ‘GPGME_ATTR_EMAIL’
+ This is the email address belonging to a user ID. It is
+ representable as a string.
+
+ ‘GPGME_ATTR_COMMENT’
+ This is the comment belonging to a user ID. It is
+ representable as a string.
+
+ ‘GPGME_ATTR_KEY_REVOKED’
+ This specifies if a key signature is a revocation signature.
+ It is representable as a number, and is ‘1’ if the key is
+ revoked, and ‘0’ otherwise.
+
+ ‘GPGME_ATTR_SIG_CLASS’
+ This specifies the signature class of a key signature. It is
+ representable as a number. The meaning is specific to the
+ crypto engine.
+
+ ‘GPGME_ATTR_SIG_CLASS’
+ This specifies the signature class of a key signature. It is
+ representable as a number. The meaning is specific to the
+ crypto engine.
+
+ ‘GPGME_ATTR_SIG_STATUS’
+ This is the same value as returned by ‘gpgme_get_sig_status’.
+
+ -- Function: const char * gpgme_key_sig_get_string_attr
+ (gpgme_key_t KEY, int UID_IDX, gpgme_attr_t WHAT,
+ const void *RESERVED, int IDX)
+ The function ‘gpgme_key_sig_get_string_attr’ returns the value of
+ the string-representable attribute WHAT of the signature IDX on the
+ user ID UID_IDX in the key KEY. The argument RESERVED is reserved
+ for later use and should be ‘NULL’.
+
+ The string returned is only valid as long as the key is valid.
+
+ The function returns ‘0’ if an attribute can’t be returned as a
+ string, KEY is not a valid pointer, UID_IDX or IDX out of range, or
+ RESERVED not ‘NULL’.
+
+ -- Function: unsigned long gpgme_key_sig_get_ulong_attr
+ (gpgme_key_t KEY, int UID_IDX, gpgme_attr_t WHAT,
+ const void *RESERVED, int IDX)
+ The function ‘gpgme_key_sig_get_ulong_attr’ returns the value of
+ the number-representable attribute WHAT of the signature IDX on the
+ user ID UID_IDX in the key KEY. The argument RESERVED is reserved
+ for later use and should be ‘NULL’.
+
+ The function returns ‘0’ if an attribute can’t be returned as a
+ string, KEY is not a valid pointer, UID_IDX or IDX out of range, or
+ RESERVED not ‘NULL’.
+
+ Trust items have attributes which can be queried using the interfaces
+below. The attribute identifiers are shared with those for key
+attributes. *Note Information About Keys::.
+
+ -- Function: const char * gpgme_trust_item_get_string_attr
+ (gpgme_trust_item_t ITEM, gpgme_attr_t WHAT,
+ const void *RESERVED, int IDX)
+ The function ‘gpgme_trust_item_get_string_attr’ returns the value
+ of the string-representable attribute WHAT of trust item ITEM. The
+ arguments IDX and RESERVED are reserved for later use and should be
+ ‘0’ and ‘NULL’ respectively.
+
+ The string returned is only valid as long as the key is valid.
+
+ The function returns ‘0’ if an attribute can’t be returned as a
+ string, KEY is not a valid pointer, IDX out of range, or RESERVED
+ not ‘NULL’.
+
+ -- Function: int gpgme_trust_item_get_int_attr
+ (gpgme_trust_item_t ITEM, gpgme_attr_t WHAT,
+ const void *RESERVED, int IDX)
+ The function ‘gpgme_trust_item_get_int_attr’ returns the value of
+ the number-representable attribute WHAT of trust item ITEM. If the
+ attribute occurs more than once in the trust item, the index is
+ specified by IDX. However, currently no such attribute exists, so
+ IDX should be ‘0’. The argument RESERVED is reserved for later use
+ and should be ‘NULL’.
+
+ The function returns ‘0’ if the attribute can’t be returned as a
+ number, KEY is not a valid pointer, IDX out of range, or RESERVED
+ not ‘NULL’.
+
+ -- Data type: enum gpgme_sig_stat_t
+ The ‘gpgme_sig_stat_t’ type holds the result of a signature check,
+ or the combined result of all signatures. The following results
+ are possible:
+
+ ‘GPGME_SIG_STAT_NONE’
+ This status should not occur in normal operation.
+
+ ‘GPGME_SIG_STAT_GOOD’
+ This status indicates that the signature is valid. For the
+ combined result this status means that all signatures are
+ valid.
+
+ ‘GPGME_SIG_STAT_GOOD_EXP’
+ This status indicates that the signature is valid but expired.
+ For the combined result this status means that all signatures
+ are valid and expired.
+
+ ‘GPGME_SIG_STAT_GOOD_EXPKEY’
+ This status indicates that the signature is valid but the key
+ used to verify the signature has expired. For the combined
+ result this status means that all signatures are valid and all
+ keys are expired.
+
+ ‘GPGME_SIG_STAT_BAD’
+ This status indicates that the signature is invalid. For the
+ combined result this status means that all signatures are
+ invalid.
+
+ ‘GPGME_SIG_STAT_NOKEY’
+ This status indicates that the signature could not be verified
+ due to a missing key. For the combined result this status
+ means that all signatures could not be checked due to missing
+ keys.
+
+ ‘GPGME_SIG_STAT_NOSIG’
+ This status indicates that the signature data provided was not
+ a real signature.
+
+ ‘GPGME_SIG_STAT_ERROR’
+ This status indicates that there was some other error which
+ prevented the signature verification.
+
+ ‘GPGME_SIG_STAT_DIFF’
+ For the combined result this status means that at least two
+ signatures have a different status. You can get each key’s
+ status with ‘gpgme_get_sig_status’.
+
+ -- Function: const char * gpgme_get_sig_status (gpgme_ctx_t CTX,
+ int IDX, gpgme_sig_stat_t *R_STAT, time_t *R_CREATED)
+ The function ‘gpgme_get_sig_status’ is equivalent to:
+
+ gpgme_verify_result_t result;
+ gpgme_signature_t sig;
+
+ result = gpgme_op_verify_result (ctx);
+ sig = result->signatures;
+
+ while (sig && idx)
+ {
+ sig = sig->next;
+ idx--;
+ }
+ if (!sig || idx)
+ return NULL;
+
+ if (r_stat)
+ {
+ switch (gpg_err_code (sig->status))
+ {
+ case GPG_ERR_NO_ERROR:
+ *r_stat = GPGME_SIG_STAT_GOOD;
+ break;
+
+ case GPG_ERR_BAD_SIGNATURE:
+ *r_stat = GPGME_SIG_STAT_BAD;
+ break;
+
+ case GPG_ERR_NO_PUBKEY:
+ *r_stat = GPGME_SIG_STAT_NOKEY;
+ break;
+
+ case GPG_ERR_NO_DATA:
+ *r_stat = GPGME_SIG_STAT_NOSIG;
+ break;
+
+ case GPG_ERR_SIG_EXPIRED:
+ *r_stat = GPGME_SIG_STAT_GOOD_EXP;
+ break;
+
+ case GPG_ERR_KEY_EXPIRED:
+ *r_stat = GPGME_SIG_STAT_GOOD_EXPKEY;
+ break;
+
+ default:
+ *r_stat = GPGME_SIG_STAT_ERROR;
+ break;
+ }
+ }
+ if (r_created)
+ *r_created = sig->timestamp;
+ return sig->fpr;
+
+ -- Function: const char * gpgme_get_sig_string_attr (gpgme_ctx_t CTX,
+ int IDX, gpgme_attr_t WHAT, int WHATIDX)
+ The function ‘gpgme_get_sig_string_attr’ is equivalent to:
-If you develop a new library, and you want it to be of the greatest
-possible use to the public, we recommend making it free software that
-everyone can redistribute and change. You can do so by permitting
-redistribution under these terms (or, alternatively, under the terms of
-the ordinary General Public License).
+ gpgme_verify_result_t result;
+ gpgme_signature_t sig;
- To apply these terms, attach the following notices to the library.
-It is safest to attach them to the start of each source file to most
-effectively convey the exclusion of warranty; and each file should have
-at least the “copyright†line and a pointer to where the full notice is
-found.
+ result = gpgme_op_verify_result (ctx);
+ sig = result->signatures;
- ONE LINE TO GIVE THE LIBRARY'S NAME AND AN IDEA OF WHAT IT DOES.
- Copyright (C) YEAR NAME OF AUTHOR
+ while (sig && idx)
+ {
+ sig = sig->next;
+ idx--;
+ }
+ if (!sig || idx)
+ return NULL;
- This library is free software; you can redistribute it and/or modify it
- under the terms of the GNU Lesser General Public License as published by
- the Free Software Foundation; either version 2.1 of the License, or (at
- your option) any later version.
+ switch (what)
+ {
+ case GPGME_ATTR_FPR:
+ return sig->fpr;
- This library is distributed in the hope that it will be useful, but
- WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- Lesser General Public License for more details.
+ case GPGME_ATTR_ERRTOK:
+ if (whatidx == 1)
+ return sig->wrong_key_usage ? "Wrong_Key_Usage" : "";
+ else
+ return "";
+ default:
+ break;
+ }
- You should have received a copy of the GNU Lesser General Public
- License along with this library; if not, write to the Free Software
- Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307,
- USA.
+ return NULL;
- Also add information on how to contact you by electronic and paper
-mail.
+ -- Function: const char * gpgme_get_sig_ulong_attr (gpgme_ctx_t CTX,
+ int IDX, gpgme_attr_t WAHT, int WHATIDX)
+ The function ‘gpgme_get_sig_ulong_attr’ is equivalent to:
- You should also get your employer (if you work as a programmer) or
-your school, if any, to sign a “copyright disclaimer†for the library,
-if necessary. Here is a sample; alter the names:
+ gpgme_verify_result_t result;
+ gpgme_signature_t sig;
- Yoyodyne, Inc., hereby disclaims all copyright interest in the library
- `Frob' (a library for tweaking knobs) written by James Random Hacker.
+ result = gpgme_op_verify_result (ctx);
+ sig = result->signatures;
- SIGNATURE OF TY COON, 1 April 1990
- Ty Coon, President of Vice
+ while (sig && idx)
+ {
+ sig = sig->next;
+ idx--;
+ }
+ if (!sig || idx)
+ return 0;
- That’s all there is to it!
+ switch (what)
+ {
+ case GPGME_ATTR_CREATED:
+ return sig->timestamp;
+
+ case GPGME_ATTR_EXPIRE:
+ return sig->exp_timestamp;
+
+ case GPGME_ATTR_VALIDITY:
+ return (unsigned long) sig->validity;
+
+ case GPGME_ATTR_SIG_STATUS:
+ switch (sig->status)
+ {
+ case GPG_ERR_NO_ERROR:
+ return GPGME_SIG_STAT_GOOD;
+
+ case GPG_ERR_BAD_SIGNATURE:
+ return GPGME_SIG_STAT_BAD;
+
+ case GPG_ERR_NO_PUBKEY:
+ return GPGME_SIG_STAT_NOKEY;
+
+ case GPG_ERR_NO_DATA:
+ return GPGME_SIG_STAT_NOSIG;
+
+ case GPG_ERR_SIG_EXPIRED:
+ return GPGME_SIG_STAT_GOOD_EXP;
+
+ case GPG_ERR_KEY_EXPIRED:
+ return GPGME_SIG_STAT_GOOD_EXPKEY;
+
+ default:
+ return GPGME_SIG_STAT_ERROR;
+ }
+
+ case GPGME_ATTR_SIG_SUMMARY:
+ return sig->summary;
+
+ default:
+ break;
+ }
+ return 0;
+
+ -- Function: const char * gpgme_get_sig_key (gpgme_ctx_t CTX, int IDX,
+ gpgme_key_t *R_KEY)
+ The function ‘gpgme_get_sig_key’ is equivalent to:
+
+ gpgme_verify_result_t result;
+ gpgme_signature_t sig;
+
+ result = gpgme_op_verify_result (ctx);
+ sig = result->signatures;
+
+ while (sig && idx)
+ {
+ sig = sig->next;
+ idx--;
+ }
+ if (!sig || idx)
+ return gpg_error (GPG_ERR_EOF);
+
+ return gpgme_get_key (ctx, sig->fpr, r_key, 0);
diff --git a/doc/gpgme.info-2 b/doc/gpgme.info-2
index 8c01702..1fdd935 100644
--- a/doc/gpgme.info-2
+++ b/doc/gpgme.info-2
@@ -1,7 +1,6 @@
This is gpgme.info, produced by makeinfo version 5.2 from gpgme.texi.
-Copyright © 2002, 2003, 2004, 2005, 2006, 2007, 2008, 2010, 2012, 2013,
-2014 g10 Code GmbH.
+Copyright © 2002–2008, 2010, 2012–2016 g10 Code GmbH.
Permission is granted to copy, distribute and/or modify this
document under the terms of the GNU General Public License as
@@ -20,11 +19,10 @@ END-INFO-DIR-ENTRY
This file documents the GPGME library.
- This is Edition 1.6.0, last updated 26 August 2015, of ‘The ‘GnuPG
-Made Easy’ Reference Manual’, for Version 1.6.0.
+ This is Edition 1.7.0-beta361, last updated 26 August 2015, of ‘The
+‘GnuPG Made Easy’ Reference Manual’, for Version 1.7.0-beta361.
- Copyright © 2002, 2003, 2004, 2005, 2006, 2007, 2008, 2010, 2012,
-2013, 2014 g10 Code GmbH.
+ Copyright © 2002–2008, 2010, 2012–2016 g10 Code GmbH.
Permission is granted to copy, distribute and/or modify this
document under the terms of the GNU General Public License as
@@ -38,6 +36,530 @@ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General
Public License for more details.

+File: gpgme.info, Node: Library Copying, Next: Copying, Prev: Deprecated Functions, Up: Top
+
+GNU Lesser General Public License
+*********************************
+
+ Version 2.1, February 1999
+
+ Copyright © 1991, 1999 Free Software Foundation, Inc.
+ 59 Temple Place – Suite 330, Boston, MA 02111-1307, USA
+
+ Everyone is permitted to copy and distribute verbatim copies
+ of this license document, but changing it is not allowed.
+
+ [This is the first released version of the Lesser GPL. It also counts
+ as the successor of the GNU Library Public License, version 2, hence the
+ version number 2.1.]
+
+Preamble
+========
+
+The licenses for most software are designed to take away your freedom to
+share and change it. By contrast, the GNU General Public Licenses are
+intended to guarantee your freedom to share and change free software—to
+make sure the software is free for all its users.
+
+ This license, the Lesser General Public License, applies to some
+specially designated software—typically libraries—of the Free Software
+Foundation and other authors who decide to use it. You can use it too,
+but we suggest you first think carefully about whether this license or
+the ordinary General Public License is the better strategy to use in any
+particular case, based on the explanations below.
+
+ When we speak of free software, we are referring to freedom of use,
+not price. Our General Public Licenses are designed to make sure that
+you have the freedom to distribute copies of free software (and charge
+for this service if you wish); that you receive source code or can get
+it if you want it; that you can change the software and use pieces of it
+in new free programs; and that you are informed that you can do these
+things.
+
+ To protect your rights, we need to make restrictions that forbid
+distributors to deny you these rights or to ask you to surrender these
+rights. These restrictions translate to certain responsibilities for
+you if you distribute copies of the library or if you modify it.
+
+ For example, if you distribute copies of the library, whether gratis
+or for a fee, you must give the recipients all the rights that we gave
+you. You must make sure that they, too, receive or can get the source
+code. If you link other code with the library, you must provide
+complete object files to the recipients, so that they can relink them
+with the library after making changes to the library and recompiling it.
+And you must show them these terms so they know their rights.
+
+ We protect your rights with a two-step method: (1) we copyright the
+library, and (2) we offer you this license, which gives you legal
+permission to copy, distribute and/or modify the library.
+
+ To protect each distributor, we want to make it very clear that there
+is no warranty for the free library. Also, if the library is modified
+by someone else and passed on, the recipients should know that what they
+have is not the original version, so that the original author’s
+reputation will not be affected by problems that might be introduced by
+others.
+
+ Finally, software patents pose a constant threat to the existence of
+any free program. We wish to make sure that a company cannot
+effectively restrict the users of a free program by obtaining a
+restrictive license from a patent holder. Therefore, we insist that any
+patent license obtained for a version of the library must be consistent
+with the full freedom of use specified in this license.
+
+ Most GNU software, including some libraries, is covered by the
+ordinary GNU General Public License. This license, the GNU Lesser
+General Public License, applies to certain designated libraries, and is
+quite different from the ordinary General Public License. We use this
+license for certain libraries in order to permit linking those libraries
+into non-free programs.
+
+ When a program is linked with a library, whether statically or using
+a shared library, the combination of the two is legally speaking a
+combined work, a derivative of the original library. The ordinary
+General Public License therefore permits such linking only if the entire
+combination fits its criteria of freedom. The Lesser General Public
+License permits more lax criteria for linking other code with the
+library.
+
+ We call this license the "Lesser" General Public License because it
+does _Less_ to protect the user’s freedom than the ordinary General
+Public License. It also provides other free software developers Less of
+an advantage over competing non-free programs. These disadvantages are
+the reason we use the ordinary General Public License for many
+libraries. However, the Lesser license provides advantages in certain
+special circumstances.
+
+ For example, on rare occasions, there may be a special need to
+encourage the widest possible use of a certain library, so that it
+becomes a de-facto standard. To achieve this, non-free programs must be
+allowed to use the library. A more frequent case is that a free library
+does the same job as widely used non-free libraries. In this case,
+there is little to gain by limiting the free library to free software
+only, so we use the Lesser General Public License.
+
+ In other cases, permission to use a particular library in non-free
+programs enables a greater number of people to use a large body of free
+software. For example, permission to use the GNU C Library in non-free
+programs enables many more people to use the whole GNU operating system,
+as well as its variant, the GNU/Linux operating system.
+
+ Although the Lesser General Public License is Less protective of the
+users’ freedom, it does ensure that the user of a program that is linked
+with the Library has the freedom and the wherewithal to run that program
+using a modified version of the Library.
+
+ The precise terms and conditions for copying, distribution and
+modification follow. Pay close attention to the difference between a
+“work based on the library†and a “work that uses the libraryâ€. The
+former contains code derived from the library, whereas the latter must
+be combined with the library in order to run.
+
+ GNU LESSER GENERAL PUBLIC LICENSE
+ TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION
+
+ 0. This License Agreement applies to any software library or other
+ program which contains a notice placed by the copyright holder or
+ other authorized party saying it may be distributed under the terms
+ of this Lesser General Public License (also called “this Licenseâ€).
+ Each licensee is addressed as “youâ€.
+
+ A “library†means a collection of software functions and/or data
+ prepared so as to be conveniently linked with application programs
+ (which use some of those functions and data) to form executables.
+
+ The “Libraryâ€, below, refers to any such software library or work
+ which has been distributed under these terms. A “work based on the
+ Library†means either the Library or any derivative work under
+ copyright law: that is to say, a work containing the Library or a
+ portion of it, either verbatim or with modifications and/or
+ translated straightforwardly into another language. (Hereinafter,
+ translation is included without limitation in the term
+ “modificationâ€.)
+
+ “Source code†for a work means the preferred form of the work for
+ making modifications to it. For a library, complete source code
+ means all the source code for all modules it contains, plus any
+ associated interface definition files, plus the scripts used to
+ control compilation and installation of the library.
+
+ Activities other than copying, distribution and modification are
+ not covered by this License; they are outside its scope. The act
+ of running a program using the Library is not restricted, and
+ output from such a program is covered only if its contents
+ constitute a work based on the Library (independent of the use of
+ the Library in a tool for writing it). Whether that is true
+ depends on what the Library does and what the program that uses the
+ Library does.
+
+ 1. You may copy and distribute verbatim copies of the Library’s
+ complete source code as you receive it, in any medium, provided
+ that you conspicuously and appropriately publish on each copy an
+ appropriate copyright notice and disclaimer of warranty; keep
+ intact all the notices that refer to this License and to the
+ absence of any warranty; and distribute a copy of this License
+ along with the Library.
+
+ You may charge a fee for the physical act of transferring a copy,
+ and you may at your option offer warranty protection in exchange
+ for a fee.
+
+ 2. You may modify your copy or copies of the Library or any portion of
+ it, thus forming a work based on the Library, and copy and
+ distribute such modifications or work under the terms of Section 1
+ above, provided that you also meet all of these conditions:
+
+ a. The modified work must itself be a software library.
+
+ b. You must cause the files modified to carry prominent notices
+ stating that you changed the files and the date of any change.
+
+ c. You must cause the whole of the work to be licensed at no
+ charge to all third parties under the terms of this License.
+
+ d. If a facility in the modified Library refers to a function or
+ a table of data to be supplied by an application program that
+ uses the facility, other than as an argument passed when the
+ facility is invoked, then you must make a good faith effort to
+ ensure that, in the event an application does not supply such
+ function or table, the facility still operates, and performs
+ whatever part of its purpose remains meaningful.
+
+ (For example, a function in a library to compute square roots
+ has a purpose that is entirely well-defined independent of the
+ application. Therefore, Subsection 2d requires that any
+ application-supplied function or table used by this function
+ must be optional: if the application does not supply it, the
+ square root function must still compute square roots.)
+
+ These requirements apply to the modified work as a whole. If
+ identifiable sections of that work are not derived from the
+ Library, and can be reasonably considered independent and separate
+ works in themselves, then this License, and its terms, do not apply
+ to those sections when you distribute them as separate works. But
+ when you distribute the same sections as part of a whole which is a
+ work based on the Library, the distribution of the whole must be on
+ the terms of this License, whose permissions for other licensees
+ extend to the entire whole, and thus to each and every part
+ regardless of who wrote it.
+
+ Thus, it is not the intent of this section to claim rights or
+ contest your rights to work written entirely by you; rather, the
+ intent is to exercise the right to control the distribution of
+ derivative or collective works based on the Library.
+
+ In addition, mere aggregation of another work not based on the
+ Library with the Library (or with a work based on the Library) on a
+ volume of a storage or distribution medium does not bring the other
+ work under the scope of this License.
+
+ 3. You may opt to apply the terms of the ordinary GNU General Public
+ License instead of this License to a given copy of the Library. To
+ do this, you must alter all the notices that refer to this License,
+ so that they refer to the ordinary GNU General Public License,
+ version 2, instead of to this License. (If a newer version than
+ version 2 of the ordinary GNU General Public License has appeared,
+ then you can specify that version instead if you wish.) Do not
+ make any other change in these notices.
+
+ Once this change is made in a given copy, it is irreversible for
+ that copy, so the ordinary GNU General Public License applies to
+ all subsequent copies and derivative works made from that copy.
+
+ This option is useful when you wish to copy part of the code of the
+ Library into a program that is not a library.
+
+ 4. You may copy and distribute the Library (or a portion or derivative
+ of it, under Section 2) in object code or executable form under the
+ terms of Sections 1 and 2 above provided that you accompany it with
+ the complete corresponding machine-readable source code, which must
+ be distributed under the terms of Sections 1 and 2 above on a
+ medium customarily used for software interchange.
+
+ If distribution of object code is made by offering access to copy
+ from a designated place, then offering equivalent access to copy
+ the source code from the same place satisfies the requirement to
+ distribute the source code, even though third parties are not
+ compelled to copy the source along with the object code.
+
+ 5. A program that contains no derivative of any portion of the
+ Library, but is designed to work with the Library by being compiled
+ or linked with it, is called a “work that uses the Libraryâ€. Such
+ a work, in isolation, is not a derivative work of the Library, and
+ therefore falls outside the scope of this License.
+
+ However, linking a “work that uses the Library†with the Library
+ creates an executable that is a derivative of the Library (because
+ it contains portions of the Library), rather than a “work that uses
+ the libraryâ€. The executable is therefore covered by this License.
+ Section 6 states terms for distribution of such executables.
+
+ When a “work that uses the Library†uses material from a header
+ file that is part of the Library, the object code for the work may
+ be a derivative work of the Library even though the source code is
+ not. Whether this is true is especially significant if the work
+ can be linked without the Library, or if the work is itself a
+ library. The threshold for this to be true is not precisely
+ defined by law.
+
+ If such an object file uses only numerical parameters, data
+ structure layouts and accessors, and small macros and small inline
+ functions (ten lines or less in length), then the use of the object
+ file is unrestricted, regardless of whether it is legally a
+ derivative work. (Executables containing this object code plus
+ portions of the Library will still fall under Section 6.)
+
+ Otherwise, if the work is a derivative of the Library, you may
+ distribute the object code for the work under the terms of Section
+ 6. Any executables containing that work also fall under Section 6,
+ whether or not they are linked directly with the Library itself.
+
+ 6. As an exception to the Sections above, you may also combine or link
+ a “work that uses the Library†with the Library to produce a work
+ containing portions of the Library, and distribute that work under
+ terms of your choice, provided that the terms permit modification
+ of the work for the customer’s own use and reverse engineering for
+ debugging such modifications.
+
+ You must give prominent notice with each copy of the work that the
+ Library is used in it and that the Library and its use are covered
+ by this License. You must supply a copy of this License. If the
+ work during execution displays copyright notices, you must include
+ the copyright notice for the Library among them, as well as a
+ reference directing the user to the copy of this License. Also,
+ you must do one of these things:
+
+ a. Accompany the work with the complete corresponding
+ machine-readable source code for the Library including
+ whatever changes were used in the work (which must be
+ distributed under Sections 1 and 2 above); and, if the work is
+ an executable linked with the Library, with the complete
+ machine-readable “work that uses the Libraryâ€, as object code
+ and/or source code, so that the user can modify the Library
+ and then relink to produce a modified executable containing
+ the modified Library. (It is understood that the user who
+ changes the contents of definitions files in the Library will
+ not necessarily be able to recompile the application to use
+ the modified definitions.)
+
+ b. Use a suitable shared library mechanism for linking with the
+ Library. A suitable mechanism is one that (1) uses at run
+ time a copy of the library already present on the user’s
+ computer system, rather than copying library functions into
+ the executable, and (2) will operate properly with a modified
+ version of the library, if the user installs one, as long as
+ the modified version is interface-compatible with the version
+ that the work was made with.
+
+ c. Accompany the work with a written offer, valid for at least
+ three years, to give the same user the materials specified in
+ Subsection 6a, above, for a charge no more than the cost of
+ performing this distribution.
+
+ d. If distribution of the work is made by offering access to copy
+ from a designated place, offer equivalent access to copy the
+ above specified materials from the same place.
+
+ e. Verify that the user has already received a copy of these
+ materials or that you have already sent this user a copy.
+
+ For an executable, the required form of the “work that uses the
+ Library†must include any data and utility programs needed for
+ reproducing the executable from it. However, as a special
+ exception, the materials to be distributed need not include
+ anything that is normally distributed (in either source or binary
+ form) with the major components (compiler, kernel, and so on) of
+ the operating system on which the executable runs, unless that
+ component itself accompanies the executable.
+
+ It may happen that this requirement contradicts the license
+ restrictions of other proprietary libraries that do not normally
+ accompany the operating system. Such a contradiction means you
+ cannot use both them and the Library together in an executable that
+ you distribute.
+
+ 7. You may place library facilities that are a work based on the
+ Library side-by-side in a single library together with other
+ library facilities not covered by this License, and distribute such
+ a combined library, provided that the separate distribution of the
+ work based on the Library and of the other library facilities is
+ otherwise permitted, and provided that you do these two things:
+
+ a. Accompany the combined library with a copy of the same work
+ based on the Library, uncombined with any other library
+ facilities. This must be distributed under the terms of the
+ Sections above.
+
+ b. Give prominent notice with the combined library of the fact
+ that part of it is a work based on the Library, and explaining
+ where to find the accompanying uncombined form of the same
+ work.
+
+ 8. You may not copy, modify, sublicense, link with, or distribute the
+ Library except as expressly provided under this License. Any
+ attempt otherwise to copy, modify, sublicense, link with, or
+ distribute the Library is void, and will automatically terminate
+ your rights under this License. However, parties who have received
+ copies, or rights, from you under this License will not have their
+ licenses terminated so long as such parties remain in full
+ compliance.
+
+ 9. You are not required to accept this License, since you have not
+ signed it. However, nothing else grants you permission to modify
+ or distribute the Library or its derivative works. These actions
+ are prohibited by law if you do not accept this License.
+ Therefore, by modifying or distributing the Library (or any work
+ based on the Library), you indicate your acceptance of this License
+ to do so, and all its terms and conditions for copying,
+ distributing or modifying the Library or works based on it.
+
+ 10. Each time you redistribute the Library (or any work based on the
+ Library), the recipient automatically receives a license from the
+ original licensor to copy, distribute, link with or modify the
+ Library subject to these terms and conditions. You may not impose
+ any further restrictions on the recipients’ exercise of the rights
+ granted herein. You are not responsible for enforcing compliance
+ by third parties with this License.
+
+ 11. If, as a consequence of a court judgment or allegation of patent
+ infringement or for any other reason (not limited to patent
+ issues), conditions are imposed on you (whether by court order,
+ agreement or otherwise) that contradict the conditions of this
+ License, they do not excuse you from the conditions of this
+ License. If you cannot distribute so as to satisfy simultaneously
+ your obligations under this License and any other pertinent
+ obligations, then as a consequence you may not distribute the
+ Library at all. For example, if a patent license would not permit
+ royalty-free redistribution of the Library by all those who receive
+ copies directly or indirectly through you, then the only way you
+ could satisfy both it and this License would be to refrain entirely
+ from distribution of the Library.
+
+ If any portion of this section is held invalid or unenforceable
+ under any particular circumstance, the balance of the section is
+ intended to apply, and the section as a whole is intended to apply
+ in other circumstances.
+
+ It is not the purpose of this section to induce you to infringe any
+ patents or other property right claims or to contest validity of
+ any such claims; this section has the sole purpose of protecting
+ the integrity of the free software distribution system which is
+ implemented by public license practices. Many people have made
+ generous contributions to the wide range of software distributed
+ through that system in reliance on consistent application of that
+ system; it is up to the author/donor to decide if he or she is
+ willing to distribute software through any other system and a
+ licensee cannot impose that choice.
+
+ This section is intended to make thoroughly clear what is believed
+ to be a consequence of the rest of this License.
+
+ 12. If the distribution and/or use of the Library is restricted in
+ certain countries either by patents or by copyrighted interfaces,
+ the original copyright holder who places the Library under this
+ License may add an explicit geographical distribution limitation
+ excluding those countries, so that distribution is permitted only
+ in or among countries not thus excluded. In such case, this
+ License incorporates the limitation as if written in the body of
+ this License.
+
+ 13. The Free Software Foundation may publish revised and/or new
+ versions of the Lesser General Public License from time to time.
+ Such new versions will be similar in spirit to the present version,
+ but may differ in detail to address new problems or concerns.
+
+ Each version is given a distinguishing version number. If the
+ Library specifies a version number of this License which applies to
+ it and “any later versionâ€, you have the option of following the
+ terms and conditions either of that version or of any later version
+ published by the Free Software Foundation. If the Library does not
+ specify a license version number, you may choose any version ever
+ published by the Free Software Foundation.
+
+ 14. If you wish to incorporate parts of the Library into other free
+ programs whose distribution conditions are incompatible with these,
+ write to the author to ask for permission. For software which is
+ copyrighted by the Free Software Foundation, write to the Free
+ Software Foundation; we sometimes make exceptions for this. Our
+ decision will be guided by the two goals of preserving the free
+ status of all derivatives of our free software and of promoting the
+ sharing and reuse of software generally.
+
+ NO WARRANTY
+
+ 15. BECAUSE THE LIBRARY IS LICENSED FREE OF CHARGE, THERE IS NO
+ WARRANTY FOR THE LIBRARY, TO THE EXTENT PERMITTED BY APPLICABLE
+ LAW. EXCEPT WHEN OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS
+ AND/OR OTHER PARTIES PROVIDE THE LIBRARY “AS IS†WITHOUT WARRANTY
+ OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, BUT NOT
+ LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
+ FOR A PARTICULAR PURPOSE. THE ENTIRE RISK AS TO THE QUALITY AND
+ PERFORMANCE OF THE LIBRARY IS WITH YOU. SHOULD THE LIBRARY PROVE
+ DEFECTIVE, YOU ASSUME THE COST OF ALL NECESSARY SERVICING, REPAIR
+ OR CORRECTION.
+
+ 16. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN
+ WRITING WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY
+ MODIFY AND/OR REDISTRIBUTE THE LIBRARY AS PERMITTED ABOVE, BE
+ LIABLE TO YOU FOR DAMAGES, INCLUDING ANY GENERAL, SPECIAL,
+ INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING OUT OF THE USE OR
+ INABILITY TO USE THE LIBRARY (INCLUDING BUT NOT LIMITED TO LOSS OF
+ DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY YOU
+ OR THIRD PARTIES OR A FAILURE OF THE LIBRARY TO OPERATE WITH ANY
+ OTHER SOFTWARE), EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN
+ ADVISED OF THE POSSIBILITY OF SUCH DAMAGES.
+
+ END OF TERMS AND CONDITIONS
+
+How to Apply These Terms to Your New Libraries
+==============================================
+
+If you develop a new library, and you want it to be of the greatest
+possible use to the public, we recommend making it free software that
+everyone can redistribute and change. You can do so by permitting
+redistribution under these terms (or, alternatively, under the terms of
+the ordinary General Public License).
+
+ To apply these terms, attach the following notices to the library.
+It is safest to attach them to the start of each source file to most
+effectively convey the exclusion of warranty; and each file should have
+at least the “copyright†line and a pointer to where the full notice is
+found.
+
+ ONE LINE TO GIVE THE LIBRARY'S NAME AND AN IDEA OF WHAT IT DOES.
+ Copyright (C) YEAR NAME OF AUTHOR
+
+ This library is free software; you can redistribute it and/or modify it
+ under the terms of the GNU Lesser General Public License as published by
+ the Free Software Foundation; either version 2.1 of the License, or (at
+ your option) any later version.
+
+ This library is distributed in the hope that it will be useful, but
+ WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Lesser General Public License for more details.
+
+ You should have received a copy of the GNU Lesser General Public
+ License along with this library; if not, write to the Free Software
+ Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307,
+ USA.
+
+ Also add information on how to contact you by electronic and paper
+mail.
+
+ You should also get your employer (if you work as a programmer) or
+your school, if any, to sign a “copyright disclaimer†for the library,
+if necessary. Here is a sample; alter the names:
+
+ Yoyodyne, Inc., hereby disclaims all copyright interest in the library
+ `Frob' (a library for tweaking knobs) written by James Random Hacker.
+
+ SIGNATURE OF TY COON, 1 April 1990
+ Ty Coon, President of Vice
+
+ That’s all there is to it!
+
+
File: gpgme.info, Node: Copying, Next: Concept Index, Prev: Library Copying, Up: Top
GNU General Public License
@@ -767,10 +1289,9 @@ Concept Index
* algorithms, public key: Public Key Algorithms. (line 6)
* armor mode: ASCII Armor. (line 6)
* ASCII armor: ASCII Armor. (line 6)
+* ASSUAN: Assuan. (line 6)
* attributes, of a key: Information About Keys.
(line 6)
-* attributes, of a trust item: Information About Trust Items.
- (line 6)
* autoconf: Using Automake. (line 6)
* automake: Using Automake. (line 6)
* backend: Protocols and Engines. (line 6)
@@ -794,6 +1315,7 @@ Concept Index
* context, creation: Creating Contexts. (line 6)
* context, destruction: Destroying Contexts. (line 6)
* context, offline mode: Offline Mode. (line 6)
+* context, pinentry mode: Pinentry Mode. (line 6)
* context, result of operation: Result Management. (line 6)
* context, selecting protocol: Protocol Selection. (line 6)
* context, text mode: Text Mode. (line 6)
@@ -836,8 +1358,10 @@ Concept Index
* debug: Debugging. (line 6)
* decryption: Decrypt. (line 6)
* decryption and verification: Decrypt and Verify. (line 6)
+* deprecated: Deprecated Functions. (line 6)
* encryption: Encrypt. (line 6)
* engine: Protocols and Engines. (line 6)
+* engine, ASSUAN: Assuan. (line 6)
* engine, configuration of: Engine Configuration. (line 6)
* engine, configuration per context: Crypto Engine. (line 6)
* engine, GnuPG: OpenPGP. (line 6)
@@ -890,7 +1414,7 @@ Concept Index
* key, information about: Information About Keys.
(line 6)
* key, manipulation: Manipulating Keys. (line 6)
-* key, signatures: Key Signatures. (line 6)
+* key, signing: Signing Keys. (line 6)
* largefile support: Largefile Support (LFS).
(line 6)
* LFS: Largefile Support (LFS).
@@ -909,11 +1433,13 @@ Concept Index
* OpenPGP: OpenPGP. (line 6)
* passphrase callback: Passphrase Callback. (line 6)
* passphrase, change: Changing Passphrases. (line 6)
+* pinentry mode: Pinentry Mode. (line 6)
* policy URL: Signature Notation Data.
(line 6)
* progress meter callback: Progress Meter Callback.
(line 6)
* protocol: Protocols and Engines. (line 6)
+* protocol, ASSUAN: Assuan. (line 6)
* protocol, CMS: Cryptographic Message Syntax.
(line 6)
* protocol, GnuPG: OpenPGP. (line 6)
@@ -936,7 +1462,6 @@ Concept Index
* signature, creation: Sign. (line 6)
* signature, selecting signers: Selecting Signers. (line 6)
* signature, verification: Verify. (line 6)
-* signatures, on a key: Key Signatures. (line 6)
* signers, selecting: Selecting Signers. (line 6)
* status message callback: Status Message Callback.
(line 6)
@@ -944,16 +1469,13 @@ Concept Index
* thread-safeness: Multi Threading. (line 6)
* trust item: Trust Item Management. (line 6)
* trust item list: Listing Trust Items. (line 6)
-* trust item, attributes: Information About Trust Items.
- (line 6)
-* trust item, information about: Information About Trust Items.
- (line 6)
* trust item, manipulation: Manipulating Trust Items.
(line 6)
* type of data: Data Buffer Convenience.
(line 6)
* UI server: UI Server Protocol. (line 6)
* user interface server: UI Server Protocol. (line 6)
+* validity, TOFU: Changing TOFU Data. (line 6)
* verification: Verify. (line 6)
* verification and decryption: Decrypt and Verify. (line 6)
* version check, of the engines: Engine Version Check. (line 6)
@@ -994,22 +1516,26 @@ Function and Data Index
* enum gpgme_event_io_t: I/O Callback Interface.
(line 58)
* enum gpgme_hash_algo_t: Hash Algorithms. (line 9)
+* enum gpgme_pinentry_mode_t: Pinentry Mode. (line 19)
* enum gpgme_protocol_t: Protocols and Engines.
(line 16)
* enum gpgme_pubkey_algo_t: Public Key Algorithms.
(line 9)
* enum gpgme_sig_mode_t: Creating a Signature.
(line 6)
-* enum gpgme_sig_stat_t: Verify. (line 273)
+* enum gpgme_sig_stat_t: Deprecated Functions.
+ (line 427)
+* enum gpgme_tofu_policy_t: Changing TOFU Data. (line 10)
* FILE: UI Server Set Input Files.
(line 9)
* GETINFO: Miscellaneous UI Server Commands.
(line 9)
-* gpgme_attr_t: Information About Keys.
- (line 41)
-* gpgme_attr_t <1>: Key Signatures. (line 19)
+* gpgme_attr_t: Deprecated Functions.
+ (line 136)
+* gpgme_attr_t <1>: Deprecated Functions.
+ (line 313)
* gpgme_cancel: Cancellation. (line 16)
-* gpgme_cancel_async: Cancellation. (line 37)
+* gpgme_cancel_async: Cancellation. (line 36)
* gpgme_check_version: Library Version Check.
(line 6)
* gpgme_ctx_get_engine_info: Crypto Engine. (line 12)
@@ -1018,7 +1544,7 @@ Function and Data Index
* gpgme_data_encoding_t: Data Buffer Meta-Data.
(line 28)
* gpgme_data_get_encoding: Data Buffer Meta-Data.
- (line 66)
+ (line 69)
* gpgme_data_get_file_name: Data Buffer Meta-Data.
(line 6)
* gpgme_data_identify: Data Buffer Convenience.
@@ -1037,8 +1563,8 @@ Function and Data Index
(line 22)
* gpgme_data_new_from_stream: File Based Data Buffers.
(line 29)
-* gpgme_data_new_with_read_cb: Callback Based Data Buffers.
- (line 98)
+* gpgme_data_new_with_read_cb: Deprecated Functions.
+ (line 107)
* gpgme_data_read: Data Buffer I/O Operations.
(line 6)
* gpgme_data_read_cb_t: Callback Based Data Buffers.
@@ -1049,16 +1575,18 @@ Function and Data Index
(line 11)
* gpgme_data_release_cb_t: Callback Based Data Buffers.
(line 56)
-* gpgme_data_rewind: Data Buffer I/O Operations.
- (line 60)
+* gpgme_data_rewind: Deprecated Functions.
+ (line 130)
* gpgme_data_seek: Data Buffer I/O Operations.
(line 25)
* gpgme_data_seek_cb_t: Callback Based Data Buffers.
(line 47)
* gpgme_data_set_encoding: Data Buffer Meta-Data.
- (line 72)
+ (line 75)
* gpgme_data_set_file_name: Data Buffer Meta-Data.
(line 16)
+* gpgme_data_set_flag: Data Buffer Meta-Data.
+ (line 80)
* gpgme_data_t: Exchanging Data. (line 13)
* gpgme_data_type_t: Data Buffer Convenience.
(line 7)
@@ -1067,17 +1595,25 @@ Function and Data Index
* gpgme_data_write_cb_t: Callback Based Data Buffers.
(line 30)
* gpgme_decrypt_result_t: Decrypt. (line 54)
-* gpgme_edit_cb_t: Advanced Key Editing.
- (line 9)
+* gpgme_edit_cb_t: Deprecated Functions.
+ (line 36)
* gpgme_encrypt_result_t: Encrypting a Plaintext.
- (line 87)
+ (line 93)
* gpgme_engine_check_version: Engine Version Check.
- (line 35)
+ (line 62)
* gpgme_engine_info_t: Engine Information. (line 6)
* gpgme_error: Error Values. (line 65)
* gpgme_error_from_errno: Error Values. (line 88)
* gpgme_error_t: Error Values. (line 24)
-* gpgme_error_t (*gpgme_edit_cb_t) (void *HANDLE, gpgme_status_code_t STATUS, const char *ARGS, int FD): Advanced Key Editing.
+* gpgme_error_t (*gpgme_assuan_data_cb_t) (void *OPAQUE, const void *DATA, size_t DATALEN): Using the Assuan protocol.
+ (line 15)
+* gpgme_error_t (*gpgme_assuan_inquire_cb_t) (void *OPAQUE, const char *NAME, const char *ARGS, gpgme_data_t *R_DATA): Using the Assuan protocol.
+ (line 23)
+* gpgme_error_t (*gpgme_assuan_status_cb_t) (void *OPAQUE, const char *STATUS, const char *ARGS): Using the Assuan protocol.
+ (line 35)
+* gpgme_error_t (*gpgme_edit_cb_t) (void *HANDLE, gpgme_status_code_t STATUS, const char *ARGS, int FD): Deprecated Functions.
+ (line 33)
+* gpgme_error_t (*gpgme_interact_cb_t) (void *HANDLE, const char *STATUS, const char *ARGS, int FD): Advanced Key Editing.
(line 6)
* gpgme_error_t (*gpgme_io_cb_t) (void *DATA, int FD): I/O Callback Interface.
(line 6)
@@ -1101,7 +1637,7 @@ Function and Data Index
(line 7)
* gpgme_free: Destroying Data Buffers.
(line 25)
-* gpgme_genkey_result_t: Generating Keys. (line 74)
+* gpgme_genkey_result_t: Generating Keys. (line 295)
* gpgme_get_armor: ASCII Armor. (line 13)
* gpgme_get_dirinfo: Engine Version Check.
(line 6)
@@ -1111,48 +1647,68 @@ Function and Data Index
* gpgme_get_io_cbs: Registering I/O Callbacks.
(line 44)
* gpgme_get_key: Listing Keys. (line 147)
-* gpgme_get_keylist_mode: Key Listing Mode. (line 68)
+* gpgme_get_keylist_mode: Key Listing Mode. (line 73)
* gpgme_get_offline: Offline Mode. (line 23)
-* gpgme_get_passphrase_cb: Passphrase Callback. (line 55)
+* gpgme_get_passphrase_cb: Passphrase Callback. (line 59)
+* gpgme_get_pinentry_mode: Pinentry Mode. (line 14)
* gpgme_get_progress_cb: Progress Meter Callback.
(line 31)
* gpgme_get_protocol: Protocol Selection. (line 21)
* gpgme_get_protocol_name: Protocols and Engines.
- (line 48)
-* gpgme_get_sig_key: Verify. (line 472)
-* gpgme_get_sig_status: Verify. (line 321)
-* gpgme_get_sig_string_attr: Verify. (line 376)
-* gpgme_get_sig_ulong_attr: Verify. (line 410)
+ (line 51)
+* gpgme_get_sig_key: Deprecated Functions.
+ (line 626)
+* gpgme_get_sig_status: Deprecated Functions.
+ (line 475)
+* gpgme_get_sig_string_attr: Deprecated Functions.
+ (line 530)
+* gpgme_get_sig_ulong_attr: Deprecated Functions.
+ (line 564)
* gpgme_get_status_cb: Status Message Callback.
(line 29)
* gpgme_get_textmode: Text Mode. (line 20)
* gpgme_hash_algo_name: Hash Algorithms. (line 28)
* gpgme_hash_algo_t: Hash Algorithms. (line 10)
-* gpgme_import_result_t: Importing Keys. (line 111)
-* gpgme_import_status_t: Importing Keys. (line 73)
+* gpgme_import_result_t: Importing Keys. (line 110)
+* gpgme_import_status_t: Importing Keys. (line 72)
+* gpgme_interact_cb_t: Advanced Key Editing.
+ (line 9)
* gpgme_invalid_key_t: Crypto Operations. (line 10)
* gpgme_io_cb_t: I/O Callback Interface.
(line 7)
* gpgme_keylist_result_t: Listing Keys. (line 124)
-* gpgme_key_get_string_attr: Information About Keys.
- (line 183)
-* gpgme_key_get_ulong_attr: Information About Keys.
- (line 197)
+* gpgme_key_get_string_attr: Deprecated Functions.
+ (line 278)
+* gpgme_key_get_ulong_attr: Deprecated Functions.
+ (line 292)
* gpgme_key_ref: Manipulating Keys. (line 6)
-* gpgme_key_release: Manipulating Keys. (line 19)
-* gpgme_key_sig_get_string_attr: Key Signatures. (line 75)
-* gpgme_key_sig_get_ulong_attr: Key Signatures. (line 89)
-* gpgme_key_sig_t: Key Management. (line 92)
-* gpgme_key_t: Key Management. (line 200)
+* gpgme_key_release: Deprecated Functions.
+ (line 14)
+* gpgme_key_sig_get_string_attr: Deprecated Functions.
+ (line 369)
+* gpgme_key_sig_get_ulong_attr: Deprecated Functions.
+ (line 383)
+* gpgme_key_sig_t: Key objects. (line 226)
+* gpgme_key_t: Key objects. (line 10)
* gpgme_key_unref: Manipulating Keys. (line 10)
* gpgme_new: Creating Contexts. (line 6)
* gpgme_new_signature_t: Creating a Signature.
(line 57)
* gpgme_off_t: Exchanging Data. (line 24)
-* gpgme_op_card_edit: Advanced Key Editing.
- (line 48)
-* gpgme_op_card_edit_start: Advanced Key Editing.
- (line 55)
+* gpgme_op_adduid: Generating Keys. (line 161)
+* gpgme_op_adduid_start: Generating Keys. (line 185)
+* gpgme_op_assuan_transact_ext: Using the Assuan protocol.
+ (line 56)
+* gpgme_op_assuan_transact_start: Using the Assuan protocol.
+ (line 43)
+* gpgme_op_card_edit: Deprecated Functions.
+ (line 82)
+* gpgme_op_card_edit_start: Deprecated Functions.
+ (line 92)
+* gpgme_op_createkey: Generating Keys. (line 14)
+* gpgme_op_createkey_start: Generating Keys. (line 99)
+* gpgme_op_createsubkey: Generating Keys. (line 109)
+* gpgme_op_createsubkey_start: Generating Keys. (line 151)
* gpgme_op_decrypt: Decrypt. (line 6)
* gpgme_op_decrypt_result: Decrypt. (line 76)
* gpgme_op_decrypt_start: Decrypt. (line 20)
@@ -1160,44 +1716,53 @@ Function and Data Index
* gpgme_op_decrypt_verify <1>: Decrypt and Verify. (line 30)
* gpgme_op_delete: Deleting Keys. (line 6)
* gpgme_op_delete_start: Deleting Keys. (line 20)
-* gpgme_op_edit: Advanced Key Editing.
- (line 19)
-* gpgme_op_edit_start: Advanced Key Editing.
- (line 37)
+* gpgme_op_edit: Deprecated Functions.
+ (line 47)
+* gpgme_op_edit_start: Deprecated Functions.
+ (line 68)
* gpgme_op_encrypt: Encrypting a Plaintext.
(line 6)
* gpgme_op_encrypt_result: Encrypting a Plaintext.
- (line 98)
+ (line 104)
* gpgme_op_encrypt_sign: Encrypting a Plaintext.
- (line 109)
+ (line 115)
* gpgme_op_encrypt_sign_start: Encrypting a Plaintext.
- (line 119)
+ (line 125)
* gpgme_op_encrypt_start: Encrypting a Plaintext.
- (line 70)
+ (line 76)
* gpgme_op_export: Exporting Keys. (line 38)
* gpgme_op_export_ext: Exporting Keys. (line 69)
* gpgme_op_export_ext_start: Exporting Keys. (line 90)
* gpgme_op_export_keys: Exporting Keys. (line 101)
* gpgme_op_export_keys_start: Exporting Keys. (line 124)
* gpgme_op_export_start: Exporting Keys. (line 58)
-* gpgme_op_genkey: Generating Keys. (line 6)
-* gpgme_op_genkey_result: Generating Keys. (line 95)
-* gpgme_op_genkey_start: Generating Keys. (line 63)
+* gpgme_op_genkey: Generating Keys. (line 225)
+* gpgme_op_genkey_result: Generating Keys. (line 328)
+* gpgme_op_genkey_start: Generating Keys. (line 283)
* gpgme_op_import: Importing Keys. (line 9)
-* gpgme_op_import_ext: Importing Keys. (line 175)
+* gpgme_op_import_ext: Deprecated Functions.
+ (line 22)
* gpgme_op_import_keys: Importing Keys. (line 35)
-* gpgme_op_import_keys_start: Importing Keys. (line 60)
-* gpgme_op_import_result: Importing Keys. (line 161)
+* gpgme_op_import_keys_start: Importing Keys. (line 59)
+* gpgme_op_import_result: Importing Keys. (line 160)
* gpgme_op_import_start: Importing Keys. (line 24)
+* gpgme_op_interact: Advanced Key Editing.
+ (line 21)
+* gpgme_op_interact_start: Advanced Key Editing.
+ (line 46)
* gpgme_op_keylist_end: Listing Keys. (line 81)
* gpgme_op_keylist_ext_start: Listing Keys. (line 33)
* gpgme_op_keylist_next: Listing Keys. (line 65)
* gpgme_op_keylist_result: Listing Keys. (line 135)
* gpgme_op_keylist_start: Listing Keys. (line 6)
+* gpgme_op_keysign: Signing Keys. (line 12)
+* gpgme_op_keysign_start: Signing Keys. (line 68)
* gpgme_op_passwd: Changing Passphrases.
(line 6)
* gpgme_op_passwd_start: Changing Passphrases.
(line 19)
+* gpgme_op_revuid: Generating Keys. (line 192)
+* gpgme_op_revuid_start: Generating Keys. (line 218)
* gpgme_op_sign: Creating a Signature.
(line 21)
* gpgme_op_sign_result: Creating a Signature.
@@ -1208,20 +1773,25 @@ Function and Data Index
(line 13)
* gpgme_op_spawn_start: Running other Programs.
(line 38)
+* gpgme_op_tofu_policy: Changing TOFU Data. (line 27)
+* gpgme_op_tofu_policy_start: Changing TOFU Data. (line 39)
* gpgme_op_trustlist_end: Listing Trust Items. (line 44)
* gpgme_op_trustlist_next: Listing Trust Items. (line 27)
* gpgme_op_trustlist_start: Listing Trust Items. (line 6)
* gpgme_op_verify: Verify. (line 6)
-* gpgme_op_verify_result: Verify. (line 256)
+* gpgme_op_verify_result: Verify. (line 262)
* gpgme_op_verify_start: Verify. (line 26)
* gpgme_passphrase_cb_t: Passphrase Callback. (line 10)
+* gpgme_pinentry_mode_t: Pinentry Mode. (line 20)
* gpgme_progress_cb_t: Progress Meter Callback.
(line 8)
* gpgme_protocol_t: Protocols and Engines.
(line 17)
* gpgme_protocol_t <1>: Engine Information. (line 7)
* gpgme_pubkey_algo_name: Public Key Algorithms.
- (line 47)
+ (line 50)
+* gpgme_pubkey_algo_string: Public Key Algorithms.
+ (line 59)
* gpgme_pubkey_algo_t: Public Key Algorithms.
(line 10)
* gpgme_recipient_t: Decrypt. (line 30)
@@ -1231,6 +1801,8 @@ Function and Data Index
* gpgme_result_ref: Result Management. (line 14)
* gpgme_result_unref: Result Management. (line 20)
* gpgme_set_armor: ASCII Armor. (line 6)
+* gpgme_set_ctx_flag: Status Message Callback.
+ (line 37)
* gpgme_set_engine_info: Engine Configuration.
(line 11)
* gpgme_set_global_flag: Library Version Check.
@@ -1243,6 +1815,7 @@ Function and Data Index
* gpgme_set_locale: Locale. (line 14)
* gpgme_set_offline: Offline Mode. (line 6)
* gpgme_set_passphrase_cb: Passphrase Callback. (line 36)
+* gpgme_set_pinentry_mode: Pinentry Mode. (line 6)
* gpgme_set_progress_cb: Progress Meter Callback.
(line 16)
* gpgme_set_protocol: Protocol Selection. (line 6)
@@ -1250,10 +1823,10 @@ Function and Data Index
(line 17)
* gpgme_set_textmode: Text Mode. (line 6)
* gpgme_signature_t: Verify. (line 88)
-* gpgme_signers_add: Selecting Signers. (line 13)
-* gpgme_signers_clear: Selecting Signers. (line 6)
-* gpgme_signers_count: Selecting Signers. (line 20)
-* gpgme_signers_enum: Selecting Signers. (line 24)
+* gpgme_signers_add: Selecting Signers. (line 18)
+* gpgme_signers_clear: Selecting Signers. (line 11)
+* gpgme_signers_count: Selecting Signers. (line 25)
+* gpgme_signers_enum: Selecting Signers. (line 29)
* gpgme_sign_result_t: Creating a Signature.
(line 85)
* gpgme_sig_mode_t: Creating a Signature.
@@ -1265,30 +1838,32 @@ Function and Data Index
* gpgme_sig_notation_get: Signature Notation Data.
(line 41)
* gpgme_sig_notation_t: Verify. (line 38)
-* gpgme_sig_stat_t: Verify. (line 274)
+* gpgme_sig_stat_t: Deprecated Functions.
+ (line 428)
* gpgme_ssize_t: Exchanging Data. (line 30)
* gpgme_status_cb_t: Status Message Callback.
(line 8)
* gpgme_strerror: Error Strings. (line 6)
* gpgme_strerror_r: Error Strings. (line 15)
* gpgme_strsource: Error Strings. (line 26)
-* gpgme_subkey_t: Key Management. (line 11)
-* gpgme_trust_item_get_int_attr: Information About Trust Items.
- (line 28)
-* gpgme_trust_item_get_string_attr: Information About Trust Items.
- (line 14)
+* gpgme_subkey_t: Key objects. (line 94)
+* gpgme_tofu_policy_t: Changing TOFU Data. (line 11)
+* gpgme_trust_item_get_int_attr: Deprecated Functions.
+ (line 413)
+* gpgme_trust_item_get_string_attr: Deprecated Functions.
+ (line 399)
* gpgme_trust_item_ref: Manipulating Trust Items.
(line 6)
-* gpgme_trust_item_release: Manipulating Trust Items.
- (line 20)
+* gpgme_trust_item_release: Deprecated Functions.
+ (line 18)
* gpgme_trust_item_t: Trust Item Management.
(line 8)
* gpgme_trust_item_unref: Manipulating Trust Items.
(line 10)
-* gpgme_user_id_t: Key Management. (line 165)
+* gpgme_user_id_t: Key objects. (line 180)
* gpgme_validity_t: Information About Keys.
(line 9)
-* gpgme_verify_result_t: Verify. (line 241)
+* gpgme_verify_result_t: Verify. (line 247)
* gpgme_wait: Waiting For Completion.
(line 6)
* IMPORT_FILES: UI Server Import/Export Keys.
diff --git a/doc/gpgme.texi b/doc/gpgme.texi
index c02a30f..ec7ebb7 100644
--- a/doc/gpgme.texi
+++ b/doc/gpgme.texi
@@ -1,6 +1,7 @@
\input texinfo @c -*- mode: texinfo; coding: utf-8; -*-
@documentencoding UTF-8
@setfilename gpgme.info
+@include defs.inc
@settitle The `GnuPG Made Easy' Reference Manual
@dircategory GNU Libraries
@@ -13,8 +14,7 @@
@syncodeindex pg fn
@copying
-Copyright @copyright{} 2002, 2003, 2004, 2005, 2006, 2007,
-2008, 2010, 2012, 2013, 2014 g10 Code GmbH.
+Copyright @copyright{} 2002--2008, 2010, 2012--2016 g10 Code GmbH.
@quotation
Permission is granted to copy, distribute and/or modify this document
@@ -30,8 +30,6 @@ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
General Public License for more details.
@end copying
-@include version.texi
-
@c Macros used by the description of the UI server protocol
@macro clnt
@sc{c:} @c
@@ -72,7 +70,7 @@ This is Edition @value{EDITION}, last updated @value{UPDATED}, of
@center for version @value{VERSION}
@page
@vskip 0pt plus 1filll
-Published by g10 Code GmbH@* Hüttenstr. 61@* 40699 Erkrath, Germany
+Published by The GnuPG Project@* c/o g10 Code GmbH@* Hüttenstr. 61@* 40699 Erkrath, Germany
@insertcopying
@end titlepage
@@ -102,6 +100,7 @@ Appendices
* UI Server Protocol:: The GnuPG UI Server Protocol.
* Debugging:: How to solve problems.
+* Deprecated Functions:: Documentation of deprecated functions.
* Library Copying:: The GNU Lesser General Public License says
how you can copy and share `GnuPG Made Easy'.
@@ -199,21 +198,22 @@ Context Attributes
Key Management
+* Key objects:: Description of the key structures.
* Listing Keys:: Browsing the list of available keys.
* Information About Keys:: Requesting detailed information about keys.
-* Key Signatures:: Listing the signatures on a key.
* Manipulating Keys:: Operations on keys.
* Generating Keys:: Creating new key pairs.
+* Signing Keys:: Adding key signatures to public keys.
* Exporting Keys:: Retrieving key data from the key ring.
* Importing Keys:: Adding keys to the key ring.
* Deleting Keys:: Removing keys from the key ring.
* Changing Passphrases:: Change the passphrase of a key.
+* Changing TOFU Data:: Changing data pertaining to TOFU.
* Advanced Key Editing:: Advanced key edit operation.
Trust Item Management
* Listing Trust Items:: Browsing the list of available trust items.
-* Information About Trust Items:: Requesting information about trust items.
* Manipulating Trust Items:: Operations on trust items.
Crypto Operations
@@ -298,6 +298,13 @@ library. Experienced programmers might want to start looking at the
examples at the end of the manual, and then only read up those parts
of the interface which are unclear.
+The documentation for the language bindings is currently not included
+in this manual. Those languages bindings follow the general
+programming model of @acronym{GPGME} but may provide some extra high
+level abstraction on top of the @acronym{GPGME} style API. For now
+please see the README files in the @file{lang/} directory of the
+source distribution.
+
@node Features
@section Features
@@ -324,8 +331,11 @@ the programmer can focus on the other parts of the program, and still
integrate strong cryptography in his application. Once support for
@acronym{GPGME} has been added to a program, it is easy to add support
for other crypto protocols once @acronym{GPGME} backends provide them.
-@end table
+@item it's language friendly
+@acronym{GPGME} comes with languages bindings for several common
+programming languages: Common Lisp, C++, Python 2, and Python 3.
+@end table
@node Overview
@section Overview
@@ -451,6 +461,19 @@ any other option to select the thread package you want to link with.
Supported thread packages are @option{--thread=pth} and
@option{--thread=pthread}.
+If you need to detect the installed language bindings you can use list
+them using:
+
+@example
+gpgme-config --print-lang
+@end example
+
+or test for the availability using
+
+@example
+gpgme-config --have-lang=python && echo 'Bindings for Pythons available'
+@end example
+
@node Largefile Support (LFS)
@section Largefile Support (LFS)
@@ -679,12 +702,12 @@ as early as possible --- even before @code{gpgme_check_version}. The
features are identified by the following values for @var{name}:
@table @code
-@item "debug"
+@item debug
To enable debugging use the string ``debug'' for @var{name} and
@var{value} identical to the value used with the environment variable
@code{GPGME_DEBUG}.
-@item "disable-gpgconf"
+@item disable-gpgconf
Using this feature with any @var{value} disables the detection of the
gpgconf program and thus forces GPGME to fallback into the simple
OpenPGP only mode. It may be used to force the use of GnuPG-1 on
@@ -692,8 +715,8 @@ systems which have both GPG versions installed. Note that in general
the use of @code{gpgme_set_engine_info} is a better way to select a
specific engine version.
-@item "gpgconf-name"
-@itemx "gpg-name"
+@item gpgconf-name
+@itemx gpg-name
Set the name of the gpgconf respective gpg binary. The defaults are
@code{GNU/GnuPG/gpgconf} and @code{GNU/GnuPG/gpg}. Under Unix the
leading directory part is ignored. Under Windows the leading
@@ -701,6 +724,22 @@ directory part is used as the default installation directory; the
@code{.exe} suffix is added by GPGME. Use forward slashed even under
Windows.
+@item require-gnupg
+Set the mimimum version of the required GnuPG engine. If that version
+is not met, GPGME fails early instead of trying to use the existant
+version. The given version must be a string with major, minor, and
+micro number. Example: "2.1.0".
+
+@item w32-inst-dir
+On Windows GPGME needs to know its installation directory to find its
+spawn helper. This is in general no problem because a DLL has this
+information. Some applications however link statically to GPGME and
+thus GPGME can only figure out the installation directory of this
+application which may be wrong in certain cases. By supplying an
+installation directory as value to this flag, GPGME will assume that
+that directory is the installation directory. This flag has no effect
+on non-Windows platforms.
+
@end table
This function returns @code{0} on success. In contrast to other
@@ -862,9 +901,12 @@ This specifies the OpenPGP protocol.
@item GPGME_PROTOCOL_CMS
This specifies the Cryptographic Message Syntax.
-@item GPGME_PROTOCOL_ASSUAN
+@item GPGME_PROTOCOL_GPGCONF
Under development. Please ask on @email{gnupg-devel@@gnupg.org} for help.
+@item GPGME_PROTOCOL_ASSUAN
+This specifies the raw Assuan protocol.
+
@item GPGME_PROTOCOL_G13
Under development. Please ask on @email{gnupg-devel@@gnupg.org} for help.
@@ -895,6 +937,7 @@ allocated string describing the protocol @var{protocol}, or
* Engine Configuration:: Changing the engine configuration.
* OpenPGP:: Support for the OpenPGP protocol.
* Cryptographic Message Syntax:: Support for the CMS.
+* Assuan:: Support for the raw Assuan protocol.
@end menu
@@ -914,9 +957,34 @@ supported values for @var{what} are:
@item homedir
Return the default home directory.
+@item sysconfdir
+Return the name of the system configuration directory
+
+@item bindir
+Return the name of the directory with GnuPG program files.
+
+@item libdir
+Return the name of the directory with GnuPG related library files.
+
+@item libexecdir
+Return the name of the directory with GnuPG helper program files.
+
+@item datadir
+Return the name of the directory with GnuPG shared data.
+
+@item localedir
+Return the name of the directory with GnuPG locale data.
+
@item agent-socket
Return the name of the socket to connect to the gpg-agent.
+@item agent-ssh-socket
+Return the name of the socket to connect to the ssh-agent component of
+gpg-agent.
+
+@item dirmngr-socket
+Return the name of the socket to connect to the dirmngr.
+
@item uiserver-socket
Return the name of the socket to connect to the user interface server.
@@ -1099,6 +1167,20 @@ GnuPG.
The @acronym{CMS} protocol is specified by @code{GPGME_PROTOCOL_CMS}.
+@node Assuan
+@section Assuan
+@cindex ASSUAN
+@cindex protocol, ASSUAN
+@cindex engine, ASSUAN
+
+Assuan is the RPC library used by the various @acronym{GnuPG}
+components. The Assuan protocol allows one to talk to arbitrary
+Assuan servers using @acronym{GPGME}. @xref{Using the Assuan
+protocol}.
+
+The ASSUAN protocol is specified by @code{GPGME_PROTOCOL_ASSUAN}.
+
+
@node Algorithms
@chapter Algorithms
@cindex algorithms
@@ -1161,6 +1243,9 @@ Algorithm as defined by FIPS 186-2 and RFC-6637.
This value indicates ECDH, the Eliptic Curve Diffie-Hellmann
encryption algorithm as defined by RFC-6637.
+@item GPGME_PK_EDDSA
+This value indicates the EdDSA algorithm.
+
@end table
@end deftp
@@ -1174,6 +1259,14 @@ If @var{algo} is not a valid public key algorithm, @code{NULL} is
returned.
@end deftypefun
+@deftypefun {char *} gpgme_pubkey_algo_string (@w{gpgme_subkey_t @var{key}})
+The function @code{gpgme_pubkey_algo_string} is a convenience function
+to build and return an algorithm string in the same way GnuPG does
+(e.g. ``rsa2048'' or ``ed25519''). The caller must free the result
+using @code{gpgme_free}. On error (e.g. invalid argument or memory
+exhausted), the function returns NULL and sets @code{ERRNO}.
+@end deftypefun
+
@node Hash Algorithms
@section Hash Algorithms
@@ -1899,33 +1992,6 @@ data object was successfully created, and @code{GPG_ERR_ENOMEM} if not
enough memory is available.
@end deftypefun
-The following interface is deprecated and only provided for backward
-compatibility. Don't use it. It will be removed in a future version
-of @acronym{GPGME}.
-
-@deftypefun gpgme_error_t gpgme_data_new_with_read_cb (@w{gpgme_data_t *@var{dh}}, @w{int (*@var{readfunc})} (@w{void *@var{hook}}, @w{char *@var{buffer}}, @w{size_t @var{count}}, @w{size_t *@var{nread}}), @w{void *@var{hook_value}})
-The function @code{gpgme_data_new_with_read_cb} creates a new
-@code{gpgme_data_t} object and uses the callback function @var{readfunc}
-to retrieve the data on demand. As the callback function can supply
-the data in any way it wants, this is the most flexible data type
-@acronym{GPGME} provides. However, it can not be used to write data.
-
-The callback function receives @var{hook_value} as its first argument
-whenever it is invoked. It should return up to @var{count} bytes in
-@var{buffer}, and return the number of bytes actually read in
-@var{nread}. It may return @code{0} in @var{nread} if no data is
-currently available. To indicate @code{EOF} the function should
-return with an error code of @code{-1} and set @var{nread} to
-@code{0}. The callback function may support to reset its internal
-read pointer if it is invoked with @var{buffer} and @var{nread} being
-@code{NULL} and @var{count} being @code{0}.
-
-The function returns the error code @code{GPG_ERR_NO_ERROR} if the
-data object was successfully created, @code{GPG_ERR_INV_VALUE} if
-@var{dh} or @var{readfunc} is not a valid pointer, and
-@code{GPG_ERR_ENOMEM} if not enough memory is available.
-@end deftypefun
-
@node Destroying Data Buffers
@section Destroying Data Buffers
@@ -1954,9 +2020,11 @@ case, the data object @var{dh} is destroyed.
@deftypefun void gpgme_free (@w{void *@var{buffer}})
The function @code{gpgme_free} releases the memory returned by
-@code{gpgme_data_release_and_get_mem}. It should be used instead of
-the system libraries @code{free} function in case different allocators
-are used in a single program.
+@code{gpgme_data_release_and_get_mem} and
+@code{gpgme_pubkey_algo_string}. It should be used instead of the
+system libraries @code{free} function in case different allocators are
+used by a program. This is often the case if gpgme is used under
+Windows as a DLL.
@end deftypefun
@@ -2035,20 +2103,6 @@ read/write position.
If the function fails, -1 is returned and @var{errno} is set.
@end deftypefun
-The following function is deprecated and should not be used. It will
-be removed in a future version of @acronym{GPGME}.
-
-@deftypefun gpgme_error_t gpgme_data_rewind (@w{gpgme_data_t @var{dh}})
-The function @code{gpgme_data_rewind} is equivalent to:
-
-@example
- return (gpgme_data_seek (dh, 0, SEEK_SET) == -1)
- ? gpgme_error_from_errno (errno) : 0;
-@end example
-@end deftypefun
-
-
-
@node Data Buffer Meta-Data
@subsection Data Buffer Meta-Data
@@ -2107,6 +2161,9 @@ scheme as used by @acronym{MIME} and other protocols.
This specifies that the data is encoded in an armored form as used by
OpenPGP and PEM.
+@item GPGME_DATA_ENCODING_MIME
+This specifies that the data is encoded as a MIME part.
+
@item GPGME_DATA_ENCODING_URL
The data is a list of linefeed delimited URLs. This is only useful with
@code{gpgme_op_import}.
@@ -2134,6 +2191,30 @@ The function @code{gpgme_data_set_encoding} changes the encoding of
the data object with the handle @var{dh} to @var{enc}.
@end deftypefun
+@deftypefun {gpgme_error_t} gpgme_data_set_flag @
+ (@w{gpgme_data_t @var{dh}}, @
+ @w{const char *@var{name}}, @
+ @w{const char *@var{value}})
+
+Some minor properties of the data object can be controlled with flags
+set by this function. The properties are identified by the following
+values for @var{name}:
+
+@table @code
+@item size-hint
+The value is a decimal number with the length gpgme shall assume for
+this data object. This is useful if the data is provided by callbacks
+or via file descriptors but the applications knows the total size of
+the data. If this is set the OpenPGP engine may use this to decide on
+buffer allocation strategies and to provide a total value for its
+progress information.
+
+@end table
+
+This function returns @code{0} on success.
+@end deftypefun
+
+
@node Data Buffer Convenience
@subsection Data Buffer Convenience Functions
@cindex data buffer, convenience
@@ -2288,6 +2369,7 @@ started. In fact, these references are accessed through the
* ASCII Armor:: Requesting @acronym{ASCII} armored output.
* Text Mode:: Choosing canonical text mode.
* Offline Mode:: Choosing offline mode.
+* Pinentry Mode:: Choosing the pinentry mode.
* Included Certificates:: Including a number of certificates.
* Key Listing Mode:: Selecting key listing mode.
* Passphrase Callback:: Getting the passphrase from the user.
@@ -2448,6 +2530,57 @@ valid pointer.
@end deftypefun
+@node Pinentry Mode
+@subsection Pinentry Mode
+@cindex context, pinentry mode
+@cindex pinentry mode
+
+@deftypefun gpgme_error_t gpgme_set_pinentry_mode (@w{gpgme_ctx_t @var{ctx}},
+@w{gpgme_pinentry_mode_t @var{mode}})
+The function @code{gpgme_set_pinentry_mode} specifies the pinentry mode
+to be used.
+
+For GnuPG >= 2.1 this option is required to be set to
+@code{GPGME_PINENTRY_MODE_LOOPBACK} to enable the passphrase callback
+mechanism in GPGME through @code{gpgme_set_passphrase_cb}.
+@end deftypefun
+
+@deftypefun gpgme_pinentry_mode_t gpgme_get_pinentry_mode (@w{gpgme_ctx_t @var{ctx}})
+The function @code{gpgme_get_pinenty_mode} returns the
+mode set for the context.
+@end deftypefun
+
+@deftp {Data type} {enum gpgme_pinentry_mode_t}
+@tindex gpgme_pinentry_mode_t
+The @code{gpgme_minentry_mode_t} type specifies the set of possible pinentry
+modes that are supported by @acronym{GPGME} if GnuPG >= 2.1 is used.
+The following modes are supported:
+
+@table @code
+@item GPGME_PINENTRY_MODE_DEFAULT
+Use the default of the agent, which is ask.
+
+@item GPGME_PINENTRY_MODE_ASK
+Force the use of the Pinentry.
+
+@item GPGME_PINENTRY_MODE_CANCEL
+Emulate use of Pinentry's cancel button.
+
+@item GPGME_PINENTRY_MODE_ERROR
+Return a Pinentry error @code{No Pinentry}.
+
+@item GPGME_PINENTRY_MODE_LOOPBACK
+Redirect Pinentry queries to the caller.
+This enables the use of @code{gpgme_set_passphrase_cb} whis pinentry
+queries redirected to gpgme.
+
+Note: This mode requires @code{allow-loopback-pinentry} to be enabled
+in the @file{gpg-agent.conf} or an agent started with that option.
+
+@end table
+@end deftp
+
+
@node Included Certificates
@subsection Included Certificates
@cindex certificates, included
@@ -2520,6 +2653,11 @@ signature notations on key signatures should be included in the listed
keys. This only works if @code{GPGME_KEYLIST_MODE_SIGS} is also
enabled.
+@item GPGME_KEYLIST_MODE_WITH_TOFU
+The @code{GPGME_KEYLIST_MODE_WITH_TOFU} symbol specifies that
+information pertaining to the TOFU trust model should be included in
+the listed keys.
+
@item GPGME_KEYLIST_MODE_WITH_SECRET
The @code{GPGME_KEYLIST_MODE_WITH_SECRET} returns information about
the presence of a corresponding secret key in a public key listing. A
@@ -2616,6 +2754,10 @@ implement their own passphrase query. Some engines do not even
support an external passphrase callback at all, in this case the error
code @code{GPG_ERR_NOT_SUPPORTED} is returned.
+For GnuPG >= 2.1 the pinentry mode has to be set to
+@code{GPGME_PINENTRY_MODE_LOOPBACK} to enable the passphrase callback.
+See @code{gpgme_set_pinentry_mode}.
+
The user can disable the use of a passphrase callback function by
calling @code{gpgme_set_passphrase_cb} with @var{passfunc} being
@code{NULL}.
@@ -2713,6 +2855,33 @@ or @var{ctx} is not a valid pointer, @code{NULL} is returned in both
variables.
@end deftypefun
+@deftypefun {gpgme_error_t} gpgme_set_ctx_flag @
+ (@w{gpgme_ctx_t @var{ctx}}, @
+ @w{const char *@var{name}}, @
+ @w{const char *@var{value}})
+
+Some minor properties of the context can be controlled with flags set
+by this function. The properties are identified by the following
+values for @var{name}:
+
+@table @code
+@item "full-status"
+Using a @var{value} of "1" the status callback set by
+gpgme_set_status_cb returns all status lines with the exception of
+PROGRESS lines. With the default of "0" the status callback is only
+called in certain situations.
+
+@item "raw-description"
+Setting the @var{value} to "1" returns human readable strings in a raw
+format. For example the non breaking space characters ("~") will not
+be removed from the @code{description} field of the
+@code{gpgme_tofu_info_t} object.
+
+@end table
+
+This function returns @code{0} on success.
+@end deftypefun
+
@node Locale
@subsection Locale
@@ -2760,9 +2929,120 @@ signers are specified. This is always done by specifying the
respective keys that should be used for the operation. The following
section describes how such keys can be selected and manipulated.
+
+@menu
+* Key objects:: Description of the key structures.
+* Listing Keys:: Browsing the list of available keys.
+* Information About Keys:: Requesting detailed information about keys.
+* Manipulating Keys:: Operations on keys.
+* Generating Keys:: Creating new key pairs.
+* Signing Keys:: Adding key signatures to public keys.
+* Exporting Keys:: Retrieving key data from the key ring.
+* Importing Keys:: Adding keys to the key ring.
+* Deleting Keys:: Removing keys from the key ring.
+* Changing Passphrases:: Change the passphrase of a key.
+* Changing TOFU Data:: Changing data pertaining to TOFU.
+* Advanced Key Editing:: Advanced key edit operation.
+@end menu
+
+@node Key objects
+@subsection Key objects
+
+The keys are represented in GPGME by structures which may only be read
+by the application but never be allocated or changed. They are valid
+as long as the key object itself is valid.
+
+@deftp {Data type} gpgme_key_t
+
+The @code{gpgme_key_t} type is a pointer to a key object. It has the
+following members:
+
+@table @code
+@item gpgme_keylist_mode_t keylist_mode
+The keylist mode that was active when the key was retrieved.
+
+@item unsigned int revoked : 1
+This is true if the key is revoked.
+
+@item unsigned int expired : 1
+This is true if the key is expired.
+
+@item unsigned int disabled : 1
+This is true if the key is disabled.
+
+@item unsigned int invalid : 1
+This is true if the key is invalid. This might have several reasons,
+for a example for the S/MIME backend, it will be set during key
+listings if the key could not be validated due to missing
+certificates or unmatched policies.
+
+@item unsigned int can_encrypt : 1
+This is true if the key (ie one of its subkeys) can be used for
+encryption.
+
+@item unsigned int can_sign : 1
+This is true if the key (ie one of its subkeys) can be used to create
+data signatures.
+
+@item unsigned int can_certify : 1
+This is true if the key (ie one of its subkeys) can be used to create
+key certificates.
+
+@item unsigned int can_authenticate : 1
+This is true if the key (ie one of its subkeys) can be used for
+authentication.
+
+@item unsigned int is_qualified : 1
+This is true if the key can be used for qualified signatures according
+to local government regulations.
+
+@item unsigned int secret : 1
+This is true if the key is a secret key. Note, that this will always
+be true even if the corresponding subkey flag may be false
+(offline/stub keys). This is only set if a listing of secret keys has
+been requested or if @code{GPGME_KEYLIST_MODE_WITH_SECRET} is active.
+
+@item gpgme_protocol_t protocol
+This is the protocol supported by this key.
+
+@item char *issuer_serial
+If @code{protocol} is @code{GPGME_PROTOCOL_CMS}, then this is the
+issuer serial.
+
+@item char *issuer_name
+If @code{protocol} is @code{GPGME_PROTOCOL_CMS}, then this is the
+issuer name.
+
+@item char *chain_id
+If @code{protocol} is @code{GPGME_PROTOCOL_CMS}, then this is the
+chain ID, which can be used to built the certificate chain.
+
+@item gpgme_validity_t owner_trust
+If @code{protocol} is @code{GPGME_PROTOCOL_OpenPGP}, then this is the
+owner trust.
+
+@item gpgme_subkey_t subkeys
+This is a linked list with the subkeys of the key. The first subkey
+in the list is the primary key and usually available.
+
+@item gpgme_user_id_t uids
+This is a linked list with the user IDs of the key. The first user ID
+in the list is the main (or primary) user ID.
+
+@item char *fpr
+This field gives the fingerprint of the primary key. Note that
+this is a copy of the fingerprint of the first subkey. For an
+incomplete key (for example from a verification result) a subkey may
+be missing but this field may be set nevertheless.
+
+@end table
+@end deftp
+
+
@deftp {Data type} gpgme_subkey_t
+
The @code{gpgme_subkey_t} type is a pointer to a subkey structure.
-Sub keys are one component of a @code{gpgme_key_t} object. In fact,
+Subkeys are one component of a @code{gpgme_key_t} object. In fact,
subkeys are those parts that contains the real information about the
individual cryptographic keys that belong to the same key object. One
@code{gpgme_key_t} can contain several subkeys. The first subkey in
@@ -2823,6 +3103,10 @@ This is the key ID of the subkey in hexadecimal digits.
This is the fingerprint of the subkey in hexadecimal digits, if
available.
+@item char *keygrip
+The keygrip of the subkey in hex digit form or @code{NULL} if not
+availabale.
+
@item long int timestamp
This is the creation timestamp of the subkey. This is -1 if the
timestamp is invalid, and 0 if it is not available.
@@ -2838,15 +3122,66 @@ True if the secret key is stored on a smart card.
The serial number of a smart card holding this key or @code{NULL}.
@item char *curve
-For ECC algoritms the name of the curve.
+For ECC algorithms the name of the curve.
@end table
@end deftp
+@deftp {Data type} gpgme_user_id_t
+
+A user ID is a component of a @code{gpgme_key_t} object. One key can
+have many user IDs. The first one in the list is the main (or
+primary) user ID.
+
+The user ID structure has the following members.
+
+@table @code
+@item gpgme_user_id_t next
+This is a pointer to the next user ID structure in the linked list, or
+@code{NULL} if this is the last element.
+
+@item unsigned int revoked : 1
+This is true if the user ID is revoked.
+
+@item unsigned int invalid : 1
+This is true if the user ID is invalid.
+
+@item gpgme_validity_t validity
+This specifies the validity of the user ID.
+
+@item char *uid
+This is the user ID string.
+
+@item char *name
+This is the name component of @code{uid}, if available.
+
+@item char *comment
+This is the comment component of @code{uid}, if available.
+
+@item char *email
+This is the email component of @code{uid}, if available.
+
+@item char *address;
+The mail address (addr-spec from RFC-5322) of the user ID string.
+This is general the same as the @code{email} part of this structure
+but might be slightly different. If no mail address is available
+@code{NULL} is stored.
+
+@item gpgme_tofu_info_t tofu
+If not @code{NULL} information from the TOFU database pertaining to
+this user id.
+
+@item gpgme_key_sig_t signatures
+This is a linked list with the signatures on this user ID.
+@end table
+@end deftp
+
+
@deftp {Data type} gpgme_key_sig_t
+
The @code{gpgme_key_sig_t} type is a pointer to a key signature structure.
Key signatures are one component of a @code{gpgme_key_t} object, and
-validate user IDs on the key.
+validate user IDs on the key in the OpenPGP protocol.
The signatures on a key are only available if the key was retrieved
via a listing operation with the @code{GPGME_KEYLIST_MODE_SIGS} mode
@@ -2917,134 +3252,6 @@ This is a linked list with the notation data and policy URLs.
@end table
@end deftp
-@deftp {Data type} gpgme_user_id_t
-A user ID is a component of a @code{gpgme_key_t} object. One key can
-have many user IDs. The first one in the list is the main (or
-primary) user ID.
-
-The user ID structure has the following members.
-
-@table @code
-@item gpgme_user_id_t next
-This is a pointer to the next user ID structure in the linked list, or
-@code{NULL} if this is the last element.
-
-@item unsigned int revoked : 1
-This is true if the user ID is revoked.
-
-@item unsigned int invalid : 1
-This is true if the user ID is invalid.
-
-@item gpgme_validity_t validity
-This specifies the validity of the user ID.
-
-@item char *uid
-This is the user ID string.
-
-@item char *name
-This is the name component of @code{uid}, if available.
-
-@item char *comment
-This is the comment component of @code{uid}, if available.
-
-@item char *email
-This is the email component of @code{uid}, if available.
-
-@item gpgme_key_sig_t signatures
-This is a linked list with the signatures on this user ID.
-@end table
-@end deftp
-
-@deftp {Data type} gpgme_key_t
-The @code{gpgme_key_t} type is a pointer to a key object. It has the
-following members:
-
-@table @code
-@item gpgme_keylist_mode_t keylist_mode
-The keylist mode that was active when the key was retrieved.
-
-@item unsigned int revoked : 1
-This is true if the key is revoked.
-
-@item unsigned int expired : 1
-This is true if the key is expired.
-
-@item unsigned int disabled : 1
-This is true if the key is disabled.
-
-@item unsigned int invalid : 1
-This is true if the key is invalid. This might have several reasons,
-for a example for the S/MIME backend, it will be set in during key
-listsing if the key could not be validated due to a missing
-certificates or unmatched policies.
-
-@item unsigned int can_encrypt : 1
-This is true if the key (ie one of its subkeys) can be used for
-encryption.
-
-@item unsigned int can_sign : 1
-This is true if the key (ie one of its subkeys) can be used to create
-data signatures.
-
-@item unsigned int can_certify : 1
-This is true if the key (ie one of its subkeys) can be used to create
-key certificates.
-
-@item unsigned int can_authenticate : 1
-This is true if the key (ie one of its subkeys) can be used for
-authentication.
-
-@item unsigned int is_qualified : 1
-This is true if the key can be used for qualified signatures according
-to local government regulations.
-
-@item unsigned int secret : 1
-This is true if the key is a secret key. Note, that this will always
-be true even if the corresponding subkey flag may be false
-(offline/stub keys). This is only set if a listing of secret keys has
-been requested or if @code{GPGME_KEYLIST_MODE_WITH_SECRET} is active.
-
-@item gpgme_protocol_t protocol
-This is the protocol supported by this key.
-
-@item char *issuer_serial
-If @code{protocol} is @code{GPGME_PROTOCOL_CMS}, then this is the
-issuer serial.
-
-@item char *issuer_name
-If @code{protocol} is @code{GPGME_PROTOCOL_CMS}, then this is the
-issuer name.
-
-@item char *chain_id
-If @code{protocol} is @code{GPGME_PROTOCOL_CMS}, then this is the
-chain ID, which can be used to built the certificate chain.
-
-@item gpgme_validity_t owner_trust
-If @code{protocol} is @code{GPGME_PROTOCOL_OpenPGP}, then this is the
-owner trust.
-
-@item gpgme_subkey_t subkeys
-This is a linked list with the subkeys of the key. The first subkey
-in the list is the primary key and usually available.
-
-@item gpgme_user_id_t uids
-This is a linked list with the user IDs of the key. The first user ID
-in the list is the main (or primary) user ID.
-@end table
-@end deftp
-
-@menu
-* Listing Keys:: Browsing the list of available keys.
-* Information About Keys:: Requesting detailed information about keys.
-* Key Signatures:: Listing the signatures on a key.
-* Manipulating Keys:: Operations on keys.
-* Generating Keys:: Creating new key pairs.
-* Exporting Keys:: Retrieving key data from the key ring.
-* Importing Keys:: Adding keys to the key ring.
-* Deleting Keys:: Removing keys from the key ring.
-* Changing Passphrases:: Change the passphrase of a key.
-* Advanced Key Editing:: Advanced key edit operation.
-@end menu
@node Listing Keys
@@ -3264,315 +3471,326 @@ validity is ``u''.
@end deftp
-The following interfaces are deprecated and only provided for backward
-compatibility. Don't use them. They will be removed in a future
-version of @acronym{GPGME}.
-
-@deftp {Data type} gpgme_attr_t
-The @code{gpgme_attr_t} type is used to specify a key or trust item
-attribute. The following attributes are defined:
-
-@table @code
-@item GPGME_ATTR_KEYID
-This is the key ID of a sub key. It is representable as a string.
-
-For trust items, the trust item refers to the key with this ID.
-@item GPGME_ATTR_FPR
-This is the fingerprint of a sub key. It is representable as a
-string.
-
-@item GPGME_ATTR_ALGO
-This is the crypto algorithm for which the sub key can be used. It
-is representable as a string and as a number. The numbers correspond
-to the @code{enum gcry_pk_algos} values in the gcrypt library.
-
-@item GPGME_ATTR_LEN
-This is the key length of a sub key. It is representable as a
-number.
-
-@item GPGME_ATTR_CREATED
-This is the timestamp at creation time of a sub key. It is
-representable as a number.
-@item GPGME_ATTR_EXPIRE
-This is the expiration time of a sub key. It is representable as a
-number.
-
-@item GPGME_ATTR_OTRUST
-XXX FIXME (also for trust items)
+@node Manipulating Keys
+@subsection Manipulating Keys
+@cindex key, manipulation
-@item GPGME_ATTR_USERID
-This is a user ID. There can be more than one user IDs in a
-@var{gpgme_key_t} object. The first one (with index 0) is the primary
-user ID. The user ID is representable as a number.
+@deftypefun void gpgme_key_ref (@w{gpgme_key_t @var{key}})
+The function @code{gpgme_key_ref} acquires an additional reference for
+the key @var{key}.
+@end deftypefun
-For trust items, this is the user ID associated with this trust item.
+@deftypefun void gpgme_key_unref (@w{gpgme_key_t @var{key}})
+The function @code{gpgme_key_unref} releases a reference for the key
+@var{key}. If this was the last reference, the key will be destroyed
+and all resources associated to it will be released.
+@end deftypefun
-@item GPGME_ATTR_NAME
-This is the name belonging to a user ID. It is representable as a string.
-@item GPGME_ATTR_EMAIL
-This is the email address belonging to a user ID. It is representable
-as a string.
-
-@item GPGME_ATTR_COMMENT
-This is the comment belonging to a user ID. It is representable as a
-string.
+@node Generating Keys
+@subsection Generating Keys
+@cindex key, creation
+@cindex key ring, add
-@item GPGME_ATTR_VALIDITY
-This is the validity belonging to a user ID. It is representable as a
-string and as a number. See below for a list of available validities.
+GPGME provides a set of functions to create public key pairs. Most of
+these functions require the use of GnuPG 2.1 and later; for older
+GnuPG versions the @code{gpgme_op_genkey} function can be used.
+Existing code which wants to update to the new functions or new code
+which shall supports older GnuPG versions may try the new functions
+first and provide a fallback to the old function if the error code
+@code{GPG_ERR_NOT_SUPPORTED} is received.
-For trust items, this is the validity that is associated with this
-trust item.
+@c
+@c gpgme_op_createkey
+@c
+@deftypefun gpgme_error_t gpgme_op_createkey @
+ (@w{gpgme_ctx_t @var{ctx}}, @
+ @w{const char *@var{userid}}, @
+ @w{const char *@var{algo}}, @
+ @w{unsigned long @var{reserved}}, @
+ @w{unsigned long @var{expires}}, @
+ @w{gpgme_key_t @var{extrakey}}, @
+ @w{unsigned int @var{flags}});
+
+The function @code{gpgme_op_createkey} generates a new key for the
+procotol active in the context @var{ctx}. As of now this function
+does only work for OpenPGP and requires at least version 2.1.13 of
+GnuPG.
-@item GPGME_ATTR_UID_REVOKED
-This specifies if a user ID is revoked. It is representable as a
-number, and is @code{1} if the user ID is revoked, and @code{0}
-otherwise.
+@var{userid} is commonly the mail address associated with the key.
+GPGME does not require a specificy syntax but if more than a mail
+address is given, RFC-822 style format is suggested. The value is
+expected to be in UTF-8 encoding (i.e. no IDN encoding for mail
+addresses). This is a required parameter.
+
+@var{algo} specifies the algorithm for the new key (actually a keypair
+of public and private key). For a list of supported algorithms, see
+the GnuPG manual. If @var{algo} is @code{NULL} or the string
+"default", the key is generated using the default algorithm of the
+engine. If the string "future-default" is used the engine may use an
+algorithm which is planned to be the default in a future release of
+the engine; however existing implementation of the protocol may not be
+able to already handle such future algorithms. For the OpenPGP
+protocol, the specification of a default algorithm, without requesting
+a non-default usage via @var{flags}, triggers the creation of a
+primary key plus a secondary key (subkey).
+
+@var{reserved} must be set to zero.
+
+@var{expires} can be set to the number of seconds since Epoch of the
+desired expiration date in UTC for the new key. Using 0 does not
+set an expiration date. Note that this parameter takes an unsigned long
+value and not a @code{time_t} to avoid problems on systems which use a
+signed 32 bit @code{time_t}. Note further that the OpenPGP protocol
+uses 32 bit values for timestamps and thus can only encode dates up to
+the year 2106.
+
+@var{extrakey} is currently not used and must be set to @code{NULL}.
+A future version of GPGME may use this parameter to create X.509 keys.
+
+@var{flags} can be set to the bit-wise OR of the following flags:
-@item GPGME_ATTR_UID_INVALID
-This specifies if a user ID is invalid. It is representable as a
-number, and is @code{1} if the user ID is invalid, and @code{0}
-otherwise.
+@table @code
+@item GPGME_CREATE_SIGN
+@itemx GPGME_CREATE_ENCR
+@itemx GPGME_CREATE_CERT
+@itemx GPGME_CREATE_AUTH
+Do not create the key with the default capabilities (key usage) of the
+requested algorithm but use those explicitly given by these flags:
+``signing'', ``encryption'', ``certification'', or ``authentication''.
+The allowed combinations depend on the algorithm.
+
+If any of these flags are set and a default algorithm has been
+selected only one key is created in the case of the OpenPGP
+protocol.
+
+@item GPGME_CREATE_NOPASSWD
+Request generation of the key without password protection.
+
+@item GPGME_CREATE_SELFSIGNED
+For an X.509 key do not create a CSR but a self-signed certificate.
+This has not yet been implemented.
+
+@item GPGME_CREATE_NOSTORE
+Do not store the created key in the local key database.
+This has not yet been implemented.
+
+@item GPGME_CREATE_WANTPUB
+@itemx GPGME_CREATE_WANTSEC
+Return the public or secret key as part of the result structure.
+This has not yet been implemented.
+
+@item GPGME_CREATE_FORCE
+The engine does not allow the creation of a key with a user ID
+already existing in the local key database. This flag can be used to
+override this check.
-@item GPGME_ATTR_LEVEL
-This is the trust level of a trust item.
+@end table
-@item GPGME_ATTR_TYPE
-This returns information about the type of key. For the string function
-this will eother be "PGP" or "X.509". The integer function returns 0
-for PGP and 1 for X.509. It is also used for the type of a trust item.
+After the operation completed successfully, information about the
+created key can be retrieved with @code{gpgme_op_genkey_result}.
-@item GPGME_ATTR_IS_SECRET
-This specifies if the key is a secret key. It is representable as a
-number, and is @code{1} if the key is revoked, and @code{0} otherwise.
+The function returns zero on success, @code{GPG_ERR_NOT_SUPPORTED} if
+the engine does not support the command, or a bunch of other error
+codes.
-@item GPGME_ATTR_KEY_REVOKED
-This specifies if a sub key is revoked. It is representable as a
-number, and is @code{1} if the key is revoked, and @code{0} otherwise.
+@end deftypefun
-@item GPGME_ATTR_KEY_INVALID
-This specifies if a sub key is invalid. It is representable as a
-number, and is @code{1} if the key is invalid, and @code{0} otherwise.
-@item GPGME_ATTR_KEY_EXPIRED
-This specifies if a sub key is expired. It is representable as a
-number, and is @code{1} if the key is expired, and @code{0} otherwise.
+@deftypefun gpgme_error_t gpgme_op_createkey_start @
+ (@w{gpgme_ctx_t @var{ctx}}, @
+ @w{const char *@var{userid}}, @
+ @w{const char *@var{algo}}, @
+ @w{unsigned long @var{reserved}}, @
+ @w{unsigned long @var{expires}}, @
+ @w{gpgme_key_t @var{extrakey}}, @
+ @w{unsigned int @var{flags}});
-@item GPGME_ATTR_KEY_DISABLED
-This specifies if a sub key is disabled. It is representable as a
-number, and is @code{1} if the key is disabled, and @code{0} otherwise.
+The function @code{gpgme_op_createkey_start} initiates a
+@code{gpgme_op_createkey} operation; see there for details. It must
+be completed by calling @code{gpgme_wait} on the context.
+@xref{Waiting For Completion}.
-@item GPGME_ATTR_KEY_CAPS
-This is a description of the capabilities of a sub key. It is
-representable as a string. The string contains the letter ``e'' if
-the key can be used for encryption, ``s'' if the key can be used for
-signatures, and ``c'' if the key can be used for certifications.
+@end deftypefun
-@item GPGME_ATTR_CAN_ENCRYPT
-This specifies if a sub key can be used for encryption. It is
-representable as a number, and is @code{1} if the sub key can be used
-for encryption, and @code{0} otherwise.
+@c
+@c gpgme_op_createsubkey
+@c
+@deftypefun gpgme_error_t gpgme_op_createsubkey @
+ (@w{gpgme_ctx_t @var{ctx}}, @
+ @w{gpgme_key_t @var{key}}, @
+ @w{const char *@var{algo}}, @
+ @w{unsigned long @var{reserved}}, @
+ @w{unsigned long @var{expires}}, @
+ @w{unsigned int @var{flags}});
-@item GPGME_ATTR_CAN_SIGN
-This specifies if a sub key can be used to create data signatures. It
-is representable as a number, and is @code{1} if the sub key can be
-used for signatures, and @code{0} otherwise.
+The function @code{gpgme_op_createsubkey} creates and adds a new
+subkey to the primary OpenPGP key given by @var{KEY}. The only
+allowed protocol in @var{ctx} is @code{GPGME_PROTOCOL_OPENPGP}.
+Subkeys (aka secondary keys) are a concept in the OpenPGP protocol to
+bind several keys to a primary key. As of now this function requires
+at least version 2.1.13 of GnuPG.
-@item GPGME_ATTR_CAN_CERTIFY
-This specifies if a sub key can be used to create key certificates.
-It is representable as a number, and is @code{1} if the sub key can be
-used for certifications, and @code{0} otherwise.
+@var{key} specifies the key to operate on.
-@item GPGME_ATTR_SERIAL
-The X.509 issuer serial attribute of the key. It is representable as
-a string.
+@var{algo} specifies the algorithm for the new subkey. For a list of
+supported algorithms, see the GnuPG manual. If @var{algo} is
+@code{NULL} or the string "default", the subkey is generated using the
+default algorithm for an encryption subkey of the engine. If the
+string "future-default" is used the engine may use an encryption
+algorithm which is planned to be the default in a future release of
+the engine; however existing implementation of the protocol may not be
+able to already handle such future algorithms.
-@item GPGME_ATTR_ISSUE
-The X.509 issuer name attribute of the key. It is representable as a
-string.
+@var{reserved} must be set to zero.
-@item GPGME_ATTR_CHAINID
-The X.509 chain ID can be used to build the certification chain. It
-is representable as a string.
-@end table
-@end deftp
+@var{expires} can be set to the number of seconds since Epoch of the
+desired expiration date in UTC for the new subkey. Using 0 does not
+set an expiration date. Note that this parameter takes an unsigned long
+value and not a @code{time_t} to avoid problems on systems which use a
+signed 32 bit @code{time_t}. Note further that the OpenPGP protocol
+uses 32 bit values for timestamps and thus can only encode dates up to
+the year 2106.
-@deftypefun {const char *} gpgme_key_get_string_attr (@w{gpgme_key_t @var{key}}, @w{gpgme_attr_t @var{what}}, @w{const void *@var{reserved}}, @w{int @var{idx}})
-The function @code{gpgme_key_get_string_attr} returns the value of the
-string-representable attribute @var{what} of key @var{key}. If the
-attribute is an attribute of a sub key or an user ID, @var{idx}
-specifies the sub key or user ID of which the attribute value is
-returned. The argument @var{reserved} is reserved for later use and
-should be @code{NULL}.
+@var{flags} takes the same values as described above for
+@code{gpgme_op_createkey}.
-The string returned is only valid as long as the key is valid.
+After the operation completed successfully, information about the
+created key can be retrieved with @code{gpgme_op_genkey_result}.
-The function returns @code{0} if an attribute can't be returned as a
-string, @var{key} is not a valid pointer, @var{idx} out of range,
-or @var{reserved} not @code{NULL}.
-@end deftypefun
+The function returns zero on success, @code{GPG_ERR_NOT_SUPPORTED} if
+the engine does not support the command, or a bunch of other error
+codes.
-@deftypefun {unsigned long} gpgme_key_get_ulong_attr (@w{gpgme_key_t @var{key}}, @w{gpgme_attr_t @var{what}}, @w{const void *@var{reserved}}, @w{int @var{idx}})
-The function @code{gpgme_key_get_ulong_attr} returns the value of the
-number-representable attribute @var{what} of key @var{key}. If the
-attribute is an attribute of a sub key or an user ID, @var{idx}
-specifies the sub key or user ID of which the attribute value is
-returned. The argument @var{reserved} is reserved for later use and
-should be @code{NULL}.
-The function returns @code{0} if the attribute can't be returned as a
-number, @var{key} is not a valid pointer, @var{idx} out of range, or
-@var{reserved} not @code{NULL}.
@end deftypefun
+@deftypefun gpgme_error_t gpgme_op_createsubkey_start @
+ (@w{gpgme_ctx_t @var{ctx}}, @
+ @w{gpgme_key_t @var{key}}, @
+ @w{const char *@var{algo}}, @
+ @w{unsigned long @var{reserved}}, @
+ @w{unsigned long @var{expires}}, @
+ @w{unsigned int @var{flags}});
-@node Key Signatures
-@subsection Key Signatures
-@cindex key, signatures
-@cindex signatures, on a key
+The function @code{gpgme_op_createsubkey_start} initiates a
+@code{gpgme_op_createsubkey} operation; see there for details. It must
+be completed by calling @code{gpgme_wait} on the context.
+@xref{Waiting For Completion}.
-The following interfaces are deprecated and only provided for backward
-compatibility. Don't use them. They will be removed in a future
-version of @acronym{GPGME}.
+@end deftypefun
-The signatures on a key are only available if the key was retrieved
-via a listing operation with the @code{GPGME_KEYLIST_MODE_SIGS} mode
-enabled, because it is expensive to retrieve all signatures of a key.
-So, before using the below interfaces to retrieve the signatures on a
-key, you have to make sure that the key was listed with signatures
-enabled. One convenient, but blocking, way to do this is to use the
-function @code{gpgme_get_key}.
+@c
+@c gpgme_op_adduid
+@c
+@deftypefun gpgme_error_t gpgme_op_adduid @
+ (@w{gpgme_ctx_t @var{ctx}}, @
+ @w{gpgme_key_t @var{key}}, @
+ @w{const char *@var{userid}}, @
+ @w{unsigned int @var{flags}});
-@deftp {Data type} gpgme_attr_t
-The @code{gpgme_attr_t} type is used to specify a key signature
-attribute. The following attributes are defined:
+The function @code{gpgme_op_adduid} adds a new user ID to the OpenPGP
+key given by @var{KEY}. Adding additional user IDs after key creation
+is a feature of the OpenPGP protocol and thus the protocol for the
+context @var{ctx} must be set to OpenPGP. As of now this function
+requires at least version 2.1.13 of GnuPG.
-@table @code
-@item GPGME_ATTR_KEYID
-This is the key ID of the key which was used for the signature. It is
-representable as a string.
+@var{key} specifies the key to operate on.
-@item GPGME_ATTR_ALGO
-This is the crypto algorithm used to create the signature. It is
-representable as a string and as a number. The numbers correspond to
-the @code{enum gcry_pk_algos} values in the gcrypt library.
+@var{userid} is the user ID to add to the key. A user ID is commonly
+the mail address to be associated with the key. GPGME does not
+require a specificy syntax but if more than a mail address is given,
+RFC-822 style format is suggested. The value is expected to be in
+UTF-8 encoding (i.e. no IDN encoding for mail addresses). This is a
+required parameter.
-@item GPGME_ATTR_CREATED
-This is the timestamp at creation time of the signature. It is
-representable as a number.
+@var{flags} are currently not used and must be set to zero.
-@item GPGME_ATTR_EXPIRE
-This is the expiration time of the signature. It is representable as
-a number.
+The function returns zero on success, @code{GPG_ERR_NOT_SUPPORTED} if
+the engine does not support the command, or a bunch of other error
+codes.
-@item GPGME_ATTR_USERID
-This is the user ID associated with the signing key. The user ID is
-representable as a number.
+@end deftypefun
-@item GPGME_ATTR_NAME
-This is the name belonging to a user ID. It is representable as a string.
+@deftypefun gpgme_error_t gpgme_op_adduid_start @
+ (@w{gpgme_ctx_t @var{ctx}}, @
+ @w{gpgme_key_t @var{key}}, @
+ @w{const char *@var{userid}}, @
+ @w{unsigned int @var{flags}});
-@item GPGME_ATTR_EMAIL
-This is the email address belonging to a user ID. It is representable
-as a string.
+The function @code{gpgme_op_adduid_start} initiates a
+@code{gpgme_op_adduid} operation; see there for details. It must
+be completed by calling @code{gpgme_wait} on the context.
+@xref{Waiting For Completion}.
-@item GPGME_ATTR_COMMENT
-This is the comment belonging to a user ID. It is representable as a
-string.
+@end deftypefun
-@item GPGME_ATTR_KEY_REVOKED
-This specifies if a key signature is a revocation signature. It is
-representable as a number, and is @code{1} if the key is revoked, and
-@code{0} otherwise.
-@c @item GPGME_ATTR_KEY_EXPIRED
-@c This specifies if a key signature is expired. It is representable as
-@c a number, and is @code{1} if the key is revoked, and @code{0}
-@c otherwise.
@c
-@item GPGME_ATTR_SIG_CLASS
-This specifies the signature class of a key signature. It is
-representable as a number. The meaning is specific to the crypto
-engine.
-
-@item GPGME_ATTR_SIG_CLASS
-This specifies the signature class of a key signature. It is
-representable as a number. The meaning is specific to the crypto
-engine.
+@c gpgme_op_revuid
+@c
+@deftypefun gpgme_error_t gpgme_op_revuid @
+ (@w{gpgme_ctx_t @var{ctx}}, @
+ @w{gpgme_key_t @var{key}}, @
+ @w{const char *@var{userid}}, @
+ @w{unsigned int @var{flags}});
-@item GPGME_ATTR_SIG_STATUS
-This is the same value as returned by @code{gpgme_get_sig_status}.
-@end table
-@end deftp
+The function @code{gpgme_op_revuid} revokes a user ID from the OpenPGP
+key given by @var{KEY}. Revoking user IDs after key creation is a
+feature of the OpenPGP protocol and thus the protocol for the context
+@var{ctx} must be set to OpenPGP. As of now this function requires at
+least version 2.1.13 of GnuPG.
-@deftypefun {const char *} gpgme_key_sig_get_string_attr (@w{gpgme_key_t @var{key}}, @w{int @var{uid_idx}}, @w{gpgme_attr_t @var{what}}, @w{const void *@var{reserved}}, @w{int @var{idx}})
-The function @code{gpgme_key_sig_get_string_attr} returns the value of
-the string-representable attribute @var{what} of the signature
-@var{idx} on the user ID @var{uid_idx} in the key @var{key}. The
-argument @var{reserved} is reserved for later use and should be
-@code{NULL}.
+@var{key} specifies the key to operate on.
-The string returned is only valid as long as the key is valid.
+@var{userid} is the user ID to be revoked from the key. The user ID
+must be given verbatim because the engine does an exact and case
+sensitive match. Thus the @code{uid} field from the user ID object
+(@code{gpgme_user_id_t}) is to be used. This is a required parameter.
-The function returns @code{0} if an attribute can't be returned as a
-string, @var{key} is not a valid pointer, @var{uid_idx} or @var{idx}
-out of range, or @var{reserved} not @code{NULL}.
-@end deftypefun
+@var{flags} are currently not used and must be set to zero.
-@deftypefun {unsigned long} gpgme_key_sig_get_ulong_attr (@w{gpgme_key_t @var{key}}, @w{int @var{uid_idx}}, @w{gpgme_attr_t @var{what}}, @w{const void *@var{reserved}}, @w{int @var{idx}})
-The function @code{gpgme_key_sig_get_ulong_attr} returns the value of
-the number-representable attribute @var{what} of the signature
-@var{idx} on the user ID @var{uid_idx} in the key @var{key}. The
-argument @var{reserved} is reserved for later use and should be
-@code{NULL}.
-
-The function returns @code{0} if an attribute can't be returned as a
-string, @var{key} is not a valid pointer, @var{uid_idx} or @var{idx}
-out of range, or @var{reserved} not @code{NULL}.
-@end deftypefun
+Note that the engine won't allow to revoke the last valid user ID. To
+change a user ID is better to first add the new user ID, then revoke
+the old one, and finally publish the key.
+The function returns zero on success, @code{GPG_ERR_NOT_SUPPORTED} if
+the engine does not support the command, or a bunch of other error
+codes.
-@node Manipulating Keys
-@subsection Manipulating Keys
-@cindex key, manipulation
-
-@deftypefun void gpgme_key_ref (@w{gpgme_key_t @var{key}})
-The function @code{gpgme_key_ref} acquires an additional reference for
-the key @var{key}.
-@end deftypefun
-
-@deftypefun void gpgme_key_unref (@w{gpgme_key_t @var{key}})
-The function @code{gpgme_key_unref} releases a reference for the key
-@var{key}. If this was the last reference, the key will be destroyed
-and all resources associated to it will be released.
@end deftypefun
+@deftypefun gpgme_error_t gpgme_op_revuid_start @
+ (@w{gpgme_ctx_t @var{ctx}}, @
+ @w{gpgme_key_t @var{key}}, @
+ @w{const char *@var{userid}}, @
+ @w{unsigned int @var{flags}});
-The following interface is deprecated and only provided for backward
-compatibility. Don't use it. It will be removed in a future version
-of @acronym{GPGME}.
+The function @code{gpgme_op_revuid_start} initiates a
+@code{gpgme_op_revuid} operation; see there for details. It must
+be completed by calling @code{gpgme_wait} on the context.
+@xref{Waiting For Completion}.
-@deftypefun void gpgme_key_release (@w{gpgme_key_t @var{key}})
-The function @code{gpgme_key_release} is equivalent to
-@code{gpgme_key_unref}.
@end deftypefun
-@node Generating Keys
-@subsection Generating Keys
-@cindex key, creation
-@cindex key ring, add
+@c
+@c gpgme_op_genkey
+@c
+@deftypefun gpgme_error_t gpgme_op_genkey @
+ (@w{gpgme_ctx_t @var{ctx}}, @
+ @w{const char *@var{parms}}, @
+ @w{gpgme_data_t @var{public}}, @
+ @w{gpgme_data_t @var{secret}})
-@deftypefun gpgme_error_t gpgme_op_genkey (@w{gpgme_ctx_t @var{ctx}}, @w{const char *@var{parms}}, @w{gpgme_data_t @var{public}}, @w{gpgme_data_t @var{secret}})
The function @code{gpgme_op_genkey} generates a new key pair in the
context @var{ctx}. The meaning of @var{public} and @var{secret}
depends on the crypto backend.
-GnuPG does not support @var{public} and @var{secret}, they should be
+GPG does not support @var{public} and @var{secret}, they should be
@code{NULL}. GnuPG will generate a key pair and add it to the
standard key ring. The fingerprint of the generated key is available
with @code{gpgme_op_genkey_result}.
@@ -3629,6 +3847,7 @@ if no key was created by the backend.
@end deftypefun
@deftypefun gpgme_error_t gpgme_op_genkey_start (@w{gpgme_ctx_t @var{ctx}}, @w{const char *@var{parms}}, @w{gpgme_data_t @var{public}}, @w{gpgme_data_t @var{secret}})
+
The function @code{gpgme_op_genkey_start} initiates a
@code{gpgme_op_genkey} operation. It can be completed by calling
@code{gpgme_wait} on the context. @xref{Waiting For Completion}.
@@ -3640,7 +3859,12 @@ operation could be started successfully, @code{GPG_ERR_INV_VALUE} if
@code{NULL}.
@end deftypefun
+
+@c
+@c gpgme_op_genkey_result
+@c
@deftp {Data type} {gpgme_genkey_result_t}
+
This is a pointer to a structure used to store the result of a
@code{gpgme_op_genkey} operation. After successfully generating a
key, you can retrieve the pointer to the result with
@@ -3649,22 +3873,34 @@ members:
@table @code
@item unsigned int primary : 1
-This is a flag that is set to 1 if a primary key was created and to 0
+This flag is set to 1 if a primary key was created and to 0
if not.
@item unsigned int sub : 1
-This is a flag that is set to 1 if a subkey was created and to 0
-if not.
+This flag is set to 1 if a subkey was created and to 0 if not.
+
+@item unsigned int uid : 1
+This flag is set to 1 if a user ID was created and to 0 if not.
@item char *fpr
This is the fingerprint of the key that was created. If both a
-primary and a sub key were generated, the fingerprint of the primary
+primary and a subkey were generated, the fingerprint of the primary
key will be returned. If the crypto engine does not provide the
fingerprint, @code{fpr} will be a null pointer.
+
+@item gpgme_data_t pubkey
+This will eventually be used to return the public key. It is
+currently not used.
+
+@item gpgme_data_t seckey
+This will eventually be used to return the secret key. It is
+currently not used.
+
@end table
@end deftp
@deftypefun gpgme_genkey_result_t gpgme_op_genkey_result (@w{gpgme_ctx_t @var{ctx}})
+
The function @code{gpgme_op_genkey_result} returns a
@code{gpgme_genkey_result_t} pointer to a structure holding the result of
a @code{gpgme_op_genkey} operation. The pointer is only valid if the
@@ -3672,9 +3908,110 @@ last operation on the context was a @code{gpgme_op_genkey} or
@code{gpgme_op_genkey_start} operation, and if this operation finished
successfully. The returned pointer is only valid until the next
operation is started on the context.
+
+@end deftypefun
+
+
+@c
+@c SIGNING KEYS
+@c
+@node Signing Keys
+@subsection Signing Keys
+@cindex key, signing
+
+Key signatures are a unique concept of the OpenPGP protocol. They can
+be used to certify the validity of a key and are used to create the
+Web-of-Trust (WoT). Instead of using the @code{gpgme_op_interact}
+function along with a finite state machine, GPGME provides a
+convenient function to create key signatures when using modern GnuPG
+versions.
+
+
+@c
+@c gpgme_op_keysign
+@c
+@deftypefun gpgme_error_t gpgme_op_keysign @
+ (@w{gpgme_ctx_t @var{ctx}}, @
+ @w{gpgme_key_t @var{key}}, @
+ @w{const char *@var{userid}}, @
+ @w{unsigned long @var{expires}}, @
+ @w{unsigned int @var{flags}});
+
+The function @code{gpgme_op_keysign} adds a new key signature to the
+public key @var{KEY}. This function requires at least version 2.1.12 of
+GnuPG.
+
+@var{CTX} is the usual context which describes the protocol to use
+(which must be OpenPGP) and has also the list of signer keys to be
+used for the signature. The common case is to use the default key for
+signing other keys. If another key or more than one key shall be used
+for a key signature, @code{gpgme_signers_add} can be used.
+@xref{Selecting Signers}.
+
+@var{key} specifies the key to operate on.
+
+@var{userid} selects the user ID or user IDs to be signed. If
+@var{userid} is set to @code{NULL} all valid user IDs are signed. The
+user ID must be given verbatim because the engine does an exact and
+case sensitive match. Thus the @code{uid} field from the user ID
+object (@code{gpgme_user_id_t}) is to be used. To select more than
+one user ID put them all into one string separated by linefeeds
+characters (@code{\n}) and set the flag @code{GPGME_KEYSIGN_LFSEP}.
+
+@var{expires} can be set to the number of seconds since Epoch of the
+desired expiration date in UTC for the new signature. The common case
+is to use 0 to not set an expiration date. However, if the
+configuration of the engine defines a default expiration for key
+signatures, that is still used unless the flag
+@code{GPGME_KEYSIGN_NOEXPIRE} is used. Note that this parameter takes
+an unsigned long value and not a @code{time_t} to avoid problems on
+systems which use a signed 32 bit @code{time_t}. Note further that
+the OpenPGP protocol uses 32 bit values for timestamps and thus can
+only encode dates up to the year 2106.
+
+@var{flags} can be set to the bit-wise OR of the following flags:
+
+@table @code
+@item GPGME_KEYSIGN_LOCAL
+Instead of creating an exportable key signature, create a key
+signature which is is marked as non-exportable.
+
+@item GPGME_KEYSIGN_LFSEP
+Although linefeeds are uncommon in user IDs this flag is required to
+explicitly declare that @var{userid} may contain several linefeed
+separated user IDs.
+
+@item GPGME_KEYSIGN_NOEXPIRE
+Force the creation of a key signature without an expiration date. This
+overrides @var{expire} and any local configuration of the engine.
+
+@end table
+
+The function returns zero on success, @code{GPG_ERR_NOT_SUPPORTED} if
+the engine does not support the command, or a bunch of other error
+codes.
+
+@end deftypefun
+
+
+@deftypefun gpgme_error_t gpgme_op_keysign_start @
+ (@w{gpgme_ctx_t @var{ctx}}, @
+ @w{gpgme_key_t @var{key}}, @
+ @w{const char *@var{userid}}, @
+ @w{unsigned long @var{expires}}, @
+ @w{unsigned int @var{flags}});
+
+The function @code{gpgme_op_keysign_start} initiates a
+@code{gpgme_op_keysign} operation; see there for details. It must
+be completed by calling @code{gpgme_wait} on the context.
+@xref{Waiting For Completion}.
+
@end deftypefun
+@c
+@c EXPORTING KEYS
+@c
@node Exporting Keys
@subsection Exporting Keys
@cindex key, export
@@ -3787,7 +4124,7 @@ for the context @var{ctx}, or, if that is not set, by the encoding
specified for @var{keydata}.
The keys to export are taken form the @code{NULL} terminated array
-@var{keys}. Only keys of the the currently selected protocol of
+@var{keys}. Only keys of the currently selected protocol of
@var{ctx} which do have a fingerprint set are considered for export.
Other keys specified by the @var{keys} are ignored. In particular
OpenPGP keys retrieved via an external key listing are not included.
@@ -3860,7 +4197,7 @@ permanent which have been retrieved from an external source (i.e. using
for the usual workaround of exporting and then importing a key to make
an X.509 key permanent.}
-Only keys of the the currently selected protocol of @var{ctx} are
+Only keys of the currently selected protocol of @var{ctx} are
considered for import. Other keys specified by the @var{keys} are
ignored. As of now all considered keys must have been retrieved using
the same method, that is the used key listing mode must be identical.
@@ -3947,34 +4284,34 @@ The number of keys without user ID.
@item int imported
The total number of imported keys.
-@item imported_rsa
+@item int imported_rsa
The number of imported RSA keys.
-@item unchanged
+@item int unchanged
The number of unchanged keys.
-@item new_user_ids
+@item int new_user_ids
The number of new user IDs.
-@item new_sub_keys
+@item int new_sub_keys
The number of new sub keys.
-@item new_signatures
+@item int new_signatures
The number of new signatures.
-@item new_revocations
+@item int new_revocations
The number of new revocations.
-@item secret_read
+@item int secret_read
The total number of secret keys read.
-@item secret_imported
+@item int secret_imported
The number of imported secret keys.
-@item secret_unchanged
+@item int secret_unchanged
The number of unchanged secret keys.
-@item not_imported
+@item int not_imported
The number of keys not imported.
@item gpgme_import_status_t imports
@@ -3993,24 +4330,6 @@ successfully. The returned pointer is only valid until the next
operation is started on the context.
@end deftypefun
-The following interface is deprecated and only provided for backward
-compatibility. Don't use it. It will be removed in a future version
-of @acronym{GPGME}.
-
-@deftypefun gpgme_error_t gpgme_op_import_ext (@w{gpgme_ctx_t @var{ctx}}, @w{gpgme_data_t @var{keydata}}, @w{int *@var{nr}})
-The function @code{gpgme_op_import_ext} is equivalent to:
-
-@example
- gpgme_error_t err = gpgme_op_import (ctx, keydata);
- if (!err)
- @{
- gpgme_import_result_t result = gpgme_op_import_result (ctx);
- *nr = result->considered;
- @}
-@end example
-@end deftypefun
-
-
@node Deleting Keys
@subsection Deleting Keys
@cindex key, delete
@@ -4043,7 +4362,7 @@ operation was started successfully, and @code{GPG_ERR_INV_VALUE} if
@node Changing Passphrases
-@subsection Changing Passphrases
+@subsection Changing Passphrases
@cindex passphrase, change
@deftypefun gpgme_error_t gpgme_op_passwd @
@@ -4077,27 +4396,104 @@ could not be started.
@end deftypefun
+@c
+@c CHANGING TOFU DATA
+@c
+@node Changing TOFU Data
+@subsection Changing TOFU Data
+@cindex validity, TOFU
+
+The OpenPGP engine features a Trust-On-First-Use (TOFU) key validation
+model. For resolving clonflics it is necessary to declare the policy
+for a key. See the GnuPG manual for details on the TOFU
+implementation.
+
+@deftp {Data type} {enum gpgme_tofu_policy_t}
+@tindex gpgme_tofu_policy_t
+The @code{gpgme_tofu_policy_t} type specifies the set of possible
+policy values that are supported by @acronym{GPGME}:
+
+@table @code
+@item GPGME_TOFU_POLICY_AUTO
+Set the policy to ``auto''.
+@item GPGME_TOFU_POLICY_GOOD
+Set the policy to ``goog''.
+@item GPGME_TOFU_POLICY_BAD
+Set the policy to ``bad''.
+@item GPGME_TOFU_POLICY_ASK
+Set the policy to ``ask''.
+@item GPGME_TOFU_POLICY_UNKNOWN
+Set the policy to ``unknown''.
+@end table
+
+@end deftp
+
+To change the policy for a key the following functions can be used:
+
+@deftypefun gpgme_error_t gpgme_op_tofu_policy @
+ (@w{gpgme_ctx_t @var{ctx}}, @
+ @w{const gpgme_key_t @var{key}}, @
+ @w{gpgme_tofu_policy_t @var{policy}})
+
+The function @code{gpgme_op_tofu_policy} changes the TOFU policy of
+@var{key}. The valid values for @var{policy} are listed above. As of
+now this function does only work for OpenPGP and requires at least
+version 2.1.10 of GnuPG.
+
+The function returns zero on success, @code{GPG_ERR_NOT_SUPPORTED} if
+the engine does not support the command, or a bunch of other error
+codes.
+
+@end deftypefun
+
+@deftypefun gpgme_error_t gpgme_op_tofu_policy_start @
+ (@w{gpgme_ctx_t @var{ctx}}, @
+ @w{const gpgme_key_t @var{key}}, @
+ @w{gpgme_tofu_policy_t @var{policy}})
+
+The function @code{gpgme_op_tofu_policy_start} initiates a
+@code{gpgme_op_tofu_policy} operation. It can be completed by calling
+@code{gpgme_wait} on the context. @xref{Waiting For Completion}.
+
+The function returns @code{0} if the operation was started successfully,
+and an error code if one of the arguments is not valid or the oepration
+could not be started.
+
+@end deftypefun
+
+
@node Advanced Key Editing
@subsection Advanced Key Editing
@cindex key, edit
-@deftp {Data type} {gpgme_error_t (*gpgme_edit_cb_t) (@w{void *@var{handle}}, @w{gpgme_status_code_t @var{status}}, @w{const char *@var{args}}, @w{int @var{fd}})}
-@tindex gpgme_edit_cb_t
-The @code{gpgme_edit_cb_t} type is the type of functions which
-@acronym{GPGME} calls if it a key edit operation is on-going. The
-status code @var{status} and the argument line @var{args} are passed
-through by @acronym{GPGME} from the crypto engine. The file
-descriptor @var{fd} is -1 for normal status messages. If @var{status}
-indicates a command rather than a status message, the response to the
-command should be written to @var{fd}. The @var{handle} is provided
-by the user at start of operation.
-
-The function should return @code{GPG_ERR_NO_ERROR} or an error value.
+@deftp {Data type} {gpgme_error_t (*gpgme_interact_cb_t) @
+ (@w{void *@var{handle}}, @
+ @w{const char *@var{status}}, @
+ @w{const char *@var{args}}, @
+ @w{int @var{fd}})}
+@tindex gpgme_interact_cb_t
+The @code{gpgme_interact_cb_t} type is the type of functions which
+@acronym{GPGME} calls if it a key interact operation is on-going. The
+status keyword @var{status} and the argument line @var{args} are
+passed through by @acronym{GPGME} from the crypto engine. An empty
+string represents EOF. The file descriptor @var{fd} is -1 for normal
+status messages. If @var{status} indicates a command rather than a
+status message, the response to the command should be written to
+@var{fd}. The @var{handle} is provided by the user at start of
+operation.
+
+The function should return @code{GPG_ERR_FALSE} if it did not handle
+the status code, @code{0} for success, or any other error value.
@end deftp
-@deftypefun gpgme_error_t gpgme_op_edit (@w{gpgme_ctx_t @var{ctx}}, @w{gpgme_key_t @var{key}}, @w{gpgme_edit_cb_t @var{fnc}}, @w{void *@var{handle}}, @w{gpgme_data_t @var{out}})
-The function @code{gpgme_op_edit} processes the key @var{KEY}
-interactively, using the edit callback function @var{FNC} with the
+@deftypefun gpgme_error_t gpgme_op_interact (@w{gpgme_ctx_t @var{ctx}}, @
+ @w{gpgme_key_t @var{key}}, @
+ @w{unsigned int @var{flags}}, @
+ @w{gpgme_interact_cb_t @var{fnc}}, @
+ @w{void *@var{handle}}, @
+ @w{gpgme_data_t @var{out}})
+The function @code{gpgme_op_interact} processes the key @var{KEY}
+interactively, using the interact callback function @var{FNC} with the
handle @var{HANDLE}. The callback is invoked for every status and
command request from the crypto engine. The output of the crypto
engine is written to the data object @var{out}.
@@ -4106,39 +4502,40 @@ Note that the protocol between the callback function and the crypto
engine is specific to the crypto engine and no further support in
implementing this protocol correctly is provided by @acronym{GPGME}.
-The function returns the error code @code{GPG_ERR_NO_ERROR} if the
-edit operation completes successfully, @code{GPG_ERR_INV_VALUE} if
-@var{ctx} or @var{key} is not a valid pointer, and any error returned
-by the crypto engine or the edit callback handler.
-@end deftypefun
+@var{flags} modifies the behaviour of the function; the only defined
+bit value is:
-@deftypefun gpgme_error_t gpgme_op_edit_start (@w{gpgme_ctx_t @var{ctx}}, @w{gpgme_key_t @var{key}}, @w{gpgme_edit_cb_t @var{fnc}}, @w{void *@var{handle}}, @w{gpgme_data_t @var{out}})
-The function @code{gpgme_op_edit_start} initiates a
-@code{gpgme_op_edit} operation. It can be completed by calling
-@code{gpgme_wait} on the context. @xref{Waiting For Completion}.
-
-The function returns the error code @code{GPG_ERR_NO_ERROR} if the
-operation was started successfully, and @code{GPG_ERR_INV_VALUE} if
-@var{ctx} or @var{key} is not a valid pointer.
-@end deftypefun
+@table @code
+@item GPGME_INTERACT_CARD
+This is used for smartcard based keys and uses gpg’s
+@code{--card-edit} command.
+@end table
-@deftypefun gpgme_error_t gpgme_op_card_edit (@w{gpgme_ctx_t @var{ctx}}, @w{gpgme_key_t @var{key}}, @w{gpgme_edit_cb_t @var{fnc}}, @w{void *@var{handle}}, @w{gpgme_data_t @var{out}})
-The function @code{gpgme_op_card_edit} is analogous to
-@code{gpgme_op_edit}, but should be used to process the smart card corresponding to the key @var{key}.
+The function returns @code{0} if the edit operation completes
+successfully, @code{GPG_ERR_INV_VALUE} if @var{ctx} or @var{key} is
+not a valid pointer, and any error returned by the crypto engine or
+the edit callback handler.
@end deftypefun
-@deftypefun gpgme_error_t gpgme_op_card_edit_start (@w{gpgme_ctx_t @var{ctx}}, @w{gpgme_key_t @var{key}}, @w{gpgme_edit_cb_t @var{fnc}}, @w{void *@var{handle}}, @w{gpgme_data_t @var{out}})
-The function @code{gpgme_op_card_edit_start} initiates a
-@code{gpgme_op_card_edit} operation. It can be completed by calling
+
+@deftypefun gpgme_error_t gpgme_op_interact_start (@w{gpgme_ctx_t @var{ctx}}, @
+ @w{gpgme_key_t @var{key}}, @
+ @w{unsigned int @var{flags}}, @
+ @w{gpgme_interact_cb_t @var{fnc}}, @
+ @w{void *@var{handle}}, @
+ @w{gpgme_data_t @var{out}})
+The function @code{gpgme_op_interact_start} initiates a
+@code{gpgme_op_interact} operation. It can be completed by calling
@code{gpgme_wait} on the context. @xref{Waiting For Completion}.
-The function returns the error code @code{GPG_ERR_NO_ERROR} if the
-operation was started successfully, and @code{GPG_ERR_INV_VALUE} if
-@var{ctx} or @var{key} is not a valid pointer.
+The function returns @code{0} if the operation was started
+successfully, and @code{GPG_ERR_INV_VALUE} if @var{ctx} or @var{key}
+is not a valid pointer.
@end deftypefun
+
@node Trust Item Management
@section Trust Item Management
@cindex trust item
@@ -4173,7 +4570,6 @@ The user name if @code{type} is 2.
@menu
* Listing Trust Items:: Browsing the list of available trust items.
-* Information About Trust Items:: Requesting information about trust items.
* Manipulating Trust Items:: Operations on trust items.
@end menu
@@ -4230,47 +4626,6 @@ time during the operation there was not enough memory available.
@end deftypefun
-@node Information About Trust Items
-@subsection Information About Trust Items
-@cindex trust item, information about
-@cindex trust item, attributes
-@cindex attributes, of a trust item
-
-The following interfaces are deprecated and only provided for backward
-compatibility. Don't use them. They will be removed in a future
-version of @acronym{GPGME}.
-
-Trust items have attributes which can be queried using the interfaces
-below. The attribute identifiers are shared with those for key
-attributes. @xref{Information About Keys}.
-
-@deftypefun {const char *} gpgme_trust_item_get_string_attr (@w{gpgme_trust_item_t @var{item}}, @w{gpgme_attr_t @var{what}}, @w{const void *@var{reserved}}, @w{int @var{idx}})
-The function @code{gpgme_trust_item_get_string_attr} returns the value
-of the string-representable attribute @var{what} of trust item
-@var{item}. The arguments @var{idx} and @var{reserved} are reserved
-for later use and should be @code{0} and @code{NULL} respectively.
-
-The string returned is only valid as long as the key is valid.
-
-The function returns @code{0} if an attribute can't be returned as a
-string, @var{key} is not a valid pointer, @var{idx} out of range,
-or @var{reserved} not @code{NULL}.
-@end deftypefun
-
-@deftypefun int gpgme_trust_item_get_int_attr (@w{gpgme_trust_item_t @var{item}}, @w{gpgme_attr_t @var{what}}, @w{const void *@var{reserved}}, @w{int @var{idx}})
-The function @code{gpgme_trust_item_get_int_attr} returns the value of
-the number-representable attribute @var{what} of trust item
-@var{item}. If the attribute occurs more than once in the trust item,
-the index is specified by @var{idx}. However, currently no such
-attribute exists, so @var{idx} should be @code{0}. The argument
-@var{reserved} is reserved for later use and should be @code{NULL}.
-
-The function returns @code{0} if the attribute can't be returned as a
-number, @var{key} is not a valid pointer, @var{idx} out of range,
-or @var{reserved} not @code{NULL}.
-@end deftypefun
-
-
@node Manipulating Trust Items
@subsection Manipulating Trust Items
@cindex trust item, manipulation
@@ -4288,16 +4643,6 @@ released.
@end deftypefun
-The following interface is deprecated and only provided for backward
-compatibility. Don't use it. It will be removed in a future version
-of @acronym{GPGME}.
-
-@deftypefun void gpgme_trust_item_release (@w{gpgme_trust_item_t @var{item}})
-The function @code{gpgme_trust_item_release} is an alias for
-@code{gpgme_trust_item_unref}.
-@end deftypefun
-
-
@node Crypto Operations
@section Crypto Operations
@cindex cryptographic operation
@@ -4676,6 +5021,13 @@ The hash algorithm used to create this signature.
@item char *pka_address
The mailbox from the PKA information or @code{NULL}.
+
+@item gpgme_key_t key
+An object describing the key used to create the signature. This key
+object may be incomplete in that it only conveys information
+availabale directly with a signature. It may also be @code{NULL} if
+such information is not readily available.
+
@end table
@end deftp
@@ -4712,238 +5064,6 @@ the context.
@end deftypefun
-The following interfaces are deprecated and only provided for backward
-compatibility. Don't use them. They will be removed in a future
-version of @acronym{GPGME}.
-
-@deftp {Data type} {enum gpgme_sig_stat_t}
-@tindex gpgme_sig_stat_t
-The @code{gpgme_sig_stat_t} type holds the result of a signature check, or
-the combined result of all signatures. The following results are
-possible:
-
-@table @code
-@item GPGME_SIG_STAT_NONE
-This status should not occur in normal operation.
-
-@item GPGME_SIG_STAT_GOOD
-This status indicates that the signature is valid. For the combined
-result this status means that all signatures are valid.
-
-@item GPGME_SIG_STAT_GOOD_EXP
-This status indicates that the signature is valid but expired. For
-the combined result this status means that all signatures are valid
-and expired.
-
-@item GPGME_SIG_STAT_GOOD_EXPKEY
-This status indicates that the signature is valid but the key used to
-verify the signature has expired. For the combined result this status
-means that all signatures are valid and all keys are expired.
-
-@item GPGME_SIG_STAT_BAD
-This status indicates that the signature is invalid. For the combined
-result this status means that all signatures are invalid.
-
-@item GPGME_SIG_STAT_NOKEY
-This status indicates that the signature could not be verified due to
-a missing key. For the combined result this status means that all
-signatures could not be checked due to missing keys.
-
-@item GPGME_SIG_STAT_NOSIG
-This status indicates that the signature data provided was not a real
-signature.
-
-@item GPGME_SIG_STAT_ERROR
-This status indicates that there was some other error which prevented
-the signature verification.
-
-@item GPGME_SIG_STAT_DIFF
-For the combined result this status means that at least two signatures
-have a different status. You can get each key's status with
-@code{gpgme_get_sig_status}.
-@end table
-@end deftp
-
-@deftypefun {const char *} gpgme_get_sig_status (@w{gpgme_ctx_t @var{ctx}}, @w{int @var{idx}}, @w{gpgme_sig_stat_t *@var{r_stat}}, @w{time_t *@var{r_created}})
-The function @code{gpgme_get_sig_status} is equivalent to:
-
-@example
- gpgme_verify_result_t result;
- gpgme_signature_t sig;
-
- result = gpgme_op_verify_result (ctx);
- sig = result->signatures;
-
- while (sig && idx)
- @{
- sig = sig->next;
- idx--;
- @}
- if (!sig || idx)
- return NULL;
-
- if (r_stat)
- @{
- switch (gpg_err_code (sig->status))
- @{
- case GPG_ERR_NO_ERROR:
- *r_stat = GPGME_SIG_STAT_GOOD;
- break;
-
- case GPG_ERR_BAD_SIGNATURE:
- *r_stat = GPGME_SIG_STAT_BAD;
- break;
-
- case GPG_ERR_NO_PUBKEY:
- *r_stat = GPGME_SIG_STAT_NOKEY;
- break;
-
- case GPG_ERR_NO_DATA:
- *r_stat = GPGME_SIG_STAT_NOSIG;
- break;
-
- case GPG_ERR_SIG_EXPIRED:
- *r_stat = GPGME_SIG_STAT_GOOD_EXP;
- break;
-
- case GPG_ERR_KEY_EXPIRED:
- *r_stat = GPGME_SIG_STAT_GOOD_EXPKEY;
- break;
-
- default:
- *r_stat = GPGME_SIG_STAT_ERROR;
- break;
- @}
- @}
- if (r_created)
- *r_created = sig->timestamp;
- return sig->fpr;
-@end example
-@end deftypefun
-
-@deftypefun {const char *} gpgme_get_sig_string_attr (@w{gpgme_ctx_t @var{ctx}}, @w{int @var{idx}}, @w{gpgme_attr_t @var{what}}, @w{int @var{whatidx}})
-The function @code{gpgme_get_sig_string_attr} is equivalent to:
-
-@example
- gpgme_verify_result_t result;
- gpgme_signature_t sig;
-
- result = gpgme_op_verify_result (ctx);
- sig = result->signatures;
-
- while (sig && idx)
- @{
- sig = sig->next;
- idx--;
- @}
- if (!sig || idx)
- return NULL;
-
- switch (what)
- @{
- case GPGME_ATTR_FPR:
- return sig->fpr;
-
- case GPGME_ATTR_ERRTOK:
- if (whatidx == 1)
- return sig->wrong_key_usage ? "Wrong_Key_Usage" : "";
- else
- return "";
- default:
- break;
- @}
-
- return NULL;
-@end example
-@end deftypefun
-
-@deftypefun {const char *} gpgme_get_sig_ulong_attr (@w{gpgme_ctx_t @var{ctx}}, @w{int @var{idx}}, @w{gpgme_attr_t @var{waht}}, @w{int @var{whatidx}})
-The function @code{gpgme_get_sig_ulong_attr} is equivalent to:
-
-@example
- gpgme_verify_result_t result;
- gpgme_signature_t sig;
-
- result = gpgme_op_verify_result (ctx);
- sig = result->signatures;
-
- while (sig && idx)
- @{
- sig = sig->next;
- idx--;
- @}
- if (!sig || idx)
- return 0;
-
- switch (what)
- @{
- case GPGME_ATTR_CREATED:
- return sig->timestamp;
-
- case GPGME_ATTR_EXPIRE:
- return sig->exp_timestamp;
-
- case GPGME_ATTR_VALIDITY:
- return (unsigned long) sig->validity;
-
- case GPGME_ATTR_SIG_STATUS:
- switch (sig->status)
- @{
- case GPG_ERR_NO_ERROR:
- return GPGME_SIG_STAT_GOOD;
-
- case GPG_ERR_BAD_SIGNATURE:
- return GPGME_SIG_STAT_BAD;
-
- case GPG_ERR_NO_PUBKEY:
- return GPGME_SIG_STAT_NOKEY;
-
- case GPG_ERR_NO_DATA:
- return GPGME_SIG_STAT_NOSIG;
-
- case GPG_ERR_SIG_EXPIRED:
- return GPGME_SIG_STAT_GOOD_EXP;
-
- case GPG_ERR_KEY_EXPIRED:
- return GPGME_SIG_STAT_GOOD_EXPKEY;
-
- default:
- return GPGME_SIG_STAT_ERROR;
- @}
-
- case GPGME_ATTR_SIG_SUMMARY:
- return sig->summary;
-
- default:
- break;
- @}
- return 0;
-@end example
-@end deftypefun
-
-@deftypefun {const char *} gpgme_get_sig_key (@w{gpgme_ctx_t @var{ctx}}, @w{int @var{idx}}, @w{gpgme_key_t *@var{r_key}})
-The function @code{gpgme_get_sig_key} is equivalent to:
-
-@example
- gpgme_verify_result_t result;
- gpgme_signature_t sig;
-
- result = gpgme_op_verify_result (ctx);
- sig = result->signatures;
-
- while (sig && idx)
- @{
- sig = sig->next;
- idx--;
- @}
- if (!sig || idx)
- return gpg_error (GPG_ERR_EOF);
-
- return gpgme_get_key (ctx, sig->fpr, r_key, 0);
-@end example
-@end deftypefun
-
-
@node Decrypt and Verify
@subsection Decrypt and Verify
@cindex decryption and verification
@@ -5013,6 +5133,11 @@ set is changed).
@cindex signature, selecting signers
@cindex signers, selecting
+The key or the keys used to create a signature are stored in the
+context. The following functions can be used to manipulate this list.
+If no signer has been set into the context a default key is used for
+signing.
+
@deftypefun void gpgme_signers_clear (@w{gpgme_ctx_t @var{ctx}})
The function @code{gpgme_signers_clear} releases a reference for each
key on the signers list and removes the list of signers from the
@@ -5271,6 +5396,12 @@ protocol to prepare an encryption (i.e. sending the
@code{GPGME_ENCRYPT_EXPECT_SIGN} symbol the UI Server is advised to
also expect a sign command.
+@item GPGME_ENCRYPT_SYMMETRIC
+The @code{GPGME_ENCRYPT_SYMMETRIC} symbol specifies that the
+output should be additionally encrypted symmetically even
+if recipients are provided. This feature is only supported for
+for the OpenPGP crypto engine.
+
@end table
If @code{GPG_ERR_UNUSABLE_PUBKEY} is returned, some recipients in
@@ -5369,6 +5500,7 @@ Here are some support functions which are sometimes useful.
@menu
* Running other Programs:: Running other Programs
+* Using the Assuan protocol:: Using the Assuan protocol
@end menu
@@ -5383,7 +5515,7 @@ which are part of the GnuPG system but are not directly accessible
with the GPGME API.
-@deftypefun gpgme_error_t gpgme_op_spawn
+@deftypefun gpgme_error_t gpgme_op_spawn @
(@w{gpgme_ctx_t @var{ctx}}, @w{const char *@var{file}}, @
@w{const char *@var{argv}[]}, @w{gpgme_data_t @var{datain}}, @
@w{gpgme_data_t @var{dataout}}, @w{gpgme_data_t @var{dataerr}}, @
@@ -5413,7 +5545,7 @@ the foreground.
@end table
@end deftypefun
-@deftypefun gpgme_error_t gpgme_op_spawn_start
+@deftypefun gpgme_error_t gpgme_op_spawn_start @
(@w{gpgme_ctx_t @var{ctx}}, @w{const char *@var{file}}, @
@w{const char *@var{argv}[]}, @w{gpgme_data_t @var{datain}}, @
@w{gpgme_data_t @var{dataout}}, @w{gpgme_data_t @var{dataerr}}, @
@@ -5423,6 +5555,83 @@ This is the asynchronous variant of @code{gpgme_op_spawn}.
@end deftypefun
+@node Using the Assuan protocol
+@subsection Using the Assuan protocol
+
+The Assuan protocol can be used to talk to arbitrary Assuan servers.
+By default it is connected to the GnuPG agent, but it may be connected
+to arbitrary servers by using @code{gpgme_ctx_set_engine_info},
+passing the location of the servers socket as @var{file_name}
+argument, and an empty string as @var{home_dir} argument.
+
+The Assuan protocol functions use three kinds of callbacks to transfer
+data:
+
+@deftp {Data type} {gpgme_error_t (*gpgme_assuan_data_cb_t) @
+ (@w{void *@var{opaque}}, @w{const void *@var{data}}, @
+ @w{size_t @var{datalen}})}
+
+This callback receives any data sent by the server. @var{opaque} is
+the pointer passed to @code{gpgme_op_assuan_transact_start},
+@var{data} of length @var{datalen} refers to the data sent.
+@end deftp
+
+@deftp {Data type} {gpgme_error_t (*gpgme_assuan_inquire_cb_t) @
+ (@w{void *@var{opaque}}, @w{const char *@var{name}}, @
+ @w{const char *@var{args}}, @w{gpgme_data_t *@var{r_data}})}
+
+This callback is used to provide additional data to the Assuan server.
+@var{opaque} is the pointer passed to
+@code{gpgme_op_assuan_transact_start}, @var{name} and @var{args}
+specify what kind of data the server requested, and @var{r_data} is
+used to return the actual data.
+
+Note: Returning data is currently not implemented in @acronym{GPGME}.
+@end deftp
+
+@deftp {Data type} {gpgme_error_t (*gpgme_assuan_status_cb_t) @
+ (@w{void *@var{opaque}}, @w{const char *@var{status}}, @
+ @w{const char *@var{args}})}
+
+This callback receives any status lines sent by the server.
+@var{opaque} is the pointer passed to
+@code{gpgme_op_assuan_transact_start}, @var{status} and @var{args}
+denote the status update sent.
+@end deftp
+
+@deftypefun gpgme_error_t gpgme_op_assuan_transact_start @
+ (@w{gpgme_ctx_t @var{ctx}}, @w{const char *@var{command}}, @
+ @w{gpgme_assuan_data_cb_t @var{data_cb}}, @
+ @w{void * @var{data_cb_value}}, @
+ @w{gpgme_assuan_inquire_cb_t @var{inquire_cb}}, @
+ @w{void * @var{inquire_cb_value}}, @
+ @w{gpgme_assuan_status_cb_t @var{status_cb}}, @
+ @w{void * @var{status_cb_value}})
+
+Send the Assuan @var{command} and return results via the callbacks.
+Any callback may be @code{NULL}. The result of the operation may be
+retrieved using @code{gpgme_wait_ext}.
+
+Asynchronous variant.
+@end deftypefun
+
+@deftypefun gpgme_error_t gpgme_op_assuan_transact_ext @
+ (@w{gpgme_ctx_t @var{ctx}}, @w{const char *@var{command}}, @
+ @w{gpgme_assuan_data_cb_t @var{data_cb}}, @
+ @w{void * @var{data_cb_value}}, @
+ @w{gpgme_assuan_inquire_cb_t @var{inquire_cb}}, @
+ @w{void * @var{inquire_cb_value}}, @
+ @w{gpgme_assuan_status_cb_t @var{status_cb}}, @
+ @w{void * @var{status_cb_value}}, @
+ @w{gpgme_error_t *@var{op_err}})
+
+Send the Assuan @var{command} and return results via the callbacks.
+The result of the operation is returned in @var{op_err}.
+
+Synchronous variant.
+@end deftypefun
+
+
@node Run Control
@section Run Control
@cindex run control
@@ -6124,16 +6333,16 @@ operation in the context @var{ctx}. This only works if you use the
global event loop or your own event loop.
If you use the global event loop, you must not call @code{gpgme_wait}
-or @code{gpgme_wait} during cancellation. After successful
+during cancellation. After successful
cancellation, you can call @code{gpgme_wait} (optionally waiting on
@var{ctx}), and the context @var{ctx} will appear as if it had
finished with the error code @code{GPG_ERR_CANCEL}.
-If you use your an external event loop, you must ensure that no I/O
+If you use an external event loop, you must ensure that no I/O
callbacks are invoked for this context (for example by halting the
event loop). On successful cancellation, all registered I/O callbacks
for this context will be unregistered, and a @code{GPGME_EVENT_DONE}
-event with the error code @code{GPG_ERR_CANCEL} will be signaled.
+event with the error code @code{GPG_ERR_CANCEL} will be signalled.
The function returns an error code if the cancellation failed (in this
case the state of @var{ctx} is not modified).
@@ -6198,6 +6407,682 @@ your application. If you are asked to send a log file, make sure that
you run your tests only with play data.
+@node Deprecated Functions
+@appendix Deprecated Functions
+@cindex deprecated
+
+For backward compatibility @acronym{GPGME} has a number of functions,
+data types and constants which are deprecated and should not be used
+anymore. We document here those which are really old to help
+understanding old code and to allow migration to their modern
+counterparts.
+
+@strong{Warning:} These interfaces will be removed in a future version
+of @acronym{GPGME}.
+
+@deftypefun void gpgme_key_release (@w{gpgme_key_t @var{key}})
+The function @code{gpgme_key_release} is equivalent to
+@code{gpgme_key_unref}.
+@end deftypefun
+
+@deftypefun void gpgme_trust_item_release (@w{gpgme_trust_item_t @var{item}})
+The function @code{gpgme_trust_item_release} is an alias for
+@code{gpgme_trust_item_unref}.
+@end deftypefun
+
+
+@deftypefun gpgme_error_t gpgme_op_import_ext (@w{gpgme_ctx_t @var{ctx}}, @w{gpgme_data_t @var{keydata}}, @w{int *@var{nr}})
+The function @code{gpgme_op_import_ext} is equivalent to:
+
+@example
+ gpgme_error_t err = gpgme_op_import (ctx, keydata);
+ if (!err)
+ @{
+ gpgme_import_result_t result = gpgme_op_import_result (ctx);
+ *nr = result->considered;
+ @}
+@end example
+@end deftypefun
+
+
+@deftp {Data type} {gpgme_error_t (*gpgme_edit_cb_t) @
+ (@w{void *@var{handle}}, @
+ @w{gpgme_status_code_t @var{status}}, @
+ @w{const char *@var{args}}, @
+ @w{int @var{fd}})}
+@tindex gpgme_edit_cb_t
+The @code{gpgme_edit_cb_t} type is the type of functions which
+@acronym{GPGME} calls if it a key edit operation is on-going. The
+status code @var{status} and the argument line @var{args} are passed
+through by @acronym{GPGME} from the crypto engine. The file
+descriptor @var{fd} is -1 for normal status messages. If @var{status}
+indicates a command rather than a status message, the response to the
+command should be written to @var{fd}. The @var{handle} is provided
+by the user at start of operation.
+
+The function should return @code{GPG_ERR_FALSE} if it did not handle
+the status code, @code{0} for success, or any other error value.
+@end deftp
+
+@deftypefun gpgme_error_t gpgme_op_edit (@w{gpgme_ctx_t @var{ctx}}, @w{gpgme_key_t @var{key}}, @w{gpgme_edit_cb_t @var{fnc}}, @w{void *@var{handle}}, @w{gpgme_data_t @var{out}})
+Note: This function is deprecated, please use
+@code{gpgme_op_interact} instead.
+
+The function @code{gpgme_op_edit} processes the key @var{KEY}
+interactively, using the edit callback function @var{FNC} with the
+handle @var{HANDLE}. The callback is invoked for every status and
+command request from the crypto engine. The output of the crypto
+engine is written to the data object @var{out}.
+
+Note that the protocol between the callback function and the crypto
+engine is specific to the crypto engine and no further support in
+implementing this protocol correctly is provided by @acronym{GPGME}.
+
+The function returns the error code @code{GPG_ERR_NO_ERROR} if the
+edit operation completes successfully, @code{GPG_ERR_INV_VALUE} if
+@var{ctx} or @var{key} is not a valid pointer, and any error returned
+by the crypto engine or the edit callback handler.
+@end deftypefun
+
+@deftypefun gpgme_error_t gpgme_op_edit_start (@w{gpgme_ctx_t @var{ctx}}, @w{gpgme_key_t @var{key}}, @w{gpgme_edit_cb_t @var{fnc}}, @w{void *@var{handle}}, @w{gpgme_data_t @var{out}})
+Note: This function is deprecated, please use
+@code{gpgme_op_interact_start} instead.
+
+The function @code{gpgme_op_edit_start} initiates a
+@code{gpgme_op_edit} operation. It can be completed by calling
+@code{gpgme_wait} on the context. @xref{Waiting For Completion}.
+
+The function returns the error code @code{GPG_ERR_NO_ERROR} if the
+operation was started successfully, and @code{GPG_ERR_INV_VALUE} if
+@var{ctx} or @var{key} is not a valid pointer.
+@end deftypefun
+
+
+@deftypefun gpgme_error_t gpgme_op_card_edit (@w{gpgme_ctx_t @var{ctx}}, @w{gpgme_key_t @var{key}}, @w{gpgme_edit_cb_t @var{fnc}}, @w{void *@var{handle}}, @w{gpgme_data_t @var{out}})
+Note: This function is deprecated, please use @code{gpgme_op_interact}
+with the flag @code{GPGME_INTERACT_CARD} instead.
+
+The function @code{gpgme_op_card_edit} is analogous to
+@code{gpgme_op_edit}, but should be used to process the smart card corresponding to the key @var{key}.
+@end deftypefun
+
+@deftypefun gpgme_error_t gpgme_op_card_edit_start (@w{gpgme_ctx_t @var{ctx}}, @w{gpgme_key_t @var{key}}, @w{gpgme_edit_cb_t @var{fnc}}, @w{void *@var{handle}}, @w{gpgme_data_t @var{out}})
+Note: This function is deprecated, please use @code{gpgme_op_interact_start}
+with the flag @code{GPGME_INTERACT_CARD} instead.
+
+The function @code{gpgme_op_card_edit_start} initiates a
+@code{gpgme_op_card_edit} operation. It can be completed by calling
+@code{gpgme_wait} on the context. @xref{Waiting For Completion}.
+
+The function returns the error code @code{GPG_ERR_NO_ERROR} if the
+operation was started successfully, and @code{GPG_ERR_INV_VALUE} if
+@var{ctx} or @var{key} is not a valid pointer.
+@end deftypefun
+
+
+
+@deftypefun gpgme_error_t gpgme_data_new_with_read_cb (@w{gpgme_data_t *@var{dh}}, @w{int (*@var{readfunc})} (@w{void *@var{hook}}, @w{char *@var{buffer}}, @w{size_t @var{count}}, @w{size_t *@var{nread}}), @w{void *@var{hook_value}})
+The function @code{gpgme_data_new_with_read_cb} creates a new
+@code{gpgme_data_t} object and uses the callback function @var{readfunc}
+to retrieve the data on demand. As the callback function can supply
+the data in any way it wants, this is the most flexible data type
+@acronym{GPGME} provides. However, it can not be used to write data.
+
+The callback function receives @var{hook_value} as its first argument
+whenever it is invoked. It should return up to @var{count} bytes in
+@var{buffer}, and return the number of bytes actually read in
+@var{nread}. It may return @code{0} in @var{nread} if no data is
+currently available. To indicate @code{EOF} the function should
+return with an error code of @code{-1} and set @var{nread} to
+@code{0}. The callback function may support to reset its internal
+read pointer if it is invoked with @var{buffer} and @var{nread} being
+@code{NULL} and @var{count} being @code{0}.
+
+The function returns the error code @code{GPG_ERR_NO_ERROR} if the
+data object was successfully created, @code{GPG_ERR_INV_VALUE} if
+@var{dh} or @var{readfunc} is not a valid pointer, and
+@code{GPG_ERR_ENOMEM} if not enough memory is available.
+@end deftypefun
+
+@deftypefun gpgme_error_t gpgme_data_rewind (@w{gpgme_data_t @var{dh}})
+The function @code{gpgme_data_rewind} is equivalent to:
+
+@example
+ return (gpgme_data_seek (dh, 0, SEEK_SET) == -1)
+ ? gpgme_error_from_errno (errno) : 0;
+@end example
+@end deftypefun
+
+
+@deftp {Data type} gpgme_attr_t
+The @code{gpgme_attr_t} type is used to specify a key or trust item
+attribute. The following attributes are defined:
+
+@table @code
+@item GPGME_ATTR_KEYID
+This is the key ID of a sub key. It is representable as a string.
+
+For trust items, the trust item refers to the key with this ID.
+
+@item GPGME_ATTR_FPR
+This is the fingerprint of a sub key. It is representable as a
+string.
+
+@item GPGME_ATTR_ALGO
+This is the crypto algorithm for which the sub key can be used. It
+is representable as a string and as a number. The numbers correspond
+to the @code{enum gcry_pk_algos} values in the gcrypt library.
+
+@item GPGME_ATTR_LEN
+This is the key length of a sub key. It is representable as a
+number.
+
+@item GPGME_ATTR_CREATED
+This is the timestamp at creation time of a sub key. It is
+representable as a number.
+
+@item GPGME_ATTR_EXPIRE
+This is the expiration time of a sub key. It is representable as a
+number.
+
+@item GPGME_ATTR_OTRUST
+XXX FIXME (also for trust items)
+
+@item GPGME_ATTR_USERID
+This is a user ID. There can be more than one user IDs in a
+@var{gpgme_key_t} object. The first one (with index 0) is the primary
+user ID. The user ID is representable as a number.
+
+For trust items, this is the user ID associated with this trust item.
+
+@item GPGME_ATTR_NAME
+This is the name belonging to a user ID. It is representable as a string.
+
+@item GPGME_ATTR_EMAIL
+This is the email address belonging to a user ID. It is representable
+as a string.
+
+@item GPGME_ATTR_COMMENT
+This is the comment belonging to a user ID. It is representable as a
+string.
+
+@item GPGME_ATTR_VALIDITY
+This is the validity belonging to a user ID. It is representable as a
+string and as a number. See below for a list of available validities.
+
+For trust items, this is the validity that is associated with this
+trust item.
+
+@item GPGME_ATTR_UID_REVOKED
+This specifies if a user ID is revoked. It is representable as a
+number, and is @code{1} if the user ID is revoked, and @code{0}
+otherwise.
+
+@item GPGME_ATTR_UID_INVALID
+This specifies if a user ID is invalid. It is representable as a
+number, and is @code{1} if the user ID is invalid, and @code{0}
+otherwise.
+
+@item GPGME_ATTR_LEVEL
+This is the trust level of a trust item.
+
+@item GPGME_ATTR_TYPE
+This returns information about the type of key. For the string function
+this will eother be "PGP" or "X.509". The integer function returns 0
+for PGP and 1 for X.509. It is also used for the type of a trust item.
+
+@item GPGME_ATTR_IS_SECRET
+This specifies if the key is a secret key. It is representable as a
+number, and is @code{1} if the key is revoked, and @code{0} otherwise.
+
+@item GPGME_ATTR_KEY_REVOKED
+This specifies if a sub key is revoked. It is representable as a
+number, and is @code{1} if the key is revoked, and @code{0} otherwise.
+
+@item GPGME_ATTR_KEY_INVALID
+This specifies if a sub key is invalid. It is representable as a
+number, and is @code{1} if the key is invalid, and @code{0} otherwise.
+
+@item GPGME_ATTR_KEY_EXPIRED
+This specifies if a sub key is expired. It is representable as a
+number, and is @code{1} if the key is expired, and @code{0} otherwise.
+
+@item GPGME_ATTR_KEY_DISABLED
+This specifies if a sub key is disabled. It is representable as a
+number, and is @code{1} if the key is disabled, and @code{0} otherwise.
+
+@item GPGME_ATTR_KEY_CAPS
+This is a description of the capabilities of a sub key. It is
+representable as a string. The string contains the letter ``e'' if
+the key can be used for encryption, ``s'' if the key can be used for
+signatures, and ``c'' if the key can be used for certifications.
+
+@item GPGME_ATTR_CAN_ENCRYPT
+This specifies if a sub key can be used for encryption. It is
+representable as a number, and is @code{1} if the sub key can be used
+for encryption, and @code{0} otherwise.
+
+@item GPGME_ATTR_CAN_SIGN
+This specifies if a sub key can be used to create data signatures. It
+is representable as a number, and is @code{1} if the sub key can be
+used for signatures, and @code{0} otherwise.
+
+@item GPGME_ATTR_CAN_CERTIFY
+This specifies if a sub key can be used to create key certificates.
+It is representable as a number, and is @code{1} if the sub key can be
+used for certifications, and @code{0} otherwise.
+
+@item GPGME_ATTR_SERIAL
+The X.509 issuer serial attribute of the key. It is representable as
+a string.
+
+@item GPGME_ATTR_ISSUE
+The X.509 issuer name attribute of the key. It is representable as a
+string.
+
+@item GPGME_ATTR_CHAINID
+The X.509 chain ID can be used to build the certification chain. It
+is representable as a string.
+@end table
+@end deftp
+
+@deftypefun {const char *} gpgme_key_get_string_attr (@w{gpgme_key_t @var{key}}, @w{gpgme_attr_t @var{what}}, @w{const void *@var{reserved}}, @w{int @var{idx}})
+The function @code{gpgme_key_get_string_attr} returns the value of the
+string-representable attribute @var{what} of key @var{key}. If the
+attribute is an attribute of a sub key or an user ID, @var{idx}
+specifies the sub key or user ID of which the attribute value is
+returned. The argument @var{reserved} is reserved for later use and
+should be @code{NULL}.
+
+The string returned is only valid as long as the key is valid.
+
+The function returns @code{0} if an attribute can't be returned as a
+string, @var{key} is not a valid pointer, @var{idx} out of range,
+or @var{reserved} not @code{NULL}.
+@end deftypefun
+
+@deftypefun {unsigned long} gpgme_key_get_ulong_attr (@w{gpgme_key_t @var{key}}, @w{gpgme_attr_t @var{what}}, @w{const void *@var{reserved}}, @w{int @var{idx}})
+The function @code{gpgme_key_get_ulong_attr} returns the value of the
+number-representable attribute @var{what} of key @var{key}. If the
+attribute is an attribute of a sub key or an user ID, @var{idx}
+specifies the sub key or user ID of which the attribute value is
+returned. The argument @var{reserved} is reserved for later use and
+should be @code{NULL}.
+
+The function returns @code{0} if the attribute can't be returned as a
+number, @var{key} is not a valid pointer, @var{idx} out of range, or
+@var{reserved} not @code{NULL}.
+@end deftypefun
+
+
+@c
+@c Key Signatures
+@c
+The signatures on a key are only available if the key was retrieved
+via a listing operation with the @code{GPGME_KEYLIST_MODE_SIGS} mode
+enabled, because it is expensive to retrieve all signatures of a key.
+
+So, before using the below interfaces to retrieve the signatures on a
+key, you have to make sure that the key was listed with signatures
+enabled. One convenient, but blocking, way to do this is to use the
+function @code{gpgme_get_key}.
+
+@deftp {Data type} gpgme_attr_t
+The @code{gpgme_attr_t} type is used to specify a key signature
+attribute. The following attributes are defined:
+
+@table @code
+@item GPGME_ATTR_KEYID
+This is the key ID of the key which was used for the signature. It is
+representable as a string.
+
+@item GPGME_ATTR_ALGO
+This is the crypto algorithm used to create the signature. It is
+representable as a string and as a number. The numbers correspond to
+the @code{enum gcry_pk_algos} values in the gcrypt library.
+
+@item GPGME_ATTR_CREATED
+This is the timestamp at creation time of the signature. It is
+representable as a number.
+
+@item GPGME_ATTR_EXPIRE
+This is the expiration time of the signature. It is representable as
+a number.
+
+@item GPGME_ATTR_USERID
+This is the user ID associated with the signing key. The user ID is
+representable as a number.
+
+@item GPGME_ATTR_NAME
+This is the name belonging to a user ID. It is representable as a string.
+
+@item GPGME_ATTR_EMAIL
+This is the email address belonging to a user ID. It is representable
+as a string.
+
+@item GPGME_ATTR_COMMENT
+This is the comment belonging to a user ID. It is representable as a
+string.
+
+@item GPGME_ATTR_KEY_REVOKED
+This specifies if a key signature is a revocation signature. It is
+representable as a number, and is @code{1} if the key is revoked, and
+@code{0} otherwise.
+
+@c @item GPGME_ATTR_KEY_EXPIRED
+@c This specifies if a key signature is expired. It is representable as
+@c a number, and is @code{1} if the key is revoked, and @code{0}
+@c otherwise.
+@c
+@item GPGME_ATTR_SIG_CLASS
+This specifies the signature class of a key signature. It is
+representable as a number. The meaning is specific to the crypto
+engine.
+
+@item GPGME_ATTR_SIG_CLASS
+This specifies the signature class of a key signature. It is
+representable as a number. The meaning is specific to the crypto
+engine.
+
+@item GPGME_ATTR_SIG_STATUS
+This is the same value as returned by @code{gpgme_get_sig_status}.
+@end table
+@end deftp
+
+@deftypefun {const char *} gpgme_key_sig_get_string_attr (@w{gpgme_key_t @var{key}}, @w{int @var{uid_idx}}, @w{gpgme_attr_t @var{what}}, @w{const void *@var{reserved}}, @w{int @var{idx}})
+The function @code{gpgme_key_sig_get_string_attr} returns the value of
+the string-representable attribute @var{what} of the signature
+@var{idx} on the user ID @var{uid_idx} in the key @var{key}. The
+argument @var{reserved} is reserved for later use and should be
+@code{NULL}.
+
+The string returned is only valid as long as the key is valid.
+
+The function returns @code{0} if an attribute can't be returned as a
+string, @var{key} is not a valid pointer, @var{uid_idx} or @var{idx}
+out of range, or @var{reserved} not @code{NULL}.
+@end deftypefun
+
+@deftypefun {unsigned long} gpgme_key_sig_get_ulong_attr (@w{gpgme_key_t @var{key}}, @w{int @var{uid_idx}}, @w{gpgme_attr_t @var{what}}, @w{const void *@var{reserved}}, @w{int @var{idx}})
+The function @code{gpgme_key_sig_get_ulong_attr} returns the value of
+the number-representable attribute @var{what} of the signature
+@var{idx} on the user ID @var{uid_idx} in the key @var{key}. The
+argument @var{reserved} is reserved for later use and should be
+@code{NULL}.
+
+The function returns @code{0} if an attribute can't be returned as a
+string, @var{key} is not a valid pointer, @var{uid_idx} or @var{idx}
+out of range, or @var{reserved} not @code{NULL}.
+@end deftypefun
+
+
+@c node Information About Trust Items
+@c subsection Information About Trust Items
+@c cindex trust item, information about
+@c cindex trust item, attributes
+@c cindex attributes, of a trust item
+
+Trust items have attributes which can be queried using the interfaces
+below. The attribute identifiers are shared with those for key
+attributes. @xref{Information About Keys}.
+
+@deftypefun {const char *} gpgme_trust_item_get_string_attr (@w{gpgme_trust_item_t @var{item}}, @w{gpgme_attr_t @var{what}}, @w{const void *@var{reserved}}, @w{int @var{idx}})
+The function @code{gpgme_trust_item_get_string_attr} returns the value
+of the string-representable attribute @var{what} of trust item
+@var{item}. The arguments @var{idx} and @var{reserved} are reserved
+for later use and should be @code{0} and @code{NULL} respectively.
+
+The string returned is only valid as long as the key is valid.
+
+The function returns @code{0} if an attribute can't be returned as a
+string, @var{key} is not a valid pointer, @var{idx} out of range,
+or @var{reserved} not @code{NULL}.
+@end deftypefun
+
+@deftypefun int gpgme_trust_item_get_int_attr (@w{gpgme_trust_item_t @var{item}}, @w{gpgme_attr_t @var{what}}, @w{const void *@var{reserved}}, @w{int @var{idx}})
+The function @code{gpgme_trust_item_get_int_attr} returns the value of
+the number-representable attribute @var{what} of trust item
+@var{item}. If the attribute occurs more than once in the trust item,
+the index is specified by @var{idx}. However, currently no such
+attribute exists, so @var{idx} should be @code{0}. The argument
+@var{reserved} is reserved for later use and should be @code{NULL}.
+
+The function returns @code{0} if the attribute can't be returned as a
+number, @var{key} is not a valid pointer, @var{idx} out of range,
+or @var{reserved} not @code{NULL}.
+@end deftypefun
+
+
+@deftp {Data type} {enum gpgme_sig_stat_t}
+@tindex gpgme_sig_stat_t
+The @code{gpgme_sig_stat_t} type holds the result of a signature check, or
+the combined result of all signatures. The following results are
+possible:
+
+@table @code
+@item GPGME_SIG_STAT_NONE
+This status should not occur in normal operation.
+
+@item GPGME_SIG_STAT_GOOD
+This status indicates that the signature is valid. For the combined
+result this status means that all signatures are valid.
+
+@item GPGME_SIG_STAT_GOOD_EXP
+This status indicates that the signature is valid but expired. For
+the combined result this status means that all signatures are valid
+and expired.
+
+@item GPGME_SIG_STAT_GOOD_EXPKEY
+This status indicates that the signature is valid but the key used to
+verify the signature has expired. For the combined result this status
+means that all signatures are valid and all keys are expired.
+
+@item GPGME_SIG_STAT_BAD
+This status indicates that the signature is invalid. For the combined
+result this status means that all signatures are invalid.
+
+@item GPGME_SIG_STAT_NOKEY
+This status indicates that the signature could not be verified due to
+a missing key. For the combined result this status means that all
+signatures could not be checked due to missing keys.
+
+@item GPGME_SIG_STAT_NOSIG
+This status indicates that the signature data provided was not a real
+signature.
+
+@item GPGME_SIG_STAT_ERROR
+This status indicates that there was some other error which prevented
+the signature verification.
+
+@item GPGME_SIG_STAT_DIFF
+For the combined result this status means that at least two signatures
+have a different status. You can get each key's status with
+@code{gpgme_get_sig_status}.
+@end table
+@end deftp
+
+@deftypefun {const char *} gpgme_get_sig_status (@w{gpgme_ctx_t @var{ctx}}, @w{int @var{idx}}, @w{gpgme_sig_stat_t *@var{r_stat}}, @w{time_t *@var{r_created}})
+The function @code{gpgme_get_sig_status} is equivalent to:
+
+@example
+ gpgme_verify_result_t result;
+ gpgme_signature_t sig;
+
+ result = gpgme_op_verify_result (ctx);
+ sig = result->signatures;
+
+ while (sig && idx)
+ @{
+ sig = sig->next;
+ idx--;
+ @}
+ if (!sig || idx)
+ return NULL;
+
+ if (r_stat)
+ @{
+ switch (gpg_err_code (sig->status))
+ @{
+ case GPG_ERR_NO_ERROR:
+ *r_stat = GPGME_SIG_STAT_GOOD;
+ break;
+
+ case GPG_ERR_BAD_SIGNATURE:
+ *r_stat = GPGME_SIG_STAT_BAD;
+ break;
+
+ case GPG_ERR_NO_PUBKEY:
+ *r_stat = GPGME_SIG_STAT_NOKEY;
+ break;
+
+ case GPG_ERR_NO_DATA:
+ *r_stat = GPGME_SIG_STAT_NOSIG;
+ break;
+
+ case GPG_ERR_SIG_EXPIRED:
+ *r_stat = GPGME_SIG_STAT_GOOD_EXP;
+ break;
+
+ case GPG_ERR_KEY_EXPIRED:
+ *r_stat = GPGME_SIG_STAT_GOOD_EXPKEY;
+ break;
+
+ default:
+ *r_stat = GPGME_SIG_STAT_ERROR;
+ break;
+ @}
+ @}
+ if (r_created)
+ *r_created = sig->timestamp;
+ return sig->fpr;
+@end example
+@end deftypefun
+
+@deftypefun {const char *} gpgme_get_sig_string_attr (@w{gpgme_ctx_t @var{ctx}}, @w{int @var{idx}}, @w{gpgme_attr_t @var{what}}, @w{int @var{whatidx}})
+The function @code{gpgme_get_sig_string_attr} is equivalent to:
+
+@example
+ gpgme_verify_result_t result;
+ gpgme_signature_t sig;
+
+ result = gpgme_op_verify_result (ctx);
+ sig = result->signatures;
+
+ while (sig && idx)
+ @{
+ sig = sig->next;
+ idx--;
+ @}
+ if (!sig || idx)
+ return NULL;
+
+ switch (what)
+ @{
+ case GPGME_ATTR_FPR:
+ return sig->fpr;
+
+ case GPGME_ATTR_ERRTOK:
+ if (whatidx == 1)
+ return sig->wrong_key_usage ? "Wrong_Key_Usage" : "";
+ else
+ return "";
+ default:
+ break;
+ @}
+
+ return NULL;
+@end example
+@end deftypefun
+
+@deftypefun {const char *} gpgme_get_sig_ulong_attr (@w{gpgme_ctx_t @var{ctx}}, @w{int @var{idx}}, @w{gpgme_attr_t @var{waht}}, @w{int @var{whatidx}})
+The function @code{gpgme_get_sig_ulong_attr} is equivalent to:
+
+@example
+ gpgme_verify_result_t result;
+ gpgme_signature_t sig;
+
+ result = gpgme_op_verify_result (ctx);
+ sig = result->signatures;
+
+ while (sig && idx)
+ @{
+ sig = sig->next;
+ idx--;
+ @}
+ if (!sig || idx)
+ return 0;
+
+ switch (what)
+ @{
+ case GPGME_ATTR_CREATED:
+ return sig->timestamp;
+
+ case GPGME_ATTR_EXPIRE:
+ return sig->exp_timestamp;
+
+ case GPGME_ATTR_VALIDITY:
+ return (unsigned long) sig->validity;
+
+ case GPGME_ATTR_SIG_STATUS:
+ switch (sig->status)
+ @{
+ case GPG_ERR_NO_ERROR:
+ return GPGME_SIG_STAT_GOOD;
+
+ case GPG_ERR_BAD_SIGNATURE:
+ return GPGME_SIG_STAT_BAD;
+
+ case GPG_ERR_NO_PUBKEY:
+ return GPGME_SIG_STAT_NOKEY;
+
+ case GPG_ERR_NO_DATA:
+ return GPGME_SIG_STAT_NOSIG;
+
+ case GPG_ERR_SIG_EXPIRED:
+ return GPGME_SIG_STAT_GOOD_EXP;
+
+ case GPG_ERR_KEY_EXPIRED:
+ return GPGME_SIG_STAT_GOOD_EXPKEY;
+
+ default:
+ return GPGME_SIG_STAT_ERROR;
+ @}
+
+ case GPGME_ATTR_SIG_SUMMARY:
+ return sig->summary;
+
+ default:
+ break;
+ @}
+ return 0;
+@end example
+@end deftypefun
+
+@deftypefun {const char *} gpgme_get_sig_key (@w{gpgme_ctx_t @var{ctx}}, @w{int @var{idx}}, @w{gpgme_key_t *@var{r_key}})
+The function @code{gpgme_get_sig_key} is equivalent to:
+
+@example
+ gpgme_verify_result_t result;
+ gpgme_signature_t sig;
+
+ result = gpgme_op_verify_result (ctx);
+ sig = result->signatures;
+
+ while (sig && idx)
+ @{
+ sig = sig->next;
+ idx--;
+ @}
+ if (!sig || idx)
+ return gpg_error (GPG_ERR_EOF);
+
+ return gpgme_get_key (ctx, sig->fpr, r_key, 0);
+@end example
+@end deftypefun
+
+
+
+
@include lesser.texi
diff --git a/doc/mkdefsinc.c b/doc/mkdefsinc.c
new file mode 100644
index 0000000..0f30d93
--- /dev/null
+++ b/doc/mkdefsinc.c
@@ -0,0 +1,310 @@
+/* mkdefsinc.c - Tool to create defs.inc
+ * Copyright (C) 2015 g10 Code GmbH
+ *
+ * This file is free software; as a special exception the author gives
+ * unlimited permission to copy and/or distribute it, with or without
+ * modifications, as long as this notice is preserved.
+ *
+ * This file is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY, to the extent permitted by law; without even the
+ * implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
+ */
+
+/* This tool needs to be build with command line supplied -D options
+ for the various directory variables. It is easier to do this in
+ build file than to use fragile make rules and a template file. */
+
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <errno.h>
+#include <time.h>
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <unistd.h>
+
+#define PGM "mkdefsinc"
+
+/* We include config.h after all include files because the config.h
+ values are not valid for the build platform but we need some values
+ nevertheless. */
+#include "config.h"
+
+
+static int verbose;
+
+
+/* The usual free wrapper. */
+static void
+xfree (void *a)
+{
+ if (a)
+ free (a);
+}
+
+
+static char *
+xmalloc (size_t n)
+{
+ char *p;
+
+ p = malloc (n);
+ if (!p)
+ {
+ fputs (PGM ": out of core\n", stderr);
+ exit (1);
+ }
+ return p;
+}
+
+
+static char *
+xstrdup (const char *string)
+{
+ char *p;
+
+ p = xmalloc (strlen (string)+1);
+ strcpy (p, string);
+ return p;
+}
+
+
+/* Return a malloced string with the last modification date of the
+ FILES. Returns NULL on error. */
+static char *
+get_date_from_files (char **files)
+{
+ const char *file;
+ const char *usedfile = NULL;
+ struct stat sb;
+ struct tm *tp;
+ int errors = 0;
+ time_t stamp = 0;
+ char *result;
+
+ for (; (file = *files); files++)
+ {
+ if (!*file || !strcmp (file, ".") || !strcmp (file, ".."))
+ continue;
+ if (stat (file, &sb))
+ {
+ fprintf (stderr, PGM ": stat failed for '%s': %s\n",
+ file, strerror (errno));
+ errors = 1;
+ continue;
+ }
+ if (sb.st_mtime > stamp)
+ {
+ stamp = sb.st_mtime;
+ usedfile = file;
+ }
+ }
+ if (errors)
+ exit (1);
+
+ if (usedfile)
+ fprintf (stderr, PGM ": taking date from '%s'\n", usedfile);
+
+ tp = gmtime (&stamp);
+ if (!tp)
+ return NULL;
+ result = xmalloc (4+1+2+1+2+1);
+ snprintf (result, 4+1+2+1+2+1, "%04d-%02d-%02d",
+ tp->tm_year + 1900, tp->tm_mon+1, tp->tm_mday);
+ return result;
+}
+
+
+/* We need to escape file names for Texinfo. */
+static void
+print_filename (const char *prefix, const char *name)
+{
+ const char *s;
+
+ fputs (prefix, stdout);
+ for (s=name; *s; s++)
+ switch (*s)
+ {
+ case '@': fputs ("@atchar{}", stdout); break;
+ case '{': fputs ("@lbracechar{}", stdout); break;
+ case '}': fputs ("@rbracechar{}", stdout); break;
+ case ',': fputs ("@comma{}", stdout); break;
+ case '\\':fputs ("@backslashchar{}", stdout); break;
+ case '#': fputs ("@hashchar{}", stdout); break;
+ default: putchar (*s); break;
+ }
+ putchar('\n');
+}
+
+
+int
+main (int argc, char **argv)
+{
+ int last_argc = -1;
+ char *opt_date = NULL;
+ int monthoff;
+ char *p, *pend;
+ size_t n;
+
+ /* Option parsing. */
+ if (argc)
+ {
+ argc--; argv++;
+ }
+ while (argc && last_argc != argc )
+ {
+ last_argc = argc;
+ if (!strcmp (*argv, "--"))
+ {
+ argc--; argv++;
+ break;
+ }
+ else if (!strcmp (*argv, "--help"))
+ {
+ fputs ("Usage: " PGM " [OPTION] [FILES]\n"
+ "Create defs.inc file.\nOptions:\n"
+ " -C DIR Change to DIR before doing anything\n"
+ " --date STRING Take publication date from STRING\n"
+ " --verbose Enable extra informational output\n"
+ " --help Display this help and exit\n"
+ , stdout);
+ exit (0);
+ }
+ else if (!strcmp (*argv, "--verbose"))
+ {
+ verbose = 1;
+ argc--; argv++;
+ }
+ else if (!strcmp (*argv, "-C"))
+ {
+ argc--; argv++;
+ if (argc)
+ {
+ if (chdir (*argv))
+ {
+ fprintf (stderr, PGM ": chdir to '%s' failed: %s\n",
+ *argv, strerror (errno));
+ exit (1);
+ }
+ argc--; argv++;
+ }
+ }
+ else if (!strcmp (*argv, "--date"))
+ {
+ argc--; argv++;
+ if (argc)
+ {
+ opt_date = xstrdup (*argv);
+ argc--; argv++;
+ }
+ }
+ else if (!strncmp (*argv, "--", 2))
+ {
+ fprintf (stderr, PGM ": unknown option '%s'\n", *argv);
+ exit (1);
+ }
+ }
+
+ if (opt_date && *opt_date)
+ {
+ time_t stamp;
+ struct tm *tp;
+
+ if (*opt_date == '2' && strlen (opt_date) >= 10
+ && opt_date[4] == '-' && opt_date[7] == '-')
+ {
+ opt_date[10] = 0;
+ }
+ else if ((stamp = strtoul (opt_date, NULL, 10)) > 0
+ && (tp = gmtime (&stamp)))
+ {
+ p = xmalloc (4+1+2+1+2+1);
+ snprintf (p, 4+1+2+1+2+1, "%04d-%02d-%02d",
+ tp->tm_year + 1900, tp->tm_mon+1, tp->tm_mday);
+ xfree (opt_date);
+ opt_date = p;
+ }
+ else
+ {
+ fprintf (stderr, PGM ": bad date '%s'\n", opt_date);
+ exit (1);
+ }
+ }
+ else
+ {
+ xfree (opt_date);
+ opt_date = argc? get_date_from_files (argv) : NULL;
+ }
+ if (!opt_date)
+ {
+ opt_date = xstrdup ("unknown");
+ monthoff = 0;
+ }
+ else
+ {
+ const char *month = "?";
+
+ switch (atoi (opt_date+5))
+ {
+ case 1: month = "January"; break;
+ case 2: month = "February"; break;
+ case 3: month = "March"; break;
+ case 4: month = "April"; break;
+ case 5: month = "May"; break;
+ case 6: month = "June"; break;
+ case 7: month = "July"; break;
+ case 8: month = "August"; break;
+ case 9: month = "September"; break;
+ case 10: month = "October"; break;
+ case 11: month = "November"; break;
+ case 12: month = "December"; break;
+ }
+ n = strlen (opt_date) + strlen (month) + 2 + 1;
+ p = xmalloc (n);
+ snprintf (p, n, "%d %n%s %d",
+ atoi (opt_date+8), &monthoff, month, atoi (opt_date));
+ xfree (opt_date);
+ opt_date = p;
+ }
+
+
+ fputs ("@c defs.inc -*- texinfo -*-\n"
+ "@c Common and build specific constants for the manuals.\n"
+ "@c This file has been created by " PGM ".\n\n", stdout);
+
+ fputs ("@ifclear defsincincluded\n"
+ "@set defsincincluded 1\n\n", stdout);
+
+
+ fputs ("\n@c Flags\n\n", stdout);
+
+ fputs ("\n@c Directories\n\n", stdout);
+
+ /* print_filename ("@set BINDIR ", GNUPG_BINDIR ); */
+
+ fputs ("\n@c Version information a la version.texi\n\n", stdout);
+
+ printf ("@set UPDATED %s\n", opt_date);
+ printf ("@set UPDATED-MONTH %s\n", opt_date + monthoff);
+ printf ("@set EDITION %s\n", PACKAGE_VERSION);
+ printf ("@set VERSION %s\n", PACKAGE_VERSION);
+
+ fputs ("\n@c Macros\n\n", stdout);
+
+ /* Trailer. */
+ fputs ("\n"
+ "@end ifclear\n"
+ "\n"
+ "@c Loc" "al Variables:\n"
+ "@c buffer-read-only: t\n"
+ "@c End:\n", stdout);
+
+ if (ferror (stdout))
+ {
+ fprintf (stderr, PGM ": error writing to stdout: %s\n", strerror (errno));
+ return 1;
+ }
+
+ return 0;
+}
diff --git a/doc/stamp-vti b/doc/stamp-vti
deleted file mode 100644
index c0e1438..0000000
--- a/doc/stamp-vti
+++ /dev/null
@@ -1,4 +0,0 @@
-@set UPDATED 26 August 2015
-@set UPDATED-MONTH August 2015
-@set EDITION 1.6.0
-@set VERSION 1.6.0
diff --git a/doc/version.texi b/doc/version.texi
deleted file mode 100644
index c0e1438..0000000
--- a/doc/version.texi
+++ /dev/null
@@ -1,4 +0,0 @@
-@set UPDATED 26 August 2015
-@set UPDATED-MONTH August 2015
-@set EDITION 1.6.0
-@set VERSION 1.6.0
diff --git a/gpgme.spec b/gpgme.spec
index e97e1db..7a269c6 100644
--- a/gpgme.spec
+++ b/gpgme.spec
@@ -1,7 +1,7 @@
# This is a template. The dist target uses it to create the real file.
Summary: GPGME - GnuPG Made Easy
Name: gpgme
-Version: 1.6.0
+Version: 1.7.0
Release: 1
URL: http://www.gnupg.org/gpgme.html
Source: ftp://ftp.gnupg.org/gcrypt/alpha/gpgme/%{name}-%{version}.tar.gz
diff --git a/lang/Makefile.am b/lang/Makefile.am
index 854d934..fd3ce4e 100644
--- a/lang/Makefile.am
+++ b/lang/Makefile.am
@@ -17,6 +17,7 @@
# License along with this program; if not, write to the Free Software
# Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
-SUBDIRS = cl
+SUBDIRS = $(ENABLED_LANGUAGES)
+DIST_SUBDIRS = cl cpp qt python
EXTRA_DIST = README
diff --git a/lang/Makefile.in b/lang/Makefile.in
index 3dc49d0..5c96b8f 100644
--- a/lang/Makefile.in
+++ b/lang/Makefile.in
@@ -100,12 +100,16 @@ subdir = lang
DIST_COMMON = $(srcdir)/Makefile.in $(srcdir)/Makefile.am \
$(top_srcdir)/build-aux/mkinstalldirs README
ACLOCAL_M4 = $(top_srcdir)/aclocal.m4
-am__aclocal_m4_deps = $(top_srcdir)/m4/glib-2.0.m4 \
- $(top_srcdir)/m4/glibc21.m4 $(top_srcdir)/m4/gnupg-ttyname.m4 \
+am__aclocal_m4_deps = $(top_srcdir)/m4/ax_cxx_compile_stdcxx.m4 \
+ $(top_srcdir)/m4/ax_pkg_swig.m4 \
+ $(top_srcdir)/m4/ax_python_devel.m4 \
+ $(top_srcdir)/m4/glib-2.0.m4 $(top_srcdir)/m4/glibc21.m4 \
+ $(top_srcdir)/m4/gnupg-ttyname.m4 \
$(top_srcdir)/m4/gpg-error.m4 $(top_srcdir)/m4/libassuan.m4 \
$(top_srcdir)/m4/libtool.m4 $(top_srcdir)/m4/ltoptions.m4 \
$(top_srcdir)/m4/ltsugar.m4 $(top_srcdir)/m4/ltversion.m4 \
- $(top_srcdir)/m4/lt~obsolete.m4 $(top_srcdir)/acinclude.m4 \
+ $(top_srcdir)/m4/lt~obsolete.m4 $(top_srcdir)/m4/pkg.m4 \
+ $(top_srcdir)/m4/qt.m4 $(top_srcdir)/acinclude.m4 \
$(top_srcdir)/configure.ac
am__configure_deps = $(am__aclocal_m4_deps) $(CONFIGURE_DEPENDENCIES) \
$(ACLOCAL_M4)
@@ -167,7 +171,6 @@ am__define_uniq_tagged_files = \
done | $(am__uniquify_input)`
ETAGS = etags
CTAGS = ctags
-DIST_SUBDIRS = $(SUBDIRS)
DISTFILES = $(DIST_COMMON) $(DIST_SOURCES) $(TEXINFOS) $(EXTRA_DIST)
am__relativize = \
dir0=`pwd`; \
@@ -208,6 +211,7 @@ BUILD_REVISION = @BUILD_REVISION@
BUILD_TIMESTAMP = @BUILD_TIMESTAMP@
CC = @CC@
CCDEPMODE = @CCDEPMODE@
+CC_FOR_BUILD = @CC_FOR_BUILD@
CFLAGS = @CFLAGS@
CPP = @CPP@
CPPFLAGS = @CPPFLAGS@
@@ -219,12 +223,14 @@ CYGPATH_W = @CYGPATH_W@
DEFS = @DEFS@
DEPDIR = @DEPDIR@
DLLTOOL = @DLLTOOL@
+DOXYGEN = @DOXYGEN@
DSYMUTIL = @DSYMUTIL@
DUMPBIN = @DUMPBIN@
ECHO_C = @ECHO_C@
ECHO_N = @ECHO_N@
ECHO_T = @ECHO_T@
EGREP = @EGREP@
+ENABLED_LANGUAGES = @ENABLED_LANGUAGES@
EXEEXT = @EXEEXT@
FGREP = @FGREP@
GITLOG_TO_CHANGELOG = @GITLOG_TO_CHANGELOG@
@@ -235,15 +241,23 @@ GLIB_LIBS = @GLIB_LIBS@
GLIB_MKENUMS = @GLIB_MKENUMS@
GOBJECT_QUERY = @GOBJECT_QUERY@
GPGME_CONFIG_API_VERSION = @GPGME_CONFIG_API_VERSION@
+GPGME_CONFIG_AVAIL_LANG = @GPGME_CONFIG_AVAIL_LANG@
GPGME_CONFIG_CFLAGS = @GPGME_CONFIG_CFLAGS@
GPGME_CONFIG_HOST = @GPGME_CONFIG_HOST@
GPGME_CONFIG_LIBS = @GPGME_CONFIG_LIBS@
+GPGME_QTTEST_CFLAGS = @GPGME_QTTEST_CFLAGS@
+GPGME_QTTEST_LIBS = @GPGME_QTTEST_LIBS@
+GPGME_QT_CFLAGS = @GPGME_QT_CFLAGS@
+GPGME_QT_LIBS = @GPGME_QT_LIBS@
GPG_ERROR_CFLAGS = @GPG_ERROR_CFLAGS@
GPG_ERROR_CONFIG = @GPG_ERROR_CONFIG@
GPG_ERROR_LIBS = @GPG_ERROR_LIBS@
GPG_ERROR_MT_CFLAGS = @GPG_ERROR_MT_CFLAGS@
GPG_ERROR_MT_LIBS = @GPG_ERROR_MT_LIBS@
+GRAPHVIZ = @GRAPHVIZ@
GREP = @GREP@
+HAVE_CXX11 = @HAVE_CXX11@
+HAVE_DOT = @HAVE_DOT@
INSTALL = @INSTALL@
INSTALL_DATA = @INSTALL_DATA@
INSTALL_PROGRAM = @INSTALL_PROGRAM@
@@ -254,10 +268,16 @@ LDFLAGS = @LDFLAGS@
LIBASSUAN_CFLAGS = @LIBASSUAN_CFLAGS@
LIBASSUAN_CONFIG = @LIBASSUAN_CONFIG@
LIBASSUAN_LIBS = @LIBASSUAN_LIBS@
+LIBGPGMEPP_LT_AGE = @LIBGPGMEPP_LT_AGE@
+LIBGPGMEPP_LT_CURRENT = @LIBGPGMEPP_LT_CURRENT@
+LIBGPGMEPP_LT_REVISION = @LIBGPGMEPP_LT_REVISION@
LIBGPGME_LT_AGE = @LIBGPGME_LT_AGE@
LIBGPGME_LT_CURRENT = @LIBGPGME_LT_CURRENT@
LIBGPGME_LT_REVISION = @LIBGPGME_LT_REVISION@
LIBOBJS = @LIBOBJS@
+LIBQGPGME_LT_AGE = @LIBQGPGME_LT_AGE@
+LIBQGPGME_LT_CURRENT = @LIBQGPGME_LT_CURRENT@
+LIBQGPGME_LT_REVISION = @LIBQGPGME_LT_REVISION@
LIBS = @LIBS@
LIBTOOL = @LIBTOOL@
LIPO = @LIPO@
@@ -267,6 +287,8 @@ MAINT = @MAINT@
MAKEINFO = @MAKEINFO@
MANIFEST_TOOL = @MANIFEST_TOOL@
MKDIR_P = @MKDIR_P@
+MOC = @MOC@
+MOC2 = @MOC2@
NEED__FILE_OFFSET_BITS = @NEED__FILE_OFFSET_BITS@
NM = @NM@
NMEDIT = @NMEDIT@
@@ -283,14 +305,27 @@ PACKAGE_URL = @PACKAGE_URL@
PACKAGE_VERSION = @PACKAGE_VERSION@
PATH_SEPARATOR = @PATH_SEPARATOR@
PKG_CONFIG = @PKG_CONFIG@
-QT4_CORE_CFLAGS = @QT4_CORE_CFLAGS@
-QT4_CORE_LIBS = @QT4_CORE_LIBS@
+PYTHON = @PYTHON@
+PYTHONS = @PYTHONS@
+PYTHON_CPPFLAGS = @PYTHON_CPPFLAGS@
+PYTHON_EXEC_PREFIX = @PYTHON_EXEC_PREFIX@
+PYTHON_EXTRA_LDFLAGS = @PYTHON_EXTRA_LDFLAGS@
+PYTHON_EXTRA_LIBS = @PYTHON_EXTRA_LIBS@
+PYTHON_LDFLAGS = @PYTHON_LDFLAGS@
+PYTHON_PLATFORM = @PYTHON_PLATFORM@
+PYTHON_PREFIX = @PYTHON_PREFIX@
+PYTHON_SITE_PKG = @PYTHON_SITE_PKG@
+PYTHON_VERSION = @PYTHON_VERSION@
+PYTHON_VERSIONS = @PYTHON_VERSIONS@
+QTCHOOSER = @QTCHOOSER@
RANLIB = @RANLIB@
RC = @RC@
SED = @SED@
SET_MAKE = @SET_MAKE@
SHELL = @SHELL@
STRIP = @STRIP@
+SWIG = @SWIG@
+SWIG_LIB = @SWIG_LIB@
SYSROOT = @SYSROOT@
VERSION = @VERSION@
VERSION_NUMBER = @VERSION_NUMBER@
@@ -339,9 +374,13 @@ mandir = @mandir@
mkdir_p = @mkdir_p@
oldincludedir = @oldincludedir@
pdfdir = @pdfdir@
+pkgpyexecdir = @pkgpyexecdir@
+pkgpythondir = @pkgpythondir@
prefix = @prefix@
program_transform_name = @program_transform_name@
psdir = @psdir@
+pyexecdir = @pyexecdir@
+pythondir = @pythondir@
sbindir = @sbindir@
sharedstatedir = @sharedstatedir@
srcdir = @srcdir@
@@ -350,7 +389,8 @@ target_alias = @target_alias@
top_build_prefix = @top_build_prefix@
top_builddir = @top_builddir@
top_srcdir = @top_srcdir@
-SUBDIRS = cl
+SUBDIRS = $(ENABLED_LANGUAGES)
+DIST_SUBDIRS = cl cpp qt python
EXTRA_DIST = README
all: all-recursive
diff --git a/lang/README b/lang/README
index da54c78..f7a1595 100644
--- a/lang/README
+++ b/lang/README
@@ -10,3 +10,6 @@ sub-directory.
Directory Language
cl Common Lisp
+cpp C++
+qt Qt-Framework API
+python Python 2 and 3 (port of PyME 0.9.0)
diff --git a/lang/cl/Makefile.in b/lang/cl/Makefile.in
index 954fc18..7a79757 100644
--- a/lang/cl/Makefile.in
+++ b/lang/cl/Makefile.in
@@ -103,12 +103,16 @@ DIST_COMMON = $(srcdir)/Makefile.in $(srcdir)/Makefile.am \
$(top_srcdir)/build-aux/mkinstalldirs $(srcdir)/gpgme.asd.in \
$(dist_clfiles_DATA) README
ACLOCAL_M4 = $(top_srcdir)/aclocal.m4
-am__aclocal_m4_deps = $(top_srcdir)/m4/glib-2.0.m4 \
- $(top_srcdir)/m4/glibc21.m4 $(top_srcdir)/m4/gnupg-ttyname.m4 \
+am__aclocal_m4_deps = $(top_srcdir)/m4/ax_cxx_compile_stdcxx.m4 \
+ $(top_srcdir)/m4/ax_pkg_swig.m4 \
+ $(top_srcdir)/m4/ax_python_devel.m4 \
+ $(top_srcdir)/m4/glib-2.0.m4 $(top_srcdir)/m4/glibc21.m4 \
+ $(top_srcdir)/m4/gnupg-ttyname.m4 \
$(top_srcdir)/m4/gpg-error.m4 $(top_srcdir)/m4/libassuan.m4 \
$(top_srcdir)/m4/libtool.m4 $(top_srcdir)/m4/ltoptions.m4 \
$(top_srcdir)/m4/ltsugar.m4 $(top_srcdir)/m4/ltversion.m4 \
- $(top_srcdir)/m4/lt~obsolete.m4 $(top_srcdir)/acinclude.m4 \
+ $(top_srcdir)/m4/lt~obsolete.m4 $(top_srcdir)/m4/pkg.m4 \
+ $(top_srcdir)/m4/qt.m4 $(top_srcdir)/acinclude.m4 \
$(top_srcdir)/configure.ac
am__configure_deps = $(am__aclocal_m4_deps) $(CONFIGURE_DEPENDENCIES) \
$(ACLOCAL_M4)
@@ -180,6 +184,7 @@ BUILD_REVISION = @BUILD_REVISION@
BUILD_TIMESTAMP = @BUILD_TIMESTAMP@
CC = @CC@
CCDEPMODE = @CCDEPMODE@
+CC_FOR_BUILD = @CC_FOR_BUILD@
CFLAGS = @CFLAGS@
CPP = @CPP@
CPPFLAGS = @CPPFLAGS@
@@ -191,12 +196,14 @@ CYGPATH_W = @CYGPATH_W@
DEFS = @DEFS@
DEPDIR = @DEPDIR@
DLLTOOL = @DLLTOOL@
+DOXYGEN = @DOXYGEN@
DSYMUTIL = @DSYMUTIL@
DUMPBIN = @DUMPBIN@
ECHO_C = @ECHO_C@
ECHO_N = @ECHO_N@
ECHO_T = @ECHO_T@
EGREP = @EGREP@
+ENABLED_LANGUAGES = @ENABLED_LANGUAGES@
EXEEXT = @EXEEXT@
FGREP = @FGREP@
GITLOG_TO_CHANGELOG = @GITLOG_TO_CHANGELOG@
@@ -207,15 +214,23 @@ GLIB_LIBS = @GLIB_LIBS@
GLIB_MKENUMS = @GLIB_MKENUMS@
GOBJECT_QUERY = @GOBJECT_QUERY@
GPGME_CONFIG_API_VERSION = @GPGME_CONFIG_API_VERSION@
+GPGME_CONFIG_AVAIL_LANG = @GPGME_CONFIG_AVAIL_LANG@
GPGME_CONFIG_CFLAGS = @GPGME_CONFIG_CFLAGS@
GPGME_CONFIG_HOST = @GPGME_CONFIG_HOST@
GPGME_CONFIG_LIBS = @GPGME_CONFIG_LIBS@
+GPGME_QTTEST_CFLAGS = @GPGME_QTTEST_CFLAGS@
+GPGME_QTTEST_LIBS = @GPGME_QTTEST_LIBS@
+GPGME_QT_CFLAGS = @GPGME_QT_CFLAGS@
+GPGME_QT_LIBS = @GPGME_QT_LIBS@
GPG_ERROR_CFLAGS = @GPG_ERROR_CFLAGS@
GPG_ERROR_CONFIG = @GPG_ERROR_CONFIG@
GPG_ERROR_LIBS = @GPG_ERROR_LIBS@
GPG_ERROR_MT_CFLAGS = @GPG_ERROR_MT_CFLAGS@
GPG_ERROR_MT_LIBS = @GPG_ERROR_MT_LIBS@
+GRAPHVIZ = @GRAPHVIZ@
GREP = @GREP@
+HAVE_CXX11 = @HAVE_CXX11@
+HAVE_DOT = @HAVE_DOT@
INSTALL = @INSTALL@
INSTALL_DATA = @INSTALL_DATA@
INSTALL_PROGRAM = @INSTALL_PROGRAM@
@@ -226,10 +241,16 @@ LDFLAGS = @LDFLAGS@
LIBASSUAN_CFLAGS = @LIBASSUAN_CFLAGS@
LIBASSUAN_CONFIG = @LIBASSUAN_CONFIG@
LIBASSUAN_LIBS = @LIBASSUAN_LIBS@
+LIBGPGMEPP_LT_AGE = @LIBGPGMEPP_LT_AGE@
+LIBGPGMEPP_LT_CURRENT = @LIBGPGMEPP_LT_CURRENT@
+LIBGPGMEPP_LT_REVISION = @LIBGPGMEPP_LT_REVISION@
LIBGPGME_LT_AGE = @LIBGPGME_LT_AGE@
LIBGPGME_LT_CURRENT = @LIBGPGME_LT_CURRENT@
LIBGPGME_LT_REVISION = @LIBGPGME_LT_REVISION@
LIBOBJS = @LIBOBJS@
+LIBQGPGME_LT_AGE = @LIBQGPGME_LT_AGE@
+LIBQGPGME_LT_CURRENT = @LIBQGPGME_LT_CURRENT@
+LIBQGPGME_LT_REVISION = @LIBQGPGME_LT_REVISION@
LIBS = @LIBS@
LIBTOOL = @LIBTOOL@
LIPO = @LIPO@
@@ -239,6 +260,8 @@ MAINT = @MAINT@
MAKEINFO = @MAKEINFO@
MANIFEST_TOOL = @MANIFEST_TOOL@
MKDIR_P = @MKDIR_P@
+MOC = @MOC@
+MOC2 = @MOC2@
NEED__FILE_OFFSET_BITS = @NEED__FILE_OFFSET_BITS@
NM = @NM@
NMEDIT = @NMEDIT@
@@ -255,14 +278,27 @@ PACKAGE_URL = @PACKAGE_URL@
PACKAGE_VERSION = @PACKAGE_VERSION@
PATH_SEPARATOR = @PATH_SEPARATOR@
PKG_CONFIG = @PKG_CONFIG@
-QT4_CORE_CFLAGS = @QT4_CORE_CFLAGS@
-QT4_CORE_LIBS = @QT4_CORE_LIBS@
+PYTHON = @PYTHON@
+PYTHONS = @PYTHONS@
+PYTHON_CPPFLAGS = @PYTHON_CPPFLAGS@
+PYTHON_EXEC_PREFIX = @PYTHON_EXEC_PREFIX@
+PYTHON_EXTRA_LDFLAGS = @PYTHON_EXTRA_LDFLAGS@
+PYTHON_EXTRA_LIBS = @PYTHON_EXTRA_LIBS@
+PYTHON_LDFLAGS = @PYTHON_LDFLAGS@
+PYTHON_PLATFORM = @PYTHON_PLATFORM@
+PYTHON_PREFIX = @PYTHON_PREFIX@
+PYTHON_SITE_PKG = @PYTHON_SITE_PKG@
+PYTHON_VERSION = @PYTHON_VERSION@
+PYTHON_VERSIONS = @PYTHON_VERSIONS@
+QTCHOOSER = @QTCHOOSER@
RANLIB = @RANLIB@
RC = @RC@
SED = @SED@
SET_MAKE = @SET_MAKE@
SHELL = @SHELL@
STRIP = @STRIP@
+SWIG = @SWIG@
+SWIG_LIB = @SWIG_LIB@
SYSROOT = @SYSROOT@
VERSION = @VERSION@
VERSION_NUMBER = @VERSION_NUMBER@
@@ -311,9 +347,13 @@ mandir = @mandir@
mkdir_p = @mkdir_p@
oldincludedir = @oldincludedir@
pdfdir = @pdfdir@
+pkgpyexecdir = @pkgpyexecdir@
+pkgpythondir = @pkgpythondir@
prefix = @prefix@
program_transform_name = @program_transform_name@
psdir = @psdir@
+pyexecdir = @pyexecdir@
+pythondir = @pythondir@
sbindir = @sbindir@
sharedstatedir = @sharedstatedir@
srcdir = @srcdir@
diff --git a/lang/cl/gpgme.asd b/lang/cl/gpgme.asd
index 9030a65..c192da7 100644
--- a/lang/cl/gpgme.asd
+++ b/lang/cl/gpgme.asd
@@ -27,7 +27,7 @@
(defsystem gpgme
:description "GnuPG Made Easy."
:author "g10 Code GmbH"
- :version "1.6.0"
+ :version "1.7.0"
:licence "GPL"
:depends-on ("cffi" "gpg-error")
:components ((:file "gpgme-package")
diff --git a/lang/cpp/Makefile.am b/lang/cpp/Makefile.am
new file mode 100644
index 0000000..7fbaca8
--- /dev/null
+++ b/lang/cpp/Makefile.am
@@ -0,0 +1,23 @@
+# Makefile.am for GPGMEPP.
+# Copyright (C) 2016 Intevation GmbH
+#
+# This file is part of GPGMEPP.
+#
+# GPGME-CL 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.
+#
+# GPGME-CL is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU Lesser General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program; if not, write to the Free Software
+# Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
+# 02111-1307, USA
+
+SUBDIRS = src
+
+EXTRA_DIST = README
diff --git a/lang/cpp/Makefile.in b/lang/cpp/Makefile.in
new file mode 100644
index 0000000..f042f77
--- /dev/null
+++ b/lang/cpp/Makefile.in
@@ -0,0 +1,709 @@
+# Makefile.in generated by automake 1.14.1 from Makefile.am.
+# @configure_input@
+
+# Copyright (C) 1994-2013 Free Software Foundation, Inc.
+
+# This Makefile.in is free software; the Free Software Foundation
+# gives unlimited permission to copy and/or distribute it,
+# with or without modifications, as long as this notice is preserved.
+
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY, to the extent permitted by law; without
+# even the implied warranty of MERCHANTABILITY or FITNESS FOR A
+# PARTICULAR PURPOSE.
+
+@SET_MAKE@
+
+# Makefile.am for GPGMEPP.
+# Copyright (C) 2016 Intevation GmbH
+#
+# This file is part of GPGMEPP.
+#
+# GPGME-CL 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.
+#
+# GPGME-CL is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU Lesser General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program; if not, write to the Free Software
+# Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
+# 02111-1307, USA
+VPATH = @srcdir@
+am__is_gnu_make = test -n '$(MAKEFILE_LIST)' && test -n '$(MAKELEVEL)'
+am__make_running_with_option = \
+ case $${target_option-} in \
+ ?) ;; \
+ *) echo "am__make_running_with_option: internal error: invalid" \
+ "target option '$${target_option-}' specified" >&2; \
+ exit 1;; \
+ esac; \
+ has_opt=no; \
+ sane_makeflags=$$MAKEFLAGS; \
+ if $(am__is_gnu_make); then \
+ sane_makeflags=$$MFLAGS; \
+ else \
+ case $$MAKEFLAGS in \
+ *\\[\ \ ]*) \
+ bs=\\; \
+ sane_makeflags=`printf '%s\n' "$$MAKEFLAGS" \
+ | sed "s/$$bs$$bs[$$bs $$bs ]*//g"`;; \
+ esac; \
+ fi; \
+ skip_next=no; \
+ strip_trailopt () \
+ { \
+ flg=`printf '%s\n' "$$flg" | sed "s/$$1.*$$//"`; \
+ }; \
+ for flg in $$sane_makeflags; do \
+ test $$skip_next = yes && { skip_next=no; continue; }; \
+ case $$flg in \
+ *=*|--*) continue;; \
+ -*I) strip_trailopt 'I'; skip_next=yes;; \
+ -*I?*) strip_trailopt 'I';; \
+ -*O) strip_trailopt 'O'; skip_next=yes;; \
+ -*O?*) strip_trailopt 'O';; \
+ -*l) strip_trailopt 'l'; skip_next=yes;; \
+ -*l?*) strip_trailopt 'l';; \
+ -[dEDm]) skip_next=yes;; \
+ -[JT]) skip_next=yes;; \
+ esac; \
+ case $$flg in \
+ *$$target_option*) has_opt=yes; break;; \
+ esac; \
+ done; \
+ test $$has_opt = yes
+am__make_dryrun = (target_option=n; $(am__make_running_with_option))
+am__make_keepgoing = (target_option=k; $(am__make_running_with_option))
+pkgdatadir = $(datadir)/@PACKAGE@
+pkgincludedir = $(includedir)/@PACKAGE@
+pkglibdir = $(libdir)/@PACKAGE@
+pkglibexecdir = $(libexecdir)/@PACKAGE@
+am__cd = CDPATH="$${ZSH_VERSION+.}$(PATH_SEPARATOR)" && cd
+install_sh_DATA = $(install_sh) -c -m 644
+install_sh_PROGRAM = $(install_sh) -c
+install_sh_SCRIPT = $(install_sh) -c
+INSTALL_HEADER = $(INSTALL_DATA)
+transform = $(program_transform_name)
+NORMAL_INSTALL = :
+PRE_INSTALL = :
+POST_INSTALL = :
+NORMAL_UNINSTALL = :
+PRE_UNINSTALL = :
+POST_UNINSTALL = :
+build_triplet = @build@
+host_triplet = @host@
+subdir = lang/cpp
+DIST_COMMON = $(srcdir)/Makefile.in $(srcdir)/Makefile.am \
+ $(top_srcdir)/build-aux/mkinstalldirs README
+ACLOCAL_M4 = $(top_srcdir)/aclocal.m4
+am__aclocal_m4_deps = $(top_srcdir)/m4/ax_cxx_compile_stdcxx.m4 \
+ $(top_srcdir)/m4/ax_pkg_swig.m4 \
+ $(top_srcdir)/m4/ax_python_devel.m4 \
+ $(top_srcdir)/m4/glib-2.0.m4 $(top_srcdir)/m4/glibc21.m4 \
+ $(top_srcdir)/m4/gnupg-ttyname.m4 \
+ $(top_srcdir)/m4/gpg-error.m4 $(top_srcdir)/m4/libassuan.m4 \
+ $(top_srcdir)/m4/libtool.m4 $(top_srcdir)/m4/ltoptions.m4 \
+ $(top_srcdir)/m4/ltsugar.m4 $(top_srcdir)/m4/ltversion.m4 \
+ $(top_srcdir)/m4/lt~obsolete.m4 $(top_srcdir)/m4/pkg.m4 \
+ $(top_srcdir)/m4/qt.m4 $(top_srcdir)/acinclude.m4 \
+ $(top_srcdir)/configure.ac
+am__configure_deps = $(am__aclocal_m4_deps) $(CONFIGURE_DEPENDENCIES) \
+ $(ACLOCAL_M4)
+mkinstalldirs = $(SHELL) $(top_srcdir)/build-aux/mkinstalldirs
+CONFIG_HEADER = $(top_builddir)/config.h
+CONFIG_CLEAN_FILES =
+CONFIG_CLEAN_VPATH_FILES =
+AM_V_P = $(am__v_P_@AM_V@)
+am__v_P_ = $(am__v_P_@AM_DEFAULT_V@)
+am__v_P_0 = false
+am__v_P_1 = :
+AM_V_GEN = $(am__v_GEN_@AM_V@)
+am__v_GEN_ = $(am__v_GEN_@AM_DEFAULT_V@)
+am__v_GEN_0 = @echo " GEN " $@;
+am__v_GEN_1 =
+AM_V_at = $(am__v_at_@AM_V@)
+am__v_at_ = $(am__v_at_@AM_DEFAULT_V@)
+am__v_at_0 = @
+am__v_at_1 =
+SOURCES =
+DIST_SOURCES =
+RECURSIVE_TARGETS = all-recursive check-recursive cscopelist-recursive \
+ ctags-recursive dvi-recursive html-recursive info-recursive \
+ install-data-recursive install-dvi-recursive \
+ install-exec-recursive install-html-recursive \
+ install-info-recursive install-pdf-recursive \
+ install-ps-recursive install-recursive installcheck-recursive \
+ installdirs-recursive pdf-recursive ps-recursive \
+ tags-recursive uninstall-recursive
+am__can_run_installinfo = \
+ case $$AM_UPDATE_INFO_DIR in \
+ n|no|NO) false;; \
+ *) (install-info --version) >/dev/null 2>&1;; \
+ esac
+RECURSIVE_CLEAN_TARGETS = mostlyclean-recursive clean-recursive \
+ distclean-recursive maintainer-clean-recursive
+am__recursive_targets = \
+ $(RECURSIVE_TARGETS) \
+ $(RECURSIVE_CLEAN_TARGETS) \
+ $(am__extra_recursive_targets)
+AM_RECURSIVE_TARGETS = $(am__recursive_targets:-recursive=) TAGS CTAGS \
+ distdir
+am__tagged_files = $(HEADERS) $(SOURCES) $(TAGS_FILES) $(LISP)
+# Read a list of newline-separated strings from the standard input,
+# and print each of them once, without duplicates. Input order is
+# *not* preserved.
+am__uniquify_input = $(AWK) '\
+ BEGIN { nonempty = 0; } \
+ { items[$$0] = 1; nonempty = 1; } \
+ END { if (nonempty) { for (i in items) print i; }; } \
+'
+# Make sure the list of sources is unique. This is necessary because,
+# e.g., the same source file might be shared among _SOURCES variables
+# for different programs/libraries.
+am__define_uniq_tagged_files = \
+ list='$(am__tagged_files)'; \
+ unique=`for i in $$list; do \
+ if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \
+ done | $(am__uniquify_input)`
+ETAGS = etags
+CTAGS = ctags
+DIST_SUBDIRS = $(SUBDIRS)
+DISTFILES = $(DIST_COMMON) $(DIST_SOURCES) $(TEXINFOS) $(EXTRA_DIST)
+am__relativize = \
+ dir0=`pwd`; \
+ sed_first='s,^\([^/]*\)/.*$$,\1,'; \
+ sed_rest='s,^[^/]*/*,,'; \
+ sed_last='s,^.*/\([^/]*\)$$,\1,'; \
+ sed_butlast='s,/*[^/]*$$,,'; \
+ while test -n "$$dir1"; do \
+ first=`echo "$$dir1" | sed -e "$$sed_first"`; \
+ if test "$$first" != "."; then \
+ if test "$$first" = ".."; then \
+ dir2=`echo "$$dir0" | sed -e "$$sed_last"`/"$$dir2"; \
+ dir0=`echo "$$dir0" | sed -e "$$sed_butlast"`; \
+ else \
+ first2=`echo "$$dir2" | sed -e "$$sed_first"`; \
+ if test "$$first2" = "$$first"; then \
+ dir2=`echo "$$dir2" | sed -e "$$sed_rest"`; \
+ else \
+ dir2="../$$dir2"; \
+ fi; \
+ dir0="$$dir0"/"$$first"; \
+ fi; \
+ fi; \
+ dir1=`echo "$$dir1" | sed -e "$$sed_rest"`; \
+ done; \
+ reldir="$$dir2"
+ACLOCAL = @ACLOCAL@
+AMTAR = @AMTAR@
+AM_DEFAULT_VERBOSITY = @AM_DEFAULT_VERBOSITY@
+AR = @AR@
+AS = @AS@
+AUTOCONF = @AUTOCONF@
+AUTOHEADER = @AUTOHEADER@
+AUTOMAKE = @AUTOMAKE@
+AWK = @AWK@
+BUILD_FILEVERSION = @BUILD_FILEVERSION@
+BUILD_REVISION = @BUILD_REVISION@
+BUILD_TIMESTAMP = @BUILD_TIMESTAMP@
+CC = @CC@
+CCDEPMODE = @CCDEPMODE@
+CC_FOR_BUILD = @CC_FOR_BUILD@
+CFLAGS = @CFLAGS@
+CPP = @CPP@
+CPPFLAGS = @CPPFLAGS@
+CXX = @CXX@
+CXXCPP = @CXXCPP@
+CXXDEPMODE = @CXXDEPMODE@
+CXXFLAGS = @CXXFLAGS@
+CYGPATH_W = @CYGPATH_W@
+DEFS = @DEFS@
+DEPDIR = @DEPDIR@
+DLLTOOL = @DLLTOOL@
+DOXYGEN = @DOXYGEN@
+DSYMUTIL = @DSYMUTIL@
+DUMPBIN = @DUMPBIN@
+ECHO_C = @ECHO_C@
+ECHO_N = @ECHO_N@
+ECHO_T = @ECHO_T@
+EGREP = @EGREP@
+ENABLED_LANGUAGES = @ENABLED_LANGUAGES@
+EXEEXT = @EXEEXT@
+FGREP = @FGREP@
+GITLOG_TO_CHANGELOG = @GITLOG_TO_CHANGELOG@
+GLIBC21 = @GLIBC21@
+GLIB_CFLAGS = @GLIB_CFLAGS@
+GLIB_GENMARSHAL = @GLIB_GENMARSHAL@
+GLIB_LIBS = @GLIB_LIBS@
+GLIB_MKENUMS = @GLIB_MKENUMS@
+GOBJECT_QUERY = @GOBJECT_QUERY@
+GPGME_CONFIG_API_VERSION = @GPGME_CONFIG_API_VERSION@
+GPGME_CONFIG_AVAIL_LANG = @GPGME_CONFIG_AVAIL_LANG@
+GPGME_CONFIG_CFLAGS = @GPGME_CONFIG_CFLAGS@
+GPGME_CONFIG_HOST = @GPGME_CONFIG_HOST@
+GPGME_CONFIG_LIBS = @GPGME_CONFIG_LIBS@
+GPGME_QTTEST_CFLAGS = @GPGME_QTTEST_CFLAGS@
+GPGME_QTTEST_LIBS = @GPGME_QTTEST_LIBS@
+GPGME_QT_CFLAGS = @GPGME_QT_CFLAGS@
+GPGME_QT_LIBS = @GPGME_QT_LIBS@
+GPG_ERROR_CFLAGS = @GPG_ERROR_CFLAGS@
+GPG_ERROR_CONFIG = @GPG_ERROR_CONFIG@
+GPG_ERROR_LIBS = @GPG_ERROR_LIBS@
+GPG_ERROR_MT_CFLAGS = @GPG_ERROR_MT_CFLAGS@
+GPG_ERROR_MT_LIBS = @GPG_ERROR_MT_LIBS@
+GRAPHVIZ = @GRAPHVIZ@
+GREP = @GREP@
+HAVE_CXX11 = @HAVE_CXX11@
+HAVE_DOT = @HAVE_DOT@
+INSTALL = @INSTALL@
+INSTALL_DATA = @INSTALL_DATA@
+INSTALL_PROGRAM = @INSTALL_PROGRAM@
+INSTALL_SCRIPT = @INSTALL_SCRIPT@
+INSTALL_STRIP_PROGRAM = @INSTALL_STRIP_PROGRAM@
+LD = @LD@
+LDFLAGS = @LDFLAGS@
+LIBASSUAN_CFLAGS = @LIBASSUAN_CFLAGS@
+LIBASSUAN_CONFIG = @LIBASSUAN_CONFIG@
+LIBASSUAN_LIBS = @LIBASSUAN_LIBS@
+LIBGPGMEPP_LT_AGE = @LIBGPGMEPP_LT_AGE@
+LIBGPGMEPP_LT_CURRENT = @LIBGPGMEPP_LT_CURRENT@
+LIBGPGMEPP_LT_REVISION = @LIBGPGMEPP_LT_REVISION@
+LIBGPGME_LT_AGE = @LIBGPGME_LT_AGE@
+LIBGPGME_LT_CURRENT = @LIBGPGME_LT_CURRENT@
+LIBGPGME_LT_REVISION = @LIBGPGME_LT_REVISION@
+LIBOBJS = @LIBOBJS@
+LIBQGPGME_LT_AGE = @LIBQGPGME_LT_AGE@
+LIBQGPGME_LT_CURRENT = @LIBQGPGME_LT_CURRENT@
+LIBQGPGME_LT_REVISION = @LIBQGPGME_LT_REVISION@
+LIBS = @LIBS@
+LIBTOOL = @LIBTOOL@
+LIPO = @LIPO@
+LN_S = @LN_S@
+LTLIBOBJS = @LTLIBOBJS@
+MAINT = @MAINT@
+MAKEINFO = @MAKEINFO@
+MANIFEST_TOOL = @MANIFEST_TOOL@
+MKDIR_P = @MKDIR_P@
+MOC = @MOC@
+MOC2 = @MOC2@
+NEED__FILE_OFFSET_BITS = @NEED__FILE_OFFSET_BITS@
+NM = @NM@
+NMEDIT = @NMEDIT@
+OBJDUMP = @OBJDUMP@
+OBJEXT = @OBJEXT@
+OTOOL = @OTOOL@
+OTOOL64 = @OTOOL64@
+PACKAGE = @PACKAGE@
+PACKAGE_BUGREPORT = @PACKAGE_BUGREPORT@
+PACKAGE_NAME = @PACKAGE_NAME@
+PACKAGE_STRING = @PACKAGE_STRING@
+PACKAGE_TARNAME = @PACKAGE_TARNAME@
+PACKAGE_URL = @PACKAGE_URL@
+PACKAGE_VERSION = @PACKAGE_VERSION@
+PATH_SEPARATOR = @PATH_SEPARATOR@
+PKG_CONFIG = @PKG_CONFIG@
+PYTHON = @PYTHON@
+PYTHONS = @PYTHONS@
+PYTHON_CPPFLAGS = @PYTHON_CPPFLAGS@
+PYTHON_EXEC_PREFIX = @PYTHON_EXEC_PREFIX@
+PYTHON_EXTRA_LDFLAGS = @PYTHON_EXTRA_LDFLAGS@
+PYTHON_EXTRA_LIBS = @PYTHON_EXTRA_LIBS@
+PYTHON_LDFLAGS = @PYTHON_LDFLAGS@
+PYTHON_PLATFORM = @PYTHON_PLATFORM@
+PYTHON_PREFIX = @PYTHON_PREFIX@
+PYTHON_SITE_PKG = @PYTHON_SITE_PKG@
+PYTHON_VERSION = @PYTHON_VERSION@
+PYTHON_VERSIONS = @PYTHON_VERSIONS@
+QTCHOOSER = @QTCHOOSER@
+RANLIB = @RANLIB@
+RC = @RC@
+SED = @SED@
+SET_MAKE = @SET_MAKE@
+SHELL = @SHELL@
+STRIP = @STRIP@
+SWIG = @SWIG@
+SWIG_LIB = @SWIG_LIB@
+SYSROOT = @SYSROOT@
+VERSION = @VERSION@
+VERSION_NUMBER = @VERSION_NUMBER@
+abs_builddir = @abs_builddir@
+abs_srcdir = @abs_srcdir@
+abs_top_builddir = @abs_top_builddir@
+abs_top_srcdir = @abs_top_srcdir@
+ac_ct_AR = @ac_ct_AR@
+ac_ct_CC = @ac_ct_CC@
+ac_ct_CXX = @ac_ct_CXX@
+ac_ct_DUMPBIN = @ac_ct_DUMPBIN@
+am__include = @am__include@
+am__leading_dot = @am__leading_dot@
+am__quote = @am__quote@
+am__tar = @am__tar@
+am__untar = @am__untar@
+bindir = @bindir@
+build = @build@
+build_alias = @build_alias@
+build_cpu = @build_cpu@
+build_os = @build_os@
+build_vendor = @build_vendor@
+builddir = @builddir@
+datadir = @datadir@
+datarootdir = @datarootdir@
+docdir = @docdir@
+dvidir = @dvidir@
+emacs_local_vars_begin = @emacs_local_vars_begin@
+emacs_local_vars_end = @emacs_local_vars_end@
+emacs_local_vars_read_only = @emacs_local_vars_read_only@
+exec_prefix = @exec_prefix@
+host = @host@
+host_alias = @host_alias@
+host_cpu = @host_cpu@
+host_os = @host_os@
+host_vendor = @host_vendor@
+htmldir = @htmldir@
+includedir = @includedir@
+infodir = @infodir@
+install_sh = @install_sh@
+libdir = @libdir@
+libexecdir = @libexecdir@
+localedir = @localedir@
+localstatedir = @localstatedir@
+mandir = @mandir@
+mkdir_p = @mkdir_p@
+oldincludedir = @oldincludedir@
+pdfdir = @pdfdir@
+pkgpyexecdir = @pkgpyexecdir@
+pkgpythondir = @pkgpythondir@
+prefix = @prefix@
+program_transform_name = @program_transform_name@
+psdir = @psdir@
+pyexecdir = @pyexecdir@
+pythondir = @pythondir@
+sbindir = @sbindir@
+sharedstatedir = @sharedstatedir@
+srcdir = @srcdir@
+sysconfdir = @sysconfdir@
+target_alias = @target_alias@
+top_build_prefix = @top_build_prefix@
+top_builddir = @top_builddir@
+top_srcdir = @top_srcdir@
+SUBDIRS = src
+EXTRA_DIST = README
+all: all-recursive
+
+.SUFFIXES:
+$(srcdir)/Makefile.in: @MAINTAINER_MODE_TRUE@ $(srcdir)/Makefile.am $(am__configure_deps)
+ @for dep in $?; do \
+ case '$(am__configure_deps)' in \
+ *$$dep*) \
+ ( cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh ) \
+ && { if test -f $@; then exit 0; else break; fi; }; \
+ exit 1;; \
+ esac; \
+ done; \
+ echo ' cd $(top_srcdir) && $(AUTOMAKE) --gnu lang/cpp/Makefile'; \
+ $(am__cd) $(top_srcdir) && \
+ $(AUTOMAKE) --gnu lang/cpp/Makefile
+.PRECIOUS: Makefile
+Makefile: $(srcdir)/Makefile.in $(top_builddir)/config.status
+ @case '$?' in \
+ *config.status*) \
+ cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh;; \
+ *) \
+ echo ' cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__depfiles_maybe)'; \
+ cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__depfiles_maybe);; \
+ esac;
+
+$(top_builddir)/config.status: $(top_srcdir)/configure $(CONFIG_STATUS_DEPENDENCIES)
+ cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh
+
+$(top_srcdir)/configure: @MAINTAINER_MODE_TRUE@ $(am__configure_deps)
+ cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh
+$(ACLOCAL_M4): @MAINTAINER_MODE_TRUE@ $(am__aclocal_m4_deps)
+ cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh
+$(am__aclocal_m4_deps):
+
+mostlyclean-libtool:
+ -rm -f *.lo
+
+clean-libtool:
+ -rm -rf .libs _libs
+
+# This directory's subdirectories are mostly independent; you can cd
+# into them and run 'make' without going through this Makefile.
+# To change the values of 'make' variables: instead of editing Makefiles,
+# (1) if the variable is set in 'config.status', edit 'config.status'
+# (which will cause the Makefiles to be regenerated when you run 'make');
+# (2) otherwise, pass the desired values on the 'make' command line.
+$(am__recursive_targets):
+ @fail=; \
+ if $(am__make_keepgoing); then \
+ failcom='fail=yes'; \
+ else \
+ failcom='exit 1'; \
+ fi; \
+ dot_seen=no; \
+ target=`echo $@ | sed s/-recursive//`; \
+ case "$@" in \
+ distclean-* | maintainer-clean-*) list='$(DIST_SUBDIRS)' ;; \
+ *) list='$(SUBDIRS)' ;; \
+ esac; \
+ for subdir in $$list; do \
+ echo "Making $$target in $$subdir"; \
+ if test "$$subdir" = "."; then \
+ dot_seen=yes; \
+ local_target="$$target-am"; \
+ else \
+ local_target="$$target"; \
+ fi; \
+ ($(am__cd) $$subdir && $(MAKE) $(AM_MAKEFLAGS) $$local_target) \
+ || eval $$failcom; \
+ done; \
+ if test "$$dot_seen" = "no"; then \
+ $(MAKE) $(AM_MAKEFLAGS) "$$target-am" || exit 1; \
+ fi; test -z "$$fail"
+
+ID: $(am__tagged_files)
+ $(am__define_uniq_tagged_files); mkid -fID $$unique
+tags: tags-recursive
+TAGS: tags
+
+tags-am: $(TAGS_DEPENDENCIES) $(am__tagged_files)
+ set x; \
+ here=`pwd`; \
+ if ($(ETAGS) --etags-include --version) >/dev/null 2>&1; then \
+ include_option=--etags-include; \
+ empty_fix=.; \
+ else \
+ include_option=--include; \
+ empty_fix=; \
+ fi; \
+ list='$(SUBDIRS)'; for subdir in $$list; do \
+ if test "$$subdir" = .; then :; else \
+ test ! -f $$subdir/TAGS || \
+ set "$$@" "$$include_option=$$here/$$subdir/TAGS"; \
+ fi; \
+ done; \
+ $(am__define_uniq_tagged_files); \
+ shift; \
+ if test -z "$(ETAGS_ARGS)$$*$$unique"; then :; else \
+ test -n "$$unique" || unique=$$empty_fix; \
+ if test $$# -gt 0; then \
+ $(ETAGS) $(ETAGSFLAGS) $(AM_ETAGSFLAGS) $(ETAGS_ARGS) \
+ "$$@" $$unique; \
+ else \
+ $(ETAGS) $(ETAGSFLAGS) $(AM_ETAGSFLAGS) $(ETAGS_ARGS) \
+ $$unique; \
+ fi; \
+ fi
+ctags: ctags-recursive
+
+CTAGS: ctags
+ctags-am: $(TAGS_DEPENDENCIES) $(am__tagged_files)
+ $(am__define_uniq_tagged_files); \
+ test -z "$(CTAGS_ARGS)$$unique" \
+ || $(CTAGS) $(CTAGSFLAGS) $(AM_CTAGSFLAGS) $(CTAGS_ARGS) \
+ $$unique
+
+GTAGS:
+ here=`$(am__cd) $(top_builddir) && pwd` \
+ && $(am__cd) $(top_srcdir) \
+ && gtags -i $(GTAGS_ARGS) "$$here"
+cscopelist: cscopelist-recursive
+
+cscopelist-am: $(am__tagged_files)
+ list='$(am__tagged_files)'; \
+ case "$(srcdir)" in \
+ [\\/]* | ?:[\\/]*) sdir="$(srcdir)" ;; \
+ *) sdir=$(subdir)/$(srcdir) ;; \
+ esac; \
+ for i in $$list; do \
+ if test -f "$$i"; then \
+ echo "$(subdir)/$$i"; \
+ else \
+ echo "$$sdir/$$i"; \
+ fi; \
+ done >> $(top_builddir)/cscope.files
+
+distclean-tags:
+ -rm -f TAGS ID GTAGS GRTAGS GSYMS GPATH tags
+
+distdir: $(DISTFILES)
+ @srcdirstrip=`echo "$(srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \
+ topsrcdirstrip=`echo "$(top_srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \
+ list='$(DISTFILES)'; \
+ dist_files=`for file in $$list; do echo $$file; done | \
+ sed -e "s|^$$srcdirstrip/||;t" \
+ -e "s|^$$topsrcdirstrip/|$(top_builddir)/|;t"`; \
+ case $$dist_files in \
+ */*) $(MKDIR_P) `echo "$$dist_files" | \
+ sed '/\//!d;s|^|$(distdir)/|;s,/[^/]*$$,,' | \
+ sort -u` ;; \
+ esac; \
+ for file in $$dist_files; do \
+ if test -f $$file || test -d $$file; then d=.; else d=$(srcdir); fi; \
+ if test -d $$d/$$file; then \
+ dir=`echo "/$$file" | sed -e 's,/[^/]*$$,,'`; \
+ if test -d "$(distdir)/$$file"; then \
+ find "$(distdir)/$$file" -type d ! -perm -700 -exec chmod u+rwx {} \;; \
+ fi; \
+ if test -d $(srcdir)/$$file && test $$d != $(srcdir); then \
+ cp -fpR $(srcdir)/$$file "$(distdir)$$dir" || exit 1; \
+ find "$(distdir)/$$file" -type d ! -perm -700 -exec chmod u+rwx {} \;; \
+ fi; \
+ cp -fpR $$d/$$file "$(distdir)$$dir" || exit 1; \
+ else \
+ test -f "$(distdir)/$$file" \
+ || cp -p $$d/$$file "$(distdir)/$$file" \
+ || exit 1; \
+ fi; \
+ done
+ @list='$(DIST_SUBDIRS)'; for subdir in $$list; do \
+ if test "$$subdir" = .; then :; else \
+ $(am__make_dryrun) \
+ || test -d "$(distdir)/$$subdir" \
+ || $(MKDIR_P) "$(distdir)/$$subdir" \
+ || exit 1; \
+ dir1=$$subdir; dir2="$(distdir)/$$subdir"; \
+ $(am__relativize); \
+ new_distdir=$$reldir; \
+ dir1=$$subdir; dir2="$(top_distdir)"; \
+ $(am__relativize); \
+ new_top_distdir=$$reldir; \
+ echo " (cd $$subdir && $(MAKE) $(AM_MAKEFLAGS) top_distdir="$$new_top_distdir" distdir="$$new_distdir" \\"; \
+ echo " am__remove_distdir=: am__skip_length_check=: am__skip_mode_fix=: distdir)"; \
+ ($(am__cd) $$subdir && \
+ $(MAKE) $(AM_MAKEFLAGS) \
+ top_distdir="$$new_top_distdir" \
+ distdir="$$new_distdir" \
+ am__remove_distdir=: \
+ am__skip_length_check=: \
+ am__skip_mode_fix=: \
+ distdir) \
+ || exit 1; \
+ fi; \
+ done
+check-am: all-am
+check: check-recursive
+all-am: Makefile
+installdirs: installdirs-recursive
+installdirs-am:
+install: install-recursive
+install-exec: install-exec-recursive
+install-data: install-data-recursive
+uninstall: uninstall-recursive
+
+install-am: all-am
+ @$(MAKE) $(AM_MAKEFLAGS) install-exec-am install-data-am
+
+installcheck: installcheck-recursive
+install-strip:
+ if test -z '$(STRIP)'; then \
+ $(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \
+ install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \
+ install; \
+ else \
+ $(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \
+ install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \
+ "INSTALL_PROGRAM_ENV=STRIPPROG='$(STRIP)'" install; \
+ fi
+mostlyclean-generic:
+
+clean-generic:
+
+distclean-generic:
+ -test -z "$(CONFIG_CLEAN_FILES)" || rm -f $(CONFIG_CLEAN_FILES)
+ -test . = "$(srcdir)" || test -z "$(CONFIG_CLEAN_VPATH_FILES)" || rm -f $(CONFIG_CLEAN_VPATH_FILES)
+
+maintainer-clean-generic:
+ @echo "This command is intended for maintainers to use"
+ @echo "it deletes files that may require special tools to rebuild."
+clean: clean-recursive
+
+clean-am: clean-generic clean-libtool mostlyclean-am
+
+distclean: distclean-recursive
+ -rm -f Makefile
+distclean-am: clean-am distclean-generic distclean-tags
+
+dvi: dvi-recursive
+
+dvi-am:
+
+html: html-recursive
+
+html-am:
+
+info: info-recursive
+
+info-am:
+
+install-data-am:
+
+install-dvi: install-dvi-recursive
+
+install-dvi-am:
+
+install-exec-am:
+
+install-html: install-html-recursive
+
+install-html-am:
+
+install-info: install-info-recursive
+
+install-info-am:
+
+install-man:
+
+install-pdf: install-pdf-recursive
+
+install-pdf-am:
+
+install-ps: install-ps-recursive
+
+install-ps-am:
+
+installcheck-am:
+
+maintainer-clean: maintainer-clean-recursive
+ -rm -f Makefile
+maintainer-clean-am: distclean-am maintainer-clean-generic
+
+mostlyclean: mostlyclean-recursive
+
+mostlyclean-am: mostlyclean-generic mostlyclean-libtool
+
+pdf: pdf-recursive
+
+pdf-am:
+
+ps: ps-recursive
+
+ps-am:
+
+uninstall-am:
+
+.MAKE: $(am__recursive_targets) install-am install-strip
+
+.PHONY: $(am__recursive_targets) CTAGS GTAGS TAGS all all-am check \
+ check-am clean clean-generic clean-libtool cscopelist-am ctags \
+ ctags-am distclean distclean-generic distclean-libtool \
+ distclean-tags distdir dvi dvi-am html html-am info info-am \
+ install install-am install-data install-data-am install-dvi \
+ install-dvi-am install-exec install-exec-am install-html \
+ install-html-am install-info install-info-am install-man \
+ install-pdf install-pdf-am install-ps install-ps-am \
+ install-strip installcheck installcheck-am installdirs \
+ installdirs-am maintainer-clean maintainer-clean-generic \
+ mostlyclean mostlyclean-generic mostlyclean-libtool pdf pdf-am \
+ ps ps-am tags tags-am uninstall uninstall-am
+
+
+# Tell versions [3.59,3.63) of GNU make to not export all variables.
+# Otherwise a system limit (for SysV at least) may be exceeded.
+.NOEXPORT:
diff --git a/lang/cpp/README b/lang/cpp/README
new file mode 100644
index 0000000..b9a48da
--- /dev/null
+++ b/lang/cpp/README
@@ -0,0 +1,101 @@
+GpgMEpp - C++ bindings/wrapper for GPGME
+----------------------------------------
+Based on KF5gpgmepp
+
+Overview
+--------
+
+GpgMEpp is a C++ wrapper (or C++ bindings) for the GnuPG project's
+gpgme (GnuPG Made Easy) library, version 0.4.4 and later.
+
+It is fairly complete, with some minor things still missing (in
+particular, the key edit interface).
+
+The design principles of this library are as follows:
+
+1. A value-based interface (most clases are implicitly shared)
+2. Callbacks are replaced by C++ interfaces (classes with only
+ abstract methods).
+3. No exceptions are thrown
+4. There is (as yet) no explicit support for multi-threaded use
+ (other than what gpgme itself provides; most notably the
+ refcounting for implicit sharing is not thread-safe)
+5. To avoid binary incompatible interface changes, we make
+ extensive use of the d-pointer pattern and avoid virtual
+ methods; any polymorphism present is already provided by gpgme
+ itself, anyway (see e.g. Data). A notable exception of the
+ no-virtuals rule is the use of abstract classes to cover
+ C-callbacks.
+6. Use of STL containers for improved memory management and
+ dealing with lists.
+7. Complete abstraction of the C-API so "gpgme.h" should not
+ be needed in your project using GpgME++.
+8. Abstraction of GnuPG's edit-key interface by prepared
+ Editinteractor classes.
+
+GpgMEpp was originally developed as part of the KDEPIM community.
+
+Usage
+-----
+
+The usage pattern of GpgMEpp closely follows GPGMEs core usage
+pattern so the documentation for GPGME itself provides a good
+way to start.
+
+The context structure in GPGME is mapped to a Context object in
+GpgMEpp. Additional convienience code provides Data objects and
+a Dataprovider interface that can be used to implement GPGME's
+data with any subclass by implementing the right callbacks.
+
+EditInteractor subclasses provide ready to use classes for
+common --edit-key tasks. You can implement your own editinteractor
+classes by implementing the EditInteractor interface and using
+your subclass as an interactor in the edit function.
+
+Example to set the ownertrust of a key:
+
+ /* Create an edit interactor */
+ EditInteractor *ei = new GpgSetOwnerTrustEditInteractor(Key::Ultimate);
+ /* Obtain a Context */
+ Context *ctx = Context::createForProtocol(Protocol::OpenPGP);
+ /* Create an in memory data object */
+ Data data;
+ /* Start the edit on some key previously obtained. */
+ Error e = ctx->edit(key, std::unique_ptr<EditInteractor>(ei), data);
+ /* Errors provide boolean comparision */
+ if (!e)
+ ...
+ /* Delete the context */
+ delete ctx;
+
+Examples / Tests
+----------------
+
+GpgMEpp is tested through the Qt API. You can refer to the
+tests in qt/tests for examples of usage or refer to
+the actual QGpgME*Job.cpp implementations which rely
+on GpgMEpp and should cover most use cases.
+
+Hacking
+-------
+
+GpgMEpp follows KDE Coding styles. See:
+https://techbase.kde.org/Policies/Frameworks_Coding_Style
+for more info.
+
+License
+-------
+GPGMEpp is free software; you can redistribute it and/or
+modify it under the terms of the GNU Library General Public
+License as published by the Free Software Foundation; either
+version 2 of the License, or (at your option) any later version.
+
+GPGMEpp is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+GNU Library General Public License for more details.
+
+You should have received a copy of the GNU Library General Public License
+along with GPGME++; see the file COPYING.LIB. If not, write to the
+Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+Boston, MA 02110-1301, USA.
diff --git a/lang/cpp/src/GpgmeppConfig.cmake.in.in b/lang/cpp/src/GpgmeppConfig.cmake.in.in
new file mode 100644
index 0000000..d54011e
--- /dev/null
+++ b/lang/cpp/src/GpgmeppConfig.cmake.in.in
@@ -0,0 +1,108 @@
+# CMake Config file for GPGMEPP.
+# Copyright (C) 2016 Intevation GmbH
+#
+# This file is part of GPGMEPP.
+#
+# GPGME-CL 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.
+#
+# GPGME-CL is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU Lesser General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program; if not, write to the Free Software
+# Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
+# 02111-1307, USA
+
+# based on a generated file from cmake.
+# Generated by CMake 3.0.2
+
+if("${CMAKE_MAJOR_VERSION}.${CMAKE_MINOR_VERSION}" LESS 2.5)
+ message(FATAL_ERROR "CMake >= 2.6.0 required")
+endif()
+cmake_policy(PUSH)
+cmake_policy(VERSION 2.6)
+#----------------------------------------------------------------
+# Generated CMake target import file.
+#----------------------------------------------------------------
+
+# Commands may need to know the format version.
+set(CMAKE_IMPORT_FILE_VERSION 1)
+
+# Protect against multiple inclusion, which would fail when already imported targets are added once more.
+set(_targetsDefined)
+set(_targetsNotDefined)
+set(_expectedTargets)
+foreach(_expectedTarget KF5::Gpgmepp Gpgmepp)
+ list(APPEND _expectedTargets ${_expectedTarget})
+ if(NOT TARGET ${_expectedTarget})
+ list(APPEND _targetsNotDefined ${_expectedTarget})
+ endif()
+ if(TARGET ${_expectedTarget})
+ list(APPEND _targetsDefined ${_expectedTarget})
+ endif()
+endforeach()
+if("${_targetsDefined}" STREQUAL "${_expectedTargets}")
+ set(CMAKE_IMPORT_FILE_VERSION)
+ cmake_policy(POP)
+ return()
+endif()
+if(NOT "${_targetsDefined}" STREQUAL "")
+ message(FATAL_ERROR "Some (but not all) targets in this export set were already defined.\nTargets Defined: ${_targetsDefined}\nTargets not yet defined: ${_targetsNotDefined}\n")
+endif()
+unset(_targetsDefined)
+unset(_targetsNotDefined)
+unset(_expectedTargets)
+
+# Compute the installation prefix relative to this file.
+get_filename_component(_IMPORT_PREFIX "${CMAKE_CURRENT_LIST_FILE}" PATH)
+get_filename_component(_IMPORT_PREFIX "${_IMPORT_PREFIX}" PATH)
+get_filename_component(_IMPORT_PREFIX "${_IMPORT_PREFIX}" PATH)
+get_filename_component(_IMPORT_PREFIX "${_IMPORT_PREFIX}" PATH)
+
+# Create imported target Gpgmepp
+add_library(Gpgmepp SHARED IMPORTED)
+
+set_target_properties(Gpgmepp PROPERTIES
+ INTERFACE_INCLUDE_DIRECTORIES "${_IMPORT_PREFIX}/include/gpgme++"
+ INTERFACE_LINK_LIBRARIES "pthread;@resolved_libdir@/libgpgme@libsuffix@;@LIBASSUAN_LIBS@"
+ IMPORTED_LOCATION "@resolved_libdir@/libgpgmepp@libsuffix@"
+)
+
+if(CMAKE_VERSION VERSION_LESS 2.8.12)
+ message(FATAL_ERROR "This file relies on consumers using CMake 2.8.12 or greater.")
+endif()
+
+# Cleanup temporary variables.
+set(_IMPORT_PREFIX)
+
+# Loop over all imported files and verify that they actually exist
+foreach(target ${_IMPORT_CHECK_TARGETS} )
+ foreach(file ${_IMPORT_CHECK_FILES_FOR_${target}} )
+ if(NOT EXISTS "${file}" )
+ message(FATAL_ERROR "The imported target \"${target}\" references the file
+ \"${file}\"
+but this file does not exist. Possible reasons include:
+* The file was deleted, renamed, or moved to another location.
+* An install or uninstall procedure did not complete successfully.
+* The installation package was faulty and contained
+ \"${CMAKE_CURRENT_LIST_FILE}\"
+but not all the files it references.
+")
+ endif()
+ endforeach()
+ unset(_IMPORT_CHECK_FILES_FOR_${target})
+endforeach()
+unset(_IMPORT_CHECK_TARGETS)
+
+# Commands beyond this point should not need to know the version.
+set(CMAKE_IMPORT_FILE_VERSION)
+cmake_policy(POP)
+
+get_filename_component(QGpgme_DIR "${CMAKE_CURRENT_LIST_FILE}" PATH)
+# Pull in QGpgme for compatibility with KF5 variant.
+find_package(QGpgme CONFIG)
diff --git a/lang/cpp/src/GpgmeppConfigVersion.cmake.in b/lang/cpp/src/GpgmeppConfigVersion.cmake.in
new file mode 100644
index 0000000..43d6512
--- /dev/null
+++ b/lang/cpp/src/GpgmeppConfigVersion.cmake.in
@@ -0,0 +1,31 @@
+# CMake Version file for GPGMEPP.
+# Copyright (C) 2016 Intevation GmbH
+#
+# This file is part of GPGMEPP.
+#
+# GPGME-CL 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.
+#
+# GPGME-CL is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU Lesser General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program; if not, write to the Free Software
+# Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
+# 02111-1307, USA
+
+# based on a generated file from cmake.
+set(PACKAGE_VERSION "@LIBGPGMEPP_LT_CURRENT@.@LIBGPGMEPP_LT_AGE@.@LIBGPGMEPP_LT_REVISION@.@BUILD_REVISION@")
+
+if("${PACKAGE_VERSION}" VERSION_LESS "${PACKAGE_FIND_VERSION}" )
+ set(PACKAGE_VERSION_COMPATIBLE FALSE)
+else()
+ set(PACKAGE_VERSION_COMPATIBLE TRUE)
+ if( "${PACKAGE_FIND_VERSION}" STREQUAL "${PACKAGE_VERSION}")
+ set(PACKAGE_VERSION_EXACT TRUE)
+ endif()
+endif()
diff --git a/lang/cpp/src/Makefile.am b/lang/cpp/src/Makefile.am
new file mode 100644
index 0000000..e65a875
--- /dev/null
+++ b/lang/cpp/src/Makefile.am
@@ -0,0 +1,99 @@
+# Makefile.am for GPGMEPP.
+# Copyright (C) 2016 Intevation GmbH
+#
+# This file is part of GPGMEPP.
+#
+# GPGME-CL 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.
+#
+# GPGME-CL is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU Lesser General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program; if not, write to the Free Software
+# Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
+# 02111-1307, USA
+
+EXTRA_DIST = GpgmeppConfig.cmake.in.in GpgmeppConfigVersion.cmake.in \
+ gpgmepp_version.h.in
+
+lib_LTLIBRARIES = libgpgmepp.la
+
+main_sources = \
+ exception.cpp context.cpp key.cpp trustitem.cpp data.cpp callbacks.cpp \
+ eventloopinteractor.cpp editinteractor.cpp \
+ keylistresult.cpp keygenerationresult.cpp importresult.cpp \
+ decryptionresult.cpp verificationresult.cpp \
+ signingresult.cpp encryptionresult.cpp \
+ engineinfo.cpp gpgsetexpirytimeeditinteractor.cpp \
+ gpgsetownertrusteditinteractor.cpp gpgsignkeyeditinteractor.cpp \
+ gpgadduserideditinteractor.cpp defaultassuantransaction.cpp \
+ scdgetinfoassuantransaction.cpp gpgagentgetinfoassuantransaction.cpp \
+ vfsmountresult.cpp configuration.cpp tofuinfo.cpp
+
+gpgmepp_headers = \
+ configuration.h context.h data.h decryptionresult.h \
+ defaultassuantransaction.h editinteractor.h encryptionresult.h \
+ engineinfo.h error.h eventloopinteractor.h exception.h global.h \
+ gpgadduserideditinteractor.h gpgagentgetinfoassuantransaction.h \
+ gpgmefw.h gpgsetexpirytimeeditinteractor.h \
+ gpgsetownertrusteditinteractor.h gpgsignkeyeditinteractor.h \
+ importresult.h keygenerationresult.h key.h keylistresult.h \
+ notation.h result.h scdgetinfoassuantransaction.h signingresult.h \
+ trustitem.h verificationresult.h vfsmountresult.h gpgmepp_export.h \
+ tofuinfo.h
+
+private_gpgmepp_headers = \
+ result_p.h context_p.h util.h callbacks.h data_p.h
+
+interface_headers= \
+ interfaces/assuantransaction.h interfaces/dataprovider.h \
+ interfaces/passphraseprovider.h interfaces/progressprovider.h
+
+gpgmeppincludedir = $(includedir)/gpgme++
+gpgmeppinclude_HEADERS = $(gpgmepp_headers)
+nobase_gpgmeppinclude_HEADERS = $(interface_headers)
+nodist_include_HEADERS = gpgmepp_version.h
+
+libgpgmepp_la_SOURCES = $(main_sources) $(gpgmepp_headers) context_vanilla.cpp \
+ $(interface_headers) $(private_gpgmepp_headers)
+
+AM_CPPFLAGS = -I$(top_builddir)/src @GPG_ERROR_CFLAGS@ @LIBASSUAN_CFLAGS@ \
+ -DBUILDING_GPGMEPP
+
+libgpgmepp_la_LIBADD = ../../../src/libgpgme.la @LIBASSUAN_LIBS@
+libgpgmepp_la_LDFLAGS = -version-info \
+ @LIBGPGMEPP_LT_CURRENT@:@LIBGPGMEPP_LT_REVISION@:@LIBGPGMEPP_LT_AGE@
+
+if HAVE_W32_SYSTEM
+libsuffix=.dll.a
+else
+libsuffix=.so
+endif
+
+GpgmeppConfig.cmake: GpgmeppConfig.cmake.in
+ sed -e 's|[@]resolved_libdir@|$(libdir)|g' < "$<" > "$@"
+ sed -e 's|[@]libsuffix@|$(libsuffix)|g' < "$@" > "$@".2
+ mv "$@".2 "$@"
+
+install-cmake-files: GpgmeppConfig.cmake GpgmeppConfigVersion.cmake
+ -$(INSTALL) -d $(DESTDIR)$(libdir)/cmake/Gpgmepp
+ $(INSTALL) GpgmeppConfig.cmake \
+ $(DESTDIR)$(libdir)/cmake/Gpgmepp/GpgmeppConfig.cmake
+ $(INSTALL) GpgmeppConfigVersion.cmake \
+ $(DESTDIR)$(libdir)/cmake/Gpgmepp/GpgmeppConfigVersion.cmake
+
+uninstall-cmake-files:
+ -rm $(DESTDIR)$(libdir)/cmake/Gpgmepp/GpgmeppConfigVersion.cmake
+ -rm $(DESTDIR)$(libdir)/cmake/Gpgmepp/GpgmeppConfig.cmake
+ -rmdir $(DESTDIR)$(libdir)/cmake/Gpgmepp/
+
+install-data-local: install-cmake-files
+
+uninstall-local: uninstall-cmake-files
+
+CLEANFILES = GpgmeppConfig.cmake
diff --git a/lang/cpp/src/Makefile.in b/lang/cpp/src/Makefile.in
new file mode 100644
index 0000000..9237d27
--- /dev/null
+++ b/lang/cpp/src/Makefile.in
@@ -0,0 +1,955 @@
+# Makefile.in generated by automake 1.14.1 from Makefile.am.
+# @configure_input@
+
+# Copyright (C) 1994-2013 Free Software Foundation, Inc.
+
+# This Makefile.in is free software; the Free Software Foundation
+# gives unlimited permission to copy and/or distribute it,
+# with or without modifications, as long as this notice is preserved.
+
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY, to the extent permitted by law; without
+# even the implied warranty of MERCHANTABILITY or FITNESS FOR A
+# PARTICULAR PURPOSE.
+
+@SET_MAKE@
+
+# Makefile.am for GPGMEPP.
+# Copyright (C) 2016 Intevation GmbH
+#
+# This file is part of GPGMEPP.
+#
+# GPGME-CL 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.
+#
+# GPGME-CL is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU Lesser General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program; if not, write to the Free Software
+# Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
+# 02111-1307, USA
+
+
+VPATH = @srcdir@
+am__is_gnu_make = test -n '$(MAKEFILE_LIST)' && test -n '$(MAKELEVEL)'
+am__make_running_with_option = \
+ case $${target_option-} in \
+ ?) ;; \
+ *) echo "am__make_running_with_option: internal error: invalid" \
+ "target option '$${target_option-}' specified" >&2; \
+ exit 1;; \
+ esac; \
+ has_opt=no; \
+ sane_makeflags=$$MAKEFLAGS; \
+ if $(am__is_gnu_make); then \
+ sane_makeflags=$$MFLAGS; \
+ else \
+ case $$MAKEFLAGS in \
+ *\\[\ \ ]*) \
+ bs=\\; \
+ sane_makeflags=`printf '%s\n' "$$MAKEFLAGS" \
+ | sed "s/$$bs$$bs[$$bs $$bs ]*//g"`;; \
+ esac; \
+ fi; \
+ skip_next=no; \
+ strip_trailopt () \
+ { \
+ flg=`printf '%s\n' "$$flg" | sed "s/$$1.*$$//"`; \
+ }; \
+ for flg in $$sane_makeflags; do \
+ test $$skip_next = yes && { skip_next=no; continue; }; \
+ case $$flg in \
+ *=*|--*) continue;; \
+ -*I) strip_trailopt 'I'; skip_next=yes;; \
+ -*I?*) strip_trailopt 'I';; \
+ -*O) strip_trailopt 'O'; skip_next=yes;; \
+ -*O?*) strip_trailopt 'O';; \
+ -*l) strip_trailopt 'l'; skip_next=yes;; \
+ -*l?*) strip_trailopt 'l';; \
+ -[dEDm]) skip_next=yes;; \
+ -[JT]) skip_next=yes;; \
+ esac; \
+ case $$flg in \
+ *$$target_option*) has_opt=yes; break;; \
+ esac; \
+ done; \
+ test $$has_opt = yes
+am__make_dryrun = (target_option=n; $(am__make_running_with_option))
+am__make_keepgoing = (target_option=k; $(am__make_running_with_option))
+pkgdatadir = $(datadir)/@PACKAGE@
+pkgincludedir = $(includedir)/@PACKAGE@
+pkglibdir = $(libdir)/@PACKAGE@
+pkglibexecdir = $(libexecdir)/@PACKAGE@
+am__cd = CDPATH="$${ZSH_VERSION+.}$(PATH_SEPARATOR)" && cd
+install_sh_DATA = $(install_sh) -c -m 644
+install_sh_PROGRAM = $(install_sh) -c
+install_sh_SCRIPT = $(install_sh) -c
+INSTALL_HEADER = $(INSTALL_DATA)
+transform = $(program_transform_name)
+NORMAL_INSTALL = :
+PRE_INSTALL = :
+POST_INSTALL = :
+NORMAL_UNINSTALL = :
+PRE_UNINSTALL = :
+POST_UNINSTALL = :
+build_triplet = @build@
+host_triplet = @host@
+subdir = lang/cpp/src
+DIST_COMMON = $(srcdir)/Makefile.in $(srcdir)/Makefile.am \
+ $(top_srcdir)/build-aux/mkinstalldirs \
+ $(srcdir)/GpgmeppConfig.cmake.in.in \
+ $(srcdir)/GpgmeppConfigVersion.cmake.in \
+ $(srcdir)/gpgmepp_version.h.in $(top_srcdir)/build-aux/depcomp \
+ $(gpgmeppinclude_HEADERS) $(nobase_gpgmeppinclude_HEADERS)
+ACLOCAL_M4 = $(top_srcdir)/aclocal.m4
+am__aclocal_m4_deps = $(top_srcdir)/m4/ax_cxx_compile_stdcxx.m4 \
+ $(top_srcdir)/m4/ax_pkg_swig.m4 \
+ $(top_srcdir)/m4/ax_python_devel.m4 \
+ $(top_srcdir)/m4/glib-2.0.m4 $(top_srcdir)/m4/glibc21.m4 \
+ $(top_srcdir)/m4/gnupg-ttyname.m4 \
+ $(top_srcdir)/m4/gpg-error.m4 $(top_srcdir)/m4/libassuan.m4 \
+ $(top_srcdir)/m4/libtool.m4 $(top_srcdir)/m4/ltoptions.m4 \
+ $(top_srcdir)/m4/ltsugar.m4 $(top_srcdir)/m4/ltversion.m4 \
+ $(top_srcdir)/m4/lt~obsolete.m4 $(top_srcdir)/m4/pkg.m4 \
+ $(top_srcdir)/m4/qt.m4 $(top_srcdir)/acinclude.m4 \
+ $(top_srcdir)/configure.ac
+am__configure_deps = $(am__aclocal_m4_deps) $(CONFIGURE_DEPENDENCIES) \
+ $(ACLOCAL_M4)
+mkinstalldirs = $(SHELL) $(top_srcdir)/build-aux/mkinstalldirs
+CONFIG_HEADER = $(top_builddir)/config.h
+CONFIG_CLEAN_FILES = GpgmeppConfig.cmake.in GpgmeppConfigVersion.cmake \
+ gpgmepp_version.h
+CONFIG_CLEAN_VPATH_FILES =
+am__vpath_adj_setup = srcdirstrip=`echo "$(srcdir)" | sed 's|.|.|g'`;
+am__vpath_adj = case $$p in \
+ $(srcdir)/*) f=`echo "$$p" | sed "s|^$$srcdirstrip/||"`;; \
+ *) f=$$p;; \
+ esac;
+am__strip_dir = f=`echo $$p | sed -e 's|^.*/||'`;
+am__install_max = 40
+am__nobase_strip_setup = \
+ srcdirstrip=`echo "$(srcdir)" | sed 's/[].[^$$\\*|]/\\\\&/g'`
+am__nobase_strip = \
+ for p in $$list; do echo "$$p"; done | sed -e "s|$$srcdirstrip/||"
+am__nobase_list = $(am__nobase_strip_setup); \
+ for p in $$list; do echo "$$p $$p"; done | \
+ sed "s| $$srcdirstrip/| |;"' / .*\//!s/ .*/ ./; s,\( .*\)/[^/]*$$,\1,' | \
+ $(AWK) 'BEGIN { files["."] = "" } { files[$$2] = files[$$2] " " $$1; \
+ if (++n[$$2] == $(am__install_max)) \
+ { print $$2, files[$$2]; n[$$2] = 0; files[$$2] = "" } } \
+ END { for (dir in files) print dir, files[dir] }'
+am__base_list = \
+ sed '$$!N;$$!N;$$!N;$$!N;$$!N;$$!N;$$!N;s/\n/ /g' | \
+ sed '$$!N;$$!N;$$!N;$$!N;s/\n/ /g'
+am__uninstall_files_from_dir = { \
+ test -z "$$files" \
+ || { test ! -d "$$dir" && test ! -f "$$dir" && test ! -r "$$dir"; } \
+ || { echo " ( cd '$$dir' && rm -f" $$files ")"; \
+ $(am__cd) "$$dir" && rm -f $$files; }; \
+ }
+am__installdirs = "$(DESTDIR)$(libdir)" \
+ "$(DESTDIR)$(gpgmeppincludedir)" \
+ "$(DESTDIR)$(gpgmeppincludedir)" "$(DESTDIR)$(includedir)"
+LTLIBRARIES = $(lib_LTLIBRARIES)
+libgpgmepp_la_DEPENDENCIES = ../../../src/libgpgme.la
+am__objects_1 = exception.lo context.lo key.lo trustitem.lo data.lo \
+ callbacks.lo eventloopinteractor.lo editinteractor.lo \
+ keylistresult.lo keygenerationresult.lo importresult.lo \
+ decryptionresult.lo verificationresult.lo signingresult.lo \
+ encryptionresult.lo engineinfo.lo \
+ gpgsetexpirytimeeditinteractor.lo \
+ gpgsetownertrusteditinteractor.lo gpgsignkeyeditinteractor.lo \
+ gpgadduserideditinteractor.lo defaultassuantransaction.lo \
+ scdgetinfoassuantransaction.lo \
+ gpgagentgetinfoassuantransaction.lo vfsmountresult.lo \
+ configuration.lo tofuinfo.lo
+am__objects_2 =
+am_libgpgmepp_la_OBJECTS = $(am__objects_1) $(am__objects_2) \
+ context_vanilla.lo $(am__objects_2) $(am__objects_2)
+libgpgmepp_la_OBJECTS = $(am_libgpgmepp_la_OBJECTS)
+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 =
+libgpgmepp_la_LINK = $(LIBTOOL) $(AM_V_lt) --tag=CXX \
+ $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=link $(CXXLD) \
+ $(AM_CXXFLAGS) $(CXXFLAGS) $(libgpgmepp_la_LDFLAGS) $(LDFLAGS) \
+ -o $@
+AM_V_P = $(am__v_P_@AM_V@)
+am__v_P_ = $(am__v_P_@AM_DEFAULT_V@)
+am__v_P_0 = false
+am__v_P_1 = :
+AM_V_GEN = $(am__v_GEN_@AM_V@)
+am__v_GEN_ = $(am__v_GEN_@AM_DEFAULT_V@)
+am__v_GEN_0 = @echo " GEN " $@;
+am__v_GEN_1 =
+AM_V_at = $(am__v_at_@AM_V@)
+am__v_at_ = $(am__v_at_@AM_DEFAULT_V@)
+am__v_at_0 = @
+am__v_at_1 =
+DEFAULT_INCLUDES = -I.@am__isrc@ -I$(top_builddir)
+depcomp = $(SHELL) $(top_srcdir)/build-aux/depcomp
+am__depfiles_maybe = depfiles
+am__mv = mv -f
+CXXCOMPILE = $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) \
+ $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS)
+LTCXXCOMPILE = $(LIBTOOL) $(AM_V_lt) --tag=CXX $(AM_LIBTOOLFLAGS) \
+ $(LIBTOOLFLAGS) --mode=compile $(CXX) $(DEFS) \
+ $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) \
+ $(AM_CXXFLAGS) $(CXXFLAGS)
+AM_V_CXX = $(am__v_CXX_@AM_V@)
+am__v_CXX_ = $(am__v_CXX_@AM_DEFAULT_V@)
+am__v_CXX_0 = @echo " CXX " $@;
+am__v_CXX_1 =
+CXXLD = $(CXX)
+CXXLINK = $(LIBTOOL) $(AM_V_lt) --tag=CXX $(AM_LIBTOOLFLAGS) \
+ $(LIBTOOLFLAGS) --mode=link $(CXXLD) $(AM_CXXFLAGS) \
+ $(CXXFLAGS) $(AM_LDFLAGS) $(LDFLAGS) -o $@
+AM_V_CXXLD = $(am__v_CXXLD_@AM_V@)
+am__v_CXXLD_ = $(am__v_CXXLD_@AM_DEFAULT_V@)
+am__v_CXXLD_0 = @echo " CXXLD " $@;
+am__v_CXXLD_1 =
+COMPILE = $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) \
+ $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS)
+LTCOMPILE = $(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) \
+ $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) \
+ $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) \
+ $(AM_CFLAGS) $(CFLAGS)
+AM_V_CC = $(am__v_CC_@AM_V@)
+am__v_CC_ = $(am__v_CC_@AM_DEFAULT_V@)
+am__v_CC_0 = @echo " CC " $@;
+am__v_CC_1 =
+CCLD = $(CC)
+LINK = $(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) \
+ $(LIBTOOLFLAGS) --mode=link $(CCLD) $(AM_CFLAGS) $(CFLAGS) \
+ $(AM_LDFLAGS) $(LDFLAGS) -o $@
+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 = $(libgpgmepp_la_SOURCES)
+DIST_SOURCES = $(libgpgmepp_la_SOURCES)
+am__can_run_installinfo = \
+ case $$AM_UPDATE_INFO_DIR in \
+ n|no|NO) false;; \
+ *) (install-info --version) >/dev/null 2>&1;; \
+ esac
+HEADERS = $(gpgmeppinclude_HEADERS) $(nobase_gpgmeppinclude_HEADERS) \
+ $(nodist_include_HEADERS)
+am__tagged_files = $(HEADERS) $(SOURCES) $(TAGS_FILES) $(LISP)
+# Read a list of newline-separated strings from the standard input,
+# and print each of them once, without duplicates. Input order is
+# *not* preserved.
+am__uniquify_input = $(AWK) '\
+ BEGIN { nonempty = 0; } \
+ { items[$$0] = 1; nonempty = 1; } \
+ END { if (nonempty) { for (i in items) print i; }; } \
+'
+# Make sure the list of sources is unique. This is necessary because,
+# e.g., the same source file might be shared among _SOURCES variables
+# for different programs/libraries.
+am__define_uniq_tagged_files = \
+ list='$(am__tagged_files)'; \
+ unique=`for i in $$list; do \
+ if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \
+ done | $(am__uniquify_input)`
+ETAGS = etags
+CTAGS = ctags
+DISTFILES = $(DIST_COMMON) $(DIST_SOURCES) $(TEXINFOS) $(EXTRA_DIST)
+ACLOCAL = @ACLOCAL@
+AMTAR = @AMTAR@
+AM_DEFAULT_VERBOSITY = @AM_DEFAULT_VERBOSITY@
+AR = @AR@
+AS = @AS@
+AUTOCONF = @AUTOCONF@
+AUTOHEADER = @AUTOHEADER@
+AUTOMAKE = @AUTOMAKE@
+AWK = @AWK@
+BUILD_FILEVERSION = @BUILD_FILEVERSION@
+BUILD_REVISION = @BUILD_REVISION@
+BUILD_TIMESTAMP = @BUILD_TIMESTAMP@
+CC = @CC@
+CCDEPMODE = @CCDEPMODE@
+CC_FOR_BUILD = @CC_FOR_BUILD@
+CFLAGS = @CFLAGS@
+CPP = @CPP@
+CPPFLAGS = @CPPFLAGS@
+CXX = @CXX@
+CXXCPP = @CXXCPP@
+CXXDEPMODE = @CXXDEPMODE@
+CXXFLAGS = @CXXFLAGS@
+CYGPATH_W = @CYGPATH_W@
+DEFS = @DEFS@
+DEPDIR = @DEPDIR@
+DLLTOOL = @DLLTOOL@
+DOXYGEN = @DOXYGEN@
+DSYMUTIL = @DSYMUTIL@
+DUMPBIN = @DUMPBIN@
+ECHO_C = @ECHO_C@
+ECHO_N = @ECHO_N@
+ECHO_T = @ECHO_T@
+EGREP = @EGREP@
+ENABLED_LANGUAGES = @ENABLED_LANGUAGES@
+EXEEXT = @EXEEXT@
+FGREP = @FGREP@
+GITLOG_TO_CHANGELOG = @GITLOG_TO_CHANGELOG@
+GLIBC21 = @GLIBC21@
+GLIB_CFLAGS = @GLIB_CFLAGS@
+GLIB_GENMARSHAL = @GLIB_GENMARSHAL@
+GLIB_LIBS = @GLIB_LIBS@
+GLIB_MKENUMS = @GLIB_MKENUMS@
+GOBJECT_QUERY = @GOBJECT_QUERY@
+GPGME_CONFIG_API_VERSION = @GPGME_CONFIG_API_VERSION@
+GPGME_CONFIG_AVAIL_LANG = @GPGME_CONFIG_AVAIL_LANG@
+GPGME_CONFIG_CFLAGS = @GPGME_CONFIG_CFLAGS@
+GPGME_CONFIG_HOST = @GPGME_CONFIG_HOST@
+GPGME_CONFIG_LIBS = @GPGME_CONFIG_LIBS@
+GPGME_QTTEST_CFLAGS = @GPGME_QTTEST_CFLAGS@
+GPGME_QTTEST_LIBS = @GPGME_QTTEST_LIBS@
+GPGME_QT_CFLAGS = @GPGME_QT_CFLAGS@
+GPGME_QT_LIBS = @GPGME_QT_LIBS@
+GPG_ERROR_CFLAGS = @GPG_ERROR_CFLAGS@
+GPG_ERROR_CONFIG = @GPG_ERROR_CONFIG@
+GPG_ERROR_LIBS = @GPG_ERROR_LIBS@
+GPG_ERROR_MT_CFLAGS = @GPG_ERROR_MT_CFLAGS@
+GPG_ERROR_MT_LIBS = @GPG_ERROR_MT_LIBS@
+GRAPHVIZ = @GRAPHVIZ@
+GREP = @GREP@
+HAVE_CXX11 = @HAVE_CXX11@
+HAVE_DOT = @HAVE_DOT@
+INSTALL = @INSTALL@
+INSTALL_DATA = @INSTALL_DATA@
+INSTALL_PROGRAM = @INSTALL_PROGRAM@
+INSTALL_SCRIPT = @INSTALL_SCRIPT@
+INSTALL_STRIP_PROGRAM = @INSTALL_STRIP_PROGRAM@
+LD = @LD@
+LDFLAGS = @LDFLAGS@
+LIBASSUAN_CFLAGS = @LIBASSUAN_CFLAGS@
+LIBASSUAN_CONFIG = @LIBASSUAN_CONFIG@
+LIBASSUAN_LIBS = @LIBASSUAN_LIBS@
+LIBGPGMEPP_LT_AGE = @LIBGPGMEPP_LT_AGE@
+LIBGPGMEPP_LT_CURRENT = @LIBGPGMEPP_LT_CURRENT@
+LIBGPGMEPP_LT_REVISION = @LIBGPGMEPP_LT_REVISION@
+LIBGPGME_LT_AGE = @LIBGPGME_LT_AGE@
+LIBGPGME_LT_CURRENT = @LIBGPGME_LT_CURRENT@
+LIBGPGME_LT_REVISION = @LIBGPGME_LT_REVISION@
+LIBOBJS = @LIBOBJS@
+LIBQGPGME_LT_AGE = @LIBQGPGME_LT_AGE@
+LIBQGPGME_LT_CURRENT = @LIBQGPGME_LT_CURRENT@
+LIBQGPGME_LT_REVISION = @LIBQGPGME_LT_REVISION@
+LIBS = @LIBS@
+LIBTOOL = @LIBTOOL@
+LIPO = @LIPO@
+LN_S = @LN_S@
+LTLIBOBJS = @LTLIBOBJS@
+MAINT = @MAINT@
+MAKEINFO = @MAKEINFO@
+MANIFEST_TOOL = @MANIFEST_TOOL@
+MKDIR_P = @MKDIR_P@
+MOC = @MOC@
+MOC2 = @MOC2@
+NEED__FILE_OFFSET_BITS = @NEED__FILE_OFFSET_BITS@
+NM = @NM@
+NMEDIT = @NMEDIT@
+OBJDUMP = @OBJDUMP@
+OBJEXT = @OBJEXT@
+OTOOL = @OTOOL@
+OTOOL64 = @OTOOL64@
+PACKAGE = @PACKAGE@
+PACKAGE_BUGREPORT = @PACKAGE_BUGREPORT@
+PACKAGE_NAME = @PACKAGE_NAME@
+PACKAGE_STRING = @PACKAGE_STRING@
+PACKAGE_TARNAME = @PACKAGE_TARNAME@
+PACKAGE_URL = @PACKAGE_URL@
+PACKAGE_VERSION = @PACKAGE_VERSION@
+PATH_SEPARATOR = @PATH_SEPARATOR@
+PKG_CONFIG = @PKG_CONFIG@
+PYTHON = @PYTHON@
+PYTHONS = @PYTHONS@
+PYTHON_CPPFLAGS = @PYTHON_CPPFLAGS@
+PYTHON_EXEC_PREFIX = @PYTHON_EXEC_PREFIX@
+PYTHON_EXTRA_LDFLAGS = @PYTHON_EXTRA_LDFLAGS@
+PYTHON_EXTRA_LIBS = @PYTHON_EXTRA_LIBS@
+PYTHON_LDFLAGS = @PYTHON_LDFLAGS@
+PYTHON_PLATFORM = @PYTHON_PLATFORM@
+PYTHON_PREFIX = @PYTHON_PREFIX@
+PYTHON_SITE_PKG = @PYTHON_SITE_PKG@
+PYTHON_VERSION = @PYTHON_VERSION@
+PYTHON_VERSIONS = @PYTHON_VERSIONS@
+QTCHOOSER = @QTCHOOSER@
+RANLIB = @RANLIB@
+RC = @RC@
+SED = @SED@
+SET_MAKE = @SET_MAKE@
+SHELL = @SHELL@
+STRIP = @STRIP@
+SWIG = @SWIG@
+SWIG_LIB = @SWIG_LIB@
+SYSROOT = @SYSROOT@
+VERSION = @VERSION@
+VERSION_NUMBER = @VERSION_NUMBER@
+abs_builddir = @abs_builddir@
+abs_srcdir = @abs_srcdir@
+abs_top_builddir = @abs_top_builddir@
+abs_top_srcdir = @abs_top_srcdir@
+ac_ct_AR = @ac_ct_AR@
+ac_ct_CC = @ac_ct_CC@
+ac_ct_CXX = @ac_ct_CXX@
+ac_ct_DUMPBIN = @ac_ct_DUMPBIN@
+am__include = @am__include@
+am__leading_dot = @am__leading_dot@
+am__quote = @am__quote@
+am__tar = @am__tar@
+am__untar = @am__untar@
+bindir = @bindir@
+build = @build@
+build_alias = @build_alias@
+build_cpu = @build_cpu@
+build_os = @build_os@
+build_vendor = @build_vendor@
+builddir = @builddir@
+datadir = @datadir@
+datarootdir = @datarootdir@
+docdir = @docdir@
+dvidir = @dvidir@
+emacs_local_vars_begin = @emacs_local_vars_begin@
+emacs_local_vars_end = @emacs_local_vars_end@
+emacs_local_vars_read_only = @emacs_local_vars_read_only@
+exec_prefix = @exec_prefix@
+host = @host@
+host_alias = @host_alias@
+host_cpu = @host_cpu@
+host_os = @host_os@
+host_vendor = @host_vendor@
+htmldir = @htmldir@
+includedir = @includedir@
+infodir = @infodir@
+install_sh = @install_sh@
+libdir = @libdir@
+libexecdir = @libexecdir@
+localedir = @localedir@
+localstatedir = @localstatedir@
+mandir = @mandir@
+mkdir_p = @mkdir_p@
+oldincludedir = @oldincludedir@
+pdfdir = @pdfdir@
+pkgpyexecdir = @pkgpyexecdir@
+pkgpythondir = @pkgpythondir@
+prefix = @prefix@
+program_transform_name = @program_transform_name@
+psdir = @psdir@
+pyexecdir = @pyexecdir@
+pythondir = @pythondir@
+sbindir = @sbindir@
+sharedstatedir = @sharedstatedir@
+srcdir = @srcdir@
+sysconfdir = @sysconfdir@
+target_alias = @target_alias@
+top_build_prefix = @top_build_prefix@
+top_builddir = @top_builddir@
+top_srcdir = @top_srcdir@
+EXTRA_DIST = GpgmeppConfig.cmake.in.in GpgmeppConfigVersion.cmake.in \
+ gpgmepp_version.h.in
+
+lib_LTLIBRARIES = libgpgmepp.la
+main_sources = \
+ exception.cpp context.cpp key.cpp trustitem.cpp data.cpp callbacks.cpp \
+ eventloopinteractor.cpp editinteractor.cpp \
+ keylistresult.cpp keygenerationresult.cpp importresult.cpp \
+ decryptionresult.cpp verificationresult.cpp \
+ signingresult.cpp encryptionresult.cpp \
+ engineinfo.cpp gpgsetexpirytimeeditinteractor.cpp \
+ gpgsetownertrusteditinteractor.cpp gpgsignkeyeditinteractor.cpp \
+ gpgadduserideditinteractor.cpp defaultassuantransaction.cpp \
+ scdgetinfoassuantransaction.cpp gpgagentgetinfoassuantransaction.cpp \
+ vfsmountresult.cpp configuration.cpp tofuinfo.cpp
+
+gpgmepp_headers = \
+ configuration.h context.h data.h decryptionresult.h \
+ defaultassuantransaction.h editinteractor.h encryptionresult.h \
+ engineinfo.h error.h eventloopinteractor.h exception.h global.h \
+ gpgadduserideditinteractor.h gpgagentgetinfoassuantransaction.h \
+ gpgmefw.h gpgsetexpirytimeeditinteractor.h \
+ gpgsetownertrusteditinteractor.h gpgsignkeyeditinteractor.h \
+ importresult.h keygenerationresult.h key.h keylistresult.h \
+ notation.h result.h scdgetinfoassuantransaction.h signingresult.h \
+ trustitem.h verificationresult.h vfsmountresult.h gpgmepp_export.h \
+ tofuinfo.h
+
+private_gpgmepp_headers = \
+ result_p.h context_p.h util.h callbacks.h data_p.h
+
+interface_headers = \
+ interfaces/assuantransaction.h interfaces/dataprovider.h \
+ interfaces/passphraseprovider.h interfaces/progressprovider.h
+
+gpgmeppincludedir = $(includedir)/gpgme++
+gpgmeppinclude_HEADERS = $(gpgmepp_headers)
+nobase_gpgmeppinclude_HEADERS = $(interface_headers)
+nodist_include_HEADERS = gpgmepp_version.h
+libgpgmepp_la_SOURCES = $(main_sources) $(gpgmepp_headers) context_vanilla.cpp \
+ $(interface_headers) $(private_gpgmepp_headers)
+
+AM_CPPFLAGS = -I$(top_builddir)/src @GPG_ERROR_CFLAGS@ @LIBASSUAN_CFLAGS@ \
+ -DBUILDING_GPGMEPP
+
+libgpgmepp_la_LIBADD = ../../../src/libgpgme.la @LIBASSUAN_LIBS@
+libgpgmepp_la_LDFLAGS = -version-info \
+ @LIBGPGMEPP_LT_CURRENT@:@LIBGPGMEPP_LT_REVISION@:@LIBGPGMEPP_LT_AGE@
+
+@HAVE_W32_SYSTEM_FALSE@libsuffix = .so
+@HAVE_W32_SYSTEM_TRUE@libsuffix = .dll.a
+CLEANFILES = GpgmeppConfig.cmake
+all: all-am
+
+.SUFFIXES:
+.SUFFIXES: .cpp .lo .o .obj
+$(srcdir)/Makefile.in: @MAINTAINER_MODE_TRUE@ $(srcdir)/Makefile.am $(am__configure_deps)
+ @for dep in $?; do \
+ case '$(am__configure_deps)' in \
+ *$$dep*) \
+ ( cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh ) \
+ && { if test -f $@; then exit 0; else break; fi; }; \
+ exit 1;; \
+ esac; \
+ done; \
+ echo ' cd $(top_srcdir) && $(AUTOMAKE) --gnu lang/cpp/src/Makefile'; \
+ $(am__cd) $(top_srcdir) && \
+ $(AUTOMAKE) --gnu lang/cpp/src/Makefile
+.PRECIOUS: Makefile
+Makefile: $(srcdir)/Makefile.in $(top_builddir)/config.status
+ @case '$?' in \
+ *config.status*) \
+ cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh;; \
+ *) \
+ echo ' cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__depfiles_maybe)'; \
+ cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__depfiles_maybe);; \
+ esac;
+
+$(top_builddir)/config.status: $(top_srcdir)/configure $(CONFIG_STATUS_DEPENDENCIES)
+ cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh
+
+$(top_srcdir)/configure: @MAINTAINER_MODE_TRUE@ $(am__configure_deps)
+ cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh
+$(ACLOCAL_M4): @MAINTAINER_MODE_TRUE@ $(am__aclocal_m4_deps)
+ cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh
+$(am__aclocal_m4_deps):
+GpgmeppConfig.cmake.in: $(top_builddir)/config.status $(srcdir)/GpgmeppConfig.cmake.in.in
+ cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@
+GpgmeppConfigVersion.cmake: $(top_builddir)/config.status $(srcdir)/GpgmeppConfigVersion.cmake.in
+ cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@
+gpgmepp_version.h: $(top_builddir)/config.status $(srcdir)/gpgmepp_version.h.in
+ cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@
+
+install-libLTLIBRARIES: $(lib_LTLIBRARIES)
+ @$(NORMAL_INSTALL)
+ @list='$(lib_LTLIBRARIES)'; test -n "$(libdir)" || list=; \
+ list2=; for p in $$list; do \
+ if test -f $$p; then \
+ list2="$$list2 $$p"; \
+ else :; fi; \
+ done; \
+ test -z "$$list2" || { \
+ echo " $(MKDIR_P) '$(DESTDIR)$(libdir)'"; \
+ $(MKDIR_P) "$(DESTDIR)$(libdir)" || exit 1; \
+ echo " $(LIBTOOL) $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=install $(INSTALL) $(INSTALL_STRIP_FLAG) $$list2 '$(DESTDIR)$(libdir)'"; \
+ $(LIBTOOL) $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=install $(INSTALL) $(INSTALL_STRIP_FLAG) $$list2 "$(DESTDIR)$(libdir)"; \
+ }
+
+uninstall-libLTLIBRARIES:
+ @$(NORMAL_UNINSTALL)
+ @list='$(lib_LTLIBRARIES)'; test -n "$(libdir)" || list=; \
+ for p in $$list; do \
+ $(am__strip_dir) \
+ echo " $(LIBTOOL) $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=uninstall rm -f '$(DESTDIR)$(libdir)/$$f'"; \
+ $(LIBTOOL) $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=uninstall rm -f "$(DESTDIR)$(libdir)/$$f"; \
+ done
+
+clean-libLTLIBRARIES:
+ -test -z "$(lib_LTLIBRARIES)" || rm -f $(lib_LTLIBRARIES)
+ @list='$(lib_LTLIBRARIES)'; \
+ locs=`for p in $$list; do echo $$p; done | \
+ sed 's|^[^/]*$$|.|; s|/[^/]*$$||; s|$$|/so_locations|' | \
+ sort -u`; \
+ test -z "$$locs" || { \
+ echo rm -f $${locs}; \
+ rm -f $${locs}; \
+ }
+
+libgpgmepp.la: $(libgpgmepp_la_OBJECTS) $(libgpgmepp_la_DEPENDENCIES) $(EXTRA_libgpgmepp_la_DEPENDENCIES)
+ $(AM_V_CXXLD)$(libgpgmepp_la_LINK) -rpath $(libdir) $(libgpgmepp_la_OBJECTS) $(libgpgmepp_la_LIBADD) $(LIBS)
+
+mostlyclean-compile:
+ -rm -f *.$(OBJEXT)
+
+distclean-compile:
+ -rm -f *.tab.c
+
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/callbacks.Plo@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/configuration.Plo@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/context.Plo@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/context_vanilla.Plo@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/data.Plo@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/decryptionresult.Plo@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/defaultassuantransaction.Plo@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/editinteractor.Plo@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/encryptionresult.Plo@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/engineinfo.Plo@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/eventloopinteractor.Plo@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/exception.Plo@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/gpgadduserideditinteractor.Plo@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/gpgagentgetinfoassuantransaction.Plo@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/gpgsetexpirytimeeditinteractor.Plo@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/gpgsetownertrusteditinteractor.Plo@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/gpgsignkeyeditinteractor.Plo@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/importresult.Plo@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/key.Plo@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/keygenerationresult.Plo@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/keylistresult.Plo@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/scdgetinfoassuantransaction.Plo@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/signingresult.Plo@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/tofuinfo.Plo@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/trustitem.Plo@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/verificationresult.Plo@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/vfsmountresult.Plo@am__quote@
+
+.cpp.o:
+@am__fastdepCXX_TRUE@ $(AM_V_CXX)$(CXXCOMPILE) -MT $@ -MD -MP -MF $(DEPDIR)/$*.Tpo -c -o $@ $<
+@am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/$*.Tpo $(DEPDIR)/$*.Po
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@ $(AM_V_CXX)source='$<' object='$@' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCXX_FALSE@ $(AM_V_CXX@am__nodep@)$(CXXCOMPILE) -c -o $@ $<
+
+.cpp.obj:
+@am__fastdepCXX_TRUE@ $(AM_V_CXX)$(CXXCOMPILE) -MT $@ -MD -MP -MF $(DEPDIR)/$*.Tpo -c -o $@ `$(CYGPATH_W) '$<'`
+@am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/$*.Tpo $(DEPDIR)/$*.Po
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@ $(AM_V_CXX)source='$<' object='$@' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCXX_FALSE@ $(AM_V_CXX@am__nodep@)$(CXXCOMPILE) -c -o $@ `$(CYGPATH_W) '$<'`
+
+.cpp.lo:
+@am__fastdepCXX_TRUE@ $(AM_V_CXX)$(LTCXXCOMPILE) -MT $@ -MD -MP -MF $(DEPDIR)/$*.Tpo -c -o $@ $<
+@am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/$*.Tpo $(DEPDIR)/$*.Plo
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@ $(AM_V_CXX)source='$<' object='$@' libtool=yes @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCXX_FALSE@ $(AM_V_CXX@am__nodep@)$(LTCXXCOMPILE) -c -o $@ $<
+
+mostlyclean-libtool:
+ -rm -f *.lo
+
+clean-libtool:
+ -rm -rf .libs _libs
+install-gpgmeppincludeHEADERS: $(gpgmeppinclude_HEADERS)
+ @$(NORMAL_INSTALL)
+ @list='$(gpgmeppinclude_HEADERS)'; test -n "$(gpgmeppincludedir)" || list=; \
+ if test -n "$$list"; then \
+ echo " $(MKDIR_P) '$(DESTDIR)$(gpgmeppincludedir)'"; \
+ $(MKDIR_P) "$(DESTDIR)$(gpgmeppincludedir)" || exit 1; \
+ fi; \
+ for p in $$list; do \
+ if test -f "$$p"; then d=; else d="$(srcdir)/"; fi; \
+ echo "$$d$$p"; \
+ done | $(am__base_list) | \
+ while read files; do \
+ echo " $(INSTALL_HEADER) $$files '$(DESTDIR)$(gpgmeppincludedir)'"; \
+ $(INSTALL_HEADER) $$files "$(DESTDIR)$(gpgmeppincludedir)" || exit $$?; \
+ done
+
+uninstall-gpgmeppincludeHEADERS:
+ @$(NORMAL_UNINSTALL)
+ @list='$(gpgmeppinclude_HEADERS)'; test -n "$(gpgmeppincludedir)" || list=; \
+ files=`for p in $$list; do echo $$p; done | sed -e 's|^.*/||'`; \
+ dir='$(DESTDIR)$(gpgmeppincludedir)'; $(am__uninstall_files_from_dir)
+install-nobase_gpgmeppincludeHEADERS: $(nobase_gpgmeppinclude_HEADERS)
+ @$(NORMAL_INSTALL)
+ @list='$(nobase_gpgmeppinclude_HEADERS)'; test -n "$(gpgmeppincludedir)" || list=; \
+ if test -n "$$list"; then \
+ echo " $(MKDIR_P) '$(DESTDIR)$(gpgmeppincludedir)'"; \
+ $(MKDIR_P) "$(DESTDIR)$(gpgmeppincludedir)" || exit 1; \
+ fi; \
+ $(am__nobase_list) | while read dir files; do \
+ xfiles=; for file in $$files; do \
+ if test -f "$$file"; then xfiles="$$xfiles $$file"; \
+ else xfiles="$$xfiles $(srcdir)/$$file"; fi; done; \
+ test -z "$$xfiles" || { \
+ test "x$$dir" = x. || { \
+ echo " $(MKDIR_P) '$(DESTDIR)$(gpgmeppincludedir)/$$dir'"; \
+ $(MKDIR_P) "$(DESTDIR)$(gpgmeppincludedir)/$$dir"; }; \
+ echo " $(INSTALL_HEADER) $$xfiles '$(DESTDIR)$(gpgmeppincludedir)/$$dir'"; \
+ $(INSTALL_HEADER) $$xfiles "$(DESTDIR)$(gpgmeppincludedir)/$$dir" || exit $$?; }; \
+ done
+
+uninstall-nobase_gpgmeppincludeHEADERS:
+ @$(NORMAL_UNINSTALL)
+ @list='$(nobase_gpgmeppinclude_HEADERS)'; test -n "$(gpgmeppincludedir)" || list=; \
+ $(am__nobase_strip_setup); files=`$(am__nobase_strip)`; \
+ dir='$(DESTDIR)$(gpgmeppincludedir)'; $(am__uninstall_files_from_dir)
+install-nodist_includeHEADERS: $(nodist_include_HEADERS)
+ @$(NORMAL_INSTALL)
+ @list='$(nodist_include_HEADERS)'; test -n "$(includedir)" || list=; \
+ if test -n "$$list"; then \
+ echo " $(MKDIR_P) '$(DESTDIR)$(includedir)'"; \
+ $(MKDIR_P) "$(DESTDIR)$(includedir)" || exit 1; \
+ fi; \
+ for p in $$list; do \
+ if test -f "$$p"; then d=; else d="$(srcdir)/"; fi; \
+ echo "$$d$$p"; \
+ done | $(am__base_list) | \
+ while read files; do \
+ echo " $(INSTALL_HEADER) $$files '$(DESTDIR)$(includedir)'"; \
+ $(INSTALL_HEADER) $$files "$(DESTDIR)$(includedir)" || exit $$?; \
+ done
+
+uninstall-nodist_includeHEADERS:
+ @$(NORMAL_UNINSTALL)
+ @list='$(nodist_include_HEADERS)'; test -n "$(includedir)" || list=; \
+ files=`for p in $$list; do echo $$p; done | sed -e 's|^.*/||'`; \
+ dir='$(DESTDIR)$(includedir)'; $(am__uninstall_files_from_dir)
+
+ID: $(am__tagged_files)
+ $(am__define_uniq_tagged_files); mkid -fID $$unique
+tags: tags-am
+TAGS: tags
+
+tags-am: $(TAGS_DEPENDENCIES) $(am__tagged_files)
+ set x; \
+ here=`pwd`; \
+ $(am__define_uniq_tagged_files); \
+ shift; \
+ if test -z "$(ETAGS_ARGS)$$*$$unique"; then :; else \
+ test -n "$$unique" || unique=$$empty_fix; \
+ if test $$# -gt 0; then \
+ $(ETAGS) $(ETAGSFLAGS) $(AM_ETAGSFLAGS) $(ETAGS_ARGS) \
+ "$$@" $$unique; \
+ else \
+ $(ETAGS) $(ETAGSFLAGS) $(AM_ETAGSFLAGS) $(ETAGS_ARGS) \
+ $$unique; \
+ fi; \
+ fi
+ctags: ctags-am
+
+CTAGS: ctags
+ctags-am: $(TAGS_DEPENDENCIES) $(am__tagged_files)
+ $(am__define_uniq_tagged_files); \
+ test -z "$(CTAGS_ARGS)$$unique" \
+ || $(CTAGS) $(CTAGSFLAGS) $(AM_CTAGSFLAGS) $(CTAGS_ARGS) \
+ $$unique
+
+GTAGS:
+ here=`$(am__cd) $(top_builddir) && pwd` \
+ && $(am__cd) $(top_srcdir) \
+ && gtags -i $(GTAGS_ARGS) "$$here"
+cscopelist: cscopelist-am
+
+cscopelist-am: $(am__tagged_files)
+ list='$(am__tagged_files)'; \
+ case "$(srcdir)" in \
+ [\\/]* | ?:[\\/]*) sdir="$(srcdir)" ;; \
+ *) sdir=$(subdir)/$(srcdir) ;; \
+ esac; \
+ for i in $$list; do \
+ if test -f "$$i"; then \
+ echo "$(subdir)/$$i"; \
+ else \
+ echo "$$sdir/$$i"; \
+ fi; \
+ done >> $(top_builddir)/cscope.files
+
+distclean-tags:
+ -rm -f TAGS ID GTAGS GRTAGS GSYMS GPATH tags
+
+distdir: $(DISTFILES)
+ @srcdirstrip=`echo "$(srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \
+ topsrcdirstrip=`echo "$(top_srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \
+ list='$(DISTFILES)'; \
+ dist_files=`for file in $$list; do echo $$file; done | \
+ sed -e "s|^$$srcdirstrip/||;t" \
+ -e "s|^$$topsrcdirstrip/|$(top_builddir)/|;t"`; \
+ case $$dist_files in \
+ */*) $(MKDIR_P) `echo "$$dist_files" | \
+ sed '/\//!d;s|^|$(distdir)/|;s,/[^/]*$$,,' | \
+ sort -u` ;; \
+ esac; \
+ for file in $$dist_files; do \
+ if test -f $$file || test -d $$file; then d=.; else d=$(srcdir); fi; \
+ if test -d $$d/$$file; then \
+ dir=`echo "/$$file" | sed -e 's,/[^/]*$$,,'`; \
+ if test -d "$(distdir)/$$file"; then \
+ find "$(distdir)/$$file" -type d ! -perm -700 -exec chmod u+rwx {} \;; \
+ fi; \
+ if test -d $(srcdir)/$$file && test $$d != $(srcdir); then \
+ cp -fpR $(srcdir)/$$file "$(distdir)$$dir" || exit 1; \
+ find "$(distdir)/$$file" -type d ! -perm -700 -exec chmod u+rwx {} \;; \
+ fi; \
+ cp -fpR $$d/$$file "$(distdir)$$dir" || exit 1; \
+ else \
+ test -f "$(distdir)/$$file" \
+ || cp -p $$d/$$file "$(distdir)/$$file" \
+ || exit 1; \
+ fi; \
+ done
+check-am: all-am
+check: check-am
+all-am: Makefile $(LTLIBRARIES) $(HEADERS)
+installdirs:
+ for dir in "$(DESTDIR)$(libdir)" "$(DESTDIR)$(gpgmeppincludedir)" "$(DESTDIR)$(gpgmeppincludedir)" "$(DESTDIR)$(includedir)"; do \
+ test -z "$$dir" || $(MKDIR_P) "$$dir"; \
+ done
+install: install-am
+install-exec: install-exec-am
+install-data: install-data-am
+uninstall: uninstall-am
+
+install-am: all-am
+ @$(MAKE) $(AM_MAKEFLAGS) install-exec-am install-data-am
+
+installcheck: installcheck-am
+install-strip:
+ if test -z '$(STRIP)'; then \
+ $(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \
+ install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \
+ install; \
+ else \
+ $(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \
+ install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \
+ "INSTALL_PROGRAM_ENV=STRIPPROG='$(STRIP)'" install; \
+ fi
+mostlyclean-generic:
+
+clean-generic:
+ -test -z "$(CLEANFILES)" || rm -f $(CLEANFILES)
+
+distclean-generic:
+ -test -z "$(CONFIG_CLEAN_FILES)" || rm -f $(CONFIG_CLEAN_FILES)
+ -test . = "$(srcdir)" || test -z "$(CONFIG_CLEAN_VPATH_FILES)" || rm -f $(CONFIG_CLEAN_VPATH_FILES)
+
+maintainer-clean-generic:
+ @echo "This command is intended for maintainers to use"
+ @echo "it deletes files that may require special tools to rebuild."
+clean: clean-am
+
+clean-am: clean-generic clean-libLTLIBRARIES clean-libtool \
+ mostlyclean-am
+
+distclean: distclean-am
+ -rm -rf ./$(DEPDIR)
+ -rm -f Makefile
+distclean-am: clean-am distclean-compile distclean-generic \
+ distclean-tags
+
+dvi: dvi-am
+
+dvi-am:
+
+html: html-am
+
+html-am:
+
+info: info-am
+
+info-am:
+
+install-data-am: install-data-local install-gpgmeppincludeHEADERS \
+ install-nobase_gpgmeppincludeHEADERS \
+ install-nodist_includeHEADERS
+
+install-dvi: install-dvi-am
+
+install-dvi-am:
+
+install-exec-am: install-libLTLIBRARIES
+
+install-html: install-html-am
+
+install-html-am:
+
+install-info: install-info-am
+
+install-info-am:
+
+install-man:
+
+install-pdf: install-pdf-am
+
+install-pdf-am:
+
+install-ps: install-ps-am
+
+install-ps-am:
+
+installcheck-am:
+
+maintainer-clean: maintainer-clean-am
+ -rm -rf ./$(DEPDIR)
+ -rm -f Makefile
+maintainer-clean-am: distclean-am maintainer-clean-generic
+
+mostlyclean: mostlyclean-am
+
+mostlyclean-am: mostlyclean-compile mostlyclean-generic \
+ mostlyclean-libtool
+
+pdf: pdf-am
+
+pdf-am:
+
+ps: ps-am
+
+ps-am:
+
+uninstall-am: uninstall-gpgmeppincludeHEADERS uninstall-libLTLIBRARIES \
+ uninstall-local uninstall-nobase_gpgmeppincludeHEADERS \
+ uninstall-nodist_includeHEADERS
+
+.MAKE: install-am install-strip
+
+.PHONY: CTAGS GTAGS TAGS all all-am check check-am clean clean-generic \
+ clean-libLTLIBRARIES clean-libtool cscopelist-am ctags \
+ ctags-am distclean distclean-compile distclean-generic \
+ distclean-libtool distclean-tags distdir dvi dvi-am html \
+ html-am info info-am install install-am install-data \
+ install-data-am install-data-local install-dvi install-dvi-am \
+ install-exec install-exec-am install-gpgmeppincludeHEADERS \
+ install-html install-html-am install-info install-info-am \
+ install-libLTLIBRARIES install-man \
+ install-nobase_gpgmeppincludeHEADERS \
+ install-nodist_includeHEADERS install-pdf install-pdf-am \
+ install-ps install-ps-am install-strip installcheck \
+ installcheck-am installdirs maintainer-clean \
+ maintainer-clean-generic mostlyclean mostlyclean-compile \
+ mostlyclean-generic mostlyclean-libtool pdf pdf-am ps ps-am \
+ tags tags-am uninstall uninstall-am \
+ uninstall-gpgmeppincludeHEADERS uninstall-libLTLIBRARIES \
+ uninstall-local uninstall-nobase_gpgmeppincludeHEADERS \
+ uninstall-nodist_includeHEADERS
+
+
+GpgmeppConfig.cmake: GpgmeppConfig.cmake.in
+ sed -e 's|[@]resolved_libdir@|$(libdir)|g' < "$<" > "$@"
+ sed -e 's|[@]libsuffix@|$(libsuffix)|g' < "$@" > "$@".2
+ mv "$@".2 "$@"
+
+install-cmake-files: GpgmeppConfig.cmake GpgmeppConfigVersion.cmake
+ -$(INSTALL) -d $(DESTDIR)$(libdir)/cmake/Gpgmepp
+ $(INSTALL) GpgmeppConfig.cmake \
+ $(DESTDIR)$(libdir)/cmake/Gpgmepp/GpgmeppConfig.cmake
+ $(INSTALL) GpgmeppConfigVersion.cmake \
+ $(DESTDIR)$(libdir)/cmake/Gpgmepp/GpgmeppConfigVersion.cmake
+
+uninstall-cmake-files:
+ -rm $(DESTDIR)$(libdir)/cmake/Gpgmepp/GpgmeppConfigVersion.cmake
+ -rm $(DESTDIR)$(libdir)/cmake/Gpgmepp/GpgmeppConfig.cmake
+ -rmdir $(DESTDIR)$(libdir)/cmake/Gpgmepp/
+
+install-data-local: install-cmake-files
+
+uninstall-local: uninstall-cmake-files
+
+# Tell versions [3.59,3.63) of GNU make to not export all variables.
+# Otherwise a system limit (for SysV at least) may be exceeded.
+.NOEXPORT:
diff --git a/lang/cpp/src/callbacks.cpp b/lang/cpp/src/callbacks.cpp
new file mode 100644
index 0000000..4b4dd80
--- /dev/null
+++ b/lang/cpp/src/callbacks.cpp
@@ -0,0 +1,149 @@
+/*
+ callbacks.cpp - callback targets for internal use:
+ Copyright (C) 2003,2004 Klarälvdalens Datakonsult AB
+
+ This file is part of GPGME++.
+
+ GPGME++ is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Library General Public
+ License as published by the Free Software Foundation; either
+ version 2 of the License, or (at your option) any later version.
+
+ GPGME++ is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU Library General Public License for more details.
+
+ You should have received a copy of the GNU Library General Public License
+ along with GPGME++; see the file COPYING.LIB. If not, write to the
+ Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+ Boston, MA 02110-1301, USA.
+*/
+
+#include "callbacks.h"
+#include "util.h"
+
+#include <interfaces/progressprovider.h>
+#include <interfaces/passphraseprovider.h>
+#include <interfaces/dataprovider.h>
+#include <error.h>
+
+#include <gpgme.h>
+#include <gpg-error.h>
+
+#include <cassert>
+#include <cerrno>
+#include <cstring>
+#include <unistd.h>
+#include <stdlib.h>
+
+static inline gpgme_error_t make_err_from_syserror()
+{
+ return gpgme_error_from_syserror();
+}
+
+using GpgME::ProgressProvider;
+using GpgME::PassphraseProvider;
+using GpgME::DataProvider;
+
+void progress_callback(void *opaque, const char *what,
+ int type, int current, int total)
+{
+ ProgressProvider *provider = static_cast<ProgressProvider *>(opaque);
+ if (provider) {
+ provider->showProgress(what, type, current, total);
+ }
+}
+
+/* To avoid that a compiler optimizes certain memset calls away, these
+ macros may be used instead. */
+#define wipememory2(_ptr,_set,_len) do { \
+ volatile char *_vptr=(volatile char *)(_ptr); \
+ size_t _vlen=(_len); \
+ while(_vlen) { *_vptr=(_set); _vptr++; _vlen--; } \
+ } while(0)
+#define wipememory(_ptr,_len) wipememory2(_ptr,0,_len)
+
+gpgme_error_t passphrase_callback(void *opaque, const char *uid_hint, const char *desc,
+ int prev_was_bad, int fd)
+{
+ PassphraseProvider *provider = static_cast<PassphraseProvider *>(opaque);
+ bool canceled = false;
+ gpgme_error_t err = GPG_ERR_NO_ERROR;
+ char *passphrase = provider ? provider->getPassphrase(uid_hint, desc, prev_was_bad, canceled) : 0 ;
+ if (canceled) {
+ err = make_error(GPG_ERR_CANCELED);
+ } else {
+ if (passphrase && *passphrase) {
+ size_t passphrase_length = std::strlen(passphrase);
+ size_t written = 0;
+ do {
+ ssize_t now_written = gpgme_io_write(fd, passphrase + written, passphrase_length - written);
+ if (now_written < 0) {
+ err = make_err_from_syserror();
+ break;
+ }
+ written += now_written;
+ } while (written < passphrase_length);
+ }
+ }
+
+ if (passphrase && *passphrase) {
+ wipememory(passphrase, std::strlen(passphrase));
+ }
+ free(passphrase);
+ gpgme_io_write(fd, "\n", 1);
+ return err;
+}
+
+static gpgme_ssize_t
+data_read_callback(void *opaque, void *buf, size_t buflen)
+{
+ DataProvider *provider = static_cast<DataProvider *>(opaque);
+ if (!provider) {
+ gpgme_err_set_errno(gpgme_err_code_to_errno(GPG_ERR_EINVAL));
+ return -1;
+ }
+ return (gpgme_ssize_t)provider->read(buf, buflen);
+}
+
+static gpgme_ssize_t
+data_write_callback(void *opaque, const void *buf, size_t buflen)
+{
+ DataProvider *provider = static_cast<DataProvider *>(opaque);
+ if (!provider) {
+ gpgme_err_set_errno(gpgme_err_code_to_errno(GPG_ERR_EINVAL));
+ return -1;
+ }
+ return (gpgme_ssize_t)provider->write(buf, buflen);
+}
+
+static gpgme_off_t
+data_seek_callback(void *opaque, gpgme_off_t offset, int whence)
+{
+ DataProvider *provider = static_cast<DataProvider *>(opaque);
+ if (!provider) {
+ gpgme_err_set_errno(gpgme_err_code_to_errno(GPG_ERR_EINVAL));
+ return -1;
+ }
+ if (whence != SEEK_SET && whence != SEEK_CUR && whence != SEEK_END) {
+ gpgme_err_set_errno(gpgme_err_code_to_errno(GPG_ERR_EINVAL));
+ return -1;
+ }
+ return provider->seek((off_t)offset, whence);
+}
+
+static void data_release_callback(void *opaque)
+{
+ DataProvider *provider = static_cast<DataProvider *>(opaque);
+ if (provider) {
+ provider->release();
+ }
+}
+
+const gpgme_data_cbs GpgME::data_provider_callbacks = {
+ &data_read_callback,
+ &data_write_callback,
+ &data_seek_callback,
+ &data_release_callback
+};
diff --git a/lang/cpp/src/callbacks.h b/lang/cpp/src/callbacks.h
new file mode 100644
index 0000000..4206637
--- /dev/null
+++ b/lang/cpp/src/callbacks.h
@@ -0,0 +1,45 @@
+/*
+ callbacks.h - callback targets for internal use:
+ Copyright (C) 2003 Klarälvdalens Datakonsult AB
+
+ This file is part of GPGME++.
+
+ This is an internal header file, subject to change without
+ notice. DO NOT USE.
+
+ GPGME++ is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Library General Public
+ License as published by the Free Software Foundation; either
+ version 2 of the License, or (at your option) any later version.
+
+ GPGME++ is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU Library General Public License for more details.
+
+ You should have received a copy of the GNU Library General Public License
+ along with GPGME++; see the file COPYING.LIB. If not, write to the
+ Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+ Boston, MA 02110-1301, USA.
+*/
+
+#ifndef __GPGMEPP_CALLBACKS_H__
+#define __GPGMEPP_CALLBACKS_H__
+
+#include <gpgme.h>
+
+extern "C" {
+
+ void progress_callback(void *opaque, const char *what,
+ int type, int current, int total);
+ gpgme_error_t passphrase_callback(void *opaque, const char *uid_hint,
+ const char *desc, int prev_was_bad, int fd);
+}
+
+namespace GpgME
+{
+extern const gpgme_data_cbs data_provider_callbacks;
+extern const gpgme_edit_cb_t edit_interactor_callback;
+}
+
+#endif // __GPGME_CALLBACKS_H__
diff --git a/lang/cpp/src/configuration.cpp b/lang/cpp/src/configuration.cpp
new file mode 100644
index 0000000..7ef2883
--- /dev/null
+++ b/lang/cpp/src/configuration.cpp
@@ -0,0 +1,934 @@
+/*
+ configuration.cpp - wraps gpgme configuration components
+ Copyright (C) 2010 Klarälvdalens Datakonsult AB
+
+ This file is part of GPGME++.
+
+ GPGME++ is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Library General Public
+ License as published by the Free Software Foundation; either
+ version 2 of the License, or (at your option) any later version.
+
+ GPGME++ is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU Library General Public License for more details.
+
+ You should have received a copy of the GNU Library General Public License
+ along with GPGME++; see the file COPYING.LIB. If not, write to the
+ Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+ Boston, MA 02110-1301, USA.
+*/
+
+#include "configuration.h"
+#include "error.h"
+#include "util.h"
+
+#include <gpgme.h>
+
+#include <iterator>
+#include <algorithm>
+#include <ostream>
+#include <cstring>
+#include <assert.h>
+
+using namespace GpgME;
+using namespace GpgME::Configuration;
+
+typedef std::shared_ptr< std::remove_pointer<gpgme_conf_opt_t>::type > shared_gpgme_conf_opt_t;
+typedef std::weak_ptr< std::remove_pointer<gpgme_conf_opt_t>::type > weak_gpgme_conf_opt_t;
+
+typedef std::shared_ptr< std::remove_pointer<gpgme_conf_arg_t>::type > shared_gpgme_conf_arg_t;
+typedef std::weak_ptr< std::remove_pointer<gpgme_conf_arg_t>::type > weak_gpgme_conf_arg_t;
+
+typedef std::shared_ptr< std::remove_pointer<gpgme_ctx_t>::type > shared_gpgme_ctx_t;
+typedef std::weak_ptr< std::remove_pointer<gpgme_ctx_t>::type > weak_gpgme_ctx_t;
+
+namespace
+{
+struct nodelete {
+ template <typename T> void operator()(T *) {}
+};
+}
+
+// static
+std::vector<Component> Component::load(Error &returnedError)
+{
+
+ //
+ // 1. get a context:
+ //
+ gpgme_ctx_t ctx_native = 0;
+ if (const gpgme_error_t err = gpgme_new(&ctx_native)) {
+ returnedError = Error(err);
+ return std::vector<Component>();
+ }
+ const shared_gpgme_ctx_t ctx(ctx_native, &gpgme_release);
+
+ //
+ // 2. load the config:
+ //
+ gpgme_conf_comp_t conf_list_native = 0;
+ if (const gpgme_error_t err = gpgme_op_conf_load(ctx_native, &conf_list_native)) {
+ returnedError = Error(err);
+ return std::vector<Component>();
+ }
+ shared_gpgme_conf_comp_t head(conf_list_native, &gpgme_conf_release);
+
+ //
+ // 3. convert to vector<Component>:
+ //
+ std::vector<Component> result;
+
+ while (head) {
+ // secure 'head->next' (if any) against memleaks:
+ shared_gpgme_conf_comp_t next;
+ if (head->next) {
+ next.reset(head->next, &gpgme_conf_release);
+ }
+
+ // now prevent double-free of next.get() and following:
+ head->next = 0;
+
+ // now add a new Component to 'result' (may throw):
+ result.resize(result.size() + 1);
+ result.back().comp.swap(head); // .comp = std::move( head );
+ head.swap(next); // head = std::move( next );
+ }
+
+ return result;
+}
+
+Error Component::save() const
+{
+
+ if (isNull()) {
+ return Error(make_error(GPG_ERR_INV_ARG));
+ }
+
+ //
+ // 1. get a context:
+ //
+ gpgme_ctx_t ctx_native = 0;
+ if (const gpgme_error_t err = gpgme_new(&ctx_native)) {
+ return Error(err);
+ }
+ const shared_gpgme_ctx_t ctx(ctx_native, &gpgme_release);
+
+ //
+ // 2. save the config:
+ //
+ return Error(gpgme_op_conf_save(ctx.get(), comp.get()));
+}
+
+const char *Component::name() const
+{
+ return comp ? comp->name : 0 ;
+}
+
+const char *Component::description() const
+{
+ return comp ? comp->description : 0 ;
+}
+
+const char *Component::programName() const
+{
+ return comp ? comp->program_name : 0 ;
+}
+
+Option Component::option(unsigned int idx) const
+{
+ gpgme_conf_opt_t opt = 0;
+ if (comp) {
+ opt = comp->options;
+ }
+ while (opt && idx) {
+ opt = opt->next;
+ --idx;
+ }
+ if (opt) {
+ return Option(comp, opt);
+ }
+ return Option();
+}
+
+Option Component::option(const char *name) const
+{
+ gpgme_conf_opt_t opt = 0;
+ if (comp) {
+ opt = comp->options;
+ }
+ using namespace std; // for strcmp
+ while (opt && strcmp(name, opt->name) != 0) {
+ opt = opt->next;
+ }
+ if (opt) {
+ return Option(comp, opt);
+ }
+ return Option();
+}
+
+unsigned int Component::numOptions() const
+{
+ unsigned int result = 0;
+ for (gpgme_conf_opt_t opt = comp ? comp->options : 0 ; opt ; opt = opt->next) {
+ ++result;
+ }
+ return result;
+}
+
+std::vector<Option> Component::options() const
+{
+ std::vector<Option> result;
+ for (gpgme_conf_opt_t opt = comp ? comp->options : 0 ; opt ; opt = opt->next) {
+ result.push_back(Option(comp, opt));
+ }
+ return result;
+}
+
+static gpgme_conf_arg_t mygpgme_conf_arg_copy(gpgme_conf_arg_t other, gpgme_conf_type_t type)
+{
+ gpgme_conf_arg_t result = 0, last = 0;
+ for (gpgme_conf_arg_t a = other ; a ; a = a->next) {
+ gpgme_conf_arg_t arg = 0;
+ const gpgme_error_t err
+ = gpgme_conf_arg_new(&arg, type,
+ a->no_arg ? 0 :
+ type == GPGME_CONF_STRING ? a->value.string :
+ /* else */ static_cast<void *>(&a->value));
+ if (err) {
+ gpgme_conf_arg_release(result, type);
+ return 0;
+ }
+ assert(arg);
+ if (result) {
+ last->next = arg;
+ } else {
+ result = arg;
+ }
+ last = arg;
+ }
+ return result;
+}
+
+Component Option::parent() const
+{
+ return Component(comp.lock());
+}
+
+unsigned int Option::flags() const
+{
+ return isNull() ? 0 : opt->flags;
+}
+
+Level Option::level() const
+{
+ return isNull() ? Internal : static_cast<Level>(opt->level) ;
+}
+
+const char *Option::name() const
+{
+ return isNull() ? 0 : opt->name ;
+}
+
+const char *Option::description() const
+{
+ return isNull() ? 0 : opt->description ;
+}
+
+const char *Option::argumentName() const
+{
+ return isNull() ? 0 : opt->argname ;
+}
+
+Type Option::type() const
+{
+ return isNull() ? NoType : static_cast<Type>(opt->type) ;
+}
+
+Type Option::alternateType() const
+{
+ return isNull() ? NoType : static_cast<Type>(opt->alt_type) ;
+}
+
+#if 0
+static Option::Variant argument_to_variant(gpgme_conf_type_t type, bool list, gpgme_conf_arg_t arg)
+{
+ assert(arg);
+ switch (type) {
+ case GPGME_CONF_NONE:
+ if (list) {
+ // return the count (number of times set):
+ return arg->value.count;
+ } else {
+ return none;
+ }
+ case GPGME_CONF_INT32:
+ if (list) {
+ std::vector<int> result;
+ for (gpgme_conf_arg_t a = arg ; a ; a = a->next) {
+ result.push_back(a->value.int32);
+ }
+ return result;
+ } else {
+ return arg->value.int32;
+ }
+ case GPGME_CONF_UINT32:
+ if (list) {
+ std::vector<unsigned int> result;
+ for (gpgme_conf_arg_t a = arg ; a ; a = a->next) {
+ result.push_back(a->value.uint32);
+ }
+ return result;
+ } else {
+ return arg->value.uint32;
+ }
+ case GPGME_CONF_FILENAME:
+ case GPGME_CONF_LDAP_SERVER:
+ case GPGME_CONF_KEY_FPR:
+ case GPGME_CONF_PUB_KEY:
+ case GPGME_CONF_SEC_KEY:
+ case GPGME_CONF_ALIAS_LIST:
+ // these should not happen in alt_type, but fall through
+ case GPGME_CONF_STRING:
+ if (list) {
+ std::vector<const char *> result;
+ for (gpgme_conf_arg_t a = arg ; a ; a = a->next) {
+ result.push_back(a->value.string);
+ }
+ return result;
+ } else {
+ return arg->value.string;
+ }
+ }
+ assert(!"Option: unknown alt_type!");
+ return Option::Variant();
+}
+
+namespace
+{
+inline const void *to_void_star(const char *s)
+{
+ return s;
+}
+inline const void *to_void_star(const std::string &s)
+{
+ return s.c_str();
+}
+inline const void *to_void_star(const int &i)
+{
+ return &i; // const-&: sic!
+}
+inline const void *to_void_star(const unsigned int &i)
+{
+ return &i; // const-&: sic!
+}
+
+struct VariantToArgumentVisitor : boost::static_visitor<gpgme_conf_arg_t> {
+ static gpgme_conf_arg_t make_argument(gpgme_conf_type_t type, const void *value)
+ {
+ gpgme_conf_arg_t arg = 0;
+#ifdef HAVE_GPGME_CONF_ARG_NEW_WITH_CONST_VALUE
+ if (const gpgme_error_t err = gpgme_conf_arg_new(&arg, type, value)) {
+ return 0;
+ }
+#else
+ if (const gpgme_error_t err = gpgme_conf_arg_new(&arg, type, const_cast<void *>(value))) {
+ return 0;
+ }
+#endif
+ else {
+ return arg;
+ }
+ }
+
+ gpgme_conf_arg_t operator()(bool v) const
+ {
+ return v ? make_argument(0) : 0 ;
+ }
+
+ gpgme_conf_arg_t operator()(const char *s) const
+ {
+ return make_argument(s ? s : "");
+ }
+
+ gpgme_conf_arg_t operator()(const std::string &s) const
+ {
+ return operator()(s.c_str());
+ }
+
+ gpgme_conf_arg_t operator()(int i) const
+ {
+ return make_argument(&i);
+ }
+
+ gpgme_conf_arg_t operator()(unsigned int i) const
+ {
+ return make_argument(&i);
+ }
+
+ template <typename T>
+ gpgme_conf_arg_t operator()(const std::vector<T> &value) const
+ {
+ gpgme_conf_arg_t result = 0;
+ gpgme_conf_arg_t last = 0;
+ for (typename std::vector<T>::const_iterator it = value.begin(), end = value.end() ; it != end ; ++it) {
+ if (gpgme_conf_arg_t arg = make_argument(to_void_star(*it))) {
+ if (last) {
+ last = last->next = arg;
+ } else {
+ result = last = arg;
+ }
+ }
+ }
+ return result;
+ }
+
+};
+}
+
+static gpgme_conf_arg_t variant_to_argument(const Option::Variant &value)
+{
+ VariantToArgumentVisitor v;
+ return apply_visitor(v, value);
+}
+
+optional<Option::Variant> Option::defaultValue() const
+{
+ if (isNull()) {
+ return optional<Variant>();
+ } else {
+ return argument_to_variant(opt->alt_type, opt->flags & GPGME_CONF_LIST, opt->default_value);
+ }
+}
+#endif
+
+Argument Option::defaultValue() const
+{
+ if (isNull()) {
+ return Argument();
+ } else {
+ return Argument(comp.lock(), opt, opt->default_value, false);
+ }
+}
+
+const char *Option::defaultDescription() const
+{
+ return isNull() ? 0 : opt->default_description ;
+}
+
+Argument Option::noArgumentValue() const
+{
+ if (isNull()) {
+ return Argument();
+ } else {
+ return Argument(comp.lock(), opt, opt->no_arg_value, false);
+ }
+}
+
+const char *Option::noArgumentDescription() const
+{
+ return isNull() ? 0 : opt->no_arg_description ;
+}
+
+Argument Option::activeValue() const
+{
+ if (isNull()) {
+ return Argument();
+ } else {
+ return Argument(comp.lock(), opt, opt->value, false);
+ }
+}
+
+Argument Option::currentValue() const
+{
+ if (isNull()) {
+ return Argument();
+ }
+ const gpgme_conf_arg_t arg =
+ opt->change_value ? opt->new_value ? opt->new_value : opt->default_value :
+ opt->value ? opt->value :
+ /* else */ opt->default_value ;
+ return Argument(comp.lock(), opt, arg, false);
+}
+
+Argument Option::newValue() const
+{
+ if (isNull()) {
+ return Argument();
+ } else {
+ return Argument(comp.lock(), opt, opt->new_value, false);
+ }
+}
+
+bool Option::set() const
+{
+ if (isNull()) {
+ return false;
+ } else if (opt->change_value) {
+ return opt->new_value;
+ } else {
+ return opt->value;
+ }
+}
+
+bool Option::dirty() const
+{
+ return !isNull() && opt->change_value ;
+}
+
+Error Option::setNewValue(const Argument &argument)
+{
+ if (isNull()) {
+ return Error(make_error(GPG_ERR_INV_ARG));
+ } else if (argument.isNull()) {
+ return resetToDefaultValue();
+ } else if (const gpgme_conf_arg_t arg = mygpgme_conf_arg_copy(argument.arg, opt->alt_type)) {
+ return Error(gpgme_conf_opt_change(opt, 0, arg));
+ } else {
+ return Error(make_error(GPG_ERR_ENOMEM));
+ }
+}
+
+Error Option::resetToActiveValue()
+{
+ if (isNull()) {
+ return Error(make_error(GPG_ERR_INV_ARG));
+ } else {
+ return Error(gpgme_conf_opt_change(opt, 1, 0));
+ }
+}
+
+Error Option::resetToDefaultValue()
+{
+ if (isNull()) {
+ return Error(make_error(GPG_ERR_INV_ARG));
+ } else {
+ return Error(gpgme_conf_opt_change(opt, 0, 0));
+ }
+}
+
+static gpgme_conf_arg_t make_argument(gpgme_conf_type_t type, const void *value)
+{
+ gpgme_conf_arg_t arg = 0;
+ if (const gpgme_error_t err = gpgme_conf_arg_new(&arg, type, value)) {
+ return 0;
+ } else {
+ return arg;
+ }
+}
+
+Argument Option::createNoneArgument(bool set) const
+{
+ if (isNull() || alternateType() != NoType) {
+ return Argument();
+ } else {
+ if (set) {
+ return createNoneListArgument(1);
+ }
+ }
+ return Argument();
+}
+
+Argument Option::createStringArgument(const char *value) const
+{
+ if (isNull() || alternateType() != StringType) {
+ return Argument();
+ } else {
+ return Argument(comp.lock(), opt, make_argument(GPGME_CONF_STRING, value), true);
+ }
+}
+
+Argument Option::createStringArgument(const std::string &value) const
+{
+ if (isNull() || alternateType() != StringType) {
+ return Argument();
+ } else {
+ return Argument(comp.lock(), opt, make_argument(GPGME_CONF_STRING, value.c_str()), true);
+ }
+}
+
+Argument Option::createIntArgument(int value) const
+{
+ if (isNull() || alternateType() != IntegerType) {
+ return Argument();
+ } else {
+ return Argument(comp.lock(), opt, make_argument(GPGME_CONF_INT32, &value), true);
+ }
+}
+
+Argument Option::createUIntArgument(unsigned int value) const
+{
+ if (isNull() || alternateType() != UnsignedIntegerType) {
+ return Argument();
+ } else {
+ return Argument(comp.lock(), opt, make_argument(GPGME_CONF_UINT32, &value), true);
+ }
+}
+
+namespace
+{
+const void *to_void_star(const char *s)
+{
+ return s;
+}
+const void *to_void_star(const std::string &s)
+{
+ return s.c_str();
+}
+const void *to_void_star(const int &i)
+{
+ return &i; // const-&: sic!
+}
+const void *to_void_star(const unsigned int &i)
+{
+ return &i; // const-&: sic!
+}
+
+template <typename T>
+gpgme_conf_arg_t make_argument(gpgme_conf_type_t type, const std::vector<T> &value)
+{
+ gpgme_conf_arg_t result = 0;
+ gpgme_conf_arg_t last = 0;
+ for (typename std::vector<T>::const_iterator it = value.begin(), end = value.end() ; it != end ; ++it) {
+ if (gpgme_conf_arg_t arg = make_argument(type, to_void_star(*it))) {
+ if (last) {
+ last = last->next = arg;
+ } else {
+ result = last = arg;
+ }
+ }
+ }
+ return result;
+}
+}
+
+Argument Option::createNoneListArgument(unsigned int value) const
+{
+ if (value) {
+ return Argument(comp.lock(), opt, make_argument(GPGME_CONF_NONE, &value), true);
+ }
+ return Argument();
+}
+
+Argument Option::createStringListArgument(const std::vector<const char *> &value) const
+{
+ return Argument(comp.lock(), opt, make_argument(GPGME_CONF_STRING, value), true);
+}
+
+Argument Option::createStringListArgument(const std::vector<std::string> &value) const
+{
+ return Argument(comp.lock(), opt, make_argument(GPGME_CONF_STRING, value), true);
+}
+
+Argument Option::createIntListArgument(const std::vector<int> &value) const
+{
+ return Argument(comp.lock(), opt, make_argument(GPGME_CONF_INT32, value), true);
+}
+
+Argument Option::createUIntListArgument(const std::vector<unsigned int> &value) const
+{
+ return Argument(comp.lock(), opt, make_argument(GPGME_CONF_UINT32, value), true);
+}
+
+Argument::Argument(const shared_gpgme_conf_comp_t &comp, gpgme_conf_opt_t opt, gpgme_conf_arg_t arg, bool owns)
+ : comp(comp),
+ opt(opt),
+ arg(owns ? arg : mygpgme_conf_arg_copy(arg, opt ? opt->alt_type : GPGME_CONF_NONE))
+{
+
+}
+
+#if 0
+Argument::Argument(const shared_gpgme_conf_comp_t &comp, gpgme_conf_opt_t opt, gpgme_conf_arg_t arg)
+ : comp(comp),
+ opt(opt),
+ arg(mygpgme_conf_arg_copy(arg, opt ? opt->alt_type : GPGME_CONF_NONE))
+{
+
+}
+#endif
+
+Argument::Argument(const Argument &other)
+ : comp(other.comp),
+ opt(other.opt),
+ arg(mygpgme_conf_arg_copy(other.arg, opt ? opt->alt_type : GPGME_CONF_NONE))
+{
+
+}
+
+Argument::~Argument()
+{
+ gpgme_conf_arg_release(arg, opt ? opt->alt_type : GPGME_CONF_NONE);
+}
+
+Option Argument::parent() const
+{
+ return Option(comp.lock(), opt);
+}
+
+bool Argument::boolValue() const
+{
+ return numberOfTimesSet();
+}
+
+unsigned int Argument::numElements() const
+{
+ if (isNull()) {
+ return 0;
+ }
+ unsigned int result = 0;
+ for (gpgme_conf_arg_t a = arg ; a ; a = a->next) {
+ ++result;
+ }
+ return result;
+}
+
+const char *Argument::stringValue(unsigned int idx) const
+{
+ if (isNull() || opt->alt_type != GPGME_CONF_STRING) {
+ return 0;
+ }
+ gpgme_conf_arg_t a = arg;
+ while (a && idx) {
+ a = a->next;
+ --idx;
+ }
+ return a ? a->value.string : 0 ;
+}
+
+int Argument::intValue(unsigned int idx) const
+{
+ if (isNull() || opt->alt_type != GPGME_CONF_INT32) {
+ return 0;
+ }
+ gpgme_conf_arg_t a = arg;
+ while (a && idx) {
+ a = a->next;
+ --idx;
+ }
+ return a ? a->value.int32 : 0 ;
+}
+
+unsigned int Argument::uintValue(unsigned int idx) const
+{
+ if (isNull() || opt->alt_type != GPGME_CONF_UINT32) {
+ return 0;
+ }
+ gpgme_conf_arg_t a = arg;
+ while (a && idx) {
+ a = a->next;
+ --idx;
+ }
+ return a ? a->value.uint32 : 0 ;
+}
+
+unsigned int Argument::numberOfTimesSet() const
+{
+ if (isNull() || opt->alt_type != GPGME_CONF_NONE) {
+ return 0;
+ }
+ return arg->value.count;
+}
+
+std::vector<const char *> Argument::stringValues() const
+{
+ if (isNull() || opt->alt_type != GPGME_CONF_STRING) {
+ return std::vector<const char *>();
+ }
+ std::vector<const char *> result;
+ for (gpgme_conf_arg_t a = arg ; a ; a = a->next) {
+ result.push_back(a->value.string);
+ }
+ return result;
+}
+
+std::vector<int> Argument::intValues() const
+{
+ if (isNull() || opt->alt_type != GPGME_CONF_INT32) {
+ return std::vector<int>();
+ }
+ std::vector<int> result;
+ for (gpgme_conf_arg_t a = arg ; a ; a = a->next) {
+ result.push_back(a->value.int32);
+ }
+ return result;
+}
+
+std::vector<unsigned int> Argument::uintValues() const
+{
+ if (isNull() || opt->alt_type != GPGME_CONF_UINT32) {
+ return std::vector<unsigned int>();
+ }
+ std::vector<unsigned int> result;
+ for (gpgme_conf_arg_t a = arg ; a ; a = a->next) {
+ result.push_back(a->value.uint32);
+ }
+ return result;
+}
+
+std::ostream &Configuration::operator<<(std::ostream &os, Level level)
+{
+ switch (level) {
+ case Basic: return os << "Basic";
+ case Advanced: return os << "Advanced";
+ case Expert: return os << "Expert";
+ case Invisible: return os << "Invisible";
+ case Internal: return os << "Internal";
+ case NumLevels: ;
+ }
+ return os << "<unknown>";
+}
+
+std::ostream &Configuration::operator<<(std::ostream &os, Type type)
+{
+ switch (type) {
+ case NoType: return os << "None";
+ case StringType: return os << "String";
+ case IntegerType: return os << "Integer";
+ case UnsignedIntegerType: return os << "UnsignedInteger";
+ case FilenameType: return os << "Filename";
+ case LdapServerType: return os << "LdapServer";
+ case KeyFingerprintType: return os << "KeyFingerprint";
+ case PublicKeyType: return os << "PublicKey";
+ case SecretKeyType: return os << "SecretKey";
+ case AliasListType: return os << "AliasList";
+ case MaxType: ;
+ }
+ return os << "<unknown>";
+}
+
+std::ostream &Configuration::operator<<(std::ostream &os, Flag f)
+{
+ unsigned int flags = f;
+ std::vector<const char *> s;
+ if (flags & Group) {
+ s.push_back("Group");
+ }
+ if (flags & Optional) {
+ s.push_back("Optional");
+ }
+ if (flags & List) {
+ s.push_back("List");
+ }
+ if (flags & Runtime) {
+ s.push_back("Runtime");
+ }
+ if (flags & Default) {
+ s.push_back("Default");
+ }
+ if (flags & DefaultDescription) {
+ s.push_back("DefaultDescription");
+ }
+ if (flags & NoArgumentDescription) {
+ s.push_back("NoArgumentDescription");
+ }
+ if (flags & NoChange) {
+ s.push_back("NoChange");
+ }
+ flags &= ~(Group | Optional | List | Runtime | Default | DefaultDescription | NoArgumentDescription | NoChange);
+ if (flags) {
+ s.push_back("other flags(");
+ }
+ std::copy(s.begin(), s.end(),
+ std::ostream_iterator<const char *>(os, "|"));
+ if (flags) {
+ os << flags << ')';
+ }
+ return os;
+}
+
+std::ostream &Configuration::operator<<(std::ostream &os, const Component &c)
+{
+ os << "Component["
+ << "\n name : " << protect(c.name())
+ << "\n description: " << protect(c.description())
+ << "\n programName: " << protect(c.programName())
+ << "\n options : \n";
+ const std::vector<Option> options = c.options();
+ std::copy(options.begin(), options.end(),
+ std::ostream_iterator<Option>(os, "\n"));
+ os << "\n]";
+ return os;
+}
+
+std::ostream &Configuration::operator<<(std::ostream &os, const Option &o)
+{
+ return os << "Option["
+ << "\n name: : " << protect(o.name())
+ << "\n description : " << protect(o.description())
+ << "\n argName : " << protect(o.argumentName())
+ << "\n flags : " << static_cast<Flag>(o.flags())
+ << "\n level : " << o.level()
+ << "\n type : " << o.type()
+ << "\n alt_type : " << o.alternateType()
+ << "\n default_val : " << o.defaultValue()
+ << "\n default_desc: " << protect(o.defaultDescription())
+ << "\n no_arg_value: " << o.noArgumentValue()
+ << "\n no_arg_desc : " << protect(o.noArgumentDescription())
+ << "\n active_value: " << o.activeValue()
+ << "\n new_value : " << o.newValue()
+ << "\n --> cur_val : " << o.currentValue()
+ << "\n set : " << o.set()
+ << "\n dirty : " << o.dirty()
+ << "\n]"
+ ;
+}
+
+std::ostream &Configuration::operator<<(std::ostream &os, const Argument &a)
+{
+ const Option o = a.parent();
+ const bool list = o.flags() & List;
+ os << "Argument[";
+ if (a) {
+ switch (o.alternateType()) {
+ case NoType:
+ if (list) {
+ os << a.numberOfTimesSet() << 'x';
+ } else {
+ os << a.boolValue();
+ }
+ break;
+ default:
+ case StringType:
+ if (list) {
+ const std::vector<const char *> v = a.stringValues();
+ os << v.size() << ':';
+ // can't use std::copy + ostream_iterator here, since we need the protect() call
+ bool first = true;
+ std::for_each(v.begin(), v.end(), [&first, &os](const char *s) {
+ if (first) {
+ first = false;
+ } else {
+ os << ',';
+ }
+ os << protect(s);
+ });
+ } else {
+ os << protect(a.stringValue());
+ }
+ break;
+ case IntegerType:
+ if (list) {
+ const std::vector<int> v = a.intValues();
+ os << v.size() << ':';
+ std::copy(v.begin(), v.end(),
+ std::ostream_iterator<int>(os, ","));
+ } else {
+ os << a.intValue();
+ }
+ break;
+ case UnsignedIntegerType:
+ if (list) {
+ const std::vector<unsigned int> v = a.uintValues();
+ os << v.size() << ':';
+ std::copy(v.begin(), v.end(),
+ std::ostream_iterator<unsigned int>(os, ","));
+ } else {
+ os << a.intValue();
+ }
+ break;
+ }
+ }
+ return os << ']';
+}
diff --git a/lang/cpp/src/configuration.h b/lang/cpp/src/configuration.h
new file mode 100644
index 0000000..288a410
--- /dev/null
+++ b/lang/cpp/src/configuration.h
@@ -0,0 +1,290 @@
+/*
+ configuration.h - wraps gpgme configuration components
+ Copyright (C) 2010 Klarälvdalens Datakonsult AB
+
+ This file is part of GPGME++.
+
+ GPGME++ is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Library General Public
+ License as published by the Free Software Foundation; either
+ version 2 of the License, or (at your option) any later version.
+
+ GPGME++ is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU Library General Public License for more details.
+
+ You should have received a copy of the GNU Library General Public License
+ along with GPGME++; see the file COPYING.LIB. If not, write to the
+ Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+ Boston, MA 02110-1301, USA.
+*/
+
+// -*- c++ -*-
+#ifndef __GPGMEPP_CONFIGURATION_H__
+#define __GPGMEPP_CONFIGURATION_H__
+
+#include "global.h"
+
+#include "gpgmefw.h"
+
+#include <iosfwd>
+#include <vector>
+#include <string>
+#include <algorithm>
+#include <memory>
+
+namespace GpgME
+{
+namespace Configuration
+{
+
+typedef std::shared_ptr< std::remove_pointer<gpgme_conf_comp_t>::type > shared_gpgme_conf_comp_t;
+typedef std::weak_ptr< std::remove_pointer<gpgme_conf_comp_t>::type > weak_gpgme_conf_comp_t;
+
+class Argument;
+class Option;
+class Component;
+
+enum Level {
+ Basic,
+ Advanced,
+ Expert,
+ Invisible,
+ Internal,
+
+ NumLevels
+};
+
+enum Type {
+ NoType,
+ StringType,
+ IntegerType,
+ UnsignedIntegerType,
+
+ FilenameType = 32,
+ LdapServerType,
+ KeyFingerprintType,
+ PublicKeyType,
+ SecretKeyType,
+ AliasListType,
+
+ MaxType
+};
+
+enum Flag {
+ Group = (1 << 0),
+ Optional = (1 << 1),
+ List = (1 << 2),
+ Runtime = (1 << 3),
+ Default = (1 << 4),
+ DefaultDescription = (1 << 5),
+ NoArgumentDescription = (1 << 6),
+ NoChange = (1 << 7),
+
+ LastFlag = NoChange
+};
+
+//
+// class Component
+//
+
+class GPGMEPP_EXPORT Component
+{
+public:
+ Component() : comp() {}
+ explicit Component(const shared_gpgme_conf_comp_t &comp)
+ : comp(comp) {}
+
+ // copy ctor is ok
+
+ const Component &operator=(const Component &other)
+ {
+ if (this != &other) {
+ Component(other).swap(*this);
+ }
+ return *this;
+ }
+
+ void swap(Component &other)
+ {
+ using std::swap;
+ swap(this->comp, other.comp);
+ }
+
+ bool isNull() const
+ {
+ return !comp;
+ }
+
+ static std::vector<Component> load(Error &err);
+ Error save() const;
+
+ const char *name() const;
+ const char *description() const;
+ const char *programName() const;
+
+ Option option(unsigned int index) const;
+ Option option(const char *name) const;
+
+ unsigned int numOptions() const;
+
+ std::vector<Option> options() const;
+
+ GPGMEPP_MAKE_SAFE_BOOL_OPERATOR(!isNull())
+private:
+ shared_gpgme_conf_comp_t comp;
+};
+
+//
+// class Option
+//
+
+class GPGMEPP_EXPORT Option
+{
+public:
+ Option() : comp(), opt(0) {}
+ Option(const shared_gpgme_conf_comp_t &comp, gpgme_conf_opt_t opt)
+ : comp(comp), opt(opt) {}
+
+ const Option &operator=(const Option &other)
+ {
+ if (this != &other) {
+ Option(other).swap(*this);
+ }
+ return *this;
+ }
+
+ void swap(Option &other)
+ {
+ using std::swap;
+ swap(this->comp, other.comp);
+ swap(this->opt, other.opt);
+ }
+
+ bool isNull() const
+ {
+ return comp.expired() || !opt;
+ }
+
+ Component parent() const;
+
+ unsigned int flags() const;
+
+ Level level() const;
+
+ const char *name() const;
+ const char *description() const;
+ const char *argumentName() const;
+
+ Type type() const;
+ Type alternateType() const;
+
+ Argument defaultValue() const;
+ const char *defaultDescription() const;
+
+ Argument noArgumentValue() const;
+ const char *noArgumentDescription() const;
+
+ /*! The value that is in the config file (or null, if it's not set). */
+ Argument activeValue() const;
+ /*! The value that is in this object, ie. either activeValue(), newValue(), or defaultValue() */
+ Argument currentValue() const;
+
+ Argument newValue() const;
+ bool set() const;
+ bool dirty() const;
+
+ Error setNewValue(const Argument &argument);
+ Error resetToDefaultValue();
+ Error resetToActiveValue();
+
+ Argument createNoneArgument(bool set) const;
+ Argument createStringArgument(const char *value) const;
+ Argument createStringArgument(const std::string &value) const;
+ Argument createIntArgument(int value) const;
+ Argument createUIntArgument(unsigned int value) const;
+
+ Argument createNoneListArgument(unsigned int count) const;
+ Argument createStringListArgument(const std::vector<const char *> &value) const;
+ Argument createStringListArgument(const std::vector<std::string> &value) const;
+ Argument createIntListArgument(const std::vector<int> &values) const;
+ Argument createUIntListArgument(const std::vector<unsigned int> &values) const;
+
+ GPGMEPP_MAKE_SAFE_BOOL_OPERATOR(!isNull())
+private:
+ weak_gpgme_conf_comp_t comp;
+ gpgme_conf_opt_t opt;
+};
+
+//
+// class Argument
+//
+
+class GPGMEPP_EXPORT Argument
+{
+ friend class ::GpgME::Configuration::Option;
+ Argument(const shared_gpgme_conf_comp_t &comp, gpgme_conf_opt_t opt, gpgme_conf_arg_t arg, bool owns);
+public:
+ Argument() : comp(), opt(0), arg(0) {}
+ //Argument( const shared_gpgme_conf_comp_t & comp, gpgme_conf_opt_t opt, gpgme_conf_arg_t arg );
+ Argument(const Argument &other);
+ ~Argument();
+
+ const Argument &operator=(const Argument &other)
+ {
+ if (this != &other) {
+ Argument(other).swap(*this);
+ }
+ return *this;
+ }
+
+ void swap(Argument &other)
+ {
+ using std::swap;
+ swap(this->comp, other.comp);
+ swap(this->opt, other.opt);
+ swap(this->arg, other.arg);
+ }
+
+ bool isNull() const
+ {
+ return comp.expired() || !opt || !arg;
+ }
+
+ Option parent() const;
+
+ unsigned int numElements() const;
+
+ bool boolValue() const;
+ const char *stringValue(unsigned int index = 0) const;
+ int intValue(unsigned int index = 0) const;
+ unsigned int uintValue(unsigned int index = 0) const;
+
+ unsigned int numberOfTimesSet() const;
+ std::vector<const char *> stringValues() const;
+ std::vector<int> intValues() const;
+ std::vector<unsigned int> uintValues() const;
+
+ GPGMEPP_MAKE_SAFE_BOOL_OPERATOR(!isNull())
+private:
+ weak_gpgme_conf_comp_t comp;
+ gpgme_conf_opt_t opt;
+ gpgme_conf_arg_t arg;
+};
+
+GPGMEPP_EXPORT std::ostream &operator<<(std::ostream &os, Level level);
+GPGMEPP_EXPORT std::ostream &operator<<(std::ostream &os, Type type);
+GPGMEPP_EXPORT std::ostream &operator<<(std::ostream &os, Flag flag);
+GPGMEPP_EXPORT std::ostream &operator<<(std::ostream &os, const Component &component);
+GPGMEPP_EXPORT std::ostream &operator<<(std::ostream &os, const Option &option);
+GPGMEPP_EXPORT std::ostream &operator<<(std::ostream &os, const Argument &argument);
+
+} // namespace Configuration
+} // namespace GpgME
+
+GPGMEPP_MAKE_STD_SWAP_SPECIALIZATION(Configuration::Component)
+GPGMEPP_MAKE_STD_SWAP_SPECIALIZATION(Configuration::Option)
+GPGMEPP_MAKE_STD_SWAP_SPECIALIZATION(Configuration::Argument)
+
+#endif // __GPGMEPP_CONFIGURATION_H__
diff --git a/lang/cpp/src/context.cpp b/lang/cpp/src/context.cpp
new file mode 100644
index 0000000..00f397b
--- /dev/null
+++ b/lang/cpp/src/context.cpp
@@ -0,0 +1,1639 @@
+/*
+ context.cpp - wraps a gpgme key context
+ Copyright (C) 2003, 2007 Klarälvdalens Datakonsult AB
+
+ This file is part of GPGME++.
+
+ GPGME++ is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Library General Public
+ License as published by the Free Software Foundation; either
+ version 2 of the License, or (at your option) any later version.
+
+ GPGME++ is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU Library General Public License for more details.
+
+ You should have received a copy of the GNU Library General Public License
+ along with GPGME++; see the file COPYING.LIB. If not, write to the
+ Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+ Boston, MA 02110-1301, USA.
+*/
+
+#include <context.h>
+#include <eventloopinteractor.h>
+#include <trustitem.h>
+#include <keylistresult.h>
+#include <keygenerationresult.h>
+#include <importresult.h>
+#include <decryptionresult.h>
+#include <verificationresult.h>
+#include <signingresult.h>
+#include <encryptionresult.h>
+#include <engineinfo.h>
+#include <editinteractor.h>
+#include <vfsmountresult.h>
+
+#include <interfaces/assuantransaction.h>
+#include <defaultassuantransaction.h>
+
+#include "callbacks.h"
+#include "data_p.h"
+#include "context_p.h"
+#include "util.h"
+#include "tofuinfo.h"
+
+#include <gpgme.h>
+
+#include <istream>
+#ifndef NDEBUG
+#include <iostream>
+using std::cerr;
+using std::endl;
+#endif
+
+#include <cassert>
+
+namespace GpgME
+{
+
+static inline unsigned int xtoi_1(const char *str)
+{
+ const unsigned int ch = *str;
+ const unsigned int result =
+ ch <= '9' ? ch - '0' :
+ ch <= 'F' ? ch - 'A' + 10 :
+ /* else */ ch - 'a' + 10 ;
+ return result < 16 ? result : 0 ;
+}
+static inline int xtoi_2(const char *str)
+{
+ return xtoi_1(str) * 16U + xtoi_1(str + 1);
+}
+
+static void percent_unescape(std::string &s, bool plus2space)
+{
+ std::string::iterator src = s.begin(), dest = s.begin(), end = s.end();
+ while (src != end) {
+ if (*src == '%' && end - src > 2) {
+ *dest++ = xtoi_2(&*++src);
+ src += 2;
+ } else if (*src == '+' && plus2space) {
+ *dest++ = ' ';
+ ++src;
+ } else {
+ *dest++ = *src++;
+ }
+ }
+ s.erase(dest, end);
+}
+
+void initializeLibrary()
+{
+ gpgme_check_version(0);
+}
+
+Error initializeLibrary(int)
+{
+ if (gpgme_check_version(GPGME_VERSION)) {
+ return Error();
+ } else {
+ return Error::fromCode(GPG_ERR_USER_1);
+ }
+}
+
+static void format_error(gpgme_error_t err, std::string &str)
+{
+ char buffer[ 1024 ];
+ gpgme_strerror_r(err, buffer, sizeof buffer);
+ buffer[ sizeof buffer - 1 ] = '\0';
+ str = buffer;
+}
+
+const char *Error::source() const
+{
+ return gpgme_strsource((gpgme_error_t)mErr);
+}
+
+const char *Error::asString() const
+{
+ if (mMessage.empty()) {
+ format_error(static_cast<gpgme_error_t>(mErr), mMessage);
+ }
+ return mMessage.c_str();
+}
+
+int Error::code() const
+{
+ return gpgme_err_code(mErr);
+}
+
+int Error::sourceID() const
+{
+ return gpgme_err_source(mErr);
+}
+
+bool Error::isCanceled() const
+{
+ return code() == GPG_ERR_CANCELED;
+}
+
+int Error::toErrno() const
+{
+//#ifdef HAVE_GPGME_GPG_ERROR_WRAPPERS
+ return gpgme_err_code_to_errno(static_cast<gpgme_err_code_t>(code()));
+//#else
+// return gpg_err_code_to_errno( static_cast<gpg_err_code_t>( code() ) );
+//#endif
+}
+
+// static
+bool Error::hasSystemError()
+{
+ return gpgme_err_code_from_syserror() == GPG_ERR_MISSING_ERRNO ;
+}
+
+// static
+void Error::setSystemError(gpg_err_code_t err)
+{
+ setErrno(gpgme_err_code_to_errno(err));
+}
+
+// static
+void Error::setErrno(int err)
+{
+ gpgme_err_set_errno(err);
+}
+
+// static
+Error Error::fromSystemError(unsigned int src)
+{
+ return Error(gpgme_err_make(static_cast<gpgme_err_source_t>(src), gpgme_err_code_from_syserror()));
+}
+
+// static
+Error Error::fromErrno(int err, unsigned int src)
+{
+ return Error(gpgme_err_make(static_cast<gpgme_err_source_t>(src), gpgme_err_code_from_errno(err)));
+}
+
+// static
+Error Error::fromCode(unsigned int err, unsigned int src)
+{
+ return Error(gpgme_err_make(static_cast<gpgme_err_source_t>(src), static_cast<gpgme_err_code_t>(err)));
+}
+
+std::ostream &operator<<(std::ostream &os, const Error &err)
+{
+ return os << "GpgME::Error(" << err.encodedError() << " (" << err.asString() << "))";
+}
+
+Context::Context(gpgme_ctx_t ctx) : d(new Private(ctx))
+{
+}
+
+Context::~Context()
+{
+ delete d;
+}
+
+Context *Context::createForProtocol(Protocol proto)
+{
+ gpgme_ctx_t ctx = 0;
+ if (gpgme_new(&ctx) != 0) {
+ return 0;
+ }
+
+ switch (proto) {
+ case OpenPGP:
+ if (gpgme_set_protocol(ctx, GPGME_PROTOCOL_OpenPGP) != 0) {
+ gpgme_release(ctx);
+ return 0;
+ }
+ break;
+ case CMS:
+ if (gpgme_set_protocol(ctx, GPGME_PROTOCOL_CMS) != 0) {
+ gpgme_release(ctx);
+ return 0;
+ }
+ break;
+ default:
+ return 0;
+ }
+
+ return new Context(ctx);
+}
+
+std::unique_ptr<Context> Context::createForEngine(Engine eng, Error *error)
+{
+ gpgme_ctx_t ctx = 0;
+ if (const gpgme_error_t err = gpgme_new(&ctx)) {
+ if (error) {
+ *error = Error(err);
+ }
+ return std::unique_ptr<Context>();
+ }
+
+ switch (eng) {
+ case AssuanEngine:
+ if (const gpgme_error_t err = gpgme_set_protocol(ctx, GPGME_PROTOCOL_ASSUAN)) {
+ gpgme_release(ctx);
+ if (error) {
+ *error = Error(err);
+ }
+ return std::unique_ptr<Context>();
+ }
+ break;
+ case G13Engine:
+ if (const gpgme_error_t err = gpgme_set_protocol(ctx, GPGME_PROTOCOL_G13)) {
+ gpgme_release(ctx);
+ if (error) {
+ *error = Error(err);
+ }
+ return std::unique_ptr<Context>();
+ }
+ break;
+ case SpawnEngine:
+ if (const gpgme_error_t err = gpgme_set_protocol(ctx, GPGME_PROTOCOL_SPAWN)) {
+ gpgme_release(ctx);
+ if (error) {
+ *error = Error(err);
+ }
+ return std::unique_ptr<Context>();
+ }
+ break;
+ default:
+ if (error) {
+ *error = Error::fromCode(GPG_ERR_INV_ARG);
+ }
+ return std::unique_ptr<Context>();
+ }
+
+ if (error) {
+ *error = Error();
+ }
+
+ return std::unique_ptr<Context>(new Context(ctx));
+}
+
+//
+//
+// Context::Private
+//
+//
+
+Context::Private::Private(gpgme_ctx_t c)
+ : ctx(c),
+ iocbs(0),
+ lastop(None),
+ lasterr(GPG_ERR_NO_ERROR),
+ lastAssuanInquireData(Data::null),
+ lastAssuanTransaction(),
+ lastEditInteractor(),
+ lastCardEditInteractor()
+{
+
+}
+
+Context::Private::~Private()
+{
+ if (ctx) {
+ gpgme_release(ctx);
+ }
+ ctx = 0;
+ delete iocbs;
+}
+
+//
+//
+// Context attributes:
+//
+//
+
+Protocol Context::protocol() const
+{
+ gpgme_protocol_t p = gpgme_get_protocol(d->ctx);
+ switch (p) {
+ case GPGME_PROTOCOL_OpenPGP: return OpenPGP;
+ case GPGME_PROTOCOL_CMS: return CMS;
+ default: return UnknownProtocol;
+ }
+}
+
+void Context::setArmor(bool useArmor)
+{
+ gpgme_set_armor(d->ctx, int(useArmor));
+}
+bool Context::armor() const
+{
+ return gpgme_get_armor(d->ctx);
+}
+
+void Context::setTextMode(bool useTextMode)
+{
+ gpgme_set_textmode(d->ctx, int(useTextMode));
+}
+bool Context::textMode() const
+{
+ return gpgme_get_textmode(d->ctx);
+}
+
+void Context::setOffline(bool useOfflineMode)
+{
+ gpgme_set_offline(d->ctx, int(useOfflineMode));
+}
+bool Context::offline() const
+{
+ return gpgme_get_offline(d->ctx);
+}
+
+void Context::setIncludeCertificates(int which)
+{
+ if (which == DefaultCertificates) {
+ which = GPGME_INCLUDE_CERTS_DEFAULT;
+ }
+ gpgme_set_include_certs(d->ctx, which);
+}
+
+int Context::includeCertificates() const
+{
+ return gpgme_get_include_certs(d->ctx);
+}
+
+void Context::setKeyListMode(unsigned int mode)
+{
+ gpgme_set_keylist_mode(d->ctx, add_to_gpgme_keylist_mode_t(0, mode));
+}
+
+void Context::addKeyListMode(unsigned int mode)
+{
+ const unsigned int cur = gpgme_get_keylist_mode(d->ctx);
+ gpgme_set_keylist_mode(d->ctx, add_to_gpgme_keylist_mode_t(cur, mode));
+}
+
+unsigned int Context::keyListMode() const
+{
+ return convert_from_gpgme_keylist_mode_t(gpgme_get_keylist_mode(d->ctx));
+}
+
+void Context::setProgressProvider(ProgressProvider *provider)
+{
+ gpgme_set_progress_cb(d->ctx, provider ? &progress_callback : 0, provider);
+}
+ProgressProvider *Context::progressProvider() const
+{
+ void *pp = 0;
+ gpgme_progress_cb_t pcb = &progress_callback;
+ gpgme_get_progress_cb(d->ctx, &pcb, &pp);
+ return static_cast<ProgressProvider *>(pp);
+}
+
+void Context::setPassphraseProvider(PassphraseProvider *provider)
+{
+ gpgme_set_passphrase_cb(d->ctx, provider ? &passphrase_callback : 0, provider);
+}
+
+PassphraseProvider *Context::passphraseProvider() const
+{
+ void *pp = 0;
+ gpgme_passphrase_cb_t pcb = &passphrase_callback;
+ gpgme_get_passphrase_cb(d->ctx, &pcb, &pp);
+ return static_cast<PassphraseProvider *>(pp);
+}
+
+void Context::setManagedByEventLoopInteractor(bool manage)
+{
+ if (!EventLoopInteractor::instance()) {
+#ifndef NDEBUG
+ cerr << "Context::setManagedByEventLoopInteractor(): "
+ "You must create an instance of EventLoopInteractor "
+ "before using anything that needs one." << endl;
+#endif
+ return;
+ }
+ if (manage) {
+ EventLoopInteractor::instance()->manage(this);
+ } else {
+ EventLoopInteractor::instance()->unmanage(this);
+ }
+}
+bool Context::managedByEventLoopInteractor() const
+{
+ return d->iocbs != 0;
+}
+
+void Context::installIOCallbacks(gpgme_io_cbs *iocbs)
+{
+ if (!iocbs) {
+ uninstallIOCallbacks();
+ return;
+ }
+ gpgme_set_io_cbs(d->ctx, iocbs);
+ delete d->iocbs; d->iocbs = iocbs;
+}
+
+void Context::uninstallIOCallbacks()
+{
+ static gpgme_io_cbs noiocbs = { 0, 0, 0, 0, 0 };
+ // io.add == 0 means disable io callbacks:
+ gpgme_set_io_cbs(d->ctx, &noiocbs);
+ delete d->iocbs; d->iocbs = 0;
+}
+
+Error Context::setLocale(int cat, const char *val)
+{
+ return Error(d->lasterr = gpgme_set_locale(d->ctx, cat, val));
+}
+
+EngineInfo Context::engineInfo() const
+{
+ return EngineInfo(gpgme_ctx_get_engine_info(d->ctx));
+}
+
+Error Context::setEngineFileName(const char *filename)
+{
+ const char *const home_dir = engineInfo().homeDirectory();
+ return Error(gpgme_ctx_set_engine_info(d->ctx, gpgme_get_protocol(d->ctx), filename, home_dir));
+}
+
+Error Context::setEngineHomeDirectory(const char *home_dir)
+{
+ const char *const filename = engineInfo().fileName();
+ return Error(gpgme_ctx_set_engine_info(d->ctx, gpgme_get_protocol(d->ctx), filename, home_dir));
+}
+
+//
+//
+// Key Management
+//
+//
+
+Error Context::startKeyListing(const char *pattern, bool secretOnly)
+{
+ d->lastop = Private::KeyList;
+ return Error(d->lasterr = gpgme_op_keylist_start(d->ctx, pattern, int(secretOnly)));
+}
+
+Error Context::startKeyListing(const char *patterns[], bool secretOnly)
+{
+ d->lastop = Private::KeyList;
+#ifndef HAVE_GPGME_EXT_KEYLIST_MODE_EXTERNAL_NONBROKEN
+ if (!patterns || !patterns[0] || !patterns[1]) {
+ // max. one pattern -> use the non-ext version
+ return startKeyListing(patterns ? patterns[0] : 0, secretOnly);
+ }
+#endif
+ return Error(d->lasterr = gpgme_op_keylist_ext_start(d->ctx, patterns, int(secretOnly), 0));
+}
+
+Key Context::nextKey(GpgME::Error &e)
+{
+ d->lastop = Private::KeyList;
+ gpgme_key_t key;
+ e = Error(d->lasterr = gpgme_op_keylist_next(d->ctx, &key));
+ return Key(key, false);
+}
+
+KeyListResult Context::endKeyListing()
+{
+ d->lasterr = gpgme_op_keylist_end(d->ctx);
+ return keyListResult();
+}
+
+KeyListResult Context::keyListResult() const
+{
+ return KeyListResult(d->ctx, Error(d->lasterr));
+}
+
+Key Context::key(const char *fingerprint, GpgME::Error &e , bool secret /*, bool forceUpdate*/)
+{
+ d->lastop = Private::KeyList;
+ gpgme_key_t key;
+ e = Error(d->lasterr = gpgme_get_key(d->ctx, fingerprint, &key, int(secret)/*, int( forceUpdate )*/));
+ return Key(key, false);
+}
+
+KeyGenerationResult Context::generateKey(const char *parameters, Data &pubKey)
+{
+ d->lastop = Private::KeyGen;
+ Data::Private *const dp = pubKey.impl();
+ d->lasterr = gpgme_op_genkey(d->ctx, parameters, dp ? dp->data : 0, 0);
+ return KeyGenerationResult(d->ctx, Error(d->lasterr));
+}
+
+Error Context::startKeyGeneration(const char *parameters, Data &pubKey)
+{
+ d->lastop = Private::KeyGen;
+ Data::Private *const dp = pubKey.impl();
+ return Error(d->lasterr = gpgme_op_genkey_start(d->ctx, parameters, dp ? dp->data : 0, 0));
+}
+
+KeyGenerationResult Context::keyGenerationResult() const
+{
+ if (d->lastop & Private::KeyGen) {
+ return KeyGenerationResult(d->ctx, Error(d->lasterr));
+ } else {
+ return KeyGenerationResult();
+ }
+}
+
+Error Context::exportPublicKeys(const char *pattern, Data &keyData)
+{
+ d->lastop = Private::Export;
+ Data::Private *const dp = keyData.impl();
+ return Error(d->lasterr = gpgme_op_export(d->ctx, pattern, 0, dp ? dp->data : 0));
+}
+
+Error Context::exportPublicKeys(const char *patterns[], Data &keyData)
+{
+ d->lastop = Private::Export;
+#ifndef HAVE_GPGME_EXT_KEYLIST_MODE_EXTERNAL_NONBROKEN
+ if (!patterns || !patterns[0] || !patterns[1]) {
+ // max. one pattern -> use the non-ext version
+ return exportPublicKeys(patterns ? patterns[0] : 0, keyData);
+ }
+#endif
+ Data::Private *const dp = keyData.impl();
+ return Error(d->lasterr = gpgme_op_export_ext(d->ctx, patterns, 0, dp ? dp->data : 0));
+}
+
+Error Context::startPublicKeyExport(const char *pattern, Data &keyData)
+{
+ d->lastop = Private::Export;
+ Data::Private *const dp = keyData.impl();
+ return Error(d->lasterr = gpgme_op_export_start(d->ctx, pattern, 0, dp ? dp->data : 0));
+}
+
+Error Context::startPublicKeyExport(const char *patterns[], Data &keyData)
+{
+ d->lastop = Private::Export;
+#ifndef HAVE_GPGME_EXT_KEYLIST_MODE_EXTERNAL_NONBROKEN
+ if (!patterns || !patterns[0] || !patterns[1]) {
+ // max. one pattern -> use the non-ext version
+ return startPublicKeyExport(patterns ? patterns[0] : 0, keyData);
+ }
+#endif
+ Data::Private *const dp = keyData.impl();
+ return Error(d->lasterr = gpgme_op_export_ext_start(d->ctx, patterns, 0, dp ? dp->data : 0));
+}
+
+ImportResult Context::importKeys(const Data &data)
+{
+ d->lastop = Private::Import;
+ const Data::Private *const dp = data.impl();
+ d->lasterr = gpgme_op_import(d->ctx, dp ? dp->data : 0);
+ return ImportResult(d->ctx, Error(d->lasterr));
+}
+
+ImportResult Context::importKeys(const std::vector<Key> &kk)
+{
+ d->lastop = Private::Import;
+ d->lasterr = make_error(GPG_ERR_NOT_IMPLEMENTED);
+
+ bool shouldHaveResult = false;
+ gpgme_key_t * const keys = new gpgme_key_t[ kk.size() + 1 ];
+ gpgme_key_t *keys_it = &keys[0];
+ for (std::vector<Key>::const_iterator it = kk.begin(), end = kk.end() ; it != end ; ++it) {
+ if (it->impl()) {
+ *keys_it++ = it->impl();
+ }
+ }
+ *keys_it++ = 0;
+ d->lasterr = gpgme_op_import_keys(d->ctx, keys);
+ shouldHaveResult = true;
+ if ((gpgme_err_code(d->lasterr) == GPG_ERR_NOT_IMPLEMENTED ||
+ gpgme_err_code(d->lasterr) == GPG_ERR_NOT_SUPPORTED) &&
+ protocol() == CMS) {
+ // ok, try the workaround (export+import):
+ std::vector<const char *> fprs;
+ for (std::vector<Key>::const_iterator it = kk.begin(), end = kk.end() ; it != end ; ++it) {
+ if (const char *fpr = it->primaryFingerprint()) {
+ if (*fpr) {
+ fprs.push_back(fpr);
+ }
+ } else if (const char *keyid = it->keyID()) {
+ if (*keyid) {
+ fprs.push_back(keyid);
+ }
+ }
+ }
+ fprs.push_back(0);
+ Data data;
+ Data::Private *const dp = data.impl();
+ const gpgme_keylist_mode_t oldMode = gpgme_get_keylist_mode(d->ctx);
+ gpgme_set_keylist_mode(d->ctx, GPGME_KEYLIST_MODE_EXTERN);
+ d->lasterr = gpgme_op_export_ext(d->ctx, &fprs[0], 0, dp ? dp->data : 0);
+ gpgme_set_keylist_mode(d->ctx, oldMode);
+ if (!d->lasterr) {
+ data.seek(0, SEEK_SET);
+ d->lasterr = gpgme_op_import(d->ctx, dp ? dp->data : 0);
+ shouldHaveResult = true;
+ }
+ }
+ delete[] keys;
+ if (shouldHaveResult) {
+ return ImportResult(d->ctx, Error(d->lasterr));
+ } else {
+ return ImportResult(Error(d->lasterr));
+ }
+}
+
+Error Context::startKeyImport(const Data &data)
+{
+ d->lastop = Private::Import;
+ const Data::Private *const dp = data.impl();
+ return Error(d->lasterr = gpgme_op_import_start(d->ctx, dp ? dp->data : 0));
+}
+
+Error Context::startKeyImport(const std::vector<Key> &kk)
+{
+ d->lastop = Private::Import;
+ gpgme_key_t * const keys = new gpgme_key_t[ kk.size() + 1 ];
+ gpgme_key_t *keys_it = &keys[0];
+ for (std::vector<Key>::const_iterator it = kk.begin(), end = kk.end() ; it != end ; ++it) {
+ if (it->impl()) {
+ *keys_it++ = it->impl();
+ }
+ }
+ *keys_it++ = 0;
+ Error err = Error(d->lasterr = gpgme_op_import_keys_start(d->ctx, keys));
+ delete[] keys;
+ return err;
+}
+
+ImportResult Context::importResult() const
+{
+ if (d->lastop & Private::Import) {
+ return ImportResult(d->ctx, Error(d->lasterr));
+ } else {
+ return ImportResult();
+ }
+}
+
+Error Context::deleteKey(const Key &key, bool allowSecretKeyDeletion)
+{
+ d->lastop = Private::Delete;
+ return Error(d->lasterr = gpgme_op_delete(d->ctx, key.impl(), int(allowSecretKeyDeletion)));
+}
+
+Error Context::startKeyDeletion(const Key &key, bool allowSecretKeyDeletion)
+{
+ d->lastop = Private::Delete;
+ return Error(d->lasterr = gpgme_op_delete_start(d->ctx, key.impl(), int(allowSecretKeyDeletion)));
+}
+
+Error Context::passwd(const Key &key)
+{
+ d->lastop = Private::Passwd;
+ return Error(d->lasterr = gpgme_op_passwd(d->ctx, key.impl(), 0U));
+}
+
+Error Context::startPasswd(const Key &key)
+{
+ d->lastop = Private::Passwd;
+ return Error(d->lasterr = gpgme_op_passwd_start(d->ctx, key.impl(), 0U));
+}
+
+
+#pragma GCC push_diagnostics
+#pragma GCC diagnostic ignored "-Wdeprecated-declarations"
+
+Error Context::edit(const Key &key, std::unique_ptr<EditInteractor> func, Data &data)
+{
+ d->lastop = Private::Edit;
+ d->lastEditInteractor = std::move(func);
+ Data::Private *const dp = data.impl();
+ return Error(d->lasterr = gpgme_op_edit(d->ctx, key.impl(),
+ d->lastEditInteractor.get() ? edit_interactor_callback : 0,
+ d->lastEditInteractor.get() ? d->lastEditInteractor->d : 0,
+ dp ? dp->data : 0));
+}
+
+
+Error Context::startEditing(const Key &key, std::unique_ptr<EditInteractor> func, Data &data)
+{
+ d->lastop = Private::Edit;
+ d->lastEditInteractor = std::move(func);
+ Data::Private *const dp = data.impl();
+ return Error(d->lasterr = gpgme_op_edit_start(d->ctx, key.impl(),
+ d->lastEditInteractor.get() ? edit_interactor_callback : 0,
+ d->lastEditInteractor.get() ? d->lastEditInteractor->d : 0,
+ dp ? dp->data : 0));
+}
+
+
+EditInteractor *Context::lastEditInteractor() const
+{
+ return d->lastEditInteractor.get();
+}
+
+std::unique_ptr<EditInteractor> Context::takeLastEditInteractor()
+{
+ return std::move(d->lastEditInteractor);
+}
+
+
+Error Context::cardEdit(const Key &key, std::unique_ptr<EditInteractor> func, Data &data)
+{
+ d->lastop = Private::CardEdit;
+ d->lastCardEditInteractor = std::move(func);
+ Data::Private *const dp = data.impl();
+ return Error(d->lasterr = gpgme_op_card_edit(d->ctx, key.impl(),
+ d->lastCardEditInteractor.get() ? edit_interactor_callback : 0,
+ d->lastCardEditInteractor.get() ? d->lastCardEditInteractor->d : 0,
+ dp ? dp->data : 0));
+}
+
+Error Context::startCardEditing(const Key &key, std::unique_ptr<EditInteractor> func, Data &data)
+{
+ d->lastop = Private::CardEdit;
+ d->lastCardEditInteractor = std::move(func);
+ Data::Private *const dp = data.impl();
+ return Error(d->lasterr = gpgme_op_card_edit_start(d->ctx, key.impl(),
+ d->lastCardEditInteractor.get() ? edit_interactor_callback : 0,
+ d->lastCardEditInteractor.get() ? d->lastCardEditInteractor->d : 0,
+ dp ? dp->data : 0));
+}
+
+#pragma GCC pop_diagnostics
+
+EditInteractor *Context::lastCardEditInteractor() const
+{
+ return d->lastCardEditInteractor.get();
+}
+
+std::unique_ptr<EditInteractor> Context::takeLastCardEditInteractor()
+{
+ return std::move(d->lastCardEditInteractor);
+}
+
+Error Context::startTrustItemListing(const char *pattern, int maxLevel)
+{
+ d->lastop = Private::TrustList;
+ return Error(d->lasterr = gpgme_op_trustlist_start(d->ctx, pattern, maxLevel));
+}
+
+TrustItem Context::nextTrustItem(Error &e)
+{
+ gpgme_trust_item_t ti = 0;
+ e = Error(d->lasterr = gpgme_op_trustlist_next(d->ctx, &ti));
+ return TrustItem(ti);
+}
+
+Error Context::endTrustItemListing()
+{
+ return Error(d->lasterr = gpgme_op_trustlist_end(d->ctx));
+}
+
+static gpgme_error_t assuan_transaction_data_callback(void *opaque, const void *data, size_t datalen)
+{
+ assert(opaque);
+ AssuanTransaction *t = static_cast<AssuanTransaction *>(opaque);
+ return t->data(static_cast<const char *>(data), datalen).encodedError();
+}
+
+static gpgme_error_t assuan_transaction_inquire_callback(void *opaque, const char *name, const char *args, gpgme_data_t *r_data)
+{
+ assert(opaque);
+ Context::Private *p = static_cast<Context::Private *>(opaque);
+ AssuanTransaction *t = p->lastAssuanTransaction.get();
+ assert(t);
+ Error err;
+ if (name) {
+ p->lastAssuanInquireData = t->inquire(name, args, err);
+ } else {
+ p->lastAssuanInquireData = Data::null;
+ }
+ if (!p->lastAssuanInquireData.isNull()) {
+ *r_data = p->lastAssuanInquireData.impl()->data;
+ }
+ return err.encodedError();
+}
+
+static gpgme_error_t assuan_transaction_status_callback(void *opaque, const char *status, const char *args)
+{
+ assert(opaque);
+ AssuanTransaction *t = static_cast<AssuanTransaction *>(opaque);
+ std::string a = args;
+ percent_unescape(a, true); // ### why doesn't gpgme do this??
+ return t->status(status, a.c_str()).encodedError();
+}
+
+Error Context::assuanTransact(const char *command)
+{
+ return assuanTransact(command, std::unique_ptr<AssuanTransaction>(new DefaultAssuanTransaction));
+}
+
+Error Context::assuanTransact(const char *command, std::unique_ptr<AssuanTransaction> transaction)
+{
+ gpgme_error_t err, operr;
+
+ d->lastop = Private::AssuanTransact;
+ d->lastAssuanTransaction = std::move(transaction);
+ if (!d->lastAssuanTransaction.get()) {
+ return Error(d->lasterr = make_error(GPG_ERR_INV_ARG));
+ }
+ err = gpgme_op_assuan_transact_ext
+ (d->ctx,
+ command,
+ assuan_transaction_data_callback,
+ d->lastAssuanTransaction.get(),
+ assuan_transaction_inquire_callback,
+ d,
+ assuan_transaction_status_callback,
+ d->lastAssuanTransaction.get(),
+ &operr);
+
+ if (!err)
+ err = operr;
+ d->lasterr = err;
+
+ return Error(d->lasterr);
+}
+
+Error Context::startAssuanTransaction(const char *command)
+{
+ return startAssuanTransaction(command, std::unique_ptr<AssuanTransaction>(new DefaultAssuanTransaction));
+}
+
+Error Context::startAssuanTransaction(const char *command, std::unique_ptr<AssuanTransaction> transaction)
+{
+ gpgme_error_t err;
+
+ d->lastop = Private::AssuanTransact;
+ d->lastAssuanTransaction = std::move(transaction);
+ if (!d->lastAssuanTransaction.get()) {
+ return Error(d->lasterr = make_error(GPG_ERR_INV_ARG));
+ }
+ err = gpgme_op_assuan_transact_start
+ (d->ctx,
+ command,
+ assuan_transaction_data_callback,
+ d->lastAssuanTransaction.get(),
+ assuan_transaction_inquire_callback,
+ d,
+ assuan_transaction_status_callback,
+ d->lastAssuanTransaction.get());
+
+ d->lasterr = err;
+
+ return Error(d->lasterr);
+}
+
+AssuanTransaction *Context::lastAssuanTransaction() const
+{
+ return d->lastAssuanTransaction.get();
+}
+
+std::unique_ptr<AssuanTransaction> Context::takeLastAssuanTransaction()
+{
+ return std::move(d->lastAssuanTransaction);
+}
+
+DecryptionResult Context::decrypt(const Data &cipherText, Data &plainText)
+{
+ d->lastop = Private::Decrypt;
+ const Data::Private *const cdp = cipherText.impl();
+ Data::Private *const pdp = plainText.impl();
+ d->lasterr = gpgme_op_decrypt(d->ctx, cdp ? cdp->data : 0, pdp ? pdp->data : 0);
+ return DecryptionResult(d->ctx, Error(d->lasterr));
+}
+
+Error Context::startDecryption(const Data &cipherText, Data &plainText)
+{
+ d->lastop = Private::Decrypt;
+ const Data::Private *const cdp = cipherText.impl();
+ Data::Private *const pdp = plainText.impl();
+ return Error(d->lasterr = gpgme_op_decrypt_start(d->ctx, cdp ? cdp->data : 0, pdp ? pdp->data : 0));
+}
+
+DecryptionResult Context::decryptionResult() const
+{
+ if (d->lastop & Private::Decrypt) {
+ return DecryptionResult(d->ctx, Error(d->lasterr));
+ } else {
+ return DecryptionResult();
+ }
+}
+
+VerificationResult Context::verifyDetachedSignature(const Data &signature, const Data &signedText)
+{
+ d->lastop = Private::Verify;
+ const Data::Private *const sdp = signature.impl();
+ const Data::Private *const tdp = signedText.impl();
+ d->lasterr = gpgme_op_verify(d->ctx, sdp ? sdp->data : 0, tdp ? tdp->data : 0, 0);
+ return VerificationResult(d->ctx, Error(d->lasterr));
+}
+
+VerificationResult Context::verifyOpaqueSignature(const Data &signedData, Data &plainText)
+{
+ d->lastop = Private::Verify;
+ const Data::Private *const sdp = signedData.impl();
+ Data::Private *const pdp = plainText.impl();
+ d->lasterr = gpgme_op_verify(d->ctx, sdp ? sdp->data : 0, 0, pdp ? pdp->data : 0);
+ return VerificationResult(d->ctx, Error(d->lasterr));
+}
+
+Error Context::startDetachedSignatureVerification(const Data &signature, const Data &signedText)
+{
+ d->lastop = Private::Verify;
+ const Data::Private *const sdp = signature.impl();
+ const Data::Private *const tdp = signedText.impl();
+ return Error(d->lasterr = gpgme_op_verify_start(d->ctx, sdp ? sdp->data : 0, tdp ? tdp->data : 0, 0));
+}
+
+Error Context::startOpaqueSignatureVerification(const Data &signedData, Data &plainText)
+{
+ d->lastop = Private::Verify;
+ const Data::Private *const sdp = signedData.impl();
+ Data::Private *const pdp = plainText.impl();
+ return Error(d->lasterr = gpgme_op_verify_start(d->ctx, sdp ? sdp->data : 0, 0, pdp ? pdp->data : 0));
+}
+
+VerificationResult Context::verificationResult() const
+{
+ if (d->lastop & Private::Verify) {
+ return VerificationResult(d->ctx, Error(d->lasterr));
+ } else {
+ return VerificationResult();
+ }
+}
+
+std::pair<DecryptionResult, VerificationResult> Context::decryptAndVerify(const Data &cipherText, Data &plainText)
+{
+ d->lastop = Private::DecryptAndVerify;
+ const Data::Private *const cdp = cipherText.impl();
+ Data::Private *const pdp = plainText.impl();
+ d->lasterr = gpgme_op_decrypt_verify(d->ctx, cdp ? cdp->data : 0, pdp ? pdp->data : 0);
+ return std::make_pair(DecryptionResult(d->ctx, Error(d->lasterr)),
+ VerificationResult(d->ctx, Error(d->lasterr)));
+}
+
+Error Context::startCombinedDecryptionAndVerification(const Data &cipherText, Data &plainText)
+{
+ d->lastop = Private::DecryptAndVerify;
+ const Data::Private *const cdp = cipherText.impl();
+ Data::Private *const pdp = plainText.impl();
+ return Error(d->lasterr = gpgme_op_decrypt_verify_start(d->ctx, cdp ? cdp->data : 0, pdp ? pdp->data : 0));
+}
+
+unsigned int to_auditlog_flags(unsigned int flags)
+{
+ unsigned int result = 0;
+ if (flags & Context::HtmlAuditLog) {
+ result |= GPGME_AUDITLOG_HTML;
+ }
+ if (flags & Context::AuditLogWithHelp) {
+ result |= GPGME_AUDITLOG_WITH_HELP;
+ }
+ return result;
+}
+
+Error Context::startGetAuditLog(Data &output, unsigned int flags)
+{
+ d->lastop = Private::GetAuditLog;
+ Data::Private *const odp = output.impl();
+ return Error(d->lasterr = gpgme_op_getauditlog_start(d->ctx, odp ? odp->data : 0, to_auditlog_flags(flags)));
+}
+
+Error Context::getAuditLog(Data &output, unsigned int flags)
+{
+ d->lastop = Private::GetAuditLog;
+ Data::Private *const odp = output.impl();
+ return Error(d->lasterr = gpgme_op_getauditlog(d->ctx, odp ? odp->data : 0, to_auditlog_flags(flags)));
+}
+
+void Context::clearSigningKeys()
+{
+ gpgme_signers_clear(d->ctx);
+}
+
+Error Context::addSigningKey(const Key &key)
+{
+ return Error(d->lasterr = gpgme_signers_add(d->ctx, key.impl()));
+}
+
+Key Context::signingKey(unsigned int idx) const
+{
+ gpgme_key_t key = gpgme_signers_enum(d->ctx, idx);
+ return Key(key, false);
+}
+
+std::vector<Key> Context::signingKeys() const
+{
+ std::vector<Key> result;
+ gpgme_key_t key;
+ for (unsigned int i = 0 ; (key = gpgme_signers_enum(d->ctx, i)) ; ++i) {
+ result.push_back(Key(key, false));
+ }
+ return result;
+}
+
+void Context::clearSignatureNotations()
+{
+ gpgme_sig_notation_clear(d->ctx);
+}
+
+GpgME::Error Context::addSignatureNotation(const char *name, const char *value, unsigned int flags)
+{
+ return Error(gpgme_sig_notation_add(d->ctx, name, value, add_to_gpgme_sig_notation_flags_t(0, flags)));
+}
+
+GpgME::Error Context::addSignaturePolicyURL(const char *url, bool critical)
+{
+ return Error(gpgme_sig_notation_add(d->ctx, 0, url, critical ? GPGME_SIG_NOTATION_CRITICAL : 0));
+}
+
+const char *Context::signaturePolicyURL() const
+{
+ for (gpgme_sig_notation_t n = gpgme_sig_notation_get(d->ctx) ; n ; n = n->next) {
+ if (!n->name) {
+ return n->value;
+ }
+ }
+}
+
+Notation Context::signatureNotation(unsigned int idx) const
+{
+ for (gpgme_sig_notation_t n = gpgme_sig_notation_get(d->ctx) ; n ; n = n->next) {
+ if (n->name) {
+ if (idx-- == 0) {
+ return Notation(n);
+ }
+ }
+ }
+ return Notation();
+}
+
+std::vector<Notation> Context::signatureNotations() const
+{
+ std::vector<Notation> result;
+ for (gpgme_sig_notation_t n = gpgme_sig_notation_get(d->ctx) ; n ; n = n->next) {
+ if (n->name) {
+ result.push_back(Notation(n));
+ }
+ }
+ return result;
+}
+
+static gpgme_sig_mode_t sigmode2sigmode(SignatureMode mode)
+{
+ switch (mode) {
+ default:
+ case NormalSignatureMode: return GPGME_SIG_MODE_NORMAL;
+ case Detached: return GPGME_SIG_MODE_DETACH;
+ case Clearsigned: return GPGME_SIG_MODE_CLEAR;
+ }
+}
+
+SigningResult Context::sign(const Data &plainText, Data &signature, SignatureMode mode)
+{
+ d->lastop = Private::Sign;
+ const Data::Private *const pdp = plainText.impl();
+ Data::Private *const sdp = signature.impl();
+ d->lasterr = gpgme_op_sign(d->ctx, pdp ? pdp->data : 0, sdp ? sdp->data : 0, sigmode2sigmode(mode));
+ return SigningResult(d->ctx, Error(d->lasterr));
+}
+
+Error Context::startSigning(const Data &plainText, Data &signature, SignatureMode mode)
+{
+ d->lastop = Private::Sign;
+ const Data::Private *const pdp = plainText.impl();
+ Data::Private *const sdp = signature.impl();
+ return Error(d->lasterr = gpgme_op_sign_start(d->ctx, pdp ? pdp->data : 0, sdp ? sdp->data : 0, sigmode2sigmode(mode)));
+}
+
+SigningResult Context::signingResult() const
+{
+ if (d->lastop & Private::Sign) {
+ return SigningResult(d->ctx, Error(d->lasterr));
+ } else {
+ return SigningResult();
+ }
+}
+
+static gpgme_encrypt_flags_t encryptflags2encryptflags(Context::EncryptionFlags flags)
+{
+ unsigned int result = 0;
+ if (flags & Context::AlwaysTrust) {
+ result |= GPGME_ENCRYPT_ALWAYS_TRUST;
+ }
+ if (flags & Context::NoEncryptTo) {
+ result |= GPGME_ENCRYPT_NO_ENCRYPT_TO;
+ }
+ if (flags & Context::Prepare) {
+ result |= GPGME_ENCRYPT_PREPARE;
+ }
+ if (flags & Context::ExpectSign) {
+ result |= GPGME_ENCRYPT_EXPECT_SIGN;
+ }
+ if (flags & Context::NoCompress) {
+ result |= GPGME_ENCRYPT_NO_COMPRESS;
+ }
+ if (flags & Context::Symmetric) {
+ result |= GPGME_ENCRYPT_SYMMETRIC;
+ }
+ return static_cast<gpgme_encrypt_flags_t>(result);
+}
+
+gpgme_key_t *Context::getKeysFromRecipients(const std::vector<Key> &recipients)
+{
+ if (recipients.empty()) {
+ return nullptr;
+ }
+ gpgme_key_t *ret = new gpgme_key_t[ recipients.size() + 1 ];
+ gpgme_key_t *keys_it = ret;
+ for (std::vector<Key>::const_iterator it = recipients.begin() ; it != recipients.end() ; ++it) {
+ if (it->impl()) {
+ *keys_it++ = it->impl();
+ }
+ }
+ *keys_it++ = 0;
+ return ret;
+}
+
+EncryptionResult Context::encrypt(const std::vector<Key> &recipients, const Data &plainText, Data &cipherText, EncryptionFlags flags)
+{
+ d->lastop = Private::Encrypt;
+ if (flags & NoEncryptTo) {
+ return EncryptionResult(Error(d->lasterr = make_error(GPG_ERR_NOT_IMPLEMENTED)));
+ }
+ const Data::Private *const pdp = plainText.impl();
+ Data::Private *const cdp = cipherText.impl();
+ gpgme_key_t *const keys = getKeysFromRecipients(recipients);
+ d->lasterr = gpgme_op_encrypt(d->ctx, keys, encryptflags2encryptflags(flags),
+ pdp ? pdp->data : 0, cdp ? cdp->data : 0);
+ if (keys) {
+ delete[] keys;
+ }
+ return EncryptionResult(d->ctx, Error(d->lasterr));
+}
+
+Error Context::encryptSymmetrically(const Data &plainText, Data &cipherText)
+{
+ d->lastop = Private::Encrypt;
+ const Data::Private *const pdp = plainText.impl();
+ Data::Private *const cdp = cipherText.impl();
+ return Error(d->lasterr = gpgme_op_encrypt(d->ctx, 0, (gpgme_encrypt_flags_t)0,
+ pdp ? pdp->data : 0, cdp ? cdp->data : 0));
+}
+
+Error Context::startEncryption(const std::vector<Key> &recipients, const Data &plainText, Data &cipherText, EncryptionFlags flags)
+{
+ d->lastop = Private::Encrypt;
+ if (flags & NoEncryptTo) {
+ return Error(d->lasterr = make_error(GPG_ERR_NOT_IMPLEMENTED));
+ }
+ const Data::Private *const pdp = plainText.impl();
+ Data::Private *const cdp = cipherText.impl();
+ gpgme_key_t *const keys = getKeysFromRecipients(recipients);
+ d->lasterr = gpgme_op_encrypt_start(d->ctx, keys, encryptflags2encryptflags(flags),
+ pdp ? pdp->data : 0, cdp ? cdp->data : 0);
+ if (keys) {
+ delete[] keys;
+ }
+ return Error(d->lasterr);
+}
+
+EncryptionResult Context::encryptionResult() const
+{
+ if (d->lastop & Private::Encrypt) {
+ return EncryptionResult(d->ctx, Error(d->lasterr));
+ } else {
+ return EncryptionResult();
+ }
+}
+
+std::pair<SigningResult, EncryptionResult> Context::signAndEncrypt(const std::vector<Key> &recipients, const Data &plainText, Data &cipherText, EncryptionFlags flags)
+{
+ d->lastop = Private::SignAndEncrypt;
+ const Data::Private *const pdp = plainText.impl();
+ Data::Private *const cdp = cipherText.impl();
+ gpgme_key_t *const keys = getKeysFromRecipients(recipients);
+ d->lasterr = gpgme_op_encrypt_sign(d->ctx, keys, encryptflags2encryptflags(flags),
+ pdp ? pdp->data : 0, cdp ? cdp->data : 0);
+ if (keys) {
+ delete[] keys;
+ }
+ return std::make_pair(SigningResult(d->ctx, Error(d->lasterr)),
+ EncryptionResult(d->ctx, Error(d->lasterr)));
+}
+
+Error Context::startCombinedSigningAndEncryption(const std::vector<Key> &recipients, const Data &plainText, Data &cipherText, EncryptionFlags flags)
+{
+ d->lastop = Private::SignAndEncrypt;
+ const Data::Private *const pdp = plainText.impl();
+ Data::Private *const cdp = cipherText.impl();
+ gpgme_key_t *const keys = getKeysFromRecipients(recipients);
+ d->lasterr = gpgme_op_encrypt_sign_start(d->ctx, keys, encryptflags2encryptflags(flags),
+ pdp ? pdp->data : 0, cdp ? cdp->data : 0);
+ if (keys) {
+ delete[] keys;
+ }
+ return Error(d->lasterr);
+}
+
+Error Context::createVFS(const char *containerFile, const std::vector< Key > &recipients)
+{
+ d->lastop = Private::CreateVFS;
+ gpgme_key_t *const keys = new gpgme_key_t[ recipients.size() + 1 ];
+ gpgme_key_t *keys_it = keys;
+ for (std::vector<Key>::const_iterator it = recipients.begin() ; it != recipients.end() ; ++it) {
+ if (it->impl()) {
+ *keys_it++ = it->impl();
+ }
+ }
+ *keys_it++ = 0;
+
+ gpgme_error_t op_err;
+ d->lasterr = gpgme_op_vfs_create(d->ctx, keys, containerFile, 0, &op_err);
+ delete[] keys;
+ Error error(d->lasterr);
+ if (error) {
+ return error;
+ }
+ return Error(d->lasterr = op_err);
+}
+
+VfsMountResult Context::mountVFS(const char *containerFile, const char *mountDir)
+{
+ d->lastop = Private::MountVFS;
+ gpgme_error_t op_err;
+ d->lasterr = gpgme_op_vfs_mount(d->ctx, containerFile, mountDir, 0, &op_err);
+ return VfsMountResult(d->ctx, Error(d->lasterr), Error(op_err));
+}
+
+Error Context::cancelPendingOperation()
+{
+ return Error(gpgme_cancel_async(d->ctx));
+}
+
+bool Context::poll()
+{
+ gpgme_error_t e = GPG_ERR_NO_ERROR;
+ const bool finished = gpgme_wait(d->ctx, &e, 0);
+ if (finished) {
+ d->lasterr = e;
+ }
+ return finished;
+}
+
+Error Context::wait()
+{
+ gpgme_error_t e = GPG_ERR_NO_ERROR;
+ gpgme_wait(d->ctx, &e, 1);
+ return Error(d->lasterr = e);
+}
+
+Error Context::lastError() const
+{
+ return Error(d->lasterr);
+}
+
+Context::PinentryMode Context::pinentryMode() const
+{
+ switch (gpgme_get_pinentry_mode (d->ctx)) {
+ case GPGME_PINENTRY_MODE_ASK:
+ return PinentryAsk;
+ case GPGME_PINENTRY_MODE_CANCEL:
+ return PinentryCancel;
+ case GPGME_PINENTRY_MODE_ERROR:
+ return PinentryError;
+ case GPGME_PINENTRY_MODE_LOOPBACK:
+ return PinentryLoopback;
+ case GPGME_PINENTRY_MODE_DEFAULT:
+ default:
+ return PinentryDefault;
+ }
+}
+
+Error Context::setPinentryMode(PinentryMode which)
+{
+ gpgme_pinentry_mode_t mode;
+ switch (which) {
+ case PinentryAsk:
+ mode = GPGME_PINENTRY_MODE_ASK;
+ break;
+ case PinentryCancel:
+ mode = GPGME_PINENTRY_MODE_CANCEL;
+ break;
+ case PinentryError:
+ mode = GPGME_PINENTRY_MODE_ERROR;
+ break;
+ case PinentryLoopback:
+ mode = GPGME_PINENTRY_MODE_LOOPBACK;
+ break;
+ case PinentryDefault:
+ default:
+ mode = GPGME_PINENTRY_MODE_DEFAULT;
+ }
+ return Error(d->lasterr = gpgme_set_pinentry_mode(d->ctx, mode));
+}
+
+static gpgme_tofu_policy_t to_tofu_policy_t(unsigned int policy)
+{
+ switch (policy) {
+ case TofuInfo::PolicyNone:
+ return GPGME_TOFU_POLICY_NONE;
+ case TofuInfo::PolicyAuto:
+ return GPGME_TOFU_POLICY_AUTO;
+ case TofuInfo::PolicyGood:
+ return GPGME_TOFU_POLICY_GOOD;
+ case TofuInfo::PolicyBad:
+ return GPGME_TOFU_POLICY_BAD;
+ case TofuInfo::PolicyAsk:
+ return GPGME_TOFU_POLICY_ASK;
+ case TofuInfo::PolicyUnknown:
+ return GPGME_TOFU_POLICY_UNKNOWN;
+ }
+}
+
+Error Context::setTofuPolicy(const Key &k, unsigned int policy)
+{
+ return Error(d->lasterr = gpgme_op_tofu_policy(d->ctx,
+ k.impl(), to_tofu_policy_t(policy)));
+}
+
+Error Context::setTofuPolicyStart(const Key &k, unsigned int policy)
+{
+ return Error(d->lasterr = gpgme_op_tofu_policy_start(d->ctx,
+ k.impl(), to_tofu_policy_t(policy)));
+}
+
+// Engine Spawn stuff
+Error Context::spawn(const char *file, const char *argv[],
+ Data &input, Data &output, Data &err,
+ SpawnFlags flags)
+{
+ return Error(d->lasterr = gpgme_op_spawn (d->ctx, file, argv,
+ input.impl() ? input.impl()->data : nullptr,
+ output.impl() ? output.impl()->data : nullptr,
+ err.impl() ? err.impl()->data : nullptr,
+ static_cast<int>(flags)));
+}
+
+Error Context::spawnAsync(const char *file, const char *argv[],
+ Data &input, Data &output, Data &err,
+ SpawnFlags flags)
+{
+ return Error(d->lasterr = gpgme_op_spawn_start (d->ctx, file, argv,
+ input.impl() ? input.impl()->data : nullptr,
+ output.impl() ? output.impl()->data : nullptr,
+ err.impl() ? err.impl()->data : nullptr,
+ static_cast<int>(flags)));
+}
+
+std::ostream &operator<<(std::ostream &os, Protocol proto)
+{
+ os << "GpgME::Protocol(";
+ switch (proto) {
+ case OpenPGP:
+ os << "OpenPGP";
+ break;
+ case CMS:
+ os << "CMS";
+ break;
+ default:
+ case UnknownProtocol:
+ os << "UnknownProtocol";
+ break;
+ }
+ return os << ')';
+}
+
+std::ostream &operator<<(std::ostream &os, Engine eng)
+{
+ os << "GpgME::Engine(";
+ switch (eng) {
+ case GpgEngine:
+ os << "GpgEngine";
+ break;
+ case GpgSMEngine:
+ os << "GpgSMEngine";
+ break;
+ case GpgConfEngine:
+ os << "GpgConfEngine";
+ break;
+ case AssuanEngine:
+ os << "AssuanEngine";
+ break;
+ case SpawnEngine:
+ os << "SpawnEngine";
+ break;
+ default:
+ case UnknownEngine:
+ os << "UnknownEngine";
+ break;
+ }
+ return os << ')';
+}
+
+std::ostream &operator<<(std::ostream &os, Context::CertificateInclusion incl)
+{
+ os << "GpgME::Context::CertificateInclusion(" << static_cast<int>(incl);
+ switch (incl) {
+ case Context::DefaultCertificates:
+ os << "(DefaultCertificates)";
+ break;
+ case Context::AllCertificatesExceptRoot:
+ os << "(AllCertificatesExceptRoot)";
+ break;
+ case Context::AllCertificates:
+ os << "(AllCertificates)";
+ break;
+ case Context::NoCertificates:
+ os << "(NoCertificates)";
+ break;
+ case Context::OnlySenderCertificate:
+ os << "(OnlySenderCertificate)";
+ break;
+ }
+ return os << ')';
+}
+
+std::ostream &operator<<(std::ostream &os, KeyListMode mode)
+{
+ os << "GpgME::KeyListMode(";
+#define CHECK( x ) if ( !(mode & (x)) ) {} else do { os << #x " "; } while (0)
+ CHECK(Local);
+ CHECK(Extern);
+ CHECK(Signatures);
+ CHECK(Validate);
+ CHECK(Ephemeral);
+ CHECK(WithTofu);
+#undef CHECK
+ return os << ')';
+}
+
+std::ostream &operator<<(std::ostream &os, SignatureMode mode)
+{
+ os << "GpgME::SignatureMode(";
+ switch (mode) {
+#define CHECK( x ) case x: os << #x; break
+ CHECK(NormalSignatureMode);
+ CHECK(Detached);
+ CHECK(Clearsigned);
+#undef CHECK
+ default:
+ os << "???" "(" << static_cast<int>(mode) << ')';
+ break;
+ }
+ return os << ')';
+}
+
+std::ostream &operator<<(std::ostream &os, Context::EncryptionFlags flags)
+{
+ os << "GpgME::Context::EncryptionFlags(";
+#define CHECK( x ) if ( !(flags & (Context::x)) ) {} else do { os << #x " "; } while (0)
+ CHECK(AlwaysTrust);
+ CHECK(NoEncryptTo);
+ CHECK(Prepare);
+ CHECK(ExpectSign);
+ CHECK(NoCompress);
+ CHECK(Symmetric);
+#undef CHECK
+ return os << ')';
+}
+
+std::ostream &operator<<(std::ostream &os, Context::AuditLogFlags flags)
+{
+ os << "GpgME::Context::AuditLogFlags(";
+#define CHECK( x ) if ( !(flags & (Context::x)) ) {} else do { os << #x " "; } while (0)
+ CHECK(HtmlAuditLog);
+ CHECK(AuditLogWithHelp);
+#undef CHECK
+ return os << ')';
+}
+
+} // namespace GpgME
+
+GpgME::Error GpgME::setDefaultLocale(int cat, const char *val)
+{
+ return Error(gpgme_set_locale(0, cat, val));
+}
+
+GpgME::EngineInfo GpgME::engineInfo(GpgME::Protocol proto)
+{
+ gpgme_engine_info_t ei = 0;
+ if (gpgme_get_engine_info(&ei)) {
+ return EngineInfo();
+ }
+
+ const gpgme_protocol_t p = proto == CMS ? GPGME_PROTOCOL_CMS : GPGME_PROTOCOL_OpenPGP ;
+
+ for (gpgme_engine_info_t i = ei ; i ; i = i->next) {
+ if (i->protocol == p) {
+ return EngineInfo(i);
+ }
+ }
+
+ return EngineInfo();
+}
+
+const char *GpgME::dirInfo(const char *what)
+{
+ return gpgme_get_dirinfo(what);
+}
+
+GpgME::Error GpgME::checkEngine(GpgME::Protocol proto)
+{
+ const gpgme_protocol_t p = proto == CMS ? GPGME_PROTOCOL_CMS : GPGME_PROTOCOL_OpenPGP ;
+
+ return Error(gpgme_engine_check_version(p));
+}
+
+static const gpgme_protocol_t UNKNOWN_PROTOCOL = static_cast<gpgme_protocol_t>(255);
+
+static gpgme_protocol_t engine2protocol(const GpgME::Engine engine)
+{
+ switch (engine) {
+ case GpgME::GpgEngine: return GPGME_PROTOCOL_OpenPGP;
+ case GpgME::GpgSMEngine: return GPGME_PROTOCOL_CMS;
+ case GpgME::GpgConfEngine:
+ return GPGME_PROTOCOL_GPGCONF;
+ case GpgME::AssuanEngine:
+ return GPGME_PROTOCOL_ASSUAN;
+ case GpgME::G13Engine:
+ return GPGME_PROTOCOL_G13;
+ case GpgME::SpawnEngine:
+ return GPGME_PROTOCOL_SPAWN;
+ case GpgME::UnknownEngine:
+ ;
+ }
+ return UNKNOWN_PROTOCOL;
+}
+
+GpgME::EngineInfo GpgME::engineInfo(GpgME::Engine engine)
+{
+ gpgme_engine_info_t ei = 0;
+ if (gpgme_get_engine_info(&ei)) {
+ return EngineInfo();
+ }
+
+ const gpgme_protocol_t p = engine2protocol(engine);
+
+ for (gpgme_engine_info_t i = ei ; i ; i = i->next) {
+ if (i->protocol == p) {
+ return EngineInfo(i);
+ }
+ }
+
+ return EngineInfo();
+}
+
+GpgME::Error GpgME::checkEngine(GpgME::Engine engine)
+{
+ const gpgme_protocol_t p = engine2protocol(engine);
+
+ return Error(gpgme_engine_check_version(p));
+}
+
+static const unsigned long supported_features = 0
+ | GpgME::ValidatingKeylistModeFeature
+ | GpgME::CancelOperationFeature
+ | GpgME::WrongKeyUsageFeature
+ | GpgME::DefaultCertificateInclusionFeature
+ | GpgME::GetSetEngineInfoFeature
+ | GpgME::ClearAddGetSignatureNotationsFeature
+ | GpgME::SetDataFileNameFeeature
+ | GpgME::SignatureNotationsKeylistModeFeature
+ | GpgME::KeySignatureNotationsFeature
+ | GpgME::KeyIsQualifiedFeature
+ | GpgME::SignatureNotationsCriticalFlagFeature
+ | GpgME::SignatureNotationsFlagsFeature
+ | GpgME::SignatureNotationsHumanReadableFlagFeature
+ | GpgME::SubkeyIsQualifiedFeature
+ | GpgME::EngineInfoHomeDirFeature
+ | GpgME::DecryptionResultFileNameFeature
+ | GpgME::DecryptionResultRecipientsFeature
+ | GpgME::VerificationResultFileNameFeature
+ | GpgME::SignaturePkaFieldsFeature
+ | GpgME::SignatureAlgorithmFieldsFeature
+ | GpgME::FdPointerFeature
+ | GpgME::AuditLogFeature
+ | GpgME::GpgConfEngineFeature
+ | GpgME::CancelOperationAsyncFeature
+ | GpgME::NoEncryptToEncryptionFlagFeature
+ | GpgME::CardKeyFeature
+ | GpgME::AssuanEngineFeature
+ | GpgME::EphemeralKeylistModeFeature
+ | GpgME::ImportFromKeyserverFeature
+ | GpgME::G13VFSFeature
+ | GpgME::PasswdFeature
+ ;
+
+static const unsigned long supported_features2 = 0
+ | GpgME::BinaryAndFineGrainedIdentify
+ ;
+
+bool GpgME::hasFeature(unsigned long features)
+{
+ return features == (features & supported_features);
+}
+
+bool GpgME::hasFeature(unsigned long features, unsigned long features2)
+{
+ return features == (features & supported_features)
+ && features2 == (features2 & supported_features2)
+ ;
+}
diff --git a/lang/cpp/src/context.h b/lang/cpp/src/context.h
new file mode 100644
index 0000000..b1e4f5f
--- /dev/null
+++ b/lang/cpp/src/context.h
@@ -0,0 +1,420 @@
+/*
+ context.h - wraps a gpgme key context
+ Copyright (C) 2003, 2007 Klarälvdalens Datakonsult AB
+
+ This file is part of GPGME++.
+
+ GPGME++ is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Library General Public
+ License as published by the Free Software Foundation; either
+ version 2 of the License, or (at your option) any later version.
+
+ GPGME++ is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU Library General Public License for more details.
+
+ You should have received a copy of the GNU Library General Public License
+ along with GPGME++; see the file COPYING.LIB. If not, write to the
+ Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+ Boston, MA 02110-1301, USA.
+*/
+
+// -*- c++ -*-
+#ifndef __GPGMEPP_CONTEXT_H__
+#define __GPGMEPP_CONTEXT_H__
+
+#include "global.h"
+
+#include "error.h"
+#include "verificationresult.h" // for Signature::Notation
+
+#include <memory>
+#include <vector>
+#include <utility>
+#include <iosfwd>
+
+namespace GpgME
+{
+
+class Key;
+class Data;
+class TrustItem;
+class ProgressProvider;
+class PassphraseProvider;
+class EventLoopInteractor;
+class EditInteractor;
+class AssuanTransaction;
+
+class KeyListResult;
+class KeyGenerationResult;
+class ImportResult;
+class DecryptionResult;
+class VerificationResult;
+class SigningResult;
+class EncryptionResult;
+class VfsMountResult;
+
+class EngineInfo;
+
+class GPGMEPP_EXPORT Context
+{
+ explicit Context(gpgme_ctx_t);
+public:
+ //using GpgME::Protocol;
+
+ //
+ // Creation and destruction:
+ //
+
+ static Context *createForProtocol(Protocol proto);
+ static std::unique_ptr<Context> createForEngine(Engine engine, Error *err = 0);
+ virtual ~Context();
+
+ //
+ // Context Attributes
+ //
+
+ Protocol protocol() const;
+
+ void setArmor(bool useArmor);
+ bool armor() const;
+
+ void setTextMode(bool useTextMode);
+ bool textMode() const;
+
+ void setOffline(bool useOfflineMode);
+ bool offline() const;
+
+ enum CertificateInclusion {
+ DefaultCertificates = -256,
+ AllCertificatesExceptRoot = -2,
+ AllCertificates = -1,
+ NoCertificates = 0,
+ OnlySenderCertificate = 1
+ };
+ void setIncludeCertificates(int which);
+ int includeCertificates() const;
+
+ //using GpgME::KeyListMode;
+ void setKeyListMode(unsigned int keyListMode);
+ void addKeyListMode(unsigned int keyListMode);
+ unsigned int keyListMode() const;
+
+ /** Set the passphrase provider
+ *
+ * To avoid problems where a class using a context registers
+ * itself as the provider the Context does not take ownership
+ * of the provider and the caller must ensure that the provider
+ * is deleted if it is no longer needed.
+ */
+ void setPassphraseProvider(PassphraseProvider *provider);
+ PassphraseProvider *passphraseProvider() const;
+
+ /** Set the progress provider
+ *
+ * To avoid problems where a class using a context registers
+ * itself as the provider the Context does not take ownership
+ * of the provider and the caller must ensure that the provider
+ * is deleted if it is no longer needed.
+ */
+ void setProgressProvider(ProgressProvider *provider);
+ ProgressProvider *progressProvider() const;
+
+ void setManagedByEventLoopInteractor(bool managed);
+ bool managedByEventLoopInteractor() const;
+
+ GpgME::Error setLocale(int category, const char *value);
+
+ EngineInfo engineInfo() const;
+ GpgME::Error setEngineFileName(const char *filename);
+ GpgME::Error setEngineHomeDirectory(const char *filename);
+
+ enum PinentryMode{
+ PinentryDefault = 0,
+ PinentryAsk = 1,
+ PinentryCancel = 2,
+ PinentryError = 3,
+ PinentryLoopback = 4
+ };
+ GpgME::Error setPinentryMode(PinentryMode which);
+ PinentryMode pinentryMode() const;
+
+private:
+ friend class ::GpgME::EventLoopInteractor;
+ void installIOCallbacks(gpgme_io_cbs *iocbs);
+ void uninstallIOCallbacks();
+
+public:
+ //
+ //
+ // Key Management
+ //
+ //
+
+ //
+ // Key Listing
+ //
+
+ GpgME::Error startKeyListing(const char *pattern = 0, bool secretOnly = false);
+ GpgME::Error startKeyListing(const char *patterns[], bool secretOnly = false);
+
+ Key nextKey(GpgME::Error &e);
+
+ KeyListResult endKeyListing();
+ KeyListResult keyListResult() const;
+
+ Key key(const char *fingerprint, GpgME::Error &e, bool secret = false);
+
+ //
+ // Key Generation
+ //
+
+ KeyGenerationResult generateKey(const char *parameters, Data &pubKey);
+ GpgME::Error startKeyGeneration(const char *parameters, Data &pubkey);
+ KeyGenerationResult keyGenerationResult() const;
+
+ //
+ // Key Export
+ //
+
+ GpgME::Error exportPublicKeys(const char *pattern, Data &keyData);
+ GpgME::Error exportPublicKeys(const char *pattern[], Data &keyData);
+ GpgME::Error startPublicKeyExport(const char *pattern, Data &keyData);
+ GpgME::Error startPublicKeyExport(const char *pattern[], Data &keyData);
+
+ //
+ // Key Import
+ //
+
+ ImportResult importKeys(const Data &data);
+ ImportResult importKeys(const std::vector<Key> &keys);
+ GpgME::Error startKeyImport(const Data &data);
+ GpgME::Error startKeyImport(const std::vector<Key> &keys);
+ ImportResult importResult() const;
+
+ //
+ // Key Deletion
+ //
+
+ GpgME::Error deleteKey(const Key &key, bool allowSecretKeyDeletion = false);
+ GpgME::Error startKeyDeletion(const Key &key, bool allowSecretKeyDeletion = false);
+
+ //
+ // Passphrase changing
+ //
+
+ GpgME::Error passwd(const Key &key);
+ GpgME::Error startPasswd(const Key &key);
+
+ //
+ // Key Editing
+ //
+
+ GpgME::Error edit(const Key &key, std::unique_ptr<EditInteractor> function, Data &out);
+ GpgME::Error startEditing(const Key &key, std::unique_ptr<EditInteractor> function, Data &out);
+
+ // using TofuInfo::Policy
+ Error setTofuPolicy(const Key &k, unsigned int policy);
+ Error setTofuPolicyStart(const Key &k, unsigned int policy);
+
+ EditInteractor *lastEditInteractor() const;
+ std::unique_ptr<EditInteractor> takeLastEditInteractor();
+
+ //
+ // SmartCard Editing
+ //
+
+ GpgME::Error cardEdit(const Key &key, std::unique_ptr<EditInteractor> function, Data &out);
+ GpgME::Error startCardEditing(const Key &key, std::unique_ptr<EditInteractor> function, Data &out);
+
+ EditInteractor *lastCardEditInteractor() const;
+ std::unique_ptr<EditInteractor> takeLastCardEditInteractor();
+
+ //
+ // Trust Item Management
+ //
+
+ GpgME::Error startTrustItemListing(const char *pattern, int maxLevel);
+ TrustItem nextTrustItem(GpgME::Error &e);
+ GpgME::Error endTrustItemListing();
+
+ //
+ // Assuan Transactions
+ //
+
+ GpgME::Error assuanTransact(const char *command, std::unique_ptr<AssuanTransaction> transaction);
+ GpgME::Error assuanTransact(const char *command);
+ GpgME::Error startAssuanTransaction(const char *command, std::unique_ptr<AssuanTransaction> transaction);
+ GpgME::Error startAssuanTransaction(const char *command);
+
+ AssuanTransaction *lastAssuanTransaction() const;
+ std::unique_ptr<AssuanTransaction> takeLastAssuanTransaction();
+
+ //
+ //
+ // Crypto Operations
+ //
+ //
+
+ //
+ // Decryption
+ //
+
+ DecryptionResult decrypt(const Data &cipherText, Data &plainText);
+ GpgME::Error startDecryption(const Data &cipherText, Data &plainText);
+ DecryptionResult decryptionResult() const;
+
+ //
+ // Signature Verification
+ //
+
+ VerificationResult verifyDetachedSignature(const Data &signature, const Data &signedText);
+ VerificationResult verifyOpaqueSignature(const Data &signedData, Data &plainText);
+ GpgME::Error startDetachedSignatureVerification(const Data &signature, const Data &signedText);
+ GpgME::Error startOpaqueSignatureVerification(const Data &signedData, Data &plainText);
+ VerificationResult verificationResult() const;
+
+ //
+ // Combined Decryption and Signature Verification
+ //
+
+ std::pair<DecryptionResult, VerificationResult> decryptAndVerify(const Data &cipherText, Data &plainText);
+ GpgME::Error startCombinedDecryptionAndVerification(const Data &cipherText, Data &plainText);
+ // use verificationResult() and decryptionResult() to retrieve the result objects...
+
+ //
+ // Signing
+ //
+
+ void clearSigningKeys();
+ GpgME::Error addSigningKey(const Key &signer);
+ Key signingKey(unsigned int index) const;
+ std::vector<Key> signingKeys() const;
+
+ void clearSignatureNotations();
+ GpgME::Error addSignatureNotation(const char *name, const char *value, unsigned int flags = 0);
+ GpgME::Error addSignaturePolicyURL(const char *url, bool critical = false);
+ const char *signaturePolicyURL() const;
+ Notation signatureNotation(unsigned int index) const;
+ std::vector<Notation> signatureNotations() const;
+
+ //using GpgME::SignatureMode;
+ SigningResult sign(const Data &plainText, Data &signature, SignatureMode mode);
+ GpgME::Error startSigning(const Data &plainText, Data &signature, SignatureMode mode);
+ SigningResult signingResult() const;
+
+ //
+ // Encryption
+ //
+
+ enum EncryptionFlags {
+ None = 0,
+ AlwaysTrust = 1,
+ NoEncryptTo = 2,
+ Prepare = 4,
+ ExpectSign = 8,
+ NoCompress = 16,
+ Symmetric = 32
+ };
+ EncryptionResult encrypt(const std::vector<Key> &recipients, const Data &plainText, Data &cipherText, EncryptionFlags flags);
+ GpgME::Error encryptSymmetrically(const Data &plainText, Data &cipherText);
+ GpgME::Error startEncryption(const std::vector<Key> &recipients, const Data &plainText, Data &cipherText, EncryptionFlags flags);
+ EncryptionResult encryptionResult() const;
+
+ //
+ // Combined Signing and Encryption
+ //
+
+ std::pair<SigningResult, EncryptionResult> signAndEncrypt(const std::vector<Key> &recipients, const Data &plainText, Data &cipherText, EncryptionFlags flags);
+ GpgME::Error startCombinedSigningAndEncryption(const std::vector<Key> &recipients, const Data &plainText, Data &cipherText, EncryptionFlags flags);
+ // use encryptionResult() and signingResult() to retrieve the result objects...
+
+ //
+ //
+ // Audit Log
+ //
+ //
+ enum AuditLogFlags {
+ HtmlAuditLog = 1,
+ AuditLogWithHelp = 128
+ };
+ GpgME::Error startGetAuditLog(Data &output, unsigned int flags = 0);
+ GpgME::Error getAuditLog(Data &output, unsigned int flags = 0);
+
+ //
+ //
+ // G13 crypto container operations
+ //
+ //
+ GpgME::Error createVFS(const char *containerFile, const std::vector<Key> &recipients);
+ VfsMountResult mountVFS(const char *containerFile, const char *mountDir);
+
+ // Spawn Engine
+ enum SpawnFlags {
+ SpawnNone = 0,
+ SpawnDetached = 1,
+ SpawnAllowSetFg = 2
+ };
+ /** Spwan the process \a file with arguments \a argv.
+ *
+ * If a data parameter is null the /dev/null will be
+ * used. (Or other platform stuff).
+ *
+ * @param file The executable to start.
+ * @param argv list of arguments file should be argv[0].
+ * @param input The data to be sent through stdin.
+ * @param output The data to be recieve the stdout.
+ * @param err The data to recieve stderr.
+ * @param flags Additional flags.
+ *
+ * @returns An error or empty error.
+ */
+ GpgME::Error spawn(const char *file, const char *argv[],
+ Data &input, Data &output, Data &err,
+ SpawnFlags flags);
+ /** Async variant of spawn. Immediately returns after starting the
+ * process. */
+ GpgME::Error spawnAsync(const char *file, const char *argv[],
+ Data &input, Data &output,
+ Data &err, SpawnFlags flags);
+ //
+ //
+ // Run Control
+ //
+ //
+
+ bool poll();
+ GpgME::Error wait();
+ GpgME::Error lastError() const;
+ GpgME::Error cancelPendingOperation();
+
+ class Private;
+ const Private *impl() const
+ {
+ return d;
+ }
+ Private *impl()
+ {
+ return d;
+ }
+private:
+ // Helper functions that need to be context because they rely
+ // on the "Friendlyness" of context to access the gpgme types.
+ gpgme_key_t *getKeysFromRecipients(const std::vector<Key> &recipients);
+
+private:
+ Private *const d;
+
+private: // disable...
+ Context(const Context &);
+ const Context &operator=(const Context &);
+};
+
+GPGMEPP_EXPORT std::ostream &operator<<(std::ostream &os, Context::CertificateInclusion incl);
+GPGMEPP_EXPORT std::ostream &operator<<(std::ostream &os, Context::EncryptionFlags flags);
+GPGMEPP_EXPORT std::ostream &operator<<(std::ostream &os, Context::AuditLogFlags flags);
+
+} // namespace GpgME
+
+#endif // __GPGMEPP_CONTEXT_H__
diff --git a/lang/cpp/src/context_p.h b/lang/cpp/src/context_p.h
new file mode 100644
index 0000000..be34783
--- /dev/null
+++ b/lang/cpp/src/context_p.h
@@ -0,0 +1,84 @@
+/*
+ context_p.h - wraps a gpgme context (private part)
+ Copyright (C) 2003, 2007 Klarälvdalens Datakonsult AB
+
+ This file is part of GPGME++.
+
+ GPGME++ is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Library General Public
+ License as published by the Free Software Foundation; either
+ version 2 of the License, or (at your option) any later version.
+
+ GPGME++ is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU Library General Public License for more details.
+
+ You should have received a copy of the GNU Library General Public License
+ along with GPGME++; see the file COPYING.LIB. If not, write to the
+ Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+ Boston, MA 02110-1301, USA.
+*/
+
+// -*- c++ -*-
+#ifndef __GPGMEPP_CONTEXT_P_H__
+#define __GPGMEPP_CONTEXT_P_H__
+
+#include <context.h>
+#include <data.h>
+
+#include <gpgme.h>
+
+namespace GpgME
+{
+
+class Context::Private
+{
+public:
+ enum Operation {
+ None = 0,
+
+ Encrypt = 0x001,
+ Decrypt = 0x002,
+ Sign = 0x004,
+ Verify = 0x008,
+ DecryptAndVerify = Decrypt | Verify,
+ SignAndEncrypt = Sign | Encrypt,
+
+ Import = 0x010,
+ Export = 0x020, // no gpgme_export_result_t, but nevertheless...
+ Delete = 0x040, // no gpgme_delete_result_t, but nevertheless...
+
+ KeyGen = 0x080,
+ KeyList = 0x100,
+ TrustList = 0x200, // no gpgme_trustlist_result_t, but nevertheless...
+
+ Edit = 0x400, // no gpgme_edit_result_t, but nevertheless...
+ CardEdit = 0x800, // no gpgme_card_edit_result_t, but nevertheless...
+
+ GetAuditLog = 0x1000, // no gpgme_getauditlog_result_t, but nevertheless...
+
+ AssuanTransact = 0x2000,
+ Passwd = 0x4000, // no gpgme_passwd_result_t, but nevertheless...
+
+ CreateVFS = 0x4000,
+ MountVFS = 0x8000,
+
+ EndMarker
+ };
+
+ Private(gpgme_ctx_t c = 0);
+ ~Private();
+
+ gpgme_ctx_t ctx;
+ gpgme_io_cbs *iocbs;
+ Operation lastop;
+ gpgme_error_t lasterr;
+ Data lastAssuanInquireData;
+ std::unique_ptr<AssuanTransaction> lastAssuanTransaction;
+ std::unique_ptr<EditInteractor> lastEditInteractor, lastCardEditInteractor;
+};
+
+} // namespace GpgME
+
+#endif // __GPGMEPP_CONTEXT_P_H__
diff --git a/lang/cpp/src/context_vanilla.cpp b/lang/cpp/src/context_vanilla.cpp
new file mode 100644
index 0000000..984d41b
--- /dev/null
+++ b/lang/cpp/src/context_vanilla.cpp
@@ -0,0 +1,33 @@
+/*
+ context_vanilla.cpp - wraps a gpgme key context, gpgme (vanilla)-specific functions
+ Copyright (C) 2007 Klarälvdalens Datakonsult AB
+
+ This file is part of GPGME++.
+
+ GPGME++ is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Library General Public
+ License as published by the Free Software Foundation; either
+ version 2 of the License, or (at your option) any later version.
+
+ GPGME++ is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU Library General Public License for more details.
+
+ You should have received a copy of the GNU Library General Public License
+ along with GPGME++; see the file COPYING.LIB. If not, write to the
+ Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+ Boston, MA 02110-1301, USA.
+*/
+
+#include <global.h>
+
+GIOChannel *GpgME::getGIOChannel(int)
+{
+ return 0;
+}
+
+QIODevice *GpgME::getQIODevice(int)
+{
+ return 0;
+}
diff --git a/lang/cpp/src/data.cpp b/lang/cpp/src/data.cpp
new file mode 100644
index 0000000..9527b2f
--- /dev/null
+++ b/lang/cpp/src/data.cpp
@@ -0,0 +1,222 @@
+/*
+ data.cpp - wraps a gpgme data object
+ Copyright (C) 2003 Klarälvdalens Datakonsult AB
+
+ This file is part of GPGME++.
+
+ GPGME++ is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Library General Public
+ License as published by the Free Software Foundation; either
+ version 2 of the License, or (at your option) any later version.
+
+ GPGME++ is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU Library General Public License for more details.
+
+ You should have received a copy of the GNU Library General Public License
+ along with GPGME++; see the file COPYING.LIB. If not, write to the
+ Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+ Boston, MA 02110-1301, USA.
+*/
+
+#include "data_p.h"
+#include <error.h>
+#include <interfaces/dataprovider.h>
+
+#include <gpgme.h>
+
+#ifndef NDEBUG
+#include <iostream>
+#endif
+
+GpgME::Data::Private::~Private()
+{
+ if (data) {
+ gpgme_data_release(data);
+ }
+}
+
+const GpgME::Data::Null GpgME::Data::null;
+
+GpgME::Data::Data()
+{
+ gpgme_data_t data;
+ const gpgme_error_t e = gpgme_data_new(&data);
+ d.reset(new Private(e ? 0 : data));
+}
+
+GpgME::Data::Data(const Null &)
+ : d(new Private(0))
+{
+
+}
+
+GpgME::Data::Data(gpgme_data_t data)
+ : d(new Private(data))
+{
+
+}
+
+GpgME::Data::Data(const char *buffer, size_t size, bool copy)
+{
+ gpgme_data_t data;
+ const gpgme_error_t e = gpgme_data_new_from_mem(&data, buffer, size, int(copy));
+ std::string sizestr = std::to_string(size);
+ // Ignore errors as this is optional
+ gpgme_data_set_flag(data, "size-hint", sizestr.c_str());
+ d.reset(new Private(e ? 0 : data));
+}
+
+GpgME::Data::Data(const char *filename)
+{
+ gpgme_data_t data;
+ const gpgme_error_t e = gpgme_data_new(&data);
+ d.reset(new Private(e ? 0 : data));
+ if (!e) {
+ setFileName(filename);
+ }
+}
+
+GpgME::Data::Data(const char *filename, off_t offset, size_t length)
+{
+ gpgme_data_t data;
+ const gpgme_error_t e = gpgme_data_new_from_filepart(&data, filename, 0, offset, length);
+ d.reset(new Private(e ? 0 : data));
+}
+
+GpgME::Data::Data(FILE *fp)
+{
+ gpgme_data_t data;
+ const gpgme_error_t e = gpgme_data_new_from_stream(&data, fp);
+ d.reset(new Private(e ? 0 : data));
+}
+
+GpgME::Data::Data(FILE *fp, off_t offset, size_t length)
+{
+ gpgme_data_t data;
+ const gpgme_error_t e = gpgme_data_new_from_filepart(&data, 0, fp, offset, length);
+ d.reset(new Private(e ? 0 : data));
+}
+
+GpgME::Data::Data(int fd)
+{
+ gpgme_data_t data;
+ const gpgme_error_t e = gpgme_data_new_from_fd(&data, fd);
+ d.reset(new Private(e ? 0 : data));
+}
+
+GpgME::Data::Data(DataProvider *dp)
+{
+ d.reset(new Private);
+ if (!dp) {
+ return;
+ }
+ if (!dp->isSupported(DataProvider::Read)) {
+ d->cbs.read = 0;
+ }
+ if (!dp->isSupported(DataProvider::Write)) {
+ d->cbs.write = 0;
+ }
+ if (!dp->isSupported(DataProvider::Seek)) {
+ d->cbs.seek = 0;
+ }
+ if (!dp->isSupported(DataProvider::Release)) {
+ d->cbs.release = 0;
+ }
+ const gpgme_error_t e = gpgme_data_new_from_cbs(&d->data, &d->cbs, dp);
+ if (e) {
+ d->data = 0;
+ }
+ if (dp->isSupported(DataProvider::Seek)) {
+ off_t size = seek(0, SEEK_END);
+ seek(0, SEEK_SET);
+ std::string sizestr = std::to_string(size);
+ // Ignore errors as this is optional
+ gpgme_data_set_flag(d->data, "size-hint", sizestr.c_str());
+ }
+#ifndef NDEBUG
+ //std::cerr << "GpgME::Data(): DataProvider supports: "
+ // << ( d->cbs.read ? "read" : "no read" ) << ", "
+ // << ( d->cbs.write ? "write" : "no write" ) << ", "
+ // << ( d->cbs.seek ? "seek" : "no seek" ) << ", "
+ // << ( d->cbs.release ? "release" : "no release" ) << std::endl;
+#endif
+}
+
+bool GpgME::Data::isNull() const
+{
+ return !d || !d->data;
+}
+
+GpgME::Data::Encoding GpgME::Data::encoding() const
+{
+ switch (gpgme_data_get_encoding(d->data)) {
+ case GPGME_DATA_ENCODING_NONE: return AutoEncoding;
+ case GPGME_DATA_ENCODING_BINARY: return BinaryEncoding;
+ case GPGME_DATA_ENCODING_BASE64: return Base64Encoding;
+ case GPGME_DATA_ENCODING_ARMOR: return ArmorEncoding;
+ case GPGME_DATA_ENCODING_MIME: return MimeEncoding;
+ }
+ return AutoEncoding;
+}
+
+GpgME::Error GpgME::Data::setEncoding(Encoding enc)
+{
+ gpgme_data_encoding_t ge = GPGME_DATA_ENCODING_NONE;
+ switch (enc) {
+ case AutoEncoding: ge = GPGME_DATA_ENCODING_NONE; break;
+ case BinaryEncoding: ge = GPGME_DATA_ENCODING_BINARY; break;
+ case Base64Encoding: ge = GPGME_DATA_ENCODING_BASE64; break;
+ case ArmorEncoding: ge = GPGME_DATA_ENCODING_ARMOR; break;
+ case MimeEncoding: ge = GPGME_DATA_ENCODING_MIME; break;
+ }
+ return Error(gpgme_data_set_encoding(d->data, ge));
+}
+
+GpgME::Data::Type GpgME::Data::type() const
+{
+ if (isNull()) {
+ return Invalid;
+ }
+ switch (gpgme_data_identify(d->data, 0)) {
+ case GPGME_DATA_TYPE_INVALID: return Invalid;
+ case GPGME_DATA_TYPE_UNKNOWN: return Unknown;
+ case GPGME_DATA_TYPE_PGP_SIGNED: return PGPSigned;
+ case GPGME_DATA_TYPE_PGP_OTHER: return PGPOther;
+ case GPGME_DATA_TYPE_PGP_KEY: return PGPKey;
+ case GPGME_DATA_TYPE_CMS_SIGNED: return CMSSigned;
+ case GPGME_DATA_TYPE_CMS_ENCRYPTED: return CMSEncrypted;
+ case GPGME_DATA_TYPE_CMS_OTHER: return CMSOther;
+ case GPGME_DATA_TYPE_X509_CERT: return X509Cert;
+ case GPGME_DATA_TYPE_PKCS12: return PKCS12;
+ case GPGME_DATA_TYPE_PGP_ENCRYPTED: return PGPEncrypted;
+ case GPGME_DATA_TYPE_PGP_SIGNATURE: return PGPSignature;
+ }
+ return Invalid;
+}
+
+char *GpgME::Data::fileName() const
+{
+ return gpgme_data_get_file_name(d->data);
+}
+
+GpgME::Error GpgME::Data::setFileName(const char *name)
+{
+ return Error(gpgme_data_set_file_name(d->data, name));
+}
+
+ssize_t GpgME::Data::read(void *buffer, size_t length)
+{
+ return gpgme_data_read(d->data, buffer, length);
+}
+
+ssize_t GpgME::Data::write(const void *buffer, size_t length)
+{
+ return gpgme_data_write(d->data, buffer, length);
+}
+
+off_t GpgME::Data::seek(off_t offset, int whence)
+{
+ return gpgme_data_seek(d->data, offset, whence);
+}
diff --git a/lang/cpp/src/data.h b/lang/cpp/src/data.h
new file mode 100644
index 0000000..b2f2173
--- /dev/null
+++ b/lang/cpp/src/data.h
@@ -0,0 +1,126 @@
+/*
+ data.h - wraps a gpgme data object
+ Copyright (C) 2003,2004 Klarälvdalens Datakonsult AB
+
+ This file is part of GPGME++.
+
+ GPGME++ is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Library General Public
+ License as published by the Free Software Foundation; either
+ version 2 of the License, or (at your option) any later version.
+
+ GPGME++ is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU Library General Public License for more details.
+
+ You should have received a copy of the GNU Library General Public License
+ along with GPGME++; see the file COPYING.LIB. If not, write to the
+ Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+ Boston, MA 02110-1301, USA.
+*/
+
+#ifndef __GPGMEPP_DATA_H__
+#define __GPGMEPP_DATA_H__
+
+#include "global.h"
+
+#include <sys/types.h> // for size_t, off_t
+#include <cstdio> // FILE
+#include <algorithm>
+#include <memory>
+
+namespace GpgME
+{
+
+class DataProvider;
+class Error;
+
+class GPGMEPP_EXPORT Data
+{
+ struct Null {
+ Null() {}
+ };
+public:
+ /* implicit */ Data(const Null &);
+ Data();
+ explicit Data(gpgme_data_t data);
+
+ // Memory-Based Data Buffers:
+ Data(const char *buffer, size_t size, bool copy = true);
+ explicit Data(const char *filename);
+ Data(const char *filename, off_t offset, size_t length);
+ Data(std::FILE *fp, off_t offset, size_t length);
+ // File-Based Data Buffers:
+ explicit Data(std::FILE *fp);
+ explicit Data(int fd);
+ // Callback-Based Data Buffers:
+ explicit Data(DataProvider *provider);
+
+ static const Null null;
+
+ const Data &operator=(Data other)
+ {
+ swap(other);
+ return *this;
+ }
+
+ void swap(Data &other)
+ {
+ using std::swap;
+ swap(this->d, other.d);
+ }
+
+ bool isNull() const;
+
+ enum Encoding {
+ AutoEncoding,
+ BinaryEncoding,
+ Base64Encoding,
+ ArmorEncoding,
+ MimeEncoding
+ };
+ Encoding encoding() const;
+ Error setEncoding(Encoding encoding);
+
+ enum Type {
+ Invalid,
+ Unknown,
+ PGPSigned,
+ PGPOther,
+ PGPKey,
+ CMSSigned,
+ CMSEncrypted,
+ CMSOther,
+ X509Cert,
+ PKCS12,
+ PGPEncrypted,
+ PGPSignature,
+ };
+ Type type() const;
+
+ char *fileName() const;
+ Error setFileName(const char *name);
+
+ ssize_t read(void *buffer, size_t length);
+ ssize_t write(const void *buffer, size_t length);
+ off_t seek(off_t offset, int whence);
+
+ class Private;
+ Private *impl()
+ {
+ return d.get();
+ }
+ const Private *impl() const
+ {
+ return d.get();
+ }
+private:
+ std::shared_ptr<Private> d;
+};
+
+}
+
+GPGMEPP_MAKE_STD_SWAP_SPECIALIZATION(Data)
+
+#endif // __GPGMEPP_DATA_H__
diff --git a/lang/cpp/src/data_p.h b/lang/cpp/src/data_p.h
new file mode 100644
index 0000000..38ba55a
--- /dev/null
+++ b/lang/cpp/src/data_p.h
@@ -0,0 +1,40 @@
+/*
+ data_p.h - wraps a gpgme data object, private part -*- c++ -*-
+ Copyright (C) 2003,2004 Klarälvdalens Datakonsult AB
+
+ This file is part of GPGME++.
+
+ GPGME++ is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Library General Public
+ License as published by the Free Software Foundation; either
+ version 2 of the License, or (at your option) any later version.
+
+ GPGME++ is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU Library General Public License for more details.
+
+ You should have received a copy of the GNU Library General Public License
+ along with GPGME++; see the file COPYING.LIB. If not, write to the
+ Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+ Boston, MA 02110-1301, USA.
+*/
+
+#ifndef __GPGMEPP_DATA_P_H__
+#define __GPGMEPP_DATA_P_H__
+
+#include <data.h>
+#include "callbacks.h"
+
+class GpgME::Data::Private
+{
+public:
+ explicit Private(gpgme_data_t d = 0)
+ : data(d), cbs(data_provider_callbacks) {}
+ ~Private();
+
+ gpgme_data_t data;
+ gpgme_data_cbs cbs;
+};
+
+#endif // __GPGMEPP_DATA_P_H__
diff --git a/lang/cpp/src/decryptionresult.cpp b/lang/cpp/src/decryptionresult.cpp
new file mode 100644
index 0000000..78a2b1b
--- /dev/null
+++ b/lang/cpp/src/decryptionresult.cpp
@@ -0,0 +1,240 @@
+/*
+ decryptionresult.cpp - wraps a gpgme keygen result
+ Copyright (C) 2004 Klarälvdalens Datakonsult AB
+
+ This file is part of GPGME++.
+
+ GPGME++ is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Library General Public
+ License as published by the Free Software Foundation; either
+ version 2 of the License, or (at your option) any later version.
+
+ GPGME++ is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU Library General Public License for more details.
+
+ You should have received a copy of the GNU Library General Public License
+ along with GPGME++; see the file COPYING.LIB. If not, write to the
+ Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+ Boston, MA 02110-1301, USA.
+*/
+
+#include <decryptionresult.h>
+#include "result_p.h"
+#include "util.h"
+
+#include <gpgme.h>
+
+#include <algorithm>
+#include <iterator>
+#include <cstring>
+#include <cstdlib>
+#include <istream>
+
+#include <string.h>
+
+class GpgME::DecryptionResult::Private
+{
+public:
+ explicit Private(const _gpgme_op_decrypt_result &r) : res(r)
+ {
+ if (res.unsupported_algorithm) {
+ res.unsupported_algorithm = strdup(res.unsupported_algorithm);
+ }
+ if (res.file_name) {
+ res.file_name = strdup(res.file_name);
+ }
+ //FIXME: copying gpgme_recipient_t objects invalidates the keyid member,
+ //thus we use _keyid for now (internal API)
+ for (gpgme_recipient_t r = res.recipients ; r ; r = r->next) {
+ recipients.push_back(*r);
+ }
+ res.recipients = 0;
+ }
+ ~Private()
+ {
+ if (res.unsupported_algorithm) {
+ std::free(res.unsupported_algorithm);
+ }
+ res.unsupported_algorithm = 0;
+ if (res.file_name) {
+ std::free(res.file_name);
+ }
+ res.file_name = 0;
+ }
+
+ _gpgme_op_decrypt_result res;
+ std::vector<_gpgme_recipient> recipients;
+};
+
+GpgME::DecryptionResult::DecryptionResult(gpgme_ctx_t ctx, int error)
+ : GpgME::Result(error), d()
+{
+ init(ctx);
+}
+
+GpgME::DecryptionResult::DecryptionResult(gpgme_ctx_t ctx, const Error &error)
+ : GpgME::Result(error), d()
+{
+ init(ctx);
+}
+
+void GpgME::DecryptionResult::init(gpgme_ctx_t ctx)
+{
+ if (!ctx) {
+ return;
+ }
+ gpgme_decrypt_result_t res = gpgme_op_decrypt_result(ctx);
+ if (!res) {
+ return;
+ }
+ d.reset(new Private(*res));
+}
+
+make_standard_stuff(DecryptionResult)
+
+const char *GpgME::DecryptionResult::unsupportedAlgorithm() const
+{
+ return d ? d->res.unsupported_algorithm : 0 ;
+}
+
+bool GpgME::DecryptionResult::isWrongKeyUsage() const
+{
+ return d && d->res.wrong_key_usage;
+}
+
+const char *GpgME::DecryptionResult::fileName() const
+{
+ return d ? d->res.file_name : 0 ;
+}
+
+unsigned int GpgME::DecryptionResult::numRecipients() const
+{
+ return d ? d->recipients.size() : 0 ;
+}
+
+GpgME::DecryptionResult::Recipient GpgME::DecryptionResult::recipient(unsigned int idx) const
+{
+ if (d && idx < d->recipients.size()) {
+ return Recipient(&d->recipients[idx]);
+ }
+ return Recipient();
+}
+
+namespace
+{
+struct make_recipient {
+ GpgME::DecryptionResult::Recipient operator()(_gpgme_recipient &t)
+ {
+ return GpgME::DecryptionResult::Recipient(&t);
+ }
+};
+}
+
+std::vector<GpgME::DecryptionResult::Recipient> GpgME::DecryptionResult::recipients() const
+{
+ std::vector<Recipient> result;
+ if (d) {
+ result.reserve(d->recipients.size());
+ std::transform(d->recipients.begin(), d->recipients.end(),
+ std::back_inserter(result),
+ make_recipient());
+ }
+ return result;
+}
+
+class GpgME::DecryptionResult::Recipient::Private : public _gpgme_recipient
+{
+public:
+ Private(gpgme_recipient_t reci) : _gpgme_recipient(*reci) {}
+};
+
+GpgME::DecryptionResult::Recipient::Recipient()
+ : d()
+{
+
+}
+
+GpgME::DecryptionResult::Recipient::Recipient(gpgme_recipient_t r)
+ : d()
+{
+ if (r) {
+ d.reset(new Private(r));
+ }
+}
+
+bool GpgME::DecryptionResult::Recipient::isNull() const
+{
+ return !d;
+}
+
+const char *GpgME::DecryptionResult::Recipient::keyID() const
+{
+ //_keyid is internal API, but the public keyid is invalid after copying (see above)
+ if (d) {
+ return d->_keyid;
+ }
+ return 0;
+}
+
+const char *GpgME::DecryptionResult::Recipient::shortKeyID() const
+{
+ //_keyid is internal API, but the public keyid is invalid after copying (see above)
+ if (d) {
+ return d->_keyid + 8;
+ }
+ return 0;
+}
+
+unsigned int GpgME::DecryptionResult::Recipient::publicKeyAlgorithm() const
+{
+ if (d) {
+ return d->pubkey_algo;
+ }
+ return 0;
+}
+
+const char *GpgME::DecryptionResult::Recipient::publicKeyAlgorithmAsString() const
+{
+ if (d) {
+ return gpgme_pubkey_algo_name(d->pubkey_algo);
+ }
+ return 0;
+}
+
+GpgME::Error GpgME::DecryptionResult::Recipient::status() const
+{
+ if (d) {
+ return Error(d->status);
+ }
+ return Error();
+}
+
+std::ostream &GpgME::operator<<(std::ostream &os, const DecryptionResult &result)
+{
+ os << "GpgME::DecryptionResult(";
+ if (!result.isNull()) {
+ os << "\n error: " << result.error()
+ << "\n fileName: " << protect(result.fileName())
+ << "\n unsupportedAlgorithm: " << protect(result.unsupportedAlgorithm())
+ << "\n isWrongKeyUsage: " << result.isWrongKeyUsage()
+ << "\n recipients:\n";
+ const std::vector<DecryptionResult::Recipient> recipients = result.recipients();
+ std::copy(recipients.begin(), recipients.end(),
+ std::ostream_iterator<DecryptionResult::Recipient>(os, "\n"));
+ }
+ return os << ')';
+}
+
+std::ostream &GpgME::operator<<(std::ostream &os, const DecryptionResult::Recipient &reci)
+{
+ os << "GpgME::DecryptionResult::Recipient(";
+ if (!reci.isNull()) {
+ os << "\n keyID: " << protect(reci.keyID())
+ << "\n shortKeyID: " << protect(reci.shortKeyID())
+ << "\n publicKeyAlgorithm: " << protect(reci.publicKeyAlgorithmAsString())
+ << "\n status: " << reci.status();
+ }
+ return os << ')';
+}
diff --git a/lang/cpp/src/decryptionresult.h b/lang/cpp/src/decryptionresult.h
new file mode 100644
index 0000000..60b78d9
--- /dev/null
+++ b/lang/cpp/src/decryptionresult.h
@@ -0,0 +1,130 @@
+/*
+ decryptionresult.h - wraps a gpgme keygen result
+ Copyright (C) 2004 Klarälvdalens Datakonsult AB
+
+ This file is part of GPGME++.
+
+ GPGME++ is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Library General Public
+ License as published by the Free Software Foundation; either
+ version 2 of the License, or (at your option) any later version.
+
+ GPGME++ is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU Library General Public License for more details.
+
+ You should have received a copy of the GNU Library General Public License
+ along with GPGME++; see the file COPYING.LIB. If not, write to the
+ Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+ Boston, MA 02110-1301, USA.
+*/
+
+#ifndef __GPGMEPP_DECRYPTIONRESULT_H__
+#define __GPGMEPP_DECRYPTIONRESULT_H__
+
+#include "gpgmefw.h"
+#include "result.h"
+#include "gpgmepp_export.h"
+
+#include <vector>
+#include <algorithm>
+#include <iosfwd>
+#include <memory>
+
+namespace GpgME
+{
+
+class Error;
+
+class GPGMEPP_EXPORT DecryptionResult : public Result
+{
+public:
+ DecryptionResult();
+ DecryptionResult(gpgme_ctx_t ctx, int error);
+ DecryptionResult(gpgme_ctx_t ctx, const Error &err);
+ explicit DecryptionResult(const Error &err);
+
+ const DecryptionResult &operator=(DecryptionResult other)
+ {
+ swap(other);
+ return *this;
+ }
+
+ void swap(DecryptionResult &other)
+ {
+ Result::swap(other);
+ using std::swap;
+ swap(this->d, other.d);
+ }
+
+ bool isNull() const;
+
+ GPGMEPP_DEPRECATED const char *unsupportedAlgortihm() const
+ {
+ return unsupportedAlgorithm();
+ }
+ const char *unsupportedAlgorithm() const;
+
+ GPGMEPP_DEPRECATED bool wrongKeyUsage() const
+ {
+ return isWrongKeyUsage();
+ }
+ bool isWrongKeyUsage() const;
+
+ const char *fileName() const;
+
+ class Recipient;
+
+ unsigned int numRecipients() const;
+ Recipient recipient(unsigned int idx) const;
+ std::vector<Recipient> recipients() const;
+
+private:
+ class Private;
+ void init(gpgme_ctx_t ctx);
+ std::shared_ptr<Private> d;
+};
+
+GPGMEPP_EXPORT std::ostream &operator<<(std::ostream &os, const DecryptionResult &result);
+
+class GPGMEPP_EXPORT DecryptionResult::Recipient
+{
+public:
+ Recipient();
+ explicit Recipient(gpgme_recipient_t reci);
+
+ const Recipient &operator=(Recipient other)
+ {
+ swap(other);
+ return *this;
+ }
+
+ void swap(Recipient &other)
+ {
+ using std::swap;
+ swap(this->d, other.d);
+ }
+
+ bool isNull() const;
+
+ const char *keyID() const;
+ const char *shortKeyID() const;
+
+ unsigned int publicKeyAlgorithm() const;
+ const char *publicKeyAlgorithmAsString() const;
+
+ Error status() const;
+
+private:
+ class Private;
+ std::shared_ptr<Private> d;
+};
+
+GPGMEPP_EXPORT std::ostream &operator<<(std::ostream &os, const DecryptionResult::Recipient &reci);
+
+}
+
+GPGMEPP_MAKE_STD_SWAP_SPECIALIZATION(DecryptionResult)
+
+#endif // __GPGMEPP_DECRYPTIONRESULT_H__
diff --git a/lang/cpp/src/defaultassuantransaction.cpp b/lang/cpp/src/defaultassuantransaction.cpp
new file mode 100644
index 0000000..5bcf970
--- /dev/null
+++ b/lang/cpp/src/defaultassuantransaction.cpp
@@ -0,0 +1,78 @@
+/*
+ defaultassuantransaction.cpp - default Assuan Transaction that just stores data and status lines
+ Copyright (C) 2009 Klarälvdalens Datakonsult AB
+
+ This file is part of GPGME++.
+
+ GPGME++ is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Library General Public
+ License as published by the Free Software Foundation; either
+ version 2 of the License, or (at your option) any later version.
+
+ GPGME++ is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU Library General Public License for more details.
+
+ You should have received a copy of the GNU Library General Public License
+ along with GPGME++; see the file COPYING.LIB. If not, write to the
+ Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+ Boston, MA 02110-1301, USA.
+*/
+
+#include "defaultassuantransaction.h"
+#include "error.h"
+#include "data.h"
+
+#include <sstream>
+
+using namespace GpgME;
+
+DefaultAssuanTransaction::DefaultAssuanTransaction()
+ : AssuanTransaction(),
+ m_status(),
+ m_data()
+{
+
+}
+
+DefaultAssuanTransaction::~DefaultAssuanTransaction() {}
+
+Error DefaultAssuanTransaction::data(const char *data, size_t len)
+{
+ m_data.append(data, len);
+ return Error();
+}
+
+Data DefaultAssuanTransaction::inquire(const char *name, const char *args, Error &err)
+{
+ (void)name; (void)args; (void)err;
+ return Data::null;
+}
+
+Error DefaultAssuanTransaction::status(const char *status, const char *args)
+{
+ m_status.push_back(std::pair<std::string, std::string>(status, args));
+ return Error();
+}
+
+std::vector<std::string> DefaultAssuanTransaction::statusLine(const char *tag) const
+{
+ std::vector<std::string> result;
+ for (std::vector< std::pair<std::string, std::string> >::const_iterator it = m_status.begin(), end = m_status.end() ; it != end ; ++it) {
+ if (it->first == tag) {
+ result.push_back(it->second);
+ }
+ }
+ return result;
+}
+
+std::string DefaultAssuanTransaction::firstStatusLine(const char *tag) const
+{
+ for (std::vector< std::pair<std::string, std::string> >::const_iterator it = m_status.begin(), end = m_status.end() ; it != end ; ++it) {
+ if (it->first == tag) {
+ return it->second;
+ }
+ }
+ return std::string();
+}
diff --git a/lang/cpp/src/defaultassuantransaction.h b/lang/cpp/src/defaultassuantransaction.h
new file mode 100644
index 0000000..bf4b839
--- /dev/null
+++ b/lang/cpp/src/defaultassuantransaction.h
@@ -0,0 +1,65 @@
+/*
+ defaultassuantransaction.h - default Assuan Transaction that just stores data and status lines
+ Copyright (C) 2009 Klarälvdalens Datakonsult AB
+
+ This file is part of GPGME++.
+
+ GPGME++ is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Library General Public
+ License as published by the Free Software Foundation; either
+ version 2 of the License, or (at your option) any later version.
+
+ GPGME++ is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU Library General Public License for more details.
+
+ You should have received a copy of the GNU Library General Public License
+ along with GPGME++; see the file COPYING.LIB. If not, write to the
+ Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+ Boston, MA 02110-1301, USA.
+*/
+
+#ifndef __GPGMEPP_DEFAULTASSUANTRANSACTION_H__
+#define __GPGMEPP_DEFAULTASSUANTRANSACTION_H__
+
+#include <interfaces/assuantransaction.h>
+
+#include <string>
+#include <vector>
+#include <utility>
+
+namespace GpgME
+{
+
+class GPGMEPP_EXPORT DefaultAssuanTransaction : public AssuanTransaction
+{
+public:
+ explicit DefaultAssuanTransaction();
+ ~DefaultAssuanTransaction();
+
+ const std::vector< std::pair<std::string, std::string> > &statusLines() const
+ {
+ return m_status;
+ }
+ std::vector<std::string> statusLine(const char *tag) const;
+ std::string firstStatusLine(const char *tag) const;
+
+ const std::string &data() const
+ {
+ return m_data;
+ }
+
+private:
+ /* reimp */ Error data(const char *data, size_t datalen);
+ /* reimp */ Data inquire(const char *name, const char *args, Error &err);
+ /* reimp */ Error status(const char *status, const char *args);
+
+private:
+ std::vector< std::pair<std::string, std::string> > m_status;
+ std::string m_data;
+};
+
+} // namespace GpgME
+
+#endif // __GPGMEPP_DEFAULTASSUANTRANSACTION_H__
diff --git a/lang/cpp/src/editinteractor.cpp b/lang/cpp/src/editinteractor.cpp
new file mode 100644
index 0000000..07dc26d
--- /dev/null
+++ b/lang/cpp/src/editinteractor.cpp
@@ -0,0 +1,339 @@
+/*
+ editinteractor.cpp - Interface for edit interactors
+ Copyright (C) 2007 Klarälvdalens Datakonsult AB
+
+ This file is part of GPGME++.
+
+ GPGME++ is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Library General Public
+ License as published by the Free Software Foundation; either
+ version 2 of the License, or (at your option) any later version.
+
+ GPGME++ is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU Library General Public License for more details.
+
+ You should have received a copy of the GNU Library General Public License
+ along with GPGME++; see the file COPYING.LIB. If not, write to the
+ Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+ Boston, MA 02110-1301, USA.
+*/
+
+#include "editinteractor.h"
+#include "callbacks.h"
+#include "error.h"
+
+#include <gpgme.h>
+
+#ifdef _WIN32
+# include <io.h>
+#include <windows.h>
+#else
+# include <unistd.h>
+#endif
+
+#include <cerrno>
+#include <cstring>
+
+#ifndef GPG_ERR_ALREADY_SIGNED
+# define GPG_ERR_ALREADY_SIGNED GPG_ERR_USER_1
+#endif
+
+using namespace GpgME;
+
+static const char *status_to_string(unsigned int status);
+static Error status_to_error(unsigned int status);
+
+class EditInteractor::Private
+{
+ friend class ::GpgME::EditInteractor;
+ friend class ::GpgME::CallbackHelper;
+ EditInteractor *const q;
+public:
+ explicit Private(EditInteractor *qq);
+ ~Private();
+
+private:
+ unsigned int state;
+ Error error;
+ std::FILE *debug;
+};
+
+class GpgME::CallbackHelper
+{
+private:
+ static int writeAll(int fd, const void *buf, size_t count)
+ {
+ size_t toWrite = count;
+ while (toWrite > 0) {
+ const int n = gpgme_io_write(fd, buf, toWrite);
+ if (n < 0) {
+ return n;
+ }
+ toWrite -= n;
+ }
+ return count;
+ }
+
+public:
+ static int edit_interactor_callback_impl(void *opaque, gpgme_status_code_t status, const char *args, int fd)
+ {
+ EditInteractor::Private *ei = (EditInteractor::Private *)opaque;
+
+ Error err = status_to_error(status);
+
+ if (!err) {
+
+ // advance to next state based on input:
+ const unsigned int oldState = ei->state;
+ ei->state = ei->q->nextState(status, args, err);
+ if (ei->debug) {
+ std::fprintf(ei->debug, "EditInteractor: %u -> nextState( %s, %s ) -> %u\n",
+ oldState, status_to_string(status), args ? args : "<null>", ei->state);
+ }
+ if (err) {
+ ei->state = oldState;
+ goto error;
+ }
+
+ if (ei->state != oldState &&
+ // if there was an error from before, we stop here (### this looks weird, can this happen at all?)
+ ei->error.code() == GPG_ERR_NO_ERROR) {
+
+ // successful state change -> call action
+ if (const char *const result = ei->q->action(err)) {
+ if (err) {
+ goto error;
+ }
+ if (ei->debug) {
+ std::fprintf(ei->debug, "EditInteractor: action result \"%s\"\n", result);
+ }
+ // if there's a result, write it:
+ if (*result) {
+ gpgme_err_set_errno(0);
+ const ssize_t len = std::strlen(result);
+ if (writeAll(fd, result, len) != len) {
+ err = Error::fromSystemError();
+ if (ei->debug) {
+ std::fprintf(ei->debug, "EditInteractor: Could not write to fd %d (%s)\n", fd, err.asString());
+ }
+ goto error;
+ }
+ }
+ gpgme_err_set_errno(0);
+ if (writeAll(fd, "\n", 1) != 1) {
+ err = Error::fromSystemError();
+ if (ei->debug) {
+ std::fprintf(ei->debug, "EditInteractor: Could not write to fd %d (%s)\n", fd, err.asString());
+ }
+ goto error;
+ }
+ } else {
+ if (err) {
+ goto error;
+ }
+ if (ei->debug) {
+ std::fprintf(ei->debug, "EditInteractor: no action result\n");
+ }
+ }
+ } else {
+ if (ei->debug) {
+ std::fprintf(ei->debug, "EditInteractor: no action executed\n");
+ }
+ }
+ }
+
+ error:
+ if (err) {
+ ei->error = err;
+ ei->state = EditInteractor::ErrorState;
+ }
+
+ if (ei->debug) {
+ std::fprintf(ei->debug, "EditInteractor: error now %u (%s)\n",
+ ei->error.encodedError(), gpgme_strerror(ei->error.encodedError()));
+ }
+
+ return ei->error.encodedError();
+ }
+};
+
+static gpgme_error_t edit_interactor_callback(void *opaque, gpgme_status_code_t status, const char *args, int fd)
+{
+ return CallbackHelper::edit_interactor_callback_impl(opaque, status, args, fd);
+}
+
+const gpgme_edit_cb_t GpgME::edit_interactor_callback = ::edit_interactor_callback;
+
+EditInteractor::Private::Private(EditInteractor *qq)
+ : q(qq),
+ state(StartState),
+ error(),
+ debug(0)
+{
+
+}
+
+EditInteractor::Private::~Private() {}
+
+EditInteractor::EditInteractor()
+ : d(new Private(this))
+{
+
+}
+
+EditInteractor::~EditInteractor()
+{
+ delete d;
+}
+
+unsigned int EditInteractor::state() const
+{
+ return d->state;
+}
+
+Error EditInteractor::lastError() const
+{
+ return d->error;
+}
+
+bool EditInteractor::needsNoResponse(unsigned int status) const
+{
+ switch (status) {
+ case GPGME_STATUS_ALREADY_SIGNED:
+ case GPGME_STATUS_ERROR:
+ case GPGME_STATUS_GET_BOOL:
+ case GPGME_STATUS_GET_LINE:
+ case GPGME_STATUS_KEY_CREATED:
+ case GPGME_STATUS_NEED_PASSPHRASE_SYM:
+ case GPGME_STATUS_SC_OP_FAILURE:
+ return false;
+ default:
+ return true;
+ }
+}
+
+// static
+Error status_to_error(unsigned int status)
+{
+ switch (status) {
+ case GPGME_STATUS_MISSING_PASSPHRASE:
+ return Error::fromCode(GPG_ERR_NO_PASSPHRASE);
+ case GPGME_STATUS_ALREADY_SIGNED:
+ return Error::fromCode(GPG_ERR_ALREADY_SIGNED);
+ case GPGME_STATUS_SIGEXPIRED:
+ return Error::fromCode(GPG_ERR_SIG_EXPIRED);
+ }
+ return Error();
+}
+
+void EditInteractor::setDebugChannel(std::FILE *debug)
+{
+ d->debug = debug;
+}
+
+static const char *const status_strings[] = {
+ "EOF",
+ /* mkstatus processing starts here */
+ "ENTER",
+ "LEAVE",
+ "ABORT",
+
+ "GOODSIG",
+ "BADSIG",
+ "ERRSIG",
+
+ "BADARMOR",
+
+ "RSA_OR_IDEA",
+ "KEYEXPIRED",
+ "KEYREVOKED",
+
+ "TRUST_UNDEFINED",
+ "TRUST_NEVER",
+ "TRUST_MARGINAL",
+ "TRUST_FULLY",
+ "TRUST_ULTIMATE",
+
+ "SHM_INFO",
+ "SHM_GET",
+ "SHM_GET_BOOL",
+ "SHM_GET_HIDDEN",
+
+ "NEED_PASSPHRASE",
+ "VALIDSIG",
+ "SIG_ID",
+ "ENC_TO",
+ "NODATA",
+ "BAD_PASSPHRASE",
+ "NO_PUBKEY",
+ "NO_SECKEY",
+ "NEED_PASSPHRASE_SYM",
+ "DECRYPTION_FAILED",
+ "DECRYPTION_OKAY",
+ "MISSING_PASSPHRASE",
+ "GOOD_PASSPHRASE",
+ "GOODMDC",
+ "BADMDC",
+ "ERRMDC",
+ "IMPORTED",
+ "IMPORT_OK",
+ "IMPORT_PROBLEM",
+ "IMPORT_RES",
+ "FILE_START",
+ "FILE_DONE",
+ "FILE_ERROR",
+
+ "BEGIN_DECRYPTION",
+ "END_DECRYPTION",
+ "BEGIN_ENCRYPTION",
+ "END_ENCRYPTION",
+
+ "DELETE_PROBLEM",
+ "GET_BOOL",
+ "GET_LINE",
+ "GET_HIDDEN",
+ "GOT_IT",
+ "PROGRESS",
+ "SIG_CREATED",
+ "SESSION_KEY",
+ "NOTATION_NAME",
+ "NOTATION_DATA",
+ "POLICY_URL",
+ "BEGIN_STREAM",
+ "END_STREAM",
+ "KEY_CREATED",
+ "USERID_HINT",
+ "UNEXPECTED",
+ "INV_RECP",
+ "NO_RECP",
+ "ALREADY_SIGNED",
+ "SIGEXPIRED",
+ "EXPSIG",
+ "EXPKEYSIG",
+ "TRUNCATED",
+ "ERROR",
+ "NEWSIG",
+ "REVKEYSIG",
+ "SIG_SUBPACKET",
+ "NEED_PASSPHRASE_PIN",
+ "SC_OP_FAILURE",
+ "SC_OP_SUCCESS",
+ "CARDCTRL",
+ "BACKUP_KEY_CREATED",
+ "PKA_TRUST_BAD",
+ "PKA_TRUST_GOOD",
+
+ "PLAINTEXT",
+};
+static const unsigned int num_status_strings = sizeof status_strings / sizeof * status_strings ;
+
+const char *status_to_string(unsigned int idx)
+{
+ if (idx < num_status_strings) {
+ return status_strings[idx];
+ } else {
+ return "(unknown)";
+ }
+}
diff --git a/lang/cpp/src/editinteractor.h b/lang/cpp/src/editinteractor.h
new file mode 100644
index 0000000..2122052
--- /dev/null
+++ b/lang/cpp/src/editinteractor.h
@@ -0,0 +1,68 @@
+/*
+ editinteractor.h - Interface for edit interactors
+ Copyright (C) 2007 Klarälvdalens Datakonsult AB
+
+ This file is part of GPGME++.
+
+ GPGME++ is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Library General Public
+ License as published by the Free Software Foundation; either
+ version 2 of the License, or (at your option) any later version.
+
+ GPGME++ is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU Library General Public License for more details.
+
+ You should have received a copy of the GNU Library General Public License
+ along with GPGME++; see the file COPYING.LIB. If not, write to the
+ Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+ Boston, MA 02110-1301, USA.
+*/
+
+#ifndef __GPGMEPP_EDITINTERACTOR_H__
+#define __GPGMEPP_EDITINTERACTOR_H__
+
+#include "gpgmepp_export.h"
+
+#include <cstdio>
+
+namespace GpgME
+{
+
+class Error;
+class Context;
+class CallbackHelper;
+
+class GPGMEPP_EXPORT EditInteractor
+{
+ friend class ::GpgME::Context;
+ friend class ::GpgME::CallbackHelper;
+ EditInteractor(const EditInteractor &);
+ EditInteractor &operator=(const EditInteractor &);
+public:
+ EditInteractor();
+ virtual ~EditInteractor();
+
+ enum {
+ StartState = 0,
+ ErrorState = 0xFFFFFFFF
+ };
+
+ virtual const char *action(Error &err) const = 0;
+ virtual unsigned int nextState(unsigned int statusCode, const char *args, Error &err) const = 0;
+
+ unsigned int state() const;
+ Error lastError() const;
+ bool needsNoResponse(unsigned int statusCode) const;
+
+ void setDebugChannel(std::FILE *file);
+
+private:
+ class Private;
+ Private *const d;
+};
+
+} // namespace GpgME
+
+#endif // __GPGMEPP_EDITINTERACTOR_H__
diff --git a/lang/cpp/src/encryptionresult.cpp b/lang/cpp/src/encryptionresult.cpp
new file mode 100644
index 0000000..c4e7df5
--- /dev/null
+++ b/lang/cpp/src/encryptionresult.cpp
@@ -0,0 +1,159 @@
+/*
+ encryptionresult.cpp - wraps a gpgme verify result
+ Copyright (C) 2004 Klarälvdalens Datakonsult AB
+
+ This file is part of GPGME++.
+
+ GPGME++ is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Library General Public
+ License as published by the Free Software Foundation; either
+ version 2 of the License, or (at your option) any later version.
+
+ GPGME++ is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU Library General Public License for more details.
+
+ You should have received a copy of the GNU Library General Public License
+ along with GPGME++; see the file COPYING.LIB. If not, write to the
+ Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+ Boston, MA 02110-1301, USA.
+*/
+
+#include <encryptionresult.h>
+#include "result_p.h"
+#include "util.h"
+
+#include <gpgme.h>
+
+#include <cstring>
+#include <cstdlib>
+#include <istream>
+#include <algorithm>
+#include <iterator>
+
+#include <string.h>
+
+class GpgME::EncryptionResult::Private
+{
+public:
+ explicit Private(const gpgme_encrypt_result_t r)
+ {
+ if (!r) {
+ return;
+ }
+ for (gpgme_invalid_key_t ik = r->invalid_recipients ; ik ; ik = ik->next) {
+ gpgme_invalid_key_t copy = new _gpgme_invalid_key(*ik);
+ if (ik->fpr) {
+ copy->fpr = strdup(ik->fpr);
+ }
+ copy->next = 0;
+ invalid.push_back(copy);
+ }
+ }
+ ~Private()
+ {
+ for (std::vector<gpgme_invalid_key_t>::iterator it = invalid.begin() ; it != invalid.end() ; ++it) {
+ std::free((*it)->fpr);
+ delete *it; *it = 0;
+ }
+ }
+
+ std::vector<gpgme_invalid_key_t> invalid;
+};
+
+GpgME::EncryptionResult::EncryptionResult(gpgme_ctx_t ctx, int error)
+ : GpgME::Result(error), d()
+{
+ init(ctx);
+}
+
+GpgME::EncryptionResult::EncryptionResult(gpgme_ctx_t ctx, const Error &error)
+ : GpgME::Result(error), d()
+{
+ init(ctx);
+}
+
+void GpgME::EncryptionResult::init(gpgme_ctx_t ctx)
+{
+ if (!ctx) {
+ return;
+ }
+ gpgme_encrypt_result_t res = gpgme_op_encrypt_result(ctx);
+ if (!res) {
+ return;
+ }
+ d.reset(new Private(res));
+}
+
+make_standard_stuff(EncryptionResult)
+
+unsigned int GpgME::EncryptionResult::numInvalidRecipients() const
+{
+ return d ? d->invalid.size() : 0 ;
+}
+
+GpgME::InvalidRecipient GpgME::EncryptionResult::invalidEncryptionKey(unsigned int idx) const
+{
+ return InvalidRecipient(d, idx);
+}
+
+std::vector<GpgME::InvalidRecipient> GpgME::EncryptionResult::invalidEncryptionKeys() const
+{
+ if (!d) {
+ return std::vector<GpgME::InvalidRecipient>();
+ }
+ std::vector<GpgME::InvalidRecipient> result;
+ result.reserve(d->invalid.size());
+ for (unsigned int i = 0 ; i < d->invalid.size() ; ++i) {
+ result.push_back(InvalidRecipient(d, i));
+ }
+ return result;
+}
+
+GpgME::InvalidRecipient::InvalidRecipient(const std::shared_ptr<EncryptionResult::Private> &parent, unsigned int i)
+ : d(parent), idx(i)
+{
+
+}
+
+GpgME::InvalidRecipient::InvalidRecipient() : d(), idx(0) {}
+
+bool GpgME::InvalidRecipient::isNull() const
+{
+ return !d || idx >= d->invalid.size() ;
+}
+
+const char *GpgME::InvalidRecipient::fingerprint() const
+{
+ return isNull() ? 0 : d->invalid[idx]->fpr ;
+}
+
+GpgME::Error GpgME::InvalidRecipient::reason() const
+{
+ return Error(isNull() ? 0 : d->invalid[idx]->reason);
+}
+
+std::ostream &GpgME::operator<<(std::ostream &os, const EncryptionResult &result)
+{
+ os << "GpgME::EncryptionResult(";
+ if (!result.isNull()) {
+ os << "\n error: " << result.error()
+ << "\n invalid recipients:\n";
+ const std::vector<InvalidRecipient> ir = result.invalidEncryptionKeys();
+ std::copy(ir.begin(), ir.end(),
+ std::ostream_iterator<InvalidRecipient>(os, "\n"));
+ }
+ return os << ')';
+}
+
+std::ostream &GpgME::operator<<(std::ostream &os, const InvalidRecipient &ir)
+{
+ os << "GpgME::InvalidRecipient(";
+ if (!ir.isNull()) {
+ os << "\n fingerprint: " << protect(ir.fingerprint())
+ << "\n reason: " << ir.reason()
+ << '\n';
+ }
+ return os << ')';
+}
diff --git a/lang/cpp/src/encryptionresult.h b/lang/cpp/src/encryptionresult.h
new file mode 100644
index 0000000..edc400f
--- /dev/null
+++ b/lang/cpp/src/encryptionresult.h
@@ -0,0 +1,113 @@
+/*
+ encryptionresult.h - wraps a gpgme sign result
+ Copyright (C) 2004 Klarälvdalens Datakonsult AB
+
+ This file is part of GPGME++.
+
+ GPGME++ is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Library General Public
+ License as published by the Free Software Foundation; either
+ version 2 of the License, or (at your option) any later version.
+
+ GPGME++ is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU Library General Public License for more details.
+
+ You should have received a copy of the GNU Library General Public License
+ along with GPGME++; see the file COPYING.LIB. If not, write to the
+ Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+ Boston, MA 02110-1301, USA.
+*/
+
+#ifndef __GPGMEPP_ENCRYPTIONRESULT_H__
+#define __GPGMEPP_ENCRYPTIONRESULT_H__
+
+#include "gpgmefw.h"
+#include "result.h"
+#include "gpgmepp_export.h"
+
+#include <memory>
+
+#include <vector>
+#include <iosfwd>
+
+namespace GpgME
+{
+
+class Error;
+class InvalidRecipient;
+
+class GPGMEPP_EXPORT EncryptionResult : public Result
+{
+public:
+ EncryptionResult();
+ EncryptionResult(gpgme_ctx_t ctx, int error);
+ EncryptionResult(gpgme_ctx_t ctx, const Error &error);
+ EncryptionResult(const Error &err);
+
+ const EncryptionResult &operator=(EncryptionResult other)
+ {
+ swap(other);
+ return *this;
+ }
+
+ void swap(EncryptionResult &other)
+ {
+ Result::swap(other);
+ using std::swap;
+ swap(this->d, other.d);
+ }
+
+ bool isNull() const;
+
+ unsigned int numInvalidRecipients() const;
+
+ InvalidRecipient invalidEncryptionKey(unsigned int index) const;
+ std::vector<InvalidRecipient> invalidEncryptionKeys() const;
+
+ class Private;
+private:
+ void init(gpgme_ctx_t ctx);
+ std::shared_ptr<Private> d;
+};
+
+GPGMEPP_EXPORT std::ostream &operator<<(std::ostream &os, const EncryptionResult &result);
+
+class GPGMEPP_EXPORT InvalidRecipient
+{
+ friend class ::GpgME::EncryptionResult;
+ InvalidRecipient(const std::shared_ptr<EncryptionResult::Private> &parent, unsigned int index);
+public:
+ InvalidRecipient();
+
+ const InvalidRecipient &operator=(InvalidRecipient other)
+ {
+ swap(other);
+ return *this;
+ }
+
+ void swap(InvalidRecipient &other)
+ {
+ using std::swap;
+ swap(this->d, other.d);
+ }
+
+ bool isNull() const;
+
+ const char *fingerprint() const;
+ Error reason() const;
+
+private:
+ std::shared_ptr<EncryptionResult::Private> d;
+ unsigned int idx;
+};
+
+GPGMEPP_EXPORT std::ostream &operator<<(std::ostream &os, const InvalidRecipient &recipient);
+
+}
+
+GPGMEPP_MAKE_STD_SWAP_SPECIALIZATION(EncryptionResult)
+GPGMEPP_MAKE_STD_SWAP_SPECIALIZATION(InvalidRecipient)
+
+#endif // __GPGMEPP_ENCRYPTIONRESULT_H__
diff --git a/lang/cpp/src/engineinfo.cpp b/lang/cpp/src/engineinfo.cpp
new file mode 100644
index 0000000..c3b3e04
--- /dev/null
+++ b/lang/cpp/src/engineinfo.cpp
@@ -0,0 +1,88 @@
+/*
+ engineinfo.h
+ Copyright (C) 2004 Klarälvdalens Datakonsult AB
+
+ This file is part of GPGME++.
+
+ GPGME++ is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Library General Public
+ License as published by the Free Software Foundation; either
+ version 2 of the License, or (at your option) any later version.
+
+ GPGME++ is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU Library General Public License for more details.
+
+ You should have received a copy of the GNU Library General Public License
+ along with GPGME++; see the file COPYING.LIB. If not, write to the
+ Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+ Boston, MA 02110-1301, USA.
+*/
+
+#include "engineinfo.h"
+
+#include <gpgme.h>
+
+class GpgME::EngineInfo::Private
+{
+public:
+ Private(gpgme_engine_info_t engine = 0) : info(engine) {}
+ ~Private()
+ {
+ info = 0;
+ }
+
+ gpgme_engine_info_t info;
+};
+
+GpgME::EngineInfo::EngineInfo() : d() {}
+
+GpgME::EngineInfo::EngineInfo(gpgme_engine_info_t engine)
+ : d(new Private(engine))
+{
+
+}
+
+bool GpgME::EngineInfo::isNull() const
+{
+ return !d || !d->info;
+}
+
+GpgME::Protocol GpgME::EngineInfo::protocol() const
+{
+ if (isNull()) {
+ return UnknownProtocol;
+ }
+ switch (d->info->protocol) {
+ case GPGME_PROTOCOL_OpenPGP: return OpenPGP;
+ case GPGME_PROTOCOL_CMS: return CMS;
+ default:
+ return UnknownProtocol;
+ }
+}
+
+const char *GpgME::EngineInfo::fileName() const
+{
+ return isNull() ? 0 : d->info->file_name;
+}
+
+const char *GpgME::EngineInfo::version() const
+{
+ return isNull() ? 0 : d->info->version;
+}
+
+GpgME::EngineInfo::Version GpgME::EngineInfo::engineVersion() const
+{
+ return Version(version());
+}
+
+const char *GpgME::EngineInfo::requiredVersion() const
+{
+ return isNull() ? 0 : d->info->req_version;
+}
+
+const char *GpgME::EngineInfo::homeDirectory() const
+{
+ return isNull() ? 0 : d->info->home_dir;
+}
diff --git a/lang/cpp/src/engineinfo.h b/lang/cpp/src/engineinfo.h
new file mode 100644
index 0000000..72e125c
--- /dev/null
+++ b/lang/cpp/src/engineinfo.h
@@ -0,0 +1,126 @@
+/*
+ engineinfo.h
+ Copyright (C) 2004 Klarälvdalens Datakonsult AB
+
+ This file is part of GPGME++.
+
+ GPGME++ is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Library General Public
+ License as published by the Free Software Foundation; either
+ version 2 of the License, or (at your option) any later version.
+
+ GPGME++ is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU Library General Public License for more details.
+
+ You should have received a copy of the GNU Library General Public License
+ along with GPGME++; see the file COPYING.LIB. If not, write to the
+ Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+ Boston, MA 02110-1301, USA.
+*/
+
+#ifndef __GPGMEPP_ENGINEINFO_H__
+#define __GPGMEPP_ENGINEINFO_H__
+
+#include "global.h"
+
+#include <memory>
+
+#include <algorithm>
+#include <string>
+#include <iostream>
+
+namespace GpgME
+{
+
+class GPGMEPP_EXPORT EngineInfo
+{
+public:
+ struct Version
+ {
+ int major, minor, patch;
+
+ Version(const std::string& version)
+ {
+ if (version.empty() ||
+ std::sscanf(version.c_str(), "%d.%d.%d", &major, &minor, &patch) != 3) {
+ major = 0;
+ minor = 0;
+ patch = 0;
+ }
+ }
+
+ bool operator < (const Version& other)
+ {
+ if (major < other.major)
+ return true;
+ if (minor < other.minor)
+ return true;
+ if (patch < other.patch)
+ return true;
+ return false;
+ }
+
+ bool operator < (const char* other)
+ {
+ return operator<(Version(other));
+ }
+
+ bool operator == (const Version& other)
+ {
+ return major == other.major
+ && minor == other.minor
+ && patch == other.patch;
+ }
+
+ bool operator == (const char* other)
+ {
+ return operator==(Version(other));
+ }
+
+ friend std::ostream& operator << (std::ostream& stream, const Version& ver)
+ {
+ stream << ver.major;
+ stream << '.';
+ stream << ver.minor;
+ stream << '.';
+ stream << ver.patch;
+ return stream;
+ }
+ };
+
+ EngineInfo();
+ explicit EngineInfo(gpgme_engine_info_t engine);
+
+ const EngineInfo &operator=(EngineInfo other)
+ {
+ swap(other);
+ return *this;
+ }
+
+ void swap(EngineInfo &other)
+ {
+ using std::swap;
+ swap(this->d, other.d);
+ }
+
+ bool isNull() const;
+
+ Protocol protocol() const;
+ const char *fileName() const;
+ const char *version() const;
+ Version engineVersion() const;
+ const char *requiredVersion() const;
+ const char *homeDirectory() const;
+
+private:
+ class Private;
+ std::shared_ptr<Private> d;
+};
+
+}
+
+GPGMEPP_MAKE_STD_SWAP_SPECIALIZATION(EngineInfo)
+
+#endif // __GPGMEPP_ENGINEINFO_H__
diff --git a/lang/cpp/src/error.h b/lang/cpp/src/error.h
new file mode 100644
index 0000000..009fe20
--- /dev/null
+++ b/lang/cpp/src/error.h
@@ -0,0 +1,78 @@
+/*
+ error.h - wraps a gpgme error
+ Copyright (C) 2003, 2007 Klarälvdalens Datakonsult AB
+
+ This file is part of GPGME++.
+
+ GPGME++ is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Library General Public
+ License as published by the Free Software Foundation; either
+ version 2 of the License, or (at your option) any later version.
+
+ GPGME++ is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU Library General Public License for more details.
+
+ You should have received a copy of the GNU Library General Public License
+ along with GPGME++; see the file COPYING.LIB. If not, write to the
+ Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+ Boston, MA 02110-1301, USA.
+*/
+
+// -*- c++ -*-
+#ifndef __GPGMEPP_ERROR_H__
+#define __GPGMEPP_ERROR_H__
+
+#include "global.h"
+
+#include <string>
+#include <iosfwd>
+
+#include <gpg-error.h>
+
+#ifndef GPGMEPP_ERR_SOURCE_DEFAULT
+# define GPGMEPP_ERR_SOURCE_DEFAULT GPG_ERR_SOURCE_USER_1
+#endif
+
+namespace GpgME
+{
+
+class GPGMEPP_EXPORT Error
+{
+public:
+ Error() : mErr(0), mMessage() {}
+ explicit Error(unsigned int e) : mErr(e), mMessage() {}
+
+ const char *source() const;
+ const char *asString() const;
+
+ int code() const;
+ int sourceID() const;
+
+ bool isCanceled() const;
+
+ unsigned int encodedError() const
+ {
+ return mErr;
+ }
+ int toErrno() const;
+
+ static bool hasSystemError();
+ static Error fromSystemError(unsigned int src = GPGMEPP_ERR_SOURCE_DEFAULT);
+ static void setSystemError(gpg_err_code_t err);
+ static void setErrno(int err);
+ static Error fromErrno(int err, unsigned int src = GPGMEPP_ERR_SOURCE_DEFAULT);
+ static Error fromCode(unsigned int err, unsigned int src = GPGMEPP_ERR_SOURCE_DEFAULT);
+
+ GPGMEPP_MAKE_SAFE_BOOL_OPERATOR(mErr &&!isCanceled())
+private:
+ unsigned int mErr;
+ mutable std::string mMessage;
+};
+
+GPGMEPP_EXPORT std::ostream &operator<<(std::ostream &os, const Error &err);
+
+} // namespace GpgME
+
+#endif /* __GPGMEPP_ERROR_H__ */
diff --git a/lang/cpp/src/eventloopinteractor.cpp b/lang/cpp/src/eventloopinteractor.cpp
new file mode 100644
index 0000000..7ec258c
--- /dev/null
+++ b/lang/cpp/src/eventloopinteractor.cpp
@@ -0,0 +1,199 @@
+/*
+ eventloopinteractor.cpp
+ Copyright (C) 2003,2004 Klarälvdalens Datakonsult AB
+
+ This file is part of GPGME++.
+
+ GPGME++ is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Library General Public
+ License as published by the Free Software Foundation; either
+ version 2 of the License, or (at your option) any later version.
+
+ GPGME++ is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU Library General Public License for more details.
+
+ You should have received a copy of the GNU Library General Public License
+ along with GPGME++; see the file COPYING.LIB. If not, write to the
+ Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+ Boston, MA 02110-1301, USA.
+*/
+
+#include <eventloopinteractor.h>
+
+#include <context.h>
+#include "context_p.h"
+#include <key.h>
+#include <trustitem.h>
+
+#include <gpgme.h>
+
+#include <vector>
+using std::vector;
+#ifndef NDEBUG
+# include <iostream>
+#endif
+#include <cassert>
+
+namespace GpgME
+{
+
+//
+// EventLoopInteractor::Private Declaration
+//
+
+class EventLoopInteractor::Private
+{
+public:
+ struct OneFD {
+ OneFD(int aFd, int aDir, gpgme_io_cb_t aFnc,
+ void *aFncData, void *aExternalTag)
+ : fd(aFd), dir(aDir), fnc(aFnc),
+ fncData(aFncData), externalTag(aExternalTag) {}
+ int fd;
+ int dir;
+ gpgme_io_cb_t fnc;
+ void *fncData;
+ void *externalTag;
+ };
+
+ vector<OneFD *> mCallbacks;
+
+ static void removeIOCb(void *tag);
+ static gpgme_error_t registerIOCb(void *data, int fd, int dir,
+ gpgme_io_cb_t fnc, void *fnc_data,
+ void **r_tag);
+ static void eventIOCb(void *, gpgme_event_io_t type, void *type_data);
+
+ static const gpgme_io_cbs iocbs;
+};
+
+const gpgme_io_cbs EventLoopInteractor::Private::iocbs = {
+ &EventLoopInteractor::Private::registerIOCb,
+ 0,
+ &EventLoopInteractor::Private::removeIOCb,
+ &EventLoopInteractor::Private::eventIOCb,
+ 0
+};
+
+//
+// EventLoopInteractor::Private IO Callback Implementations
+//
+
+gpgme_error_t EventLoopInteractor::Private::registerIOCb(void *, int fd, int dir,
+ gpgme_io_cb_t fnc, void *fnc_data,
+ void **r_tag)
+{
+ assert(instance()); assert(instance()->d);
+ bool ok = false;
+ void *etag = instance()->registerWatcher(fd, dir ? Read : Write, ok);
+ if (!ok) {
+ return gpgme_error(GPG_ERR_GENERAL);
+ }
+ instance()->d->mCallbacks.push_back(new OneFD(fd, dir, fnc, fnc_data, etag));
+ if (r_tag) {
+ *r_tag = instance()->d->mCallbacks.back();
+ }
+ return GPG_ERR_NO_ERROR;
+}
+
+void EventLoopInteractor::Private::removeIOCb(void *tag)
+{
+
+ if (!instance() || !instance()->d) {
+ return;
+ }
+ for (vector<OneFD *>::iterator it = instance()->d->mCallbacks.begin();
+ it != instance()->d->mCallbacks.end() ; ++it) {
+ if (*it == tag) {
+ instance()->unregisterWatcher((*it)->externalTag);
+ delete *it; *it = 0;
+ instance()->d->mCallbacks.erase(it);
+ return;
+ }
+ }
+}
+
+void EventLoopInteractor::Private::eventIOCb(void *data, gpgme_event_io_t type, void *type_data)
+{
+ assert(instance());
+ Context *ctx = static_cast<Context *>(data);
+ switch (type) {
+ case GPGME_EVENT_START: {
+ instance()->operationStartEvent(ctx);
+ // TODO: what's in type_data?
+ }
+ break;
+ case GPGME_EVENT_DONE: {
+ gpgme_error_t e = *static_cast<gpgme_error_t *>(type_data);
+ if (ctx && ctx->impl()) {
+ ctx->impl()->lasterr = e;
+ }
+ instance()->operationDoneEvent(ctx, Error(e));
+ }
+ break;
+ case GPGME_EVENT_NEXT_KEY: {
+ gpgme_key_t key = static_cast<gpgme_key_t>(type_data);
+ instance()->nextKeyEvent(ctx, Key(key, false));
+ }
+ break;
+ case GPGME_EVENT_NEXT_TRUSTITEM: {
+ gpgme_trust_item_t item = static_cast<gpgme_trust_item_t>(type_data);
+ instance()->nextTrustItemEvent(ctx, TrustItem(item));
+ gpgme_trust_item_unref(item);
+ }
+ break;
+ default: // warn
+ ;
+ }
+}
+
+//
+// EventLoopInteractor Implementation
+//
+
+EventLoopInteractor *EventLoopInteractor::mSelf = 0;
+
+EventLoopInteractor::EventLoopInteractor() : d(new Private)
+{
+ assert(!mSelf);
+ mSelf = this;
+}
+
+EventLoopInteractor::~EventLoopInteractor()
+{
+ // warn if there are still callbacks registered
+ mSelf = 0;
+ delete d;
+}
+
+void EventLoopInteractor::manage(Context *context)
+{
+ if (!context || context->managedByEventLoopInteractor()) {
+ return;
+ }
+ gpgme_io_cbs *iocbs = new gpgme_io_cbs(Private::iocbs);
+ iocbs->event_priv = context;
+ context->installIOCallbacks(iocbs);
+}
+
+void EventLoopInteractor::unmanage(Context *context)
+{
+ if (context) {
+ context->uninstallIOCallbacks();
+ }
+}
+
+void EventLoopInteractor::actOn(int fd, Direction dir)
+{
+ for (vector<Private::OneFD *>::const_iterator it = d->mCallbacks.begin();
+ it != d->mCallbacks.end() ; ++it) {
+ if ((*it)->fd == fd && ((*it)->dir ? Read : Write) == dir) {
+ (*((*it)->fnc))((*it)->fncData, fd);
+ break;
+ }
+ }
+}
+
+} // namespace GpgME
diff --git a/lang/cpp/src/eventloopinteractor.h b/lang/cpp/src/eventloopinteractor.h
new file mode 100644
index 0000000..94821d6
--- /dev/null
+++ b/lang/cpp/src/eventloopinteractor.h
@@ -0,0 +1,156 @@
+/*
+ eventloopinteractor.h
+ Copyright (C) 2003,2004 Klarälvdalens Datakonsult AB
+
+ This file is part of GPGME++.
+
+ GPGME++ is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Library General Public
+ License as published by the Free Software Foundation; either
+ version 2 of the License, or (at your option) any later version.
+
+ GPGME++ is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU Library General Public License for more details.
+
+ You should have received a copy of the GNU Library General Public License
+ along with GPGME++; see the file COPYING.LIB. If not, write to the
+ Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+ Boston, MA 02110-1301, USA.
+*/
+
+// -*- c++ -*-
+#ifndef __GPGMEPP_EVENTLOOPINTERACTOR_H__
+#define __GPGMEPP_EVENTLOOPINTERACTOR_H__
+
+#include "gpgmepp_export.h"
+
+namespace GpgME
+{
+
+class Context;
+class Error;
+class TrustItem;
+class Key;
+
+/*! \file eventloopinteractor.h
+ \brief Abstract base class for gpgme's external event loop support
+
+ This class does most of the work involved with hooking GpgME++
+ up with external event loops, such as the GTK or Qt ones.
+
+ It actually provides two interfaces: An interface to the gpgme
+ IO Callback handling and one for gpgme events. The IO Callback
+ interface consists of the three methods \c actOn(), \c
+ registerWatcher() and \c unregisterWatcher(). The event
+ interface consists of the three methods \c nextTrustItemEvent(),
+ \c nextKeyEvent() and \c operationDoneEvent().
+
+ \sect General Usage
+
+ \c EventLoopInteractor is designed to be used as a
+ singleton. However, in order to make any use of it, you have to
+ subclass it and reimplement it's pure virtual methods (see
+ below). We suggest you keep the constructor protected and
+ provide a static \c instance() method that returns the single
+ instance. Alternatively, you can create an instance on the
+ stack, e.g. in \c main().
+
+ If you want \c EventLoopInteractor to manage a particular \c
+ Context, just call \c manage() on the \c Context. OTOH, if you
+ want to disable IO callbacks for a \c Context, use \c unmanage().
+
+ \sect IO Callback Interface
+
+ One part of this interface is represented by \c
+ registerWatcher() and \c unregisterWatcher(), both of which are
+ pure virtual. \c registerWatcher() should do anything necessary
+ to hook up watching of file descriptor \c fd for reading (\c dir
+ = \c Read) or writing (\c dir = Write) to the event loop you use
+ and return a tag identifying that particular watching process
+ uniquely. This could be the index into an array of objects you
+ use for that purpose or the address of such an object. E.g. in
+ Qt, you'd essentially just create a new \c QSocketNotifier:
+
+ \verbatim
+ void * registerWatcher( int fd, Direction dir ) {
+ return new QSocketNotifier( fd, dir == Read ? QSocketNotifier::Read : QSocketNotifier::Write );
+ // misses connecting to the activated() signal...
+ }
+ \endverbatim
+
+ which uses the address of the created object as unique tag. The
+ tag returned by \c registerWatcher is stored by \c
+ EventLoopInteractor and passed as argument to \c
+ unregisterWatcher(). So, in the picture above, you'd implement \c
+ unregisterWatcher() like this:
+
+ \verbatim
+ void unregisterWatcher( void * tag ) {
+ delete static_cast<QSocketNotifier*>( tag );
+ }
+ \endverbatim
+
+ The other part of the IO callback interface is \c actOn(), which
+ you should call if you receive notification from your event loop
+ about activity on file descriptor \c fd in direction \c dir. In
+ the picture above, you'd call this from the slot connected to
+ the socket notifier's \c activated() signal.
+
+ \note \c registerWatcher() as well as \c unregisterWatcher() may
+ be called from within \c actOn(), so be careful with
+ e.g. locking in threaded environments and keep in mind that the
+ object you used to find the \c fd and \c dir fo the \c actOn()
+ call might be deleted when \c actOn() returns!
+
+ \sect Event Handler Interface
+
+*/
+class GPGMEPP_EXPORT EventLoopInteractor
+{
+protected:
+ EventLoopInteractor();
+public:
+ virtual ~EventLoopInteractor();
+
+ static EventLoopInteractor *instance()
+ {
+ return mSelf;
+ }
+
+ void manage(Context *context);
+ void unmanage(Context *context);
+
+ enum Direction { Read, Write };
+protected:
+ //
+ // IO Notification Interface
+ //
+
+ /** Call this if your event loop detected activity on file
+ descriptor fd, with direction dir */
+ void actOn(int fd, Direction dir);
+
+ virtual void *registerWatcher(int fd, Direction dir, bool &ok) = 0;
+ virtual void unregisterWatcher(void *tag) = 0;
+
+ //
+ // Event Handler Interface
+ //
+
+ virtual void operationStartEvent(Context *context) = 0;
+ virtual void nextTrustItemEvent(Context *context, const TrustItem &item) = 0;
+ virtual void nextKeyEvent(Context *context, const Key &key) = 0;
+ virtual void operationDoneEvent(Context *context, const Error &e) = 0;
+
+private:
+ class Private;
+ friend class Private;
+ Private *const d;
+ static EventLoopInteractor *mSelf;
+};
+
+}
+
+#endif // __GPGMEPP_EVENTLOOPINTERACTOR_H__
diff --git a/lang/cpp/src/exception.cpp b/lang/cpp/src/exception.cpp
new file mode 100644
index 0000000..c687024
--- /dev/null
+++ b/lang/cpp/src/exception.cpp
@@ -0,0 +1,58 @@
+/*
+ exception.cpp - exception wrapping a gpgme error
+ Copyright (C) 2007 Klarälvdalens Datakonsult AB
+
+ This file is part of GPGME++.
+
+ GPGME++ is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Library General Public
+ License as published by the Free Software Foundation; either
+ version 2 of the License, or (at your option) any later version.
+
+ GPGME++ is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU Library General Public License for more details.
+
+ You should have received a copy of the GNU Library General Public License
+ along with GPGME++; see the file COPYING.LIB. If not, write to the
+ Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+ Boston, MA 02110-1301, USA.
+*/
+
+// -*- c++ -*-
+#include "exception.h"
+
+#include <gpgme.h>
+
+#include <sstream>
+
+using namespace GpgME;
+using namespace std; // only safe b/c it's so small a file!
+
+Exception::~Exception() throw() {}
+
+// static
+string Exception::make_message(const Error &err, const string &msg)
+{
+ return make_message(err, msg, NoOptions);
+}
+
+// static
+string Exception::make_message(const Error &err, const string &msg, Options opt)
+{
+ if (opt & MessageOnly) {
+ return msg;
+ }
+ char error_string[128];
+ error_string[0] = '\0';
+ gpgme_strerror_r(err.encodedError(), error_string, sizeof error_string);
+ error_string[sizeof error_string - 1] = '\0';
+ stringstream ss;
+ ss << gpgme_strsource(err.encodedError()) << ": ";
+ if (!msg.empty()) {
+ ss << msg << ": ";
+ }
+ ss << error_string << " (" << static_cast<unsigned long>(err.encodedError()) << ')';
+ return ss.str();
+}
diff --git a/lang/cpp/src/exception.h b/lang/cpp/src/exception.h
new file mode 100644
index 0000000..8f40b0e
--- /dev/null
+++ b/lang/cpp/src/exception.h
@@ -0,0 +1,68 @@
+/*
+ exception.h - exception wrapping a gpgme error
+ Copyright (C) 2007 Klarälvdalens Datakonsult AB
+
+ This file is part of GPGME++.
+
+ GPGME++ is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Library General Public
+ License as published by the Free Software Foundation; either
+ version 2 of the License, or (at your option) any later version.
+
+ GPGME++ is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU Library General Public License for more details.
+
+ You should have received a copy of the GNU Library General Public License
+ along with GPGME++; see the file COPYING.LIB. If not, write to the
+ Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+ Boston, MA 02110-1301, USA.
+*/
+
+// -*- c++ -*-
+#ifndef __GPGMEPP_EXCEPTION_H__
+#define __GPGMEPP_EXCEPTION_H__
+
+#include "error.h"
+
+#include <stdexcept>
+#include <string>
+
+namespace GpgME
+{
+
+class GPGMEPP_EXPORT Exception : public std::runtime_error
+{
+public:
+ enum Options {
+ NoOptions = 0x0,
+ MessageOnly = 0x1,
+
+ AllOptions = MessageOnly
+ };
+
+ explicit Exception(const GpgME::Error &err, const std::string &msg = std::string(), Options opt = NoOptions)
+ : std::runtime_error(make_message(err, msg, opt)), m_error(err), m_message(msg) {}
+
+ ~Exception() throw();
+
+ Error error() const
+ {
+ return m_error;
+ }
+ const std::string &message() const
+ {
+ return m_message;
+ }
+private:
+ static std::string make_message(const GpgME::Error &err, const std::string &msg);
+ static std::string make_message(const GpgME::Error &err, const std::string &msg, Options opt);
+private:
+ const GpgME::Error m_error;
+ const std::string m_message;
+};
+
+} // namespace GpgME
+
+#endif /* __GPGMEPP_EXCEPTION_H__ */
diff --git a/lang/cpp/src/global.h b/lang/cpp/src/global.h
new file mode 100644
index 0000000..15cc027
--- /dev/null
+++ b/lang/cpp/src/global.h
@@ -0,0 +1,218 @@
+/*
+ global.h - global gpgme functions and enums
+ Copyright (C) 2003, 2007 Klarälvdalens Datakonsult AB
+
+ This file is part of GPGME++.
+
+ GPGME++ is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Library General Public
+ License as published by the Free Software Foundation; either
+ version 2 of the License, or (at your option) any later version.
+
+ GPGME++ is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU Library General Public License for more details.
+
+ You should have received a copy of the GNU Library General Public License
+ along with GPGME++; see the file COPYING.LIB. If not, write to the
+ Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+ Boston, MA 02110-1301, USA.
+*/
+
+// -*- c++ -*-
+#ifndef __GPGMEPP_GLOBAL_H__
+#define __GPGMEPP_GLOBAL_H__
+
+#include "gpgmefw.h"
+#include "gpgmepp_export.h"
+
+#include <iosfwd>
+#include <cstring>
+
+namespace GpgME
+{
+class Error;
+class EngineInfo;
+class Context;
+}
+
+struct _GIOChannel;
+typedef struct _GIOChannel GIOChannel;
+class QIODevice;
+
+namespace GpgME
+{
+
+GPGMEPP_EXPORT void initializeLibrary();
+/*!
+ Initializes the library, returns Error::code() ==
+ GPG_ERR_USER_1 if underlying gpgme is too old.
+*/
+GPGMEPP_EXPORT Error initializeLibrary(int);
+
+enum Protocol { OpenPGP, CMS, UnknownProtocol };
+
+enum Engine { GpgEngine, GpgSMEngine, GpgConfEngine, UnknownEngine, AssuanEngine, G13Engine, SpawnEngine };
+
+enum KeyListMode {
+ Local = 0x1,
+ Extern = 0x2,
+ Signatures = 0x4,
+ SignatureNotations = 0x8,
+ Validate = 0x10,
+ Ephemeral = 0x20,
+ WithTofu = 0x40
+};
+
+enum SignatureMode { NormalSignatureMode, Detached, Clearsigned };
+
+GPGMEPP_EXPORT std::ostream &operator<<(std::ostream &os, Protocol proto);
+GPGMEPP_EXPORT std::ostream &operator<<(std::ostream &os, Engine eng);
+GPGMEPP_EXPORT std::ostream &operator<<(std::ostream &os, KeyListMode mode);
+GPGMEPP_EXPORT std::ostream &operator<<(std::ostream &os, SignatureMode mode);
+
+GPGMEPP_EXPORT Error setDefaultLocale(int category, const char *value);
+
+GPGMEPP_EXPORT Context *wait(Error &e, bool hang = true);
+typedef void (*IdleFunction)(void);
+GPGMEPP_EXPORT IdleFunction registerIdleFunction(IdleFunction idleFunction);
+
+typedef void (*IOCallback)(void *data, int fd);
+
+GPGMEPP_EXPORT EngineInfo engineInfo(Protocol proto);
+GPGMEPP_EXPORT EngineInfo engineInfo(Engine engine);
+/** Wrapper around gpgme_get_dirinfo. What can be:
+homedir, sysconfdir, bindir, libexecdir, libdir,
+datadir, localedir, agent-socket, agent-ssh-socket,
+dirmngr-socket, uiserver-socket, gpgconf-name, gpg-name,
+gpgsm-name, g13-name
+
+This may be extended in the future.
+*/
+GPGMEPP_EXPORT const char *dirInfo(const char *what);
+
+GPGMEPP_EXPORT Error checkEngine(Protocol proto);
+GPGMEPP_EXPORT Error checkEngine(Engine engine);
+
+GPGMEPP_EXPORT GIOChannel *getGIOChannel(int fd);
+GPGMEPP_EXPORT QIODevice *getQIODevice(int fd);
+
+enum Feature {
+ ValidatingKeylistModeFeature = 0x00000001,
+ CancelOperationFeature = 0x00000002,
+ WrongKeyUsageFeature = 0x00000004,
+ DefaultCertificateInclusionFeature = 0x00000008,
+
+ GetSetEngineInfoFeature = 0x00000010,
+ EngineInfoHomeDirFeature = 0x00000020,
+ NoEncryptToEncryptionFlagFeature = 0x00000040,
+ EphemeralKeylistModeFeature = 0x00000080,
+
+ SetDataFileNameFeeature = 0x00000100,
+ VerificationResultFileNameFeature = 0x00000200,
+ DecryptionResultFileNameFeature = 0x00000400,
+ DecryptionResultRecipientsFeature = 0x00000800,
+
+ AuditLogFeature = 0x00001000,
+ GpgConfEngineFeature = 0x00002000,
+ CancelOperationAsyncFeature = 0x00004000,
+ AssuanEngineFeature = 0x00008000,
+
+ ClearAddGetSignatureNotationsFeature = 0x00010000,
+ SignatureNotationsKeylistModeFeature = 0x00020000,
+ KeySignatureNotationsFeature = 0x00040000,
+ SignatureNotationsFlagsFeature = 0x00080000,
+ SignatureNotationsCriticalFlagFeature = 0x00100000,
+ SignatureNotationsHumanReadableFlagFeature = 0x00200000,
+ CardKeyFeature = 0x00400000,
+ ImportFromKeyserverFeature = 0x00800000,
+
+ KeyIsQualifiedFeature = 0x01000200,
+ SubkeyIsQualifiedFeature = 0x02000000,
+ SignaturePkaFieldsFeature = 0x04000000,
+ SignatureAlgorithmFieldsFeature = 0x08000000,
+
+ FdPointerFeature = 0x10000000,
+ G13VFSFeature = 0x20000000,
+ PasswdFeature = 0x40000000, // gpgme >= 1.3.0
+ // unusable (max value)
+
+ FeatureMaxValue = 0x80000000
+};
+enum Feature2 {
+ BinaryAndFineGrainedIdentify = 0x00000001, // gpgme >= 1.7.0
+ Feature2MaxValue = 0x80000000
+};
+
+// use hasFeature( unsigned long, unsigned long ) instead
+GPGMEPP_DEPRECATED_EXPORT bool hasFeature(unsigned long feature);
+GPGMEPP_EXPORT bool hasFeature(unsigned long feature, unsigned long feature2);
+
+} // namespace GpgME
+
+# ifndef GPGMEPP_MAKE_STD_SWAP_SPECIALIZATION
+# define GPGMEPP_MAKE_STD_SWAP_SPECIALIZATION( Class ) \
+ namespace std { template <> inline void swap< GpgME::Class >( GpgME::Class & lhs, GpgME::Class & rhs ) { lhs.swap( rhs ); } }
+# endif
+
+# ifndef GPGMEPP_MAKE_SAFE_BOOL_OPERATOR
+# define GPGMEPP_MAKE_SAFE_BOOL_OPERATOR( Cond ) \
+ private: \
+ struct __safe_bool_dummy__ { void nonnull() {} }; \
+ typedef void ( __safe_bool_dummy__::*unspecified_bool_type )(); \
+ public: \
+ operator unspecified_bool_type() const { return ( Cond ) ? &__safe_bool_dummy__::nonnull : 0 ; }
+# endif
+
+inline int _gpgmepp_strcmp(const char *s1, const char *s2)
+{
+ return s1 ? s2 ? std::strcmp(s1, s2) : 1 : s2 ? -1 : 0;
+}
+
+#define _GPGMEPP_MAKE_STRCMP( Name, expr, cmp ) \
+ template <template <typename U> class Op> \
+ struct Name { \
+ typedef bool result_type; \
+ \
+ bool operator()( const char * lhs, const char * rhs ) const { \
+ return Op<int>()( cmp, 0 ); \
+ } \
+ \
+ bool operator()( const std::string & lhs, const std::string & rhs ) const { \
+ return operator()( lhs.c_str(), rhs.c_str() ); \
+ } \
+ bool operator()( const char * lhs, const std::string & rhs ) const { \
+ return operator()( lhs, rhs.c_str() ); \
+ } \
+ bool operator()( const std::string & lhs, const char * rhs ) const { \
+ return operator()( lhs.c_str(), rhs ); \
+ } \
+ \
+ template <typename T> \
+ bool operator()( const T & lhs, const T & rhs ) const { \
+ return operator()( (lhs expr), (rhs expr) ); \
+ } \
+ template <typename T> \
+ bool operator()( const T & lhs, const char * rhs ) const { \
+ return operator()( (lhs expr), rhs ); \
+ } \
+ template <typename T> \
+ bool operator()( const char * lhs, const T & rhs ) const { \
+ return operator()( lhs, (rhs expr) ); \
+ } \
+ template <typename T> \
+ bool operator()( const T & lhs, const std::string & rhs ) const { \
+ return operator()( (lhs expr), rhs ); \
+ } \
+ template <typename T> \
+ bool operator()( const std::string & lhs, const T & rhs ) const { \
+ return operator()( lhs, (rhs expr) ); \
+ } \
+ }
+
+#define GPGMEPP_MAKE_STRCMP( Name, expr ) \
+ _GPGMEPP_MAKE_STRCMP( Name, expr, _gpgmepp_strcmp( lhs, rhs ) )
+
+
+#endif // __GPGMEPP_GLOBAL_H__
diff --git a/lang/cpp/src/gpgadduserideditinteractor.cpp b/lang/cpp/src/gpgadduserideditinteractor.cpp
new file mode 100644
index 0000000..43c8592
--- /dev/null
+++ b/lang/cpp/src/gpgadduserideditinteractor.cpp
@@ -0,0 +1,189 @@
+/*
+ gpgadduserideditinteractor.cpp - Edit Interactor to add a new UID to an OpenPGP key
+ Copyright (C) 2008 Klarälvdalens Datakonsult AB
+
+ This file is part of GPGME++.
+
+ GPGME++ is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Library General Public
+ License as published by the Free Software Foundation; either
+ version 2 of the License, or (at your option) any later version.
+
+ GPGME++ is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU Library General Public License for more details.
+
+ You should have received a copy of the GNU Library General Public License
+ along with GPGME++; see the file COPYING.LIB. If not, write to the
+ Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+ Boston, MA 02110-1301, USA.
+*/
+
+#include "gpgadduserideditinteractor.h"
+
+#include "error.h"
+
+#include <gpgme.h>
+
+#include <cstring>
+
+using std::strcmp;
+
+// avoid conflict (msvc)
+#ifdef ERROR
+# undef ERROR
+#endif
+
+using namespace GpgME;
+
+GpgAddUserIDEditInteractor::GpgAddUserIDEditInteractor()
+ : EditInteractor(),
+ m_name(),
+ m_email(),
+ m_comment()
+{
+
+}
+
+GpgAddUserIDEditInteractor::~GpgAddUserIDEditInteractor() {}
+
+void GpgAddUserIDEditInteractor::setNameUtf8(const std::string &name)
+{
+ m_name = name;
+}
+
+void GpgAddUserIDEditInteractor::setEmailUtf8(const std::string &email)
+{
+ m_email = email;
+}
+
+void GpgAddUserIDEditInteractor::setCommentUtf8(const std::string &comment)
+{
+ m_comment = comment;
+}
+
+// work around --enable-final
+namespace GpgAddUserIDEditInteractor_Private
+{
+enum {
+ START = EditInteractor::StartState,
+ COMMAND,
+ NAME,
+ EMAIL,
+ COMMENT,
+ QUIT,
+ SAVE,
+
+ ERROR = EditInteractor::ErrorState
+};
+}
+
+const char *GpgAddUserIDEditInteractor::action(Error &err) const
+{
+
+ using namespace GpgAddUserIDEditInteractor_Private;
+
+ switch (state()) {
+ case COMMAND:
+ return "adduid";
+ case NAME:
+ return m_name.c_str();
+ case EMAIL:
+ return m_email.c_str();
+ case COMMENT:
+ return m_comment.c_str();
+ case QUIT:
+ return "quit";
+ case SAVE:
+ return "Y";
+ case START:
+ case ERROR:
+ return 0;
+ default:
+ err = Error::fromCode(GPG_ERR_GENERAL);
+ return 0;
+ }
+}
+
+unsigned int GpgAddUserIDEditInteractor::nextState(unsigned int status, const char *args, Error &err) const
+{
+
+ static const Error GENERAL_ERROR = Error::fromCode(GPG_ERR_GENERAL);
+ static const Error INV_NAME_ERROR = Error::fromCode(GPG_ERR_INV_NAME);
+ static const Error INV_EMAIL_ERROR = Error::fromCode(GPG_ERR_INV_USER_ID);
+ static const Error INV_COMMENT_ERROR = Error::fromCode(GPG_ERR_INV_USER_ID);
+
+ if (needsNoResponse(status)) {
+ return state();
+ }
+
+ using namespace GpgAddUserIDEditInteractor_Private;
+
+ switch (state()) {
+ case START:
+ if (status == GPGME_STATUS_GET_LINE &&
+ strcmp(args, "keyedit.prompt") == 0) {
+ return COMMAND;
+ }
+ err = GENERAL_ERROR;
+ return ERROR;
+ case COMMAND:
+ if (status == GPGME_STATUS_GET_LINE &&
+ strcmp(args, "keygen.name") == 0) {
+ return NAME;
+ }
+ err = GENERAL_ERROR;
+ return ERROR;
+ case NAME:
+ if (status == GPGME_STATUS_GET_LINE &&
+ strcmp(args, "keygen.email") == 0) {
+ return EMAIL;
+ }
+ err = GENERAL_ERROR;
+ if (status == GPGME_STATUS_GET_LINE &&
+ strcmp(args, "keygen.name") == 0) {
+ err = INV_NAME_ERROR;
+ }
+ return ERROR;
+ case EMAIL:
+ if (status == GPGME_STATUS_GET_LINE &&
+ strcmp(args, "keygen.comment") == 0) {
+ return COMMENT;
+ }
+ err = GENERAL_ERROR;
+ if (status == GPGME_STATUS_GET_LINE &&
+ strcmp(args, "keygen.email") == 0) {
+ err = INV_EMAIL_ERROR;
+ }
+ return ERROR;
+ case COMMENT:
+ if (status == GPGME_STATUS_GET_LINE &&
+ strcmp(args, "keyedit.prompt") == 0) {
+ return QUIT;
+ }
+ err = GENERAL_ERROR;
+ if (status == GPGME_STATUS_GET_LINE &&
+ strcmp(args, "keygen.comment") == 0) {
+ err = INV_COMMENT_ERROR;
+ }
+ return ERROR;
+ case QUIT:
+ if (status == GPGME_STATUS_GET_BOOL &&
+ strcmp(args, "keyedit.save.okay") == 0) {
+ return SAVE;
+ }
+ err = GENERAL_ERROR;
+ return ERROR;
+ case ERROR:
+ if (status == GPGME_STATUS_GET_LINE &&
+ strcmp(args, "keyedit.prompt") == 0) {
+ return QUIT;
+ }
+ err = lastError();
+ return ERROR;
+ default:
+ err = GENERAL_ERROR;
+ return ERROR;
+ }
+}
diff --git a/lang/cpp/src/gpgadduserideditinteractor.h b/lang/cpp/src/gpgadduserideditinteractor.h
new file mode 100644
index 0000000..12b6e46
--- /dev/null
+++ b/lang/cpp/src/gpgadduserideditinteractor.h
@@ -0,0 +1,67 @@
+/*
+ gpgadduserideditinteractor.h - Edit Interactor to add a new UID to an OpenPGP key
+ Copyright (C) 2008 Klarälvdalens Datakonsult AB
+
+ This file is part of GPGME++.
+
+ GPGME++ is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Library General Public
+ License as published by the Free Software Foundation; either
+ version 2 of the License, or (at your option) any later version.
+
+ GPGME++ is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU Library General Public License for more details.
+
+ You should have received a copy of the GNU Library General Public License
+ along with GPGME++; see the file COPYING.LIB. If not, write to the
+ Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+ Boston, MA 02110-1301, USA.
+*/
+
+#ifndef __GPGMEPP_GPGADDUSERIDEDITINTERACTOR_H__
+#define __GPGMEPP_GPGADDUSERIDEDITINTERACTOR_H__
+
+#include <editinteractor.h>
+
+#include <string>
+
+namespace GpgME
+{
+
+class GPGMEPP_EXPORT GpgAddUserIDEditInteractor : public EditInteractor
+{
+public:
+ explicit GpgAddUserIDEditInteractor();
+ ~GpgAddUserIDEditInteractor();
+
+ void setNameUtf8(const std::string &name);
+ const std::string &nameUtf8() const
+ {
+ return m_name;
+ }
+
+ void setEmailUtf8(const std::string &email);
+ const std::string &emailUtf8() const
+ {
+ return m_email;
+ }
+
+ void setCommentUtf8(const std::string &comment);
+ const std::string &commentUtf8() const
+ {
+ return m_comment;
+ }
+
+private:
+ /* reimp */ const char *action(Error &err) const;
+ /* reimp */ unsigned int nextState(unsigned int statusCode, const char *args, Error &err) const;
+
+private:
+ std::string m_name, m_email, m_comment;
+};
+
+} // namespace GpgME
+
+#endif // __GPGMEPP_GPGADDUSERIDEDITINTERACTOR_H__
diff --git a/lang/cpp/src/gpgagentgetinfoassuantransaction.cpp b/lang/cpp/src/gpgagentgetinfoassuantransaction.cpp
new file mode 100644
index 0000000..4739aa2
--- /dev/null
+++ b/lang/cpp/src/gpgagentgetinfoassuantransaction.cpp
@@ -0,0 +1,119 @@
+/*
+ gpgagentgetinfoassuantransaction.cpp - Assuan Transaction to get information from gpg-agent
+ Copyright (C) 2009 Klarälvdalens Datakonsult AB
+
+ This file is part of GPGME++.
+
+ GPGME++ is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Library General Public
+ License as published by the Free Software Foundation; either
+ version 2 of the License, or (at your option) any later version.
+
+ GPGME++ is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU Library General Public License for more details.
+
+ You should have received a copy of the GNU Library General Public License
+ along with GPGME++; see the file COPYING.LIB. If not, write to the
+ Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+ Boston, MA 02110-1301, USA.
+*/
+
+#include "gpgagentgetinfoassuantransaction.h"
+#include "error.h"
+#include "data.h"
+#include "util.h"
+
+#include <assert.h>
+
+#include <sstream>
+
+using namespace GpgME;
+
+GpgAgentGetInfoAssuanTransaction::GpgAgentGetInfoAssuanTransaction(InfoItem item)
+ : AssuanTransaction(),
+ m_item(item),
+ m_command(),
+ m_data()
+{
+
+}
+
+GpgAgentGetInfoAssuanTransaction::~GpgAgentGetInfoAssuanTransaction() {}
+
+std::string GpgAgentGetInfoAssuanTransaction::version() const
+{
+ if (m_item == Version) {
+ return m_data;
+ } else {
+ return std::string();
+ }
+}
+
+unsigned int GpgAgentGetInfoAssuanTransaction::pid() const
+{
+ if (m_item == Pid) {
+ return to_pid(m_data);
+ } else {
+ return 0U;
+ }
+}
+
+std::string GpgAgentGetInfoAssuanTransaction::socketName() const
+{
+ if (m_item == SocketName) {
+ return m_data;
+ } else {
+ return std::string();
+ }
+}
+
+std::string GpgAgentGetInfoAssuanTransaction::sshSocketName() const
+{
+ if (m_item == SshSocketName) {
+ return m_data;
+ } else {
+ return std::string();
+ }
+}
+
+static const char *const gpgagent_getinfo_tokens[] = {
+ "version",
+ "pid",
+ "socket_name",
+ "ssh_socket_name",
+ "scd_running",
+};
+
+void GpgAgentGetInfoAssuanTransaction::makeCommand() const
+{
+ assert(m_item >= 0);
+ assert(m_item < LastInfoItem);
+ m_command = "GETINFO ";
+ m_command += gpgagent_getinfo_tokens[m_item];
+}
+
+const char *GpgAgentGetInfoAssuanTransaction::command() const
+{
+ makeCommand();
+ return m_command.c_str();
+}
+
+Error GpgAgentGetInfoAssuanTransaction::data(const char *data, size_t len)
+{
+ m_data.append(data, len);
+ return Error();
+}
+
+Data GpgAgentGetInfoAssuanTransaction::inquire(const char *name, const char *args, Error &err)
+{
+ (void)name; (void)args; (void)err;
+ return Data::null;
+}
+
+Error GpgAgentGetInfoAssuanTransaction::status(const char *status, const char *args)
+{
+ (void)status; (void)args;
+ return Error();
+}
diff --git a/lang/cpp/src/gpgagentgetinfoassuantransaction.h b/lang/cpp/src/gpgagentgetinfoassuantransaction.h
new file mode 100644
index 0000000..9e3e958
--- /dev/null
+++ b/lang/cpp/src/gpgagentgetinfoassuantransaction.h
@@ -0,0 +1,73 @@
+/*
+ gpgagentgetinfoassuantransaction.h - Assuan Transaction to get information from gpg-agent
+ Copyright (C) 2009 Klarälvdalens Datakonsult AB
+
+ This file is part of GPGME++.
+
+ GPGME++ is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Library General Public
+ License as published by the Free Software Foundation; either
+ version 2 of the License, or (at your option) any later version.
+
+ GPGME++ is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU Library General Public License for more details.
+
+ You should have received a copy of the GNU Library General Public License
+ along with GPGME++; see the file COPYING.LIB. If not, write to the
+ Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+ Boston, MA 02110-1301, USA.
+*/
+
+#ifndef __GPGMEPP_GPGAGENTGETINFOASSUANTRANSACTION_H__
+#define __GPGMEPP_GPGAGENTGETINFOASSUANTRANSACTION_H__
+
+#include <interfaces/assuantransaction.h>
+
+#include <string>
+#include <vector>
+
+namespace GpgME
+{
+
+class GPGMEPP_EXPORT GpgAgentGetInfoAssuanTransaction : public AssuanTransaction
+{
+public:
+ enum InfoItem {
+ Version, // string
+ Pid, // unsigned long
+ SocketName, // string (path)
+ SshSocketName, // string (path)
+ ScdRunning, // (none, returns GPG_ERR_GENERAL when scdaemon isn't running)
+ //CommandHasOption, // not supported
+
+ LastInfoItem
+ };
+
+ explicit GpgAgentGetInfoAssuanTransaction(InfoItem item);
+ ~GpgAgentGetInfoAssuanTransaction();
+
+ std::string version() const;
+ unsigned int pid() const;
+ std::string socketName() const;
+ std::string sshSocketName() const;
+
+private:
+ /* reimp */ const char *command() const;
+ /* reimp */ Error data(const char *data, size_t datalen);
+ /* reimp */ Data inquire(const char *name, const char *args, Error &err);
+ /* reimp */ Error status(const char *status, const char *args);
+
+private:
+ void makeCommand() const;
+
+private:
+ InfoItem m_item;
+ mutable std::string m_command;
+ std::string m_data;
+};
+
+} // namespace GpgME
+
+#endif // __GPGMEPP_GPGAGENTGETINFOASSUANTRANSACTION_H__
diff --git a/lang/cpp/src/gpgmefw.h b/lang/cpp/src/gpgmefw.h
new file mode 100644
index 0000000..cbdd444
--- /dev/null
+++ b/lang/cpp/src/gpgmefw.h
@@ -0,0 +1,70 @@
+/*
+ gpgmefw.h - Forwards declarations for gpgme (0.3 and 0.4)
+ Copyright (C) 2004 Klarälvdalens Datakonsult AB
+
+ This file is part of GPGME++.
+
+ GPGME++ is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Library General Public
+ License as published by the Free Software Foundation; either
+ version 2 of the License, or (at your option) any later version.
+
+ GPGME++ is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU Library General Public License for more details.
+
+ You should have received a copy of the GNU Library General Public License
+ along with GPGME++; see the file COPYING.LIB. If not, write to the
+ Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+ Boston, MA 02110-1301, USA.
+*/
+
+#ifndef __GPGMEPP_GPGMEFW_H__
+#define __GPGMEPP_GPGMEFW_H__
+
+struct gpgme_context;
+typedef gpgme_context *gpgme_ctx_t;
+
+struct gpgme_data;
+typedef gpgme_data *gpgme_data_t;
+
+struct gpgme_io_cbs;
+
+struct _gpgme_key;
+typedef struct _gpgme_key *gpgme_key_t;
+
+struct _gpgme_trust_item;
+typedef struct _gpgme_trust_item *gpgme_trust_item_t;
+
+struct _gpgme_subkey;
+typedef struct _gpgme_subkey *gpgme_sub_key_t;
+
+struct _gpgme_user_id;
+typedef struct _gpgme_user_id *gpgme_user_id_t;
+
+struct _gpgme_key_sig;
+typedef struct _gpgme_key_sig *gpgme_key_sig_t;
+
+struct _gpgme_sig_notation;
+typedef struct _gpgme_sig_notation *gpgme_sig_notation_t;
+
+struct _gpgme_engine_info;
+typedef struct _gpgme_engine_info *gpgme_engine_info_t;
+
+struct _gpgme_op_keylist_result;
+typedef struct _gpgme_op_keylist_result *gpgme_keylist_result_t;
+
+struct _gpgme_recipient;
+typedef struct _gpgme_recipient *gpgme_recipient_t;
+
+struct gpgme_conf_opt;
+typedef struct gpgme_conf_opt *gpgme_conf_opt_t;
+
+struct gpgme_conf_comp;
+typedef struct gpgme_conf_comp *gpgme_conf_comp_t;
+
+struct gpgme_conf_arg;
+typedef struct gpgme_conf_arg *gpgme_conf_arg_t;
+
+#endif // __GPGMEPP_GPGMEFW_H__
diff --git a/lang/cpp/src/gpgmepp_export.h b/lang/cpp/src/gpgmepp_export.h
new file mode 100644
index 0000000..d660310
--- /dev/null
+++ b/lang/cpp/src/gpgmepp_export.h
@@ -0,0 +1,73 @@
+/*gpgmepp_export.h - Export macros for gpgmepp
+ Copyright (C) 2016, Intevation GmbH
+
+ This file is part of GPGME++.
+
+ GPGME++ is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Library General Public
+ License as published by the Free Software Foundation; either
+ version 2 of the License, or (at your option) any later version.
+
+ GPGME++ is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU Library General Public License for more details.
+
+ You should have received a copy of the GNU Library General Public License
+ along with GPGME++; see the file COPYING.LIB. If not, write to the
+ Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+ Boston, MA 02110-1301, USA.
+*/
+
+#ifndef GPGMEPP_EXPORT_H
+#define GPGMEPP_EXPORT_H
+
+#ifdef GPGMEPP_STATIC_DEFINE
+# define GPGMEPP_EXPORT
+# define GPGMEPP_NO_EXPORT
+#else
+# ifndef GPGMEPP_EXPORT
+# ifdef BUILDING_GPGMEPP
+ /* We are building this library */
+# ifdef WIN32
+# define GPGMEPP_EXPORT __declspec(dllexport)
+# else
+# define GPGMEPP_EXPORT __attribute__((visibility("default")))
+# endif
+# else
+ /* We are using this library */
+# ifdef WIN32
+# define GPGMEPP_EXPORT __declspec(dllimport)
+# else
+# define GPGMEPP_EXPORT __attribute__((visibility("default")))
+# endif
+# endif
+# endif
+
+# ifndef GPGMEPP_NO_EXPORT
+# ifdef WIN32
+# define GPGMEPP_NO_EXPORT
+# else
+# define GPGMEPP_NO_EXPORT __attribute__((visibility("hidden")))
+# endif
+# endif
+#endif
+
+#ifndef GPGMEPP_DEPRECATED
+# define GPGMEPP_DEPRECATED __attribute__ ((__deprecated__))
+#endif
+
+#ifndef GPGMEPP_DEPRECATED_EXPORT
+# define GPGMEPP_DEPRECATED_EXPORT GPGMEPP_EXPORT GPGMEPP_DEPRECATED
+#endif
+
+#ifndef GPGMEPP_DEPRECATED_NO_EXPORT
+# define GPGMEPP_DEPRECATED_NO_EXPORT GPGMEPP_NO_EXPORT GPGMEPP_DEPRECATED
+#endif
+
+#define DEFINE_NO_DEPRECATED 0
+#if DEFINE_NO_DEPRECATED
+# define GPGMEPP_NO_DEPRECATED
+#endif
+
+#endif
diff --git a/lang/cpp/src/gpgmepp_version.h.in b/lang/cpp/src/gpgmepp_version.h.in
new file mode 100644
index 0000000..3c33a30
--- /dev/null
+++ b/lang/cpp/src/gpgmepp_version.h.in
@@ -0,0 +1,32 @@
+/*gpgmepp_version.h - Version macros for gpgmepp
+ Copyright (C) 2016, Intevation GmbH
+
+ This file is part of GPGME++.
+
+ GPGME++ is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Library General Public
+ License as published by the Free Software Foundation; either
+ version 2 of the License, or (at your option) any later version.
+
+ GPGME++ is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU Library General Public License for more details.
+
+ You should have received a copy of the GNU Library General Public License
+ along with GPGME++; see the file COPYING.LIB. If not, write to the
+ Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+ Boston, MA 02110-1301, USA.
+*/
+
+
+#ifndef GPGMEPP_VERSION_H
+#define GPGMEPP_VERSION_H
+
+#define GPGMEPP_VERSION_STRING "@LIBGPGMEPP_LT_CURRENT@.@LIBGPGMEPP_LT_AGE@.@LIBGPGMEPP_LT_REVISION@"
+#define GPGMEPP_VERSION_MAJOR @LIBGPGMEPP_LT_CURRENT@
+#define GPGMEPP_VERSION_MINOR @LIBGPGMEPP_LT_AGE@
+#define GPGMEPP_VERSION_PATCH @LIBGPGMEPP_LT_REVISION@
+#define GPGMEPP_VERSION ((@LIBGPGMEPP_LT_CURRENT@<<16)|(@LIBGPGMEPP_LT_AGE@<<8)|(@LIBGPGMEPP_LT_REVISION@))
+
+#endif
diff --git a/lang/cpp/src/gpgsetexpirytimeeditinteractor.cpp b/lang/cpp/src/gpgsetexpirytimeeditinteractor.cpp
new file mode 100644
index 0000000..8af897c
--- /dev/null
+++ b/lang/cpp/src/gpgsetexpirytimeeditinteractor.cpp
@@ -0,0 +1,141 @@
+/*
+ gpgsetexpirytimeeditinteractor.cpp - Edit Interactor to change the expiry time of an OpenPGP key
+ Copyright (C) 2007 Klarälvdalens Datakonsult AB
+
+ This file is part of GPGME++.
+
+ GPGME++ is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Library General Public
+ License as published by the Free Software Foundation; either
+ version 2 of the License, or (at your option) any later version.
+
+ GPGME++ is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU Library General Public License for more details.
+
+ You should have received a copy of the GNU Library General Public License
+ along with GPGME++; see the file COPYING.LIB. If not, write to the
+ Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+ Boston, MA 02110-1301, USA.
+*/
+
+#include "gpgsetexpirytimeeditinteractor.h"
+#include "error.h"
+
+#include <gpgme.h>
+
+#include <cstring>
+
+using std::strcmp;
+
+// avoid conflict (msvc)
+#ifdef ERROR
+# undef ERROR
+#endif
+
+using namespace GpgME;
+
+GpgSetExpiryTimeEditInteractor::GpgSetExpiryTimeEditInteractor(const std::string &t)
+ : EditInteractor(),
+ m_strtime(t)
+{
+
+}
+
+GpgSetExpiryTimeEditInteractor::~GpgSetExpiryTimeEditInteractor() {}
+
+// work around --enable-final
+namespace GpgSetExpiryTimeEditInteractor_Private
+{
+enum {
+ START = EditInteractor::StartState,
+ COMMAND,
+ DATE,
+ QUIT,
+ SAVE,
+
+ ERROR = EditInteractor::ErrorState
+};
+}
+
+const char *GpgSetExpiryTimeEditInteractor::action(Error &err) const
+{
+
+ using namespace GpgSetExpiryTimeEditInteractor_Private;
+
+ switch (state()) {
+ case COMMAND:
+ return "expire";
+ case DATE:
+ return m_strtime.c_str();
+ case QUIT:
+ return "quit";
+ case SAVE:
+ return "Y";
+ case START:
+ case ERROR:
+ return 0;
+ default:
+ err = Error::fromCode(GPG_ERR_GENERAL);
+ return 0;
+ }
+}
+
+unsigned int GpgSetExpiryTimeEditInteractor::nextState(unsigned int status, const char *args, Error &err) const
+{
+
+ static const Error GENERAL_ERROR = Error::fromCode(GPG_ERR_GENERAL);
+ static const Error INV_TIME_ERROR = Error::fromCode(GPG_ERR_INV_TIME);
+
+ if (needsNoResponse(status)) {
+ return state();
+ }
+
+ using namespace GpgSetExpiryTimeEditInteractor_Private;
+
+ switch (state()) {
+ case START:
+ if (status == GPGME_STATUS_GET_LINE &&
+ strcmp(args, "keyedit.prompt") == 0) {
+ return COMMAND;
+ }
+ err = GENERAL_ERROR;
+ return ERROR;
+ case COMMAND:
+ if (status == GPGME_STATUS_GET_LINE &&
+ strcmp(args, "keygen.valid") == 0) {
+ return DATE;
+ }
+ err = GENERAL_ERROR;
+ return ERROR;
+ case DATE:
+ if (status == GPGME_STATUS_GET_LINE &&
+ strcmp(args, "keyedit.prompt") == 0) {
+ return QUIT;
+ } else if (status == GPGME_STATUS_GET_LINE &&
+ strcmp(args, "keygen.valid")) {
+ err = INV_TIME_ERROR;
+ return ERROR;
+ }
+ err = GENERAL_ERROR;
+ return ERROR;
+ case QUIT:
+ if (status == GPGME_STATUS_GET_BOOL &&
+ strcmp(args, "keyedit.save.okay") == 0) {
+ return SAVE;
+ }
+ err = GENERAL_ERROR;
+ return ERROR;
+ case ERROR:
+ if (status == GPGME_STATUS_GET_LINE &&
+ strcmp(args, "keyedit.prompt") == 0) {
+ return QUIT;
+ }
+ err = lastError();
+ return ERROR;
+ default:
+ err = GENERAL_ERROR;
+ return ERROR;
+ }
+}
diff --git a/lang/cpp/src/gpgsetexpirytimeeditinteractor.h b/lang/cpp/src/gpgsetexpirytimeeditinteractor.h
new file mode 100644
index 0000000..670b445
--- /dev/null
+++ b/lang/cpp/src/gpgsetexpirytimeeditinteractor.h
@@ -0,0 +1,49 @@
+/*
+ gpgsetexpirytimeeditinteractor.h - Edit Interactor to change the expiry time of an OpenPGP key
+ Copyright (C) 2007 Klarälvdalens Datakonsult AB
+
+ This file is part of GPGME++.
+
+ GPGME++ is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Library General Public
+ License as published by the Free Software Foundation; either
+ version 2 of the License, or (at your option) any later version.
+
+ GPGME++ is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU Library General Public License for more details.
+
+ You should have received a copy of the GNU Library General Public License
+ along with GPGME++; see the file COPYING.LIB. If not, write to the
+ Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+ Boston, MA 02110-1301, USA.
+*/
+
+#ifndef __GPGMEPP_GPGSETEXPIRYTIMEEDITINTERACTOR_H__
+#define __GPGMEPP_GPGSETEXPIRYTIMEEDITINTERACTOR_H__
+
+#include <editinteractor.h>
+
+#include <string>
+
+namespace GpgME
+{
+
+class GPGMEPP_EXPORT GpgSetExpiryTimeEditInteractor : public EditInteractor
+{
+public:
+ explicit GpgSetExpiryTimeEditInteractor(const std::string &timeString = "0");
+ ~GpgSetExpiryTimeEditInteractor();
+
+private:
+ /* reimp */ const char *action(Error &err) const;
+ /* reimp */ unsigned int nextState(unsigned int statusCode, const char *args, Error &err) const;
+
+private:
+ const std::string m_strtime;
+};
+
+} // namespace GpgME
+
+#endif // __GPGMEPP_GPGSETEXPIRYTIMEEDITINTERACTOR_H___
diff --git a/lang/cpp/src/gpgsetownertrusteditinteractor.cpp b/lang/cpp/src/gpgsetownertrusteditinteractor.cpp
new file mode 100644
index 0000000..15b1269
--- /dev/null
+++ b/lang/cpp/src/gpgsetownertrusteditinteractor.cpp
@@ -0,0 +1,151 @@
+/*
+ gpgsetownertrusteditinteractor.cpp - Edit Interactor to change the expiry time of an OpenPGP key
+ Copyright (C) 2007 Klarälvdalens Datakonsult AB
+
+ This file is part of GPGME++.
+
+ GPGME++ is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Library General Public
+ License as published by the Free Software Foundation; either
+ version 2 of the License, or (at your option) any later version.
+
+ GPGME++ is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU Library General Public License for more details.
+
+ You should have received a copy of the GNU Library General Public License
+ along with GPGME++; see the file COPYING.LIB. If not, write to the
+ Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+ Boston, MA 02110-1301, USA.
+*/
+
+#include "gpgsetownertrusteditinteractor.h"
+#include "error.h"
+
+#include <gpgme.h>
+
+#include <cstring>
+
+using std::strcmp;
+
+// avoid conflict (msvc)
+#ifdef ERROR
+# undef ERROR
+#endif
+
+using namespace GpgME;
+
+GpgSetOwnerTrustEditInteractor::GpgSetOwnerTrustEditInteractor(Key::OwnerTrust ot)
+ : EditInteractor(),
+ m_ownertrust(ot)
+{
+
+}
+
+GpgSetOwnerTrustEditInteractor::~GpgSetOwnerTrustEditInteractor() {}
+
+// work around --enable-final
+namespace GpgSetOwnerTrustEditInteractor_Private
+{
+enum {
+ START = EditInteractor::StartState,
+ COMMAND,
+ VALUE,
+ REALLY_ULTIMATE,
+ QUIT,
+ SAVE,
+
+ ERROR = EditInteractor::ErrorState
+};
+}
+
+const char *GpgSetOwnerTrustEditInteractor::action(Error &err) const
+{
+ static const char truststrings[][2] = { "1", "1", "2", "3", "4", "5" };
+
+ using namespace GpgSetOwnerTrustEditInteractor_Private;
+
+ switch (state()) {
+ case COMMAND:
+ return "trust";
+ case VALUE:
+ return truststrings[m_ownertrust];
+ case REALLY_ULTIMATE:
+ return "Y";
+ case QUIT:
+ return "quit";
+ case SAVE:
+ return "Y";
+ case START:
+ case ERROR:
+ return 0;
+ default:
+ err = Error::fromCode(GPG_ERR_GENERAL);
+ return 0;
+ }
+}
+
+unsigned int GpgSetOwnerTrustEditInteractor::nextState(unsigned int status, const char *args, Error &err) const
+{
+
+ static const Error GENERAL_ERROR = Error::fromCode(GPG_ERR_GENERAL);
+ //static const Error INV_TIME_ERROR = Error::fromCode( GPG_ERR_INV_TIME );
+
+ if (needsNoResponse(status)) {
+ return state();
+ }
+
+ using namespace GpgSetOwnerTrustEditInteractor_Private;
+
+ switch (state()) {
+ case START:
+ if (status == GPGME_STATUS_GET_LINE &&
+ strcmp(args, "keyedit.prompt") == 0) {
+ return COMMAND;
+ }
+ err = GENERAL_ERROR;
+ return ERROR;
+ case COMMAND:
+ if (status == GPGME_STATUS_GET_LINE &&
+ strcmp(args, "edit_ownertrust.value") == 0) {
+ return VALUE;
+ }
+ err = GENERAL_ERROR;
+ return ERROR;
+ case VALUE:
+ if (status == GPGME_STATUS_GET_LINE &&
+ strcmp(args, "keyedit.prompt") == 0) {
+ return QUIT;
+ } else if (status == GPGME_STATUS_GET_BOOL &&
+ strcmp(args, "edit_ownertrust.set_ultimate.okay") == 0) {
+ return REALLY_ULTIMATE;
+ }
+ err = GENERAL_ERROR;
+ return ERROR;
+ case REALLY_ULTIMATE:
+ if (status == GPGME_STATUS_GET_LINE &&
+ strcmp(args, "keyedit.prompt") == 0) {
+ return QUIT;
+ }
+ err = GENERAL_ERROR;
+ return ERROR;
+ case QUIT:
+ if (status == GPGME_STATUS_GET_BOOL &&
+ strcmp(args, "keyedit.save.okay") == 0) {
+ return SAVE;
+ }
+ err = GENERAL_ERROR;
+ return ERROR;
+ case ERROR:
+ if (status == GPGME_STATUS_GET_LINE &&
+ strcmp(args, "keyedit.prompt") == 0) {
+ return QUIT;
+ }
+ err = lastError();
+ return ERROR;
+ default:
+ err = GENERAL_ERROR;
+ return ERROR;
+ };
+}
diff --git a/lang/cpp/src/gpgsetownertrusteditinteractor.h b/lang/cpp/src/gpgsetownertrusteditinteractor.h
new file mode 100644
index 0000000..caf29ee
--- /dev/null
+++ b/lang/cpp/src/gpgsetownertrusteditinteractor.h
@@ -0,0 +1,50 @@
+/*
+ gpgsetownertrusteditinteractor.h - Edit Interactor to change the owner trust of an OpenPGP key
+ Copyright (C) 2007 Klarälvdalens Datakonsult AB
+
+ This file is part of GPGME++.
+
+ GPGME++ is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Library General Public
+ License as published by the Free Software Foundation; either
+ version 2 of the License, or (at your option) any later version.
+
+ GPGME++ is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU Library General Public License for more details.
+
+ You should have received a copy of the GNU Library General Public License
+ along with GPGME++; see the file COPYING.LIB. If not, write to the
+ Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+ Boston, MA 02110-1301, USA.
+*/
+
+#ifndef __GPGMEPP_GPGSETOWNERTRUSTEDITINTERACTOR_H__
+#define __GPGMEPP_GPGSETOWNERTRUSTEDITINTERACTOR_H__
+
+#include <editinteractor.h>
+#include <key.h>
+
+#include <string>
+
+namespace GpgME
+{
+
+class GPGMEPP_EXPORT GpgSetOwnerTrustEditInteractor : public EditInteractor
+{
+public:
+ explicit GpgSetOwnerTrustEditInteractor(Key::OwnerTrust ownertrust);
+ ~GpgSetOwnerTrustEditInteractor();
+
+private:
+ /* reimp */ const char *action(Error &err) const;
+ /* reimp */ unsigned int nextState(unsigned int statusCode, const char *args, Error &err) const;
+
+private:
+ const Key::OwnerTrust m_ownertrust;
+};
+
+} // namespace GpgME
+
+#endif // __GPGMEPP_GPGSETOWNERTRUSTEDITINTERACTOR_H__
diff --git a/lang/cpp/src/gpgsignkeyeditinteractor.cpp b/lang/cpp/src/gpgsignkeyeditinteractor.cpp
new file mode 100644
index 0000000..fded90f
--- /dev/null
+++ b/lang/cpp/src/gpgsignkeyeditinteractor.cpp
@@ -0,0 +1,318 @@
+/*
+ gpgsignkeyeditinteractor.cpp - Edit Interactor to change the expiry time of an OpenPGP key
+ Copyright (C) 2007 Klarälvdalens Datakonsult AB
+
+ This file is part of GPGME++.
+
+ GPGME++ is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Library General Public
+ License as published by the Free Software Foundation; either
+ version 2 of the License, or (at your option) any later version.
+
+ GPGME++ is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU Library General Public License for more details.
+
+ You should have received a copy of the GNU Library General Public License
+ along with GPGME++; see the file COPYING.LIB. If not, write to the
+ Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+ Boston, MA 02110-1301, USA.
+*/
+
+#include "gpgsignkeyeditinteractor.h"
+#include "error.h"
+#include "key.h"
+
+#include <gpgme.h>
+
+#include <map>
+#include <string>
+#include <sstream>
+
+#include <cassert>
+#include <cstring>
+
+using std::strcmp;
+
+// avoid conflict (msvc)
+#ifdef ERROR
+# undef ERROR
+#endif
+
+#ifdef _MSC_VER
+#undef snprintf
+#define snprintf _snprintf
+#endif
+
+using namespace GpgME;
+
+class GpgSignKeyEditInteractor::Private
+{
+public:
+ Private();
+
+ std::string scratch;
+ bool started;
+ int options;
+ std::vector<unsigned int> userIDs;
+ std::vector<unsigned int>::const_iterator currentId, nextId;
+ unsigned int checkLevel;
+
+ const char *command() const
+ {
+ const bool local = (options & Exportable) == 0;
+ const bool nonRevoc = options & NonRevocable;
+ const bool trust = options & Trust;
+ //TODO: check if all combinations are valid
+ if (local && nonRevoc && trust) {
+ return "ltnrsign";
+ }
+ if (local && nonRevoc) {
+ return "lnrsign";
+ }
+ if (local && trust) {
+ return "ltsign";
+ }
+ if (local) {
+ return "lsign";
+ }
+ if (nonRevoc && trust) {
+ return "tnrsign";
+ }
+ if (nonRevoc) {
+ return "nrsign";
+ }
+ if (trust) {
+ return "tsign";
+ }
+ return "sign";
+ }
+
+ bool signAll() const
+ {
+ return userIDs.empty();
+ }
+ unsigned int nextUserID()
+ {
+ assert(nextId != userIDs.end());
+ currentId = nextId++;
+ return currentUserID();
+ }
+
+ bool allUserIDsListed() const
+ {
+ return nextId == userIDs.end();
+ }
+
+ unsigned int currentUserID() const
+ {
+ assert(currentId != userIDs.end());
+ return *currentId + 1;
+ }
+
+};
+
+GpgSignKeyEditInteractor::Private::Private()
+ :
+ started(false),
+ options(0),
+ userIDs(),
+ currentId(),
+ nextId(),
+ checkLevel(0)
+{
+}
+
+GpgSignKeyEditInteractor::GpgSignKeyEditInteractor()
+ : EditInteractor(), d(new Private)
+{
+
+}
+
+GpgSignKeyEditInteractor::~GpgSignKeyEditInteractor()
+{
+ delete d;
+}
+
+// work around --enable-final
+namespace GpgSignKeyEditInteractor_Private
+{
+enum SignKeyState {
+ START = EditInteractor::StartState,
+ COMMAND,
+ UIDS_ANSWER_SIGN_ALL,
+ UIDS_LIST_SEPARATELY,
+ // all these free slots belong to UIDS_LIST_SEPARATELY, too
+ // (we increase state() by one for each UID, so that action() is called)
+ UIDS_LIST_SEPARATELY_DONE = 1000000,
+ SET_EXPIRE,
+ SET_CHECK_LEVEL,
+ SET_TRUST_VALUE,
+ SET_TRUST_DEPTH,
+ SET_TRUST_REGEXP,
+ CONFIRM,
+ QUIT,
+ SAVE,
+ ERROR = EditInteractor::ErrorState
+};
+
+typedef std::map<std::tuple<SignKeyState, unsigned int, std::string>, SignKeyState> TransitionMap;
+
+}
+
+static const char *answer(bool b)
+{
+ return b ? "Y" : "N";
+}
+
+static GpgSignKeyEditInteractor_Private::TransitionMap makeTable()
+{
+ using namespace GpgSignKeyEditInteractor_Private;
+ TransitionMap tab;
+ const unsigned int GET_BOOL = GPGME_STATUS_GET_BOOL;
+ const unsigned int GET_LINE = GPGME_STATUS_GET_LINE;
+#define addEntry( s1, status, str, s2 ) tab[std::make_tuple( s1, status, str)] = s2
+ addEntry(START, GET_LINE, "keyedit.prompt", COMMAND);
+ addEntry(COMMAND, GET_BOOL, "keyedit.sign_all.okay", UIDS_ANSWER_SIGN_ALL);
+ addEntry(COMMAND, GET_BOOL, "sign_uid.okay", CONFIRM);
+ addEntry(UIDS_ANSWER_SIGN_ALL, GET_BOOL, "sign_uid.okay", CONFIRM);
+ addEntry(UIDS_ANSWER_SIGN_ALL, GET_LINE, "sign_uid.expire", SET_EXPIRE);
+ addEntry(UIDS_ANSWER_SIGN_ALL, GET_LINE, "sign_uid.class", SET_CHECK_LEVEL);
+ addEntry(SET_TRUST_VALUE, GET_LINE, "trustsign_prompt.trust_depth", SET_TRUST_DEPTH);
+ addEntry(SET_TRUST_DEPTH, GET_LINE, "trustsign_prompt.trust_regexp", SET_TRUST_REGEXP);
+ addEntry(SET_TRUST_REGEXP, GET_LINE, "sign_uid.okay", CONFIRM);
+ addEntry(SET_CHECK_LEVEL, GET_BOOL, "sign_uid.okay", CONFIRM);
+ addEntry(SET_EXPIRE, GET_BOOL, "sign_uid.class", SET_CHECK_LEVEL);
+ addEntry(CONFIRM, GET_BOOL, "sign_uid.local_promote_okay", CONFIRM);
+ addEntry(CONFIRM, GET_BOOL, "sign_uid.okay", CONFIRM);
+ addEntry(CONFIRM, GET_LINE, "keyedit.prompt", COMMAND);
+ addEntry(CONFIRM, GET_LINE, "trustsign_prompt.trust_value", SET_TRUST_VALUE);
+ addEntry(CONFIRM, GET_LINE, "sign_uid.expire", SET_EXPIRE);
+ addEntry(CONFIRM, GET_LINE, "sign_uid.class", SET_CHECK_LEVEL);
+ addEntry(UIDS_LIST_SEPARATELY_DONE, GET_BOOL, "sign_uid.local_promote_okay", CONFIRM);
+ addEntry(UIDS_LIST_SEPARATELY_DONE, GET_LINE, "keyedit.prompt", COMMAND);
+ addEntry(UIDS_LIST_SEPARATELY_DONE, GET_LINE, "trustsign_prompt.trust_value", SET_TRUST_VALUE);
+ addEntry(UIDS_LIST_SEPARATELY_DONE, GET_LINE, "sign_uid.expire", SET_EXPIRE);
+ addEntry(UIDS_LIST_SEPARATELY_DONE, GET_LINE, "sign_uid.class", SET_CHECK_LEVEL);
+ addEntry(UIDS_LIST_SEPARATELY_DONE, GET_BOOL, "sign_uid.okay", CONFIRM);
+ addEntry(CONFIRM, GET_LINE, "keyedit.prompt", QUIT);
+ addEntry(ERROR, GET_LINE, "keyedit.prompt", QUIT);
+ addEntry(QUIT, GET_BOOL, "keyedit.save.okay", SAVE);
+#undef addEntry
+ return tab;
+}
+
+const char *GpgSignKeyEditInteractor::action(Error &err) const
+{
+ static const char check_level_strings[][2] = { "0", "1", "2", "3" };
+ using namespace GpgSignKeyEditInteractor_Private;
+ using namespace std;
+
+ switch (const unsigned int st = state()) {
+ case COMMAND:
+ return d->command();
+ case UIDS_ANSWER_SIGN_ALL:
+ return answer(d->signAll());
+ case UIDS_LIST_SEPARATELY_DONE:
+ return d->command();
+ case SET_EXPIRE:
+ return answer(true);
+ case SET_TRUST_VALUE:
+ // TODO
+ case SET_TRUST_DEPTH:
+ //TODO
+ case SET_TRUST_REGEXP:
+ //TODO
+ return 0;
+ case SET_CHECK_LEVEL:
+ return check_level_strings[d->checkLevel];
+ case CONFIRM:
+ return answer(true);
+ case QUIT:
+ return "quit";
+ case SAVE:
+ return answer(true);
+ default:
+ if (st >= UIDS_LIST_SEPARATELY && st < UIDS_LIST_SEPARATELY_DONE) {
+ std::stringstream ss;
+ ss << d->nextUserID();
+ d->scratch = ss.str();
+ return d->scratch.c_str();
+ }
+ // fall through
+ case ERROR:
+ err = Error::fromCode(GPG_ERR_GENERAL);
+ return 0;
+ }
+}
+
+unsigned int GpgSignKeyEditInteractor::nextState(unsigned int status, const char *args, Error &err) const
+{
+ d->started = true;
+ using namespace GpgSignKeyEditInteractor_Private;
+ static const Error GENERAL_ERROR = Error::fromCode(GPG_ERR_GENERAL);
+ //static const Error INV_TIME_ERROR = Error::fromCode( GPG_ERR_INV_TIME );
+ static const TransitionMap table(makeTable());
+ if (needsNoResponse(status)) {
+ return state();
+ }
+
+ using namespace GpgSignKeyEditInteractor_Private;
+
+ //lookup transition in map
+ const TransitionMap::const_iterator it = table.find(std::make_tuple(static_cast<SignKeyState>(state()), status, std::string(args)));
+ if (it != table.end()) {
+ return it->second;
+ }
+
+ //handle cases that cannot be handled via the map
+ switch (const unsigned int st = state()) {
+ case UIDS_ANSWER_SIGN_ALL:
+ if (status == GPGME_STATUS_GET_LINE &&
+ strcmp(args, "keyedit.prompt") == 0) {
+ if (!d->signAll()) {
+ return UIDS_LIST_SEPARATELY;
+ }
+ err = Error::fromCode(GPG_ERR_UNUSABLE_PUBKEY);
+ return ERROR;
+ }
+ break;
+ default:
+ if (st >= UIDS_LIST_SEPARATELY && st < UIDS_LIST_SEPARATELY_DONE) {
+ if (status == GPGME_STATUS_GET_LINE &&
+ strcmp(args, "keyedit.prompt") == 0) {
+ return d->allUserIDsListed() ? UIDS_LIST_SEPARATELY_DONE : st + 1 ;
+ }
+ }
+ break;
+ case CONFIRM:
+ case ERROR:
+ err = lastError();
+ return ERROR;
+ }
+
+ err = GENERAL_ERROR;
+ return ERROR;
+}
+
+void GpgSignKeyEditInteractor::setCheckLevel(unsigned int checkLevel)
+{
+ assert(!d->started);
+ assert(checkLevel <= 3);
+ d->checkLevel = checkLevel;
+}
+
+void GpgSignKeyEditInteractor::setUserIDsToSign(const std::vector<unsigned int> &userIDsToSign)
+{
+ assert(!d->started);
+ d->userIDs = userIDsToSign;
+ d->nextId = d->userIDs.begin();
+ d->currentId = d->userIDs.end();
+
+}
+void GpgSignKeyEditInteractor::setSigningOptions(int options)
+{
+ assert(!d->started);
+ d->options = options;
+}
diff --git a/lang/cpp/src/gpgsignkeyeditinteractor.h b/lang/cpp/src/gpgsignkeyeditinteractor.h
new file mode 100644
index 0000000..47ff8e5
--- /dev/null
+++ b/lang/cpp/src/gpgsignkeyeditinteractor.h
@@ -0,0 +1,64 @@
+/*
+ gpgsignkeyeditinteractor.h - Edit Interactor to change the owner trust of an OpenPGP key
+ Copyright (C) 2008 Klarälvdalens Datakonsult AB
+
+ This file is part of GPGME++.
+
+ GPGME++ is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Library General Public
+ License as published by the Free Software Foundation; either
+ version 2 of the License, or (at your option) any later version.
+
+ GPGME++ is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU Library General Public License for more details.
+
+ You should have received a copy of the GNU Library General Public License
+ along with GPGME++; see the file COPYING.LIB. If not, write to the
+ Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+ Boston, MA 02110-1301, USA.
+*/
+
+#ifndef __GPGMEPP_GPGSIGNKEYEDITINTERACTOR_H__
+#define __GPGMEPP_GPGSIGNKEYEDITINTERACTOR_H__
+
+#include <editinteractor.h>
+
+#include <string>
+#include <vector>
+
+namespace GpgME
+{
+
+class Key;
+class UserID;
+
+class GPGMEPP_EXPORT GpgSignKeyEditInteractor : public EditInteractor
+{
+public:
+ enum SignOption {
+ Exportable = 0x1,
+ NonRevocable = 0x2,
+ Trust = 0x4
+ };
+
+ GpgSignKeyEditInteractor();
+ ~GpgSignKeyEditInteractor();
+
+ void setCheckLevel(unsigned int checkLevel);
+ void setUserIDsToSign(const std::vector<unsigned int> &userIDsToSign);
+ void setSigningOptions(int options);
+
+private:
+ /* reimp */ const char *action(Error &err) const;
+ /* reimp */ unsigned int nextState(unsigned int statusCode, const char *args, Error &err) const;
+
+private:
+ class Private;
+ Private *const d;
+};
+
+} // namespace GpgME
+
+#endif // __GPGMEPP_GPGSIGNKEYEDITINTERACTOR_H__
diff --git a/lang/cpp/src/importresult.cpp b/lang/cpp/src/importresult.cpp
new file mode 100644
index 0000000..97e8239
--- /dev/null
+++ b/lang/cpp/src/importresult.cpp
@@ -0,0 +1,215 @@
+/*
+ importresult.cpp - wraps a gpgme import result
+ Copyright (C) 2004 Klarälvdalens Datakonsult AB
+
+ This file is part of GPGME++.
+
+ GPGME++ is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Library General Public
+ License as published by the Free Software Foundation; either
+ version 2 of the License, or (at your option) any later version.
+
+ GPGME++ is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU Library General Public License for more details.
+
+ You should have received a copy of the GNU Library General Public License
+ along with GPGME++; see the file COPYING.LIB. If not, write to the
+ Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+ Boston, MA 02110-1301, USA.
+*/
+
+
+#include <importresult.h>
+#include "result_p.h"
+
+#include <gpgme.h>
+#include <cstdlib>
+#include <cstring>
+
+#include <string.h>
+
+class GpgME::ImportResult::Private
+{
+public:
+ Private(const _gpgme_op_import_result &r) : res(r)
+ {
+ // copy recursively, using compiler-generated copy ctor.
+ // We just need to handle the pointers in the structs:
+ for (gpgme_import_status_t is = r.imports ; is ; is = is->next) {
+ gpgme_import_status_t copy = new _gpgme_import_status(*is);
+ copy->fpr = strdup(is->fpr);
+ copy->next = 0;
+ imports.push_back(copy);
+ }
+ res.imports = 0;
+ }
+ ~Private()
+ {
+ for (std::vector<gpgme_import_status_t>::iterator it = imports.begin() ; it != imports.end() ; ++it) {
+ std::free((*it)->fpr);
+ delete *it; *it = 0;
+ }
+ }
+
+ _gpgme_op_import_result res;
+ std::vector<gpgme_import_status_t> imports;
+};
+
+GpgME::ImportResult::ImportResult(gpgme_ctx_t ctx, int error)
+ : GpgME::Result(error), d()
+{
+ init(ctx);
+}
+
+GpgME::ImportResult::ImportResult(gpgme_ctx_t ctx, const Error &error)
+ : GpgME::Result(error), d()
+{
+ init(ctx);
+}
+
+void GpgME::ImportResult::init(gpgme_ctx_t ctx)
+{
+ if (!ctx) {
+ return;
+ }
+ gpgme_import_result_t res = gpgme_op_import_result(ctx);
+ if (!res) {
+ return;
+ }
+ d.reset(new Private(*res));
+}
+
+make_standard_stuff(ImportResult)
+
+int GpgME::ImportResult::numConsidered() const
+{
+ return d ? d->res.considered : 0 ;
+}
+
+int GpgME::ImportResult::numKeysWithoutUserID() const
+{
+ return d ? d->res.no_user_id : 0 ;
+}
+
+int GpgME::ImportResult::numImported() const
+{
+ return d ? d->res.imported : 0 ;
+}
+
+int GpgME::ImportResult::numRSAImported() const
+{
+ return d ? d->res.imported_rsa : 0 ;
+}
+
+int GpgME::ImportResult::numUnchanged() const
+{
+ return d ? d->res.unchanged : 0 ;
+}
+
+int GpgME::ImportResult::newUserIDs() const
+{
+ return d ? d->res.new_user_ids : 0 ;
+}
+
+int GpgME::ImportResult::newSubkeys() const
+{
+ return d ? d->res.new_sub_keys : 0 ;
+}
+
+int GpgME::ImportResult::newSignatures() const
+{
+ return d ? d->res.new_signatures : 0 ;
+}
+
+int GpgME::ImportResult::newRevocations() const
+{
+ return d ? d->res.new_revocations : 0 ;
+}
+
+int GpgME::ImportResult::numSecretKeysConsidered() const
+{
+ return d ? d->res.secret_read : 0 ;
+}
+
+int GpgME::ImportResult::numSecretKeysImported() const
+{
+ return d ? d->res.secret_imported : 0 ;
+}
+
+int GpgME::ImportResult::numSecretKeysUnchanged() const
+{
+ return d ? d->res.secret_unchanged : 0 ;
+}
+
+int GpgME::ImportResult::notImported() const
+{
+ return d ? d->res.not_imported : 0 ;
+}
+
+GpgME::Import GpgME::ImportResult::import(unsigned int idx) const
+{
+ return Import(d, idx);
+}
+
+std::vector<GpgME::Import> GpgME::ImportResult::imports() const
+{
+ if (!d) {
+ return std::vector<Import>();
+ }
+ std::vector<Import> result;
+ result.reserve(d->imports.size());
+ for (unsigned int i = 0 ; i < d->imports.size() ; ++i) {
+ result.push_back(Import(d, i));
+ }
+ return result;
+}
+
+GpgME::Import::Import(const std::shared_ptr<ImportResult::Private> &parent, unsigned int i)
+ : d(parent), idx(i)
+{
+
+}
+
+GpgME::Import::Import() : d(), idx(0) {}
+
+bool GpgME::Import::isNull() const
+{
+ return !d || idx >= d->imports.size() ;
+}
+
+const char *GpgME::Import::fingerprint() const
+{
+ return isNull() ? 0 : d->imports[idx]->fpr ;
+}
+
+GpgME::Error GpgME::Import::error() const
+{
+ return Error(isNull() ? 0 : d->imports[idx]->result);
+}
+
+GpgME::Import::Status GpgME::Import::status() const
+{
+ if (isNull()) {
+ return Unknown;
+ }
+ const unsigned int s = d->imports[idx]->status;
+ unsigned int result = Unknown;
+ if (s & GPGME_IMPORT_NEW) {
+ result |= NewKey;
+ }
+ if (s & GPGME_IMPORT_UID) {
+ result |= NewUserIDs;
+ }
+ if (s & GPGME_IMPORT_SIG) {
+ result |= NewSignatures;
+ }
+ if (s & GPGME_IMPORT_SUBKEY) {
+ result |= NewSubkeys;
+ }
+ if (s & GPGME_IMPORT_SECRET) {
+ result |= ContainedSecretKey;
+ }
+ return static_cast<Status>(result);
+}
diff --git a/lang/cpp/src/importresult.h b/lang/cpp/src/importresult.h
new file mode 100644
index 0000000..adda80a
--- /dev/null
+++ b/lang/cpp/src/importresult.h
@@ -0,0 +1,134 @@
+/*
+ importresult.h - wraps a gpgme import result
+ Copyright (C) 2004 Klarälvdalens Datakonsult AB
+
+ This file is part of GPGME++.
+
+ GPGME++ is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Library General Public
+ License as published by the Free Software Foundation; either
+ version 2 of the License, or (at your option) any later version.
+
+ GPGME++ is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU Library General Public License for more details.
+
+ You should have received a copy of the GNU Library General Public License
+ along with GPGME++; see the file COPYING.LIB. If not, write to the
+ Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+ Boston, MA 02110-1301, USA.
+*/
+
+#ifndef __GPGMEPP_IMPORTRESULT_H__
+#define __GPGMEPP_IMPORTRESULT_H__
+
+#include "gpgmefw.h"
+#include "result.h"
+#include "gpgmepp_export.h"
+
+#include <memory>
+
+#include <vector>
+
+namespace GpgME
+{
+
+class Error;
+class Import;
+
+class GPGMEPP_EXPORT ImportResult : public Result
+{
+public:
+ ImportResult();
+ ImportResult(gpgme_ctx_t ctx, int error);
+ ImportResult(gpgme_ctx_t ctx, const Error &error);
+ explicit ImportResult(const Error &error);
+
+ const ImportResult &operator=(ImportResult other)
+ {
+ swap(other);
+ return *this;
+ }
+
+ void swap(ImportResult &other)
+ {
+ Result::swap(other);
+ using std::swap;
+ swap(this->d, other.d);
+ }
+
+ bool isNull() const;
+
+ int numConsidered() const;
+ int numKeysWithoutUserID() const;
+ int numImported() const;
+ int numRSAImported() const;
+ int numUnchanged() const;
+
+ int newUserIDs() const;
+ int newSubkeys() const;
+ int newSignatures() const;
+ int newRevocations() const;
+
+ int numSecretKeysConsidered() const;
+ int numSecretKeysImported() const;
+ int numSecretKeysUnchanged() const;
+
+ int notImported() const;
+
+ Import import(unsigned int idx) const;
+ std::vector<Import> imports() const;
+
+ class Private;
+private:
+ void init(gpgme_ctx_t ctx);
+ std::shared_ptr<Private> d;
+};
+
+class GPGMEPP_EXPORT Import
+{
+ friend class ::GpgME::ImportResult;
+ Import(const std::shared_ptr<ImportResult::Private> &parent, unsigned int idx);
+public:
+ Import();
+
+ const Import &operator=(Import other)
+ {
+ swap(other);
+ return *this;
+ }
+
+ void swap(Import &other)
+ {
+ using std::swap;
+ swap(this->d, other.d);
+ swap(this->idx, other.idx);
+ }
+
+ bool isNull() const;
+
+ const char *fingerprint() const;
+ Error error() const;
+
+ enum Status {
+ Unknown = 0x0,
+ NewKey = 0x1,
+ NewUserIDs = 0x2,
+ NewSignatures = 0x4,
+ NewSubkeys = 0x8,
+ ContainedSecretKey = 0x10
+ };
+ Status status() const;
+
+private:
+ std::shared_ptr<ImportResult::Private> d;
+ unsigned int idx;
+};
+
+}
+
+GPGMEPP_MAKE_STD_SWAP_SPECIALIZATION(ImportResult)
+GPGMEPP_MAKE_STD_SWAP_SPECIALIZATION(Import)
+
+#endif // __GPGMEPP_IMPORTRESULT_H__
diff --git a/lang/cpp/src/interfaces/assuantransaction.h b/lang/cpp/src/interfaces/assuantransaction.h
new file mode 100644
index 0000000..a382b05
--- /dev/null
+++ b/lang/cpp/src/interfaces/assuantransaction.h
@@ -0,0 +1,49 @@
+/*
+ assuantransaction.h - Interface for ASSUAN transactions
+ Copyright (C) 2009 Klarälvdalens Datakonsult AB <info@kdab.com>
+ Author: Marc Mutz <marc@kdab.com>
+
+ This file is part of GPGME++.
+
+ GPGME++ is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Library General Public
+ License as published by the Free Software Foundation; either
+ version 2 of the License, or (at your option) any later version.
+
+ GPGME++ is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU Library General Public License for more details.
+
+ You should have received a copy of the GNU Library General Public License
+ along with GPGME++; see the file COPYING.LIB. If not, write to the
+ Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+ Boston, MA 02110-1301, USA.
+*/
+
+#ifndef __GPGMEPP_INTERFACES_ASSUANTRANSACTION_H__
+#define __GPGMEPP_INTERFACES_ASSUANTRANSACTION_H__
+
+#include "gpgmepp_export.h"
+
+#include <stddef.h>
+
+namespace GpgME
+{
+
+class Error;
+class Data;
+
+class GPGMEPP_EXPORT AssuanTransaction
+{
+public:
+ virtual ~AssuanTransaction() {}
+
+ virtual Error data(const char *data, size_t datalen) = 0;
+ virtual Data inquire(const char *name, const char *args, Error &err) = 0;
+ virtual Error status(const char *status, const char *args) = 0;
+};
+
+} // namespace GpgME
+
+#endif // __GPGMEPP_INTERFACES_ASSUANTRANSACTION_H__
diff --git a/lang/cpp/src/interfaces/dataprovider.h b/lang/cpp/src/interfaces/dataprovider.h
new file mode 100644
index 0000000..166bb4e
--- /dev/null
+++ b/lang/cpp/src/interfaces/dataprovider.h
@@ -0,0 +1,53 @@
+/*
+ interface/dataprovider.h - Interface for data sources
+ Copyright (C) 2003 Klarälvdalens Datakonsult AB
+
+ This file is part of GPGME++.
+
+ GPGME++ is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Library General Public
+ License as published by the Free Software Foundation; either
+ version 2 of the License, or (at your option) any later version.
+
+ GPGME++ is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU Library General Public License for more details.
+
+ You should have received a copy of the GNU Library General Public License
+ along with GPGME++; see the file COPYING.LIB. If not, write to the
+ Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+ Boston, MA 02110-1301, USA.
+*/
+
+#ifndef __GPGMEPP_INTERFACES_DATAPROVIDER_H__
+#define __GPGMEPP_INTERFACES_DATAPROVIDER_H__
+
+#include <sys/types.h>
+
+#include "gpgmepp_export.h"
+
+#include <gpg-error.h>
+
+namespace GpgME
+{
+
+class GPGMEPP_EXPORT DataProvider
+{
+public:
+ virtual ~DataProvider() {}
+
+ enum Operation {
+ Read, Write, Seek, Release
+ };
+ virtual bool isSupported(Operation op) const = 0;
+
+ virtual ssize_t read(void *buffer, size_t bufSize) = 0;
+ virtual ssize_t write(const void *buffer, size_t bufSize) = 0;
+ virtual off_t seek(off_t offset, int whence) = 0;
+ virtual void release() = 0;
+};
+
+} // namespace GpgME
+
+#endif // __GPGMEPP_INTERFACES_DATAPROVIDER_H__
diff --git a/lang/cpp/src/interfaces/passphraseprovider.h b/lang/cpp/src/interfaces/passphraseprovider.h
new file mode 100644
index 0000000..5275e44
--- /dev/null
+++ b/lang/cpp/src/interfaces/passphraseprovider.h
@@ -0,0 +1,40 @@
+/*
+ interface/passphraseprovider.h - Interface for passphrase callbacks
+ Copyright (C) 2003,2004 Klarälvdalens Datakonsult AB
+
+ This file is part of GPGME++.
+
+ GPGME++ is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Library General Public
+ License as published by the Free Software Foundation; either
+ version 2 of the License, or (at your option) any later version.
+
+ GPGME++ is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU Library General Public License for more details.
+
+ You should have received a copy of the GNU Library General Public License
+ along with GPGME++; see the file COPYING.LIB. If not, write to the
+ Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+ Boston, MA 02110-1301, USA.
+*/
+
+#ifndef __GPGMEPP_INTERFACES_PASSPHRASEPROVIDER_H__
+#define __GPGMEPP_INTERFACES_PASSPHRASEPROVIDER_H__
+
+namespace GpgME
+{
+
+class PassphraseProvider
+{
+public:
+ virtual ~PassphraseProvider() {}
+
+ virtual char *getPassphrase(const char *useridHint, const char *description,
+ bool previousWasBad, bool &canceled) = 0;
+};
+
+} // namespace GpgME
+
+#endif // __GPGMEPP_INTERFACES_PASSPHRASEPROVIDER_H__
diff --git a/lang/cpp/src/interfaces/progressprovider.h b/lang/cpp/src/interfaces/progressprovider.h
new file mode 100644
index 0000000..78bbdd7
--- /dev/null
+++ b/lang/cpp/src/interfaces/progressprovider.h
@@ -0,0 +1,40 @@
+/*
+ interface/progressprovider.h - Interface for progress reports
+ Copyright (C) 2003 Klarälvdalens Datakonsult AB
+
+ This file is part of GPGME++.
+
+ GPGME++ is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Library General Public
+ License as published by the Free Software Foundation; either
+ version 2 of the License, or (at your option) any later version.
+
+ GPGME++ is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU Library General Public License for more details.
+
+ You should have received a copy of the GNU Library General Public License
+ along with GPGME++; see the file COPYING.LIB. If not, write to the
+ Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+ Boston, MA 02110-1301, USA.
+*/
+
+#ifndef __GPGMEPP_INTERFACES_PROGRESSPROVIDER_H__
+#define __GPGMEPP_INTERFACES_PROGRESSPROVIDER_H__
+
+namespace GpgME
+{
+
+class ProgressProvider
+{
+public:
+ virtual ~ProgressProvider() {}
+
+ virtual void showProgress(const char *what, int type,
+ int current, int total) = 0;
+};
+
+} // namespace GpgME
+
+#endif // __GPGMEPP_INTERFACES_PROGRESSPROVIDER_H__
diff --git a/lang/cpp/src/key.cpp b/lang/cpp/src/key.cpp
new file mode 100644
index 0000000..cfa1ba3
--- /dev/null
+++ b/lang/cpp/src/key.cpp
@@ -0,0 +1,912 @@
+/*
+ key.cpp - wraps a gpgme key
+ Copyright (C) 2003, 2005 Klarälvdalens Datakonsult AB
+
+ This file is part of GPGME++.
+
+ GPGME++ is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Library General Public
+ License as published by the Free Software Foundation; either
+ version 2 of the License, or (at your option) any later version.
+
+ GPGME++ is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU Library General Public License for more details.
+
+ You should have received a copy of the GNU Library General Public License
+ along with GPGME++; see the file COPYING.LIB. If not, write to the
+ Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+ Boston, MA 02110-1301, USA.
+*/
+
+#include <key.h>
+
+#include "util.h"
+#include "tofuinfo.h"
+#include "context.h"
+
+#include <gpgme.h>
+
+#include <string.h>
+#include <istream>
+#include <iterator>
+
+const GpgME::Key::Null GpgME::Key::null;
+
+namespace GpgME
+{
+
+Key::Key() : key() {}
+
+Key::Key(const Null &) : key() {}
+
+Key::Key(const shared_gpgme_key_t &k) : key(k) {}
+
+Key::Key(gpgme_key_t k, bool ref)
+ : key(k
+ ? shared_gpgme_key_t(k, &gpgme_key_unref)
+ : shared_gpgme_key_t())
+{
+ if (ref && impl()) {
+ gpgme_key_ref(impl());
+ }
+}
+
+UserID Key::userID(unsigned int index) const
+{
+ return UserID(key, index);
+}
+
+Subkey Key::subkey(unsigned int index) const
+{
+ return Subkey(key, index);
+}
+
+unsigned int Key::numUserIDs() const
+{
+ if (!key) {
+ return 0;
+ }
+ unsigned int count = 0;
+ for (gpgme_user_id_t uid = key->uids ; uid ; uid = uid->next) {
+ ++count;
+ }
+ return count;
+}
+
+unsigned int Key::numSubkeys() const
+{
+ if (!key) {
+ return 0;
+ }
+ unsigned int count = 0;
+ for (gpgme_sub_key_t subkey = key->subkeys ; subkey ; subkey = subkey->next) {
+ ++count;
+ }
+ return count;
+}
+
+std::vector<UserID> Key::userIDs() const
+{
+ if (!key) {
+ return std::vector<UserID>();
+ }
+
+ std::vector<UserID> v;
+ v.reserve(numUserIDs());
+ for (gpgme_user_id_t uid = key->uids ; uid ; uid = uid->next) {
+ v.push_back(UserID(key, uid));
+ }
+ return v;
+}
+
+std::vector<Subkey> Key::subkeys() const
+{
+ if (!key) {
+ return std::vector<Subkey>();
+ }
+
+ std::vector<Subkey> v;
+ v.reserve(numSubkeys());
+ for (gpgme_sub_key_t subkey = key->subkeys ; subkey ; subkey = subkey->next) {
+ v.push_back(Subkey(key, subkey));
+ }
+ return v;
+}
+
+Key::OwnerTrust Key::ownerTrust() const
+{
+ if (!key) {
+ return Unknown;
+ }
+ switch (key->owner_trust) {
+ default:
+ case GPGME_VALIDITY_UNKNOWN: return Unknown;
+ case GPGME_VALIDITY_UNDEFINED: return Undefined;
+ case GPGME_VALIDITY_NEVER: return Never;
+ case GPGME_VALIDITY_MARGINAL: return Marginal;
+ case GPGME_VALIDITY_FULL: return Full;
+ case GPGME_VALIDITY_ULTIMATE: return Ultimate;
+ }
+}
+char Key::ownerTrustAsString() const
+{
+ if (!key) {
+ return '?';
+ }
+ switch (key->owner_trust) {
+ default:
+ case GPGME_VALIDITY_UNKNOWN: return '?';
+ case GPGME_VALIDITY_UNDEFINED: return 'q';
+ case GPGME_VALIDITY_NEVER: return 'n';
+ case GPGME_VALIDITY_MARGINAL: return 'm';
+ case GPGME_VALIDITY_FULL: return 'f';
+ case GPGME_VALIDITY_ULTIMATE: return 'u';
+ }
+}
+
+Protocol Key::protocol() const
+{
+ if (!key) {
+ return UnknownProtocol;
+ }
+ switch (key->protocol) {
+ case GPGME_PROTOCOL_CMS: return CMS;
+ case GPGME_PROTOCOL_OpenPGP: return OpenPGP;
+ default: return UnknownProtocol;
+ }
+}
+
+const char *Key::protocolAsString() const
+{
+ return key ? gpgme_get_protocol_name(key->protocol) : 0 ;
+}
+
+bool Key::isRevoked() const
+{
+ return key && key->revoked;
+}
+
+bool Key::isExpired() const
+{
+ return key && key->expired;
+}
+
+bool Key::isDisabled() const
+{
+ return key && key->disabled;
+}
+
+bool Key::isInvalid() const
+{
+ return key && key->invalid;
+}
+
+bool Key::hasSecret() const
+{
+ return key && key->secret;
+}
+
+bool Key::isRoot() const
+{
+ return key && key->subkeys && key->subkeys->fpr && key->chain_id &&
+ strcasecmp(key->subkeys->fpr, key->chain_id) == 0;
+}
+
+bool Key::canEncrypt() const
+{
+ return key && key->can_encrypt;
+}
+
+bool Key::canSign() const
+{
+#ifndef GPGME_CAN_SIGN_ON_SECRET_OPENPGP_KEYLISTING_NOT_BROKEN
+ if (key && key->protocol == GPGME_PROTOCOL_OpenPGP) {
+ return true;
+ }
+#endif
+ return canReallySign();
+}
+
+bool Key::canReallySign() const
+{
+ return key && key->can_sign;
+}
+
+bool Key::canCertify() const
+{
+ return key && key->can_certify;
+}
+
+bool Key::canAuthenticate() const
+{
+ return key && key->can_authenticate;
+}
+
+bool Key::isQualified() const
+{
+ return key && key->is_qualified;
+}
+
+const char *Key::issuerSerial() const
+{
+ return key ? key->issuer_serial : 0 ;
+}
+const char *Key::issuerName() const
+{
+ return key ? key->issuer_name : 0 ;
+}
+const char *Key::chainID() const
+{
+ return key ? key->chain_id : 0 ;
+}
+
+const char *Key::keyID() const
+{
+ return key && key->subkeys ? key->subkeys->keyid : 0 ;
+}
+
+const char *Key::shortKeyID() const
+{
+ if (!key || !key->subkeys || !key->subkeys->keyid) {
+ return 0;
+ }
+ const int len = strlen(key->subkeys->keyid);
+ if (len > 8) {
+ return key->subkeys->keyid + len - 8; // return the last 8 bytes (in hex notation)
+ } else {
+ return key->subkeys->keyid;
+ }
+}
+
+const char *Key::primaryFingerprint() const
+{
+ if (!key) {
+ return nullptr;
+ }
+ if (key->fpr) {
+ /* Return what gpgme thinks is the primary fingerprint */
+ return key->fpr;
+ }
+ if (key->subkeys) {
+ /* Return the first subkeys fingerprint */
+ return key->subkeys->fpr;
+ }
+}
+
+unsigned int Key::keyListMode() const
+{
+ return key ? convert_from_gpgme_keylist_mode_t(key->keylist_mode) : 0 ;
+}
+
+const Key &Key::mergeWith(const Key &other)
+{
+ // ### incomplete. Just merges has* and can*, nothing else atm
+ // ### detach also missing
+
+ if (!this->primaryFingerprint() ||
+ !other.primaryFingerprint() ||
+ strcasecmp(this->primaryFingerprint(), other.primaryFingerprint()) != 0) {
+ return *this; // only merge the Key object which describe the same key
+ }
+
+ const gpgme_key_t me = impl();
+ const gpgme_key_t him = other.impl();
+
+ if (!me || !him) {
+ return *this;
+ }
+
+ me->revoked |= him->revoked;
+ me->expired |= him->expired;
+ me->disabled |= him->disabled;
+ me->invalid |= him->invalid;
+ me->can_encrypt |= him->can_encrypt;
+ me->can_sign |= him->can_sign;
+ me->can_certify |= him->can_certify;
+ me->secret |= him->secret;
+ me->can_authenticate |= him->can_authenticate;
+ me->is_qualified |= him->is_qualified;
+ me->keylist_mode |= him->keylist_mode;
+
+ // make sure the gpgme_sub_key_t::is_cardkey flag isn't lost:
+ for (gpgme_sub_key_t mysk = me->subkeys ; mysk ; mysk = mysk->next) {
+ for (gpgme_sub_key_t hissk = him->subkeys ; hissk ; hissk = hissk->next) {
+ if (strcmp(mysk->fpr, hissk->fpr) == 0) {
+ mysk->is_cardkey |= hissk->is_cardkey;
+ break;
+ }
+ }
+ }
+
+ return *this;
+}
+
+void Key::update()
+{
+ auto ctx = Context::createForProtocol(protocol());
+ if (!ctx) {
+ return;
+ }
+ ctx->setKeyListMode(KeyListMode::Local |
+ KeyListMode::Signatures |
+ KeyListMode::SignatureNotations |
+ KeyListMode::Validate |
+ KeyListMode::WithTofu);
+ Error err;
+ auto newKey = ctx->key(primaryFingerprint(), err, hasSecret());
+ delete ctx;
+ if (err) {
+ return;
+ }
+ swap(newKey);
+ return;
+}
+
+//
+//
+// class Subkey
+//
+//
+
+gpgme_sub_key_t find_subkey(const shared_gpgme_key_t &key, unsigned int idx)
+{
+ if (key) {
+ for (gpgme_sub_key_t s = key->subkeys ; s ; s = s->next, --idx) {
+ if (idx == 0) {
+ return s;
+ }
+ }
+ }
+ return 0;
+}
+
+gpgme_sub_key_t verify_subkey(const shared_gpgme_key_t &key, gpgme_sub_key_t subkey)
+{
+ if (key) {
+ for (gpgme_sub_key_t s = key->subkeys ; s ; s = s->next) {
+ if (s == subkey) {
+ return subkey;
+ }
+ }
+ }
+ return 0;
+}
+
+Subkey::Subkey() : key(), subkey(0) {}
+
+Subkey::Subkey(const shared_gpgme_key_t &k, unsigned int idx)
+ : key(k), subkey(find_subkey(k, idx))
+{
+
+}
+
+Subkey::Subkey(const shared_gpgme_key_t &k, gpgme_sub_key_t sk)
+ : key(k), subkey(verify_subkey(k, sk))
+{
+
+}
+
+Key Subkey::parent() const
+{
+ return Key(key);
+}
+
+const char *Subkey::keyID() const
+{
+ return subkey ? subkey->keyid : 0 ;
+}
+
+const char *Subkey::fingerprint() const
+{
+ return subkey ? subkey->fpr : 0 ;
+}
+
+Subkey::PubkeyAlgo Subkey::publicKeyAlgorithm() const
+{
+ return subkey ? static_cast<PubkeyAlgo>(subkey->pubkey_algo) : AlgoUnknown;
+}
+
+const char *Subkey::publicKeyAlgorithmAsString() const
+{
+ return gpgme_pubkey_algo_name(subkey ? subkey->pubkey_algo : (gpgme_pubkey_algo_t)0);
+}
+
+/* static */
+const char *Subkey::publicKeyAlgorithmAsString(PubkeyAlgo algo)
+{
+ if (algo == AlgoUnknown) {
+ return NULL;
+ }
+ return gpgme_pubkey_algo_name(static_cast<gpgme_pubkey_algo_t>(algo));
+}
+
+std::string Subkey::algoName() const
+{
+ char *gpgmeStr;
+ if (subkey && (gpgmeStr = gpgme_pubkey_algo_string(subkey))) {
+ std::string ret = std::string(gpgmeStr);
+ gpgme_free(gpgmeStr);
+ return ret;
+ }
+ return std::string();
+}
+
+bool Subkey::canEncrypt() const
+{
+ return subkey && subkey->can_encrypt;
+}
+
+bool Subkey::canSign() const
+{
+ return subkey && subkey->can_sign;
+}
+
+bool Subkey::canCertify() const
+{
+ return subkey && subkey->can_certify;
+}
+
+bool Subkey::canAuthenticate() const
+{
+ return subkey && subkey->can_authenticate;
+}
+
+bool Subkey::isQualified() const
+{
+ return subkey && subkey->is_qualified;
+}
+
+bool Subkey::isCardKey() const
+{
+ return subkey && subkey->is_cardkey;
+}
+
+const char *Subkey::cardSerialNumber() const
+{
+ return subkey ? subkey->card_number : 0 ;
+}
+
+bool Subkey::isSecret() const
+{
+ return subkey && subkey->secret;
+}
+
+unsigned int Subkey::length() const
+{
+ return subkey ? subkey->length : 0 ;
+}
+
+time_t Subkey::creationTime() const
+{
+ return static_cast<time_t>(subkey ? subkey->timestamp : 0);
+}
+
+time_t Subkey::expirationTime() const
+{
+ return static_cast<time_t>(subkey ? subkey->expires : 0);
+}
+
+bool Subkey::neverExpires() const
+{
+ return expirationTime() == time_t(0);
+}
+
+bool Subkey::isRevoked() const
+{
+ return subkey && subkey->revoked;
+}
+
+bool Subkey::isInvalid() const
+{
+ return subkey && subkey->invalid;
+}
+
+bool Subkey::isExpired() const
+{
+ return subkey && subkey->expired;
+}
+
+bool Subkey::isDisabled() const
+{
+ return subkey && subkey->disabled;
+}
+
+//
+//
+// class UserID
+//
+//
+
+gpgme_user_id_t find_uid(const shared_gpgme_key_t &key, unsigned int idx)
+{
+ if (key) {
+ for (gpgme_user_id_t u = key->uids ; u ; u = u->next, --idx) {
+ if (idx == 0) {
+ return u;
+ }
+ }
+ }
+ return 0;
+}
+
+gpgme_user_id_t verify_uid(const shared_gpgme_key_t &key, gpgme_user_id_t uid)
+{
+ if (key) {
+ for (gpgme_user_id_t u = key->uids ; u ; u = u->next) {
+ if (u == uid) {
+ return uid;
+ }
+ }
+ }
+ return 0;
+}
+
+UserID::UserID() : key(), uid(0) {}
+
+UserID::UserID(const shared_gpgme_key_t &k, gpgme_user_id_t u)
+ : key(k), uid(verify_uid(k, u))
+{
+
+}
+
+UserID::UserID(const shared_gpgme_key_t &k, unsigned int idx)
+ : key(k), uid(find_uid(k, idx))
+{
+
+}
+
+Key UserID::parent() const
+{
+ return Key(key);
+}
+
+UserID::Signature UserID::signature(unsigned int index) const
+{
+ return Signature(key, uid, index);
+}
+
+unsigned int UserID::numSignatures() const
+{
+ if (!uid) {
+ return 0;
+ }
+ unsigned int count = 0;
+ for (gpgme_key_sig_t sig = uid->signatures ; sig ; sig = sig->next) {
+ ++count;
+ }
+ return count;
+}
+
+std::vector<UserID::Signature> UserID::signatures() const
+{
+ if (!uid) {
+ return std::vector<Signature>();
+ }
+
+ std::vector<Signature> v;
+ v.reserve(numSignatures());
+ for (gpgme_key_sig_t sig = uid->signatures ; sig ; sig = sig->next) {
+ v.push_back(Signature(key, uid, sig));
+ }
+ return v;
+}
+
+const char *UserID::id() const
+{
+ return uid ? uid->uid : 0 ;
+}
+
+const char *UserID::name() const
+{
+ return uid ? uid->name : 0 ;
+}
+
+const char *UserID::email() const
+{
+ return uid ? uid->email : 0 ;
+}
+
+const char *UserID::comment() const
+{
+ return uid ? uid->comment : 0 ;
+}
+
+UserID::Validity UserID::validity() const
+{
+ if (!uid) {
+ return Unknown;
+ }
+ switch (uid->validity) {
+ default:
+ case GPGME_VALIDITY_UNKNOWN: return Unknown;
+ case GPGME_VALIDITY_UNDEFINED: return Undefined;
+ case GPGME_VALIDITY_NEVER: return Never;
+ case GPGME_VALIDITY_MARGINAL: return Marginal;
+ case GPGME_VALIDITY_FULL: return Full;
+ case GPGME_VALIDITY_ULTIMATE: return Ultimate;
+ }
+}
+
+char UserID::validityAsString() const
+{
+ if (!uid) {
+ return '?';
+ }
+ switch (uid->validity) {
+ default:
+ case GPGME_VALIDITY_UNKNOWN: return '?';
+ case GPGME_VALIDITY_UNDEFINED: return 'q';
+ case GPGME_VALIDITY_NEVER: return 'n';
+ case GPGME_VALIDITY_MARGINAL: return 'm';
+ case GPGME_VALIDITY_FULL: return 'f';
+ case GPGME_VALIDITY_ULTIMATE: return 'u';
+ }
+}
+
+bool UserID::isRevoked() const
+{
+ return uid && uid->revoked;
+}
+
+bool UserID::isInvalid() const
+{
+ return uid && uid->invalid;
+}
+
+TofuInfo UserID::tofuInfo() const
+{
+ if (!uid) {
+ return TofuInfo();
+ }
+ return TofuInfo(uid->tofu);
+}
+
+//
+//
+// class Signature
+//
+//
+
+gpgme_key_sig_t find_signature(gpgme_user_id_t uid, unsigned int idx)
+{
+ if (uid) {
+ for (gpgme_key_sig_t s = uid->signatures ; s ; s = s->next, --idx) {
+ if (idx == 0) {
+ return s;
+ }
+ }
+ }
+ return 0;
+}
+
+gpgme_key_sig_t verify_signature(gpgme_user_id_t uid, gpgme_key_sig_t sig)
+{
+ if (uid) {
+ for (gpgme_key_sig_t s = uid->signatures ; s ; s = s->next) {
+ if (s == sig) {
+ return sig;
+ }
+ }
+ }
+ return 0;
+}
+
+UserID::Signature::Signature() : key(), uid(0), sig(0) {}
+
+UserID::Signature::Signature(const shared_gpgme_key_t &k, gpgme_user_id_t u, unsigned int idx)
+ : key(k), uid(verify_uid(k, u)), sig(find_signature(uid, idx))
+{
+
+}
+
+UserID::Signature::Signature(const shared_gpgme_key_t &k, gpgme_user_id_t u, gpgme_key_sig_t s)
+ : key(k), uid(verify_uid(k, u)), sig(verify_signature(uid, s))
+{
+
+}
+
+UserID UserID::Signature::parent() const
+{
+ return UserID(key, uid);
+}
+
+const char *UserID::Signature::signerKeyID() const
+{
+ return sig ? sig->keyid : 0 ;
+}
+
+const char *UserID::Signature::algorithmAsString() const
+{
+ return gpgme_pubkey_algo_name(sig ? sig->pubkey_algo : (gpgme_pubkey_algo_t)0);
+}
+
+unsigned int UserID::Signature::algorithm() const
+{
+ return sig ? sig->pubkey_algo : 0 ;
+}
+
+time_t UserID::Signature::creationTime() const
+{
+ return static_cast<time_t>(sig ? sig->timestamp : 0);
+}
+
+time_t UserID::Signature::expirationTime() const
+{
+ return static_cast<time_t>(sig ? sig->expires : 0);
+}
+
+bool UserID::Signature::neverExpires() const
+{
+ return expirationTime() == time_t(0);
+}
+
+bool UserID::Signature::isRevokation() const
+{
+ return sig && sig->revoked;
+}
+
+bool UserID::Signature::isInvalid() const
+{
+ return sig && sig->invalid;
+}
+
+bool UserID::Signature::isExpired() const
+{
+ return sig && sig->expired;
+}
+
+bool UserID::Signature::isExportable() const
+{
+ return sig && sig->exportable;
+}
+
+const char *UserID::Signature::signerUserID() const
+{
+ return sig ? sig->uid : 0 ;
+}
+
+const char *UserID::Signature::signerName() const
+{
+ return sig ? sig->name : 0 ;
+}
+
+const char *UserID::Signature::signerEmail() const
+{
+ return sig ? sig->email : 0 ;
+}
+
+const char *UserID::Signature::signerComment() const
+{
+ return sig ? sig->comment : 0 ;
+}
+
+unsigned int UserID::Signature::certClass() const
+{
+ return sig ? sig->sig_class : 0 ;
+}
+
+UserID::Signature::Status UserID::Signature::status() const
+{
+ if (!sig) {
+ return GeneralError;
+ }
+
+ switch (gpgme_err_code(sig->status)) {
+ case GPG_ERR_NO_ERROR: return NoError;
+ case GPG_ERR_SIG_EXPIRED: return SigExpired;
+ case GPG_ERR_KEY_EXPIRED: return KeyExpired;
+ case GPG_ERR_BAD_SIGNATURE: return BadSignature;
+ case GPG_ERR_NO_PUBKEY: return NoPublicKey;
+ default:
+ case GPG_ERR_GENERAL: return GeneralError;
+ }
+}
+
+std::string UserID::Signature::statusAsString() const
+{
+ if (!sig) {
+ return std::string();
+ }
+ char buf[ 1024 ];
+ gpgme_strerror_r(sig->status, buf, sizeof buf);
+ buf[ sizeof buf - 1 ] = '\0';
+ return std::string(buf);
+}
+
+GpgME::Notation UserID::Signature::notation(unsigned int idx) const
+{
+ if (!sig) {
+ return GpgME::Notation();
+ }
+ for (gpgme_sig_notation_t nota = sig->notations ; nota ; nota = nota->next) {
+ if (nota->name) {
+ if (idx-- == 0) {
+ return GpgME::Notation(nota);
+ }
+ }
+ }
+ return GpgME::Notation();
+}
+
+unsigned int UserID::Signature::numNotations() const
+{
+ if (!sig) {
+ return 0;
+ }
+ unsigned int count = 0;
+ for (gpgme_sig_notation_t nota = sig->notations ; nota ; nota = nota->next) {
+ if (nota->name) {
+ ++count; // others are policy URLs...
+ }
+ }
+ return count;
+}
+
+std::vector<Notation> UserID::Signature::notations() const
+{
+ if (!sig) {
+ return std::vector<GpgME::Notation>();
+ }
+ std::vector<GpgME::Notation> v;
+ v.reserve(numNotations());
+ for (gpgme_sig_notation_t nota = sig->notations ; nota ; nota = nota->next) {
+ if (nota->name) {
+ v.push_back(GpgME::Notation(nota));
+ }
+ }
+ return v;
+}
+
+const char *UserID::Signature::policyURL() const
+{
+ if (!sig) {
+ return 0;
+ }
+ for (gpgme_sig_notation_t nota = sig->notations ; nota ; nota = nota->next) {
+ if (!nota->name) {
+ return nota->value;
+ }
+ }
+ return 0;
+}
+
+std::ostream &operator<<(std::ostream &os, const UserID &uid)
+{
+ os << "GpgME::UserID(";
+ if (!uid.isNull()) {
+ os << "\n name: " << protect(uid.name())
+ << "\n email: " << protect(uid.email())
+ << "\n comment: " << protect(uid.comment())
+ << "\n validity: " << uid.validityAsString()
+ << "\n revoked: " << uid.isRevoked()
+ << "\n invalid: " << uid.isInvalid()
+ << "\n numsigs: " << uid.numSignatures()
+ << "\n tofuinfo:\n" << uid.tofuInfo();
+ }
+ return os << ')';
+}
+
+std::ostream &operator<<(std::ostream &os, const Key &key)
+{
+ os << "GpgME::Key(";
+ if (!key.isNull()) {
+ os << "\n protocol: " << protect(key.protocolAsString())
+ << "\n ownertrust: " << key.ownerTrustAsString()
+ << "\n issuer: " << protect(key.issuerName())
+ << "\n fingerprint:" << protect(key.primaryFingerprint())
+ << "\n listmode: " << key.keyListMode()
+ << "\n canSign: " << key.canReallySign()
+ << "\n canEncrypt: " << key.canEncrypt()
+ << "\n canCertify: " << key.canCertify()
+ << "\n canAuth: " << key.canAuthenticate()
+ << "\n uids:\n";
+ const std::vector<UserID> uids = key.userIDs();
+ std::copy(uids.begin(), uids.end(),
+ std::ostream_iterator<UserID>(os, "\n"));
+ }
+ return os << ')';
+}
+
+} // namespace GpgME
diff --git a/lang/cpp/src/key.h b/lang/cpp/src/key.h
new file mode 100644
index 0000000..f193093
--- /dev/null
+++ b/lang/cpp/src/key.h
@@ -0,0 +1,415 @@
+/*
+ key.h - wraps a gpgme key
+ Copyright (C) 2003, 2005 Klarälvdalens Datakonsult AB
+
+ This file is part of GPGME++.
+
+ GPGME++ is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Library General Public
+ License as published by the Free Software Foundation; either
+ version 2 of the License, or (at your option) any later version.
+
+ GPGME++ is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU Library General Public License for more details.
+
+ You should have received a copy of the GNU Library General Public License
+ along with GPGME++; see the file COPYING.LIB. If not, write to the
+ Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+ Boston, MA 02110-1301, USA.
+*/
+
+// -*- c++ -*-
+#ifndef __GPGMEPP_KEY_H__
+#define __GPGMEPP_KEY_H__
+
+#include "global.h"
+#include "notation.h"
+
+#include "gpgmefw.h"
+
+#include <memory>
+#include <sys/time.h>
+
+#include <vector>
+#include <algorithm>
+#include <string>
+
+namespace GpgME
+{
+
+class Context;
+
+class Subkey;
+class UserID;
+class TofuInfo;
+
+typedef std::shared_ptr< std::remove_pointer<gpgme_key_t>::type > shared_gpgme_key_t;
+
+//
+// class Key
+//
+
+class GPGMEPP_EXPORT Key
+{
+ friend class ::GpgME::Context;
+ struct Null {
+ Null() {}
+ };
+public:
+ Key();
+ /* implicit */ Key(const Null &);
+ Key(const shared_gpgme_key_t &key);
+ Key(gpgme_key_t key, bool acquireRef);
+
+ static const Null null;
+
+ const Key &operator=(Key other)
+ {
+ swap(other);
+ return *this;
+ }
+
+ const Key &mergeWith(const Key &other);
+
+ void swap(Key &other)
+ {
+ using std::swap;
+ swap(this->key, other.key);
+ }
+
+ bool isNull() const
+ {
+ return !key;
+ }
+
+ UserID userID(unsigned int index) const;
+ Subkey subkey(unsigned int index) const;
+
+ unsigned int numUserIDs() const;
+ unsigned int numSubkeys() const;
+
+ std::vector<UserID> userIDs() const;
+ std::vector<Subkey> subkeys() const;
+
+ bool isRevoked() const;
+ bool isExpired() const;
+ bool isDisabled() const;
+ bool isInvalid() const;
+
+ bool canEncrypt() const;
+ /*!
+ This function contains a workaround for old gpgme's: all secret
+ OpenPGP keys canSign() == true, which canReallySign() doesn't
+ have. I don't have time to find what breaks when I remove this
+ workaround, but since Kleopatra merges secret into public keys,
+ the workaround is not necessary there (and actively harms), I've
+ added a new function instead.
+ */
+ bool canSign() const;
+ bool canReallySign() const;
+ bool canCertify() const;
+ bool canAuthenticate() const;
+ bool isQualified() const;
+
+ bool hasSecret() const;
+ GPGMEPP_DEPRECATED bool isSecret() const
+ {
+ return hasSecret();
+ }
+
+ /*!
+ @return true if this is a X.509 root certificate (currently
+ equivalent to something like
+ strcmp( chainID(), subkey(0).fingerprint() ) == 0 )
+ */
+ bool isRoot() const;
+
+ enum OwnerTrust { Unknown = 0, Undefined = 1, Never = 2,
+ Marginal = 3, Full = 4, Ultimate = 5
+ };
+
+ OwnerTrust ownerTrust() const;
+ char ownerTrustAsString() const;
+
+ Protocol protocol() const;
+ const char *protocolAsString() const;
+
+ const char *issuerSerial() const;
+ const char *issuerName() const;
+ const char *chainID() const;
+
+ const char *keyID() const;
+ const char *shortKeyID() const;
+ const char *primaryFingerprint() const;
+
+ unsigned int keyListMode() const;
+
+ /*! Update information about this key.
+ * Starts a keylisting for this key with validity
+ * and tofu information gathering. Blocks for
+ * how long the keylisting takes.*/
+ void update();
+
+private:
+ gpgme_key_t impl() const
+ {
+ return key.get();
+ }
+ shared_gpgme_key_t key;
+};
+
+//
+// class Subkey
+//
+
+class GPGMEPP_EXPORT Subkey
+{
+public:
+ Subkey();
+ Subkey(const shared_gpgme_key_t &key, gpgme_sub_key_t subkey);
+ Subkey(const shared_gpgme_key_t &key, unsigned int idx);
+
+ const Subkey &operator=(Subkey other)
+ {
+ swap(other);
+ return *this;
+ }
+
+ void swap(Subkey &other)
+ {
+ using std::swap;
+ swap(this->key, other.key);
+ swap(this->subkey, other.subkey);
+ }
+
+ bool isNull() const
+ {
+ return !key || !subkey;
+ }
+
+ Key parent() const;
+
+ const char *keyID() const;
+ const char *fingerprint() const;
+
+ time_t creationTime() const;
+ time_t expirationTime() const;
+ bool neverExpires() const;
+
+ bool isRevoked() const;
+ bool isExpired() const;
+ bool isInvalid() const;
+ bool isDisabled() const;
+
+ bool canEncrypt() const;
+ bool canSign() const;
+ bool canCertify() const;
+ bool canAuthenticate() const;
+ bool isQualified() const;
+ bool isCardKey() const;
+
+ bool isSecret() const;
+
+ /** Same as gpgme_pubkey_algo_t */
+ enum PubkeyAlgo {
+ AlgoUnknown = 0,
+ AlgoRSA = 1,
+ AlgoRSA_E = 2,
+ AlgoRSA_S = 3,
+ AlgoELG_E = 16,
+ AlgoDSA = 17,
+ AlgoECC = 18,
+ AlgoELG = 20,
+ AlgoECDSA = 301,
+ AlgoECDH = 302,
+ AlgoEDDSA = 303,
+ AlgoMax = 1 << 31
+ };
+
+ PubkeyAlgo publicKeyAlgorithm() const;
+
+ /**
+ @brief Get the public key algorithm name.
+
+ This only works for the pre 2.1 algorithms for ECC NULL is returned.
+
+ @returns a statically allocated string with the name of the public
+ key algorithm, or NULL if that name is not known.
+ */
+ const char *publicKeyAlgorithmAsString() const;
+
+ /** @brief Same as publicKeyAlgorithmAsString but static. */
+ static const char *publicKeyAlgorithmAsString(PubkeyAlgo algo);
+
+ /**
+ @brief Get the key algo string like GnuPG 2.1 prints it.
+
+ This returns combinations of size and algorithm. Like
+ bp512 or rsa2048. Misnamed because publicKeyAlgorithmAsString
+ already used the older pubkey_algo_name.
+ Actually uses gpgme_pubkey_algo_string.
+
+ @returns the key algorithm as string. Empty string on error.
+ */
+ std::string algoName() const;
+
+ unsigned int length() const;
+
+ const char *cardSerialNumber() const;
+
+private:
+ shared_gpgme_key_t key;
+ gpgme_sub_key_t subkey;
+};
+
+//
+// class UserID
+//
+
+class GPGMEPP_EXPORT UserID
+{
+public:
+ class Signature;
+
+ UserID();
+ UserID(const shared_gpgme_key_t &key, gpgme_user_id_t uid);
+ UserID(const shared_gpgme_key_t &key, unsigned int idx);
+
+ const UserID &operator=(UserID other)
+ {
+ swap(other);
+ return *this;
+ }
+
+ void swap(UserID &other)
+ {
+ using std::swap;
+ swap(this->key, other.key);
+ swap(this->uid, other.uid);
+ }
+
+ bool isNull() const
+ {
+ return !key || !uid;
+ }
+
+ Key parent() const;
+
+ unsigned int numSignatures() const;
+ Signature signature(unsigned int index) const;
+ std::vector<Signature> signatures() const;
+
+ const char *id() const;
+ const char *name() const;
+ const char *email() const;
+ const char *comment() const;
+
+ enum Validity { Unknown = 0, Undefined = 1, Never = 2,
+ Marginal = 3, Full = 4, Ultimate = 5
+ };
+
+ Validity validity() const;
+ char validityAsString() const;
+
+ bool isRevoked() const;
+ bool isInvalid() const;
+
+ /** TOFU info for this userid.
+ * @returns The TOFU stats or a null TofuInfo.
+ */
+ GpgME::TofuInfo tofuInfo() const;
+private:
+ shared_gpgme_key_t key;
+ gpgme_user_id_t uid;
+};
+
+//
+// class UserID::Signature
+//
+
+class GPGMEPP_EXPORT UserID::Signature
+{
+public:
+ typedef GPGMEPP_DEPRECATED GpgME::Notation Notation;
+
+ Signature();
+ Signature(const shared_gpgme_key_t &key, gpgme_user_id_t uid, gpgme_key_sig_t sig);
+ Signature(const shared_gpgme_key_t &key, gpgme_user_id_t uid, unsigned int idx);
+
+ const Signature &operator=(Signature other)
+ {
+ swap(other);
+ return *this;
+ }
+
+ void swap(Signature &other)
+ {
+ using std::swap;
+ swap(this->key, other.key);
+ swap(this->uid, other.uid);
+ swap(this->sig, other.sig);
+ }
+
+ bool isNull() const
+ {
+ return !sig || !uid || !key ;
+ }
+
+ UserID parent() const;
+
+ const char *signerKeyID() const;
+
+ const char *algorithmAsString() const;
+ unsigned int algorithm() const;
+ time_t creationTime() const;
+ time_t expirationTime() const;
+ bool neverExpires() const;
+
+ bool isRevokation() const;
+ bool isInvalid() const;
+ bool isExpired() const;
+ bool isExportable() const;
+
+ const char *signerUserID() const;
+ const char *signerName() const;
+ const char *signerEmail() const;
+ const char *signerComment() const;
+
+ unsigned int certClass() const;
+
+ enum Status { NoError = 0, SigExpired, KeyExpired,
+ BadSignature, NoPublicKey, GeneralError
+ };
+ Status status() const;
+ std::string statusAsString() const;
+
+ const char *policyURL() const;
+
+ unsigned int numNotations() const;
+ GpgME::Notation notation(unsigned int idx) const;
+ std::vector<GpgME::Notation> notations() const;
+
+private:
+ shared_gpgme_key_t key;
+ gpgme_user_id_t uid;
+ gpgme_key_sig_t sig;
+};
+
+GPGMEPP_EXPORT std::ostream &operator<<(std::ostream &os, const UserID &uid);
+GPGMEPP_EXPORT std::ostream &operator<<(std::ostream &os, const Key &key);
+
+} // namespace GpgME
+
+GPGMEPP_MAKE_STD_SWAP_SPECIALIZATION(Key)
+GPGMEPP_MAKE_STD_SWAP_SPECIALIZATION(Subkey)
+GPGMEPP_MAKE_STD_SWAP_SPECIALIZATION(UserID)
+GPGMEPP_MAKE_STD_SWAP_SPECIALIZATION(UserID::Signature)
+
+GPGMEPP_MAKE_STRCMP(ByFingerprint, .primaryFingerprint());
+GPGMEPP_MAKE_STRCMP(ByKeyID, .keyID());
+GPGMEPP_MAKE_STRCMP(ByShortKeyID, .shortKeyID());
+GPGMEPP_MAKE_STRCMP(ByChainID, .chainID());
+
+#endif // __GPGMEPP_KEY_H__
diff --git a/lang/cpp/src/keygenerationresult.cpp b/lang/cpp/src/keygenerationresult.cpp
new file mode 100644
index 0000000..7837e20
--- /dev/null
+++ b/lang/cpp/src/keygenerationresult.cpp
@@ -0,0 +1,92 @@
+/*
+ keygenerationresult.cpp - wraps a gpgme keygen result
+ Copyright (C) 2004 Klarälvdalens Datakonsult AB
+
+ This file is part of GPGME++.
+
+ GPGME++ is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Library General Public
+ License as published by the Free Software Foundation; either
+ version 2 of the License, or (at your option) any later version.
+
+ GPGME++ is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU Library General Public License for more details.
+
+ You should have received a copy of the GNU Library General Public License
+ along with GPGME++; see the file COPYING.LIB. If not, write to the
+ Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+ Boston, MA 02110-1301, USA.
+*/
+
+#include <keygenerationresult.h>
+#include "result_p.h"
+
+#include <gpgme.h>
+
+#include <cstring>
+#include <cstdlib>
+
+#include <string.h>
+
+class GpgME::KeyGenerationResult::Private
+{
+public:
+ Private(const _gpgme_op_genkey_result &r) : res(r)
+ {
+ if (res.fpr) {
+ res.fpr = strdup(res.fpr);
+ }
+ }
+ ~Private()
+ {
+ if (res.fpr) {
+ std::free(res.fpr);
+ }
+ res.fpr = 0;
+ }
+
+ _gpgme_op_genkey_result res;
+};
+
+GpgME::KeyGenerationResult::KeyGenerationResult(gpgme_ctx_t ctx, int error)
+ : GpgME::Result(error), d()
+{
+ init(ctx);
+}
+
+GpgME::KeyGenerationResult::KeyGenerationResult(gpgme_ctx_t ctx, const Error &error)
+ : GpgME::Result(error), d()
+{
+ init(ctx);
+}
+
+void GpgME::KeyGenerationResult::init(gpgme_ctx_t ctx)
+{
+ if (!ctx) {
+ return;
+ }
+ gpgme_genkey_result_t res = gpgme_op_genkey_result(ctx);
+ if (!res) {
+ return;
+ }
+ d.reset(new Private(*res));
+}
+
+make_standard_stuff(KeyGenerationResult)
+
+bool GpgME::KeyGenerationResult::isPrimaryKeyGenerated() const
+{
+ return d && d->res.primary;
+}
+
+bool GpgME::KeyGenerationResult::isSubkeyGenerated() const
+{
+ return d && d->res.sub;
+}
+
+const char *GpgME::KeyGenerationResult::fingerprint() const
+{
+ return d ? d->res.fpr : 0 ;
+}
diff --git a/lang/cpp/src/keygenerationresult.h b/lang/cpp/src/keygenerationresult.h
new file mode 100644
index 0000000..c35c504
--- /dev/null
+++ b/lang/cpp/src/keygenerationresult.h
@@ -0,0 +1,82 @@
+/*
+ keygenerationresult.h - wraps a gpgme keygen result
+ Copyright (C) 2004 Klarälvdalens Datakonsult AB
+
+ This file is part of GPGME++.
+
+ GPGME++ is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Library General Public
+ License as published by the Free Software Foundation; either
+ version 2 of the License, or (at your option) any later version.
+
+ GPGME++ is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU Library General Public License for more details.
+
+ You should have received a copy of the GNU Library General Public License
+ along with GPGME++; see the file COPYING.LIB. If not, write to the
+ Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+ Boston, MA 02110-1301, USA.
+*/
+
+#ifndef __GPGMEPP_KEYGENERATIONRESULT_H__
+#define __GPGMEPP_KEYGENERATIONRESULT_H__
+
+#include "gpgmefw.h"
+#include "result.h"
+#include "gpgmepp_export.h"
+
+#include <memory>
+
+namespace GpgME
+{
+
+class Error;
+
+class GPGMEPP_EXPORT KeyGenerationResult : public Result
+{
+public:
+ KeyGenerationResult();
+ KeyGenerationResult(gpgme_ctx_t ctx, int error);
+ KeyGenerationResult(gpgme_ctx_t ctx, const Error &error);
+ explicit KeyGenerationResult(const Error &err);
+
+ const KeyGenerationResult &operator=(KeyGenerationResult other)
+ {
+ swap(other);
+ return *this;
+ }
+
+ void swap(KeyGenerationResult &other)
+ {
+ Result::swap(other);
+ using std::swap;
+ swap(this->d, other.d);
+ }
+
+ bool isNull() const;
+
+ GPGMEPP_DEPRECATED bool primaryKeyGenerated() const
+ {
+ return isPrimaryKeyGenerated();
+ }
+ GPGMEPP_DEPRECATED bool subkeyGenerated() const
+ {
+ return isSubkeyGenerated();
+ }
+ bool isPrimaryKeyGenerated() const;
+ bool isSubkeyGenerated() const;
+ const char *fingerprint() const;
+
+private:
+ class Private;
+ void init(gpgme_ctx_t ctx);
+ std::shared_ptr<Private> d;
+};
+
+}
+
+GPGMEPP_MAKE_STD_SWAP_SPECIALIZATION(KeyGenerationResult)
+
+#endif // __GPGMEPP_KEYGENERATIONRESULT_H__
diff --git a/lang/cpp/src/keylistresult.cpp b/lang/cpp/src/keylistresult.cpp
new file mode 100644
index 0000000..4512d3b
--- /dev/null
+++ b/lang/cpp/src/keylistresult.cpp
@@ -0,0 +1,107 @@
+/*
+ keylistresult.cpp - wraps a gpgme keylist result
+ Copyright (C) 2004 Klarälvdalens Datakonsult AB
+
+ This file is part of GPGME++.
+
+ GPGME++ is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Library General Public
+ License as published by the Free Software Foundation; either
+ version 2 of the License, or (at your option) any later version.
+
+ GPGME++ is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU Library General Public License for more details.
+
+ You should have received a copy of the GNU Library General Public License
+ along with GPGME++; see the file COPYING.LIB. If not, write to the
+ Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+ Boston, MA 02110-1301, USA.
+*/
+
+#include <keylistresult.h>
+#include "result_p.h"
+
+#include <gpgme.h>
+
+#include <cstring>
+#include <cassert>
+
+class GpgME::KeyListResult::Private
+{
+public:
+ Private(const _gpgme_op_keylist_result &r) : res(r) {}
+ Private(const Private &other) : res(other.res) {}
+
+ _gpgme_op_keylist_result res;
+};
+
+GpgME::KeyListResult::KeyListResult(gpgme_ctx_t ctx, int error)
+ : GpgME::Result(error), d()
+{
+ init(ctx);
+}
+
+GpgME::KeyListResult::KeyListResult(gpgme_ctx_t ctx, const Error &error)
+ : GpgME::Result(error), d()
+{
+ init(ctx);
+}
+
+void GpgME::KeyListResult::init(gpgme_ctx_t ctx)
+{
+ if (!ctx) {
+ return;
+ }
+ gpgme_keylist_result_t res = gpgme_op_keylist_result(ctx);
+ if (!res) {
+ return;
+ }
+ d.reset(new Private(*res));
+}
+
+GpgME::KeyListResult::KeyListResult(const Error &error, const _gpgme_op_keylist_result &res)
+ : GpgME::Result(error), d(new Private(res))
+{
+
+}
+
+make_standard_stuff(KeyListResult)
+
+void GpgME::KeyListResult::detach()
+{
+ if (!d || d.unique()) {
+ return;
+ }
+ d.reset(new Private(*d));
+}
+
+void GpgME::KeyListResult::mergeWith(const KeyListResult &other)
+{
+ if (other.isNull()) {
+ return;
+ }
+ if (isNull()) { // just assign
+ operator=(other);
+ return;
+ }
+ // merge the truncated flag (try to keep detaching to a minimum):
+ if (other.isTruncated() && !this->isTruncated()) {
+ assert(other.d);
+ detach();
+ if (!d) {
+ d.reset(new Private(*other.d));
+ } else {
+ d->res.truncated = true;
+ }
+ }
+ if (! bool(error())) { // only merge the error when there was none yet.
+ Result::operator=(other);
+ }
+}
+
+bool GpgME::KeyListResult::isTruncated() const
+{
+ return d && d->res.truncated;
+}
diff --git a/lang/cpp/src/keylistresult.h b/lang/cpp/src/keylistresult.h
new file mode 100644
index 0000000..7dfe2d7
--- /dev/null
+++ b/lang/cpp/src/keylistresult.h
@@ -0,0 +1,81 @@
+/*
+ keylistresult.h - wraps a gpgme keylist result
+ Copyright (C) 2004 Klarälvdalens Datakonsult AB
+
+ This file is part of GPGME++.
+
+ GPGME++ is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Library General Public
+ License as published by the Free Software Foundation; either
+ version 2 of the License, or (at your option) any later version.
+
+ GPGME++ is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU Library General Public License for more details.
+
+ You should have received a copy of the GNU Library General Public License
+ along with GPGME++; see the file COPYING.LIB. If not, write to the
+ Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+ Boston, MA 02110-1301, USA.
+*/
+
+#ifndef __GPGMEPP_KEYLISTRESULT_H__
+#define __GPGMEPP_KEYLISTRESULT_H__
+
+#include "gpgmefw.h"
+#include "result.h"
+#include "gpgmepp_export.h"
+
+#include <memory>
+
+namespace GpgME
+{
+
+class Error;
+
+class GPGMEPP_EXPORT KeyListResult : public Result
+{
+public:
+ KeyListResult();
+ KeyListResult(gpgme_ctx_t ctx, int error);
+ KeyListResult(gpgme_ctx_t ctx, const Error &error);
+ explicit KeyListResult(const Error &err);
+ KeyListResult(const Error &err, const _gpgme_op_keylist_result &res);
+
+ const KeyListResult &operator=(KeyListResult other)
+ {
+ swap(other);
+ return *this;
+ }
+ void swap(KeyListResult &other)
+ {
+ Result::swap(other);
+ using std::swap;
+ swap(this->d, other.d);
+ }
+
+ const KeyListResult &operator+=(const KeyListResult &other)
+ {
+ mergeWith(other);
+ return *this;
+ }
+
+ void mergeWith(const KeyListResult &other);
+
+ bool isNull() const;
+
+ bool isTruncated() const;
+
+private:
+ void detach();
+ void init(gpgme_ctx_t ctx);
+ class Private;
+ std::shared_ptr<Private> d;
+};
+
+}
+
+GPGMEPP_MAKE_STD_SWAP_SPECIALIZATION(KeyListResult)
+
+#endif // __GPGMEPP_KEYLISTRESULT_H__
diff --git a/lang/cpp/src/notation.h b/lang/cpp/src/notation.h
new file mode 100644
index 0000000..807bdaa
--- /dev/null
+++ b/lang/cpp/src/notation.h
@@ -0,0 +1,84 @@
+/*
+ notation.h - wraps a gpgme verify result
+ Copyright (C) 2004, 2007 Klarälvdalens Datakonsult AB
+
+ This file is part of GPGME++.
+
+ GPGME++ is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Library General Public
+ License as published by the Free Software Foundation; either
+ version 2 of the License, or (at your option) any later version.
+
+ GPGME++ is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU Library General Public License for more details.
+
+ You should have received a copy of the GNU Library General Public License
+ along with GPGME++; see the file COPYING.LIB. If not, write to the
+ Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+ Boston, MA 02110-1301, USA.
+*/
+
+#ifndef __GPGMEPP_NOTATION_H__
+#define __GPGMEPP_NOTATION_H__
+
+#include "gpgmefw.h"
+#include "verificationresult.h"
+#include "gpgmepp_export.h"
+
+#include <memory>
+
+#include <iosfwd>
+
+namespace GpgME
+{
+
+class GPGMEPP_EXPORT Notation
+{
+ friend class ::GpgME::Signature;
+ Notation(const std::shared_ptr<VerificationResult::Private> &parent, unsigned int sindex, unsigned int nindex);
+public:
+ Notation();
+ explicit Notation(gpgme_sig_notation_t nota);
+
+ const Notation &operator=(Notation other)
+ {
+ swap(other);
+ return *this;
+ }
+
+ void swap(Notation &other)
+ {
+ using std::swap;
+ swap(this->d, other.d);
+ }
+
+ bool isNull() const;
+
+ const char *name() const;
+ const char *value() const;
+
+ enum Flags {
+ NoFlags = 0,
+ HumanReadable = 1,
+ Critical = 2
+ };
+ Flags flags() const;
+
+ bool isHumanReadable() const;
+ bool isCritical() const;
+
+private:
+ class Private;
+ std::shared_ptr<Private> d;
+};
+
+GPGMEPP_EXPORT std::ostream &operator<<(std::ostream &os, const Notation &nota);
+GPGMEPP_EXPORT std::ostream &operator<<(std::ostream &os, Notation::Flags flags);
+
+}
+
+GPGMEPP_MAKE_STD_SWAP_SPECIALIZATION(Notation)
+
+#endif // __GPGMEPP_NOTATION_H__
diff --git a/lang/cpp/src/result.h b/lang/cpp/src/result.h
new file mode 100644
index 0000000..a86d81f
--- /dev/null
+++ b/lang/cpp/src/result.h
@@ -0,0 +1,58 @@
+/*
+ result.h - base class for results
+ Copyright (C) 2004 Klarälvdalens Datakonsult AB
+
+ This file is part of GPGME++.
+
+ GPGME++ is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Library General Public
+ License as published by the Free Software Foundation; either
+ version 2 of the License, or (at your option) any later version.
+
+ GPGME++ is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU Library General Public License for more details.
+
+ You should have received a copy of the GNU Library General Public License
+ along with GPGME++; see the file COPYING.LIB. If not, write to the
+ Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+ Boston, MA 02110-1301, USA.
+*/
+
+#ifndef __GPGMEPP_RESULT_H__
+#define __GPGMEPP_RESULT_H__
+
+#include "gpgmefw.h"
+#include "error.h"
+
+#include <algorithm> // std::swap
+
+namespace GpgME
+{
+
+class GPGMEPP_EXPORT Result
+{
+protected:
+ explicit Result() : mError() {}
+ explicit Result(int err) : mError(err) {}
+ explicit Result(const Error &err) : mError(err) {}
+
+ void swap(Result &other)
+ {
+ std::swap(other.mError, mError);
+ }
+
+public:
+ const Error &error() const
+ {
+ return mError;
+ }
+
+protected:
+ Error mError;
+};
+
+}
+
+#endif // __GPGMEPP_RESULT_H__
diff --git a/lang/cpp/src/result_p.h b/lang/cpp/src/result_p.h
new file mode 100644
index 0000000..0cf73e4
--- /dev/null
+++ b/lang/cpp/src/result_p.h
@@ -0,0 +1,43 @@
+/*
+ result.h - base class for results
+ Copyright (C) 2004 Klarälvdalens Datakonsult AB
+
+ This file is part of GPGME++.
+
+ GPGME++ is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Library General Public
+ License as published by the Free Software Foundation; either
+ version 2 of the License, or (at your option) any later version.
+
+ GPGME++ is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU Library General Public License for more details.
+
+ You should have received a copy of the GNU Library General Public License
+ along with GPGME++; see the file COPYING.LIB. If not, write to the
+ Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+ Boston, MA 02110-1301, USA.
+*/
+
+#ifndef __GPGMEPP_RESULT_P_H__
+#define __GPGMEPP_RESULT_P_H__
+
+#define make_default_ctor(x) \
+ GpgME::x::x() : GpgME::Result(), d() {}
+
+#define make_error_ctor(x) \
+ GpgME::x::x( const Error & error ) \
+ : GpgME::Result( error ), d() \
+ { \
+ \
+ }
+
+#define make_isNull(x) bool GpgME::x::isNull() const { return !d && !bool(error()); }
+
+#define make_standard_stuff(x) \
+ make_default_ctor(x) \
+ make_error_ctor(x) \
+ make_isNull(x)
+
+#endif // __GPGMEPP_RESULT_P_H__
diff --git a/lang/cpp/src/scdgetinfoassuantransaction.cpp b/lang/cpp/src/scdgetinfoassuantransaction.cpp
new file mode 100644
index 0000000..073d772
--- /dev/null
+++ b/lang/cpp/src/scdgetinfoassuantransaction.cpp
@@ -0,0 +1,156 @@
+/*
+ scdgetinfoassuantransaction.cpp - Assuan Transaction to get information from scdaemon
+ Copyright (C) 2009 Klarälvdalens Datakonsult AB
+
+ This file is part of GPGME++.
+
+ GPGME++ is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Library General Public
+ License as published by the Free Software Foundation; either
+ version 2 of the License, or (at your option) any later version.
+
+ GPGME++ is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU Library General Public License for more details.
+
+ You should have received a copy of the GNU Library General Public License
+ along with GPGME++; see the file COPYING.LIB. If not, write to the
+ Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+ Boston, MA 02110-1301, USA.
+*/
+
+#include "scdgetinfoassuantransaction.h"
+#include "error.h"
+#include "data.h"
+#include "util.h"
+
+#include <sstream>
+#include <assert.h>
+
+using namespace GpgME;
+
+ScdGetInfoAssuanTransaction::ScdGetInfoAssuanTransaction(InfoItem item)
+ : AssuanTransaction(),
+ m_item(item),
+ m_command(),
+ m_data()
+{
+
+}
+
+ScdGetInfoAssuanTransaction::~ScdGetInfoAssuanTransaction() {}
+
+static std::vector<std::string> to_reader_list(const std::string &s)
+{
+ std::vector<std::string> result;
+ std::stringstream ss(s);
+ std::string tok;
+ while (std::getline(ss, tok, '\n')) {
+ result.push_back(tok);
+ }
+ return result;
+}
+
+static std::vector<std::string> to_app_list(const std::string &s)
+{
+ return to_reader_list(s);
+}
+
+std::string ScdGetInfoAssuanTransaction::version() const
+{
+ if (m_item == Version) {
+ return m_data;
+ } else {
+ return std::string();
+ }
+}
+
+unsigned int ScdGetInfoAssuanTransaction::pid() const
+{
+ if (m_item == Pid) {
+ return to_pid(m_data);
+ } else {
+ return 0U;
+ }
+}
+
+std::string ScdGetInfoAssuanTransaction::socketName() const
+{
+ if (m_item == SocketName) {
+ return m_data;
+ } else {
+ return std::string();
+ }
+}
+
+char ScdGetInfoAssuanTransaction::status() const
+{
+ if (m_item == Status && !m_data.empty()) {
+ return m_data[0];
+ } else {
+ return '\0';
+ }
+}
+
+std::vector<std::string> ScdGetInfoAssuanTransaction::readerList() const
+{
+ if (m_item == ReaderList) {
+ return to_reader_list(m_data);
+ } else {
+ return std::vector<std::string>();
+ }
+}
+
+std::vector<std::string> ScdGetInfoAssuanTransaction::applicationList() const
+{
+ if (m_item == ApplicationList) {
+ return to_app_list(m_data);
+ } else {
+ return std::vector<std::string>();
+ }
+}
+
+static const char *const scd_getinfo_tokens[] = {
+ "version",
+ "pid",
+ "socket_name",
+ "status",
+ "reader_list",
+ "deny_admin",
+ "app_list",
+};
+static_assert((sizeof scd_getinfo_tokens / sizeof * scd_getinfo_tokens == ScdGetInfoAssuanTransaction::LastInfoItem),
+ "getinfo_tokens size mismatch");
+
+void ScdGetInfoAssuanTransaction::makeCommand() const
+{
+ assert(m_item >= 0);
+ assert(m_item < LastInfoItem);
+ m_command = "SCD GETINFO ";
+ m_command += scd_getinfo_tokens[m_item];
+}
+
+const char *ScdGetInfoAssuanTransaction::command() const
+{
+ makeCommand();
+ return m_command.c_str();
+}
+
+Error ScdGetInfoAssuanTransaction::data(const char *data, size_t len)
+{
+ m_data.append(data, len);
+ return Error();
+}
+
+Data ScdGetInfoAssuanTransaction::inquire(const char *name, const char *args, Error &err)
+{
+ (void)name; (void)args; (void)err;
+ return Data::null;
+}
+
+Error ScdGetInfoAssuanTransaction::status(const char *status, const char *args)
+{
+ (void)status; (void)args;
+ return Error();
+}
diff --git a/lang/cpp/src/scdgetinfoassuantransaction.h b/lang/cpp/src/scdgetinfoassuantransaction.h
new file mode 100644
index 0000000..a22a0ff
--- /dev/null
+++ b/lang/cpp/src/scdgetinfoassuantransaction.h
@@ -0,0 +1,76 @@
+/*
+ scdgetinfoassuantransaction.h - Assuan Transaction to get information from scdaemon
+ Copyright (C) 2009 Klarälvdalens Datakonsult AB
+
+ This file is part of GPGME++.
+
+ GPGME++ is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Library General Public
+ License as published by the Free Software Foundation; either
+ version 2 of the License, or (at your option) any later version.
+
+ GPGME++ is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU Library General Public License for more details.
+
+ You should have received a copy of the GNU Library General Public License
+ along with GPGME++; see the file COPYING.LIB. If not, write to the
+ Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+ Boston, MA 02110-1301, USA.
+*/
+
+#ifndef __GPGMEPP_SCDGETINFOASSUANTRANSACTION_H__
+#define __GPGMEPP_SCDGETINFOASSUANTRANSACTION_H__
+
+#include <interfaces/assuantransaction.h>
+
+#include <string>
+#include <vector>
+
+namespace GpgME
+{
+
+class GPGMEPP_EXPORT ScdGetInfoAssuanTransaction : public AssuanTransaction
+{
+public:
+ enum InfoItem {
+ Version, // string
+ Pid, // unsigned long
+ SocketName, // string (path)
+ Status, // char (status)
+ ReaderList, // string list
+ DenyAdmin, // (none, returns GPG_ERR_GENERAL when admin commands are allowed)
+ ApplicationList, // string list
+
+ LastInfoItem
+ };
+
+ explicit ScdGetInfoAssuanTransaction(InfoItem item);
+ ~ScdGetInfoAssuanTransaction();
+
+ std::string version() const;
+ unsigned int pid() const;
+ std::string socketName() const;
+ char status() const;
+ std::vector<std::string> readerList() const;
+ std::vector<std::string> applicationList() const;
+
+private:
+ /* reimp */ const char *command() const;
+ /* reimp */ Error data(const char *data, size_t datalen);
+ /* reimp */ Data inquire(const char *name, const char *args, Error &err);
+ /* reimp */ Error status(const char *status, const char *args);
+
+private:
+ void makeCommand() const;
+
+private:
+ InfoItem m_item;
+ mutable std::string m_command;
+ std::string m_data;
+};
+
+} // namespace GpgME
+
+#endif // __GPGMEPP_SCDGETINFOASSUANTRANSACTION_H__
diff --git a/lang/cpp/src/signingresult.cpp b/lang/cpp/src/signingresult.cpp
new file mode 100644
index 0000000..4f2ef72
--- /dev/null
+++ b/lang/cpp/src/signingresult.cpp
@@ -0,0 +1,265 @@
+/*
+ signingresult.cpp - wraps a gpgme verify result
+ Copyright (C) 2004 Klarälvdalens Datakonsult AB
+
+ This file is part of GPGME++.
+
+ GPGME++ is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Library General Public
+ License as published by the Free Software Foundation; either
+ version 2 of the License, or (at your option) any later version.
+
+ GPGME++ is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU Library General Public License for more details.
+
+ You should have received a copy of the GNU Library General Public License
+ along with GPGME++; see the file COPYING.LIB. If not, write to the
+ Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+ Boston, MA 02110-1301, USA.
+*/
+
+#include <signingresult.h>
+#include "result_p.h"
+#include "util.h"
+
+#include <gpgme.h>
+
+#include <cstring>
+#include <cstdlib>
+#include <algorithm>
+#include <istream>
+#include <iterator>
+
+#include <string.h>
+
+class GpgME::SigningResult::Private
+{
+public:
+ Private(const gpgme_sign_result_t r)
+ {
+ if (!r) {
+ return;
+ }
+ for (gpgme_new_signature_t is = r->signatures ; is ; is = is->next) {
+ gpgme_new_signature_t copy = new _gpgme_new_signature(*is);
+ if (is->fpr) {
+ copy->fpr = strdup(is->fpr);
+ }
+ copy->next = 0;
+ created.push_back(copy);
+ }
+ for (gpgme_invalid_key_t ik = r->invalid_signers ; ik ; ik = ik->next) {
+ gpgme_invalid_key_t copy = new _gpgme_invalid_key(*ik);
+ if (ik->fpr) {
+ copy->fpr = strdup(ik->fpr);
+ }
+ copy->next = 0;
+ invalid.push_back(copy);
+ }
+ }
+ ~Private()
+ {
+ for (std::vector<gpgme_new_signature_t>::iterator it = created.begin() ; it != created.end() ; ++it) {
+ std::free((*it)->fpr);
+ delete *it; *it = 0;
+ }
+ for (std::vector<gpgme_invalid_key_t>::iterator it = invalid.begin() ; it != invalid.end() ; ++it) {
+ std::free((*it)->fpr);
+ delete *it; *it = 0;
+ }
+ }
+
+ std::vector<gpgme_new_signature_t> created;
+ std::vector<gpgme_invalid_key_t> invalid;
+};
+
+GpgME::SigningResult::SigningResult(gpgme_ctx_t ctx, int error)
+ : GpgME::Result(error), d()
+{
+ init(ctx);
+}
+
+GpgME::SigningResult::SigningResult(gpgme_ctx_t ctx, const Error &error)
+ : GpgME::Result(error), d()
+{
+ init(ctx);
+}
+
+void GpgME::SigningResult::init(gpgme_ctx_t ctx)
+{
+ if (!ctx) {
+ return;
+ }
+ gpgme_sign_result_t res = gpgme_op_sign_result(ctx);
+ if (!res) {
+ return;
+ }
+ d.reset(new Private(res));
+}
+
+make_standard_stuff(SigningResult)
+
+GpgME::CreatedSignature GpgME::SigningResult::createdSignature(unsigned int idx) const
+{
+ return CreatedSignature(d, idx);
+}
+
+std::vector<GpgME::CreatedSignature> GpgME::SigningResult::createdSignatures() const
+{
+ if (!d) {
+ return std::vector<CreatedSignature>();
+ }
+ std::vector<CreatedSignature> result;
+ result.reserve(d->created.size());
+ for (unsigned int i = 0 ; i < d->created.size() ; ++i) {
+ result.push_back(CreatedSignature(d, i));
+ }
+ return result;
+}
+
+GpgME::InvalidSigningKey GpgME::SigningResult::invalidSigningKey(unsigned int idx) const
+{
+ return InvalidSigningKey(d, idx);
+}
+
+std::vector<GpgME::InvalidSigningKey> GpgME::SigningResult::invalidSigningKeys() const
+{
+ if (!d) {
+ return std::vector<GpgME::InvalidSigningKey>();
+ }
+ std::vector<GpgME::InvalidSigningKey> result;
+ result.reserve(d->invalid.size());
+ for (unsigned int i = 0 ; i < d->invalid.size() ; ++i) {
+ result.push_back(InvalidSigningKey(d, i));
+ }
+ return result;
+}
+
+GpgME::InvalidSigningKey::InvalidSigningKey(const std::shared_ptr<SigningResult::Private> &parent, unsigned int i)
+ : d(parent), idx(i)
+{
+
+}
+
+GpgME::InvalidSigningKey::InvalidSigningKey() : d(), idx(0) {}
+
+bool GpgME::InvalidSigningKey::isNull() const
+{
+ return !d || idx >= d->invalid.size() ;
+}
+
+const char *GpgME::InvalidSigningKey::fingerprint() const
+{
+ return isNull() ? 0 : d->invalid[idx]->fpr ;
+}
+
+GpgME::Error GpgME::InvalidSigningKey::reason() const
+{
+ return Error(isNull() ? 0 : d->invalid[idx]->reason);
+}
+
+GpgME::CreatedSignature::CreatedSignature(const std::shared_ptr<SigningResult::Private> &parent, unsigned int i)
+ : d(parent), idx(i)
+{
+
+}
+
+GpgME::CreatedSignature::CreatedSignature() : d(), idx(0) {}
+
+bool GpgME::CreatedSignature::isNull() const
+{
+ return !d || idx >= d->created.size() ;
+}
+
+const char *GpgME::CreatedSignature::fingerprint() const
+{
+ return isNull() ? 0 : d->created[idx]->fpr ;
+}
+
+time_t GpgME::CreatedSignature::creationTime() const
+{
+ return static_cast<time_t>(isNull() ? 0 : d->created[idx]->timestamp);
+}
+
+GpgME::SignatureMode GpgME::CreatedSignature::mode() const
+{
+ if (isNull()) {
+ return NormalSignatureMode;
+ }
+ switch (d->created[idx]->type) {
+ default:
+ case GPGME_SIG_MODE_NORMAL: return NormalSignatureMode;
+ case GPGME_SIG_MODE_DETACH: return Detached;
+ case GPGME_SIG_MODE_CLEAR: return Clearsigned;
+ }
+}
+
+unsigned int GpgME::CreatedSignature::publicKeyAlgorithm() const
+{
+ return isNull() ? 0 : d->created[idx]->pubkey_algo ;
+}
+
+const char *GpgME::CreatedSignature::publicKeyAlgorithmAsString() const
+{
+ return gpgme_pubkey_algo_name(isNull() ? (gpgme_pubkey_algo_t)0 : d->created[idx]->pubkey_algo);
+}
+
+unsigned int GpgME::CreatedSignature::hashAlgorithm() const
+{
+ return isNull() ? 0 : d->created[idx]->hash_algo ;
+}
+
+const char *GpgME::CreatedSignature::hashAlgorithmAsString() const
+{
+ return gpgme_hash_algo_name(isNull() ? (gpgme_hash_algo_t)0 : d->created[idx]->hash_algo);
+}
+
+unsigned int GpgME::CreatedSignature::signatureClass() const
+{
+ return isNull() ? 0 : d->created[idx]->sig_class ;
+}
+
+std::ostream &GpgME::operator<<(std::ostream &os, const SigningResult &result)
+{
+ os << "GpgME::SigningResult(";
+ if (!result.isNull()) {
+ os << "\n error: " << result.error()
+ << "\n createdSignatures:\n";
+ const std::vector<CreatedSignature> cs = result.createdSignatures();
+ std::copy(cs.begin(), cs.end(),
+ std::ostream_iterator<CreatedSignature>(os, "\n"));
+ os << " invalidSigningKeys:\n";
+ const std::vector<InvalidSigningKey> isk = result.invalidSigningKeys();
+ std::copy(isk.begin(), isk.end(),
+ std::ostream_iterator<InvalidSigningKey>(os, "\n"));
+ }
+ return os << ')';
+}
+
+std::ostream &GpgME::operator<<(std::ostream &os, const CreatedSignature &sig)
+{
+ os << "GpgME::CreatedSignature(";
+ if (!sig.isNull()) {
+ os << "\n fingerprint: " << protect(sig.fingerprint())
+ << "\n creationTime: " << sig.creationTime()
+ << "\n mode: " << sig.mode()
+ << "\n publicKeyAlgorithm: " << protect(sig.publicKeyAlgorithmAsString())
+ << "\n hashAlgorithm: " << protect(sig.hashAlgorithmAsString())
+ << "\n signatureClass: " << sig.signatureClass()
+ << '\n';
+ }
+ return os << ')';
+}
+
+std::ostream &GpgME::operator<<(std::ostream &os, const InvalidSigningKey &key)
+{
+ os << "GpgME::InvalidSigningKey(";
+ if (!key.isNull()) {
+ os << "\n fingerprint: " << protect(key.fingerprint())
+ << "\n reason: " << key.reason()
+ << '\n';
+ }
+ return os << ')';
+}
diff --git a/lang/cpp/src/signingresult.h b/lang/cpp/src/signingresult.h
new file mode 100644
index 0000000..2c27454
--- /dev/null
+++ b/lang/cpp/src/signingresult.h
@@ -0,0 +1,162 @@
+/*
+ signingresult.h - wraps a gpgme sign result
+ Copyright (C) 2004 Klarälvdalens Datakonsult AB
+
+ This file is part of GPGME++.
+
+ GPGME++ is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Library General Public
+ License as published by the Free Software Foundation; either
+ version 2 of the License, or (at your option) any later version.
+
+ GPGME++ is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU Library General Public License for more details.
+
+ You should have received a copy of the GNU Library General Public License
+ along with GPGME++; see the file COPYING.LIB. If not, write to the
+ Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+ Boston, MA 02110-1301, USA.
+*/
+
+#ifndef __GPGMEPP_SIGNINGRESULT_H__
+#define __GPGMEPP_SIGNINGRESULT_H__
+
+#include "global.h"
+#include "result.h"
+
+#include <time.h>
+
+#include <memory>
+
+#include <vector>
+#include <iosfwd>
+
+namespace GpgME
+{
+
+class Error;
+class CreatedSignature;
+class InvalidSigningKey;
+
+class GPGMEPP_EXPORT SigningResult : public Result
+{
+public:
+ SigningResult();
+ SigningResult(gpgme_ctx_t ctx, int error);
+ SigningResult(gpgme_ctx_t ctx, const Error &error);
+ explicit SigningResult(const Error &err);
+
+ const SigningResult &operator=(SigningResult other)
+ {
+ swap(other);
+ return *this;
+ }
+
+ void swap(SigningResult &other)
+ {
+ Result::swap(other);
+ using std::swap;
+ swap(this->d, other.d);
+ }
+
+ bool isNull() const;
+
+ CreatedSignature createdSignature(unsigned int index) const;
+ std::vector<CreatedSignature> createdSignatures() const;
+
+ InvalidSigningKey invalidSigningKey(unsigned int index) const;
+ std::vector<InvalidSigningKey> invalidSigningKeys() const;
+
+ class Private;
+private:
+ void init(gpgme_ctx_t ctx);
+ std::shared_ptr<Private> d;
+};
+
+GPGMEPP_EXPORT std::ostream &operator<<(std::ostream &os, const SigningResult &result);
+
+class GPGMEPP_EXPORT InvalidSigningKey
+{
+ friend class ::GpgME::SigningResult;
+ InvalidSigningKey(const std::shared_ptr<SigningResult::Private> &parent, unsigned int index);
+public:
+ InvalidSigningKey();
+
+ const InvalidSigningKey &operator=(InvalidSigningKey other)
+ {
+ swap(other);
+ return *this;
+ }
+
+ void swap(InvalidSigningKey &other)
+ {
+ using std::swap;
+ swap(this->d, other.d);
+ swap(this->idx, other.idx);
+ }
+
+ bool isNull() const;
+
+ const char *fingerprint() const;
+ Error reason() const;
+
+private:
+ std::shared_ptr<SigningResult::Private> d;
+ unsigned int idx;
+};
+
+GPGMEPP_EXPORT std::ostream &operator<<(std::ostream &os, const InvalidSigningKey &key);
+
+class GPGMEPP_EXPORT CreatedSignature
+{
+ friend class ::GpgME::SigningResult;
+ CreatedSignature(const std::shared_ptr<SigningResult::Private> &parent, unsigned int index);
+public:
+
+ CreatedSignature();
+
+ const CreatedSignature &operator=(CreatedSignature other)
+ {
+ swap(other);
+ return *this;
+ }
+
+ void swap(CreatedSignature &other)
+ {
+ using std::swap;
+ swap(this->d, other.d);
+ swap(this->idx, other.idx);
+ }
+
+ bool isNull() const;
+
+ const char *fingerprint() const;
+
+ time_t creationTime() const;
+
+ SignatureMode mode() const;
+
+ unsigned int publicKeyAlgorithm() const;
+ const char *publicKeyAlgorithmAsString() const;
+
+ unsigned int hashAlgorithm() const;
+ const char *hashAlgorithmAsString() const;
+
+ unsigned int signatureClass() const;
+
+private:
+ std::shared_ptr<SigningResult::Private> d;
+ unsigned int idx;
+};
+
+GPGMEPP_EXPORT std::ostream &operator<<(std::ostream &os, const CreatedSignature &sig);
+
+}
+
+GPGMEPP_MAKE_STD_SWAP_SPECIALIZATION(SigningResult)
+GPGMEPP_MAKE_STD_SWAP_SPECIALIZATION(InvalidSigningKey)
+GPGMEPP_MAKE_STD_SWAP_SPECIALIZATION(CreatedSignature)
+
+#endif // __GPGMEPP_SIGNINGRESULT_H__
diff --git a/lang/cpp/src/tofuinfo.cpp b/lang/cpp/src/tofuinfo.cpp
new file mode 100644
index 0000000..bb67fc8
--- /dev/null
+++ b/lang/cpp/src/tofuinfo.cpp
@@ -0,0 +1,167 @@
+/* tofuinfo.cpp - wraps gpgme tofu info
+ Copyright (C) 2016 Intevation GmbH
+
+ This file is part of GPGME++.
+
+ GPGME++ is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Library General Public
+ License as published by the Free Software Foundation; either
+ version 2 of the License, or (at your option) any later version.
+
+ GPGME++ is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU Library General Public License for more details.
+
+ You should have received a copy of the GNU Library General Public License
+ along with GPGME++; see the file COPYING.LIB. If not, write to the
+ Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+ Boston, MA 02110-1301, USA.
+*/
+
+#include "tofuinfo.h"
+
+#include <istream>
+#include "util.h"
+
+class GpgME::TofuInfo::Private
+{
+public:
+ Private() {}
+ Private(gpgme_tofu_info_t info)
+ : mInfo(info ? new _gpgme_tofu_info(*info) : nullptr)
+ {
+ if (mInfo && mInfo->description) {
+ mInfo->description = strdup(mInfo->description);
+ }
+ }
+
+ Private(const Private &other)
+ : mInfo(other.mInfo)
+ {
+ if (mInfo && mInfo->description) {
+ mInfo->description = strdup(mInfo->description);
+ }
+ }
+
+ ~Private()
+ {
+ if (mInfo) {
+ std::free(mInfo->description);
+ mInfo->description = nullptr;
+
+ delete mInfo;
+ }
+ }
+
+ gpgme_tofu_info_t mInfo;
+};
+
+GpgME::TofuInfo::TofuInfo(gpgme_tofu_info_t info)
+ : d(new Private(info))
+{
+}
+
+GpgME::TofuInfo::TofuInfo() : d()
+{
+}
+
+bool GpgME::TofuInfo::isNull() const
+{
+ return !d || !d->mInfo;
+}
+
+GpgME::TofuInfo::Validity GpgME::TofuInfo::validity() const
+{
+ if (isNull()) {
+ return ValidityUnknown;
+ }
+ switch (d->mInfo->validity) {
+ case 0:
+ return Conflict;
+ case 1:
+ return NoHistory;
+ case 2:
+ return LittleHistory;
+ case 3:
+ return BasicHistory;
+ case 4:
+ return LargeHistory;
+ default:
+ return ValidityUnknown;
+ }
+}
+
+GpgME::TofuInfo::Policy GpgME::TofuInfo::policy() const
+{
+ if (isNull()) {
+ return PolicyUnknown;
+ }
+ switch (d->mInfo->policy) {
+ case GPGME_TOFU_POLICY_NONE:
+ return PolicyNone;
+ case GPGME_TOFU_POLICY_AUTO:
+ return PolicyAuto;
+ case GPGME_TOFU_POLICY_GOOD:
+ return PolicyGood;
+ case GPGME_TOFU_POLICY_BAD:
+ return PolicyBad;
+ case GPGME_TOFU_POLICY_ASK:
+ return PolicyAsk;
+ case GPGME_TOFU_POLICY_UNKNOWN:
+ return PolicyUnknown;
+ }
+}
+
+const char *GpgME::TofuInfo::description() const
+{
+ return isNull() ? nullptr : d->mInfo->description;
+}
+
+unsigned short GpgME::TofuInfo::signCount() const
+{
+ return isNull() ? 0 : d->mInfo->signcount;
+}
+
+unsigned short GpgME::TofuInfo::encrCount() const
+{
+ return isNull() ? 0 : d->mInfo->encrcount;
+}
+
+unsigned long GpgME::TofuInfo::signFirst() const
+{
+ return isNull() ? 0 : d->mInfo->signfirst;
+}
+
+unsigned long GpgME::TofuInfo::signLast() const
+{
+ return isNull() ? 0 : d->mInfo->signlast;
+}
+
+unsigned long GpgME::TofuInfo::encrFirst() const
+{
+ return isNull() ? 0 : d->mInfo->encrfirst;
+}
+
+unsigned long GpgME::TofuInfo::encrLast() const
+{
+ return isNull() ? 0 : d->mInfo->encrlast;
+}
+
+std::ostream &GpgME::operator<<(std::ostream &os, const GpgME::TofuInfo &info)
+{
+ os << "GpgME::Signature::TofuInfo(";
+ if (!info.isNull()) {
+ os << "\n desc: " << protect(info.description())
+ << "\n validity: " << info.validity()
+ << "\n policy: " << info.policy()
+ << "\n signcount: "<< info.signCount()
+ << "\n signfirst: "<< info.signFirst()
+ << "\n signlast: " << info.signLast()
+ << "\n encrcount: "<< info.encrCount()
+ << "\n encrfirst: "<< info.encrFirst()
+ << "\n encrlast: " << info.encrLast()
+ << '\n';
+ }
+ return os << ")";
+}
diff --git a/lang/cpp/src/tofuinfo.h b/lang/cpp/src/tofuinfo.h
new file mode 100644
index 0000000..c09c82a
--- /dev/null
+++ b/lang/cpp/src/tofuinfo.h
@@ -0,0 +1,124 @@
+/*
+ tofuinfo.h - wraps gpgme tofu info
+ Copyright (C) 2016 Intevation GmbH
+
+ This file is part of GPGME++.
+
+ GPGME++ is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Library General Public
+ License as published by the Free Software Foundation; either
+ version 2 of the License, or (at your option) any later version.
+
+ GPGME++ is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU Library General Public License for more details.
+
+ You should have received a copy of the GNU Library General Public License
+ along with GPGME++; see the file COPYING.LIB. If not, write to the
+ Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+ Boston, MA 02110-1301, USA.
+*/
+
+#ifndef __GPGMEPP_TOFUINFO_H__
+#define __GPGMEPP_TOFUINFO_H__
+
+#include "gpgmepp_export.h"
+
+#include "gpgme.h"
+
+#include "global.h"
+
+#include <memory>
+
+namespace GpgME
+{
+
+class GPGMEPP_EXPORT TofuInfo
+{
+public:
+ TofuInfo();
+ explicit TofuInfo(gpgme_tofu_info_t info);
+
+ const TofuInfo &operator=(TofuInfo other)
+ {
+ swap(other);
+ return *this;
+ }
+
+ void swap(TofuInfo &other)
+ {
+ using std::swap;
+ swap(this->d, other.d);
+ }
+
+ bool isNull() const;
+
+ /* @enum Validity
+ * @brief The TOFU Validity. */
+ enum Validity : unsigned int {
+ /*! Unknown (uninitialized).*/
+ ValidityUnknown,
+ /*! TOFU Conflict.*/
+ Conflict,
+ /*! Key without history.*/
+ NoHistory,
+ /*! Key with too little history.*/
+ LittleHistory,
+ /*! Key with enough history for basic trust.*/
+ BasicHistory,
+ /*! Key with a lot of history.*/
+ LargeHistory,
+ };
+ Validity validity() const;
+
+ /* @enum Policy
+ * @brief The TOFU Validity. */
+ enum Policy : unsigned int {
+ /*! GPGME_TOFU_POLICY_NONE */
+ PolicyNone,
+ /*! GPGME_TOFU_POLICY_AUTO */
+ PolicyAuto,
+ /*! GPGME_TOFU_POLICY_GOOD */
+ PolicyGood,
+ /*! GPGME_TOFU_POLICY_UNKNOWN */
+ PolicyUnknown,
+ /*! GPGME_TOFU_POLICY_BAD */
+ PolicyBad,
+ /*! GPGME_TOFU_POLICY_ASK */
+ PolicyAsk,
+ };
+ Policy policy() const;
+
+ /* Number of signatures seen for this binding. Capped at USHRT_MAX. */
+ unsigned short signCount() const;
+
+ /* Number of encryption done to this binding. Capped at USHRT_MAX. */
+ unsigned short encrCount() const;
+
+ /** Number of seconds since epoch when the first message was verified */
+ unsigned long signFirst() const;
+
+ /** Number of seconds since epoch when the last message was verified */
+ unsigned long signLast() const;
+
+ /** Number of seconds since epoch when the first message was encrypted */
+ unsigned long encrFirst() const;
+
+ /** Number of seconds since epoch when the last message was encrypted */
+ unsigned long encrLast() const;
+
+ /* If non-NULL a human readable string summarizing the TOFU data. */
+ const char *description() const;
+
+private:
+ class Private;
+ std::shared_ptr<Private> d;
+};
+
+GPGMEPP_EXPORT std::ostream &operator<<(std::ostream &os, const TofuInfo &info);
+
+} // namespace GpgME
+
+GPGMEPP_MAKE_STD_SWAP_SPECIALIZATION(TofuInfo)
+#endif // __GPGMEPP_TOFUINFO_H__
diff --git a/lang/cpp/src/trustitem.cpp b/lang/cpp/src/trustitem.cpp
new file mode 100644
index 0000000..fc7e4a6
--- /dev/null
+++ b/lang/cpp/src/trustitem.cpp
@@ -0,0 +1,114 @@
+/*
+ trustitem.cpp - wraps a gpgme trust item
+ Copyright (C) 2003 Klarälvdalens Datakonsult AB
+
+ This file is part of GPGME.
+
+ GPGME++ is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Library General Public
+ License as published by the Free Software Foundation; either
+ version 2 of the License, or (at your option) any later version.
+
+ GPGME++ is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU Library General Public License for more details.
+
+ You should have received a copy of the GNU Library General Public License
+ along with GPGME++; see the file COPYING.LIB. If not, write to the
+ Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+ Boston, MA 02110-1301, USA.
+*/
+
+#include <trustitem.h>
+
+#include <gpgme.h>
+
+#include <cassert>
+
+namespace GpgME
+{
+
+class TrustItem::Private
+{
+public:
+ Private(gpgme_trust_item_t aItem)
+ : item(aItem)
+ {
+ }
+
+ gpgme_trust_item_t item;
+};
+
+TrustItem::TrustItem(gpgme_trust_item_t item)
+{
+ d = new Private(item);
+ if (d->item) {
+ gpgme_trust_item_ref(d->item);
+ }
+}
+
+TrustItem::TrustItem(const TrustItem &other)
+{
+ d = new Private(other.d->item);
+ if (d->item) {
+ gpgme_trust_item_ref(d->item);
+ }
+}
+
+TrustItem::~TrustItem()
+{
+ if (d->item) {
+ gpgme_trust_item_unref(d->item);
+ }
+ delete d; d = 0;
+}
+
+bool TrustItem::isNull() const
+{
+ return !d || !d->item;
+}
+
+gpgme_trust_item_t TrustItem::impl() const
+{
+ return d->item;
+}
+
+const char *TrustItem::keyID() const
+{
+ return d->item ? d->item->keyid : 0 ;
+}
+
+const char *TrustItem::userID() const
+{
+ return d->item ? d->item->name : 0 ;
+}
+
+const char *TrustItem::ownerTrustAsString() const
+{
+ return d->item ? d->item->owner_trust : 0 ;
+}
+
+const char *TrustItem::validityAsString() const
+{
+ return d->item ? d->item->validity : 0 ;
+}
+
+int TrustItem::trustLevel() const
+{
+ return d->item ? d->item->level : 0 ;
+}
+
+TrustItem::Type TrustItem::type() const
+{
+ if (!d->item) {
+ return Unknown;
+ } else {
+ return
+ d->item->type == 1 ? Key :
+ d->item->type == 2 ? UserID :
+ Unknown ;
+ }
+}
+
+} // namespace GpgME
diff --git a/lang/cpp/src/trustitem.h b/lang/cpp/src/trustitem.h
new file mode 100644
index 0000000..65f109c
--- /dev/null
+++ b/lang/cpp/src/trustitem.h
@@ -0,0 +1,81 @@
+/*
+ trustitem.h - wraps a gpgme trust item
+ Copyright (C) 2003 Klarälvdalens Datakonsult AB
+
+ This file is part of GPGME.
+
+ GPGME++ is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Library General Public
+ License as published by the Free Software Foundation; either
+ version 2 of the License, or (at your option) any later version.
+
+ GPGME++ is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU Library General Public License for more details.
+
+ You should have received a copy of the GNU Library General Public License
+ along with GPGME++; see the file COPYING.LIB. If not, write to the
+ Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+ Boston, MA 02110-1301, USA.
+*/
+
+// -*- c++ -*-
+#ifndef __GPGMEPP_TRUSTITEM_H__
+#define __GPGMEPP_TRUSTITEM_H__
+
+#include "gpgmefw.h"
+#include <key.h>
+#include "gpgmepp_export.h"
+
+#include <algorithm>
+
+namespace GpgME
+{
+
+class Context;
+
+class GPGMEPP_EXPORT TrustItem
+{
+ friend class ::GpgME::Context;
+public:
+ explicit TrustItem(gpgme_trust_item_t item = 0);
+ TrustItem(const TrustItem &other);
+ virtual ~TrustItem();
+
+ const TrustItem &operator=(TrustItem other)
+ {
+ swap(other);
+ return *this;
+ }
+
+ void swap(TrustItem &other)
+ {
+ using std::swap;
+ swap(this->d, other.d);
+ }
+
+ bool isNull() const;
+
+ const char *keyID() const;
+ const char *userID() const;
+
+ const char *ownerTrustAsString() const;
+ const char *validityAsString() const;
+
+ int trustLevel() const;
+
+ enum Type { Unknown = 0, Key = 1, UserID = 2 };
+ Type type() const;
+
+private:
+ gpgme_trust_item_t impl() const;
+ class Private;
+ Private *d;
+};
+
+} // namepace GpgME
+
+GPGMEPP_MAKE_STD_SWAP_SPECIALIZATION(TrustItem)
+
+#endif // __GPGMEPP_TRUSTITEM_H__
diff --git a/lang/cpp/src/util.h b/lang/cpp/src/util.h
new file mode 100644
index 0000000..b0d47e3
--- /dev/null
+++ b/lang/cpp/src/util.h
@@ -0,0 +1,149 @@
+/*
+ util.h - some inline helper functions
+ Copyright (C) 2004 Klarälvdalens Datakonsult AB
+
+ This file is part of GPGME++.
+
+ GPGME++ is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Library General Public
+ License as published by the Free Software Foundation; either
+ version 2 of the License, or (at your option) any later version.
+
+ GPGME++ is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU Library General Public License for more details.
+
+ You should have received a copy of the GNU Library General Public License
+ along with GPGME++; see the file COPYING.LIB. If not, write to the
+ Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+ Boston, MA 02110-1301, USA.
+*/
+
+// -*- c++ -*-
+#ifndef __GPGMEPP_UTIL_H__
+#define __GPGMEPP_UTIL_H__
+
+#include "global.h"
+#include "notation.h"
+
+#include <gpgme.h>
+
+#ifndef NDEBUG
+#include <iostream>
+#endif
+#include <sstream>
+#include <string>
+
+static inline const char *protect(const char *s)
+{
+ return s ? s : "<null>" ;
+}
+
+static inline gpgme_error_t make_error(gpgme_err_code_t code)
+{
+ return gpgme_err_make((gpgme_err_source_t)22, code);
+}
+
+static inline unsigned long to_pid(const std::string &s)
+{
+ std::stringstream ss(s);
+ unsigned int result;
+ if (ss >> result) {
+ return result;
+ } else {
+ return 0U;
+ }
+}
+
+static inline gpgme_keylist_mode_t add_to_gpgme_keylist_mode_t(unsigned int oldmode, unsigned int newmodes)
+{
+ if (newmodes & GpgME::Local) {
+ oldmode |= GPGME_KEYLIST_MODE_LOCAL;
+ }
+ if (newmodes & GpgME::Extern) {
+ oldmode |= GPGME_KEYLIST_MODE_EXTERN;
+ }
+ if (newmodes & GpgME::Signatures) {
+ oldmode |= GPGME_KEYLIST_MODE_SIGS;
+ }
+ if (newmodes & GpgME::SignatureNotations) {
+ oldmode |= GPGME_KEYLIST_MODE_SIG_NOTATIONS;
+ }
+ if (newmodes & GpgME::Ephemeral) {
+ oldmode |= GPGME_KEYLIST_MODE_EPHEMERAL;
+ }
+ if (newmodes & GpgME::Validate) {
+ oldmode |= GPGME_KEYLIST_MODE_VALIDATE;
+ }
+ if (newmodes & GpgME::WithTofu) {
+ oldmode |= GPGME_KEYLIST_MODE_WITH_TOFU;
+ }
+#ifndef NDEBUG
+ if (newmodes & ~(GpgME::Local | GpgME::Extern | GpgME::Signatures | GpgME::SignatureNotations | GpgME::Ephemeral | GpgME::Validate)) {
+ //std::cerr << "GpgME::Context: keylist mode must be one of Local, "
+ //"Extern, Signatures, SignatureNotations, or Validate, or a combination thereof!" << std::endl;
+ }
+#endif
+ return static_cast<gpgme_keylist_mode_t>(oldmode);
+}
+
+static inline unsigned int convert_from_gpgme_keylist_mode_t(unsigned int mode)
+{
+ unsigned int result = 0;
+ if (mode & GPGME_KEYLIST_MODE_LOCAL) {
+ result |= GpgME::Local;
+ }
+ if (mode & GPGME_KEYLIST_MODE_EXTERN) {
+ result |= GpgME::Extern;
+ }
+ if (mode & GPGME_KEYLIST_MODE_SIGS) {
+ result |= GpgME::Signatures;
+ }
+ if (mode & GPGME_KEYLIST_MODE_SIG_NOTATIONS) {
+ result |= GpgME::SignatureNotations;
+ }
+ if (mode & GPGME_KEYLIST_MODE_EPHEMERAL) {
+ result |= GpgME::Ephemeral;
+ }
+ if (mode & GPGME_KEYLIST_MODE_VALIDATE) {
+ result |= GpgME::Validate;
+ }
+#ifndef NDEBUG
+ if (mode & ~(GPGME_KEYLIST_MODE_LOCAL |
+ GPGME_KEYLIST_MODE_EXTERN |
+ GPGME_KEYLIST_MODE_SIG_NOTATIONS |
+ GPGME_KEYLIST_MODE_EPHEMERAL |
+ GPGME_KEYLIST_MODE_VALIDATE |
+ GPGME_KEYLIST_MODE_SIGS)) {
+ //std::cerr << "GpgME: WARNING: gpgme_get_keylist_mode() returned an unknown flag!" << std::endl;
+ }
+#endif // NDEBUG
+ return result;
+}
+
+static inline GpgME::Notation::Flags convert_from_gpgme_sig_notation_flags_t(unsigned int flags)
+{
+ unsigned int result = 0;
+ if (flags & GPGME_SIG_NOTATION_HUMAN_READABLE) {
+ result |= GpgME::Notation::HumanReadable ;
+ }
+ if (flags & GPGME_SIG_NOTATION_CRITICAL) {
+ result |= GpgME::Notation::Critical ;
+ }
+ return static_cast<GpgME::Notation::Flags>(result);
+}
+
+static inline gpgme_sig_notation_flags_t add_to_gpgme_sig_notation_flags_t(unsigned int oldflags, unsigned int newflags)
+{
+ unsigned int result = oldflags;
+ if (newflags & GpgME::Notation::HumanReadable) {
+ result |= GPGME_SIG_NOTATION_HUMAN_READABLE;
+ }
+ if (newflags & GpgME::Notation::Critical) {
+ result |= GPGME_SIG_NOTATION_CRITICAL;
+ }
+ return static_cast<gpgme_sig_notation_flags_t>(result);
+}
+
+#endif // __GPGMEPP_UTIL_H__
diff --git a/lang/cpp/src/verificationresult.cpp b/lang/cpp/src/verificationresult.cpp
new file mode 100644
index 0000000..c62625d
--- /dev/null
+++ b/lang/cpp/src/verificationresult.cpp
@@ -0,0 +1,575 @@
+/*
+ verificationresult.cpp - wraps a gpgme verify result
+ Copyright (C) 2004 Klarälvdalens Datakonsult AB
+
+ This file is part of GPGME++.
+
+ GPGME++ is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Library General Public
+ License as published by the Free Software Foundation; either
+ version 2 of the License, or (at your option) any later version.
+
+ GPGME++ is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU Library General Public License for more details.
+
+ You should have received a copy of the GNU Library General Public License
+ along with GPGME++; see the file COPYING.LIB. If not, write to the
+ Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+ Boston, MA 02110-1301, USA.
+*/
+
+#include <verificationresult.h>
+#include <notation.h>
+#include "result_p.h"
+#include "util.h"
+#include "key.h"
+
+#include <gpgme.h>
+
+#include <istream>
+#include <algorithm>
+#include <iterator>
+#include <string>
+#include <cstring>
+#include <cstdlib>
+
+#include <string.h>
+
+class GpgME::VerificationResult::Private
+{
+public:
+ explicit Private(const gpgme_verify_result_t r)
+ {
+ if (!r) {
+ return;
+ }
+ if (r->file_name) {
+ file_name = r->file_name;
+ }
+ // copy recursively, using compiler-generated copy ctor.
+ // We just need to handle the pointers in the structs:
+ for (gpgme_signature_t is = r->signatures ; is ; is = is->next) {
+ gpgme_signature_t scopy = new _gpgme_signature(*is);
+ if (is->fpr) {
+ scopy->fpr = strdup(is->fpr);
+ }
+// PENDING(marc) why does this crash on Windows in strdup()?
+# ifndef _WIN32
+ if (is->pka_address) {
+ scopy->pka_address = strdup(is->pka_address);
+ }
+# else
+ scopy->pka_address = 0;
+# endif
+ scopy->next = 0;
+ sigs.push_back(scopy);
+ // copy keys
+ if (scopy->key) {
+ keys.push_back(Key(scopy->key, true));
+ }
+ // copy notations:
+ nota.push_back(std::vector<Nota>());
+ purls.push_back(0);
+ for (gpgme_sig_notation_t in = is->notations ; in ; in = in->next) {
+ if (!in->name) {
+ if (in->value) {
+ purls.back() = strdup(in->value); // policy url
+ }
+ continue;
+ }
+ Nota n = { 0, 0, in->flags };
+ n.name = strdup(in->name);
+ if (in->value) {
+ n.value = strdup(in->value);
+ }
+ nota.back().push_back(n);
+ }
+ }
+ }
+ ~Private()
+ {
+ for (std::vector<gpgme_signature_t>::iterator it = sigs.begin() ; it != sigs.end() ; ++it) {
+ std::free((*it)->fpr);
+ std::free((*it)->pka_address);
+ delete *it; *it = 0;
+ }
+ for (std::vector< std::vector<Nota> >::iterator it = nota.begin() ; it != nota.end() ; ++it) {
+ for (std::vector<Nota>::iterator jt = it->begin() ; jt != it->end() ; ++jt) {
+ std::free(jt->name); jt->name = 0;
+ std::free(jt->value); jt->value = 0;
+ }
+ }
+ std::for_each(purls.begin(), purls.end(), &std::free);
+ }
+
+ struct Nota {
+ char *name;
+ char *value;
+ gpgme_sig_notation_flags_t flags;
+ };
+
+ std::vector<gpgme_signature_t> sigs;
+ std::vector< std::vector<Nota> > nota;
+ std::vector<GpgME::Key> keys;
+ std::vector<char *> purls;
+ std::string file_name;
+};
+
+GpgME::VerificationResult::VerificationResult(gpgme_ctx_t ctx, int error)
+ : GpgME::Result(error), d()
+{
+ init(ctx);
+}
+
+GpgME::VerificationResult::VerificationResult(gpgme_ctx_t ctx, const Error &error)
+ : GpgME::Result(error), d()
+{
+ init(ctx);
+}
+
+void GpgME::VerificationResult::init(gpgme_ctx_t ctx)
+{
+ if (!ctx) {
+ return;
+ }
+ gpgme_verify_result_t res = gpgme_op_verify_result(ctx);
+ if (!res) {
+ return;
+ }
+ d.reset(new Private(res));
+}
+
+make_standard_stuff(VerificationResult)
+
+const char *GpgME::VerificationResult::fileName() const
+{
+ return d ? d->file_name.c_str() : 0 ;
+}
+
+unsigned int GpgME::VerificationResult::numSignatures() const
+{
+ return d ? d->sigs.size() : 0 ;
+}
+
+GpgME::Signature GpgME::VerificationResult::signature(unsigned int idx) const
+{
+ return Signature(d, idx);
+}
+
+std::vector<GpgME::Signature> GpgME::VerificationResult::signatures() const
+{
+ if (!d) {
+ return std::vector<Signature>();
+ }
+ std::vector<Signature> result;
+ result.reserve(d->sigs.size());
+ for (unsigned int i = 0 ; i < d->sigs.size() ; ++i) {
+ result.push_back(Signature(d, i));
+ }
+ return result;
+}
+
+GpgME::Signature::Signature(const std::shared_ptr<VerificationResult::Private> &parent, unsigned int i)
+ : d(parent), idx(i)
+{
+}
+
+GpgME::Signature::Signature() : d(), idx(0) {}
+
+bool GpgME::Signature::isNull() const
+{
+ return !d || idx >= d->sigs.size() ;
+}
+
+GpgME::Signature::Summary GpgME::Signature::summary() const
+{
+ if (isNull()) {
+ return None;
+ }
+ gpgme_sigsum_t sigsum = d->sigs[idx]->summary;
+ unsigned int result = 0;
+ if (sigsum & GPGME_SIGSUM_VALID) {
+ result |= Valid;
+ }
+ if (sigsum & GPGME_SIGSUM_GREEN) {
+ result |= Green;
+ }
+ if (sigsum & GPGME_SIGSUM_RED) {
+ result |= Red;
+ }
+ if (sigsum & GPGME_SIGSUM_KEY_REVOKED) {
+ result |= KeyRevoked;
+ }
+ if (sigsum & GPGME_SIGSUM_KEY_EXPIRED) {
+ result |= KeyExpired;
+ }
+ if (sigsum & GPGME_SIGSUM_SIG_EXPIRED) {
+ result |= SigExpired;
+ }
+ if (sigsum & GPGME_SIGSUM_KEY_MISSING) {
+ result |= KeyMissing;
+ }
+ if (sigsum & GPGME_SIGSUM_CRL_MISSING) {
+ result |= CrlMissing;
+ }
+ if (sigsum & GPGME_SIGSUM_CRL_TOO_OLD) {
+ result |= CrlTooOld;
+ }
+ if (sigsum & GPGME_SIGSUM_BAD_POLICY) {
+ result |= BadPolicy;
+ }
+ if (sigsum & GPGME_SIGSUM_SYS_ERROR) {
+ result |= SysError;
+ }
+ if (sigsum & GPGME_SIGSUM_TOFU_CONFLICT) {
+ result |= TofuConflict;
+ }
+ return static_cast<Summary>(result);
+}
+
+const char *GpgME::Signature::fingerprint() const
+{
+ return isNull() ? 0 : d->sigs[idx]->fpr ;
+}
+
+GpgME::Error GpgME::Signature::status() const
+{
+ return Error(isNull() ? 0 : d->sigs[idx]->status);
+}
+
+time_t GpgME::Signature::creationTime() const
+{
+ return static_cast<time_t>(isNull() ? 0 : d->sigs[idx]->timestamp);
+}
+
+time_t GpgME::Signature::expirationTime() const
+{
+ return static_cast<time_t>(isNull() ? 0 : d->sigs[idx]->exp_timestamp);
+}
+
+bool GpgME::Signature::neverExpires() const
+{
+ return expirationTime() == (time_t)0;
+}
+
+bool GpgME::Signature::isWrongKeyUsage() const
+{
+ return !isNull() && d->sigs[idx]->wrong_key_usage;
+}
+
+bool GpgME::Signature::isVerifiedUsingChainModel() const
+{
+ return !isNull() && d->sigs[idx]->chain_model;
+}
+
+GpgME::Signature::PKAStatus GpgME::Signature::pkaStatus() const
+{
+ if (!isNull()) {
+ return static_cast<PKAStatus>(d->sigs[idx]->pka_trust);
+ }
+ return UnknownPKAStatus;
+}
+
+const char *GpgME::Signature::pkaAddress() const
+{
+ if (!isNull()) {
+ return d->sigs[idx]->pka_address;
+ }
+ return 0;
+}
+
+GpgME::Signature::Validity GpgME::Signature::validity() const
+{
+ if (isNull()) {
+ return Unknown;
+ }
+ switch (d->sigs[idx]->validity) {
+ default:
+ case GPGME_VALIDITY_UNKNOWN: return Unknown;
+ case GPGME_VALIDITY_UNDEFINED: return Undefined;
+ case GPGME_VALIDITY_NEVER: return Never;
+ case GPGME_VALIDITY_MARGINAL: return Marginal;
+ case GPGME_VALIDITY_FULL: return Full;
+ case GPGME_VALIDITY_ULTIMATE: return Ultimate;
+ }
+}
+
+char GpgME::Signature::validityAsString() const
+{
+ if (isNull()) {
+ return '?';
+ }
+ switch (d->sigs[idx]->validity) {
+ default:
+ case GPGME_VALIDITY_UNKNOWN: return '?';
+ case GPGME_VALIDITY_UNDEFINED: return 'q';
+ case GPGME_VALIDITY_NEVER: return 'n';
+ case GPGME_VALIDITY_MARGINAL: return 'm';
+ case GPGME_VALIDITY_FULL: return 'f';
+ case GPGME_VALIDITY_ULTIMATE: return 'u';
+ }
+}
+
+GpgME::Error GpgME::Signature::nonValidityReason() const
+{
+ return Error(isNull() ? 0 : d->sigs[idx]->validity_reason);
+}
+
+unsigned int GpgME::Signature::publicKeyAlgorithm() const
+{
+ if (!isNull()) {
+ return d->sigs[idx]->pubkey_algo;
+ }
+ return 0;
+}
+
+const char *GpgME::Signature::publicKeyAlgorithmAsString() const
+{
+ if (!isNull()) {
+ return gpgme_pubkey_algo_name(d->sigs[idx]->pubkey_algo);
+ }
+ return 0;
+}
+
+unsigned int GpgME::Signature::hashAlgorithm() const
+{
+ if (!isNull()) {
+ return d->sigs[idx]->hash_algo;
+ }
+ return 0;
+}
+
+const char *GpgME::Signature::hashAlgorithmAsString() const
+{
+ if (!isNull()) {
+ return gpgme_hash_algo_name(d->sigs[idx]->hash_algo);
+ }
+ return 0;
+}
+
+const char *GpgME::Signature::policyURL() const
+{
+ return isNull() ? 0 : d->purls[idx] ;
+}
+
+GpgME::Notation GpgME::Signature::notation(unsigned int nidx) const
+{
+ return GpgME::Notation(d, idx, nidx);
+}
+
+std::vector<GpgME::Notation> GpgME::Signature::notations() const
+{
+ if (isNull()) {
+ return std::vector<GpgME::Notation>();
+ }
+ std::vector<GpgME::Notation> result;
+ result.reserve(d->nota[idx].size());
+ for (unsigned int i = 0 ; i < d->nota[idx].size() ; ++i) {
+ result.push_back(GpgME::Notation(d, idx, i));
+ }
+ return result;
+}
+
+GpgME::Key GpgME::Signature::key() const
+{
+ if (isNull()) {
+ return Key();
+ }
+ return d->keys[idx];
+}
+
+class GpgME::Notation::Private
+{
+public:
+ Private() : d(), sidx(0), nidx(0), nota(0) {}
+ Private(const std::shared_ptr<VerificationResult::Private> &priv, unsigned int sindex, unsigned int nindex)
+ : d(priv), sidx(sindex), nidx(nindex), nota(0)
+ {
+
+ }
+ Private(gpgme_sig_notation_t n)
+ : d(), sidx(0), nidx(0), nota(n ? new _gpgme_sig_notation(*n) : 0)
+ {
+ if (nota && nota->name) {
+ nota->name = strdup(nota->name);
+ }
+ if (nota && nota->value) {
+ nota->value = strdup(nota->value);
+ }
+ }
+ Private(const Private &other)
+ : d(other.d), sidx(other.sidx), nidx(other.nidx), nota(other.nota)
+ {
+ if (nota) {
+ nota->name = strdup(nota->name);
+ nota->value = strdup(nota->value);
+ }
+ }
+ ~Private()
+ {
+ if (nota) {
+ std::free(nota->name); nota->name = 0;
+ std::free(nota->value); nota->value = 0;
+ delete nota;
+ }
+ }
+
+ std::shared_ptr<VerificationResult::Private> d;
+ unsigned int sidx, nidx;
+ gpgme_sig_notation_t nota;
+};
+
+GpgME::Notation::Notation(const std::shared_ptr<VerificationResult::Private> &parent, unsigned int sindex, unsigned int nindex)
+ : d(new Private(parent, sindex, nindex))
+{
+
+}
+
+GpgME::Notation::Notation(gpgme_sig_notation_t nota)
+ : d(new Private(nota))
+{
+
+}
+
+GpgME::Notation::Notation() : d() {}
+
+bool GpgME::Notation::isNull() const
+{
+ if (!d) {
+ return true;
+ }
+ if (d->d) {
+ return d->sidx >= d->d->nota.size() || d->nidx >= d->d->nota[d->sidx].size() ;
+ }
+ return !d->nota;
+}
+
+const char *GpgME::Notation::name() const
+{
+ return
+ isNull() ? 0 :
+ d->d ? d->d->nota[d->sidx][d->nidx].name :
+ d->nota ? d->nota->name : 0 ;
+}
+
+const char *GpgME::Notation::value() const
+{
+ return
+ isNull() ? 0 :
+ d->d ? d->d->nota[d->sidx][d->nidx].value :
+ d->nota ? d->nota->value : 0 ;
+}
+
+GpgME::Notation::Flags GpgME::Notation::flags() const
+{
+ return
+ convert_from_gpgme_sig_notation_flags_t(
+ isNull() ? 0 :
+ d->d ? d->d->nota[d->sidx][d->nidx].flags :
+ d->nota ? d->nota->flags : 0);
+}
+
+bool GpgME::Notation::isHumanReadable() const
+{
+ return flags() & HumanReadable;
+}
+
+bool GpgME::Notation::isCritical() const
+{
+ return flags() & Critical;
+}
+
+std::ostream &GpgME::operator<<(std::ostream &os, const VerificationResult &result)
+{
+ os << "GpgME::VerificationResult(";
+ if (!result.isNull()) {
+ os << "\n error: " << result.error()
+ << "\n fileName: " << protect(result.fileName())
+ << "\n signatures:\n";
+ const std::vector<Signature> sigs = result.signatures();
+ std::copy(sigs.begin(), sigs.end(),
+ std::ostream_iterator<Signature>(os, "\n"));
+ }
+ return os << ')';
+}
+
+std::ostream &GpgME::operator<<(std::ostream &os, Signature::PKAStatus pkaStatus)
+{
+#define OUTPUT( x ) if ( !(pkaStatus & (GpgME::Signature:: x)) ) {} else do { os << #x " "; } while(0)
+ os << "GpgME::Signature::PKAStatus(";
+ OUTPUT(UnknownPKAStatus);
+ OUTPUT(PKAVerificationFailed);
+ OUTPUT(PKAVerificationSucceeded);
+#undef OUTPUT
+ return os << ')';
+}
+
+std::ostream &GpgME::operator<<(std::ostream &os, Signature::Summary summary)
+{
+#define OUTPUT( x ) if ( !(summary & (GpgME::Signature:: x)) ) {} else do { os << #x " "; } while(0)
+ os << "GpgME::Signature::Summary(";
+ OUTPUT(Valid);
+ OUTPUT(Green);
+ OUTPUT(Red);
+ OUTPUT(KeyRevoked);
+ OUTPUT(KeyExpired);
+ OUTPUT(SigExpired);
+ OUTPUT(KeyMissing);
+ OUTPUT(CrlMissing);
+ OUTPUT(CrlTooOld);
+ OUTPUT(BadPolicy);
+ OUTPUT(SysError);
+ OUTPUT(TofuConflict);
+#undef OUTPUT
+ return os << ')';
+}
+
+std::ostream &GpgME::operator<<(std::ostream &os, const Signature &sig)
+{
+ os << "GpgME::Signature(";
+ if (!sig.isNull()) {
+ os << "\n Summary: " << sig.summary()
+ << "\n Fingerprint: " << protect(sig.fingerprint())
+ << "\n Status: " << sig.status()
+ << "\n creationTime: " << sig.creationTime()
+ << "\n expirationTime: " << sig.expirationTime()
+ << "\n isWrongKeyUsage: " << sig.isWrongKeyUsage()
+ << "\n isVerifiedUsingChainModel: " << sig.isVerifiedUsingChainModel()
+ << "\n pkaStatus: " << sig.pkaStatus()
+ << "\n pkaAddress: " << protect(sig.pkaAddress())
+ << "\n validity: " << sig.validityAsString()
+ << "\n nonValidityReason: " << sig.nonValidityReason()
+ << "\n publicKeyAlgorithm: " << protect(sig.publicKeyAlgorithmAsString())
+ << "\n hashAlgorithm: " << protect(sig.hashAlgorithmAsString())
+ << "\n policyURL: " << protect(sig.policyURL())
+ << "\n notations:\n";
+ const std::vector<Notation> nota = sig.notations();
+ std::copy(nota.begin(), nota.end(),
+ std::ostream_iterator<Notation>(os, "\n"));
+ }
+ return os << ')';
+}
+
+std::ostream &GpgME::operator<<(std::ostream &os, Notation::Flags flags)
+{
+ os << "GpgME::Notation::Flags(";
+#define OUTPUT( x ) if ( !(flags & (GpgME::Notation:: x)) ) {} else do { os << #x " "; } while(0)
+ OUTPUT(HumanReadable);
+ OUTPUT(Critical);
+#undef OUTPUT
+ return os << ')';
+}
+
+std::ostream &GpgME::operator<<(std::ostream &os, const Notation &nota)
+{
+ os << "GpgME::Signature::Notation(";
+ if (!nota.isNull()) {
+ os << "\n name: " << protect(nota.name())
+ << "\n value: " << protect(nota.value())
+ << "\n flags: " << nota.flags()
+ << '\n';
+ }
+ return os << ")";
+}
diff --git a/lang/cpp/src/verificationresult.h b/lang/cpp/src/verificationresult.h
new file mode 100644
index 0000000..93288af
--- /dev/null
+++ b/lang/cpp/src/verificationresult.h
@@ -0,0 +1,180 @@
+/*
+ verificationresult.h - wraps a gpgme verify result
+ Copyright (C) 2004 Klarälvdalens Datakonsult AB
+
+ This file is part of GPGME++.
+
+ GPGME++ is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Library General Public
+ License as published by the Free Software Foundation; either
+ version 2 of the License, or (at your option) any later version.
+
+ GPGME++ is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU Library General Public License for more details.
+
+ You should have received a copy of the GNU Library General Public License
+ along with GPGME++; see the file COPYING.LIB. If not, write to the
+ Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+ Boston, MA 02110-1301, USA.
+*/
+
+#ifndef __GPGMEPP_VERIFICATIONRESULT_H__
+#define __GPGMEPP_VERIFICATIONRESULT_H__
+
+#include "gpgmefw.h"
+#include "result.h"
+#include "gpgmepp_export.h"
+
+#include <time.h>
+
+#include <memory>
+
+#include <vector>
+#include <iosfwd>
+
+namespace GpgME
+{
+
+class Error;
+class Signature;
+class Notation;
+class Key;
+
+class GPGMEPP_EXPORT VerificationResult : public Result
+{
+public:
+ VerificationResult();
+ VerificationResult(gpgme_ctx_t ctx, int error);
+ VerificationResult(gpgme_ctx_t ctx, const Error &error);
+ explicit VerificationResult(const Error &err);
+
+ const VerificationResult &operator=(VerificationResult other)
+ {
+ swap(other);
+ return *this;
+ }
+
+ void swap(VerificationResult &other)
+ {
+ Result::swap(other);
+ using std::swap;
+ swap(this->d, other.d);
+ }
+
+ bool isNull() const;
+
+ const char *fileName() const;
+
+ unsigned int numSignatures() const;
+ Signature signature(unsigned int index) const;
+ std::vector<Signature> signatures() const;
+
+ class Private;
+private:
+ void init(gpgme_ctx_t ctx);
+ std::shared_ptr<Private> d;
+};
+
+GPGMEPP_EXPORT std::ostream &operator<<(std::ostream &os, const VerificationResult &result);
+
+class GPGMEPP_EXPORT Signature
+{
+ friend class ::GpgME::VerificationResult;
+ Signature(const std::shared_ptr<VerificationResult::Private> &parent, unsigned int index);
+public:
+ typedef GPGMEPP_DEPRECATED GpgME::Notation Notation;
+
+ Signature();
+
+ const Signature &operator=(Signature other)
+ {
+ swap(other);
+ return *this;
+ }
+
+ void swap(Signature &other)
+ {
+ using std::swap;
+ swap(this->d, other.d);
+ swap(this->idx, other.idx);
+ }
+
+ bool isNull() const;
+
+ enum Summary {
+ None = 0x000,
+ Valid = 0x001,
+ Green = 0x002,
+ Red = 0x004,
+ KeyRevoked = 0x008,
+ KeyExpired = 0x010,
+ SigExpired = 0x020,
+ KeyMissing = 0x040,
+ CrlMissing = 0x080,
+ CrlTooOld = 0x100,
+ BadPolicy = 0x200,
+ SysError = 0x400,
+ TofuConflict= 0x800
+ };
+ Summary summary() const;
+
+ const char *fingerprint() const;
+
+ Error status() const;
+
+ time_t creationTime() const;
+ time_t expirationTime() const;
+ bool neverExpires() const;
+
+ GPGMEPP_DEPRECATED bool wrongKeyUsage() const
+ {
+ return isWrongKeyUsage();
+ }
+ bool isWrongKeyUsage() const;
+ bool isVerifiedUsingChainModel() const;
+
+ enum PKAStatus {
+ UnknownPKAStatus, PKAVerificationFailed, PKAVerificationSucceeded
+ };
+ PKAStatus pkaStatus() const;
+ const char *pkaAddress() const;
+
+ enum Validity {
+ Unknown, Undefined, Never, Marginal, Full, Ultimate
+ };
+ Validity validity() const;
+ char validityAsString() const;
+ Error nonValidityReason() const;
+
+ unsigned int publicKeyAlgorithm() const;
+ const char *publicKeyAlgorithmAsString() const;
+
+ unsigned int hashAlgorithm() const;
+ const char *hashAlgorithmAsString() const;
+
+ const char *policyURL() const;
+ GpgME::Notation notation(unsigned int index) const;
+ std::vector<GpgME::Notation> notations() const;
+
+ /** Returns the key object associated with this signature.
+ * May be incomplete but will have at least the fingerprint
+ * set or the associated TOFU Information if applicable. */
+ GpgME::Key key() const;
+
+private:
+ std::shared_ptr<VerificationResult::Private> d;
+ unsigned int idx;
+};
+
+GPGMEPP_EXPORT std::ostream &operator<<(std::ostream &os, const Signature &sig);
+GPGMEPP_EXPORT std::ostream &operator<<(std::ostream &os, Signature::PKAStatus pkaStatus);
+GPGMEPP_EXPORT std::ostream &operator<<(std::ostream &os, Signature::Summary summary);
+
+}
+
+GPGMEPP_MAKE_STD_SWAP_SPECIALIZATION(VerificationResult)
+GPGMEPP_MAKE_STD_SWAP_SPECIALIZATION(Signature)
+
+#endif // __GPGMEPP_VERIFICATIONRESULT_H__
diff --git a/lang/cpp/src/vfsmountresult.cpp b/lang/cpp/src/vfsmountresult.cpp
new file mode 100644
index 0000000..c9fdd5e
--- /dev/null
+++ b/lang/cpp/src/vfsmountresult.cpp
@@ -0,0 +1,90 @@
+/*
+ vfsmountresult.cpp - wraps a gpgme vfs mount result
+ Copyright (C) 2009 Klarälvdalens Datakonsult AB <info@kdab.com>
+ Author: Marc Mutz <marc@kdab.com>, Volker Krause <volker@kdab.com>
+
+ This file is part of GPGME++.
+
+ GPGME++ is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Library General Public
+ License as published by the Free Software Foundation; either
+ version 2 of the License, or (at your option) any later version.
+
+ GPGME++ is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU Library General Public License for more details.
+
+ You should have received a copy of the GNU Library General Public License
+ along with GPGME++; see the file COPYING.LIB. If not, write to the
+ Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+ Boston, MA 02110-1301, USA.
+*/
+
+#include <vfsmountresult.h>
+#include "result_p.h"
+
+#include <gpgme.h>
+
+#include <istream>
+#include <string.h>
+
+using namespace GpgME;
+
+class VfsMountResult::Private
+{
+public:
+ explicit Private(const gpgme_vfs_mount_result_t r) : mountDir(0)
+ {
+ if (r && r->mount_dir) {
+ mountDir = strdup(r->mount_dir);
+ }
+ }
+
+ ~Private()
+ {
+ std::free(mountDir);
+ }
+
+ char *mountDir;
+};
+
+VfsMountResult::VfsMountResult(gpgme_ctx_t ctx, const Error &error, const Error &opError)
+ : Result(error ? error : opError), d()
+{
+ init(ctx);
+}
+
+void VfsMountResult::init(gpgme_ctx_t ctx)
+{
+ (void)ctx;
+ if (!ctx) {
+ return;
+ }
+ gpgme_vfs_mount_result_t res = gpgme_op_vfs_mount_result(ctx);
+ if (!res) {
+ return;
+ }
+ d.reset(new Private(res));
+}
+
+make_standard_stuff(VfsMountResult)
+
+const char *VfsMountResult::mountDir() const
+{
+ if (d) {
+ return d->mountDir;
+ }
+ return 0;
+}
+
+std::ostream &GpgME::operator<<(std::ostream &os, const VfsMountResult &result)
+{
+ os << "GpgME::VfsMountResult(";
+ if (!result.isNull()) {
+ os << "\n error: " << result.error()
+ << "\n mount dir: " << result.mountDir()
+ << "\n";
+ }
+ return os << ')';
+}
diff --git a/lang/cpp/src/vfsmountresult.h b/lang/cpp/src/vfsmountresult.h
new file mode 100644
index 0000000..b46eeb1
--- /dev/null
+++ b/lang/cpp/src/vfsmountresult.h
@@ -0,0 +1,76 @@
+/*
+ vfsmountresult.h - wraps a gpgme vfs mount result
+ Copyright (C) 2009 Klarälvdalens Datakonsult AB <info@kdab.com>
+ Author: Marc Mutz <marc@kdab.com>, Volker Krause <volker@kdab.com>
+
+ This file is part of GPGME++.
+
+ GPGME++ is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Library General Public
+ License as published by the Free Software Foundation; either
+ version 2 of the License, or (at your option) any later version.
+
+ GPGME++ is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU Library General Public License for more details.
+
+ You should have received a copy of the GNU Library General Public License
+ along with GPGME++; see the file COPYING.LIB. If not, write to the
+ Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+ Boston, MA 02110-1301, USA.
+*/
+
+#ifndef __GPGMEPP_VFSMOUNTRESULT_H__
+#define __GPGMEPP_VFSMOUNTRESULT_H__
+
+#include "gpgmefw.h"
+#include "result.h"
+#include "gpgmepp_export.h"
+
+#include <memory>
+
+#include <vector>
+#include <iosfwd>
+
+namespace GpgME
+{
+
+class Error;
+
+class GPGMEPP_EXPORT VfsMountResult : public Result
+{
+public:
+ VfsMountResult();
+ VfsMountResult(gpgme_ctx_t ctx, const Error &error, const Error &opError);
+ explicit VfsMountResult(const Error &err);
+
+ const VfsMountResult &operator=(VfsMountResult other)
+ {
+ swap(other);
+ return *this;
+ }
+
+ void swap(VfsMountResult &other)
+ {
+ Result::swap(other);
+ using std::swap;
+ swap(this->d, other.d);
+ }
+
+ bool isNull() const;
+ const char *mountDir() const;
+
+ class Private;
+private:
+ void init(gpgme_ctx_t ctx);
+ std::shared_ptr<Private> d;
+};
+
+GPGMEPP_EXPORT std::ostream &operator<<(std::ostream &os, const VfsMountResult &result);
+
+}
+
+GPGMEPP_MAKE_STD_SWAP_SPECIALIZATION(VfsMountResult)
+
+#endif // __GPGMEPP_VFSMOUNTRESULT_H__
diff --git a/lang/python/MANIFEST.in b/lang/python/MANIFEST.in
new file mode 100644
index 0000000..eefdb83
--- /dev/null
+++ b/lang/python/MANIFEST.in
@@ -0,0 +1,4 @@
+recursive-include examples *.py
+include gpgme-h-clean.py gpgme.i
+include helpers.c helpers.h private.h
+recursive-include pyme *.py
diff --git a/lang/python/Makefile.am b/lang/python/Makefile.am
new file mode 100644
index 0000000..2271ce0
--- /dev/null
+++ b/lang/python/Makefile.am
@@ -0,0 +1,106 @@
+# Makefile.am for the Python bindings.
+# Copyright (C) 2016 g10 Code GmbH
+#
+# This file is part of GPGME.
+#
+# GPGME is free software; you can redistribute it and/or modify it
+# under the terms of the GNU Lesser General Public License as
+# published by the Free Software Foundation; either version 2.1 of the
+# License, or (at your option) any later version.
+#
+# GPGME is distributed in the hope that it will be useful, but WITHOUT
+# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
+# or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General
+# Public License for more details.
+#
+# You should have received a copy of the GNU Lesser General Public
+# License along with this program; if not, see <http://www.gnu.org/licenses/>.
+
+EXTRA_DIST = \
+ README \
+ MANIFEST.in \
+ gpgme.i \
+ helpers.c helpers.h private.h \
+ gpgme-h-clean.py \
+ examples \
+ pyme
+
+SUBDIRS = . tests
+
+COPY_FILES = \
+ $(srcdir)/gpgme.i \
+ $(srcdir)/README \
+ $(srcdir)/MANIFEST.in \
+ $(srcdir)/gpgme-h-clean.py \
+ $(srcdir)/examples \
+ $(srcdir)/helpers.c $(srcdir)/helpers.h $(srcdir)/private.h
+
+COPY_FILES_PYME = \
+ $(srcdir)/pyme/callbacks.py \
+ $(srcdir)/pyme/constants \
+ $(srcdir)/pyme/core.py \
+ $(srcdir)/pyme/errors.py \
+ $(srcdir)/pyme/__init__.py \
+ $(srcdir)/pyme/results.py \
+ $(srcdir)/pyme/util.py
+
+# For VPATH builds we need to copy some files because Python's
+# distutils are not VPATH-aware.
+copystamp: $(COPY_FILES) $(COPY_FILES_PYME)
+ if test "$(srcdir)" != "$(builddir)" ; then \
+ cp -R $(COPY_FILES) . ; \
+ cp -R $(COPY_FILES_PYME) pyme ; \
+ fi
+ touch $@
+
+all-local: copystamp
+ for PYTHON in $(PYTHONS); do \
+ CFLAGS="$(CFLAGS) -I$(top_srcdir)" \
+ $$PYTHON setup.py build --verbose ; \
+ done
+
+dist/pyme3-$(VERSION).tar.gz dist/pyme3-$(VERSION).tar.gz.asc: copystamp
+ CFLAGS="$(CFLAGS) -I$(top_srcdir)" \
+ $(PYTHON) setup.py sdist --verbose
+ gpg2 --detach-sign --armor dist/pyme3-$(VERSION).tar.gz
+
+.PHONY: sdist
+sdist: dist/pyme3-$(VERSION).tar.gz dist/pyme3-$(VERSION).tar.gz.asc
+
+.PHONY: upload
+upload: dist/pyme3-$(VERSION).tar.gz dist/pyme3-$(VERSION).tar.gz.asc
+ twine upload $^
+
+CLEANFILES = gpgme.h errors.i gpgme_wrap.c pyme/gpgme.py \
+ copystamp
+
+# Remove the rest.
+#
+# 'make distclean' clears the write bit, breaking rm -rf. Fix the
+# permissions.
+clean-local:
+ rm -rf -- build
+ if test "$(srcdir)" != "$(builddir)" ; then \
+ find . -type d ! -perm -200 -exec chmod u+w {} ';' ; \
+ for F in $(COPY_FILES); do rm -rf -- `basename $$F` ; done ; \
+ for F in $(COPY_FILES_PYME); do \
+ rm -rf -- pyme/`basename $$F` ; \
+ done ; \
+ fi
+
+install-exec-local:
+ rm -f install_files.txt
+ for PYTHON in $(PYTHONS); do \
+ $$PYTHON setup.py install \
+ --prefix $(DESTDIR)$(prefix) \
+ --record files.txt \
+ --verbose ; \
+ cat files.txt >> install_files.txt ; \
+ rm files.txt ; \
+ done
+ $(MKDIR_P) $(DESTDIR)$(pythondir)/pyme
+ mv install_files.txt $(DESTDIR)$(pythondir)/pyme
+
+uninstall-local:
+ xargs <$(DESTDIR)$(pythondir)/pyme/install_files.txt -- rm -rf --
+ rm -rf -- $(DESTDIR)$(pythondir)/pyme
diff --git a/lang/python/Makefile.in b/lang/python/Makefile.in
new file mode 100644
index 0000000..6e6cfe6
--- /dev/null
+++ b/lang/python/Makefile.in
@@ -0,0 +1,798 @@
+# Makefile.in generated by automake 1.14.1 from Makefile.am.
+# @configure_input@
+
+# Copyright (C) 1994-2013 Free Software Foundation, Inc.
+
+# This Makefile.in is free software; the Free Software Foundation
+# gives unlimited permission to copy and/or distribute it,
+# with or without modifications, as long as this notice is preserved.
+
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY, to the extent permitted by law; without
+# even the implied warranty of MERCHANTABILITY or FITNESS FOR A
+# PARTICULAR PURPOSE.
+
+@SET_MAKE@
+
+# Makefile.am for the Python bindings.
+# Copyright (C) 2016 g10 Code GmbH
+#
+# This file is part of GPGME.
+#
+# GPGME is free software; you can redistribute it and/or modify it
+# under the terms of the GNU Lesser General Public License as
+# published by the Free Software Foundation; either version 2.1 of the
+# License, or (at your option) any later version.
+#
+# GPGME is distributed in the hope that it will be useful, but WITHOUT
+# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
+# or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General
+# Public License for more details.
+#
+# You should have received a copy of the GNU Lesser General Public
+# License along with this program; if not, see <http://www.gnu.org/licenses/>.
+VPATH = @srcdir@
+am__is_gnu_make = test -n '$(MAKEFILE_LIST)' && test -n '$(MAKELEVEL)'
+am__make_running_with_option = \
+ case $${target_option-} in \
+ ?) ;; \
+ *) echo "am__make_running_with_option: internal error: invalid" \
+ "target option '$${target_option-}' specified" >&2; \
+ exit 1;; \
+ esac; \
+ has_opt=no; \
+ sane_makeflags=$$MAKEFLAGS; \
+ if $(am__is_gnu_make); then \
+ sane_makeflags=$$MFLAGS; \
+ else \
+ case $$MAKEFLAGS in \
+ *\\[\ \ ]*) \
+ bs=\\; \
+ sane_makeflags=`printf '%s\n' "$$MAKEFLAGS" \
+ | sed "s/$$bs$$bs[$$bs $$bs ]*//g"`;; \
+ esac; \
+ fi; \
+ skip_next=no; \
+ strip_trailopt () \
+ { \
+ flg=`printf '%s\n' "$$flg" | sed "s/$$1.*$$//"`; \
+ }; \
+ for flg in $$sane_makeflags; do \
+ test $$skip_next = yes && { skip_next=no; continue; }; \
+ case $$flg in \
+ *=*|--*) continue;; \
+ -*I) strip_trailopt 'I'; skip_next=yes;; \
+ -*I?*) strip_trailopt 'I';; \
+ -*O) strip_trailopt 'O'; skip_next=yes;; \
+ -*O?*) strip_trailopt 'O';; \
+ -*l) strip_trailopt 'l'; skip_next=yes;; \
+ -*l?*) strip_trailopt 'l';; \
+ -[dEDm]) skip_next=yes;; \
+ -[JT]) skip_next=yes;; \
+ esac; \
+ case $$flg in \
+ *$$target_option*) has_opt=yes; break;; \
+ esac; \
+ done; \
+ test $$has_opt = yes
+am__make_dryrun = (target_option=n; $(am__make_running_with_option))
+am__make_keepgoing = (target_option=k; $(am__make_running_with_option))
+pkgdatadir = $(datadir)/@PACKAGE@
+pkgincludedir = $(includedir)/@PACKAGE@
+pkglibdir = $(libdir)/@PACKAGE@
+pkglibexecdir = $(libexecdir)/@PACKAGE@
+am__cd = CDPATH="$${ZSH_VERSION+.}$(PATH_SEPARATOR)" && cd
+install_sh_DATA = $(install_sh) -c -m 644
+install_sh_PROGRAM = $(install_sh) -c
+install_sh_SCRIPT = $(install_sh) -c
+INSTALL_HEADER = $(INSTALL_DATA)
+transform = $(program_transform_name)
+NORMAL_INSTALL = :
+PRE_INSTALL = :
+POST_INSTALL = :
+NORMAL_UNINSTALL = :
+PRE_UNINSTALL = :
+POST_UNINSTALL = :
+build_triplet = @build@
+host_triplet = @host@
+subdir = lang/python
+DIST_COMMON = $(srcdir)/Makefile.in $(srcdir)/Makefile.am \
+ $(top_srcdir)/build-aux/mkinstalldirs $(srcdir)/setup.py.in \
+ README
+ACLOCAL_M4 = $(top_srcdir)/aclocal.m4
+am__aclocal_m4_deps = $(top_srcdir)/m4/ax_cxx_compile_stdcxx.m4 \
+ $(top_srcdir)/m4/ax_pkg_swig.m4 \
+ $(top_srcdir)/m4/ax_python_devel.m4 \
+ $(top_srcdir)/m4/glib-2.0.m4 $(top_srcdir)/m4/glibc21.m4 \
+ $(top_srcdir)/m4/gnupg-ttyname.m4 \
+ $(top_srcdir)/m4/gpg-error.m4 $(top_srcdir)/m4/libassuan.m4 \
+ $(top_srcdir)/m4/libtool.m4 $(top_srcdir)/m4/ltoptions.m4 \
+ $(top_srcdir)/m4/ltsugar.m4 $(top_srcdir)/m4/ltversion.m4 \
+ $(top_srcdir)/m4/lt~obsolete.m4 $(top_srcdir)/m4/pkg.m4 \
+ $(top_srcdir)/m4/qt.m4 $(top_srcdir)/acinclude.m4 \
+ $(top_srcdir)/configure.ac
+am__configure_deps = $(am__aclocal_m4_deps) $(CONFIGURE_DEPENDENCIES) \
+ $(ACLOCAL_M4)
+mkinstalldirs = $(SHELL) $(top_srcdir)/build-aux/mkinstalldirs
+CONFIG_HEADER = $(top_builddir)/config.h
+CONFIG_CLEAN_FILES = setup.py
+CONFIG_CLEAN_VPATH_FILES =
+AM_V_P = $(am__v_P_@AM_V@)
+am__v_P_ = $(am__v_P_@AM_DEFAULT_V@)
+am__v_P_0 = false
+am__v_P_1 = :
+AM_V_GEN = $(am__v_GEN_@AM_V@)
+am__v_GEN_ = $(am__v_GEN_@AM_DEFAULT_V@)
+am__v_GEN_0 = @echo " GEN " $@;
+am__v_GEN_1 =
+AM_V_at = $(am__v_at_@AM_V@)
+am__v_at_ = $(am__v_at_@AM_DEFAULT_V@)
+am__v_at_0 = @
+am__v_at_1 =
+SOURCES =
+DIST_SOURCES =
+RECURSIVE_TARGETS = all-recursive check-recursive cscopelist-recursive \
+ ctags-recursive dvi-recursive html-recursive info-recursive \
+ install-data-recursive install-dvi-recursive \
+ install-exec-recursive install-html-recursive \
+ install-info-recursive install-pdf-recursive \
+ install-ps-recursive install-recursive installcheck-recursive \
+ installdirs-recursive pdf-recursive ps-recursive \
+ tags-recursive uninstall-recursive
+am__can_run_installinfo = \
+ case $$AM_UPDATE_INFO_DIR in \
+ n|no|NO) false;; \
+ *) (install-info --version) >/dev/null 2>&1;; \
+ esac
+RECURSIVE_CLEAN_TARGETS = mostlyclean-recursive clean-recursive \
+ distclean-recursive maintainer-clean-recursive
+am__recursive_targets = \
+ $(RECURSIVE_TARGETS) \
+ $(RECURSIVE_CLEAN_TARGETS) \
+ $(am__extra_recursive_targets)
+AM_RECURSIVE_TARGETS = $(am__recursive_targets:-recursive=) TAGS CTAGS \
+ distdir
+am__tagged_files = $(HEADERS) $(SOURCES) $(TAGS_FILES) $(LISP)
+# Read a list of newline-separated strings from the standard input,
+# and print each of them once, without duplicates. Input order is
+# *not* preserved.
+am__uniquify_input = $(AWK) '\
+ BEGIN { nonempty = 0; } \
+ { items[$$0] = 1; nonempty = 1; } \
+ END { if (nonempty) { for (i in items) print i; }; } \
+'
+# Make sure the list of sources is unique. This is necessary because,
+# e.g., the same source file might be shared among _SOURCES variables
+# for different programs/libraries.
+am__define_uniq_tagged_files = \
+ list='$(am__tagged_files)'; \
+ unique=`for i in $$list; do \
+ if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \
+ done | $(am__uniquify_input)`
+ETAGS = etags
+CTAGS = ctags
+DIST_SUBDIRS = $(SUBDIRS)
+DISTFILES = $(DIST_COMMON) $(DIST_SOURCES) $(TEXINFOS) $(EXTRA_DIST)
+am__relativize = \
+ dir0=`pwd`; \
+ sed_first='s,^\([^/]*\)/.*$$,\1,'; \
+ sed_rest='s,^[^/]*/*,,'; \
+ sed_last='s,^.*/\([^/]*\)$$,\1,'; \
+ sed_butlast='s,/*[^/]*$$,,'; \
+ while test -n "$$dir1"; do \
+ first=`echo "$$dir1" | sed -e "$$sed_first"`; \
+ if test "$$first" != "."; then \
+ if test "$$first" = ".."; then \
+ dir2=`echo "$$dir0" | sed -e "$$sed_last"`/"$$dir2"; \
+ dir0=`echo "$$dir0" | sed -e "$$sed_butlast"`; \
+ else \
+ first2=`echo "$$dir2" | sed -e "$$sed_first"`; \
+ if test "$$first2" = "$$first"; then \
+ dir2=`echo "$$dir2" | sed -e "$$sed_rest"`; \
+ else \
+ dir2="../$$dir2"; \
+ fi; \
+ dir0="$$dir0"/"$$first"; \
+ fi; \
+ fi; \
+ dir1=`echo "$$dir1" | sed -e "$$sed_rest"`; \
+ done; \
+ reldir="$$dir2"
+ACLOCAL = @ACLOCAL@
+AMTAR = @AMTAR@
+AM_DEFAULT_VERBOSITY = @AM_DEFAULT_VERBOSITY@
+AR = @AR@
+AS = @AS@
+AUTOCONF = @AUTOCONF@
+AUTOHEADER = @AUTOHEADER@
+AUTOMAKE = @AUTOMAKE@
+AWK = @AWK@
+BUILD_FILEVERSION = @BUILD_FILEVERSION@
+BUILD_REVISION = @BUILD_REVISION@
+BUILD_TIMESTAMP = @BUILD_TIMESTAMP@
+CC = @CC@
+CCDEPMODE = @CCDEPMODE@
+CC_FOR_BUILD = @CC_FOR_BUILD@
+CFLAGS = @CFLAGS@
+CPP = @CPP@
+CPPFLAGS = @CPPFLAGS@
+CXX = @CXX@
+CXXCPP = @CXXCPP@
+CXXDEPMODE = @CXXDEPMODE@
+CXXFLAGS = @CXXFLAGS@
+CYGPATH_W = @CYGPATH_W@
+DEFS = @DEFS@
+DEPDIR = @DEPDIR@
+DLLTOOL = @DLLTOOL@
+DOXYGEN = @DOXYGEN@
+DSYMUTIL = @DSYMUTIL@
+DUMPBIN = @DUMPBIN@
+ECHO_C = @ECHO_C@
+ECHO_N = @ECHO_N@
+ECHO_T = @ECHO_T@
+EGREP = @EGREP@
+ENABLED_LANGUAGES = @ENABLED_LANGUAGES@
+EXEEXT = @EXEEXT@
+FGREP = @FGREP@
+GITLOG_TO_CHANGELOG = @GITLOG_TO_CHANGELOG@
+GLIBC21 = @GLIBC21@
+GLIB_CFLAGS = @GLIB_CFLAGS@
+GLIB_GENMARSHAL = @GLIB_GENMARSHAL@
+GLIB_LIBS = @GLIB_LIBS@
+GLIB_MKENUMS = @GLIB_MKENUMS@
+GOBJECT_QUERY = @GOBJECT_QUERY@
+GPGME_CONFIG_API_VERSION = @GPGME_CONFIG_API_VERSION@
+GPGME_CONFIG_AVAIL_LANG = @GPGME_CONFIG_AVAIL_LANG@
+GPGME_CONFIG_CFLAGS = @GPGME_CONFIG_CFLAGS@
+GPGME_CONFIG_HOST = @GPGME_CONFIG_HOST@
+GPGME_CONFIG_LIBS = @GPGME_CONFIG_LIBS@
+GPGME_QTTEST_CFLAGS = @GPGME_QTTEST_CFLAGS@
+GPGME_QTTEST_LIBS = @GPGME_QTTEST_LIBS@
+GPGME_QT_CFLAGS = @GPGME_QT_CFLAGS@
+GPGME_QT_LIBS = @GPGME_QT_LIBS@
+GPG_ERROR_CFLAGS = @GPG_ERROR_CFLAGS@
+GPG_ERROR_CONFIG = @GPG_ERROR_CONFIG@
+GPG_ERROR_LIBS = @GPG_ERROR_LIBS@
+GPG_ERROR_MT_CFLAGS = @GPG_ERROR_MT_CFLAGS@
+GPG_ERROR_MT_LIBS = @GPG_ERROR_MT_LIBS@
+GRAPHVIZ = @GRAPHVIZ@
+GREP = @GREP@
+HAVE_CXX11 = @HAVE_CXX11@
+HAVE_DOT = @HAVE_DOT@
+INSTALL = @INSTALL@
+INSTALL_DATA = @INSTALL_DATA@
+INSTALL_PROGRAM = @INSTALL_PROGRAM@
+INSTALL_SCRIPT = @INSTALL_SCRIPT@
+INSTALL_STRIP_PROGRAM = @INSTALL_STRIP_PROGRAM@
+LD = @LD@
+LDFLAGS = @LDFLAGS@
+LIBASSUAN_CFLAGS = @LIBASSUAN_CFLAGS@
+LIBASSUAN_CONFIG = @LIBASSUAN_CONFIG@
+LIBASSUAN_LIBS = @LIBASSUAN_LIBS@
+LIBGPGMEPP_LT_AGE = @LIBGPGMEPP_LT_AGE@
+LIBGPGMEPP_LT_CURRENT = @LIBGPGMEPP_LT_CURRENT@
+LIBGPGMEPP_LT_REVISION = @LIBGPGMEPP_LT_REVISION@
+LIBGPGME_LT_AGE = @LIBGPGME_LT_AGE@
+LIBGPGME_LT_CURRENT = @LIBGPGME_LT_CURRENT@
+LIBGPGME_LT_REVISION = @LIBGPGME_LT_REVISION@
+LIBOBJS = @LIBOBJS@
+LIBQGPGME_LT_AGE = @LIBQGPGME_LT_AGE@
+LIBQGPGME_LT_CURRENT = @LIBQGPGME_LT_CURRENT@
+LIBQGPGME_LT_REVISION = @LIBQGPGME_LT_REVISION@
+LIBS = @LIBS@
+LIBTOOL = @LIBTOOL@
+LIPO = @LIPO@
+LN_S = @LN_S@
+LTLIBOBJS = @LTLIBOBJS@
+MAINT = @MAINT@
+MAKEINFO = @MAKEINFO@
+MANIFEST_TOOL = @MANIFEST_TOOL@
+MKDIR_P = @MKDIR_P@
+MOC = @MOC@
+MOC2 = @MOC2@
+NEED__FILE_OFFSET_BITS = @NEED__FILE_OFFSET_BITS@
+NM = @NM@
+NMEDIT = @NMEDIT@
+OBJDUMP = @OBJDUMP@
+OBJEXT = @OBJEXT@
+OTOOL = @OTOOL@
+OTOOL64 = @OTOOL64@
+PACKAGE = @PACKAGE@
+PACKAGE_BUGREPORT = @PACKAGE_BUGREPORT@
+PACKAGE_NAME = @PACKAGE_NAME@
+PACKAGE_STRING = @PACKAGE_STRING@
+PACKAGE_TARNAME = @PACKAGE_TARNAME@
+PACKAGE_URL = @PACKAGE_URL@
+PACKAGE_VERSION = @PACKAGE_VERSION@
+PATH_SEPARATOR = @PATH_SEPARATOR@
+PKG_CONFIG = @PKG_CONFIG@
+PYTHON = @PYTHON@
+PYTHONS = @PYTHONS@
+PYTHON_CPPFLAGS = @PYTHON_CPPFLAGS@
+PYTHON_EXEC_PREFIX = @PYTHON_EXEC_PREFIX@
+PYTHON_EXTRA_LDFLAGS = @PYTHON_EXTRA_LDFLAGS@
+PYTHON_EXTRA_LIBS = @PYTHON_EXTRA_LIBS@
+PYTHON_LDFLAGS = @PYTHON_LDFLAGS@
+PYTHON_PLATFORM = @PYTHON_PLATFORM@
+PYTHON_PREFIX = @PYTHON_PREFIX@
+PYTHON_SITE_PKG = @PYTHON_SITE_PKG@
+PYTHON_VERSION = @PYTHON_VERSION@
+PYTHON_VERSIONS = @PYTHON_VERSIONS@
+QTCHOOSER = @QTCHOOSER@
+RANLIB = @RANLIB@
+RC = @RC@
+SED = @SED@
+SET_MAKE = @SET_MAKE@
+SHELL = @SHELL@
+STRIP = @STRIP@
+SWIG = @SWIG@
+SWIG_LIB = @SWIG_LIB@
+SYSROOT = @SYSROOT@
+VERSION = @VERSION@
+VERSION_NUMBER = @VERSION_NUMBER@
+abs_builddir = @abs_builddir@
+abs_srcdir = @abs_srcdir@
+abs_top_builddir = @abs_top_builddir@
+abs_top_srcdir = @abs_top_srcdir@
+ac_ct_AR = @ac_ct_AR@
+ac_ct_CC = @ac_ct_CC@
+ac_ct_CXX = @ac_ct_CXX@
+ac_ct_DUMPBIN = @ac_ct_DUMPBIN@
+am__include = @am__include@
+am__leading_dot = @am__leading_dot@
+am__quote = @am__quote@
+am__tar = @am__tar@
+am__untar = @am__untar@
+bindir = @bindir@
+build = @build@
+build_alias = @build_alias@
+build_cpu = @build_cpu@
+build_os = @build_os@
+build_vendor = @build_vendor@
+builddir = @builddir@
+datadir = @datadir@
+datarootdir = @datarootdir@
+docdir = @docdir@
+dvidir = @dvidir@
+emacs_local_vars_begin = @emacs_local_vars_begin@
+emacs_local_vars_end = @emacs_local_vars_end@
+emacs_local_vars_read_only = @emacs_local_vars_read_only@
+exec_prefix = @exec_prefix@
+host = @host@
+host_alias = @host_alias@
+host_cpu = @host_cpu@
+host_os = @host_os@
+host_vendor = @host_vendor@
+htmldir = @htmldir@
+includedir = @includedir@
+infodir = @infodir@
+install_sh = @install_sh@
+libdir = @libdir@
+libexecdir = @libexecdir@
+localedir = @localedir@
+localstatedir = @localstatedir@
+mandir = @mandir@
+mkdir_p = @mkdir_p@
+oldincludedir = @oldincludedir@
+pdfdir = @pdfdir@
+pkgpyexecdir = @pkgpyexecdir@
+pkgpythondir = @pkgpythondir@
+prefix = @prefix@
+program_transform_name = @program_transform_name@
+psdir = @psdir@
+pyexecdir = @pyexecdir@
+pythondir = @pythondir@
+sbindir = @sbindir@
+sharedstatedir = @sharedstatedir@
+srcdir = @srcdir@
+sysconfdir = @sysconfdir@
+target_alias = @target_alias@
+top_build_prefix = @top_build_prefix@
+top_builddir = @top_builddir@
+top_srcdir = @top_srcdir@
+EXTRA_DIST = \
+ README \
+ MANIFEST.in \
+ gpgme.i \
+ helpers.c helpers.h private.h \
+ gpgme-h-clean.py \
+ examples \
+ pyme
+
+SUBDIRS = . tests
+COPY_FILES = \
+ $(srcdir)/gpgme.i \
+ $(srcdir)/README \
+ $(srcdir)/MANIFEST.in \
+ $(srcdir)/gpgme-h-clean.py \
+ $(srcdir)/examples \
+ $(srcdir)/helpers.c $(srcdir)/helpers.h $(srcdir)/private.h
+
+COPY_FILES_PYME = \
+ $(srcdir)/pyme/callbacks.py \
+ $(srcdir)/pyme/constants \
+ $(srcdir)/pyme/core.py \
+ $(srcdir)/pyme/errors.py \
+ $(srcdir)/pyme/__init__.py \
+ $(srcdir)/pyme/results.py \
+ $(srcdir)/pyme/util.py
+
+CLEANFILES = gpgme.h errors.i gpgme_wrap.c pyme/gpgme.py \
+ copystamp
+
+all: all-recursive
+
+.SUFFIXES:
+$(srcdir)/Makefile.in: @MAINTAINER_MODE_TRUE@ $(srcdir)/Makefile.am $(am__configure_deps)
+ @for dep in $?; do \
+ case '$(am__configure_deps)' in \
+ *$$dep*) \
+ ( cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh ) \
+ && { if test -f $@; then exit 0; else break; fi; }; \
+ exit 1;; \
+ esac; \
+ done; \
+ echo ' cd $(top_srcdir) && $(AUTOMAKE) --gnu lang/python/Makefile'; \
+ $(am__cd) $(top_srcdir) && \
+ $(AUTOMAKE) --gnu lang/python/Makefile
+.PRECIOUS: Makefile
+Makefile: $(srcdir)/Makefile.in $(top_builddir)/config.status
+ @case '$?' in \
+ *config.status*) \
+ cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh;; \
+ *) \
+ echo ' cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__depfiles_maybe)'; \
+ cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__depfiles_maybe);; \
+ esac;
+
+$(top_builddir)/config.status: $(top_srcdir)/configure $(CONFIG_STATUS_DEPENDENCIES)
+ cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh
+
+$(top_srcdir)/configure: @MAINTAINER_MODE_TRUE@ $(am__configure_deps)
+ cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh
+$(ACLOCAL_M4): @MAINTAINER_MODE_TRUE@ $(am__aclocal_m4_deps)
+ cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh
+$(am__aclocal_m4_deps):
+setup.py: $(top_builddir)/config.status $(srcdir)/setup.py.in
+ cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@
+
+mostlyclean-libtool:
+ -rm -f *.lo
+
+clean-libtool:
+ -rm -rf .libs _libs
+
+# This directory's subdirectories are mostly independent; you can cd
+# into them and run 'make' without going through this Makefile.
+# To change the values of 'make' variables: instead of editing Makefiles,
+# (1) if the variable is set in 'config.status', edit 'config.status'
+# (which will cause the Makefiles to be regenerated when you run 'make');
+# (2) otherwise, pass the desired values on the 'make' command line.
+$(am__recursive_targets):
+ @fail=; \
+ if $(am__make_keepgoing); then \
+ failcom='fail=yes'; \
+ else \
+ failcom='exit 1'; \
+ fi; \
+ dot_seen=no; \
+ target=`echo $@ | sed s/-recursive//`; \
+ case "$@" in \
+ distclean-* | maintainer-clean-*) list='$(DIST_SUBDIRS)' ;; \
+ *) list='$(SUBDIRS)' ;; \
+ esac; \
+ for subdir in $$list; do \
+ echo "Making $$target in $$subdir"; \
+ if test "$$subdir" = "."; then \
+ dot_seen=yes; \
+ local_target="$$target-am"; \
+ else \
+ local_target="$$target"; \
+ fi; \
+ ($(am__cd) $$subdir && $(MAKE) $(AM_MAKEFLAGS) $$local_target) \
+ || eval $$failcom; \
+ done; \
+ if test "$$dot_seen" = "no"; then \
+ $(MAKE) $(AM_MAKEFLAGS) "$$target-am" || exit 1; \
+ fi; test -z "$$fail"
+
+ID: $(am__tagged_files)
+ $(am__define_uniq_tagged_files); mkid -fID $$unique
+tags: tags-recursive
+TAGS: tags
+
+tags-am: $(TAGS_DEPENDENCIES) $(am__tagged_files)
+ set x; \
+ here=`pwd`; \
+ if ($(ETAGS) --etags-include --version) >/dev/null 2>&1; then \
+ include_option=--etags-include; \
+ empty_fix=.; \
+ else \
+ include_option=--include; \
+ empty_fix=; \
+ fi; \
+ list='$(SUBDIRS)'; for subdir in $$list; do \
+ if test "$$subdir" = .; then :; else \
+ test ! -f $$subdir/TAGS || \
+ set "$$@" "$$include_option=$$here/$$subdir/TAGS"; \
+ fi; \
+ done; \
+ $(am__define_uniq_tagged_files); \
+ shift; \
+ if test -z "$(ETAGS_ARGS)$$*$$unique"; then :; else \
+ test -n "$$unique" || unique=$$empty_fix; \
+ if test $$# -gt 0; then \
+ $(ETAGS) $(ETAGSFLAGS) $(AM_ETAGSFLAGS) $(ETAGS_ARGS) \
+ "$$@" $$unique; \
+ else \
+ $(ETAGS) $(ETAGSFLAGS) $(AM_ETAGSFLAGS) $(ETAGS_ARGS) \
+ $$unique; \
+ fi; \
+ fi
+ctags: ctags-recursive
+
+CTAGS: ctags
+ctags-am: $(TAGS_DEPENDENCIES) $(am__tagged_files)
+ $(am__define_uniq_tagged_files); \
+ test -z "$(CTAGS_ARGS)$$unique" \
+ || $(CTAGS) $(CTAGSFLAGS) $(AM_CTAGSFLAGS) $(CTAGS_ARGS) \
+ $$unique
+
+GTAGS:
+ here=`$(am__cd) $(top_builddir) && pwd` \
+ && $(am__cd) $(top_srcdir) \
+ && gtags -i $(GTAGS_ARGS) "$$here"
+cscopelist: cscopelist-recursive
+
+cscopelist-am: $(am__tagged_files)
+ list='$(am__tagged_files)'; \
+ case "$(srcdir)" in \
+ [\\/]* | ?:[\\/]*) sdir="$(srcdir)" ;; \
+ *) sdir=$(subdir)/$(srcdir) ;; \
+ esac; \
+ for i in $$list; do \
+ if test -f "$$i"; then \
+ echo "$(subdir)/$$i"; \
+ else \
+ echo "$$sdir/$$i"; \
+ fi; \
+ done >> $(top_builddir)/cscope.files
+
+distclean-tags:
+ -rm -f TAGS ID GTAGS GRTAGS GSYMS GPATH tags
+
+distdir: $(DISTFILES)
+ @srcdirstrip=`echo "$(srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \
+ topsrcdirstrip=`echo "$(top_srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \
+ list='$(DISTFILES)'; \
+ dist_files=`for file in $$list; do echo $$file; done | \
+ sed -e "s|^$$srcdirstrip/||;t" \
+ -e "s|^$$topsrcdirstrip/|$(top_builddir)/|;t"`; \
+ case $$dist_files in \
+ */*) $(MKDIR_P) `echo "$$dist_files" | \
+ sed '/\//!d;s|^|$(distdir)/|;s,/[^/]*$$,,' | \
+ sort -u` ;; \
+ esac; \
+ for file in $$dist_files; do \
+ if test -f $$file || test -d $$file; then d=.; else d=$(srcdir); fi; \
+ if test -d $$d/$$file; then \
+ dir=`echo "/$$file" | sed -e 's,/[^/]*$$,,'`; \
+ if test -d "$(distdir)/$$file"; then \
+ find "$(distdir)/$$file" -type d ! -perm -700 -exec chmod u+rwx {} \;; \
+ fi; \
+ if test -d $(srcdir)/$$file && test $$d != $(srcdir); then \
+ cp -fpR $(srcdir)/$$file "$(distdir)$$dir" || exit 1; \
+ find "$(distdir)/$$file" -type d ! -perm -700 -exec chmod u+rwx {} \;; \
+ fi; \
+ cp -fpR $$d/$$file "$(distdir)$$dir" || exit 1; \
+ else \
+ test -f "$(distdir)/$$file" \
+ || cp -p $$d/$$file "$(distdir)/$$file" \
+ || exit 1; \
+ fi; \
+ done
+ @list='$(DIST_SUBDIRS)'; for subdir in $$list; do \
+ if test "$$subdir" = .; then :; else \
+ $(am__make_dryrun) \
+ || test -d "$(distdir)/$$subdir" \
+ || $(MKDIR_P) "$(distdir)/$$subdir" \
+ || exit 1; \
+ dir1=$$subdir; dir2="$(distdir)/$$subdir"; \
+ $(am__relativize); \
+ new_distdir=$$reldir; \
+ dir1=$$subdir; dir2="$(top_distdir)"; \
+ $(am__relativize); \
+ new_top_distdir=$$reldir; \
+ echo " (cd $$subdir && $(MAKE) $(AM_MAKEFLAGS) top_distdir="$$new_top_distdir" distdir="$$new_distdir" \\"; \
+ echo " am__remove_distdir=: am__skip_length_check=: am__skip_mode_fix=: distdir)"; \
+ ($(am__cd) $$subdir && \
+ $(MAKE) $(AM_MAKEFLAGS) \
+ top_distdir="$$new_top_distdir" \
+ distdir="$$new_distdir" \
+ am__remove_distdir=: \
+ am__skip_length_check=: \
+ am__skip_mode_fix=: \
+ distdir) \
+ || exit 1; \
+ fi; \
+ done
+check-am: all-am
+check: check-recursive
+all-am: Makefile all-local
+installdirs: installdirs-recursive
+installdirs-am:
+install: install-recursive
+install-exec: install-exec-recursive
+install-data: install-data-recursive
+uninstall: uninstall-recursive
+
+install-am: all-am
+ @$(MAKE) $(AM_MAKEFLAGS) install-exec-am install-data-am
+
+installcheck: installcheck-recursive
+install-strip:
+ if test -z '$(STRIP)'; then \
+ $(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \
+ install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \
+ install; \
+ else \
+ $(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \
+ install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \
+ "INSTALL_PROGRAM_ENV=STRIPPROG='$(STRIP)'" install; \
+ fi
+mostlyclean-generic:
+
+clean-generic:
+ -test -z "$(CLEANFILES)" || rm -f $(CLEANFILES)
+
+distclean-generic:
+ -test -z "$(CONFIG_CLEAN_FILES)" || rm -f $(CONFIG_CLEAN_FILES)
+ -test . = "$(srcdir)" || test -z "$(CONFIG_CLEAN_VPATH_FILES)" || rm -f $(CONFIG_CLEAN_VPATH_FILES)
+
+maintainer-clean-generic:
+ @echo "This command is intended for maintainers to use"
+ @echo "it deletes files that may require special tools to rebuild."
+clean: clean-recursive
+
+clean-am: clean-generic clean-libtool clean-local mostlyclean-am
+
+distclean: distclean-recursive
+ -rm -f Makefile
+distclean-am: clean-am distclean-generic distclean-tags
+
+dvi: dvi-recursive
+
+dvi-am:
+
+html: html-recursive
+
+html-am:
+
+info: info-recursive
+
+info-am:
+
+install-data-am:
+
+install-dvi: install-dvi-recursive
+
+install-dvi-am:
+
+install-exec-am: install-exec-local
+
+install-html: install-html-recursive
+
+install-html-am:
+
+install-info: install-info-recursive
+
+install-info-am:
+
+install-man:
+
+install-pdf: install-pdf-recursive
+
+install-pdf-am:
+
+install-ps: install-ps-recursive
+
+install-ps-am:
+
+installcheck-am:
+
+maintainer-clean: maintainer-clean-recursive
+ -rm -f Makefile
+maintainer-clean-am: distclean-am maintainer-clean-generic
+
+mostlyclean: mostlyclean-recursive
+
+mostlyclean-am: mostlyclean-generic mostlyclean-libtool
+
+pdf: pdf-recursive
+
+pdf-am:
+
+ps: ps-recursive
+
+ps-am:
+
+uninstall-am: uninstall-local
+
+.MAKE: $(am__recursive_targets) install-am install-strip
+
+.PHONY: $(am__recursive_targets) CTAGS GTAGS TAGS all all-am all-local \
+ check check-am clean clean-generic clean-libtool clean-local \
+ cscopelist-am ctags ctags-am distclean distclean-generic \
+ distclean-libtool distclean-tags distdir dvi dvi-am html \
+ html-am info info-am install install-am install-data \
+ install-data-am install-dvi install-dvi-am install-exec \
+ install-exec-am install-exec-local install-html \
+ install-html-am install-info install-info-am install-man \
+ install-pdf install-pdf-am install-ps install-ps-am \
+ install-strip installcheck installcheck-am installdirs \
+ installdirs-am maintainer-clean maintainer-clean-generic \
+ mostlyclean mostlyclean-generic mostlyclean-libtool pdf pdf-am \
+ ps ps-am tags tags-am uninstall uninstall-am uninstall-local
+
+
+# For VPATH builds we need to copy some files because Python's
+# distutils are not VPATH-aware.
+copystamp: $(COPY_FILES) $(COPY_FILES_PYME)
+ if test "$(srcdir)" != "$(builddir)" ; then \
+ cp -R $(COPY_FILES) . ; \
+ cp -R $(COPY_FILES_PYME) pyme ; \
+ fi
+ touch $@
+
+all-local: copystamp
+ for PYTHON in $(PYTHONS); do \
+ CFLAGS="$(CFLAGS) -I$(top_srcdir)" \
+ $$PYTHON setup.py build --verbose ; \
+ done
+
+dist/pyme3-$(VERSION).tar.gz dist/pyme3-$(VERSION).tar.gz.asc: copystamp
+ CFLAGS="$(CFLAGS) -I$(top_srcdir)" \
+ $(PYTHON) setup.py sdist --verbose
+ gpg2 --detach-sign --armor dist/pyme3-$(VERSION).tar.gz
+
+.PHONY: sdist
+sdist: dist/pyme3-$(VERSION).tar.gz dist/pyme3-$(VERSION).tar.gz.asc
+
+.PHONY: upload
+upload: dist/pyme3-$(VERSION).tar.gz dist/pyme3-$(VERSION).tar.gz.asc
+ twine upload $^
+
+# Remove the rest.
+#
+# 'make distclean' clears the write bit, breaking rm -rf. Fix the
+# permissions.
+clean-local:
+ rm -rf -- build
+ if test "$(srcdir)" != "$(builddir)" ; then \
+ find . -type d ! -perm -200 -exec chmod u+w {} ';' ; \
+ for F in $(COPY_FILES); do rm -rf -- `basename $$F` ; done ; \
+ for F in $(COPY_FILES_PYME); do \
+ rm -rf -- pyme/`basename $$F` ; \
+ done ; \
+ fi
+
+install-exec-local:
+ rm -f install_files.txt
+ for PYTHON in $(PYTHONS); do \
+ $$PYTHON setup.py install \
+ --prefix $(DESTDIR)$(prefix) \
+ --record files.txt \
+ --verbose ; \
+ cat files.txt >> install_files.txt ; \
+ rm files.txt ; \
+ done
+ $(MKDIR_P) $(DESTDIR)$(pythondir)/pyme
+ mv install_files.txt $(DESTDIR)$(pythondir)/pyme
+
+uninstall-local:
+ xargs <$(DESTDIR)$(pythondir)/pyme/install_files.txt -- rm -rf --
+ rm -rf -- $(DESTDIR)$(pythondir)/pyme
+
+# Tell versions [3.59,3.63) of GNU make to not export all variables.
+# Otherwise a system limit (for SysV at least) may be exceeded.
+.NOEXPORT:
diff --git a/lang/python/README b/lang/python/README
new file mode 100644
index 0000000..98c007e
--- /dev/null
+++ b/lang/python/README
@@ -0,0 +1,59 @@
+PyME - GPGME for Python -*- org -*-
+=======================
+
+PyME is a python interface to the GPGME library:
+https://www.gnupg.org/related_software/gpgme/
+
+PyME offers two interfaces, one is a high-level, curated, and
+idiomatic interface that is implemented as a shim on top of the
+low-level interface automatically created using SWIG.
+
+This way we make simple things easy, while still providing the entire
+functionality of the underlying library.
+
+* Mailing List
+
+For general discussion and help see the gnupg-users mailing list:
+https://lists.gnupg.org/mailman/listinfo/gnupg-users
+
+For development see the gnupg-devel mailing list:
+https://lists.gnupg.org/mailman/listinfo/gnupg-devel
+
+* Bugs
+
+Please report bugs using our bug tracker using the category 'gpgme',
+and topic 'python':
+https://bugs.gnupg.org/gnupg/
+
+* Authors
+
+PyME has been created by John Goerzen, and maintained, developed, and
+cherished by Igor Belyi, Martin Albrecht, Ben McGinnes, and everyone
+who contributed to it in any way.
+
+In 2016 we merged a port of PyME to into the GPGME repository, and
+development will continue there. Please see the VCS history for the
+list of contributors, and if you do find bugs, or want to contribute,
+please get in touch and help maintain PyME.
+
+Please see the section 'History' further down this document for
+references to previous versions.
+
+* History
+
+ - The bindings have been merged into the GPGME repository in 2016.
+
+ - The latest version of PyME for Python 3.2 and above (as of
+ May, 2015) is v0.9.1.
+ https://git.gnupg.org/gpgme.git/lang/py3-pyme
+
+ - The latest version of PyME for Python 2.6 and 2.7 (as of this
+ writing) is v0.9.0. https://bitbucket.org/malb/pyme
+
+ - A previous version of PyME v0.8.0 can be found on sourceforge:
+ http://pyme.sourceforge.net/
+
+ - A previous version of PyME v0.5.1 which works with GPGME v0.3.15
+ can be found on John Goerzen's PyME page:
+ http://quux.org/devel/pyme/
+ http://www.complete.org/JohnGoerzen
diff --git a/lang/python/examples/assuan.py b/lang/python/examples/assuan.py
new file mode 100644
index 0000000..22960d3
--- /dev/null
+++ b/lang/python/examples/assuan.py
@@ -0,0 +1,28 @@
+#!/usr/bin/env python
+#
+# Copyright (C) 2016 g10 Code GmbH
+#
+# This program 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.
+#
+# This program 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, see <http://www.gnu.org/licenses/>.
+
+"""Demonstrate the use of the Assuan protocol engine"""
+
+from __future__ import absolute_import, print_function, unicode_literals
+del absolute_import, print_function, unicode_literals
+
+import pyme
+
+with pyme.Context(protocol=pyme.constants.PROTOCOL_ASSUAN) as c:
+ # Invoke the pinentry to get a confirmation.
+ err = c.assuan_transact(['GET_CONFIRMATION', 'Hello there'])
+ print("You chose {}.".format("cancel" if err else "ok"))
diff --git a/lang/python/examples/decryption-filter.py b/lang/python/examples/decryption-filter.py
new file mode 100644
index 0000000..3007c2b
--- /dev/null
+++ b/lang/python/examples/decryption-filter.py
@@ -0,0 +1,32 @@
+#!/usr/bin/env python
+#
+# Copyright (C) 2016 g10 Code GmbH
+#
+# This program 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.
+#
+# This program 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, see <http://www.gnu.org/licenses/>.
+
+"""A decryption filter
+
+This demonstrates decryption using pyme3 in three lines of code. To
+be used like this:
+
+./decryption-filter.py <message.gpg >message.plain
+
+"""
+
+from __future__ import absolute_import, print_function, unicode_literals
+del absolute_import, print_function, unicode_literals
+
+import sys
+import pyme
+pyme.Context().decrypt(sys.stdin, sink=sys.stdout)
diff --git a/lang/python/examples/delkey.py b/lang/python/examples/delkey.py
new file mode 100755
index 0000000..a02f412
--- /dev/null
+++ b/lang/python/examples/delkey.py
@@ -0,0 +1,33 @@
+#!/usr/bin/env python
+#
+# Copyright (C) 2016 g10 Code GmbH
+# Copyright (C) 2004,2008 Igor Belyi <belyi@users.sourceforge.net>
+#
+# This program 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.
+#
+# This program 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, see <http://www.gnu.org/licenses/>.
+
+# Sample of key deletion
+# It deletes keys for joe@example.org generated by genkey.py script
+
+from __future__ import absolute_import, print_function, unicode_literals
+del absolute_import, print_function, unicode_literals
+
+import pyme
+
+with pyme.Context() as c:
+ # Note: We must not modify the key store during iteration,
+ # therefore, we explicitly make a list.
+ keys = list(c.keylist("joe+pyme@example.org"))
+
+ for k in keys:
+ c.op_delete(k, True)
diff --git a/lang/python/examples/encrypt-to-all.py b/lang/python/examples/encrypt-to-all.py
new file mode 100755
index 0000000..35873bd
--- /dev/null
+++ b/lang/python/examples/encrypt-to-all.py
@@ -0,0 +1,53 @@
+#!/usr/bin/env python
+#
+# Copyright (C) 2016 g10 Code GmbH
+# Copyright (C) 2008 Igor Belyi <belyi@users.sourceforge.net>
+# Copyright (C) 2002 John Goerzen <jgoerzen@complete.org>
+#
+# This program 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.
+#
+# This program 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, see <http://www.gnu.org/licenses/>.
+
+"""
+This program will try to encrypt a simple message to each key on your
+keyring. If your keyring has any invalid keys on it, those keys will
+be skipped and it will re-try the encryption."""
+
+from __future__ import absolute_import, print_function, unicode_literals
+del absolute_import, print_function, unicode_literals
+
+import sys
+import pyme
+
+with pyme.Context(armor=True) as c:
+ recipients = list()
+ for key in c.keylist():
+ valid = 0
+ if any(sk.can_encrypt for sk in key.subkeys):
+ recipients.append(key)
+ print("Adding recipient {0}.".format(key.uids[0].uid))
+
+ ciphertext = None
+ while not ciphertext:
+ print("Encrypting to %d recipients" % len(recipients))
+ try:
+ ciphertext, _, _ = c.encrypt(b'This is my message.',
+ recipients=recipients)
+ except pyme.errors.InvalidRecipients as e:
+ print("Encryption failed for these keys:\n{0!s}".format(e))
+
+ # filter out the bad keys
+ bad_keys = {bad.fpr for bad in e.recipients}
+ recipients = [r for r in recipients
+ if not r.subkeys[0].fpr in bad_keys]
+
+ sys.stdout.buffer.write(ciphertext)
diff --git a/lang/python/examples/exportimport.py b/lang/python/examples/exportimport.py
new file mode 100755
index 0000000..bc946bc
--- /dev/null
+++ b/lang/python/examples/exportimport.py
@@ -0,0 +1,61 @@
+#!/usr/bin/env python
+#
+# Copyright (C) 2016 g10 Code GmbH
+# Copyright (C) 2004,2008 Igor Belyi <belyi@users.sourceforge.net>
+#
+# This program 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.
+#
+# This program 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, see <http://www.gnu.org/licenses/>.
+
+# Sample of export and import of keys
+# It uses keys for joe+pyme@example.org generated by genkey.py script
+
+from __future__ import absolute_import, print_function, unicode_literals
+del absolute_import, print_function, unicode_literals
+
+import sys
+import os
+import pyme
+
+user = "joe+pyme@example.org"
+
+with pyme.Context(armor=True) as c, pyme.Data() as expkey:
+ print(" - Export %s's public keys - " % user)
+ c.op_export(user, 0, expkey)
+
+ # print out exported data to see how it looks in armor.
+ expkey.seek(0, os.SEEK_SET)
+ expstring = expkey.read()
+ if expstring:
+ sys.stdout.buffer.write(expstring)
+ else:
+ sys.exit("No %s's keys to export!" % user)
+
+# delete keys to ensure that they came from our imported data. Note
+# that if joe's key has private part as well we can only delete both
+# of them.
+with pyme.Context() as c:
+ # Note: We must not modify the key store during iteration,
+ # therfore, we explicitly make a list.
+ keys = list(c.keylist(user))
+
+ for k in keys:
+ c.op_delete(k, True)
+
+with pyme.Context() as c:
+ print(" - Import exported keys - ")
+ c.op_import(expstring)
+ result = c.op_import_result()
+ if result:
+ print(result)
+ else:
+ sys.exit(" - No import result - ")
diff --git a/lang/python/examples/genkey.py b/lang/python/examples/genkey.py
new file mode 100755
index 0000000..ee70303
--- /dev/null
+++ b/lang/python/examples/genkey.py
@@ -0,0 +1,44 @@
+#!/usr/bin/env python
+#
+# Copyright (C) 2016 g10 Code GmbH
+# Copyright (C) 2004 Igor Belyi <belyi@users.sourceforge.net>
+# Copyright (C) 2002 John Goerzen <jgoerzen@complete.org>
+#
+# This program 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.
+#
+# This program 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, see <http://www.gnu.org/licenses/>.
+
+from __future__ import absolute_import, print_function, unicode_literals
+del absolute_import, print_function, unicode_literals
+
+import pyme
+
+# This is the example from the GPGME manual.
+
+parms = """<GnupgKeyParms format="internal">
+Key-Type: RSA
+Key-Length: 2048
+Subkey-Type: RSA
+Subkey-Length: 2048
+Name-Real: Joe Tester
+Name-Comment: with stupid passphrase
+Name-Email: joe+pyme@example.org
+Passphrase: Crypt0R0cks
+Expire-Date: 2020-12-31
+</GnupgKeyParms>
+"""
+
+with pyme.Context() as c:
+ c.set_progress_cb(pyme.callbacks.progress_stdout)
+ c.op_genkey(parms, None, None)
+ print("Generated key with fingerprint {0}.".format(
+ c.op_genkey_result().fpr))
diff --git a/lang/python/examples/inter-edit.py b/lang/python/examples/inter-edit.py
new file mode 100644
index 0000000..39d6f17
--- /dev/null
+++ b/lang/python/examples/inter-edit.py
@@ -0,0 +1,56 @@
+#!/usr/bin/env python
+#
+# Copyright (C) 2016 g10 Code GmbH
+# Copyright (C) 2005 Igor Belyi <belyi@users.sourceforge.net>
+#
+# This program 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.
+#
+# This program 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, see <http://www.gnu.org/licenses/>.
+
+"""Simple interactive editor to test editor scripts"""
+
+from __future__ import absolute_import, print_function, unicode_literals
+del absolute_import, print_function, unicode_literals
+
+import sys
+import pyme
+
+if len(sys.argv) != 2:
+ sys.exit("Usage: %s <Gpg key pattern>\n" % sys.argv[0])
+
+name = sys.argv[1]
+
+with pyme.Context() as c:
+ keys = list(c.keylist(name))
+ if len(keys) == 0:
+ sys.exit("No key matching {}.".format(name))
+ if len(keys) > 1:
+ sys.exit("More than one key matching {}.".format(name))
+
+ key = keys[0]
+ print("Editing key {} ({}):".format(key.uids[0].uid, key.subkeys[0].fpr))
+
+ def edit_fnc(keyword, args):
+ print("Status: {} ({}), args: {} > ".format(
+ keyword, status, args), end='', flush=True)
+
+ if not 'GET' in keyword:
+ # no prompt
+ print()
+ return None
+
+ try:
+ return input()
+ except EOFError:
+ return "quit"
+
+ c.interact(key, edit_fnc, sink=sys.stdout)
diff --git a/lang/python/examples/sign.py b/lang/python/examples/sign.py
new file mode 100755
index 0000000..2f235ba
--- /dev/null
+++ b/lang/python/examples/sign.py
@@ -0,0 +1,28 @@
+#!/usr/bin/env python
+#
+# Copyright (C) 2016 g10 Code GmbH
+# Copyright (C) 2002 John Goerzen <jgoerzen@complete.org>
+#
+# This program 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.
+#
+# This program 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, see <http://www.gnu.org/licenses/>.
+
+from __future__ import absolute_import, print_function, unicode_literals
+del absolute_import, print_function, unicode_literals
+
+import sys
+import pyme
+from pyme.constants.sig import mode
+
+with pyme.Context() as c:
+ signed, _ = c.sign(b"Test message", mode=mode.CLEAR)
+ sys.stdout.buffer.write(signed)
diff --git a/lang/python/examples/signverify.py b/lang/python/examples/signverify.py
new file mode 100755
index 0000000..03bc0a6
--- /dev/null
+++ b/lang/python/examples/signverify.py
@@ -0,0 +1,41 @@
+#!/usr/bin/env python
+#
+# Copyright (C) 2016 g10 Code GmbH
+# Copyright (C) 2004,2008 Igor Belyi <belyi@users.sourceforge.net>
+#
+# This program 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.
+#
+# This program 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, see <http://www.gnu.org/licenses/>.
+
+# Sample of unattended signing/verifying of a message.
+# It uses keys for joe+pyme@example.org generated by genkey.py script
+
+from __future__ import absolute_import, print_function, unicode_literals
+del absolute_import, print_function, unicode_literals
+
+import sys
+import pyme
+from pyme.constants.sig import mode
+
+user = "joe+pyme"
+
+with pyme.Context(pinentry_mode=pyme.constants.PINENTRY_MODE_LOOPBACK) as c:
+ keys = list(c.keylist(user))
+ if len(keys) == 0:
+ sys.exit("No key matching {}.".format(user))
+
+ c.signers = keys[:1]
+ c.set_passphrase_cb(lambda *args: "Crypt0R0cks")
+ signed_data, _ = c.sign(b"Test message", mode=mode.CLEAR)
+
+ data, result = c.verify(signed_data, verify=keys[:1])
+ print("Data: {!r}\nSignature: {!s}".format(data, result.signatures[0]))
diff --git a/lang/python/examples/simple.py b/lang/python/examples/simple.py
new file mode 100755
index 0000000..5598487
--- /dev/null
+++ b/lang/python/examples/simple.py
@@ -0,0 +1,47 @@
+#!/usr/bin/env python
+#
+# Copyright (C) 2016 g10 Code GmbH
+# Copyright (C) 2005 Igor Belyi <belyi@users.sourceforge.net>
+# Copyright (C) 2002 John Goerzen <jgoerzen@complete.org>
+#
+# This program 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.
+#
+# This program 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, see <http://www.gnu.org/licenses/>.
+
+from __future__ import absolute_import, print_function, unicode_literals
+del absolute_import, print_function, unicode_literals
+
+import sys
+import pyme
+
+with pyme.Context(armor=True) as c:
+ recipients = []
+ print("Enter name of your recipient(s), end with a blank line.")
+ while True:
+ line = input()
+ if not line:
+ break
+ new = list(c.keylist(line))
+ if not new:
+ print("Matched no known keys.")
+ else:
+ print("Adding {}.".format(", ".join(k.uids[0].name for k in new)))
+ recipients.extend(new)
+
+ if not recipients:
+ sys.exit("No recipients.")
+
+ print("Encrypting for {}.".format(", ".join(k.uids[0].name
+ for k in recipients)))
+
+ ciphertext, _, _ = c.encrypt(b"This is my message,", recipients)
+ sys.stdout.buffer.write(ciphertext)
diff --git a/lang/python/examples/testCMSgetkey.py b/lang/python/examples/testCMSgetkey.py
new file mode 100644
index 0000000..4467b6c
--- /dev/null
+++ b/lang/python/examples/testCMSgetkey.py
@@ -0,0 +1,35 @@
+#!/usr/bin/env python
+#
+# Copyright (C) 2016 g10 Code GmbH
+# Copyright (C) 2008 Bernhard Reiter <bernhard@intevation.de>
+#
+# This program 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.
+#
+# This program 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, see <http://www.gnu.org/licenses/>.
+
+"""A test applicaton for the CMS protocol."""
+
+from __future__ import absolute_import, print_function, unicode_literals
+del absolute_import, print_function, unicode_literals
+
+import sys
+import pyme
+
+if len(sys.argv) != 2:
+ sys.exit("fingerprint or unique key ID for gpgme_get_key()")
+
+with pyme.Context(protocol=pyme.constants.PROTOCOL_CMS) as c:
+ key = c.get_key(sys.argv[1], False)
+
+ print("got key: ", key.subkeys[0].fpr)
+ for uid in key.uids:
+ print(uid.uid)
diff --git a/lang/python/examples/verifydetails.py b/lang/python/examples/verifydetails.py
new file mode 100755
index 0000000..fa34926
--- /dev/null
+++ b/lang/python/examples/verifydetails.py
@@ -0,0 +1,79 @@
+#!/usr/bin/env python
+#
+# Copyright (C) 2016 g10 Code GmbH
+# Copyright (C) 2004,2008 Igor Belyi <belyi@users.sourceforge.net>
+# Copyright (c) 2008 Bernhard Reiter <bernhard@intevation.de>
+#
+# This program 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.
+#
+# This program 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, see <http://www.gnu.org/licenses/>.
+
+from __future__ import absolute_import, print_function, unicode_literals
+del absolute_import, print_function, unicode_literals
+
+import sys
+from pyme import core
+from pyme.constants import protocol
+
+def print_engine_infos():
+ print("gpgme version:", core.check_version(None))
+ print("engines:")
+
+ for engine in core.get_engine_info():
+ print(engine.file_name, engine.version)
+
+ for proto in [protocol.OpenPGP, protocol.CMS]:
+ print("Have {}? {}".format(core.get_protocol_name(proto),
+ core.engine_check_version(proto)))
+
+
+def verifyprintdetails(filename, detached_sig_filename=None):
+ """Verify a signature, print a lot of details."""
+ with core.Context() as c:
+
+ # Verify.
+ data, result = c.verify(open(filename),
+ open(detached_sig_filename)
+ if detached_sig_filename else None)
+
+ # List results for all signatures. Status equal 0 means "Ok".
+ for index, sign in enumerate(result.signatures):
+ print("signature", index, ":")
+ print(" summary: %#0x" % (sign.summary))
+ print(" status: %#0x" % (sign.status))
+ print(" timestamp: ", sign.timestamp)
+ print(" fingerprint:", sign.fpr)
+ print(" uid: ", c.get_key(sign.fpr, 0).uids[0].uid)
+
+ # Print "unsigned" text if inline signature
+ if data:
+ sys.stdout.buffer.write(data)
+
+def main():
+ print_engine_infos()
+ print()
+
+ argc = len(sys.argv)
+ if argc < 2 or argc > 3:
+ sys.exit(
+ "Usage: {} <filename>[ <detached_signature_filename>]".format(
+ sys.argv[0]))
+
+ if argc == 2:
+ print("trying to verify file {}.".format(sys.argv[1]))
+ verifyprintdetails(sys.argv[1])
+ if argc == 3:
+ print("trying to verify signature {1} for file {0}.".format(*sys.argv))
+ verifyprintdetails(sys.argv[1], sys.argv[2])
+
+if __name__ == "__main__":
+ main()
diff --git a/lang/python/gpgme-h-clean.py b/lang/python/gpgme-h-clean.py
new file mode 100755
index 0000000..52f8676
--- /dev/null
+++ b/lang/python/gpgme-h-clean.py
@@ -0,0 +1,53 @@
+#!/usr/bin/env python
+
+# Copyright (C) 2016 g10 Code GmbH
+# Copyright (C) 2004,2008 Igor Belyi <belyi@users.sourceforge.net>
+#
+# This library is free software; you can redistribute it and/or
+# modify it under the terms of the GNU Lesser General Public
+# License as published by the Free Software Foundation; either
+# version 2.1 of the License, or (at your option) any later version.
+#
+# This library is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+# Lesser General Public License for more details.
+#
+# You should have received a copy of the GNU Lesser General Public
+# License along with this library; if not, write to the Free Software
+# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+
+from __future__ import absolute_import, print_function, unicode_literals
+del absolute_import, print_function, unicode_literals
+
+import sys, re
+
+if len(sys.argv) != 2:
+ sys.stderr.write("Usage: %s path/to/[gpgme|gpg-error].h\n" % sys.argv[0])
+ sys.exit(1)
+
+deprec_func = re.compile(r'^(.*typedef.*|.*\(.*\)|[^#]+\s+.+)'
+ + r'\s*_GPGME_DEPRECATED(_OUTSIDE_GPGME)?\(.*\);\s*',
+ re.S)
+line_break = re.compile(';|\\$|\\x0c|^\s*#|{');
+
+if 'gpgme.h' in sys.argv[1]:
+ gpgme = open(sys.argv[1])
+ tmp = gpgme.readline()
+ text = ''
+ while tmp:
+ text += re.sub(' class ', ' _py_obsolete_class ', tmp)
+ if line_break.search(tmp):
+ if not deprec_func.search(text):
+ sys.stdout.write(text)
+ text = ''
+ tmp = gpgme.readline()
+ sys.stdout.write(text)
+ gpgme.close()
+else:
+ filter_re = re.compile(r'GPG_ERR_[^ ]* =')
+ rewrite_re = re.compile(r' *(.*) = .*')
+ for line in open(sys.argv[1]):
+ if not filter_re.search(line):
+ continue
+ print(rewrite_re.sub(r'%constant long \1 = \1;', line.strip()))
diff --git a/lang/python/gpgme.i b/lang/python/gpgme.i
new file mode 100644
index 0000000..84addae
--- /dev/null
+++ b/lang/python/gpgme.i
@@ -0,0 +1,625 @@
+/*
+# Copyright (C) 2016 g10 Code GmbH
+# Copyright (C) 2004,2008 Igor Belyi <belyi@users.sourceforge.net>
+# Copyright (C) 2002 John Goerzen <jgoerzen@complete.org>
+#
+# This library is free software; you can redistribute it and/or
+# modify it under the terms of the GNU Lesser General Public
+# License as published by the Free Software Foundation; either
+# version 2.1 of the License, or (at your option) any later version.
+#
+# This library is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+# Lesser General Public License for more details.
+#
+# You should have received a copy of the GNU Lesser General Public
+# License along with this library; if not, write to the Free Software
+# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+*/
+%module gpgme
+%include "cpointer.i"
+%include "cstring.i"
+
+/* Generate doc strings for all methods.
+
+ This will generate docstrings of the form
+
+ gpgme_op_encrypt(ctx, recp, flags, plain, cipher) -> gpgme_error_t
+
+ which we transform into
+
+ ctx.op_encrypt(recp, flags, plain, cipher) -> gpgme_error_t
+
+ for automagically wrapped functions. */
+%feature("autodoc", "0");
+
+
+/* Allow use of Unicode objects, bytes, and None for strings. */
+%typemap(in) const char *(PyObject *encodedInput = NULL) {
+ if ($input == Py_None)
+ $1 = NULL;
+ else if (PyUnicode_Check($input))
+ {
+ encodedInput = PyUnicode_AsUTF8String($input);
+ if (encodedInput == NULL)
+ return NULL;
+ $1 = PyBytes_AsString(encodedInput);
+ }
+ else if (PyBytes_Check($input))
+ $1 = PyBytes_AsString($input);
+ else {
+ PyErr_Format(PyExc_TypeError,
+ "arg %d: expected str, bytes, or None, got %s",
+ $argnum, $input->ob_type->tp_name);
+ return NULL;
+ }
+}
+%typemap(freearg) const char * {
+ Py_XDECREF(encodedInput$argnum);
+}
+
+/* Likewise for a list of strings. */
+%typemap(in) const char *[] (void *vector = NULL,
+ size_t size,
+ PyObject **pyVector = NULL) {
+ /* Check if is a list */
+ if (PyList_Check($input)) {
+ size_t i, j;
+ size = PyList_Size($input);
+ $1 = (char **) (vector = malloc((size+1) * sizeof(char *)));
+ pyVector = calloc(sizeof *pyVector, size);
+
+ for (i = 0; i < size; i++) {
+ PyObject *o = PyList_GetItem($input,i);
+ if (PyUnicode_Check(o))
+ {
+ pyVector[i] = PyUnicode_AsUTF8String(o);
+ if (pyVector[i] == NULL)
+ {
+ free(vector);
+ for (j = 0; j < i; j++)
+ Py_XDECREF(pyVector[j]);
+ return NULL;
+ }
+ $1[i] = PyBytes_AsString(pyVector[i]);
+ }
+ else if (PyString_Check(o))
+ $1[i] = PyString_AsString(o);
+ else {
+ PyErr_Format(PyExc_TypeError,
+ "arg %d: list must contain only str or bytes, got %s "
+ "at position %d",
+ $argnum, o->ob_type->tp_name, i);
+ free($1);
+ return NULL;
+ }
+ }
+ $1[i] = NULL;
+ } else {
+ PyErr_Format(PyExc_TypeError,
+ "arg %d: expected a list of str or bytes, got %s",
+ $argnum, $input->ob_type->tp_name);
+ return NULL;
+ }
+}
+%typemap(freearg) const char *[] {
+ size_t i;
+ free(vector$argnum);
+ for (i = 0; i < size$argnum; i++)
+ Py_XDECREF(pyVector$argnum[i]);
+}
+
+// Release returned buffers as necessary.
+%typemap(newfree) char * "free($1);";
+%newobject gpgme_data_release_and_get_mem;
+
+%typemap(arginit) gpgme_key_t [] {
+ $1 = NULL;
+}
+
+%typemap(in) gpgme_key_t [] {
+ int i, numb = 0;
+ if (!PySequence_Check($input)) {
+ PyErr_Format(PyExc_ValueError, "arg %d: Expected a list of gpgme_key_t",
+ $argnum);
+ return NULL;
+ }
+ if((numb = PySequence_Length($input)) != 0) {
+ $1 = (gpgme_key_t*)malloc((numb+1)*sizeof(gpgme_key_t));
+ for(i=0; i<numb; i++) {
+ PyObject *pypointer = PySequence_GetItem($input, i);
+
+ /* input = $input, 1 = $1, 1_descriptor = $1_descriptor */
+ /* &1_descriptor = $&1_descriptor *1_descriptor = $*1_descriptor */
+
+ // Following code is from swig's python.swg
+ if ((SWIG_ConvertPtr(pypointer,(void **) &$1[i], $*1_descriptor,SWIG_POINTER_EXCEPTION | $disown )) == -1) {
+ Py_DECREF(pypointer);
+ return NULL;
+ }
+ Py_DECREF(pypointer);
+ }
+ $1[numb] = NULL;
+ }
+}
+%typemap(freearg) gpgme_key_t [] {
+ if ($1) free($1);
+}
+
+// Special handling for references to our objects.
+%typemap(in) gpgme_data_t DATAIN (gpgme_data_t wrapper = NULL,
+ PyObject *bytesio = NULL,
+ Py_buffer view, int have_view = 0) {
+ /* If we create a temporary wrapper object, we will store it in
+ wrapperN, where N is $argnum. Here in this fragment, SWIG will
+ automatically append $argnum. */
+ memset(&view, 0, sizeof view);
+ if ($input == Py_None)
+ $1 = NULL;
+ else {
+ PyObject *pypointer;
+ pypointer = _pyme_obj2gpgme_data_t($input, $argnum, &wrapper,
+ &bytesio, &view);
+ if (pypointer == NULL)
+ return NULL;
+ have_view = !! view.obj;
+
+ /* input = $input, 1 = $1, 1_descriptor = $1_descriptor */
+
+ // Following code is from swig's python.swg
+
+ if ((SWIG_ConvertPtr(pypointer,(void **) &$1, $1_descriptor,
+ SWIG_POINTER_EXCEPTION | $disown )) == -1) {
+ Py_DECREF(pypointer);
+ return NULL;
+ }
+ Py_DECREF(pypointer);
+ }
+}
+
+#if HAVE_DATA_H
+/* If we are doing an in-tree build, we can use the internal
+ representation of struct gpgme_data for an very efficient check if
+ the buffer has been modified. */
+%{
+#include "src/data.h" /* For struct gpgme_data. */
+%}
+#endif
+
+%typemap(freearg) gpgme_data_t DATAIN {
+ /* See whether we need to update the Python buffer. */
+ if (resultobj && wrapper$argnum && view$argnum.buf)
+ {
+ int dirty;
+ char *new_data = NULL;
+ size_t new_size;
+
+#if HAVE_DATA_H
+ new_data = wrapper$argnum->data.mem.buffer;
+ new_size = wrapper$argnum->data.mem.length;
+ dirty = new_data != NULL;
+#else
+ new_data = gpgme_data_release_and_get_mem (wrapper$argnum, &new_size);
+ wrapper$argnum = NULL;
+ dirty = new_size != view$argnum.len
+ || memcmp (new_data, view$argnum.buf, view$argnum.len);
+#endif
+
+ if (dirty)
+ {
+ /* The buffer is dirty. */
+ if (view$argnum.readonly)
+ {
+ Py_XDECREF(resultobj);
+ resultobj = NULL;
+ PyErr_SetString(PyExc_ValueError,
+ "cannot update read-only buffer");
+ }
+
+ /* See if we need to truncate the buffer. */
+ if (resultobj && view$argnum.len != new_size)
+ {
+ if (bytesio$argnum == NULL)
+ {
+ Py_XDECREF(resultobj);
+ resultobj = NULL;
+ PyErr_SetString(PyExc_ValueError, "cannot resize buffer");
+ }
+ else
+ {
+ PyObject *retval;
+ PyBuffer_Release(&view$argnum);
+ assert(view$argnum.obj == NULL);
+ retval = PyObject_CallMethod(bytesio$argnum, "truncate",
+ "l", (long) new_size);
+ if (retval == NULL)
+ {
+ Py_XDECREF(resultobj);
+ resultobj = NULL;
+ }
+ else
+ {
+ Py_DECREF(retval);
+
+ retval = PyObject_CallMethod(bytesio$argnum,
+ "getbuffer", NULL);
+ if (retval == NULL
+ || PyObject_GetBuffer(retval, &view$argnum,
+ PyBUF_SIMPLE|PyBUF_WRITABLE) < 0)
+ {
+ Py_XDECREF(resultobj);
+ resultobj = NULL;
+ }
+
+ Py_XDECREF(retval);
+
+ if (resultobj && view$argnum.len
+ != new_size)
+ {
+ Py_XDECREF(resultobj);
+ resultobj = NULL;
+ PyErr_Format(PyExc_ValueError,
+ "Expected buffer of length %zu, got %zi",
+ new_size,
+ view$argnum.len);
+ }
+ }
+ }
+ }
+ if (resultobj)
+ memcpy(view$argnum.buf, new_data, new_size);
+ }
+#if ! HAVE_DATA_H
+ free (new_data);
+#endif
+ }
+
+ /* Free the temporary wrapper, if any. */
+ if (wrapper$argnum)
+ gpgme_data_release(wrapper$argnum);
+ Py_XDECREF (bytesio$argnum);
+ if (have_view$argnum && view$argnum.buf)
+ PyBuffer_Release(&view$argnum);
+}
+
+%apply gpgme_data_t DATAIN {gpgme_data_t plain, gpgme_data_t cipher,
+ gpgme_data_t sig, gpgme_data_t signed_text,
+ gpgme_data_t plaintext, gpgme_data_t keydata,
+ gpgme_data_t pubkey, gpgme_data_t seckey,
+ gpgme_data_t out};
+
+/* SWIG has problems interpreting ssize_t, off_t or gpgme_error_t in
+ gpgme.h. */
+/* XXX: This is wrong at least for off_t if compiled with LFS. */
+%typemap(out) ssize_t, off_t, gpgme_error_t, gpgme_err_code_t, gpgme_err_source_t, gpg_error_t {
+ $result = PyLong_FromLong($1);
+}
+/* XXX: This is wrong at least for off_t if compiled with LFS. */
+%typemap(in) ssize_t, off_t, gpgme_error_t, gpgme_err_code_t, gpgme_err_source_t, gpg_error_t {
+ $1 = PyLong_AsLong($input);
+}
+
+// Those are for gpgme_data_read() and gpgme_strerror_r()
+%typemap(in) (void *buffer, size_t size), (char *buf, size_t buflen) {
+ $2 = PyLong_AsLong($input);
+ if ($2 < 0) {
+ PyErr_SetString(PyExc_ValueError, "Positive integer expected");
+ return NULL;
+ }
+ $1 = ($1_ltype) malloc($2+1);
+}
+%typemap(argout) (void *buffer, size_t size), (char *buf, size_t buflen) {
+ Py_XDECREF($result); /* Blow away any previous result */
+ if (result < 0) { /* Check for I/O error */
+ free($1);
+ return PyErr_SetFromErrno(PyExc_RuntimeError);
+ }
+ $result = PyBytes_FromStringAndSize($1,result);
+ free($1);
+}
+
+/* For gpgme_data_write, but should be universal. */
+%typemap(in) (const void *buffer, size_t size)(PyObject *encodedInput = NULL) {
+ Py_ssize_t ssize;
+
+ if ($input == Py_None)
+ $1 = NULL, $2 = 0;
+ else if (PyUnicode_Check($input))
+ {
+ encodedInput = PyUnicode_AsUTF8String($input);
+ if (encodedInput == NULL)
+ return NULL;
+ if (PyBytes_AsStringAndSize(encodedInput, (char **) &$1, &ssize) == -1)
+ {
+ Py_DECREF(encodedInput);
+ return NULL;
+ }
+ }
+ else if (PyBytes_Check($input))
+ PyBytes_AsStringAndSize($input, (char **) &$1, &ssize);
+ else {
+ PyErr_Format(PyExc_TypeError,
+ "arg %d: expected str, bytes, or None, got %s",
+ $argnum, $input->ob_type->tp_name);
+ return NULL;
+ }
+
+ if (! $1)
+ $2 = 0;
+ else
+ {
+ assert (ssize >= 0);
+ $2 = (size_t) ssize;
+ }
+}
+%typemap(freearg) (const void *buffer, size_t size) {
+ Py_XDECREF(encodedInput$argnum);
+}
+
+// Make types containing 'next' field to be lists
+%ignore next;
+%typemap(out) gpgme_sig_notation_t, gpgme_subkey_t,
+ gpgme_key_sig_t, gpgme_user_id_t, gpgme_invalid_key_t,
+ gpgme_recipient_t, gpgme_new_signature_t, gpgme_signature_t,
+ gpgme_import_status_t, gpgme_conf_arg_t, gpgme_conf_opt_t,
+ gpgme_conf_comp_t, gpgme_tofu_info_t {
+ int i;
+ int size = 0;
+ $1_ltype curr;
+ for (curr = $1; curr != NULL; curr = curr->next) {
+ size++;
+ }
+ $result = PyList_New(size);
+ for (i=0,curr=$1; i<size; i++,curr=curr->next) {
+ PyObject *o = SWIG_NewPointerObj(SWIG_as_voidptr(curr), $1_descriptor, %newpointer_flags);
+ PyList_SetItem($result, i, o);
+ }
+}
+
+
+
+/* Wrap the fragile result objects into robust Python ones. */
+%typemap(out) gpgme_encrypt_result_t {
+ PyObject *fragile;
+ fragile = SWIG_NewPointerObj(SWIG_as_voidptr($1), $1_descriptor,
+ %newpointer_flags);
+ $result = _pyme_wrap_result(fragile, "EncryptResult");
+ Py_DECREF(fragile);
+}
+
+%typemap(out) gpgme_decrypt_result_t {
+ PyObject *fragile;
+ fragile = SWIG_NewPointerObj(SWIG_as_voidptr($1), $1_descriptor,
+ %newpointer_flags);
+ $result = _pyme_wrap_result(fragile, "DecryptResult");
+ Py_DECREF(fragile);
+}
+
+%typemap(out) gpgme_sign_result_t {
+ PyObject *fragile;
+ fragile = SWIG_NewPointerObj(SWIG_as_voidptr($1), $1_descriptor,
+ %newpointer_flags);
+ $result = _pyme_wrap_result(fragile, "SignResult");
+ Py_DECREF(fragile);
+}
+
+%typemap(out) gpgme_verify_result_t {
+ PyObject *fragile;
+ fragile = SWIG_NewPointerObj(SWIG_as_voidptr($1), $1_descriptor,
+ %newpointer_flags);
+ $result = _pyme_wrap_result(fragile, "VerifyResult");
+ Py_DECREF(fragile);
+}
+
+%typemap(out) gpgme_import_result_t {
+ PyObject *fragile;
+ fragile = SWIG_NewPointerObj(SWIG_as_voidptr($1), $1_descriptor,
+ %newpointer_flags);
+ $result = _pyme_wrap_result(fragile, "ImportResult");
+ Py_DECREF(fragile);
+}
+
+%typemap(out) gpgme_genkey_result_t {
+ PyObject *fragile;
+ fragile = SWIG_NewPointerObj(SWIG_as_voidptr($1), $1_descriptor,
+ %newpointer_flags);
+ $result = _pyme_wrap_result(fragile, "GenkeyResult");
+ Py_DECREF(fragile);
+}
+
+%typemap(out) gpgme_keylist_result_t {
+ PyObject *fragile;
+ fragile = SWIG_NewPointerObj(SWIG_as_voidptr($1), $1_descriptor,
+ %newpointer_flags);
+ $result = _pyme_wrap_result(fragile, "KeylistResult");
+ Py_DECREF(fragile);
+}
+
+%typemap(out) gpgme_vfs_mount_result_t {
+ PyObject *fragile;
+ fragile = SWIG_NewPointerObj(SWIG_as_voidptr($1), $1_descriptor,
+ %newpointer_flags);
+ $result = _pyme_wrap_result(fragile, "VFSMountResult");
+ Py_DECREF(fragile);
+}
+
+%typemap(out) gpgme_engine_info_t {
+ int i;
+ int size = 0;
+ $1_ltype curr;
+ for (curr = $1; curr != NULL; curr = curr->next) {
+ size++;
+ }
+ $result = PyList_New(size);
+ if ($result == NULL)
+ return NULL; /* raise */
+ for (i=0,curr=$1; i<size; i++,curr=curr->next) {
+ PyObject *fragile, *o;
+ fragile = SWIG_NewPointerObj(SWIG_as_voidptr(curr), $1_descriptor,
+ %newpointer_flags);
+ if (fragile == NULL)
+ {
+ Py_DECREF($result);
+ return NULL; /* raise */
+ }
+ o = _pyme_wrap_result(fragile, "EngineInfo");
+ Py_DECREF(fragile);
+ if (o == NULL)
+ {
+ Py_DECREF($result);
+ return NULL; /* raise */
+ }
+ PyList_SetItem($result, i, o);
+ }
+}
+
+
+
+/* Include mapper for interact callbacks. */
+%typemap(in) (gpgme_interact_cb_t fnc, void *fnc_value) {
+ if (! PyTuple_Check($input))
+ return PyErr_Format(PyExc_TypeError, "interact callback must be a tuple");
+ if (PyTuple_Size($input) != 2 && PyTuple_Size($input) != 3)
+ return PyErr_Format(PyExc_TypeError,
+ "interact callback must be a tuple of size 2 or 3");
+
+ $1 = (gpgme_interact_cb_t) _pyme_interact_cb;
+ $2 = $input;
+}
+
+
+
+/* The assuan protocol callbacks. */
+%typemap(in) (gpgme_assuan_data_cb_t data_cb, void *data_cb_value) {
+ if ($input == Py_None)
+ $1 = $2 = NULL;
+ else
+ {
+ if (! PyTuple_Check($input))
+ return PyErr_Format(PyExc_TypeError, "callback must be a tuple");
+ if (PyTuple_Size($input) != 2)
+ return PyErr_Format(PyExc_TypeError,
+ "callback must be a tuple of size 2");
+ if (! PyCallable_Check(PyTuple_GetItem($input, 1)))
+ return PyErr_Format(PyExc_TypeError, "second item must be callable");
+ $1 = _pyme_assuan_data_cb;
+ $2 = $input;
+ }
+}
+
+%typemap(in) (gpgme_assuan_inquire_cb_t inq_cb, void *inq_cb_value) {
+ if ($input == Py_None)
+ $1 = $2 = NULL;
+ else
+ {
+ if (! PyTuple_Check($input))
+ return PyErr_Format(PyExc_TypeError, "callback must be a tuple");
+ if (PyTuple_Size($input) != 2)
+ return PyErr_Format(PyExc_TypeError,
+ "callback must be a tuple of size 2");
+ if (! PyCallable_Check(PyTuple_GetItem($input, 1)))
+ return PyErr_Format(PyExc_TypeError, "second item must be callable");
+ $1 = _pyme_assuan_inquire_cb;
+ $2 = $input;
+ }
+}
+
+%typemap(in) (gpgme_assuan_status_cb_t stat_cb, void *stat_cb_value) {
+ if ($input == Py_None)
+ $1 = $2 = NULL;
+ else
+ {
+ if (! PyTuple_Check($input))
+ return PyErr_Format(PyExc_TypeError, "callback must be a tuple");
+ if (PyTuple_Size($input) != 2)
+ return PyErr_Format(PyExc_TypeError,
+ "callback must be a tuple of size 2");
+ if (! PyCallable_Check(PyTuple_GetItem($input, 1)))
+ return PyErr_Format(PyExc_TypeError, "second item must be callable");
+ $1 = _pyme_assuan_status_cb;
+ $2 = $input;
+ }
+}
+
+/* Include the unmodified <gpgme.h> for cc, and the cleaned-up local
+ version for SWIG. We do, however, want to hide certain fields on
+ some structs, which we provide prior to including the version for
+ SWIG. */
+%{
+#include <gpgme.h>
+%}
+
+/* This is for notations, where we want to hide the length fields, and
+ the unused bit field block. */
+struct _gpgme_sig_notation
+{
+ struct _gpgme_sig_notation *next;
+
+ /* If NAME is a null pointer, then VALUE contains a policy URL
+ rather than a notation. */
+ char *name;
+
+ /* The value of the notation data. */
+ char *value;
+
+ /* The accumulated flags. */
+ gpgme_sig_notation_flags_t flags;
+
+ /* Notation data is human-readable. */
+ unsigned int human_readable : 1;
+
+ /* Notation data is critical. */
+ unsigned int critical : 1;
+};
+
+/* Now include our local modified version. Any structs defined above
+ are ignored. */
+%include "gpgme.h"
+
+%include "errors.i"
+
+// Generating and handling pointers-to-pointers.
+
+%pointer_functions(gpgme_ctx_t, gpgme_ctx_t_p);
+%pointer_functions(gpgme_data_t, gpgme_data_t_p);
+%pointer_functions(gpgme_key_t, gpgme_key_t_p);
+%pointer_functions(gpgme_error_t, gpgme_error_t_p);
+%pointer_functions(gpgme_trust_item_t, gpgme_trust_item_t_p);
+%pointer_functions(gpgme_engine_info_t, gpgme_engine_info_t_p);
+
+// Helper functions.
+
+%{
+#include <stdio.h>
+%}
+FILE *fdopen(int fildes, const char *mode);
+
+/* We include both headers in the generated c code... */
+%{
+#include "helpers.h"
+#include "private.h"
+
+/* SWIG runtime support for helpers.c */
+PyObject *
+_pyme_wrap_gpgme_data_t(gpgme_data_t data)
+{
+ return SWIG_Python_NewPointerObj(NULL, data, SWIGTYPE_p_gpgme_data, 0);
+}
+
+gpgme_ctx_t
+_pyme_unwrap_gpgme_ctx_t(PyObject *wrapped)
+{
+ gpgme_ctx_t result;
+ if (SWIG_ConvertPtr(wrapped,
+ (void **) &result,
+ SWIGTYPE_p_gpgme_context,
+ SWIG_POINTER_EXCEPTION) == -1)
+ return NULL;
+ return result;
+}
+%}
+
+/* ... but only the public definitions here. They will be exposed to
+ the Python world, so let's be careful. */
+%include "helpers.h"
diff --git a/lang/python/helpers.c b/lang/python/helpers.c
new file mode 100644
index 0000000..f9aec91
--- /dev/null
+++ b/lang/python/helpers.c
@@ -0,0 +1,1169 @@
+/*
+# Copyright (C) 2016 g10 Code GmbH
+# Copyright (C) 2004 Igor Belyi <belyi@users.sourceforge.net>
+# Copyright (C) 2002 John Goerzen <jgoerzen@complete.org>
+#
+# This library is free software; you can redistribute it and/or
+# modify it under the terms of the GNU Lesser General Public
+# License as published by the Free Software Foundation; either
+# version 2.1 of the License, or (at your option) any later version.
+#
+# This library is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+# Lesser General Public License for more details.
+#
+# You should have received a copy of the GNU Lesser General Public
+# License along with this library; if not, write to the Free Software
+# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+*/
+
+#include <assert.h>
+#include <stdio.h>
+#include <gpgme.h>
+#include <stdlib.h>
+#include <string.h>
+#include "Python.h"
+
+#include "helpers.h"
+#include "private.h"
+
+/* Flag specifying whether this is an in-tree build. */
+int pyme_in_tree_build =
+#if IN_TREE_BUILD
+ 1
+#else
+ 0
+#endif
+ ;
+
+static PyObject *GPGMEError = NULL;
+
+void _pyme_exception_init(void) {
+ if (GPGMEError == NULL) {
+ PyObject *errors;
+ PyObject *from_list = PyList_New(0);
+ errors = PyImport_ImportModuleLevel("errors", PyEval_GetGlobals(),
+ PyEval_GetLocals(), from_list, 1);
+ Py_XDECREF(from_list);
+ if (errors) {
+ GPGMEError=PyDict_GetItemString(PyModule_GetDict(errors), "GPGMEError");
+ Py_XINCREF(GPGMEError);
+ }
+ }
+}
+
+static PyObject *
+_pyme_raise_exception(gpgme_error_t err)
+{
+ PyObject *e;
+
+ _pyme_exception_init();
+ if (GPGMEError == NULL)
+ return PyErr_Format(PyExc_RuntimeError, "Got gpgme_error_t %d", err);
+
+ e = PyObject_CallFunction(GPGMEError, "l", (long) err);
+ if (e == NULL)
+ return NULL;
+
+ PyErr_SetObject(GPGMEError, e);
+ Py_DECREF(e);
+
+ return NULL; /* raise */
+}
+
+gpgme_error_t _pyme_exception2code(void) {
+ gpgme_error_t err_status = gpg_error(GPG_ERR_GENERAL);
+ if (GPGMEError && PyErr_ExceptionMatches(GPGMEError)) {
+ PyObject *type = 0, *value = 0, *traceback = 0;
+ PyObject *error = 0;
+ PyErr_Fetch(&type, &value, &traceback);
+ PyErr_NormalizeException(&type, &value, &traceback);
+ error = PyObject_GetAttrString(value, "error");
+ err_status = PyLong_AsLong(error);
+ Py_DECREF(error);
+ PyErr_Restore(type, value, traceback);
+ }
+ return err_status;
+}
+
+/* Exception support for callbacks. */
+#define EXCINFO "_callback_excinfo"
+
+static void _pyme_stash_callback_exception(PyObject *weak_self)
+{
+ PyObject *self, *ptype, *pvalue, *ptraceback, *excinfo;
+
+ PyErr_Fetch(&ptype, &pvalue, &ptraceback);
+ excinfo = PyTuple_New(3);
+ PyTuple_SetItem(excinfo, 0, ptype);
+
+ if (pvalue)
+ PyTuple_SetItem(excinfo, 1, pvalue);
+ else {
+ Py_INCREF(Py_None);
+ PyTuple_SetItem(excinfo, 1, Py_None);
+ }
+
+ if (ptraceback)
+ PyTuple_SetItem(excinfo, 2, ptraceback);
+ else {
+ Py_INCREF(Py_None);
+ PyTuple_SetItem(excinfo, 2, Py_None);
+ }
+
+ self = PyWeakref_GetObject(weak_self);
+ /* self only has a borrowed reference. */
+ if (self == Py_None) {
+ /* This should not happen, as even if we're called from the data
+ release callback triggered from the wrappers destructor, the
+ object is still alive and hence the weak reference still refers
+ to the object. However, in case this ever changes, not seeing
+ any exceptions is worse than having a little extra code, so
+ here we go. */
+ fprintf(stderr,
+ "Error occurred in callback, but the wrapper object "
+ "has been deallocated.\n");
+ PyErr_Restore(ptype, pvalue, ptraceback);
+ PyErr_Print();
+ }
+ else
+ PyObject_SetAttrString(self, EXCINFO, excinfo);
+ Py_DECREF(excinfo);
+}
+
+PyObject *pyme_raise_callback_exception(PyObject *self)
+{
+ PyGILState_STATE state = PyGILState_Ensure();
+ PyObject *ptype, *pvalue, *ptraceback, *excinfo;
+
+ if (! PyObject_HasAttrString(self, EXCINFO))
+ goto leave;
+
+ excinfo = PyObject_GetAttrString(self, EXCINFO);
+ if (! PyTuple_Check(excinfo))
+ {
+ Py_DECREF(excinfo);
+ goto leave;
+ }
+
+ ptype = PyTuple_GetItem(excinfo, 0);
+ Py_INCREF(excinfo);
+
+ pvalue = PyTuple_GetItem(excinfo, 1);
+ if (pvalue == Py_None)
+ pvalue = NULL;
+ else
+ Py_INCREF(pvalue);
+
+ ptraceback = PyTuple_GetItem(excinfo, 2);
+ if (ptraceback == Py_None)
+ ptraceback = NULL;
+ else
+ Py_INCREF(ptraceback);
+
+ /* We now have references for the extracted items. */
+ Py_DECREF(excinfo);
+
+ /* Clear the exception information. It is important to do this
+ before setting the error, because setting the attribute may
+ execute python code, and the runtime system raises a SystemError
+ if an exception is set but values are returned. */
+ Py_INCREF(Py_None);
+ PyObject_SetAttrString(self, EXCINFO, Py_None);
+
+ /* Restore exception. */
+ PyErr_Restore(ptype, pvalue, ptraceback);
+ PyGILState_Release(state);
+ return NULL; /* Raise exception. */
+
+ leave:
+ Py_INCREF(Py_None);
+ PyGILState_Release(state);
+ return Py_None;
+}
+#undef EXCINFO
+
+/* Argument conversion. */
+
+/* Convert object to a pointer to gpgme type, generic version. */
+PyObject *
+_pyme_obj2gpgme_t(PyObject *input, const char *objtype, int argnum)
+{
+ PyObject *pyname = NULL, *pypointer = NULL;
+ pyname = PyObject_GetAttrString(input, "_ctype");
+ if (pyname && PyUnicode_Check(pyname))
+ {
+ PyObject *encoded = PyUnicode_AsUTF8String(pyname);
+ if (strcmp(PyBytes_AsString(encoded), objtype) != 0)
+ {
+ PyErr_Format(PyExc_TypeError,
+ "arg %d: Expected value of type %s, but got %s",
+ argnum, objtype, PyBytes_AsString(encoded));
+ Py_DECREF(encoded);
+ Py_DECREF(pyname);
+ return NULL;
+ }
+ Py_DECREF(encoded);
+ }
+ else
+ return NULL;
+
+ Py_DECREF(pyname);
+ pypointer = PyObject_GetAttrString(input, "wrapped");
+ if (pypointer == NULL) {
+ PyErr_Format(PyExc_TypeError,
+ "arg %d: Use of uninitialized Python object %s",
+ argnum, objtype);
+ return NULL;
+ }
+ return pypointer;
+}
+
+/* Convert object to a pointer to gpgme type, version for data
+ objects. Constructs a wrapper Python on the fly e.g. for file-like
+ objects with a fileno method, returning it in WRAPPER. This object
+ must be de-referenced when no longer needed. */
+PyObject *
+_pyme_obj2gpgme_data_t(PyObject *input, int argnum, gpgme_data_t *wrapper,
+ PyObject **bytesio, Py_buffer *view)
+{
+ gpgme_error_t err;
+ PyObject *data;
+ PyObject *fd;
+
+ /* See if it is a file-like object with file number. */
+ fd = PyObject_CallMethod(input, "fileno", NULL);
+ if (fd) {
+ err = gpgme_data_new_from_fd(wrapper, (int) PyLong_AsLong(fd));
+ Py_DECREF(fd);
+ if (err)
+ return _pyme_raise_exception (err);
+
+ return _pyme_wrap_gpgme_data_t(*wrapper);
+ }
+ else
+ PyErr_Clear();
+
+ /* No? Maybe it implements the buffer protocol. */
+ data = PyObject_CallMethod(input, "getbuffer", NULL);
+ if (data)
+ {
+ /* Save a reference to input, which seems to be a BytesIO
+ object. */
+ Py_INCREF(input);
+ *bytesio = input;
+ }
+ else
+ {
+ PyErr_Clear();
+
+ /* No, but maybe the user supplied a buffer object? */
+ data = input;
+ }
+
+ /* Do we have a buffer object? */
+ if (PyObject_CheckBuffer(data))
+ {
+ if (PyObject_GetBuffer(data, view, PyBUF_SIMPLE) < 0)
+ return NULL;
+
+ if (data != input)
+ Py_DECREF(data);
+
+ assert (view->obj);
+ assert (view->ndim == 1);
+ assert (view->shape == NULL);
+ assert (view->strides == NULL);
+ assert (view->suboffsets == NULL);
+
+ err = gpgme_data_new_from_mem(wrapper, view->buf, (size_t) view->len, 0);
+ if (err)
+ return _pyme_raise_exception (err);
+
+ return _pyme_wrap_gpgme_data_t(*wrapper);
+ }
+
+ /* As last resort we assume it is a wrapped data object. */
+ if (PyObject_HasAttrString(data, "_ctype"))
+ return _pyme_obj2gpgme_t(data, "gpgme_data_t", argnum);
+
+ return PyErr_Format(PyExc_TypeError,
+ "arg %d: expected pyme.Data, file, or an object "
+ "implementing the buffer protocol, got %s",
+ argnum, data->ob_type->tp_name);
+}
+
+
+
+PyObject *
+_pyme_wrap_result(PyObject *fragile, const char *classname)
+{
+ static PyObject *results;
+ PyObject *class;
+ PyObject *replacement;
+
+ if (results == NULL)
+ {
+ PyObject *from_list = PyList_New(0);
+ if (from_list == NULL)
+ return NULL;
+
+ results = PyImport_ImportModuleLevel("results", PyEval_GetGlobals(),
+ PyEval_GetLocals(), from_list, 1);
+ Py_DECREF(from_list);
+
+ if (results == NULL)
+ return NULL;
+ }
+
+ class = PyMapping_GetItemString(PyModule_GetDict(results), classname);
+ if (class == NULL)
+ return NULL;
+
+ replacement = PyObject_CallFunctionObjArgs(class, fragile, NULL);
+ Py_DECREF(class);
+ return replacement;
+}
+
+
+
+/* Callback support. */
+static gpgme_error_t pyPassphraseCb(void *hook,
+ const char *uid_hint,
+ const char *passphrase_info,
+ int prev_was_bad,
+ int fd) {
+ PyGILState_STATE state = PyGILState_Ensure();
+ PyObject *pyhook = (PyObject *) hook;
+ PyObject *self = NULL;
+ PyObject *func = NULL;
+ PyObject *args = NULL;
+ PyObject *retval = NULL;
+ PyObject *dataarg = NULL;
+ PyObject *encoded = NULL;
+ gpgme_error_t err_status = 0;
+
+ _pyme_exception_init();
+
+ assert (PyTuple_Check(pyhook));
+ assert (PyTuple_Size(pyhook) == 2 || PyTuple_Size(pyhook) == 3);
+ self = PyTuple_GetItem(pyhook, 0);
+ func = PyTuple_GetItem(pyhook, 1);
+ if (PyTuple_Size(pyhook) == 3) {
+ dataarg = PyTuple_GetItem(pyhook, 2);
+ args = PyTuple_New(4);
+ } else {
+ args = PyTuple_New(3);
+ }
+
+ if (uid_hint == NULL)
+ {
+ Py_INCREF(Py_None);
+ PyTuple_SetItem(args, 0, Py_None);
+ }
+ else
+ PyTuple_SetItem(args, 0, PyUnicode_DecodeUTF8(uid_hint, strlen (uid_hint),
+ "strict"));
+ if (PyErr_Occurred()) {
+ Py_DECREF(args);
+ err_status = gpg_error(GPG_ERR_GENERAL);
+ goto leave;
+ }
+
+ PyTuple_SetItem(args, 1, PyBytes_FromString(passphrase_info));
+ PyTuple_SetItem(args, 2, PyBool_FromLong((long)prev_was_bad));
+ if (dataarg) {
+ Py_INCREF(dataarg); /* Because GetItem doesn't give a ref but SetItem taketh away */
+ PyTuple_SetItem(args, 3, dataarg);
+ }
+
+ retval = PyObject_CallObject(func, args);
+ Py_DECREF(args);
+ if (PyErr_Occurred()) {
+ err_status = _pyme_exception2code();
+ } else {
+ if (!retval) {
+ if (write(fd, "\n", 1) < 0) {
+ err_status = gpgme_error_from_syserror ();
+ _pyme_raise_exception (err_status);
+ }
+ } else {
+ char *buf;
+ size_t len;
+ if (PyBytes_Check(retval))
+ buf = PyBytes_AsString(retval), len = PyBytes_Size(retval);
+ else if (PyUnicode_Check(retval))
+ {
+ Py_ssize_t ssize;
+ encoded = PyUnicode_AsUTF8String(retval);
+ if (encoded == NULL)
+ {
+ err_status = gpg_error(GPG_ERR_GENERAL);
+ goto leave;
+ }
+ if (PyBytes_AsStringAndSize(encoded, &buf, &ssize) == -1)
+ {
+ err_status = gpg_error(GPG_ERR_GENERAL);
+ goto leave;
+ }
+ assert (! buf || ssize >= 0);
+ len = (size_t) ssize;
+ }
+ else
+ {
+ PyErr_Format(PyExc_TypeError,
+ "expected str or bytes from passphrase callback, got %s",
+ retval->ob_type->tp_name);
+ err_status = gpg_error(GPG_ERR_GENERAL);
+ goto leave;
+ }
+
+ if (write(fd, buf, len) < 0) {
+ err_status = gpgme_error_from_syserror ();
+ _pyme_raise_exception (err_status);
+ }
+ if (! err_status && write(fd, "\n", 1) < 0) {
+ err_status = gpgme_error_from_syserror ();
+ _pyme_raise_exception (err_status);
+ }
+
+ Py_DECREF(retval);
+ }
+ }
+
+ leave:
+ if (err_status)
+ _pyme_stash_callback_exception(self);
+
+ Py_XDECREF(encoded);
+ PyGILState_Release(state);
+ return err_status;
+}
+
+PyObject *
+pyme_set_passphrase_cb(PyObject *self, PyObject *cb) {
+ PyGILState_STATE state = PyGILState_Ensure();
+ PyObject *wrapped;
+ gpgme_ctx_t ctx;
+
+ wrapped = PyObject_GetAttrString(self, "wrapped");
+ if (wrapped == NULL)
+ {
+ assert (PyErr_Occurred ());
+ PyGILState_Release(state);
+ return NULL;
+ }
+
+ ctx = _pyme_unwrap_gpgme_ctx_t(wrapped);
+ Py_DECREF(wrapped);
+ if (ctx == NULL)
+ {
+ if (cb == Py_None)
+ goto out;
+ else
+ return PyErr_Format(PyExc_RuntimeError, "wrapped is NULL");
+ }
+
+ if (cb == Py_None) {
+ gpgme_set_passphrase_cb(ctx, NULL, NULL);
+ PyObject_SetAttrString(self, "_passphrase_cb", Py_None);
+ goto out;
+ }
+
+ if (! PyTuple_Check(cb))
+ return PyErr_Format(PyExc_TypeError, "cb must be a tuple");
+ if (PyTuple_Size(cb) != 2 && PyTuple_Size(cb) != 3)
+ return PyErr_Format(PyExc_TypeError,
+ "cb must be a tuple of size 2 or 3");
+
+ gpgme_set_passphrase_cb(ctx, (gpgme_passphrase_cb_t) pyPassphraseCb,
+ (void *) cb);
+ PyObject_SetAttrString(self, "_passphrase_cb", cb);
+
+ out:
+ Py_INCREF(Py_None);
+ PyGILState_Release(state);
+ return Py_None;
+}
+
+static void pyProgressCb(void *hook, const char *what, int type, int current,
+ int total) {
+ PyGILState_STATE state = PyGILState_Ensure();
+ PyObject *func = NULL, *dataarg = NULL, *args = NULL, *retval = NULL;
+ PyObject *pyhook = (PyObject *) hook;
+ PyObject *self = NULL;
+
+ assert (PyTuple_Check(pyhook));
+ assert (PyTuple_Size(pyhook) == 2 || PyTuple_Size(pyhook) == 3);
+ self = PyTuple_GetItem(pyhook, 0);
+ func = PyTuple_GetItem(pyhook, 1);
+ if (PyTuple_Size(pyhook) == 3) {
+ dataarg = PyTuple_GetItem(pyhook, 2);
+ args = PyTuple_New(5);
+ } else {
+ args = PyTuple_New(4);
+ }
+
+ PyTuple_SetItem(args, 0, PyUnicode_DecodeUTF8(what, strlen (what),
+ "strict"));
+ if (PyErr_Occurred()) {
+ _pyme_stash_callback_exception(self);
+ Py_DECREF(args);
+ PyGILState_Release(state);
+ return;
+ }
+ PyTuple_SetItem(args, 1, PyLong_FromLong((long) type));
+ PyTuple_SetItem(args, 2, PyLong_FromLong((long) current));
+ PyTuple_SetItem(args, 3, PyLong_FromLong((long) total));
+ if (dataarg) {
+ Py_INCREF(dataarg); /* Because GetItem doesn't give a ref but SetItem taketh away */
+ PyTuple_SetItem(args, 4, dataarg);
+ }
+
+ retval = PyObject_CallObject(func, args);
+ if (PyErr_Occurred())
+ _pyme_stash_callback_exception(self);
+ Py_DECREF(args);
+ Py_XDECREF(retval);
+ PyGILState_Release(state);
+}
+
+PyObject *
+pyme_set_progress_cb(PyObject *self, PyObject *cb) {
+ PyGILState_STATE state = PyGILState_Ensure();
+ PyObject *wrapped;
+ gpgme_ctx_t ctx;
+
+ wrapped = PyObject_GetAttrString(self, "wrapped");
+ if (wrapped == NULL)
+ {
+ assert (PyErr_Occurred ());
+ PyGILState_Release(state);
+ return NULL;
+ }
+
+ ctx = _pyme_unwrap_gpgme_ctx_t(wrapped);
+ Py_DECREF(wrapped);
+ if (ctx == NULL)
+ {
+ if (cb == Py_None)
+ goto out;
+ else
+ return PyErr_Format(PyExc_RuntimeError, "wrapped is NULL");
+ }
+
+ if (cb == Py_None) {
+ gpgme_set_progress_cb(ctx, NULL, NULL);
+ PyObject_SetAttrString(self, "_progress_cb", Py_None);
+ goto out;
+ }
+
+ if (! PyTuple_Check(cb))
+ return PyErr_Format(PyExc_TypeError, "cb must be a tuple");
+ if (PyTuple_Size(cb) != 2 && PyTuple_Size(cb) != 3)
+ return PyErr_Format(PyExc_TypeError,
+ "cb must be a tuple of size 2 or 3");
+
+ gpgme_set_progress_cb(ctx, (gpgme_progress_cb_t) pyProgressCb, (void *) cb);
+ PyObject_SetAttrString(self, "_progress_cb", cb);
+
+ out:
+ Py_INCREF(Py_None);
+ PyGILState_Release(state);
+ return Py_None;
+}
+
+/* Status callbacks. */
+static gpgme_error_t pyStatusCb(void *hook, const char *keyword,
+ const char *args) {
+ PyGILState_STATE state = PyGILState_Ensure();
+ gpgme_error_t err = 0;
+ PyObject *pyhook = (PyObject *) hook;
+ PyObject *self = NULL;
+ PyObject *func = NULL;
+ PyObject *dataarg = NULL;
+ PyObject *pyargs = NULL;
+ PyObject *retval = NULL;
+
+ assert (PyTuple_Check(pyhook));
+ assert (PyTuple_Size(pyhook) == 2 || PyTuple_Size(pyhook) == 3);
+ self = PyTuple_GetItem(pyhook, 0);
+ func = PyTuple_GetItem(pyhook, 1);
+ if (PyTuple_Size(pyhook) == 3) {
+ dataarg = PyTuple_GetItem(pyhook, 2);
+ pyargs = PyTuple_New(3);
+ } else {
+ pyargs = PyTuple_New(2);
+ }
+
+ if (keyword)
+ PyTuple_SetItem(pyargs, 0, PyUnicode_DecodeUTF8(keyword, strlen (keyword),
+ "strict"));
+ else
+ {
+ Py_INCREF(Py_None);
+ PyTuple_SetItem(pyargs, 0, Py_None);
+ }
+ PyTuple_SetItem(pyargs, 1, PyUnicode_DecodeUTF8(args, strlen (args),
+ "strict"));
+ if (PyErr_Occurred()) {
+ err = gpg_error(GPG_ERR_GENERAL);
+ Py_DECREF(pyargs);
+ goto leave;
+ }
+
+ if (dataarg) {
+ Py_INCREF(dataarg);
+ PyTuple_SetItem(pyargs, 2, dataarg);
+ }
+
+ retval = PyObject_CallObject(func, pyargs);
+ if (PyErr_Occurred())
+ err = _pyme_exception2code();
+ Py_DECREF(pyargs);
+ Py_XDECREF(retval);
+
+ leave:
+ if (err)
+ _pyme_stash_callback_exception(self);
+ PyGILState_Release(state);
+ return err;
+}
+
+PyObject *
+pyme_set_status_cb(PyObject *self, PyObject *cb) {
+ PyGILState_STATE state = PyGILState_Ensure();
+ PyObject *wrapped;
+ gpgme_ctx_t ctx;
+
+ wrapped = PyObject_GetAttrString(self, "wrapped");
+ if (wrapped == NULL)
+ {
+ assert (PyErr_Occurred ());
+ PyGILState_Release(state);
+ return NULL;
+ }
+
+ ctx = _pyme_unwrap_gpgme_ctx_t(wrapped);
+ Py_DECREF(wrapped);
+ if (ctx == NULL)
+ {
+ if (cb == Py_None)
+ goto out;
+ else
+ return PyErr_Format(PyExc_RuntimeError, "wrapped is NULL");
+ }
+
+ if (cb == Py_None) {
+ gpgme_set_status_cb(ctx, NULL, NULL);
+ PyObject_SetAttrString(self, "_status_cb", Py_None);
+ goto out;
+ }
+
+ if (! PyTuple_Check(cb))
+ return PyErr_Format(PyExc_TypeError, "cb must be a tuple");
+ if (PyTuple_Size(cb) != 2 && PyTuple_Size(cb) != 3)
+ return PyErr_Format(PyExc_TypeError,
+ "cb must be a tuple of size 2 or 3");
+
+ gpgme_set_status_cb(ctx, (gpgme_status_cb_t) pyStatusCb, (void *) cb);
+ PyObject_SetAttrString(self, "_status_cb", cb);
+
+ out:
+ Py_INCREF(Py_None);
+ PyGILState_Release(state);
+ return Py_None;
+}
+
+
+
+/* Interact callbacks. */
+gpgme_error_t
+_pyme_interact_cb(void *opaque, const char *keyword,
+ const char *args, int fd)
+{
+ PyGILState_STATE state = PyGILState_Ensure();
+ PyObject *func = NULL, *dataarg = NULL, *pyargs = NULL, *retval = NULL;
+ PyObject *py_keyword;
+ PyObject *pyopaque = (PyObject *) opaque;
+ gpgme_error_t err_status = 0;
+ PyObject *self = NULL;
+
+ _pyme_exception_init();
+
+ assert (PyTuple_Check(pyopaque));
+ assert (PyTuple_Size(pyopaque) == 2 || PyTuple_Size(pyopaque) == 3);
+ self = PyTuple_GetItem(pyopaque, 0);
+ func = PyTuple_GetItem(pyopaque, 1);
+ if (PyTuple_Size(pyopaque) == 3) {
+ dataarg = PyTuple_GetItem(pyopaque, 2);
+ pyargs = PyTuple_New(3);
+ } else {
+ pyargs = PyTuple_New(2);
+ }
+
+ if (keyword)
+ py_keyword = PyUnicode_FromString(keyword);
+ else
+ {
+ Py_INCREF(Py_None);
+ py_keyword = Py_None;
+ }
+
+ PyTuple_SetItem(pyargs, 0, py_keyword);
+ PyTuple_SetItem(pyargs, 1, PyUnicode_FromString(args));
+ if (dataarg) {
+ Py_INCREF(dataarg); /* Because GetItem doesn't give a ref but SetItem taketh away */
+ PyTuple_SetItem(pyargs, 2, dataarg);
+ }
+
+ retval = PyObject_CallObject(func, pyargs);
+ Py_DECREF(pyargs);
+ if (PyErr_Occurred()) {
+ err_status = _pyme_exception2code();
+ } else {
+ if (fd>=0 && retval && PyUnicode_Check(retval)) {
+ PyObject *encoded = NULL;
+ char *buffer;
+ Py_ssize_t size;
+
+ encoded = PyUnicode_AsUTF8String(retval);
+ if (encoded == NULL)
+ {
+ err_status = gpg_error(GPG_ERR_GENERAL);
+ goto leave;
+ }
+ if (PyBytes_AsStringAndSize(encoded, &buffer, &size) == -1)
+ {
+ Py_DECREF(encoded);
+ err_status = gpg_error(GPG_ERR_GENERAL);
+ goto leave;
+ }
+
+ if (write(fd, buffer, size) < 0) {
+ err_status = gpgme_error_from_syserror ();
+ _pyme_raise_exception (err_status);
+ }
+ if (! err_status && write(fd, "\n", 1) < 0) {
+ err_status = gpgme_error_from_syserror ();
+ _pyme_raise_exception (err_status);
+ }
+ Py_DECREF(encoded);
+ }
+ }
+ leave:
+ if (err_status)
+ _pyme_stash_callback_exception(self);
+
+ Py_XDECREF(retval);
+ PyGILState_Release(state);
+ return err_status;
+}
+
+
+
+/* Data callbacks. */
+
+/* Read up to SIZE bytes into buffer BUFFER from the data object with
+ the handle HOOK. Return the number of characters read, 0 on EOF
+ and -1 on error. If an error occurs, errno is set. */
+static ssize_t pyDataReadCb(void *hook, void *buffer, size_t size)
+{
+ PyGILState_STATE state = PyGILState_Ensure();
+ ssize_t result;
+ PyObject *pyhook = (PyObject *) hook;
+ PyObject *self = NULL;
+ PyObject *func = NULL;
+ PyObject *dataarg = NULL;
+ PyObject *pyargs = NULL;
+ PyObject *retval = NULL;
+
+ assert (PyTuple_Check(pyhook));
+ assert (PyTuple_Size(pyhook) == 5 || PyTuple_Size(pyhook) == 6);
+
+ self = PyTuple_GetItem(pyhook, 0);
+ func = PyTuple_GetItem(pyhook, 1);
+ if (PyTuple_Size(pyhook) == 6) {
+ dataarg = PyTuple_GetItem(pyhook, 5);
+ pyargs = PyTuple_New(2);
+ } else {
+ pyargs = PyTuple_New(1);
+ }
+
+ PyTuple_SetItem(pyargs, 0, PyLong_FromSize_t(size));
+ if (dataarg) {
+ Py_INCREF(dataarg);
+ PyTuple_SetItem(pyargs, 1, dataarg);
+ }
+
+ retval = PyObject_CallObject(func, pyargs);
+ Py_DECREF(pyargs);
+ if (PyErr_Occurred()) {
+ _pyme_stash_callback_exception(self);
+ result = -1;
+ goto leave;
+ }
+
+ if (! PyBytes_Check(retval)) {
+ PyErr_Format(PyExc_TypeError,
+ "expected bytes from read callback, got %s",
+ retval->ob_type->tp_name);
+ _pyme_stash_callback_exception(self);
+ result = -1;
+ goto leave;
+ }
+
+ if (PyBytes_Size(retval) > size) {
+ PyErr_Format(PyExc_TypeError,
+ "expected %zu bytes from read callback, got %zu",
+ size, PyBytes_Size(retval));
+ _pyme_stash_callback_exception(self);
+ result = -1;
+ goto leave;
+ }
+
+ memcpy(buffer, PyBytes_AsString(retval), PyBytes_Size(retval));
+ result = PyBytes_Size(retval);
+
+ leave:
+ Py_XDECREF(retval);
+ PyGILState_Release(state);
+ return result;
+}
+
+/* Write up to SIZE bytes from buffer BUFFER to the data object with
+ the handle HOOK. Return the number of characters written, or -1
+ on error. If an error occurs, errno is set. */
+static ssize_t pyDataWriteCb(void *hook, const void *buffer, size_t size)
+{
+ PyGILState_STATE state = PyGILState_Ensure();
+ ssize_t result;
+ PyObject *pyhook = (PyObject *) hook;
+ PyObject *self = NULL;
+ PyObject *func = NULL;
+ PyObject *dataarg = NULL;
+ PyObject *pyargs = NULL;
+ PyObject *retval = NULL;
+
+ assert (PyTuple_Check(pyhook));
+ assert (PyTuple_Size(pyhook) == 5 || PyTuple_Size(pyhook) == 6);
+
+ self = PyTuple_GetItem(pyhook, 0);
+ func = PyTuple_GetItem(pyhook, 2);
+ if (PyTuple_Size(pyhook) == 6) {
+ dataarg = PyTuple_GetItem(pyhook, 5);
+ pyargs = PyTuple_New(2);
+ } else {
+ pyargs = PyTuple_New(1);
+ }
+
+ PyTuple_SetItem(pyargs, 0, PyBytes_FromStringAndSize(buffer, size));
+ if (dataarg) {
+ Py_INCREF(dataarg);
+ PyTuple_SetItem(pyargs, 1, dataarg);
+ }
+
+ retval = PyObject_CallObject(func, pyargs);
+ Py_DECREF(pyargs);
+ if (PyErr_Occurred()) {
+ _pyme_stash_callback_exception(self);
+ result = -1;
+ goto leave;
+ }
+
+#if PY_MAJOR_VERSION < 3
+ if (PyInt_Check(retval))
+ result = PyInt_AsSsize_t(retval);
+ else
+#endif
+ if (PyLong_Check(retval))
+ result = PyLong_AsSsize_t(retval);
+ else {
+ PyErr_Format(PyExc_TypeError,
+ "expected int from write callback, got %s",
+ retval->ob_type->tp_name);
+ _pyme_stash_callback_exception(self);
+ result = -1;
+ }
+
+ leave:
+ Py_XDECREF(retval);
+ PyGILState_Release(state);
+ return result;
+}
+
+/* Set the current position from where the next read or write starts
+ in the data object with the handle HOOK to OFFSET, relativ to
+ WHENCE. Returns the new offset in bytes from the beginning of the
+ data object. */
+static off_t pyDataSeekCb(void *hook, off_t offset, int whence)
+{
+ PyGILState_STATE state = PyGILState_Ensure();
+ off_t result;
+ PyObject *pyhook = (PyObject *) hook;
+ PyObject *self = NULL;
+ PyObject *func = NULL;
+ PyObject *dataarg = NULL;
+ PyObject *pyargs = NULL;
+ PyObject *retval = NULL;
+
+ assert (PyTuple_Check(pyhook));
+ assert (PyTuple_Size(pyhook) == 5 || PyTuple_Size(pyhook) == 6);
+
+ self = PyTuple_GetItem(pyhook, 0);
+ func = PyTuple_GetItem(pyhook, 3);
+ if (PyTuple_Size(pyhook) == 6) {
+ dataarg = PyTuple_GetItem(pyhook, 5);
+ pyargs = PyTuple_New(3);
+ } else {
+ pyargs = PyTuple_New(2);
+ }
+
+#if defined(_FILE_OFFSET_BITS) && _FILE_OFFSET_BITS == 64
+ PyTuple_SetItem(pyargs, 0, PyLong_FromLongLong((long long) offset));
+#else
+ PyTuple_SetItem(pyargs, 0, PyLong_FromLong((long) offset));
+#endif
+ PyTuple_SetItem(pyargs, 1, PyLong_FromLong((long) whence));
+ if (dataarg) {
+ Py_INCREF(dataarg);
+ PyTuple_SetItem(pyargs, 2, dataarg);
+ }
+
+ retval = PyObject_CallObject(func, pyargs);
+ Py_DECREF(pyargs);
+ if (PyErr_Occurred()) {
+ _pyme_stash_callback_exception(self);
+ result = -1;
+ goto leave;
+ }
+
+#if PY_MAJOR_VERSION < 3
+ if (PyInt_Check(retval))
+ result = PyInt_AsLong(retval);
+ else
+#endif
+ if (PyLong_Check(retval))
+#if defined(_FILE_OFFSET_BITS) && _FILE_OFFSET_BITS == 64
+ result = PyLong_AsLongLong(retval);
+#else
+ result = PyLong_AsLong(retval);
+#endif
+ else {
+ PyErr_Format(PyExc_TypeError,
+ "expected int from seek callback, got %s",
+ retval->ob_type->tp_name);
+ _pyme_stash_callback_exception(self);
+ result = -1;
+ }
+
+ leave:
+ Py_XDECREF(retval);
+ PyGILState_Release(state);
+ return result;
+}
+
+/* Close the data object with the handle HOOK. */
+static void pyDataReleaseCb(void *hook)
+{
+ PyGILState_STATE state = PyGILState_Ensure();
+ PyObject *pyhook = (PyObject *) hook;
+ PyObject *self = NULL;
+ PyObject *func = NULL;
+ PyObject *dataarg = NULL;
+ PyObject *pyargs = NULL;
+ PyObject *retval = NULL;
+
+ assert (PyTuple_Check(pyhook));
+ assert (PyTuple_Size(pyhook) == 5 || PyTuple_Size(pyhook) == 6);
+
+ self = PyTuple_GetItem(pyhook, 0);
+ func = PyTuple_GetItem(pyhook, 4);
+ if (PyTuple_Size(pyhook) == 6) {
+ dataarg = PyTuple_GetItem(pyhook, 5);
+ pyargs = PyTuple_New(1);
+ } else {
+ pyargs = PyTuple_New(0);
+ }
+
+ if (dataarg) {
+ Py_INCREF(dataarg);
+ PyTuple_SetItem(pyargs, 0, dataarg);
+ }
+
+ retval = PyObject_CallObject(func, pyargs);
+ Py_XDECREF(retval);
+ Py_DECREF(pyargs);
+ if (PyErr_Occurred())
+ _pyme_stash_callback_exception(self);
+ PyGILState_Release(state);
+}
+
+PyObject *
+pyme_data_new_from_cbs(PyObject *self,
+ PyObject *pycbs,
+ gpgme_data_t *r_data)
+{
+ PyGILState_STATE state = PyGILState_Ensure();
+ static struct gpgme_data_cbs cbs = {
+ pyDataReadCb,
+ pyDataWriteCb,
+ pyDataSeekCb,
+ pyDataReleaseCb,
+ };
+ gpgme_error_t err;
+
+ if (! PyTuple_Check(pycbs))
+ return PyErr_Format(PyExc_TypeError, "pycbs must be a tuple");
+ if (PyTuple_Size(pycbs) != 5 && PyTuple_Size(pycbs) != 6)
+ return PyErr_Format(PyExc_TypeError,
+ "pycbs must be a tuple of size 5 or 6");
+
+ err = gpgme_data_new_from_cbs(r_data, &cbs, (void *) pycbs);
+ if (err)
+ return _pyme_raise_exception(err);
+
+ PyObject_SetAttrString(self, "_data_cbs", pycbs);
+
+ Py_INCREF(Py_None);
+ PyGILState_Release(state);
+ return Py_None;
+}
+
+
+
+/* The assuan callbacks. */
+
+gpgme_error_t
+_pyme_assuan_data_cb (void *hook, const void *data, size_t datalen)
+{
+ PyGILState_STATE state = PyGILState_Ensure();
+ gpgme_error_t err = 0;
+ PyObject *pyhook = (PyObject *) hook;
+ PyObject *self = NULL;
+ PyObject *func = NULL;
+ PyObject *py_data = NULL;
+ PyObject *retval = NULL;
+
+ assert (PyTuple_Check(pyhook));
+ assert (PyTuple_Size(pyhook) == 2);
+ self = PyTuple_GetItem(pyhook, 0);
+ func = PyTuple_GetItem(pyhook, 1);
+ assert (PyCallable_Check(func));
+
+ py_data = PyBytes_FromStringAndSize(data, datalen);
+ if (py_data == NULL)
+ {
+ err = _pyme_exception2code();
+ goto leave;
+ }
+
+ retval = PyObject_CallFunctionObjArgs(func, py_data, NULL);
+ if (PyErr_Occurred())
+ err = _pyme_exception2code();
+ Py_DECREF(py_data);
+ Py_XDECREF(retval);
+
+ leave:
+ if (err)
+ _pyme_stash_callback_exception(self);
+ PyGILState_Release(state);
+ return err;
+}
+
+gpgme_error_t
+_pyme_assuan_inquire_cb (void *hook, const char *name, const char *args,
+ gpgme_data_t *r_data)
+{
+ PyGILState_STATE state = PyGILState_Ensure();
+ gpgme_error_t err = 0;
+ PyObject *pyhook = (PyObject *) hook;
+ PyObject *self = NULL;
+ PyObject *func = NULL;
+ PyObject *py_name = NULL;
+ PyObject *py_args = NULL;
+ PyObject *retval = NULL;
+
+ assert (PyTuple_Check(pyhook));
+ assert (PyTuple_Size(pyhook) == 2);
+ self = PyTuple_GetItem(pyhook, 0);
+ func = PyTuple_GetItem(pyhook, 1);
+ assert (PyCallable_Check(func));
+
+ py_name = PyUnicode_FromString(name);
+ if (py_name == NULL)
+ {
+ err = _pyme_exception2code();
+ goto leave;
+ }
+
+ py_args = PyUnicode_FromString(args);
+ if (py_args == NULL)
+ {
+ err = _pyme_exception2code();
+ goto leave;
+ }
+
+ retval = PyObject_CallFunctionObjArgs(func, py_name, py_args, NULL);
+ if (PyErr_Occurred())
+ err = _pyme_exception2code();
+ Py_XDECREF(retval);
+
+ /* FIXME: Returning data is not yet implemented. */
+ *r_data = NULL;
+
+ leave:
+ Py_XDECREF(py_name);
+ Py_XDECREF(py_args);
+ if (err)
+ _pyme_stash_callback_exception(self);
+ PyGILState_Release(state);
+ return err;
+}
+
+gpgme_error_t
+_pyme_assuan_status_cb (void *hook, const char *status, const char *args)
+{
+ PyGILState_STATE state = PyGILState_Ensure();
+ gpgme_error_t err = 0;
+ PyObject *pyhook = (PyObject *) hook;
+ PyObject *self = NULL;
+ PyObject *func = NULL;
+ PyObject *py_status = NULL;
+ PyObject *py_args = NULL;
+ PyObject *retval = NULL;
+
+ assert (PyTuple_Check(pyhook));
+ assert (PyTuple_Size(pyhook) == 2);
+ self = PyTuple_GetItem(pyhook, 0);
+ func = PyTuple_GetItem(pyhook, 1);
+ assert (PyCallable_Check(func));
+
+ py_status = PyUnicode_FromString(status);
+ if (py_status == NULL)
+ {
+ err = _pyme_exception2code();
+ goto leave;
+ }
+
+ py_args = PyUnicode_FromString(args);
+ if (py_args == NULL)
+ {
+ err = _pyme_exception2code();
+ goto leave;
+ }
+
+ retval = PyObject_CallFunctionObjArgs(func, py_status, py_args, NULL);
+ if (PyErr_Occurred())
+ err = _pyme_exception2code();
+ Py_XDECREF(retval);
+
+ leave:
+ Py_XDECREF(py_status);
+ Py_XDECREF(py_args);
+ if (err)
+ _pyme_stash_callback_exception(self);
+ PyGILState_Release(state);
+ return err;
+}
diff --git a/lang/python/helpers.h b/lang/python/helpers.h
new file mode 100644
index 0000000..9200f93
--- /dev/null
+++ b/lang/python/helpers.h
@@ -0,0 +1,39 @@
+/*
+# Copyright (C) 2016 g10 Code GmbH
+# Copyright (C) 2004 Igor Belyi <belyi@users.sourceforge.net>
+# Copyright (C) 2002 John Goerzen <jgoerzen@complete.org>
+#
+# This library is free software; you can redistribute it and/or
+# modify it under the terms of the GNU Lesser General Public
+# License as published by the Free Software Foundation; either
+# version 2.1 of the License, or (at your option) any later version.
+#
+# This library is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+# Lesser General Public License for more details.
+#
+# You should have received a copy of the GNU Lesser General Public
+# License along with this library; if not, write to the Free Software
+# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+*/
+
+#include <gpgme.h>
+#include "Python.h"
+
+#ifdef _WIN32
+#include <windows.h>
+#define write(fd, str, sz) {DWORD written; WriteFile((HANDLE) fd, str, sz, &written, 0);}
+#endif
+
+/* Flag specifying whether this is an in-tree build. */
+extern int pyme_in_tree_build;
+
+PyObject *pyme_raise_callback_exception(PyObject *self);
+
+PyObject *pyme_set_passphrase_cb(PyObject *self, PyObject *cb);
+PyObject *pyme_set_progress_cb(PyObject *self, PyObject *cb);
+PyObject *pyme_set_status_cb(PyObject *self, PyObject *cb);
+
+PyObject *pyme_data_new_from_cbs(PyObject *self, PyObject *pycbs,
+ gpgme_data_t *r_data);
diff --git a/lang/python/private.h b/lang/python/private.h
new file mode 100644
index 0000000..3a903c1
--- /dev/null
+++ b/lang/python/private.h
@@ -0,0 +1,54 @@
+/*
+ * Copyright (C) 2016 g10 Code GmbH
+ *
+ * This file is part of GPGME.
+ *
+ * GPGME is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU Lesser General Public License as
+ * published by the Free Software Foundation; either version 2.1 of
+ * the License, or (at your option) any later version.
+ *
+ * GPGME is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this program; if not, see <http://www.gnu.org/licenses/>.
+ */
+
+#include <gpgme.h>
+
+#ifndef _PYME_PRIVATE_H_
+#define _PYME_PRIVATE_H_
+
+/* GPGME glue. Implemented in helpers.c. */
+
+void _pyme_exception_init(void);
+gpgme_error_t _pyme_exception2code(void);
+
+PyObject *_pyme_obj2gpgme_t(PyObject *input, const char *objtype, int argnum);
+PyObject *_pyme_obj2gpgme_data_t(PyObject *input, int argnum,
+ gpgme_data_t *wrapper,
+ PyObject **bytesio, Py_buffer *view);
+
+PyObject *_pyme_wrap_result(PyObject *fragile, const char *classname);
+
+gpgme_error_t _pyme_interact_cb(void *opaque, const char *keyword,
+ const char *args, int fd);
+gpgme_error_t _pyme_assuan_data_cb (void *hook,
+ const void *data, size_t datalen);
+gpgme_error_t _pyme_assuan_inquire_cb (void *hook,
+ const char *name, const char *args,
+ gpgme_data_t *r_data);
+gpgme_error_t _pyme_assuan_status_cb (void *hook,
+ const char *status, const char *args);
+
+
+
+/* SWIG runtime support. Implemented in gpgme.i. */
+
+PyObject *_pyme_wrap_gpgme_data_t(gpgme_data_t data);
+gpgme_ctx_t _pyme_unwrap_gpgme_ctx_t(PyObject *wrapped);
+
+#endif /* _PYME_PRIVATE_H_ */
diff --git a/lang/python/pyme/__init__.py b/lang/python/pyme/__init__.py
new file mode 100644
index 0000000..12c96c2
--- /dev/null
+++ b/lang/python/pyme/__init__.py
@@ -0,0 +1,125 @@
+# Copyright (C) 2016 g10 Code GmbH
+# Copyright (C) 2004 Igor Belyi <belyi@users.sourceforge.net>
+# Copyright (C) 2002 John Goerzen <jgoerzen@complete.org>
+#
+# This library is free software; you can redistribute it and/or
+# modify it under the terms of the GNU Lesser General Public
+# License as published by the Free Software Foundation; either
+# version 2.1 of the License, or (at your option) any later version.
+#
+# This library is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+# Lesser General Public License for more details.
+#
+# You should have received a copy of the GNU Lesser General Public
+# License along with this library; if not, write to the Free Software
+# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+
+"""Pyme: GPGME Interface for Python
+
+Welcome to PyME, the GPGME Interface for Python. "Pyme", when prounced,
+rhymes with "Pine".
+
+The latest release of this package may be obtained from
+https://www.gnupg.org
+
+Previous releases of this package for Python 2 can be obtained from
+http://pyme.sourceforge.net
+
+FEATURES
+--------
+
+ * Feature-rich, full implementation of the GPGME library. Supports
+ all GPGME features. Callback functions may be written in pure
+ Python. Exceptions raised in callbacks are properly propagated.
+
+ * Ability to sign, encrypt, decrypt, and verify data.
+
+ * Ability to list keys, export and import keys, and manage the keyring.
+
+ * Fully object-oriented with convenient classes and modules.
+
+QUICK EXAMPLE
+-------------
+
+ >>> import pyme
+ >>> with pyme.Context() as c:
+ >>> with pyme.Context() as c:
+ ... cipher, _, _ = c.encrypt("Hello world :)".encode(),
+ ... passphrase="abc")
+ ... c.decrypt(cipher, passphrase="abc")
+ ...
+ (b'Hello world :)',
+ <pyme.results.DecryptResult object at 0x7f5ab8121080>,
+ <pyme.results.VerifyResult object at 0x7f5ab81219b0>)
+
+GENERAL OVERVIEW
+----------------
+
+For those of you familiar with GPGME, you will be right at home here.
+
+Pyme is, for the most part, a direct interface to the C GPGME
+library. However, it is re-packaged in a more Pythonic way --
+object-oriented with classes and modules. Take a look at the classes
+defined here -- they correspond directly to certain object types in GPGME
+for C. For instance, the following C code:
+
+gpgme_ctx_t context;
+gpgme_new(&context);
+...
+gpgme_op_encrypt(context, recp, 1, plain, cipher);
+
+Translates into the following Python code:
+
+context = core.Context()
+...
+context.op_encrypt(recp, 1, plain, cipher)
+
+The Python module automatically does error-checking and raises Python
+exception pyme.errors.GPGMEError when GPGME signals an error. getcode()
+and getsource() of this exception return code and source of the error.
+
+IMPORTANT NOTE
+--------------
+This documentation only covers a small subset of available GPGME functions and
+methods. Please consult the documentation for the C library
+for comprehensive coverage.
+
+This library uses Python's reflection to automatically detect the methods
+that are available for each class, and as such, most of those methods
+do not appear explicitly anywhere. You can use dir() python built-in command
+on an object to see what methods and fields it has but their meaning can
+be found only in GPGME documentation.
+
+FOR MORE INFORMATION
+--------------------
+PYME3 homepage: https://www.gnupg.org/
+GPGME documentation: https://www.gnupg.org/documentation/manuals/gpgme/
+
+"""
+
+from __future__ import absolute_import, print_function, unicode_literals
+del absolute_import, print_function, unicode_literals
+
+from . import core
+from . import errors
+from . import constants
+from . import util
+from . import callbacks
+from . import version
+from .core import Context
+from .core import Data
+
+# Interface hygiene.
+
+# Drop the low-level gpgme that creeps in for some reason.
+gpgme = None
+del gpgme
+
+# This is a white-list of symbols. Any other will alert pyflakes.
+_ = [Context, Data, core, errors, constants, util, callbacks, version]
+del _
+
+__all__ = ["Context", "Data",
+ "core", "errors", "constants", "util", "callbacks", "version"]
diff --git a/lang/python/pyme/__pycache__/__init__.cpython-34.pyc b/lang/python/pyme/__pycache__/__init__.cpython-34.pyc
new file mode 100644
index 0000000..ba78937
--- /dev/null
+++ b/lang/python/pyme/__pycache__/__init__.cpython-34.pyc
Binary files differ
diff --git a/lang/python/pyme/__pycache__/version.cpython-34.pyc b/lang/python/pyme/__pycache__/version.cpython-34.pyc
new file mode 100644
index 0000000..658008a
--- /dev/null
+++ b/lang/python/pyme/__pycache__/version.cpython-34.pyc
Binary files differ
diff --git a/lang/python/pyme/callbacks.py b/lang/python/pyme/callbacks.py
new file mode 100644
index 0000000..b25a9a7
--- /dev/null
+++ b/lang/python/pyme/callbacks.py
@@ -0,0 +1,49 @@
+# Copyright (C) 2004 Igor Belyi <belyi@users.sourceforge.net>
+# Copyright (C) 2002 John Goerzen <jgoerzen@complete.org>
+#
+# This library is free software; you can redistribute it and/or
+# modify it under the terms of the GNU Lesser General Public
+# License as published by the Free Software Foundation; either
+# version 2.1 of the License, or (at your option) any later version.
+#
+# This library is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+# Lesser General Public License for more details.
+#
+# You should have received a copy of the GNU Lesser General Public
+# License along with this library; if not, write to the Free Software
+# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+
+from __future__ import absolute_import, print_function, unicode_literals
+del absolute_import, print_function, unicode_literals
+
+from getpass import getpass
+
+def passphrase_stdin(hint, desc, prev_bad, hook=None):
+ """This is a sample callback that will read a passphrase from
+ the terminal. The hook here, if present, will be used to describe
+ why the passphrase is needed."""
+ why = ''
+ if hook != None:
+ why = ' ' + hook
+ if prev_bad:
+ why += ' (again)'
+ print("Please supply %s' password%s:" % (hint, why))
+ return getpass()
+
+def progress_stdout(what, type, current, total, hook=None):
+ print("PROGRESS UPDATE: what = %s, type = %d, current = %d, total = %d" %\
+ (what, type, current, total))
+
+def readcb_fh(count, hook):
+ """A callback for data. hook should be a Python file-like object."""
+ if count:
+ # Should return '' on EOF
+ return hook.read(count)
+ else:
+ # Wants to rewind.
+ if not hasattr(hook, 'seek'):
+ return None
+ hook.seek(0, 0)
+ return None
diff --git a/lang/python/pyme/constants/__init__.py b/lang/python/pyme/constants/__init__.py
new file mode 100644
index 0000000..96d89e4
--- /dev/null
+++ b/lang/python/pyme/constants/__init__.py
@@ -0,0 +1,114 @@
+
+from __future__ import absolute_import, print_function, unicode_literals
+del absolute_import, print_function, unicode_literals
+
+from pyme import util
+util.process_constants('GPGME_', globals())
+
+__all__ = ['data', 'event', 'import', 'keylist', 'md', 'pk',
+ 'protocol', 'sig', 'sigsum', 'status', 'validity']
+
+# GPGME 1.7 replaced gpgme_op_edit with gpgme_op_interact. We
+# implement pyme.Context.op_edit using gpgme_op_interact, so the
+# callbacks will be called with string keywords instead of numeric
+# status messages. Code that is using these constants will continue
+# to work.
+
+STATUS_ABORT = "ABORT"
+STATUS_ALREADY_SIGNED = "ALREADY_SIGNED"
+STATUS_ATTRIBUTE = "ATTRIBUTE"
+STATUS_BACKUP_KEY_CREATED = "BACKUP_KEY_CREATED"
+STATUS_BAD_PASSPHRASE = "BAD_PASSPHRASE"
+STATUS_BADARMOR = "BADARMOR"
+STATUS_BADMDC = "BADMDC"
+STATUS_BADSIG = "BADSIG"
+STATUS_BEGIN_DECRYPTION = "BEGIN_DECRYPTION"
+STATUS_BEGIN_ENCRYPTION = "BEGIN_ENCRYPTION"
+STATUS_BEGIN_SIGNING = "BEGIN_SIGNING"
+STATUS_BEGIN_STREAM = "BEGIN_STREAM"
+STATUS_CARDCTRL = "CARDCTRL"
+STATUS_DECRYPTION_FAILED = "DECRYPTION_FAILED"
+STATUS_DECRYPTION_INFO = "DECRYPTION_INFO"
+STATUS_DECRYPTION_OKAY = "DECRYPTION_OKAY"
+STATUS_DELETE_PROBLEM = "DELETE_PROBLEM"
+STATUS_ENC_TO = "ENC_TO"
+STATUS_END_DECRYPTION = "END_DECRYPTION"
+STATUS_END_ENCRYPTION = "END_ENCRYPTION"
+STATUS_END_STREAM = "END_STREAM"
+STATUS_ENTER = "ENTER"
+STATUS_ERRMDC = "ERRMDC"
+STATUS_ERROR = "ERROR"
+STATUS_ERRSIG = "ERRSIG"
+STATUS_EXPKEYSIG = "EXPKEYSIG"
+STATUS_EXPSIG = "EXPSIG"
+STATUS_FAILURE = "FAILURE"
+STATUS_FILE_DONE = "FILE_DONE"
+STATUS_FILE_ERROR = "FILE_ERROR"
+STATUS_FILE_START = "FILE_START"
+STATUS_GET_BOOL = "GET_BOOL"
+STATUS_GET_HIDDEN = "GET_HIDDEN"
+STATUS_GET_LINE = "GET_LINE"
+STATUS_GOOD_PASSPHRASE = "GOOD_PASSPHRASE"
+STATUS_GOODMDC = "GOODMDC"
+STATUS_GOODSIG = "GOODSIG"
+STATUS_GOT_IT = "GOT_IT"
+STATUS_IMPORT_OK = "IMPORT_OK"
+STATUS_IMPORT_PROBLEM = "IMPORT_PROBLEM"
+STATUS_IMPORT_RES = "IMPORT_RES"
+STATUS_IMPORTED = "IMPORTED"
+STATUS_INQUIRE_MAXLEN = "INQUIRE_MAXLEN"
+STATUS_INV_RECP = "INV_RECP"
+STATUS_INV_SGNR = "INV_SGNR"
+STATUS_KEY_CONSIDERED = "KEY_CONSIDERED"
+STATUS_KEY_CREATED = "KEY_CREATED"
+STATUS_KEY_NOT_CREATED = "KEY_NOT_CREATED"
+STATUS_KEYEXPIRED = "KEYEXPIRED"
+STATUS_KEYREVOKED = "KEYREVOKED"
+STATUS_LEAVE = "LEAVE"
+STATUS_MISSING_PASSPHRASE = "MISSING_PASSPHRASE"
+STATUS_MOUNTPOINT = "MOUNTPOINT"
+STATUS_NEED_PASSPHRASE = "NEED_PASSPHRASE"
+STATUS_NEED_PASSPHRASE_PIN = "NEED_PASSPHRASE_PIN"
+STATUS_NEED_PASSPHRASE_SYM = "NEED_PASSPHRASE_SYM"
+STATUS_NEWSIG = "NEWSIG"
+STATUS_NO_PUBKEY = "NO_PUBKEY"
+STATUS_NO_RECP = "NO_RECP"
+STATUS_NO_SECKEY = "NO_SECKEY"
+STATUS_NO_SGNR = "NO_SGNR"
+STATUS_NODATA = "NODATA"
+STATUS_NOTATION_DATA = "NOTATION_DATA"
+STATUS_NOTATION_FLAGS = "NOTATION_FLAGS"
+STATUS_NOTATION_NAME = "NOTATION_NAME"
+STATUS_PINENTRY_LAUNCHED = "PINENTRY_LAUNCHED"
+STATUS_PKA_TRUST_BAD = "PKA_TRUST_BAD"
+STATUS_PKA_TRUST_GOOD = "PKA_TRUST_GOOD"
+STATUS_PLAINTEXT = "PLAINTEXT"
+STATUS_PLAINTEXT_LENGTH = "PLAINTEXT_LENGTH"
+STATUS_POLICY_URL = "POLICY_URL"
+STATUS_PROGRESS = "PROGRESS"
+STATUS_REVKEYSIG = "REVKEYSIG"
+STATUS_RSA_OR_IDEA = "RSA_OR_IDEA"
+STATUS_SC_OP_FAILURE = "SC_OP_FAILURE"
+STATUS_SC_OP_SUCCESS = "SC_OP_SUCCESS"
+STATUS_SESSION_KEY = "SESSION_KEY"
+STATUS_SHM_GET = "SHM_GET"
+STATUS_SHM_GET_BOOL = "SHM_GET_BOOL"
+STATUS_SHM_GET_HIDDEN = "SHM_GET_HIDDEN"
+STATUS_SHM_INFO = "SHM_INFO"
+STATUS_SIG_CREATED = "SIG_CREATED"
+STATUS_SIG_ID = "SIG_ID"
+STATUS_SIG_SUBPACKET = "SIG_SUBPACKET"
+STATUS_SIGEXPIRED = "SIGEXPIRED"
+STATUS_SUCCESS = "SUCCESS"
+STATUS_TOFU_STATS = "TOFU_STATS"
+STATUS_TOFU_STATS_LONG = "TOFU_STATS_LONG"
+STATUS_TOFU_USER = "TOFU_USER"
+STATUS_TRUNCATED = "TRUNCATED"
+STATUS_TRUST_FULLY = "TRUST_FULLY"
+STATUS_TRUST_MARGINAL = "TRUST_MARGINAL"
+STATUS_TRUST_NEVER = "TRUST_NEVER"
+STATUS_TRUST_ULTIMATE = "TRUST_ULTIMATE"
+STATUS_TRUST_UNDEFINED = "TRUST_UNDEFINED"
+STATUS_UNEXPECTED = "UNEXPECTED"
+STATUS_USERID_HINT = "USERID_HINT"
+STATUS_VALIDSIG = "VALIDSIG"
diff --git a/lang/python/pyme/constants/data/__init__.py b/lang/python/pyme/constants/data/__init__.py
new file mode 100644
index 0000000..8274ab9
--- /dev/null
+++ b/lang/python/pyme/constants/data/__init__.py
@@ -0,0 +1,6 @@
+
+from __future__ import absolute_import, print_function, unicode_literals
+del absolute_import, print_function, unicode_literals
+
+from . import encoding
+__all__ = ['encoding']
diff --git a/lang/python/pyme/constants/data/encoding.py b/lang/python/pyme/constants/data/encoding.py
new file mode 100644
index 0000000..a05dbb4
--- /dev/null
+++ b/lang/python/pyme/constants/data/encoding.py
@@ -0,0 +1,22 @@
+# Copyright (C) 2004 Igor Belyi <belyi@users.sourceforge.net>
+# Copyright (C) 2002 John Goerzen <jgoerzen@complete.org>
+#
+# This library is free software; you can redistribute it and/or
+# modify it under the terms of the GNU Lesser General Public
+# License as published by the Free Software Foundation; either
+# version 2.1 of the License, or (at your option) any later version.
+#
+# This library is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+# Lesser General Public License for more details.
+#
+# You should have received a copy of the GNU Lesser General Public
+# License along with this library; if not, write to the Free Software
+# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+
+from __future__ import absolute_import, print_function, unicode_literals
+del absolute_import, print_function, unicode_literals
+
+from pyme import util
+util.process_constants('GPGME_DATA_ENCODING_', globals())
diff --git a/lang/python/pyme/constants/event.py b/lang/python/pyme/constants/event.py
new file mode 100644
index 0000000..2e30c5e
--- /dev/null
+++ b/lang/python/pyme/constants/event.py
@@ -0,0 +1,22 @@
+# Copyright (C) 2004 Igor Belyi <belyi@users.sourceforge.net>
+# Copyright (C) 2002 John Goerzen <jgoerzen@complete.org>
+#
+# This library is free software; you can redistribute it and/or
+# modify it under the terms of the GNU Lesser General Public
+# License as published by the Free Software Foundation; either
+# version 2.1 of the License, or (at your option) any later version.
+#
+# This library is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+# Lesser General Public License for more details.
+#
+# You should have received a copy of the GNU Lesser General Public
+# License along with this library; if not, write to the Free Software
+# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+
+from __future__ import absolute_import, print_function, unicode_literals
+del absolute_import, print_function, unicode_literals
+
+from pyme import util
+util.process_constants('GPGME_EVENT_', globals())
diff --git a/lang/python/pyme/constants/import.py b/lang/python/pyme/constants/import.py
new file mode 100644
index 0000000..10e7d3c
--- /dev/null
+++ b/lang/python/pyme/constants/import.py
@@ -0,0 +1,22 @@
+# Copyright (C) 2004 Igor Belyi <belyi@users.sourceforge.net>
+# Copyright (C) 2002 John Goerzen <jgoerzen@complete.org>
+#
+# This library is free software; you can redistribute it and/or
+# modify it under the terms of the GNU Lesser General Public
+# License as published by the Free Software Foundation; either
+# version 2.1 of the License, or (at your option) any later version.
+#
+# This library is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+# Lesser General Public License for more details.
+#
+# You should have received a copy of the GNU Lesser General Public
+# License along with this library; if not, write to the Free Software
+# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+
+from __future__ import absolute_import, print_function, unicode_literals
+del absolute_import, print_function, unicode_literals
+
+from pyme import util
+util.process_constants('GPGME_IMPORT_', globals())
diff --git a/lang/python/pyme/constants/keylist/__init__.py b/lang/python/pyme/constants/keylist/__init__.py
new file mode 100644
index 0000000..2ce0edf
--- /dev/null
+++ b/lang/python/pyme/constants/keylist/__init__.py
@@ -0,0 +1,6 @@
+
+from __future__ import absolute_import, print_function, unicode_literals
+del absolute_import, print_function, unicode_literals
+
+from . import mode
+__all__ = ['mode']
diff --git a/lang/python/pyme/constants/keylist/mode.py b/lang/python/pyme/constants/keylist/mode.py
new file mode 100644
index 0000000..000dd79
--- /dev/null
+++ b/lang/python/pyme/constants/keylist/mode.py
@@ -0,0 +1,22 @@
+# Copyright (C) 2004 Igor Belyi <belyi@users.sourceforge.net>
+# Copyright (C) 2002 John Goerzen <jgoerzen@complete.org>
+#
+# This library is free software; you can redistribute it and/or
+# modify it under the terms of the GNU Lesser General Public
+# License as published by the Free Software Foundation; either
+# version 2.1 of the License, or (at your option) any later version.
+#
+# This library is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+# Lesser General Public License for more details.
+#
+# You should have received a copy of the GNU Lesser General Public
+# License along with this library; if not, write to the Free Software
+# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+
+from __future__ import absolute_import, print_function, unicode_literals
+del absolute_import, print_function, unicode_literals
+
+from pyme import util
+util.process_constants('GPGME_KEYLIST_MODE_', globals())
diff --git a/lang/python/pyme/constants/md.py b/lang/python/pyme/constants/md.py
new file mode 100644
index 0000000..dbd762c
--- /dev/null
+++ b/lang/python/pyme/constants/md.py
@@ -0,0 +1,22 @@
+# Copyright (C) 2004 Igor Belyi <belyi@users.sourceforge.net>
+# Copyright (C) 2002 John Goerzen <jgoerzen@complete.org>
+#
+# This library is free software; you can redistribute it and/or
+# modify it under the terms of the GNU Lesser General Public
+# License as published by the Free Software Foundation; either
+# version 2.1 of the License, or (at your option) any later version.
+#
+# This library is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+# Lesser General Public License for more details.
+#
+# You should have received a copy of the GNU Lesser General Public
+# License along with this library; if not, write to the Free Software
+# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+
+from __future__ import absolute_import, print_function, unicode_literals
+del absolute_import, print_function, unicode_literals
+
+from pyme import util
+util.process_constants('GPGME_MD_', globals())
diff --git a/lang/python/pyme/constants/pk.py b/lang/python/pyme/constants/pk.py
new file mode 100644
index 0000000..cfc5309
--- /dev/null
+++ b/lang/python/pyme/constants/pk.py
@@ -0,0 +1,22 @@
+# Copyright (C) 2004 Igor Belyi <belyi@users.sourceforge.net>
+# Copyright (C) 2002 John Goerzen <jgoerzen@complete.org>
+#
+# This library is free software; you can redistribute it and/or
+# modify it under the terms of the GNU Lesser General Public
+# License as published by the Free Software Foundation; either
+# version 2.1 of the License, or (at your option) any later version.
+#
+# This library is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+# Lesser General Public License for more details.
+#
+# You should have received a copy of the GNU Lesser General Public
+# License along with this library; if not, write to the Free Software
+# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+
+from __future__ import absolute_import, print_function, unicode_literals
+del absolute_import, print_function, unicode_literals
+
+from pyme import util
+util.process_constants('GPGME_PK_', globals())
diff --git a/lang/python/pyme/constants/protocol.py b/lang/python/pyme/constants/protocol.py
new file mode 100644
index 0000000..a4b6583
--- /dev/null
+++ b/lang/python/pyme/constants/protocol.py
@@ -0,0 +1,22 @@
+# Copyright (C) 2004 Igor Belyi <belyi@users.sourceforge.net>
+# Copyright (C) 2002 John Goerzen <jgoerzen@complete.org>
+#
+# This library is free software; you can redistribute it and/or
+# modify it under the terms of the GNU Lesser General Public
+# License as published by the Free Software Foundation; either
+# version 2.1 of the License, or (at your option) any later version.
+#
+# This library is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+# Lesser General Public License for more details.
+#
+# You should have received a copy of the GNU Lesser General Public
+# License along with this library; if not, write to the Free Software
+# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+
+from __future__ import absolute_import, print_function, unicode_literals
+del absolute_import, print_function, unicode_literals
+
+from pyme import util
+util.process_constants('GPGME_PROTOCOL_', globals())
diff --git a/lang/python/pyme/constants/sig/__init__.py b/lang/python/pyme/constants/sig/__init__.py
new file mode 100644
index 0000000..2ce0edf
--- /dev/null
+++ b/lang/python/pyme/constants/sig/__init__.py
@@ -0,0 +1,6 @@
+
+from __future__ import absolute_import, print_function, unicode_literals
+del absolute_import, print_function, unicode_literals
+
+from . import mode
+__all__ = ['mode']
diff --git a/lang/python/pyme/constants/sig/mode.py b/lang/python/pyme/constants/sig/mode.py
new file mode 100644
index 0000000..fb534bc
--- /dev/null
+++ b/lang/python/pyme/constants/sig/mode.py
@@ -0,0 +1,22 @@
+# Copyright (C) 2004 Igor Belyi <belyi@users.sourceforge.net>
+# Copyright (C) 2002 John Goerzen <jgoerzen@complete.org>
+#
+# This library is free software; you can redistribute it and/or
+# modify it under the terms of the GNU Lesser General Public
+# License as published by the Free Software Foundation; either
+# version 2.1 of the License, or (at your option) any later version.
+#
+# This library is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+# Lesser General Public License for more details.
+#
+# You should have received a copy of the GNU Lesser General Public
+# License along with this library; if not, write to the Free Software
+# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+
+from __future__ import absolute_import, print_function, unicode_literals
+del absolute_import, print_function, unicode_literals
+
+from pyme import util
+util.process_constants('GPGME_SIG_MODE_', globals())
diff --git a/lang/python/pyme/constants/sigsum.py b/lang/python/pyme/constants/sigsum.py
new file mode 100644
index 0000000..3d94745
--- /dev/null
+++ b/lang/python/pyme/constants/sigsum.py
@@ -0,0 +1,22 @@
+# Copyright (C) 2004 Igor Belyi <belyi@users.sourceforge.net>
+# Copyright (C) 2002 John Goerzen <jgoerzen@complete.org>
+#
+# This library is free software; you can redistribute it and/or
+# modify it under the terms of the GNU Lesser General Public
+# License as published by the Free Software Foundation; either
+# version 2.1 of the License, or (at your option) any later version.
+#
+# This library is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+# Lesser General Public License for more details.
+#
+# You should have received a copy of the GNU Lesser General Public
+# License along with this library; if not, write to the Free Software
+# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+
+from __future__ import absolute_import, print_function, unicode_literals
+del absolute_import, print_function, unicode_literals
+
+from pyme import util
+util.process_constants('GPGME_SIGSUM_', globals())
diff --git a/lang/python/pyme/constants/status.py b/lang/python/pyme/constants/status.py
new file mode 100644
index 0000000..a04d9aa
--- /dev/null
+++ b/lang/python/pyme/constants/status.py
@@ -0,0 +1,124 @@
+# Copyright (C) 2004 Igor Belyi <belyi@users.sourceforge.net>
+# Copyright (C) 2002 John Goerzen <jgoerzen@complete.org>
+#
+# This library is free software; you can redistribute it and/or
+# modify it under the terms of the GNU Lesser General Public
+# License as published by the Free Software Foundation; either
+# version 2.1 of the License, or (at your option) any later version.
+#
+# This library is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+# Lesser General Public License for more details.
+#
+# You should have received a copy of the GNU Lesser General Public
+# License along with this library; if not, write to the Free Software
+# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+
+from __future__ import absolute_import, print_function, unicode_literals
+del absolute_import, print_function, unicode_literals
+
+# GPGME 1.7 replaced gpgme_op_edit with gpgme_op_interact. We
+# implement pyme.Context.op_edit using gpgme_op_interact, so the
+# callbacks will be called with string keywords instead of numeric
+# status messages. Code that is using these constants will continue
+# to work.
+
+ABORT = "ABORT"
+ALREADY_SIGNED = "ALREADY_SIGNED"
+ATTRIBUTE = "ATTRIBUTE"
+BACKUP_KEY_CREATED = "BACKUP_KEY_CREATED"
+BAD_PASSPHRASE = "BAD_PASSPHRASE"
+BADARMOR = "BADARMOR"
+BADMDC = "BADMDC"
+BADSIG = "BADSIG"
+BEGIN_DECRYPTION = "BEGIN_DECRYPTION"
+BEGIN_ENCRYPTION = "BEGIN_ENCRYPTION"
+BEGIN_SIGNING = "BEGIN_SIGNING"
+BEGIN_STREAM = "BEGIN_STREAM"
+CARDCTRL = "CARDCTRL"
+DECRYPTION_FAILED = "DECRYPTION_FAILED"
+DECRYPTION_INFO = "DECRYPTION_INFO"
+DECRYPTION_OKAY = "DECRYPTION_OKAY"
+DELETE_PROBLEM = "DELETE_PROBLEM"
+ENC_TO = "ENC_TO"
+END_DECRYPTION = "END_DECRYPTION"
+END_ENCRYPTION = "END_ENCRYPTION"
+END_STREAM = "END_STREAM"
+ENTER = "ENTER"
+ERRMDC = "ERRMDC"
+ERROR = "ERROR"
+ERRSIG = "ERRSIG"
+EXPKEYSIG = "EXPKEYSIG"
+EXPSIG = "EXPSIG"
+FAILURE = "FAILURE"
+FILE_DONE = "FILE_DONE"
+FILE_ERROR = "FILE_ERROR"
+FILE_START = "FILE_START"
+GET_BOOL = "GET_BOOL"
+GET_HIDDEN = "GET_HIDDEN"
+GET_LINE = "GET_LINE"
+GOOD_PASSPHRASE = "GOOD_PASSPHRASE"
+GOODMDC = "GOODMDC"
+GOODSIG = "GOODSIG"
+GOT_IT = "GOT_IT"
+IMPORT_OK = "IMPORT_OK"
+IMPORT_PROBLEM = "IMPORT_PROBLEM"
+IMPORT_RES = "IMPORT_RES"
+IMPORTED = "IMPORTED"
+INQUIRE_MAXLEN = "INQUIRE_MAXLEN"
+INV_RECP = "INV_RECP"
+INV_SGNR = "INV_SGNR"
+KEY_CONSIDERED = "KEY_CONSIDERED"
+KEY_CREATED = "KEY_CREATED"
+KEY_NOT_CREATED = "KEY_NOT_CREATED"
+KEYEXPIRED = "KEYEXPIRED"
+KEYREVOKED = "KEYREVOKED"
+LEAVE = "LEAVE"
+MISSING_PASSPHRASE = "MISSING_PASSPHRASE"
+MOUNTPOINT = "MOUNTPOINT"
+NEED_PASSPHRASE = "NEED_PASSPHRASE"
+NEED_PASSPHRASE_PIN = "NEED_PASSPHRASE_PIN"
+NEED_PASSPHRASE_SYM = "NEED_PASSPHRASE_SYM"
+NEWSIG = "NEWSIG"
+NO_PUBKEY = "NO_PUBKEY"
+NO_RECP = "NO_RECP"
+NO_SECKEY = "NO_SECKEY"
+NO_SGNR = "NO_SGNR"
+NODATA = "NODATA"
+NOTATION_DATA = "NOTATION_DATA"
+NOTATION_FLAGS = "NOTATION_FLAGS"
+NOTATION_NAME = "NOTATION_NAME"
+PINENTRY_LAUNCHED = "PINENTRY_LAUNCHED"
+PKA_TRUST_BAD = "PKA_TRUST_BAD"
+PKA_TRUST_GOOD = "PKA_TRUST_GOOD"
+PLAINTEXT = "PLAINTEXT"
+PLAINTEXT_LENGTH = "PLAINTEXT_LENGTH"
+POLICY_URL = "POLICY_URL"
+PROGRESS = "PROGRESS"
+REVKEYSIG = "REVKEYSIG"
+RSA_OR_IDEA = "RSA_OR_IDEA"
+SC_OP_FAILURE = "SC_OP_FAILURE"
+SC_OP_SUCCESS = "SC_OP_SUCCESS"
+SESSION_KEY = "SESSION_KEY"
+SHM_GET = "SHM_GET"
+SHM_GET_BOOL = "SHM_GET_BOOL"
+SHM_GET_HIDDEN = "SHM_GET_HIDDEN"
+SHM_INFO = "SHM_INFO"
+SIG_CREATED = "SIG_CREATED"
+SIG_ID = "SIG_ID"
+SIG_SUBPACKET = "SIG_SUBPACKET"
+SIGEXPIRED = "SIGEXPIRED"
+SUCCESS = "SUCCESS"
+TOFU_STATS = "TOFU_STATS"
+TOFU_STATS_LONG = "TOFU_STATS_LONG"
+TOFU_USER = "TOFU_USER"
+TRUNCATED = "TRUNCATED"
+TRUST_FULLY = "TRUST_FULLY"
+TRUST_MARGINAL = "TRUST_MARGINAL"
+TRUST_NEVER = "TRUST_NEVER"
+TRUST_ULTIMATE = "TRUST_ULTIMATE"
+TRUST_UNDEFINED = "TRUST_UNDEFINED"
+UNEXPECTED = "UNEXPECTED"
+USERID_HINT = "USERID_HINT"
+VALIDSIG = "VALIDSIG"
diff --git a/lang/python/pyme/constants/validity.py b/lang/python/pyme/constants/validity.py
new file mode 100644
index 0000000..4ecd4d3
--- /dev/null
+++ b/lang/python/pyme/constants/validity.py
@@ -0,0 +1,22 @@
+# Copyright (C) 2004 Igor Belyi <belyi@users.sourceforge.net>
+# Copyright (C) 2002 John Goerzen <jgoerzen@complete.org>
+#
+# This library is free software; you can redistribute it and/or
+# modify it under the terms of the GNU Lesser General Public
+# License as published by the Free Software Foundation; either
+# version 2.1 of the License, or (at your option) any later version.
+#
+# This library is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+# Lesser General Public License for more details.
+#
+# You should have received a copy of the GNU Lesser General Public
+# License along with this library; if not, write to the Free Software
+# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+
+from __future__ import absolute_import, print_function, unicode_literals
+del absolute_import, print_function, unicode_literals
+
+from pyme import util
+util.process_constants('GPGME_VALIDITY_', globals())
diff --git a/lang/python/pyme/core.py b/lang/python/pyme/core.py
new file mode 100644
index 0000000..88a086b
--- /dev/null
+++ b/lang/python/pyme/core.py
@@ -0,0 +1,1145 @@
+# Copyright (C) 2016 g10 Code GmbH
+# Copyright (C) 2004,2008 Igor Belyi <belyi@users.sourceforge.net>
+# Copyright (C) 2002 John Goerzen <jgoerzen@complete.org>
+#
+# This library is free software; you can redistribute it and/or
+# modify it under the terms of the GNU Lesser General Public
+# License as published by the Free Software Foundation; either
+# version 2.1 of the License, or (at your option) any later version.
+#
+# This library is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+# Lesser General Public License for more details.
+#
+# You should have received a copy of the GNU Lesser General Public
+# License along with this library; if not, write to the Free Software
+# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+
+"""Core functionality
+
+Core functionality of GPGME wrapped in a object-oriented fashion.
+Provides the 'Context' class for performing cryptographic operations,
+and the 'Data' class describing buffers of data.
+
+"""
+
+from __future__ import absolute_import, print_function, unicode_literals
+del absolute_import, print_function, unicode_literals
+
+import re
+import os
+import warnings
+import weakref
+from . import gpgme
+from .errors import errorcheck, GPGMEError
+from . import constants
+from . import errors
+from . import util
+
+class GpgmeWrapper(object):
+ """Base wrapper class
+
+ Not to be instantiated directly.
+
+ """
+
+ def __init__(self, wrapped):
+ self._callback_excinfo = None
+ self.wrapped = wrapped
+
+ def __repr__(self):
+ return '<{}/{!r}>'.format(super(GpgmeWrapper, self).__repr__(),
+ self.wrapped)
+
+ def __str__(self):
+ acc = ['{}.{}'.format(__name__, self.__class__.__name__)]
+ flags = [f for f in self._boolean_properties if getattr(self, f)]
+ if flags:
+ acc.append('({})'.format(' '.join(flags)))
+
+ return '<{}>'.format(' '.join(acc))
+
+ def __hash__(self):
+ return hash(repr(self.wrapped))
+
+ def __eq__(self, other):
+ if other == None:
+ return False
+ else:
+ return repr(self.wrapped) == repr(other.wrapped)
+
+ @property
+ def _ctype(self):
+ """The name of the c type wrapped by this class
+
+ Must be set by child classes.
+
+ """
+ raise NotImplementedError()
+
+ @property
+ def _cprefix(self):
+ """The common prefix of c functions wrapped by this class
+
+ Must be set by child classes.
+
+ """
+ raise NotImplementedError()
+
+ def _errorcheck(self, name):
+ """Must be implemented by child classes.
+
+ This function must return a trueish value for all c functions
+ returning gpgme_error_t."""
+ raise NotImplementedError()
+
+ """The set of all boolean properties"""
+ _boolean_properties = set()
+
+ def __wrap_boolean_property(self, key, do_set=False, value=None):
+ get_func = getattr(gpgme,
+ "{}get_{}".format(self._cprefix, key))
+ set_func = getattr(gpgme,
+ "{}set_{}".format(self._cprefix, key))
+ def get(slf):
+ return bool(get_func(slf.wrapped))
+ def set_(slf, value):
+ set_func(slf.wrapped, bool(value))
+
+ p = property(get, set_, doc="{} flag".format(key))
+ setattr(self.__class__, key, p)
+
+ if do_set:
+ set_(self, bool(value))
+ else:
+ return get(self)
+
+ _munge_docstring = re.compile(r'gpgme_([^(]*)\(([^,]*), (.*\) -> .*)')
+ def __getattr__(self, key):
+ """On-the-fly generation of wrapper methods and properties"""
+ if key[0] == '_' or self._cprefix == None:
+ return None
+
+ if key in self._boolean_properties:
+ return self.__wrap_boolean_property(key)
+
+ name = self._cprefix + key
+ func = getattr(gpgme, name)
+
+ if self._errorcheck(name):
+ def _funcwrap(slf, *args):
+ result = func(slf.wrapped, *args)
+ if slf._callback_excinfo:
+ gpgme.pyme_raise_callback_exception(slf)
+ return errorcheck(result, "Invocation of " + name)
+ else:
+ def _funcwrap(slf, *args):
+ result = func(slf.wrapped, *args)
+ if slf._callback_excinfo:
+ gpgme.pyme_raise_callback_exception(slf)
+ return result
+
+ doc = self._munge_docstring.sub(r'\2.\1(\3', getattr(func, "__doc__"))
+ _funcwrap.__doc__ = doc
+
+ # Monkey-patch the class.
+ setattr(self.__class__, key, _funcwrap)
+
+ # Bind the method to 'self'.
+ def wrapper(*args):
+ return _funcwrap(self, *args)
+ wrapper.__doc__ = doc
+
+ return wrapper
+
+ def __setattr__(self, key, value):
+ """On-the-fly generation of properties"""
+ if key in self._boolean_properties:
+ self.__wrap_boolean_property(key, True, value)
+ else:
+ super(GpgmeWrapper, self).__setattr__(key, value)
+
+class Context(GpgmeWrapper):
+ """Context for cryptographic operations
+
+ All cryptographic operations in GPGME are performed within a
+ context, which contains the internal state of the operation as
+ well as configuration parameters. By using several contexts you
+ can run several cryptographic operations in parallel, with
+ different configuration.
+
+ Access to a context must be synchronized.
+
+ """
+
+ def __init__(self, armor=False, textmode=False, offline=False,
+ signers=[], pinentry_mode=constants.PINENTRY_MODE_DEFAULT,
+ protocol=constants.PROTOCOL_OpenPGP,
+ wrapped=None):
+ """Construct a context object
+
+ Keyword arguments:
+ armor -- enable ASCII armoring (default False)
+ textmode -- enable canonical text mode (default False)
+ offline -- do not contact external key sources (default False)
+ signers -- list of keys used for signing (default [])
+ pinentry_mode -- pinentry mode (default PINENTRY_MODE_DEFAULT)
+ protocol -- protocol to use (default PROTOCOL_OpenPGP)
+
+ """
+ if wrapped:
+ self.own = False
+ else:
+ tmp = gpgme.new_gpgme_ctx_t_p()
+ errorcheck(gpgme.gpgme_new(tmp))
+ wrapped = gpgme.gpgme_ctx_t_p_value(tmp)
+ gpgme.delete_gpgme_ctx_t_p(tmp)
+ self.own = True
+ super(Context, self).__init__(wrapped)
+ self.armor = armor
+ self.textmode = textmode
+ self.offline = offline
+ self.signers = signers
+ self.pinentry_mode = pinentry_mode
+ self.protocol = protocol
+
+ def encrypt(self, plaintext, recipients=[], sign=True, sink=None,
+ passphrase=None, always_trust=False, add_encrypt_to=False,
+ prepare=False, expect_sign=False, compress=True):
+ """Encrypt data
+
+ Encrypt the given plaintext for the given recipients. If the
+ list of recipients is empty, the data is encrypted
+ symmetrically with a passphrase.
+
+ The passphrase can be given as parameter, using a callback
+ registered at the context, or out-of-band via pinentry.
+
+ Keyword arguments:
+ recipients -- list of keys to encrypt to
+ sign -- sign plaintext (default True)
+ sink -- write result to sink instead of returning it
+ passphrase -- for symmetric encryption
+ always_trust -- always trust the keys (default False)
+ add_encrypt_to -- encrypt to configured additional keys (default False)
+ prepare -- (ui) prepare for encryption (default False)
+ expect_sign -- (ui) prepare for signing (default False)
+ compress -- compress plaintext (default True)
+
+ Returns:
+ ciphertext -- the encrypted data (or None if sink is given)
+ result -- additional information about the encryption
+ sign_result -- additional information about the signature(s)
+
+ Raises:
+ InvalidRecipients -- if encryption using a particular key failed
+ InvalidSigners -- if signing using a particular key failed
+ GPGMEError -- as signaled by the underlying library
+
+ """
+ ciphertext = sink if sink else Data()
+ flags = 0
+ flags |= always_trust * constants.ENCRYPT_ALWAYS_TRUST
+ flags |= (not add_encrypt_to) * constants.ENCRYPT_NO_ENCRYPT_TO
+ flags |= prepare * constants.ENCRYPT_PREPARE
+ flags |= expect_sign * constants.ENCRYPT_EXPECT_SIGN
+ flags |= (not compress) * constants.ENCRYPT_NO_COMPRESS
+
+ if passphrase != None:
+ old_pinentry_mode = self.pinentry_mode
+ old_passphrase_cb = getattr(self, '_passphrase_cb', None)
+ self.pinentry_mode = constants.PINENTRY_MODE_LOOPBACK
+ def passphrase_cb(hint, desc, prev_bad, hook=None):
+ return passphrase
+ self.set_passphrase_cb(passphrase_cb)
+
+ try:
+ if sign:
+ self.op_encrypt_sign(recipients, flags, plaintext, ciphertext)
+ else:
+ self.op_encrypt(recipients, flags, plaintext, ciphertext)
+ except errors.GPGMEError as e:
+ if e.getcode() == errors.UNUSABLE_PUBKEY:
+ result = self.op_encrypt_result()
+ if result.invalid_recipients:
+ raise errors.InvalidRecipients(result.invalid_recipients)
+ if e.getcode() == errors.UNUSABLE_SECKEY:
+ sig_result = self.op_sign_result()
+ if sig_result.invalid_signers:
+ raise errors.InvalidSigners(sig_result.invalid_signers)
+ raise
+ finally:
+ if passphrase != None:
+ self.pinentry_mode = old_pinentry_mode
+ if old_passphrase_cb:
+ self.set_passphrase_cb(*old_passphrase_cb[1:])
+
+ result = self.op_encrypt_result()
+ assert not result.invalid_recipients
+ sig_result = self.op_sign_result() if sign else None
+ assert not sig_result or not sig_result.invalid_signers
+
+ cipherbytes = None
+ if not sink:
+ ciphertext.seek(0, os.SEEK_SET)
+ cipherbytes = ciphertext.read()
+ return cipherbytes, result, sig_result
+
+ def decrypt(self, ciphertext, sink=None, passphrase=None, verify=True):
+ """Decrypt data
+
+ Decrypt the given ciphertext and verify any signatures. If
+ VERIFY is an iterable of keys, the ciphertext must be signed
+ by all those keys, otherwise an error is raised.
+
+ If the ciphertext is symmetrically encrypted using a
+ passphrase, that passphrase can be given as parameter, using a
+ callback registered at the context, or out-of-band via
+ pinentry.
+
+ Keyword arguments:
+ sink -- write result to sink instead of returning it
+ passphrase -- for symmetric decryption
+ verify -- check signatures (default True)
+
+ Returns:
+ plaintext -- the decrypted data (or None if sink is given)
+ result -- additional information about the decryption
+ verify_result -- additional information about the signature(s)
+
+ Raises:
+ UnsupportedAlgorithm -- if an unsupported algorithm was used
+ BadSignatures -- if a bad signature is encountered
+ MissingSignatures -- if expected signatures are missing or bad
+ GPGMEError -- as signaled by the underlying library
+
+ """
+ plaintext = sink if sink else Data()
+
+ if passphrase != None:
+ old_pinentry_mode = self.pinentry_mode
+ old_passphrase_cb = getattr(self, '_passphrase_cb', None)
+ self.pinentry_mode = constants.PINENTRY_MODE_LOOPBACK
+ def passphrase_cb(hint, desc, prev_bad, hook=None):
+ return passphrase
+ self.set_passphrase_cb(passphrase_cb)
+
+ try:
+ if verify:
+ self.op_decrypt_verify(ciphertext, plaintext)
+ else:
+ self.op_decrypt(ciphertext, plaintext)
+ finally:
+ if passphrase != None:
+ self.pinentry_mode = old_pinentry_mode
+ if old_passphrase_cb:
+ self.set_passphrase_cb(*old_passphrase_cb[1:])
+
+ result = self.op_decrypt_result()
+ verify_result = self.op_verify_result() if verify else None
+ if result.unsupported_algorithm:
+ raise errors.UnsupportedAlgorithm(result.unsupported_algorithm)
+
+ if verify:
+ if any(s.status != errors.NO_ERROR
+ for s in verify_result.signatures):
+ raise errors.BadSignatures(verify_result)
+
+ if verify and verify != True:
+ missing = list()
+ for key in verify:
+ ok = False
+ for subkey in key.subkeys:
+ for sig in verify_result.signatures:
+ if sig.summary & constants.SIGSUM_VALID == 0:
+ continue
+ if subkey.can_sign and subkey.fpr == sig.fpr:
+ ok = True
+ break
+ if ok:
+ break
+ if not ok:
+ missing.append(key)
+ if missing:
+ raise errors.MissingSignatures(verify_result, missing)
+
+ plainbytes = None
+ if not sink:
+ plaintext.seek(0, os.SEEK_SET)
+ plainbytes = plaintext.read()
+ return plainbytes, result, verify_result
+
+ def sign(self, data, sink=None, mode=constants.SIG_MODE_NORMAL):
+ """Sign data
+
+ Sign the given data with either the configured default local
+ key, or the 'signers' keys of this context.
+
+ Keyword arguments:
+ mode -- signature mode (default: normal, see below)
+ sink -- write result to sink instead of returning it
+
+ Returns:
+ either
+ signed_data -- encoded data and signature (normal mode)
+ signature -- only the signature data (detached mode)
+ cleartext -- data and signature as text (cleartext mode)
+ (or None if sink is given)
+ result -- additional information about the signature(s)
+
+ Raises:
+ InvalidSigners -- if signing using a particular key failed
+ GPGMEError -- as signaled by the underlying library
+
+ """
+ signeddata = sink if sink else Data()
+
+ try:
+ self.op_sign(data, signeddata, mode)
+ except errors.GPGMEError as e:
+ if e.getcode() == errors.UNUSABLE_SECKEY:
+ result = self.op_sign_result()
+ if result.invalid_signers:
+ raise errors.InvalidSigners(result.invalid_signers)
+ raise
+
+ result = self.op_sign_result()
+ assert not result.invalid_signers
+
+ signedbytes = None
+ if not sink:
+ signeddata.seek(0, os.SEEK_SET)
+ signedbytes = signeddata.read()
+ return signedbytes, result
+
+ def verify(self, signed_data, signature=None, sink=None, verify=[]):
+ """Verify signatures
+
+ Verify signatures over data. If VERIFY is an iterable of
+ keys, the ciphertext must be signed by all those keys,
+ otherwise an error is raised.
+
+ Keyword arguments:
+ signature -- detached signature data
+ sink -- write result to sink instead of returning it
+
+ Returns:
+ data -- the plain data
+ (or None if sink is given, or we verified a detached signature)
+ result -- additional information about the signature(s)
+
+ Raises:
+ BadSignatures -- if a bad signature is encountered
+ MissingSignatures -- if expected signatures are missing or bad
+ GPGMEError -- as signaled by the underlying library
+
+ """
+ if signature:
+ # Detached signature, we don't return the plain text.
+ data = None
+ else:
+ data = sink if sink else Data()
+
+ if signature:
+ self.op_verify(signature, signed_data, None)
+ else:
+ self.op_verify(signed_data, None, data)
+
+ result = self.op_verify_result()
+ if any(s.status != errors.NO_ERROR for s in result.signatures):
+ raise errors.BadSignatures(result)
+
+ missing = list()
+ for key in verify:
+ ok = False
+ for subkey in key.subkeys:
+ for sig in result.signatures:
+ if sig.summary & constants.SIGSUM_VALID == 0:
+ continue
+ if subkey.can_sign and subkey.fpr == sig.fpr:
+ ok = True
+ break
+ if ok:
+ break
+ if not ok:
+ missing.append(key)
+ if missing:
+ raise errors.MissingSignatures(result, missing)
+
+ plainbytes = None
+ if data and not sink:
+ data.seek(0, os.SEEK_SET)
+ plainbytes = data.read()
+ return plainbytes, result
+
+ def keylist(self, pattern=None, secret=False):
+ """List keys
+
+ Keyword arguments:
+ pattern -- return keys matching pattern (default: all keys)
+ secret -- return only secret keys
+
+ Returns:
+ -- an iterator returning key objects
+
+ Raises:
+ GPGMEError -- as signaled by the underlying library
+ """
+ return self.op_keylist_all(pattern, secret)
+
+ def assuan_transact(self, command,
+ data_cb=None, inquire_cb=None, status_cb=None):
+ """Issue a raw assuan command
+
+ This function can be used to issue a raw assuan command to the
+ engine.
+
+ If command is a string or bytes, it will be used as-is. If it
+ is an iterable of strings, it will be properly escaped and
+ joined into an well-formed assuan command.
+
+ Keyword arguments:
+ data_cb -- a callback receiving data lines
+ inquire_cb -- a callback providing more information
+ status_cb -- a callback receiving status lines
+
+ Returns:
+ result -- the result of command as GPGMEError
+
+ Raises:
+ GPGMEError -- as signaled by the underlying library
+
+ """
+
+ if isinstance(command, (str, bytes)):
+ cmd = command
+ else:
+ cmd = " ".join(util.percent_escape(f) for f in command)
+
+ errptr = gpgme.new_gpgme_error_t_p()
+
+ err = gpgme.gpgme_op_assuan_transact_ext(
+ self.wrapped,
+ cmd,
+ (weakref.ref(self), data_cb) if data_cb else None,
+ (weakref.ref(self), inquire_cb) if inquire_cb else None,
+ (weakref.ref(self), status_cb) if status_cb else None,
+ errptr)
+
+ if self._callback_excinfo:
+ gpgme.pyme_raise_callback_exception(self)
+
+ errorcheck(err)
+
+ status = gpgme.gpgme_error_t_p_value(errptr)
+ gpgme.delete_gpgme_error_t_p(errptr)
+
+ return GPGMEError(status) if status != 0 else None
+
+ def interact(self, key, func, sink=None, flags=0, fnc_value=None):
+ """Interact with the engine
+
+ This method can be used to edit keys and cards interactively.
+ KEY is the key to edit, FUNC is called repeatedly with two
+ unicode arguments, 'keyword' and 'args'. See the GPGME manual
+ for details.
+
+ Keyword arguments:
+ sink -- if given, additional output is written here
+ flags -- use constants.INTERACT_CARD to edit a card
+
+ Raises:
+ GPGMEError -- as signaled by the underlying library
+
+ """
+ if key == None:
+ raise ValueError("First argument cannot be None")
+
+ if sink == None:
+ sink = Data()
+
+ if fnc_value:
+ opaquedata = (weakref.ref(self), func, fnc_value)
+ else:
+ opaquedata = (weakref.ref(self), func)
+
+ result = gpgme.gpgme_op_interact(self.wrapped, key, flags,
+ opaquedata, sink)
+ if self._callback_excinfo:
+ gpgme.pyme_raise_callback_exception(self)
+ errorcheck(result)
+
+ @property
+ def signers(self):
+ """Keys used for signing"""
+ return [self.signers_enum(i) for i in range(self.signers_count())]
+ @signers.setter
+ def signers(self, signers):
+ old = self.signers
+ self.signers_clear()
+ try:
+ for key in signers:
+ self.signers_add(key)
+ except:
+ self.signers = old
+ raise
+
+ @property
+ def pinentry_mode(self):
+ """Pinentry mode"""
+ return self.get_pinentry_mode()
+ @pinentry_mode.setter
+ def pinentry_mode(self, value):
+ self.set_pinentry_mode(value)
+
+ @property
+ def protocol(self):
+ """Protocol to use"""
+ return self.get_protocol()
+ @protocol.setter
+ def protocol(self, value):
+ errorcheck(gpgme.gpgme_engine_check_version(value))
+ self.set_protocol(value)
+
+ _ctype = 'gpgme_ctx_t'
+ _cprefix = 'gpgme_'
+
+ def _errorcheck(self, name):
+ """This function should list all functions returning gpgme_error_t"""
+ return ((name.startswith('gpgme_op_')
+ and not name.endswith('_result'))
+ or name in {
+ 'gpgme_set_ctx_flag',
+ 'gpgme_set_protocol',
+ 'gpgme_set_sub_protocol',
+ 'gpgme_set_keylist_mode',
+ 'gpgme_set_pinentry_mode',
+ 'gpgme_set_locale',
+ 'gpgme_set_engine_info',
+ 'gpgme_signers_add',
+ 'gpgme_get_sig_key',
+ 'gpgme_sig_notation_add',
+ 'gpgme_cancel',
+ 'gpgme_cancel_async',
+ 'gpgme_cancel_get_key',
+ })
+
+ _boolean_properties = {'armor', 'textmode', 'offline'}
+
+ def __del__(self):
+ if not gpgme:
+ # At interpreter shutdown, gpgme is set to NONE.
+ return
+
+ self._free_passcb()
+ self._free_progresscb()
+ self._free_statuscb()
+ if self.own and self.wrapped and gpgme.gpgme_release:
+ gpgme.gpgme_release(self.wrapped)
+ self.wrapped = None
+
+ # Implement the context manager protocol.
+ def __enter__(self):
+ return self
+ def __exit__(self, type, value, tb):
+ self.__del__()
+
+ def op_keylist_all(self, *args, **kwargs):
+ self.op_keylist_start(*args, **kwargs)
+ key = self.op_keylist_next()
+ while key:
+ yield key
+ key = self.op_keylist_next()
+ self.op_keylist_end()
+
+ def op_keylist_next(self):
+ """Returns the next key in the list created
+ by a call to op_keylist_start(). The object returned
+ is of type Key."""
+ ptr = gpgme.new_gpgme_key_t_p()
+ try:
+ errorcheck(gpgme.gpgme_op_keylist_next(self.wrapped, ptr))
+ key = gpgme.gpgme_key_t_p_value(ptr)
+ except errors.GPGMEError as excp:
+ key = None
+ if excp.getcode() != errors.EOF:
+ raise excp
+ gpgme.delete_gpgme_key_t_p(ptr)
+ if key:
+ key.__del__ = lambda self: gpgme.gpgme_key_unref(self)
+ return key
+
+ def get_key(self, fpr, secret):
+ """Return the key corresponding to the fingerprint 'fpr'"""
+ ptr = gpgme.new_gpgme_key_t_p()
+ errorcheck(gpgme.gpgme_get_key(self.wrapped, fpr, ptr, secret))
+ key = gpgme.gpgme_key_t_p_value(ptr)
+ gpgme.delete_gpgme_key_t_p(ptr)
+ if key:
+ key.__del__ = lambda self: gpgme.gpgme_key_unref(self)
+ return key
+
+ def op_trustlist_all(self, *args, **kwargs):
+ self.op_trustlist_start(*args, **kwargs)
+ trust = self.op_trustlist_next()
+ while trust:
+ yield trust
+ trust = self.op_trustlist_next()
+ self.op_trustlist_end()
+
+ def op_trustlist_next(self):
+ """Returns the next trust item in the list created
+ by a call to op_trustlist_start(). The object returned
+ is of type TrustItem."""
+ ptr = gpgme.new_gpgme_trust_item_t_p()
+ try:
+ errorcheck(gpgme.gpgme_op_trustlist_next(self.wrapped, ptr))
+ trust = gpgme.gpgme_trust_item_t_p_value(ptr)
+ except errors.GPGMEError as excp:
+ trust = None
+ if excp.getcode() != errors.EOF:
+ raise
+ gpgme.delete_gpgme_trust_item_t_p(ptr)
+ return trust
+
+ def set_passphrase_cb(self, func, hook=None):
+ """Sets the passphrase callback to the function specified by func.
+
+ When the system needs a passphrase, it will call func with three args:
+ hint, a string describing the key it needs the passphrase for;
+ desc, a string describing the passphrase it needs;
+ prev_bad, a boolean equal True if this is a call made after
+ unsuccessful previous attempt.
+
+ If hook has a value other than None it will be passed into the func
+ as a forth argument.
+
+ Please see the GPGME manual for more information.
+ """
+ if func == None:
+ hookdata = None
+ else:
+ if hook == None:
+ hookdata = (weakref.ref(self), func)
+ else:
+ hookdata = (weakref.ref(self), func, hook)
+ gpgme.pyme_set_passphrase_cb(self, hookdata)
+
+ def _free_passcb(self):
+ if gpgme.pyme_set_passphrase_cb:
+ self.set_passphrase_cb(None)
+
+ def set_progress_cb(self, func, hook=None):
+ """Sets the progress meter callback to the function specified by FUNC.
+ If FUNC is None, the callback will be cleared.
+
+ This function will be called to provide an interactive update
+ of the system's progress. The function will be called with
+ three arguments, type, total, and current. If HOOK is not
+ None, it will be supplied as fourth argument.
+
+ Please see the GPGME manual for more information.
+
+ """
+ if func == None:
+ hookdata = None
+ else:
+ if hook == None:
+ hookdata = (weakref.ref(self), func)
+ else:
+ hookdata = (weakref.ref(self), func, hook)
+ gpgme.pyme_set_progress_cb(self, hookdata)
+
+ def _free_progresscb(self):
+ if gpgme.pyme_set_progress_cb:
+ self.set_progress_cb(None)
+
+ def set_status_cb(self, func, hook=None):
+ """Sets the status callback to the function specified by FUNC. If
+ FUNC is None, the callback will be cleared.
+
+ The function will be called with two arguments, keyword and
+ args. If HOOK is not None, it will be supplied as third
+ argument.
+
+ Please see the GPGME manual for more information.
+
+ """
+ if func == None:
+ hookdata = None
+ else:
+ if hook == None:
+ hookdata = (weakref.ref(self), func)
+ else:
+ hookdata = (weakref.ref(self), func, hook)
+ gpgme.pyme_set_status_cb(self, hookdata)
+
+ def _free_statuscb(self):
+ if gpgme.pyme_set_status_cb:
+ self.set_status_cb(None)
+
+ @property
+ def engine_info(self):
+ """Configuration of the engine currently in use"""
+ p = self.protocol
+ infos = [i for i in self.get_engine_info() if i.protocol == p]
+ assert len(infos) == 1
+ return infos[0]
+
+ def get_engine_info(self):
+ """Get engine configuration
+
+ Returns information about all configured and installed
+ engines.
+
+ Returns:
+ infos -- a list of engine infos
+
+ """
+ return gpgme.gpgme_ctx_get_engine_info(self.wrapped)
+
+ def set_engine_info(self, proto, file_name=None, home_dir=None):
+ """Change engine configuration
+
+ Changes the configuration of the crypto engine implementing
+ the protocol 'proto' for the context.
+
+ Keyword arguments:
+ file_name -- engine program file name (unchanged if None)
+ home_dir -- configuration directory (unchanged if None)
+
+ """
+ errorcheck(gpgme.gpgme_ctx_set_engine_info(
+ self.wrapped, proto, file_name, home_dir))
+
+ def wait(self, hang):
+ """Wait for asynchronous call to finish. Wait forever if hang is True.
+ Raises an exception on errors.
+
+ Please read the GPGME manual for more information.
+
+ """
+ ptr = gpgme.new_gpgme_error_t_p()
+ gpgme.gpgme_wait(self.wrapped, ptr, hang)
+ status = gpgme.gpgme_error_t_p_value(ptr)
+ gpgme.delete_gpgme_error_t_p(ptr)
+ errorcheck(status)
+
+ def op_edit(self, key, func, fnc_value, out):
+ """Start key editing using supplied callback function
+
+ Note: This interface is deprecated and will be removed with
+ GPGME 1.8. Please use .interact instead. Furthermore, we
+ implement this using gpgme_op_interact, so callbacks will get
+ called with string keywords instead of numeric status
+ messages. Code that is using constants.STATUS_X or
+ constants.status.X will continue to work, whereas code using
+ magic numbers will break as a result.
+
+ """
+ warnings.warn("Call to deprecated method op_edit.",
+ category=DeprecationWarning)
+ return self.interact(key, func, sink=out, fnc_value=fnc_value)
+
+
+class Data(GpgmeWrapper):
+ """Data buffer
+
+ A lot of data has to be exchanged between the user and the crypto
+ engine, like plaintext messages, ciphertext, signatures and
+ information about the keys. The technical details about
+ exchanging the data information are completely abstracted by
+ GPGME. The user provides and receives the data via `gpgme_data_t'
+ objects, regardless of the communication protocol between GPGME
+ and the crypto engine in use.
+
+ This Data class is the implementation of the GpgmeData objects.
+
+ Please see the information about __init__ for instantiation.
+
+ """
+
+ _ctype = 'gpgme_data_t'
+ _cprefix = 'gpgme_data_'
+
+ def _errorcheck(self, name):
+ """This function should list all functions returning gpgme_error_t"""
+ return name not in {
+ 'gpgme_data_release_and_get_mem',
+ 'gpgme_data_get_encoding',
+ 'gpgme_data_seek',
+ 'gpgme_data_get_file_name',
+ }
+
+ def __init__(self, string=None, file=None, offset=None,
+ length=None, cbs=None, copy=True):
+ """Initialize a new gpgme_data_t object.
+
+ If no args are specified, make it an empty object.
+
+ If string alone is specified, initialize it with the data
+ contained there.
+
+ If file, offset, and length are all specified, file must
+ be either a filename or a file-like object, and the object
+ will be initialized by reading the specified chunk from the file.
+
+ If cbs is specified, it MUST be a tuple of the form:
+
+ (read_cb, write_cb, seek_cb, release_cb[, hook])
+
+ where the first four items are functions implementing reading,
+ writing, seeking the data, and releasing any resources once
+ the data object is deallocated. The functions must match the
+ following prototypes:
+
+ def read(amount, hook=None):
+ return <a b"bytes" object>
+
+ def write(data, hook=None):
+ return <the number of bytes written>
+
+ def seek(offset, whence, hook=None):
+ return <the new file position>
+
+ def release(hook=None):
+ <return value and exceptions are ignored>
+
+ The functions may be bound methods. In that case, you can
+ simply use the 'self' reference instead of using a hook.
+
+ If file is specified without any other arguments, then
+ it must be a filename, and the object will be initialized from
+ that file.
+
+ """
+ super(Data, self).__init__(None)
+ self.data_cbs = None
+
+ if cbs != None:
+ self.new_from_cbs(*cbs)
+ elif string != None:
+ self.new_from_mem(string, copy)
+ elif file != None and offset != None and length != None:
+ self.new_from_filepart(file, offset, length)
+ elif file != None:
+ if util.is_a_string(file):
+ self.new_from_file(file, copy)
+ else:
+ self.new_from_fd(file)
+ else:
+ self.new()
+
+ def __del__(self):
+ if not gpgme:
+ # At interpreter shutdown, gpgme is set to NONE.
+ return
+
+ if self.wrapped != None and gpgme.gpgme_data_release:
+ gpgme.gpgme_data_release(self.wrapped)
+ if self._callback_excinfo:
+ gpgme.pyme_raise_callback_exception(self)
+ self.wrapped = None
+ self._free_datacbs()
+
+ # Implement the context manager protocol.
+ def __enter__(self):
+ return self
+ def __exit__(self, type, value, tb):
+ self.__del__()
+
+ def _free_datacbs(self):
+ self._data_cbs = None
+
+ def new(self):
+ tmp = gpgme.new_gpgme_data_t_p()
+ errorcheck(gpgme.gpgme_data_new(tmp))
+ self.wrapped = gpgme.gpgme_data_t_p_value(tmp)
+ gpgme.delete_gpgme_data_t_p(tmp)
+
+ def new_from_mem(self, string, copy=True):
+ tmp = gpgme.new_gpgme_data_t_p()
+ errorcheck(gpgme.gpgme_data_new_from_mem(tmp,string,len(string),copy))
+ self.wrapped = gpgme.gpgme_data_t_p_value(tmp)
+ gpgme.delete_gpgme_data_t_p(tmp)
+
+ def new_from_file(self, filename, copy=True):
+ tmp = gpgme.new_gpgme_data_t_p()
+ try:
+ errorcheck(gpgme.gpgme_data_new_from_file(tmp, filename, copy))
+ except errors.GPGMEError as e:
+ if e.getcode() == errors.INV_VALUE and not copy:
+ raise ValueError("delayed reads are not yet supported")
+ else:
+ raise e
+ self.wrapped = gpgme.gpgme_data_t_p_value(tmp)
+ gpgme.delete_gpgme_data_t_p(tmp)
+
+ def new_from_cbs(self, read_cb, write_cb, seek_cb, release_cb, hook=None):
+ tmp = gpgme.new_gpgme_data_t_p()
+ if hook != None:
+ hookdata = (weakref.ref(self),
+ read_cb, write_cb, seek_cb, release_cb, hook)
+ else:
+ hookdata = (weakref.ref(self),
+ read_cb, write_cb, seek_cb, release_cb)
+ gpgme.pyme_data_new_from_cbs(self, hookdata, tmp)
+ self.wrapped = gpgme.gpgme_data_t_p_value(tmp)
+ gpgme.delete_gpgme_data_t_p(tmp)
+
+ def new_from_filepart(self, file, offset, length):
+ """This wraps the GPGME gpgme_data_new_from_filepart() function.
+ The argument "file" may be:
+
+ * a string specifying a file name, or
+ * a file-like object supporting the fileno() and the mode attribute.
+
+ """
+
+ tmp = gpgme.new_gpgme_data_t_p()
+ filename = None
+ fp = None
+
+ if util.is_a_string(file):
+ filename = file
+ else:
+ fp = gpgme.fdopen(file.fileno(), file.mode)
+ if fp == None:
+ raise ValueError("Failed to open file from %s arg %s" % \
+ (str(type(file)), str(file)))
+
+ errorcheck(gpgme.gpgme_data_new_from_filepart(tmp, filename, fp,
+ offset, length))
+ self.wrapped = gpgme.gpgme_data_t_p_value(tmp)
+ gpgme.delete_gpgme_data_t_p(tmp)
+
+ def new_from_fd(self, file):
+ """This wraps the GPGME gpgme_data_new_from_fd() function. The
+ argument "file" must be a file-like object, supporting the
+ fileno() method.
+
+ """
+ tmp = gpgme.new_gpgme_data_t_p()
+ errorcheck(gpgme.gpgme_data_new_from_fd(tmp, file.fileno()))
+ self.wrapped = gpgme.gpgme_data_t_p_value(tmp)
+ gpgme.delete_gpgme_data_t_p(tmp)
+
+ def new_from_stream(self, file):
+ """This wrap around gpgme_data_new_from_stream is an alias for
+ new_from_fd() method since in python there's not difference
+ between file stream and file descriptor"""
+ self.new_from_fd(file)
+
+ def write(self, buffer):
+ """Write buffer given as string or bytes.
+
+ If a string is given, it is implicitly encoded using UTF-8."""
+ written = gpgme.gpgme_data_write(self.wrapped, buffer)
+ if written < 0:
+ if self._callback_excinfo:
+ gpgme.pyme_raise_callback_exception(self)
+ else:
+ raise GPGMEError.fromSyserror()
+ return written
+
+ def read(self, size = -1):
+ """Read at most size bytes, returned as bytes.
+
+ If the size argument is negative or omitted, read until EOF is reached.
+
+ Returns the data read, or the empty string if there was no data
+ to read before EOF was reached."""
+
+ if size == 0:
+ return ''
+
+ if size > 0:
+ try:
+ result = gpgme.gpgme_data_read(self.wrapped, size)
+ except:
+ if self._callback_excinfo:
+ gpgme.pyme_raise_callback_exception(self)
+ else:
+ raise
+ return result
+ else:
+ chunks = []
+ while True:
+ try:
+ result = gpgme.gpgme_data_read(self.wrapped, 4096)
+ except:
+ if self._callback_excinfo:
+ gpgme.pyme_raise_callback_exception(self)
+ else:
+ raise
+ if len(result) == 0:
+ break
+ chunks.append(result)
+ return b''.join(chunks)
+
+def pubkey_algo_name(algo):
+ return gpgme.gpgme_pubkey_algo_name(algo)
+
+def hash_algo_name(algo):
+ return gpgme.gpgme_hash_algo_name(algo)
+
+def get_protocol_name(proto):
+ return gpgme.gpgme_get_protocol_name(proto)
+
+def check_version(version=None):
+ return gpgme.gpgme_check_version(version)
+
+# check_version also makes sure that several subsystems are properly
+# initialized, and it must be run at least once before invoking any
+# other function. We do it here so that the user does not have to do
+# it unless she really wants to check for a certain version.
+check_version()
+
+def engine_check_version (proto):
+ try:
+ errorcheck(gpgme.gpgme_engine_check_version(proto))
+ return True
+ except errors.GPGMEError:
+ return False
+
+def get_engine_info():
+ ptr = gpgme.new_gpgme_engine_info_t_p()
+ try:
+ errorcheck(gpgme.gpgme_get_engine_info(ptr))
+ info = gpgme.gpgme_engine_info_t_p_value(ptr)
+ except errors.GPGMEError:
+ info = None
+ gpgme.delete_gpgme_engine_info_t_p(ptr)
+ return info
+
+def set_engine_info(proto, file_name, home_dir=None):
+ """Changes the default configuration of the crypto engine implementing
+ the protocol 'proto'. 'file_name' is the file name of
+ the executable program implementing this protocol. 'home_dir' is the
+ directory name of the configuration directory (engine's default is
+ used if omitted)."""
+ errorcheck(gpgme.gpgme_set_engine_info(proto, file_name, home_dir))
+
+def set_locale(category, value):
+ """Sets the default locale used by contexts"""
+ errorcheck(gpgme.gpgme_set_locale(None, category, value))
+
+def wait(hang):
+ """Wait for asynchronous call on any Context to finish.
+ Wait forever if hang is True.
+
+ For finished anynch calls it returns a tuple (status, context):
+ status - status return by asnynchronous call.
+ context - context which caused this call to return.
+
+ Please read the GPGME manual of more information."""
+ ptr = gpgme.new_gpgme_error_t_p()
+ context = gpgme.gpgme_wait(None, ptr, hang)
+ status = gpgme.gpgme_error_t_p_value(ptr)
+ gpgme.delete_gpgme_error_t_p(ptr)
+ if context == None:
+ errorcheck(status)
+ else:
+ context = Context(context)
+ return (status, context)
diff --git a/lang/python/pyme/errors.py b/lang/python/pyme/errors.py
new file mode 100644
index 0000000..e26c747
--- /dev/null
+++ b/lang/python/pyme/errors.py
@@ -0,0 +1,111 @@
+# Copyright (C) 2004 Igor Belyi <belyi@users.sourceforge.net>
+# Copyright (C) 2002 John Goerzen <jgoerzen@complete.org>
+#
+# This library is free software; you can redistribute it and/or
+# modify it under the terms of the GNU Lesser General Public
+# License as published by the Free Software Foundation; either
+# version 2.1 of the License, or (at your option) any later version.
+#
+# This library is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+# Lesser General Public License for more details.
+#
+# You should have received a copy of the GNU Lesser General Public
+# License along with this library; if not, write to the Free Software
+# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+
+from __future__ import absolute_import, print_function, unicode_literals
+del absolute_import, print_function, unicode_literals
+
+from . import gpgme
+from . import util
+
+util.process_constants('GPG_ERR_', globals())
+
+# To appease static analysis tools, we define some constants here:
+NO_ERROR = 0
+
+class PymeError(Exception):
+ pass
+
+class GPGMEError(PymeError):
+ def __init__(self, error = None, message = None):
+ self.error = error
+ self.message = message
+
+ @classmethod
+ def fromSyserror(cls):
+ return cls(gpgme.gpgme_err_code_from_syserror())
+
+ def getstring(self):
+ message = "%s: %s" % (gpgme.gpgme_strsource(self.error),
+ gpgme.gpgme_strerror(self.error))
+ if self.message != None:
+ message = "%s: %s" % (self.message, message)
+ return message
+
+ def getcode(self):
+ return gpgme.gpgme_err_code(self.error)
+
+ def getsource(self):
+ return gpgme.gpgme_err_source(self.error)
+
+ def __str__(self):
+ return self.getstring()
+
+def errorcheck(retval, extradata = None):
+ if retval:
+ raise GPGMEError(retval, extradata)
+
+# These errors are raised in the idiomatic interface code.
+
+class EncryptionError(PymeError):
+ pass
+
+class InvalidRecipients(EncryptionError):
+ def __init__(self, recipients):
+ self.recipients = recipients
+ def __str__(self):
+ return ", ".join("{}: {}".format(r.fpr,
+ gpgme.gpgme_strerror(r.reason))
+ for r in self.recipients)
+
+class DeryptionError(PymeError):
+ pass
+
+class UnsupportedAlgorithm(DeryptionError):
+ def __init__(self, algorithm):
+ self.algorithm = algorithm
+ def __str__(self):
+ return self.algorithm
+
+class SigningError(PymeError):
+ pass
+
+class InvalidSigners(SigningError):
+ def __init__(self, signers):
+ self.signers = signers
+ def __str__(self):
+ return ", ".join("{}: {}".format(s.fpr,
+ gpgme.gpgme_strerror(s.reason))
+ for s in self.signers)
+
+class VerificationError(PymeError):
+ pass
+
+class BadSignatures(VerificationError):
+ def __init__(self, result):
+ self.result = result
+ def __str__(self):
+ return ", ".join("{}: {}".format(s.fpr,
+ gpgme.gpgme_strerror(s.status))
+ for s in self.result.signatures
+ if s.status != NO_ERROR)
+
+class MissingSignatures(VerificationError):
+ def __init__(self, result, missing):
+ self.result = result
+ self.missing = missing
+ def __str__(self):
+ return ", ".join(k.subkeys[0].fpr for k in self.missing)
diff --git a/lang/python/pyme/gpgme.py b/lang/python/pyme/gpgme.py
new file mode 100644
index 0000000..ea4983d
--- /dev/null
+++ b/lang/python/pyme/gpgme.py
@@ -0,0 +1,125 @@
+# This file was automatically generated by SWIG (http://www.swig.org).
+# Version 3.0.7
+#
+# Do not make changes to this file unless you know what you are doing--modify
+# the SWIG interface file instead.
+
+
+
+
+
+from sys import version_info
+if version_info >= (2, 6, 0):
+ def swig_import_helper():
+ from os.path import dirname
+ import imp
+ fp = None
+ try:
+ fp, pathname, description = imp.find_module('_gpgme', [dirname(__file__)])
+ except ImportError:
+ import _gpgme
+ return _gpgme
+ if fp is not None:
+ try:
+ _mod = imp.load_module('_gpgme', fp, pathname, description)
+ finally:
+ fp.close()
+ return _mod
+ _gpgme = swig_import_helper()
+ del swig_import_helper
+else:
+ import _gpgme
+del version_info
+from _gpgme import *
+try:
+ _swig_property = property
+except NameError:
+ pass # Python < 2.2 doesn't have 'property'.
+
+
+def _swig_setattr_nondynamic(self, class_type, name, value, static=1):
+ if (name == "thisown"):
+ return self.this.own(value)
+ if (name == "this"):
+ if type(value).__name__ == 'SwigPyObject':
+ self.__dict__[name] = value
+ return
+ method = class_type.__swig_setmethods__.get(name, None)
+ if method:
+ return method(self, value)
+ if (not static):
+ if _newclass:
+ object.__setattr__(self, name, value)
+ else:
+ self.__dict__[name] = value
+ else:
+ raise AttributeError("You cannot add attributes to %s" % self)
+
+
+def _swig_setattr(self, class_type, name, value):
+ return _swig_setattr_nondynamic(self, class_type, name, value, 0)
+
+
+def _swig_getattr_nondynamic(self, class_type, name, static=1):
+ if (name == "thisown"):
+ return self.this.own()
+ method = class_type.__swig_getmethods__.get(name, None)
+ if method:
+ return method(self)
+ if (not static):
+ return object.__getattr__(self, name)
+ else:
+ raise AttributeError(name)
+
+def _swig_getattr(self, class_type, name):
+ return _swig_getattr_nondynamic(self, class_type, name, 0)
+
+
+def _swig_repr(self):
+ try:
+ strthis = "proxy of " + self.this.__repr__()
+ except:
+ strthis = ""
+ return "<%s.%s; %s >" % (self.__class__.__module__, self.__class__.__name__, strthis,)
+
+try:
+ _object = object
+ _newclass = 1
+except AttributeError:
+ class _object:
+ pass
+ _newclass = 0
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+# This file is compatible with both classic and new-style classes.
+
+
diff --git a/lang/python/pyme/results.py b/lang/python/pyme/results.py
new file mode 100644
index 0000000..3383896
--- /dev/null
+++ b/lang/python/pyme/results.py
@@ -0,0 +1,118 @@
+# Robust result objects
+#
+# Copyright (C) 2016 g10 Code GmbH
+#
+# This file is part of GPGME.
+#
+# GPGME is free software; you can redistribute it and/or modify it
+# under the terms of the GNU Lesser General Public License as
+# published by the Free Software Foundation; either version 2.1 of the
+# License, or (at your option) any later version.
+#
+# GPGME is distributed in the hope that it will be useful, but WITHOUT
+# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
+# or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General
+# Public License for more details.
+#
+# You should have received a copy of the GNU Lesser General Public
+# License along with this program; if not, see <http://www.gnu.org/licenses/>.
+
+from __future__ import absolute_import, print_function, unicode_literals
+del absolute_import, print_function, unicode_literals
+
+"""Robust result objects
+
+Results returned by the underlying library are fragile, i.e. they are
+only valid until the next operation is performed in the context.
+
+We cannot arbitrarily constrain the lifetime of Python objects, we
+therefore create deep copies of the results.
+
+"""
+
+class Result(object):
+ """Result object
+
+ Describes the result of an operation.
+
+ """
+
+ """Convert to types"""
+ _type = {}
+
+ """Map functions over list attributes"""
+ _map = {}
+
+ """Automatically copy unless blacklisted"""
+ _blacklist = {
+ 'acquire', 'append', 'disown', 'next', 'own', 'this', 'thisown',
+ }
+ def __init__(self, fragile):
+ for key, func in self._type.items():
+ if hasattr(fragile, key):
+ setattr(self, key, func(getattr(fragile, key)))
+
+ for key, func in self._map.items():
+ if hasattr(fragile, key):
+ setattr(self, key, list(map(func, getattr(fragile, key))))
+
+ for key in dir(fragile):
+ if key.startswith('_') or key in self._blacklist:
+ continue
+ if hasattr(self, key):
+ continue
+
+ setattr(self, key, getattr(fragile, key))
+
+ def __str__(self):
+ return '<{} {}>'.format(
+ self.__class__.__name__,
+ ', '.join('{}: {}'.format(k, getattr(self, k))
+ for k in dir(self) if not k.startswith('_')))
+
+class InvalidKey(Result):
+ pass
+
+class EncryptResult(Result):
+ _map = dict(invalid_recipients=InvalidKey)
+
+class Recipient(Result):
+ pass
+
+class DecryptResult(Result):
+ _type = dict(wrong_key_usage=bool)
+ _map = dict(recipients=Recipient)
+
+class NewSignature(Result):
+ pass
+
+class SignResult(Result):
+ _map = dict(invalid_signers=InvalidKey, signatures=NewSignature)
+
+class Notation(Result):
+ pass
+
+class Signature(Result):
+ _type = dict(wrong_key_usage=bool, chain_model=bool)
+ _map = dict(notations=Notation)
+
+class VerifyResult(Result):
+ _map = dict(signatures=Signature)
+
+class ImportStatus(Result):
+ pass
+
+class ImportResult(Result):
+ _map = dict(imports=ImportStatus)
+
+class GenkeyResult(Result):
+ _type = dict(primary=bool, sub=bool)
+
+class KeylistResult(Result):
+ _type = dict(truncated=bool)
+
+class VFSMountResult(Result):
+ pass
+
+class EngineInfo(Result):
+ pass
diff --git a/lang/python/pyme/util.py b/lang/python/pyme/util.py
new file mode 100644
index 0000000..e4fca4c
--- /dev/null
+++ b/lang/python/pyme/util.py
@@ -0,0 +1,53 @@
+# Copyright (C) 2016 g10 Code GmbH
+# Copyright (C) 2004,2008 Igor Belyi <belyi@users.sourceforge.net>
+# Copyright (C) 2002 John Goerzen <jgoerzen@complete.org>
+#
+# This library is free software; you can redistribute it and/or
+# modify it under the terms of the GNU Lesser General Public
+# License as published by the Free Software Foundation; either
+# version 2.1 of the License, or (at your option) any later version.
+#
+# This library is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+# Lesser General Public License for more details.
+#
+# You should have received a copy of the GNU Lesser General Public
+# License along with this library; if not, write to the Free Software
+# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+
+from __future__ import absolute_import, print_function, unicode_literals
+del absolute_import, print_function, unicode_literals
+
+import sys
+
+def process_constants(prefix, scope):
+ """Called by the constant modules to load up the constants from the C
+ library starting with PREFIX. Matching constants will be inserted
+ into SCOPE with PREFIX stripped from the names. Returns the names
+ of inserted constants.
+
+ """
+ from . import gpgme
+ index = len(prefix)
+ constants = {identifier[index:]: getattr(gpgme, identifier)
+ for identifier in dir(gpgme)
+ if identifier.startswith(prefix)}
+ scope.update(constants)
+ return list(constants.keys())
+
+def percent_escape(s):
+ return ''.join(
+ '%{0:2x}'.format(ord(c))
+ if c == '+' or c == '"' or c == '%' or ord(c) <= 0x20 else c
+ for c in s)
+
+# Python2/3 compatibility
+if sys.version_info[0] == 3:
+ # Python3
+ def is_a_string(x):
+ return isinstance(x, str)
+else:
+ # Python2
+ def is_a_string(x):
+ return isinstance(x, basestring)
diff --git a/lang/python/pyme/version.py b/lang/python/pyme/version.py
new file mode 100644
index 0000000..21a0122
--- /dev/null
+++ b/lang/python/pyme/version.py
@@ -0,0 +1,68 @@
+# Copyright (C) 2016 g10 Code GmbH
+# Copyright (C) 2015 Ben McGinnes <ben@adversary.org>
+# Copyright (C) 2004 Igor Belyi <belyi@users.sourceforge.net>
+#
+# This library is free software; you can redistribute it and/or
+# modify it under the terms of the GNU Lesser General Public
+# License as published by the Free Software Foundation; either
+# version 2.1 of the License, or (at your option) any later version.
+#
+# This library is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+# Lesser General Public License for more details.
+#
+# You should have received a copy of the GNU Lesser General Public
+# License along with this library; if not, write to the Free Software
+# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+
+from __future__ import absolute_import, print_function
+del absolute_import, print_function
+
+from . import gpgme
+
+productname = 'pyme'
+versionstr = "1.7.0"
+gpgme_versionstr = gpgme.GPGME_VERSION
+in_tree_build = bool(gpgme.cvar.pyme_in_tree_build)
+
+versionlist = versionstr.split(".")
+major = versionlist[0]
+minor = versionlist[1]
+patch = versionlist[2]
+
+copyright = """\
+Copyright (C) 2016 g10 Code GmbH
+Copyright (C) 2015 Ben McGinnes
+Copyright (C) 2014-2015 Martin Albrecht
+Copyright (C) 2004-2008 Igor Belyi
+Copyright (C) 2002 John Goerzen"""
+
+author = "The GnuPG hackers"
+author_email = "gnupg-devel@gnupg.org"
+
+description = "Python support for GPGME GnuPG cryptography library"
+homepage = "https://gnupg.org"
+
+license = """Copyright (C) 2016 g10 Code GmbH
+Copyright (C) 2015 Ben McGinnes <ben@adversary.org>
+Copyright (C) 2014, 2015 Martin Albrecht <martinralbrecht@googlemail.com>
+Copyright (C) 2004, 2008 Igor Belyi <belyi@users.sourceforge.net>
+Copyright (C) 2002 John Goerzen <jgoerzen@complete.org>
+
+This library is free software; you can redistribute it and/or
+modify it under the terms of the GNU Lesser General Public
+License as published by the Free Software Foundation; either
+version 2.1 of the License, or (at your option) any later version.
+
+This library is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+Lesser General Public License for more details.
+
+You should have received a copy of the GNU Lesser General Public
+License along with this library; if not, write to the Free Software
+Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA"""
+
+# Interface hygiene. Keep this at the end.
+del gpgme
diff --git a/lang/python/pyme/version.py.in b/lang/python/pyme/version.py.in
new file mode 100644
index 0000000..cfb9510
--- /dev/null
+++ b/lang/python/pyme/version.py.in
@@ -0,0 +1,68 @@
+# Copyright (C) 2016 g10 Code GmbH
+# Copyright (C) 2015 Ben McGinnes <ben@adversary.org>
+# Copyright (C) 2004 Igor Belyi <belyi@users.sourceforge.net>
+#
+# This library is free software; you can redistribute it and/or
+# modify it under the terms of the GNU Lesser General Public
+# License as published by the Free Software Foundation; either
+# version 2.1 of the License, or (at your option) any later version.
+#
+# This library is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+# Lesser General Public License for more details.
+#
+# You should have received a copy of the GNU Lesser General Public
+# License along with this library; if not, write to the Free Software
+# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+
+from __future__ import absolute_import, print_function
+del absolute_import, print_function
+
+from . import gpgme
+
+productname = 'pyme'
+versionstr = "@VERSION@"
+gpgme_versionstr = gpgme.GPGME_VERSION
+in_tree_build = bool(gpgme.cvar.pyme_in_tree_build)
+
+versionlist = versionstr.split(".")
+major = versionlist[0]
+minor = versionlist[1]
+patch = versionlist[2]
+
+copyright = """\
+Copyright (C) 2016 g10 Code GmbH
+Copyright (C) 2015 Ben McGinnes
+Copyright (C) 2014-2015 Martin Albrecht
+Copyright (C) 2004-2008 Igor Belyi
+Copyright (C) 2002 John Goerzen"""
+
+author = "The GnuPG hackers"
+author_email = "gnupg-devel@gnupg.org"
+
+description = "Python support for GPGME GnuPG cryptography library"
+homepage = "https://gnupg.org"
+
+license = """Copyright (C) 2016 g10 Code GmbH
+Copyright (C) 2015 Ben McGinnes <ben@adversary.org>
+Copyright (C) 2014, 2015 Martin Albrecht <martinralbrecht@googlemail.com>
+Copyright (C) 2004, 2008 Igor Belyi <belyi@users.sourceforge.net>
+Copyright (C) 2002 John Goerzen <jgoerzen@complete.org>
+
+This library is free software; you can redistribute it and/or
+modify it under the terms of the GNU Lesser General Public
+License as published by the Free Software Foundation; either
+version 2.1 of the License, or (at your option) any later version.
+
+This library is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+Lesser General Public License for more details.
+
+You should have received a copy of the GNU Lesser General Public
+License along with this library; if not, write to the Free Software
+Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA"""
+
+# Interface hygiene. Keep this at the end.
+del gpgme
diff --git a/lang/python/setup.py.in b/lang/python/setup.py.in
new file mode 100755
index 0000000..31892c1
--- /dev/null
+++ b/lang/python/setup.py.in
@@ -0,0 +1,190 @@
+#!/usr/bin/env python
+
+# Copyright (C) 2016 g10 Code GmbH
+# Copyright (C) 2004 Igor Belyi <belyi@users.sourceforge.net>
+# Copyright (C) 2002 John Goerzen <jgoerzen@complete.org>
+#
+# This library is free software; you can redistribute it and/or
+# modify it under the terms of the GNU Lesser General Public
+# License as published by the Free Software Foundation; either
+# version 2.1 of the License, or (at your option) any later version.
+#
+# This library is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+# Lesser General Public License for more details.
+#
+# You should have received a copy of the GNU Lesser General Public
+# License along with this library; if not, write to the Free Software
+# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+
+from distutils.core import setup, Extension
+import os, os.path, sys
+import glob
+import subprocess
+
+# Out-of-tree build of the pyme3 bindings.
+gpg_error_config = ["gpg-error-config"]
+gpgme_config_flags = ["--thread=pthread"]
+gpgme_config = ["gpgme-config"] + gpgme_config_flags
+gpgme_h = ""
+library_dirs = []
+in_tree = False
+extra_swig_opts = []
+extra_macros = dict()
+
+if os.path.exists("../../src/gpgme-config"):
+ # In-tree build.
+ in_tree = True
+ gpgme_config = ["../../src/gpgme-config"] + gpgme_config_flags
+ gpgme_h = "../../src/gpgme.h"
+ library_dirs = ["../../src/.libs"] # XXX uses libtool internals
+ extra_macros.update(
+ HAVE_DATA_H=1,
+ IN_TREE_BUILD=1,
+ )
+
+if hasattr(subprocess, "DEVNULL"):
+ devnull = subprocess.DEVNULL
+else:
+ devnull = open(os.devnull, "w")
+
+try:
+ subprocess.check_call(gpg_error_config + ['--version'],
+ stdout=devnull)
+except:
+ sys.exit("Could not find gpg-error-config. " +
+ "Please install the libgpg-error development package.")
+
+try:
+ subprocess.check_call(gpgme_config + ['--version'],
+ stdout=devnull)
+except:
+ sys.exit("Could not find gpgme-config. " +
+ "Please install the libgpgme development package.")
+
+def getconfig(what, config=gpgme_config):
+ confdata = subprocess.Popen(config + ["--%s" % what],
+ stdout=subprocess.PIPE).communicate()[0]
+ return [x for x in confdata.decode('utf-8').split() if x != '']
+
+version = version_raw = getconfig("version")[0]
+if '-' in version:
+ version = version.split('-')[0]
+major, minor, patch = map(int, version.split('.'))
+
+if not (major > 1 or (major == 1 and minor >= 6)):
+ sys.exit('Need at least GPGME version 1.6, found {}.'.format(version_raw))
+
+if not gpgme_h:
+ gpgme_h = os.path.join(getconfig("prefix")[0], "include", "gpgme.h")
+
+gpg_error_prefix = getconfig("prefix", config=gpg_error_config)[0]
+gpg_error_h = os.path.join(gpg_error_prefix, "include", "gpg-error.h")
+if not os.path.exists(gpg_error_h):
+ gpg_error_h = \
+ glob.glob(os.path.join(gpg_error_prefix, "include",
+ "*", "gpg-error.h"))[0]
+
+print("Building pyme3 using {} and {}.".format(gpgme_h, gpg_error_h))
+
+# Cleanup gpgme.h from deprecated functions and typedefs.
+subprocess.check_call([sys.executable, "gpgme-h-clean.py", gpgme_h],
+ stdout=open("gpgme.h", "w"))
+subprocess.check_call([sys.executable, "gpgme-h-clean.py", gpg_error_h],
+ stdout=open("errors.i", "w"))
+
+include_dirs = [os.getcwd()]
+define_macros = []
+libs = getconfig('libs')
+
+# Define extra_macros for both the SWIG and C code
+for k, v in extra_macros.items():
+ extra_swig_opts.append("-D{0}={1}".format(k, v))
+ define_macros.append((k, str(v)))
+
+for item in getconfig('cflags'):
+ if item.startswith("-I"):
+ include_dirs.append(item[2:])
+ elif item.startswith("-D"):
+ defitem = item[2:].split("=", 1)
+ if len(defitem)==2:
+ define_macros.append((defitem[0], defitem[1]))
+ else:
+ define_macros.append((defitem[0], None))
+
+# Adjust include and library locations in case of win32
+uname_s = os.popen("uname -s").read()
+if uname_s.startswith("MINGW32"):
+ mnts = [x.split()[0:3:2] for x in os.popen("mount").read().split("\n") if x]
+ tmplist = sorted([(len(x[1]), x[1], x[0]) for x in mnts])
+ tmplist.reverse()
+ extra_dirs = []
+ for item in include_dirs:
+ for ln, mnt, tgt in tmplist:
+ if item.startswith(mnt):
+ item = os.path.normpath(item[ln:])
+ while item[0] == os.path.sep:
+ item = item[1:]
+ extra_dirs.append(os.path.join(tgt, item))
+ break
+ include_dirs += extra_dirs
+ for item in [x[2:] for x in libs if x.startswith("-L")]:
+ for ln, mnt, tgt in tmplist:
+ if item.startswith(mnt):
+ item = os.path.normpath(item[ln:])
+ while item[0] == os.path.sep:
+ item = item[1:]
+ library_dirs.append(os.path.join(tgt, item))
+ break
+
+# We build an Extension using SWIG, which generates a Python module.
+# By default, the 'build_py' step is run before 'build_ext', and
+# therefore the generated Python module is not copied into the build
+# directory.
+# Bug: http://bugs.python.org/issue1016626
+# Workaround:
+# http://stackoverflow.com/questions/12491328/python-distutils-not-include-the-swig-generated-module
+from distutils.command.build import build
+class BuildExtFirstHack(build):
+ def run(self):
+ self.run_command('build_ext')
+ build.run(self)
+
+swige = Extension("pyme._gpgme", ["gpgme.i", "helpers.c"],
+ swig_opts = ['-py3', '-builtin', '-threads',
+ '-outdir', 'pyme'] + extra_swig_opts,
+ include_dirs = include_dirs,
+ define_macros = define_macros,
+ library_dirs = library_dirs,
+ extra_link_args = libs)
+
+setup(name="pyme3",
+ cmdclass={'build': BuildExtFirstHack},
+ version="@VERSION@",
+ description='Python bindings for GPGME GnuPG cryptography library',
+ # XXX add a long description
+ #long_description=long_description,
+ author='The GnuPG hackers',
+ author_email='gnupg-devel@gnupg.org',
+ url='https://www.gnupg.org',
+ ext_modules=[swige],
+ packages = ['pyme', 'pyme.constants', 'pyme.constants.data',
+ 'pyme.constants.keylist', 'pyme.constants.sig'],
+ license="LGPL2.1+ (the library), GPL2+ (tests and examples)",
+ classifiers=[
+ 'Development Status :: 4 - Beta',
+ 'Intended Audience :: Developers',
+ 'License :: OSI Approved :: GNU Lesser General Public License v2 or later (LGPLv2+)',
+ 'Programming Language :: Python :: 2',
+ 'Programming Language :: Python :: 2.7',
+ 'Programming Language :: Python :: 3',
+ 'Programming Language :: Python :: 3.4',
+ 'Programming Language :: Python :: 3.5',
+ 'Programming Language :: Python :: 3.6',
+ 'Operating System :: POSIX',
+ 'Operating System :: Microsoft :: Windows',
+ 'Topic :: Communications :: Email',
+ 'Topic :: Security :: Cryptography',
+ ],
+)
diff --git a/lang/python/tests/Makefile.am b/lang/python/tests/Makefile.am
new file mode 100644
index 0000000..aa88bdc
--- /dev/null
+++ b/lang/python/tests/Makefile.am
@@ -0,0 +1,114 @@
+# Makefile.am for the tests of the Python bindings.
+# Copyright (C) 2016 g10 Code GmbH
+#
+# This file is part of GPGME.
+#
+# GPGME is free software; you can redistribute it and/or modify it
+# under the terms of the GNU General Public License as published by
+# the Free Software Foundation; either version 2 of the License, or
+# (at your option) any later version.
+#
+# GPGME is distributed in the hope that it will be useful, but WITHOUT
+# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
+# or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General
+# Public License for more details.
+#
+# You should have received a copy of the GNU Lesser General Public
+# License along with this program; if not, see <http://www.gnu.org/licenses/>.
+
+GPG = gpg
+GPG_AGENT = gpg-agent
+export GNUPGHOME := $(abs_builddir)
+export GPG_AGENT_INFO :=
+
+test_srcdir = $(top_srcdir)/tests/gpg
+
+TESTS_ENVIRONMENT = GNUPGHOME=$(abs_builddir) \
+ LC_ALL=C GPG_AGENT_INFO= \
+ top_srcdir=$(top_srcdir) \
+ srcdir=$(srcdir) \
+ LD_LIBRARY_PATH="../../../src/.libs:$(LD_LIBRARY_PATH)"
+
+py_tests = t-wrapper.py \
+ t-callbacks.py \
+ t-data.py \
+ t-encrypt.py \
+ t-encrypt-sym.py \
+ t-encrypt-sign.py \
+ t-sign.py \
+ t-signers.py \
+ t-decrypt.py \
+ t-verify.py \
+ t-decrypt-verify.py \
+ t-sig-notation.py \
+ t-export.py \
+ t-import.py \
+ t-trustlist.py \
+ t-edit.py \
+ t-keylist.py \
+ t-wait.py \
+ t-encrypt-large.py \
+ t-file-name.py \
+ t-idiomatic.py \
+ t-protocol-assuan.py
+
+XTESTS = initial.py $(py_tests) final.py
+EXTRA_DIST = support.py $(XTESTS) encrypt-only.asc sign-only.asc \
+ run-tests.py
+
+# XXX: Currently, one cannot override automake's 'check' target. As a
+# workaround, we avoid defining 'TESTS', thus automake will not emit
+# the 'check' target. For extra robustness, we merely define a
+# dependency on 'xcheck', so this hack should also work even if
+# automake would emit the 'check' target, as adding dependencies to
+# targets is okay.
+check: xcheck
+
+.PHONY: xcheck
+
+xcheck: ./pubring-stamp
+ $(TESTS_ENVIRONMENT) $(PYTHON) $(srcdir)/run-tests.py \
+ --interpreters="$(PYTHONS)" --srcdir=$(srcdir) $(TESTFLAGS) \
+ $(XTESTS)
+
+CLEANFILES = secring.gpg pubring.gpg pubring.kbx trustdb.gpg dirmngr.conf \
+ gpg-agent.conf pubring.kbx~ gpg.conf pubring.gpg~ \
+ random_seed .gpg-v21-migrated \
+ pubring-stamp private-keys-v1.d/gpg-sample.stamp
+
+private_keys = \
+ $(test_srcdir)/13CD0F3BDF24BE53FE192D62F18737256FF6E4FD \
+ $(test_srcdir)/76F7E2B35832976B50A27A282D9B87E44577EB66 \
+ $(test_srcdir)/A0747D5F9425E6664F4FFBEED20FBCA79FDED2BD \
+ $(test_srcdir)/13CBE3758AFE42B5E5E2AE4CED27AFA455E3F87F \
+ $(test_srcdir)/7A030357C0F253A5BBCD282FFC4E521B37558F5C
+
+clean-local:
+ -$(top_srcdir)/tests/start-stop-agent --stop
+ -rm -fR -- private-keys-v1.d openpgp-revocs.d S.gpg-agent sshcontrol
+
+
+./private-keys-v1.d/gpg-sample.stamp: $(private_keys)
+ test -d ./private-keys-v1.d || mkdir ./private-keys-v1.d
+ for k in $(private_keys); do \
+ cp $$k private-keys-v1.d/$${k#$(test_srcdir)/}.key; \
+ done
+ echo x > ./private-keys-v1.d/gpg-sample.stamp
+
+./pubring-stamp: $(test_srcdir)/pubdemo.asc \
+ ./gpg.conf ./gpg-agent.conf \
+ ./private-keys-v1.d/gpg-sample.stamp
+ $(GPG) --batch --no-permission-warning \
+ --import $(test_srcdir)/pubdemo.asc
+ -$(GPG) --batch --no-permission-warning \
+ --import $(test_srcdir)/secdemo.asc
+ echo x > ./pubring-stamp
+
+./gpg.conf:
+# This is required for t-sig-notations.
+ echo no-force-v3-sigs > ./gpg.conf
+
+./gpg-agent.conf:
+# This is required for gpg2, which does not support command fd.
+ echo pinentry-program $(abs_top_srcdir)/tests/gpg/pinentry >$@
+ echo allow-loopback-pinentry >>$@
diff --git a/lang/python/tests/Makefile.in b/lang/python/tests/Makefile.in
new file mode 100644
index 0000000..3886bf4
--- /dev/null
+++ b/lang/python/tests/Makefile.in
@@ -0,0 +1,620 @@
+# Makefile.in generated by automake 1.14.1 from Makefile.am.
+# @configure_input@
+
+# Copyright (C) 1994-2013 Free Software Foundation, Inc.
+
+# This Makefile.in is free software; the Free Software Foundation
+# gives unlimited permission to copy and/or distribute it,
+# with or without modifications, as long as this notice is preserved.
+
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY, to the extent permitted by law; without
+# even the implied warranty of MERCHANTABILITY or FITNESS FOR A
+# PARTICULAR PURPOSE.
+
+@SET_MAKE@
+
+# Makefile.am for the tests of the Python bindings.
+# Copyright (C) 2016 g10 Code GmbH
+#
+# This file is part of GPGME.
+#
+# GPGME is free software; you can redistribute it and/or modify it
+# under the terms of the GNU General Public License as published by
+# the Free Software Foundation; either version 2 of the License, or
+# (at your option) any later version.
+#
+# GPGME is distributed in the hope that it will be useful, but WITHOUT
+# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
+# or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General
+# Public License for more details.
+#
+# You should have received a copy of the GNU Lesser General Public
+# License along with this program; if not, see <http://www.gnu.org/licenses/>.
+VPATH = @srcdir@
+am__is_gnu_make = test -n '$(MAKEFILE_LIST)' && test -n '$(MAKELEVEL)'
+am__make_running_with_option = \
+ case $${target_option-} in \
+ ?) ;; \
+ *) echo "am__make_running_with_option: internal error: invalid" \
+ "target option '$${target_option-}' specified" >&2; \
+ exit 1;; \
+ esac; \
+ has_opt=no; \
+ sane_makeflags=$$MAKEFLAGS; \
+ if $(am__is_gnu_make); then \
+ sane_makeflags=$$MFLAGS; \
+ else \
+ case $$MAKEFLAGS in \
+ *\\[\ \ ]*) \
+ bs=\\; \
+ sane_makeflags=`printf '%s\n' "$$MAKEFLAGS" \
+ | sed "s/$$bs$$bs[$$bs $$bs ]*//g"`;; \
+ esac; \
+ fi; \
+ skip_next=no; \
+ strip_trailopt () \
+ { \
+ flg=`printf '%s\n' "$$flg" | sed "s/$$1.*$$//"`; \
+ }; \
+ for flg in $$sane_makeflags; do \
+ test $$skip_next = yes && { skip_next=no; continue; }; \
+ case $$flg in \
+ *=*|--*) continue;; \
+ -*I) strip_trailopt 'I'; skip_next=yes;; \
+ -*I?*) strip_trailopt 'I';; \
+ -*O) strip_trailopt 'O'; skip_next=yes;; \
+ -*O?*) strip_trailopt 'O';; \
+ -*l) strip_trailopt 'l'; skip_next=yes;; \
+ -*l?*) strip_trailopt 'l';; \
+ -[dEDm]) skip_next=yes;; \
+ -[JT]) skip_next=yes;; \
+ esac; \
+ case $$flg in \
+ *$$target_option*) has_opt=yes; break;; \
+ esac; \
+ done; \
+ test $$has_opt = yes
+am__make_dryrun = (target_option=n; $(am__make_running_with_option))
+am__make_keepgoing = (target_option=k; $(am__make_running_with_option))
+pkgdatadir = $(datadir)/@PACKAGE@
+pkgincludedir = $(includedir)/@PACKAGE@
+pkglibdir = $(libdir)/@PACKAGE@
+pkglibexecdir = $(libexecdir)/@PACKAGE@
+am__cd = CDPATH="$${ZSH_VERSION+.}$(PATH_SEPARATOR)" && cd
+install_sh_DATA = $(install_sh) -c -m 644
+install_sh_PROGRAM = $(install_sh) -c
+install_sh_SCRIPT = $(install_sh) -c
+INSTALL_HEADER = $(INSTALL_DATA)
+transform = $(program_transform_name)
+NORMAL_INSTALL = :
+PRE_INSTALL = :
+POST_INSTALL = :
+NORMAL_UNINSTALL = :
+PRE_UNINSTALL = :
+POST_UNINSTALL = :
+build_triplet = @build@
+host_triplet = @host@
+subdir = lang/python/tests
+DIST_COMMON = $(srcdir)/Makefile.in $(srcdir)/Makefile.am \
+ $(top_srcdir)/build-aux/mkinstalldirs
+ACLOCAL_M4 = $(top_srcdir)/aclocal.m4
+am__aclocal_m4_deps = $(top_srcdir)/m4/ax_cxx_compile_stdcxx.m4 \
+ $(top_srcdir)/m4/ax_pkg_swig.m4 \
+ $(top_srcdir)/m4/ax_python_devel.m4 \
+ $(top_srcdir)/m4/glib-2.0.m4 $(top_srcdir)/m4/glibc21.m4 \
+ $(top_srcdir)/m4/gnupg-ttyname.m4 \
+ $(top_srcdir)/m4/gpg-error.m4 $(top_srcdir)/m4/libassuan.m4 \
+ $(top_srcdir)/m4/libtool.m4 $(top_srcdir)/m4/ltoptions.m4 \
+ $(top_srcdir)/m4/ltsugar.m4 $(top_srcdir)/m4/ltversion.m4 \
+ $(top_srcdir)/m4/lt~obsolete.m4 $(top_srcdir)/m4/pkg.m4 \
+ $(top_srcdir)/m4/qt.m4 $(top_srcdir)/acinclude.m4 \
+ $(top_srcdir)/configure.ac
+am__configure_deps = $(am__aclocal_m4_deps) $(CONFIGURE_DEPENDENCIES) \
+ $(ACLOCAL_M4)
+mkinstalldirs = $(SHELL) $(top_srcdir)/build-aux/mkinstalldirs
+CONFIG_HEADER = $(top_builddir)/config.h
+CONFIG_CLEAN_FILES =
+CONFIG_CLEAN_VPATH_FILES =
+AM_V_P = $(am__v_P_@AM_V@)
+am__v_P_ = $(am__v_P_@AM_DEFAULT_V@)
+am__v_P_0 = false
+am__v_P_1 = :
+AM_V_GEN = $(am__v_GEN_@AM_V@)
+am__v_GEN_ = $(am__v_GEN_@AM_DEFAULT_V@)
+am__v_GEN_0 = @echo " GEN " $@;
+am__v_GEN_1 =
+AM_V_at = $(am__v_at_@AM_V@)
+am__v_at_ = $(am__v_at_@AM_DEFAULT_V@)
+am__v_at_0 = @
+am__v_at_1 =
+SOURCES =
+DIST_SOURCES =
+am__can_run_installinfo = \
+ case $$AM_UPDATE_INFO_DIR in \
+ n|no|NO) false;; \
+ *) (install-info --version) >/dev/null 2>&1;; \
+ esac
+am__tagged_files = $(HEADERS) $(SOURCES) $(TAGS_FILES) $(LISP)
+DISTFILES = $(DIST_COMMON) $(DIST_SOURCES) $(TEXINFOS) $(EXTRA_DIST)
+ACLOCAL = @ACLOCAL@
+AMTAR = @AMTAR@
+AM_DEFAULT_VERBOSITY = @AM_DEFAULT_VERBOSITY@
+AR = @AR@
+AS = @AS@
+AUTOCONF = @AUTOCONF@
+AUTOHEADER = @AUTOHEADER@
+AUTOMAKE = @AUTOMAKE@
+AWK = @AWK@
+BUILD_FILEVERSION = @BUILD_FILEVERSION@
+BUILD_REVISION = @BUILD_REVISION@
+BUILD_TIMESTAMP = @BUILD_TIMESTAMP@
+CC = @CC@
+CCDEPMODE = @CCDEPMODE@
+CC_FOR_BUILD = @CC_FOR_BUILD@
+CFLAGS = @CFLAGS@
+CPP = @CPP@
+CPPFLAGS = @CPPFLAGS@
+CXX = @CXX@
+CXXCPP = @CXXCPP@
+CXXDEPMODE = @CXXDEPMODE@
+CXXFLAGS = @CXXFLAGS@
+CYGPATH_W = @CYGPATH_W@
+DEFS = @DEFS@
+DEPDIR = @DEPDIR@
+DLLTOOL = @DLLTOOL@
+DOXYGEN = @DOXYGEN@
+DSYMUTIL = @DSYMUTIL@
+DUMPBIN = @DUMPBIN@
+ECHO_C = @ECHO_C@
+ECHO_N = @ECHO_N@
+ECHO_T = @ECHO_T@
+EGREP = @EGREP@
+ENABLED_LANGUAGES = @ENABLED_LANGUAGES@
+EXEEXT = @EXEEXT@
+FGREP = @FGREP@
+GITLOG_TO_CHANGELOG = @GITLOG_TO_CHANGELOG@
+GLIBC21 = @GLIBC21@
+GLIB_CFLAGS = @GLIB_CFLAGS@
+GLIB_GENMARSHAL = @GLIB_GENMARSHAL@
+GLIB_LIBS = @GLIB_LIBS@
+GLIB_MKENUMS = @GLIB_MKENUMS@
+GOBJECT_QUERY = @GOBJECT_QUERY@
+GPGME_CONFIG_API_VERSION = @GPGME_CONFIG_API_VERSION@
+GPGME_CONFIG_AVAIL_LANG = @GPGME_CONFIG_AVAIL_LANG@
+GPGME_CONFIG_CFLAGS = @GPGME_CONFIG_CFLAGS@
+GPGME_CONFIG_HOST = @GPGME_CONFIG_HOST@
+GPGME_CONFIG_LIBS = @GPGME_CONFIG_LIBS@
+GPGME_QTTEST_CFLAGS = @GPGME_QTTEST_CFLAGS@
+GPGME_QTTEST_LIBS = @GPGME_QTTEST_LIBS@
+GPGME_QT_CFLAGS = @GPGME_QT_CFLAGS@
+GPGME_QT_LIBS = @GPGME_QT_LIBS@
+GPG_ERROR_CFLAGS = @GPG_ERROR_CFLAGS@
+GPG_ERROR_CONFIG = @GPG_ERROR_CONFIG@
+GPG_ERROR_LIBS = @GPG_ERROR_LIBS@
+GPG_ERROR_MT_CFLAGS = @GPG_ERROR_MT_CFLAGS@
+GPG_ERROR_MT_LIBS = @GPG_ERROR_MT_LIBS@
+GRAPHVIZ = @GRAPHVIZ@
+GREP = @GREP@
+HAVE_CXX11 = @HAVE_CXX11@
+HAVE_DOT = @HAVE_DOT@
+INSTALL = @INSTALL@
+INSTALL_DATA = @INSTALL_DATA@
+INSTALL_PROGRAM = @INSTALL_PROGRAM@
+INSTALL_SCRIPT = @INSTALL_SCRIPT@
+INSTALL_STRIP_PROGRAM = @INSTALL_STRIP_PROGRAM@
+LD = @LD@
+LDFLAGS = @LDFLAGS@
+LIBASSUAN_CFLAGS = @LIBASSUAN_CFLAGS@
+LIBASSUAN_CONFIG = @LIBASSUAN_CONFIG@
+LIBASSUAN_LIBS = @LIBASSUAN_LIBS@
+LIBGPGMEPP_LT_AGE = @LIBGPGMEPP_LT_AGE@
+LIBGPGMEPP_LT_CURRENT = @LIBGPGMEPP_LT_CURRENT@
+LIBGPGMEPP_LT_REVISION = @LIBGPGMEPP_LT_REVISION@
+LIBGPGME_LT_AGE = @LIBGPGME_LT_AGE@
+LIBGPGME_LT_CURRENT = @LIBGPGME_LT_CURRENT@
+LIBGPGME_LT_REVISION = @LIBGPGME_LT_REVISION@
+LIBOBJS = @LIBOBJS@
+LIBQGPGME_LT_AGE = @LIBQGPGME_LT_AGE@
+LIBQGPGME_LT_CURRENT = @LIBQGPGME_LT_CURRENT@
+LIBQGPGME_LT_REVISION = @LIBQGPGME_LT_REVISION@
+LIBS = @LIBS@
+LIBTOOL = @LIBTOOL@
+LIPO = @LIPO@
+LN_S = @LN_S@
+LTLIBOBJS = @LTLIBOBJS@
+MAINT = @MAINT@
+MAKEINFO = @MAKEINFO@
+MANIFEST_TOOL = @MANIFEST_TOOL@
+MKDIR_P = @MKDIR_P@
+MOC = @MOC@
+MOC2 = @MOC2@
+NEED__FILE_OFFSET_BITS = @NEED__FILE_OFFSET_BITS@
+NM = @NM@
+NMEDIT = @NMEDIT@
+OBJDUMP = @OBJDUMP@
+OBJEXT = @OBJEXT@
+OTOOL = @OTOOL@
+OTOOL64 = @OTOOL64@
+PACKAGE = @PACKAGE@
+PACKAGE_BUGREPORT = @PACKAGE_BUGREPORT@
+PACKAGE_NAME = @PACKAGE_NAME@
+PACKAGE_STRING = @PACKAGE_STRING@
+PACKAGE_TARNAME = @PACKAGE_TARNAME@
+PACKAGE_URL = @PACKAGE_URL@
+PACKAGE_VERSION = @PACKAGE_VERSION@
+PATH_SEPARATOR = @PATH_SEPARATOR@
+PKG_CONFIG = @PKG_CONFIG@
+PYTHON = @PYTHON@
+PYTHONS = @PYTHONS@
+PYTHON_CPPFLAGS = @PYTHON_CPPFLAGS@
+PYTHON_EXEC_PREFIX = @PYTHON_EXEC_PREFIX@
+PYTHON_EXTRA_LDFLAGS = @PYTHON_EXTRA_LDFLAGS@
+PYTHON_EXTRA_LIBS = @PYTHON_EXTRA_LIBS@
+PYTHON_LDFLAGS = @PYTHON_LDFLAGS@
+PYTHON_PLATFORM = @PYTHON_PLATFORM@
+PYTHON_PREFIX = @PYTHON_PREFIX@
+PYTHON_SITE_PKG = @PYTHON_SITE_PKG@
+PYTHON_VERSION = @PYTHON_VERSION@
+PYTHON_VERSIONS = @PYTHON_VERSIONS@
+QTCHOOSER = @QTCHOOSER@
+RANLIB = @RANLIB@
+RC = @RC@
+SED = @SED@
+SET_MAKE = @SET_MAKE@
+SHELL = @SHELL@
+STRIP = @STRIP@
+SWIG = @SWIG@
+SWIG_LIB = @SWIG_LIB@
+SYSROOT = @SYSROOT@
+VERSION = @VERSION@
+VERSION_NUMBER = @VERSION_NUMBER@
+abs_builddir = @abs_builddir@
+abs_srcdir = @abs_srcdir@
+abs_top_builddir = @abs_top_builddir@
+abs_top_srcdir = @abs_top_srcdir@
+ac_ct_AR = @ac_ct_AR@
+ac_ct_CC = @ac_ct_CC@
+ac_ct_CXX = @ac_ct_CXX@
+ac_ct_DUMPBIN = @ac_ct_DUMPBIN@
+am__include = @am__include@
+am__leading_dot = @am__leading_dot@
+am__quote = @am__quote@
+am__tar = @am__tar@
+am__untar = @am__untar@
+bindir = @bindir@
+build = @build@
+build_alias = @build_alias@
+build_cpu = @build_cpu@
+build_os = @build_os@
+build_vendor = @build_vendor@
+builddir = @builddir@
+datadir = @datadir@
+datarootdir = @datarootdir@
+docdir = @docdir@
+dvidir = @dvidir@
+emacs_local_vars_begin = @emacs_local_vars_begin@
+emacs_local_vars_end = @emacs_local_vars_end@
+emacs_local_vars_read_only = @emacs_local_vars_read_only@
+exec_prefix = @exec_prefix@
+host = @host@
+host_alias = @host_alias@
+host_cpu = @host_cpu@
+host_os = @host_os@
+host_vendor = @host_vendor@
+htmldir = @htmldir@
+includedir = @includedir@
+infodir = @infodir@
+install_sh = @install_sh@
+libdir = @libdir@
+libexecdir = @libexecdir@
+localedir = @localedir@
+localstatedir = @localstatedir@
+mandir = @mandir@
+mkdir_p = @mkdir_p@
+oldincludedir = @oldincludedir@
+pdfdir = @pdfdir@
+pkgpyexecdir = @pkgpyexecdir@
+pkgpythondir = @pkgpythondir@
+prefix = @prefix@
+program_transform_name = @program_transform_name@
+psdir = @psdir@
+pyexecdir = @pyexecdir@
+pythondir = @pythondir@
+sbindir = @sbindir@
+sharedstatedir = @sharedstatedir@
+srcdir = @srcdir@
+sysconfdir = @sysconfdir@
+target_alias = @target_alias@
+top_build_prefix = @top_build_prefix@
+top_builddir = @top_builddir@
+top_srcdir = @top_srcdir@
+GPG = gpg
+GPG_AGENT = gpg-agent
+test_srcdir = $(top_srcdir)/tests/gpg
+TESTS_ENVIRONMENT = GNUPGHOME=$(abs_builddir) \
+ LC_ALL=C GPG_AGENT_INFO= \
+ top_srcdir=$(top_srcdir) \
+ srcdir=$(srcdir) \
+ LD_LIBRARY_PATH="../../../src/.libs:$(LD_LIBRARY_PATH)"
+
+py_tests = t-wrapper.py \
+ t-callbacks.py \
+ t-data.py \
+ t-encrypt.py \
+ t-encrypt-sym.py \
+ t-encrypt-sign.py \
+ t-sign.py \
+ t-signers.py \
+ t-decrypt.py \
+ t-verify.py \
+ t-decrypt-verify.py \
+ t-sig-notation.py \
+ t-export.py \
+ t-import.py \
+ t-trustlist.py \
+ t-edit.py \
+ t-keylist.py \
+ t-wait.py \
+ t-encrypt-large.py \
+ t-file-name.py \
+ t-idiomatic.py \
+ t-protocol-assuan.py
+
+XTESTS = initial.py $(py_tests) final.py
+EXTRA_DIST = support.py $(XTESTS) encrypt-only.asc sign-only.asc \
+ run-tests.py
+
+CLEANFILES = secring.gpg pubring.gpg pubring.kbx trustdb.gpg dirmngr.conf \
+ gpg-agent.conf pubring.kbx~ gpg.conf pubring.gpg~ \
+ random_seed .gpg-v21-migrated \
+ pubring-stamp private-keys-v1.d/gpg-sample.stamp
+
+private_keys = \
+ $(test_srcdir)/13CD0F3BDF24BE53FE192D62F18737256FF6E4FD \
+ $(test_srcdir)/76F7E2B35832976B50A27A282D9B87E44577EB66 \
+ $(test_srcdir)/A0747D5F9425E6664F4FFBEED20FBCA79FDED2BD \
+ $(test_srcdir)/13CBE3758AFE42B5E5E2AE4CED27AFA455E3F87F \
+ $(test_srcdir)/7A030357C0F253A5BBCD282FFC4E521B37558F5C
+
+all: all-am
+
+.SUFFIXES:
+$(srcdir)/Makefile.in: @MAINTAINER_MODE_TRUE@ $(srcdir)/Makefile.am $(am__configure_deps)
+ @for dep in $?; do \
+ case '$(am__configure_deps)' in \
+ *$$dep*) \
+ ( cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh ) \
+ && { if test -f $@; then exit 0; else break; fi; }; \
+ exit 1;; \
+ esac; \
+ done; \
+ echo ' cd $(top_srcdir) && $(AUTOMAKE) --gnu lang/python/tests/Makefile'; \
+ $(am__cd) $(top_srcdir) && \
+ $(AUTOMAKE) --gnu lang/python/tests/Makefile
+.PRECIOUS: Makefile
+Makefile: $(srcdir)/Makefile.in $(top_builddir)/config.status
+ @case '$?' in \
+ *config.status*) \
+ cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh;; \
+ *) \
+ echo ' cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__depfiles_maybe)'; \
+ cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__depfiles_maybe);; \
+ esac;
+
+$(top_builddir)/config.status: $(top_srcdir)/configure $(CONFIG_STATUS_DEPENDENCIES)
+ cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh
+
+$(top_srcdir)/configure: @MAINTAINER_MODE_TRUE@ $(am__configure_deps)
+ cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh
+$(ACLOCAL_M4): @MAINTAINER_MODE_TRUE@ $(am__aclocal_m4_deps)
+ cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh
+$(am__aclocal_m4_deps):
+
+mostlyclean-libtool:
+ -rm -f *.lo
+
+clean-libtool:
+ -rm -rf .libs _libs
+tags TAGS:
+
+ctags CTAGS:
+
+cscope cscopelist:
+
+
+distdir: $(DISTFILES)
+ @srcdirstrip=`echo "$(srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \
+ topsrcdirstrip=`echo "$(top_srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \
+ list='$(DISTFILES)'; \
+ dist_files=`for file in $$list; do echo $$file; done | \
+ sed -e "s|^$$srcdirstrip/||;t" \
+ -e "s|^$$topsrcdirstrip/|$(top_builddir)/|;t"`; \
+ case $$dist_files in \
+ */*) $(MKDIR_P) `echo "$$dist_files" | \
+ sed '/\//!d;s|^|$(distdir)/|;s,/[^/]*$$,,' | \
+ sort -u` ;; \
+ esac; \
+ for file in $$dist_files; do \
+ if test -f $$file || test -d $$file; then d=.; else d=$(srcdir); fi; \
+ if test -d $$d/$$file; then \
+ dir=`echo "/$$file" | sed -e 's,/[^/]*$$,,'`; \
+ if test -d "$(distdir)/$$file"; then \
+ find "$(distdir)/$$file" -type d ! -perm -700 -exec chmod u+rwx {} \;; \
+ fi; \
+ if test -d $(srcdir)/$$file && test $$d != $(srcdir); then \
+ cp -fpR $(srcdir)/$$file "$(distdir)$$dir" || exit 1; \
+ find "$(distdir)/$$file" -type d ! -perm -700 -exec chmod u+rwx {} \;; \
+ fi; \
+ cp -fpR $$d/$$file "$(distdir)$$dir" || exit 1; \
+ else \
+ test -f "$(distdir)/$$file" \
+ || cp -p $$d/$$file "$(distdir)/$$file" \
+ || exit 1; \
+ fi; \
+ done
+check-am: all-am
+check: check-am
+all-am: Makefile
+installdirs:
+install: install-am
+install-exec: install-exec-am
+install-data: install-data-am
+uninstall: uninstall-am
+
+install-am: all-am
+ @$(MAKE) $(AM_MAKEFLAGS) install-exec-am install-data-am
+
+installcheck: installcheck-am
+install-strip:
+ if test -z '$(STRIP)'; then \
+ $(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \
+ install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \
+ install; \
+ else \
+ $(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \
+ install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \
+ "INSTALL_PROGRAM_ENV=STRIPPROG='$(STRIP)'" install; \
+ fi
+mostlyclean-generic:
+
+clean-generic:
+ -test -z "$(CLEANFILES)" || rm -f $(CLEANFILES)
+
+distclean-generic:
+ -test -z "$(CONFIG_CLEAN_FILES)" || rm -f $(CONFIG_CLEAN_FILES)
+ -test . = "$(srcdir)" || test -z "$(CONFIG_CLEAN_VPATH_FILES)" || rm -f $(CONFIG_CLEAN_VPATH_FILES)
+
+maintainer-clean-generic:
+ @echo "This command is intended for maintainers to use"
+ @echo "it deletes files that may require special tools to rebuild."
+clean: clean-am
+
+clean-am: clean-generic clean-libtool clean-local mostlyclean-am
+
+distclean: distclean-am
+ -rm -f Makefile
+distclean-am: clean-am distclean-generic
+
+dvi: dvi-am
+
+dvi-am:
+
+html: html-am
+
+html-am:
+
+info: info-am
+
+info-am:
+
+install-data-am:
+
+install-dvi: install-dvi-am
+
+install-dvi-am:
+
+install-exec-am:
+
+install-html: install-html-am
+
+install-html-am:
+
+install-info: install-info-am
+
+install-info-am:
+
+install-man:
+
+install-pdf: install-pdf-am
+
+install-pdf-am:
+
+install-ps: install-ps-am
+
+install-ps-am:
+
+installcheck-am:
+
+maintainer-clean: maintainer-clean-am
+ -rm -f Makefile
+maintainer-clean-am: distclean-am maintainer-clean-generic
+
+mostlyclean: mostlyclean-am
+
+mostlyclean-am: mostlyclean-generic mostlyclean-libtool
+
+pdf: pdf-am
+
+pdf-am:
+
+ps: ps-am
+
+ps-am:
+
+uninstall-am:
+
+.MAKE: install-am install-strip
+
+.PHONY: all all-am check check-am clean clean-generic clean-libtool \
+ clean-local cscopelist-am ctags-am distclean distclean-generic \
+ distclean-libtool distdir dvi dvi-am html html-am info info-am \
+ install install-am install-data install-data-am install-dvi \
+ install-dvi-am install-exec install-exec-am install-html \
+ install-html-am install-info install-info-am install-man \
+ install-pdf install-pdf-am install-ps install-ps-am \
+ install-strip installcheck installcheck-am installdirs \
+ maintainer-clean maintainer-clean-generic mostlyclean \
+ mostlyclean-generic mostlyclean-libtool pdf pdf-am ps ps-am \
+ tags-am uninstall uninstall-am
+
+export GNUPGHOME := $(abs_builddir)
+export GPG_AGENT_INFO :=
+
+# XXX: Currently, one cannot override automake's 'check' target. As a
+# workaround, we avoid defining 'TESTS', thus automake will not emit
+# the 'check' target. For extra robustness, we merely define a
+# dependency on 'xcheck', so this hack should also work even if
+# automake would emit the 'check' target, as adding dependencies to
+# targets is okay.
+check: xcheck
+
+.PHONY: xcheck
+
+xcheck: ./pubring-stamp
+ $(TESTS_ENVIRONMENT) $(PYTHON) $(srcdir)/run-tests.py \
+ --interpreters="$(PYTHONS)" --srcdir=$(srcdir) $(TESTFLAGS) \
+ $(XTESTS)
+
+clean-local:
+ -$(top_srcdir)/tests/start-stop-agent --stop
+ -rm -fR -- private-keys-v1.d openpgp-revocs.d S.gpg-agent sshcontrol
+
+./private-keys-v1.d/gpg-sample.stamp: $(private_keys)
+ test -d ./private-keys-v1.d || mkdir ./private-keys-v1.d
+ for k in $(private_keys); do \
+ cp $$k private-keys-v1.d/$${k#$(test_srcdir)/}.key; \
+ done
+ echo x > ./private-keys-v1.d/gpg-sample.stamp
+
+./pubring-stamp: $(test_srcdir)/pubdemo.asc \
+ ./gpg.conf ./gpg-agent.conf \
+ ./private-keys-v1.d/gpg-sample.stamp
+ $(GPG) --batch --no-permission-warning \
+ --import $(test_srcdir)/pubdemo.asc
+ -$(GPG) --batch --no-permission-warning \
+ --import $(test_srcdir)/secdemo.asc
+ echo x > ./pubring-stamp
+
+./gpg.conf:
+# This is required for t-sig-notations.
+ echo no-force-v3-sigs > ./gpg.conf
+
+./gpg-agent.conf:
+# This is required for gpg2, which does not support command fd.
+ echo pinentry-program $(abs_top_srcdir)/tests/gpg/pinentry >$@
+ echo allow-loopback-pinentry >>$@
+
+# Tell versions [3.59,3.63) of GNU make to not export all variables.
+# Otherwise a system limit (for SysV at least) may be exceeded.
+.NOEXPORT:
diff --git a/lang/python/tests/encrypt-only.asc b/lang/python/tests/encrypt-only.asc
new file mode 100644
index 0000000..6e068a0
--- /dev/null
+++ b/lang/python/tests/encrypt-only.asc
@@ -0,0 +1,33 @@
+-----BEGIN PGP PRIVATE KEY BLOCK-----
+Version: GnuPG v2
+
+lQPGBFd/jL0BCAD8jfoblIrlHS0shDCbSiO7RFaT6sEa/6tSPkv6XzBba9oXOkuO
+FLTkNpIwPb92U8SOS+27j7n9v6U5NW2tyZwIoeLb8lUyKnCBr22IUhTFVXf7fros
+zmPugsJaDBi9f7RL0bqiCn4EV3DGKyAukZklk1k1JV4Ec3dEPMAmL9LmnvXreEjU
+pQZZN9sJV32ew8CYkZ6AB8foFQwfxn4x0iUoKvj8kW9RsY1KMPucp4YiFhHeMZW1
+5wGAZdEIZYKyWEp4bi/wC9yn/TUR5uNWc0uVJzQvuHwaYjolPW89DinjBkPEJCBr
+RwumaOWfbu/hb51wBoUTmUr9diVw93L2ROLPABEBAAH+BwMC1bmUAoPJKI/WBiHm
+P6tSNRLdd+7etfjAFvKL7Ob2pNTrc3hbtyOLIQ9tuEaqXEyfnCms/DCg8QdkaFUv
+Nkoj0W5+G/MQuR2jIvrq/wyL/4jIw0AFbp9/V1JbSXZh2g1eJLnnykn7uPxCbDFY
+FrVeFmkhoxZ3pid6ZQSWlxXsdW+YMvbUfNIIZpbygI/alIBvbDS1YJYEBDCwFZjU
+7quE2Ufxo8dm34EHcmbpYpn4r3DUrU5AHQ2fIprLIVqHn4+NUrR8WZS9nCnIeu/z
+OaJUZ2lJFRjUC6Gpsbsw6Xwh4Ntwzyt2SsXc+UVZngjozw3yw0VpDifxMBqcd+9x
+baSc7dfbOZF2BCZOwnB7/QrFZDaqe5b3n6rTdj1va/CrJMuxbgaNAjvLpdT2EUPZ
+fHDAdPAjASofxBREv+HIKwksuPJ9cvavZU6Q4KQA7buo25hd7yjuba4WbLQhp0jH
+AT1P7SdakMhk/IFcUKFdB3ZyZZZ1JTTPa2xZn9yDa3Jb1t7IMLYLwY6EFbjvaxH5
+WEGZvOAq2iEa941mxv4miwgf7MQPx6g9u0+dXc7iZApwWs9MNfJo3J25sKhWK5Be
+Bu3w7c6nrlg40GtPuDRgaBvYWbVerJcepTA/EPfugEJtRsDJkt7wZq1H9lWHU7Ih
+Up6/+XKtBzlCIqYjorzFLnC721pcKFcPhLgvtjjNJvUsLXbr9CwnBub/eTFcfRb2
+ro60H9cOhf0fQSQyvkZWfzq0BN6rG27G1KhyprsJAmpW0fTHHkB4V19788C2sTQv
+D93VU3Nd6MWocwAYtPWmtwXPpuOAU9IcwAvVTxBeBJCXxbH3uyx1frwDXA7lf4Pb
+a8hMoMMVU+rAG1uepKI5h4seBIKP7qKEKAPloI6/Vtf7/Ump4DKprS1QpfOW+lsX
+aR48lgNR6sQXtDdFbmNyeXB0aW9uIE9ubHkgKHRlc3Qga2V5LCBkbyBub3QgdXNl
+KSA8ZW9AZXhhbXBsZS5vcmc+iQE3BBMBCAAhBQJXf4y9AhsNBQsJCAcCBhUICQoL
+AgQWAgMBAh4BAheAAAoJEJIFcnabn+Gc/KgH/07wzrsBzTqdI5L6cIqQ81Vq8ASj
+tsuYoVfFxymB8F/AxpnLMhYRuWQTcoUHQ/olG2yA0C6o4e1JPAmh6LQGwr0eRnc2
+2tr4cbnQAhXpJ8xOR6kH9eE8nGeC7tlEeeV/Wnj3SLZOXOjYjnA9bA3JX9DP3qcz
+w1sKQPEHsGkMJuT0ZadnlJ1qw8AnnNKLDlG4kIO9hz3qB8BjxFZf+j5f/nhFNv5I
+pnNdMcDwQqHVrwD6WO+Xmmdykab0awL9To0S9DG9ohcXuJiTMa8vtXFSBM0koUDk
+BWajEq+QAcDpmdFsQr4/gbzvHkAIVTQb0seJr4gpmXFZu3TMuGVD9j13GaI=
+=38ri
+-----END PGP PRIVATE KEY BLOCK-----
diff --git a/lang/python/tests/final.py b/lang/python/tests/final.py
new file mode 100755
index 0000000..8e7ab33
--- /dev/null
+++ b/lang/python/tests/final.py
@@ -0,0 +1,27 @@
+#!/usr/bin/env python
+
+# Copyright (C) 2016 g10 Code GmbH
+#
+# This file is part of GPGME.
+#
+# GPGME is free software; you can redistribute it and/or modify it
+# under the terms of the GNU General Public License as published by
+# the Free Software Foundation; either version 2 of the License, or
+# (at your option) any later version.
+#
+# GPGME is distributed in the hope that it will be useful, but WITHOUT
+# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
+# or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General
+# Public License for more details.
+#
+# You should have received a copy of the GNU Lesser General Public
+# License along with this program; if not, see <http://www.gnu.org/licenses/>.
+
+from __future__ import absolute_import, print_function, unicode_literals
+del absolute_import, print_function, unicode_literals
+
+import os
+import subprocess
+
+subprocess.check_call([os.path.join(os.getenv('top_srcdir'),
+ "tests", "start-stop-agent"), "--stop"])
diff --git a/lang/python/tests/initial.py b/lang/python/tests/initial.py
new file mode 100755
index 0000000..2d4827a
--- /dev/null
+++ b/lang/python/tests/initial.py
@@ -0,0 +1,41 @@
+#!/usr/bin/env python
+
+# Copyright (C) 2016 g10 Code GmbH
+#
+# This file is part of GPGME.
+#
+# GPGME is free software; you can redistribute it and/or modify it
+# under the terms of the GNU General Public License as published by
+# the Free Software Foundation; either version 2 of the License, or
+# (at your option) any later version.
+#
+# GPGME is distributed in the hope that it will be useful, but WITHOUT
+# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
+# or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General
+# Public License for more details.
+#
+# You should have received a copy of the GNU Lesser General Public
+# License along with this program; if not, see <http://www.gnu.org/licenses/>.
+
+from __future__ import absolute_import, print_function, unicode_literals
+del absolute_import, print_function, unicode_literals
+
+import os
+import subprocess
+import pyme
+import support
+support.init_gpgme(pyme.constants.PROTOCOL_OpenPGP)
+
+subprocess.check_call([os.path.join(os.getenv('top_srcdir'),
+ "tests", "start-stop-agent"), "--start"])
+
+with pyme.Context() as c:
+ alpha = c.get_key("A0FF4590BB6122EDEF6E3C542D727CC768697734", False)
+ bob = c.get_key("D695676BDCEDCC2CDD6152BCFE180B1DA9E3B0B2", False)
+
+ # Mark alpha as trusted. The signature verification tests expect
+ # this.
+ support.mark_key_trusted(c, alpha)
+
+ c.op_import(open(support.in_srcdir("encrypt-only.asc")))
+ c.op_import(open(support.in_srcdir("sign-only.asc")))
diff --git a/lang/python/tests/run-tests.py b/lang/python/tests/run-tests.py
new file mode 100644
index 0000000..55d3f11
--- /dev/null
+++ b/lang/python/tests/run-tests.py
@@ -0,0 +1,90 @@
+#!/usr/bin/env python
+
+# Copyright (C) 2016 g10 Code GmbH
+#
+# This file is part of GPGME.
+#
+# GPGME is free software; you can redistribute it and/or modify it
+# under the terms of the GNU General Public License as published by
+# the Free Software Foundation; either version 2 of the License, or
+# (at your option) any later version.
+#
+# GPGME is distributed in the hope that it will be useful, but WITHOUT
+# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
+# or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General
+# Public License for more details.
+#
+# You should have received a copy of the GNU Lesser General Public
+# License along with this program; if not, see <http://www.gnu.org/licenses/>.
+
+from __future__ import absolute_import
+from __future__ import division
+from __future__ import print_function
+from __future__ import unicode_literals
+
+import argparse
+import glob
+import os
+import subprocess
+import sys
+
+class SplitAndAccumulate(argparse.Action):
+ def __call__(self, parser, namespace, values, option_string=None):
+ current = getattr(namespace, self.dest, list())
+ current.extend(values.split())
+ setattr(namespace, self.dest, current)
+
+parser = argparse.ArgumentParser(description='Run tests.')
+parser.add_argument('tests', metavar='TEST', type=str, nargs='+',
+ help='A test to run')
+parser.add_argument('-v', '--verbose', action="store_true", default=False,
+ help='Be verbose.')
+parser.add_argument('--interpreters', metavar='PYTHON', type=str,
+ default=[], action=SplitAndAccumulate,
+ help='Use these interpreters to run the tests, ' +
+ 'separated by spaces.')
+parser.add_argument('--srcdir', type=str,
+ default=os.environ.get("srcdir", ""),
+ help='Location of the tests.')
+parser.add_argument('--builddir', type=str,
+ default=os.environ.get("abs_builddir", ""),
+ help='Location of the tests.')
+
+args = parser.parse_args()
+if not args.interpreters:
+ args.interpreters = [sys.executable]
+
+out = sys.stdout if args.verbose else None
+err = sys.stderr if args.verbose else None
+
+def status_to_str(code):
+ return {0: "PASS", 77: "SKIP", 99: "ERROR"}.get(code, "FAIL")
+
+results = list()
+for interpreter in args.interpreters:
+ version = subprocess.check_output(
+ [interpreter, "-c", "import sys; print('{0}.{1}'.format(sys.version_info[0], sys.version_info[1]))"]).strip().decode()
+
+ builddirs = glob.glob(os.path.join(args.builddir, "..", "build",
+ "lib*"+version))
+ assert len(builddirs) == 1, \
+ "Expected one build directory, got {0}".format(builddirs)
+ env = dict(os.environ)
+ env["PYTHONPATH"] = builddirs[0]
+
+ print("Running tests using {0} ({1})...".format(interpreter, version))
+ for test in args.tests:
+ status = subprocess.call(
+ [interpreter, os.path.join(args.srcdir, test)],
+ env=env, stdout=out, stderr=err)
+ print("{0}: {1}".format(status_to_str(status), test))
+ results.append(status)
+
+def count(status):
+ return len(list(filter(lambda x: x == status, results)))
+def failed():
+ return len(list(filter(lambda x: x not in (0, 77, 99), results)))
+
+print("{0} tests run, {1} succeeded, {2} failed, {3} skipped.".format(
+ len(results), count(0), failed(), count(77)))
+sys.exit(len(results) - count(0))
diff --git a/lang/python/tests/sign-only.asc b/lang/python/tests/sign-only.asc
new file mode 100644
index 0000000..6e2a6f3
--- /dev/null
+++ b/lang/python/tests/sign-only.asc
@@ -0,0 +1,33 @@
+-----BEGIN PGP PRIVATE KEY BLOCK-----
+Version: GnuPG v2
+
+lQPFBFd/jO8BCADiull4EVJiKmJqclPyU6GhTlbJXw7Ch0zbFAauOWYT3ACmgr1U
+KfJlZ2sPe2EezZkVSACxgIjTCzcgKQLh/swXdhO8uEgWEIN8f07WcSVDrcRGYwDS
+KFSRsK0bfO/OQQDUsSkNQSHjcOdLnCHCinMrQi1mBZOs+Y/DXOkkEV1zbFFV7q6X
+4vX9HSWwTRQTdOV9CFZykbwM+X1YIZlVtpOAKqSNJi3P17uQF7P9zko6HWKKKQ5S
+96BfXUOIpBRl82R85/yQgeGrWlvZ2BT2ittscNQlBKqLHJ7LIeDr9ctbKlKZjHTn
+Da7NYg+PoMHspbizjSONbEzpcR/9ZUq16oJJABEBAAH+BwMC7hQZNJSmlX/W6sfL
+0wakX6kTsiCEMy2vMCRcZ769JKT234avHtkL/g7MBJEzqdG9HSEp7+LHGuOWJhfa
+20f61WvPT5ujUIy//QXJ9a8z877jCm+fHKCTDXGYLLfCkJLfr3/GfTRy6gaIGTSw
+BqZaRelPvHbMp+eiFqDkf8W/E1LO3/83k87+pXggjz4p0OasyMw8RcDmy+IKBMGG
+bzet5WIKHIhpblIzuuucQHOjtwA8vCedub3F4lcRuULe2GW6sNuCB9kjSC9g6D1d
+bJ+WYi5GiUUQARGSNXiWVoVPLpEo0i6/2bKJ7vBYGRewNp42ebVQU2bFW7uzhaIq
+4itzNTjFNTpcxX3Lo0/mzJpe7pVRJwN+HGahNGT0EtPDsT/nNTFDUq8e8nt0U9/8
+0eekg4MRBJEzE3A+wosIHPjzCkQgu98+nh79rPMbCpZVxNfLb136cTkubmHCWptN
+T2MbqK2L4hMcOxHGGOmI9SjFltNeKtTsVtkxh3Vj67UESPdN550centfasJYA0bj
+guRQfHWHJXYIfFwblIFkl8xtIVLTeWlQMEvc7oI8jcJOc2ri8Zdjj/55xxv/RvjC
+ZKzfjPpdkLYcN1zP/hETLD68u7WmiMAYCr8Eq9YQ3oKklUpWxRMCAAtmgjGGpm5P
+QQW+36s96Q3cuG8R0Z4Wo8y89FgWzCEzuAhemCdffoUA8kn0HJQaVndnExJb1Ebz
+wp+zsX/JqiOFvcKHJAWCaXkk0oXVi1aIV4tQyCPfhyjnd846K7g8UabAz51IJHvF
+CXRAmqJvu26NqjYOfWBJJxZQsPH4FjPfYx+e/MFPZa+UTKCfzaOHClrePHUDHw58
+Ez5ItcORYn51IWW33r+c4tlhW5mrjMD7FcjFOuYT4EIivd5BSnwLP0fjBz8TBVAY
+yyFO+YAXTQ+0MVNpZ24gT25seSAodGVzdCBrZXksIGRvIG5vdCB1c2UpIDxzb0Bl
+eGFtcGxlLm9yZz6JATcEEwEIACEFAld/jO8CGwMFCwkIBwIGFQgJCgsCBBYCAwEC
+HgECF4AACgkQ/tFT8S8Y9F3PAwgAvKav6+luvcAhrpBMO4z/Q8kDMtO5AW1KTEcz
+neqpj5eTVJVbYUgDuBlEXbFYtcZmYyYtJC5KQkN3bxPmehVUzGk27UYWMWbPIWyU
+riGcFL5BWWQaKSqiWUypzhNVnxYoiWVhHeJ36LICVMpLBaubgcpwCSW/j58yZo/7
+XRwf40OblXr4cevIW4Oq5GSxKOQF+DCErF6BeikC2i+NoqSxwNiIO/1NUxs8QfAI
+z8UT/bSUXr62BWLfeCIDGgXutMMPth3tKi4DlvLCzI6eYJrd8E3Rt7iUZm9IH8OQ
+Djv2DKnL/E/AP8oITItrOmICqfEWcj+Tk2Xep4pCCMNU+Pa0yg==
+=gG5b
+-----END PGP PRIVATE KEY BLOCK-----
diff --git a/lang/python/tests/support.py b/lang/python/tests/support.py
new file mode 100644
index 0000000..4d7135e
--- /dev/null
+++ b/lang/python/tests/support.py
@@ -0,0 +1,69 @@
+# Copyright (C) 2016 g10 Code GmbH
+#
+# This file is part of GPGME.
+#
+# GPGME is free software; you can redistribute it and/or modify it
+# under the terms of the GNU General Public License as published by
+# the Free Software Foundation; either version 2 of the License, or
+# (at your option) any later version.
+#
+# GPGME is distributed in the hope that it will be useful, but WITHOUT
+# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
+# or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General
+# Public License for more details.
+#
+# You should have received a copy of the GNU Lesser General Public
+# License along with this program; if not, see <http://www.gnu.org/licenses/>.
+
+from __future__ import absolute_import, print_function, unicode_literals
+del absolute_import, print_function, unicode_literals
+
+import sys
+import os
+from pyme import core
+
+# known keys
+alpha = "A0FF4590BB6122EDEF6E3C542D727CC768697734"
+bob = "D695676BDCEDCC2CDD6152BCFE180B1DA9E3B0B2"
+encrypt_only = "F52770D5C4DB41408D918C9F920572769B9FE19C"
+sign_only = "7CCA20CCDE5394CEE71C9F0BFED153F12F18F45D"
+
+def make_filename(name):
+ return os.path.join(os.environ['top_srcdir'], 'tests', 'gpg', name)
+
+def in_srcdir(name):
+ return os.path.join(os.environ['srcdir'], name)
+
+def init_gpgme(proto):
+ core.engine_check_version(proto)
+
+verbose = int(os.environ.get('verbose', 0)) > 1
+def print_data(data):
+ if verbose:
+ try:
+ # See if it is a file-like object.
+ data.seek(0, os.SEEK_SET)
+ data = data.read()
+ except:
+ # Hope for the best.
+ pass
+ sys.stdout.buffer.write(data)
+
+def mark_key_trusted(ctx, key):
+ class Editor(object):
+ def __init__(self):
+ self.steps = ["trust", "save"]
+ def edit(self, status, args, out):
+ if args == "keyedit.prompt":
+ result = self.steps.pop(0)
+ elif args == "edit_ownertrust.value":
+ result = "5"
+ elif args == "edit_ownertrust.set_ultimate.okay":
+ result = "Y"
+ elif args == "keyedit.save.okay":
+ result = "Y"
+ else:
+ result = None
+ return result
+ with core.Data() as sink:
+ ctx.op_edit(key, Editor().edit, sink, sink)
diff --git a/lang/python/tests/t-callbacks.py b/lang/python/tests/t-callbacks.py
new file mode 100755
index 0000000..b3b4349
--- /dev/null
+++ b/lang/python/tests/t-callbacks.py
@@ -0,0 +1,257 @@
+#!/usr/bin/env python
+
+# Copyright (C) 2016 g10 Code GmbH
+#
+# This file is part of GPGME.
+#
+# GPGME is free software; you can redistribute it and/or modify it
+# under the terms of the GNU General Public License as published by
+# the Free Software Foundation; either version 2 of the License, or
+# (at your option) any later version.
+#
+# GPGME is distributed in the hope that it will be useful, but WITHOUT
+# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
+# or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General
+# Public License for more details.
+#
+# You should have received a copy of the GNU Lesser General Public
+# License along with this program; if not, see <http://www.gnu.org/licenses/>.
+
+from __future__ import absolute_import, print_function, unicode_literals
+del absolute_import, print_function, unicode_literals
+
+import os
+from pyme import core, constants
+import support
+
+support.init_gpgme(constants.PROTOCOL_OpenPGP)
+
+c = core.Context()
+c.set_pinentry_mode(constants.PINENTRY_MODE_LOOPBACK)
+
+source = core.Data("Hallo Leute\n")
+sink = core.Data()
+
+# Valid passphrases, both as string and bytes.
+for passphrase in ('foo', b'foo'):
+ def passphrase_cb(hint, desc, prev_bad, hook=None):
+ assert hook == passphrase
+ return hook
+
+ c.set_passphrase_cb(passphrase_cb, passphrase)
+ c.op_encrypt([], 0, source, sink)
+
+# Returning an invalid type.
+def passphrase_cb(hint, desc, prev_bad, hook=None):
+ return 0
+
+c.set_passphrase_cb(passphrase_cb, None)
+try:
+ c.op_encrypt([], 0, source, sink)
+except Exception as e:
+ assert type(e) == TypeError
+ assert str(e) == "expected str or bytes from passphrase callback, got int"
+else:
+ assert False, "Expected an error, got none"
+
+# Raising an exception inside callback.
+myException = Exception()
+def passphrase_cb(hint, desc, prev_bad, hook=None):
+ raise myException
+
+c.set_passphrase_cb(passphrase_cb, None)
+try:
+ c.op_encrypt([], 0, source, sink)
+except Exception as e:
+ assert e == myException
+else:
+ assert False, "Expected an error, got none"
+
+# Wrong kind of callback function.
+def bad_passphrase_cb():
+ pass
+
+c.set_passphrase_cb(bad_passphrase_cb, None)
+try:
+ c.op_encrypt([], 0, source, sink)
+except Exception as e:
+ assert type(e) == TypeError
+else:
+ assert False, "Expected an error, got none"
+
+
+
+# Test the progress callback.
+parms = """<GnupgKeyParms format="internal">
+Key-Type: RSA
+Key-Length: 1024
+Name-Real: Joe Tester
+Name-Comment: with stupid passphrase
+Name-Email: joe+pyme@example.org
+Passphrase: Crypt0R0cks
+Expire-Date: 2020-12-31
+</GnupgKeyParms>
+"""
+
+messages = []
+def progress_cb(what, typ, current, total, hook=None):
+ assert hook == messages
+ messages.append(
+ "PROGRESS UPDATE: what = {}, type = {}, current = {}, total = {}"
+ .format(what, typ, current, total))
+
+c = core.Context()
+c.set_progress_cb(progress_cb, messages)
+c.op_genkey(parms, None, None)
+assert len(messages) > 0
+
+# Test exception handling.
+def progress_cb(what, typ, current, total, hook=None):
+ raise myException
+
+c = core.Context()
+c.set_progress_cb(progress_cb, None)
+try:
+ c.op_genkey(parms, None, None)
+except Exception as e:
+ assert e == myException
+else:
+ assert False, "Expected an error, got none"
+
+
+# Test the edit callback.
+c = core.Context()
+c.set_pinentry_mode(constants.PINENTRY_MODE_LOOPBACK)
+c.set_passphrase_cb(lambda *args: "abc")
+sink = core.Data()
+alpha = c.get_key("A0FF4590BB6122EDEF6E3C542D727CC768697734", False)
+
+cookie = object()
+edit_cb_called = False
+def edit_cb(status, args, hook):
+ global edit_cb_called
+ edit_cb_called = True
+ assert hook == cookie
+ return "quit" if args == "keyedit.prompt" else None
+c.op_edit(alpha, edit_cb, cookie, sink)
+assert edit_cb_called
+
+# Test exceptions.
+c = core.Context()
+c.set_pinentry_mode(constants.PINENTRY_MODE_LOOPBACK)
+c.set_passphrase_cb(lambda *args: "abc")
+sink = core.Data()
+
+def edit_cb(status, args):
+ raise myException
+try:
+ c.op_edit(alpha, edit_cb, None, sink)
+except Exception as e:
+ assert e == myException
+else:
+ assert False, "Expected an error, got none"
+
+
+
+# Test the status callback.
+source = core.Data("Hallo Leute\n")
+sink = core.Data()
+
+status_cb_called = False
+def status_cb(keyword, args, hook=None):
+ global status_cb_called
+ status_cb_called = True
+ assert hook == cookie
+
+c = core.Context()
+c.set_status_cb(status_cb, cookie)
+c.set_ctx_flag("full-status", "1")
+c.op_encrypt([alpha], constants.ENCRYPT_ALWAYS_TRUST, source, sink)
+assert status_cb_called
+
+# Test exceptions.
+source = core.Data("Hallo Leute\n")
+sink = core.Data()
+
+def status_cb(keyword, args):
+ raise myException
+
+c = core.Context()
+c.set_status_cb(status_cb, None)
+c.set_ctx_flag("full-status", "1")
+try:
+ c.op_encrypt([alpha], constants.ENCRYPT_ALWAYS_TRUST, source, sink)
+except Exception as e:
+ assert e == myException
+else:
+ assert False, "Expected an error, got none"
+
+
+
+# Test the data callbacks.
+def read_cb(amount, hook=None):
+ assert hook == cookie
+ return 0
+def release_cb(hook=None):
+ assert hook == cookie
+data = core.Data(cbs=(read_cb, None, None, release_cb, cookie))
+try:
+ data.read()
+except Exception as e:
+ assert type(e) == TypeError
+else:
+ assert False, "Expected an error, got none"
+
+def read_cb(amount):
+ raise myException
+data = core.Data(cbs=(read_cb, None, None, lambda: None))
+try:
+ data.read()
+except Exception as e:
+ assert e == myException
+else:
+ assert False, "Expected an error, got none"
+
+
+def write_cb(what, hook=None):
+ assert hook == cookie
+ return "wrong type"
+data = core.Data(cbs=(None, write_cb, None, release_cb, cookie))
+try:
+ data.write(b'stuff')
+except Exception as e:
+ assert type(e) == TypeError
+else:
+ assert False, "Expected an error, got none"
+
+def write_cb(what):
+ raise myException
+data = core.Data(cbs=(None, write_cb, None, lambda: None))
+try:
+ data.write(b'stuff')
+except Exception as e:
+ assert e == myException
+else:
+ assert False, "Expected an error, got none"
+
+
+def seek_cb(offset, whence, hook=None):
+ assert hook == cookie
+ return "wrong type"
+data = core.Data(cbs=(None, None, seek_cb, release_cb, cookie))
+try:
+ data.seek(0, os.SEEK_SET)
+except Exception as e:
+ assert type(e) == TypeError
+else:
+ assert False, "Expected an error, got none"
+
+def seek_cb(offset, whence):
+ raise myException
+data = core.Data(cbs=(None, None, seek_cb, lambda: None))
+try:
+ data.seek(0, os.SEEK_SET)
+except Exception as e:
+ assert e == myException
+else:
+ assert False, "Expected an error, got none"
diff --git a/lang/python/tests/t-data.py b/lang/python/tests/t-data.py
new file mode 100755
index 0000000..4812a2e
--- /dev/null
+++ b/lang/python/tests/t-data.py
@@ -0,0 +1,129 @@
+#!/usr/bin/env python
+
+# Copyright (C) 2016 g10 Code GmbH
+#
+# This file is part of GPGME.
+#
+# GPGME is free software; you can redistribute it and/or modify it
+# under the terms of the GNU General Public License as published by
+# the Free Software Foundation; either version 2 of the License, or
+# (at your option) any later version.
+#
+# GPGME is distributed in the hope that it will be useful, but WITHOUT
+# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
+# or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General
+# Public License for more details.
+#
+# You should have received a copy of the GNU Lesser General Public
+# License along with this program; if not, see <http://www.gnu.org/licenses/>.
+
+from __future__ import absolute_import, print_function, unicode_literals
+del absolute_import, print_function, unicode_literals
+
+import io
+import os
+import tempfile
+from pyme import core
+
+data = core.Data('Hello world!')
+assert data.read() == b'Hello world!'
+assert data.read() == b''
+
+data.seek(0, os.SEEK_SET)
+assert data.read() == b'Hello world!'
+assert data.read() == b''
+
+data = core.Data(b'Hello world!')
+assert data.read() == b'Hello world!'
+
+data = core.Data(b'Hello world!', copy=False)
+assert data.read() == b'Hello world!'
+
+data = core.Data()
+data.write('Hello world!')
+data.seek(0, os.SEEK_SET)
+assert data.read() == b'Hello world!'
+
+data = core.Data()
+data.write(b'Hello world!')
+data.seek(0, os.SEEK_SET)
+assert data.read() == b'Hello world!'
+
+binjunk = bytes(range(256))
+data = core.Data()
+data.write(binjunk)
+data.seek(0, os.SEEK_SET)
+assert data.read() == binjunk
+
+data = core.Data()
+data.set_file_name("foobar")
+assert data.get_file_name() == "foobar"
+
+# Test reading from an existing file.
+with tempfile.NamedTemporaryFile() as tmp:
+ tmp.write(binjunk)
+ tmp.flush()
+ tmp.seek(0)
+
+ # Open using name.
+ data = core.Data(file=tmp.name)
+ assert data.read() == binjunk
+
+ # Open using name, without copying.
+ if False:
+ # delayed reads are not yet supported
+ data = core.Data(file=tmp.name, copy=False)
+ assert data.read() == binjunk
+
+ # Open using stream.
+ tmp.seek(0)
+ data = core.Data(file=tmp)
+ assert data.read() == binjunk
+
+ # Open using stream, offset, and length.
+ data = core.Data(file=tmp, offset=0, length=42)
+ assert data.read() == binjunk[:42]
+
+ # Open using name, offset, and length.
+ data = core.Data(file=tmp.name, offset=23, length=42)
+ assert data.read() == binjunk[23:23+42]
+
+# Test callbacks.
+class DataObject(object):
+ def __init__(self):
+ self.buffer = io.BytesIO()
+ self.released = False
+
+ def read(self, amount, hook=None):
+ assert not self.released
+ return self.buffer.read(amount)
+
+ def write(self, data, hook=None):
+ assert not self.released
+ return self.buffer.write(data)
+
+ def seek(self, offset, whence, hook=None):
+ assert not self.released
+ return self.buffer.seek(offset, whence)
+
+ def release(self, hook=None):
+ assert not self.released
+ self.released = True
+
+do = DataObject()
+cookie = object()
+data = core.Data(cbs=(do.read, do.write, do.seek, do.release, cookie))
+data.write('Hello world!')
+data.seek(0, os.SEEK_SET)
+assert data.read() == b'Hello world!'
+del data
+assert do.released
+
+# Again, without the cookie.
+do = DataObject()
+data = core.Data(cbs=(do.read, do.write, do.seek, do.release))
+data.write('Hello world!')
+data.seek(0, os.SEEK_SET)
+assert data.read() == b'Hello world!'
+del data
+assert do.released
diff --git a/lang/python/tests/t-decrypt-verify.py b/lang/python/tests/t-decrypt-verify.py
new file mode 100755
index 0000000..a38a965
--- /dev/null
+++ b/lang/python/tests/t-decrypt-verify.py
@@ -0,0 +1,77 @@
+#!/usr/bin/env python
+
+# Copyright (C) 2016 g10 Code GmbH
+#
+# This file is part of GPGME.
+#
+# GPGME is free software; you can redistribute it and/or modify it
+# under the terms of the GNU General Public License as published by
+# the Free Software Foundation; either version 2 of the License, or
+# (at your option) any later version.
+#
+# GPGME is distributed in the hope that it will be useful, but WITHOUT
+# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
+# or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General
+# Public License for more details.
+#
+# You should have received a copy of the GNU Lesser General Public
+# License along with this program; if not, see <http://www.gnu.org/licenses/>.
+
+from __future__ import absolute_import, print_function, unicode_literals
+del absolute_import, print_function, unicode_literals
+
+import pyme
+from pyme import core, constants, errors
+import support
+
+def check_verify_result(result, summary, fpr, status):
+ assert len(result.signatures) == 1, "Unexpected number of signatures"
+ sig = result.signatures[0]
+ assert sig.summary == summary, "Unexpected signature summary"
+ assert sig.fpr == fpr
+ assert errors.GPGMEError(sig.status).getcode() == status
+ assert len(sig.notations) == 0
+ assert not sig.wrong_key_usage
+ assert sig.validity == constants.VALIDITY_FULL
+ assert errors.GPGMEError(sig.validity_reason).getcode() == errors.NO_ERROR
+
+support.init_gpgme(constants.PROTOCOL_OpenPGP)
+c = core.Context()
+
+source = core.Data(file=support.make_filename("cipher-2.asc"))
+sink = core.Data()
+
+c.op_decrypt_verify(source, sink)
+result = c.op_decrypt_result()
+assert not result.unsupported_algorithm, \
+ "Unsupported algorithm: {}".format(result.unsupported_algorithm)
+
+support.print_data(sink)
+
+verify_result = c.op_verify_result()
+check_verify_result(verify_result,
+ constants.SIGSUM_VALID | constants.SIGSUM_GREEN,
+ "A0FF4590BB6122EDEF6E3C542D727CC768697734",
+ errors.NO_ERROR)
+
+# Idiomatic interface.
+with pyme.Context() as c:
+ alpha = c.get_key("A0FF4590BB6122EDEF6E3C542D727CC768697734", False)
+ bob = c.get_key("D695676BDCEDCC2CDD6152BCFE180B1DA9E3B0B2", False)
+ plaintext, _, verify_result = \
+ c.decrypt(open(support.make_filename("cipher-2.asc")), verify=[alpha])
+ assert plaintext.find(b'Wenn Sie dies lesen k') >= 0, \
+ 'Plaintext not found'
+ check_verify_result(verify_result,
+ constants.SIGSUM_VALID | constants.SIGSUM_GREEN,
+ "A0FF4590BB6122EDEF6E3C542D727CC768697734",
+ errors.NO_ERROR)
+
+ try:
+ c.decrypt(open(support.make_filename("cipher-2.asc")),
+ verify=[alpha, bob])
+ except errors.MissingSignatures as e:
+ assert len(e.missing) == 1
+ assert e.missing[0] == bob
+ else:
+ assert False, "Expected an error, got none"
diff --git a/lang/python/tests/t-decrypt.py b/lang/python/tests/t-decrypt.py
new file mode 100755
index 0000000..2d85bc2
--- /dev/null
+++ b/lang/python/tests/t-decrypt.py
@@ -0,0 +1,45 @@
+#!/usr/bin/env python
+
+# Copyright (C) 2016 g10 Code GmbH
+#
+# This file is part of GPGME.
+#
+# GPGME is free software; you can redistribute it and/or modify it
+# under the terms of the GNU General Public License as published by
+# the Free Software Foundation; either version 2 of the License, or
+# (at your option) any later version.
+#
+# GPGME is distributed in the hope that it will be useful, but WITHOUT
+# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
+# or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General
+# Public License for more details.
+#
+# You should have received a copy of the GNU Lesser General Public
+# License along with this program; if not, see <http://www.gnu.org/licenses/>.
+
+from __future__ import absolute_import, print_function, unicode_literals
+del absolute_import, print_function, unicode_literals
+
+import pyme
+from pyme import core, constants
+import support
+
+support.init_gpgme(constants.PROTOCOL_OpenPGP)
+c = core.Context()
+
+source = core.Data(file=support.make_filename("cipher-1.asc"))
+sink = core.Data()
+
+c.op_decrypt(source, sink)
+result = c.op_decrypt_result()
+assert not result.unsupported_algorithm, \
+ "Unsupported algorithm: {}".format(result.unsupported_algorithm)
+
+support.print_data(sink)
+
+# Idiomatic interface.
+with pyme.Context() as c:
+ plaintext, _, _ = c.decrypt(open(support.make_filename("cipher-1.asc")))
+ assert len(plaintext) > 0
+ assert plaintext.find(b'Wenn Sie dies lesen k') >= 0, \
+ 'Plaintext not found'
diff --git a/lang/python/tests/t-edit.py b/lang/python/tests/t-edit.py
new file mode 100755
index 0000000..18bcb94
--- /dev/null
+++ b/lang/python/tests/t-edit.py
@@ -0,0 +1,72 @@
+#!/usr/bin/env python
+
+# Copyright (C) 2005 Igor Belyi <belyi@users.sourceforge.net>
+# Copyright (C) 2016 g10 Code GmbH
+#
+# This file is part of GPGME.
+#
+# GPGME is free software; you can redistribute it and/or modify it
+# under the terms of the GNU General Public License as published by
+# the Free Software Foundation; either version 2 of the License, or
+# (at your option) any later version.
+#
+# GPGME is distributed in the hope that it will be useful, but WITHOUT
+# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
+# or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General
+# Public License for more details.
+#
+# You should have received a copy of the GNU Lesser General Public
+# License along with this program; if not, see <http://www.gnu.org/licenses/>.
+
+from __future__ import absolute_import, print_function, unicode_literals
+del absolute_import, print_function, unicode_literals
+
+import sys
+import os
+from pyme import core, constants
+import support
+
+class KeyEditor(object):
+ def __init__(self):
+ self.steps = ["fpr", "expire", "1", "primary", "quit"]
+ self.step = 0
+ self.done = False
+ self.verbose = int(os.environ.get('verbose', 0)) > 1
+
+ def edit_fnc(self, status, args, out=None):
+ if args == "keyedit.prompt":
+ result = self.steps[self.step]
+ self.step += 1
+ elif args == "keyedit.save.okay":
+ result = "Y"
+ self.done = self.step == len(self.steps)
+ elif args == "keygen.valid":
+ result = "0"
+ else:
+ result = None
+
+ if self.verbose:
+ sys.stderr.write("Code: {}, args: {!r}, Returning: {!r}\n"
+ .format(status, args, result))
+
+ return result
+
+support.init_gpgme(constants.PROTOCOL_OpenPGP)
+
+c = core.Context()
+c.set_pinentry_mode(constants.PINENTRY_MODE_LOOPBACK)
+c.set_passphrase_cb(lambda *args: "abc")
+c.set_armor(True)
+
+# The deprecated interface.
+editor = KeyEditor()
+c.interact(c.get_key("A0FF4590BB6122EDEF6E3C542D727CC768697734", False),
+ editor.edit_fnc)
+assert editor.done
+
+# The deprecated interface.
+sink = core.Data()
+editor = KeyEditor()
+c.op_edit(c.get_key("A0FF4590BB6122EDEF6E3C542D727CC768697734", False),
+ editor.edit_fnc, sink, sink)
+assert editor.done
diff --git a/lang/python/tests/t-encrypt-large.py b/lang/python/tests/t-encrypt-large.py
new file mode 100755
index 0000000..b9cc3b5
--- /dev/null
+++ b/lang/python/tests/t-encrypt-large.py
@@ -0,0 +1,66 @@
+#!/usr/bin/env python
+
+# Copyright (C) 2016 g10 Code GmbH
+#
+# This file is part of GPGME.
+#
+# GPGME is free software; you can redistribute it and/or modify it
+# under the terms of the GNU General Public License as published by
+# the Free Software Foundation; either version 2 of the License, or
+# (at your option) any later version.
+#
+# GPGME is distributed in the hope that it will be useful, but WITHOUT
+# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
+# or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General
+# Public License for more details.
+#
+# You should have received a copy of the GNU Lesser General Public
+# License along with this program; if not, see <http://www.gnu.org/licenses/>.
+
+from __future__ import absolute_import, print_function, unicode_literals
+del absolute_import, print_function, unicode_literals
+
+import sys
+import random
+from pyme import core, constants
+import support
+
+if len(sys.argv) == 2:
+ nbytes = int(sys.argv[1])
+else:
+ nbytes = 100000
+
+support.init_gpgme(constants.PROTOCOL_OpenPGP)
+c = core.Context()
+
+ntoread = nbytes
+def read_cb(amount):
+ global ntoread
+ chunk = ntoread if ntoread < amount else amount
+ ntoread -= chunk
+ assert ntoread >= 0
+ assert chunk >= 0
+ return bytes(bytearray(random.randrange(256) for i in range(chunk)))
+
+nwritten = 0
+def write_cb(data):
+ global nwritten
+ nwritten += len(data)
+ return len(data)
+
+source = core.Data(cbs=(read_cb, None, None, lambda: None))
+sink = core.Data(cbs=(None, write_cb, None, lambda: None))
+
+keys = []
+keys.append(c.get_key("A0FF4590BB6122EDEF6E3C542D727CC768697734", False))
+keys.append(c.get_key("D695676BDCEDCC2CDD6152BCFE180B1DA9E3B0B2", False))
+
+c.op_encrypt(keys, constants.ENCRYPT_ALWAYS_TRUST, source, sink)
+result = c.op_encrypt_result()
+assert not result.invalid_recipients, \
+ "Invalid recipient encountered: {}".format(result.invalid_recipients.fpr)
+assert ntoread == 0
+
+if support.verbose:
+ sys.stderr.write(
+ "plaintext={} bytes, ciphertext={} bytes\n".format(nbytes, nwritten))
diff --git a/lang/python/tests/t-encrypt-sign.py b/lang/python/tests/t-encrypt-sign.py
new file mode 100755
index 0000000..a453f79
--- /dev/null
+++ b/lang/python/tests/t-encrypt-sign.py
@@ -0,0 +1,98 @@
+#!/usr/bin/env python
+
+# Copyright (C) 2016 g10 Code GmbH
+#
+# This file is part of GPGME.
+#
+# GPGME is free software; you can redistribute it and/or modify it
+# under the terms of the GNU General Public License as published by
+# the Free Software Foundation; either version 2 of the License, or
+# (at your option) any later version.
+#
+# GPGME is distributed in the hope that it will be useful, but WITHOUT
+# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
+# or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General
+# Public License for more details.
+#
+# You should have received a copy of the GNU Lesser General Public
+# License along with this program; if not, see <http://www.gnu.org/licenses/>.
+
+from __future__ import absolute_import, print_function, unicode_literals
+del absolute_import, print_function, unicode_literals
+
+import sys
+import pyme
+from pyme import core, constants
+import support
+
+support.init_gpgme(constants.PROTOCOL_OpenPGP)
+c = core.Context()
+c.set_armor(True)
+
+def check_result(r, typ):
+ if r.invalid_signers:
+ sys.exit("Invalid signer found: {}".format(r.invalid_signers.fpr))
+
+ if len(r.signatures) != 1:
+ sys.exit("Unexpected number of signatures created")
+
+ signature = r.signatures[0]
+ if signature.type != typ:
+ sys.exit("Wrong type of signature created")
+
+ if signature.pubkey_algo != constants.PK_DSA:
+ sys.exit("Wrong pubkey algorithm reported: {}".format(
+ signature.pubkey_algo))
+
+ if signature.hash_algo not in (constants.MD_SHA1, constants.MD_RMD160):
+ sys.exit("Wrong hash algorithm reported: {}".format(
+ signature.hash_algo))
+
+ if signature.sig_class != 0:
+ sys.exit("Wrong signature class reported: {}".format(
+ signature.sig_class))
+
+ if signature.fpr != "A0FF4590BB6122EDEF6E3C542D727CC768697734":
+ sys.exit("Wrong fingerprint reported: {}".format(signature.fpr))
+
+keys = []
+keys.append(c.get_key("A0FF4590BB6122EDEF6E3C542D727CC768697734", False))
+keys.append(c.get_key("D695676BDCEDCC2CDD6152BCFE180B1DA9E3B0B2", False))
+
+for recipients in (keys, []):
+ source = core.Data("Hallo Leute\n")
+ sink = core.Data()
+
+ c.op_encrypt_sign(recipients, constants.ENCRYPT_ALWAYS_TRUST, source, sink)
+ result = c.op_encrypt_result()
+ assert not result.invalid_recipients, \
+ "Invalid recipient encountered: {}".format(
+ result.invalid_recipients.fpr)
+
+ result = c.op_sign_result()
+ check_result(result, constants.SIG_MODE_NORMAL)
+
+ support.print_data(sink)
+
+
+# Idiomatic interface.
+with pyme.Context(armor=True) as c:
+ message = "Hallo Leute\n".encode()
+ ciphertext, _, sig_result = c.encrypt(message,
+ recipients=keys,
+ always_trust=True)
+ assert len(ciphertext) > 0
+ assert ciphertext.find(b'BEGIN PGP MESSAGE') > 0, 'Marker not found'
+ check_result(sig_result, constants.SIG_MODE_NORMAL)
+
+ c.signers = [c.get_key(support.sign_only, True)]
+ c.encrypt(message, recipients=keys, always_trust=True)
+
+ c.signers = [c.get_key(support.encrypt_only, True)]
+ try:
+ c.encrypt(message, recipients=keys, always_trust=True)
+ except pyme.errors.InvalidSigners as e:
+ assert len(e.signers) == 1
+ assert support.encrypt_only.endswith(e.signers[0].fpr)
+ else:
+ assert False, "Expected an InvalidSigners error, got none"
diff --git a/lang/python/tests/t-encrypt-sym.py b/lang/python/tests/t-encrypt-sym.py
new file mode 100755
index 0000000..d577184
--- /dev/null
+++ b/lang/python/tests/t-encrypt-sym.py
@@ -0,0 +1,86 @@
+#!/usr/bin/env python
+
+# Copyright (C) 2016 g10 Code GmbH
+#
+# This file is part of GPGME.
+#
+# GPGME is free software; you can redistribute it and/or modify it
+# under the terms of the GNU General Public License as published by
+# the Free Software Foundation; either version 2 of the License, or
+# (at your option) any later version.
+#
+# GPGME is distributed in the hope that it will be useful, but WITHOUT
+# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
+# or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General
+# Public License for more details.
+#
+# You should have received a copy of the GNU Lesser General Public
+# License along with this program; if not, see <http://www.gnu.org/licenses/>.
+
+from __future__ import absolute_import, print_function, unicode_literals
+del absolute_import, print_function, unicode_literals
+
+import os
+import pyme
+from pyme import core, constants
+import support
+
+support.init_gpgme(constants.PROTOCOL_OpenPGP)
+
+for passphrase in ("abc", b"abc"):
+ c = core.Context()
+ c.set_armor(True)
+ c.set_pinentry_mode(constants.PINENTRY_MODE_LOOPBACK)
+
+ source = core.Data("Hallo Leute\n")
+ cipher = core.Data()
+
+ passphrase_cb_called = 0
+ def passphrase_cb(hint, desc, prev_bad, hook=None):
+ global passphrase_cb_called
+ passphrase_cb_called += 1
+ return passphrase
+
+ c.set_passphrase_cb(passphrase_cb, None)
+
+ c.op_encrypt([], 0, source, cipher)
+ assert passphrase_cb_called == 1, \
+ "Callback called {} times".format(passphrase_cb_called)
+ support.print_data(cipher)
+
+ c = core.Context()
+ c.set_armor(True)
+ c.set_pinentry_mode(constants.PINENTRY_MODE_LOOPBACK)
+ c.set_passphrase_cb(passphrase_cb, None)
+ plain = core.Data()
+ cipher.seek(0, os.SEEK_SET)
+
+ c.op_decrypt(cipher, plain)
+ # Seems like the passphrase is cached.
+ #assert passphrase_cb_called == 2, \
+ # "Callback called {} times".format(passphrase_cb_called)
+ support.print_data(plain)
+
+ plain.seek(0, os.SEEK_SET)
+ plaintext = plain.read()
+ assert plaintext == b"Hallo Leute\n", \
+ "Wrong plaintext {!r}".format(plaintext)
+
+# Idiomatic interface.
+for passphrase in ("abc", b"abc"):
+ with pyme.Context(armor=True) as c:
+ # Check that the passphrase callback is not altered.
+ def f(*args):
+ assert False
+ c.set_passphrase_cb(f)
+
+ message = "Hallo Leute\n".encode()
+ ciphertext, _, _ = c.encrypt(message,
+ passphrase=passphrase,
+ sign=False)
+ assert ciphertext.find(b'BEGIN PGP MESSAGE') > 0, 'Marker not found'
+
+ plaintext, _, _ = c.decrypt(ciphertext, passphrase=passphrase)
+ assert plaintext == message, 'Message body not recovered'
+
+ assert c._passphrase_cb[1] == f, "Passphrase callback not restored"
diff --git a/lang/python/tests/t-encrypt.py b/lang/python/tests/t-encrypt.py
new file mode 100755
index 0000000..65e7d24
--- /dev/null
+++ b/lang/python/tests/t-encrypt.py
@@ -0,0 +1,65 @@
+#!/usr/bin/env python
+
+# Copyright (C) 2016 g10 Code GmbH
+#
+# This file is part of GPGME.
+#
+# GPGME is free software; you can redistribute it and/or modify it
+# under the terms of the GNU General Public License as published by
+# the Free Software Foundation; either version 2 of the License, or
+# (at your option) any later version.
+#
+# GPGME is distributed in the hope that it will be useful, but WITHOUT
+# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
+# or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General
+# Public License for more details.
+#
+# You should have received a copy of the GNU Lesser General Public
+# License along with this program; if not, see <http://www.gnu.org/licenses/>.
+
+from __future__ import absolute_import, print_function, unicode_literals
+del absolute_import, print_function, unicode_literals
+
+import pyme
+from pyme import core, constants
+import support
+
+support.init_gpgme(constants.PROTOCOL_OpenPGP)
+c = core.Context()
+c.set_armor(True)
+
+source = core.Data("Hallo Leute\n")
+sink = core.Data()
+
+keys = []
+keys.append(c.get_key("A0FF4590BB6122EDEF6E3C542D727CC768697734", False))
+keys.append(c.get_key("D695676BDCEDCC2CDD6152BCFE180B1DA9E3B0B2", False))
+
+c.op_encrypt(keys, constants.ENCRYPT_ALWAYS_TRUST, source, sink)
+result = c.op_encrypt_result()
+assert not result.invalid_recipients, \
+ "Invalid recipients: {}".format(", ".join(r.fpr for r in result.recipients))
+support.print_data(sink)
+
+# Idiomatic interface.
+with pyme.Context(armor=True) as c:
+ ciphertext, _, _ = c.encrypt("Hallo Leute\n".encode(),
+ recipients=keys,
+ sign=False,
+ always_trust=True)
+ assert len(ciphertext) > 0
+ assert ciphertext.find(b'BEGIN PGP MESSAGE') > 0, 'Marker not found'
+
+ c.encrypt("Hallo Leute\n".encode(),
+ recipients=[c.get_key(support.encrypt_only, False)],
+ sign=False, always_trust=True)
+
+ try:
+ c.encrypt("Hallo Leute\n".encode(),
+ recipients=[c.get_key(support.sign_only, False)],
+ sign=False, always_trust=True)
+ except pyme.errors.InvalidRecipients as e:
+ assert len(e.recipients) == 1
+ assert support.sign_only.endswith(e.recipients[0].fpr)
+ else:
+ assert False, "Expected an InvalidRecipients error, got none"
diff --git a/lang/python/tests/t-export.py b/lang/python/tests/t-export.py
new file mode 100755
index 0000000..db36b98
--- /dev/null
+++ b/lang/python/tests/t-export.py
@@ -0,0 +1,40 @@
+#!/usr/bin/env python
+
+# Copyright (C) 2016 g10 Code GmbH
+#
+# This file is part of GPGME.
+#
+# GPGME is free software; you can redistribute it and/or modify it
+# under the terms of the GNU General Public License as published by
+# the Free Software Foundation; either version 2 of the License, or
+# (at your option) any later version.
+#
+# GPGME is distributed in the hope that it will be useful, but WITHOUT
+# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
+# or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General
+# Public License for more details.
+#
+# You should have received a copy of the GNU Lesser General Public
+# License along with this program; if not, see <http://www.gnu.org/licenses/>.
+
+from __future__ import absolute_import, print_function, unicode_literals
+del absolute_import, print_function, unicode_literals
+
+from pyme import core, constants
+import support
+
+support.init_gpgme(constants.PROTOCOL_OpenPGP)
+c = core.Context()
+c.set_armor(True)
+
+sink = core.Data()
+c.op_export_ext(['Alpha', 'Bob'], 0, sink)
+support.print_data(sink)
+
+# Again. Now using a key array.
+keys = []
+keys.append(c.get_key("0x68697734", False)) # Alpha
+keys.append(c.get_key("0xA9E3B0B2", False)) # Bob
+sink = core.Data()
+c.op_export_keys(keys, 0, sink)
+support.print_data(sink)
diff --git a/lang/python/tests/t-file-name.py b/lang/python/tests/t-file-name.py
new file mode 100755
index 0000000..e93b120
--- /dev/null
+++ b/lang/python/tests/t-file-name.py
@@ -0,0 +1,45 @@
+#!/usr/bin/env python
+
+# Copyright (C) 2016 g10 Code GmbH
+#
+# This file is part of GPGME.
+#
+# GPGME is free software; you can redistribute it and/or modify it
+# under the terms of the GNU General Public License as published by
+# the Free Software Foundation; either version 2 of the License, or
+# (at your option) any later version.
+#
+# GPGME is distributed in the hope that it will be useful, but WITHOUT
+# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
+# or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General
+# Public License for more details.
+#
+# You should have received a copy of the GNU Lesser General Public
+# License along with this program; if not, see <http://www.gnu.org/licenses/>.
+
+from __future__ import absolute_import, print_function, unicode_literals
+del absolute_import, print_function, unicode_literals
+
+import os
+from pyme import core, constants
+import support
+
+testname = "abcde12345"
+
+support.init_gpgme(constants.PROTOCOL_OpenPGP)
+c = core.Context()
+c.set_armor(True)
+
+source = core.Data("Hallo Leute\n")
+source.set_file_name(testname)
+cipher = core.Data()
+plain = core.Data()
+
+keys = []
+keys.append(c.get_key("A0FF4590BB6122EDEF6E3C542D727CC768697734", False))
+
+c.op_encrypt(keys, constants.ENCRYPT_ALWAYS_TRUST, source, cipher)
+cipher.seek(0, os.SEEK_SET)
+c.op_decrypt(cipher, plain)
+result = c.op_decrypt_result()
+assert result.file_name == testname
diff --git a/lang/python/tests/t-idiomatic.py b/lang/python/tests/t-idiomatic.py
new file mode 100755
index 0000000..f063206
--- /dev/null
+++ b/lang/python/tests/t-idiomatic.py
@@ -0,0 +1,84 @@
+#!/usr/bin/env python
+
+# Copyright (C) 2016 g10 Code GmbH
+#
+# This file is part of GPGME.
+#
+# GPGME is free software; you can redistribute it and/or modify it
+# under the terms of the GNU General Public License as published by
+# the Free Software Foundation; either version 2 of the License, or
+# (at your option) any later version.
+#
+# GPGME is distributed in the hope that it will be useful, but WITHOUT
+# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
+# or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General
+# Public License for more details.
+#
+# You should have received a copy of the GNU Lesser General Public
+# License along with this program; if not, see <http://www.gnu.org/licenses/>.
+
+from __future__ import absolute_import, print_function, unicode_literals
+del absolute_import, print_function, unicode_literals
+
+import sys
+import io
+import os
+import tempfile
+import pyme
+import support
+
+support.init_gpgme(pyme.constants.PROTOCOL_OpenPGP)
+
+# Both Context and Data can be used as context manager:
+with pyme.Context() as c, pyme.Data() as d:
+ c.get_engine_info()
+ d.write(b"Halloechen")
+ leak_c = c
+ leak_d = d
+assert leak_c.wrapped == None
+assert leak_d.wrapped == None
+
+def sign_and_verify(source, signed, sink):
+ with pyme.Context() as c:
+ c.op_sign(source, signed, pyme.constants.SIG_MODE_NORMAL)
+ signed.seek(0, os.SEEK_SET)
+ c.op_verify(signed, None, sink)
+ result = c.op_verify_result()
+
+ assert len(result.signatures) == 1, "Unexpected number of signatures"
+ sig = result.signatures[0]
+ assert sig.summary == (pyme.constants.SIGSUM_VALID |
+ pyme.constants.SIGSUM_GREEN)
+ assert pyme.errors.GPGMEError(sig.status).getcode() == pyme.errors.NO_ERROR
+
+ sink.seek(0, os.SEEK_SET)
+ assert sink.read() == b"Hallo Leute\n"
+
+# Demonstrate automatic wrapping of file-like objects with 'fileno'
+# method.
+with tempfile.TemporaryFile() as source, \
+ tempfile.TemporaryFile() as signed, \
+ tempfile.TemporaryFile() as sink:
+ source.write(b"Hallo Leute\n")
+ source.seek(0, os.SEEK_SET)
+
+ sign_and_verify(source, signed, sink)
+
+if sys.version_info[0] == 3:
+ # Python2's io.BytesIO does not implement the buffer interface,
+ # hence we cannot use it as sink.
+
+ # XXX: Python's io.BytesIo.truncate does not work as advertised.
+ # http://bugs.python.org/issue27261
+ bio = io.BytesIO()
+ bio.truncate(1)
+ if len(bio.getvalue()) != 1:
+ # This version of Python is affected, preallocate buffer.
+ preallocate = 128*b'\x00'
+ else:
+ preallocate = b''
+
+ # Demonstrate automatic wrapping of objects implementing the buffer
+ # interface, and the use of data objects with the 'with' statement.
+ with io.BytesIO(preallocate) as signed, pyme.Data() as sink:
+ sign_and_verify(b"Hallo Leute\n", signed, sink)
diff --git a/lang/python/tests/t-import.py b/lang/python/tests/t-import.py
new file mode 100755
index 0000000..0b50d02
--- /dev/null
+++ b/lang/python/tests/t-import.py
@@ -0,0 +1,79 @@
+#!/usr/bin/env python
+
+# Copyright (C) 2016 g10 Code GmbH
+#
+# This file is part of GPGME.
+#
+# GPGME is free software; you can redistribute it and/or modify it
+# under the terms of the GNU General Public License as published by
+# the Free Software Foundation; either version 2 of the License, or
+# (at your option) any later version.
+#
+# GPGME is distributed in the hope that it will be useful, but WITHOUT
+# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
+# or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General
+# Public License for more details.
+#
+# You should have received a copy of the GNU Lesser General Public
+# License along with this program; if not, see <http://www.gnu.org/licenses/>.
+
+from __future__ import absolute_import, print_function, unicode_literals
+del absolute_import, print_function, unicode_literals
+
+from pyme import core, constants
+import support
+
+def check_result(result, fpr, secret):
+ assert result.considered == 1 or (secret and result.considered == 3)
+ assert result.no_user_id == 0
+ assert not ((secret and result.imported != 0)
+ or (not secret and (result.imported != 0
+ and result.imported != 1)))
+ assert result.imported_rsa == 0
+ assert not ((secret and (result.unchanged != 0 and result.unchanged != 1))
+ or (not secret and ((result.imported == 0
+ and result.unchanged != 1)
+ or (result.imported == 1
+ and result.unchanged != 0))))
+ assert result.new_user_ids == 0
+ assert result.new_sub_keys == 0
+ assert not ((secret
+ and ((result.secret_imported == 0
+ and result.new_signatures != 0)
+ or (result.secret_imported == 1
+ and result.new_signatures > 1)))
+ or (not secret and result.new_signatures != 0))
+ assert result.new_revocations == 0
+ assert not ((secret and result.secret_read != 1 and result.secret_read != 3)
+ or (not secret and result.secret_read != 0))
+ assert not ((secret and result.secret_imported != 0
+ and result.secret_imported != 1
+ and result.secret_imported != 2)
+ or (not secret and result.secret_imported != 0))
+ assert not ((secret
+ and ((result.secret_imported == 0
+ and result.secret_unchanged != 1
+ and result.secret_unchanged != 2)
+ or (result.secret_imported == 1
+ and result.secret_unchanged != 0)))
+ or (not secret and result.secret_unchanged != 0))
+ assert result.not_imported == 0
+ if secret:
+ assert not (len(result.imports) in (0, 3))
+ else:
+ assert not (len(result.imports) in (0, 2))
+
+ assert fpr == result.imports[0].fpr
+ assert len(result.imports) == 1 or fpr == result.imports[1].fpr
+ assert result.imports[0].result == 0
+
+support.init_gpgme(constants.PROTOCOL_OpenPGP)
+c = core.Context()
+
+c.op_import(core.Data(file=support.make_filename("pubkey-1.asc")))
+result = c.op_import_result()
+check_result(result, "ADAB7FCC1F4DE2616ECFA402AF82244F9CD9FD55", False)
+
+c.op_import(core.Data(file=support.make_filename("seckey-1.asc")))
+result = c.op_import_result()
+check_result(result, "ADAB7FCC1F4DE2616ECFA402AF82244F9CD9FD55", True)
diff --git a/lang/python/tests/t-keylist.py b/lang/python/tests/t-keylist.py
new file mode 100755
index 0000000..5e8b333
--- /dev/null
+++ b/lang/python/tests/t-keylist.py
@@ -0,0 +1,246 @@
+#!/usr/bin/env python
+
+# Copyright (C) 2016 g10 Code GmbH
+#
+# This file is part of GPGME.
+#
+# GPGME is free software; you can redistribute it and/or modify it
+# under the terms of the GNU General Public License as published by
+# the Free Software Foundation; either version 2 of the License, or
+# (at your option) any later version.
+#
+# GPGME is distributed in the hope that it will be useful, but WITHOUT
+# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
+# or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General
+# Public License for more details.
+#
+# You should have received a copy of the GNU Lesser General Public
+# License along with this program; if not, see <http://www.gnu.org/licenses/>.
+
+from __future__ import absolute_import, print_function, unicode_literals
+del absolute_import, print_function, unicode_literals
+
+from pyme import core, constants
+import support
+
+support.init_gpgme(constants.PROTOCOL_OpenPGP)
+c = core.Context()
+
+# Check expration of keys. This test assumes three subkeys of which
+# 2 are expired; it is used with the "Whisky" test key. It has
+# already been checked that these 3 subkeys are available.
+def check_whisky(name, key):
+ sub1 = key.subkeys[2]
+ sub2 = key.subkeys[3]
+
+ assert sub1.expired and sub2.expired, \
+ "Subkey of `{}' not flagged as expired".format(name)
+ assert sub1.expires == 1129636886 and sub2.expires == 1129636939, \
+ "Subkey of `{}' has wrong expiration date".format(name)
+
+keys = [
+ [ "A0FF4590BB6122EDEF6E3C542D727CC768697734", "6AE6D7EE46A871F8",
+ [ [ "Alfa Test", "demo key", "alfa@example.net" ],
+ [ "Alpha Test", "demo key", "alpha@example.net" ],
+ [ "Alice", "demo key", "" ] ], 1 ],
+ [ "D695676BDCEDCC2CDD6152BCFE180B1DA9E3B0B2", "5381EA4EE29BA37F",
+ [ [ "Bob", "demo key", "" ],
+ [ "Bravo Test", "demo key", "bravo@example.net" ] ], 1 ],
+ [ "61EE841A2A27EB983B3B3C26413F4AF31AFDAB6C", "E71E72ACBC43DA60",
+ [ [ "Charlie Test", "demo key", "charlie@example.net" ] ], 1 ],
+ [ "6560C59C43D031C54D7C588EEBA9F240EB9DC9E6", "06F22880B0C45424",
+ [ [ "Delta Test", "demo key", "delta@example.net" ] ], 1 ],
+ [ "3531152DE293E26A07F504BC318C1FAEFAEF6D1B", "B5C79E1A7272144D",
+ [ [ "Echelon", "demo key", "" ],
+ [ "Echo Test", "demo key", "echo@example.net" ],
+ [ "Eve", "demo key", "" ] ], 1 ],
+ [ "56D33268F7FE693FBB594762D4BF57F37372E243", "0A32EE79EE45198E",
+ [ [ "Foxtrot Test", "demo key", "foxtrot@example.net" ] ], 1 ],
+ [ "C9C07DCC6621B9FB8D071B1D168410A48FC282E6", "247491CC9DCAD354",
+ [ [ "Golf Test", "demo key", "golf@example.net" ] ], 1 ],
+ [ "9E91CBB11E4D4135583EF90513DB965534C6E3F1", "76E26537D622AD0A",
+ [ [ "Hotel Test", "demo key", "hotel@example.net" ] ], 1 ],
+ [ "CD538D6CC9FB3D745ECDA5201FE8FC6F04259677", "C1C8EFDE61F76C73",
+ [ [ "India Test", "demo key", "india@example.net" ] ], 1 ],
+ [ "F8F1EDC73995AB739AD54B380C820C71D2699313", "BD0B108735F8F136",
+ [ [ "Juliet Test", "demo key", "juliet@example.net" ] ], 1 ],
+ [ "3FD11083779196C2ECDD9594AD1B0FAD43C2D0C7", "86CBB34A9AF64D02",
+ [ [ "Kilo Test", "demo key", "kilo@example.net" ] ], 1 ],
+ [ "1DDD28CEF714F5B03B8C246937CAB51FB79103F8", "0363B449FE56350C",
+ [ [ "Lima Test", "demo key", "lima@example.net" ] ], 1 ],
+ [ "2686AA191A278013992C72EBBE794852BE5CF886", "5F600A834F31EAE8",
+ [ [ "Mallory", "demo key", "" ],
+ [ "Mike Test", "demo key", "mike@example.net" ] ], 1 ],
+ [ "5AB9D6D7BAA1C95B3BAA3D9425B00FD430CEC684", "4C1D63308B70E472",
+ [ [ "November Test", "demo key", "november@example.net" ] ], 1 ],
+ [ "43929E89F8F79381678CAE515F6356BA6D9732AC", "FF0785712681619F",
+ [ [ "Oscar Test", "demo key", "oscar@example.net" ] ], 1 ],
+ [ "6FAA9C201E5E26DCBAEC39FD5D15E01D3FF13206", "2764E18263330D9C",
+ [ [ "Papa test", "demo key", "papa@example.net" ] ], 1 ],
+ [ "A7969DA1C3297AA96D49843F1C67EC133C661C84", "6CDCFC44A029ACF4",
+ [ [ "Quebec Test", "demo key", "quebec@example.net" ] ], 1 ],
+ [ "38FBE1E4BF6A5E1242C8F6A13BDBEDB1777FBED3", "9FAB805A11D102EA",
+ [ [ "Romeo Test", "demo key", "romeo@example.net" ] ], 1 ],
+ [ "045B2334ADD69FC221076841A5E67F7FA3AE3EA1", "93B88B0F0F1B50B4",
+ [ [ "Sierra Test", "demo key", "sierra@example.net" ] ], 1 ],
+ [ "ECAC774F4EEEB0620767044A58CB9A4C85A81F38", "97B60E01101C0402",
+ [ [ "Tango Test", "demo key", "tango@example.net" ] ], 1 ],
+ [ "0DBCAD3F08843B9557C6C4D4A94C0F75653244D6", "93079B915522BDB9",
+ [ [ "Uniform Test", "demo key", "uniform@example.net" ] ], 1 ],
+ [ "E8143C489C8D41124DC40D0B47AF4B6961F04784", "04071FB807287134",
+ [ [ "Victor Test", "demo key", "victor@example.org" ] ], 1 ],
+ [ "E8D6C90B683B0982BD557A99DEF0F7B8EC67DBDE", "D7FBB421FD6E27F6",
+ [ [ "Whisky Test", "demo key", "whisky@example.net" ] ], 3,
+ check_whisky ],
+ [ "04C1DF62EFA0EBB00519B06A8979A6C5567FB34A", "5CC6F87F41E408BE",
+ [ [ "XRay Test", "demo key", "xray@example.net" ] ], 1 ],
+ [ "ED9B316F78644A58D042655A9EEF34CD4B11B25F", "5ADFD255F7B080AD",
+ [ [ "Yankee Test", "demo key", "yankee@example.net" ] ], 1 ],
+ [ "23FD347A419429BACCD5E72D6BC4778054ACD246", "EF9DC276A172C881",
+ [ [ "Zulu Test", "demo key", "zulu@example.net" ] ], 1 ],
+]
+
+def check_global(key, uids, n_subkeys):
+ assert not key.revoked, "Key unexpectedly revoked"
+ assert not key.expired, "Key unexpectedly expired"
+ assert not key.disabled, "Key unexpectedly disabled"
+ assert not key.invalid, "Key unexpectedly invalid"
+ assert key.can_sign, "Key unexpectedly unusable for signing"
+ assert key.can_certify, "Key unexpectedly unusable for certifications"
+ assert not key.secret, "Key unexpectedly secret"
+ assert not key.protocol != constants.PROTOCOL_OpenPGP, \
+ "Key has unexpected protocol: {}".format(key.protocol)
+ assert not key.issuer_serial, \
+ "Key unexpectedly carries issuer serial: {}".format(key.issuer_serial)
+ assert not key.issuer_name, \
+ "Key unexpectedly carries issuer name: {}".format(key.issuer_name)
+ assert not key.chain_id, \
+ "Key unexpectedly carries chain ID: {}".format(key.chain_id)
+
+ # Only key Alfa is trusted
+ assert key.uids[0].name == 'Alfa Test' \
+ or key.owner_trust == constants.VALIDITY_UNKNOWN, \
+ "Key has unexpected owner trust: {}".format(key.owner_trust)
+ assert key.uids[0].name != 'Alfa Test' \
+ or key.owner_trust == constants.VALIDITY_ULTIMATE, \
+ "Key has unexpected owner trust: {}".format(key.owner_trust)
+
+ assert len(key.subkeys) - 1 == n_subkeys, \
+ "Key `{}' has unexpected number of subkeys".format(uids[0][0])
+
+
+def check_subkey(fpr, which, subkey):
+ assert not subkey.revoked, which + " key unexpectedly revoked"
+ assert not subkey.expired, which + " key unexpectedly expired"
+ assert not subkey.disabled, which + " key unexpectedly disabled"
+ assert not subkey.invalid, which + " key unexpectedly invalid"
+
+ if which == "Primary":
+ assert not subkey.can_encrypt, \
+ which + " key unexpectedly usable for encryption"
+ assert subkey.can_sign, \
+ which + " key unexpectedly unusable for signing"
+ assert subkey.can_certify, \
+ which + " key unexpectedly unusable for certifications"
+ else:
+ assert subkey.can_encrypt, \
+ which + " key unexpectedly unusable for encryption"
+ assert not subkey.can_sign, \
+ which + " key unexpectedly usable for signing"
+ assert not subkey.can_certify, \
+ which + " key unexpectedly usable for certifications"
+
+ assert not subkey.secret, which + " key unexpectedly secret"
+ assert not subkey.is_cardkey, "Public key marked as card key"
+ assert not subkey.card_number, "Public key with card number set"
+ assert not subkey.pubkey_algo != (constants.PK_DSA if which == "Primary"
+ else constants.PK_ELG_E), \
+ which + " key has unexpected public key algo: {}".\
+ format(subkey.pubkey_algo)
+ assert subkey.length == 1024, \
+ which + " key has unexpected length: {}".format(subkey.length)
+ assert fpr.endswith(subkey.keyid), \
+ which + " key has unexpected key ID: {}".format(subkey.keyid)
+ assert which == "Secondary" or subkey.fpr == fpr, \
+ which + " key has unexpected fingerprint: {}".format(subkey.fpr)
+ assert not subkey.expires, \
+ which + " key unexpectedly expires: {}".format(subkey.expires)
+
+def check_uid(which, ref, uid):
+ assert not uid.revoked, which + " user ID unexpectedly revoked"
+ assert not uid.invalid, which + " user ID unexpectedly invalid"
+ assert uid.validity == (constants.VALIDITY_UNKNOWN
+ if uid.name.split()[0]
+ not in {'Alfa', 'Alpha', 'Alice'} else
+ constants.VALIDITY_ULTIMATE), \
+ which + " user ID has unexpectedly validity: {}".format(uid.validity)
+ assert not uid.signatures, which + " user ID unexpectedly signed"
+ assert uid.name == ref[0], \
+ "Unexpected name in {} user ID: {!r}".format(which.lower(), uid.name)
+ assert uid.comment == ref[1], \
+ "Unexpected comment in {} user ID: {!r}".format(which.lower(),
+ uid.comment)
+ assert uid.email == ref[2], \
+ "Unexpected email in {} user ID: {!r}".format(which.lower(), uid.email)
+
+i = 0
+c.op_keylist_start(None, False)
+key = c.op_keylist_next ()
+while key:
+ try:
+ if len(keys[i]) == 4:
+ fpr, sec_keyid, uids, n_subkeys = keys[i]
+ misc_check = None
+ else:
+ fpr, sec_keyid, uids, n_subkeys, misc_check = keys[i]
+ except IndexError:
+ # There are more keys. We don't check for that.
+ break
+
+ # Global key flags.
+ check_global(key, uids, n_subkeys)
+ check_subkey(fpr, "Primary", key.subkeys[0])
+ check_subkey(sec_keyid, "Secondary", key.subkeys[1])
+
+ assert len(key.uids) == len(uids)
+ check_uid("First", uids[0], key.uids[0])
+ if len(key.uids) > 1:
+ check_uid("Second", uids[1], key.uids[1])
+ if len(key.uids) > 2:
+ check_uid("Third", uids[2], key.uids[2])
+
+ if misc_check:
+ misc_check (uids[0][0], key)
+ key = c.op_keylist_next ()
+ i += 1
+
+c.op_keylist_end()
+result = c.op_keylist_result()
+assert not result.truncated, "Key listing unexpectedly truncated"
+
+
+for i, key in enumerate(c.keylist()):
+ try:
+ if len(keys[i]) == 4:
+ fpr, sec_keyid, uids, n_subkeys = keys[i]
+ misc_check = None
+ else:
+ fpr, sec_keyid, uids, n_subkeys, misc_check = keys[i]
+ except IndexError:
+ # There are more keys. We don't check for that.
+ break
+
+ # Global key flags.
+ check_global(key, uids, n_subkeys)
+ check_subkey(fpr, "Primary", key.subkeys[0])
+ check_subkey(sec_keyid, "Secondary", key.subkeys[1])
+
+ assert len(key.uids) == len(uids)
+ check_uid("First", uids[0], key.uids[0])
+ if len(key.uids) > 1:
+ check_uid("Second", uids[1], key.uids[1])
+ if len(key.uids) > 2:
+ check_uid("Third", uids[2], key.uids[2])
+
+ if misc_check:
+ misc_check (uids[0][0], key)
diff --git a/lang/python/tests/t-protocol-assuan.py b/lang/python/tests/t-protocol-assuan.py
new file mode 100755
index 0000000..172c7d0
--- /dev/null
+++ b/lang/python/tests/t-protocol-assuan.py
@@ -0,0 +1,69 @@
+#!/usr/bin/env python
+
+# Copyright (C) 2016 g10 Code GmbH
+#
+# This file is part of GPGME.
+#
+# GPGME is free software; you can redistribute it and/or modify it
+# under the terms of the GNU General Public License as published by
+# the Free Software Foundation; either version 2 of the License, or
+# (at your option) any later version.
+#
+# GPGME is distributed in the hope that it will be useful, but WITHOUT
+# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
+# or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General
+# Public License for more details.
+#
+# You should have received a copy of the GNU Lesser General Public
+# License along with this program; if not, see <http://www.gnu.org/licenses/>.
+
+from __future__ import absolute_import, print_function, unicode_literals
+del absolute_import, print_function, unicode_literals
+
+import pyme
+
+with pyme.Context(protocol=pyme.constants.PROTOCOL_ASSUAN) as c:
+ # Do nothing.
+ c.assuan_transact('nop')
+ c.assuan_transact('NOP')
+ c.assuan_transact(['NOP'])
+
+ err = c.assuan_transact('idontexist')
+ assert err.getsource() == pyme.errors.SOURCE_GPGAGENT
+ assert err.getcode() == pyme.errors.ASS_UNKNOWN_CMD
+
+ # Invoke the pinentry to get a confirmation.
+ c.assuan_transact(['GET_CONFIRMATION', 'Hello there'])
+
+ data = []
+ def data_cb(line):
+ data.append(line)
+
+ err = c.assuan_transact(['GETINFO', 'version'], data_cb=data_cb)
+ assert not err
+ assert len(data) == 1
+
+ data = []
+ err = c.assuan_transact(['GETINFO', 's2k_count'], data_cb=data_cb)
+ if not err:
+ assert len(data) == 1
+ assert int(data[0]) > 0
+
+ # XXX HELP sends status lines if we could use ASSUAN_CONVEY_COMMENTS.
+
+ status = []
+ def status_cb(line, args):
+ status.append((line, args))
+
+ alphas_grip = '76F7E2B35832976B50A27A282D9B87E44577EB66'
+ err = c.assuan_transact(['KEYINFO', alphas_grip], status_cb=status_cb)
+ if not err:
+ assert len(status) == 1
+ line, args = status[0]
+ assert line.startswith('KEYINFO')
+ assert args.startswith(alphas_grip)
+
+ # XXX: test these callbacks, e.g. using PRESET_PASSPHRASE
+ # XXX: once issue2428 is resolved
+ def inq_cb(name, args):
+ print("inq_cb", name, args)
diff --git a/lang/python/tests/t-sig-notation.py b/lang/python/tests/t-sig-notation.py
new file mode 100755
index 0000000..777bc0b
--- /dev/null
+++ b/lang/python/tests/t-sig-notation.py
@@ -0,0 +1,79 @@
+#!/usr/bin/env python
+
+# Copyright (C) 2016 g10 Code GmbH
+#
+# This file is part of GPGME.
+#
+# GPGME is free software; you can redistribute it and/or modify it
+# under the terms of the GNU General Public License as published by
+# the Free Software Foundation; either version 2 of the License, or
+# (at your option) any later version.
+#
+# GPGME is distributed in the hope that it will be useful, but WITHOUT
+# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
+# or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General
+# Public License for more details.
+#
+# You should have received a copy of the GNU Lesser General Public
+# License along with this program; if not, see <http://www.gnu.org/licenses/>.
+
+from __future__ import absolute_import, print_function, unicode_literals
+del absolute_import, print_function, unicode_literals
+
+import os
+from pyme import core, constants
+import support
+
+expected_notations = {
+ "laughing@me": ("Just Squeeze Me", constants.SIG_NOTATION_HUMAN_READABLE),
+ "preferred-email-encoding@pgp.com": ("pgpmime",
+ constants.SIG_NOTATION_HUMAN_READABLE
+ | constants.SIG_NOTATION_CRITICAL),
+ None: ("http://www.gnu.org/policy/", 0),
+}
+
+# GnuPG prior to 2.1.13 did not report the critical flag correctly.
+with core.Context() as c:
+ version = c.engine_info.version
+ have_correct_sig_data = not (version.startswith("1.")
+ or version == "2.1.1"
+ or (version.startswith("2.1.1")
+ and version[5] < '3'))
+
+def check_result(result):
+ assert len(result.signatures) == 1, "Unexpected number of signatures"
+ sig = result.signatures[0]
+ assert len(sig.notations) == len(expected_notations)
+
+ for r in sig.notations:
+ assert not 'name_len' in dir(r)
+ assert not 'value_len' in dir(r)
+ assert r.name in expected_notations
+ value, flags = expected_notations.pop(r.name)
+
+ assert r.value == value, \
+ "Expected {!r}, got {!r}".format(value, r.value)
+ assert r.human_readable \
+ == bool(flags&constants.SIG_NOTATION_HUMAN_READABLE)
+ assert r.critical \
+ == (bool(flags&constants.SIG_NOTATION_CRITICAL)
+ if have_correct_sig_data else False)
+
+ assert len(expected_notations) == 0
+
+support.init_gpgme(constants.PROTOCOL_OpenPGP)
+
+source = core.Data("Hallo Leute\n")
+signed = core.Data()
+
+c = core.Context()
+for name, (value, flags) in expected_notations.items():
+ c.sig_notation_add(name, value, flags)
+
+c.op_sign(source, signed, constants.SIG_MODE_NORMAL)
+
+signed.seek(0, os.SEEK_SET)
+sink = core.Data()
+c.op_verify(signed, None, sink)
+result = c.op_verify_result()
+check_result(result)
diff --git a/lang/python/tests/t-sign.py b/lang/python/tests/t-sign.py
new file mode 100755
index 0000000..b0e211a
--- /dev/null
+++ b/lang/python/tests/t-sign.py
@@ -0,0 +1,122 @@
+#!/usr/bin/env python
+
+# Copyright (C) 2016 g10 Code GmbH
+#
+# This file is part of GPGME.
+#
+# GPGME is free software; you can redistribute it and/or modify it
+# under the terms of the GNU General Public License as published by
+# the Free Software Foundation; either version 2 of the License, or
+# (at your option) any later version.
+#
+# GPGME is distributed in the hope that it will be useful, but WITHOUT
+# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
+# or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General
+# Public License for more details.
+#
+# You should have received a copy of the GNU Lesser General Public
+# License along with this program; if not, see <http://www.gnu.org/licenses/>.
+
+from __future__ import absolute_import, print_function, unicode_literals
+del absolute_import, print_function, unicode_literals
+
+import os
+import pyme
+from pyme import core, constants
+import support
+
+def fail(msg):
+ raise RuntimeError(msg)
+
+def check_result(r, typ):
+ if r.invalid_signers:
+ fail("Invalid signer found: {}".format(r.invalid_signers.fpr))
+
+ if len(r.signatures) != 1:
+ fail("Unexpected number of signatures created")
+
+ signature = r.signatures[0]
+ if signature.type != typ:
+ fail("Wrong type of signature created")
+
+ if signature.pubkey_algo != constants.PK_DSA:
+ fail("Wrong pubkey algorithm reported: {}".format(
+ signature.pubkey_algo))
+
+ if signature.hash_algo != constants.MD_SHA1:
+ fail("Wrong hash algorithm reported: {}".format(
+ signature.hash_algo))
+
+ if signature.sig_class != 1:
+ fail("Wrong signature class reported: {}".format(
+ signature.sig_class))
+
+ if signature.fpr != "A0FF4590BB6122EDEF6E3C542D727CC768697734":
+ fail("Wrong fingerprint reported: {}".format(signature.fpr))
+
+
+support.init_gpgme(constants.PROTOCOL_OpenPGP)
+c = core.Context()
+c.set_textmode(True)
+c.set_armor(True)
+
+source = core.Data("Hallo Leute\n")
+sink = core.Data()
+
+c.op_sign(source, sink, constants.SIG_MODE_NORMAL)
+
+result = c.op_sign_result()
+check_result(result, constants.SIG_MODE_NORMAL)
+support.print_data(sink)
+
+# Now a detached signature.
+source.seek(0, os.SEEK_SET)
+sink = core.Data()
+
+c.op_sign(source, sink, constants.SIG_MODE_DETACH)
+
+result = c.op_sign_result()
+check_result(result, constants.SIG_MODE_DETACH)
+support.print_data(sink)
+
+# And finally a cleartext signature. */
+source.seek(0, os.SEEK_SET)
+sink = core.Data()
+
+c.op_sign(source, sink, constants.SIG_MODE_CLEAR)
+
+result = c.op_sign_result()
+check_result(result, constants.SIG_MODE_CLEAR)
+support.print_data(sink)
+
+# Idiomatic interface.
+with pyme.Context(armor=True, textmode=True) as c:
+ message = "Hallo Leute\n".encode()
+ signed, _ = c.sign(message)
+ assert len(signed) > 0
+ assert signed.find(b'BEGIN PGP MESSAGE') > 0, 'Message not found'
+
+ signed, _ = c.sign(message, mode=pyme.constants.SIG_MODE_DETACH)
+ assert len(signed) > 0
+ assert signed.find(b'BEGIN PGP SIGNATURE') > 0, 'Signature not found'
+
+ signed, _ = c.sign(message, mode=pyme.constants.SIG_MODE_CLEAR)
+ assert len(signed) > 0
+ assert signed.find(b'BEGIN PGP SIGNED MESSAGE') > 0, 'Message not found'
+ assert signed.find(message) > 0, 'Message content not found'
+ assert signed.find(b'BEGIN PGP SIGNATURE') > 0, 'Signature not found'
+
+with pyme.Context() as c:
+ message = "Hallo Leute\n".encode()
+
+ c.signers = [c.get_key(support.sign_only, True)]
+ c.sign(message)
+
+ c.signers = [c.get_key(support.encrypt_only, True)]
+ try:
+ c.sign(message)
+ except pyme.errors.InvalidSigners as e:
+ assert len(e.signers) == 1
+ assert support.encrypt_only.endswith(e.signers[0].fpr)
+ else:
+ assert False, "Expected an InvalidSigners error, got none"
diff --git a/lang/python/tests/t-signers.py b/lang/python/tests/t-signers.py
new file mode 100755
index 0000000..11403af
--- /dev/null
+++ b/lang/python/tests/t-signers.py
@@ -0,0 +1,98 @@
+#!/usr/bin/env python
+
+# Copyright (C) 2016 g10 Code GmbH
+#
+# This file is part of GPGME.
+#
+# GPGME is free software; you can redistribute it and/or modify it
+# under the terms of the GNU General Public License as published by
+# the Free Software Foundation; either version 2 of the License, or
+# (at your option) any later version.
+#
+# GPGME is distributed in the hope that it will be useful, but WITHOUT
+# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
+# or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General
+# Public License for more details.
+#
+# You should have received a copy of the GNU Lesser General Public
+# License along with this program; if not, see <http://www.gnu.org/licenses/>.
+
+from __future__ import absolute_import, print_function, unicode_literals
+del absolute_import, print_function, unicode_literals
+
+import pyme
+from pyme import core, constants
+import support
+
+def fail(msg):
+ raise RuntimeError(msg)
+
+def check_result(r, typ):
+ if r.invalid_signers:
+ fail("Invalid signer found: {}".format(r.invalid_signers.fpr))
+
+ if len(r.signatures) != 2:
+ fail("Unexpected number of signatures created")
+
+ for signature in r.signatures:
+ if signature.type != typ:
+ fail("Wrong type of signature created")
+
+ if signature.pubkey_algo != constants.PK_DSA:
+ fail("Wrong pubkey algorithm reported: {}".format(
+ signature.pubkey_algo))
+
+ if signature.hash_algo != constants.MD_SHA1:
+ fail("Wrong hash algorithm reported: {}".format(
+ signature.hash_algo))
+
+ if signature.sig_class != 1:
+ fail("Wrong signature class reported: got {}, want {}".format(
+ signature.sig_class, 1))
+
+ if signature.fpr not in ("A0FF4590BB6122EDEF6E3C542D727CC768697734",
+ "23FD347A419429BACCD5E72D6BC4778054ACD246"):
+ fail("Wrong fingerprint reported: {}".format(signature.fpr))
+
+
+support.init_gpgme(constants.PROTOCOL_OpenPGP)
+c = core.Context()
+c.set_textmode(True)
+c.set_armor(True)
+
+keys = []
+c.op_keylist_start('', True)
+keys.append(c.op_keylist_next())
+keys.append(c.op_keylist_next())
+c.op_keylist_end()
+
+c.signers_add(keys[0])
+c.signers_add(keys[1])
+
+for mode in (constants.SIG_MODE_NORMAL, constants.SIG_MODE_DETACH,
+ constants.SIG_MODE_CLEAR):
+ source = core.Data("Hallo Leute\n")
+ sink = core.Data()
+
+ c.op_sign(source, sink, mode)
+
+ result = c.op_sign_result()
+ check_result(result, mode)
+ support.print_data(sink)
+
+# Idiomatic interface.
+with pyme.Context(armor=True, textmode=True, signers=keys) as c:
+ message = "Hallo Leute\n".encode()
+ signed, result = c.sign(message)
+ check_result(result, constants.SIG_MODE_NORMAL)
+ assert signed.find(b'BEGIN PGP MESSAGE') > 0, 'Message not found'
+
+ signed, result = c.sign(message, mode=constants.SIG_MODE_DETACH)
+ check_result(result, constants.SIG_MODE_DETACH)
+ assert signed.find(b'BEGIN PGP SIGNATURE') > 0, 'Signature not found'
+
+ signed, result = c.sign(message, mode=constants.SIG_MODE_CLEAR)
+ check_result(result, constants.SIG_MODE_CLEAR)
+ assert signed.find(b'BEGIN PGP SIGNED MESSAGE') > 0, 'Message not found'
+ assert signed.find(message) > 0, 'Message content not found'
+ assert signed.find(b'BEGIN PGP SIGNATURE') > 0, 'Signature not found'
diff --git a/lang/python/tests/t-trustlist.py b/lang/python/tests/t-trustlist.py
new file mode 100755
index 0000000..4253bd7
--- /dev/null
+++ b/lang/python/tests/t-trustlist.py
@@ -0,0 +1,43 @@
+#!/usr/bin/env python
+
+# Copyright (C) 2016 g10 Code GmbH
+#
+# This file is part of GPGME.
+#
+# GPGME is free software; you can redistribute it and/or modify it
+# under the terms of the GNU General Public License as published by
+# the Free Software Foundation; either version 2 of the License, or
+# (at your option) any later version.
+#
+# GPGME is distributed in the hope that it will be useful, but WITHOUT
+# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
+# or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General
+# Public License for more details.
+#
+# You should have received a copy of the GNU Lesser General Public
+# License along with this program; if not, see <http://www.gnu.org/licenses/>.
+
+from __future__ import absolute_import, print_function, unicode_literals
+del absolute_import, print_function, unicode_literals
+
+from pyme import core, constants
+import support
+
+support.init_gpgme(constants.PROTOCOL_OpenPGP)
+c = core.Context()
+
+def dump_item(item):
+ print("l={} k={} t={} o={} v={} u={}".format(
+ item.level, item.keyid, item.type, item.owner_trust,
+ item.validity, item.name))
+
+c.op_trustlist_start("alice", 0)
+while True:
+ item = c.op_trustlist_next()
+ if not item:
+ break
+ dump_item(item)
+c.op_trustlist_end()
+
+for item in c.op_trustlist_all("alice", 0):
+ dump_item(item)
diff --git a/lang/python/tests/t-verify.py b/lang/python/tests/t-verify.py
new file mode 100755
index 0000000..39f6176
--- /dev/null
+++ b/lang/python/tests/t-verify.py
@@ -0,0 +1,195 @@
+#!/usr/bin/env python
+
+# Copyright (C) 2016 g10 Code GmbH
+#
+# This file is part of GPGME.
+#
+# GPGME is free software; you can redistribute it and/or modify it
+# under the terms of the GNU General Public License as published by
+# the Free Software Foundation; either version 2 of the License, or
+# (at your option) any later version.
+#
+# GPGME is distributed in the hope that it will be useful, but WITHOUT
+# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
+# or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General
+# Public License for more details.
+#
+# You should have received a copy of the GNU Lesser General Public
+# License along with this program; if not, see <http://www.gnu.org/licenses/>.
+
+from __future__ import absolute_import, print_function, unicode_literals
+del absolute_import, print_function, unicode_literals
+
+import sys
+import os
+import pyme
+from pyme import core, constants, errors
+import support
+
+test_text1 = b"Just GNU it!\n"
+test_text1f= b"Just GNU it?\n"
+test_sig1 = b"""-----BEGIN PGP SIGNATURE-----
+
+iN0EABECAJ0FAjoS+i9FFIAAAAAAAwA5YmFyw7bDpMO8w58gZGFzIHdhcmVuIFVt
+bGF1dGUgdW5kIGpldHp0IGVpbiBwcm96ZW50JS1aZWljaGVuNRSAAAAAAAgAJGZv
+b2Jhci4xdGhpcyBpcyBhIG5vdGF0aW9uIGRhdGEgd2l0aCAyIGxpbmVzGhpodHRw
+Oi8vd3d3Lmd1Lm9yZy9wb2xpY3kvAAoJEC1yfMdoaXc0JBIAoIiLlUsvpMDOyGEc
+dADGKXF/Hcb+AKCJWPphZCphduxSvrzH0hgzHdeQaA==
+=nts1
+-----END PGP SIGNATURE-----
+"""
+
+test_sig2 = b"""-----BEGIN PGP MESSAGE-----
+
+owGbwMvMwCSoW1RzPCOz3IRxjXQSR0lqcYleSUWJTZOvjVdpcYmCu1+oQmaJIleH
+GwuDIBMDGysTSIqBi1MApi+nlGGuwDeHao53HBr+FoVGP3xX+kvuu9fCMJvl6IOf
+y1kvP4y+8D5a11ang0udywsA
+=Crq6
+-----END PGP MESSAGE-----
+"""
+
+# A message with a prepended but unsigned plaintext packet.
+double_plaintext_sig = b"""-----BEGIN PGP MESSAGE-----
+
+rDRiCmZvb2Jhci50eHRF4pxNVGhpcyBpcyBteSBzbmVha3kgcGxhaW50ZXh0IG1l
+c3NhZ2UKowGbwMvMwCSoW1RzPCOz3IRxTWISa6JebnG666MFD1wzSzJSixQ81XMV
+UlITUxTyixRyKxXKE0uSMxQyEosVikvyCwpSU/S4FNCArq6Ce1F+aXJGvoJvYlGF
+erFCTmJxiUJ5flFKMVeHGwuDIBMDGysTyA4GLk4BmO036xgWzMgzt9V85jCtfDFn
+UqVooWlGXHwNw/xg/fVzt9VNbtjtJ/fhUqYo0/LyCGEA
+=6+AK
+-----END PGP MESSAGE-----
+"""
+
+def check_result(result, summary, validity, fpr, status, notation):
+ assert len(result.signatures) == 1, "Unexpected number of signatures"
+ sig = result.signatures[0]
+ assert sig.summary == summary, \
+ "Unexpected signature summary: {}, want: {}".format(sig.summary,
+ summary)
+ assert sig.fpr == fpr
+ assert errors.GPGMEError(sig.status).getcode() == status
+
+ if notation:
+ expected_notations = {
+ "bar": (b"\xc3\xb6\xc3\xa4\xc3\xbc\xc3\x9f" +
+ b" das waren Umlaute und jetzt ein prozent%-Zeichen"
+ if sys.version_info[0] < 3 else
+ b"\xc3\xb6\xc3\xa4\xc3\xbc\xc3\x9f".decode() +
+ " das waren Umlaute und jetzt ein prozent%-Zeichen"),
+ "foobar.1": "this is a notation data with 2 lines",
+ None: "http://www.gu.org/policy/",
+ }
+ assert len(sig.notations) == len(expected_notations)
+
+ for r in sig.notations:
+ assert not 'name_len' in dir(r)
+ assert not 'value_len' in dir(r)
+ assert r.name in expected_notations
+ assert r.value == expected_notations[r.name], \
+ "Expected {!r}, got {!r}".format(expected_notations[r.name],
+ r.value)
+ expected_notations.pop(r.name)
+
+ assert len(expected_notations) == 0
+
+ assert not sig.wrong_key_usage
+ assert sig.validity == validity, \
+ "Unexpected signature validity: {}, want: {}".format(
+ sig.validity, validity)
+ assert errors.GPGMEError(sig.validity_reason).getcode() == errors.NO_ERROR
+
+
+support.init_gpgme(constants.PROTOCOL_OpenPGP)
+c = core.Context()
+c.set_armor(True)
+
+# Checking a valid message.
+text = core.Data(test_text1)
+sig = core.Data(test_sig1)
+c.op_verify(sig, text, None)
+result = c.op_verify_result()
+check_result(result, constants.SIGSUM_VALID | constants.SIGSUM_GREEN,
+ constants.VALIDITY_FULL,
+ "A0FF4590BB6122EDEF6E3C542D727CC768697734",
+ errors.NO_ERROR, True)
+
+
+# Checking a manipulated message.
+text = core.Data(test_text1f)
+sig.seek(0, os.SEEK_SET)
+c.op_verify(sig, text, None)
+result = c.op_verify_result()
+check_result(result, constants.SIGSUM_RED, constants.VALIDITY_UNKNOWN,
+ "2D727CC768697734", errors.BAD_SIGNATURE, False)
+
+# Checking a normal signature.
+text = core.Data()
+sig = core.Data(test_sig2)
+c.op_verify(sig, None, text)
+result = c.op_verify_result()
+check_result(result, constants.SIGSUM_VALID | constants.SIGSUM_GREEN,
+ constants.VALIDITY_FULL,
+ "A0FF4590BB6122EDEF6E3C542D727CC768697734",
+ errors.NO_ERROR, False)
+
+# Checking an invalid message.
+text = core.Data()
+sig = core.Data(double_plaintext_sig)
+try:
+ c.op_verify(sig, None, text)
+except Exception as e:
+ assert type(e) == errors.GPGMEError
+ assert e.getcode() == errors.BAD_DATA
+else:
+ assert False, "Expected an error but got none."
+
+
+# Idiomatic interface.
+with pyme.Context(armor=True) as c:
+ # Checking a valid message.
+ _, result = c.verify(test_text1, test_sig1)
+ check_result(result, constants.SIGSUM_VALID | constants.SIGSUM_GREEN,
+ constants.VALIDITY_FULL,
+ "A0FF4590BB6122EDEF6E3C542D727CC768697734",
+ errors.NO_ERROR, True)
+
+ # Checking a manipulated message.
+ try:
+ c.verify(test_text1f, test_sig1)
+ except errors.BadSignatures as e:
+ check_result(e.result, constants.SIGSUM_RED,
+ constants.VALIDITY_UNKNOWN,
+ "2D727CC768697734", errors.BAD_SIGNATURE, False)
+ else:
+ assert False, "Expected an error but got none."
+
+ # Checking a normal signature.
+ sig = core.Data(test_sig2)
+ data, result = c.verify(test_sig2)
+ check_result(result, constants.SIGSUM_VALID | constants.SIGSUM_GREEN,
+ constants.VALIDITY_FULL,
+ "A0FF4590BB6122EDEF6E3C542D727CC768697734",
+ errors.NO_ERROR, False)
+ assert data == test_text1
+
+ # Checking an invalid message.
+ try:
+ c.verify(double_plaintext_sig)
+ except errors.GPGMEError as e:
+ assert e.getcode() == errors.BAD_DATA
+ else:
+ assert False, "Expected an error but got none."
+
+ alpha = c.get_key("A0FF4590BB6122EDEF6E3C542D727CC768697734", False)
+ bob = c.get_key("D695676BDCEDCC2CDD6152BCFE180B1DA9E3B0B2", False)
+
+ # Checking a valid message.
+ c.verify(test_text1, test_sig1, verify=[alpha])
+
+ try:
+ c.verify(test_text1, test_sig1, verify=[alpha, bob])
+ except errors.MissingSignatures as e:
+ assert len(e.missing) == 1
+ assert e.missing[0] == bob
+ else:
+ assert False, "Expected an error, got none"
diff --git a/lang/python/tests/t-wait.py b/lang/python/tests/t-wait.py
new file mode 100755
index 0000000..b7d9a34
--- /dev/null
+++ b/lang/python/tests/t-wait.py
@@ -0,0 +1,45 @@
+#!/usr/bin/env python
+
+# Copyright (C) 2016 g10 Code GmbH
+#
+# This file is part of GPGME.
+#
+# GPGME is free software; you can redistribute it and/or modify it
+# under the terms of the GNU General Public License as published by
+# the Free Software Foundation; either version 2 of the License, or
+# (at your option) any later version.
+#
+# GPGME is distributed in the hope that it will be useful, but WITHOUT
+# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
+# or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General
+# Public License for more details.
+#
+# You should have received a copy of the GNU Lesser General Public
+# License along with this program; if not, see <http://www.gnu.org/licenses/>.
+
+from __future__ import absolute_import, print_function, unicode_literals
+del absolute_import, print_function, unicode_literals
+
+import time
+from pyme import core, constants, errors
+import support
+
+support.init_gpgme(constants.PROTOCOL_OpenPGP)
+c = core.Context()
+c.set_armor(True)
+
+# Checking a message without a signature.
+sig = core.Data("foo\n")
+text = core.Data()
+c.op_verify_start(sig, None, text)
+
+try:
+ while True:
+ err = c.wait(False)
+ if err:
+ break
+ time.sleep(0.1)
+except Exception as e:
+ assert e.getcode() == errors.NO_DATA
+else:
+ assert False, "Expected an error, got none"
diff --git a/lang/python/tests/t-wrapper.py b/lang/python/tests/t-wrapper.py
new file mode 100755
index 0000000..d260264
--- /dev/null
+++ b/lang/python/tests/t-wrapper.py
@@ -0,0 +1,25 @@
+#!/usr/bin/env python
+
+# Copyright (C) 2016 g10 Code GmbH
+#
+# This file is part of GPGME.
+#
+# GPGME is free software; you can redistribute it and/or modify it
+# under the terms of the GNU General Public License as published by
+# the Free Software Foundation; either version 2 of the License, or
+# (at your option) any later version.
+#
+# GPGME is distributed in the hope that it will be useful, but WITHOUT
+# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
+# or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General
+# Public License for more details.
+#
+# You should have received a copy of the GNU Lesser General Public
+# License along with this program; if not, see <http://www.gnu.org/licenses/>.
+
+from pyme import core
+
+d0 = core.Data()
+d0.seek # trigger on-demand-wrapping
+assert d0.seek == d0.seek, "Generated wrapper functions are not cached"
+assert hasattr(core.Data, 'seek'), "Generated wrapper functions are not shared"
diff --git a/lang/qt/Makefile.am b/lang/qt/Makefile.am
new file mode 100644
index 0000000..39eb55e
--- /dev/null
+++ b/lang/qt/Makefile.am
@@ -0,0 +1,23 @@
+# Makefile.am for GPGMEPP.
+# Copyright (C) 2016 Intevation GmbH
+#
+# This file is part of GPGMEPP.
+#
+# GPGME-CL 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.
+#
+# GPGME-CL is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU Lesser General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program; if not, write to the Free Software
+# Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
+# 02111-1307, USA
+
+SUBDIRS = src tests doc
+
+EXTRA_DIST = README
diff --git a/lang/qt/Makefile.in b/lang/qt/Makefile.in
new file mode 100644
index 0000000..d8b48d2
--- /dev/null
+++ b/lang/qt/Makefile.in
@@ -0,0 +1,709 @@
+# Makefile.in generated by automake 1.14.1 from Makefile.am.
+# @configure_input@
+
+# Copyright (C) 1994-2013 Free Software Foundation, Inc.
+
+# This Makefile.in is free software; the Free Software Foundation
+# gives unlimited permission to copy and/or distribute it,
+# with or without modifications, as long as this notice is preserved.
+
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY, to the extent permitted by law; without
+# even the implied warranty of MERCHANTABILITY or FITNESS FOR A
+# PARTICULAR PURPOSE.
+
+@SET_MAKE@
+
+# Makefile.am for GPGMEPP.
+# Copyright (C) 2016 Intevation GmbH
+#
+# This file is part of GPGMEPP.
+#
+# GPGME-CL 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.
+#
+# GPGME-CL is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU Lesser General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program; if not, write to the Free Software
+# Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
+# 02111-1307, USA
+VPATH = @srcdir@
+am__is_gnu_make = test -n '$(MAKEFILE_LIST)' && test -n '$(MAKELEVEL)'
+am__make_running_with_option = \
+ case $${target_option-} in \
+ ?) ;; \
+ *) echo "am__make_running_with_option: internal error: invalid" \
+ "target option '$${target_option-}' specified" >&2; \
+ exit 1;; \
+ esac; \
+ has_opt=no; \
+ sane_makeflags=$$MAKEFLAGS; \
+ if $(am__is_gnu_make); then \
+ sane_makeflags=$$MFLAGS; \
+ else \
+ case $$MAKEFLAGS in \
+ *\\[\ \ ]*) \
+ bs=\\; \
+ sane_makeflags=`printf '%s\n' "$$MAKEFLAGS" \
+ | sed "s/$$bs$$bs[$$bs $$bs ]*//g"`;; \
+ esac; \
+ fi; \
+ skip_next=no; \
+ strip_trailopt () \
+ { \
+ flg=`printf '%s\n' "$$flg" | sed "s/$$1.*$$//"`; \
+ }; \
+ for flg in $$sane_makeflags; do \
+ test $$skip_next = yes && { skip_next=no; continue; }; \
+ case $$flg in \
+ *=*|--*) continue;; \
+ -*I) strip_trailopt 'I'; skip_next=yes;; \
+ -*I?*) strip_trailopt 'I';; \
+ -*O) strip_trailopt 'O'; skip_next=yes;; \
+ -*O?*) strip_trailopt 'O';; \
+ -*l) strip_trailopt 'l'; skip_next=yes;; \
+ -*l?*) strip_trailopt 'l';; \
+ -[dEDm]) skip_next=yes;; \
+ -[JT]) skip_next=yes;; \
+ esac; \
+ case $$flg in \
+ *$$target_option*) has_opt=yes; break;; \
+ esac; \
+ done; \
+ test $$has_opt = yes
+am__make_dryrun = (target_option=n; $(am__make_running_with_option))
+am__make_keepgoing = (target_option=k; $(am__make_running_with_option))
+pkgdatadir = $(datadir)/@PACKAGE@
+pkgincludedir = $(includedir)/@PACKAGE@
+pkglibdir = $(libdir)/@PACKAGE@
+pkglibexecdir = $(libexecdir)/@PACKAGE@
+am__cd = CDPATH="$${ZSH_VERSION+.}$(PATH_SEPARATOR)" && cd
+install_sh_DATA = $(install_sh) -c -m 644
+install_sh_PROGRAM = $(install_sh) -c
+install_sh_SCRIPT = $(install_sh) -c
+INSTALL_HEADER = $(INSTALL_DATA)
+transform = $(program_transform_name)
+NORMAL_INSTALL = :
+PRE_INSTALL = :
+POST_INSTALL = :
+NORMAL_UNINSTALL = :
+PRE_UNINSTALL = :
+POST_UNINSTALL = :
+build_triplet = @build@
+host_triplet = @host@
+subdir = lang/qt
+DIST_COMMON = $(srcdir)/Makefile.in $(srcdir)/Makefile.am \
+ $(top_srcdir)/build-aux/mkinstalldirs README
+ACLOCAL_M4 = $(top_srcdir)/aclocal.m4
+am__aclocal_m4_deps = $(top_srcdir)/m4/ax_cxx_compile_stdcxx.m4 \
+ $(top_srcdir)/m4/ax_pkg_swig.m4 \
+ $(top_srcdir)/m4/ax_python_devel.m4 \
+ $(top_srcdir)/m4/glib-2.0.m4 $(top_srcdir)/m4/glibc21.m4 \
+ $(top_srcdir)/m4/gnupg-ttyname.m4 \
+ $(top_srcdir)/m4/gpg-error.m4 $(top_srcdir)/m4/libassuan.m4 \
+ $(top_srcdir)/m4/libtool.m4 $(top_srcdir)/m4/ltoptions.m4 \
+ $(top_srcdir)/m4/ltsugar.m4 $(top_srcdir)/m4/ltversion.m4 \
+ $(top_srcdir)/m4/lt~obsolete.m4 $(top_srcdir)/m4/pkg.m4 \
+ $(top_srcdir)/m4/qt.m4 $(top_srcdir)/acinclude.m4 \
+ $(top_srcdir)/configure.ac
+am__configure_deps = $(am__aclocal_m4_deps) $(CONFIGURE_DEPENDENCIES) \
+ $(ACLOCAL_M4)
+mkinstalldirs = $(SHELL) $(top_srcdir)/build-aux/mkinstalldirs
+CONFIG_HEADER = $(top_builddir)/config.h
+CONFIG_CLEAN_FILES =
+CONFIG_CLEAN_VPATH_FILES =
+AM_V_P = $(am__v_P_@AM_V@)
+am__v_P_ = $(am__v_P_@AM_DEFAULT_V@)
+am__v_P_0 = false
+am__v_P_1 = :
+AM_V_GEN = $(am__v_GEN_@AM_V@)
+am__v_GEN_ = $(am__v_GEN_@AM_DEFAULT_V@)
+am__v_GEN_0 = @echo " GEN " $@;
+am__v_GEN_1 =
+AM_V_at = $(am__v_at_@AM_V@)
+am__v_at_ = $(am__v_at_@AM_DEFAULT_V@)
+am__v_at_0 = @
+am__v_at_1 =
+SOURCES =
+DIST_SOURCES =
+RECURSIVE_TARGETS = all-recursive check-recursive cscopelist-recursive \
+ ctags-recursive dvi-recursive html-recursive info-recursive \
+ install-data-recursive install-dvi-recursive \
+ install-exec-recursive install-html-recursive \
+ install-info-recursive install-pdf-recursive \
+ install-ps-recursive install-recursive installcheck-recursive \
+ installdirs-recursive pdf-recursive ps-recursive \
+ tags-recursive uninstall-recursive
+am__can_run_installinfo = \
+ case $$AM_UPDATE_INFO_DIR in \
+ n|no|NO) false;; \
+ *) (install-info --version) >/dev/null 2>&1;; \
+ esac
+RECURSIVE_CLEAN_TARGETS = mostlyclean-recursive clean-recursive \
+ distclean-recursive maintainer-clean-recursive
+am__recursive_targets = \
+ $(RECURSIVE_TARGETS) \
+ $(RECURSIVE_CLEAN_TARGETS) \
+ $(am__extra_recursive_targets)
+AM_RECURSIVE_TARGETS = $(am__recursive_targets:-recursive=) TAGS CTAGS \
+ distdir
+am__tagged_files = $(HEADERS) $(SOURCES) $(TAGS_FILES) $(LISP)
+# Read a list of newline-separated strings from the standard input,
+# and print each of them once, without duplicates. Input order is
+# *not* preserved.
+am__uniquify_input = $(AWK) '\
+ BEGIN { nonempty = 0; } \
+ { items[$$0] = 1; nonempty = 1; } \
+ END { if (nonempty) { for (i in items) print i; }; } \
+'
+# Make sure the list of sources is unique. This is necessary because,
+# e.g., the same source file might be shared among _SOURCES variables
+# for different programs/libraries.
+am__define_uniq_tagged_files = \
+ list='$(am__tagged_files)'; \
+ unique=`for i in $$list; do \
+ if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \
+ done | $(am__uniquify_input)`
+ETAGS = etags
+CTAGS = ctags
+DIST_SUBDIRS = $(SUBDIRS)
+DISTFILES = $(DIST_COMMON) $(DIST_SOURCES) $(TEXINFOS) $(EXTRA_DIST)
+am__relativize = \
+ dir0=`pwd`; \
+ sed_first='s,^\([^/]*\)/.*$$,\1,'; \
+ sed_rest='s,^[^/]*/*,,'; \
+ sed_last='s,^.*/\([^/]*\)$$,\1,'; \
+ sed_butlast='s,/*[^/]*$$,,'; \
+ while test -n "$$dir1"; do \
+ first=`echo "$$dir1" | sed -e "$$sed_first"`; \
+ if test "$$first" != "."; then \
+ if test "$$first" = ".."; then \
+ dir2=`echo "$$dir0" | sed -e "$$sed_last"`/"$$dir2"; \
+ dir0=`echo "$$dir0" | sed -e "$$sed_butlast"`; \
+ else \
+ first2=`echo "$$dir2" | sed -e "$$sed_first"`; \
+ if test "$$first2" = "$$first"; then \
+ dir2=`echo "$$dir2" | sed -e "$$sed_rest"`; \
+ else \
+ dir2="../$$dir2"; \
+ fi; \
+ dir0="$$dir0"/"$$first"; \
+ fi; \
+ fi; \
+ dir1=`echo "$$dir1" | sed -e "$$sed_rest"`; \
+ done; \
+ reldir="$$dir2"
+ACLOCAL = @ACLOCAL@
+AMTAR = @AMTAR@
+AM_DEFAULT_VERBOSITY = @AM_DEFAULT_VERBOSITY@
+AR = @AR@
+AS = @AS@
+AUTOCONF = @AUTOCONF@
+AUTOHEADER = @AUTOHEADER@
+AUTOMAKE = @AUTOMAKE@
+AWK = @AWK@
+BUILD_FILEVERSION = @BUILD_FILEVERSION@
+BUILD_REVISION = @BUILD_REVISION@
+BUILD_TIMESTAMP = @BUILD_TIMESTAMP@
+CC = @CC@
+CCDEPMODE = @CCDEPMODE@
+CC_FOR_BUILD = @CC_FOR_BUILD@
+CFLAGS = @CFLAGS@
+CPP = @CPP@
+CPPFLAGS = @CPPFLAGS@
+CXX = @CXX@
+CXXCPP = @CXXCPP@
+CXXDEPMODE = @CXXDEPMODE@
+CXXFLAGS = @CXXFLAGS@
+CYGPATH_W = @CYGPATH_W@
+DEFS = @DEFS@
+DEPDIR = @DEPDIR@
+DLLTOOL = @DLLTOOL@
+DOXYGEN = @DOXYGEN@
+DSYMUTIL = @DSYMUTIL@
+DUMPBIN = @DUMPBIN@
+ECHO_C = @ECHO_C@
+ECHO_N = @ECHO_N@
+ECHO_T = @ECHO_T@
+EGREP = @EGREP@
+ENABLED_LANGUAGES = @ENABLED_LANGUAGES@
+EXEEXT = @EXEEXT@
+FGREP = @FGREP@
+GITLOG_TO_CHANGELOG = @GITLOG_TO_CHANGELOG@
+GLIBC21 = @GLIBC21@
+GLIB_CFLAGS = @GLIB_CFLAGS@
+GLIB_GENMARSHAL = @GLIB_GENMARSHAL@
+GLIB_LIBS = @GLIB_LIBS@
+GLIB_MKENUMS = @GLIB_MKENUMS@
+GOBJECT_QUERY = @GOBJECT_QUERY@
+GPGME_CONFIG_API_VERSION = @GPGME_CONFIG_API_VERSION@
+GPGME_CONFIG_AVAIL_LANG = @GPGME_CONFIG_AVAIL_LANG@
+GPGME_CONFIG_CFLAGS = @GPGME_CONFIG_CFLAGS@
+GPGME_CONFIG_HOST = @GPGME_CONFIG_HOST@
+GPGME_CONFIG_LIBS = @GPGME_CONFIG_LIBS@
+GPGME_QTTEST_CFLAGS = @GPGME_QTTEST_CFLAGS@
+GPGME_QTTEST_LIBS = @GPGME_QTTEST_LIBS@
+GPGME_QT_CFLAGS = @GPGME_QT_CFLAGS@
+GPGME_QT_LIBS = @GPGME_QT_LIBS@
+GPG_ERROR_CFLAGS = @GPG_ERROR_CFLAGS@
+GPG_ERROR_CONFIG = @GPG_ERROR_CONFIG@
+GPG_ERROR_LIBS = @GPG_ERROR_LIBS@
+GPG_ERROR_MT_CFLAGS = @GPG_ERROR_MT_CFLAGS@
+GPG_ERROR_MT_LIBS = @GPG_ERROR_MT_LIBS@
+GRAPHVIZ = @GRAPHVIZ@
+GREP = @GREP@
+HAVE_CXX11 = @HAVE_CXX11@
+HAVE_DOT = @HAVE_DOT@
+INSTALL = @INSTALL@
+INSTALL_DATA = @INSTALL_DATA@
+INSTALL_PROGRAM = @INSTALL_PROGRAM@
+INSTALL_SCRIPT = @INSTALL_SCRIPT@
+INSTALL_STRIP_PROGRAM = @INSTALL_STRIP_PROGRAM@
+LD = @LD@
+LDFLAGS = @LDFLAGS@
+LIBASSUAN_CFLAGS = @LIBASSUAN_CFLAGS@
+LIBASSUAN_CONFIG = @LIBASSUAN_CONFIG@
+LIBASSUAN_LIBS = @LIBASSUAN_LIBS@
+LIBGPGMEPP_LT_AGE = @LIBGPGMEPP_LT_AGE@
+LIBGPGMEPP_LT_CURRENT = @LIBGPGMEPP_LT_CURRENT@
+LIBGPGMEPP_LT_REVISION = @LIBGPGMEPP_LT_REVISION@
+LIBGPGME_LT_AGE = @LIBGPGME_LT_AGE@
+LIBGPGME_LT_CURRENT = @LIBGPGME_LT_CURRENT@
+LIBGPGME_LT_REVISION = @LIBGPGME_LT_REVISION@
+LIBOBJS = @LIBOBJS@
+LIBQGPGME_LT_AGE = @LIBQGPGME_LT_AGE@
+LIBQGPGME_LT_CURRENT = @LIBQGPGME_LT_CURRENT@
+LIBQGPGME_LT_REVISION = @LIBQGPGME_LT_REVISION@
+LIBS = @LIBS@
+LIBTOOL = @LIBTOOL@
+LIPO = @LIPO@
+LN_S = @LN_S@
+LTLIBOBJS = @LTLIBOBJS@
+MAINT = @MAINT@
+MAKEINFO = @MAKEINFO@
+MANIFEST_TOOL = @MANIFEST_TOOL@
+MKDIR_P = @MKDIR_P@
+MOC = @MOC@
+MOC2 = @MOC2@
+NEED__FILE_OFFSET_BITS = @NEED__FILE_OFFSET_BITS@
+NM = @NM@
+NMEDIT = @NMEDIT@
+OBJDUMP = @OBJDUMP@
+OBJEXT = @OBJEXT@
+OTOOL = @OTOOL@
+OTOOL64 = @OTOOL64@
+PACKAGE = @PACKAGE@
+PACKAGE_BUGREPORT = @PACKAGE_BUGREPORT@
+PACKAGE_NAME = @PACKAGE_NAME@
+PACKAGE_STRING = @PACKAGE_STRING@
+PACKAGE_TARNAME = @PACKAGE_TARNAME@
+PACKAGE_URL = @PACKAGE_URL@
+PACKAGE_VERSION = @PACKAGE_VERSION@
+PATH_SEPARATOR = @PATH_SEPARATOR@
+PKG_CONFIG = @PKG_CONFIG@
+PYTHON = @PYTHON@
+PYTHONS = @PYTHONS@
+PYTHON_CPPFLAGS = @PYTHON_CPPFLAGS@
+PYTHON_EXEC_PREFIX = @PYTHON_EXEC_PREFIX@
+PYTHON_EXTRA_LDFLAGS = @PYTHON_EXTRA_LDFLAGS@
+PYTHON_EXTRA_LIBS = @PYTHON_EXTRA_LIBS@
+PYTHON_LDFLAGS = @PYTHON_LDFLAGS@
+PYTHON_PLATFORM = @PYTHON_PLATFORM@
+PYTHON_PREFIX = @PYTHON_PREFIX@
+PYTHON_SITE_PKG = @PYTHON_SITE_PKG@
+PYTHON_VERSION = @PYTHON_VERSION@
+PYTHON_VERSIONS = @PYTHON_VERSIONS@
+QTCHOOSER = @QTCHOOSER@
+RANLIB = @RANLIB@
+RC = @RC@
+SED = @SED@
+SET_MAKE = @SET_MAKE@
+SHELL = @SHELL@
+STRIP = @STRIP@
+SWIG = @SWIG@
+SWIG_LIB = @SWIG_LIB@
+SYSROOT = @SYSROOT@
+VERSION = @VERSION@
+VERSION_NUMBER = @VERSION_NUMBER@
+abs_builddir = @abs_builddir@
+abs_srcdir = @abs_srcdir@
+abs_top_builddir = @abs_top_builddir@
+abs_top_srcdir = @abs_top_srcdir@
+ac_ct_AR = @ac_ct_AR@
+ac_ct_CC = @ac_ct_CC@
+ac_ct_CXX = @ac_ct_CXX@
+ac_ct_DUMPBIN = @ac_ct_DUMPBIN@
+am__include = @am__include@
+am__leading_dot = @am__leading_dot@
+am__quote = @am__quote@
+am__tar = @am__tar@
+am__untar = @am__untar@
+bindir = @bindir@
+build = @build@
+build_alias = @build_alias@
+build_cpu = @build_cpu@
+build_os = @build_os@
+build_vendor = @build_vendor@
+builddir = @builddir@
+datadir = @datadir@
+datarootdir = @datarootdir@
+docdir = @docdir@
+dvidir = @dvidir@
+emacs_local_vars_begin = @emacs_local_vars_begin@
+emacs_local_vars_end = @emacs_local_vars_end@
+emacs_local_vars_read_only = @emacs_local_vars_read_only@
+exec_prefix = @exec_prefix@
+host = @host@
+host_alias = @host_alias@
+host_cpu = @host_cpu@
+host_os = @host_os@
+host_vendor = @host_vendor@
+htmldir = @htmldir@
+includedir = @includedir@
+infodir = @infodir@
+install_sh = @install_sh@
+libdir = @libdir@
+libexecdir = @libexecdir@
+localedir = @localedir@
+localstatedir = @localstatedir@
+mandir = @mandir@
+mkdir_p = @mkdir_p@
+oldincludedir = @oldincludedir@
+pdfdir = @pdfdir@
+pkgpyexecdir = @pkgpyexecdir@
+pkgpythondir = @pkgpythondir@
+prefix = @prefix@
+program_transform_name = @program_transform_name@
+psdir = @psdir@
+pyexecdir = @pyexecdir@
+pythondir = @pythondir@
+sbindir = @sbindir@
+sharedstatedir = @sharedstatedir@
+srcdir = @srcdir@
+sysconfdir = @sysconfdir@
+target_alias = @target_alias@
+top_build_prefix = @top_build_prefix@
+top_builddir = @top_builddir@
+top_srcdir = @top_srcdir@
+SUBDIRS = src tests doc
+EXTRA_DIST = README
+all: all-recursive
+
+.SUFFIXES:
+$(srcdir)/Makefile.in: @MAINTAINER_MODE_TRUE@ $(srcdir)/Makefile.am $(am__configure_deps)
+ @for dep in $?; do \
+ case '$(am__configure_deps)' in \
+ *$$dep*) \
+ ( cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh ) \
+ && { if test -f $@; then exit 0; else break; fi; }; \
+ exit 1;; \
+ esac; \
+ done; \
+ echo ' cd $(top_srcdir) && $(AUTOMAKE) --gnu lang/qt/Makefile'; \
+ $(am__cd) $(top_srcdir) && \
+ $(AUTOMAKE) --gnu lang/qt/Makefile
+.PRECIOUS: Makefile
+Makefile: $(srcdir)/Makefile.in $(top_builddir)/config.status
+ @case '$?' in \
+ *config.status*) \
+ cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh;; \
+ *) \
+ echo ' cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__depfiles_maybe)'; \
+ cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__depfiles_maybe);; \
+ esac;
+
+$(top_builddir)/config.status: $(top_srcdir)/configure $(CONFIG_STATUS_DEPENDENCIES)
+ cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh
+
+$(top_srcdir)/configure: @MAINTAINER_MODE_TRUE@ $(am__configure_deps)
+ cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh
+$(ACLOCAL_M4): @MAINTAINER_MODE_TRUE@ $(am__aclocal_m4_deps)
+ cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh
+$(am__aclocal_m4_deps):
+
+mostlyclean-libtool:
+ -rm -f *.lo
+
+clean-libtool:
+ -rm -rf .libs _libs
+
+# This directory's subdirectories are mostly independent; you can cd
+# into them and run 'make' without going through this Makefile.
+# To change the values of 'make' variables: instead of editing Makefiles,
+# (1) if the variable is set in 'config.status', edit 'config.status'
+# (which will cause the Makefiles to be regenerated when you run 'make');
+# (2) otherwise, pass the desired values on the 'make' command line.
+$(am__recursive_targets):
+ @fail=; \
+ if $(am__make_keepgoing); then \
+ failcom='fail=yes'; \
+ else \
+ failcom='exit 1'; \
+ fi; \
+ dot_seen=no; \
+ target=`echo $@ | sed s/-recursive//`; \
+ case "$@" in \
+ distclean-* | maintainer-clean-*) list='$(DIST_SUBDIRS)' ;; \
+ *) list='$(SUBDIRS)' ;; \
+ esac; \
+ for subdir in $$list; do \
+ echo "Making $$target in $$subdir"; \
+ if test "$$subdir" = "."; then \
+ dot_seen=yes; \
+ local_target="$$target-am"; \
+ else \
+ local_target="$$target"; \
+ fi; \
+ ($(am__cd) $$subdir && $(MAKE) $(AM_MAKEFLAGS) $$local_target) \
+ || eval $$failcom; \
+ done; \
+ if test "$$dot_seen" = "no"; then \
+ $(MAKE) $(AM_MAKEFLAGS) "$$target-am" || exit 1; \
+ fi; test -z "$$fail"
+
+ID: $(am__tagged_files)
+ $(am__define_uniq_tagged_files); mkid -fID $$unique
+tags: tags-recursive
+TAGS: tags
+
+tags-am: $(TAGS_DEPENDENCIES) $(am__tagged_files)
+ set x; \
+ here=`pwd`; \
+ if ($(ETAGS) --etags-include --version) >/dev/null 2>&1; then \
+ include_option=--etags-include; \
+ empty_fix=.; \
+ else \
+ include_option=--include; \
+ empty_fix=; \
+ fi; \
+ list='$(SUBDIRS)'; for subdir in $$list; do \
+ if test "$$subdir" = .; then :; else \
+ test ! -f $$subdir/TAGS || \
+ set "$$@" "$$include_option=$$here/$$subdir/TAGS"; \
+ fi; \
+ done; \
+ $(am__define_uniq_tagged_files); \
+ shift; \
+ if test -z "$(ETAGS_ARGS)$$*$$unique"; then :; else \
+ test -n "$$unique" || unique=$$empty_fix; \
+ if test $$# -gt 0; then \
+ $(ETAGS) $(ETAGSFLAGS) $(AM_ETAGSFLAGS) $(ETAGS_ARGS) \
+ "$$@" $$unique; \
+ else \
+ $(ETAGS) $(ETAGSFLAGS) $(AM_ETAGSFLAGS) $(ETAGS_ARGS) \
+ $$unique; \
+ fi; \
+ fi
+ctags: ctags-recursive
+
+CTAGS: ctags
+ctags-am: $(TAGS_DEPENDENCIES) $(am__tagged_files)
+ $(am__define_uniq_tagged_files); \
+ test -z "$(CTAGS_ARGS)$$unique" \
+ || $(CTAGS) $(CTAGSFLAGS) $(AM_CTAGSFLAGS) $(CTAGS_ARGS) \
+ $$unique
+
+GTAGS:
+ here=`$(am__cd) $(top_builddir) && pwd` \
+ && $(am__cd) $(top_srcdir) \
+ && gtags -i $(GTAGS_ARGS) "$$here"
+cscopelist: cscopelist-recursive
+
+cscopelist-am: $(am__tagged_files)
+ list='$(am__tagged_files)'; \
+ case "$(srcdir)" in \
+ [\\/]* | ?:[\\/]*) sdir="$(srcdir)" ;; \
+ *) sdir=$(subdir)/$(srcdir) ;; \
+ esac; \
+ for i in $$list; do \
+ if test -f "$$i"; then \
+ echo "$(subdir)/$$i"; \
+ else \
+ echo "$$sdir/$$i"; \
+ fi; \
+ done >> $(top_builddir)/cscope.files
+
+distclean-tags:
+ -rm -f TAGS ID GTAGS GRTAGS GSYMS GPATH tags
+
+distdir: $(DISTFILES)
+ @srcdirstrip=`echo "$(srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \
+ topsrcdirstrip=`echo "$(top_srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \
+ list='$(DISTFILES)'; \
+ dist_files=`for file in $$list; do echo $$file; done | \
+ sed -e "s|^$$srcdirstrip/||;t" \
+ -e "s|^$$topsrcdirstrip/|$(top_builddir)/|;t"`; \
+ case $$dist_files in \
+ */*) $(MKDIR_P) `echo "$$dist_files" | \
+ sed '/\//!d;s|^|$(distdir)/|;s,/[^/]*$$,,' | \
+ sort -u` ;; \
+ esac; \
+ for file in $$dist_files; do \
+ if test -f $$file || test -d $$file; then d=.; else d=$(srcdir); fi; \
+ if test -d $$d/$$file; then \
+ dir=`echo "/$$file" | sed -e 's,/[^/]*$$,,'`; \
+ if test -d "$(distdir)/$$file"; then \
+ find "$(distdir)/$$file" -type d ! -perm -700 -exec chmod u+rwx {} \;; \
+ fi; \
+ if test -d $(srcdir)/$$file && test $$d != $(srcdir); then \
+ cp -fpR $(srcdir)/$$file "$(distdir)$$dir" || exit 1; \
+ find "$(distdir)/$$file" -type d ! -perm -700 -exec chmod u+rwx {} \;; \
+ fi; \
+ cp -fpR $$d/$$file "$(distdir)$$dir" || exit 1; \
+ else \
+ test -f "$(distdir)/$$file" \
+ || cp -p $$d/$$file "$(distdir)/$$file" \
+ || exit 1; \
+ fi; \
+ done
+ @list='$(DIST_SUBDIRS)'; for subdir in $$list; do \
+ if test "$$subdir" = .; then :; else \
+ $(am__make_dryrun) \
+ || test -d "$(distdir)/$$subdir" \
+ || $(MKDIR_P) "$(distdir)/$$subdir" \
+ || exit 1; \
+ dir1=$$subdir; dir2="$(distdir)/$$subdir"; \
+ $(am__relativize); \
+ new_distdir=$$reldir; \
+ dir1=$$subdir; dir2="$(top_distdir)"; \
+ $(am__relativize); \
+ new_top_distdir=$$reldir; \
+ echo " (cd $$subdir && $(MAKE) $(AM_MAKEFLAGS) top_distdir="$$new_top_distdir" distdir="$$new_distdir" \\"; \
+ echo " am__remove_distdir=: am__skip_length_check=: am__skip_mode_fix=: distdir)"; \
+ ($(am__cd) $$subdir && \
+ $(MAKE) $(AM_MAKEFLAGS) \
+ top_distdir="$$new_top_distdir" \
+ distdir="$$new_distdir" \
+ am__remove_distdir=: \
+ am__skip_length_check=: \
+ am__skip_mode_fix=: \
+ distdir) \
+ || exit 1; \
+ fi; \
+ done
+check-am: all-am
+check: check-recursive
+all-am: Makefile
+installdirs: installdirs-recursive
+installdirs-am:
+install: install-recursive
+install-exec: install-exec-recursive
+install-data: install-data-recursive
+uninstall: uninstall-recursive
+
+install-am: all-am
+ @$(MAKE) $(AM_MAKEFLAGS) install-exec-am install-data-am
+
+installcheck: installcheck-recursive
+install-strip:
+ if test -z '$(STRIP)'; then \
+ $(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \
+ install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \
+ install; \
+ else \
+ $(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \
+ install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \
+ "INSTALL_PROGRAM_ENV=STRIPPROG='$(STRIP)'" install; \
+ fi
+mostlyclean-generic:
+
+clean-generic:
+
+distclean-generic:
+ -test -z "$(CONFIG_CLEAN_FILES)" || rm -f $(CONFIG_CLEAN_FILES)
+ -test . = "$(srcdir)" || test -z "$(CONFIG_CLEAN_VPATH_FILES)" || rm -f $(CONFIG_CLEAN_VPATH_FILES)
+
+maintainer-clean-generic:
+ @echo "This command is intended for maintainers to use"
+ @echo "it deletes files that may require special tools to rebuild."
+clean: clean-recursive
+
+clean-am: clean-generic clean-libtool mostlyclean-am
+
+distclean: distclean-recursive
+ -rm -f Makefile
+distclean-am: clean-am distclean-generic distclean-tags
+
+dvi: dvi-recursive
+
+dvi-am:
+
+html: html-recursive
+
+html-am:
+
+info: info-recursive
+
+info-am:
+
+install-data-am:
+
+install-dvi: install-dvi-recursive
+
+install-dvi-am:
+
+install-exec-am:
+
+install-html: install-html-recursive
+
+install-html-am:
+
+install-info: install-info-recursive
+
+install-info-am:
+
+install-man:
+
+install-pdf: install-pdf-recursive
+
+install-pdf-am:
+
+install-ps: install-ps-recursive
+
+install-ps-am:
+
+installcheck-am:
+
+maintainer-clean: maintainer-clean-recursive
+ -rm -f Makefile
+maintainer-clean-am: distclean-am maintainer-clean-generic
+
+mostlyclean: mostlyclean-recursive
+
+mostlyclean-am: mostlyclean-generic mostlyclean-libtool
+
+pdf: pdf-recursive
+
+pdf-am:
+
+ps: ps-recursive
+
+ps-am:
+
+uninstall-am:
+
+.MAKE: $(am__recursive_targets) install-am install-strip
+
+.PHONY: $(am__recursive_targets) CTAGS GTAGS TAGS all all-am check \
+ check-am clean clean-generic clean-libtool cscopelist-am ctags \
+ ctags-am distclean distclean-generic distclean-libtool \
+ distclean-tags distdir dvi dvi-am html html-am info info-am \
+ install install-am install-data install-data-am install-dvi \
+ install-dvi-am install-exec install-exec-am install-html \
+ install-html-am install-info install-info-am install-man \
+ install-pdf install-pdf-am install-ps install-ps-am \
+ install-strip installcheck installcheck-am installdirs \
+ installdirs-am maintainer-clean maintainer-clean-generic \
+ mostlyclean mostlyclean-generic mostlyclean-libtool pdf pdf-am \
+ ps ps-am tags tags-am uninstall uninstall-am
+
+
+# Tell versions [3.59,3.63) of GNU make to not export all variables.
+# Otherwise a system limit (for SysV at least) may be exceeded.
+.NOEXPORT:
diff --git a/lang/qt/README b/lang/qt/README
new file mode 100644
index 0000000..6360a5b
--- /dev/null
+++ b/lang/qt/README
@@ -0,0 +1,130 @@
+Qt API bindings/wrapper for GPGME
+---------------------------------
+Based on KF5gpgmepp QGpgME and libkleo/backends/qgpgme
+
+Please note that QGpgME has a different license (GPL only)
+then GPGME itself. See the License secion in this
+document for more information.
+
+Overview
+--------
+QGpgme provides a very high level Qt API around GpgMEpp.
+As such it depends on GpgMEpp additionally to GpgME.
+
+There are two general concepts in QGpgME. Data abstraction
+through GpgMEpp's Dataprovider interface and the Job pattern.
+
+Data can be provided with QByteArrayDataProvider or
+QIODeviceDataProvider which can be constructed from their
+respective types. This means you can pass a QFile, QProcess,
+QString, etc.. directly to GPGME.
+
+To provide a stable API / ABI and because of historic reasons
+in libkleo (Where QGpgME was originally developed as an abstract
+crypto backend) QGpgME only provides abstract interfaces as
+public API while the actual implementation happens in the
+private QGpgME prefixed classes.
+
+Usage
+-----
+
+To use QGpgME first you need to obtain a Protocol class
+either for CMS (S/MIME) or OpenPGP. This Protocol class
+can then be used to create a Job.
+
+Each Job can be started asynchronusly and emits a result
+signal when done. The jobs are deleted automatically
+with QObject::deleteLater so they can be started without
+result handlers.
+
+The result signal provides a tuple of objects with the
+appropiate result information for this job. For historic
+reasons each result signal also includes an AuditLog
+and an AuditLog Error. These are only useful for
+S/MIME signature validation but are part of other jobs
+for API stability reasons.
+
+Some jobs like the verification or decryption jobs have
+dedicated result classes. Each result class at least
+has the member function error() that can be used
+to check if a job failed. Additionally errors are emited
+in the result signal.
+
+Jobs also provide progress signal whenever GnuPG emits
+a progress status line.
+
+Most jobs also provide a way synchronusly execute them.
+Please not that synchronus use does not cause the autodeletion
+to take place so you have to manually delete them.
+
+Async usage:
+
+ /* Create a job */
+ EncryptJob *job = openpgp()->encryptJob(/*ASCII Armor */false, /* Textmode */ false);
+ /* Connect something to the result signal */
+ connect(job, &EncryptJob::result, this, [] (const GpgME::EncryptionResult &result,
+ const QByteArray &cipherText,
+ const QString,
+ const GpgME::Error) {
+ /* Handle the result / do something with the ciphertext */
+ });
+ /* Start the job */
+ job->start(keys, inptr, outptr, Context::AlwaysTrust);
+ /* Do not delete the job as it is autodeleted. */
+
+Syncronus usage:
+
+ /* Create a job */
+ KeyListJob *listjob = openpgp()->keyListJob(false, false, false);
+ /* Prepare result vector */
+ std::vector<Key> keys;
+ /* Execute it synchronusly */
+ KeyListResult result = listjob->exec(QStringList() << QStringLiteral("alfa@example.net"),
+ false, keys);
+ /* Delete the job */
+ delete listjob;
+ /* Work with the result */
+
+See the generated documentation for more info on the classes
+in QGpgME. (Subdir doc)
+
+Examples / Tests
+----------------
+
+The tests in the tests subdir can be used to get a better
+idea of QGpgME's usage. They also serve to test the C++
+API. Kleopatra and KMails Messagelib also make extensive
+use of QGpgME and can be used as further examples.
+
+Hacking
+-------
+QGpgME comes from a KDE background. As such it does not use
+GNU Coding styles but KDE Coding styles. See:
+https://techbase.kde.org/Policies/Frameworks_Coding_Style
+
+License
+-------
+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.
diff --git a/lang/qt/doc/Doxyfile.in b/lang/qt/doc/Doxyfile.in
new file mode 100644
index 0000000..5d94f90
--- /dev/null
+++ b/lang/qt/doc/Doxyfile.in
@@ -0,0 +1,2352 @@
+# Doxyfile 1.8.8
+
+# This file describes the settings to be used by the documentation system
+# doxygen (www.doxygen.org) for a project.
+#
+# All text after a double hash (##) is considered a comment and is placed in
+# front of the TAG it is preceding.
+#
+# All text after a single hash (#) is considered a comment and will be ignored.
+# The format is:
+# TAG = value [value, ...]
+# For lists, items can also be appended using:
+# TAG += value [value, ...]
+# Values that contain spaces should be placed between quotes (\" \").
+
+#---------------------------------------------------------------------------
+# Project related configuration options
+#---------------------------------------------------------------------------
+
+# This tag specifies the encoding used for all characters in the config file
+# that follow. The default is UTF-8 which is also the encoding used for all text
+# before the first occurrence of this tag. Doxygen uses libiconv (or the iconv
+# built into libc) for the transcoding. See http://www.gnu.org/software/libiconv
+# for the list of possible encodings.
+# The default value is: UTF-8.
+
+DOXYFILE_ENCODING = UTF-8
+
+# The PROJECT_NAME tag is a single word (or a sequence of words surrounded by
+# double-quotes, unless you are using Doxywizard) that should identify the
+# project for which the documentation is generated. This name is used in the
+# title of most generated pages and in a few other places.
+# The default value is: My Project.
+
+PROJECT_NAME = "QGpgME"
+
+# The PROJECT_NUMBER tag can be used to enter a project or revision number. This
+# could be handy for archiving the generated documentation or if some version
+# control system is used.
+
+PROJECT_NUMBER = "@LIBQGPGME_LT_CURRENT@.@LIBQGPGME_LT_AGE@.@LIBQGPGME_LT_REVISION@.@BUILD_REVISION@"
+
+# Using the PROJECT_BRIEF tag one can provide an optional one line description
+# for a project that appears at the top of each page and should give viewer a
+# quick idea about the purpose of the project. Keep the description short.
+
+PROJECT_BRIEF = "Qt API for GpgME"
+
+# With the PROJECT_LOGO tag one can specify an logo or icon that is included in
+# the documentation. The maximum height of the logo should not exceed 55 pixels
+# and the maximum width should not exceed 200 pixels. Doxygen will copy the logo
+# to the output directory.
+
+PROJECT_LOGO =
+
+# The OUTPUT_DIRECTORY tag is used to specify the (relative or absolute) path
+# into which the generated documentation will be written. If a relative path is
+# entered, it will be relative to the location where doxygen was started. If
+# left blank the current directory will be used.
+
+OUTPUT_DIRECTORY = "@abs_builddir@/generated"
+
+# If the CREATE_SUBDIRS tag is set to YES, then doxygen will create 4096 sub-
+# directories (in 2 levels) under the output directory of each output format and
+# will distribute the generated files over these directories. Enabling this
+# option can be useful when feeding doxygen a huge amount of source files, where
+# putting all generated files in the same directory would otherwise causes
+# performance problems for the file system.
+# The default value is: NO.
+
+CREATE_SUBDIRS = NO
+
+# If the ALLOW_UNICODE_NAMES tag is set to YES, doxygen will allow non-ASCII
+# characters to appear in the names of generated files. If set to NO, non-ASCII
+# characters will be escaped, for example _xE3_x81_x84 will be used for Unicode
+# U+3044.
+# The default value is: NO.
+
+ALLOW_UNICODE_NAMES = NO
+
+# The OUTPUT_LANGUAGE tag is used to specify the language in which all
+# documentation generated by doxygen is written. Doxygen will use this
+# information to generate all constant output in the proper language.
+# Possible values are: Afrikaans, Arabic, Armenian, Brazilian, Catalan, Chinese,
+# Chinese-Traditional, Croatian, Czech, Danish, Dutch, English (United States),
+# Esperanto, Farsi (Persian), Finnish, French, German, Greek, Hungarian,
+# Indonesian, Italian, Japanese, Japanese-en (Japanese with English messages),
+# Korean, Korean-en (Korean with English messages), Latvian, Lithuanian,
+# Macedonian, Norwegian, Persian (Farsi), Polish, Portuguese, Romanian, Russian,
+# Serbian, Serbian-Cyrillic, Slovak, Slovene, Spanish, Swedish, Turkish,
+# Ukrainian and Vietnamese.
+# The default value is: English.
+
+OUTPUT_LANGUAGE = English
+
+# If the BRIEF_MEMBER_DESC tag is set to YES doxygen will include brief member
+# descriptions after the members that are listed in the file and class
+# documentation (similar to Javadoc). Set to NO to disable this.
+# The default value is: YES.
+
+BRIEF_MEMBER_DESC = YES
+
+# If the REPEAT_BRIEF tag is set to YES doxygen will prepend the brief
+# description of a member or function before the detailed description
+#
+# Note: If both HIDE_UNDOC_MEMBERS and BRIEF_MEMBER_DESC are set to NO, the
+# brief descriptions will be completely suppressed.
+# The default value is: YES.
+
+REPEAT_BRIEF = YES
+
+# This tag implements a quasi-intelligent brief description abbreviator that is
+# used to form the text in various listings. Each string in this list, if found
+# as the leading text of the brief description, will be stripped from the text
+# and the result, after processing the whole list, is used as the annotated
+# text. Otherwise, the brief description is used as-is. If left blank, the
+# following values are used ($name is automatically replaced with the name of
+# the entity):The $name class, The $name widget, The $name file, is, provides,
+# specifies, contains, represents, a, an and the.
+
+ABBREVIATE_BRIEF =
+
+# If the ALWAYS_DETAILED_SEC and REPEAT_BRIEF tags are both set to YES then
+# doxygen will generate a detailed section even if there is only a brief
+# description.
+# The default value is: NO.
+
+ALWAYS_DETAILED_SEC = NO
+
+# If the INLINE_INHERITED_MEMB tag is set to YES, doxygen will show all
+# inherited members of a class in the documentation of that class as if those
+# members were ordinary class members. Constructors, destructors and assignment
+# operators of the base classes will not be shown.
+# The default value is: NO.
+
+INLINE_INHERITED_MEMB = NO
+
+# If the FULL_PATH_NAMES tag is set to YES doxygen will prepend the full path
+# before files name in the file list and in the header files. If set to NO the
+# shortest path that makes the file name unique will be used
+# The default value is: YES.
+
+FULL_PATH_NAMES = YES
+
+# The STRIP_FROM_PATH tag can be used to strip a user-defined part of the path.
+# Stripping is only done if one of the specified strings matches the left-hand
+# part of the path. The tag can be used to show relative paths in the file list.
+# If left blank the directory from which doxygen is run is used as the path to
+# strip.
+#
+# Note that you can specify absolute paths here, but also relative paths, which
+# will be relative from the directory where doxygen is started.
+# This tag requires that the tag FULL_PATH_NAMES is set to YES.
+
+STRIP_FROM_PATH =
+
+# The STRIP_FROM_INC_PATH tag can be used to strip a user-defined part of the
+# path mentioned in the documentation of a class, which tells the reader which
+# header file to include in order to use a class. If left blank only the name of
+# the header file containing the class definition is used. Otherwise one should
+# specify the list of include paths that are normally passed to the compiler
+# using the -I flag.
+
+STRIP_FROM_INC_PATH =
+
+# If the SHORT_NAMES tag is set to YES, doxygen will generate much shorter (but
+# less readable) file names. This can be useful is your file systems doesn't
+# support long names like on DOS, Mac, or CD-ROM.
+# The default value is: NO.
+
+SHORT_NAMES = NO
+
+# If the JAVADOC_AUTOBRIEF tag is set to YES then doxygen will interpret the
+# first line (until the first dot) of a Javadoc-style comment as the brief
+# description. If set to NO, the Javadoc-style will behave just like regular Qt-
+# style comments (thus requiring an explicit @brief command for a brief
+# description.)
+# The default value is: NO.
+
+JAVADOC_AUTOBRIEF = NO
+
+# If the QT_AUTOBRIEF tag is set to YES then doxygen will interpret the first
+# line (until the first dot) of a Qt-style comment as the brief description. If
+# set to NO, the Qt-style will behave just like regular Qt-style comments (thus
+# requiring an explicit \brief command for a brief description.)
+# The default value is: NO.
+
+QT_AUTOBRIEF = NO
+
+# The MULTILINE_CPP_IS_BRIEF tag can be set to YES to make doxygen treat a
+# multi-line C++ special comment block (i.e. a block of //! or /// comments) as
+# a brief description. This used to be the default behavior. The new default is
+# to treat a multi-line C++ comment block as a detailed description. Set this
+# tag to YES if you prefer the old behavior instead.
+#
+# Note that setting this tag to YES also means that rational rose comments are
+# not recognized any more.
+# The default value is: NO.
+
+MULTILINE_CPP_IS_BRIEF = NO
+
+# If the INHERIT_DOCS tag is set to YES then an undocumented member inherits the
+# documentation from any documented member that it re-implements.
+# The default value is: YES.
+
+INHERIT_DOCS = YES
+
+# If the SEPARATE_MEMBER_PAGES tag is set to YES, then doxygen will produce a
+# new page for each member. If set to NO, the documentation of a member will be
+# part of the file/class/namespace that contains it.
+# The default value is: NO.
+
+SEPARATE_MEMBER_PAGES = NO
+
+# The TAB_SIZE tag can be used to set the number of spaces in a tab. Doxygen
+# uses this value to replace tabs by spaces in code fragments.
+# Minimum value: 1, maximum value: 16, default value: 4.
+
+TAB_SIZE = 4
+
+# This tag can be used to specify a number of aliases that act as commands in
+# the documentation. An alias has the form:
+# name=value
+# For example adding
+# "sideeffect=@par Side Effects:\n"
+# will allow you to put the command \sideeffect (or @sideeffect) in the
+# documentation, which will result in a user-defined paragraph with heading
+# "Side Effects:". You can put \n's in the value part of an alias to insert
+# newlines.
+
+ALIASES =
+
+# This tag can be used to specify a number of word-keyword mappings (TCL only).
+# A mapping has the form "name=value". For example adding "class=itcl::class"
+# will allow you to use the command class in the itcl::class meaning.
+
+TCL_SUBST =
+
+# Set the OPTIMIZE_OUTPUT_FOR_C tag to YES if your project consists of C sources
+# only. Doxygen will then generate output that is more tailored for C. For
+# instance, some of the names that are used will be different. The list of all
+# members will be omitted, etc.
+# The default value is: NO.
+
+OPTIMIZE_OUTPUT_FOR_C = NO
+
+# Set the OPTIMIZE_OUTPUT_JAVA tag to YES if your project consists of Java or
+# Python sources only. Doxygen will then generate output that is more tailored
+# for that language. For instance, namespaces will be presented as packages,
+# qualified scopes will look different, etc.
+# The default value is: NO.
+
+OPTIMIZE_OUTPUT_JAVA = NO
+
+# Set the OPTIMIZE_FOR_FORTRAN tag to YES if your project consists of Fortran
+# sources. Doxygen will then generate output that is tailored for Fortran.
+# The default value is: NO.
+
+OPTIMIZE_FOR_FORTRAN = NO
+
+# Set the OPTIMIZE_OUTPUT_VHDL tag to YES if your project consists of VHDL
+# sources. Doxygen will then generate output that is tailored for VHDL.
+# The default value is: NO.
+
+OPTIMIZE_OUTPUT_VHDL = NO
+
+# Doxygen selects the parser to use depending on the extension of the files it
+# parses. With this tag you can assign which parser to use for a given
+# extension. Doxygen has a built-in mapping, but you can override or extend it
+# using this tag. The format is ext=language, where ext is a file extension, and
+# language is one of the parsers supported by doxygen: IDL, Java, Javascript,
+# C#, C, C++, D, PHP, Objective-C, Python, Fortran (fixed format Fortran:
+# FortranFixed, free formatted Fortran: FortranFree, unknown formatted Fortran:
+# Fortran. In the later case the parser tries to guess whether the code is fixed
+# or free formatted code, this is the default for Fortran type files), VHDL. For
+# instance to make doxygen treat .inc files as Fortran files (default is PHP),
+# and .f files as C (default is Fortran), use: inc=Fortran f=C.
+#
+# Note For files without extension you can use no_extension as a placeholder.
+#
+# Note that for custom extensions you also need to set FILE_PATTERNS otherwise
+# the files are not read by doxygen.
+
+EXTENSION_MAPPING =
+
+# If the MARKDOWN_SUPPORT tag is enabled then doxygen pre-processes all comments
+# according to the Markdown format, which allows for more readable
+# documentation. See http://daringfireball.net/projects/markdown/ for details.
+# The output of markdown processing is further processed by doxygen, so you can
+# mix doxygen, HTML, and XML commands with Markdown formatting. Disable only in
+# case of backward compatibilities issues.
+# The default value is: YES.
+
+MARKDOWN_SUPPORT = YES
+
+# When enabled doxygen tries to link words that correspond to documented
+# classes, or namespaces to their corresponding documentation. Such a link can
+# be prevented in individual cases by by putting a % sign in front of the word
+# or globally by setting AUTOLINK_SUPPORT to NO.
+# The default value is: YES.
+
+AUTOLINK_SUPPORT = YES
+
+# If you use STL classes (i.e. std::string, std::vector, etc.) but do not want
+# to include (a tag file for) the STL sources as input, then you should set this
+# tag to YES in order to let doxygen match functions declarations and
+# definitions whose arguments contain STL classes (e.g. func(std::string);
+# versus func(std::string) {}). This also make the inheritance and collaboration
+# diagrams that involve STL classes more complete and accurate.
+# The default value is: NO.
+
+BUILTIN_STL_SUPPORT = NO
+
+# If you use Microsoft's C++/CLI language, you should set this option to YES to
+# enable parsing support.
+# The default value is: NO.
+
+CPP_CLI_SUPPORT = NO
+
+# Set the SIP_SUPPORT tag to YES if your project consists of sip (see:
+# http://www.riverbankcomputing.co.uk/software/sip/intro) sources only. Doxygen
+# will parse them like normal C++ but will assume all classes use public instead
+# of private inheritance when no explicit protection keyword is present.
+# The default value is: NO.
+
+SIP_SUPPORT = NO
+
+# For Microsoft's IDL there are propget and propput attributes to indicate
+# getter and setter methods for a property. Setting this option to YES will make
+# doxygen to replace the get and set methods by a property in the documentation.
+# This will only work if the methods are indeed getting or setting a simple
+# type. If this is not the case, or you want to show the methods anyway, you
+# should set this option to NO.
+# The default value is: YES.
+
+IDL_PROPERTY_SUPPORT = YES
+
+# If member grouping is used in the documentation and the DISTRIBUTE_GROUP_DOC
+# tag is set to YES, then doxygen will reuse the documentation of the first
+# member in the group (if any) for the other members of the group. By default
+# all members of a group must be documented explicitly.
+# The default value is: NO.
+
+DISTRIBUTE_GROUP_DOC = NO
+
+# Set the SUBGROUPING tag to YES to allow class member groups of the same type
+# (for instance a group of public functions) to be put as a subgroup of that
+# type (e.g. under the Public Functions section). Set it to NO to prevent
+# subgrouping. Alternatively, this can be done per class using the
+# \nosubgrouping command.
+# The default value is: YES.
+
+SUBGROUPING = YES
+
+# When the INLINE_GROUPED_CLASSES tag is set to YES, classes, structs and unions
+# are shown inside the group in which they are included (e.g. using \ingroup)
+# instead of on a separate page (for HTML and Man pages) or section (for LaTeX
+# and RTF).
+#
+# Note that this feature does not work in combination with
+# SEPARATE_MEMBER_PAGES.
+# The default value is: NO.
+
+INLINE_GROUPED_CLASSES = NO
+
+# When the INLINE_SIMPLE_STRUCTS tag is set to YES, structs, classes, and unions
+# with only public data fields or simple typedef fields will be shown inline in
+# the documentation of the scope in which they are defined (i.e. file,
+# namespace, or group documentation), provided this scope is documented. If set
+# to NO, structs, classes, and unions are shown on a separate page (for HTML and
+# Man pages) or section (for LaTeX and RTF).
+# The default value is: NO.
+
+INLINE_SIMPLE_STRUCTS = NO
+
+# When TYPEDEF_HIDES_STRUCT tag is enabled, a typedef of a struct, union, or
+# enum is documented as struct, union, or enum with the name of the typedef. So
+# typedef struct TypeS {} TypeT, will appear in the documentation as a struct
+# with name TypeT. When disabled the typedef will appear as a member of a file,
+# namespace, or class. And the struct will be named TypeS. This can typically be
+# useful for C code in case the coding convention dictates that all compound
+# types are typedef'ed and only the typedef is referenced, never the tag name.
+# The default value is: NO.
+
+TYPEDEF_HIDES_STRUCT = NO
+
+# The size of the symbol lookup cache can be set using LOOKUP_CACHE_SIZE. This
+# cache is used to resolve symbols given their name and scope. Since this can be
+# an expensive process and often the same symbol appears multiple times in the
+# code, doxygen keeps a cache of pre-resolved symbols. If the cache is too small
+# doxygen will become slower. If the cache is too large, memory is wasted. The
+# cache size is given by this formula: 2^(16+LOOKUP_CACHE_SIZE). The valid range
+# is 0..9, the default is 0, corresponding to a cache size of 2^16=65536
+# symbols. At the end of a run doxygen will report the cache usage and suggest
+# the optimal cache size from a speed point of view.
+# Minimum value: 0, maximum value: 9, default value: 0.
+
+LOOKUP_CACHE_SIZE = 0
+
+#---------------------------------------------------------------------------
+# Build related configuration options
+#---------------------------------------------------------------------------
+
+# If the EXTRACT_ALL tag is set to YES doxygen will assume all entities in
+# documentation are documented, even if no documentation was available. Private
+# class members and static file members will be hidden unless the
+# EXTRACT_PRIVATE respectively EXTRACT_STATIC tags are set to YES.
+# Note: This will also disable the warnings about undocumented members that are
+# normally produced when WARNINGS is set to YES.
+# The default value is: NO.
+
+EXTRACT_ALL = NO
+
+# If the EXTRACT_PRIVATE tag is set to YES all private members of a class will
+# be included in the documentation.
+# The default value is: NO.
+
+EXTRACT_PRIVATE = NO
+
+# If the EXTRACT_PACKAGE tag is set to YES all members with package or internal
+# scope will be included in the documentation.
+# The default value is: NO.
+
+EXTRACT_PACKAGE = NO
+
+# If the EXTRACT_STATIC tag is set to YES all static members of a file will be
+# included in the documentation.
+# The default value is: NO.
+
+EXTRACT_STATIC = NO
+
+# If the EXTRACT_LOCAL_CLASSES tag is set to YES classes (and structs) defined
+# locally in source files will be included in the documentation. If set to NO
+# only classes defined in header files are included. Does not have any effect
+# for Java sources.
+# The default value is: YES.
+
+EXTRACT_LOCAL_CLASSES = YES
+
+# This flag is only useful for Objective-C code. When set to YES local methods,
+# which are defined in the implementation section but not in the interface are
+# included in the documentation. If set to NO only methods in the interface are
+# included.
+# The default value is: NO.
+
+EXTRACT_LOCAL_METHODS = NO
+
+# If this flag is set to YES, the members of anonymous namespaces will be
+# extracted and appear in the documentation as a namespace called
+# 'anonymous_namespace{file}', where file will be replaced with the base name of
+# the file that contains the anonymous namespace. By default anonymous namespace
+# are hidden.
+# The default value is: NO.
+
+EXTRACT_ANON_NSPACES = NO
+
+# If the HIDE_UNDOC_MEMBERS tag is set to YES, doxygen will hide all
+# undocumented members inside documented classes or files. If set to NO these
+# members will be included in the various overviews, but no documentation
+# section is generated. This option has no effect if EXTRACT_ALL is enabled.
+# The default value is: NO.
+
+HIDE_UNDOC_MEMBERS = NO
+
+# If the HIDE_UNDOC_CLASSES tag is set to YES, doxygen will hide all
+# undocumented classes that are normally visible in the class hierarchy. If set
+# to NO these classes will be included in the various overviews. This option has
+# no effect if EXTRACT_ALL is enabled.
+# The default value is: NO.
+
+HIDE_UNDOC_CLASSES = NO
+
+# If the HIDE_FRIEND_COMPOUNDS tag is set to YES, doxygen will hide all friend
+# (class|struct|union) declarations. If set to NO these declarations will be
+# included in the documentation.
+# The default value is: NO.
+
+HIDE_FRIEND_COMPOUNDS = NO
+
+# If the HIDE_IN_BODY_DOCS tag is set to YES, doxygen will hide any
+# documentation blocks found inside the body of a function. If set to NO these
+# blocks will be appended to the function's detailed documentation block.
+# The default value is: NO.
+
+HIDE_IN_BODY_DOCS = NO
+
+# The INTERNAL_DOCS tag determines if documentation that is typed after a
+# \internal command is included. If the tag is set to NO then the documentation
+# will be excluded. Set it to YES to include the internal documentation.
+# The default value is: NO.
+
+INTERNAL_DOCS = NO
+
+# If the CASE_SENSE_NAMES tag is set to NO then doxygen will only generate file
+# names in lower-case letters. If set to YES upper-case letters are also
+# allowed. This is useful if you have classes or files whose names only differ
+# in case and if your file system supports case sensitive file names. Windows
+# and Mac users are advised to set this option to NO.
+# The default value is: system dependent.
+
+CASE_SENSE_NAMES = YES
+
+# If the HIDE_SCOPE_NAMES tag is set to NO then doxygen will show members with
+# their full class and namespace scopes in the documentation. If set to YES the
+# scope will be hidden.
+# The default value is: NO.
+
+HIDE_SCOPE_NAMES = NO
+
+# If the SHOW_INCLUDE_FILES tag is set to YES then doxygen will put a list of
+# the files that are included by a file in the documentation of that file.
+# The default value is: YES.
+
+SHOW_INCLUDE_FILES = YES
+
+# If the SHOW_GROUPED_MEMB_INC tag is set to YES then Doxygen will add for each
+# grouped member an include statement to the documentation, telling the reader
+# which file to include in order to use the member.
+# The default value is: NO.
+
+SHOW_GROUPED_MEMB_INC = NO
+
+# If the FORCE_LOCAL_INCLUDES tag is set to YES then doxygen will list include
+# files with double quotes in the documentation rather than with sharp brackets.
+# The default value is: NO.
+
+FORCE_LOCAL_INCLUDES = NO
+
+# If the INLINE_INFO tag is set to YES then a tag [inline] is inserted in the
+# documentation for inline members.
+# The default value is: YES.
+
+INLINE_INFO = YES
+
+# If the SORT_MEMBER_DOCS tag is set to YES then doxygen will sort the
+# (detailed) documentation of file and class members alphabetically by member
+# name. If set to NO the members will appear in declaration order.
+# The default value is: YES.
+
+SORT_MEMBER_DOCS = YES
+
+# If the SORT_BRIEF_DOCS tag is set to YES then doxygen will sort the brief
+# descriptions of file, namespace and class members alphabetically by member
+# name. If set to NO the members will appear in declaration order. Note that
+# this will also influence the order of the classes in the class list.
+# The default value is: NO.
+
+SORT_BRIEF_DOCS = NO
+
+# If the SORT_MEMBERS_CTORS_1ST tag is set to YES then doxygen will sort the
+# (brief and detailed) documentation of class members so that constructors and
+# destructors are listed first. If set to NO the constructors will appear in the
+# respective orders defined by SORT_BRIEF_DOCS and SORT_MEMBER_DOCS.
+# Note: If SORT_BRIEF_DOCS is set to NO this option is ignored for sorting brief
+# member documentation.
+# Note: If SORT_MEMBER_DOCS is set to NO this option is ignored for sorting
+# detailed member documentation.
+# The default value is: NO.
+
+SORT_MEMBERS_CTORS_1ST = NO
+
+# If the SORT_GROUP_NAMES tag is set to YES then doxygen will sort the hierarchy
+# of group names into alphabetical order. If set to NO the group names will
+# appear in their defined order.
+# The default value is: NO.
+
+SORT_GROUP_NAMES = NO
+
+# If the SORT_BY_SCOPE_NAME tag is set to YES, the class list will be sorted by
+# fully-qualified names, including namespaces. If set to NO, the class list will
+# be sorted only by class name, not including the namespace part.
+# Note: This option is not very useful if HIDE_SCOPE_NAMES is set to YES.
+# Note: This option applies only to the class list, not to the alphabetical
+# list.
+# The default value is: NO.
+
+SORT_BY_SCOPE_NAME = NO
+
+# If the STRICT_PROTO_MATCHING option is enabled and doxygen fails to do proper
+# type resolution of all parameters of a function it will reject a match between
+# the prototype and the implementation of a member function even if there is
+# only one candidate or it is obvious which candidate to choose by doing a
+# simple string match. By disabling STRICT_PROTO_MATCHING doxygen will still
+# accept a match between prototype and implementation in such cases.
+# The default value is: NO.
+
+STRICT_PROTO_MATCHING = NO
+
+# The GENERATE_TODOLIST tag can be used to enable ( YES) or disable ( NO) the
+# todo list. This list is created by putting \todo commands in the
+# documentation.
+# The default value is: YES.
+
+GENERATE_TODOLIST = YES
+
+# The GENERATE_TESTLIST tag can be used to enable ( YES) or disable ( NO) the
+# test list. This list is created by putting \test commands in the
+# documentation.
+# The default value is: YES.
+
+GENERATE_TESTLIST = YES
+
+# The GENERATE_BUGLIST tag can be used to enable ( YES) or disable ( NO) the bug
+# list. This list is created by putting \bug commands in the documentation.
+# The default value is: YES.
+
+GENERATE_BUGLIST = YES
+
+# The GENERATE_DEPRECATEDLIST tag can be used to enable ( YES) or disable ( NO)
+# the deprecated list. This list is created by putting \deprecated commands in
+# the documentation.
+# The default value is: YES.
+
+GENERATE_DEPRECATEDLIST= YES
+
+# The ENABLED_SECTIONS tag can be used to enable conditional documentation
+# sections, marked by \if <section_label> ... \endif and \cond <section_label>
+# ... \endcond blocks.
+
+ENABLED_SECTIONS =
+
+# The MAX_INITIALIZER_LINES tag determines the maximum number of lines that the
+# initial value of a variable or macro / define can have for it to appear in the
+# documentation. If the initializer consists of more lines than specified here
+# it will be hidden. Use a value of 0 to hide initializers completely. The
+# appearance of the value of individual variables and macros / defines can be
+# controlled using \showinitializer or \hideinitializer command in the
+# documentation regardless of this setting.
+# Minimum value: 0, maximum value: 10000, default value: 30.
+
+MAX_INITIALIZER_LINES = 30
+
+# Set the SHOW_USED_FILES tag to NO to disable the list of files generated at
+# the bottom of the documentation of classes and structs. If set to YES the list
+# will mention the files that were used to generate the documentation.
+# The default value is: YES.
+
+SHOW_USED_FILES = YES
+
+# Set the SHOW_FILES tag to NO to disable the generation of the Files page. This
+# will remove the Files entry from the Quick Index and from the Folder Tree View
+# (if specified).
+# The default value is: YES.
+
+SHOW_FILES = YES
+
+# Set the SHOW_NAMESPACES tag to NO to disable the generation of the Namespaces
+# page. This will remove the Namespaces entry from the Quick Index and from the
+# Folder Tree View (if specified).
+# The default value is: YES.
+
+SHOW_NAMESPACES = YES
+
+# The FILE_VERSION_FILTER tag can be used to specify a program or script that
+# doxygen should invoke to get the current version for each file (typically from
+# the version control system). Doxygen will invoke the program by executing (via
+# popen()) the command command input-file, where command is the value of the
+# FILE_VERSION_FILTER tag, and input-file is the name of an input file provided
+# by doxygen. Whatever the program writes to standard output is used as the file
+# version. For an example see the documentation.
+
+FILE_VERSION_FILTER =
+
+# The LAYOUT_FILE tag can be used to specify a layout file which will be parsed
+# by doxygen. The layout file controls the global structure of the generated
+# output files in an output format independent way. To create the layout file
+# that represents doxygen's defaults, run doxygen with the -l option. You can
+# optionally specify a file name after the option, if omitted DoxygenLayout.xml
+# will be used as the name of the layout file.
+#
+# Note that if you run doxygen from a directory containing a file called
+# DoxygenLayout.xml, doxygen will parse it automatically even if the LAYOUT_FILE
+# tag is left empty.
+
+LAYOUT_FILE =
+
+# The CITE_BIB_FILES tag can be used to specify one or more bib files containing
+# the reference definitions. This must be a list of .bib files. The .bib
+# extension is automatically appended if omitted. This requires the bibtex tool
+# to be installed. See also http://en.wikipedia.org/wiki/BibTeX for more info.
+# For LaTeX the style of the bibliography can be controlled using
+# LATEX_BIB_STYLE. To use this feature you need bibtex and perl available in the
+# search path. See also \cite for info how to create references.
+
+CITE_BIB_FILES =
+
+#---------------------------------------------------------------------------
+# Configuration options related to warning and progress messages
+#---------------------------------------------------------------------------
+
+# The QUIET tag can be used to turn on/off the messages that are generated to
+# standard output by doxygen. If QUIET is set to YES this implies that the
+# messages are off.
+# The default value is: NO.
+
+QUIET = YES
+
+# The WARNINGS tag can be used to turn on/off the warning messages that are
+# generated to standard error ( stderr) by doxygen. If WARNINGS is set to YES
+# this implies that the warnings are on.
+#
+# Tip: Turn warnings on while writing the documentation.
+# The default value is: YES.
+
+WARNINGS = YES
+
+# If the WARN_IF_UNDOCUMENTED tag is set to YES, then doxygen will generate
+# warnings for undocumented members. If EXTRACT_ALL is set to YES then this flag
+# will automatically be disabled.
+# The default value is: YES.
+
+WARN_IF_UNDOCUMENTED = NO
+
+# If the WARN_IF_DOC_ERROR tag is set to YES, doxygen will generate warnings for
+# potential errors in the documentation, such as not documenting some parameters
+# in a documented function, or documenting parameters that don't exist or using
+# markup commands wrongly.
+# The default value is: YES.
+
+WARN_IF_DOC_ERROR = YES
+
+# This WARN_NO_PARAMDOC option can be enabled to get warnings for functions that
+# are documented, but have no documentation for their parameters or return
+# value. If set to NO doxygen will only warn about wrong or incomplete parameter
+# documentation, but not about the absence of documentation.
+# The default value is: NO.
+
+WARN_NO_PARAMDOC = NO
+
+# The WARN_FORMAT tag determines the format of the warning messages that doxygen
+# can produce. The string should contain the $file, $line, and $text tags, which
+# will be replaced by the file and line number from which the warning originated
+# and the warning text. Optionally the format may contain $version, which will
+# be replaced by the version of the file (if it could be obtained via
+# FILE_VERSION_FILTER)
+# The default value is: $file:$line: $text.
+
+WARN_FORMAT = "$file:$line: $text"
+
+# The WARN_LOGFILE tag can be used to specify a file to which warning and error
+# messages should be written. If left blank the output is written to standard
+# error (stderr).
+
+WARN_LOGFILE =
+
+#---------------------------------------------------------------------------
+# Configuration options related to the input files
+#---------------------------------------------------------------------------
+
+# The INPUT tag is used to specify the files and/or directories that contain
+# documented source files. You may enter file names like myfile.cpp or
+# directories like /usr/src/myproject. Separate the files or directories with
+# spaces.
+# Note: If this tag is empty the current directory is searched.
+
+INPUT = "@top_srcdir@/lang/qt/src"
+
+# This tag can be used to specify the character encoding of the source files
+# that doxygen parses. Internally doxygen uses the UTF-8 encoding. Doxygen uses
+# libiconv (or the iconv built into libc) for the transcoding. See the libiconv
+# documentation (see: http://www.gnu.org/software/libiconv) for the list of
+# possible encodings.
+# The default value is: UTF-8.
+
+INPUT_ENCODING = UTF-8
+
+# If the value of the INPUT tag contains directories, you can use the
+# FILE_PATTERNS tag to specify one or more wildcard patterns (like *.cpp and
+# *.h) to filter out the source-files in the directories. If left blank the
+# following patterns are tested:*.c, *.cc, *.cxx, *.cpp, *.c++, *.java, *.ii,
+# *.ixx, *.ipp, *.i++, *.inl, *.idl, *.ddl, *.odl, *.h, *.hh, *.hxx, *.hpp,
+# *.h++, *.cs, *.d, *.php, *.php4, *.php5, *.phtml, *.inc, *.m, *.markdown,
+# *.md, *.mm, *.dox, *.py, *.f90, *.f, *.for, *.tcl, *.vhd, *.vhdl, *.ucf,
+# *.qsf, *.as and *.js.
+
+FILE_PATTERNS =
+
+# The RECURSIVE tag can be used to specify whether or not subdirectories should
+# be searched for input files as well.
+# The default value is: NO.
+
+RECURSIVE = NO
+
+# The EXCLUDE tag can be used to specify files and/or directories that should be
+# excluded from the INPUT source files. This way you can easily exclude a
+# subdirectory from a directory tree whose root is specified with the INPUT tag.
+#
+# Note that relative paths are relative to the directory from which doxygen is
+# run.
+
+EXCLUDE =
+
+# The EXCLUDE_SYMLINKS tag can be used to select whether or not files or
+# directories that are symbolic links (a Unix file system feature) are excluded
+# from the input.
+# The default value is: NO.
+
+EXCLUDE_SYMLINKS = NO
+
+# If the value of the INPUT tag contains directories, you can use the
+# EXCLUDE_PATTERNS tag to specify one or more wildcard patterns to exclude
+# certain files from those directories.
+#
+# Note that the wildcards are matched against the file with absolute path, so to
+# exclude all test directories for example use the pattern */test/*
+
+EXCLUDE_PATTERNS =
+
+# The EXCLUDE_SYMBOLS tag can be used to specify one or more symbol names
+# (namespaces, classes, functions, etc.) that should be excluded from the
+# output. The symbol name can be a fully qualified name, a word, or if the
+# wildcard * is used, a substring. Examples: ANamespace, AClass,
+# AClass::ANamespace, ANamespace::*Test
+#
+# Note that the wildcards are matched against the file with absolute path, so to
+# exclude all test directories use the pattern */test/*
+
+EXCLUDE_SYMBOLS =
+
+# The EXAMPLE_PATH tag can be used to specify one or more files or directories
+# that contain example code fragments that are included (see the \include
+# command).
+
+EXAMPLE_PATH =
+
+# If the value of the EXAMPLE_PATH tag contains directories, you can use the
+# EXAMPLE_PATTERNS tag to specify one or more wildcard pattern (like *.cpp and
+# *.h) to filter out the source-files in the directories. If left blank all
+# files are included.
+
+EXAMPLE_PATTERNS =
+
+# If the EXAMPLE_RECURSIVE tag is set to YES then subdirectories will be
+# searched for input files to be used with the \include or \dontinclude commands
+# irrespective of the value of the RECURSIVE tag.
+# The default value is: NO.
+
+EXAMPLE_RECURSIVE = NO
+
+# The IMAGE_PATH tag can be used to specify one or more files or directories
+# that contain images that are to be included in the documentation (see the
+# \image command).
+
+IMAGE_PATH =
+
+# The INPUT_FILTER tag can be used to specify a program that doxygen should
+# invoke to filter for each input file. Doxygen will invoke the filter program
+# by executing (via popen()) the command:
+#
+# <filter> <input-file>
+#
+# where <filter> is the value of the INPUT_FILTER tag, and <input-file> is the
+# name of an input file. Doxygen will then use the output that the filter
+# program writes to standard output. If FILTER_PATTERNS is specified, this tag
+# will be ignored.
+#
+# Note that the filter must not add or remove lines; it is applied before the
+# code is scanned, but not when the output code is generated. If lines are added
+# or removed, the anchors will not be placed correctly.
+
+INPUT_FILTER =
+
+# The FILTER_PATTERNS tag can be used to specify filters on a per file pattern
+# basis. Doxygen will compare the file name with each pattern and apply the
+# filter if there is a match. The filters are a list of the form: pattern=filter
+# (like *.cpp=my_cpp_filter). See INPUT_FILTER for further information on how
+# filters are used. If the FILTER_PATTERNS tag is empty or if none of the
+# patterns match the file name, INPUT_FILTER is applied.
+
+FILTER_PATTERNS =
+
+# If the FILTER_SOURCE_FILES tag is set to YES, the input filter (if set using
+# INPUT_FILTER ) will also be used to filter the input files that are used for
+# producing the source files to browse (i.e. when SOURCE_BROWSER is set to YES).
+# The default value is: NO.
+
+FILTER_SOURCE_FILES = NO
+
+# The FILTER_SOURCE_PATTERNS tag can be used to specify source filters per file
+# pattern. A pattern will override the setting for FILTER_PATTERN (if any) and
+# it is also possible to disable source filtering for a specific pattern using
+# *.ext= (so without naming a filter).
+# This tag requires that the tag FILTER_SOURCE_FILES is set to YES.
+
+FILTER_SOURCE_PATTERNS =
+
+# If the USE_MDFILE_AS_MAINPAGE tag refers to the name of a markdown file that
+# is part of the input, its contents will be placed on the main page
+# (index.html). This can be useful if you have a project on for instance GitHub
+# and want to reuse the introduction page also for the doxygen output.
+
+USE_MDFILE_AS_MAINPAGE =
+
+#---------------------------------------------------------------------------
+# Configuration options related to source browsing
+#---------------------------------------------------------------------------
+
+# If the SOURCE_BROWSER tag is set to YES then a list of source files will be
+# generated. Documented entities will be cross-referenced with these sources.
+#
+# Note: To get rid of all source code in the generated output, make sure that
+# also VERBATIM_HEADERS is set to NO.
+# The default value is: NO.
+
+SOURCE_BROWSER = NO
+
+# Setting the INLINE_SOURCES tag to YES will include the body of functions,
+# classes and enums directly into the documentation.
+# The default value is: NO.
+
+INLINE_SOURCES = NO
+
+# Setting the STRIP_CODE_COMMENTS tag to YES will instruct doxygen to hide any
+# special comment blocks from generated source code fragments. Normal C, C++ and
+# Fortran comments will always remain visible.
+# The default value is: YES.
+
+STRIP_CODE_COMMENTS = YES
+
+# If the REFERENCED_BY_RELATION tag is set to YES then for each documented
+# function all documented functions referencing it will be listed.
+# The default value is: NO.
+
+REFERENCED_BY_RELATION = NO
+
+# If the REFERENCES_RELATION tag is set to YES then for each documented function
+# all documented entities called/used by that function will be listed.
+# The default value is: NO.
+
+REFERENCES_RELATION = NO
+
+# If the REFERENCES_LINK_SOURCE tag is set to YES and SOURCE_BROWSER tag is set
+# to YES, then the hyperlinks from functions in REFERENCES_RELATION and
+# REFERENCED_BY_RELATION lists will link to the source code. Otherwise they will
+# link to the documentation.
+# The default value is: YES.
+
+REFERENCES_LINK_SOURCE = YES
+
+# If SOURCE_TOOLTIPS is enabled (the default) then hovering a hyperlink in the
+# source code will show a tooltip with additional information such as prototype,
+# brief description and links to the definition and documentation. Since this
+# will make the HTML file larger and loading of large files a bit slower, you
+# can opt to disable this feature.
+# The default value is: YES.
+# This tag requires that the tag SOURCE_BROWSER is set to YES.
+
+SOURCE_TOOLTIPS = YES
+
+# If the USE_HTAGS tag is set to YES then the references to source code will
+# point to the HTML generated by the htags(1) tool instead of doxygen built-in
+# source browser. The htags tool is part of GNU's global source tagging system
+# (see http://www.gnu.org/software/global/global.html). You will need version
+# 4.8.6 or higher.
+#
+# To use it do the following:
+# - Install the latest version of global
+# - Enable SOURCE_BROWSER and USE_HTAGS in the config file
+# - Make sure the INPUT points to the root of the source tree
+# - Run doxygen as normal
+#
+# Doxygen will invoke htags (and that will in turn invoke gtags), so these
+# tools must be available from the command line (i.e. in the search path).
+#
+# The result: instead of the source browser generated by doxygen, the links to
+# source code will now point to the output of htags.
+# The default value is: NO.
+# This tag requires that the tag SOURCE_BROWSER is set to YES.
+
+USE_HTAGS = NO
+
+# If the VERBATIM_HEADERS tag is set the YES then doxygen will generate a
+# verbatim copy of the header file for each class for which an include is
+# specified. Set to NO to disable this.
+# See also: Section \class.
+# The default value is: YES.
+
+VERBATIM_HEADERS = YES
+
+# If the CLANG_ASSISTED_PARSING tag is set to YES, then doxygen will use the
+# clang parser (see: http://clang.llvm.org/) for more accurate parsing at the
+# cost of reduced performance. This can be particularly helpful with template
+# rich C++ code for which doxygen's built-in parser lacks the necessary type
+# information.
+# Note: The availability of this option depends on whether or not doxygen was
+# compiled with the --with-libclang option.
+# The default value is: NO.
+
+CLANG_ASSISTED_PARSING = NO
+
+# If clang assisted parsing is enabled you can provide the compiler with command
+# line options that you would normally use when invoking the compiler. Note that
+# the include paths will already be set by doxygen for the files and directories
+# specified with INPUT and INCLUDE_PATH.
+# This tag requires that the tag CLANG_ASSISTED_PARSING is set to YES.
+
+CLANG_OPTIONS =
+
+#---------------------------------------------------------------------------
+# Configuration options related to the alphabetical class index
+#---------------------------------------------------------------------------
+
+# If the ALPHABETICAL_INDEX tag is set to YES, an alphabetical index of all
+# compounds will be generated. Enable this if the project contains a lot of
+# classes, structs, unions or interfaces.
+# The default value is: YES.
+
+ALPHABETICAL_INDEX = YES
+
+# The COLS_IN_ALPHA_INDEX tag can be used to specify the number of columns in
+# which the alphabetical index list will be split.
+# Minimum value: 1, maximum value: 20, default value: 5.
+# This tag requires that the tag ALPHABETICAL_INDEX is set to YES.
+
+COLS_IN_ALPHA_INDEX = 5
+
+# In case all classes in a project start with a common prefix, all classes will
+# be put under the same header in the alphabetical index. The IGNORE_PREFIX tag
+# can be used to specify a prefix (or a list of prefixes) that should be ignored
+# while generating the index headers.
+# This tag requires that the tag ALPHABETICAL_INDEX is set to YES.
+
+IGNORE_PREFIX =
+
+#---------------------------------------------------------------------------
+# Configuration options related to the HTML output
+#---------------------------------------------------------------------------
+
+# If the GENERATE_HTML tag is set to YES doxygen will generate HTML output
+# The default value is: YES.
+
+GENERATE_HTML = YES
+
+# The HTML_OUTPUT tag is used to specify where the HTML docs will be put. If a
+# relative path is entered the value of OUTPUT_DIRECTORY will be put in front of
+# it.
+# The default directory is: html.
+# This tag requires that the tag GENERATE_HTML is set to YES.
+
+HTML_OUTPUT = html
+
+# The HTML_FILE_EXTENSION tag can be used to specify the file extension for each
+# generated HTML page (for example: .htm, .php, .asp).
+# The default value is: .html.
+# This tag requires that the tag GENERATE_HTML is set to YES.
+
+HTML_FILE_EXTENSION = .html
+
+# The HTML_HEADER tag can be used to specify a user-defined HTML header file for
+# each generated HTML page. If the tag is left blank doxygen will generate a
+# standard header.
+#
+# To get valid HTML the header file that includes any scripts and style sheets
+# that doxygen needs, which is dependent on the configuration options used (e.g.
+# the setting GENERATE_TREEVIEW). It is highly recommended to start with a
+# default header using
+# doxygen -w html new_header.html new_footer.html new_stylesheet.css
+# YourConfigFile
+# and then modify the file new_header.html. See also section "Doxygen usage"
+# for information on how to generate the default header that doxygen normally
+# uses.
+# Note: The header is subject to change so you typically have to regenerate the
+# default header when upgrading to a newer version of doxygen. For a description
+# of the possible markers and block names see the documentation.
+# This tag requires that the tag GENERATE_HTML is set to YES.
+
+HTML_HEADER =
+
+# The HTML_FOOTER tag can be used to specify a user-defined HTML footer for each
+# generated HTML page. If the tag is left blank doxygen will generate a standard
+# footer. See HTML_HEADER for more information on how to generate a default
+# footer and what special commands can be used inside the footer. See also
+# section "Doxygen usage" for information on how to generate the default footer
+# that doxygen normally uses.
+# This tag requires that the tag GENERATE_HTML is set to YES.
+
+HTML_FOOTER =
+
+# The HTML_STYLESHEET tag can be used to specify a user-defined cascading style
+# sheet that is used by each HTML page. It can be used to fine-tune the look of
+# the HTML output. If left blank doxygen will generate a default style sheet.
+# See also section "Doxygen usage" for information on how to generate the style
+# sheet that doxygen normally uses.
+# Note: It is recommended to use HTML_EXTRA_STYLESHEET instead of this tag, as
+# it is more robust and this tag (HTML_STYLESHEET) will in the future become
+# obsolete.
+# This tag requires that the tag GENERATE_HTML is set to YES.
+
+HTML_STYLESHEET =
+
+# The HTML_EXTRA_STYLESHEET tag can be used to specify additional user-defined
+# cascading style sheets that are included after the standard style sheets
+# created by doxygen. Using this option one can overrule certain style aspects.
+# This is preferred over using HTML_STYLESHEET since it does not replace the
+# standard style sheet and is therefor more robust against future updates.
+# Doxygen will copy the style sheet files to the output directory.
+# Note: The order of the extra stylesheet files is of importance (e.g. the last
+# stylesheet in the list overrules the setting of the previous ones in the
+# list). For an example see the documentation.
+# This tag requires that the tag GENERATE_HTML is set to YES.
+
+HTML_EXTRA_STYLESHEET =
+
+# The HTML_EXTRA_FILES tag can be used to specify one or more extra images or
+# other source files which should be copied to the HTML output directory. Note
+# that these files will be copied to the base HTML output directory. Use the
+# $relpath^ marker in the HTML_HEADER and/or HTML_FOOTER files to load these
+# files. In the HTML_STYLESHEET file, use the file name only. Also note that the
+# files will be copied as-is; there are no commands or markers available.
+# This tag requires that the tag GENERATE_HTML is set to YES.
+
+HTML_EXTRA_FILES =
+
+# The HTML_COLORSTYLE_HUE tag controls the color of the HTML output. Doxygen
+# will adjust the colors in the stylesheet and background images according to
+# this color. Hue is specified as an angle on a colorwheel, see
+# http://en.wikipedia.org/wiki/Hue for more information. For instance the value
+# 0 represents red, 60 is yellow, 120 is green, 180 is cyan, 240 is blue, 300
+# purple, and 360 is red again.
+# Minimum value: 0, maximum value: 359, default value: 220.
+# This tag requires that the tag GENERATE_HTML is set to YES.
+
+HTML_COLORSTYLE_HUE = 220
+
+# The HTML_COLORSTYLE_SAT tag controls the purity (or saturation) of the colors
+# in the HTML output. For a value of 0 the output will use grayscales only. A
+# value of 255 will produce the most vivid colors.
+# Minimum value: 0, maximum value: 255, default value: 100.
+# This tag requires that the tag GENERATE_HTML is set to YES.
+
+HTML_COLORSTYLE_SAT = 100
+
+# The HTML_COLORSTYLE_GAMMA tag controls the gamma correction applied to the
+# luminance component of the colors in the HTML output. Values below 100
+# gradually make the output lighter, whereas values above 100 make the output
+# darker. The value divided by 100 is the actual gamma applied, so 80 represents
+# a gamma of 0.8, The value 220 represents a gamma of 2.2, and 100 does not
+# change the gamma.
+# Minimum value: 40, maximum value: 240, default value: 80.
+# This tag requires that the tag GENERATE_HTML is set to YES.
+
+HTML_COLORSTYLE_GAMMA = 80
+
+# If the HTML_TIMESTAMP tag is set to YES then the footer of each generated HTML
+# page will contain the date and time when the page was generated. Setting this
+# to NO can help when comparing the output of multiple runs.
+# The default value is: YES.
+# This tag requires that the tag GENERATE_HTML is set to YES.
+
+HTML_TIMESTAMP = YES
+
+# If the HTML_DYNAMIC_SECTIONS tag is set to YES then the generated HTML
+# documentation will contain sections that can be hidden and shown after the
+# page has loaded.
+# The default value is: NO.
+# This tag requires that the tag GENERATE_HTML is set to YES.
+
+HTML_DYNAMIC_SECTIONS = NO
+
+# With HTML_INDEX_NUM_ENTRIES one can control the preferred number of entries
+# shown in the various tree structured indices initially; the user can expand
+# and collapse entries dynamically later on. Doxygen will expand the tree to
+# such a level that at most the specified number of entries are visible (unless
+# a fully collapsed tree already exceeds this amount). So setting the number of
+# entries 1 will produce a full collapsed tree by default. 0 is a special value
+# representing an infinite number of entries and will result in a full expanded
+# tree by default.
+# Minimum value: 0, maximum value: 9999, default value: 100.
+# This tag requires that the tag GENERATE_HTML is set to YES.
+
+HTML_INDEX_NUM_ENTRIES = 100
+
+# If the GENERATE_DOCSET tag is set to YES, additional index files will be
+# generated that can be used as input for Apple's Xcode 3 integrated development
+# environment (see: http://developer.apple.com/tools/xcode/), introduced with
+# OSX 10.5 (Leopard). To create a documentation set, doxygen will generate a
+# Makefile in the HTML output directory. Running make will produce the docset in
+# that directory and running make install will install the docset in
+# ~/Library/Developer/Shared/Documentation/DocSets so that Xcode will find it at
+# startup. See http://developer.apple.com/tools/creatingdocsetswithdoxygen.html
+# for more information.
+# The default value is: NO.
+# This tag requires that the tag GENERATE_HTML is set to YES.
+
+GENERATE_DOCSET = NO
+
+# This tag determines the name of the docset feed. A documentation feed provides
+# an umbrella under which multiple documentation sets from a single provider
+# (such as a company or product suite) can be grouped.
+# The default value is: Doxygen generated docs.
+# This tag requires that the tag GENERATE_DOCSET is set to YES.
+
+DOCSET_FEEDNAME = "Doxygen generated docs"
+
+# This tag specifies a string that should uniquely identify the documentation
+# set bundle. This should be a reverse domain-name style string, e.g.
+# com.mycompany.MyDocSet. Doxygen will append .docset to the name.
+# The default value is: org.doxygen.Project.
+# This tag requires that the tag GENERATE_DOCSET is set to YES.
+
+DOCSET_BUNDLE_ID = org.doxygen.Project
+
+# The DOCSET_PUBLISHER_ID tag specifies a string that should uniquely identify
+# the documentation publisher. This should be a reverse domain-name style
+# string, e.g. com.mycompany.MyDocSet.documentation.
+# The default value is: org.doxygen.Publisher.
+# This tag requires that the tag GENERATE_DOCSET is set to YES.
+
+DOCSET_PUBLISHER_ID = org.doxygen.Publisher
+
+# The DOCSET_PUBLISHER_NAME tag identifies the documentation publisher.
+# The default value is: Publisher.
+# This tag requires that the tag GENERATE_DOCSET is set to YES.
+
+DOCSET_PUBLISHER_NAME = Publisher
+
+# If the GENERATE_HTMLHELP tag is set to YES then doxygen generates three
+# additional HTML index files: index.hhp, index.hhc, and index.hhk. The
+# index.hhp is a project file that can be read by Microsoft's HTML Help Workshop
+# (see: http://www.microsoft.com/en-us/download/details.aspx?id=21138) on
+# Windows.
+#
+# The HTML Help Workshop contains a compiler that can convert all HTML output
+# generated by doxygen into a single compiled HTML file (.chm). Compiled HTML
+# files are now used as the Windows 98 help format, and will replace the old
+# Windows help format (.hlp) on all Windows platforms in the future. Compressed
+# HTML files also contain an index, a table of contents, and you can search for
+# words in the documentation. The HTML workshop also contains a viewer for
+# compressed HTML files.
+# The default value is: NO.
+# This tag requires that the tag GENERATE_HTML is set to YES.
+
+GENERATE_HTMLHELP = NO
+
+# The CHM_FILE tag can be used to specify the file name of the resulting .chm
+# file. You can add a path in front of the file if the result should not be
+# written to the html output directory.
+# This tag requires that the tag GENERATE_HTMLHELP is set to YES.
+
+CHM_FILE =
+
+# The HHC_LOCATION tag can be used to specify the location (absolute path
+# including file name) of the HTML help compiler ( hhc.exe). If non-empty
+# doxygen will try to run the HTML help compiler on the generated index.hhp.
+# The file has to be specified with full path.
+# This tag requires that the tag GENERATE_HTMLHELP is set to YES.
+
+HHC_LOCATION =
+
+# The GENERATE_CHI flag controls if a separate .chi index file is generated (
+# YES) or that it should be included in the master .chm file ( NO).
+# The default value is: NO.
+# This tag requires that the tag GENERATE_HTMLHELP is set to YES.
+
+GENERATE_CHI = NO
+
+# The CHM_INDEX_ENCODING is used to encode HtmlHelp index ( hhk), content ( hhc)
+# and project file content.
+# This tag requires that the tag GENERATE_HTMLHELP is set to YES.
+
+CHM_INDEX_ENCODING =
+
+# The BINARY_TOC flag controls whether a binary table of contents is generated (
+# YES) or a normal table of contents ( NO) in the .chm file. Furthermore it
+# enables the Previous and Next buttons.
+# The default value is: NO.
+# This tag requires that the tag GENERATE_HTMLHELP is set to YES.
+
+BINARY_TOC = NO
+
+# The TOC_EXPAND flag can be set to YES to add extra items for group members to
+# the table of contents of the HTML help documentation and to the tree view.
+# The default value is: NO.
+# This tag requires that the tag GENERATE_HTMLHELP is set to YES.
+
+TOC_EXPAND = NO
+
+# If the GENERATE_QHP tag is set to YES and both QHP_NAMESPACE and
+# QHP_VIRTUAL_FOLDER are set, an additional index file will be generated that
+# can be used as input for Qt's qhelpgenerator to generate a Qt Compressed Help
+# (.qch) of the generated HTML documentation.
+# The default value is: NO.
+# This tag requires that the tag GENERATE_HTML is set to YES.
+
+GENERATE_QHP = NO
+
+# If the QHG_LOCATION tag is specified, the QCH_FILE tag can be used to specify
+# the file name of the resulting .qch file. The path specified is relative to
+# the HTML output folder.
+# This tag requires that the tag GENERATE_QHP is set to YES.
+
+QCH_FILE =
+
+# The QHP_NAMESPACE tag specifies the namespace to use when generating Qt Help
+# Project output. For more information please see Qt Help Project / Namespace
+# (see: http://qt-project.org/doc/qt-4.8/qthelpproject.html#namespace).
+# The default value is: org.doxygen.Project.
+# This tag requires that the tag GENERATE_QHP is set to YES.
+
+QHP_NAMESPACE = org.doxygen.Project
+
+# The QHP_VIRTUAL_FOLDER tag specifies the namespace to use when generating Qt
+# Help Project output. For more information please see Qt Help Project / Virtual
+# Folders (see: http://qt-project.org/doc/qt-4.8/qthelpproject.html#virtual-
+# folders).
+# The default value is: doc.
+# This tag requires that the tag GENERATE_QHP is set to YES.
+
+QHP_VIRTUAL_FOLDER = doc
+
+# If the QHP_CUST_FILTER_NAME tag is set, it specifies the name of a custom
+# filter to add. For more information please see Qt Help Project / Custom
+# Filters (see: http://qt-project.org/doc/qt-4.8/qthelpproject.html#custom-
+# filters).
+# This tag requires that the tag GENERATE_QHP is set to YES.
+
+QHP_CUST_FILTER_NAME =
+
+# The QHP_CUST_FILTER_ATTRS tag specifies the list of the attributes of the
+# custom filter to add. For more information please see Qt Help Project / Custom
+# Filters (see: http://qt-project.org/doc/qt-4.8/qthelpproject.html#custom-
+# filters).
+# This tag requires that the tag GENERATE_QHP is set to YES.
+
+QHP_CUST_FILTER_ATTRS =
+
+# The QHP_SECT_FILTER_ATTRS tag specifies the list of the attributes this
+# project's filter section matches. Qt Help Project / Filter Attributes (see:
+# http://qt-project.org/doc/qt-4.8/qthelpproject.html#filter-attributes).
+# This tag requires that the tag GENERATE_QHP is set to YES.
+
+QHP_SECT_FILTER_ATTRS =
+
+# The QHG_LOCATION tag can be used to specify the location of Qt's
+# qhelpgenerator. If non-empty doxygen will try to run qhelpgenerator on the
+# generated .qhp file.
+# This tag requires that the tag GENERATE_QHP is set to YES.
+
+QHG_LOCATION =
+
+# If the GENERATE_ECLIPSEHELP tag is set to YES, additional index files will be
+# generated, together with the HTML files, they form an Eclipse help plugin. To
+# install this plugin and make it available under the help contents menu in
+# Eclipse, the contents of the directory containing the HTML and XML files needs
+# to be copied into the plugins directory of eclipse. The name of the directory
+# within the plugins directory should be the same as the ECLIPSE_DOC_ID value.
+# After copying Eclipse needs to be restarted before the help appears.
+# The default value is: NO.
+# This tag requires that the tag GENERATE_HTML is set to YES.
+
+GENERATE_ECLIPSEHELP = NO
+
+# A unique identifier for the Eclipse help plugin. When installing the plugin
+# the directory name containing the HTML and XML files should also have this
+# name. Each documentation set should have its own identifier.
+# The default value is: org.doxygen.Project.
+# This tag requires that the tag GENERATE_ECLIPSEHELP is set to YES.
+
+ECLIPSE_DOC_ID = org.doxygen.Project
+
+# If you want full control over the layout of the generated HTML pages it might
+# be necessary to disable the index and replace it with your own. The
+# DISABLE_INDEX tag can be used to turn on/off the condensed index (tabs) at top
+# of each HTML page. A value of NO enables the index and the value YES disables
+# it. Since the tabs in the index contain the same information as the navigation
+# tree, you can set this option to YES if you also set GENERATE_TREEVIEW to YES.
+# The default value is: NO.
+# This tag requires that the tag GENERATE_HTML is set to YES.
+
+DISABLE_INDEX = NO
+
+# The GENERATE_TREEVIEW tag is used to specify whether a tree-like index
+# structure should be generated to display hierarchical information. If the tag
+# value is set to YES, a side panel will be generated containing a tree-like
+# index structure (just like the one that is generated for HTML Help). For this
+# to work a browser that supports JavaScript, DHTML, CSS and frames is required
+# (i.e. any modern browser). Windows users are probably better off using the
+# HTML help feature. Via custom stylesheets (see HTML_EXTRA_STYLESHEET) one can
+# further fine-tune the look of the index. As an example, the default style
+# sheet generated by doxygen has an example that shows how to put an image at
+# the root of the tree instead of the PROJECT_NAME. Since the tree basically has
+# the same information as the tab index, you could consider setting
+# DISABLE_INDEX to YES when enabling this option.
+# The default value is: NO.
+# This tag requires that the tag GENERATE_HTML is set to YES.
+
+GENERATE_TREEVIEW = NO
+
+# The ENUM_VALUES_PER_LINE tag can be used to set the number of enum values that
+# doxygen will group on one line in the generated HTML documentation.
+#
+# Note that a value of 0 will completely suppress the enum values from appearing
+# in the overview section.
+# Minimum value: 0, maximum value: 20, default value: 4.
+# This tag requires that the tag GENERATE_HTML is set to YES.
+
+ENUM_VALUES_PER_LINE = 4
+
+# If the treeview is enabled (see GENERATE_TREEVIEW) then this tag can be used
+# to set the initial width (in pixels) of the frame in which the tree is shown.
+# Minimum value: 0, maximum value: 1500, default value: 250.
+# This tag requires that the tag GENERATE_HTML is set to YES.
+
+TREEVIEW_WIDTH = 250
+
+# When the EXT_LINKS_IN_WINDOW option is set to YES doxygen will open links to
+# external symbols imported via tag files in a separate window.
+# The default value is: NO.
+# This tag requires that the tag GENERATE_HTML is set to YES.
+
+EXT_LINKS_IN_WINDOW = NO
+
+# Use this tag to change the font size of LaTeX formulas included as images in
+# the HTML documentation. When you change the font size after a successful
+# doxygen run you need to manually remove any form_*.png images from the HTML
+# output directory to force them to be regenerated.
+# Minimum value: 8, maximum value: 50, default value: 10.
+# This tag requires that the tag GENERATE_HTML is set to YES.
+
+FORMULA_FONTSIZE = 10
+
+# Use the FORMULA_TRANPARENT tag to determine whether or not the images
+# generated for formulas are transparent PNGs. Transparent PNGs are not
+# supported properly for IE 6.0, but are supported on all modern browsers.
+#
+# Note that when changing this option you need to delete any form_*.png files in
+# the HTML output directory before the changes have effect.
+# The default value is: YES.
+# This tag requires that the tag GENERATE_HTML is set to YES.
+
+FORMULA_TRANSPARENT = YES
+
+# Enable the USE_MATHJAX option to render LaTeX formulas using MathJax (see
+# http://www.mathjax.org) which uses client side Javascript for the rendering
+# instead of using prerendered bitmaps. Use this if you do not have LaTeX
+# installed or if you want to formulas look prettier in the HTML output. When
+# enabled you may also need to install MathJax separately and configure the path
+# to it using the MATHJAX_RELPATH option.
+# The default value is: NO.
+# This tag requires that the tag GENERATE_HTML is set to YES.
+
+USE_MATHJAX = NO
+
+# When MathJax is enabled you can set the default output format to be used for
+# the MathJax output. See the MathJax site (see:
+# http://docs.mathjax.org/en/latest/output.html) for more details.
+# Possible values are: HTML-CSS (which is slower, but has the best
+# compatibility), NativeMML (i.e. MathML) and SVG.
+# The default value is: HTML-CSS.
+# This tag requires that the tag USE_MATHJAX is set to YES.
+
+MATHJAX_FORMAT = HTML-CSS
+
+# When MathJax is enabled you need to specify the location relative to the HTML
+# output directory using the MATHJAX_RELPATH option. The destination directory
+# should contain the MathJax.js script. For instance, if the mathjax directory
+# is located at the same level as the HTML output directory, then
+# MATHJAX_RELPATH should be ../mathjax. The default value points to the MathJax
+# Content Delivery Network so you can quickly see the result without installing
+# MathJax. However, it is strongly recommended to install a local copy of
+# MathJax from http://www.mathjax.org before deployment.
+# The default value is: http://cdn.mathjax.org/mathjax/latest.
+# This tag requires that the tag USE_MATHJAX is set to YES.
+
+MATHJAX_RELPATH = http://cdn.mathjax.org/mathjax/latest
+
+# The MATHJAX_EXTENSIONS tag can be used to specify one or more MathJax
+# extension names that should be enabled during MathJax rendering. For example
+# MATHJAX_EXTENSIONS = TeX/AMSmath TeX/AMSsymbols
+# This tag requires that the tag USE_MATHJAX is set to YES.
+
+MATHJAX_EXTENSIONS =
+
+# The MATHJAX_CODEFILE tag can be used to specify a file with javascript pieces
+# of code that will be used on startup of the MathJax code. See the MathJax site
+# (see: http://docs.mathjax.org/en/latest/output.html) for more details. For an
+# example see the documentation.
+# This tag requires that the tag USE_MATHJAX is set to YES.
+
+MATHJAX_CODEFILE =
+
+# When the SEARCHENGINE tag is enabled doxygen will generate a search box for
+# the HTML output. The underlying search engine uses javascript and DHTML and
+# should work on any modern browser. Note that when using HTML help
+# (GENERATE_HTMLHELP), Qt help (GENERATE_QHP), or docsets (GENERATE_DOCSET)
+# there is already a search function so this one should typically be disabled.
+# For large projects the javascript based search engine can be slow, then
+# enabling SERVER_BASED_SEARCH may provide a better solution. It is possible to
+# search using the keyboard; to jump to the search box use <access key> + S
+# (what the <access key> is depends on the OS and browser, but it is typically
+# <CTRL>, <ALT>/<option>, or both). Inside the search box use the <cursor down
+# key> to jump into the search results window, the results can be navigated
+# using the <cursor keys>. Press <Enter> to select an item or <escape> to cancel
+# the search. The filter options can be selected when the cursor is inside the
+# search box by pressing <Shift>+<cursor down>. Also here use the <cursor keys>
+# to select a filter and <Enter> or <escape> to activate or cancel the filter
+# option.
+# The default value is: YES.
+# This tag requires that the tag GENERATE_HTML is set to YES.
+
+SEARCHENGINE = YES
+
+# When the SERVER_BASED_SEARCH tag is enabled the search engine will be
+# implemented using a web server instead of a web client using Javascript. There
+# are two flavors of web server based searching depending on the EXTERNAL_SEARCH
+# setting. When disabled, doxygen will generate a PHP script for searching and
+# an index file used by the script. When EXTERNAL_SEARCH is enabled the indexing
+# and searching needs to be provided by external tools. See the section
+# "External Indexing and Searching" for details.
+# The default value is: NO.
+# This tag requires that the tag SEARCHENGINE is set to YES.
+
+SERVER_BASED_SEARCH = NO
+
+# When EXTERNAL_SEARCH tag is enabled doxygen will no longer generate the PHP
+# script for searching. Instead the search results are written to an XML file
+# which needs to be processed by an external indexer. Doxygen will invoke an
+# external search engine pointed to by the SEARCHENGINE_URL option to obtain the
+# search results.
+#
+# Doxygen ships with an example indexer ( doxyindexer) and search engine
+# (doxysearch.cgi) which are based on the open source search engine library
+# Xapian (see: http://xapian.org/).
+#
+# See the section "External Indexing and Searching" for details.
+# The default value is: NO.
+# This tag requires that the tag SEARCHENGINE is set to YES.
+
+EXTERNAL_SEARCH = NO
+
+# The SEARCHENGINE_URL should point to a search engine hosted by a web server
+# which will return the search results when EXTERNAL_SEARCH is enabled.
+#
+# Doxygen ships with an example indexer ( doxyindexer) and search engine
+# (doxysearch.cgi) which are based on the open source search engine library
+# Xapian (see: http://xapian.org/). See the section "External Indexing and
+# Searching" for details.
+# This tag requires that the tag SEARCHENGINE is set to YES.
+
+SEARCHENGINE_URL =
+
+# When SERVER_BASED_SEARCH and EXTERNAL_SEARCH are both enabled the unindexed
+# search data is written to a file for indexing by an external tool. With the
+# SEARCHDATA_FILE tag the name of this file can be specified.
+# The default file is: searchdata.xml.
+# This tag requires that the tag SEARCHENGINE is set to YES.
+
+SEARCHDATA_FILE = searchdata.xml
+
+# When SERVER_BASED_SEARCH and EXTERNAL_SEARCH are both enabled the
+# EXTERNAL_SEARCH_ID tag can be used as an identifier for the project. This is
+# useful in combination with EXTRA_SEARCH_MAPPINGS to search through multiple
+# projects and redirect the results back to the right project.
+# This tag requires that the tag SEARCHENGINE is set to YES.
+
+EXTERNAL_SEARCH_ID =
+
+# The EXTRA_SEARCH_MAPPINGS tag can be used to enable searching through doxygen
+# projects other than the one defined by this configuration file, but that are
+# all added to the same external search index. Each project needs to have a
+# unique id set via EXTERNAL_SEARCH_ID. The search mapping then maps the id of
+# to a relative location where the documentation can be found. The format is:
+# EXTRA_SEARCH_MAPPINGS = tagname1=loc1 tagname2=loc2 ...
+# This tag requires that the tag SEARCHENGINE is set to YES.
+
+EXTRA_SEARCH_MAPPINGS =
+
+#---------------------------------------------------------------------------
+# Configuration options related to the LaTeX output
+#---------------------------------------------------------------------------
+
+# If the GENERATE_LATEX tag is set to YES doxygen will generate LaTeX output.
+# The default value is: YES.
+
+GENERATE_LATEX = YES
+
+# The LATEX_OUTPUT tag is used to specify where the LaTeX docs will be put. If a
+# relative path is entered the value of OUTPUT_DIRECTORY will be put in front of
+# it.
+# The default directory is: latex.
+# This tag requires that the tag GENERATE_LATEX is set to YES.
+
+LATEX_OUTPUT = latex
+
+# The LATEX_CMD_NAME tag can be used to specify the LaTeX command name to be
+# invoked.
+#
+# Note that when enabling USE_PDFLATEX this option is only used for generating
+# bitmaps for formulas in the HTML output, but not in the Makefile that is
+# written to the output directory.
+# The default file is: latex.
+# This tag requires that the tag GENERATE_LATEX is set to YES.
+
+LATEX_CMD_NAME = latex
+
+# The MAKEINDEX_CMD_NAME tag can be used to specify the command name to generate
+# index for LaTeX.
+# The default file is: makeindex.
+# This tag requires that the tag GENERATE_LATEX is set to YES.
+
+MAKEINDEX_CMD_NAME = makeindex
+
+# If the COMPACT_LATEX tag is set to YES doxygen generates more compact LaTeX
+# documents. This may be useful for small projects and may help to save some
+# trees in general.
+# The default value is: NO.
+# This tag requires that the tag GENERATE_LATEX is set to YES.
+
+COMPACT_LATEX = NO
+
+# The PAPER_TYPE tag can be used to set the paper type that is used by the
+# printer.
+# Possible values are: a4 (210 x 297 mm), letter (8.5 x 11 inches), legal (8.5 x
+# 14 inches) and executive (7.25 x 10.5 inches).
+# The default value is: a4.
+# This tag requires that the tag GENERATE_LATEX is set to YES.
+
+PAPER_TYPE = a4
+
+# The EXTRA_PACKAGES tag can be used to specify one or more LaTeX package names
+# that should be included in the LaTeX output. To get the times font for
+# instance you can specify
+# EXTRA_PACKAGES=times
+# If left blank no extra packages will be included.
+# This tag requires that the tag GENERATE_LATEX is set to YES.
+
+EXTRA_PACKAGES =
+
+# The LATEX_HEADER tag can be used to specify a personal LaTeX header for the
+# generated LaTeX document. The header should contain everything until the first
+# chapter. If it is left blank doxygen will generate a standard header. See
+# section "Doxygen usage" for information on how to let doxygen write the
+# default header to a separate file.
+#
+# Note: Only use a user-defined header if you know what you are doing! The
+# following commands have a special meaning inside the header: $title,
+# $datetime, $date, $doxygenversion, $projectname, $projectnumber,
+# $projectbrief, $projectlogo. Doxygen will replace $title with the empy string,
+# for the replacement values of the other commands the user is refered to
+# HTML_HEADER.
+# This tag requires that the tag GENERATE_LATEX is set to YES.
+
+LATEX_HEADER =
+
+# The LATEX_FOOTER tag can be used to specify a personal LaTeX footer for the
+# generated LaTeX document. The footer should contain everything after the last
+# chapter. If it is left blank doxygen will generate a standard footer. See
+# LATEX_HEADER for more information on how to generate a default footer and what
+# special commands can be used inside the footer.
+#
+# Note: Only use a user-defined footer if you know what you are doing!
+# This tag requires that the tag GENERATE_LATEX is set to YES.
+
+LATEX_FOOTER =
+
+# The LATEX_EXTRA_FILES tag can be used to specify one or more extra images or
+# other source files which should be copied to the LATEX_OUTPUT output
+# directory. Note that the files will be copied as-is; there are no commands or
+# markers available.
+# This tag requires that the tag GENERATE_LATEX is set to YES.
+
+LATEX_EXTRA_FILES =
+
+# If the PDF_HYPERLINKS tag is set to YES, the LaTeX that is generated is
+# prepared for conversion to PDF (using ps2pdf or pdflatex). The PDF file will
+# contain links (just like the HTML output) instead of page references. This
+# makes the output suitable for online browsing using a PDF viewer.
+# The default value is: YES.
+# This tag requires that the tag GENERATE_LATEX is set to YES.
+
+PDF_HYPERLINKS = YES
+
+# If the USE_PDFLATEX tag is set to YES, doxygen will use pdflatex to generate
+# the PDF file directly from the LaTeX files. Set this option to YES to get a
+# higher quality PDF documentation.
+# The default value is: YES.
+# This tag requires that the tag GENERATE_LATEX is set to YES.
+
+USE_PDFLATEX = YES
+
+# If the LATEX_BATCHMODE tag is set to YES, doxygen will add the \batchmode
+# command to the generated LaTeX files. This will instruct LaTeX to keep running
+# if errors occur, instead of asking the user for help. This option is also used
+# when generating formulas in HTML.
+# The default value is: NO.
+# This tag requires that the tag GENERATE_LATEX is set to YES.
+
+LATEX_BATCHMODE = NO
+
+# If the LATEX_HIDE_INDICES tag is set to YES then doxygen will not include the
+# index chapters (such as File Index, Compound Index, etc.) in the output.
+# The default value is: NO.
+# This tag requires that the tag GENERATE_LATEX is set to YES.
+
+LATEX_HIDE_INDICES = NO
+
+# If the LATEX_SOURCE_CODE tag is set to YES then doxygen will include source
+# code with syntax highlighting in the LaTeX output.
+#
+# Note that which sources are shown also depends on other settings such as
+# SOURCE_BROWSER.
+# The default value is: NO.
+# This tag requires that the tag GENERATE_LATEX is set to YES.
+
+LATEX_SOURCE_CODE = NO
+
+# The LATEX_BIB_STYLE tag can be used to specify the style to use for the
+# bibliography, e.g. plainnat, or ieeetr. See
+# http://en.wikipedia.org/wiki/BibTeX and \cite for more info.
+# The default value is: plain.
+# This tag requires that the tag GENERATE_LATEX is set to YES.
+
+LATEX_BIB_STYLE = plain
+
+#---------------------------------------------------------------------------
+# Configuration options related to the RTF output
+#---------------------------------------------------------------------------
+
+# If the GENERATE_RTF tag is set to YES doxygen will generate RTF output. The
+# RTF output is optimized for Word 97 and may not look too pretty with other RTF
+# readers/editors.
+# The default value is: NO.
+
+GENERATE_RTF = NO
+
+# The RTF_OUTPUT tag is used to specify where the RTF docs will be put. If a
+# relative path is entered the value of OUTPUT_DIRECTORY will be put in front of
+# it.
+# The default directory is: rtf.
+# This tag requires that the tag GENERATE_RTF is set to YES.
+
+RTF_OUTPUT = rtf
+
+# If the COMPACT_RTF tag is set to YES doxygen generates more compact RTF
+# documents. This may be useful for small projects and may help to save some
+# trees in general.
+# The default value is: NO.
+# This tag requires that the tag GENERATE_RTF is set to YES.
+
+COMPACT_RTF = NO
+
+# If the RTF_HYPERLINKS tag is set to YES, the RTF that is generated will
+# contain hyperlink fields. The RTF file will contain links (just like the HTML
+# output) instead of page references. This makes the output suitable for online
+# browsing using Word or some other Word compatible readers that support those
+# fields.
+#
+# Note: WordPad (write) and others do not support links.
+# The default value is: NO.
+# This tag requires that the tag GENERATE_RTF is set to YES.
+
+RTF_HYPERLINKS = NO
+
+# Load stylesheet definitions from file. Syntax is similar to doxygen's config
+# file, i.e. a series of assignments. You only have to provide replacements,
+# missing definitions are set to their default value.
+#
+# See also section "Doxygen usage" for information on how to generate the
+# default style sheet that doxygen normally uses.
+# This tag requires that the tag GENERATE_RTF is set to YES.
+
+RTF_STYLESHEET_FILE =
+
+# Set optional variables used in the generation of an RTF document. Syntax is
+# similar to doxygen's config file. A template extensions file can be generated
+# using doxygen -e rtf extensionFile.
+# This tag requires that the tag GENERATE_RTF is set to YES.
+
+RTF_EXTENSIONS_FILE =
+
+#---------------------------------------------------------------------------
+# Configuration options related to the man page output
+#---------------------------------------------------------------------------
+
+# If the GENERATE_MAN tag is set to YES doxygen will generate man pages for
+# classes and files.
+# The default value is: NO.
+
+GENERATE_MAN = NO
+
+# The MAN_OUTPUT tag is used to specify where the man pages will be put. If a
+# relative path is entered the value of OUTPUT_DIRECTORY will be put in front of
+# it. A directory man3 will be created inside the directory specified by
+# MAN_OUTPUT.
+# The default directory is: man.
+# This tag requires that the tag GENERATE_MAN is set to YES.
+
+MAN_OUTPUT = man
+
+# The MAN_EXTENSION tag determines the extension that is added to the generated
+# man pages. In case the manual section does not start with a number, the number
+# 3 is prepended. The dot (.) at the beginning of the MAN_EXTENSION tag is
+# optional.
+# The default value is: .3.
+# This tag requires that the tag GENERATE_MAN is set to YES.
+
+MAN_EXTENSION = .3
+
+# The MAN_SUBDIR tag determines the name of the directory created within
+# MAN_OUTPUT in which the man pages are placed. If defaults to man followed by
+# MAN_EXTENSION with the initial . removed.
+# This tag requires that the tag GENERATE_MAN is set to YES.
+
+MAN_SUBDIR =
+
+# If the MAN_LINKS tag is set to YES and doxygen generates man output, then it
+# will generate one additional man file for each entity documented in the real
+# man page(s). These additional files only source the real man page, but without
+# them the man command would be unable to find the correct page.
+# The default value is: NO.
+# This tag requires that the tag GENERATE_MAN is set to YES.
+
+MAN_LINKS = NO
+
+#---------------------------------------------------------------------------
+# Configuration options related to the XML output
+#---------------------------------------------------------------------------
+
+# If the GENERATE_XML tag is set to YES doxygen will generate an XML file that
+# captures the structure of the code including all documentation.
+# The default value is: NO.
+
+GENERATE_XML = NO
+
+# The XML_OUTPUT tag is used to specify where the XML pages will be put. If a
+# relative path is entered the value of OUTPUT_DIRECTORY will be put in front of
+# it.
+# The default directory is: xml.
+# This tag requires that the tag GENERATE_XML is set to YES.
+
+XML_OUTPUT = xml
+
+# If the XML_PROGRAMLISTING tag is set to YES doxygen will dump the program
+# listings (including syntax highlighting and cross-referencing information) to
+# the XML output. Note that enabling this will significantly increase the size
+# of the XML output.
+# The default value is: YES.
+# This tag requires that the tag GENERATE_XML is set to YES.
+
+XML_PROGRAMLISTING = YES
+
+#---------------------------------------------------------------------------
+# Configuration options related to the DOCBOOK output
+#---------------------------------------------------------------------------
+
+# If the GENERATE_DOCBOOK tag is set to YES doxygen will generate Docbook files
+# that can be used to generate PDF.
+# The default value is: NO.
+
+GENERATE_DOCBOOK = NO
+
+# The DOCBOOK_OUTPUT tag is used to specify where the Docbook pages will be put.
+# If a relative path is entered the value of OUTPUT_DIRECTORY will be put in
+# front of it.
+# The default directory is: docbook.
+# This tag requires that the tag GENERATE_DOCBOOK is set to YES.
+
+DOCBOOK_OUTPUT = docbook
+
+# If the DOCBOOK_PROGRAMLISTING tag is set to YES doxygen will include the
+# program listings (including syntax highlighting and cross-referencing
+# information) to the DOCBOOK output. Note that enabling this will significantly
+# increase the size of the DOCBOOK output.
+# The default value is: NO.
+# This tag requires that the tag GENERATE_DOCBOOK is set to YES.
+
+DOCBOOK_PROGRAMLISTING = NO
+
+#---------------------------------------------------------------------------
+# Configuration options for the AutoGen Definitions output
+#---------------------------------------------------------------------------
+
+# If the GENERATE_AUTOGEN_DEF tag is set to YES doxygen will generate an AutoGen
+# Definitions (see http://autogen.sf.net) file that captures the structure of
+# the code including all documentation. Note that this feature is still
+# experimental and incomplete at the moment.
+# The default value is: NO.
+
+GENERATE_AUTOGEN_DEF = NO
+
+#---------------------------------------------------------------------------
+# Configuration options related to the Perl module output
+#---------------------------------------------------------------------------
+
+# If the GENERATE_PERLMOD tag is set to YES doxygen will generate a Perl module
+# file that captures the structure of the code including all documentation.
+#
+# Note that this feature is still experimental and incomplete at the moment.
+# The default value is: NO.
+
+GENERATE_PERLMOD = NO
+
+# If the PERLMOD_LATEX tag is set to YES doxygen will generate the necessary
+# Makefile rules, Perl scripts and LaTeX code to be able to generate PDF and DVI
+# output from the Perl module output.
+# The default value is: NO.
+# This tag requires that the tag GENERATE_PERLMOD is set to YES.
+
+PERLMOD_LATEX = NO
+
+# If the PERLMOD_PRETTY tag is set to YES the Perl module output will be nicely
+# formatted so it can be parsed by a human reader. This is useful if you want to
+# understand what is going on. On the other hand, if this tag is set to NO the
+# size of the Perl module output will be much smaller and Perl will parse it
+# just the same.
+# The default value is: YES.
+# This tag requires that the tag GENERATE_PERLMOD is set to YES.
+
+PERLMOD_PRETTY = YES
+
+# The names of the make variables in the generated doxyrules.make file are
+# prefixed with the string contained in PERLMOD_MAKEVAR_PREFIX. This is useful
+# so different doxyrules.make files included by the same Makefile don't
+# overwrite each other's variables.
+# This tag requires that the tag GENERATE_PERLMOD is set to YES.
+
+PERLMOD_MAKEVAR_PREFIX =
+
+#---------------------------------------------------------------------------
+# Configuration options related to the preprocessor
+#---------------------------------------------------------------------------
+
+# If the ENABLE_PREPROCESSING tag is set to YES doxygen will evaluate all
+# C-preprocessor directives found in the sources and include files.
+# The default value is: YES.
+
+ENABLE_PREPROCESSING = YES
+
+# If the MACRO_EXPANSION tag is set to YES doxygen will expand all macro names
+# in the source code. If set to NO only conditional compilation will be
+# performed. Macro expansion can be done in a controlled way by setting
+# EXPAND_ONLY_PREDEF to YES.
+# The default value is: NO.
+# This tag requires that the tag ENABLE_PREPROCESSING is set to YES.
+
+MACRO_EXPANSION = NO
+
+# If the EXPAND_ONLY_PREDEF and MACRO_EXPANSION tags are both set to YES then
+# the macro expansion is limited to the macros specified with the PREDEFINED and
+# EXPAND_AS_DEFINED tags.
+# The default value is: NO.
+# This tag requires that the tag ENABLE_PREPROCESSING is set to YES.
+
+EXPAND_ONLY_PREDEF = NO
+
+# If the SEARCH_INCLUDES tag is set to YES the includes files in the
+# INCLUDE_PATH will be searched if a #include is found.
+# The default value is: YES.
+# This tag requires that the tag ENABLE_PREPROCESSING is set to YES.
+
+SEARCH_INCLUDES = YES
+
+# The INCLUDE_PATH tag can be used to specify one or more directories that
+# contain include files that are not input files but should be processed by the
+# preprocessor.
+# This tag requires that the tag SEARCH_INCLUDES is set to YES.
+
+INCLUDE_PATH =
+
+# You can use the INCLUDE_FILE_PATTERNS tag to specify one or more wildcard
+# patterns (like *.h and *.hpp) to filter out the header-files in the
+# directories. If left blank, the patterns specified with FILE_PATTERNS will be
+# used.
+# This tag requires that the tag ENABLE_PREPROCESSING is set to YES.
+
+INCLUDE_FILE_PATTERNS =
+
+# The PREDEFINED tag can be used to specify one or more macro names that are
+# defined before the preprocessor is started (similar to the -D option of e.g.
+# gcc). The argument of the tag is a list of macros of the form: name or
+# name=definition (no spaces). If the definition and the "=" are omitted, "=1"
+# is assumed. To prevent a macro definition from being undefined via #undef or
+# recursively expanded use the := operator instead of the = operator.
+# This tag requires that the tag ENABLE_PREPROCESSING is set to YES.
+
+PREDEFINED =
+
+# If the MACRO_EXPANSION and EXPAND_ONLY_PREDEF tags are set to YES then this
+# tag can be used to specify a list of macro names that should be expanded. The
+# macro definition that is found in the sources will be used. Use the PREDEFINED
+# tag if you want to use a different macro definition that overrules the
+# definition found in the source code.
+# This tag requires that the tag ENABLE_PREPROCESSING is set to YES.
+
+EXPAND_AS_DEFINED =
+
+# If the SKIP_FUNCTION_MACROS tag is set to YES then doxygen's preprocessor will
+# remove all references to function-like macros that are alone on a line, have
+# an all uppercase name, and do not end with a semicolon. Such function macros
+# are typically used for boiler-plate code, and will confuse the parser if not
+# removed.
+# The default value is: YES.
+# This tag requires that the tag ENABLE_PREPROCESSING is set to YES.
+
+SKIP_FUNCTION_MACROS = YES
+
+#---------------------------------------------------------------------------
+# Configuration options related to external references
+#---------------------------------------------------------------------------
+
+# The TAGFILES tag can be used to specify one or more tag files. For each tag
+# file the location of the external documentation should be added. The format of
+# a tag file without this location is as follows:
+# TAGFILES = file1 file2 ...
+# Adding location for the tag files is done as follows:
+# TAGFILES = file1=loc1 "file2 = loc2" ...
+# where loc1 and loc2 can be relative or absolute paths or URLs. See the
+# section "Linking to external documentation" for more information about the use
+# of tag files.
+# Note: Each tag file must have a unique name (where the name does NOT include
+# the path). If a tag file is not located in the directory in which doxygen is
+# run, you must also specify the path to the tagfile here.
+
+TAGFILES =
+
+# When a file name is specified after GENERATE_TAGFILE, doxygen will create a
+# tag file that is based on the input files it reads. See section "Linking to
+# external documentation" for more information about the usage of tag files.
+
+GENERATE_TAGFILE =
+
+# If the ALLEXTERNALS tag is set to YES all external class will be listed in the
+# class index. If set to NO only the inherited external classes will be listed.
+# The default value is: NO.
+
+ALLEXTERNALS = NO
+
+# If the EXTERNAL_GROUPS tag is set to YES all external groups will be listed in
+# the modules index. If set to NO, only the current project's groups will be
+# listed.
+# The default value is: YES.
+
+EXTERNAL_GROUPS = YES
+
+# If the EXTERNAL_PAGES tag is set to YES all external pages will be listed in
+# the related pages index. If set to NO, only the current project's pages will
+# be listed.
+# The default value is: YES.
+
+EXTERNAL_PAGES = YES
+
+# The PERL_PATH should be the absolute path and name of the perl script
+# interpreter (i.e. the result of 'which perl').
+# The default file (with absolute path) is: /usr/bin/perl.
+
+PERL_PATH = /usr/bin/perl
+
+#---------------------------------------------------------------------------
+# Configuration options related to the dot tool
+#---------------------------------------------------------------------------
+
+# If the CLASS_DIAGRAMS tag is set to YES doxygen will generate a class diagram
+# (in HTML and LaTeX) for classes with base or super classes. Setting the tag to
+# NO turns the diagrams off. Note that this option also works with HAVE_DOT
+# disabled, but it is recommended to install and use dot, since it yields more
+# powerful graphs.
+# The default value is: YES.
+
+CLASS_DIAGRAMS = YES
+
+# You can define message sequence charts within doxygen comments using the \msc
+# command. Doxygen will then run the mscgen tool (see:
+# http://www.mcternan.me.uk/mscgen/)) to produce the chart and insert it in the
+# documentation. The MSCGEN_PATH tag allows you to specify the directory where
+# the mscgen tool resides. If left empty the tool is assumed to be found in the
+# default search path.
+
+MSCGEN_PATH =
+
+# You can include diagrams made with dia in doxygen documentation. Doxygen will
+# then run dia to produce the diagram and insert it in the documentation. The
+# DIA_PATH tag allows you to specify the directory where the dia binary resides.
+# If left empty dia is assumed to be found in the default search path.
+
+DIA_PATH =
+
+# If set to YES, the inheritance and collaboration graphs will hide inheritance
+# and usage relations if the target is undocumented or is not a class.
+# The default value is: YES.
+
+HIDE_UNDOC_RELATIONS = YES
+
+# If you set the HAVE_DOT tag to YES then doxygen will assume the dot tool is
+# available from the path. This tool is part of Graphviz (see:
+# http://www.graphviz.org/), a graph visualization toolkit from AT&T and Lucent
+# Bell Labs. The other options in this section have no effect if this option is
+# set to NO
+# The default value is: YES.
+
+HAVE_DOT = @HAVE_DOT@
+
+# The DOT_NUM_THREADS specifies the number of dot invocations doxygen is allowed
+# to run in parallel. When set to 0 doxygen will base this on the number of
+# processors available in the system. You can set it explicitly to a value
+# larger than 0 to get control over the balance between CPU load and processing
+# speed.
+# Minimum value: 0, maximum value: 32, default value: 0.
+# This tag requires that the tag HAVE_DOT is set to YES.
+
+DOT_NUM_THREADS = 0
+
+# When you want a differently looking font in the dot files that doxygen
+# generates you can specify the font name using DOT_FONTNAME. You need to make
+# sure dot is able to find the font, which can be done by putting it in a
+# standard location or by setting the DOTFONTPATH environment variable or by
+# setting DOT_FONTPATH to the directory containing the font.
+# The default value is: Helvetica.
+# This tag requires that the tag HAVE_DOT is set to YES.
+
+DOT_FONTNAME = Helvetica
+
+# The DOT_FONTSIZE tag can be used to set the size (in points) of the font of
+# dot graphs.
+# Minimum value: 4, maximum value: 24, default value: 10.
+# This tag requires that the tag HAVE_DOT is set to YES.
+
+DOT_FONTSIZE = 10
+
+# By default doxygen will tell dot to use the default font as specified with
+# DOT_FONTNAME. If you specify a different font using DOT_FONTNAME you can set
+# the path where dot can find it using this tag.
+# This tag requires that the tag HAVE_DOT is set to YES.
+
+DOT_FONTPATH =
+
+# If the CLASS_GRAPH tag is set to YES then doxygen will generate a graph for
+# each documented class showing the direct and indirect inheritance relations.
+# Setting this tag to YES will force the CLASS_DIAGRAMS tag to NO.
+# The default value is: YES.
+# This tag requires that the tag HAVE_DOT is set to YES.
+
+CLASS_GRAPH = YES
+
+# If the COLLABORATION_GRAPH tag is set to YES then doxygen will generate a
+# graph for each documented class showing the direct and indirect implementation
+# dependencies (inheritance, containment, and class references variables) of the
+# class with other documented classes.
+# The default value is: YES.
+# This tag requires that the tag HAVE_DOT is set to YES.
+
+COLLABORATION_GRAPH = YES
+
+# If the GROUP_GRAPHS tag is set to YES then doxygen will generate a graph for
+# groups, showing the direct groups dependencies.
+# The default value is: YES.
+# This tag requires that the tag HAVE_DOT is set to YES.
+
+GROUP_GRAPHS = YES
+
+# If the UML_LOOK tag is set to YES doxygen will generate inheritance and
+# collaboration diagrams in a style similar to the OMG's Unified Modeling
+# Language.
+# The default value is: NO.
+# This tag requires that the tag HAVE_DOT is set to YES.
+
+UML_LOOK = NO
+
+# If the UML_LOOK tag is enabled, the fields and methods are shown inside the
+# class node. If there are many fields or methods and many nodes the graph may
+# become too big to be useful. The UML_LIMIT_NUM_FIELDS threshold limits the
+# number of items for each type to make the size more manageable. Set this to 0
+# for no limit. Note that the threshold may be exceeded by 50% before the limit
+# is enforced. So when you set the threshold to 10, up to 15 fields may appear,
+# but if the number exceeds 15, the total amount of fields shown is limited to
+# 10.
+# Minimum value: 0, maximum value: 100, default value: 10.
+# This tag requires that the tag HAVE_DOT is set to YES.
+
+UML_LIMIT_NUM_FIELDS = 10
+
+# If the TEMPLATE_RELATIONS tag is set to YES then the inheritance and
+# collaboration graphs will show the relations between templates and their
+# instances.
+# The default value is: NO.
+# This tag requires that the tag HAVE_DOT is set to YES.
+
+TEMPLATE_RELATIONS = NO
+
+# If the INCLUDE_GRAPH, ENABLE_PREPROCESSING and SEARCH_INCLUDES tags are set to
+# YES then doxygen will generate a graph for each documented file showing the
+# direct and indirect include dependencies of the file with other documented
+# files.
+# The default value is: YES.
+# This tag requires that the tag HAVE_DOT is set to YES.
+
+INCLUDE_GRAPH = YES
+
+# If the INCLUDED_BY_GRAPH, ENABLE_PREPROCESSING and SEARCH_INCLUDES tags are
+# set to YES then doxygen will generate a graph for each documented file showing
+# the direct and indirect include dependencies of the file with other documented
+# files.
+# The default value is: YES.
+# This tag requires that the tag HAVE_DOT is set to YES.
+
+INCLUDED_BY_GRAPH = YES
+
+# If the CALL_GRAPH tag is set to YES then doxygen will generate a call
+# dependency graph for every global function or class method.
+#
+# Note that enabling this option will significantly increase the time of a run.
+# So in most cases it will be better to enable call graphs for selected
+# functions only using the \callgraph command.
+# The default value is: NO.
+# This tag requires that the tag HAVE_DOT is set to YES.
+
+CALL_GRAPH = NO
+
+# If the CALLER_GRAPH tag is set to YES then doxygen will generate a caller
+# dependency graph for every global function or class method.
+#
+# Note that enabling this option will significantly increase the time of a run.
+# So in most cases it will be better to enable caller graphs for selected
+# functions only using the \callergraph command.
+# The default value is: NO.
+# This tag requires that the tag HAVE_DOT is set to YES.
+
+CALLER_GRAPH = NO
+
+# If the GRAPHICAL_HIERARCHY tag is set to YES then doxygen will graphical
+# hierarchy of all classes instead of a textual one.
+# The default value is: YES.
+# This tag requires that the tag HAVE_DOT is set to YES.
+
+GRAPHICAL_HIERARCHY = YES
+
+# If the DIRECTORY_GRAPH tag is set to YES then doxygen will show the
+# dependencies a directory has on other directories in a graphical way. The
+# dependency relations are determined by the #include relations between the
+# files in the directories.
+# The default value is: YES.
+# This tag requires that the tag HAVE_DOT is set to YES.
+
+DIRECTORY_GRAPH = YES
+
+# The DOT_IMAGE_FORMAT tag can be used to set the image format of the images
+# generated by dot.
+# Note: If you choose svg you need to set HTML_FILE_EXTENSION to xhtml in order
+# to make the SVG files visible in IE 9+ (other browsers do not have this
+# requirement).
+# Possible values are: png, png:cairo, png:cairo:cairo, png:cairo:gd, png:gd,
+# png:gd:gd, jpg, jpg:cairo, jpg:cairo:gd, jpg:gd, jpg:gd:gd, gif, gif:cairo,
+# gif:cairo:gd, gif:gd, gif:gd:gd and svg.
+# The default value is: png.
+# This tag requires that the tag HAVE_DOT is set to YES.
+
+DOT_IMAGE_FORMAT = png
+
+# If DOT_IMAGE_FORMAT is set to svg, then this option can be set to YES to
+# enable generation of interactive SVG images that allow zooming and panning.
+#
+# Note that this requires a modern browser other than Internet Explorer. Tested
+# and working are Firefox, Chrome, Safari, and Opera.
+# Note: For IE 9+ you need to set HTML_FILE_EXTENSION to xhtml in order to make
+# the SVG files visible. Older versions of IE do not have SVG support.
+# The default value is: NO.
+# This tag requires that the tag HAVE_DOT is set to YES.
+
+INTERACTIVE_SVG = NO
+
+# The DOT_PATH tag can be used to specify the path where the dot tool can be
+# found. If left blank, it is assumed the dot tool can be found in the path.
+# This tag requires that the tag HAVE_DOT is set to YES.
+
+DOT_PATH =
+
+# The DOTFILE_DIRS tag can be used to specify one or more directories that
+# contain dot files that are included in the documentation (see the \dotfile
+# command).
+# This tag requires that the tag HAVE_DOT is set to YES.
+
+DOTFILE_DIRS =
+
+# The MSCFILE_DIRS tag can be used to specify one or more directories that
+# contain msc files that are included in the documentation (see the \mscfile
+# command).
+
+MSCFILE_DIRS =
+
+# The DIAFILE_DIRS tag can be used to specify one or more directories that
+# contain dia files that are included in the documentation (see the \diafile
+# command).
+
+DIAFILE_DIRS =
+
+# When using plantuml, the PLANTUML_JAR_PATH tag should be used to specify the
+# path where java can find the plantuml.jar file. If left blank, it is assumed
+# PlantUML is not used or called during a preprocessing step. Doxygen will
+# generate a warning when it encounters a \startuml command in this case and
+# will not generate output for the diagram.
+# This tag requires that the tag HAVE_DOT is set to YES.
+
+PLANTUML_JAR_PATH =
+
+# The DOT_GRAPH_MAX_NODES tag can be used to set the maximum number of nodes
+# that will be shown in the graph. If the number of nodes in a graph becomes
+# larger than this value, doxygen will truncate the graph, which is visualized
+# by representing a node as a red box. Note that doxygen if the number of direct
+# children of the root node in a graph is already larger than
+# DOT_GRAPH_MAX_NODES then the graph will not be shown at all. Also note that
+# the size of a graph can be further restricted by MAX_DOT_GRAPH_DEPTH.
+# Minimum value: 0, maximum value: 10000, default value: 50.
+# This tag requires that the tag HAVE_DOT is set to YES.
+
+DOT_GRAPH_MAX_NODES = 50
+
+# The MAX_DOT_GRAPH_DEPTH tag can be used to set the maximum depth of the graphs
+# generated by dot. A depth value of 3 means that only nodes reachable from the
+# root by following a path via at most 3 edges will be shown. Nodes that lay
+# further from the root node will be omitted. Note that setting this option to 1
+# or 2 may greatly reduce the computation time needed for large code bases. Also
+# note that the size of a graph can be further restricted by
+# DOT_GRAPH_MAX_NODES. Using a depth of 0 means no depth restriction.
+# Minimum value: 0, maximum value: 1000, default value: 0.
+# This tag requires that the tag HAVE_DOT is set to YES.
+
+MAX_DOT_GRAPH_DEPTH = 0
+
+# Set the DOT_TRANSPARENT tag to YES to generate images with a transparent
+# background. This is disabled by default, because dot on Windows does not seem
+# to support this out of the box.
+#
+# Warning: Depending on the platform used, enabling this option may lead to
+# badly anti-aliased labels on the edges of a graph (i.e. they become hard to
+# read).
+# The default value is: NO.
+# This tag requires that the tag HAVE_DOT is set to YES.
+
+DOT_TRANSPARENT = NO
+
+# Set the DOT_MULTI_TARGETS tag to YES allow dot to generate multiple output
+# files in one run (i.e. multiple -o and -T options on the command line). This
+# makes dot run faster, but since only newer versions of dot (>1.8.10) support
+# this, this feature is disabled by default.
+# The default value is: NO.
+# This tag requires that the tag HAVE_DOT is set to YES.
+
+DOT_MULTI_TARGETS = NO
+
+# If the GENERATE_LEGEND tag is set to YES doxygen will generate a legend page
+# explaining the meaning of the various boxes and arrows in the dot generated
+# graphs.
+# The default value is: YES.
+# This tag requires that the tag HAVE_DOT is set to YES.
+
+GENERATE_LEGEND = YES
+
+# If the DOT_CLEANUP tag is set to YES doxygen will remove the intermediate dot
+# files that are used to generate the various graphs.
+# The default value is: YES.
+# This tag requires that the tag HAVE_DOT is set to YES.
+
+DOT_CLEANUP = YES
diff --git a/lang/qt/doc/Makefile.am b/lang/qt/doc/Makefile.am
new file mode 100644
index 0000000..ddf4935
--- /dev/null
+++ b/lang/qt/doc/Makefile.am
@@ -0,0 +1,31 @@
+# Makefile.am - Makefile for GPGME Qt docs.
+# Copyright (C) 2016 Intevation GmbH
+#
+# This file is part of GPGME.
+#
+# GPGME is free software; you can redistribute it and/or modify it
+# under the terms of the GNU Lesser General Public License as
+# published by the Free Software Foundation; either version 2.1 of the
+# License, or (at your option) any later version.
+#
+# GPGME is distributed in the hope that it will be useful, but WITHOUT
+# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
+# or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General
+# Public License for more details.
+#
+# You should have received a copy of the GNU Lesser General Public
+# License along with this program; if not, see <http://www.gnu.org/licenses/>.
+
+## Process this file with automake to produce Makefile.in
+
+if HAVE_DOXYGEN
+doxyfile.stamp:
+ $(DOXYGEN) Doxyfile
+ touch doxyfile.stamp
+
+CLEANFILES = doxyfile.stamp
+
+all-local: doxyfile.stamp
+clean-local:
+ rm -rf $(abs_builddir)/generated
+endif
diff --git a/lang/qt/doc/Makefile.in b/lang/qt/doc/Makefile.in
new file mode 100644
index 0000000..d6d9ef7
--- /dev/null
+++ b/lang/qt/doc/Makefile.in
@@ -0,0 +1,540 @@
+# Makefile.in generated by automake 1.14.1 from Makefile.am.
+# @configure_input@
+
+# Copyright (C) 1994-2013 Free Software Foundation, Inc.
+
+# This Makefile.in is free software; the Free Software Foundation
+# gives unlimited permission to copy and/or distribute it,
+# with or without modifications, as long as this notice is preserved.
+
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY, to the extent permitted by law; without
+# even the implied warranty of MERCHANTABILITY or FITNESS FOR A
+# PARTICULAR PURPOSE.
+
+@SET_MAKE@
+
+# Makefile.am - Makefile for GPGME Qt docs.
+# Copyright (C) 2016 Intevation GmbH
+#
+# This file is part of GPGME.
+#
+# GPGME is free software; you can redistribute it and/or modify it
+# under the terms of the GNU Lesser General Public License as
+# published by the Free Software Foundation; either version 2.1 of the
+# License, or (at your option) any later version.
+#
+# GPGME is distributed in the hope that it will be useful, but WITHOUT
+# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
+# or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General
+# Public License for more details.
+#
+# You should have received a copy of the GNU Lesser General Public
+# License along with this program; if not, see <http://www.gnu.org/licenses/>.
+VPATH = @srcdir@
+am__is_gnu_make = test -n '$(MAKEFILE_LIST)' && test -n '$(MAKELEVEL)'
+am__make_running_with_option = \
+ case $${target_option-} in \
+ ?) ;; \
+ *) echo "am__make_running_with_option: internal error: invalid" \
+ "target option '$${target_option-}' specified" >&2; \
+ exit 1;; \
+ esac; \
+ has_opt=no; \
+ sane_makeflags=$$MAKEFLAGS; \
+ if $(am__is_gnu_make); then \
+ sane_makeflags=$$MFLAGS; \
+ else \
+ case $$MAKEFLAGS in \
+ *\\[\ \ ]*) \
+ bs=\\; \
+ sane_makeflags=`printf '%s\n' "$$MAKEFLAGS" \
+ | sed "s/$$bs$$bs[$$bs $$bs ]*//g"`;; \
+ esac; \
+ fi; \
+ skip_next=no; \
+ strip_trailopt () \
+ { \
+ flg=`printf '%s\n' "$$flg" | sed "s/$$1.*$$//"`; \
+ }; \
+ for flg in $$sane_makeflags; do \
+ test $$skip_next = yes && { skip_next=no; continue; }; \
+ case $$flg in \
+ *=*|--*) continue;; \
+ -*I) strip_trailopt 'I'; skip_next=yes;; \
+ -*I?*) strip_trailopt 'I';; \
+ -*O) strip_trailopt 'O'; skip_next=yes;; \
+ -*O?*) strip_trailopt 'O';; \
+ -*l) strip_trailopt 'l'; skip_next=yes;; \
+ -*l?*) strip_trailopt 'l';; \
+ -[dEDm]) skip_next=yes;; \
+ -[JT]) skip_next=yes;; \
+ esac; \
+ case $$flg in \
+ *$$target_option*) has_opt=yes; break;; \
+ esac; \
+ done; \
+ test $$has_opt = yes
+am__make_dryrun = (target_option=n; $(am__make_running_with_option))
+am__make_keepgoing = (target_option=k; $(am__make_running_with_option))
+pkgdatadir = $(datadir)/@PACKAGE@
+pkgincludedir = $(includedir)/@PACKAGE@
+pkglibdir = $(libdir)/@PACKAGE@
+pkglibexecdir = $(libexecdir)/@PACKAGE@
+am__cd = CDPATH="$${ZSH_VERSION+.}$(PATH_SEPARATOR)" && cd
+install_sh_DATA = $(install_sh) -c -m 644
+install_sh_PROGRAM = $(install_sh) -c
+install_sh_SCRIPT = $(install_sh) -c
+INSTALL_HEADER = $(INSTALL_DATA)
+transform = $(program_transform_name)
+NORMAL_INSTALL = :
+PRE_INSTALL = :
+POST_INSTALL = :
+NORMAL_UNINSTALL = :
+PRE_UNINSTALL = :
+POST_UNINSTALL = :
+build_triplet = @build@
+host_triplet = @host@
+subdir = lang/qt/doc
+DIST_COMMON = $(srcdir)/Makefile.in $(srcdir)/Makefile.am \
+ $(top_srcdir)/build-aux/mkinstalldirs $(srcdir)/Doxyfile.in
+ACLOCAL_M4 = $(top_srcdir)/aclocal.m4
+am__aclocal_m4_deps = $(top_srcdir)/m4/ax_cxx_compile_stdcxx.m4 \
+ $(top_srcdir)/m4/ax_pkg_swig.m4 \
+ $(top_srcdir)/m4/ax_python_devel.m4 \
+ $(top_srcdir)/m4/glib-2.0.m4 $(top_srcdir)/m4/glibc21.m4 \
+ $(top_srcdir)/m4/gnupg-ttyname.m4 \
+ $(top_srcdir)/m4/gpg-error.m4 $(top_srcdir)/m4/libassuan.m4 \
+ $(top_srcdir)/m4/libtool.m4 $(top_srcdir)/m4/ltoptions.m4 \
+ $(top_srcdir)/m4/ltsugar.m4 $(top_srcdir)/m4/ltversion.m4 \
+ $(top_srcdir)/m4/lt~obsolete.m4 $(top_srcdir)/m4/pkg.m4 \
+ $(top_srcdir)/m4/qt.m4 $(top_srcdir)/acinclude.m4 \
+ $(top_srcdir)/configure.ac
+am__configure_deps = $(am__aclocal_m4_deps) $(CONFIGURE_DEPENDENCIES) \
+ $(ACLOCAL_M4)
+mkinstalldirs = $(SHELL) $(top_srcdir)/build-aux/mkinstalldirs
+CONFIG_HEADER = $(top_builddir)/config.h
+CONFIG_CLEAN_FILES = Doxyfile
+CONFIG_CLEAN_VPATH_FILES =
+AM_V_P = $(am__v_P_@AM_V@)
+am__v_P_ = $(am__v_P_@AM_DEFAULT_V@)
+am__v_P_0 = false
+am__v_P_1 = :
+AM_V_GEN = $(am__v_GEN_@AM_V@)
+am__v_GEN_ = $(am__v_GEN_@AM_DEFAULT_V@)
+am__v_GEN_0 = @echo " GEN " $@;
+am__v_GEN_1 =
+AM_V_at = $(am__v_at_@AM_V@)
+am__v_at_ = $(am__v_at_@AM_DEFAULT_V@)
+am__v_at_0 = @
+am__v_at_1 =
+SOURCES =
+DIST_SOURCES =
+am__can_run_installinfo = \
+ case $$AM_UPDATE_INFO_DIR in \
+ n|no|NO) false;; \
+ *) (install-info --version) >/dev/null 2>&1;; \
+ esac
+am__tagged_files = $(HEADERS) $(SOURCES) $(TAGS_FILES) $(LISP)
+DISTFILES = $(DIST_COMMON) $(DIST_SOURCES) $(TEXINFOS) $(EXTRA_DIST)
+ACLOCAL = @ACLOCAL@
+AMTAR = @AMTAR@
+AM_DEFAULT_VERBOSITY = @AM_DEFAULT_VERBOSITY@
+AR = @AR@
+AS = @AS@
+AUTOCONF = @AUTOCONF@
+AUTOHEADER = @AUTOHEADER@
+AUTOMAKE = @AUTOMAKE@
+AWK = @AWK@
+BUILD_FILEVERSION = @BUILD_FILEVERSION@
+BUILD_REVISION = @BUILD_REVISION@
+BUILD_TIMESTAMP = @BUILD_TIMESTAMP@
+CC = @CC@
+CCDEPMODE = @CCDEPMODE@
+CC_FOR_BUILD = @CC_FOR_BUILD@
+CFLAGS = @CFLAGS@
+CPP = @CPP@
+CPPFLAGS = @CPPFLAGS@
+CXX = @CXX@
+CXXCPP = @CXXCPP@
+CXXDEPMODE = @CXXDEPMODE@
+CXXFLAGS = @CXXFLAGS@
+CYGPATH_W = @CYGPATH_W@
+DEFS = @DEFS@
+DEPDIR = @DEPDIR@
+DLLTOOL = @DLLTOOL@
+DOXYGEN = @DOXYGEN@
+DSYMUTIL = @DSYMUTIL@
+DUMPBIN = @DUMPBIN@
+ECHO_C = @ECHO_C@
+ECHO_N = @ECHO_N@
+ECHO_T = @ECHO_T@
+EGREP = @EGREP@
+ENABLED_LANGUAGES = @ENABLED_LANGUAGES@
+EXEEXT = @EXEEXT@
+FGREP = @FGREP@
+GITLOG_TO_CHANGELOG = @GITLOG_TO_CHANGELOG@
+GLIBC21 = @GLIBC21@
+GLIB_CFLAGS = @GLIB_CFLAGS@
+GLIB_GENMARSHAL = @GLIB_GENMARSHAL@
+GLIB_LIBS = @GLIB_LIBS@
+GLIB_MKENUMS = @GLIB_MKENUMS@
+GOBJECT_QUERY = @GOBJECT_QUERY@
+GPGME_CONFIG_API_VERSION = @GPGME_CONFIG_API_VERSION@
+GPGME_CONFIG_AVAIL_LANG = @GPGME_CONFIG_AVAIL_LANG@
+GPGME_CONFIG_CFLAGS = @GPGME_CONFIG_CFLAGS@
+GPGME_CONFIG_HOST = @GPGME_CONFIG_HOST@
+GPGME_CONFIG_LIBS = @GPGME_CONFIG_LIBS@
+GPGME_QTTEST_CFLAGS = @GPGME_QTTEST_CFLAGS@
+GPGME_QTTEST_LIBS = @GPGME_QTTEST_LIBS@
+GPGME_QT_CFLAGS = @GPGME_QT_CFLAGS@
+GPGME_QT_LIBS = @GPGME_QT_LIBS@
+GPG_ERROR_CFLAGS = @GPG_ERROR_CFLAGS@
+GPG_ERROR_CONFIG = @GPG_ERROR_CONFIG@
+GPG_ERROR_LIBS = @GPG_ERROR_LIBS@
+GPG_ERROR_MT_CFLAGS = @GPG_ERROR_MT_CFLAGS@
+GPG_ERROR_MT_LIBS = @GPG_ERROR_MT_LIBS@
+GRAPHVIZ = @GRAPHVIZ@
+GREP = @GREP@
+HAVE_CXX11 = @HAVE_CXX11@
+HAVE_DOT = @HAVE_DOT@
+INSTALL = @INSTALL@
+INSTALL_DATA = @INSTALL_DATA@
+INSTALL_PROGRAM = @INSTALL_PROGRAM@
+INSTALL_SCRIPT = @INSTALL_SCRIPT@
+INSTALL_STRIP_PROGRAM = @INSTALL_STRIP_PROGRAM@
+LD = @LD@
+LDFLAGS = @LDFLAGS@
+LIBASSUAN_CFLAGS = @LIBASSUAN_CFLAGS@
+LIBASSUAN_CONFIG = @LIBASSUAN_CONFIG@
+LIBASSUAN_LIBS = @LIBASSUAN_LIBS@
+LIBGPGMEPP_LT_AGE = @LIBGPGMEPP_LT_AGE@
+LIBGPGMEPP_LT_CURRENT = @LIBGPGMEPP_LT_CURRENT@
+LIBGPGMEPP_LT_REVISION = @LIBGPGMEPP_LT_REVISION@
+LIBGPGME_LT_AGE = @LIBGPGME_LT_AGE@
+LIBGPGME_LT_CURRENT = @LIBGPGME_LT_CURRENT@
+LIBGPGME_LT_REVISION = @LIBGPGME_LT_REVISION@
+LIBOBJS = @LIBOBJS@
+LIBQGPGME_LT_AGE = @LIBQGPGME_LT_AGE@
+LIBQGPGME_LT_CURRENT = @LIBQGPGME_LT_CURRENT@
+LIBQGPGME_LT_REVISION = @LIBQGPGME_LT_REVISION@
+LIBS = @LIBS@
+LIBTOOL = @LIBTOOL@
+LIPO = @LIPO@
+LN_S = @LN_S@
+LTLIBOBJS = @LTLIBOBJS@
+MAINT = @MAINT@
+MAKEINFO = @MAKEINFO@
+MANIFEST_TOOL = @MANIFEST_TOOL@
+MKDIR_P = @MKDIR_P@
+MOC = @MOC@
+MOC2 = @MOC2@
+NEED__FILE_OFFSET_BITS = @NEED__FILE_OFFSET_BITS@
+NM = @NM@
+NMEDIT = @NMEDIT@
+OBJDUMP = @OBJDUMP@
+OBJEXT = @OBJEXT@
+OTOOL = @OTOOL@
+OTOOL64 = @OTOOL64@
+PACKAGE = @PACKAGE@
+PACKAGE_BUGREPORT = @PACKAGE_BUGREPORT@
+PACKAGE_NAME = @PACKAGE_NAME@
+PACKAGE_STRING = @PACKAGE_STRING@
+PACKAGE_TARNAME = @PACKAGE_TARNAME@
+PACKAGE_URL = @PACKAGE_URL@
+PACKAGE_VERSION = @PACKAGE_VERSION@
+PATH_SEPARATOR = @PATH_SEPARATOR@
+PKG_CONFIG = @PKG_CONFIG@
+PYTHON = @PYTHON@
+PYTHONS = @PYTHONS@
+PYTHON_CPPFLAGS = @PYTHON_CPPFLAGS@
+PYTHON_EXEC_PREFIX = @PYTHON_EXEC_PREFIX@
+PYTHON_EXTRA_LDFLAGS = @PYTHON_EXTRA_LDFLAGS@
+PYTHON_EXTRA_LIBS = @PYTHON_EXTRA_LIBS@
+PYTHON_LDFLAGS = @PYTHON_LDFLAGS@
+PYTHON_PLATFORM = @PYTHON_PLATFORM@
+PYTHON_PREFIX = @PYTHON_PREFIX@
+PYTHON_SITE_PKG = @PYTHON_SITE_PKG@
+PYTHON_VERSION = @PYTHON_VERSION@
+PYTHON_VERSIONS = @PYTHON_VERSIONS@
+QTCHOOSER = @QTCHOOSER@
+RANLIB = @RANLIB@
+RC = @RC@
+SED = @SED@
+SET_MAKE = @SET_MAKE@
+SHELL = @SHELL@
+STRIP = @STRIP@
+SWIG = @SWIG@
+SWIG_LIB = @SWIG_LIB@
+SYSROOT = @SYSROOT@
+VERSION = @VERSION@
+VERSION_NUMBER = @VERSION_NUMBER@
+abs_builddir = @abs_builddir@
+abs_srcdir = @abs_srcdir@
+abs_top_builddir = @abs_top_builddir@
+abs_top_srcdir = @abs_top_srcdir@
+ac_ct_AR = @ac_ct_AR@
+ac_ct_CC = @ac_ct_CC@
+ac_ct_CXX = @ac_ct_CXX@
+ac_ct_DUMPBIN = @ac_ct_DUMPBIN@
+am__include = @am__include@
+am__leading_dot = @am__leading_dot@
+am__quote = @am__quote@
+am__tar = @am__tar@
+am__untar = @am__untar@
+bindir = @bindir@
+build = @build@
+build_alias = @build_alias@
+build_cpu = @build_cpu@
+build_os = @build_os@
+build_vendor = @build_vendor@
+builddir = @builddir@
+datadir = @datadir@
+datarootdir = @datarootdir@
+docdir = @docdir@
+dvidir = @dvidir@
+emacs_local_vars_begin = @emacs_local_vars_begin@
+emacs_local_vars_end = @emacs_local_vars_end@
+emacs_local_vars_read_only = @emacs_local_vars_read_only@
+exec_prefix = @exec_prefix@
+host = @host@
+host_alias = @host_alias@
+host_cpu = @host_cpu@
+host_os = @host_os@
+host_vendor = @host_vendor@
+htmldir = @htmldir@
+includedir = @includedir@
+infodir = @infodir@
+install_sh = @install_sh@
+libdir = @libdir@
+libexecdir = @libexecdir@
+localedir = @localedir@
+localstatedir = @localstatedir@
+mandir = @mandir@
+mkdir_p = @mkdir_p@
+oldincludedir = @oldincludedir@
+pdfdir = @pdfdir@
+pkgpyexecdir = @pkgpyexecdir@
+pkgpythondir = @pkgpythondir@
+prefix = @prefix@
+program_transform_name = @program_transform_name@
+psdir = @psdir@
+pyexecdir = @pyexecdir@
+pythondir = @pythondir@
+sbindir = @sbindir@
+sharedstatedir = @sharedstatedir@
+srcdir = @srcdir@
+sysconfdir = @sysconfdir@
+target_alias = @target_alias@
+top_build_prefix = @top_build_prefix@
+top_builddir = @top_builddir@
+top_srcdir = @top_srcdir@
+@HAVE_DOXYGEN_TRUE@CLEANFILES = doxyfile.stamp
+all: all-am
+
+.SUFFIXES:
+$(srcdir)/Makefile.in: @MAINTAINER_MODE_TRUE@ $(srcdir)/Makefile.am $(am__configure_deps)
+ @for dep in $?; do \
+ case '$(am__configure_deps)' in \
+ *$$dep*) \
+ ( cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh ) \
+ && { if test -f $@; then exit 0; else break; fi; }; \
+ exit 1;; \
+ esac; \
+ done; \
+ echo ' cd $(top_srcdir) && $(AUTOMAKE) --gnu lang/qt/doc/Makefile'; \
+ $(am__cd) $(top_srcdir) && \
+ $(AUTOMAKE) --gnu lang/qt/doc/Makefile
+.PRECIOUS: Makefile
+Makefile: $(srcdir)/Makefile.in $(top_builddir)/config.status
+ @case '$?' in \
+ *config.status*) \
+ cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh;; \
+ *) \
+ echo ' cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__depfiles_maybe)'; \
+ cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__depfiles_maybe);; \
+ esac;
+
+$(top_builddir)/config.status: $(top_srcdir)/configure $(CONFIG_STATUS_DEPENDENCIES)
+ cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh
+
+$(top_srcdir)/configure: @MAINTAINER_MODE_TRUE@ $(am__configure_deps)
+ cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh
+$(ACLOCAL_M4): @MAINTAINER_MODE_TRUE@ $(am__aclocal_m4_deps)
+ cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh
+$(am__aclocal_m4_deps):
+@HAVE_DOXYGEN_TRUE@Doxyfile: $(top_builddir)/config.status $(srcdir)/Doxyfile.in
+@HAVE_DOXYGEN_TRUE@ cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@
+
+mostlyclean-libtool:
+ -rm -f *.lo
+
+clean-libtool:
+ -rm -rf .libs _libs
+tags TAGS:
+
+ctags CTAGS:
+
+cscope cscopelist:
+
+
+distdir: $(DISTFILES)
+ @srcdirstrip=`echo "$(srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \
+ topsrcdirstrip=`echo "$(top_srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \
+ list='$(DISTFILES)'; \
+ dist_files=`for file in $$list; do echo $$file; done | \
+ sed -e "s|^$$srcdirstrip/||;t" \
+ -e "s|^$$topsrcdirstrip/|$(top_builddir)/|;t"`; \
+ case $$dist_files in \
+ */*) $(MKDIR_P) `echo "$$dist_files" | \
+ sed '/\//!d;s|^|$(distdir)/|;s,/[^/]*$$,,' | \
+ sort -u` ;; \
+ esac; \
+ for file in $$dist_files; do \
+ if test -f $$file || test -d $$file; then d=.; else d=$(srcdir); fi; \
+ if test -d $$d/$$file; then \
+ dir=`echo "/$$file" | sed -e 's,/[^/]*$$,,'`; \
+ if test -d "$(distdir)/$$file"; then \
+ find "$(distdir)/$$file" -type d ! -perm -700 -exec chmod u+rwx {} \;; \
+ fi; \
+ if test -d $(srcdir)/$$file && test $$d != $(srcdir); then \
+ cp -fpR $(srcdir)/$$file "$(distdir)$$dir" || exit 1; \
+ find "$(distdir)/$$file" -type d ! -perm -700 -exec chmod u+rwx {} \;; \
+ fi; \
+ cp -fpR $$d/$$file "$(distdir)$$dir" || exit 1; \
+ else \
+ test -f "$(distdir)/$$file" \
+ || cp -p $$d/$$file "$(distdir)/$$file" \
+ || exit 1; \
+ fi; \
+ done
+check-am: all-am
+check: check-am
+@HAVE_DOXYGEN_FALSE@all-local:
+all-am: Makefile all-local
+installdirs:
+install: install-am
+install-exec: install-exec-am
+install-data: install-data-am
+uninstall: uninstall-am
+
+install-am: all-am
+ @$(MAKE) $(AM_MAKEFLAGS) install-exec-am install-data-am
+
+installcheck: installcheck-am
+install-strip:
+ if test -z '$(STRIP)'; then \
+ $(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \
+ install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \
+ install; \
+ else \
+ $(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \
+ install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \
+ "INSTALL_PROGRAM_ENV=STRIPPROG='$(STRIP)'" install; \
+ fi
+mostlyclean-generic:
+
+clean-generic:
+ -test -z "$(CLEANFILES)" || rm -f $(CLEANFILES)
+
+distclean-generic:
+ -test -z "$(CONFIG_CLEAN_FILES)" || rm -f $(CONFIG_CLEAN_FILES)
+ -test . = "$(srcdir)" || test -z "$(CONFIG_CLEAN_VPATH_FILES)" || rm -f $(CONFIG_CLEAN_VPATH_FILES)
+
+maintainer-clean-generic:
+ @echo "This command is intended for maintainers to use"
+ @echo "it deletes files that may require special tools to rebuild."
+@HAVE_DOXYGEN_FALSE@clean-local:
+clean: clean-am
+
+clean-am: clean-generic clean-libtool clean-local mostlyclean-am
+
+distclean: distclean-am
+ -rm -f Makefile
+distclean-am: clean-am distclean-generic
+
+dvi: dvi-am
+
+dvi-am:
+
+html: html-am
+
+html-am:
+
+info: info-am
+
+info-am:
+
+install-data-am:
+
+install-dvi: install-dvi-am
+
+install-dvi-am:
+
+install-exec-am:
+
+install-html: install-html-am
+
+install-html-am:
+
+install-info: install-info-am
+
+install-info-am:
+
+install-man:
+
+install-pdf: install-pdf-am
+
+install-pdf-am:
+
+install-ps: install-ps-am
+
+install-ps-am:
+
+installcheck-am:
+
+maintainer-clean: maintainer-clean-am
+ -rm -f Makefile
+maintainer-clean-am: distclean-am maintainer-clean-generic
+
+mostlyclean: mostlyclean-am
+
+mostlyclean-am: mostlyclean-generic mostlyclean-libtool
+
+pdf: pdf-am
+
+pdf-am:
+
+ps: ps-am
+
+ps-am:
+
+uninstall-am:
+
+.MAKE: install-am install-strip
+
+.PHONY: all all-am all-local check check-am clean clean-generic \
+ clean-libtool clean-local cscopelist-am ctags-am distclean \
+ distclean-generic distclean-libtool distdir dvi dvi-am html \
+ html-am info info-am install install-am install-data \
+ install-data-am install-dvi install-dvi-am install-exec \
+ install-exec-am install-html install-html-am install-info \
+ install-info-am install-man install-pdf install-pdf-am \
+ install-ps install-ps-am install-strip installcheck \
+ installcheck-am installdirs maintainer-clean \
+ maintainer-clean-generic mostlyclean mostlyclean-generic \
+ mostlyclean-libtool pdf pdf-am ps ps-am tags-am uninstall \
+ uninstall-am
+
+
+@HAVE_DOXYGEN_TRUE@doxyfile.stamp:
+@HAVE_DOXYGEN_TRUE@ $(DOXYGEN) Doxyfile
+@HAVE_DOXYGEN_TRUE@ touch doxyfile.stamp
+
+@HAVE_DOXYGEN_TRUE@all-local: doxyfile.stamp
+@HAVE_DOXYGEN_TRUE@clean-local:
+@HAVE_DOXYGEN_TRUE@ rm -rf $(abs_builddir)/generated
+
+# Tell versions [3.59,3.63) of GNU make to not export all variables.
+# Otherwise a system limit (for SysV at least) may be exceeded.
+.NOEXPORT:
diff --git a/lang/qt/src/AddUserIDJob b/lang/qt/src/AddUserIDJob
new file mode 100644
index 0000000..87d82ec
--- /dev/null
+++ b/lang/qt/src/AddUserIDJob
@@ -0,0 +1 @@
+#include "qgpgme/adduseridjob.h"
diff --git a/lang/qt/src/ChangeExpiryJob b/lang/qt/src/ChangeExpiryJob
new file mode 100644
index 0000000..f5eea6a
--- /dev/null
+++ b/lang/qt/src/ChangeExpiryJob
@@ -0,0 +1 @@
+#include "qgpgme/changeexpiryjob.h"
diff --git a/lang/qt/src/ChangeOwnerTrustJob b/lang/qt/src/ChangeOwnerTrustJob
new file mode 100644
index 0000000..03635d5
--- /dev/null
+++ b/lang/qt/src/ChangeOwnerTrustJob
@@ -0,0 +1 @@
+#include "qgpgme/changeownertrustjob.h"
diff --git a/lang/qt/src/ChangePasswdJob b/lang/qt/src/ChangePasswdJob
new file mode 100644
index 0000000..3660940
--- /dev/null
+++ b/lang/qt/src/ChangePasswdJob
@@ -0,0 +1 @@
+#include "qgpgme/changepasswdjob.h"
diff --git a/lang/qt/src/CryptoConfig b/lang/qt/src/CryptoConfig
new file mode 100644
index 0000000..4edbd19
--- /dev/null
+++ b/lang/qt/src/CryptoConfig
@@ -0,0 +1 @@
+#include "qgpgme/cryptoconfig.h"
diff --git a/lang/qt/src/DataProvider b/lang/qt/src/DataProvider
new file mode 100644
index 0000000..6a43c1d
--- /dev/null
+++ b/lang/qt/src/DataProvider
@@ -0,0 +1 @@
+#include "qgpgme/dataprovider.h"
diff --git a/lang/qt/src/DecryptJob b/lang/qt/src/DecryptJob
new file mode 100644
index 0000000..c0f9845
--- /dev/null
+++ b/lang/qt/src/DecryptJob
@@ -0,0 +1 @@
+#include "qgpgme/decryptjob.h"
diff --git a/lang/qt/src/DecryptVerifyJob b/lang/qt/src/DecryptVerifyJob
new file mode 100644
index 0000000..e3de1cc
--- /dev/null
+++ b/lang/qt/src/DecryptVerifyJob
@@ -0,0 +1 @@
+#include "qgpgme/decryptverifyjob.h"
diff --git a/lang/qt/src/DefaultKeyGenerationJob b/lang/qt/src/DefaultKeyGenerationJob
new file mode 100644
index 0000000..1dc8c40
--- /dev/null
+++ b/lang/qt/src/DefaultKeyGenerationJob
@@ -0,0 +1 @@
+#include "qgpgme/defaultkeygenerationjob.h"
diff --git a/lang/qt/src/DeleteJob b/lang/qt/src/DeleteJob
new file mode 100644
index 0000000..a2fdc4a
--- /dev/null
+++ b/lang/qt/src/DeleteJob
@@ -0,0 +1 @@
+#include "qgpgme/deletejob.h"
diff --git a/lang/qt/src/DownloadJob b/lang/qt/src/DownloadJob
new file mode 100644
index 0000000..9b47aac
--- /dev/null
+++ b/lang/qt/src/DownloadJob
@@ -0,0 +1 @@
+#include "qgpgme/downloadjob.h"
diff --git a/lang/qt/src/EncryptJob b/lang/qt/src/EncryptJob
new file mode 100644
index 0000000..59a878d
--- /dev/null
+++ b/lang/qt/src/EncryptJob
@@ -0,0 +1 @@
+#include "qgpgme/encryptjob.h"
diff --git a/lang/qt/src/ExportJob b/lang/qt/src/ExportJob
new file mode 100644
index 0000000..1d053fd
--- /dev/null
+++ b/lang/qt/src/ExportJob
@@ -0,0 +1 @@
+#include "qgpgme/exportjob.h"
diff --git a/lang/qt/src/HierarchicalKeyKistJob b/lang/qt/src/HierarchicalKeyKistJob
new file mode 100644
index 0000000..cd31f48
--- /dev/null
+++ b/lang/qt/src/HierarchicalKeyKistJob
@@ -0,0 +1 @@
+#include "qgpgme/hierarchicalkeykistjob.h"
diff --git a/lang/qt/src/ImportFromKeyserverJob b/lang/qt/src/ImportFromKeyserverJob
new file mode 100644
index 0000000..17a5fd6
--- /dev/null
+++ b/lang/qt/src/ImportFromKeyserverJob
@@ -0,0 +1 @@
+#include "qgpgme/importfromkeyserverjob.h"
diff --git a/lang/qt/src/ImportJob b/lang/qt/src/ImportJob
new file mode 100644
index 0000000..e5228d7
--- /dev/null
+++ b/lang/qt/src/ImportJob
@@ -0,0 +1 @@
+#include "qgpgme/importjob.h"
diff --git a/lang/qt/src/Job b/lang/qt/src/Job
new file mode 100644
index 0000000..3a45ca7
--- /dev/null
+++ b/lang/qt/src/Job
@@ -0,0 +1 @@
+#include "qgpgme/job.h"
diff --git a/lang/qt/src/KeyForMailboxJob b/lang/qt/src/KeyForMailboxJob
new file mode 100644
index 0000000..2d2b8cb
--- /dev/null
+++ b/lang/qt/src/KeyForMailboxJob
@@ -0,0 +1 @@
+#include "qgpgme/keyformailboxjob.h"
diff --git a/lang/qt/src/KeyGenerationJob b/lang/qt/src/KeyGenerationJob
new file mode 100644
index 0000000..1612ba7
--- /dev/null
+++ b/lang/qt/src/KeyGenerationJob
@@ -0,0 +1 @@
+#include "qgpgme/keygenerationjob.h"
diff --git a/lang/qt/src/KeyListJob b/lang/qt/src/KeyListJob
new file mode 100644
index 0000000..7366665
--- /dev/null
+++ b/lang/qt/src/KeyListJob
@@ -0,0 +1 @@
+#include "qgpgme/keylistjob.h"
diff --git a/lang/qt/src/ListAllKeysJob b/lang/qt/src/ListAllKeysJob
new file mode 100644
index 0000000..8023f8f
--- /dev/null
+++ b/lang/qt/src/ListAllKeysJob
@@ -0,0 +1 @@
+#include "qgpgme/listallkeysjob.h"
diff --git a/lang/qt/src/Makefile.am b/lang/qt/src/Makefile.am
new file mode 100644
index 0000000..c15da18
--- /dev/null
+++ b/lang/qt/src/Makefile.am
@@ -0,0 +1,256 @@
+# Makefile.am for GPGMEPP.
+# Copyright (C) 2016 Intevation GmbH
+#
+# This file is part of GPGMEPP.
+#
+# GPGME-CL 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.
+#
+# GPGME-CL is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU Lesser General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program; if not, write to the Free Software
+# Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
+# 02111-1307, USA
+lib_LTLIBRARIES = libqgpgme.la
+EXTRA_DIST = QGpgmeConfig.cmake.in.in QGpgmeConfigVersion.cmake.in \
+ gpgme_backend_debug.h qgpgme_version.h.in
+
+qgpgme_sources = \
+ dataprovider.cpp job.cpp qgpgmeadduseridjob.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 \
+ qgpgmerefreshkeysjob.cpp \
+ qgpgmesecretkeyexportjob.cpp qgpgmesignencryptjob.cpp \
+ qgpgmesignjob.cpp qgpgmesignkeyjob.cpp qgpgmeverifydetachedjob.cpp \
+ qgpgmeverifyopaquejob.cpp threadedjobmixin.cpp \
+ qgpgmekeyformailboxjob.cpp gpgme_backend_debug.cpp \
+ qgpgmetofupolicyjob.cpp \
+ defaultkeygenerationjob.cpp qgpgmewkspublishjob.cpp
+
+# If you add one here make sure that you also add one in camelcase
+qgpgme_headers= \
+ adduseridjob.h \
+ changeexpiryjob.h \
+ changeownertrustjob.h \
+ changepasswdjob.h \
+ dataprovider.h \
+ decryptjob.h \
+ decryptverifyjob.h \
+ downloadjob.h \
+ encryptjob.h \
+ exportjob.h \
+ hierarchicalkeylistjob.h \
+ job.h \
+ keyformailboxjob.h \
+ multideletejob.h \
+ protocol.h \
+ qgpgme_export.h \
+ qgpgmenewcryptoconfig.h \
+ signjob.h \
+ signkeyjob.h \
+ signencryptjob.h \
+ verifyopaquejob.h \
+ refreshkeysjob.h \
+ cryptoconfig.h \
+ deletejob.h \
+ importfromkeyserverjob.h \
+ importjob.h \
+ keygenerationjob.h \
+ keylistjob.h \
+ listallkeysjob.h \
+ verifydetachedjob.h \
+ defaultkeygenerationjob.h \
+ tofupolicyjob.h \
+ wkspublishjob.h
+
+camelcase_headers= \
+ AddUserIDJob \
+ ChangeExpiryJob \
+ ChangeOwnerTrustJob \
+ ChangePasswdJob \
+ DataProvider \
+ DecryptJob \
+ DecryptVerifyJob \
+ DownloadJob \
+ EncryptJob \
+ ExportJob \
+ HierarchicalKeyKistJob \
+ Job \
+ MultiDeleteJob \
+ Protocol \
+ QGpgMENewCryptoConfig \
+ SignJob \
+ SignKeyJob \
+ SignEncryptJob \
+ VerifyOpaqueJob \
+ RefreshKeysJob \
+ CryptoConfig \
+ DeleteJob \
+ ImportFromKeyserverJob \
+ ImportJob \
+ KeyGenerationJob \
+ KeyListJob \
+ ListAllKeysJob \
+ VerifyDetachedJob \
+ KeyForMailboxJob \
+ DefaultKeyGenerationJob \
+ WKSPublishJob \
+ TofuPolicyJob
+
+private_qgpgme_headers = \
+ qgpgme_export.h \
+ abstractimportjob.h \
+ protocol_p.h \
+ qgpgmeadduseridjob.h \
+ qgpgmebackend.h \
+ qgpgmechangeexpiryjob.h \
+ qgpgmechangeownertrustjob.h \
+ qgpgmechangepasswdjob.h \
+ qgpgmedecryptjob.h \
+ qgpgmedecryptverifyjob.h \
+ qgpgmedeletejob.h \
+ qgpgmedownloadjob.h \
+ qgpgmeencryptjob.h \
+ qgpgmeexportjob.h \
+ qgpgmeimportfromkeyserverjob.h \
+ qgpgmeimportjob.h \
+ qgpgmekeygenerationjob.h \
+ qgpgmekeylistjob.h \
+ qgpgmelistallkeysjob.h \
+ qgpgmerefreshkeysjob.h \
+ qgpgmesecretkeyexportjob.h \
+ qgpgmesignencryptjob.h \
+ qgpgmesignjob.h \
+ qgpgmesignkeyjob.h \
+ qgpgmeverifydetachedjob.h \
+ qgpgmeverifyopaquejob.h \
+ qgpgmekeyformailboxjob.h \
+ qgpgmewkspublishjob.h \
+ qgpgmetofupolicyjob.h \
+ specialjob.h \
+ threadedjobmixin.h
+
+qgpgme_moc_sources = \
+ abstractimportjob.moc \
+ adduseridjob.moc \
+ changeexpiryjob.moc \
+ changeownertrustjob.moc \
+ changepasswdjob.moc \
+ decryptjob.moc \
+ decryptverifyjob.moc \
+ deletejob.moc \
+ downloadjob.moc \
+ encryptjob.moc \
+ exportjob.moc \
+ hierarchicalkeylistjob.moc \
+ importfromkeyserverjob.moc \
+ importjob.moc \
+ job.moc \
+ keygenerationjob.moc \
+ keylistjob.moc \
+ listallkeysjob.moc \
+ multideletejob.moc \
+ qgpgmeadduseridjob.moc \
+ qgpgmechangeexpiryjob.moc \
+ qgpgmechangeownertrustjob.moc \
+ qgpgmechangepasswdjob.moc \
+ qgpgmedecryptjob.moc \
+ qgpgmedecryptverifyjob.moc \
+ qgpgmedeletejob.moc \
+ qgpgmedownloadjob.moc \
+ qgpgmeencryptjob.moc \
+ qgpgmeexportjob.moc \
+ qgpgmeimportfromkeyserverjob.moc \
+ qgpgmeimportjob.moc \
+ qgpgmekeygenerationjob.moc \
+ qgpgmekeylistjob.moc \
+ qgpgmelistallkeysjob.moc \
+ qgpgmerefreshkeysjob.moc \
+ qgpgmesecretkeyexportjob.moc \
+ qgpgmesignencryptjob.moc \
+ qgpgmesignjob.moc \
+ qgpgmesignkeyjob.moc \
+ qgpgmeverifydetachedjob.moc \
+ qgpgmeverifyopaquejob.moc \
+ qgpgmewkspublishjob.moc \
+ tofupolicyjob.moc \
+ qgpgmetofupolicyjob.moc \
+ refreshkeysjob.moc \
+ signencryptjob.moc \
+ signjob.moc \
+ signkeyjob.moc \
+ specialjob.moc \
+ verifydetachedjob.moc \
+ verifyopaquejob.moc \
+ keyformailboxjob.moc \
+ wkspublishjob.moc \
+ qgpgmekeyformailboxjob.moc \
+ defaultkeygenerationjob.moc
+
+qgpgmeincludedir = $(includedir)/qgpgme
+qgpgmeinclude_HEADERS = $(qgpgme_headers)
+camelcaseincludedir = $(includedir)/QGpgME
+camelcaseinclude_HEADERS = $(camelcase_headers)
+nodist_include_HEADERS = qgpgme_version.h
+
+libqgpgme_la_SOURCES = $(qgpgme_sources) $(qgpgme_headers) $(private_qgpgme_headers)
+
+AM_CPPFLAGS = -I$(top_srcdir)/lang/cpp/src -I$(top_builddir)/src \
+ @GPGME_QT_CFLAGS@ @GPG_ERROR_CFLAGS@ @LIBASSUAN_CFLAGS@ \
+ -DBUILDING_QGPGME
+
+libqgpgme_la_LIBADD = ../../cpp/src/libgpgmepp.la ../../../src/libgpgme.la \
+ @LIBASSUAN_LIBS@ @GPGME_QT_LIBS@
+libqgpgme_la_LDFLAGS = -version-info \
+ @LIBQGPGME_LT_CURRENT@:@LIBQGPGME_LT_REVISION@:@LIBQGPGME_LT_AGE@
+
+if HAVE_W32_SYSTEM
+libsuffix=.dll.a
+else
+libsuffix=.so
+endif
+
+QGpgmeConfig.cmake: QGpgmeConfig.cmake.in
+ sed -e 's|[@]resolved_libdir@|$(libdir)|g' < "$<" > "$@"
+ sed -e 's|[@]libsuffix@|$(libsuffix)|g' < "$@" > "$@".2
+ mv "$@".2 "$@"
+
+$(camelcase_headers): Makefile.am
+ echo -n "#include \"qgpgme/" > "$@"
+ echo -n "$@" | tr '[:upper:]' '[:lower:]' >> "$@"
+ echo ".h\"" >> "$@"
+
+install-cmake-files: QGpgmeConfig.cmake QGpgmeConfigVersion.cmake
+ -$(INSTALL) -d $(DESTDIR)$(libdir)/cmake/Gpgmepp
+ $(INSTALL) QGpgmeConfig.cmake \
+ $(DESTDIR)$(libdir)/cmake/Gpgmepp/QGpgmeConfig.cmake
+ $(INSTALL) QGpgmeConfigVersion.cmake \
+ $(DESTDIR)$(libdir)/cmake/Gpgmepp/QGpgmeConfigVersion.cmake
+
+uninstall-cmake-files:
+ -rm $(DESTDIR)$(libdir)/cmake/Gpgmepp/QGpgmeConfigVersion.cmake
+ -rm $(DESTDIR)$(libdir)/cmake/Gpgmepp/QGpgmeConfig.cmake
+ -rmdir $(DESTDIR)$(libdir)/cmake/Gpgmepp/
+
+install-data-local: install-cmake-files
+
+uninstall-local: uninstall-cmake-files
+
+BUILT_SOURCES = $(qgpgme_moc_sources) $(camelcase_headers)
+
+CLEANFILES = $(qgpgme_moc_sources) $(camelcase_headers) QGpgmeConfig.cmake
+
+nodist_libqgpgme_la_SOURCES = $(qgpgme_moc_sources)
+
+.h.moc:
+ $(MOC) `test -f '$<' || echo '$(srcdir)/'`$< -o $@
diff --git a/lang/qt/src/Makefile.in b/lang/qt/src/Makefile.in
new file mode 100644
index 0000000..d10eca3
--- /dev/null
+++ b/lang/qt/src/Makefile.in
@@ -0,0 +1,1123 @@
+# Makefile.in generated by automake 1.14.1 from Makefile.am.
+# @configure_input@
+
+# Copyright (C) 1994-2013 Free Software Foundation, Inc.
+
+# This Makefile.in is free software; the Free Software Foundation
+# gives unlimited permission to copy and/or distribute it,
+# with or without modifications, as long as this notice is preserved.
+
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY, to the extent permitted by law; without
+# even the implied warranty of MERCHANTABILITY or FITNESS FOR A
+# PARTICULAR PURPOSE.
+
+@SET_MAKE@
+
+
+VPATH = @srcdir@
+am__is_gnu_make = test -n '$(MAKEFILE_LIST)' && test -n '$(MAKELEVEL)'
+am__make_running_with_option = \
+ case $${target_option-} in \
+ ?) ;; \
+ *) echo "am__make_running_with_option: internal error: invalid" \
+ "target option '$${target_option-}' specified" >&2; \
+ exit 1;; \
+ esac; \
+ has_opt=no; \
+ sane_makeflags=$$MAKEFLAGS; \
+ if $(am__is_gnu_make); then \
+ sane_makeflags=$$MFLAGS; \
+ else \
+ case $$MAKEFLAGS in \
+ *\\[\ \ ]*) \
+ bs=\\; \
+ sane_makeflags=`printf '%s\n' "$$MAKEFLAGS" \
+ | sed "s/$$bs$$bs[$$bs $$bs ]*//g"`;; \
+ esac; \
+ fi; \
+ skip_next=no; \
+ strip_trailopt () \
+ { \
+ flg=`printf '%s\n' "$$flg" | sed "s/$$1.*$$//"`; \
+ }; \
+ for flg in $$sane_makeflags; do \
+ test $$skip_next = yes && { skip_next=no; continue; }; \
+ case $$flg in \
+ *=*|--*) continue;; \
+ -*I) strip_trailopt 'I'; skip_next=yes;; \
+ -*I?*) strip_trailopt 'I';; \
+ -*O) strip_trailopt 'O'; skip_next=yes;; \
+ -*O?*) strip_trailopt 'O';; \
+ -*l) strip_trailopt 'l'; skip_next=yes;; \
+ -*l?*) strip_trailopt 'l';; \
+ -[dEDm]) skip_next=yes;; \
+ -[JT]) skip_next=yes;; \
+ esac; \
+ case $$flg in \
+ *$$target_option*) has_opt=yes; break;; \
+ esac; \
+ done; \
+ test $$has_opt = yes
+am__make_dryrun = (target_option=n; $(am__make_running_with_option))
+am__make_keepgoing = (target_option=k; $(am__make_running_with_option))
+pkgdatadir = $(datadir)/@PACKAGE@
+pkgincludedir = $(includedir)/@PACKAGE@
+pkglibdir = $(libdir)/@PACKAGE@
+pkglibexecdir = $(libexecdir)/@PACKAGE@
+am__cd = CDPATH="$${ZSH_VERSION+.}$(PATH_SEPARATOR)" && cd
+install_sh_DATA = $(install_sh) -c -m 644
+install_sh_PROGRAM = $(install_sh) -c
+install_sh_SCRIPT = $(install_sh) -c
+INSTALL_HEADER = $(INSTALL_DATA)
+transform = $(program_transform_name)
+NORMAL_INSTALL = :
+PRE_INSTALL = :
+POST_INSTALL = :
+NORMAL_UNINSTALL = :
+PRE_UNINSTALL = :
+POST_UNINSTALL = :
+build_triplet = @build@
+host_triplet = @host@
+subdir = lang/qt/src
+DIST_COMMON = $(srcdir)/Makefile.in $(srcdir)/Makefile.am \
+ $(top_srcdir)/build-aux/mkinstalldirs \
+ $(srcdir)/QGpgmeConfig.cmake.in.in \
+ $(srcdir)/QGpgmeConfigVersion.cmake.in \
+ $(srcdir)/qgpgme_version.h.in $(top_srcdir)/build-aux/depcomp \
+ $(camelcaseinclude_HEADERS) $(qgpgmeinclude_HEADERS)
+ACLOCAL_M4 = $(top_srcdir)/aclocal.m4
+am__aclocal_m4_deps = $(top_srcdir)/m4/ax_cxx_compile_stdcxx.m4 \
+ $(top_srcdir)/m4/ax_pkg_swig.m4 \
+ $(top_srcdir)/m4/ax_python_devel.m4 \
+ $(top_srcdir)/m4/glib-2.0.m4 $(top_srcdir)/m4/glibc21.m4 \
+ $(top_srcdir)/m4/gnupg-ttyname.m4 \
+ $(top_srcdir)/m4/gpg-error.m4 $(top_srcdir)/m4/libassuan.m4 \
+ $(top_srcdir)/m4/libtool.m4 $(top_srcdir)/m4/ltoptions.m4 \
+ $(top_srcdir)/m4/ltsugar.m4 $(top_srcdir)/m4/ltversion.m4 \
+ $(top_srcdir)/m4/lt~obsolete.m4 $(top_srcdir)/m4/pkg.m4 \
+ $(top_srcdir)/m4/qt.m4 $(top_srcdir)/acinclude.m4 \
+ $(top_srcdir)/configure.ac
+am__configure_deps = $(am__aclocal_m4_deps) $(CONFIGURE_DEPENDENCIES) \
+ $(ACLOCAL_M4)
+mkinstalldirs = $(SHELL) $(top_srcdir)/build-aux/mkinstalldirs
+CONFIG_HEADER = $(top_builddir)/config.h
+CONFIG_CLEAN_FILES = QGpgmeConfig.cmake.in QGpgmeConfigVersion.cmake \
+ qgpgme_version.h
+CONFIG_CLEAN_VPATH_FILES =
+am__vpath_adj_setup = srcdirstrip=`echo "$(srcdir)" | sed 's|.|.|g'`;
+am__vpath_adj = case $$p in \
+ $(srcdir)/*) f=`echo "$$p" | sed "s|^$$srcdirstrip/||"`;; \
+ *) f=$$p;; \
+ esac;
+am__strip_dir = f=`echo $$p | sed -e 's|^.*/||'`;
+am__install_max = 40
+am__nobase_strip_setup = \
+ srcdirstrip=`echo "$(srcdir)" | sed 's/[].[^$$\\*|]/\\\\&/g'`
+am__nobase_strip = \
+ for p in $$list; do echo "$$p"; done | sed -e "s|$$srcdirstrip/||"
+am__nobase_list = $(am__nobase_strip_setup); \
+ for p in $$list; do echo "$$p $$p"; done | \
+ sed "s| $$srcdirstrip/| |;"' / .*\//!s/ .*/ ./; s,\( .*\)/[^/]*$$,\1,' | \
+ $(AWK) 'BEGIN { files["."] = "" } { files[$$2] = files[$$2] " " $$1; \
+ if (++n[$$2] == $(am__install_max)) \
+ { print $$2, files[$$2]; n[$$2] = 0; files[$$2] = "" } } \
+ END { for (dir in files) print dir, files[dir] }'
+am__base_list = \
+ sed '$$!N;$$!N;$$!N;$$!N;$$!N;$$!N;$$!N;s/\n/ /g' | \
+ sed '$$!N;$$!N;$$!N;$$!N;s/\n/ /g'
+am__uninstall_files_from_dir = { \
+ test -z "$$files" \
+ || { test ! -d "$$dir" && test ! -f "$$dir" && test ! -r "$$dir"; } \
+ || { echo " ( cd '$$dir' && rm -f" $$files ")"; \
+ $(am__cd) "$$dir" && rm -f $$files; }; \
+ }
+am__installdirs = "$(DESTDIR)$(libdir)" \
+ "$(DESTDIR)$(camelcaseincludedir)" "$(DESTDIR)$(includedir)" \
+ "$(DESTDIR)$(qgpgmeincludedir)"
+LTLIBRARIES = $(lib_LTLIBRARIES)
+libqgpgme_la_DEPENDENCIES = ../../cpp/src/libgpgmepp.la \
+ ../../../src/libgpgme.la
+am__objects_1 = dataprovider.lo job.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 \
+ qgpgmeverifydetachedjob.lo qgpgmeverifyopaquejob.lo \
+ threadedjobmixin.lo qgpgmekeyformailboxjob.lo \
+ gpgme_backend_debug.lo qgpgmetofupolicyjob.lo \
+ defaultkeygenerationjob.lo qgpgmewkspublishjob.lo
+am__objects_2 =
+am_libqgpgme_la_OBJECTS = $(am__objects_1) $(am__objects_2) \
+ $(am__objects_2)
+nodist_libqgpgme_la_OBJECTS = $(am__objects_2)
+libqgpgme_la_OBJECTS = $(am_libqgpgme_la_OBJECTS) \
+ $(nodist_libqgpgme_la_OBJECTS)
+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 =
+libqgpgme_la_LINK = $(LIBTOOL) $(AM_V_lt) --tag=CXX $(AM_LIBTOOLFLAGS) \
+ $(LIBTOOLFLAGS) --mode=link $(CXXLD) $(AM_CXXFLAGS) \
+ $(CXXFLAGS) $(libqgpgme_la_LDFLAGS) $(LDFLAGS) -o $@
+AM_V_P = $(am__v_P_@AM_V@)
+am__v_P_ = $(am__v_P_@AM_DEFAULT_V@)
+am__v_P_0 = false
+am__v_P_1 = :
+AM_V_GEN = $(am__v_GEN_@AM_V@)
+am__v_GEN_ = $(am__v_GEN_@AM_DEFAULT_V@)
+am__v_GEN_0 = @echo " GEN " $@;
+am__v_GEN_1 =
+AM_V_at = $(am__v_at_@AM_V@)
+am__v_at_ = $(am__v_at_@AM_DEFAULT_V@)
+am__v_at_0 = @
+am__v_at_1 =
+DEFAULT_INCLUDES = -I.@am__isrc@ -I$(top_builddir)
+depcomp = $(SHELL) $(top_srcdir)/build-aux/depcomp
+am__depfiles_maybe = depfiles
+am__mv = mv -f
+CXXCOMPILE = $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) \
+ $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS)
+LTCXXCOMPILE = $(LIBTOOL) $(AM_V_lt) --tag=CXX $(AM_LIBTOOLFLAGS) \
+ $(LIBTOOLFLAGS) --mode=compile $(CXX) $(DEFS) \
+ $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) \
+ $(AM_CXXFLAGS) $(CXXFLAGS)
+AM_V_CXX = $(am__v_CXX_@AM_V@)
+am__v_CXX_ = $(am__v_CXX_@AM_DEFAULT_V@)
+am__v_CXX_0 = @echo " CXX " $@;
+am__v_CXX_1 =
+CXXLD = $(CXX)
+CXXLINK = $(LIBTOOL) $(AM_V_lt) --tag=CXX $(AM_LIBTOOLFLAGS) \
+ $(LIBTOOLFLAGS) --mode=link $(CXXLD) $(AM_CXXFLAGS) \
+ $(CXXFLAGS) $(AM_LDFLAGS) $(LDFLAGS) -o $@
+AM_V_CXXLD = $(am__v_CXXLD_@AM_V@)
+am__v_CXXLD_ = $(am__v_CXXLD_@AM_DEFAULT_V@)
+am__v_CXXLD_0 = @echo " CXXLD " $@;
+am__v_CXXLD_1 =
+COMPILE = $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) \
+ $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS)
+LTCOMPILE = $(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) \
+ $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) \
+ $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) \
+ $(AM_CFLAGS) $(CFLAGS)
+AM_V_CC = $(am__v_CC_@AM_V@)
+am__v_CC_ = $(am__v_CC_@AM_DEFAULT_V@)
+am__v_CC_0 = @echo " CC " $@;
+am__v_CC_1 =
+CCLD = $(CC)
+LINK = $(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) \
+ $(LIBTOOLFLAGS) --mode=link $(CCLD) $(AM_CFLAGS) $(CFLAGS) \
+ $(AM_LDFLAGS) $(LDFLAGS) -o $@
+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 = $(libqgpgme_la_SOURCES) $(nodist_libqgpgme_la_SOURCES)
+DIST_SOURCES = $(libqgpgme_la_SOURCES)
+am__can_run_installinfo = \
+ case $$AM_UPDATE_INFO_DIR in \
+ n|no|NO) false;; \
+ *) (install-info --version) >/dev/null 2>&1;; \
+ esac
+HEADERS = $(camelcaseinclude_HEADERS) $(nodist_include_HEADERS) \
+ $(qgpgmeinclude_HEADERS)
+am__tagged_files = $(HEADERS) $(SOURCES) $(TAGS_FILES) $(LISP)
+# Read a list of newline-separated strings from the standard input,
+# and print each of them once, without duplicates. Input order is
+# *not* preserved.
+am__uniquify_input = $(AWK) '\
+ BEGIN { nonempty = 0; } \
+ { items[$$0] = 1; nonempty = 1; } \
+ END { if (nonempty) { for (i in items) print i; }; } \
+'
+# Make sure the list of sources is unique. This is necessary because,
+# e.g., the same source file might be shared among _SOURCES variables
+# for different programs/libraries.
+am__define_uniq_tagged_files = \
+ list='$(am__tagged_files)'; \
+ unique=`for i in $$list; do \
+ if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \
+ done | $(am__uniquify_input)`
+ETAGS = etags
+CTAGS = ctags
+DISTFILES = $(DIST_COMMON) $(DIST_SOURCES) $(TEXINFOS) $(EXTRA_DIST)
+ACLOCAL = @ACLOCAL@
+AMTAR = @AMTAR@
+AM_DEFAULT_VERBOSITY = @AM_DEFAULT_VERBOSITY@
+AR = @AR@
+AS = @AS@
+AUTOCONF = @AUTOCONF@
+AUTOHEADER = @AUTOHEADER@
+AUTOMAKE = @AUTOMAKE@
+AWK = @AWK@
+BUILD_FILEVERSION = @BUILD_FILEVERSION@
+BUILD_REVISION = @BUILD_REVISION@
+BUILD_TIMESTAMP = @BUILD_TIMESTAMP@
+CC = @CC@
+CCDEPMODE = @CCDEPMODE@
+CC_FOR_BUILD = @CC_FOR_BUILD@
+CFLAGS = @CFLAGS@
+CPP = @CPP@
+CPPFLAGS = @CPPFLAGS@
+CXX = @CXX@
+CXXCPP = @CXXCPP@
+CXXDEPMODE = @CXXDEPMODE@
+CXXFLAGS = @CXXFLAGS@
+CYGPATH_W = @CYGPATH_W@
+DEFS = @DEFS@
+DEPDIR = @DEPDIR@
+DLLTOOL = @DLLTOOL@
+DOXYGEN = @DOXYGEN@
+DSYMUTIL = @DSYMUTIL@
+DUMPBIN = @DUMPBIN@
+ECHO_C = @ECHO_C@
+ECHO_N = @ECHO_N@
+ECHO_T = @ECHO_T@
+EGREP = @EGREP@
+ENABLED_LANGUAGES = @ENABLED_LANGUAGES@
+EXEEXT = @EXEEXT@
+FGREP = @FGREP@
+GITLOG_TO_CHANGELOG = @GITLOG_TO_CHANGELOG@
+GLIBC21 = @GLIBC21@
+GLIB_CFLAGS = @GLIB_CFLAGS@
+GLIB_GENMARSHAL = @GLIB_GENMARSHAL@
+GLIB_LIBS = @GLIB_LIBS@
+GLIB_MKENUMS = @GLIB_MKENUMS@
+GOBJECT_QUERY = @GOBJECT_QUERY@
+GPGME_CONFIG_API_VERSION = @GPGME_CONFIG_API_VERSION@
+GPGME_CONFIG_AVAIL_LANG = @GPGME_CONFIG_AVAIL_LANG@
+GPGME_CONFIG_CFLAGS = @GPGME_CONFIG_CFLAGS@
+GPGME_CONFIG_HOST = @GPGME_CONFIG_HOST@
+GPGME_CONFIG_LIBS = @GPGME_CONFIG_LIBS@
+GPGME_QTTEST_CFLAGS = @GPGME_QTTEST_CFLAGS@
+GPGME_QTTEST_LIBS = @GPGME_QTTEST_LIBS@
+GPGME_QT_CFLAGS = @GPGME_QT_CFLAGS@
+GPGME_QT_LIBS = @GPGME_QT_LIBS@
+GPG_ERROR_CFLAGS = @GPG_ERROR_CFLAGS@
+GPG_ERROR_CONFIG = @GPG_ERROR_CONFIG@
+GPG_ERROR_LIBS = @GPG_ERROR_LIBS@
+GPG_ERROR_MT_CFLAGS = @GPG_ERROR_MT_CFLAGS@
+GPG_ERROR_MT_LIBS = @GPG_ERROR_MT_LIBS@
+GRAPHVIZ = @GRAPHVIZ@
+GREP = @GREP@
+HAVE_CXX11 = @HAVE_CXX11@
+HAVE_DOT = @HAVE_DOT@
+INSTALL = @INSTALL@
+INSTALL_DATA = @INSTALL_DATA@
+INSTALL_PROGRAM = @INSTALL_PROGRAM@
+INSTALL_SCRIPT = @INSTALL_SCRIPT@
+INSTALL_STRIP_PROGRAM = @INSTALL_STRIP_PROGRAM@
+LD = @LD@
+LDFLAGS = @LDFLAGS@
+LIBASSUAN_CFLAGS = @LIBASSUAN_CFLAGS@
+LIBASSUAN_CONFIG = @LIBASSUAN_CONFIG@
+LIBASSUAN_LIBS = @LIBASSUAN_LIBS@
+LIBGPGMEPP_LT_AGE = @LIBGPGMEPP_LT_AGE@
+LIBGPGMEPP_LT_CURRENT = @LIBGPGMEPP_LT_CURRENT@
+LIBGPGMEPP_LT_REVISION = @LIBGPGMEPP_LT_REVISION@
+LIBGPGME_LT_AGE = @LIBGPGME_LT_AGE@
+LIBGPGME_LT_CURRENT = @LIBGPGME_LT_CURRENT@
+LIBGPGME_LT_REVISION = @LIBGPGME_LT_REVISION@
+LIBOBJS = @LIBOBJS@
+LIBQGPGME_LT_AGE = @LIBQGPGME_LT_AGE@
+LIBQGPGME_LT_CURRENT = @LIBQGPGME_LT_CURRENT@
+LIBQGPGME_LT_REVISION = @LIBQGPGME_LT_REVISION@
+LIBS = @LIBS@
+LIBTOOL = @LIBTOOL@
+LIPO = @LIPO@
+LN_S = @LN_S@
+LTLIBOBJS = @LTLIBOBJS@
+MAINT = @MAINT@
+MAKEINFO = @MAKEINFO@
+MANIFEST_TOOL = @MANIFEST_TOOL@
+MKDIR_P = @MKDIR_P@
+MOC = @MOC@
+MOC2 = @MOC2@
+NEED__FILE_OFFSET_BITS = @NEED__FILE_OFFSET_BITS@
+NM = @NM@
+NMEDIT = @NMEDIT@
+OBJDUMP = @OBJDUMP@
+OBJEXT = @OBJEXT@
+OTOOL = @OTOOL@
+OTOOL64 = @OTOOL64@
+PACKAGE = @PACKAGE@
+PACKAGE_BUGREPORT = @PACKAGE_BUGREPORT@
+PACKAGE_NAME = @PACKAGE_NAME@
+PACKAGE_STRING = @PACKAGE_STRING@
+PACKAGE_TARNAME = @PACKAGE_TARNAME@
+PACKAGE_URL = @PACKAGE_URL@
+PACKAGE_VERSION = @PACKAGE_VERSION@
+PATH_SEPARATOR = @PATH_SEPARATOR@
+PKG_CONFIG = @PKG_CONFIG@
+PYTHON = @PYTHON@
+PYTHONS = @PYTHONS@
+PYTHON_CPPFLAGS = @PYTHON_CPPFLAGS@
+PYTHON_EXEC_PREFIX = @PYTHON_EXEC_PREFIX@
+PYTHON_EXTRA_LDFLAGS = @PYTHON_EXTRA_LDFLAGS@
+PYTHON_EXTRA_LIBS = @PYTHON_EXTRA_LIBS@
+PYTHON_LDFLAGS = @PYTHON_LDFLAGS@
+PYTHON_PLATFORM = @PYTHON_PLATFORM@
+PYTHON_PREFIX = @PYTHON_PREFIX@
+PYTHON_SITE_PKG = @PYTHON_SITE_PKG@
+PYTHON_VERSION = @PYTHON_VERSION@
+PYTHON_VERSIONS = @PYTHON_VERSIONS@
+QTCHOOSER = @QTCHOOSER@
+RANLIB = @RANLIB@
+RC = @RC@
+SED = @SED@
+SET_MAKE = @SET_MAKE@
+SHELL = @SHELL@
+STRIP = @STRIP@
+SWIG = @SWIG@
+SWIG_LIB = @SWIG_LIB@
+SYSROOT = @SYSROOT@
+VERSION = @VERSION@
+VERSION_NUMBER = @VERSION_NUMBER@
+abs_builddir = @abs_builddir@
+abs_srcdir = @abs_srcdir@
+abs_top_builddir = @abs_top_builddir@
+abs_top_srcdir = @abs_top_srcdir@
+ac_ct_AR = @ac_ct_AR@
+ac_ct_CC = @ac_ct_CC@
+ac_ct_CXX = @ac_ct_CXX@
+ac_ct_DUMPBIN = @ac_ct_DUMPBIN@
+am__include = @am__include@
+am__leading_dot = @am__leading_dot@
+am__quote = @am__quote@
+am__tar = @am__tar@
+am__untar = @am__untar@
+bindir = @bindir@
+build = @build@
+build_alias = @build_alias@
+build_cpu = @build_cpu@
+build_os = @build_os@
+build_vendor = @build_vendor@
+builddir = @builddir@
+datadir = @datadir@
+datarootdir = @datarootdir@
+docdir = @docdir@
+dvidir = @dvidir@
+emacs_local_vars_begin = @emacs_local_vars_begin@
+emacs_local_vars_end = @emacs_local_vars_end@
+emacs_local_vars_read_only = @emacs_local_vars_read_only@
+exec_prefix = @exec_prefix@
+host = @host@
+host_alias = @host_alias@
+host_cpu = @host_cpu@
+host_os = @host_os@
+host_vendor = @host_vendor@
+htmldir = @htmldir@
+includedir = @includedir@
+infodir = @infodir@
+install_sh = @install_sh@
+libdir = @libdir@
+libexecdir = @libexecdir@
+localedir = @localedir@
+localstatedir = @localstatedir@
+mandir = @mandir@
+mkdir_p = @mkdir_p@
+oldincludedir = @oldincludedir@
+pdfdir = @pdfdir@
+pkgpyexecdir = @pkgpyexecdir@
+pkgpythondir = @pkgpythondir@
+prefix = @prefix@
+program_transform_name = @program_transform_name@
+psdir = @psdir@
+pyexecdir = @pyexecdir@
+pythondir = @pythondir@
+sbindir = @sbindir@
+sharedstatedir = @sharedstatedir@
+srcdir = @srcdir@
+sysconfdir = @sysconfdir@
+target_alias = @target_alias@
+top_build_prefix = @top_build_prefix@
+top_builddir = @top_builddir@
+top_srcdir = @top_srcdir@
+
+# Makefile.am for GPGMEPP.
+# Copyright (C) 2016 Intevation GmbH
+#
+# This file is part of GPGMEPP.
+#
+# GPGME-CL 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.
+#
+# GPGME-CL is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU Lesser General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program; if not, write to the Free Software
+# Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
+# 02111-1307, USA
+lib_LTLIBRARIES = libqgpgme.la
+EXTRA_DIST = QGpgmeConfig.cmake.in.in QGpgmeConfigVersion.cmake.in \
+ gpgme_backend_debug.h qgpgme_version.h.in
+
+qgpgme_sources = \
+ dataprovider.cpp job.cpp qgpgmeadduseridjob.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 \
+ qgpgmerefreshkeysjob.cpp \
+ qgpgmesecretkeyexportjob.cpp qgpgmesignencryptjob.cpp \
+ qgpgmesignjob.cpp qgpgmesignkeyjob.cpp qgpgmeverifydetachedjob.cpp \
+ qgpgmeverifyopaquejob.cpp threadedjobmixin.cpp \
+ qgpgmekeyformailboxjob.cpp gpgme_backend_debug.cpp \
+ qgpgmetofupolicyjob.cpp \
+ defaultkeygenerationjob.cpp qgpgmewkspublishjob.cpp
+
+
+# If you add one here make sure that you also add one in camelcase
+qgpgme_headers = \
+ adduseridjob.h \
+ changeexpiryjob.h \
+ changeownertrustjob.h \
+ changepasswdjob.h \
+ dataprovider.h \
+ decryptjob.h \
+ decryptverifyjob.h \
+ downloadjob.h \
+ encryptjob.h \
+ exportjob.h \
+ hierarchicalkeylistjob.h \
+ job.h \
+ keyformailboxjob.h \
+ multideletejob.h \
+ protocol.h \
+ qgpgme_export.h \
+ qgpgmenewcryptoconfig.h \
+ signjob.h \
+ signkeyjob.h \
+ signencryptjob.h \
+ verifyopaquejob.h \
+ refreshkeysjob.h \
+ cryptoconfig.h \
+ deletejob.h \
+ importfromkeyserverjob.h \
+ importjob.h \
+ keygenerationjob.h \
+ keylistjob.h \
+ listallkeysjob.h \
+ verifydetachedjob.h \
+ defaultkeygenerationjob.h \
+ tofupolicyjob.h \
+ wkspublishjob.h
+
+camelcase_headers = \
+ AddUserIDJob \
+ ChangeExpiryJob \
+ ChangeOwnerTrustJob \
+ ChangePasswdJob \
+ DataProvider \
+ DecryptJob \
+ DecryptVerifyJob \
+ DownloadJob \
+ EncryptJob \
+ ExportJob \
+ HierarchicalKeyKistJob \
+ Job \
+ MultiDeleteJob \
+ Protocol \
+ QGpgMENewCryptoConfig \
+ SignJob \
+ SignKeyJob \
+ SignEncryptJob \
+ VerifyOpaqueJob \
+ RefreshKeysJob \
+ CryptoConfig \
+ DeleteJob \
+ ImportFromKeyserverJob \
+ ImportJob \
+ KeyGenerationJob \
+ KeyListJob \
+ ListAllKeysJob \
+ VerifyDetachedJob \
+ KeyForMailboxJob \
+ DefaultKeyGenerationJob \
+ WKSPublishJob \
+ TofuPolicyJob
+
+private_qgpgme_headers = \
+ qgpgme_export.h \
+ abstractimportjob.h \
+ protocol_p.h \
+ qgpgmeadduseridjob.h \
+ qgpgmebackend.h \
+ qgpgmechangeexpiryjob.h \
+ qgpgmechangeownertrustjob.h \
+ qgpgmechangepasswdjob.h \
+ qgpgmedecryptjob.h \
+ qgpgmedecryptverifyjob.h \
+ qgpgmedeletejob.h \
+ qgpgmedownloadjob.h \
+ qgpgmeencryptjob.h \
+ qgpgmeexportjob.h \
+ qgpgmeimportfromkeyserverjob.h \
+ qgpgmeimportjob.h \
+ qgpgmekeygenerationjob.h \
+ qgpgmekeylistjob.h \
+ qgpgmelistallkeysjob.h \
+ qgpgmerefreshkeysjob.h \
+ qgpgmesecretkeyexportjob.h \
+ qgpgmesignencryptjob.h \
+ qgpgmesignjob.h \
+ qgpgmesignkeyjob.h \
+ qgpgmeverifydetachedjob.h \
+ qgpgmeverifyopaquejob.h \
+ qgpgmekeyformailboxjob.h \
+ qgpgmewkspublishjob.h \
+ qgpgmetofupolicyjob.h \
+ specialjob.h \
+ threadedjobmixin.h
+
+qgpgme_moc_sources = \
+ abstractimportjob.moc \
+ adduseridjob.moc \
+ changeexpiryjob.moc \
+ changeownertrustjob.moc \
+ changepasswdjob.moc \
+ decryptjob.moc \
+ decryptverifyjob.moc \
+ deletejob.moc \
+ downloadjob.moc \
+ encryptjob.moc \
+ exportjob.moc \
+ hierarchicalkeylistjob.moc \
+ importfromkeyserverjob.moc \
+ importjob.moc \
+ job.moc \
+ keygenerationjob.moc \
+ keylistjob.moc \
+ listallkeysjob.moc \
+ multideletejob.moc \
+ qgpgmeadduseridjob.moc \
+ qgpgmechangeexpiryjob.moc \
+ qgpgmechangeownertrustjob.moc \
+ qgpgmechangepasswdjob.moc \
+ qgpgmedecryptjob.moc \
+ qgpgmedecryptverifyjob.moc \
+ qgpgmedeletejob.moc \
+ qgpgmedownloadjob.moc \
+ qgpgmeencryptjob.moc \
+ qgpgmeexportjob.moc \
+ qgpgmeimportfromkeyserverjob.moc \
+ qgpgmeimportjob.moc \
+ qgpgmekeygenerationjob.moc \
+ qgpgmekeylistjob.moc \
+ qgpgmelistallkeysjob.moc \
+ qgpgmerefreshkeysjob.moc \
+ qgpgmesecretkeyexportjob.moc \
+ qgpgmesignencryptjob.moc \
+ qgpgmesignjob.moc \
+ qgpgmesignkeyjob.moc \
+ qgpgmeverifydetachedjob.moc \
+ qgpgmeverifyopaquejob.moc \
+ qgpgmewkspublishjob.moc \
+ tofupolicyjob.moc \
+ qgpgmetofupolicyjob.moc \
+ refreshkeysjob.moc \
+ signencryptjob.moc \
+ signjob.moc \
+ signkeyjob.moc \
+ specialjob.moc \
+ verifydetachedjob.moc \
+ verifyopaquejob.moc \
+ keyformailboxjob.moc \
+ wkspublishjob.moc \
+ qgpgmekeyformailboxjob.moc \
+ defaultkeygenerationjob.moc
+
+qgpgmeincludedir = $(includedir)/qgpgme
+qgpgmeinclude_HEADERS = $(qgpgme_headers)
+camelcaseincludedir = $(includedir)/QGpgME
+camelcaseinclude_HEADERS = $(camelcase_headers)
+nodist_include_HEADERS = qgpgme_version.h
+libqgpgme_la_SOURCES = $(qgpgme_sources) $(qgpgme_headers) $(private_qgpgme_headers)
+AM_CPPFLAGS = -I$(top_srcdir)/lang/cpp/src -I$(top_builddir)/src \
+ @GPGME_QT_CFLAGS@ @GPG_ERROR_CFLAGS@ @LIBASSUAN_CFLAGS@ \
+ -DBUILDING_QGPGME
+
+libqgpgme_la_LIBADD = ../../cpp/src/libgpgmepp.la ../../../src/libgpgme.la \
+ @LIBASSUAN_LIBS@ @GPGME_QT_LIBS@
+
+libqgpgme_la_LDFLAGS = -version-info \
+ @LIBQGPGME_LT_CURRENT@:@LIBQGPGME_LT_REVISION@:@LIBQGPGME_LT_AGE@
+
+@HAVE_W32_SYSTEM_FALSE@libsuffix = .so
+@HAVE_W32_SYSTEM_TRUE@libsuffix = .dll.a
+BUILT_SOURCES = $(qgpgme_moc_sources) $(camelcase_headers)
+CLEANFILES = $(qgpgme_moc_sources) $(camelcase_headers) QGpgmeConfig.cmake
+nodist_libqgpgme_la_SOURCES = $(qgpgme_moc_sources)
+all: $(BUILT_SOURCES)
+ $(MAKE) $(AM_MAKEFLAGS) all-am
+
+.SUFFIXES:
+.SUFFIXES: .cpp .h .lo .moc .o .obj
+$(srcdir)/Makefile.in: @MAINTAINER_MODE_TRUE@ $(srcdir)/Makefile.am $(am__configure_deps)
+ @for dep in $?; do \
+ case '$(am__configure_deps)' in \
+ *$$dep*) \
+ ( cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh ) \
+ && { if test -f $@; then exit 0; else break; fi; }; \
+ exit 1;; \
+ esac; \
+ done; \
+ echo ' cd $(top_srcdir) && $(AUTOMAKE) --gnu lang/qt/src/Makefile'; \
+ $(am__cd) $(top_srcdir) && \
+ $(AUTOMAKE) --gnu lang/qt/src/Makefile
+.PRECIOUS: Makefile
+Makefile: $(srcdir)/Makefile.in $(top_builddir)/config.status
+ @case '$?' in \
+ *config.status*) \
+ cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh;; \
+ *) \
+ echo ' cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__depfiles_maybe)'; \
+ cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__depfiles_maybe);; \
+ esac;
+
+$(top_builddir)/config.status: $(top_srcdir)/configure $(CONFIG_STATUS_DEPENDENCIES)
+ cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh
+
+$(top_srcdir)/configure: @MAINTAINER_MODE_TRUE@ $(am__configure_deps)
+ cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh
+$(ACLOCAL_M4): @MAINTAINER_MODE_TRUE@ $(am__aclocal_m4_deps)
+ cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh
+$(am__aclocal_m4_deps):
+QGpgmeConfig.cmake.in: $(top_builddir)/config.status $(srcdir)/QGpgmeConfig.cmake.in.in
+ cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@
+QGpgmeConfigVersion.cmake: $(top_builddir)/config.status $(srcdir)/QGpgmeConfigVersion.cmake.in
+ cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@
+qgpgme_version.h: $(top_builddir)/config.status $(srcdir)/qgpgme_version.h.in
+ cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@
+
+install-libLTLIBRARIES: $(lib_LTLIBRARIES)
+ @$(NORMAL_INSTALL)
+ @list='$(lib_LTLIBRARIES)'; test -n "$(libdir)" || list=; \
+ list2=; for p in $$list; do \
+ if test -f $$p; then \
+ list2="$$list2 $$p"; \
+ else :; fi; \
+ done; \
+ test -z "$$list2" || { \
+ echo " $(MKDIR_P) '$(DESTDIR)$(libdir)'"; \
+ $(MKDIR_P) "$(DESTDIR)$(libdir)" || exit 1; \
+ echo " $(LIBTOOL) $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=install $(INSTALL) $(INSTALL_STRIP_FLAG) $$list2 '$(DESTDIR)$(libdir)'"; \
+ $(LIBTOOL) $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=install $(INSTALL) $(INSTALL_STRIP_FLAG) $$list2 "$(DESTDIR)$(libdir)"; \
+ }
+
+uninstall-libLTLIBRARIES:
+ @$(NORMAL_UNINSTALL)
+ @list='$(lib_LTLIBRARIES)'; test -n "$(libdir)" || list=; \
+ for p in $$list; do \
+ $(am__strip_dir) \
+ echo " $(LIBTOOL) $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=uninstall rm -f '$(DESTDIR)$(libdir)/$$f'"; \
+ $(LIBTOOL) $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=uninstall rm -f "$(DESTDIR)$(libdir)/$$f"; \
+ done
+
+clean-libLTLIBRARIES:
+ -test -z "$(lib_LTLIBRARIES)" || rm -f $(lib_LTLIBRARIES)
+ @list='$(lib_LTLIBRARIES)'; \
+ locs=`for p in $$list; do echo $$p; done | \
+ sed 's|^[^/]*$$|.|; s|/[^/]*$$||; s|$$|/so_locations|' | \
+ sort -u`; \
+ test -z "$$locs" || { \
+ echo rm -f $${locs}; \
+ rm -f $${locs}; \
+ }
+
+libqgpgme.la: $(libqgpgme_la_OBJECTS) $(libqgpgme_la_DEPENDENCIES) $(EXTRA_libqgpgme_la_DEPENDENCIES)
+ $(AM_V_CXXLD)$(libqgpgme_la_LINK) -rpath $(libdir) $(libqgpgme_la_OBJECTS) $(libqgpgme_la_LIBADD) $(LIBS)
+
+mostlyclean-compile:
+ -rm -f *.$(OBJEXT)
+
+distclean-compile:
+ -rm -f *.tab.c
+
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/dataprovider.Plo@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/defaultkeygenerationjob.Plo@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/gpgme_backend_debug.Plo@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/job.Plo@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/qgpgmeadduseridjob.Plo@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/qgpgmebackend.Plo@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/qgpgmechangeexpiryjob.Plo@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/qgpgmechangeownertrustjob.Plo@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/qgpgmechangepasswdjob.Plo@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/qgpgmedecryptjob.Plo@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/qgpgmedecryptverifyjob.Plo@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/qgpgmedeletejob.Plo@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/qgpgmedownloadjob.Plo@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/qgpgmeencryptjob.Plo@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/qgpgmeexportjob.Plo@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/qgpgmeimportfromkeyserverjob.Plo@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/qgpgmeimportjob.Plo@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/qgpgmekeyformailboxjob.Plo@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/qgpgmekeygenerationjob.Plo@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/qgpgmekeylistjob.Plo@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/qgpgmelistallkeysjob.Plo@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/qgpgmenewcryptoconfig.Plo@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/qgpgmerefreshkeysjob.Plo@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/qgpgmesecretkeyexportjob.Plo@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/qgpgmesignencryptjob.Plo@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/qgpgmesignjob.Plo@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/qgpgmesignkeyjob.Plo@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/qgpgmetofupolicyjob.Plo@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/qgpgmeverifydetachedjob.Plo@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/qgpgmeverifyopaquejob.Plo@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/qgpgmewkspublishjob.Plo@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/threadedjobmixin.Plo@am__quote@
+
+.cpp.o:
+@am__fastdepCXX_TRUE@ $(AM_V_CXX)$(CXXCOMPILE) -MT $@ -MD -MP -MF $(DEPDIR)/$*.Tpo -c -o $@ $<
+@am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/$*.Tpo $(DEPDIR)/$*.Po
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@ $(AM_V_CXX)source='$<' object='$@' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCXX_FALSE@ $(AM_V_CXX@am__nodep@)$(CXXCOMPILE) -c -o $@ $<
+
+.cpp.obj:
+@am__fastdepCXX_TRUE@ $(AM_V_CXX)$(CXXCOMPILE) -MT $@ -MD -MP -MF $(DEPDIR)/$*.Tpo -c -o $@ `$(CYGPATH_W) '$<'`
+@am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/$*.Tpo $(DEPDIR)/$*.Po
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@ $(AM_V_CXX)source='$<' object='$@' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCXX_FALSE@ $(AM_V_CXX@am__nodep@)$(CXXCOMPILE) -c -o $@ `$(CYGPATH_W) '$<'`
+
+.cpp.lo:
+@am__fastdepCXX_TRUE@ $(AM_V_CXX)$(LTCXXCOMPILE) -MT $@ -MD -MP -MF $(DEPDIR)/$*.Tpo -c -o $@ $<
+@am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/$*.Tpo $(DEPDIR)/$*.Plo
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@ $(AM_V_CXX)source='$<' object='$@' libtool=yes @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCXX_FALSE@ $(AM_V_CXX@am__nodep@)$(LTCXXCOMPILE) -c -o $@ $<
+
+mostlyclean-libtool:
+ -rm -f *.lo
+
+clean-libtool:
+ -rm -rf .libs _libs
+install-camelcaseincludeHEADERS: $(camelcaseinclude_HEADERS)
+ @$(NORMAL_INSTALL)
+ @list='$(camelcaseinclude_HEADERS)'; test -n "$(camelcaseincludedir)" || list=; \
+ if test -n "$$list"; then \
+ echo " $(MKDIR_P) '$(DESTDIR)$(camelcaseincludedir)'"; \
+ $(MKDIR_P) "$(DESTDIR)$(camelcaseincludedir)" || exit 1; \
+ fi; \
+ for p in $$list; do \
+ if test -f "$$p"; then d=; else d="$(srcdir)/"; fi; \
+ echo "$$d$$p"; \
+ done | $(am__base_list) | \
+ while read files; do \
+ echo " $(INSTALL_HEADER) $$files '$(DESTDIR)$(camelcaseincludedir)'"; \
+ $(INSTALL_HEADER) $$files "$(DESTDIR)$(camelcaseincludedir)" || exit $$?; \
+ done
+
+uninstall-camelcaseincludeHEADERS:
+ @$(NORMAL_UNINSTALL)
+ @list='$(camelcaseinclude_HEADERS)'; test -n "$(camelcaseincludedir)" || list=; \
+ files=`for p in $$list; do echo $$p; done | sed -e 's|^.*/||'`; \
+ dir='$(DESTDIR)$(camelcaseincludedir)'; $(am__uninstall_files_from_dir)
+install-nodist_includeHEADERS: $(nodist_include_HEADERS)
+ @$(NORMAL_INSTALL)
+ @list='$(nodist_include_HEADERS)'; test -n "$(includedir)" || list=; \
+ if test -n "$$list"; then \
+ echo " $(MKDIR_P) '$(DESTDIR)$(includedir)'"; \
+ $(MKDIR_P) "$(DESTDIR)$(includedir)" || exit 1; \
+ fi; \
+ for p in $$list; do \
+ if test -f "$$p"; then d=; else d="$(srcdir)/"; fi; \
+ echo "$$d$$p"; \
+ done | $(am__base_list) | \
+ while read files; do \
+ echo " $(INSTALL_HEADER) $$files '$(DESTDIR)$(includedir)'"; \
+ $(INSTALL_HEADER) $$files "$(DESTDIR)$(includedir)" || exit $$?; \
+ done
+
+uninstall-nodist_includeHEADERS:
+ @$(NORMAL_UNINSTALL)
+ @list='$(nodist_include_HEADERS)'; test -n "$(includedir)" || list=; \
+ files=`for p in $$list; do echo $$p; done | sed -e 's|^.*/||'`; \
+ dir='$(DESTDIR)$(includedir)'; $(am__uninstall_files_from_dir)
+install-qgpgmeincludeHEADERS: $(qgpgmeinclude_HEADERS)
+ @$(NORMAL_INSTALL)
+ @list='$(qgpgmeinclude_HEADERS)'; test -n "$(qgpgmeincludedir)" || list=; \
+ if test -n "$$list"; then \
+ echo " $(MKDIR_P) '$(DESTDIR)$(qgpgmeincludedir)'"; \
+ $(MKDIR_P) "$(DESTDIR)$(qgpgmeincludedir)" || exit 1; \
+ fi; \
+ for p in $$list; do \
+ if test -f "$$p"; then d=; else d="$(srcdir)/"; fi; \
+ echo "$$d$$p"; \
+ done | $(am__base_list) | \
+ while read files; do \
+ echo " $(INSTALL_HEADER) $$files '$(DESTDIR)$(qgpgmeincludedir)'"; \
+ $(INSTALL_HEADER) $$files "$(DESTDIR)$(qgpgmeincludedir)" || exit $$?; \
+ done
+
+uninstall-qgpgmeincludeHEADERS:
+ @$(NORMAL_UNINSTALL)
+ @list='$(qgpgmeinclude_HEADERS)'; test -n "$(qgpgmeincludedir)" || list=; \
+ files=`for p in $$list; do echo $$p; done | sed -e 's|^.*/||'`; \
+ dir='$(DESTDIR)$(qgpgmeincludedir)'; $(am__uninstall_files_from_dir)
+
+ID: $(am__tagged_files)
+ $(am__define_uniq_tagged_files); mkid -fID $$unique
+tags: tags-am
+TAGS: tags
+
+tags-am: $(TAGS_DEPENDENCIES) $(am__tagged_files)
+ set x; \
+ here=`pwd`; \
+ $(am__define_uniq_tagged_files); \
+ shift; \
+ if test -z "$(ETAGS_ARGS)$$*$$unique"; then :; else \
+ test -n "$$unique" || unique=$$empty_fix; \
+ if test $$# -gt 0; then \
+ $(ETAGS) $(ETAGSFLAGS) $(AM_ETAGSFLAGS) $(ETAGS_ARGS) \
+ "$$@" $$unique; \
+ else \
+ $(ETAGS) $(ETAGSFLAGS) $(AM_ETAGSFLAGS) $(ETAGS_ARGS) \
+ $$unique; \
+ fi; \
+ fi
+ctags: ctags-am
+
+CTAGS: ctags
+ctags-am: $(TAGS_DEPENDENCIES) $(am__tagged_files)
+ $(am__define_uniq_tagged_files); \
+ test -z "$(CTAGS_ARGS)$$unique" \
+ || $(CTAGS) $(CTAGSFLAGS) $(AM_CTAGSFLAGS) $(CTAGS_ARGS) \
+ $$unique
+
+GTAGS:
+ here=`$(am__cd) $(top_builddir) && pwd` \
+ && $(am__cd) $(top_srcdir) \
+ && gtags -i $(GTAGS_ARGS) "$$here"
+cscopelist: cscopelist-am
+
+cscopelist-am: $(am__tagged_files)
+ list='$(am__tagged_files)'; \
+ case "$(srcdir)" in \
+ [\\/]* | ?:[\\/]*) sdir="$(srcdir)" ;; \
+ *) sdir=$(subdir)/$(srcdir) ;; \
+ esac; \
+ for i in $$list; do \
+ if test -f "$$i"; then \
+ echo "$(subdir)/$$i"; \
+ else \
+ echo "$$sdir/$$i"; \
+ fi; \
+ done >> $(top_builddir)/cscope.files
+
+distclean-tags:
+ -rm -f TAGS ID GTAGS GRTAGS GSYMS GPATH tags
+
+distdir: $(DISTFILES)
+ @srcdirstrip=`echo "$(srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \
+ topsrcdirstrip=`echo "$(top_srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \
+ list='$(DISTFILES)'; \
+ dist_files=`for file in $$list; do echo $$file; done | \
+ sed -e "s|^$$srcdirstrip/||;t" \
+ -e "s|^$$topsrcdirstrip/|$(top_builddir)/|;t"`; \
+ case $$dist_files in \
+ */*) $(MKDIR_P) `echo "$$dist_files" | \
+ sed '/\//!d;s|^|$(distdir)/|;s,/[^/]*$$,,' | \
+ sort -u` ;; \
+ esac; \
+ for file in $$dist_files; do \
+ if test -f $$file || test -d $$file; then d=.; else d=$(srcdir); fi; \
+ if test -d $$d/$$file; then \
+ dir=`echo "/$$file" | sed -e 's,/[^/]*$$,,'`; \
+ if test -d "$(distdir)/$$file"; then \
+ find "$(distdir)/$$file" -type d ! -perm -700 -exec chmod u+rwx {} \;; \
+ fi; \
+ if test -d $(srcdir)/$$file && test $$d != $(srcdir); then \
+ cp -fpR $(srcdir)/$$file "$(distdir)$$dir" || exit 1; \
+ find "$(distdir)/$$file" -type d ! -perm -700 -exec chmod u+rwx {} \;; \
+ fi; \
+ cp -fpR $$d/$$file "$(distdir)$$dir" || exit 1; \
+ else \
+ test -f "$(distdir)/$$file" \
+ || cp -p $$d/$$file "$(distdir)/$$file" \
+ || exit 1; \
+ fi; \
+ done
+check-am: all-am
+check: $(BUILT_SOURCES)
+ $(MAKE) $(AM_MAKEFLAGS) check-am
+all-am: Makefile $(LTLIBRARIES) $(HEADERS)
+installdirs:
+ for dir in "$(DESTDIR)$(libdir)" "$(DESTDIR)$(camelcaseincludedir)" "$(DESTDIR)$(includedir)" "$(DESTDIR)$(qgpgmeincludedir)"; do \
+ test -z "$$dir" || $(MKDIR_P) "$$dir"; \
+ done
+install: $(BUILT_SOURCES)
+ $(MAKE) $(AM_MAKEFLAGS) install-am
+install-exec: install-exec-am
+install-data: install-data-am
+uninstall: uninstall-am
+
+install-am: all-am
+ @$(MAKE) $(AM_MAKEFLAGS) install-exec-am install-data-am
+
+installcheck: installcheck-am
+install-strip:
+ if test -z '$(STRIP)'; then \
+ $(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \
+ install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \
+ install; \
+ else \
+ $(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \
+ install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \
+ "INSTALL_PROGRAM_ENV=STRIPPROG='$(STRIP)'" install; \
+ fi
+mostlyclean-generic:
+
+clean-generic:
+ -test -z "$(CLEANFILES)" || rm -f $(CLEANFILES)
+
+distclean-generic:
+ -test -z "$(CONFIG_CLEAN_FILES)" || rm -f $(CONFIG_CLEAN_FILES)
+ -test . = "$(srcdir)" || test -z "$(CONFIG_CLEAN_VPATH_FILES)" || rm -f $(CONFIG_CLEAN_VPATH_FILES)
+
+maintainer-clean-generic:
+ @echo "This command is intended for maintainers to use"
+ @echo "it deletes files that may require special tools to rebuild."
+ -test -z "$(BUILT_SOURCES)" || rm -f $(BUILT_SOURCES)
+clean: clean-am
+
+clean-am: clean-generic clean-libLTLIBRARIES clean-libtool \
+ mostlyclean-am
+
+distclean: distclean-am
+ -rm -rf ./$(DEPDIR)
+ -rm -f Makefile
+distclean-am: clean-am distclean-compile distclean-generic \
+ distclean-tags
+
+dvi: dvi-am
+
+dvi-am:
+
+html: html-am
+
+html-am:
+
+info: info-am
+
+info-am:
+
+install-data-am: install-camelcaseincludeHEADERS install-data-local \
+ install-nodist_includeHEADERS install-qgpgmeincludeHEADERS
+
+install-dvi: install-dvi-am
+
+install-dvi-am:
+
+install-exec-am: install-libLTLIBRARIES
+
+install-html: install-html-am
+
+install-html-am:
+
+install-info: install-info-am
+
+install-info-am:
+
+install-man:
+
+install-pdf: install-pdf-am
+
+install-pdf-am:
+
+install-ps: install-ps-am
+
+install-ps-am:
+
+installcheck-am:
+
+maintainer-clean: maintainer-clean-am
+ -rm -rf ./$(DEPDIR)
+ -rm -f Makefile
+maintainer-clean-am: distclean-am maintainer-clean-generic
+
+mostlyclean: mostlyclean-am
+
+mostlyclean-am: mostlyclean-compile mostlyclean-generic \
+ mostlyclean-libtool
+
+pdf: pdf-am
+
+pdf-am:
+
+ps: ps-am
+
+ps-am:
+
+uninstall-am: uninstall-camelcaseincludeHEADERS \
+ uninstall-libLTLIBRARIES uninstall-local \
+ uninstall-nodist_includeHEADERS uninstall-qgpgmeincludeHEADERS
+
+.MAKE: all check install install-am install-strip
+
+.PHONY: CTAGS GTAGS TAGS all all-am check check-am clean clean-generic \
+ clean-libLTLIBRARIES clean-libtool cscopelist-am ctags \
+ ctags-am distclean distclean-compile distclean-generic \
+ distclean-libtool distclean-tags distdir dvi dvi-am html \
+ html-am info info-am install install-am \
+ install-camelcaseincludeHEADERS install-data install-data-am \
+ install-data-local install-dvi install-dvi-am install-exec \
+ install-exec-am install-html install-html-am install-info \
+ install-info-am install-libLTLIBRARIES install-man \
+ install-nodist_includeHEADERS install-pdf install-pdf-am \
+ install-ps install-ps-am install-qgpgmeincludeHEADERS \
+ install-strip installcheck installcheck-am installdirs \
+ maintainer-clean maintainer-clean-generic mostlyclean \
+ mostlyclean-compile mostlyclean-generic mostlyclean-libtool \
+ pdf pdf-am ps ps-am tags tags-am uninstall uninstall-am \
+ uninstall-camelcaseincludeHEADERS uninstall-libLTLIBRARIES \
+ uninstall-local uninstall-nodist_includeHEADERS \
+ uninstall-qgpgmeincludeHEADERS
+
+
+QGpgmeConfig.cmake: QGpgmeConfig.cmake.in
+ sed -e 's|[@]resolved_libdir@|$(libdir)|g' < "$<" > "$@"
+ sed -e 's|[@]libsuffix@|$(libsuffix)|g' < "$@" > "$@".2
+ mv "$@".2 "$@"
+
+$(camelcase_headers): Makefile.am
+ echo -n "#include \"qgpgme/" > "$@"
+ echo -n "$@" | tr '[:upper:]' '[:lower:]' >> "$@"
+ echo ".h\"" >> "$@"
+
+install-cmake-files: QGpgmeConfig.cmake QGpgmeConfigVersion.cmake
+ -$(INSTALL) -d $(DESTDIR)$(libdir)/cmake/Gpgmepp
+ $(INSTALL) QGpgmeConfig.cmake \
+ $(DESTDIR)$(libdir)/cmake/Gpgmepp/QGpgmeConfig.cmake
+ $(INSTALL) QGpgmeConfigVersion.cmake \
+ $(DESTDIR)$(libdir)/cmake/Gpgmepp/QGpgmeConfigVersion.cmake
+
+uninstall-cmake-files:
+ -rm $(DESTDIR)$(libdir)/cmake/Gpgmepp/QGpgmeConfigVersion.cmake
+ -rm $(DESTDIR)$(libdir)/cmake/Gpgmepp/QGpgmeConfig.cmake
+ -rmdir $(DESTDIR)$(libdir)/cmake/Gpgmepp/
+
+install-data-local: install-cmake-files
+
+uninstall-local: uninstall-cmake-files
+
+.h.moc:
+ $(MOC) `test -f '$<' || echo '$(srcdir)/'`$< -o $@
+
+# Tell versions [3.59,3.63) of GNU make to not export all variables.
+# Otherwise a system limit (for SysV at least) may be exceeded.
+.NOEXPORT:
diff --git a/lang/qt/src/MultiDeleteJob b/lang/qt/src/MultiDeleteJob
new file mode 100644
index 0000000..e398c79
--- /dev/null
+++ b/lang/qt/src/MultiDeleteJob
@@ -0,0 +1 @@
+#include "qgpgme/multideletejob.h"
diff --git a/lang/qt/src/Protocol b/lang/qt/src/Protocol
new file mode 100644
index 0000000..6f92b75
--- /dev/null
+++ b/lang/qt/src/Protocol
@@ -0,0 +1 @@
+#include "qgpgme/protocol.h"
diff --git a/lang/qt/src/QGpgMENewCryptoConfig b/lang/qt/src/QGpgMENewCryptoConfig
new file mode 100644
index 0000000..99f353f
--- /dev/null
+++ b/lang/qt/src/QGpgMENewCryptoConfig
@@ -0,0 +1 @@
+#include "qgpgme/qgpgmenewcryptoconfig.h"
diff --git a/lang/qt/src/QGpgmeConfig.cmake.in.in b/lang/qt/src/QGpgmeConfig.cmake.in.in
new file mode 100644
index 0000000..3d19696
--- /dev/null
+++ b/lang/qt/src/QGpgmeConfig.cmake.in.in
@@ -0,0 +1,107 @@
+# CMake Config file for QGPGME.
+# Copyright (C) 2016 Intevation GmbH
+#
+# This file is part of GPGME.
+#
+# GPGME-CL 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.
+#
+# GPGME-CL is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU Lesser General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program; if not, write to the Free Software
+# Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
+# 02111-1307, USA
+
+# based on a generated file from cmake.
+# Generated by CMake 3.0.2
+
+if("${CMAKE_MAJOR_VERSION}.${CMAKE_MINOR_VERSION}" LESS 2.5)
+ message(FATAL_ERROR "CMake >= 2.6.0 required")
+endif()
+cmake_policy(PUSH)
+cmake_policy(VERSION 2.6)
+#----------------------------------------------------------------
+# Generated CMake target import file.
+#----------------------------------------------------------------
+
+# Commands may need to know the format version.
+set(CMAKE_IMPORT_FILE_VERSION 1)
+
+# Protect against multiple inclusion, which would fail when already imported targets are added once more.
+set(_targetsDefined)
+set(_targetsNotDefined)
+set(_expectedTargets)
+foreach(_expectedTarget QGpgme KF5::QGpgme)
+ list(APPEND _expectedTargets ${_expectedTarget})
+ if(NOT TARGET ${_expectedTarget})
+ list(APPEND _targetsNotDefined ${_expectedTarget})
+ endif()
+ if(TARGET ${_expectedTarget})
+ list(APPEND _targetsDefined ${_expectedTarget})
+ endif()
+endforeach()
+if("${_targetsDefined}" STREQUAL "${_expectedTargets}")
+ set(CMAKE_IMPORT_FILE_VERSION)
+ cmake_policy(POP)
+ return()
+endif()
+if(NOT "${_targetsDefined}" STREQUAL "")
+ message(FATAL_ERROR "Some (but not all) targets in this export set were already defined.\nTargets Defined: ${_targetsDefined}\nTargets not yet defined: ${_targetsNotDefined}\n")
+endif()
+unset(_targetsDefined)
+unset(_targetsNotDefined)
+unset(_expectedTargets)
+
+# Compute the installation prefix relative to this file.
+get_filename_component(_IMPORT_PREFIX "${CMAKE_CURRENT_LIST_FILE}" PATH)
+get_filename_component(_IMPORT_PREFIX "${_IMPORT_PREFIX}" PATH)
+get_filename_component(_IMPORT_PREFIX "${_IMPORT_PREFIX}" PATH)
+get_filename_component(_IMPORT_PREFIX "${_IMPORT_PREFIX}" PATH)
+
+# Create imported target QGpgme
+add_library(QGpgme SHARED IMPORTED)
+
+set_target_properties(QGpgme PROPERTIES
+ INTERFACE_INCLUDE_DIRECTORIES "${_IMPORT_PREFIX}/include;${_IMPORT_PREFIX}/include/qgpgme"
+ INTERFACE_LINK_LIBRARIES "Gpgmepp;Qt5::Core"
+ IMPORTED_LOCATION "@resolved_libdir@/libqgpgme@libsuffix@"
+)
+
+if(CMAKE_VERSION VERSION_LESS 2.8.12)
+ message(FATAL_ERROR "This file relies on consumers using CMake 2.8.12 or greater.")
+endif()
+
+# Cleanup temporary variables.
+set(_IMPORT_PREFIX)
+
+# Loop over all imported files and verify that they actually exist
+foreach(target ${_IMPORT_CHECK_TARGETS} )
+ foreach(file ${_IMPORT_CHECK_FILES_FOR_${target}} )
+ if(NOT EXISTS "${file}" )
+ message(FATAL_ERROR "The imported target \"${target}\" references the file
+ \"${file}\"
+but this file does not exist. Possible reasons include:
+* The file was deleted, renamed, or moved to another location.
+* An install or uninstall procedure did not complete successfully.
+* The installation package was faulty and contained
+ \"${CMAKE_CURRENT_LIST_FILE}\"
+but not all the files it references.
+")
+ endif()
+ endforeach()
+ unset(_IMPORT_CHECK_FILES_FOR_${target})
+endforeach()
+unset(_IMPORT_CHECK_TARGETS)
+
+# This file does not depend on other imported targets which have
+# been exported from the same project but in a separate export set.
+
+# Commands beyond this point should not need to know the version.
+set(CMAKE_IMPORT_FILE_VERSION)
+cmake_policy(POP)
diff --git a/lang/qt/src/QGpgmeConfigVersion.cmake.in b/lang/qt/src/QGpgmeConfigVersion.cmake.in
new file mode 100644
index 0000000..04a12cb
--- /dev/null
+++ b/lang/qt/src/QGpgmeConfigVersion.cmake.in
@@ -0,0 +1,31 @@
+# CMake Version file for QGPGME.
+# Copyright (C) 2016 Intevation GmbH
+#
+# This file is part of GPGME.
+#
+# GPGME-CL 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.
+#
+# GPGME-CL is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU Lesser General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program; if not, write to the Free Software
+# Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
+# 02111-1307, USA
+
+# based on a generated file from cmake.
+set(PACKAGE_VERSION "@LIBQGPGME_LT_CURRENT@.@LIBQGPGME_LT_AGE@.@LIBQGPGME_LT_REVISION@.@BUILD_REVISION@")
+
+if("${PACKAGE_VERSION}" VERSION_LESS "${PACKAGE_FIND_VERSION}" )
+ set(PACKAGE_VERSION_COMPATIBLE FALSE)
+else()
+ set(PACKAGE_VERSION_COMPATIBLE TRUE)
+ if( "${PACKAGE_FIND_VERSION}" STREQUAL "${PACKAGE_VERSION}")
+ set(PACKAGE_VERSION_EXACT TRUE)
+ endif()
+endif()
diff --git a/lang/qt/src/RefreshKeysJob b/lang/qt/src/RefreshKeysJob
new file mode 100644
index 0000000..678d8d0
--- /dev/null
+++ b/lang/qt/src/RefreshKeysJob
@@ -0,0 +1 @@
+#include "qgpgme/refreshkeysjob.h"
diff --git a/lang/qt/src/SignEncryptJob b/lang/qt/src/SignEncryptJob
new file mode 100644
index 0000000..4075e49
--- /dev/null
+++ b/lang/qt/src/SignEncryptJob
@@ -0,0 +1 @@
+#include "qgpgme/signencryptjob.h"
diff --git a/lang/qt/src/SignJob b/lang/qt/src/SignJob
new file mode 100644
index 0000000..135cab1
--- /dev/null
+++ b/lang/qt/src/SignJob
@@ -0,0 +1 @@
+#include "qgpgme/signjob.h"
diff --git a/lang/qt/src/SignKeyJob b/lang/qt/src/SignKeyJob
new file mode 100644
index 0000000..094753c
--- /dev/null
+++ b/lang/qt/src/SignKeyJob
@@ -0,0 +1 @@
+#include "qgpgme/signkeyjob.h"
diff --git a/lang/qt/src/TofuPolicyJob b/lang/qt/src/TofuPolicyJob
new file mode 100644
index 0000000..e379942
--- /dev/null
+++ b/lang/qt/src/TofuPolicyJob
@@ -0,0 +1 @@
+#include "qgpgme/tofupolicyjob.h"
diff --git a/lang/qt/src/VerifyDetachedJob b/lang/qt/src/VerifyDetachedJob
new file mode 100644
index 0000000..445fe27
--- /dev/null
+++ b/lang/qt/src/VerifyDetachedJob
@@ -0,0 +1 @@
+#include "qgpgme/verifydetachedjob.h"
diff --git a/lang/qt/src/VerifyOpaqueJob b/lang/qt/src/VerifyOpaqueJob
new file mode 100644
index 0000000..5292a70
--- /dev/null
+++ b/lang/qt/src/VerifyOpaqueJob
@@ -0,0 +1 @@
+#include "qgpgme/verifyopaquejob.h"
diff --git a/lang/qt/src/WKSPublishJob b/lang/qt/src/WKSPublishJob
new file mode 100644
index 0000000..747f7c8
--- /dev/null
+++ b/lang/qt/src/WKSPublishJob
@@ -0,0 +1 @@
+#include "qgpgme/wkspublishjob.h"
diff --git a/lang/qt/src/abstractimportjob.h b/lang/qt/src/abstractimportjob.h
new file mode 100644
index 0000000..572f203
--- /dev/null
+++ b/lang/qt/src/abstractimportjob.h
@@ -0,0 +1,64 @@
+/*
+ abstractimportjob.h
+
+ This file is part of qgpgme, the Qt API binding for gpgme
+ Copyright (c) 2009 Klarälvdalens Datakonsult AB
+ Copyright (c) 2016 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.
+*/
+
+#ifndef __KLEO_ABSTRACTIMPORTJOB_H__
+#define __KLEO_ABSTRACTIMPORTJOB_H__
+
+#include "job.h"
+
+#include "qgpgme_export.h"
+
+namespace GpgME
+{
+class Error;
+class ImportResult;
+}
+
+namespace QGpgME
+{
+
+class QGPGME_EXPORT AbstractImportJob : public Job
+{
+ Q_OBJECT
+protected:
+ explicit AbstractImportJob(QObject *parent);
+public:
+ ~AbstractImportJob();
+
+Q_SIGNALS:
+ void result(const GpgME::ImportResult &result, const QString &auditLogAsHtml = QString(), const GpgME::Error &auditLogError = GpgME::Error());
+};
+
+}
+
+#endif // __KLEO_IMPORTJOB_H__
diff --git a/lang/qt/src/adduseridjob.h b/lang/qt/src/adduseridjob.h
new file mode 100644
index 0000000..1b5676f
--- /dev/null
+++ b/lang/qt/src/adduseridjob.h
@@ -0,0 +1,84 @@
+/*
+ adduseridjob.h
+
+ This file is part of qgpgme, the Qt API binding for gpgme
+ Copyright (c) 2008 Klarälvdalens Datakonsult AB
+ Copyright (c) 2016 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.
+*/
+
+#ifndef __KLEO_ADDUSERIDJOB_H__
+#define __KLEO_ADDUSERIDJOB_H__
+
+#include "job.h"
+
+#include <QtCore/QString>
+
+namespace GpgME
+{
+class Error;
+class Key;
+}
+
+namespace QGpgME
+{
+
+/**
+ @short An abstract base class to asynchronously add UIDs to OpenPGP keys
+
+ To use a AddUserIDJob, first obtain an instance from the
+ CryptoBackend implementation, connect the progress() and result()
+ signals to suitable slots and then start the job with a call
+ to start(). This call might fail, in which case the AddUserIDJob
+ instance will have scheduled it's own destruction with a call to
+ QObject::deleteLater().
+
+ After result() is emitted, the AddUserIDJob will schedule it's own
+ destruction by calling QObject::deleteLater().
+*/
+class QGPGME_EXPORT AddUserIDJob : public Job
+{
+ Q_OBJECT
+protected:
+ explicit AddUserIDJob(QObject *parent);
+public:
+ ~AddUserIDJob();
+
+ /**
+ Starts the operation. \a key is the key to add the UID to. \a
+ name, \a email and \a comment are the components of the user id.
+ */
+ virtual GpgME::Error start(const GpgME::Key &key, const QString &name,
+ const QString &email, const QString &comment = QString()) = 0;
+
+Q_SIGNALS:
+ void result(const GpgME::Error &result, const QString &auditLogAsHtml = QString(), const GpgME::Error &auditLogError = GpgME::Error());
+};
+
+}
+
+#endif // __KLEO_ADDUSERIDJOB_H__
diff --git a/lang/qt/src/changeexpiryjob.h b/lang/qt/src/changeexpiryjob.h
new file mode 100644
index 0000000..7902cb8
--- /dev/null
+++ b/lang/qt/src/changeexpiryjob.h
@@ -0,0 +1,84 @@
+/*
+ changeexpiryjob.h
+
+ This file is part of qgpgme, the Qt API binding for gpgme
+ Copyright (c) 2008 Klarälvdalens Datakonsult AB
+ Copyright (c) 2016 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.
+*/
+
+#ifndef __KLEO_CHANGEEXPIRYJOB_H__
+#define __KLEO_CHANGEEXPIRYJOB_H__
+
+#include "job.h"
+
+namespace GpgME
+{
+class Error;
+class Key;
+}
+
+class QDateTime;
+
+namespace QGpgME
+{
+
+/**
+ @short An abstract base class to change expiry asynchronously
+
+ To use a ChangeExpiryJob, first obtain an instance from the
+ CryptoBackend implementation, connect the progress() and result()
+ signals to suitable slots and then start the job with a call
+ to start(). This call might fail, in which case the ChangeExpiryJob
+ instance will have scheduled it's own destruction with a call to
+ QObject::deleteLater().
+
+ After result() is emitted, the ChangeExpiryJob will schedule it's own
+ destruction by calling QObject::deleteLater().
+*/
+class QGPGME_EXPORT ChangeExpiryJob : public Job
+{
+ Q_OBJECT
+protected:
+ explicit ChangeExpiryJob(QObject *parent);
+public:
+ ~ChangeExpiryJob();
+
+ /**
+ 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
+ is not valid, \a key is set to never expire.
+ */
+ virtual GpgME::Error start(const GpgME::Key &key, const QDateTime &expiry) = 0;
+
+Q_SIGNALS:
+ void result(const GpgME::Error &result, const QString &auditLogAsHtml = QString(), const GpgME::Error &auditLogError = GpgME::Error());
+};
+
+}
+
+#endif // __KLEO_CHANGEEXPIRYJOB_H__
diff --git a/lang/qt/src/changeownertrustjob.h b/lang/qt/src/changeownertrustjob.h
new file mode 100644
index 0000000..75c1163
--- /dev/null
+++ b/lang/qt/src/changeownertrustjob.h
@@ -0,0 +1,81 @@
+/*
+ changeownertrustjob.h
+
+ This file is part of qgpgme, the Qt API binding for gpgme
+ Copyright (c) 2008 Klarälvdalens Datakonsult AB
+ Copyright (c) 2016 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.
+*/
+
+#ifndef __KLEO_CHANGEOWNERTRUST_H__
+#define __KLEO_CHANGEOWNERTRUST_H__
+
+#include "job.h"
+
+#ifdef BUILDING_QGPGME
+# include "key.h"
+#else
+# include <gpgme++/key.h>
+#endif
+
+namespace QGpgME
+{
+
+/**
+ @short An abstract base class to change owner trust asynchronously
+
+ To use a ChangeOwnerTrustJob, first obtain an instance from the
+ CryptoBackend implementation, connect the progress() and result()
+ signals to suitable slots and then start the job with a call
+ to start(). This call might fail, in which case the ChangeOwnerTrustJob
+ instance will have scheduled it's own destruction with a call to
+ QObject::deleteLater().
+
+ After result() is emitted, the ChangeOwnerTrustJob will schedule it's own
+ destruction by calling QObject::deleteLater().
+*/
+class QGPGME_EXPORT ChangeOwnerTrustJob : public Job
+{
+ Q_OBJECT
+protected:
+ explicit ChangeOwnerTrustJob(QObject *parent);
+public:
+ ~ChangeOwnerTrustJob();
+
+ /**
+ Starts the change-owner trust operation. \a key is the key to change
+ the owner trust of . \a trust is the new trust level.
+ */
+ virtual GpgME::Error start(const GpgME::Key &key, GpgME::Key::OwnerTrust trust) = 0;
+
+Q_SIGNALS:
+ void result(const GpgME::Error &result, const QString &auditLogAsHtml = QString(), const GpgME::Error &auditLogError = GpgME::Error());
+};
+
+}
+
+#endif // __KLEO_CHANGEOWNERTRUSTJOB_H__
diff --git a/lang/qt/src/changepasswdjob.h b/lang/qt/src/changepasswdjob.h
new file mode 100644
index 0000000..7290898
--- /dev/null
+++ b/lang/qt/src/changepasswdjob.h
@@ -0,0 +1,82 @@
+/*
+ changepasswdjob.h
+
+ This file is part of qgpgme, the Qt API binding for gpgme
+ Copyright (c) 2010 Klarälvdalens Datakonsult AB
+ Copyright (c) 2016 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.
+*/
+
+#ifndef __KLEO_CHANGEPASSWDJOB_H__
+#define __KLEO_CHANGEPASSWDJOB_H__
+
+#include "job.h"
+
+namespace GpgME
+{
+class Error;
+class Key;
+}
+
+namespace QGpgME
+{
+
+/**
+ @short An abstract base class to change a key's passphrase asynchronously
+
+ To use a ChangePasswdJob, first obtain an instance from the
+ CryptoBackend implementation, connect the progress() and result()
+ signals to suitable slots and then start the job with a call
+ to start(). This call might fail, in which case the ChangePasswdJob
+ instance will have scheduled it's own destruction with a call to
+ QObject::deleteLater().
+
+ After result() is emitted, the ChangePasswdJob will schedule it's own
+ destruction by calling QObject::deleteLater().
+*/
+class QGPGME_EXPORT ChangePasswdJob : public Job
+{
+ Q_OBJECT
+protected:
+ explicit ChangePasswdJob(QObject *parent);
+public:
+ ~ChangePasswdJob();
+
+ /**
+ Starts the passphrase-change operation. \a key is the key to
+ change the passphrase of. The passphrase is queried by the
+ backend directly, you cannot give it to the job beforehand.
+ */
+ virtual GpgME::Error start(const GpgME::Key &key) = 0;
+
+Q_SIGNALS:
+ void result(const GpgME::Error &result, const QString &auditLogAsHtml = QString(), const GpgME::Error &auditLogError = GpgME::Error());
+};
+
+}
+
+#endif // __KLEO_CHANGEPASSWDJOB_H__
diff --git a/lang/qt/src/cryptoconfig.h b/lang/qt/src/cryptoconfig.h
new file mode 100644
index 0000000..c3f0c7e
--- /dev/null
+++ b/lang/qt/src/cryptoconfig.h
@@ -0,0 +1,400 @@
+/*
+ cryptoconfig.h
+
+ This file is part of qgpgme, the Qt API binding for gpgme
+ Copyright (c) 2004 Klarälvdalens Datakonsult AB
+ Copyright (c) 2016 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.
+*/
+
+#ifndef CRYPTOCONFIG_H
+#define CRYPTOCONFIG_H
+
+#include "qgpgme_export.h"
+#ifdef __cplusplus
+/* we read this file from a C compiler, and are only interested in the
+ * enums... */
+
+#include <QUrl>
+
+#include <vector>
+
+/* Start reading this file from the bottom up :) */
+
+namespace QGpgME
+{
+
+/**
+ * Description of a single option
+ */
+class QGPGME_EXPORT CryptoConfigEntry
+{
+
+public:
+#endif /* __cplusplus */
+ /**
+ @li basic This option should always be offered to the user.
+ @li advanced This option may be offered to advanced users.
+ @li expert This option should only be offered to expert users.
+ */
+ enum Level { Level_Basic = 0,
+ Level_Advanced = 1,
+ Level_Expert = 2
+ };
+
+ /**
+ Type of the argument
+ @li ArgType_None The option is set or not set, but no argument.
+ @li ArgType_String An unformatted string.
+ @li ArgType_Int A signed integer number.
+ @li ArgType_UInt An unsigned integer number.
+ @li ArgType_Path A string that describes the pathname of a file.
+ The file does not necessarily need to exist.
+ Separated from string so that e.g. a FileDialog can be used.
+ @li ArgType_DirPath A string that describes the pathname of a directory.
+ The directory does not necessarily need to exist.
+ Separated from path so that e.g. a FileDialog can be used which only
+ allows directories to be selected.
+ @li ArgType_LDAPURL A LDAP URL
+ Separated from URL so that a more specific widget can be shown, hiding the url syntax
+ */
+ enum ArgType { ArgType_None = 0,
+ ArgType_String = 1,
+ ArgType_Int = 2,
+ ArgType_UInt = 3,
+ ArgType_Path = 4,
+ /* Nr. 5 was URL historically. */
+ ArgType_LDAPURL = 6,
+ ArgType_DirPath = 7,
+
+ NumArgType
+ };
+
+#ifdef __cplusplus
+ virtual ~CryptoConfigEntry() {}
+
+ /**
+ * Return the internal name of this entry
+ */
+ virtual QString name() const = 0;
+
+ /**
+ * @return user-visible description of this entry
+ */
+ virtual QString description() const = 0;
+
+ /**
+ * @return "component/group/name"
+ */
+ virtual QString path() const = 0;
+
+ /**
+ * @return true if the argument is optional
+ */
+ virtual bool isOptional() const = 0;
+
+ /**
+ * @return true if the entry is readonly
+ */
+ virtual bool isReadOnly() const = 0;
+
+ /**
+ * @return true if the argument can be given multiple times
+ */
+ virtual bool isList() const = 0;
+
+ /**
+ * @return true if the argument can be changed at runtime
+ */
+ virtual bool isRuntime() const = 0;
+
+ /**
+ * User level
+ */
+ virtual Level level() const = 0;
+
+ /**
+ * Argument type
+ */
+ virtual ArgType argType() const = 0;
+
+ /**
+ * Return true if the option is set, i.e. different from default
+ */
+ virtual bool isSet() const = 0;
+
+ /**
+ * Return value as a bool (only allowed for ArgType_None)
+ */
+ virtual bool boolValue() const = 0;
+
+ /**
+ * Return value as a string (available for all argtypes)
+ * The returned string can be empty (explicitly set to empty) or null (not set).
+ */
+ virtual QString stringValue() const = 0;
+
+ /**
+ * Return value as a signed int
+ */
+ virtual int intValue() const = 0;
+
+ /**
+ * Return value as an unsigned int
+ */
+ virtual unsigned int uintValue() const = 0;
+
+ /**
+ * Return value as a URL (only meaningful for Path and URL argtypes)
+ */
+ virtual QUrl urlValue() const = 0;
+
+ /**
+ * Return number of times the option is set (only valid for ArgType_None, if isList())
+ */
+ virtual unsigned int numberOfTimesSet() const = 0;
+
+ /**
+ * Return value as a list of signed ints
+ */
+ virtual std::vector<int> intValueList() const = 0;
+
+ /**
+ * Return value as a list of unsigned ints
+ */
+ virtual std::vector<unsigned int> uintValueList() const = 0;
+
+ /**
+ * Return value as a list of URLs (only meaningful for Path and URL argtypes, if isList())
+ */
+ virtual QList<QUrl> urlValueList() const = 0;
+
+ /**
+ * Reset an option to its default value
+ */
+ virtual void resetToDefault() = 0;
+
+ /**
+ * Define whether the option is set or not (only allowed for ArgType_None)
+ * #### TODO: and for options with optional args
+ */
+ virtual void setBoolValue(bool) = 0;
+
+ /**
+ * Set string value (allowed for all argtypes)
+ */
+ virtual void setStringValue(const QString &) = 0;
+
+ /**
+ * Set a new signed int value
+ */
+ virtual void setIntValue(int) = 0;
+
+ /**
+ * Set a new unsigned int value
+ */
+ virtual void setUIntValue(unsigned int) = 0;
+
+ /**
+ * Set value as a URL (only meaningful for Path (if local) and URL argtypes)
+ */
+ virtual void setURLValue(const QUrl &) = 0;
+
+ /**
+ * Set the number of times the option is set (only valid for ArgType_None, if isList())
+ */
+ virtual void setNumberOfTimesSet(unsigned int) = 0;
+
+ /**
+ * Set a new list of signed int values
+ */
+ virtual void setIntValueList(const std::vector<int> &) = 0;
+
+ /**
+ * Set a new list of unsigned int values
+ */
+ virtual void setUIntValueList(const std::vector<unsigned int> &) = 0;
+
+ /**
+ * Set value as a URL list (only meaningful for Path (if all URLs are local) and URL argtypes, if isList())
+ */
+ virtual void setURLValueList(const QList<QUrl> &) = 0;
+
+ /**
+ * @return true if the value was changed
+ */
+ virtual bool isDirty() const = 0;
+};
+
+/**
+ * Group containing a set of config options
+ */
+class QGPGME_EXPORT CryptoConfigGroup
+{
+
+public:
+ virtual ~CryptoConfigGroup() {}
+
+ /**
+ * Return the internal name of this group
+ */
+ virtual QString name() const = 0;
+
+ /**
+ * Return the name of the icon for this group
+ */
+ virtual QString iconName() const = 0;
+
+ /**
+ * @return user-visible description of this group
+ */
+ virtual QString description() const = 0;
+
+ /**
+ * @return "component/group"
+ */
+ virtual QString path() const = 0;
+
+ /**
+ * User level
+ */
+ virtual CryptoConfigEntry::Level level() const = 0;
+
+ /**
+ * Returns the list of entries that are known by this group.
+ *
+ * @return list of group entry names.
+ **/
+ virtual QStringList entryList() const = 0;
+
+ /**
+ * @return the configuration object for a given entry in this group
+ * The object is owned by CryptoConfigGroup, don't delete it.
+ * Groups cannot be nested, so all entries returned here are pure entries, no groups.
+ */
+ virtual CryptoConfigEntry *entry(const QString &name) const = 0;
+};
+
+/**
+ * Crypto config for one component (e.g. gpg-agent, dirmngr etc.)
+ */
+class QGPGME_EXPORT CryptoConfigComponent
+{
+
+public:
+ virtual ~CryptoConfigComponent() {}
+
+ /**
+ * Return the internal name of this component
+ */
+ virtual QString name() const = 0;
+
+ /**
+ * Return the name of the icon for this component
+ */
+ virtual QString iconName() const = 0;
+
+ /**
+ * Return user-visible description of this component
+ */
+ virtual QString description() const = 0;
+
+ /**
+ * Returns the list of groups that are known about.
+ *
+ * @return list of group names. One of them can be "<nogroup>", which is the group where all
+ * "toplevel" options (belonging to no group) are.
+ */
+ virtual QStringList groupList() const = 0;
+
+ /**
+ * @return the configuration object for a given group
+ * The object is owned by CryptoConfigComponent, don't delete it.
+ */
+ virtual CryptoConfigGroup *group(const QString &name) const = 0;
+
+};
+
+/**
+ * Main interface to crypto configuration.
+ */
+class QGPGME_EXPORT CryptoConfig
+{
+
+public:
+ virtual ~CryptoConfig() {}
+
+ /**
+ * Returns the list of known components (e.g. "gpg-agent", "dirmngr" etc.).
+ * Use @ref component() to retrieve more information about each one.
+ * @return list of component names.
+ **/
+ virtual QStringList componentList() const = 0;
+
+ /**
+ * @return the configuration object for a given component
+ * The object is owned by CryptoConfig, don't delete it.
+ */
+ virtual CryptoConfigComponent *component(const QString &name) const = 0;
+
+ /**
+ * Convenience method to get hold of a single configuration entry when
+ * its component, group and name are known. This can be used to read
+ * the value and/or to set a value to it.
+ *
+ * @return the configuration object for a single configuration entry, 0 if not found.
+ * The object is owned by CryptoConfig, don't delete it.
+ */
+ CryptoConfigEntry *entry(const QString &componentName, const QString &groupName, const QString &entryName) const
+ {
+ const QGpgME::CryptoConfigComponent *comp = component(componentName);
+ const QGpgME::CryptoConfigGroup *group = comp ? comp->group(groupName) : 0;
+ return group ? group->entry(entryName) : 0;
+ }
+
+ /**
+ * Write back changes
+ *
+ * @param runtime If this option is set, the changes will take effect at run-time, as
+ * far as this is possible. Otherwise, they will take effect at the next
+ * start of the respective backend programs.
+ */
+ virtual void sync(bool runtime) = 0;
+
+ /**
+ * Tells the CryptoConfig to discard any cached information, including
+ * all components, groups and entries.
+ * Call this to free some memory when you won't be using the object
+ * for some time.
+ * DON'T call this if you're holding pointers to components, groups or entries.
+ */
+ virtual void clear() = 0;
+};
+
+}
+#endif /* __cplusplus */
+#endif /* CRYPTOCONFIG_H */
diff --git a/lang/qt/src/dataprovider.cpp b/lang/qt/src/dataprovider.cpp
new file mode 100644
index 0000000..533b67d
--- /dev/null
+++ b/lang/qt/src/dataprovider.cpp
@@ -0,0 +1,282 @@
+/* dataprovider.cpp
+ Copyright (C) 2004 Klar�vdalens Datakonsult AB
+ Copyright (c) 2016 Intevation GmbH
+
+ This file is part of QGPGME.
+
+ QGPGME is free software; you can redistribute it and/or modify it
+ under the terms of the GNU Library General Public License as published
+ by the Free Software Foundation; either version 2 of the License, or
+ (at your option) any later version.
+
+ 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 Library General Public License for more details.
+
+ You should have received a copy of the GNU Library General Public License
+ along with QGPGME; see the file COPYING.LIB. If not, write to the
+ Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+ Boston, MA 02110-1301, USA. */
+
+// -*- c++ -*-
+
+#include <dataprovider.h>
+
+#include <error.h>
+
+#include <QIODevice>
+#include <QProcess>
+
+#include <cstdio>
+#include <cstring>
+#include <cassert>
+
+using namespace QGpgME;
+using namespace GpgME;
+
+//
+//
+// QByteArrayDataProvider
+//
+//
+
+static bool resizeAndInit(QByteArray &ba, size_t newSize)
+{
+ const size_t oldSize = ba.size();
+ ba.resize(newSize);
+ const bool ok = (newSize == static_cast<size_t>(ba.size()));
+ if (ok) {
+ memset(ba.data() + oldSize, 0, newSize - oldSize);
+ }
+ return ok;
+}
+
+QByteArrayDataProvider::QByteArrayDataProvider()
+ : GpgME::DataProvider(), mOff(0) {}
+
+QByteArrayDataProvider::QByteArrayDataProvider(const QByteArray &initialData)
+ : GpgME::DataProvider(), mArray(initialData), mOff(0) {}
+
+QByteArrayDataProvider::~QByteArrayDataProvider() {}
+
+ssize_t QByteArrayDataProvider::read(void *buffer, size_t bufSize)
+{
+#ifndef NDEBUG
+ //qDebug( "QByteArrayDataProvider::read( %p, %d )", buffer, bufSize );
+#endif
+ if (bufSize == 0) {
+ return 0;
+ }
+ if (!buffer) {
+ Error::setSystemError(GPG_ERR_EINVAL);
+ return -1;
+ }
+ if (mOff >= mArray.size()) {
+ return 0; // EOF
+ }
+ size_t amount = qMin(bufSize, static_cast<size_t>(mArray.size() - mOff));
+ assert(amount > 0);
+ memcpy(buffer, mArray.data() + mOff, amount);
+ mOff += amount;
+ return amount;
+}
+
+ssize_t QByteArrayDataProvider::write(const void *buffer, size_t bufSize)
+{
+#ifndef NDEBUG
+ //qDebug( "QByteArrayDataProvider::write( %p, %lu )", buffer, static_cast<unsigned long>( bufSize ) );
+#endif
+ if (bufSize == 0) {
+ return 0;
+ }
+ if (!buffer) {
+ Error::setSystemError(GPG_ERR_EINVAL);
+ return -1;
+ }
+ if (mOff >= mArray.size()) {
+ resizeAndInit(mArray, mOff + bufSize);
+ }
+ if (mOff >= mArray.size()) {
+ Error::setSystemError(GPG_ERR_EIO);
+ return -1;
+ }
+ assert(bufSize <= static_cast<size_t>(mArray.size()) - mOff);
+ memcpy(mArray.data() + mOff, buffer, bufSize);
+ mOff += bufSize;
+ return bufSize;
+}
+
+off_t QByteArrayDataProvider::seek(off_t offset, int whence)
+{
+#ifndef NDEBUG
+ //qDebug( "QByteArrayDataProvider::seek( %d, %d )", int(offset), whence );
+#endif
+ int newOffset = mOff;
+ switch (whence) {
+ case SEEK_SET:
+ newOffset = offset;
+ break;
+ case SEEK_CUR:
+ newOffset += offset;
+ break;
+ case SEEK_END:
+ newOffset = mArray.size() + offset;
+ break;
+ default:
+ Error::setSystemError(GPG_ERR_EINVAL);
+ return (off_t) - 1;
+ }
+ return mOff = newOffset;
+}
+
+void QByteArrayDataProvider::release()
+{
+#ifndef NDEBUG
+ //qDebug( "QByteArrayDataProvider::release()" );
+#endif
+ mArray = QByteArray();
+}
+
+//
+//
+// QIODeviceDataProvider
+//
+//
+
+QIODeviceDataProvider::QIODeviceDataProvider(const std::shared_ptr<QIODevice> &io)
+ : GpgME::DataProvider(),
+ mIO(io),
+ mErrorOccurred(false),
+ mHaveQProcess(qobject_cast<QProcess *>(io.get()))
+{
+ assert(mIO);
+}
+
+QIODeviceDataProvider::~QIODeviceDataProvider() {}
+
+bool QIODeviceDataProvider::isSupported(Operation op) const
+{
+ const QProcess *const proc = qobject_cast<QProcess *>(mIO.get());
+ bool canRead = true;
+ if (proc) {
+ canRead = proc->readChannel() == QProcess::StandardOutput;
+ }
+
+ switch (op) {
+ case Read: return mIO->isReadable() && canRead;
+ case Write: return mIO->isWritable();
+ case Seek: return !mIO->isSequential();
+ case Release: return true;
+ default: return false;
+ }
+}
+
+static qint64 blocking_read(const std::shared_ptr<QIODevice> &io, char *buffer, qint64 maxSize)
+{
+ while (!io->bytesAvailable()) {
+ if (!io->waitForReadyRead(-1)) {
+ if (const QProcess *const p = qobject_cast<QProcess *>(io.get())) {
+ if (p->error() == QProcess::UnknownError &&
+ p->exitStatus() == QProcess::NormalExit &&
+ p->exitCode() == 0) {
+ return 0;
+ } else {
+ Error::setSystemError(GPG_ERR_EIO);
+ return -1;
+ }
+ } else {
+ return 0; // assume EOF (loses error cases :/ )
+ }
+ }
+ }
+ return io->read(buffer, maxSize);
+}
+
+ssize_t QIODeviceDataProvider::read(void *buffer, size_t bufSize)
+{
+#ifndef NDEBUG
+ //qDebug( "QIODeviceDataProvider::read( %p, %lu )", buffer, bufSize );
+#endif
+ if (bufSize == 0) {
+ return 0;
+ }
+ if (!buffer) {
+ Error::setSystemError(GPG_ERR_EINVAL);
+ return -1;
+ }
+ const qint64 numRead = mHaveQProcess
+ ? blocking_read(mIO, static_cast<char *>(buffer), bufSize)
+ : mIO->read(static_cast<char *>(buffer), bufSize);
+
+ //workaround: some QIODevices (known example: QProcess) might not return 0 (EOF), but immediately -1 when finished. If no
+ //errno is set, gpgme doesn't detect the error and loops forever. So return 0 on the very first -1 in case errno is 0
+
+ ssize_t rc = numRead;
+ if (numRead < 0 && !Error::hasSystemError()) {
+ if (mErrorOccurred) {
+ Error::setSystemError(GPG_ERR_EIO);
+ } else {
+ rc = 0;
+ }
+ }
+ if (numRead < 0) {
+ mErrorOccurred = true;
+ }
+ return rc;
+}
+
+ssize_t QIODeviceDataProvider::write(const void *buffer, size_t bufSize)
+{
+#ifndef NDEBUG
+ //qDebug( "QIODeviceDataProvider::write( %p, %lu )", buffer, static_cast<unsigned long>( bufSize ) );
+#endif
+ if (bufSize == 0) {
+ return 0;
+ }
+ if (!buffer) {
+ Error::setSystemError(GPG_ERR_EINVAL);
+ return -1;
+ }
+
+ return mIO->write(static_cast<const char *>(buffer), bufSize);
+}
+
+off_t QIODeviceDataProvider::seek(off_t offset, int whence)
+{
+#ifndef NDEBUG
+ //qDebug( "QIODeviceDataProvider::seek( %d, %d )", int(offset), whence );
+#endif
+ if (mIO->isSequential()) {
+ Error::setSystemError(GPG_ERR_ESPIPE);
+ return (off_t) - 1;
+ }
+ qint64 newOffset = mIO->pos();
+ switch (whence) {
+ case SEEK_SET:
+ newOffset = offset;
+ break;
+ case SEEK_CUR:
+ newOffset += offset;
+ break;
+ case SEEK_END:
+ newOffset = mIO->size() + offset;
+ break;
+ default:
+ Error::setSystemError(GPG_ERR_EINVAL);
+ return (off_t) - 1;
+ }
+ if (!mIO->seek(newOffset)) {
+ Error::setSystemError(GPG_ERR_EINVAL);
+ return (off_t) - 1;
+ }
+ return newOffset;
+}
+
+void QIODeviceDataProvider::release()
+{
+#ifndef NDEBUG
+ //qDebug( "QIODeviceDataProvider::release()" );
+#endif
+ mIO->close();
+}
diff --git a/lang/qt/src/dataprovider.h b/lang/qt/src/dataprovider.h
new file mode 100644
index 0000000..337f264
--- /dev/null
+++ b/lang/qt/src/dataprovider.h
@@ -0,0 +1,95 @@
+/* dataprovider.h
+ Copyright (C) 2004 Klarälvdalens Datakonsult AB
+ Copyright (c) 2016 Intevation GmbH
+
+ This file is part of QGPGME.
+
+ QGPGME is free software; you can redistribute it and/or modify it
+ under the terms of the GNU Library General Public License as published
+ by the Free Software Foundation; either version 2 of the License, or
+ (at your option) any later version.
+
+ 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 Library General Public License for more details.
+
+ You should have received a copy of the GNU Library General Public License
+ along with QGPGME; see the file COPYING.LIB. If not, write to the
+ Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+ Boston, MA 02110-1301, USA. */
+
+// -*- c++ -*-
+#ifndef __QGPGME_DATAPROVIDER_H__
+#define __QGPGME_DATAPROVIDER_H__
+
+#include "qgpgme_export.h"
+#include <interfaces/dataprovider.h>
+#include <memory>
+
+#include <QtCore/QByteArray>
+
+
+class QIODevice;
+
+namespace QGpgME
+{
+
+class QGPGME_EXPORT QByteArrayDataProvider : public GpgME::DataProvider
+{
+public:
+ QByteArrayDataProvider();
+ explicit QByteArrayDataProvider(const QByteArray &initialData);
+ ~QByteArrayDataProvider();
+
+ const QByteArray &data() const
+ {
+ return mArray;
+ }
+
+private:
+ // these shall only be accessed through the dataprovider
+ // interface, where they're public:
+ bool isSupported(Operation) const
+ {
+ return true;
+ }
+ ssize_t read(void *buffer, size_t bufSize);
+ ssize_t write(const void *buffer, size_t bufSize);
+ off_t seek(off_t offset, int whence);
+ void release();
+
+private:
+ QByteArray mArray;
+ off_t mOff;
+};
+
+class QGPGME_EXPORT QIODeviceDataProvider : public GpgME::DataProvider
+{
+public:
+ explicit QIODeviceDataProvider(const std::shared_ptr<QIODevice> &initialData);
+ ~QIODeviceDataProvider();
+
+ const std::shared_ptr<QIODevice> &ioDevice() const
+ {
+ return mIO;
+ }
+
+private:
+ // these shall only be accessed through the dataprovider
+ // interface, where they're public:
+ bool isSupported(Operation) const;
+ ssize_t read(void *buffer, size_t bufSize);
+ ssize_t write(const void *buffer, size_t bufSize);
+ off_t seek(off_t offset, int whence);
+ void release();
+
+private:
+ const std::shared_ptr<QIODevice> mIO;
+ bool mErrorOccurred : 1;
+ bool mHaveQProcess : 1;
+};
+
+} // namespace QGpgME
+
+#endif
diff --git a/lang/qt/src/decryptjob.h b/lang/qt/src/decryptjob.h
new file mode 100644
index 0000000..c4fc86f
--- /dev/null
+++ b/lang/qt/src/decryptjob.h
@@ -0,0 +1,100 @@
+/*
+ decryptjob.h
+
+ This file is part of qgpgme, the Qt API binding for gpgme
+ Copyright (c) 2004, 2007 Klarälvdalens Datakonsult AB
+ Copyright (c) 2016 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.
+*/
+
+#ifndef __KLEO_DECRYPTJOB_H__
+#define __KLEO_DECRYPTJOB_H__
+
+#include "job.h"
+
+#include <memory>
+
+class QByteArray;
+class QIODevice;
+
+namespace GpgME
+{
+class Error;
+class DecryptionResult;
+}
+
+namespace QGpgME
+{
+
+/**
+ @short An abstract base class for asynchronous decrypters
+
+ To use a DecryptJob, first obtain an instance from the
+ CryptoBackend implementation, connect the progress() and result()
+ signals to suitable slots and then start the decryption with a
+ call to start(). This call might fail, in which case the
+ DecryptJob instance will have scheduled it's own destruction with
+ a call to QObject::deleteLater().
+
+ After result() is emitted, the DecryptJob will schedule it's own
+ destruction by calling QObject::deleteLater().
+*/
+class QGPGME_EXPORT DecryptJob : public Job
+{
+ Q_OBJECT
+protected:
+ explicit DecryptJob(QObject *parent);
+public:
+ ~DecryptJob();
+
+ /**
+ Starts the decryption operation. \a cipherText is the data to
+ decrypt.
+ */
+ virtual QGPGME_DEPRECATED_EXPORT GpgME::Error start(const QByteArray &cipherText) = 0;
+
+ /*!
+ \overload
+
+ If \a plainText is non-null, the plaintext is written
+ there. Otherwise, it will be delivered in the second argument
+ of result().
+
+ \throws GpgME::Exception if starting fails
+ */
+ virtual void start(const std::shared_ptr<QIODevice> &cipherText, const std::shared_ptr<QIODevice> &plainText = std::shared_ptr<QIODevice>()) = 0;
+
+ virtual GpgME::DecryptionResult exec(const QByteArray &cipherText,
+ QByteArray &plainText) = 0;
+
+Q_SIGNALS:
+ void result(const GpgME::DecryptionResult &result, const QByteArray &plainText, const QString &auditLogAsHtml = QString(), const GpgME::Error &auditLogError = GpgME::Error());
+};
+
+}
+
+#endif // __KLEO_DECRYPTJOB_H__
diff --git a/lang/qt/src/decryptverifyjob.h b/lang/qt/src/decryptverifyjob.h
new file mode 100644
index 0000000..97af008
--- /dev/null
+++ b/lang/qt/src/decryptverifyjob.h
@@ -0,0 +1,105 @@
+/*
+ decryptverifyjob.h
+
+ This file is part of qgpgme, the Qt API binding for gpgme
+ Copyright (c) 2004, 2007 Klarälvdalens Datakonsult AB
+ Copyright (c) 2016 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.
+*/
+
+#ifndef __KLEO_DECRYPTVERIFYJOB_H__
+#define __KLEO_DECRYPTVERIFYJOB_H__
+
+#include "job.h"
+
+#include <memory>
+
+class QByteArray;
+class QIODevice;
+
+namespace GpgME
+{
+class Error;
+class DecryptionResult;
+class VerificationResult;
+}
+
+namespace QGpgME
+{
+
+/**
+ @short An abstract base class for asynchronous combined decrypters and verifiers
+
+ To use a DecryptVerifyJob, first obtain an instance from the
+ CryptoBackend implementation, connect the progress() and result()
+ signals to suitable slots and then start the operation with a
+ call to start(). This call might fail, in which case the
+ DecryptVerifyJob instance will have scheduled it's own destruction with
+ a call to QObject::deleteLater().
+
+ After result() is emitted, the DecryptVerifyJob will schedule it's own
+ destruction by calling QObject::deleteLater().
+*/
+class QGPGME_EXPORT DecryptVerifyJob : public Job
+{
+ Q_OBJECT
+protected:
+ explicit DecryptVerifyJob(QObject *parent);
+public:
+ ~DecryptVerifyJob();
+
+ /**
+ Starts the combined decryption and verification operation.
+ \a cipherText is the data to decrypt and later verify.
+ */
+ virtual QGPGME_DEPRECATED_EXPORT GpgME::Error start(const QByteArray &cipherText) = 0;
+
+ /*!
+ \overload
+
+ If \a plainText is non-null, the plaintext is written
+ there. Otherwise, it will be delivered in the third argument
+ of result().
+
+ \throws GpgME::Exception if starting fails
+ */
+ virtual void start(const std::shared_ptr<QIODevice> &cipherText, const std::shared_ptr<QIODevice> &plainText = std::shared_ptr<QIODevice>()) = 0;
+
+ /** Synchronous equivalent of start() */
+ virtual std::pair<GpgME::DecryptionResult, GpgME::VerificationResult>
+ exec(const QByteArray &cipherText, QByteArray &plainText) = 0;
+
+Q_SIGNALS:
+ void result(const GpgME::DecryptionResult &decryptionresult,
+ const GpgME::VerificationResult &verificationresult,
+ const QByteArray &plainText, const QString &auditLogAsHtml = QString(),
+ const GpgME::Error &auditLogError = GpgME::Error());
+};
+
+}
+
+#endif // __KLEO_DECRYPTVERIFYJOB_H__
diff --git a/lang/qt/src/defaultkeygenerationjob.cpp b/lang/qt/src/defaultkeygenerationjob.cpp
new file mode 100644
index 0000000..8257a72
--- /dev/null
+++ b/lang/qt/src/defaultkeygenerationjob.cpp
@@ -0,0 +1,125 @@
+/* defaultkeygenerationjob.cpp
+
+ Copyright (c) 2016 Klarälvdalens Datakonsult AB
+
+ 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 "defaultkeygenerationjob.h"
+#include "protocol.h"
+#include "keygenerationjob.h"
+
+#include <QPointer>
+#include <QEvent>
+
+using namespace QGpgME;
+
+namespace QGpgME {
+
+class DefaultKeyGenerationJob::Private
+{
+public:
+ Private()
+ {}
+
+ ~Private()
+ {
+ if (job) {
+ job->deleteLater();
+ }
+ }
+
+ QPointer<KeyGenerationJob> job;
+};
+}
+
+
+DefaultKeyGenerationJob::DefaultKeyGenerationJob(QObject* parent)
+ : Job(parent)
+ , d(new DefaultKeyGenerationJob::Private())
+{
+}
+
+DefaultKeyGenerationJob::~DefaultKeyGenerationJob()
+{
+ delete d;
+}
+
+QString DefaultKeyGenerationJob::auditLogAsHtml() const
+{
+ return d->job ? d->job->auditLogAsHtml() : QString();
+}
+
+GpgME::Error DefaultKeyGenerationJob::auditLogError() const
+{
+ return d->job ? d->job->auditLogError() : GpgME::Error();
+}
+
+void DefaultKeyGenerationJob::slotCancel()
+{
+ if (d->job) {
+ d->job->slotCancel();
+ }
+}
+
+GpgME::Error DefaultKeyGenerationJob::start(const QString &email, const QString &name)
+{
+ const QString args = QStringLiteral("<GnupgKeyParms format=\"internal\">\n"
+ "%ask-passphrase\n"
+ "key-type: RSA\n"
+ "key-length: 2048\n"
+ "key-usage: sign\n"
+ "subkey-type: RSA\n"
+ "subkey-length: 2048\n"
+ "subkey-usage: encrypt\n"
+ "name-email: %1\n"
+ "name-real: %2\n"
+ "</GnupgKeyParms>").arg(email, name);
+
+ d->job = openpgp()->keyGenerationJob();
+ d->job->installEventFilter(this);
+ connect(d->job, &KeyGenerationJob::result,
+ this, &DefaultKeyGenerationJob::result);
+ connect(d->job, &KeyGenerationJob::done,
+ this, &DefaultKeyGenerationJob::done);
+ connect(d->job, &KeyGenerationJob::done,
+ this, &QObject::deleteLater);
+ return d->job->start(args);
+}
+
+bool DefaultKeyGenerationJob::eventFilter(QObject *watched, QEvent *event)
+{
+ // Intercept the KeyGenerationJob's deferred delete event. We want the job
+ // to live at least as long as we do so we can delegate calls to it. We will
+ // delete the job manually afterwards.
+ if (watched == d->job && event->type() == QEvent::DeferredDelete) {
+ return true;
+ }
+
+ return Job::eventFilter(watched, event);
+}
+
+#include "defaultkeygenerationjob.moc"
diff --git a/lang/qt/src/defaultkeygenerationjob.h b/lang/qt/src/defaultkeygenerationjob.h
new file mode 100644
index 0000000..5b7334c
--- /dev/null
+++ b/lang/qt/src/defaultkeygenerationjob.h
@@ -0,0 +1,76 @@
+/* defaultkeygenerationjob.h
+
+ Copyright (c) 2016 Klarälvdalens Datakonsult AB
+
+ 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_DEFAULTKEYGENERATION_H
+#define QGPGME_DEFAULTKEYGENERATION_H
+
+#include "job.h"
+
+#include "qgpgme_export.h"
+
+namespace GpgME {
+class KeyGenerationResult;
+}
+
+namespace QGpgME{
+
+/**
+ * Generates a PGP RSA/2048 bit key pair for given name and email address.
+ */
+class QGPGME_EXPORT DefaultKeyGenerationJob : public Job
+{
+ Q_OBJECT
+public:
+ explicit DefaultKeyGenerationJob(QObject *parent = Q_NULLPTR);
+ ~DefaultKeyGenerationJob();
+
+ GpgME::Error start(const QString &email, const QString &name);
+
+ QString auditLogAsHtml() const Q_DECL_OVERRIDE;
+ GpgME::Error auditLogError() const Q_DECL_OVERRIDE;
+
+
+public Q_SLOTS:
+ void slotCancel() Q_DECL_OVERRIDE;
+
+Q_SIGNALS:
+ void result(const GpgME::KeyGenerationResult &result, const QByteArray &pubkeyData,
+ const QString &auditLogAsHtml, const GpgME::Error &auditLogError);
+
+protected:
+ bool eventFilter(QObject *watched, QEvent *event) Q_DECL_OVERRIDE;
+
+private:
+ class Private;
+ Private * const d;
+};
+
+}
+
+#endif
diff --git a/lang/qt/src/deletejob.h b/lang/qt/src/deletejob.h
new file mode 100644
index 0000000..f8479b1
--- /dev/null
+++ b/lang/qt/src/deletejob.h
@@ -0,0 +1,83 @@
+/*
+ deletejob.h
+
+ This file is part of qgpgme, the Qt API binding for gpgme
+ Copyright (c) 2004 Klarälvdalens Datakonsult AB
+ Copyright (c) 2016 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.
+*/
+
+#ifndef __KLEO_DELETEJOB_H__
+#define __KLEO_DELETEJOB_H__
+
+#include "qgpgme_export.h"
+#include "job.h"
+
+namespace GpgME
+{
+class Error;
+class Key;
+}
+
+namespace QGpgME
+{
+
+/**
+ @short An abstract base class for asynchronous deleters
+
+ To use a DeleteJob, first obtain an instance from the
+ CryptoBackend implementation, connect the progress() and result()
+ signals to suitable slots and then start the delete with a call
+ to start(). This call might fail, in which case the DeleteJob
+ instance will have scheduled it's own destruction with a call to
+ QObject::deleteLater().
+
+ After result() is emitted, the DeleteJob will schedule it's own
+ destruction by calling QObject::deleteLater().
+*/
+class QGPGME_EXPORT DeleteJob : public Job
+{
+ Q_OBJECT
+protected:
+ explicit DeleteJob(QObject *parent);
+public:
+ ~DeleteJob();
+
+ /**
+ Starts the delete operation. \a key represents the key to
+ delete, \a allowSecretKeyDeletion specifies if a key may also
+ be deleted if the secret key part is available, too.
+ */
+ virtual GpgME::Error start(const GpgME::Key &key, bool allowSecretKeyDeletion = false) = 0;
+
+Q_SIGNALS:
+ void result(const GpgME::Error &result, const QString &auditLogAsHtml = QString(), const GpgME::Error &auditLogError = GpgME::Error());
+};
+
+}
+
+#endif // __KLEO_DELETEJOB_H__
diff --git a/lang/qt/src/downloadjob.h b/lang/qt/src/downloadjob.h
new file mode 100644
index 0000000..09eecf6
--- /dev/null
+++ b/lang/qt/src/downloadjob.h
@@ -0,0 +1,103 @@
+/*
+ downloadjob.h
+
+ This file is part of qgpgme, the Qt API binding for gpgme
+ Copyright (c) 2004 Klarälvdalens Datakonsult AB
+ Copyright (c) 2016 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.
+*/
+
+#ifndef __KLEO_DOWNLOADJOB_H__
+#define __KLEO_DOWNLOADJOB_H__
+
+#include "job.h"
+
+#include <QtCore/QByteArray>
+
+#include <memory>
+
+namespace GpgME
+{
+class Error;
+}
+
+class QStringList;
+class QIODevice;
+class QByteArray;
+
+namespace QGpgME
+{
+
+/**
+ @short An abstract base class for asynchronous downloaders
+
+ To use a DownloadJob, first obtain an instance from the
+ CryptoBackend implementation, connect the progress() and result()
+ signals to suitable slots and then start the download with a call
+ to start(). This call might fail, in which case the DownloadJob
+ instance will have scheduled it's own destruction with a call to
+ QObject::deleteLater().
+
+ After result() is emitted, the DownloadJob will schedule it's own
+ destruction by calling QObject::deleteLater().
+*/
+class QGPGME_EXPORT DownloadJob : public Job
+{
+ Q_OBJECT
+protected:
+ explicit DownloadJob(QObject *parent);
+public:
+ ~DownloadJob();
+
+ /**
+ Starts the download operation. \a fingerprint is the
+ fingerprint of the key to download. If \a fingerprint is empty,
+ contains only whitespace or anything other than a fingerprint,
+ the result is undefined.
+
+ Output is written to \a keyData, if given. Otherwise, it is
+ passed as the second argument of result().
+ */
+ virtual GpgME::Error start(const QByteArray &fingerprint,
+ const std::shared_ptr<QIODevice> &keyData) = 0;
+
+ /**
+ Starts the download operation. \a fingerprints is a list of
+ fingerprints used to specify the list of keys downloaded. Empty
+ patterns are ignored. If \a fingerprints is empty, contains
+ only empty strings or anything other than fingerprints, the
+ result is undefined.
+ */
+ virtual QGPGME_DEPRECATED_EXPORT GpgME::Error start(const QStringList &fingerprints) = 0;
+
+Q_SIGNALS:
+ void result(const GpgME::Error &result, const QByteArray &keyData, const QString &auditLogAsHtml = QString(), const GpgME::Error &auditLogError = GpgME::Error());
+};
+
+}
+
+#endif // __KLEO_DOWNLOADJOB_H__
diff --git a/lang/qt/src/encryptjob.h b/lang/qt/src/encryptjob.h
new file mode 100644
index 0000000..4ff9c82
--- /dev/null
+++ b/lang/qt/src/encryptjob.h
@@ -0,0 +1,136 @@
+/*
+ encryptjob.h
+
+ This file is part of qgpgme, the Qt API binding for gpgme
+ Copyright (c) 2004, 2007 Klarälvdalens Datakonsult AB
+ Copyright (c) 2016 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.
+*/
+
+#ifndef __KLEO_ENCRYPTJOB_H__
+#define __KLEO_ENCRYPTJOB_H__
+
+#include "job.h"
+
+#include <memory>
+#include <vector>
+
+#ifdef BUILDING_QGPGME
+# include "context.h"
+#else
+# include <gpgme++/context.h>
+#endif
+
+class QByteArray;
+class QIODevice;
+
+namespace GpgME
+{
+class Error;
+class Key;
+class EncryptionResult;
+}
+
+namespace QGpgME
+{
+
+/**
+ @short An abstract base class for asynchronous encrypters
+
+ To use a EncryptJob, first obtain an instance from the
+ CryptoBackend implementation, connect the progress() and result()
+ signals to suitable slots and then start the encryption with a
+ call to start(). This call might fail, in which case the
+ EncryptJob instance will have scheduled it's own destruction with
+ a call to QObject::deleteLater().
+
+ After result() is emitted, the EncryptJob will schedule it's own
+ destruction by calling QObject::deleteLater().
+*/
+class QGPGME_EXPORT EncryptJob : public Job
+{
+ Q_OBJECT
+protected:
+ explicit EncryptJob(QObject *parent);
+public:
+ ~EncryptJob();
+
+ /**
+ Starts the encryption operation. \a recipients is the a list of
+ keys to encrypt \a plainText to. Empty (null) keys are
+ ignored. If \a recipients is empty, performs symmetric
+ (passphrase) encryption.
+
+ If \a alwaysTrust is true, validity checking for the keys will
+ not be performed, but full validity assumed for all keys
+ without further checks.
+ */
+ virtual QGPGME_DEPRECATED_EXPORT GpgME::Error start(const std::vector<GpgME::Key> &recipients,
+ const QByteArray &plainText, bool alwaysTrust = false) = 0;
+
+ /*!
+ \overload
+
+ If \a cipherText is non-null, the ciphertext is written
+ there. Otherwise, it will be delivered in the second argument of
+ result().
+
+ \throws GpgME::Exception if starting fails
+ */
+ virtual void start(const std::vector<GpgME::Key> &recipients,
+ const std::shared_ptr<QIODevice> &plainText,
+ const std::shared_ptr<QIODevice> &cipherText = std::shared_ptr<QIODevice>(),
+ bool alwaysTrust = false) = 0;
+
+ virtual GpgME::EncryptionResult exec(const std::vector<GpgME::Key> &recipients,
+ const QByteArray &plainText,
+ bool alwaysTrust, QByteArray &cipherText) = 0;
+ /*!
+ This is a hack to request BASE64 output (instead of whatever
+ comes out normally).
+ */
+ virtual void setOutputIsBase64Encoded(bool) = 0;
+
+ /** Like start but with an additional argument for EncryptionFlags for
+ * more flexibility. */
+ virtual void start(const std::vector<GpgME::Key> &recipients,
+ const std::shared_ptr<QIODevice> &plainText,
+ const std::shared_ptr<QIODevice> &cipherText = std::shared_ptr<QIODevice>(),
+ const GpgME::Context::EncryptionFlags flags = GpgME::Context::None) = 0;
+
+ /** Like exec but with an additional argument for EncryptionFlags for
+ * more flexibility. */
+ virtual GpgME::EncryptionResult exec(const std::vector<GpgME::Key> &recipients,
+ const QByteArray &plainText,
+ const GpgME::Context::EncryptionFlags flags, QByteArray &cipherText) = 0;
+Q_SIGNALS:
+ void result(const GpgME::EncryptionResult &result, const QByteArray &cipherText, const QString &auditLogAsHtml = QString(), const GpgME::Error &auditLogError = GpgME::Error());
+};
+
+}
+
+#endif // __KLEO_ENCRYPTJOB_H__
diff --git a/lang/qt/src/exportjob.h b/lang/qt/src/exportjob.h
new file mode 100644
index 0000000..583d4c0
--- /dev/null
+++ b/lang/qt/src/exportjob.h
@@ -0,0 +1,87 @@
+/*
+ exportjob.h
+
+ This file is part of qgpgme, the Qt API binding for gpgme
+ Copyright (c) 2004 Klarälvdalens Datakonsult AB
+ Copyright (c) 2016 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.
+*/
+
+#ifndef __QGPGME_EXPORTJOB_H__
+#define __QGPGME_EXPORTJOB_H__
+
+#include "qgpgme_export.h"
+#include "job.h"
+
+#include <QtCore/QByteArray>
+
+namespace GpgME
+{
+class Error;
+}
+
+class QStringList;
+
+namespace QGpgME
+{
+
+/**
+ @short An abstract base class for asynchronous exporters
+
+ To use a ExportJob, first obtain an instance from the
+ CryptoBackend implementation, connect the progress() and result()
+ signals to suitable slots and then start the export with a call
+ to start(). This call might fail, in which case the ExportJob
+ instance will have scheduled it's own destruction with a call to
+ QObject::deleteLater().
+
+ After result() is emitted, the ExportJob will schedule it's own
+ destruction by calling QObject::deleteLater().
+*/
+class QGPGME_EXPORT ExportJob : public Job
+{
+ Q_OBJECT
+protected:
+ explicit ExportJob(QObject *parent);
+public:
+ ~ExportJob();
+
+ /**
+ Starts the export operation. \a patterns is a list of patterns
+ used to restrict the list of keys exported. Empty patterns are
+ ignored. If \a patterns is empty or contains only empty
+ strings, all available keys are exported.
+ */
+ virtual GpgME::Error start(const QStringList &patterns) = 0;
+
+Q_SIGNALS:
+ void result(const GpgME::Error &result, const QByteArray &keyData, const QString &auditLogAsHtml = QString(), const GpgME::Error &auditLogError = GpgME::Error());
+};
+
+}
+
+#endif // __QGPGME_EXPORTJOB_H__
diff --git a/lang/qt/src/gpgme_backend_debug.cpp b/lang/qt/src/gpgme_backend_debug.cpp
new file mode 100644
index 0000000..6dfb313
--- /dev/null
+++ b/lang/qt/src/gpgme_backend_debug.cpp
@@ -0,0 +1,10 @@
+// This file is autogenerated by CMake: DO NOT EDIT
+
+#include "gpgme_backend_debug.h"
+
+
+#if QT_VERSION >= QT_VERSION_CHECK(5, 4, 0)
+Q_LOGGING_CATEGORY(GPGPME_BACKEND_LOG, "log_gpgme_backend", QtWarningMsg)
+#else
+Q_LOGGING_CATEGORY(GPGPME_BACKEND_LOG, "log_gpgme_backend")
+#endif
diff --git a/lang/qt/src/gpgme_backend_debug.h b/lang/qt/src/gpgme_backend_debug.h
new file mode 100644
index 0000000..5ac93db
--- /dev/null
+++ b/lang/qt/src/gpgme_backend_debug.h
@@ -0,0 +1,11 @@
+// This file is autogenerated by CMake: DO NOT EDIT
+
+#ifndef GPGPME_BACKEND_LOG_H
+#define GPGPME_BACKEND_LOG_H
+
+#include <QLoggingCategory>
+
+Q_DECLARE_LOGGING_CATEGORY(GPGPME_BACKEND_LOG)
+
+
+#endif
diff --git a/lang/qt/src/hierarchicalkeylistjob.h b/lang/qt/src/hierarchicalkeylistjob.h
new file mode 100644
index 0000000..2ec187d
--- /dev/null
+++ b/lang/qt/src/hierarchicalkeylistjob.h
@@ -0,0 +1,125 @@
+/*
+ hierarchicalkeylistjob.h
+
+ This file is part of qgpgme, the Qt API binding for gpgme
+ Copyright (c) 2004 Klarälvdalens Datakonsult AB
+ Copyright (c) 2016 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.
+*/
+
+#ifndef __KLEO_HIERARCHICALKEYLISTJOB_H__
+#define __KLEO_HIERARCHICALKEYLISTJOB_H__
+
+#include "qgpgme_export.h"
+#include "keylistjob.h"
+#include "cryptobackend.h"
+
+#ifdef BUILDING_QGPGME
+# include "keylistresult.h"
+#else
+#include <gpgme++/keylistresult.h>
+#endif
+
+#include <QPointer>
+
+#include <set>
+
+namespace GpgME
+{
+class Error;
+class Key;
+}
+
+namespace QGpgME
+{
+class KeyListJob;
+}
+
+namespace QGpgME
+{
+
+/**
+ @short A convenience job that additionally fetches all available issuers.
+
+ To use a HierarchicalKeyListJob, pass it a CryptoBackend
+ implementation, connect the progress() and result() signals to
+ suitable slots and then start the keylisting with a call to
+ start(). This call might fail, in which case the
+ HierarchicalKeyListJob instance will have scheduled it's own
+ destruction with a call to QObject::deleteLater().
+
+ After result() is emitted, the HierarchicalKeyListJob will
+ schedule its own destruction by calling QObject::deleteLater().
+*/
+class QGPGME_EXPORT HierarchicalKeyListJob : public KeyListJob
+{
+ Q_OBJECT
+public:
+ explicit HierarchicalKeyListJob(const Protocol *protocol,
+ bool remote = false, bool includeSigs = false,
+ bool validating = false);
+ ~HierarchicalKeyListJob();
+
+ /**
+ Starts the keylist operation. \a patterns is a list of patterns
+ used to restrict the list of keys returned. Empty patterns are
+ ignored. \a patterns must not be empty or contain only empty
+ patterns; use the normal KeyListJob for a full listing.
+
+ The \a secretOnly parameter is ignored by
+ HierarchicalKeyListJob and must be set to false.
+ */
+ GpgME::Error start(const QStringList &patterns, bool secretOnly = false) Q_DECL_OVERRIDE;
+
+ GpgME::KeyListResult exec(const QStringList &patterns, bool secretOnly,
+ std::vector<GpgME::Key> &keys) Q_DECL_OVERRIDE;
+
+private Q_SLOTS:
+ void slotResult(const GpgME::KeyListResult &);
+ void slotNextKey(const GpgME::Key &key);
+ /* from Job */
+ void slotCancel() Q_DECL_OVERRIDE;
+
+private:
+ GpgME::Error startAJob();
+
+private:
+ const Protocol *const mProtocol;
+ const bool mRemote;
+ const bool mIncludeSigs;
+ const bool mValidating;
+ bool mTruncated;
+ std::set<QString> mSentSet; // keys already sent (prevent duplicates even if the backend should return them)
+ std::set<QString> mScheduledSet; // keys already scheduled (by starting a job for them)
+ std::set<QString> mNextSet; // keys to schedule for the next iteraton
+ GpgME::KeyListResult mIntermediateResult;
+ QPointer<KeyListJob> mJob;
+};
+
+}
+
+#endif // __KLEO_HIERARCHICALKEYLISTJOB_H__
diff --git a/lang/qt/src/importfromkeyserverjob.h b/lang/qt/src/importfromkeyserverjob.h
new file mode 100644
index 0000000..f548ea7
--- /dev/null
+++ b/lang/qt/src/importfromkeyserverjob.h
@@ -0,0 +1,84 @@
+/*
+ importfromkeyserverjob.h
+
+ This file is part of qgpgme, the Qt API binding for gpgme
+ Copyright (c) 2004 Klarälvdalens Datakonsult AB
+ Copyright (c) 2016 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.
+*/
+
+#ifndef __KLEO_IMPORTFROMKEYSERVERJOB_H__
+#define __KLEO_IMPORTFROMKEYSERVERJOB_H__
+
+#include "abstractimportjob.h"
+#include "qgpgme_export.h"
+
+namespace GpgME
+{
+class Key;
+class Error;
+class ImportResult;
+}
+
+#include <vector>
+
+namespace QGpgME
+{
+
+/**
+ @short An abstract base class for asynchronous keyserver-importers
+
+ To use a ImportJob, first obtain an instance from the
+ CryptoBackend implementation, connect the progress() and result()
+ signals to suitable slots and then start the import with a call
+ to start(). This call might fail, in which case the ImportJob
+ instance will have scheduled it's own destruction with a call to
+ QObject::deleteLater().
+
+ After result() is emitted, the ImportJob will schedule it's own
+ destruction by calling QObject::deleteLater().
+*/
+class QGPGME_EXPORT ImportFromKeyserverJob : public AbstractImportJob
+{
+ Q_OBJECT
+protected:
+ explicit ImportFromKeyserverJob(QObject *parent);
+public:
+ ~ImportFromKeyserverJob();
+
+ /**
+ Starts the importing operation. \a keyData contains the data to
+ import from.
+ */
+ virtual GpgME::Error start(const std::vector<GpgME::Key> &keys) = 0;
+
+ virtual GpgME::ImportResult exec(const std::vector<GpgME::Key> &keys) = 0;
+};
+
+}
+
+#endif // __KLEO_IMPORTFROMKEYSERVERJOB_H__
diff --git a/lang/qt/src/importjob.h b/lang/qt/src/importjob.h
new file mode 100644
index 0000000..5c7b24d
--- /dev/null
+++ b/lang/qt/src/importjob.h
@@ -0,0 +1,83 @@
+/*
+ importjob.h
+
+ This file is part of qgpgme, the Qt API binding for gpgme
+ Copyright (c) 2004 Klarälvdalens Datakonsult AB
+ Copyright (c) 2016 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.
+*/
+
+#ifndef __KLEO_IMPORTJOB_H__
+#define __KLEO_IMPORTJOB_H__
+
+#include "abstractimportjob.h"
+#include "qgpgme_export.h"
+
+#include <QtCore/QByteArray>
+
+namespace GpgME
+{
+class Error;
+class ImportResult;
+}
+
+namespace QGpgME
+{
+
+/**
+ @short An abstract base class for asynchronous importers
+
+ To use a ImportJob, first obtain an instance from the
+ CryptoBackend implementation, connect the progress() and result()
+ signals to suitable slots and then start the import with a call
+ to start(). This call might fail, in which case the ImportJob
+ instance will have scheduled it's own destruction with a call to
+ QObject::deleteLater().
+
+ After result() is emitted, the ImportJob will schedule it's own
+ destruction by calling QObject::deleteLater().
+*/
+class QGPGME_EXPORT ImportJob : public AbstractImportJob
+{
+ Q_OBJECT
+protected:
+ explicit ImportJob(QObject *parent);
+public:
+ ~ImportJob();
+
+ /**
+ Starts the importing operation. \a keyData contains the data to
+ import from.
+ */
+ virtual GpgME::Error start(const QByteArray &keyData) = 0;
+
+ virtual GpgME::ImportResult exec(const QByteArray &keyData) = 0;
+};
+
+}
+
+#endif // __KLEO_IMPORTJOB_H__
diff --git a/lang/qt/src/job.cpp b/lang/qt/src/job.cpp
new file mode 100644
index 0000000..8936ea5
--- /dev/null
+++ b/lang/qt/src/job.cpp
@@ -0,0 +1,159 @@
+/*
+ job.cpp
+
+ This file is part of qgpgme, the Qt API binding for gpgme
+ Copyright (c) 2004,2005 Klarälvdalens Datakonsult AB
+ Copyright (c) 2016 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.
+*/
+
+#include "job.h"
+
+#include "keylistjob.h"
+#include "listallkeysjob.h"
+#include "encryptjob.h"
+#include "decryptjob.h"
+#include "decryptverifyjob.h"
+#include "signjob.h"
+#include "signkeyjob.h"
+#include "signencryptjob.h"
+#include "verifydetachedjob.h"
+#include "verifyopaquejob.h"
+#include "keygenerationjob.h"
+#include "importjob.h"
+#include "importfromkeyserverjob.h"
+#include "exportjob.h"
+#include "changeexpiryjob.h"
+#include "changeownertrustjob.h"
+#include "changepasswdjob.h"
+#include "downloadjob.h"
+#include "deletejob.h"
+#include "refreshkeysjob.h"
+#include "adduseridjob.h"
+#include "specialjob.h"
+#include "keyformailboxjob.h"
+#include "wkspublishjob.h"
+#include "tofupolicyjob.h"
+
+#include <QCoreApplication>
+#include <QDebug>
+
+#include <gpg-error.h>
+
+QGpgME::Job::Job(QObject *parent)
+ : QObject(parent)
+{
+ if (QCoreApplication *app = QCoreApplication::instance()) {
+ connect(app, &QCoreApplication::aboutToQuit, this, &Job::slotCancel);
+ }
+}
+
+QGpgME::Job::~Job()
+{
+
+}
+
+QString QGpgME::Job::auditLogAsHtml() const
+{
+ qDebug() << "QGpgME::Job::auditLogAsHtml() should be reimplemented in Kleo::Job subclasses!";
+ return QString();
+}
+
+GpgME::Error QGpgME::Job::auditLogError() const
+{
+ qDebug() << "QGpgME::Job::auditLogError() should be reimplemented in Kleo::Job subclasses!";
+ return GpgME::Error::fromCode(GPG_ERR_NOT_IMPLEMENTED);
+}
+
+bool QGpgME::Job::isAuditLogSupported() const
+{
+ return auditLogError().code() != GPG_ERR_NOT_IMPLEMENTED;
+}
+
+#define make_job_subclass_ext(x,y) \
+ QGpgME::x::x( QObject * parent ) : y( parent ) {} \
+ QGpgME::x::~x() {}
+
+#define make_job_subclass(x) make_job_subclass_ext(x,Job)
+
+make_job_subclass(KeyListJob)
+make_job_subclass(ListAllKeysJob)
+make_job_subclass(EncryptJob)
+make_job_subclass(DecryptJob)
+make_job_subclass(DecryptVerifyJob)
+make_job_subclass(SignJob)
+make_job_subclass(SignEncryptJob)
+make_job_subclass(SignKeyJob)
+make_job_subclass(VerifyDetachedJob)
+make_job_subclass(VerifyOpaqueJob)
+make_job_subclass(KeyGenerationJob)
+make_job_subclass(AbstractImportJob)
+make_job_subclass_ext(ImportJob, AbstractImportJob)
+make_job_subclass_ext(ImportFromKeyserverJob, AbstractImportJob)
+make_job_subclass(ExportJob)
+make_job_subclass(ChangeExpiryJob)
+make_job_subclass(ChangeOwnerTrustJob)
+make_job_subclass(ChangePasswdJob)
+make_job_subclass(DownloadJob)
+make_job_subclass(DeleteJob)
+make_job_subclass(RefreshKeysJob)
+make_job_subclass(AddUserIDJob)
+make_job_subclass(SpecialJob)
+make_job_subclass(KeyForMailboxJob)
+make_job_subclass(WKSPublishJob)
+make_job_subclass(TofuPolicyJob)
+
+#undef make_job_subclass
+
+#include "job.moc"
+
+#include "keylistjob.moc"
+#include "listallkeysjob.moc"
+#include "encryptjob.moc"
+#include "decryptjob.moc"
+#include "decryptverifyjob.moc"
+#include "signjob.moc"
+#include "signencryptjob.moc"
+#include "signkeyjob.moc"
+#include "verifydetachedjob.moc"
+#include "verifyopaquejob.moc"
+#include "keygenerationjob.moc"
+#include "abstractimportjob.moc"
+#include "importjob.moc"
+#include "importfromkeyserverjob.moc"
+#include "exportjob.moc"
+#include "changeexpiryjob.moc"
+#include "changeownertrustjob.moc"
+#include "changepasswdjob.moc"
+#include "downloadjob.moc"
+#include "deletejob.moc"
+#include "refreshkeysjob.moc"
+#include "adduseridjob.moc"
+#include "specialjob.moc"
+#include "keyformailboxjob.moc"
+#include "wkspublishjob.moc"
+#include "tofupolicyjob.moc"
diff --git a/lang/qt/src/job.h b/lang/qt/src/job.h
new file mode 100644
index 0000000..5767729
--- /dev/null
+++ b/lang/qt/src/job.h
@@ -0,0 +1,92 @@
+/*
+ job.h
+
+ This file is part of qgpgme, the Qt API binding for gpgme
+ Copyright (c) 2004 Klarälvdalens Datakonsult AB
+ Copyright (c) 2016 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.
+*/
+
+#ifndef __KLEO_JOB_H__
+#define __KLEO_JOB_H__
+
+#include "qgpgme_export.h"
+
+#include <QObject>
+#include <QString>
+
+#ifdef BUILDING_QGPGME
+# include "error.h"
+#else
+# include <gpgme++/error.h>
+#endif
+
+class QWidget;
+
+namespace QGpgME
+{
+
+/**
+ @short An abstract base class for asynchronous crypto operations
+
+ During the operation, you might receive progress updates through
+ the progress() signal as they arrive, but an implementation is
+ free to not send progress information. You should show a busy
+ progressbar until the first progress() signal is received.
+
+ The done() signal is emitted _before_ the result() signals of
+ subclasses and should be used to hide and/or reset progress bars,
+ not to learn of the end of the operation. Use the result()
+ signals for that.
+
+ To cancel the operation, simply call slotCancel(). The result()
+ signal of subclasses will still be emitted, though, and will
+ carry the information that the operation was canceled.
+*/
+class QGPGME_EXPORT Job : public QObject
+{
+ Q_OBJECT
+protected:
+ explicit Job(QObject *parent);
+public:
+ ~Job();
+
+ virtual QString auditLogAsHtml() const;
+ virtual GpgME::Error auditLogError() const;
+ bool isAuditLogSupported() const;
+
+public Q_SLOTS:
+ virtual void slotCancel() = 0;
+
+Q_SIGNALS:
+ void progress(const QString &what, int current, int total);
+ void done();
+};
+
+}
+
+#endif // __KLEO_JOB_H__
diff --git a/lang/qt/src/keyformailboxjob.h b/lang/qt/src/keyformailboxjob.h
new file mode 100644
index 0000000..d8b6c6b
--- /dev/null
+++ b/lang/qt/src/keyformailboxjob.h
@@ -0,0 +1,106 @@
+/*
+ keyformailboxjob.h
+
+ This file is part of qgpgme, the Qt API binding for gpgme
+ Copyright (c) 2016 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.
+*/
+#ifndef __KLEO_KEYFORMAILBOX_H__
+#define __KLEO_KEYFORMAILBOX_H__
+
+#include <QString>
+
+#include "job.h"
+
+#ifdef BUILDING_QGPGME
+# include "key.h"
+#else
+# include <gpgme++/key.h>
+#endif
+
+namespace GpgME
+{
+class Error;
+class KeyListResult;
+}
+
+namespace QGpgME
+{
+
+/**
+ @short Get the best key to use for a Mailbox
+
+ To use the keyformailboxjob, first obtain an instance from the
+ CryptoBackend and either exec it or start and
+ conncet the result() signals to a suitable slot.
+ The job will be automatically deleted in which
+ case the KeylistJob instance will have schedules it's own
+ destruction with a call to QObject::deleteLater().
+
+ The best key is defined as the key with a UID that has an
+ E-Mail that matches the mailbox provided. If multiple
+ keys are found the one with the highest validity is returned.
+
+ After result() is emitted, the
+ KeyListJob will schedule it's own destruction by calling
+ QObject::deleteLater().
+*/
+class QGPGME_EXPORT KeyForMailboxJob: public Job
+{
+ Q_OBJECT
+protected:
+ explicit KeyForMailboxJob(QObject *parent);
+
+public:
+ ~KeyForMailboxJob();
+
+ /**
+ Starts the operation. \a mailbox is the mailbox to
+ look for.
+
+ The result is the same as for the LocateKeysJob.
+
+ If \a canEncrypt is true, only keys that have a subkey for encryption
+ usage are returned. Use this if you need to select a
+ key for signing.
+ */
+ virtual GpgME::Error start(const QString &mailbox, bool canEncrypt = true) = 0;
+
+ virtual GpgME::KeyListResult exec(const QString &mailbox, bool canEncrypt, GpgME::Key &key, GpgME::UserID &uid) = 0;
+
+Q_SIGNALS:
+ /** The result. \a Key is the key found or a Null key.
+ *
+ * The userid is the uid where the mailbox matches.
+ *
+ * The auditlog params are always null / empty.
+ */
+ void result(const GpgME::KeyListResult &result, const GpgME::Key &key, const GpgME::UserID &uid, const QString &auditLogAsHtml = QString(), const GpgME::Error &auditLogError = GpgME::Error());
+};
+
+}
+#endif
diff --git a/lang/qt/src/keygenerationjob.h b/lang/qt/src/keygenerationjob.h
new file mode 100644
index 0000000..a0beeac
--- /dev/null
+++ b/lang/qt/src/keygenerationjob.h
@@ -0,0 +1,85 @@
+/*
+ keygenerationjob.h
+
+ This file is part of qgpgme, the Qt API binding for gpgme
+ Copyright (c) 2004 Klarälvdalens Datakonsult AB
+ Copyright (c) 2016 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.
+*/
+
+#ifndef __KLEO_KEYGENERATIONJOB_H__
+#define __KLEO_KEYGENERATIONJOB_H__
+
+#include "job.h"
+#include "qgpgme_export.h"
+
+#include <QtCore/QByteArray>
+
+namespace GpgME
+{
+class Error;
+class KeyGenerationResult;
+}
+
+namespace QGpgME
+{
+
+/**
+ @short An abstract base class for asynchronous key generation
+
+ To use a KeyGenerationJob, first obtain an instance from the
+ CryptoBackend implementation, connect the progress() and result()
+ signals to suitable slots and then start the key generation with
+ a call to start(). This call might fail, in which case the
+ KeyGenerationJob instance will have scheduled it's own
+ destruction with a call to QObject::deleteLater().
+
+ After result() is emitted, the KeyGenerationJob will schedule it's own
+ destruction by calling QObject::deleteLater().
+*/
+class QGPGME_EXPORT KeyGenerationJob : public Job
+{
+ Q_OBJECT
+protected:
+ explicit KeyGenerationJob(QObject *parent);
+public:
+ ~KeyGenerationJob();
+
+ /**
+ Starts the key generation operation. \a parameters is a
+ backend-specific string containing the parameters of the key to
+ create (length, capabilities, etc).
+ */
+ virtual GpgME::Error start(const QString &parameters) = 0;
+
+Q_SIGNALS:
+ void result(const GpgME::KeyGenerationResult &result, const QByteArray &pubKeyData, const QString &auditLogAsHtml = QString(), const GpgME::Error &auditLogError = GpgME::Error());
+};
+
+}
+
+#endif // __KLEO_KEYGENERATIONJOB_H__
diff --git a/lang/qt/src/keylistjob.h b/lang/qt/src/keylistjob.h
new file mode 100644
index 0000000..8dc736e
--- /dev/null
+++ b/lang/qt/src/keylistjob.h
@@ -0,0 +1,109 @@
+/*
+ keylistjob.h
+
+ This file is part of qgpgme, the Qt API binding for gpgme
+ Copyright (c) 2004 Klarälvdalens Datakonsult AB
+ Copyright (c) 2016 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.
+*/
+
+#ifndef __KLEO_KEYLISTJOB_H__
+#define __KLEO_KEYLISTJOB_H__
+
+#include "job.h"
+#include "qgpgme_export.h"
+
+#ifdef BUILDING_QGPGME
+# include "key.h"
+#else
+# include <gpgme++/key.h>
+#endif
+
+#include <vector>
+
+namespace GpgME
+{
+class Error;
+class KeyListResult;
+}
+
+class QStringList;
+
+namespace QGpgME
+{
+
+/**
+ @short An abstract base class for asynchronous key listers
+
+ To use a KeyListJob, first obtain an instance from the
+ CryptoBackend implementation, connect the nextKey(), progress()
+ and result() signals to suitable slots and then start the key
+ listing with a call to start(). This call might fail, in which
+ case the KeylistJob instance will have schedules it's own
+ destruction with a call to QObject::deleteLater().
+
+ During keylisting, you will receive new key objects through the
+ nextKey() signal as they arrive. After result() is emitted, the
+ KeyListJob will schedule it's own destruction by calling
+ QObject::deleteLater().
+*/
+class QGPGME_EXPORT KeyListJob : public Job
+{
+ Q_OBJECT
+protected:
+ explicit KeyListJob(QObject *parent);
+
+public:
+ ~KeyListJob();
+
+ /**
+ Starts the keylist operation. \a pattern is a list of patterns
+ used to restrict the list of keys returned. Empty patterns are
+ ignored. If \a pattern is empty or contains only empty strings,
+ all keys are returned (however, the backend is free to truncate
+ the result and should do so; when this happens, it will be
+ reported by the reult object).
+
+ If \a secretOnly is true, only keys for which the secret key is
+ also available are returned. Use this if you need to select a
+ key for signing.
+ */
+ virtual GpgME::Error start(const QStringList &patterns, bool secretOnly = false) = 0;
+
+ virtual GpgME::KeyListResult exec(const QStringList &patterns, bool secretOnly, std::vector<GpgME::Key> &keys) = 0;
+
+ /** Add a flag to the keylistmode used. */
+ virtual void addMode(GpgME::KeyListMode mode) = 0;
+
+Q_SIGNALS:
+ void nextKey(const GpgME::Key &key);
+ void result(const GpgME::KeyListResult &result, const std::vector<GpgME::Key> &keys = std::vector<GpgME::Key>(), const QString &auditLogAsHtml = QString(), const GpgME::Error &auditLogError = GpgME::Error());
+};
+
+}
+
+#endif // __KLEO_KEYLISTJOB_H__
diff --git a/lang/qt/src/listallkeysjob.h b/lang/qt/src/listallkeysjob.h
new file mode 100644
index 0000000..4fbb469
--- /dev/null
+++ b/lang/qt/src/listallkeysjob.h
@@ -0,0 +1,104 @@
+/*
+ listallkeysjob.h
+
+ This file is part of qgpgme, the Qt API binding for gpgme
+ Copyright (c) 2004 Klarälvdalens Datakonsult AB
+ Copyright (c) 2016 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.
+*/
+
+#ifndef __KLEO_LISTALLKEYSJOB_H__
+#define __KLEO_LISTALLKEYSJOB_H__
+
+#include "job.h"
+#include "qgpgme_export.h"
+
+#ifdef BUILDING_QGPGME
+# include "key.h"
+#else
+# include <gpgme++/key.h>
+#endif
+
+#include <vector>
+
+namespace GpgME
+{
+class Error;
+class KeyListResult;
+}
+
+namespace QGpgME
+{
+
+/**
+ @short An abstract base class for asynchronously listing all keys
+
+ To use a ListAllKeysJob, first obtain an instance from the
+ CryptoBackend implementation, connect the progress()
+ and result() signals to suitable slots and then start the key
+ listing with a call to start(). This call might fail, in which
+ case the ListAllKeysJob instance will have schedules it's own
+ destruction with a call to QObject::deleteLater().
+
+ After result() is emitted, the ListAllKeysJob will schedule it's
+ own destruction by calling QObject::deleteLater().
+
+ This is potentially much faster than a KeyListJob with empty
+ pattern.
+*/
+class QGPGME_EXPORT ListAllKeysJob : public Job
+{
+ Q_OBJECT
+protected:
+ explicit ListAllKeysJob(QObject *parent);
+
+public:
+ ~ListAllKeysJob();
+
+ /**
+ Starts the listallkeys operation. In general, all keys are
+ returned (however, the backend is free to truncate the result
+ and should do so; when this happens, it will be reported by the
+ result object).
+
+ If \a mergeKeys is true, secret keys are merged into public
+ keys.
+ */
+ virtual GpgME::Error start(bool mergeKeys = false) = 0;
+
+ /**
+ Synchronous version of start().
+ */
+ virtual GpgME::KeyListResult exec(std::vector<GpgME::Key> &pub, std::vector<GpgME::Key> &sec, bool mergeKeys = false) = 0;
+
+Q_SIGNALS:
+ void result(const GpgME::KeyListResult &result, const std::vector<GpgME::Key> &pub = std::vector<GpgME::Key>(), const std::vector<GpgME::Key> &sec = std::vector<GpgME::Key>(), const QString &auditLogAsHtml = QString(), const GpgME::Error &auditLogError = GpgME::Error());
+};
+
+}
+
+#endif // __KLEO_LISTALLKEYSJOB_H__
diff --git a/lang/qt/src/multideletejob.h b/lang/qt/src/multideletejob.h
new file mode 100644
index 0000000..8915cd1
--- /dev/null
+++ b/lang/qt/src/multideletejob.h
@@ -0,0 +1,107 @@
+/*
+ multideletejob.h
+
+ This file is part of qgpgme, the Qt API binding for gpgme
+ Copyright (c) 2004 Klarälvdalens Datakonsult AB
+ Copyright (c) 2016 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.
+*/
+
+#ifndef __KLEO_MULTIDELETEJOB_H__
+#define __KLEO_MULTIDELETEJOB_H__
+
+#include "qgpgme_export.h"
+#include "job.h"
+#include "cryptobackend.h"
+
+#include <QPointer>
+
+#include <vector>
+
+namespace GpgME
+{
+class Error;
+class Key;
+}
+
+namespace QGpgME
+{
+class DeleteJob;
+}
+
+namespace QGpgME
+{
+
+/**
+ @short A convenience class bundling together multiple DeleteJobs.
+
+ To use a MultiDeleteJob, pass it a CryptoBackend implementation,
+ connect the progress() and result() signals to suitable slots and
+ then start the delete with a call to start(). This call might
+ fail, in which case the MultiDeleteJob instance will have scheduled
+ it's own destruction with a call to QObject::deleteLater().
+
+ After result() is emitted, the MultiDeleteJob will schedule it's own
+ destruction by calling QObject::deleteLater().
+*/
+class QGPGME_EXPORT MultiDeleteJob : public Job
+{
+ Q_OBJECT
+public:
+ explicit MultiDeleteJob(const Protocol *protocol);
+ ~MultiDeleteJob();
+
+ /**
+ Starts the delete operation. \a keys is the list of keys to
+ delete, \a allowSecretKeyDeletion specifies if a key may also
+ be deleted if the secret key part is available, too.
+ */
+ GpgME::Error start(const std::vector<GpgME::Key> &keys, bool allowSecretKeyDeletion = false);
+
+ /* from Job */
+ void slotCancel() Q_DECL_OVERRIDE;
+
+Q_SIGNALS:
+ void result(const GpgME::Error &result, const GpgME::Key &errorKey);
+
+private Q_SLOTS:
+ void slotResult(const GpgME::Error &);
+
+private:
+ GpgME::Error startAJob();
+
+private:
+ const Protocol *mProtocol;
+ QPointer<DeleteJob> mJob;
+ std::vector<GpgME::Key> mKeys;
+ std::vector<GpgME::Key>::const_iterator mIt;
+ bool mAllowSecretKeyDeletion;
+};
+
+}
+
+#endif // __KLEO_MULTIDELETEJOB_H__
diff --git a/lang/qt/src/protocol.h b/lang/qt/src/protocol.h
new file mode 100644
index 0000000..40ddcb5
--- /dev/null
+++ b/lang/qt/src/protocol.h
@@ -0,0 +1,183 @@
+/*
+ protocol.h
+
+ This file is part of qgpgme, the Qt API binding for gpgme
+ Copyright (c) 2004,2005 Klarälvdalens Datakonsult AB
+ Copyright (c) 2016 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.
+*/
+#ifndef __QGPGME_PROTOCOL_H__
+#define __QGPGME_PROTOCOL_H__
+
+#include <QString>
+#include <QVariant>
+
+#include "qgpgme_export.h"
+
+namespace QGpgME {
+class CryptoConfig;
+class KeyListJob;
+class ListAllKeysJob;
+class KeyGenerationJob;
+class ImportJob;
+class ImportFromKeyserverJob;
+class ExportJob;
+class DownloadJob;
+class DeleteJob;
+class EncryptJob;
+class DecryptJob;
+class SignJob;
+class SignKeyJob;
+class VerifyDetachedJob;
+class VerifyOpaqueJob;
+class SignEncryptJob;
+class DecryptVerifyJob;
+class RefreshKeysJob;
+class ChangeExpiryJob;
+class ChangeOwnerTrustJob;
+class ChangePasswdJob;
+class AddUserIDJob;
+class SpecialJob;
+class KeyForMailboxJob;
+class WKSPublishJob;
+class TofuPolicyJob;
+
+/** The main entry point for QGpgME Comes in OpenPGP and SMIME(CMS) flavors.
+ *
+ * Use the proctocol class to obtain an instance of a job. Jobs
+ * provide async API for GnuPG that can be connected to signals / slots.
+ *
+ * A job is usually started with start() and emits a result signal.
+ * The parameters of the result signal depend on the job but the last
+ * two are always a QString for the auditlog and an GpgME::Error for
+ * an eventual error.
+ *
+ * In case async API is used and the result signal is emited a
+ * job schedules its own deletion.
+ *
+ * Most jobs also provide a synchronous call exec in which case
+ * you have to explicitly delete the job if you don't need it anymore.
+ *
+ * \code
+ * // Async example:
+ * KeyListJob *job = openpgp()->keyListJob();
+ * connect(job, &KeyListJob::result, job, [this, job](KeyListResult, std::vector<Key> keys, QString, Error)
+ * {
+ * // keys and resuls can now be used.
+ * });
+ * \endcode
+ *
+ * \code
+ * // Sync eaxmple:
+ * KeyListJob *job = openpgp()->keyListJob(false, false, false);
+ * std::vector<GpgME::Key> keys;
+ * GpgME::KeyListResult result = job->exec(QStringList() <<
+ * QStringLiteral("alfa@example.net"),
+ * false, keys);
+ * delete job;
+ * \endcode
+ */
+class QGPGME_EXPORT Protocol
+{
+public:
+ virtual ~Protocol() {}
+
+ virtual QString name() const = 0;
+
+ virtual QString displayName() const = 0;
+
+ virtual KeyListJob *keyListJob(bool remote = false, bool includeSigs = false, bool validate = false) const = 0;
+ virtual ListAllKeysJob *listAllKeysJob(bool includeSigs = false, bool validate = false) const = 0;
+ virtual EncryptJob *encryptJob(bool armor = false, bool textmode = false) const = 0;
+ virtual DecryptJob *decryptJob() const = 0;
+ virtual SignJob *signJob(bool armor = false, bool textMode = false) const = 0;
+ virtual VerifyDetachedJob *verifyDetachedJob(bool textmode = false) const = 0;
+ virtual VerifyOpaqueJob *verifyOpaqueJob(bool textmode = false) const = 0;
+ virtual KeyGenerationJob *keyGenerationJob() const = 0;
+ virtual ImportJob *importJob() const = 0;
+ virtual ImportFromKeyserverJob *importFromKeyserverJob() 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;
+ virtual DownloadJob *downloadJob(bool armor = false) const = 0;
+ virtual DeleteJob *deleteJob() const = 0;
+ virtual SignEncryptJob *signEncryptJob(bool armor = false, bool textMode = false) const = 0;
+ virtual DecryptVerifyJob *decryptVerifyJob(bool textmode = false) const = 0;
+ virtual RefreshKeysJob *refreshKeysJob() const = 0;
+ virtual ChangeExpiryJob *changeExpiryJob() const = 0;
+ virtual SignKeyJob *signKeyJob() const = 0;
+ virtual ChangePasswdJob *changePasswdJob() const = 0;
+ virtual ChangeOwnerTrustJob *changeOwnerTrustJob() const = 0;
+ virtual AddUserIDJob *addUserIDJob() const = 0;
+ virtual SpecialJob *specialJob(const char *type, const QMap<QString, QVariant> &args) const = 0;
+
+ /** A key locate job.
+ *
+ * This tries to find a key in local
+ * and remote sources, if the key was remote it is imported
+ * by GnuPG. Same as KeyListJob but intended to be used
+ * to locate keys automatically. This ends up calling --locate-keys.
+ *
+ * Only available for OpenPGP
+ *
+ * Results are validated. As if keyListJob was called
+ * with both includeSigs and validate options.
+ */
+ virtual KeyListJob *locateKeysJob() const = 0;
+ /** Find the best key to use for a mailbox. */
+ virtual KeyForMailboxJob *keyForMailboxJob() const = 0;
+
+ /** A Job for interacting with gnupg's wks tools. */
+ virtual WKSPublishJob *wksPublishJob() const = 0;
+
+ /** A Job to set tofu policy */
+ virtual TofuPolicyJob *tofuPolicyJob() const = 0;
+};
+
+/** Obtain a reference to the OpenPGP Protocol.
+ *
+ * The reference is to a static object.
+ * @returns Refrence to the OpenPGP Protocol.
+ */
+QGPGME_EXPORT Protocol *openpgp();
+
+/** Obtain a reference to the smime Protocol.
+ *
+ * The reference is to a static object.
+ * @returns Refrence to the smime Protocol.
+ */
+QGPGME_EXPORT Protocol *smime();
+
+/** Obtain a reference to a cryptoConfig object.
+ *
+ * The reference is to a static object.
+ * @returns reference to cryptoConfig object.
+ */
+QGPGME_EXPORT CryptoConfig *cryptoConfig();
+
+}
+#endif
diff --git a/lang/qt/src/protocol_p.h b/lang/qt/src/protocol_p.h
new file mode 100644
index 0000000..7f66fa4
--- /dev/null
+++ b/lang/qt/src/protocol_p.h
@@ -0,0 +1,419 @@
+/*
+ protocol_p.h
+
+ This file is part of qgpgme, the Qt API binding for gpgme
+ Copyright (c) 2004,2005 Klarälvdalens Datakonsult AB
+ Copyright (c) 2016 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.
+*/
+#ifndef __QGPGME_PROTOCOL_P_H__
+#define __QGPGME_PROTOCOL_P_H__
+#include "qgpgmenewcryptoconfig.h"
+
+#include "qgpgmekeygenerationjob.h"
+#include "qgpgmekeylistjob.h"
+#include "qgpgmelistallkeysjob.h"
+#include "qgpgmedecryptjob.h"
+#include "qgpgmedecryptverifyjob.h"
+#include "qgpgmerefreshkeysjob.h"
+#include "qgpgmedeletejob.h"
+#include "qgpgmesecretkeyexportjob.h"
+#include "qgpgmedownloadjob.h"
+#include "qgpgmesignencryptjob.h"
+#include "qgpgmeencryptjob.h"
+#include "qgpgmesignjob.h"
+#include "qgpgmesignkeyjob.h"
+#include "qgpgmeexportjob.h"
+#include "qgpgmeverifydetachedjob.h"
+#include "qgpgmeimportjob.h"
+#include "qgpgmeimportfromkeyserverjob.h"
+#include "qgpgmeverifyopaquejob.h"
+#include "qgpgmechangeexpiryjob.h"
+#include "qgpgmechangeownertrustjob.h"
+#include "qgpgmechangepasswdjob.h"
+#include "qgpgmeadduseridjob.h"
+#include "qgpgmekeyformailboxjob.h"
+#include "qgpgmewkspublishjob.h"
+#include "qgpgmetofupolicyjob.h"
+
+namespace
+{
+
+class Protocol : public QGpgME::Protocol
+{
+ GpgME::Protocol mProtocol;
+public:
+ explicit Protocol(GpgME::Protocol proto) : mProtocol(proto) {}
+
+ QString name() const Q_DECL_OVERRIDE
+ {
+ switch (mProtocol) {
+ case GpgME::OpenPGP: return QStringLiteral("OpenPGP");
+ case GpgME::CMS: return QStringLiteral("SMIME");
+ default: return QString();
+ }
+ }
+
+ QString displayName() const Q_DECL_OVERRIDE
+ {
+ // ah (2.4.16): Where is this used and isn't this inverted
+ // with name
+ switch (mProtocol) {
+ case GpgME::OpenPGP: return QStringLiteral("gpg");
+ case GpgME::CMS: return QStringLiteral("gpgsm");
+ default: return QStringLiteral("unknown");
+ }
+ }
+
+ QGpgME::SpecialJob *specialJob(const char *, const QMap<QString, QVariant> &) const Q_DECL_OVERRIDE
+ {
+ return 0;
+ }
+
+ QGpgME::KeyListJob *keyListJob(bool remote, bool includeSigs, bool validate) const Q_DECL_OVERRIDE
+ {
+ GpgME::Context *context = GpgME::Context::createForProtocol(mProtocol);
+ if (!context) {
+ return 0;
+ }
+
+ unsigned int mode = context->keyListMode();
+ if (remote) {
+ mode |= GpgME::Extern;
+ mode &= ~GpgME::Local;
+ } else {
+ mode |= GpgME::Local;
+ mode &= ~GpgME::Extern;
+ }
+ if (includeSigs) {
+ mode |= GpgME::Signatures;
+ }
+ if (validate) {
+ mode |= GpgME::Validate;
+ }
+ context->setKeyListMode(mode);
+ return new QGpgME::QGpgMEKeyListJob(context);
+ }
+
+ QGpgME::ListAllKeysJob *listAllKeysJob(bool includeSigs, bool validate) const Q_DECL_OVERRIDE
+ {
+ GpgME::Context *context = GpgME::Context::createForProtocol(mProtocol);
+ if (!context) {
+ return 0;
+ }
+
+ unsigned int mode = context->keyListMode();
+ mode |= GpgME::Local;
+ mode &= ~GpgME::Extern;
+ if (includeSigs) {
+ mode |= GpgME::Signatures;
+ }
+ if (validate) {
+ mode |= GpgME::Validate;
+ /* Setting the context to offline mode disables CRL / OCSP checks in
+ this Job. Otherwise we would try to fetch the CRL's for all CMS
+ keys in the users keyring because GpgME::Validate includes remote
+ resources by default in the validity check.
+ This setting only has any effect if gpgsm >= 2.1.6 is used.
+ */
+ context->setOffline(true);
+ }
+ context->setKeyListMode(mode);
+ return new QGpgME::QGpgMEListAllKeysJob(context);
+ }
+
+ QGpgME::EncryptJob *encryptJob(bool armor, bool textmode) const Q_DECL_OVERRIDE
+ {
+ GpgME::Context *context = GpgME::Context::createForProtocol(mProtocol);
+ if (!context) {
+ return 0;
+ }
+
+ context->setArmor(armor);
+ context->setTextMode(textmode);
+ return new QGpgME::QGpgMEEncryptJob(context);
+ }
+
+ QGpgME::DecryptJob *decryptJob() const Q_DECL_OVERRIDE
+ {
+ GpgME::Context *context = GpgME::Context::createForProtocol(mProtocol);
+ if (!context) {
+ return 0;
+ }
+ return new QGpgME::QGpgMEDecryptJob(context);
+ }
+
+ QGpgME::SignJob *signJob(bool armor, bool textMode) const Q_DECL_OVERRIDE
+ {
+ GpgME::Context *context = GpgME::Context::createForProtocol(mProtocol);
+ if (!context) {
+ return 0;
+ }
+
+ context->setArmor(armor);
+ context->setTextMode(textMode);
+ return new QGpgME::QGpgMESignJob(context);
+ }
+
+ QGpgME::VerifyDetachedJob *verifyDetachedJob(bool textMode) const Q_DECL_OVERRIDE
+ {
+ GpgME::Context *context = GpgME::Context::createForProtocol(mProtocol);
+ if (!context) {
+ return 0;
+ }
+
+ context->setTextMode(textMode);
+ return new QGpgME::QGpgMEVerifyDetachedJob(context);
+ }
+
+ QGpgME::VerifyOpaqueJob *verifyOpaqueJob(bool textMode) const Q_DECL_OVERRIDE
+ {
+ GpgME::Context *context = GpgME::Context::createForProtocol(mProtocol);
+ if (!context) {
+ return 0;
+ }
+
+ context->setTextMode(textMode);
+ return new QGpgME::QGpgMEVerifyOpaqueJob(context);
+ }
+
+ QGpgME::KeyGenerationJob *keyGenerationJob() const Q_DECL_OVERRIDE
+ {
+ GpgME::Context *context = GpgME::Context::createForProtocol(mProtocol);
+ if (!context) {
+ return 0;
+ }
+ return new QGpgME::QGpgMEKeyGenerationJob(context);
+ }
+
+ QGpgME::ImportJob *importJob() const Q_DECL_OVERRIDE
+ {
+ GpgME::Context *context = GpgME::Context::createForProtocol(mProtocol);
+ if (!context) {
+ return 0;
+ }
+ return new QGpgME::QGpgMEImportJob(context);
+ }
+
+ QGpgME::ImportFromKeyserverJob *importFromKeyserverJob() const Q_DECL_OVERRIDE
+ {
+ GpgME::Context *context = GpgME::Context::createForProtocol(mProtocol);
+ if (!context) {
+ return 0;
+ }
+ return new QGpgME::QGpgMEImportFromKeyserverJob(context);
+ }
+
+ QGpgME::ExportJob *publicKeyExportJob(bool armor) const Q_DECL_OVERRIDE
+ {
+ GpgME::Context *context = GpgME::Context::createForProtocol(mProtocol);
+ if (!context) {
+ return 0;
+ }
+
+ context->setArmor(armor);
+ return new QGpgME::QGpgMEExportJob(context);
+ }
+
+ QGpgME::ExportJob *secretKeyExportJob(bool armor, const QString &charset) const Q_DECL_OVERRIDE
+ {
+ if (mProtocol != GpgME::CMS) { // fixme: add support for gpg, too
+ return 0;
+ }
+
+ // this operation is not supported by gpgme, so we have to call gpgsm ourselves:
+ return new QGpgME::QGpgMESecretKeyExportJob(armor, charset);
+ }
+
+ QGpgME::RefreshKeysJob *refreshKeysJob() const Q_DECL_OVERRIDE
+ {
+ if (mProtocol != GpgME::CMS) { // fixme: add support for gpg, too
+ return 0;
+ }
+
+ // this operation is not supported by gpgme, so we have to call gpgsm ourselves:
+ return new QGpgME::QGpgMERefreshKeysJob();
+ }
+
+ QGpgME::DownloadJob *downloadJob(bool armor) const Q_DECL_OVERRIDE
+ {
+ GpgME::Context *context = GpgME::Context::createForProtocol(mProtocol);
+ if (!context) {
+ return 0;
+ }
+
+ context->setArmor(armor);
+ // this is the hackish interface for downloading from keyserers currently:
+ context->setKeyListMode(GpgME::Extern);
+ return new QGpgME::QGpgMEDownloadJob(context);
+ }
+
+ QGpgME::DeleteJob *deleteJob() const Q_DECL_OVERRIDE
+ {
+ GpgME::Context *context = GpgME::Context::createForProtocol(mProtocol);
+ if (!context) {
+ return 0;
+ }
+ return new QGpgME::QGpgMEDeleteJob(context);
+ }
+
+ QGpgME::SignEncryptJob *signEncryptJob(bool armor, bool textMode) const Q_DECL_OVERRIDE
+ {
+ GpgME::Context *context = GpgME::Context::createForProtocol(mProtocol);
+ if (!context) {
+ return 0;
+ }
+
+ context->setArmor(armor);
+ context->setTextMode(textMode);
+ return new QGpgME::QGpgMESignEncryptJob(context);
+ }
+
+ QGpgME::DecryptVerifyJob *decryptVerifyJob(bool textMode) const Q_DECL_OVERRIDE
+ {
+ GpgME::Context *context = GpgME::Context::createForProtocol(mProtocol);
+ if (!context) {
+ return 0;
+ }
+
+ context->setTextMode(textMode);
+ return new QGpgME::QGpgMEDecryptVerifyJob(context);
+ }
+
+ QGpgME::ChangeExpiryJob *changeExpiryJob() const Q_DECL_OVERRIDE
+ {
+ if (mProtocol != GpgME::OpenPGP) {
+ return 0; // only supported by gpg
+ }
+
+ GpgME::Context *context = GpgME::Context::createForProtocol(mProtocol);
+ if (!context) {
+ return 0;
+ }
+ return new QGpgME::QGpgMEChangeExpiryJob(context);
+ }
+
+ QGpgME::ChangePasswdJob *changePasswdJob() const Q_DECL_OVERRIDE
+ {
+ if (!GpgME::hasFeature(GpgME::PasswdFeature, 0)) {
+ return 0;
+ }
+ GpgME::Context *context = GpgME::Context::createForProtocol(mProtocol);
+ if (!context) {
+ return 0;
+ }
+ return new QGpgME::QGpgMEChangePasswdJob(context);
+ }
+
+ QGpgME::SignKeyJob *signKeyJob() const Q_DECL_OVERRIDE
+ {
+ if (mProtocol != GpgME::OpenPGP) {
+ return 0; // only supported by gpg
+ }
+
+ GpgME::Context *context = GpgME::Context::createForProtocol(mProtocol);
+ if (!context) {
+ return 0;
+ }
+ return new QGpgME::QGpgMESignKeyJob(context);
+ }
+
+ QGpgME::ChangeOwnerTrustJob *changeOwnerTrustJob() const Q_DECL_OVERRIDE
+ {
+ if (mProtocol != GpgME::OpenPGP) {
+ return 0; // only supported by gpg
+ }
+
+ GpgME::Context *context = GpgME::Context::createForProtocol(mProtocol);
+ if (!context) {
+ return 0;
+ }
+ return new QGpgME::QGpgMEChangeOwnerTrustJob(context);
+ }
+
+ QGpgME::AddUserIDJob *addUserIDJob() const Q_DECL_OVERRIDE
+ {
+ if (mProtocol != GpgME::OpenPGP) {
+ return 0; // only supported by gpg
+ }
+
+ GpgME::Context *context = GpgME::Context::createForProtocol(mProtocol);
+ if (!context) {
+ return 0;
+ }
+ return new QGpgME::QGpgMEAddUserIDJob(context);
+ }
+
+ QGpgME::KeyListJob *locateKeysJob() const Q_DECL_OVERRIDE
+ {
+ if (mProtocol != GpgME::OpenPGP) {
+ return Q_NULLPTR;
+ }
+ GpgME::Context *context = GpgME::Context::createForProtocol(mProtocol);
+ if (!context) {
+ return Q_NULLPTR;
+ }
+ context->setKeyListMode(GpgME::Extern | GpgME::Local | GpgME::Signatures | GpgME::Validate);
+ return new QGpgME::QGpgMEKeyListJob(context);
+ }
+
+ QGpgME::KeyForMailboxJob *keyForMailboxJob() const Q_DECL_OVERRIDE
+ {
+ GpgME::Context *context = GpgME::Context::createForProtocol(mProtocol);
+ if (!context) {
+ return Q_NULLPTR;
+ }
+ return new QGpgME::QGpgMEKeyForMailboxJob(context);
+ }
+
+ QGpgME::WKSPublishJob *wksPublishJob() const Q_DECL_OVERRIDE
+ {
+ if (mProtocol != GpgME::OpenPGP) {
+ return Q_NULLPTR;
+ }
+ auto context = GpgME::Context::createForEngine(GpgME::SpawnEngine);
+ if (!context) {
+ return Q_NULLPTR;
+ }
+ return new QGpgME::QGpgMEWKSPublishJob(context.release());
+ }
+
+ QGpgME::TofuPolicyJob *tofuPolicyJob() const Q_DECL_OVERRIDE
+ {
+ if (mProtocol != GpgME::OpenPGP) {
+ return Q_NULLPTR;
+ }
+ GpgME::Context *context = GpgME::Context::createForProtocol(mProtocol);
+ if (!context) {
+ return Q_NULLPTR;
+ }
+ return new QGpgME::QGpgMETofuPolicyJob(context);
+ }
+};
+
+}
+#endif
diff --git a/lang/qt/src/qgpgme_export.h b/lang/qt/src/qgpgme_export.h
new file mode 100644
index 0000000..ceb3888
--- /dev/null
+++ b/lang/qt/src/qgpgme_export.h
@@ -0,0 +1,73 @@
+/*qgpgme_export.h - Export macros for qgpgme
+ Copyright (C) 2016, Intevation GmbH
+
+ This file is part of GPGME++.
+
+ GPGME++ is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Library General Public
+ License as published by the Free Software Foundation; either
+ version 2 of the License, or (at your option) any later version.
+
+ GPGME++ is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU Library General Public License for more details.
+
+ You should have received a copy of the GNU Library General Public License
+ along with GPGME++; see the file COPYING.LIB. If not, write to the
+ Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+ Boston, MA 02110-1301, USA.
+*/
+
+#ifndef QGPGME_EXPORT_H
+#define QGPGME_EXPORT_H
+
+#ifdef QGPGME_STATIC_DEFINE
+# define QGPGME_EXPORT
+# define QGPGME_NO_EXPORT
+#else
+# ifndef QGPGME_EXPORT
+# ifdef BUILDING_QGPGME
+ /* We are building this library */
+# ifdef WIN32
+# define QGPGME_EXPORT __declspec(dllexport)
+# else
+# define QGPGME_EXPORT __attribute__((visibility("default")))
+# endif
+# else
+ /* We are using this library */
+# ifdef WIN32
+# define QGPGME_EXPORT __declspec(dllimport)
+# else
+# define QGPGME_EXPORT __attribute__((visibility("default")))
+# endif
+# endif
+# endif
+
+# ifndef QGPGME_NO_EXPORT
+# ifdef WIN32
+# define QGPGME_NO_EXPORT
+# else
+# define QGPGME_NO_EXPORT __attribute__((visibility("hidden")))
+# endif
+# endif
+#endif
+
+#ifndef QGPGME_DEPRECATED
+# define QGPGME_DEPRECATED __attribute__ ((__deprecated__))
+#endif
+
+#ifndef QGPGME_DEPRECATED_EXPORT
+# define QGPGME_DEPRECATED_EXPORT QGPGME_EXPORT QGPGME_DEPRECATED
+#endif
+
+#ifndef QGPGME_DEPRECATED_NO_EXPORT
+# define QGPGME_DEPRECATED_NO_EXPORT QGPGME_NO_EXPORT QGPGME_DEPRECATED
+#endif
+
+#define DEFINE_NO_DEPRECATED 0
+#if DEFINE_NO_DEPRECATED
+# define QGPGME_NO_DEPRECATED
+#endif
+
+#endif
diff --git a/lang/qt/src/qgpgme_version.h.in b/lang/qt/src/qgpgme_version.h.in
new file mode 100644
index 0000000..9fbe965
--- /dev/null
+++ b/lang/qt/src/qgpgme_version.h.in
@@ -0,0 +1,32 @@
+/*qgpgme_version.h - Version macros for qgpgme
+ Copyright (C) 2016, Intevation GmbH
+
+ This file is part of GPGME++.
+
+ GPGME++ is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Library General Public
+ License as published by the Free Software Foundation; either
+ version 2 of the License, or (at your option) any later version.
+
+ GPGME++ is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU Library General Public License for more details.
+
+ You should have received a copy of the GNU Library General Public License
+ along with GPGME++; see the file COPYING.LIB. If not, write to the
+ Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+ Boston, MA 02110-1301, USA.
+*/
+
+
+#ifndef QGPGME_VERSION_H
+#define QGPGME_VERSION_H
+
+#define QGPGME_VERSION_STRING "@LIBQGPGME_LT_CURRENT@.@LIBQGPGME_LT_AGE@.@LIBQGPGME_LT_REVISION@"
+#define QGPGME_VERSION_MAJOR @LIBQGPGME_LT_CURRENT@
+#define QGPGME_VERSION_MINOR @LIBQGPGME_LT_AGE@
+#define QGPGME_VERSION_PATCH @LIBQGPGME_LT_REVISION@
+#define QGPGME_VERSION ((@LIBQGPGME_LT_CURRENT@<<16)|(@LIBQGPGME_LT_AGE@<<8)|(@LIBQGPGME_LT_REVISION@))
+
+#endif
diff --git a/lang/qt/src/qgpgmeadduseridjob.cpp b/lang/qt/src/qgpgmeadduseridjob.cpp
new file mode 100644
index 0000000..eb3bfab
--- /dev/null
+++ b/lang/qt/src/qgpgmeadduseridjob.cpp
@@ -0,0 +1,80 @@
+/*
+ qgpgmeadduseridjob.cpp
+
+ This file is part of qgpgme, the Qt API binding for gpgme
+ Copyright (c) 2008 Klarälvdalens Datakonsult AB
+ Copyright (c) 2016 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.
+*/
+
+#include "qgpgmeadduseridjob.h"
+
+#include "dataprovider.h"
+
+#include "context.h"
+#include "data.h"
+#include "gpgadduserideditinteractor.h"
+#include "key.h"
+
+#include <cassert>
+#include <memory>
+
+using namespace QGpgME;
+using namespace GpgME;
+
+QGpgMEAddUserIDJob::QGpgMEAddUserIDJob(Context *context)
+ : mixin_type(context)
+{
+ lateInitialization();
+}
+
+QGpgMEAddUserIDJob::~QGpgMEAddUserIDJob() {}
+
+static QGpgMEAddUserIDJob::result_type add_user_id(Context *ctx, const Key &key, const QString &name, const QString &email, const QString &comment)
+{
+
+ GpgAddUserIDEditInteractor *gau = new GpgAddUserIDEditInteractor;
+
+ gau->setNameUtf8(name.toUtf8().constData());
+ gau->setEmailUtf8(email.toUtf8().constData());
+ gau->setCommentUtf8(comment.toUtf8().constData());
+
+ QGpgME::QByteArrayDataProvider dp;
+ Data data(&dp);
+ assert(!data.isNull());
+ const Error err = ctx->edit(key, std::unique_ptr<EditInteractor> (gau), data);
+ Error ae;
+ const QString log = _detail::audit_log_as_html(ctx, ae);
+ return std::make_tuple(err, log, ae);
+}
+
+Error QGpgMEAddUserIDJob::start(const Key &key, const QString &name, const QString &email, const QString &comment)
+{
+ run(std::bind(&add_user_id, std::placeholders::_1, key, name, email, comment));
+ return Error();
+}
+#include "qgpgmeadduseridjob.moc"
diff --git a/lang/qt/src/qgpgmeadduseridjob.h b/lang/qt/src/qgpgmeadduseridjob.h
new file mode 100644
index 0000000..294eb6c
--- /dev/null
+++ b/lang/qt/src/qgpgmeadduseridjob.h
@@ -0,0 +1,65 @@
+/*
+ qgpgmeadduseridjob.h
+
+ This file is part of qgpgme, the Qt API binding for gpgme
+ Copyright (c) 2008 Klarälvdalens Datakonsult AB
+ Copyright (c) 2016 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.
+*/
+
+#ifndef __QGPGME_QGPGMEADDUSERIDJOB_H__
+#define __QGPGME_QGPGMEADDUSERIDJOB_H__
+
+#include "adduseridjob.h"
+
+#include "threadedjobmixin.h"
+
+namespace QGpgME
+{
+
+class QGpgMEAddUserIDJob
+#ifdef Q_MOC_RUN
+ : public AddUserIDJob
+#else
+ : public _detail::ThreadedJobMixin<AddUserIDJob>
+#endif
+{
+ Q_OBJECT
+#ifdef Q_MOC_RUN
+private Q_SLOTS:
+ void slotFinished();
+#endif
+public:
+ explicit QGpgMEAddUserIDJob(GpgME::Context *context);
+ ~QGpgMEAddUserIDJob();
+
+ /* from AddUserIDJob */
+ GpgME::Error start(const GpgME::Key &key, const QString &name, const QString &email, const QString &comment) Q_DECL_OVERRIDE;
+};
+}
+
+#endif // __QGPGME_QGPGMEADDUSERIDJOB_H__
diff --git a/lang/qt/src/qgpgmebackend.cpp b/lang/qt/src/qgpgmebackend.cpp
new file mode 100644
index 0000000..797e58a
--- /dev/null
+++ b/lang/qt/src/qgpgmebackend.cpp
@@ -0,0 +1,203 @@
+/*
+ qgpgmebackend.cpp
+
+ This file is part of qgpgme, the Qt API binding for gpgme
+ Copyright (c) 2004,2005 Klarälvdalens Datakonsult AB
+ Copyright (c) 2016 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.
+*/
+
+#include "qgpgmebackend.h"
+
+
+#include "error.h"
+#include "engineinfo.h"
+
+#include "protocol_p.h"
+
+#include <QFile>
+#include <QString>
+
+const char QGpgME::QGpgMEBackend::OpenPGP[] = "OpenPGP";
+const char QGpgME::QGpgMEBackend::SMIME[] = "SMIME";
+
+
+QGpgME::QGpgMEBackend::QGpgMEBackend()
+ : mCryptoConfig(0),
+ mOpenPGPProtocol(0),
+ mSMIMEProtocol(0)
+{
+ GpgME::initializeLibrary();
+}
+
+QGpgME::QGpgMEBackend::~QGpgMEBackend()
+{
+ delete mCryptoConfig; mCryptoConfig = 0;
+ delete mOpenPGPProtocol; mOpenPGPProtocol = 0;
+ delete mSMIMEProtocol; mSMIMEProtocol = 0;
+}
+
+QString QGpgME::QGpgMEBackend::name() const
+{
+ return QStringLiteral("gpgme");
+}
+
+QString QGpgME::QGpgMEBackend::displayName() const
+{
+ return QStringLiteral("GpgME");
+}
+
+QGpgME::CryptoConfig *QGpgME::QGpgMEBackend::config() const
+{
+ if (!mCryptoConfig) {
+ if (GpgME::hasFeature(GpgME::GpgConfEngineFeature, 0)) {
+ mCryptoConfig = new QGpgMENewCryptoConfig;
+ }
+ }
+ return mCryptoConfig;
+}
+
+static bool check(GpgME::Protocol proto, QString *reason)
+{
+ if (!GpgME::checkEngine(proto)) {
+ return true;
+ }
+ if (!reason) {
+ return false;
+ }
+ // error, check why:
+#if 0
+Port away from localised string or delete.
+ const GpgME::EngineInfo ei = GpgME::engineInfo(proto);
+ if (ei.isNull()) {
+ *reason = i18n("GPGME was compiled without support for %1.", proto == GpgME::CMS ? QLatin1String("S/MIME") : QLatin1String("OpenPGP"));
+ } else if (ei.fileName() && !ei.version()) {
+ *reason = i18n("Engine %1 is not installed properly.", QFile::decodeName(ei.fileName()));
+ } else if (ei.fileName() && ei.version() && ei.requiredVersion())
+ *reason = i18n("Engine %1 version %2 installed, "
+ "but at least version %3 is required.",
+ QFile::decodeName(ei.fileName()), QLatin1String(ei.version()), QLatin1String(ei.requiredVersion()));
+ else {
+ *reason = i18n("Unknown problem with engine for protocol %1.", proto == GpgME::CMS ? QLatin1String("S/MIME") : QLatin1String("OpenPGP"));
+ }
+#endif
+ return false;
+}
+
+bool QGpgME::QGpgMEBackend::checkForOpenPGP(QString *reason) const
+{
+ return check(GpgME::OpenPGP, reason);
+}
+
+bool QGpgME::QGpgMEBackend::checkForSMIME(QString *reason) const
+{
+ return check(GpgME::CMS, reason);
+}
+
+bool QGpgME::QGpgMEBackend::checkForProtocol(const char *name, QString *reason) const
+{
+ if (qstricmp(name, OpenPGP) == 0) {
+ return check(GpgME::OpenPGP, reason);
+ }
+ if (qstricmp(name, SMIME) == 0) {
+ return check(GpgME::CMS, reason);
+ }
+ if (reason) {
+ *reason = QStringLiteral("Unsupported protocol \"%1\"").arg(QLatin1String(name));
+ }
+ return false;
+}
+
+QGpgME::Protocol *QGpgME::QGpgMEBackend::openpgp() const
+{
+ if (!mOpenPGPProtocol)
+ if (checkForOpenPGP()) {
+ mOpenPGPProtocol = new ::Protocol(GpgME::OpenPGP);
+ }
+ return mOpenPGPProtocol;
+}
+
+QGpgME::Protocol *QGpgME::QGpgMEBackend::smime() const
+{
+ if (!mSMIMEProtocol)
+ if (checkForSMIME()) {
+ mSMIMEProtocol = new ::Protocol(GpgME::CMS);
+ }
+ return mSMIMEProtocol;
+}
+
+QGpgME::Protocol *QGpgME::QGpgMEBackend::protocol(const char *name) const
+{
+ if (qstricmp(name, OpenPGP) == 0) {
+ return openpgp();
+ }
+ if (qstricmp(name, SMIME) == 0) {
+ return smime();
+ }
+ return 0;
+}
+
+bool QGpgME::QGpgMEBackend::supportsProtocol(const char *name) const
+{
+ return qstricmp(name, OpenPGP) == 0 || qstricmp(name, SMIME) == 0;
+}
+
+const char *QGpgME::QGpgMEBackend::enumerateProtocols(int i) const
+{
+ switch (i) {
+ case 0: return OpenPGP;
+ case 1: return SMIME;
+ default: return 0;
+ }
+}
+
+static QGpgME::QGpgMEBackend *gpgmeBackend;
+
+QGpgME::CryptoConfig *QGpgME::cryptoConfig()
+{
+ if (!gpgmeBackend) {
+ gpgmeBackend = new QGpgME::QGpgMEBackend();
+ }
+ return gpgmeBackend->config();
+
+}
+
+QGpgME::Protocol *QGpgME::openpgp()
+{
+ if (!gpgmeBackend) {
+ gpgmeBackend = new QGpgME::QGpgMEBackend();
+ }
+ return gpgmeBackend->openpgp();
+}
+
+QGpgME::Protocol *QGpgME::smime()
+{
+ if (!gpgmeBackend) {
+ gpgmeBackend = new QGpgME::QGpgMEBackend();
+ }
+ return gpgmeBackend->smime();
+}
diff --git a/lang/qt/src/qgpgmebackend.h b/lang/qt/src/qgpgmebackend.h
new file mode 100644
index 0000000..cca8b71
--- /dev/null
+++ b/lang/qt/src/qgpgmebackend.h
@@ -0,0 +1,92 @@
+/*
+ qgpgmebackend.h
+
+ This file is part of qgpgme, the Qt API binding for gpgme
+ Copyright (c) 2004,2005 Klarälvdalens Datakonsult AB
+ Copyright (c) 2016 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.
+*/
+
+#ifndef __QGPGME_QGPGMEBACKEND_H__
+#define __QGPGME_QGPGMEBACKEND_H__
+
+#include <QString>
+
+#include "protocol.h"
+
+class QString;
+template <typename T_Key, typename T_Value> class QMap;
+
+namespace QGpgME
+{
+class CryptoConfig;
+class Protocol;
+
+
+class QGpgMEBackend
+{
+public:
+ QGpgMEBackend();
+ ~QGpgMEBackend();
+
+ QString name() const;
+ QString displayName() const;
+
+ CryptoConfig *config() const;
+
+ Protocol *openpgp() const;
+ Protocol *smime() const;
+ Protocol *protocol(const char *name) const;
+
+ static const char OpenPGP[];
+ static const char SMIME[];
+
+ bool checkForOpenPGP(QString *reason = Q_NULLPTR) const;
+ bool checkForSMIME(QString *reason = Q_NULLPTR) const;
+ bool checkForProtocol(const char *name, QString *reason) const;
+
+ bool supportsOpenPGP() const
+ {
+ return true;
+ }
+ bool supportsSMIME() const
+ {
+ return true;
+ }
+ bool supportsProtocol(const char *name) const;
+
+ const char *enumerateProtocols(int i) const;
+
+private:
+ mutable QGpgME::CryptoConfig *mCryptoConfig;
+ mutable Protocol *mOpenPGPProtocol;
+ mutable Protocol *mSMIMEProtocol;
+};
+
+}
+
+#endif // __QGPGME_QGPGMEBACKEND_H__
diff --git a/lang/qt/src/qgpgmechangeexpiryjob.cpp b/lang/qt/src/qgpgmechangeexpiryjob.cpp
new file mode 100644
index 0000000..43ceee3
--- /dev/null
+++ b/lang/qt/src/qgpgmechangeexpiryjob.cpp
@@ -0,0 +1,80 @@
+/*
+ qgpgmechangeexpiryjob.cpp
+
+ This file is part of qgpgme, the Qt API binding for gpgme
+ Copyright (c) 2008 Klarälvdalens Datakonsult AB
+ Copyright (c) 2016 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.
+*/
+
+#include "qgpgmechangeexpiryjob.h"
+
+#include "dataprovider.h"
+
+#include "context.h"
+#include "data.h"
+#include "gpgsetexpirytimeeditinteractor.h"
+#include "key.h"
+
+#include <QDateTime>
+
+#include <cassert>
+#include <memory>
+#include <string>
+
+using namespace QGpgME;
+using namespace GpgME;
+
+QGpgMEChangeExpiryJob::QGpgMEChangeExpiryJob(Context *context)
+ : mixin_type(context)
+{
+ lateInitialization();
+}
+
+QGpgMEChangeExpiryJob::~QGpgMEChangeExpiryJob() {}
+
+static QGpgMEChangeExpiryJob::result_type change_expiry(Context *ctx, const Key &key, const QDateTime &expiry)
+{
+ EditInteractor *ei = expiry.isValid()
+ ? new GpgSetExpiryTimeEditInteractor(expiry.date().toString(Qt::ISODate).toStdString())
+ : new GpgSetExpiryTimeEditInteractor();
+
+ QGpgME::QByteArrayDataProvider dp;
+ Data data(&dp);
+ assert(!data.isNull());
+ const Error err = ctx->edit(key, std::unique_ptr<EditInteractor> (ei), data);
+ Error ae;
+ const QString log = _detail::audit_log_as_html(ctx, ae);
+ return std::make_tuple(err, log, ae);
+}
+
+Error QGpgMEChangeExpiryJob::start(const Key &key, const QDateTime &expiry)
+{
+ run(std::bind(&change_expiry, std::placeholders::_1, key, expiry));
+ return Error();
+}
+#include "qgpgmechangeexpiryjob.moc"
diff --git a/lang/qt/src/qgpgmechangeexpiryjob.h b/lang/qt/src/qgpgmechangeexpiryjob.h
new file mode 100644
index 0000000..4abdf78
--- /dev/null
+++ b/lang/qt/src/qgpgmechangeexpiryjob.h
@@ -0,0 +1,66 @@
+/*
+ qgpgmechangeexpiryjob.h
+
+ This file is part of qgpgme, the Qt API binding for gpgme
+ Copyright (c) 2008 Klarälvdalens Datakonsult AB
+ Copyright (c) 2016 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.
+*/
+
+#ifndef __QGPGME_QGPGMECHANGEEXPIRYJOB_H__
+#define __QGPGME_QGPGMECHANGEEXPIRYJOB_H__
+
+#include "changeexpiryjob.h"
+
+#include "threadedjobmixin.h"
+
+namespace QGpgME
+{
+
+class QGpgMEChangeExpiryJob
+#ifdef Q_MOC_RUN
+ : public ChangeExpiryJob
+#else
+ : public _detail::ThreadedJobMixin<ChangeExpiryJob>
+#endif
+{
+ Q_OBJECT
+#ifdef Q_MOC_RUN
+private Q_SLOTS:
+ void slotFinished();
+#endif
+public:
+ explicit QGpgMEChangeExpiryJob(GpgME::Context *context);
+ ~QGpgMEChangeExpiryJob();
+
+ /* from ChangeExpiryJob */
+ GpgME::Error start(const GpgME::Key &key, const QDateTime &expiry) Q_DECL_OVERRIDE;
+};
+
+}
+
+#endif // __QGPGME_QGPGMECHANGEEXPIRYJOB_H__
diff --git a/lang/qt/src/qgpgmechangeownertrustjob.cpp b/lang/qt/src/qgpgmechangeownertrustjob.cpp
new file mode 100644
index 0000000..55131d9
--- /dev/null
+++ b/lang/qt/src/qgpgmechangeownertrustjob.cpp
@@ -0,0 +1,76 @@
+/*
+ qgpgmechangeownertrustjob.cpp
+
+ This file is part of qgpgme, the Qt API binding for gpgme
+ Copyright (c) 2008 Klarälvdalens Datakonsult AB
+ Copyright (c) 2016 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.
+*/
+
+#include "qgpgmechangeownertrustjob.h"
+
+#include "dataprovider.h"
+
+#include "context.h"
+#include "data.h"
+#include "gpgsetownertrusteditinteractor.h"
+#include "key.h"
+
+#include <cassert>
+#include <memory>
+
+using namespace QGpgME;
+using namespace GpgME;
+
+QGpgMEChangeOwnerTrustJob::QGpgMEChangeOwnerTrustJob(Context *context)
+ : mixin_type(context)
+{
+ lateInitialization();
+}
+
+QGpgMEChangeOwnerTrustJob::~QGpgMEChangeOwnerTrustJob() {}
+
+static QGpgMEChangeOwnerTrustJob::result_type change_ownertrust(Context *ctx, const Key &key, Key::OwnerTrust trust)
+{
+ EditInteractor *ei = new GpgSetOwnerTrustEditInteractor(trust);
+
+ QGpgME::QByteArrayDataProvider dp;
+ Data data(&dp);
+ assert(!data.isNull());
+
+ const Error err = ctx->edit(key, std::unique_ptr<EditInteractor>(ei), data);
+ Error ae;
+ const QString log = _detail::audit_log_as_html(ctx, ae);
+ return std::make_tuple(err, log, ae);
+}
+
+Error QGpgMEChangeOwnerTrustJob::start(const Key &key, Key::OwnerTrust trust)
+{
+ run(std::bind(&change_ownertrust, std::placeholders::_1, key, trust));
+ return Error();
+}
+#include "qgpgmechangeownertrustjob.moc"
diff --git a/lang/qt/src/qgpgmechangeownertrustjob.h b/lang/qt/src/qgpgmechangeownertrustjob.h
new file mode 100644
index 0000000..7740616
--- /dev/null
+++ b/lang/qt/src/qgpgmechangeownertrustjob.h
@@ -0,0 +1,65 @@
+/*
+ qgpgmechangeexpiryjob.h
+
+ This file is part of qgpgme, the Qt API binding for gpgme
+ Copyright (c) 2008 Klarälvdalens Datakonsult AB
+ Copyright (c) 2016 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.
+*/
+
+#ifndef __QGPGME_QGPGMECHANGEOWNERTRUSTJOB_H__
+#define __QGPGME_QGPGMECHANGEOWNERTRUSTJOB_H__
+
+#include "changeownertrustjob.h"
+
+#include "threadedjobmixin.h"
+
+namespace QGpgME
+{
+
+class QGpgMEChangeOwnerTrustJob
+#ifdef Q_MOC_RUN
+ : public ChangeOwnerTrustJob
+#else
+ : public _detail::ThreadedJobMixin<ChangeOwnerTrustJob>
+#endif
+{
+ Q_OBJECT
+#ifdef Q_MOC_RUN
+private Q_SLOTS:
+ void slotFinished();
+#endif
+public:
+ explicit QGpgMEChangeOwnerTrustJob(GpgME::Context *context);
+ ~QGpgMEChangeOwnerTrustJob();
+
+ /* from ChangeOwnerTrustJob */
+ GpgME::Error start(const GpgME::Key &key, GpgME::Key::OwnerTrust trust) Q_DECL_OVERRIDE;
+};
+}
+
+#endif // __QGPGME_QGPGMECHANGEOWNERTRUSTJOB_H__
diff --git a/lang/qt/src/qgpgmechangepasswdjob.cpp b/lang/qt/src/qgpgmechangepasswdjob.cpp
new file mode 100644
index 0000000..0aec927
--- /dev/null
+++ b/lang/qt/src/qgpgmechangepasswdjob.cpp
@@ -0,0 +1,79 @@
+/*
+ qgpgmechangepasswdjob.cpp
+
+ This file is part of qgpgme, the Qt API binding for gpgme
+ Copyright (c) 2010 Klarälvdalens Datakonsult AB
+ Copyright (c) 2016 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.
+*/
+
+#include "qgpgmechangepasswdjob.h"
+
+#include "dataprovider.h"
+
+#include "context.h"
+#include "data.h"
+#include "key.h"
+
+#include <cassert>
+#include <memory>
+
+using namespace QGpgME;
+using namespace GpgME;
+
+QGpgMEChangePasswdJob::QGpgMEChangePasswdJob(Context *context)
+ : mixin_type(context)
+{
+ lateInitialization();
+}
+
+QGpgMEChangePasswdJob::~QGpgMEChangePasswdJob() {}
+
+static QGpgMEChangePasswdJob::result_type change_passwd(Context *ctx, const Key &key)
+{
+#if 0 // in case we want to fall back to edit interactor for gpg...
+ std::unique_ptr<EditInteractor> ei(new GpgChangePasswdEditInteractor);
+
+ QGpgME::QByteArrayDataProvider dp;
+ Data data(&dp);
+ assert(!data.isNull());
+ const Error err = ctx->edit(key, ei, data);
+#else
+ const Error err = ctx->passwd(key);
+#endif
+ Error ae;
+ const QString log = _detail::audit_log_as_html(ctx, ae);
+ return std::make_tuple(err, log, ae);
+}
+
+Error QGpgMEChangePasswdJob::start(const Key &key)
+{
+ run(std::bind(&change_passwd, std::placeholders::_1, key));
+ return Error();
+}
+
+#include "qgpgmechangepasswdjob.moc"
diff --git a/lang/qt/src/qgpgmechangepasswdjob.h b/lang/qt/src/qgpgmechangepasswdjob.h
new file mode 100644
index 0000000..e37789e
--- /dev/null
+++ b/lang/qt/src/qgpgmechangepasswdjob.h
@@ -0,0 +1,66 @@
+/*
+ qgpgmechangepasswdjob.h
+
+ This file is part of qgpgme, the Qt API binding for gpgme
+ Copyright (c) 2010 Klarälvdalens Datakonsult AB
+ Copyright (c) 2016 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.
+*/
+
+#ifndef __QGPGME_QGPGMECHANGEPASSWDJOB_H__
+#define __QGPGME_QGPGMECHANGEPASSWDJOB_H__
+
+#include "changepasswdjob.h"
+
+#include "threadedjobmixin.h"
+
+namespace QGpgME
+{
+
+class QGpgMEChangePasswdJob
+#ifdef Q_MOC_RUN
+ : public ChangePasswdJob
+#else
+ : public _detail::ThreadedJobMixin<ChangePasswdJob>
+#endif
+{
+ Q_OBJECT
+#ifdef Q_MOC_RUN
+private Q_SLOTS:
+ void slotFinished();
+#endif
+public:
+ explicit QGpgMEChangePasswdJob(GpgME::Context *context);
+ ~QGpgMEChangePasswdJob();
+
+ /* from ChangePasswdJob */
+ GpgME::Error start(const GpgME::Key &key) Q_DECL_OVERRIDE;
+};
+
+}
+
+#endif // __QGPGME_QGPGMECHANGEPASSWDJOB_H__
diff --git a/lang/qt/src/qgpgmedecryptjob.cpp b/lang/qt/src/qgpgmedecryptjob.cpp
new file mode 100644
index 0000000..7116449
--- /dev/null
+++ b/lang/qt/src/qgpgmedecryptjob.cpp
@@ -0,0 +1,128 @@
+/*
+ qgpgmedecryptjob.cpp
+
+ This file is part of qgpgme, the Qt API binding for gpgme
+ Copyright (c) 2004,2008 Klarälvdalens Datakonsult AB
+ Copyright (c) 2016 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.
+*/
+
+#include "qgpgmedecryptjob.h"
+
+#include "dataprovider.h"
+
+#include "context.h"
+#include "decryptionresult.h"
+#include "data.h"
+
+#include <QBuffer>
+
+#include <cassert>
+
+using namespace QGpgME;
+using namespace GpgME;
+
+QGpgMEDecryptJob::QGpgMEDecryptJob(Context *context)
+ : mixin_type(context)
+{
+ lateInitialization();
+}
+
+QGpgMEDecryptJob::~QGpgMEDecryptJob() {}
+
+static QGpgMEDecryptJob::result_type decrypt(Context *ctx, QThread *thread,
+ const std::weak_ptr<QIODevice> &cipherText_,
+ const std::weak_ptr<QIODevice> &plainText_)
+{
+
+ const std::shared_ptr<QIODevice> cipherText = cipherText_.lock();
+ const std::shared_ptr<QIODevice> plainText = plainText_.lock();
+
+ const _detail::ToThreadMover ctMover(cipherText, thread);
+ const _detail::ToThreadMover ptMover(plainText, thread);
+
+ QGpgME::QIODeviceDataProvider in(cipherText);
+ const Data indata(&in);
+
+ if (!plainText) {
+ QGpgME::QByteArrayDataProvider out;
+ Data outdata(&out);
+
+ const DecryptionResult res = ctx->decrypt(indata, outdata);
+ Error ae;
+ const QString log = _detail::audit_log_as_html(ctx, ae);
+ return std::make_tuple(res, out.data(), log, ae);
+ } else {
+ QGpgME::QIODeviceDataProvider out(plainText);
+ Data outdata(&out);
+
+ const DecryptionResult res = ctx->decrypt(indata, outdata);
+ Error ae;
+ const QString log = _detail::audit_log_as_html(ctx, ae);
+ return std::make_tuple(res, QByteArray(), log, ae);
+ }
+
+}
+
+static QGpgMEDecryptJob::result_type decrypt_qba(Context *ctx, const QByteArray &cipherText)
+{
+ const std::shared_ptr<QBuffer> buffer(new QBuffer);
+ buffer->setData(cipherText);
+ if (!buffer->open(QIODevice::ReadOnly)) {
+ assert(!"This should never happen: QBuffer::open() failed");
+ }
+ return decrypt(ctx, 0, buffer, std::shared_ptr<QIODevice>());
+}
+
+Error QGpgMEDecryptJob::start(const QByteArray &cipherText)
+{
+ run(std::bind(&decrypt_qba, std::placeholders::_1, cipherText));
+ return Error();
+}
+
+void QGpgMEDecryptJob::start(const std::shared_ptr<QIODevice> &cipherText, const std::shared_ptr<QIODevice> &plainText)
+{
+ run(std::bind(&decrypt, std::placeholders::_1, std::placeholders::_2, std::placeholders::_3, std::placeholders::_4), cipherText, plainText);
+}
+
+GpgME::DecryptionResult QGpgME::QGpgMEDecryptJob::exec(const QByteArray &cipherText,
+ QByteArray &plainText)
+{
+ const result_type r = decrypt_qba(context(), cipherText);
+ plainText = std::get<1>(r);
+ resultHook(r);
+ return mResult;
+}
+
+//PENDING(marc) implement showErrorDialog()
+
+void QGpgMEDecryptJob::resultHook(const result_type &tuple)
+{
+ mResult = std::get<0>(tuple);
+}
+
+#include "qgpgmedecryptjob.moc"
diff --git a/lang/qt/src/qgpgmedecryptjob.h b/lang/qt/src/qgpgmedecryptjob.h
new file mode 100644
index 0000000..5335e84
--- /dev/null
+++ b/lang/qt/src/qgpgmedecryptjob.h
@@ -0,0 +1,84 @@
+/*
+ qgpgmedecryptjob.h
+
+ This file is part of qgpgme, the Qt API binding for gpgme
+ Copyright (c) 2004,2008 Klarälvdalens Datakonsult AB
+ Copyright (c) 2016 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.
+*/
+
+#ifndef __QGPGME_QGPGMEDECRYPTJOB_H__
+#define __QGPGME_QGPGMEDECRYPTJOB_H__
+
+#include "decryptjob.h"
+
+#include "threadedjobmixin.h"
+
+#ifdef BUILDING_QGPGME
+# include "decryptionresult.h"
+#else
+#include <gpgme++/decryptionresult.h>
+#endif
+
+namespace QGpgME
+{
+
+class QGpgMEDecryptJob
+#ifdef Q_MOC_RUN
+ : public DecryptJob
+#else
+ : public _detail::ThreadedJobMixin<DecryptJob, std::tuple<GpgME::DecryptionResult, QByteArray, QString, GpgME::Error> >
+#endif
+{
+ Q_OBJECT
+#ifdef Q_MOC_RUN
+private Q_SLOTS:
+ void slotFinished();
+#endif
+public:
+ explicit QGpgMEDecryptJob(GpgME::Context *context);
+ ~QGpgMEDecryptJob();
+
+ /* from DecryptJob */
+ GpgME::Error start(const QByteArray &cipherText) Q_DECL_OVERRIDE;
+
+ /* from DecryptJob */
+ void start(const std::shared_ptr<QIODevice> &cipherText, const std::shared_ptr<QIODevice> &plainText) Q_DECL_OVERRIDE;
+
+ /* from DecryptJob */
+ GpgME::DecryptionResult exec(const QByteArray &cipherText,
+ QByteArray &plainText) Q_DECL_OVERRIDE;
+
+ /* from ThreadedJobMixin */
+ void resultHook(const result_type &r) Q_DECL_OVERRIDE;
+
+private:
+ GpgME::DecryptionResult mResult;
+};
+
+}
+#endif // __QGPGME_QGPGMEDECRYPTJOB_H__
diff --git a/lang/qt/src/qgpgmedecryptverifyjob.cpp b/lang/qt/src/qgpgmedecryptverifyjob.cpp
new file mode 100644
index 0000000..d46a9b5
--- /dev/null
+++ b/lang/qt/src/qgpgmedecryptverifyjob.cpp
@@ -0,0 +1,135 @@
+/*
+ qgpgmedecryptverifyjob.cpp
+
+ This file is part of qgpgme, the Qt API binding for gpgme
+ Copyright (c) 2004,2008 Klarälvdalens Datakonsult AB
+ Copyright (c) 2016 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.
+*/
+
+#include "qgpgmedecryptverifyjob.h"
+
+#include "dataprovider.h"
+
+#include "context.h"
+#include "decryptionresult.h"
+#include "verificationresult.h"
+#include "data.h"
+
+#include <QDebug>
+#include "gpgme_backend_debug.h"
+
+#include <QBuffer>
+
+#include <cassert>
+
+using namespace QGpgME;
+using namespace GpgME;
+
+QGpgMEDecryptVerifyJob::QGpgMEDecryptVerifyJob(Context *context)
+ : mixin_type(context)
+{
+ lateInitialization();
+}
+
+QGpgMEDecryptVerifyJob::~QGpgMEDecryptVerifyJob() {}
+
+static QGpgMEDecryptVerifyJob::result_type decrypt_verify(Context *ctx, QThread *thread,
+ const std::weak_ptr<QIODevice> &cipherText_,
+ const std::weak_ptr<QIODevice> &plainText_)
+{
+
+ qCDebug(GPGPME_BACKEND_LOG);
+
+ const std::shared_ptr<QIODevice> cipherText = cipherText_.lock();
+ const std::shared_ptr<QIODevice> plainText = plainText_.lock();
+
+ const _detail::ToThreadMover ctMover(cipherText, thread);
+ const _detail::ToThreadMover ptMover(plainText, thread);
+
+ QGpgME::QIODeviceDataProvider in(cipherText);
+ const Data indata(&in);
+
+ if (!plainText) {
+ QGpgME::QByteArrayDataProvider out;
+ Data outdata(&out);
+
+ const std::pair<DecryptionResult, VerificationResult> res = ctx->decryptAndVerify(indata, outdata);
+ Error ae;
+ const QString log = _detail::audit_log_as_html(ctx, ae);
+ qCDebug(GPGPME_BACKEND_LOG) << "End no plainText. Error: " << ae;
+ return std::make_tuple(res.first, res.second, out.data(), log, ae);
+ } else {
+ QGpgME::QIODeviceDataProvider out(plainText);
+ Data outdata(&out);
+
+ const std::pair<DecryptionResult, VerificationResult> res = ctx->decryptAndVerify(indata, outdata);
+ Error ae;
+ const QString log = _detail::audit_log_as_html(ctx, ae);
+ qCDebug(GPGPME_BACKEND_LOG) << "End plainText. Error: " << ae;
+ return std::make_tuple(res.first, res.second, QByteArray(), log, ae);
+ }
+
+}
+
+static QGpgMEDecryptVerifyJob::result_type decrypt_verify_qba(Context *ctx, const QByteArray &cipherText)
+{
+ const std::shared_ptr<QBuffer> buffer(new QBuffer);
+ buffer->setData(cipherText);
+ if (!buffer->open(QIODevice::ReadOnly)) {
+ assert(!"This should never happen: QBuffer::open() failed");
+ }
+ return decrypt_verify(ctx, 0, buffer, std::shared_ptr<QIODevice>());
+}
+
+Error QGpgMEDecryptVerifyJob::start(const QByteArray &cipherText)
+{
+ run(std::bind(&decrypt_verify_qba, std::placeholders::_1, cipherText));
+ return Error();
+}
+
+void QGpgMEDecryptVerifyJob::start(const std::shared_ptr<QIODevice> &cipherText, const std::shared_ptr<QIODevice> &plainText)
+{
+ run(std::bind(&decrypt_verify, std::placeholders::_1, std::placeholders::_2, std::placeholders::_3, std::placeholders::_4), cipherText, plainText);
+}
+
+std::pair<GpgME::DecryptionResult, GpgME::VerificationResult>
+QGpgME::QGpgMEDecryptVerifyJob::exec(const QByteArray &cipherText, QByteArray &plainText)
+{
+ const result_type r = decrypt_verify_qba(context(), cipherText);
+ plainText = std::get<2>(r);
+ resultHook(r);
+ return mResult;
+}
+
+//PENDING(marc) implement showErrorDialog()
+
+void QGpgMEDecryptVerifyJob::resultHook(const result_type &tuple)
+{
+ mResult = std::make_pair(std::get<0>(tuple), std::get<1>(tuple));
+}
+#include "qgpgmedecryptverifyjob.moc"
diff --git a/lang/qt/src/qgpgmedecryptverifyjob.h b/lang/qt/src/qgpgmedecryptverifyjob.h
new file mode 100644
index 0000000..de2bce7
--- /dev/null
+++ b/lang/qt/src/qgpgmedecryptverifyjob.h
@@ -0,0 +1,89 @@
+/*
+ qgpgmedecryptverifyjob.h
+
+ This file is part of qgpgme, the Qt API binding for gpgme
+ Copyright (c) 2004,2008 Klarälvdalens Datakonsult AB
+ Copyright (c) 2016 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.
+*/
+
+#ifndef __QGPGME_QGPGMEDECRYPTVERIFYJOB_H__
+#define __QGPGME_QGPGMEDECRYPTVERIFYJOB_H__
+
+#include "decryptverifyjob.h"
+
+#include "threadedjobmixin.h"
+
+#ifdef BUILDING_QGPGME
+# include "decryptionresult.h"
+#else
+#include <gpgme++/decryptionresult.h>
+#endif
+#ifdef BUILDING_QGPGME
+# include "verificationresult.h"
+#else
+#include <gpgme++/verificationresult.h>
+#endif
+
+namespace QGpgME
+{
+
+class QGpgMEDecryptVerifyJob
+#ifdef Q_MOC_RUN
+ : public DecryptVerifyJob
+#else
+ : public _detail::ThreadedJobMixin<DecryptVerifyJob, std::tuple<GpgME::DecryptionResult, GpgME::VerificationResult, QByteArray, QString, GpgME::Error> >
+#endif
+{
+ Q_OBJECT
+#ifdef Q_MOC_RUN
+private Q_SLOTS:
+ void slotFinished();
+#endif
+public:
+ explicit QGpgMEDecryptVerifyJob(GpgME::Context *context);
+ ~QGpgMEDecryptVerifyJob();
+
+ /* from DecryptVerifyJob */
+ GpgME::Error start(const QByteArray &cipherText) Q_DECL_OVERRIDE;
+
+ /* from DecryptVerifyJob */
+ void start(const std::shared_ptr<QIODevice> &cipherText, const std::shared_ptr<QIODevice> &plainText) Q_DECL_OVERRIDE;
+
+ /* from DecryptVerifyJob */
+ std::pair<GpgME::DecryptionResult, GpgME::VerificationResult>
+ exec(const QByteArray &cipherText, QByteArray &plainText) Q_DECL_OVERRIDE;
+
+ /* from ThreadedJobMixin */
+ void resultHook(const result_type &r) Q_DECL_OVERRIDE;
+
+private:
+ std::pair<GpgME::DecryptionResult, GpgME::VerificationResult> mResult;
+};
+
+}
+#endif // __QGPGME_QGPGMEDECRYPTVERIFYJOB_H__
diff --git a/lang/qt/src/qgpgmedeletejob.cpp b/lang/qt/src/qgpgmedeletejob.cpp
new file mode 100644
index 0000000..323aec4
--- /dev/null
+++ b/lang/qt/src/qgpgmedeletejob.cpp
@@ -0,0 +1,65 @@
+/*
+ qgpgmedeletejob.cpp
+
+ This file is part of qgpgme, the Qt API binding for gpgme
+ Copyright (c) 2004,2008 Klarälvdalens Datakonsult AB
+ Copyright (c) 2016 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.
+*/
+
+#include "qgpgmedeletejob.h"
+
+#include "context.h"
+#include "key.h"
+
+#include <cassert>
+
+using namespace QGpgME;
+using namespace GpgME;
+
+QGpgMEDeleteJob::QGpgMEDeleteJob(Context *context)
+ : mixin_type(context)
+{
+ lateInitialization();
+}
+
+QGpgMEDeleteJob::~QGpgMEDeleteJob() {}
+
+static QGpgMEDeleteJob::result_type delete_key(Context *ctx, const Key &key, bool allowSecretKeyDeletion)
+{
+ const Error err = ctx->deleteKey(key, allowSecretKeyDeletion);
+ Error ae;
+ const QString log = _detail::audit_log_as_html(ctx, ae);
+ return std::make_tuple(err, log, ae);
+}
+
+Error QGpgMEDeleteJob::start(const Key &key, bool allowSecretKeyDeletion)
+{
+ run(std::bind(&delete_key, std::placeholders::_1, key, allowSecretKeyDeletion));
+ return Error();
+}
+#include "qgpgmedeletejob.moc"
diff --git a/lang/qt/src/qgpgmedeletejob.h b/lang/qt/src/qgpgmedeletejob.h
new file mode 100644
index 0000000..992442f
--- /dev/null
+++ b/lang/qt/src/qgpgmedeletejob.h
@@ -0,0 +1,71 @@
+/*
+ qgpgmedeletejob.h
+
+ This file is part of qgpgme, the Qt API binding for gpgme
+ Copyright (c) 2004,2008 Klarälvdalens Datakonsult AB
+ Copyright (c) 2016 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.
+*/
+
+#ifndef __QGPGME_QGPGMEDELETEJOB_H__
+#define __QGPGME_QGPGMEDELETEJOB_H__
+
+#include "deletejob.h"
+
+#include "threadedjobmixin.h"
+
+namespace GpgME
+{
+class Key;
+}
+
+namespace QGpgME
+{
+
+class QGpgMEDeleteJob
+#ifdef Q_MOC_RUN
+ : public DeleteJob
+#else
+ : public _detail::ThreadedJobMixin<DeleteJob>
+#endif
+{
+ Q_OBJECT
+#ifdef Q_MOC_RUN
+public Q_SLOTS:
+ void slotFinished();
+#endif
+public:
+ explicit QGpgMEDeleteJob(GpgME::Context *context);
+ ~QGpgMEDeleteJob();
+
+ /* from DeleteJob */
+ GpgME::Error start(const GpgME::Key &key, bool allowSecretKeyDeletion) Q_DECL_OVERRIDE;
+};
+
+}
+
+#endif // __QGPGME_QGPGMEDELETEJOB_H__
diff --git a/lang/qt/src/qgpgmedownloadjob.cpp b/lang/qt/src/qgpgmedownloadjob.cpp
new file mode 100644
index 0000000..48cc907
--- /dev/null
+++ b/lang/qt/src/qgpgmedownloadjob.cpp
@@ -0,0 +1,100 @@
+/*
+ qgpgmedownloadjob.cpp
+
+ This file is part of qgpgme, the Qt API binding for gpgme
+ Copyright (c) 2004,2008 Klarälvdalens Datakonsult AB
+ Copyright (c) 2016 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.
+*/
+
+#include "qgpgmedownloadjob.h"
+
+#include "dataprovider.h"
+
+#include "context.h"
+#include "data.h"
+
+#include <QStringList>
+
+#include <cassert>
+
+using namespace QGpgME;
+using namespace GpgME;
+
+QGpgMEDownloadJob::QGpgMEDownloadJob(Context *context)
+ : mixin_type(context)
+{
+ lateInitialization();
+}
+
+QGpgMEDownloadJob::~QGpgMEDownloadJob() {}
+
+static QGpgMEDownloadJob::result_type download_qsl(Context *ctx, const QStringList &pats)
+{
+ QGpgME::QByteArrayDataProvider dp;
+ Data data(&dp);
+
+ const _detail::PatternConverter pc(pats);
+
+ const Error err = ctx->exportPublicKeys(pc.patterns(), data);
+ Error ae;
+ const QString log = _detail::audit_log_as_html(ctx, ae);
+ return std::make_tuple(err, dp.data(), log, ae);
+}
+
+static QGpgMEDownloadJob::result_type download(Context *ctx, QThread *thread, const QByteArray &fpr, const std::weak_ptr<QIODevice> &keyData_)
+{
+ const std::shared_ptr<QIODevice> keyData = keyData_.lock();
+ if (!keyData) {
+ return download_qsl(ctx, QStringList(QString::fromUtf8(fpr)));
+ }
+
+ const _detail::ToThreadMover kdMover(keyData, thread);
+
+ QGpgME::QIODeviceDataProvider dp(keyData);
+ Data data(&dp);
+
+ const _detail::PatternConverter pc(fpr);
+
+ const Error err = ctx->exportPublicKeys(pc.patterns(), data);
+ Error ae;
+ const QString log = _detail::audit_log_as_html(ctx, ae);
+ return std::make_tuple(err, QByteArray(), log, ae);
+}
+
+Error QGpgMEDownloadJob::start(const QStringList &pats)
+{
+ run(std::bind(&download_qsl, std::placeholders::_1, pats));
+ return Error();
+}
+
+Error QGpgMEDownloadJob::start(const QByteArray &fpr, const std::shared_ptr<QIODevice> &keyData)
+{
+ run(std::bind(&download, std::placeholders::_1, std::placeholders::_2, fpr, std::placeholders::_3), keyData);
+ return Error();
+}
+#include "qgpgmedownloadjob.moc"
diff --git a/lang/qt/src/qgpgmedownloadjob.h b/lang/qt/src/qgpgmedownloadjob.h
new file mode 100644
index 0000000..4091190
--- /dev/null
+++ b/lang/qt/src/qgpgmedownloadjob.h
@@ -0,0 +1,69 @@
+/*
+ qgpgmedownloadjob.h
+
+ This file is part of qgpgme, the Qt API binding for gpgme
+ Copyright (c) 2004,2008 Klarälvdalens Datakonsult AB
+ Copyright (c) 2016 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.
+*/
+
+#ifndef __QGPGME_QGPGMEDOWNLOADJOB_H__
+#define __QGPGME_QGPGMEDOWNLOADJOB_H__
+
+#include "downloadjob.h"
+
+#include "threadedjobmixin.h"
+
+namespace QGpgME
+{
+
+class QGpgMEDownloadJob
+#ifdef Q_MOC_RUN
+ : public DownloadJob
+#else
+ : public _detail::ThreadedJobMixin<DownloadJob, std::tuple<GpgME::Error, QByteArray, QString, GpgME::Error> >
+#endif
+{
+ Q_OBJECT
+#ifdef Q_MOC_RUN
+public Q_SLOTS:
+ void slotFinished();
+#endif
+public:
+ explicit QGpgMEDownloadJob(GpgME::Context *context);
+ ~QGpgMEDownloadJob();
+
+ /* from DownloadJob */
+ GpgME::Error start(const QStringList &fingerprints) Q_DECL_OVERRIDE;
+
+ /* from DownloadJob */
+ GpgME::Error start(const QByteArray &fingerprint, const std::shared_ptr<QIODevice> &keyData) Q_DECL_OVERRIDE;
+};
+
+}
+
+#endif // __QGPGME_QGPGMEDOWNLOADJOB_H__
diff --git a/lang/qt/src/qgpgmeencryptjob.cpp b/lang/qt/src/qgpgmeencryptjob.cpp
new file mode 100644
index 0000000..82c8ed8
--- /dev/null
+++ b/lang/qt/src/qgpgmeencryptjob.cpp
@@ -0,0 +1,170 @@
+/*
+ qgpgmeencryptjob.cpp
+
+ This file is part of qgpgme, the Qt API binding for gpgme
+ Copyright (c) 2004,2007,2008 Klarälvdalens Datakonsult AB
+ Copyright (c) 2016 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.
+*/
+
+#include "qgpgmeencryptjob.h"
+
+#include "dataprovider.h"
+
+#include "context.h"
+#include "encryptionresult.h"
+#include "data.h"
+
+#include <QBuffer>
+
+
+#include <cassert>
+
+using namespace QGpgME;
+using namespace GpgME;
+
+QGpgMEEncryptJob::QGpgMEEncryptJob(Context *context)
+ : mixin_type(context),
+ mOutputIsBase64Encoded(false)
+{
+ lateInitialization();
+}
+
+QGpgMEEncryptJob::~QGpgMEEncryptJob() {}
+
+void QGpgMEEncryptJob::setOutputIsBase64Encoded(bool on)
+{
+ mOutputIsBase64Encoded = on;
+}
+
+static QGpgMEEncryptJob::result_type encrypt(Context *ctx, QThread *thread,
+ const std::vector<Key> &recipients,
+ const std::weak_ptr<QIODevice> &plainText_,
+ const std::weak_ptr<QIODevice> &cipherText_,
+ const Context::EncryptionFlags eflags,
+ bool outputIsBsse64Encoded)
+{
+
+ const std::shared_ptr<QIODevice> plainText = plainText_.lock();
+ const std::shared_ptr<QIODevice> cipherText = cipherText_.lock();
+
+ const _detail::ToThreadMover ctMover(cipherText, thread);
+ const _detail::ToThreadMover ptMover(plainText, thread);
+
+ QGpgME::QIODeviceDataProvider in(plainText);
+ const Data indata(&in);
+
+ if (!cipherText) {
+ QGpgME::QByteArrayDataProvider out;
+ Data outdata(&out);
+
+ if (outputIsBsse64Encoded) {
+ outdata.setEncoding(Data::Base64Encoding);
+ }
+
+ const EncryptionResult res = ctx->encrypt(recipients, indata, outdata, eflags);
+ Error ae;
+ const QString log = _detail::audit_log_as_html(ctx, ae);
+ return std::make_tuple(res, out.data(), log, ae);
+ } else {
+ QGpgME::QIODeviceDataProvider out(cipherText);
+ Data outdata(&out);
+
+ if (outputIsBsse64Encoded) {
+ outdata.setEncoding(Data::Base64Encoding);
+ }
+
+ const EncryptionResult res = ctx->encrypt(recipients, indata, outdata, eflags);
+ Error ae;
+ const QString log = _detail::audit_log_as_html(ctx, ae);
+ return std::make_tuple(res, QByteArray(), log, ae);
+ }
+
+}
+
+static QGpgMEEncryptJob::result_type encrypt_qba(Context *ctx, const std::vector<Key> &recipients, const QByteArray &plainText, const Context::EncryptionFlags eflags, bool outputIsBsse64Encoded)
+{
+ const std::shared_ptr<QBuffer> buffer(new QBuffer);
+ buffer->setData(plainText);
+ if (!buffer->open(QIODevice::ReadOnly)) {
+ assert(!"This should never happen: QBuffer::open() failed");
+ }
+ return encrypt(ctx, 0, recipients, buffer, std::shared_ptr<QIODevice>(), eflags, outputIsBsse64Encoded);
+}
+
+Error QGpgMEEncryptJob::start(const std::vector<Key> &recipients, const QByteArray &plainText, bool alwaysTrust)
+{
+ run(std::bind(&encrypt_qba, std::placeholders::_1, recipients, plainText,
+ alwaysTrust ? Context::AlwaysTrust : Context::None, mOutputIsBase64Encoded));
+ return Error();
+}
+
+void QGpgMEEncryptJob::start(const std::vector<Key> &recipients, const std::shared_ptr<QIODevice> &plainText,
+ const std::shared_ptr<QIODevice> &cipherText, const Context::EncryptionFlags eflags)
+{
+ run(std::bind(&encrypt,
+ std::placeholders::_1, std::placeholders::_2,
+ recipients,
+ std::placeholders::_3, std::placeholders::_4,
+ eflags,
+ mOutputIsBase64Encoded),
+ plainText, cipherText);
+}
+
+EncryptionResult QGpgMEEncryptJob::exec(const std::vector<Key> &recipients, const QByteArray &plainText,
+ const Context::EncryptionFlags eflags, QByteArray &cipherText)
+{
+ const result_type r = encrypt_qba(context(), recipients, plainText, eflags, mOutputIsBase64Encoded);
+ cipherText = std::get<1>(r);
+ resultHook(r);
+ return mResult;
+}
+
+void QGpgMEEncryptJob::start(const std::vector<Key> &recipients, const std::shared_ptr<QIODevice> &plainText, const std::shared_ptr<QIODevice> &cipherText, bool alwaysTrust)
+{
+ return start(recipients, plainText, cipherText, alwaysTrust ? Context::AlwaysTrust : Context::None);
+}
+
+EncryptionResult QGpgMEEncryptJob::exec(const std::vector<Key> &recipients, const QByteArray &plainText, bool alwaysTrust, QByteArray &cipherText)
+{
+ return exec(recipients, plainText, alwaysTrust ? Context::AlwaysTrust : Context::None, cipherText);
+}
+
+void QGpgMEEncryptJob::resultHook(const result_type &tuple)
+{
+ mResult = std::get<0>(tuple);
+}
+
+#if 0
+void QGpgMEEncryptJob::showErrorDialog(QWidget *parent, const QString &caption) const
+{
+ if (mResult.error() && !mResult.error().isCanceled()) {
+ MessageBox::error(parent, mResult, this, caption);
+ }
+}
+#endif
+#include "qgpgmeencryptjob.moc"
diff --git a/lang/qt/src/qgpgmeencryptjob.h b/lang/qt/src/qgpgmeencryptjob.h
new file mode 100644
index 0000000..42c1c78
--- /dev/null
+++ b/lang/qt/src/qgpgmeencryptjob.h
@@ -0,0 +1,109 @@
+/*
+ qgpgmeencryptjob.h
+
+ This file is part of qgpgme, the Qt API binding for gpgme
+ Copyright (c) 2004,2007,2008 Klarälvdalens Datakonsult AB
+ Copyright (c) 2016 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.
+*/
+
+#ifndef __QGPGME_QGPGMEENCRYPTJOB_H__
+#define __QGPGME_QGPGMEENCRYPTJOB_H__
+
+#include "encryptjob.h"
+
+#include "threadedjobmixin.h"
+
+#ifdef BUILDING_QGPGME
+# include "encryptionresult.h"
+#else
+#include <gpgme++/encryptionresult.h>
+#endif
+#ifdef BUILDING_QGPGME
+# include "key.h"
+#else
+#include <gpgme++/key.h>
+#endif
+
+namespace QGpgME
+{
+
+class QGpgMEEncryptJob
+#ifdef Q_MOC_RUN
+ : public EncryptJob
+#else
+ : public _detail::ThreadedJobMixin<EncryptJob, std::tuple<GpgME::EncryptionResult, QByteArray, QString, GpgME::Error> >
+#endif
+{
+ Q_OBJECT
+#ifdef Q_MOC_RUN
+public Q_SLOTS:
+ void slotFinished();
+#endif
+public:
+ explicit QGpgMEEncryptJob(GpgME::Context *context);
+ ~QGpgMEEncryptJob();
+
+ /* from EncryptJob */
+ GpgME::Error start(const std::vector<GpgME::Key> &recipients,
+ const QByteArray &plainText, bool alwaysTrust) Q_DECL_OVERRIDE;
+
+ /* from EncryptJob */
+ void start(const std::vector<GpgME::Key> &recipients,
+ const std::shared_ptr<QIODevice> &plainText,
+ const std::shared_ptr<QIODevice> &cipherText,
+ bool alwaysTrust) Q_DECL_OVERRIDE;
+
+ /* from EncryptJob */
+ GpgME::EncryptionResult exec(const std::vector<GpgME::Key> &recipients,
+ const QByteArray &plainText, bool alwaysTrust,
+ QByteArray &cipherText) Q_DECL_OVERRIDE;
+ /* from EncryptJob */
+ void start(const std::vector<GpgME::Key> &recipients,
+ const std::shared_ptr<QIODevice> &plainText,
+ const std::shared_ptr<QIODevice> &cipherText,
+ const GpgME::Context::EncryptionFlags flags) Q_DECL_OVERRIDE;
+
+ /* from EncryptJob */
+ GpgME::EncryptionResult exec(const std::vector<GpgME::Key> &recipients,
+ const QByteArray &plainText, const GpgME::Context::EncryptionFlags flags,
+ QByteArray &cipherText) Q_DECL_OVERRIDE;
+
+ /* from EncryptJob */
+ void setOutputIsBase64Encoded(bool on) Q_DECL_OVERRIDE;
+
+ /* from ThreadedJobMixin */
+ void resultHook(const result_type &r) Q_DECL_OVERRIDE;
+
+private:
+ bool mOutputIsBase64Encoded;
+ GpgME::EncryptionResult mResult;
+};
+
+}
+
+#endif // __QGPGME_QGPGMEENCRYPTJOB_H__
diff --git a/lang/qt/src/qgpgmeexportjob.cpp b/lang/qt/src/qgpgmeexportjob.cpp
new file mode 100644
index 0000000..dfc5fc9
--- /dev/null
+++ b/lang/qt/src/qgpgmeexportjob.cpp
@@ -0,0 +1,76 @@
+/*
+ qgpgmeexportjob.cpp
+
+ This file is part of qgpgme, the Qt API binding for gpgme
+ Copyright (c) 2004,2008 Klarälvdalens Datakonsult AB
+ Copyright (c) 2016 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.
+*/
+
+#include "qgpgmeexportjob.h"
+
+#include "dataprovider.h"
+
+#include "context.h"
+#include "data.h"
+#include "key.h"
+
+#include <QStringList>
+
+#include <cassert>
+
+using namespace QGpgME;
+using namespace GpgME;
+
+QGpgMEExportJob::QGpgMEExportJob(Context *context)
+ : mixin_type(context)
+{
+ lateInitialization();
+}
+
+QGpgMEExportJob::~QGpgMEExportJob() {}
+
+static QGpgMEExportJob::result_type export_qba(Context *ctx, const QStringList &patterns)
+{
+
+ const _detail::PatternConverter pc(patterns);
+
+ QGpgME::QByteArrayDataProvider dp;
+ Data data(&dp);
+
+ const Error err = ctx->exportPublicKeys(pc.patterns(), data);
+ Error ae;
+ const QString log = _detail::audit_log_as_html(ctx, ae);
+ return std::make_tuple(err, dp.data(), log, ae);
+}
+
+Error QGpgMEExportJob::start(const QStringList &patterns)
+{
+ run(std::bind(&export_qba, std::placeholders::_1, patterns));
+ return Error();
+}
+#include "qgpgmeexportjob.moc"
diff --git a/lang/qt/src/qgpgmeexportjob.h b/lang/qt/src/qgpgmeexportjob.h
new file mode 100644
index 0000000..7561054
--- /dev/null
+++ b/lang/qt/src/qgpgmeexportjob.h
@@ -0,0 +1,66 @@
+/*
+ qgpgmeexportjob.h
+
+ This file is part of qgpgme, the Qt API binding for gpgme
+ Copyright (c) 2004,2008 Klarälvdalens Datakonsult AB
+ Copyright (c) 2016 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.
+*/
+
+#ifndef __QGPGME_QGPGMEEXPORTJOB_H__
+#define __QGPGME_QGPGMEEXPORTJOB_H__
+
+#include "exportjob.h"
+
+#include "threadedjobmixin.h"
+
+namespace QGpgME
+{
+
+class QGpgMEExportJob
+#ifdef Q_MOC_RUN
+ : public ExportJob
+#else
+ : public _detail::ThreadedJobMixin<ExportJob, std::tuple<GpgME::Error, QByteArray, QString, GpgME::Error> >
+#endif
+{
+ Q_OBJECT
+#ifdef Q_MOC_RUN
+public Q_SLOTS:
+ void slotFinished();
+#endif
+public:
+ explicit QGpgMEExportJob(GpgME::Context *context);
+ ~QGpgMEExportJob();
+
+ /* from ExportJob */
+ GpgME::Error start(const QStringList &patterns) Q_DECL_OVERRIDE;
+};
+
+}
+
+#endif // __QGPGME_QGPGMEEXPORTJOB_H__
diff --git a/lang/qt/src/qgpgmeimportfromkeyserverjob.cpp b/lang/qt/src/qgpgmeimportfromkeyserverjob.cpp
new file mode 100644
index 0000000..0f19679
--- /dev/null
+++ b/lang/qt/src/qgpgmeimportfromkeyserverjob.cpp
@@ -0,0 +1,82 @@
+/*
+ qgpgmeimportfromkeyserverjob.cpp
+
+ This file is part of qgpgme, the Qt API binding for gpgme
+ Copyright (c) 2004,2008 Klarälvdalens Datakonsult AB
+ Copyright (c) 2016 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.
+*/
+
+#include "qgpgmeimportfromkeyserverjob.h"
+
+#include "dataprovider.h"
+
+#include "context.h"
+#include "data.h"
+#include "key.h"
+
+#include <cassert>
+
+using namespace QGpgME;
+using namespace GpgME;
+
+QGpgMEImportFromKeyserverJob::QGpgMEImportFromKeyserverJob(Context *context)
+ : mixin_type(context)
+{
+ lateInitialization();
+}
+
+QGpgMEImportFromKeyserverJob::~QGpgMEImportFromKeyserverJob() {}
+
+static QGpgMEImportFromKeyserverJob::result_type importfromkeyserver(Context *ctx, const std::vector<Key> &keys)
+{
+ const ImportResult res = ctx->importKeys(keys);
+ Error ae;
+ const QString log = _detail::audit_log_as_html(ctx, ae);
+ return std::make_tuple(res, log, ae);
+}
+
+Error QGpgMEImportFromKeyserverJob::start(const std::vector<Key> &keys)
+{
+ run(std::bind(&importfromkeyserver, std::placeholders::_1, keys));
+ return Error();
+}
+
+GpgME::ImportResult QGpgME::QGpgMEImportFromKeyserverJob::exec(const std::vector<Key> &keys)
+{
+ const result_type r = importfromkeyserver(context(), keys);
+ resultHook(r);
+ return mResult;
+}
+
+// PENDING(marc) implement showErrorDialog()
+
+void QGpgME::QGpgMEImportFromKeyserverJob::resultHook(const result_type &tuple)
+{
+ mResult = std::get<0>(tuple);
+}
+#include "qgpgmeimportfromkeyserverjob.moc"
diff --git a/lang/qt/src/qgpgmeimportfromkeyserverjob.h b/lang/qt/src/qgpgmeimportfromkeyserverjob.h
new file mode 100644
index 0000000..8c9f944
--- /dev/null
+++ b/lang/qt/src/qgpgmeimportfromkeyserverjob.h
@@ -0,0 +1,81 @@
+/*
+ qgpgmeimportfromkeyserverjob.h
+
+ This file is part of qgpgme, the Qt API binding for gpgme
+ Copyright (c) 2004,2008 Klarälvdalens Datakonsult AB
+ Copyright (c) 2016 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.
+*/
+
+#ifndef __QGPGME_QGPGMEIMPORTFROMKEYSERVERJOB_H__
+#define __QGPGME_QGPGMEIMPORTFROMKEYSERVERJOB_H__
+
+#include "importfromkeyserverjob.h"
+
+#include "threadedjobmixin.h"
+
+#ifdef BUILDING_QGPGME
+# include "importresult.h"
+#else
+#include <gpgme++/importresult.h>
+#endif
+
+namespace QGpgME
+{
+
+class QGpgMEImportFromKeyserverJob
+#ifdef Q_MOC_RUN
+ : public ImportFromKeyserverJob
+#else
+ : public _detail::ThreadedJobMixin<ImportFromKeyserverJob, std::tuple<GpgME::ImportResult, QString, GpgME::Error> >
+#endif
+{
+ Q_OBJECT
+#ifdef Q_MOC_RUN
+public Q_SLOTS:
+ void slotFinished();
+#endif
+public:
+ explicit QGpgMEImportFromKeyserverJob(GpgME::Context *context);
+ ~QGpgMEImportFromKeyserverJob();
+
+ /* from ImportFromKeyserverJob */
+ GpgME::Error start(const std::vector<GpgME::Key> &keys) Q_DECL_OVERRIDE;
+
+ /* from ImportFromKeyserverJob */
+ GpgME::ImportResult exec(const std::vector<GpgME::Key> &keys) Q_DECL_OVERRIDE;
+
+ /* from ThreadedJobMixin */
+ void resultHook(const result_type &r) Q_DECL_OVERRIDE;
+
+private:
+ GpgME::ImportResult mResult;
+};
+
+}
+
+#endif // __QGPGME_QGPGMEIMPORTFROMKEYSERVERJOB_H__
diff --git a/lang/qt/src/qgpgmeimportjob.cpp b/lang/qt/src/qgpgmeimportjob.cpp
new file mode 100644
index 0000000..f125b12
--- /dev/null
+++ b/lang/qt/src/qgpgmeimportjob.cpp
@@ -0,0 +1,85 @@
+/*
+ qgpgmeimportjob.cpp
+
+ This file is part of qgpgme, the Qt API binding for gpgme
+ Copyright (c) 2004,2008 Klarälvdalens Datakonsult AB
+ Copyright (c) 2016 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.
+*/
+
+#include "qgpgmeimportjob.h"
+
+#include "dataprovider.h"
+
+#include "context.h"
+#include "data.h"
+#include "key.h"
+
+#include <cassert>
+
+using namespace QGpgME;
+using namespace GpgME;
+
+QGpgMEImportJob::QGpgMEImportJob(Context *context)
+ : mixin_type(context)
+{
+ lateInitialization();
+}
+
+QGpgMEImportJob::~QGpgMEImportJob() {}
+
+static QGpgMEImportJob::result_type import_qba(Context *ctx, const QByteArray &certData)
+{
+ QGpgME::QByteArrayDataProvider dp(certData);
+ Data data(&dp);
+
+ const ImportResult res = ctx->importKeys(data);
+ Error ae;
+ const QString log = _detail::audit_log_as_html(ctx, ae);
+ return std::make_tuple(res, log, ae);
+}
+
+Error QGpgMEImportJob::start(const QByteArray &certData)
+{
+ run(std::bind(&import_qba, std::placeholders::_1, certData));
+ return Error();
+}
+
+GpgME::ImportResult QGpgME::QGpgMEImportJob::exec(const QByteArray &keyData)
+{
+ const result_type r = import_qba(context(), keyData);
+ resultHook(r);
+ return mResult;
+}
+
+// PENDING(marc) implement showErrorDialog()
+
+void QGpgME::QGpgMEImportJob::resultHook(const result_type &tuple)
+{
+ mResult = std::get<0>(tuple);
+}
+#include "qgpgmeimportjob.moc"
diff --git a/lang/qt/src/qgpgmeimportjob.h b/lang/qt/src/qgpgmeimportjob.h
new file mode 100644
index 0000000..424cb50
--- /dev/null
+++ b/lang/qt/src/qgpgmeimportjob.h
@@ -0,0 +1,81 @@
+/*
+ qgpgmeimportjob.h
+
+ This file is part of qgpgme, the Qt API binding for gpgme
+ Copyright (c) 2004,2008 Klarälvdalens Datakonsult AB
+ Copyright (c) 2016 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.
+*/
+
+#ifndef __QGPGME_QGPGMEIMPORTJOB_H__
+#define __QGPGME_QGPGMEIMPORTJOB_H__
+
+#include "importjob.h"
+
+#include "threadedjobmixin.h"
+
+#ifdef BUILDING_QGPGME
+# include "importresult.h"
+#else
+#include <gpgme++/importresult.h>
+#endif
+
+namespace QGpgME
+{
+
+class QGpgMEImportJob
+#ifdef Q_MOC_RUN
+ : public ImportJob
+#else
+ : public _detail::ThreadedJobMixin<ImportJob, std::tuple<GpgME::ImportResult, QString, GpgME::Error> >
+#endif
+{
+ Q_OBJECT
+#ifdef Q_MOC_RUN
+public Q_SLOTS:
+ void slotFinished();
+#endif
+public:
+ explicit QGpgMEImportJob(GpgME::Context *context);
+ ~QGpgMEImportJob();
+
+ /* from ImportJob */
+ GpgME::Error start(const QByteArray &keyData) Q_DECL_OVERRIDE;
+
+ /* from ImportJob */
+ GpgME::ImportResult exec(const QByteArray &keyData) Q_DECL_OVERRIDE;
+
+ /* from ThreadedJobMixin */
+ void resultHook(const result_type &r) Q_DECL_OVERRIDE;
+
+private:
+ GpgME::ImportResult mResult;
+};
+
+}
+
+#endif // __QGPGME_QGPGMEIMPORTJOB_H__
diff --git a/lang/qt/src/qgpgmekeyformailboxjob.cpp b/lang/qt/src/qgpgmekeyformailboxjob.cpp
new file mode 100644
index 0000000..803d0e6
--- /dev/null
+++ b/lang/qt/src/qgpgmekeyformailboxjob.cpp
@@ -0,0 +1,138 @@
+/*
+ qgpgmekeyformailboxjob.cpp
+
+ This file is part of qgpgme, the Qt API binding for gpgme
+ Copyright (c) 2016 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.
+*/
+
+#include "qgpgmekeyformailboxjob.h"
+#include "qgpgmekeylistjob.h"
+
+#include <QStringList>
+
+#include <tuple>
+
+using namespace GpgME;
+using namespace QGpgME;
+
+QGpgMEKeyForMailboxJob::QGpgMEKeyForMailboxJob(Context *context)
+ : mixin_type(context)
+{
+ lateInitialization();
+}
+
+QGpgMEKeyForMailboxJob::~QGpgMEKeyForMailboxJob() {}
+
+static bool keyIsOk(const Key k)
+{
+ return !k.isExpired() && !k.isRevoked() && !k.isInvalid() && !k.isDisabled();
+}
+
+static bool uidIsOk(const UserID uid)
+{
+ return keyIsOk(uid.parent()) && !uid.isRevoked() && !uid.isInvalid();
+}
+
+static bool subkeyIsOk(const Subkey s)
+{
+ return !s.isRevoked() && !s.isInvalid() && !s.isDisabled();
+}
+
+static QGpgMEKeyForMailboxJob::result_type do_work(Context *ctx, const QString &mailbox, bool canEncrypt)
+{
+ /* Do a Keylisting. */
+ ctx->setKeyListMode(GpgME::Extern | GpgME::Local | GpgME::Signatures | GpgME::Validate);
+ std::vector<Key> keys;
+ QGpgMEKeyListJob *keylist = new QGpgMEKeyListJob(ctx);
+
+ KeyListResult result = keylist->exec(QStringList() << mailbox, false, keys);
+
+ if (result.error()) {
+ return std::make_tuple(result, Key(), UserID(), QString(), Error());
+ }
+
+ // This should ideally be decided by GnuPG and this Job changed
+ // to just call the according API in GpgME
+ // See: https://bugs.gnupg.org/gnupg/issue2359
+ Key keyC;
+ UserID uidC;
+ Q_FOREACH (const Key k, keys) {
+ if (canEncrypt && !k.canEncrypt()) {
+ continue;
+ }
+ /* First get the uid that matches the mailbox */
+ Q_FOREACH (const UserID u, k.userIDs()) {
+ if (QString::fromUtf8(u.email()).toLower() == mailbox.toLower()) {
+ if (uidC.isNull()) {
+ keyC = k;
+ uidC = u;
+ } else if ((!uidIsOk(uidC) && uidIsOk(u)) || uidC.validity() < u.validity()) {
+ /* Validity of the new key is better. */
+ uidC = u;
+ keyC = k;
+ } else if (uidC.validity() == u.validity() && uidIsOk(u)) {
+ /* Both are the same check which one is newer. */
+ time_t oldTime = 0;
+ Q_FOREACH (const Subkey s, keyC.subkeys()) {
+ if ((canEncrypt && s.canEncrypt()) && subkeyIsOk(s)) {
+ oldTime = s.creationTime();
+ }
+ }
+ time_t newTime = 0;
+ Q_FOREACH (const Subkey s, k.subkeys()) {
+ if ((canEncrypt && s.canEncrypt()) && subkeyIsOk(s)) {
+ newTime = s.creationTime();
+ }
+ }
+ if (newTime > oldTime) {
+ uidC = u;
+ keyC = k;
+ }
+ }
+ }
+ }
+ }
+ return std::make_tuple(result, keyC, uidC, QString(), Error());
+}
+
+Error QGpgMEKeyForMailboxJob::start(const QString &mailbox, bool canEncrypt)
+{
+ run(std::bind(&do_work, std::placeholders::_1, mailbox, canEncrypt));
+ return Error();
+}
+
+KeyListResult QGpgMEKeyForMailboxJob::exec(const QString &mailbox, bool canEncrypt, Key &key, UserID &uid)
+{
+ const result_type r = do_work(context(), mailbox, canEncrypt);
+ resultHook(r);
+ key = std::get<1>(r);
+ uid = std::get<2>(r);
+ return std::get<0>(r);
+}
+
+#include "qgpgmekeyformailboxjob.moc"
diff --git a/lang/qt/src/qgpgmekeyformailboxjob.h b/lang/qt/src/qgpgmekeyformailboxjob.h
new file mode 100644
index 0000000..8ac2c1f
--- /dev/null
+++ b/lang/qt/src/qgpgmekeyformailboxjob.h
@@ -0,0 +1,84 @@
+/*
+ qgpgmekeyformailboxjob.h
+
+ This file is part of libkleopatra, the KDE keymanagement library
+ Copyright (c) 2004,2008 Klarälvdalens Datakonsult AB
+ This file is part of qgpgme, the Qt API binding for gpgme
+ Copyright (c) 2016 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.
+*/
+
+#ifndef __QGPGME_QGPGMEKEYFORMAILBOXJOB_H__
+#define __QGPGME_QGPGMEKEYFORMAILBOXJOB_H__
+#include "keyformailboxjob.h"
+
+#include "threadedjobmixin.h"
+
+#ifdef BUILDING_QGPGME
+# include "keylistresult.h"
+# include "key.h"
+#else
+# include <gpgme++/keylistresult.h>
+# include <gpgme++/key.h>
+#endif
+
+namespace QGpgME
+{
+
+class QGpgMEKeyForMailboxJob
+#ifdef Q_MOC_RUN
+ : public KeyForMailboxJob
+#else
+ : public _detail::ThreadedJobMixin<KeyForMailboxJob, std::tuple<GpgME::KeyListResult, GpgME::Key, GpgME::UserID, QString, GpgME::Error> >
+#endif
+{
+ Q_OBJECT
+#ifdef Q_MOC_RUN
+public Q_SLOTS:
+ void slotFinished();
+#endif
+public:
+ explicit QGpgMEKeyForMailboxJob(GpgME::Context *context);
+ ~QGpgMEKeyForMailboxJob();
+
+ /**
+ Starts the operation. \a mailbox is the mailbox to
+ look for.
+
+ The result is the same as for the LocateKeysJob.
+
+ If \a canEncrypt is true, only keys that have a subkey for encryption
+ usage are returned. Use this if you need to select a
+ key for signing.
+ */
+ GpgME::Error start(const QString &mailbox, bool canEncrypt = true) Q_DECL_OVERRIDE;
+
+ GpgME::KeyListResult exec(const QString &mailbox, bool canEncrypt, GpgME::Key &key, GpgME::UserID &uid) Q_DECL_OVERRIDE;
+};
+
+}
+#endif
diff --git a/lang/qt/src/qgpgmekeygenerationjob.cpp b/lang/qt/src/qgpgmekeygenerationjob.cpp
new file mode 100644
index 0000000..cba6b76
--- /dev/null
+++ b/lang/qt/src/qgpgmekeygenerationjob.cpp
@@ -0,0 +1,71 @@
+/*
+ qgpgmekeygenerationjob.cpp
+
+ This file is part of qgpgme, the Qt API binding for gpgme
+ Copyright (c) 2004 Klarälvdalens Datakonsult AB
+ Copyright (c) 2016 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.
+*/
+
+#include "qgpgmekeygenerationjob.h"
+
+#include "dataprovider.h"
+
+#include "context.h"
+#include "data.h"
+
+#include <cassert>
+
+using namespace QGpgME;
+using namespace GpgME;
+
+QGpgMEKeyGenerationJob::QGpgMEKeyGenerationJob(Context *context)
+ : mixin_type(context)
+{
+ lateInitialization();
+}
+
+QGpgMEKeyGenerationJob::~QGpgMEKeyGenerationJob() {}
+
+static QGpgMEKeyGenerationJob::result_type generate_key(Context *ctx, const QString &parameters)
+{
+ QGpgME::QByteArrayDataProvider dp;
+ Data data = ctx->protocol() == CMS ? Data(&dp) : Data(Data::null);
+ assert(data.isNull() == (ctx->protocol() != CMS));
+
+ const KeyGenerationResult res = ctx->generateKey(parameters.toUtf8().constData(), data);
+ Error ae;
+ const QString log = _detail::audit_log_as_html(ctx, ae);
+ return std::make_tuple(res, dp.data(), log, ae);
+}
+
+Error QGpgMEKeyGenerationJob::start(const QString &parameters)
+{
+ run(std::bind(&generate_key, std::placeholders::_1, parameters));
+ return Error();
+}
+#include "qgpgmekeygenerationjob.moc"
diff --git a/lang/qt/src/qgpgmekeygenerationjob.h b/lang/qt/src/qgpgmekeygenerationjob.h
new file mode 100644
index 0000000..808b714
--- /dev/null
+++ b/lang/qt/src/qgpgmekeygenerationjob.h
@@ -0,0 +1,72 @@
+/*
+ qgpgmekeygenerationjob.h
+
+ This file is part of qgpgme, the Qt API binding for gpgme
+ Copyright (c) 2004,2008 Klarälvdalens Datakonsult AB
+ Copyright (c) 2016 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.
+*/
+
+#ifndef __QGPGME_QGPGMEKEYGENERATIONJOB_H__
+#define __QGPGME_QGPGMEKEYGENERATIONJOB_H__
+
+#include "keygenerationjob.h"
+
+#include "threadedjobmixin.h"
+
+#ifdef BUILDING_QGPGME
+# include "keygenerationresult.h"
+#else
+#include <gpgme++/keygenerationresult.h>
+#endif
+
+namespace QGpgME
+{
+
+class QGpgMEKeyGenerationJob
+#ifdef Q_MOC_RUN
+ : public KeyGenerationJob
+#else
+ : public _detail::ThreadedJobMixin<KeyGenerationJob, std::tuple<GpgME::KeyGenerationResult, QByteArray, QString, GpgME::Error> >
+#endif
+{
+ Q_OBJECT
+#ifdef Q_MOC_RUN
+private Q_SLOTS:
+ void slotFinished();
+#endif
+public:
+ explicit QGpgMEKeyGenerationJob(GpgME::Context *context);
+ ~QGpgMEKeyGenerationJob();
+
+ /* from KeygenerationJob */
+ GpgME::Error start(const QString &parameters) Q_DECL_OVERRIDE;
+};
+
+}
+
+#endif // __QGPGME_QGPGMEKEYGENERATIONJOB_H__
diff --git a/lang/qt/src/qgpgmekeylistjob.cpp b/lang/qt/src/qgpgmekeylistjob.cpp
new file mode 100644
index 0000000..1169c46
--- /dev/null
+++ b/lang/qt/src/qgpgmekeylistjob.cpp
@@ -0,0 +1,172 @@
+/*
+ qgpgmekeylistjob.cpp
+
+ This file is part of qgpgme, the Qt API binding for gpgme
+ Copyright (c) 2004,2008 Klarälvdalens Datakonsult AB
+ Copyright (c) 2016 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.
+*/
+
+#include "qgpgmekeylistjob.h"
+
+#include "key.h"
+#include "context.h"
+#include "keylistresult.h"
+#include <gpg-error.h>
+
+#include <QStringList>
+
+#include <algorithm>
+
+#include <cstdlib>
+#include <cstring>
+#include <cassert>
+
+using namespace QGpgME;
+using namespace GpgME;
+
+QGpgMEKeyListJob::QGpgMEKeyListJob(Context *context)
+ : mixin_type(context),
+ mResult(), mSecretOnly(false)
+{
+ lateInitialization();
+}
+
+QGpgMEKeyListJob::~QGpgMEKeyListJob() {}
+
+static KeyListResult do_list_keys(Context *ctx, const QStringList &pats, std::vector<Key> &keys, bool secretOnly)
+{
+
+ const _detail::PatternConverter pc(pats);
+
+ if (const Error err = ctx->startKeyListing(pc.patterns(), secretOnly)) {
+ return KeyListResult(0, err);
+ }
+
+ Error err;
+ do {
+ keys.push_back(ctx->nextKey(err));
+ } while (!err);
+
+ keys.pop_back();
+
+ const KeyListResult result = ctx->endKeyListing();
+ ctx->cancelPendingOperation();
+ return result;
+}
+
+static QGpgMEKeyListJob::result_type list_keys(Context *ctx, QStringList pats, bool secretOnly)
+{
+ if (pats.size() < 2) {
+ std::vector<Key> keys;
+ const KeyListResult r = do_list_keys(ctx, pats, keys, secretOnly);
+ return std::make_tuple(r, keys, QString(), Error());
+ }
+
+ // The communication channel between gpgme and gpgsm is limited in
+ // the number of patterns that can be transported, but they won't
+ // say to how much, so we need to find out ourselves if we get a
+ // LINE_TOO_LONG error back...
+
+ // We could of course just feed them single patterns, and that would
+ // probably be easier, but the performance penalty would currently
+ // be noticeable.
+
+ unsigned int chunkSize = pats.size();
+retry:
+ std::vector<Key> keys;
+ keys.reserve(pats.size());
+ KeyListResult result;
+ do {
+ const KeyListResult this_result = do_list_keys(ctx, pats.mid(0, chunkSize), keys, secretOnly);
+ if (this_result.error().code() == GPG_ERR_LINE_TOO_LONG) {
+ // got LINE_TOO_LONG, try a smaller chunksize:
+ chunkSize /= 2;
+ if (chunkSize < 1)
+ // chunks smaller than one can't be -> return the error.
+ {
+ return std::make_tuple(this_result, keys, QString(), Error());
+ } else {
+ goto retry;
+ }
+ } else if (this_result.error().code() == GPG_ERR_EOF) {
+ // early end of keylisting (can happen when ~/.gnupg doesn't
+ // exist). Fakeing an empty result:
+ return std::make_tuple(KeyListResult(), std::vector<Key>(), QString(), Error());
+ }
+ // ok, that seemed to work...
+ result.mergeWith(this_result);
+ if (result.error().code()) {
+ break;
+ }
+ pats = pats.mid(chunkSize);
+ } while (!pats.empty());
+ return std::make_tuple(result, keys, QString(), Error());
+}
+
+Error QGpgMEKeyListJob::start(const QStringList &patterns, bool secretOnly)
+{
+ mSecretOnly = secretOnly;
+ run(std::bind(&list_keys, std::placeholders::_1, patterns, secretOnly));
+ return Error();
+}
+
+KeyListResult QGpgMEKeyListJob::exec(const QStringList &patterns, bool secretOnly, std::vector<Key> &keys)
+{
+ mSecretOnly = secretOnly;
+ const result_type r = list_keys(context(), patterns, secretOnly);
+ resultHook(r);
+ keys = std::get<1>(r);
+ return std::get<0>(r);
+}
+
+void QGpgMEKeyListJob::resultHook(const result_type &tuple)
+{
+ mResult = std::get<0>(tuple);
+ Q_FOREACH (const Key &key, std::get<1>(tuple)) {
+ Q_EMIT nextKey(key);
+ }
+}
+
+void QGpgMEKeyListJob::addMode(KeyListMode mode)
+{
+ context()->addKeyListMode(mode);
+}
+#if 0
+void QGpgMEKeyListJob::showErrorDialog(QWidget *parent, const QString &caption) const
+{
+ if (!mResult.error() || mResult.error().isCanceled()) {
+ return;
+ }
+ const QString msg = i18n("<qt><p>An error occurred while fetching "
+ "the keys from the backend:</p>"
+ "<p><b>%1</b></p></qt>",
+ QString::fromLocal8Bit(mResult.error().asString()));
+ KMessageBox::error(parent, msg, caption);
+}
+#endif
+#include "qgpgmekeylistjob.moc"
diff --git a/lang/qt/src/qgpgmekeylistjob.h b/lang/qt/src/qgpgmekeylistjob.h
new file mode 100644
index 0000000..2d5406a
--- /dev/null
+++ b/lang/qt/src/qgpgmekeylistjob.h
@@ -0,0 +1,88 @@
+/*
+ qgpgmekeylistjob.h
+
+ This file is part of qgpgme, the Qt API binding for gpgme
+ Copyright (c) 2004,2008 Klarälvdalens Datakonsult AB
+ Copyright (c) 2016 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.
+*/
+
+#ifndef __QGPGME_QGPGMEKEYLISTJOB_H__
+#define __QGPGME_QGPGMEKEYLISTJOB_H__
+
+#include "keylistjob.h"
+
+#include "threadedjobmixin.h"
+
+#ifdef BUILDING_QGPGME
+# include "keylistresult.h"
+#else
+#include <gpgme++/keylistresult.h>
+#endif
+#ifdef BUILDING_QGPGME
+# include "key.h"
+#else
+#include <gpgme++/key.h>
+#endif
+
+namespace QGpgME
+{
+
+class QGpgMEKeyListJob
+#ifdef Q_MOC_RUN
+ : public KeyListJob
+#else
+ : public _detail::ThreadedJobMixin<KeyListJob, std::tuple<GpgME::KeyListResult, std::vector<GpgME::Key>, QString, GpgME::Error> >
+#endif
+{
+ Q_OBJECT
+#ifdef Q_MOC_RUN
+public Q_SLOTS:
+ void slotFinished();
+#endif
+public:
+ explicit QGpgMEKeyListJob(GpgME::Context *context);
+ ~QGpgMEKeyListJob();
+
+ /* from KeyListJob */
+ GpgME::Error start(const QStringList &patterns, bool secretOnly) Q_DECL_OVERRIDE;
+
+ /* from KeyListJob */
+ GpgME::KeyListResult exec(const QStringList &patterns, bool secretOnly, std::vector<GpgME::Key> &keys) Q_DECL_OVERRIDE;
+
+ void addMode(GpgME::KeyListMode mode) Q_DECL_OVERRIDE;
+
+ /* from ThreadedJobMixin */
+ void resultHook(const result_type &result) Q_DECL_OVERRIDE;
+private:
+ GpgME::KeyListResult mResult;
+ bool mSecretOnly;
+};
+
+}
+
+#endif // __QGPGME_QGPGMEKEYLISTJOB_H__
diff --git a/lang/qt/src/qgpgmelistallkeysjob.cpp b/lang/qt/src/qgpgmelistallkeysjob.cpp
new file mode 100644
index 0000000..fd8bfc3
--- /dev/null
+++ b/lang/qt/src/qgpgmelistallkeysjob.cpp
@@ -0,0 +1,168 @@
+/*
+ qgpgmelistallkeysjob.cpp
+
+ This file is part of qgpgme, the Qt API binding for gpgme
+ Copyright (c) 2004,2008 Klarälvdalens Datakonsult AB
+ Copyright (c) 2016 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.
+*/
+
+#include "qgpgmelistallkeysjob.h"
+
+#include "key.h"
+#include "context.h"
+#include "keylistresult.h"
+#include <gpg-error.h>
+
+#include <algorithm>
+
+#include <cstdlib>
+#include <cstring>
+#include <cassert>
+
+using namespace QGpgME;
+using namespace GpgME;
+
+QGpgMEListAllKeysJob::QGpgMEListAllKeysJob(Context *context)
+ : mixin_type(context),
+ mResult()
+{
+ lateInitialization();
+}
+
+QGpgMEListAllKeysJob::~QGpgMEListAllKeysJob() {}
+
+static KeyListResult do_list_keys(Context *ctx, std::vector<Key> &keys, bool secretOnly)
+{
+
+ const char **pat = 0;
+ if (const Error err = ctx->startKeyListing(pat, secretOnly)) {
+ return KeyListResult(0, err);
+ }
+
+ Error err;
+ do {
+ keys.push_back(ctx->nextKey(err));
+ } while (!err);
+
+ keys.pop_back();
+
+ const KeyListResult result = ctx->endKeyListing();
+ ctx->cancelPendingOperation();
+ return result;
+}
+
+namespace
+{
+
+template <typename ForwardIterator, typename BinaryPredicate>
+ForwardIterator unique_by_merge(ForwardIterator first, ForwardIterator last, BinaryPredicate pred)
+{
+ first = std::adjacent_find(first, last, pred);
+ if (first == last) {
+ return last;
+ }
+
+ ForwardIterator dest = first;
+ dest->mergeWith(*++first);
+ while (++first != last)
+ if (pred(*dest, *first)) {
+ dest->mergeWith(*first);
+ } else {
+ *++dest = *first;
+ }
+ return ++dest;
+}
+
+}
+
+static void merge_keys(std::vector<Key> &merged, std::vector<Key> &pub, std::vector<Key> &sec)
+{
+ merged.reserve(pub.size() + sec.size());
+
+ std::merge(pub.begin(), pub.end(),
+ sec.begin(), sec.end(),
+ std::back_inserter(merged),
+ ByFingerprint<std::less>());
+
+ merged.erase(unique_by_merge(merged.begin(), merged.end(), ByFingerprint<std::equal_to>()),
+ merged.end());
+}
+
+static QGpgMEListAllKeysJob::result_type list_keys(Context *ctx, bool mergeKeys)
+{
+ std::vector<Key> pub, sec, merged;
+ KeyListResult r;
+
+ r.mergeWith(do_list_keys(ctx, pub, false));
+ std::sort(pub.begin(), pub.end(), ByFingerprint<std::less>());
+
+ r.mergeWith(do_list_keys(ctx, sec, true));
+ std::sort(sec.begin(), sec.end(), ByFingerprint<std::less>());
+
+ if (mergeKeys) {
+ merge_keys(merged, pub, sec);
+ } else {
+ merged.swap(pub);
+ }
+ return std::make_tuple(r, merged, sec, QString(), Error());
+}
+
+Error QGpgMEListAllKeysJob::start(bool mergeKeys)
+{
+ run(std::bind(&list_keys, std::placeholders::_1, mergeKeys));
+ return Error();
+}
+
+KeyListResult QGpgMEListAllKeysJob::exec(std::vector<Key> &pub, std::vector<Key> &sec, bool mergeKeys)
+{
+ const result_type r = list_keys(context(), mergeKeys);
+ resultHook(r);
+ pub = std::get<1>(r);
+ sec = std::get<2>(r);
+ return std::get<0>(r);
+}
+
+void QGpgMEListAllKeysJob::resultHook(const result_type &tuple)
+{
+ mResult = std::get<0>(tuple);
+}
+
+#if 0
+void QGpgMEListAllKeysJob::showErrorDialog(QWidget *parent, const QString &caption) const
+{
+ if (!mResult.error() || mResult.error().isCanceled()) {
+ return;
+ }
+ const QString msg = i18n("<qt><p>An error occurred while fetching "
+ "the keys from the backend:</p>"
+ "<p><b>%1</b></p></qt>",
+ QString::fromLocal8Bit(mResult.error().asString()));
+ KMessageBox::error(parent, msg, caption);
+}
+#endif
+#include "qgpgmelistallkeysjob.moc"
diff --git a/lang/qt/src/qgpgmelistallkeysjob.h b/lang/qt/src/qgpgmelistallkeysjob.h
new file mode 100644
index 0000000..1fc69d4
--- /dev/null
+++ b/lang/qt/src/qgpgmelistallkeysjob.h
@@ -0,0 +1,86 @@
+/*
+ qgpgmelistallkeysjob.h
+
+ This file is part of qgpgme, the Qt API binding for gpgme
+ Copyright (c) 2004,2008 Klarälvdalens Datakonsult AB
+ Copyright (c) 2016 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.
+*/
+
+#ifndef __QGPGME_QGPGMELISTALLKEYSJOB_H__
+#define __QGPGME_QGPGMELISTALLKEYSJOB_H__
+
+#include "listallkeysjob.h"
+
+#include "threadedjobmixin.h"
+
+#ifdef BUILDING_QGPGME
+# include "keylistresult.h"
+#else
+#include <gpgme++/keylistresult.h>
+#endif
+#ifdef BUILDING_QGPGME
+# include "key.h"
+#else
+#include <gpgme++/key.h>
+#endif
+
+namespace QGpgME
+{
+
+class QGpgMEListAllKeysJob
+#ifdef Q_MOC_RUN
+ : public ListAllKeysJob
+#else
+ : public _detail::ThreadedJobMixin<ListAllKeysJob, std::tuple<GpgME::KeyListResult, std::vector<GpgME::Key>, std::vector<GpgME::Key>, QString, GpgME::Error> >
+#endif
+{
+ Q_OBJECT
+#ifdef Q_MOC_RUN
+public Q_SLOTS:
+ void slotFinished();
+#endif
+public:
+ explicit QGpgMEListAllKeysJob(GpgME::Context *context);
+ ~QGpgMEListAllKeysJob();
+
+ /* from ListAllKeysJob */
+ GpgME::Error start(bool mergeKeys) Q_DECL_OVERRIDE;
+
+ /* from ListAllKeysJob */
+ GpgME::KeyListResult exec(std::vector<GpgME::Key> &pub, std::vector<GpgME::Key> &sec, bool mergeKeys) Q_DECL_OVERRIDE;
+
+ /* from ThreadedJobMixin */
+ void resultHook(const result_type &result) Q_DECL_OVERRIDE;
+
+private:
+ GpgME::KeyListResult mResult;
+};
+
+}
+
+#endif // __QGPGME_QGPGMELISTALLKEYSJOB_H__
diff --git a/lang/qt/src/qgpgmenewcryptoconfig.cpp b/lang/qt/src/qgpgmenewcryptoconfig.cpp
new file mode 100644
index 0000000..7303f10
--- /dev/null
+++ b/lang/qt/src/qgpgmenewcryptoconfig.cpp
@@ -0,0 +1,738 @@
+/*
+ qgpgmenewcryptoconfig.cpp
+
+ This file is part of qgpgme, the Qt API binding for gpgme
+ Copyright (c) 2010 Klarälvdalens Datakonsult AB
+ Copyright (c) 2016 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.
+*/
+
+#include "qgpgmenewcryptoconfig.h"
+
+#include <QDebug>
+#include "gpgme_backend_debug.h"
+
+#include <QFile>
+
+#include "global.h"
+#include "error.h"
+
+
+#include <sstream>
+#include <string>
+#include <cassert>
+
+using namespace QGpgME;
+using namespace GpgME;
+using namespace GpgME::Configuration;
+
+namespace
+{
+struct Select1St {
+ template <typename U, typename V>
+ const U &operator()(const std::pair<U, V> &p) const
+ {
+ return p.first;
+ }
+ template <typename U, typename V>
+ const U &operator()(const QPair<U, V> &p) const
+ {
+ return p.first;
+ }
+};
+}
+
+// Just for the Q_ASSERT in the dtor. Not thread-safe, but who would
+// have 2 threads talking to gpgconf anyway? :)
+static bool s_duringClear = false;
+
+QGpgMENewCryptoConfig::QGpgMENewCryptoConfig()
+ : m_parsed(false)
+{
+}
+
+QGpgMENewCryptoConfig::~QGpgMENewCryptoConfig()
+{
+ clear();
+}
+
+void QGpgMENewCryptoConfig::reloadConfiguration(bool showErrors)
+{
+ clear();
+
+ Error error;
+ const std::vector<Component> components = Component::load(error);
+#ifndef NDEBUG
+ {
+ std::stringstream ss;
+ ss << "error: " << error
+ << "components:\n";
+ std::copy(components.begin(), components.end(),
+ std::ostream_iterator<Component>(ss, "\n"));
+ qCDebug(GPGPME_BACKEND_LOG) << ss.str().c_str();
+ }
+#endif
+#if 0
+ TODO port?
+ if (error && showErrors) {
+ const QString wmsg = i18n("<qt>Failed to execute gpgconf:<p>%1</p></qt>", QString::fromLocal8Bit(error.asString()));
+ qCWarning(GPGPME_BACKEND_LOG) << wmsg; // to see it from test_cryptoconfig.cpp
+ KMessageBox::error(0, wmsg);
+ }
+#endif
+ Q_FOREACH(const Component & c, components) {
+ const std::shared_ptr<QGpgMENewCryptoConfigComponent> comp(new QGpgMENewCryptoConfigComponent);
+ comp->setComponent(c);
+ m_componentsByName[ comp->name() ] = comp;
+ }
+ m_parsed = true;
+}
+
+QStringList QGpgMENewCryptoConfig::componentList() const
+{
+ if (!m_parsed) {
+ const_cast<QGpgMENewCryptoConfig *>(this)->reloadConfiguration(true);
+ }
+ QStringList result;
+ std::transform(m_componentsByName.begin(), m_componentsByName.end(),
+ std::back_inserter(result),
+ mem_fn(&QGpgMENewCryptoConfigComponent::name));
+ return result;
+}
+
+QGpgMENewCryptoConfigComponent *QGpgMENewCryptoConfig::component(const QString &name) const
+{
+ if (!m_parsed) {
+ const_cast<QGpgMENewCryptoConfig *>(this)->reloadConfiguration(false);
+ }
+ return m_componentsByName.value(name).get();
+}
+
+void QGpgMENewCryptoConfig::sync(bool runtime)
+{
+ Q_FOREACH(const std::shared_ptr<QGpgMENewCryptoConfigComponent> &c, m_componentsByName)
+ c->sync(runtime);
+}
+
+void QGpgMENewCryptoConfig::clear()
+{
+ s_duringClear = true;
+ m_componentsByName.clear();
+ s_duringClear = false;
+ m_parsed = false; // next call to componentList/component will need to run gpgconf again
+}
+
+////
+
+QGpgMENewCryptoConfigComponent::QGpgMENewCryptoConfigComponent()
+ : CryptoConfigComponent(),
+ m_component()
+{
+
+}
+
+void QGpgMENewCryptoConfigComponent::setComponent(const Component &component)
+{
+ m_component = component;
+ m_groupsByName.clear();
+
+ std::shared_ptr<QGpgMENewCryptoConfigGroup> group;
+
+ const std::vector<Option> options = m_component.options();
+ Q_FOREACH(const Option & o, options)
+ if (o.flags() & Group) {
+ if (group) {
+ m_groupsByName[group->name()] = group;
+ }
+ group.reset(new QGpgMENewCryptoConfigGroup(shared_from_this(), o));
+ } else if (group) {
+ const std::shared_ptr<QGpgMENewCryptoConfigEntry> entry(new QGpgMENewCryptoConfigEntry(group, o));
+ const QString name = entry->name();
+ group->m_entryNames.push_back(name);
+ group->m_entriesByName[name] = entry;
+ } else {
+ qCWarning(GPGPME_BACKEND_LOG) << "found no group for entry" << o.name() << "of component" << name();
+ }
+ if (group) {
+ m_groupsByName[group->name()] = group;
+ }
+
+}
+
+QGpgMENewCryptoConfigComponent::~QGpgMENewCryptoConfigComponent() {}
+
+QString QGpgMENewCryptoConfigComponent::name() const
+{
+ return QString::fromUtf8(m_component.name());
+}
+
+QString QGpgMENewCryptoConfigComponent::description() const
+{
+ return QString::fromUtf8(m_component.description());
+}
+
+QStringList QGpgMENewCryptoConfigComponent::groupList() const
+{
+ QStringList result;
+ result.reserve(m_groupsByName.size());
+ std::transform(m_groupsByName.begin(), m_groupsByName.end(),
+ std::back_inserter(result),
+ std::mem_fn(&QGpgMENewCryptoConfigGroup::name));
+ return result;
+}
+
+QGpgMENewCryptoConfigGroup *QGpgMENewCryptoConfigComponent::group(const QString &name) const
+{
+ return m_groupsByName.value(name).get();
+}
+
+void QGpgMENewCryptoConfigComponent::sync(bool runtime)
+{
+ Q_UNUSED(runtime)
+ // ### how to pass --runtime to gpgconf? -> marcus: not yet supported (2010-11-20)
+ if (const Error err = m_component.save()) {
+#if 0
+ TODO port
+ const QString wmsg = i18n("Error from gpgconf while saving configuration: %1", QString::fromLocal8Bit(err.asString()));
+ qCWarning(GPGPME_BACKEND_LOG) << ":" << wmsg;
+ KMessageBox::error(0, wmsg);
+#endif
+ }
+ // ### unset dirty state again
+}
+
+////
+
+QGpgMENewCryptoConfigGroup::QGpgMENewCryptoConfigGroup(const std::shared_ptr<QGpgMENewCryptoConfigComponent> &comp, const Option &option)
+ : CryptoConfigGroup(),
+ m_component(comp),
+ m_option(option)
+{
+}
+
+QGpgMENewCryptoConfigGroup::~QGpgMENewCryptoConfigGroup() {}
+
+QString QGpgMENewCryptoConfigGroup::name() const
+{
+ return QString::fromUtf8(m_option.name());
+}
+
+QString QGpgMENewCryptoConfigGroup::description() const
+{
+ return QString::fromUtf8(m_option.description());
+}
+
+QString QGpgMENewCryptoConfigGroup::path() const
+{
+ if (const std::shared_ptr<QGpgMENewCryptoConfigComponent> c = m_component.lock()) {
+ return c->name() + QLatin1Char('/') + name();
+ } else {
+ return QString();
+ }
+}
+
+CryptoConfigEntry::Level QGpgMENewCryptoConfigGroup::level() const
+{
+ // two casts to make SunCC happy:
+ return static_cast<CryptoConfigEntry::Level>(static_cast<unsigned int>(m_option.level()));
+}
+
+QStringList QGpgMENewCryptoConfigGroup::entryList() const
+{
+ return m_entryNames;
+}
+
+QGpgMENewCryptoConfigEntry *QGpgMENewCryptoConfigGroup::entry(const QString &name) const
+{
+ return m_entriesByName.value(name).get();
+}
+
+static QString urlpart_encode(const QString &str)
+{
+ QString enc(str);
+ enc.replace(QLatin1Char('%'), QStringLiteral("%25")); // first!
+ enc.replace(QLatin1Char(':'), QStringLiteral("%3a"));
+ //qCDebug(GPGPME_BACKEND_LOG) <<" urlpart_encode:" << str <<" ->" << enc;
+ return enc;
+}
+
+static QString urlpart_decode(const QString &str)
+{
+ return QUrl::fromPercentEncoding(str.toLatin1());
+}
+
+// gpgconf arg type number -> NewCryptoConfigEntry arg type enum mapping
+static QGpgME::CryptoConfigEntry::ArgType knownArgType(int argType, bool &ok)
+{
+ ok = true;
+ switch (argType) {
+ case 0: // none
+ return QGpgME::CryptoConfigEntry::ArgType_None;
+ case 1: // string
+ return QGpgME::CryptoConfigEntry::ArgType_String;
+ case 2: // int32
+ return QGpgME::CryptoConfigEntry::ArgType_Int;
+ case 3: // uint32
+ return QGpgME::CryptoConfigEntry::ArgType_UInt;
+ case 32: // pathname
+ return QGpgME::CryptoConfigEntry::ArgType_Path;
+ case 33: // ldap server
+ return QGpgME::CryptoConfigEntry::ArgType_LDAPURL;
+ default:
+ ok = false;
+ return QGpgME::CryptoConfigEntry::ArgType_None;
+ }
+}
+
+QGpgMENewCryptoConfigEntry::QGpgMENewCryptoConfigEntry(const std::shared_ptr<QGpgMENewCryptoConfigGroup> &group, const Option &option)
+ : m_group(group), m_option(option)
+{
+}
+
+#if 0
+QVariant QGpgMENewCryptoConfigEntry::stringToValue(const QString &str, bool unescape) const
+{
+ const bool isString = isStringType();
+
+ if (isList()) {
+ if (argType() == ArgType_None) {
+ bool ok = true;
+ const QVariant v = str.isEmpty() ? 0U : str.toUInt(&ok);
+ if (!ok) {
+ qCWarning(GPGPME_BACKEND_LOG) << "list-of-none should have an unsigned int as value:" << str;
+ }
+ return v;
+ }
+ QList<QVariant> lst;
+ QStringList items = str.split(',', QString::SkipEmptyParts);
+ for (QStringList::const_iterator valit = items.constBegin(); valit != items.constEnd(); ++valit) {
+ QString val = *valit;
+ if (isString) {
+ if (val.isEmpty()) {
+ lst << QVariant(QString());
+ continue;
+ } else if (unescape) {
+ if (val[0] != '"') { // see README.gpgconf
+ qCWarning(GPGPME_BACKEND_LOG) << "String value should start with '\"' :" << val;
+ }
+ val = val.mid(1);
+ }
+ }
+ lst << QVariant(unescape ? gpgconf_unescape(val) : val);
+ }
+ return lst;
+ } else { // not a list
+ QString val(str);
+ if (isString) {
+ if (val.isEmpty()) {
+ return QVariant(QString()); // not set [ok with lists too?]
+ } else if (unescape) {
+ if (val[0] != '"') { // see README.gpgconf
+ qCWarning(GPGPME_BACKEND_LOG) << "String value should start with '\"' :" << val;
+ }
+ val = val.mid(1);
+ }
+ }
+ return QVariant(unescape ? gpgconf_unescape(val) : val);
+ }
+}
+#endif
+
+QGpgMENewCryptoConfigEntry::~QGpgMENewCryptoConfigEntry()
+{
+#ifndef NDEBUG
+ if (!s_duringClear && m_option.dirty())
+ qCWarning(GPGPME_BACKEND_LOG) << "Deleting a QGpgMENewCryptoConfigEntry that was modified (" << m_option.description() << ")"
+ << "You forgot to call sync() (to commit) or clear() (to discard)";
+#endif
+}
+
+QString QGpgMENewCryptoConfigEntry::name() const
+{
+ return QString::fromUtf8(m_option.name());
+}
+
+QString QGpgMENewCryptoConfigEntry::description() const
+{
+ return QString::fromUtf8(m_option.description());
+}
+
+QString QGpgMENewCryptoConfigEntry::path() const
+{
+ if (const std::shared_ptr<QGpgMENewCryptoConfigGroup> g = m_group.lock()) {
+ return g->path() + QLatin1Char('/') + name();
+ } else {
+ return QString();
+ }
+}
+
+bool QGpgMENewCryptoConfigEntry::isOptional() const
+{
+ return m_option.flags() & Optional;
+}
+
+bool QGpgMENewCryptoConfigEntry::isReadOnly() const
+{
+ return m_option.flags() & NoChange;
+}
+
+bool QGpgMENewCryptoConfigEntry::isList() const
+{
+ return m_option.flags() & List;
+}
+
+bool QGpgMENewCryptoConfigEntry::isRuntime() const
+{
+ return m_option.flags() & Runtime;
+}
+
+CryptoConfigEntry::Level QGpgMENewCryptoConfigEntry::level() const
+{
+ // two casts to make SunCC happy:
+ return static_cast<Level>(static_cast<unsigned int>(m_option.level()));
+}
+
+CryptoConfigEntry::ArgType QGpgMENewCryptoConfigEntry::argType() const
+{
+ bool ok = false;
+ const ArgType type = knownArgType(m_option.type(), ok);
+ if (ok) {
+ return type;
+ } else {
+ return knownArgType(m_option.alternateType(), ok);
+ }
+}
+
+bool QGpgMENewCryptoConfigEntry::isSet() const
+{
+ return m_option.set();
+}
+
+bool QGpgMENewCryptoConfigEntry::boolValue() const
+{
+ Q_ASSERT(m_option.alternateType() == NoType);
+ Q_ASSERT(!isList());
+ return m_option.currentValue().boolValue();
+}
+
+QString QGpgMENewCryptoConfigEntry::stringValue() const
+{
+ //return toString( false );
+ Q_ASSERT(m_option.alternateType() == StringType);
+ Q_ASSERT(!isList());
+ return QString::fromUtf8(m_option.currentValue().stringValue());
+}
+
+int QGpgMENewCryptoConfigEntry::intValue() const
+{
+ Q_ASSERT(m_option.alternateType() == IntegerType);
+ Q_ASSERT(!isList());
+ return m_option.currentValue().intValue();
+}
+
+unsigned int QGpgMENewCryptoConfigEntry::uintValue() const
+{
+ Q_ASSERT(m_option.alternateType() == UnsignedIntegerType);
+ Q_ASSERT(!isList());
+ return m_option.currentValue().uintValue();
+}
+
+static QUrl parseURL(int mRealArgType, const QString &str)
+{
+ if (mRealArgType == 33) { // LDAP server
+ // The format is HOSTNAME:PORT:USERNAME:PASSWORD:BASE_DN
+ QStringList items = str.split(QLatin1Char(':'));
+ if (items.count() == 5) {
+ QStringList::const_iterator it = items.constBegin();
+ QUrl url;
+ url.setScheme(QStringLiteral("ldap"));
+ url.setHost(urlpart_decode(*it++));
+
+ bool ok;
+ const int port = (*it++).toInt(&ok);
+ if (ok) {
+ url.setPort(port);
+ } else if (!it->isEmpty()) {
+ qCWarning(GPGPME_BACKEND_LOG) << "parseURL: malformed LDAP server port, ignoring: \"" << *it << "\"";
+ }
+
+ const QString userName = urlpart_decode(*it++);
+ if (!userName.isEmpty()) {
+ url.setUserName(userName);
+ }
+ const QString passWord = urlpart_decode(*it++);
+ if (!passWord.isEmpty()) {
+ url.setPassword(passWord);
+ }
+ url.setQuery(urlpart_decode(*it));
+ return url;
+ } else {
+ qCWarning(GPGPME_BACKEND_LOG) << "parseURL: malformed LDAP server:" << str;
+ }
+ }
+ // other URLs : assume wellformed URL syntax.
+ return QUrl(str);
+}
+
+// The opposite of parseURL
+static QString splitURL(int mRealArgType, const QUrl &url)
+{
+ if (mRealArgType == 33) { // LDAP server
+ // The format is HOSTNAME:PORT:USERNAME:PASSWORD:BASE_DN
+ Q_ASSERT(url.scheme() == QLatin1String("ldap"));
+ return urlpart_encode(url.host()) + QLatin1Char(':') +
+ (url.port() != -1 ? QString::number(url.port()) : QString()) + QLatin1Char(':') + // -1 is used for default ports, omit
+ urlpart_encode(url.userName()) + QLatin1Char(':') +
+ urlpart_encode(url.password()) + QLatin1Char(':') +
+ urlpart_encode(url.query());
+ }
+ return url.path();
+}
+
+QUrl QGpgMENewCryptoConfigEntry::urlValue() const
+{
+ const Type type = m_option.type();
+ Q_ASSERT(type == FilenameType || type == LdapServerType);
+ Q_ASSERT(!isList());
+ if (type == FilenameType) {
+ QUrl url;
+ url.setPath(QFile::decodeName(m_option.currentValue().stringValue()));
+ return url;
+ }
+ return parseURL(type, stringValue());
+}
+
+unsigned int QGpgMENewCryptoConfigEntry::numberOfTimesSet() const
+{
+ Q_ASSERT(m_option.alternateType() == NoType);
+ Q_ASSERT(isList());
+ return m_option.currentValue().uintValue();
+}
+
+std::vector<int> QGpgMENewCryptoConfigEntry::intValueList() const
+{
+ Q_ASSERT(m_option.alternateType() == IntegerType);
+ Q_ASSERT(isList());
+ return m_option.currentValue().intValues();
+}
+
+std::vector<unsigned int> QGpgMENewCryptoConfigEntry::uintValueList() const
+{
+ Q_ASSERT(m_option.alternateType() == UnsignedIntegerType);
+ Q_ASSERT(isList());
+ return m_option.currentValue().uintValues();
+}
+
+QList<QUrl> QGpgMENewCryptoConfigEntry::urlValueList() const
+{
+ const Type type = m_option.type();
+ Q_ASSERT(type == FilenameType || type == LdapServerType);
+ Q_ASSERT(isList());
+ const Argument arg = m_option.currentValue();
+ const std::vector<const char *> values = arg.stringValues();
+ QList<QUrl> ret;
+ Q_FOREACH(const char *value, values)
+ if (type == FilenameType) {
+ QUrl url;
+ url.setPath(QFile::decodeName(value));
+ ret << url;
+ } else {
+ ret << parseURL(type, QString::fromUtf8(value));
+ }
+ return ret;
+}
+
+void QGpgMENewCryptoConfigEntry::resetToDefault()
+{
+ m_option.resetToDefaultValue();
+}
+
+void QGpgMENewCryptoConfigEntry::setBoolValue(bool b)
+{
+ Q_ASSERT(m_option.alternateType() == NoType);
+ Q_ASSERT(!isList());
+ // A "no arg" option is either set or not set.
+ // Being set means createNoneArgument(), being unset means resetToDefault()
+ m_option.setNewValue(m_option.createNoneArgument(b));
+}
+
+void QGpgMENewCryptoConfigEntry::setStringValue(const QString &str)
+{
+ Q_ASSERT(m_option.alternateType() == StringType);
+ Q_ASSERT(!isList());
+ const Type type = m_option.type();
+ // When setting a string to empty (and there's no default), we need to act like resetToDefault
+ // Otherwise we try e.g. "ocsp-responder:0:" and gpgconf answers:
+ // "gpgconf: argument required for option ocsp-responder"
+ if (str.isEmpty() && !isOptional()) {
+ m_option.resetToDefaultValue();
+ } else if (type == FilenameType) {
+ m_option.setNewValue(m_option.createStringArgument(QFile::encodeName(str).constData()));
+ } else {
+ m_option.setNewValue(m_option.createStringArgument(str.toUtf8().constData()));
+ }
+}
+
+void QGpgMENewCryptoConfigEntry::setIntValue(int i)
+{
+ Q_ASSERT(m_option.alternateType() == IntegerType);
+ Q_ASSERT(!isList());
+ m_option.setNewValue(m_option.createIntArgument(i));
+}
+
+void QGpgMENewCryptoConfigEntry::setUIntValue(unsigned int i)
+{
+ Q_ASSERT(m_option.alternateType() == UnsignedIntegerType);
+ Q_ASSERT(!isList());
+ m_option.setNewValue(m_option.createUIntArgument(i));
+}
+
+void QGpgMENewCryptoConfigEntry::setURLValue(const QUrl &url)
+{
+ const Type type = m_option.type();
+ Q_ASSERT(type == FilenameType || type == LdapServerType);
+ Q_ASSERT(!isList());
+ const QString str = splitURL(type, url);
+ // cf. setStringValue()
+ if (str.isEmpty() && !isOptional()) {
+ m_option.resetToDefaultValue();
+ } else if (type == FilenameType) {
+ m_option.setNewValue(m_option.createStringArgument(QFile::encodeName(str).constData()));
+ } else {
+ m_option.setNewValue(m_option.createStringArgument(str.toUtf8().constData()));
+ }
+}
+
+void QGpgMENewCryptoConfigEntry::setNumberOfTimesSet(unsigned int i)
+{
+ Q_ASSERT(m_option.alternateType() == NoType);
+ Q_ASSERT(isList());
+ m_option.setNewValue(m_option.createNoneListArgument(i));
+}
+
+void QGpgMENewCryptoConfigEntry::setIntValueList(const std::vector<int> &lst)
+{
+ Q_ASSERT(m_option.alternateType() == IntegerType);
+ Q_ASSERT(isList());
+ m_option.setNewValue(m_option.createIntListArgument(lst));
+}
+
+void QGpgMENewCryptoConfigEntry::setUIntValueList(const std::vector<unsigned int> &lst)
+{
+ Q_ASSERT(m_option.alternateType() == UnsignedIntegerType);
+ Q_ASSERT(isList());
+ m_option.setNewValue(m_option.createUIntListArgument(lst));
+}
+
+void QGpgMENewCryptoConfigEntry::setURLValueList(const QList<QUrl> &urls)
+{
+ const Type type = m_option.type();
+ Q_ASSERT(m_option.alternateType() == StringType);
+ Q_ASSERT(isList());
+ std::vector<std::string> values;
+ values.reserve(urls.size());
+ Q_FOREACH (const QUrl &url, urls)
+ if (type == FilenameType) {
+ values.push_back(QFile::encodeName(url.path()).constData());
+ } else {
+ values.push_back(splitURL(type, url).toUtf8().constData());
+ }
+ m_option.setNewValue(m_option.createStringListArgument(values));
+}
+
+bool QGpgMENewCryptoConfigEntry::isDirty() const
+{
+ return m_option.dirty();
+}
+
+#if 0
+QString QGpgMENewCryptoConfigEntry::toString(bool escape) const
+{
+ // Basically the opposite of stringToValue
+ if (isStringType()) {
+ if (mValue.isNull()) {
+ return QString();
+ } else if (isList()) { // string list
+ QStringList lst = mValue.toStringList();
+ if (escape) {
+ for (QStringList::iterator it = lst.begin(); it != lst.end(); ++it) {
+ if (!(*it).isNull()) {
+ *it = gpgconf_escape(*it).prepend("\"");
+ }
+ }
+ }
+ QString res = lst.join(",");
+ //qCDebug(GPGPME_BACKEND_LOG) <<"toString:" << res;
+ return res;
+ } else { // normal string
+ QString res = mValue.toString();
+ if (escape) {
+ res = gpgconf_escape(res).prepend("\"");
+ }
+ return res;
+ }
+ }
+ if (!isList()) { // non-list non-string
+ if (mArgType == ArgType_None) {
+ return mValue.toBool() ? QString::fromLatin1("1") : QString();
+ } else { // some int
+ Q_ASSERT(mArgType == ArgType_Int || mArgType == ArgType_UInt);
+ return mValue.toString(); // int to string conversion
+ }
+ }
+
+ // Lists (of other types than strings)
+ if (mArgType == ArgType_None) {
+ return QString::number(numberOfTimesSet());
+ }
+ QStringList ret;
+ QList<QVariant> lst = mValue.toList();
+ for (QList<QVariant>::const_iterator it = lst.constBegin(); it != lst.constEnd(); ++it) {
+ ret << (*it).toString(); // QVariant does the conversion
+ }
+ return ret.join(",");
+}
+
+QString QGpgMENewCryptoConfigEntry::outputString() const
+{
+ Q_ASSERT(mSet);
+ return toString(true);
+}
+
+bool QGpgMENewCryptoConfigEntry::isStringType() const
+{
+ return (mArgType == QGpgME::NewCryptoConfigEntry::ArgType_String
+ || mArgType == QGpgME::NewCryptoConfigEntry::ArgType_Path
+ || mArgType == QGpgME::NewCryptoConfigEntry::ArgType_URL
+ || mArgType == QGpgME::NewCryptoConfigEntry::ArgType_LDAPURL);
+}
+
+void QGpgMENewCryptoConfigEntry::setDirty(bool b)
+{
+ mDirty = b;
+}
+#endif
diff --git a/lang/qt/src/qgpgmenewcryptoconfig.h b/lang/qt/src/qgpgmenewcryptoconfig.h
new file mode 100644
index 0000000..81b4cb4
--- /dev/null
+++ b/lang/qt/src/qgpgmenewcryptoconfig.h
@@ -0,0 +1,189 @@
+/*
+ qgpgmenewcryptoconfig.h
+
+ This file is part of qgpgme, the Qt API binding for gpgme
+ Copyright (c) 2010 Klarälvdalens Datakonsult AB
+ Copyright (c) 2016 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.
+*/
+
+#ifndef QGPGME_QGPGMENEWCRYPTOCONFIG_H
+#define QGPGME_QGPGMENEWCRYPTOCONFIG_H
+
+#include "qgpgme_export.h"
+#include "cryptoconfig.h"
+
+#include <QHash>
+#include <QStringList>
+#include <QVariant>
+
+#ifdef BUILDING_QGPGME
+# include "configuration.h"
+#else
+# include <gpgme++/configuration.h>
+#endif
+
+
+#include <vector>
+#include <utility>
+
+class QGpgMENewCryptoConfig;
+class QGpgMENewCryptoConfigComponent;
+class QGpgMENewCryptoConfigGroup;
+class QGpgMENewCryptoConfigEntry;
+
+class QGpgMENewCryptoConfigEntry : public QGpgME::CryptoConfigEntry
+{
+public:
+ QGpgMENewCryptoConfigEntry(const std::shared_ptr<QGpgMENewCryptoConfigGroup> &group, const GpgME::Configuration::Option &option);
+ ~QGpgMENewCryptoConfigEntry();
+
+ QString name() const Q_DECL_OVERRIDE;
+ QString description() const Q_DECL_OVERRIDE;
+ QString path() const Q_DECL_OVERRIDE;
+ bool isOptional() const Q_DECL_OVERRIDE;
+ bool isReadOnly() const Q_DECL_OVERRIDE;
+ bool isList() const Q_DECL_OVERRIDE;
+ bool isRuntime() const Q_DECL_OVERRIDE;
+ Level level() const Q_DECL_OVERRIDE;
+ ArgType argType() const Q_DECL_OVERRIDE;
+ bool isSet() const Q_DECL_OVERRIDE;
+ bool boolValue() const Q_DECL_OVERRIDE;
+ QString stringValue() const Q_DECL_OVERRIDE;
+ int intValue() const Q_DECL_OVERRIDE;
+ unsigned int uintValue() const Q_DECL_OVERRIDE;
+ QUrl urlValue() const Q_DECL_OVERRIDE;
+ unsigned int numberOfTimesSet() const Q_DECL_OVERRIDE;
+ std::vector<int> intValueList() const Q_DECL_OVERRIDE;
+ std::vector<unsigned int> uintValueList() const Q_DECL_OVERRIDE;
+ QList<QUrl> urlValueList() const Q_DECL_OVERRIDE;
+ void resetToDefault() Q_DECL_OVERRIDE;
+ void setBoolValue(bool) Q_DECL_OVERRIDE;
+ void setStringValue(const QString &) Q_DECL_OVERRIDE;
+ void setIntValue(int) Q_DECL_OVERRIDE;
+ void setUIntValue(unsigned int) Q_DECL_OVERRIDE;
+ void setURLValue(const QUrl &) Q_DECL_OVERRIDE;
+ void setNumberOfTimesSet(unsigned int) Q_DECL_OVERRIDE;
+ void setIntValueList(const std::vector<int> &) Q_DECL_OVERRIDE;
+ void setUIntValueList(const std::vector<unsigned int> &) Q_DECL_OVERRIDE;
+ void setURLValueList(const QList<QUrl> &) Q_DECL_OVERRIDE;
+ bool isDirty() const Q_DECL_OVERRIDE;
+
+#if 0
+ void setDirty(bool b);
+ QString outputString() const;
+
+protected:
+ bool isStringType() const;
+ QVariant stringToValue(const QString &value, bool unescape) const;
+ QString toString(bool escape) const;
+#endif
+private:
+ std::weak_ptr<QGpgMENewCryptoConfigGroup> m_group;
+ GpgME::Configuration::Option m_option;
+};
+
+class QGpgMENewCryptoConfigGroup : public QGpgME::CryptoConfigGroup
+{
+public:
+ QGpgMENewCryptoConfigGroup(const std::shared_ptr<QGpgMENewCryptoConfigComponent> &parent, const GpgME::Configuration::Option &option);
+ ~QGpgMENewCryptoConfigGroup();
+
+ QString name() const Q_DECL_OVERRIDE;
+ QString iconName() const Q_DECL_OVERRIDE
+ {
+ return QString();
+ }
+ QString description() const Q_DECL_OVERRIDE;
+ QString path() const Q_DECL_OVERRIDE;
+ QGpgME::CryptoConfigEntry::Level level() const Q_DECL_OVERRIDE;
+ QStringList entryList() const Q_DECL_OVERRIDE;
+ QGpgMENewCryptoConfigEntry *entry(const QString &name) const Q_DECL_OVERRIDE;
+
+private:
+ friend class QGpgMENewCryptoConfigComponent; // it adds the entries
+ std::weak_ptr<QGpgMENewCryptoConfigComponent> m_component;
+ GpgME::Configuration::Option m_option;
+ QStringList m_entryNames;
+ QHash< QString, std::shared_ptr<QGpgMENewCryptoConfigEntry> > m_entriesByName;
+};
+
+/// For docu, see kleo/cryptoconfig.h
+class QGpgMENewCryptoConfigComponent : public QGpgME::CryptoConfigComponent, public std::enable_shared_from_this<QGpgMENewCryptoConfigComponent>
+{
+public:
+ QGpgMENewCryptoConfigComponent();
+ ~QGpgMENewCryptoConfigComponent();
+
+ void setComponent(const GpgME::Configuration::Component &component);
+
+ QString name() const Q_DECL_OVERRIDE;
+ QString iconName() const Q_DECL_OVERRIDE
+ {
+ return name();
+ }
+ QString description() const Q_DECL_OVERRIDE;
+ QStringList groupList() const Q_DECL_OVERRIDE;
+ QGpgMENewCryptoConfigGroup *group(const QString &name) const Q_DECL_OVERRIDE;
+
+ void sync(bool runtime);
+
+private:
+ GpgME::Configuration::Component m_component;
+ QHash< QString, std::shared_ptr<QGpgMENewCryptoConfigGroup> > m_groupsByName;
+};
+
+/**
+ * CryptoConfig implementation around the gpgconf command-line tool
+ * For method docu, see kleo/cryptoconfig.h
+ */
+class QGPGME_EXPORT QGpgMENewCryptoConfig : public QGpgME::CryptoConfig
+{
+public:
+ /**
+ * Constructor
+ */
+ QGpgMENewCryptoConfig();
+ ~QGpgMENewCryptoConfig();
+
+ QStringList componentList() const Q_DECL_OVERRIDE;
+
+ QGpgMENewCryptoConfigComponent *component(const QString &name) const Q_DECL_OVERRIDE;
+
+ void clear() Q_DECL_OVERRIDE;
+ void sync(bool runtime) Q_DECL_OVERRIDE;
+
+private:
+ /// @param showErrors if true, a messagebox will be shown if e.g. gpgconf wasn't found
+ void reloadConfiguration(bool showErrors);
+
+private:
+ QHash< QString, std::shared_ptr<QGpgMENewCryptoConfigComponent> > m_componentsByName;
+ bool m_parsed;
+};
+
+#endif /* QGPGME_QGPGMENEWCRYPTOCONFIG_H */
diff --git a/lang/qt/src/qgpgmerefreshkeysjob.cpp b/lang/qt/src/qgpgmerefreshkeysjob.cpp
new file mode 100644
index 0000000..3d221f6
--- /dev/null
+++ b/lang/qt/src/qgpgmerefreshkeysjob.cpp
@@ -0,0 +1,225 @@
+/*
+ qgpgmerefreshkeysjob.cpp
+
+ This file is part of qgpgme, the Qt API binding for gpgme
+ Copyright (c) 2004 Klar�vdalens Datakonsult AB
+ Copyright (c) 2016 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.
+*/
+
+#define MAX_CMD_LENGTH 32768
+
+#include "qgpgmerefreshkeysjob.h"
+
+#include <QDebug>
+#include "gpgme_backend_debug.h"
+
+#include "context.h"
+
+#include <QByteArray>
+#include <QStringList>
+
+#include <gpg-error.h>
+
+#include <assert.h>
+
+QGpgME::QGpgMERefreshKeysJob::QGpgMERefreshKeysJob()
+ : RefreshKeysJob(0),
+ mProcess(0),
+ mError(0)
+{
+
+}
+
+QGpgME::QGpgMERefreshKeysJob::~QGpgMERefreshKeysJob()
+{
+
+}
+
+GpgME::Error QGpgME::QGpgMERefreshKeysJob::start(const QStringList &patterns)
+{
+ assert(mPatternsToDo.empty());
+
+ mPatternsToDo = patterns;
+ if (mPatternsToDo.empty()) {
+ mPatternsToDo.push_back(QStringLiteral(" ")); // empty list means all -> mae
+ }
+ // sure to fail the first
+ // startAProcess() guard clause
+
+ return startAProcess();
+}
+
+#if MAX_CMD_LENGTH < 65 + 128
+#error MAX_CMD_LENGTH is too low
+#endif
+
+GpgME::Error QGpgME::QGpgMERefreshKeysJob::startAProcess()
+{
+ if (mPatternsToDo.empty()) {
+ return GpgME::Error();
+ }
+ // create and start gpgsm process:
+ mProcess = new QProcess(this);
+ mProcess->setObjectName(QStringLiteral("gpgsm -k --with-validation --force-crl-refresh --enable-crl-checks"));
+
+ // FIXME: obbtain the path to gpgsm from gpgme, so we use the same instance.
+ mProcess->setProgram(QStringLiteral("gpgsm"));
+ QStringList arguments;
+ arguments << QStringLiteral("-k")
+ << QStringLiteral("--with-validation")
+ << QStringLiteral("--force-crl-refresh")
+ << QStringLiteral("--enable-crl-checks");
+ unsigned int commandLineLength = MAX_CMD_LENGTH;
+ commandLineLength -=
+ strlen("gpgsm") + 1 + strlen("-k") + 1 +
+ strlen("--with-validation") + 1 + strlen("--force-crl-refresh") + 1 +
+ strlen("--enable-crl-checks") + 1;
+ while (!mPatternsToDo.empty()) {
+ const QByteArray pat = mPatternsToDo.front().toUtf8().trimmed();
+ const unsigned int patLength = pat.length();
+ if (patLength >= commandLineLength) {
+ break;
+ }
+ mPatternsToDo.pop_front();
+ if (pat.isEmpty()) {
+ continue;
+ }
+ arguments << QLatin1String(pat);
+ commandLineLength -= patLength + 1;
+ }
+
+ mProcess->setArguments(arguments);
+
+ connect(mProcess, SIGNAL(finished(int,QProcess::ExitStatus)),
+ SLOT(slotProcessExited(int,QProcess::ExitStatus)));
+ connect(mProcess, SIGNAL(readyReadStandardOutput()),
+ SLOT(slotStdout()));
+ connect(mProcess, &QProcess::readyReadStandardError,
+ this, &QGpgMERefreshKeysJob::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::QGpgMERefreshKeysJob::slotCancel()
+{
+ if (mProcess) {
+ mProcess->kill();
+ }
+ mProcess = 0;
+ mError = GpgME::Error::fromCode(GPG_ERR_CANCELED, GPG_ERR_SOURCE_GPGSM);
+}
+
+void QGpgME::QGpgMERefreshKeysJob::slotStatus(QProcess *proc, const QString &type, const QStringList &args)
+{
+ if (proc != mProcess) {
+ return;
+ }
+ QStringList::const_iterator it = args.begin();
+ bool ok = false;
+
+ if (type == QLatin1String("ERROR")) {
+
+ if (args.size() < 2) {
+ qCDebug(GPGPME_BACKEND_LOG) << "not recognising ERROR with < 2 args!";
+ return;
+ }
+ const int source = (*++it).toInt(&ok);
+ if (!ok) {
+ qCDebug(GPGPME_BACKEND_LOG) << "expected number for first ERROR arg, got something else";
+ return;
+ }
+ ok = false;
+ const int code = (*++it).toInt(&ok);
+ if (!ok) {
+ qCDebug(GPGPME_BACKEND_LOG) << "expected number for second ERROR arg, got something else";
+ return;
+ }
+ mError = GpgME::Error::fromCode(code, source);
+
+ } else if (type == QLatin1String("PROGRESS")) {
+
+ if (args.size() < 4) {
+ qCDebug(GPGPME_BACKEND_LOG) << "not recognising PROGRESS with < 4 args!";
+ return;
+ }
+ const QString what = *++it;
+ ok = false;
+ (*++it).toInt(&ok);
+ if (!ok) {
+ qCDebug(GPGPME_BACKEND_LOG) << "expected number for \"type\", got something else";
+ return;
+ }
+ ok = false;
+ const int cur = (*++it).toInt(&ok);
+ if (!ok) {
+ qCDebug(GPGPME_BACKEND_LOG) << "expected number for \"cur\", got something else";
+ return;
+ }
+ ok = false;
+ const int total = (*++it).toInt(&ok);
+ if (!ok) {
+ qCDebug(GPGPME_BACKEND_LOG) << "expected number for \"total\", got something else";
+ return;
+ }
+ // TODO port
+ Q_EMIT progress(QString(), cur, total);
+
+ }
+}
+
+void QGpgME::QGpgMERefreshKeysJob::slotStderr()
+{
+ // implement? or not?
+}
+
+void QGpgME::QGpgMERefreshKeysJob::slotProcessExited(int exitCode, QProcess::ExitStatus exitStatus)
+{
+ if (!mError && !mPatternsToDo.empty()) {
+ if (const GpgME::Error err = startAProcess()) {
+ mError = err;
+ } else {
+ return;
+ }
+ }
+
+ 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);
+ deleteLater();
+}
+#include "qgpgmerefreshkeysjob.moc"
diff --git a/lang/qt/src/qgpgmerefreshkeysjob.h b/lang/qt/src/qgpgmerefreshkeysjob.h
new file mode 100644
index 0000000..2a54e38
--- /dev/null
+++ b/lang/qt/src/qgpgmerefreshkeysjob.h
@@ -0,0 +1,79 @@
+/*
+ qgpgmerefreshkeysjob.h
+
+ This file is part of qgpgme, the Qt API binding for gpgme
+ Copyright (c) 2004 Klarälvdalens Datakonsult AB
+ Copyright (c) 2016 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.
+*/
+
+#ifndef __QGPGME_QGPGMEREFRESHKEYSJOB_H__
+#define __QGPGME_QGPGMEREFRESHKEYSJOB_H__
+
+#include "refreshkeysjob.h"
+#ifdef BUILDING_QGPGME
+# include "context.h"
+#else
+#include "gpgme++/context.h"
+#endif
+
+#include <QStringList>
+#include <QProcess>
+
+namespace QGpgME
+{
+
+class QGpgMERefreshKeysJob : public RefreshKeysJob
+{
+ Q_OBJECT
+public:
+ QGpgMERefreshKeysJob();
+ ~QGpgMERefreshKeysJob();
+
+ /* from RefreshKeysJob */
+ GpgME::Error start(const QStringList &patterns) Q_DECL_OVERRIDE;
+
+private Q_SLOTS:
+ /* from Job */
+ void slotCancel() Q_DECL_OVERRIDE;
+
+ void slotStatus(QProcess *, const QString &, const QStringList &);
+ void slotStderr();
+ void slotProcessExited(int exitCode, QProcess::ExitStatus exitStatus);
+
+private:
+ GpgME::Error startAProcess();
+
+private:
+ QProcess *mProcess;
+ GpgME::Error mError;
+ QStringList mPatternsToDo;
+};
+
+}
+
+#endif // __QGPGME_QGPGMEREFRESHKEYSJOB_H__
diff --git a/lang/qt/src/qgpgmesecretkeyexportjob.cpp b/lang/qt/src/qgpgmesecretkeyexportjob.cpp
new file mode 100644
index 0000000..f4ec698
--- /dev/null
+++ b/lang/qt/src/qgpgmesecretkeyexportjob.cpp
@@ -0,0 +1,142 @@
+/*
+ qgpgmesecretexportjob.cpp
+
+ This file is part of qgpgme, the Qt API binding for gpgme
+ Copyright (c) 2004 Klar�vdalens Datakonsult AB
+ Copyright (c) 2016 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.
+*/
+
+#include "qgpgmesecretkeyexportjob.h"
+
+#include <QDebug>
+#include "gpgme_backend_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(0),
+ mProcess(0),
+ 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 = 0;
+ 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/qgpgmesecretkeyexportjob.h b/lang/qt/src/qgpgmesecretkeyexportjob.h
new file mode 100644
index 0000000..ad53f99
--- /dev/null
+++ b/lang/qt/src/qgpgmesecretkeyexportjob.h
@@ -0,0 +1,81 @@
+/*
+ qgpgmesecretkeyexportjob.h
+
+ This file is part of qgpgme, the Qt API binding for gpgme
+ Copyright (c) 2004 Klarälvdalens Datakonsult AB
+ Copyright (c) 2016 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.
+*/
+
+#ifndef __QGPGME_QGPGMESECRETKEYEXPORTJOB_H__
+#define __QGPGME_QGPGMESECRETKEYEXPORTJOB_H__
+
+#include "exportjob.h"
+#ifdef BUILDING_QGPGME
+# include "context.h"
+#else
+#include "gpgme++/context.h"
+#endif
+#include <QProcess>
+
+namespace GpgME
+{
+class Data;
+}
+
+namespace QGpgME
+{
+
+class QGpgMESecretKeyExportJob : public ExportJob
+{
+ Q_OBJECT
+public:
+ QGpgMESecretKeyExportJob(bool armour, const QString &charset);
+ ~QGpgMESecretKeyExportJob();
+
+ /* from ExportJob */
+ GpgME::Error start(const QStringList &patterns) Q_DECL_OVERRIDE;
+
+private Q_SLOTS:
+ /* from Job */
+ void slotCancel() Q_DECL_OVERRIDE;
+
+ void slotStdout();
+ void slotStderr();
+ void slotProcessExited(int exitCode, QProcess::ExitStatus exitStatus);
+
+private:
+ QProcess *mProcess;
+ QByteArray mKeyData;
+ GpgME::Error mError;
+ bool mArmour;
+ QString mCharset;
+};
+
+}
+
+#endif // __QGPGME_QGPGMESECRETKEYEXPORTJOB_H__
diff --git a/lang/qt/src/qgpgmesignencryptjob.cpp b/lang/qt/src/qgpgmesignencryptjob.cpp
new file mode 100644
index 0000000..d2e45b1
--- /dev/null
+++ b/lang/qt/src/qgpgmesignencryptjob.cpp
@@ -0,0 +1,171 @@
+/*
+ qgpgmesignencryptjob.cpp
+
+ This file is part of qgpgme, the Qt API binding for gpgme
+ Copyright (c) 2004, 2007 Klarälvdalens Datakonsult AB
+ Copyright (c) 2016 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.
+*/
+
+#include "qgpgmesignencryptjob.h"
+
+#include "dataprovider.h"
+
+#include "context.h"
+#include "data.h"
+#include "key.h"
+#include "exception.h"
+
+#include <QBuffer>
+
+
+#include <cassert>
+
+using namespace QGpgME;
+using namespace GpgME;
+
+QGpgMESignEncryptJob::QGpgMESignEncryptJob(Context *context)
+ : mixin_type(context),
+ mOutputIsBase64Encoded(false)
+{
+ lateInitialization();
+}
+
+QGpgMESignEncryptJob::~QGpgMESignEncryptJob() {}
+
+void QGpgMESignEncryptJob::setOutputIsBase64Encoded(bool on)
+{
+ mOutputIsBase64Encoded = on;
+}
+
+static QGpgMESignEncryptJob::result_type sign_encrypt(Context *ctx, QThread *thread, const std::vector<Key> &signers,
+ const std::vector<Key> &recipients, const std::weak_ptr<QIODevice> &plainText_,
+ const std::weak_ptr<QIODevice> &cipherText_, const Context::EncryptionFlags eflags, bool outputIsBsse64Encoded)
+{
+ const std::shared_ptr<QIODevice> &plainText = plainText_.lock();
+ const std::shared_ptr<QIODevice> &cipherText = cipherText_.lock();
+
+ const _detail::ToThreadMover ctMover(cipherText, thread);
+ const _detail::ToThreadMover ptMover(plainText, thread);
+
+ QGpgME::QIODeviceDataProvider in(plainText);
+ const Data indata(&in);
+
+ ctx->clearSigningKeys();
+ Q_FOREACH (const Key &signer, signers)
+ if (!signer.isNull())
+ if (const Error err = ctx->addSigningKey(signer)) {
+ return std::make_tuple(SigningResult(err), EncryptionResult(), QByteArray(), QString(), Error());
+ }
+
+ if (!cipherText) {
+ QGpgME::QByteArrayDataProvider out;
+ Data outdata(&out);
+
+ if (outputIsBsse64Encoded) {
+ outdata.setEncoding(Data::Base64Encoding);
+ }
+
+ const std::pair<SigningResult, EncryptionResult> res = ctx->signAndEncrypt(recipients, indata, outdata, eflags);
+ Error ae;
+ const QString log = _detail::audit_log_as_html(ctx, ae);
+ return std::make_tuple(res.first, res.second, out.data(), log, ae);
+ } else {
+ QGpgME::QIODeviceDataProvider out(cipherText);
+ Data outdata(&out);
+
+ if (outputIsBsse64Encoded) {
+ outdata.setEncoding(Data::Base64Encoding);
+ }
+
+ const std::pair<SigningResult, EncryptionResult> res = ctx->signAndEncrypt(recipients, indata, outdata, eflags);
+ Error ae;
+ const QString log = _detail::audit_log_as_html(ctx, ae);
+ return std::make_tuple(res.first, res.second, QByteArray(), log, ae);
+ }
+
+}
+
+static QGpgMESignEncryptJob::result_type sign_encrypt_qba(Context *ctx, const std::vector<Key> &signers,
+ const std::vector<Key> &recipients, const QByteArray &plainText, const Context::EncryptionFlags eflags, bool outputIsBsse64Encoded)
+{
+ const std::shared_ptr<QBuffer> buffer(new QBuffer);
+ buffer->setData(plainText);
+ if (!buffer->open(QIODevice::ReadOnly)) {
+ assert(!"This should never happen: QBuffer::open() failed");
+ }
+ return sign_encrypt(ctx, 0, signers, recipients, buffer, std::shared_ptr<QIODevice>(), eflags, outputIsBsse64Encoded);
+}
+
+Error QGpgMESignEncryptJob::start(const std::vector<Key> &signers, const std::vector<Key> &recipients, const QByteArray &plainText, bool alwaysTrust)
+{
+ run(std::bind(&sign_encrypt_qba, std::placeholders::_1, signers, recipients, plainText, alwaysTrust ? Context::AlwaysTrust : Context::None, mOutputIsBase64Encoded));
+ return Error();
+}
+
+void QGpgMESignEncryptJob::start(const std::vector<Key> &signers, const std::vector<Key> &recipients,
+ const std::shared_ptr<QIODevice> &plainText, const std::shared_ptr<QIODevice> &cipherText, const Context::EncryptionFlags eflags)
+{
+ run(std::bind(&sign_encrypt, std::placeholders::_1, std::placeholders::_2, signers, recipients, std::placeholders::_3, std::placeholders::_4, eflags, mOutputIsBase64Encoded), plainText, cipherText);
+}
+
+void QGpgMESignEncryptJob::start(const std::vector<Key> &signers, const std::vector<Key> &recipients, const std::shared_ptr<QIODevice> &plainText, const std::shared_ptr<QIODevice> &cipherText, bool alwaysTrust)
+{
+ return start(signers, recipients, plainText, cipherText, alwaysTrust ? Context::AlwaysTrust : Context::None);
+}
+
+std::pair<SigningResult, EncryptionResult> QGpgMESignEncryptJob::exec(const std::vector<Key> &signers, const std::vector<Key> &recipients, const QByteArray &plainText, const Context::EncryptionFlags eflags, QByteArray &cipherText)
+{
+ const result_type r = sign_encrypt_qba(context(), signers, recipients, plainText, eflags, mOutputIsBase64Encoded);
+ cipherText = std::get<2>(r);
+ resultHook(r);
+ return mResult;
+}
+
+std::pair<SigningResult, EncryptionResult> QGpgMESignEncryptJob::exec(const std::vector<Key> &signers, const std::vector<Key> &recipients, const QByteArray &plainText, bool alwaysTrust, QByteArray &cipherText)
+{
+ return exec(signers, recipients, plainText, alwaysTrust ? Context::AlwaysTrust : Context::None, cipherText);
+}
+
+
+#if 0
+
+TODO port?
+void QGpgMESignEncryptJob::showErrorDialog(QWidget *parent, const QString &caption) const
+{
+ if ((mResult.first.error() && !mResult.first.error().isCanceled()) ||
+ (mResult.second.error() && !mResult.second.error().isCanceled())) {
+ MessageBox::error(parent, mResult.first, mResult.second, this, caption);
+ }
+}
+#endif
+
+void QGpgMESignEncryptJob::resultHook(const result_type &tuple)
+{
+ mResult = std::make_pair(std::get<0>(tuple), std::get<1>(tuple));
+}
+#include "qgpgmesignencryptjob.moc"
diff --git a/lang/qt/src/qgpgmesignencryptjob.h b/lang/qt/src/qgpgmesignencryptjob.h
new file mode 100644
index 0000000..e76c245
--- /dev/null
+++ b/lang/qt/src/qgpgmesignencryptjob.h
@@ -0,0 +1,121 @@
+/*
+ qgpgmesignencryptjob.h
+
+ This file is part of qgpgme, the Qt API binding for gpgme
+ Copyright (c) 2004,2007,2008 Klarälvdalens Datakonsult AB
+ Copyright (c) 2016 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.
+*/
+
+#ifndef __QGPGME_QGPGMESIGNENCRYPTJOB_H__
+#define __QGPGME_QGPGMESIGNENCRYPTJOB_H__
+
+#include "signencryptjob.h"
+
+#include "threadedjobmixin.h"
+
+#ifdef BUILDING_QGPGME
+# include "signingresult.h"
+#else
+#include <gpgme++/signingresult.h>
+#endif
+#ifdef BUILDING_QGPGME
+# include "encryptionresult.h"
+#else
+#include <gpgme++/encryptionresult.h>
+#endif
+#ifdef BUILDING_QGPGME
+# include "key.h"
+#else
+#include <gpgme++/key.h>
+#endif
+
+#include <utility>
+
+namespace QGpgME
+{
+
+class QGpgMESignEncryptJob
+#ifdef Q_MOC_RUN
+ : public SignEncryptJob
+#else
+ : public _detail::ThreadedJobMixin<SignEncryptJob, std::tuple<GpgME::SigningResult, GpgME::EncryptionResult, QByteArray, QString, GpgME::Error> >
+#endif
+{
+ Q_OBJECT
+#ifdef Q_MOC_RUN
+public Q_SLOTS:
+ void slotFinished();
+#endif
+public:
+ explicit QGpgMESignEncryptJob(GpgME::Context *context);
+ ~QGpgMESignEncryptJob();
+
+ /* from SignEncryptJob */
+ GpgME::Error start(const std::vector<GpgME::Key> &signers,
+ const std::vector<GpgME::Key> &recipients,
+ const QByteArray &plainText, bool alwaysTrust) Q_DECL_OVERRIDE;
+
+ /* from SignEncryptJob */
+ void start(const std::vector<GpgME::Key> &signers,
+ const std::vector<GpgME::Key> &recipients,
+ const std::shared_ptr<QIODevice> &plainText,
+ const std::shared_ptr<QIODevice> &cipherText,
+ bool alwaysTrust) Q_DECL_OVERRIDE;
+
+ void start(const std::vector<GpgME::Key> &signers,
+ const std::vector<GpgME::Key> &recipients,
+ const std::shared_ptr<QIODevice> &plainText,
+ const std::shared_ptr<QIODevice> &cipherText,
+ const GpgME::Context::EncryptionFlags flags) Q_DECL_OVERRIDE;
+
+ std::pair<GpgME::SigningResult, GpgME::EncryptionResult>
+ exec(const std::vector<GpgME::Key> &signers,
+ const std::vector<GpgME::Key> &recipients,
+ const QByteArray &plainText, bool alwaysTrust,
+ QByteArray &cipherText) Q_DECL_OVERRIDE;
+
+ std::pair<GpgME::SigningResult, GpgME::EncryptionResult>
+ exec(const std::vector<GpgME::Key> &signers,
+ const std::vector<GpgME::Key> &recipients,
+ const QByteArray &plainText, const GpgME::Context::EncryptionFlags flags,
+ QByteArray &cipherText) Q_DECL_OVERRIDE;
+
+ /* from SignEncryptJob */
+ void setOutputIsBase64Encoded(bool on) Q_DECL_OVERRIDE;
+
+ /* from ThreadedJobMixin */
+ void resultHook(const result_type &r) Q_DECL_OVERRIDE;
+
+private:
+ bool mOutputIsBase64Encoded;
+ std::pair<GpgME::SigningResult, GpgME::EncryptionResult> mResult;
+};
+
+}
+
+#endif // __QGPGME_QGPGMESIGNENCRYPTJOB_H__
diff --git a/lang/qt/src/qgpgmesignjob.cpp b/lang/qt/src/qgpgmesignjob.cpp
new file mode 100644
index 0000000..4e2312b
--- /dev/null
+++ b/lang/qt/src/qgpgmesignjob.cpp
@@ -0,0 +1,163 @@
+/*
+ qgpgmesignjob.cpp
+
+ This file is part of qgpgme, the Qt API binding for gpgme
+ Copyright (c) 2004,2007,2008 Klarälvdalens Datakonsult AB
+ Copyright (c) 2016 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.
+*/
+
+#include "qgpgmesignjob.h"
+
+#include "dataprovider.h"
+
+#include "context.h"
+#include "signingresult.h"
+#include "data.h"
+
+#include <QBuffer>
+
+
+#include <cassert>
+
+using namespace QGpgME;
+using namespace GpgME;
+
+QGpgMESignJob::QGpgMESignJob(Context *context)
+ : mixin_type(context),
+ mOutputIsBase64Encoded(false)
+{
+ lateInitialization();
+}
+
+QGpgMESignJob::~QGpgMESignJob() {}
+
+void QGpgMESignJob::setOutputIsBase64Encoded(bool on)
+{
+ mOutputIsBase64Encoded = on;
+}
+
+static QGpgMESignJob::result_type sign(Context *ctx, QThread *thread,
+ const std::vector<Key> &signers,
+ const std::weak_ptr<QIODevice> &plainText_,
+ const std::weak_ptr<QIODevice> &signature_,
+ SignatureMode mode,
+ bool outputIsBsse64Encoded)
+{
+
+ const std::shared_ptr<QIODevice> plainText = plainText_.lock();
+ const std::shared_ptr<QIODevice> signature = signature_.lock();
+
+ const _detail::ToThreadMover ptMover(plainText, thread);
+ const _detail::ToThreadMover sgMover(signature, thread);
+
+ QGpgME::QIODeviceDataProvider in(plainText);
+ const Data indata(&in);
+
+ ctx->clearSigningKeys();
+ Q_FOREACH (const Key &signer, signers)
+ if (!signer.isNull())
+ if (const Error err = ctx->addSigningKey(signer)) {
+ return std::make_tuple(SigningResult(err), QByteArray(), QString(), Error());
+ }
+
+ if (!signature) {
+ QGpgME::QByteArrayDataProvider out;
+ Data outdata(&out);
+
+ if (outputIsBsse64Encoded) {
+ outdata.setEncoding(Data::Base64Encoding);
+ }
+
+ const SigningResult res = ctx->sign(indata, outdata, mode);
+ Error ae;
+ const QString log = _detail::audit_log_as_html(ctx, ae);
+ return std::make_tuple(res, out.data(), log, ae);
+ } else {
+ QGpgME::QIODeviceDataProvider out(signature);
+ Data outdata(&out);
+
+ if (outputIsBsse64Encoded) {
+ outdata.setEncoding(Data::Base64Encoding);
+ }
+
+ const SigningResult res = ctx->sign(indata, outdata, mode);
+ Error ae;
+ const QString log = _detail::audit_log_as_html(ctx, ae);
+ return std::make_tuple(res, QByteArray(), log, ae);
+ }
+
+}
+
+static QGpgMESignJob::result_type sign_qba(Context *ctx,
+ const std::vector<Key> &signers,
+ const QByteArray &plainText,
+ SignatureMode mode,
+ bool outputIsBsse64Encoded)
+{
+ const std::shared_ptr<QBuffer> buffer(new QBuffer);
+ buffer->setData(plainText);
+ if (!buffer->open(QIODevice::ReadOnly)) {
+ assert(!"This should never happen: QBuffer::open() failed");
+ }
+ return sign(ctx, 0, signers, buffer, std::shared_ptr<QIODevice>(), mode, outputIsBsse64Encoded);
+}
+
+Error QGpgMESignJob::start(const std::vector<Key> &signers, const QByteArray &plainText, SignatureMode mode)
+{
+ run(std::bind(&sign_qba, std::placeholders::_1, signers, plainText, mode, mOutputIsBase64Encoded));
+ return Error();
+}
+
+void QGpgMESignJob::start(const std::vector<Key> &signers, const std::shared_ptr<QIODevice> &plainText, const std::shared_ptr<QIODevice> &signature, SignatureMode mode)
+{
+ run(std::bind(&sign, std::placeholders::_1, std::placeholders::_2, signers, std::placeholders::_3, std::placeholders::_4, mode, mOutputIsBase64Encoded), plainText, signature);
+}
+
+SigningResult QGpgMESignJob::exec(const std::vector<Key> &signers, const QByteArray &plainText, SignatureMode mode, QByteArray &signature)
+{
+ const result_type r = sign_qba(context(), signers, plainText, mode, mOutputIsBase64Encoded);
+ signature = std::get<1>(r);
+ resultHook(r);
+ return mResult;
+}
+
+void QGpgMESignJob::resultHook(const result_type &tuple)
+{
+ mResult = std::get<0>(tuple);
+}
+
+#if 0
+TODO port
+void QGpgMESignJob::showErrorDialog(QWidget *parent, const QString &caption) const
+{
+ if (mResult.error() && !mResult.error().isCanceled()) {
+ MessageBox::error(parent, mResult, this, caption);
+ }
+}
+#endif
+#include "qgpgmesignjob.moc"
diff --git a/lang/qt/src/qgpgmesignjob.h b/lang/qt/src/qgpgmesignjob.h
new file mode 100644
index 0000000..1d4a174
--- /dev/null
+++ b/lang/qt/src/qgpgmesignjob.h
@@ -0,0 +1,101 @@
+/*
+ qgpgmesignjob.h
+
+ This file is part of qgpgme, the Qt API binding for gpgme
+ Copyright (c) 2004,2007,2008 Klarälvdalens Datakonsult AB
+ Copyright (c) 2016 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.
+*/
+
+#ifndef __QGPGME_QGPGMESIGNJOB_H__
+#define __QGPGME_QGPGMESIGNJOB_H__
+
+#include "signjob.h"
+
+#include "threadedjobmixin.h"
+
+#ifdef BUILDING_QGPGME
+# include "signingresult.h"
+#else
+#include <gpgme++/signingresult.h>
+#endif
+#ifdef BUILDING_QGPGME
+# include "key.h"
+#else
+#include <gpgme++/key.h>
+#endif
+
+namespace QGpgME
+{
+
+class QGpgMESignJob
+#ifdef Q_MOC_RUN
+ : public SignJob
+#else
+ : public _detail::ThreadedJobMixin<SignJob, std::tuple<GpgME::SigningResult, QByteArray, QString, GpgME::Error> >
+#endif
+{
+ Q_OBJECT
+#ifdef Q_MOC_RUN
+public Q_SLOTS:
+ void slotFinished();
+#endif
+public:
+ explicit QGpgMESignJob(GpgME::Context *context);
+ ~QGpgMESignJob();
+
+ /* from SignJob */
+ GpgME::Error start(const std::vector<GpgME::Key> &signers,
+ const QByteArray &plainText,
+ GpgME::SignatureMode mode) Q_DECL_OVERRIDE;
+
+ /* from SignJob */
+ void start(const std::vector<GpgME::Key> &signers,
+ const std::shared_ptr<QIODevice> &plainText,
+ const std::shared_ptr<QIODevice> &signature,
+ GpgME::SignatureMode mode) Q_DECL_OVERRIDE;
+
+ /* from SignJob */
+ GpgME::SigningResult exec(const std::vector<GpgME::Key> &signers,
+ const QByteArray &plainText,
+ GpgME::SignatureMode mode,
+ QByteArray &signature) Q_DECL_OVERRIDE;
+
+ /* from SignJob */
+ void setOutputIsBase64Encoded(bool on) Q_DECL_OVERRIDE;
+
+ /* from ThreadedJobMixin */
+ void resultHook(const result_type &r) Q_DECL_OVERRIDE;
+
+private:
+ GpgME::SigningResult mResult;
+ bool mOutputIsBase64Encoded;
+};
+
+}
+
+#endif // __QGPGME_QGPGMESIGNJOB_H__
diff --git a/lang/qt/src/qgpgmesignkeyjob.cpp b/lang/qt/src/qgpgmesignkeyjob.cpp
new file mode 100644
index 0000000..e6c1478
--- /dev/null
+++ b/lang/qt/src/qgpgmesignkeyjob.cpp
@@ -0,0 +1,125 @@
+/*
+ qgpgmesignkeyjob.cpp
+
+ This file is part of qgpgme, the Qt API binding for gpgme
+ Copyright (c) 2008 Klarälvdalens Datakonsult AB
+ Copyright (c) 2016 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.
+*/
+
+#include "qgpgmesignkeyjob.h"
+
+#include "dataprovider.h"
+
+#include "context.h"
+#include "data.h"
+#include "gpgsignkeyeditinteractor.h"
+
+#include <cassert>
+#include <memory>
+
+using namespace QGpgME;
+using namespace GpgME;
+
+QGpgMESignKeyJob::QGpgMESignKeyJob(Context *context)
+ : mixin_type(context),
+ m_userIDsToSign(),
+ m_signingKey(),
+ m_checkLevel(0),
+ m_exportable(false),
+ m_nonRevocable(false),
+ m_started(false)
+{
+ lateInitialization();
+}
+
+QGpgMESignKeyJob::~QGpgMESignKeyJob() {}
+
+static QGpgMESignKeyJob::result_type sign_key(Context *ctx, const Key &key, const std::vector<unsigned int> &uids, unsigned int checkLevel, const Key &signer, unsigned int opts)
+{
+ QGpgME::QByteArrayDataProvider dp;
+ Data data(&dp);
+
+ GpgSignKeyEditInteractor *skei(new GpgSignKeyEditInteractor);
+ skei->setUserIDsToSign(uids);
+ skei->setCheckLevel(checkLevel);
+ skei->setSigningOptions(opts);
+
+ if (!signer.isNull())
+ if (const Error err = ctx->addSigningKey(signer)) {
+ return std::make_tuple(err, QString(), Error());
+ }
+ const Error err = ctx->edit(key, std::unique_ptr<EditInteractor> (skei), data);
+ Error ae;
+ const QString log = _detail::audit_log_as_html(ctx, ae);
+ return std::make_tuple(err, log, ae);
+}
+
+Error QGpgMESignKeyJob::start(const Key &key)
+{
+ unsigned int opts = 0;
+ if (m_nonRevocable) {
+ opts |= GpgSignKeyEditInteractor::NonRevocable;
+ }
+ if (m_exportable) {
+ opts |= GpgSignKeyEditInteractor::Exportable;
+ }
+ run(std::bind(&sign_key, std::placeholders::_1, key, m_userIDsToSign, m_checkLevel, m_signingKey, opts));
+ m_started = true;
+ return Error();
+}
+
+void QGpgMESignKeyJob::setUserIDsToSign(const std::vector<unsigned int> &idsToSign)
+{
+ assert(!m_started);
+ m_userIDsToSign = idsToSign;
+}
+
+void QGpgMESignKeyJob::setCheckLevel(unsigned int checkLevel)
+{
+ assert(!m_started);
+ m_checkLevel = checkLevel;
+}
+
+void QGpgMESignKeyJob::setExportable(bool exportable)
+{
+ assert(!m_started);
+ m_exportable = exportable;
+}
+
+void QGpgMESignKeyJob::setSigningKey(const Key &key)
+{
+ assert(!m_started);
+ m_signingKey = key;
+}
+
+void QGpgMESignKeyJob::setNonRevocable(bool nonRevocable)
+{
+ assert(!m_started);
+ m_nonRevocable = nonRevocable;
+}
+#include "qgpgmesignkeyjob.moc"
diff --git a/lang/qt/src/qgpgmesignkeyjob.h b/lang/qt/src/qgpgmesignkeyjob.h
new file mode 100644
index 0000000..6cdb7db
--- /dev/null
+++ b/lang/qt/src/qgpgmesignkeyjob.h
@@ -0,0 +1,94 @@
+/*
+ qgpgmesignkeyjob.h
+
+ This file is part of qgpgme, the Qt API binding for gpgme
+ Copyright (c) 2008 Klarälvdalens Datakonsult AB
+ Copyright (c) 2016 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.
+*/
+
+#ifndef __QGPGME_QGPGMESIGNKEYJOB_H__
+#define __QGPGME_QGPGMESIGNKEYJOB_H__
+
+#include "signkeyjob.h"
+
+#include "threadedjobmixin.h"
+
+#ifdef BUILDING_QGPGME
+# include "key.h"
+#else
+#include <gpgme++/key.h>
+#endif
+
+namespace QGpgME
+{
+
+class QGpgMESignKeyJob
+#ifdef Q_MOC_RUN
+ : public SignKeyJob
+#else
+ : public _detail::ThreadedJobMixin<SignKeyJob>
+#endif
+{
+ Q_OBJECT
+#ifdef Q_MOC_RUN
+public Q_SLOTS:
+ void slotFinished();
+#endif
+public:
+ explicit QGpgMESignKeyJob(GpgME::Context *context);
+ ~QGpgMESignKeyJob();
+
+ /* from SignKeyJob */
+ GpgME::Error start(const GpgME::Key &key) Q_DECL_OVERRIDE;
+
+ /* from SignKeyJob */
+ void setUserIDsToSign(const std::vector<unsigned int> &idsToSign) Q_DECL_OVERRIDE;
+
+ /* from SignKeyJob */
+ void setCheckLevel(unsigned int checkLevel) Q_DECL_OVERRIDE;
+
+ /* from SignKeyJob */
+ void setExportable(bool exportable) Q_DECL_OVERRIDE;
+
+ /* from SignKeyJob */
+ void setSigningKey(const GpgME::Key &key) Q_DECL_OVERRIDE;
+
+ /* from SignKeyJob */
+ void setNonRevocable(bool nonRevocable) Q_DECL_OVERRIDE;
+
+private:
+ std::vector<unsigned int> m_userIDsToSign;
+ GpgME::Key m_signingKey;
+ unsigned int m_checkLevel;
+ bool m_exportable;
+ bool m_nonRevocable;
+ bool m_started;
+};
+}
+
+#endif // __QGPGME_QGPGMESIGNKEYJOB_H__
diff --git a/lang/qt/src/qgpgmetofupolicyjob.cpp b/lang/qt/src/qgpgmetofupolicyjob.cpp
new file mode 100644
index 0000000..a24c946
--- /dev/null
+++ b/lang/qt/src/qgpgmetofupolicyjob.cpp
@@ -0,0 +1,65 @@
+/* qgpgmetofupolicyjob.cpp
+
+ Copyright (c) 2016 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.
+*/
+
+#include "qgpgmetofupolicyjob.h"
+
+#include "context.h"
+#include "key.h"
+#include "tofuinfo.h"
+
+
+using namespace QGpgME;
+using namespace GpgME;
+
+QGpgMETofuPolicyJob::QGpgMETofuPolicyJob(Context *context)
+ : mixin_type(context)
+{
+ lateInitialization();
+}
+
+QGpgMETofuPolicyJob::~QGpgMETofuPolicyJob() {}
+
+static QGpgMETofuPolicyJob::result_type policy_worker(Context *ctx, const Key &key, TofuInfo::Policy policy)
+{
+ return std::make_tuple (ctx->setTofuPolicy(key, policy),
+ QString(), Error());
+}
+
+void QGpgMETofuPolicyJob::start(const Key &key, TofuInfo::Policy policy)
+{
+ run(std::bind(&policy_worker, std::placeholders::_1, key, policy));
+}
+
+Error QGpgMETofuPolicyJob::exec(const Key &key, TofuInfo::Policy policy)
+{
+ return std::get<0>(policy_worker(context(), key, policy));
+}
+
+#include "qgpgmetofupolicyjob.moc"
diff --git a/lang/qt/src/qgpgmetofupolicyjob.h b/lang/qt/src/qgpgmetofupolicyjob.h
new file mode 100644
index 0000000..e7272e7
--- /dev/null
+++ b/lang/qt/src/qgpgmetofupolicyjob.h
@@ -0,0 +1,65 @@
+/* qgpgmetofupolicyjob.h
+
+ Copyright (c) 2016 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.
+*/
+#ifndef QGPGME_QGPGMETOFUPOLICYJOB_H
+#define QGPGME_QGPGMETOFUPOLICYJOB_H
+
+#include "tofupolicyjob.h"
+
+#include "threadedjobmixin.h"
+namespace GpgME
+{
+ class Key;
+} // namespace GpgME
+
+namespace QGpgME {
+
+class QGpgMETofuPolicyJob
+#ifdef Q_MOC_RUN
+ : public TofuPolicyJob
+#else
+ : public _detail::ThreadedJobMixin<TofuPolicyJob, std::tuple<GpgME::Error, QString, GpgME::Error> >
+#endif
+{
+ Q_OBJECT
+#ifdef Q_MOC_RUN
+public Q_SLOTS:
+ void slotFinished();
+#endif
+public:
+ explicit QGpgMETofuPolicyJob(GpgME::Context *context);
+ ~QGpgMETofuPolicyJob();
+
+ void start(const GpgME::Key &key, GpgME::TofuInfo::Policy policy) Q_DECL_OVERRIDE;
+ GpgME::Error exec(const GpgME::Key &key, GpgME::TofuInfo::Policy policy) Q_DECL_OVERRIDE;
+};
+
+}
+
+#endif
diff --git a/lang/qt/src/qgpgmeverifydetachedjob.cpp b/lang/qt/src/qgpgmeverifydetachedjob.cpp
new file mode 100644
index 0000000..8efef05
--- /dev/null
+++ b/lang/qt/src/qgpgmeverifydetachedjob.cpp
@@ -0,0 +1,118 @@
+/*
+ qgpgmeverifydetachedjob.cpp
+
+ This file is part of qgpgme, the Qt API binding for gpgme
+ Copyright (c) 2004,2007,2008 Klarälvdalens Datakonsult AB
+ Copyright (c) 2016 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.
+*/
+
+#include "qgpgmeverifydetachedjob.h"
+
+#include "dataprovider.h"
+
+#include "context.h"
+#include "verificationresult.h"
+#include "data.h"
+
+#include <cassert>
+
+
+using namespace QGpgME;
+using namespace GpgME;
+
+QGpgMEVerifyDetachedJob::QGpgMEVerifyDetachedJob(Context *context)
+ : mixin_type(context)
+{
+ lateInitialization();
+}
+
+QGpgMEVerifyDetachedJob::~QGpgMEVerifyDetachedJob() {}
+
+static QGpgMEVerifyDetachedJob::result_type verify_detached(Context *ctx, QThread *thread, const std::weak_ptr<QIODevice> &signature_, const std::weak_ptr<QIODevice> &signedData_)
+{
+ const std::shared_ptr<QIODevice> signature = signature_.lock();
+ const std::shared_ptr<QIODevice> signedData = signedData_.lock();
+
+ const _detail::ToThreadMover sgMover(signature, thread);
+ const _detail::ToThreadMover sdMover(signedData, thread);
+
+ QGpgME::QIODeviceDataProvider sigDP(signature);
+ Data sig(&sigDP);
+
+ QGpgME::QIODeviceDataProvider dataDP(signedData);
+ Data data(&dataDP);
+
+ const VerificationResult res = ctx->verifyDetachedSignature(sig, data);
+ Error ae;
+ const QString log = _detail::audit_log_as_html(ctx, ae);
+
+ return std::make_tuple(res, log, ae);
+}
+
+static QGpgMEVerifyDetachedJob::result_type verify_detached_qba(Context *ctx, const QByteArray &signature, const QByteArray &signedData)
+{
+ QGpgME::QByteArrayDataProvider sigDP(signature);
+ Data sig(&sigDP);
+
+ QGpgME::QByteArrayDataProvider dataDP(signedData);
+ Data data(&dataDP);
+
+ const VerificationResult res = ctx->verifyDetachedSignature(sig, data);
+ Error ae;
+ const QString log = _detail::audit_log_as_html(ctx, ae);
+
+ return std::make_tuple(res, log, ae);
+
+}
+
+Error QGpgMEVerifyDetachedJob::start(const QByteArray &signature, const QByteArray &signedData)
+{
+ run(std::bind(&verify_detached_qba, std::placeholders::_1, signature, signedData));
+ return Error();
+}
+
+void QGpgMEVerifyDetachedJob::start(const std::shared_ptr<QIODevice> &signature, const std::shared_ptr<QIODevice> &signedData)
+{
+ run(std::bind(&verify_detached, std::placeholders::_1, std::placeholders::_2, std::placeholders::_3, std::placeholders::_4), signature, signedData);
+}
+
+GpgME::VerificationResult QGpgME::QGpgMEVerifyDetachedJob::exec(const QByteArray &signature,
+ const QByteArray &signedData)
+{
+ const result_type r = verify_detached_qba(context(), signature, signedData);
+ resultHook(r);
+ return mResult;
+}
+
+//PENDING(marc) implement showErrorDialog()
+
+void QGpgME::QGpgMEVerifyDetachedJob::resultHook(const result_type &tuple)
+{
+ mResult = std::get<0>(tuple);
+}
+#include "qgpgmeverifydetachedjob.moc"
diff --git a/lang/qt/src/qgpgmeverifydetachedjob.h b/lang/qt/src/qgpgmeverifydetachedjob.h
new file mode 100644
index 0000000..051caf0
--- /dev/null
+++ b/lang/qt/src/qgpgmeverifydetachedjob.h
@@ -0,0 +1,85 @@
+/*
+ qgpgmeverifydetachedjob.h
+
+ This file is part of qgpgme, the Qt API binding for gpgme
+ Copyright (c) 2004,2007,2008 Klarälvdalens Datakonsult AB
+ Copyright (c) 2016 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.
+*/
+
+#ifndef __QGPGME_QGPGMEVERIFYDETACHEDJOB_H__
+#define __QGPGME_QGPGMEVERIFYDETACHEDJOB_H__
+
+#include "verifydetachedjob.h"
+
+#include "threadedjobmixin.h"
+
+#ifdef BUILDING_QGPGME
+# include "verificationresult.h"
+#else
+#include <gpgme++/verificationresult.h>
+#endif
+
+namespace QGpgME
+{
+
+class QGpgMEVerifyDetachedJob
+#ifdef Q_MOC_RUN
+ : public VerifyDetachedJob
+#else
+ : public _detail::ThreadedJobMixin<VerifyDetachedJob, std::tuple<GpgME::VerificationResult, QString, GpgME::Error> >
+#endif
+{
+ Q_OBJECT
+#ifdef Q_MOC_RUN
+public Q_SLOTS:
+ void slotFinished();
+#endif
+public:
+ explicit QGpgMEVerifyDetachedJob(GpgME::Context *context);
+ ~QGpgMEVerifyDetachedJob();
+
+ /* from VerifyDetachedJob */
+ GpgME::Error start(const QByteArray &signature, const QByteArray &signedData) Q_DECL_OVERRIDE;
+
+ /* from VerifyDetachedJob */
+ void start(const std::shared_ptr<QIODevice> &signature, const std::shared_ptr<QIODevice> &signedData) Q_DECL_OVERRIDE;
+
+ /* from VerifyDetachedJob */
+ GpgME::VerificationResult exec(const QByteArray &signature,
+ const QByteArray &signedData) Q_DECL_OVERRIDE;
+
+ /* from ThreadedJobMixin */
+ void resultHook(const result_type &r) Q_DECL_OVERRIDE;
+
+private:
+ GpgME::VerificationResult mResult;
+};
+
+}
+
+#endif // __QGPGME_QGPGMEVERIFYDETACHEDJOB_H__
diff --git a/lang/qt/src/qgpgmeverifyopaquejob.cpp b/lang/qt/src/qgpgmeverifyopaquejob.cpp
new file mode 100644
index 0000000..b513f82
--- /dev/null
+++ b/lang/qt/src/qgpgmeverifyopaquejob.cpp
@@ -0,0 +1,125 @@
+/*
+ qgpgmeverifyopaquejob.cpp
+
+ This file is part of qgpgme, the Qt API binding for gpgme
+ Copyright (c) 2004,2007,2008 Klarälvdalens Datakonsult AB
+ Copyright (c) 2016 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.
+*/
+
+#include "qgpgmeverifyopaquejob.h"
+
+#include "dataprovider.h"
+
+#include "context.h"
+#include "verificationresult.h"
+#include "data.h"
+
+#include <QBuffer>
+
+
+#include <cassert>
+
+using namespace QGpgME;
+using namespace GpgME;
+
+QGpgMEVerifyOpaqueJob::QGpgMEVerifyOpaqueJob(Context *context)
+ : mixin_type(context)
+{
+ lateInitialization();
+}
+
+QGpgMEVerifyOpaqueJob::~QGpgMEVerifyOpaqueJob() {}
+
+static QGpgMEVerifyOpaqueJob::result_type verify_opaque(Context *ctx, QThread *thread, const std::weak_ptr<QIODevice> &signedData_, const std::weak_ptr<QIODevice> &plainText_)
+{
+
+ const std::shared_ptr<QIODevice> plainText = plainText_.lock();
+ const std::shared_ptr<QIODevice> signedData = signedData_.lock();
+
+ const _detail::ToThreadMover ptMover(plainText, thread);
+ const _detail::ToThreadMover sdMover(signedData, thread);
+
+ QGpgME::QIODeviceDataProvider in(signedData);
+ const Data indata(&in);
+
+ if (!plainText) {
+ QGpgME::QByteArrayDataProvider out;
+ Data outdata(&out);
+
+ const VerificationResult res = ctx->verifyOpaqueSignature(indata, outdata);
+ Error ae;
+ const QString log = _detail::audit_log_as_html(ctx, ae);
+ return std::make_tuple(res, out.data(), log, ae);
+ } else {
+ QGpgME::QIODeviceDataProvider out(plainText);
+ Data outdata(&out);
+
+ const VerificationResult res = ctx->verifyOpaqueSignature(indata, outdata);
+ Error ae;
+ const QString log = _detail::audit_log_as_html(ctx, ae);
+ return std::make_tuple(res, QByteArray(), log, ae);
+ }
+
+}
+
+static QGpgMEVerifyOpaqueJob::result_type verify_opaque_qba(Context *ctx, const QByteArray &signedData)
+{
+ const std::shared_ptr<QBuffer> buffer(new QBuffer);
+ buffer->setData(signedData);
+ if (!buffer->open(QIODevice::ReadOnly)) {
+ assert(!"This should never happen: QBuffer::open() failed");
+ }
+ return verify_opaque(ctx, 0, buffer, std::shared_ptr<QIODevice>());
+}
+
+Error QGpgMEVerifyOpaqueJob::start(const QByteArray &signedData)
+{
+ run(std::bind(&verify_opaque_qba, std::placeholders::_1, signedData));
+ return Error();
+}
+
+void QGpgMEVerifyOpaqueJob::start(const std::shared_ptr<QIODevice> &signedData, const std::shared_ptr<QIODevice> &plainText)
+{
+ run(std::bind(&verify_opaque, std::placeholders::_1, std::placeholders::_2, std::placeholders::_3, std::placeholders::_4), signedData, plainText);
+}
+
+GpgME::VerificationResult QGpgME::QGpgMEVerifyOpaqueJob::exec(const QByteArray &signedData, QByteArray &plainText)
+{
+ const result_type r = verify_opaque_qba(context(), signedData);
+ plainText = std::get<1>(r);
+ resultHook(r);
+ return mResult;
+}
+
+//PENDING(marc) implement showErrorDialog()
+
+void QGpgME::QGpgMEVerifyOpaqueJob::resultHook(const result_type &tuple)
+{
+ mResult = std::get<0>(tuple);
+}
+#include "qgpgmeverifyopaquejob.moc"
diff --git a/lang/qt/src/qgpgmeverifyopaquejob.h b/lang/qt/src/qgpgmeverifyopaquejob.h
new file mode 100644
index 0000000..87c94a3
--- /dev/null
+++ b/lang/qt/src/qgpgmeverifyopaquejob.h
@@ -0,0 +1,84 @@
+/*
+ qgpgmeverifyopaquejob.h
+
+ This file is part of qgpgme, the Qt API binding for gpgme
+ Copyright (c) 2004,2007,2008 Klarälvdalens Datakonsult AB
+ Copyright (c) 2016 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.
+*/
+
+#ifndef __QGPGME_QGPGMEVERIFYOPAQUEJOB_H__
+#define __QGPGME_QGPGMEVERIFYOPAQUEJOB_H__
+
+#include "verifyopaquejob.h"
+
+#include "threadedjobmixin.h"
+
+#ifdef BUILDING_QGPGME
+# include "verificationresult.h"
+#else
+#include <gpgme++/verificationresult.h>
+#endif
+
+namespace QGpgME
+{
+
+class QGpgMEVerifyOpaqueJob
+#ifdef Q_MOC_RUN
+ : public VerifyOpaqueJob
+#else
+ : public _detail::ThreadedJobMixin<VerifyOpaqueJob, std::tuple<GpgME::VerificationResult, QByteArray, QString, GpgME::Error> >
+#endif
+{
+ Q_OBJECT
+#ifdef Q_MOC_RUN
+public Q_SLOTS:
+ void slotFinished();
+#endif
+public:
+ explicit QGpgMEVerifyOpaqueJob(GpgME::Context *context);
+ ~QGpgMEVerifyOpaqueJob();
+
+ /* from VerifyOpaqueJob */
+ GpgME::Error start(const QByteArray &signedData) Q_DECL_OVERRIDE;
+
+ /* from VerifyOpaqueJob */
+ void start(const std::shared_ptr<QIODevice> &signedData, const std::shared_ptr<QIODevice> &plainText) Q_DECL_OVERRIDE;
+
+ /* form VerifyOpaqueJob */
+ GpgME::VerificationResult exec(const QByteArray &signedData, QByteArray &plainData) Q_DECL_OVERRIDE;
+
+ /* from ThreadedJobMixin */
+ void resultHook(const result_type &r) Q_DECL_OVERRIDE;
+
+private:
+ GpgME::VerificationResult mResult;
+};
+
+}
+
+#endif // __QGPGME_QGPGMEVERIFYOPAQUEJOB_H__
diff --git a/lang/qt/src/qgpgmewkspublishjob.cpp b/lang/qt/src/qgpgmewkspublishjob.cpp
new file mode 100644
index 0000000..8f97cb5
--- /dev/null
+++ b/lang/qt/src/qgpgmewkspublishjob.cpp
@@ -0,0 +1,189 @@
+/* wkspublishjob.cpp
+
+ Copyright (c) 2016 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.
+*/
+
+#include "qgpgmewkspublishjob.h"
+
+#include "context.h"
+#include "key.h"
+#include "util.h"
+
+#include <QFileInfo>
+#include <QDir>
+#include <QProcess>
+
+/* Timeout for the WKS Processes will be 5 Minutes as
+ * they can involve pinentry questions. */
+#define TIMEOUT_VALUE (5*60*1000)
+
+using namespace QGpgME;
+using namespace GpgME;
+
+QGpgMEWKSPublishJob::QGpgMEWKSPublishJob(Context *context)
+ : mixin_type(context)
+{
+ lateInitialization();
+}
+
+QGpgMEWKSPublishJob::~QGpgMEWKSPublishJob() {}
+
+static QString getWKSClient()
+{
+ auto libexecdir = QString::fromLocal8Bit(dirInfo("libexecdir"));
+ if (libexecdir.isEmpty()) {
+ return QString();
+ }
+
+ const QFileInfo fi(QDir(libexecdir).absoluteFilePath(QStringLiteral("gpg-wks-client")));
+ if (fi.exists() && fi.isExecutable()) {
+ return fi.absoluteFilePath();
+ }
+ return QString();
+}
+
+static QGpgMEWKSPublishJob::result_type check_worker(const QString &mail)
+{
+ if (mail.isEmpty()) {
+ return std::make_tuple (Error(make_error(GPG_ERR_INV_ARG)),
+ QByteArray(), QByteArray(), QString(), Error());
+ }
+
+ const auto wksPath = getWKSClient();
+ if (wksPath.isEmpty()) {
+ return std::make_tuple (Error(make_error(GPG_ERR_NOT_SUPPORTED)),
+ QByteArray(), QByteArray(), QString(), Error());
+ }
+
+ /* QProcess instead of engine_spawn because engine_spawn does not communicate
+ * the return value of the process and we are in qt anyway. */
+ QProcess proc;
+ proc.setProgram(wksPath);
+ proc.setArguments(QStringList() << QStringLiteral("--supported") << mail);
+ proc.start();
+ if (!proc.waitForStarted()) {
+ return std::make_tuple (Error(make_error(GPG_ERR_NOT_SUPPORTED)),
+ QByteArray(), QByteArray(), QString(), Error());
+ }
+ if (!proc.waitForFinished(TIMEOUT_VALUE)) {
+ return std::make_tuple (Error(make_error(GPG_ERR_TIMEOUT)),
+ QByteArray(), QByteArray(), QString(), Error());
+ }
+ if (proc.exitStatus() == QProcess::NormalExit && proc.exitCode() == 0) {
+ return std::make_tuple (Error(), QByteArray(), QByteArray(), QString(), Error());
+ }
+ return std::make_tuple (Error(make_error(GPG_ERR_NOT_ENABLED)),
+ QByteArray(), QByteArray(), QString(), Error());
+}
+
+static QGpgMEWKSPublishJob::result_type create_worker(const char *fpr, const QString &mail)
+{
+ if (mail.isEmpty() || !fpr) {
+ return std::make_tuple (Error(make_error(GPG_ERR_INV_ARG)),
+ QByteArray(), QByteArray(), QString(), Error());
+ }
+
+ const auto wksPath = getWKSClient();
+ if (wksPath.isEmpty()) {
+ return std::make_tuple (Error(make_error(GPG_ERR_NOT_SUPPORTED)),
+ QByteArray(), QByteArray(), QString(), Error());
+ }
+
+ QProcess proc;
+ proc.setProgram(wksPath);
+ proc.setArguments(QStringList() << QStringLiteral("--create")
+ << QLatin1String(fpr)
+ << mail);
+ proc.start();
+ if (!proc.waitForStarted()) {
+ return std::make_tuple (Error(make_error(GPG_ERR_NOT_SUPPORTED)),
+ QByteArray(), QByteArray(), QString(), Error());
+ }
+
+ if (!proc.waitForFinished(TIMEOUT_VALUE)) {
+ return std::make_tuple (Error(make_error(GPG_ERR_TIMEOUT)),
+ QByteArray(), QByteArray(), QString(), Error());
+ }
+ if (proc.exitStatus() == QProcess::NormalExit && proc.exitCode() == 0) {
+ return std::make_tuple (Error(), proc.readAllStandardOutput(),
+ proc.readAllStandardError(), QString(), Error());
+ }
+ return std::make_tuple (Error(make_error(GPG_ERR_GENERAL)),
+ proc.readAllStandardOutput(), proc.readAllStandardError(), QString(), Error());
+}
+
+static QGpgMEWKSPublishJob::result_type recieve_worker(const QByteArray &response)
+{
+ if (response.isEmpty()) {
+ return std::make_tuple (Error(make_error(GPG_ERR_INV_ARG)),
+ QByteArray(), QByteArray(), QString(), Error());
+ }
+
+ const auto wksPath = getWKSClient();
+ if (wksPath.isEmpty()) {
+ return std::make_tuple (Error(make_error(GPG_ERR_NOT_SUPPORTED)),
+ QByteArray(), QByteArray(), QString(), Error());
+ }
+
+ QProcess proc;
+ proc.setProgram(wksPath);
+ proc.setArguments(QStringList() << QStringLiteral("--receive"));
+ proc.start();
+ if (!proc.waitForStarted()) {
+ return std::make_tuple (Error(make_error(GPG_ERR_NOT_SUPPORTED)),
+ QByteArray(), QByteArray(), QString(), Error());
+ }
+ proc.write(response);
+ proc.closeWriteChannel();
+ if (!proc.waitForFinished(TIMEOUT_VALUE)) {
+ return std::make_tuple (Error(make_error(GPG_ERR_TIMEOUT)),
+ QByteArray(), QByteArray(), QString(), Error());
+ }
+ if (proc.exitStatus() == QProcess::NormalExit && proc.exitCode() == 0) {
+ return std::make_tuple (Error(), proc.readAllStandardOutput(),
+ proc.readAllStandardError(), QString(), Error());
+ }
+ return std::make_tuple (Error(make_error(GPG_ERR_GENERAL)),
+ proc.readAllStandardOutput(), proc.readAllStandardError(), QString(), Error());
+}
+
+void QGpgMEWKSPublishJob::startCheck(const QString &mailbox)
+{
+ run(std::bind(&check_worker, mailbox));
+}
+
+void QGpgMEWKSPublishJob::startCreate(const char *fpr, const QString &mailbox) {
+ run(std::bind(&create_worker, fpr, mailbox));
+}
+
+void QGpgMEWKSPublishJob::startRecieve(const QByteArray &response)
+{
+ run(std::bind(&recieve_worker, response));
+}
+
+#include "qgpgmewkspublishjob.moc"
diff --git a/lang/qt/src/qgpgmewkspublishjob.h b/lang/qt/src/qgpgmewkspublishjob.h
new file mode 100644
index 0000000..1a31149
--- /dev/null
+++ b/lang/qt/src/qgpgmewkspublishjob.h
@@ -0,0 +1,70 @@
+/* qgpgmewkspublishjob.h
+
+ Copyright (c) 2016 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.
+*/
+#ifndef QGPGME_QGPGMEWKSPUBLISHJOB_H
+#define QGPGME_QGPGMEWKSPUBLISHJOB_H
+
+#include "wkspublishjob.h"
+
+#include "threadedjobmixin.h"
+namespace GpgME
+{
+ class Key;
+} // namespace GpgME
+
+namespace QGpgME {
+
+/**
+ * Handles Web Key Service Publishing. Needs WKS tools installed and
+ * server support.
+ */
+class QGpgMEWKSPublishJob
+#ifdef Q_MOC_RUN
+ : public WKSPublishJob
+#else
+ : public _detail::ThreadedJobMixin<WKSPublishJob, std::tuple<GpgME::Error, QByteArray, QByteArray, QString, GpgME::Error> >
+#endif
+{
+ Q_OBJECT
+#ifdef Q_MOC_RUN
+public Q_SLOTS:
+ void slotFinished();
+#endif
+public:
+ explicit QGpgMEWKSPublishJob(GpgME::Context *context);
+ ~QGpgMEWKSPublishJob();
+
+ void startCheck(const QString &mailbox) Q_DECL_OVERRIDE;
+ void startCreate(const char *fpr, const QString &mailbox) Q_DECL_OVERRIDE;
+ void startRecieve(const QByteArray &response) Q_DECL_OVERRIDE;
+};
+
+}
+
+#endif
diff --git a/lang/qt/src/refreshkeysjob.h b/lang/qt/src/refreshkeysjob.h
new file mode 100644
index 0000000..a97de80
--- /dev/null
+++ b/lang/qt/src/refreshkeysjob.h
@@ -0,0 +1,94 @@
+/*
+ refreshkeysjob.h
+
+ This file is part of qgpgme, the Qt API binding for gpgme
+ Copyright (c) 2004 Klarälvdalens Datakonsult AB
+ Copyright (c) 2016 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.
+*/
+
+#ifndef __KLEO_REFRESHKEYSJOB_H__
+#define __KLEO_REFRESHKEYSJOB_H__
+
+#include "job.h"
+#include "qgpgme_export.h"
+
+#include <vector>
+
+namespace GpgME
+{
+class Error;
+class Key;
+}
+
+class QStringList;
+
+namespace QGpgME
+{
+
+/**
+ @short An abstract base class for asynchronous key refreshers.
+
+ To use a RefreshKeysJob, first obtain an instance from the
+ CryptoBackend implementation, connect the progress() and result()
+ signals to suitable slots and then start the key refresh with a
+ call to start(). This call might fail, in which case the
+ RefreshKeysJob instance will have scheduled its own destruction
+ with a call to QObject::deleteLater().
+
+ After result() is emitted, the KeyListJob will schedule it's own
+ destruction by calling QObject::deleteLater().
+*/
+class QGPGME_EXPORT RefreshKeysJob : public Job
+{
+ Q_OBJECT
+protected:
+ explicit RefreshKeysJob(QObject *parent);
+public:
+ ~RefreshKeysJob();
+
+ /**
+ Starts the keylist operation. \a pattern is a list of patterns
+ used to restrict the list of keys returned. Empty patterns are
+ ignored. If \a pattern is empty or contains only empty strings,
+ all keys are returned (however, the backend is free to truncate
+ the result and should do so; when this happens, it will be
+ reported by the reult object).
+
+ If \a secretOnly is true, only keys for which the secret key is
+ also available are returned. Use this if you need to select a
+ key for signing.
+ */
+ virtual GpgME::Error start(const QStringList &patterns) = 0;
+
+Q_SIGNALS:
+ void result(const GpgME::Error &error);
+};
+
+}
+
+#endif // __KLEO_REFRESHKEYSJOB_H__
diff --git a/lang/qt/src/signencryptjob.h b/lang/qt/src/signencryptjob.h
new file mode 100644
index 0000000..4e07744
--- /dev/null
+++ b/lang/qt/src/signencryptjob.h
@@ -0,0 +1,153 @@
+/*
+ signencryptjob.h
+
+ This file is part of qgpgme, the Qt API binding for gpgme
+ Copyright (c) 2004, 2007 Klarälvdalens Datakonsult AB
+ Copyright (c) 2016 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.
+*/
+
+#ifndef __KLEO_SIGNENCRYPTJOB_H__
+#define __KLEO_SIGNENCRYPTJOB_H__
+
+#include "job.h"
+#include "qgpgme_export.h"
+
+#ifdef BUILDING_QGPGME
+# include "global.h"
+# include "context.h"
+#else
+# include <gpgme++/global.h>
+# include <gpgme++/context.h>
+#endif
+
+#include <memory>
+#include <vector>
+#include <utility>
+
+class QByteArray;
+class QIODevice;
+
+namespace GpgME
+{
+class Error;
+class Key;
+class SigningResult;
+class EncryptionResult;
+}
+
+namespace QGpgME
+{
+
+/**
+ @short An abstract base class for asynchronous combined signing and encrypting
+
+ To use a SignEncryptJob, first obtain an instance from the
+ CryptoBackend implementation, connect the progress() and result()
+ signals to suitable slots and then start the operation with a
+ call to start(). This call might fail, in which case the
+ SignEncryptJob instance will have scheduled it's own destruction
+ with a call to QObject::deleteLater().
+
+ After result() is emitted, the SignEncryptJob will schedule it's
+ own destruction by calling QObject::deleteLater().
+*/
+class QGPGME_EXPORT SignEncryptJob : public Job
+{
+ Q_OBJECT
+protected:
+ explicit SignEncryptJob(QObject *parent);
+public:
+ ~SignEncryptJob();
+
+ /**
+ Starts the combined signing and encrypting operation. \a signers
+ is the list of keys to sign \a plainText with. \a recipients is
+ a list of keys to encrypt the signed \a plainText to. In both
+ lists, empty (null) keys are ignored.
+
+ If \a alwaysTrust is true, validity checking for the
+ \em recipient keys will not be performed, but full validity
+ assumed for all \em recipient keys without further checks.
+ */
+ virtual QGPGME_DEPRECATED_EXPORT GpgME::Error start(const std::vector<GpgME::Key> &signers,
+ const std::vector<GpgME::Key> &recipients,
+ const QByteArray &plainText,
+ bool alwaysTrust = false) = 0;
+
+ /*!
+ \overload
+
+ If \a cipherText is non-null, the ciphertext is written
+ there. Otherwise, it will be delivered in the third argument of
+ result().
+
+ \throws GpgME::Exception if starting fails
+ */
+ virtual void start(const std::vector<GpgME::Key> &signers,
+ const std::vector<GpgME::Key> &recipients,
+ const std::shared_ptr<QIODevice> &plainText,
+ const std::shared_ptr<QIODevice> &cipherText = std::shared_ptr<QIODevice>(),
+ bool alwaysTrust = false) = 0;
+
+ virtual std::pair<GpgME::SigningResult, GpgME::EncryptionResult>
+ exec(const std::vector<GpgME::Key> &signers,
+ const std::vector<GpgME::Key> &recipients,
+ const QByteArray &plainText,
+ bool alwaysTrust, QByteArray &cipherText) = 0;
+
+ /*!
+ This is a hack to request BASE64 output (instead of whatever
+ comes out normally).
+ */
+ virtual void setOutputIsBase64Encoded(bool) = 0;
+
+ /** Like start but with an additional argument for EncryptionFlags for
+ * more flexibility. */
+ virtual void start(const std::vector<GpgME::Key> &signers,
+ const std::vector<GpgME::Key> &recipients,
+ const std::shared_ptr<QIODevice> &plainText,
+ const std::shared_ptr<QIODevice> &cipherText = std::shared_ptr<QIODevice>(),
+ const GpgME::Context::EncryptionFlags flags = GpgME::Context::None) = 0;
+
+ /** Like exec but with an additional argument for EncryptionFlags for
+ * more flexibility. */
+ virtual std::pair<GpgME::SigningResult, GpgME::EncryptionResult>
+ exec(const std::vector<GpgME::Key> &signers,
+ const std::vector<GpgME::Key> &recipients,
+ const QByteArray &plainText,
+ const GpgME::Context::EncryptionFlags flags, QByteArray &cipherText) = 0;
+Q_SIGNALS:
+ void result(const GpgME::SigningResult &signingresult,
+ const GpgME::EncryptionResult &encryptionresult,
+ const QByteArray &cipherText, const QString &auditLogAsHtml = QString(),
+ const GpgME::Error &auditLogError = GpgME::Error());
+};
+
+}
+
+#endif // __KLEO_SIGNENCRYPTJOB_H__
diff --git a/lang/qt/src/signjob.h b/lang/qt/src/signjob.h
new file mode 100644
index 0000000..cf5c628
--- /dev/null
+++ b/lang/qt/src/signjob.h
@@ -0,0 +1,122 @@
+/*
+ signjob.h
+
+ This file is part of qgpgme, the Qt API binding for gpgme
+ Copyright (c) 2004, 2007 Klarälvdalens Datakonsult AB
+ Copyright (c) 2016 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.
+*/
+
+#ifndef __KLEO_SIGNJOB_H__
+#define __KLEO_SIGNJOB_H__
+
+#include "job.h"
+
+#ifdef BUILDING_QGPGME
+# include "global.h"
+#else
+# include <gpgme++/global.h>
+#endif
+
+
+#include <vector>
+#include <memory>
+
+class QByteArray;
+class QIODevice;
+
+namespace GpgME
+{
+class Error;
+class Key;
+class SigningResult;
+}
+
+namespace QGpgME
+{
+
+/**
+ @short An abstract base class for asynchronous signing
+
+ To use a SignJob, first obtain an instance from the CryptoBackend
+ implementation, connect the progress() and result() signals to
+ suitable slots and then start the signing with a call to
+ start(). This call might fail, in which case the SignJob instance
+ will have scheduled it's own destruction with a call to
+ QObject::deleteLater().
+
+ After result() is emitted, the SignJob will schedule it's own
+ destruction by calling QObject::deleteLater().
+*/
+class QGPGME_EXPORT SignJob : public Job
+{
+ Q_OBJECT
+protected:
+ explicit SignJob(QObject *parent);
+public:
+ ~SignJob();
+
+ /**
+ Starts the signing operation. \a signers is the list of keys to
+ sign \a plainText with. Empty (null) keys are ignored.
+ */
+ virtual QGPGME_DEPRECATED_EXPORT GpgME::Error start(const std::vector<GpgME::Key> &signers,
+ const QByteArray &plainText,
+ GpgME::SignatureMode mode) = 0;
+
+ /*!
+ \overload
+
+ If \a signature is non-null the signature is written
+ there. Otherwise, it will be delivered in the second argument of
+ result().
+
+ \throws GpgME::Exception if starting fails
+ */
+ virtual void start(const std::vector<GpgME::Key> &signers,
+ const std::shared_ptr<QIODevice> &plainText,
+ const std::shared_ptr<QIODevice> &signature,
+ GpgME::SignatureMode mode) = 0;
+
+ virtual GpgME::SigningResult exec(const std::vector<GpgME::Key> &signers,
+ const QByteArray &plainText,
+ GpgME::SignatureMode mode,
+ QByteArray &signature) = 0;
+
+ /*!
+ This is a hack to request BASE64 output (instead of whatever
+ comes out normally).
+ */
+ virtual void setOutputIsBase64Encoded(bool) = 0;
+
+Q_SIGNALS:
+ void result(const GpgME::SigningResult &result, const QByteArray &signature, const QString &auditLogAsHtml = QString(), const GpgME::Error &auditLogError = GpgME::Error());
+};
+
+}
+
+#endif // __KLEO_SIGNJOB_H__
diff --git a/lang/qt/src/signkeyjob.h b/lang/qt/src/signkeyjob.h
new file mode 100644
index 0000000..b5efc01
--- /dev/null
+++ b/lang/qt/src/signkeyjob.h
@@ -0,0 +1,117 @@
+/*
+ signkeyjob.h
+
+ This file is part of qgpgme, the Qt API binding for gpgme
+ Copyright (c) 2008 Klarälvdalens Datakonsult AB
+ Copyright (c) 2016 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.
+*/
+
+#ifndef __KLEO_SIGNKEYJOB_H__
+#define __KLEO_SIGNKEYJOB_H__
+
+#include "job.h"
+
+#include <vector>
+
+namespace GpgME
+{
+class Error;
+class Key;
+}
+
+namespace QGpgME
+{
+
+/**
+ @short An abstract base class to sign keys asynchronously
+
+ To use a SignKeyJob, first obtain an instance from the
+ CryptoBackend implementation, connect the progress() and result()
+ signals to suitable slots and then start the job with a call
+ to start(). This call might fail, in which case the ChangeExpiryJob
+ instance will have scheduled it's own destruction with a call to
+ QObject::deleteLater().
+
+ After result() is emitted, the SignKeyJob will schedule it's own
+ destruction by calling QObject::deleteLater().
+*/
+class QGPGME_EXPORT SignKeyJob : public Job
+{
+ Q_OBJECT
+protected:
+ explicit SignKeyJob(QObject *parent);
+public:
+ ~SignKeyJob();
+
+ /**
+ Starts the key signing operation. \a key is the key to sign.
+ @param keyToSign the key to be signed
+ @param idsToSign the user IDs to sign
+ @param signingKey the secret key to use for signing
+ @param option the signing mode, either local or exportable
+ */
+ virtual GpgME::Error start(const GpgME::Key &keyToSign) = 0;
+
+ /**
+ * If explicitly specified, only the listed user IDs will be signed. Otherwise all user IDs
+ * are signed.
+ * @param list of user ID indexes (of the key to be signed).
+ */
+ virtual void setUserIDsToSign(const std::vector<unsigned int> &idsToSign) = 0;
+
+ /**
+ * sets the check level
+ * @param the check level, ranges from 0 (no claim) and 3 (extensively checked),
+ * default is 0
+ */
+ virtual void setCheckLevel(unsigned int checkLevel) = 0;
+
+ /**
+ * sets whether the signature should be exportable, or local only.
+ * default is local.
+ */
+ virtual void setExportable(bool exportable) = 0;
+
+ /**
+ * sets an alternate signing key
+ */
+ virtual void setSigningKey(const GpgME::Key &key) = 0;
+
+ /**
+ * if set, the created signature won't be revocable. By default signatures
+ * can be revoked.
+ */
+ virtual void setNonRevocable(bool nonRevocable) = 0;
+
+Q_SIGNALS:
+ void result(const GpgME::Error &result, const QString &auditLogAsHtml = QString(), const GpgME::Error &auditLogError = GpgME::Error());
+};
+
+}
+
+#endif // __KLEO_SIGNKEYJOB_H__
diff --git a/lang/qt/src/specialjob.h b/lang/qt/src/specialjob.h
new file mode 100644
index 0000000..2c80f20
--- /dev/null
+++ b/lang/qt/src/specialjob.h
@@ -0,0 +1,91 @@
+/*
+ specialjob.h
+
+ This file is part of qgpgme, the Qt API binding for gpgme
+ Copyright (c) 2004 Klarälvdalens Datakonsult AB
+ Copyright (c) 2016 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.
+*/
+
+#ifndef __KLEO_SPECIALJOB_H__
+#define __KLEO_SPECIALJOB_H__
+
+#include "job.h"
+#include "qgpgme_export.h"
+
+namespace GpgME
+{
+class Error;
+}
+
+namespace QGpgME
+{
+
+/**
+ @short An abstract base class for protocol-specific jobs
+
+ To use a SpecialJob, first obtain an instance from the
+ CryptoBackend implementation, connect progress() and result()
+ signals to suitable slots and then start the job with a call to
+ start(). This call might fail, in which case the SpecialJob
+ instance will have schedules its own destruction with a call to
+ QObject::deleteLater().
+
+ After result() is emitted, the SpecialJob will schedule its own
+ destruction by calling QObject::deleteLater().
+
+ Parameters are set using the Qt property system. More general, or
+ constructor parameters are given in the call to
+ QGpgME::Protocol::specialJob().
+
+ The result is made available through the result signal, and
+ through the read-only result property, the latter of which needs
+ to be defined in each SpecialJob subclass.
+*/
+class QGPGME_EXPORT SpecialJob : public Job
+{
+ Q_OBJECT
+protected:
+ explicit SpecialJob(QObject *parent);
+
+public:
+ ~SpecialJob();
+
+ /**
+ Starts the special operation.
+ */
+ virtual GpgME::Error start() = 0;
+
+ virtual GpgME::Error exec() = 0;
+
+Q_SIGNALS:
+ void result(const GpgME::Error &result, const QVariant &data);
+};
+
+}
+
+#endif // __KLEO_SPECIALJOB_H__
diff --git a/lang/qt/src/threadedjobmixin.cpp b/lang/qt/src/threadedjobmixin.cpp
new file mode 100644
index 0000000..cd6ab5f
--- /dev/null
+++ b/lang/qt/src/threadedjobmixin.cpp
@@ -0,0 +1,110 @@
+/*
+ threadedjobmixin.cpp
+
+ This file is part of qgpgme, the Qt API binding for gpgme
+ Copyright (c) 2008 Klarälvdalens Datakonsult AB
+ Copyright (c) 2016 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.
+*/
+
+#include "threadedjobmixin.h"
+
+#include "dataprovider.h"
+
+#include "data.h"
+
+#include <QString>
+#include <QStringList>
+#include <QByteArray>
+
+
+#include <algorithm>
+#include <iterator>
+
+using namespace QGpgME;
+using namespace GpgME;
+
+static const unsigned int GetAuditLogFlags = Context::AuditLogWithHelp | Context::HtmlAuditLog;
+
+QString _detail::audit_log_as_html(Context *ctx, GpgME::Error &err)
+{
+ assert(ctx);
+ QGpgME::QByteArrayDataProvider dp;
+ Data data(&dp);
+ assert(!data.isNull());
+ if ((err = ctx->lastError()) || (err = ctx->getAuditLog(data, GetAuditLogFlags))) {
+ return QString::fromLocal8Bit(err.asString());
+ }
+ const QByteArray ba = dp.data();
+ return QString::fromUtf8(ba.data(), ba.size());
+}
+
+static QList<QByteArray> from_sl(const QStringList &sl)
+{
+ QList<QByteArray> result;
+ Q_FOREACH (const QString &str, sl) {
+ result.append(str.toUtf8());
+ }
+
+#if 0
+ std::transform(sl.begin(), sl.end(), std::back_inserter(result),
+ mem_fn(static_cast<QByteArray()const>(&QString::toUtf8)));
+#endif
+ return result;
+}
+
+static QList<QByteArray> single(const QByteArray &ba)
+{
+ QList<QByteArray> result;
+ result.push_back(ba);
+ return result;
+}
+
+_detail::PatternConverter::PatternConverter(const QByteArray &ba)
+ : m_list(single(ba)), m_patterns(0) {}
+_detail::PatternConverter::PatternConverter(const QString &s)
+ : m_list(single(s.toUtf8())), m_patterns(0) {}
+_detail::PatternConverter::PatternConverter(const QList<QByteArray> &lba)
+ : m_list(lba), m_patterns(0) {}
+_detail::PatternConverter::PatternConverter(const QStringList &sl)
+ : m_list(from_sl(sl)), m_patterns(0) {}
+
+const char **_detail::PatternConverter::patterns() const
+{
+ if (!m_patterns) {
+ m_patterns = new const char *[ m_list.size() + 1 ];
+ const char **end = std::transform(m_list.begin(), m_list.end(), m_patterns,
+ std::mem_fn(&QByteArray::constData));
+ *end = 0;
+ }
+ return m_patterns;
+}
+
+_detail::PatternConverter::~PatternConverter()
+{
+ delete [] m_patterns;
+}
diff --git a/lang/qt/src/threadedjobmixin.h b/lang/qt/src/threadedjobmixin.h
new file mode 100644
index 0000000..62d7f1c
--- /dev/null
+++ b/lang/qt/src/threadedjobmixin.h
@@ -0,0 +1,272 @@
+/*
+ threadedjobmixin.h
+
+ This file is part of qgpgme, the Qt API binding for gpgme
+ Copyright (c) 2008 Klarälvdalens Datakonsult AB
+ Copyright (c) 2016 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.
+*/
+
+#ifndef __QGPGME_THREADEDJOBMIXING_H__
+#define __QGPGME_THREADEDJOBMIXING_H__
+
+#include <QMutex>
+#include <QMutexLocker>
+#include <QThread>
+#include <QString>
+#include <QIODevice>
+
+#ifdef BUILDING_QGPGME
+# include "context.h"
+# include "interfaces/progressprovider.h"
+#else
+# include <gpgme++/context.h>
+# include <gpgme++/interfaces/progressprovider.h>
+#endif
+
+
+#include <cassert>
+
+namespace QGpgME
+{
+namespace _detail
+{
+
+QString audit_log_as_html(GpgME::Context *ctx, GpgME::Error &err);
+
+class PatternConverter
+{
+ const QList<QByteArray> m_list;
+ mutable const char **m_patterns;
+public:
+ explicit PatternConverter(const QByteArray &ba);
+ explicit PatternConverter(const QString &s);
+ explicit PatternConverter(const QList<QByteArray> &lba);
+ explicit PatternConverter(const QStringList &sl);
+ ~PatternConverter();
+
+ const char **patterns() const;
+};
+
+class ToThreadMover
+{
+ QObject *const m_object;
+ QThread *const m_thread;
+public:
+ ToThreadMover(QObject *o, QThread *t) : m_object(o), m_thread(t) {}
+ ToThreadMover(QObject &o, QThread *t) : m_object(&o), m_thread(t) {}
+ ToThreadMover(const std::shared_ptr<QObject> &o, QThread *t) : m_object(o.get()), m_thread(t) {}
+ ~ToThreadMover()
+ {
+ if (m_object && m_thread) {
+ m_object->moveToThread(m_thread);
+ }
+ }
+};
+
+template <typename T_result>
+class Thread : public QThread
+{
+public:
+ explicit Thread(QObject *parent = Q_NULLPTR) : QThread(parent) {}
+
+ void setFunction(const std::function<T_result()> &function)
+ {
+ const QMutexLocker locker(&m_mutex);
+ m_function = function;
+ }
+
+ T_result result() const
+ {
+ const QMutexLocker locker(&m_mutex);
+ return m_result;
+ }
+
+private:
+ void run() Q_DECL_OVERRIDE {
+ const QMutexLocker locker(&m_mutex);
+ m_result = m_function();
+ }
+private:
+ mutable QMutex m_mutex;
+ std::function<T_result()> m_function;
+ T_result m_result;
+};
+
+template <typename T_base, typename T_result = std::tuple<GpgME::Error, QString, GpgME::Error> >
+class ThreadedJobMixin : public T_base, public GpgME::ProgressProvider
+{
+public:
+ typedef ThreadedJobMixin<T_base, T_result> mixin_type;
+ typedef T_result result_type;
+
+protected:
+ static_assert(std::tuple_size<T_result>::value > 2,
+ "Result tuple too small");
+ static_assert(std::is_same <
+ typename std::tuple_element <
+ std::tuple_size<T_result>::value - 2,
+ T_result
+ >::type,
+ QString
+ >::value,
+ "Second to last result type not a QString");
+ static_assert(std::is_same <
+ typename std::tuple_element <
+ std::tuple_size<T_result>::value - 1,
+ T_result
+ >::type,
+ GpgME::Error
+ >::value,
+ "Last result type not a GpgME::Error");
+
+ explicit ThreadedJobMixin(GpgME::Context *ctx)
+ : T_base(0), m_ctx(ctx), m_thread(), m_auditLog(), m_auditLogError()
+ {
+
+ }
+
+ void lateInitialization()
+ {
+ assert(m_ctx);
+ QObject::connect(&m_thread, SIGNAL(finished()), this, SLOT(slotFinished()));
+ m_ctx->setProgressProvider(this);
+ }
+
+ template <typename T_binder>
+ void run(const T_binder &func)
+ {
+ m_thread.setFunction(std::bind(func, this->context()));
+ m_thread.start();
+ }
+ template <typename T_binder>
+ void run(const T_binder &func, const std::shared_ptr<QIODevice> &io)
+ {
+ if (io) {
+ io->moveToThread(&m_thread);
+ }
+ // the arguments passed here to the functor are stored in a QThread, and are not
+ // necessarily destroyed (living outside the UI thread) at the time the result signal
+ // is emitted and the signal receiver wants to clean up IO devices.
+ // To avoid such races, we pass std::weak_ptr's to the functor.
+ m_thread.setFunction(std::bind(func, this->context(), this->thread(), std::weak_ptr<QIODevice>(io)));
+ m_thread.start();
+ }
+ template <typename T_binder>
+ void run(const T_binder &func, const std::shared_ptr<QIODevice> &io1, const std::shared_ptr<QIODevice> &io2)
+ {
+ if (io1) {
+ io1->moveToThread(&m_thread);
+ }
+ if (io2) {
+ io2->moveToThread(&m_thread);
+ }
+ // the arguments passed here to the functor are stored in a QThread, and are not
+ // necessarily destroyed (living outside the UI thread) at the time the result signal
+ // is emitted and the signal receiver wants to clean up IO devices.
+ // To avoid such races, we pass std::weak_ptr's to the functor.
+ m_thread.setFunction(std::bind(func, this->context(), this->thread(), std::weak_ptr<QIODevice>(io1), std::weak_ptr<QIODevice>(io2)));
+ m_thread.start();
+ }
+ GpgME::Context *context() const
+ {
+ return m_ctx.get();
+ }
+
+ virtual void resultHook(const result_type &) {}
+
+ void slotFinished()
+ {
+ const T_result r = m_thread.result();
+ m_auditLog = std::get < std::tuple_size<T_result>::value - 2 > (r);
+ m_auditLogError = std::get < std::tuple_size<T_result>::value - 1 > (r);
+ resultHook(r);
+ Q_EMIT this->done();
+ doEmitResult(r);
+ this->deleteLater();
+ }
+ void slotCancel() Q_DECL_OVERRIDE {
+ if (m_ctx)
+ {
+ m_ctx->cancelPendingOperation();
+ }
+ }
+ QString auditLogAsHtml() const Q_DECL_OVERRIDE
+ {
+ return m_auditLog;
+ }
+ GpgME::Error auditLogError() const Q_DECL_OVERRIDE
+ {
+ return m_auditLogError;
+ }
+ void showProgress(const char *what, int type, int current, int total) Q_DECL_OVERRIDE {
+ // will be called from the thread exec'ing the operation, so
+ // just bounce everything to the owning thread:
+ // ### hope this is thread-safe (meta obj is const, and
+ // ### portEvent is thread-safe, so should be ok)
+ QMetaObject::invokeMethod(this, "progress", Qt::QueuedConnection,
+ // TODO port
+ Q_ARG(QString, QString()),
+ Q_ARG(int, current),
+ Q_ARG(int, total));
+ }
+private:
+ template <typename T1, typename T2>
+ void doEmitResult(const std::tuple<T1, T2> &tuple)
+ {
+ Q_EMIT this->result(std::get<0>(tuple), std::get<1>(tuple));
+ }
+
+ template <typename T1, typename T2, typename T3>
+ void doEmitResult(const std::tuple<T1, T2, T3> &tuple)
+ {
+ Q_EMIT this->result(std::get<0>(tuple), std::get<1>(tuple), std::get<2>(tuple));
+ }
+
+ template <typename T1, typename T2, typename T3, typename T4>
+ void doEmitResult(const std::tuple<T1, T2, T3, T4> &tuple)
+ {
+ Q_EMIT this->result(std::get<0>(tuple), std::get<1>(tuple), std::get<2>(tuple), std::get<3>(tuple));
+ }
+
+ template <typename T1, typename T2, typename T3, typename T4, typename T5>
+ void doEmitResult(const std::tuple<T1, T2, T3, T4, T5> &tuple)
+ {
+ Q_EMIT this->result(std::get<0>(tuple), std::get<1>(tuple), std::get<2>(tuple), std::get<3>(tuple), std::get<4>(tuple));
+ }
+
+private:
+ std::shared_ptr<GpgME::Context> m_ctx;
+ Thread<T_result> m_thread;
+ QString m_auditLog;
+ GpgME::Error m_auditLogError;
+};
+
+}
+}
+
+#endif /* __QGPGME_THREADEDJOBMIXING_H__ */
diff --git a/lang/qt/src/tofupolicyjob.h b/lang/qt/src/tofupolicyjob.h
new file mode 100644
index 0000000..3079f91
--- /dev/null
+++ b/lang/qt/src/tofupolicyjob.h
@@ -0,0 +1,80 @@
+/* tofupolicyjob.h
+
+ Copyright (c) 2016 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.
+*/
+#ifndef QGPGME_TOFUPOLICYJOB_H
+#define QGPGME_TOFUPOLICYJOB_H
+
+#include "job.h"
+
+#include "qgpgme_export.h"
+
+#ifdef BUILDING_QGPGME
+# include "tofuinfo.h"
+#else
+# include <gpgme++/tofuinfo.h>
+#endif
+
+namespace GpgME
+{
+ class Key;
+} // namespace GpgME
+
+namespace QGpgME {
+
+/**
+ * Set the TOFU Policy for a key
+ */
+class QGPGME_EXPORT TofuPolicyJob: public Job
+{
+ Q_OBJECT
+protected:
+ explicit TofuPolicyJob(QObject *parent);
+public:
+ ~TofuPolicyJob();
+
+
+ /* Set the policy to \a policy see the gpgme manual for
+ * policy explanations. */
+ virtual void start(const GpgME::Key &key, GpgME::TofuInfo::Policy policy) = 0;
+
+ virtual GpgME::Error exec(const GpgME::Key &key, GpgME::TofuInfo::Policy policy) = 0;
+
+Q_SIGNALS:
+ /* Result of the operation
+ *
+ * As usual auditLogAsHtml and auditLogError can be ignored.
+ **/
+ void result(const GpgME::Error &error,
+ const QString &auditLogAsHtml = QString(),
+ const GpgME::Error &auditLogError = GpgME::Error());
+};
+
+}
+
+#endif
diff --git a/lang/qt/src/verifydetachedjob.h b/lang/qt/src/verifydetachedjob.h
new file mode 100644
index 0000000..b339a8c
--- /dev/null
+++ b/lang/qt/src/verifydetachedjob.h
@@ -0,0 +1,99 @@
+/*
+ verifydetachedjob.h
+
+ This file is part of qgpgme, the Qt API binding for gpgme
+ Copyright (c) 2004, 2007 Klarälvdalens Datakonsult AB
+ Copyright (c) 2016 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.
+*/
+
+#ifndef __KLEO_VERIFYDETACHEDJOB_H__
+#define __KLEO_VERIFYDETACHEDJOB_H__
+
+#include "job.h"
+#include "qgpgme_export.h"
+
+#include <memory>
+
+class QByteArray;
+class QIODevice;
+
+namespace GpgME
+{
+class Error;
+class VerificationResult;
+}
+
+namespace QGpgME
+{
+
+/**
+ @short An abstract base class for asynchronous verification of detached signatures
+
+ To use a VerifyDetachedJob, first obtain an instance from the
+ CryptoBackend implementation, connect the progress() and result()
+ signals to suitable slots and then start the verification with a
+ call to start(). This call might fail, in which case the
+ VerifyDetachedJob instance will have scheduled it's own
+ destruction with a call to QObject::deleteLater().
+
+ After result() is emitted, the VerifyDetachedJob will schedule
+ it's own destruction by calling QObject::deleteLater().
+*/
+class QGPGME_EXPORT VerifyDetachedJob : public Job
+{
+ Q_OBJECT
+protected:
+ explicit VerifyDetachedJob(QObject *parent);
+public:
+ ~VerifyDetachedJob();
+
+ /**
+ Starts the verification operation. \a signature contains the
+ signature data, while \a signedData contains the data over
+ which the signature was made.
+ */
+ virtual QGPGME_DEPRECATED_EXPORT GpgME::Error start(const QByteArray &signature,
+ const QByteArray &signedData) = 0;
+
+ /*!
+ \overload
+
+ \throws GpgME::Exception if starting fails.
+ */
+ virtual void start(const std::shared_ptr<QIODevice> &signature, const std::shared_ptr<QIODevice> &signedData) = 0;
+
+ virtual GpgME::VerificationResult exec(const QByteArray &signature,
+ const QByteArray &signedData) = 0;
+
+Q_SIGNALS:
+ void result(const GpgME::VerificationResult &result, const QString &auditLogAsHtml = QString(), const GpgME::Error &auditLogError = GpgME::Error());
+};
+
+}
+
+#endif // __KLEO_VERIFYDETACHEDJOB_H__
diff --git a/lang/qt/src/verifyopaquejob.h b/lang/qt/src/verifyopaquejob.h
new file mode 100644
index 0000000..f064049
--- /dev/null
+++ b/lang/qt/src/verifyopaquejob.h
@@ -0,0 +1,101 @@
+/*
+ verifyopaquejob.h
+
+ This file is part of qgpgme, the Qt API binding for gpgme
+ Copyright (c) 2004, 2007 Klarälvdalens Datakonsult AB
+ Copyright (c) 2016 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.
+*/
+
+#ifndef __KLEO_VERIFYOPAQUEJOB_H__
+#define __KLEO_VERIFYOPAQUEJOB_H__
+
+#include "job.h"
+
+#include <memory>
+
+class QByteArray;
+class QIODevice;
+
+namespace GpgME
+{
+class Error;
+class VerificationResult;
+}
+
+namespace QGpgME
+{
+
+/**
+ @short An abstract base class for asynchronous verification of opaque signatures
+
+ To use a VerifyOpaqueJob, first obtain an instance from the
+ CryptoBackend implementation, connect the progress() and result()
+ signals to suitable slots and then start the verification with a
+ call to start(). This call might fail, in which case the
+ VerifyOpaqueJob instance will have scheduled it's own
+ destruction with a call to QObject::deleteLater().
+
+ After result() is emitted, the VerifyOpaqueJob will schedule
+ it's own destruction by calling QObject::deleteLater().
+*/
+class QGPGME_EXPORT VerifyOpaqueJob : public Job
+{
+ Q_OBJECT
+protected:
+ explicit VerifyOpaqueJob(QObject *parent);
+public:
+ ~VerifyOpaqueJob();
+
+ /**
+ Starts the verification operation. \a signature contains the
+ signature data, while \a signedData contains the data over
+ which the signature was made.
+ */
+ virtual QGPGME_DEPRECATED_EXPORT GpgME::Error start(const QByteArray &signedData) = 0;
+
+ /*!
+ \overload
+
+ If \a plainText is non-null, the plaintext is written
+ there. Otherwise, it will be delivered in the second argument
+ of result().
+
+ \throws GpgME::Exception if starting fails
+ */
+ virtual void start(const std::shared_ptr<QIODevice> &signedData, const std::shared_ptr<QIODevice> &plainText = std::shared_ptr<QIODevice>()) = 0;
+
+ /** Synchronous version of @ref start */
+ virtual GpgME::VerificationResult exec(const QByteArray &signedData, QByteArray &plainText) = 0;
+
+Q_SIGNALS:
+ void result(const GpgME::VerificationResult &result, const QByteArray &plainText, const QString &auditLogAsHtml = QString(), const GpgME::Error &auditLogError = GpgME::Error());
+};
+
+}
+
+#endif // __KLEO_VERIFYOPAQUEJOB_H__
diff --git a/lang/qt/src/wkspublishjob.h b/lang/qt/src/wkspublishjob.h
new file mode 100644
index 0000000..782112f
--- /dev/null
+++ b/lang/qt/src/wkspublishjob.h
@@ -0,0 +1,101 @@
+/* wkspublishjob.h
+
+ Copyright (c) 2016 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.
+*/
+#ifndef QGPGME_WKSPUBLISHJOB_H
+#define QGPGME_WKSPUBLISHJOB_H
+
+#include "job.h"
+
+#include "qgpgme_export.h"
+
+namespace GpgME
+{
+ class Key;
+} // namespace GpgME
+
+namespace QGpgME {
+
+/**
+ * Handles Web Key Service Publishing. Needs WKS tools installed and
+ * server support.
+ *
+ * Remember that after a result is emited the job is auto deleted
+ * so you can only use it for a single action.
+ */
+class QGPGME_EXPORT WKSPublishJob: public Job
+{
+ Q_OBJECT
+protected:
+ explicit WKSPublishJob(QObject *parent);
+public:
+ ~WKSPublishJob();
+
+
+ /** Start a check if WKS Publishing is supported. As this involves
+ * an HTTP Query it might take a while. Returns GPG_ERR_NOT_SUPPORED
+ * result if GnuPG is too old or the required tools are not installed.
+ *
+ * The error GPG_ERR_NOT_ENABLED indicates that wks-tools failed to
+ * detect a working wks service for this.
+ *
+ * @param the mailbox to check for.
+ **/
+ virtual void startCheck(const QString &mailbox) = 0;
+
+ /** Create a publish request.
+ * The returned Data from the result will contain
+ * the full Mail as returned by gpg-wks-client --create
+ *
+ * @param fpr the fingerprint of the key to create the request for.
+ * @param mailbox A simple mail address without a Name.
+ */
+ virtual void startCreate(const char *fpr, const QString &mailbox) = 0;
+
+ /** Handle a submisson response. The returned Data will contain
+ * the full Mail as returned by gpg-wks-client --create
+ *
+ * @param response The response of the server.
+ **/
+ virtual void startRecieve(const QByteArray &response) = 0;
+
+Q_SIGNALS:
+ /* Result of the operation returned Data and returned Error are
+ * the results from gpg-wks-client's stdout or stderr respectively.
+ *
+ * As usual auditLogAsHtml and auditLogError can be ignored.
+ **/
+ void result(const GpgME::Error &error, const QByteArray &returnedData,
+ const QByteArray &returnedError,
+ const QString &auditLogAsHtml = QString(),
+ const GpgME::Error &auditLogError = GpgME::Error());
+};
+
+}
+
+#endif
diff --git a/lang/qt/tests/Makefile.am b/lang/qt/tests/Makefile.am
new file mode 100644
index 0000000..f243a55
--- /dev/null
+++ b/lang/qt/tests/Makefile.am
@@ -0,0 +1,95 @@
+# Makefile.am - Makefile for GPGME Qt tests.
+# Copyright (C) 2016 Intevation GmbH
+#
+# This file is part of GPGME.
+#
+# GPGME is free software; you can redistribute it and/or modify it
+# under the terms of the GNU Lesser General Public License as
+# published by the Free Software Foundation; either version 2.1 of the
+# License, or (at your option) any later version.
+#
+# GPGME is distributed in the hope that it will be useful, but WITHOUT
+# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
+# or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General
+# Public License for more details.
+#
+# You should have received a copy of the GNU Lesser General Public
+# License along with this program; if not, see <http://www.gnu.org/licenses/>.
+
+## Process this file with automake to produce Makefile.in
+
+GPG = gpg
+
+TESTS_ENVIRONMENT = GNUPGHOME=$(abs_builddir)
+
+EXTRA_DIST = initial.test
+
+TESTS = initial.test t-keylist t-keylocate t-ownertrust t-tofuinfo \
+ t-encrypt t-wkspublish
+
+moc_files = t-keylist.moc t-keylocate.moc t-ownertrust.moc t-tofuinfo.moc \
+ t-encrypt.moc t-support.hmoc t-wkspublish.moc
+
+AM_LDFLAGS = -no-install
+
+LDADD = ../../cpp/src/libgpgmepp.la ../src/libqgpgme.la \
+ ../../../src/libgpgme.la @GPGME_QT_LIBS@ @GPG_ERROR_LIBS@ \
+ @GPGME_QTTEST_LIBS@ -lstdc++
+
+AM_CPPFLAGS = -I$(top_srcdir)/lang/cpp/src -I$(top_builddir)/src \
+ @GPG_ERROR_CFLAGS@ @GPGME_QT_CFLAGS@ @GPG_ERROR_CFLAGS@ \
+ @LIBASSUAN_CFLAGS@ @GPGME_QTTEST_CFLAGS@ -DBUILDING_QGPGME \
+ -I$(top_srcdir)/lang/qt/src \
+ -DTOP_SRCDIR="$(top_srcdir)"
+
+check-local: ./pubring-stamp
+
+# To guarantee that check-local is run before any tests we
+# add this dependency:
+initial.test : check-local
+
+support_src = t-support.h t-support.cpp
+
+t_keylist_SOURCES = t-keylist.cpp $(support_src)
+t_keylocate_SOURCES = t-keylocate.cpp $(support_src)
+t_ownertrust_SOURCES = t-ownertrust.cpp $(support_src)
+t_tofuinfo_SOURCES = t-tofuinfo.cpp $(support_src)
+t_encrypt_SOURCES = t-encrypt.cpp $(support_src)
+t_wkspublish_SOURCES = t-wkspublish.cpp $(support_src)
+run_keyformailboxjob_SOURCES = run-keyformailboxjob.cpp
+
+nodist_t_keylist_SOURCES = $(moc_files)
+
+BUILT_SOURCES = $(moc_files)
+
+noinst_PROGRAMS = t-keylist t-keylocate t-ownertrust t-tofuinfo t-encrypt \
+ run-keyformailboxjob t-wkspublish
+
+CLEANFILES = secring.gpg pubring.gpg pubring.kbx trustdb.gpg dirmngr.conf \
+ gpg-agent.conf pubring.kbx~ S.gpg-agent gpg.conf pubring.gpg~ \
+ random_seed S.gpg-agent .gpg-v21-migrated pubring-stamp $(moc_files) \
+ gpg.conf
+
+clean-local:
+ -rm -fR private-keys-v1.d crls.d
+
+export GNUPGHOME := $(abs_builddir)
+
+./pubring-stamp: $(top_srcdir)/tests/gpg/pubdemo.asc \
+ $(top_srcdir)/tests/gpg/secdemo.asc
+ echo "ignore-invalid-option allow-loopback-pinentry" > $(abs_builddir)/gpg-agent.conf
+ echo "allow-loopback-pinentry" >> gpg-agent.conf
+ echo "ignore-invalid-option pinentry-mode" > gpg.conf
+ echo "pinentry-mode loopback" >> gpg.conf
+ $(GPG) --no-permission-warning \
+ --import $(top_srcdir)/tests/gpg/pubdemo.asc
+ $(GPG) --no-permission-warning \
+ --passphrase "abc" \
+ --import $(top_srcdir)/tests/gpg/secdemo.asc
+ touch ./pubring-stamp
+
+.cpp.moc:
+ $(MOC) `test -f '$<' || echo '$(srcdir)/'`$< -o $@
+
+.h.hmoc:
+ $(MOC) `test -f '$<' || echo '$(srcdir)/'`$< -o $@
diff --git a/lang/qt/tests/Makefile.in b/lang/qt/tests/Makefile.in
new file mode 100644
index 0000000..45d4c76
--- /dev/null
+++ b/lang/qt/tests/Makefile.in
@@ -0,0 +1,951 @@
+# Makefile.in generated by automake 1.14.1 from Makefile.am.
+# @configure_input@
+
+# Copyright (C) 1994-2013 Free Software Foundation, Inc.
+
+# This Makefile.in is free software; the Free Software Foundation
+# gives unlimited permission to copy and/or distribute it,
+# with or without modifications, as long as this notice is preserved.
+
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY, to the extent permitted by law; without
+# even the implied warranty of MERCHANTABILITY or FITNESS FOR A
+# PARTICULAR PURPOSE.
+
+@SET_MAKE@
+
+# Makefile.am - Makefile for GPGME Qt tests.
+# Copyright (C) 2016 Intevation GmbH
+#
+# This file is part of GPGME.
+#
+# GPGME is free software; you can redistribute it and/or modify it
+# under the terms of the GNU Lesser General Public License as
+# published by the Free Software Foundation; either version 2.1 of the
+# License, or (at your option) any later version.
+#
+# GPGME is distributed in the hope that it will be useful, but WITHOUT
+# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
+# or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General
+# Public License for more details.
+#
+# You should have received a copy of the GNU Lesser General Public
+# License along with this program; if not, see <http://www.gnu.org/licenses/>.
+
+VPATH = @srcdir@
+am__is_gnu_make = test -n '$(MAKEFILE_LIST)' && test -n '$(MAKELEVEL)'
+am__make_running_with_option = \
+ case $${target_option-} in \
+ ?) ;; \
+ *) echo "am__make_running_with_option: internal error: invalid" \
+ "target option '$${target_option-}' specified" >&2; \
+ exit 1;; \
+ esac; \
+ has_opt=no; \
+ sane_makeflags=$$MAKEFLAGS; \
+ if $(am__is_gnu_make); then \
+ sane_makeflags=$$MFLAGS; \
+ else \
+ case $$MAKEFLAGS in \
+ *\\[\ \ ]*) \
+ bs=\\; \
+ sane_makeflags=`printf '%s\n' "$$MAKEFLAGS" \
+ | sed "s/$$bs$$bs[$$bs $$bs ]*//g"`;; \
+ esac; \
+ fi; \
+ skip_next=no; \
+ strip_trailopt () \
+ { \
+ flg=`printf '%s\n' "$$flg" | sed "s/$$1.*$$//"`; \
+ }; \
+ for flg in $$sane_makeflags; do \
+ test $$skip_next = yes && { skip_next=no; continue; }; \
+ case $$flg in \
+ *=*|--*) continue;; \
+ -*I) strip_trailopt 'I'; skip_next=yes;; \
+ -*I?*) strip_trailopt 'I';; \
+ -*O) strip_trailopt 'O'; skip_next=yes;; \
+ -*O?*) strip_trailopt 'O';; \
+ -*l) strip_trailopt 'l'; skip_next=yes;; \
+ -*l?*) strip_trailopt 'l';; \
+ -[dEDm]) skip_next=yes;; \
+ -[JT]) skip_next=yes;; \
+ esac; \
+ case $$flg in \
+ *$$target_option*) has_opt=yes; break;; \
+ esac; \
+ done; \
+ test $$has_opt = yes
+am__make_dryrun = (target_option=n; $(am__make_running_with_option))
+am__make_keepgoing = (target_option=k; $(am__make_running_with_option))
+pkgdatadir = $(datadir)/@PACKAGE@
+pkgincludedir = $(includedir)/@PACKAGE@
+pkglibdir = $(libdir)/@PACKAGE@
+pkglibexecdir = $(libexecdir)/@PACKAGE@
+am__cd = CDPATH="$${ZSH_VERSION+.}$(PATH_SEPARATOR)" && cd
+install_sh_DATA = $(install_sh) -c -m 644
+install_sh_PROGRAM = $(install_sh) -c
+install_sh_SCRIPT = $(install_sh) -c
+INSTALL_HEADER = $(INSTALL_DATA)
+transform = $(program_transform_name)
+NORMAL_INSTALL = :
+PRE_INSTALL = :
+POST_INSTALL = :
+NORMAL_UNINSTALL = :
+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-wkspublish$(EXEEXT)
+noinst_PROGRAMS = t-keylist$(EXEEXT) t-keylocate$(EXEEXT) \
+ t-ownertrust$(EXEEXT) t-tofuinfo$(EXEEXT) t-encrypt$(EXEEXT) \
+ run-keyformailboxjob$(EXEEXT) t-wkspublish$(EXEEXT)
+subdir = lang/qt/tests
+DIST_COMMON = $(srcdir)/Makefile.in $(srcdir)/Makefile.am \
+ $(top_srcdir)/build-aux/mkinstalldirs \
+ $(top_srcdir)/build-aux/depcomp
+ACLOCAL_M4 = $(top_srcdir)/aclocal.m4
+am__aclocal_m4_deps = $(top_srcdir)/m4/ax_cxx_compile_stdcxx.m4 \
+ $(top_srcdir)/m4/ax_pkg_swig.m4 \
+ $(top_srcdir)/m4/ax_python_devel.m4 \
+ $(top_srcdir)/m4/glib-2.0.m4 $(top_srcdir)/m4/glibc21.m4 \
+ $(top_srcdir)/m4/gnupg-ttyname.m4 \
+ $(top_srcdir)/m4/gpg-error.m4 $(top_srcdir)/m4/libassuan.m4 \
+ $(top_srcdir)/m4/libtool.m4 $(top_srcdir)/m4/ltoptions.m4 \
+ $(top_srcdir)/m4/ltsugar.m4 $(top_srcdir)/m4/ltversion.m4 \
+ $(top_srcdir)/m4/lt~obsolete.m4 $(top_srcdir)/m4/pkg.m4 \
+ $(top_srcdir)/m4/qt.m4 $(top_srcdir)/acinclude.m4 \
+ $(top_srcdir)/configure.ac
+am__configure_deps = $(am__aclocal_m4_deps) $(CONFIGURE_DEPENDENCIES) \
+ $(ACLOCAL_M4)
+mkinstalldirs = $(SHELL) $(top_srcdir)/build-aux/mkinstalldirs
+CONFIG_HEADER = $(top_builddir)/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 \
+ ../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__objects_1 = t-support.$(OBJEXT)
+am_t_encrypt_OBJECTS = t-encrypt.$(OBJEXT) $(am__objects_1)
+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_keylist_OBJECTS = t-keylist.$(OBJEXT) $(am__objects_1)
+am__objects_2 =
+nodist_t_keylist_OBJECTS = $(am__objects_2)
+t_keylist_OBJECTS = $(am_t_keylist_OBJECTS) \
+ $(nodist_t_keylist_OBJECTS)
+t_keylist_LDADD = $(LDADD)
+t_keylist_DEPENDENCIES = ../../cpp/src/libgpgmepp.la \
+ ../src/libqgpgme.la ../../../src/libgpgme.la
+am_t_keylocate_OBJECTS = t-keylocate.$(OBJEXT) $(am__objects_1)
+t_keylocate_OBJECTS = $(am_t_keylocate_OBJECTS)
+t_keylocate_LDADD = $(LDADD)
+t_keylocate_DEPENDENCIES = ../../cpp/src/libgpgmepp.la \
+ ../src/libqgpgme.la ../../../src/libgpgme.la
+am_t_ownertrust_OBJECTS = t-ownertrust.$(OBJEXT) $(am__objects_1)
+t_ownertrust_OBJECTS = $(am_t_ownertrust_OBJECTS)
+t_ownertrust_LDADD = $(LDADD)
+t_ownertrust_DEPENDENCIES = ../../cpp/src/libgpgmepp.la \
+ ../src/libqgpgme.la ../../../src/libgpgme.la
+am_t_tofuinfo_OBJECTS = t-tofuinfo.$(OBJEXT) $(am__objects_1)
+t_tofuinfo_OBJECTS = $(am_t_tofuinfo_OBJECTS)
+t_tofuinfo_LDADD = $(LDADD)
+t_tofuinfo_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)
+t_wkspublish_DEPENDENCIES = ../../cpp/src/libgpgmepp.la \
+ ../src/libqgpgme.la ../../../src/libgpgme.la
+AM_V_P = $(am__v_P_@AM_V@)
+am__v_P_ = $(am__v_P_@AM_DEFAULT_V@)
+am__v_P_0 = false
+am__v_P_1 = :
+AM_V_GEN = $(am__v_GEN_@AM_V@)
+am__v_GEN_ = $(am__v_GEN_@AM_DEFAULT_V@)
+am__v_GEN_0 = @echo " GEN " $@;
+am__v_GEN_1 =
+AM_V_at = $(am__v_at_@AM_V@)
+am__v_at_ = $(am__v_at_@AM_DEFAULT_V@)
+am__v_at_0 = @
+am__v_at_1 =
+DEFAULT_INCLUDES = -I.@am__isrc@ -I$(top_builddir)
+depcomp = $(SHELL) $(top_srcdir)/build-aux/depcomp
+am__depfiles_maybe = depfiles
+am__mv = mv -f
+CXXCOMPILE = $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) \
+ $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS)
+LTCXXCOMPILE = $(LIBTOOL) $(AM_V_lt) --tag=CXX $(AM_LIBTOOLFLAGS) \
+ $(LIBTOOLFLAGS) --mode=compile $(CXX) $(DEFS) \
+ $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) \
+ $(AM_CXXFLAGS) $(CXXFLAGS)
+AM_V_CXX = $(am__v_CXX_@AM_V@)
+am__v_CXX_ = $(am__v_CXX_@AM_DEFAULT_V@)
+am__v_CXX_0 = @echo " CXX " $@;
+am__v_CXX_1 =
+CXXLD = $(CXX)
+CXXLINK = $(LIBTOOL) $(AM_V_lt) --tag=CXX $(AM_LIBTOOLFLAGS) \
+ $(LIBTOOLFLAGS) --mode=link $(CXXLD) $(AM_CXXFLAGS) \
+ $(CXXFLAGS) $(AM_LDFLAGS) $(LDFLAGS) -o $@
+AM_V_CXXLD = $(am__v_CXXLD_@AM_V@)
+am__v_CXXLD_ = $(am__v_CXXLD_@AM_DEFAULT_V@)
+am__v_CXXLD_0 = @echo " CXXLD " $@;
+am__v_CXXLD_1 =
+COMPILE = $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) \
+ $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS)
+LTCOMPILE = $(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) \
+ $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) \
+ $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) \
+ $(AM_CFLAGS) $(CFLAGS)
+AM_V_CC = $(am__v_CC_@AM_V@)
+am__v_CC_ = $(am__v_CC_@AM_DEFAULT_V@)
+am__v_CC_0 = @echo " CC " $@;
+am__v_CC_1 =
+CCLD = $(CC)
+LINK = $(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) \
+ $(LIBTOOLFLAGS) --mode=link $(CCLD) $(AM_CFLAGS) $(CFLAGS) \
+ $(AM_LDFLAGS) $(LDFLAGS) -o $@
+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_encrypt_SOURCES) \
+ $(t_keylist_SOURCES) $(nodist_t_keylist_SOURCES) \
+ $(t_keylocate_SOURCES) $(t_ownertrust_SOURCES) \
+ $(t_tofuinfo_SOURCES) $(t_wkspublish_SOURCES)
+DIST_SOURCES = $(run_keyformailboxjob_SOURCES) $(t_encrypt_SOURCES) \
+ $(t_keylist_SOURCES) $(t_keylocate_SOURCES) \
+ $(t_ownertrust_SOURCES) $(t_tofuinfo_SOURCES) \
+ $(t_wkspublish_SOURCES)
+am__can_run_installinfo = \
+ case $$AM_UPDATE_INFO_DIR in \
+ n|no|NO) false;; \
+ *) (install-info --version) >/dev/null 2>&1;; \
+ esac
+am__tagged_files = $(HEADERS) $(SOURCES) $(TAGS_FILES) $(LISP)
+# Read a list of newline-separated strings from the standard input,
+# and print each of them once, without duplicates. Input order is
+# *not* preserved.
+am__uniquify_input = $(AWK) '\
+ BEGIN { nonempty = 0; } \
+ { items[$$0] = 1; nonempty = 1; } \
+ END { if (nonempty) { for (i in items) print i; }; } \
+'
+# Make sure the list of sources is unique. This is necessary because,
+# e.g., the same source file might be shared among _SOURCES variables
+# for different programs/libraries.
+am__define_uniq_tagged_files = \
+ list='$(am__tagged_files)'; \
+ unique=`for i in $$list; do \
+ if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \
+ done | $(am__uniquify_input)`
+ETAGS = etags
+CTAGS = ctags
+am__tty_colors_dummy = \
+ mgn= red= grn= lgn= blu= brg= std=; \
+ am__color_tests=no
+am__tty_colors = { \
+ $(am__tty_colors_dummy); \
+ if test "X$(AM_COLOR_TESTS)" = Xno; then \
+ am__color_tests=no; \
+ elif test "X$(AM_COLOR_TESTS)" = Xalways; then \
+ am__color_tests=yes; \
+ elif test "X$$TERM" != Xdumb && { test -t 1; } 2>/dev/null; then \
+ am__color_tests=yes; \
+ fi; \
+ if test $$am__color_tests = yes; then \
+ red=''; \
+ grn=''; \
+ lgn=''; \
+ blu=''; \
+ mgn=''; \
+ brg=''; \
+ std=''; \
+ fi; \
+}
+DISTFILES = $(DIST_COMMON) $(DIST_SOURCES) $(TEXINFOS) $(EXTRA_DIST)
+ACLOCAL = @ACLOCAL@
+AMTAR = @AMTAR@
+AM_DEFAULT_VERBOSITY = @AM_DEFAULT_VERBOSITY@
+AR = @AR@
+AS = @AS@
+AUTOCONF = @AUTOCONF@
+AUTOHEADER = @AUTOHEADER@
+AUTOMAKE = @AUTOMAKE@
+AWK = @AWK@
+BUILD_FILEVERSION = @BUILD_FILEVERSION@
+BUILD_REVISION = @BUILD_REVISION@
+BUILD_TIMESTAMP = @BUILD_TIMESTAMP@
+CC = @CC@
+CCDEPMODE = @CCDEPMODE@
+CC_FOR_BUILD = @CC_FOR_BUILD@
+CFLAGS = @CFLAGS@
+CPP = @CPP@
+CPPFLAGS = @CPPFLAGS@
+CXX = @CXX@
+CXXCPP = @CXXCPP@
+CXXDEPMODE = @CXXDEPMODE@
+CXXFLAGS = @CXXFLAGS@
+CYGPATH_W = @CYGPATH_W@
+DEFS = @DEFS@
+DEPDIR = @DEPDIR@
+DLLTOOL = @DLLTOOL@
+DOXYGEN = @DOXYGEN@
+DSYMUTIL = @DSYMUTIL@
+DUMPBIN = @DUMPBIN@
+ECHO_C = @ECHO_C@
+ECHO_N = @ECHO_N@
+ECHO_T = @ECHO_T@
+EGREP = @EGREP@
+ENABLED_LANGUAGES = @ENABLED_LANGUAGES@
+EXEEXT = @EXEEXT@
+FGREP = @FGREP@
+GITLOG_TO_CHANGELOG = @GITLOG_TO_CHANGELOG@
+GLIBC21 = @GLIBC21@
+GLIB_CFLAGS = @GLIB_CFLAGS@
+GLIB_GENMARSHAL = @GLIB_GENMARSHAL@
+GLIB_LIBS = @GLIB_LIBS@
+GLIB_MKENUMS = @GLIB_MKENUMS@
+GOBJECT_QUERY = @GOBJECT_QUERY@
+GPGME_CONFIG_API_VERSION = @GPGME_CONFIG_API_VERSION@
+GPGME_CONFIG_AVAIL_LANG = @GPGME_CONFIG_AVAIL_LANG@
+GPGME_CONFIG_CFLAGS = @GPGME_CONFIG_CFLAGS@
+GPGME_CONFIG_HOST = @GPGME_CONFIG_HOST@
+GPGME_CONFIG_LIBS = @GPGME_CONFIG_LIBS@
+GPGME_QTTEST_CFLAGS = @GPGME_QTTEST_CFLAGS@
+GPGME_QTTEST_LIBS = @GPGME_QTTEST_LIBS@
+GPGME_QT_CFLAGS = @GPGME_QT_CFLAGS@
+GPGME_QT_LIBS = @GPGME_QT_LIBS@
+GPG_ERROR_CFLAGS = @GPG_ERROR_CFLAGS@
+GPG_ERROR_CONFIG = @GPG_ERROR_CONFIG@
+GPG_ERROR_LIBS = @GPG_ERROR_LIBS@
+GPG_ERROR_MT_CFLAGS = @GPG_ERROR_MT_CFLAGS@
+GPG_ERROR_MT_LIBS = @GPG_ERROR_MT_LIBS@
+GRAPHVIZ = @GRAPHVIZ@
+GREP = @GREP@
+HAVE_CXX11 = @HAVE_CXX11@
+HAVE_DOT = @HAVE_DOT@
+INSTALL = @INSTALL@
+INSTALL_DATA = @INSTALL_DATA@
+INSTALL_PROGRAM = @INSTALL_PROGRAM@
+INSTALL_SCRIPT = @INSTALL_SCRIPT@
+INSTALL_STRIP_PROGRAM = @INSTALL_STRIP_PROGRAM@
+LD = @LD@
+LDFLAGS = @LDFLAGS@
+LIBASSUAN_CFLAGS = @LIBASSUAN_CFLAGS@
+LIBASSUAN_CONFIG = @LIBASSUAN_CONFIG@
+LIBASSUAN_LIBS = @LIBASSUAN_LIBS@
+LIBGPGMEPP_LT_AGE = @LIBGPGMEPP_LT_AGE@
+LIBGPGMEPP_LT_CURRENT = @LIBGPGMEPP_LT_CURRENT@
+LIBGPGMEPP_LT_REVISION = @LIBGPGMEPP_LT_REVISION@
+LIBGPGME_LT_AGE = @LIBGPGME_LT_AGE@
+LIBGPGME_LT_CURRENT = @LIBGPGME_LT_CURRENT@
+LIBGPGME_LT_REVISION = @LIBGPGME_LT_REVISION@
+LIBOBJS = @LIBOBJS@
+LIBQGPGME_LT_AGE = @LIBQGPGME_LT_AGE@
+LIBQGPGME_LT_CURRENT = @LIBQGPGME_LT_CURRENT@
+LIBQGPGME_LT_REVISION = @LIBQGPGME_LT_REVISION@
+LIBS = @LIBS@
+LIBTOOL = @LIBTOOL@
+LIPO = @LIPO@
+LN_S = @LN_S@
+LTLIBOBJS = @LTLIBOBJS@
+MAINT = @MAINT@
+MAKEINFO = @MAKEINFO@
+MANIFEST_TOOL = @MANIFEST_TOOL@
+MKDIR_P = @MKDIR_P@
+MOC = @MOC@
+MOC2 = @MOC2@
+NEED__FILE_OFFSET_BITS = @NEED__FILE_OFFSET_BITS@
+NM = @NM@
+NMEDIT = @NMEDIT@
+OBJDUMP = @OBJDUMP@
+OBJEXT = @OBJEXT@
+OTOOL = @OTOOL@
+OTOOL64 = @OTOOL64@
+PACKAGE = @PACKAGE@
+PACKAGE_BUGREPORT = @PACKAGE_BUGREPORT@
+PACKAGE_NAME = @PACKAGE_NAME@
+PACKAGE_STRING = @PACKAGE_STRING@
+PACKAGE_TARNAME = @PACKAGE_TARNAME@
+PACKAGE_URL = @PACKAGE_URL@
+PACKAGE_VERSION = @PACKAGE_VERSION@
+PATH_SEPARATOR = @PATH_SEPARATOR@
+PKG_CONFIG = @PKG_CONFIG@
+PYTHON = @PYTHON@
+PYTHONS = @PYTHONS@
+PYTHON_CPPFLAGS = @PYTHON_CPPFLAGS@
+PYTHON_EXEC_PREFIX = @PYTHON_EXEC_PREFIX@
+PYTHON_EXTRA_LDFLAGS = @PYTHON_EXTRA_LDFLAGS@
+PYTHON_EXTRA_LIBS = @PYTHON_EXTRA_LIBS@
+PYTHON_LDFLAGS = @PYTHON_LDFLAGS@
+PYTHON_PLATFORM = @PYTHON_PLATFORM@
+PYTHON_PREFIX = @PYTHON_PREFIX@
+PYTHON_SITE_PKG = @PYTHON_SITE_PKG@
+PYTHON_VERSION = @PYTHON_VERSION@
+PYTHON_VERSIONS = @PYTHON_VERSIONS@
+QTCHOOSER = @QTCHOOSER@
+RANLIB = @RANLIB@
+RC = @RC@
+SED = @SED@
+SET_MAKE = @SET_MAKE@
+SHELL = @SHELL@
+STRIP = @STRIP@
+SWIG = @SWIG@
+SWIG_LIB = @SWIG_LIB@
+SYSROOT = @SYSROOT@
+VERSION = @VERSION@
+VERSION_NUMBER = @VERSION_NUMBER@
+abs_builddir = @abs_builddir@
+abs_srcdir = @abs_srcdir@
+abs_top_builddir = @abs_top_builddir@
+abs_top_srcdir = @abs_top_srcdir@
+ac_ct_AR = @ac_ct_AR@
+ac_ct_CC = @ac_ct_CC@
+ac_ct_CXX = @ac_ct_CXX@
+ac_ct_DUMPBIN = @ac_ct_DUMPBIN@
+am__include = @am__include@
+am__leading_dot = @am__leading_dot@
+am__quote = @am__quote@
+am__tar = @am__tar@
+am__untar = @am__untar@
+bindir = @bindir@
+build = @build@
+build_alias = @build_alias@
+build_cpu = @build_cpu@
+build_os = @build_os@
+build_vendor = @build_vendor@
+builddir = @builddir@
+datadir = @datadir@
+datarootdir = @datarootdir@
+docdir = @docdir@
+dvidir = @dvidir@
+emacs_local_vars_begin = @emacs_local_vars_begin@
+emacs_local_vars_end = @emacs_local_vars_end@
+emacs_local_vars_read_only = @emacs_local_vars_read_only@
+exec_prefix = @exec_prefix@
+host = @host@
+host_alias = @host_alias@
+host_cpu = @host_cpu@
+host_os = @host_os@
+host_vendor = @host_vendor@
+htmldir = @htmldir@
+includedir = @includedir@
+infodir = @infodir@
+install_sh = @install_sh@
+libdir = @libdir@
+libexecdir = @libexecdir@
+localedir = @localedir@
+localstatedir = @localstatedir@
+mandir = @mandir@
+mkdir_p = @mkdir_p@
+oldincludedir = @oldincludedir@
+pdfdir = @pdfdir@
+pkgpyexecdir = @pkgpyexecdir@
+pkgpythondir = @pkgpythondir@
+prefix = @prefix@
+program_transform_name = @program_transform_name@
+psdir = @psdir@
+pyexecdir = @pyexecdir@
+pythondir = @pythondir@
+sbindir = @sbindir@
+sharedstatedir = @sharedstatedir@
+srcdir = @srcdir@
+sysconfdir = @sysconfdir@
+target_alias = @target_alias@
+top_build_prefix = @top_build_prefix@
+top_builddir = @top_builddir@
+top_srcdir = @top_srcdir@
+GPG = gpg
+TESTS_ENVIRONMENT = GNUPGHOME=$(abs_builddir)
+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
+
+AM_LDFLAGS = -no-install
+LDADD = ../../cpp/src/libgpgmepp.la ../src/libqgpgme.la \
+ ../../../src/libgpgme.la @GPGME_QT_LIBS@ @GPG_ERROR_LIBS@ \
+ @GPGME_QTTEST_LIBS@ -lstdc++
+
+AM_CPPFLAGS = -I$(top_srcdir)/lang/cpp/src -I$(top_builddir)/src \
+ @GPG_ERROR_CFLAGS@ @GPGME_QT_CFLAGS@ @GPG_ERROR_CFLAGS@ \
+ @LIBASSUAN_CFLAGS@ @GPGME_QTTEST_CFLAGS@ -DBUILDING_QGPGME \
+ -I$(top_srcdir)/lang/qt/src \
+ -DTOP_SRCDIR="$(top_srcdir)"
+
+support_src = t-support.h t-support.cpp
+t_keylist_SOURCES = t-keylist.cpp $(support_src)
+t_keylocate_SOURCES = t-keylocate.cpp $(support_src)
+t_ownertrust_SOURCES = t-ownertrust.cpp $(support_src)
+t_tofuinfo_SOURCES = t-tofuinfo.cpp $(support_src)
+t_encrypt_SOURCES = t-encrypt.cpp $(support_src)
+t_wkspublish_SOURCES = t-wkspublish.cpp $(support_src)
+run_keyformailboxjob_SOURCES = run-keyformailboxjob.cpp
+nodist_t_keylist_SOURCES = $(moc_files)
+BUILT_SOURCES = $(moc_files)
+CLEANFILES = secring.gpg pubring.gpg pubring.kbx trustdb.gpg dirmngr.conf \
+ gpg-agent.conf pubring.kbx~ S.gpg-agent gpg.conf pubring.gpg~ \
+ random_seed S.gpg-agent .gpg-v21-migrated pubring-stamp $(moc_files) \
+ gpg.conf
+
+all: $(BUILT_SOURCES)
+ $(MAKE) $(AM_MAKEFLAGS) all-am
+
+.SUFFIXES:
+.SUFFIXES: .cpp .h .hmoc .lo .moc .o .obj
+$(srcdir)/Makefile.in: @MAINTAINER_MODE_TRUE@ $(srcdir)/Makefile.am $(am__configure_deps)
+ @for dep in $?; do \
+ case '$(am__configure_deps)' in \
+ *$$dep*) \
+ ( cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh ) \
+ && { if test -f $@; then exit 0; else break; fi; }; \
+ exit 1;; \
+ esac; \
+ done; \
+ echo ' cd $(top_srcdir) && $(AUTOMAKE) --gnu lang/qt/tests/Makefile'; \
+ $(am__cd) $(top_srcdir) && \
+ $(AUTOMAKE) --gnu lang/qt/tests/Makefile
+.PRECIOUS: Makefile
+Makefile: $(srcdir)/Makefile.in $(top_builddir)/config.status
+ @case '$?' in \
+ *config.status*) \
+ cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh;; \
+ *) \
+ echo ' cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__depfiles_maybe)'; \
+ cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__depfiles_maybe);; \
+ esac;
+
+$(top_builddir)/config.status: $(top_srcdir)/configure $(CONFIG_STATUS_DEPENDENCIES)
+ cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh
+
+$(top_srcdir)/configure: @MAINTAINER_MODE_TRUE@ $(am__configure_deps)
+ cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh
+$(ACLOCAL_M4): @MAINTAINER_MODE_TRUE@ $(am__aclocal_m4_deps)
+ cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh
+$(am__aclocal_m4_deps):
+
+clean-noinstPROGRAMS:
+ @list='$(noinst_PROGRAMS)'; test -n "$$list" || exit 0; \
+ echo " rm -f" $$list; \
+ rm -f $$list || exit $$?; \
+ test -n "$(EXEEXT)" || exit 0; \
+ list=`for p in $$list; do echo "$$p"; done | sed 's/$(EXEEXT)$$//'`; \
+ echo " rm -f" $$list; \
+ rm -f $$list
+
+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)
+
+t-encrypt$(EXEEXT): $(t_encrypt_OBJECTS) $(t_encrypt_DEPENDENCIES) $(EXTRA_t_encrypt_DEPENDENCIES)
+ @rm -f t-encrypt$(EXEEXT)
+ $(AM_V_CXXLD)$(CXXLINK) $(t_encrypt_OBJECTS) $(t_encrypt_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)
+
+t-keylocate$(EXEEXT): $(t_keylocate_OBJECTS) $(t_keylocate_DEPENDENCIES) $(EXTRA_t_keylocate_DEPENDENCIES)
+ @rm -f t-keylocate$(EXEEXT)
+ $(AM_V_CXXLD)$(CXXLINK) $(t_keylocate_OBJECTS) $(t_keylocate_LDADD) $(LIBS)
+
+t-ownertrust$(EXEEXT): $(t_ownertrust_OBJECTS) $(t_ownertrust_DEPENDENCIES) $(EXTRA_t_ownertrust_DEPENDENCIES)
+ @rm -f t-ownertrust$(EXEEXT)
+ $(AM_V_CXXLD)$(CXXLINK) $(t_ownertrust_OBJECTS) $(t_ownertrust_LDADD) $(LIBS)
+
+t-tofuinfo$(EXEEXT): $(t_tofuinfo_OBJECTS) $(t_tofuinfo_DEPENDENCIES) $(EXTRA_t_tofuinfo_DEPENDENCIES)
+ @rm -f t-tofuinfo$(EXEEXT)
+ $(AM_V_CXXLD)$(CXXLINK) $(t_tofuinfo_OBJECTS) $(t_tofuinfo_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)
+
+mostlyclean-compile:
+ -rm -f *.$(OBJEXT)
+
+distclean-compile:
+ -rm -f *.tab.c
+
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/run-keyformailboxjob.Po@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/t-encrypt.Po@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/t-keylist.Po@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/t-keylocate.Po@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/t-ownertrust.Po@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/t-support.Po@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/t-tofuinfo.Po@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/t-wkspublish.Po@am__quote@
+
+.cpp.o:
+@am__fastdepCXX_TRUE@ $(AM_V_CXX)$(CXXCOMPILE) -MT $@ -MD -MP -MF $(DEPDIR)/$*.Tpo -c -o $@ $<
+@am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/$*.Tpo $(DEPDIR)/$*.Po
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@ $(AM_V_CXX)source='$<' object='$@' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCXX_FALSE@ $(AM_V_CXX@am__nodep@)$(CXXCOMPILE) -c -o $@ $<
+
+.cpp.obj:
+@am__fastdepCXX_TRUE@ $(AM_V_CXX)$(CXXCOMPILE) -MT $@ -MD -MP -MF $(DEPDIR)/$*.Tpo -c -o $@ `$(CYGPATH_W) '$<'`
+@am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/$*.Tpo $(DEPDIR)/$*.Po
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@ $(AM_V_CXX)source='$<' object='$@' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCXX_FALSE@ $(AM_V_CXX@am__nodep@)$(CXXCOMPILE) -c -o $@ `$(CYGPATH_W) '$<'`
+
+.cpp.lo:
+@am__fastdepCXX_TRUE@ $(AM_V_CXX)$(LTCXXCOMPILE) -MT $@ -MD -MP -MF $(DEPDIR)/$*.Tpo -c -o $@ $<
+@am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/$*.Tpo $(DEPDIR)/$*.Plo
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@ $(AM_V_CXX)source='$<' object='$@' libtool=yes @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCXX_FALSE@ $(AM_V_CXX@am__nodep@)$(LTCXXCOMPILE) -c -o $@ $<
+
+mostlyclean-libtool:
+ -rm -f *.lo
+
+clean-libtool:
+ -rm -rf .libs _libs
+
+ID: $(am__tagged_files)
+ $(am__define_uniq_tagged_files); mkid -fID $$unique
+tags: tags-am
+TAGS: tags
+
+tags-am: $(TAGS_DEPENDENCIES) $(am__tagged_files)
+ set x; \
+ here=`pwd`; \
+ $(am__define_uniq_tagged_files); \
+ shift; \
+ if test -z "$(ETAGS_ARGS)$$*$$unique"; then :; else \
+ test -n "$$unique" || unique=$$empty_fix; \
+ if test $$# -gt 0; then \
+ $(ETAGS) $(ETAGSFLAGS) $(AM_ETAGSFLAGS) $(ETAGS_ARGS) \
+ "$$@" $$unique; \
+ else \
+ $(ETAGS) $(ETAGSFLAGS) $(AM_ETAGSFLAGS) $(ETAGS_ARGS) \
+ $$unique; \
+ fi; \
+ fi
+ctags: ctags-am
+
+CTAGS: ctags
+ctags-am: $(TAGS_DEPENDENCIES) $(am__tagged_files)
+ $(am__define_uniq_tagged_files); \
+ test -z "$(CTAGS_ARGS)$$unique" \
+ || $(CTAGS) $(CTAGSFLAGS) $(AM_CTAGSFLAGS) $(CTAGS_ARGS) \
+ $$unique
+
+GTAGS:
+ here=`$(am__cd) $(top_builddir) && pwd` \
+ && $(am__cd) $(top_srcdir) \
+ && gtags -i $(GTAGS_ARGS) "$$here"
+cscopelist: cscopelist-am
+
+cscopelist-am: $(am__tagged_files)
+ list='$(am__tagged_files)'; \
+ case "$(srcdir)" in \
+ [\\/]* | ?:[\\/]*) sdir="$(srcdir)" ;; \
+ *) sdir=$(subdir)/$(srcdir) ;; \
+ esac; \
+ for i in $$list; do \
+ if test -f "$$i"; then \
+ echo "$(subdir)/$$i"; \
+ else \
+ echo "$$sdir/$$i"; \
+ fi; \
+ done >> $(top_builddir)/cscope.files
+
+distclean-tags:
+ -rm -f TAGS ID GTAGS GRTAGS GSYMS GPATH tags
+
+check-TESTS: $(TESTS)
+ @failed=0; all=0; xfail=0; xpass=0; skip=0; \
+ srcdir=$(srcdir); export srcdir; \
+ list=' $(TESTS) '; \
+ $(am__tty_colors); \
+ if test -n "$$list"; then \
+ for tst in $$list; do \
+ if test -f ./$$tst; then dir=./; \
+ elif test -f $$tst; then dir=; \
+ else dir="$(srcdir)/"; fi; \
+ if $(TESTS_ENVIRONMENT) $${dir}$$tst $(AM_TESTS_FD_REDIRECT); then \
+ all=`expr $$all + 1`; \
+ case " $(XFAIL_TESTS) " in \
+ *[\ \ ]$$tst[\ \ ]*) \
+ xpass=`expr $$xpass + 1`; \
+ failed=`expr $$failed + 1`; \
+ col=$$red; res=XPASS; \
+ ;; \
+ *) \
+ col=$$grn; res=PASS; \
+ ;; \
+ esac; \
+ elif test $$? -ne 77; then \
+ all=`expr $$all + 1`; \
+ case " $(XFAIL_TESTS) " in \
+ *[\ \ ]$$tst[\ \ ]*) \
+ xfail=`expr $$xfail + 1`; \
+ col=$$lgn; res=XFAIL; \
+ ;; \
+ *) \
+ failed=`expr $$failed + 1`; \
+ col=$$red; res=FAIL; \
+ ;; \
+ esac; \
+ else \
+ skip=`expr $$skip + 1`; \
+ col=$$blu; res=SKIP; \
+ fi; \
+ echo "$${col}$$res$${std}: $$tst"; \
+ done; \
+ if test "$$all" -eq 1; then \
+ tests="test"; \
+ All=""; \
+ else \
+ tests="tests"; \
+ All="All "; \
+ fi; \
+ if test "$$failed" -eq 0; then \
+ if test "$$xfail" -eq 0; then \
+ banner="$$All$$all $$tests passed"; \
+ else \
+ if test "$$xfail" -eq 1; then failures=failure; else failures=failures; fi; \
+ banner="$$All$$all $$tests behaved as expected ($$xfail expected $$failures)"; \
+ fi; \
+ else \
+ if test "$$xpass" -eq 0; then \
+ banner="$$failed of $$all $$tests failed"; \
+ else \
+ if test "$$xpass" -eq 1; then passes=pass; else passes=passes; fi; \
+ banner="$$failed of $$all $$tests did not behave as expected ($$xpass unexpected $$passes)"; \
+ fi; \
+ fi; \
+ dashes="$$banner"; \
+ skipped=""; \
+ if test "$$skip" -ne 0; then \
+ if test "$$skip" -eq 1; then \
+ skipped="($$skip test was not run)"; \
+ else \
+ skipped="($$skip tests were not run)"; \
+ fi; \
+ test `echo "$$skipped" | wc -c` -le `echo "$$banner" | wc -c` || \
+ dashes="$$skipped"; \
+ fi; \
+ report=""; \
+ if test "$$failed" -ne 0 && test -n "$(PACKAGE_BUGREPORT)"; then \
+ report="Please report to $(PACKAGE_BUGREPORT)"; \
+ test `echo "$$report" | wc -c` -le `echo "$$banner" | wc -c` || \
+ dashes="$$report"; \
+ fi; \
+ dashes=`echo "$$dashes" | sed s/./=/g`; \
+ if test "$$failed" -eq 0; then \
+ col="$$grn"; \
+ else \
+ col="$$red"; \
+ fi; \
+ echo "$${col}$$dashes$${std}"; \
+ echo "$${col}$$banner$${std}"; \
+ test -z "$$skipped" || echo "$${col}$$skipped$${std}"; \
+ test -z "$$report" || echo "$${col}$$report$${std}"; \
+ echo "$${col}$$dashes$${std}"; \
+ test "$$failed" -eq 0; \
+ else :; fi
+
+distdir: $(DISTFILES)
+ @srcdirstrip=`echo "$(srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \
+ topsrcdirstrip=`echo "$(top_srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \
+ list='$(DISTFILES)'; \
+ dist_files=`for file in $$list; do echo $$file; done | \
+ sed -e "s|^$$srcdirstrip/||;t" \
+ -e "s|^$$topsrcdirstrip/|$(top_builddir)/|;t"`; \
+ case $$dist_files in \
+ */*) $(MKDIR_P) `echo "$$dist_files" | \
+ sed '/\//!d;s|^|$(distdir)/|;s,/[^/]*$$,,' | \
+ sort -u` ;; \
+ esac; \
+ for file in $$dist_files; do \
+ if test -f $$file || test -d $$file; then d=.; else d=$(srcdir); fi; \
+ if test -d $$d/$$file; then \
+ dir=`echo "/$$file" | sed -e 's,/[^/]*$$,,'`; \
+ if test -d "$(distdir)/$$file"; then \
+ find "$(distdir)/$$file" -type d ! -perm -700 -exec chmod u+rwx {} \;; \
+ fi; \
+ if test -d $(srcdir)/$$file && test $$d != $(srcdir); then \
+ cp -fpR $(srcdir)/$$file "$(distdir)$$dir" || exit 1; \
+ find "$(distdir)/$$file" -type d ! -perm -700 -exec chmod u+rwx {} \;; \
+ fi; \
+ cp -fpR $$d/$$file "$(distdir)$$dir" || exit 1; \
+ else \
+ test -f "$(distdir)/$$file" \
+ || cp -p $$d/$$file "$(distdir)/$$file" \
+ || exit 1; \
+ fi; \
+ done
+check-am: all-am
+ $(MAKE) $(AM_MAKEFLAGS) check-TESTS check-local
+check: $(BUILT_SOURCES)
+ $(MAKE) $(AM_MAKEFLAGS) check-am
+all-am: Makefile $(PROGRAMS)
+installdirs:
+install: $(BUILT_SOURCES)
+ $(MAKE) $(AM_MAKEFLAGS) install-am
+install-exec: install-exec-am
+install-data: install-data-am
+uninstall: uninstall-am
+
+install-am: all-am
+ @$(MAKE) $(AM_MAKEFLAGS) install-exec-am install-data-am
+
+installcheck: installcheck-am
+install-strip:
+ if test -z '$(STRIP)'; then \
+ $(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \
+ install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \
+ install; \
+ else \
+ $(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \
+ install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \
+ "INSTALL_PROGRAM_ENV=STRIPPROG='$(STRIP)'" install; \
+ fi
+mostlyclean-generic:
+
+clean-generic:
+ -test -z "$(CLEANFILES)" || rm -f $(CLEANFILES)
+
+distclean-generic:
+ -test -z "$(CONFIG_CLEAN_FILES)" || rm -f $(CONFIG_CLEAN_FILES)
+ -test . = "$(srcdir)" || test -z "$(CONFIG_CLEAN_VPATH_FILES)" || rm -f $(CONFIG_CLEAN_VPATH_FILES)
+
+maintainer-clean-generic:
+ @echo "This command is intended for maintainers to use"
+ @echo "it deletes files that may require special tools to rebuild."
+ -test -z "$(BUILT_SOURCES)" || rm -f $(BUILT_SOURCES)
+clean: clean-am
+
+clean-am: clean-generic clean-libtool clean-local clean-noinstPROGRAMS \
+ mostlyclean-am
+
+distclean: distclean-am
+ -rm -rf ./$(DEPDIR)
+ -rm -f Makefile
+distclean-am: clean-am distclean-compile distclean-generic \
+ distclean-tags
+
+dvi: dvi-am
+
+dvi-am:
+
+html: html-am
+
+html-am:
+
+info: info-am
+
+info-am:
+
+install-data-am:
+
+install-dvi: install-dvi-am
+
+install-dvi-am:
+
+install-exec-am:
+
+install-html: install-html-am
+
+install-html-am:
+
+install-info: install-info-am
+
+install-info-am:
+
+install-man:
+
+install-pdf: install-pdf-am
+
+install-pdf-am:
+
+install-ps: install-ps-am
+
+install-ps-am:
+
+installcheck-am:
+
+maintainer-clean: maintainer-clean-am
+ -rm -rf ./$(DEPDIR)
+ -rm -f Makefile
+maintainer-clean-am: distclean-am maintainer-clean-generic
+
+mostlyclean: mostlyclean-am
+
+mostlyclean-am: mostlyclean-compile mostlyclean-generic \
+ mostlyclean-libtool
+
+pdf: pdf-am
+
+pdf-am:
+
+ps: ps-am
+
+ps-am:
+
+uninstall-am:
+
+.MAKE: all check check-am install install-am install-strip
+
+.PHONY: CTAGS GTAGS TAGS all all-am check check-TESTS check-am \
+ check-local clean clean-generic clean-libtool clean-local \
+ clean-noinstPROGRAMS cscopelist-am ctags ctags-am distclean \
+ distclean-compile distclean-generic distclean-libtool \
+ distclean-tags distdir dvi dvi-am html html-am info info-am \
+ install install-am install-data install-data-am install-dvi \
+ install-dvi-am install-exec install-exec-am install-html \
+ install-html-am install-info install-info-am install-man \
+ install-pdf install-pdf-am install-ps install-ps-am \
+ install-strip installcheck installcheck-am installdirs \
+ maintainer-clean maintainer-clean-generic mostlyclean \
+ mostlyclean-compile mostlyclean-generic mostlyclean-libtool \
+ pdf pdf-am ps ps-am tags tags-am uninstall uninstall-am
+
+
+check-local: ./pubring-stamp
+
+# To guarantee that check-local is run before any tests we
+# add this dependency:
+initial.test : check-local
+
+clean-local:
+ -rm -fR private-keys-v1.d crls.d
+
+export GNUPGHOME := $(abs_builddir)
+
+./pubring-stamp: $(top_srcdir)/tests/gpg/pubdemo.asc \
+ $(top_srcdir)/tests/gpg/secdemo.asc
+ echo "ignore-invalid-option allow-loopback-pinentry" > $(abs_builddir)/gpg-agent.conf
+ echo "allow-loopback-pinentry" >> gpg-agent.conf
+ echo "ignore-invalid-option pinentry-mode" > gpg.conf
+ echo "pinentry-mode loopback" >> gpg.conf
+ $(GPG) --no-permission-warning \
+ --import $(top_srcdir)/tests/gpg/pubdemo.asc
+ $(GPG) --no-permission-warning \
+ --passphrase "abc" \
+ --import $(top_srcdir)/tests/gpg/secdemo.asc
+ touch ./pubring-stamp
+
+.cpp.moc:
+ $(MOC) `test -f '$<' || echo '$(srcdir)/'`$< -o $@
+
+.h.hmoc:
+ $(MOC) `test -f '$<' || echo '$(srcdir)/'`$< -o $@
+
+# Tell versions [3.59,3.63) of GNU make to not export all variables.
+# Otherwise a system limit (for SysV at least) may be exceeded.
+.NOEXPORT:
diff --git a/lang/qt/tests/initial.test b/lang/qt/tests/initial.test
new file mode 100755
index 0000000..039e4d0
--- /dev/null
+++ b/lang/qt/tests/initial.test
@@ -0,0 +1,2 @@
+#!/bin/sh
+exit 0
diff --git a/lang/qt/tests/run-keyformailboxjob.cpp b/lang/qt/tests/run-keyformailboxjob.cpp
new file mode 100644
index 0000000..9ac7668
--- /dev/null
+++ b/lang/qt/tests/run-keyformailboxjob.cpp
@@ -0,0 +1,56 @@
+/*
+ run-keyformailbox.cpp
+
+ This file is part of QGpgME's test suite.
+ Copyright (c) 2016 Intevation GmbH
+
+ 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.
+*/
+
+#include "keyformailboxjob.h"
+#include "keylistjob.h"
+#include "protocol.h"
+
+#include "key.h"
+#include "keylistresult.h"
+
+#include <QDebug>
+
+
+int main(int argc, char **argv)
+{
+ QString mailbox;
+ if (argc == 2) {
+ mailbox = QString::fromLocal8Bit(argv[1]);
+ }
+
+ auto job = QGpgME::openpgp()->keyForMailboxJob();
+ GpgME::Key k;
+ GpgME::UserID uid;
+ job->exec(mailbox, true, k, uid);
+ qDebug() << "UID Name: " << uid.name() << " Mail: " << uid.email() << " id: " << uid.id();
+ qDebug() << "Key fpr: " << k.primaryFingerprint();
+ return 0;
+}
diff --git a/lang/qt/tests/t-encrypt.cpp b/lang/qt/tests/t-encrypt.cpp
new file mode 100644
index 0000000..3d4cfa9
--- /dev/null
+++ b/lang/qt/tests/t-encrypt.cpp
@@ -0,0 +1,254 @@
+/* t-encrypt.cpp
+
+ This file is part of qgpgme, the Qt API binding for gpgme
+ Copyright (c) 2016 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.
+*/
+#include <QDebug>
+#include <QTest>
+#include <QTemporaryDir>
+#include <QSignalSpy>
+#include <QBuffer>
+#include "keylistjob.h"
+#include "encryptjob.h"
+#include "qgpgmeencryptjob.h"
+#include "encryptionresult.h"
+#include "decryptionresult.h"
+#include "qgpgmedecryptjob.h"
+#include "qgpgmebackend.h"
+#include "keylistresult.h"
+#include "engineinfo.h"
+#include "t-support.h"
+
+#define PROGRESS_TEST_SIZE 1 * 1024 * 1024
+
+using namespace QGpgME;
+using namespace GpgME;
+
+class EncryptionTest : public QGpgMETest
+{
+ Q_OBJECT
+
+Q_SIGNALS:
+ void asyncDone();
+
+private Q_SLOTS:
+
+ void testSimpleEncryptDecrypt()
+ {
+ auto listjob = openpgp()->keyListJob(false, false, false);
+ std::vector<Key> keys;
+ auto keylistresult = listjob->exec(QStringList() << QStringLiteral("alfa@example.net"),
+ false, keys);
+ Q_ASSERT(!keylistresult.error());
+ Q_ASSERT(keys.size() == 1);
+ delete listjob;
+
+ auto job = openpgp()->encryptJob(/*ASCII Armor */true, /* Textmode */ true);
+ Q_ASSERT(job);
+ QByteArray cipherText;
+ auto result = job->exec(keys, QStringLiteral("Hello World").toUtf8(), Context::AlwaysTrust, cipherText);
+ delete job;
+ Q_ASSERT(!result.error());
+ const auto cipherString = QString::fromUtf8(cipherText);
+ Q_ASSERT(cipherString.startsWith("-----BEGIN PGP MESSAGE-----"));
+
+ /* Now decrypt */
+ auto ctx = Context::createForProtocol(OpenPGP);
+ TestPassphraseProvider provider;
+ ctx->setPassphraseProvider(&provider);
+ ctx->setPinentryMode(Context::PinentryLoopback);
+ auto decJob = new QGpgMEDecryptJob(ctx);
+ QByteArray plainText;
+ auto decResult = decJob->exec(cipherText, plainText);
+ Q_ASSERT(!result.error());
+ Q_ASSERT(QString::fromUtf8(plainText) == QStringLiteral("Hello World"));
+ delete decJob;
+ }
+
+ void testProgress()
+ {
+ if (GpgME::engineInfo(GpgME::GpgEngine).engineVersion() < "2.1.15") {
+ // We can only test the progress with 2.1.15 as this started to
+ // have total progress for memory callbacks
+ return;
+ }
+ auto listjob = openpgp()->keyListJob(false, false, false);
+ std::vector<Key> keys;
+ auto keylistresult = listjob->exec(QStringList() << QStringLiteral("alfa@example.net"),
+ false, keys);
+ Q_ASSERT(!keylistresult.error());
+ Q_ASSERT(keys.size() == 1);
+ delete listjob;
+
+ auto job = openpgp()->encryptJob(/*ASCII Armor */false, /* Textmode */ false);
+ Q_ASSERT(job);
+ QByteArray plainBa;
+ plainBa.fill('X', PROGRESS_TEST_SIZE);
+ QByteArray cipherText;
+
+ bool initSeen = false;
+ bool finishSeen = false;
+ connect(job, &Job::progress, this, [this, &initSeen, &finishSeen] (const QString& what, int current, int total) {
+ // We only check for progress 0 and max progress as the other progress
+ // lines depend on the system speed and are as such unreliable to test.
+ Q_ASSERT(total == PROGRESS_TEST_SIZE);
+ if (current == 0) {
+ initSeen = true;
+ }
+ if (current == total) {
+ finishSeen = true;
+ }
+ Q_ASSERT(current >= 0 && current <= total);
+ });
+ connect(job, &EncryptJob::result, this, [this, &initSeen, &finishSeen] (const GpgME::EncryptionResult &result,
+ const QByteArray &cipherText,
+ const QString,
+ const GpgME::Error) {
+ Q_ASSERT(initSeen);
+ Q_ASSERT(finishSeen);
+ Q_EMIT asyncDone();
+ });
+
+ auto inptr = std::shared_ptr<QIODevice>(new QBuffer(&plainBa));
+ inptr->open(QIODevice::ReadOnly);
+ auto outptr = std::shared_ptr<QIODevice>(new QBuffer(&cipherText));
+ outptr->open(QIODevice::WriteOnly);
+
+ job->start(keys, inptr, outptr, Context::AlwaysTrust);
+ QSignalSpy spy (this, SIGNAL(asyncDone()));
+ Q_ASSERT(spy.wait());
+ }
+
+ void testSymmetricEncryptDecrypt()
+ {
+ auto ctx = Context::createForProtocol(OpenPGP);
+ TestPassphraseProvider provider;
+ ctx->setPassphraseProvider(&provider);
+ ctx->setPinentryMode(Context::PinentryLoopback);
+ ctx->setArmor(true);
+ ctx->setTextMode(true);
+ auto job = new QGpgMEEncryptJob(ctx);
+ QByteArray cipherText;
+ auto result = job->exec(std::vector<Key>(), QStringLiteral("Hello symmetric World").toUtf8(), Context::AlwaysTrust, cipherText);
+ delete job;
+ Q_ASSERT(!result.error());
+ const auto cipherString = QString::fromUtf8(cipherText);
+ Q_ASSERT(cipherString.startsWith("-----BEGIN PGP MESSAGE-----"));
+
+ killAgent(mDir.path());
+
+ auto ctx2 = Context::createForProtocol(OpenPGP);
+ ctx2->setPassphraseProvider(&provider);
+ ctx2->setPinentryMode(Context::PinentryLoopback);
+ auto decJob = new QGpgMEDecryptJob(ctx2);
+ QByteArray plainText;
+ auto decResult = decJob->exec(cipherText, plainText);
+ Q_ASSERT(!result.error());
+ Q_ASSERT(QString::fromUtf8(plainText) == QStringLiteral("Hello symmetric World"));
+ delete decJob;
+ }
+
+private:
+ /* Loopback and passphrase provider don't work for mixed encryption.
+ * So this test is disabled until gnupg(?) is fixed for this. */
+ void testMixedEncryptDecrypt()
+ {
+ auto listjob = openpgp()->keyListJob(false, false, false);
+ std::vector<Key> keys;
+ auto keylistresult = listjob->exec(QStringList() << QStringLiteral("alfa@example.net"),
+ false, keys);
+ Q_ASSERT(!keylistresult.error());
+ Q_ASSERT(keys.size() == 1);
+ delete listjob;
+
+ auto ctx = Context::createForProtocol(OpenPGP);
+ ctx->setPassphraseProvider(new TestPassphraseProvider);
+ ctx->setPinentryMode(Context::PinentryLoopback);
+ ctx->setArmor(true);
+ ctx->setTextMode(true);
+ auto job = new QGpgMEEncryptJob(ctx);
+ QByteArray cipherText;
+ printf("Before exec, flags: %x\n", Context::Symmetric | Context::AlwaysTrust);
+ auto result = job->exec(keys, QStringLiteral("Hello symmetric World").toUtf8(),
+ static_cast<Context::EncryptionFlags>(Context::Symmetric | Context::AlwaysTrust),
+ cipherText);
+ printf("After exec\n");
+ delete job;
+ Q_ASSERT(!result.error());
+ printf("Cipher:\n%s\n", cipherText.constData());
+ const auto cipherString = QString::fromUtf8(cipherText);
+ Q_ASSERT(cipherString.startsWith("-----BEGIN PGP MESSAGE-----"));
+
+ killAgent(mDir.path());
+
+ /* Now create a new homedir which with we test symetric decrypt. */
+ QTemporaryDir tmp;
+ qputenv("GNUPGHOME", tmp.path().toUtf8());
+ QFile agentConf(tmp.path() + QStringLiteral("/gpg-agent.conf"));
+ Q_ASSERT(agentConf.open(QIODevice::WriteOnly));
+ agentConf.write("allow-loopback-pinentry");
+ agentConf.close();
+
+ auto ctx2 = Context::createForProtocol(OpenPGP);
+ ctx2->setPassphraseProvider(new TestPassphraseProvider);
+ ctx2->setPinentryMode(Context::PinentryLoopback);
+ ctx2->setTextMode(true);
+ auto decJob = new QGpgMEDecryptJob(ctx2);
+ QByteArray plainText;
+ auto decResult = decJob->exec(cipherText, plainText);
+ Q_ASSERT(!decResult.error());
+ qDebug() << "Plain: " << plainText;
+ Q_ASSERT(QString::fromUtf8(plainText) == QStringLiteral("Hello symmetric World"));
+ delete decJob;
+
+ killAgent(tmp.path());
+ qputenv("GNUPGHOME", mDir.path().toUtf8());
+ }
+
+public Q_SLOT:
+
+ void initTestCase()
+ {
+ QGpgMETest::initTestCase();
+ const QString gpgHome = qgetenv("GNUPGHOME");
+ qputenv("GNUPGHOME", mDir.path().toUtf8());
+ Q_ASSERT(mDir.isValid());
+ QFile agentConf(mDir.path() + QStringLiteral("/gpg-agent.conf"));
+ Q_ASSERT(agentConf.open(QIODevice::WriteOnly));
+ agentConf.write("allow-loopback-pinentry");
+ agentConf.close();
+ Q_ASSERT(copyKeyrings(gpgHome, mDir.path()));
+ }
+
+private:
+ QTemporaryDir mDir;
+};
+
+QTEST_MAIN(EncryptionTest)
+
+#include "t-encrypt.moc"
diff --git a/lang/qt/tests/t-keylist.cpp b/lang/qt/tests/t-keylist.cpp
new file mode 100644
index 0000000..767c96b
--- /dev/null
+++ b/lang/qt/tests/t-keylist.cpp
@@ -0,0 +1,107 @@
+/* t-keylist.cpp
+
+ This file is part of qgpgme, the Qt API binding for gpgme
+ Copyright (c) 2016 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.
+*/
+
+#include <QDebug>
+#include <QTest>
+#include <QSignalSpy>
+#include <QMap>
+#include "keylistjob.h"
+#include "qgpgmebackend.h"
+#include "keylistresult.h"
+
+#include "t-support.h"
+
+using namespace QGpgME;
+using namespace GpgME;
+
+class KeyListTest : public QGpgMETest
+{
+ Q_OBJECT
+
+Q_SIGNALS:
+ void asyncDone();
+
+private Q_SLOTS:
+ void testSingleKeyListSync()
+ {
+ KeyListJob *job = openpgp()->keyListJob(false, false, false);
+ std::vector<GpgME::Key> keys;
+ GpgME::KeyListResult result = job->exec(QStringList() << QStringLiteral("alfa@example.net"),
+ false, keys);
+ delete job;
+ Q_ASSERT (!result.error());
+ Q_ASSERT (keys.size() == 1);
+ const QString kId = QLatin1String(keys.front().keyID());
+ Q_ASSERT (kId == QStringLiteral("2D727CC768697734"));
+
+ Q_ASSERT (keys[0].subkeys().size() == 2);
+ Q_ASSERT (keys[0].subkeys()[0].publicKeyAlgorithm() == Subkey::AlgoDSA);
+ Q_ASSERT (keys[0].subkeys()[1].publicKeyAlgorithm() == Subkey::AlgoELG_E);
+ }
+
+ void testPubkeyAlgoAsString()
+ {
+ static const QMap<Subkey::PubkeyAlgo, QString> expected {
+ { Subkey::AlgoRSA, QStringLiteral("RSA") },
+ { Subkey::AlgoRSA_E, QStringLiteral("RSA-E") },
+ { Subkey::AlgoRSA_S, QStringLiteral("RSA-S") },
+ { Subkey::AlgoELG_E, QStringLiteral("ELG-E") },
+ { Subkey::AlgoDSA, QStringLiteral("DSA") },
+ { Subkey::AlgoECC, QStringLiteral("ECC") },
+ { Subkey::AlgoELG, QStringLiteral("ELG") },
+ { Subkey::AlgoECDSA, QStringLiteral("ECDSA") },
+ { Subkey::AlgoECDH, QStringLiteral("ECDH") },
+ { Subkey::AlgoEDDSA, QStringLiteral("EdDSA") },
+ { Subkey::AlgoUnknown, QString() }
+ };
+ Q_FOREACH (Subkey::PubkeyAlgo algo, expected.keys()) {
+ Q_ASSERT(QString::fromUtf8(Subkey::publicKeyAlgorithmAsString(algo)) ==
+ expected.value(algo));
+ }
+ }
+
+ void testKeyListAsync()
+ {
+ KeyListJob *job = openpgp()->keyListJob();
+ connect(job, &KeyListJob::result, job, [this, job](KeyListResult, std::vector<Key> keys, QString, Error)
+ {
+ Q_ASSERT(keys.size() == 1);
+ Q_EMIT asyncDone();
+ });
+ job->start(QStringList() << "alfa@example.net");
+ QSignalSpy spy (this, SIGNAL(asyncDone()));
+ Q_ASSERT(spy.wait());
+ }
+};
+
+QTEST_MAIN(KeyListTest)
+
+#include "t-keylist.moc"
diff --git a/lang/qt/tests/t-keylocate.cpp b/lang/qt/tests/t-keylocate.cpp
new file mode 100644
index 0000000..e75f24d
--- /dev/null
+++ b/lang/qt/tests/t-keylocate.cpp
@@ -0,0 +1,130 @@
+/* t-keylocate.cpp
+
+ This file is part of qgpgme, the Qt API binding for gpgme
+ Copyright (c) 2016 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.
+*/
+#include <QDebug>
+#include <QTest>
+#include <QSignalSpy>
+#include <QTemporaryDir>
+#include "keylistjob.h"
+#include "protocol.h"
+#include "keylistresult.h"
+#include "engineinfo.h"
+
+#include "t-support.h"
+
+using namespace QGpgME;
+using namespace GpgME;
+
+class KeyLocateTest : public QGpgMETest
+{
+ Q_OBJECT
+
+Q_SIGNALS:
+ void asyncDone();
+
+private Q_SLOTS:
+
+#ifdef DO_ONLINE_TESTS
+ void testDaneKeyLocate()
+ {
+ QTemporaryDir dir;
+ const QString oldHome = qgetenv("GNUPGHOME");
+ qputenv("GNUPGHOME", dir.path().toUtf8());
+ /* Could do this with gpgconf but this is not a gpgconf test ;-) */
+ QFile conf(dir.path() + QStringLiteral("/gpg.conf"));
+ Q_ASSERT(conf.open(QIODevice::WriteOnly));
+ conf.write("auto-key-locate dane");
+ conf.close();
+
+ auto *job = openpgp()->locateKeysJob();
+ mTestpattern = QStringLiteral("wk@gnupg.org");
+ connect(job, &KeyListJob::result, job, [this, job](KeyListResult result, std::vector<Key> keys, QString, Error)
+ {
+ Q_ASSERT(!result.error());
+ Q_ASSERT(keys.size() == 1);
+
+ Key k = keys.front();
+ Q_ASSERT(k.numUserIDs());
+ bool found = false;
+ Q_FOREACH (const UserID uid, k.userIDs()) {
+ const QString mailBox = QString::fromUtf8(uid.email());
+ if (mTestpattern.toLower() == mailBox.toLower()) {
+ found = true;
+ }
+ }
+ Q_ASSERT(found);
+ Q_EMIT asyncDone();
+ });
+ job->start(QStringList() << mTestpattern);
+ QSignalSpy spy (this, SIGNAL(asyncDone()));
+ Q_ASSERT(spy.wait());
+ qputenv("GNUPGHOME", oldHome.toUtf8());
+ }
+#endif
+
+ void testKeyLocateSingle()
+ {
+ if (GpgME::engineInfo(GpgME::GpgEngine).engineVersion() < "2.0.10") {
+ return;
+ }
+ auto *job = openpgp()->locateKeysJob();
+ mTestpattern = QStringLiteral("alfa@example.net");
+
+ connect(job, &KeyListJob::result, job, [this, job](KeyListResult result, std::vector<Key> keys, QString, Error)
+ {
+ Q_ASSERT(!result.isNull());
+ Q_ASSERT(!result.isTruncated());
+ Q_ASSERT(!result.error());
+ Q_ASSERT(keys.size() == 1);
+
+ Key k = keys.front();
+ Q_ASSERT(k.numUserIDs());
+ bool found = false;
+ Q_FOREACH (const UserID uid, k.userIDs()) {
+ const QString mailBox = QString::fromUtf8(uid.email());
+ if (mTestpattern.toLower() == mailBox.toLower()) {
+ found = true;
+ }
+ }
+ Q_ASSERT(found);
+ Q_EMIT asyncDone();
+ });
+ job->start(QStringList() << mTestpattern);
+ QSignalSpy spy (this, SIGNAL(asyncDone()));
+ Q_ASSERT(spy.wait());
+ }
+
+private:
+ QString mTestpattern;
+};
+
+QTEST_MAIN(KeyLocateTest)
+
+#include "t-keylocate.moc"
diff --git a/lang/qt/tests/t-ownertrust.cpp b/lang/qt/tests/t-ownertrust.cpp
new file mode 100644
index 0000000..b9efffd
--- /dev/null
+++ b/lang/qt/tests/t-ownertrust.cpp
@@ -0,0 +1,107 @@
+/* t-ownertrust.cpp
+
+ This file is part of qgpgme, the Qt API binding for gpgme
+ Copyright (c) 2016 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.
+*/
+
+#include <QDebug>
+#include <QTest>
+#include <QSignalSpy>
+#include "keylistjob.h"
+#include "protocol.h"
+#include "keylistresult.h"
+#include "changeownertrustjob.h"
+
+#include "t-support.h"
+
+using namespace QGpgME;
+using namespace GpgME;
+
+class ChangeOwnerTrustTest: public QGpgMETest
+{
+ Q_OBJECT
+
+Q_SIGNALS:
+ void asyncDone();
+
+private Q_SLOTS:
+
+ void testChangeOwnerTrust()
+ {
+ KeyListJob *job = openpgp()->keyListJob(false, true, true);
+ std::vector<GpgME::Key> keys;
+ GpgME::KeyListResult result = job->exec(QStringList() << QStringLiteral("alfa@example.net"),
+ false, keys);
+ delete job;
+ Q_ASSERT (!result.error());
+ Q_ASSERT (keys.size() == 1);
+ Key key = keys.front();
+ Q_ASSERT (key.ownerTrust() == Key::Unknown);
+
+ ChangeOwnerTrustJob *job2 = openpgp()->changeOwnerTrustJob();
+ connect(job2, &ChangeOwnerTrustJob::result, this, [this](Error e)
+ {
+ if (e) {
+ qDebug() << "Error in result: " << e.asString();
+ }
+ Q_ASSERT(!e);
+ Q_EMIT asyncDone();
+ });
+ job2->start(key, Key::Ultimate);
+ QSignalSpy spy (this, SIGNAL(asyncDone()));
+ Q_ASSERT(spy.wait());
+
+ job = openpgp()->keyListJob(false, true, true);
+ result = job->exec(QStringList() << QStringLiteral("alfa@example.net"),
+ false, keys);
+ delete job;
+ key = keys.front();
+ Q_ASSERT (key.ownerTrust() == Key::Ultimate);
+
+ ChangeOwnerTrustJob *job3 = openpgp()->changeOwnerTrustJob();
+ connect(job3, &ChangeOwnerTrustJob::result, this, [this](Error e)
+ {
+ Q_ASSERT(!e);
+ Q_EMIT asyncDone();
+ });
+ job3->start(key, Key::Unknown);
+ Q_ASSERT(spy.wait());
+
+ job = openpgp()->keyListJob(false, true, true);
+ result = job->exec(QStringList() << QStringLiteral("alfa@example.net"),
+ false, keys);
+ delete job;
+
+ key = keys.front();
+ Q_ASSERT (key.ownerTrust() == Key::Unknown);
+ }
+};
+
+QTEST_MAIN(ChangeOwnerTrustTest)
+
+#include "t-ownertrust.moc"
diff --git a/lang/qt/tests/t-support.cpp b/lang/qt/tests/t-support.cpp
new file mode 100644
index 0000000..86372f7
--- /dev/null
+++ b/lang/qt/tests/t-support.cpp
@@ -0,0 +1,95 @@
+/* t-support.cpp
+
+ This file is part of qgpgme, the Qt API binding for gpgme
+ Copyright (c) 2016 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.
+*/
+
+#include "t-support.h"
+
+#include <QTest>
+
+#include <QProcess>
+#include <QCoreApplication>
+#include <QObject>
+#include <QDir>
+
+void QGpgMETest::initTestCase()
+{
+ const QString gpgHome = qgetenv("GNUPGHOME");
+ QVERIFY2(!gpgHome.isEmpty(), "GNUPGHOME environment variable is not set.");
+}
+
+void QGpgMETest::cleanupTestCase()
+{
+ QCoreApplication::sendPostedEvents();
+ killAgent();
+}
+
+bool QGpgMETest::copyKeyrings(const QString &src, const QString &dest)
+{
+ bool is21dir = QFileInfo(src + QDir::separator() + QStringLiteral("pubring.kbx")).exists();
+ const QString name = is21dir ? QStringLiteral("pubring.kbx") :
+ QStringLiteral("pubring.gpg");
+ if (!QFile::copy(src + QDir::separator() + name, dest + QDir::separator() + name)) {
+ return false;
+ }
+ if (!is21dir) {
+ return (QFile::copy(src + QDir::separator() + QStringLiteral("secring.gpg"),
+ dest + QDir::separator() + QStringLiteral("secring.gpg")));
+ }
+ QDir dir (src + QDir::separator() + QStringLiteral("private-keys-v1.d"));
+ QDir target(dest);
+ if (!target.mkdir("private-keys-v1.d")) {
+ return false;
+ }
+ foreach (QString f, dir.entryList(QDir::Files)) {
+ if (!QFile::copy(dir.path() + QDir::separator() + f,
+ dest + QDir::separator() +
+ QStringLiteral("private-keys-v1.d") + QDir::separator() + f)) {
+ return false;
+ }
+ }
+ return true;
+}
+
+void killAgent(const QString& dir)
+{
+ QProcess proc;
+ proc.setProgram(QStringLiteral("gpg-connect-agent"));
+ QStringList arguments;
+ arguments << "-S " << dir + "/S.gpg-agent";
+ proc.start();
+ proc.waitForStarted();
+ proc.write("KILLAGENT\n");
+ proc.write("BYE\n");
+ proc.closeWriteChannel();
+ proc.waitForFinished();
+}
+
+
+#include "t-support.hmoc"
diff --git a/lang/qt/tests/t-support.h b/lang/qt/tests/t-support.h
new file mode 100644
index 0000000..59d9a4d
--- /dev/null
+++ b/lang/qt/tests/t-support.h
@@ -0,0 +1,63 @@
+/* t-support.h
+
+ This file is part of qgpgme, the Qt API binding for gpgme
+ Copyright (c) 2016 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.
+*/
+#ifndef T_SUPPORT_H
+#define T_SUPPORT_H
+
+#include "interfaces/passphraseprovider.h"
+#include <QObject>
+
+namespace GpgME
+{
+class TestPassphraseProvider : public PassphraseProvider
+{
+public:
+ char *getPassphrase(const char *useridHint, const char *description,
+ bool previousWasBad, bool &canceled) Q_DECL_OVERRIDE
+ {
+ return strdup("abc");
+ }
+};
+} // namespace GpgME
+
+void killAgent(const QString &dir = qgetenv("GNUPGHOME"));
+
+class QGpgMETest : public QObject
+{
+ Q_OBJECT
+protected:
+ bool copyKeyrings(const QString &from, const QString& to);
+
+public Q_SLOTS:
+ void initTestCase();
+ void cleanupTestCase();
+};
+
+#endif // T_SUPPORT_H
diff --git a/lang/qt/tests/t-tofuinfo.cpp b/lang/qt/tests/t-tofuinfo.cpp
new file mode 100644
index 0000000..d76ff7b
--- /dev/null
+++ b/lang/qt/tests/t-tofuinfo.cpp
@@ -0,0 +1,367 @@
+/* t-tofuinfo.cpp
+
+ This file is part of qgpgme, the Qt API binding for gpgme
+ Copyright (c) 2016 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.
+*/
+#include <QDebug>
+#include <QTest>
+#include <QTemporaryDir>
+#include "protocol.h"
+#include "tofuinfo.h"
+#include "tofupolicyjob.h"
+#include "verifyopaquejob.h"
+#include "verificationresult.h"
+#include "signingresult.h"
+#include "keylistjob.h"
+#include "keylistresult.h"
+#include "qgpgmesignjob.h"
+#include "key.h"
+#include "t-support.h"
+#include "engineinfo.h"
+#include <iostream>
+
+using namespace QGpgME;
+using namespace GpgME;
+
+static const char testMsg1[] =
+"-----BEGIN PGP MESSAGE-----\n"
+"\n"
+"owGbwMvMwCSoW1RzPCOz3IRxjXQSR0lqcYleSUWJTZOvjVdpcYmCu1+oQmaJIleH\n"
+"GwuDIBMDGysTSIqBi1MApi+nlGGuwDeHao53HBr+FoVGP3xX+kvuu9fCMJvl6IOf\n"
+"y1kvP4y+8D5a11ang0udywsA\n"
+"=Crq6\n"
+"-----END PGP MESSAGE-----\n";
+
+class TofuInfoTest: public QGpgMETest
+{
+ Q_OBJECT
+
+ bool testSupported()
+ {
+ return !(GpgME::engineInfo(GpgME::GpgEngine).engineVersion() < "2.1.16");
+ }
+
+ void testTofuCopy(TofuInfo other, const TofuInfo &orig)
+ {
+ Q_ASSERT(!orig.isNull());
+ Q_ASSERT(!other.isNull());
+ Q_ASSERT(orig.signLast() == other.signLast());
+ Q_ASSERT(orig.signCount() == other.signCount());
+ Q_ASSERT(orig.validity() == other.validity());
+ Q_ASSERT(orig.policy() == other.policy());
+ }
+
+ void signAndVerify(const QString &what, const GpgME::Key &key, int expected)
+ {
+ Context *ctx = Context::createForProtocol(OpenPGP);
+ TestPassphraseProvider provider;
+ ctx->setPassphraseProvider(&provider);
+ ctx->setPinentryMode(Context::PinentryLoopback);
+ auto *job = new QGpgMESignJob(ctx);
+
+ std::vector<Key> keys;
+ keys.push_back(key);
+ QByteArray signedData;
+ auto sigResult = job->exec(keys, what.toUtf8(), NormalSignatureMode, signedData);
+ delete job;
+
+ Q_ASSERT(!sigResult.error());
+ foreach (const auto uid, keys[0].userIDs()) {
+ auto info = uid.tofuInfo();
+ Q_ASSERT(info.signCount() == expected - 1);
+ }
+
+ auto verifyJob = openpgp()->verifyOpaqueJob();
+ QByteArray verified;
+
+ auto result = verifyJob->exec(signedData, verified);
+ delete verifyJob;
+
+ Q_ASSERT(!result.error());
+ Q_ASSERT(verified == what.toUtf8());
+
+ Q_ASSERT(result.numSignatures() == 1);
+ auto sig = result.signatures()[0];
+
+ auto key2 = sig.key();
+ Q_ASSERT(!key.isNull());
+ Q_ASSERT(!strcmp (key2.primaryFingerprint(), key.primaryFingerprint()));
+ Q_ASSERT(!strcmp (key.primaryFingerprint(), sig.fingerprint()));
+ auto stats = key2.userID(0).tofuInfo();
+ Q_ASSERT(!stats.isNull());
+ if (stats.signCount() != expected) {
+ std::cout << "################ Key before verify: "
+ << key
+ << "################ Key after verify: "
+ << key2;
+ }
+ Q_ASSERT(stats.signCount() == expected);
+ }
+
+private Q_SLOTS:
+ void testTofuNull()
+ {
+ if (!testSupported()) {
+ return;
+ }
+ TofuInfo tofu;
+ Q_ASSERT(tofu.isNull());
+ Q_ASSERT(!tofu.description());
+ Q_ASSERT(!tofu.signCount());
+ Q_ASSERT(!tofu.signLast());
+ Q_ASSERT(!tofu.signFirst());
+ Q_ASSERT(tofu.validity() == TofuInfo::ValidityUnknown);
+ Q_ASSERT(tofu.policy() == TofuInfo::PolicyUnknown);
+ }
+
+ void testTofuInfo()
+ {
+ if (!testSupported()) {
+ return;
+ }
+ auto *job = openpgp()->verifyOpaqueJob(true);
+ const QByteArray data1(testMsg1);
+ QByteArray plaintext;
+
+ auto result = job->exec(data1, plaintext);
+ delete job;
+
+ Q_ASSERT(!result.isNull());
+ Q_ASSERT(!result.error());
+ Q_ASSERT(!strcmp(plaintext.constData(), "Just GNU it!\n"));
+
+ Q_ASSERT(result.numSignatures() == 1);
+ Signature sig = result.signatures()[0];
+ /* TOFU is always marginal */
+ Q_ASSERT(sig.validity() == Signature::Marginal);
+
+ auto stats = sig.key().userID(0).tofuInfo();
+ Q_ASSERT(!stats.isNull());
+ Q_ASSERT(sig.key().primaryFingerprint());
+ Q_ASSERT(sig.fingerprint());
+ Q_ASSERT(!strcmp(sig.key().primaryFingerprint(), sig.fingerprint()));
+ Q_ASSERT(stats.signFirst() == stats.signLast());
+ Q_ASSERT(stats.signCount() == 1);
+ Q_ASSERT(stats.policy() == TofuInfo::PolicyAuto);
+ Q_ASSERT(stats.validity() == TofuInfo::LittleHistory);
+
+ testTofuCopy(stats, stats);
+
+ /* Another verify */
+
+ job = openpgp()->verifyOpaqueJob(true);
+ result = job->exec(data1, plaintext);
+ delete job;
+
+ Q_ASSERT(!result.isNull());
+ Q_ASSERT(!result.error());
+
+ Q_ASSERT(result.numSignatures() == 1);
+ sig = result.signatures()[0];
+ /* TOFU is always marginal */
+ Q_ASSERT(sig.validity() == Signature::Marginal);
+
+ stats = sig.key().userID(0).tofuInfo();
+ Q_ASSERT(!stats.isNull());
+ Q_ASSERT(!strcmp(sig.key().primaryFingerprint(), sig.fingerprint()));
+ Q_ASSERT(stats.signFirst() == stats.signLast());
+ Q_ASSERT(stats.signCount() == 1);
+ Q_ASSERT(stats.policy() == TofuInfo::PolicyAuto);
+ Q_ASSERT(stats.validity() == TofuInfo::LittleHistory);
+
+ /* Verify that another call yields the same result */
+ job = openpgp()->verifyOpaqueJob(true);
+ result = job->exec(data1, plaintext);
+ delete job;
+
+ Q_ASSERT(!result.isNull());
+ Q_ASSERT(!result.error());
+
+ Q_ASSERT(result.numSignatures() == 1);
+ sig = result.signatures()[0];
+ /* TOFU is always marginal */
+ Q_ASSERT(sig.validity() == Signature::Marginal);
+
+ stats = sig.key().userID(0).tofuInfo();
+ Q_ASSERT(!stats.isNull());
+ Q_ASSERT(!strcmp(sig.key().primaryFingerprint(), sig.fingerprint()));
+ Q_ASSERT(stats.signFirst() == stats.signLast());
+ Q_ASSERT(stats.signCount() == 1);
+ Q_ASSERT(stats.policy() == TofuInfo::PolicyAuto);
+ Q_ASSERT(stats.validity() == TofuInfo::LittleHistory);
+ }
+
+ void testTofuSignCount()
+ {
+ if (!testSupported()) {
+ return;
+ }
+ auto *job = openpgp()->keyListJob(false, false, false);
+ job->addMode(GpgME::WithTofu);
+ std::vector<GpgME::Key> keys;
+ GpgME::KeyListResult result = job->exec(QStringList() << QStringLiteral("zulu@example.net"),
+ true, keys);
+ delete job;
+ Q_ASSERT(!keys.empty());
+ Key key = keys[0];
+ Q_ASSERT(!key.isNull());
+
+ /* As we sign & verify quickly here we need different
+ * messages to avoid having them treated as the same
+ * message if they were created within the same second.
+ * Alternatively we could use the same message and wait
+ * a second between each call. But this would slow down
+ * the testsuite. */
+ signAndVerify(QStringLiteral("Hello"), key, 1);
+ key.update();
+ signAndVerify(QStringLiteral("Hello2"), key, 2);
+ key.update();
+ signAndVerify(QStringLiteral("Hello3"), key, 3);
+ key.update();
+ signAndVerify(QStringLiteral("Hello4"), key, 4);
+ }
+
+ void testTofuKeyList()
+ {
+ if (!testSupported()) {
+ return;
+ }
+
+ /* First check that the key has no tofu info. */
+ auto *job = openpgp()->keyListJob(false, false, false);
+ std::vector<GpgME::Key> keys;
+ auto result = job->exec(QStringList() << QStringLiteral("zulu@example.net"),
+ true, keys);
+ delete job;
+ Q_ASSERT(!keys.empty());
+ auto key = keys[0];
+ Q_ASSERT(!key.isNull());
+ Q_ASSERT(key.userID(0).tofuInfo().isNull());
+ auto keyCopy = key;
+ keyCopy.update();
+ auto sigCnt = keyCopy.userID(0).tofuInfo().signCount();
+ signAndVerify(QStringLiteral("Hello5"), keyCopy,
+ sigCnt + 1);
+ keyCopy.update();
+ signAndVerify(QStringLiteral("Hello6"), keyCopy,
+ sigCnt + 2);
+
+ /* Now another one but with tofu */
+ job = openpgp()->keyListJob(false, false, false);
+ job->addMode(GpgME::WithTofu);
+ result = job->exec(QStringList() << QStringLiteral("zulu@example.net"),
+ true, keys);
+ delete job;
+ Q_ASSERT(!result.error());
+ Q_ASSERT(!keys.empty());
+ auto key2 = keys[0];
+ Q_ASSERT(!key2.isNull());
+ auto info = key2.userID(0).tofuInfo();
+ Q_ASSERT(!info.isNull());
+ Q_ASSERT(info.signCount());
+ }
+
+ void testTofuPolicy()
+ {
+ if (!testSupported()) {
+ return;
+ }
+
+ /* First check that the key has no tofu info. */
+ auto *job = openpgp()->keyListJob(false, false, false);
+ std::vector<GpgME::Key> keys;
+ job->addMode(GpgME::WithTofu);
+ auto result = job->exec(QStringList() << QStringLiteral("bravo@example.net"),
+ false, keys);
+
+ if (keys.empty()) {
+ qDebug() << "bravo@example.net not found";
+ qDebug() << "Error: " << result.error().asString();
+ const auto homedir = QString::fromLocal8Bit(qgetenv("GNUPGHOME"));
+ qDebug() << "Homedir is: " << homedir;
+ QFileInfo fi(homedir + "/pubring.gpg");
+ qDebug () << "pubring exists: " << fi.exists() << " readable? "
+ << fi.isReadable() << " size: " << fi.size();
+ QFileInfo fi2(homedir + "/pubring.kbx");
+ qDebug () << "keybox exists: " << fi2.exists() << " readable? "
+ << fi2.isReadable() << " size: " << fi2.size();
+
+ result = job->exec(QStringList(), false, keys);
+ foreach (const auto key, keys) {
+ qDebug() << "Key: " << key.userID(0).name() << " <"
+ << key.userID(0).email()
+ << ">\n fpr: " << key.primaryFingerprint();
+ }
+ }
+ Q_ASSERT(!result.error());
+ Q_ASSERT(!keys.empty());
+ auto key = keys[0];
+ Q_ASSERT(!key.isNull());
+ Q_ASSERT(key.userID(0).tofuInfo().policy() != TofuInfo::PolicyBad);
+ auto *tofuJob = openpgp()->tofuPolicyJob();
+ auto err = tofuJob->exec(key, TofuInfo::PolicyBad);
+ Q_ASSERT(!err);
+ result = job->exec(QStringList() << QStringLiteral("bravo@example.net"),
+ false, keys);
+ Q_ASSERT(!keys.empty());
+ key = keys[0];
+ Q_ASSERT(key.userID(0).tofuInfo().policy() == TofuInfo::PolicyBad);
+ err = tofuJob->exec(key, TofuInfo::PolicyGood);
+
+ result = job->exec(QStringList() << QStringLiteral("bravo@example.net"),
+ false, keys);
+ key = keys[0];
+ Q_ASSERT(key.userID(0).tofuInfo().policy() == TofuInfo::PolicyGood);
+ delete tofuJob;
+ delete job;
+ }
+
+ void initTestCase()
+ {
+ QGpgMETest::initTestCase();
+ const QString gpgHome = qgetenv("GNUPGHOME");
+ qputenv("GNUPGHOME", mDir.path().toUtf8());
+ Q_ASSERT(mDir.isValid());
+ QFile conf(mDir.path() + QStringLiteral("/gpg.conf"));
+ Q_ASSERT(conf.open(QIODevice::WriteOnly));
+ conf.write("trust-model tofu+pgp");
+ conf.close();
+ QFile agentConf(mDir.path() + QStringLiteral("/gpg-agent.conf"));
+ Q_ASSERT(agentConf.open(QIODevice::WriteOnly));
+ agentConf.write("allow-loopback-pinentry");
+ agentConf.close();
+ Q_ASSERT(copyKeyrings(gpgHome, mDir.path()));
+ }
+private:
+ QTemporaryDir mDir;
+
+};
+
+QTEST_MAIN(TofuInfoTest)
+
+#include "t-tofuinfo.moc"
diff --git a/lang/qt/tests/t-wkspublish.cpp b/lang/qt/tests/t-wkspublish.cpp
new file mode 100644
index 0000000..17d3447
--- /dev/null
+++ b/lang/qt/tests/t-wkspublish.cpp
@@ -0,0 +1,278 @@
+/* t-wkspublish.cpp
+
+ This file is part of qgpgme, the Qt API binding for gpgme
+ Copyright (c) 2016 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.
+*/
+#include <QDebug>
+#include <QTest>
+#include <QSignalSpy>
+#include <QTemporaryDir>
+#include "wkspublishjob.h"
+#include "keygenerationjob.h"
+#include "keygenerationresult.h"
+#include "importjob.h"
+#include "importresult.h"
+#include "protocol.h"
+#include "engineinfo.h"
+
+#include "t-support.h"
+
+using namespace QGpgME;
+using namespace GpgME;
+
+//#define DO_ONLINE_TESTS
+
+#define TEST_ADDRESS "testuser2@test.gnupg.org"
+
+static const char *testSecKey =
+"-----BEGIN PGP PRIVATE KEY BLOCK-----\n"
+"\n"
+"lHgEV77hVhMJKyQDAwIIAQEHAgMEN3qKqBr9EecnfUnpw8RS8DHAjJqhwm2HAoEE\n"
+"3yfQQ9w8uB/bKm5dqW4HML3JWRH8YoJaKSVrJY2D1FZUY+vHlgABAKDwEAB0HND8\n"
+"5kbxiJmqKIuuNqCJ2jHgs9G0xk4GdKvZEdq0JlRlc3QgVXNlciAyIDx0ZXN0dXNl\n"
+"cjJAdGVzdC5nbnVwZy5vcmc+iHkEExMIACEFAle+4VYCGwMFCwkIBwIGFQgJCgsC\n"
+"BBYCAwECHgECF4AACgkQRVRoUEJO+6zgFQD7BF3pnS3w3A7J9y+Y3kyGfmscXFWJ\n"
+"Kme1PAsAlVSm1y4A+weReMvWFYHJH257v94yhStmV8egGoybsNDttNAW53cbnHwE\n"
+"V77hVhIJKyQDAwIIAQEHAgMEX+6cF0HEn4g3ztFvwHyr7uwXMVYUGL3lE3mjhnV3\n"
+"SbY6Dmy3OeFVnEVkawHqSv+HobpQTeEqNoQHAoIiXFCRlgMBCAcAAP9FykiyDspm\n"
+"T33XWRPD+LAOmaIU7CIhfv9+lVkeExlU1w+qiGEEGBMIAAkFAle+4VYCGwwACgkQ\n"
+"RVRoUEJO+6xjhgD/ZJ/MwYZJPk/xPYhTP8+wF+tErVNA8w3pP9D69dgUPdcA/izZ\n"
+"Pji6YetVhgsyaHc4PrKynsk5G6nM3KkAOehUQsX8\n"
+"=S/Wa\n"
+"-----END PGP PRIVATE KEY BLOCK-----\n";
+
+static const char *testResponse =
+"From key-submission@test.gnupg.org Thu Aug 25 12:15:54 2016\n"
+"Return-Path: <webkey@g10code.com>\n"
+"From: key-submission@test.gnupg.org\n"
+"To: testuser2@test.gnupg.org\n"
+"Subject: Confirm your key publication\n"
+"X-Wks-Loop: webkey.g10code.com\n"
+"MIME-Version: 1.0\n"
+"Content-Type: multipart/encrypted; protocol=\"application/pgp-encrypted\";\n"
+" boundary=\"=-=01-wbu5fr9nu6fix5tcojjo=-=\"\n"
+"Date: Thu, 25 Aug 2016 12:15:54 +0000\n"
+"Message-Id: <E1bctZa-0004LE-Fr@kerckhoffs.g10code.com>\n"
+"Sender: <webkey@g10code.com>\n"
+"X-Kolab-Scheduling-Message: FALSE\n"
+"\n"
+" \n"
+"\n"
+"--=-=01-wbu5fr9nu6fix5tcojjo=-=\n"
+"Content-Type: application/pgp-encrypted\n"
+"\n"
+"Version: 1\n"
+"\n"
+"--=-=01-wbu5fr9nu6fix5tcojjo=-=\n"
+"Content-Type: application/octet-stream\n"
+"\n"
+"-----BEGIN PGP MESSAGE-----\n"
+"Version: GnuPG v2\n"
+"\n"
+"hH4D8pSp7hUsFUASAgMEg0w39E6d0TkFYxLbT6n3YcoKTT+Ur/c7Sn1ECyL7Rnuk\n"
+"cmPO0adt3JxueK7Oz5COlk32SECFODdF3cQuDhkGxzC6Sfc4SfisdILmNhaT/MeW\n"
+"8a+yE4skSK70absif4kw5XkvxXNxHeIHfAteP50jPJLSwEsBTEceb9cRMoP7s8w0\n"
+"lYyi+RWQ7UKlKKywtcRCL4ow2H7spjx+a+3FzNOAoy7K0/thhLVRk8z+iuPi0/4n\n"
+"Z2Ql60USLLUlfV2ZIpXdCd+5GjTJsnGhDos1pas5TZcOOAxO12Cg5TcqHISOaqa8\n"
+"6BqxcKCU3NypIynOKHj375KArSs0WsEH8HWHyBBHB+NYtNpnTAuHNKxM+JtNxf+U\n"
+"NfD2zptS6kyiHLw+4zjL5pEV7RHS2PBwWBDS6vhnyybNwckleya96U04iYiGRYGE\n"
+"lUUR6Fl8H6x04dItFH1/jJA6Ppcu4FoYou04HADWCqJXPTgztjiW1/9QoCeXl5lm\n"
+"CcOCcuw7lXp+qTejuns=\n"
+"=SsWX\n"
+"-----END PGP MESSAGE-----\n"
+"\n"
+"--=-=01-wbu5fr9nu6fix5tcojjo=-=--\n";
+
+
+class WKSPublishTest : public QGpgMETest
+{
+ Q_OBJECT
+
+Q_SIGNALS:
+ void asyncDone();
+
+private Q_SLOTS:
+ void testUnsupported()
+ {
+ // First check if it is supported
+ auto job = openpgp()->wksPublishJob();
+ connect(job, &WKSPublishJob::result, this,
+ [this] (Error err, QByteArray out, QByteArray errout, QString, Error) {
+ Q_ASSERT(err);
+ Q_EMIT asyncDone();
+ });
+ job->startCheck ("testuser1@localhost");
+ QSignalSpy spy (this, SIGNAL(asyncDone()));
+ Q_ASSERT(spy.wait());
+ }
+#ifdef DO_ONLINE_TESTS
+private Q_SLOTS:
+#else
+private:
+#endif
+ void testWSKPublishSupport()
+ {
+ // First check if it is supported
+ auto job = openpgp()->wksPublishJob();
+ connect(job, &WKSPublishJob::result, this,
+ [this] (Error err, QByteArray out, QByteArray errout, QString, Error) {
+ if (GpgME::engineInfo(GpgME::GpgEngine).engineVersion() < "2.0.16") {
+ std::cout << err;
+ Q_ASSERT(err);
+ } else {
+ Q_ASSERT(!err);
+ }
+ Q_EMIT asyncDone();
+ });
+ job->startCheck ("testuser1@test.gnupg.org");
+ QSignalSpy spy (this, SIGNAL(asyncDone()));
+ Q_ASSERT(spy.wait());
+ }
+
+ void testWKSPublishErrors() {
+ if (GpgME::engineInfo(GpgME::GpgEngine).engineVersion() < "2.0.16") {
+ /* Not supported */
+ return;
+ }
+ auto job = openpgp()->wksPublishJob();
+ connect(job, &WKSPublishJob::result, this,
+ [this] (Error err, QByteArray out, QByteArray errout, QString, Error) {
+ Q_ASSERT(err);
+ Q_EMIT asyncDone();
+ });
+ job->startCreate("AB874F24E98EBB8487EE7B170F8E3D97FE7011B7",
+ QStringLiteral("Foo@bar.baz"));
+ QSignalSpy spy (this, SIGNAL(asyncDone()));
+ Q_ASSERT(spy.wait());
+ }
+
+ void testWKSPublishCreate() {
+ if (GpgME::engineInfo(GpgME::GpgEngine).engineVersion() < "2.0.16") {
+ /* Not supported */
+ return;
+ }
+ /* First generate a test key */
+ const QString args = QStringLiteral("<GnupgKeyParms format=\"internal\">\n"
+ "%no-protection\n"
+ "%transient-key\n"
+ "key-type: ECDSA\n"
+ "key-curve: brainpoolP256r1\n"
+ "key-usage: sign\n"
+ "subkey-type: ECDH\n"
+ "subkey-curve: brainpoolP256r1\n"
+ "subkey-usage: encrypt\n"
+ "name-email: %1\n"
+ "name-real: Test User\n"
+ "</GnupgKeyParms>").arg(TEST_ADDRESS);
+
+ auto keygenjob = openpgp()->keyGenerationJob();
+ QByteArray fpr;
+ connect(keygenjob, &KeyGenerationJob::result, this,
+ [this, &fpr](KeyGenerationResult result, QByteArray pubkeyData, QString, Error)
+ {
+ Q_ASSERT(!result.error());
+ fpr = QByteArray(result.fingerprint());
+ Q_ASSERT(!fpr.isEmpty());
+ Q_EMIT asyncDone();
+ });
+ keygenjob->start(args);
+ QSignalSpy spy (this, SIGNAL(asyncDone()));
+ Q_ASSERT(spy.wait());
+
+ /* Then try to create a request. */
+ auto job = openpgp()->wksPublishJob();
+ connect(job, &WKSPublishJob::result, this,
+ [this] (Error err, QByteArray out, QByteArray errout, QString, Error) {
+ Q_ASSERT(!err);
+ Q_EMIT asyncDone();
+ const QString outstr = QString(out);
+ Q_ASSERT(outstr.contains(
+ QStringLiteral("-----BEGIN PGP PUBLIC KEY BLOCK-----")));
+ Q_ASSERT(outstr.contains(
+ QStringLiteral("Content-Type: application/pgp-keys")));
+ Q_ASSERT(outstr.contains(
+ QStringLiteral("From: " TEST_ADDRESS)));
+ });
+ job->startCreate(fpr.constData(), QLatin1String(TEST_ADDRESS));
+ Q_ASSERT(spy.wait());
+ }
+
+ void testWKSPublishRecieve() {
+ if (GpgME::engineInfo(GpgME::GpgEngine).engineVersion() < "2.0.16") {
+ /* Not supported */
+ return;
+ }
+ auto importjob = openpgp()->importJob();
+ connect(importjob, &ImportJob::result, this,
+ [this](ImportResult result, QString, Error)
+ {
+ Q_ASSERT(!result.error());
+ Q_ASSERT(!result.imports().empty());
+ Q_ASSERT(result.numSecretKeysImported());
+ Q_EMIT asyncDone();
+ });
+ importjob->start(QByteArray(testSecKey));
+ QSignalSpy spy (this, SIGNAL(asyncDone()));
+ Q_ASSERT(spy.wait());
+
+ /* Get a response. */
+ auto job = openpgp()->wksPublishJob();
+ connect(job, &WKSPublishJob::result, this,
+ [this] (Error err, QByteArray out, QByteArray errout, QString, Error) {
+ Q_ASSERT(!err);
+ Q_EMIT asyncDone();
+ const QString outstr = QString(out);
+ Q_ASSERT(outstr.contains(
+ QStringLiteral("-----BEGIN PGP MESSAGE-----")));
+ Q_ASSERT(outstr.contains(
+ QStringLiteral("Content-Type: multipart/encrypted;")));
+ Q_ASSERT(outstr.contains(
+ QStringLiteral("From: " TEST_ADDRESS)));
+ });
+ job->startRecieve(QByteArray(testResponse));
+ Q_ASSERT(spy.wait());
+ }
+
+ void initTestCase()
+ {
+ QGpgMETest::initTestCase();
+ const QString gpgHome = qgetenv("GNUPGHOME");
+ qputenv("GNUPGHOME", mDir.path().toUtf8());
+ Q_ASSERT(mDir.isValid());
+ QFile agentConf(mDir.path() + QStringLiteral("/gpg-agent.conf"));
+ Q_ASSERT(agentConf.open(QIODevice::WriteOnly));
+ agentConf.write("allow-loopback-pinentry");
+ agentConf.close();
+ }
+private:
+ QTemporaryDir mDir;
+};
+
+QTEST_MAIN(WKSPublishTest)
+
+#include "t-wkspublish.moc"
diff --git a/m4/ax_cxx_compile_stdcxx.m4 b/m4/ax_cxx_compile_stdcxx.m4
new file mode 100644
index 0000000..de3d012
--- /dev/null
+++ b/m4/ax_cxx_compile_stdcxx.m4
@@ -0,0 +1,558 @@
+# ===========================================================================
+# http://www.gnu.org/software/autoconf-archive/ax_cxx_compile_stdcxx.html
+# ===========================================================================
+#
+# SYNOPSIS
+#
+# AX_CXX_COMPILE_STDCXX(VERSION, [ext|noext], [mandatory|optional])
+#
+# DESCRIPTION
+#
+# Check for baseline language coverage in the compiler for the specified
+# version of the C++ standard. If necessary, add switches to CXX and
+# CXXCPP to enable support. VERSION may be '11' (for the C++11 standard)
+# or '14' (for the C++14 standard).
+#
+# The second argument, if specified, indicates whether you insist on an
+# extended mode (e.g. -std=gnu++11) or a strict conformance mode (e.g.
+# -std=c++11). If neither is specified, you get whatever works, with
+# preference for an extended mode.
+#
+# The third argument, if specified 'mandatory' or if left unspecified,
+# indicates that baseline support for the specified C++ standard is
+# required and that the macro should error out if no mode with that
+# support is found. If specified 'optional', then configuration proceeds
+# regardless, after defining HAVE_CXX${VERSION} if and only if a
+# supporting mode is found.
+#
+# LICENSE
+#
+# Copyright (c) 2008 Benjamin Kosnik <bkoz@redhat.com>
+# Copyright (c) 2012 Zack Weinberg <zackw@panix.com>
+# Copyright (c) 2013 Roy Stogner <roystgnr@ices.utexas.edu>
+# Copyright (c) 2014, 2015 Google Inc.; contributed by Alexey Sokolov <sokolov@google.com>
+# Copyright (c) 2015 Paul Norman <penorman@mac.com>
+# Copyright (c) 2015 Moritz Klammler <moritz@klammler.eu>
+#
+# Copying and distribution of this file, with or without modification, are
+# permitted in any medium without royalty provided the copyright notice
+# and this notice are preserved. This file is offered as-is, without any
+# warranty.
+
+#serial 4
+
+dnl This macro is based on the code from the AX_CXX_COMPILE_STDCXX_11 macro
+dnl (serial version number 13).
+
+AC_DEFUN([AX_CXX_COMPILE_STDCXX], [dnl
+ m4_if([$1], [11], [],
+ [$1], [14], [],
+ [$1], [17], [m4_fatal([support for C++17 not yet implemented in AX_CXX_COMPILE_STDCXX])],
+ [m4_fatal([invalid first argument `$1' to AX_CXX_COMPILE_STDCXX])])dnl
+ m4_if([$2], [], [],
+ [$2], [ext], [],
+ [$2], [noext], [],
+ [m4_fatal([invalid second argument `$2' to AX_CXX_COMPILE_STDCXX])])dnl
+ m4_if([$3], [], [ax_cxx_compile_cxx$1_required=true],
+ [$3], [mandatory], [ax_cxx_compile_cxx$1_required=true],
+ [$3], [optional], [ax_cxx_compile_cxx$1_required=false],
+ [m4_fatal([invalid third argument `$3' to AX_CXX_COMPILE_STDCXX])])
+ AC_LANG_PUSH([C++])dnl
+ ac_success=no
+ AC_CACHE_CHECK(whether $CXX supports C++$1 features by default,
+ ax_cv_cxx_compile_cxx$1,
+ [AC_COMPILE_IFELSE([AC_LANG_SOURCE([_AX_CXX_COMPILE_STDCXX_testbody_$1])],
+ [ax_cv_cxx_compile_cxx$1=yes],
+ [ax_cv_cxx_compile_cxx$1=no])])
+ if test x$ax_cv_cxx_compile_cxx$1 = xyes; then
+ ac_success=yes
+ fi
+
+ m4_if([$2], [noext], [], [dnl
+ if test x$ac_success = xno; then
+ for switch in -std=gnu++$1 -std=gnu++0x; do
+ cachevar=AS_TR_SH([ax_cv_cxx_compile_cxx$1_$switch])
+ AC_CACHE_CHECK(whether $CXX supports C++$1 features with $switch,
+ $cachevar,
+ [ac_save_CXX="$CXX"
+ CXX="$CXX $switch"
+ AC_COMPILE_IFELSE([AC_LANG_SOURCE([_AX_CXX_COMPILE_STDCXX_testbody_$1])],
+ [eval $cachevar=yes],
+ [eval $cachevar=no])
+ CXX="$ac_save_CXX"])
+ if eval test x\$$cachevar = xyes; then
+ CXX="$CXX $switch"
+ CXXCPP="$CXXCPP $switch"
+ ac_success=yes
+ break
+ fi
+ done
+ fi])
+
+ m4_if([$2], [ext], [], [dnl
+ if test x$ac_success = xno; then
+ dnl HP's aCC needs +std=c++11 according to:
+ dnl http://h21007.www2.hp.com/portal/download/files/unprot/aCxx/PDF_Release_Notes/769149-001.pdf
+ dnl Cray's crayCC needs "-h std=c++11"
+ for switch in -std=c++$1 -std=c++0x +std=c++$1 "-h std=c++$1"; do
+ cachevar=AS_TR_SH([ax_cv_cxx_compile_cxx$1_$switch])
+ AC_CACHE_CHECK(whether $CXX supports C++$1 features with $switch,
+ $cachevar,
+ [ac_save_CXX="$CXX"
+ CXX="$CXX $switch"
+ AC_COMPILE_IFELSE([AC_LANG_SOURCE([_AX_CXX_COMPILE_STDCXX_testbody_$1])],
+ [eval $cachevar=yes],
+ [eval $cachevar=no])
+ CXX="$ac_save_CXX"])
+ if eval test x\$$cachevar = xyes; then
+ CXX="$CXX $switch"
+ CXXCPP="$CXXCPP $switch"
+ ac_success=yes
+ break
+ fi
+ done
+ fi])
+ AC_LANG_POP([C++])
+ if test x$ax_cxx_compile_cxx$1_required = xtrue; then
+ if test x$ac_success = xno; then
+ AC_MSG_ERROR([*** A compiler with support for C++$1 language features is required.])
+ fi
+ fi
+ if test x$ac_success = xno; then
+ HAVE_CXX$1=0
+ AC_MSG_NOTICE([No compiler with C++$1 support was found])
+ else
+ HAVE_CXX$1=1
+ AC_DEFINE(HAVE_CXX$1,1,
+ [define if the compiler supports basic C++$1 syntax])
+ fi
+ AC_SUBST(HAVE_CXX$1)
+])
+
+
+dnl Test body for checking C++11 support
+
+m4_define([_AX_CXX_COMPILE_STDCXX_testbody_11],
+ _AX_CXX_COMPILE_STDCXX_testbody_new_in_11
+)
+
+
+dnl Test body for checking C++14 support
+
+m4_define([_AX_CXX_COMPILE_STDCXX_testbody_14],
+ _AX_CXX_COMPILE_STDCXX_testbody_new_in_11
+ _AX_CXX_COMPILE_STDCXX_testbody_new_in_14
+)
+
+
+dnl Tests for new features in C++11
+
+m4_define([_AX_CXX_COMPILE_STDCXX_testbody_new_in_11], [[
+
+// If the compiler admits that it is not ready for C++11, why torture it?
+// Hopefully, this will speed up the test.
+
+#ifndef __cplusplus
+
+#error "This is not a C++ compiler"
+
+#elif __cplusplus < 201103L
+
+#error "This is not a C++11 compiler"
+
+#else
+
+namespace cxx11
+{
+
+ namespace test_static_assert
+ {
+
+ template <typename T>
+ struct check
+ {
+ static_assert(sizeof(int) <= sizeof(T), "not big enough");
+ };
+
+ }
+
+ namespace test_final_override
+ {
+
+ struct Base
+ {
+ virtual void f() {}
+ };
+
+ struct Derived : public Base
+ {
+ virtual void f() override {}
+ };
+
+ }
+
+ namespace test_double_right_angle_brackets
+ {
+
+ template < typename T >
+ struct check {};
+
+ typedef check<void> single_type;
+ typedef check<check<void>> double_type;
+ typedef check<check<check<void>>> triple_type;
+ typedef check<check<check<check<void>>>> quadruple_type;
+
+ }
+
+ namespace test_decltype
+ {
+
+ int
+ f()
+ {
+ int a = 1;
+ decltype(a) b = 2;
+ return a + b;
+ }
+
+ }
+
+ namespace test_type_deduction
+ {
+
+ template < typename T1, typename T2 >
+ struct is_same
+ {
+ static const bool value = false;
+ };
+
+ template < typename T >
+ struct is_same<T, T>
+ {
+ static const bool value = true;
+ };
+
+ template < typename T1, typename T2 >
+ auto
+ add(T1 a1, T2 a2) -> decltype(a1 + a2)
+ {
+ return a1 + a2;
+ }
+
+ int
+ test(const int c, volatile int v)
+ {
+ static_assert(is_same<int, decltype(0)>::value == true, "");
+ static_assert(is_same<int, decltype(c)>::value == false, "");
+ static_assert(is_same<int, decltype(v)>::value == false, "");
+ auto ac = c;
+ auto av = v;
+ auto sumi = ac + av + 'x';
+ auto sumf = ac + av + 1.0;
+ static_assert(is_same<int, decltype(ac)>::value == true, "");
+ static_assert(is_same<int, decltype(av)>::value == true, "");
+ static_assert(is_same<int, decltype(sumi)>::value == true, "");
+ static_assert(is_same<int, decltype(sumf)>::value == false, "");
+ static_assert(is_same<int, decltype(add(c, v))>::value == true, "");
+ return (sumf > 0.0) ? sumi : add(c, v);
+ }
+
+ }
+
+ namespace test_noexcept
+ {
+
+ int f() { return 0; }
+ int g() noexcept { return 0; }
+
+ static_assert(noexcept(f()) == false, "");
+ static_assert(noexcept(g()) == true, "");
+
+ }
+
+ namespace test_constexpr
+ {
+
+ template < typename CharT >
+ unsigned long constexpr
+ strlen_c_r(const CharT *const s, const unsigned long acc) noexcept
+ {
+ return *s ? strlen_c_r(s + 1, acc + 1) : acc;
+ }
+
+ template < typename CharT >
+ unsigned long constexpr
+ strlen_c(const CharT *const s) noexcept
+ {
+ return strlen_c_r(s, 0UL);
+ }
+
+ static_assert(strlen_c("") == 0UL, "");
+ static_assert(strlen_c("1") == 1UL, "");
+ static_assert(strlen_c("example") == 7UL, "");
+ static_assert(strlen_c("another\0example") == 7UL, "");
+
+ }
+
+ namespace test_rvalue_references
+ {
+
+ template < int N >
+ struct answer
+ {
+ static constexpr int value = N;
+ };
+
+ answer<1> f(int&) { return answer<1>(); }
+ answer<2> f(const int&) { return answer<2>(); }
+ answer<3> f(int&&) { return answer<3>(); }
+
+ void
+ test()
+ {
+ int i = 0;
+ const int c = 0;
+ static_assert(decltype(f(i))::value == 1, "");
+ static_assert(decltype(f(c))::value == 2, "");
+ static_assert(decltype(f(0))::value == 3, "");
+ }
+
+ }
+
+ namespace test_uniform_initialization
+ {
+
+ struct test
+ {
+ static const int zero {};
+ static const int one {1};
+ };
+
+ static_assert(test::zero == 0, "");
+ static_assert(test::one == 1, "");
+
+ }
+
+ namespace test_lambdas
+ {
+
+ void
+ test1()
+ {
+ auto lambda1 = [](){};
+ auto lambda2 = lambda1;
+ lambda1();
+ lambda2();
+ }
+
+ int
+ test2()
+ {
+ auto a = [](int i, int j){ return i + j; }(1, 2);
+ auto b = []() -> int { return '0'; }();
+ auto c = [=](){ return a + b; }();
+ auto d = [&](){ return c; }();
+ auto e = [a, &b](int x) mutable {
+ const auto identity = [](int y){ return y; };
+ for (auto i = 0; i < a; ++i)
+ a += b--;
+ return x + identity(a + b);
+ }(0);
+ return a + b + c + d + e;
+ }
+
+ int
+ test3()
+ {
+ const auto nullary = [](){ return 0; };
+ const auto unary = [](int x){ return x; };
+ using nullary_t = decltype(nullary);
+ using unary_t = decltype(unary);
+ const auto higher1st = [](nullary_t f){ return f(); };
+ const auto higher2nd = [unary](nullary_t f1){
+ return [unary, f1](unary_t f2){ return f2(unary(f1())); };
+ };
+ return higher1st(nullary) + higher2nd(nullary)(unary);
+ }
+
+ }
+
+ namespace test_variadic_templates
+ {
+
+ template <int...>
+ struct sum;
+
+ template <int N0, int... N1toN>
+ struct sum<N0, N1toN...>
+ {
+ static constexpr auto value = N0 + sum<N1toN...>::value;
+ };
+
+ template <>
+ struct sum<>
+ {
+ static constexpr auto value = 0;
+ };
+
+ static_assert(sum<>::value == 0, "");
+ static_assert(sum<1>::value == 1, "");
+ static_assert(sum<23>::value == 23, "");
+ static_assert(sum<1, 2>::value == 3, "");
+ static_assert(sum<5, 5, 11>::value == 21, "");
+ static_assert(sum<2, 3, 5, 7, 11, 13>::value == 41, "");
+
+ }
+
+ // http://stackoverflow.com/questions/13728184/template-aliases-and-sfinae
+ // Clang 3.1 fails with headers of libstd++ 4.8.3 when using std::function
+ // because of this.
+ namespace test_template_alias_sfinae
+ {
+
+ struct foo {};
+
+ template<typename T>
+ using member = typename T::member_type;
+
+ template<typename T>
+ void func(...) {}
+
+ template<typename T>
+ void func(member<T>*) {}
+
+ void test();
+
+ void test() { func<foo>(0); }
+
+ }
+
+} // namespace cxx11
+
+#endif // __cplusplus >= 201103L
+
+]])
+
+
+dnl Tests for new features in C++14
+
+m4_define([_AX_CXX_COMPILE_STDCXX_testbody_new_in_14], [[
+
+// If the compiler admits that it is not ready for C++14, why torture it?
+// Hopefully, this will speed up the test.
+
+#ifndef __cplusplus
+
+#error "This is not a C++ compiler"
+
+#elif __cplusplus < 201402L
+
+#error "This is not a C++14 compiler"
+
+#else
+
+namespace cxx14
+{
+
+ namespace test_polymorphic_lambdas
+ {
+
+ int
+ test()
+ {
+ const auto lambda = [](auto&&... args){
+ const auto istiny = [](auto x){
+ return (sizeof(x) == 1UL) ? 1 : 0;
+ };
+ const int aretiny[] = { istiny(args)... };
+ return aretiny[0];
+ };
+ return lambda(1, 1L, 1.0f, '1');
+ }
+
+ }
+
+ namespace test_binary_literals
+ {
+
+ constexpr auto ivii = 0b0000000000101010;
+ static_assert(ivii == 42, "wrong value");
+
+ }
+
+ namespace test_generalized_constexpr
+ {
+
+ template < typename CharT >
+ constexpr unsigned long
+ strlen_c(const CharT *const s) noexcept
+ {
+ auto length = 0UL;
+ for (auto p = s; *p; ++p)
+ ++length;
+ return length;
+ }
+
+ static_assert(strlen_c("") == 0UL, "");
+ static_assert(strlen_c("x") == 1UL, "");
+ static_assert(strlen_c("test") == 4UL, "");
+ static_assert(strlen_c("another\0test") == 7UL, "");
+
+ }
+
+ namespace test_lambda_init_capture
+ {
+
+ int
+ test()
+ {
+ auto x = 0;
+ const auto lambda1 = [a = x](int b){ return a + b; };
+ const auto lambda2 = [a = lambda1(x)](){ return a; };
+ return lambda2();
+ }
+
+ }
+
+ namespace test_digit_seperators
+ {
+
+ constexpr auto ten_million = 100'000'000;
+ static_assert(ten_million == 100000000, "");
+
+ }
+
+ namespace test_return_type_deduction
+ {
+
+ auto f(int& x) { return x; }
+ decltype(auto) g(int& x) { return x; }
+
+ template < typename T1, typename T2 >
+ struct is_same
+ {
+ static constexpr auto value = false;
+ };
+
+ template < typename T >
+ struct is_same<T, T>
+ {
+ static constexpr auto value = true;
+ };
+
+ int
+ test()
+ {
+ auto x = 0;
+ static_assert(is_same<int, decltype(f(x))>::value, "");
+ static_assert(is_same<int&, decltype(g(x))>::value, "");
+ return x;
+ }
+
+ }
+
+} // namespace cxx14
+
+#endif // __cplusplus >= 201402L
+
+]])
diff --git a/m4/ax_pkg_swig.m4 b/m4/ax_pkg_swig.m4
new file mode 100644
index 0000000..d836eec
--- /dev/null
+++ b/m4/ax_pkg_swig.m4
@@ -0,0 +1,135 @@
+# ===========================================================================
+# http://www.gnu.org/software/autoconf-archive/ax_pkg_swig.html
+# ===========================================================================
+#
+# SYNOPSIS
+#
+# AX_PKG_SWIG([major.minor.micro], [action-if-found], [action-if-not-found])
+#
+# DESCRIPTION
+#
+# This macro searches for a SWIG installation on your system. If found,
+# then SWIG is AC_SUBST'd; if not found, then $SWIG is empty. If SWIG is
+# found, then SWIG_LIB is set to the SWIG library path, and AC_SUBST'd.
+#
+# You can use the optional first argument to check if the version of the
+# available SWIG is greater than or equal to the value of the argument. It
+# should have the format: N[.N[.N]] (N is a number between 0 and 999. Only
+# the first N is mandatory.) If the version argument is given (e.g.
+# 1.3.17), AX_PKG_SWIG checks that the swig package is this version number
+# or higher.
+#
+# As usual, action-if-found is executed if SWIG is found, otherwise
+# action-if-not-found is executed.
+#
+# In configure.in, use as:
+#
+# AX_PKG_SWIG(1.3.17, [], [ AC_MSG_ERROR([SWIG is required to build..]) ])
+# AX_SWIG_ENABLE_CXX
+# AX_SWIG_MULTI_MODULE_SUPPORT
+# AX_SWIG_PYTHON
+#
+# LICENSE
+#
+# Copyright (c) 2008 Sebastian Huber <sebastian-huber@web.de>
+# Copyright (c) 2008 Alan W. Irwin
+# Copyright (c) 2008 Rafael Laboissiere <rafael@laboissiere.net>
+# Copyright (c) 2008 Andrew Collier
+# Copyright (c) 2011 Murray Cumming <murrayc@openismus.com>
+#
+# This program 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.
+#
+# This program 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, see <http://www.gnu.org/licenses/>.
+#
+# As a special exception, the respective Autoconf Macro's copyright owner
+# gives unlimited permission to copy, distribute and modify the configure
+# scripts that are the output of Autoconf when processing the Macro. You
+# need not follow the terms of the GNU General Public License when using
+# or distributing such scripts, even though portions of the text of the
+# Macro appear in them. The GNU General Public License (GPL) does govern
+# all other use of the material that constitutes the Autoconf Macro.
+#
+# This special exception to the GPL applies to versions of the Autoconf
+# Macro released by the Autoconf Archive. When you make and distribute a
+# modified version of the Autoconf Macro, you may extend this special
+# exception to the GPL to apply to your modified version as well.
+
+#serial 11
+
+AC_DEFUN([AX_PKG_SWIG],[
+ # Ubuntu has swig 2.0 as /usr/bin/swig2.0
+ AC_PATH_PROGS([SWIG],[swig swig2.0])
+ if test -z "$SWIG" ; then
+ m4_ifval([$3],[$3],[:])
+ elif test -n "$1" ; then
+ AC_MSG_CHECKING([SWIG version])
+ [swig_version=`$SWIG -version 2>&1 | grep 'SWIG Version' | sed 's/.*\([0-9][0-9]*\.[0-9][0-9]*\.[0-9][0-9]*\).*/\1/g'`]
+ AC_MSG_RESULT([$swig_version])
+ if test -n "$swig_version" ; then
+ # Calculate the required version number components
+ [required=$1]
+ [required_major=`echo $required | sed 's/[^0-9].*//'`]
+ if test -z "$required_major" ; then
+ [required_major=0]
+ fi
+ [required=`echo $required | sed 's/[0-9]*[^0-9]//'`]
+ [required_minor=`echo $required | sed 's/[^0-9].*//'`]
+ if test -z "$required_minor" ; then
+ [required_minor=0]
+ fi
+ [required=`echo $required | sed 's/[0-9]*[^0-9]//'`]
+ [required_patch=`echo $required | sed 's/[^0-9].*//'`]
+ if test -z "$required_patch" ; then
+ [required_patch=0]
+ fi
+ # Calculate the available version number components
+ [available=$swig_version]
+ [available_major=`echo $available | sed 's/[^0-9].*//'`]
+ if test -z "$available_major" ; then
+ [available_major=0]
+ fi
+ [available=`echo $available | sed 's/[0-9]*[^0-9]//'`]
+ [available_minor=`echo $available | sed 's/[^0-9].*//'`]
+ if test -z "$available_minor" ; then
+ [available_minor=0]
+ fi
+ [available=`echo $available | sed 's/[0-9]*[^0-9]//'`]
+ [available_patch=`echo $available | sed 's/[^0-9].*//'`]
+ if test -z "$available_patch" ; then
+ [available_patch=0]
+ fi
+ # Convert the version tuple into a single number for easier comparison.
+ # Using base 100 should be safe since SWIG internally uses BCD values
+ # to encode its version number.
+ required_swig_vernum=`expr $required_major \* 10000 \
+ \+ $required_minor \* 100 \+ $required_patch`
+ available_swig_vernum=`expr $available_major \* 10000 \
+ \+ $available_minor \* 100 \+ $available_patch`
+
+ if test $available_swig_vernum -lt $required_swig_vernum; then
+ AC_MSG_WARN([SWIG version >= $1 is required. You have $swig_version.])
+ SWIG=''
+ m4_ifval([$3],[$3],[])
+ else
+ AC_MSG_CHECKING([for SWIG library])
+ SWIG_LIB=`$SWIG -swiglib`
+ AC_MSG_RESULT([$SWIG_LIB])
+ m4_ifval([$2],[$2],[])
+ fi
+ else
+ AC_MSG_WARN([cannot determine SWIG version])
+ SWIG=''
+ m4_ifval([$3],[$3],[])
+ fi
+ fi
+ AC_SUBST([SWIG_LIB])
+])
diff --git a/m4/ax_python_devel.m4 b/m4/ax_python_devel.m4
new file mode 100644
index 0000000..de992c8
--- /dev/null
+++ b/m4/ax_python_devel.m4
@@ -0,0 +1,323 @@
+# ===========================================================================
+# http://www.gnu.org/software/autoconf-archive/ax_python_devel.html
+# ===========================================================================
+#
+# SYNOPSIS
+#
+# AX_PYTHON_DEVEL([version])
+#
+# DESCRIPTION
+#
+# Note: Defines as a precious variable "PYTHON_VERSION". Don't override it
+# in your configure.ac.
+#
+# This macro checks for Python and tries to get the include path to
+# 'Python.h'. It provides the $(PYTHON_CPPFLAGS) and $(PYTHON_LDFLAGS)
+# output variables. It also exports $(PYTHON_EXTRA_LIBS) and
+# $(PYTHON_EXTRA_LDFLAGS) for embedding Python in your code.
+#
+# You can search for some particular version of Python by passing a
+# parameter to this macro, for example ">= '2.3.1'", or "== '2.4'". Please
+# note that you *have* to pass also an operator along with the version to
+# match, and pay special attention to the single quotes surrounding the
+# version number. Don't use "PYTHON_VERSION" for this: that environment
+# variable is declared as precious and thus reserved for the end-user.
+#
+# This macro should work for all versions of Python >= 2.1.0. As an end
+# user, you can disable the check for the python version by setting the
+# PYTHON_NOVERSIONCHECK environment variable to something else than the
+# empty string.
+#
+# If you need to use this macro for an older Python version, please
+# contact the authors. We're always open for feedback.
+#
+# LICENSE
+#
+# Copyright (c) 2009 Sebastian Huber <sebastian-huber@web.de>
+# Copyright (c) 2009 Alan W. Irwin
+# Copyright (c) 2009 Rafael Laboissiere <rafael@laboissiere.net>
+# Copyright (c) 2009 Andrew Collier
+# Copyright (c) 2009 Matteo Settenvini <matteo@member.fsf.org>
+# Copyright (c) 2009 Horst Knorr <hk_classes@knoda.org>
+# Copyright (c) 2013 Daniel Mullner <muellner@math.stanford.edu>
+#
+# This program 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 3 of the License, or (at your
+# option) any later version.
+#
+# This program 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, see <http://www.gnu.org/licenses/>.
+#
+# As a special exception, the respective Autoconf Macro's copyright owner
+# gives unlimited permission to copy, distribute and modify the configure
+# scripts that are the output of Autoconf when processing the Macro. You
+# need not follow the terms of the GNU General Public License when using
+# or distributing such scripts, even though portions of the text of the
+# Macro appear in them. The GNU General Public License (GPL) does govern
+# all other use of the material that constitutes the Autoconf Macro.
+#
+# This special exception to the GPL applies to versions of the Autoconf
+# Macro released by the Autoconf Archive. When you make and distribute a
+# modified version of the Autoconf Macro, you may extend this special
+# exception to the GPL to apply to your modified version as well.
+
+#serial 17
+
+AU_ALIAS([AC_PYTHON_DEVEL], [AX_PYTHON_DEVEL])
+AC_DEFUN([AX_PYTHON_DEVEL],[
+ #
+ # Allow the use of a (user set) custom python version
+ #
+ AC_ARG_VAR([PYTHON_VERSION],[The installed Python
+ version to use, for example '2.3'. This string
+ will be appended to the Python interpreter
+ canonical name.])
+
+ AC_PATH_PROG([PYTHON],[python[$PYTHON_VERSION]])
+ if test -z "$PYTHON"; then
+ AC_MSG_ERROR([Cannot find python$PYTHON_VERSION in your system path])
+ PYTHON_VERSION=""
+ fi
+
+ #
+ # Check for a version of Python >= 2.1.0
+ #
+ AC_MSG_CHECKING([for a version of Python >= '2.1.0'])
+ ac_supports_python_ver=`$PYTHON -c "import sys; \
+ ver = sys.version.split ()[[0]]; \
+ print (ver >= '2.1.0')"`
+ if test "$ac_supports_python_ver" != "True"; then
+ if test -z "$PYTHON_NOVERSIONCHECK"; then
+ AC_MSG_RESULT([no])
+ AC_MSG_FAILURE([
+This version of the AC@&t@_PYTHON_DEVEL macro
+doesn't work properly with versions of Python before
+2.1.0. You may need to re-run configure, setting the
+variables PYTHON_CPPFLAGS, PYTHON_LDFLAGS, PYTHON_SITE_PKG,
+PYTHON_EXTRA_LIBS and PYTHON_EXTRA_LDFLAGS by hand.
+Moreover, to disable this check, set PYTHON_NOVERSIONCHECK
+to something else than an empty string.
+])
+ else
+ AC_MSG_RESULT([skip at user request])
+ fi
+ else
+ AC_MSG_RESULT([yes])
+ fi
+
+ #
+ # if the macro parameter ``version'' is set, honour it
+ #
+ if test -n "$1"; then
+ AC_MSG_CHECKING([for a version of Python $1])
+ ac_supports_python_ver=`$PYTHON -c "import sys; \
+ ver = sys.version.split ()[[0]]; \
+ print (ver $1)"`
+ if test "$ac_supports_python_ver" = "True"; then
+ AC_MSG_RESULT([yes])
+ else
+ AC_MSG_RESULT([no])
+ AC_MSG_ERROR([this package requires Python $1.
+If you have it installed, but it isn't the default Python
+interpreter in your system path, please pass the PYTHON_VERSION
+variable to configure. See ``configure --help'' for reference.
+])
+ PYTHON_VERSION=""
+ fi
+ fi
+
+ #
+ # Check if you have distutils, else fail
+ #
+ AC_MSG_CHECKING([for the distutils Python package])
+ ac_distutils_result=`$PYTHON -c "import distutils" 2>&1`
+ if test -z "$ac_distutils_result"; then
+ AC_MSG_RESULT([yes])
+ else
+ AC_MSG_RESULT([no])
+ AC_MSG_ERROR([cannot import Python module "distutils".
+Please check your Python installation. The error was:
+$ac_distutils_result])
+ PYTHON_VERSION=""
+ fi
+
+ #
+ # Check for Python include path
+ #
+ AC_MSG_CHECKING([for Python include path])
+ if test -z "$PYTHON_CPPFLAGS"; then
+ python_path=`$PYTHON -c "import distutils.sysconfig; \
+ print (distutils.sysconfig.get_python_inc ());"`
+ plat_python_path=`$PYTHON -c "import distutils.sysconfig; \
+ print (distutils.sysconfig.get_python_inc (plat_specific=1));"`
+ if test -n "${python_path}"; then
+ if test "${plat_python_path}" != "${python_path}"; then
+ python_path="-I$python_path -I$plat_python_path"
+ else
+ python_path="-I$python_path"
+ fi
+ fi
+ PYTHON_CPPFLAGS=$python_path
+ fi
+ AC_MSG_RESULT([$PYTHON_CPPFLAGS])
+ AC_SUBST([PYTHON_CPPFLAGS])
+
+ #
+ # Check for Python library path
+ #
+ AC_MSG_CHECKING([for Python library path])
+ if test -z "$PYTHON_LDFLAGS"; then
+ # (makes two attempts to ensure we've got a version number
+ # from the interpreter)
+ ac_python_version=`cat<<EOD | $PYTHON -
+
+# join all versioning strings, on some systems
+# major/minor numbers could be in different list elements
+from distutils.sysconfig import *
+e = get_config_var('VERSION')
+if e is not None:
+ print(e)
+EOD`
+
+ if test -z "$ac_python_version"; then
+ if test -n "$PYTHON_VERSION"; then
+ ac_python_version=$PYTHON_VERSION
+ else
+ ac_python_version=`$PYTHON -c "import sys; \
+ print (sys.version[[:3]])"`
+ fi
+ fi
+
+ # Make the versioning information available to the compiler
+ AC_DEFINE_UNQUOTED([HAVE_PYTHON], ["$ac_python_version"],
+ [If available, contains the Python version number currently in use.])
+
+ # First, the library directory:
+ ac_python_libdir=`cat<<EOD | $PYTHON -
+
+# There should be only one
+import distutils.sysconfig
+e = distutils.sysconfig.get_config_var('LIBDIR')
+if e is not None:
+ print (e)
+EOD`
+
+ # Now, for the library:
+ ac_python_library=`cat<<EOD | $PYTHON -
+
+import distutils.sysconfig
+c = distutils.sysconfig.get_config_vars()
+if 'LDVERSION' in c:
+ print ('python'+c[['LDVERSION']])
+else:
+ print ('python'+c[['VERSION']])
+EOD`
+
+ # This small piece shamelessly adapted from PostgreSQL python macro;
+ # credits goes to momjian, I think. I'd like to put the right name
+ # in the credits, if someone can point me in the right direction... ?
+ #
+ if test -n "$ac_python_libdir" -a -n "$ac_python_library"
+ then
+ # use the official shared library
+ ac_python_library=`echo "$ac_python_library" | sed "s/^lib//"`
+ PYTHON_LDFLAGS="-L$ac_python_libdir -l$ac_python_library"
+ else
+ # old way: use libpython from python_configdir
+ ac_python_libdir=`$PYTHON -c \
+ "from distutils.sysconfig import get_python_lib as f; \
+ import os; \
+ print (os.path.join(f(plat_specific=1, standard_lib=1), 'config'));"`
+ PYTHON_LDFLAGS="-L$ac_python_libdir -lpython$ac_python_version"
+ fi
+
+ if test -z "PYTHON_LDFLAGS"; then
+ AC_MSG_ERROR([
+ Cannot determine location of your Python DSO. Please check it was installed with
+ dynamic libraries enabled, or try setting PYTHON_LDFLAGS by hand.
+ ])
+ fi
+ fi
+ AC_MSG_RESULT([$PYTHON_LDFLAGS])
+ AC_SUBST([PYTHON_LDFLAGS])
+
+ #
+ # Check for site packages
+ #
+ AC_MSG_CHECKING([for Python site-packages path])
+ if test -z "$PYTHON_SITE_PKG"; then
+ PYTHON_SITE_PKG=`$PYTHON -c "import distutils.sysconfig; \
+ print (distutils.sysconfig.get_python_lib(0,0));"`
+ fi
+ AC_MSG_RESULT([$PYTHON_SITE_PKG])
+ AC_SUBST([PYTHON_SITE_PKG])
+
+ #
+ # libraries which must be linked in when embedding
+ #
+ AC_MSG_CHECKING(python extra libraries)
+ if test -z "$PYTHON_EXTRA_LIBS"; then
+ PYTHON_EXTRA_LIBS=`$PYTHON -c "import distutils.sysconfig; \
+ conf = distutils.sysconfig.get_config_var; \
+ print (conf('LIBS') + ' ' + conf('SYSLIBS'))"`
+ fi
+ AC_MSG_RESULT([$PYTHON_EXTRA_LIBS])
+ AC_SUBST(PYTHON_EXTRA_LIBS)
+
+ #
+ # linking flags needed when embedding
+ #
+ AC_MSG_CHECKING(python extra linking flags)
+ if test -z "$PYTHON_EXTRA_LDFLAGS"; then
+ PYTHON_EXTRA_LDFLAGS=`$PYTHON -c "import distutils.sysconfig; \
+ conf = distutils.sysconfig.get_config_var; \
+ print (conf('LINKFORSHARED'))"`
+ fi
+ AC_MSG_RESULT([$PYTHON_EXTRA_LDFLAGS])
+ AC_SUBST(PYTHON_EXTRA_LDFLAGS)
+
+ #
+ # final check to see if everything compiles alright
+ #
+ AC_MSG_CHECKING([consistency of all components of python development environment])
+ # save current global flags
+ ac_save_LIBS="$LIBS"
+ ac_save_CPPFLAGS="$CPPFLAGS"
+ LIBS="$ac_save_LIBS $PYTHON_LDFLAGS $PYTHON_EXTRA_LDFLAGS $PYTHON_EXTRA_LIBS"
+ CPPFLAGS="$ac_save_CPPFLAGS $PYTHON_CPPFLAGS"
+ AC_LANG_PUSH([C])
+ AC_LINK_IFELSE([
+ AC_LANG_PROGRAM([[#include <Python.h>]],
+ [[Py_Initialize();]])
+ ],[pythonexists=yes],[pythonexists=no])
+ AC_LANG_POP([C])
+ # turn back to default flags
+ CPPFLAGS="$ac_save_CPPFLAGS"
+ LIBS="$ac_save_LIBS"
+
+ AC_MSG_RESULT([$pythonexists])
+
+ if test ! "x$pythonexists" = "xyes"; then
+ AC_MSG_WARN([
+ Could not link test program to Python. Maybe the main Python library has been
+ installed in some non-standard library path. If so, pass it to configure,
+ via the LDFLAGS environment variable.
+ Example: ./configure LDFLAGS="-L/usr/non-standard-path/python/lib"
+ ============================================================================
+ You probably have to install the development version of the Python package
+ for your distribution. The exact name of this package varies among them.
+ ============================================================================
+ ])
+ PYTHON_VERSION=""
+ fi
+
+ #
+ # all done!
+ #
+])
diff --git a/m4/pkg.m4 b/m4/pkg.m4
new file mode 100644
index 0000000..c29b6c0
--- /dev/null
+++ b/m4/pkg.m4
@@ -0,0 +1,157 @@
+# pkg.m4 - Macros to locate and utilise pkg-config. -*- Autoconf -*-
+#
+# Copyright © 2004 Scott James Remnant <scott@netsplit.com>.
+#
+# This program 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.
+#
+# This program 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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+#
+# As a special exception to the GNU General Public License, if you
+# distribute this file as part of a program that contains a
+# configuration script generated by Autoconf, you may include it under
+# the same distribution terms that you use for the rest of that program.
+
+# PKG_PROG_PKG_CONFIG([MIN-VERSION])
+# ----------------------------------
+AC_DEFUN([PKG_PROG_PKG_CONFIG],
+[m4_pattern_forbid([^_?PKG_[A-Z_]+$])
+m4_pattern_allow([^PKG_CONFIG(_PATH)?$])
+AC_ARG_VAR([PKG_CONFIG], [path to pkg-config utility])dnl
+if test "x$ac_cv_env_PKG_CONFIG_set" != "xset"; then
+ AC_PATH_TOOL([PKG_CONFIG], [pkg-config])
+fi
+if test -n "$PKG_CONFIG"; then
+ _pkg_min_version=m4_default([$1], [0.9.0])
+ AC_MSG_CHECKING([pkg-config is at least version $_pkg_min_version])
+ if $PKG_CONFIG --atleast-pkgconfig-version $_pkg_min_version; then
+ AC_MSG_RESULT([yes])
+ else
+ AC_MSG_RESULT([no])
+ PKG_CONFIG=""
+ fi
+
+fi[]dnl
+])# PKG_PROG_PKG_CONFIG
+
+# PKG_CHECK_EXISTS(MODULES, [ACTION-IF-FOUND], [ACTION-IF-NOT-FOUND])
+#
+# Check to see whether a particular set of modules exists. Similar
+# to PKG_CHECK_MODULES(), but does not set variables or print errors.
+#
+#
+# Similar to PKG_CHECK_MODULES, make sure that the first instance of
+# this or PKG_CHECK_MODULES is called, or make sure to call
+# PKG_CHECK_EXISTS manually
+# --------------------------------------------------------------
+AC_DEFUN([PKG_CHECK_EXISTS],
+[AC_REQUIRE([PKG_PROG_PKG_CONFIG])dnl
+if test -n "$PKG_CONFIG" && \
+ AC_RUN_LOG([$PKG_CONFIG --exists --print-errors "$1"]); then
+ m4_ifval([$2], [$2], [:])
+m4_ifvaln([$3], [else
+ $3])dnl
+fi])
+
+
+# _PKG_CONFIG([VARIABLE], [COMMAND], [MODULES])
+# ---------------------------------------------
+m4_define([_PKG_CONFIG],
+[if test -n "$PKG_CONFIG"; then
+ if test -n "$$1"; then
+ pkg_cv_[]$1="$$1"
+ else
+ PKG_CHECK_EXISTS([$3],
+ [pkg_cv_[]$1=`$PKG_CONFIG --[]$2 "$3" 2>/dev/null`],
+ [pkg_failed=yes])
+ fi
+else
+ pkg_failed=untried
+fi[]dnl
+])# _PKG_CONFIG
+
+# _PKG_SHORT_ERRORS_SUPPORTED
+# -----------------------------
+AC_DEFUN([_PKG_SHORT_ERRORS_SUPPORTED],
+[AC_REQUIRE([PKG_PROG_PKG_CONFIG])
+if $PKG_CONFIG --atleast-pkgconfig-version 0.20; then
+ _pkg_short_errors_supported=yes
+else
+ _pkg_short_errors_supported=no
+fi[]dnl
+])# _PKG_SHORT_ERRORS_SUPPORTED
+
+
+# PKG_CHECK_MODULES(VARIABLE-PREFIX, MODULES, [ACTION-IF-FOUND],
+# [ACTION-IF-NOT-FOUND])
+#
+#
+# Note that if there is a possibility the first call to
+# PKG_CHECK_MODULES might not happen, you should be sure to include an
+# explicit call to PKG_PROG_PKG_CONFIG in your configure.ac
+#
+#
+# --------------------------------------------------------------
+AC_DEFUN([PKG_CHECK_MODULES],
+[AC_REQUIRE([PKG_PROG_PKG_CONFIG])dnl
+AC_ARG_VAR([$1][_CFLAGS], [C compiler flags for $1, overriding pkg-config])dnl
+AC_ARG_VAR([$1][_LIBS], [linker flags for $1, overriding pkg-config])dnl
+
+pkg_failed=no
+AC_MSG_CHECKING([for $1])
+
+_PKG_CONFIG([$1][_CFLAGS], [cflags], [$2])
+_PKG_CONFIG([$1][_LIBS], [libs], [$2])
+
+m4_define([_PKG_TEXT], [Alternatively, you may set the environment variables $1[]_CFLAGS
+and $1[]_LIBS to avoid the need to call pkg-config.
+See the pkg-config man page for more details.])
+
+if test $pkg_failed = yes; then
+ _PKG_SHORT_ERRORS_SUPPORTED
+ if test $_pkg_short_errors_supported = yes; then
+ $1[]_PKG_ERRORS=`$PKG_CONFIG --short-errors --errors-to-stdout --print-errors "$2"`
+ else
+ $1[]_PKG_ERRORS=`$PKG_CONFIG --errors-to-stdout --print-errors "$2"`
+ fi
+ # Put the nasty error message in config.log where it belongs
+ echo "$$1[]_PKG_ERRORS" >&AS_MESSAGE_LOG_FD
+
+ ifelse([$4], , [AC_MSG_ERROR(dnl
+[Package requirements ($2) were not met:
+
+$$1_PKG_ERRORS
+
+Consider adjusting the PKG_CONFIG_PATH environment variable if you
+installed software in a non-standard prefix.
+
+_PKG_TEXT
+])],
+ [AC_MSG_RESULT([no])
+ $4])
+elif test $pkg_failed = untried; then
+ ifelse([$4], , [AC_MSG_FAILURE(dnl
+[The pkg-config script could not be found or is too old. Make sure it
+is in your PATH or set the PKG_CONFIG environment variable to the full
+path to pkg-config.
+
+_PKG_TEXT
+
+To get pkg-config, see <http://www.freedesktop.org/software/pkgconfig>.])],
+ [$4])
+else
+ $1[]_CFLAGS=$pkg_cv_[]$1[]_CFLAGS
+ $1[]_LIBS=$pkg_cv_[]$1[]_LIBS
+ AC_MSG_RESULT([yes])
+ ifelse([$3], , :, [$3])
+fi[]dnl
+])# PKG_CHECK_MODULES
diff --git a/m4/qt.m4 b/m4/qt.m4
new file mode 100644
index 0000000..e7aac41
--- /dev/null
+++ b/m4/qt.m4
@@ -0,0 +1,80 @@
+dnl qt.m4
+dnl Copyright (C) 2016 Intevation GmbH
+dnl
+dnl This file is part of gpgme and is provided under the same license as gpgme
+
+dnl Autoconf macro to find either Qt4 or Qt5
+dnl
+dnl sets GPGME_QT_LIBS and GPGME_QT_CFLAGS
+dnl
+dnl if QT5 was found have_qt5_libs is set to yes
+
+AC_DEFUN([FIND_QT],
+[
+ have_qt5_libs="no";
+
+ PKG_CHECK_MODULES(GPGME_QT,
+ Qt5Core >= 5.0.0,
+ [have_qt5_libs="yes"],
+ [have_qt5_libs="no"])
+
+ PKG_CHECK_MODULES(GPGME_QTTEST,
+ Qt5Test >= 5.0.0,
+ [have_qt5test_libs="yes"],
+ [have_qt5test_libs="no"])
+
+ if ! test "$have_w32_system" = yes; then
+ if "$PKG_CONFIG" --variable qt_config Qt5Core | grep -q "reduce_relocations"; then
+ GPGME_QT_CFLAGS="$GPGME_QT_CFLAGS -fpic"
+ fi
+ fi
+ if test "$have_qt5_libs" = "yes"; then
+ AC_CHECK_TOOL(MOC, moc)
+ AC_MSG_CHECKING([moc version])
+ mocversion=`$MOC -v 2>&1`
+ mocversiongrep=`echo $mocversion | grep "Qt 5\|moc 5"`
+ if test x"$mocversiongrep" != x"$mocversion"; then
+ AC_MSG_RESULT([no])
+ # moc was not the qt5 one, try with moc-qt5
+ AC_CHECK_TOOL(MOC2, moc-qt5)
+ mocversion=`$MOC2 -v 2>&1`
+ mocversiongrep=`echo $mocversion | grep "Qt 5\|moc-qt5 5\|moc 5"`
+ if test x"$mocversiongrep" != x"$mocversion"; then
+ AC_CHECK_TOOL(QTCHOOSER, qtchooser)
+ qt5tooldir=`QT_SELECT=qt5 qtchooser -print-env | grep QTTOOLDIR | cut -d '=' -f 2 | cut -d \" -f 2`
+ mocversion=`$qt5tooldir/moc -v 2>&1`
+ mocversiongrep=`echo $mocversion | grep "Qt 5\|moc 5"`
+ if test x"$mocversiongrep" != x"$mocversion"; then
+ # no valid moc found
+ have_qt5_libs="no";
+ else
+ MOC=$qt5tooldir/moc
+ fi
+ else
+ MOC=$MOC2
+ fi
+ fi
+ AC_MSG_RESULT([$mocversion])
+ dnl Check that a binary can actually be build with this qt.
+ dnl pkg-config may be set up in a way that it looks also for libaries
+ dnl of the build system and not only for the host system. In that case
+ dnl we check here that we can actually compile / link a qt application
+ dnl for host.
+ OLDCPPFLAGS=$CPPFLAGS
+ CPPFLAGS=$GPGME_QT_CFLAGS
+ OLDLIBS=$LIBS
+ LIBS=$GPGME_QT_LIBS
+ AC_LANG_PUSH(C++)
+ AC_MSG_CHECKING([whether a simple qt program can be built])
+ AC_LINK_IFELSE([AC_LANG_SOURCE([
+ #include <QCoreApplication>
+ int main (int argc, char **argv) {
+ QCoreApplication app(argc, argv);
+ app.exec();
+ }])], [have_qt5_libs='yes'], [have_qt5_libs='no'])
+ AC_MSG_RESULT([$have_qt5_libs])
+ AC_LANG_POP()
+ CPPFLAGS=$OLDCPPFLAGS
+ LIBS=$OLDLIBS
+ fi
+])
diff --git a/src/Makefile.am b/src/Makefile.am
index 58922f9..f166f3b 100644
--- a/src/Makefile.am
+++ b/src/Makefile.am
@@ -18,9 +18,8 @@
## Process this file with automake to produce Makefile.in
-# Note: moc_kdpipeiodevice should actually be a dependecy below.
EXTRA_DIST = gpgme-config.in gpgme.m4 libgpgme.vers ChangeLog-2011 \
- gpgme.h.in versioninfo.rc.in gpgme.def moc_kdpipeiodevice.cpp
+ gpgme.h.in versioninfo.rc.in gpgme.def
bin_SCRIPTS = gpgme-config
m4datadir = $(datadir)/aclocal
@@ -41,12 +40,6 @@ else
ltlib_gpgme_glib =
endif
-if BUILD_W32_QT
-ltlib_gpgme_qt = libgpgme-qt.la
-else
-ltlib_gpgme_qt =
-endif
-
lib_LTLIBRARIES = libgpgme.la $(ltlib_gpgme_glib) $(ltlib_gpgme_qt) \
$(ltlib_gpgme_pthread)
@@ -80,8 +73,9 @@ endif
# right linking order with libtool, as the non-installed version has
# unresolved symbols to the thread module.
main_sources = \
- util.h conversion.c get-env.c context.h ops.h \
+ util.h conversion.c b64dec.c get-env.c context.h ops.h \
parsetlv.c parsetlv.h \
+ mbox-util.c mbox-util.h \
data.h data.c data-fd.c data-stream.c data-mem.c data-user.c \
data-compat.c data-identify.c \
signers.c sig-notation.c \
@@ -89,7 +83,7 @@ main_sources = \
op-support.c \
encrypt.c encrypt-sign.c decrypt.c decrypt-verify.c verify.c \
sign.c passphrase.c progress.c \
- key.c keylist.c trust-item.c trustlist.c \
+ key.c keylist.c keysign.c trust-item.c trustlist.c tofupolicy.c \
import.c export.c genkey.c delete.c edit.c getauditlog.c \
opassuan.c passwd.c spawn.c assuan-support.c \
engine.h engine-backend.h engine.c engine-gpg.c status-table.c \
@@ -110,24 +104,11 @@ if BUILD_W32_GLIB
libgpgme_glib_la_SOURCES = $(main_sources) ath.h ath.c w32-glib-io.c
endif
-if BUILD_W32_QT
-libgpgme_qt_la_SOURCES = $(main_sources) ath.h ath.c w32-qt-io.cpp \
- kdpipeiodevice.h kdpipeiodevice.cpp kdpipeiodevice.moc
-# FIXME: Add extra depedency: moc_kdpipeiodevice.cpp
-
-# These are built sources (normally).
-# moc_kdpipeiodevice.cpp: kdpipeiodevice.h
-# $(MOC4) -o $@ $<
-#
-# kdpipeiodevice.moc: kdpipeiodevice.cpp
-# $(MOC4) -o $@ $<
-endif
-
-# We use a global CFLAGS and CPPFLAGS setting for all library
+# We use a global CFLAGS setting for all library
# versions, because then every object file is only compiled once.
-AM_CPPFLAGS = @GPG_ERROR_CFLAGS@ @QT4_CORE_CFLAGS@
-AM_CFLAGS = @LIBASSUAN_CFLAGS@ @GLIB_CFLAGS@ @QT4_CORE_CFLAGS@
+AM_CFLAGS = @LIBASSUAN_CFLAGS@ @GLIB_CFLAGS@
+gpgme_tool_SOURCES = gpgme-tool.c argparse.c argparse.h
gpgme_tool_LDADD = libgpgme.la @LIBASSUAN_LIBS@
@@ -201,15 +182,6 @@ libgpgme_glib_la_LIBADD = $(gpgme_res) @LIBASSUAN_LIBS@ @LTLIBOBJS@ \
@GPG_ERROR_LIBS@ @GLIB_LIBS@
endif
-if BUILD_W32_QT
-libgpgme_qt_la_LDFLAGS = $(no_undefined) \
- $(export_symbols) $(libgpgme_version_script_cmd) -version-info \
- @LIBGPGME_LT_CURRENT@:@LIBGPGME_LT_REVISION@:@LIBGPGME_LT_AGE@
-libgpgme_qt_la_DEPENDENCIES = @LTLIBOBJS@ $(srcdir)/libgpgme.vers $(gpgme_deps)
-libgpgme_qt_la_LIBADD = $(gpgme_res) @LIBASSUAN_LIBS@ @LTLIBOBJS@ \
- @GPG_ERROR_LIBS@ @QT4_CORE_LIBS@
-endif
-
install-data-local: install-def-file
uninstall-local: uninstall-def-file
diff --git a/src/Makefile.in b/src/Makefile.in
index ec839e4..75d7659 100644
--- a/src/Makefile.in
+++ b/src/Makefile.in
@@ -107,15 +107,19 @@ subdir = src
DIST_COMMON = $(srcdir)/Makefile.in $(srcdir)/Makefile.am \
$(top_srcdir)/build-aux/mkinstalldirs \
$(srcdir)/versioninfo.rc.in $(srcdir)/gpgme.h.in \
- $(srcdir)/gpgme-config.in stpcpy.c funopen.c vasprintf.c \
- setenv.c ttyname_r.c $(top_srcdir)/build-aux/depcomp
+ $(srcdir)/gpgme-config.in setenv.c stpcpy.c vasprintf.c \
+ ttyname_r.c funopen.c $(top_srcdir)/build-aux/depcomp
ACLOCAL_M4 = $(top_srcdir)/aclocal.m4
-am__aclocal_m4_deps = $(top_srcdir)/m4/glib-2.0.m4 \
- $(top_srcdir)/m4/glibc21.m4 $(top_srcdir)/m4/gnupg-ttyname.m4 \
+am__aclocal_m4_deps = $(top_srcdir)/m4/ax_cxx_compile_stdcxx.m4 \
+ $(top_srcdir)/m4/ax_pkg_swig.m4 \
+ $(top_srcdir)/m4/ax_python_devel.m4 \
+ $(top_srcdir)/m4/glib-2.0.m4 $(top_srcdir)/m4/glibc21.m4 \
+ $(top_srcdir)/m4/gnupg-ttyname.m4 \
$(top_srcdir)/m4/gpg-error.m4 $(top_srcdir)/m4/libassuan.m4 \
$(top_srcdir)/m4/libtool.m4 $(top_srcdir)/m4/ltoptions.m4 \
$(top_srcdir)/m4/ltsugar.m4 $(top_srcdir)/m4/ltversion.m4 \
- $(top_srcdir)/m4/lt~obsolete.m4 $(top_srcdir)/acinclude.m4 \
+ $(top_srcdir)/m4/lt~obsolete.m4 $(top_srcdir)/m4/pkg.m4 \
+ $(top_srcdir)/m4/qt.m4 $(top_srcdir)/acinclude.m4 \
$(top_srcdir)/configure.ac
am__configure_deps = $(am__aclocal_m4_deps) $(CONFIGURE_DEPENDENCIES) \
$(ACLOCAL_M4)
@@ -155,16 +159,17 @@ am__installdirs = "$(DESTDIR)$(libdir)" "$(DESTDIR)$(bindir)" \
"$(DESTDIR)$(m4datadir)" "$(DESTDIR)$(includedir)"
LTLIBRARIES = $(lib_LTLIBRARIES)
@HAVE_W32_SYSTEM_TRUE@am__DEPENDENCIES_1 = versioninfo.lo
-am__libgpgme_glib_la_SOURCES_DIST = util.h conversion.c get-env.c \
- context.h ops.h parsetlv.c parsetlv.h data.h data.c data-fd.c \
- data-stream.c data-mem.c data-user.c data-compat.c \
- data-identify.c signers.c sig-notation.c wait.c wait-global.c \
- wait-private.c wait-user.c wait.h op-support.c encrypt.c \
- encrypt-sign.c decrypt.c decrypt-verify.c verify.c sign.c \
- passphrase.c progress.c key.c keylist.c trust-item.c \
- trustlist.c import.c export.c genkey.c delete.c edit.c \
- getauditlog.c opassuan.c passwd.c spawn.c assuan-support.c \
- engine.h engine-backend.h engine.c engine-gpg.c status-table.c \
+am__libgpgme_glib_la_SOURCES_DIST = util.h conversion.c b64dec.c \
+ get-env.c context.h ops.h parsetlv.c parsetlv.h mbox-util.c \
+ mbox-util.h data.h data.c data-fd.c data-stream.c data-mem.c \
+ data-user.c data-compat.c data-identify.c signers.c \
+ sig-notation.c wait.c wait-global.c wait-private.c wait-user.c \
+ wait.h op-support.c encrypt.c encrypt-sign.c decrypt.c \
+ decrypt-verify.c verify.c sign.c passphrase.c progress.c key.c \
+ keylist.c keysign.c trust-item.c trustlist.c tofupolicy.c \
+ import.c export.c genkey.c delete.c edit.c getauditlog.c \
+ opassuan.c passwd.c spawn.c assuan-support.c engine.h \
+ engine-backend.h engine.c engine-gpg.c status-table.c \
engine-gpgsm.c engine-assuan.c engine-gpgconf.c \
engine-uiserver.c engine-g13.c vfs-mount.c vfs-create.c \
engine-spawn.c gpgconf.c sema.h priv-io.h ath.h posix-util.c \
@@ -177,16 +182,17 @@ am__libgpgme_glib_la_SOURCES_DIST = util.h conversion.c get-env.c \
@HAVE_DOSISH_SYSTEM_FALSE@ posix-io.lo $(am__objects_2)
@HAVE_DOSISH_SYSTEM_TRUE@am__objects_3 = w32-util.lo w32-sema.lo \
@HAVE_DOSISH_SYSTEM_TRUE@ $(am__objects_2)
-am__objects_4 = conversion.lo get-env.lo parsetlv.lo data.lo \
- data-fd.lo data-stream.lo data-mem.lo data-user.lo \
- data-compat.lo data-identify.lo signers.lo sig-notation.lo \
- wait.lo wait-global.lo wait-private.lo wait-user.lo \
- op-support.lo encrypt.lo encrypt-sign.lo decrypt.lo \
- decrypt-verify.lo verify.lo sign.lo passphrase.lo progress.lo \
- key.lo keylist.lo trust-item.lo trustlist.lo import.lo \
- export.lo genkey.lo delete.lo edit.lo getauditlog.lo \
- opassuan.lo passwd.lo spawn.lo assuan-support.lo engine.lo \
- engine-gpg.lo status-table.lo engine-gpgsm.lo engine-assuan.lo \
+am__objects_4 = conversion.lo b64dec.lo get-env.lo parsetlv.lo \
+ mbox-util.lo data.lo data-fd.lo data-stream.lo data-mem.lo \
+ data-user.lo data-compat.lo data-identify.lo signers.lo \
+ sig-notation.lo wait.lo wait-global.lo wait-private.lo \
+ wait-user.lo op-support.lo encrypt.lo encrypt-sign.lo \
+ decrypt.lo decrypt-verify.lo verify.lo sign.lo passphrase.lo \
+ progress.lo key.lo keylist.lo keysign.lo trust-item.lo \
+ trustlist.lo tofupolicy.lo import.lo export.lo genkey.lo \
+ delete.lo edit.lo getauditlog.lo opassuan.lo passwd.lo \
+ spawn.lo assuan-support.lo engine.lo engine-gpg.lo \
+ status-table.lo engine-gpgsm.lo engine-assuan.lo \
engine-gpgconf.lo $(am__objects_1) engine-g13.lo vfs-mount.lo \
vfs-create.lo engine-spawn.lo gpgconf.lo $(am__objects_3) \
dirinfo.lo debug.lo gpgme.lo version.lo error.lo
@@ -202,16 +208,17 @@ libgpgme_glib_la_LINK = $(LIBTOOL) $(AM_V_lt) --tag=CC \
$(AM_CFLAGS) $(CFLAGS) $(libgpgme_glib_la_LDFLAGS) $(LDFLAGS) \
-o $@
@BUILD_W32_GLIB_TRUE@am_libgpgme_glib_la_rpath = -rpath $(libdir)
-am__libgpgme_pthread_la_SOURCES_DIST = util.h conversion.c get-env.c \
- context.h ops.h parsetlv.c parsetlv.h data.h data.c data-fd.c \
- data-stream.c data-mem.c data-user.c data-compat.c \
- data-identify.c signers.c sig-notation.c wait.c wait-global.c \
- wait-private.c wait-user.c wait.h op-support.c encrypt.c \
- encrypt-sign.c decrypt.c decrypt-verify.c verify.c sign.c \
- passphrase.c progress.c key.c keylist.c trust-item.c \
- trustlist.c import.c export.c genkey.c delete.c edit.c \
- getauditlog.c opassuan.c passwd.c spawn.c assuan-support.c \
- engine.h engine-backend.h engine.c engine-gpg.c status-table.c \
+am__libgpgme_pthread_la_SOURCES_DIST = util.h conversion.c b64dec.c \
+ get-env.c context.h ops.h parsetlv.c parsetlv.h mbox-util.c \
+ mbox-util.h data.h data.c data-fd.c data-stream.c data-mem.c \
+ data-user.c data-compat.c data-identify.c signers.c \
+ sig-notation.c wait.c wait-global.c wait-private.c wait-user.c \
+ wait.h op-support.c encrypt.c encrypt-sign.c decrypt.c \
+ decrypt-verify.c verify.c sign.c passphrase.c progress.c key.c \
+ keylist.c keysign.c trust-item.c trustlist.c tofupolicy.c \
+ import.c export.c genkey.c delete.c edit.c getauditlog.c \
+ opassuan.c passwd.c spawn.c assuan-support.c engine.h \
+ engine-backend.h engine.c engine-gpg.c status-table.c \
engine-gpgsm.c engine-assuan.c engine-gpgconf.c \
engine-uiserver.c engine-g13.c vfs-mount.c vfs-create.c \
engine-spawn.c gpgconf.c sema.h priv-io.h ath.h posix-util.c \
@@ -227,55 +234,30 @@ libgpgme_pthread_la_LINK = $(LIBTOOL) $(AM_V_lt) --tag=CC \
$(AM_CFLAGS) $(CFLAGS) $(libgpgme_pthread_la_LDFLAGS) \
$(LDFLAGS) -o $@
@HAVE_PTHREAD_TRUE@am_libgpgme_pthread_la_rpath = -rpath $(libdir)
-am__libgpgme_qt_la_SOURCES_DIST = util.h conversion.c get-env.c \
- context.h ops.h parsetlv.c parsetlv.h data.h data.c data-fd.c \
- data-stream.c data-mem.c data-user.c data-compat.c \
- data-identify.c signers.c sig-notation.c wait.c wait-global.c \
- wait-private.c wait-user.c wait.h op-support.c encrypt.c \
- encrypt-sign.c decrypt.c decrypt-verify.c verify.c sign.c \
- passphrase.c progress.c key.c keylist.c trust-item.c \
- trustlist.c import.c export.c genkey.c delete.c edit.c \
- getauditlog.c opassuan.c passwd.c spawn.c assuan-support.c \
- engine.h engine-backend.h engine.c engine-gpg.c status-table.c \
- engine-gpgsm.c engine-assuan.c engine-gpgconf.c \
- engine-uiserver.c engine-g13.c vfs-mount.c vfs-create.c \
- engine-spawn.c gpgconf.c sema.h priv-io.h ath.h posix-util.c \
- posix-sema.c posix-io.c w32-ce.h w32-ce.c w32-util.c \
- w32-sema.c sys-util.h dirinfo.c debug.c debug.h gpgme.c \
- version.c error.c ath.c w32-qt-io.cpp kdpipeiodevice.h \
- kdpipeiodevice.cpp kdpipeiodevice.moc
-@BUILD_W32_QT_TRUE@am_libgpgme_qt_la_OBJECTS = $(am__objects_4) ath.lo \
-@BUILD_W32_QT_TRUE@ w32-qt-io.lo kdpipeiodevice.lo
-libgpgme_qt_la_OBJECTS = $(am_libgpgme_qt_la_OBJECTS)
-libgpgme_qt_la_LINK = $(LIBTOOL) $(AM_V_lt) --tag=CXX \
- $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=link $(CXXLD) \
- $(AM_CXXFLAGS) $(CXXFLAGS) $(libgpgme_qt_la_LDFLAGS) \
- $(LDFLAGS) -o $@
-@BUILD_W32_QT_TRUE@am_libgpgme_qt_la_rpath = -rpath $(libdir)
-am__libgpgme_la_SOURCES_DIST = util.h conversion.c get-env.c context.h \
- ops.h parsetlv.c parsetlv.h data.h data.c data-fd.c \
- data-stream.c data-mem.c data-user.c data-compat.c \
- data-identify.c signers.c sig-notation.c wait.c wait-global.c \
- wait-private.c wait-user.c wait.h op-support.c encrypt.c \
- encrypt-sign.c decrypt.c decrypt-verify.c verify.c sign.c \
- passphrase.c progress.c key.c keylist.c trust-item.c \
- trustlist.c import.c export.c genkey.c delete.c edit.c \
- getauditlog.c opassuan.c passwd.c spawn.c assuan-support.c \
- engine.h engine-backend.h engine.c engine-gpg.c status-table.c \
- engine-gpgsm.c engine-assuan.c engine-gpgconf.c \
- engine-uiserver.c engine-g13.c vfs-mount.c vfs-create.c \
- engine-spawn.c gpgconf.c sema.h priv-io.h ath.h posix-util.c \
- posix-sema.c posix-io.c w32-ce.h w32-ce.c w32-util.c \
- w32-sema.c sys-util.h dirinfo.c debug.c debug.h gpgme.c \
- version.c error.c ath.c w32-io.c
+am__libgpgme_la_SOURCES_DIST = util.h conversion.c b64dec.c get-env.c \
+ context.h ops.h parsetlv.c parsetlv.h mbox-util.c mbox-util.h \
+ data.h data.c data-fd.c data-stream.c data-mem.c data-user.c \
+ data-compat.c data-identify.c signers.c sig-notation.c wait.c \
+ wait-global.c wait-private.c wait-user.c wait.h op-support.c \
+ encrypt.c encrypt-sign.c decrypt.c decrypt-verify.c verify.c \
+ sign.c passphrase.c progress.c key.c keylist.c keysign.c \
+ trust-item.c trustlist.c tofupolicy.c import.c export.c \
+ genkey.c delete.c edit.c getauditlog.c opassuan.c passwd.c \
+ spawn.c assuan-support.c engine.h engine-backend.h engine.c \
+ engine-gpg.c status-table.c engine-gpgsm.c engine-assuan.c \
+ engine-gpgconf.c engine-uiserver.c engine-g13.c vfs-mount.c \
+ vfs-create.c engine-spawn.c gpgconf.c sema.h priv-io.h ath.h \
+ posix-util.c posix-sema.c posix-io.c w32-ce.h w32-ce.c \
+ w32-util.c w32-sema.c sys-util.h dirinfo.c debug.c debug.h \
+ gpgme.c version.c error.c ath.c w32-io.c
am_libgpgme_la_OBJECTS = $(am__objects_4) ath.lo $(am__objects_5)
libgpgme_la_OBJECTS = $(am_libgpgme_la_OBJECTS)
libgpgme_la_LINK = $(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) \
$(LIBTOOLFLAGS) --mode=link $(CCLD) $(AM_CFLAGS) $(CFLAGS) \
$(libgpgme_la_LDFLAGS) $(LDFLAGS) -o $@
PROGRAMS = $(bin_PROGRAMS) $(libexec_PROGRAMS)
-gpgme_tool_SOURCES = gpgme-tool.c
-gpgme_tool_OBJECTS = gpgme-tool.$(OBJEXT)
+am_gpgme_tool_OBJECTS = gpgme-tool.$(OBJEXT) argparse.$(OBJEXT)
+gpgme_tool_OBJECTS = $(am_gpgme_tool_OBJECTS)
gpgme_tool_DEPENDENCIES = libgpgme.la
gpgme_w32spawn_SOURCES = gpgme-w32spawn.c
gpgme_w32spawn_OBJECTS = gpgme-w32spawn.$(OBJEXT)
@@ -315,31 +297,12 @@ 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 =
-CXXCOMPILE = $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) \
- $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS)
-LTCXXCOMPILE = $(LIBTOOL) $(AM_V_lt) --tag=CXX $(AM_LIBTOOLFLAGS) \
- $(LIBTOOLFLAGS) --mode=compile $(CXX) $(DEFS) \
- $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) \
- $(AM_CXXFLAGS) $(CXXFLAGS)
-AM_V_CXX = $(am__v_CXX_@AM_V@)
-am__v_CXX_ = $(am__v_CXX_@AM_DEFAULT_V@)
-am__v_CXX_0 = @echo " CXX " $@;
-am__v_CXX_1 =
-CXXLD = $(CXX)
-CXXLINK = $(LIBTOOL) $(AM_V_lt) --tag=CXX $(AM_LIBTOOLFLAGS) \
- $(LIBTOOLFLAGS) --mode=link $(CXXLD) $(AM_CXXFLAGS) \
- $(CXXFLAGS) $(AM_LDFLAGS) $(LDFLAGS) -o $@
-AM_V_CXXLD = $(am__v_CXXLD_@AM_V@)
-am__v_CXXLD_ = $(am__v_CXXLD_@AM_DEFAULT_V@)
-am__v_CXXLD_0 = @echo " CXXLD " $@;
-am__v_CXXLD_1 =
SOURCES = $(libgpgme_glib_la_SOURCES) $(libgpgme_pthread_la_SOURCES) \
- $(libgpgme_qt_la_SOURCES) $(libgpgme_la_SOURCES) gpgme-tool.c \
- gpgme-w32spawn.c
+ $(libgpgme_la_SOURCES) $(gpgme_tool_SOURCES) gpgme-w32spawn.c
DIST_SOURCES = $(am__libgpgme_glib_la_SOURCES_DIST) \
$(am__libgpgme_pthread_la_SOURCES_DIST) \
- $(am__libgpgme_qt_la_SOURCES_DIST) \
- $(am__libgpgme_la_SOURCES_DIST) gpgme-tool.c gpgme-w32spawn.c
+ $(am__libgpgme_la_SOURCES_DIST) $(gpgme_tool_SOURCES) \
+ gpgme-w32spawn.c
am__can_run_installinfo = \
case $$AM_UPDATE_INFO_DIR in \
n|no|NO) false;; \
@@ -381,6 +344,7 @@ BUILD_REVISION = @BUILD_REVISION@
BUILD_TIMESTAMP = @BUILD_TIMESTAMP@
CC = @CC@
CCDEPMODE = @CCDEPMODE@
+CC_FOR_BUILD = @CC_FOR_BUILD@
CFLAGS = @CFLAGS@
CPP = @CPP@
CPPFLAGS = @CPPFLAGS@
@@ -392,12 +356,14 @@ CYGPATH_W = @CYGPATH_W@
DEFS = @DEFS@
DEPDIR = @DEPDIR@
DLLTOOL = @DLLTOOL@
+DOXYGEN = @DOXYGEN@
DSYMUTIL = @DSYMUTIL@
DUMPBIN = @DUMPBIN@
ECHO_C = @ECHO_C@
ECHO_N = @ECHO_N@
ECHO_T = @ECHO_T@
EGREP = @EGREP@
+ENABLED_LANGUAGES = @ENABLED_LANGUAGES@
EXEEXT = @EXEEXT@
FGREP = @FGREP@
GITLOG_TO_CHANGELOG = @GITLOG_TO_CHANGELOG@
@@ -408,15 +374,23 @@ GLIB_LIBS = @GLIB_LIBS@
GLIB_MKENUMS = @GLIB_MKENUMS@
GOBJECT_QUERY = @GOBJECT_QUERY@
GPGME_CONFIG_API_VERSION = @GPGME_CONFIG_API_VERSION@
+GPGME_CONFIG_AVAIL_LANG = @GPGME_CONFIG_AVAIL_LANG@
GPGME_CONFIG_CFLAGS = @GPGME_CONFIG_CFLAGS@
GPGME_CONFIG_HOST = @GPGME_CONFIG_HOST@
GPGME_CONFIG_LIBS = @GPGME_CONFIG_LIBS@
+GPGME_QTTEST_CFLAGS = @GPGME_QTTEST_CFLAGS@
+GPGME_QTTEST_LIBS = @GPGME_QTTEST_LIBS@
+GPGME_QT_CFLAGS = @GPGME_QT_CFLAGS@
+GPGME_QT_LIBS = @GPGME_QT_LIBS@
GPG_ERROR_CFLAGS = @GPG_ERROR_CFLAGS@
GPG_ERROR_CONFIG = @GPG_ERROR_CONFIG@
GPG_ERROR_LIBS = @GPG_ERROR_LIBS@
GPG_ERROR_MT_CFLAGS = @GPG_ERROR_MT_CFLAGS@
GPG_ERROR_MT_LIBS = @GPG_ERROR_MT_LIBS@
+GRAPHVIZ = @GRAPHVIZ@
GREP = @GREP@
+HAVE_CXX11 = @HAVE_CXX11@
+HAVE_DOT = @HAVE_DOT@
INSTALL = @INSTALL@
INSTALL_DATA = @INSTALL_DATA@
INSTALL_PROGRAM = @INSTALL_PROGRAM@
@@ -427,10 +401,16 @@ LDFLAGS = @LDFLAGS@
LIBASSUAN_CFLAGS = @LIBASSUAN_CFLAGS@
LIBASSUAN_CONFIG = @LIBASSUAN_CONFIG@
LIBASSUAN_LIBS = @LIBASSUAN_LIBS@
+LIBGPGMEPP_LT_AGE = @LIBGPGMEPP_LT_AGE@
+LIBGPGMEPP_LT_CURRENT = @LIBGPGMEPP_LT_CURRENT@
+LIBGPGMEPP_LT_REVISION = @LIBGPGMEPP_LT_REVISION@
LIBGPGME_LT_AGE = @LIBGPGME_LT_AGE@
LIBGPGME_LT_CURRENT = @LIBGPGME_LT_CURRENT@
LIBGPGME_LT_REVISION = @LIBGPGME_LT_REVISION@
LIBOBJS = @LIBOBJS@
+LIBQGPGME_LT_AGE = @LIBQGPGME_LT_AGE@
+LIBQGPGME_LT_CURRENT = @LIBQGPGME_LT_CURRENT@
+LIBQGPGME_LT_REVISION = @LIBQGPGME_LT_REVISION@
LIBS = @LIBS@
LIBTOOL = @LIBTOOL@
LIPO = @LIPO@
@@ -440,6 +420,8 @@ MAINT = @MAINT@
MAKEINFO = @MAKEINFO@
MANIFEST_TOOL = @MANIFEST_TOOL@
MKDIR_P = @MKDIR_P@
+MOC = @MOC@
+MOC2 = @MOC2@
NEED__FILE_OFFSET_BITS = @NEED__FILE_OFFSET_BITS@
NM = @NM@
NMEDIT = @NMEDIT@
@@ -456,14 +438,27 @@ PACKAGE_URL = @PACKAGE_URL@
PACKAGE_VERSION = @PACKAGE_VERSION@
PATH_SEPARATOR = @PATH_SEPARATOR@
PKG_CONFIG = @PKG_CONFIG@
-QT4_CORE_CFLAGS = @QT4_CORE_CFLAGS@
-QT4_CORE_LIBS = @QT4_CORE_LIBS@
+PYTHON = @PYTHON@
+PYTHONS = @PYTHONS@
+PYTHON_CPPFLAGS = @PYTHON_CPPFLAGS@
+PYTHON_EXEC_PREFIX = @PYTHON_EXEC_PREFIX@
+PYTHON_EXTRA_LDFLAGS = @PYTHON_EXTRA_LDFLAGS@
+PYTHON_EXTRA_LIBS = @PYTHON_EXTRA_LIBS@
+PYTHON_LDFLAGS = @PYTHON_LDFLAGS@
+PYTHON_PLATFORM = @PYTHON_PLATFORM@
+PYTHON_PREFIX = @PYTHON_PREFIX@
+PYTHON_SITE_PKG = @PYTHON_SITE_PKG@
+PYTHON_VERSION = @PYTHON_VERSION@
+PYTHON_VERSIONS = @PYTHON_VERSIONS@
+QTCHOOSER = @QTCHOOSER@
RANLIB = @RANLIB@
RC = @RC@
SED = @SED@
SET_MAKE = @SET_MAKE@
SHELL = @SHELL@
STRIP = @STRIP@
+SWIG = @SWIG@
+SWIG_LIB = @SWIG_LIB@
SYSROOT = @SYSROOT@
VERSION = @VERSION@
VERSION_NUMBER = @VERSION_NUMBER@
@@ -512,9 +507,13 @@ mandir = @mandir@
mkdir_p = @mkdir_p@
oldincludedir = @oldincludedir@
pdfdir = @pdfdir@
+pkgpyexecdir = @pkgpyexecdir@
+pkgpythondir = @pkgpythondir@
prefix = @prefix@
program_transform_name = @program_transform_name@
psdir = @psdir@
+pyexecdir = @pyexecdir@
+pythondir = @pythondir@
sbindir = @sbindir@
sharedstatedir = @sharedstatedir@
srcdir = @srcdir@
@@ -523,10 +522,8 @@ target_alias = @target_alias@
top_build_prefix = @top_build_prefix@
top_builddir = @top_builddir@
top_srcdir = @top_srcdir@
-
-# Note: moc_kdpipeiodevice should actually be a dependecy below.
EXTRA_DIST = gpgme-config.in gpgme.m4 libgpgme.vers ChangeLog-2011 \
- gpgme.h.in versioninfo.rc.in gpgme.def moc_kdpipeiodevice.cpp
+ gpgme.h.in versioninfo.rc.in gpgme.def
bin_SCRIPTS = gpgme-config
m4datadir = $(datadir)/aclocal
@@ -536,8 +533,6 @@ nodist_include_HEADERS = gpgme.h
@HAVE_PTHREAD_TRUE@ltlib_gpgme_pthread = libgpgme-pthread.la
@BUILD_W32_GLIB_FALSE@ltlib_gpgme_glib =
@BUILD_W32_GLIB_TRUE@ltlib_gpgme_glib = libgpgme-glib.la
-@BUILD_W32_QT_FALSE@ltlib_gpgme_qt =
-@BUILD_W32_QT_TRUE@ltlib_gpgme_qt = libgpgme-qt.la
lib_LTLIBRARIES = libgpgme.la $(ltlib_gpgme_glib) $(ltlib_gpgme_qt) \
$(ltlib_gpgme_pthread)
@@ -559,8 +554,9 @@ lib_LTLIBRARIES = libgpgme.la $(ltlib_gpgme_glib) $(ltlib_gpgme_qt) \
# right linking order with libtool, as the non-installed version has
# unresolved symbols to the thread module.
main_sources = \
- util.h conversion.c get-env.c context.h ops.h \
+ util.h conversion.c b64dec.c get-env.c context.h ops.h \
parsetlv.c parsetlv.h \
+ mbox-util.c mbox-util.h \
data.h data.c data-fd.c data-stream.c data-mem.c data-user.c \
data-compat.c data-identify.c \
signers.c sig-notation.c \
@@ -568,7 +564,7 @@ main_sources = \
op-support.c \
encrypt.c encrypt-sign.c decrypt.c decrypt-verify.c verify.c \
sign.c passphrase.c progress.c \
- key.c keylist.c trust-item.c trustlist.c \
+ key.c keylist.c keysign.c trust-item.c trustlist.c tofupolicy.c \
import.c export.c genkey.c delete.c edit.c getauditlog.c \
opassuan.c passwd.c spawn.c assuan-support.c \
engine.h engine-backend.h engine.c engine-gpg.c status-table.c \
@@ -587,22 +583,11 @@ libgpgme_pthread_la_SOURCES = $(main_sources) \
ath.h ath-pthread.c $(system_components_not_extra)
@BUILD_W32_GLIB_TRUE@libgpgme_glib_la_SOURCES = $(main_sources) ath.h ath.c w32-glib-io.c
-@BUILD_W32_QT_TRUE@libgpgme_qt_la_SOURCES = $(main_sources) ath.h ath.c w32-qt-io.cpp \
-@BUILD_W32_QT_TRUE@ kdpipeiodevice.h kdpipeiodevice.cpp kdpipeiodevice.moc
-
-# FIXME: Add extra depedency: moc_kdpipeiodevice.cpp
-# These are built sources (normally).
-# moc_kdpipeiodevice.cpp: kdpipeiodevice.h
-# $(MOC4) -o $@ $<
-#
-# kdpipeiodevice.moc: kdpipeiodevice.cpp
-# $(MOC4) -o $@ $<
-
-# We use a global CFLAGS and CPPFLAGS setting for all library
+# We use a global CFLAGS setting for all library
# versions, because then every object file is only compiled once.
-AM_CPPFLAGS = @GPG_ERROR_CFLAGS@ @QT4_CORE_CFLAGS@
-AM_CFLAGS = @LIBASSUAN_CFLAGS@ @GLIB_CFLAGS@ @QT4_CORE_CFLAGS@
+AM_CFLAGS = @LIBASSUAN_CFLAGS@ @GLIB_CFLAGS@
+gpgme_tool_SOURCES = gpgme-tool.c argparse.c argparse.h
gpgme_tool_LDADD = libgpgme.la @LIBASSUAN_LIBS@
@HAVE_W32_SYSTEM_TRUE@RCCOMPILE = $(RC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES)
@HAVE_W32_SYSTEM_TRUE@LTRCCOMPILE = $(LIBTOOL) --mode=compile --tag=RC $(RCCOMPILE)
@@ -645,18 +630,10 @@ libgpgme_pthread_la_LIBADD = $(gpgme_res) @LIBASSUAN_LIBS@ @LTLIBOBJS@ \
@BUILD_W32_GLIB_TRUE@libgpgme_glib_la_LIBADD = $(gpgme_res) @LIBASSUAN_LIBS@ @LTLIBOBJS@ \
@BUILD_W32_GLIB_TRUE@ @GPG_ERROR_LIBS@ @GLIB_LIBS@
-@BUILD_W32_QT_TRUE@libgpgme_qt_la_LDFLAGS = $(no_undefined) \
-@BUILD_W32_QT_TRUE@ $(export_symbols) $(libgpgme_version_script_cmd) -version-info \
-@BUILD_W32_QT_TRUE@ @LIBGPGME_LT_CURRENT@:@LIBGPGME_LT_REVISION@:@LIBGPGME_LT_AGE@
-
-@BUILD_W32_QT_TRUE@libgpgme_qt_la_DEPENDENCIES = @LTLIBOBJS@ $(srcdir)/libgpgme.vers $(gpgme_deps)
-@BUILD_W32_QT_TRUE@libgpgme_qt_la_LIBADD = $(gpgme_res) @LIBASSUAN_LIBS@ @LTLIBOBJS@ \
-@BUILD_W32_QT_TRUE@ @GPG_ERROR_LIBS@ @QT4_CORE_LIBS@
-
all: all-am
.SUFFIXES:
-.SUFFIXES: .rc .lo .c .cpp .o .obj
+.SUFFIXES: .rc .lo .c .o .obj
$(srcdir)/Makefile.in: @MAINTAINER_MODE_TRUE@ $(srcdir)/Makefile.am $(am__configure_deps)
@for dep in $?; do \
case '$(am__configure_deps)' in \
@@ -735,9 +712,6 @@ libgpgme-glib.la: $(libgpgme_glib_la_OBJECTS) $(libgpgme_glib_la_DEPENDENCIES) $
libgpgme-pthread.la: $(libgpgme_pthread_la_OBJECTS) $(libgpgme_pthread_la_DEPENDENCIES) $(EXTRA_libgpgme_pthread_la_DEPENDENCIES)
$(AM_V_CCLD)$(libgpgme_pthread_la_LINK) $(am_libgpgme_pthread_la_rpath) $(libgpgme_pthread_la_OBJECTS) $(libgpgme_pthread_la_LIBADD) $(LIBS)
-libgpgme-qt.la: $(libgpgme_qt_la_OBJECTS) $(libgpgme_qt_la_DEPENDENCIES) $(EXTRA_libgpgme_qt_la_DEPENDENCIES)
- $(AM_V_CXXLD)$(libgpgme_qt_la_LINK) $(am_libgpgme_qt_la_rpath) $(libgpgme_qt_la_OBJECTS) $(libgpgme_qt_la_LIBADD) $(LIBS)
-
libgpgme.la: $(libgpgme_la_OBJECTS) $(libgpgme_la_DEPENDENCIES) $(EXTRA_libgpgme_la_DEPENDENCIES)
$(AM_V_CCLD)$(libgpgme_la_LINK) -rpath $(libdir) $(libgpgme_la_OBJECTS) $(libgpgme_la_LIBADD) $(LIBS)
install-binPROGRAMS: $(bin_PROGRAMS)
@@ -893,9 +867,11 @@ distclean-compile:
@AMDEP_TRUE@@am__include@ @am__quote@$(DEPDIR)/stpcpy.Plo@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@$(DEPDIR)/ttyname_r.Plo@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@$(DEPDIR)/vasprintf.Plo@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/argparse.Po@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/assuan-support.Plo@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/ath-pthread.Plo@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/ath.Plo@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/b64dec.Plo@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/conversion.Plo@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/data-compat.Plo@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/data-fd.Plo@am__quote@
@@ -930,9 +906,10 @@ distclean-compile:
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/gpgme-w32spawn.Po@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/gpgme.Plo@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/import.Plo@am__quote@
-@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/kdpipeiodevice.Plo@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/key.Plo@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/keylist.Plo@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/keysign.Plo@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/mbox-util.Plo@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/op-support.Plo@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/opassuan.Plo@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/parsetlv.Plo@am__quote@
@@ -947,6 +924,7 @@ distclean-compile:
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/signers.Plo@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/spawn.Plo@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/status-table.Plo@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/tofupolicy.Plo@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/trust-item.Plo@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/trustlist.Plo@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/verify.Plo@am__quote@
@@ -956,7 +934,6 @@ distclean-compile:
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/w32-ce.Plo@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/w32-glib-io.Plo@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/w32-io.Plo@am__quote@
-@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/w32-qt-io.Plo@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/w32-sema.Plo@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/w32-util.Plo@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/wait-global.Plo@am__quote@
@@ -985,27 +962,6 @@ distclean-compile:
@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LTCOMPILE) -c -o $@ $<
-.cpp.o:
-@am__fastdepCXX_TRUE@ $(AM_V_CXX)$(CXXCOMPILE) -MT $@ -MD -MP -MF $(DEPDIR)/$*.Tpo -c -o $@ $<
-@am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/$*.Tpo $(DEPDIR)/$*.Po
-@AMDEP_TRUE@@am__fastdepCXX_FALSE@ $(AM_V_CXX)source='$<' object='$@' libtool=no @AMDEPBACKSLASH@
-@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@
-@am__fastdepCXX_FALSE@ $(AM_V_CXX@am__nodep@)$(CXXCOMPILE) -c -o $@ $<
-
-.cpp.obj:
-@am__fastdepCXX_TRUE@ $(AM_V_CXX)$(CXXCOMPILE) -MT $@ -MD -MP -MF $(DEPDIR)/$*.Tpo -c -o $@ `$(CYGPATH_W) '$<'`
-@am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/$*.Tpo $(DEPDIR)/$*.Po
-@AMDEP_TRUE@@am__fastdepCXX_FALSE@ $(AM_V_CXX)source='$<' object='$@' libtool=no @AMDEPBACKSLASH@
-@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@
-@am__fastdepCXX_FALSE@ $(AM_V_CXX@am__nodep@)$(CXXCOMPILE) -c -o $@ `$(CYGPATH_W) '$<'`
-
-.cpp.lo:
-@am__fastdepCXX_TRUE@ $(AM_V_CXX)$(LTCXXCOMPILE) -MT $@ -MD -MP -MF $(DEPDIR)/$*.Tpo -c -o $@ $<
-@am__fastdepCXX_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/$*.Tpo $(DEPDIR)/$*.Plo
-@AMDEP_TRUE@@am__fastdepCXX_FALSE@ $(AM_V_CXX)source='$<' object='$@' libtool=yes @AMDEPBACKSLASH@
-@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@
-@am__fastdepCXX_FALSE@ $(AM_V_CXX@am__nodep@)$(LTCXXCOMPILE) -c -o $@ $<
-
mostlyclean-libtool:
-rm -f *.lo
diff --git a/src/argparse.c b/src/argparse.c
new file mode 100644
index 0000000..003334f
--- /dev/null
+++ b/src/argparse.c
@@ -0,0 +1,1610 @@
+/* [argparse.c wk 17.06.97] Argument Parser for option handling
+ * Copyright (C) 1998-2001, 2006-2008, 2012 Free Software Foundation, Inc.
+ * Copyright (C) 1997-2001, 2006-2008, 2013-2015 Werner Koch
+ *
+ * This file is part of GnuPG.
+ *
+ * GnuPG is free software; you can redistribute it and/or modify it
+ * under the terms of either
+ *
+ * - the GNU Lesser General Public License as published by the Free
+ * Software Foundation; either version 3 of the License, or (at
+ * your option) any later version.
+ *
+ * or
+ *
+ * - 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.
+ *
+ * or both in parallel, as here.
+ *
+ * GnuPG 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 copies of the GNU General Public License
+ * and the GNU Lesser General Public License along with this program;
+ * if not, see <http://www.gnu.org/licenses/>.
+ */
+
+/* This file may be used as part of GnuPG or standalone. A GnuPG
+ build is detected by the presence of the macro GNUPG_MAJOR_VERSION.
+ Some feature are only availalbe in the GnuPG build mode.
+ */
+
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+#endif
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <ctype.h>
+#include <string.h>
+#include <stdarg.h>
+#include <limits.h>
+#include <errno.h>
+
+#ifdef GNUPG_MAJOR_VERSION
+# include "util.h"
+# include "common-defs.h"
+# include "i18n.h"
+# include "mischelp.h"
+# include "stringhelp.h"
+# include "logging.h"
+# include "utf8conv.h"
+#endif /*GNUPG_MAJOR_VERSION*/
+
+#include "argparse.h"
+
+/* GnuPG uses GPLv3+ but a standalone version of this defaults to
+ GPLv2+ because that is the license of this file. Change this if
+ you include it in a program which uses GPLv3. If you don't want to
+ set a a copyright string for your usage() you may also hardcode it
+ here. */
+#ifndef GNUPG_MAJOR_VERSION
+
+# define ARGPARSE_GPL_VERSION 2
+# define ARGPARSE_CRIGHT_STR "Copyright (C) YEAR NAME"
+
+#else /* Used by GnuPG */
+
+# define ARGPARSE_GPL_VERSION 3
+# define ARGPARSE_CRIGHT_STR "Copyright (C) 2015 Free Software Foundation, Inc."
+
+#endif /*GNUPG_MAJOR_VERSION*/
+
+/* Replacements for standalone builds. */
+#ifndef GNUPG_MAJOR_VERSION
+# ifndef _
+# define _(a) (a)
+# endif
+# ifndef DIM
+# define DIM(v) (sizeof(v)/sizeof((v)[0]))
+# endif
+# define xtrymalloc(a) malloc ((a))
+# define xtryrealloc(a,b) realloc ((a), (b))
+# define xtrystrdup(a) strdup ((a))
+# define xfree(a) free ((a))
+# define log_error my_log_error
+# define log_bug my_log_bug
+# define trim_spaces(a) my_trim_spaces ((a))
+# define map_static_macro_string(a) (a)
+#endif /*!GNUPG_MAJOR_VERSION*/
+
+
+#define ARGPARSE_STR(v) #v
+#define ARGPARSE_STR2(v) ARGPARSE_STR(v)
+
+
+/* Replacements for standalone builds. */
+#ifndef GNUPG_MAJOR_VERSION
+static void
+my_log_error (const char *fmt, ...)
+{
+ va_list arg_ptr ;
+
+ va_start (arg_ptr, fmt);
+ fprintf (stderr, "%s: ", strusage (11));
+ vfprintf (stderr, fmt, arg_ptr);
+ va_end (arg_ptr);
+}
+
+static void
+my_log_bug (const char *fmt, ...)
+{
+ va_list arg_ptr ;
+
+ va_start (arg_ptr, fmt);
+ fprintf (stderr, "%s: Ohhhh jeeee: ", strusage (11));
+ vfprintf (stderr, fmt, arg_ptr);
+ va_end (arg_ptr);
+ abort ();
+}
+
+/* Return true if the native charset is utf-8. */
+static int
+is_native_utf8 (void)
+{
+ return 1;
+}
+
+static char *
+my_trim_spaces (char *str)
+{
+ char *string, *p, *mark;
+
+ string = str;
+ /* Find first non space character. */
+ for (p=string; *p && isspace (*(unsigned char*)p) ; p++)
+ ;
+ /* Move characters. */
+ for ((mark = NULL); (*string = *p); string++, p++)
+ if (isspace (*(unsigned char*)p))
+ {
+ if (!mark)
+ mark = string;
+ }
+ else
+ mark = NULL;
+ if (mark)
+ *mark = '\0' ; /* Remove trailing spaces. */
+
+ return str ;
+}
+
+#endif /*!GNUPG_MAJOR_VERSION*/
+
+
+
+/*********************************
+ * @Summary arg_parse
+ * #include "argparse.h"
+ *
+ * typedef struct {
+ * char *argc; pointer to argc (value subject to change)
+ * char ***argv; pointer to argv (value subject to change)
+ * unsigned flags; Global flags (DO NOT CHANGE)
+ * int err; print error about last option
+ * 1 = warning, 2 = abort
+ * int r_opt; return option
+ * int r_type; type of return value (0 = no argument found)
+ * union {
+ * int ret_int;
+ * long ret_long
+ * ulong ret_ulong;
+ * char *ret_str;
+ * } r; Return values
+ * struct {
+ * int idx;
+ * const char *last;
+ * void *aliases;
+ * } internal; DO NOT CHANGE
+ * } ARGPARSE_ARGS;
+ *
+ * typedef struct {
+ * int short_opt;
+ * const char *long_opt;
+ * unsigned flags;
+ * } ARGPARSE_OPTS;
+ *
+ * int arg_parse( ARGPARSE_ARGS *arg, ARGPARSE_OPTS *opts );
+ *
+ * @Description
+ * This is my replacement for getopt(). See the example for a typical usage.
+ * Global flags are:
+ * Bit 0 : Do not remove options form argv
+ * Bit 1 : Do not stop at last option but return other args
+ * with r_opt set to -1.
+ * Bit 2 : Assume options and real args are mixed.
+ * Bit 3 : Do not use -- to stop option processing.
+ * Bit 4 : Do not skip the first arg.
+ * Bit 5 : allow usage of long option with only one dash
+ * Bit 6 : ignore --version
+ * all other bits must be set to zero, this value is modified by the
+ * function, so assume this is write only.
+ * Local flags (for each option):
+ * Bit 2-0 : 0 = does not take an argument
+ * 1 = takes int argument
+ * 2 = takes string argument
+ * 3 = takes long argument
+ * 4 = takes ulong argument
+ * Bit 3 : argument is optional (r_type will the be set to 0)
+ * Bit 4 : allow 0x etc. prefixed values.
+ * Bit 6 : Ignore this option
+ * Bit 7 : This is a command and not an option
+ * You stop the option processing by setting opts to NULL, the function will
+ * then return 0.
+ * @Return Value
+ * Returns the args.r_opt or 0 if ready
+ * r_opt may be -2/-7 to indicate an unknown option/command.
+ * @See Also
+ * ArgExpand
+ * @Notes
+ * You do not need to process the options 'h', '--help' or '--version'
+ * because this function includes standard help processing; but if you
+ * specify '-h', '--help' or '--version' you have to do it yourself.
+ * The option '--' stops argument processing; if bit 1 is set the function
+ * continues to return normal arguments.
+ * To process float args or unsigned args you must use a string args and do
+ * the conversion yourself.
+ * @Example
+ *
+ * ARGPARSE_OPTS opts[] = {
+ * { 'v', "verbose", 0 },
+ * { 'd', "debug", 0 },
+ * { 'o', "output", 2 },
+ * { 'c', "cross-ref", 2|8 },
+ * { 'm', "my-option", 1|8 },
+ * { 300, "ignored-long-option, ARGPARSE_OP_IGNORE},
+ * { 500, "have-no-short-option-for-this-long-option", 0 },
+ * {0} };
+ * ARGPARSE_ARGS pargs = { &argc, &argv, 0 }
+ *
+ * while( ArgParse( &pargs, &opts) ) {
+ * switch( pargs.r_opt ) {
+ * case 'v': opt.verbose++; break;
+ * case 'd': opt.debug++; break;
+ * case 'o': opt.outfile = pargs.r.ret_str; break;
+ * case 'c': opt.crf = pargs.r_type? pargs.r.ret_str:"a.crf"; break;
+ * case 'm': opt.myopt = pargs.r_type? pargs.r.ret_int : 1; break;
+ * case 500: opt.a_long_one++; break
+ * default : pargs.err = 1; break; -- force warning output --
+ * }
+ * }
+ * if( argc > 1 )
+ * log_fatal( "Too many args");
+ *
+ */
+
+typedef struct alias_def_s *ALIAS_DEF;
+struct alias_def_s {
+ ALIAS_DEF next;
+ char *name; /* malloced buffer with name, \0, value */
+ const char *value; /* ptr into name */
+};
+
+
+/* Object to store the names for the --ignore-invalid-option option.
+ This is a simple linked list. */
+typedef struct iio_item_def_s *IIO_ITEM_DEF;
+struct iio_item_def_s
+{
+ IIO_ITEM_DEF next;
+ char name[1]; /* String with the long option name. */
+};
+
+static const char *(*strusage_handler)( int ) = NULL;
+static int (*custom_outfnc) (int, const char *);
+
+static int set_opt_arg(ARGPARSE_ARGS *arg, unsigned flags, char *s);
+static void show_help(ARGPARSE_OPTS *opts, unsigned flags);
+static void show_version(void);
+static int writestrings (int is_error, const char *string, ...)
+#if __GNUC__ >= 4
+ __attribute__ ((sentinel(0)))
+#endif
+ ;
+
+
+void
+argparse_register_outfnc (int (*fnc)(int, const char *))
+{
+ custom_outfnc = fnc;
+}
+
+
+/* Write STRING and all following const char * arguments either to
+ stdout or, if IS_ERROR is set, to stderr. The list of strings must
+ be terminated by a NULL. */
+static int
+writestrings (int is_error, const char *string, ...)
+{
+ va_list arg_ptr;
+ const char *s;
+ int count = 0;
+
+ if (string)
+ {
+ s = string;
+ va_start (arg_ptr, string);
+ do
+ {
+ if (custom_outfnc)
+ custom_outfnc (is_error? 2:1, s);
+ else
+ fputs (s, is_error? stderr : stdout);
+ count += strlen (s);
+ }
+ while ((s = va_arg (arg_ptr, const char *)));
+ va_end (arg_ptr);
+ }
+ return count;
+}
+
+
+static void
+flushstrings (int is_error)
+{
+ if (custom_outfnc)
+ custom_outfnc (is_error? 2:1, NULL);
+ else
+ fflush (is_error? stderr : stdout);
+}
+
+
+static void
+initialize( ARGPARSE_ARGS *arg, const char *filename, unsigned *lineno )
+{
+ if( !(arg->flags & (1<<15)) )
+ {
+ /* Initialize this instance. */
+ arg->internal.idx = 0;
+ arg->internal.last = NULL;
+ arg->internal.inarg = 0;
+ arg->internal.stopped = 0;
+ arg->internal.aliases = NULL;
+ arg->internal.cur_alias = NULL;
+ arg->internal.iio_list = NULL;
+ arg->err = 0;
+ arg->flags |= 1<<15; /* Mark as initialized. */
+ if ( *arg->argc < 0 )
+ log_bug ("invalid argument for arg_parse\n");
+ }
+
+
+ if (arg->err)
+ {
+ /* Last option was erroneous. */
+ const char *s;
+
+ if (filename)
+ {
+ if ( arg->r_opt == ARGPARSE_UNEXPECTED_ARG )
+ s = _("argument not expected");
+ else if ( arg->r_opt == ARGPARSE_READ_ERROR )
+ s = _("read error");
+ else if ( arg->r_opt == ARGPARSE_KEYWORD_TOO_LONG )
+ s = _("keyword too long");
+ else if ( arg->r_opt == ARGPARSE_MISSING_ARG )
+ s = _("missing argument");
+ else if ( arg->r_opt == ARGPARSE_INVALID_ARG )
+ s = _("invalid argument");
+ else if ( arg->r_opt == ARGPARSE_INVALID_COMMAND )
+ s = _("invalid command");
+ else if ( arg->r_opt == ARGPARSE_INVALID_ALIAS )
+ s = _("invalid alias definition");
+ else if ( arg->r_opt == ARGPARSE_OUT_OF_CORE )
+ s = _("out of core");
+ else
+ s = _("invalid option");
+ log_error ("%s:%u: %s\n", filename, *lineno, s);
+ }
+ else
+ {
+ s = arg->internal.last? arg->internal.last:"[??]";
+
+ if ( arg->r_opt == ARGPARSE_MISSING_ARG )
+ log_error (_("missing argument for option \"%.50s\"\n"), s);
+ else if ( arg->r_opt == ARGPARSE_INVALID_ARG )
+ log_error (_("invalid argument for option \"%.50s\"\n"), s);
+ else if ( arg->r_opt == ARGPARSE_UNEXPECTED_ARG )
+ log_error (_("option \"%.50s\" does not expect an argument\n"), s);
+ else if ( arg->r_opt == ARGPARSE_INVALID_COMMAND )
+ log_error (_("invalid command \"%.50s\"\n"), s);
+ else if ( arg->r_opt == ARGPARSE_AMBIGUOUS_OPTION )
+ log_error (_("option \"%.50s\" is ambiguous\n"), s);
+ else if ( arg->r_opt == ARGPARSE_AMBIGUOUS_COMMAND )
+ log_error (_("command \"%.50s\" is ambiguous\n"),s );
+ else if ( arg->r_opt == ARGPARSE_OUT_OF_CORE )
+ log_error ("%s\n", _("out of core\n"));
+ else
+ log_error (_("invalid option \"%.50s\"\n"), s);
+ }
+ if (arg->err != ARGPARSE_PRINT_WARNING)
+ exit (2);
+ arg->err = 0;
+ }
+
+ /* Zero out the return value union. */
+ arg->r.ret_str = NULL;
+ arg->r.ret_long = 0;
+}
+
+
+static void
+store_alias( ARGPARSE_ARGS *arg, char *name, char *value )
+{
+ /* TODO: replace this dummy function with a rea one
+ * and fix the probelms IRIX has with (ALIAS_DEV)arg..
+ * used as lvalue
+ */
+ (void)arg;
+ (void)name;
+ (void)value;
+#if 0
+ ALIAS_DEF a = xmalloc( sizeof *a );
+ a->name = name;
+ a->value = value;
+ a->next = (ALIAS_DEF)arg->internal.aliases;
+ (ALIAS_DEF)arg->internal.aliases = a;
+#endif
+}
+
+
+/* Return true if KEYWORD is in the ignore-invalid-option list. */
+static int
+ignore_invalid_option_p (ARGPARSE_ARGS *arg, const char *keyword)
+{
+ IIO_ITEM_DEF item = arg->internal.iio_list;
+
+ for (; item; item = item->next)
+ if (!strcmp (item->name, keyword))
+ return 1;
+ return 0;
+}
+
+
+/* Add the keywords up to the next LF to the list of to be ignored
+ options. After returning FP will either be at EOF or the next
+ character read wll be the first of a new line. The function
+ returns 0 on success or true on malloc failure. */
+static int
+ignore_invalid_option_add (ARGPARSE_ARGS *arg, FILE *fp)
+{
+ IIO_ITEM_DEF item;
+ int c;
+ char name[100];
+ int namelen = 0;
+ int ready = 0;
+ enum { skipWS, collectNAME, skipNAME, addNAME} state = skipWS;
+
+ while (!ready)
+ {
+ c = getc (fp);
+ if (c == '\n')
+ ready = 1;
+ else if (c == EOF)
+ {
+ c = '\n';
+ ready = 1;
+ }
+ again:
+ switch (state)
+ {
+ case skipWS:
+ if (!isascii (c) || !isspace(c))
+ {
+ namelen = 0;
+ state = collectNAME;
+ goto again;
+ }
+ break;
+
+ case collectNAME:
+ if (isspace (c))
+ {
+ state = addNAME;
+ goto again;
+ }
+ else if (namelen < DIM(name)-1)
+ name[namelen++] = c;
+ else /* Too long. */
+ state = skipNAME;
+ break;
+
+ case skipNAME:
+ if (isspace (c))
+ {
+ state = skipWS;
+ goto again;
+ }
+ break;
+
+ case addNAME:
+ name[namelen] = 0;
+ if (!ignore_invalid_option_p (arg, name))
+ {
+ item = xtrymalloc (sizeof *item + namelen);
+ if (!item)
+ return 1;
+ strcpy (item->name, name);
+ item->next = (IIO_ITEM_DEF)arg->internal.iio_list;
+ arg->internal.iio_list = item;
+ }
+ state = skipWS;
+ goto again;
+ }
+ }
+ return 0;
+}
+
+
+/* Clear the entire ignore-invalid-option list. */
+static void
+ignore_invalid_option_clear (ARGPARSE_ARGS *arg)
+{
+ IIO_ITEM_DEF item, tmpitem;
+
+ for (item = arg->internal.iio_list; item; item = tmpitem)
+ {
+ tmpitem = item->next;
+ xfree (item);
+ }
+ arg->internal.iio_list = NULL;
+}
+
+
+
+/****************
+ * Get options from a file.
+ * Lines starting with '#' are comment lines.
+ * Syntax is simply a keyword and the argument.
+ * Valid keywords are all keywords from the long_opt list without
+ * the leading dashes. The special keywords "help", "warranty" and "version"
+ * are not valid here.
+ * The special keyword "alias" may be used to store alias definitions,
+ * which are later expanded like long options.
+ * The option
+ * ignore-invalid-option OPTIONNAMEs
+ * is recognized and updates a list of option which should be ignored if they
+ * are not defined.
+ * Caller must free returned strings.
+ * If called with FP set to NULL command line args are parse instead.
+ *
+ * Q: Should we allow the syntax
+ * keyword = value
+ * and accept for boolean options a value of 1/0, yes/no or true/false?
+ * Note: Abbreviation of options is here not allowed.
+ */
+int
+optfile_parse (FILE *fp, const char *filename, unsigned *lineno,
+ ARGPARSE_ARGS *arg, ARGPARSE_OPTS *opts)
+{
+ int state, i, c;
+ int idx=0;
+ char keyword[100];
+ char *buffer = NULL;
+ size_t buflen = 0;
+ int in_alias=0;
+
+ if (!fp) /* Divert to to arg_parse() in this case. */
+ return arg_parse (arg, opts);
+
+ initialize (arg, filename, lineno);
+
+ /* Find the next keyword. */
+ state = i = 0;
+ for (;;)
+ {
+ c = getc (fp);
+ if (c == '\n' || c== EOF )
+ {
+ if ( c != EOF )
+ ++*lineno;
+ if (state == -1)
+ break;
+ else if (state == 2)
+ {
+ keyword[i] = 0;
+ for (i=0; opts[i].short_opt; i++ )
+ {
+ if (opts[i].long_opt && !strcmp (opts[i].long_opt, keyword))
+ break;
+ }
+ idx = i;
+ arg->r_opt = opts[idx].short_opt;
+ if ((opts[idx].flags & ARGPARSE_OPT_IGNORE))
+ {
+ state = i = 0;
+ continue;
+ }
+ else if (!opts[idx].short_opt )
+ {
+ if (!strcmp (keyword, "ignore-invalid-option"))
+ {
+ /* No argument - ignore this meta option. */
+ state = i = 0;
+ continue;
+ }
+ else if (ignore_invalid_option_p (arg, keyword))
+ {
+ /* This invalid option is in the iio list. */
+ state = i = 0;
+ continue;
+ }
+ arg->r_opt = ((opts[idx].flags & ARGPARSE_OPT_COMMAND)
+ ? ARGPARSE_INVALID_COMMAND
+ : ARGPARSE_INVALID_OPTION);
+ }
+ else if (!(opts[idx].flags & ARGPARSE_TYPE_MASK))
+ arg->r_type = 0; /* Does not take an arg. */
+ else if ((opts[idx].flags & ARGPARSE_OPT_OPTIONAL) )
+ arg->r_type = 0; /* Arg is optional. */
+ else
+ arg->r_opt = ARGPARSE_MISSING_ARG;
+
+ break;
+ }
+ else if (state == 3)
+ {
+ /* No argument found. */
+ if (in_alias)
+ arg->r_opt = ARGPARSE_MISSING_ARG;
+ else if (!(opts[idx].flags & ARGPARSE_TYPE_MASK))
+ arg->r_type = 0; /* Does not take an arg. */
+ else if ((opts[idx].flags & ARGPARSE_OPT_OPTIONAL))
+ arg->r_type = 0; /* No optional argument. */
+ else
+ arg->r_opt = ARGPARSE_MISSING_ARG;
+
+ break;
+ }
+ else if (state == 4)
+ {
+ /* Has an argument. */
+ if (in_alias)
+ {
+ if (!buffer)
+ arg->r_opt = ARGPARSE_UNEXPECTED_ARG;
+ else
+ {
+ char *p;
+
+ buffer[i] = 0;
+ p = strpbrk (buffer, " \t");
+ if (p)
+ {
+ *p++ = 0;
+ trim_spaces (p);
+ }
+ if (!p || !*p)
+ {
+ xfree (buffer);
+ arg->r_opt = ARGPARSE_INVALID_ALIAS;
+ }
+ else
+ {
+ store_alias (arg, buffer, p);
+ }
+ }
+ }
+ else if (!(opts[idx].flags & ARGPARSE_TYPE_MASK))
+ arg->r_opt = ARGPARSE_UNEXPECTED_ARG;
+ else
+ {
+ char *p;
+
+ if (!buffer)
+ {
+ keyword[i] = 0;
+ buffer = xtrystrdup (keyword);
+ if (!buffer)
+ arg->r_opt = ARGPARSE_OUT_OF_CORE;
+ }
+ else
+ buffer[i] = 0;
+
+ if (buffer)
+ {
+ trim_spaces (buffer);
+ p = buffer;
+ if (*p == '"')
+ {
+ /* Remove quotes. */
+ p++;
+ if (*p && p[strlen(p)-1] == '\"' )
+ p[strlen(p)-1] = 0;
+ }
+ if (!set_opt_arg (arg, opts[idx].flags, p))
+ xfree (buffer);
+ }
+ }
+ break;
+ }
+ else if (c == EOF)
+ {
+ ignore_invalid_option_clear (arg);
+ if (ferror (fp))
+ arg->r_opt = ARGPARSE_READ_ERROR;
+ else
+ arg->r_opt = 0; /* EOF. */
+ break;
+ }
+ state = 0;
+ i = 0;
+ }
+ else if (state == -1)
+ ; /* Skip. */
+ else if (state == 0 && isascii (c) && isspace(c))
+ ; /* Skip leading white space. */
+ else if (state == 0 && c == '#' )
+ state = 1; /* Start of a comment. */
+ else if (state == 1)
+ ; /* Skip comments. */
+ else if (state == 2 && isascii (c) && isspace(c))
+ {
+ /* Check keyword. */
+ keyword[i] = 0;
+ for (i=0; opts[i].short_opt; i++ )
+ if (opts[i].long_opt && !strcmp (opts[i].long_opt, keyword))
+ break;
+ idx = i;
+ arg->r_opt = opts[idx].short_opt;
+ if ((opts[idx].flags & ARGPARSE_OPT_IGNORE))
+ {
+ state = 1; /* Process like a comment. */
+ }
+ else if (!opts[idx].short_opt)
+ {
+ if (!strcmp (keyword, "alias"))
+ {
+ in_alias = 1;
+ state = 3;
+ }
+ else if (!strcmp (keyword, "ignore-invalid-option"))
+ {
+ if (ignore_invalid_option_add (arg, fp))
+ {
+ arg->r_opt = ARGPARSE_OUT_OF_CORE;
+ break;
+ }
+ state = i = 0;
+ ++*lineno;
+ }
+ else if (ignore_invalid_option_p (arg, keyword))
+ state = 1; /* Process like a comment. */
+ else
+ {
+ arg->r_opt = ((opts[idx].flags & ARGPARSE_OPT_COMMAND)
+ ? ARGPARSE_INVALID_COMMAND
+ : ARGPARSE_INVALID_OPTION);
+ state = -1; /* Skip rest of line and leave. */
+ }
+ }
+ else
+ state = 3;
+ }
+ else if (state == 3)
+ {
+ /* Skip leading spaces of the argument. */
+ if (!isascii (c) || !isspace(c))
+ {
+ i = 0;
+ keyword[i++] = c;
+ state = 4;
+ }
+ }
+ else if (state == 4)
+ {
+ /* Collect the argument. */
+ if (buffer)
+ {
+ if (i < buflen-1)
+ buffer[i++] = c;
+ else
+ {
+ char *tmp;
+ size_t tmplen = buflen + 50;
+
+ tmp = xtryrealloc (buffer, tmplen);
+ if (tmp)
+ {
+ buflen = tmplen;
+ buffer = tmp;
+ buffer[i++] = c;
+ }
+ else
+ {
+ xfree (buffer);
+ arg->r_opt = ARGPARSE_OUT_OF_CORE;
+ break;
+ }
+ }
+ }
+ else if (i < DIM(keyword)-1)
+ keyword[i++] = c;
+ else
+ {
+ size_t tmplen = DIM(keyword) + 50;
+ buffer = xtrymalloc (tmplen);
+ if (buffer)
+ {
+ buflen = tmplen;
+ memcpy(buffer, keyword, i);
+ buffer[i++] = c;
+ }
+ else
+ {
+ arg->r_opt = ARGPARSE_OUT_OF_CORE;
+ break;
+ }
+ }
+ }
+ else if (i >= DIM(keyword)-1)
+ {
+ arg->r_opt = ARGPARSE_KEYWORD_TOO_LONG;
+ state = -1; /* Skip rest of line and leave. */
+ }
+ else
+ {
+ keyword[i++] = c;
+ state = 2;
+ }
+ }
+
+ return arg->r_opt;
+}
+
+
+
+static int
+find_long_option( ARGPARSE_ARGS *arg,
+ ARGPARSE_OPTS *opts, const char *keyword )
+{
+ int i;
+ size_t n;
+
+ (void)arg;
+
+ /* Would be better if we can do a binary search, but it is not
+ possible to reorder our option table because we would mess
+ up our help strings - What we can do is: Build a nice option
+ lookup table when this function is first invoked */
+ if( !*keyword )
+ return -1;
+ for(i=0; opts[i].short_opt; i++ )
+ if( opts[i].long_opt && !strcmp( opts[i].long_opt, keyword) )
+ return i;
+#if 0
+ {
+ ALIAS_DEF a;
+ /* see whether it is an alias */
+ for( a = args->internal.aliases; a; a = a->next ) {
+ if( !strcmp( a->name, keyword) ) {
+ /* todo: must parse the alias here */
+ args->internal.cur_alias = a;
+ return -3; /* alias available */
+ }
+ }
+ }
+#endif
+ /* not found, see whether it is an abbreviation */
+ /* aliases may not be abbreviated */
+ n = strlen( keyword );
+ for(i=0; opts[i].short_opt; i++ ) {
+ if( opts[i].long_opt && !strncmp( opts[i].long_opt, keyword, n ) ) {
+ int j;
+ for(j=i+1; opts[j].short_opt; j++ ) {
+ if( opts[j].long_opt
+ && !strncmp( opts[j].long_opt, keyword, n ) )
+ return -2; /* abbreviation is ambiguous */
+ }
+ return i;
+ }
+ }
+ return -1; /* Not found. */
+}
+
+int
+arg_parse( ARGPARSE_ARGS *arg, ARGPARSE_OPTS *opts)
+{
+ int idx;
+ int argc;
+ char **argv;
+ char *s, *s2;
+ int i;
+ char string_with_x[] = "x";
+
+ initialize( arg, NULL, NULL );
+ argc = *arg->argc;
+ argv = *arg->argv;
+ idx = arg->internal.idx;
+
+ if (!idx && argc && !(arg->flags & ARGPARSE_FLAG_ARG0))
+ {
+ /* Skip the first argument. */
+ argc--; argv++; idx++;
+ }
+
+ next_one:
+ if (!argc)
+ {
+ /* No more args. */
+ arg->r_opt = 0;
+ goto leave; /* Ready. */
+ }
+
+ s = *argv;
+ arg->internal.last = s;
+
+ if (arg->internal.stopped && (arg->flags & ARGPARSE_FLAG_ALL))
+ {
+ arg->r_opt = ARGPARSE_IS_ARG; /* Not an option but an argument. */
+ arg->r_type = 2;
+ arg->r.ret_str = s;
+ argc--; argv++; idx++; /* set to next one */
+ }
+ else if( arg->internal.stopped )
+ {
+ arg->r_opt = 0;
+ goto leave; /* Ready. */
+ }
+ else if ( *s == '-' && s[1] == '-' )
+ {
+ /* Long option. */
+ char *argpos;
+
+ arg->internal.inarg = 0;
+ if (!s[2] && !(arg->flags & ARGPARSE_FLAG_NOSTOP))
+ {
+ /* Stop option processing. */
+ arg->internal.stopped = 1;
+ arg->flags |= ARGPARSE_FLAG_STOP_SEEN;
+ argc--; argv++; idx++;
+ goto next_one;
+ }
+
+ argpos = strchr( s+2, '=' );
+ if ( argpos )
+ *argpos = 0;
+ i = find_long_option ( arg, opts, s+2 );
+ if ( argpos )
+ *argpos = '=';
+
+ if ( i < 0 && !strcmp ( "help", s+2) )
+ show_help (opts, arg->flags);
+ else if ( i < 0 && !strcmp ( "version", s+2) )
+ {
+ if (!(arg->flags & ARGPARSE_FLAG_NOVERSION))
+ {
+ show_version ();
+ exit(0);
+ }
+ }
+ else if ( i < 0 && !strcmp( "warranty", s+2))
+ {
+ writestrings (0, strusage (16), "\n", NULL);
+ exit (0);
+ }
+ else if ( i < 0 && !strcmp( "dump-options", s+2) )
+ {
+ for (i=0; opts[i].short_opt; i++ )
+ {
+ if (opts[i].long_opt && !(opts[i].flags & ARGPARSE_OPT_IGNORE))
+ writestrings (0, "--", opts[i].long_opt, "\n", NULL);
+ }
+ writestrings (0, "--dump-options\n--help\n--version\n--warranty\n",
+ NULL);
+ exit (0);
+ }
+
+ if ( i == -2 )
+ arg->r_opt = ARGPARSE_AMBIGUOUS_OPTION;
+ else if ( i == -1 )
+ {
+ arg->r_opt = ARGPARSE_INVALID_OPTION;
+ arg->r.ret_str = s+2;
+ }
+ else
+ arg->r_opt = opts[i].short_opt;
+ if ( i < 0 )
+ ;
+ else if ( (opts[i].flags & ARGPARSE_TYPE_MASK) )
+ {
+ if ( argpos )
+ {
+ s2 = argpos+1;
+ if ( !*s2 )
+ s2 = NULL;
+ }
+ else
+ s2 = argv[1];
+ if ( !s2 && (opts[i].flags & ARGPARSE_OPT_OPTIONAL) )
+ {
+ arg->r_type = ARGPARSE_TYPE_NONE; /* Argument is optional. */
+ }
+ else if ( !s2 )
+ {
+ arg->r_opt = ARGPARSE_MISSING_ARG;
+ }
+ else if ( !argpos && *s2 == '-'
+ && (opts[i].flags & ARGPARSE_OPT_OPTIONAL) )
+ {
+ /* The argument is optional and the next seems to be an
+ option. We do not check this possible option but
+ assume no argument */
+ arg->r_type = ARGPARSE_TYPE_NONE;
+ }
+ else
+ {
+ set_opt_arg (arg, opts[i].flags, s2);
+ if ( !argpos )
+ {
+ argc--; argv++; idx++; /* Skip one. */
+ }
+ }
+ }
+ else
+ {
+ /* Does not take an argument. */
+ if ( argpos )
+ arg->r_type = ARGPARSE_UNEXPECTED_ARG;
+ else
+ arg->r_type = 0;
+ }
+ argc--; argv++; idx++; /* Set to next one. */
+ }
+ else if ( (*s == '-' && s[1]) || arg->internal.inarg )
+ {
+ /* Short option. */
+ int dash_kludge = 0;
+
+ i = 0;
+ if ( !arg->internal.inarg )
+ {
+ arg->internal.inarg++;
+ if ( (arg->flags & ARGPARSE_FLAG_ONEDASH) )
+ {
+ for (i=0; opts[i].short_opt; i++ )
+ if ( opts[i].long_opt && !strcmp (opts[i].long_opt, s+1))
+ {
+ dash_kludge = 1;
+ break;
+ }
+ }
+ }
+ s += arg->internal.inarg;
+
+ if (!dash_kludge )
+ {
+ for (i=0; opts[i].short_opt; i++ )
+ if ( opts[i].short_opt == *s )
+ break;
+ }
+
+ if ( !opts[i].short_opt && ( *s == 'h' || *s == '?' ) )
+ show_help (opts, arg->flags);
+
+ arg->r_opt = opts[i].short_opt;
+ if (!opts[i].short_opt )
+ {
+ arg->r_opt = (opts[i].flags & ARGPARSE_OPT_COMMAND)?
+ ARGPARSE_INVALID_COMMAND:ARGPARSE_INVALID_OPTION;
+ arg->internal.inarg++; /* Point to the next arg. */
+ arg->r.ret_str = s;
+ }
+ else if ( (opts[i].flags & ARGPARSE_TYPE_MASK) )
+ {
+ if ( s[1] && !dash_kludge )
+ {
+ s2 = s+1;
+ set_opt_arg (arg, opts[i].flags, s2);
+ }
+ else
+ {
+ s2 = argv[1];
+ if ( !s2 && (opts[i].flags & ARGPARSE_OPT_OPTIONAL) )
+ {
+ arg->r_type = ARGPARSE_TYPE_NONE;
+ }
+ else if ( !s2 )
+ {
+ arg->r_opt = ARGPARSE_MISSING_ARG;
+ }
+ else if ( *s2 == '-' && s2[1]
+ && (opts[i].flags & ARGPARSE_OPT_OPTIONAL) )
+ {
+ /* The argument is optional and the next seems to
+ be an option. We do not check this possible
+ option but assume no argument. */
+ arg->r_type = ARGPARSE_TYPE_NONE;
+ }
+ else
+ {
+ set_opt_arg (arg, opts[i].flags, s2);
+ argc--; argv++; idx++; /* Skip one. */
+ }
+ }
+ s = string_with_x; /* This is so that !s[1] yields false. */
+ }
+ else
+ {
+ /* Does not take an argument. */
+ arg->r_type = ARGPARSE_TYPE_NONE;
+ arg->internal.inarg++; /* Point to the next arg. */
+ }
+ if ( !s[1] || dash_kludge )
+ {
+ /* No more concatenated short options. */
+ arg->internal.inarg = 0;
+ argc--; argv++; idx++;
+ }
+ }
+ else if ( arg->flags & ARGPARSE_FLAG_MIXED )
+ {
+ arg->r_opt = ARGPARSE_IS_ARG;
+ arg->r_type = 2;
+ arg->r.ret_str = s;
+ argc--; argv++; idx++; /* Set to next one. */
+ }
+ else
+ {
+ arg->internal.stopped = 1; /* Stop option processing. */
+ goto next_one;
+ }
+
+ leave:
+ *arg->argc = argc;
+ *arg->argv = argv;
+ arg->internal.idx = idx;
+ return arg->r_opt;
+}
+
+
+/* Returns: -1 on error, 0 for an integer type and 1 for a non integer
+ type argument. */
+static int
+set_opt_arg (ARGPARSE_ARGS *arg, unsigned flags, char *s)
+{
+ int base = (flags & ARGPARSE_OPT_PREFIX)? 0 : 10;
+ long l;
+
+ switch ( (arg->r_type = (flags & ARGPARSE_TYPE_MASK)) )
+ {
+ case ARGPARSE_TYPE_LONG:
+ case ARGPARSE_TYPE_INT:
+ errno = 0;
+ l = strtol (s, NULL, base);
+ if ((l == LONG_MIN || l == LONG_MAX) && errno == ERANGE)
+ {
+ arg->r_opt = ARGPARSE_INVALID_ARG;
+ return -1;
+ }
+ if (arg->r_type == ARGPARSE_TYPE_LONG)
+ arg->r.ret_long = l;
+ else if ( (l < 0 && l < INT_MIN) || l > INT_MAX )
+ {
+ arg->r_opt = ARGPARSE_INVALID_ARG;
+ return -1;
+ }
+ else
+ arg->r.ret_int = (int)l;
+ return 0;
+
+ case ARGPARSE_TYPE_ULONG:
+ while (isascii (*s) && isspace(*s))
+ s++;
+ if (*s == '-')
+ {
+ arg->r.ret_ulong = 0;
+ arg->r_opt = ARGPARSE_INVALID_ARG;
+ return -1;
+ }
+ errno = 0;
+ arg->r.ret_ulong = strtoul (s, NULL, base);
+ if (arg->r.ret_ulong == ULONG_MAX && errno == ERANGE)
+ {
+ arg->r_opt = ARGPARSE_INVALID_ARG;
+ return -1;
+ }
+ return 0;
+
+ case ARGPARSE_TYPE_STRING:
+ default:
+ arg->r.ret_str = s;
+ return 1;
+ }
+}
+
+
+static size_t
+long_opt_strlen( ARGPARSE_OPTS *o )
+{
+ size_t n = strlen (o->long_opt);
+
+ if ( o->description && *o->description == '|' )
+ {
+ const char *s;
+ int is_utf8 = is_native_utf8 ();
+
+ s=o->description+1;
+ if ( *s != '=' )
+ n++;
+ /* For a (mostly) correct length calculation we exclude
+ continuation bytes (10xxxxxx) if we are on a native utf8
+ terminal. */
+ for (; *s && *s != '|'; s++ )
+ if ( is_utf8 && (*s&0xc0) != 0x80 )
+ n++;
+ }
+ return n;
+}
+
+
+/****************
+ * Print formatted help. The description string has some special
+ * meanings:
+ * - A description string which is "@" suppresses help output for
+ * this option
+ * - a description,ine which starts with a '@' and is followed by
+ * any other characters is printed as is; this may be used for examples
+ * ans such.
+ * - A description which starts with a '|' outputs the string between this
+ * bar and the next one as arguments of the long option.
+ */
+static void
+show_help (ARGPARSE_OPTS *opts, unsigned int flags)
+{
+ const char *s;
+ char tmp[2];
+
+ show_version ();
+ writestrings (0, "\n", NULL);
+ s = strusage (42);
+ if (s && *s == '1')
+ {
+ s = strusage (40);
+ writestrings (1, s, NULL);
+ if (*s && s[strlen(s)] != '\n')
+ writestrings (1, "\n", NULL);
+ }
+ s = strusage(41);
+ writestrings (0, s, "\n", NULL);
+ if ( opts[0].description )
+ {
+ /* Auto format the option description. */
+ int i,j, indent;
+
+ /* Get max. length of long options. */
+ for (i=indent=0; opts[i].short_opt; i++ )
+ {
+ if ( opts[i].long_opt )
+ if ( !opts[i].description || *opts[i].description != '@' )
+ if ( (j=long_opt_strlen(opts+i)) > indent && j < 35 )
+ indent = j;
+ }
+
+ /* Example: " -v, --verbose Viele Sachen ausgeben" */
+ indent += 10;
+ if ( *opts[0].description != '@' )
+ writestrings (0, "Options:", "\n", NULL);
+ for (i=0; opts[i].short_opt; i++ )
+ {
+ s = map_static_macro_string (_( opts[i].description ));
+ if ( s && *s== '@' && !s[1] ) /* Hide this line. */
+ continue;
+ if ( s && *s == '@' ) /* Unindented comment only line. */
+ {
+ for (s++; *s; s++ )
+ {
+ if ( *s == '\n' )
+ {
+ if( s[1] )
+ writestrings (0, "\n", NULL);
+ }
+ else
+ {
+ tmp[0] = *s;
+ tmp[1] = 0;
+ writestrings (0, tmp, NULL);
+ }
+ }
+ writestrings (0, "\n", NULL);
+ continue;
+ }
+
+ j = 3;
+ if ( opts[i].short_opt < 256 )
+ {
+ tmp[0] = opts[i].short_opt;
+ tmp[1] = 0;
+ writestrings (0, " -", tmp, NULL );
+ if ( !opts[i].long_opt )
+ {
+ if (s && *s == '|' )
+ {
+ writestrings (0, " ", NULL); j++;
+ for (s++ ; *s && *s != '|'; s++, j++ )
+ {
+ tmp[0] = *s;
+ tmp[1] = 0;
+ writestrings (0, tmp, NULL);
+ }
+ if ( *s )
+ s++;
+ }
+ }
+ }
+ else
+ writestrings (0, " ", NULL);
+ if ( opts[i].long_opt )
+ {
+ tmp[0] = opts[i].short_opt < 256?',':' ';
+ tmp[1] = 0;
+ j += writestrings (0, tmp, " --", opts[i].long_opt, NULL);
+ if (s && *s == '|' )
+ {
+ if ( *++s != '=' )
+ {
+ writestrings (0, " ", NULL);
+ j++;
+ }
+ for ( ; *s && *s != '|'; s++, j++ )
+ {
+ tmp[0] = *s;
+ tmp[1] = 0;
+ writestrings (0, tmp, NULL);
+ }
+ if ( *s )
+ s++;
+ }
+ writestrings (0, " ", NULL);
+ j += 3;
+ }
+ for (;j < indent; j++ )
+ writestrings (0, " ", NULL);
+ if ( s )
+ {
+ if ( *s && j > indent )
+ {
+ writestrings (0, "\n", NULL);
+ for (j=0;j < indent; j++ )
+ writestrings (0, " ", NULL);
+ }
+ for (; *s; s++ )
+ {
+ if ( *s == '\n' )
+ {
+ if ( s[1] )
+ {
+ writestrings (0, "\n", NULL);
+ for (j=0; j < indent; j++ )
+ writestrings (0, " ", NULL);
+ }
+ }
+ else
+ {
+ tmp[0] = *s;
+ tmp[1] = 0;
+ writestrings (0, tmp, NULL);
+ }
+ }
+ }
+ writestrings (0, "\n", NULL);
+ }
+ if ( (flags & ARGPARSE_FLAG_ONEDASH) )
+ writestrings (0, "\n(A single dash may be used "
+ "instead of the double ones)\n", NULL);
+ }
+ if ( (s=strusage(19)) )
+ {
+ writestrings (0, "\n", NULL);
+ writestrings (0, s, NULL);
+ }
+ flushstrings (0);
+ exit(0);
+}
+
+static void
+show_version ()
+{
+ const char *s;
+ int i;
+
+ /* Version line. */
+ writestrings (0, strusage (11), NULL);
+ if ((s=strusage (12)))
+ writestrings (0, " (", s, ")", NULL);
+ writestrings (0, " ", strusage (13), "\n", NULL);
+ /* Additional version lines. */
+ for (i=20; i < 30; i++)
+ if ((s=strusage (i)))
+ writestrings (0, s, "\n", NULL);
+ /* Copyright string. */
+ if ((s=strusage (14)))
+ writestrings (0, s, "\n", NULL);
+ /* Licence string. */
+ if( (s=strusage (10)) )
+ writestrings (0, s, "\n", NULL);
+ /* Copying conditions. */
+ if ( (s=strusage(15)) )
+ writestrings (0, s, NULL);
+ /* Thanks. */
+ if ((s=strusage(18)))
+ writestrings (0, s, NULL);
+ /* Additional program info. */
+ for (i=30; i < 40; i++ )
+ if ( (s=strusage (i)) )
+ writestrings (0, s, NULL);
+ flushstrings (0);
+}
+
+
+void
+usage (int level)
+{
+ const char *p;
+
+ if (!level)
+ {
+ writestrings (1, strusage(11), " ", strusage(13), "; ",
+ strusage (14), "\n", NULL);
+ flushstrings (1);
+ }
+ else if (level == 1)
+ {
+ p = strusage (40);
+ writestrings (1, p, NULL);
+ if (*p && p[strlen(p)] != '\n')
+ writestrings (1, "\n", NULL);
+ exit (2);
+ }
+ else if (level == 2)
+ {
+ p = strusage (42);
+ if (p && *p == '1')
+ {
+ p = strusage (40);
+ writestrings (1, p, NULL);
+ if (*p && p[strlen(p)] != '\n')
+ writestrings (1, "\n", NULL);
+ }
+ writestrings (0, strusage(41), "\n", NULL);
+ exit (0);
+ }
+}
+
+/* Level
+ * 0: Print copyright string to stderr
+ * 1: Print a short usage hint to stderr and terminate
+ * 2: Print a long usage hint to stdout and terminate
+ * 10: Return license info string
+ * 11: Return the name of the program
+ * 12: Return optional name of package which includes this program.
+ * 13: version string
+ * 14: copyright string
+ * 15: Short copying conditions (with LFs)
+ * 16: Long copying conditions (with LFs)
+ * 17: Optional printable OS name
+ * 18: Optional thanks list (with LFs)
+ * 19: Bug report info
+ *20..29: Additional lib version strings.
+ *30..39: Additional program info (with LFs)
+ * 40: short usage note (with LF)
+ * 41: long usage note (with LF)
+ * 42: Flag string:
+ * First char is '1':
+ * The short usage notes needs to be printed
+ * before the long usage note.
+ */
+const char *
+strusage( int level )
+{
+ const char *p = strusage_handler? strusage_handler(level) : NULL;
+
+ if ( p )
+ return map_static_macro_string (p);
+
+ switch ( level )
+ {
+
+ case 10:
+#if ARGPARSE_GPL_VERSION == 3
+ p = ("License GPLv3+: GNU GPL version 3 or later "
+ "<http://gnu.org/licenses/gpl.html>");
+#else
+ p = ("License GPLv2+: GNU GPL version 2 or later "
+ "<http://gnu.org/licenses/>");
+#endif
+ break;
+ case 11: p = "foo"; break;
+ case 13: p = "0.0"; break;
+ case 14: p = ARGPARSE_CRIGHT_STR; break;
+ case 15: p =
+"This is free software: you are free to change and redistribute it.\n"
+"There is NO WARRANTY, to the extent permitted by law.\n";
+ break;
+ case 16: p =
+"This is free software; you can redistribute it and/or modify\n"
+"it under the terms of the GNU General Public License as published by\n"
+"the Free Software Foundation; either version "
+ARGPARSE_STR2(ARGPARSE_GPL_VERSION)
+" of the License, or\n"
+"(at your option) any later version.\n\n"
+"It is distributed in the hope that it will be useful,\n"
+"but WITHOUT ANY WARRANTY; without even the implied warranty of\n"
+"MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the\n"
+"GNU General Public License for more details.\n\n"
+"You should have received a copy of the GNU General Public License\n"
+"along with this software. If not, see <http://www.gnu.org/licenses/>.\n";
+ break;
+ case 40: /* short and long usage */
+ case 41: p = ""; break;
+ }
+
+ return p;
+}
+
+
+/* Set the usage handler. This function is basically a constructor. */
+void
+set_strusage ( const char *(*f)( int ) )
+{
+ strusage_handler = f;
+}
+
+
+#ifdef TEST
+static struct {
+ int verbose;
+ int debug;
+ char *outfile;
+ char *crf;
+ int myopt;
+ int echo;
+ int a_long_one;
+} opt;
+
+int
+main(int argc, char **argv)
+{
+ ARGPARSE_OPTS opts[] = {
+ ARGPARSE_x('v', "verbose", NONE, 0, "Laut sein"),
+ ARGPARSE_s_n('e', "echo" , ("Zeile ausgeben, damit wir sehen, "
+ "was wir eingegeben haben")),
+ ARGPARSE_s_n('d', "debug", "Debug\nfalls mal etwas\nschief geht"),
+ ARGPARSE_s_s('o', "output", 0 ),
+ ARGPARSE_o_s('c', "cross-ref", "cross-reference erzeugen\n" ),
+ /* Note that on a non-utf8 terminal the ß might garble the output. */
+ ARGPARSE_s_n('s', "street","|Straße|set the name of the street to Straße"),
+ ARGPARSE_o_i('m', "my-option", 0),
+ ARGPARSE_s_n(500, "a-long-option", 0 ),
+ ARGPARSE_end()
+ };
+ ARGPARSE_ARGS pargs = { &argc, &argv, (ARGPARSE_FLAG_ALL
+ | ARGPARSE_FLAG_MIXED
+ | ARGPARSE_FLAG_ONEDASH) };
+ int i;
+
+ while (arg_parse (&pargs, opts))
+ {
+ switch (pargs.r_opt)
+ {
+ case ARGPARSE_IS_ARG :
+ printf ("arg='%s'\n", pargs.r.ret_str);
+ break;
+ case 'v': opt.verbose++; break;
+ case 'e': opt.echo++; break;
+ case 'd': opt.debug++; break;
+ case 'o': opt.outfile = pargs.r.ret_str; break;
+ case 'c': opt.crf = pargs.r_type? pargs.r.ret_str:"a.crf"; break;
+ case 'm': opt.myopt = pargs.r_type? pargs.r.ret_int : 1; break;
+ case 500: opt.a_long_one++; break;
+ default : pargs.err = ARGPARSE_PRINT_WARNING; break;
+ }
+ }
+ for (i=0; i < argc; i++ )
+ printf ("%3d -> (%s)\n", i, argv[i] );
+ puts ("Options:");
+ if (opt.verbose)
+ printf (" verbose=%d\n", opt.verbose );
+ if (opt.debug)
+ printf (" debug=%d\n", opt.debug );
+ if (opt.outfile)
+ printf (" outfile='%s'\n", opt.outfile );
+ if (opt.crf)
+ printf (" crffile='%s'\n", opt.crf );
+ if (opt.myopt)
+ printf (" myopt=%d\n", opt.myopt );
+ if (opt.a_long_one)
+ printf (" a-long-one=%d\n", opt.a_long_one );
+ if (opt.echo)
+ printf (" echo=%d\n", opt.echo );
+
+ return 0;
+}
+#endif /*TEST*/
+
+/**** bottom of file ****/
diff --git a/src/argparse.h b/src/argparse.h
new file mode 100644
index 0000000..10b838f
--- /dev/null
+++ b/src/argparse.h
@@ -0,0 +1,203 @@
+/* argparse.h - Argument parser for option handling.
+ * Copyright (C) 1998,1999,2000,2001,2006 Free Software Foundation, Inc.
+ *
+ * This file is part of GnuPG.
+ *
+ * GnuPG is free software; you can redistribute it and/or modify it
+ * under the terms of either
+ *
+ * - the GNU Lesser General Public License as published by the Free
+ * Software Foundation; either version 3 of the License, or (at
+ * your option) any later version.
+ *
+ * or
+ *
+ * - 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.
+ *
+ * or both in parallel, as here.
+ *
+ * GnuPG 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 copies of the GNU General Public License
+ * and the GNU Lesser General Public License along with this program;
+ * if not, see <http://www.gnu.org/licenses/>.
+ */
+
+#ifndef GNUPG_COMMON_ARGPARSE_H
+#define GNUPG_COMMON_ARGPARSE_H
+
+#include <stdio.h>
+
+typedef struct
+{
+ int *argc; /* Pointer to ARGC (value subject to change). */
+ char ***argv; /* Pointer to ARGV (value subject to change). */
+ unsigned int flags; /* Global flags. May be set prior to calling the
+ parser. The parser may change the value. */
+ int err; /* Print error description for last option.
+ Either 0, ARGPARSE_PRINT_WARNING or
+ ARGPARSE_PRINT_ERROR. */
+
+ int r_opt; /* Returns option code. */
+ int r_type; /* Returns type of option value. */
+ union {
+ int ret_int;
+ long ret_long;
+ unsigned long ret_ulong;
+ char *ret_str;
+ } r; /* Return values */
+
+ struct {
+ int idx;
+ int inarg;
+ int stopped;
+ const char *last;
+ void *aliases;
+ const void *cur_alias;
+ void *iio_list;
+ } internal; /* Private - do not change. */
+} ARGPARSE_ARGS;
+
+typedef struct
+{
+ int short_opt;
+ const char *long_opt;
+ unsigned int flags;
+ const char *description; /* Optional option description. */
+} ARGPARSE_OPTS;
+
+
+/* Global flags (ARGPARSE_ARGS). */
+#define ARGPARSE_FLAG_KEEP 1 /* Do not remove options form argv. */
+#define ARGPARSE_FLAG_ALL 2 /* Do not stop at last option but return
+ remaining args with R_OPT set to -1. */
+#define ARGPARSE_FLAG_MIXED 4 /* Assume options and args are mixed. */
+#define ARGPARSE_FLAG_NOSTOP 8 /* Do not stop processing at "--". */
+#define ARGPARSE_FLAG_ARG0 16 /* Do not skip the first arg. */
+#define ARGPARSE_FLAG_ONEDASH 32 /* Allow long options with one dash. */
+#define ARGPARSE_FLAG_NOVERSION 64 /* No output for "--version". */
+
+#define ARGPARSE_FLAG_STOP_SEEN 256 /* Set to true if a "--" has been seen. */
+
+/* Flags for each option (ARGPARSE_OPTS). The type code may be
+ ORed with the OPT flags. */
+#define ARGPARSE_TYPE_NONE 0 /* Does not take an argument. */
+#define ARGPARSE_TYPE_INT 1 /* Takes an int argument. */
+#define ARGPARSE_TYPE_STRING 2 /* Takes a string argument. */
+#define ARGPARSE_TYPE_LONG 3 /* Takes a long argument. */
+#define ARGPARSE_TYPE_ULONG 4 /* Takes an unsigned long argument. */
+#define ARGPARSE_OPT_OPTIONAL (1<<3) /* Argument is optional. */
+#define ARGPARSE_OPT_PREFIX (1<<4) /* Allow 0x etc. prefixed values. */
+#define ARGPARSE_OPT_IGNORE (1<<6) /* Ignore command or option. */
+#define ARGPARSE_OPT_COMMAND (1<<7) /* The argument is a command. */
+
+#define ARGPARSE_TYPE_MASK 7 /* Mask for the type values (internal). */
+
+/* A set of macros to make option definitions easier to read. */
+#define ARGPARSE_x(s,l,t,f,d) \
+ { (s), (l), ARGPARSE_TYPE_ ## t | (f), (d) }
+
+#define ARGPARSE_s(s,l,t,d) \
+ { (s), (l), ARGPARSE_TYPE_ ## t, (d) }
+#define ARGPARSE_s_n(s,l,d) \
+ { (s), (l), ARGPARSE_TYPE_NONE, (d) }
+#define ARGPARSE_s_i(s,l,d) \
+ { (s), (l), ARGPARSE_TYPE_INT, (d) }
+#define ARGPARSE_s_s(s,l,d) \
+ { (s), (l), ARGPARSE_TYPE_STRING, (d) }
+#define ARGPARSE_s_l(s,l,d) \
+ { (s), (l), ARGPARSE_TYPE_LONG, (d) }
+#define ARGPARSE_s_u(s,l,d) \
+ { (s), (l), ARGPARSE_TYPE_ULONG, (d) }
+
+#define ARGPARSE_o(s,l,t,d) \
+ { (s), (l), (ARGPARSE_TYPE_ ## t | ARGPARSE_OPT_OPTIONAL), (d) }
+#define ARGPARSE_o_n(s,l,d) \
+ { (s), (l), (ARGPARSE_TYPE_NONE | ARGPARSE_OPT_OPTIONAL), (d) }
+#define ARGPARSE_o_i(s,l,d) \
+ { (s), (l), (ARGPARSE_TYPE_INT | ARGPARSE_OPT_OPTIONAL), (d) }
+#define ARGPARSE_o_s(s,l,d) \
+ { (s), (l), (ARGPARSE_TYPE_STRING | ARGPARSE_OPT_OPTIONAL), (d) }
+#define ARGPARSE_o_l(s,l,d) \
+ { (s), (l), (ARGPARSE_TYPE_LONG | ARGPARSE_OPT_OPTIONAL), (d) }
+#define ARGPARSE_o_u(s,l,d) \
+ { (s), (l), (ARGPARSE_TYPE_ULONG | ARGPARSE_OPT_OPTIONAL), (d) }
+
+#define ARGPARSE_p(s,l,t,d) \
+ { (s), (l), (ARGPARSE_TYPE_ ## t | ARGPARSE_OPT_PREFIX), (d) }
+#define ARGPARSE_p_n(s,l,d) \
+ { (s), (l), (ARGPARSE_TYPE_NONE | ARGPARSE_OPT_PREFIX), (d) }
+#define ARGPARSE_p_i(s,l,d) \
+ { (s), (l), (ARGPARSE_TYPE_INT | ARGPARSE_OPT_PREFIX), (d) }
+#define ARGPARSE_p_s(s,l,d) \
+ { (s), (l), (ARGPARSE_TYPE_STRING | ARGPARSE_OPT_PREFIX), (d) }
+#define ARGPARSE_p_l(s,l,d) \
+ { (s), (l), (ARGPARSE_TYPE_LONG | ARGPARSE_OPT_PREFIX), (d) }
+#define ARGPARSE_p_u(s,l,d) \
+ { (s), (l), (ARGPARSE_TYPE_ULONG | ARGPARSE_OPT_PREFIX), (d) }
+
+#define ARGPARSE_op(s,l,t,d) \
+ { (s), (l), (ARGPARSE_TYPE_ ## t \
+ | ARGPARSE_OPT_OPTIONAL | ARGPARSE_OPT_PREFIX), (d) }
+#define ARGPARSE_op_n(s,l,d) \
+ { (s), (l), (ARGPARSE_TYPE_NONE \
+ | ARGPARSE_OPT_OPTIONAL | ARGPARSE_OPT_PREFIX), (d) }
+#define ARGPARSE_op_i(s,l,d) \
+ { (s), (l), (ARGPARSE_TYPE_INT \
+ | ARGPARSE_OPT_OPTIONAL | ARGPARSE_OPT_PREFIX), (d) }
+#define ARGPARSE_op_s(s,l,d) \
+ { (s), (l), (ARGPARSE_TYPE_STRING \
+ | ARGPARSE_OPT_OPTIONAL | ARGPARSE_OPT_PREFIX), (d) }
+#define ARGPARSE_op_l(s,l,d) \
+ { (s), (l), (ARGPARSE_TYPE_LONG \
+ | ARGPARSE_OPT_OPTIONAL | ARGPARSE_OPT_PREFIX), (d) }
+#define ARGPARSE_op_u(s,l,d) \
+ { (s), (l), (ARGPARSE_TYPE_ULONG \
+ | ARGPARSE_OPT_OPTIONAL | ARGPARSE_OPT_PREFIX), (d) }
+
+#define ARGPARSE_c(s,l,d) \
+ { (s), (l), (ARGPARSE_TYPE_NONE | ARGPARSE_OPT_COMMAND), (d) }
+
+#define ARGPARSE_ignore(s,l) \
+ { (s), (l), (ARGPARSE_OPT_IGNORE), "@" }
+
+#define ARGPARSE_group(s,d) \
+ { (s), NULL, 0, (d) }
+
+#define ARGPARSE_end() { 0, NULL, 0, NULL }
+
+
+/* Other constants. */
+#define ARGPARSE_PRINT_WARNING 1
+#define ARGPARSE_PRINT_ERROR 2
+
+
+/* Error values. */
+#define ARGPARSE_IS_ARG (-1)
+#define ARGPARSE_INVALID_OPTION (-2)
+#define ARGPARSE_MISSING_ARG (-3)
+#define ARGPARSE_KEYWORD_TOO_LONG (-4)
+#define ARGPARSE_READ_ERROR (-5)
+#define ARGPARSE_UNEXPECTED_ARG (-6)
+#define ARGPARSE_INVALID_COMMAND (-7)
+#define ARGPARSE_AMBIGUOUS_OPTION (-8)
+#define ARGPARSE_AMBIGUOUS_COMMAND (-9)
+#define ARGPARSE_INVALID_ALIAS (-10)
+#define ARGPARSE_OUT_OF_CORE (-11)
+#define ARGPARSE_INVALID_ARG (-12)
+
+
+int arg_parse (ARGPARSE_ARGS *arg, ARGPARSE_OPTS *opts);
+int optfile_parse (FILE *fp, const char *filename, unsigned *lineno,
+ ARGPARSE_ARGS *arg, ARGPARSE_OPTS *opts);
+void usage (int level);
+const char *strusage (int level);
+void set_strusage (const char *(*f)( int ));
+void argparse_register_outfnc (int (*fnc)(int, const char *));
+
+#endif /*GNUPG_COMMON_ARGPARSE_H*/
diff --git a/src/assuan-support.c b/src/assuan-support.c
index 745d2aa..2cfdc35 100644
--- a/src/assuan-support.c
+++ b/src/assuan-support.c
@@ -26,6 +26,10 @@ int
_gpgme_assuan_log_cb (assuan_context_t ctx, void *hook,
unsigned int cat, const char *msg)
{
+ (void)ctx;
+ (void)hook;
+ (void)cat;
+
if (msg == NULL)
return 1;
@@ -49,6 +53,8 @@ my_pipe (assuan_context_t ctx, assuan_fd_t fds[2], int inherit_idx)
int res;
int gfds[2];
+ (void)ctx;
+
res = _gpgme_io_pipe (gfds, inherit_idx);
/* For now... */
@@ -64,6 +70,7 @@ my_pipe (assuan_context_t ctx, assuan_fd_t fds[2], int inherit_idx)
static int
my_close (assuan_context_t ctx, assuan_fd_t fd)
{
+ (void)ctx;
return _gpgme_io_close ((int) fd);
}
@@ -71,6 +78,7 @@ my_close (assuan_context_t ctx, assuan_fd_t fd)
static gpgme_ssize_t
my_read (assuan_context_t ctx, assuan_fd_t fd, void *buffer, size_t size)
{
+ (void)ctx;
return _gpgme_io_read ((int) fd, buffer, size);
}
@@ -78,6 +86,7 @@ my_read (assuan_context_t ctx, assuan_fd_t fd, void *buffer, size_t size)
static gpgme_ssize_t
my_write (assuan_context_t ctx, assuan_fd_t fd, const void *buffer, size_t size)
{
+ (void)ctx;
return _gpgme_io_write ((int) fd, buffer, size);
}
@@ -86,6 +95,7 @@ static int
my_recvmsg (assuan_context_t ctx, assuan_fd_t fd, assuan_msghdr_t msg,
int flags)
{
+ (void)ctx;
#ifdef HAVE_W32_SYSTEM
gpg_err_set_errno (ENOSYS);
return -1;
@@ -100,6 +110,7 @@ static int
my_sendmsg (assuan_context_t ctx, assuan_fd_t fd, const assuan_msghdr_t msg,
int flags)
{
+ (void)ctx;
#ifdef HAVE_W32_SYSTEM
gpg_err_set_errno (ENOSYS);
return -1;
@@ -124,6 +135,9 @@ my_spawn (assuan_context_t ctx, pid_t *r_pid, const char *name,
struct spawn_fd_item_s *fd_items;
int i;
+ (void)ctx;
+ (void)flags;
+
assert (name);
if (! name)
@@ -194,6 +208,7 @@ static pid_t
my_waitpid (assuan_context_t ctx, pid_t pid,
int nowait, int *status, int options)
{
+ (void)ctx;
#ifdef HAVE_W32_SYSTEM
CloseHandle ((HANDLE) pid);
#else
@@ -226,6 +241,7 @@ my_socketpair (assuan_context_t ctx, int namespace, int style,
static int
my_socket (assuan_context_t ctx, int namespace, int style, int protocol)
{
+ (void)ctx;
return _gpgme_io_socket (namespace, style, protocol);
}
@@ -234,6 +250,7 @@ static int
my_connect (assuan_context_t ctx, int sock, struct sockaddr *addr,
socklen_t length)
{
+ (void)ctx;
return _gpgme_io_connect (sock, addr, length);
}
diff --git a/src/b64dec.c b/src/b64dec.c
new file mode 100644
index 0000000..7965a30
--- /dev/null
+++ b/src/b64dec.c
@@ -0,0 +1,251 @@
+/* b64dec.c - Simple Base64 decoder.
+ * Copyright (C) 2008, 2011 Free Software Foundation, Inc.
+ * Copyright (C) 2008, 2011, 2016 g10 Code GmbH
+ *
+ * This file is part of GnuPG.
+ *
+ * This file is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License as
+ * published by the Free Software Foundation; either version 2.1 of
+ * the License, or (at your option) any later version.
+ *
+ * This file 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 Lesser General Public License
+ * along with this program; if not, see <http://www.gnu.org/licenses/>.
+ */
+
+#include <config.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <assert.h>
+
+#include "gpgme.h"
+#include "util.h"
+
+
+/* The reverse base-64 list used for base-64 decoding. */
+static unsigned char const asctobin[128] =
+ {
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+ 0xff, 0xff, 0xff, 0x3e, 0xff, 0xff, 0xff, 0x3f,
+ 0x34, 0x35, 0x36, 0x37, 0x38, 0x39, 0x3a, 0x3b,
+ 0x3c, 0x3d, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+ 0xff, 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06,
+ 0x07, 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e,
+ 0x0f, 0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16,
+ 0x17, 0x18, 0x19, 0xff, 0xff, 0xff, 0xff, 0xff,
+ 0xff, 0x1a, 0x1b, 0x1c, 0x1d, 0x1e, 0x1f, 0x20,
+ 0x21, 0x22, 0x23, 0x24, 0x25, 0x26, 0x27, 0x28,
+ 0x29, 0x2a, 0x2b, 0x2c, 0x2d, 0x2e, 0x2f, 0x30,
+ 0x31, 0x32, 0x33, 0xff, 0xff, 0xff, 0xff, 0xff
+ };
+
+enum decoder_states
+ {
+ s_init, s_idle, s_lfseen, s_beginseen, s_waitheader, s_waitblank, s_begin,
+ s_b64_0, s_b64_1, s_b64_2, s_b64_3,
+ s_waitendtitle, s_waitend
+ };
+
+
+
+/* Initialize the context for the base64 decoder. If TITLE is NULL a
+ plain base64 decoding is done. If it is the empty string the
+ decoder will skip everything until a "-----BEGIN " line has been
+ seen, decoding ends at a "----END " line. */
+gpg_error_t
+_gpgme_b64dec_start (struct b64state *state, const char *title)
+{
+ memset (state, 0, sizeof *state);
+ if (title)
+ {
+ state->title = strdup (title);
+ if (!state->title)
+ state->lasterr = gpg_error_from_syserror ();
+ else
+ state->idx = s_init;
+ }
+ else
+ state->idx = s_b64_0;
+ return state->lasterr;
+}
+
+
+/* Do in-place decoding of base-64 data of LENGTH in BUFFER. Stores the
+ new length of the buffer at R_NBYTES. */
+gpg_error_t
+_gpgme_b64dec_proc (struct b64state *state, void *buffer, size_t length,
+ size_t *r_nbytes)
+{
+ enum decoder_states ds = state->idx;
+ unsigned char val = state->radbuf[0];
+ int pos = state->quad_count;
+ char *d, *s;
+
+ if (state->lasterr)
+ return state->lasterr;
+
+ if (state->stop_seen)
+ {
+ *r_nbytes = 0;
+ state->lasterr = gpg_error (GPG_ERR_EOF);
+ free (state->title);
+ state->title = NULL;
+ return state->lasterr;
+ }
+
+ for (s=d=buffer; length && !state->stop_seen; length--, s++)
+ {
+ again:
+ switch (ds)
+ {
+ case s_idle:
+ if (*s == '\n')
+ {
+ ds = s_lfseen;
+ pos = 0;
+ }
+ break;
+ case s_init:
+ ds = s_lfseen;
+ case s_lfseen:
+ if (*s != "-----BEGIN "[pos])
+ {
+ ds = s_idle;
+ goto again;
+ }
+ else if (pos == 10)
+ {
+ pos = 0;
+ ds = s_beginseen;
+ }
+ else
+ pos++;
+ break;
+ case s_beginseen:
+ if (*s != "PGP "[pos])
+ ds = s_begin; /* Not a PGP armor. */
+ else if (pos == 3)
+ ds = s_waitheader;
+ else
+ pos++;
+ break;
+ case s_waitheader:
+ if (*s == '\n')
+ ds = s_waitblank;
+ break;
+ case s_waitblank:
+ if (*s == '\n')
+ ds = s_b64_0; /* blank line found. */
+ else if (*s == ' ' || *s == '\r' || *s == '\t')
+ ; /* Ignore spaces. */
+ else
+ {
+ /* Armor header line. Note that we don't care that our
+ * FSM accepts a header prefixed with spaces. */
+ ds = s_waitheader; /* Wait for next header. */
+ }
+ break;
+ case s_begin:
+ if (*s == '\n')
+ ds = s_b64_0;
+ break;
+ case s_b64_0:
+ case s_b64_1:
+ case s_b64_2:
+ case s_b64_3:
+ {
+ int c;
+
+ if (*s == '-' && state->title)
+ {
+ /* Not a valid Base64 character: assume end
+ header. */
+ ds = s_waitend;
+ }
+ else if (*s == '=')
+ {
+ /* Pad character: stop */
+ if (ds == s_b64_1)
+ *d++ = val;
+ ds = state->title? s_waitendtitle : s_waitend;
+ }
+ else if (*s == '\n' || *s == ' ' || *s == '\r' || *s == '\t')
+ ; /* Skip white spaces. */
+ else if ( (*s & 0x80)
+ || (c = asctobin[*(unsigned char *)s]) == 255)
+ {
+ /* Skip invalid encodings. */
+ state->invalid_encoding = 1;
+ }
+ else if (ds == s_b64_0)
+ {
+ val = c << 2;
+ ds = s_b64_1;
+ }
+ else if (ds == s_b64_1)
+ {
+ val |= (c>>4)&3;
+ *d++ = val;
+ val = (c<<4)&0xf0;
+ ds = s_b64_2;
+ }
+ else if (ds == s_b64_2)
+ {
+ val |= (c>>2)&15;
+ *d++ = val;
+ val = (c<<6)&0xc0;
+ ds = s_b64_3;
+ }
+ else
+ {
+ val |= c&0x3f;
+ *d++ = val;
+ ds = s_b64_0;
+ }
+ }
+ break;
+ case s_waitendtitle:
+ if (*s == '-')
+ ds = s_waitend;
+ break;
+ case s_waitend:
+ if ( *s == '\n')
+ state->stop_seen = 1;
+ break;
+ default:
+ assert (!"invalid state");
+ }
+ }
+
+
+ state->idx = ds;
+ state->radbuf[0] = val;
+ state->quad_count = pos;
+ *r_nbytes = (d -(char*) buffer);
+ return 0;
+}
+
+
+/* This function needs to be called before releasing the decoder
+ state. It may return an error code in case an encoding error has
+ been found during decoding. */
+gpg_error_t
+_gpgme_b64dec_finish (struct b64state *state)
+{
+ if (state->lasterr)
+ return state->lasterr;
+
+ free (state->title);
+ state->title = NULL;
+ return state->invalid_encoding? gpg_error(GPG_ERR_BAD_DATA): 0;
+}
diff --git a/src/context.h b/src/context.h
index 757d9b4..4b12c3b 100644
--- a/src/context.h
+++ b/src/context.h
@@ -38,7 +38,7 @@ typedef enum
OPDATA_DECRYPT, OPDATA_SIGN, OPDATA_ENCRYPT, OPDATA_PASSPHRASE,
OPDATA_IMPORT, OPDATA_GENKEY, OPDATA_KEYLIST, OPDATA_EDIT,
OPDATA_VERIFY, OPDATA_TRUSTLIST, OPDATA_ASSUAN, OPDATA_VFS_MOUNT,
- OPDATA_PASSWD, OPDATA_EXPORT
+ OPDATA_PASSWD, OPDATA_EXPORT, OPDATA_KEYSIGN, OPDATA_TOFU_POLICY
} ctx_op_data_id_t;
@@ -101,6 +101,15 @@ struct gpgme_context
/* True if offline mode should be used. */
unsigned int offline : 1;
+ /* True if a status callback shall be called for nearly all status
+ * lines. */
+ unsigned int full_status : 1;
+
+ /* The Tofu info has a human readable string which is presented to
+ * the user in a directly usable format. By enabling this flag the
+ * unmodified string, as received form gpg, will be returned. */
+ unsigned int raw_description : 1;
+
/* Flags for keylist mode. */
gpgme_keylist_mode_t keylist_mode;
diff --git a/src/conversion.c b/src/conversion.c
index d04a6be..3df8fe5 100644
--- a/src/conversion.c
+++ b/src/conversion.c
@@ -317,6 +317,72 @@ _gpgme_encode_percent_string (const char *src, char **destp, size_t len)
}
+/* Split a string into space delimited fields and remove leading and
+ * trailing spaces from each field. A pointer to the each field is
+ * stored in ARRAY. Stop splitting at ARRAYSIZE fields. The function
+ * modifies STRING. The number of parsed fields is returned.
+ */
+int
+_gpgme_split_fields (char *string, char **array, int arraysize)
+{
+ int n = 0;
+ char *p, *pend;
+
+ for (p = string; *p == ' '; p++)
+ ;
+ do
+ {
+ if (n == arraysize)
+ break;
+ array[n++] = p;
+ pend = strchr (p, ' ');
+ if (!pend)
+ break;
+ *pend++ = 0;
+ for (p = pend; *p == ' '; p++)
+ ;
+ }
+ while (*p);
+
+ return n;
+}
+
+/* Convert the field STRING into an unsigned long value. Check for
+ * trailing garbage. */
+gpgme_error_t
+_gpgme_strtoul_field (const char *string, unsigned long *result)
+{
+ char *endp;
+
+ gpg_err_set_errno (0);
+ *result = strtoul (string, &endp, 0);
+ if (errno)
+ return gpg_error_from_syserror ();
+ if (endp == string || *endp)
+ return gpg_error (GPG_ERR_INV_VALUE);
+ return 0;
+}
+
+
+/* Convert STRING into an offset value. Note that this functions only
+ * allows for a base-10 length. This function is similar to atoi()
+ * and thus there is no error checking. */
+gpgme_off_t
+_gpgme_string_to_off (const char *string)
+{
+ gpgme_off_t value = 0;
+
+ while (*string == ' ' || *string == '\t')
+ string++;
+ for (; *string >= '0' && *string <= '9'; string++)
+ {
+ value *= 10;
+ value += atoi_1 (string);
+ }
+ return value;
+}
+
+
#ifdef HAVE_W32_SYSTEM
static time_t
_gpgme_timegm (struct tm *tm)
@@ -427,6 +493,7 @@ _gpgme_map_pk_algo (int algo, gpgme_protocol_t protocol)
case 18: algo = GPGME_PK_ECDH; break;
case 19: algo = GPGME_PK_ECDSA; break;
case 20: break;
+ case 22: algo = GPGME_PK_EDDSA; break;
default: algo = 0; break; /* Unknown. */
}
}
diff --git a/src/data-compat.c b/src/data-compat.c
index 99827f1..5c7d543 100644
--- a/src/data-compat.c
+++ b/src/data-compat.c
@@ -128,7 +128,7 @@ gpgme_data_new_from_file (gpgme_data_t *r_dh, const char *fname, int copy)
#else
gpgme_error_t err;
struct stat statbuf;
- TRACE_BEG3 (DEBUG_DATA, "gpgme_data_new_from_filepart", r_dh,
+ TRACE_BEG3 (DEBUG_DATA, "gpgme_data_new_from_file", r_dh,
"file_name=%s, copy=%i (%s)", fname, copy, copy ? "yes" : "no");
if (!fname || !copy)
@@ -146,7 +146,7 @@ gpgme_data_new_from_file (gpgme_data_t *r_dh, const char *fname, int copy)
static int
gpgme_error_to_errno (gpgme_error_t err)
{
- int res = gpg_err_code_to_errno (err);
+ int res = gpg_err_code_to_errno (gpg_err_code (err));
if (!err)
{
@@ -187,7 +187,7 @@ old_user_read (gpgme_data_t dh, void *buffer, size_t size)
buffer, size, &amt);
if (err)
return TRACE_SYSRES (gpgme_error_to_errno (err));
- return TRACE_SYSRES (amt);
+ return TRACE_SYSRES ((gpgme_ssize_t)amt);
}
diff --git a/src/data-identify.c b/src/data-identify.c
index 9600633..a5da7f5 100644
--- a/src/data-identify.c
+++ b/src/data-identify.c
@@ -1,5 +1,5 @@
/* data-identify.c - Try to identify the data
- Copyright (C) 2013 g10 Code GmbH
+ Copyright (C) 2013, 2016 g10 Code GmbH
This file is part of GPGME.
@@ -29,17 +29,283 @@
#include "util.h"
#include "parsetlv.h"
+
/* The size of the sample data we take for detection. */
#define SAMPLE_SIZE 2048
+/* OpenPGP packet types. */
+enum
+ {
+ PKT_NONE = 0,
+ PKT_PUBKEY_ENC = 1, /* Public key encrypted packet. */
+ PKT_SIGNATURE = 2, /* Secret key encrypted packet. */
+ PKT_SYMKEY_ENC = 3, /* Session key packet. */
+ PKT_ONEPASS_SIG = 4, /* One pass sig packet. */
+ PKT_SECRET_KEY = 5, /* Secret key. */
+ PKT_PUBLIC_KEY = 6, /* Public key. */
+ PKT_SECRET_SUBKEY = 7, /* Secret subkey. */
+ PKT_COMPRESSED = 8, /* Compressed data packet. */
+ PKT_ENCRYPTED = 9, /* Conventional encrypted data. */
+ PKT_MARKER = 10, /* Marker packet. */
+ PKT_PLAINTEXT = 11, /* Literal data packet. */
+ PKT_RING_TRUST = 12, /* Keyring trust packet. */
+ PKT_USER_ID = 13, /* User id packet. */
+ PKT_PUBLIC_SUBKEY = 14, /* Public subkey. */
+ PKT_OLD_COMMENT = 16, /* Comment packet from an OpenPGP draft. */
+ PKT_ATTRIBUTE = 17, /* PGP's attribute packet. */
+ PKT_ENCRYPTED_MDC = 18, /* Integrity protected encrypted data. */
+ PKT_MDC = 19, /* Manipulation detection code packet. */
+ };
+
+
+static inline unsigned long
+buf32_to_ulong (const void *buffer)
+{
+ const unsigned char *p = buffer;
+
+ return (((unsigned long)p[0] << 24) | (p[1] << 16) | (p[2] << 8) | p[3]);
+}
+
+
+/* Parse the next openpgp packet. This function assumes a valid
+ * OpenPGP packet at the address pointed to by BUFPTR which has a
+ * maximum length as stored at BUFLEN. Return the header information
+ * of that packet and advance the pointer stored at BUFPTR to the next
+ * packet; also adjust the length stored at BUFLEN to match the
+ * remaining bytes. If there are no more packets, store NULL at
+ * BUFPTR. Return an non-zero error code on failure or the following
+ * data on success:
+ *
+ * R_PKTTYPE = The packet type.
+ * R_NTOTAL = The total number of bytes of this packet
+ *
+ * If GPG_ERR_TRUNCATED is returned, a packet type is anyway stored at
+ * R_PKTTYPE but R_NOTAL won't have a usable value,
+ */
+static gpg_error_t
+next_openpgp_packet (unsigned char const **bufptr, size_t *buflen,
+ int *r_pkttype, size_t *r_ntotal)
+{
+ const unsigned char *buf = *bufptr;
+ size_t len = *buflen;
+ int c, ctb, pkttype;
+ unsigned long pktlen;
+
+ if (!len)
+ return gpg_error (GPG_ERR_NO_DATA);
+
+ /* First some blacklisting. */
+ if (len >= 4 && !memcmp (buf, "\x89PNG", 4))
+ return gpg_error (GPG_ERR_INV_PACKET); /* This is a PNG file. */
+
+ /* Start parsing. */
+ ctb = *buf++; len--;
+ if ( !(ctb & 0x80) )
+ return gpg_error (GPG_ERR_INV_PACKET); /* Invalid CTB. */
+
+ if ((ctb & 0x40)) /* New style (OpenPGP) CTB. */
+ {
+ pkttype = (ctb & 0x3f);
+ if (!len)
+ return gpg_error (GPG_ERR_INV_PACKET); /* No 1st length byte. */
+ c = *buf++; len--;
+ if ( c < 192 )
+ pktlen = c;
+ else if ( c < 224 )
+ {
+ pktlen = (c - 192) * 256;
+ if (!len)
+ return gpg_error (GPG_ERR_INV_PACKET); /* No 2nd length byte. */
+ c = *buf++; len--;
+ pktlen += c + 192;
+ }
+ else if (c == 255)
+ {
+ if (len < 4)
+ return gpg_error (GPG_ERR_INV_PACKET); /* No length bytes. */
+ pktlen = buf32_to_ulong (buf);
+ buf += 4;
+ len -= 4;
+ }
+ else /* Partial length encoding. */
+ {
+ pktlen = 0;
+ }
+ }
+ else /* Old style CTB. */
+ {
+ int lenbytes;
+
+ pktlen = 0;
+ pkttype = (ctb>>2)&0xf;
+ lenbytes = ((ctb&3)==3)? 0 : (1<<(ctb & 3));
+ if (len < lenbytes)
+ return gpg_error (GPG_ERR_INV_PACKET); /* Not enough length bytes. */
+ for (; lenbytes; lenbytes--)
+ {
+ pktlen <<= 8;
+ pktlen |= *buf++; len--;
+ }
+ }
+
+ /* Do some basic sanity check. */
+ switch (pkttype)
+ {
+ case PKT_PUBKEY_ENC:
+ case PKT_SIGNATURE:
+ case PKT_SYMKEY_ENC:
+ case PKT_ONEPASS_SIG:
+ case PKT_SECRET_KEY:
+ case PKT_PUBLIC_KEY:
+ case PKT_SECRET_SUBKEY:
+ case PKT_COMPRESSED:
+ case PKT_ENCRYPTED:
+ case PKT_MARKER:
+ case PKT_PLAINTEXT:
+ case PKT_RING_TRUST:
+ case PKT_USER_ID:
+ case PKT_PUBLIC_SUBKEY:
+ case PKT_OLD_COMMENT:
+ case PKT_ATTRIBUTE:
+ case PKT_ENCRYPTED_MDC:
+ case PKT_MDC:
+ break; /* Okay these are allowed packets. */
+ default:
+ return gpg_error (GPG_ERR_UNEXPECTED);
+ }
+
+ if (pktlen > len)
+ {
+ /* Packet length header too long. This is possible because we
+ * may have only a truncated image. */
+ *r_pkttype = pkttype;
+ *r_ntotal = 0;
+ *bufptr = NULL;
+ return gpg_error (GPG_ERR_TRUNCATED);
+ }
+
+ *r_pkttype = pkttype;
+ *r_ntotal = (buf - *bufptr) + pktlen;
+
+ *bufptr = buf + pktlen;
+ *buflen = len - pktlen;
+ if (!*buflen)
+ *bufptr = NULL;
+
+ return 0;
+}
+
+
+/* Detection of PGP binary data. This function parses an OpenPGP
+ * message. This parser is robust enough to work on a truncated
+ * version. Returns a GPGME_DATA_TYPE_. */
+static gpgme_data_type_t
+pgp_binary_detection (const void *image_arg, size_t imagelen)
+{
+ gpg_error_t err = 0;
+ const unsigned char *image = image_arg;
+ size_t n;
+ int pkttype;
+ int anypacket = 0;
+ int allsignatures = 0;
+
+ while (!err && image)
+ {
+ err = next_openpgp_packet (&image, &imagelen, &pkttype, &n);
+ if (gpg_err_code (err) == GPG_ERR_TRUNCATED)
+ ;
+ else if (err)
+ break;
+
+ /* Skip all leading marker packets. */
+ if (!anypacket && pkttype == PKT_MARKER)
+ continue;
+
+ if (pkttype == PKT_SIGNATURE)
+ {
+ if (!anypacket)
+ allsignatures = 1;
+ }
+ else
+ allsignatures = 0;
+
+ switch (pkttype)
+ {
+ case PKT_SIGNATURE:
+ break; /* We decide later. */
+
+ case PKT_PLAINTEXT:
+ /* Old style signature format: {sig}+,plaintext */
+ if (allsignatures)
+ return GPGME_DATA_TYPE_PGP_SIGNED;
+ break;
+
+ case PKT_ONEPASS_SIG:
+ return GPGME_DATA_TYPE_PGP_SIGNED;
+
+ case PKT_SECRET_KEY:
+ case PKT_PUBLIC_KEY:
+ return GPGME_DATA_TYPE_PGP_KEY;
+
+ case PKT_SECRET_SUBKEY:
+ case PKT_PUBLIC_SUBKEY:
+ return GPGME_DATA_TYPE_PGP_OTHER;
+ case PKT_PUBKEY_ENC:
+ case PKT_SYMKEY_ENC:
+ return GPGME_DATA_TYPE_PGP_ENCRYPTED;
+
+ case PKT_COMPRESSED:
+ /* If this is the first packet we assume that that a signed
+ * packet follows. We do not want to uncompress it here due
+ * to the need of a lot of code and the potentail DoS. */
+ if (!anypacket)
+ return GPGME_DATA_TYPE_PGP_SIGNED;
+ return GPGME_DATA_TYPE_PGP_OTHER;
+
+ default:
+ return GPGME_DATA_TYPE_PGP_OTHER;
+ }
+ anypacket = 1;
+ }
+
+ if (allsignatures)
+ return GPGME_DATA_TYPE_PGP_SIGNATURE;
+
+ return GPGME_DATA_TYPE_UNKNOWN;
+}
+
+
+/* This is probably an armored "PGP MESSAGE" which can encode
+ * different PGP data types. STRING is modified after a call to this
+ * fucntion. */
+static gpgme_data_type_t
+inspect_pgp_message (char *string)
+{
+ struct b64state state;
+ size_t nbytes;
+
+ if (_gpgme_b64dec_start (&state, ""))
+ return GPGME_DATA_TYPE_INVALID; /* oops */
+
+ if (_gpgme_b64dec_proc (&state, string, strlen (string), &nbytes))
+ {
+ _gpgme_b64dec_finish (&state);
+ return GPGME_DATA_TYPE_UNKNOWN; /* bad encoding etc. */
+ }
+ _gpgme_b64dec_finish (&state);
+ string[nbytes] = 0; /* Better append a Nul. */
+
+ return pgp_binary_detection (string, nbytes);
+}
+
/* Note that DATA may be binary but a final nul is required so that
string operations will find a terminator.
Returns: GPGME_DATA_TYPE_xxxx */
static gpgme_data_type_t
-basic_detection (const char *data, size_t datalen)
+basic_detection (char *data, size_t datalen)
{
tlvinfo_t ti;
const char *s;
@@ -167,7 +433,7 @@ basic_detection (const char *data, size_t datalen)
at all defined and in any case it is uncommon. Thus we don't
do any further plausibility checks but stupidly assume no CMS
armored data will follow. */
- return GPGME_DATA_TYPE_UNKNOWN;
+ return pgp_binary_detection (data, datalen);
}
/* Now check whether there are armor lines. */
@@ -182,7 +448,7 @@ basic_detection (const char *data, size_t datalen)
if (!strncmp (s+11, "PGP ", 4))
{
if (!strncmp (s+15, "SIGNATURE", 9))
- return GPGME_DATA_TYPE_PGP_SIGNED;
+ return GPGME_DATA_TYPE_PGP_SIGNATURE;
if (!strncmp (s+15, "SIGNED MESSAGE", 14))
return GPGME_DATA_TYPE_PGP_SIGNED;
if (!strncmp (s+15, "PUBLIC KEY BLOCK", 16))
@@ -193,7 +459,8 @@ basic_detection (const char *data, size_t datalen)
return GPGME_DATA_TYPE_PGP_KEY;
if (!strncmp (s+15, "ARMORED FILE", 12))
return GPGME_DATA_TYPE_UNKNOWN;
- return GPGME_DATA_TYPE_PGP_OTHER; /* PGP MESSAGE */
+
+ return inspect_pgp_message (data);
}
if (!strncmp (s+11, "CERTIFICATE", 11))
return GPGME_DATA_TYPE_X509_CERT;
@@ -222,6 +489,8 @@ gpgme_data_identify (gpgme_data_t dh, int reserved)
int n;
gpgme_off_t off;
+ (void)reserved;
+
/* Check whether we can seek the data object. */
off = gpgme_data_seek (dh, 0, SEEK_CUR);
if (off == (gpgme_off_t)(-1))
diff --git a/src/data-mem.c b/src/data-mem.c
index e06a920..a498b82 100644
--- a/src/data-mem.c
+++ b/src/data-mem.c
@@ -271,7 +271,8 @@ gpgme_data_release_and_get_mem (gpgme_data_t dh, size_t *r_len)
}
-/* Release the memory returned by gpgme_data_release_and_get_mem(). */
+/* Release the memory returned by gpgme_data_release_and_get_mem() and
+ some other functions. */
void
gpgme_free (void *buffer)
{
diff --git a/src/data.c b/src/data.c
index 7123a82..6964246 100644
--- a/src/data.c
+++ b/src/data.c
@@ -193,7 +193,7 @@ gpgme_data_set_encoding (gpgme_data_t dh, gpgme_data_encoding_t enc)
"encoding=%i", enc);
if (!dh)
return TRACE_ERR (gpg_error (GPG_ERR_INV_VALUE));
- if (enc < 0 || enc > GPGME_DATA_ENCODING_URL0)
+ if (enc < 0 || enc > GPGME_DATA_ENCODING_MIME)
return TRACE_ERR (gpg_error (GPG_ERR_INV_VALUE));
dh->encoding = enc;
return TRACE_ERR (0);
@@ -243,6 +243,28 @@ gpgme_data_get_file_name (gpgme_data_t dh)
return dh->file_name;
}
+
+/* Set a flag for the data object DH. See the manual for details. */
+gpg_error_t
+gpgme_data_set_flag (gpgme_data_t dh, const char *name, const char *value)
+{
+ TRACE_BEG2 (DEBUG_DATA, "gpgme_data_set_flag", dh,
+ "%s=%s", name, value);
+
+ if (!dh)
+ return TRACE_ERR (gpg_error (GPG_ERR_INV_VALUE));
+
+ if (!strcmp (name, "size-hint"))
+ {
+ dh->size_hint= value? _gpgme_string_to_off (value) : 0;
+ }
+ else
+ return gpg_error (GPG_ERR_UNKNOWN_NAME);
+
+ return 0;
+}
+
+
/* Functions to support the wait interface. */
@@ -334,3 +356,11 @@ _gpgme_data_get_fd (gpgme_data_t dh)
return -1;
return (*dh->cbs->get_fd) (dh);
}
+
+
+/* Get the size-hint value for DH or 0 if not available. */
+gpgme_off_t
+_gpgme_data_get_size_hint (gpgme_data_t dh)
+{
+ return dh ? dh->size_hint : 0;
+}
diff --git a/src/data.h b/src/data.h
index 3d404af..0a15b61 100644
--- a/src/data.h
+++ b/src/data.h
@@ -89,6 +89,9 @@ struct gpgme_data
/* File name of the data object. */
char *file_name;
+ /* Hint on the to be expected toatl size of the data. */
+ gpgme_off_t size_hint;
+
union
{
/* For gpgme_data_new_from_fd. */
@@ -134,4 +137,7 @@ void _gpgme_data_release (gpgme_data_t dh);
return -1. */
int _gpgme_data_get_fd (gpgme_data_t dh);
+/* Get the size-hint value for DH or 0 if not available. */
+gpgme_off_t _gpgme_data_get_size_hint (gpgme_data_t dh);
+
#endif /* DATA_H */
diff --git a/src/decrypt.c b/src/decrypt.c
index 4db68a1..51e4292 100644
--- a/src/decrypt.c
+++ b/src/decrypt.c
@@ -303,7 +303,7 @@ _gpgme_decrypt_status_handler (void *priv, gpgme_status_code_t code,
break;
case GPGME_STATUS_INQUIRE_MAXLEN:
- if (ctx->status_cb)
+ if (ctx->status_cb && !ctx->full_status)
{
err = ctx->status_cb (ctx->status_cb_value, "INQUIRE_MAXLEN", args);
if (err)
diff --git a/src/delete.c b/src/delete.c
index 37e54f8..fc99aac 100644
--- a/src/delete.c
+++ b/src/delete.c
@@ -33,6 +33,8 @@
static gpgme_error_t
delete_status_handler (void *priv, gpgme_status_code_t code, char *args)
{
+ (void)priv;
+
if (code == GPGME_STATUS_DELETE_PROBLEM)
{
enum delete_problem
@@ -64,8 +66,40 @@ delete_status_handler (void *priv, gpgme_status_code_t code, char *args)
case DELETE_Ambiguous_Specification:
return gpg_error (GPG_ERR_AMBIGUOUS_NAME);
- default:
- return gpg_error (GPG_ERR_GENERAL);
+ }
+
+ return gpg_error (GPG_ERR_GENERAL);
+ }
+ else if (code == GPGME_STATUS_ERROR)
+ {
+ /* Some error stati are informational, so we don't return an
+ error code if we are not ready to process this status. */
+ gpgme_error_t err;
+ char *where = strchr (args, ' ');
+ char *which;
+
+ if (where)
+ {
+ *where = '\0';
+ which = where + 1;
+
+ where = strchr (which, ' ');
+ if (where)
+ *where = '\0';
+
+ where = args;
+ }
+ else
+ return trace_gpg_error (GPG_ERR_INV_ENGINE);
+
+ err = atoi (which);
+
+ if (!strcmp (where, "delete_key.secret")
+ && (gpg_err_code (err) == GPG_ERR_CANCELED
+ || gpg_err_code (err) == GPG_ERR_FULLY_CANCELED))
+ {
+ /* This indicates a user cancellation on the confirmation dialog. */
+ return gpg_error (gpg_err_code (err));
}
}
return 0;
diff --git a/src/dirinfo.c b/src/dirinfo.c
index 8824c9a..b24a8a0 100644
--- a/src/dirinfo.c
+++ b/src/dirinfo.c
@@ -37,12 +37,20 @@ DEFINE_STATIC_LOCK (dirinfo_lock);
enum
{
WANT_HOMEDIR,
+ WANT_SYSCONFDIR,
+ WANT_BINDIR,
+ WANT_LIBEXECDIR,
+ WANT_LIBDIR,
+ WANT_DATADIR,
+ WANT_LOCALEDIR,
WANT_AGENT_SOCKET,
+ WANT_AGENT_SSH_SOCKET,
+ WANT_DIRMNGR_SOCKET,
+ WANT_UISRV_SOCKET,
WANT_GPGCONF_NAME,
WANT_GPG_NAME,
WANT_GPGSM_NAME,
WANT_G13_NAME,
- WANT_UISRV_SOCKET,
WANT_GPG_ONE_MODE
};
@@ -51,12 +59,20 @@ static struct {
int valid; /* Cached information is valid. */
int disable_gpgconf;
char *homedir;
+ char *sysconfdir;
+ char *bindir;
+ char *libexecdir;
+ char *libdir;
+ char *datadir;
+ char *localedir;
char *agent_socket;
+ char *agent_ssh_socket;
+ char *dirmngr_socket;
+ char *uisrv_socket;
char *gpgconf_name;
char *gpg_name;
char *gpgsm_name;
char *g13_name;
- char *uisrv_socket;
int gpg_one_mode; /* System is in gpg1 mode. */
} dirinfo;
@@ -70,6 +86,15 @@ _gpgme_dirinfo_disable_gpgconf (void)
}
+/* Return the length of the directory part including the trailing
+ * slash of NAME. */
+static size_t
+dirname_len (const char *name)
+{
+ return _gpgme_get_basename (name) - name;
+}
+
+
/* Parse the output of "gpgconf --list-dirs". This function expects
that DIRINFO_LOCK is held by the caller. If COMPONENTS is set, the
output of --list-components is expected. */
@@ -77,6 +102,7 @@ static void
parse_output (char *line, int components)
{
char *value, *p;
+ size_t n;
value = strchr (line, ':');
if (!value)
@@ -110,22 +136,41 @@ parse_output (char *line, int components)
else
{
if (!strcmp (line, "homedir") && !dirinfo.homedir)
+ dirinfo.homedir = strdup (value);
+ else if (!strcmp (line, "sysconfdir") && !dirinfo.sysconfdir)
+ dirinfo.sysconfdir = strdup (value);
+ else if (!strcmp (line, "bindir") && !dirinfo.bindir)
+ dirinfo.bindir = strdup (value);
+ else if (!strcmp (line, "libexecdir") && !dirinfo.libexecdir)
+ dirinfo.libexecdir = strdup (value);
+ else if (!strcmp (line, "libdir") && !dirinfo.libdir)
+ dirinfo.libdir = strdup (value);
+ else if (!strcmp (line, "datadir") && !dirinfo.datadir)
+ dirinfo.datadir = strdup (value);
+ else if (!strcmp (line, "localedir") && !dirinfo.localedir)
+ dirinfo.localedir = strdup (value);
+ else if (!strcmp (line, "agent-socket") && !dirinfo.agent_socket)
{
const char name[] = "S.uiserver";
+ char *buffer;
- dirinfo.homedir = strdup (value);
- if (dirinfo.homedir)
+ dirinfo.agent_socket = strdup (value);
+ if (dirinfo.agent_socket)
{
- dirinfo.uisrv_socket = malloc (strlen (dirinfo
- .homedir)
- + 1 + strlen (name) + 1);
- if (dirinfo.uisrv_socket)
- strcpy (stpcpy (stpcpy (dirinfo.uisrv_socket, dirinfo.homedir),
- DIRSEP_S), name);
+ n = dirname_len (dirinfo.agent_socket);
+ buffer = malloc (n + strlen (name) + 1);
+ if (buffer)
+ {
+ strncpy (buffer, dirinfo.agent_socket, n);
+ strcpy (buffer + n, name);
+ dirinfo.uisrv_socket = buffer;
+ }
}
}
- else if (!strcmp (line, "agent-socket") && !dirinfo.agent_socket)
- dirinfo.agent_socket = strdup (value);
+ else if (!strcmp (line, "dirmngr-socket") && !dirinfo.dirmngr_socket)
+ dirinfo.dirmngr_socket = strdup (value);
+ else if (!strcmp (line, "agent-ssh-socket") && !dirinfo.agent_ssh_socket)
+ dirinfo.agent_ssh_socket = strdup (value);
}
}
@@ -148,7 +193,7 @@ read_gpgconf_dirs (const char *pgmname, int components)
char *mark = NULL;
argv[0] = (char *)pgmname;
- argv[1] = components? "--list-components" : "--list-dirs";
+ argv[1] = (char*)(components? "--list-components" : "--list-dirs");
argv[2] = NULL;
if (_gpgme_io_pipe (rp, 1) < 0)
@@ -260,14 +305,28 @@ get_gpgconf_item (int what)
if (dirinfo.agent_socket)
_gpgme_debug (DEBUG_INIT, "gpgme-dinfo: agent='%s'\n",
dirinfo.agent_socket);
+ if (dirinfo.agent_ssh_socket)
+ _gpgme_debug (DEBUG_INIT, "gpgme-dinfo: ssh='%s'\n",
+ dirinfo.agent_ssh_socket);
+ if (dirinfo.dirmngr_socket)
+ _gpgme_debug (DEBUG_INIT, "gpgme-dinfo: dirmngr='%s'\n",
+ dirinfo.dirmngr_socket);
if (dirinfo.uisrv_socket)
_gpgme_debug (DEBUG_INIT, "gpgme-dinfo: uisrv='%s'\n",
dirinfo.uisrv_socket);
}
switch (what)
{
- case WANT_HOMEDIR: result = dirinfo.homedir; break;
+ case WANT_HOMEDIR: result = dirinfo.homedir; break;
+ case WANT_SYSCONFDIR: result = dirinfo.sysconfdir; break;
+ case WANT_BINDIR: result = dirinfo.bindir; break;
+ case WANT_LIBEXECDIR: result = dirinfo.libexecdir; break;
+ case WANT_LIBDIR: result = dirinfo.libdir; break;
+ case WANT_DATADIR: result = dirinfo.datadir; break;
+ case WANT_LOCALEDIR: result = dirinfo.localedir; break;
case WANT_AGENT_SOCKET: result = dirinfo.agent_socket; break;
+ case WANT_AGENT_SSH_SOCKET: result = dirinfo.agent_ssh_socket; break;
+ case WANT_DIRMNGR_SOCKET: result = dirinfo.dirmngr_socket; break;
case WANT_GPGCONF_NAME: result = dirinfo.gpgconf_name; break;
case WANT_GPG_NAME: result = dirinfo.gpg_name; break;
case WANT_GPGSM_NAME: result = dirinfo.gpgsm_name; break;
@@ -379,6 +438,22 @@ gpgme_get_dirinfo (const char *what)
return get_gpgconf_item (WANT_GPGSM_NAME);
else if (!strcmp (what, "g13-name"))
return get_gpgconf_item (WANT_G13_NAME);
+ else if (!strcmp (what, "agent-ssh-socket"))
+ return get_gpgconf_item (WANT_AGENT_SSH_SOCKET);
+ else if (!strcmp (what, "dirmngr-socket"))
+ return get_gpgconf_item (WANT_DIRMNGR_SOCKET);
+ else if (!strcmp (what, "sysconfdir"))
+ return get_gpgconf_item (WANT_SYSCONFDIR);
+ else if (!strcmp (what, "bindir"))
+ return get_gpgconf_item (WANT_BINDIR);
+ else if (!strcmp (what, "libexecdir"))
+ return get_gpgconf_item (WANT_LIBEXECDIR);
+ else if (!strcmp (what, "libdir"))
+ return get_gpgconf_item (WANT_LIBDIR);
+ else if (!strcmp (what, "datadir"))
+ return get_gpgconf_item (WANT_DATADIR);
+ else if (!strcmp (what, "localedir"))
+ return get_gpgconf_item (WANT_LOCALEDIR);
else
return NULL;
}
diff --git a/src/edit.c b/src/edit.c
index 72fa458..887af73 100644
--- a/src/edit.c
+++ b/src/edit.c
@@ -27,12 +27,15 @@
#include "debug.h"
#include "context.h"
#include "ops.h"
+#include "util.h"
+
typedef struct
{
/* The user callback function and its hook value. */
- gpgme_edit_cb_t fnc;
+ gpgme_interact_cb_t fnc;
+ gpgme_edit_cb_t fnc_old;
void *fnc_value;
} *op_data_t;
@@ -58,7 +61,11 @@ edit_status_handler (void *priv, gpgme_status_code_t status, char *args)
if (err)
return err;
- return (*opd->fnc) (opd->fnc_value, status, args, -1);
+ if (opd->fnc_old)
+ return (*opd->fnc_old) (opd->fnc_value, status, args, -1);
+
+ return (*opd->fnc) (opd->fnc_value, _gpgme_status_to_string (status),
+ args, -1);
}
@@ -77,6 +84,8 @@ command_handler (void *priv, gpgme_status_code_t status, const char *args,
if (err)
return err;
}
+ else
+ err = 0;
if (!processed)
{
@@ -88,20 +97,105 @@ command_handler (void *priv, gpgme_status_code_t status, const char *args,
if (err)
return err;
- /* FIXME: We expect the user to handle _all_ status codes.
- Later, we may fix the callback interface to allow the user
- indicate if it processed the status code or not. */
- *processed_r = 1;
+ if (opd->fnc_old)
+ err = (*opd->fnc_old) (opd->fnc_value, status, args, fd);
+ else
+ err = (*opd->fnc) (opd->fnc_value, _gpgme_status_to_string (status),
+ args, fd);
- return (*opd->fnc) (opd->fnc_value, status, args, fd);
+ if (gpg_err_code (err) == GPG_ERR_FALSE)
+ err = 0;
+ else
+ processed = 1;
}
*processed_r = processed;
- return 0;
+ return err;
}
static gpgme_error_t
+interact_start (gpgme_ctx_t ctx, int synchronous, gpgme_key_t key,
+ unsigned int flags,
+ gpgme_interact_cb_t fnc, void *fnc_value, gpgme_data_t out)
+{
+ gpgme_error_t err;
+ void *hook;
+ op_data_t opd;
+
+ err = _gpgme_op_reset (ctx, synchronous);
+ if (err)
+ return err;
+
+ if (!fnc || !out)
+ return gpg_error (GPG_ERR_INV_VALUE);
+
+ err = _gpgme_op_data_lookup (ctx, OPDATA_EDIT, &hook, sizeof (*opd), NULL);
+ opd = hook;
+ if (err)
+ return err;
+
+ opd->fnc = fnc;
+ opd->fnc_old = NULL;
+ opd->fnc_value = fnc_value;
+
+ err = _gpgme_engine_set_command_handler (ctx->engine, command_handler,
+ ctx, out);
+ if (err)
+ return err;
+
+ _gpgme_engine_set_status_handler (ctx->engine, edit_status_handler, ctx);
+
+ return _gpgme_engine_op_edit (ctx->engine,
+ (flags & GPGME_INTERACT_CARD)? 1: 0,
+ key, out, ctx);
+}
+
+
+gpgme_error_t
+gpgme_op_interact_start (gpgme_ctx_t ctx, gpgme_key_t key, unsigned int flags,
+ gpgme_interact_cb_t fnc, void *fnc_value,
+ gpgme_data_t out)
+{
+ gpgme_error_t err;
+
+ TRACE_BEG5 (DEBUG_CTX, "gpgme_op_interact_start", ctx,
+ "key=%p flags=0x%x fnc=%p fnc_value=%p, out=%p",
+ key, flags,fnc, fnc_value, out);
+
+ if (!ctx)
+ return TRACE_ERR (gpg_error (GPG_ERR_INV_VALUE));
+
+ err = interact_start (ctx, 0, key, flags, fnc, fnc_value, out);
+ return err;
+}
+
+
+gpgme_error_t
+gpgme_op_interact (gpgme_ctx_t ctx, gpgme_key_t key, unsigned int flags,
+ gpgme_interact_cb_t fnc, void *fnc_value,
+ gpgme_data_t out)
+{
+ gpgme_error_t err;
+
+ TRACE_BEG5 (DEBUG_CTX, "gpgme_op_interact", ctx,
+ "key=%p flags=0x%x fnc=%p fnc_value=%p, out=%p",
+ key, flags,fnc, fnc_value, out);
+
+ if (!ctx)
+ return TRACE_ERR (gpg_error (GPG_ERR_INV_VALUE));
+
+ err = interact_start (ctx, 1, key, flags, fnc, fnc_value, out);
+ if (!err)
+ err = _gpgme_wait_one (ctx);
+ return err;
+}
+
+
+
+
+/* The deprectated interface. */
+static gpgme_error_t
edit_start (gpgme_ctx_t ctx, int synchronous, int type, gpgme_key_t key,
gpgme_edit_cb_t fnc, void *fnc_value, gpgme_data_t out)
{
@@ -121,7 +215,8 @@ edit_start (gpgme_ctx_t ctx, int synchronous, int type, gpgme_key_t key,
if (err)
return err;
- opd->fnc = fnc;
+ opd->fnc = NULL;
+ opd->fnc_old = fnc;
opd->fnc_value = fnc_value;
err = _gpgme_engine_set_command_handler (ctx->engine, command_handler,
diff --git a/src/encrypt-sign.c b/src/encrypt-sign.c
index 4f484e9..af6de63 100644
--- a/src/encrypt-sign.c
+++ b/src/encrypt-sign.c
@@ -72,7 +72,7 @@ encrypt_sign_start (gpgme_ctx_t ctx, int synchronous, gpgme_key_t recp[],
if (err)
return err;
- symmetric = !recp;
+ symmetric = !recp || (flags & GPGME_ENCRYPT_SYMMETRIC);
if (!plain)
return gpg_error (GPG_ERR_NO_DATA);
diff --git a/src/encrypt.c b/src/encrypt.c
index 9f5134d..4023654 100644
--- a/src/encrypt.c
+++ b/src/encrypt.c
@@ -39,6 +39,12 @@ typedef struct
/* The error code from a FAILURE status line or 0. */
gpg_error_t failure_code;
+ /* The fingerprint from the last KEY_CONSIDERED status line. */
+ char *kc_fpr;
+
+ /* The flags from the last KEY_CONSIDERED status line. */
+ unsigned int kc_flags;
+
/* A pointer to the next pointer of the last invalid recipient in
the list. This makes appending new invalid recipients painless
while preserving the order. */
@@ -60,6 +66,8 @@ release_op_data (void *hook)
free (invalid_recipient);
invalid_recipient = next;
}
+
+ free (opd->kc_fpr);
}
@@ -128,12 +136,26 @@ _gpgme_encrypt_status_handler (void *priv, gpgme_status_code_t code,
return opd->failure_code;
break;
+ case GPGME_STATUS_KEY_CONSIDERED:
+ /* This is emitted during gpg's key lookup to give information
+ * about the lookup results. We store the last one so it can be
+ * used in connection with INV_RECP. */
+ free (opd->kc_fpr);
+ opd->kc_fpr = NULL;
+ err = _gpgme_parse_key_considered (args, &opd->kc_fpr, &opd->kc_flags);
+ if (err)
+ return err;
+ break;
+
case GPGME_STATUS_INV_RECP:
- err = _gpgme_parse_inv_recp (args, opd->lastp);
+ err = _gpgme_parse_inv_recp (args, 0, opd->kc_fpr, opd->kc_flags,
+ opd->lastp);
if (err)
- return err;
+ return err;
opd->lastp = &(*opd->lastp)->next;
+ free (opd->kc_fpr);
+ opd->kc_fpr = NULL;
break;
case GPGME_STATUS_NO_RECP:
@@ -162,8 +184,13 @@ encrypt_sym_status_handler (void *priv, gpgme_status_code_t code, char *args)
static gpgme_error_t
encrypt_status_handler (void *priv, gpgme_status_code_t code, char *args)
{
- return _gpgme_progress_status_handler (priv, code, args)
- || _gpgme_encrypt_status_handler (priv, code, args);
+ gpgme_error_t err;
+
+ err = _gpgme_progress_status_handler (priv, code, args);
+ if (!err)
+ err = _gpgme_encrypt_status_handler (priv, code, args);
+
+ return err;
}
@@ -201,8 +228,7 @@ encrypt_start (gpgme_ctx_t ctx, int synchronous, gpgme_key_t recp[],
if (err)
return err;
- if (!recp)
- symmetric = 1;
+ symmetric = !recp || (flags & GPGME_ENCRYPT_SYMMETRIC);
if (!plain)
return gpg_error (GPG_ERR_NO_DATA);
diff --git a/src/engine-assuan.c b/src/engine-assuan.c
index 9902467..65924eb 100644
--- a/src/engine-assuan.c
+++ b/src/engine-assuan.c
@@ -131,14 +131,15 @@ llass_get_home_dir (void)
static char *
llass_get_version (const char *file_name)
{
- return strdup ("1.0");
+ (void)file_name;
+ return NULL;
}
static const char *
llass_get_req_version (void)
{
- return "1.0";
+ return NULL;
}
@@ -212,11 +213,15 @@ llass_release (void *engine)
/* Create a new instance. If HOME_DIR is NULL standard options for use
with gpg-agent are issued. */
static gpgme_error_t
-llass_new (void **engine, const char *file_name, const char *home_dir)
+llass_new (void **engine, const char *file_name, const char *home_dir,
+ const char *version)
{
gpgme_error_t err = 0;
engine_llass_t llass;
char *optstr;
+ char *env_tty = NULL;
+
+ (void)version; /* Not yet used. */
llass = calloc (1, sizeof *llass);
if (!llass)
@@ -245,6 +250,7 @@ llass_new (void **engine, const char *file_name, const char *home_dir)
if (err)
goto leave;
assuan_ctx_set_system_hooks (llass->assuan_ctx, &_gpgme_assuan_system_hooks);
+ assuan_set_flag (llass->assuan_ctx, ASSUAN_CONVEY_COMMENTS, 1);
err = assuan_socket_connect (llass->assuan_ctx, file_name, 0, 0);
if (err)
@@ -275,13 +281,24 @@ llass_new (void **engine, const char *file_name, const char *home_dir)
}
}
- if (llass->opt.gpg_agent && isatty (1))
+ if (llass->opt.gpg_agent)
+ err = _gpgme_getenv ("GPG_TTY", &env_tty);
+
+ if (llass->opt.gpg_agent && (isatty (1) || env_tty || err))
{
- int rc;
+ int rc = 0;
char dft_ttyname[64];
char *dft_ttytype = NULL;
- rc = ttyname_r (1, dft_ttyname, sizeof (dft_ttyname));
+ if (err)
+ goto leave;
+ else if (env_tty)
+ {
+ snprintf (dft_ttyname, sizeof (dft_ttyname), "%s", env_tty);
+ free (env_tty);
+ }
+ else
+ rc = ttyname_r (1, dft_ttyname, sizeof (dft_ttyname));
/* Even though isatty() returns 1, ttyname_r() may fail in many
ways, e.g., when /dev/pts is not accessible under chroot. */
@@ -354,7 +371,7 @@ llass_set_locale (void *engine, int category, const char *value)
gpgme_error_t err;
engine_llass_t llass = engine;
char *optstr;
- char *catstr;
+ const char *catstr;
if (!llass->opt.gpg_agent)
return 0;
@@ -752,6 +769,7 @@ struct engine_ops _gpgme_engine_ops_assuan =
/* Member functions. */
llass_release,
NULL, /* reset */
+ NULL, /* set_status_cb */
NULL, /* set_status_handler */
NULL, /* set_command_handler */
NULL, /* set_colon_line_handler */
@@ -769,6 +787,8 @@ struct engine_ops _gpgme_engine_ops_assuan =
NULL, /* import */
NULL, /* keylist */
NULL, /* keylist_ext */
+ NULL, /* keysign */
+ NULL, /* tofu_policy */
NULL, /* sign */
NULL, /* trustlist */
NULL, /* verify */
diff --git a/src/engine-backend.h b/src/engine-backend.h
index 4f4519c..ccab0e3 100644
--- a/src/engine-backend.h
+++ b/src/engine-backend.h
@@ -44,11 +44,13 @@ struct engine_ops
const char *(*get_req_version) (void);
gpgme_error_t (*new) (void **r_engine,
- const char *file_name, const char *home_dir);
+ const char *file_name, const char *home_dir,
+ const char *version);
/* Member functions. */
void (*release) (void *engine);
gpgme_error_t (*reset) (void *engine);
+ void (*set_status_cb) (void *engine, gpgme_status_cb_t cb, void *cb_value);
void (*set_status_handler) (void *engine, engine_status_handler_t fnc,
void *fnc_value);
gpgme_error_t (*set_command_handler) (void *engine,
@@ -80,7 +82,12 @@ struct engine_ops
gpgme_error_t (*export_ext) (void *engine, const char *pattern[],
gpgme_export_mode_t mode, gpgme_data_t keydata,
int use_armor);
- gpgme_error_t (*genkey) (void *engine, gpgme_data_t help_data, int use_armor,
+ gpgme_error_t (*genkey) (void *engine,
+ const char *userid, const char *algo,
+ unsigned long reserved, unsigned long expires,
+ gpgme_key_t key, unsigned int flags,
+ gpgme_data_t help_data,
+ unsigned int extraflags,
gpgme_data_t pubkey, gpgme_data_t seckey);
gpgme_error_t (*import) (void *engine, gpgme_data_t keydata,
gpgme_key_t *keyarray);
@@ -91,6 +98,13 @@ struct engine_ops
int secret_only, int reserved,
gpgme_keylist_mode_t mode,
int engine_flags);
+ gpgme_error_t (*keysign) (void *engine,
+ gpgme_key_t key, const char *userid,
+ unsigned long expires, unsigned int flags,
+ gpgme_ctx_t ctx);
+ gpgme_error_t (*tofu_policy) (void *engine,
+ gpgme_key_t key,
+ gpgme_tofu_policy_t policy);
gpgme_error_t (*sign) (void *engine, gpgme_data_t in, gpgme_data_t out,
gpgme_sig_mode_t mode, int use_armor,
int use_textmode, int include_certs,
diff --git a/src/engine-g13.c b/src/engine-g13.c
index 4a7b75c..d34db82 100644
--- a/src/engine-g13.c
+++ b/src/engine-g13.c
@@ -212,7 +212,8 @@ g13_release (void *engine)
static gpgme_error_t
-g13_new (void **engine, const char *file_name, const char *home_dir)
+g13_new (void **engine, const char *file_name, const char *home_dir,
+ const char *version)
{
gpgme_error_t err = 0;
engine_g13_t g13;
@@ -221,9 +222,12 @@ g13_new (void **engine, const char *file_name, const char *home_dir)
const char *argv[5];
char *dft_display = NULL;
char dft_ttyname[64];
+ char *env_tty = NULL;
char *dft_ttytype = NULL;
char *optstr;
+ (void)version; /* Not yet used. */
+
g13 = calloc (1, sizeof *g13);
if (!g13)
return gpg_error_from_syserror ();
@@ -281,11 +285,20 @@ g13_new (void **engine, const char *file_name, const char *home_dir)
goto leave;
}
- if (isatty (1))
+ err = _gpgme_getenv ("GPG_TTY", &env_tty);
+ if (isatty (1) || env_tty || err)
{
- int rc;
+ int rc = 0;
- rc = ttyname_r (1, dft_ttyname, sizeof (dft_ttyname));
+ if (err)
+ goto leave;
+ else if (env_tty)
+ {
+ snprintf (dft_ttyname, sizeof (dft_ttyname), "%s", env_tty);
+ free (env_tty);
+ }
+ else
+ rc = ttyname_r (1, dft_ttyname, sizeof (dft_ttyname));
/* Even though isatty() returns 1, ttyname_r() may fail in many
ways, e.g., when /dev/pts is not accessible under chroot. */
@@ -353,7 +366,7 @@ g13_set_locale (void *engine, int category, const char *value)
engine_g13_t g13 = engine;
gpgme_error_t err;
char *optstr;
- char *catstr;
+ const char *catstr;
/* FIXME: If value is NULL, we need to reset the option to default.
But we can't do this. So we error out here. G13 needs support
@@ -402,7 +415,7 @@ g13_set_locale (void *engine, int category, const char *value)
#if USE_DESCRIPTOR_PASSING
static gpgme_error_t
-g13_assuan_simple_command (assuan_context_t ctx, char *cmd,
+g13_assuan_simple_command (assuan_context_t ctx, const char *cmd,
engine_status_handler_t status_fnc,
void *status_fnc_value)
{
@@ -410,6 +423,9 @@ g13_assuan_simple_command (assuan_context_t ctx, char *cmd,
char *line;
size_t linelen;
+ (void)status_fnc;
+ (void)status_fnc_value;
+
err = assuan_write_line (ctx, cmd);
if (err)
return err;
@@ -768,6 +784,7 @@ struct engine_ops _gpgme_engine_ops_g13 =
#else
NULL, /* reset */
#endif
+ NULL, /* set_status_cb */
NULL, /* set_status_handler */
NULL, /* set_command_handler */
NULL, /* set_colon_line_handler */
@@ -785,6 +802,8 @@ struct engine_ops _gpgme_engine_ops_g13 =
NULL, /* import */
NULL, /* keylist */
NULL, /* keylist_ext */
+ NULL, /* keysign */
+ NULL, /* tofu_policy */
NULL, /* sign */
NULL, /* trustlist */
NULL, /* verify */
diff --git a/src/engine-gpg.c b/src/engine-gpg.c
index 9efced2..8bb348f 100644
--- a/src/engine-gpg.c
+++ b/src/engine-gpg.c
@@ -42,6 +42,7 @@
#include "priv-io.h"
#include "sema.h"
#include "debug.h"
+#include "data.h"
#include "engine-backend.h"
@@ -78,6 +79,7 @@ typedef gpgme_error_t (*colon_preprocessor_t) (char *line, char **rline);
struct engine_gpg
{
char *file_name;
+ char *version;
char *lc_messages;
char *lc_ctype;
@@ -95,6 +97,8 @@ struct engine_gpg
int eof;
engine_status_handler_t fnc;
void *fnc_value;
+ gpgme_status_cb_t mon_cb;
+ void *mon_cb_value;
void *tag;
} status;
@@ -202,14 +206,16 @@ close_notify_handler (int fd, void *opaque)
/* If FRONT is true, push at the front of the list. Use this for
options added late in the process. */
static gpgme_error_t
-_add_arg (engine_gpg_t gpg, const char *arg, int front, int *arg_locp)
+_add_arg (engine_gpg_t gpg, const char *prefix, const char *arg, size_t arglen,
+ int front, int *arg_locp)
{
struct arg_and_data_s *a;
+ size_t prefixlen = prefix? strlen (prefix) : 0;
assert (gpg);
assert (arg);
- a = malloc (sizeof *a + strlen (arg));
+ a = malloc (sizeof *a + prefixlen + arglen);
if (!a)
return gpg_error_from_syserror ();
@@ -217,7 +223,10 @@ _add_arg (engine_gpg_t gpg, const char *arg, int front, int *arg_locp)
a->dup_to = -1;
a->arg_locp = arg_locp;
- strcpy (a->arg, arg);
+ if (prefixlen)
+ memcpy (a->arg, prefix, prefixlen);
+ memcpy (a->arg + prefixlen, arg, arglen);
+ a->arg[prefixlen + arglen] = 0;
if (front)
{
a->next = gpg->arglist;
@@ -239,24 +248,36 @@ _add_arg (engine_gpg_t gpg, const char *arg, int front, int *arg_locp)
return 0;
}
+
static gpgme_error_t
add_arg_ext (engine_gpg_t gpg, const char *arg, int front)
{
- return _add_arg (gpg, arg, front, NULL);
+ return _add_arg (gpg, NULL, arg, strlen (arg), front, NULL);
}
-
static gpgme_error_t
add_arg_with_locp (engine_gpg_t gpg, const char *arg, int *locp)
{
- return _add_arg (gpg, arg, 0, locp);
+ return _add_arg (gpg, NULL, arg, strlen (arg), 0, locp);
}
-
static gpgme_error_t
add_arg (engine_gpg_t gpg, const char *arg)
{
- return add_arg_ext (gpg, arg, 0);
+ return _add_arg (gpg, NULL, arg, strlen (arg), 0, NULL);
+}
+
+static gpgme_error_t
+add_arg_pfx (engine_gpg_t gpg, const char *prefix, const char *arg)
+{
+ return _add_arg (gpg, prefix, arg, strlen (arg), 0, NULL);
+}
+
+static gpgme_error_t
+add_arg_len (engine_gpg_t gpg, const char *prefix,
+ const char *arg, size_t arglen)
+{
+ return _add_arg (gpg, prefix, arg, arglen, 0, NULL);
}
@@ -291,6 +312,15 @@ add_data (engine_gpg_t gpg, gpgme_data_t data, int dup_to, int inbound)
return 0;
}
+
+/* Return true if the engine's version is at least VERSION. */
+static int
+have_gpg_version (engine_gpg_t gpg, const char *version)
+{
+ return _gpgme_compare_versions (gpg->version, version);
+}
+
+
static char *
gpg_get_version (const char *file_name)
@@ -386,6 +416,8 @@ gpg_release (void *engine)
if (gpg->file_name)
free (gpg->file_name);
+ if (gpg->version)
+ free (gpg->version);
if (gpg->lc_messages)
free (gpg->lc_messages);
@@ -414,13 +446,15 @@ gpg_release (void *engine)
static gpgme_error_t
-gpg_new (void **engine, const char *file_name, const char *home_dir)
+gpg_new (void **engine, const char *file_name, const char *home_dir,
+ const char *version)
{
engine_gpg_t gpg;
gpgme_error_t rc = 0;
char *dft_display = NULL;
char dft_ttyname[64];
char *dft_ttytype = NULL;
+ char *env_tty = NULL;
gpg = calloc (1, sizeof *gpg);
if (!gpg)
@@ -436,6 +470,16 @@ gpg_new (void **engine, const char *file_name, const char *home_dir)
}
}
+ if (version)
+ {
+ gpg->version = strdup (version);
+ if (!gpg->version)
+ {
+ rc = gpg_error_from_syserror ();
+ goto leave;
+ }
+ }
+
gpg->argtail = &gpg->arglist;
gpg->status.fd[0] = -1;
gpg->status.fd[1] = -1;
@@ -517,11 +561,20 @@ gpg_new (void **engine, const char *file_name, const char *home_dir)
goto leave;
}
- if (isatty (1))
+ rc = _gpgme_getenv ("GPG_TTY", &env_tty);
+ if (isatty (1) || env_tty || rc)
{
- int err;
+ int err = 0;
- err = ttyname_r (1, dft_ttyname, sizeof (dft_ttyname));
+ if (rc)
+ goto leave;
+ else if (env_tty)
+ {
+ snprintf (dft_ttyname, sizeof (dft_ttyname), "%s", env_tty);
+ free (env_tty);
+ }
+ else
+ err = ttyname_r (1, dft_ttyname, sizeof (dft_ttyname));
/* Even though isatty() returns 1, ttyname_r() may fail in many
ways, e.g., when /dev/pts is not accessible under chroot. */
@@ -609,6 +662,17 @@ gpg_set_locale (void *engine, int category, const char *value)
return 0;
}
+/* This sets a status callback for monitoring status lines before they
+ * are passed to a caller set handler. */
+static void
+gpg_set_status_cb (void *engine, gpgme_status_cb_t cb, void *cb_value)
+{
+ engine_gpg_t gpg = engine;
+
+ gpg->status.mon_cb = cb;
+ gpg->status.mon_cb_value = cb_value;
+}
+
/* Note, that the status_handler is allowed to modifiy the args
value. */
@@ -829,7 +893,7 @@ build_argv (engine_gpg_t gpg, const char *pgmname)
argc++;
}
- if (gpg->pinentry_mode)
+ if (gpg->pinentry_mode && have_gpg_version (gpg, "2.1.0"))
{
const char *s = NULL;
switch (gpg->pinentry_mode)
@@ -1019,6 +1083,7 @@ read_status (engine_gpg_t gpg)
size_t bufsize = gpg->status.bufsize;
char *buffer = gpg->status.buffer;
size_t readpos = gpg->status.readpos;
+ gpgme_error_t err;
assert (buffer);
if (bufsize - readpos < 256)
@@ -1037,15 +1102,20 @@ read_status (engine_gpg_t gpg)
if (!nread)
{
+ err = 0;
gpg->status.eof = 1;
+ if (gpg->status.mon_cb)
+ err = gpg->status.mon_cb (gpg->status.mon_cb_value, "", "");
if (gpg->status.fnc)
- {
- gpgme_error_t err;
- err = gpg->status.fnc (gpg->status.fnc_value, GPGME_STATUS_EOF, "");
- if (err)
- return err;
- }
- return 0;
+ {
+ char emptystring[1] = {0};
+ err = gpg->status.fnc (gpg->status.fnc_value,
+ GPGME_STATUS_EOF, emptystring);
+ if (gpg_err_code (err) == GPG_ERR_FALSE)
+ err = 0; /* Drop special error code. */
+ }
+
+ return err;
}
while (nread > 0)
@@ -1071,6 +1141,15 @@ read_status (engine_gpg_t gpg)
*rest++ = 0;
r = _gpgme_parse_status (buffer + 9);
+ if (gpg->status.mon_cb && r != GPGME_STATUS_PROGRESS)
+ {
+ /* Note that we call the monitor even if we do
+ * not know the status code (r < 0). */
+ err = gpg->status.mon_cb (gpg->status.mon_cb_value,
+ buffer + 9, rest);
+ if (err)
+ return err;
+ }
if (r >= 0)
{
if (gpg->cmd.used
@@ -1099,9 +1178,10 @@ read_status (engine_gpg_t gpg)
}
else if (gpg->status.fnc)
{
- gpgme_error_t err;
err = gpg->status.fnc (gpg->status.fnc_value,
r, rest);
+ if (gpg_err_code (err) == GPG_ERR_FALSE)
+ err = 0; /* Drop special error code. */
if (err)
return err;
}
@@ -1438,6 +1518,35 @@ start (engine_gpg_t gpg)
}
+/* Add the --input-size-hint option if requested. */
+static gpgme_error_t
+add_input_size_hint (engine_gpg_t gpg, gpgme_data_t data)
+{
+ gpgme_error_t err;
+ gpgme_off_t value = _gpgme_data_get_size_hint (data);
+ char numbuf[50]; /* Large enough for even 2^128 in base-10. */
+ char *p;
+
+ if (!value || !have_gpg_version (gpg, "2.1.15"))
+ return 0;
+
+ err = add_arg (gpg, "--input-size-hint");
+ if (!err)
+ {
+ p = numbuf + sizeof numbuf;
+ *--p = 0;
+ do
+ {
+ *--p = '0' + (value % 10);
+ value /= 10;
+ }
+ while (value);
+ err = add_arg (gpg, p);
+ }
+ return err;
+}
+
+
static gpgme_error_t
gpg_decrypt (void *engine, gpgme_data_t ciph, gpgme_data_t plain)
{
@@ -1454,6 +1563,8 @@ gpg_decrypt (void *engine, gpgme_data_t ciph, gpgme_data_t plain)
if (!err)
err = add_data (gpg, plain, 1, 1);
if (!err)
+ err = add_input_size_hint (gpg, ciph);
+ if (!err)
err = add_arg (gpg, "--");
if (!err)
err = add_data (gpg, ciph, -1, 0);
@@ -1493,6 +1604,8 @@ gpg_passwd (void *engine, gpgme_key_t key, unsigned int flags)
engine_gpg_t gpg = engine;
gpgme_error_t err;
+ (void)flags;
+
if (!key || !key->subkeys || !key->subkeys->fpr)
return gpg_error (GPG_ERR_INV_CERT_OBJ);
@@ -1523,7 +1636,8 @@ append_args_from_signers (engine_gpg_t gpg, gpgme_ctx_t ctx /* FIXME */)
err = add_arg (gpg, s);
}
gpgme_key_unref (key);
- if (err) break;
+ if (err)
+ break;
}
return err;
}
@@ -1672,10 +1786,13 @@ gpg_encrypt (void *engine, gpgme_key_t recp[], gpgme_encrypt_flags_t flags,
gpgme_data_t plain, gpgme_data_t ciph, int use_armor)
{
engine_gpg_t gpg = engine;
- gpgme_error_t err;
- int symmetric = !recp;
+ gpgme_error_t err = 0;
- err = add_arg (gpg, symmetric ? "--symmetric" : "--encrypt");
+ if (recp)
+ err = add_arg (gpg, "--encrypt");
+
+ if (!err && ((flags & GPGME_ENCRYPT_SYMMETRIC) || !recp))
+ err = add_arg (gpg, "--symmetric");
if (!err && use_armor)
err = add_arg (gpg, "--armor");
@@ -1683,7 +1800,11 @@ gpg_encrypt (void *engine, gpgme_key_t recp[], gpgme_encrypt_flags_t flags,
if (!err && (flags & GPGME_ENCRYPT_NO_COMPRESS))
err = add_arg (gpg, "--compress-algo=none");
- if (!symmetric)
+ if (gpgme_data_get_encoding (plain) == GPGME_DATA_ENCODING_MIME
+ && have_gpg_version (gpg, "2.1.14"))
+ err = add_arg (gpg, "--mimemode");
+
+ if (recp)
{
/* If we know that all recipients are valid (full or ultimate trust)
we can suppress further checks. */
@@ -1712,6 +1833,8 @@ gpg_encrypt (void *engine, gpgme_key_t recp[], gpgme_encrypt_flags_t flags,
err = add_arg (gpg, gpgme_data_get_file_name (plain));
}
if (!err)
+ err = add_input_size_hint (gpg, plain);
+ if (!err)
err = add_arg (gpg, "--");
if (!err)
err = add_data (gpg, plain, -1, 0);
@@ -1730,10 +1853,13 @@ gpg_encrypt_sign (void *engine, gpgme_key_t recp[],
gpgme_ctx_t ctx /* FIXME */)
{
engine_gpg_t gpg = engine;
- gpgme_error_t err;
- int symmetric = !recp;
+ gpgme_error_t err = 0;
+
+ if (recp)
+ err = add_arg (gpg, "--encrypt");
- err = add_arg (gpg, symmetric ? "--symmetric" : "--encrypt");
+ if (!err && ((flags & GPGME_ENCRYPT_SYMMETRIC) || !recp))
+ err = add_arg (gpg, "--symmetric");
if (!err)
err = add_arg (gpg, "--sign");
@@ -1743,7 +1869,11 @@ gpg_encrypt_sign (void *engine, gpgme_key_t recp[],
if (!err && (flags & GPGME_ENCRYPT_NO_COMPRESS))
err = add_arg (gpg, "--compress-algo=none");
- if (!symmetric)
+ if (gpgme_data_get_encoding (plain) == GPGME_DATA_ENCODING_MIME
+ && have_gpg_version (gpg, "2.1.14"))
+ err = add_arg (gpg, "--mimemode");
+
+ if (recp)
{
/* If we know that all recipients are valid (full or ultimate trust)
we can suppress further checks. */
@@ -1778,6 +1908,8 @@ gpg_encrypt_sign (void *engine, gpgme_key_t recp[],
err = add_arg (gpg, gpgme_data_get_file_name (plain));
}
if (!err)
+ err = add_input_size_hint (gpg, plain);
+ if (!err)
err = add_arg (gpg, "--");
if (!err)
err = add_data (gpg, plain, -1, 0);
@@ -1868,33 +2000,210 @@ gpg_export_ext (void *engine, const char *pattern[], gpgme_export_mode_t mode,
}
+
+/* Helper to add algo, usage, and expire to the list of args. */
static gpgme_error_t
-gpg_genkey (void *engine, gpgme_data_t help_data, int use_armor,
- gpgme_data_t pubkey, gpgme_data_t seckey)
+gpg_add_algo_usage_expire (engine_gpg_t gpg,
+ const char *algo,
+ unsigned long expires,
+ unsigned int flags)
{
- engine_gpg_t gpg = engine;
- gpgme_error_t err;
+ gpg_error_t err;
- if (!gpg)
- return gpg_error (GPG_ERR_INV_VALUE);
+ /* This condition is only required to allow the use of gpg < 2.1.16 */
+ if (algo
+ || (flags & (GPGME_CREATE_SIGN | GPGME_CREATE_ENCR
+ | GPGME_CREATE_CERT | GPGME_CREATE_AUTH))
+ || expires)
+ {
+ err = add_arg (gpg, algo? algo : "default");
+ if (!err)
+ {
+ char tmpbuf[5*4+1];
+ snprintf (tmpbuf, sizeof tmpbuf, "%s%s%s%s",
+ (flags & GPGME_CREATE_SIGN)? " sign":"",
+ (flags & GPGME_CREATE_ENCR)? " encr":"",
+ (flags & GPGME_CREATE_CERT)? " cert":"",
+ (flags & GPGME_CREATE_AUTH)? " auth":"");
+ err = add_arg (gpg, *tmpbuf? tmpbuf : "default");
+ }
+ if (!err && expires)
+ {
+ char tmpbuf[8+20];
+ snprintf (tmpbuf, sizeof tmpbuf, "seconds=%lu", expires);
+ err = add_arg (gpg, tmpbuf);
+ }
+ }
+ else
+ err = 0;
+
+ return err;
+}
- /* We need a special mechanism to get the fd of a pipe here, so that
- we can use this for the %pubring and %secring parameters. We
- don't have this yet, so we implement only the adding to the
- standard keyrings. */
- if (pubkey || seckey)
- return gpg_error (GPG_ERR_NOT_IMPLEMENTED);
+
+static gpgme_error_t
+gpg_createkey_from_param (engine_gpg_t gpg,
+ gpgme_data_t help_data, unsigned int extraflags)
+{
+ gpgme_error_t err;
err = add_arg (gpg, "--gen-key");
- if (!err && use_armor)
+ if (!err && (extraflags & GENKEY_EXTRAFLAG_ARMOR))
err = add_arg (gpg, "--armor");
if (!err)
err = add_arg (gpg, "--");
if (!err)
err = add_data (gpg, help_data, -1, 0);
+ if (!err)
+ err = start (gpg);
+ return err;
+}
+
+
+static gpgme_error_t
+gpg_createkey (engine_gpg_t gpg,
+ const char *userid, const char *algo,
+ unsigned long expires,
+ unsigned int flags,
+ unsigned int extraflags)
+{
+ gpgme_error_t err;
+
+ err = add_arg (gpg, "--quick-gen-key");
+ if (!err && (extraflags & GENKEY_EXTRAFLAG_ARMOR))
+ err = add_arg (gpg, "--armor");
+ if (!err && (flags & GPGME_CREATE_NOPASSWD))
+ {
+ err = add_arg (gpg, "--passphrase");
+ if (!err)
+ err = add_arg (gpg, "");
+ }
+ if (!err && (flags & GPGME_CREATE_FORCE))
+ err = add_arg (gpg, "--yes");
+ if (!err)
+ err = add_arg (gpg, "--");
+ if (!err)
+ err = add_arg (gpg, userid);
+
+ if (!err)
+ err = gpg_add_algo_usage_expire (gpg, algo, expires, flags);
if (!err)
err = start (gpg);
+ return err;
+}
+
+
+static gpgme_error_t
+gpg_addkey (engine_gpg_t gpg,
+ const char *algo,
+ unsigned long expires,
+ gpgme_key_t key,
+ unsigned int flags,
+ unsigned int extraflags)
+{
+ gpgme_error_t err;
+
+ if (!key || !key->fpr)
+ return gpg_error (GPG_ERR_INV_ARG);
+
+ err = add_arg (gpg, "--quick-addkey");
+ if (!err && (extraflags & GENKEY_EXTRAFLAG_ARMOR))
+ err = add_arg (gpg, "--armor");
+ if (!err && (flags & GPGME_CREATE_NOPASSWD))
+ {
+ err = add_arg (gpg, "--passphrase");
+ if (!err)
+ err = add_arg (gpg, "");
+ }
+ if (!err)
+ err = add_arg (gpg, "--");
+ if (!err)
+ err = add_arg (gpg, key->fpr);
+
+ if (!err)
+ err = gpg_add_algo_usage_expire (gpg, algo, expires, flags);
+
+ if (!err)
+ err = start (gpg);
+ return err;
+}
+
+
+static gpgme_error_t
+gpg_adduid (engine_gpg_t gpg,
+ gpgme_key_t key,
+ const char *userid,
+ unsigned int extraflags)
+{
+ gpgme_error_t err;
+
+ if (!key || !key->fpr || !userid)
+ return gpg_error (GPG_ERR_INV_ARG);
+
+ if ((extraflags & GENKEY_EXTRAFLAG_REVOKE))
+ err = add_arg (gpg, "--quick-revuid");
+ else
+ err = add_arg (gpg, "--quick-adduid");
+
+ if (!err)
+ err = add_arg (gpg, "--");
+ if (!err)
+ err = add_arg (gpg, key->fpr);
+ if (!err)
+ err = add_arg (gpg, userid);
+
+ if (!err)
+ err = start (gpg);
+ return err;
+}
+
+
+static gpgme_error_t
+gpg_genkey (void *engine,
+ const char *userid, const char *algo,
+ unsigned long reserved, unsigned long expires,
+ gpgme_key_t key, unsigned int flags,
+ gpgme_data_t help_data, unsigned int extraflags,
+ gpgme_data_t pubkey, gpgme_data_t seckey)
+{
+ engine_gpg_t gpg = engine;
+ gpgme_error_t err;
+
+ (void)reserved;
+
+ if (!gpg)
+ return gpg_error (GPG_ERR_INV_VALUE);
+
+ /* If HELP_DATA is given the use of the old interface
+ * (gpgme_op_genkey) has been requested. The other modes are:
+ *
+ * USERID && !KEY - Create a new keyblock.
+ * !USERID && KEY - Add a new subkey to KEY (gpg >= 2.1.14)
+ * USERID && KEY && !ALGO - Add a new user id to KEY (gpg >= 2.1.14).
+ *
+ */
+ if (help_data)
+ {
+ /* We need a special mechanism to get the fd of a pipe here, so
+ that we can use this for the %pubring and %secring
+ parameters. We don't have this yet, so we implement only the
+ adding to the standard keyrings. */
+ if (pubkey || seckey)
+ err = gpg_error (GPG_ERR_NOT_IMPLEMENTED);
+ else
+ err = gpg_createkey_from_param (gpg, help_data, extraflags);
+ }
+ else if (!have_gpg_version (gpg, "2.1.13"))
+ err = gpg_error (GPG_ERR_NOT_SUPPORTED);
+ else if (userid && !key)
+ err = gpg_createkey (gpg, userid, algo, expires, flags, extraflags);
+ else if (!userid && key)
+ err = gpg_addkey (gpg, algo, expires, key, flags, extraflags);
+ else if (userid && key && !algo)
+ err = gpg_adduid (gpg, key, userid, extraflags);
+ else
+ err = gpg_error (GPG_ERR_INV_VALUE);
return err;
}
@@ -2230,14 +2539,26 @@ gpg_keylist_build_options (engine_gpg_t gpg, int secret_only,
gpg_error_t err;
err = add_arg (gpg, "--with-colons");
- if (!err)
- err = add_arg (gpg, "--fixed-list-mode");
- if (!err)
- err = add_arg (gpg, "--with-fingerprint");
- if (!err)
- err = add_arg (gpg, "--with-fingerprint");
+
+ /* Since gpg 2.1.15 fingerprints are always printed, thus there is
+ * no more need to explictly request them. */
+ if (!have_gpg_version (gpg, "2.1.15"))
+ {
+ if (!err)
+ err = add_arg (gpg, "--fixed-list-mode");
+ if (!err)
+ err = add_arg (gpg, "--with-fingerprint");
+ if (!err)
+ err = add_arg (gpg, "--with-fingerprint");
+ }
+
+ if (!err && (mode & GPGME_KEYLIST_MODE_WITH_TOFU)
+ && have_gpg_version (gpg, "2.1.16"))
+ err = add_arg (gpg, "--with-tofu-info");
+
if (!err && (mode & GPGME_KEYLIST_MODE_WITH_SECRET))
err = add_arg (gpg, "--with-secret");
+
if (!err
&& (mode & GPGME_KEYLIST_MODE_SIGS)
&& (mode & GPGME_KEYLIST_MODE_SIG_NOTATIONS))
@@ -2246,6 +2567,7 @@ gpg_keylist_build_options (engine_gpg_t gpg, int secret_only,
if (!err)
err = add_arg (gpg, "show-sig-subpackets=\"20,26\"");
}
+
if (!err)
{
if ( (mode & GPGME_KEYLIST_MODE_EXTERN) )
@@ -2277,6 +2599,7 @@ gpg_keylist_build_options (engine_gpg_t gpg, int secret_only,
? "--check-sigs" : "--list-keys"));
}
}
+
if (!err)
err = add_arg (gpg, "--");
@@ -2291,6 +2614,8 @@ gpg_keylist (void *engine, const char *pattern, int secret_only,
engine_gpg_t gpg = engine;
gpgme_error_t err;
+ (void)engine_flags;
+
err = gpg_keylist_build_options (gpg, secret_only, mode);
if (!err && pattern && *pattern)
@@ -2310,6 +2635,8 @@ gpg_keylist_ext (void *engine, const char *pattern[], int secret_only,
engine_gpg_t gpg = engine;
gpgme_error_t err;
+ (void)engine_flags;
+
if (reserved)
return gpg_error (GPG_ERR_INV_VALUE);
@@ -2329,6 +2656,111 @@ gpg_keylist_ext (void *engine, const char *pattern[], int secret_only,
static gpgme_error_t
+gpg_keysign (void *engine, gpgme_key_t key, const char *userid,
+ unsigned long expire, unsigned int flags,
+ gpgme_ctx_t ctx)
+{
+ engine_gpg_t gpg = engine;
+ gpgme_error_t err;
+ const char *s;
+
+ if (!key || !key->fpr)
+ return gpg_error (GPG_ERR_INV_ARG);
+
+ if (!have_gpg_version (gpg, "2.1.12"))
+ return gpg_error (GPG_ERR_NOT_SUPPORTED);
+
+ if ((flags & GPGME_KEYSIGN_LOCAL))
+ err = add_arg (gpg, "--quick-lsign-key");
+ else
+ err = add_arg (gpg, "--quick-sign-key");
+
+ if (!err)
+ err = append_args_from_signers (gpg, ctx);
+
+ /* If an expiration time has been given use that. If none has been
+ * given the default from gpg.conf is used. To make sure not to set
+ * an expiration time at all the flag GPGME_KEYSIGN_NOEXPIRE can be
+ * used. */
+ if (!err && (expire || (flags & GPGME_KEYSIGN_NOEXPIRE)))
+ {
+ char tmpbuf[8+20];
+
+ if ((flags & GPGME_KEYSIGN_NOEXPIRE))
+ expire = 0;
+ snprintf (tmpbuf, sizeof tmpbuf, "seconds=%lu", expire);
+ err = add_arg (gpg, "--default-cert-expire");
+ if (!err)
+ err = add_arg (gpg, tmpbuf);
+ }
+
+ if (!err)
+ err = add_arg (gpg, "--");
+
+ if (!err)
+ err = add_arg (gpg, key->fpr);
+ if (!err && userid)
+ {
+ if ((flags & GPGME_KEYSIGN_LFSEP))
+ {
+ for (; !err && (s = strchr (userid, '\n')); userid = s + 1)
+ if ((s - userid))
+ err = add_arg_len (gpg, "=", userid, s - userid);
+ if (!err && *userid)
+ err = add_arg_pfx (gpg, "=", userid);
+ }
+ else
+ err = add_arg_pfx (gpg, "=", userid);
+ }
+
+ if (!err)
+ err = start (gpg);
+
+ return err;
+}
+
+
+static gpgme_error_t
+gpg_tofu_policy (void *engine, gpgme_key_t key, gpgme_tofu_policy_t policy)
+{
+ engine_gpg_t gpg = engine;
+ gpgme_error_t err;
+ const char *policystr = NULL;
+
+ if (!key || !key->fpr)
+ return gpg_error (GPG_ERR_INV_ARG);
+
+ switch (policy)
+ {
+ case GPGME_TOFU_POLICY_NONE: break;
+ case GPGME_TOFU_POLICY_AUTO: policystr = "auto"; break;
+ case GPGME_TOFU_POLICY_GOOD: policystr = "good"; break;
+ case GPGME_TOFU_POLICY_BAD: policystr = "bad"; break;
+ case GPGME_TOFU_POLICY_ASK: policystr = "ask"; break;
+ case GPGME_TOFU_POLICY_UNKNOWN: policystr = "unknown"; break;
+ }
+ if (!policystr)
+ return gpg_error (GPG_ERR_INV_VALUE);
+
+ if (!have_gpg_version (gpg, "2.1.10"))
+ return gpg_error (GPG_ERR_NOT_SUPPORTED);
+
+ err = add_arg (gpg, "--tofu-policy");
+ if (!err)
+ err = add_arg (gpg, "--");
+ if (!err)
+ err = add_arg (gpg, policystr);
+ if (!err)
+ err = add_arg (gpg, key->fpr);
+
+ if (!err)
+ err = start (gpg);
+
+ return err;
+}
+
+
+static gpgme_error_t
gpg_sign (void *engine, gpgme_data_t in, gpgme_data_t out,
gpgme_sig_mode_t mode, int use_armor, int use_textmode,
int include_certs, gpgme_ctx_t ctx /* FIXME */)
@@ -2336,6 +2768,8 @@ gpg_sign (void *engine, gpgme_data_t in, gpgme_data_t out,
engine_gpg_t gpg = engine;
gpgme_error_t err;
+ (void)include_certs;
+
if (mode == GPGME_SIG_MODE_CLEAR)
err = add_arg (gpg, "--clearsign");
else
@@ -2345,8 +2779,14 @@ gpg_sign (void *engine, gpgme_data_t in, gpgme_data_t out,
err = add_arg (gpg, "--detach");
if (!err && use_armor)
err = add_arg (gpg, "--armor");
- if (!err && use_textmode)
- err = add_arg (gpg, "--textmode");
+ if (!err)
+ {
+ if (gpgme_data_get_encoding (in) == GPGME_DATA_ENCODING_MIME
+ && have_gpg_version (gpg, "2.1.14"))
+ err = add_arg (gpg, "--mimemode");
+ else if (use_textmode)
+ err = add_arg (gpg, "--textmode");
+ }
}
if (!err)
@@ -2364,6 +2804,8 @@ gpg_sign (void *engine, gpgme_data_t in, gpgme_data_t out,
/* Tell the gpg object about the data. */
if (!err)
+ err = add_input_size_hint (gpg, in);
+ if (!err)
err = add_arg (gpg, "--");
if (!err)
err = add_data (gpg, in, -1, 0);
@@ -2409,11 +2851,12 @@ gpg_verify (void *engine, gpgme_data_t sig, gpgme_data_t signed_text,
if (plaintext)
{
/* Normal or cleartext signature. */
-
err = add_arg (gpg, "--output");
if (!err)
err = add_arg (gpg, "-");
if (!err)
+ err = add_input_size_hint (gpg, sig);
+ if (!err)
err = add_arg (gpg, "--");
if (!err)
err = add_data (gpg, sig, -1, 0);
@@ -2424,6 +2867,8 @@ gpg_verify (void *engine, gpgme_data_t sig, gpgme_data_t signed_text,
{
err = add_arg (gpg, "--verify");
if (!err)
+ err = add_input_size_hint (gpg, signed_text);
+ if (!err)
err = add_arg (gpg, "--");
if (!err)
err = add_data (gpg, sig, -1, 0);
@@ -2470,6 +2915,7 @@ struct engine_ops _gpgme_engine_ops_gpg =
/* Member functions. */
gpg_release,
NULL, /* reset */
+ gpg_set_status_cb,
gpg_set_status_handler,
gpg_set_command_handler,
gpg_set_colon_line_handler,
@@ -2487,6 +2933,8 @@ struct engine_ops _gpgme_engine_ops_gpg =
gpg_import,
gpg_keylist,
gpg_keylist_ext,
+ gpg_keysign,
+ gpg_tofu_policy, /* tofu_policy */
gpg_sign,
gpg_trustlist,
gpg_verify,
diff --git a/src/engine-gpgconf.c b/src/engine-gpgconf.c
index a2407ac..90f32c7 100644
--- a/src/engine-gpgconf.c
+++ b/src/engine-gpgconf.c
@@ -90,11 +90,14 @@ gpgconf_release (void *engine)
static gpgme_error_t
-gpgconf_new (void **engine, const char *file_name, const char *home_dir)
+gpgconf_new (void **engine, const char *file_name, const char *home_dir,
+ const char *version)
{
gpgme_error_t err = 0;
engine_gpgconf_t gpgconf;
+ (void)version; /* Not yet used. */
+
gpgconf = calloc (1, sizeof *gpgconf);
if (!gpgconf)
return gpg_error_from_syserror ();
@@ -197,7 +200,7 @@ gpgconf_config_release (gpgme_conf_comp_t conf)
allow for quite a long "group" line, which is usually the longest
line (mine is currently ~3k). */
static gpgme_error_t
-gpgconf_read (void *engine, char *arg1, char *arg2,
+gpgconf_read (void *engine, const char *arg1, char *arg2,
gpgme_error_t (*cb) (void *hook, char *line),
void *hook)
{
@@ -214,7 +217,7 @@ gpgconf_read (void *engine, char *arg1, char *arg2,
int nread;
char *mark = NULL;
- argv[1] = arg1;
+ argv[1] = (char*)arg1;
argv[2] = arg2;
@@ -675,14 +678,14 @@ _gpgme_conf_opt_change (gpgme_conf_opt_t opt, int reset, gpgme_conf_arg_t arg)
/* FIXME: Major problem: We don't get errors from gpgconf. */
static gpgme_error_t
-gpgconf_write (void *engine, char *arg1, char *arg2, gpgme_data_t conf)
+gpgconf_write (void *engine, const char *arg1, char *arg2, gpgme_data_t conf)
{
struct engine_gpgconf *gpgconf = engine;
gpgme_error_t err = 0;
#define BUFLEN 1024
char buf[BUFLEN];
int buflen = 0;
- char *argv[] = { NULL /* file_name */, arg1, arg2, 0 };
+ char *argv[] = { NULL /* file_name */, (char*)arg1, arg2, 0 };
int rp[2];
struct spawn_fd_item_s cfd[] = { {-1, 0 /* STDIN_FILENO */}, {-1, -1} };
int status;
@@ -909,6 +912,8 @@ gpgconf_conf_save (void *engine, gpgme_conf_comp_t comp)
static void
gpgconf_set_io_cbs (void *engine, gpgme_io_cbs_t io_cbs)
{
+ (void)engine;
+ (void)io_cbs;
/* Nothing to do. */
}
@@ -934,6 +939,7 @@ struct engine_ops _gpgme_engine_ops_gpgconf =
/* Member functions. */
gpgconf_release,
NULL, /* reset */
+ NULL, /* set_status_cb */
NULL, /* set_status_handler */
NULL, /* set_command_handler */
NULL, /* set_colon_line_handler */
@@ -951,6 +957,8 @@ struct engine_ops _gpgme_engine_ops_gpgconf =
NULL, /* import */
NULL, /* keylist */
NULL, /* keylist_ext */
+ NULL, /* keysign */
+ NULL, /* tofu_policy */
NULL, /* sign */
NULL, /* trustlist */
NULL, /* verify */
diff --git a/src/engine-gpgsm.c b/src/engine-gpgsm.c
index 476e9ef..e7e2a20 100644
--- a/src/engine-gpgsm.c
+++ b/src/engine-gpgsm.c
@@ -88,6 +88,8 @@ struct engine_gpgsm
{
engine_status_handler_t fnc;
void *fnc_value;
+ gpgme_status_cb_t mon_cb;
+ void *mon_cb_value;
} status;
struct
@@ -183,6 +185,8 @@ close_notify_handler (int fd, void *opaque)
static gpgme_error_t
default_inq_cb (engine_gpgsm_t gpgsm, const char *line)
{
+ (void)gpgsm;
+
if (!strncmp (line, "PINENTRY_LAUNCHED", 17) && (line[17]==' '||!line[17]))
{
_gpgme_allow_set_foreground_window ((pid_t)strtoul (line+17, NULL, 10));
@@ -235,7 +239,8 @@ gpgsm_release (void *engine)
static gpgme_error_t
-gpgsm_new (void **engine, const char *file_name, const char *home_dir)
+gpgsm_new (void **engine, const char *file_name, const char *home_dir,
+ const char *version)
{
gpgme_error_t err = 0;
engine_gpgsm_t gpgsm;
@@ -248,9 +253,12 @@ gpgsm_new (void **engine, const char *file_name, const char *home_dir)
#endif
char *dft_display = NULL;
char dft_ttyname[64];
+ char *env_tty = NULL;
char *dft_ttytype = NULL;
char *optstr;
+ (void)version; /* Not yet used. */
+
gpgsm = calloc (1, sizeof *gpgsm);
if (!gpgsm)
return gpg_error_from_syserror ();
@@ -403,11 +411,20 @@ gpgsm_new (void **engine, const char *file_name, const char *home_dir)
goto leave;
}
- if (isatty (1))
+ err = _gpgme_getenv ("GPG_TTY", &env_tty);
+ if (isatty (1) || env_tty || err)
{
- int rc;
+ int rc = 0;
- rc = ttyname_r (1, dft_ttyname, sizeof (dft_ttyname));
+ if (err)
+ goto leave;
+ else if (env_tty)
+ {
+ snprintf (dft_ttyname, sizeof (dft_ttyname), "%s", env_tty);
+ free (env_tty);
+ }
+ else
+ rc = ttyname_r (1, dft_ttyname, sizeof (dft_ttyname));
/* Even though isatty() returns 1, ttyname_r() may fail in many
ways, e.g., when /dev/pts is not accessible under chroot. */
@@ -510,7 +527,7 @@ gpgsm_set_locale (void *engine, int category, const char *value)
engine_gpgsm_t gpgsm = engine;
gpgme_error_t err;
char *optstr;
- char *catstr;
+ const char *catstr;
/* FIXME: If value is NULL, we need to reset the option to default.
But we can't do this. So we error out here. GPGSM needs support
@@ -558,10 +575,11 @@ gpgsm_set_locale (void *engine, int category, const char *value)
static gpgme_error_t
-gpgsm_assuan_simple_command (assuan_context_t ctx, char *cmd,
+gpgsm_assuan_simple_command (engine_gpgsm_t gpgsm, const char *cmd,
engine_status_handler_t status_fnc,
void *status_fnc_value)
{
+ assuan_context_t ctx = gpgsm->assuan_ctx;
gpg_error_t err, cb_err;
char *line;
size_t linelen;
@@ -610,8 +628,15 @@ gpgsm_assuan_simple_command (assuan_context_t ctx, char *cmd,
*(rest++) = 0;
r = _gpgme_parse_status (line + 2);
+ if (gpgsm->status.mon_cb && r != GPGME_STATUS_PROGRESS)
+ {
+ /* Note that we call the monitor even if we do
+ * not know the status code (r < 0). */
+ cb_err = gpgsm->status.mon_cb (gpgsm->status.mon_cb_value,
+ line + 2, rest);
+ }
- if (r >= 0 && status_fnc)
+ if (r >= 0 && status_fnc && !cb_err)
cb_err = status_fnc (status_fnc_value, r, rest);
}
}
@@ -647,6 +672,9 @@ gpgsm_clear_fd (engine_gpgsm_t gpgsm, fd_type_t fd_type)
_gpgme_io_close (gpgsm->message_cb.fd);
break;
}
+#else
+ (void)gpgsm;
+ (void)fd_type;
#endif
}
@@ -656,7 +684,7 @@ gpgsm_set_fd (engine_gpgsm_t gpgsm, fd_type_t fd_type, const char *opt)
{
gpg_error_t err = 0;
char line[COMMANDLINELEN];
- char *which;
+ const char *which;
iocb_data_t *iocb_data;
#if USE_DESCRIPTOR_PASSING
int dir;
@@ -726,7 +754,7 @@ gpgsm_set_fd (engine_gpgsm_t gpgsm, fd_type_t fd_type, const char *opt)
which, iocb_data->server_fd_str);
#endif
- err = gpgsm_assuan_simple_command (gpgsm->assuan_ctx, line, NULL, NULL);
+ err = gpgsm_assuan_simple_command (gpgsm, line, NULL, NULL);
#if USE_DESCRIPTOR_PASSING
leave_set_fd:
@@ -805,8 +833,13 @@ status_handler (void *opaque, int fd)
&& (line[2] == '\0' || line[2] == ' '))
{
if (gpgsm->status.fnc)
- err = gpgsm->status.fnc (gpgsm->status.fnc_value,
- GPGME_STATUS_EOF, "");
+ {
+ char emptystring[1] = {0};
+ err = gpgsm->status.fnc (gpgsm->status.fnc_value,
+ GPGME_STATUS_EOF, emptystring);
+ if (gpg_err_code (err) == GPG_ERR_FALSE)
+ err = 0; /* Drop special error code. */
+ }
if (!err && gpgsm->colon.fnc && gpgsm->colon.any)
{
@@ -957,7 +990,11 @@ status_handler (void *opaque, int fd)
if (r >= 0)
{
if (gpgsm->status.fnc)
- err = gpgsm->status.fnc (gpgsm->status.fnc_value, r, rest);
+ {
+ err = gpgsm->status.fnc (gpgsm->status.fnc_value, r, rest);
+ if (gpg_err_code (err) == GPG_ERR_FALSE)
+ err = 0; /* Drop special error code. */
+ }
}
else
fprintf (stderr, "[UNKNOWN STATUS]%s %s", line + 2, rest);
@@ -1075,8 +1112,7 @@ gpgsm_reset (void *engine)
need to reset the list of signers. Note that RESET does not
reset OPTION commands. */
return (gpgsm->assuan_ctx
- ? gpgsm_assuan_simple_command (gpgsm->assuan_ctx, "RESET",
- NULL, NULL)
+ ? gpgsm_assuan_simple_command (gpgsm, "RESET", NULL, NULL)
: 0);
}
#endif
@@ -1118,6 +1154,8 @@ gpgsm_delete (void *engine, gpgme_key_t key, int allow_secret)
char *line;
int length = 8; /* "DELKEYS " */
+ (void)allow_secret;
+
if (!fpr)
return gpg_error (GPG_ERR_INV_VALUE);
@@ -1180,7 +1218,6 @@ static gpgme_error_t
set_recipients (engine_gpgsm_t gpgsm, gpgme_key_t recp[])
{
gpgme_error_t err = 0;
- assuan_context_t ctx = gpgsm->assuan_ctx;
char *line;
int linelen;
int invalid_recipients = 0;
@@ -1218,7 +1255,7 @@ set_recipients (engine_gpgsm_t gpgsm, gpgme_key_t recp[])
}
strcpy (&line[10], fpr);
- err = gpgsm_assuan_simple_command (ctx, line, gpgsm->status.fnc,
+ err = gpgsm_assuan_simple_command (gpgsm, line, gpgsm->status.fnc,
gpgsm->status.fnc_value);
/* FIXME: This requires more work. */
if (gpg_err_code (err) == GPG_ERR_NO_PUBKEY)
@@ -1249,7 +1286,7 @@ gpgsm_encrypt (void *engine, gpgme_key_t recp[], gpgme_encrypt_flags_t flags,
if (flags & GPGME_ENCRYPT_NO_ENCRYPT_TO)
{
- err = gpgsm_assuan_simple_command (gpgsm->assuan_ctx,
+ err = gpgsm_assuan_simple_command (gpgsm,
"OPTION no-encrypt-to", NULL, NULL);
if (err)
return err;
@@ -1422,29 +1459,51 @@ gpgsm_export_ext (void *engine, const char *pattern[], gpgme_export_mode_t mode,
static gpgme_error_t
-gpgsm_genkey (void *engine, gpgme_data_t help_data, int use_armor,
+gpgsm_genkey (void *engine,
+ const char *userid, const char *algo,
+ unsigned long reserved, unsigned long expires,
+ gpgme_key_t key, unsigned int flags,
+ gpgme_data_t help_data, unsigned int extraflags,
gpgme_data_t pubkey, gpgme_data_t seckey)
{
engine_gpgsm_t gpgsm = engine;
gpgme_error_t err;
- if (!gpgsm || !pubkey || seckey)
+ (void)reserved;
+
+ if (!gpgsm)
return gpg_error (GPG_ERR_INV_VALUE);
- gpgsm->input_cb.data = help_data;
- err = gpgsm_set_fd (gpgsm, INPUT_FD, map_data_enc (gpgsm->input_cb.data));
- if (err)
- return err;
- gpgsm->output_cb.data = pubkey;
- err = gpgsm_set_fd (gpgsm, OUTPUT_FD, use_armor ? "--armor"
- : map_data_enc (gpgsm->output_cb.data));
- if (err)
- return err;
- gpgsm_clear_fd (gpgsm, MESSAGE_FD);
- gpgsm->inline_data = NULL;
+ if (help_data)
+ {
+ if (!pubkey || seckey)
+ return gpg_error (GPG_ERR_INV_VALUE);
- err = start (gpgsm, "GENKEY");
- return err;
+ gpgsm->input_cb.data = help_data;
+ err = gpgsm_set_fd (gpgsm, INPUT_FD, map_data_enc (gpgsm->input_cb.data));
+ if (err)
+ return err;
+ gpgsm->output_cb.data = pubkey;
+ err = gpgsm_set_fd (gpgsm, OUTPUT_FD,
+ (extraflags & GENKEY_EXTRAFLAG_ARMOR)? "--armor"
+ : map_data_enc (gpgsm->output_cb.data));
+ if (err)
+ return err;
+ gpgsm_clear_fd (gpgsm, MESSAGE_FD);
+ gpgsm->inline_data = NULL;
+
+ err = start (gpgsm, "GENKEY");
+ return err;
+ }
+
+ (void)userid;
+ (void)algo;
+ (void)expires;
+ (void)key;
+ (void)flags;
+
+ /* The new interface has not yet been implemented, */
+ return gpg_error (GPG_ERR_NOT_IMPLEMENTED);
}
@@ -1472,8 +1531,7 @@ gpgsm_import (void *engine, gpgme_data_t keydata, gpgme_key_t *keyarray)
/* Fist check whether the engine already features the
--re-import option. */
err = gpgsm_assuan_simple_command
- (gpgsm->assuan_ctx,
- "GETINFO cmd_has_option IMPORT re-import", NULL, NULL);
+ (gpgsm, "GETINFO cmd_has_option IMPORT re-import", NULL, NULL);
if (err)
return gpg_error (GPG_ERR_NOT_SUPPORTED);
@@ -1575,13 +1633,12 @@ gpgsm_keylist (void *engine, const char *pattern, int secret_only,
available and thus there is no need for gpgsm to ask the agent
whether a secret key exists for the public key. */
if (secret_only || (mode & GPGME_KEYLIST_MODE_WITH_SECRET))
- gpgsm_assuan_simple_command (gpgsm->assuan_ctx, "GETINFO agent-check",
- NULL, NULL);
+ gpgsm_assuan_simple_command (gpgsm, "GETINFO agent-check", NULL, NULL);
/* Always send list-mode option because RESET does not reset it. */
if (asprintf (&line, "OPTION list-mode=%d", (list_mode & 3)) < 0)
return gpg_error_from_syserror ();
- err = gpgsm_assuan_simple_command (gpgsm->assuan_ctx, line, NULL, NULL);
+ err = gpgsm_assuan_simple_command (gpgsm, line, NULL, NULL);
free (line);
if (err)
return err;
@@ -1591,24 +1648,24 @@ gpgsm_keylist (void *engine, const char *pattern, int secret_only,
/* Use the validation mode if requested. We don't check for an error
yet because this is a pretty fresh gpgsm features. */
- gpgsm_assuan_simple_command (gpgsm->assuan_ctx,
+ gpgsm_assuan_simple_command (gpgsm,
(mode & GPGME_KEYLIST_MODE_VALIDATE)?
"OPTION with-validation=1":
"OPTION with-validation=0" ,
NULL, NULL);
/* Include the ephemeral keys if requested. We don't check for an error
yet because this is a pretty fresh gpgsm features. */
- gpgsm_assuan_simple_command (gpgsm->assuan_ctx,
+ gpgsm_assuan_simple_command (gpgsm,
(mode & GPGME_KEYLIST_MODE_EPHEMERAL)?
"OPTION with-ephemeral-keys=1":
"OPTION with-ephemeral-keys=0" ,
NULL, NULL);
- gpgsm_assuan_simple_command (gpgsm->assuan_ctx,
+ gpgsm_assuan_simple_command (gpgsm,
(mode & GPGME_KEYLIST_MODE_WITH_SECRET)?
"OPTION with-secret=1":
"OPTION with-secret=0" ,
NULL, NULL);
- gpgsm_assuan_simple_command (gpgsm->assuan_ctx,
+ gpgsm_assuan_simple_command (gpgsm,
(engine_flags & GPGME_ENGINE_FLAG_OFFLINE)?
"OPTION offline=1":
"OPTION offline=0" ,
@@ -1665,7 +1722,7 @@ gpgsm_keylist_ext (void *engine, const char *pattern[], int secret_only,
/* Always send list-mode option because RESET does not reset it. */
if (asprintf (&line, "OPTION list-mode=%d", (list_mode & 3)) < 0)
return gpg_error_from_syserror ();
- err = gpgsm_assuan_simple_command (gpgsm->assuan_ctx, line, NULL, NULL);
+ err = gpgsm_assuan_simple_command (gpgsm, line, NULL, NULL);
free (line);
if (err)
return err;
@@ -1673,17 +1730,17 @@ gpgsm_keylist_ext (void *engine, const char *pattern[], int secret_only,
/* Always send key validation because RESET does not reset it. */
/* Use the validation mode if required. We don't check for an error
yet because this is a pretty fresh gpgsm features. */
- gpgsm_assuan_simple_command (gpgsm->assuan_ctx,
+ gpgsm_assuan_simple_command (gpgsm,
(mode & GPGME_KEYLIST_MODE_VALIDATE)?
"OPTION with-validation=1":
"OPTION with-validation=0" ,
NULL, NULL);
- gpgsm_assuan_simple_command (gpgsm->assuan_ctx,
+ gpgsm_assuan_simple_command (gpgsm,
(mode & GPGME_KEYLIST_MODE_WITH_SECRET)?
"OPTION with-secret=1":
"OPTION with-secret=0" ,
NULL, NULL);
- gpgsm_assuan_simple_command (gpgsm->assuan_ctx,
+ gpgsm_assuan_simple_command (gpgsm,
(engine_flags & GPGME_ENGINE_FLAG_OFFLINE)?
"OPTION offline=1":
"OPTION offline=0" ,
@@ -1784,6 +1841,8 @@ gpgsm_sign (void *engine, gpgme_data_t in, gpgme_data_t out,
int i;
gpgme_key_t key;
+ (void)use_textmode;
+
if (!gpgsm)
return gpg_error (GPG_ERR_INV_VALUE);
@@ -1797,8 +1856,7 @@ gpgsm_sign (void *engine, gpgme_data_t in, gpgme_data_t out,
if (asprintf (&assuan_cmd, "OPTION include-certs %i", include_certs) < 0)
return gpg_error_from_syserror ();
- err = gpgsm_assuan_simple_command (gpgsm->assuan_ctx, assuan_cmd,
- NULL, NULL);
+ err = gpgsm_assuan_simple_command (gpgsm, assuan_cmd, NULL, NULL);
free (assuan_cmd);
if (err)
return err;
@@ -1812,7 +1870,7 @@ gpgsm_sign (void *engine, gpgme_data_t in, gpgme_data_t out,
char buf[100];
strcpy (stpcpy (buf, "SIGNER "), s);
- err = gpgsm_assuan_simple_command (gpgsm->assuan_ctx, buf,
+ err = gpgsm_assuan_simple_command (gpgsm, buf,
gpgsm->status.fnc,
gpgsm->status.fnc_value);
}
@@ -1913,6 +1971,17 @@ gpgsm_getauditlog (void *engine, gpgme_data_t output, unsigned int flags)
}
+/* This sets a status callback for monitoring status lines before they
+ * are passed to a caller set handler. */
+static void
+gpgsm_set_status_cb (void *engine, gpgme_status_cb_t cb, void *cb_value)
+{
+ engine_gpgsm_t gpgsm = engine;
+
+ gpgsm->status.mon_cb = cb;
+ gpgsm->status.mon_cb_value = cb_value;
+}
+
static void
gpgsm_set_status_handler (void *engine, engine_status_handler_t fnc,
@@ -1966,6 +2035,8 @@ gpgsm_passwd (void *engine, gpgme_key_t key, unsigned int flags)
gpgme_error_t err;
char *line;
+ (void)flags;
+
if (!key || !key->subkeys || !key->subkeys->fpr)
return gpg_error (GPG_ERR_INV_CERT_OBJ);
@@ -2001,6 +2072,7 @@ struct engine_ops _gpgme_engine_ops_gpgsm =
#else
NULL, /* reset */
#endif
+ gpgsm_set_status_cb,
gpgsm_set_status_handler,
NULL, /* set_command_handler */
gpgsm_set_colon_line_handler,
@@ -2018,6 +2090,8 @@ struct engine_ops _gpgme_engine_ops_gpgsm =
gpgsm_import,
gpgsm_keylist,
gpgsm_keylist_ext,
+ NULL, /* keysign */
+ NULL, /* tofu_policy */
gpgsm_sign,
NULL, /* trustlist */
gpgsm_verify,
diff --git a/src/engine-spawn.c b/src/engine-spawn.c
index eb4e038..df90cb2 100644
--- a/src/engine-spawn.c
+++ b/src/engine-spawn.c
@@ -312,24 +312,26 @@ static char *
engspawn_get_version (const char *file_name)
{
(void)file_name;
- return strdup ("1.0");
+ return NULL;
}
static const char *
engspawn_get_req_version (void)
{
- return "1.0";
+ return NULL;
}
static gpgme_error_t
-engspawn_new (void **engine, const char *file_name, const char *home_dir)
+engspawn_new (void **engine, const char *file_name, const char *home_dir,
+ const char *version)
{
engine_spawn_t esp;
(void)file_name;
(void)home_dir;
+ (void)version;
esp = calloc (1, sizeof *esp);
if (!esp)
@@ -440,6 +442,7 @@ struct engine_ops _gpgme_engine_ops_spawn =
/* Member functions. */
engspawn_release,
NULL, /* reset */
+ NULL, /* set_status_cb */
NULL, /* set_status_handler */
NULL, /* set_command_handler */
NULL, /* set_colon_line_handler */
@@ -457,6 +460,8 @@ struct engine_ops _gpgme_engine_ops_spawn =
NULL, /* import */
NULL, /* keylist */
NULL, /* keylist_ext */
+ NULL, /* keysign */
+ NULL, /* tofu_policy */
NULL, /* sign */
NULL, /* trustlist */
NULL, /* verify */
diff --git a/src/engine-uiserver.c b/src/engine-uiserver.c
index e4fd47c..63e77de 100644
--- a/src/engine-uiserver.c
+++ b/src/engine-uiserver.c
@@ -90,6 +90,8 @@ struct engine_uiserver
{
engine_status_handler_t fnc;
void *fnc_value;
+ gpgme_status_cb_t mon_cb;
+ void *mon_cb_value;
} status;
struct
@@ -121,14 +123,15 @@ static void uiserver_io_event (void *engine,
static char *
uiserver_get_version (const char *file_name)
{
- return strdup ("1.0");
+ (void)file_name;
+ return NULL;
}
static const char *
uiserver_get_req_version (void)
{
- return "1.0";
+ return NULL;
}
@@ -184,6 +187,8 @@ close_notify_handler (int fd, void *opaque)
static gpgme_error_t
default_inq_cb (engine_uiserver_t uiserver, const char *line)
{
+ (void)uiserver;
+
if (!strncmp (line, "PINENTRY_LAUNCHED", 17) && (line[17]==' '||!line[17]))
{
_gpgme_allow_set_foreground_window ((pid_t)strtoul (line+17, NULL, 10));
@@ -236,15 +241,20 @@ uiserver_release (void *engine)
static gpgme_error_t
-uiserver_new (void **engine, const char *file_name, const char *home_dir)
+uiserver_new (void **engine, const char *file_name, const char *home_dir,
+ const char *version)
{
gpgme_error_t err = 0;
engine_uiserver_t uiserver;
char *dft_display = NULL;
char dft_ttyname[64];
+ char *env_tty = NULL;
char *dft_ttytype = NULL;
char *optstr;
+ (void)home_dir;
+ (void)version; /* Not yet used. */
+
uiserver = calloc (1, sizeof *uiserver);
if (!uiserver)
return gpg_error_from_syserror ();
@@ -321,11 +331,20 @@ uiserver_new (void **engine, const char *file_name, const char *home_dir)
goto leave;
}
- if (isatty (1))
+ err = _gpgme_getenv ("GPG_TTY", &env_tty);
+ if (isatty (1) || env_tty || err)
{
- int rc;
+ int rc = 0;
- rc = ttyname_r (1, dft_ttyname, sizeof (dft_ttyname));
+ if (err)
+ goto leave;
+ else if (env_tty)
+ {
+ snprintf (dft_ttyname, sizeof (dft_ttyname), "%s", env_tty);
+ free (env_tty);
+ }
+ else
+ rc = ttyname_r (1, dft_ttyname, sizeof (dft_ttyname));
/* Even though isatty() returns 1, ttyname_r() may fail in many
ways, e.g., when /dev/pts is not accessible under chroot. */
@@ -392,7 +411,7 @@ uiserver_set_locale (void *engine, int category, const char *value)
engine_uiserver_t uiserver = engine;
gpgme_error_t err;
char *optstr;
- char *catstr;
+ const char *catstr;
/* FIXME: If value is NULL, we need to reset the option to default.
But we can't do this. So we error out here. UISERVER needs support
@@ -451,10 +470,11 @@ uiserver_set_protocol (void *engine, gpgme_protocol_t protocol)
static gpgme_error_t
-uiserver_assuan_simple_command (assuan_context_t ctx, char *cmd,
- engine_status_handler_t status_fnc,
- void *status_fnc_value)
+uiserver_assuan_simple_command (engine_uiserver_t uiserver, const char *cmd,
+ engine_status_handler_t status_fnc,
+ void *status_fnc_value)
{
+ assuan_context_t ctx = uiserver->assuan_ctx;
gpg_error_t err;
char *line;
size_t linelen;
@@ -493,8 +513,17 @@ uiserver_assuan_simple_command (assuan_context_t ctx, char *cmd,
*(rest++) = 0;
r = _gpgme_parse_status (line + 2);
+ if (uiserver->status.mon_cb && r != GPGME_STATUS_PROGRESS)
+ {
+ /* Note that we call the monitor even if we do
+ * not know the status code (r < 0). */
+ err = uiserver->status.mon_cb (uiserver->status.mon_cb_value,
+ line + 2, rest);
+ }
- if (r >= 0 && status_fnc)
+ if (err)
+ ;
+ else if (r >= 0 && status_fnc)
err = status_fnc (status_fnc_value, r, rest);
else
err = gpg_error (GPG_ERR_GENERAL);
@@ -516,7 +545,7 @@ uiserver_set_fd (engine_uiserver_t uiserver, fd_type_t fd_type, const char *opt)
{
gpg_error_t err = 0;
char line[COMMANDLINELEN];
- char *which;
+ const char *which;
iocb_data_t *iocb_data;
int dir;
@@ -576,7 +605,7 @@ uiserver_set_fd (engine_uiserver_t uiserver, fd_type_t fd_type, const char *opt)
else
snprintf (line, COMMANDLINELEN, "%s FD", which);
- err = uiserver_assuan_simple_command (uiserver->assuan_ctx, line, NULL, NULL);
+ err = uiserver_assuan_simple_command (uiserver, line, NULL, NULL);
leave_set_fd:
if (err)
@@ -653,8 +682,13 @@ status_handler (void *opaque, int fd)
&& (line[2] == '\0' || line[2] == ' '))
{
if (uiserver->status.fnc)
- err = uiserver->status.fnc (uiserver->status.fnc_value,
- GPGME_STATUS_EOF, "");
+ {
+ char emptystring[1] = {0};
+ err = uiserver->status.fnc (uiserver->status.fnc_value,
+ GPGME_STATUS_EOF, emptystring);
+ if (gpg_err_code (err) == GPG_ERR_FALSE)
+ err = 0; /* Drop special error code. */
+ }
if (!err && uiserver->colon.fnc && uiserver->colon.any)
{
@@ -805,7 +839,12 @@ status_handler (void *opaque, int fd)
if (r >= 0)
{
if (uiserver->status.fnc)
- err = uiserver->status.fnc (uiserver->status.fnc_value, r, rest);
+ {
+ err = uiserver->status.fnc (uiserver->status.fnc_value,
+ r, rest);
+ if (gpg_err_code (err) == GPG_ERR_FALSE)
+ err = 0; /* Drop special error code. */
+ }
}
else
fprintf (stderr, "[UNKNOWN STATUS]%s %s", line + 2, rest);
@@ -915,7 +954,7 @@ uiserver_reset (void *engine)
/* We must send a reset because we need to reset the list of
signers. Note that RESET does not reset OPTION commands. */
- return uiserver_assuan_simple_command (uiserver->assuan_ctx, "RESET", NULL, NULL);
+ return uiserver_assuan_simple_command (uiserver, "RESET", NULL, NULL);
}
@@ -984,7 +1023,6 @@ static gpgme_error_t
set_recipients (engine_uiserver_t uiserver, gpgme_key_t recp[])
{
gpgme_error_t err = 0;
- assuan_context_t ctx = uiserver->assuan_ctx;
char *line;
int linelen;
int invalid_recipients = 0;
@@ -1023,7 +1061,8 @@ set_recipients (engine_uiserver_t uiserver, gpgme_key_t recp[])
/* FIXME: need to do proper escaping */
strcpy (&line[10], uid);
- err = uiserver_assuan_simple_command (ctx, line, uiserver->status.fnc,
+ err = uiserver_assuan_simple_command (uiserver, line,
+ uiserver->status.fnc,
uiserver->status.fnc_value);
/* FIXME: This might requires more work. */
if (gpg_err_code (err) == GPG_ERR_NO_PUBKEY)
@@ -1132,6 +1171,9 @@ uiserver_sign (void *engine, gpgme_data_t in, gpgme_data_t out,
char *cmd;
gpgme_key_t key;
+ (void)use_textmode;
+ (void)include_certs;
+
if (!uiserver || !in || !out)
return gpg_error (GPG_ERR_INV_VALUE);
if (uiserver->protocol == GPGME_PROTOCOL_DEFAULT)
@@ -1160,7 +1202,7 @@ uiserver_sign (void *engine, gpgme_data_t in, gpgme_data_t out,
char buf[100];
strcpy (stpcpy (buf, "SENDER --info "), s);
- err = uiserver_assuan_simple_command (uiserver->assuan_ctx, buf,
+ err = uiserver_assuan_simple_command (uiserver, buf,
uiserver->status.fnc,
uiserver->status.fnc_value);
}
@@ -1252,6 +1294,18 @@ uiserver_verify (void *engine, gpgme_data_t sig, gpgme_data_t signed_text,
}
+/* This sets a status callback for monitoring status lines before they
+ * are passed to a caller set handler. */
+static void
+uiserver_set_status_cb (void *engine, gpgme_status_cb_t cb, void *cb_value)
+{
+ engine_uiserver_t uiserver = engine;
+
+ uiserver->status.mon_cb = cb;
+ uiserver->status.mon_cb_value = cb_value;
+}
+
+
static void
uiserver_set_status_handler (void *engine, engine_status_handler_t fnc,
void *fnc_value)
@@ -1309,6 +1363,7 @@ struct engine_ops _gpgme_engine_ops_uiserver =
/* Member functions. */
uiserver_release,
uiserver_reset,
+ uiserver_set_status_cb,
uiserver_set_status_handler,
NULL, /* set_command_handler */
uiserver_set_colon_line_handler,
@@ -1326,6 +1381,8 @@ struct engine_ops _gpgme_engine_ops_uiserver =
NULL, /* import */
NULL, /* keylist */
NULL, /* keylist_ext */
+ NULL, /* keysign */
+ NULL, /* tofu_policy */
uiserver_sign,
NULL, /* trustlist */
uiserver_verify,
diff --git a/src/engine.c b/src/engine.c
index 8e84da9..a1173a0 100644
--- a/src/engine.c
+++ b/src/engine.c
@@ -63,6 +63,10 @@ static struct engine_ops *engine_ops[] =
static gpgme_engine_info_t engine_info;
DEFINE_STATIC_LOCK (engine_info_lock);
+/* If non-NULL, the minimal version required for all engines. */
+static char *engine_minimal_version;
+
+
/* Get the file name of the engine for PROTOCOL. */
static const char *
@@ -93,7 +97,8 @@ engine_get_home_dir (gpgme_protocol_t proto)
/* Get a malloced string containing the version number of the engine
- for PROTOCOL. */
+ * for PROTOCOL. If this function returns NULL for a valid protocol,
+ * it should be assumed that the engine is a pseudo engine. */
static char *
engine_get_version (gpgme_protocol_t proto, const char *file_name)
{
@@ -107,7 +112,8 @@ engine_get_version (gpgme_protocol_t proto, const char *file_name)
}
-/* Get the required version number of the engine for PROTOCOL. */
+/* Get the required version number of the engine for PROTOCOL. This
+ * may be NULL. */
static const char *
engine_get_req_version (gpgme_protocol_t proto)
{
@@ -164,8 +170,8 @@ _gpgme_engine_info_release (gpgme_engine_info_t info)
{
gpgme_engine_info_t next_info = info->next;
- assert (info->file_name);
- free (info->file_name);
+ if (info->file_name)
+ free (info->file_name);
if (info->home_dir)
free (info->home_dir);
if (info->version)
@@ -176,6 +182,26 @@ _gpgme_engine_info_release (gpgme_engine_info_t info)
}
+/* This is an internal function to set a mimimal required version.
+ * This function must only be called by gpgme_set_global_flag.
+ * Returns 0 on success. */
+int
+_gpgme_set_engine_minimal_version (const char *value)
+{
+ free (engine_minimal_version);
+ if (value)
+ {
+ engine_minimal_version = strdup (value);
+ return !engine_minimal_version;
+ }
+ else
+ {
+ engine_minimal_version = NULL;
+ return 0;
+ }
+}
+
+
/* Get the information about the configured and installed engines. A
pointer to the first engine in the statically allocated linked list
is returned in *INFO. If an error occurs, it is returned. The
@@ -203,6 +229,7 @@ gpgme_get_engine_info (gpgme_engine_info_t *info)
{
const char *ofile_name = engine_get_file_name (proto_list[proto]);
const char *ohome_dir = engine_get_home_dir (proto_list[proto]);
+ char *version = engine_get_version (proto_list[proto], NULL);
char *file_name;
char *home_dir;
@@ -222,10 +249,29 @@ gpgme_get_engine_info (gpgme_engine_info_t *info)
else
home_dir = NULL;
- *lastp = malloc (sizeof (*engine_info));
+ *lastp = calloc (1, sizeof (*engine_info));
if (!*lastp && !err)
err = gpg_error_from_syserror ();
+ /* Check against the optional minimal engine version. */
+ if (!err && version && engine_minimal_version
+ && !_gpgme_compare_versions (version, engine_minimal_version))
+ {
+#if GPG_ERROR_VERSION_NUMBER < 0x011900 /* 1.25 */
+ err = gpg_error (GPG_ERR_NO_ENGINE);
+#else
+ err = gpg_error (GPG_ERR_ENGINE_TOO_OLD);
+#endif
+ }
+
+ /* Now set the dummy version for pseudo engines. */
+ if (!err && !version)
+ {
+ version = strdup ("1.0.0");
+ if (!version)
+ err = gpg_error_from_syserror ();
+ }
+
if (err)
{
_gpgme_engine_info_release (engine_info);
@@ -235,6 +281,8 @@ gpgme_get_engine_info (gpgme_engine_info_t *info)
free (file_name);
if (home_dir)
free (home_dir);
+ if (version)
+ free (version);
UNLOCK (engine_info_lock);
return err;
@@ -243,8 +291,10 @@ gpgme_get_engine_info (gpgme_engine_info_t *info)
(*lastp)->protocol = proto_list[proto];
(*lastp)->file_name = file_name;
(*lastp)->home_dir = home_dir;
- (*lastp)->version = engine_get_version (proto_list[proto], NULL);
+ (*lastp)->version = version;
(*lastp)->req_version = engine_get_req_version (proto_list[proto]);
+ if (!(*lastp)->req_version)
+ (*lastp)->req_version = "1.0.0"; /* Dummy for pseudo engines. */
(*lastp)->next = NULL;
lastp = &(*lastp)->next;
}
@@ -353,6 +403,7 @@ _gpgme_set_engine_info (gpgme_engine_info_t info, gpgme_protocol_t proto,
{
char *new_file_name;
char *new_home_dir;
+ char *new_version;
/* FIXME: Use some PROTO_MAX definition. */
if (proto > DIM (engine_ops))
@@ -401,6 +452,17 @@ _gpgme_set_engine_info (gpgme_engine_info_t info, gpgme_protocol_t proto,
new_home_dir = NULL;
}
+ new_version = engine_get_version (proto, new_file_name);
+ if (!new_version)
+ {
+ new_version = strdup ("1.0.0"); /* Fake one for dummy entries. */
+ if (!new_version)
+ {
+ free (new_file_name);
+ free (new_home_dir);
+ }
+ }
+
/* Remove the old members. */
assert (info->file_name);
free (info->file_name);
@@ -412,7 +474,7 @@ _gpgme_set_engine_info (gpgme_engine_info_t info, gpgme_protocol_t proto,
/* Install the new members. */
info->file_name = new_file_name;
info->home_dir = new_home_dir;
- info->version = engine_get_version (proto, new_file_name);
+ info->version = new_version;
return 0;
}
@@ -463,7 +525,8 @@ _gpgme_engine_new (gpgme_engine_info_t info, engine_t *r_engine)
{
gpgme_error_t err;
err = (*engine->ops->new) (&engine->engine,
- info->file_name, info->home_dir);
+ info->file_name, info->home_dir,
+ info->version);
if (err)
{
free (engine);
@@ -503,6 +566,21 @@ _gpgme_engine_release (engine_t engine)
}
+/* Set a status callback which is used to monitor the status values
+ * before they are passed to a handler set with
+ * _gpgme_engine_set_status_handler. */
+void
+_gpgme_engine_set_status_cb (engine_t engine,
+ gpgme_status_cb_t cb, void *cb_value)
+{
+ if (!engine)
+ return;
+
+ if (engine->ops->set_status_cb)
+ (*engine->ops->set_status_cb) (engine->engine, cb, cb_value);
+}
+
+
void
_gpgme_engine_set_status_handler (engine_t engine,
engine_status_handler_t fnc, void *fnc_value)
@@ -695,9 +773,13 @@ _gpgme_engine_op_export_ext (engine_t engine, const char *pattern[],
gpgme_error_t
-_gpgme_engine_op_genkey (engine_t engine, gpgme_data_t help_data,
- int use_armor, gpgme_data_t pubkey,
- gpgme_data_t seckey)
+_gpgme_engine_op_genkey (engine_t engine,
+ const char *userid, const char *algo,
+ unsigned long reserved, unsigned long expires,
+ gpgme_key_t key, unsigned int flags,
+ gpgme_data_t help_data,
+ unsigned int extraflags,
+ gpgme_data_t pubkey, gpgme_data_t seckey)
{
if (!engine)
return gpg_error (GPG_ERR_INV_VALUE);
@@ -705,12 +787,44 @@ _gpgme_engine_op_genkey (engine_t engine, gpgme_data_t help_data,
if (!engine->ops->genkey)
return gpg_error (GPG_ERR_NOT_IMPLEMENTED);
- return (*engine->ops->genkey) (engine->engine, help_data, use_armor,
+ return (*engine->ops->genkey) (engine->engine,
+ userid, algo, reserved, expires, key, flags,
+ help_data, extraflags,
pubkey, seckey);
}
gpgme_error_t
+_gpgme_engine_op_keysign (engine_t engine, gpgme_key_t key, const char *userid,
+ unsigned long expires, unsigned int flags,
+ gpgme_ctx_t ctx)
+{
+ if (!engine)
+ return gpg_error (GPG_ERR_INV_VALUE);
+
+ if (!engine->ops->keysign)
+ return gpg_error (GPG_ERR_NOT_IMPLEMENTED);
+
+ return (*engine->ops->keysign) (engine->engine,
+ key, userid, expires, flags, ctx);
+}
+
+
+gpgme_error_t
+_gpgme_engine_op_tofu_policy (engine_t engine,
+ gpgme_key_t key, gpgme_tofu_policy_t policy)
+{
+ if (!engine)
+ return gpg_error (GPG_ERR_INV_VALUE);
+
+ if (!engine->ops->tofu_policy)
+ return gpg_error (GPG_ERR_NOT_IMPLEMENTED);
+
+ return (*engine->ops->tofu_policy) (engine->engine, key, policy);
+}
+
+
+gpgme_error_t
_gpgme_engine_op_import (engine_t engine, gpgme_data_t keydata,
gpgme_key_t *keyarray)
{
diff --git a/src/engine.h b/src/engine.h
index 56fcc42..4ce2bed 100644
--- a/src/engine.h
+++ b/src/engine.h
@@ -24,6 +24,11 @@
#include "gpgme.h"
+/* Flags used by the EXTRAFLAGS arg of _gpgme_engine_op_genkey. */
+#define GENKEY_EXTRAFLAG_ARMOR 1
+#define GENKEY_EXTRAFLAG_REVOKE 2
+
+
struct engine;
typedef struct engine *engine_t;
@@ -38,6 +43,8 @@ typedef gpgme_error_t (*engine_command_handler_t) (void *priv,
typedef gpgme_error_t (*engine_assuan_result_cb_t) (void *priv,
gpgme_error_t result);
+/* Helper for gpgme_set_global_flag. */
+int _gpgme_set_engine_minimal_version (const char *value);
/* Get a deep copy of the engine info and return it in INFO. */
gpgme_error_t _gpgme_engine_info_copy (gpgme_engine_info_t *r_info);
@@ -62,6 +69,8 @@ gpgme_error_t _gpgme_engine_set_locale (engine_t engine, int category,
gpgme_error_t _gpgme_engine_set_protocol (engine_t engine,
gpgme_protocol_t protocol);
void _gpgme_engine_release (engine_t engine);
+void _gpgme_engine_set_status_cb (engine_t engine,
+ gpgme_status_cb_t cb, void *cb_value);
void _gpgme_engine_set_status_handler (engine_t engine,
engine_status_handler_t fnc,
void *fnc_value);
@@ -104,9 +113,22 @@ gpgme_error_t _gpgme_engine_op_export_ext (engine_t engine,
gpgme_data_t keydata,
int use_armor);
gpgme_error_t _gpgme_engine_op_genkey (engine_t engine,
+ const char *userid, const char *algo,
+ unsigned long reserved,
+ unsigned long expires,
+ gpgme_key_t key, unsigned int flags,
gpgme_data_t help_data,
- int use_armor, gpgme_data_t pubkey,
+ unsigned int extraflags,
+ gpgme_data_t pubkey,
gpgme_data_t seckey);
+gpgme_error_t _gpgme_engine_op_keysign (engine_t engine,
+ gpgme_key_t key, const char *userid,
+ unsigned long expires,
+ unsigned int flags,
+ gpgme_ctx_t ctx);
+gpgme_error_t _gpgme_engine_op_tofu_policy (engine_t engine,
+ gpgme_key_t key,
+ gpgme_tofu_policy_t policy);
gpgme_error_t _gpgme_engine_op_import (engine_t engine,
gpgme_data_t keydata,
gpgme_key_t *keyarray);
diff --git a/src/export.c b/src/export.c
index a29fbde..41a9eba 100644
--- a/src/export.c
+++ b/src/export.c
@@ -34,7 +34,7 @@
/* Local operation data. */
typedef struct
{
- gpg_error_t err; /* Error encountred during the export. */
+ gpg_error_t err; /* Error encountered during the export. */
} *op_data_t;
diff --git a/src/funopen.c b/src/funopen.c
index b71d3ae..b722020 100644
--- a/src/funopen.c
+++ b/src/funopen.c
@@ -35,7 +35,7 @@
The functions to provide my either be NULL if not required or
similar to the unistd function with the exception of using the
- cookie instead of the fiel descripor.
+ cookie instead of the file descriptor.
*/
diff --git a/src/genkey.c b/src/genkey.c
index 3afd3b4..9dcf0be 100644
--- a/src/genkey.c
+++ b/src/genkey.c
@@ -1,23 +1,22 @@
/* genkey.c - Key generation.
- Copyright (C) 2000 Werner Koch (dd9jn)
- Copyright (C) 2001, 2002, 2003, 2004 g10 Code GmbH
-
- This file is part of GPGME.
-
- GPGME is free software; you can redistribute it and/or modify it
- under the terms of the GNU Lesser General Public License as
- published by the Free Software Foundation; either version 2.1 of
- the License, or (at your option) any later version.
-
- GPGME is distributed in the hope that it will be useful, but
- WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- Lesser General Public License for more details.
-
- You should have received a copy of the GNU Lesser General Public
- License along with this program; if not, write to the Free Software
- Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
- 02111-1307, USA. */
+ * Copyright (C) 2000 Werner Koch (dd9jn)
+ * Copyright (C) 2001, 2002, 2003, 2004, 2016 g10 Code GmbH
+ *
+ * This file is part of GPGME.
+ *
+ * GPGME is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU Lesser General Public License as
+ * published by the Free Software Foundation; either version 2.1 of
+ * the License, or (at your option) any later version.
+ *
+ * GPGME is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this program; if not, see <http://www.gnu.org/licenses/>.
+ */
#if HAVE_CONFIG_H
#include <config.h>
@@ -40,6 +39,12 @@ typedef struct
/* The error code from a FAILURE status line or 0. */
gpg_error_t failure_code;
+ /* The error code from certain ERROR status lines or 0. */
+ gpg_error_t error_code;
+
+ /* Flag to indicate that a UID is to be added. */
+ gpg_error_t uidmode;
+
/* The key parameters passed to the crypto engine. */
gpgme_data_t key_parameter;
} *op_data_t;
@@ -82,7 +87,39 @@ gpgme_op_genkey_result (gpgme_ctx_t ctx)
return &opd->result;
}
+
+/* Parse an error status line. Return the error location and the
+ error code. The function may modify ARGS. */
+static char *
+parse_error (char *args, gpg_error_t *r_err)
+{
+ char *where = strchr (args, ' ');
+ char *which;
+
+ if (where)
+ {
+ *where = '\0';
+ which = where + 1;
+
+ where = strchr (which, ' ');
+ if (where)
+ *where = '\0';
+
+ where = args;
+ }
+ else
+ {
+ *r_err = trace_gpg_error (GPG_ERR_INV_ENGINE);
+ return NULL;
+ }
+
+ *r_err = atoi (which);
+
+ return where;
+}
+
+
static gpgme_error_t
genkey_status_handler (void *priv, gpgme_status_code_t code, char *args)
{
@@ -90,6 +127,7 @@ genkey_status_handler (void *priv, gpgme_status_code_t code, char *args)
gpgme_error_t err;
void *hook;
op_data_t opd;
+ char *loc;
/* Pipe the status code through the progress status handler. */
err = _gpgme_progress_status_handler (ctx, code, args);
@@ -107,7 +145,10 @@ genkey_status_handler (void *priv, gpgme_status_code_t code, char *args)
if (args && *args)
{
if (*args == 'B' || *args == 'P')
- opd->result.primary = 1;
+ {
+ opd->result.primary = 1;
+ opd->result.uid = 1;
+ }
if (*args == 'B' || *args == 'S')
opd->result.sub = 1;
if (args[1] == ' ')
@@ -121,20 +162,31 @@ genkey_status_handler (void *priv, gpgme_status_code_t code, char *args)
}
break;
+ case GPGME_STATUS_ERROR:
+ loc = parse_error (args, &err);
+ if (!loc)
+ return err;
+ if (!opd->error_code)
+ opd->error_code = err;
+ break;
+
case GPGME_STATUS_FAILURE:
opd->failure_code = _gpgme_parse_failure (args);
break;
case GPGME_STATUS_EOF:
- /* FIXME: Should return some more useful error value. */
- if (!opd->result.primary && !opd->result.sub)
+ if (opd->error_code)
+ return opd->error_code;
+ else if (!opd->uidmode && !opd->result.primary && !opd->result.sub)
return gpg_error (GPG_ERR_GENERAL);
else if (opd->failure_code)
return opd->failure_code;
+ else if (opd->uidmode == 1)
+ opd->result.uid = 1; /* We have no status line, thus this hack. */
break;
case GPGME_STATUS_INQUIRE_MAXLEN:
- if (ctx->status_cb)
+ if (ctx->status_cb && !ctx->full_status)
{
err = ctx->status_cb (ctx->status_cb_value, "INQUIRE_MAXLEN", args);
if (err)
@@ -212,8 +264,11 @@ genkey_start (gpgme_ctx_t ctx, int synchronous, const char *parms,
return err;
}
- return _gpgme_engine_op_genkey (ctx->engine, opd->key_parameter,
- ctx->use_armor, pubkey, seckey);
+ return _gpgme_engine_op_genkey (ctx->engine,
+ NULL, NULL, 0, 0, NULL, 0,
+ opd->key_parameter,
+ ctx->use_armor? GENKEY_EXTRAFLAG_ARMOR:0,
+ pubkey, seckey);
}
@@ -231,7 +286,7 @@ gpgme_op_genkey_start (gpgme_ctx_t ctx, const char *parms,
TRACE_LOGBUF (parms, strlen (parms));
if (!ctx)
- return TRACE_ERR (gpg_error (GPG_ERR_INV_VALUE));
+ return TRACE_ERR (gpg_error (GPG_ERR_INV_ARG));
err = genkey_start (ctx, 0, parms, pubkey, seckey);
return TRACE_ERR (err);
@@ -252,10 +307,302 @@ gpgme_op_genkey (gpgme_ctx_t ctx, const char *parms, gpgme_data_t pubkey,
TRACE_LOGBUF (parms, strlen (parms));
if (!ctx)
- return TRACE_ERR (gpg_error (GPG_ERR_INV_VALUE));
+ return TRACE_ERR (gpg_error (GPG_ERR_INV_ARG));
err = genkey_start (ctx, 1, parms, pubkey, seckey);
if (!err)
err = _gpgme_wait_one (ctx);
return TRACE_ERR (err);
}
+
+
+
+static gpgme_error_t
+createkey_start (gpgme_ctx_t ctx, int synchronous,
+ const char *userid, const char *algo,
+ unsigned long reserved, unsigned long expires,
+ gpgme_key_t anchorkey, unsigned int flags)
+{
+ gpgme_error_t err;
+ void *hook;
+ op_data_t opd;
+
+ err = _gpgme_op_reset (ctx, synchronous);
+ if (err)
+ return err;
+
+ if (reserved || anchorkey || !userid)
+ return gpg_error (GPG_ERR_INV_ARG);
+
+ err = _gpgme_op_data_lookup (ctx, OPDATA_GENKEY, &hook,
+ sizeof (*opd), release_op_data);
+ opd = hook;
+ if (err)
+ return err;
+
+ _gpgme_engine_set_status_handler (ctx->engine, genkey_status_handler, ctx);
+
+ if (ctx->passphrase_cb)
+ {
+ err = _gpgme_engine_set_command_handler
+ (ctx->engine, _gpgme_passphrase_command_handler, ctx, NULL);
+ if (err)
+ return err;
+ }
+
+ return _gpgme_engine_op_genkey (ctx->engine,
+ userid, algo, reserved, expires,
+ anchorkey, flags,
+ NULL,
+ ctx->use_armor? GENKEY_EXTRAFLAG_ARMOR:0,
+ NULL, NULL);
+
+}
+
+
+gpgme_error_t
+gpgme_op_createkey_start (gpgme_ctx_t ctx, const char *userid, const char *algo,
+ unsigned long reserved, unsigned long expires,
+ gpgme_key_t anchorkey, unsigned int flags)
+{
+ gpgme_error_t err;
+
+ TRACE_BEG3 (DEBUG_CTX, "gpgme_op_createkey_start", ctx,
+ "userid='%s', algo='%s' flags=0x%x", userid, algo, flags);
+
+ if (!ctx)
+ return TRACE_ERR (gpg_error (GPG_ERR_INV_ARG));
+
+ err = createkey_start (ctx, 0,
+ userid, algo, reserved, expires, anchorkey, flags);
+ return TRACE_ERR (err);
+}
+
+
+gpgme_error_t
+gpgme_op_createkey (gpgme_ctx_t ctx, const char *userid, const char *algo,
+ unsigned long reserved, unsigned long expires,
+ gpgme_key_t anchorkey, unsigned int flags)
+{
+ gpgme_error_t err;
+
+ TRACE_BEG3 (DEBUG_CTX, "gpgme_op_createkey", ctx,
+ "userid='%s', algo='%s' flags=0x%x", userid, algo, flags);
+
+ if (!ctx)
+ return TRACE_ERR (gpg_error (GPG_ERR_INV_ARG));
+
+ err = createkey_start (ctx, 1,
+ userid, algo, reserved, expires, anchorkey, flags);
+ if (!err)
+ err = _gpgme_wait_one (ctx);
+ return TRACE_ERR (err);
+}
+
+
+
+static gpgme_error_t
+createsubkey_start (gpgme_ctx_t ctx, int synchronous,
+ gpgme_key_t key,
+ const char *algo,
+ unsigned long reserved, unsigned long expires,
+ unsigned int flags)
+{
+ gpgme_error_t err;
+ void *hook;
+ op_data_t opd;
+
+ if (ctx->protocol != GPGME_PROTOCOL_OPENPGP)
+ return gpgme_error (GPG_ERR_UNSUPPORTED_PROTOCOL);
+
+ err = _gpgme_op_reset (ctx, synchronous);
+ if (err)
+ return err;
+
+ if (reserved || !key)
+ return gpg_error (GPG_ERR_INV_ARG);
+
+ err = _gpgme_op_data_lookup (ctx, OPDATA_GENKEY, &hook,
+ sizeof (*opd), release_op_data);
+ opd = hook;
+ if (err)
+ return err;
+
+ _gpgme_engine_set_status_handler (ctx->engine, genkey_status_handler, ctx);
+
+ if (ctx->passphrase_cb)
+ {
+ err = _gpgme_engine_set_command_handler
+ (ctx->engine, _gpgme_passphrase_command_handler, ctx, NULL);
+ if (err)
+ return err;
+ }
+
+ return _gpgme_engine_op_genkey (ctx->engine,
+ NULL, algo, reserved, expires,
+ key, flags,
+ NULL,
+ ctx->use_armor? GENKEY_EXTRAFLAG_ARMOR:0,
+ NULL, NULL);
+
+}
+
+
+/* Add a subkey to an existing KEY. */
+gpgme_error_t
+gpgme_op_createsubkey_start (gpgme_ctx_t ctx, gpgme_key_t key, const char *algo,
+ unsigned long reserved, unsigned long expires,
+ unsigned int flags)
+{
+ gpgme_error_t err;
+
+ TRACE_BEG3 (DEBUG_CTX, "gpgme_op_createsubkey_start", ctx,
+ "key=%p, algo='%s' flags=0x%x", key, algo, flags);
+
+ if (!ctx)
+ return TRACE_ERR (gpg_error (GPG_ERR_INV_ARG));
+
+ err = createsubkey_start (ctx, 0, key, algo, reserved, expires, flags);
+ return TRACE_ERR (err);
+}
+
+
+gpgme_error_t
+gpgme_op_createsubkey (gpgme_ctx_t ctx, gpgme_key_t key, const char *algo,
+ unsigned long reserved, unsigned long expires,
+ unsigned int flags)
+{
+ gpgme_error_t err;
+
+ TRACE_BEG3 (DEBUG_CTX, "gpgme_op_createsubkey", ctx,
+ "key=%p, algo='%s' flags=0x%x", key, algo, flags);
+
+ if (!ctx)
+ return TRACE_ERR (gpg_error (GPG_ERR_INV_ARG));
+
+ err = createsubkey_start (ctx, 1, key, algo, reserved, expires, flags);
+ if (!err)
+ err = _gpgme_wait_one (ctx);
+ return TRACE_ERR (err);
+}
+
+
+
+static gpgme_error_t
+addrevuid_start (gpgme_ctx_t ctx, int synchronous, int revoke,
+ gpgme_key_t key, const char *userid, unsigned int flags)
+{
+ gpgme_error_t err;
+ void *hook;
+ op_data_t opd;
+
+ if (ctx->protocol != GPGME_PROTOCOL_OPENPGP)
+ return gpgme_error (GPG_ERR_UNSUPPORTED_PROTOCOL);
+
+ if (!key || !userid)
+ return gpg_error (GPG_ERR_INV_ARG);
+
+ err = _gpgme_op_reset (ctx, synchronous);
+ if (err)
+ return err;
+
+ err = _gpgme_op_data_lookup (ctx, OPDATA_GENKEY, &hook,
+ sizeof (*opd), release_op_data);
+ opd = hook;
+ if (err)
+ return err;
+
+ opd->uidmode = revoke? 2 : 1;
+
+ _gpgme_engine_set_status_handler (ctx->engine, genkey_status_handler, ctx);
+
+ if (ctx->passphrase_cb)
+ {
+ err = _gpgme_engine_set_command_handler
+ (ctx->engine, _gpgme_passphrase_command_handler, ctx, NULL);
+ if (err)
+ return err;
+ }
+
+ return _gpgme_engine_op_genkey (ctx->engine,
+ userid, NULL, 0, 0,
+ key, flags,
+ NULL,
+ revoke? GENKEY_EXTRAFLAG_REVOKE : 0,
+ NULL, NULL);
+
+}
+
+
+/* Add USERID to an existing KEY. */
+gpgme_error_t
+gpgme_op_adduid_start (gpgme_ctx_t ctx,
+ gpgme_key_t key, const char *userid, unsigned int flags)
+{
+ gpgme_error_t err;
+
+ TRACE_BEG2 (DEBUG_CTX, "gpgme_op_adduid_start", ctx,
+ "uid='%s' flags=0x%x", userid, flags);
+
+ if (!ctx)
+ return TRACE_ERR (gpg_error (GPG_ERR_INV_ARG));
+
+ err = addrevuid_start (ctx, 0, 0, key, userid, flags);
+ return TRACE_ERR (err);
+}
+
+
+gpgme_error_t
+gpgme_op_adduid (gpgme_ctx_t ctx,
+ gpgme_key_t key, const char *userid, unsigned int flags)
+{
+ gpgme_error_t err;
+
+ TRACE_BEG2 (DEBUG_CTX, "gpgme_op_adduid", ctx,
+ "uid='%s' flags=0x%x", userid, flags);
+
+ if (!ctx)
+ return TRACE_ERR (gpg_error (GPG_ERR_INV_ARG));
+
+ err = addrevuid_start (ctx, 1, 0, key, userid, flags);
+ if (!err)
+ err = _gpgme_wait_one (ctx);
+ return TRACE_ERR (err);
+}
+
+
+/* Revoke USERID from KEY. */
+gpgme_error_t
+gpgme_op_revuid_start (gpgme_ctx_t ctx,
+ gpgme_key_t key, const char *userid, unsigned int flags)
+{
+ gpgme_error_t err;
+
+ TRACE_BEG2 (DEBUG_CTX, "gpgme_op_revuid_start", ctx,
+ "uid='%s' flags=0x%x", userid, flags);
+
+ if (!ctx)
+ return TRACE_ERR (gpg_error (GPG_ERR_INV_ARG));
+
+ err = addrevuid_start (ctx, 0, 1, key, userid, flags);
+ return TRACE_ERR (err);
+}
+
+
+gpgme_error_t
+gpgme_op_revuid (gpgme_ctx_t ctx,
+ gpgme_key_t key, const char *userid, unsigned int flags)
+{
+ gpgme_error_t err;
+
+ TRACE_BEG2 (DEBUG_CTX, "gpgme_op_revuid", ctx,
+ "uid='%s' flags=0x%x", userid, flags);
+
+ if (!ctx)
+ return TRACE_ERR (gpg_error (GPG_ERR_INV_ARG));
+
+ err = addrevuid_start (ctx, 1, 1, key, userid, flags);
+ if (!err)
+ err = _gpgme_wait_one (ctx);
+ return TRACE_ERR (err);
+}
diff --git a/src/getauditlog.c b/src/getauditlog.c
index 3bb4138..e2ba25e 100644
--- a/src/getauditlog.c
+++ b/src/getauditlog.c
@@ -31,6 +31,9 @@
static gpgme_error_t
getauditlog_status_handler (void *priv, gpgme_status_code_t code, char *args)
{
+ (void)priv;
+ (void)code;
+ (void)args;
return 0;
}
diff --git a/src/gpgme-config.in b/src/gpgme-config.in
index 4be1e08..0d9fda2 100644
--- a/src/gpgme-config.in
+++ b/src/gpgme-config.in
@@ -36,6 +36,8 @@ thread_modules=""
libs_pthread="-lpthread"
cflags_pthread=""
+avail_lang='c @GPGME_CONFIG_AVAIL_LANG@'
+
# Configure glib.
libs_glib="@GLIB_LIBS@"
cflags_glib="@GLIB_CFLAGS@"
@@ -48,16 +50,16 @@ usage()
cat <<EOF
Usage: gpgme-config [OPTIONS]
Options:
- [--thread={${thread_modules}}]
- [--prefix]
- [--exec-prefix]
- [--version]
- [--api-version]
- [--host]
- [--libs]
- [--cflags]
- [--get-gpg]
- [--get-gpgsm]
+ --thread={${thread_modules}}]
+ --prefix
+ --exec-prefix
+ --version
+ --api-version
+ --host
+ --libs
+ --cflags
+ --print-lang Print available language bindings
+ --have-lang=LANG Return success if LANG is available
EOF
exit $1
}
@@ -178,10 +180,23 @@ while test $# -gt 0; do
usage 1 1>&2
fi
;;
+ --print-lang)
+ output="$avail_lang"
+ ;;
+ --have-lang=*)
+ for lang in $avail_lang; do
+ if test x"$lang" = x"$optarg"; then
+ exit 0
+ fi
+ done
+ exit 1
+ ;;
--get-gpg)
+ # Deprecated
output="$output @GPG@"
;;
--get-gpgsm)
+ # Deprecated
output="$output @GPGSM@"
;;
*)
diff --git a/src/gpgme-tool.c b/src/gpgme-tool.c
index e5e5707..fb158f1 100644
--- a/src/gpgme-tool.c
+++ b/src/gpgme-tool.c
@@ -32,12 +32,10 @@
#ifdef HAVE_LOCALE_H
#include <locale.h>
#endif
-#ifdef HAVE_ARGP_H
-#include <argp.h>
-#endif
#include <assuan.h>
+#include "argparse.h"
#include "gpgme.h"
/* GCC attributes. */
@@ -60,421 +58,6 @@
-#ifndef HAVE_ARGP_H
-/* Minimal argp implementation. */
-
-/* Differences to ARGP:
- argp_program_version: Required.
- argp_program_bug_address: Required.
- argp_program_version_hook: Not supported.
- argp_err_exit_status: Required.
- struct argp: Children and help_filter not supported.
- argp_domain: Not supported.
- struct argp_option: Group not supported. Options are printed in
- order given. Flags OPTION_ALIAS, OPTION_DOC and OPTION_NO_USAGE
- are not supported.
- argp_parse: No flags are supported (ARGP_PARSE_ARGV0, ARGP_NO_ERRS,
- ARGP_NO_ARGS, ARGP_IN_ORDER, ARGP_NO_HELP, ARGP_NO_EXIT,
- ARGP_LONG_ONLY, ARGP_SILENT). ARGP must not be NULL.
- argp_help: Flag ARGP_HELP_LONG_ONLY not supported.
- argp_state: argc, argv, next may not be modified and should not be used. */
-
-extern const char *argp_program_version;
-extern const char *argp_program_bug_address;
-extern error_t argp_err_exit_status;
-
-struct argp_option
-{
- const char *name;
- int key;
- const char *arg;
-#define OPTION_ARG_OPTIONAL 0x1
-#define OPTION_HIDDEN 0x2
- int flags;
- const char *doc;
- int group;
-};
-
-struct argp;
-struct argp_state
-{
- const struct argp *const root_argp;
- int argc;
- char **argv;
- int next;
- unsigned flags;
- unsigned arg_num;
- int quoted;
- void *input;
- void **child_inputs;
- void *hook;
- char *name;
- FILE *err_stream;
- FILE *out_stream;
- void *pstate;
-};
-
-#ifdef EDEADLK
-# define ARGP_ERR_UNKNOWN EDEADLK /* POSIX */
-#else
-# define ARGP_ERR_UNKNOWN EDEADLOCK /* *GNU/kFreebsd does not define this) */
-#endif
-#define ARGP_KEY_ARG 0
-#define ARGP_KEY_ARGS 0x1000006
-#define ARGP_KEY_END 0x1000001
-#define ARGP_KEY_NO_ARGS 0x1000002
-#define ARGP_KEY_INIT 0x1000003
-#define ARGP_KEY_FINI 0x1000007
-#define ARGP_KEY_SUCCESS 0x1000004
-#define ARGP_KEY_ERROR 0x1000005
-typedef error_t (*argp_parser_t) (int key, char *arg, struct argp_state *state);
-
-struct argp
-{
- const struct argp_option *options;
- argp_parser_t parser;
- const char *args_doc;
- const char *doc;
-
- const struct argp_child *children;
- char *(*help_filter) (int key, const char *text, void *input);
- const char *argp_domain;
-};
-
-#define ARGP_HELP_USAGE ARGP_HELP_SHORT_USAGE
-#define ARGP_HELP_SHORT_USAGE 0x02
-#define ARGP_HELP_SEE 0x04
-#define ARGP_HELP_LONG 0x08
-#define ARGP_HELP_PRE_DOC 0x10
-#define ARGP_HELP_POST_DOC 0x20
-#define ARGP_HELP_DOC (ARGP_HELP_PRE_DOC | ARGP_HELP_POST_DOC)
-#define ARGP_HELP_BUG_ADDR 0x40
-#define ARGP_HELP_EXIT_ERR 0x100
-#define ARGP_HELP_EXIT_OK 0x200
-#define ARGP_HELP_STD_ERR (ARGP_HELP_SEE | ARGP_HELP_EXIT_ERR)
-#define ARGP_HELP_STD_USAGE \
- (ARGP_HELP_SHORT_USAGE | ARGP_HELP_SEE | ARGP_HELP_EXIT_ERR)
-#define ARGP_HELP_STD_HELP \
- (ARGP_HELP_SHORT_USAGE | ARGP_HELP_LONG | ARGP_HELP_EXIT_OK \
- | ARGP_HELP_DOC | ARGP_HELP_BUG_ADDR)
-
-
-void argp_error (const struct argp_state *state,
- const char *fmt, ...) GT_GCC_A_PRINTF(2, 3);
-
-
-
-char *
-_argp_pname (char *name)
-{
- char *pname = name;
- char *bname = strrchr (pname, '/');
- if (! bname)
- bname = strrchr (pname, '\\');
- if (bname)
- pname = bname + 1;
- return pname;
-}
-
-
-void
-_argp_state_help (const struct argp *argp, const struct argp_state *state,
- FILE *stream, unsigned flags, char *name)
-{
- if (state)
- name = state->name;
-
- if (flags & ARGP_HELP_SHORT_USAGE)
- fprintf (stream, "Usage: %s [OPTIONS...] %s\n", name, argp->args_doc);
- if (flags & ARGP_HELP_SEE)
- fprintf (stream, "Try `%s --help' or `%s --usage' for more information.\n",
- name, name);
- if (flags & ARGP_HELP_PRE_DOC)
- {
- char buf[1024];
- char *end;
- strncpy (buf, argp->doc, sizeof (buf));
- buf[sizeof (buf) - 1] = '\0';
- end = strchr (buf, '\v');
- if (end)
- *end = '\0';
- fprintf (stream, "%s\n%s", buf, buf[0] ? "\n" : "");
- }
- if (flags & ARGP_HELP_LONG)
- {
- const struct argp_option *opt = argp->options;
- while (opt->key)
- {
- #define NSPACES 29
- char spaces[NSPACES + 1] = " ";
- int len = 0;
- fprintf (stream, " ");
- len += 2;
- if (isascii (opt->key))
- {
- fprintf (stream, "-%c", opt->key);
- len += 2;
- if (opt->name)
- {
- fprintf (stream, ", ");
- len += 2;
- }
- }
- if (opt->name)
- {
- fprintf (stream, "--%s", opt->name);
- len += 2 + strlen (opt->name);
- }
- if (opt->arg && (opt->flags & OPTION_ARG_OPTIONAL))
- {
- fprintf (stream, "[=%s]", opt->arg);
- len += 3 + strlen (opt->arg);
- }
- else if (opt->arg)
- {
- fprintf (stream, "=%s", opt->arg);
- len += 1 + strlen (opt->arg);
- }
- if (len >= NSPACES)
- len = NSPACES - 1;
- spaces[NSPACES - len] = '\0';
- fprintf (stream, "%s%s\n", spaces, opt->doc);
- opt++;
- }
- fprintf (stream, " -?, --help Give this help list\n");
- fprintf (stream, " --usage Give a short usage "
- "message\n");
- }
- if (flags & ARGP_HELP_POST_DOC)
- {
- char buf[1024];
- char *end;
- strncpy (buf, argp->doc, sizeof (buf));
- buf[sizeof (buf) - 1] = '\0';
- end = strchr (buf, '\v');
- if (end)
- {
- end++;
- if (*end)
- fprintf (stream, "\n%s\n", end);
- }
- fprintf (stream, "\nMandatory or optional arguments to long options are also mandatory or optional\n");
- fprintf (stream, "for any corresponding short options.\n");
- }
- if (flags & ARGP_HELP_BUG_ADDR)
- fprintf (stream, "\nReport bugs to %s.\n", argp_program_bug_address);
-
- if (flags & ARGP_HELP_EXIT_ERR)
- exit (argp_err_exit_status);
- if (flags & ARGP_HELP_EXIT_OK)
- exit (0);
-}
-
-
-void
-argp_usage (const struct argp_state *state)
-{
- _argp_state_help (state->root_argp, state, state->err_stream,
- ARGP_HELP_STD_USAGE, state->name);
-}
-
-
-void
-argp_state_help (const struct argp_state *state, FILE *stream, unsigned flags)
-{
- _argp_state_help (state->root_argp, state, stream, flags, state->name);
-}
-
-
-void
-argp_error (const struct argp_state *state, const char *fmt, ...)
-{
- va_list ap;
-
- fprintf (state->err_stream, "%s: ", state->name);
- va_start (ap, fmt);
- vfprintf (state->err_stream, fmt, ap);
- va_end (ap);
- fprintf (state->err_stream, "\n");
- argp_state_help (state, state->err_stream, ARGP_HELP_STD_ERR);
- exit (argp_err_exit_status);
-}
-
-
-void
-argp_help (const struct argp *argp, FILE *stream, unsigned flags, char *name)
-{
- _argp_state_help (argp, NULL, stream, flags, name);
-}
-
-
-error_t
-argp_parse (const struct argp *argp, int argc,
- char **argv, unsigned flags, int *arg_index, void *input)
-{
- int rc = 0;
- struct argp_state state = { argp, argc, argv, 1, flags, 0, 0, input,
- NULL, NULL, _argp_pname (argv[0]),
- stderr, stdout, NULL };
- /* All non-option arguments are collected at the beginning of
- &argv[1] during processing. This is a counter for their number. */
- int non_opt_args = 0;
-
- rc = argp->parser (ARGP_KEY_INIT, NULL, &state);
- if (rc && rc != ARGP_ERR_UNKNOWN)
- goto argperror;
-
- while (state.next < state.argc - non_opt_args)
- {
- int idx = state.next;
- state.next++;
-
- if (! strcasecmp (state.argv[idx], "--"))
- {
- state.quoted = idx;
- continue;
- }
-
- if (state.quoted || state.argv[idx][0] != '-')
- {
- char *arg_saved = state.argv[idx];
- non_opt_args++;
- memmove (&state.argv[idx], &state.argv[idx + 1],
- (state.argc - 1 - idx) * sizeof (char *));
- state.argv[argc - 1] = arg_saved;
- state.next--;
- }
- else if (! strcasecmp (state.argv[idx], "--help")
- || !strcmp (state.argv[idx], "-?"))
- {
- argp_state_help (&state, state.out_stream, ARGP_HELP_STD_HELP);
- }
- else if (! strcasecmp (state.argv[idx], "--usage"))
- {
- argp_state_help (&state, state.out_stream,
- ARGP_HELP_USAGE | ARGP_HELP_EXIT_OK);
- }
- else if (! strcasecmp (state.argv[idx], "--version")
- || !strcmp (state.argv[idx], "-V"))
- {
- fprintf (state.out_stream, "%s\n", argp_program_version);
- exit (0);
- }
- else
- {
- /* Search for option and call parser with its KEY. */
- int key = ARGP_KEY_ARG; /* Just some dummy value. */
- const struct argp_option *opt = argp->options;
- char *arg = NULL;
- int found = 0;
-
- /* Check for --opt=value syntax. */
- arg = strchr (state.argv[idx], '=');
- if (arg)
- {
- *arg = '\0';
- arg++;
- }
-
- if (state.argv[idx][1] != '-')
- key = state.argv[idx][1];
-
- while (! found && opt->key)
- {
- if (key == opt->key
- || (key == ARGP_KEY_ARG
- && ! strcasecmp (&state.argv[idx][2], opt->name)))
- {
- if (arg && !opt->arg)
- argp_error (&state, "Option %s does not take an argument",
- state.argv[idx]);
- if (opt->arg && state.next < state.argc
- && state.argv[idx + 1][0] != '-')
- {
- arg = state.argv[idx + 1];
- state.next++;
- }
- if (opt->arg && !(opt->flags & OPTION_ARG_OPTIONAL))
- argp_error (&state, "Option %s requires an argument",
- state.argv[idx]);
-
- rc = argp->parser (opt->key, arg, &state);
- if (rc == ARGP_ERR_UNKNOWN)
- break;
- else if (rc)
- goto argperror;
- found = 1;
- }
- opt++;
- }
- if (! found)
- argp_error (&state, "Unknown option %s", state.argv[idx]);
- }
- }
-
- while (state.next < state.argc)
- {
- /* Call parser for all non-option args. */
- int idx = state.next;
- state.next++;
- rc = argp->parser (ARGP_KEY_ARG, state.argv[idx], &state);
- if (rc && rc != ARGP_ERR_UNKNOWN)
- goto argperror;
- if (rc == ARGP_ERR_UNKNOWN)
- {
- int old_next = state.next;
- rc = argp->parser (ARGP_KEY_ARGS, NULL, &state);
- if (rc == ARGP_ERR_UNKNOWN)
- {
- argp_error (&state, "Too many arguments");
- goto argperror;
- }
- if (! rc && state.next == old_next)
- {
- state.arg_num += state.argc - state.next;
- state.next = state.argc;
- }
- }
- else
- state.arg_num++;
- }
-
- if (state.arg_num == 0)
- {
- rc = argp->parser (ARGP_KEY_NO_ARGS, NULL, &state);
- if (rc && rc != ARGP_ERR_UNKNOWN)
- goto argperror;
- }
- if (state.next == state.argc)
- {
- rc = argp->parser (ARGP_KEY_END, NULL, &state);
- if (rc && rc != ARGP_ERR_UNKNOWN)
- goto argperror;
- }
- rc = argp->parser (ARGP_KEY_FINI, NULL, &state);
- if (rc && rc != ARGP_ERR_UNKNOWN)
- goto argperror;
-
- rc = 0;
- argp->parser (ARGP_KEY_SUCCESS, NULL, &state);
-
- argperror:
- if (rc)
- {
- argp_error (&state, "unexpected error: %s", strerror (rc));
- argp->parser (ARGP_KEY_ERROR, NULL, &state);
- }
-
- argp->parser (ARGP_KEY_FINI, NULL, &state);
-
- if (arg_index)
- *arg_index = state.next - 1;
-
- return 0;
-}
-#endif
-
-
/* MEMBUF */
/* A simple implementation of a dynamic buffer. Use init_membuf() to
@@ -619,7 +202,7 @@ peek_membuf (membuf_t *mb, size_t *len)
/* SUPPORT. */
FILE *log_stream;
-char *program_name = "gpgme-tool";
+char program_name[] = "gpgme-tool";
#define spacep(p) (*(p) == ' ' || *(p) == '\t')
@@ -725,7 +308,7 @@ struct result_xml_state
#define MAX_TAGS 20
int next_tag;
- char *tag[MAX_TAGS];
+ const char *tag[MAX_TAGS];
int had_data[MAX_TAGS];
};
@@ -754,13 +337,14 @@ result_xml_indent (struct result_xml_state *state)
gpg_error_t
-result_xml_tag_start (struct result_xml_state *state, char *name, ...)
+result_xml_tag_start (struct result_xml_state *state, const char *name, ...)
{
result_xml_write_cb_t cb = state->cb;
void *hook = state->hook;
va_list ap;
char *attr;
char *attr_val;
+ char string_null[] = "(null)";
va_start (ap, name);
@@ -791,7 +375,7 @@ result_xml_tag_start (struct result_xml_state *state, char *name, ...)
attr_val = va_arg (ap, char *);
if (attr_val == NULL)
- attr_val = "(null)";
+ attr_val = string_null;
(*cb) (hook, " ", 1);
(*cb) (hook, attr, strlen (attr));
@@ -908,7 +492,8 @@ result_xml_tag_end (struct result_xml_state *state)
gpg_error_t
-result_add_error (struct result_xml_state *state, char *name, gpg_error_t err)
+result_add_error (struct result_xml_state *state,
+ const char *name, gpg_error_t err)
{
char code[20];
char msg[1024];
@@ -924,7 +509,7 @@ result_add_error (struct result_xml_state *state, char *name, gpg_error_t err)
gpg_error_t
result_add_pubkey_algo (struct result_xml_state *state,
- char *name, gpgme_pubkey_algo_t algo)
+ const char *name, gpgme_pubkey_algo_t algo)
{
char code[20];
char msg[80];
@@ -940,10 +525,11 @@ result_add_pubkey_algo (struct result_xml_state *state,
gpg_error_t
result_add_hash_algo (struct result_xml_state *state,
- char *name, gpgme_hash_algo_t algo)
+ const char *name, gpgme_hash_algo_t algo)
{
char code[20];
char msg[80];
+
snprintf (code, sizeof (code) - 1, "0x%x", algo);
snprintf (msg, sizeof (msg) - 1, "%s",
gpgme_hash_algo_name (algo));
@@ -955,7 +541,8 @@ result_add_hash_algo (struct result_xml_state *state,
gpg_error_t
-result_add_keyid (struct result_xml_state *state, char *name, char *keyid)
+result_add_keyid (struct result_xml_state *state,
+ const char *name, const char *keyid)
{
result_xml_tag_start (state, name, NULL);
result_xml_tag_data (state, keyid);
@@ -965,7 +552,8 @@ result_add_keyid (struct result_xml_state *state, char *name, char *keyid)
gpg_error_t
-result_add_fpr (struct result_xml_state *state, char *name, char *fpr)
+result_add_fpr (struct result_xml_state *state,
+ const char *name, const char *fpr)
{
result_xml_tag_start (state, name, NULL);
result_xml_tag_data (state, fpr);
@@ -975,7 +563,7 @@ result_add_fpr (struct result_xml_state *state, char *name, char *fpr)
gpg_error_t
-result_add_timestamp (struct result_xml_state *state, char *name,
+result_add_timestamp (struct result_xml_state *state, const char *name,
unsigned int timestamp)
{
char code[20];
@@ -988,10 +576,10 @@ result_add_timestamp (struct result_xml_state *state, char *name,
gpg_error_t
-result_add_sig_mode (struct result_xml_state *state, char *name,
+result_add_sig_mode (struct result_xml_state *state, const char *name,
gpgme_sig_mode_t sig_mode)
{
- char *mode;
+ const char *mode;
char code[20];
snprintf (code, sizeof (code) - 1, "%i", sig_mode);
@@ -1018,7 +606,7 @@ result_add_sig_mode (struct result_xml_state *state, char *name,
gpg_error_t
-result_add_protocol (struct result_xml_state *state, char *name,
+result_add_protocol (struct result_xml_state *state, const char *name,
gpgme_protocol_t protocol)
{
const char *str;
@@ -1036,7 +624,7 @@ result_add_protocol (struct result_xml_state *state, char *name,
gpg_error_t
-result_add_validity (struct result_xml_state *state, char *name,
+result_add_validity (struct result_xml_state *state, const char *name,
gpgme_validity_t validity)
{
const char *str;
@@ -1073,7 +661,7 @@ result_add_validity (struct result_xml_state *state, char *name,
gpg_error_t
result_add_value (struct result_xml_state *state,
- char *name, unsigned int val)
+ const char *name, unsigned int val)
{
char code[20];
@@ -1086,7 +674,7 @@ result_add_value (struct result_xml_state *state,
gpg_error_t
result_add_string (struct result_xml_state *state,
- char *name, char *str)
+ const char *name, const char *str)
{
if (!str)
str = "";
@@ -2100,6 +1688,8 @@ gt_identify (gpgme_tool_t gt, gpgme_data_t data)
case GPGME_DATA_TYPE_INVALID: return gpg_error (GPG_ERR_GENERAL);
case GPGME_DATA_TYPE_UNKNOWN : s = "unknown"; break;
case GPGME_DATA_TYPE_PGP_SIGNED : s = "PGP-signed"; break;
+ case GPGME_DATA_TYPE_PGP_SIGNATURE: s = "PGP-signature"; break;
+ case GPGME_DATA_TYPE_PGP_ENCRYPTED: s = "PGP-encrypted"; break;
case GPGME_DATA_TYPE_PGP_OTHER : s = "PGP"; break;
case GPGME_DATA_TYPE_PGP_KEY : s = "PGP-key"; break;
case GPGME_DATA_TYPE_CMS_SIGNED : s = "CMS-signed"; break;
@@ -2140,9 +1730,9 @@ gt_result (gpgme_tool_t gt, unsigned int flags)
{
int indent = 2;
- gt_write_data (gt, xml_preamble1, sizeof (xml_preamble1));
+ gt_write_data (gt, xml_preamble1, strlen (xml_preamble1));
gt_write_data (gt, NULL, 0);
- gt_write_data (gt, xml_preamble2, sizeof (xml_preamble2));
+ gt_write_data (gt, xml_preamble2, strlen (xml_preamble2));
gt_write_data (gt, NULL, 0);
if (flags & GT_RESULT_ENCRYPT)
result_encrypt_to_xml (gt->ctx, indent,
@@ -2168,7 +1758,7 @@ gt_result (gpgme_tool_t gt, unsigned int flags)
if (flags & GT_RESULT_VFS_MOUNT)
result_vfs_mount_to_xml (gt->ctx, indent,
(result_xml_write_cb_t) gt_write_data, gt);
- gt_write_data (gt, xml_end, sizeof (xml_end));
+ gt_write_data (gt, xml_end, strlen (xml_end));
return 0;
}
@@ -2223,6 +1813,8 @@ server_passphrase_cb (void *opaque, const char *uid_hint, const char *info,
unsigned char *buf = NULL;
size_t buflen = 0;
+ (void)was_bad;
+
if (server && server->assuan_ctx)
{
if (uid_hint)
@@ -2291,6 +1883,8 @@ server_data_encoding (const char *line)
return GPGME_DATA_ENCODING_URLESC;
if (strstr (line, "--url0"))
return GPGME_DATA_ENCODING_URL0;
+ if (strstr (line, "--mime"))
+ return GPGME_DATA_ENCODING_MIME;
return GPGME_DATA_ENCODING_NONE;
}
@@ -2395,6 +1989,9 @@ static gpg_error_t
reset_notify (assuan_context_t ctx, char *line)
{
struct server *server = assuan_get_pointer (ctx);
+
+ (void)line;
+
server_reset_fds (server);
gt_reset (server->gt);
return 0;
@@ -2718,6 +2315,8 @@ cmd_signers_clear (assuan_context_t ctx, char *line)
{
struct server *server = assuan_get_pointer (ctx);
+ (void)line;
+
return gt_signers_clear (server->gt);
}
@@ -2734,6 +2333,8 @@ _cmd_decrypt_verify (assuan_context_t ctx, char *line, int verify)
gpgme_data_t inp_data;
gpgme_data_t out_data;
+ (void)line;
+
inp_fd = server->input_fd;
inp_fn = server->input_filename;
if (inp_fd == ASSUAN_INVALID_FD && !inp_fn)
@@ -2960,6 +2561,8 @@ cmd_verify (assuan_context_t ctx, char *line)
gpgme_data_t msg_data = NULL;
gpgme_data_t out_data = NULL;
+ (void)line;
+
inp_fd = server->input_fd;
inp_fn = server->input_filename;
if (inp_fd == ASSUAN_INVALID_FD && !inp_fn)
@@ -3135,6 +2738,8 @@ cmd_genkey (assuan_context_t ctx, char *line)
gpgme_data_t parms_data = NULL;
const char *parms;
+ (void)line;
+
inp_fd = server->input_fd;
inp_fn = server->input_filename;
if (inp_fd == ASSUAN_INVALID_FD && !inp_fn)
@@ -3266,9 +2871,9 @@ cmd_keylist (assuan_context_t ctx, char *line)
}
pattern[idx] = NULL;
- gt_write_data (gt, xml_preamble1, sizeof (xml_preamble1));
+ gt_write_data (gt, xml_preamble1, strlen (xml_preamble1));
gt_write_data (gt, NULL, 0);
- gt_write_data (gt, xml_preamble2, sizeof (xml_preamble2));
+ gt_write_data (gt, xml_preamble2, strlen (xml_preamble2));
gt_write_data (gt, NULL, 0);
result_init (&state, indent, (result_xml_write_cb_t) gt_write_data, gt);
result_xml_tag_start (&state, "keylist", NULL);
@@ -3343,7 +2948,7 @@ cmd_keylist (assuan_context_t ctx, char *line)
}
result_xml_tag_end (&state); /* keylist */
- gt_write_data (gt, xml_end, sizeof (xml_end));
+ gt_write_data (gt, xml_end, strlen (xml_end));
server_reset_fds (server);
@@ -3450,6 +3055,9 @@ static gpg_error_t
cmd_result (assuan_context_t ctx, char *line)
{
struct server *server = assuan_get_pointer (ctx);
+
+ (void)line;
+
return gt_result (server->gt, GT_RESULT_ALL);
}
@@ -3505,6 +3113,8 @@ cmd_identify (assuan_context_t ctx, char *line)
char *inp_fn;
gpgme_data_t inp_data;
+ (void)line;
+
inp_fd = server->input_fd;
inp_fn = server->input_filename;
if (inp_fd == ASSUAN_INVALID_FD && !inp_fn)
@@ -3722,85 +3332,51 @@ gpgme_server (gpgme_tool_t gt)
-/* MAIN PROGRAM STARTS HERE. */
-
-const char *argp_program_version = VERSION;
-const char *argp_program_bug_address = "bug-gpgme@gnupg.org";
-error_t argp_err_exit_status = 1;
-
-static char doc[] = "GPGME Tool -- Assuan server exposing GPGME operations";
-static char args_doc[] = "COMMAND [OPTIONS...]";
-
-static struct argp_option options[] = {
- { "server", 's', 0, 0, "Server mode" },
- { "gpg-binary", 501, "FILE", 0, "Use FILE for the GPG backend" },
- { "lib-version", 502, 0, 0, "Show library version" },
- { 0 }
-};
-
-static error_t parse_options (int key, char *arg, struct argp_state *state);
-static struct argp argp = { options, parse_options, args_doc, doc };
-
-struct args
-{
- enum { CMD_DEFAULT, CMD_SERVER, CMD_LIBVERSION } cmd;
- const char *gpg_binary;
-};
-
-void
-args_init (struct args *args)
-{
- memset (args, '\0', sizeof (*args));
- args->cmd = CMD_DEFAULT;
-}
-
-
-static error_t
-parse_options (int key, char *arg, struct argp_state *state)
+static const char *
+my_strusage( int level )
{
- struct args *args = state->input;
+ const char *p;
- switch (key)
+ switch (level)
{
- case 's':
- args->cmd = CMD_SERVER;
- break;
-
- case 501:
- args->gpg_binary = arg;
+ case 11: p = "gpgme-tool"; break;
+ case 13: p = PACKAGE_VERSION; break;
+ case 14: p = "Copyright (C) 2015 g10 Code GmbH"; break;
+ case 19: p = "Please report bugs to <" PACKAGE_BUGREPORT ">.\n"; break;
+ case 1:
+ case 40:
+ p = "Usage: gpgme-tool [OPTIONS] [COMMANDS]";
break;
-
- case 502:
- args->cmd = CMD_LIBVERSION;
- break;
-
-#if 0
- case ARGP_KEY_ARG:
- if (state->arg_num >= 2)
- argp_usage (state);
- printf ("Arg[%i] = %s\n", state->arg_num, arg);
+ case 41:
+ p = "GPGME Tool -- Assuan server exposing GPGME operations\n";
break;
- case ARGP_KEY_END:
- if (state->arg_num < 2)
- argp_usage (state);
+ case 42:
+ p = "1"; /* Flag print 40 as part of 41. */
break;
-#endif
-
- default:
- return ARGP_ERR_UNKNOWN;
+ default: p = NULL; break;
}
- return 0;
+ return p;
}
-
+
int
main (int argc, char *argv[])
{
- struct args args;
+ static ARGPARSE_OPTS opts[] = {
+ ARGPARSE_c ('s', "server", "Server mode"),
+ ARGPARSE_s_s(501, "gpg-binary", "|FILE|Use FILE for the GPG backend"),
+ ARGPARSE_c (502, "lib-version", "Show library version"),
+ ARGPARSE_end()
+ };
+ ARGPARSE_ARGS pargs = { &argc, &argv, 0 };
+ enum { CMD_DEFAULT, CMD_SERVER, CMD_LIBVERSION } cmd = CMD_DEFAULT;
+ const char *gpg_binary = NULL;
struct gpgme_tool gt;
gpg_error_t err;
int needgt = 1;
+ set_strusage (my_strusage);
+
#ifdef HAVE_SETLOCALE
setlocale (LC_ALL, "");
#endif
@@ -3812,30 +3388,40 @@ main (int argc, char *argv[])
gpgme_set_locale (NULL, LC_MESSAGES, setlocale (LC_MESSAGES, NULL));
#endif
- args_init (&args);
-
- argp_parse (&argp, argc, argv, 0, 0, &args);
log_init ();
- if (args.cmd == CMD_LIBVERSION)
+ while (arg_parse (&pargs, opts))
+ {
+ switch (pargs.r_opt)
+ {
+ case 's': cmd = CMD_SERVER; break;
+ case 501: gpg_binary = pargs.r.ret_str; break;
+ case 502: cmd = CMD_LIBVERSION; break;
+ default:
+ pargs.err = ARGPARSE_PRINT_WARNING;
+ break;
+ }
+ }
+
+ if (cmd == CMD_LIBVERSION)
needgt = 0;
- if (needgt && args.gpg_binary)
+ if (needgt && gpg_binary)
{
- if (access (args.gpg_binary, X_OK))
+ if (access (gpg_binary, X_OK))
err = gpg_error_from_syserror ();
else
err = gpgme_set_engine_info (GPGME_PROTOCOL_OpenPGP,
- args.gpg_binary, NULL);
+ gpg_binary, NULL);
if (err)
log_error (1, err, "error witching OpenPGP engine to '%s'",
- args.gpg_binary);
+ gpg_binary);
}
if (needgt)
gt_init (&gt);
- switch (args.cmd)
+ switch (cmd)
{
case CMD_DEFAULT:
case CMD_SERVER:
@@ -3860,4 +3446,3 @@ main (int argc, char *argv[])
return 0;
}
-
diff --git a/src/gpgme.c b/src/gpgme.c
index 0cf999a..d59f808 100644
--- a/src/gpgme.c
+++ b/src/gpgme.c
@@ -1,7 +1,7 @@
/* gpgme.c - GnuPG Made Easy.
Copyright (C) 2000 Werner Koch (dd9jn)
Copyright (C) 2001, 2002, 2003, 2004, 2005, 2007, 2012,
- 2014 g10 Code GmbH
+ 2014, 2015 g10 Code GmbH
This file is part of GPGME.
@@ -71,15 +71,52 @@ gpgme_set_global_flag (const char *name, const char *value)
_gpgme_dirinfo_disable_gpgconf ();
return 0;
}
+ else if (!strcmp (name, "require-gnupg"))
+ return _gpgme_set_engine_minimal_version (value);
else if (!strcmp (name, "gpgconf-name"))
return _gpgme_set_default_gpgconf_name (value);
else if (!strcmp (name, "gpg-name"))
return _gpgme_set_default_gpg_name (value);
+ else if (!strcmp (name, "w32-inst-dir"))
+ return _gpgme_set_override_inst_dir (value);
else
return -1;
}
+/* Set the flag NAME for CTX to VALUE. The supported flags are:
+ *
+ * - full-status :: With a value of "1" the status callback set by
+ * gpgme_set_status_cb returns all status lines
+ * except for PROGRESS lines. With the default of
+ * "0" the status callback is only called in certain
+ * situations.
+ */
+gpgme_error_t
+gpgme_set_ctx_flag (gpgme_ctx_t ctx, const char *name, const char *value)
+{
+ int abool;
+
+ if (!ctx || !name || !value)
+ return gpg_error (GPG_ERR_INV_VALUE);
+
+ abool = *value? !!atoi (value) : 0;
+
+ if (!strcmp (name, "full-status"))
+ {
+ ctx->full_status = abool;
+ }
+ else if (!strcmp (name, "raw-description"))
+ {
+ ctx->raw_description = abool;
+ }
+ else
+ return gpg_error (GPG_ERR_UNKNOWN_NAME);
+
+ return 0;
+}
+
+
/* Create a new context as an environment for GPGME crypto
operations. */
@@ -91,7 +128,7 @@ gpgme_new (gpgme_ctx_t *r_ctx)
TRACE_BEG (DEBUG_CTX, "gpgme_new", r_ctx);
if (_gpgme_selftest)
- return TRACE_ERR (gpgme_error (_gpgme_selftest));
+ return TRACE_ERR (_gpgme_selftest);
if (!r_ctx)
return TRACE_ERR (gpg_error (GPG_ERR_INV_VALUE));
@@ -994,41 +1031,70 @@ gpgme_sig_notation_get (gpgme_ctx_t ctx)
return ctx->sig_notations;
}
+
-const char *
-gpgme_pubkey_algo_name (gpgme_pubkey_algo_t algo)
+/* Return a public key algorithm string made of the algorithm and size
+ or the curve name. May return NULL on error. Caller must free the
+ result using gpgme_free. */
+char *
+gpgme_pubkey_algo_string (gpgme_subkey_t subkey)
{
- switch (algo)
+ const char *prefix = NULL;
+ char *result;
+
+ if (!subkey)
{
- case GPGME_PK_RSA:
- return "RSA";
+ gpg_err_set_errno (EINVAL);
+ return NULL;
+ }
+ switch (subkey->pubkey_algo)
+ {
+ case GPGME_PK_RSA:
case GPGME_PK_RSA_E:
- return "RSA-E";
-
- case GPGME_PK_RSA_S:
- return "RSA-S";
-
- case GPGME_PK_ELG_E:
- return "ELG-E";
-
- case GPGME_PK_DSA:
- return "DSA";
-
+ case GPGME_PK_RSA_S: prefix = "rsa"; break;
+ case GPGME_PK_ELG_E: prefix = "elg"; break;
+ case GPGME_PK_DSA: prefix = "dsa"; break;
+ case GPGME_PK_ELG: prefix = "xxx"; break;
case GPGME_PK_ECC:
- return "ECC";
+ case GPGME_PK_ECDH:
+ case GPGME_PK_ECDSA:
+ case GPGME_PK_EDDSA: prefix = ""; break;
+ }
- case GPGME_PK_ELG:
- return "ELG";
+ if (prefix && *prefix)
+ {
+ char buffer[40];
+ snprintf (buffer, sizeof buffer, "%s%u", prefix, subkey->length);
+ result = strdup (buffer);
+ }
+ else if (prefix && subkey->curve && *subkey->curve)
+ result = strdup (subkey->curve);
+ else if (prefix)
+ result = strdup ("E_error");
+ else
+ result = strdup ("unknown");
- case GPGME_PK_ECDSA:
- return "ECDSA";
+ return result;
+}
- case GPGME_PK_ECDH:
- return "ECDH";
- default:
- return NULL;
+const char *
+gpgme_pubkey_algo_name (gpgme_pubkey_algo_t algo)
+{
+ switch (algo)
+ {
+ case GPGME_PK_RSA: return "RSA";
+ case GPGME_PK_RSA_E: return "RSA-E";
+ case GPGME_PK_RSA_S: return "RSA-S";
+ case GPGME_PK_ELG_E: return "ELG-E";
+ case GPGME_PK_DSA: return "DSA";
+ case GPGME_PK_ECC: return "ECC";
+ case GPGME_PK_ELG: return "ELG";
+ case GPGME_PK_ECDSA: return "ECDSA";
+ case GPGME_PK_ECDH: return "ECDH";
+ case GPGME_PK_EDDSA: return "EdDSA";
+ default: return NULL;
}
}
diff --git a/src/gpgme.def b/src/gpgme.def
index a3f5fb4..9815a83 100644
--- a/src/gpgme.def
+++ b/src/gpgme.def
@@ -223,5 +223,26 @@ EXPORTS
gpgme_set_status_cb @167
gpgme_get_status_cb @168
+
+ gpgme_pubkey_algo_string @169
+ gpgme_set_ctx_flag @170
+
+ gpgme_data_set_flag @171
+
+ gpgme_op_createkey_start @172
+ gpgme_op_createkey @173
+ gpgme_op_createsubkey_start @174
+ gpgme_op_createsubkey @175
+ gpgme_op_adduid_start @176
+ gpgme_op_adduid @177
+ gpgme_op_revuid_start @178
+ gpgme_op_revuid @179
+ gpgme_op_keysign_start @180
+ gpgme_op_keysign @181
+ gpgme_op_tofu_policy_start @182
+ gpgme_op_tofu_policy @183
+ gpgme_op_interact_start @184
+ gpgme_op_interact @185
+
; END
diff --git a/src/gpgme.h.in b/src/gpgme.h.in
index 6cea2c7..20654db 100644
--- a/src/gpgme.h.in
+++ b/src/gpgme.h.in
@@ -1,6 +1,6 @@
/* gpgme.h - Public interface to GnuPG Made Easy. -*- c -*-
* Copyright (C) 2000 Werner Koch (dd9jn)
- * Copyright (C) 2001-2015 g10 Code GmbH
+ * Copyright (C) 2001-2016 g10 Code GmbH
*
* This file is part of GPGME.
*
@@ -67,29 +67,31 @@ extern "C" {
#endif
+/* The deprecated macro takes the version number of GPGME which
+ * introduced the deprecation as parameter for documentation. */
#ifdef GPGRT_ATTR_DEPRECATED
-# define _GPGME_DEPRECATED GPGRT_ATTR_DEPRECATED
+# define _GPGME_DEPRECATED(a,b) GPGRT_ATTR_DEPRECATED
#elif defined(__GNUC__)
# define _GPGME_GCC_VERSION (__GNUC__ * 10000 \
+ __GNUC_MINOR__ * 100 \
+ __GNUC_PATCHLEVEL__)
# if _GPGME_GCC_VERSION > 30100
-# define _GPGME_DEPRECATED __attribute__ ((__deprecated__))
+# define _GPGME_DEPRECATED(a,b) __attribute__ ((__deprecated__))
# else
-# define _GPGME_DEPRECATED
+# define _GPGME_DEPRECATED(a,b)
# endif
#else
-# define _GPGME_DEPRECATED
+# define _GPGME_DEPRECATED(a,b)
#endif
/* The macro _GPGME_DEPRECATED_OUTSIDE_GPGME suppresses warnings for
fields we must access in GPGME for ABI compatibility. */
#ifdef _GPGME_IN_GPGME
-#define _GPGME_DEPRECATED_OUTSIDE_GPGME
+#define _GPGME_DEPRECATED_OUTSIDE_GPGME(a,b)
#else
-#define _GPGME_DEPRECATED_OUTSIDE_GPGME _GPGME_DEPRECATED
+#define _GPGME_DEPRECATED_OUTSIDE_GPGME(a,b) _GPGME_DEPRECATED(a,b)
#endif
@@ -228,7 +230,8 @@ typedef enum
GPGME_DATA_ENCODING_ARMOR = 3, /* Either PEM or OpenPGP Armor. */
GPGME_DATA_ENCODING_URL = 4, /* LF delimited URL list. */
GPGME_DATA_ENCODING_URLESC = 5, /* Ditto, but percent escaped. */
- GPGME_DATA_ENCODING_URL0 = 6 /* Nul delimited URL list. */
+ GPGME_DATA_ENCODING_URL0 = 6, /* Nul delimited URL list. */
+ GPGME_DATA_ENCODING_MIME = 7 /* Data is a MIME part. */
}
gpgme_data_encoding_t;
@@ -239,8 +242,10 @@ typedef enum
GPGME_DATA_TYPE_INVALID = 0, /* Not detected. */
GPGME_DATA_TYPE_UNKNOWN = 1,
GPGME_DATA_TYPE_PGP_SIGNED = 0x10,
+ GPGME_DATA_TYPE_PGP_ENCRYPTED= 0x11,
GPGME_DATA_TYPE_PGP_OTHER = 0x12,
GPGME_DATA_TYPE_PGP_KEY = 0x13,
+ GPGME_DATA_TYPE_PGP_SIGNATURE= 0x18, /* Detached signature */
GPGME_DATA_TYPE_CMS_SIGNED = 0x20,
GPGME_DATA_TYPE_CMS_ENCRYPTED= 0x21,
GPGME_DATA_TYPE_CMS_OTHER = 0x22,
@@ -261,7 +266,8 @@ typedef enum
GPGME_PK_ECC = 18,
GPGME_PK_ELG = 20,
GPGME_PK_ECDSA = 301,
- GPGME_PK_ECDH = 302
+ GPGME_PK_ECDH = 302,
+ GPGME_PK_EDDSA = 303
}
gpgme_pubkey_algo_t;
@@ -303,7 +309,7 @@ typedef enum
GPGME_SIG_STAT_GOOD_EXPKEY = 8
}
_gpgme_sig_stat_t;
-typedef _gpgme_sig_stat_t gpgme_sig_stat_t _GPGME_DEPRECATED;
+typedef _gpgme_sig_stat_t gpgme_sig_stat_t _GPGME_DEPRECATED(0,4);
/* The available signature modes. */
@@ -354,7 +360,7 @@ typedef enum
GPGME_ATTR_SIG_CLASS = 32
}
_gpgme_attr_t;
-typedef _gpgme_attr_t gpgme_attr_t _GPGME_DEPRECATED;
+typedef _gpgme_attr_t gpgme_attr_t _GPGME_DEPRECATED(0,4);
/* The available validities for a trust item or key. */
@@ -370,6 +376,19 @@ typedef enum
gpgme_validity_t;
+/* The TOFU policies. */
+typedef enum
+ {
+ GPGME_TOFU_POLICY_NONE = 0,
+ GPGME_TOFU_POLICY_AUTO = 1,
+ GPGME_TOFU_POLICY_GOOD = 2,
+ GPGME_TOFU_POLICY_UNKNOWN = 3,
+ GPGME_TOFU_POLICY_BAD = 4,
+ GPGME_TOFU_POLICY_ASK = 5
+ }
+gpgme_tofu_policy_t;
+
+
/* The available protocols. */
typedef enum
{
@@ -394,6 +413,7 @@ gpgme_protocol_t;
#define GPGME_KEYLIST_MODE_SIGS 4
#define GPGME_KEYLIST_MODE_SIG_NOTATIONS 8
#define GPGME_KEYLIST_MODE_WITH_SECRET 16
+#define GPGME_KEYLIST_MODE_WITH_TOFU 32
#define GPGME_KEYLIST_MODE_EPHEMERAL 128
#define GPGME_KEYLIST_MODE_VALIDATE 256
@@ -426,7 +446,9 @@ typedef unsigned int gpgme_export_mode_t;
#define GPGME_AUDITLOG_HTML 1
#define GPGME_AUDITLOG_WITH_HELP 128
-/* The possible stati for the edit operation. */
+
+/* The possible stati for gpgme_op_edit. The use of that function and
+ * these status codes are deprecated in favor of gpgme_op_interact. */
typedef enum
{
GPGME_STATUS_EOF = 0,
@@ -531,7 +553,12 @@ typedef enum
GPGME_STATUS_BEGIN_SIGNING = 90,
GPGME_STATUS_KEY_NOT_CREATED = 91,
GPGME_STATUS_INQUIRE_MAXLEN = 92,
- GPGME_STATUS_FAILURE = 93
+ GPGME_STATUS_FAILURE = 93,
+ GPGME_STATUS_KEY_CONSIDERED = 94,
+ GPGME_STATUS_TOFU_USER = 95,
+ GPGME_STATUS_TOFU_STATS = 96,
+ GPGME_STATUS_TOFU_STATS_LONG = 97,
+ GPGME_STATUS_NOTATION_FLAGS = 98
}
gpgme_status_code_t;
@@ -602,6 +629,43 @@ struct _gpgme_engine_info
typedef struct _gpgme_engine_info *gpgme_engine_info_t;
+/* An object with TOFU information. */
+struct _gpgme_tofu_info
+{
+ struct _gpgme_tofu_info *next;
+
+ /* The TOFU validity:
+ * 0 := conflict
+ * 1 := key without history
+ * 2 := key with too little history
+ * 3 := key with enough history for basic trust
+ * 4 := key with a lot of history
+ */
+ unsigned int validity : 3;
+
+ /* The TOFU policy (gpgme_tofu_policy_t). */
+ unsigned int policy : 4;
+
+ unsigned int _rfu : 25;
+
+ /* Number of signatures seen for this binding. Capped at USHRT_MAX. */
+ unsigned short signcount;
+ /* Number of encryptions done with this binding. Capped at USHRT_MAX. */
+ unsigned short encrcount;
+
+ /* Number of seconds since Epoch when the first and the most
+ * recently seen message were verified/decrypted. 0 means unknown. */
+ unsigned long signfirst;
+ unsigned long signlast;
+ unsigned long encrfirst;
+ unsigned long encrlast;
+
+ /* If non-NULL a human readable string summarizing the TOFU data. */
+ char *description;
+};
+typedef struct _gpgme_tofu_info *gpgme_tofu_info_t;
+
+
/* A subkey from a key. */
struct _gpgme_subkey
{
@@ -669,6 +733,9 @@ struct _gpgme_subkey
/* The name of the curve for ECC algorithms or NULL. */
char *curve;
+
+ /* The keygrip of the subkey in hex digit form or NULL if not availabale. */
+ char *keygrip;
};
typedef struct _gpgme_subkey *gpgme_subkey_t;
@@ -712,10 +779,10 @@ struct _gpgme_key_sig
gpgme_error_t status;
#ifdef __cplusplus
- unsigned int _obsolete_class _GPGME_DEPRECATED;
+ unsigned int _obsolete_class _GPGME_DEPRECATED(0,4);
#else
/* Must be set to SIG_CLASS below. */
- unsigned int class _GPGME_DEPRECATED_OUTSIDE_GPGME;
+ unsigned int class _GPGME_DEPRECATED_OUTSIDE_GPGME(0,4);
#endif
/* The user ID string. */
@@ -776,6 +843,15 @@ struct _gpgme_user_id
/* Internal to GPGME, do not use. */
gpgme_key_sig_t _last_keysig;
+
+ /* The mail address (addr-spec from RFC5322) of the UID string.
+ * This is general the same as the EMAIL part of this struct but
+ * might be slightly different. IF no mail address is available
+ * NULL is stored. */
+ char *address;
+
+ /* The malloced TOFU information or NULL. */
+ gpgme_tofu_info_t tofu;
};
typedef struct _gpgme_user_id *gpgme_user_id_t;
@@ -852,6 +928,11 @@ struct _gpgme_key
/* The keylist mode that was active when listing the key. */
gpgme_keylist_mode_t keylist_mode;
+
+ /* This field gives the fingerprint of the primary key. Note that
+ * this is a copy of the FPR of the first subkey. We need it here
+ * to allow for an incomplete key object. */
+ char *fpr;
};
typedef struct _gpgme_key *gpgme_key_t;
@@ -860,7 +941,12 @@ typedef struct _gpgme_key *gpgme_key_t;
struct _gpgme_invalid_key
{
struct _gpgme_invalid_key *next;
+
+ /* The string used to request the key. Despite the name this may
+ * not be a fingerprint. */
char *fpr;
+
+ /* The error code. */
gpgme_error_t reason;
};
typedef struct _gpgme_invalid_key *gpgme_invalid_key_t;
@@ -885,8 +971,13 @@ typedef void (*gpgme_progress_cb_t) (void *opaque, const char *what,
typedef gpgme_error_t (*gpgme_status_cb_t) (void *opaque, const char *keyword,
const char *args);
-
/* Interact with the user about an edit operation. */
+typedef gpgme_error_t (*gpgme_interact_cb_t) (void *opaque,
+ const char *keyword,
+ const char *args, int fd);
+
+/* The callback type used by the deprecated functions gpgme_op_edit
+ * and gpgme_op_card_edit. */
typedef gpgme_error_t (*gpgme_edit_cb_t) (void *opaque,
gpgme_status_code_t status,
const char *args, int fd);
@@ -904,6 +995,10 @@ gpgme_error_t gpgme_new (gpgme_ctx_t *ctx);
/* Release the context CTX. */
void gpgme_release (gpgme_ctx_t ctx);
+/* Set the flag NAME for CTX to VALUE. */
+gpgme_error_t gpgme_set_ctx_flag (gpgme_ctx_t ctx,
+ const char *name, const char *value);
+
/* Set the protocol to be used by CTX to PROTO. */
gpgme_error_t gpgme_set_protocol (gpgme_ctx_t ctx, gpgme_protocol_t proto);
@@ -986,7 +1081,7 @@ void gpgme_get_progress_cb (gpgme_ctx_t ctx, gpgme_progress_cb_t *cb,
void **hook_value);
/* Set the status callback function in CTX to CB. HOOK_VALUE is
- passed as first argument to thes status callback function. */
+ passed as first argument to the status callback function. */
void gpgme_set_status_cb (gpgme_ctx_t c, gpgme_status_cb_t cb,
void *hook_value);
@@ -1031,7 +1126,7 @@ gpgme_key_t gpgme_signers_enum (const gpgme_ctx_t ctx, int seq);
Deprecated, use verify result directly. */
const char *gpgme_get_sig_status (gpgme_ctx_t ctx, int idx,
_gpgme_sig_stat_t *r_stat,
- time_t *r_created) _GPGME_DEPRECATED;
+ time_t *r_created) _GPGME_DEPRECATED(0,4);
/* Retrieve certain attributes of a signature. IDX is the index
number of the signature after a successful verify operation. WHAT
@@ -1039,16 +1134,16 @@ const char *gpgme_get_sig_status (gpgme_ctx_t ctx, int idx,
one. WHATIDX is to be passed as 0 for most attributes . */
unsigned long gpgme_get_sig_ulong_attr (gpgme_ctx_t c, int idx,
_gpgme_attr_t what, int whatidx)
- _GPGME_DEPRECATED;
+ _GPGME_DEPRECATED(0,4);
const char *gpgme_get_sig_string_attr (gpgme_ctx_t c, int idx,
_gpgme_attr_t what, int whatidx)
- _GPGME_DEPRECATED;
+ _GPGME_DEPRECATED(0,4);
/* Get the key used to create signature IDX in CTX and return it in
R_KEY. */
gpgme_error_t gpgme_get_sig_key (gpgme_ctx_t ctx, int idx, gpgme_key_t *r_key)
- _GPGME_DEPRECATED;
+ _GPGME_DEPRECATED(0,4);
/* Clear all notation data from the context. */
@@ -1131,7 +1226,7 @@ void gpgme_set_io_cbs (gpgme_ctx_t ctx, gpgme_io_cbs_t io_cbs);
void gpgme_get_io_cbs (gpgme_ctx_t ctx, gpgme_io_cbs_t io_cbs);
/* Wrappers around the internal I/O functions for use with
- gpgme_passphrase_cb_t and gpgme_edit_cb_t. */
+ gpgme_passphrase_cb_t and gpgme_interact_cb_t. */
@API__SSIZE_T@ gpgme_io_read (int fd, void *buffer, size_t count);
@API__SSIZE_T@ gpgme_io_write (int fd, const void *buffer, size_t count);
int gpgme_io_writen (int fd, const void *buffer, size_t count);
@@ -1169,11 +1264,12 @@ typedef @API__SSIZE_T@ (*gpgme_data_write_cb_t) (void *handle, const void *buffe
/* Set the current position from where the next read or write starts
in the data object with the handle HANDLE to OFFSET, relativ to
- WHENCE. */
+ WHENCE. Returns the new offset in bytes from the beginning of the
+ data object. */
typedef @API__OFF_T@ (*gpgme_data_seek_cb_t) (void *handle,
@API__OFF_T@ offset, int whence);
-/* Close the data object with the handle DL. */
+/* Close the data object with the handle HANDLE. */
typedef void (*gpgme_data_release_cb_t) (void *handle);
struct gpgme_data_cbs
@@ -1196,8 +1292,9 @@ typedef struct gpgme_data_cbs *gpgme_data_cbs_t;
@API__SSIZE_T@ gpgme_data_write (gpgme_data_t dh, const void *buffer, size_t size);
/* Set the current position from where the next read or write starts
- in the data object with the handle DH to OFFSET, relativ to
- WHENCE. */
+ in the data object with the handle DH to OFFSET, relativ to WHENCE.
+ Returns the new offset in bytes from the beginning of the data
+ object. */
@API__OFF_T@ gpgme_data_seek (gpgme_data_t dh, @API__OFF_T@ offset, int whence);
/* Create a new data buffer and return it in R_DH. */
@@ -1218,7 +1315,8 @@ gpgme_error_t gpgme_data_new_from_mem (gpgme_data_t *r_dh,
size is returned in R_LEN. */
char *gpgme_data_release_and_get_mem (gpgme_data_t dh, size_t *r_len);
-/* Release the memory returned by gpgme_data_release_and_get_mem(). */
+/* Release the memory returned by gpgme_data_release_and_get_mem() and
+ some other functions. */
void gpgme_free (void *buffer);
gpgme_error_t gpgme_data_new_from_cbs (gpgme_data_t *dh,
@@ -1245,6 +1343,10 @@ char *gpgme_data_get_file_name (gpgme_data_t dh);
gpgme_error_t gpgme_data_set_file_name (gpgme_data_t dh,
const char *file_name);
+/* Set a flag for the data object DH. See the manual for details. */
+gpg_error_t gpgme_data_set_flag (gpgme_data_t dh,
+ const char *name, const char *value);
+
/* Try to identify the type of the data in DH. */
gpgme_data_type_t gpgme_data_identify (gpgme_data_t dh, int reserved);
@@ -1256,11 +1358,11 @@ gpgme_error_t gpgme_data_new_with_read_cb (gpgme_data_t *r_dh,
int (*read_cb) (void*,char *,
size_t,size_t*),
void *read_cb_value)
- _GPGME_DEPRECATED;
+ _GPGME_DEPRECATED(0,4);
/* Create a new data buffer filled with the content of file FNAME.
COPY must be non-zero. For delayed read, please use
- gpgme_data_new_from_fd or gpgme_data_new_from stream instead. */
+ gpgme_data_new_from_fd or gpgme_data_new_from_stream instead. */
gpgme_error_t gpgme_data_new_from_file (gpgme_data_t *r_dh,
const char *fname,
int copy);
@@ -1274,7 +1376,7 @@ gpgme_error_t gpgme_data_new_from_filepart (gpgme_data_t *r_dh,
/* Reset the read pointer in DH. Deprecated, please use
gpgme_data_seek instead. */
-gpgme_error_t gpgme_data_rewind (gpgme_data_t dh) _GPGME_DEPRECATED;
+gpgme_error_t gpgme_data_rewind (gpgme_data_t dh) _GPGME_DEPRECATED(0,4);
@@ -1304,7 +1406,7 @@ void gpgme_key_release (gpgme_key_t key);
key structure directly instead. */
const char *gpgme_key_get_string_attr (gpgme_key_t key, _gpgme_attr_t what,
const void *reserved, int idx)
- _GPGME_DEPRECATED;
+ _GPGME_DEPRECATED(0,4);
/* Return the value of the attribute WHAT of KEY, which has to be
representable by an unsigned integer. IDX specifies the sub key or
@@ -1312,7 +1414,7 @@ const char *gpgme_key_get_string_attr (gpgme_key_t key, _gpgme_attr_t what,
Deprecated, use key structure directly instead. */
unsigned long gpgme_key_get_ulong_attr (gpgme_key_t key, _gpgme_attr_t what,
const void *reserved, int idx)
- _GPGME_DEPRECATED;
+ _GPGME_DEPRECATED(0,4);
/* Return the value of the attribute WHAT of a signature on user ID
UID_IDX in KEY, which has to be representable by a string. IDX
@@ -1321,7 +1423,7 @@ unsigned long gpgme_key_get_ulong_attr (gpgme_key_t key, _gpgme_attr_t what,
const char *gpgme_key_sig_get_string_attr (gpgme_key_t key, int uid_idx,
_gpgme_attr_t what,
const void *reserved, int idx)
- _GPGME_DEPRECATED;
+ _GPGME_DEPRECATED(0,4);
/* Return the value of the attribute WHAT of a signature on user ID
UID_IDX in KEY, which has to be representable by an unsigned
@@ -1330,7 +1432,7 @@ const char *gpgme_key_sig_get_string_attr (gpgme_key_t key, int uid_idx,
unsigned long gpgme_key_sig_get_ulong_attr (gpgme_key_t key, int uid_idx,
_gpgme_attr_t what,
const void *reserved, int idx)
- _GPGME_DEPRECATED;
+ _GPGME_DEPRECATED(0,4);
@@ -1355,7 +1457,8 @@ typedef enum
GPGME_ENCRYPT_NO_ENCRYPT_TO = 2,
GPGME_ENCRYPT_PREPARE = 4,
GPGME_ENCRYPT_EXPECT_SIGN = 8,
- GPGME_ENCRYPT_NO_COMPRESS = 16
+ GPGME_ENCRYPT_NO_COMPRESS = 16,
+ GPGME_ENCRYPT_SYMMETRIC = 32
}
gpgme_encrypt_flags_t;
@@ -1471,7 +1574,7 @@ struct _gpgme_new_signature
unsigned int _obsolete_class_2;
#else
/* Must be set to SIG_CLASS below. */
- unsigned int class _GPGME_DEPRECATED_OUTSIDE_GPGME;
+ unsigned int class _GPGME_DEPRECATED_OUTSIDE_GPGME(0,4);
#endif
/* Crypto backend specific signature class. */
@@ -1516,10 +1619,12 @@ typedef enum
GPGME_SIGSUM_CRL_MISSING = 0x0100, /* CRL not available. */
GPGME_SIGSUM_CRL_TOO_OLD = 0x0200, /* Available CRL is too old. */
GPGME_SIGSUM_BAD_POLICY = 0x0400, /* A policy was not met. */
- GPGME_SIGSUM_SYS_ERROR = 0x0800 /* A system error occured. */
+ GPGME_SIGSUM_SYS_ERROR = 0x0800, /* A system error occurred. */
+ GPGME_SIGSUM_TOFU_CONFLICT=0x1000 /* Tofu conflict detected. */
}
gpgme_sigsum_t;
+
struct _gpgme_signature
{
struct _gpgme_signature *next;
@@ -1527,7 +1632,7 @@ struct _gpgme_signature
/* A summary of the signature status. */
gpgme_sigsum_t summary;
- /* The fingerprint or key ID of the signature. */
+ /* The fingerprint of the signature. This can be a subkey. */
char *fpr;
/* The status of the signature. */
@@ -1539,7 +1644,7 @@ struct _gpgme_signature
/* Signature creation time. */
unsigned long timestamp;
- /* Signature exipration time or 0. */
+ /* Signature expiration time or 0. */
unsigned long exp_timestamp;
/* Key should not have been used for signing. */
@@ -1565,6 +1670,10 @@ struct _gpgme_signature
/* The mailbox from the PKA information or NULL. */
char *pka_address;
+
+ /* If non-NULL, a possible incomplete key object with the data
+ * available for the signature. */
+ gpgme_key_t key;
};
typedef struct _gpgme_signature *gpgme_signature_t;
@@ -1608,7 +1717,7 @@ struct _gpgme_import_status
/* Fingerprint. */
char *fpr;
- /* If a problem occured, the reason why the key could not be
+ /* If a problem occurred, the reason why the key could not be
imported. Otherwise GPGME_No_Error. */
gpgme_error_t result;
@@ -1676,7 +1785,7 @@ gpgme_import_result_t gpgme_op_import_result (gpgme_ctx_t ctx);
gpgme_error_t gpgme_op_import_start (gpgme_ctx_t ctx, gpgme_data_t keydata);
gpgme_error_t gpgme_op_import (gpgme_ctx_t ctx, gpgme_data_t keydata);
gpgme_error_t gpgme_op_import_ext (gpgme_ctx_t ctx, gpgme_data_t keydata,
- int *nr) _GPGME_DEPRECATED;
+ int *nr) _GPGME_DEPRECATED(0,4);
/* Import the keys from the array KEYS into the keyring. */
gpgme_error_t gpgme_op_import_keys_start (gpgme_ctx_t ctx, gpgme_key_t keys[]);
@@ -1715,6 +1824,18 @@ gpgme_error_t gpgme_op_export_keys (gpgme_ctx_t ctx,
* Key generation.
*/
+/* Flags for the key creation functions. */
+#define GPGME_CREATE_SIGN (1 << 0) /* Allow usage: signing. */
+#define GPGME_CREATE_ENCR (1 << 1) /* Allow usage: encryption. */
+#define GPGME_CREATE_CERT (1 << 2) /* Allow usage: certification. */
+#define GPGME_CREATE_AUTH (1 << 3) /* Allow usage: authentication. */
+#define GPGME_CREATE_NOPASSWD (1 << 7) /* Create w/o passphrase. */
+#define GPGME_CREATE_SELFSIGNED (1 << 8) /* Create self-signed cert. */
+#define GPGME_CREATE_NOSTORE (1 << 9) /* Do not store the key. */
+#define GPGME_CREATE_WANTPUB (1 << 10) /* Return the public key. */
+#define GPGME_CREATE_WANTSEC (1 << 11) /* Return the secret key. */
+#define GPGME_CREATE_FORCE (1 << 12) /* Force creation. */
+
struct _gpgme_op_genkey_result
{
/* A primary key was generated. */
@@ -1723,11 +1844,22 @@ struct _gpgme_op_genkey_result
/* A sub key was generated. */
unsigned int sub : 1;
+ /* A user id was generated. */
+ unsigned int uid : 1;
+
/* Internal to GPGME, do not use. */
- unsigned int _unused : 30;
+ unsigned int _unused : 29;
/* The fingerprint of the generated key. */
char *fpr;
+
+ /* A memory data object with the created public key. Only set when
+ * GPGME_CREATE_WANTPUB has been used. */
+ gpgme_data_t pubkey;
+
+ /* A memory data object with the created secret key. Only set when
+ * GPGME_CREATE_WANTSEC has been used. */
+ gpgme_data_t seckey;
};
typedef struct _gpgme_op_genkey_result *gpgme_genkey_result_t;
@@ -1739,7 +1871,55 @@ gpgme_error_t gpgme_op_genkey_start (gpgme_ctx_t ctx, const char *parms,
gpgme_error_t gpgme_op_genkey (gpgme_ctx_t ctx, const char *parms,
gpgme_data_t pubkey, gpgme_data_t seckey);
-/* Retrieve a pointer to the result of the genkey operation. */
+/* Generate a key pair using the modern interface. */
+gpgme_error_t gpgme_op_createkey_start (gpgme_ctx_t ctx,
+ const char *userid,
+ const char *algo,
+ unsigned long reserved,
+ unsigned long expires,
+ gpgme_key_t certkey,
+ unsigned int flags);
+gpgme_error_t gpgme_op_createkey (gpgme_ctx_t ctx,
+ const char *userid,
+ const char *algo,
+ unsigned long reserved,
+ unsigned long expires,
+ gpgme_key_t certkey,
+ unsigned int flags);
+/* Add a new subkey to KEY. */
+gpgme_error_t gpgme_op_createsubkey_start (gpgme_ctx_t ctx,
+ gpgme_key_t key,
+ const char *algo,
+ unsigned long reserved,
+ unsigned long expires,
+ unsigned int flags);
+gpgme_error_t gpgme_op_createsubkey (gpgme_ctx_t ctx,
+ gpgme_key_t key,
+ const char *algo,
+ unsigned long reserved,
+ unsigned long expires,
+ unsigned int flags);
+
+/* Add USERID to an existing KEY. */
+gpgme_error_t gpgme_op_adduid_start (gpgme_ctx_t ctx,
+ gpgme_key_t key, const char *userid,
+ unsigned int reserved);
+gpgme_error_t gpgme_op_adduid (gpgme_ctx_t ctx,
+ gpgme_key_t key, const char *userid,
+ unsigned int reserved);
+
+/* Revoke a USERID from a KEY. */
+gpgme_error_t gpgme_op_revuid_start (gpgme_ctx_t ctx,
+ gpgme_key_t key, const char *userid,
+ unsigned int reserved);
+gpgme_error_t gpgme_op_revuid (gpgme_ctx_t ctx,
+ gpgme_key_t key, const char *userid,
+ unsigned int reserved);
+
+
+
+/* Retrieve a pointer to the result of a genkey, createkey, or
+ * createsubkey operation. */
gpgme_genkey_result_t gpgme_op_genkey_result (gpgme_ctx_t ctx);
@@ -1750,29 +1930,76 @@ gpgme_error_t gpgme_op_delete_start (gpgme_ctx_t ctx, const gpgme_key_t key,
gpgme_error_t gpgme_op_delete (gpgme_ctx_t ctx, const gpgme_key_t key,
int allow_secret);
+
+/*
+ * Key signing interface
+ */
+
+/* Flags for the key signing functions. */
+#define GPGME_KEYSIGN_LOCAL (1 << 7) /* Create a local signature. */
+#define GPGME_KEYSIGN_LFSEP (1 << 8) /* Indicate LF separated user ids. */
+#define GPGME_KEYSIGN_NOEXPIRE (1 << 9) /* Force no expiration. */
+
+
+/* Sign the USERID of KEY using the current set of signers. */
+gpgme_error_t gpgme_op_keysign_start (gpgme_ctx_t ctx,
+ gpgme_key_t key, const char *userid,
+ unsigned long expires,
+ unsigned int flags);
+gpgme_error_t gpgme_op_keysign (gpgme_ctx_t ctx,
+ gpgme_key_t key, const char *userid,
+ unsigned long expires,
+ unsigned int flags);
+
+
/*
- * Key Edit interface
+ * Key edit interface
*/
-/* Edit the key KEY. Send status and command requests to FNC and
+/* Flags to select the mode of the interact. */
+#define GPGME_INTERACT_CARD (1 << 0) /* Use --card-edit mode. */
+
+
+/* Edit the KEY. Send status and command requests to FNC and
output of edit commands to OUT. */
+gpgme_error_t gpgme_op_interact_start (gpgme_ctx_t ctx,
+ gpgme_key_t key,
+ unsigned int flags,
+ gpgme_interact_cb_t fnc,
+ void *fnc_value,
+ gpgme_data_t out);
+gpgme_error_t gpgme_op_interact (gpgme_ctx_t ctx, gpgme_key_t key,
+ unsigned int flags,
+ gpgme_interact_cb_t fnc,
+ void *fnc_value,
+ gpgme_data_t out);
+
gpgme_error_t gpgme_op_edit_start (gpgme_ctx_t ctx, gpgme_key_t key,
gpgme_edit_cb_t fnc, void *fnc_value,
- gpgme_data_t out);
-gpgme_error_t gpgme_op_edit (gpgme_ctx_t ctx, gpgme_key_t key,
- gpgme_edit_cb_t fnc, void *fnc_value,
- gpgme_data_t out);
-
-/* Edit the card for the key KEY. Send status and command requests to
- FNC and output of edit commands to OUT. */
+ gpgme_data_t out) _GPGME_DEPRECATED(1,7);
+gpgme_error_t gpgme_op_edit (gpgme_ctx_t ctx, gpgme_key_t key,
+ gpgme_edit_cb_t fnc, void *fnc_value,
+ gpgme_data_t out) _GPGME_DEPRECATED(1,7);
gpgme_error_t gpgme_op_card_edit_start (gpgme_ctx_t ctx, gpgme_key_t key,
gpgme_edit_cb_t fnc, void *fnc_value,
- gpgme_data_t out);
-gpgme_error_t gpgme_op_card_edit (gpgme_ctx_t ctx, gpgme_key_t key,
- gpgme_edit_cb_t fnc, void *fnc_value,
- gpgme_data_t out);
+ gpgme_data_t out)
+ _GPGME_DEPRECATED(1,7);
+gpgme_error_t gpgme_op_card_edit (gpgme_ctx_t ctx, gpgme_key_t key,
+ gpgme_edit_cb_t fnc, void *fnc_value,
+ gpgme_data_t out)
+ _GPGME_DEPRECATED(1,7);
+
+
+/* Set the Tofu policy of KEY to POLCIY. */
+gpgme_error_t gpgme_op_tofu_policy_start (gpgme_ctx_t ctx,
+ gpgme_key_t key,
+ gpgme_tofu_policy_t policy);
+gpgme_error_t gpgme_op_tofu_policy (gpgme_ctx_t ctx,
+ gpgme_key_t key,
+ gpgme_tofu_policy_t policy);
+
@@ -1875,7 +2102,7 @@ void gpgme_trust_item_unref (gpgme_trust_item_t item);
/* Release the trust item ITEM. Deprecated, use
gpgme_trust_item_unref. */
-void gpgme_trust_item_release (gpgme_trust_item_t item) _GPGME_DEPRECATED;
+void gpgme_trust_item_release (gpgme_trust_item_t item) _GPGME_DEPRECATED(0,4);
/* Return the value of the attribute WHAT of ITEM, which has to be
representable by a string. Deprecated, use trust item structure
@@ -1883,7 +2110,7 @@ void gpgme_trust_item_release (gpgme_trust_item_t item) _GPGME_DEPRECATED;
const char *gpgme_trust_item_get_string_attr (gpgme_trust_item_t item,
_gpgme_attr_t what,
const void *reserved, int idx)
- _GPGME_DEPRECATED;
+ _GPGME_DEPRECATED(0,4);
/* Return the value of the attribute WHAT of KEY, which has to be
representable by an integer. IDX specifies a running index if the
@@ -1891,7 +2118,7 @@ const char *gpgme_trust_item_get_string_attr (gpgme_trust_item_t item,
item structure directly. */
int gpgme_trust_item_get_int_attr (gpgme_trust_item_t item, _gpgme_attr_t what,
const void *reserved, int idx)
- _GPGME_DEPRECATED;
+ _GPGME_DEPRECATED(0,4);
@@ -1974,14 +2201,14 @@ struct _gpgme_op_assuan_result
{
/* Deprecated. Use the second value in a DONE event or the
synchronous variant gpgme_op_assuan_transact_ext. */
- gpgme_error_t err _GPGME_DEPRECATED_OUTSIDE_GPGME;
+ gpgme_error_t err _GPGME_DEPRECATED_OUTSIDE_GPGME(1,2);
};
typedef struct _gpgme_op_assuan_result *gpgme_assuan_result_t;
/* Return the result of the last Assuan command. */
gpgme_assuan_result_t gpgme_op_assuan_result (gpgme_ctx_t ctx)
- _GPGME_DEPRECATED;
+ _GPGME_DEPRECATED(1,2);
gpgme_error_t
gpgme_op_assuan_transact (gpgme_ctx_t ctx,
@@ -1991,7 +2218,7 @@ gpgme_op_assuan_transact (gpgme_ctx_t ctx,
gpgme_assuan_inquire_cb_t inq_cb,
void *inq_cb_value,
gpgme_assuan_status_cb_t status_cb,
- void *status_cb_value) _GPGME_DEPRECATED;
+ void *status_cb_value) _GPGME_DEPRECATED(1,2);
/*
@@ -2077,7 +2304,7 @@ typedef struct gpgme_conf_arg
} *gpgme_conf_arg_t;
-/* The flags of a configuration option. See the gpg-conf
+/* The flags of a configuration option. See the gpgconf
documentation for details. */
#define GPGME_CONF_GROUP (1 << 0)
#define GPGME_CONF_OPTIONAL (1 << 1)
@@ -2232,6 +2459,10 @@ gpgme_error_t gpgme_engine_check_version (gpgme_protocol_t proto);
void gpgme_result_ref (void *result);
void gpgme_result_unref (void *result);
+/* Return a public key algorithm string (e.g. "rsa2048"). Caller must
+ free using gpgme_free. */
+char *gpgme_pubkey_algo_string (gpgme_subkey_t subkey);
+
/* Return a statically allocated string with the name of the public
key algorithm ALGO, or NULL if that name is not known. */
const char *gpgme_pubkey_algo_name (gpgme_pubkey_algo_t algo);
@@ -2245,44 +2476,44 @@ const char *gpgme_hash_algo_name (gpgme_hash_algo_t algo);
/*
* Deprecated types.
*/
-typedef gpgme_ctx_t GpgmeCtx _GPGME_DEPRECATED;
-typedef gpgme_data_t GpgmeData _GPGME_DEPRECATED;
-typedef gpgme_error_t GpgmeError _GPGME_DEPRECATED;
-typedef gpgme_data_encoding_t GpgmeDataEncoding _GPGME_DEPRECATED;
-typedef gpgme_pubkey_algo_t GpgmePubKeyAlgo _GPGME_DEPRECATED;
-typedef gpgme_hash_algo_t GpgmeHashAlgo _GPGME_DEPRECATED;
-typedef gpgme_sig_stat_t GpgmeSigStat _GPGME_DEPRECATED;
-typedef gpgme_sig_mode_t GpgmeSigMode _GPGME_DEPRECATED;
-typedef gpgme_attr_t GpgmeAttr _GPGME_DEPRECATED;
-typedef gpgme_validity_t GpgmeValidity _GPGME_DEPRECATED;
-typedef gpgme_protocol_t GpgmeProtocol _GPGME_DEPRECATED;
-typedef gpgme_engine_info_t GpgmeEngineInfo _GPGME_DEPRECATED;
-typedef gpgme_subkey_t GpgmeSubkey _GPGME_DEPRECATED;
-typedef gpgme_key_sig_t GpgmeKeySig _GPGME_DEPRECATED;
-typedef gpgme_user_id_t GpgmeUserID _GPGME_DEPRECATED;
-typedef gpgme_key_t GpgmeKey _GPGME_DEPRECATED;
-typedef gpgme_passphrase_cb_t GpgmePassphraseCb _GPGME_DEPRECATED;
-typedef gpgme_progress_cb_t GpgmeProgressCb _GPGME_DEPRECATED;
-typedef gpgme_io_cb_t GpgmeIOCb _GPGME_DEPRECATED;
-typedef gpgme_register_io_cb_t GpgmeRegisterIOCb _GPGME_DEPRECATED;
-typedef gpgme_remove_io_cb_t GpgmeRemoveIOCb _GPGME_DEPRECATED;
-typedef gpgme_event_io_t GpgmeEventIO _GPGME_DEPRECATED;
-typedef gpgme_event_io_cb_t GpgmeEventIOCb _GPGME_DEPRECATED;
+typedef gpgme_ctx_t GpgmeCtx _GPGME_DEPRECATED(0,4);
+typedef gpgme_data_t GpgmeData _GPGME_DEPRECATED(0,4);
+typedef gpgme_error_t GpgmeError _GPGME_DEPRECATED(0,4);
+typedef gpgme_data_encoding_t GpgmeDataEncoding _GPGME_DEPRECATED(0,4);
+typedef gpgme_pubkey_algo_t GpgmePubKeyAlgo _GPGME_DEPRECATED(0,4);
+typedef gpgme_hash_algo_t GpgmeHashAlgo _GPGME_DEPRECATED(0,4);
+typedef gpgme_sig_stat_t GpgmeSigStat _GPGME_DEPRECATED(0,4);
+typedef gpgme_sig_mode_t GpgmeSigMode _GPGME_DEPRECATED(0,4);
+typedef gpgme_attr_t GpgmeAttr _GPGME_DEPRECATED(0,4);
+typedef gpgme_validity_t GpgmeValidity _GPGME_DEPRECATED(0,4);
+typedef gpgme_protocol_t GpgmeProtocol _GPGME_DEPRECATED(0,4);
+typedef gpgme_engine_info_t GpgmeEngineInfo _GPGME_DEPRECATED(0,4);
+typedef gpgme_subkey_t GpgmeSubkey _GPGME_DEPRECATED(0,4);
+typedef gpgme_key_sig_t GpgmeKeySig _GPGME_DEPRECATED(0,4);
+typedef gpgme_user_id_t GpgmeUserID _GPGME_DEPRECATED(0,4);
+typedef gpgme_key_t GpgmeKey _GPGME_DEPRECATED(0,4);
+typedef gpgme_passphrase_cb_t GpgmePassphraseCb _GPGME_DEPRECATED(0,4);
+typedef gpgme_progress_cb_t GpgmeProgressCb _GPGME_DEPRECATED(0,4);
+typedef gpgme_io_cb_t GpgmeIOCb _GPGME_DEPRECATED(0,4);
+typedef gpgme_register_io_cb_t GpgmeRegisterIOCb _GPGME_DEPRECATED(0,4);
+typedef gpgme_remove_io_cb_t GpgmeRemoveIOCb _GPGME_DEPRECATED(0,4);
+typedef gpgme_event_io_t GpgmeEventIO _GPGME_DEPRECATED(0,4);
+typedef gpgme_event_io_cb_t GpgmeEventIOCb _GPGME_DEPRECATED(0,4);
#define GpgmeIOCbs gpgme_io_cbs
-typedef gpgme_data_read_cb_t GpgmeDataReadCb _GPGME_DEPRECATED;
-typedef gpgme_data_write_cb_t GpgmeDataWriteCb _GPGME_DEPRECATED;
-typedef gpgme_data_seek_cb_t GpgmeDataSeekCb _GPGME_DEPRECATED;
-typedef gpgme_data_release_cb_t GpgmeDataReleaseCb _GPGME_DEPRECATED;
+typedef gpgme_data_read_cb_t GpgmeDataReadCb _GPGME_DEPRECATED(0,4);
+typedef gpgme_data_write_cb_t GpgmeDataWriteCb _GPGME_DEPRECATED(0,4);
+typedef gpgme_data_seek_cb_t GpgmeDataSeekCb _GPGME_DEPRECATED(0,4);
+typedef gpgme_data_release_cb_t GpgmeDataReleaseCb _GPGME_DEPRECATED(0,4);
#define GpgmeDataCbs gpgme_data_cbs
-typedef gpgme_encrypt_result_t GpgmeEncryptResult _GPGME_DEPRECATED;
-typedef gpgme_sig_notation_t GpgmeSigNotation _GPGME_DEPRECATED;
-typedef gpgme_signature_t GpgmeSignature _GPGME_DEPRECATED;
-typedef gpgme_verify_result_t GpgmeVerifyResult _GPGME_DEPRECATED;
-typedef gpgme_import_status_t GpgmeImportStatus _GPGME_DEPRECATED;
-typedef gpgme_import_result_t GpgmeImportResult _GPGME_DEPRECATED;
-typedef gpgme_genkey_result_t GpgmeGenKeyResult _GPGME_DEPRECATED;
-typedef gpgme_trust_item_t GpgmeTrustItem _GPGME_DEPRECATED;
-typedef gpgme_status_code_t GpgmeStatusCode _GPGME_DEPRECATED;
+typedef gpgme_encrypt_result_t GpgmeEncryptResult _GPGME_DEPRECATED(0,4);
+typedef gpgme_sig_notation_t GpgmeSigNotation _GPGME_DEPRECATED(0,4);
+typedef gpgme_signature_t GpgmeSignature _GPGME_DEPRECATED(0,4);
+typedef gpgme_verify_result_t GpgmeVerifyResult _GPGME_DEPRECATED(0,4);
+typedef gpgme_import_status_t GpgmeImportStatus _GPGME_DEPRECATED(0,4);
+typedef gpgme_import_result_t GpgmeImportResult _GPGME_DEPRECATED(0,4);
+typedef gpgme_genkey_result_t GpgmeGenKeyResult _GPGME_DEPRECATED(0,4);
+typedef gpgme_trust_item_t GpgmeTrustItem _GPGME_DEPRECATED(0,4);
+typedef gpgme_status_code_t GpgmeStatusCode _GPGME_DEPRECATED(0,4);
#ifdef __cplusplus
}
diff --git a/src/kdpipeiodevice.cpp b/src/kdpipeiodevice.cpp
deleted file mode 100644
index 5661790..0000000
--- a/src/kdpipeiodevice.cpp
+++ /dev/null
@@ -1,951 +0,0 @@
-/*
- Copyright (C) 2007 Klarälvdalens Datakonsult AB
-
- KDPipeIODevice is free software; you can redistribute it and/or
- modify it under the terms of the GNU Library General Public
- License as published by the Free Software Foundation; either
- version 2 of the License, or (at your option) any later version.
-
- KDPipeIODevice is distributed in the hope that it will be useful,
- but WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- GNU Library General Public License for more details.
-
- You should have received a copy of the GNU Library General Public License
- along with KDPipeIODevice; see the file COPYING.LIB. If not, write to the
- Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
- Boston, MA 02110-1301, USA.
-*/
-
-#include "kdpipeiodevice.h"
-
-#include <QtCore>
-
-#include <cassert>
-#include <memory>
-#include <algorithm>
-
-#ifdef Q_OS_WIN32
-# ifndef NOMINMAX
-# define NOMINMAX
-# endif
-# include <windows.h>
-# include <io.h>
-#else
-# include <unistd.h>
-# include <errno.h>
-#endif
-
-using namespace _gpgme_;
-
-#ifndef KDAB_CHECK_THIS
-# define KDAB_CHECK_CTOR (void)1
-# define KDAB_CHECK_DTOR KDAB_CHECK_CTOR
-# define KDAB_CHECK_THIS KDAB_CHECK_CTOR
-#endif
-
-#define LOCKED( d ) const QMutexLocker locker( &d->mutex )
-#define synchronized( d ) if ( int i = 0 ) {} else for ( const QMutexLocker locker( &d->mutex ) ; !i ; ++i )
-
-const unsigned int BUFFER_SIZE = 4096;
-const bool ALLOW_QIODEVICE_BUFFERING = true;
-
-// comment to get trace output:
-//#define qDebug if(1){}else qDebug
-
-namespace {
-class Reader : public QThread {
- Q_OBJECT
-public:
- Reader( int fd, Qt::HANDLE handle );
- ~Reader();
-
- qint64 readData( char * data, qint64 maxSize );
-
- unsigned int bytesInBuffer() const {
- return ( wptr + sizeof buffer - rptr ) % sizeof buffer ;
- }
-
- bool bufferFull() const {
- return bytesInBuffer() == sizeof buffer - 1;
- }
-
- bool bufferEmpty() const {
- return bytesInBuffer() == 0;
- }
-
- bool bufferContains( char ch ) {
- const unsigned int bib = bytesInBuffer();
- for ( unsigned int i = rptr ; i < rptr + bib ; ++i )
- if ( buffer[i%sizeof buffer] == ch )
- return true;
- return false;
- }
-
- void notifyReadyRead();
-
-Q_SIGNALS:
- void readyRead();
-
-protected:
- /* reimp */ void run();
-
-private:
- int fd;
- Qt::HANDLE handle;
-public:
- QMutex mutex;
- QWaitCondition waitForCancelCondition;
- QWaitCondition bufferNotFullCondition;
- QWaitCondition bufferNotEmptyCondition;
- QWaitCondition hasStarted;
- QWaitCondition readyReadSentCondition;
- QWaitCondition blockedConsumerIsDoneCondition;
- bool cancel;
- bool eof;
- bool error;
- bool eofShortCut;
- int errorCode;
- bool isReading;
- bool consumerBlocksOnUs;
-
-private:
- unsigned int rptr, wptr;
- char buffer[BUFFER_SIZE+1]; // need to keep one byte free to detect empty state
-};
-
-
-Reader::Reader( int fd_, Qt::HANDLE handle_ )
- : QThread(),
- fd( fd_ ),
- handle( handle_ ),
- mutex(),
- bufferNotFullCondition(),
- bufferNotEmptyCondition(),
- hasStarted(),
- cancel( false ),
- eof( false ),
- error( false ),
- eofShortCut( false ),
- errorCode( 0 ),
- isReading( false ),
- consumerBlocksOnUs( false ),
- rptr( 0 ), wptr( 0 )
-{
-
-}
-
-Reader::~Reader() {}
-
-
-class Writer : public QThread {
- Q_OBJECT
-public:
- Writer( int fd, Qt::HANDLE handle );
- ~Writer();
-
- qint64 writeData( const char * data, qint64 size );
-
- unsigned int bytesInBuffer() const { return numBytesInBuffer; }
-
- bool bufferFull() const {
- return numBytesInBuffer == sizeof buffer;
- }
-
- bool bufferEmpty() const {
- return numBytesInBuffer == 0;
- }
-
-Q_SIGNALS:
- void bytesWritten( qint64 );
-
-protected:
- /* reimp */ void run();
-
-private:
- int fd;
- Qt::HANDLE handle;
-public:
- QMutex mutex;
- QWaitCondition bufferEmptyCondition;
- QWaitCondition bufferNotEmptyCondition;
- QWaitCondition hasStarted;
- bool cancel;
- bool error;
- int errorCode;
-private:
- unsigned int numBytesInBuffer;
- char buffer[BUFFER_SIZE];
-};
-}
-
-Writer::Writer( int fd_, Qt::HANDLE handle_ )
- : QThread(),
- fd( fd_ ),
- handle( handle_ ),
- mutex(),
- bufferEmptyCondition(),
- bufferNotEmptyCondition(),
- hasStarted(),
- cancel( false ),
- error( false ),
- errorCode( 0 ),
- numBytesInBuffer( 0 )
-{
-
-}
-
-Writer::~Writer() {}
-
-
-class KDPipeIODevice::Private : public QObject {
-Q_OBJECT
- friend class ::KDPipeIODevice;
- KDPipeIODevice * const q;
-public:
- explicit Private( KDPipeIODevice * qq );
- ~Private();
-
- bool doOpen( int, Qt::HANDLE, OpenMode );
- bool startReaderThread();
- bool startWriterThread();
- void stopThreads();
-
-public Q_SLOTS:
- void emitReadyRead();
-
-private:
- int fd;
- Qt::HANDLE handle;
- Reader * reader;
- Writer * writer;
- bool triedToStartReader;
- bool triedToStartWriter;
-};
-
-KDPipeIODevice::Private::Private( KDPipeIODevice * qq )
- : QObject( qq ), q( qq ),
- fd( -1 ),
- handle( 0 ),
- reader( 0 ),
- writer( 0 ),
- triedToStartReader( false ), triedToStartWriter( false )
-{
-
-}
-
-KDPipeIODevice::Private::~Private() {
- qDebug( "KDPipeIODevice::~Private(): Destroying %p", q );
-}
-
-KDPipeIODevice::KDPipeIODevice( QObject * p )
- : QIODevice( p ), d( new Private( this ) )
-{
- KDAB_CHECK_CTOR;
-}
-
-KDPipeIODevice::KDPipeIODevice( int fd, OpenMode mode, QObject * p )
- : QIODevice( p ), d( new Private( this ) )
-{
- KDAB_CHECK_CTOR;
- open( fd, mode );
-}
-
-KDPipeIODevice::KDPipeIODevice( Qt::HANDLE handle, OpenMode mode, QObject * p )
- : QIODevice( p ), d( new Private( this ) )
-{
- KDAB_CHECK_CTOR;
- open( handle, mode );
-}
-
-KDPipeIODevice::~KDPipeIODevice() { KDAB_CHECK_DTOR;
- if ( isOpen() )
- close();
- delete d; d = 0;
-}
-
-
-bool KDPipeIODevice::open( int fd, OpenMode mode ) { KDAB_CHECK_THIS;
-
-#ifdef Q_OS_WIN32
- return d->doOpen( fd, (HANDLE)_get_osfhandle( fd ), mode );
-#else
- return d->doOpen( fd, 0, mode );
-#endif
-
-}
-
-bool KDPipeIODevice::open( Qt::HANDLE h, OpenMode mode ) { KDAB_CHECK_THIS;
-
-#ifdef Q_OS_WIN32
- return d->doOpen( -1, h, mode );
-#else
- Q_UNUSED( h );
- Q_UNUSED( mode );
- assert( !"KDPipeIODevice::open( Qt::HANDLE, OpenMode ) should never be called except on Windows." );
-#endif
-
-}
-
-bool KDPipeIODevice::Private::startReaderThread()
-{
- if ( triedToStartReader )
- return true;
- triedToStartReader = true;
- if ( reader && !reader->isRunning() && !reader->isFinished() ) {
- qDebug("KDPipeIODevice::Private::startReaderThread(): locking reader (CONSUMER THREAD)" );
- LOCKED( reader );
- qDebug("KDPipeIODevice::Private::startReaderThread(): locked reader (CONSUMER THREAD)" );
- reader->start( QThread::HighestPriority );
- qDebug("KDPipeIODevice::Private::startReaderThread(): waiting for hasStarted (CONSUMER THREAD)" );
- const bool hasStarted = reader->hasStarted.wait( &reader->mutex, 1000 );
- qDebug("KDPipeIODevice::Private::startReaderThread(): returned from hasStarted (CONSUMER THREAD)" );
-
- return hasStarted;
- }
- return true;
-}
-
-bool KDPipeIODevice::Private::startWriterThread()
-{
- if ( triedToStartWriter )
- return true;
- triedToStartWriter = true;
- if ( writer && !writer->isRunning() && !writer->isFinished() ) {
- LOCKED( writer );
-
- writer->start( QThread::HighestPriority );
- if ( !writer->hasStarted.wait( &writer->mutex, 1000 ) )
- return false;
- }
- return true;
-}
-
-void KDPipeIODevice::Private::emitReadyRead()
-{
- QPointer<Private> thisPointer( this );
- qDebug( "KDPipeIODevice::Private::emitReadyRead %p", this );
-
- emit q->readyRead();
-
- if ( !thisPointer )
- return;
-
- bool mustNotify = false;
-
- if ( reader ) {
- qDebug( "KDPipeIODevice::Private::emitReadyRead %p: locking reader (CONSUMER THREAD)", this );
- synchronized( reader ) {
- qDebug( "KDPipeIODevice::Private::emitReadyRead %p: locked reader (CONSUMER THREAD)", this );
- reader->readyReadSentCondition.wakeAll();
- mustNotify = !reader->bufferEmpty() && reader->isReading;
- qDebug( "KDPipeIODevice::emitReadyRead %p: bufferEmpty: %d reader in ReadFile: %d", this, reader->bufferEmpty(), reader->isReading );
- }
- }
- if ( mustNotify )
- QTimer::singleShot( 100, this, SLOT( emitReadyRead() ) );
- qDebug( "KDPipeIODevice::Private::emitReadyRead %p leaving", this );
-
-}
-
-bool KDPipeIODevice::Private::doOpen( int fd_, Qt::HANDLE handle_, OpenMode mode_ ) {
-
- if ( q->isOpen() )
- return false;
-
-#ifdef Q_OS_WIN32
- if ( !handle_ )
- return false;
-#else
- if ( fd_ < 0 )
- return false;
-#endif
-
- if ( !(mode_ & ReadWrite) )
- return false; // need to have at least read -or- write
-
-
- std::auto_ptr<Reader> reader_;
- std::auto_ptr<Writer> writer_;
-
- if ( mode_ & ReadOnly ) {
- reader_.reset( new Reader( fd_, handle_ ) );
- qDebug( "KDPipeIODevice::doOpen (%p): created reader (%p) for fd %d", this, reader_.get(), fd_ );
- connect( reader_.get(), SIGNAL(readyRead()), this, SLOT(emitReadyRead()),
-Qt::QueuedConnection );
- }
- if ( mode_ & WriteOnly ) {
- writer_.reset( new Writer( fd_, handle_ ) );
- qDebug( "KDPipeIODevice::doOpen (%p): created writer (%p) for fd %d", this, writer_.get(), fd_ );
- connect( writer_.get(), SIGNAL(bytesWritten(qint64)), q, SIGNAL(bytesWritten(qint64)),
-Qt::QueuedConnection );
- }
-
- // commit to *this:
- fd = fd_;
- handle = handle_;
- reader = reader_.release();
- writer = writer_.release();
-
- q->setOpenMode( mode_|Unbuffered );
- return true;
-}
-
-int KDPipeIODevice::descriptor() const { KDAB_CHECK_THIS;
- return d->fd;
-}
-
-
-Qt::HANDLE KDPipeIODevice::handle() const { KDAB_CHECK_THIS;
- return d->handle;
-}
-
-qint64 KDPipeIODevice::bytesAvailable() const { KDAB_CHECK_THIS;
- const qint64 base = QIODevice::bytesAvailable();
- if ( !d->triedToStartReader ) {
- d->startReaderThread();
- return base;
- }
- if ( d->reader )
- synchronized( d->reader ) {
- const qint64 inBuffer = d->reader->bytesInBuffer();
- return base + inBuffer;
- }
- return base;
-}
-
-qint64 KDPipeIODevice::bytesToWrite() const { KDAB_CHECK_THIS;
- d->startWriterThread();
- const qint64 base = QIODevice::bytesToWrite();
- if ( d->writer )
- synchronized( d->writer ) return base + d->writer->bytesInBuffer();
- return base;
-}
-
-bool KDPipeIODevice::canReadLine() const { KDAB_CHECK_THIS;
- d->startReaderThread();
- if ( QIODevice::canReadLine() )
- return true;
- if ( d->reader )
- synchronized( d->reader ) return d->reader->bufferContains( '\n' );
- return true;
-}
-
-bool KDPipeIODevice::isSequential() const {
- return true;
-}
-
-bool KDPipeIODevice::atEnd() const { KDAB_CHECK_THIS;
- d->startReaderThread();
- if ( !QIODevice::atEnd() ) {
- qDebug( "%p: KDPipeIODevice::atEnd returns false since QIODevice::atEnd does (with bytesAvailable=%ld)", this, static_cast<long>(bytesAvailable()) );
- return false;
- }
- if ( !isOpen() )
- return true;
- if ( d->reader->eofShortCut )
- return true;
- LOCKED( d->reader );
- const bool eof = ( d->reader->error || d->reader->eof ) && d->reader->bufferEmpty();
- if ( !eof ) {
- if ( !d->reader->error && !d->reader->eof )
- qDebug( "%p: KDPipeIODevice::atEnd returns false since !reader->error && !reader->eof", this );
- if ( !d->reader->bufferEmpty() )
- qDebug( "%p: KDPipeIODevice::atEnd returns false since !reader->bufferEmpty()", this );
- }
- return eof;
-}
-
-bool KDPipeIODevice::waitForBytesWritten( int msecs ) { KDAB_CHECK_THIS;
- d->startWriterThread();
- Writer * const w = d->writer;
- if ( !w )
- return true;
- LOCKED( w );
- qDebug( "KDPipeIODevice::waitForBytesWritten (%p,w=%p): entered locked area", this, w
-);
- return w->bufferEmpty() || w->error || w->bufferEmptyCondition.wait( &w->mutex, msecs ) ;
-}
-
-bool KDPipeIODevice::waitForReadyRead( int msecs ) { KDAB_CHECK_THIS;
- qDebug( "KDPipeIODEvice::waitForReadyRead()(%p)", this);
- d->startReaderThread();
- if ( ALLOW_QIODEVICE_BUFFERING ) {
- if ( bytesAvailable() > 0 )
- return true;
- }
- Reader * const r = d->reader;
- if ( !r || r->eofShortCut )
- return true;
- LOCKED( r );
- if ( r->bytesInBuffer() != 0 || r->eof || r->error )
- return true;
-
- return msecs >= 0 ? r->bufferNotEmptyCondition.wait( &r->mutex, msecs ) : r->bufferNotEmptyCondition.wait( &r->mutex );
-}
-
-template <typename T>
-class TemporaryValue {
-public:
- TemporaryValue( T& var_, const T& tv ) : var( var_ ), oldValue( var_ ) { var = tv; }
- ~TemporaryValue() { var = oldValue; }
-private:
- T& var;
- const T oldValue;
-};
-
-
-bool KDPipeIODevice::readWouldBlock() const
-{
- d->startReaderThread();
- LOCKED( d->reader );
- return d->reader->bufferEmpty() && !d->reader->eof && !d->reader->error;
-}
-
-bool KDPipeIODevice::writeWouldBlock() const
-{
- d->startWriterThread();
- LOCKED( d->writer );
- return !d->writer->bufferEmpty() && !d->writer->error;
-}
-
-
-qint64 KDPipeIODevice::readData( char * data, qint64 maxSize ) { KDAB_CHECK_THIS;
- qDebug( "%p: KDPipeIODevice::readData: data=%p, maxSize=%lld", this, data, maxSize );
- d->startReaderThread();
- Reader * const r = d->reader;
-
- assert( r );
-
-
- //assert( r->isRunning() ); // wrong (might be eof, error)
- assert( data || maxSize == 0 );
- assert( maxSize >= 0 );
-
- if ( r->eofShortCut ) {
- qDebug( "%p: KDPipeIODevice::readData: hit eofShortCut, returning 0", this );
- return 0;
- }
-
- if ( maxSize < 0 )
- maxSize = 0;
-
- if ( ALLOW_QIODEVICE_BUFFERING ) {
- if ( bytesAvailable() > 0 )
- maxSize = std::min( maxSize, bytesAvailable() ); // don't block
- }
- qDebug( "%p: KDPipeIODevice::readData: try to lock reader (CONSUMER THREAD)", this );
- LOCKED( r );
- qDebug( "%p: KDPipeIODevice::readData: locked reader (CONSUMER THREAD)", this );
-
- r->readyReadSentCondition.wakeAll();
- if ( /* maxSize > 0 && */ r->bufferEmpty() && !r->error && !r->eof ) { // ### block on maxSize == 0?
- qDebug( "%p: KDPipeIODevice::readData: waiting for bufferNotEmptyCondition (CONSUMER THREAD)", this );
- const TemporaryValue<bool> tmp( d->reader->consumerBlocksOnUs, true );
- r->bufferNotEmptyCondition.wait( &r->mutex );
- r->blockedConsumerIsDoneCondition.wakeAll();
- qDebug( "%p: KDPipeIODevice::readData: woke up from bufferNotEmptyCondition (CONSUMER THREAD)", this );
- }
-
- if ( r->bufferEmpty() ) {
- qDebug( "%p: KDPipeIODevice::readData: got empty buffer, signal eof", this );
- // woken with an empty buffer must mean either EOF or error:
- assert( r->eof || r->error );
- r->eofShortCut = true;
- return r->eof ? 0 : -1 ;
- }
-
- qDebug( "%p: KDPipeIODevice::readData: got bufferNotEmptyCondition, trying to read %lld bytes", this, maxSize );
- const qint64 bytesRead = r->readData( data, maxSize );
- qDebug( "%p: KDPipeIODevice::readData: read %lld bytes", this, bytesRead );
- qDebug( "%p (fd=%d): KDPipeIODevice::readData: %s", this, d->fd, data );
-
- return bytesRead;
-}
-
-qint64 Reader::readData( char * data, qint64 maxSize ) {
- qint64 numRead = rptr < wptr ? wptr - rptr : sizeof buffer - rptr ;
- if ( numRead > maxSize )
- numRead = maxSize;
-
- qDebug( "%p: KDPipeIODevice::readData: data=%p, maxSize=%lld; rptr=%u, wptr=%u (bytesInBuffer=%u); -> numRead=%lld", this,
- data, maxSize, rptr, wptr, bytesInBuffer(), numRead );
-
- std::memcpy( data, buffer + rptr, numRead );
-
- rptr = ( rptr + numRead ) % sizeof buffer ;
-
- if ( !bufferFull() ) {
- qDebug( "%p: KDPipeIODevice::readData: signal bufferNotFullCondition", this );
- bufferNotFullCondition.wakeAll();
- }
-
- return numRead;
-}
-
-qint64 KDPipeIODevice::writeData( const char * data, qint64 size ) { KDAB_CHECK_THIS;
- d->startWriterThread();
- Writer * const w = d->writer;
-
- assert( w );
- assert( w->error || w->isRunning() );
- assert( data || size == 0 );
- assert( size >= 0 );
-
- LOCKED( w );
-
- while ( !w->error && !w->bufferEmpty() ) {
- qDebug( "%p: KDPipeIODevice::writeData: wait for empty buffer", this );
- w->bufferEmptyCondition.wait( &w->mutex );
- qDebug( "%p: KDPipeIODevice::writeData: empty buffer signaled", this );
-
- }
- if ( w->error )
- return -1;
-
- assert( w->bufferEmpty() );
-
- return w->writeData( data, size );
-}
-
-qint64 Writer::writeData( const char * data, qint64 size ) {
- assert( bufferEmpty() );
-
- if ( size > static_cast<qint64>( sizeof buffer ) )
- size = sizeof buffer;
-
- std::memcpy( buffer, data, size );
-
- numBytesInBuffer = size;
-
- if ( !bufferEmpty() ) {
- bufferNotEmptyCondition.wakeAll();
- }
- return size;
-}
-
-void KDPipeIODevice::Private::stopThreads()
-{
- if ( triedToStartWriter )
- {
- if ( writer && q->bytesToWrite() > 0 )
- q->waitForBytesWritten( -1 );
-
- assert( q->bytesToWrite() == 0 );
- }
- if ( Reader * & r = reader ) {
- disconnect( r, SIGNAL( readyRead() ), this, SLOT( emitReadyRead() ) );
- synchronized( r ) {
- // tell thread to cancel:
- r->cancel = true;
- // and wake it, so it can terminate:
- r->waitForCancelCondition.wakeAll();
- r->bufferNotFullCondition.wakeAll();
- r->readyReadSentCondition.wakeAll();
- }
- }
- if ( Writer * & w = writer ) {
- synchronized( w ) {
- // tell thread to cancel:
- w->cancel = true;
- // and wake it, so it can terminate:
- w->bufferNotEmptyCondition.wakeAll();
- }
- }
-}
-
-void KDPipeIODevice::close() { KDAB_CHECK_THIS;
- qDebug( "KDPipeIODevice::close(%p)", this );
- if ( !isOpen() )
- return;
-
- // tell clients we're about to close:
- emit aboutToClose();
- d->stopThreads();
-
-#define waitAndDelete( t ) if ( t ) { t->wait(); QThread* const t2 = t; t = 0; delete t2; }
- qDebug( "KPipeIODevice::close(%p): wait and closing writer %p", this, d->writer );
- waitAndDelete( d->writer );
- qDebug( "KPipeIODevice::close(%p): wait and closing reader %p", this, d->reader );
- if ( d->reader ) {
- LOCKED( d->reader );
- d->reader->readyReadSentCondition.wakeAll();
- }
- waitAndDelete( d->reader );
-#undef waitAndDelete
-#ifdef Q_OS_WIN32
- if ( d->fd != -1 )
- _close( d->fd );
- else
- CloseHandle( d->handle );
-#else
- ::close( d->fd );
-#endif
-
- setOpenMode( NotOpen );
- d->fd = -1;
- d->handle = 0;
-}
-
-void Reader::run() {
-
- LOCKED( this );
-
- // too bad QThread doesn't have that itself; a signal isn't enough
- hasStarted.wakeAll();
-
- qDebug( "%p: Reader::run: started", this );
-
- while ( true ) {
- if ( !cancel && ( eof || error ) ) {
- //notify the client until the buffer is empty and then once
- //again so he receives eof/error. After that, wait for him
- //to cancel
- const bool wasEmpty = bufferEmpty();
- qDebug( "%p: Reader::run: received eof(%d) or error(%d), waking everyone", this, eof, error );
- notifyReadyRead();
- if ( !cancel && wasEmpty )
- waitForCancelCondition.wait( &mutex );
- } else if ( !cancel && !bufferFull() && !bufferEmpty() ) {
- qDebug( "%p: Reader::run: buffer no longer empty, waking everyone", this );
- notifyReadyRead();
- }
-
- while ( !cancel && !error && bufferFull() ) {
- notifyReadyRead();
- if ( !cancel && bufferFull() ) {
- qDebug( "%p: Reader::run: buffer is full, going to sleep", this );
- bufferNotFullCondition.wait( &mutex );
- }
- }
-
- if ( cancel ) {
- qDebug( "%p: Reader::run: detected cancel", this );
- goto leave;
- }
-
- if ( !eof && !error ) {
- if ( rptr == wptr ) // optimize for larger chunks in case the buffer is empty
- rptr = wptr = 0;
-
- unsigned int numBytes = ( rptr + sizeof buffer - wptr - 1 ) % sizeof buffer;
- if ( numBytes > sizeof buffer - wptr )
- numBytes = sizeof buffer - wptr;
-
- qDebug( "%p: Reader::run: rptr=%d, wptr=%d -> numBytes=%d", this, rptr, wptr, numBytes );
-
- assert( numBytes > 0 );
-
- qDebug( "%p: Reader::run: trying to read %d bytes", this, numBytes );
-#ifdef Q_OS_WIN32
- isReading = true;
- mutex.unlock();
- DWORD numRead;
- const bool ok = ReadFile( handle, buffer + wptr, numBytes, &numRead, 0 );
- mutex.lock();
- isReading = false;
- if ( ok ) {
- if ( numRead == 0 ) {
- qDebug( "%p: Reader::run: got eof (numRead==0)", this );
- eof = true;
- }
- } else { // !ok
- errorCode = static_cast<int>( GetLastError() );
- if ( errorCode == ERROR_BROKEN_PIPE ) {
- assert( numRead == 0 );
- qDebug( "%p: Reader::run: got eof (broken pipe)", this );
- eof = true;
- } else {
- assert( numRead == 0 );
- qDebug( "%p: Reader::run: got error: %s (%d)", this, strerror( errorCode ), errorCode );
- error = true;
- }
- }
-#else
- qint64 numRead;
- mutex.unlock();
- do {
- numRead = ::read( fd, buffer + wptr, numBytes );
- } while ( numRead == -1 && errno == EINTR );
- mutex.lock();
-
- if ( numRead < 0 ) {
- errorCode = errno;
- error = true;
- qDebug( "%p: Reader::run: got error: %d", this, errorCode );
- } else if ( numRead == 0 ) {
- qDebug( "%p: Reader::run: eof detected", this );
- eof = true;
- }
-#endif
- qDebug( "%p: Reader::run: read %ld bytes", this, static_cast<long>(numRead) );
- qDebug( "%p: Reader::run(fd=%d): %s", this, fd, buffer );
-
- if ( numRead > 0 ) {
- qDebug( "%p: Reader::run: buffer before: rptr=%4d, wptr=%4d", this, rptr, wptr );
- wptr = ( wptr + numRead ) % sizeof buffer;
- qDebug( "%p: Reader::run: buffer after: rptr=%4d, wptr=%4d", this, rptr, wptr );
- }
- }
- }
- leave:
- qDebug( "%p: Reader::run: terminated", this );
-}
-
-void Reader::notifyReadyRead()
-{
- qDebug( "notifyReadyRead: %d bytes available", bytesInBuffer() );
- assert( !cancel );
-
- if ( consumerBlocksOnUs ) {
- bufferNotEmptyCondition.wakeAll();
- blockedConsumerIsDoneCondition.wait( &mutex );
- return;
- }
- qDebug( "notifyReadyRead: emit signal" );
- emit readyRead();
- readyReadSentCondition.wait( &mutex );
- qDebug( "notifyReadyRead: returning from waiting, leave" );
-}
-
-void Writer::run() {
-
- LOCKED( this );
-
- // too bad QThread doesn't have that itself; a signal isn't enough
- hasStarted.wakeAll();
-
- qDebug( "%p: Writer::run: started", this );
-
- while ( true ) {
-
- while ( !cancel && bufferEmpty() ) {
- qDebug( "%p: Writer::run: buffer is empty, wake bufferEmptyCond listeners", this );
- bufferEmptyCondition.wakeAll();
- emit bytesWritten( 0 );
- qDebug( "%p: Writer::run: buffer is empty, going to sleep", this );
- bufferNotEmptyCondition.wait( &mutex );
- qDebug( "%p: Writer::run: woke up", this );
- }
-
- if ( cancel ) {
- qDebug( "%p: Writer::run: detected cancel", this );
- goto leave;
- }
-
- assert( numBytesInBuffer > 0 );
-
- qDebug( "%p: Writer::run: Trying to write %u bytes", this, numBytesInBuffer );
- qint64 totalWritten = 0;
- do {
- mutex.unlock();
-#ifdef Q_OS_WIN32
- DWORD numWritten;
- qDebug( "%p (fd=%d): Writer::run: buffer before WriteFile (numBytes=%lld): %s:", this, fd, numBytesInBuffer, buffer );
- qDebug( "%p (fd=%d): Writer::run: Going into WriteFile", this, fd );
- if ( !WriteFile( handle, buffer + totalWritten, numBytesInBuffer - totalWritten, &numWritten, 0 ) ) {
- mutex.lock();
- errorCode = static_cast<int>( GetLastError() );
- qDebug( "%p: Writer::run: got error code: %d", this, errorCode );
- error = true;
- goto leave;
- }
-#else
- qint64 numWritten;
- do {
- numWritten = ::write( fd, buffer + totalWritten, numBytesInBuffer - totalWritten );
- } while ( numWritten == -1 && errno == EINTR );
-
- if ( numWritten < 0 ) {
- mutex.lock();
- errorCode = errno;
- qDebug( "%p: Writer::run: got error code: %d", this, errorCode );
- error = true;
- goto leave;
- }
-#endif
- qDebug( "%p (fd=%d): Writer::run: buffer after WriteFile (numBytes=%u): %s:", this, fd, numBytesInBuffer, buffer );
- totalWritten += numWritten;
- mutex.lock();
- } while ( totalWritten < numBytesInBuffer );
-
- qDebug( "%p: Writer::run: wrote %lld bytes", this, totalWritten );
-
- numBytesInBuffer = 0;
-
- qDebug( "%p: Writer::run: buffer is empty, wake bufferEmptyCond listeners", this );
- bufferEmptyCondition.wakeAll();
- emit bytesWritten( totalWritten );
- }
- leave:
- qDebug( "%p: Writer::run: terminating", this );
- numBytesInBuffer = 0;
- qDebug( "%p: Writer::run: buffer is empty, wake bufferEmptyCond listeners", this );
- bufferEmptyCondition.wakeAll();
- emit bytesWritten( 0 );
-}
-
-// static
-std::pair<KDPipeIODevice*,KDPipeIODevice*> KDPipeIODevice::makePairOfConnectedPipes() {
- KDPipeIODevice * read = 0;
- KDPipeIODevice * write = 0;
-#ifdef Q_OS_WIN32
- HANDLE rh;
- HANDLE wh;
- SECURITY_ATTRIBUTES sa;
- memset( &sa, 0, sizeof(sa) );
- sa.nLength = sizeof(sa);
- sa.bInheritHandle = TRUE;
- if ( CreatePipe( &rh, &wh, &sa, BUFFER_SIZE ) ) {
- read = new KDPipeIODevice;
- read->open( rh, ReadOnly );
- write = new KDPipeIODevice;
- write->open( wh, WriteOnly );
- }
-#else
- int fds[2];
- if ( pipe( fds ) == 0 ) {
- read = new KDPipeIODevice;
- read->open( fds[0], ReadOnly );
- write = new KDPipeIODevice;
- write->open( fds[1], WriteOnly );
- }
-#endif
- return std::make_pair( read, write );
-}
-
-#ifdef KDAB_DEFINE_CHECKS
-KDAB_DEFINE_CHECKS( KDPipeIODevice ) {
- if ( !isOpen() ) {
- assert( openMode() == NotOpen );
- assert( !d->reader );
- assert( !d->writer );
-#ifdef Q_OS_WIN32
- assert( !d->handle );
-#else
- assert( d->fd < 0 );
-#endif
- } else {
- assert( openMode() != NotOpen );
- assert( openMode() & ReadWrite );
- if ( openMode() & ReadOnly ) {
- assert( d->reader );
- synchronized( d->reader )
- assert( d->reader->eof || d->reader->error || d->reader->isRunning() );
- }
- if ( openMode() & WriteOnly ) {
- assert( d->writer );
- synchronized( d->writer )
- assert( d->writer->error || d->writer->isRunning() );
- }
-#ifdef Q_OS_WIN32
- assert( d->handle );
-#else
- assert( d->fd >= 0 );
-#endif
- }
-}
-#endif // KDAB_DEFINE_CHECKS
-
-#include "moc_kdpipeiodevice.cpp"
-#include "kdpipeiodevice.moc"
diff --git a/src/kdpipeiodevice.h b/src/kdpipeiodevice.h
deleted file mode 100644
index 8da6af6..0000000
--- a/src/kdpipeiodevice.h
+++ /dev/null
@@ -1,73 +0,0 @@
-/*
- Copyright (C) 2007 Klarälvdalens Datakonsult AB
-
- KDPipeIODevice is free software; you can redistribute it and/or
- modify it under the terms of the GNU Library General Public
- License as published by the Free Software Foundation; either
- version 2 of the License, or (at your option) any later version.
-
- KDPipeIODevice is distributed in the hope that it will be useful,
- but WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- GNU Library General Public License for more details.
-
- You should have received a copy of the GNU Library General Public License
- along with KDPipeIODevice; see the file COPYING.LIB. If not, write to the
- Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
- Boston, MA 02110-1301, USA.
-*/
-
-#ifndef __KDTOOLSCORE_KDPIPEIODEVICE_H__
-#define __KDTOOLSCORE_KDPIPEIODEVICE_H__
-
-#include <QIODevice>
-
-#include <utility>
-
-//#include "checker.h"
-
-namespace _gpgme_ {
-
-class KDPipeIODevice : public QIODevice {
- Q_OBJECT
- //KDAB_MAKE_CHECKABLE( KDPipeIODevice )
-public:
- explicit KDPipeIODevice( QObject * parent=0 );
- explicit KDPipeIODevice( int fd, OpenMode=ReadOnly, QObject * parent=0 );
- explicit KDPipeIODevice( Qt::HANDLE handle, OpenMode=ReadOnly, QObject * parent=0 );
- ~KDPipeIODevice();
-
- static std::pair<KDPipeIODevice*, KDPipeIODevice*> makePairOfConnectedPipes();
-
- bool open( int fd, OpenMode mode=ReadOnly );
- bool open( Qt::HANDLE handle, OpenMode mode=ReadOnly );
-
- Qt::HANDLE handle() const;
- int descriptor() const;
-
- bool readWouldBlock() const;
- bool writeWouldBlock() const;
-
- /* reimp */ qint64 bytesAvailable() const;
- /* reimp */ qint64 bytesToWrite() const;
- /* reimp */ bool canReadLine() const;
- /* reimp */ void close();
- /* reimp */ bool isSequential() const;
- /* reimp */ bool atEnd() const;
-
- /* reimp */ bool waitForBytesWritten( int msecs );
- /* reimp */ bool waitForReadyRead( int msecs );
-
-protected:
- /* reimp */ qint64 readData( char * data, qint64 maxSize );
- /* reimp */ qint64 writeData( const char * data, qint64 maxSize );
-
-private:
- class Private;
- Private * d;
-};
-
-} /* namespace _gpgme_ */
-
-#endif /* __KDTOOLSCORE_KDPIPEIODEVICE_H__ */
-
diff --git a/src/kdpipeiodevice.moc b/src/kdpipeiodevice.moc
deleted file mode 100644
index 457f371..0000000
--- a/src/kdpipeiodevice.moc
+++ /dev/null
@@ -1,183 +0,0 @@
-/****************************************************************************
-** Meta object code from reading C++ file 'kdpipeiodevice.cpp'
-**
-** Created: Tue Oct 2 19:30:13 2007
-** by: The Qt Meta Object Compiler version 59 (Qt 4.3.1)
-**
-** WARNING! All changes made in this file will be lost!
-*****************************************************************************/
-
-#if !defined(Q_MOC_OUTPUT_REVISION)
-#error "The header file 'kdpipeiodevice.cpp' doesn't include <QObject>."
-#elif Q_MOC_OUTPUT_REVISION != 59
-#error "This file was generated using the moc from 4.3.1. It"
-#error "cannot be used with the include files from this version of Qt."
-#error "(The moc has changed too much.)"
-#endif
-
-static const uint qt_meta_data_Reader[] = {
-
- // content:
- 1, // revision
- 0, // classname
- 0, 0, // classinfo
- 1, 10, // methods
- 0, 0, // properties
- 0, 0, // enums/sets
-
- // signals: signature, parameters, type, tag, flags
- 8, 7, 7, 7, 0x05,
-
- 0 // eod
-};
-
-static const char qt_meta_stringdata_Reader[] = {
- "Reader\0\0readyRead()\0"
-};
-
-const QMetaObject Reader::staticMetaObject = {
- { &QThread::staticMetaObject, qt_meta_stringdata_Reader,
- qt_meta_data_Reader, 0 }
-};
-
-const QMetaObject *Reader::metaObject() const
-{
- return &staticMetaObject;
-}
-
-void *Reader::qt_metacast(const char *_clname)
-{
- if (!_clname) return 0;
- if (!strcmp(_clname, qt_meta_stringdata_Reader))
- return static_cast<void*>(const_cast< Reader*>(this));
- return QThread::qt_metacast(_clname);
-}
-
-int Reader::qt_metacall(QMetaObject::Call _c, int _id, void **_a)
-{
- _id = QThread::qt_metacall(_c, _id, _a);
- if (_id < 0)
- return _id;
- if (_c == QMetaObject::InvokeMetaMethod) {
- switch (_id) {
- case 0: readyRead(); break;
- }
- _id -= 1;
- }
- return _id;
-}
-
-// SIGNAL 0
-void Reader::readyRead()
-{
- QMetaObject::activate(this, &staticMetaObject, 0, 0);
-}
-static const uint qt_meta_data_Writer[] = {
-
- // content:
- 1, // revision
- 0, // classname
- 0, 0, // classinfo
- 1, 10, // methods
- 0, 0, // properties
- 0, 0, // enums/sets
-
- // signals: signature, parameters, type, tag, flags
- 8, 7, 7, 7, 0x05,
-
- 0 // eod
-};
-
-static const char qt_meta_stringdata_Writer[] = {
- "Writer\0\0bytesWritten(qint64)\0"
-};
-
-const QMetaObject Writer::staticMetaObject = {
- { &QThread::staticMetaObject, qt_meta_stringdata_Writer,
- qt_meta_data_Writer, 0 }
-};
-
-const QMetaObject *Writer::metaObject() const
-{
- return &staticMetaObject;
-}
-
-void *Writer::qt_metacast(const char *_clname)
-{
- if (!_clname) return 0;
- if (!strcmp(_clname, qt_meta_stringdata_Writer))
- return static_cast<void*>(const_cast< Writer*>(this));
- return QThread::qt_metacast(_clname);
-}
-
-int Writer::qt_metacall(QMetaObject::Call _c, int _id, void **_a)
-{
- _id = QThread::qt_metacall(_c, _id, _a);
- if (_id < 0)
- return _id;
- if (_c == QMetaObject::InvokeMetaMethod) {
- switch (_id) {
- case 0: bytesWritten((*reinterpret_cast< qint64(*)>(_a[1]))); break;
- }
- _id -= 1;
- }
- return _id;
-}
-
-// SIGNAL 0
-void Writer::bytesWritten(qint64 _t1)
-{
- void *_a[] = { 0, const_cast<void*>(reinterpret_cast<const void*>(&_t1)) };
- QMetaObject::activate(this, &staticMetaObject, 0, _a);
-}
-static const uint qt_meta_data_KDPipeIODevice__Private[] = {
-
- // content:
- 1, // revision
- 0, // classname
- 0, 0, // classinfo
- 1, 10, // methods
- 0, 0, // properties
- 0, 0, // enums/sets
-
- // slots: signature, parameters, type, tag, flags
- 25, 24, 24, 24, 0x0a,
-
- 0 // eod
-};
-
-static const char qt_meta_stringdata_KDPipeIODevice__Private[] = {
- "KDPipeIODevice::Private\0\0emitReadyRead()\0"
-};
-
-const QMetaObject KDPipeIODevice::Private::staticMetaObject = {
- { &QObject::staticMetaObject, qt_meta_stringdata_KDPipeIODevice__Private,
- qt_meta_data_KDPipeIODevice__Private, 0 }
-};
-
-const QMetaObject *KDPipeIODevice::Private::metaObject() const
-{
- return &staticMetaObject;
-}
-
-void *KDPipeIODevice::Private::qt_metacast(const char *_clname)
-{
- if (!_clname) return 0;
- if (!strcmp(_clname, qt_meta_stringdata_KDPipeIODevice__Private))
- return static_cast<void*>(const_cast< Private*>(this));
- return QObject::qt_metacast(_clname);
-}
-
-int KDPipeIODevice::Private::qt_metacall(QMetaObject::Call _c, int _id, void **_a)
-{
- _id = QObject::qt_metacall(_c, _id, _a);
- if (_id < 0)
- return _id;
- if (_c == QMetaObject::InvokeMetaMethod) {
- switch (_id) {
- case 0: emitReadyRead(); break;
- }
- _id -= 1;
- }
- return _id;
-}
diff --git a/src/key.c b/src/key.c
index 1a68966..38acc71 100644
--- a/src/key.c
+++ b/src/key.c
@@ -31,6 +31,8 @@
#include "ops.h"
#include "sema.h"
#include "debug.h"
+#include "mbox-util.h"
+
/* Protects all reference counters in keys. All other accesses to a
@@ -233,6 +235,14 @@ _gpgme_key_append_name (gpgme_key_t key, const char *src, int convert)
parse_user_id (uid->uid, &uid->name, &uid->email,
&uid->comment, dst);
+ uid->address = _gpgme_mailbox_from_userid (uid->uid);
+ if (uid->address && uid->email && !strcmp (uid->address, uid->email))
+ {
+ /* The ADDRESS is the same as EMAIL: Save some space. */
+ free (uid->address);
+ uid->address = uid->email;
+ }
+
if (!key->uids)
key->uids = uid;
if (key->_last_uid)
@@ -333,6 +343,8 @@ gpgme_key_unref (gpgme_key_t key)
free (subkey->fpr);
if (subkey->curve)
free (subkey->curve);
+ if (subkey->keygrip)
+ free (subkey->keygrip);
if (subkey->card_number)
free (subkey->card_number);
free (subkey);
@@ -344,6 +356,7 @@ gpgme_key_unref (gpgme_key_t key)
{
gpgme_user_id_t next_uid = uid->next;
gpgme_key_sig_t keysig = uid->signatures;
+ gpgme_tofu_info_t tofu = uid->tofu;
while (keysig)
{
@@ -361,6 +374,21 @@ gpgme_key_unref (gpgme_key_t key)
free (keysig);
keysig = next_keysig;
}
+
+ while (tofu)
+ {
+ /* NB: The ->next is currently not used but we are prepared
+ * for it. */
+ gpgme_tofu_info_t tofu_next = tofu->next;
+
+ free (tofu->description);
+ free (tofu);
+ tofu = tofu_next;
+ }
+
+ if (uid->address && uid->address != uid->email)
+ free (uid->address);
+
free (uid);
uid = next_uid;
}
@@ -372,10 +400,13 @@ gpgme_key_unref (gpgme_key_t key)
if (key->chain_id)
free (key->chain_id);
+ if (key->fpr)
+ free (key->fpr);
free (key);
}
+
/* Support functions. */
diff --git a/src/keylist.c b/src/keylist.c
index fcf574f..8a0c5a3 100644
--- a/src/keylist.c
+++ b/src/keylist.c
@@ -33,6 +33,7 @@
#include <assert.h>
#include <ctype.h>
#include <errno.h>
+#include <limits.h>
/* Suppress warning for accessing deprecated member "class". */
#define _GPGME_IN_GPGME
@@ -121,6 +122,8 @@ keylist_status_handler (void *priv, gpgme_status_code_t code, char *args)
void *hook;
op_data_t opd;
+ (void)args;
+
err = _gpgme_op_data_lookup (ctx, OPDATA_KEYLIST, &hook, -1, NULL);
opd = hook;
if (err)
@@ -403,6 +406,98 @@ parse_sec_field15 (gpgme_key_t key, gpgme_subkey_t subkey, char *field)
}
+/* Parse a tfs record. */
+static gpg_error_t
+parse_tfs_record (gpgme_user_id_t uid, char **field, int nfield)
+{
+ gpg_error_t err;
+ gpgme_tofu_info_t ti;
+ unsigned long uval;
+
+ /* We add only the first TOFU record in case future versions emit
+ * several. */
+ if (uid->tofu)
+ return 0;
+
+ /* Check that we have enough fields and that the version is supported. */
+ if (nfield < 8 || atoi(field[1]) != 1)
+ return trace_gpg_error (GPG_ERR_INV_ENGINE);
+
+ ti = calloc (1, sizeof *ti);
+ if (!ti)
+ return gpg_error_from_syserror ();
+
+ /* Note that we allow a value of up to 7 which is what we can store
+ * in the ti->validity. */
+ err = _gpgme_strtoul_field (field[2], &uval);
+ if (err || uval > 7)
+ goto inv_engine;
+ ti->validity = uval;
+
+ /* Parse the sign-count. */
+ err = _gpgme_strtoul_field (field[3], &uval);
+ if (err)
+ goto inv_engine;
+ if (uval > USHRT_MAX)
+ uval = USHRT_MAX;
+ ti->signcount = uval;
+
+ /* Parse the encr-count. */
+ err = _gpgme_strtoul_field (field[4], &uval);
+ if (err)
+ goto inv_engine;
+ if (uval > USHRT_MAX)
+ uval = USHRT_MAX;
+ ti->encrcount = uval;
+
+ /* Parse the policy. */
+ if (!strcmp (field[5], "none"))
+ ti->policy = GPGME_TOFU_POLICY_NONE;
+ else if (!strcmp (field[5], "auto"))
+ ti->policy = GPGME_TOFU_POLICY_AUTO;
+ else if (!strcmp (field[5], "good"))
+ ti->policy = GPGME_TOFU_POLICY_GOOD;
+ else if (!strcmp (field[5], "bad"))
+ ti->policy = GPGME_TOFU_POLICY_BAD;
+ else if (!strcmp (field[5], "ask"))
+ ti->policy = GPGME_TOFU_POLICY_ASK;
+ else /* "unknown" and invalid policy strings. */
+ ti->policy = GPGME_TOFU_POLICY_UNKNOWN;
+
+ /* Parse first and last seen timestamps. */
+ err = _gpgme_strtoul_field (field[6], &uval);
+ if (err)
+ goto inv_engine;
+ ti->signfirst = uval;
+ err = _gpgme_strtoul_field (field[7], &uval);
+ if (err)
+ goto inv_engine;
+ ti->signlast = uval;
+
+ if (nfield > 9)
+ {
+ /* This condition is only to allow for gpg 2.1.15 - can
+ * eventually be removed. */
+ err = _gpgme_strtoul_field (field[8], &uval);
+ if (err)
+ goto inv_engine;
+ ti->encrfirst = uval;
+ err = _gpgme_strtoul_field (field[9], &uval);
+ if (err)
+ goto inv_engine;
+ ti->encrlast = uval;
+ }
+
+ /* Ready. */
+ uid->tofu = ti;
+ return 0;
+
+ inv_engine:
+ free (ti);
+ return trace_gpg_error (GPG_ERR_INV_ENGINE);
+}
+
+
/* We have read an entire key into tmp_key and should now finish it.
It is assumed that this releases tmp_key. */
static void
@@ -426,7 +521,7 @@ keylist_colon_handler (void *priv, char *line)
gpgme_ctx_t ctx = (gpgme_ctx_t) priv;
enum
{
- RT_NONE, RT_SIG, RT_UID, RT_SUB, RT_PUB, RT_FPR,
+ RT_NONE, RT_SIG, RT_UID, RT_TFS, RT_SUB, RT_PUB, RT_FPR, RT_GRP,
RT_SSB, RT_SEC, RT_CRT, RT_CRS, RT_REV, RT_SPK
}
rectype = RT_NONE;
@@ -479,8 +574,12 @@ keylist_colon_handler (void *priv, char *line)
rectype = RT_CRS;
else if (!strcmp (field[0], "fpr") && key)
rectype = RT_FPR;
+ else if (!strcmp (field[0], "grp") && key)
+ rectype = RT_GRP;
else if (!strcmp (field[0], "uid") && key)
rectype = RT_UID;
+ else if (!strcmp (field[0], "tfs") && key)
+ rectype = RT_TFS;
else if (!strcmp (field[0], "sub") && key)
rectype = RT_SUB;
else if (!strcmp (field[0], "ssb") && key)
@@ -490,10 +589,10 @@ keylist_colon_handler (void *priv, char *line)
else
rectype = RT_NONE;
- /* Only look at signatures immediately following a user ID. For
- this, clear the user ID pointer when encountering anything but a
- signature. */
- if (rectype != RT_SIG && rectype != RT_REV)
+ /* Only look at signature and trust info records immediately
+ following a user ID. For this, clear the user ID pointer when
+ encountering anything but a signature or trust record. */
+ if (rectype != RT_SIG && rectype != RT_REV && rectype != RT_TFS)
opd->tmp_uid = NULL;
/* Only look at subpackets immediately following a signature. For
@@ -693,6 +792,15 @@ keylist_colon_handler (void *priv, char *line)
}
break;
+ case RT_TFS:
+ if (opd->tmp_uid)
+ {
+ err = parse_tfs_record (opd->tmp_uid, field, fields);
+ if (err)
+ return err;
+ }
+ break;
+
case RT_FPR:
/* Field 10 has the fingerprint (take only the first one). */
if (fields >= 10 && field[9] && *field[9])
@@ -706,6 +814,22 @@ keylist_colon_handler (void *priv, char *line)
if (!subkey->fpr)
return gpg_error_from_syserror ();
}
+ /* If this is the first subkey, store the fingerprint also
+ in the KEY object. */
+ if (subkey == key->subkeys)
+ {
+ if (key->fpr && strcmp (key->fpr, subkey->fpr))
+ {
+ /* FPR already set but mismatch: Should never happen. */
+ return trace_gpg_error (GPG_ERR_INTERNAL);
+ }
+ if (!key->fpr)
+ {
+ key->fpr = strdup (subkey->fpr);
+ if (!key->fpr)
+ return gpg_error_from_syserror ();
+ }
+ }
}
/* Field 13 has the gpgsm chain ID (take only the first one). */
@@ -717,6 +841,22 @@ keylist_colon_handler (void *priv, char *line)
}
break;
+ case RT_GRP:
+ /* Field 10 has the keygrip. */
+ if (fields >= 10 && field[9] && *field[9])
+ {
+ /* Need to apply it to the last subkey because all subkeys
+ have a keygrip. */
+ subkey = key->_last_subkey;
+ if (!subkey->keygrip)
+ {
+ subkey->keygrip = strdup (field[9]);
+ if (!subkey->keygrip)
+ return gpg_error_from_syserror ();
+ }
+ }
+ break;
+
case RT_SIG:
case RT_REV:
if (!opd->tmp_uid)
diff --git a/src/keysign.c b/src/keysign.c
new file mode 100644
index 0000000..7d08c11
--- /dev/null
+++ b/src/keysign.c
@@ -0,0 +1,218 @@
+/* keysign.c - OpenPGP key signing
+ * Copyright (C) 2016 g10 Code GmbH
+ *
+ * This file is part of GPGME.
+ *
+ * GPGME is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU Lesser General Public License as
+ * published by the Free Software Foundation; either version 2.1 of
+ * the License, or (at your option) any later version.
+ *
+ * GPGME is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this program; if not, see <http://www.gnu.org/licenses/>.
+ */
+
+#if HAVE_CONFIG_H
+#include <config.h>
+#endif
+#include <stdlib.h>
+#include <string.h>
+#include <errno.h>
+
+#include "gpgme.h"
+#include "debug.h"
+#include "context.h"
+#include "ops.h"
+#include "util.h"
+
+
+typedef struct
+{
+ /* The error code from a FAILURE status line or 0. */
+ gpg_error_t failure_code;
+
+ /* The error code from certain ERROR status lines or 0. */
+ gpg_error_t error_code;
+
+} *op_data_t;
+
+
+static void
+release_op_data (void *hook)
+{
+ op_data_t opd = (op_data_t) hook;
+
+ (void)opd;
+}
+
+
+/* Parse an error status line. Return the error location and the
+ error code. The function may modify ARGS. */
+static char *
+parse_error (char *args, gpg_error_t *r_err)
+{
+ char *where = strchr (args, ' ');
+ char *which;
+
+ if (where)
+ {
+ *where = '\0';
+ which = where + 1;
+
+ where = strchr (which, ' ');
+ if (where)
+ *where = '\0';
+
+ where = args;
+ }
+ else
+ {
+ *r_err = trace_gpg_error (GPG_ERR_INV_ENGINE);
+ return NULL;
+ }
+
+ *r_err = atoi (which);
+
+ return where;
+}
+
+
+static gpgme_error_t
+keysign_status_handler (void *priv, gpgme_status_code_t code, char *args)
+{
+ gpgme_ctx_t ctx = (gpgme_ctx_t) priv;
+ gpgme_error_t err;
+ void *hook;
+ op_data_t opd;
+ char *loc;
+
+ /* Pipe the status code through the progress status handler. */
+ err = _gpgme_progress_status_handler (ctx, code, args);
+ if (err)
+ return err;
+
+ err = _gpgme_op_data_lookup (ctx, OPDATA_KEYSIGN, &hook, -1, NULL);
+ opd = hook;
+ if (err)
+ return err;
+
+ switch (code)
+ {
+ case GPGME_STATUS_ERROR:
+ loc = parse_error (args, &err);
+ if (!loc)
+ return err;
+ if (!opd->error_code)
+ opd->error_code = err;
+ break;
+
+ case GPGME_STATUS_FAILURE:
+ opd->failure_code = _gpgme_parse_failure (args);
+ break;
+
+ case GPGME_STATUS_EOF:
+ if (opd->error_code)
+ return opd->error_code;
+ else if (opd->failure_code)
+ return opd->failure_code;
+ break;
+
+ case GPGME_STATUS_INQUIRE_MAXLEN:
+ if (ctx->status_cb && !ctx->full_status)
+ {
+ err = ctx->status_cb (ctx->status_cb_value, "INQUIRE_MAXLEN", args);
+ if (err)
+ return err;
+ }
+ break;
+
+ default:
+ break;
+ }
+ return 0;
+}
+
+
+/* Sign the USERID of KEY using the current set of signers. If USERID
+ * is NULL, sign all user ids. To put several user ids into USERID,
+ * separate them by LF and set the flag GPGME_KEYSIGN_LFSEP. */
+static gpgme_error_t
+keysign_start (gpgme_ctx_t ctx, int synchronous,
+ gpgme_key_t key, const char *userid,
+ unsigned long expires, unsigned int flags)
+{
+ gpgme_error_t err;
+ void *hook;
+ op_data_t opd;
+
+ if (ctx->protocol != GPGME_PROTOCOL_OPENPGP)
+ return gpgme_error (GPG_ERR_UNSUPPORTED_PROTOCOL);
+
+ err = _gpgme_op_reset (ctx, synchronous);
+ if (err)
+ return err;
+
+ if (!key)
+ return gpg_error (GPG_ERR_INV_ARG);
+
+ err = _gpgme_op_data_lookup (ctx, OPDATA_KEYSIGN, &hook,
+ sizeof (*opd), release_op_data);
+ opd = hook;
+ if (err)
+ return err;
+
+ _gpgme_engine_set_status_handler (ctx->engine, keysign_status_handler, ctx);
+
+ if (ctx->passphrase_cb)
+ {
+ err = _gpgme_engine_set_command_handler
+ (ctx->engine, _gpgme_passphrase_command_handler, ctx, NULL);
+ if (err)
+ return err;
+ }
+
+ return _gpgme_engine_op_keysign (ctx->engine,
+ key, userid, expires, flags, ctx);
+}
+
+
+/* Sign the USERID of KEY using the current set of signers. */
+gpgme_error_t
+gpgme_op_keysign_start (gpgme_ctx_t ctx, gpgme_key_t key, const char *userid,
+ unsigned long expires, unsigned int flags)
+{
+ gpgme_error_t err;
+
+ TRACE_BEG3 (DEBUG_CTX, "gpgme_op_keysign_start", ctx,
+ "key=%p, uid='%s' flags=0x%x", key, userid, flags);
+
+ if (!ctx)
+ return TRACE_ERR (gpg_error (GPG_ERR_INV_ARG));
+
+ err = keysign_start (ctx, 0, key, userid, expires, flags);
+ return TRACE_ERR (err);
+}
+
+
+gpgme_error_t
+gpgme_op_keysign (gpgme_ctx_t ctx, gpgme_key_t key, const char *userid,
+ unsigned long expires, unsigned int flags)
+{
+ gpgme_error_t err;
+
+ TRACE_BEG3 (DEBUG_CTX, "gpgme_op_keysign", ctx,
+ "key=%p, uid='%s' flags=0x%x", key, userid, flags);
+
+ if (!ctx)
+ return TRACE_ERR (gpg_error (GPG_ERR_INV_ARG));
+
+ err = keysign_start (ctx, 1, key, userid, expires, flags);
+ if (!err)
+ err = _gpgme_wait_one (ctx);
+ return TRACE_ERR (err);
+}
diff --git a/src/libgpgme.vers b/src/libgpgme.vers
index 6687571..aec9090 100644
--- a/src/libgpgme.vers
+++ b/src/libgpgme.vers
@@ -98,6 +98,25 @@ GPGME_1.1 {
gpgme_set_status_cb;
gpgme_get_status_cb;
+
+ gpgme_pubkey_algo_string;
+ gpgme_set_ctx_flag;
+ gpgme_data_set_flag;
+
+ gpgme_op_createkey_start;
+ gpgme_op_createkey;
+ gpgme_op_createsubkey_start;
+ gpgme_op_createsubkey;
+ gpgme_op_adduid_start;
+ gpgme_op_adduid;
+ gpgme_op_revuid_start;
+ gpgme_op_revuid;
+ gpgme_op_keysign_start;
+ gpgme_op_keysign;
+ gpgme_op_tofu_policy_start;
+ gpgme_op_tofu_policy;
+ gpgme_op_interact_start;
+ gpgme_op_interact;
};
diff --git a/src/mbox-util.c b/src/mbox-util.c
new file mode 100644
index 0000000..83c8b5e
--- /dev/null
+++ b/src/mbox-util.c
@@ -0,0 +1,257 @@
+/* mbox-util.c - Mail address helper functions
+ * Copyright (C) 1998-2010 Free Software Foundation, Inc.
+ * Copyright (C) 1998-2015 Werner Koch
+ *
+ * This file is part of GnuPG.
+ *
+ * This file is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License as
+ * published by the Free Software Foundation; either version 2.1 of
+ * the License, or (at your option) any later version.
+ *
+ * This file 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 Lesser General Public License
+ * along with this program; if not, see <http://www.gnu.org/licenses/>.
+ */
+
+/* NB: This code has been taken from GnuPG. Please keep it in sync
+ * with GnuPG. */
+
+#if HAVE_CONFIG_H
+# include <config.h>
+#endif
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <unistd.h>
+#include <errno.h>
+
+#include "mbox-util.h"
+
+/* Lowercase all ASCII characters in STRING. */
+static char *
+ascii_strlwr (char *string)
+{
+ char *p;
+
+ for (p = string; *p; p++ )
+ if (!(*p & ~0x7f) && *p >= 'A' && *p <= 'Z')
+ *p |= 0x20;
+
+ return string;
+}
+
+
+static int
+string_count_chr (const char *string, int c)
+{
+ int count;
+
+ for (count=0; *string; string++ )
+ if ( *string == c )
+ count++;
+ return count;
+}
+
+static int
+mem_count_chr (const void *buffer, int c, size_t length)
+{
+ const char *s = buffer;
+ int count;
+
+ for (count=0; length; length--, s++)
+ if (*s == c)
+ count++;
+ return count;
+}
+
+
+/* This is a case-sensitive version of our memistr. I wonder why no
+ standard function memstr exists but I better do not use the name
+ memstr to avoid future conflicts. */
+static const char *
+my_memstr (const void *buffer, size_t buflen, const char *sub)
+{
+ const unsigned char *buf = buffer;
+ const unsigned char *t = (const unsigned char *)buf;
+ const unsigned char *s = (const unsigned char *)sub;
+ size_t n = buflen;
+
+ for ( ; n ; t++, n-- )
+ {
+ if (*t == *s)
+ {
+ for (buf = t++, buflen = n--, s++; n && *t ==*s; t++, s++, n--)
+ ;
+ if (!*s)
+ return (const char*)buf;
+ t = (const unsigned char *)buf;
+ s = (const unsigned char *)sub ;
+ n = buflen;
+ }
+ }
+ return NULL;
+}
+
+
+
+static int
+string_has_ctrl_or_space (const char *string)
+{
+ for (; *string; string++ )
+ if (!(*string & 0x80) && *string <= 0x20)
+ return 1;
+ return 0;
+}
+
+
+/* Return true if STRING has two consecutive '.' after an '@'
+ sign. */
+static int
+has_dotdot_after_at (const char *string)
+{
+ string = strchr (string, '@');
+ if (!string)
+ return 0; /* No at-sign. */
+ string++;
+ return !!strstr (string, "..");
+}
+
+
+/* Check whether BUFFER has characters not valid in an RFC-822
+ address. LENGTH gives the length of BUFFER.
+
+ To cope with OpenPGP we ignore non-ascii characters so that for
+ example umlauts are legal in an email address. An OpenPGP user ID
+ must be utf-8 encoded but there is no strict requirement for
+ RFC-822. Thus to avoid IDNA encoding we put the address verbatim
+ as utf-8 into the user ID under the assumption that mail programs
+ handle IDNA at a lower level and take OpenPGP user IDs as utf-8.
+ Note that we can't do an utf-8 encoding checking here because in
+ keygen.c this function is called with the native encoding and
+ native to utf-8 encoding is only done later. */
+static int
+has_invalid_email_chars (const void *buffer, size_t length)
+{
+ const unsigned char *s = buffer;
+ int at_seen=0;
+ const char *valid_chars=
+ "01234567890_-.abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ";
+
+ for ( ; length && *s; length--, s++ )
+ {
+ if ((*s & 0x80))
+ continue; /* We only care about ASCII. */
+ if (*s == '@')
+ at_seen=1;
+ else if (!at_seen && !(strchr (valid_chars, *s)
+ || strchr ("!#$%&'*+/=?^`{|}~", *s)))
+ return 1;
+ else if (at_seen && !strchr (valid_chars, *s))
+ return 1;
+ }
+ return 0;
+}
+
+
+/* Same as is_valid_mailbox (see below) but operates on non-nul
+ terminated buffer. */
+static int
+is_valid_mailbox_mem (const void *name_arg, size_t namelen)
+{
+ const char *name = name_arg;
+
+ return !( !name
+ || !namelen
+ || has_invalid_email_chars (name, namelen)
+ || mem_count_chr (name, '@', namelen) != 1
+ || *name == '@'
+ || name[namelen-1] == '@'
+ || name[namelen-1] == '.'
+ || my_memstr (name, namelen, ".."));
+}
+
+
+/* Check whether NAME represents a valid mailbox according to
+ RFC822. Returns true if so. */
+int
+_gpgme_is_valid_mailbox (const char *name)
+{
+ return name? is_valid_mailbox_mem (name, strlen (name)) : 0;
+}
+
+
+/* Return the mailbox (local-part@domain) form a standard user id.
+ All plain ASCII characters in the result are converted to
+ lowercase. Caller must free the result. Returns NULL if no valid
+ mailbox was found (or we are out of memory). */
+char *
+_gpgme_mailbox_from_userid (const char *userid)
+{
+ const char *s, *s_end;
+ size_t len;
+ char *result = NULL;
+
+ s = strchr (userid, '<');
+ if (s)
+ {
+ /* Seems to be a standard user id. */
+ s++;
+ s_end = strchr (s, '>');
+ if (s_end && s_end > s)
+ {
+ len = s_end - s;
+ result = malloc (len + 1);
+ if (!result)
+ return NULL; /* Ooops - out of core. */
+ strncpy (result, s, len);
+ result[len] = 0;
+ /* Apply some basic checks on the address. We do not use
+ is_valid_mailbox because those checks are too strict. */
+ if (string_count_chr (result, '@') != 1 /* Need exactly one '@. */
+ || *result == '@' /* local-part missing. */
+ || result[len-1] == '@' /* domain missing. */
+ || result[len-1] == '.' /* ends with a dot. */
+ || string_has_ctrl_or_space (result)
+ || has_dotdot_after_at (result))
+ {
+ free (result);
+ result = NULL;
+ errno = EINVAL;
+ }
+ }
+ else
+ errno = EINVAL;
+ }
+ else if (_gpgme_is_valid_mailbox (userid))
+ {
+ /* The entire user id is a mailbox. Return that one. Note that
+ this fallback method has some restrictions on the valid
+ syntax of the mailbox. However, those who want weird
+ addresses should know about it and use the regular <...>
+ syntax. */
+ result = strdup (userid);
+ }
+ else
+ errno = EINVAL;
+
+ return result? ascii_strlwr (result): NULL;
+}
+
+
+/* /\* Check whether UID is a valid standard user id of the form */
+/* "Heinrich Heine <heinrichh@duesseldorf.de>" */
+/* and return true if this is the case. *\/ */
+/* int */
+/* is_valid_user_id (const char *uid) */
+/* { */
+/* if (!uid || !*uid) */
+/* return 0; */
+
+/* return 1; */
+/* } */
diff --git a/src/mbox-util.h b/src/mbox-util.h
new file mode 100644
index 0000000..3195a4d
--- /dev/null
+++ b/src/mbox-util.h
@@ -0,0 +1,29 @@
+/* mbox-util.h - Defs for mail address helper functions
+ * Copyright (C) 2015 Werner Koch
+ *
+ * This file is part of GnuPG.
+ *
+ * This file is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License as
+ * published by the Free Software Foundation; either version 2.1 of
+ * the License, or (at your option) any later version.
+ *
+ * This file 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 Lesser General Public License
+ * along with this program; if not, see <http://www.gnu.org/licenses/>.
+ */
+#ifndef GNUPG_COMMON_MBOX_UTIL_H
+#define GNUPG_COMMON_MBOX_UTIL_H
+
+/* int has_invalid_email_chars (const void *buffer, size_t length); */
+int _gpgme_is_valid_mailbox (const char *name);
+/* int _gpgme_is_valid_mailbox_mem (const void *buffer, size_t length); */
+char *_gpgme_mailbox_from_userid (const char *userid);
+/* int is_valid_user_id (const char *uid); */
+
+
+#endif /*GNUPG_COMMON_MBOX_UTIL_H*/
diff --git a/src/moc_kdpipeiodevice.cpp b/src/moc_kdpipeiodevice.cpp
deleted file mode 100644
index eac7b23..0000000
--- a/src/moc_kdpipeiodevice.cpp
+++ /dev/null
@@ -1,60 +0,0 @@
-/****************************************************************************
-** Meta object code from reading C++ file 'kdpipeiodevice.h'
-**
-** Created: Mon Aug 27 15:17:18 2007
-** by: The Qt Meta Object Compiler version 59 (Qt 4.3.0)
-**
-** WARNING! All changes made in this file will be lost!
-*****************************************************************************/
-
-#include "kdpipeiodevice.h"
-#if !defined(Q_MOC_OUTPUT_REVISION)
-#error "The header file 'kdpipeiodevice.h' doesn't include <QObject>."
-#elif Q_MOC_OUTPUT_REVISION != 59
-#error "This file was generated using the moc from 4.3.0. It"
-#error "cannot be used with the include files from this version of Qt."
-#error "(The moc has changed too much.)"
-#endif
-
-static const uint qt_meta_data_KDPipeIODevice[] = {
-
- // content:
- 1, // revision
- 0, // classname
- 0, 0, // classinfo
- 0, 0, // methods
- 0, 0, // properties
- 0, 0, // enums/sets
-
- 0 // eod
-};
-
-static const char qt_meta_stringdata_KDPipeIODevice[] = {
- "KDPipeIODevice\0"
-};
-
-const QMetaObject KDPipeIODevice::staticMetaObject = {
- { &QIODevice::staticMetaObject, qt_meta_stringdata_KDPipeIODevice,
- qt_meta_data_KDPipeIODevice, 0 }
-};
-
-const QMetaObject *KDPipeIODevice::metaObject() const
-{
- return &staticMetaObject;
-}
-
-void *KDPipeIODevice::qt_metacast(const char *_clname)
-{
- if (!_clname) return 0;
- if (!strcmp(_clname, qt_meta_stringdata_KDPipeIODevice))
- return static_cast<void*>(const_cast< KDPipeIODevice*>(this));
- return QIODevice::qt_metacast(_clname);
-}
-
-int KDPipeIODevice::qt_metacall(QMetaObject::Call _c, int _id, void **_a)
-{
- _id = QIODevice::qt_metacall(_c, _id, _a);
- if (_id < 0)
- return _id;
- return _id;
-}
diff --git a/src/op-support.c b/src/op-support.c
index 02940ef..9f10cd3 100644
--- a/src/op-support.c
+++ b/src/op-support.c
@@ -33,6 +33,11 @@
#include "util.h"
#include "debug.h"
+#if GPG_ERROR_VERSION_NUMBER < 0x011700 /* 1.23 */
+# define GPG_ERR_SUBKEYS_EXP_OR_REV 217
+#endif
+
+
gpgme_error_t
_gpgme_op_data_lookup (gpgme_ctx_t ctx, ctx_op_data_id_t type, void **hook,
@@ -143,6 +148,12 @@ _gpgme_op_reset (gpgme_ctx_t ctx, int type)
err = 0;
}
+ if (!err && ctx->status_cb && ctx->full_status)
+ {
+ _gpgme_engine_set_status_cb (ctx->engine,
+ ctx->status_cb, ctx->status_cb_value);
+ }
+
if (err)
{
_gpgme_engine_release (ctx->engine);
@@ -190,16 +201,21 @@ _gpgme_op_reset (gpgme_ctx_t ctx, int type)
}
-/* Parse the INV_RECP or INV-SNDR status line in ARGS and return the
- result in KEY. */
+/* Parse the INV_RECP or INV_SNDR status line in ARGS and return the
+ result in KEY. If KC_FPR (from the KEY_CONSIDERED status line) is
+ not NULL take the KC_FLAGS in account. */
gpgme_error_t
-_gpgme_parse_inv_recp (char *args, gpgme_invalid_key_t *key)
+_gpgme_parse_inv_recp (char *args, int for_signing,
+ const char *kc_fpr, unsigned int kc_flags,
+ gpgme_invalid_key_t *key)
{
gpgme_invalid_key_t inv_key;
char *tail;
long int reason;
- inv_key = malloc (sizeof (*inv_key));
+ (void)for_signing;
+
+ inv_key = calloc (1, sizeof (*inv_key));
if (!inv_key)
return gpg_error_from_syserror ();
inv_key->next = NULL;
@@ -214,9 +230,11 @@ _gpgme_parse_inv_recp (char *args, gpgme_invalid_key_t *key)
switch (reason)
{
- default:
case 0:
- inv_key->reason = gpg_error (GPG_ERR_GENERAL);
+ if (kc_fpr && (kc_flags & 2))
+ inv_key->reason = gpg_error (GPG_ERR_SUBKEYS_EXP_OR_REV);
+ else
+ inv_key->reason = gpg_error (GPG_ERR_GENERAL);
break;
case 1:
@@ -274,6 +292,10 @@ _gpgme_parse_inv_recp (char *args, gpgme_invalid_key_t *key)
case 14:
inv_key->reason = gpg_error (GPG_ERR_INV_USER_ID);
break;
+
+ default:
+ inv_key->reason = gpg_error (GPG_ERR_GENERAL);
+ break;
}
while (*tail && *tail == ' ')
@@ -287,14 +309,49 @@ _gpgme_parse_inv_recp (char *args, gpgme_invalid_key_t *key)
return gpg_error_from_syserror ();
}
}
- else
- inv_key->fpr = NULL;
*key = inv_key;
return 0;
}
+
+/* Parse a KEY_CONSIDERED status line in ARGS and store the
+ * fingerprint and the flags at R_FPR and R_FLAGS. The caller must
+ * free the value at R_FPR on success. */
+gpgme_error_t
+_gpgme_parse_key_considered (const char *args,
+ char **r_fpr, unsigned int *r_flags)
+{
+ char *pend;
+ size_t n;
+
+ *r_fpr = NULL;
+
+ pend = strchr (args, ' ');
+ if (!pend || pend == args)
+ return trace_gpg_error (GPG_ERR_INV_ENGINE); /* Bogus status line. */
+ n = pend - args;
+ *r_fpr = malloc (n + 1);
+ if (!*r_fpr)
+ return gpg_error_from_syserror ();
+ memcpy (*r_fpr, args, n);
+ (*r_fpr)[n] = 0;
+ args = pend + 1;
+
+ gpg_err_set_errno (0);
+ *r_flags = strtoul (args, &pend, 0);
+ if (errno || args == pend || (*pend && *pend != ' '))
+ {
+ free (*r_fpr);
+ *r_fpr = NULL;
+ return trace_gpg_error (GPG_ERR_INV_ENGINE);
+ }
+
+ return 0;
+}
+
+
/* Parse the PLAINTEXT status line in ARGS and return the result in
FILENAMEP. */
gpgme_error_t
diff --git a/src/ops.h b/src/ops.h
index 3662d57..97b1019 100644
--- a/src/ops.h
+++ b/src/ops.h
@@ -57,9 +57,15 @@ gpgme_error_t _gpgme_op_data_lookup (gpgme_ctx_t ctx, ctx_op_data_id_t type,
/* Prepare a new operation on CTX. */
gpgme_error_t _gpgme_op_reset (gpgme_ctx_t ctx, int synchronous);
+/* Parse the KEY_CONSIDERED status line. */
+gpgme_error_t _gpgme_parse_key_considered (const char *args,
+ char **r_fpr, unsigned int *r_flags);
+
/* Parse the INV_RECP status line in ARGS and return the result in
KEY. */
-gpgme_error_t _gpgme_parse_inv_recp (char *args, gpgme_invalid_key_t *key);
+gpgme_error_t _gpgme_parse_inv_recp (char *args, int for_signing,
+ const char *kc_fpr, unsigned int kc_flags,
+ gpgme_invalid_key_t *key);
/* Parse the PLAINTEXT status line in ARGS and return the result in
FILENAMEP. */
@@ -132,9 +138,11 @@ gpgme_error_t _gpgme_progress_status_handler (void *priv,
gpgme_error_t _gpgme_key_new (gpgme_key_t *r_key);
gpgme_error_t _gpgme_key_add_subkey (gpgme_key_t key,
gpgme_subkey_t *r_subkey);
-gpgme_error_t _gpgme_key_append_name (gpgme_key_t key, const char *src, int convert);
+gpgme_error_t _gpgme_key_append_name (gpgme_key_t key,
+ const char *src, int convert);
gpgme_key_sig_t _gpgme_key_add_sig (gpgme_key_t key, char *src);
+
/* From keylist.c. */
void _gpgme_op_keylist_event_cb (void *data, gpgme_event_io_t type,
diff --git a/src/passphrase.c b/src/passphrase.c
index c88e57d..74d235c 100644
--- a/src/passphrase.c
+++ b/src/passphrase.c
@@ -118,9 +118,8 @@ _gpgme_passphrase_status_handler (void *priv, gpgme_status_code_t code,
case GPGME_STATUS_ERROR:
/* We abuse this status handler to forward ERROR status codes to
- the caller. This should better be done in a generic handler,
- but for now this is sufficient. */
- if (ctx->status_cb)
+ the caller. */
+ if (ctx->status_cb && !ctx->full_status)
{
err = ctx->status_cb (ctx->status_cb_value, "ERROR", args);
if (err)
@@ -130,9 +129,8 @@ _gpgme_passphrase_status_handler (void *priv, gpgme_status_code_t code,
case GPGME_STATUS_FAILURE:
/* We abuse this status handler to forward FAILURE status codes
- to the caller. This should better be done in a generic
- handler, but for now this is sufficient. */
- if (ctx->status_cb)
+ to the caller. */
+ if (ctx->status_cb && !ctx->full_status)
{
err = ctx->status_cb (ctx->status_cb_value, "FAILURE", args);
if (err)
@@ -173,6 +171,7 @@ _gpgme_passphrase_command_handler (void *priv, gpgme_status_code_t code,
if (processed)
*processed = 1;
+ /* Fake a status line to to convey the MAXLEN info. */
if (ctx->status_cb && opd->maxlen)
err = ctx->status_cb (ctx->status_cb_value, "INQUIRE_MAXLEN",
opd->maxlen);
diff --git a/src/passwd.c b/src/passwd.c
index ff30df0..c34f357 100644
--- a/src/passwd.c
+++ b/src/passwd.c
@@ -148,6 +148,14 @@ passwd_start (gpgme_ctx_t ctx, int synchronous, gpgme_key_t key,
_gpgme_engine_set_status_handler (ctx->engine, passwd_status_handler, ctx);
+ if (ctx->passphrase_cb)
+ {
+ err = _gpgme_engine_set_command_handler
+ (ctx->engine, _gpgme_passphrase_command_handler, ctx, NULL);
+ if (err)
+ return err;
+ }
+
return _gpgme_engine_op_passwd (ctx->engine, key, flags);
}
diff --git a/src/posix-io.c b/src/posix-io.c
index ac823fc..c0b2f4f 100644
--- a/src/posix-io.c
+++ b/src/posix-io.c
@@ -23,6 +23,9 @@
#endif
#include <stdio.h>
#include <stdlib.h>
+#ifdef HAVE_STDINT_H
+# include <stdint.h>
+#endif
#include <string.h>
#include <assert.h>
#include <errno.h>
@@ -44,6 +47,12 @@
#include <ctype.h>
#include <sys/resource.h>
+#if __linux__
+# include <sys/types.h>
+# include <dirent.h>
+#endif /*__linux__ */
+
+
#include "util.h"
#include "priv-io.h"
#include "sema.h"
@@ -273,20 +282,54 @@ _gpgme_io_set_nonblocking (int fd)
static long int
get_max_fds (void)
{
- char *source = NULL;
+ const char *source = NULL;
long int fds = -1;
int rc;
-#ifdef RLIMIT_NOFILE
+ /* Under Linux we can figure out the highest used file descriptor by
+ * reading /proc/self/fd. This is in the common cases much fast than
+ * for example doing 4096 close calls where almost all of them will
+ * fail. */
+#ifdef __linux__
{
- struct rlimit rl;
- rc = getrlimit (RLIMIT_NOFILE, &rl);
- if (rc == 0)
+ DIR *dir = NULL;
+ struct dirent *dir_entry;
+ const char *s;
+ int x;
+
+ dir = opendir ("/proc/self/fd");
+ if (dir)
{
- source = "RLIMIT_NOFILE";
- fds = rl.rlim_max;
+ while ((dir_entry = readdir (dir)))
+ {
+ s = dir_entry->d_name;
+ if ( *s < '0' || *s > '9')
+ continue;
+ x = atoi (s);
+ if (x > fds)
+ fds = x;
+ }
+ closedir (dir);
}
- }
+ if (fds != -1)
+ {
+ fds++;
+ source = "/proc";
+ }
+ }
+#endif /* __linux__ */
+
+#ifdef RLIMIT_NOFILE
+ if (fds == -1)
+ {
+ struct rlimit rl;
+ rc = getrlimit (RLIMIT_NOFILE, &rl);
+ if (rc == 0)
+ {
+ source = "RLIMIT_NOFILE";
+ fds = rl.rlim_max;
+ }
+ }
#endif
#ifdef RLIMIT_OFILE
if (fds == -1)
@@ -331,6 +374,16 @@ get_max_fds (void)
fds = 1024;
}
+ /* AIX returns INT32_MAX instead of a proper value. We assume that
+ * this is always an error and use a more reasonable limit. */
+#ifdef INT32_MAX
+ if (fds == INT32_MAX)
+ {
+ source = "aix-fix";
+ fds = 1024;
+ }
+#endif
+
TRACE2 (DEBUG_SYSIO, "gpgme:max_fds", 0, "max fds=%i (%s)", fds, source);
return fds;
}
@@ -551,6 +604,12 @@ _gpgme_io_select (struct io_select_fd_s *fds, size_t nfds, int nonblock)
continue;
if (fds[i].for_read)
{
+ if (fds[i].fd >= FD_SETSIZE)
+ {
+ TRACE_END (dbg_help, " -BAD- ]");
+ gpg_err_set_errno (EBADF);
+ return TRACE_SYSRES (-1);
+ }
assert (!FD_ISSET (fds[i].fd, &readfds));
FD_SET (fds[i].fd, &readfds);
if (fds[i].fd > max_fd)
@@ -560,6 +619,12 @@ _gpgme_io_select (struct io_select_fd_s *fds, size_t nfds, int nonblock)
}
else if (fds[i].for_write)
{
+ if (fds[i].fd >= FD_SETSIZE)
+ {
+ TRACE_END (dbg_help, " -BAD- ]");
+ gpg_err_set_errno (EBADF);
+ return TRACE_SYSRES (-1);
+ }
assert (!FD_ISSET (fds[i].fd, &writefds));
FD_SET (fds[i].fd, &writefds);
if (fds[i].fd > max_fd)
diff --git a/src/posix-util.c b/src/posix-util.c
index f7e0a17..889c6aa 100644
--- a/src/posix-util.c
+++ b/src/posix-util.c
@@ -71,6 +71,15 @@ _gpgme_set_default_gpgconf_name (const char *name)
}
+/* Dummy function - see w32-util.c for the actual code. */
+int
+_gpgme_set_override_inst_dir (const char *dir)
+{
+ (void)dir;
+ return 0;
+}
+
+
/* Find an executable program PGM along the envvar PATH. */
static char *
walk_path (const char *pgm)
@@ -136,6 +145,8 @@ _gpgme_get_gpgconf_path (void)
int
_gpgme_get_conf_int (const char *key, int *value)
{
+ (void)key;
+ (void)value;
return 0;
}
diff --git a/src/sign.c b/src/sign.c
index 6c9fc03..bfd9ad1 100644
--- a/src/sign.c
+++ b/src/sign.c
@@ -42,6 +42,12 @@ typedef struct
/* The error code from a FAILURE status line or 0. */
gpg_error_t failure_code;
+ /* The fingerprint from the last KEY_CONSIDERED status line. */
+ char *kc_fpr;
+
+ /* The flags from the last KEY_CONSIDERED status line. */
+ unsigned int kc_flags;
+
/* A pointer to the next pointer of the last invalid signer in
the list. This makes appending new invalid signers painless
while preserving the order. */
@@ -86,6 +92,7 @@ release_op_data (void *hook)
}
release_signatures (opd->result.signatures);
+ free (opd->kc_fpr);
}
@@ -316,6 +323,17 @@ _gpgme_sign_status_handler (void *priv, gpgme_status_code_t code, char *args)
opd->last_sig_p = &(*opd->last_sig_p)->next;
break;
+ case GPGME_STATUS_KEY_CONSIDERED:
+ /* This is emitted during gpg's key lookup to give information
+ * about the lookup results. We store the last one so it can be
+ * used in connection with INV_RECP. */
+ free (opd->kc_fpr);
+ opd->kc_fpr = NULL;
+ err = _gpgme_parse_key_considered (args, &opd->kc_fpr, &opd->kc_flags);
+ if (err)
+ return err;
+ break;
+
case GPGME_STATUS_INV_RECP:
if (opd->inv_sgnr_seen && opd->ignore_inv_recp)
break;
@@ -323,11 +341,16 @@ _gpgme_sign_status_handler (void *priv, gpgme_status_code_t code, char *args)
case GPGME_STATUS_INV_SGNR:
if (code == GPGME_STATUS_INV_SGNR)
opd->inv_sgnr_seen = 1;
- err = _gpgme_parse_inv_recp (args, opd->last_signer_p);
+ free (opd->kc_fpr);
+ opd->kc_fpr = NULL;
+ err = _gpgme_parse_inv_recp (args, 1, opd->kc_fpr, opd->kc_flags,
+ opd->last_signer_p);
if (err)
return err;
opd->last_signer_p = &(*opd->last_signer_p)->next;
+ free (opd->kc_fpr);
+ opd->kc_fpr = NULL;
break;
case GPGME_STATUS_FAILURE:
@@ -346,7 +369,7 @@ _gpgme_sign_status_handler (void *priv, gpgme_status_code_t code, char *args)
break;
case GPGME_STATUS_INQUIRE_MAXLEN:
- if (ctx->status_cb)
+ if (ctx->status_cb && !ctx->full_status)
err = ctx->status_cb (ctx->status_cb_value, "INQUIRE_MAXLEN", args);
break;
diff --git a/src/status-table.c b/src/status-table.c
index 6d428d7..c9bf357 100644
--- a/src/status-table.c
+++ b/src/status-table.c
@@ -84,6 +84,7 @@ static struct status_table_s status_table[] =
{ "INQUIRE_MAXLEN", GPGME_STATUS_INQUIRE_MAXLEN },
{ "INV_RECP", GPGME_STATUS_INV_RECP },
{ "INV_SGNR", GPGME_STATUS_INV_SGNR },
+ { "KEY_CONSIDERED", GPGME_STATUS_KEY_CONSIDERED },
{ "KEY_CREATED", GPGME_STATUS_KEY_CREATED },
{ "KEY_NOT_CREATED", GPGME_STATUS_KEY_NOT_CREATED },
{ "KEYEXPIRED", GPGME_STATUS_KEYEXPIRED },
@@ -101,6 +102,7 @@ static struct status_table_s status_table[] =
{ "NO_SGNR", GPGME_STATUS_NO_SGNR },
{ "NODATA", GPGME_STATUS_NODATA },
{ "NOTATION_DATA", GPGME_STATUS_NOTATION_DATA },
+ { "NOTATION_FLAGS", GPGME_STATUS_NOTATION_FLAGS },
{ "NOTATION_NAME", GPGME_STATUS_NOTATION_NAME },
{ "PINENTRY_LAUNCHED", GPGME_STATUS_PINENTRY_LAUNCHED},
{ "PKA_TRUST_BAD", GPGME_STATUS_PKA_TRUST_BAD },
@@ -123,6 +125,9 @@ static struct status_table_s status_table[] =
{ "SIG_SUBPACKET", GPGME_STATUS_SIG_SUBPACKET },
{ "SIGEXPIRED", GPGME_STATUS_SIGEXPIRED },
{ "SUCCESS", GPGME_STATUS_SUCCESS },
+ { "TOFU_STATS", GPGME_STATUS_TOFU_STATS },
+ { "TOFU_STATS_LONG", GPGME_STATUS_TOFU_STATS_LONG },
+ { "TOFU_USER", GPGME_STATUS_TOFU_USER },
{ "TRUNCATED", GPGME_STATUS_TRUNCATED },
{ "TRUST_FULLY", GPGME_STATUS_TRUST_FULLY },
{ "TRUST_MARGINAL", GPGME_STATUS_TRUST_MARGINAL },
@@ -164,3 +169,15 @@ _gpgme_parse_status (const char *name)
sizeof t, status_cmp);
return r ? r->code : -1;
}
+
+
+const char *
+_gpgme_status_to_string (gpgme_status_code_t code)
+{
+ int i;
+
+ for (i=0; i < DIM(status_table); i++)
+ if (status_table[i].code == code)
+ return status_table[i].name? status_table[i].name : "";
+ return "status_code_lost";
+}
diff --git a/src/sys-util.h b/src/sys-util.h
index 589634b..541c557 100644
--- a/src/sys-util.h
+++ b/src/sys-util.h
@@ -23,6 +23,7 @@
/*-- {posix,w32}-util.c --*/
int _gpgme_set_default_gpg_name (const char *name);
int _gpgme_set_default_gpgconf_name (const char *name);
+int _gpgme_set_override_inst_dir (const char *dir);
char *_gpgme_get_gpg_path (void);
char *_gpgme_get_gpgconf_path (void);
diff --git a/src/tofupolicy.c b/src/tofupolicy.c
new file mode 100644
index 0000000..799779e
--- /dev/null
+++ b/src/tofupolicy.c
@@ -0,0 +1,184 @@
+/* tofupolicy.c - Tofu policy helpers.
+ * Copyright (C) 2016 g10 Code GmbH
+ *
+ * This file is part of GPGME.
+ *
+ * GPGME is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU Lesser General Public License as
+ * published by the Free Software Foundation; either version 2.1 of
+ * the License, or (at your option) any later version.
+ *
+ * GPGME is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this program; if not, see <http://www.gnu.org/licenses/>.
+ */
+
+#if HAVE_CONFIG_H
+#include <config.h>
+#endif
+#include <stdlib.h>
+
+#include "gpgme.h"
+#include "debug.h"
+#include "context.h"
+#include "ops.h"
+
+
+typedef struct
+{
+ /* The error code from a FAILURE status line or 0. */
+ gpg_error_t failure_code;
+
+ /* The error code from an ERROR status line or 0. */
+ gpg_error_t error_code;
+
+} *op_data_t;
+
+
+
+/* Parse an error status line. Return the error location and the
+ error code. The function may modify ARGS. */
+static char *
+parse_error (char *args, gpg_error_t *r_err)
+{
+ char *where = strchr (args, ' ');
+ char *which;
+
+ if (where)
+ {
+ *where = '\0';
+ which = where + 1;
+
+ where = strchr (which, ' ');
+ if (where)
+ *where = '\0';
+
+ where = args;
+ }
+ else
+ {
+ *r_err = trace_gpg_error (GPG_ERR_INV_ENGINE);
+ return NULL;
+ }
+
+ *r_err = atoi (which);
+
+ return where;
+}
+
+
+static gpgme_error_t
+tofu_policy_status_handler (void *priv, gpgme_status_code_t code, char *args)
+{
+ gpgme_ctx_t ctx = (gpgme_ctx_t) priv;
+ gpgme_error_t err;
+ void *hook;
+ op_data_t opd;
+ char *loc;
+
+ err = _gpgme_op_data_lookup (ctx, OPDATA_TOFU_POLICY, &hook, -1, NULL);
+ opd = hook;
+ if (err)
+ return err;
+
+ switch (code)
+ {
+ case GPGME_STATUS_ERROR:
+ loc = parse_error (args, &err);
+ if (!loc)
+ return err;
+ if (!opd->error_code)
+ opd->error_code = err;
+ break;
+
+ case GPGME_STATUS_FAILURE:
+ opd->failure_code = _gpgme_parse_failure (args);
+ break;
+
+ case GPGME_STATUS_EOF:
+ if (opd->error_code)
+ err = opd->error_code;
+ else if (opd->failure_code)
+ err = opd->failure_code;
+ break;
+
+ default:
+ break;
+ }
+
+ return err;
+}
+
+
+/* Set the TOFU policy for KEY to POLICY. */
+static gpgme_error_t
+tofu_policy_start (gpgme_ctx_t ctx, int synchronous,
+ gpgme_key_t key, gpgme_tofu_policy_t policy)
+{
+ gpgme_error_t err;
+ void *hook;
+ op_data_t opd;
+
+ if (ctx->protocol != GPGME_PROTOCOL_OPENPGP)
+ return gpgme_error (GPG_ERR_UNSUPPORTED_PROTOCOL);
+
+ if (!key)
+ return gpg_error (GPG_ERR_INV_VALUE);
+
+ err = _gpgme_op_reset (ctx, synchronous);
+ if (err)
+ return err;
+
+ err = _gpgme_op_data_lookup (ctx, OPDATA_TOFU_POLICY, &hook,
+ sizeof (*opd), NULL);
+ opd = hook;
+ if (err)
+ return err;
+
+ _gpgme_engine_set_status_handler (ctx->engine, tofu_policy_status_handler,
+ ctx);
+
+ return _gpgme_engine_op_tofu_policy (ctx->engine, key, policy);
+}
+
+
+
+/* Set the TOFU policy of KEY to POLCIY. This is the asynchronous
+ * variant. */
+gpgme_error_t
+gpgme_op_tofu_policy_start (gpgme_ctx_t ctx,
+ gpgme_key_t key, gpgme_tofu_policy_t policy)
+{
+ gpg_error_t err;
+ TRACE_BEG2 (DEBUG_CTX, "gpgme_op_tofu_policy_start", ctx,
+ "key=%p, policy=%u", key, (unsigned int)policy);
+
+ if (!ctx)
+ return TRACE_ERR (gpg_error (GPG_ERR_INV_VALUE));
+
+ err = tofu_policy_start (ctx, 0, key, policy);
+ return TRACE_ERR (err);
+}
+
+
+/* This is the synchronous variant of gpgme_op_tofu_policy_start. */
+gpgme_error_t
+gpgme_op_tofu_policy (gpgme_ctx_t ctx,
+ gpgme_key_t key, gpgme_tofu_policy_t policy)
+{
+ gpgme_error_t err;
+ TRACE_BEG2 (DEBUG_CTX, "gpgme_op_tofu_policy", ctx,
+ "key=%p, policy=%u", key, (unsigned int)policy);
+
+ if (!ctx)
+ return TRACE_ERR (gpg_error (GPG_ERR_INV_VALUE));
+
+ err = tofu_policy_start (ctx, 1, key, policy);
+ if (!err)
+ err = _gpgme_wait_one (ctx);
+ return TRACE_ERR (err);
+}
diff --git a/src/trustlist.c b/src/trustlist.c
index d456780..c85ef87 100644
--- a/src/trustlist.c
+++ b/src/trustlist.c
@@ -52,6 +52,9 @@ typedef struct
static gpgme_error_t
trustlist_status_handler (void *priv, gpgme_status_code_t code, char *args)
{
+ (void)priv;
+ (void)code;
+ (void)args;
return 0;
}
diff --git a/src/util.h b/src/util.h
index 365f1d8..88e7750 100644
--- a/src/util.h
+++ b/src/util.h
@@ -45,6 +45,11 @@
#define DIM(v) (sizeof(v)/sizeof((v)[0]))
+#if GPG_ERROR_VERSION_NUMBER < 0x011500 /* 1.21 */
+# define GPG_ERR_FALSE 256
+#endif
+
+
/*-- {posix,w32}-util.c --*/
int _gpgme_get_conf_int (const char *key, int *value);
@@ -124,6 +129,18 @@ gpgme_error_t _gpgme_decode_percent_string (const char *src, char **destp,
gpgme_error_t _gpgme_encode_percent_string (const char *src, char **destp,
size_t len);
+/* Split a string into space delimited fields and remove leading and
+ * trailing spaces from each field. A pointer to the each field is
+ * stored in ARRAY. Stop splitting at ARRAYSIZE fields. The function
+ * modifies STRING. The number of parsed fields is returned. */
+int _gpgme_split_fields (char *string, char **array, int arraysize);
+
+/* Convert the field STRING into an unsigned long value. Check for
+ * trailing garbage. */
+gpgme_error_t _gpgme_strtoul_field (const char *string, unsigned long *result);
+
+/* Convert STRING into an offset value similar to atoi(). */
+gpgme_off_t _gpgme_string_to_off (const char *string);
/* Parse the string TIMESTAMP into a time_t. The string may either be
seconds since Epoch or in the ISO 8601 format like
@@ -138,6 +155,26 @@ gpgme_error_t _gpgme_map_gnupg_error (char *err);
int _gpgme_map_pk_algo (int algo, gpgme_protocol_t protocol);
+/*-- b64dec.c --*/
+
+struct b64state
+{
+ int idx;
+ int quad_count;
+ char *title;
+ unsigned char radbuf[4];
+ int stop_seen:1;
+ int invalid_encoding:1;
+ gpg_error_t lasterr;
+};
+
+gpg_error_t _gpgme_b64dec_start (struct b64state *state, const char *title);
+gpg_error_t _gpgme_b64dec_proc (struct b64state *state,
+ void *buffer, size_t length, size_t *r_nbytes);
+gpg_error_t _gpgme_b64dec_finish (struct b64state *state);
+
+
+
/* Retrieve the environment variable NAME and return a copy of it in a
malloc()'ed buffer in *VALUE. If the environment variable is not
set, return NULL in *VALUE. */
@@ -148,6 +185,7 @@ gpgme_error_t _gpgme_getenv (const char *name, char **value);
/* Convert a status string to a status code. */
void _gpgme_status_init (void);
gpgme_status_code_t _gpgme_parse_status (const char *name);
+const char *_gpgme_status_to_string (gpgme_status_code_t code);
#ifdef HAVE_W32_SYSTEM
diff --git a/src/verify.c b/src/verify.c
index 75914e2..eb1cc10 100644
--- a/src/verify.c
+++ b/src/verify.c
@@ -26,6 +26,7 @@
#include <string.h>
#include <errno.h>
#include <assert.h>
+#include <limits.h>
#include "gpgme.h"
#include "debug.h"
@@ -71,6 +72,8 @@ release_op_data (void *hook)
free (sig->fpr);
if (sig->pka_address)
free (sig->pka_address);
+ if (sig->key)
+ gpgme_key_unref (sig->key);
free (sig);
sig = next;
}
@@ -363,25 +366,10 @@ parse_new_sig (op_data_t opd, gpgme_status_code_t code, char *args,
end++;
/* Parse the return code. */
- if (end[0] && (!end[1] || end[1] == ' '))
- {
- switch (end[0])
- {
- case '4':
- sig->status = gpg_error (GPG_ERR_UNSUPPORTED_ALGORITHM);
- break;
-
- case '9':
- sig->status = gpg_error (GPG_ERR_NO_PUBKEY);
- break;
-
- default:
- sig->status = gpg_error (GPG_ERR_GENERAL);
- }
- }
- else
+ if (!*end)
goto parse_err_sig_fail;
+ sig->status = strtoul (end, NULL, 10);
goto parse_err_sig_ok;
parse_err_sig_fail:
@@ -486,13 +474,14 @@ parse_notation (gpgme_signature_t sig, gpgme_status_code_t code, char *args)
gpgme_error_t err;
gpgme_sig_notation_t *lastp = &sig->notations;
gpgme_sig_notation_t notation = sig->notations;
- char *end = strchr (args, ' ');
-
- if (end)
- *end = '\0';
+ char *p;
if (code == GPGME_STATUS_NOTATION_NAME || code == GPGME_STATUS_POLICY_URL)
{
+ p = strchr (args, ' ');
+ if (p)
+ *p = '\0';
+
/* FIXME: We could keep a pointer to the last notation in the list. */
while (notation && notation->value)
{
@@ -520,9 +509,8 @@ parse_notation (gpgme_signature_t sig, gpgme_status_code_t code, char *args)
notation->name_len = strlen (notation->name);
- /* FIXME: For now we fake the human-readable flag. The
- critical flag can not be reported as it is not
- provided. */
+ /* Set default flags for use with older gpg versions which
+ * do not emit a NOTATIONS_FLAG line. */
notation->flags = GPGME_SIG_NOTATION_HUMAN_READABLE;
notation->human_readable = 1;
}
@@ -541,6 +529,37 @@ parse_notation (gpgme_signature_t sig, gpgme_status_code_t code, char *args)
}
*lastp = notation;
}
+ else if (code == GPGME_STATUS_NOTATION_FLAGS)
+ {
+ char *field[2];
+
+ while (notation && notation->next)
+ {
+ lastp = &notation->next;
+ notation = notation->next;
+ }
+
+ if (!notation || !notation->name)
+ { /* There are notation flags without a previous notation name.
+ * The crypto backend misbehaves. */
+ return trace_gpg_error (GPG_ERR_INV_ENGINE);
+ }
+ if (_gpgme_split_fields (args, field, DIM (field)) < 2)
+ { /* Required args missing. */
+ return trace_gpg_error (GPG_ERR_INV_ENGINE);
+ }
+ notation->flags = 0;
+ if (atoi (field[0]))
+ {
+ notation->flags |= GPGME_SIG_NOTATION_CRITICAL;
+ notation->critical = 1;
+ }
+ if (atoi (field[1]))
+ {
+ notation->flags |= GPGME_SIG_NOTATION_HUMAN_READABLE;
+ notation->human_readable = 1;
+ }
+ }
else if (code == GPGME_STATUS_NOTATION_DATA)
{
int len = strlen (args) + 1;
@@ -635,6 +654,213 @@ parse_trust (gpgme_signature_t sig, gpgme_status_code_t code, char *args)
}
+/* Parse a TOFU_USER line and put the info into SIG. */
+static gpgme_error_t
+parse_tofu_user (gpgme_signature_t sig, char *args, gpgme_protocol_t protocol)
+{
+ gpg_error_t err;
+ char *tail;
+ gpgme_user_id_t uid;
+ gpgme_tofu_info_t ti;
+ char *fpr = NULL;
+ char *address = NULL;
+
+ tail = strchr (args, ' ');
+ if (!tail || tail == args)
+ {
+ err = trace_gpg_error (GPG_ERR_INV_ENGINE); /* No fingerprint. */
+ goto leave;
+ }
+ *tail++ = 0;
+
+ fpr = strdup (args);
+ if (!fpr)
+ {
+ err = gpg_error_from_syserror ();
+ goto leave;
+ }
+
+ args = tail;
+ tail = strchr (args, ' ');
+ if (tail == args)
+ {
+ err = trace_gpg_error (GPG_ERR_INV_ENGINE); /* No addr-spec. */
+ goto leave;
+ }
+ if (tail)
+ *tail = 0;
+
+ err = _gpgme_decode_percent_string (args, &address, 0, 0);
+ if (err)
+ goto leave;
+
+ if (!sig->key)
+ {
+ err = _gpgme_key_new (&sig->key);
+ if (err)
+ goto leave;
+ sig->key->fpr = fpr;
+ sig->key->protocol = protocol;
+ fpr = NULL;
+ }
+ else if (!sig->key->fpr)
+ {
+ err = trace_gpg_error (GPG_ERR_INTERNAL);
+ goto leave;
+ }
+ else if (strcmp (sig->key->fpr, fpr))
+ {
+ /* The engine did not emit NEWSIG before a new key. */
+ err = trace_gpg_error (GPG_ERR_INV_ENGINE);
+ goto leave;
+ }
+
+ err = _gpgme_key_append_name (sig->key, address, 0);
+ if (err)
+ goto leave;
+
+ uid = sig->key->_last_uid;
+ assert (uid);
+
+ ti = calloc (1, sizeof *ti);
+ if (!ti)
+ {
+ err = gpg_error_from_syserror ();
+ goto leave;
+ }
+ uid->tofu = ti;
+
+
+ leave:
+ free (fpr);
+ free (address);
+ return err;
+}
+
+
+/* Parse a TOFU_STATS line and store it in the last tofu info of SIG.
+ *
+ * TOFU_STATS <validity> <sign-count> <encr-count> \
+ * [<policy> [<tm1> <tm2> <tm3> <tm4>]]
+ */
+static gpgme_error_t
+parse_tofu_stats (gpgme_signature_t sig, char *args)
+{
+ gpgme_error_t err;
+ gpgme_tofu_info_t ti;
+ char *field[8];
+ int nfields;
+ unsigned long uval;
+
+ if (!sig->key || !sig->key->_last_uid || !(ti = sig->key->_last_uid->tofu))
+ return trace_gpg_error (GPG_ERR_INV_ENGINE); /* No TOFU_USER seen. */
+ if (ti->signfirst || ti->signcount || ti->validity || ti->policy)
+ return trace_gpg_error (GPG_ERR_INV_ENGINE); /* Already set. */
+
+ nfields = _gpgme_split_fields (args, field, DIM (field));
+ if (nfields < 3)
+ return trace_gpg_error (GPG_ERR_INV_ENGINE); /* Required args missing. */
+
+ /* Note that we allow a value of up to 7 which is what we can store
+ * in the ti->validity. */
+ err = _gpgme_strtoul_field (field[0], &uval);
+ if (err || uval > 7)
+ return trace_gpg_error (GPG_ERR_INV_ENGINE);
+ ti->validity = uval;
+
+ /* Parse the sign-count. */
+ err = _gpgme_strtoul_field (field[1], &uval);
+ if (err)
+ return trace_gpg_error (GPG_ERR_INV_ENGINE);
+ if (uval > USHRT_MAX)
+ uval = USHRT_MAX;
+ ti->signcount = uval;
+
+ /* Parse the encr-count. */
+ err = _gpgme_strtoul_field (field[2], &uval);
+ if (err)
+ return trace_gpg_error (GPG_ERR_INV_ENGINE);
+ if (uval > USHRT_MAX)
+ uval = USHRT_MAX;
+ ti->encrcount = uval;
+
+ if (nfields == 3)
+ return 0; /* All mandatory fields parsed. */
+
+ /* Parse the policy. */
+ if (!strcmp (field[3], "none"))
+ ti->policy = GPGME_TOFU_POLICY_NONE;
+ else if (!strcmp (field[3], "auto"))
+ ti->policy = GPGME_TOFU_POLICY_AUTO;
+ else if (!strcmp (field[3], "good"))
+ ti->policy = GPGME_TOFU_POLICY_GOOD;
+ else if (!strcmp (field[3], "bad"))
+ ti->policy = GPGME_TOFU_POLICY_BAD;
+ else if (!strcmp (field[3], "ask"))
+ ti->policy = GPGME_TOFU_POLICY_ASK;
+ else /* "unknown" and invalid policy strings. */
+ ti->policy = GPGME_TOFU_POLICY_UNKNOWN;
+
+ if (nfields == 4)
+ return 0; /* No more optional fields. */
+
+ /* Parse first and last seen timestamps (none or both are required). */
+ if (nfields < 6)
+ return trace_gpg_error (GPG_ERR_INV_ENGINE); /* "tm2" missing. */
+ err = _gpgme_strtoul_field (field[4], &uval);
+ if (err)
+ return trace_gpg_error (GPG_ERR_INV_ENGINE);
+ ti->signfirst = uval;
+ err = _gpgme_strtoul_field (field[5], &uval);
+ if (err)
+ return trace_gpg_error (GPG_ERR_INV_ENGINE);
+ ti->signlast = uval;
+ if (nfields > 7)
+ {
+ /* This condition is only to allow for gpg 2.1.15 - can
+ * eventually be removed. */
+ err = _gpgme_strtoul_field (field[6], &uval);
+ if (err)
+ return trace_gpg_error (GPG_ERR_INV_ENGINE);
+ ti->encrfirst = uval;
+ err = _gpgme_strtoul_field (field[7], &uval);
+ if (err)
+ return trace_gpg_error (GPG_ERR_INV_ENGINE);
+ ti->encrlast = uval;
+ }
+
+ return 0;
+}
+
+
+/* Parse a TOFU_STATS_LONG line and store it in the last tofu info of SIG. */
+static gpgme_error_t
+parse_tofu_stats_long (gpgme_signature_t sig, char *args, int raw)
+{
+ gpgme_error_t err;
+ gpgme_tofu_info_t ti;
+ char *p;
+
+ if (!sig->key || !sig->key->_last_uid || !(ti = sig->key->_last_uid->tofu))
+ return trace_gpg_error (GPG_ERR_INV_ENGINE); /* No TOFU_USER seen. */
+ if (ti->description)
+ return trace_gpg_error (GPG_ERR_INV_ENGINE); /* Already set. */
+
+ err = _gpgme_decode_percent_string (args, &ti->description, 0, 0);
+ if (err)
+ return err;
+
+ /* Remove the non-breaking spaces. */
+ if (!raw)
+ {
+ for (p = ti->description; *p; p++)
+ if (*p == '~')
+ *p = ' ';
+ }
+ return 0;
+}
+
+
/* Parse an error status line and if SET_STATUS is true update the
result status as appropriate. With SET_STATUS being false, only
check for an error. */
@@ -737,6 +963,7 @@ _gpgme_verify_status_handler (void *priv, gpgme_status_code_t code, char *args)
break;
case GPGME_STATUS_NOTATION_NAME:
+ case GPGME_STATUS_NOTATION_FLAGS:
case GPGME_STATUS_NOTATION_DATA:
case GPGME_STATUS_POLICY_URL:
opd->only_newsig_seen = 0;
@@ -766,6 +993,21 @@ _gpgme_verify_status_handler (void *priv, gpgme_status_code_t code, char *args)
sig->pka_address = strdup (args);
break;
+ case GPGME_STATUS_TOFU_USER:
+ opd->only_newsig_seen = 0;
+ return sig ? parse_tofu_user (sig, args, ctx->protocol)
+ /* */ : trace_gpg_error (GPG_ERR_INV_ENGINE);
+
+ case GPGME_STATUS_TOFU_STATS:
+ opd->only_newsig_seen = 0;
+ return sig ? parse_tofu_stats (sig, args)
+ /* */ : trace_gpg_error (GPG_ERR_INV_ENGINE);
+
+ case GPGME_STATUS_TOFU_STATS_LONG:
+ opd->only_newsig_seen = 0;
+ return sig ? parse_tofu_stats_long (sig, args, ctx->raw_description)
+ /* */ : trace_gpg_error (GPG_ERR_INV_ENGINE);
+
case GPGME_STATUS_ERROR:
opd->only_newsig_seen = 0;
/* Some error stati are informational, so we don't return an
@@ -861,8 +1103,6 @@ verify_start (gpgme_ctx_t ctx, int synchronous, gpgme_data_t sig,
if (!sig)
return gpg_error (GPG_ERR_NO_DATA);
- if (!signed_text && !plaintext)
- return gpg_error (GPG_ERR_INV_VALUE);
return _gpgme_engine_op_verify (ctx->engine, sig, signed_text, plaintext);
}
@@ -1009,6 +1249,8 @@ gpgme_get_sig_ulong_attr (gpgme_ctx_t ctx, int idx,
gpgme_verify_result_t result;
gpgme_signature_t sig;
+ (void)whatidx;
+
result = gpgme_op_verify_result (ctx);
sig = result->signatures;
diff --git a/src/version.c b/src/version.c
index 15e5aee..8bc898f 100644
--- a/src/version.c
+++ b/src/version.c
@@ -124,7 +124,7 @@ parse_version_number (const char *str, int *number)
/* Parse the version string STR in the format MAJOR.MINOR.MICRO (for
example, 9.3.2) and return the components in MAJOR, MINOR and MICRO
as integers. The function returns the tail of the string that
- follows the version number. This might be te empty string if there
+ follows the version number. This might be the empty string if there
is nothing following the version number, or a patchlevel. The
function returns NULL if the version string is not valid. */
static const char *
@@ -196,7 +196,7 @@ _gpgme_compare_versions (const char *my_version,
const char *
gpgme_check_version (const char *req_version)
{
- char *result;
+ const char *result;
do_subsystem_inits ();
/* Catch-22: We need to get at least the debug subsystem ready
@@ -307,7 +307,7 @@ _gpgme_get_program_version (const char *const file_name)
char *mark = NULL;
int rp[2];
int nread;
- char *argv[] = {NULL /* file_name */, "--version", 0};
+ char *argv[] = {NULL /* file_name */, (char*)"--version", 0};
struct spawn_fd_item_s cfd[] = { {-1, 1 /* STDOUT_FILENO */, -1, 0},
{-1, -1} };
int status;
diff --git a/src/versioninfo.rc.in b/src/versioninfo.rc.in
index 7f19b30..3ce38f0 100644
--- a/src/versioninfo.rc.in
+++ b/src/versioninfo.rc.in
@@ -39,7 +39,7 @@ BEGIN
VALUE "FileDescription", "GPGME - GnuPG Made Easy\0"
VALUE "FileVersion", "@LIBGPGME_LT_CURRENT@.@LIBGPGME_LT_AGE@.@LIBGPGME_LT_REVISION@.@BUILD_REVISION@\0"
VALUE "InternalName", "gpgme\0"
- VALUE "LegalCopyright", "Copyright © 2001-2015 g10 Code GmbH\0"
+ VALUE "LegalCopyright", "Copyright © 2001-2016 g10 Code GmbH\0"
VALUE "LegalTrademarks", "\0"
VALUE "OriginalFilename", "gpgme.dll\0"
VALUE "PrivateBuild", "\0"
diff --git a/src/vfs-create.c b/src/vfs-create.c
index 48931b9..a01d4da 100644
--- a/src/vfs-create.c
+++ b/src/vfs-create.c
@@ -118,6 +118,8 @@ _gpgme_op_vfs_create (gpgme_ctx_t ctx, gpgme_key_t recp[],
char *container_file_esc = NULL;
int i;
+ (void)flags;
+
/* We want to encourage people to check error values, so not getting
them is discouraged here. Also makes our code easier. */
if (! op_err)
diff --git a/src/vfs-mount.c b/src/vfs-mount.c
index b9b1b4d..5d2f2a9 100644
--- a/src/vfs-mount.c
+++ b/src/vfs-mount.c
@@ -173,6 +173,8 @@ _gpgme_op_vfs_mount (gpgme_ctx_t ctx, const char *container_file,
char *cmd;
char *container_file_esc = NULL;
+ (void)flags;
+
/* We want to encourage people to check error values, so not getting
them is discouraged here. Also makes our code easier. */
if (! op_err)
diff --git a/src/w32-glib-io.c b/src/w32-glib-io.c
index a5af4e6..66dc9bf 100644
--- a/src/w32-glib-io.c
+++ b/src/w32-glib-io.c
@@ -98,7 +98,7 @@ static struct
FD is closed. This, together with the fact that dup'ed file
descriptors are closed before the file descriptors from which
they are dup'ed are closed, ensures that CHAN is always valid,
- and shared among all file descriptors refering to the same
+ and shared among all file descriptors referring to the same
underlying object.
The logic behind this is that there is only one reason for us to
diff --git a/src/w32-io.c b/src/w32-io.c
index 42961e3..3a69541 100644
--- a/src/w32-io.c
+++ b/src/w32-io.c
@@ -50,6 +50,7 @@
#include "sema.h"
#include "priv-io.h"
#include "debug.h"
+#include "sys-util.h"
/* FIXME: Optimize. */
@@ -74,7 +75,7 @@ static struct
that dup'ed file descriptors are closed before the file
descriptors from which they are dup'ed are closed, ensures that
the handle or socket is always valid, and shared among all file
- descriptors refering to the same underlying object.
+ descriptors referring to the same underlying object.
The logic behind this is that there is only one reason for us to
dup file descriptors anyway: to allow simpler book-keeping of
@@ -978,7 +979,7 @@ _gpgme_io_write (int fd, const void *buffer, size_t count)
return TRACE_SYSRES (-1);
}
- /* If no error occured, the number of bytes in the buffer must be
+ /* If no error occurred, the number of bytes in the buffer must be
zero. */
assert (!ctx->nbytes);
@@ -1550,6 +1551,7 @@ _gpgme_io_spawn (const char *path, char *const argv[], unsigned int flags,
int debug_me = 0;
int tmp_fd;
char *tmp_name;
+ const char *spawnhelper;
TRACE_BEG1 (DEBUG_SYSIO, "_gpgme_io_spawn", path,
"path=%s", path);
@@ -1603,7 +1605,33 @@ _gpgme_io_spawn (const char *path, char *const argv[], unsigned int flags,
if ((flags & IOSPAWN_FLAG_DETACHED))
cr_flags |= DETACHED_PROCESS;
cr_flags |= GetPriorityClass (GetCurrentProcess ());
- if (!CreateProcessA (_gpgme_get_w32spawn_path (),
+ spawnhelper = _gpgme_get_w32spawn_path ();
+ if (!spawnhelper)
+ {
+ /* This is a common mistake for new users of gpgme not to include
+ gpgme-w32spawn.exe with their binary. So we want to make
+ this transparent to developers. If users have somehow messed
+ up their installation this should also be properly communicated
+ as otherwise calls to gnupg will result in unsupported protocol
+ errors that do not explain a lot. */
+ char *msg;
+ gpgrt_asprintf (&msg, "gpgme-w32spawn.exe was not found in the "
+ "detected installation directory of GpgME"
+ "\n\t\"%s\"\n\n"
+ "Crypto operations will not work.\n\n"
+ "If you see this it indicates a problem "
+ "with your installation.\n"
+ "Please report the problem to your "
+ "distributor of GpgME.\n\n"
+ "Developers Note: The install dir can be "
+ "manually set with: gpgme_set_global_flag",
+ _gpgme_get_inst_dir ());
+ MessageBoxA (NULL, msg, "GpgME not installed correctly", MB_OK);
+ free (msg);
+ gpg_err_set_errno (EIO);
+ return TRACE_SYSRES (-1);
+ }
+ if (!CreateProcessA (spawnhelper,
arg_string,
&sec_attr, /* process security attributes */
&sec_attr, /* thread security attributes */
@@ -1614,7 +1642,8 @@ _gpgme_io_spawn (const char *path, char *const argv[], unsigned int flags,
&si, /* startup information */
&pi)) /* returns process information */
{
- TRACE_LOG1 ("CreateProcess failed: ec=%d", (int) GetLastError ());
+ int lasterr = (int)GetLastError ();
+ TRACE_LOG1 ("CreateProcess failed: ec=%d", lasterr);
free (arg_string);
close (tmp_fd);
DeleteFileA (tmp_name);
diff --git a/src/w32-qt-io.cpp b/src/w32-qt-io.cpp
deleted file mode 100644
index 44655ec..0000000
--- a/src/w32-qt-io.cpp
+++ /dev/null
@@ -1,700 +0,0 @@
-/* w32-qt-io.c - W32 Glib I/O functions
- Copyright (C) 2000 Werner Koch (dd9jn)
- Copyright (C) 2001, 2002, 2004, 2005, 2007 g10 Code GmbH
-
- This file is part of GPGME.
-
- GPGME is free software; you can redistribute it and/or modify it
- under the terms of the GNU Lesser General Public License as
- published by the Free Software Foundation; either version 2.1 of
- the License, or (at your option) any later version.
-
- GPGME is distributed in the hope that it will be useful, but
- WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- Lesser General Public License for more details.
-
- You should have received a copy of the GNU Lesser General Public
- License along with this program; if not, write to the Free Software
- Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
- 02111-1307, USA. */
-
-#ifdef HAVE_CONFIG_H
-#include <config.h>
-#endif
-#include <stdio.h>
-#include <stdlib.h>
-#include <string.h>
-#include <assert.h>
-#include <errno.h>
-#include <fcntl.h>
-#include <unistd.h>
-#include <sys/time.h>
-#include <sys/types.h>
-#include <windows.h>
-#include <io.h>
-
-#include "kdpipeiodevice.h"
-
-extern "C"
-{
-#include "util.h"
-#include "priv-io.h"
-#include "sema.h"
-#include "debug.h"
-}
-
-#ifndef O_BINARY
-#ifdef _O_BINARY
-#define O_BINARY _O_BINARY
-#else
-#define O_BINARY 0
-#endif
-#endif
-
-using _gpgme_::KDPipeIODevice;
-
-
-/* This file is an ugly hack to get GPGME working with Qt on Windows
- targets. On Windows, you can not select() on file descriptors.
-
- The only way to check if there is something to read is to read
- something. This means that GPGME can not let Qt check for data
- without letting Qt also handle the data on Windows targets.
-
- The ugly consequence is that we need to work on QIODevices in
- GPGME, creating a Qt dependency. Also, we need to export an
- interface for the application to get at GPGME's QIODevices. There
- is no good way to abstract all this with callbacks, because the
- whole thing is also interconnected with the creation of pipes and
- child processes.
-
- The following rule applies only to this I/O backend:
-
- * ALL operations must use the user defined event loop. GPGME can
- not anymore provide its own event loop. This is mostly a sanity
- requirement: Although we have in theory all information we need to
- make the GPGME W32 code for select still work, it would be a big
- complication and require changes throughout GPGME.
-
- Eventually, we probably have to bite the bullet and make some
- really nice callback interfaces to let the user control all this at
- a per-context level. */
-
-#define MAX_SLAFD 1024
-
-struct DeviceEntry {
- DeviceEntry() : iodev( 0 ), refCount( 1 ), blocking( true ) {}
- KDPipeIODevice* iodev;
- bool blocking;
- mutable int refCount;
- void ref() const { ++refCount; }
- int unref() const { assert( refCount > 0 ); return --refCount; }
-};
-
-DeviceEntry* iodevice_table[MAX_SLAFD];
-
-
-static KDPipeIODevice *
-find_channel (int fd, int create)
-{
- assert( fd < MAX_SLAFD );
- if (fd < 0 || fd >= MAX_SLAFD)
- return NULL;
-
- if (create && !iodevice_table[fd])
- {
- DeviceEntry* entry = new DeviceEntry;
- entry->iodev = new KDPipeIODevice
- (fd, QIODevice::ReadWrite|QIODevice::Unbuffered);
- iodevice_table[fd] = entry;
- }
- return iodevice_table[fd] ? iodevice_table[fd]->iodev : 0;
-}
-
-/* Write the printable version of FD to the buffer BUF of length
- BUFLEN. The printable version is the representation on the command
- line that the child process expects. */
-int
-_gpgme_io_fd2str (char *buf, int buflen, int fd)
-{
- return snprintf (buf, buflen, "%d", (long)_get_osfhandle( fd ) );
-}
-
-
-void
-_gpgme_io_subsystem_init (void)
-{
-}
-
-
-static struct
-{
- _gpgme_close_notify_handler_t handler;
- void *value;
-} notify_table[MAX_SLAFD];
-
-
-int
-_gpgme_io_read (int fd, void *buffer, size_t count)
-{
- int saved_errno = 0;
- qint64 nread;
- KDPipeIODevice *chan;
- TRACE_BEG2 (DEBUG_SYSIO, "_gpgme_io_read", fd,
- "buffer=%p, count=%u", buffer, count);
-
- chan = find_channel (fd, 0);
- if (!chan)
- {
- TRACE_LOG ("no channel registered");
- errno = EINVAL;
- return TRACE_SYSRES (-1);
- }
- TRACE_LOG1 ("channel %p", chan);
- if ( iodevice_table[fd] && !iodevice_table[fd]->blocking && chan->readWouldBlock() ) {
- errno = EAGAIN;
- return TRACE_SYSRES( -1 );
- }
-
- nread = chan->read ((char *) buffer, count);
- if (nread < 0)
- {
- TRACE_LOG1 ("err %s", qPrintable (chan->errorString ()));
- saved_errno = EIO;
- nread = -1;
- }
-
- TRACE_LOGBUF ((char *) buffer, nread);
-
- errno = saved_errno;
- return TRACE_SYSRES (nread);
-}
-
-
-int
-_gpgme_io_write (int fd, const void *buffer, size_t count)
-{
- qint64 nwritten;
- KDPipeIODevice *chan;
- TRACE_BEG2 (DEBUG_SYSIO, "_gpgme_io_write", fd,
- "buffer=%p, count=%u", buffer, count);
- TRACE_LOGBUF ((char *) buffer, count);
-
- chan = find_channel (fd, 0);
- if (!chan)
- {
- TRACE_LOG ("fd %d: no channel registered");
- errno = EINVAL;
- return -1;
- }
-
- if ( iodevice_table[fd] && !iodevice_table[fd]->blocking && chan->writeWouldBlock() )
- {
- errno = EAGAIN;
- return TRACE_SYSRES( -1 );
- }
- nwritten = chan->write ((char *) buffer, count);
-
- if (nwritten < 0)
- {
- nwritten = -1;
- errno = EIO;
- return TRACE_SYSRES(-1);
- }
- errno = 0;
- return TRACE_SYSRES (nwritten);
-}
-
-
-int
-_gpgme_io_pipe (int filedes[2], int inherit_idx)
-{
- KDPipeIODevice *chan;
- TRACE_BEG2 (DEBUG_SYSIO, "_gpgme_io_pipe", filedes,
- "inherit_idx=%i (GPGME uses it for %s)",
- inherit_idx, inherit_idx ? "reading" : "writing");
-
-#define PIPEBUF_SIZE 4096
- if (_pipe (filedes, PIPEBUF_SIZE, O_NOINHERIT | O_BINARY) == -1)
- return TRACE_SYSRES (-1);
-
- /* Make one end inheritable. */
- if (inherit_idx == 0)
- {
- int new_read;
-
- new_read = _dup (filedes[0]);
- _close (filedes[0]);
- filedes[0] = new_read;
-
- if (new_read < 0)
- {
- _close (filedes[1]);
- return TRACE_SYSRES (-1);
- }
- }
- else if (inherit_idx == 1)
- {
- int new_write;
-
- new_write = _dup (filedes[1]);
- _close (filedes[1]);
- filedes[1] = new_write;
-
- if (new_write < 0)
- {
- _close (filedes[0]);
- return TRACE_SYSRES (-1);
- }
- }
-
- /* Now we have a pipe with the right end inheritable. The other end
- should have a giochannel. */
-
- chan = find_channel (filedes[1 - inherit_idx], 1);
-
- if (!chan)
- {
- int saved_errno = errno;
- _close (filedes[0]);
- _close (filedes[1]);
- errno = saved_errno;
- return TRACE_SYSRES (-1);
- }
-
- return TRACE_SUC5 ("read=0x%x/%p, write=0x%x/%p, channel=%p",
- filedes[0], (HANDLE) _get_osfhandle (filedes[0]),
- filedes[1], (HANDLE) _get_osfhandle (filedes[1]),
- chan);
-}
-
-int
-_gpgme_io_close (int fd)
-{
- KDPipeIODevice *chan;
- TRACE_BEG (DEBUG_SYSIO, "_gpgme_io_close", fd);
-
- if (fd < 0 || fd >= MAX_SLAFD)
- {
- errno = EBADF;
- return TRACE_SYSRES (-1);
- }
-
- /* First call the notify handler. */
- if (notify_table[fd].handler)
- {
- notify_table[fd].handler (fd, notify_table[fd].value);
- notify_table[fd].handler = NULL;
- notify_table[fd].value = NULL;
- }
-
- /* Then do the close. */
-
- DeviceEntry* const entry = iodevice_table[fd];
- if ( entry ) {
- if ( entry->unref() == 0 ) {
- entry->iodev->close();
- delete entry->iodev;
- delete entry;
- iodevice_table[fd] = 0;
- }
- } else {
- _close( fd );
- }
-
-
-
- return 0;
-}
-
-
-int
-_gpgme_io_set_close_notify (int fd, _gpgme_close_notify_handler_t handler,
- void *value)
-{
- TRACE_BEG2 (DEBUG_SYSIO, "_gpgme_io_set_close_notify", fd,
- "close_handler=%p/%p", handler, value);
-
- assert (fd != -1);
-
- if (fd < 0 || fd >= (int) DIM (notify_table))
- {
- errno = EINVAL;
- return TRACE_SYSRES (-1);
- }
- notify_table[fd].handler = handler;
- notify_table[fd].value = value;
- return TRACE_SYSRES (0);
-}
-
-
-int
-_gpgme_io_set_nonblocking (int fd)
-{
- DeviceEntry* const entry = iodevice_table[fd];
- assert( entry );
- entry->blocking = false;
- TRACE_BEG (DEBUG_SYSIO, "_gpgme_io_set_nonblocking", fd);
- return TRACE_SYSRES (0);
-}
-
-
-static char *
-build_commandline (char **argv)
-{
- int i;
- int n = 0;
- char *buf;
- char *p;
-
- /* We have to quote some things because under Windows the program
- parses the commandline and does some unquoting. We enclose the
- whole argument in double-quotes, and escape literal double-quotes
- as well as backslashes with a backslash. We end up with a
- trailing space at the end of the line, but that is harmless. */
- for (i = 0; argv[i]; i++)
- {
- p = argv[i];
- /* The leading double-quote. */
- n++;
- while (*p)
- {
- /* An extra one for each literal that must be escaped. */
- if (*p == '\\' || *p == '"')
- n++;
- n++;
- p++;
- }
- /* The trailing double-quote and the delimiter. */
- n += 2;
- }
- /* And a trailing zero. */
- n++;
-
- buf = p = (char *) malloc (n);
- if (!buf)
- return NULL;
- for (i = 0; argv[i]; i++)
- {
- char *argvp = argv[i];
-
- *(p++) = '"';
- while (*argvp)
- {
- if (*argvp == '\\' || *argvp == '"')
- *(p++) = '\\';
- *(p++) = *(argvp++);
- }
- *(p++) = '"';
- *(p++) = ' ';
- }
- *(p++) = 0;
-
- return buf;
-}
-
-
-int
-_gpgme_io_spawn (const char *path, char * const argv[], unsigned int flags,
- struct spawn_fd_item_s *fd_list,
- void (*atfork) (void *opaque, int reserved),
- void *atforkvalue, pid_t *r_pid)
-{
- SECURITY_ATTRIBUTES sec_attr;
- PROCESS_INFORMATION pi =
- {
- NULL, /* returns process handle */
- 0, /* returns primary thread handle */
- 0, /* returns pid */
- 0 /* returns tid */
- };
- STARTUPINFO si;
- int cr_flags = CREATE_DEFAULT_ERROR_MODE
- | GetPriorityClass (GetCurrentProcess ());
- int i;
- char **args;
- char *arg_string;
- /* FIXME. */
- int debug_me = 0;
- int tmp_fd;
- char *tmp_name;
-
- TRACE_BEG1 (DEBUG_SYSIO, "_gpgme_io_spawn", path,
- "path=%s", path);
- i = 0;
- while (argv[i])
- {
- TRACE_LOG2 ("argv[%2i] = %s", i, argv[i]);
- i++;
- }
-
- /* We do not inherit any handles by default, and just insert those
- handles we want the child to have afterwards. But some handle
- values occur on the command line, and we need to move
- stdin/out/err to the right location. So we use a wrapper program
- which gets the information from a temporary file. */
- if (_gpgme_mkstemp (&tmp_fd, &tmp_name) < 0)
- {
- TRACE_LOG1 ("_gpgme_mkstemp failed: %s", strerror (errno));
- return TRACE_SYSRES (-1);
- }
- TRACE_LOG1 ("tmp_name = %s", tmp_name);
-
- args = (char **) calloc (2 + i + 1, sizeof (*args));
- args[0] = (char *) _gpgme_get_w32spawn_path ();
- args[1] = tmp_name;
- args[2] = const_cast<char *>(path);
- memcpy (&args[3], &argv[1], i * sizeof (*args));
-
- memset (&sec_attr, 0, sizeof sec_attr);
- sec_attr.nLength = sizeof sec_attr;
- sec_attr.bInheritHandle = FALSE;
-
- arg_string = build_commandline (args);
- free (args);
- if (!arg_string)
- {
- close (tmp_fd);
- DeleteFile (tmp_name);
- return TRACE_SYSRES (-1);
- }
-
- memset (&si, 0, sizeof si);
- si.cb = sizeof (si);
- si.dwFlags = STARTF_USESTDHANDLES | STARTF_USESHOWWINDOW;
- si.wShowWindow = debug_me ? SW_SHOW : SW_HIDE;
- si.hStdInput = INVALID_HANDLE_VALUE;
- si.hStdOutput = INVALID_HANDLE_VALUE;
- si.hStdError = INVALID_HANDLE_VALUE;
-
- cr_flags |= CREATE_SUSPENDED;
- if ((flags & IOSPAWN_FLAG_DETACHED))
- cr_flags |= DETACHED_PROCESS;
- if (!CreateProcessA (_gpgme_get_w32spawn_path (),
- arg_string,
- &sec_attr, /* process security attributes */
- &sec_attr, /* thread security attributes */
- FALSE, /* inherit handles */
- cr_flags, /* creation flags */
- NULL, /* environment */
- NULL, /* use current drive/directory */
- &si, /* startup information */
- &pi)) /* returns process information */
- {
- TRACE_LOG1 ("CreateProcess failed: ec=%d", (int) GetLastError ());
- free (arg_string);
- close (tmp_fd);
- DeleteFile (tmp_name);
-
- /* FIXME: Should translate the error code. */
- errno = EIO;
- return TRACE_SYSRES (-1);
- }
-
- free (arg_string);
-
- if (flags & IOSPAWN_FLAG_ALLOW_SET_FG)
- _gpgme_allow_set_foreground_window ((pid_t)pi.dwProcessId);
-
- /* Insert the inherited handles. */
- for (i = 0; fd_list[i].fd != -1; i++)
- {
- HANDLE hd;
-
- if (!DuplicateHandle (GetCurrentProcess(),
- (HANDLE) _get_osfhandle (fd_list[i].fd),
- pi.hProcess, &hd, 0, TRUE, DUPLICATE_SAME_ACCESS))
- {
- TRACE_LOG1 ("DuplicateHandle failed: ec=%d", (int) GetLastError ());
- TerminateProcess (pi.hProcess, 0);
- /* Just in case TerminateProcess didn't work, let the
- process fail on its own. */
- ResumeThread (pi.hThread);
- CloseHandle (pi.hThread);
- CloseHandle (pi.hProcess);
-
- close (tmp_fd);
- DeleteFile (tmp_name);
-
- /* FIXME: Should translate the error code. */
- errno = EIO;
- return TRACE_SYSRES (-1);
- }
- /* Return the child name of this handle. */
- fd_list[i].peer_name = (int) hd;
- }
-
- /* Write the handle translation information to the temporary
- file. */
- {
- /* Hold roughly MAX_TRANS quadruplets of 64 bit numbers in hex
- notation: "0xFEDCBA9876543210" with an extra white space after
- every quadruplet. 10*(19*4 + 1) - 1 = 769. This plans ahead
- for a time when a HANDLE is 64 bit. */
-#define BUFFER_MAX 800
- char line[BUFFER_MAX + 1];
- int res;
- int written;
- size_t len;
-
- if ((flags & IOSPAWN_FLAG_ALLOW_SET_FG))
- strcpy (line, "~1 \n");
- else
- strcpy (line, "\n");
- for (i = 0; fd_list[i].fd != -1; i++)
- {
- /* Strip the newline. */
- len = strlen (line) - 1;
-
- /* Format is: Local name, stdin/stdout/stderr, peer name, argv idx. */
- snprintf (&line[len], BUFFER_MAX - len, "0x%x %d 0x%x %d \n",
- fd_list[i].fd, fd_list[i].dup_to,
- fd_list[i].peer_name, fd_list[i].arg_loc);
- /* Rather safe than sorry. */
- line[BUFFER_MAX - 1] = '\n';
- line[BUFFER_MAX] = '\0';
- }
- len = strlen (line);
- written = 0;
- do
- {
- res = write (tmp_fd, &line[written], len - written);
- if (res > 0)
- written += res;
- }
- while (res > 0 || (res < 0 && errno == EAGAIN));
- }
- close (tmp_fd);
- /* The temporary file is deleted by the gpgme-w32spawn process
- (hopefully). */
-
- TRACE_LOG4 ("CreateProcess ready: hProcess=%p, hThread=%p, "
- "dwProcessID=%d, dwThreadId=%d",
- pi.hProcess, pi.hThread,
- (int) pi.dwProcessId, (int) pi.dwThreadId);
-
- if (r_pid)
- *r_pid = (pid_t)pi.dwProcessId;
-
- if (ResumeThread (pi.hThread) < 0)
- TRACE_LOG1 ("ResumeThread failed: ec=%d", (int) GetLastError ());
-
- if (!CloseHandle (pi.hThread))
- TRACE_LOG1 ("CloseHandle of thread failed: ec=%d",
- (int) GetLastError ());
-
- TRACE_LOG1 ("process=%p", pi.hProcess);
-
- /* We don't need to wait for the process. */
- if (!CloseHandle (pi.hProcess))
- TRACE_LOG1 ("CloseHandle of process failed: ec=%d",
- (int) GetLastError ());
-
- for (i = 0; fd_list[i].fd != -1; i++)
- _gpgme_io_close (fd_list[i].fd);
-
- for (i = 0; fd_list[i].fd != -1; i++)
- if (fd_list[i].dup_to == -1)
- TRACE_LOG3 ("fd[%i] = 0x%x -> 0x%x", i, fd_list[i].fd,
- fd_list[i].peer_name);
- else
- TRACE_LOG4 ("fd[%i] = 0x%x -> 0x%x (std%s)", i, fd_list[i].fd,
- fd_list[i].peer_name, (fd_list[i].dup_to == 0) ? "in" :
- ((fd_list[i].dup_to == 1) ? "out" : "err"));
-
- return TRACE_SYSRES (0);
-}
-
-
-/* Select on the list of fds. Returns: -1 = error, 0 = timeout or
- nothing to select, > 0 = number of signaled fds. */
-int
-_gpgme_io_select (struct io_select_fd_s *fds, size_t nfds, int nonblock)
-{
- /* Use a 1s timeout. */
-
- void *dbg_help = NULL;
- TRACE_BEG2 (DEBUG_SYSIO, "_gpgme_io_select", fds,
- "nfds=%u, nonblock=%u", nfds, nonblock);
-
- int count = 0;
-
- TRACE_SEQ (dbg_help, "select on [ ");
- for (int i = 0; i < nfds; i++)
- {
- if (fds[i].fd == -1)
- {
- fds[i].signaled = 0;
- }
- else if (fds[i].for_read )
- {
- KDPipeIODevice * const chan = find_channel (fds[i].fd, 0);
- assert (chan);
- if ( nonblock )
- fds[i].signaled = chan->readWouldBlock() ? 0 : 1;
- else
- fds[i].signaled = chan->waitForReadyRead( 1000 ) ? 1 : 0;
- TRACE_ADD1 (dbg_help, "w0x%x ", fds[i].fd);
- if ( fds[i].signaled )
- count++;
- }
- else if (fds[i].for_write)
- {
- const KDPipeIODevice * const chan = find_channel (fds[i].fd, 0);
- assert (chan);
- fds[i].signaled = nonblock ? ( chan->writeWouldBlock() ? 0 : 1 ) : 1;
- TRACE_ADD1 (dbg_help, "w0x%x ", fds[i].fd);
- if ( fds[i].signaled )
- count++;
- }
- }
- TRACE_END (dbg_help, "]");
-
- return TRACE_SYSRES (count);
-}
-
-
-/* Look up the qiodevice for file descriptor FD. */
-extern "C"
-void *
-gpgme_get_fdptr (int fd)
-{
- return find_channel (fd, 0);
-}
-
-
-/* Obsolete compatibility interface. */
-extern "C"
-void *
-gpgme_get_giochannel (int fd)
-{
- return NULL;
-}
-
-
-int
-_gpgme_io_dup (int fd)
-{
- assert( iodevice_table[fd] );
- iodevice_table[fd]->ref();
- return fd;
-}
-
-
-extern "C"
-int
-_gpgme_io_socket (int domain, int type, int proto)
-{
- errno = EIO;
- return -1;
-}
-
-
-extern "C"
-int
-_gpgme_io_connect (int fd, struct sockaddr *addr, int addrlen)
-{
- errno = EIO;
- return -1;
-}
diff --git a/src/w32-util.c b/src/w32-util.c
index 9aba26f..0086fe3 100644
--- a/src/w32-util.c
+++ b/src/w32-util.c
@@ -85,7 +85,10 @@ static HMODULE my_hmodule;
binaries. The are set only once by gpgme_set_global_flag. */
static char *default_gpg_name;
static char *default_gpgconf_name;
-
+/* If this variable is not NULL the value is assumed to be the
+ installation directory. The variable may only be set once by
+ gpgme_set_global_flag and accessed by _gpgme_get_inst_dir. */
+static char *override_inst_dir;
#ifdef HAVE_ALLOW_SET_FOREGROUND_WINDOW
@@ -347,6 +350,9 @@ _gpgme_get_inst_dir (void)
{
static char *inst_dir;
+ if (override_inst_dir)
+ return override_inst_dir;
+
LOCK (get_path_lock);
if (!inst_dir)
{
@@ -403,8 +409,13 @@ find_program_at_standard_place (const char *name)
char path[MAX_PATH];
char *result = NULL;
- /* See http://wiki.tcl.tk/17492 for details on compatibility. */
- if (SHGetSpecialFolderPathA (NULL, path, CSIDL_PROGRAM_FILES, 0))
+ /* See http://wiki.tcl.tk/17492 for details on compatibility.
+
+ We First try the generic place and then fallback to the x86
+ (i.e. 32 bit) place. This will prefer a 64 bit of the program
+ over a 32 bit version on 64 bit Windows if installed. */
+ if (SHGetSpecialFolderPathA (NULL, path, CSIDL_PROGRAM_FILES, 0)
+ || SHGetSpecialFolderPathA (NULL, path, CSIDL_PROGRAM_FILESX86, 0))
{
result = malloc (strlen (path) + 1 + strlen (name) + 1);
if (result)
@@ -456,6 +467,28 @@ _gpgme_set_default_gpgconf_name (const char *name)
}
+/* Set the override installation directory. This function may only be
+ called by gpgme_set_global_flag. Returns 0 on success. */
+int
+_gpgme_set_override_inst_dir (const char *dir)
+{
+ if (!override_inst_dir)
+ {
+ override_inst_dir = malloc (strlen (dir) + 1);
+ if (override_inst_dir)
+ {
+ strcpy (override_inst_dir, dir);
+ replace_slashes (override_inst_dir);
+ /* Remove a trailing slash. */
+ if (*override_inst_dir
+ && override_inst_dir[strlen (override_inst_dir)-1] == '\\')
+ override_inst_dir[strlen (override_inst_dir)-1] = 0;
+ }
+ }
+ return !override_inst_dir;
+}
+
+
/* Return the full file name of the GPG binary. This function is used
iff gpgconf was not found and thus it can be assumed that gpg2 is
not installed. This function is only called by get_gpgconf_item
@@ -530,15 +563,26 @@ _gpgme_get_gpgconf_path (void)
gpgconf = find_program_at_standard_place (name2);
}
- /* 3. Try to find gpgconf.exe using that ancient registry key. This
- should eventually be removed. */
+ /* 3. Try to find gpgconf.exe using the Windows registry. */
if (!gpgconf)
{
char *dir;
- dir = read_w32_registry_string ("HKEY_LOCAL_MACHINE",
+ dir = read_w32_registry_string (NULL,
"Software\\GNU\\GnuPG",
"Install Directory");
+ if (!dir)
+ {
+ char *tmp = read_w32_registry_string (NULL,
+ "Software\\GnuPG",
+ "Install Directory");
+ if (tmp)
+ {
+ if (gpgrt_asprintf (&dir, "%s\\bin", tmp) == -1)
+ return NULL;
+ free (tmp);
+ }
+ }
if (dir)
{
gpgconf = find_program_in_dir (dir, name);
@@ -614,7 +658,7 @@ static const char letters[] =
does not exist at the time of the call to mkstemp. TMPL is
overwritten with the result. */
static int
-mkstemp (char *tmpl)
+my_mkstemp (char *tmpl)
{
int len;
char *XXXXXX;
@@ -722,7 +766,7 @@ _gpgme_mkstemp (int *fd, char **name)
if (!tmpname)
return -1;
strcpy (stpcpy (tmpname, tmp), "\\gpgme-XXXXXX");
- *fd = mkstemp (tmpname);
+ *fd = my_mkstemp (tmpname);
if (fd < 0)
{
free (tmpname);
diff --git a/src/wait-global.c b/src/wait-global.c
index f03775e..28f3921 100644
--- a/src/wait-global.c
+++ b/src/wait-global.c
@@ -206,7 +206,7 @@ _gpgme_wait_global_event_cb (void *data, gpgme_event_io_t type,
gpgme_error_t err = ctx_active (ctx);
if (err)
- /* An error occured. Close all fds in this context, and
+ /* An error occurred. Close all fds in this context, and
send the error in a done event. */
_gpgme_cancel_with_err (ctx, err, 0);
}
@@ -325,7 +325,7 @@ gpgme_wait_ext (gpgme_ctx_t ctx, gpgme_error_t *status,
err = _gpgme_run_io_cb (&fdt.fds[i], 0, &local_op_err);
if (err || local_op_err)
{
- /* An error occured. Close all fds in this context,
+ /* An error occurred. Close all fds in this context,
and signal it. */
_gpgme_cancel_with_err (ictx, err, local_op_err);
diff --git a/src/wait-private.c b/src/wait-private.c
index 9a43110..12d3180 100644
--- a/src/wait-private.c
+++ b/src/wait-private.c
@@ -89,7 +89,7 @@ _gpgme_wait_on_condition (gpgme_ctx_t ctx, volatile int *cond,
if (nr < 0)
{
- /* An error occured. Close all fds in this context, and
+ /* An error occurred. Close all fds in this context, and
signal it. */
err = gpg_error_from_syserror ();
_gpgme_cancel_with_err (ctx, err, 0);
@@ -116,7 +116,7 @@ _gpgme_wait_on_condition (gpgme_ctx_t ctx, volatile int *cond,
err = _gpgme_run_io_cb (&ctx->fdt.fds[i], 0, &op_err);
if (err)
{
- /* An error occured. Close all fds in this context,
+ /* An error occurred. Close all fds in this context,
and signal it. */
_gpgme_cancel_with_err (ctx, err, 0);
@@ -124,7 +124,7 @@ _gpgme_wait_on_condition (gpgme_ctx_t ctx, volatile int *cond,
}
else if (op_err)
{
- /* An operational error occured. Cancel the current
+ /* An operational error occurred. Cancel the current
operation but not the session, and signal it. */
_gpgme_cancel_with_err (ctx, 0, op_err);
diff --git a/src/wait-user.c b/src/wait-user.c
index ba28761..c7bc80f 100644
--- a/src/wait-user.c
+++ b/src/wait-user.c
@@ -46,6 +46,8 @@ _gpgme_user_io_cb_handler (void *data, int fd)
struct tag *tag = (struct tag *) data;
gpgme_ctx_t ctx;
+ (void)fd;
+
assert (data);
ctx = tag->ctx;
assert (ctx);
diff --git a/tests/Makefile.am b/tests/Makefile.am
index 89e52e8..c71914f 100644
--- a/tests/Makefile.am
+++ b/tests/Makefile.am
@@ -32,7 +32,8 @@ LDADD = ../src/libgpgme.la @GPG_ERROR_LIBS@
noinst_HEADERS = run-support.h
noinst_PROGRAMS = $(TESTS) run-keylist run-export run-import run-sign \
- run-verify
+ run-verify run-encrypt run-identify run-decrypt run-genkey \
+ run-keysign run-tofu
if RUN_GPG_TESTS
diff --git a/tests/Makefile.in b/tests/Makefile.in
index ab2418a..7af2558 100644
--- a/tests/Makefile.in
+++ b/tests/Makefile.in
@@ -101,18 +101,24 @@ host_triplet = @host@
TESTS = t-version$(EXEEXT) t-data$(EXEEXT) t-engine-info$(EXEEXT)
noinst_PROGRAMS = $(am__EXEEXT_1) run-keylist$(EXEEXT) \
run-export$(EXEEXT) run-import$(EXEEXT) run-sign$(EXEEXT) \
- run-verify$(EXEEXT)
+ run-verify$(EXEEXT) run-encrypt$(EXEEXT) run-identify$(EXEEXT) \
+ run-decrypt$(EXEEXT) run-genkey$(EXEEXT) run-keysign$(EXEEXT) \
+ run-tofu$(EXEEXT)
subdir = tests
DIST_COMMON = $(srcdir)/Makefile.in $(srcdir)/Makefile.am \
$(top_srcdir)/build-aux/mkinstalldirs \
$(top_srcdir)/build-aux/depcomp $(noinst_HEADERS)
ACLOCAL_M4 = $(top_srcdir)/aclocal.m4
-am__aclocal_m4_deps = $(top_srcdir)/m4/glib-2.0.m4 \
- $(top_srcdir)/m4/glibc21.m4 $(top_srcdir)/m4/gnupg-ttyname.m4 \
+am__aclocal_m4_deps = $(top_srcdir)/m4/ax_cxx_compile_stdcxx.m4 \
+ $(top_srcdir)/m4/ax_pkg_swig.m4 \
+ $(top_srcdir)/m4/ax_python_devel.m4 \
+ $(top_srcdir)/m4/glib-2.0.m4 $(top_srcdir)/m4/glibc21.m4 \
+ $(top_srcdir)/m4/gnupg-ttyname.m4 \
$(top_srcdir)/m4/gpg-error.m4 $(top_srcdir)/m4/libassuan.m4 \
$(top_srcdir)/m4/libtool.m4 $(top_srcdir)/m4/ltoptions.m4 \
$(top_srcdir)/m4/ltsugar.m4 $(top_srcdir)/m4/ltversion.m4 \
- $(top_srcdir)/m4/lt~obsolete.m4 $(top_srcdir)/acinclude.m4 \
+ $(top_srcdir)/m4/lt~obsolete.m4 $(top_srcdir)/m4/pkg.m4 \
+ $(top_srcdir)/m4/qt.m4 $(top_srcdir)/acinclude.m4 \
$(top_srcdir)/configure.ac
am__configure_deps = $(am__aclocal_m4_deps) $(CONFIGURE_DEPENDENCIES) \
$(ACLOCAL_M4)
@@ -123,14 +129,30 @@ CONFIG_CLEAN_VPATH_FILES =
am__EXEEXT_1 = t-version$(EXEEXT) t-data$(EXEEXT) \
t-engine-info$(EXEEXT)
PROGRAMS = $(noinst_PROGRAMS)
-run_export_SOURCES = run-export.c
-run_export_OBJECTS = run-export.$(OBJEXT)
-run_export_LDADD = $(LDADD)
-run_export_DEPENDENCIES = ../src/libgpgme.la
+run_decrypt_SOURCES = run-decrypt.c
+run_decrypt_OBJECTS = run-decrypt.$(OBJEXT)
+run_decrypt_LDADD = $(LDADD)
+run_decrypt_DEPENDENCIES = ../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 =
+run_encrypt_SOURCES = run-encrypt.c
+run_encrypt_OBJECTS = run-encrypt.$(OBJEXT)
+run_encrypt_LDADD = $(LDADD)
+run_encrypt_DEPENDENCIES = ../src/libgpgme.la
+run_export_SOURCES = run-export.c
+run_export_OBJECTS = run-export.$(OBJEXT)
+run_export_LDADD = $(LDADD)
+run_export_DEPENDENCIES = ../src/libgpgme.la
+run_genkey_SOURCES = run-genkey.c
+run_genkey_OBJECTS = run-genkey.$(OBJEXT)
+run_genkey_LDADD = $(LDADD)
+run_genkey_DEPENDENCIES = ../src/libgpgme.la
+run_identify_SOURCES = run-identify.c
+run_identify_OBJECTS = run-identify.$(OBJEXT)
+run_identify_LDADD = $(LDADD)
+run_identify_DEPENDENCIES = ../src/libgpgme.la
run_import_SOURCES = run-import.c
run_import_OBJECTS = run-import.$(OBJEXT)
run_import_LDADD = $(LDADD)
@@ -139,10 +161,18 @@ run_keylist_SOURCES = run-keylist.c
run_keylist_OBJECTS = run-keylist.$(OBJEXT)
run_keylist_LDADD = $(LDADD)
run_keylist_DEPENDENCIES = ../src/libgpgme.la
+run_keysign_SOURCES = run-keysign.c
+run_keysign_OBJECTS = run-keysign.$(OBJEXT)
+run_keysign_LDADD = $(LDADD)
+run_keysign_DEPENDENCIES = ../src/libgpgme.la
run_sign_SOURCES = run-sign.c
run_sign_OBJECTS = run-sign.$(OBJEXT)
run_sign_LDADD = $(LDADD)
run_sign_DEPENDENCIES = ../src/libgpgme.la
+run_tofu_SOURCES = run-tofu.c
+run_tofu_OBJECTS = run-tofu.$(OBJEXT)
+run_tofu_LDADD = $(LDADD)
+run_tofu_DEPENDENCIES = ../src/libgpgme.la
run_verify_SOURCES = run-verify.c
run_verify_OBJECTS = run-verify.$(OBJEXT)
run_verify_LDADD = $(LDADD)
@@ -193,10 +223,14 @@ 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-export.c run-import.c run-keylist.c run-sign.c \
- run-verify.c t-data.c t-engine-info.c t-version.c
-DIST_SOURCES = run-export.c run-import.c run-keylist.c run-sign.c \
- run-verify.c t-data.c t-engine-info.c t-version.c
+SOURCES = run-decrypt.c run-encrypt.c run-export.c run-genkey.c \
+ run-identify.c run-import.c run-keylist.c run-keysign.c \
+ run-sign.c run-tofu.c run-verify.c t-data.c t-engine-info.c \
+ t-version.c
+DIST_SOURCES = run-decrypt.c run-encrypt.c run-export.c run-genkey.c \
+ run-identify.c run-import.c run-keylist.c run-keysign.c \
+ run-sign.c run-tofu.c run-verify.c t-data.c t-engine-info.c \
+ t-version.c
RECURSIVE_TARGETS = all-recursive check-recursive cscopelist-recursive \
ctags-recursive dvi-recursive html-recursive info-recursive \
install-data-recursive install-dvi-recursive \
@@ -301,6 +335,7 @@ BUILD_REVISION = @BUILD_REVISION@
BUILD_TIMESTAMP = @BUILD_TIMESTAMP@
CC = @CC@
CCDEPMODE = @CCDEPMODE@
+CC_FOR_BUILD = @CC_FOR_BUILD@
CFLAGS = @CFLAGS@
CPP = @CPP@
CPPFLAGS = @CPPFLAGS@
@@ -312,12 +347,14 @@ CYGPATH_W = @CYGPATH_W@
DEFS = @DEFS@
DEPDIR = @DEPDIR@
DLLTOOL = @DLLTOOL@
+DOXYGEN = @DOXYGEN@
DSYMUTIL = @DSYMUTIL@
DUMPBIN = @DUMPBIN@
ECHO_C = @ECHO_C@
ECHO_N = @ECHO_N@
ECHO_T = @ECHO_T@
EGREP = @EGREP@
+ENABLED_LANGUAGES = @ENABLED_LANGUAGES@
EXEEXT = @EXEEXT@
FGREP = @FGREP@
GITLOG_TO_CHANGELOG = @GITLOG_TO_CHANGELOG@
@@ -328,15 +365,23 @@ GLIB_LIBS = @GLIB_LIBS@
GLIB_MKENUMS = @GLIB_MKENUMS@
GOBJECT_QUERY = @GOBJECT_QUERY@
GPGME_CONFIG_API_VERSION = @GPGME_CONFIG_API_VERSION@
+GPGME_CONFIG_AVAIL_LANG = @GPGME_CONFIG_AVAIL_LANG@
GPGME_CONFIG_CFLAGS = @GPGME_CONFIG_CFLAGS@
GPGME_CONFIG_HOST = @GPGME_CONFIG_HOST@
GPGME_CONFIG_LIBS = @GPGME_CONFIG_LIBS@
+GPGME_QTTEST_CFLAGS = @GPGME_QTTEST_CFLAGS@
+GPGME_QTTEST_LIBS = @GPGME_QTTEST_LIBS@
+GPGME_QT_CFLAGS = @GPGME_QT_CFLAGS@
+GPGME_QT_LIBS = @GPGME_QT_LIBS@
GPG_ERROR_CFLAGS = @GPG_ERROR_CFLAGS@
GPG_ERROR_CONFIG = @GPG_ERROR_CONFIG@
GPG_ERROR_LIBS = @GPG_ERROR_LIBS@
GPG_ERROR_MT_CFLAGS = @GPG_ERROR_MT_CFLAGS@
GPG_ERROR_MT_LIBS = @GPG_ERROR_MT_LIBS@
+GRAPHVIZ = @GRAPHVIZ@
GREP = @GREP@
+HAVE_CXX11 = @HAVE_CXX11@
+HAVE_DOT = @HAVE_DOT@
INSTALL = @INSTALL@
INSTALL_DATA = @INSTALL_DATA@
INSTALL_PROGRAM = @INSTALL_PROGRAM@
@@ -347,10 +392,16 @@ LDFLAGS = @LDFLAGS@
LIBASSUAN_CFLAGS = @LIBASSUAN_CFLAGS@
LIBASSUAN_CONFIG = @LIBASSUAN_CONFIG@
LIBASSUAN_LIBS = @LIBASSUAN_LIBS@
+LIBGPGMEPP_LT_AGE = @LIBGPGMEPP_LT_AGE@
+LIBGPGMEPP_LT_CURRENT = @LIBGPGMEPP_LT_CURRENT@
+LIBGPGMEPP_LT_REVISION = @LIBGPGMEPP_LT_REVISION@
LIBGPGME_LT_AGE = @LIBGPGME_LT_AGE@
LIBGPGME_LT_CURRENT = @LIBGPGME_LT_CURRENT@
LIBGPGME_LT_REVISION = @LIBGPGME_LT_REVISION@
LIBOBJS = @LIBOBJS@
+LIBQGPGME_LT_AGE = @LIBQGPGME_LT_AGE@
+LIBQGPGME_LT_CURRENT = @LIBQGPGME_LT_CURRENT@
+LIBQGPGME_LT_REVISION = @LIBQGPGME_LT_REVISION@
LIBS = @LIBS@
LIBTOOL = @LIBTOOL@
LIPO = @LIPO@
@@ -360,6 +411,8 @@ MAINT = @MAINT@
MAKEINFO = @MAKEINFO@
MANIFEST_TOOL = @MANIFEST_TOOL@
MKDIR_P = @MKDIR_P@
+MOC = @MOC@
+MOC2 = @MOC2@
NEED__FILE_OFFSET_BITS = @NEED__FILE_OFFSET_BITS@
NM = @NM@
NMEDIT = @NMEDIT@
@@ -376,14 +429,27 @@ PACKAGE_URL = @PACKAGE_URL@
PACKAGE_VERSION = @PACKAGE_VERSION@
PATH_SEPARATOR = @PATH_SEPARATOR@
PKG_CONFIG = @PKG_CONFIG@
-QT4_CORE_CFLAGS = @QT4_CORE_CFLAGS@
-QT4_CORE_LIBS = @QT4_CORE_LIBS@
+PYTHON = @PYTHON@
+PYTHONS = @PYTHONS@
+PYTHON_CPPFLAGS = @PYTHON_CPPFLAGS@
+PYTHON_EXEC_PREFIX = @PYTHON_EXEC_PREFIX@
+PYTHON_EXTRA_LDFLAGS = @PYTHON_EXTRA_LDFLAGS@
+PYTHON_EXTRA_LIBS = @PYTHON_EXTRA_LIBS@
+PYTHON_LDFLAGS = @PYTHON_LDFLAGS@
+PYTHON_PLATFORM = @PYTHON_PLATFORM@
+PYTHON_PREFIX = @PYTHON_PREFIX@
+PYTHON_SITE_PKG = @PYTHON_SITE_PKG@
+PYTHON_VERSION = @PYTHON_VERSION@
+PYTHON_VERSIONS = @PYTHON_VERSIONS@
+QTCHOOSER = @QTCHOOSER@
RANLIB = @RANLIB@
RC = @RC@
SED = @SED@
SET_MAKE = @SET_MAKE@
SHELL = @SHELL@
STRIP = @STRIP@
+SWIG = @SWIG@
+SWIG_LIB = @SWIG_LIB@
SYSROOT = @SYSROOT@
VERSION = @VERSION@
VERSION_NUMBER = @VERSION_NUMBER@
@@ -432,9 +498,13 @@ mandir = @mandir@
mkdir_p = @mkdir_p@
oldincludedir = @oldincludedir@
pdfdir = @pdfdir@
+pkgpyexecdir = @pkgpyexecdir@
+pkgpythondir = @pkgpythondir@
prefix = @prefix@
program_transform_name = @program_transform_name@
psdir = @psdir@
+pyexecdir = @pyexecdir@
+pythondir = @pythondir@
sbindir = @sbindir@
sharedstatedir = @sharedstatedir@
srcdir = @srcdir@
@@ -498,10 +568,26 @@ clean-noinstPROGRAMS:
echo " rm -f" $$list; \
rm -f $$list
+run-decrypt$(EXEEXT): $(run_decrypt_OBJECTS) $(run_decrypt_DEPENDENCIES) $(EXTRA_run_decrypt_DEPENDENCIES)
+ @rm -f run-decrypt$(EXEEXT)
+ $(AM_V_CCLD)$(LINK) $(run_decrypt_OBJECTS) $(run_decrypt_LDADD) $(LIBS)
+
+run-encrypt$(EXEEXT): $(run_encrypt_OBJECTS) $(run_encrypt_DEPENDENCIES) $(EXTRA_run_encrypt_DEPENDENCIES)
+ @rm -f run-encrypt$(EXEEXT)
+ $(AM_V_CCLD)$(LINK) $(run_encrypt_OBJECTS) $(run_encrypt_LDADD) $(LIBS)
+
run-export$(EXEEXT): $(run_export_OBJECTS) $(run_export_DEPENDENCIES) $(EXTRA_run_export_DEPENDENCIES)
@rm -f run-export$(EXEEXT)
$(AM_V_CCLD)$(LINK) $(run_export_OBJECTS) $(run_export_LDADD) $(LIBS)
+run-genkey$(EXEEXT): $(run_genkey_OBJECTS) $(run_genkey_DEPENDENCIES) $(EXTRA_run_genkey_DEPENDENCIES)
+ @rm -f run-genkey$(EXEEXT)
+ $(AM_V_CCLD)$(LINK) $(run_genkey_OBJECTS) $(run_genkey_LDADD) $(LIBS)
+
+run-identify$(EXEEXT): $(run_identify_OBJECTS) $(run_identify_DEPENDENCIES) $(EXTRA_run_identify_DEPENDENCIES)
+ @rm -f run-identify$(EXEEXT)
+ $(AM_V_CCLD)$(LINK) $(run_identify_OBJECTS) $(run_identify_LDADD) $(LIBS)
+
run-import$(EXEEXT): $(run_import_OBJECTS) $(run_import_DEPENDENCIES) $(EXTRA_run_import_DEPENDENCIES)
@rm -f run-import$(EXEEXT)
$(AM_V_CCLD)$(LINK) $(run_import_OBJECTS) $(run_import_LDADD) $(LIBS)
@@ -510,10 +596,18 @@ run-keylist$(EXEEXT): $(run_keylist_OBJECTS) $(run_keylist_DEPENDENCIES) $(EXTRA
@rm -f run-keylist$(EXEEXT)
$(AM_V_CCLD)$(LINK) $(run_keylist_OBJECTS) $(run_keylist_LDADD) $(LIBS)
+run-keysign$(EXEEXT): $(run_keysign_OBJECTS) $(run_keysign_DEPENDENCIES) $(EXTRA_run_keysign_DEPENDENCIES)
+ @rm -f run-keysign$(EXEEXT)
+ $(AM_V_CCLD)$(LINK) $(run_keysign_OBJECTS) $(run_keysign_LDADD) $(LIBS)
+
run-sign$(EXEEXT): $(run_sign_OBJECTS) $(run_sign_DEPENDENCIES) $(EXTRA_run_sign_DEPENDENCIES)
@rm -f run-sign$(EXEEXT)
$(AM_V_CCLD)$(LINK) $(run_sign_OBJECTS) $(run_sign_LDADD) $(LIBS)
+run-tofu$(EXEEXT): $(run_tofu_OBJECTS) $(run_tofu_DEPENDENCIES) $(EXTRA_run_tofu_DEPENDENCIES)
+ @rm -f run-tofu$(EXEEXT)
+ $(AM_V_CCLD)$(LINK) $(run_tofu_OBJECTS) $(run_tofu_LDADD) $(LIBS)
+
run-verify$(EXEEXT): $(run_verify_OBJECTS) $(run_verify_DEPENDENCIES) $(EXTRA_run_verify_DEPENDENCIES)
@rm -f run-verify$(EXEEXT)
$(AM_V_CCLD)$(LINK) $(run_verify_OBJECTS) $(run_verify_LDADD) $(LIBS)
@@ -536,10 +630,16 @@ mostlyclean-compile:
distclean-compile:
-rm -f *.tab.c
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/run-decrypt.Po@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/run-encrypt.Po@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/run-export.Po@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/run-genkey.Po@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/run-identify.Po@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/run-import.Po@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/run-keylist.Po@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/run-keysign.Po@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/run-sign.Po@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/run-tofu.Po@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/run-verify.Po@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/t-data.Po@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/t-engine-info.Po@am__quote@
diff --git a/tests/gpg/Makefile.am b/tests/gpg/Makefile.am
index 107397b..9877843 100644
--- a/tests/gpg/Makefile.am
+++ b/tests/gpg/Makefile.am
@@ -38,7 +38,7 @@ c_tests = \
t-encrypt t-encrypt-sym t-encrypt-sign t-sign t-signers \
t-decrypt t-verify t-decrypt-verify t-sig-notation t-export \
t-import t-trustlist t-edit t-keylist t-keylist-sig t-wait \
- t-encrypt-large t-file-name t-gpgconf $(tests_unix)
+ t-encrypt-large t-file-name t-gpgconf t-encrypt-mixed $(tests_unix)
TESTS = initial.test $(c_tests) final.test
@@ -89,11 +89,11 @@ export GPG_AGENT_INFO :=
echo x > ./private-keys-v1.d/gpg-sample.stamp
./pubring-stamp: $(srcdir)/pubdemo.asc
- $(GPG) --no-permission-warning \
+ $(GPG) --batch --no-permission-warning \
--import $(srcdir)/pubdemo.asc
- -$(GPG) --no-permission-warning \
+ -$(GPG) --batch --no-permission-warning \
--import $(srcdir)/secdemo.asc
- touch ./pubring-stamp
+ echo x > ./pubring-stamp
./gpg.conf:
# This is required for t-sig-notations.
diff --git a/tests/gpg/Makefile.in b/tests/gpg/Makefile.in
index 3fbec6d..7886769 100644
--- a/tests/gpg/Makefile.in
+++ b/tests/gpg/Makefile.in
@@ -105,12 +105,16 @@ DIST_COMMON = $(srcdir)/Makefile.in $(srcdir)/Makefile.am \
$(top_srcdir)/build-aux/mkinstalldirs \
$(top_srcdir)/build-aux/depcomp $(noinst_HEADERS)
ACLOCAL_M4 = $(top_srcdir)/aclocal.m4
-am__aclocal_m4_deps = $(top_srcdir)/m4/glib-2.0.m4 \
- $(top_srcdir)/m4/glibc21.m4 $(top_srcdir)/m4/gnupg-ttyname.m4 \
+am__aclocal_m4_deps = $(top_srcdir)/m4/ax_cxx_compile_stdcxx.m4 \
+ $(top_srcdir)/m4/ax_pkg_swig.m4 \
+ $(top_srcdir)/m4/ax_python_devel.m4 \
+ $(top_srcdir)/m4/glib-2.0.m4 $(top_srcdir)/m4/glibc21.m4 \
+ $(top_srcdir)/m4/gnupg-ttyname.m4 \
$(top_srcdir)/m4/gpg-error.m4 $(top_srcdir)/m4/libassuan.m4 \
$(top_srcdir)/m4/libtool.m4 $(top_srcdir)/m4/ltoptions.m4 \
$(top_srcdir)/m4/ltsugar.m4 $(top_srcdir)/m4/ltversion.m4 \
- $(top_srcdir)/m4/lt~obsolete.m4 $(top_srcdir)/acinclude.m4 \
+ $(top_srcdir)/m4/lt~obsolete.m4 $(top_srcdir)/m4/pkg.m4 \
+ $(top_srcdir)/m4/qt.m4 $(top_srcdir)/acinclude.m4 \
$(top_srcdir)/configure.ac
am__configure_deps = $(am__aclocal_m4_deps) $(CONFIGURE_DEPENDENCIES) \
$(ACLOCAL_M4)
@@ -127,7 +131,7 @@ am__EXEEXT_2 = t-encrypt$(EXEEXT) t-encrypt-sym$(EXEEXT) \
t-trustlist$(EXEEXT) t-edit$(EXEEXT) t-keylist$(EXEEXT) \
t-keylist-sig$(EXEEXT) t-wait$(EXEEXT) \
t-encrypt-large$(EXEEXT) t-file-name$(EXEEXT) \
- t-gpgconf$(EXEEXT) $(am__EXEEXT_1)
+ t-gpgconf$(EXEEXT) t-encrypt-mixed$(EXEEXT) $(am__EXEEXT_1)
PROGRAMS = $(noinst_PROGRAMS)
t_decrypt_SOURCES = t-decrypt.c
t_decrypt_OBJECTS = t-decrypt.$(OBJEXT)
@@ -153,6 +157,10 @@ t_encrypt_large_SOURCES = t-encrypt-large.c
t_encrypt_large_OBJECTS = t-encrypt-large.$(OBJEXT)
t_encrypt_large_LDADD = $(LDADD)
t_encrypt_large_DEPENDENCIES = ../../src/libgpgme.la
+t_encrypt_mixed_SOURCES = t-encrypt-mixed.c
+t_encrypt_mixed_OBJECTS = t-encrypt-mixed.$(OBJEXT)
+t_encrypt_mixed_LDADD = $(LDADD)
+t_encrypt_mixed_DEPENDENCIES = ../../src/libgpgme.la
t_encrypt_sign_SOURCES = t-encrypt-sign.c
t_encrypt_sign_OBJECTS = t-encrypt-sign.$(OBJEXT)
t_encrypt_sign_LDADD = $(LDADD)
@@ -255,17 +263,17 @@ am__v_CCLD_ = $(am__v_CCLD_@AM_DEFAULT_V@)
am__v_CCLD_0 = @echo " CCLD " $@;
am__v_CCLD_1 =
SOURCES = t-decrypt.c t-decrypt-verify.c t-edit.c t-encrypt.c \
- t-encrypt-large.c t-encrypt-sign.c t-encrypt-sym.c \
- t-eventloop.c t-export.c t-file-name.c t-genkey.c t-gpgconf.c \
- t-import.c t-keylist.c t-keylist-sig.c t-sig-notation.c \
- t-sign.c t-signers.c t-thread1.c t-trustlist.c t-verify.c \
- t-wait.c
+ t-encrypt-large.c t-encrypt-mixed.c t-encrypt-sign.c \
+ t-encrypt-sym.c t-eventloop.c t-export.c t-file-name.c \
+ t-genkey.c t-gpgconf.c t-import.c t-keylist.c t-keylist-sig.c \
+ t-sig-notation.c t-sign.c t-signers.c t-thread1.c \
+ t-trustlist.c t-verify.c t-wait.c
DIST_SOURCES = t-decrypt.c t-decrypt-verify.c t-edit.c t-encrypt.c \
- t-encrypt-large.c t-encrypt-sign.c t-encrypt-sym.c \
- t-eventloop.c t-export.c t-file-name.c t-genkey.c t-gpgconf.c \
- t-import.c t-keylist.c t-keylist-sig.c t-sig-notation.c \
- t-sign.c t-signers.c t-thread1.c t-trustlist.c t-verify.c \
- t-wait.c
+ t-encrypt-large.c t-encrypt-mixed.c t-encrypt-sign.c \
+ t-encrypt-sym.c t-eventloop.c t-export.c t-file-name.c \
+ t-genkey.c t-gpgconf.c t-import.c t-keylist.c t-keylist-sig.c \
+ t-sig-notation.c t-sign.c t-signers.c t-thread1.c \
+ t-trustlist.c t-verify.c t-wait.c
am__can_run_installinfo = \
case $$AM_UPDATE_INFO_DIR in \
n|no|NO) false;; \
@@ -328,6 +336,7 @@ BUILD_REVISION = @BUILD_REVISION@
BUILD_TIMESTAMP = @BUILD_TIMESTAMP@
CC = @CC@
CCDEPMODE = @CCDEPMODE@
+CC_FOR_BUILD = @CC_FOR_BUILD@
CFLAGS = @CFLAGS@
CPP = @CPP@
CPPFLAGS = @CPPFLAGS@
@@ -339,12 +348,14 @@ CYGPATH_W = @CYGPATH_W@
DEFS = @DEFS@
DEPDIR = @DEPDIR@
DLLTOOL = @DLLTOOL@
+DOXYGEN = @DOXYGEN@
DSYMUTIL = @DSYMUTIL@
DUMPBIN = @DUMPBIN@
ECHO_C = @ECHO_C@
ECHO_N = @ECHO_N@
ECHO_T = @ECHO_T@
EGREP = @EGREP@
+ENABLED_LANGUAGES = @ENABLED_LANGUAGES@
EXEEXT = @EXEEXT@
FGREP = @FGREP@
GITLOG_TO_CHANGELOG = @GITLOG_TO_CHANGELOG@
@@ -355,15 +366,23 @@ GLIB_LIBS = @GLIB_LIBS@
GLIB_MKENUMS = @GLIB_MKENUMS@
GOBJECT_QUERY = @GOBJECT_QUERY@
GPGME_CONFIG_API_VERSION = @GPGME_CONFIG_API_VERSION@
+GPGME_CONFIG_AVAIL_LANG = @GPGME_CONFIG_AVAIL_LANG@
GPGME_CONFIG_CFLAGS = @GPGME_CONFIG_CFLAGS@
GPGME_CONFIG_HOST = @GPGME_CONFIG_HOST@
GPGME_CONFIG_LIBS = @GPGME_CONFIG_LIBS@
+GPGME_QTTEST_CFLAGS = @GPGME_QTTEST_CFLAGS@
+GPGME_QTTEST_LIBS = @GPGME_QTTEST_LIBS@
+GPGME_QT_CFLAGS = @GPGME_QT_CFLAGS@
+GPGME_QT_LIBS = @GPGME_QT_LIBS@
GPG_ERROR_CFLAGS = @GPG_ERROR_CFLAGS@
GPG_ERROR_CONFIG = @GPG_ERROR_CONFIG@
GPG_ERROR_LIBS = @GPG_ERROR_LIBS@
GPG_ERROR_MT_CFLAGS = @GPG_ERROR_MT_CFLAGS@
GPG_ERROR_MT_LIBS = @GPG_ERROR_MT_LIBS@
+GRAPHVIZ = @GRAPHVIZ@
GREP = @GREP@
+HAVE_CXX11 = @HAVE_CXX11@
+HAVE_DOT = @HAVE_DOT@
INSTALL = @INSTALL@
INSTALL_DATA = @INSTALL_DATA@
INSTALL_PROGRAM = @INSTALL_PROGRAM@
@@ -374,10 +393,16 @@ LDFLAGS = @LDFLAGS@
LIBASSUAN_CFLAGS = @LIBASSUAN_CFLAGS@
LIBASSUAN_CONFIG = @LIBASSUAN_CONFIG@
LIBASSUAN_LIBS = @LIBASSUAN_LIBS@
+LIBGPGMEPP_LT_AGE = @LIBGPGMEPP_LT_AGE@
+LIBGPGMEPP_LT_CURRENT = @LIBGPGMEPP_LT_CURRENT@
+LIBGPGMEPP_LT_REVISION = @LIBGPGMEPP_LT_REVISION@
LIBGPGME_LT_AGE = @LIBGPGME_LT_AGE@
LIBGPGME_LT_CURRENT = @LIBGPGME_LT_CURRENT@
LIBGPGME_LT_REVISION = @LIBGPGME_LT_REVISION@
LIBOBJS = @LIBOBJS@
+LIBQGPGME_LT_AGE = @LIBQGPGME_LT_AGE@
+LIBQGPGME_LT_CURRENT = @LIBQGPGME_LT_CURRENT@
+LIBQGPGME_LT_REVISION = @LIBQGPGME_LT_REVISION@
LIBS = @LIBS@
LIBTOOL = @LIBTOOL@
LIPO = @LIPO@
@@ -387,6 +412,8 @@ MAINT = @MAINT@
MAKEINFO = @MAKEINFO@
MANIFEST_TOOL = @MANIFEST_TOOL@
MKDIR_P = @MKDIR_P@
+MOC = @MOC@
+MOC2 = @MOC2@
NEED__FILE_OFFSET_BITS = @NEED__FILE_OFFSET_BITS@
NM = @NM@
NMEDIT = @NMEDIT@
@@ -403,14 +430,27 @@ PACKAGE_URL = @PACKAGE_URL@
PACKAGE_VERSION = @PACKAGE_VERSION@
PATH_SEPARATOR = @PATH_SEPARATOR@
PKG_CONFIG = @PKG_CONFIG@
-QT4_CORE_CFLAGS = @QT4_CORE_CFLAGS@
-QT4_CORE_LIBS = @QT4_CORE_LIBS@
+PYTHON = @PYTHON@
+PYTHONS = @PYTHONS@
+PYTHON_CPPFLAGS = @PYTHON_CPPFLAGS@
+PYTHON_EXEC_PREFIX = @PYTHON_EXEC_PREFIX@
+PYTHON_EXTRA_LDFLAGS = @PYTHON_EXTRA_LDFLAGS@
+PYTHON_EXTRA_LIBS = @PYTHON_EXTRA_LIBS@
+PYTHON_LDFLAGS = @PYTHON_LDFLAGS@
+PYTHON_PLATFORM = @PYTHON_PLATFORM@
+PYTHON_PREFIX = @PYTHON_PREFIX@
+PYTHON_SITE_PKG = @PYTHON_SITE_PKG@
+PYTHON_VERSION = @PYTHON_VERSION@
+PYTHON_VERSIONS = @PYTHON_VERSIONS@
+QTCHOOSER = @QTCHOOSER@
RANLIB = @RANLIB@
RC = @RC@
SED = @SED@
SET_MAKE = @SET_MAKE@
SHELL = @SHELL@
STRIP = @STRIP@
+SWIG = @SWIG@
+SWIG_LIB = @SWIG_LIB@
SYSROOT = @SYSROOT@
VERSION = @VERSION@
VERSION_NUMBER = @VERSION_NUMBER@
@@ -459,9 +499,13 @@ mandir = @mandir@
mkdir_p = @mkdir_p@
oldincludedir = @oldincludedir@
pdfdir = @pdfdir@
+pkgpyexecdir = @pkgpyexecdir@
+pkgpythondir = @pkgpythondir@
prefix = @prefix@
program_transform_name = @program_transform_name@
psdir = @psdir@
+pyexecdir = @pyexecdir@
+pythondir = @pythondir@
sbindir = @sbindir@
sharedstatedir = @sharedstatedir@
srcdir = @srcdir@
@@ -484,7 +528,7 @@ c_tests = \
t-encrypt t-encrypt-sym t-encrypt-sign t-sign t-signers \
t-decrypt t-verify t-decrypt-verify t-sig-notation t-export \
t-import t-trustlist t-edit t-keylist t-keylist-sig t-wait \
- t-encrypt-large t-file-name t-gpgconf $(tests_unix)
+ t-encrypt-large t-file-name t-gpgconf t-encrypt-mixed $(tests_unix)
CLEANFILES = secring.gpg pubring.gpg pubring.kbx trustdb.gpg dirmngr.conf \
gpg-agent.conf pubring.kbx~ S.gpg-agent gpg.conf pubring.gpg~ \
@@ -569,6 +613,10 @@ t-encrypt-large$(EXEEXT): $(t_encrypt_large_OBJECTS) $(t_encrypt_large_DEPENDENC
@rm -f t-encrypt-large$(EXEEXT)
$(AM_V_CCLD)$(LINK) $(t_encrypt_large_OBJECTS) $(t_encrypt_large_LDADD) $(LIBS)
+t-encrypt-mixed$(EXEEXT): $(t_encrypt_mixed_OBJECTS) $(t_encrypt_mixed_DEPENDENCIES) $(EXTRA_t_encrypt_mixed_DEPENDENCIES)
+ @rm -f t-encrypt-mixed$(EXEEXT)
+ $(AM_V_CCLD)$(LINK) $(t_encrypt_mixed_OBJECTS) $(t_encrypt_mixed_LDADD) $(LIBS)
+
t-encrypt-sign$(EXEEXT): $(t_encrypt_sign_OBJECTS) $(t_encrypt_sign_DEPENDENCIES) $(EXTRA_t_encrypt_sign_DEPENDENCIES)
@rm -f t-encrypt-sign$(EXEEXT)
$(AM_V_CCLD)$(LINK) $(t_encrypt_sign_OBJECTS) $(t_encrypt_sign_LDADD) $(LIBS)
@@ -647,6 +695,7 @@ distclean-compile:
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/t-decrypt.Po@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/t-edit.Po@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/t-encrypt-large.Po@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/t-encrypt-mixed.Po@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/t-encrypt-sign.Po@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/t-encrypt-sym.Po@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/t-encrypt.Po@am__quote@
@@ -1015,11 +1064,11 @@ export GPG_AGENT_INFO :=
echo x > ./private-keys-v1.d/gpg-sample.stamp
./pubring-stamp: $(srcdir)/pubdemo.asc
- $(GPG) --no-permission-warning \
+ $(GPG) --batch --no-permission-warning \
--import $(srcdir)/pubdemo.asc
- -$(GPG) --no-permission-warning \
+ -$(GPG) --batch --no-permission-warning \
--import $(srcdir)/secdemo.asc
- touch ./pubring-stamp
+ echo x > ./pubring-stamp
./gpg.conf:
# This is required for t-sig-notations.
diff --git a/tests/gpg/t-decrypt-verify.c b/tests/gpg/t-decrypt-verify.c
index 113aec1..b774cfd 100644
--- a/tests/gpg/t-decrypt-verify.c
+++ b/tests/gpg/t-decrypt-verify.c
@@ -1,23 +1,22 @@
/* t-decrypt-verify.c - Regression test.
- Copyright (C) 2000 Werner Koch (dd9jn)
- Copyright (C) 2001, 2002, 2003, 2004 g10 Code GmbH
-
- This file is part of GPGME.
-
- GPGME is free software; you can redistribute it and/or modify it
- under the terms of the GNU Lesser General Public License as
- published by the Free Software Foundation; either version 2.1 of
- the License, or (at your option) any later version.
-
- GPGME is distributed in the hope that it will be useful, but
- WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- Lesser General Public License for more details.
-
- You should have received a copy of the GNU Lesser General Public
- License along with this program; if not, write to the Free Software
- Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
- 02111-1307, USA. */
+ * Copyright (C) 2000 Werner Koch (dd9jn)
+ * Copyright (C) 2001, 2002, 2003, 2004 g10 Code GmbH
+ *
+ * This file is part of GPGME.
+ *
+ * GPGME is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU Lesser General Public License as
+ * published by the Free Software Foundation; either version 2.1 of
+ * the License, or (at your option) any later version.
+ *
+ * GPGME is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this program; if not, see <http://www.gnu.org/licenses/>.
+ */
/* We need to include config.h so that we know whether we are building
with large file system (LFS) support. */
@@ -38,7 +37,7 @@
static void
check_verify_result (gpgme_verify_result_t result, unsigned int summary,
- char *fpr, gpgme_error_t status)
+ const char *fpr, gpgme_error_t status)
{
gpgme_signature_t sig;
@@ -94,7 +93,7 @@ check_verify_result (gpgme_verify_result_t result, unsigned int summary,
}
-int
+int
main (int argc, char *argv[])
{
gpgme_ctx_t ctx;
@@ -102,9 +101,12 @@ main (int argc, char *argv[])
gpgme_data_t in, out;
gpgme_decrypt_result_t decrypt_result;
gpgme_verify_result_t verify_result;
- const char *cipher_2_asc = make_filename ("cipher-2.asc");
+ char *cipher_2_asc = make_filename ("cipher-2.asc");
char *agent_info;
+ (void)argc;
+ (void)argv;
+
init_gpgme (GPGME_PROTOCOL_OpenPGP);
err = gpgme_new (&ctx);
@@ -115,6 +117,7 @@ main (int argc, char *argv[])
gpgme_set_passphrase_cb (ctx, passphrase_cb, NULL);
err = gpgme_data_new_from_file (&in, cipher_2_asc, 1);
+ free (cipher_2_asc);
fail_if_err (err);
err = gpgme_data_new (&out);
fail_if_err (err);
@@ -127,7 +130,7 @@ main (int argc, char *argv[])
fprintf (stderr, "%s:%i: unsupported algorithm: %s\n",
__FILE__, __LINE__, decrypt_result->unsupported_algorithm);
exit (1);
- }
+ }
print_data (out);
verify_result = gpgme_op_verify_result (ctx);
check_verify_result (verify_result, 0,
diff --git a/tests/gpg/t-decrypt.c b/tests/gpg/t-decrypt.c
index 2a2f4d7..92fadd6 100644
--- a/tests/gpg/t-decrypt.c
+++ b/tests/gpg/t-decrypt.c
@@ -3,17 +3,17 @@
Copyright (C) 2001, 2003, 2004 g10 Code GmbH
This file is part of GPGME.
-
+
GPGME is free software; you can redistribute it and/or modify it
under the terms of the GNU Lesser General Public License as
published by the Free Software Foundation; either version 2.1 of
the License, or (at your option) any later version.
-
+
GPGME is distributed in the hope that it will be useful, but
WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
Lesser General Public License for more details.
-
+
You should have received a copy of the GNU Lesser General Public
License along with this program; if not, write to the Free Software
Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
@@ -36,16 +36,19 @@
#include "t-support.h"
-int
+int
main (int argc, char *argv[])
{
gpgme_ctx_t ctx;
gpgme_error_t err;
gpgme_data_t in, out;
gpgme_decrypt_result_t result;
- const char *cipher_1_asc = make_filename ("cipher-1.asc");
+ char *cipher_1_asc = make_filename ("cipher-1.asc");
char *agent_info;
+ (void)argc;
+ (void)argv;
+
init_gpgme (GPGME_PROTOCOL_OpenPGP);
err = gpgme_new (&ctx);
@@ -56,11 +59,12 @@ main (int argc, char *argv[])
gpgme_set_passphrase_cb (ctx, passphrase_cb, NULL);
err = gpgme_data_new_from_file (&in, cipher_1_asc, 1);
+ free (cipher_1_asc);
fail_if_err (err);
err = gpgme_data_new (&out);
fail_if_err (err);
-
+
err = gpgme_op_decrypt (ctx, in, out);
fail_if_err (err);
result = gpgme_op_decrypt_result (ctx);
@@ -71,7 +75,7 @@ main (int argc, char *argv[])
exit (1);
}
print_data (out);
-
+
gpgme_data_release (in);
gpgme_data_release (out);
gpgme_release (ctx);
diff --git a/tests/gpg/t-edit.c b/tests/gpg/t-edit.c
index 545db73..7b444fa 100644
--- a/tests/gpg/t-edit.c
+++ b/tests/gpg/t-edit.c
@@ -3,17 +3,17 @@
Copyright (C) 2001, 2002, 2003, 2004 g10 Code GmbH
This file is part of GPGME.
-
+
GPGME is free software; you can redistribute it and/or modify it
under the terms of the GNU Lesser General Public License as
published by the Free Software Foundation; either version 2.1 of
the License, or (at your option) any later version.
-
+
GPGME is distributed in the hope that it will be useful, but
WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
Lesser General Public License for more details.
-
+
You should have received a copy of the GNU Lesser General Public
License along with this program; if not, write to the Free Software
Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
@@ -43,7 +43,7 @@ flush_data (gpgme_data_t dh)
{
char buf[100];
int ret;
-
+
ret = gpgme_data_seek (dh, 0, SEEK_SET);
if (ret)
fail_if_err (gpgme_error_from_errno (errno));
@@ -55,22 +55,22 @@ flush_data (gpgme_data_t dh)
gpgme_error_t
-edit_fnc (void *opaque, gpgme_status_code_t status, const char *args, int fd)
+interact_fnc (void *opaque, const char *status, const char *args, int fd)
{
- char *result = NULL;
+ const char *result = NULL;
gpgme_data_t out = (gpgme_data_t) opaque;
fputs ("[-- Response --]\n", stdout);
- flush_data (out);
+ flush_data (out);
- fprintf (stdout, "[-- Code: %i, %s --]\n", status, args);
+ fprintf (stdout, "[-- Code: %s, %s --]\n", status, args);
if (fd >= 0)
{
if (!strcmp (args, "keyedit.prompt"))
{
static int step = 0;
-
+
switch (step)
{
case 0:
@@ -103,14 +103,14 @@ edit_fnc (void *opaque, gpgme_status_code_t status, const char *args, int fd)
if (result)
{
- gpgme_io_write (fd, result, strlen (result));
- gpgme_io_write (fd, "\n", 1);
+ gpgme_io_writen (fd, result, strlen (result));
+ gpgme_io_writen (fd, "\n", 1);
}
return 0;
}
-int
+int
main (int argc, char **argv)
{
gpgme_ctx_t ctx;
@@ -120,6 +120,9 @@ main (int argc, char **argv)
const char *pattern = "Alpha";
char *agent_info;
+ (void)argc;
+ (void)argv;
+
init_gpgme (GPGME_PROTOCOL_OpenPGP);
err = gpgme_new (&ctx);
@@ -138,7 +141,7 @@ main (int argc, char **argv)
err = gpgme_op_keylist_end (ctx);
fail_if_err (err);
- err = gpgme_op_edit (ctx, key, edit_fnc, out, out);
+ err = gpgme_op_interact (ctx, key, 0, interact_fnc, out, out);
fail_if_err (err);
fputs ("[-- Last response --]\n", stdout);
diff --git a/tests/gpg/t-encrypt-large.c b/tests/gpg/t-encrypt-large.c
index 6cc6138..8d78a04 100644
--- a/tests/gpg/t-encrypt-large.c
+++ b/tests/gpg/t-encrypt-large.c
@@ -2,17 +2,17 @@
Copyright (C) 2005 g10 Code GmbH
This file is part of GPGME.
-
+
GPGME is free software; you can redistribute it and/or modify it
under the terms of the GNU Lesser General Public License as
published by the Free Software Foundation; either version 2.1 of
the License, or (at your option) any later version.
-
+
GPGME is distributed in the hope that it will be useful, but
WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
Lesser General Public License for more details.
-
+
You should have received a copy of the GNU Lesser General Public
License along with this program; if not, write to the Free Software
Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
@@ -50,7 +50,7 @@ read_cb (void *handle, void *buffer, size_t size)
for (; size && parms->bytes_to_send; size--, parms->bytes_to_send--)
*p++ = rand ();
-
+
return (p - (char*)buffer);
}
@@ -60,6 +60,8 @@ write_cb (void *handle, const void *buffer, size_t size)
{
struct cb_parms *parms = handle;
+ (void)buffer;
+
parms->bytes_received += size;
return size;
@@ -70,13 +72,18 @@ static void
progress_cb (void *opaque, const char *what, int type, int current, int total)
{
/* This is just a dummy. */
+ (void)opaque;
+ (void)what;
+ (void)type;
+ (void)current;
+ (void)total;
}
-int
+int
main (int argc, char *argv[])
{
gpgme_ctx_t ctx;
@@ -94,7 +101,7 @@ main (int argc, char *argv[])
nbytes = 100000;
init_gpgme (GPGME_PROTOCOL_OpenPGP);
-
+
memset (&cbs, 0, sizeof cbs);
cbs.read = read_cb;
cbs.write = write_cb;
@@ -131,7 +138,7 @@ main (int argc, char *argv[])
result->invalid_recipients->fpr);
exit (1);
}
- printf ("plaintext=%u bytes, ciphertext=%u bytes\n",
+ printf ("plaintext=%u bytes, ciphertext=%u bytes\n",
(unsigned int)nbytes, (unsigned int)parms.bytes_received);
gpgme_key_unref (key[0]);
diff --git a/tests/gpg/t-encrypt-mixed.c b/tests/gpg/t-encrypt-mixed.c
new file mode 100644
index 0000000..afe5ba2
--- /dev/null
+++ b/tests/gpg/t-encrypt-mixed.c
@@ -0,0 +1,129 @@
+/* t-encrypt-mixed.c - Regression test.
+ Copyright (C) 2016 Intevation GmbH
+
+ This file is part of GPGME.
+
+ GPGME is free software; you can redistribute it and/or modify it
+ under the terms of the GNU Lesser General Public License as
+ published by the Free Software Foundation; either version 2.1 of
+ the License, or (at your option) any later version.
+
+ GPGME is distributed in the hope that it will be useful, but
+ WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Lesser General Public License for more details.
+
+ You should have received a copy of the GNU Lesser General Public
+ License along with this program; if not, write to the Free Software
+ Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
+ 02111-1307, USA. */
+
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+#endif
+
+#include <stdlib.h>
+#include <stdio.h>
+#include <string.h>
+
+#include <gpgme.h>
+
+#include "t-support.h"
+
+/* Tests mixed symmetric and asymetric decryption. Verifies
+ that an encrypted message can be decrypted without the
+ secret key but that the recipient is also set correctly. */
+int
+main (void)
+{
+ gpgme_ctx_t ctx;
+ gpgme_error_t err;
+ gpgme_data_t in, out;
+ gpgme_key_t key[2] = { NULL, NULL };
+ gpgme_encrypt_result_t result;
+ gpgme_decrypt_result_t dec_result;
+ gpgme_recipient_t recipient;
+ const char *text = "Hallo Leute\n";
+ char *text2;
+ size_t len;
+
+ init_gpgme (GPGME_PROTOCOL_OpenPGP);
+
+ err = gpgme_new (&ctx);
+ fail_if_err (err);
+ gpgme_set_armor (ctx, 1);
+
+ err = gpgme_data_new_from_mem (&in, text, strlen (text), 0);
+ fail_if_err (err);
+
+ err = gpgme_data_new (&out);
+ fail_if_err (err);
+
+ gpgme_set_passphrase_cb (ctx, passphrase_cb, NULL);
+
+ /* A recipient for which we don't have a secret key */
+ err = gpgme_get_key (ctx, "D695676BDCEDCC2CDD6152BCFE180B1DA9E3B0B2",
+ &key[0], 0);
+ fail_if_err (err);
+
+ err = gpgme_op_encrypt (ctx, key,
+ GPGME_ENCRYPT_ALWAYS_TRUST | GPGME_ENCRYPT_SYMMETRIC,
+ in, out);
+ fail_if_err (err);
+ result = gpgme_op_encrypt_result (ctx);
+ if (result->invalid_recipients)
+ {
+ fprintf (stderr, "Invalid recipient encountered: %s\n",
+ result->invalid_recipients->fpr);
+ exit (1);
+ }
+
+ print_data (out);
+
+ /* Now try to decrypt */
+ gpgme_data_seek (out, 0, SEEK_SET);
+
+ gpgme_data_release (in);
+ err = gpgme_data_new (&in);
+ fail_if_err (err);
+
+ err = gpgme_op_decrypt (ctx, out, in);
+ fail_if_err (err);
+
+ fputs ("Begin Result Decryption:\n", stdout);
+ print_data (in);
+ fputs ("End Result.\n", stdout);
+
+ dec_result = gpgme_op_decrypt_result (ctx);
+ if (dec_result->unsupported_algorithm || dec_result->wrong_key_usage)
+ {
+ fprintf (stderr, "%s:%d: Decryption failed\n", __FILE__, __LINE__);
+ exit (1);
+ }
+
+ text2 = gpgme_data_release_and_get_mem (in, &len);
+ if (strncmp (text, text2, len))
+ {
+ fprintf (stderr, "%s:%d: Wrong plaintext\n", __FILE__, __LINE__);
+ exit (1);
+ }
+
+ recipient = dec_result->recipients;
+ if (!recipient || recipient->next)
+ {
+ fprintf (stderr, "%s:%d: Invalid recipients \n", __FILE__, __LINE__);
+ exit (1);
+ }
+
+ if (strncmp (recipient->keyid, "5381EA4EE29BA37F", 16))
+ {
+ fprintf (stderr, "%s:%d: Not encrypted to recipient's subkey \n", __FILE__, __LINE__);
+ exit (1);
+ }
+
+ gpgme_key_unref (key[0]);
+ free (text2);
+ gpgme_data_release (out);
+ gpgme_release (ctx);
+ return 0;
+}
diff --git a/tests/gpg/t-encrypt-sign.c b/tests/gpg/t-encrypt-sign.c
index 1e1262f..41d16a0 100644
--- a/tests/gpg/t-encrypt-sign.c
+++ b/tests/gpg/t-encrypt-sign.c
@@ -94,6 +94,9 @@ main (int argc, char **argv)
gpgme_sign_result_t sign_result;
char *agent_info;
+ (void)argc;
+ (void)argv;
+
init_gpgme (GPGME_PROTOCOL_OpenPGP);
err = gpgme_new (&ctx);
diff --git a/tests/gpg/t-encrypt-sym.c b/tests/gpg/t-encrypt-sym.c
index 51a3fc1..8e5e7ff 100644
--- a/tests/gpg/t-encrypt-sym.c
+++ b/tests/gpg/t-encrypt-sym.c
@@ -3,17 +3,17 @@
Copyright (C) 2001, 2003, 2004 g10 Code GmbH
This file is part of GPGME.
-
+
GPGME is free software; you can redistribute it and/or modify it
under the terms of the GNU Lesser General Public License as
published by the Free Software Foundation; either version 2.1 of
the License, or (at your option) any later version.
-
+
GPGME is distributed in the hope that it will be useful, but
WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
Lesser General Public License for more details.
-
+
You should have received a copy of the GNU Lesser General Public
License along with this program; if not, write to the Free Software
Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
@@ -36,7 +36,7 @@
#include "t-support.h"
-int
+int
main (int argc, char *argv[])
{
gpgme_ctx_t ctx;
@@ -47,6 +47,9 @@ main (int argc, char *argv[])
char *p;
size_t len;
+ (void)argc;
+ (void)argv;
+
init_gpgme (GPGME_PROTOCOL_OpenPGP);
err = gpgme_new (&ctx);
@@ -92,6 +95,7 @@ main (int argc, char *argv[])
}
gpgme_data_release (cipher);
+ free (text2);
gpgme_release (ctx);
return 0;
diff --git a/tests/gpg/t-encrypt.c b/tests/gpg/t-encrypt.c
index 264f31a..6eafc00 100644
--- a/tests/gpg/t-encrypt.c
+++ b/tests/gpg/t-encrypt.c
@@ -3,17 +3,17 @@
Copyright (C) 2001, 2002, 2003, 2004 g10 Code GmbH
This file is part of GPGME.
-
+
GPGME is free software; you can redistribute it and/or modify it
under the terms of the GNU Lesser General Public License as
published by the Free Software Foundation; either version 2.1 of
the License, or (at your option) any later version.
-
+
GPGME is distributed in the hope that it will be useful, but
WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
Lesser General Public License for more details.
-
+
You should have received a copy of the GNU Lesser General Public
License along with this program; if not, write to the Free Software
Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
@@ -34,7 +34,7 @@
#include "t-support.h"
-int
+int
main (int argc, char *argv[])
{
gpgme_ctx_t ctx;
@@ -43,8 +43,11 @@ main (int argc, char *argv[])
gpgme_key_t key[3] = { NULL, NULL, NULL };
gpgme_encrypt_result_t result;
+ (void)argc;
+ (void)argv;
+
init_gpgme (GPGME_PROTOCOL_OpenPGP);
-
+
err = gpgme_new (&ctx);
fail_if_err (err);
gpgme_set_armor (ctx, 1);
diff --git a/tests/gpg/t-eventloop.c b/tests/gpg/t-eventloop.c
index cb1e57c..74af35f 100644
--- a/tests/gpg/t-eventloop.c
+++ b/tests/gpg/t-eventloop.c
@@ -3,17 +3,17 @@
Copyright (C) 2001, 2002, 2003, 2004 g10 Code GmbH
This file is part of GPGME.
-
+
GPGME is free software; you can redistribute it and/or modify it
under the terms of the GNU Lesser General Public License as
published by the Free Software Foundation; either version 2.1 of
the License, or (at your option) any later version.
-
+
GPGME is distributed in the hope that it will be useful, but
WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
Lesser General Public License for more details.
-
+
You should have received a copy of the GNU Lesser General Public
License along with this program; if not, write to the Free Software
Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
@@ -167,8 +167,8 @@ struct gpgme_io_cbs io_cbs =
};
-int
-main (int argc, char *argv[])
+int
+main (void)
{
gpgme_ctx_t ctx;
gpgme_error_t err;
@@ -214,7 +214,7 @@ main (int argc, char *argv[])
fputs ("Begin Result:\n", stdout);
print_data (out);
fputs ("End Result.\n", stdout);
-
+
gpgme_key_unref (key[0]);
gpgme_key_unref (key[1]);
gpgme_data_release (in);
diff --git a/tests/gpg/t-export.c b/tests/gpg/t-export.c
index 85cff23..eaed829 100644
--- a/tests/gpg/t-export.c
+++ b/tests/gpg/t-export.c
@@ -3,17 +3,17 @@
Copyright (C) 2001, 2003, 2004 g10 Code GmbH
This file is part of GPGME.
-
+
GPGME is free software; you can redistribute it and/or modify it
under the terms of the GNU Lesser General Public License as
published by the Free Software Foundation; either version 2.1 of
the License, or (at your option) any later version.
-
+
GPGME is distributed in the hope that it will be useful, but
WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
Lesser General Public License for more details.
-
+
You should have received a copy of the GNU Lesser General Public
License along with this program; if not, write to the Free Software
Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
@@ -35,7 +35,7 @@
#include "t-support.h"
-int
+int
main (int argc, char **argv)
{
gpgme_ctx_t ctx;
@@ -44,6 +44,9 @@ main (int argc, char **argv)
const char *pattern[] = { "Alpha", "Bob", NULL };
gpgme_key_t keyarray[3];
+ (void)argc;
+ (void)argv;
+
init_gpgme (GPGME_PROTOCOL_OpenPGP);
err = gpgme_new (&ctx);
@@ -60,7 +63,7 @@ main (int argc, char **argv)
fputs ("Begin Result:\n", stdout);
print_data (out);
fputs ("End Result.\n", stdout);
-
+
gpgme_data_release (out);
/* Again. Now using a key array. */
@@ -84,11 +87,11 @@ main (int argc, char **argv)
fputs ("Begin Result:\n", stdout);
print_data (out);
fputs ("End Result.\n", stdout);
-
+
gpgme_data_release (out);
gpgme_release (ctx);
-
+
return 0;
}
diff --git a/tests/gpg/t-file-name.c b/tests/gpg/t-file-name.c
index eb20fc0..3c2a796 100644
--- a/tests/gpg/t-file-name.c
+++ b/tests/gpg/t-file-name.c
@@ -3,17 +3,17 @@
Copyright (C) 2001, 2002, 2003, 2004 g10 Code GmbH
This file is part of GPGME.
-
+
GPGME is free software; you can redistribute it and/or modify it
under the terms of the GNU Lesser General Public License as
published by the Free Software Foundation; either version 2.1 of
the License, or (at your option) any later version.
-
+
GPGME is distributed in the hope that it will be useful, but
WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
Lesser General Public License for more details.
-
+
You should have received a copy of the GNU Lesser General Public
License along with this program; if not, write to the Free Software
Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
@@ -36,8 +36,8 @@
#define TESTNAME "abcde12345"
-int
-main (int argc, char *argv[])
+int
+main (void)
{
gpgme_ctx_t ctx;
gpgme_error_t err;
@@ -47,7 +47,7 @@ main (int argc, char *argv[])
char *agent_info;
init_gpgme (GPGME_PROTOCOL_OpenPGP);
-
+
err = gpgme_new (&ctx);
fail_if_err (err);
gpgme_set_armor (ctx, 1);
@@ -87,7 +87,7 @@ main (int argc, char *argv[])
{
fprintf (stderr, "%s:%i: Unexpected result file name: %s\n",
__FILE__, __LINE__,
- result->file_name ? "(null)" : result->file_name);
+ result->file_name ? result->file_name : "(null)");
exit (1);
}
diff --git a/tests/gpg/t-genkey.c b/tests/gpg/t-genkey.c
index 407824f..f0127f7 100644
--- a/tests/gpg/t-genkey.c
+++ b/tests/gpg/t-genkey.c
@@ -3,17 +3,17 @@
Copyright (C) 2001, 2003, 2004 g10 Code GmbH
This file is part of GPGME.
-
+
GPGME is free software; you can redistribute it and/or modify it
under the terms of the GNU Lesser General Public License as
published by the Free Software Foundation; either version 2.1 of
the License, or (at your option) any later version.
-
+
GPGME is distributed in the hope that it will be useful, but
WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
Lesser General Public License for more details.
-
+
You should have received a copy of the GNU Lesser General Public
License along with this program; if not, write to the Free Software
Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
@@ -40,6 +40,8 @@ static int progress_called;
static void
progress (void *self, const char *what, int type, int current, int total)
{
+ (void)self;
+
if (!strcmp (what, "primegen") && !current && !total
&& (type == '.' || type == '+' || type == '!'
|| type == '^' || type == '<' || type == '>'))
@@ -57,7 +59,7 @@ progress (void *self, const char *what, int type, int current, int total)
}
-int
+int
main (int argc, char **argv)
{
gpgme_ctx_t ctx;
@@ -75,13 +77,16 @@ main (int argc, char **argv)
"</GnupgKeyParms>\n";
gpgme_genkey_result_t result;
+ (void)argc;
+ (void)argv;
+
init_gpgme (GPGME_PROTOCOL_OpenPGP);
err = gpgme_new (&ctx);
fail_if_err (err);
gpgme_set_progress_cb (ctx, progress, NULL);
-
+
err = gpgme_op_genkey (ctx, parms, NULL, NULL);
fail_if_err (err);
diff --git a/tests/gpg/t-gpgconf.c b/tests/gpg/t-gpgconf.c
index 8e487b7..55033bf 100644
--- a/tests/gpg/t-gpgconf.c
+++ b/tests/gpg/t-gpgconf.c
@@ -7,12 +7,12 @@
under the terms of the GNU Lesser General Public License as
published by the Free Software Foundation; either version 2.1 of
the License, or (at your option) any later version.
-
+
GPGME is distributed in the hope that it will be useful, but
WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
Lesser General Public License for more details.
-
+
You should have received a copy of the GNU Lesser General Public
License along with this program; if not, write to the Free Software
Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
@@ -172,8 +172,8 @@ dump_opt (gpgme_conf_opt_t opt)
{
if (opt->argname)
{
- char *more = (opt->flags & GPGME_CONF_LIST) ? "..." : "";
-
+ const char *more = (opt->flags & GPGME_CONF_LIST) ? "..." : "";
+
if (opt->flags & GPGME_CONF_OPTIONAL)
{
printf ("%c%c --%s [%s%s] %s", level, runtime, opt->name, opt->argname, more,
@@ -187,7 +187,7 @@ dump_opt (gpgme_conf_opt_t opt)
}
else
printf ("%c%c --%s%s", level, runtime, opt->name, spaces (opt->name, 5));
-
+
if (opt->description)
printf ("%s", opt->description);
printf ("\n");
@@ -250,8 +250,8 @@ dump_comp (gpgme_conf_comp_t comp)
}
-int
-main (int argc, char **argv)
+int
+main (void)
{
gpgme_ctx_t ctx;
gpgme_error_t err;
@@ -302,13 +302,13 @@ main (int argc, char **argv)
opt = comp->options;
while (opt && strcmp (opt->name, "verbose"))
opt = opt->next;
-
+
/* Allow for the verbose option not to be there. */
if (opt)
{
err = gpgme_conf_opt_change (opt, 0, arg);
fail_if_err (err);
-
+
err = gpgme_op_conf_save (ctx, comp);
fail_if_err (err);
}
diff --git a/tests/gpg/t-import.c b/tests/gpg/t-import.c
index d673f87..89a5815 100644
--- a/tests/gpg/t-import.c
+++ b/tests/gpg/t-import.c
@@ -3,17 +3,17 @@
Copyright (C) 2001, 2003, 2004 g10 Code GmbH
This file is part of GPGME.
-
+
GPGME is free software; you can redistribute it and/or modify it
under the terms of the GNU Lesser General Public License as
published by the Free Software Foundation; either version 2.1 of
the License, or (at your option) any later version.
-
+
GPGME is distributed in the hope that it will be useful, but
WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
Lesser General Public License for more details.
-
+
You should have received a copy of the GNU Lesser General Public
License along with this program; if not, write to the Free Software
Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
@@ -36,7 +36,7 @@
void
-check_result (gpgme_import_result_t result, char *fpr, int secret)
+check_result (gpgme_import_result_t result, const char *fpr, int secret)
{
if (result->considered != 1 && (secret && result->considered != 3))
{
@@ -207,15 +207,18 @@ check_result (gpgme_import_result_t result, char *fpr, int secret)
}
-int
+int
main (int argc, char *argv[])
{
gpgme_ctx_t ctx;
gpgme_error_t err;
gpgme_data_t in;
gpgme_import_result_t result;
- const char *pubkey_1_asc = make_filename ("pubkey-1.asc");
- const char *seckey_1_asc = make_filename ("seckey-1.asc");
+ char *pubkey_1_asc = make_filename ("pubkey-1.asc");
+ char *seckey_1_asc = make_filename ("seckey-1.asc");
+
+ (void)argc;
+ (void)argv;
init_gpgme (GPGME_PROTOCOL_OpenPGP);
@@ -223,6 +226,7 @@ main (int argc, char *argv[])
fail_if_err (err);
err = gpgme_data_new_from_file (&in, pubkey_1_asc, 1);
+ free (pubkey_1_asc);
fail_if_err (err);
err = gpgme_op_import (ctx, in);
@@ -232,6 +236,7 @@ main (int argc, char *argv[])
gpgme_data_release (in);
err = gpgme_data_new_from_file (&in, seckey_1_asc, 1);
+ free (seckey_1_asc);
fail_if_err (err);
err = gpgme_op_import (ctx, in);
diff --git a/tests/gpg/t-keylist-sig.c b/tests/gpg/t-keylist-sig.c
index ec30624..fdec7ca 100644
--- a/tests/gpg/t-keylist-sig.c
+++ b/tests/gpg/t-keylist-sig.c
@@ -36,20 +36,20 @@
struct
{
- char *fpr;
- char *sec_keyid;
+ const char *fpr;
+ const char *sec_keyid;
struct
{
- char *name;
- char *comment;
- char *email;
+ const char *name;
+ const char *comment;
+ const char *email;
struct
{
gpgme_pubkey_algo_t algo;
- char *keyid;
- char *name;
- char *comment;
- char *email;
+ const char *keyid;
+ const char *name;
+ const char *comment;
+ const char *email;
unsigned int sig_class;
int exportable;
} sig;
@@ -72,7 +72,7 @@ keys[] =
int
-main (int argc, char **argv)
+main (void)
{
gpgme_error_t err;
gpgme_ctx_t ctx;
diff --git a/tests/gpg/t-keylist.c b/tests/gpg/t-keylist.c
index 67844cb..6ee023c 100644
--- a/tests/gpg/t-keylist.c
+++ b/tests/gpg/t-keylist.c
@@ -3,17 +3,17 @@
Copyright (C) 2001, 2003, 2004 g10 Code GmbH
This file is part of GPGME.
-
+
GPGME is free software; you can redistribute it and/or modify it
under the terms of the GNU Lesser General Public License as
published by the Free Software Foundation; either version 2.1 of
the License, or (at your option) any later version.
-
+
GPGME is distributed in the hope that it will be useful, but
WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
Lesser General Public License for more details.
-
+
You should have received a copy of the GNU Lesser General Public
License along with this program; if not, write to the Free Software
Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
@@ -36,13 +36,13 @@
struct key_info_s
{
- char *fpr;
- char *sec_keyid;
+ const char *fpr;
+ const char *sec_keyid;
struct
{
- char *name;
- char *comment;
- char *email;
+ const char *name;
+ const char *comment;
+ const char *email;
} uid[3];
int n_subkeys;
void (*misc_check)(struct key_info_s *keyinfo, gpgme_key_t key);
@@ -121,7 +121,7 @@ struct key_info_s keys[] =
};
-int
+int
main (int argc, char **argv)
{
gpgme_error_t err;
@@ -132,6 +132,9 @@ main (int argc, char **argv)
int n;
gpgme_subkey_t subkey;
+ (void)argc;
+ (void)argv;
+
init_gpgme (GPGME_PROTOCOL_OpenPGP);
err = gpgme_new (&ctx);
@@ -139,7 +142,7 @@ main (int argc, char **argv)
err = gpgme_op_keylist_start (ctx, NULL, 0);
fail_if_err (err);
-
+
while (!(err = gpgme_op_keylist_next (ctx, &key)))
{
if (!keys[i].fpr)
@@ -223,7 +226,7 @@ main (int argc, char **argv)
exit (1);
}
- for (n=0, subkey = key->subkeys; subkey; subkey = subkey->next)
+ for (n=0, subkey = key->subkeys; subkey; subkey = subkey->next)
n++;
if (!n || n-1 != keys[i].n_subkeys)
{
@@ -583,7 +586,7 @@ check_whisky (struct key_info_s *keyinfo, gpgme_key_t key)
{
const char *name = keyinfo->uid[0].name;
gpgme_subkey_t sub1, sub2;
-
+
sub1 = key->subkeys->next->next;
sub2 = sub1->next;
diff --git a/tests/gpg/t-sig-notation.c b/tests/gpg/t-sig-notation.c
index 7345a52..aee7551 100644
--- a/tests/gpg/t-sig-notation.c
+++ b/tests/gpg/t-sig-notation.c
@@ -2,17 +2,17 @@
Copyright (C) 2005 g10 Code GmbH
This file is part of GPGME.
-
+
GPGME is free software; you can redistribute it and/or modify it
under the terms of the GNU Lesser General Public License as
published by the Free Software Foundation; either version 2.1 of
the License, or (at your option) any later version.
-
+
GPGME is distributed in the hope that it will be useful, but
WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
Lesser General Public License for more details.
-
+
You should have received a copy of the GNU Lesser General Public
License along with this program; if not, write to the Free Software
Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
@@ -24,6 +24,7 @@
#include <config.h>
#endif
+#include <assert.h>
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
@@ -33,19 +34,24 @@
#include "t-support.h"
+
+/* GnuPG prior to 2.1.13 did not report the critical flag
+ correctly. */
+int have_correct_sig_data;
+
static struct {
const char *name;
const char *value;
gpgme_sig_notation_flags_t flags;
int seen;
-} expected_notations[] = {
+} expected_notations[] = {
{ "laughing@me",
"Just Squeeze Me",
GPGME_SIG_NOTATION_HUMAN_READABLE },
{ "preferred-email-encoding@pgp.com",
"pgpmime",
GPGME_SIG_NOTATION_HUMAN_READABLE | GPGME_SIG_NOTATION_CRITICAL },
- { NULL,
+ { NULL,
"http://www.gnu.org/policy/",
0 }
};
@@ -55,7 +61,7 @@ check_result (gpgme_verify_result_t result)
{
int i;
gpgme_sig_notation_t r;
-
+
gpgme_signature_t sig;
sig = result->signatures;
@@ -68,7 +74,7 @@ check_result (gpgme_verify_result_t result)
for (i=0; i < DIM(expected_notations); i++ )
expected_notations[i].seen = 0;
-
+
for (r = result->signatures->notations; r; r = r->next)
{
int any = 0;
@@ -84,10 +90,16 @@ check_result (gpgme_verify_result_t result)
&& !strcmp (r->value, expected_notations[i].value)
&& r->value_len == strlen (expected_notations[i].value)
&& r->flags
- == (expected_notations[i].flags & ~GPGME_SIG_NOTATION_CRITICAL)
+ == (have_correct_sig_data
+ ? expected_notations[i].flags
+ : expected_notations[i].flags
+ & ~GPGME_SIG_NOTATION_CRITICAL)
&& r->human_readable
== !!(r->flags & GPGME_SIG_NOTATION_HUMAN_READABLE)
- && r->critical == 0)
+ && r->critical
+ == (have_correct_sig_data
+ ? !!(r->flags & GPGME_SIG_NOTATION_CRITICAL)
+ : 0))
{
expected_notations[i].seen++;
any++;
@@ -112,7 +124,7 @@ check_result (gpgme_verify_result_t result)
}
-int
+int
main (int argc, char *argv[])
{
gpgme_ctx_t ctx;
@@ -121,9 +133,28 @@ main (int argc, char *argv[])
gpgme_verify_result_t result;
char *agent_info;
int i;
+ gpgme_engine_info_t engine_info;
+
+ (void)argc;
+ (void)argv;
init_gpgme (GPGME_PROTOCOL_OpenPGP);
+ err = gpgme_get_engine_info (&engine_info);
+ fail_if_err (err);
+ for (; engine_info; engine_info = engine_info->next)
+ if (engine_info->protocol == GPGME_PROTOCOL_OpenPGP)
+ break;
+ assert (engine_info);
+
+ /* GnuPG prior to 2.1.13 did not report the critical flag
+ correctly. */
+ have_correct_sig_data =
+ ! (strncmp ("1.", engine_info->version, 2) == 0
+ || (strncmp ("2.1.1", engine_info->version, 5) == 0
+ && (engine_info->version[5] == 0
+ || engine_info->version[5] < '3')));
+
err = gpgme_new (&ctx);
fail_if_err (err);
@@ -144,7 +175,7 @@ main (int argc, char *argv[])
expected_notations[i].flags);
fail_if_err (err);
}
-
+
err = gpgme_op_sign (ctx, in, out, GPGME_SIG_MODE_NORMAL);
fail_if_err (err);
diff --git a/tests/gpg/t-sign.c b/tests/gpg/t-sign.c
index bdd3323..66f54ea 100644
--- a/tests/gpg/t-sign.c
+++ b/tests/gpg/t-sign.c
@@ -3,17 +3,17 @@
Copyright (C) 2001, 2003, 2004 g10 Code GmbH
This file is part of GPGME.
-
+
GPGME is free software; you can redistribute it and/or modify it
under the terms of the GNU Lesser General Public License as
published by the Free Software Foundation; either version 2.1 of
the License, or (at your option) any later version.
-
+
GPGME is distributed in the hope that it will be useful, but
WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
Lesser General Public License for more details.
-
+
You should have received a copy of the GNU Lesser General Public
License along with this program; if not, write to the Free Software
Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
@@ -82,7 +82,7 @@ check_result (gpgme_sign_result_t result, gpgme_sig_mode_t type)
}
-int
+int
main (int argc, char **argv)
{
gpgme_ctx_t ctx;
@@ -91,6 +91,9 @@ main (int argc, char **argv)
gpgme_sign_result_t result;
char *agent_info;
+ (void)argc;
+ (void)argv;
+
init_gpgme (GPGME_PROTOCOL_OpenPGP);
err = gpgme_new (&ctx);
@@ -102,7 +105,7 @@ main (int argc, char **argv)
gpgme_set_textmode (ctx, 1);
gpgme_set_armor (ctx, 1);
-
+
#if 0
{
gpgme_key_t akey;
@@ -126,8 +129,8 @@ main (int argc, char **argv)
check_result (result, GPGME_SIG_MODE_NORMAL);
print_data (out);
gpgme_data_release (out);
-
- /* Now a detached signature. */
+
+ /* Now a detached signature. */
gpgme_data_seek (in, 0, SEEK_SET);
err = gpgme_data_new (&out);
fail_if_err (err);
diff --git a/tests/gpg/t-signers.c b/tests/gpg/t-signers.c
index c75c1d4..b1eb191 100644
--- a/tests/gpg/t-signers.c
+++ b/tests/gpg/t-signers.c
@@ -3,17 +3,17 @@
Copyright (C) 2001, 2003, 2004 g10 Code GmbH
This file is part of GPGME.
-
+
GPGME is free software; you can redistribute it and/or modify it
under the terms of the GNU Lesser General Public License as
published by the Free Software Foundation; either version 2.1 of
the License, or (at your option) any later version.
-
+
GPGME is distributed in the hope that it will be useful, but
WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
Lesser General Public License for more details.
-
+
You should have received a copy of the GNU Lesser General Public
License along with this program; if not, write to the Free Software
Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
@@ -93,7 +93,7 @@ check_result (gpgme_sign_result_t result, gpgme_sig_mode_t type)
}
-int
+int
main (int argc, char *argv[])
{
gpgme_ctx_t ctx;
@@ -103,6 +103,9 @@ main (int argc, char *argv[])
gpgme_sign_result_t result;
char *agent_info;
+ (void)argc;
+ (void)argv;
+
init_gpgme (GPGME_PROTOCOL_OpenPGP);
err = gpgme_new (&ctx);
@@ -141,7 +144,7 @@ main (int argc, char *argv[])
check_result (result, GPGME_SIG_MODE_NORMAL);
print_data (out);
gpgme_data_release (out);
-
+
/* Now a detached signature. */
gpgme_data_seek (in, 0, SEEK_SET);
err = gpgme_data_new (&out);
@@ -152,7 +155,7 @@ main (int argc, char *argv[])
check_result (result, GPGME_SIG_MODE_DETACH);
print_data (out);
gpgme_data_release (out);
-
+
/* And finally a cleartext signature. */
gpgme_data_seek (in, 0, SEEK_SET);
err = gpgme_data_new (&out);
@@ -161,10 +164,10 @@ main (int argc, char *argv[])
fail_if_err (err);
result = gpgme_op_sign_result (ctx);
check_result (result, GPGME_SIG_MODE_CLEAR);
- print_data (out);
+ print_data (out);
gpgme_data_release (out);
gpgme_data_seek (in, 0, SEEK_SET);
-
+
gpgme_data_release (in);
gpgme_release (ctx);
diff --git a/tests/gpg/t-support.h b/tests/gpg/t-support.h
index 6a18b5c..db69dd0 100644
--- a/tests/gpg/t-support.h
+++ b/tests/gpg/t-support.h
@@ -3,17 +3,17 @@
Copyright (C) 2001, 2002, 2003, 2004 g10 Code GmbH
This file is part of GPGME.
-
+
GPGME is free software; you can redistribute it and/or modify it
under the terms of the GNU Lesser General Public License as
published by the Free Software Foundation; either version 2.1 of
the License, or (at your option) any later version.
-
+
GPGME is distributed in the hope that it will be useful, but
WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
Lesser General Public License for more details.
-
+
You should have received a copy of the GNU Lesser General Public
License along with this program; if not, write to the Free Software
Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
@@ -61,7 +61,7 @@ print_data (gpgme_data_t dh)
#define BUF_SIZE 512
char buf[BUF_SIZE + 1];
int ret;
-
+
ret = gpgme_data_seek (dh, 0, SEEK_SET);
if (ret)
fail_if_err (gpgme_err_code_from_errno (errno));
@@ -76,27 +76,25 @@ gpgme_error_t
passphrase_cb (void *opaque, const char *uid_hint, const char *passphrase_info,
int last_was_bad, int fd)
{
-#ifdef HAVE_W32_SYSTEM
- DWORD written;
- WriteFile ((HANDLE) fd, "abc\n", 4, &written, 0);
-#else
int res;
- char *pass = "abc\n";
+ char pass[] = "abc\n";
int passlen = strlen (pass);
int off = 0;
+ (void)opaque;
+ (void)uid_hint;
+ (void)passphrase_info;
+ (void)last_was_bad;
+
do
{
- res = write (fd, &pass[off], passlen - off);
+ res = gpgme_io_write (fd, &pass[off], passlen - off);
if (res > 0)
off += res;
}
while (res > 0 && off != passlen);
return off == passlen ? 0 : gpgme_error_from_errno (errno);
-#endif
-
- return 0;
}
@@ -109,7 +107,7 @@ make_filename (const char *fname)
if (!srcdir)
srcdir = ".";
buf = malloc (strlen(srcdir) + strlen(fname) + 2);
- if (!buf)
+ if (!buf)
exit (8);
strcpy (buf, srcdir);
strcat (buf, "/");
diff --git a/tests/gpg/t-thread1.c b/tests/gpg/t-thread1.c
index 86ea51a..2f9ee5d 100644
--- a/tests/gpg/t-thread1.c
+++ b/tests/gpg/t-thread1.c
@@ -3,17 +3,17 @@
Copyright (C) 2001, 2003, 2004 g10 Code GmbH
This file is part of GPGME.
-
+
GPGME is free software; you can redistribute it and/or modify it
under the terms of the GNU Lesser General Public License as
published by the Free Software Foundation; either version 2.1 of
the License, or (at your option) any later version.
-
+
GPGME is distributed in the hope that it will be useful, but
WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
Lesser General Public License for more details.
-
+
You should have received a copy of the GNU Lesser General Public
License along with this program; if not, write to the Free Software
Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
@@ -68,7 +68,7 @@ thread_one (void *name)
err = gpgme_get_key (ctx, "D695676BDCEDCC2CDD6152BCFE180B1DA9E3B0B2",
&key[1], 0);
fail_if_err (err);
-
+
err = gpgme_op_encrypt (ctx, key, GPGME_ENCRYPT_ALWAYS_TRUST, in, out);
fail_if_err (err);
result = gpgme_op_encrypt_result (ctx);
@@ -94,7 +94,7 @@ void *
thread_two (void *name)
{
int i;
- const char *cipher_1_asc = make_filename ("cipher-1.asc");
+ char *cipher_1_asc = make_filename ("cipher-1.asc");
char *agent_info;
agent_info = getenv("GPG_AGENT_INFO");
@@ -119,7 +119,7 @@ thread_two (void *name)
err = gpgme_data_new (&out);
fail_if_err (err);
-
+
err = gpgme_op_decrypt (ctx, in, out);
fail_if_err (err);
result = gpgme_op_decrypt_result (ctx);
@@ -130,24 +130,27 @@ thread_two (void *name)
exit (1);
}
printf ("Decrypt %s %i\n", (char *) name, i);
-
+
gpgme_data_release (in);
gpgme_data_release (out);
gpgme_release (ctx);
}
+ free (cipher_1_asc);
return NULL;
}
-int
-main (int argc, char *argv[])
+int
+main (void)
{
pthread_t tone;
pthread_t ttwo;
+ char arg_A[] = "A";
+ char arg_B[] = "B";
init_gpgme (GPGME_PROTOCOL_OpenPGP);
- pthread_create (&tone, NULL, thread_one, "A");
- pthread_create (&ttwo, NULL, thread_two, "B");
+ pthread_create (&tone, NULL, thread_one, arg_A);
+ pthread_create (&ttwo, NULL, thread_two, arg_B);
pthread_join (tone, NULL);
pthread_join (ttwo, NULL);
diff --git a/tests/gpg/t-trustlist.c b/tests/gpg/t-trustlist.c
index 5d24518..eeab85e 100644
--- a/tests/gpg/t-trustlist.c
+++ b/tests/gpg/t-trustlist.c
@@ -3,17 +3,17 @@
Copyright (C) 2001, 2003, 2004 g10 Code GmbH
This file is part of GPGME.
-
+
GPGME is free software; you can redistribute it and/or modify it
under the terms of the GNU Lesser General Public License as
published by the Free Software Foundation; either version 2.1 of
the License, or (at your option) any later version.
-
+
GPGME is distributed in the hope that it will be useful, but
WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
Lesser General Public License for more details.
-
+
You should have received a copy of the GNU Lesser General Public
License along with this program; if not, write to the Free Software
Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
@@ -34,13 +34,16 @@
#include "t-support.h"
-int
+int
main (int argc, char *argv[])
{
gpgme_ctx_t ctx;
gpgme_error_t err;
gpgme_trust_item_t item;
+ (void)argc;
+ (void)argv;
+
init_gpgme (GPGME_PROTOCOL_OpenPGP);
err = gpgme_new (&ctx);
diff --git a/tests/gpg/t-verify.c b/tests/gpg/t-verify.c
index dceabac..9842d3a 100644
--- a/tests/gpg/t-verify.c
+++ b/tests/gpg/t-verify.c
@@ -3,17 +3,17 @@
Copyright (C) 2001, 2002, 2003, 2004 g10 Code GmbH
This file is part of GPGME.
-
+
GPGME is free software; you can redistribute it and/or modify it
under the terms of the GNU Lesser General Public License as
published by the Free Software Foundation; either version 2.1 of
the License, or (at your option) any later version.
-
+
GPGME is distributed in the hope that it will be useful, but
WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
Lesser General Public License for more details.
-
+
You should have received a copy of the GNU Lesser General Public
License along with this program; if not, write to the Free Software
Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
@@ -77,7 +77,7 @@ static const char test_sig2[] =
"-----END PGP MESSAGE-----\n";
/* A message with a prepended but unsigned plaintext packet. */
-static const char double_plaintext_sig[] =
+static const char double_plaintext_sig[] =
"-----BEGIN PGP MESSAGE-----\n"
"\n"
"rDRiCmZvb2Jhci50eHRF4pxNVGhpcyBpcyBteSBzbmVha3kgcGxhaW50ZXh0IG1l\n"
@@ -92,7 +92,8 @@ static const char double_plaintext_sig[] =
static void
-check_result (gpgme_verify_result_t result, unsigned int summary, char *fpr,
+check_result (gpgme_verify_result_t result, unsigned int summary,
+ const char *fpr,
gpgme_error_t status, int notation)
{
gpgme_signature_t sig;
@@ -135,7 +136,7 @@ check_result (gpgme_verify_result_t result, unsigned int summary, char *fpr,
" das waren Umlaute und jetzt ein prozent%-Zeichen" },
{ "foobar.1",
"this is a notation data with 2 lines" },
- { NULL,
+ { NULL,
"http://www.gu.org/policy/" }
};
int i;
@@ -201,7 +202,7 @@ check_result (gpgme_verify_result_t result, unsigned int summary, char *fpr,
}
-int
+int
main (int argc, char *argv[])
{
gpgme_ctx_t ctx;
@@ -209,6 +210,9 @@ main (int argc, char *argv[])
gpgme_data_t sig, text;
gpgme_verify_result_t result;
+ (void)argc;
+ (void)argv;
+
init_gpgme (GPGME_PROTOCOL_OpenPGP);
err = gpgme_new (&ctx);
diff --git a/tests/gpg/t-wait.c b/tests/gpg/t-wait.c
index e58adad..352b9bf 100644
--- a/tests/gpg/t-wait.c
+++ b/tests/gpg/t-wait.c
@@ -3,17 +3,17 @@
Copyright (C) 2001, 2002, 2003, 2004, 2005, 2007 g10 Code GmbH
This file is part of GPGME.
-
+
GPGME is free software; you can redistribute it and/or modify it
under the terms of the GNU Lesser General Public License as
published by the Free Software Foundation; either version 2.1 of
the License, or (at your option) any later version.
-
+
GPGME is distributed in the hope that it will be useful, but
WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
Lesser General Public License for more details.
-
+
You should have received a copy of the GNU Lesser General Public
License along with this program; if not, write to the Free Software
Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
@@ -38,8 +38,8 @@
#include "t-support.h"
-int
-main (int argc, char *argv[])
+int
+main (void)
{
gpgme_ctx_t ctx;
gpgme_error_t err;
diff --git a/tests/gpgsm/Makefile.in b/tests/gpgsm/Makefile.in
index edcd1a1..d653b96 100644
--- a/tests/gpgsm/Makefile.in
+++ b/tests/gpgsm/Makefile.in
@@ -106,12 +106,16 @@ DIST_COMMON = $(srcdir)/Makefile.in $(srcdir)/Makefile.am \
$(top_srcdir)/build-aux/mkinstalldirs \
$(top_srcdir)/build-aux/depcomp $(noinst_HEADERS)
ACLOCAL_M4 = $(top_srcdir)/aclocal.m4
-am__aclocal_m4_deps = $(top_srcdir)/m4/glib-2.0.m4 \
- $(top_srcdir)/m4/glibc21.m4 $(top_srcdir)/m4/gnupg-ttyname.m4 \
+am__aclocal_m4_deps = $(top_srcdir)/m4/ax_cxx_compile_stdcxx.m4 \
+ $(top_srcdir)/m4/ax_pkg_swig.m4 \
+ $(top_srcdir)/m4/ax_python_devel.m4 \
+ $(top_srcdir)/m4/glib-2.0.m4 $(top_srcdir)/m4/glibc21.m4 \
+ $(top_srcdir)/m4/gnupg-ttyname.m4 \
$(top_srcdir)/m4/gpg-error.m4 $(top_srcdir)/m4/libassuan.m4 \
$(top_srcdir)/m4/libtool.m4 $(top_srcdir)/m4/ltoptions.m4 \
$(top_srcdir)/m4/ltsugar.m4 $(top_srcdir)/m4/ltversion.m4 \
- $(top_srcdir)/m4/lt~obsolete.m4 $(top_srcdir)/acinclude.m4 \
+ $(top_srcdir)/m4/lt~obsolete.m4 $(top_srcdir)/m4/pkg.m4 \
+ $(top_srcdir)/m4/qt.m4 $(top_srcdir)/acinclude.m4 \
$(top_srcdir)/configure.ac
am__configure_deps = $(am__aclocal_m4_deps) $(CONFIGURE_DEPENDENCIES) \
$(ACLOCAL_M4)
@@ -269,6 +273,7 @@ BUILD_REVISION = @BUILD_REVISION@
BUILD_TIMESTAMP = @BUILD_TIMESTAMP@
CC = @CC@
CCDEPMODE = @CCDEPMODE@
+CC_FOR_BUILD = @CC_FOR_BUILD@
CFLAGS = @CFLAGS@
CPP = @CPP@
CPPFLAGS = @CPPFLAGS@
@@ -280,12 +285,14 @@ CYGPATH_W = @CYGPATH_W@
DEFS = @DEFS@
DEPDIR = @DEPDIR@
DLLTOOL = @DLLTOOL@
+DOXYGEN = @DOXYGEN@
DSYMUTIL = @DSYMUTIL@
DUMPBIN = @DUMPBIN@
ECHO_C = @ECHO_C@
ECHO_N = @ECHO_N@
ECHO_T = @ECHO_T@
EGREP = @EGREP@
+ENABLED_LANGUAGES = @ENABLED_LANGUAGES@
EXEEXT = @EXEEXT@
FGREP = @FGREP@
GITLOG_TO_CHANGELOG = @GITLOG_TO_CHANGELOG@
@@ -296,15 +303,23 @@ GLIB_LIBS = @GLIB_LIBS@
GLIB_MKENUMS = @GLIB_MKENUMS@
GOBJECT_QUERY = @GOBJECT_QUERY@
GPGME_CONFIG_API_VERSION = @GPGME_CONFIG_API_VERSION@
+GPGME_CONFIG_AVAIL_LANG = @GPGME_CONFIG_AVAIL_LANG@
GPGME_CONFIG_CFLAGS = @GPGME_CONFIG_CFLAGS@
GPGME_CONFIG_HOST = @GPGME_CONFIG_HOST@
GPGME_CONFIG_LIBS = @GPGME_CONFIG_LIBS@
+GPGME_QTTEST_CFLAGS = @GPGME_QTTEST_CFLAGS@
+GPGME_QTTEST_LIBS = @GPGME_QTTEST_LIBS@
+GPGME_QT_CFLAGS = @GPGME_QT_CFLAGS@
+GPGME_QT_LIBS = @GPGME_QT_LIBS@
GPG_ERROR_CFLAGS = @GPG_ERROR_CFLAGS@
GPG_ERROR_CONFIG = @GPG_ERROR_CONFIG@
GPG_ERROR_LIBS = @GPG_ERROR_LIBS@
GPG_ERROR_MT_CFLAGS = @GPG_ERROR_MT_CFLAGS@
GPG_ERROR_MT_LIBS = @GPG_ERROR_MT_LIBS@
+GRAPHVIZ = @GRAPHVIZ@
GREP = @GREP@
+HAVE_CXX11 = @HAVE_CXX11@
+HAVE_DOT = @HAVE_DOT@
INSTALL = @INSTALL@
INSTALL_DATA = @INSTALL_DATA@
INSTALL_PROGRAM = @INSTALL_PROGRAM@
@@ -315,10 +330,16 @@ LDFLAGS = @LDFLAGS@
LIBASSUAN_CFLAGS = @LIBASSUAN_CFLAGS@
LIBASSUAN_CONFIG = @LIBASSUAN_CONFIG@
LIBASSUAN_LIBS = @LIBASSUAN_LIBS@
+LIBGPGMEPP_LT_AGE = @LIBGPGMEPP_LT_AGE@
+LIBGPGMEPP_LT_CURRENT = @LIBGPGMEPP_LT_CURRENT@
+LIBGPGMEPP_LT_REVISION = @LIBGPGMEPP_LT_REVISION@
LIBGPGME_LT_AGE = @LIBGPGME_LT_AGE@
LIBGPGME_LT_CURRENT = @LIBGPGME_LT_CURRENT@
LIBGPGME_LT_REVISION = @LIBGPGME_LT_REVISION@
LIBOBJS = @LIBOBJS@
+LIBQGPGME_LT_AGE = @LIBQGPGME_LT_AGE@
+LIBQGPGME_LT_CURRENT = @LIBQGPGME_LT_CURRENT@
+LIBQGPGME_LT_REVISION = @LIBQGPGME_LT_REVISION@
LIBS = @LIBS@
LIBTOOL = @LIBTOOL@
LIPO = @LIPO@
@@ -328,6 +349,8 @@ MAINT = @MAINT@
MAKEINFO = @MAKEINFO@
MANIFEST_TOOL = @MANIFEST_TOOL@
MKDIR_P = @MKDIR_P@
+MOC = @MOC@
+MOC2 = @MOC2@
NEED__FILE_OFFSET_BITS = @NEED__FILE_OFFSET_BITS@
NM = @NM@
NMEDIT = @NMEDIT@
@@ -344,14 +367,27 @@ PACKAGE_URL = @PACKAGE_URL@
PACKAGE_VERSION = @PACKAGE_VERSION@
PATH_SEPARATOR = @PATH_SEPARATOR@
PKG_CONFIG = @PKG_CONFIG@
-QT4_CORE_CFLAGS = @QT4_CORE_CFLAGS@
-QT4_CORE_LIBS = @QT4_CORE_LIBS@
+PYTHON = @PYTHON@
+PYTHONS = @PYTHONS@
+PYTHON_CPPFLAGS = @PYTHON_CPPFLAGS@
+PYTHON_EXEC_PREFIX = @PYTHON_EXEC_PREFIX@
+PYTHON_EXTRA_LDFLAGS = @PYTHON_EXTRA_LDFLAGS@
+PYTHON_EXTRA_LIBS = @PYTHON_EXTRA_LIBS@
+PYTHON_LDFLAGS = @PYTHON_LDFLAGS@
+PYTHON_PLATFORM = @PYTHON_PLATFORM@
+PYTHON_PREFIX = @PYTHON_PREFIX@
+PYTHON_SITE_PKG = @PYTHON_SITE_PKG@
+PYTHON_VERSION = @PYTHON_VERSION@
+PYTHON_VERSIONS = @PYTHON_VERSIONS@
+QTCHOOSER = @QTCHOOSER@
RANLIB = @RANLIB@
RC = @RC@
SED = @SED@
SET_MAKE = @SET_MAKE@
SHELL = @SHELL@
STRIP = @STRIP@
+SWIG = @SWIG@
+SWIG_LIB = @SWIG_LIB@
SYSROOT = @SYSROOT@
VERSION = @VERSION@
VERSION_NUMBER = @VERSION_NUMBER@
@@ -400,9 +436,13 @@ mandir = @mandir@
mkdir_p = @mkdir_p@
oldincludedir = @oldincludedir@
pdfdir = @pdfdir@
+pkgpyexecdir = @pkgpyexecdir@
+pkgpythondir = @pkgpythondir@
prefix = @prefix@
program_transform_name = @program_transform_name@
psdir = @psdir@
+pyexecdir = @pyexecdir@
+pythondir = @pythondir@
sbindir = @sbindir@
sharedstatedir = @sharedstatedir@
srcdir = @srcdir@
diff --git a/tests/gpgsm/t-decrypt.c b/tests/gpgsm/t-decrypt.c
index 654c7e1..658809c 100644
--- a/tests/gpgsm/t-decrypt.c
+++ b/tests/gpgsm/t-decrypt.c
@@ -3,17 +3,17 @@
Copyright (C) 2001, 2003, 2004 g10 Code GmbH
This file is part of GPGME.
-
+
GPGME is free software; you can redistribute it and/or modify it
under the terms of the GNU Lesser General Public License as
published by the Free Software Foundation; either version 2.1 of
the License, or (at your option) any later version.
-
+
GPGME is distributed in the hope that it will be useful, but
WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
Lesser General Public License for more details.
-
+
You should have received a copy of the GNU Lesser General Public
License along with this program; if not, write to the Free Software
Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
@@ -48,8 +48,8 @@ static const char test_cip1[] =
"-----END CMS OBJECT-----\n";
-int
-main (int argc, char *argv[])
+int
+main (void)
{
gpgme_ctx_t ctx;
gpgme_error_t err;
@@ -78,7 +78,7 @@ main (int argc, char *argv[])
exit (1);
}
print_data (out);
-
+
gpgme_data_release (in);
gpgme_data_release (out);
gpgme_release (ctx);
diff --git a/tests/gpgsm/t-encrypt.c b/tests/gpgsm/t-encrypt.c
index 45c772b..50c7a33 100644
--- a/tests/gpgsm/t-encrypt.c
+++ b/tests/gpgsm/t-encrypt.c
@@ -3,17 +3,17 @@
Copyright (C) 2001, 2002, 2003, 2004 g10 Code GmbH
This file is part of GPGME.
-
+
GPGME is free software; you can redistribute it and/or modify it
under the terms of the GNU Lesser General Public License as
published by the Free Software Foundation; either version 2.1 of
the License, or (at your option) any later version.
-
+
GPGME is distributed in the hope that it will be useful, but
WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
Lesser General Public License for more details.
-
+
You should have received a copy of the GNU Lesser General Public
License along with this program; if not, write to the Free Software
Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
@@ -33,8 +33,8 @@
#include "t-support.h"
-int
-main (int argc, char **argv)
+int
+main (void)
{
gpgme_ctx_t ctx;
gpgme_error_t err;
@@ -54,7 +54,7 @@ main (int argc, char **argv)
err = gpgme_data_new (&out);
fail_if_err (err);
-
+
err = gpgme_get_key (ctx, "3CF405464F66ED4A7DF45BBDD1E4282E33BDB76E",
&key[0], 0);
fail_if_err (err);
diff --git a/tests/gpgsm/t-export.c b/tests/gpgsm/t-export.c
index d8856f2..120df6b 100644
--- a/tests/gpgsm/t-export.c
+++ b/tests/gpgsm/t-export.c
@@ -3,17 +3,17 @@
Copyright (C) 2001, 2003, 2004 g10 Code GmbH
This file is part of GPGME.
-
+
GPGME is free software; you can redistribute it and/or modify it
under the terms of the GNU Lesser General Public License as
published by the Free Software Foundation; either version 2.1 of
the License, or (at your option) any later version.
-
+
GPGME is distributed in the hope that it will be useful, but
WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
Lesser General Public License for more details.
-
+
You should have received a copy of the GNU Lesser General Public
License along with this program; if not, write to the Free Software
Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
@@ -34,15 +34,15 @@
#include "t-support.h"
-int
-main (int argc, char *argv[])
+int
+main (void)
{
gpgme_ctx_t ctx;
gpgme_error_t err;
gpgme_data_t out;
const char *pattern1[] = { "DFN Top Level Certification Authority", NULL };
const char *pattern2[] = { "3CF405464F66ED4A7DF45BBDD1E4282E33BDB76E",
- "DFN Server Certification Authority",
+ "DFN Server Certification Authority",
NULL };
init_gpgme (GPGME_PROTOCOL_CMS);
diff --git a/tests/gpgsm/t-genkey.c b/tests/gpgsm/t-genkey.c
index 9de9d54..fb05034 100644
--- a/tests/gpgsm/t-genkey.c
+++ b/tests/gpgsm/t-genkey.c
@@ -3,17 +3,17 @@
Copyright (C) 2001, 2003, 2004 g10 Code GmbH
This file is part of GPGME.
-
+
GPGME is free software; you can redistribute it and/or modify it
under the terms of the GNU Lesser General Public License as
published by the Free Software Foundation; either version 2.1 of
the License, or (at your option) any later version.
-
+
GPGME is distributed in the hope that it will be useful, but
WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
Lesser General Public License for more details.
-
+
You should have received a copy of the GNU Lesser General Public
License along with this program; if not, write to the Free Software
Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
@@ -40,6 +40,8 @@ static int progress_called;
static void
progress (void *self, const char *what, int type, int current, int total)
{
+ (void)self;
+
if (!strcmp (what, "primegen") && !current && !total
&& (type == '.' || type == '+' || type == '!'
|| type == '^' || type == '<' || type == '>'))
@@ -57,8 +59,8 @@ progress (void *self, const char *what, int type, int current, int total)
}
-int
-main (int argc, char *argv[])
+int
+main (void)
{
gpgme_ctx_t ctx;
gpgme_error_t err;
@@ -83,7 +85,7 @@ main (int argc, char *argv[])
gpgme_set_armor (ctx, 1);
gpgme_set_progress_cb (ctx, progress, NULL);
-
+
err = gpgme_op_genkey (ctx, parms, certreq, NULL);
fail_if_err (err);
diff --git a/tests/gpgsm/t-import.c b/tests/gpgsm/t-import.c
index 2d23779..a8dfcca 100644
--- a/tests/gpgsm/t-import.c
+++ b/tests/gpgsm/t-import.c
@@ -3,17 +3,17 @@
Copyright (C) 2001, 2003, 2004 g10 Code GmbH
This file is part of GPGME.
-
+
GPGME is free software; you can redistribute it and/or modify it
under the terms of the GNU Lesser General Public License as
published by the Free Software Foundation; either version 2.1 of
the License, or (at your option) any later version.
-
+
GPGME is distributed in the hope that it will be useful, but
WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
Lesser General Public License for more details.
-
+
You should have received a copy of the GNU Lesser General Public
License along with this program; if not, write to the Free Software
Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
@@ -36,9 +36,11 @@
void
-check_result (gpgme_import_result_t result, char *fpr, int total,
+check_result (gpgme_import_result_t result, const char *fpr, int total,
int total_stat)
{
+ (void)fpr;
+
if (result->considered != total)
{
fprintf (stderr, "Unexpected number of considered keys %i\n",
@@ -118,14 +120,14 @@ check_result (gpgme_import_result_t result, char *fpr, int total,
result->not_imported);
exit (1);
}
-
+
{
int n;
gpgme_import_status_t r;
for (n=0, r=result->imports; r; r=r->next)
n++;
-
+
if (n != total_stat)
{
fprintf (stderr, "Unexpected number of status reports\n");
@@ -135,24 +137,25 @@ check_result (gpgme_import_result_t result, char *fpr, int total,
}
-int
-main (int argc, char **argv)
+int
+main (void)
{
gpgme_ctx_t ctx;
gpgme_error_t err;
gpgme_data_t in;
gpgme_import_result_t result;
- const char *cert_1 = make_filename ("cert_dfn_pca01.der");
- const char *cert_2 = make_filename ("cert_dfn_pca15.der");
+ char *cert_1 = make_filename ("cert_dfn_pca01.der");
+ char *cert_2 = make_filename ("cert_dfn_pca15.der");
init_gpgme (GPGME_PROTOCOL_CMS);
err = gpgme_new (&ctx);
fail_if_err (err);
-
+
gpgme_set_protocol (ctx, GPGME_PROTOCOL_CMS);
err = gpgme_data_new_from_file (&in, cert_1, 1);
+ free (cert_1);
fail_if_err (err);
err = gpgme_op_import (ctx, in);
@@ -162,6 +165,7 @@ main (int argc, char **argv)
gpgme_data_release (in);
err = gpgme_data_new_from_file (&in, cert_2, 1);
+ free (cert_2);
fail_if_err (err);
err = gpgme_op_import (ctx, in);
diff --git a/tests/gpgsm/t-keylist.c b/tests/gpgsm/t-keylist.c
index bebd9d6..314109c 100644
--- a/tests/gpgsm/t-keylist.c
+++ b/tests/gpgsm/t-keylist.c
@@ -3,17 +3,17 @@
Copyright (C) 2001, 2003, 2004 g10 Code GmbH
This file is part of GPGME.
-
+
GPGME is free software; you can redistribute it and/or modify it
under the terms of the GNU Lesser General Public License as
published by the Free Software Foundation; either version 2.1 of
the License, or (at your option) any later version.
-
+
GPGME is distributed in the hope that it will be useful, but
WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
Lesser General Public License for more details.
-
+
You should have received a copy of the GNU Lesser General Public
License along with this program; if not, write to the Free Software
Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
@@ -36,15 +36,15 @@
struct
{
- char *fpr;
+ const char *fpr;
int secret;
long timestamp;
long expires;
- char *issuer_serial;
- char *issuer_name;
- char *chain_id;
- char *uid;
- char *email;
+ const char *issuer_serial;
+ const char *issuer_name;
+ const char *chain_id;
+ const char *uid;
+ const char *email;
gpgme_validity_t validity;
unsigned int key_length;
}
@@ -80,8 +80,8 @@ keys[] =
};
-int
-main (int argc, char **argv)
+int
+main (void)
{
gpgme_error_t err;
gpgme_ctx_t ctx;
@@ -97,7 +97,7 @@ main (int argc, char **argv)
err = gpgme_op_keylist_start (ctx, NULL, 0);
fail_if_err (err);
-
+
while (!(err = gpgme_op_keylist_next (ctx, &key)))
{
if (!keys[i].fpr)
@@ -110,6 +110,7 @@ main (int argc, char **argv)
{
fprintf (stderr, "Warning: Skipping unknown key %s\n",
key->subkeys->fpr);
+ gpgme_key_unref (key);
continue;
}
else
diff --git a/tests/gpgsm/t-sign.c b/tests/gpgsm/t-sign.c
index dc2d841..d4e143d 100644
--- a/tests/gpgsm/t-sign.c
+++ b/tests/gpgsm/t-sign.c
@@ -3,17 +3,17 @@
Copyright (C) 2001, 2003, 2004 g10 Code GmbH
This file is part of GPGME.
-
+
GPGME is free software; you can redistribute it and/or modify it
under the terms of the GNU Lesser General Public License as
published by the Free Software Foundation; either version 2.1 of
the License, or (at your option) any later version.
-
+
GPGME is distributed in the hope that it will be useful, but
WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
Lesser General Public License for more details.
-
+
You should have received a copy of the GNU Lesser General Public
License along with this program; if not, write to the Free Software
Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
@@ -80,8 +80,8 @@ check_result (gpgme_sign_result_t result, gpgme_sig_mode_t type)
}
-int
-main (int argc, char *argv[])
+int
+main (void)
{
gpgme_ctx_t ctx;
gpgme_error_t err;
@@ -109,8 +109,8 @@ main (int argc, char *argv[])
check_result (result, GPGME_SIG_MODE_NORMAL);
print_data (out);
gpgme_data_release (out);
-
- /* Now a detached signature. */
+
+ /* Now a detached signature. */
gpgme_data_seek (in, 0, SEEK_SET);
err = gpgme_data_new (&out);
fail_if_err (err);
diff --git a/tests/gpgsm/t-support.h b/tests/gpgsm/t-support.h
index cc1a7db..c3074db 100644
--- a/tests/gpgsm/t-support.h
+++ b/tests/gpgsm/t-support.h
@@ -3,17 +3,17 @@
Copyright (C) 2001, 2002, 2003, 2004 g10 Code GmbH
This file is part of GPGME.
-
+
GPGME is free software; you can redistribute it and/or modify it
under the terms of the GNU Lesser General Public License as
published by the Free Software Foundation; either version 2.1 of
the License, or (at your option) any later version.
-
+
GPGME is distributed in the hope that it will be useful, but
WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
Lesser General Public License for more details.
-
+
You should have received a copy of the GNU Lesser General Public
License along with this program; if not, write to the Free Software
Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
@@ -47,7 +47,7 @@ print_data (gpgme_data_t dh)
#define BUF_SIZE 512
char buf[BUF_SIZE + 1];
int ret;
-
+
ret = gpgme_data_seek (dh, 0, SEEK_SET);
if (ret)
fail_if_err (gpgme_error_from_errno (errno));
@@ -63,13 +63,18 @@ passphrase_cb (void *opaque, const char *uid_hint, const char *passphrase_info,
int last_was_bad, int fd)
{
int res;
- char *pass = "abc\n";
+ char pass[] = "abc\n";
int passlen = strlen (pass);
int off = 0;
+ (void)opaque;
+ (void)uid_hint;
+ (void)passphrase_info;
+ (void)last_was_bad;
+
do
{
- res = write (fd, &pass[off], passlen - off);
+ res = gpgme_io_write (fd, &pass[off], passlen - off);
if (res > 0)
off += res;
}
@@ -88,7 +93,7 @@ make_filename (const char *fname)
if (!srcdir)
srcdir = ".";
buf = malloc (strlen(srcdir) + strlen(fname) + 2);
- if (!buf)
+ if (!buf)
exit (8);
strcpy (buf, srcdir);
strcat (buf, "/");
diff --git a/tests/gpgsm/t-verify.c b/tests/gpgsm/t-verify.c
index 901b46f..004a125 100644
--- a/tests/gpgsm/t-verify.c
+++ b/tests/gpgsm/t-verify.c
@@ -3,17 +3,17 @@
Copyright (C) 2001, 2002, 2003, 2004 g10 Code GmbH
This file is part of GPGME.
-
+
GPGME is free software; you can redistribute it and/or modify it
under the terms of the GNU Lesser General Public License as
published by the Free Software Foundation; either version 2.1 of
the License, or (at your option) any later version.
-
+
GPGME is distributed in the hope that it will be useful, but
WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
Lesser General Public License for more details.
-
+
You should have received a copy of the GNU Lesser General Public
License along with this program; if not, write to the Free Software
Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
@@ -52,7 +52,7 @@ static const char test_sig1[] =
static void
-check_result (gpgme_verify_result_t result, int summary, char *fpr,
+check_result (gpgme_verify_result_t result, int summary, const char *fpr,
gpgme_error_t status, gpgme_validity_t validity)
{
gpgme_signature_t sig;
@@ -134,8 +134,8 @@ show_auditlog (gpgme_ctx_t ctx)
-int
-main (int argc, char **argv)
+int
+main (void)
{
gpgme_ctx_t ctx;
gpgme_error_t err;
@@ -147,7 +147,7 @@ main (int argc, char **argv)
err = gpgme_new (&ctx);
fail_if_err (err);
gpgme_set_protocol (ctx, GPGME_PROTOCOL_CMS);
-
+
/* Checking a valid message. */
err = gpgme_data_new_from_mem (&text, test_text1, strlen (test_text1), 0);
fail_if_err (err);
@@ -179,6 +179,6 @@ main (int argc, char **argv)
gpgme_data_release (text);
gpgme_data_release (sig);
- gpgme_release (ctx);
+ gpgme_release (ctx);
return got_errors? 1 : 0;
}
diff --git a/tests/opassuan/Makefile.in b/tests/opassuan/Makefile.in
index 018cbbe..1740ad0 100644
--- a/tests/opassuan/Makefile.in
+++ b/tests/opassuan/Makefile.in
@@ -103,12 +103,16 @@ DIST_COMMON = $(srcdir)/Makefile.in $(srcdir)/Makefile.am \
$(top_srcdir)/build-aux/mkinstalldirs \
$(top_srcdir)/build-aux/depcomp $(noinst_HEADERS)
ACLOCAL_M4 = $(top_srcdir)/aclocal.m4
-am__aclocal_m4_deps = $(top_srcdir)/m4/glib-2.0.m4 \
- $(top_srcdir)/m4/glibc21.m4 $(top_srcdir)/m4/gnupg-ttyname.m4 \
+am__aclocal_m4_deps = $(top_srcdir)/m4/ax_cxx_compile_stdcxx.m4 \
+ $(top_srcdir)/m4/ax_pkg_swig.m4 \
+ $(top_srcdir)/m4/ax_python_devel.m4 \
+ $(top_srcdir)/m4/glib-2.0.m4 $(top_srcdir)/m4/glibc21.m4 \
+ $(top_srcdir)/m4/gnupg-ttyname.m4 \
$(top_srcdir)/m4/gpg-error.m4 $(top_srcdir)/m4/libassuan.m4 \
$(top_srcdir)/m4/libtool.m4 $(top_srcdir)/m4/ltoptions.m4 \
$(top_srcdir)/m4/ltsugar.m4 $(top_srcdir)/m4/ltversion.m4 \
- $(top_srcdir)/m4/lt~obsolete.m4 $(top_srcdir)/acinclude.m4 \
+ $(top_srcdir)/m4/lt~obsolete.m4 $(top_srcdir)/m4/pkg.m4 \
+ $(top_srcdir)/m4/qt.m4 $(top_srcdir)/acinclude.m4 \
$(top_srcdir)/configure.ac
am__configure_deps = $(am__aclocal_m4_deps) $(CONFIGURE_DEPENDENCIES) \
$(ACLOCAL_M4)
@@ -224,6 +228,7 @@ BUILD_REVISION = @BUILD_REVISION@
BUILD_TIMESTAMP = @BUILD_TIMESTAMP@
CC = @CC@
CCDEPMODE = @CCDEPMODE@
+CC_FOR_BUILD = @CC_FOR_BUILD@
CFLAGS = @CFLAGS@
CPP = @CPP@
CPPFLAGS = @CPPFLAGS@
@@ -235,12 +240,14 @@ CYGPATH_W = @CYGPATH_W@
DEFS = @DEFS@
DEPDIR = @DEPDIR@
DLLTOOL = @DLLTOOL@
+DOXYGEN = @DOXYGEN@
DSYMUTIL = @DSYMUTIL@
DUMPBIN = @DUMPBIN@
ECHO_C = @ECHO_C@
ECHO_N = @ECHO_N@
ECHO_T = @ECHO_T@
EGREP = @EGREP@
+ENABLED_LANGUAGES = @ENABLED_LANGUAGES@
EXEEXT = @EXEEXT@
FGREP = @FGREP@
GITLOG_TO_CHANGELOG = @GITLOG_TO_CHANGELOG@
@@ -251,15 +258,23 @@ GLIB_LIBS = @GLIB_LIBS@
GLIB_MKENUMS = @GLIB_MKENUMS@
GOBJECT_QUERY = @GOBJECT_QUERY@
GPGME_CONFIG_API_VERSION = @GPGME_CONFIG_API_VERSION@
+GPGME_CONFIG_AVAIL_LANG = @GPGME_CONFIG_AVAIL_LANG@
GPGME_CONFIG_CFLAGS = @GPGME_CONFIG_CFLAGS@
GPGME_CONFIG_HOST = @GPGME_CONFIG_HOST@
GPGME_CONFIG_LIBS = @GPGME_CONFIG_LIBS@
+GPGME_QTTEST_CFLAGS = @GPGME_QTTEST_CFLAGS@
+GPGME_QTTEST_LIBS = @GPGME_QTTEST_LIBS@
+GPGME_QT_CFLAGS = @GPGME_QT_CFLAGS@
+GPGME_QT_LIBS = @GPGME_QT_LIBS@
GPG_ERROR_CFLAGS = @GPG_ERROR_CFLAGS@
GPG_ERROR_CONFIG = @GPG_ERROR_CONFIG@
GPG_ERROR_LIBS = @GPG_ERROR_LIBS@
GPG_ERROR_MT_CFLAGS = @GPG_ERROR_MT_CFLAGS@
GPG_ERROR_MT_LIBS = @GPG_ERROR_MT_LIBS@
+GRAPHVIZ = @GRAPHVIZ@
GREP = @GREP@
+HAVE_CXX11 = @HAVE_CXX11@
+HAVE_DOT = @HAVE_DOT@
INSTALL = @INSTALL@
INSTALL_DATA = @INSTALL_DATA@
INSTALL_PROGRAM = @INSTALL_PROGRAM@
@@ -270,10 +285,16 @@ LDFLAGS = @LDFLAGS@
LIBASSUAN_CFLAGS = @LIBASSUAN_CFLAGS@
LIBASSUAN_CONFIG = @LIBASSUAN_CONFIG@
LIBASSUAN_LIBS = @LIBASSUAN_LIBS@
+LIBGPGMEPP_LT_AGE = @LIBGPGMEPP_LT_AGE@
+LIBGPGMEPP_LT_CURRENT = @LIBGPGMEPP_LT_CURRENT@
+LIBGPGMEPP_LT_REVISION = @LIBGPGMEPP_LT_REVISION@
LIBGPGME_LT_AGE = @LIBGPGME_LT_AGE@
LIBGPGME_LT_CURRENT = @LIBGPGME_LT_CURRENT@
LIBGPGME_LT_REVISION = @LIBGPGME_LT_REVISION@
LIBOBJS = @LIBOBJS@
+LIBQGPGME_LT_AGE = @LIBQGPGME_LT_AGE@
+LIBQGPGME_LT_CURRENT = @LIBQGPGME_LT_CURRENT@
+LIBQGPGME_LT_REVISION = @LIBQGPGME_LT_REVISION@
LIBS = @LIBS@
LIBTOOL = @LIBTOOL@
LIPO = @LIPO@
@@ -283,6 +304,8 @@ MAINT = @MAINT@
MAKEINFO = @MAKEINFO@
MANIFEST_TOOL = @MANIFEST_TOOL@
MKDIR_P = @MKDIR_P@
+MOC = @MOC@
+MOC2 = @MOC2@
NEED__FILE_OFFSET_BITS = @NEED__FILE_OFFSET_BITS@
NM = @NM@
NMEDIT = @NMEDIT@
@@ -299,14 +322,27 @@ PACKAGE_URL = @PACKAGE_URL@
PACKAGE_VERSION = @PACKAGE_VERSION@
PATH_SEPARATOR = @PATH_SEPARATOR@
PKG_CONFIG = @PKG_CONFIG@
-QT4_CORE_CFLAGS = @QT4_CORE_CFLAGS@
-QT4_CORE_LIBS = @QT4_CORE_LIBS@
+PYTHON = @PYTHON@
+PYTHONS = @PYTHONS@
+PYTHON_CPPFLAGS = @PYTHON_CPPFLAGS@
+PYTHON_EXEC_PREFIX = @PYTHON_EXEC_PREFIX@
+PYTHON_EXTRA_LDFLAGS = @PYTHON_EXTRA_LDFLAGS@
+PYTHON_EXTRA_LIBS = @PYTHON_EXTRA_LIBS@
+PYTHON_LDFLAGS = @PYTHON_LDFLAGS@
+PYTHON_PLATFORM = @PYTHON_PLATFORM@
+PYTHON_PREFIX = @PYTHON_PREFIX@
+PYTHON_SITE_PKG = @PYTHON_SITE_PKG@
+PYTHON_VERSION = @PYTHON_VERSION@
+PYTHON_VERSIONS = @PYTHON_VERSIONS@
+QTCHOOSER = @QTCHOOSER@
RANLIB = @RANLIB@
RC = @RC@
SED = @SED@
SET_MAKE = @SET_MAKE@
SHELL = @SHELL@
STRIP = @STRIP@
+SWIG = @SWIG@
+SWIG_LIB = @SWIG_LIB@
SYSROOT = @SYSROOT@
VERSION = @VERSION@
VERSION_NUMBER = @VERSION_NUMBER@
@@ -355,9 +391,13 @@ mandir = @mandir@
mkdir_p = @mkdir_p@
oldincludedir = @oldincludedir@
pdfdir = @pdfdir@
+pkgpyexecdir = @pkgpyexecdir@
+pkgpythondir = @pkgpythondir@
prefix = @prefix@
program_transform_name = @program_transform_name@
psdir = @psdir@
+pyexecdir = @pyexecdir@
+pythondir = @pythondir@
sbindir = @sbindir@
sharedstatedir = @sharedstatedir@
srcdir = @srcdir@
diff --git a/tests/opassuan/t-command.c b/tests/opassuan/t-command.c
index 87f8202..9c791ee 100644
--- a/tests/opassuan/t-command.c
+++ b/tests/opassuan/t-command.c
@@ -7,12 +7,12 @@
under the terms of the GNU Lesser General Public License as
published by the Free Software Foundation; either version 2.1 of
the License, or (at your option) any later version.
-
+
GPGME is distributed in the hope that it will be useful, but
WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
Lesser General Public License for more details.
-
+
You should have received a copy of the GNU Lesser General Public
License along with this program; if not, see <http://www.gnu.org/licenses/>.
*/
@@ -46,9 +46,12 @@
static gpgme_error_t
data_cb (void *opaque, const void *data, size_t datalen)
{
+ (void)opaque;
+ (void)data;
+
printf ("DATA_CB: datalen=%d\n", (int)datalen);
return 0;
-}
+}
static gpgme_error_t
@@ -58,12 +61,14 @@ inq_cb (void *opaque, const char *name, const char *args,
gpgme_data_t data;
gpgme_error_t err;
+ (void)opaque;
+
if (name)
{
printf ("INQ_CB: name=`%s' args=`%s'\n", name, args);
/* There shall be no data object. */
assert (!*r_data);
-
+
err = gpgme_data_new (&data);
fail_if_err (err);
*r_data = data;
@@ -85,19 +90,21 @@ inq_cb (void *opaque, const char *name, const char *args,
return 0;
-}
+}
static gpgme_error_t
status_cb (void *opaque, const char *status, const char *args)
{
+ (void)opaque;
+
printf ("STATUS_CB: status=`%s' args=`%s'\n", status, args);
return 0;
-}
+}
-int
+int
main (int argc, char **argv)
{
gpgme_error_t err;
@@ -118,7 +125,7 @@ main (int argc, char **argv)
argv++;
}
command = argc? *argv : "NOP";
-
+
err = gpgme_new (&ctx);
fail_if_err (err);
diff --git a/tests/run-decrypt.c b/tests/run-decrypt.c
new file mode 100644
index 0000000..6d38aee
--- /dev/null
+++ b/tests/run-decrypt.c
@@ -0,0 +1,189 @@
+/* run-decrypt.c - Helper to perform a verify operation
+ Copyright (C) 2009 g10 Code GmbH
+ 2016 Intevation GmbH
+
+ This file is part of GPGME.
+
+ GPGME is free software; you can redistribute it and/or modify it
+ under the terms of the GNU Lesser General Public License as
+ published by the Free Software Foundation; either version 2.1 of
+ the License, or (at your option) any later version.
+
+ GPGME is distributed in the hope that it will be useful, but
+ WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Lesser General Public License for more details.
+
+ You should have received a copy of the GNU Lesser General Public
+ License along with this program; if not, see <http://www.gnu.org/licenses/>.
+*/
+
+/* We need to include config.h so that we know whether we are building
+ with large file system (LFS) support. */
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+#endif
+
+#include <stdlib.h>
+#include <stdio.h>
+#include <string.h>
+
+#include <gpgme.h>
+
+#define PGM "run-decrypt"
+
+#include "run-support.h"
+
+
+static int verbose;
+
+static gpg_error_t
+status_cb (void *opaque, const char *keyword, const char *value)
+{
+ (void)opaque;
+ fprintf (stderr, "status_cb: %s %s\n", keyword, value);
+ return 0;
+}
+
+
+static void
+print_result (gpgme_decrypt_result_t result)
+{
+ gpgme_recipient_t recp;
+ int count = 0;
+ printf ("Original file name: %s\n", nonnull(result->file_name));
+ printf ("Wrong key usage: %i\n", result->wrong_key_usage);
+ printf ("Unsupported algorithm: %s\n ", nonnull(result->unsupported_algorithm));
+
+ for (recp = result->recipients; recp->next; recp = recp->next)
+ {
+ printf ("recipient %d\n", count++);
+ printf (" status ....: %s\n", gpgme_strerror (recp->status));
+ printf (" keyid: %s\n", nonnull (recp->keyid));
+ printf (" algo ...: %s\n", gpgme_pubkey_algo_name (recp->pubkey_algo));
+ }
+}
+
+
+static int
+show_usage (int ex)
+{
+ fputs ("usage: " PGM " [options] FILE\n\n"
+ "Options:\n"
+ " --verbose run in verbose mode\n"
+ " --status print status lines from the backend\n"
+ " --openpgp use the OpenPGP protocol (default)\n"
+ " --cms use the CMS protocol\n"
+ , stderr);
+ exit (ex);
+}
+
+
+int
+main (int argc, char **argv)
+{
+ int last_argc = -1;
+ gpgme_error_t err;
+ gpgme_ctx_t ctx;
+ gpgme_protocol_t protocol = GPGME_PROTOCOL_OpenPGP;
+ FILE *fp_in = NULL;
+ gpgme_data_t in = NULL;
+ gpgme_data_t out = NULL;
+ gpgme_decrypt_result_t result;
+ int print_status = 0;
+
+ if (argc)
+ { argc--; argv++; }
+
+ while (argc && last_argc != argc )
+ {
+ last_argc = argc;
+ if (!strcmp (*argv, "--"))
+ {
+ argc--; argv++;
+ break;
+ }
+ else if (!strcmp (*argv, "--help"))
+ show_usage (0);
+ else if (!strcmp (*argv, "--verbose"))
+ {
+ verbose = 1;
+ argc--; argv++;
+ }
+ else if (!strcmp (*argv, "--status"))
+ {
+ print_status = 1;
+ argc--; argv++;
+ }
+ else if (!strcmp (*argv, "--openpgp"))
+ {
+ protocol = GPGME_PROTOCOL_OpenPGP;
+ argc--; argv++;
+ }
+ else if (!strcmp (*argv, "--cms"))
+ {
+ protocol = GPGME_PROTOCOL_CMS;
+ argc--; argv++;
+ }
+ else if (!strncmp (*argv, "--", 2))
+ show_usage (1);
+
+ }
+
+ if (argc < 1 || argc > 2)
+ show_usage (1);
+
+ fp_in = fopen (argv[0], "rb");
+ if (!fp_in)
+ {
+ err = gpgme_error_from_syserror ();
+ fprintf (stderr, PGM ": can't open `%s': %s\n",
+ argv[0], gpgme_strerror (err));
+ exit (1);
+ }
+
+ init_gpgme (protocol);
+
+ err = gpgme_new (&ctx);
+ fail_if_err (err);
+ gpgme_set_protocol (ctx, protocol);
+ if (print_status)
+ {
+ gpgme_set_status_cb (ctx, status_cb, NULL);
+ gpgme_set_ctx_flag (ctx, "full-status", "1");
+ }
+
+ err = gpgme_data_new_from_stream (&in, fp_in);
+ if (err)
+ {
+ fprintf (stderr, PGM ": error allocating data object: %s\n",
+ gpgme_strerror (err));
+ exit (1);
+ }
+
+ err = gpgme_data_new (&out);
+ if (err)
+ {
+ fprintf (stderr, PGM ": error allocating data object: %s\n",
+ gpgme_strerror (err));
+ exit (1);
+ }
+
+ err = gpgme_op_decrypt (ctx, in, out);
+ result = gpgme_op_decrypt_result (ctx);
+ if (err)
+ {
+ fprintf (stderr, PGM ": decrypt failed: %s\n", gpgme_strerror (err));
+ exit (1);
+ }
+ if (result) {
+ print_result (result);
+ print_data (out);
+ }
+
+ gpgme_data_release (out);
+ gpgme_data_release (in);
+
+ gpgme_release (ctx);
+ return 0;
+}
diff --git a/tests/run-encrypt.c b/tests/run-encrypt.c
new file mode 100644
index 0000000..b94b028
--- /dev/null
+++ b/tests/run-encrypt.c
@@ -0,0 +1,293 @@
+/* run-encrypt.c - Helper to perform an encrypt operation
+ * Copyright (C) 2016 g10 Code GmbH
+ *
+ * This file is part of GPGME.
+ *
+ * GPGME is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU Lesser General Public License as
+ * published by the Free Software Foundation; either version 2.1 of
+ * the License, or (at your option) any later version.
+ *
+ * GPGME is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this program; if not, see <http://www.gnu.org/licenses/>.
+ */
+
+/* We need to include config.h so that we know whether we are building
+ with large file system (LFS) support. */
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+#endif
+
+#include <stdlib.h>
+#include <stdio.h>
+#include <string.h>
+
+#include <gpgme.h>
+
+#define PGM "run-encrypt"
+
+#include "run-support.h"
+
+
+static int verbose;
+
+
+static gpg_error_t
+status_cb (void *opaque, const char *keyword, const char *value)
+{
+ (void)opaque;
+ fprintf (stderr, "status_cb: %s %s\n", nonnull(keyword), nonnull(value));
+ return 0;
+}
+
+
+static void
+progress_cb (void *opaque, const char *what, int type, int current, int total)
+{
+ (void)opaque;
+ (void)type;
+
+ if (total)
+ fprintf (stderr, "progress for '%s' %u%% (%d of %d)\n",
+ nonnull (what),
+ (unsigned)(((double)current / total) * 100), current, total);
+ else
+ fprintf (stderr, "progress for '%s' %d\n", nonnull(what), current);
+ fflush (stderr);
+}
+
+
+static void
+print_result (gpgme_encrypt_result_t result)
+{
+ gpgme_invalid_key_t invkey;
+
+ for (invkey = result->invalid_recipients; invkey; invkey = invkey->next)
+ printf ("Encryption key `%s' not used: %s <%s>\n",
+ nonnull (invkey->fpr),
+ gpg_strerror (invkey->reason), gpg_strsource (invkey->reason));
+}
+
+
+
+static int
+show_usage (int ex)
+{
+ fputs ("usage: " PGM " [options] FILE\n\n"
+ "Options:\n"
+ " --verbose run in verbose mode\n"
+ " --status print status lines from the backend\n"
+ " --progress print progress info\n"
+ " --openpgp use the OpenPGP protocol (default)\n"
+ " --cms use the CMS protocol\n"
+ " --uiserver use the UI server\n"
+ " --loopback use a loopback pinentry\n"
+ " --key NAME encrypt to key NAME\n"
+ " --symmetric encrypt symmetric (OpenPGP only)\n"
+ , stderr);
+ exit (ex);
+}
+
+
+int
+main (int argc, char **argv)
+{
+ int last_argc = -1;
+ gpgme_error_t err;
+ gpgme_ctx_t ctx;
+ const char *key_string = NULL;
+ gpgme_protocol_t protocol = GPGME_PROTOCOL_OpenPGP;
+ gpgme_data_t in, out;
+ gpgme_encrypt_result_t result;
+ int print_status = 0;
+ int print_progress = 0;
+ int use_loopback = 0;
+ char *keyargs[10];
+ gpgme_key_t keys[10+1];
+ int keycount = 0;
+ int i;
+ gpgme_encrypt_flags_t flags = GPGME_ENCRYPT_ALWAYS_TRUST;
+ gpgme_off_t offset;
+
+ if (argc)
+ { argc--; argv++; }
+
+ if (DIM(keys) != DIM(keyargs)+1)
+ abort ();
+
+ while (argc && last_argc != argc )
+ {
+ last_argc = argc;
+ if (!strcmp (*argv, "--"))
+ {
+ argc--; argv++;
+ break;
+ }
+ else if (!strcmp (*argv, "--help"))
+ show_usage (0);
+ else if (!strcmp (*argv, "--verbose"))
+ {
+ verbose = 1;
+ argc--; argv++;
+ }
+ else if (!strcmp (*argv, "--status"))
+ {
+ print_status = 1;
+ argc--; argv++;
+ }
+ else if (!strcmp (*argv, "--progress"))
+ {
+ print_progress = 1;
+ argc--; argv++;
+ }
+ else if (!strcmp (*argv, "--openpgp"))
+ {
+ protocol = GPGME_PROTOCOL_OpenPGP;
+ argc--; argv++;
+ }
+ else if (!strcmp (*argv, "--cms"))
+ {
+ protocol = GPGME_PROTOCOL_CMS;
+ argc--; argv++;
+ }
+ else if (!strcmp (*argv, "--uiserver"))
+ {
+ protocol = GPGME_PROTOCOL_UISERVER;
+ argc--; argv++;
+ }
+ else if (!strcmp (*argv, "--key"))
+ {
+ argc--; argv++;
+ if (!argc)
+ show_usage (1);
+ if (keycount == DIM (keyargs))
+ show_usage (1);
+ keyargs[keycount++] = *argv;
+ argc--; argv++;
+ }
+ else if (!strcmp (*argv, "--loopback"))
+ {
+ use_loopback = 1;
+ argc--; argv++;
+ }
+ else if (!strcmp (*argv, "--symmetric"))
+ {
+ flags |= GPGME_ENCRYPT_SYMMETRIC;
+ argc--; argv++;
+ }
+ else if (!strncmp (*argv, "--", 2))
+ show_usage (1);
+
+ }
+
+ if (argc != 1)
+ show_usage (1);
+
+ if (key_string && protocol == GPGME_PROTOCOL_UISERVER)
+ {
+ fprintf (stderr, PGM ": ignoring --key in UI-server mode\n");
+ key_string = NULL;
+ }
+
+ if (!key_string)
+ key_string = "test";
+
+ init_gpgme (protocol);
+
+ err = gpgme_new (&ctx);
+ fail_if_err (err);
+ gpgme_set_protocol (ctx, protocol);
+ gpgme_set_armor (ctx, 1);
+ if (print_status)
+ {
+ gpgme_set_status_cb (ctx, status_cb, NULL);
+ gpgme_set_ctx_flag (ctx, "full-status", "1");
+ }
+ if (print_progress)
+ gpgme_set_progress_cb (ctx, progress_cb, NULL);
+ if (use_loopback)
+ {
+ gpgme_set_pinentry_mode (ctx, GPGME_PINENTRY_MODE_LOOPBACK);
+ gpgme_set_passphrase_cb (ctx, passphrase_cb, NULL);
+ }
+
+ for (i=0; i < keycount; i++)
+ {
+ err = gpgme_get_key (ctx, keyargs[i], &keys[i], 0);
+ fail_if_err (err);
+ }
+ keys[i] = NULL;
+
+ err = gpgme_data_new_from_file (&in, *argv, 1);
+ if (err)
+ {
+ fprintf (stderr, PGM ": error reading `%s': %s\n",
+ *argv, gpg_strerror (err));
+ exit (1);
+ }
+ offset = gpgme_data_seek (in, 0, SEEK_END);
+ if (offset == (gpgme_off_t)(-1))
+ {
+ err = gpg_error_from_syserror ();
+ fprintf (stderr, PGM ": error seeking `%s': %s\n",
+ *argv, gpg_strerror (err));
+ exit (1);
+ }
+ if (gpgme_data_seek (in, 0, SEEK_SET) == (gpgme_off_t)(-1))
+ {
+ err = gpg_error_from_syserror ();
+ fprintf (stderr, PGM ": error seeking `%s': %s\n",
+ *argv, gpg_strerror (err));
+ exit (1);
+ }
+ {
+ char numbuf[50];
+ char *p;
+
+ p = numbuf + sizeof numbuf;
+ *--p = 0;
+ do
+ {
+ *--p = '0' + (offset % 10);
+ offset /= 10;
+ }
+ while (offset);
+ err = gpgme_data_set_flag (in, "size-hint", p);
+ if (err)
+ {
+ fprintf (stderr, PGM ": error setting size-hint for `%s': %s\n",
+ *argv, gpg_strerror (err));
+ exit (1);
+ }
+ }
+
+ err = gpgme_data_new (&out);
+ fail_if_err (err);
+
+ err = gpgme_op_encrypt (ctx, keycount ? keys : NULL, flags, in, out);
+ result = gpgme_op_encrypt_result (ctx);
+ if (result)
+ print_result (result);
+ if (err)
+ {
+ fprintf (stderr, PGM ": encrypting failed: %s\n", gpg_strerror (err));
+ exit (1);
+ }
+
+ fputs ("Begin Output:\n", stdout);
+ print_data (out);
+ fputs ("End Output.\n", stdout);
+ gpgme_data_release (out);
+
+ gpgme_data_release (in);
+
+ for (i=0; i < keycount; i++)
+ gpgme_key_unref (keys[i]);
+ gpgme_release (ctx);
+ return 0;
+}
diff --git a/tests/run-genkey.c b/tests/run-genkey.c
new file mode 100644
index 0000000..20e7db5
--- /dev/null
+++ b/tests/run-genkey.c
@@ -0,0 +1,439 @@
+/* run-genkey.c - Test tool to perform key generation
+ * Copyright (C) 2016 g10 Code GmbH
+ *
+ * This file is part of GPGME.
+ *
+ * GPGME is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU Lesser General Public License as
+ * published by the Free Software Foundation; either version 2.1 of
+ * the License, or (at your option) any later version.
+ *
+ * GPGME is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this program; if not, see <http://www.gnu.org/licenses/>.
+ */
+
+/* We need to include config.h so that we know whether we are building
+ with large file system (LFS) support. */
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+#endif
+
+#include <stdlib.h>
+#include <stdio.h>
+#include <string.h>
+#include <assert.h>
+
+#include <gpgme.h>
+
+#define PGM "run-genkey"
+
+#include "run-support.h"
+
+
+static int verbose;
+
+
+/* Tokenize STRING using the set of delimiters in DELIM. Leading
+ * spaces and tabs are removed from all tokens. The caller must free
+ * the result.
+ *
+ * Returns: A malloced and NULL delimited array with the tokens. On
+ * memory error NULL is returned and ERRNO is set.
+ */
+static char **
+strtokenize (const char *string, const char *delim)
+{
+ const char *s;
+ size_t fields;
+ size_t bytes, n;
+ char *buffer;
+ char *p, *px, *pend;
+ char **result;
+
+ /* Count the number of fields. */
+ for (fields = 1, s = strpbrk (string, delim); s; s = strpbrk (s + 1, delim))
+ fields++;
+ fields++; /* Add one for the terminating NULL. */
+
+ /* Allocate an array for all fields, a terminating NULL, and space
+ for a copy of the string. */
+ bytes = fields * sizeof *result;
+ if (bytes / sizeof *result != fields)
+ {
+ gpg_err_set_errno (ENOMEM);
+ return NULL;
+ }
+ n = strlen (string) + 1;
+ bytes += n;
+ if (bytes < n)
+ {
+ gpg_err_set_errno (ENOMEM);
+ return NULL;
+ }
+ result = malloc (bytes);
+ if (!result)
+ return NULL;
+ buffer = (char*)(result + fields);
+
+ /* Copy and parse the string. */
+ strcpy (buffer, string);
+ for (n = 0, p = buffer; (pend = strpbrk (p, delim)); p = pend + 1)
+ {
+ *pend = 0;
+ while (*p == ' ' || *p == '\t')
+ p++;
+ for (px = pend - 1; px >= p && (*px == ' ' || *px == '\t'); px--)
+ *px = 0;
+ result[n++] = p;
+ }
+ while (*p == ' ' || *p == '\t')
+ p++;
+ for (px = p + strlen (p) - 1; px >= p && (*px == ' ' || *px == '\t'); px--)
+ *px = 0;
+ result[n++] = p;
+ result[n] = NULL;
+
+ assert ((char*)(result + n + 1) == buffer);
+
+ return result;
+}
+
+
+static gpg_error_t
+status_cb (void *opaque, const char *keyword, const char *value)
+{
+ (void)opaque;
+ fprintf (stderr, "status_cb: %s %s\n", nonnull(keyword), nonnull(value));
+ return 0;
+}
+
+
+static void
+progress_cb (void *opaque, const char *what, int type, int current, int total)
+{
+ (void)opaque;
+ (void)type;
+
+ if (total)
+ fprintf (stderr, "progress for '%s' %u%% (%d of %d)\n",
+ nonnull (what),
+ (unsigned)(((double)current / total) * 100), current, total);
+ else
+ fprintf (stderr, "progress for '%s' %d\n", nonnull(what), current);
+ fflush (stderr);
+}
+
+
+static unsigned long
+parse_expire_string (const char *string)
+{
+ unsigned long seconds;
+
+ if (!string || !*string || !strcmp (string, "none")
+ || !strcmp (string, "never") || !strcmp (string, "-"))
+ seconds = 0;
+ else if (strspn (string, "01234567890") == strlen (string))
+ seconds = strtoul (string, NULL, 10);
+ else
+ {
+ fprintf (stderr, PGM ": invalid value '%s'\n", string);
+ exit (1);
+ }
+
+ return seconds;
+}
+
+
+/* Parse a usage string and return flags for gpgme_op_createkey. */
+static unsigned int
+parse_usage_string (const char *string)
+{
+ gpg_error_t err;
+ char **tokens = NULL;
+ const char *s;
+ int i;
+ unsigned int flags = 0;
+
+ tokens = strtokenize (string, " \t,");
+ if (!tokens)
+ {
+ err = gpg_error_from_syserror ();
+ fprintf (stderr, PGM": strtokenize failed: %s\n", gpg_strerror (err));
+ exit (1);
+ }
+
+ for (i=0; (s = tokens[i]); i++)
+ {
+ if (!*s)
+ ;
+ else if (!strcmp (s, "default"))
+ ;
+ else if (!strcmp (s, "sign"))
+ flags |= GPGME_CREATE_SIGN;
+ else if (!strcmp (s, "encr"))
+ flags |= GPGME_CREATE_ENCR;
+ else if (!strcmp (s, "cert"))
+ flags |= GPGME_CREATE_CERT;
+ else if (!strcmp (s, "auth"))
+ flags |= GPGME_CREATE_AUTH;
+ else
+ {
+ free (tokens);
+ fprintf (stderr, PGM": invalid value '%s': %s\n",
+ string, "bad usage");
+ exit (1);
+ }
+ }
+
+ free (tokens);
+ return flags;
+}
+
+
+
+static int
+show_usage (int ex)
+{
+ fputs ("usage: " PGM " [options] ARGS\n"
+ " args: USERID [ALGO [USAGE [EXPIRESECONDS]]]\n"
+ " for addkey: FPR [ALGO [USAGE [EXPIRESECONDS]]]\n"
+ " for adduid: FPR USERID\n"
+ " for revuid: FPR USERID\n"
+ "Options:\n"
+ " --addkey add a subkey to the key with FPR\n"
+ " --adduid add a user id to the key with FPR\n"
+ " --revuid Revoke a user id from the key with FPR\n"
+ " --verbose run in verbose mode\n"
+ " --status print status lines from the backend\n"
+ " --progress print progress info\n"
+ " --openpgp use the OpenPGP protocol (default)\n"
+ " --cms use the CMS protocol\n"
+ " --loopback use a loopback pinentry\n"
+ " --unprotected do not use a passphrase\n"
+ " --force do not check for a duplicated user id\n"
+ , stderr);
+ exit (ex);
+}
+
+
+int
+main (int argc, char **argv)
+{
+ int last_argc = -1;
+ gpgme_error_t err;
+ gpgme_ctx_t ctx;
+ gpgme_protocol_t protocol = GPGME_PROTOCOL_OpenPGP;
+ int print_status = 0;
+ int print_progress = 0;
+ int use_loopback = 0;
+ int addkey = 0;
+ int adduid = 0;
+ int revuid = 0;
+ const char *userid;
+ const char *algo = NULL;
+ const char *newuserid = NULL;
+ unsigned int flags = 0;
+ unsigned long expire = 0;
+ gpgme_genkey_result_t result;
+
+ if (argc)
+ { argc--; argv++; }
+
+ while (argc && last_argc != argc )
+ {
+ last_argc = argc;
+ if (!strcmp (*argv, "--"))
+ {
+ argc--; argv++;
+ break;
+ }
+ else if (!strcmp (*argv, "--help"))
+ show_usage (0);
+ else if (!strcmp (*argv, "--addkey"))
+ {
+ addkey = 1;
+ adduid = 0;
+ revuid = 0;
+ argc--; argv++;
+ }
+ else if (!strcmp (*argv, "--adduid"))
+ {
+ addkey = 0;
+ adduid = 1;
+ revuid = 0;
+ argc--; argv++;
+ }
+ else if (!strcmp (*argv, "--revuid"))
+ {
+ addkey = 0;
+ adduid = 0;
+ revuid = 1;
+ argc--; argv++;
+ }
+ else if (!strcmp (*argv, "--verbose"))
+ {
+ verbose = 1;
+ argc--; argv++;
+ }
+ else if (!strcmp (*argv, "--status"))
+ {
+ print_status = 1;
+ argc--; argv++;
+ }
+ else if (!strcmp (*argv, "--progress"))
+ {
+ print_progress = 1;
+ argc--; argv++;
+ }
+ else if (!strcmp (*argv, "--openpgp"))
+ {
+ protocol = GPGME_PROTOCOL_OpenPGP;
+ argc--; argv++;
+ }
+ else if (!strcmp (*argv, "--cms"))
+ {
+ protocol = GPGME_PROTOCOL_CMS;
+ argc--; argv++;
+ }
+ else if (!strcmp (*argv, "--loopback"))
+ {
+ use_loopback = 1;
+ argc--; argv++;
+ }
+ else if (!strcmp (*argv, "--unprotected"))
+ {
+ flags |= GPGME_CREATE_NOPASSWD;
+ argc--; argv++;
+ }
+ else if (!strcmp (*argv, "--force"))
+ {
+ flags |= GPGME_CREATE_FORCE;
+ argc--; argv++;
+ }
+ else if (!strncmp (*argv, "--", 2))
+ show_usage (1);
+ }
+
+ if (adduid || revuid)
+ {
+ if (argc != 2)
+ show_usage (1);
+ userid = argv[0];
+ newuserid = argv[1];
+ }
+ else
+ {
+ if (!argc || argc > 4)
+ show_usage (1);
+ userid = argv[0];
+ if (argc > 1)
+ algo = argv[1];
+ if (argc > 2)
+ flags |= parse_usage_string (argv[2]);
+ if (argc > 3)
+ expire = parse_expire_string (argv[3]);
+ }
+
+ init_gpgme (protocol);
+
+ err = gpgme_new (&ctx);
+ fail_if_err (err);
+ gpgme_set_protocol (ctx, protocol);
+ gpgme_set_armor (ctx, 1);
+ if (print_status)
+ {
+ gpgme_set_status_cb (ctx, status_cb, NULL);
+ gpgme_set_ctx_flag (ctx, "full-status", "1");
+ }
+ if (print_progress)
+ gpgme_set_progress_cb (ctx, progress_cb, NULL);
+ if (use_loopback)
+ {
+ gpgme_set_pinentry_mode (ctx, GPGME_PINENTRY_MODE_LOOPBACK);
+ gpgme_set_passphrase_cb (ctx, passphrase_cb, NULL);
+ }
+
+ if (addkey || adduid || revuid)
+ {
+ gpgme_key_t akey;
+
+ err = gpgme_get_key (ctx, userid, &akey, 1);
+ if (err)
+ {
+ fprintf (stderr, PGM ": error getting secret key for '%s': %s\n",
+ userid, gpg_strerror (err));
+ exit (1);
+ }
+
+ if (addkey)
+ {
+ err = gpgme_op_createsubkey (ctx, akey, algo, 0, expire, flags);
+ if (err)
+ {
+ fprintf (stderr, PGM ": gpgme_op_createsubkey failed: %s\n",
+ gpg_strerror (err));
+ exit (1);
+ }
+ }
+ else if (adduid)
+ {
+ err = gpgme_op_adduid (ctx, akey, newuserid, flags);
+ if (err)
+ {
+ fprintf (stderr, PGM ": gpgme_op_adduid failed: %s\n",
+ gpg_strerror (err));
+ exit (1);
+ }
+ }
+ else if (revuid)
+ {
+ err = gpgme_op_revuid (ctx, akey, newuserid, flags);
+ if (err)
+ {
+ fprintf (stderr, PGM ": gpgme_op_revuid failed: %s\n",
+ gpg_strerror (err));
+ exit (1);
+ }
+ }
+ gpgme_key_unref (akey);
+ }
+ else
+ {
+ err = gpgme_op_createkey (ctx, userid, algo, 0, expire, NULL, flags);
+ if (err)
+ {
+ fprintf (stderr, PGM ": gpgme_op_createkey failed: %s\n",
+ gpg_strerror (err));
+ exit (1);
+ }
+ }
+
+ result = gpgme_op_genkey_result (ctx);
+ if (!result)
+ {
+ fprintf (stderr, PGM": gpgme_op_genkey_result returned NULL\n");
+ exit (1);
+ }
+
+ printf ("Generated key: %s (%s)\n",
+ result->fpr ? result->fpr : "none",
+ result->primary ? (result->sub ? "primary, sub" : "primary")
+ /**/ : (result->sub ? "sub" : "none"));
+
+ if (result->fpr && strlen (result->fpr) < 40)
+ fprintf (stderr, PGM": generated key has unexpected fingerprint\n");
+ if (!result->primary)
+ fprintf (stderr, PGM": primary key was not generated\n");
+ if (!result->sub)
+ fprintf (stderr, PGM": sub key was not generated\n");
+ if (!result->uid)
+ fprintf (stderr, PGM": uid was not generated\n");
+
+ gpgme_release (ctx);
+ return 0;
+}
diff --git a/tests/run-identify.c b/tests/run-identify.c
new file mode 100644
index 0000000..d5ce55f
--- /dev/null
+++ b/tests/run-identify.c
@@ -0,0 +1,129 @@
+/* run-identify - Helper to run the identify command
+ * Copyright (C) 2016 g10 Code GmbH
+ *
+ * This file is part of GPGME.
+ *
+ * GPGME is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU Lesser General Public License as
+ * published by the Free Software Foundation; either version 2.1 of
+ * the License, or (at your option) any later version.
+ *
+ * GPGME is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this program; if not, see <http://www.gnu.org/licenses/>.
+ */
+
+/* We need to include config.h so that we know whether we are building
+ with large file system (LFS) support. */
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+#endif
+
+#include <stdlib.h>
+#include <stdio.h>
+#include <string.h>
+
+#include <gpgme.h>
+
+#define PGM "run-identify"
+
+#include "run-support.h"
+
+
+static int verbose;
+
+
+static const char *
+data_type_to_string (gpgme_data_type_t dt)
+{
+ const char *s = "[?]";
+
+ switch (dt)
+ {
+ case GPGME_DATA_TYPE_INVALID : s = "invalid"; break;
+ case GPGME_DATA_TYPE_UNKNOWN : s = "unknown"; break;
+ case GPGME_DATA_TYPE_PGP_SIGNED : s = "PGP-signed"; break;
+ case GPGME_DATA_TYPE_PGP_SIGNATURE: s = "PGP-signature"; break;
+ case GPGME_DATA_TYPE_PGP_ENCRYPTED: s = "PGP-encrypted"; break;
+ case GPGME_DATA_TYPE_PGP_OTHER : s = "PGP"; break;
+ case GPGME_DATA_TYPE_PGP_KEY : s = "PGP-key"; break;
+ case GPGME_DATA_TYPE_CMS_SIGNED : s = "CMS-signed"; break;
+ case GPGME_DATA_TYPE_CMS_ENCRYPTED: s = "CMS-encrypted"; break;
+ case GPGME_DATA_TYPE_CMS_OTHER : s = "CMS"; break;
+ case GPGME_DATA_TYPE_X509_CERT : s = "X.509"; break;
+ case GPGME_DATA_TYPE_PKCS12 : s = "PKCS12"; break;
+ }
+ return s;
+}
+
+
+static int
+show_usage (int ex)
+{
+ fputs ("usage: " PGM " [options] FILENAMEs\n\n"
+ "Options:\n"
+ " --verbose run in verbose mode\n"
+ , stderr);
+ exit (ex);
+}
+
+int
+main (int argc, char **argv)
+{
+ int last_argc = -1;
+ gpgme_error_t err;
+ int anyerr = 0;
+ gpgme_data_t data;
+ gpgme_data_type_t dt;
+
+ if (argc)
+ { argc--; argv++; }
+ while (argc && last_argc != argc )
+ {
+ last_argc = argc;
+ if (!strcmp (*argv, "--"))
+ {
+ argc--; argv++;
+ break;
+ }
+ else if (!strcmp (*argv, "--help"))
+ show_usage (0);
+ else if (!strcmp (*argv, "--verbose"))
+ {
+ verbose = 1;
+ argc--; argv++;
+ }
+ else if (!strncmp (*argv, "--", 2))
+ show_usage (1);
+
+ }
+
+ init_gpgme (GPGME_PROTOCOL_OpenPGP);
+
+ for (; argc; argc--, argv++)
+ {
+ if (verbose)
+ printf ("reading file `%s'\n", *argv);
+ err = gpgme_data_new_from_file (&data, *argv, 1);
+ if (err)
+ {
+ fprintf (stderr, PGM ": error reading '%s': %s\n",
+ *argv, gpg_strerror (err));
+ anyerr = 1;
+ }
+ else
+ {
+ dt = gpgme_data_identify (data, 0);
+ if (dt == GPGME_DATA_TYPE_INVALID)
+ anyerr = 1;
+ printf ("%s: %s\n", *argv, data_type_to_string (dt));
+ gpgme_data_release (data);
+ }
+ }
+
+ return anyerr;
+}
diff --git a/tests/run-keylist.c b/tests/run-keylist.c
index 8abdf43..647a9ed 100644
--- a/tests/run-keylist.c
+++ b/tests/run-keylist.c
@@ -26,6 +26,7 @@
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
+#include <time.h>
#include <gpgme.h>
@@ -49,16 +50,38 @@ show_usage (int ex)
" --local use GPGME_KEYLIST_MODE_LOCAL\n"
" --extern use GPGME_KEYLIST_MODE_EXTERN\n"
" --sigs use GPGME_KEYLIST_MODE_SIGS\n"
+ " --tofu use GPGME_KEYLIST_MODE_TOFU\n"
" --sig-notations use GPGME_KEYLIST_MODE_SIG_NOTATIONS\n"
" --ephemeral use GPGME_KEYLIST_MODE_EPHEMERAL\n"
" --validate use GPGME_KEYLIST_MODE_VALIDATE\n"
" --import import all keys\n"
" --offline use offline mode\n"
+ " --require-gnupg required at least the given GnuPG version\n"
, stderr);
exit (ex);
}
+static const char *
+isotimestr (unsigned long value)
+{
+ time_t t;
+ static char buffer[25+5];
+ struct tm *tp;
+
+ if (!value)
+ return "none";
+ t = value;
+
+ tp = gmtime (&t);
+ snprintf (buffer, sizeof buffer, "%04d-%02d-%02d %02d:%02d:%02d",
+ 1900+tp->tm_year, tp->tm_mon+1, tp->tm_mday,
+ tp->tm_hour, tp->tm_min, tp->tm_sec);
+ return buffer;
+}
+
+
+
int
main (int argc, char **argv)
{
@@ -67,6 +90,7 @@ main (int argc, char **argv)
gpgme_ctx_t ctx;
gpgme_keylist_mode_t mode = 0;
gpgme_key_t key;
+ gpgme_subkey_t subkey;
gpgme_keylist_result_t result;
int import = 0;
gpgme_key_t keyarray[100];
@@ -118,6 +142,11 @@ main (int argc, char **argv)
mode |= GPGME_KEYLIST_MODE_EXTERN;
argc--; argv++;
}
+ else if (!strcmp (*argv, "--tofu"))
+ {
+ mode |= GPGME_KEYLIST_MODE_WITH_TOFU;
+ argc--; argv++;
+ }
else if (!strcmp (*argv, "--sigs"))
{
mode |= GPGME_KEYLIST_MODE_SIGS;
@@ -148,9 +177,16 @@ main (int argc, char **argv)
offline = 1;
argc--; argv++;
}
+ else if (!strcmp (*argv, "--require-gnupg"))
+ {
+ argc--; argv++;
+ if (!argc)
+ show_usage (1);
+ gpgme_set_global_flag ("require-gnupg", *argv);
+ argc--; argv++;
+ }
else if (!strncmp (*argv, "--", 2))
show_usage (1);
-
}
if (argc > 1)
@@ -172,33 +208,95 @@ main (int argc, char **argv)
while (!(err = gpgme_op_keylist_next (ctx, &key)))
{
gpgme_user_id_t uid;
+ gpgme_tofu_info_t ti;
int nuids;
-
+ int nsub;
printf ("keyid : %s\n", key->subkeys?nonnull (key->subkeys->keyid):"?");
printf ("fpr : %s\n", key->subkeys?nonnull (key->subkeys->fpr):"?");
+ if (key->subkeys && key->subkeys->keygrip)
+ printf ("grip : %s\n", key->subkeys->keygrip);
+ if (key->subkeys && key->subkeys->curve)
+ printf ("curve : %s\n", key->subkeys->curve);
printf ("caps : %s%s%s%s\n",
key->can_encrypt? "e":"",
key->can_sign? "s":"",
key->can_certify? "c":"",
key->can_authenticate? "a":"");
- printf ("flags :%s%s%s%s%s%s\n",
+ printf ("flags :%s%s%s%s%s%s%s\n",
key->secret? " secret":"",
key->revoked? " revoked":"",
key->expired? " expired":"",
key->disabled? " disabled":"",
key->invalid? " invalid":"",
- key->is_qualified? " qualifid":"");
+ key->is_qualified? " qualifid":"",
+ key->subkeys && key->subkeys->is_cardkey? " cardkey":"");
+
+ subkey = key->subkeys;
+ if (subkey)
+ subkey = subkey->next;
+ for (nsub=1; subkey; subkey = subkey->next, nsub++)
+ {
+ printf ("fpr %2d: %s\n", nsub, nonnull (subkey->fpr));
+ if (subkey->keygrip)
+ printf ("grip %2d: %s\n", nsub, subkey->keygrip);
+ if (subkey->curve)
+ printf ("curve %2d: %s\n", nsub, subkey->curve);
+ printf ("caps %2d: %s%s%s%s\n",
+ nsub,
+ subkey->can_encrypt? "e":"",
+ subkey->can_sign? "s":"",
+ subkey->can_certify? "c":"",
+ subkey->can_authenticate? "a":"");
+ printf ("flags %2d:%s%s%s%s%s%s%s\n",
+ nsub,
+ subkey->secret? " secret":"",
+ subkey->revoked? " revoked":"",
+ subkey->expired? " expired":"",
+ subkey->disabled? " disabled":"",
+ subkey->invalid? " invalid":"",
+ subkey->is_qualified? " qualifid":"",
+ subkey->is_cardkey? " cardkey":"");
+ }
for (nuids=0, uid=key->uids; uid; uid = uid->next, nuids++)
{
printf ("userid %d: %s\n", nuids, nonnull(uid->uid));
- printf ("valid %d: %s\n", nuids,
+ printf (" mbox: %s\n", nonnull(uid->address));
+ if (uid->email && uid->email != uid->address)
+ printf (" email: %s\n", uid->email);
+ if (uid->name)
+ printf (" name: %s\n", uid->name);
+ if (uid->comment)
+ printf (" cmmnt: %s\n", uid->comment);
+ printf (" valid: %s\n",
uid->validity == GPGME_VALIDITY_UNKNOWN? "unknown":
uid->validity == GPGME_VALIDITY_UNDEFINED? "undefined":
uid->validity == GPGME_VALIDITY_NEVER? "never":
uid->validity == GPGME_VALIDITY_MARGINAL? "marginal":
uid->validity == GPGME_VALIDITY_FULL? "full":
uid->validity == GPGME_VALIDITY_ULTIMATE? "ultimate": "[?]");
+ if ((ti = uid->tofu))
+ {
+ printf (" tofu: %u (%s)\n", ti->validity,
+ ti->validity == 0? "conflict" :
+ ti->validity == 1? "no history" :
+ ti->validity == 2? "little history" :
+ ti->validity == 3? "enough history" :
+ ti->validity == 4? "lot of history" : "?");
+ printf (" policy: %u (%s)\n", ti->policy,
+ ti->policy == GPGME_TOFU_POLICY_NONE? "none" :
+ ti->policy == GPGME_TOFU_POLICY_AUTO? "auto" :
+ ti->policy == GPGME_TOFU_POLICY_GOOD? "good" :
+ ti->policy == GPGME_TOFU_POLICY_UNKNOWN? "unknown" :
+ ti->policy == GPGME_TOFU_POLICY_BAD? "bad" :
+ ti->policy == GPGME_TOFU_POLICY_ASK? "ask" : "?");
+ printf (" nsigs: %hu\n", ti->signcount);
+ printf (" first: %s\n", isotimestr (ti->signfirst));
+ printf (" last: %s\n", isotimestr (ti->signlast));
+ printf (" nencr: %hu\n", ti->encrcount);
+ printf (" first: %s\n", isotimestr (ti->encrfirst));
+ printf (" last: %s\n", isotimestr (ti->encrlast));
+ }
}
putchar ('\n');
diff --git a/tests/run-keysign.c b/tests/run-keysign.c
new file mode 100644
index 0000000..f5a13e4
--- /dev/null
+++ b/tests/run-keysign.c
@@ -0,0 +1,261 @@
+/* run-keysign.c - Test tool to sign a key
+ * Copyright (C) 2016 g10 Code GmbH
+ *
+ * This file is part of GPGME.
+ *
+ * GPGME is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU Lesser General Public License as
+ * published by the Free Software Foundation; either version 2.1 of
+ * the License, or (at your option) any later version.
+ *
+ * GPGME is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this program; if not, see <http://www.gnu.org/licenses/>.
+ */
+
+/* We need to include config.h so that we know whether we are building
+ with large file system (LFS) support. */
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+#endif
+
+#include <stdlib.h>
+#include <stdio.h>
+#include <string.h>
+#include <assert.h>
+
+#include <gpgme.h>
+
+#define PGM "run-keysign"
+
+#include "run-support.h"
+
+
+static int verbose;
+
+
+static gpg_error_t
+status_cb (void *opaque, const char *keyword, const char *value)
+{
+ (void)opaque;
+ fprintf (stderr, "status_cb: %s %s\n", nonnull(keyword), nonnull(value));
+ return 0;
+}
+
+
+static unsigned long
+parse_expire_string (const char *string)
+{
+ unsigned long seconds;
+
+ if (!string || !*string || !strcmp (string, "none")
+ || !strcmp (string, "never") || !strcmp (string, "-"))
+ seconds = 0;
+ else if (strspn (string, "01234567890") == strlen (string))
+ seconds = strtoul (string, NULL, 10);
+ else
+ {
+ fprintf (stderr, PGM ": invalid value '%s'\n", string);
+ exit (1);
+ }
+
+ return seconds;
+}
+
+
+
+static int
+show_usage (int ex)
+{
+ fputs ("usage: " PGM " [options] FPR USERIDS\n\n"
+ "Options:\n"
+ " --verbose run in verbose mode\n"
+ " --status print status lines from the backend\n"
+ " --loopback use a loopback pinentry\n"
+ " --signer NAME use key NAME for signing\n"
+ " --local create a local signature\n"
+ " --noexpire force no expiration\n"
+ " --expire EPOCH expire the signature at EPOCH\n"
+ , stderr);
+ exit (ex);
+}
+
+
+int
+main (int argc, char **argv)
+{
+ int last_argc = -1;
+ gpgme_error_t err;
+ gpgme_ctx_t ctx;
+ gpgme_protocol_t protocol = GPGME_PROTOCOL_OpenPGP;
+ const char *signer_string = NULL;
+ int print_status = 0;
+ int use_loopback = 0;
+ const char *userid;
+ unsigned int flags = 0;
+ unsigned long expire = 0;
+ gpgme_key_t thekey;
+ int i;
+ size_t n;
+ char *userid_buffer = NULL;
+
+ if (argc)
+ { argc--; argv++; }
+
+ while (argc && last_argc != argc )
+ {
+ last_argc = argc;
+ if (!strcmp (*argv, "--"))
+ {
+ argc--; argv++;
+ break;
+ }
+ else if (!strcmp (*argv, "--help"))
+ show_usage (0);
+ else if (!strcmp (*argv, "--verbose"))
+ {
+ verbose = 1;
+ argc--; argv++;
+ }
+ else if (!strcmp (*argv, "--status"))
+ {
+ print_status = 1;
+ argc--; argv++;
+ }
+ else if (!strcmp (*argv, "--signer"))
+ {
+ argc--; argv++;
+ if (!argc)
+ show_usage (1);
+ signer_string = *argv;
+ argc--; argv++;
+ }
+ else if (!strcmp (*argv, "--loopback"))
+ {
+ use_loopback = 1;
+ argc--; argv++;
+ }
+ else if (!strcmp (*argv, "--local"))
+ {
+ flags |= GPGME_KEYSIGN_LOCAL;
+ argc--; argv++;
+ }
+ else if (!strcmp (*argv, "--noexpire"))
+ {
+ flags |= GPGME_KEYSIGN_NOEXPIRE;
+ argc--; argv++;
+ }
+ else if (!strcmp (*argv, "--expire"))
+ {
+ argc--; argv++;
+ if (!argc)
+ show_usage (1);
+ expire = parse_expire_string (*argv);
+ argc--; argv++;
+ }
+ else if (!strncmp (*argv, "--", 2))
+ show_usage (1);
+ }
+
+ if (!argc)
+ show_usage (1);
+ userid = argv[0];
+ argc--; argv++;
+
+ init_gpgme (protocol);
+
+ err = gpgme_new (&ctx);
+ fail_if_err (err);
+ gpgme_set_protocol (ctx, protocol);
+ gpgme_set_armor (ctx, 1);
+ if (print_status)
+ {
+ gpgme_set_status_cb (ctx, status_cb, NULL);
+ gpgme_set_ctx_flag (ctx, "full-status", "1");
+ }
+ if (use_loopback)
+ {
+ gpgme_set_pinentry_mode (ctx, GPGME_PINENTRY_MODE_LOOPBACK);
+ gpgme_set_passphrase_cb (ctx, passphrase_cb, NULL);
+ }
+
+ if (signer_string)
+ {
+ gpgme_key_t akey;
+
+ err = gpgme_get_key (ctx, signer_string, &akey, 1);
+ if (err)
+ {
+ fprintf (stderr, PGM ": error getting signer key '%s': %s\n",
+ signer_string, gpg_strerror (err));
+ exit (1);
+ }
+ err = gpgme_signers_add (ctx, akey);
+ if (err)
+ {
+ fprintf (stderr, PGM ": error adding signer key: %s\n",
+ gpg_strerror (err));
+ exit (1);
+ }
+ gpgme_key_unref (akey);
+ }
+
+
+ err = gpgme_get_key (ctx, userid, &thekey, 0);
+ if (err)
+ {
+ fprintf (stderr, PGM ": error getting key for '%s': %s\n",
+ userid, gpg_strerror (err));
+ exit (1);
+ }
+
+ if (argc > 1)
+ {
+ /* Several user ids given */
+ for (i=0, n = 0; i < argc; i++)
+ n += strlen (argv[1]) + 1;
+ n++;
+ userid_buffer = malloc (n);
+ if (!userid_buffer)
+ {
+ fprintf (stderr, PGM ": malloc failed: %s\n",
+ gpg_strerror (gpg_error_from_syserror ()));
+ exit (1);
+ }
+ *userid_buffer = 0;
+ for (i=0; i < argc; i++)
+ {
+ strcat (userid_buffer, argv[i]);
+ strcat (userid_buffer, "\n");
+ }
+ userid = userid_buffer;
+ flags |= GPGME_KEYSIGN_LFSEP;
+ }
+ else if (argc)
+ {
+ /* One user id given */
+ userid = *argv;
+ }
+ else
+ {
+ /* No user id given. */
+ userid = NULL;
+ }
+
+ err = gpgme_op_keysign (ctx, thekey, userid, expire, flags);
+ if (err)
+ {
+ fprintf (stderr, PGM ": gpgme_op_adduid failed: %s\n",
+ gpg_strerror (err));
+ exit (1);
+ }
+
+ free (userid_buffer);
+ gpgme_key_unref (thekey);
+ gpgme_release (ctx);
+ return 0;
+}
diff --git a/tests/run-sign.c b/tests/run-sign.c
index c59c356..70853ed 100644
--- a/tests/run-sign.c
+++ b/tests/run-sign.c
@@ -51,6 +51,8 @@ print_result (gpgme_sign_result_t result, gpgme_sig_mode_t type)
gpgme_invalid_key_t invkey;
gpgme_new_signature_t sig;
+ (void)type;
+
for (invkey = result->invalid_signers; invkey; invkey = invkey->next)
printf ("Signing key `%s' not used: %s <%s>\n",
nonnull (invkey->fpr),
diff --git a/tests/run-support.h b/tests/run-support.h
index b1aea4b..e4a4f70 100644
--- a/tests/run-support.h
+++ b/tests/run-support.h
@@ -75,27 +75,25 @@ gpgme_error_t
passphrase_cb (void *opaque, const char *uid_hint, const char *passphrase_info,
int last_was_bad, int fd)
{
-#ifdef HAVE_W32_SYSTEM
- DWORD written;
- WriteFile ((HANDLE) fd, "abc\n", 4, &written, 0);
-#else
int res;
- char *pass = "abc\n";
+ char pass[] = "abc\n";
int passlen = strlen (pass);
int off = 0;
+ (void)opaque;
+ (void)uid_hint;
+ (void)passphrase_info;
+ (void)last_was_bad;
+
do
{
- res = write (fd, &pass[off], passlen - off);
+ res = gpgme_io_write (fd, &pass[off], passlen - off);
if (res > 0)
off += res;
}
while (res > 0 && off != passlen);
return off == passlen ? 0 : gpgme_error_from_errno (errno);
-#endif
-
- return 0;
}
diff --git a/tests/run-tofu.c b/tests/run-tofu.c
new file mode 100644
index 0000000..ff55789
--- /dev/null
+++ b/tests/run-tofu.c
@@ -0,0 +1,178 @@
+/* run-tofu.c - Test tool for Tofu functions
+ * Copyright (C) 2016 g10 Code GmbH
+ *
+ * This file is part of GPGME.
+ *
+ * GPGME is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU Lesser General Public License as
+ * published by the Free Software Foundation; either version 2.1 of
+ * the License, or (at your option) any later version.
+ *
+ * GPGME is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this program; if not, see <http://www.gnu.org/licenses/>.
+ */
+
+/* We need to include config.h so that we know whether we are building
+ with large file system (LFS) support. */
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+#endif
+
+#include <stdlib.h>
+#include <stdio.h>
+#include <string.h>
+#include <assert.h>
+
+#include <gpgme.h>
+
+#define PGM "run-tofu"
+
+#include "run-support.h"
+
+
+static int verbose;
+
+
+static gpg_error_t
+status_cb (void *opaque, const char *keyword, const char *value)
+{
+ (void)opaque;
+ fprintf (stderr, "status_cb: %s %s\n", nonnull(keyword), nonnull(value));
+ return 0;
+}
+
+
+
+static gpgme_tofu_policy_t
+parse_policy_string (const char *string)
+{
+ gpgme_tofu_policy_t policy;
+
+ if (!strcmp (string, "auto"))
+ policy = GPGME_TOFU_POLICY_AUTO;
+ else if (!strcmp (string, "good"))
+ policy = GPGME_TOFU_POLICY_GOOD;
+ else if (!strcmp (string, "bad"))
+ policy = GPGME_TOFU_POLICY_BAD;
+ else if (!strcmp (string, "ask"))
+ policy = GPGME_TOFU_POLICY_ASK;
+ else if (!strcmp (string, "unknown"))
+ policy = GPGME_TOFU_POLICY_UNKNOWN;
+ else
+ {
+ fprintf (stderr, PGM ": invalid policy value '%s'\n", string);
+ exit (1);
+ }
+
+ return policy;
+}
+
+
+
+static int
+show_usage (int ex)
+{
+ fputs ("usage: " PGM " [options] FPR\n\n"
+ "Options:\n"
+ " --policy NAME Set tofu policy for key to NAME\n"
+ " --verbose run in verbose mode\n"
+ " --status print status lines from the backend\n"
+ , stderr);
+ exit (ex);
+}
+
+
+int
+main (int argc, char **argv)
+{
+ int last_argc = -1;
+ gpgme_error_t err;
+ gpgme_ctx_t ctx;
+ gpgme_protocol_t protocol = GPGME_PROTOCOL_OpenPGP;
+ int print_status = 0;
+ gpgme_key_t thekey;
+ const char *fpr;
+ const char *policystr = NULL;
+ gpgme_tofu_policy_t policy;
+
+ if (argc)
+ { argc--; argv++; }
+
+ while (argc && last_argc != argc )
+ {
+ last_argc = argc;
+ if (!strcmp (*argv, "--"))
+ {
+ argc--; argv++;
+ break;
+ }
+ else if (!strcmp (*argv, "--help"))
+ show_usage (0);
+ else if (!strcmp (*argv, "--verbose"))
+ {
+ verbose = 1;
+ argc--; argv++;
+ }
+ else if (!strcmp (*argv, "--status"))
+ {
+ print_status = 1;
+ argc--; argv++;
+ }
+ else if (!strcmp (*argv, "--policy"))
+ {
+ argc--; argv++;
+ if (!argc)
+ show_usage (1);
+ policystr = *argv;
+ argc--; argv++;
+ }
+ else if (!strncmp (*argv, "--", 2))
+ show_usage (1);
+ }
+
+ if (argc != 1)
+ show_usage (1);
+ fpr = argv[0];
+
+ init_gpgme (protocol);
+
+ err = gpgme_new (&ctx);
+ fail_if_err (err);
+ gpgme_set_protocol (ctx, protocol);
+ gpgme_set_armor (ctx, 1);
+ if (print_status)
+ {
+ gpgme_set_status_cb (ctx, status_cb, NULL);
+ gpgme_set_ctx_flag (ctx, "full-status", "1");
+ }
+
+ err = gpgme_get_key (ctx, fpr, &thekey, 0);
+ if (err)
+ {
+ fprintf (stderr, PGM ": error getting key '%s': %s\n",
+ fpr, gpg_strerror (err));
+ exit (1);
+ }
+
+ if (policystr)
+ {
+ policy = parse_policy_string (policystr);
+
+ err = gpgme_op_tofu_policy (ctx, thekey, policy);
+ if (err)
+ {
+ fprintf (stderr, PGM ": gpgme_op_tofu_polciy failed: %s\n",
+ gpg_strerror (err));
+ exit (1);
+ }
+ }
+
+ gpgme_key_unref (thekey);
+ gpgme_release (ctx);
+ return 0;
+}
diff --git a/tests/run-verify.c b/tests/run-verify.c
index b49ea2a..ebc20d9 100644
--- a/tests/run-verify.c
+++ b/tests/run-verify.c
@@ -26,6 +26,7 @@
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
+#include <time.h>
#include <gpgme.h>
@@ -36,6 +37,35 @@
static int verbose;
+
+static const char *
+isotimestr (unsigned long value)
+{
+ time_t t;
+ static char buffer[25+5];
+ struct tm *tp;
+
+ if (!value)
+ return "none";
+ t = value;
+
+ tp = gmtime (&t);
+ snprintf (buffer, sizeof buffer, "%04d-%02d-%02d %02d:%02d:%02d",
+ 1900+tp->tm_year, tp->tm_mon+1, tp->tm_mday,
+ tp->tm_hour, tp->tm_min, tp->tm_sec);
+ return buffer;
+}
+
+
+static gpg_error_t
+status_cb (void *opaque, const char *keyword, const char *value)
+{
+ (void)opaque;
+ fprintf (stderr, "status_cb: %s %s\n", keyword, value);
+ return 0;
+}
+
+
static void
print_summary (gpgme_sigsum_t summary)
{
@@ -85,9 +115,25 @@ print_validity (gpgme_validity_t val)
static void
+print_description (const char *text, int indent)
+{
+ for (; *text; text++)
+ {
+ putchar (*text);
+ if (*text == '\n')
+ printf ("%*s", indent, "");
+ }
+ putchar ('\n');
+}
+
+
+static void
print_result (gpgme_verify_result_t result)
{
gpgme_signature_t sig;
+ gpgme_sig_notation_t nt;
+ gpgme_user_id_t uid;
+ gpgme_tofu_info_t ti;
int count = 0;
printf ("Original file name: %s\n", nonnull(result->file_name));
@@ -102,8 +148,10 @@ print_result (gpgme_verify_result_t result)
printf (" validity ..: ");
print_validity (sig->validity); putchar ('\n');
printf (" val.reason : %s\n", gpgme_strerror (sig->status));
- printf (" pubkey algo: %d\n", sig->pubkey_algo);
- printf (" digest algo: %d\n", sig->hash_algo);
+ printf (" pubkey algo: %d (%s)\n", sig->pubkey_algo,
+ nonnull(gpgme_pubkey_algo_name (sig->pubkey_algo)));
+ printf (" digest algo: %d (%s)\n", sig->hash_algo,
+ nonnull(gpgme_hash_algo_name (sig->hash_algo)));
printf (" pka address: %s\n", nonnull (sig->pka_address));
printf (" pka trust .: %s\n",
sig->pka_trust == 0? "n/a" :
@@ -113,8 +161,52 @@ print_result (gpgme_verify_result_t result)
sig->wrong_key_usage? " wrong-key-usage":"",
sig->chain_model? " chain-model":""
);
- printf (" notations .: %s\n",
- sig->notations? "yes":"no");
+ for (nt = sig->notations; nt; nt = nt->next)
+ {
+ printf (" notation ..: '%s'\n", nt->name);
+ if (strlen (nt->name) != nt->name_len)
+ printf (" warning : name larger (%d)\n", nt->name_len);
+ printf (" flags ...:%s%s (0x%02x)\n",
+ nt->critical? " critical":"",
+ nt->human_readable? " human":"",
+ nt->flags);
+ if (nt->value)
+ printf (" value ...: '%s'\n", nt->value);
+ if ((nt->value?strlen (nt->value):0) != nt->value_len)
+ printf (" warning : value larger (%d)\n", nt->value_len);
+ }
+ if (sig->key)
+ {
+ printf (" primary fpr: %s\n", nonnull (sig->key->fpr));
+ for (uid = sig->key->uids; uid; uid = uid->next)
+ {
+ printf (" tofu addr .: %s\n", nonnull (uid->address));
+ ti = uid->tofu;
+ if (!ti)
+ continue;
+ printf (" validity : %u (%s)\n", ti->validity,
+ ti->validity == 0? "conflict" :
+ ti->validity == 1? "no history" :
+ ti->validity == 2? "little history" :
+ ti->validity == 3? "enough history" :
+ ti->validity == 4? "lot of history" : "?");
+ printf (" policy ..: %u (%s)\n", ti->policy,
+ ti->policy == GPGME_TOFU_POLICY_NONE? "none" :
+ ti->policy == GPGME_TOFU_POLICY_AUTO? "auto" :
+ ti->policy == GPGME_TOFU_POLICY_GOOD? "good" :
+ ti->policy == GPGME_TOFU_POLICY_UNKNOWN? "unknown" :
+ ti->policy == GPGME_TOFU_POLICY_BAD? "bad" :
+ ti->policy == GPGME_TOFU_POLICY_ASK? "ask" : "?");
+ printf (" signcount: %hu\n", ti->signcount);
+ printf (" first..: %s\n", isotimestr (ti->signfirst));
+ printf (" last ..: %s\n", isotimestr (ti->signlast));
+ printf (" encrcount: %hu\n", ti->encrcount);
+ printf (" first..: %s\n", isotimestr (ti->encrfirst));
+ printf (" last ..: %s\n", isotimestr (ti->encrlast));
+ printf (" desc ....: ");
+ print_description (nonnull (ti->description), 15);
+ }
+ }
}
}
@@ -126,6 +218,7 @@ show_usage (int ex)
fputs ("usage: " PGM " [options] [DETACHEDSIGFILE] FILE\n\n"
"Options:\n"
" --verbose run in verbose mode\n"
+ " --status print status lines from the backend\n"
" --openpgp use the OpenPGP protocol (default)\n"
" --cms use the CMS protocol\n"
, stderr);
@@ -145,6 +238,7 @@ main (int argc, char **argv)
FILE *fp_msg = NULL;
gpgme_data_t msg = NULL;
gpgme_verify_result_t result;
+ int print_status = 0;
if (argc)
{ argc--; argv++; }
@@ -164,6 +258,11 @@ main (int argc, char **argv)
verbose = 1;
argc--; argv++;
}
+ else if (!strcmp (*argv, "--status"))
+ {
+ print_status = 1;
+ argc--; argv++;
+ }
else if (!strcmp (*argv, "--openpgp"))
{
protocol = GPGME_PROTOCOL_OpenPGP;
@@ -207,6 +306,12 @@ main (int argc, char **argv)
err = gpgme_new (&ctx);
fail_if_err (err);
gpgme_set_protocol (ctx, protocol);
+ if (print_status)
+ {
+ gpgme_set_status_cb (ctx, status_cb, NULL);
+ gpgme_set_ctx_flag (ctx, "full-status", "1");
+ }
+ /* gpgme_set_ctx_flag (ctx, "raw-description", "1"); */
err = gpgme_data_new_from_stream (&sig, fp_sig);
if (err)
@@ -232,7 +337,7 @@ main (int argc, char **argv)
print_result (result);
if (err)
{
- fprintf (stderr, PGM ": signing failed: %s\n", gpgme_strerror (err));
+ fprintf (stderr, PGM ": verify failed: %s\n", gpgme_strerror (err));
exit (1);
}
diff --git a/tests/t-data.c b/tests/t-data.c
index 888475f..fe2d59e 100644
--- a/tests/t-data.c
+++ b/tests/t-data.c
@@ -86,6 +86,8 @@ read_cb (void *cb_value, char *buffer, size_t count, size_t *nread)
unsigned int amount = strlen (text) - off;
/* round_t round = *((round_t *) cb_value); */
+ (void)cb_value;
+
if (!buffer && !count && !nread)
{
/* Rewind requested. */
@@ -143,7 +145,7 @@ read_test (round_t round, gpgme_data_t data)
read = gpgme_data_read (data, buffer, sizeof (buffer));
if (read > 0)
{
- fprintf (stderr, "%s:%d: (%i) gpgme_data_read succeded unexpectedly\n",
+ fprintf (stderr, "%s:%d: (%i) gpgme_data_read succeeded unexpectedly\n",
__FILE__, __LINE__, round);
exit (1);
}
@@ -190,12 +192,13 @@ write_test (round_t round, gpgme_data_t data)
}
}
+
int
-main (int argc, char **argv)
+main (void)
{
round_t round = TEST_INITIALIZER;
- const char *text_filename = make_filename ("t-data-1.txt");
- const char *longer_text_filename = make_filename ("t-data-2.txt");
+ char *text_filename = make_filename ("t-data-1.txt");
+ char *longer_text_filename = make_filename ("t-data-2.txt");
const char *missing_filename = "this-file-surely-does-not-exist";
gpgme_error_t err = 0;
gpgme_data_t data;
@@ -269,7 +272,7 @@ main (int argc, char **argv)
}
break;
case TEST_END:
- return 0;
+ goto out;
case TEST_INITIALIZER:
/* Shouldn't happen. */
fprintf (stderr, "%s:%d: impossible condition\n", __FILE__, __LINE__);
@@ -281,5 +284,8 @@ main (int argc, char **argv)
write_test (round, data);
gpgme_data_release (data);
}
+ out:
+ free (text_filename);
+ free (longer_text_filename);
return 0;
}
diff --git a/tests/t-engine-info.c b/tests/t-engine-info.c
index 53f5b2f..8f617f9 100644
--- a/tests/t-engine-info.c
+++ b/tests/t-engine-info.c
@@ -111,8 +111,20 @@ main (int argc, char **argv )
gpgme_check_version (NULL);
{
- const char *keys[] = {"homedir", "agent-socket", "uiserver-socket",
- "gpgconf-name", "gpg-name", "gpgsm-name",
+ const char *keys[] = {"homedir",
+ "sysconfdir",
+ "bindir",
+ "libexecdir",
+ "libdir",
+ "datadir",
+ "localedir",
+ "agent-socket",
+ "agent-ssh-socket",
+ "dirmngr-socket",
+ "uiserver-socket",
+ "gpgconf-name",
+ "gpg-name",
+ "gpgsm-name",
"g13-name", NULL };
const char *s;
int i;