Compare commits
6 Commits
master
...
dkg/fix-T4
Author | SHA1 | Date | |
---|---|---|---|
|
ac8d7238db | ||
|
5e21e61cfe | ||
|
fefa46173e | ||
|
30ddb2cabc | ||
|
9a1903cc42 | ||
|
827a2f3ad5 |
16
AUTHORS
16
AUTHORS
@ -9,24 +9,20 @@ License (software): LGPL-2.1-or-later
|
||||
License (manual+tools): GPL-3.0-or-later
|
||||
|
||||
|
||||
GPGME is free software. See the files COPYING.LESSER and COPYING for
|
||||
copying conditions, , and LICENSES for notices about contributions
|
||||
that require these additional notices to be distributed. License
|
||||
copyright years may be listed using range notation, e.g., 2000-2013,
|
||||
indicating that every year in the range, inclusive, is a copyrightable
|
||||
year that would otherwise be listed individually.
|
||||
|
||||
GPGME is free software. See the files COPYING for copying conditions.
|
||||
License copyright years may be listed using range notation, e.g.,
|
||||
2000-2013, indicating that every year in the range, inclusive, is a
|
||||
copyrightable year that would otherwise be listed individually.
|
||||
|
||||
List of Copyright holders
|
||||
=========================
|
||||
|
||||
Copyright (C) 1991-2013 Free Software Foundation, Inc.
|
||||
Copyright (C) 2000-2001 Werner Koch
|
||||
Copyright (C) 2001-2023 g10 Code GmbH
|
||||
Copyright (C) 2001-2018 g10 Code GmbH
|
||||
Copyright (C) 2002 Klarälvdalens Datakonsult AB
|
||||
Copyright (C) 2004-2008 Igor Belyi
|
||||
Copyright (C) 2002 John Goerzen
|
||||
Copyright (c) 2009 Dave Gamble
|
||||
Copyright (C) 2014, 2015 Martin Albrecht
|
||||
Copyright (C) 2015, 2018 Ben McGinnes
|
||||
Copyright (C) 2015, 2016, 2018
|
||||
@ -43,7 +39,7 @@ FSF <gnu@gnu.org>
|
||||
src/stpcpy.c, src/w32-ce.c.
|
||||
|
||||
g10 Code GmbH <code@g10code.com>
|
||||
- All stuff since mid March 2001.
|
||||
- All stuff since mid march 2001.
|
||||
|
||||
Werner Koch <wk@gnupg.org>
|
||||
- Design and most stuff.
|
||||
|
38
LICENSES
38
LICENSES
@ -1,38 +0,0 @@
|
||||
Additional license notices for GPGME. -*- org -*-
|
||||
|
||||
This file contains the copying permission notices for various files in
|
||||
the GPGME distribution which are not covered by the GNU Lesser
|
||||
General Public License (LGPL) or the GNU General Public License (GPL).
|
||||
|
||||
These notices all require that a copy of the notice be included
|
||||
in the accompanying documentation and be distributed with binary
|
||||
distributions of the code, so be sure to include this file along
|
||||
with any binary distributions derived from the GNU C Library.
|
||||
|
||||
* MIT License
|
||||
|
||||
For files:
|
||||
- cJSON.c, cJSON.h
|
||||
|
||||
#+begin_quote
|
||||
Copyright (c) 2009 Dave Gamble
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining
|
||||
a opy of this software and associated documentation files (the
|
||||
"Software"), to eal in the Software without restriction, including
|
||||
without limitation the ights to use, copy, modify, merge, publish,
|
||||
distribute, sublicense, and/or sell copies of the Software, and to
|
||||
permit persons to whom the Software is furnished to do so, subject to
|
||||
the following conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be
|
||||
included in all copies or substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
||||
EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
||||
MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
||||
NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
|
||||
LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
|
||||
OF CONTRACT, TORT OR OTHERWISE, ARISING ROM, OUT OF OR IN CONNECTION
|
||||
WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||
#+end_quote
|
39
Makefile.am
39
Makefile.am
@ -20,14 +20,14 @@
|
||||
|
||||
## Process this file with automake to produce Makefile.in
|
||||
|
||||
# Location of the released tarball archives. This is prefixed by
|
||||
# the variable RELEASE_ARCHIVE in ~/.gnupg-autogen.rc. For example:
|
||||
# RELEASE_ARCHIVE=user@host:archive/tarballs
|
||||
RELEASE_ARCHIVE_SUFFIX = gpgme
|
||||
# The variable RELEASE_SIGNKEY in ~/.gnupg-autogen.rc is used
|
||||
# to specify the key for signing. For example:
|
||||
# RELEASE_SIGNKEY=D8692123C4065DEA5E0F3AB5249B39D24F25E3B6
|
||||
# Location of the released tarball archives. Note that this is an
|
||||
# internal archive and before uploading this to the public server,
|
||||
# manual tests should be run and the git release tat set and pushed.
|
||||
# Adjust as needed.
|
||||
RELEASE_ARCHIVE_DIR = wk@vigenere:tarballs/gpgme/
|
||||
|
||||
# The key used to sign the released sources. Adjust as needed.
|
||||
RELEASE_SIGNING_KEY = D8692123C4065DEA5E0F3AB5249B39D24F25E3B6
|
||||
|
||||
# Autoconf flags
|
||||
ACLOCAL_AMFLAGS = -I m4
|
||||
@ -36,11 +36,8 @@ DISTCHECK_CONFIGURE_FLAGS =
|
||||
|
||||
EXTRA_DIST = autogen.sh autogen.rc gpgme.spec.in \
|
||||
ChangeLog-2011 m4/ChangeLog-2011 \
|
||||
build-aux/libtool-patch.sed \
|
||||
conf/whatisthis VERSION LICENSES
|
||||
conf/whatisthis VERSION
|
||||
|
||||
# This artificial line is to put a dependency to conf/config.h for 'all'
|
||||
BUILT_SOURCES = conf/config.h
|
||||
|
||||
if RUN_GPG_TESTS
|
||||
tests = tests
|
||||
@ -100,7 +97,7 @@ release:
|
||||
cd $(abs_top_builddir); \
|
||||
rm -rf dist; mkdir dist ; cd dist ; \
|
||||
$(abs_top_srcdir)/configure --enable-maintainer-mode; \
|
||||
$(MAKE) distcheck; \
|
||||
$(MAKE) distcheck TESTFLAGS=--parallel; \
|
||||
echo "/* Build finished at $$(date -uIseconds) */" ;\
|
||||
echo "/*" ;\
|
||||
echo " * Please run the final step interactively:" ;\
|
||||
@ -110,32 +107,20 @@ release:
|
||||
|
||||
sign-release:
|
||||
+(set -e; \
|
||||
test $$(pwd | sed 's,.*/,,') = dist || cd dist; \
|
||||
x=$$(grep '^RELEASE_ARCHIVE=' $$HOME/.gnupg-autogen.rc|cut -d= -f2);\
|
||||
if [ -z "$$x" ]; then \
|
||||
echo "error: RELEASE_ARCHIVE missing in ~/.gnupg-autogen.rc">&2; \
|
||||
exit 2;\
|
||||
fi;\
|
||||
myarchive="$$x/$(RELEASE_ARCHIVE_SUFFIX)";\
|
||||
x=$$(grep '^RELEASE_SIGNKEY=' $$HOME/.gnupg-autogen.rc|cut -d= -f2);\
|
||||
if [ -z "$$x" ]; then \
|
||||
echo "error: RELEASE_SIGNKEY missing in ~/.gnupg-autogen.rc">&2; \
|
||||
exit 2;\
|
||||
fi;\
|
||||
mysignkey="$$x";\
|
||||
cd dist; \
|
||||
files1="$(RELEASE_NAME).tar.bz2" ;\
|
||||
files2="$(RELEASE_NAME).tar.bz2.sig \
|
||||
$(RELEASE_NAME).swdb \
|
||||
$(RELEASE_NAME).buildlog" ;\
|
||||
echo "/* Signing the source tarball ..." ;\
|
||||
gpg -sbu $$mysignkey $(RELEASE_NAME).tar.bz2 ;\
|
||||
gpg -sbu $(RELEASE_SIGNING_KEY) $(RELEASE_NAME).tar.bz2 ;\
|
||||
cat $(RELEASE_NAME).swdb >swdb.snippet;\
|
||||
echo >>swdb.snippet ;\
|
||||
sha1sum $${files1} >>swdb.snippet ;\
|
||||
cat "../$(RELEASE_NAME).buildlog" swdb.snippet \
|
||||
| gzip >$(RELEASE_NAME).buildlog ;\
|
||||
echo "Copying to local archive ..." ;\
|
||||
scp -p $${files1} $${files2} $$myarchive/ || true;\
|
||||
scp -p $${files1} $${files2} $(RELEASE_ARCHIVE_DIR)/ || true;\
|
||||
echo "Uploading documentation ..." ;\
|
||||
$(MAKE) -C doc online; \
|
||||
echo '/*' ;\
|
||||
|
756
NEWS
756
NEWS
@ -1,767 +1,13 @@
|
||||
Noteworthy changes in version 1.24.0 (unrelease)
|
||||
Noteworthy changes in version 1.12.1 (unreleased)
|
||||
-------------------------------------------------
|
||||
|
||||
* Extended gpgme_op_decrypt* and gpgme_op_verify* to allow writing the
|
||||
output directly to a file. [T6550]
|
||||
|
||||
* Extended gpgme_op_encrypt*, gpgme_op_encrypt_sign*, and gpgme_op_sign*
|
||||
to allow reading the input data directly from a file. [T6550]
|
||||
|
||||
* Add information about designated revocation keys. [T7118]
|
||||
|
||||
* New context flag "import-options". [T7152]
|
||||
|
||||
* cpp: Provide information about designated revocation keys for a Key.
|
||||
[T7118]
|
||||
|
||||
* cpp: Add safer member function returning text describing an error.
|
||||
[T5960]
|
||||
|
||||
* qt: Build QGpgME for Qt 5 and Qt 6 simultaneously. [T7205]
|
||||
|
||||
* qt: Install headers for Qt 5 and Qt 6 in separate folders. [T7161]
|
||||
|
||||
* qt: Allow reading the data to decrypt/encrypt/sign/verify directly from
|
||||
files. [T6550]
|
||||
|
||||
* qt: Allow writing the decrypted/encrypted/signed/verified data directly
|
||||
to files. [T6550]
|
||||
|
||||
* qt: Allow specifying import options when importing keys. [T7152]
|
||||
|
||||
* qt: Allow appending a detached signature to an existing file. [T6867]
|
||||
|
||||
* Interface changes relative to the 1.23.2 release:
|
||||
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
GPGME_ENCRYPT_FILE NEW.
|
||||
GPGME_SIG_MODE_FILE NEW.
|
||||
gpgme_key_t EXTENDED: New field 'revkeys'.
|
||||
gpgme_revocation_key_t NEW.
|
||||
gpgme_set_ctx_flag EXTENDED: New flag 'import-options'.
|
||||
cpp: Context::EncryptFile NEW.
|
||||
cpp: SignatureMode::SignFile NEW.
|
||||
cpp: RevocationKey NEW.
|
||||
cpp: Key::revocationKey NEW.
|
||||
cpp: Key::numRevocationKeys NEW.
|
||||
cpp: Key::revocationKeys NEW.
|
||||
cpp: Error::asStdString NEW.
|
||||
cpp: Error::asString DEPRECATED.
|
||||
qt: DecryptVerifyJob::setInputFile NEW.
|
||||
qt: DecryptVerifyJob::inputFile NEW.
|
||||
qt: DecryptVerifyJob::setOutputFile NEW.
|
||||
qt: DecryptVerifyJob::outputFile NEW.
|
||||
qt: EncryptJob::setRecipients NEW.
|
||||
qt: EncryptJob::recipients NEW.
|
||||
qt: EncryptJob::setInputFile NEW.
|
||||
qt: EncryptJob::inputFile NEW.
|
||||
qt: EncryptJob::setOutputFile NEW.
|
||||
qt: EncryptJob::outputFile NEW.
|
||||
qt: EncryptJob::setEncryptionFlags NEW.
|
||||
qt: EncryptJob::encryptionFlags NEW.
|
||||
qt: SignEncryptJob::setSigners NEW.
|
||||
qt: SignEncryptJob::signers NEW.
|
||||
qt: SignEncryptJob::setRecipients NEW.
|
||||
qt: SignEncryptJob::recipients NEW.
|
||||
qt: SignEncryptJob::setInputFile NEW.
|
||||
qt: SignEncryptJob::inputFile NEW.
|
||||
qt: SignEncryptJob::setOutputFile NEW.
|
||||
qt: SignEncryptJob::outputFile NEW.
|
||||
qt: SignEncryptJob::setEncryptionFlags NEW.
|
||||
qt: SignEncryptJob::encryptionFlags NEW.
|
||||
qt: SignJob::setSigners NEW.
|
||||
qt: SignJob::signers NEW.
|
||||
qt: SignJob::setInputFile NEW.
|
||||
qt: SignJob::inputFile NEW.
|
||||
qt: SignJob::setOutputFile NEW.
|
||||
qt: SignJob::outputFile NEW.
|
||||
qt: SignJob::setSigningFlags NEW.
|
||||
qt: SignJob::signingFlags NEW.
|
||||
qt: SignJob::setAppendSignature NEW.
|
||||
qt: SignJob::appendSignatureEnabled NEW.
|
||||
qt: VerifyDetachedJob::setSignatureFile NEW.
|
||||
qt: VerifyDetachedJob::signatureFile NEW.
|
||||
qt: VerifyDetachedJob::setSignedFile NEW.
|
||||
qt: VerifyDetachedJob::signedFile NEW.
|
||||
qt: VerifyOpaqueJob::setInputFile NEW.
|
||||
qt: VerifyOpaqueJob::inputFile NEW.
|
||||
qt: VerifyOpaqueJob::setOutputFile NEW.
|
||||
qt: VerifyOpaqueJob::outputFile NEW.
|
||||
qt: ImportJob::setImportOptions NEW.
|
||||
qt: ImportJob::importOptions NEW.
|
||||
|
||||
|
||||
Noteworthy changes in version 1.23.2 (2023-11-28)
|
||||
-------------------------------------------------
|
||||
|
||||
* Preserve more specific existing failure code. [T6575]
|
||||
|
||||
* qt: Start dirmngr with gpgconf to avoid multiple instances. [T6833]
|
||||
|
||||
* qt: On Windows, use UTF-8 when logging the error text. [T5960]
|
||||
|
||||
* qt: Remove left-over partial files more persistently. [T6584]
|
||||
|
||||
* qt: Use a temporary file name when creating signed or encrypted
|
||||
archives. [T6721]
|
||||
|
||||
* qt: Build Qt 6 bindings with -fPIC if requested or Qt 6 was built with
|
||||
this flag. [T6781]
|
||||
|
||||
Notes:
|
||||
~~~~~~
|
||||
qt: DefaultKeyGenerationJob DEPRECATED.
|
||||
|
||||
[c=C43/A32/R1 cpp=C26/A20/R1 qt=C20/A5/R1]
|
||||
|
||||
Release-info: https://dev.gnupg.org/T6782
|
||||
|
||||
|
||||
Noteworthy changes in version 1.23.1 (2023-10-27)
|
||||
-------------------------------------------------
|
||||
|
||||
* w32: Change gpgme-w32-spawn to use Unicode arguments. [T6728]
|
||||
|
||||
[c=C43/A32/R0 cpp=C26/A20/R0 qt=C20/A5/R0]
|
||||
|
||||
Release-info: https://dev.gnupg.org/T6774
|
||||
|
||||
|
||||
Noteworthy changes in version 1.23.0 (2023-10-25)
|
||||
-------------------------------------------------
|
||||
|
||||
* Support GPGME_ENCRYPT_ALWAYS_TRUST also for S/MIME. [T6559]
|
||||
|
||||
* New keylist mode GPGME_KEYLIST_MODE_WITH_V5FPR. [T6705]
|
||||
|
||||
* New key capability flags has_*. [T6748]
|
||||
|
||||
* gpgme-tool: Support use of Windows HANDLE. [T6634]
|
||||
|
||||
* qt: Support refreshing keys via WKD. [T6672]
|
||||
|
||||
* qt: Handle cancel in changeexpiryjob. [T6754]
|
||||
|
||||
* Interface changes relative to the 1.22.0 release:
|
||||
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
GPGME_KEYLIST_MODE_WITH_V5FPR NEW.
|
||||
gpgme_key_t EXTENDED: New field has_encrypt.
|
||||
gpgme_key_t EXTENDED: New field has_sign.
|
||||
gpgme_key_t EXTENDED: New field has_certify.
|
||||
gpgme_key_t EXTENDED: New field has_authenticate.
|
||||
cpp: Key::canCertify NEW.
|
||||
cpp: Key::canSign NEW.
|
||||
cpp: Key::canEncrypt NEW.
|
||||
cpp: Key::canAuthenticate NEW.
|
||||
qt: Protocol::wkdRefreshJob NEW.
|
||||
qt: WKDRefreshJob NEW.
|
||||
|
||||
[c=C43/A32/R0 cpp=C26/A20/R0 qt=C20/A5/R0]
|
||||
|
||||
Release-info: https://dev.gnupg.org/T6774
|
||||
|
||||
|
||||
Noteworthy changes in version 1.22.0 (2023-08-21)
|
||||
-------------------------------------------------
|
||||
|
||||
* Prevent wrong plaintext when verifying clearsigned signature. [T6622]
|
||||
|
||||
* Return bad data error instead of general error on unexpected data.
|
||||
[T6617]
|
||||
|
||||
* Take care of offline mode for all operations of gpgsm engine.
|
||||
[T6648]
|
||||
|
||||
* Prepare the use of the forthcoming libassuan version 3.
|
||||
|
||||
* New configure option --with-libtool-modification. [T6619]
|
||||
|
||||
* cpp: Expose gpgme_decrypt_result_t.is_mime. [T6199]
|
||||
|
||||
* qt: Clean up after failure or cancel of sign/encrypt archive
|
||||
operation. [T6584]
|
||||
|
||||
* qt: Add setInputEncoding to QGpgMe::EncryptJob. [T6166]
|
||||
|
||||
* qt: Make toLogString helper public. [T6584]
|
||||
|
||||
* Interface changes relative to the 1.21.0 release:
|
||||
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
qt: EncryptJob::setInputEncoding NEW.
|
||||
qt: DecryptionResult::isMime NEW.
|
||||
qt: toLogString NEW.
|
||||
|
||||
[c=C42/A31/R0 cpp=C25/A19/R0 qt=C19/A4/R0]
|
||||
|
||||
Release-info: https://dev.gnupg.org/T6668
|
||||
|
||||
|
||||
Noteworthy changes in version 1.21.0 (2023-07-07)
|
||||
-------------------------------------------------
|
||||
|
||||
* Extended gpgme_op_encrypt, gpgme_op_encrypt_sign, and gpgme_op_sign
|
||||
to allow writing the output directly to a file. [T6530]
|
||||
|
||||
* Extended gpgme_op_decrypt and gpgme_op_verify to allow reading the
|
||||
input data directly from files. [T6530]
|
||||
|
||||
* For key signing and uid revoking allow an empty user id.
|
||||
[rMfbc3963d62]
|
||||
|
||||
* Pass an input-size-hint also to the gpgsm engine. [T6534]
|
||||
|
||||
* qt: Allow writing the created archives directly to a
|
||||
file. [T6530]
|
||||
|
||||
* qt: Allow reading the signed/encrypted archive to decrypt
|
||||
or verify directly from a file. [T6530]
|
||||
|
||||
* qt: Qt Jobs working with QIODeviceDataProvider now properly
|
||||
handle input-size hints and progress for files larger.
|
||||
2^32 bytes in 32 bit builds. [T6534]
|
||||
|
||||
* cpp: Error::isCanceled now also returns true for error code
|
||||
GPG_ERR_FULLY_CANCELED. [T6510]
|
||||
|
||||
* python: Fix wrong use of write. [T6501]
|
||||
|
||||
* Interface changes relative to the 1.20.0 release:
|
||||
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
cpp: Data::setFlag NEW.
|
||||
cpp: Data::setSizeHint NEW.
|
||||
qt: Job::startIt NEW.
|
||||
qt: DecryptVerifyArchiveJob::setInputFile NEW.
|
||||
qt: DecryptVerifyArchiveJob::inputFile NEW.
|
||||
qt: EncryptArchiveJob::setRecipients NEW.
|
||||
qt: EncryptArchiveJob::recipients NEW.
|
||||
qt: EncryptArchiveJob::setInputPaths NEW.
|
||||
qt: EncryptArchiveJob::inputPaths NEW.
|
||||
qt: EncryptArchiveJob::setOutputFile NEW.
|
||||
qt: EncryptArchiveJob::outputFile NEW.
|
||||
qt: EncryptArchiveJob::setEncryptionFlags NEW.
|
||||
qt: EncryptArchiveJob::encryptionFlags NEW.
|
||||
qt: SignArchiveJob::setSigners NEW.
|
||||
qt: SignArchiveJob::signers NEW.
|
||||
qt: SignArchiveJob::setInputPaths NEW.
|
||||
qt: SignArchiveJob::inputPaths NEW.
|
||||
qt: SignArchiveJob::setOutputFile NEW.
|
||||
qt: SignArchiveJob::outputFile NEW.
|
||||
qt: SignEncryptArchiveJob::setSigners NEW.
|
||||
qt: SignEncryptArchiveJob::signers NEW.
|
||||
qt: SignEncryptArchiveJob::setRecipients NEW.
|
||||
qt: SignEncryptArchiveJob::recipients NEW.
|
||||
qt: SignEncryptArchiveJob::setInputPaths NEW.
|
||||
qt: SignEncryptArchiveJob::inputPaths NEW.
|
||||
qt: SignEncryptArchiveJob::setOutputFile NEW.
|
||||
qt: SignEncryptArchiveJob::outputFile NEW.
|
||||
qt: SignEncryptArchiveJob::setEncryptionFlags NEW.
|
||||
qt: SignEncryptArchiveJob::encryptionFlags NEW.
|
||||
|
||||
[c=C41/A30/R0 cpp=C24/A18/R0 qt=C18/A3/R0]
|
||||
|
||||
Release-info: https://dev.gnupg.org/T6585
|
||||
|
||||
|
||||
Noteworthy changes in version 1.20.0 (2023-04-20)
|
||||
-------------------------------------------------
|
||||
|
||||
* On Windows, the gettext functions provided by gpgrt are switched
|
||||
into utf8 mode, so that all localized texts returned by GpgME or
|
||||
gpgrt, e.g. the texts for error codes are now UTF-8 encoded.
|
||||
[T5960]
|
||||
|
||||
* Key::canSign now returns false for OpenPGP keys without signing
|
||||
(sub)key. [T6456]
|
||||
|
||||
* The new macOS Homebrew location is now by default supported.
|
||||
[T6440]
|
||||
|
||||
* Fix regression in 1.19.0. [rMb608c084b9]
|
||||
|
||||
* Fix invocation of gpgtar on Windows. [rM0c29119e06]
|
||||
|
||||
* Interface changes relative to the 1.19.0 release:
|
||||
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
gpgme_subkey_t EXTENDED: New field 'can_renc'.
|
||||
gpgme_subkey_t EXTENDED: New field 'can_timestamp'.
|
||||
gpgme_subkey_t EXTENDED: New field 'is_group_owned'.
|
||||
cpp: Subkey::canRenc NEW.
|
||||
cpp: Subkey::canTimestamp NEW.
|
||||
cpp: Subkey::isGroupOwned NEW.
|
||||
cpp: Key::canReallySign DEPRECATED.
|
||||
|
||||
[c=C40/A29/R0 cpp=C23/A17/R0 qt=C17/A2/R1]
|
||||
|
||||
Release-info: https://dev.gnupg.org/T6463
|
||||
|
||||
|
||||
Noteworthy changes in version 1.19.0 (2023-03-17)
|
||||
-------------------------------------------------
|
||||
|
||||
* New convenience option --identify for gpgme-json.
|
||||
|
||||
* New context flag "no-auto-check-trustdb". [T6261]
|
||||
|
||||
* Optionally, build QGpgME for Qt 6
|
||||
|
||||
* Support component "gpgtar-name" in gpgme_get_dirinfo. [T6342]
|
||||
|
||||
* Extended gpgme_op_encrypt*, gpgme_op_encrypt_sign*, and
|
||||
gpgme_op_sign* to allow creating an encrypted and/or signed
|
||||
archive. [T6342]
|
||||
|
||||
* Extended gpgme_op_decrypt*, gpgme_op_decrypt_verify*, and gpgme_op_verify*
|
||||
to allow extracting an encrypted and/or signed archive. [T6342]
|
||||
|
||||
* cpp: Handle error when trying to sign expired keys. [T6155]
|
||||
|
||||
* cpp: Support encryption flags ThrowKeyIds, EncryptWrap, and WantAddress.
|
||||
[T6359]
|
||||
|
||||
* cpp, qt: Fix building with C++11. [T6141]
|
||||
|
||||
* qt: Fix problem with expiration dates after 2038-01-19 on 32-bit systems
|
||||
when adding an existing subkey to another key. [T6137]
|
||||
|
||||
* cpp: Allow setting the curve to use when generating ECC keys
|
||||
for smart cards. [T4429]
|
||||
|
||||
* qt: Extend ListAllKeysJob to allow disabling the automatic trust database
|
||||
check when listing all keys. [T6261]
|
||||
|
||||
* qt: Allow deferred start of import jobs. [T6323]
|
||||
|
||||
* qt: Support creating and extracting signed and encrypted archives. [T6342]
|
||||
|
||||
* Interface changes relative to the 1.18.0 release:
|
||||
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
gpgme_get_ctx_flag EXTENDED: New flag 'no-auto-check-trustdb'.
|
||||
gpgme_set_ctx_flag EXTENDED: New flag 'no-auto-check-trustdb'.
|
||||
GPGME_DECRYPT_ARCHIVE NEW.
|
||||
GPGME_ENCRYPT_ARCHIVE NEW.
|
||||
GPGME_SIG_MODE_ARCHIVE NEW.
|
||||
GPGME_VERIFY_ARCHIVE NEW.
|
||||
gpgme_verify_flags_t NEW.
|
||||
gpgme_op_verify_ext_start NEW.
|
||||
gpgme_op_verify_ext NEW.
|
||||
cpp: GpgGenCardKeyInteractor::Curve NEW.
|
||||
cpp: GpgGenCardKeyInteractor::setCurve NEW.
|
||||
cpp: Context::WantAddress NEW.
|
||||
cpp: Context::DecryptArchive NEW.
|
||||
cpp: Context::EncryptArchive NEW.
|
||||
cpp: SignArchive NEW.
|
||||
cpp: Data::setFileName EXTENDED: New overload
|
||||
qt: ListAllKeysJob::Option NEW.
|
||||
qt: ListAllKeysJob::Options NEW.
|
||||
qt: ListAllKeysJob::setOptions NEW.
|
||||
qt: ListAllKeysJob::options NEW.
|
||||
qt: Job::startNow NEW.
|
||||
qt: ImportJob::startLater NEW.
|
||||
qt: FileListDataProvider NEW.
|
||||
qt: DecryptVerifyArchiveJob NEW.
|
||||
qt: EncryptArchiveJob NEW.
|
||||
qt: SignArchiveJob NEW.
|
||||
qt: SignEncryptArchiveJob NEW.
|
||||
qt: Protocol::decryptVerifyArchiveJob NEW.
|
||||
qt: Protocol::encryptArchiveJob NEW.
|
||||
qt: Protocol::signArchiveJob NEW.
|
||||
qt: Protocol::signEncryptArchiveJob NEW.
|
||||
qt: Job::jobProgress NEW.
|
||||
qt: Job::rawProgress NEW.
|
||||
qt: Job::progress DEPRECATED.
|
||||
|
||||
[c=C39/A28/R0 cpp=C22/A16/R0 qt=C17/A2/R0]
|
||||
|
||||
Release-info: https://dev.gnupg.org/T6341
|
||||
|
||||
|
||||
Noteworthy changes in version 1.18.0 (2022-08-10)
|
||||
-------------------------------------------------
|
||||
|
||||
* New keylist mode to force refresh via external methods. [T5951]
|
||||
|
||||
* The keylist operations now create an import result to report the
|
||||
result of the locate keylist modes. [T5951]
|
||||
|
||||
* core: Return BAD_PASSPHRASE error code on symmetric decryption
|
||||
failure. [T5939]
|
||||
|
||||
* cpp, qt: Do not export internal symbols anymore. [T5906]
|
||||
|
||||
* cpp, qt: Support revocation of own OpenPGP keys. [T5904]
|
||||
|
||||
* qt: The file name of (signed and) encrypted data can now be set. [T6056]
|
||||
|
||||
* cpp, qt: Support setting the primary user ID. [T5938]
|
||||
|
||||
* python: Fix segv(NULL) when inspecting contect after exeception. [T6060]
|
||||
|
||||
* Interface changes relative to the 1.17.1 release:
|
||||
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
GPGME_KEYLIST_MODE_FORCE_EXTERN NEW.
|
||||
GPGME_KEYLIST_MODE_LOCATE_EXTERNAL NEW.
|
||||
cpp: RevocationReason NEW.
|
||||
cpp: GpgRevokeKeyEditInteractor NEW.
|
||||
cpp: Result::setError NEW.
|
||||
cpp: KeyListMode::ForceExtern NEW.
|
||||
cpp: KeyListMode::LocateExternal NEW.
|
||||
cpp: KeyListMode::KeyListModeMask NEW.
|
||||
cpp: ImportResult::mergeWith NEW.
|
||||
cpp: KeyListModeSaver NEW.
|
||||
cpp: Context::setPrimaryUid NEW.
|
||||
cpp: Context::startSetPrimaryUid NEW.
|
||||
qt: RevokeKeyJob NEW.
|
||||
qt: Protocol::revokeKeyJob NEW.
|
||||
qt: EncryptJob::setFileName NEW.
|
||||
qt: EncryptJob::fileName NEW.
|
||||
qt: SignEncryptJob::setFileName NEW.
|
||||
qt: SignEncryptJob::fileName NEW.
|
||||
qt: SetPrimaryUserIDJob NEW.
|
||||
qt: Protocol::setPrimaryUserIDJob NEW.
|
||||
|
||||
[c=C38/A27/R0 cpp=C21/A15/R0 qt=C16/A1/R0]
|
||||
|
||||
Release-info: https://dev.gnupg.org/T6128
|
||||
|
||||
|
||||
Noteworthy changes in version 1.17.1 (2022-03-06)
|
||||
-------------------------------------------------
|
||||
|
||||
* qt: Fix a bug in the ABI compatibility of 1.17.0. [T5834]
|
||||
|
||||
[c=C37/A26/R0 cpp=C20/A14/R0 qt=C15/A0/R0]
|
||||
|
||||
Release-info: https://dev.gnupg.org/T5872
|
||||
|
||||
|
||||
Noteworthy changes in version 1.17.0 (2022-02-07)
|
||||
-------------------------------------------------
|
||||
|
||||
* New context flag "key-origin". [#5733]
|
||||
|
||||
* New context flag "import-filter". [#5739]
|
||||
|
||||
* New export mode to export secret subkeys. [#5757]
|
||||
|
||||
* Detect errors during the export of secret keys. [#5766]
|
||||
|
||||
* New function gpgme_op_receive_keys to import keys from a keyserver
|
||||
without first running a key listing. [#5808]
|
||||
|
||||
* Detect bad passphrase error in certificate import. [T5713]
|
||||
|
||||
* Allow setting --key-origin when importing keys. [T5733]
|
||||
|
||||
* Support components "keyboxd", "gpg-agent", "scdaemon", "dirmngr",
|
||||
"pinentry", and "socketdir" in gpgme_get_dirinfo. [T5727,T5613]
|
||||
|
||||
* Under Unix use poll(2) instead of select(2), when available.
|
||||
[T2385]
|
||||
|
||||
* Do not use --flat_namespace when linking for macOS. [T5610]
|
||||
|
||||
* Fix results returned by gpgme_data_* functions. [T5481]
|
||||
|
||||
* Support closefrom also for glibc. [rM4b64774b6d]
|
||||
|
||||
* cpp,qt: Add support for export of secret keys and secret subkeys.
|
||||
[#5757]
|
||||
|
||||
* cpp,qt: Support for adding existing subkeys to other keys. [#5770]
|
||||
|
||||
* qt: Extend ChangeExpiryJob to change expiration of primary key
|
||||
and of subkeys at the same time. [#4717]
|
||||
|
||||
* qt: Support WKD lookup without implicit import. [#5728]
|
||||
|
||||
* qt: Allow specifying an import filter when importing keys. [#5739]
|
||||
|
||||
* qt: Expect UTF-8 on stderr on Windows. [rM8fe1546282]
|
||||
|
||||
* qt: Allow retrieving the default value of a config entry. [T5515]
|
||||
|
||||
* Interface changes relative to the 1.16.0 release:
|
||||
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
gpgme_op_receive_keys NEW.
|
||||
gpgme_op_receive_keys_start NEW.
|
||||
qt: Protocol::secretSubkeyExportJob NEW.
|
||||
cpp: Context::exportSecretSubkeys NEW.
|
||||
cpp: Context::startSecretSubkeyExport NEW.
|
||||
qt: Protocol::secretKeyExportJob CHANGED: Param 'charset' is ignored.
|
||||
cpp: Context::exportKeys NEW.
|
||||
cpp: Context::startKeyExport NEW.
|
||||
cpp: Context::exportSecretKeys NEW.
|
||||
cpp: Context::startSecretKeyExport NEW.
|
||||
cpp: GpgAddExistingSubkeyEditInteractor NEW.
|
||||
GPGME_EXPORT_MODE_SECRET_SUBKEY NEW.
|
||||
gpgme_set_ctx_flag EXTENDED: New flag 'key-origin'.
|
||||
gpgme_set_ctx_flag EXTENDED: New flag 'import-filter'.
|
||||
qt: ChangeExpiryJob::Option NEW.
|
||||
qt: ChangeExpiryJob::Options NEW.
|
||||
qt: ChangeExpiryJob::setOptions NEW.
|
||||
qt: ChangeExpiryJob::options NEW.
|
||||
qt: CryptoConfigEntry::defaultValue NEW.
|
||||
qt: WKDLookupJob NEW.
|
||||
qt: WKDLookupResult NEW.
|
||||
qt: Protocol::wkdLookupJob NEW.
|
||||
qt: ImportJob::setKeyOrigin NEW.
|
||||
qt: ImportJob::keyOrigin NEW.
|
||||
qt: ImportJob::keyOriginUrl NEW.
|
||||
qt: setImportFilter NEW.
|
||||
qt: importFilter NEW.
|
||||
qt: AddExistingSubkeyJob NEW.
|
||||
qt: Protocol::addExistingSubkeyJob NEW.
|
||||
|
||||
[c=C37/A26/R0 cpp=C20/A14/R0 qt=C14/A7/R0]
|
||||
|
||||
Release-info: https://dev.gnupg.org/T5819
|
||||
|
||||
|
||||
Noteworthy changes in version 1.16.0 (2021-06-24)
|
||||
-------------------------------------------------
|
||||
|
||||
* New context flag "cert-expire". [#5505]
|
||||
|
||||
* New data flags "io-buffer-size" and "sensitive". [#5478]
|
||||
|
||||
* Increase I/O buffer size from 512 to 4k under Windows.
|
||||
|
||||
* cpp,qt: Add support for trust signatures. [#5421]
|
||||
|
||||
* qt: Add support for flags in LDAP server options. [#5217]
|
||||
|
||||
* qt: Fix too high memory consumption due to QProcess. [#5475]
|
||||
|
||||
* qt: Do not set empty base DN as query of keyserver URL. [#5465]
|
||||
|
||||
* qt: Extend SignKeyJob to create signatures with expiration date.
|
||||
[5506]
|
||||
|
||||
* python: New optional parameter filter_signatures for decrypt.
|
||||
[#5292]
|
||||
|
||||
* Interface changes relative to the 1.15.1 release:
|
||||
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
gpgme_set_ctx_flag EXTENDED: New flag 'cert-expire'.
|
||||
cpp: SignKeyJob::setTrustSignature NEW.
|
||||
cpp: TrustSignatureTrust NEW.
|
||||
cpp: GpgSignKeyEditInteractor::setTrustSignatureTrust NEW.
|
||||
cpp: GpgSignKeyEditInteractor::setTrustSignatureDepth NEW.
|
||||
cpp: GpgSignKeyEditInteractor::setTrustSignatureScope NEW.
|
||||
cpp: UserID::Signature::isTrustSignature NEW.
|
||||
cpp: UserID::Signature::trustValue NEW.
|
||||
cpp: UserID::Signature::trustDepth NEW.
|
||||
cpp: UserID::Signature::trustScope NEW.
|
||||
gpgme_key_sig_t EXTENDED: New field 'trust_depth'.
|
||||
gpgme_key_sig_t EXTENDED: New field 'trust_value'.
|
||||
gpgme_key_sig_t EXTENDED: New field 'trust_scope'.
|
||||
GPGME_KEYSIGN_FORCE NEW.
|
||||
qt: CryptoConfig::entry CHANGED: Added overload; deprecated old
|
||||
|
||||
[c=C36/A25/R0 cpp=C19/A13/R0 qt=C13/A6/R0]
|
||||
|
||||
Release-info: https://dev.gnupg.org/T5499
|
||||
|
||||
|
||||
Noteworthy changes in version 1.15.1 (2021-01-08)
|
||||
-------------------------------------------------
|
||||
|
||||
* Fix another bug in the secret key export. [#5046]
|
||||
|
||||
* Make listing of signatures work if only secret keys are listed. [#3580]
|
||||
|
||||
* Fix build problem on FreeBSD. [a6220adf30]
|
||||
|
||||
* qt: Avoid empty "rem@gnupg.org" signature notations. [#5142]
|
||||
|
||||
* python: Fix key_export functions. [#5149]
|
||||
|
||||
|
||||
[c=C35/A24/R1 cpp=C18/A12/R1 qt=C12/A5/R1]
|
||||
|
||||
Release-info: https://dev.gnupg.org/T5225
|
||||
|
||||
|
||||
Noteworthy changes in version 1.15.0 (2020-11-12)
|
||||
-------------------------------------------------
|
||||
|
||||
* New function gpgme_op_setexpire to make changing the expiration
|
||||
easier (requires GnuPG 2.1.22). [#4999]
|
||||
|
||||
* New function gpgme_op_revsig to revoke key signatures (requires
|
||||
GnuPG 2.2.24). [#5094]
|
||||
|
||||
* Support exporting secret keys. [#5046]
|
||||
|
||||
* cpp: Support for set expire operations in the C++ bindings. [#5003]
|
||||
|
||||
* cpp: Support for revoking key signatures in the C++ bindings. [#5094]
|
||||
|
||||
* qt: Extended ChangeExpiryJob to support changing the expiry of
|
||||
subkeys. [#4717]
|
||||
|
||||
* qt: Extended QuickJob to support revoking of key signatures. [#5094]
|
||||
|
||||
* qt: Added QDebug stream operator for GpgME::Error.
|
||||
|
||||
* Require a somewhat newer version of libgpg-error (1.36).
|
||||
|
||||
* Interface changes relative to the 1.14.0 release:
|
||||
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
gpgme_op_setexpire_start NEW.
|
||||
gpgme_op_setexpire NEW.
|
||||
gpgme_op_revsig_start NEW.
|
||||
gpgme_op_revsig NEW.
|
||||
GPGME_REVSIG_LFSEP NEW.
|
||||
cpp: Context::setExpire NEW.
|
||||
cpp: Context::startSetExpire NEW.
|
||||
cpp: EngineInfo::Version::operator<= NEW.
|
||||
cpp: EngineInfo::Version::operator>= NEW.
|
||||
cpp: EngineInfo::Version::operator!= NEW.
|
||||
cpp: StatusConsumer NEW.
|
||||
cpp: StatusConsumerAssuanTransaction NEW.
|
||||
cpp: Context::cancelPendingOperationImmediately NEW.
|
||||
cpp: Context::revokeSignature NEW.
|
||||
cpp: Context::startRevokeSignature NEW.
|
||||
cpp: UserID::Signature::operator< NEW.
|
||||
qt: operator<<(QDebug debug, const GpgME::Error &err) NEW.
|
||||
qt: QuickJob::startRevokeSignature NEW.
|
||||
qt: QuickJob::result CHANGED: Made params 'auditLogAsHtml'
|
||||
and 'auditLogError' optional.
|
||||
|
||||
[c=C35/A24/R0 cpp=C18/A12/R0 qt=C12/A5/R0]
|
||||
|
||||
Release-info: https://dev.gnupg.org/T5131
|
||||
|
||||
|
||||
Noteworthy changes in version 1.14.0 (2020-07-16)
|
||||
-------------------------------------------------
|
||||
|
||||
* New keylist mode to force the engine to return the keygrip. [#4820]
|
||||
|
||||
* New export mode to export as OpenSSH public key. [#4310]
|
||||
|
||||
* New context flag "extended-edit" to enable expert key edit. [#4734]
|
||||
|
||||
* Deprecate the anyway non working trustlist functions. [#4834]
|
||||
|
||||
* cpp: Add convenience API to obtain remarks. [#4734]
|
||||
|
||||
* cpp: The sign key edit-interactor now supports multiple signatures
|
||||
from the same key. [#4734]
|
||||
|
||||
* qt: Extended signkeyjob to handle remarks and multiple signatures.
|
||||
[#4734]
|
||||
|
||||
* qt: Added job API for gpg-card.
|
||||
|
||||
* qt: The logging category has been changed to gpg.qgpgme to be more
|
||||
consistent with other qt logging categories.
|
||||
|
||||
* Interface changes relative to the 1.13.1 release:
|
||||
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
GPGME_KEYLIST_MODE_WITH_KEYGRIP NEW.
|
||||
GPGME_EXPORT_MODE_SSH NEW.
|
||||
gpgme_user_id_t EXTENDED: New field 'uidhash'.
|
||||
cpp: UserID::remark NEW.
|
||||
cpp: UserID::remarks NEW.
|
||||
cpp: GpgSignKeyEditInteractor::setDupeOk NEW.
|
||||
cpp: Context::exportPublicKeys EXTENDED: New param 'flags'.
|
||||
cpp: Context::startPublicKeyExport EXTENDED: New param 'flags'.
|
||||
cpp: Context::ExportMode NEW.
|
||||
qt: SignKeyJob::setDupeOk NEW.
|
||||
qt: SignKeyJob::setRemark NEW.
|
||||
qt: GpgCardJob NEW.
|
||||
qt: ExportJob::setExportFlags NEW.
|
||||
|
||||
[c=C34/A23/R0 cpp=C17/A11/R0 qt=C11/A4/R0]
|
||||
|
||||
Release-info: https://dev.gnupg.org/T4996
|
||||
|
||||
|
||||
Noteworthy changes in version 1.13.1 (2019-06-13)
|
||||
-------------------------------------------------
|
||||
|
||||
* cpp: gpgme_set_global_flag is now wrapped. [#4471]
|
||||
|
||||
* w32: Improved handling of unicode install paths. [#4453]
|
||||
|
||||
* w32: The gpgme_io_spawn error message is now only shown once. [#4453]
|
||||
|
||||
* Fixed a crash introduced in 1.13.0 when working with S/MIME. [#4556]
|
||||
|
||||
* w32: Fixed format string errors introduced in 1.13.0 that could
|
||||
cause crashes. [#4440]
|
||||
|
||||
* w32: Fixed an error in the new diagnostic gpgsm support introduced
|
||||
in 1.13.0 that caused crashes in low fd scenarios. [#4439]
|
||||
|
||||
* python: Fixed a DecryptionError Exception. [#4478]
|
||||
|
||||
* python: No longer raises BadSignatures from decrypt(verify=True).
|
||||
[#4276]
|
||||
|
||||
* Interface changes relative to the 1.13.0 release:
|
||||
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
cpp: setGlobalFlag NEW.
|
||||
|
||||
[c=C33/A22/R1 cpp=C16/A10/R0 qt=C10/A3/R4]
|
||||
|
||||
Release-info: https://dev.gnupg.org/T4551
|
||||
|
||||
|
||||
Noteworthy changes in version 1.13.0 (2019-03-26)
|
||||
-------------------------------------------------
|
||||
|
||||
* Support GPGME_AUDITLOG_DIAG for gpgsm. [#4426]
|
||||
|
||||
* New context flag "trust-model".
|
||||
|
||||
* Removed support for WindowsCE and Windows ME.
|
||||
|
||||
* Aligned the gpgrt-config code with our other libaries.
|
||||
|
||||
* Auto-check for all installed Python versions. [#3354]
|
||||
|
||||
* Fixed generating card key in the C++ bindings. [#4428]
|
||||
|
||||
* Fixed a segv due to bad parameters in genkey. [#4192]
|
||||
|
||||
* Fixed crash if the plaintext is ignored in a CMS verify.
|
||||
|
||||
* Fixed memleak on Windows. [T4238]
|
||||
|
||||
* Tweaked the Windows I/O code.
|
||||
|
||||
* Fixed random crashes on Windows due to closing an arbitrary
|
||||
handle. [#4237]
|
||||
|
||||
* Fixed a segv on Windows. [#4369]
|
||||
|
||||
* Fixed test suite problems related to dtags. [#4298]
|
||||
|
||||
* Fixed bunch of python bugs. [#4242,commit 9de1c96ac3cf]
|
||||
|
||||
* Several fixes to the Common Lisp bindings.
|
||||
|
||||
* Fixed minor bugs in gpgme-json. [#4331,#4341,#4342,#4343]
|
||||
|
||||
* Require trace level 8 to dump all I/O data.
|
||||
|
||||
* The compiler must now support variadic macros.
|
||||
|
||||
* Interface changes relative to the 1.12.0 release:
|
||||
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
gpgme_set_ctx_flag EXTENDED: New flag 'trust-model'.
|
||||
cpp: Context::create NEW.
|
||||
cpp: Key::isBad NEW.
|
||||
cpp: Subkey::isBad NEW.
|
||||
cpp: UserID::isBad NEW.
|
||||
cpp: UserID::Signature::isBad NEW.
|
||||
cpp: GenCardKeyInteractor::setAlgo NEW.
|
||||
|
||||
[c=C33/A22/R0 cpp=C15/A9/R0 qt=C10/A3/R3]
|
||||
|
||||
Release-info: https://dev.gnupg.org/T4376
|
||||
|
||||
|
||||
Noteworthy changes in version 1.12.0 (2018-10-08)
|
||||
|
8
README
8
README
@ -1,7 +1,7 @@
|
||||
GPGME - GnuPG Made Easy
|
||||
---------------------------
|
||||
|
||||
Copyright 2001-2023 g10 Code GmbH
|
||||
Copyright 2001-2018 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
|
||||
@ -41,11 +41,11 @@ See the file INSTALL for generic installation instructions.
|
||||
Check that you have unmodified sources. See below on how to do this.
|
||||
Don't skip it - this is an important step!
|
||||
|
||||
To build GPGME, you need to install libgpg-error (>= 1.36) and
|
||||
To build GPGME, you need to install libgpg-error (>= 1.24) and
|
||||
Libassuan (>= 2.4.2).
|
||||
|
||||
For support of the OpenPGP and the CMS protocols, you should use at
|
||||
least GnuPG version 2.2.41 or 2.4.3, available at:
|
||||
For support of the OpenPGP and the CMS protocols, you should use the
|
||||
latest version of GnuPG (>= 2.1.18) , available at:
|
||||
https://gnupg.org/ftp/gcrypt/gnupg/.
|
||||
|
||||
For building the Git version of GPGME please see the file README.GIT
|
||||
|
@ -11,4 +11,4 @@ case "$myhost" in
|
||||
esac
|
||||
|
||||
|
||||
final_info="mkdir build && cd build && ../configure --enable-maintainer-mode && make"
|
||||
final_info="./configure --enable-maintainer-mode && make"
|
||||
|
43
autogen.sh
43
autogen.sh
@ -1,6 +1,6 @@
|
||||
#! /bin/sh
|
||||
# autogen.sh
|
||||
# Copyright (C) 2003, 2014, 2017, 2018, 2022 g10 Code GmbH
|
||||
# Copyright (C) 2003, 2014, 2017, 2018 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
|
||||
@ -15,7 +15,7 @@
|
||||
# configure it for the respective package. It is maintained as part of
|
||||
# GnuPG and source copied by other packages.
|
||||
#
|
||||
# Version: 2023-03-15
|
||||
# Version: 2018-07-10
|
||||
|
||||
configure_ac="configure.ac"
|
||||
|
||||
@ -137,6 +137,8 @@ extraoptions=
|
||||
# List of optional variables sourced from autogen.rc and ~/.gnupg-autogen.rc
|
||||
w32_toolprefixes=
|
||||
w32_extraoptions=
|
||||
w32ce_toolprefixes=
|
||||
w32ce_extraoptions=
|
||||
w64_toolprefixes=
|
||||
w64_extraoptions=
|
||||
amd64_toolprefixes=
|
||||
@ -144,6 +146,7 @@ amd64_toolprefixes=
|
||||
# What follows are variables which are sourced but default to
|
||||
# environment variables or lacking them hardcoded values.
|
||||
#w32root=
|
||||
#w32ce_root=
|
||||
#w64root=
|
||||
#amd64root=
|
||||
|
||||
@ -164,6 +167,11 @@ case "$1" in
|
||||
myhost="w32"
|
||||
shift
|
||||
;;
|
||||
--build-w32ce)
|
||||
myhost="w32"
|
||||
myhostsub="ce"
|
||||
shift
|
||||
;;
|
||||
--build-w64)
|
||||
myhost="w32"
|
||||
myhostsub="64"
|
||||
@ -195,7 +203,7 @@ if [ "$myhost" = "git-build" ]; then
|
||||
die_p
|
||||
make || fatal "error running make"
|
||||
die_p
|
||||
make check || fatal "error running make check"
|
||||
make check || fatal "error running male check"
|
||||
die_p
|
||||
exit 0
|
||||
fi
|
||||
@ -233,12 +241,10 @@ if [ "$myhost" = "find-version" ]; then
|
||||
if [ -z "$micro" ]; then
|
||||
matchstr1="$package-$major.[0-9]*"
|
||||
matchstr2="$package-$major-base"
|
||||
matchstr3=""
|
||||
vers="$major.$minor"
|
||||
else
|
||||
matchstr1="$package-$major.$minor.[0-9]*"
|
||||
matchstr2="$package-$major.[0-9]*-base"
|
||||
matchstr3="$package-$major-base"
|
||||
matchstr2="$package-$major.$minor-base"
|
||||
vers="$major.$minor.$micro"
|
||||
fi
|
||||
|
||||
@ -246,22 +252,13 @@ if [ "$myhost" = "find-version" ]; then
|
||||
if [ -e .git ]; then
|
||||
ingit=yes
|
||||
tmp=$(git describe --match "${matchstr1}" --long 2>/dev/null)
|
||||
tmp=$(echo "$tmp" | sed s/^"$package"//)
|
||||
if [ -n "$tmp" ]; then
|
||||
tmp=$(echo "$tmp" | sed s/^"$package"// \
|
||||
| awk -F- '$3!=0 && $3 !~ /^beta/ {print"-beta"$3}')
|
||||
tmp=$(echo "$tmp" | sed s/^"$package"// \
|
||||
| awk -F- '$3!=0 && $3 !~ /^beta/ {print"-beta"$3}')
|
||||
else
|
||||
# (due tof "-base" in the tag we need to take the 4th field)
|
||||
tmp=$(git describe --match "${matchstr2}" --long 2>/dev/null)
|
||||
if [ -n "$tmp" ]; then
|
||||
tmp=$(echo "$tmp" | sed s/^"$package"// \
|
||||
| awk -F- '$4!=0 && $4 !~ /^beta/ {print"-beta"$4}')
|
||||
elif [ -n "${matchstr3}" ]; then
|
||||
tmp=$(git describe --match "${matchstr3}" --long 2>/dev/null)
|
||||
if [ -n "$tmp" ]; then
|
||||
tmp=$(echo "$tmp" | sed s/^"$package"// \
|
||||
| awk -F- '$4!=0 && $4 !~ /^beta/ {print"-beta"$4}')
|
||||
fi
|
||||
fi
|
||||
tmp=$(git describe --match "${matchstr2}" --long 2>/dev/null \
|
||||
| awk -F- '$4!=0{print"-beta"$4}')
|
||||
fi
|
||||
[ -n "$tmp" ] && beta=yes
|
||||
rev=$(git rev-parse --short HEAD | tr -d '\n\r')
|
||||
@ -297,6 +294,12 @@ fi
|
||||
# ******************
|
||||
if [ "$myhost" = "w32" ]; then
|
||||
case $myhostsub in
|
||||
ce)
|
||||
w32root="$w32ce_root"
|
||||
[ -z "$w32root" ] && w32root="$HOME/w32ce_root"
|
||||
toolprefixes="$w32ce_toolprefixes arm-mingw32ce"
|
||||
extraoptions="$extraoptions $w32ce_extraoptions"
|
||||
;;
|
||||
64)
|
||||
w32root="$w64root"
|
||||
[ -z "$w32root" ] && w32root="$HOME/w64root"
|
||||
|
1612
build-aux/config.guess
vendored
1612
build-aux/config.guess
vendored
File diff suppressed because it is too large
Load Diff
2909
build-aux/config.sub
vendored
2909
build-aux/config.sub
vendored
File diff suppressed because it is too large
Load Diff
@ -1,68 +0,0 @@
|
||||
#
|
||||
# This is a sed script to patch the generated libtool,
|
||||
# which works well against both of libtool 2.4.2 and 2.4.7.
|
||||
#
|
||||
# You may use this work under the terms of a Creative Commons CC0 1.0
|
||||
# License/Waiver.
|
||||
#
|
||||
# CC0 Public Domain Dedication
|
||||
# https://creativecommons.org/publicdomain/zero/1.0/
|
||||
|
||||
#
|
||||
# This sed script applys two hunks of the patch:
|
||||
#
|
||||
# Part1: after the comment "# bleh windows"
|
||||
# Part2: after the comment "#extension on DOS 8.3..."
|
||||
#
|
||||
# Only when those two parts are patched correctly, it exits with 0 or
|
||||
# else, it exits with 1
|
||||
#
|
||||
|
||||
# Find the part 1, by the comment
|
||||
/^[ \t]*# bleh windows$/b part1_start
|
||||
# Not found the part1, raise an error
|
||||
$ q1
|
||||
b
|
||||
|
||||
:part1_start
|
||||
n
|
||||
# The first line in the part 1 must be the begining of the case statement.
|
||||
/^[ \t]*case \$host in$/! q1
|
||||
n
|
||||
# Insert the entry for x86_64-*mingw32*, for modified versuffix.
|
||||
i\
|
||||
x86_64-*mingw32*)
|
||||
i\
|
||||
func_arith $current - $age
|
||||
i\
|
||||
major=$func_arith_result
|
||||
i\
|
||||
versuffix="6-$major"
|
||||
i\
|
||||
;;
|
||||
:part1_0
|
||||
# Find the end of the case statement
|
||||
/^[ \t]*esac$/b find_part2
|
||||
# Not found the end of the case statement, raise an error
|
||||
$ q1
|
||||
n
|
||||
b part1_0
|
||||
|
||||
:find_part2
|
||||
/^[ \t]*# extension on DOS 8.3 file.*systems.$/b part2_process
|
||||
# Not found the part2, raise an error
|
||||
$ q1
|
||||
n
|
||||
b find_part2
|
||||
|
||||
:part2_process
|
||||
$ q1
|
||||
s/^[ \t]*\(versuffix=\)\(.*\)\(-$major\)\(.*\)$/\t case \$host in\n\t x86_64-*mingw32*)\n\t \1\26\3\4\n\t ;;\n\t *)\n\t \1\2\3\4\n\t ;;\n\t esac/
|
||||
t part2_done
|
||||
n
|
||||
b part2_process
|
||||
|
||||
:part2_done
|
||||
$ q0
|
||||
n
|
||||
b part2_done
|
@ -482,7 +482,7 @@
|
||||
% \def\foo{\parsearg\Xfoo}
|
||||
% \def\Xfoo#1{...}
|
||||
%
|
||||
% Actually, I use \csname\string\foo\endcsname, i.e. \\foo, as it is my
|
||||
% Actually, I use \csname\string\foo\endcsname, ie. \\foo, as it is my
|
||||
% favourite TeX trick. --kasal, 16nov03
|
||||
|
||||
\def\parseargdef#1{%
|
||||
|
481
configure.ac
481
configure.ac
@ -1,6 +1,6 @@
|
||||
# configure.ac for GPGME
|
||||
# Copyright (C) 2000 Werner Koch (dd9jn)
|
||||
# Copyright (C) 2001-2021 g10 Code GmbH
|
||||
# Copyright (C) 2001-2018 g10 Code GmbH
|
||||
#
|
||||
# This file is part of GPGME.
|
||||
#
|
||||
@ -19,20 +19,18 @@
|
||||
# SPDX-License-Identifier: LGPL-2.1-or-later
|
||||
|
||||
# (Process this file with autoconf to produce a configure script.)
|
||||
AC_PREREQ([2.69])
|
||||
AC_PREREQ(2.59)
|
||||
min_automake_version="1.14"
|
||||
|
||||
# To build a release you need to create a tag with the version number
|
||||
# "gpgme-n.m.k" and run "./autogen.sh --force". Please bump the
|
||||
# version number immediately after the release and do another commit
|
||||
# and push so that the git magic is able to work. If you start a new
|
||||
# series by bumping the minor (m) remember to also create a tag named
|
||||
# "gpgme-n.m-base" as the start point for beta numbering. See below
|
||||
# (git tag -s gpgme-n.m.k) and run "./autogen.sh --force". Please
|
||||
# bump the version number immediately after the release and do another
|
||||
# commit and push so that the git magic is able to work. See below
|
||||
# for the LT versions.
|
||||
m4_define([mym4_package],[gpgme])
|
||||
m4_define([mym4_major], [1])
|
||||
m4_define([mym4_minor], [24])
|
||||
m4_define([mym4_micro], [0])
|
||||
m4_define([mym4_minor], [12])
|
||||
m4_define([mym4_micro], [1])
|
||||
|
||||
# Below is m4 magic to extract and compute the git revision number,
|
||||
# the decimalized short revision number, a beta version string and a
|
||||
@ -45,7 +43,7 @@ m4_define([mym4_version], m4_argn(4, mym4_verslist))
|
||||
m4_define([mym4_revision], m4_argn(7, mym4_verslist))
|
||||
m4_define([mym4_revision_dec], m4_argn(8, mym4_verslist))
|
||||
m4_esyscmd([echo ]mym4_version[>VERSION])
|
||||
AC_INIT([mym4_package],[mym4_version],[https://bugs.gnupg.org])
|
||||
AC_INIT([mym4_package],[mym4_version], [https://bugs.gnupg.org])
|
||||
|
||||
# LT Version numbers, remember to change them just *before* a release.
|
||||
# (Code changed: REVISION++)
|
||||
@ -53,20 +51,20 @@ AC_INIT([mym4_package],[mym4_version],[https://bugs.gnupg.org])
|
||||
# (Interfaces added: AGE++)
|
||||
# (Interfaces removed: AGE=0)
|
||||
#
|
||||
LIBGPGME_LT_CURRENT=43
|
||||
LIBGPGME_LT_AGE=32
|
||||
LIBGPGME_LT_REVISION=1
|
||||
LIBGPGME_LT_CURRENT=32
|
||||
LIBGPGME_LT_AGE=21
|
||||
LIBGPGME_LT_REVISION=0
|
||||
|
||||
# If there is an ABI break in gpgmepp or qgpgme also bump the
|
||||
# version in IMPORTED_LOCATION in the GpgmeppConfig-w32.cmake.in.in
|
||||
|
||||
LIBGPGMEPP_LT_CURRENT=26
|
||||
LIBGPGMEPP_LT_AGE=20
|
||||
LIBGPGMEPP_LT_REVISION=1
|
||||
LIBGPGMEPP_LT_CURRENT=14
|
||||
LIBGPGMEPP_LT_AGE=8
|
||||
LIBGPGMEPP_LT_REVISION=0
|
||||
|
||||
LIBQGPGME_LT_CURRENT=20
|
||||
LIBQGPGME_LT_AGE=5
|
||||
LIBQGPGME_LT_REVISION=1
|
||||
LIBQGPGME_LT_CURRENT=10
|
||||
LIBQGPGME_LT_AGE=3
|
||||
LIBQGPGME_LT_REVISION=2
|
||||
################################################
|
||||
|
||||
AC_SUBST(LIBGPGME_LT_CURRENT)
|
||||
@ -85,7 +83,7 @@ AC_SUBST(LIBQGPGME_LT_REVISION)
|
||||
GPGME_CONFIG_API_VERSION=1
|
||||
##############################################
|
||||
|
||||
NEED_GPG_ERROR_VERSION=1.47
|
||||
NEED_GPG_ERROR_VERSION=1.24
|
||||
NEED_LIBASSUAN_API=2
|
||||
NEED_LIBASSUAN_VERSION=2.4.2
|
||||
|
||||
@ -96,8 +94,8 @@ VERSION_MICRO=mym4_micro
|
||||
|
||||
AC_CONFIG_AUX_DIR([build-aux])
|
||||
AC_CONFIG_MACRO_DIR([m4])
|
||||
AC_CONFIG_SRCDIR([src/gpgme.h.in])
|
||||
AC_CONFIG_HEADERS([conf/config.h])
|
||||
AC_CONFIG_SRCDIR(src/gpgme.h.in)
|
||||
AC_CONFIG_HEADER(conf/config.h)
|
||||
AM_INIT_AUTOMAKE([serial-tests dist-bzip2 no-dist-gzip])
|
||||
AM_MAINTAINER_MODE
|
||||
AC_CANONICAL_HOST
|
||||
@ -105,42 +103,7 @@ AM_SILENT_RULES
|
||||
AC_ARG_VAR(SYSROOT,[locate config scripts also below that directory])
|
||||
|
||||
# Enable GNU extensions on systems that have them.
|
||||
AC_USE_SYSTEM_EXTENSIONS
|
||||
|
||||
# Taken from mpfr-4.0.1, then modified for LDADD_FOR_TESTS_KLUDGE
|
||||
dnl Under Linux, make sure that the old dtags are used if LD_LIBRARY_PATH
|
||||
dnl is defined. The issue is that with the new dtags, LD_LIBRARY_PATH has
|
||||
dnl the precedence over the run path, so that if a compatible MPFR library
|
||||
dnl is installed in some directory from $LD_LIBRARY_PATH, then the tested
|
||||
dnl MPFR library will be this library instead of the MPFR library from the
|
||||
dnl build tree. Other OS with the same issue might be added later.
|
||||
dnl
|
||||
dnl References:
|
||||
dnl https://bugs.debian.org/cgi-bin/bugreport.cgi?bug=859732
|
||||
dnl http://lists.gnu.org/archive/html/libtool/2017-05/msg00000.html
|
||||
dnl
|
||||
dnl We need to check whether --disable-new-dtags is supported as alternate
|
||||
dnl linkers may be used (e.g., with tcc: CC=tcc LD=tcc).
|
||||
dnl
|
||||
case $host in
|
||||
*-*-linux*)
|
||||
if test -n "$LD_LIBRARY_PATH"; then
|
||||
saved_LDFLAGS="$LDFLAGS"
|
||||
LDADD_FOR_TESTS_KLUDGE="-Wl,--disable-new-dtags"
|
||||
LDFLAGS="$LDFLAGS $LDADD_FOR_TESTS_KLUDGE"
|
||||
AC_MSG_CHECKING(whether --disable-new-dtags is supported by the linker)
|
||||
AC_LINK_IFELSE([AC_LANG_SOURCE([[
|
||||
int main (void) { return 0; }
|
||||
]])],
|
||||
[AC_MSG_RESULT(yes (use it since LD_LIBRARY_PATH is set))],
|
||||
[AC_MSG_RESULT(no)
|
||||
LDADD_FOR_TESTS_KLUDGE=""
|
||||
])
|
||||
LDFLAGS="$saved_LDFLAGS"
|
||||
fi
|
||||
;;
|
||||
esac
|
||||
AC_SUBST([LDADD_FOR_TESTS_KLUDGE])
|
||||
AC_GNU_SOURCE
|
||||
|
||||
AH_VERBATIM([_REENTRANT],
|
||||
[/* To allow the use of GPGME in multithreaded programs we have to use
|
||||
@ -198,7 +161,7 @@ case "${host}" in
|
||||
have_ld_version_script=yes
|
||||
;;
|
||||
*-apple-darwin*)
|
||||
AC_DEFINE(_DARWIN_C_SOURCE, 1,
|
||||
AC_DEFINE(_DARWIN_C_SOURCE, 900000L,
|
||||
Expose all libc features (__DARWIN_C_FULL).)
|
||||
AC_DEFINE(_XOPEN_SOURCE, 500, Activate POSIX interface on MacOS X)
|
||||
;;
|
||||
@ -206,44 +169,6 @@ esac
|
||||
|
||||
AM_CONDITIONAL(HAVE_LD_VERSION_SCRIPT, test "$have_ld_version_script" = "yes")
|
||||
|
||||
#
|
||||
# Specify how we support our local modification of libtool for Windows
|
||||
# 64-bit. Options are:
|
||||
#
|
||||
# (1) apply: when appying patch fails, it results failure of entire build
|
||||
# (2) never: never apply the patch (no try)
|
||||
# (3) try: use patched if it goes well, use original if fails
|
||||
#
|
||||
AC_ARG_WITH([libtool-modification],
|
||||
AS_HELP_STRING([--with-libtool-modification=apply|never|try],
|
||||
[how to handle libtool modification (default=never)]),
|
||||
build_libtool_modification=$withval,
|
||||
build_libtool_modification=never)
|
||||
|
||||
#
|
||||
# Apply a patch (locally maintained one of ours) to libtool
|
||||
#
|
||||
case $host in
|
||||
x86_64-*mingw32*)
|
||||
AC_CONFIG_COMMANDS([libtool-patch],[[
|
||||
if test "$build_selection" = never; then
|
||||
echo "patch not applied"
|
||||
elif (mv -f libtool libtool.orig; \
|
||||
sed -f $srcdir/build-aux/libtool-patch.sed libtool.orig >libtool); then
|
||||
echo "applied successfully"
|
||||
elif test "$build_selection" = try; then
|
||||
mv -f libtool.orig libtool
|
||||
echo "patch failed, thus, using original"
|
||||
else
|
||||
echo "patch failed"
|
||||
as_fn_exit 1
|
||||
fi
|
||||
]],[build_selection=$build_libtool_modification])
|
||||
;;
|
||||
*)
|
||||
;;
|
||||
esac
|
||||
|
||||
GPG_DEFAULT=no
|
||||
GPGSM_DEFAULT=no
|
||||
GPGCONF_DEFAULT=no
|
||||
@ -256,8 +181,8 @@ have_w64_system=no
|
||||
have_macos_system=no
|
||||
build_w32_glib=no
|
||||
build_w32_qt=no
|
||||
available_languages="cl cpp python qt qt5 qt6"
|
||||
default_languages="cl cpp python qt5 qt6"
|
||||
available_languages="cl cpp python qt"
|
||||
default_languages="cl cpp python qt"
|
||||
case "${host}" in
|
||||
x86_64-*mingw32*)
|
||||
have_w64_system=yes
|
||||
@ -281,7 +206,7 @@ case "${host}" in
|
||||
|
||||
AM_PATH_GLIB_2_0
|
||||
AC_ARG_ENABLE(w32-glib,
|
||||
AS_HELP_STRING([--enable-w32-glib],[build GPGME Glib for W32]),
|
||||
AC_HELP_STRING([--enable-w32-glib], [build GPGME Glib for W32]),
|
||||
build_w32_glib=$enableval)
|
||||
;;
|
||||
*)
|
||||
@ -329,7 +254,7 @@ AM_CONDITIONAL(BUILD_W32_GLIB, test "$build_w32_glib" = yes)
|
||||
|
||||
|
||||
AC_ARG_ENABLE([fixed-path],
|
||||
AS_HELP_STRING([--enable-fixed-path=PATH],
|
||||
AC_HELP_STRING([--enable-fixed-path=PATH],
|
||||
[locate binaries only via this PATH]),
|
||||
[fixed_search_path="$enableval"],
|
||||
[fixed_search_path=""])
|
||||
@ -338,44 +263,12 @@ if test x$fixed_search_path != x ; then
|
||||
[Locate binaries only via this PATH])
|
||||
fi
|
||||
|
||||
# Option --enable-reduce-relocations
|
||||
#
|
||||
# Allow building the Qt 6 bindings explicitly with -fPIC if the automatic
|
||||
# detection fails. Note: We assume that this flag is always available (unless
|
||||
# we built for Windows).
|
||||
AC_ARG_ENABLE([reduce-relocations],
|
||||
AS_HELP_STRING([--enable-reduce-relocations],
|
||||
[build Qt 6 bindings with -fPIC (default is
|
||||
auto)]),
|
||||
[use_reduce_relocations="$enableval"],
|
||||
[use_reduce_relocations=""])
|
||||
|
||||
# Option --enable-no-direct-extern-access
|
||||
#
|
||||
# Some distributions build Qt 6 with -mno-direct-extern-access. Libraries and
|
||||
# applications using Qt then must also be build with this flag. As workaround
|
||||
# for a bug in Qt's pkgconfig files which don't have this flag we allow
|
||||
# building with this flag explicitly.
|
||||
AC_LANG_PUSH(C++)
|
||||
AX_CHECK_COMPILE_FLAG([-mno-direct-extern-access],
|
||||
[have_no_direct_extern_access="yes"],
|
||||
[have_no_direct_extern_access="no"],
|
||||
[-Werror])
|
||||
AC_LANG_POP()
|
||||
AC_ARG_ENABLE([no-direct-extern-access],
|
||||
AS_HELP_STRING([--enable-no-direct-extern-access],
|
||||
[build Qt 6 bindings with
|
||||
-mno-direct-extern-access (default is auto)]),
|
||||
[use_no_direct_extern_access="$enableval"],
|
||||
[use_no_direct_extern_access=""])
|
||||
|
||||
|
||||
# Note: You need to declare all possible languages also in
|
||||
# lang/Makefile.am's DIST_SUBDIRS.
|
||||
AC_ARG_ENABLE([languages],
|
||||
AS_HELP_STRING([--enable-languages=languages],
|
||||
[enable only specific language bindings:
|
||||
cl cpp python qt5 qt6]),
|
||||
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/'`],
|
||||
@ -401,182 +294,69 @@ for language in $enabled_languages; do
|
||||
fi
|
||||
done
|
||||
|
||||
# Check whether qt5 and/or qt6 are enabled
|
||||
want_qt5="no"
|
||||
LIST_MEMBER("qt5", $enabled_languages)
|
||||
if test "$found" = "1"; then
|
||||
if test "$explicit_languages" = "1"; then
|
||||
want_qt5="yes"
|
||||
else
|
||||
want_qt5="maybe"
|
||||
fi
|
||||
# Remove qt5; further down qt will be added
|
||||
enabled_languages=$(echo $enabled_languages | sed 's/qt5//')
|
||||
fi
|
||||
want_qt6="no"
|
||||
LIST_MEMBER("qt6", $enabled_languages)
|
||||
if test "$found" = "1"; then
|
||||
if test "$explicit_languages" = "1"; then
|
||||
want_qt6="yes"
|
||||
else
|
||||
want_qt6="maybe"
|
||||
fi
|
||||
# Remove qt6; further down qt will be added
|
||||
enabled_languages=$(echo $enabled_languages | sed 's/qt6//')
|
||||
fi
|
||||
|
||||
# Check whether qt is enabled; if yes then it has been enabled explicitly
|
||||
want_qt="no"
|
||||
LIST_MEMBER("qt", $enabled_languages)
|
||||
if test "$found" = "1"; then
|
||||
# Ignore qt if specified together with qt5 or qt6
|
||||
if test "$want_qt5" = "no" -a "$want_qt6" = "no"; then
|
||||
want_qt="yes"
|
||||
fi
|
||||
# Remove qt
|
||||
enabled_languages=$(echo $enabled_languages | sed 's/qt//')
|
||||
AC_MSG_WARN([[
|
||||
***
|
||||
*** Language binding "qt" is deprecated and will be removed in a future version.
|
||||
*** Use "qt5" and/or "qt6" instead.
|
||||
***]])
|
||||
fi
|
||||
|
||||
# Ensure that pkg-config is available for all calls of FIND_QT5/FIND_QT6
|
||||
PKG_PROG_PKG_CONFIG
|
||||
|
||||
# Check for Qt 5 (if qt5 or qt is enabled)
|
||||
if test "$want_qt" = "yes"; then
|
||||
want_qt5="maybe"
|
||||
fi
|
||||
if test "$want_qt5" != "no"; then
|
||||
FIND_QT5
|
||||
if test "$have_qt5_libs" = "yes"; then
|
||||
want_qt5="yes"
|
||||
elif test "$want_qt5" = "yes"; then
|
||||
AC_MSG_ERROR([[
|
||||
***
|
||||
*** Qt5 (Qt5Core) is required for the Qt 5 binding.
|
||||
***]])
|
||||
else
|
||||
want_qt5="no"
|
||||
fi
|
||||
fi
|
||||
|
||||
# Check for Qt 6 (if qt6 is enabled or if qt is enabled and Qt 5 wasn't found)
|
||||
if test "$want_qt" = "yes" -a "$have_qt5_libs" != "yes"; then
|
||||
want_qt6="maybe"
|
||||
fi
|
||||
if test "$want_qt6" != "no"; then
|
||||
FIND_QT6
|
||||
if test "$have_qt6_libs" = "yes"; then
|
||||
want_qt6="yes";
|
||||
elif test "$want_qt6" = "yes"; then
|
||||
AC_MSG_ERROR([[
|
||||
***
|
||||
*** Qt6 (Qt6Core) is required for the Qt 6 binding.
|
||||
***]])
|
||||
else
|
||||
want_qt6="no"
|
||||
fi
|
||||
fi
|
||||
|
||||
# Check if any Qt was found (if qt is enabled)
|
||||
if test "$want_qt" = "yes" -a "$have_qt5_libs" != "yes" -a "$have_qt6_libs" != "yes"; then
|
||||
AC_MSG_ERROR([[
|
||||
***
|
||||
*** Qt5 (Qt5Core) or Qt6 (Qt6Core) is required for the Qt bindings.
|
||||
***]])
|
||||
fi
|
||||
|
||||
# Check that cpp is enabled if qt5 or qt6 is enabled and was found
|
||||
if test "$want_qt5" = "yes" -o "$want_qt6" = "yes"; then
|
||||
LIST_MEMBER("cpp", $enabled_languages)
|
||||
if test "$found" = "0"; then
|
||||
AC_MSG_ERROR([[
|
||||
***
|
||||
*** The Qt bindings depend on the C++ binding.
|
||||
***]])
|
||||
fi
|
||||
fi
|
||||
|
||||
# Enable C++ 17 if qt6 is requested
|
||||
if test "$want_qt6" = "yes"; then
|
||||
AX_CXX_COMPILE_STDCXX(17, noext, optional)
|
||||
if test "$HAVE_CXX17" != "1"; then
|
||||
if test "$explicit_languages" = "1"; then
|
||||
AC_MSG_ERROR([[
|
||||
***
|
||||
*** A compiler with c++17 support is required for the Qt 6 binding.
|
||||
***]])
|
||||
else
|
||||
want_qt6="no"
|
||||
AC_MSG_WARN([[
|
||||
***
|
||||
*** No c++17 support detected. Qt 6 binding will be disabled.
|
||||
***]])
|
||||
fi
|
||||
fi
|
||||
fi
|
||||
|
||||
# Enable C++ 11 if cpp is requested (unless C++ 17 was already enabled)
|
||||
# Enable C++ 11 if cpp language is requested
|
||||
LIST_MEMBER("cpp", $enabled_languages)
|
||||
if test "$found" = "1" -a "$HAVE_CXX17" != "1"; then
|
||||
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.
|
||||
*** A compiler with c++11 support is required for the c++ binding.
|
||||
***]])
|
||||
else
|
||||
enabled_languages=$(echo $enabled_languages | sed 's/cpp//')
|
||||
want_qt5="no"
|
||||
enabled_languages=$(echo $enabled_languages | sed 's/qt//')
|
||||
AC_MSG_WARN([[
|
||||
***
|
||||
*** No c++11 support detected. C++ and Qt 5 bindings will be disabled.
|
||||
*** No c++11 support detected. C++ and Qt bindings will be disabled.
|
||||
***]])
|
||||
fi
|
||||
fi
|
||||
fi
|
||||
|
||||
# Now append qt to the list of language bindings (to enable the subdir in lang)
|
||||
if test "$want_qt5" = "yes" -o "$want_qt6" = "yes"; then
|
||||
enabled_languages=$(echo $enabled_languages qt)
|
||||
fi
|
||||
|
||||
# Check whether compiler supports visibility attribute (if cpp language is enabled)
|
||||
LIST_MEMBER("cpp", $enabled_languages)
|
||||
# Check that if qt is enabled cpp also is enabled
|
||||
LIST_MEMBER("qt", $enabled_languages)
|
||||
if test "$found" = "1"; then
|
||||
AX_GCC_FUNC_ATTRIBUTE(visibility)
|
||||
if test "$ax_cv_have_func_attribute_visibility" = "yes"; then
|
||||
GPGME_CPP_CFLAGS="$GPGME_CPP_CFLAGS -fvisibility=hidden"
|
||||
if test "$want_qt5" = "yes"; then
|
||||
GPGME_QT5_CFLAGS="$GPGME_QT5_CFLAGS -fvisibility=hidden"
|
||||
# We need to ensure that in the language 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
|
||||
if test "$want_qt6" = "yes"; then
|
||||
GPGME_QT6_CFLAGS="$GPGME_QT6_CFLAGS -fvisibility=hidden"
|
||||
else
|
||||
enabled_languages=`echo $enabled_languages qt`
|
||||
|
||||
AC_CHECK_PROGS([DOXYGEN], [doxygen])
|
||||
if test -z "$DOXYGEN";
|
||||
# This is not highlighted because it's not really important.
|
||||
then AC_MSG_WARN([Doxygen not found - Qt binding doc will not be built.])
|
||||
fi
|
||||
AC_CHECK_PROGS([GRAPHVIZ], [dot])
|
||||
if test -z "$GRAPHVIZ";
|
||||
then AC_MSG_WARN([Graphviz not found - Qt binding doc will not have diagrams.])
|
||||
fi
|
||||
fi
|
||||
fi
|
||||
AC_SUBST(GPGME_CPP_CFLAGS)
|
||||
|
||||
AM_CONDITIONAL(WANT_QT5, test "$want_qt5" = yes)
|
||||
AM_CONDITIONAL(WANT_QT6, test "$want_qt6" = yes)
|
||||
|
||||
# Check for tools for building the Qt binding docs
|
||||
if test "$want_qt5" = "yes" -o "$want_qt6" = "yes"; then
|
||||
AC_CHECK_PROGS([DOXYGEN], [doxygen])
|
||||
if test -z "$DOXYGEN"; then
|
||||
# This is not highlighted because it's not really important.
|
||||
AC_MSG_WARN([Doxygen not found - Qt binding doc will not be built.])
|
||||
fi
|
||||
AC_CHECK_PROGS([GRAPHVIZ], [dot])
|
||||
if test -z "$GRAPHVIZ"; then
|
||||
AC_MSG_WARN([Graphviz not found - Qt binding doc will not have diagrams.])
|
||||
fi
|
||||
fi
|
||||
|
||||
AM_CONDITIONAL([HAVE_DOXYGEN],
|
||||
[test -n "$DOXYGEN"])
|
||||
if test -n "$GRAPHVIZ"; then
|
||||
@ -608,12 +388,11 @@ if test "$found_py" = "1"; then
|
||||
if test "$found_py" = "1" -o "$found_py3" = "1"; then
|
||||
# Reset everything, so that we can look for another Python.
|
||||
m4_foreach([mym4pythonver],
|
||||
[[2.7],[3.6],[3.8],[3.9],[3.10],[3.11],[3.12],[all]],
|
||||
[[2.7],[3.4],[3.5],[3.6],[3.7],[3.8],[all]],
|
||||
[unset PYTHON
|
||||
unset PYTHON_VERSION
|
||||
unset PYTHON_CPPFLAGS
|
||||
unset PYTHON_LDFLAGS
|
||||
unset PYTHON_LIBS
|
||||
unset PYTHON_SITE_PKG
|
||||
unset PYTHON_EXTRA_LIBS
|
||||
unset PYTHON_EXTRA_LDFLAGS
|
||||
@ -624,7 +403,7 @@ if test "$found_py" = "1"; then
|
||||
unset am_cv_python_pythondir
|
||||
unset am_cv_python_pyexecdir
|
||||
AM_PATH_PYTHON(mym4pythonver, [
|
||||
AX_PYTHON_DEVEL([], [true])
|
||||
AX_PYTHON_DEVEL
|
||||
if test "$PYTHON_VERSION"; then
|
||||
PYTHONS="$(echo $PYTHONS $PYTHON)"
|
||||
PYTHON_VERSIONS="$(echo $PYTHON_VERSIONS $PYTHON_VERSION)"
|
||||
@ -678,7 +457,7 @@ AC_SUBST(BUILD_VERSION)
|
||||
AC_SUBST(BUILD_FILEVERSION)
|
||||
|
||||
AC_ARG_ENABLE([build-timestamp],
|
||||
AS_HELP_STRING([--enable-build-timestamp],
|
||||
AC_HELP_STRING([--enable-build-timestamp],
|
||||
[set an explicit build timestamp for reproducibility.
|
||||
(default is the current time in ISO-8601 format)]),
|
||||
[if test "$enableval" = "yes"; then
|
||||
@ -697,37 +476,36 @@ AC_DEFINE_UNQUOTED(BUILD_TIMESTAMP, "$BUILD_TIMESTAMP",
|
||||
#
|
||||
run_gpgconf_test="yes"
|
||||
AC_ARG_ENABLE(gpgconf-test,
|
||||
AS_HELP_STRING([--disable-gpgconf-test],[disable GPGCONF regression test]),
|
||||
AC_HELP_STRING([--disable-gpgconf-test], [disable GPGCONF regression test]),
|
||||
run_gpgconf_test=$enableval)
|
||||
AM_CONDITIONAL(RUN_GPGCONF_TESTS, test "$run_gpgconf_test" = "yes")
|
||||
|
||||
run_gpg_test="yes"
|
||||
AC_ARG_ENABLE(gpg-test,
|
||||
AS_HELP_STRING([--disable-gpg-test],[disable GPG regression test]),
|
||||
AC_HELP_STRING([--disable-gpg-test], [disable GPG regression test]),
|
||||
run_gpg_test=$enableval)
|
||||
AM_CONDITIONAL(RUN_GPG_TESTS, test "$run_gpg_test" = "yes")
|
||||
|
||||
run_gpgsm_test="yes"
|
||||
AC_ARG_ENABLE(gpgsm-test,
|
||||
AS_HELP_STRING([--disable-gpgsm-test],[disable GPGSM regression test]),
|
||||
AC_HELP_STRING([--disable-gpgsm-test], [disable GPGSM regression test]),
|
||||
run_gpgsm_test=$enableval)
|
||||
AM_CONDITIONAL(RUN_GPGSM_TESTS, test "$run_gpgsm_test" = "yes")
|
||||
|
||||
run_g13_test="yes"
|
||||
AC_ARG_ENABLE(g13-test,
|
||||
AS_HELP_STRING([--disable-g13-test],[disable G13 regression test]),
|
||||
AC_HELP_STRING([--disable-g13-test], [disable G13 regression test]),
|
||||
run_g13_test=$enableval)
|
||||
AM_CONDITIONAL(RUN_G13_TESTS, test "$run_g13_test" = "yes")
|
||||
|
||||
|
||||
# Checks for header files.
|
||||
AC_CHECK_HEADERS_ONCE([locale.h sys/select.h sys/uio.h argp.h stdint.h
|
||||
unistd.h poll.h sys/time.h sys/types.h sys/stat.h])
|
||||
unistd.h sys/time.h sys/types.h sys/stat.h])
|
||||
|
||||
|
||||
# Type checks.
|
||||
AC_C_INLINE
|
||||
AC_C_FLEXIBLE_ARRAY_MEMBER
|
||||
AC_CHECK_SIZEOF(unsigned int)
|
||||
AC_SYS_LARGEFILE
|
||||
AC_TYPE_OFF_T
|
||||
@ -786,30 +564,25 @@ AM_SUBST_NOTMAKE(API__SSIZE_T)
|
||||
# Checks for compiler features.
|
||||
if test "$GCC" = yes; then
|
||||
CFLAGS="$CFLAGS -Wall -Wcast-align -Wshadow -Wstrict-prototypes"
|
||||
CFLAGS="$CFLAGS -Wno-format-y2k"
|
||||
|
||||
# If -Wno-missing-field-initializers is supported we can expect a
|
||||
# a larger set of warning options.
|
||||
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 -Wno-missing-field-initializers"
|
||||
CFLAGS="$CFLAGS -Wno-sign-compare"
|
||||
CFLAGS="$CFLAGS -Wno-format-zero-length"
|
||||
CFLAGS="$CFLAGS -Wno-format-truncation"
|
||||
CFLAGS="$CFLAGS -Wno-sizeof-pointer-div"
|
||||
fi
|
||||
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"
|
||||
CFLAGS="$CFLAGS -Wno-format-zero-length"
|
||||
fi
|
||||
CFLAGS="$CFLAGS -Wformat -Wformat-security"
|
||||
CXXFLAGS="$CXXFLAGS -Wall -Wextra -Wno-shadow"
|
||||
|
||||
AC_MSG_CHECKING([if gcc supports -Wpointer-arith])
|
||||
@ -890,9 +663,6 @@ AM_PATH_GPG_ERROR("$NEED_GPG_ERROR_VERSION",
|
||||
AC_DEFINE(GPG_ERR_SOURCE_DEFAULT, GPG_ERR_SOURCE_GPGME,
|
||||
[The default error source for GPGME.])
|
||||
|
||||
AM_CONDITIONAL(USE_GPGRT_CONFIG, [test -n "$GPGRT_CONFIG" \
|
||||
-a "$ac_cv_path_GPG_ERROR_CONFIG" = no])
|
||||
|
||||
# And for libassuan.
|
||||
have_libassuan=no
|
||||
AM_PATH_LIBASSUAN("$NEED_LIBASSUAN_API:$NEED_LIBASSUAN_VERSION",
|
||||
@ -908,7 +678,7 @@ fi
|
||||
#
|
||||
|
||||
# Check for getgid etc
|
||||
AC_CHECK_FUNCS(getgid getegid closefrom nanosleep)
|
||||
AC_CHECK_FUNCS(getgid getegid closefrom)
|
||||
|
||||
|
||||
# Replacement functions.
|
||||
@ -938,7 +708,7 @@ AC_CHECK_MEMBER(struct cmsghdr.cmsg_len,
|
||||
|
||||
use_descriptor_passing=yes
|
||||
AC_ARG_ENABLE(fd-passing,
|
||||
AS_HELP_STRING([--disable-fd-passing],[do not use FD passing]),
|
||||
AC_HELP_STRING([--disable-fd-passing], [do not use FD passing]),
|
||||
use_descriptor_passing=$enableval)
|
||||
|
||||
if test "$supports_descriptor_passing" != "yes"; then
|
||||
@ -970,7 +740,7 @@ AM_CONDITIONAL(HAVE_UISERVER, test "$uiserver" != "no")
|
||||
# before an exec. This option allows to switch this optimization off.
|
||||
use_linux_getdents=yes
|
||||
AC_ARG_ENABLE(linux-getdents,
|
||||
AS_HELP_STRING([--disable-linux-getdents],
|
||||
AC_HELP_STRING([--disable-linux-getdents],
|
||||
[do not use SYS_getdents on Linux]),
|
||||
use_linux_getdents=$enableval)
|
||||
if test "$use_linux_getdents" = "yes"; then
|
||||
@ -1008,56 +778,19 @@ AH_BOTTOM([
|
||||
# define GPGME_GCC_A_PURE
|
||||
#endif
|
||||
|
||||
/* Under Windows we use the gettext code from gpgrt. */
|
||||
#define GPG_ERR_ENABLE_GETTEXT_MACROS 1
|
||||
|
||||
/* Under WindowsCE we need gpg-error's strerror macro. */
|
||||
#define GPG_ERR_ENABLE_ERRNO_MACROS 1
|
||||
|
||||
#define CRIGHTBLURB "Copyright (C) 2000 Werner Koch\n" \
|
||||
"Copyright (C) 2001--2021 g10 Code GmbH\n"
|
||||
"Copyright (C) 2001--2018 g10 Code GmbH\n"
|
||||
])
|
||||
|
||||
|
||||
# Substitution used for gpgme-config and gpgme.pc
|
||||
# Substitution used for gpgme-config
|
||||
GPGME_CONFIG_LIBS="-lgpgme"
|
||||
GPGME_CONFIG_CFLAGS=""
|
||||
GPGME_CONFIG_HOST="$host"
|
||||
GPGME_CONFIG_AVAIL_LANG="$enabled_languages"
|
||||
|
||||
case "$includedir" in
|
||||
/usr/include|/include) ;;
|
||||
'${prefix}/include')
|
||||
if test "$prefix" != / -a "$prefix" != /usr; then
|
||||
if test -z "$GPGME_CONFIG_CFLAGS"; then
|
||||
GPGME_CONFIG_CFLAGS="-I\${includedir}"
|
||||
else
|
||||
GPGME_CONFIG_CFLAGS="-I\${includedir} $GPGME_CONFIG_CFLAGS"
|
||||
fi
|
||||
fi
|
||||
;;
|
||||
*)
|
||||
if test -z "$GPGME_CONFIG_CFLAGS"; then
|
||||
GPGME_CONFIG_CFLAGS="-I\${includedir}"
|
||||
else
|
||||
GPGME_CONFIG_CFLAGS="-I\${includedir} $GPGME_CONFIG_CFLAGS"
|
||||
fi
|
||||
;;
|
||||
esac
|
||||
case "$libdir" in
|
||||
/usr/lib|/usr/lib64|/lib|/lib64) ;;
|
||||
'${exec_prefix}/lib'|'${exec_prefix}/lib64')
|
||||
if test "$exec_prefix" = "NONE"; then
|
||||
if test "$prefix" != / -a "$prefix" != /usr; then
|
||||
GPGME_CONFIG_LIBS="-L\${libdir} $GPGME_CONFIG_LIBS"
|
||||
fi
|
||||
elif test "$exec_prefix" != / -a "$exec_prefix" != /usr; then
|
||||
GPGME_CONFIG_LIBS="-L\${libdir} $GPGME_CONFIG_LIBS"
|
||||
fi
|
||||
;;
|
||||
*) GPGME_CONFIG_LIBS="-L\${libdir} $GPGME_CONFIG_LIBS" ;;
|
||||
esac
|
||||
|
||||
AC_SUBST(GPGME_CONFIG_API_VERSION)
|
||||
AC_SUBST(GPGME_CONFIG_LIBS)
|
||||
AC_SUBST(GPGME_CONFIG_CFLAGS)
|
||||
@ -1136,16 +869,9 @@ 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)
|
||||
if test "$want_qt5" = "yes"; then
|
||||
AC_CONFIG_FILES(lang/qt/src/QGpgmeConfig-w32.cmake.in)
|
||||
AC_CONFIG_FILES(lang/qt/src/QGpgmeConfig.cmake.in)
|
||||
AC_CONFIG_FILES(lang/qt/src/QGpgmeConfigVersion.cmake)
|
||||
fi
|
||||
if test "$want_qt6" = "yes"; then
|
||||
AC_CONFIG_FILES(lang/qt/src/QGpgmeQt6Config-w32.cmake.in)
|
||||
AC_CONFIG_FILES(lang/qt/src/QGpgmeQt6Config.cmake.in)
|
||||
AC_CONFIG_FILES(lang/qt/src/QGpgmeQt6ConfigVersion.cmake)
|
||||
fi
|
||||
AC_CONFIG_FILES(lang/qt/src/QGpgmeConfig-w32.cmake.in)
|
||||
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])
|
||||
@ -1156,21 +882,10 @@ AC_CONFIG_FILES([lang/js/Makefile lang/js/src/Makefile
|
||||
AC_CONFIG_FILES(lang/qt/doc/Makefile)
|
||||
AC_CONFIG_FILES([lang/python/Makefile
|
||||
lang/python/version.py
|
||||
lang/python/tests/Makefile
|
||||
lang/python/src/Makefile
|
||||
lang/python/examples/Makefile
|
||||
lang/python/doc/Makefile])
|
||||
lang/python/tests/Makefile])
|
||||
AC_CONFIG_FILES([lang/python/setup.py], [chmod a+x lang/python/setup.py])
|
||||
AC_OUTPUT
|
||||
|
||||
if test "$want_qt5" = "yes" -a "$want_qt6" = "yes"; then
|
||||
enabled_languages_v=$(echo ${enabled_languages_v:-$enabled_languages} | sed "s/qt/qt (Qt 5, Qt 6)/")
|
||||
elif test "$want_qt5" = "yes"; then
|
||||
enabled_languages_v=$(echo ${enabled_languages_v:-$enabled_languages} | sed "s/qt/qt (Qt 5)/")
|
||||
elif test "$want_qt6" = "yes"; then
|
||||
enabled_languages_v=$(echo ${enabled_languages_v:-$enabled_languages} | sed "s/qt/qt (Qt 6)/")
|
||||
fi
|
||||
|
||||
echo "
|
||||
GPGME v${VERSION} has been configured as follows:
|
||||
|
||||
|
986
doc/gpgme.texi
986
doc/gpgme.texi
File diff suppressed because it is too large
Load Diff
@ -498,7 +498,7 @@
|
||||
% \def\foo{\parsearg\Xfoo}
|
||||
% \def\Xfoo#1{...}
|
||||
%
|
||||
% Actually, I use \csname\string\foo\endcsname, i.e. \\foo, as it is my
|
||||
% Actually, I use \csname\string\foo\endcsname, ie. \\foo, as it is my
|
||||
% favourite TeX trick. --kasal, 16nov03
|
||||
|
||||
\def\parseargdef#1{%
|
||||
|
@ -18,12 +18,6 @@
|
||||
# License along with this program; if not, see <https://gnu.org/licenses/>.
|
||||
# SPDX-License-Identifier: LGPL-2.1-or-later
|
||||
|
||||
if RUN_GPG_TESTS
|
||||
tests = tests
|
||||
else
|
||||
tests =
|
||||
endif
|
||||
|
||||
SUBDIRS = src ${tests}
|
||||
SUBDIRS = src tests
|
||||
|
||||
EXTRA_DIST = README
|
||||
|
@ -97,3 +97,7 @@ 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)
|
||||
|
@ -93,3 +93,7 @@ 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)
|
||||
|
@ -33,13 +33,9 @@ main_sources = \
|
||||
engineinfo.cpp gpgsetexpirytimeeditinteractor.cpp \
|
||||
gpgsetownertrusteditinteractor.cpp gpgsignkeyeditinteractor.cpp \
|
||||
gpgadduserideditinteractor.cpp gpggencardkeyinteractor.cpp \
|
||||
gpgaddexistingsubkeyeditinteractor.cpp \
|
||||
gpgrevokekeyeditinteractor.cpp \
|
||||
defaultassuantransaction.cpp \
|
||||
scdgetinfoassuantransaction.cpp gpgagentgetinfoassuantransaction.cpp \
|
||||
statusconsumerassuantransaction.cpp \
|
||||
vfsmountresult.cpp configuration.cpp tofuinfo.cpp swdbresult.cpp \
|
||||
util.cpp
|
||||
vfsmountresult.cpp configuration.cpp tofuinfo.cpp swdbresult.cpp
|
||||
|
||||
gpgmepp_headers = \
|
||||
configuration.h context.h data.h decryptionresult.h \
|
||||
@ -49,11 +45,8 @@ gpgmepp_headers = \
|
||||
gpgmefw.h gpgsetexpirytimeeditinteractor.h \
|
||||
gpgsetownertrusteditinteractor.h gpgsignkeyeditinteractor.h \
|
||||
gpggencardkeyinteractor.h \
|
||||
gpgaddexistingsubkeyeditinteractor.h \
|
||||
gpgrevokekeyeditinteractor.h \
|
||||
importresult.h keygenerationresult.h key.h keylistresult.h \
|
||||
notation.h result.h scdgetinfoassuantransaction.h signingresult.h \
|
||||
statusconsumerassuantransaction.h \
|
||||
trustitem.h verificationresult.h vfsmountresult.h gpgmepp_export.h \
|
||||
tofuinfo.h swdbresult.h
|
||||
|
||||
@ -62,8 +55,7 @@ private_gpgmepp_headers = \
|
||||
|
||||
interface_headers= \
|
||||
interfaces/assuantransaction.h interfaces/dataprovider.h \
|
||||
interfaces/passphraseprovider.h interfaces/progressprovider.h \
|
||||
interfaces/statusconsumer.h
|
||||
interfaces/passphraseprovider.h interfaces/progressprovider.h
|
||||
|
||||
gpgmeppincludedir = $(includedir)/gpgme++
|
||||
gpgmeppinclude_HEADERS = $(gpgmepp_headers)
|
||||
@ -73,8 +65,7 @@ nodist_gpgmeppinclude_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 \
|
||||
@GPGME_CPP_CFLAGS@ @GPG_ERROR_CFLAGS@ @LIBASSUAN_CFLAGS@ \
|
||||
AM_CPPFLAGS = -I$(top_builddir)/src @GPG_ERROR_CFLAGS@ @LIBASSUAN_CFLAGS@ \
|
||||
-DBUILDING_GPGMEPP -Wsuggest-override \
|
||||
-Wzero-as-null-pointer-constant
|
||||
|
||||
@ -88,14 +79,6 @@ else
|
||||
libsuffix=.so
|
||||
endif
|
||||
|
||||
copied_headers = $(gpgmepp_headers:%=gpgme++/%) $(interface_headers:%=gpgme++/%)
|
||||
|
||||
$(copied_headers): Makefile.am
|
||||
mkdir -p $(builddir)/gpgme++/interfaces
|
||||
echo -n "#include \"$(abs_srcdir)" > "$@"
|
||||
echo -n "$@" | sed "s/gpgme++//" >> "$@"
|
||||
echo "\"" >> "$@"
|
||||
|
||||
if HAVE_W32_SYSTEM
|
||||
GpgmeppConfig.cmake: GpgmeppConfig-w32.cmake.in
|
||||
sed -e 's|[@]resolved_bindir@|$(bindir)|g' < "$<" | \
|
||||
@ -123,8 +106,5 @@ install-data-local: install-cmake-files
|
||||
|
||||
uninstall-local: uninstall-cmake-files
|
||||
|
||||
BUILT_SOURCES = $(copied_headers)
|
||||
|
||||
CLEANFILES = GpgmeppConfig.cmake GpgmeppConfigVersion.cmake \
|
||||
gpgmepp_version.h GpgmeppConfig.cmake.in \
|
||||
$(copied_headers)
|
||||
gpgmepp_version.h GpgmeppConfig.cmake.in
|
||||
|
@ -257,6 +257,158 @@ 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()) {
|
||||
|
@ -98,7 +98,8 @@ public:
|
||||
explicit Component(const shared_gpgme_conf_comp_t &gpgme_comp)
|
||||
: comp(gpgme_comp) {}
|
||||
|
||||
Component(const Component &other) = default;
|
||||
// copy ctor is ok
|
||||
|
||||
const Component &operator=(const Component &other)
|
||||
{
|
||||
if (this != &other) {
|
||||
@ -148,7 +149,6 @@ public:
|
||||
Option(const shared_gpgme_conf_comp_t &gpgme_comp, gpgme_conf_opt_t gpgme_opt)
|
||||
: comp(gpgme_comp), opt(gpgme_opt) {}
|
||||
|
||||
Option(const Option &other) = default;
|
||||
const Option &operator=(const Option &other)
|
||||
{
|
||||
if (this != &other) {
|
||||
@ -190,7 +190,7 @@ public:
|
||||
|
||||
/*! 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, i.e. either activeValue(), newValue(), or defaultValue() */
|
||||
/*! The value that is in this object, ie. either activeValue(), newValue(), or defaultValue() */
|
||||
Argument currentValue() const;
|
||||
|
||||
Argument newValue() const;
|
||||
|
@ -50,9 +50,7 @@
|
||||
|
||||
#include <gpgme.h>
|
||||
|
||||
#include <functional>
|
||||
#include <istream>
|
||||
#include <numeric>
|
||||
#ifndef NDEBUG
|
||||
#include <iostream>
|
||||
using std::cerr;
|
||||
@ -130,13 +128,6 @@ const char *Error::asString() const
|
||||
return mMessage.c_str();
|
||||
}
|
||||
|
||||
std::string Error::asStdString() const
|
||||
{
|
||||
std::string message;
|
||||
format_error(static_cast<gpgme_error_t>(mErr), message);
|
||||
return message;
|
||||
}
|
||||
|
||||
int Error::code() const
|
||||
{
|
||||
return gpgme_err_code(mErr);
|
||||
@ -149,18 +140,22 @@ int Error::sourceID() const
|
||||
|
||||
bool Error::isCanceled() const
|
||||
{
|
||||
return code() == GPG_ERR_CANCELED || code() == GPG_ERR_FULLY_CANCELED;
|
||||
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 ;
|
||||
return gpgme_err_code_from_syserror() == GPG_ERR_MISSING_ERRNO ;
|
||||
}
|
||||
|
||||
// static
|
||||
@ -195,20 +190,7 @@ Error Error::fromCode(unsigned int err, unsigned int src)
|
||||
|
||||
std::ostream &operator<<(std::ostream &os, const Error &err)
|
||||
{
|
||||
return os << "GpgME::Error(" << err.encodedError() << " (" << err.asStdString() << "))";
|
||||
}
|
||||
|
||||
Context::KeyListModeSaver::KeyListModeSaver(Context *ctx)
|
||||
: mCtx{ctx}
|
||||
, mKeyListMode{ctx ? ctx->keyListMode() : 0}
|
||||
{
|
||||
}
|
||||
|
||||
Context::KeyListModeSaver::~KeyListModeSaver()
|
||||
{
|
||||
if (mCtx) {
|
||||
mCtx->setKeyListMode(mKeyListMode);
|
||||
}
|
||||
return os << "GpgME::Error(" << err.encodedError() << " (" << err.asString() << "))";
|
||||
}
|
||||
|
||||
Context::Context(gpgme_ctx_t ctx) : d(new Private(ctx))
|
||||
@ -479,33 +461,9 @@ Error Context::setLocale(int cat, const char *val)
|
||||
return Error(d->lasterr = gpgme_set_locale(d->ctx, cat, val));
|
||||
}
|
||||
|
||||
static GpgME::EngineInfo get_engine_info(gpgme_engine_info_t engineInfos, gpgme_protocol_t protocol)
|
||||
{
|
||||
if (!engineInfos) {
|
||||
return EngineInfo{};
|
||||
}
|
||||
|
||||
for (gpgme_engine_info_t i = engineInfos ; i ; i = i->next) {
|
||||
if (i->protocol == protocol) {
|
||||
return EngineInfo{i};
|
||||
}
|
||||
}
|
||||
|
||||
return EngineInfo{};
|
||||
}
|
||||
|
||||
static GpgME::EngineInfo get_static_engine_info(gpgme_protocol_t protocol)
|
||||
{
|
||||
gpgme_engine_info_t ei = nullptr;
|
||||
if (gpgme_get_engine_info(&ei)) {
|
||||
return EngineInfo{};
|
||||
}
|
||||
return get_engine_info(ei, protocol);
|
||||
}
|
||||
|
||||
EngineInfo Context::engineInfo() const
|
||||
{
|
||||
return get_engine_info(gpgme_ctx_get_engine_info(d->ctx), gpgme_get_protocol(d->ctx));
|
||||
return EngineInfo(gpgme_ctx_get_engine_info(d->ctx));
|
||||
}
|
||||
|
||||
Error Context::setEngineFileName(const char *filename)
|
||||
@ -538,25 +496,25 @@ const char *Context::getSender ()
|
||||
|
||||
Error Context::startKeyListing(const char *pattern, bool secretOnly)
|
||||
{
|
||||
d->lastop = (((keyListMode() & GpgME::Locate) == GpgME::Locate)
|
||||
? Private::KeyListWithImport
|
||||
: Private::KeyList);
|
||||
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 = (((keyListMode() & GpgME::Locate) == GpgME::Locate)
|
||||
? Private::KeyListWithImport
|
||||
: Private::KeyList);
|
||||
d->lastop = Private::KeyList;
|
||||
#ifndef HAVE_GPGME_EXT_KEYLIST_MODE_EXTERNAL_NONBROKEN
|
||||
if (!patterns || !patterns[0] || !patterns[1]) {
|
||||
// max. one pattern -> use the non-ext version
|
||||
return startKeyListing(patterns ? patterns[0] : nullptr, secretOnly);
|
||||
}
|
||||
#endif
|
||||
return Error(d->lasterr = gpgme_op_keylist_ext_start(d->ctx, patterns, int(secretOnly), 0));
|
||||
}
|
||||
|
||||
Key Context::nextKey(GpgME::Error &e)
|
||||
{
|
||||
d->lastop = (((keyListMode() & GpgME::Locate) == GpgME::Locate)
|
||||
? Private::KeyListWithImport
|
||||
: Private::KeyList);
|
||||
d->lastop = Private::KeyList;
|
||||
gpgme_key_t key = nullptr;
|
||||
e = Error(d->lasterr = gpgme_op_keylist_next(d->ctx, &key));
|
||||
return Key(key, false);
|
||||
@ -605,137 +563,44 @@ KeyGenerationResult Context::keyGenerationResult() const
|
||||
}
|
||||
}
|
||||
|
||||
Error Context::exportKeys(const char *pattern, Data &keyData, unsigned int mode)
|
||||
{
|
||||
d->lastop = Private::Export;
|
||||
Data::Private *const dp = keyData.impl();
|
||||
return Error(d->lasterr = gpgme_op_export(d->ctx, pattern, mode, dp ? dp->data : nullptr));
|
||||
}
|
||||
|
||||
Error Context::exportKeys(const char *patterns[], Data &keyData, unsigned int mode)
|
||||
{
|
||||
d->lastop = Private::Export;
|
||||
Data::Private *const dp = keyData.impl();
|
||||
return Error(d->lasterr = gpgme_op_export_ext(d->ctx, patterns, mode, dp ? dp->data : nullptr));
|
||||
}
|
||||
|
||||
Error Context::startKeyExport(const char *pattern, Data &keyData, unsigned int mode)
|
||||
{
|
||||
d->lastop = Private::Export;
|
||||
Data::Private *const dp = keyData.impl();
|
||||
return Error(d->lasterr = gpgme_op_export_start(d->ctx, pattern, mode, dp ? dp->data : nullptr));
|
||||
}
|
||||
|
||||
Error Context::startKeyExport(const char *patterns[], Data &keyData, unsigned int mode)
|
||||
{
|
||||
d->lastop = Private::Export;
|
||||
Data::Private *const dp = keyData.impl();
|
||||
return Error(d->lasterr = gpgme_op_export_ext_start(d->ctx, patterns, mode, dp ? dp->data : nullptr));
|
||||
}
|
||||
|
||||
Error Context::exportPublicKeys(const char *pattern, Data &keyData, unsigned int mode)
|
||||
{
|
||||
if (mode & (ExportSecret | ExportSecretSubkey)) {
|
||||
return Error::fromCode(GPG_ERR_INV_FLAG);
|
||||
}
|
||||
return exportKeys(pattern, keyData, mode);
|
||||
}
|
||||
|
||||
Error Context::exportPublicKeys(const char *patterns[], Data &keyData, unsigned int mode)
|
||||
{
|
||||
if (mode & (ExportSecret | ExportSecretSubkey)) {
|
||||
return Error::fromCode(GPG_ERR_INV_FLAG);
|
||||
}
|
||||
return exportKeys(patterns, keyData, mode);
|
||||
}
|
||||
|
||||
Error Context::startPublicKeyExport(const char *pattern, Data &keyData, unsigned int mode)
|
||||
{
|
||||
if (mode & (ExportSecret | ExportSecretSubkey)) {
|
||||
return Error::fromCode(GPG_ERR_INV_FLAG);
|
||||
}
|
||||
return startKeyExport(pattern, keyData, mode);
|
||||
}
|
||||
|
||||
Error Context::startPublicKeyExport(const char *patterns[], Data &keyData, unsigned int mode)
|
||||
{
|
||||
if (mode & (ExportSecret | ExportSecretSubkey)) {
|
||||
return Error::fromCode(GPG_ERR_INV_FLAG);
|
||||
}
|
||||
return startKeyExport(patterns, keyData, mode);
|
||||
}
|
||||
|
||||
/* Same as above but without mode */
|
||||
Error Context::exportPublicKeys(const char *pattern, Data &keyData)
|
||||
{
|
||||
return exportPublicKeys(pattern, keyData, 0);
|
||||
d->lastop = Private::Export;
|
||||
Data::Private *const dp = keyData.impl();
|
||||
return Error(d->lasterr = gpgme_op_export(d->ctx, pattern, 0, dp ? dp->data : nullptr));
|
||||
}
|
||||
|
||||
Error Context::exportPublicKeys(const char *patterns[], Data &keyData)
|
||||
{
|
||||
return exportPublicKeys(patterns, keyData, 0);
|
||||
d->lastop = Private::Export;
|
||||
#ifndef HAVE_GPGME_EXT_KEYLIST_MODE_EXTERNAL_NONBROKEN
|
||||
if (!patterns || !patterns[0] || !patterns[1]) {
|
||||
// max. one pattern -> use the non-ext version
|
||||
return exportPublicKeys(patterns ? patterns[0] : nullptr, keyData);
|
||||
}
|
||||
#endif
|
||||
Data::Private *const dp = keyData.impl();
|
||||
return Error(d->lasterr = gpgme_op_export_ext(d->ctx, patterns, 0, dp ? dp->data : nullptr));
|
||||
}
|
||||
|
||||
Error Context::startPublicKeyExport(const char *pattern, Data &keyData)
|
||||
{
|
||||
return startPublicKeyExport(pattern, keyData, 0);
|
||||
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 : nullptr));
|
||||
}
|
||||
|
||||
Error Context::startPublicKeyExport(const char *patterns[], Data &keyData)
|
||||
{
|
||||
return startPublicKeyExport(patterns, keyData, 0);
|
||||
}
|
||||
|
||||
Error Context::exportSecretKeys(const char *pattern, Data &keyData, unsigned int mode)
|
||||
{
|
||||
if (mode & ExportSecretSubkey) {
|
||||
return Error::fromCode(GPG_ERR_INV_FLAG);
|
||||
d->lastop = Private::Export;
|
||||
#ifndef HAVE_GPGME_EXT_KEYLIST_MODE_EXTERNAL_NONBROKEN
|
||||
if (!patterns || !patterns[0] || !patterns[1]) {
|
||||
// max. one pattern -> use the non-ext version
|
||||
return startPublicKeyExport(patterns ? patterns[0] : nullptr, keyData);
|
||||
}
|
||||
return exportKeys(pattern, keyData, mode|ExportSecret);
|
||||
}
|
||||
|
||||
Error Context::exportSecretKeys(const char *patterns[], Data &keyData, unsigned int mode)
|
||||
{
|
||||
if (mode & ExportSecretSubkey) {
|
||||
return Error::fromCode(GPG_ERR_INV_FLAG);
|
||||
}
|
||||
return exportKeys(patterns, keyData, mode|ExportSecret);
|
||||
}
|
||||
|
||||
Error Context::startSecretKeyExport(const char *pattern, Data &keyData, unsigned int mode)
|
||||
{
|
||||
if (mode & ExportSecretSubkey) {
|
||||
return Error::fromCode(GPG_ERR_INV_FLAG);
|
||||
}
|
||||
return startKeyExport(pattern, keyData, mode|ExportSecret);
|
||||
}
|
||||
|
||||
Error Context::startSecretKeyExport(const char *patterns[], Data &keyData, unsigned int mode)
|
||||
{
|
||||
if (mode & ExportSecretSubkey) {
|
||||
return Error::fromCode(GPG_ERR_INV_FLAG);
|
||||
}
|
||||
return startKeyExport(patterns, keyData, mode|ExportSecret);
|
||||
}
|
||||
|
||||
Error Context::exportSecretSubkeys(const char *pattern, Data &keyData, unsigned int mode)
|
||||
{
|
||||
return exportKeys(pattern, keyData, mode|ExportSecretSubkey);
|
||||
}
|
||||
|
||||
Error Context::exportSecretSubkeys(const char *patterns[], Data &keyData, unsigned int mode)
|
||||
{
|
||||
return exportKeys(patterns, keyData, mode|ExportSecretSubkey);
|
||||
}
|
||||
|
||||
Error Context::startSecretSubkeyExport(const char *pattern, Data &keyData, unsigned int mode)
|
||||
{
|
||||
return startKeyExport(pattern, keyData, mode|ExportSecretSubkey);
|
||||
}
|
||||
|
||||
Error Context::startSecretSubkeyExport(const char *patterns[], Data &keyData, unsigned int mode)
|
||||
{
|
||||
return startKeyExport(patterns, keyData, mode|ExportSecretSubkey);
|
||||
#endif
|
||||
Data::Private *const dp = keyData.impl();
|
||||
return Error(d->lasterr = gpgme_op_export_ext_start(d->ctx, patterns, 0, dp ? dp->data : nullptr));
|
||||
}
|
||||
|
||||
ImportResult Context::importKeys(const Data &data)
|
||||
@ -822,22 +687,6 @@ Error Context::startKeyImport(const std::vector<Key> &kk)
|
||||
return err;
|
||||
}
|
||||
|
||||
ImportResult Context::importKeys(const std::vector<std::string> &keyIds)
|
||||
{
|
||||
d->lastop = Private::Import;
|
||||
const StringsToCStrings keyids{keyIds};
|
||||
d->lasterr = gpgme_op_receive_keys(d->ctx, keyids.c_strs());
|
||||
return ImportResult(d->ctx, Error(d->lasterr));
|
||||
}
|
||||
|
||||
Error Context::startKeyImport(const std::vector<std::string> &keyIds)
|
||||
{
|
||||
d->lastop = Private::Import;
|
||||
const StringsToCStrings keyids{keyIds};
|
||||
d->lasterr = gpgme_op_receive_keys_start(d->ctx, keyids.c_strs());
|
||||
return Error(d->lasterr);
|
||||
}
|
||||
|
||||
ImportResult Context::importResult() const
|
||||
{
|
||||
if (d->lastop & Private::Import) {
|
||||
@ -1073,7 +922,7 @@ DecryptionResult Context::decrypt(const Data &cipherText, Data &plainText, const
|
||||
const Data::Private *const cdp = cipherText.impl();
|
||||
Data::Private *const pdp = plainText.impl();
|
||||
d->lasterr = gpgme_op_decrypt_ext(d->ctx, static_cast<gpgme_decrypt_flags_t> (d->decryptFlags | flags), cdp ? cdp->data : nullptr, pdp ? pdp->data : nullptr);
|
||||
return decryptionResult();
|
||||
return DecryptionResult(d->ctx, Error(d->lasterr));
|
||||
}
|
||||
|
||||
DecryptionResult Context::decrypt(const Data &cipherText, Data &plainText)
|
||||
@ -1110,7 +959,7 @@ VerificationResult Context::verifyDetachedSignature(const Data &signature, const
|
||||
const Data::Private *const sdp = signature.impl();
|
||||
const Data::Private *const tdp = signedText.impl();
|
||||
d->lasterr = gpgme_op_verify(d->ctx, sdp ? sdp->data : nullptr, tdp ? tdp->data : nullptr, nullptr);
|
||||
return verificationResult();
|
||||
return VerificationResult(d->ctx, Error(d->lasterr));
|
||||
}
|
||||
|
||||
VerificationResult Context::verifyOpaqueSignature(const Data &signedData, Data &plainText)
|
||||
@ -1119,7 +968,7 @@ VerificationResult Context::verifyOpaqueSignature(const Data &signedData, Data &
|
||||
const Data::Private *const sdp = signedData.impl();
|
||||
Data::Private *const pdp = plainText.impl();
|
||||
d->lasterr = gpgme_op_verify(d->ctx, sdp ? sdp->data : nullptr, nullptr, pdp ? pdp->data : nullptr);
|
||||
return verificationResult();
|
||||
return VerificationResult(d->ctx, Error(d->lasterr));
|
||||
}
|
||||
|
||||
Error Context::startDetachedSignatureVerification(const Data &signature, const Data &signedText)
|
||||
@ -1141,18 +990,9 @@ Error Context::startOpaqueSignatureVerification(const Data &signedData, Data &pl
|
||||
VerificationResult Context::verificationResult() const
|
||||
{
|
||||
if (d->lastop & Private::Verify) {
|
||||
const auto res = VerificationResult{d->ctx, Error(d->lasterr)};
|
||||
if ((d->lastop == Private::DecryptAndVerify)
|
||||
&& (res.error().code() == GPG_ERR_NO_DATA)
|
||||
&& (res.numSignatures() > 0)) {
|
||||
// ignore "no data" error for verification if there are signatures and
|
||||
// the operation was a combined (tentative) decryption and verification
|
||||
// because then "no data" just indicates that there was nothing to decrypt
|
||||
return VerificationResult{d->ctx, Error{}};
|
||||
}
|
||||
return res;
|
||||
return VerificationResult(d->ctx, Error(d->lasterr));
|
||||
} else {
|
||||
return {};
|
||||
return VerificationResult();
|
||||
}
|
||||
}
|
||||
|
||||
@ -1163,7 +1003,8 @@ std::pair<DecryptionResult, VerificationResult> Context::decryptAndVerify(const
|
||||
Data::Private *const pdp = plainText.impl();
|
||||
d->lasterr = gpgme_op_decrypt_ext(d->ctx, static_cast<gpgme_decrypt_flags_t> (d->decryptFlags | flags | DecryptVerify),
|
||||
cdp ? cdp->data : nullptr, pdp ? pdp->data : nullptr);
|
||||
return std::make_pair(decryptionResult(), verificationResult());
|
||||
return std::make_pair(DecryptionResult(d->ctx, Error(d->lasterr)),
|
||||
VerificationResult(d->ctx, Error(d->lasterr)));
|
||||
}
|
||||
|
||||
std::pair<DecryptionResult, VerificationResult> Context::decryptAndVerify(const Data &cipherText, Data &plainText)
|
||||
@ -1184,7 +1025,6 @@ Error Context::startCombinedDecryptionAndVerification(const Data &cipherText, Da
|
||||
return startCombinedDecryptionAndVerification(cipherText, plainText, DecryptNone);
|
||||
}
|
||||
|
||||
namespace {
|
||||
unsigned int to_auditlog_flags(unsigned int flags)
|
||||
{
|
||||
unsigned int result = 0;
|
||||
@ -1199,7 +1039,6 @@ unsigned int to_auditlog_flags(unsigned int flags)
|
||||
}
|
||||
return result;
|
||||
}
|
||||
}
|
||||
|
||||
Error Context::startGetAuditLog(Data &output, unsigned int flags)
|
||||
{
|
||||
@ -1289,25 +1128,14 @@ std::vector<Notation> Context::signatureNotations() const
|
||||
return result;
|
||||
}
|
||||
|
||||
static gpgme_sig_mode_t sigflags2sigflags(SignatureMode flags)
|
||||
static gpgme_sig_mode_t sigmode2sigmode(SignatureMode mode)
|
||||
{
|
||||
unsigned int result = 0;
|
||||
if (flags & SignatureMode::NormalSignatureMode) {
|
||||
result |= GPGME_SIG_MODE_NORMAL;
|
||||
switch (mode) {
|
||||
default:
|
||||
case NormalSignatureMode: return GPGME_SIG_MODE_NORMAL;
|
||||
case Detached: return GPGME_SIG_MODE_DETACH;
|
||||
case Clearsigned: return GPGME_SIG_MODE_CLEAR;
|
||||
}
|
||||
if (flags & SignatureMode::Detached) {
|
||||
result |= GPGME_SIG_MODE_DETACH;
|
||||
}
|
||||
if (flags & SignatureMode::Clearsigned) {
|
||||
result |= GPGME_SIG_MODE_CLEAR;
|
||||
}
|
||||
if (flags & SignatureMode::SignArchive) {
|
||||
result |= GPGME_SIG_MODE_ARCHIVE;
|
||||
}
|
||||
if (flags & SignatureMode::SignFile) {
|
||||
result |= GPGME_SIG_MODE_FILE;
|
||||
}
|
||||
return static_cast<gpgme_sig_mode_t>(result);
|
||||
}
|
||||
|
||||
SigningResult Context::sign(const Data &plainText, Data &signature, SignatureMode mode)
|
||||
@ -1315,7 +1143,7 @@ SigningResult Context::sign(const Data &plainText, Data &signature, SignatureMod
|
||||
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 : nullptr, sdp ? sdp->data : nullptr, sigflags2sigflags(mode));
|
||||
d->lasterr = gpgme_op_sign(d->ctx, pdp ? pdp->data : nullptr, sdp ? sdp->data : nullptr, sigmode2sigmode(mode));
|
||||
return SigningResult(d->ctx, Error(d->lasterr));
|
||||
}
|
||||
|
||||
@ -1324,7 +1152,7 @@ Error Context::startSigning(const Data &plainText, Data &signature, SignatureMod
|
||||
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 : nullptr, sdp ? sdp->data : nullptr, sigflags2sigflags(mode)));
|
||||
return Error(d->lasterr = gpgme_op_sign_start(d->ctx, pdp ? pdp->data : nullptr, sdp ? sdp->data : nullptr, sigmode2sigmode(mode)));
|
||||
}
|
||||
|
||||
SigningResult Context::signingResult() const
|
||||
@ -1357,21 +1185,6 @@ static gpgme_encrypt_flags_t encryptflags2encryptflags(Context::EncryptionFlags
|
||||
if (flags & Context::Symmetric) {
|
||||
result |= GPGME_ENCRYPT_SYMMETRIC;
|
||||
}
|
||||
if (flags & Context::ThrowKeyIds) {
|
||||
result |= GPGME_ENCRYPT_THROW_KEYIDS;
|
||||
}
|
||||
if (flags & Context::EncryptWrap) {
|
||||
result |= GPGME_ENCRYPT_WRAP;
|
||||
}
|
||||
if (flags & Context::WantAddress) {
|
||||
result |= GPGME_ENCRYPT_WANT_ADDRESS;
|
||||
}
|
||||
if (flags & Context::EncryptArchive) {
|
||||
result |= GPGME_ENCRYPT_ARCHIVE;
|
||||
}
|
||||
if (flags & Context::EncryptFile) {
|
||||
result |= GPGME_ENCRYPT_FILE;
|
||||
}
|
||||
return static_cast<gpgme_encrypt_flags_t>(result);
|
||||
}
|
||||
|
||||
@ -1507,11 +1320,6 @@ Error Context::cancelPendingOperation()
|
||||
return Error(gpgme_cancel_async(d->ctx));
|
||||
}
|
||||
|
||||
Error Context::cancelPendingOperationImmediately()
|
||||
{
|
||||
return Error(gpgme_cancel(d->ctx));
|
||||
}
|
||||
|
||||
bool Context::poll()
|
||||
{
|
||||
gpgme_error_t e = GPG_ERR_NO_ERROR;
|
||||
@ -1678,16 +1486,6 @@ Error Context::startRevUid(const Key &k, const char *userid)
|
||||
k.impl(), userid, 0));
|
||||
}
|
||||
|
||||
Error Context::setPrimaryUid(const Key &k, const char *userid)
|
||||
{
|
||||
return Error(d->lasterr = gpgme_op_set_uid_flag(d->ctx, k.impl(), userid, "primary", nullptr));
|
||||
}
|
||||
|
||||
Error Context::startSetPrimaryUid(const Key &k, const char *userid)
|
||||
{
|
||||
return Error(d->lasterr = gpgme_op_set_uid_flag_start(d->ctx, k.impl(), userid, "primary", nullptr));
|
||||
}
|
||||
|
||||
Error Context::createSubkey(const Key &k, const char *algo,
|
||||
unsigned long reserved,
|
||||
unsigned long expires,
|
||||
@ -1706,112 +1504,6 @@ Error Context::startCreateSubkey(const Key &k, const char *algo,
|
||||
k.impl(), algo, reserved, expires, flags));
|
||||
}
|
||||
|
||||
static std::string getLFSeparatedListOfStrings(const std::vector<std::string> &strings)
|
||||
{
|
||||
if (strings.empty()) {
|
||||
return std::string();
|
||||
}
|
||||
|
||||
return std::accumulate(
|
||||
std::next(strings.begin()),
|
||||
strings.end(),
|
||||
strings[0],
|
||||
[](const std::string &a, const std::string &b) {
|
||||
return a + '\n' + b;
|
||||
}
|
||||
);
|
||||
}
|
||||
|
||||
static std::string getLFSeparatedListOfFingerprintsFromSubkeys(const std::vector<Subkey> &subkeys)
|
||||
{
|
||||
if (subkeys.empty()) {
|
||||
return std::string();
|
||||
}
|
||||
|
||||
std::vector<std::string> fprs;
|
||||
fprs.reserve(subkeys.size());
|
||||
for (auto &it : subkeys) {
|
||||
if (it.fingerprint()) {
|
||||
fprs.push_back(std::string(it.fingerprint()));
|
||||
}
|
||||
}
|
||||
|
||||
return getLFSeparatedListOfStrings(fprs);
|
||||
}
|
||||
|
||||
Error Context::setExpire(const Key &k, unsigned long expires,
|
||||
const std::vector<Subkey> &subkeys,
|
||||
const Context::SetExpireFlags flags)
|
||||
{
|
||||
std::string subfprs;
|
||||
if (flags & Context::SetExpireAllSubkeys) {
|
||||
subfprs = "*";
|
||||
} else {
|
||||
subfprs = getLFSeparatedListOfFingerprintsFromSubkeys(subkeys);
|
||||
}
|
||||
return Error(d->lasterr = gpgme_op_setexpire(d->ctx,
|
||||
k.impl(), expires, subfprs.c_str(), 0));
|
||||
}
|
||||
|
||||
Error Context::startSetExpire(const Key &k, unsigned long expires,
|
||||
const std::vector<Subkey> &subkeys,
|
||||
const Context::SetExpireFlags flags)
|
||||
{
|
||||
std::string subfprs;
|
||||
if (flags & Context::SetExpireAllSubkeys) {
|
||||
subfprs = "*";
|
||||
} else {
|
||||
subfprs = getLFSeparatedListOfFingerprintsFromSubkeys(subkeys);
|
||||
}
|
||||
return Error(d->lasterr = gpgme_op_setexpire_start(d->ctx,
|
||||
k.impl(), expires, subfprs.c_str(), 0));
|
||||
}
|
||||
|
||||
static std::string getLFSeparatedListOfUserIds(const std::vector<UserID> &userIds)
|
||||
{
|
||||
if (userIds.empty()) {
|
||||
return std::string();
|
||||
}
|
||||
|
||||
std::vector<std::string> uids;
|
||||
uids.reserve(userIds.size());
|
||||
for (auto &userId : userIds) {
|
||||
if (userId.id()) {
|
||||
uids.push_back(std::string(userId.id()));
|
||||
}
|
||||
}
|
||||
|
||||
return getLFSeparatedListOfStrings(uids);
|
||||
}
|
||||
|
||||
Error Context::revokeSignature(const Key &key, const Key &signingKey,
|
||||
const std::vector<UserID> &userIds)
|
||||
{
|
||||
const unsigned int flags = userIds.size() > 1 ? GPGME_REVSIG_LFSEP : 0;
|
||||
const std::string uids = getLFSeparatedListOfUserIds(userIds);
|
||||
return Error(d->lasterr = gpgme_op_revsig(d->ctx,
|
||||
key.impl(), signingKey.impl(), uids.c_str(), flags));
|
||||
}
|
||||
|
||||
Error Context::startRevokeSignature(const Key &key, const Key &signingKey,
|
||||
const std::vector<UserID> &userIds)
|
||||
{
|
||||
const unsigned int flags = userIds.size() > 1 ? GPGME_REVSIG_LFSEP : 0;
|
||||
const std::string uids = getLFSeparatedListOfUserIds(userIds);
|
||||
return Error(d->lasterr = gpgme_op_revsig_start(d->ctx,
|
||||
key.impl(), signingKey.impl(), uids.c_str(), flags));
|
||||
}
|
||||
|
||||
Error Context::addAdsk(const Key &k, const char *adsk)
|
||||
{
|
||||
return Error(d->lasterr = gpgme_op_createsubkey(d->ctx, k.impl(), adsk, 0, 0, GPGME_CREATE_ADSK));
|
||||
}
|
||||
|
||||
Error Context::startAddAdsk(const Key &k, const char *adsk)
|
||||
{
|
||||
return Error(d->lasterr = gpgme_op_createsubkey_start(d->ctx, k.impl(), adsk, 0, 0, GPGME_CREATE_ADSK));
|
||||
}
|
||||
|
||||
Error Context::setFlag(const char *name, const char *value)
|
||||
{
|
||||
return Error(d->lasterr = gpgme_set_ctx_flag(d->ctx, name, value));
|
||||
@ -1923,9 +1615,6 @@ std::ostream &operator<<(std::ostream &os, KeyListMode mode)
|
||||
CHECK(Validate);
|
||||
CHECK(Ephemeral);
|
||||
CHECK(WithTofu);
|
||||
CHECK(WithKeygrip);
|
||||
CHECK(WithSecret);
|
||||
CHECK(ForceExtern);
|
||||
#undef CHECK
|
||||
return os << ')';
|
||||
}
|
||||
@ -1933,8 +1622,7 @@ std::ostream &operator<<(std::ostream &os, KeyListMode mode)
|
||||
std::ostream &operator<<(std::ostream &os, SignatureMode mode)
|
||||
{
|
||||
os << "GpgME::SignatureMode(";
|
||||
#undef CHECK
|
||||
switch (mode & (NormalSignatureMode|Detached|Clearsigned)) {
|
||||
switch (mode) {
|
||||
#define CHECK( x ) case x: os << #x; break
|
||||
CHECK(NormalSignatureMode);
|
||||
CHECK(Detached);
|
||||
@ -1944,10 +1632,6 @@ std::ostream &operator<<(std::ostream &os, SignatureMode mode)
|
||||
os << "???" "(" << static_cast<int>(mode) << ')';
|
||||
break;
|
||||
}
|
||||
#define CHECK( x ) if ( !(mode & (x)) ) {} else do { os << #x " "; } while (0)
|
||||
CHECK(SignArchive);
|
||||
CHECK(SignFile);
|
||||
#undef CHECK
|
||||
return os << ')';
|
||||
}
|
||||
|
||||
@ -1961,11 +1645,6 @@ std::ostream &operator<<(std::ostream &os, Context::EncryptionFlags flags)
|
||||
CHECK(ExpectSign);
|
||||
CHECK(NoCompress);
|
||||
CHECK(Symmetric);
|
||||
CHECK(ThrowKeyIds);
|
||||
CHECK(EncryptWrap);
|
||||
CHECK(WantAddress);
|
||||
CHECK(EncryptArchive);
|
||||
CHECK(EncryptFile);
|
||||
#undef CHECK
|
||||
return os << ')';
|
||||
}
|
||||
@ -1989,7 +1668,20 @@ GpgME::Error GpgME::setDefaultLocale(int cat, const char *val)
|
||||
|
||||
GpgME::EngineInfo GpgME::engineInfo(GpgME::Protocol proto)
|
||||
{
|
||||
return get_static_engine_info(proto == CMS ? GPGME_PROTOCOL_CMS : GPGME_PROTOCOL_OpenPGP);
|
||||
gpgme_engine_info_t ei = nullptr;
|
||||
if (gpgme_get_engine_info(&ei)) {
|
||||
return EngineInfo();
|
||||
}
|
||||
|
||||
const gpgme_protocol_t p = proto == CMS ? GPGME_PROTOCOL_CMS : GPGME_PROTOCOL_OpenPGP ;
|
||||
|
||||
for (gpgme_engine_info_t i = ei ; i ; i = i->next) {
|
||||
if (i->protocol == p) {
|
||||
return EngineInfo(i);
|
||||
}
|
||||
}
|
||||
|
||||
return EngineInfo();
|
||||
}
|
||||
|
||||
const char *GpgME::dirInfo(const char *what)
|
||||
@ -2027,7 +1719,20 @@ static gpgme_protocol_t engine2protocol(const GpgME::Engine engine)
|
||||
|
||||
GpgME::EngineInfo GpgME::engineInfo(GpgME::Engine engine)
|
||||
{
|
||||
return get_static_engine_info(engine2protocol(engine));
|
||||
gpgme_engine_info_t ei = nullptr;
|
||||
if (gpgme_get_engine_info(&ei)) {
|
||||
return EngineInfo();
|
||||
}
|
||||
|
||||
const gpgme_protocol_t p = engine2protocol(engine);
|
||||
|
||||
for (gpgme_engine_info_t i = ei ; i ; i = i->next) {
|
||||
if (i->protocol == p) {
|
||||
return EngineInfo(i);
|
||||
}
|
||||
}
|
||||
|
||||
return EngineInfo();
|
||||
}
|
||||
|
||||
GpgME::Error GpgME::checkEngine(GpgME::Engine engine)
|
||||
@ -2086,8 +1791,3 @@ bool GpgME::hasFeature(unsigned long features, unsigned long features2)
|
||||
&& features2 == (features2 & supported_features2)
|
||||
;
|
||||
}
|
||||
|
||||
int GpgME::setGlobalFlag(const char *name, const char *value)
|
||||
{
|
||||
return gpgme_set_global_flag(name, value);
|
||||
}
|
||||
|
@ -27,11 +27,9 @@
|
||||
#include "global.h"
|
||||
|
||||
#include "error.h"
|
||||
#include "key.h"
|
||||
#include "verificationresult.h" // for Signature::Notation
|
||||
|
||||
#include <memory>
|
||||
#include <string>
|
||||
#include <vector>
|
||||
#include <utility>
|
||||
#include <iosfwd>
|
||||
@ -39,6 +37,7 @@
|
||||
namespace GpgME
|
||||
{
|
||||
|
||||
class Key;
|
||||
class Data;
|
||||
class TrustItem;
|
||||
class ProgressProvider;
|
||||
@ -64,17 +63,6 @@ class GPGMEPP_EXPORT Context
|
||||
public:
|
||||
//using GpgME::Protocol;
|
||||
|
||||
/// RAII-style class for saving/restoring the key list mode.
|
||||
class GPGMEPP_EXPORT KeyListModeSaver
|
||||
{
|
||||
public:
|
||||
explicit KeyListModeSaver(Context *ctx);
|
||||
~KeyListModeSaver();
|
||||
private:
|
||||
Context *mCtx;
|
||||
unsigned int mKeyListMode;
|
||||
};
|
||||
|
||||
//
|
||||
// Creation and destruction:
|
||||
//
|
||||
@ -194,42 +182,11 @@ public:
|
||||
//
|
||||
// Key Export
|
||||
//
|
||||
enum ExportMode {
|
||||
ExportDefault = 0,
|
||||
ExportExtern = 2,
|
||||
ExportMinimal = 4,
|
||||
ExportSecret = 16,
|
||||
ExportRaw = 32,
|
||||
ExportPKCS12 = 64,
|
||||
ExportNoUID = 128, // obsolete; has no effect
|
||||
ExportSSH = 256,
|
||||
ExportSecretSubkey = 512,
|
||||
};
|
||||
|
||||
GpgME::Error exportPublicKeys(const char *pattern, Data &keyData);
|
||||
GpgME::Error exportPublicKeys(const char *pattern, Data &keyData, unsigned int mode);
|
||||
GpgME::Error exportPublicKeys(const char *pattern[], Data &keyData);
|
||||
GpgME::Error exportPublicKeys(const char *pattern[], Data &keyData, unsigned int mode);
|
||||
GpgME::Error startPublicKeyExport(const char *pattern, Data &keyData);
|
||||
GpgME::Error startPublicKeyExport(const char *pattern, Data &keyData, unsigned int mode);
|
||||
GpgME::Error startPublicKeyExport(const char *pattern[], Data &keyData);
|
||||
GpgME::Error startPublicKeyExport(const char *pattern[], Data &keyData, unsigned int mode);
|
||||
|
||||
GpgME::Error exportSecretKeys(const char *pattern, Data &keyData, unsigned int mode = ExportSecret);
|
||||
GpgME::Error exportSecretKeys(const char *pattern[], Data &keyData, unsigned int mode = ExportSecret);
|
||||
GpgME::Error startSecretKeyExport(const char *pattern, Data &keyData, unsigned int mode = ExportSecret);
|
||||
GpgME::Error startSecretKeyExport(const char *pattern[], Data &keyData, unsigned int mode = ExportSecret);
|
||||
|
||||
GpgME::Error exportSecretSubkeys(const char *pattern, Data &keyData, unsigned int mode = ExportSecretSubkey);
|
||||
GpgME::Error exportSecretSubkeys(const char *pattern[], Data &keyData, unsigned int mode = ExportSecretSubkey);
|
||||
GpgME::Error startSecretSubkeyExport(const char *pattern, Data &keyData, unsigned int mode = ExportSecretSubkey);
|
||||
GpgME::Error startSecretSubkeyExport(const char *pattern[], Data &keyData, unsigned int mode = ExportSecretSubkey);
|
||||
|
||||
// generic export functions; prefer using the specific public/secret key export functions
|
||||
GpgME::Error exportKeys(const char *pattern, Data &keyData, unsigned int mode = ExportDefault);
|
||||
GpgME::Error exportKeys(const char *pattern[], Data &keyData, unsigned int mode = ExportDefault);
|
||||
GpgME::Error startKeyExport(const char *pattern, Data &keyData, unsigned int mode = ExportDefault);
|
||||
GpgME::Error startKeyExport(const char *pattern[], Data &keyData, unsigned int mode = ExportDefault);
|
||||
|
||||
//
|
||||
// Key Import
|
||||
@ -237,10 +194,8 @@ public:
|
||||
|
||||
ImportResult importKeys(const Data &data);
|
||||
ImportResult importKeys(const std::vector<Key> &keys);
|
||||
ImportResult importKeys(const std::vector<std::string> &keyIds);
|
||||
GpgME::Error startKeyImport(const Data &data);
|
||||
GpgME::Error startKeyImport(const std::vector<Key> &keys);
|
||||
GpgME::Error startKeyImport(const std::vector<std::string> &keyIds);
|
||||
ImportResult importResult() const;
|
||||
|
||||
//
|
||||
@ -295,9 +250,6 @@ public:
|
||||
Error revUid(const Key &key, const char *userid);
|
||||
Error startRevUid(const Key &key, const char *userid);
|
||||
|
||||
Error setPrimaryUid(const Key &key, const char *userid);
|
||||
Error startSetPrimaryUid(const Key &key, const char *userid);
|
||||
|
||||
Error createSubkey(const Key &key, const char *algo,
|
||||
unsigned long reserved = 0,
|
||||
unsigned long expires = 0,
|
||||
@ -307,26 +259,6 @@ public:
|
||||
unsigned long expires = 0,
|
||||
unsigned int flags = 0);
|
||||
|
||||
enum SetExpireFlags {
|
||||
SetExpireDefault = 0,
|
||||
SetExpireAllSubkeys = 1
|
||||
};
|
||||
|
||||
Error setExpire(const Key &k, unsigned long expires,
|
||||
const std::vector<Subkey> &subkeys = std::vector<Subkey>(),
|
||||
const SetExpireFlags flags = SetExpireDefault);
|
||||
Error startSetExpire(const Key &k, unsigned long expires,
|
||||
const std::vector<Subkey> &subkeys = std::vector<Subkey>(),
|
||||
const SetExpireFlags flags = SetExpireDefault);
|
||||
|
||||
Error revokeSignature(const Key &key, const Key &signingKey,
|
||||
const std::vector<UserID> &userIds = std::vector<UserID>());
|
||||
Error startRevokeSignature(const Key &key, const Key &signingKey,
|
||||
const std::vector<UserID> &userIds = std::vector<UserID>());
|
||||
|
||||
Error addAdsk(const Key &k, const char *adsk);
|
||||
Error startAddAdsk(const Key &k, const char *adsk);
|
||||
|
||||
// using TofuInfo::Policy
|
||||
Error setTofuPolicy(const Key &k, unsigned int policy);
|
||||
Error setTofuPolicyStart(const Key &k, unsigned int policy);
|
||||
@ -373,7 +305,6 @@ public:
|
||||
// Keep in line with core's flags
|
||||
DecryptNone = 0,
|
||||
DecryptVerify = 1,
|
||||
DecryptArchive = 2,
|
||||
DecryptUnwrap = 128,
|
||||
DecryptMaxValue = 0x80000000
|
||||
};
|
||||
@ -451,10 +382,7 @@ public:
|
||||
NoCompress = 16,
|
||||
Symmetric = 32,
|
||||
ThrowKeyIds = 64,
|
||||
EncryptWrap = 128,
|
||||
WantAddress = 256,
|
||||
EncryptArchive = 512,
|
||||
EncryptFile = 1024
|
||||
EncryptWrap = 128
|
||||
};
|
||||
EncryptionResult encrypt(const std::vector<Key> &recipients, const Data &plainText, Data &cipherText, EncryptionFlags flags);
|
||||
GpgME::Error encryptSymmetrically(const Data &plainText, Data &cipherText);
|
||||
@ -530,7 +458,6 @@ public:
|
||||
GpgME::Error wait();
|
||||
GpgME::Error lastError() const;
|
||||
GpgME::Error cancelPendingOperation();
|
||||
GpgME::Error cancelPendingOperationImmediately();
|
||||
|
||||
class Private;
|
||||
const Private *impl() const
|
||||
|
@ -1,7 +1,8 @@
|
||||
/*
|
||||
statusconsumer.h - Interface for status callbacks
|
||||
Copyright (c) 2020 g10 Code GmbH
|
||||
Software engineering by Ingo Klöcker <dev@ingo-kloecker.de>
|
||||
context_glib.cpp - wraps a gpgme key context, gpgme-glib-specific functions
|
||||
Copyright (C) 2007 Klarälvdalens Datakonsult AB
|
||||
2016 Bundesamt für Sicherheit in der Informationstechnik
|
||||
Software engineering by Intevation GmbH
|
||||
|
||||
This file is part of GPGME++.
|
||||
|
||||
@ -21,22 +22,20 @@
|
||||
Boston, MA 02110-1301, USA.
|
||||
*/
|
||||
|
||||
#ifndef __GPGMEPP_INTERFACES_STATUSCONSUMER_H__
|
||||
#define __GPGMEPP_INTERFACES_STATUSCONSUMER_H__
|
||||
#ifdef HAVE_CONFIG_H
|
||||
#include "config.h"
|
||||
#endif
|
||||
|
||||
#include "../gpgmepp_export.h"
|
||||
#include <global.h>
|
||||
|
||||
namespace GpgME
|
||||
extern "C" GIOChannel *gpgme_get_fdptr(int);
|
||||
|
||||
GIOChannel *GpgME::getGIOChannel(int fd)
|
||||
{
|
||||
return gpgme_get_fdptr(fd);
|
||||
}
|
||||
|
||||
class GPGMEPP_EXPORT StatusConsumer
|
||||
QIODevice *GpgME::getQIODevice(int fd)
|
||||
{
|
||||
public:
|
||||
virtual ~StatusConsumer() {}
|
||||
|
||||
virtual void status(const char *status, const char *details) = 0;
|
||||
};
|
||||
|
||||
} // namespace GpgME
|
||||
|
||||
#endif // __GPGMEPP_INTERFACES_STATUSCONSUMER_H__
|
||||
return 0;
|
||||
}
|
@ -53,7 +53,6 @@ public:
|
||||
|
||||
KeyGen = 0x080,
|
||||
KeyList = 0x100,
|
||||
KeyListWithImport = KeyList | Import, // gpgme_keylist_result_t and gpgme_import_result_t
|
||||
TrustList = 0x200, // no gpgme_trustlist_result_t, but nevertheless...
|
||||
|
||||
Edit = 0x400, // no gpgme_edit_result_t, but nevertheless...
|
||||
|
@ -1,7 +1,8 @@
|
||||
/*
|
||||
util.cpp - some internal helpers
|
||||
Copyright (c) 2022 g10 Code GmbH
|
||||
Software engineering by Ingo Klöcker <dev@ingo-kloecker.de>
|
||||
context_qt.cpp - wraps a gpgme key context, gpgme-qt-specific functions
|
||||
Copyright (C) 2007 Klarälvdalens Datakonsult AB
|
||||
2016 Bundesamt für Sicherheit in der Informationstechnik
|
||||
Software engineering by Intevation GmbH
|
||||
|
||||
This file is part of GPGME++.
|
||||
|
||||
@ -25,23 +26,16 @@
|
||||
#include "config.h"
|
||||
#endif
|
||||
|
||||
#include "util.h"
|
||||
#include <global.h>
|
||||
|
||||
#include <functional>
|
||||
extern "C" QIODevice *gpgme_get_fdptr(int);
|
||||
|
||||
StringsToCStrings::StringsToCStrings(const std::vector<std::string>& v)
|
||||
: m_strings{v}
|
||||
GIOChannel *GpgME::getGIOChannel(int)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
const char **StringsToCStrings::c_strs() const
|
||||
QIODevice *GpgME::getQIODevice(int fd)
|
||||
{
|
||||
if (m_cstrings.empty()) {
|
||||
m_cstrings.reserve(m_strings.size() + 1);
|
||||
std::transform(std::begin(m_strings), std::end(m_strings),
|
||||
std::back_inserter(m_cstrings),
|
||||
std::mem_fn(&std::string::c_str));
|
||||
m_cstrings.push_back(nullptr);
|
||||
}
|
||||
return m_cstrings.data();
|
||||
return gpgme_get_fdptr(fd);
|
||||
}
|
@ -217,11 +217,6 @@ GpgME::Error GpgME::Data::setFileName(const char *name)
|
||||
return Error(gpgme_data_set_file_name(d->data, name));
|
||||
}
|
||||
|
||||
GpgME::Error GpgME::Data::setFileName(const std::string &name)
|
||||
{
|
||||
return Error(gpgme_data_set_file_name(d->data, name.c_str()));
|
||||
}
|
||||
|
||||
ssize_t GpgME::Data::read(void *buffer, size_t length)
|
||||
{
|
||||
return gpgme_data_read(d->data, buffer, length);
|
||||
@ -261,8 +256,6 @@ std::vector<GpgME::Key> GpgME::Data::toKeys(Protocol proto) const
|
||||
while (!gpgme_op_keylist_next (ctx->impl()->ctx, &key)) {
|
||||
ret.push_back(GpgME::Key(key, false));
|
||||
}
|
||||
gpgme_data_seek (d->data, 0, SEEK_SET);
|
||||
|
||||
delete ctx;
|
||||
return ret;
|
||||
}
|
||||
@ -280,14 +273,3 @@ std::string GpgME::Data::toString()
|
||||
seek (0, SEEK_SET);
|
||||
return ret;
|
||||
}
|
||||
|
||||
GpgME::Error GpgME::Data::setFlag(const char *name, const char *value)
|
||||
{
|
||||
return Error(gpgme_data_set_flag(d->data, name, value));
|
||||
}
|
||||
|
||||
GpgME::Error GpgME::Data::setSizeHint(uint64_t size)
|
||||
{
|
||||
const std::string val = std::to_string(size);
|
||||
return Error(gpgme_data_set_flag(d->data, "size-hint", val.c_str()));
|
||||
}
|
||||
|
@ -27,7 +27,6 @@
|
||||
#include "key.h"
|
||||
|
||||
#include <sys/types.h> // for size_t, off_t
|
||||
#include <cstdint> // unit64_t
|
||||
#include <cstdio> // FILE
|
||||
#include <algorithm>
|
||||
#include <memory>
|
||||
@ -61,7 +60,6 @@ public:
|
||||
|
||||
static const Null null;
|
||||
|
||||
Data(const Data &other) = default;
|
||||
const Data &operator=(Data other)
|
||||
{
|
||||
swap(other);
|
||||
@ -107,7 +105,6 @@ public:
|
||||
|
||||
char *fileName() const;
|
||||
Error setFileName(const char *name);
|
||||
Error setFileName(const std::string &name);
|
||||
|
||||
ssize_t read(void *buffer, size_t length);
|
||||
ssize_t write(const void *buffer, size_t length);
|
||||
@ -123,12 +120,6 @@ public:
|
||||
/** Return a copy of the data as std::string. Sets seek pos to 0 */
|
||||
std::string toString();
|
||||
|
||||
/** See gpgme_data_set_flag */
|
||||
Error setFlag(const char *name, const char *value);
|
||||
|
||||
/** Set a size hint for this data e.g. for progress calculations. */
|
||||
Error setSizeHint(uint64_t size);
|
||||
|
||||
class Private;
|
||||
Private *impl()
|
||||
{
|
||||
|
@ -122,11 +122,6 @@ bool GpgME::DecryptionResult::isDeVs() const
|
||||
return d && d->res.is_de_vs;
|
||||
}
|
||||
|
||||
bool GpgME::DecryptionResult::isMime() const
|
||||
{
|
||||
return d && d->res.is_mime;
|
||||
}
|
||||
|
||||
const char *GpgME::DecryptionResult::fileName() const
|
||||
{
|
||||
return d ? d->res.file_name : nullptr ;
|
||||
|
@ -47,7 +47,6 @@ public:
|
||||
DecryptionResult(gpgme_ctx_t ctx, const Error &err);
|
||||
explicit DecryptionResult(const Error &err);
|
||||
|
||||
DecryptionResult(const DecryptionResult &other) = default;
|
||||
const DecryptionResult &operator=(DecryptionResult other)
|
||||
{
|
||||
swap(other);
|
||||
@ -75,7 +74,6 @@ public:
|
||||
}
|
||||
bool isWrongKeyUsage() const;
|
||||
bool isDeVs() const;
|
||||
bool isMime() const;
|
||||
|
||||
const char *fileName() const;
|
||||
|
||||
@ -105,7 +103,6 @@ public:
|
||||
Recipient();
|
||||
explicit Recipient(gpgme_recipient_t reci);
|
||||
|
||||
Recipient(const Recipient &other) = default;
|
||||
const Recipient &operator=(Recipient other)
|
||||
{
|
||||
swap(other);
|
||||
|
@ -30,6 +30,8 @@
|
||||
#include "error.h"
|
||||
#include "data.h"
|
||||
|
||||
#include <sstream>
|
||||
|
||||
using namespace GpgME;
|
||||
|
||||
DefaultAssuanTransaction::DefaultAssuanTransaction()
|
||||
|
@ -25,7 +25,7 @@
|
||||
#ifndef __GPGMEPP_DEFAULTASSUANTRANSACTION_H__
|
||||
#define __GPGMEPP_DEFAULTASSUANTRANSACTION_H__
|
||||
|
||||
#include "interfaces/assuantransaction.h"
|
||||
#include <interfaces/assuantransaction.h>
|
||||
|
||||
#include <string>
|
||||
#include <vector>
|
||||
|
@ -29,7 +29,6 @@
|
||||
#include "editinteractor.h"
|
||||
#include "callbacks.h"
|
||||
#include "error.h"
|
||||
#include "util.h"
|
||||
|
||||
#include <gpgme.h>
|
||||
|
||||
@ -42,7 +41,6 @@
|
||||
|
||||
#include <cerrno>
|
||||
#include <cstring>
|
||||
#include <cstdlib>
|
||||
|
||||
#ifndef GPG_ERR_ALREADY_SIGNED
|
||||
# define GPG_ERR_ALREADY_SIGNED GPG_ERR_USER_1
|
||||
@ -52,7 +50,6 @@ using namespace GpgME;
|
||||
|
||||
static const char *status_to_string(unsigned int status);
|
||||
static Error status_to_error(unsigned int status);
|
||||
static Error parse_sc_op_failure(const char *args);
|
||||
|
||||
class EditInteractor::Private
|
||||
{
|
||||
@ -64,10 +61,9 @@ public:
|
||||
~Private();
|
||||
|
||||
private:
|
||||
unsigned int state = StartState;
|
||||
unsigned int state;
|
||||
Error error;
|
||||
std::FILE *debug = nullptr;
|
||||
bool debugNeedsClosing = false;
|
||||
std::FILE *debug;
|
||||
};
|
||||
|
||||
class GpgME::CallbackHelper
|
||||
@ -97,24 +93,12 @@ public:
|
||||
|
||||
// advance to next state based on input:
|
||||
const unsigned int oldState = ei->state;
|
||||
|
||||
if (ei->q->needsNoResponse(status)) {
|
||||
// keep state
|
||||
} else if (status == GPGME_STATUS_ERROR) {
|
||||
err = ei->q->parseStatusError(args);
|
||||
ei->state = EditInteractor::ErrorState;
|
||||
} else if (status == GPGME_STATUS_SC_OP_FAILURE) {
|
||||
err = parse_sc_op_failure(args);
|
||||
ei->state = EditInteractor::ErrorState;
|
||||
} else {
|
||||
ei->state = ei->q->nextState(status, args, err);
|
||||
}
|
||||
|
||||
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 || err.isCanceled()) {
|
||||
if (err) {
|
||||
ei->state = oldState;
|
||||
goto error;
|
||||
}
|
||||
@ -138,7 +122,7 @@ public:
|
||||
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.asStdString().c_str());
|
||||
std::fprintf(ei->debug, "EditInteractor: Could not write to fd %d (%s)\n", fd, err.asString());
|
||||
}
|
||||
goto error;
|
||||
}
|
||||
@ -147,7 +131,7 @@ public:
|
||||
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.asStdString().c_str());
|
||||
std::fprintf(ei->debug, "EditInteractor: Could not write to fd %d (%s)\n", fd, err.asString());
|
||||
}
|
||||
goto error;
|
||||
}
|
||||
@ -167,7 +151,7 @@ public:
|
||||
}
|
||||
|
||||
error:
|
||||
if (err || err.isCanceled()) {
|
||||
if (err) {
|
||||
ei->error = err;
|
||||
ei->state = EditInteractor::ErrorState;
|
||||
}
|
||||
@ -189,28 +173,15 @@ static gpgme_error_t edit_interactor_callback(void *opaque, gpgme_status_code_t
|
||||
const gpgme_edit_cb_t GpgME::edit_interactor_callback = ::edit_interactor_callback;
|
||||
|
||||
EditInteractor::Private::Private(EditInteractor *qq)
|
||||
: q(qq)
|
||||
: q(qq),
|
||||
state(StartState),
|
||||
error(),
|
||||
debug(nullptr)
|
||||
{
|
||||
const char *debug_env = std::getenv("GPGMEPP_INTERACTOR_DEBUG");
|
||||
if (!debug_env) {
|
||||
return;
|
||||
}
|
||||
if (!strcmp(debug_env, "stdout")) {
|
||||
debug = stdout;
|
||||
} else if (!strcmp(debug_env, "stderr")) {
|
||||
debug = stderr;
|
||||
} else if (debug_env) {
|
||||
debug = std::fopen(debug_env, "a+");
|
||||
debugNeedsClosing = true;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
EditInteractor::Private::~Private()
|
||||
{
|
||||
if (debug && debugNeedsClosing) {
|
||||
std::fclose(debug);
|
||||
}
|
||||
}
|
||||
EditInteractor::Private::~Private() {}
|
||||
|
||||
EditInteractor::EditInteractor()
|
||||
: d(new Private(this))
|
||||
@ -270,52 +241,6 @@ void EditInteractor::setDebugChannel(std::FILE *debug)
|
||||
d->debug = debug;
|
||||
}
|
||||
|
||||
GpgME::Error EditInteractor::parseStatusError(const char *args)
|
||||
{
|
||||
Error err;
|
||||
|
||||
const auto fields = split(args, ' ');
|
||||
if (fields.size() >= 2) {
|
||||
err = Error{static_cast<unsigned int>(std::stoul(fields[1]))};
|
||||
} else {
|
||||
err = Error::fromCode(GPG_ERR_GENERAL);
|
||||
}
|
||||
|
||||
return err;
|
||||
}
|
||||
|
||||
static Error sc_op_failure_to_error(unsigned int status)
|
||||
{
|
||||
switch (status) {
|
||||
case 1:
|
||||
// GPG_ERR_CANCELED or GPG_ERR_FULLY_CANCELED
|
||||
return Error::fromCode(GPG_ERR_CANCELED);
|
||||
case 2:
|
||||
// GPG_ERR_BAD_PIN or GPG_ERR_BAD_RESET_CODE [sic]
|
||||
return Error::fromCode(GPG_ERR_BAD_PIN);
|
||||
case 3:
|
||||
return Error::fromCode(GPG_ERR_PIN_BLOCKED);
|
||||
case 4:
|
||||
return Error::fromCode(GPG_ERR_NO_RESET_CODE);
|
||||
}
|
||||
return Error::fromCode(GPG_ERR_CARD);
|
||||
}
|
||||
|
||||
// static
|
||||
Error parse_sc_op_failure(const char *args)
|
||||
{
|
||||
Error err;
|
||||
|
||||
const auto fields = split(args, ' ');
|
||||
if (fields.size() >= 1) {
|
||||
err = sc_op_failure_to_error(static_cast<unsigned int>(std::stoul(fields[0])));
|
||||
} else {
|
||||
err = Error::fromCode(GPG_ERR_CARD);
|
||||
}
|
||||
|
||||
return err;
|
||||
}
|
||||
|
||||
static const char *const status_strings[] = {
|
||||
"EOF",
|
||||
/* mkstatus processing starts here */
|
||||
|
@ -60,9 +60,6 @@ public:
|
||||
|
||||
void setDebugChannel(std::FILE *file);
|
||||
|
||||
protected:
|
||||
Error parseStatusError(const char *args);
|
||||
|
||||
private:
|
||||
class Private;
|
||||
Private *const d;
|
||||
|
@ -48,7 +48,6 @@ public:
|
||||
EncryptionResult(gpgme_ctx_t ctx, const Error &error);
|
||||
EncryptionResult(const Error &err);
|
||||
|
||||
EncryptionResult(const EncryptionResult &other) = default;
|
||||
const EncryptionResult &operator=(EncryptionResult other)
|
||||
{
|
||||
swap(other);
|
||||
@ -84,7 +83,6 @@ class GPGMEPP_EXPORT InvalidRecipient
|
||||
public:
|
||||
InvalidRecipient();
|
||||
|
||||
InvalidRecipient(const InvalidRecipient &other) = default;
|
||||
const InvalidRecipient &operator=(InvalidRecipient other)
|
||||
{
|
||||
swap(other);
|
||||
|
@ -69,76 +69,6 @@ public:
|
||||
}
|
||||
}
|
||||
|
||||
bool operator < (const Version& other) const
|
||||
{
|
||||
if (major > other.major ||
|
||||
(major == other.major && minor > other.minor) ||
|
||||
(major == other.major && minor == other.minor && patch > other.patch) ||
|
||||
(major >= other.major && minor >= other.minor && patch >= other.patch)) {
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
bool operator < (const char* other) const
|
||||
{
|
||||
return operator<(Version(other));
|
||||
}
|
||||
|
||||
bool operator <= (const Version &other) const
|
||||
{
|
||||
return !operator>(other);
|
||||
}
|
||||
|
||||
bool operator <= (const char *other) const
|
||||
{
|
||||
return operator<=(Version(other));
|
||||
}
|
||||
|
||||
bool operator > (const char* other) const
|
||||
{
|
||||
return operator>(Version(other));
|
||||
}
|
||||
|
||||
bool operator > (const Version & other) const
|
||||
{
|
||||
return !operator<(other) && !operator==(other);
|
||||
}
|
||||
|
||||
bool operator >= (const Version &other) const
|
||||
{
|
||||
return !operator<(other);
|
||||
}
|
||||
|
||||
bool operator >= (const char *other) const
|
||||
{
|
||||
return operator>=(Version(other));
|
||||
}
|
||||
|
||||
bool operator == (const Version& other) const
|
||||
{
|
||||
return major == other.major
|
||||
&& minor == other.minor
|
||||
&& patch == other.patch;
|
||||
}
|
||||
|
||||
bool operator == (const char* other) const
|
||||
{
|
||||
return operator==(Version(other));
|
||||
}
|
||||
|
||||
bool operator != (const Version &other) const
|
||||
{
|
||||
return !operator==(other);
|
||||
}
|
||||
|
||||
bool operator != (const char *other) const
|
||||
{
|
||||
return operator!=(Version(other));
|
||||
}
|
||||
|
||||
// the non-const overloads of the comparison operators are kept for
|
||||
// binary compatibility
|
||||
bool operator < (const Version& other)
|
||||
{
|
||||
if (major > other.major ||
|
||||
@ -155,36 +85,15 @@ public:
|
||||
return operator<(Version(other));
|
||||
}
|
||||
|
||||
bool operator <= (const Version &other)
|
||||
{
|
||||
return !operator>(other);
|
||||
}
|
||||
|
||||
bool operator <= (const char *other)
|
||||
{
|
||||
return operator<=(Version(other));
|
||||
}
|
||||
|
||||
bool operator > (const char* other)
|
||||
{
|
||||
return operator>(Version(other));
|
||||
return !operator<(Version(other));
|
||||
}
|
||||
|
||||
bool operator > (const Version & other)
|
||||
{
|
||||
return !operator<(other) && !operator==(other);
|
||||
}
|
||||
|
||||
bool operator >= (const Version &other)
|
||||
{
|
||||
return !operator<(other);
|
||||
}
|
||||
|
||||
bool operator >= (const char *other)
|
||||
{
|
||||
return operator>=(Version(other));
|
||||
}
|
||||
|
||||
bool operator == (const Version& other)
|
||||
{
|
||||
return major == other.major
|
||||
@ -197,16 +106,6 @@ public:
|
||||
return operator==(Version(other));
|
||||
}
|
||||
|
||||
bool operator != (const Version &other)
|
||||
{
|
||||
return !operator==(other);
|
||||
}
|
||||
|
||||
bool operator != (const char *other)
|
||||
{
|
||||
return operator!=(Version(other));
|
||||
}
|
||||
|
||||
friend std::ostream& operator << (std::ostream& stream, const Version& ver)
|
||||
{
|
||||
stream << ver.major;
|
||||
@ -221,7 +120,6 @@ public:
|
||||
EngineInfo();
|
||||
explicit EngineInfo(gpgme_engine_info_t engine);
|
||||
|
||||
EngineInfo(const EngineInfo &other) = default;
|
||||
const EngineInfo &operator=(EngineInfo other)
|
||||
{
|
||||
swap(other);
|
||||
|
@ -47,11 +47,7 @@ public:
|
||||
explicit Error(unsigned int e) : mErr(e), mMessage() {}
|
||||
|
||||
const char *source() const;
|
||||
/* This function is deprecated. Use asStdString() instead. asString() may
|
||||
* return wrongly encoded (i.e. not UTF-8) results on Windows for the main
|
||||
* thread if the function was first called from a secondary thread. */
|
||||
GPGMEPP_DEPRECATED const char *asString() const;
|
||||
std::string asStdString() const;
|
||||
const char *asString() const;
|
||||
|
||||
int code() const;
|
||||
int sourceID() const;
|
||||
|
@ -60,34 +60,15 @@ enum Engine { GpgEngine, GpgSMEngine, GpgConfEngine, UnknownEngine, AssuanEngine
|
||||
enum KeyListMode {
|
||||
Local = 0x1,
|
||||
Extern = 0x2,
|
||||
Locate = Local|Extern,
|
||||
Locate = 0x3,
|
||||
Signatures = 0x4,
|
||||
SignatureNotations = 0x8,
|
||||
Validate = 0x10,
|
||||
Ephemeral = 0x20,
|
||||
WithTofu = 0x40,
|
||||
WithKeygrip = 0x80,
|
||||
WithSecret = 0x100,
|
||||
ForceExtern = 0x200,
|
||||
LocateExternal = Locate|ForceExtern,
|
||||
|
||||
KeyListModeMask = 0x3ff
|
||||
WithTofu = 0x40
|
||||
};
|
||||
|
||||
enum SignatureMode {
|
||||
NormalSignatureMode = 0,
|
||||
Detached = 1,
|
||||
Clearsigned = 2,
|
||||
SignArchive = 4,
|
||||
SignFile = 8,
|
||||
};
|
||||
|
||||
enum class RevocationReason {
|
||||
Unspecified = 0,
|
||||
Compromised = 1,
|
||||
Superseded = 2,
|
||||
NoLongerUsed = 3
|
||||
};
|
||||
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);
|
||||
@ -108,8 +89,7 @@ GPGMEPP_EXPORT EngineInfo engineInfo(Engine engine);
|
||||
homedir, sysconfdir, bindir, libexecdir, libdir,
|
||||
datadir, localedir, agent-socket, agent-ssh-socket,
|
||||
dirmngr-socket, uiserver-socket, gpgconf-name, gpg-name,
|
||||
gpgsm-name, g13-name, keyboxd-name, agent-name, scdaemon-name,
|
||||
dirmngr-name, pinentry-name, socketdir, gpg-wks-client-name, gpgtar-name.
|
||||
gpgsm-name, g13-name
|
||||
|
||||
This may be extended in the future.
|
||||
*/
|
||||
@ -118,9 +98,6 @@ GPGMEPP_EXPORT const char *dirInfo(const char *what);
|
||||
GPGMEPP_EXPORT Error checkEngine(Protocol proto);
|
||||
GPGMEPP_EXPORT Error checkEngine(Engine engine);
|
||||
|
||||
/* Wrapper for gpgme_set_global_flag */
|
||||
GPGMEPP_EXPORT int setGlobalFlag(const char *name, const char *value);
|
||||
|
||||
GPGMEPP_EXPORT GIOChannel *getGIOChannel(int fd);
|
||||
GPGMEPP_EXPORT QIODevice *getQIODevice(int fd);
|
||||
|
||||
|
@ -1,205 +0,0 @@
|
||||
/*
|
||||
gpgaddexistingsubkeyeditinteractor.cpp - Edit Interactor to add an existing subkey to an OpenPGP key
|
||||
Copyright (c) 2022 g10 Code GmbH
|
||||
Software engineering by Ingo Klöcker <dev@ingo-kloecker.de>
|
||||
|
||||
This file is part of GPGME++.
|
||||
|
||||
GPGME++ is free software; you can redistribute it and/or
|
||||
modify it under the terms of the GNU Library General Public
|
||||
License as published by the Free Software Foundation; either
|
||||
version 2 of the License, or (at your option) any later version.
|
||||
|
||||
GPGME++ is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU Library General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU Library General Public License
|
||||
along with GPGME++; see the file COPYING.LIB. If not, write to the
|
||||
Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
|
||||
Boston, MA 02110-1301, USA.
|
||||
*/
|
||||
|
||||
#ifdef HAVE_CONFIG_H
|
||||
#include "config.h"
|
||||
#endif
|
||||
|
||||
#include "gpgaddexistingsubkeyeditinteractor.h"
|
||||
|
||||
#include "error.h"
|
||||
|
||||
#include <gpgme.h>
|
||||
|
||||
// avoid conflict (msvc)
|
||||
#ifdef ERROR
|
||||
# undef ERROR
|
||||
#endif
|
||||
|
||||
using namespace GpgME;
|
||||
|
||||
class GpgAddExistingSubkeyEditInteractor::Private
|
||||
{
|
||||
enum {
|
||||
START = EditInteractor::StartState,
|
||||
COMMAND,
|
||||
ADD_EXISTING_KEY,
|
||||
KEYGRIP,
|
||||
FLAGS,
|
||||
VALID,
|
||||
KEY_CREATED,
|
||||
QUIT,
|
||||
SAVE,
|
||||
|
||||
ERROR = EditInteractor::ErrorState
|
||||
};
|
||||
|
||||
GpgAddExistingSubkeyEditInteractor *const q = nullptr;
|
||||
|
||||
public:
|
||||
Private(GpgAddExistingSubkeyEditInteractor *q, const std::string &keygrip)
|
||||
: q{q}
|
||||
, keygrip{keygrip}
|
||||
{
|
||||
}
|
||||
|
||||
const char *action(Error &err) const;
|
||||
unsigned int nextState(unsigned int statusCode, const char *args, Error &err) const;
|
||||
|
||||
std::string keygrip;
|
||||
std::string expiry;
|
||||
};
|
||||
|
||||
const char *GpgAddExistingSubkeyEditInteractor::Private::action(Error &err) const
|
||||
{
|
||||
switch (q->state()) {
|
||||
case COMMAND:
|
||||
return "addkey";
|
||||
case ADD_EXISTING_KEY:
|
||||
return "keygrip";
|
||||
case KEYGRIP:
|
||||
return keygrip.c_str();
|
||||
case FLAGS:
|
||||
return "Q"; // do not toggle any usage flags
|
||||
case VALID:
|
||||
return expiry.empty() ? "0" : expiry.c_str();
|
||||
case QUIT:
|
||||
return "quit";
|
||||
case SAVE:
|
||||
return "Y";
|
||||
case START:
|
||||
case KEY_CREATED:
|
||||
case ERROR:
|
||||
return nullptr;
|
||||
default:
|
||||
err = Error::fromCode(GPG_ERR_GENERAL);
|
||||
return nullptr;
|
||||
}
|
||||
}
|
||||
|
||||
unsigned int GpgAddExistingSubkeyEditInteractor::Private::nextState(unsigned int status, const char *args, Error &err) const
|
||||
{
|
||||
using std::strcmp;
|
||||
|
||||
static const Error GENERAL_ERROR = Error::fromCode(GPG_ERR_GENERAL);
|
||||
static const Error NO_KEY_ERROR = Error::fromCode(GPG_ERR_NO_KEY);
|
||||
static const Error INV_TIME_ERROR = Error::fromCode(GPG_ERR_INV_TIME);
|
||||
|
||||
switch (q->state()) {
|
||||
case START:
|
||||
if (status == GPGME_STATUS_GET_LINE &&
|
||||
strcmp(args, "keyedit.prompt") == 0) {
|
||||
return COMMAND;
|
||||
}
|
||||
err = GENERAL_ERROR;
|
||||
return ERROR;
|
||||
case COMMAND:
|
||||
if (status == GPGME_STATUS_GET_LINE &&
|
||||
strcmp(args, "keygen.algo") == 0) {
|
||||
return ADD_EXISTING_KEY;
|
||||
}
|
||||
err = GENERAL_ERROR;
|
||||
return ERROR;
|
||||
case ADD_EXISTING_KEY:
|
||||
if (status == GPGME_STATUS_GET_LINE &&
|
||||
strcmp(args, "keygen.keygrip") == 0) {
|
||||
return KEYGRIP;
|
||||
}
|
||||
err = GENERAL_ERROR;
|
||||
return ERROR;
|
||||
case KEYGRIP:
|
||||
if (status == GPGME_STATUS_GET_LINE &&
|
||||
strcmp(args, "keygen.flags") == 0) {
|
||||
return FLAGS;
|
||||
} else if (status == GPGME_STATUS_GET_LINE &&
|
||||
strcmp(args, "keygen.keygrip") == 0) {
|
||||
err = NO_KEY_ERROR;
|
||||
return ERROR;
|
||||
}
|
||||
err = GENERAL_ERROR;
|
||||
return ERROR;
|
||||
case FLAGS:
|
||||
if (status == GPGME_STATUS_GET_LINE &&
|
||||
strcmp(args, "keygen.valid") == 0) {
|
||||
return VALID;
|
||||
}
|
||||
err = GENERAL_ERROR;
|
||||
return ERROR;
|
||||
case VALID:
|
||||
if (status == GPGME_STATUS_KEY_CREATED) {
|
||||
return KEY_CREATED;
|
||||
}
|
||||
if (status == GPGME_STATUS_GET_LINE &&
|
||||
strcmp(args, "keyedit.prompt") == 0) {
|
||||
return QUIT;
|
||||
} else if (status == GPGME_STATUS_GET_LINE &&
|
||||
strcmp(args, "keygen.valid") == 0) {
|
||||
err = INV_TIME_ERROR;
|
||||
return ERROR;
|
||||
}
|
||||
err = GENERAL_ERROR;
|
||||
return ERROR;
|
||||
case KEY_CREATED:
|
||||
return QUIT;
|
||||
case QUIT:
|
||||
if (status == GPGME_STATUS_GET_BOOL &&
|
||||
strcmp(args, "keyedit.save.okay") == 0) {
|
||||
return SAVE;
|
||||
}
|
||||
err = GENERAL_ERROR;
|
||||
return ERROR;
|
||||
case ERROR:
|
||||
if (status == GPGME_STATUS_GET_LINE &&
|
||||
strcmp(args, "keyedit.prompt") == 0) {
|
||||
return QUIT;
|
||||
}
|
||||
err = q->lastError();
|
||||
return ERROR;
|
||||
default:
|
||||
err = GENERAL_ERROR;
|
||||
return ERROR;
|
||||
}
|
||||
}
|
||||
|
||||
GpgAddExistingSubkeyEditInteractor::GpgAddExistingSubkeyEditInteractor(const std::string &keygrip)
|
||||
: EditInteractor{}
|
||||
, d{new Private{this, keygrip}}
|
||||
{
|
||||
}
|
||||
|
||||
GpgAddExistingSubkeyEditInteractor::~GpgAddExistingSubkeyEditInteractor() = default;
|
||||
|
||||
void GpgAddExistingSubkeyEditInteractor::setExpiry(const std::string &timeString)
|
||||
{
|
||||
d->expiry = timeString;
|
||||
}
|
||||
|
||||
const char *GpgAddExistingSubkeyEditInteractor::action(Error &err) const
|
||||
{
|
||||
return d->action(err);
|
||||
}
|
||||
|
||||
unsigned int GpgAddExistingSubkeyEditInteractor::nextState(unsigned int status, const char *args, Error &err) const
|
||||
{
|
||||
return d->nextState(status, args, err);
|
||||
}
|
@ -1,59 +0,0 @@
|
||||
/*
|
||||
gpgaddexistingsubkeyeditinteractor.h - Edit Interactor to add an existing subkey to an OpenPGP key
|
||||
Copyright (c) 2022 g10 Code GmbH
|
||||
Software engineering by Ingo Klöcker <dev@ingo-kloecker.de>
|
||||
|
||||
This file is part of GPGME++.
|
||||
|
||||
GPGME++ is free software; you can redistribute it and/or
|
||||
modify it under the terms of the GNU Library General Public
|
||||
License as published by the Free Software Foundation; either
|
||||
version 2 of the License, or (at your option) any later version.
|
||||
|
||||
GPGME++ is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU Library General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU Library General Public License
|
||||
along with GPGME++; see the file COPYING.LIB. If not, write to the
|
||||
Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
|
||||
Boston, MA 02110-1301, USA.
|
||||
*/
|
||||
|
||||
#ifndef __GPGMEPP_GPGADDEXISTINGSUBKEYEDITINTERACTOR_H__
|
||||
#define __GPGMEPP_GPGADDEXISTINGSUBKEYEDITINTERACTOR_H__
|
||||
|
||||
#include "editinteractor.h"
|
||||
|
||||
#include <memory>
|
||||
|
||||
namespace GpgME
|
||||
{
|
||||
|
||||
class GPGMEPP_EXPORT GpgAddExistingSubkeyEditInteractor : public EditInteractor
|
||||
{
|
||||
public:
|
||||
/** Edit interactor to add the existing subkey with keygrip \a keygrip
|
||||
* to the key a key edit operation is working on.
|
||||
**/
|
||||
explicit GpgAddExistingSubkeyEditInteractor(const std::string &keygrip);
|
||||
~GpgAddExistingSubkeyEditInteractor() override;
|
||||
|
||||
/** Sets the validity period of the added subkey. Use "0" for no expiration
|
||||
* or a simplified ISO date string ("yyyymmddThhmmss") for setting an
|
||||
* expiration date. */
|
||||
void setExpiry(const std::string &timeString);
|
||||
|
||||
private:
|
||||
const char *action(Error &err) const override;
|
||||
unsigned int nextState(unsigned int statusCode, const char *args, Error &err) const override;
|
||||
|
||||
private:
|
||||
class Private;
|
||||
const std::unique_ptr<Private> d;
|
||||
};
|
||||
|
||||
} // namespace GpgME
|
||||
|
||||
#endif // __GPGMEPP_GPGADDEXISTINGSUBKEYEDITINTERACTOR_H__
|
@ -120,6 +120,10 @@ unsigned int GpgAddUserIDEditInteractor::nextState(unsigned int status, const ch
|
||||
static const Error INV_EMAIL_ERROR = Error::fromCode(GPG_ERR_INV_USER_ID);
|
||||
static const Error INV_COMMENT_ERROR = Error::fromCode(GPG_ERR_INV_USER_ID);
|
||||
|
||||
if (needsNoResponse(status)) {
|
||||
return state();
|
||||
}
|
||||
|
||||
using namespace GpgAddUserIDEditInteractor_Private;
|
||||
|
||||
switch (state()) {
|
||||
|
@ -25,7 +25,7 @@
|
||||
#ifndef __GPGMEPP_GPGADDUSERIDEDITINTERACTOR_H__
|
||||
#define __GPGMEPP_GPGADDUSERIDEDITINTERACTOR_H__
|
||||
|
||||
#include "editinteractor.h"
|
||||
#include <editinteractor.h>
|
||||
|
||||
#include <string>
|
||||
|
||||
|
@ -33,6 +33,8 @@
|
||||
|
||||
#include <assert.h>
|
||||
|
||||
#include <sstream>
|
||||
|
||||
using namespace GpgME;
|
||||
|
||||
GpgAgentGetInfoAssuanTransaction::GpgAgentGetInfoAssuanTransaction(InfoItem item)
|
||||
|
@ -25,7 +25,7 @@
|
||||
#ifndef __GPGMEPP_GPGAGENTGETINFOASSUANTRANSACTION_H__
|
||||
#define __GPGMEPP_GPGAGENTGETINFOASSUANTRANSACTION_H__
|
||||
|
||||
#include "interfaces/assuantransaction.h"
|
||||
#include <interfaces/assuantransaction.h>
|
||||
|
||||
#include <string>
|
||||
#include <vector>
|
||||
|
@ -36,17 +36,15 @@ using namespace GpgME;
|
||||
class GpgGenCardKeyInteractor::Private
|
||||
{
|
||||
public:
|
||||
Private() : keysize("2048")
|
||||
Private() : keysize("2048"), backup(false)
|
||||
{
|
||||
}
|
||||
|
||||
}
|
||||
std::string name, email, backupFileName, expiry, serial, keysize;
|
||||
bool backup = false;
|
||||
Algo algo = RSA;
|
||||
std::string curve;
|
||||
bool backup;
|
||||
};
|
||||
|
||||
GpgGenCardKeyInteractor::~GpgGenCardKeyInteractor() = default;
|
||||
GpgGenCardKeyInteractor::~GpgGenCardKeyInteractor() {}
|
||||
|
||||
GpgGenCardKeyInteractor::GpgGenCardKeyInteractor(const std::string &serial):
|
||||
d(new Private)
|
||||
@ -84,20 +82,6 @@ std::string GpgGenCardKeyInteractor::backupFileName() const
|
||||
return d->backupFileName;
|
||||
}
|
||||
|
||||
void GpgGenCardKeyInteractor::setAlgo(Algo algo)
|
||||
{
|
||||
d->algo = algo;
|
||||
}
|
||||
|
||||
void GpgGenCardKeyInteractor::setCurve(Curve curve)
|
||||
{
|
||||
if (curve == DefaultCurve) {
|
||||
d->curve.clear();
|
||||
} else if (curve >= 1 && curve <= LastCurve) {
|
||||
d->curve = std::to_string(static_cast<int>(curve));
|
||||
}
|
||||
}
|
||||
|
||||
namespace GpgGenCardKeyInteractor_Private
|
||||
{
|
||||
enum {
|
||||
@ -120,14 +104,6 @@ enum {
|
||||
QUIT,
|
||||
SAVE,
|
||||
|
||||
KEY_ATTR,
|
||||
KEY_ALGO1,
|
||||
KEY_ALGO2,
|
||||
KEY_ALGO3,
|
||||
KEY_CURVE1,
|
||||
KEY_CURVE2,
|
||||
KEY_CURVE3,
|
||||
|
||||
ERROR = EditInteractor::ErrorState
|
||||
};
|
||||
}
|
||||
@ -142,16 +118,6 @@ const char *GpgGenCardKeyInteractor::action(Error &err) const
|
||||
return "admin";
|
||||
case COMMAND:
|
||||
return "generate";
|
||||
case KEY_ATTR:
|
||||
return "key-attr";
|
||||
case KEY_ALGO1:
|
||||
case KEY_ALGO2:
|
||||
case KEY_ALGO3:
|
||||
return d->algo == RSA ? "1" : "2";
|
||||
case KEY_CURVE1:
|
||||
case KEY_CURVE2:
|
||||
case KEY_CURVE3:
|
||||
return d->curve.empty() ? "1" : d->curve.c_str(); // default is Curve25519
|
||||
case NAME:
|
||||
return d->name.c_str();
|
||||
case EMAIL:
|
||||
@ -192,6 +158,10 @@ unsigned int GpgGenCardKeyInteractor::nextState(unsigned int status, const char
|
||||
static const Error INV_EMAIL_ERROR = Error::fromCode(GPG_ERR_INV_USER_ID);
|
||||
static const Error INV_COMMENT_ERROR = Error::fromCode(GPG_ERR_INV_USER_ID);
|
||||
|
||||
if (needsNoResponse(status)) {
|
||||
return state();
|
||||
}
|
||||
|
||||
using namespace GpgGenCardKeyInteractor_Private;
|
||||
|
||||
switch (state()) {
|
||||
@ -221,92 +191,12 @@ unsigned int GpgGenCardKeyInteractor::nextState(unsigned int status, const char
|
||||
err = GENERAL_ERROR;
|
||||
return ERROR;
|
||||
case DO_ADMIN:
|
||||
if (status == GPGME_STATUS_GET_LINE &&
|
||||
strcmp(args, "cardedit.prompt") == 0) {
|
||||
return KEY_ATTR;
|
||||
}
|
||||
err = GENERAL_ERROR;
|
||||
return ERROR;
|
||||
// Handling for key-attr subcommand
|
||||
case KEY_ATTR:
|
||||
if (status == GPGME_STATUS_GET_LINE &&
|
||||
strcmp(args, "cardedit.prompt") == 0) {
|
||||
// Happens if key attr is not yet supported.
|
||||
return COMMAND;
|
||||
}
|
||||
if (status == GPGME_STATUS_GET_LINE &&
|
||||
strcmp(args, "cardedit.genkeys.algo") == 0) {
|
||||
return KEY_ALGO1;
|
||||
}
|
||||
err = GENERAL_ERROR;
|
||||
return ERROR;
|
||||
case KEY_ALGO1:
|
||||
if (status == GPGME_STATUS_GET_LINE &&
|
||||
strcmp(args, "cardedit.genkeys.size") == 0) {
|
||||
return SIZE;
|
||||
}
|
||||
if (status == GPGME_STATUS_GET_LINE &&
|
||||
strcmp(args, "keygen.curve") == 0) {
|
||||
return KEY_CURVE1;
|
||||
}
|
||||
err = GENERAL_ERROR;
|
||||
return ERROR;
|
||||
case KEY_ALGO2:
|
||||
if (status == GPGME_STATUS_GET_LINE &&
|
||||
strcmp(args, "cardedit.genkeys.size") == 0) {
|
||||
return SIZE2;
|
||||
}
|
||||
if (status == GPGME_STATUS_GET_LINE &&
|
||||
strcmp(args, "keygen.curve") == 0) {
|
||||
return KEY_CURVE2;
|
||||
}
|
||||
err = GENERAL_ERROR;
|
||||
return ERROR;
|
||||
case KEY_ALGO3:
|
||||
if (status == GPGME_STATUS_GET_LINE &&
|
||||
strcmp(args, "cardedit.genkeys.size") == 0) {
|
||||
return SIZE3;
|
||||
}
|
||||
if (status == GPGME_STATUS_GET_LINE &&
|
||||
strcmp(args, "keygen.curve") == 0) {
|
||||
return KEY_CURVE3;
|
||||
}
|
||||
err = GENERAL_ERROR;
|
||||
return ERROR;
|
||||
case KEY_CURVE1:
|
||||
if (status == GPGME_STATUS_GET_LINE &&
|
||||
strcmp(args, "cardedit.genkeys.algo") == 0) {
|
||||
return KEY_ALGO2;
|
||||
}
|
||||
if (status == GPGME_STATUS_GET_LINE &&
|
||||
strcmp(args, "cardedit.prompt") == 0) {
|
||||
return COMMAND;
|
||||
}
|
||||
err = GENERAL_ERROR;
|
||||
return ERROR;
|
||||
case KEY_CURVE2:
|
||||
if (status == GPGME_STATUS_GET_LINE &&
|
||||
strcmp(args, "cardedit.genkeys.algo") == 0) {
|
||||
return KEY_ALGO3;
|
||||
}
|
||||
if (status == GPGME_STATUS_GET_LINE &&
|
||||
strcmp(args, "cardedit.prompt") == 0) {
|
||||
return COMMAND;
|
||||
}
|
||||
err = GENERAL_ERROR;
|
||||
return ERROR;
|
||||
case KEY_CURVE3:
|
||||
if (status == GPGME_STATUS_GET_LINE &&
|
||||
strcmp(args, "cardedit.genkeys.algo") == 0) {
|
||||
return KEY_ALGO3;
|
||||
}
|
||||
if (status == GPGME_STATUS_GET_LINE &&
|
||||
strcmp(args, "cardedit.prompt") == 0) {
|
||||
return COMMAND;
|
||||
}
|
||||
err = GENERAL_ERROR;
|
||||
return ERROR;
|
||||
// End key-attr handling
|
||||
case COMMAND:
|
||||
if (status == GPGME_STATUS_GET_LINE &&
|
||||
strcmp(args, "cardedit.genkeys.backup_enc") == 0) {
|
||||
@ -323,21 +213,14 @@ unsigned int GpgGenCardKeyInteractor::nextState(unsigned int status, const char
|
||||
strcmp(args, "cardedit.genkeys.size") == 0) {
|
||||
return SIZE;
|
||||
}
|
||||
if (status == GPGME_STATUS_GET_LINE &&
|
||||
strcmp(args, "keygen.valid") == 0) {
|
||||
return EXPIRE;
|
||||
}
|
||||
err = GENERAL_ERROR;
|
||||
return ERROR;
|
||||
case REPLACE:
|
||||
if (status == GPGME_STATUS_GET_LINE &&
|
||||
strcmp(args, "cardedit.genkeys.size") == 0) {
|
||||
printf("Moving to SIZE\n");
|
||||
return SIZE;
|
||||
}
|
||||
if (status == GPGME_STATUS_GET_LINE &&
|
||||
strcmp(args, "keygen.valid") == 0) {
|
||||
return EXPIRE;
|
||||
}
|
||||
err = GENERAL_ERROR;
|
||||
return ERROR;
|
||||
case SIZE:
|
||||
@ -349,14 +232,6 @@ unsigned int GpgGenCardKeyInteractor::nextState(unsigned int status, const char
|
||||
strcmp(args, "keygen.valid") == 0) {
|
||||
return EXPIRE;
|
||||
}
|
||||
if (status == GPGME_STATUS_GET_LINE &&
|
||||
strcmp(args, "cardedit.genkeys.algo") == 0) {
|
||||
return KEY_ALGO2;
|
||||
}
|
||||
if (status == GPGME_STATUS_GET_LINE &&
|
||||
strcmp(args, "cardedit.prompt") == 0) {
|
||||
return COMMAND;
|
||||
}
|
||||
err = GENERAL_ERROR;
|
||||
return ERROR;
|
||||
case SIZE2:
|
||||
@ -368,14 +243,6 @@ unsigned int GpgGenCardKeyInteractor::nextState(unsigned int status, const char
|
||||
strcmp(args, "keygen.valid") == 0) {
|
||||
return EXPIRE;
|
||||
}
|
||||
if (status == GPGME_STATUS_GET_LINE &&
|
||||
strcmp(args, "cardedit.genkeys.algo") == 0) {
|
||||
return KEY_ALGO3;
|
||||
}
|
||||
if (status == GPGME_STATUS_GET_LINE &&
|
||||
strcmp(args, "cardedit.prompt") == 0) {
|
||||
return COMMAND;
|
||||
}
|
||||
err = GENERAL_ERROR;
|
||||
return ERROR;
|
||||
case SIZE3:
|
||||
@ -383,10 +250,6 @@ unsigned int GpgGenCardKeyInteractor::nextState(unsigned int status, const char
|
||||
strcmp(args, "keygen.valid") == 0) {
|
||||
return EXPIRE;
|
||||
}
|
||||
if (status == GPGME_STATUS_GET_LINE &&
|
||||
strcmp(args, "cardedit.prompt") == 0) {
|
||||
return COMMAND;
|
||||
}
|
||||
err = GENERAL_ERROR;
|
||||
return ERROR;
|
||||
case EXPIRE:
|
||||
|
@ -24,7 +24,7 @@
|
||||
#ifndef __GPGMEPP_GPGGENCARDKEYEDITINTERACTOR_H__
|
||||
#define __GPGMEPP_GPGGENCARDKEYEDITINTERACTOR_H__
|
||||
|
||||
#include "editinteractor.h"
|
||||
#include <editinteractor.h>
|
||||
|
||||
#include <string>
|
||||
#include <memory>
|
||||
@ -56,29 +56,6 @@ public:
|
||||
void setDoBackup(bool value);
|
||||
void setExpiry(const std::string &timeString);
|
||||
|
||||
enum Algo {
|
||||
RSA = 1,
|
||||
ECC = 2,
|
||||
};
|
||||
void setAlgo(Algo algo);
|
||||
|
||||
// the enum values minus 1 have to match the indexes of the curves used by
|
||||
// ask_curve() in gnupg's g10/keygen.c
|
||||
enum Curve {
|
||||
DefaultCurve = 0, // currently Curve25519
|
||||
Curve25519 = 1,
|
||||
Curve448,
|
||||
NISTP256,
|
||||
NISTP384,
|
||||
NISTP521,
|
||||
BrainpoolP256,
|
||||
BrainpoolP384,
|
||||
BrainpoolP512,
|
||||
Secp256k1,
|
||||
LastCurve = Secp256k1,
|
||||
};
|
||||
void setCurve(Curve curve);
|
||||
|
||||
std::string backupFileName() const;
|
||||
|
||||
private:
|
||||
|
@ -75,7 +75,4 @@ typedef struct _gpgme_tofu_info *gpgme_tofu_info_t;
|
||||
struct _gpgme_op_query_swdb_result;
|
||||
typedef struct _gpgme_op_query_swdb_result *gpgme_query_swdb_result_t;
|
||||
|
||||
struct _gpgme_revocation_key;
|
||||
typedef struct _gpgme_revocation_key *gpgme_revocation_key_t;
|
||||
|
||||
#endif // __GPGMEPP_GPGMEFW_H__
|
||||
|
@ -1,207 +0,0 @@
|
||||
/*
|
||||
gpgrevokekeyeditinteractor.cpp - Edit Interactor to revoke own OpenPGP keys
|
||||
Copyright (c) 2022 g10 Code GmbH
|
||||
Software engineering by Ingo Klöcker <dev@ingo-kloecker.de>
|
||||
|
||||
This file is part of GPGME++.
|
||||
|
||||
GPGME++ is free software; you can redistribute it and/or
|
||||
modify it under the terms of the GNU Library General Public
|
||||
License as published by the Free Software Foundation; either
|
||||
version 2 of the License, or (at your option) any later version.
|
||||
|
||||
GPGME++ is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU Library General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU Library General Public License
|
||||
along with GPGME++; see the file COPYING.LIB. If not, write to the
|
||||
Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
|
||||
Boston, MA 02110-1301, USA.
|
||||
*/
|
||||
|
||||
#ifdef HAVE_CONFIG_H
|
||||
#include "config.h"
|
||||
#endif
|
||||
|
||||
#include "gpgrevokekeyeditinteractor.h"
|
||||
|
||||
#include "error.h"
|
||||
|
||||
#include <gpgme.h>
|
||||
|
||||
#include <vector>
|
||||
|
||||
// avoid conflict (msvc)
|
||||
#ifdef ERROR
|
||||
# undef ERROR
|
||||
#endif
|
||||
|
||||
using namespace GpgME;
|
||||
|
||||
class GpgRevokeKeyEditInteractor::Private
|
||||
{
|
||||
enum {
|
||||
START = EditInteractor::StartState,
|
||||
COMMAND,
|
||||
CONFIRM_REVOKING_ENTIRE_KEY,
|
||||
REASON_CODE,
|
||||
REASON_TEXT,
|
||||
// all these free slots belong to REASON_TEXT, too; we increase state()
|
||||
// by one for each line of text, so that action() is called
|
||||
REASON_TEXT_DONE = REASON_TEXT + 1000,
|
||||
CONFIRM_REASON,
|
||||
QUIT,
|
||||
CONFIRM_SAVE,
|
||||
|
||||
ERROR = EditInteractor::ErrorState
|
||||
};
|
||||
|
||||
GpgRevokeKeyEditInteractor *const q = nullptr;
|
||||
|
||||
public:
|
||||
Private(GpgRevokeKeyEditInteractor *q)
|
||||
: q{q}
|
||||
, reasonCode{"0"}
|
||||
{
|
||||
}
|
||||
|
||||
const char *action(Error &err) const;
|
||||
unsigned int nextState(unsigned int statusCode, const char *args, Error &err);
|
||||
|
||||
std::string reasonCode;
|
||||
std::vector<std::string> reasonLines;
|
||||
int nextLine = -1;
|
||||
};
|
||||
|
||||
const char *GpgRevokeKeyEditInteractor::Private::action(Error &err) const
|
||||
{
|
||||
switch (const auto state = q->state()) {
|
||||
case COMMAND:
|
||||
return "revkey";
|
||||
case CONFIRM_REVOKING_ENTIRE_KEY:
|
||||
return "Y";
|
||||
case REASON_CODE:
|
||||
return reasonCode.c_str();
|
||||
case REASON_TEXT_DONE:
|
||||
return "";
|
||||
case CONFIRM_REASON:
|
||||
return "Y";
|
||||
case QUIT:
|
||||
return "quit";
|
||||
case CONFIRM_SAVE:
|
||||
return "Y";
|
||||
case START:
|
||||
return nullptr;
|
||||
default:
|
||||
if (state >= REASON_TEXT && state < REASON_TEXT_DONE) {
|
||||
return reasonLines[nextLine].c_str();
|
||||
}
|
||||
// fall through
|
||||
case ERROR:
|
||||
err = Error::fromCode(GPG_ERR_GENERAL);
|
||||
return nullptr;
|
||||
}
|
||||
}
|
||||
|
||||
unsigned int GpgRevokeKeyEditInteractor::Private::nextState(unsigned int status, const char *args, Error &err)
|
||||
{
|
||||
using std::strcmp;
|
||||
|
||||
static const Error GENERAL_ERROR = Error::fromCode(GPG_ERR_GENERAL);
|
||||
|
||||
switch (const auto state = q->state()) {
|
||||
case START:
|
||||
if (status == GPGME_STATUS_GET_LINE &&
|
||||
strcmp(args, "keyedit.prompt") == 0) {
|
||||
return COMMAND;
|
||||
}
|
||||
err = GENERAL_ERROR;
|
||||
return ERROR;
|
||||
case COMMAND:
|
||||
if (status == GPGME_STATUS_GET_BOOL &&
|
||||
strcmp(args, "keyedit.revoke.subkey.okay") == 0) {
|
||||
return CONFIRM_REVOKING_ENTIRE_KEY;
|
||||
}
|
||||
err = GENERAL_ERROR;
|
||||
return ERROR;
|
||||
case CONFIRM_REVOKING_ENTIRE_KEY:
|
||||
if (status == GPGME_STATUS_GET_LINE &&
|
||||
strcmp(args, "ask_revocation_reason.code") == 0) {
|
||||
return REASON_CODE;
|
||||
}
|
||||
err = GENERAL_ERROR;
|
||||
return ERROR;
|
||||
case REASON_CODE:
|
||||
if (status == GPGME_STATUS_GET_LINE &&
|
||||
strcmp(args, "ask_revocation_reason.text") == 0) {
|
||||
nextLine++;
|
||||
return static_cast<std::size_t>(nextLine) < reasonLines.size() ? REASON_TEXT : REASON_TEXT_DONE;
|
||||
}
|
||||
err = GENERAL_ERROR;
|
||||
return ERROR;
|
||||
default:
|
||||
if (state >= REASON_TEXT && state < REASON_TEXT_DONE) {
|
||||
if (status == GPGME_STATUS_GET_LINE &&
|
||||
strcmp(args, "ask_revocation_reason.text") == 0) {
|
||||
nextLine++;
|
||||
return static_cast<std::size_t>(nextLine) < reasonLines.size() ? state + 1 : REASON_TEXT_DONE;
|
||||
}
|
||||
}
|
||||
err = GENERAL_ERROR;
|
||||
return ERROR;
|
||||
case REASON_TEXT_DONE:
|
||||
if (status == GPGME_STATUS_GET_BOOL &&
|
||||
strcmp(args, "ask_revocation_reason.okay") == 0) {
|
||||
return CONFIRM_REASON;
|
||||
}
|
||||
err = GENERAL_ERROR;
|
||||
return ERROR;
|
||||
case CONFIRM_REASON:
|
||||
if (status == GPGME_STATUS_GET_LINE &&
|
||||
strcmp(args, "keyedit.prompt") == 0) {
|
||||
return QUIT;
|
||||
}
|
||||
err = GENERAL_ERROR;
|
||||
return ERROR;
|
||||
case QUIT:
|
||||
if (status == GPGME_STATUS_GET_BOOL &&
|
||||
strcmp(args, "keyedit.save.okay") == 0) {
|
||||
return CONFIRM_SAVE;
|
||||
}
|
||||
err = GENERAL_ERROR;
|
||||
return ERROR;
|
||||
case ERROR:
|
||||
if (status == GPGME_STATUS_GET_LINE &&
|
||||
strcmp(args, "keyedit.prompt") == 0) {
|
||||
return QUIT;
|
||||
}
|
||||
err = q->lastError();
|
||||
return ERROR;
|
||||
}
|
||||
}
|
||||
|
||||
GpgRevokeKeyEditInteractor::GpgRevokeKeyEditInteractor()
|
||||
: EditInteractor{}
|
||||
, d{new Private{this}}
|
||||
{
|
||||
}
|
||||
|
||||
GpgRevokeKeyEditInteractor::~GpgRevokeKeyEditInteractor() = default;
|
||||
|
||||
void GpgRevokeKeyEditInteractor::setReason(RevocationReason reason, const std::vector<std::string> &description)
|
||||
{
|
||||
d->reasonCode = std::to_string(static_cast<int>(reason));
|
||||
d->reasonLines = description;
|
||||
}
|
||||
|
||||
const char *GpgRevokeKeyEditInteractor::action(Error &err) const
|
||||
{
|
||||
return d->action(err);
|
||||
}
|
||||
|
||||
unsigned int GpgRevokeKeyEditInteractor::nextState(unsigned int status, const char *args, Error &err) const
|
||||
{
|
||||
return d->nextState(status, args, err);
|
||||
}
|
@ -1,62 +0,0 @@
|
||||
/*
|
||||
gpgrevokekeyeditinteractor.h - Edit Interactor to revoke own OpenPGP keys
|
||||
Copyright (c) 2022 g10 Code GmbH
|
||||
Software engineering by Ingo Klöcker <dev@ingo-kloecker.de>
|
||||
|
||||
This file is part of GPGME++.
|
||||
|
||||
GPGME++ is free software; you can redistribute it and/or
|
||||
modify it under the terms of the GNU Library General Public
|
||||
License as published by the Free Software Foundation; either
|
||||
version 2 of the License, or (at your option) any later version.
|
||||
|
||||
GPGME++ is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU Library General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU Library General Public License
|
||||
along with GPGME++; see the file COPYING.LIB. If not, write to the
|
||||
Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
|
||||
Boston, MA 02110-1301, USA.
|
||||
*/
|
||||
|
||||
#ifndef __GPGMEPP_GPGREVOKEKEYEDITINTERACTOR_H__
|
||||
#define __GPGMEPP_GPGREVOKEKEYEDITINTERACTOR_H__
|
||||
|
||||
#include "editinteractor.h"
|
||||
#include "global.h"
|
||||
|
||||
#include <memory>
|
||||
#include <vector>
|
||||
|
||||
namespace GpgME
|
||||
{
|
||||
|
||||
/** Edit interactor to revoke the key a key edit operation is working on.
|
||||
* Supports revocation of own keys only. */
|
||||
class GPGMEPP_EXPORT GpgRevokeKeyEditInteractor : public EditInteractor
|
||||
{
|
||||
public:
|
||||
GpgRevokeKeyEditInteractor();
|
||||
~GpgRevokeKeyEditInteractor() override;
|
||||
|
||||
/** Sets the reason for the revocation. The reason defaults to \c Unspecified.
|
||||
* \a description can be used for adding a comment for the revocation. The
|
||||
* individual elements of \a description must be non-empty strings and they
|
||||
* must not contain any endline characters.
|
||||
*/
|
||||
void setReason(RevocationReason reason, const std::vector<std::string> &description = {});
|
||||
|
||||
private:
|
||||
const char *action(Error &err) const override;
|
||||
unsigned int nextState(unsigned int statusCode, const char *args, Error &err) const override;
|
||||
|
||||
private:
|
||||
class GPGMEPP_NO_EXPORT Private;
|
||||
const std::unique_ptr<Private> d;
|
||||
};
|
||||
|
||||
} // namespace GpgME
|
||||
|
||||
#endif // __GPGMEPP_GPGREVOKEKEYEDITINTERACTOR_H__
|
@ -94,6 +94,10 @@ unsigned int GpgSetExpiryTimeEditInteractor::nextState(unsigned int status, cons
|
||||
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()) {
|
||||
|
@ -25,7 +25,7 @@
|
||||
#ifndef __GPGMEPP_GPGSETEXPIRYTIMEEDITINTERACTOR_H__
|
||||
#define __GPGMEPP_GPGSETEXPIRYTIMEEDITINTERACTOR_H__
|
||||
|
||||
#include "editinteractor.h"
|
||||
#include <editinteractor.h>
|
||||
|
||||
#include <string>
|
||||
|
||||
|
@ -98,6 +98,10 @@ unsigned int GpgSetOwnerTrustEditInteractor::nextState(unsigned int status, cons
|
||||
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()) {
|
||||
|
@ -25,8 +25,8 @@
|
||||
#ifndef __GPGMEPP_GPGSETOWNERTRUSTEDITINTERACTOR_H__
|
||||
#define __GPGMEPP_GPGSETOWNERTRUSTEDITINTERACTOR_H__
|
||||
|
||||
#include "editinteractor.h"
|
||||
#include "key.h"
|
||||
#include <editinteractor.h>
|
||||
#include <key.h>
|
||||
|
||||
#include <string>
|
||||
|
||||
|
@ -64,13 +64,6 @@ public:
|
||||
std::vector<unsigned int> userIDs;
|
||||
std::vector<unsigned int>::const_iterator currentId, nextId;
|
||||
unsigned int checkLevel;
|
||||
bool dupeOk;
|
||||
Key key;
|
||||
struct {
|
||||
TrustSignatureTrust trust;
|
||||
std::string depth;
|
||||
std::string scope;
|
||||
} trustSignature;
|
||||
|
||||
const char *command() const
|
||||
{
|
||||
@ -133,9 +126,7 @@ GpgSignKeyEditInteractor::Private::Private()
|
||||
userIDs(),
|
||||
currentId(),
|
||||
nextId(),
|
||||
checkLevel(0),
|
||||
dupeOk(false),
|
||||
trustSignature{TrustSignatureTrust::None, "0", {}}
|
||||
checkLevel(0)
|
||||
{
|
||||
}
|
||||
|
||||
@ -168,9 +159,6 @@ enum SignKeyState {
|
||||
SET_TRUST_REGEXP,
|
||||
CONFIRM,
|
||||
CONFIRM2,
|
||||
DUPE_OK,
|
||||
DUPE_OK2,
|
||||
REJECT_SIGN_EXPIRED,
|
||||
QUIT,
|
||||
SAVE,
|
||||
ERROR = EditInteractor::ErrorState
|
||||
@ -194,43 +182,30 @@ static GpgSignKeyEditInteractor_Private::TransitionMap makeTable()
|
||||
#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.expired_okay", REJECT_SIGN_EXPIRED);
|
||||
addEntry(COMMAND, GET_BOOL, "sign_uid.okay", CONFIRM);
|
||||
addEntry(COMMAND, GET_BOOL, "sign_uid.local_promote_okay", CONFIRM2);
|
||||
addEntry(COMMAND, GET_BOOL, "sign_uid.dupe_okay", DUPE_OK);
|
||||
addEntry(COMMAND, GET_LINE, "trustsig_prompt.trust_value", SET_TRUST_VALUE);
|
||||
addEntry(UIDS_ANSWER_SIGN_ALL, GET_BOOL, "sign_uid.okay", CONFIRM);
|
||||
addEntry(UIDS_ANSWER_SIGN_ALL, GET_BOOL, "sign_uid.dupe_okay", DUPE_OK);
|
||||
addEntry(UIDS_ANSWER_SIGN_ALL, GET_LINE, "sign_uid.expire", SET_EXPIRE);
|
||||
addEntry(UIDS_ANSWER_SIGN_ALL, GET_LINE, "sign_uid.class", SET_CHECK_LEVEL);
|
||||
addEntry(UIDS_ANSWER_SIGN_ALL, GET_LINE, "trustsig_prompt.trust_value", SET_TRUST_VALUE);
|
||||
addEntry(SET_TRUST_VALUE, GET_LINE, "trustsig_prompt.trust_depth", SET_TRUST_DEPTH);
|
||||
addEntry(SET_TRUST_DEPTH, GET_LINE, "trustsig_prompt.trust_regexp", SET_TRUST_REGEXP);
|
||||
addEntry(SET_TRUST_REGEXP, GET_BOOL, "sign_uid.okay", CONFIRM);
|
||||
addEntry(SET_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(DUPE_OK, GET_BOOL, "sign_uid.okay", CONFIRM);
|
||||
addEntry(DUPE_OK2, GET_BOOL, "sign_uid.okay", CONFIRM);
|
||||
addEntry(DUPE_OK, GET_LINE, "trustsig_prompt.trust_value", SET_TRUST_VALUE);
|
||||
addEntry(DUPE_OK2, GET_LINE, "trustsig_prompt.trust_value", SET_TRUST_VALUE);
|
||||
addEntry(CONFIRM, GET_BOOL, "sign_uid.okay", CONFIRM);
|
||||
addEntry(CONFIRM2, GET_BOOL, "sign_uid.okay", CONFIRM);
|
||||
addEntry(CONFIRM, GET_LINE, "keyedit.prompt", COMMAND);
|
||||
addEntry(CONFIRM, GET_LINE, "trustsig_prompt.trust_value", SET_TRUST_VALUE);
|
||||
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, "trustsig_prompt.trust_value", SET_TRUST_VALUE);
|
||||
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(UIDS_LIST_SEPARATELY_DONE, GET_BOOL, "sign_uid.dupe_okay", DUPE_OK);
|
||||
addEntry(DUPE_OK, GET_BOOL, "sign_uid.dupe_okay", DUPE_OK2);
|
||||
addEntry(DUPE_OK2, GET_BOOL, "sign_uid.dupe_okay", DUPE_OK);
|
||||
addEntry(CONFIRM, GET_LINE, "keyedit.prompt", QUIT);
|
||||
addEntry(REJECT_SIGN_EXPIRED, GET_LINE, "keyedit.prompt", QUIT);
|
||||
addEntry(ERROR, GET_LINE, "keyedit.prompt", QUIT);
|
||||
addEntry(QUIT, GET_BOOL, "keyedit.save.okay", SAVE);
|
||||
#undef addEntry
|
||||
@ -253,22 +228,17 @@ const char *GpgSignKeyEditInteractor::action(Error &err) const
|
||||
case SET_EXPIRE:
|
||||
return answer(true);
|
||||
case SET_TRUST_VALUE:
|
||||
return d->trustSignature.trust == TrustSignatureTrust::Partial ? "1" : "2";
|
||||
// TODO
|
||||
case SET_TRUST_DEPTH:
|
||||
return d->trustSignature.depth.c_str();
|
||||
//TODO
|
||||
case SET_TRUST_REGEXP:
|
||||
return d->trustSignature.scope.c_str();
|
||||
//TODO
|
||||
return nullptr;
|
||||
case SET_CHECK_LEVEL:
|
||||
return check_level_strings[d->checkLevel];
|
||||
case DUPE_OK:
|
||||
case DUPE_OK2:
|
||||
return answer(d->dupeOk);
|
||||
case CONFIRM2:
|
||||
case CONFIRM:
|
||||
return answer(true);
|
||||
case REJECT_SIGN_EXPIRED:
|
||||
err = Error::fromCode(GPG_ERR_KEY_EXPIRED);
|
||||
return answer(false);
|
||||
case QUIT:
|
||||
return "quit";
|
||||
case SAVE:
|
||||
@ -276,17 +246,7 @@ const char *GpgSignKeyEditInteractor::action(Error &err) const
|
||||
default:
|
||||
if (st >= UIDS_LIST_SEPARATELY && st < UIDS_LIST_SEPARATELY_DONE) {
|
||||
std::stringstream ss;
|
||||
auto nextID = d->nextUserID();
|
||||
const char *hash;
|
||||
assert (nextID);
|
||||
if (!d->key.isNull() && (hash = d->key.userID(nextID - 1).uidhash())) {
|
||||
/* Prefer uidhash if it is available as it might happen
|
||||
* that uidattrs break the ordering of the uids in the
|
||||
* edit-key interface */
|
||||
ss << "uid " << hash;
|
||||
} else {
|
||||
ss << nextID;
|
||||
}
|
||||
ss << d->nextUserID();
|
||||
d->scratch = ss.str();
|
||||
return d->scratch.c_str();
|
||||
}
|
||||
@ -304,6 +264,9 @@ unsigned int GpgSignKeyEditInteractor::nextState(unsigned int status, const char
|
||||
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;
|
||||
|
||||
@ -342,10 +305,6 @@ unsigned int GpgSignKeyEditInteractor::nextState(unsigned int status, const char
|
||||
err = GENERAL_ERROR;
|
||||
return ERROR;
|
||||
}
|
||||
void GpgSignKeyEditInteractor::setKey(const Key &key)
|
||||
{
|
||||
d->key = key;
|
||||
}
|
||||
|
||||
void GpgSignKeyEditInteractor::setCheckLevel(unsigned int checkLevel)
|
||||
{
|
||||
@ -367,29 +326,3 @@ void GpgSignKeyEditInteractor::setSigningOptions(int options)
|
||||
assert(!d->started);
|
||||
d->options = options;
|
||||
}
|
||||
|
||||
void GpgSignKeyEditInteractor::setDupeOk(bool value)
|
||||
{
|
||||
assert(!d->started);
|
||||
d->dupeOk = value;
|
||||
}
|
||||
|
||||
void GpgSignKeyEditInteractor::setTrustSignatureTrust(GpgME::TrustSignatureTrust trust)
|
||||
{
|
||||
assert(!d->started);
|
||||
assert(trust != TrustSignatureTrust::None);
|
||||
d->trustSignature.trust = trust;
|
||||
}
|
||||
|
||||
void GpgSignKeyEditInteractor::setTrustSignatureDepth(unsigned short depth)
|
||||
{
|
||||
assert(!d->started);
|
||||
assert(depth <= 255);
|
||||
d->trustSignature.depth = std::to_string(depth);
|
||||
}
|
||||
|
||||
void GpgSignKeyEditInteractor::setTrustSignatureScope(const std::string &scope)
|
||||
{
|
||||
assert(!d->started);
|
||||
d->trustSignature.scope = scope;
|
||||
}
|
||||
|
@ -25,7 +25,7 @@
|
||||
#ifndef __GPGMEPP_GPGSIGNKEYEDITINTERACTOR_H__
|
||||
#define __GPGMEPP_GPGSIGNKEYEDITINTERACTOR_H__
|
||||
|
||||
#include "editinteractor.h"
|
||||
#include <editinteractor.h>
|
||||
|
||||
#include <string>
|
||||
#include <vector>
|
||||
@ -35,7 +35,6 @@ namespace GpgME
|
||||
|
||||
class Key;
|
||||
class UserID;
|
||||
enum class TrustSignatureTrust : char;
|
||||
|
||||
class GPGMEPP_EXPORT GpgSignKeyEditInteractor : public EditInteractor
|
||||
{
|
||||
@ -51,18 +50,8 @@ public:
|
||||
|
||||
void setCheckLevel(unsigned int checkLevel);
|
||||
void setUserIDsToSign(const std::vector<unsigned int> &userIDsToSign);
|
||||
void setKey(const Key &key);
|
||||
void setSigningOptions(int options);
|
||||
|
||||
/* Set this if it is ok to overwrite an existing signature. In that
|
||||
* case the context has to have the flag "extended-edit" set to 1 through
|
||||
* Context::setFlag before calling edit.*/
|
||||
void setDupeOk(bool value);
|
||||
|
||||
void setTrustSignatureTrust(TrustSignatureTrust trust);
|
||||
void setTrustSignatureDepth(unsigned short depth);
|
||||
void setTrustSignatureScope(const std::string &scope);
|
||||
|
||||
private:
|
||||
const char *action(Error &err) const override;
|
||||
unsigned int nextState(unsigned int statusCode, const char *args, Error &err) const override;
|
||||
|
@ -35,9 +35,6 @@
|
||||
#include <cstring>
|
||||
|
||||
#include <string.h>
|
||||
#include <strings.h>
|
||||
#include <istream>
|
||||
#include <iterator>
|
||||
|
||||
class GpgME::ImportResult::Private
|
||||
{
|
||||
@ -48,9 +45,7 @@ public:
|
||||
// We just need to handle the pointers in the structs:
|
||||
for (gpgme_import_status_t is = r.imports ; is ; is = is->next) {
|
||||
gpgme_import_status_t copy = new _gpgme_import_status(*is);
|
||||
if (is->fpr) {
|
||||
copy->fpr = strdup(is->fpr);
|
||||
}
|
||||
copy->fpr = strdup(is->fpr);
|
||||
copy->next = nullptr;
|
||||
imports.push_back(copy);
|
||||
}
|
||||
@ -94,131 +89,6 @@ void GpgME::ImportResult::init(gpgme_ctx_t ctx)
|
||||
|
||||
make_standard_stuff(ImportResult)
|
||||
|
||||
void GpgME::ImportResult::mergeWith(const ImportResult &other)
|
||||
{
|
||||
if (other.isNull()) {
|
||||
return;
|
||||
}
|
||||
if (isNull()) { // just assign
|
||||
operator=(other);
|
||||
return;
|
||||
}
|
||||
|
||||
// Add the numbers of considered keys; the number will be corrected when
|
||||
// merging the imports to account for duplicates
|
||||
d->res.considered += other.d->res.considered;
|
||||
// Add the numbers of keys without user ID; may count duplicates
|
||||
d->res.no_user_id += other.d->res.no_user_id;
|
||||
// Add the numbers of imported keys
|
||||
d->res.imported += other.d->res.imported;
|
||||
// Add the numbers of imported RSA keys
|
||||
d->res.imported_rsa += other.d->res.imported_rsa;
|
||||
// Add the numbers of unchanged keys; the number will be corrected when
|
||||
// merging the imports to account for keys changed by this import
|
||||
d->res.unchanged += other.d->res.unchanged;
|
||||
// Add the numbers of new user IDs
|
||||
d->res.new_user_ids += other.d->res.new_user_ids;
|
||||
// Add the numbers of new subkeys
|
||||
d->res.new_sub_keys += other.d->res.new_sub_keys;
|
||||
// Add the numbers of new signatures
|
||||
d->res.new_signatures += other.d->res.new_signatures;
|
||||
// Add the numbers of new revocations
|
||||
d->res.new_revocations += other.d->res.new_revocations;
|
||||
|
||||
// Add the numbers of considered secret keys; the number will be corrected when
|
||||
// merging the imports to account for duplicates
|
||||
d->res.secret_read += other.d->res.secret_read;
|
||||
// Add the numbers of imported secret keys
|
||||
d->res.secret_imported += other.d->res.secret_imported;
|
||||
// Add the numbers of unchanged secret keys; the number will be corrected when
|
||||
// merging the imports to account for keys changed by this import
|
||||
d->res.secret_unchanged += other.d->res.secret_unchanged;
|
||||
|
||||
// Add the numbers of new keys that were skipped; may count duplicates
|
||||
d->res.skipped_new_keys += other.d->res.skipped_new_keys;
|
||||
// Add the numbers of keys that were not imported; may count duplicates
|
||||
d->res.not_imported += other.d->res.not_imported;
|
||||
// Add the numbers of v3 keys that were skipped; may count duplicates
|
||||
d->res.skipped_v3_keys += other.d->res.skipped_v3_keys;
|
||||
|
||||
// Look at the list of keys for which an import was attempted during the
|
||||
// other import to correct some of the consolidated numbers
|
||||
for (auto it = std::begin(other.d->imports), end = std::end(other.d->imports); it != end; ++it) {
|
||||
const char *fpr = (*it)->fpr;
|
||||
if (!fpr || !*fpr) {
|
||||
// we cannot derive any useful information about an import if the
|
||||
// fingerprint is null or empty
|
||||
continue;
|
||||
}
|
||||
// was this key also considered during the first import
|
||||
const auto consideredInFirstImports =
|
||||
std::any_of(std::begin(d->imports), std::end(d->imports), [fpr](const gpgme_import_status_t i) {
|
||||
return i->fpr && !strcmp(i->fpr, fpr);
|
||||
});
|
||||
// did we see this key already in the list of keys of the other import
|
||||
const auto consideredInPreviousOtherImports =
|
||||
std::any_of(std::begin(other.d->imports), it, [fpr](const gpgme_import_status_t i) {
|
||||
return i->fpr && !strcmp(i->fpr, fpr);
|
||||
});
|
||||
// was anything added to this key during the other import
|
||||
const auto changedInOtherImports =
|
||||
std::any_of(std::begin(other.d->imports), std::end(other.d->imports), [fpr](const gpgme_import_status_t i) {
|
||||
return i->fpr && !strcmp(i->fpr, fpr) && (i->status != 0);
|
||||
});
|
||||
if (consideredInFirstImports && !consideredInPreviousOtherImports) {
|
||||
// key was also considered during first import, but not before in the list of other imports
|
||||
d->res.considered -= 1;
|
||||
if (!changedInOtherImports) {
|
||||
// key was (most likely) counted as unchanged in the second import;
|
||||
// this needs to be corrected (regardless of whether it was changed in the first import)
|
||||
d->res.unchanged -= 1;
|
||||
}
|
||||
}
|
||||
|
||||
// now do the same for the secret key counts
|
||||
const auto secretKeyConsideredInFirstImports =
|
||||
std::any_of(std::begin(d->imports), std::end(d->imports), [fpr](const gpgme_import_status_t i) {
|
||||
return i->fpr && !strcmp(i->fpr, fpr) && (i->status & GPGME_IMPORT_SECRET);
|
||||
});
|
||||
const auto secretKeyConsideredInPreviousOtherImports =
|
||||
std::any_of(std::begin(other.d->imports), it, [fpr](const gpgme_import_status_t i) {
|
||||
return i->fpr && !strcmp(i->fpr, fpr) && (i->status & GPGME_IMPORT_SECRET);
|
||||
});
|
||||
const auto secretKeyChangedInOtherImports =
|
||||
std::any_of(std::begin(other.d->imports), std::end(other.d->imports), [fpr](const gpgme_import_status_t i) {
|
||||
return i->fpr && !strcmp(i->fpr, fpr) && (i->status & GPGME_IMPORT_SECRET) && (i->status != GPGME_IMPORT_SECRET);
|
||||
});
|
||||
if (secretKeyConsideredInFirstImports && !secretKeyConsideredInPreviousOtherImports) {
|
||||
// key was also considered during first import, but not before in the list of other imports
|
||||
d->res.secret_read -= 1;
|
||||
if (!secretKeyChangedInOtherImports) {
|
||||
// key was (most likely) counted as unchanged in the second import;
|
||||
// this needs to be corrected (regardless of whether it was changed in the first import)
|
||||
d->res.secret_unchanged -= 1;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Now append the list of keys for which an import was attempted during the
|
||||
// other import
|
||||
d->imports.reserve(d->imports.size() + other.d->imports.size());
|
||||
std::transform(std::begin(other.d->imports), std::end(other.d->imports),
|
||||
std::back_inserter(d->imports),
|
||||
[](const gpgme_import_status_t import) {
|
||||
gpgme_import_status_t copy = new _gpgme_import_status{*import};
|
||||
if (import->fpr) {
|
||||
copy->fpr = strdup(import->fpr);
|
||||
}
|
||||
copy->next = nullptr; // should already be null, but better safe than sorry
|
||||
return copy;
|
||||
});
|
||||
|
||||
// Finally, merge the error if there was none yet
|
||||
if (!bool(error())) {
|
||||
Result::operator=(other);
|
||||
}
|
||||
}
|
||||
|
||||
int GpgME::ImportResult::numConsidered() const
|
||||
{
|
||||
return d ? d->res.considered : 0 ;
|
||||
@ -354,42 +224,3 @@ GpgME::Import::Status GpgME::Import::status() const
|
||||
}
|
||||
return static_cast<Status>(result);
|
||||
}
|
||||
|
||||
std::ostream &GpgME::operator<<(std::ostream &os,
|
||||
const GpgME::ImportResult &result)
|
||||
{
|
||||
os << "GpgME::ImportResult(";
|
||||
if (!result.isNull()) {
|
||||
os << "\n considered: " << result.numConsidered()
|
||||
<< "\n without UID: " << result.numKeysWithoutUserID()
|
||||
<< "\n imported: " << result.numImported()
|
||||
<< "\n RSA Imported: " << result.numRSAImported()
|
||||
<< "\n unchanged: " << result.numUnchanged()
|
||||
<< "\n newUserIDs: " << result.newUserIDs()
|
||||
<< "\n newSubkeys: " << result.newSubkeys()
|
||||
<< "\n newSignatures: " << result.newSignatures()
|
||||
<< "\n newRevocations: " << result.newRevocations()
|
||||
<< "\n numSecretKeysConsidered: " << result.numSecretKeysConsidered()
|
||||
<< "\n numSecretKeysImported: " << result.numSecretKeysImported()
|
||||
<< "\n numSecretKeysUnchanged: " << result.numSecretKeysUnchanged()
|
||||
<< "\n"
|
||||
<< "\n notImported: " << result.notImported()
|
||||
<< "\n numV3KeysSkipped: " << result.numV3KeysSkipped()
|
||||
<< "\n imports:\n";
|
||||
const std::vector<Import> imp = result.imports();
|
||||
std::copy(imp.begin(), imp.end(),
|
||||
std::ostream_iterator<Import>(os, "\n"));
|
||||
}
|
||||
return os << ')';
|
||||
}
|
||||
|
||||
std::ostream &GpgME::operator<<(std::ostream &os, const GpgME::Import &imp)
|
||||
{
|
||||
os << "GpgME::Import(";
|
||||
if (!imp.isNull()) {
|
||||
os << "\n fpr: " << (imp.fingerprint() ? imp.fingerprint() : "null")
|
||||
<< "\n status: " << imp.status()
|
||||
<< "\n err: " << imp.error();
|
||||
}
|
||||
return os << ')';
|
||||
}
|
||||
|
@ -47,7 +47,6 @@ public:
|
||||
ImportResult(gpgme_ctx_t ctx, const Error &error);
|
||||
explicit ImportResult(const Error &error);
|
||||
|
||||
ImportResult(const ImportResult &other) = default;
|
||||
const ImportResult &operator=(ImportResult other)
|
||||
{
|
||||
swap(other);
|
||||
@ -61,16 +60,6 @@ public:
|
||||
swap(this->d, other.d);
|
||||
}
|
||||
|
||||
/**
|
||||
* Merges the result @p other into this result (and all of its copies).
|
||||
*
|
||||
* @note The merge algorithm assumes that @p other is the result of an
|
||||
* import that was performed after the import of this result.
|
||||
* @note Some numbers cannot be consolidated reliably, e.g. the number of
|
||||
* keys without user ID.
|
||||
*/
|
||||
void mergeWith(const ImportResult &other);
|
||||
|
||||
bool isNull() const;
|
||||
|
||||
int numConsidered() const;
|
||||
@ -107,7 +96,6 @@ class GPGMEPP_EXPORT Import
|
||||
public:
|
||||
Import();
|
||||
|
||||
Import(const Import &other) = default;
|
||||
const Import &operator=(Import other)
|
||||
{
|
||||
swap(other);
|
||||
@ -141,10 +129,7 @@ private:
|
||||
unsigned int idx;
|
||||
};
|
||||
|
||||
GPGMEPP_EXPORT std::ostream &operator<<(std::ostream &os, const ImportResult &irs);
|
||||
GPGMEPP_EXPORT std::ostream &operator<<(std::ostream &os, const Import &imp);
|
||||
|
||||
} // namespace GpgME
|
||||
}
|
||||
|
||||
GPGMEPP_MAKE_STD_SWAP_SPECIALIZATION(ImportResult)
|
||||
GPGMEPP_MAKE_STD_SWAP_SPECIALIZATION(Import)
|
||||
|
@ -26,7 +26,7 @@
|
||||
#ifndef __GPGMEPP_INTERFACES_ASSUANTRANSACTION_H__
|
||||
#define __GPGMEPP_INTERFACES_ASSUANTRANSACTION_H__
|
||||
|
||||
#include "../gpgmepp_export.h"
|
||||
#include "gpgmepp_export.h"
|
||||
|
||||
#include <stddef.h>
|
||||
|
||||
|
@ -27,7 +27,7 @@
|
||||
|
||||
#include <sys/types.h>
|
||||
|
||||
#include "../gpgmepp_export.h"
|
||||
#include "gpgmepp_export.h"
|
||||
|
||||
#include <gpg-error.h>
|
||||
|
||||
|
@ -29,13 +29,11 @@
|
||||
#include "util.h"
|
||||
#include "tofuinfo.h"
|
||||
#include "context.h"
|
||||
#include "engineinfo.h"
|
||||
|
||||
#include <gpgme.h>
|
||||
|
||||
#include <string.h>
|
||||
#include <strings.h>
|
||||
#include <cassert>
|
||||
#include <istream>
|
||||
#include <iterator>
|
||||
|
||||
@ -122,37 +120,6 @@ std::vector<Subkey> Key::subkeys() const
|
||||
return v;
|
||||
}
|
||||
|
||||
RevocationKey Key::revocationKey(unsigned int index) const
|
||||
{
|
||||
return RevocationKey(key, index);
|
||||
}
|
||||
|
||||
unsigned int Key::numRevocationKeys() const
|
||||
{
|
||||
if (!key) {
|
||||
return 0;
|
||||
}
|
||||
unsigned int count = 0;
|
||||
for (auto revkey = key->revocation_keys; revkey; revkey = revkey->next) {
|
||||
++count;
|
||||
}
|
||||
return count;
|
||||
}
|
||||
|
||||
std::vector<RevocationKey> Key::revocationKeys() const
|
||||
{
|
||||
if (!key) {
|
||||
return std::vector<RevocationKey>();
|
||||
}
|
||||
|
||||
std::vector<RevocationKey> v;
|
||||
v.reserve(numRevocationKeys());
|
||||
for (auto revkey = key->revocation_keys; revkey; revkey = revkey->next) {
|
||||
v.push_back(RevocationKey(key, revkey));
|
||||
}
|
||||
return v;
|
||||
}
|
||||
|
||||
Key::OwnerTrust Key::ownerTrust() const
|
||||
{
|
||||
if (!key) {
|
||||
@ -239,12 +206,17 @@ bool Key::canEncrypt() const
|
||||
|
||||
bool Key::canSign() const
|
||||
{
|
||||
return key && key->can_sign;
|
||||
#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 canSign();
|
||||
return key && key->can_sign;
|
||||
}
|
||||
|
||||
bool Key::canCertify() const
|
||||
@ -278,26 +250,6 @@ bool Key::isDeVs() const
|
||||
return true;
|
||||
}
|
||||
|
||||
bool Key::hasCertify() const
|
||||
{
|
||||
return key && key->has_certify;
|
||||
}
|
||||
|
||||
bool Key::hasSign() const
|
||||
{
|
||||
return key && key->has_sign;
|
||||
}
|
||||
|
||||
bool Key::hasEncrypt() const
|
||||
{
|
||||
return key && key->has_encrypt;
|
||||
}
|
||||
|
||||
bool Key::hasAuthenticate() const
|
||||
{
|
||||
return key && key->has_authenticate;
|
||||
}
|
||||
|
||||
const char *Key::issuerSerial() const
|
||||
{
|
||||
return key ? key->issuer_serial : nullptr ;
|
||||
@ -385,10 +337,6 @@ const Key &Key::mergeWith(const Key &other)
|
||||
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;
|
||||
mysk->secret |= hissk->secret;
|
||||
if (hissk->keygrip && !mysk->keygrip) {
|
||||
mysk->keygrip = strdup(hissk->keygrip);
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
@ -410,25 +358,20 @@ void Key::update()
|
||||
KeyListMode::Signatures |
|
||||
KeyListMode::SignatureNotations |
|
||||
KeyListMode::Validate |
|
||||
KeyListMode::WithTofu |
|
||||
KeyListMode::WithKeygrip |
|
||||
KeyListMode::WithSecret);
|
||||
KeyListMode::WithTofu);
|
||||
Error err;
|
||||
Key newKey;
|
||||
if (GpgME::engineInfo(GpgME::GpgEngine).engineVersion() < "2.1.0") {
|
||||
newKey = ctx->key(primaryFingerprint(), err, true);
|
||||
// Not secret so we get the information from the pubring.
|
||||
if (newKey.isNull()) {
|
||||
newKey = ctx->key(primaryFingerprint(), err, false);
|
||||
}
|
||||
} else {
|
||||
auto newKey = ctx->key(primaryFingerprint(), err, true);
|
||||
// Not secret so we get the information from the pubring.
|
||||
if (newKey.isNull())
|
||||
{
|
||||
newKey = ctx->key(primaryFingerprint(), err, false);
|
||||
}
|
||||
}
|
||||
delete ctx;
|
||||
if (err) {
|
||||
return;
|
||||
}
|
||||
swap(newKey);
|
||||
return;
|
||||
}
|
||||
|
||||
// static
|
||||
@ -458,7 +401,7 @@ Key Key::locate(const char *mbox)
|
||||
//
|
||||
//
|
||||
|
||||
static gpgme_sub_key_t find_subkey(const shared_gpgme_key_t &key, unsigned int idx)
|
||||
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) {
|
||||
@ -470,7 +413,7 @@ static gpgme_sub_key_t find_subkey(const shared_gpgme_key_t &key, unsigned int i
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
static gpgme_sub_key_t verify_subkey(const shared_gpgme_key_t &key, gpgme_sub_key_t subkey)
|
||||
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) {
|
||||
@ -561,21 +504,6 @@ bool Subkey::canAuthenticate() const
|
||||
return subkey && subkey->can_authenticate;
|
||||
}
|
||||
|
||||
bool Subkey::canRenc() const
|
||||
{
|
||||
return subkey && subkey->can_renc;
|
||||
}
|
||||
|
||||
bool Subkey::canTimestamp() const
|
||||
{
|
||||
return subkey && subkey->can_timestamp;
|
||||
}
|
||||
|
||||
bool Subkey::isGroupOwned() const
|
||||
{
|
||||
return subkey && subkey->is_group_owned;
|
||||
}
|
||||
|
||||
bool Subkey::isQualified() const
|
||||
{
|
||||
return subkey && subkey->is_qualified;
|
||||
@ -652,7 +580,7 @@ bool Subkey::isDisabled() const
|
||||
//
|
||||
//
|
||||
|
||||
static gpgme_user_id_t find_uid(const shared_gpgme_key_t &key, unsigned int idx)
|
||||
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) {
|
||||
@ -664,7 +592,7 @@ static gpgme_user_id_t find_uid(const shared_gpgme_key_t &key, unsigned int idx)
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
static gpgme_user_id_t verify_uid(const shared_gpgme_key_t &key, gpgme_user_id_t uid)
|
||||
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) {
|
||||
@ -746,11 +674,6 @@ const char *UserID::comment() const
|
||||
return uid ? uid->comment : nullptr ;
|
||||
}
|
||||
|
||||
const char *UserID::uidhash() const
|
||||
{
|
||||
return uid ? uid->uidhash : nullptr ;
|
||||
}
|
||||
|
||||
UserID::Validity UserID::validity() const
|
||||
{
|
||||
if (!uid) {
|
||||
@ -801,83 +724,13 @@ TofuInfo UserID::tofuInfo() const
|
||||
return TofuInfo(uid->tofu);
|
||||
}
|
||||
|
||||
static gpgme_key_sig_t find_last_valid_sig_for_keyid (gpgme_user_id_t uid,
|
||||
const char *keyid)
|
||||
{
|
||||
if (!keyid) {
|
||||
return nullptr;
|
||||
}
|
||||
gpgme_key_sig_t ret = NULL;
|
||||
for (gpgme_key_sig_t s = uid->signatures ; s ; s = s->next) {
|
||||
if (s->keyid && !strcmp(keyid, s->keyid)) {
|
||||
if (!s->expired && !s->revoked && !s->invalid && !s->status) {
|
||||
if (!ret) {
|
||||
ret = s;
|
||||
} else if (ret && ret->timestamp <= s->timestamp) {
|
||||
/* Equals because when the timestamps are the same we prefer
|
||||
the last in the list */
|
||||
ret = s;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
const char *UserID::remark(const Key &remarker, Error &err) const
|
||||
{
|
||||
if (!uid || remarker.isNull()) {
|
||||
err = Error::fromCode(GPG_ERR_GENERAL);
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
if (key->protocol != GPGME_PROTOCOL_OpenPGP) {
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
if (!(key->keylist_mode & GPGME_KEYLIST_MODE_SIG_NOTATIONS) ||
|
||||
!(key->keylist_mode & GPGME_KEYLIST_MODE_SIGS)) {
|
||||
err = Error::fromCode(GPG_ERR_NO_DATA);
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
gpgme_key_sig_t s = find_last_valid_sig_for_keyid(uid, remarker.keyID());
|
||||
|
||||
if (!s) {
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
for (gpgme_sig_notation_t n = s->notations; n ; n = n->next) {
|
||||
if (n->name && !strcmp(n->name, "rem@gnupg.org")) {
|
||||
return n->value;
|
||||
}
|
||||
}
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
std::vector<std::string> UserID::remarks(std::vector<Key> keys, Error &err) const
|
||||
{
|
||||
std::vector<std::string> ret;
|
||||
|
||||
for (const auto &key: keys) {
|
||||
const char *rem = remark(key, err);
|
||||
if (err) {
|
||||
return ret;
|
||||
}
|
||||
if (rem) {
|
||||
ret.push_back(rem);
|
||||
}
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
//
|
||||
//
|
||||
// class Signature
|
||||
//
|
||||
//
|
||||
|
||||
static gpgme_key_sig_t find_signature(gpgme_user_id_t uid, unsigned int idx)
|
||||
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) {
|
||||
@ -889,7 +742,7 @@ static gpgme_key_sig_t find_signature(gpgme_user_id_t uid, unsigned int idx)
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
static gpgme_key_sig_t verify_signature(gpgme_user_id_t uid, gpgme_key_sig_t sig)
|
||||
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) {
|
||||
@ -901,82 +754,18 @@ static gpgme_key_sig_t verify_signature(gpgme_user_id_t uid, gpgme_key_sig_t sig
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
static int signature_index(gpgme_user_id_t uid, gpgme_key_sig_t sig)
|
||||
{
|
||||
if (uid) {
|
||||
int i = 0;
|
||||
for (gpgme_key_sig_t s = uid->signatures ; s ; s = s->next, ++i) {
|
||||
if (s == sig) {
|
||||
return i;
|
||||
}
|
||||
}
|
||||
}
|
||||
return -1;
|
||||
}
|
||||
|
||||
UserID::Signature::Signature() : key(), uid(nullptr), sig(nullptr) {}
|
||||
|
||||
UserID::Signature::Signature(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))
|
||||
{
|
||||
}
|
||||
|
||||
bool UserID::Signature::operator<(const Signature &other)
|
||||
{
|
||||
// kept for binary compatibility
|
||||
return static_cast<const UserID::Signature *>(this)->operator<(other);
|
||||
}
|
||||
|
||||
bool UserID::Signature::operator<(const Signature &other) const
|
||||
{
|
||||
// based on cmp_signodes() in g10/keylist.c
|
||||
|
||||
// both signatures must belong to the same user ID
|
||||
assert(uid == other.uid);
|
||||
|
||||
// self-signatures are ordered first
|
||||
const char *primaryKeyId = parent().parent().keyID();
|
||||
const bool thisIsSelfSignature = strcmp(signerKeyID(), primaryKeyId) == 0;
|
||||
const bool otherIsSelfSignature = strcmp(other.signerKeyID(), primaryKeyId) == 0;
|
||||
if (thisIsSelfSignature && !otherIsSelfSignature) {
|
||||
return true;
|
||||
}
|
||||
if (otherIsSelfSignature && !thisIsSelfSignature) {
|
||||
return false;
|
||||
}
|
||||
|
||||
// then sort by signer key ID (which are or course the same for self-sigs)
|
||||
const int keyIdComparison = strcmp(signerKeyID(), other.signerKeyID());
|
||||
if (keyIdComparison < 0) {
|
||||
return true;
|
||||
}
|
||||
if (keyIdComparison > 0) {
|
||||
return false;
|
||||
}
|
||||
|
||||
// followed by creation time
|
||||
if (creationTime() < other.creationTime()) {
|
||||
return true;
|
||||
}
|
||||
if (creationTime() > other.creationTime()) {
|
||||
return false;
|
||||
}
|
||||
|
||||
// followed by the class in a way that a rev comes first
|
||||
if (certClass() < other.certClass()) {
|
||||
return true;
|
||||
}
|
||||
if (certClass() > other.certClass()) {
|
||||
return false;
|
||||
}
|
||||
|
||||
// to make the sort stable we compare the indexes of the signatures as last resort
|
||||
return signature_index(uid, sig) < signature_index(uid, other.sig);
|
||||
}
|
||||
|
||||
UserID UserID::Signature::parent() const
|
||||
@ -1144,29 +933,6 @@ const char *UserID::Signature::policyURL() const
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
bool UserID::Signature::isTrustSignature() const
|
||||
{
|
||||
return sig && sig->trust_depth > 0;
|
||||
}
|
||||
|
||||
TrustSignatureTrust UserID::Signature::trustValue() const
|
||||
{
|
||||
if (!sig || !isTrustSignature()) {
|
||||
return TrustSignatureTrust::None;
|
||||
}
|
||||
return sig->trust_value >= 120 ? TrustSignatureTrust::Complete : TrustSignatureTrust::Partial;
|
||||
}
|
||||
|
||||
unsigned int UserID::Signature::trustDepth() const
|
||||
{
|
||||
return sig ? sig->trust_depth : 0;
|
||||
}
|
||||
|
||||
const char *UserID::Signature::trustScope() const
|
||||
{
|
||||
return sig ? sig->trust_scope : nullptr;
|
||||
}
|
||||
|
||||
std::string UserID::addrSpecFromString(const char *userid)
|
||||
{
|
||||
if (!userid) {
|
||||
@ -1287,68 +1053,6 @@ bool UserID::Signature::isBad() const
|
||||
return isNull() || isExpired() || isInvalid();
|
||||
}
|
||||
|
||||
//
|
||||
//
|
||||
// class RevocationKey
|
||||
//
|
||||
//
|
||||
|
||||
static gpgme_revocation_key_t find_revkey(const shared_gpgme_key_t &key, unsigned int idx)
|
||||
{
|
||||
if (key) {
|
||||
for (gpgme_revocation_key_t s = key->revocation_keys; s; s = s->next, --idx) {
|
||||
if (idx == 0) {
|
||||
return s;
|
||||
}
|
||||
}
|
||||
}
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
static gpgme_revocation_key_t verify_revkey(const shared_gpgme_key_t &key, gpgme_revocation_key_t revkey)
|
||||
{
|
||||
if (key) {
|
||||
for (gpgme_revocation_key_t s = key->revocation_keys; s; s = s->next) {
|
||||
if (s == revkey) {
|
||||
return revkey;
|
||||
}
|
||||
}
|
||||
}
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
RevocationKey::RevocationKey() : key(), revkey(nullptr) {}
|
||||
|
||||
RevocationKey::RevocationKey(const shared_gpgme_key_t &k, unsigned int idx)
|
||||
: key(k), revkey(find_revkey(k, idx))
|
||||
{
|
||||
}
|
||||
|
||||
RevocationKey::RevocationKey(const shared_gpgme_key_t &k, gpgme_revocation_key_t sk)
|
||||
: key(k), revkey(verify_revkey(k, sk))
|
||||
{
|
||||
}
|
||||
|
||||
Key RevocationKey::parent() const
|
||||
{
|
||||
return Key(key);
|
||||
}
|
||||
|
||||
const char *RevocationKey::fingerprint() const
|
||||
{
|
||||
return revkey ? revkey->fpr : nullptr;
|
||||
}
|
||||
|
||||
bool RevocationKey::isSensitive() const
|
||||
{
|
||||
return revkey ? revkey->sensitive : false;
|
||||
}
|
||||
|
||||
int RevocationKey::algorithm() const
|
||||
{
|
||||
return revkey ? revkey->pubkey_algo : 0;
|
||||
}
|
||||
|
||||
std::ostream &operator<<(std::ostream &os, const UserID &uid)
|
||||
{
|
||||
os << "GpgME::UserID(";
|
||||
@ -1368,34 +1072,6 @@ std::ostream &operator<<(std::ostream &os, const UserID &uid)
|
||||
return os << ')';
|
||||
}
|
||||
|
||||
std::ostream &operator<<(std::ostream &os, const Subkey &subkey)
|
||||
{
|
||||
os << "GpgME::Subkey(";
|
||||
if (!subkey.isNull()) {
|
||||
os << "\n fingerprint: " << protect(subkey.fingerprint())
|
||||
<< "\n keyGrip: " << protect(subkey.keyGrip())
|
||||
<< "\n creationTime: " << subkey.creationTime()
|
||||
<< "\n expirationTime:" << subkey.expirationTime()
|
||||
<< "\n isRevoked: " << subkey.isRevoked()
|
||||
<< "\n isExpired: " << subkey.isExpired()
|
||||
<< "\n isInvalid: " << subkey.isInvalid()
|
||||
<< "\n isDisabled: " << subkey.isDisabled()
|
||||
<< "\n canSign: " << subkey.canSign()
|
||||
<< "\n canEncrypt: " << subkey.canEncrypt()
|
||||
<< "\n canCertify: " << subkey.canCertify()
|
||||
<< "\n canAuth: " << subkey.canAuthenticate()
|
||||
<< "\n canRenc: " << subkey.canRenc()
|
||||
<< "\n canTimestanp: " << subkey.canTimestamp()
|
||||
<< "\n isSecret: " << subkey.isSecret()
|
||||
<< "\n isGroupOwned: " << subkey.isGroupOwned()
|
||||
<< "\n isQualified: " << subkey.isQualified()
|
||||
<< "\n isDeVs: " << subkey.isDeVs()
|
||||
<< "\n isCardKey: " << subkey.isCardKey()
|
||||
<< "\n cardSerialNumber:" << protect(subkey.cardSerialNumber());
|
||||
}
|
||||
return os << ')';
|
||||
}
|
||||
|
||||
std::ostream &operator<<(std::ostream &os, const Key &key)
|
||||
{
|
||||
os << "GpgME::Key(";
|
||||
@ -1405,7 +1081,7 @@ std::ostream &operator<<(std::ostream &os, const Key &key)
|
||||
<< "\n issuer: " << protect(key.issuerName())
|
||||
<< "\n fingerprint:" << protect(key.primaryFingerprint())
|
||||
<< "\n listmode: " << key.keyListMode()
|
||||
<< "\n canSign: " << key.canSign()
|
||||
<< "\n canSign: " << key.canReallySign()
|
||||
<< "\n canEncrypt: " << key.canEncrypt()
|
||||
<< "\n canCertify: " << key.canCertify()
|
||||
<< "\n canAuth: " << key.canAuthenticate()
|
||||
@ -1415,23 +1091,6 @@ std::ostream &operator<<(std::ostream &os, const Key &key)
|
||||
const std::vector<UserID> uids = key.userIDs();
|
||||
std::copy(uids.begin(), uids.end(),
|
||||
std::ostream_iterator<UserID>(os, "\n"));
|
||||
const std::vector<Subkey> subkeys = key.subkeys();
|
||||
std::copy(subkeys.begin(), subkeys.end(),
|
||||
std::ostream_iterator<Subkey>(os, "\n"));
|
||||
os << " revocationKeys:\n";
|
||||
const std::vector<RevocationKey> revkeys = key.revocationKeys();
|
||||
std::copy(revkeys.begin(), revkeys.end(),
|
||||
std::ostream_iterator<RevocationKey>(os, "\n"));
|
||||
}
|
||||
return os << ')';
|
||||
}
|
||||
|
||||
std::ostream &operator<<(std::ostream &os, const RevocationKey &revkey)
|
||||
{
|
||||
os << "GpgME::RevocationKey(";
|
||||
if (!revkey.isNull()) {
|
||||
os << "\n fingerprint: " << protect(revkey.fingerprint())
|
||||
<< "\n isSensitive: " << revkey.isSensitive();
|
||||
}
|
||||
return os << ')';
|
||||
}
|
||||
|
@ -44,16 +44,9 @@ class Context;
|
||||
class Subkey;
|
||||
class UserID;
|
||||
class TofuInfo;
|
||||
class RevocationKey;
|
||||
|
||||
typedef std::shared_ptr< std::remove_pointer<gpgme_key_t>::type > shared_gpgme_key_t;
|
||||
|
||||
enum class TrustSignatureTrust : char {
|
||||
None = 0,
|
||||
Partial,
|
||||
Complete,
|
||||
};
|
||||
|
||||
//
|
||||
// class Key
|
||||
//
|
||||
@ -72,7 +65,6 @@ public:
|
||||
|
||||
static const Null null;
|
||||
|
||||
Key(const Key &other) = default;
|
||||
const Key &operator=(Key other)
|
||||
{
|
||||
swap(other);
|
||||
@ -101,10 +93,6 @@ public:
|
||||
std::vector<UserID> userIDs() const;
|
||||
std::vector<Subkey> subkeys() const;
|
||||
|
||||
RevocationKey revocationKey(unsigned int index) const;
|
||||
unsigned int numRevocationKeys() const;
|
||||
std::vector<RevocationKey> revocationKeys() const;
|
||||
|
||||
bool isRevoked() const;
|
||||
bool isExpired() const;
|
||||
bool isDisabled() const;
|
||||
@ -114,31 +102,22 @@ public:
|
||||
* isDisabled || isInvalid */
|
||||
bool isBad() const;
|
||||
|
||||
/** Returns true, if the key can be used for encryption (i.e. it's not bad
|
||||
* and has an encryption subkey) or if the primary subkey can encrypt. */
|
||||
bool canEncrypt() const;
|
||||
/** Returns true, if the key can be used for signing (i.e. it's not bad
|
||||
* and has a signing subkey) or if the primary subkey can sign. */
|
||||
/*!
|
||||
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;
|
||||
GPGMEPP_DEPRECATED bool canReallySign() const;
|
||||
/** Returns true, if the key can be used for certification (i.e. it's not bad
|
||||
* and has a certification subkey) or if the primary subkey can certify. */
|
||||
bool canReallySign() const;
|
||||
bool canCertify() const;
|
||||
/** Returns true, if the key can be used for authentication (i.e. it's not bad
|
||||
* and has a authentication subkey) or if the primary subkey can authenticate. */
|
||||
bool canAuthenticate() const;
|
||||
bool isQualified() const;
|
||||
bool isDeVs() const;
|
||||
|
||||
/** Returns true, if the key has a certification subkey. */
|
||||
bool hasCertify() const;
|
||||
/** Returns true, if the key has a signing subkey. */
|
||||
bool hasSign() const;
|
||||
/** Returns true, if the key has an encryption subkey. */
|
||||
bool hasEncrypt() const;
|
||||
/** Returns true, if the key has an authentication subkey. */
|
||||
bool hasAuthenticate() const;
|
||||
|
||||
bool hasSecret() const;
|
||||
GPGMEPP_DEPRECATED bool isSecret() const
|
||||
{
|
||||
@ -243,7 +222,6 @@ public:
|
||||
Subkey(const shared_gpgme_key_t &key, gpgme_sub_key_t subkey);
|
||||
Subkey(const shared_gpgme_key_t &key, unsigned int idx);
|
||||
|
||||
Subkey(const Subkey &other) = default;
|
||||
const Subkey &operator=(Subkey other)
|
||||
{
|
||||
swap(other);
|
||||
@ -284,9 +262,6 @@ public:
|
||||
bool canSign() const;
|
||||
bool canCertify() const;
|
||||
bool canAuthenticate() const;
|
||||
bool canRenc() const;
|
||||
bool canTimestamp() const;
|
||||
bool isGroupOwned() const;
|
||||
bool isQualified() const;
|
||||
bool isDeVs() const;
|
||||
bool isCardKey() const;
|
||||
@ -360,7 +335,6 @@ public:
|
||||
UserID(const shared_gpgme_key_t &key, gpgme_user_id_t uid);
|
||||
UserID(const shared_gpgme_key_t &key, unsigned int idx);
|
||||
|
||||
UserID(const UserID &other) = default;
|
||||
const UserID &operator=(UserID other)
|
||||
{
|
||||
swap(other);
|
||||
@ -389,7 +363,6 @@ public:
|
||||
const char *name() const;
|
||||
const char *email() const;
|
||||
const char *comment() const;
|
||||
const char *uidhash() const;
|
||||
|
||||
enum Validity { Unknown = 0, Undefined = 1, Never = 2,
|
||||
Marginal = 3, Full = 4, Ultimate = 5
|
||||
@ -440,27 +413,6 @@ public:
|
||||
*
|
||||
* @returns the last update time. */
|
||||
time_t lastUpdate() const;
|
||||
|
||||
/*! Get a remark made by the key provided.
|
||||
* A remark is a signature notation on
|
||||
* this user id made by the key with the
|
||||
* name "rem@gnupg.org". Returns an error if the
|
||||
* parent key of this user id was not listed with the
|
||||
* keylist mode flags for signatures and signature notations.
|
||||
*
|
||||
* @param key The key for which comments should be searched.
|
||||
* @param error Set to GPG_ERR_NO_DATA if the keylist did
|
||||
* not include signature notations.
|
||||
*
|
||||
* @returns The value of the comment or NULL if none exists.
|
||||
**/
|
||||
const char *remark(const Key &key,
|
||||
Error &error) const;
|
||||
|
||||
/*! Get multiple remarks made by potentially multiple keys. */
|
||||
std::vector <std::string> remarks(std::vector<GpgME::Key> remarkers,
|
||||
Error &error) const;
|
||||
|
||||
private:
|
||||
shared_gpgme_key_t key;
|
||||
gpgme_user_id_t uid;
|
||||
@ -479,7 +431,6 @@ public:
|
||||
Signature(const shared_gpgme_key_t &key, gpgme_user_id_t uid, gpgme_key_sig_t sig);
|
||||
Signature(const shared_gpgme_key_t &key, gpgme_user_id_t uid, unsigned int idx);
|
||||
|
||||
Signature(const Signature &other) = default;
|
||||
const Signature &operator=(Signature other)
|
||||
{
|
||||
swap(other);
|
||||
@ -494,11 +445,6 @@ public:
|
||||
swap(this->sig, other.sig);
|
||||
}
|
||||
|
||||
/*! Defines a canonical sort order for signatures of the same user ID. */
|
||||
bool operator<(const Signature &other) const;
|
||||
|
||||
GPGMEPP_DEPRECATED bool operator<(const Signature &other);
|
||||
|
||||
bool isNull() const
|
||||
{
|
||||
return !sig || !uid || !key ;
|
||||
@ -541,64 +487,14 @@ public:
|
||||
GpgME::Notation notation(unsigned int idx) const;
|
||||
std::vector<GpgME::Notation> notations() const;
|
||||
|
||||
bool isTrustSignature() const;
|
||||
TrustSignatureTrust trustValue() const;
|
||||
unsigned int trustDepth() const;
|
||||
const char *trustScope() const;
|
||||
|
||||
private:
|
||||
shared_gpgme_key_t key;
|
||||
gpgme_user_id_t uid;
|
||||
gpgme_key_sig_t sig;
|
||||
};
|
||||
|
||||
//
|
||||
// class RevocationKey
|
||||
//
|
||||
|
||||
class GPGMEPP_EXPORT RevocationKey
|
||||
{
|
||||
public:
|
||||
RevocationKey();
|
||||
RevocationKey(const shared_gpgme_key_t &key, gpgme_revocation_key_t revkey);
|
||||
RevocationKey(const shared_gpgme_key_t &key, unsigned int idx);
|
||||
|
||||
// Rule of Zero
|
||||
|
||||
void swap(RevocationKey &other)
|
||||
{
|
||||
using std::swap;
|
||||
swap(this->key, other.key);
|
||||
swap(this->revkey, other.revkey);
|
||||
}
|
||||
|
||||
bool isNull() const
|
||||
{
|
||||
return !key || !revkey;
|
||||
}
|
||||
|
||||
Key parent() const;
|
||||
|
||||
const char *fingerprint() const;
|
||||
|
||||
bool isSensitive() const;
|
||||
|
||||
int algorithm() const;
|
||||
|
||||
private:
|
||||
shared_gpgme_key_t key;
|
||||
gpgme_revocation_key_t revkey;
|
||||
};
|
||||
|
||||
inline void swap(RevocationKey& v1, RevocationKey& v2)
|
||||
{
|
||||
v1.swap(v2);
|
||||
}
|
||||
|
||||
GPGMEPP_EXPORT std::ostream &operator<<(std::ostream &os, const UserID &uid);
|
||||
GPGMEPP_EXPORT std::ostream &operator<<(std::ostream &os, const Subkey &subkey);
|
||||
GPGMEPP_EXPORT std::ostream &operator<<(std::ostream &os, const Key &key);
|
||||
GPGMEPP_EXPORT std::ostream &operator<<(std::ostream &os, const RevocationKey &revkey);
|
||||
|
||||
} // namespace GpgME
|
||||
|
||||
|
@ -44,7 +44,6 @@ public:
|
||||
KeyGenerationResult(gpgme_ctx_t ctx, const Error &error);
|
||||
explicit KeyGenerationResult(const Error &err);
|
||||
|
||||
KeyGenerationResult(const KeyGenerationResult &other) = default;
|
||||
const KeyGenerationResult &operator=(KeyGenerationResult other)
|
||||
{
|
||||
swap(other);
|
||||
|
@ -45,7 +45,6 @@ public:
|
||||
explicit KeyListResult(const Error &err);
|
||||
KeyListResult(const Error &err, const _gpgme_op_keylist_result &res);
|
||||
|
||||
KeyListResult(const KeyListResult &other) = default;
|
||||
const KeyListResult &operator=(KeyListResult other)
|
||||
{
|
||||
swap(other);
|
||||
|
@ -44,7 +44,6 @@ public:
|
||||
Notation();
|
||||
explicit Notation(gpgme_sig_notation_t nota);
|
||||
|
||||
Notation(const Notation &other) = default;
|
||||
const Notation &operator=(Notation other)
|
||||
{
|
||||
swap(other);
|
||||
|
@ -50,14 +50,6 @@ public:
|
||||
{
|
||||
return mError;
|
||||
}
|
||||
/**
|
||||
* Replaces the error set during construction with \p error.
|
||||
* Use with care, e.g. to set a more suitable error.
|
||||
*/
|
||||
void setError(const Error &error)
|
||||
{
|
||||
mError = error;
|
||||
}
|
||||
|
||||
protected:
|
||||
Error mError;
|
||||
|
@ -31,6 +31,7 @@
|
||||
#include "data.h"
|
||||
#include "util.h"
|
||||
|
||||
#include <sstream>
|
||||
#include <assert.h>
|
||||
|
||||
using namespace GpgME;
|
||||
|
@ -25,7 +25,7 @@
|
||||
#ifndef __GPGMEPP_SCDGETINFOASSUANTRANSACTION_H__
|
||||
#define __GPGMEPP_SCDGETINFOASSUANTRANSACTION_H__
|
||||
|
||||
#include "interfaces/assuantransaction.h"
|
||||
#include <interfaces/assuantransaction.h>
|
||||
|
||||
#include <string>
|
||||
#include <vector>
|
||||
|
@ -199,8 +199,6 @@ GpgME::SignatureMode GpgME::CreatedSignature::mode() const
|
||||
case GPGME_SIG_MODE_NORMAL: return NormalSignatureMode;
|
||||
case GPGME_SIG_MODE_DETACH: return Detached;
|
||||
case GPGME_SIG_MODE_CLEAR: return Clearsigned;
|
||||
case GPGME_SIG_MODE_ARCHIVE: return SignArchive; // cannot happen
|
||||
case GPGME_SIG_MODE_FILE: return SignFile; // cannot happen
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -50,7 +50,6 @@ public:
|
||||
SigningResult(gpgme_ctx_t ctx, const Error &error);
|
||||
explicit SigningResult(const Error &err);
|
||||
|
||||
SigningResult(const SigningResult &other) = default;
|
||||
const SigningResult &operator=(SigningResult other)
|
||||
{
|
||||
swap(other);
|
||||
@ -87,7 +86,6 @@ class GPGMEPP_EXPORT InvalidSigningKey
|
||||
public:
|
||||
InvalidSigningKey();
|
||||
|
||||
InvalidSigningKey(const InvalidSigningKey &other) = default;
|
||||
const InvalidSigningKey &operator=(InvalidSigningKey other)
|
||||
{
|
||||
swap(other);
|
||||
@ -121,7 +119,6 @@ public:
|
||||
|
||||
CreatedSignature();
|
||||
|
||||
CreatedSignature(const CreatedSignature &other) = default;
|
||||
const CreatedSignature &operator=(CreatedSignature other)
|
||||
{
|
||||
swap(other);
|
||||
|
@ -1,67 +0,0 @@
|
||||
/*
|
||||
statusconsumerassuantransaction.cpp
|
||||
Copyright (c) 2020 g10 Code GmbH
|
||||
Software engineering by Ingo Klöcker <dev@ingo-kloecker.de>
|
||||
|
||||
This file is part of GPGME++.
|
||||
|
||||
GPGME++ is free software; you can redistribute it and/or
|
||||
modify it under the terms of the GNU Library General Public
|
||||
License as published by the Free Software Foundation; either
|
||||
version 2 of the License, or (at your option) any later version.
|
||||
|
||||
GPGME++ is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU Library General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU Library General Public License
|
||||
along with GPGME++; see the file COPYING.LIB. If not, write to the
|
||||
Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
|
||||
Boston, MA 02110-1301, USA.
|
||||
*/
|
||||
|
||||
#ifdef HAVE_CONFIG_H
|
||||
#include "config.h"
|
||||
#endif
|
||||
|
||||
#include "statusconsumerassuantransaction.h"
|
||||
|
||||
#include "data.h"
|
||||
#include "error.h"
|
||||
|
||||
#include "interfaces/statusconsumer.h"
|
||||
|
||||
using namespace GpgME;
|
||||
|
||||
StatusConsumerAssuanTransaction::StatusConsumerAssuanTransaction(StatusConsumer *statusConsumer)
|
||||
: AssuanTransaction()
|
||||
, m_consumer(statusConsumer)
|
||||
{
|
||||
}
|
||||
|
||||
StatusConsumerAssuanTransaction::~StatusConsumerAssuanTransaction()
|
||||
{
|
||||
}
|
||||
|
||||
Error StatusConsumerAssuanTransaction::data(const char *data, size_t datalen)
|
||||
{
|
||||
(void) data;
|
||||
(void) datalen;
|
||||
return Error();
|
||||
}
|
||||
|
||||
Data StatusConsumerAssuanTransaction::inquire(const char *name, const char *args, Error &err)
|
||||
{
|
||||
(void)name;
|
||||
(void)args;
|
||||
(void)err;
|
||||
return Data::null;
|
||||
}
|
||||
|
||||
Error StatusConsumerAssuanTransaction::status(const char *status, const char *args)
|
||||
{
|
||||
m_consumer->status(status, args);
|
||||
|
||||
return Error();
|
||||
}
|
@ -1,51 +0,0 @@
|
||||
/*
|
||||
statusconsumerassuantransaction.h - Assuan transaction that forwards status lines to a consumer
|
||||
Copyright (c) 2020 g10 Code GmbH
|
||||
Software engineering by Ingo Klöcker <dev@ingo-kloecker.de>
|
||||
|
||||
This file is part of GPGME++.
|
||||
|
||||
GPGME++ is free software; you can redistribute it and/or
|
||||
modify it under the terms of the GNU Library General Public
|
||||
License as published by the Free Software Foundation; either
|
||||
version 2 of the License, or (at your option) any later version.
|
||||
|
||||
GPGME++ is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU Library General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU Library General Public License
|
||||
along with GPGME++; see the file COPYING.LIB. If not, write to the
|
||||
Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
|
||||
Boston, MA 02110-1301, USA.
|
||||
*/
|
||||
|
||||
#ifndef __GPGMEPP_STATUSCONSUMERASSUANTRANSACTION_H__
|
||||
#define __GPGMEPP_STATUSCONSUMERASSUANTRANSACTION_H__
|
||||
|
||||
#include "interfaces/assuantransaction.h"
|
||||
|
||||
namespace GpgME
|
||||
{
|
||||
|
||||
class StatusConsumer;
|
||||
|
||||
class GPGMEPP_EXPORT StatusConsumerAssuanTransaction: public AssuanTransaction
|
||||
{
|
||||
public:
|
||||
explicit StatusConsumerAssuanTransaction(StatusConsumer *statusConsumer);
|
||||
~StatusConsumerAssuanTransaction();
|
||||
|
||||
private:
|
||||
Error data(const char *data, size_t datalen) override;
|
||||
Data inquire(const char *name, const char *args, Error &err) override;
|
||||
Error status(const char *status, const char *args) override;
|
||||
|
||||
private:
|
||||
StatusConsumer *m_consumer;
|
||||
};
|
||||
|
||||
} // namespace GpgME
|
||||
|
||||
#endif // __GPGMEPP_STATUSCONSUMERASSUANTRANSACTION_H__
|
@ -62,7 +62,6 @@ public:
|
||||
const char *iversion = NULL,
|
||||
Error *err = NULL);
|
||||
|
||||
SwdbResult(const SwdbResult &other) = default;
|
||||
const SwdbResult &operator=(SwdbResult other)
|
||||
{
|
||||
swap(other);
|
||||
|
@ -39,7 +39,6 @@ public:
|
||||
TofuInfo();
|
||||
explicit TofuInfo(gpgme_tofu_info_t info);
|
||||
|
||||
TofuInfo(const TofuInfo &other) = default;
|
||||
const TofuInfo &operator=(TofuInfo other)
|
||||
{
|
||||
swap(other);
|
||||
|
@ -27,7 +27,7 @@
|
||||
#define __GPGMEPP_TRUSTITEM_H__
|
||||
|
||||
#include "gpgmefw.h"
|
||||
#include "key.h"
|
||||
#include <key.h>
|
||||
#include "gpgmepp_export.h"
|
||||
|
||||
#include <algorithm>
|
||||
|
@ -1,10 +1,8 @@
|
||||
/*
|
||||
util.h - some internal helpers
|
||||
util.h - some inline helper functions
|
||||
Copyright (C) 2004 Klarälvdalens Datakonsult AB
|
||||
2016 Bundesamt für Sicherheit in der Informationstechnik
|
||||
Software engineering by Intevation GmbH
|
||||
Copyright (c) 2022 g10 Code GmbH
|
||||
Software engineering by Ingo Klöcker <dev@ingo-kloecker.de>
|
||||
|
||||
This file is part of GPGME++.
|
||||
|
||||
@ -74,30 +72,19 @@ static inline gpgme_keylist_mode_t add_to_gpgme_keylist_mode_t(unsigned int oldm
|
||||
if (newmodes & GpgME::SignatureNotations) {
|
||||
oldmode |= GPGME_KEYLIST_MODE_SIG_NOTATIONS;
|
||||
}
|
||||
if (newmodes & GpgME::Validate) {
|
||||
oldmode |= GPGME_KEYLIST_MODE_VALIDATE;
|
||||
}
|
||||
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;
|
||||
}
|
||||
if (newmodes & GpgME::WithKeygrip) {
|
||||
oldmode |= GPGME_KEYLIST_MODE_WITH_KEYGRIP;
|
||||
}
|
||||
if (newmodes & GpgME::WithSecret) {
|
||||
oldmode |= GPGME_KEYLIST_MODE_WITH_SECRET;
|
||||
}
|
||||
if (newmodes & GpgME::ForceExtern) {
|
||||
oldmode |= GPGME_KEYLIST_MODE_FORCE_EXTERN;
|
||||
}
|
||||
#ifndef NDEBUG
|
||||
if (newmodes & ~(GpgME::KeyListModeMask)) {
|
||||
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, Validate, Ephemeral, WithTofu, "
|
||||
//"WithKeygrip, WithSecret, ForceExtern, or a combination thereof!"
|
||||
//<< std::endl;
|
||||
//"Extern, Signatures, SignatureNotations, or Validate, or a combination thereof!" << std::endl;
|
||||
}
|
||||
#endif
|
||||
return static_cast<gpgme_keylist_mode_t>(oldmode);
|
||||
@ -118,35 +105,19 @@ static inline unsigned int convert_from_gpgme_keylist_mode_t(unsigned int mode)
|
||||
if (mode & GPGME_KEYLIST_MODE_SIG_NOTATIONS) {
|
||||
result |= GpgME::SignatureNotations;
|
||||
}
|
||||
if (mode & GPGME_KEYLIST_MODE_WITH_SECRET) {
|
||||
result |= GpgME::WithSecret;
|
||||
}
|
||||
if (mode & GPGME_KEYLIST_MODE_WITH_TOFU) {
|
||||
result |= GpgME::WithTofu;
|
||||
}
|
||||
if (mode & GPGME_KEYLIST_MODE_WITH_KEYGRIP) {
|
||||
result |= GpgME::WithKeygrip;
|
||||
}
|
||||
if (mode & GPGME_KEYLIST_MODE_EPHEMERAL) {
|
||||
result |= GpgME::Ephemeral;
|
||||
}
|
||||
if (mode & GPGME_KEYLIST_MODE_VALIDATE) {
|
||||
result |= GpgME::Validate;
|
||||
}
|
||||
if (mode & GPGME_KEYLIST_MODE_FORCE_EXTERN) {
|
||||
result |= GpgME::ForceExtern;
|
||||
}
|
||||
#ifndef NDEBUG
|
||||
if (mode & ~(GPGME_KEYLIST_MODE_LOCAL |
|
||||
GPGME_KEYLIST_MODE_EXTERN |
|
||||
GPGME_KEYLIST_MODE_SIGS |
|
||||
GPGME_KEYLIST_MODE_SIG_NOTATIONS |
|
||||
GPGME_KEYLIST_MODE_WITH_SECRET |
|
||||
GPGME_KEYLIST_MODE_WITH_TOFU |
|
||||
GPGME_KEYLIST_MODE_WITH_KEYGRIP |
|
||||
GPGME_KEYLIST_MODE_EPHEMERAL |
|
||||
GPGME_KEYLIST_MODE_VALIDATE |
|
||||
GPGME_KEYLIST_MODE_FORCE_EXTERN)) {
|
||||
GPGME_KEYLIST_MODE_SIGS)) {
|
||||
//std::cerr << "GpgME: WARNING: gpgme_get_keylist_mode() returned an unknown flag!" << std::endl;
|
||||
}
|
||||
#endif // NDEBUG
|
||||
@ -177,38 +148,4 @@ static inline gpgme_sig_notation_flags_t add_to_gpgme_sig_notation_flags_t(unsi
|
||||
return static_cast<gpgme_sig_notation_flags_t>(result);
|
||||
}
|
||||
|
||||
static inline std::vector<std::string> split(const std::string &text, char delimiter)
|
||||
{
|
||||
std::vector<std::string> result;
|
||||
if (!text.empty()) {
|
||||
std::istringstream stream{text};
|
||||
std::string line;
|
||||
while (std::getline(stream, line, delimiter)) {
|
||||
result.push_back(line);
|
||||
}
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
/**
|
||||
* Adapter for passing a vector of strings as NULL-terminated array of
|
||||
* const char* to the C-interface of gpgme.
|
||||
*/
|
||||
class StringsToCStrings
|
||||
{
|
||||
public:
|
||||
explicit StringsToCStrings(const std::vector<std::string> &v);
|
||||
~StringsToCStrings() = default;
|
||||
|
||||
StringsToCStrings(const StringsToCStrings &) = delete;
|
||||
StringsToCStrings &operator=(const StringsToCStrings &) = delete;
|
||||
StringsToCStrings(StringsToCStrings &&) = delete;
|
||||
StringsToCStrings &operator=(StringsToCStrings &&) = delete;
|
||||
|
||||
const char **c_strs() const;
|
||||
private:
|
||||
const std::vector<std::string> m_strings;
|
||||
mutable std::vector<const char *> m_cstrings;
|
||||
};
|
||||
|
||||
#endif // __GPGMEPP_UTIL_H__
|
||||
|
@ -413,8 +413,7 @@ GpgME::Key GpgME::Signature::key(bool search, bool update) const
|
||||
KeyListMode::Signatures |
|
||||
KeyListMode::SignatureNotations |
|
||||
KeyListMode::Validate |
|
||||
KeyListMode::WithTofu |
|
||||
KeyListMode::WithKeygrip);
|
||||
KeyListMode::WithTofu);
|
||||
Error e;
|
||||
ret = d->keys[idx] = ctx->key(fingerprint(), e, false);
|
||||
delete ctx;
|
||||
@ -544,41 +543,32 @@ std::ostream &GpgME::operator<<(std::ostream &os, const VerificationResult &resu
|
||||
|
||||
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(";
|
||||
switch (pkaStatus) {
|
||||
#define OUTPUT( x ) case GpgME::Signature:: x: os << #x; break
|
||||
OUTPUT(UnknownPKAStatus);
|
||||
OUTPUT(PKAVerificationFailed);
|
||||
OUTPUT(PKAVerificationSucceeded);
|
||||
OUTPUT(UnknownPKAStatus);
|
||||
OUTPUT(PKAVerificationFailed);
|
||||
OUTPUT(PKAVerificationSucceeded);
|
||||
#undef OUTPUT
|
||||
default:
|
||||
os << "??? (" << static_cast<int>(pkaStatus) << ')';
|
||||
break;
|
||||
}
|
||||
return os << ')';
|
||||
}
|
||||
|
||||
std::ostream &GpgME::operator<<(std::ostream &os, Signature::Summary summary)
|
||||
{
|
||||
os << "GpgME::Signature::Summary(";
|
||||
if (summary == Signature::None) {
|
||||
os << "None";
|
||||
} else {
|
||||
#define OUTPUT( x ) if ( !(summary & (GpgME::Signature:: x)) ) {} else do { os << #x " "; } while(0)
|
||||
OUTPUT(Valid);
|
||||
OUTPUT(Green);
|
||||
OUTPUT(Red);
|
||||
OUTPUT(KeyRevoked);
|
||||
OUTPUT(KeyExpired);
|
||||
OUTPUT(SigExpired);
|
||||
OUTPUT(KeyMissing);
|
||||
OUTPUT(CrlMissing);
|
||||
OUTPUT(CrlTooOld);
|
||||
OUTPUT(BadPolicy);
|
||||
OUTPUT(SysError);
|
||||
OUTPUT(TofuConflict);
|
||||
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 << ')';
|
||||
}
|
||||
|
||||
@ -612,14 +602,10 @@ std::ostream &GpgME::operator<<(std::ostream &os, const Signature &sig)
|
||||
std::ostream &GpgME::operator<<(std::ostream &os, Notation::Flags flags)
|
||||
{
|
||||
os << "GpgME::Notation::Flags(";
|
||||
if (flags == Notation::NoFlags) {
|
||||
os << "NoFlags";
|
||||
} else {
|
||||
#define OUTPUT( x ) if ( !(flags & (GpgME::Notation:: x)) ) {} else do { os << #x " "; } while(0)
|
||||
OUTPUT(HumanReadable);
|
||||
OUTPUT(Critical);
|
||||
OUTPUT(HumanReadable);
|
||||
OUTPUT(Critical);
|
||||
#undef OUTPUT
|
||||
}
|
||||
return os << ')';
|
||||
}
|
||||
|
||||
|
@ -52,7 +52,6 @@ public:
|
||||
VerificationResult(gpgme_ctx_t ctx, const Error &error);
|
||||
explicit VerificationResult(const Error &err);
|
||||
|
||||
VerificationResult(const VerificationResult &other) = default;
|
||||
const VerificationResult &operator=(VerificationResult other)
|
||||
{
|
||||
swap(other);
|
||||
@ -91,7 +90,6 @@ public:
|
||||
|
||||
Signature();
|
||||
|
||||
Signature(const Signature &other) = default;
|
||||
const Signature &operator=(Signature other)
|
||||
{
|
||||
swap(other);
|
||||
|
@ -45,7 +45,6 @@ public:
|
||||
VfsMountResult(gpgme_ctx_t ctx, const Error &error, const Error &opError);
|
||||
explicit VfsMountResult(const Error &err);
|
||||
|
||||
VfsMountResult(const VfsMountResult &other) = default;
|
||||
const VfsMountResult &operator=(VfsMountResult other)
|
||||
{
|
||||
swap(other);
|
||||
|
@ -22,7 +22,7 @@ AM_LDFLAGS = -no-install
|
||||
|
||||
LDADD = ../../cpp/src/libgpgmepp.la \
|
||||
../../../src/libgpgme.la @GPG_ERROR_LIBS@ \
|
||||
@LDADD_FOR_TESTS_KLUDGE@ -lstdc++
|
||||
-lstdc++
|
||||
|
||||
AM_CPPFLAGS = -I$(top_srcdir)/lang/cpp/src -I$(top_builddir)/src \
|
||||
@GPG_ERROR_CFLAGS@ @GPG_ERROR_CFLAGS@ \
|
||||
@ -32,14 +32,5 @@ AM_CPPFLAGS = -I$(top_srcdir)/lang/cpp/src -I$(top_builddir)/src \
|
||||
run_getkey_SOURCES = run-getkey.cpp
|
||||
run_keylist_SOURCES = run-keylist.cpp
|
||||
run_verify_SOURCES = run-verify.cpp
|
||||
if !HAVE_W32_SYSTEM
|
||||
run_wkdlookup_SOURCES = run-wkdlookup.cpp
|
||||
endif
|
||||
|
||||
if HAVE_W32_SYSTEM
|
||||
programs_unix =
|
||||
else
|
||||
programs_unix = run-wkdlookup
|
||||
endif
|
||||
|
||||
noinst_PROGRAMS = run-getkey run-keylist run-verify $(programs_unix)
|
||||
noinst_PROGRAMS = run-getkey run-keylist run-verify
|
||||
|
@ -60,8 +60,6 @@ show_usage (int ex)
|
||||
" --ephemeral use GPGME_KEYLIST_MODE_EPHEMERAL\n"
|
||||
" --validate use GPGME_KEYLIST_MODE_VALIDATE\n"
|
||||
" --locate use GPGME_KEYLIST_MODE_LOCATE\n"
|
||||
" --force-extern use GPGME_KEYLIST_MODE_FORCE_EXTERN\n"
|
||||
" --locate-external use GPGME_KEYLIST_MODE_LOCATE_EXTERNAL\n"
|
||||
, stderr);
|
||||
exit (ex);
|
||||
}
|
||||
@ -118,12 +116,6 @@ main (int argc, char **argv)
|
||||
} else if (!strcmp (*argv, "--locate")) {
|
||||
argc--; argv++;
|
||||
mode |= KeyListMode::Locate;
|
||||
} else if (!strcmp (*argv, "--force-extern")) {
|
||||
argc--; argv++;
|
||||
mode |= KeyListMode::ForceExtern;
|
||||
} else if (!strcmp (*argv, "--locate-external")) {
|
||||
argc--; argv++;
|
||||
mode |= KeyListMode::LocateExternal;
|
||||
} else if (!strncmp (*argv, "--", 2)) {
|
||||
show_usage (1);
|
||||
}
|
||||
@ -140,17 +132,11 @@ main (int argc, char **argv)
|
||||
return -1;
|
||||
}
|
||||
ctx->setKeyListMode (mode);
|
||||
if (ctx->keyListMode() != mode) {
|
||||
// unfortunately, Context::setKeyListMode() does not return the error
|
||||
// returned by gpgme
|
||||
std::cerr << "Failed to set keylist mode. You may have used an invalid combination of options.";
|
||||
return -1;
|
||||
}
|
||||
Error err;
|
||||
const GpgME::Key key = ctx->key (*argv, err, only_secret);
|
||||
std::stringstream ss;
|
||||
|
||||
ss << "Key " << key << " Err: " << err.asStdString() << "\n";
|
||||
ss << "Key " << key << " Err: " << err.asString() << "\n";
|
||||
|
||||
std::cout << ss.str();
|
||||
|
||||
|
@ -61,8 +61,6 @@ show_usage (int ex)
|
||||
" --ephemeral use GPGME_KEYLIST_MODE_EPHEMERAL\n"
|
||||
" --validate use GPGME_KEYLIST_MODE_VALIDATE\n"
|
||||
" --locate use GPGME_KEYLIST_MODE_LOCATE\n"
|
||||
" --force-extern use GPGME_KEYLIST_MODE_FORCE_EXTERN\n"
|
||||
" --locate-external use GPGME_KEYLIST_MODE_LOCATE_EXTERNAL\n"
|
||||
, stderr);
|
||||
exit (ex);
|
||||
}
|
||||
@ -119,17 +117,7 @@ main (int argc, char **argv)
|
||||
} else if (!strcmp (*argv, "--locate")) {
|
||||
argc--; argv++;
|
||||
mode |= KeyListMode::Locate;
|
||||
} else if (!strcmp (*argv, "--with-secret")) {
|
||||
argc--; argv++;
|
||||
mode |= KeyListMode::WithSecret;
|
||||
} else if (!strcmp (*argv, "--force-extern")) {
|
||||
argc--; argv++;
|
||||
mode |= KeyListMode::ForceExtern;
|
||||
} else if (!strcmp (*argv, "--locate-external")) {
|
||||
argc--; argv++;
|
||||
mode |= KeyListMode::LocateExternal;
|
||||
} else if (!strncmp (*argv, "--", 2)) {
|
||||
std::cerr << "Error: Unknown option: " << *argv << std::endl;
|
||||
show_usage (1);
|
||||
}
|
||||
}
|
||||
@ -145,25 +133,16 @@ main (int argc, char **argv)
|
||||
return -1;
|
||||
}
|
||||
ctx->setKeyListMode (mode);
|
||||
if (ctx->keyListMode() != mode) {
|
||||
// unfortunately, Context::setKeyListMode() does not return the error
|
||||
// returned by gpgme
|
||||
std::cerr << "Failed to set keylist mode. You may have used an invalid combination of options.\n";
|
||||
return -1;
|
||||
}
|
||||
Error err = ctx->startKeyListing (*argv, only_secret);
|
||||
if (err) {
|
||||
std::cout << "Error: " << err.asStdString() << "\n";
|
||||
std::cout << "Error: " << err.asString() << "\n";
|
||||
return -1;
|
||||
}
|
||||
GpgME::Key key;
|
||||
std::stringstream ss;
|
||||
do {
|
||||
key = ctx->nextKey(err);
|
||||
if (!err)
|
||||
{
|
||||
ss << key << "\n\n";
|
||||
}
|
||||
ss << key << "\n\n";
|
||||
} while (!err && !key.isNull());
|
||||
|
||||
std::cout << ss.str();
|
||||
|
@ -38,6 +38,7 @@
|
||||
#include "verificationresult.h"
|
||||
|
||||
#include <memory>
|
||||
#include <sstream>
|
||||
#include <iostream>
|
||||
|
||||
using namespace GpgME;
|
||||
|
@ -1,158 +0,0 @@
|
||||
/*
|
||||
run-wkdlookup.cpp
|
||||
|
||||
This file is part of GpgMEpp's test suite.
|
||||
Copyright (c) 2021 g10 Code GmbH
|
||||
Software engineering by Ingo Klöcker <dev@ingo-kloecker.de>
|
||||
|
||||
GPGME++ is free software; you can redistribute it and/or
|
||||
modify it under the terms of the GNU Library General Public
|
||||
License as published by the Free Software Foundation; either
|
||||
version 2 of the License, or (at your option) any later version.
|
||||
|
||||
GPGME++ is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU Library General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU Library General Public License
|
||||
along with GPGME++; see the file COPYING.LIB. If not, write to the
|
||||
Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
|
||||
Boston, MA 02110-1301, USA.
|
||||
*/
|
||||
|
||||
#ifdef HAVE_CONFIG_H
|
||||
#include "config.h"
|
||||
#endif
|
||||
|
||||
#include "context.h"
|
||||
#include "data.h"
|
||||
#include "defaultassuantransaction.h"
|
||||
#include "key.h"
|
||||
|
||||
#include <memory>
|
||||
#include <iostream>
|
||||
#include <thread>
|
||||
|
||||
using namespace GpgME;
|
||||
|
||||
static int
|
||||
show_usage (int ex)
|
||||
{
|
||||
fputs ("usage: run-wkdlookup <email address>\n\n"
|
||||
, stderr);
|
||||
exit (ex);
|
||||
}
|
||||
|
||||
int
|
||||
main (int argc, char **argv)
|
||||
{
|
||||
int last_argc = -1;
|
||||
|
||||
if (argc) {
|
||||
argc--; argv++;
|
||||
}
|
||||
|
||||
while (argc && last_argc != argc ) {
|
||||
last_argc = argc;
|
||||
if (!strcmp (*argv, "--")) {
|
||||
argc--; argv++;
|
||||
break;
|
||||
} else if (!strcmp (*argv, "--help")) {
|
||||
show_usage (0);
|
||||
} else if (!strncmp (*argv, "--", 2)) {
|
||||
show_usage (1);
|
||||
}
|
||||
}
|
||||
|
||||
if (argc != 1) {
|
||||
show_usage (1);
|
||||
}
|
||||
|
||||
const std::string email{*argv};
|
||||
|
||||
GpgME::initializeLibrary();
|
||||
Error err;
|
||||
auto ctx = std::unique_ptr<Context>{Context::createForEngine(AssuanEngine, &err)};
|
||||
if (!ctx) {
|
||||
std::cerr << "Failed to get context (Error: " << err.asStdString() << ")\n";
|
||||
return -1;
|
||||
}
|
||||
|
||||
const std::string dirmngrSocket = GpgME::dirInfo("dirmngr-socket");
|
||||
if ((err = ctx->setEngineFileName(dirmngrSocket.c_str()))) {
|
||||
std::cerr << "Failed to set engine file name (Error: " << err.asStdString() << ")\n";
|
||||
return -1;
|
||||
}
|
||||
if ((err = ctx->setEngineHomeDirectory(""))) {
|
||||
std::cerr << "Failed to set engine home directory (Error: " << err.asStdString() << ")\n";
|
||||
return -1;
|
||||
}
|
||||
|
||||
// try to connect to dirmngr
|
||||
err = ctx->assuanTransact("GETINFO version");
|
||||
if (err && err.code() != GPG_ERR_ASS_CONNECT_FAILED) {
|
||||
std::cerr << "Failed to start assuan transaction (Error: " << err.asStdString() << ")\n";
|
||||
return -1;
|
||||
}
|
||||
if (err.code() == GPG_ERR_ASS_CONNECT_FAILED) {
|
||||
std::cerr << "Starting dirmngr ...\n";
|
||||
auto spawnCtx = std::unique_ptr<Context>{Context::createForEngine(SpawnEngine, &err)};
|
||||
if (!spawnCtx) {
|
||||
std::cerr << "Failed to get context for spawn engine (Error: " << err.asStdString() << ")\n";
|
||||
return -1;
|
||||
}
|
||||
|
||||
const auto gpgconfProgram = GpgME::dirInfo("gpgconf-name");
|
||||
// replace backslashes with forward slashes in homedir to work around bug T6833
|
||||
std::string homedir{GpgME::dirInfo("homedir")};
|
||||
std::replace(homedir.begin(), homedir.end(), '\\', '/');
|
||||
const char *argv[] = {
|
||||
gpgconfProgram,
|
||||
"--homedir",
|
||||
homedir.c_str(),
|
||||
"--launch",
|
||||
"dirmngr",
|
||||
NULL
|
||||
};
|
||||
auto ignoreIO = Data{Data::null};
|
||||
err = spawnCtx->spawn(gpgconfProgram, argv,
|
||||
ignoreIO, ignoreIO, ignoreIO,
|
||||
Context::SpawnDetached);
|
||||
if (err) {
|
||||
std::cerr << "Failed to start dirmngr (Error: " << err.asStdString() << ")\n";
|
||||
return -1;
|
||||
}
|
||||
|
||||
// wait for socket to become available
|
||||
int cnt = 0;
|
||||
do {
|
||||
++cnt;
|
||||
std::cerr << "Waiting for dirmngr to start ...\n";
|
||||
std::this_thread::sleep_for(std::chrono::milliseconds{250 * cnt});
|
||||
err = ctx->assuanTransact("GETINFO version");
|
||||
} while (err.code() == GPG_ERR_ASS_CONNECT_FAILED && cnt < 5);
|
||||
}
|
||||
|
||||
const auto cmd = std::string{"WKD_GET "} + email;
|
||||
err = ctx->assuanTransact(cmd.c_str());
|
||||
if (err && err.code() != GPG_ERR_NO_NAME && err.code() != GPG_ERR_NO_DATA) {
|
||||
std::cerr << "Error: WKD_GET returned " << err.asStdString() << "\n";
|
||||
return -1;
|
||||
}
|
||||
|
||||
const auto transaction = std::unique_ptr<DefaultAssuanTransaction>(dynamic_cast<DefaultAssuanTransaction*>(ctx->takeLastAssuanTransaction().release()));
|
||||
const auto source = transaction->firstStatusLine("SOURCE");
|
||||
const auto rawData = transaction->data();
|
||||
if (rawData.size() == 0) {
|
||||
std::cout << "No key found for " << email << "\n";
|
||||
} else {
|
||||
const auto data = GpgME::Data{rawData.c_str(), rawData.size()};
|
||||
const auto keys = data.toKeys(GpgME::OpenPGP);
|
||||
for (const auto &key : keys) {
|
||||
std::cout << "Found key for " << email << " at " << source << ":\n" << key << "\n";
|
||||
}
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
@ -44,16 +44,4 @@ describe('GPGME context', function (){
|
||||
done();
|
||||
});
|
||||
});
|
||||
|
||||
it('Error message on unsuccessful connection (timeout)', function (done) {
|
||||
let prm = Gpgmejs.init({ timeout: 1 });
|
||||
prm.then(
|
||||
null,
|
||||
function (error){
|
||||
expect(error).to.be.an('error');
|
||||
expect(error.code).to.equal('CONN_TIMEOUT');
|
||||
done();
|
||||
}
|
||||
);
|
||||
});
|
||||
});
|
@ -40,15 +40,7 @@ import { decode, atobArray, Utf8ArrayToStr } from './Helpers';
|
||||
export class Connection{
|
||||
|
||||
constructor (){
|
||||
this._connectionError = null;
|
||||
this._connection = chrome.runtime.connectNative('gpgmejson');
|
||||
this._connection.onDisconnect.addListener(() => {
|
||||
if (chrome.runtime.lastError) {
|
||||
this._connectionError = chrome.runtime.lastError.message;
|
||||
} else {
|
||||
this._connectionError = 'Disconnected without error message';
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
@ -58,16 +50,9 @@ export class Connection{
|
||||
if (this._connection){
|
||||
this._connection.disconnect();
|
||||
this._connection = null;
|
||||
this._connectionError = 'Disconnect requested by gpgmejs';
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Checks if the connection terminated with an error state
|
||||
*/
|
||||
get isDisconnected (){
|
||||
return this._connectionError !== null;
|
||||
}
|
||||
|
||||
/**
|
||||
* @typedef {Object} backEndDetails
|
||||
@ -99,29 +84,25 @@ export class Connection{
|
||||
timeout = 1000;
|
||||
}
|
||||
const msg = createMessage('version');
|
||||
const prm = Promise.race([
|
||||
this.post(msg),
|
||||
new Promise(function (resolve, reject){
|
||||
setTimeout(function (){
|
||||
reject(gpgme_error('CONN_TIMEOUT'));
|
||||
}, timeout);
|
||||
})
|
||||
]);
|
||||
return new Promise( function (resolve, reject) {
|
||||
prm.then(function (success){
|
||||
if (details === true ) {
|
||||
resolve(success);
|
||||
} else {
|
||||
if (details === true) {
|
||||
return this.post(msg);
|
||||
} else {
|
||||
let me = this;
|
||||
return new Promise(function (resolve) {
|
||||
Promise.race([
|
||||
me.post(msg),
|
||||
new Promise(function (resolve, reject){
|
||||
setTimeout(function (){
|
||||
reject(gpgme_error('CONN_TIMEOUT'));
|
||||
}, timeout);
|
||||
})
|
||||
]).then(function (){ // success
|
||||
resolve(true);
|
||||
}
|
||||
}, function (error) {
|
||||
if (details === true ) {
|
||||
reject(error);
|
||||
} else {
|
||||
}, function (){ // failure
|
||||
resolve(false);
|
||||
}
|
||||
});
|
||||
});
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
@ -147,7 +128,7 @@ export class Connection{
|
||||
}
|
||||
let chunksize = message.chunksize;
|
||||
const me = this;
|
||||
const nativeCommunication = new Promise(function (resolve, reject){
|
||||
return new Promise(function (resolve, reject){
|
||||
let answer = new Answer(message);
|
||||
let listener = function (msg) {
|
||||
if (!msg){
|
||||
@ -180,35 +161,29 @@ export class Connection{
|
||||
}
|
||||
};
|
||||
me._connection.onMessage.addListener(listener);
|
||||
me._connection.postMessage(message.message);
|
||||
|
||||
// check for browser messaging errors after a while
|
||||
// (browsers' extension permission checks take some time)
|
||||
setTimeout( () => {
|
||||
if (me.isDisconnected) {
|
||||
if ( me.isNativeHostUnknown === true) {
|
||||
return reject(gpgme_error('CONN_NO_CONFIG'));
|
||||
} else {
|
||||
return reject(gpgme_error(
|
||||
'CONN_NO_CONNECT', me._connectionError));
|
||||
if (permittedOperations[message.operation].pinentry){
|
||||
return me._connection.postMessage(message.message);
|
||||
} else {
|
||||
return Promise.race([
|
||||
me._connection.postMessage(message.message),
|
||||
function (resolve, reject){
|
||||
setTimeout(function (){
|
||||
me._connection.disconnect();
|
||||
reject(gpgme_error('CONN_TIMEOUT'));
|
||||
}, 5000);
|
||||
}
|
||||
}
|
||||
}, 25);
|
||||
|
||||
]).then(function (result){
|
||||
return result;
|
||||
}, function (reject){
|
||||
if (!(reject instanceof Error)) {
|
||||
me._connection.disconnect();
|
||||
return gpgme_error('GNUPG_ERROR', reject);
|
||||
} else {
|
||||
return reject;
|
||||
}
|
||||
});
|
||||
}
|
||||
});
|
||||
if (permittedOperations[message.operation].pinentry === true) {
|
||||
return nativeCommunication;
|
||||
} else {
|
||||
return Promise.race([
|
||||
nativeCommunication,
|
||||
new Promise(function (resolve, reject){
|
||||
setTimeout(function (){
|
||||
me.disconnect();
|
||||
reject(gpgme_error('CONN_TIMEOUT'));
|
||||
}, 5000);
|
||||
})
|
||||
]);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@ -237,13 +212,6 @@ class Answer{
|
||||
return this._expected;
|
||||
}
|
||||
|
||||
/**
|
||||
* Checks if an error matching browsers 'host not known' messages occurred
|
||||
*/
|
||||
get isNativeHostUnknown () {
|
||||
return this._connectionError === 'Specified native messaging host not found.';
|
||||
}
|
||||
|
||||
/**
|
||||
* Adds incoming base64 encoded data to the existing response
|
||||
* @param {*} msg base64 encoded data.
|
||||
|
@ -35,14 +35,6 @@ export const err_list = {
|
||||
msg: 'The nativeMessaging answer was empty.',
|
||||
type: 'error'
|
||||
},
|
||||
'CONN_NO_CONFIG':{
|
||||
msg: 'The browser does not recognize the nativeMessaging host.',
|
||||
type: 'error'
|
||||
},
|
||||
'CONN_NATIVEMESSAGE':{
|
||||
msg: 'The native messaging was not successful.',
|
||||
type: 'error'
|
||||
},
|
||||
'CONN_TIMEOUT': {
|
||||
msg: 'A connection timeout was exceeded.',
|
||||
type: 'error'
|
||||
@ -164,8 +156,8 @@ export function gpgme_error (code = 'GENERIC_ERROR', info){
|
||||
*/
|
||||
class GPGME_Error extends Error{
|
||||
constructor (code = 'GENERIC_ERROR', msg=''){
|
||||
const verboseErrors = ['GNUPG_ERROR', 'CONN_NATIVEMESSAGE'];
|
||||
if (verboseErrors.includes(code) && typeof (msg) === 'string'){
|
||||
|
||||
if (code === 'GNUPG_ERROR' && typeof (msg) === 'string'){
|
||||
super(msg);
|
||||
} else if (err_list.hasOwnProperty(code)){
|
||||
if (msg){
|
||||
|
@ -33,7 +33,7 @@ import { Connection } from './Connection';
|
||||
* An unsuccessful attempt will reject as a GPGME_Error.
|
||||
* @param {Object} config (optional) configuration options
|
||||
* @param {Number} config.timeout set the timeout for the initial connection
|
||||
* check. On some machines and operating systems a default timeout of 1000 ms is
|
||||
* check. On some machines and operating systems a default timeout of 500 ms is
|
||||
* too low, so a higher number might be attempted.
|
||||
* @returns {Promise<GpgME>}
|
||||
* @async
|
||||
@ -46,17 +46,7 @@ function init ({ timeout = 1000 } = {}){
|
||||
if (result === true) {
|
||||
resolve(new GpgME());
|
||||
} else {
|
||||
if (connection._connectionError) {
|
||||
if (connection.isNativeHostUnknown){
|
||||
reject(gpgme_error('CONN_NO_CONFIG'));
|
||||
} else {
|
||||
reject(gpgme_error('CONN_NATIVEMESSAGE',
|
||||
connection._connectionError)
|
||||
);
|
||||
}
|
||||
} else {
|
||||
reject(gpgme_error('CONN_TIMEOUT'));
|
||||
}
|
||||
reject(gpgme_error('CONN_NO_CONNECT'));
|
||||
}
|
||||
}, function (){ // unspecific connection error. Should not happen
|
||||
reject(gpgme_error('CONN_NO_CONNECT'));
|
||||
|
@ -49,42 +49,11 @@ function unittests (){
|
||||
expect(answer.info).to.be.an('Array');
|
||||
expect(conn0.disconnect).to.be.a('function');
|
||||
expect(conn0.post).to.be.a('function');
|
||||
expect(conn0.isDisconnected).to.be.false;
|
||||
done();
|
||||
});
|
||||
|
||||
});
|
||||
|
||||
it('Simple connection check', function (done) {
|
||||
let conn0 = new Connection;
|
||||
conn0.checkConnection(false, connectionTimeout).then(
|
||||
function (answer) {
|
||||
expect(answer).to.be.true;
|
||||
expect(conn0.isDisconnected).to.be.false;
|
||||
done();
|
||||
});
|
||||
});
|
||||
|
||||
it('Connection check with backend information', function (done) {
|
||||
let conn0 = new Connection;
|
||||
conn0.checkConnection(true, connectionTimeout).then(
|
||||
function (answer) {
|
||||
expect(answer).to.be.an('Object');
|
||||
expect(answer.gpgme).to.be.a('String');
|
||||
expect(answer.info).to.be.an('Array');
|
||||
expect(answer.info.length).to.be.above(0);
|
||||
for (const item of answer.info) {
|
||||
expect(item).to.have.property('protocol');
|
||||
expect(item).to.have.property('fname');
|
||||
expect(item).to.have.property('version');
|
||||
expect(item).to.have.property('req_version');
|
||||
expect(item).to.have.property('homedir');
|
||||
}
|
||||
expect(conn0.isDisconnected).to.be.false;
|
||||
done();
|
||||
});
|
||||
});
|
||||
|
||||
it('Disconnecting', function (done) {
|
||||
let conn0 = new Connection;
|
||||
conn0.checkConnection(false, connectionTimeout).then(
|
||||
@ -94,7 +63,6 @@ function unittests (){
|
||||
conn0.checkConnection(false, connectionTimeout).then(
|
||||
function (result) {
|
||||
expect(result).to.be.false;
|
||||
expect(conn0.isDisconnected).to.be.true;
|
||||
done();
|
||||
});
|
||||
});
|
||||
|
@ -21,15 +21,12 @@ EXTRA_DIST = \
|
||||
README \
|
||||
MANIFEST.in \
|
||||
gpgme.i \
|
||||
helpers.c helpers.h private.h
|
||||
helpers.c helpers.h private.h \
|
||||
examples \
|
||||
doc \
|
||||
src
|
||||
|
||||
if RUN_GPG_TESTS
|
||||
tests = tests
|
||||
else
|
||||
tests =
|
||||
endif
|
||||
|
||||
SUBDIRS = . ${tests} examples doc src
|
||||
SUBDIRS = . tests
|
||||
|
||||
.PHONY: prepare
|
||||
prepare: copystamp
|
||||
@ -80,7 +77,7 @@ CLEANFILES = copystamp \
|
||||
# 'make distclean' clears the write bit, breaking rm -rf. Fix the
|
||||
# permissions.
|
||||
clean-local:
|
||||
rm -rf -- build dist gpg.egg-info
|
||||
rm -rf -- build
|
||||
for PYTHON in $(PYTHONS); do \
|
||||
find "$$(basename "$${PYTHON}")-gpg" -type d ! -perm -200 -exec chmod u+w {} ';' ; \
|
||||
rm -rf -- "$$(basename "$${PYTHON}")-gpg" ; \
|
||||
@ -101,12 +98,8 @@ install-exec-local:
|
||||
done
|
||||
|
||||
uninstall-local:
|
||||
set -x; \
|
||||
GV=$$(echo $(VERSION) | tr - _); \
|
||||
normalizedGV=$$(echo $$GV | sed s/_beta/b/); \
|
||||
for PYTHON in $(PYTHONS); do \
|
||||
set -x; GV=$$(echo $(VERSION) | tr - _); for PYTHON in $(PYTHONS); do \
|
||||
PLATLIB="$(prefix)/$$("$${PYTHON}" -c 'import sysconfig, os; print(os.path.relpath(sysconfig.get_path("platlib", scheme="posix_prefix"), sysconfig.get_config_var("prefix")))')" ; \
|
||||
rm -rf -- "$(DESTDIR)$${PLATLIB}/gpg" \
|
||||
"$(DESTDIR)$${PLATLIB}"/gpg-$$GV-py*.egg-info \
|
||||
"$(DESTDIR)$${PLATLIB}"/gpg-$$normalizedGV-py*.egg ; \
|
||||
"$(DESTDIR)$${PLATLIB}"/gpg-$$GV-py*.egg-info ; \
|
||||
done
|
||||
|
@ -1,61 +0,0 @@
|
||||
# Makefile.am for the Python bindings.
|
||||
# Copyright (C) 2019 g10 Code GmbH
|
||||
#
|
||||
# This file is part of GPGME.
|
||||
#
|
||||
# GPGME is free software; you can redistribute it and/or modify it
|
||||
# under the terms of the GNU Lesser General Public License as
|
||||
# published by the Free Software Foundation; either version 2.1 of the
|
||||
# License, or (at your option) any later version.
|
||||
#
|
||||
# GPGME is distributed in the hope that it will be useful, but WITHOUT
|
||||
# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
|
||||
# or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General
|
||||
# Public License for more details.
|
||||
#
|
||||
# You should have received a copy of the GNU Lesser General Public
|
||||
# License along with this program; if not, see <https://gnu.org/licenses/>.
|
||||
# SPDX-License-Identifier: LGPL-2.1-or-later
|
||||
|
||||
EXTRA_DIST = README rst src texinfo
|
||||
|
||||
if MAINTAINER_MODE
|
||||
|
||||
ORGSRCS = index.org gpgme-python-howto.org maintenance-mode.org \
|
||||
short-history.org what-is-new.org what-was-new.org
|
||||
|
||||
# Make sure we have 'rst' and 'texinfo' dirs in build directory
|
||||
.PHONY: the_doc_dirs gen_rst gen_texi
|
||||
|
||||
the_doc_dirs:
|
||||
@if test ! -d rst; then echo $(MKDIR_P) rst; $(MKDIR_P) rst; fi
|
||||
@if test ! -d texinfo; then echo $(MKDIR_P) texinfo; $(MKDIR_P) texinfo; fi
|
||||
|
||||
# Generate RST files from ORG
|
||||
gen_rst:
|
||||
@for f in $(ORGSRCS); do if test ! -e rst/$${f%.org}.rst \
|
||||
-o rst/$${f%.org}.rst -ot $(srcdir)/src/$$f; then \
|
||||
echo pandoc -f org -t rst $(srcdir)/src/$$f -o rst/$${f%.org}.rst; \
|
||||
pandoc -f org -t rst $(srcdir)/src/$$f -o rst/$${f%.org}.rst; \
|
||||
fi; \
|
||||
done
|
||||
|
||||
# Generate Texinfo files from ORG
|
||||
gen_texi:
|
||||
@for f in $(ORGSRCS); do if test ! -e texinfo/$${f%.org}.texi \
|
||||
-o texinfo/$${f%.org}.texi -ot $(srcdir)/src/$$f; then \
|
||||
echo pandoc -f org -t texinfo $(srcdir)/src/$$f -o texinfo/$${f%.org}.texi; \
|
||||
pandoc -f org -t texinfo $(srcdir)/src/$$f -o texinfo/$${f%.org}.texi; \
|
||||
fi; \
|
||||
done
|
||||
|
||||
all-local: gen_rst gen_texi
|
||||
|
||||
gen_rst gen_texi: the_doc_dirs
|
||||
|
||||
maintainer-clean-local:
|
||||
@for f in $(ORGSRCS); do \
|
||||
echo rm -f rst/$${f%.org}.rst texinfo/$${f%.org}.texi; \
|
||||
rm -f rst/$${f%.org}.rst texinfo/$${f%.org}.texi; \
|
||||
done
|
||||
endif
|
@ -15,8 +15,6 @@
|
||||
# import os
|
||||
# import sys
|
||||
# sys.path.insert(0, os.path.abspath('.'))
|
||||
import hashlib
|
||||
import time
|
||||
|
||||
|
||||
# -- Project information -----------------------------------------------------
|
||||
@ -103,7 +101,7 @@ html_static_path = ['_static']
|
||||
# -- Options for HTMLHelp output ---------------------------------------------
|
||||
|
||||
# Output file base name for HTML help builder.
|
||||
htmlhelp_basename = 'GPGMEPythonBindings'
|
||||
htmlhelp_basename = 'GPGMEPythonBindingsdoc'
|
||||
|
||||
|
||||
# -- Options for LaTeX output ------------------------------------------------
|
||||
@ -116,7 +114,6 @@ latex_elements = {
|
||||
# The font size ('10pt', '11pt' or '12pt').
|
||||
#
|
||||
# 'pointsize': '10pt',
|
||||
'pointsize': '12pt'
|
||||
|
||||
# Additional stuff for the LaTeX preamble.
|
||||
#
|
||||
@ -131,8 +128,7 @@ latex_elements = {
|
||||
# (source start file, target name, title,
|
||||
# author, documentclass [howto, manual, or own class]).
|
||||
latex_documents = [
|
||||
(master_doc, 'GPGMEPythonBindings.tex',
|
||||
'GPGME Python Bindings Documentation',
|
||||
(master_doc, 'GPGMEPythonBindings.tex', 'GPGME Python Bindings Documentation',
|
||||
'The GnuPG Hackers', 'manual'),
|
||||
]
|
||||
|
||||
@ -154,8 +150,8 @@ man_pages = [
|
||||
# dir menu entry, description, category)
|
||||
texinfo_documents = [
|
||||
(master_doc, 'GPGMEPythonBindings', 'GPGME Python Bindings Documentation',
|
||||
author, 'GPGMEPythonBindings',
|
||||
'Python Bindings to the GNU Privacy Guard API.', 'Miscellaneous'),
|
||||
author, 'GPGMEPythonBindings', 'One line description of project.',
|
||||
'Miscellaneous'),
|
||||
]
|
||||
|
||||
|
||||
@ -164,21 +160,14 @@ texinfo_documents = [
|
||||
# Bibliographic Dublin Core info.
|
||||
epub_title = project
|
||||
|
||||
# The unique identifier of the text. This can be an ISBN number
|
||||
# The unique identifier of the text. This can be a ISBN number
|
||||
# or the project homepage.
|
||||
#
|
||||
# epub_identifier = ''
|
||||
epub_identifier = 'org.gnupg.gpgme.python'
|
||||
|
||||
# A unique identification for the text.
|
||||
#
|
||||
# epub_uid = ''
|
||||
stt = str(time.time())
|
||||
epub_seed = "{0} {1}".format(epub_identifier, tt)
|
||||
# SHA1 would be more than fine for this, but since the dimmest always panic
|
||||
# about any use of SHA1 with GnuPG, we'll use SHA256.
|
||||
epub_hash = hashlib.sha256(epub_seed).hexdigest()
|
||||
epub_uid = 'sha256:{0}'.format(epub_hash)
|
||||
|
||||
# A list of files that should not be packed into the epub file.
|
||||
epub_exclude_files = ['search.html']
|
3191
lang/python/doc/rst/gpgme-python-howto.rst
Normal file
3191
lang/python/doc/rst/gpgme-python-howto.rst
Normal file
File diff suppressed because it is too large
Load Diff
30
lang/python/doc/rst/index.rst
Normal file
30
lang/python/doc/rst/index.rst
Normal file
@ -0,0 +1,30 @@
|
||||
.. GPGME Python Bindings documentation master file, created by
|
||||
sphinx-quickstart on Wed Dec 5 09:04:47 2018.
|
||||
You can adapt this file completely to your liking, but it should at least
|
||||
contain the root `toctree` directive.
|
||||
|
||||
GPGME Python Bindings
|
||||
=====================
|
||||
|
||||
.. toctree::
|
||||
:maxdepth: 2
|
||||
:caption: Contents:
|
||||
|
||||
Contents
|
||||
--------
|
||||
|
||||
- `A short history of the project <short-history>`__
|
||||
- `What\'s New <what-is-new>`__
|
||||
|
||||
- `Maintenance Mode <maintenance-mode>`__ (from January, 2019)
|
||||
|
||||
- `What Was New <what-was-new>`__
|
||||
- `GPGME Python Bindings HOWTO <gpgme-python-howto>`__
|
||||
|
||||
|
||||
Indices and tables
|
||||
==================
|
||||
|
||||
* :ref:`genindex`
|
||||
* :ref:`modindex`
|
||||
* :ref:`search`
|
90
lang/python/doc/rst/maintenance-mode.rst
Normal file
90
lang/python/doc/rst/maintenance-mode.rst
Normal file
@ -0,0 +1,90 @@
|
||||
.. _maintenance-mode:
|
||||
|
||||
Maintenance Mode from 2019
|
||||
==========================
|
||||
|
||||
+-----------------+------------------------------------------+
|
||||
| Version: | 0.0.1 |
|
||||
+-----------------+------------------------------------------+
|
||||
| GPGME Version: | 1.13.0 |
|
||||
+-----------------+------------------------------------------+
|
||||
| Author: | Ben McGinnes <ben@gnupg.org> |
|
||||
+-----------------+------------------------------------------+
|
||||
| Author GPG Key: | DB4724E6FA4286C92B4E55C4321E4E2373590E5D |
|
||||
+-----------------+------------------------------------------+
|
||||
| Language: | Australian English, British English |
|
||||
+-----------------+------------------------------------------+
|
||||
| xml:lang: | en-AU, en-GB, en |
|
||||
+-----------------+------------------------------------------+
|
||||
|
||||
From the beginning of 2019 the Python bindings to GPGME will enter
|
||||
maintenance mode, meaning that new features will not be added and only
|
||||
bug fixes and security fixes will be made. This also means that
|
||||
documentation beyond that existing at the end of 2018 will not be
|
||||
developed further except to correct errors.
|
||||
|
||||
Though use of these bindings appears to have been quite well received,
|
||||
there has been no indication of what demand there is, if any for either
|
||||
financial backing of the current Python bindings development or support
|
||||
contracts with g10code GmbH citing the necessity of including the
|
||||
bindings.
|
||||
|
||||
.. _maintenance-mode-bm:
|
||||
|
||||
Maintainer from 2019 onward
|
||||
---------------------------
|
||||
|
||||
How does this affect the position of GnuPG Python Bindings Maintainer?
|
||||
|
||||
Well, I will remain as maintainer of the bindings; but without funding
|
||||
for that position, the amount of time I will be able to dedicate solely
|
||||
to this task will be limited and reduced to volunteered time. As with
|
||||
all volunteered time and effort in free software projects, this will be
|
||||
subject to numerous external imperatives.
|
||||
|
||||
.. _maintenance-mode-blade-runner:
|
||||
|
||||
Using the Python Bindings from 2019 and beyond
|
||||
----------------------------------------------
|
||||
|
||||
For most, if not all, Python developers using these bindings; they will
|
||||
continue to "just work" the same as they always have. Expansions of
|
||||
GPGME itself are usually handled by SWIG with the existing code and thus
|
||||
bindings are generated properly when the bindings are installed
|
||||
alongside GPGME and when the latter is built from source.
|
||||
|
||||
In the rare circumstances where that is not enough to address some new
|
||||
addition to GPGME, then that is a bug and thus subject to the
|
||||
maintenance mode provisions (i.e. it will be fixed following a bug
|
||||
report being raised and your humble author will need to remember where
|
||||
the timesheet template was filed, depending on how many years off such
|
||||
an event is).
|
||||
|
||||
All the GPGME functionality will continue to be accessible via the lower
|
||||
level, dynamically generated methods which match the GPGME C
|
||||
documentation. While the more intuitively Pythonic higher level layer
|
||||
already covers the vast majority of functionality people require with
|
||||
key generation, signatures, certifications (key signing), encryption,
|
||||
decryption, verification, validation, trust levels and so on.
|
||||
|
||||
Any wanted features lacking in the Python bindings are usually lacking
|
||||
because they are missing from GPGME itself (e.g. revoking keys via the
|
||||
API) and in such cases they are usually deliberately excluded. More
|
||||
discussion of these issues can be found in the archives of the
|
||||
`gnupg-devel mailing
|
||||
list <https://lists.gnupg.org/mailman/listinfo/gnupg-devel>`__.
|
||||
|
||||
Any features existing in the dynamically generated layer for which
|
||||
people want a specific, higher level function included to make it more
|
||||
Pythonic (e.g. to avoid needing to learn or memorise cryptographic mode
|
||||
values or GnuPG status code numbers), would be a feature request and
|
||||
*not* a bug.
|
||||
|
||||
It is still worthwhile requesting it, but the addition of such a feature
|
||||
would not be guaranteed and provided on a purely volunteer basis.
|
||||
Expediting such a request would require funding that request.
|
||||
|
||||
Those with a commercial interest in expediting such a feature request
|
||||
already know how to `expedite
|
||||
it <https://gnupg.org/cgi-bin/procdonate.cgi?mode=preset>`__ (use the
|
||||
message field to state what feature is being requested).
|
166
lang/python/doc/rst/short-history.rst
Normal file
166
lang/python/doc/rst/short-history.rst
Normal file
@ -0,0 +1,166 @@
|
||||
Overview
|
||||
========
|
||||
|
||||
+-----------------+------------------------------------------+
|
||||
| Version: | 0.0.1 |
|
||||
+-----------------+------------------------------------------+
|
||||
| GPGME Version: | 1.13.0 |
|
||||
+-----------------+------------------------------------------+
|
||||
| Author: | Ben McGinnes <ben@gnupg.org> |
|
||||
+-----------------+------------------------------------------+
|
||||
| Author GPG Key: | DB4724E6FA4286C92B4E55C4321E4E2373590E5D |
|
||||
+-----------------+------------------------------------------+
|
||||
| Language: | Australian English, British English |
|
||||
+-----------------+------------------------------------------+
|
||||
| xml:lang: | en-AU, en-GB, en |
|
||||
+-----------------+------------------------------------------+
|
||||
|
||||
The GPGME Python bindings passed through many hands and numerous phases
|
||||
before, after a fifteen year journey, coming full circle to return to
|
||||
the source. This is a short explanation of that journey.
|
||||
|
||||
.. _in-the-begining:
|
||||
|
||||
In the beginning
|
||||
----------------
|
||||
|
||||
In 2002 John Goerzen released PyME; Python bindings for the GPGME module
|
||||
which utilised the current release of Python of the time and SWIG. [1]_
|
||||
Shortly after creating it and ensuring it worked he stopped supporting
|
||||
it, though he left his work available on his Gopher site.
|
||||
|
||||
Keeping the flame alive
|
||||
-----------------------
|
||||
|
||||
A couple of years later the project was picked up by Igor Belyi and
|
||||
actively developed and maintained by him from 2004 to 2008. Igor\'s
|
||||
whereabouts at the time of this document\'s creation are unknown, but
|
||||
the current authors do hope he is well. We\'re assuming (or hoping) that
|
||||
life did what life does and made continuing untenable.
|
||||
|
||||
Passing the torch
|
||||
-----------------
|
||||
|
||||
In 2014 Martin Albrecht wanted to patch a bug in the PyME code and
|
||||
discovered the absence of Igor. Following a discussion on the PyME
|
||||
mailing list he became the new maintainer for PyME, releasing version
|
||||
0.9.0 in May of that year. He remains the maintainer of the original
|
||||
PyME release in Python 2.6 and 2.7 (available via PyPI).
|
||||
|
||||
.. _ouroboros:
|
||||
|
||||
Coming full circle
|
||||
------------------
|
||||
|
||||
In 2015 Ben McGinnes approached Martin about a Python 3 version, while
|
||||
investigating how complex a task this would be the task ended up being
|
||||
completed. A subsequent discussion with Werner Koch led to the decision
|
||||
to fold the Python 3 port back into the original GPGME release in the
|
||||
languages subdirectory for non-C bindings under the module name of
|
||||
``pyme3``.
|
||||
|
||||
In 2016 this PyME module was integrated back into the GPGME project by
|
||||
Justus Winter. During the course of this work Justus adjusted the port
|
||||
to restore limited support for Python 2, but not as many minor point
|
||||
releases as the original PyME package supports. During the course of
|
||||
this integration the package was renamed to more accurately reflect its
|
||||
status as a component of GPGME. The ``pyme3`` module was renamed to
|
||||
``gpg`` and adopted by the upstream GnuPG team.
|
||||
|
||||
In 2017 Justus departed G10code and the GnuPG team. Following this Ben
|
||||
returned to maintain of gpgme Python bindings and continue building them
|
||||
from that point.
|
||||
|
||||
.. _relics-past:
|
||||
|
||||
Relics of the past
|
||||
==================
|
||||
|
||||
There are a few things, in addition to code specific factors, such as
|
||||
SWIG itself, which are worth noting here.
|
||||
|
||||
The Annoyances of Git
|
||||
---------------------
|
||||
|
||||
As anyone who has ever worked with git knows, submodules are horrible
|
||||
way to deal with pretty much anything. In the interests of avoiding
|
||||
migraines, that was skipped with addition of the PyME code to GPGME.
|
||||
|
||||
Instead the files were added to a subdirectory of the ``lang/``
|
||||
directory, along with a copy of the entire git log up to that point as a
|
||||
separate file within the ``lang/python/docs/`` directory. [2]_ As the
|
||||
log for PyME is nearly 100KB and the log for GPGME is approximately 1MB,
|
||||
this would cause considerable bloat, as well as some confusion, should
|
||||
the two be merged.
|
||||
|
||||
Hence the unfortunate, but necessary, step to simply move the files. A
|
||||
regular repository version has been maintained should it be possible to
|
||||
implement this better in the future.
|
||||
|
||||
The Perils of PyPI
|
||||
------------------
|
||||
|
||||
The early port of the Python 2 ``pyme`` module as ``pyme3`` was never
|
||||
added to PyPI while the focus remained on development and testing during
|
||||
2015 and early 2016. Later in 2016, however, when Justus completed his
|
||||
major integration work and subsequently renamed the module from
|
||||
``pyme3`` to ``gpg``, some prior releases were also provided through
|
||||
PyPI.
|
||||
|
||||
Since these bindings require a matching release of the GPGME libraries
|
||||
in order to function, it was determined that there was little benefit in
|
||||
also providing a copy through PyPI since anyone obtaining the GPGME
|
||||
source code would obtain the Python bindings source code at the same
|
||||
time. Whereas there was the potential to sew confusion amongst Python
|
||||
users installing the module from PyPI, only to discover that without the
|
||||
relevant C files, header files or SWIG compiled binaries, the Python
|
||||
module did them little good.
|
||||
|
||||
There are only two files on PyPI which might turn up in a search for
|
||||
this module or a sample of its content:
|
||||
|
||||
#. gpg (1.8.0) - Python bindings for GPGME GnuPG cryptography library
|
||||
#. pyme (0.9.0) - Python support for GPGME GnuPG cryptography library
|
||||
|
||||
.. _pypi-gpgme-180:
|
||||
|
||||
GPG 1·8·0 - Python bindings for GPGME GnuPG cryptography library
|
||||
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
|
||||
This is the most recent version to reach PyPI and is the version of the
|
||||
official Pyhon bindings which shipped with GPGME 1.8.0. If you have
|
||||
GPGME 1.8.0 installed and *only* 1.8.0 installed, then it is probably
|
||||
safe to use this copy from PyPI.
|
||||
|
||||
As there have been a lot of changes since the release of GPGME 1.8.0,
|
||||
the GnuPG Project recommends not using this version of the module and
|
||||
instead installing the current version of GPGME along with the Python
|
||||
bindings included with that package.
|
||||
|
||||
.. _pypi-gpgme-90:
|
||||
|
||||
PyME 0·9·0 - Python support for GPGME GnuPG cryptography library
|
||||
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
|
||||
This is the last release of the PyME bindings maintained by Martin
|
||||
Albrecht and is only compatible with Python 2, it will not work with
|
||||
Python 3. This is the version of the software from which the port from
|
||||
Python 2 to Python 3 code was made in 2015.
|
||||
|
||||
Users of the more recent Python bindings will recognise numerous points
|
||||
of similarity, but also significant differences. It is likely that the
|
||||
more recent official bindings will feel \"more pythonic.\"
|
||||
|
||||
For those using Python 2, there is essentially no harm in using this
|
||||
module, but it may lack a number of more recent features added to GPGME.
|
||||
|
||||
Footnotes
|
||||
=========
|
||||
|
||||
.. [1]
|
||||
In all likelihood this would have been Python 2.2 or possibly Python
|
||||
2.3.
|
||||
|
||||
.. [2]
|
||||
The entire PyME git log and other preceding VCS logs are located in
|
||||
the ``gpgme/lang/python/docs/old-commits.log`` file.
|
41
lang/python/doc/rst/what-is-new.rst
Normal file
41
lang/python/doc/rst/what-is-new.rst
Normal file
@ -0,0 +1,41 @@
|
||||
.. _new-stuff:
|
||||
|
||||
What\'s New
|
||||
===========
|
||||
|
||||
+-----------------+------------------------------------------+
|
||||
| Version: | 0.0.1 |
|
||||
+-----------------+------------------------------------------+
|
||||
| GPGME Version: | 1.13.0 |
|
||||
+-----------------+------------------------------------------+
|
||||
| Author: | Ben McGinnes <ben@gnupg.org> |
|
||||
+-----------------+------------------------------------------+
|
||||
| Author GPG Key: | DB4724E6FA4286C92B4E55C4321E4E2373590E5D |
|
||||
+-----------------+------------------------------------------+
|
||||
| Language: | Australian English, British English |
|
||||
+-----------------+------------------------------------------+
|
||||
| xml:lang: | en-AU, en-GB, en |
|
||||
+-----------------+------------------------------------------+
|
||||
|
||||
Last time the most obviously new thing was adding the *What\'s New*
|
||||
section to the HOWTO. Now it\'s moving it out of the HOWTO.
|
||||
|
||||
.. _new-stuff-1-13-0:
|
||||
|
||||
New in GPGME 1·13·0
|
||||
-------------------
|
||||
|
||||
Additions since GPGME 1.12.0 include:
|
||||
|
||||
- Moving the *What\'s New* section out of the basic
|
||||
`HOWTO <gpgme-python-howto.org>`__ document and into its own file so
|
||||
as to more readily include other documents beyond that HOWTO.
|
||||
- Moving the preceding, archival, segments into `another
|
||||
file <what-was-new.org>`__.
|
||||
- Added ``gpg.version.versionintlist`` to make it easier for Python
|
||||
developers to check for a specific version number, even with beta
|
||||
versions (it will drop the \"-betaN\" part).
|
||||
- Added expanded detail on issues pertaining to installing for Windows
|
||||
users.
|
||||
- Bindings enter `maintenance mode <maintenance-mode>`__ from January,
|
||||
2019.
|
111
lang/python/doc/rst/what-was-new.rst
Normal file
111
lang/python/doc/rst/what-was-new.rst
Normal file
@ -0,0 +1,111 @@
|
||||
.. _new-stuff:
|
||||
|
||||
What Was New
|
||||
============
|
||||
|
||||
+-----------------+------------------------------------------+
|
||||
| Version: | 0.0.1 |
|
||||
+-----------------+------------------------------------------+
|
||||
| GPGME Version: | 1.13.0 |
|
||||
+-----------------+------------------------------------------+
|
||||
| Author: | Ben McGinnes <ben@gnupg.org> |
|
||||
+-----------------+------------------------------------------+
|
||||
| Author GPG Key: | DB4724E6FA4286C92B4E55C4321E4E2373590E5D |
|
||||
+-----------------+------------------------------------------+
|
||||
| Language: | Australian English, British English |
|
||||
+-----------------+------------------------------------------+
|
||||
| xml:lang: | en-AU, en-GB, en |
|
||||
+-----------------+------------------------------------------+
|
||||
|
||||
The following are all the past *What\'s New* sections for the Python
|
||||
Bindings HOWTO and other documentation.
|
||||
|
||||
.. _gpgme-1-12-0:
|
||||
|
||||
What Was New in GPGME 1·12·0
|
||||
----------------------------
|
||||
|
||||
The most obviously new point for those reading this guide is this
|
||||
section on other new things, but that's hardly important. Not given all
|
||||
the other things which spurred the need for adding this section and its
|
||||
subsections.
|
||||
|
||||
.. _new-stuff-1-12-0:
|
||||
|
||||
New in GPGME 1·12·0
|
||||
~~~~~~~~~~~~~~~~~~~
|
||||
|
||||
There have been quite a number of additions to GPGME and the Python
|
||||
bindings to it since the last release of GPGME with versions 1.11.0 and
|
||||
1.11.1 in April, 2018.
|
||||
|
||||
The bullet points of new additiions are:
|
||||
|
||||
- an expanded section on
|
||||
`installing <gpgme-python-howto#installation>`__ and
|
||||
`troubleshooting <gpgme-python-howto#snafu>`__ the Python bindings.
|
||||
- The release of Python 3.7.0; which appears to be working just fine
|
||||
with our bindings, in spite of intermittent reports of problems for
|
||||
many other Python projects with that new release.
|
||||
- Python 3.7 has been moved to the head of the specified python
|
||||
versions list in the build process.
|
||||
- In order to fix some other issues, there are certain underlying
|
||||
functions which are more exposed through the
|
||||
`gpg.Context() <gpgme-python-howto#howto-get-context>`__, but ongoing
|
||||
documentation ought to clarify that or otherwise provide the best
|
||||
means of using the bindings. Some additions to ``gpg.core`` and the
|
||||
``Context()``, however, were intended (see below).
|
||||
- Continuing work in identifying and confirming the cause of
|
||||
oft-reported `problems installing the Python bindings on
|
||||
Windows <gpgme-python-howto#snafu-runtime-not-funtime>`__.
|
||||
- GSOC: Google\'s Surreptitiously Ordered Conscription ... erm ... oh,
|
||||
right; Google\'s Summer of Code. Though there were two hopeful
|
||||
candidates this year; only one ended up involved with the GnuPG
|
||||
Project directly, the other concentrated on an unrelated third party
|
||||
project with closer ties to one of the GNU/Linux distributions than
|
||||
to the GnuPG Project. Thus the Python bindings benefited from GSOC
|
||||
participant Jacob Adams, who added the key\ :sub:`import` function;
|
||||
building on prior work by Tobias Mueller.
|
||||
- Several new methods functions were added to the gpg.Context(),
|
||||
including: `key\ import <gpgme-python-howto#howto-import-key>`__,
|
||||
`key\ export <gpgme-python-howto#howto-export-key>`__,
|
||||
`key\ exportminimal <gpgme-python-howto#howto-export-public-key>`__
|
||||
and
|
||||
`key\ exportsecret <gpgme-python-howto#howto-export-secret-key>`__.
|
||||
- Importing and exporting examples include versions integrated with
|
||||
Marcel Fest\'s recently released `HKP for
|
||||
Python <https://github.com/Selfnet/hkp4py>`__ module. Some
|
||||
`additional notes on this module <gpgme-python-howto#hkp4py>`__ are
|
||||
included at the end of the HOWTO.
|
||||
- Instructions for dealing with semi-walled garden implementations like
|
||||
ProtonMail are also included. This is intended to make things a
|
||||
little easier when communicating with users of ProtonMail\'s services
|
||||
and should not be construed as an endorsement of said service. The
|
||||
GnuPG Project neither favours, nor disfavours ProtonMail and the
|
||||
majority of this deals with interacting with the ProtonMail
|
||||
keyserver.
|
||||
- Semi-formalised the location where `draft
|
||||
versions <gpgme-python-howto#draft-editions>`__ of this HOWTO may
|
||||
periodically be accessible. This is both for the reference of others
|
||||
and testing the publishing of the document itself. Renamed this file
|
||||
at around the same time.
|
||||
- The Texinfo documentation build configuration has been replicated
|
||||
from the parent project in order to make to maintain consistency with
|
||||
that project (and actually ship with each release).
|
||||
- a reStructuredText (``.rst``) version is also generated for Python
|
||||
developers more used to and comfortable with that format as it is the
|
||||
standard Python documentation format and Python developers may wish
|
||||
to use it with Sphinx. Please note that there has been no testing of
|
||||
the reStructuredText version with Sphinx at all. The reST file was
|
||||
generated by the simple expedient of using
|
||||
`Pandoc <https://pandoc.org/>`__.
|
||||
- Added a new section for `advanced or experimental
|
||||
use <gpgme-python-howto#advanced-use>`__.
|
||||
- Began the advanced use cases with `a
|
||||
section <gpgme-python-howto#cython>`__ on using the module with
|
||||
`Cython <https://cython.org/>`__.
|
||||
- Added a number of new scripts to the ``example/howto/`` directory;
|
||||
some of which may be in advance of their planned sections of the
|
||||
HOWTO (and some are just there because it seemed like a good idea at
|
||||
the time).
|
||||
- Cleaned up a lot of things under the hood.
|
@ -15,8 +15,8 @@
|
||||
:CUSTOM_ID: intro
|
||||
:END:
|
||||
|
||||
| Version: | 0.1.5 |
|
||||
| GPGME Version: | 1.13.0 |
|
||||
| Version: | 0.1.4 |
|
||||
| GPGME Version: | 1.12.1 |
|
||||
| Author: | Ben McGinnes <ben@gnupg.org> |
|
||||
| Author GPG Key: | DB4724E6FA4286C92B4E55C4321E4E2373590E5D |
|
||||
| Language: | Australian English, British English |
|
||||
@ -397,7 +397,7 @@ both by and in order to create, the bindings (including both the
|
||||
If specifying a selected number of languages to create bindings for,
|
||||
try to leave Python last. Currently the majority of the other
|
||||
language bindings are also preceding Python of either version when
|
||||
listed alphabetically (not counting the Qt bindings).
|
||||
listed alphabetically and so that just happens by default currently.
|
||||
|
||||
If Python is set to precede one of the other languages then it is
|
||||
possible that the errors described here may interrupt the build
|
||||
@ -406,12 +406,6 @@ these cases it may be preferable to configure all preferred language
|
||||
bindings separately with alternative =configure= steps for GPGME using
|
||||
the =--enable-languages=$LANGUAGE= option.
|
||||
|
||||
Alternatively =make= (or =gmake=, depending on your platform) may be
|
||||
run with the the =-k= option, which tells make to keep going even if
|
||||
errors are encountered. In that case the failure of one language's
|
||||
set of bindings to build should not hamper another language's bindings
|
||||
to build.
|
||||
|
||||
|
||||
*** Reinstalling Responsibly
|
||||
:PROPERTIES:
|
||||
@ -464,8 +458,8 @@ case in most, if not all, cases.
|
||||
|
||||
Note that from GPGME [[https://dev.gnupg.org/rMff6ff616aea6f59b7f2ce1176492850ecdf3851e][1.12.1]] the default installation installs to each
|
||||
version of Python it can find first. That is that it will currently
|
||||
install for the first copies of Python versions 2.7, 3.4, 3.5, and so on
|
||||
up until the current dev branch that it finds. Usually this will be in the
|
||||
install for the first copies of Python versions 2.7, 3.4, 3.5, 3.6,
|
||||
3.7 and 3.8 (dev branch) that it finds. Usually this will be in the
|
||||
same prefix as GPGME itself, but is dictated by the =$PATH= when the
|
||||
installation is performed. The above instructions can still be
|
||||
performed on other python installations which the installer does not
|
||||
@ -575,13 +569,6 @@ x86-64 (i.e. Intel and AMD) and ARM architectures for CPython 3.5,
|
||||
3.6, 3.7 and later releases. That's the bare *minimum*, it'd probably
|
||||
be higher.
|
||||
|
||||
Additionally, with only a binary installation used in conjunction with
|
||||
the CPython installer from =python.org= the advanced options available
|
||||
which utilise [[#cython][Cython]] will not be able to be used at all. Cython
|
||||
depends on being able to compile the C code it generates and that too
|
||||
would need to utilise a matching runtime to both the installed version
|
||||
of CPython and these bindings in order to work with the bindings.
|
||||
|
||||
Considering all of that, what do we recommend?
|
||||
|
||||
1. Use a recent version of CPython; at least 3.5, but ideally 3.6 or
|
||||
@ -705,22 +692,6 @@ the command =python3 -m virtualenv /path/to/install/virtual/thingy=
|
||||
instead.
|
||||
|
||||
|
||||
*** Post installation
|
||||
:PROPERTIES:
|
||||
:CUSTOM_ID: snafu-docs
|
||||
:END:
|
||||
|
||||
Following installation it is recommended to move the
|
||||
=post_installer.py= script from the =lang/python/examples/howto/=
|
||||
directory to the =lang/python/= directory and run it. This will fix
|
||||
or restore files needed by Sphinx which may be removed during a
|
||||
distribution build for release. It will also generate reST files from
|
||||
Org mode files with Pandoc and generate Texinfo files from Org mode
|
||||
files with GNU Emacs and Org mode (in batch mode). Additionally it
|
||||
will fix the UTF-8 declaration line in the Texinfo files (Emacs
|
||||
expects "UTF-8" to be "utf-8").
|
||||
|
||||
|
||||
* Fundamentals
|
||||
:PROPERTIES:
|
||||
:CUSTOM_ID: howto-fund-a-mental
|
||||
@ -985,14 +956,6 @@ relative ease by which such key IDs can be reproduced, as demonstrated
|
||||
by the Evil32 Project in 2014 (which was subsequently exploited in
|
||||
2016).
|
||||
|
||||
Testing for whether a string in any given search is or may be a
|
||||
hexadecimal value which may be missing the leading =0x= is a simple
|
||||
matter of using a try/except statement which attempts to convert the
|
||||
string as hex to an integer and then back to hex; then using that to
|
||||
search with. Raising a ValueError simply results in treating the
|
||||
string as a string. This is the method and logic utilised in the
|
||||
=import-keys-hkp.py= script (see below).
|
||||
|
||||
|
||||
*** Working with ProtonMail
|
||||
:PROPERTIES:
|
||||
@ -1127,7 +1090,6 @@ import sys
|
||||
c = gpg.Context()
|
||||
server = hkp4py.KeyServer("hkps://hkps.pool.sks-keyservers.net")
|
||||
results = []
|
||||
keys = []
|
||||
|
||||
if len(sys.argv) > 2:
|
||||
pattern = " ".join(sys.argv[1:])
|
||||
@ -1136,56 +1098,22 @@ elif len(sys.argv) == 2:
|
||||
else:
|
||||
pattern = input("Enter the pattern to search for keys or user IDs: ")
|
||||
|
||||
|
||||
if pattern is not None:
|
||||
try:
|
||||
key = server.search(hex(int(pattern, 16)))
|
||||
keyed = True
|
||||
except ValueError as ve:
|
||||
key = server.search(pattern)
|
||||
keyed = False
|
||||
|
||||
if key is not None:
|
||||
keys.append(key[0])
|
||||
if keyed is True:
|
||||
try:
|
||||
fob = server.search(pattern)
|
||||
except:
|
||||
fob = None
|
||||
if fob is not None:
|
||||
keys.append(fob[0])
|
||||
else:
|
||||
pass
|
||||
else:
|
||||
pass
|
||||
|
||||
try:
|
||||
keys = server.search(pattern)
|
||||
print("Found {0} key(s).".format(len(keys)))
|
||||
except Exception as e:
|
||||
keys = []
|
||||
for logrus in pattern.split():
|
||||
try:
|
||||
key = server.search(hex(int(logrus, 16)))
|
||||
hexed = True
|
||||
except ValueError as ve:
|
||||
if logrus.startswith("0x") is True:
|
||||
key = server.search(logrus)
|
||||
hexed = False
|
||||
|
||||
if key is not None:
|
||||
keys.append(key[0])
|
||||
if hexed is True:
|
||||
try:
|
||||
fob = server.search(logrus)
|
||||
except:
|
||||
fob = None
|
||||
if fob is not None:
|
||||
keys.append(fob[0])
|
||||
else:
|
||||
pass
|
||||
else:
|
||||
pass
|
||||
key = server.search("0x{0}".format(logrus))
|
||||
keys.append(key[0])
|
||||
print("Found {0} key(s).".format(len(keys)))
|
||||
|
||||
|
||||
if len(keys) > 0:
|
||||
for key in keys:
|
||||
import_result = c.key_import(key.key_blob)
|
||||
results.append(import_result)
|
||||
for key in keys:
|
||||
import_result = c.key_import(key.key_blob)
|
||||
results.append(import_result)
|
||||
|
||||
for result in results:
|
||||
if result is not None and hasattr(result, "considered") is False:
|
||||
@ -1612,7 +1540,6 @@ of the entire public keybox.
|
||||
|
||||
#+BEGIN_SRC python -i
|
||||
import gpg
|
||||
import os
|
||||
import os.path
|
||||
import sys
|
||||
|
||||
@ -1620,9 +1547,6 @@ print("""
|
||||
This script exports one or more public keys in minimised form.
|
||||
""")
|
||||
|
||||
def open_0o600(path, flags):
|
||||
return os.open(path, flags, mode=0o600)
|
||||
|
||||
c = gpg.Context(armor=True)
|
||||
|
||||
if len(sys.argv) >= 4:
|
||||
@ -1658,7 +1582,7 @@ except:
|
||||
result = c.key_export_minimal(pattern=None)
|
||||
|
||||
if result is not None:
|
||||
with open(keyfile, "wb", opener=open_0o600) as f:
|
||||
with open(keyfile, "wb") as f:
|
||||
f.write(result)
|
||||
else:
|
||||
pass
|
||||
@ -1690,9 +1614,6 @@ This script exports one or more secret keys.
|
||||
The gpg-agent and pinentry are invoked to authorise the export.
|
||||
""")
|
||||
|
||||
def open_0o600(path, flags):
|
||||
return os.open(path, flags, mode=0o600)
|
||||
|
||||
c = gpg.Context(armor=True)
|
||||
|
||||
if len(sys.argv) >= 4:
|
||||
@ -1742,8 +1663,9 @@ except:
|
||||
result = c.key_export_secret(pattern=None)
|
||||
|
||||
if result is not None:
|
||||
with open(keyfile, "wb", opener=open_0o600)) as f:
|
||||
with open(keyfile, "wb") as f:
|
||||
f.write(result)
|
||||
os.chmod(keyfile, 0o600)
|
||||
else:
|
||||
pass
|
||||
#+END_SRC
|
||||
@ -2166,10 +2088,6 @@ content as a byte object, the recipient key IDs and algorithms in
|
||||
=result= and the results of verifying any signatures of the data in
|
||||
=verify_result=.
|
||||
|
||||
If =gpg.Context().decrypt(cfile, verify=False)= is called instead,
|
||||
then =verify_result= will be returned as =None= and the rest remains
|
||||
as described here.
|
||||
|
||||
|
||||
** Signing text and files
|
||||
:PROPERTIES:
|
||||
@ -2945,7 +2863,7 @@ Save that into a file called =keycount.pyx= and then create a
|
||||
=setup.py= file which contains this:
|
||||
|
||||
#+BEGIN_SRC python -i
|
||||
from setuptools import setup
|
||||
from distutils.core import setup
|
||||
from Cython.Build import cythonize
|
||||
|
||||
setup(
|
||||
@ -3028,29 +2946,33 @@ if sys.platform == "win32":
|
||||
else:
|
||||
gpgconfcmd = "gpgconf --list-options gpg"
|
||||
|
||||
process = subprocess.Popen(gpgconfcmd.split(), stdout=subprocess.PIPE)
|
||||
procom = process.communicate()
|
||||
try:
|
||||
lines = subprocess.getoutput(gpgconfcmd).splitlines()
|
||||
except:
|
||||
process = subprocess.Popen(gpgconfcmd.split(), stdout=subprocess.PIPE)
|
||||
procom = process.communicate()
|
||||
if sys.version_info[0] == 2:
|
||||
lines = procom[0].splitlines()
|
||||
else:
|
||||
lines = procom[0].decode().splitlines()
|
||||
|
||||
if sys.version_info[0] == 2:
|
||||
lines = procom[0].splitlines()
|
||||
else:
|
||||
lines = procom[0].decode().splitlines()
|
||||
|
||||
for line in lines:
|
||||
if line.startswith("group") is True:
|
||||
break
|
||||
for i in range(len(lines)):
|
||||
if lines[i].startswith("group") is True:
|
||||
line = lines[i]
|
||||
else:
|
||||
pass
|
||||
|
||||
groups = line.split(":")[-1].replace('"', '').split(',')
|
||||
|
||||
group_lines = []
|
||||
group_lists = []
|
||||
|
||||
for group in groups:
|
||||
group_lines.append(group.split("="))
|
||||
group_lists.append(group.split("="))
|
||||
for i in range(len(groups)):
|
||||
group_lines.append(groups[i].split("="))
|
||||
group_lists.append(groups[i].split("="))
|
||||
|
||||
for glist in group_lists:
|
||||
glist[1] = glist[1].split()
|
||||
for i in range(len(group_lists)):
|
||||
group_lists[i][1] = group_lists[i][1].split()
|
||||
#+END_SRC
|
||||
|
||||
The result of that code is that =group_lines= is a list of lists where
|
||||
@ -3130,7 +3052,7 @@ minimum required version of GPGME is in use.
|
||||
|
||||
For the most part the =gpg.version.versionstr= and
|
||||
=gpg.version.versionlist= methods have been quite sufficient. The
|
||||
former returns the same string as =pkg-config gpgme --modversion=, while the
|
||||
former returns the same string as =gpgme-config --version=, while the
|
||||
latter returns the major, minor and patch values in a list.
|
||||
|
||||
To check if the installed bindings have actually been built against
|
||||
@ -3141,7 +3063,7 @@ import gpg
|
||||
import subprocess
|
||||
import sys
|
||||
|
||||
gpgme_version_call = subprocess.Popen(["pkg-config", "gpgme", "--modversion"],
|
||||
gpgme_version_call = subprocess.Popen(["gpgme-config", "--version"],
|
||||
stdout=subprocess.PIPE,
|
||||
stderr=subprocess.PIPE)
|
||||
gpgme_version_str = gpgme_version_call.communicate()
|
||||
@ -3222,6 +3144,8 @@ occur in versions which do not have the =gpgme.version.is_beta= and
|
||||
|
||||
Copyright © The GnuPG Project, 2018.
|
||||
|
||||
Copyright (C) The GnuPG Project, 2018.
|
||||
|
||||
|
||||
** Draft Editions of this HOWTO
|
||||
:PROPERTIES:
|
||||
@ -3231,27 +3155,18 @@ Copyright © The GnuPG Project, 2018.
|
||||
Draft editions of this HOWTO may be periodically available directly
|
||||
from the author at any of the following URLs:
|
||||
|
||||
- [[https://files.au.adversary.org/crypto/gpgme-python-howto.html][GPGME Python Bindings HOWTO draft (HTML single file, AWS S3 SSL)]]
|
||||
- [[http://files.au.adversary.org/crypto/gpgme-python-howto.html][GPGME Python Bindings HOWTO draft (HTML single file, AWS S3 no SSL)]]
|
||||
- [[https://files.au.adversary.org/crypto/gpgme-python-howto-split/index.html][GPGME Python Bindings HOWTO draft (HTML multiple files, AWS S3 SSL)]]
|
||||
- [[http://files.au.adversary.org/crypto/gpgme-python-howto/index.html][GPGME Python Bindings HOWTO draft (HTML multiple files, AWS S3 no SSL)]]
|
||||
- [[https://files.au.adversary.org/crypto/gpgme-python-howto.html][GPGME Python Bindings HOWTO draft (XHTML single file, AWS S3 SSL)]]
|
||||
- [[http://files.au.adversary.org/crypto/gpgme-python-howto.html][GPGME Python Bindings HOWTO draft (XHTML single file, AWS S3 no SS)]]
|
||||
- [[https://files.au.adversary.org/crypto/gpgme-python-howto-split/index.html][GPGME Python Bindings HOWTO draft (XHTML multiple files, AWS S3 SSL)]]
|
||||
- [[http://files.au.adversary.org/crypto/gpgme-python-howto-split/index.html][GPGME Python Bindings HOWTO draft (XHTML multiple files, AWS S3 no SSL)]]
|
||||
|
||||
These draft versions have been generated from this document via GNU
|
||||
Emacs [[https://orgmode.org/][Org mode]] to =.texi= and [[https://www.gnu.org/software/texinfo/][GNU Texinfo]] to HTML. Though it is
|
||||
All of these draft versions except for one have been generated from
|
||||
this document via GNU Emacs [[https://orgmode.org/][Org mode]] and [[https://www.gnu.org/software/texinfo/][GNU Texinfo]]. Though it is
|
||||
likely that the specific [[https://files.au.adversary.org/crypto/gpgme-python-howto][file]] [[http://files.au.adversary.org/crypto/gpgme-python-howto.org][version]] used will be on the same server
|
||||
with the generated output formats. Occasionally I may include the Org
|
||||
mode generated XHTML versions:
|
||||
|
||||
- [[https://files.au.adversary.org/crypto/gpgme-python-howto.xhtml][GPGME Python Bindings HOWTO draft (HTML single file, AWS S3 SSL)]]
|
||||
- [[http://files.au.adversary.org/crypto/gpgme-python-howto.xhtml][GPGME Python Bindings HOWTO draft (HTML single file, AWS S3 no SSL)]]
|
||||
|
||||
That XHTML version, however, is exported in a way which inherits a
|
||||
colour scheme from [[https://github.com/holomorph/emacs-zenburn][the author's Emacs theme]] (which is a higher contrast
|
||||
version of [[http://kippura.org/zenburnpage/][Zenburn]] ported by [[https://github.com/holomorph][Holomorph]]). So it's fine for people who
|
||||
prefer dark themed web pages, but not so great for everyone else.
|
||||
with the generated output formats.
|
||||
|
||||
The GNU Texinfo and reStructured Text versions ship with the software,
|
||||
while the GNU Emacs Info version is generated from the Texinfo
|
||||
while the GNU Emacs Info verseion is generated from the Texinfo
|
||||
version using GNU Texinfo or GNU Makeinfo. The Texinfo format is
|
||||
generated from the original Org mode source file in Org mode itself
|
||||
either within GNU Emacs or via the command line by invoking Emacs in
|
||||
@ -3262,63 +3177,20 @@ batch mode:
|
||||
emacs gpgme-python-howto --batch -f org-texinfo-export-to-texinfo --kill
|
||||
#+END_SRC
|
||||
|
||||
The reStructuredText format is also generated from the Org mode source
|
||||
The reStructuredText format is also generated from the Org-mode source
|
||||
file, except it is generated using [[https://pandoc.org][Pandoc]] with either of the following
|
||||
commands (depending on the filename):
|
||||
commands:
|
||||
|
||||
#+BEGIN_SRC shell
|
||||
pandoc -f org -t rst+smart -o gpgme-python-howto.rst gpgme-python-howto.org
|
||||
pandoc -f org -t rst+smart -o gpgme-python-howto.rst gpgme-python-howto
|
||||
#+END_SRC
|
||||
|
||||
Note that the Org mode source files are identified as such via a mode
|
||||
line at the top of each file and have had their =.org= file extensions
|
||||
dropped in order to make scripted generation of output formats easier
|
||||
and not require renaming files post-conversion.
|
||||
|
||||
Due to a bug in Org mode's texinfo conversion method, the recommended
|
||||
steps for generating the Texinfo files for all the files in the
|
||||
=lang/python/doc/src/= directory are as follows:
|
||||
|
||||
#+BEGIN_SRC shell
|
||||
for x in * ; do
|
||||
emacs $x --batch -f org-texinfo-export-to-texinfo --kill
|
||||
cat $x.texi | sed -e 's/@documentencoding UTF-8/@documentencoding utf-8/g' > ../texinfo/$x.texi
|
||||
pandoc -f org -t rst+smart -o ../rst/$x.rst $x
|
||||
done ;
|
||||
rm -fv *.texi
|
||||
cd ../texinfo
|
||||
mkdir info
|
||||
mkdir html
|
||||
for x in *.texi ; do
|
||||
makeinfo -v $x
|
||||
makeinfo --html --no-split $x
|
||||
done ;
|
||||
mv *.info info/
|
||||
mv *.html html/
|
||||
#+END_SRC
|
||||
|
||||
This code snippet includes the generation of the reStructuredText
|
||||
files and would be expected to be run from the =doc/src/= directory
|
||||
containing the Org mode source files. It also assumes that the
|
||||
commands are being run on POSIX compliant systems with basic tools
|
||||
like sed, the Bourne shell and GNU Emacs[fn:6] available. The code
|
||||
snippet also includes the steps for generating the Emacs Info files
|
||||
and HTML files from the Texinfo files. Using reStructuredText files
|
||||
with Sphinx is best left for the documentation of that project.
|
||||
|
||||
In addition to these there is a significantly less frequently updated
|
||||
version as a HTML [[https://files.au.adversary.org/crypto/gpgme-python/dita/webhelp/index.html][WebHelp site]] (AWS S3 SSL); generated from DITA XML
|
||||
version as a HTML [[https://files.au.adversary.org/crypto/gpgme-python-howto/webhelp/index.html][WebHelp site]] (AWS S3 SSL); generated from DITA XML
|
||||
source files, which can be found in [[https://dev.gnupg.org/source/gpgme/browse/ben%252Fhowto-dita/][an alternative branch]] of the GPGME
|
||||
git repository.
|
||||
|
||||
Various generated output formats may occasionally be found in
|
||||
subdirectories of the [[https://s3.amazonaws.com/files.au.adversary.org/crypto/gpgme-python][gpgme-python]] directory. In particular within
|
||||
the [[https://s3.amazonaws.com/files.au.adversary.org/crypto/gpgme-python/dita][DITA]], [[https://s3.amazonaws.com/files.au.adversary.org/crypto/gpgme-python/rst][reStructuredText]] and [[https://s3.amazonaws.com/files.au.adversary.org/crypto/gpgme-python/texinfo][Texinfo]] subdirectories. The =rst=
|
||||
directory contains output files generated with Sphinx and may include a
|
||||
considerable number of its possible output formats, but there are no
|
||||
guarantees as to how recent these are or even if they are present.
|
||||
|
||||
These draft editions are not official documents and the version of
|
||||
documentation in the master branch or which ships with released
|
||||
versions is the only official documentation. Nevertheless, these
|
||||
@ -3372,8 +3244,3 @@ restricted servers which only advertise either HTTP or HTTPS end
|
||||
points and not HKP or HKPS end points must still be identified as as
|
||||
HKP or HKPS within the Python Code. The =hkp4py= module will rewrite
|
||||
these appropriately when the connection is made to the server.
|
||||
|
||||
[fn:6] Okay, Emacs might not necessarily qualify as a basic tool, but
|
||||
it is common enough that having it installed on a system isn't too
|
||||
great an expectation, nor is it difficult to add to most POSIX
|
||||
systems, even if the users of those systems do not personally use it.
|
@ -93,43 +93,3 @@ basis. Expediting such a request would require funding that request.
|
||||
Those with a commercial interest in expediting such a feature request
|
||||
already know how to [[https://gnupg.org/cgi-bin/procdonate.cgi?mode=preset][expedite it]] (use the message field to state what
|
||||
feature is being requested).
|
||||
|
||||
|
||||
** Documentation formats
|
||||
:PROPERTIES:
|
||||
:CUSTOM_ID: docs
|
||||
:END:
|
||||
|
||||
The documentation has been written in Org mode for GNU Emacs, with
|
||||
both Texinfo and reStructuredText formats generated from that. The
|
||||
Texinfo files are intended for use with the rest of the GnuPG
|
||||
documentation; while the reStructuredText files are intended for use
|
||||
with Docutils and Sphinx, as with other Python projects.
|
||||
|
||||
|
||||
*** Cautionary Notes regarding Sphinx and EPUB
|
||||
:PROPERTIES:
|
||||
:CUSTOM_ID: sphinx-made-epubs-suck
|
||||
:END:
|
||||
|
||||
Though Python's Docutils in conjunction with Sphinx is capable of
|
||||
generating some very useful HTML sites, as proven by [[https://readthedocs.org/][Read the Docs]] and
|
||||
the [[https://docs.python.org/][Python documentation]], there are a number of output formats it does
|
||||
not handle well. At the top of the list of things it manages to break
|
||||
so atrociously as to be embarassing is the [[http://idpf.org/epub][EPUB 3]] format.
|
||||
|
||||
The automatically generated EPUB of the CPython documentation always
|
||||
contains hundreds of validation errors and even the modest amount of
|
||||
documentation here [[https://files.au.adversary.org.s3.amazonaws.com/crypto/gpgme-python/rst/epub/GPGMEPythonBindings.epub][produced a file]] with approximately thirty
|
||||
validation errors. As the volume of documentation content increases,
|
||||
so does the induced errors. Whereas Texinfo doesn't produce EPUB
|
||||
output at all, nor does Org-mode.
|
||||
|
||||
Should there ever be genuine demand for this format, lodge a [[https://dev.gnupg.org/maniphest/task/edit/form/4/][feature
|
||||
request]] case marked for [[https://dev.gnupg.org/p/BenM/][my]] attention. The means of generating such
|
||||
files flawlessly is already available, but is not yet part of the
|
||||
GnuPG build system. Nor is it integrated with a means of converting
|
||||
Org mode input files to the relevant base format automatically, as can
|
||||
already be done when converting Org to reStructuredText or Org to
|
||||
Texinfo. As a certain amount of work would be required to get it
|
||||
done, there would need to be clear demand for that work to be done.
|
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in New Issue
Block a user