From 49195c487e6c923f7137f092b982e7d833d98de6 Mon Sep 17 00:00:00 2001 From: Alon Bar-Lev Date: Wed, 5 Apr 2017 19:47:08 +0300 Subject: python: simplify build, some fixups * lang/python/gpg/version.py.in: Rename to lang/python/version.py.in. configure.ac: Generate version.py.in in lang/python. * lang/python/MANIFEST.in: Include version.py explicitly. * lang/python/gpg: Rename to 'src'. * lang/python/Makefile.am: Do not copy source files, do not use absolute directories, support lib64 in uninstall, clean also dist directory, use symlink for gpg src. * lang/python/setup.py.in: Use builddir, copy sources into builddir, copy version.py into module. -- Simplify build to symlink the gpg sources into builddir instead of copying. This requires handling of version.py as generated file. In addition apply some cleanups: Drop the absolution pathes, clean the dist directory as well, support lib64 for sitelib at uninstall. Signed-off-by: Alon Bar-Lev --- lang/python/MANIFEST.in | 1 + lang/python/Makefile.am | 38 +- lang/python/gpg/__init__.py | 121 -- lang/python/gpg/callbacks.py | 49 - lang/python/gpg/constants/__init__.py | 142 --- lang/python/gpg/constants/create.py | 25 - lang/python/gpg/constants/data/__init__.py | 6 - lang/python/gpg/constants/data/encoding.py | 23 - lang/python/gpg/constants/event.py | 23 - lang/python/gpg/constants/import.py | 23 - lang/python/gpg/constants/keylist/__init__.py | 6 - lang/python/gpg/constants/keylist/mode.py | 23 - lang/python/gpg/constants/keysign.py | 25 - lang/python/gpg/constants/md.py | 23 - lang/python/gpg/constants/pk.py | 23 - lang/python/gpg/constants/protocol.py | 23 - lang/python/gpg/constants/sig/__init__.py | 6 - lang/python/gpg/constants/sig/mode.py | 23 - lang/python/gpg/constants/sig/notation.py | 25 - lang/python/gpg/constants/sigsum.py | 23 - lang/python/gpg/constants/status.py | 124 -- lang/python/gpg/constants/tofu/__init__.py | 24 - lang/python/gpg/constants/tofu/policy.py | 25 - lang/python/gpg/constants/validity.py | 23 - lang/python/gpg/core.py | 1490 ------------------------- lang/python/gpg/errors.py | 128 --- lang/python/gpg/results.py | 118 -- lang/python/gpg/util.py | 53 - lang/python/gpg/version.py.in | 68 -- lang/python/setup.py.in | 23 +- lang/python/src/__init__.py | 121 ++ lang/python/src/callbacks.py | 49 + lang/python/src/constants/__init__.py | 142 +++ lang/python/src/constants/create.py | 25 + lang/python/src/constants/data/__init__.py | 6 + lang/python/src/constants/data/encoding.py | 23 + lang/python/src/constants/event.py | 23 + lang/python/src/constants/import.py | 23 + lang/python/src/constants/keylist/__init__.py | 6 + lang/python/src/constants/keylist/mode.py | 23 + lang/python/src/constants/keysign.py | 25 + lang/python/src/constants/md.py | 23 + lang/python/src/constants/pk.py | 23 + lang/python/src/constants/protocol.py | 23 + lang/python/src/constants/sig/__init__.py | 6 + lang/python/src/constants/sig/mode.py | 23 + lang/python/src/constants/sig/notation.py | 25 + lang/python/src/constants/sigsum.py | 23 + lang/python/src/constants/status.py | 124 ++ lang/python/src/constants/tofu/__init__.py | 24 + lang/python/src/constants/tofu/policy.py | 25 + lang/python/src/constants/validity.py | 23 + lang/python/src/core.py | 1490 +++++++++++++++++++++++++ lang/python/src/errors.py | 128 +++ lang/python/src/results.py | 118 ++ lang/python/src/util.py | 53 + lang/python/version.py.in | 68 ++ 57 files changed, 2688 insertions(+), 2704 deletions(-) delete mode 100644 lang/python/gpg/__init__.py delete mode 100644 lang/python/gpg/callbacks.py delete mode 100644 lang/python/gpg/constants/__init__.py delete mode 100644 lang/python/gpg/constants/create.py delete mode 100644 lang/python/gpg/constants/data/__init__.py delete mode 100644 lang/python/gpg/constants/data/encoding.py delete mode 100644 lang/python/gpg/constants/event.py delete mode 100644 lang/python/gpg/constants/import.py delete mode 100644 lang/python/gpg/constants/keylist/__init__.py delete mode 100644 lang/python/gpg/constants/keylist/mode.py delete mode 100644 lang/python/gpg/constants/keysign.py delete mode 100644 lang/python/gpg/constants/md.py delete mode 100644 lang/python/gpg/constants/pk.py delete mode 100644 lang/python/gpg/constants/protocol.py delete mode 100644 lang/python/gpg/constants/sig/__init__.py delete mode 100644 lang/python/gpg/constants/sig/mode.py delete mode 100644 lang/python/gpg/constants/sig/notation.py delete mode 100644 lang/python/gpg/constants/sigsum.py delete mode 100644 lang/python/gpg/constants/status.py delete mode 100644 lang/python/gpg/constants/tofu/__init__.py delete mode 100644 lang/python/gpg/constants/tofu/policy.py delete mode 100644 lang/python/gpg/constants/validity.py delete mode 100644 lang/python/gpg/core.py delete mode 100644 lang/python/gpg/errors.py delete mode 100644 lang/python/gpg/results.py delete mode 100644 lang/python/gpg/util.py delete mode 100644 lang/python/gpg/version.py.in create mode 100644 lang/python/src/__init__.py create mode 100644 lang/python/src/callbacks.py create mode 100644 lang/python/src/constants/__init__.py create mode 100644 lang/python/src/constants/create.py create mode 100644 lang/python/src/constants/data/__init__.py create mode 100644 lang/python/src/constants/data/encoding.py create mode 100644 lang/python/src/constants/event.py create mode 100644 lang/python/src/constants/import.py create mode 100644 lang/python/src/constants/keylist/__init__.py create mode 100644 lang/python/src/constants/keylist/mode.py create mode 100644 lang/python/src/constants/keysign.py create mode 100644 lang/python/src/constants/md.py create mode 100644 lang/python/src/constants/pk.py create mode 100644 lang/python/src/constants/protocol.py create mode 100644 lang/python/src/constants/sig/__init__.py create mode 100644 lang/python/src/constants/sig/mode.py create mode 100644 lang/python/src/constants/sig/notation.py create mode 100644 lang/python/src/constants/sigsum.py create mode 100644 lang/python/src/constants/status.py create mode 100644 lang/python/src/constants/tofu/__init__.py create mode 100644 lang/python/src/constants/tofu/policy.py create mode 100644 lang/python/src/constants/validity.py create mode 100644 lang/python/src/core.py create mode 100644 lang/python/src/errors.py create mode 100644 lang/python/src/results.py create mode 100644 lang/python/src/util.py create mode 100644 lang/python/version.py.in (limited to 'lang') diff --git a/lang/python/MANIFEST.in b/lang/python/MANIFEST.in index ff38172d..c34e84a2 100644 --- a/lang/python/MANIFEST.in +++ b/lang/python/MANIFEST.in @@ -1,4 +1,5 @@ recursive-include examples *.py include gpgme.i include helpers.c helpers.h private.h +include version.py recursive-include gpg *.py diff --git a/lang/python/Makefile.am b/lang/python/Makefile.am index 42beeee2..4ebd214e 100644 --- a/lang/python/Makefile.am +++ b/lang/python/Makefile.am @@ -22,28 +22,19 @@ EXTRA_DIST = \ gpgme.i \ helpers.c helpers.h private.h \ examples \ - gpg + src SUBDIRS = . tests -COPY_FILES_GPG = \ - $(srcdir)/gpg/callbacks.py \ - $(srcdir)/gpg/constants \ - $(srcdir)/gpg/core.py \ - $(srcdir)/gpg/errors.py \ - $(srcdir)/gpg/__init__.py \ - $(srcdir)/gpg/results.py \ - $(srcdir)/gpg/util.py - .PHONY: prepare prepare: copystamp # For VPATH builds we need to copy some files because Python's # distutils are not VPATH-aware. copystamp: - ln -sf "$(abs_top_srcdir)/src/data.h" . - ln -sf "$(abs_top_builddir)/config.h" . - if test $(srcdir) != . ; then cp -R $(COPY_FILES_GPG) gpg ; fi + ln -sf "$(top_srcdir)/src/data.h" . + ln -sf "$(top_builddir)/config.h" . + ln -sf "$(srcdir)/src" gpg touch $@ all-local: copystamp @@ -51,7 +42,7 @@ all-local: copystamp PYTHON="$$1" ; shift ; \ CFLAGS="$(CFLAGS)" \ srcdir="$(srcdir)" \ - abs_top_builddir="$(abs_top_builddir)" \ + top_builddir="$(top_builddir)" \ $$PYTHON setup.py build --verbose --build-base=python$${VERSION}-gpg ; \ done @@ -59,7 +50,7 @@ python$(PYTHON_VERSION)-gpg/dist/gpg-$(VERSION).tar.gz.asc: copystamp $(MKDIR_P) python$(PYTHON_VERSION)-gpg-dist CFLAGS="$(CFLAGS)" \ srcdir="$(srcdir)" \ - abs_top_builddir="$(abs_top_builddir)" \ + top_builddir="$(top_builddir)" \ $(PYTHON) setup.py sdist --verbose --dist-dir=python$(PYTHON_VERSION)-gpg-dist \ --manifest=python$(PYTHON_VERSION)-gpg-dist/MANIFEST gpg2 --detach-sign --armor python$(PYTHON_VERSION)-gpg-dist/gpg-$(VERSION).tar.gz @@ -75,6 +66,7 @@ upload: python$(PYTHON_VERSION)-gpg-dist/gpg-$(VERSION).tar.gz \ CLEANFILES = copystamp \ config.h \ data.h \ + gpg \ files.txt \ install_files.txt @@ -84,22 +76,16 @@ CLEANFILES = copystamp \ # permissions. clean-local: rm -rf -- build - if test $(srcdir) != . ; then \ - find gpg -type d ! -perm -200 -exec chmod u+w {} ';' ; \ - for FILE in $(COPY_FILES_GPG); do \ - rm -rf -- gpg/$$(basename $$FILE) ; \ - done \ - fi for VERSION in $(PYTHON_VERSIONS); do \ - find python$${VERSION}-gpg -type d ! -perm -200 -exec chmod u+w {} ';' ; \ - rm -rf -- python$${VERSION}-gpg ; \ + find python$${VERSION}-gpg* -type d ! -perm -200 -exec chmod u+w {} ';' ; \ + rm -rf -- python$${VERSION}-gpg* ; \ done install-exec-local: set -e ; set $(PYTHONS); for VERSION in $(PYTHON_VERSIONS); do \ PYTHON="$$1" ; shift ; \ srcdir="$(srcdir)" \ - abs_top_builddir="$(abs_top_builddir)" \ + top_builddir="$(top_builddir)" \ $$PYTHON setup.py \ build \ --build-base=python$${VERSION}-gpg \ @@ -110,6 +96,6 @@ install-exec-local: uninstall-local: GV=$$(echo $(VERSION) | tr - _); for PV in $(PYTHON_VERSIONS); do \ - rm -rf -- "$(DESTDIR)$(prefix)/lib/python$$PV/site-packages/gpg" \ -"$(DESTDIR)$(prefix)/lib/python$$PV/site-packages/gpg-$$GV-py$$PV.egg-info" ; \ + rm -rf -- "$(DESTDIR)$(prefix)"/lib*/python$$PV/site-packages/gpg \ +"$(DESTDIR)$(prefix)"/lib*/python$$PV/site-packages/gpg-$$GV-py$$PV.egg-info ; \ done diff --git a/lang/python/gpg/__init__.py b/lang/python/gpg/__init__.py deleted file mode 100644 index 385b17e3..00000000 --- a/lang/python/gpg/__init__.py +++ /dev/null @@ -1,121 +0,0 @@ -# Copyright (C) 2016 g10 Code GmbH -# Copyright (C) 2004 Igor Belyi -# Copyright (C) 2002 John Goerzen -# -# This library is free software; you can redistribute it and/or -# modify it under the terms of the GNU Lesser General Public -# License as published by the Free Software Foundation; either -# version 2.1 of the License, or (at your option) any later version. -# -# This library is distributed in the hope that it will be useful, -# but WITHOUT ANY WARRANTY; without even the implied warranty of -# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU -# Lesser General Public License for more details. -# -# You should have received a copy of the GNU Lesser General Public -# License along with this library; if not, write to the Free Software -# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - -"""gpg: GnuPG Interface for Python (GPGME bindings) - -Welcome to gpg, the GnuPG Interface for Python. - -The latest release of this package may be obtained from -https://www.gnupg.org - -FEATURES --------- - - * Feature-rich, full implementation of the GPGME library. Supports - all GPGME features. Callback functions may be written in pure - Python. Exceptions raised in callbacks are properly propagated. - - * Ability to sign, encrypt, decrypt, and verify data. - - * Ability to list keys, export and import keys, and manage the keyring. - - * Fully object-oriented with convenient classes and modules. - -QUICK EXAMPLE -------------- - - >>> import gpg - >>> with gpg.Context() as c: - >>> with gpg.Context() as c: - ... cipher, _, _ = c.encrypt("Hello world :)".encode(), - ... passphrase="abc") - ... c.decrypt(cipher, passphrase="abc") - ... - (b'Hello world :)', - , - ) - -GENERAL OVERVIEW ----------------- - -For those of you familiar with GPGME, you will be right at home here. - -The python gpg module is, for the most part, a direct interface to the C GPGME -library. However, it is re-packaged in a more Pythonic way -- -object-oriented with classes and modules. Take a look at the classes -defined here -- they correspond directly to certain object types in GPGME -for C. For instance, the following C code: - -gpgme_ctx_t context; -gpgme_new(&context); -... -gpgme_op_encrypt(context, recp, 1, plain, cipher); - -Translates into the following Python code: - -context = core.Context() -... -context.op_encrypt(recp, 1, plain, cipher) - -The Python module automatically does error-checking and raises Python -exception gpg.errors.GPGMEError when GPGME signals an error. getcode() -and getsource() of this exception return code and source of the error. - -IMPORTANT NOTE --------------- -This documentation only covers a small subset of available GPGME functions and -methods. Please consult the documentation for the C library -for comprehensive coverage. - -This library uses Python's reflection to automatically detect the methods -that are available for each class, and as such, most of those methods -do not appear explicitly anywhere. You can use dir() python built-in command -on an object to see what methods and fields it has but their meaning can -be found only in GPGME documentation. - -FOR MORE INFORMATION --------------------- -GnuPG homepage: https://www.gnupg.org/ -GPGME documentation: https://www.gnupg.org/documentation/manuals/gpgme/ - -""" - -from __future__ import absolute_import, print_function, unicode_literals -del absolute_import, print_function, unicode_literals - -from . import core -from . import errors -from . import constants -from . import util -from . import callbacks -from . import version -from .core import Context -from .core import Data - -# Interface hygiene. - -# Drop the low-level gpgme that creeps in for some reason. -gpgme = None -del gpgme - -# This is a white-list of symbols. Any other will alert pyflakes. -_ = [Context, Data, core, errors, constants, util, callbacks, version] -del _ - -__all__ = ["Context", "Data", - "core", "errors", "constants", "util", "callbacks", "version"] diff --git a/lang/python/gpg/callbacks.py b/lang/python/gpg/callbacks.py deleted file mode 100644 index b25a9a74..00000000 --- a/lang/python/gpg/callbacks.py +++ /dev/null @@ -1,49 +0,0 @@ -# Copyright (C) 2004 Igor Belyi -# Copyright (C) 2002 John Goerzen -# -# This library is free software; you can redistribute it and/or -# modify it under the terms of the GNU Lesser General Public -# License as published by the Free Software Foundation; either -# version 2.1 of the License, or (at your option) any later version. -# -# This library is distributed in the hope that it will be useful, -# but WITHOUT ANY WARRANTY; without even the implied warranty of -# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU -# Lesser General Public License for more details. -# -# You should have received a copy of the GNU Lesser General Public -# License along with this library; if not, write to the Free Software -# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - -from __future__ import absolute_import, print_function, unicode_literals -del absolute_import, print_function, unicode_literals - -from getpass import getpass - -def passphrase_stdin(hint, desc, prev_bad, hook=None): - """This is a sample callback that will read a passphrase from - the terminal. The hook here, if present, will be used to describe - why the passphrase is needed.""" - why = '' - if hook != None: - why = ' ' + hook - if prev_bad: - why += ' (again)' - print("Please supply %s' password%s:" % (hint, why)) - return getpass() - -def progress_stdout(what, type, current, total, hook=None): - print("PROGRESS UPDATE: what = %s, type = %d, current = %d, total = %d" %\ - (what, type, current, total)) - -def readcb_fh(count, hook): - """A callback for data. hook should be a Python file-like object.""" - if count: - # Should return '' on EOF - return hook.read(count) - else: - # Wants to rewind. - if not hasattr(hook, 'seek'): - return None - hook.seek(0, 0) - return None diff --git a/lang/python/gpg/constants/__init__.py b/lang/python/gpg/constants/__init__.py deleted file mode 100644 index 484ffd29..00000000 --- a/lang/python/gpg/constants/__init__.py +++ /dev/null @@ -1,142 +0,0 @@ -# Constants. -# -# Copyright (C) 2016 g10 Code GmbH -# -# This file is part of GPGME. -# -# GPGME is free software; you can redistribute it and/or modify it -# under the terms of the GNU Lesser General Public License as -# published by the Free Software Foundation; either version 2.1 of the -# License, or (at your option) any later version. -# -# GPGME is distributed in the hope that it will be useful, but WITHOUT -# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY -# or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General -# Public License for more details. -# -# You should have received a copy of the GNU Lesser General Public -# License along with this program; if not, see . - -from __future__ import absolute_import, print_function, unicode_literals -del absolute_import, print_function, unicode_literals - -from gpg import util -util.process_constants('GPGME_', globals()) -del util - -# For convenience, we import the modules here. -from . import data, keylist, sig, tofu # The subdirs. -from . import create, event, keysign, md, pk, protocol, sigsum, status, validity - -# A complication arises because 'import' is a reserved keyword. -# Import it as 'Import' instead. -globals()['Import'] = getattr(__import__('', globals(), locals(), - [str('import')], 1), "import") - -__all__ = ['data', 'event', 'import', 'keysign', 'keylist', 'md', 'pk', - 'protocol', 'sig', 'sigsum', 'status', 'tofu', 'validity', 'create'] - -# GPGME 1.7 replaced gpgme_op_edit with gpgme_op_interact. We -# implement gpg.Context.op_edit using gpgme_op_interact, so the -# callbacks will be called with string keywords instead of numeric -# status messages. Code that is using these constants will continue -# to work. - -STATUS_ABORT = "ABORT" -STATUS_ALREADY_SIGNED = "ALREADY_SIGNED" -STATUS_ATTRIBUTE = "ATTRIBUTE" -STATUS_BACKUP_KEY_CREATED = "BACKUP_KEY_CREATED" -STATUS_BAD_PASSPHRASE = "BAD_PASSPHRASE" -STATUS_BADARMOR = "BADARMOR" -STATUS_BADMDC = "BADMDC" -STATUS_BADSIG = "BADSIG" -STATUS_BEGIN_DECRYPTION = "BEGIN_DECRYPTION" -STATUS_BEGIN_ENCRYPTION = "BEGIN_ENCRYPTION" -STATUS_BEGIN_SIGNING = "BEGIN_SIGNING" -STATUS_BEGIN_STREAM = "BEGIN_STREAM" -STATUS_CARDCTRL = "CARDCTRL" -STATUS_DECRYPTION_FAILED = "DECRYPTION_FAILED" -STATUS_DECRYPTION_INFO = "DECRYPTION_INFO" -STATUS_DECRYPTION_OKAY = "DECRYPTION_OKAY" -STATUS_DELETE_PROBLEM = "DELETE_PROBLEM" -STATUS_ENC_TO = "ENC_TO" -STATUS_END_DECRYPTION = "END_DECRYPTION" -STATUS_END_ENCRYPTION = "END_ENCRYPTION" -STATUS_END_STREAM = "END_STREAM" -STATUS_ENTER = "ENTER" -STATUS_ERRMDC = "ERRMDC" -STATUS_ERROR = "ERROR" -STATUS_ERRSIG = "ERRSIG" -STATUS_EXPKEYSIG = "EXPKEYSIG" -STATUS_EXPSIG = "EXPSIG" -STATUS_FAILURE = "FAILURE" -STATUS_FILE_DONE = "FILE_DONE" -STATUS_FILE_ERROR = "FILE_ERROR" -STATUS_FILE_START = "FILE_START" -STATUS_GET_BOOL = "GET_BOOL" -STATUS_GET_HIDDEN = "GET_HIDDEN" -STATUS_GET_LINE = "GET_LINE" -STATUS_GOOD_PASSPHRASE = "GOOD_PASSPHRASE" -STATUS_GOODMDC = "GOODMDC" -STATUS_GOODSIG = "GOODSIG" -STATUS_GOT_IT = "GOT_IT" -STATUS_IMPORT_OK = "IMPORT_OK" -STATUS_IMPORT_PROBLEM = "IMPORT_PROBLEM" -STATUS_IMPORT_RES = "IMPORT_RES" -STATUS_IMPORTED = "IMPORTED" -STATUS_INQUIRE_MAXLEN = "INQUIRE_MAXLEN" -STATUS_INV_RECP = "INV_RECP" -STATUS_INV_SGNR = "INV_SGNR" -STATUS_KEY_CONSIDERED = "KEY_CONSIDERED" -STATUS_KEY_CREATED = "KEY_CREATED" -STATUS_KEY_NOT_CREATED = "KEY_NOT_CREATED" -STATUS_KEYEXPIRED = "KEYEXPIRED" -STATUS_KEYREVOKED = "KEYREVOKED" -STATUS_LEAVE = "LEAVE" -STATUS_MISSING_PASSPHRASE = "MISSING_PASSPHRASE" -STATUS_MOUNTPOINT = "MOUNTPOINT" -STATUS_NEED_PASSPHRASE = "NEED_PASSPHRASE" -STATUS_NEED_PASSPHRASE_PIN = "NEED_PASSPHRASE_PIN" -STATUS_NEED_PASSPHRASE_SYM = "NEED_PASSPHRASE_SYM" -STATUS_NEWSIG = "NEWSIG" -STATUS_NO_PUBKEY = "NO_PUBKEY" -STATUS_NO_RECP = "NO_RECP" -STATUS_NO_SECKEY = "NO_SECKEY" -STATUS_NO_SGNR = "NO_SGNR" -STATUS_NODATA = "NODATA" -STATUS_NOTATION_DATA = "NOTATION_DATA" -STATUS_NOTATION_FLAGS = "NOTATION_FLAGS" -STATUS_NOTATION_NAME = "NOTATION_NAME" -STATUS_PINENTRY_LAUNCHED = "PINENTRY_LAUNCHED" -STATUS_PKA_TRUST_BAD = "PKA_TRUST_BAD" -STATUS_PKA_TRUST_GOOD = "PKA_TRUST_GOOD" -STATUS_PLAINTEXT = "PLAINTEXT" -STATUS_PLAINTEXT_LENGTH = "PLAINTEXT_LENGTH" -STATUS_POLICY_URL = "POLICY_URL" -STATUS_PROGRESS = "PROGRESS" -STATUS_REVKEYSIG = "REVKEYSIG" -STATUS_RSA_OR_IDEA = "RSA_OR_IDEA" -STATUS_SC_OP_FAILURE = "SC_OP_FAILURE" -STATUS_SC_OP_SUCCESS = "SC_OP_SUCCESS" -STATUS_SESSION_KEY = "SESSION_KEY" -STATUS_SHM_GET = "SHM_GET" -STATUS_SHM_GET_BOOL = "SHM_GET_BOOL" -STATUS_SHM_GET_HIDDEN = "SHM_GET_HIDDEN" -STATUS_SHM_INFO = "SHM_INFO" -STATUS_SIG_CREATED = "SIG_CREATED" -STATUS_SIG_ID = "SIG_ID" -STATUS_SIG_SUBPACKET = "SIG_SUBPACKET" -STATUS_SIGEXPIRED = "SIGEXPIRED" -STATUS_SUCCESS = "SUCCESS" -STATUS_TOFU_STATS = "TOFU_STATS" -STATUS_TOFU_STATS_LONG = "TOFU_STATS_LONG" -STATUS_TOFU_USER = "TOFU_USER" -STATUS_TRUNCATED = "TRUNCATED" -STATUS_TRUST_FULLY = "TRUST_FULLY" -STATUS_TRUST_MARGINAL = "TRUST_MARGINAL" -STATUS_TRUST_NEVER = "TRUST_NEVER" -STATUS_TRUST_ULTIMATE = "TRUST_ULTIMATE" -STATUS_TRUST_UNDEFINED = "TRUST_UNDEFINED" -STATUS_UNEXPECTED = "UNEXPECTED" -STATUS_USERID_HINT = "USERID_HINT" -STATUS_VALIDSIG = "VALIDSIG" diff --git a/lang/python/gpg/constants/create.py b/lang/python/gpg/constants/create.py deleted file mode 100644 index 132e96d4..00000000 --- a/lang/python/gpg/constants/create.py +++ /dev/null @@ -1,25 +0,0 @@ -# Flags for key creation -# -# Copyright (C) 2017 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 . - -from __future__ import absolute_import, print_function, unicode_literals -del absolute_import, print_function, unicode_literals - -from gpg import util -util.process_constants('GPGME_CREATE_', globals()) -del util diff --git a/lang/python/gpg/constants/data/__init__.py b/lang/python/gpg/constants/data/__init__.py deleted file mode 100644 index 8274ab91..00000000 --- a/lang/python/gpg/constants/data/__init__.py +++ /dev/null @@ -1,6 +0,0 @@ - -from __future__ import absolute_import, print_function, unicode_literals -del absolute_import, print_function, unicode_literals - -from . import encoding -__all__ = ['encoding'] diff --git a/lang/python/gpg/constants/data/encoding.py b/lang/python/gpg/constants/data/encoding.py deleted file mode 100644 index e76a22ee..00000000 --- a/lang/python/gpg/constants/data/encoding.py +++ /dev/null @@ -1,23 +0,0 @@ -# Copyright (C) 2004 Igor Belyi -# Copyright (C) 2002 John Goerzen -# -# This library is free software; you can redistribute it and/or -# modify it under the terms of the GNU Lesser General Public -# License as published by the Free Software Foundation; either -# version 2.1 of the License, or (at your option) any later version. -# -# This library is distributed in the hope that it will be useful, -# but WITHOUT ANY WARRANTY; without even the implied warranty of -# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU -# Lesser General Public License for more details. -# -# You should have received a copy of the GNU Lesser General Public -# License along with this library; if not, write to the Free Software -# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - -from __future__ import absolute_import, print_function, unicode_literals -del absolute_import, print_function, unicode_literals - -from gpg import util -util.process_constants('GPGME_DATA_ENCODING_', globals()) -del util diff --git a/lang/python/gpg/constants/event.py b/lang/python/gpg/constants/event.py deleted file mode 100644 index 1b14d1d1..00000000 --- a/lang/python/gpg/constants/event.py +++ /dev/null @@ -1,23 +0,0 @@ -# Copyright (C) 2004 Igor Belyi -# Copyright (C) 2002 John Goerzen -# -# This library is free software; you can redistribute it and/or -# modify it under the terms of the GNU Lesser General Public -# License as published by the Free Software Foundation; either -# version 2.1 of the License, or (at your option) any later version. -# -# This library is distributed in the hope that it will be useful, -# but WITHOUT ANY WARRANTY; without even the implied warranty of -# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU -# Lesser General Public License for more details. -# -# You should have received a copy of the GNU Lesser General Public -# License along with this library; if not, write to the Free Software -# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - -from __future__ import absolute_import, print_function, unicode_literals -del absolute_import, print_function, unicode_literals - -from gpg import util -util.process_constants('GPGME_EVENT_', globals()) -del util diff --git a/lang/python/gpg/constants/import.py b/lang/python/gpg/constants/import.py deleted file mode 100644 index 47c296cb..00000000 --- a/lang/python/gpg/constants/import.py +++ /dev/null @@ -1,23 +0,0 @@ -# Copyright (C) 2004 Igor Belyi -# Copyright (C) 2002 John Goerzen -# -# This library is free software; you can redistribute it and/or -# modify it under the terms of the GNU Lesser General Public -# License as published by the Free Software Foundation; either -# version 2.1 of the License, or (at your option) any later version. -# -# This library is distributed in the hope that it will be useful, -# but WITHOUT ANY WARRANTY; without even the implied warranty of -# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU -# Lesser General Public License for more details. -# -# You should have received a copy of the GNU Lesser General Public -# License along with this library; if not, write to the Free Software -# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - -from __future__ import absolute_import, print_function, unicode_literals -del absolute_import, print_function, unicode_literals - -from gpg import util -util.process_constants('GPGME_IMPORT_', globals()) -del util diff --git a/lang/python/gpg/constants/keylist/__init__.py b/lang/python/gpg/constants/keylist/__init__.py deleted file mode 100644 index 2ce0edfd..00000000 --- a/lang/python/gpg/constants/keylist/__init__.py +++ /dev/null @@ -1,6 +0,0 @@ - -from __future__ import absolute_import, print_function, unicode_literals -del absolute_import, print_function, unicode_literals - -from . import mode -__all__ = ['mode'] diff --git a/lang/python/gpg/constants/keylist/mode.py b/lang/python/gpg/constants/keylist/mode.py deleted file mode 100644 index 39e1819d..00000000 --- a/lang/python/gpg/constants/keylist/mode.py +++ /dev/null @@ -1,23 +0,0 @@ -# Copyright (C) 2004 Igor Belyi -# Copyright (C) 2002 John Goerzen -# -# This library is free software; you can redistribute it and/or -# modify it under the terms of the GNU Lesser General Public -# License as published by the Free Software Foundation; either -# version 2.1 of the License, or (at your option) any later version. -# -# This library is distributed in the hope that it will be useful, -# but WITHOUT ANY WARRANTY; without even the implied warranty of -# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU -# Lesser General Public License for more details. -# -# You should have received a copy of the GNU Lesser General Public -# License along with this library; if not, write to the Free Software -# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - -from __future__ import absolute_import, print_function, unicode_literals -del absolute_import, print_function, unicode_literals - -from gpg import util -util.process_constants('GPGME_KEYLIST_MODE_', globals()) -del util diff --git a/lang/python/gpg/constants/keysign.py b/lang/python/gpg/constants/keysign.py deleted file mode 100644 index fccdbc42..00000000 --- a/lang/python/gpg/constants/keysign.py +++ /dev/null @@ -1,25 +0,0 @@ -# Flags for key signing -# -# Copyright (C) 2017 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 . - -from __future__ import absolute_import, print_function, unicode_literals -del absolute_import, print_function, unicode_literals - -from gpg import util -util.process_constants('GPGME_KEYSIGN_', globals()) -del util diff --git a/lang/python/gpg/constants/md.py b/lang/python/gpg/constants/md.py deleted file mode 100644 index f3e8bbdb..00000000 --- a/lang/python/gpg/constants/md.py +++ /dev/null @@ -1,23 +0,0 @@ -# Copyright (C) 2004 Igor Belyi -# Copyright (C) 2002 John Goerzen -# -# This library is free software; you can redistribute it and/or -# modify it under the terms of the GNU Lesser General Public -# License as published by the Free Software Foundation; either -# version 2.1 of the License, or (at your option) any later version. -# -# This library is distributed in the hope that it will be useful, -# but WITHOUT ANY WARRANTY; without even the implied warranty of -# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU -# Lesser General Public License for more details. -# -# You should have received a copy of the GNU Lesser General Public -# License along with this library; if not, write to the Free Software -# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - -from __future__ import absolute_import, print_function, unicode_literals -del absolute_import, print_function, unicode_literals - -from gpg import util -util.process_constants('GPGME_MD_', globals()) -del util diff --git a/lang/python/gpg/constants/pk.py b/lang/python/gpg/constants/pk.py deleted file mode 100644 index 6bf2a215..00000000 --- a/lang/python/gpg/constants/pk.py +++ /dev/null @@ -1,23 +0,0 @@ -# Copyright (C) 2004 Igor Belyi -# Copyright (C) 2002 John Goerzen -# -# This library is free software; you can redistribute it and/or -# modify it under the terms of the GNU Lesser General Public -# License as published by the Free Software Foundation; either -# version 2.1 of the License, or (at your option) any later version. -# -# This library is distributed in the hope that it will be useful, -# but WITHOUT ANY WARRANTY; without even the implied warranty of -# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU -# Lesser General Public License for more details. -# -# You should have received a copy of the GNU Lesser General Public -# License along with this library; if not, write to the Free Software -# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - -from __future__ import absolute_import, print_function, unicode_literals -del absolute_import, print_function, unicode_literals - -from gpg import util -util.process_constants('GPGME_PK_', globals()) -del util diff --git a/lang/python/gpg/constants/protocol.py b/lang/python/gpg/constants/protocol.py deleted file mode 100644 index d086bbde..00000000 --- a/lang/python/gpg/constants/protocol.py +++ /dev/null @@ -1,23 +0,0 @@ -# Copyright (C) 2004 Igor Belyi -# Copyright (C) 2002 John Goerzen -# -# This library is free software; you can redistribute it and/or -# modify it under the terms of the GNU Lesser General Public -# License as published by the Free Software Foundation; either -# version 2.1 of the License, or (at your option) any later version. -# -# This library is distributed in the hope that it will be useful, -# but WITHOUT ANY WARRANTY; without even the implied warranty of -# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU -# Lesser General Public License for more details. -# -# You should have received a copy of the GNU Lesser General Public -# License along with this library; if not, write to the Free Software -# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - -from __future__ import absolute_import, print_function, unicode_literals -del absolute_import, print_function, unicode_literals - -from gpg import util -util.process_constants('GPGME_PROTOCOL_', globals()) -del util diff --git a/lang/python/gpg/constants/sig/__init__.py b/lang/python/gpg/constants/sig/__init__.py deleted file mode 100644 index 39d4e6e1..00000000 --- a/lang/python/gpg/constants/sig/__init__.py +++ /dev/null @@ -1,6 +0,0 @@ - -from __future__ import absolute_import, print_function, unicode_literals -del absolute_import, print_function, unicode_literals - -from . import mode, notation -__all__ = ['mode', 'notation'] diff --git a/lang/python/gpg/constants/sig/mode.py b/lang/python/gpg/constants/sig/mode.py deleted file mode 100644 index 0f4f0efc..00000000 --- a/lang/python/gpg/constants/sig/mode.py +++ /dev/null @@ -1,23 +0,0 @@ -# Copyright (C) 2004 Igor Belyi -# Copyright (C) 2002 John Goerzen -# -# This library is free software; you can redistribute it and/or -# modify it under the terms of the GNU Lesser General Public -# License as published by the Free Software Foundation; either -# version 2.1 of the License, or (at your option) any later version. -# -# This library is distributed in the hope that it will be useful, -# but WITHOUT ANY WARRANTY; without even the implied warranty of -# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU -# Lesser General Public License for more details. -# -# You should have received a copy of the GNU Lesser General Public -# License along with this library; if not, write to the Free Software -# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - -from __future__ import absolute_import, print_function, unicode_literals -del absolute_import, print_function, unicode_literals - -from gpg import util -util.process_constants('GPGME_SIG_MODE_', globals()) -del util diff --git a/lang/python/gpg/constants/sig/notation.py b/lang/python/gpg/constants/sig/notation.py deleted file mode 100644 index 9a79e014..00000000 --- a/lang/python/gpg/constants/sig/notation.py +++ /dev/null @@ -1,25 +0,0 @@ -# Constants for signature notation data. -# -# Copyright (C) 2016 g10 Code GmbH -# -# This file is part of GPGME. -# -# GPGME is free software; you can redistribute it and/or modify it -# under the terms of the GNU Lesser General Public License as -# published by the Free Software Foundation; either version 2.1 of the -# License, or (at your option) any later version. -# -# GPGME is distributed in the hope that it will be useful, but WITHOUT -# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY -# or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General -# Public License for more details. -# -# You should have received a copy of the GNU Lesser General Public -# License along with this program; if not, see . - -from __future__ import absolute_import, print_function, unicode_literals -del absolute_import, print_function, unicode_literals - -from gpg import util -util.process_constants('GPGME_SIG_NOTATION_', globals()) -del util diff --git a/lang/python/gpg/constants/sigsum.py b/lang/python/gpg/constants/sigsum.py deleted file mode 100644 index 09ef9d78..00000000 --- a/lang/python/gpg/constants/sigsum.py +++ /dev/null @@ -1,23 +0,0 @@ -# Copyright (C) 2004 Igor Belyi -# Copyright (C) 2002 John Goerzen -# -# This library is free software; you can redistribute it and/or -# modify it under the terms of the GNU Lesser General Public -# License as published by the Free Software Foundation; either -# version 2.1 of the License, or (at your option) any later version. -# -# This library is distributed in the hope that it will be useful, -# but WITHOUT ANY WARRANTY; without even the implied warranty of -# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU -# Lesser General Public License for more details. -# -# You should have received a copy of the GNU Lesser General Public -# License along with this library; if not, write to the Free Software -# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - -from __future__ import absolute_import, print_function, unicode_literals -del absolute_import, print_function, unicode_literals - -from gpg import util -util.process_constants('GPGME_SIGSUM_', globals()) -del util diff --git a/lang/python/gpg/constants/status.py b/lang/python/gpg/constants/status.py deleted file mode 100644 index a0ad073e..00000000 --- a/lang/python/gpg/constants/status.py +++ /dev/null @@ -1,124 +0,0 @@ -# Copyright (C) 2004 Igor Belyi -# Copyright (C) 2002 John Goerzen -# -# This library is free software; you can redistribute it and/or -# modify it under the terms of the GNU Lesser General Public -# License as published by the Free Software Foundation; either -# version 2.1 of the License, or (at your option) any later version. -# -# This library is distributed in the hope that it will be useful, -# but WITHOUT ANY WARRANTY; without even the implied warranty of -# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU -# Lesser General Public License for more details. -# -# You should have received a copy of the GNU Lesser General Public -# License along with this library; if not, write to the Free Software -# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - -from __future__ import absolute_import, print_function, unicode_literals -del absolute_import, print_function, unicode_literals - -# GPGME 1.7 replaced gpgme_op_edit with gpgme_op_interact. We -# implement gpg.Context.op_edit using gpgme_op_interact, so the -# callbacks will be called with string keywords instead of numeric -# status messages. Code that is using these constants will continue -# to work. - -ABORT = "ABORT" -ALREADY_SIGNED = "ALREADY_SIGNED" -ATTRIBUTE = "ATTRIBUTE" -BACKUP_KEY_CREATED = "BACKUP_KEY_CREATED" -BAD_PASSPHRASE = "BAD_PASSPHRASE" -BADARMOR = "BADARMOR" -BADMDC = "BADMDC" -BADSIG = "BADSIG" -BEGIN_DECRYPTION = "BEGIN_DECRYPTION" -BEGIN_ENCRYPTION = "BEGIN_ENCRYPTION" -BEGIN_SIGNING = "BEGIN_SIGNING" -BEGIN_STREAM = "BEGIN_STREAM" -CARDCTRL = "CARDCTRL" -DECRYPTION_FAILED = "DECRYPTION_FAILED" -DECRYPTION_INFO = "DECRYPTION_INFO" -DECRYPTION_OKAY = "DECRYPTION_OKAY" -DELETE_PROBLEM = "DELETE_PROBLEM" -ENC_TO = "ENC_TO" -END_DECRYPTION = "END_DECRYPTION" -END_ENCRYPTION = "END_ENCRYPTION" -END_STREAM = "END_STREAM" -ENTER = "ENTER" -ERRMDC = "ERRMDC" -ERROR = "ERROR" -ERRSIG = "ERRSIG" -EXPKEYSIG = "EXPKEYSIG" -EXPSIG = "EXPSIG" -FAILURE = "FAILURE" -FILE_DONE = "FILE_DONE" -FILE_ERROR = "FILE_ERROR" -FILE_START = "FILE_START" -GET_BOOL = "GET_BOOL" -GET_HIDDEN = "GET_HIDDEN" -GET_LINE = "GET_LINE" -GOOD_PASSPHRASE = "GOOD_PASSPHRASE" -GOODMDC = "GOODMDC" -GOODSIG = "GOODSIG" -GOT_IT = "GOT_IT" -IMPORT_OK = "IMPORT_OK" -IMPORT_PROBLEM = "IMPORT_PROBLEM" -IMPORT_RES = "IMPORT_RES" -IMPORTED = "IMPORTED" -INQUIRE_MAXLEN = "INQUIRE_MAXLEN" -INV_RECP = "INV_RECP" -INV_SGNR = "INV_SGNR" -KEY_CONSIDERED = "KEY_CONSIDERED" -KEY_CREATED = "KEY_CREATED" -KEY_NOT_CREATED = "KEY_NOT_CREATED" -KEYEXPIRED = "KEYEXPIRED" -KEYREVOKED = "KEYREVOKED" -LEAVE = "LEAVE" -MISSING_PASSPHRASE = "MISSING_PASSPHRASE" -MOUNTPOINT = "MOUNTPOINT" -NEED_PASSPHRASE = "NEED_PASSPHRASE" -NEED_PASSPHRASE_PIN = "NEED_PASSPHRASE_PIN" -NEED_PASSPHRASE_SYM = "NEED_PASSPHRASE_SYM" -NEWSIG = "NEWSIG" -NO_PUBKEY = "NO_PUBKEY" -NO_RECP = "NO_RECP" -NO_SECKEY = "NO_SECKEY" -NO_SGNR = "NO_SGNR" -NODATA = "NODATA" -NOTATION_DATA = "NOTATION_DATA" -NOTATION_FLAGS = "NOTATION_FLAGS" -NOTATION_NAME = "NOTATION_NAME" -PINENTRY_LAUNCHED = "PINENTRY_LAUNCHED" -PKA_TRUST_BAD = "PKA_TRUST_BAD" -PKA_TRUST_GOOD = "PKA_TRUST_GOOD" -PLAINTEXT = "PLAINTEXT" -PLAINTEXT_LENGTH = "PLAINTEXT_LENGTH" -POLICY_URL = "POLICY_URL" -PROGRESS = "PROGRESS" -REVKEYSIG = "REVKEYSIG" -RSA_OR_IDEA = "RSA_OR_IDEA" -SC_OP_FAILURE = "SC_OP_FAILURE" -SC_OP_SUCCESS = "SC_OP_SUCCESS" -SESSION_KEY = "SESSION_KEY" -SHM_GET = "SHM_GET" -SHM_GET_BOOL = "SHM_GET_BOOL" -SHM_GET_HIDDEN = "SHM_GET_HIDDEN" -SHM_INFO = "SHM_INFO" -SIG_CREATED = "SIG_CREATED" -SIG_ID = "SIG_ID" -SIG_SUBPACKET = "SIG_SUBPACKET" -SIGEXPIRED = "SIGEXPIRED" -SUCCESS = "SUCCESS" -TOFU_STATS = "TOFU_STATS" -TOFU_STATS_LONG = "TOFU_STATS_LONG" -TOFU_USER = "TOFU_USER" -TRUNCATED = "TRUNCATED" -TRUST_FULLY = "TRUST_FULLY" -TRUST_MARGINAL = "TRUST_MARGINAL" -TRUST_NEVER = "TRUST_NEVER" -TRUST_ULTIMATE = "TRUST_ULTIMATE" -TRUST_UNDEFINED = "TRUST_UNDEFINED" -UNEXPECTED = "UNEXPECTED" -USERID_HINT = "USERID_HINT" -VALIDSIG = "VALIDSIG" diff --git a/lang/python/gpg/constants/tofu/__init__.py b/lang/python/gpg/constants/tofu/__init__.py deleted file mode 100644 index 819a58bb..00000000 --- a/lang/python/gpg/constants/tofu/__init__.py +++ /dev/null @@ -1,24 +0,0 @@ -# TOFU -# -# Copyright (C) 2017 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 . - -from __future__ import absolute_import, print_function, unicode_literals -del absolute_import, print_function, unicode_literals - -from . import policy -__all__ = ['policy'] diff --git a/lang/python/gpg/constants/tofu/policy.py b/lang/python/gpg/constants/tofu/policy.py deleted file mode 100644 index 5a61f067..00000000 --- a/lang/python/gpg/constants/tofu/policy.py +++ /dev/null @@ -1,25 +0,0 @@ -# TOFU policies -# -# Copyright (C) 2017 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 . - -from __future__ import absolute_import, print_function, unicode_literals -del absolute_import, print_function, unicode_literals - -from gpg import util -util.process_constants('GPGME_TOFU_POLICY_', globals()) -del util diff --git a/lang/python/gpg/constants/validity.py b/lang/python/gpg/constants/validity.py deleted file mode 100644 index d3c53458..00000000 --- a/lang/python/gpg/constants/validity.py +++ /dev/null @@ -1,23 +0,0 @@ -# Copyright (C) 2004 Igor Belyi -# Copyright (C) 2002 John Goerzen -# -# This library is free software; you can redistribute it and/or -# modify it under the terms of the GNU Lesser General Public -# License as published by the Free Software Foundation; either -# version 2.1 of the License, or (at your option) any later version. -# -# This library is distributed in the hope that it will be useful, -# but WITHOUT ANY WARRANTY; without even the implied warranty of -# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU -# Lesser General Public License for more details. -# -# You should have received a copy of the GNU Lesser General Public -# License along with this library; if not, write to the Free Software -# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - -from __future__ import absolute_import, print_function, unicode_literals -del absolute_import, print_function, unicode_literals - -from gpg import util -util.process_constants('GPGME_VALIDITY_', globals()) -del util diff --git a/lang/python/gpg/core.py b/lang/python/gpg/core.py deleted file mode 100644 index 632f4ca5..00000000 --- a/lang/python/gpg/core.py +++ /dev/null @@ -1,1490 +0,0 @@ -# Copyright (C) 2016-2017 g10 Code GmbH -# Copyright (C) 2004,2008 Igor Belyi -# Copyright (C) 2002 John Goerzen -# -# This library is free software; you can redistribute it and/or -# modify it under the terms of the GNU Lesser General Public -# License as published by the Free Software Foundation; either -# version 2.1 of the License, or (at your option) any later version. -# -# This library is distributed in the hope that it will be useful, -# but WITHOUT ANY WARRANTY; without even the implied warranty of -# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU -# Lesser General Public License for more details. -# -# You should have received a copy of the GNU Lesser General Public -# License along with this library; if not, write to the Free Software -# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - -"""Core functionality - -Core functionality of GPGME wrapped in a object-oriented fashion. -Provides the 'Context' class for performing cryptographic operations, -and the 'Data' class describing buffers of data. - -""" - -from __future__ import absolute_import, print_function, unicode_literals -del absolute_import, print_function, unicode_literals - -import re -import os -import warnings -import weakref -from . import gpgme -from .errors import errorcheck, GPGMEError -from . import constants -from . import errors -from . import util - -class GpgmeWrapper(object): - """Base wrapper class - - Not to be instantiated directly. - - """ - - def __init__(self, wrapped): - self._callback_excinfo = None - self.wrapped = wrapped - - def __repr__(self): - return '<{}/{!r}>'.format(super(GpgmeWrapper, self).__repr__(), - self.wrapped) - - def __str__(self): - acc = ['{}.{}'.format(__name__, self.__class__.__name__)] - flags = [f for f in self._boolean_properties if getattr(self, f)] - if flags: - acc.append('({})'.format(' '.join(flags))) - - return '<{}>'.format(' '.join(acc)) - - def __hash__(self): - return hash(repr(self.wrapped)) - - def __eq__(self, other): - if other == None: - return False - else: - return repr(self.wrapped) == repr(other.wrapped) - - @property - def _ctype(self): - """The name of the c type wrapped by this class - - Must be set by child classes. - - """ - raise NotImplementedError() - - @property - def _cprefix(self): - """The common prefix of c functions wrapped by this class - - Must be set by child classes. - - """ - raise NotImplementedError() - - def _errorcheck(self, name): - """Must be implemented by child classes. - - This function must return a trueish value for all c functions - returning gpgme_error_t.""" - raise NotImplementedError() - - """The set of all boolean properties""" - _boolean_properties = set() - - def __wrap_boolean_property(self, key, do_set=False, value=None): - get_func = getattr(gpgme, - "{}get_{}".format(self._cprefix, key)) - set_func = getattr(gpgme, - "{}set_{}".format(self._cprefix, key)) - def get(slf): - return bool(get_func(slf.wrapped)) - def set_(slf, value): - set_func(slf.wrapped, bool(value)) - - p = property(get, set_, doc="{} flag".format(key)) - setattr(self.__class__, key, p) - - if do_set: - set_(self, bool(value)) - else: - return get(self) - - _munge_docstring = re.compile(r'gpgme_([^(]*)\(([^,]*), (.*\) -> .*)') - def __getattr__(self, key): - """On-the-fly generation of wrapper methods and properties""" - if key[0] == '_' or self._cprefix == None: - return None - - if key in self._boolean_properties: - return self.__wrap_boolean_property(key) - - name = self._cprefix + key - func = getattr(gpgme, name) - - if self._errorcheck(name): - def _funcwrap(slf, *args): - result = func(slf.wrapped, *args) - if slf._callback_excinfo: - gpgme.gpg_raise_callback_exception(slf) - return errorcheck(result, "Invocation of " + name) - else: - def _funcwrap(slf, *args): - result = func(slf.wrapped, *args) - if slf._callback_excinfo: - gpgme.gpg_raise_callback_exception(slf) - return result - - doc = self._munge_docstring.sub(r'\2.\1(\3', getattr(func, "__doc__")) - _funcwrap.__doc__ = doc - - # Monkey-patch the class. - setattr(self.__class__, key, _funcwrap) - - # Bind the method to 'self'. - def wrapper(*args): - return _funcwrap(self, *args) - wrapper.__doc__ = doc - - return wrapper - - def __setattr__(self, key, value): - """On-the-fly generation of properties""" - if key in self._boolean_properties: - self.__wrap_boolean_property(key, True, value) - else: - super(GpgmeWrapper, self).__setattr__(key, value) - -class Context(GpgmeWrapper): - """Context for cryptographic operations - - All cryptographic operations in GPGME are performed within a - context, which contains the internal state of the operation as - well as configuration parameters. By using several contexts you - can run several cryptographic operations in parallel, with - different configuration. - - Access to a context must be synchronized. - - """ - - def __init__(self, armor=False, textmode=False, offline=False, - signers=[], pinentry_mode=constants.PINENTRY_MODE_DEFAULT, - protocol=constants.PROTOCOL_OpenPGP, - wrapped=None, home_dir=None): - """Construct a context object - - Keyword arguments: - armor -- enable ASCII armoring (default False) - textmode -- enable canonical text mode (default False) - offline -- do not contact external key sources (default False) - signers -- list of keys used for signing (default []) - pinentry_mode -- pinentry mode (default PINENTRY_MODE_DEFAULT) - protocol -- protocol to use (default PROTOCOL_OpenPGP) - home_dir -- state directory (default is the engine default) - - """ - if wrapped: - self.own = False - else: - tmp = gpgme.new_gpgme_ctx_t_p() - errorcheck(gpgme.gpgme_new(tmp)) - wrapped = gpgme.gpgme_ctx_t_p_value(tmp) - gpgme.delete_gpgme_ctx_t_p(tmp) - self.own = True - super(Context, self).__init__(wrapped) - self.armor = armor - self.textmode = textmode - self.offline = offline - self.signers = signers - self.pinentry_mode = pinentry_mode - self.protocol = protocol - self.home_dir = home_dir - - def __repr__(self): - return ( - "Context(armor={0.armor}, " - "textmode={0.textmode}, offline={0.offline}, " - "signers={0.signers}, pinentry_mode={0.pinentry_mode}, " - "protocol={0.protocol}, home_dir={0.home_dir}" - ")").format(self) - - def encrypt(self, plaintext, recipients=[], sign=True, sink=None, - passphrase=None, always_trust=False, add_encrypt_to=False, - prepare=False, expect_sign=False, compress=True): - """Encrypt data - - Encrypt the given plaintext for the given recipients. If the - list of recipients is empty, the data is encrypted - symmetrically with a passphrase. - - The passphrase can be given as parameter, using a callback - registered at the context, or out-of-band via pinentry. - - Keyword arguments: - recipients -- list of keys to encrypt to - sign -- sign plaintext (default True) - sink -- write result to sink instead of returning it - passphrase -- for symmetric encryption - always_trust -- always trust the keys (default False) - add_encrypt_to -- encrypt to configured additional keys (default False) - prepare -- (ui) prepare for encryption (default False) - expect_sign -- (ui) prepare for signing (default False) - compress -- compress plaintext (default True) - - Returns: - ciphertext -- the encrypted data (or None if sink is given) - result -- additional information about the encryption - sign_result -- additional information about the signature(s) - - Raises: - InvalidRecipients -- if encryption using a particular key failed - InvalidSigners -- if signing using a particular key failed - GPGMEError -- as signaled by the underlying library - - """ - ciphertext = sink if sink else Data() - flags = 0 - flags |= always_trust * constants.ENCRYPT_ALWAYS_TRUST - flags |= (not add_encrypt_to) * constants.ENCRYPT_NO_ENCRYPT_TO - flags |= prepare * constants.ENCRYPT_PREPARE - flags |= expect_sign * constants.ENCRYPT_EXPECT_SIGN - flags |= (not compress) * constants.ENCRYPT_NO_COMPRESS - - if passphrase != None: - old_pinentry_mode = self.pinentry_mode - old_passphrase_cb = getattr(self, '_passphrase_cb', None) - self.pinentry_mode = constants.PINENTRY_MODE_LOOPBACK - def passphrase_cb(hint, desc, prev_bad, hook=None): - return passphrase - self.set_passphrase_cb(passphrase_cb) - - try: - if sign: - self.op_encrypt_sign(recipients, flags, plaintext, ciphertext) - else: - self.op_encrypt(recipients, flags, plaintext, ciphertext) - except errors.GPGMEError as e: - if e.getcode() == errors.UNUSABLE_PUBKEY: - result = self.op_encrypt_result() - if result.invalid_recipients: - raise errors.InvalidRecipients(result.invalid_recipients) - if e.getcode() == errors.UNUSABLE_SECKEY: - sig_result = self.op_sign_result() - if sig_result.invalid_signers: - raise errors.InvalidSigners(sig_result.invalid_signers) - raise - finally: - if passphrase != None: - self.pinentry_mode = old_pinentry_mode - if old_passphrase_cb: - self.set_passphrase_cb(*old_passphrase_cb[1:]) - - result = self.op_encrypt_result() - assert not result.invalid_recipients - sig_result = self.op_sign_result() if sign else None - assert not sig_result or not sig_result.invalid_signers - - cipherbytes = None - if not sink: - ciphertext.seek(0, os.SEEK_SET) - cipherbytes = ciphertext.read() - return cipherbytes, result, sig_result - - def decrypt(self, ciphertext, sink=None, passphrase=None, verify=True): - """Decrypt data - - Decrypt the given ciphertext and verify any signatures. If - VERIFY is an iterable of keys, the ciphertext must be signed - by all those keys, otherwise an error is raised. - - If the ciphertext is symmetrically encrypted using a - passphrase, that passphrase can be given as parameter, using a - callback registered at the context, or out-of-band via - pinentry. - - Keyword arguments: - sink -- write result to sink instead of returning it - passphrase -- for symmetric decryption - verify -- check signatures (default True) - - Returns: - plaintext -- the decrypted data (or None if sink is given) - result -- additional information about the decryption - verify_result -- additional information about the signature(s) - - Raises: - UnsupportedAlgorithm -- if an unsupported algorithm was used - BadSignatures -- if a bad signature is encountered - MissingSignatures -- if expected signatures are missing or bad - GPGMEError -- as signaled by the underlying library - - """ - plaintext = sink if sink else Data() - - if passphrase != None: - old_pinentry_mode = self.pinentry_mode - old_passphrase_cb = getattr(self, '_passphrase_cb', None) - self.pinentry_mode = constants.PINENTRY_MODE_LOOPBACK - def passphrase_cb(hint, desc, prev_bad, hook=None): - return passphrase - self.set_passphrase_cb(passphrase_cb) - - try: - if verify: - self.op_decrypt_verify(ciphertext, plaintext) - else: - self.op_decrypt(ciphertext, plaintext) - finally: - if passphrase != None: - self.pinentry_mode = old_pinentry_mode - if old_passphrase_cb: - self.set_passphrase_cb(*old_passphrase_cb[1:]) - - result = self.op_decrypt_result() - verify_result = self.op_verify_result() if verify else None - if result.unsupported_algorithm: - raise errors.UnsupportedAlgorithm(result.unsupported_algorithm) - - if verify: - if any(s.status != errors.NO_ERROR - for s in verify_result.signatures): - raise errors.BadSignatures(verify_result) - - if verify and verify != True: - missing = list() - for key in verify: - ok = False - for subkey in key.subkeys: - for sig in verify_result.signatures: - if sig.summary & constants.SIGSUM_VALID == 0: - continue - if subkey.can_sign and subkey.fpr == sig.fpr: - ok = True - break - if ok: - break - if not ok: - missing.append(key) - if missing: - raise errors.MissingSignatures(verify_result, missing) - - plainbytes = None - if not sink: - plaintext.seek(0, os.SEEK_SET) - plainbytes = plaintext.read() - return plainbytes, result, verify_result - - def sign(self, data, sink=None, mode=constants.SIG_MODE_NORMAL): - """Sign data - - Sign the given data with either the configured default local - key, or the 'signers' keys of this context. - - Keyword arguments: - mode -- signature mode (default: normal, see below) - sink -- write result to sink instead of returning it - - Returns: - either - signed_data -- encoded data and signature (normal mode) - signature -- only the signature data (detached mode) - cleartext -- data and signature as text (cleartext mode) - (or None if sink is given) - result -- additional information about the signature(s) - - Raises: - InvalidSigners -- if signing using a particular key failed - GPGMEError -- as signaled by the underlying library - - """ - signeddata = sink if sink else Data() - - try: - self.op_sign(data, signeddata, mode) - except errors.GPGMEError as e: - if e.getcode() == errors.UNUSABLE_SECKEY: - result = self.op_sign_result() - if result.invalid_signers: - raise errors.InvalidSigners(result.invalid_signers) - raise - - result = self.op_sign_result() - assert not result.invalid_signers - - signedbytes = None - if not sink: - signeddata.seek(0, os.SEEK_SET) - signedbytes = signeddata.read() - return signedbytes, result - - def verify(self, signed_data, signature=None, sink=None, verify=[]): - """Verify signatures - - Verify signatures over data. If VERIFY is an iterable of - keys, the ciphertext must be signed by all those keys, - otherwise an error is raised. - - Keyword arguments: - signature -- detached signature data - sink -- write result to sink instead of returning it - - Returns: - data -- the plain data - (or None if sink is given, or we verified a detached signature) - result -- additional information about the signature(s) - - Raises: - BadSignatures -- if a bad signature is encountered - MissingSignatures -- if expected signatures are missing or bad - GPGMEError -- as signaled by the underlying library - - """ - if signature: - # Detached signature, we don't return the plain text. - data = None - else: - data = sink if sink else Data() - - if signature: - self.op_verify(signature, signed_data, None) - else: - self.op_verify(signed_data, None, data) - - result = self.op_verify_result() - if any(s.status != errors.NO_ERROR for s in result.signatures): - raise errors.BadSignatures(result) - - missing = list() - for key in verify: - ok = False - for subkey in key.subkeys: - for sig in result.signatures: - if sig.summary & constants.SIGSUM_VALID == 0: - continue - if subkey.can_sign and subkey.fpr == sig.fpr: - ok = True - break - if ok: - break - if not ok: - missing.append(key) - if missing: - raise errors.MissingSignatures(result, missing) - - plainbytes = None - if data and not sink: - data.seek(0, os.SEEK_SET) - plainbytes = data.read() - return plainbytes, result - - def keylist(self, pattern=None, secret=False, - mode=constants.keylist.mode.LOCAL, - source=None): - """List keys - - Keyword arguments: - pattern -- return keys matching pattern (default: all keys) - secret -- return only secret keys (default: False) - mode -- keylist mode (default: list local keys) - source -- read keys from source instead from the keyring - (all other options are ignored in this case) - - Returns: - -- an iterator returning key objects - - Raises: - GPGMEError -- as signaled by the underlying library - """ - if not source: - self.set_keylist_mode(mode) - self.op_keylist_start(pattern, secret) - else: - # Automatic wrapping of SOURCE is not possible here, - # because the object must not be deallocated until the - # iteration over the results ends. - if not isinstance(source, Data): - source = Data(file=source) - self.op_keylist_from_data_start(source, 0) - - key = self.op_keylist_next() - while key: - yield key - key = self.op_keylist_next() - self.op_keylist_end() - - def create_key(self, userid, algorithm=None, expires_in=0, expires=True, - sign=False, encrypt=False, certify=False, authenticate=False, - passphrase=None, force=False): - """Create a primary key - - Create a primary key for the user id USERID. - - ALGORITHM may be used to specify the public key encryption - algorithm for the new key. By default, a reasonable default - is chosen. You may use "future-default" to select an - algorithm that will be the default in a future implementation - of the engine. ALGORITHM may be a string like "rsa", or - "rsa2048" to explicitly request an algorithm and a key size. - - EXPIRES_IN specifies the expiration time of the key in number - of seconds since the keys creation. By default, a reasonable - expiration time is chosen. If you want to create a key that - does not expire, use the keyword argument EXPIRES. - - SIGN, ENCRYPT, CERTIFY, and AUTHENTICATE can be used to - request the capabilities of the new key. If you don't request - any, a reasonable set of capabilities is selected, and in case - of OpenPGP, a subkey with a reasonable set of capabilities is - created. - - If PASSPHRASE is None (the default), then the key will not be - protected with a passphrase. If PASSPHRASE is a string, it - will be used to protect the key. If PASSPHRASE is True, the - passphrase must be supplied using a passphrase callback or - out-of-band with a pinentry. - - Keyword arguments: - algorithm -- public key algorithm, see above (default: reasonable) - expires_in -- expiration time in seconds (default: reasonable) - expires -- whether or not the key should expire (default: True) - sign -- request the signing capability (see above) - encrypt -- request the encryption capability (see above) - certify -- request the certification capability (see above) - authenticate -- request the authentication capability (see above) - passphrase -- protect the key with a passphrase (default: no passphrase) - force -- force key creation even if a key with the same userid exists - (default: False) - - Returns: - -- an object describing the result of the key creation - - Raises: - GPGMEError -- as signaled by the underlying library - - """ - if util.is_a_string(passphrase): - old_pinentry_mode = self.pinentry_mode - old_passphrase_cb = getattr(self, '_passphrase_cb', None) - self.pinentry_mode = constants.PINENTRY_MODE_LOOPBACK - def passphrase_cb(hint, desc, prev_bad, hook=None): - return passphrase - self.set_passphrase_cb(passphrase_cb) - - try: - self.op_createkey(userid, algorithm, - 0, # reserved - expires_in, - None, # extrakey - ((constants.create.SIGN if sign else 0) - | (constants.create.ENCR if encrypt else 0) - | (constants.create.CERT if certify else 0) - | (constants.create.AUTH if authenticate else 0) - | (constants.create.NOPASSWD if passphrase == None else 0) - | (0 if expires else constants.create.NOEXPIRE) - | (constants.create.FORCE if force else 0))) - finally: - if util.is_a_string(passphrase): - self.pinentry_mode = old_pinentry_mode - if old_passphrase_cb: - self.set_passphrase_cb(*old_passphrase_cb[1:]) - - return self.op_genkey_result() - - def create_subkey(self, key, algorithm=None, expires_in=0, expires=True, - sign=False, encrypt=False, authenticate=False, passphrase=None): - """Create a subkey - - Create a subkey for the given KEY. As subkeys are a concept - of OpenPGP, calling this is only valid for the OpenPGP - protocol. - - ALGORITHM may be used to specify the public key encryption - algorithm for the new subkey. By default, a reasonable - default is chosen. You may use "future-default" to select an - algorithm that will be the default in a future implementation - of the engine. ALGORITHM may be a string like "rsa", or - "rsa2048" to explicitly request an algorithm and a key size. - - EXPIRES_IN specifies the expiration time of the subkey in - number of seconds since the subkeys creation. By default, a - reasonable expiration time is chosen. If you want to create a - subkey that does not expire, use the keyword argument EXPIRES. - - SIGN, ENCRYPT, and AUTHENTICATE can be used to request the - capabilities of the new subkey. If you don't request any, an - encryption subkey is generated. - - If PASSPHRASE is None (the default), then the subkey will not - be protected with a passphrase. If PASSPHRASE is a string, it - will be used to protect the subkey. If PASSPHRASE is True, - the passphrase must be supplied using a passphrase callback or - out-of-band with a pinentry. - - Keyword arguments: - algorithm -- public key algorithm, see above (default: reasonable) - expires_in -- expiration time in seconds (default: reasonable) - expires -- whether or not the subkey should expire (default: True) - sign -- request the signing capability (see above) - encrypt -- request the encryption capability (see above) - authenticate -- request the authentication capability (see above) - passphrase -- protect the subkey with a passphrase (default: no passphrase) - - Returns: - -- an object describing the result of the subkey creation - - Raises: - GPGMEError -- as signaled by the underlying library - - """ - if util.is_a_string(passphrase): - old_pinentry_mode = self.pinentry_mode - old_passphrase_cb = getattr(self, '_passphrase_cb', None) - self.pinentry_mode = constants.PINENTRY_MODE_LOOPBACK - def passphrase_cb(hint, desc, prev_bad, hook=None): - return passphrase - self.set_passphrase_cb(passphrase_cb) - - try: - self.op_createsubkey(key, algorithm, - 0, # reserved - expires_in, - ((constants.create.SIGN if sign else 0) - | (constants.create.ENCR if encrypt else 0) - | (constants.create.AUTH if authenticate else 0) - | (constants.create.NOPASSWD - if passphrase == None else 0) - | (0 if expires else constants.create.NOEXPIRE))) - finally: - if util.is_a_string(passphrase): - self.pinentry_mode = old_pinentry_mode - if old_passphrase_cb: - self.set_passphrase_cb(*old_passphrase_cb[1:]) - - return self.op_genkey_result() - - def key_add_uid(self, key, uid): - """Add a UID - - Add the uid UID to the given KEY. Calling this function is - only valid for the OpenPGP protocol. - - Raises: - GPGMEError -- as signaled by the underlying library - - """ - self.op_adduid(key, uid, 0) - - def key_revoke_uid(self, key, uid): - """Revoke a UID - - Revoke the uid UID from the given KEY. Calling this function - is only valid for the OpenPGP protocol. - - Raises: - GPGMEError -- as signaled by the underlying library - - """ - self.op_revuid(key, uid, 0) - - def key_sign(self, key, uids=None, expires_in=False, local=False): - """Sign a key - - Sign a key with the current set of signing keys. Calling this - function is only valid for the OpenPGP protocol. - - If UIDS is None (the default), then all UIDs are signed. If - it is a string, then only the matching UID is signed. If it - is a list of strings, then all matching UIDs are signed. Note - that a case-sensitive exact string comparison is done. - - EXPIRES_IN specifies the expiration time of the signature in - seconds. If EXPIRES_IN is False, the signature does not - expire. - - Keyword arguments: - uids -- user ids to sign, see above (default: sign all) - expires_in -- validity period of the signature in seconds - (default: do not expire) - local -- create a local, non-exportable signature - (default: False) - - Raises: - GPGMEError -- as signaled by the underlying library - - """ - flags = 0 - if uids == None or util.is_a_string(uids): - pass#through unchanged - else: - flags |= constants.keysign.LFSEP - uids = "\n".join(uids) - - if not expires_in: - flags |= constants.keysign.NOEXPIRE - - if local: - flags |= constants.keysign.LOCAL - - self.op_keysign(key, uids, expires_in, flags) - - def key_tofu_policy(self, key, policy): - """Set a keys' TOFU policy - - Set the TOFU policy associated with KEY to POLICY. Calling - this function is only valid for the OpenPGP protocol. - - Raises: - GPGMEError -- as signaled by the underlying library - - """ - self.op_tofu_policy(key, policy) - - def assuan_transact(self, command, - data_cb=None, inquire_cb=None, status_cb=None): - """Issue a raw assuan command - - This function can be used to issue a raw assuan command to the - engine. - - If command is a string or bytes, it will be used as-is. If it - is an iterable of strings, it will be properly escaped and - joined into an well-formed assuan command. - - Keyword arguments: - data_cb -- a callback receiving data lines - inquire_cb -- a callback providing more information - status_cb -- a callback receiving status lines - - Returns: - result -- the result of command as GPGMEError - - Raises: - GPGMEError -- as signaled by the underlying library - - """ - - if util.is_a_string(command) or isinstance(command, bytes): - cmd = command - else: - cmd = " ".join(util.percent_escape(f) for f in command) - - errptr = gpgme.new_gpgme_error_t_p() - - err = gpgme.gpgme_op_assuan_transact_ext( - self.wrapped, - cmd, - (weakref.ref(self), data_cb) if data_cb else None, - (weakref.ref(self), inquire_cb) if inquire_cb else None, - (weakref.ref(self), status_cb) if status_cb else None, - errptr) - - if self._callback_excinfo: - gpgme.gpg_raise_callback_exception(self) - - errorcheck(err) - - status = gpgme.gpgme_error_t_p_value(errptr) - gpgme.delete_gpgme_error_t_p(errptr) - - return GPGMEError(status) if status != 0 else None - - def interact(self, key, func, sink=None, flags=0, fnc_value=None): - """Interact with the engine - - This method can be used to edit keys and cards interactively. - KEY is the key to edit, FUNC is called repeatedly with two - unicode arguments, 'keyword' and 'args'. See the GPGME manual - for details. - - Keyword arguments: - sink -- if given, additional output is written here - flags -- use constants.INTERACT_CARD to edit a card - - Raises: - GPGMEError -- as signaled by the underlying library - - """ - if key == None: - raise ValueError("First argument cannot be None") - - if sink == None: - sink = Data() - - if fnc_value: - opaquedata = (weakref.ref(self), func, fnc_value) - else: - opaquedata = (weakref.ref(self), func) - - result = gpgme.gpgme_op_interact(self.wrapped, key, flags, - opaquedata, sink) - if self._callback_excinfo: - gpgme.gpg_raise_callback_exception(self) - errorcheck(result) - - @property - def signers(self): - """Keys used for signing""" - return [self.signers_enum(i) for i in range(self.signers_count())] - @signers.setter - def signers(self, signers): - old = self.signers - self.signers_clear() - try: - for key in signers: - self.signers_add(key) - except: - self.signers = old - raise - - @property - def pinentry_mode(self): - """Pinentry mode""" - return self.get_pinentry_mode() - @pinentry_mode.setter - def pinentry_mode(self, value): - self.set_pinentry_mode(value) - - @property - def protocol(self): - """Protocol to use""" - return self.get_protocol() - @protocol.setter - def protocol(self, value): - errorcheck(gpgme.gpgme_engine_check_version(value)) - self.set_protocol(value) - - @property - def home_dir(self): - """Engine's home directory""" - return self.engine_info.home_dir - @home_dir.setter - def home_dir(self, value): - self.set_engine_info(self.protocol, home_dir=value) - - _ctype = 'gpgme_ctx_t' - _cprefix = 'gpgme_' - - def _errorcheck(self, name): - """This function should list all functions returning gpgme_error_t""" - # The list of functions is created using: - # - # $ grep '^gpgme_error_t ' obj/lang/python/python3.5-gpg/gpgme.h \ - # | grep -v _op_ | awk "/\(gpgme_ctx/ { printf (\"'%s',\\n\", \$2) } " - return ((name.startswith('gpgme_op_') - and not name.endswith('_result')) - or name in { - 'gpgme_new', - 'gpgme_set_ctx_flag', - 'gpgme_set_protocol', - 'gpgme_set_sub_protocol', - 'gpgme_set_keylist_mode', - 'gpgme_set_pinentry_mode', - 'gpgme_set_locale', - 'gpgme_ctx_set_engine_info', - 'gpgme_signers_add', - 'gpgme_sig_notation_add', - 'gpgme_set_sender', - 'gpgme_cancel', - 'gpgme_cancel_async', - 'gpgme_get_key', - }) - - _boolean_properties = {'armor', 'textmode', 'offline'} - - def __del__(self): - if not gpgme: - # At interpreter shutdown, gpgme is set to NONE. - return - - self._free_passcb() - self._free_progresscb() - self._free_statuscb() - if self.own and self.wrapped and gpgme.gpgme_release: - gpgme.gpgme_release(self.wrapped) - self.wrapped = None - - # Implement the context manager protocol. - def __enter__(self): - return self - def __exit__(self, type, value, tb): - self.__del__() - - def op_keylist_all(self, *args, **kwargs): - self.op_keylist_start(*args, **kwargs) - key = self.op_keylist_next() - while key: - yield key - key = self.op_keylist_next() - self.op_keylist_end() - - def op_keylist_next(self): - """Returns the next key in the list created - by a call to op_keylist_start(). The object returned - is of type Key.""" - ptr = gpgme.new_gpgme_key_t_p() - try: - errorcheck(gpgme.gpgme_op_keylist_next(self.wrapped, ptr)) - key = gpgme.gpgme_key_t_p_value(ptr) - except errors.GPGMEError as excp: - key = None - if excp.getcode() != errors.EOF: - raise excp - gpgme.delete_gpgme_key_t_p(ptr) - if key: - key.__del__ = lambda self: gpgme.gpgme_key_unref(self) - return key - - def get_key(self, fpr, secret=False): - """Get a key given a fingerprint - - Keyword arguments: - secret -- to request a secret key - - Returns: - -- the matching key - - Raises: - KeyError -- if the key was not found - GPGMEError -- as signaled by the underlying library - - """ - ptr = gpgme.new_gpgme_key_t_p() - - try: - errorcheck(gpgme.gpgme_get_key(self.wrapped, fpr, ptr, secret)) - except errors.GPGMEError as e: - if e.getcode() == errors.EOF: - raise errors.KeyNotFound(fpr) - raise e - - key = gpgme.gpgme_key_t_p_value(ptr) - gpgme.delete_gpgme_key_t_p(ptr) - assert key - key.__del__ = lambda self: gpgme.gpgme_key_unref(self) - return key - - def op_trustlist_all(self, *args, **kwargs): - self.op_trustlist_start(*args, **kwargs) - trust = self.op_trustlist_next() - while trust: - yield trust - trust = self.op_trustlist_next() - self.op_trustlist_end() - - def op_trustlist_next(self): - """Returns the next trust item in the list created - by a call to op_trustlist_start(). The object returned - is of type TrustItem.""" - ptr = gpgme.new_gpgme_trust_item_t_p() - try: - errorcheck(gpgme.gpgme_op_trustlist_next(self.wrapped, ptr)) - trust = gpgme.gpgme_trust_item_t_p_value(ptr) - except errors.GPGMEError as excp: - trust = None - if excp.getcode() != errors.EOF: - raise - gpgme.delete_gpgme_trust_item_t_p(ptr) - return trust - - def set_passphrase_cb(self, func, hook=None): - """Sets the passphrase callback to the function specified by func. - - When the system needs a passphrase, it will call func with three args: - hint, a string describing the key it needs the passphrase for; - desc, a string describing the passphrase it needs; - prev_bad, a boolean equal True if this is a call made after - unsuccessful previous attempt. - - If hook has a value other than None it will be passed into the func - as a forth argument. - - Please see the GPGME manual for more information. - """ - if func == None: - hookdata = None - else: - if hook == None: - hookdata = (weakref.ref(self), func) - else: - hookdata = (weakref.ref(self), func, hook) - gpgme.gpg_set_passphrase_cb(self, hookdata) - - def _free_passcb(self): - if gpgme.gpg_set_passphrase_cb: - self.set_passphrase_cb(None) - - def set_progress_cb(self, func, hook=None): - """Sets the progress meter callback to the function specified by FUNC. - If FUNC is None, the callback will be cleared. - - This function will be called to provide an interactive update - of the system's progress. The function will be called with - three arguments, type, total, and current. If HOOK is not - None, it will be supplied as fourth argument. - - Please see the GPGME manual for more information. - - """ - if func == None: - hookdata = None - else: - if hook == None: - hookdata = (weakref.ref(self), func) - else: - hookdata = (weakref.ref(self), func, hook) - gpgme.gpg_set_progress_cb(self, hookdata) - - def _free_progresscb(self): - if gpgme.gpg_set_progress_cb: - self.set_progress_cb(None) - - def set_status_cb(self, func, hook=None): - """Sets the status callback to the function specified by FUNC. If - FUNC is None, the callback will be cleared. - - The function will be called with two arguments, keyword and - args. If HOOK is not None, it will be supplied as third - argument. - - Please see the GPGME manual for more information. - - """ - if func == None: - hookdata = None - else: - if hook == None: - hookdata = (weakref.ref(self), func) - else: - hookdata = (weakref.ref(self), func, hook) - gpgme.gpg_set_status_cb(self, hookdata) - - def _free_statuscb(self): - if gpgme.gpg_set_status_cb: - self.set_status_cb(None) - - @property - def engine_info(self): - """Configuration of the engine currently in use""" - p = self.protocol - infos = [i for i in self.get_engine_info() if i.protocol == p] - assert len(infos) == 1 - return infos[0] - - def get_engine_info(self): - """Get engine configuration - - Returns information about all configured and installed - engines. - - Returns: - infos -- a list of engine infos - - """ - return gpgme.gpgme_ctx_get_engine_info(self.wrapped) - - def set_engine_info(self, proto, file_name=None, home_dir=None): - """Change engine configuration - - Changes the configuration of the crypto engine implementing - the protocol 'proto' for the context. - - Keyword arguments: - file_name -- engine program file name (unchanged if None) - home_dir -- configuration directory (unchanged if None) - - """ - self.ctx_set_engine_info(proto, file_name, home_dir) - - def wait(self, hang): - """Wait for asynchronous call to finish. Wait forever if hang is True. - Raises an exception on errors. - - Please read the GPGME manual for more information. - - """ - ptr = gpgme.new_gpgme_error_t_p() - gpgme.gpgme_wait(self.wrapped, ptr, hang) - status = gpgme.gpgme_error_t_p_value(ptr) - gpgme.delete_gpgme_error_t_p(ptr) - errorcheck(status) - - def op_edit(self, key, func, fnc_value, out): - """Start key editing using supplied callback function - - Note: This interface is deprecated and will be removed with - GPGME 1.8. Please use .interact instead. Furthermore, we - implement this using gpgme_op_interact, so callbacks will get - called with string keywords instead of numeric status - messages. Code that is using constants.STATUS_X or - constants.status.X will continue to work, whereas code using - magic numbers will break as a result. - - """ - warnings.warn("Call to deprecated method op_edit.", - category=DeprecationWarning) - return self.interact(key, func, sink=out, fnc_value=fnc_value) - - -class Data(GpgmeWrapper): - """Data buffer - - A lot of data has to be exchanged between the user and the crypto - engine, like plaintext messages, ciphertext, signatures and - information about the keys. The technical details about - exchanging the data information are completely abstracted by - GPGME. The user provides and receives the data via `gpgme_data_t' - objects, regardless of the communication protocol between GPGME - and the crypto engine in use. - - This Data class is the implementation of the GpgmeData objects. - - Please see the information about __init__ for instantiation. - - """ - - _ctype = 'gpgme_data_t' - _cprefix = 'gpgme_data_' - - def _errorcheck(self, name): - """This function should list all functions returning gpgme_error_t""" - # This list is compiled using - # - # $ grep -v '^gpgme_error_t ' obj/lang/python/python3.5-gpg/gpgme.h \ - # | awk "/\(gpgme_data_t/ { printf (\"'%s',\\n\", \$2) } " | sed "s/'\\*/'/" - return name not in { - 'gpgme_data_read', - 'gpgme_data_write', - 'gpgme_data_seek', - 'gpgme_data_release', - 'gpgme_data_release_and_get_mem', - 'gpgme_data_get_encoding', - 'gpgme_data_get_file_name', - 'gpgme_data_identify', - } - - def __init__(self, string=None, file=None, offset=None, - length=None, cbs=None, copy=True): - """Initialize a new gpgme_data_t object. - - If no args are specified, make it an empty object. - - If string alone is specified, initialize it with the data - contained there. - - If file, offset, and length are all specified, file must - be either a filename or a file-like object, and the object - will be initialized by reading the specified chunk from the file. - - If cbs is specified, it MUST be a tuple of the form: - - (read_cb, write_cb, seek_cb, release_cb[, hook]) - - where the first four items are functions implementing reading, - writing, seeking the data, and releasing any resources once - the data object is deallocated. The functions must match the - following prototypes: - - def read(amount, hook=None): - return - - def write(data, hook=None): - return - - def seek(offset, whence, hook=None): - return - - def release(hook=None): - - - The functions may be bound methods. In that case, you can - simply use the 'self' reference instead of using a hook. - - If file is specified without any other arguments, then - it must be a filename, and the object will be initialized from - that file. - - """ - super(Data, self).__init__(None) - self.data_cbs = None - - if cbs != None: - self.new_from_cbs(*cbs) - elif string != None: - self.new_from_mem(string, copy) - elif file != None and offset != None and length != None: - self.new_from_filepart(file, offset, length) - elif file != None: - if util.is_a_string(file): - self.new_from_file(file, copy) - else: - self.new_from_fd(file) - else: - self.new() - - def __del__(self): - if not gpgme: - # At interpreter shutdown, gpgme is set to NONE. - return - - if self.wrapped != None and gpgme.gpgme_data_release: - gpgme.gpgme_data_release(self.wrapped) - if self._callback_excinfo: - gpgme.gpg_raise_callback_exception(self) - self.wrapped = None - self._free_datacbs() - - # Implement the context manager protocol. - def __enter__(self): - return self - def __exit__(self, type, value, tb): - self.__del__() - - def _free_datacbs(self): - self._data_cbs = None - - def new(self): - tmp = gpgme.new_gpgme_data_t_p() - errorcheck(gpgme.gpgme_data_new(tmp)) - self.wrapped = gpgme.gpgme_data_t_p_value(tmp) - gpgme.delete_gpgme_data_t_p(tmp) - - def new_from_mem(self, string, copy=True): - tmp = gpgme.new_gpgme_data_t_p() - errorcheck(gpgme.gpgme_data_new_from_mem(tmp,string,len(string),copy)) - self.wrapped = gpgme.gpgme_data_t_p_value(tmp) - gpgme.delete_gpgme_data_t_p(tmp) - - def new_from_file(self, filename, copy=True): - tmp = gpgme.new_gpgme_data_t_p() - try: - errorcheck(gpgme.gpgme_data_new_from_file(tmp, filename, copy)) - except errors.GPGMEError as e: - if e.getcode() == errors.INV_VALUE and not copy: - raise ValueError("delayed reads are not yet supported") - else: - raise e - self.wrapped = gpgme.gpgme_data_t_p_value(tmp) - gpgme.delete_gpgme_data_t_p(tmp) - - def new_from_cbs(self, read_cb, write_cb, seek_cb, release_cb, hook=None): - tmp = gpgme.new_gpgme_data_t_p() - if hook != None: - hookdata = (weakref.ref(self), - read_cb, write_cb, seek_cb, release_cb, hook) - else: - hookdata = (weakref.ref(self), - read_cb, write_cb, seek_cb, release_cb) - gpgme.gpg_data_new_from_cbs(self, hookdata, tmp) - self.wrapped = gpgme.gpgme_data_t_p_value(tmp) - gpgme.delete_gpgme_data_t_p(tmp) - - def new_from_filepart(self, file, offset, length): - """This wraps the GPGME gpgme_data_new_from_filepart() function. - The argument "file" may be: - - * a string specifying a file name, or - * a file-like object supporting the fileno() and the mode attribute. - - """ - - tmp = gpgme.new_gpgme_data_t_p() - filename = None - fp = None - - if util.is_a_string(file): - filename = file - else: - fp = gpgme.fdopen(file.fileno(), file.mode) - if fp == None: - raise ValueError("Failed to open file from %s arg %s" % \ - (str(type(file)), str(file))) - - errorcheck(gpgme.gpgme_data_new_from_filepart(tmp, filename, fp, - offset, length)) - self.wrapped = gpgme.gpgme_data_t_p_value(tmp) - gpgme.delete_gpgme_data_t_p(tmp) - - def new_from_fd(self, file): - """This wraps the GPGME gpgme_data_new_from_fd() function. The - argument "file" must be a file-like object, supporting the - fileno() method. - - """ - tmp = gpgme.new_gpgme_data_t_p() - errorcheck(gpgme.gpgme_data_new_from_fd(tmp, file.fileno())) - self.wrapped = gpgme.gpgme_data_t_p_value(tmp) - gpgme.delete_gpgme_data_t_p(tmp) - - def new_from_stream(self, file): - """This wrap around gpgme_data_new_from_stream is an alias for - new_from_fd() method since in python there's not difference - between file stream and file descriptor""" - self.new_from_fd(file) - - def write(self, buffer): - """Write buffer given as string or bytes. - - If a string is given, it is implicitly encoded using UTF-8.""" - written = gpgme.gpgme_data_write(self.wrapped, buffer) - if written < 0: - if self._callback_excinfo: - gpgme.gpg_raise_callback_exception(self) - else: - raise GPGMEError.fromSyserror() - return written - - def read(self, size = -1): - """Read at most size bytes, returned as bytes. - - If the size argument is negative or omitted, read until EOF is reached. - - Returns the data read, or the empty string if there was no data - to read before EOF was reached.""" - - if size == 0: - return '' - - if size > 0: - try: - result = gpgme.gpgme_data_read(self.wrapped, size) - except: - if self._callback_excinfo: - gpgme.gpg_raise_callback_exception(self) - else: - raise - return result - else: - chunks = [] - while True: - try: - result = gpgme.gpgme_data_read(self.wrapped, 4096) - except: - if self._callback_excinfo: - gpgme.gpg_raise_callback_exception(self) - else: - raise - if len(result) == 0: - break - chunks.append(result) - return b''.join(chunks) - -def pubkey_algo_string(subkey): - """Return short algorithm string - - Return a public key algorithm string (e.g. "rsa2048") for a given - SUBKEY. - - Returns: - algo - a string - - """ - return gpgme.gpgme_pubkey_algo_string(subkey) - -def pubkey_algo_name(algo): - """Return name of public key algorithm - - Return the name of the public key algorithm for a given numeric - algorithm id ALGO (cf. RFC4880). - - Returns: - algo - a string - - """ - return gpgme.gpgme_pubkey_algo_name(algo) - -def hash_algo_name(algo): - """Return name of hash algorithm - - Return the name of the hash algorithm for a given numeric - algorithm id ALGO (cf. RFC4880). - - Returns: - algo - a string - - """ - return gpgme.gpgme_hash_algo_name(algo) - -def get_protocol_name(proto): - """Get protocol description - - Get the string describing protocol PROTO. - - Returns: - proto - a string - - """ - return gpgme.gpgme_get_protocol_name(proto) - -def addrspec_from_uid(uid): - """Return the address spec - - Return the addr-spec (cf. RFC2822 section 4.3) from a user id UID. - - Returns: - addr_spec - a string - - """ - return gpgme.gpgme_addrspec_from_uid(uid) - -def check_version(version=None): - return gpgme.gpgme_check_version(version) - -# check_version also makes sure that several subsystems are properly -# initialized, and it must be run at least once before invoking any -# other function. We do it here so that the user does not have to do -# it unless she really wants to check for a certain version. -check_version() - -def engine_check_version (proto): - try: - errorcheck(gpgme.gpgme_engine_check_version(proto)) - return True - except errors.GPGMEError: - return False - -def get_engine_info(): - ptr = gpgme.new_gpgme_engine_info_t_p() - try: - errorcheck(gpgme.gpgme_get_engine_info(ptr)) - info = gpgme.gpgme_engine_info_t_p_value(ptr) - except errors.GPGMEError: - info = None - gpgme.delete_gpgme_engine_info_t_p(ptr) - return info - -def set_engine_info(proto, file_name, home_dir=None): - """Changes the default configuration of the crypto engine implementing - the protocol 'proto'. 'file_name' is the file name of - the executable program implementing this protocol. 'home_dir' is the - directory name of the configuration directory (engine's default is - used if omitted).""" - errorcheck(gpgme.gpgme_set_engine_info(proto, file_name, home_dir)) - -def set_locale(category, value): - """Sets the default locale used by contexts""" - errorcheck(gpgme.gpgme_set_locale(None, category, value)) - -def wait(hang): - """Wait for asynchronous call on any Context to finish. - Wait forever if hang is True. - - For finished anynch calls it returns a tuple (status, context): - status - status return by asnynchronous call. - context - context which caused this call to return. - - Please read the GPGME manual of more information.""" - ptr = gpgme.new_gpgme_error_t_p() - context = gpgme.gpgme_wait(None, ptr, hang) - status = gpgme.gpgme_error_t_p_value(ptr) - gpgme.delete_gpgme_error_t_p(ptr) - if context == None: - errorcheck(status) - else: - context = Context(context) - return (status, context) diff --git a/lang/python/gpg/errors.py b/lang/python/gpg/errors.py deleted file mode 100644 index 1ce139e8..00000000 --- a/lang/python/gpg/errors.py +++ /dev/null @@ -1,128 +0,0 @@ -# Copyright (C) 2004 Igor Belyi -# Copyright (C) 2002 John Goerzen -# -# This library is free software; you can redistribute it and/or -# modify it under the terms of the GNU Lesser General Public -# License as published by the Free Software Foundation; either -# version 2.1 of the License, or (at your option) any later version. -# -# This library is distributed in the hope that it will be useful, -# but WITHOUT ANY WARRANTY; without even the implied warranty of -# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU -# Lesser General Public License for more details. -# -# You should have received a copy of the GNU Lesser General Public -# License along with this library; if not, write to the Free Software -# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - -from __future__ import absolute_import, print_function, unicode_literals -del absolute_import, print_function, unicode_literals - -from . import gpgme -from . import util - -# To appease static analysis tools, we define some constants here. -# They are overwritten with the proper values by process_constants. -NO_ERROR = None -EOF = None - -util.process_constants('GPG_ERR_', globals()) -del util - -class GpgError(Exception): - pass - -class GPGMEError(GpgError): - def __init__(self, error = None, message = None): - self.error = error - self.message = message - - @classmethod - def fromSyserror(cls): - return cls(gpgme.gpgme_err_code_from_syserror()) - - def getstring(self): - message = "%s: %s" % (gpgme.gpgme_strsource(self.error), - gpgme.gpgme_strerror(self.error)) - if self.message != None: - message = "%s: %s" % (self.message, message) - return message - - def getcode(self): - return gpgme.gpgme_err_code(self.error) - - def getsource(self): - return gpgme.gpgme_err_source(self.error) - - def __str__(self): - return self.getstring() - -def errorcheck(retval, extradata = None): - if retval: - raise GPGMEError(retval, extradata) - -class KeyNotFound(GPGMEError, KeyError): - """Raised if a key was not found - - GPGME indicates this condition with EOF, which is not very - idiomatic. We raise this error that is both a GPGMEError - indicating EOF, and a KeyError. - - """ - def __init__(self, keystr): - self.keystr = keystr - GPGMEError.__init__(self, EOF) - def __str__(self): - return self.keystr - -# These errors are raised in the idiomatic interface code. - -class EncryptionError(GpgError): - pass - -class InvalidRecipients(EncryptionError): - def __init__(self, recipients): - self.recipients = recipients - def __str__(self): - return ", ".join("{}: {}".format(r.fpr, - gpgme.gpgme_strerror(r.reason)) - for r in self.recipients) - -class DeryptionError(GpgError): - pass - -class UnsupportedAlgorithm(DeryptionError): - def __init__(self, algorithm): - self.algorithm = algorithm - def __str__(self): - return self.algorithm - -class SigningError(GpgError): - pass - -class InvalidSigners(SigningError): - def __init__(self, signers): - self.signers = signers - def __str__(self): - return ", ".join("{}: {}".format(s.fpr, - gpgme.gpgme_strerror(s.reason)) - for s in self.signers) - -class VerificationError(GpgError): - pass - -class BadSignatures(VerificationError): - def __init__(self, result): - self.result = result - def __str__(self): - return ", ".join("{}: {}".format(s.fpr, - gpgme.gpgme_strerror(s.status)) - for s in self.result.signatures - if s.status != NO_ERROR) - -class MissingSignatures(VerificationError): - def __init__(self, result, missing): - self.result = result - self.missing = missing - def __str__(self): - return ", ".join(k.subkeys[0].fpr for k in self.missing) diff --git a/lang/python/gpg/results.py b/lang/python/gpg/results.py deleted file mode 100644 index 46ebeec6..00000000 --- a/lang/python/gpg/results.py +++ /dev/null @@ -1,118 +0,0 @@ -# Robust result objects -# -# Copyright (C) 2016 g10 Code GmbH -# -# This file is part of GPGME. -# -# GPGME is free software; you can redistribute it and/or modify it -# under the terms of the GNU Lesser General Public License as -# published by the Free Software Foundation; either version 2.1 of the -# License, or (at your option) any later version. -# -# GPGME is distributed in the hope that it will be useful, but WITHOUT -# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY -# or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General -# Public License for more details. -# -# You should have received a copy of the GNU Lesser General Public -# License along with this program; if not, see . - -from __future__ import absolute_import, print_function, unicode_literals -del absolute_import, print_function, unicode_literals - -"""Robust result objects - -Results returned by the underlying library are fragile, i.e. they are -only valid until the next operation is performed in the context. - -We cannot arbitrarily constrain the lifetime of Python objects, we -therefore create deep copies of the results. - -""" - -class Result(object): - """Result object - - Describes the result of an operation. - - """ - - """Convert to types""" - _type = {} - - """Map functions over list attributes""" - _map = {} - - """Automatically copy unless blacklisted""" - _blacklist = { - 'acquire', 'append', 'disown', 'next', 'own', 'this', 'thisown', - } - def __init__(self, fragile): - for key, func in self._type.items(): - if hasattr(fragile, key): - setattr(self, key, func(getattr(fragile, key))) - - for key, func in self._map.items(): - if hasattr(fragile, key): - setattr(self, key, list(map(func, getattr(fragile, key)))) - - for key in dir(fragile): - if key.startswith('_') or key in self._blacklist: - continue - if hasattr(self, key): - continue - - setattr(self, key, getattr(fragile, key)) - - def __repr__(self): - return '{}({})'.format( - self.__class__.__name__, - ', '.join('{}={!r}'.format(k, getattr(self, k)) - for k in dir(self) if not k.startswith('_'))) - -class InvalidKey(Result): - pass - -class EncryptResult(Result): - _map = dict(invalid_recipients=InvalidKey) - -class Recipient(Result): - pass - -class DecryptResult(Result): - _type = dict(wrong_key_usage=bool) - _map = dict(recipients=Recipient) - -class NewSignature(Result): - pass - -class SignResult(Result): - _map = dict(invalid_signers=InvalidKey, signatures=NewSignature) - -class Notation(Result): - pass - -class Signature(Result): - _type = dict(wrong_key_usage=bool, chain_model=bool) - _map = dict(notations=Notation) - -class VerifyResult(Result): - _map = dict(signatures=Signature) - -class ImportStatus(Result): - pass - -class ImportResult(Result): - _map = dict(imports=ImportStatus) - -class GenkeyResult(Result): - _type = dict(primary=bool, sub=bool) - -class KeylistResult(Result): - _type = dict(truncated=bool) - -class VFSMountResult(Result): - pass - -class EngineInfo(Result): - pass diff --git a/lang/python/gpg/util.py b/lang/python/gpg/util.py deleted file mode 100644 index e4fca4c1..00000000 --- a/lang/python/gpg/util.py +++ /dev/null @@ -1,53 +0,0 @@ -# Copyright (C) 2016 g10 Code GmbH -# Copyright (C) 2004,2008 Igor Belyi -# Copyright (C) 2002 John Goerzen -# -# This library is free software; you can redistribute it and/or -# modify it under the terms of the GNU Lesser General Public -# License as published by the Free Software Foundation; either -# version 2.1 of the License, or (at your option) any later version. -# -# This library is distributed in the hope that it will be useful, -# but WITHOUT ANY WARRANTY; without even the implied warranty of -# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU -# Lesser General Public License for more details. -# -# You should have received a copy of the GNU Lesser General Public -# License along with this library; if not, write to the Free Software -# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - -from __future__ import absolute_import, print_function, unicode_literals -del absolute_import, print_function, unicode_literals - -import sys - -def process_constants(prefix, scope): - """Called by the constant modules to load up the constants from the C - library starting with PREFIX. Matching constants will be inserted - into SCOPE with PREFIX stripped from the names. Returns the names - of inserted constants. - - """ - from . import gpgme - index = len(prefix) - constants = {identifier[index:]: getattr(gpgme, identifier) - for identifier in dir(gpgme) - if identifier.startswith(prefix)} - scope.update(constants) - return list(constants.keys()) - -def percent_escape(s): - return ''.join( - '%{0:2x}'.format(ord(c)) - if c == '+' or c == '"' or c == '%' or ord(c) <= 0x20 else c - for c in s) - -# Python2/3 compatibility -if sys.version_info[0] == 3: - # Python3 - def is_a_string(x): - return isinstance(x, str) -else: - # Python2 - def is_a_string(x): - return isinstance(x, basestring) diff --git a/lang/python/gpg/version.py.in b/lang/python/gpg/version.py.in deleted file mode 100644 index 1a1baf08..00000000 --- a/lang/python/gpg/version.py.in +++ /dev/null @@ -1,68 +0,0 @@ -# Copyright (C) 2016 g10 Code GmbH -# Copyright (C) 2015 Ben McGinnes -# Copyright (C) 2004 Igor Belyi -# -# This library is free software; you can redistribute it and/or -# modify it under the terms of the GNU Lesser General Public -# License as published by the Free Software Foundation; either -# version 2.1 of the License, or (at your option) any later version. -# -# This library is distributed in the hope that it will be useful, -# but WITHOUT ANY WARRANTY; without even the implied warranty of -# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU -# Lesser General Public License for more details. -# -# You should have received a copy of the GNU Lesser General Public -# License along with this library; if not, write to the Free Software -# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - -from __future__ import absolute_import, print_function -del absolute_import, print_function - -from . import gpgme - -productname = 'gpg' -versionstr = "@VERSION@" -gpgme_versionstr = gpgme.GPGME_VERSION -in_tree_build = bool(gpgme.cvar.gpg_in_tree_build) - -versionlist = versionstr.split(".") -major = versionlist[0] -minor = versionlist[1] -patch = versionlist[2] - -copyright = """\ -Copyright (C) 2016 g10 Code GmbH -Copyright (C) 2015 Ben McGinnes -Copyright (C) 2014-2015 Martin Albrecht -Copyright (C) 2004-2008 Igor Belyi -Copyright (C) 2002 John Goerzen""" - -author = "The GnuPG hackers" -author_email = "gnupg-devel@gnupg.org" - -description = "Python support for GPGME GnuPG cryptography library" -homepage = "https://gnupg.org" - -license = """Copyright (C) 2016 g10 Code GmbH -Copyright (C) 2015 Ben McGinnes -Copyright (C) 2014, 2015 Martin Albrecht -Copyright (C) 2004, 2008 Igor Belyi -Copyright (C) 2002 John Goerzen - -This library is free software; you can redistribute it and/or -modify it under the terms of the GNU Lesser General Public -License as published by the Free Software Foundation; either -version 2.1 of the License, or (at your option) any later version. - -This library is distributed in the hope that it will be useful, -but WITHOUT ANY WARRANTY; without even the implied warranty of -MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU -Lesser General Public License for more details. - -You should have received a copy of the GNU Lesser General Public -License along with this library; if not, write to the Free Software -Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA""" - -# Interface hygiene. Keep this at the end. -del gpgme diff --git a/lang/python/setup.py.in b/lang/python/setup.py.in index 2114aafe..5d94c704 100755 --- a/lang/python/setup.py.in +++ b/lang/python/setup.py.in @@ -38,18 +38,17 @@ gpgme_config = ["gpgme-config"] + gpgme_config_flags gpgme_h = "" include_dirs = [os.getcwd()] library_dirs = [] -vpath_build = os.environ.get('srcdir', '.') != '.' in_tree = False extra_swig_opts = [] extra_macros = dict() -abs_top_builddir = os.environ.get("abs_top_builddir") -if abs_top_builddir: +top_builddir = os.environ.get("top_builddir") +if top_builddir: # In-tree build. in_tree = True - gpgme_config = [os.path.join(abs_top_builddir, "src/gpgme-config")] + gpgme_config_flags - gpgme_h = os.path.join(abs_top_builddir, "src/gpgme.h") - library_dirs = [os.path.join(abs_top_builddir, "src/.libs")] # XXX uses libtool internals + gpgme_config = [os.path.join(top_builddir, "src/gpgme-config")] + gpgme_config_flags + gpgme_h = os.path.join(top_builddir, "src/gpgme.h") + library_dirs = [os.path.join(top_builddir, "src/.libs")] # XXX uses libtool internals extra_macros.update( HAVE_CONFIG_H=1, HAVE_DATA_H=1, @@ -210,23 +209,21 @@ class BuildExtFirstHack(build): # Copy due to http://bugs.python.org/issue2624 # Avoid creating in srcdir for source, target in ((in_srcdir(n), in_build_base(n)) - for n in ('gpgme.i', 'helpers.c')): + for n in ('gpgme.i', 'helpers.c', 'private.h', 'helpers.h')): if not up_to_date(source, target): shutil.copy2(source, target) - def run(self): - self._generate() - # Append generated files via build_base if not os.path.exists(os.path.join(self.build_lib, "gpg")): os.makedirs(os.path.join(self.build_lib, "gpg")) + shutil.copy2("version.py", os.path.join(self.build_lib, "gpg")) + + def run(self): + self._generate() swig_sources.append(os.path.join(self.build_base, 'gpgme.i')) swig_opts.extend(['-I' + self.build_base, - '-I' + in_srcdir('.'), '-outdir', os.path.join(self.build_lib, 'gpg')]) - if vpath_build: - include_dirs.append(in_srcdir('.')) include_dirs.append(self.build_base) self.run_command('build_ext') diff --git a/lang/python/src/__init__.py b/lang/python/src/__init__.py new file mode 100644 index 00000000..385b17e3 --- /dev/null +++ b/lang/python/src/__init__.py @@ -0,0 +1,121 @@ +# Copyright (C) 2016 g10 Code GmbH +# Copyright (C) 2004 Igor Belyi +# Copyright (C) 2002 John Goerzen +# +# This library is free software; you can redistribute it and/or +# modify it under the terms of the GNU Lesser General Public +# License as published by the Free Software Foundation; either +# version 2.1 of the License, or (at your option) any later version. +# +# This library is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +# Lesser General Public License for more details. +# +# You should have received a copy of the GNU Lesser General Public +# License along with this library; if not, write to the Free Software +# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + +"""gpg: GnuPG Interface for Python (GPGME bindings) + +Welcome to gpg, the GnuPG Interface for Python. + +The latest release of this package may be obtained from +https://www.gnupg.org + +FEATURES +-------- + + * Feature-rich, full implementation of the GPGME library. Supports + all GPGME features. Callback functions may be written in pure + Python. Exceptions raised in callbacks are properly propagated. + + * Ability to sign, encrypt, decrypt, and verify data. + + * Ability to list keys, export and import keys, and manage the keyring. + + * Fully object-oriented with convenient classes and modules. + +QUICK EXAMPLE +------------- + + >>> import gpg + >>> with gpg.Context() as c: + >>> with gpg.Context() as c: + ... cipher, _, _ = c.encrypt("Hello world :)".encode(), + ... passphrase="abc") + ... c.decrypt(cipher, passphrase="abc") + ... + (b'Hello world :)', + , + ) + +GENERAL OVERVIEW +---------------- + +For those of you familiar with GPGME, you will be right at home here. + +The python gpg module is, for the most part, a direct interface to the C GPGME +library. However, it is re-packaged in a more Pythonic way -- +object-oriented with classes and modules. Take a look at the classes +defined here -- they correspond directly to certain object types in GPGME +for C. For instance, the following C code: + +gpgme_ctx_t context; +gpgme_new(&context); +... +gpgme_op_encrypt(context, recp, 1, plain, cipher); + +Translates into the following Python code: + +context = core.Context() +... +context.op_encrypt(recp, 1, plain, cipher) + +The Python module automatically does error-checking and raises Python +exception gpg.errors.GPGMEError when GPGME signals an error. getcode() +and getsource() of this exception return code and source of the error. + +IMPORTANT NOTE +-------------- +This documentation only covers a small subset of available GPGME functions and +methods. Please consult the documentation for the C library +for comprehensive coverage. + +This library uses Python's reflection to automatically detect the methods +that are available for each class, and as such, most of those methods +do not appear explicitly anywhere. You can use dir() python built-in command +on an object to see what methods and fields it has but their meaning can +be found only in GPGME documentation. + +FOR MORE INFORMATION +-------------------- +GnuPG homepage: https://www.gnupg.org/ +GPGME documentation: https://www.gnupg.org/documentation/manuals/gpgme/ + +""" + +from __future__ import absolute_import, print_function, unicode_literals +del absolute_import, print_function, unicode_literals + +from . import core +from . import errors +from . import constants +from . import util +from . import callbacks +from . import version +from .core import Context +from .core import Data + +# Interface hygiene. + +# Drop the low-level gpgme that creeps in for some reason. +gpgme = None +del gpgme + +# This is a white-list of symbols. Any other will alert pyflakes. +_ = [Context, Data, core, errors, constants, util, callbacks, version] +del _ + +__all__ = ["Context", "Data", + "core", "errors", "constants", "util", "callbacks", "version"] diff --git a/lang/python/src/callbacks.py b/lang/python/src/callbacks.py new file mode 100644 index 00000000..b25a9a74 --- /dev/null +++ b/lang/python/src/callbacks.py @@ -0,0 +1,49 @@ +# Copyright (C) 2004 Igor Belyi +# Copyright (C) 2002 John Goerzen +# +# This library is free software; you can redistribute it and/or +# modify it under the terms of the GNU Lesser General Public +# License as published by the Free Software Foundation; either +# version 2.1 of the License, or (at your option) any later version. +# +# This library is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +# Lesser General Public License for more details. +# +# You should have received a copy of the GNU Lesser General Public +# License along with this library; if not, write to the Free Software +# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + +from __future__ import absolute_import, print_function, unicode_literals +del absolute_import, print_function, unicode_literals + +from getpass import getpass + +def passphrase_stdin(hint, desc, prev_bad, hook=None): + """This is a sample callback that will read a passphrase from + the terminal. The hook here, if present, will be used to describe + why the passphrase is needed.""" + why = '' + if hook != None: + why = ' ' + hook + if prev_bad: + why += ' (again)' + print("Please supply %s' password%s:" % (hint, why)) + return getpass() + +def progress_stdout(what, type, current, total, hook=None): + print("PROGRESS UPDATE: what = %s, type = %d, current = %d, total = %d" %\ + (what, type, current, total)) + +def readcb_fh(count, hook): + """A callback for data. hook should be a Python file-like object.""" + if count: + # Should return '' on EOF + return hook.read(count) + else: + # Wants to rewind. + if not hasattr(hook, 'seek'): + return None + hook.seek(0, 0) + return None diff --git a/lang/python/src/constants/__init__.py b/lang/python/src/constants/__init__.py new file mode 100644 index 00000000..484ffd29 --- /dev/null +++ b/lang/python/src/constants/__init__.py @@ -0,0 +1,142 @@ +# Constants. +# +# Copyright (C) 2016 g10 Code GmbH +# +# This file is part of GPGME. +# +# GPGME is free software; you can redistribute it and/or modify it +# under the terms of the GNU Lesser General Public License as +# published by the Free Software Foundation; either version 2.1 of the +# License, or (at your option) any later version. +# +# GPGME is distributed in the hope that it will be useful, but WITHOUT +# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY +# or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General +# Public License for more details. +# +# You should have received a copy of the GNU Lesser General Public +# License along with this program; if not, see . + +from __future__ import absolute_import, print_function, unicode_literals +del absolute_import, print_function, unicode_literals + +from gpg import util +util.process_constants('GPGME_', globals()) +del util + +# For convenience, we import the modules here. +from . import data, keylist, sig, tofu # The subdirs. +from . import create, event, keysign, md, pk, protocol, sigsum, status, validity + +# A complication arises because 'import' is a reserved keyword. +# Import it as 'Import' instead. +globals()['Import'] = getattr(__import__('', globals(), locals(), + [str('import')], 1), "import") + +__all__ = ['data', 'event', 'import', 'keysign', 'keylist', 'md', 'pk', + 'protocol', 'sig', 'sigsum', 'status', 'tofu', 'validity', 'create'] + +# GPGME 1.7 replaced gpgme_op_edit with gpgme_op_interact. We +# implement gpg.Context.op_edit using gpgme_op_interact, so the +# callbacks will be called with string keywords instead of numeric +# status messages. Code that is using these constants will continue +# to work. + +STATUS_ABORT = "ABORT" +STATUS_ALREADY_SIGNED = "ALREADY_SIGNED" +STATUS_ATTRIBUTE = "ATTRIBUTE" +STATUS_BACKUP_KEY_CREATED = "BACKUP_KEY_CREATED" +STATUS_BAD_PASSPHRASE = "BAD_PASSPHRASE" +STATUS_BADARMOR = "BADARMOR" +STATUS_BADMDC = "BADMDC" +STATUS_BADSIG = "BADSIG" +STATUS_BEGIN_DECRYPTION = "BEGIN_DECRYPTION" +STATUS_BEGIN_ENCRYPTION = "BEGIN_ENCRYPTION" +STATUS_BEGIN_SIGNING = "BEGIN_SIGNING" +STATUS_BEGIN_STREAM = "BEGIN_STREAM" +STATUS_CARDCTRL = "CARDCTRL" +STATUS_DECRYPTION_FAILED = "DECRYPTION_FAILED" +STATUS_DECRYPTION_INFO = "DECRYPTION_INFO" +STATUS_DECRYPTION_OKAY = "DECRYPTION_OKAY" +STATUS_DELETE_PROBLEM = "DELETE_PROBLEM" +STATUS_ENC_TO = "ENC_TO" +STATUS_END_DECRYPTION = "END_DECRYPTION" +STATUS_END_ENCRYPTION = "END_ENCRYPTION" +STATUS_END_STREAM = "END_STREAM" +STATUS_ENTER = "ENTER" +STATUS_ERRMDC = "ERRMDC" +STATUS_ERROR = "ERROR" +STATUS_ERRSIG = "ERRSIG" +STATUS_EXPKEYSIG = "EXPKEYSIG" +STATUS_EXPSIG = "EXPSIG" +STATUS_FAILURE = "FAILURE" +STATUS_FILE_DONE = "FILE_DONE" +STATUS_FILE_ERROR = "FILE_ERROR" +STATUS_FILE_START = "FILE_START" +STATUS_GET_BOOL = "GET_BOOL" +STATUS_GET_HIDDEN = "GET_HIDDEN" +STATUS_GET_LINE = "GET_LINE" +STATUS_GOOD_PASSPHRASE = "GOOD_PASSPHRASE" +STATUS_GOODMDC = "GOODMDC" +STATUS_GOODSIG = "GOODSIG" +STATUS_GOT_IT = "GOT_IT" +STATUS_IMPORT_OK = "IMPORT_OK" +STATUS_IMPORT_PROBLEM = "IMPORT_PROBLEM" +STATUS_IMPORT_RES = "IMPORT_RES" +STATUS_IMPORTED = "IMPORTED" +STATUS_INQUIRE_MAXLEN = "INQUIRE_MAXLEN" +STATUS_INV_RECP = "INV_RECP" +STATUS_INV_SGNR = "INV_SGNR" +STATUS_KEY_CONSIDERED = "KEY_CONSIDERED" +STATUS_KEY_CREATED = "KEY_CREATED" +STATUS_KEY_NOT_CREATED = "KEY_NOT_CREATED" +STATUS_KEYEXPIRED = "KEYEXPIRED" +STATUS_KEYREVOKED = "KEYREVOKED" +STATUS_LEAVE = "LEAVE" +STATUS_MISSING_PASSPHRASE = "MISSING_PASSPHRASE" +STATUS_MOUNTPOINT = "MOUNTPOINT" +STATUS_NEED_PASSPHRASE = "NEED_PASSPHRASE" +STATUS_NEED_PASSPHRASE_PIN = "NEED_PASSPHRASE_PIN" +STATUS_NEED_PASSPHRASE_SYM = "NEED_PASSPHRASE_SYM" +STATUS_NEWSIG = "NEWSIG" +STATUS_NO_PUBKEY = "NO_PUBKEY" +STATUS_NO_RECP = "NO_RECP" +STATUS_NO_SECKEY = "NO_SECKEY" +STATUS_NO_SGNR = "NO_SGNR" +STATUS_NODATA = "NODATA" +STATUS_NOTATION_DATA = "NOTATION_DATA" +STATUS_NOTATION_FLAGS = "NOTATION_FLAGS" +STATUS_NOTATION_NAME = "NOTATION_NAME" +STATUS_PINENTRY_LAUNCHED = "PINENTRY_LAUNCHED" +STATUS_PKA_TRUST_BAD = "PKA_TRUST_BAD" +STATUS_PKA_TRUST_GOOD = "PKA_TRUST_GOOD" +STATUS_PLAINTEXT = "PLAINTEXT" +STATUS_PLAINTEXT_LENGTH = "PLAINTEXT_LENGTH" +STATUS_POLICY_URL = "POLICY_URL" +STATUS_PROGRESS = "PROGRESS" +STATUS_REVKEYSIG = "REVKEYSIG" +STATUS_RSA_OR_IDEA = "RSA_OR_IDEA" +STATUS_SC_OP_FAILURE = "SC_OP_FAILURE" +STATUS_SC_OP_SUCCESS = "SC_OP_SUCCESS" +STATUS_SESSION_KEY = "SESSION_KEY" +STATUS_SHM_GET = "SHM_GET" +STATUS_SHM_GET_BOOL = "SHM_GET_BOOL" +STATUS_SHM_GET_HIDDEN = "SHM_GET_HIDDEN" +STATUS_SHM_INFO = "SHM_INFO" +STATUS_SIG_CREATED = "SIG_CREATED" +STATUS_SIG_ID = "SIG_ID" +STATUS_SIG_SUBPACKET = "SIG_SUBPACKET" +STATUS_SIGEXPIRED = "SIGEXPIRED" +STATUS_SUCCESS = "SUCCESS" +STATUS_TOFU_STATS = "TOFU_STATS" +STATUS_TOFU_STATS_LONG = "TOFU_STATS_LONG" +STATUS_TOFU_USER = "TOFU_USER" +STATUS_TRUNCATED = "TRUNCATED" +STATUS_TRUST_FULLY = "TRUST_FULLY" +STATUS_TRUST_MARGINAL = "TRUST_MARGINAL" +STATUS_TRUST_NEVER = "TRUST_NEVER" +STATUS_TRUST_ULTIMATE = "TRUST_ULTIMATE" +STATUS_TRUST_UNDEFINED = "TRUST_UNDEFINED" +STATUS_UNEXPECTED = "UNEXPECTED" +STATUS_USERID_HINT = "USERID_HINT" +STATUS_VALIDSIG = "VALIDSIG" diff --git a/lang/python/src/constants/create.py b/lang/python/src/constants/create.py new file mode 100644 index 00000000..132e96d4 --- /dev/null +++ b/lang/python/src/constants/create.py @@ -0,0 +1,25 @@ +# Flags for key creation +# +# Copyright (C) 2017 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 . + +from __future__ import absolute_import, print_function, unicode_literals +del absolute_import, print_function, unicode_literals + +from gpg import util +util.process_constants('GPGME_CREATE_', globals()) +del util diff --git a/lang/python/src/constants/data/__init__.py b/lang/python/src/constants/data/__init__.py new file mode 100644 index 00000000..8274ab91 --- /dev/null +++ b/lang/python/src/constants/data/__init__.py @@ -0,0 +1,6 @@ + +from __future__ import absolute_import, print_function, unicode_literals +del absolute_import, print_function, unicode_literals + +from . import encoding +__all__ = ['encoding'] diff --git a/lang/python/src/constants/data/encoding.py b/lang/python/src/constants/data/encoding.py new file mode 100644 index 00000000..e76a22ee --- /dev/null +++ b/lang/python/src/constants/data/encoding.py @@ -0,0 +1,23 @@ +# Copyright (C) 2004 Igor Belyi +# Copyright (C) 2002 John Goerzen +# +# This library is free software; you can redistribute it and/or +# modify it under the terms of the GNU Lesser General Public +# License as published by the Free Software Foundation; either +# version 2.1 of the License, or (at your option) any later version. +# +# This library is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +# Lesser General Public License for more details. +# +# You should have received a copy of the GNU Lesser General Public +# License along with this library; if not, write to the Free Software +# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + +from __future__ import absolute_import, print_function, unicode_literals +del absolute_import, print_function, unicode_literals + +from gpg import util +util.process_constants('GPGME_DATA_ENCODING_', globals()) +del util diff --git a/lang/python/src/constants/event.py b/lang/python/src/constants/event.py new file mode 100644 index 00000000..1b14d1d1 --- /dev/null +++ b/lang/python/src/constants/event.py @@ -0,0 +1,23 @@ +# Copyright (C) 2004 Igor Belyi +# Copyright (C) 2002 John Goerzen +# +# This library is free software; you can redistribute it and/or +# modify it under the terms of the GNU Lesser General Public +# License as published by the Free Software Foundation; either +# version 2.1 of the License, or (at your option) any later version. +# +# This library is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +# Lesser General Public License for more details. +# +# You should have received a copy of the GNU Lesser General Public +# License along with this library; if not, write to the Free Software +# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + +from __future__ import absolute_import, print_function, unicode_literals +del absolute_import, print_function, unicode_literals + +from gpg import util +util.process_constants('GPGME_EVENT_', globals()) +del util diff --git a/lang/python/src/constants/import.py b/lang/python/src/constants/import.py new file mode 100644 index 00000000..47c296cb --- /dev/null +++ b/lang/python/src/constants/import.py @@ -0,0 +1,23 @@ +# Copyright (C) 2004 Igor Belyi +# Copyright (C) 2002 John Goerzen +# +# This library is free software; you can redistribute it and/or +# modify it under the terms of the GNU Lesser General Public +# License as published by the Free Software Foundation; either +# version 2.1 of the License, or (at your option) any later version. +# +# This library is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +# Lesser General Public License for more details. +# +# You should have received a copy of the GNU Lesser General Public +# License along with this library; if not, write to the Free Software +# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + +from __future__ import absolute_import, print_function, unicode_literals +del absolute_import, print_function, unicode_literals + +from gpg import util +util.process_constants('GPGME_IMPORT_', globals()) +del util diff --git a/lang/python/src/constants/keylist/__init__.py b/lang/python/src/constants/keylist/__init__.py new file mode 100644 index 00000000..2ce0edfd --- /dev/null +++ b/lang/python/src/constants/keylist/__init__.py @@ -0,0 +1,6 @@ + +from __future__ import absolute_import, print_function, unicode_literals +del absolute_import, print_function, unicode_literals + +from . import mode +__all__ = ['mode'] diff --git a/lang/python/src/constants/keylist/mode.py b/lang/python/src/constants/keylist/mode.py new file mode 100644 index 00000000..39e1819d --- /dev/null +++ b/lang/python/src/constants/keylist/mode.py @@ -0,0 +1,23 @@ +# Copyright (C) 2004 Igor Belyi +# Copyright (C) 2002 John Goerzen +# +# This library is free software; you can redistribute it and/or +# modify it under the terms of the GNU Lesser General Public +# License as published by the Free Software Foundation; either +# version 2.1 of the License, or (at your option) any later version. +# +# This library is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +# Lesser General Public License for more details. +# +# You should have received a copy of the GNU Lesser General Public +# License along with this library; if not, write to the Free Software +# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + +from __future__ import absolute_import, print_function, unicode_literals +del absolute_import, print_function, unicode_literals + +from gpg import util +util.process_constants('GPGME_KEYLIST_MODE_', globals()) +del util diff --git a/lang/python/src/constants/keysign.py b/lang/python/src/constants/keysign.py new file mode 100644 index 00000000..fccdbc42 --- /dev/null +++ b/lang/python/src/constants/keysign.py @@ -0,0 +1,25 @@ +# Flags for key signing +# +# Copyright (C) 2017 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 . + +from __future__ import absolute_import, print_function, unicode_literals +del absolute_import, print_function, unicode_literals + +from gpg import util +util.process_constants('GPGME_KEYSIGN_', globals()) +del util diff --git a/lang/python/src/constants/md.py b/lang/python/src/constants/md.py new file mode 100644 index 00000000..f3e8bbdb --- /dev/null +++ b/lang/python/src/constants/md.py @@ -0,0 +1,23 @@ +# Copyright (C) 2004 Igor Belyi +# Copyright (C) 2002 John Goerzen +# +# This library is free software; you can redistribute it and/or +# modify it under the terms of the GNU Lesser General Public +# License as published by the Free Software Foundation; either +# version 2.1 of the License, or (at your option) any later version. +# +# This library is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +# Lesser General Public License for more details. +# +# You should have received a copy of the GNU Lesser General Public +# License along with this library; if not, write to the Free Software +# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + +from __future__ import absolute_import, print_function, unicode_literals +del absolute_import, print_function, unicode_literals + +from gpg import util +util.process_constants('GPGME_MD_', globals()) +del util diff --git a/lang/python/src/constants/pk.py b/lang/python/src/constants/pk.py new file mode 100644 index 00000000..6bf2a215 --- /dev/null +++ b/lang/python/src/constants/pk.py @@ -0,0 +1,23 @@ +# Copyright (C) 2004 Igor Belyi +# Copyright (C) 2002 John Goerzen +# +# This library is free software; you can redistribute it and/or +# modify it under the terms of the GNU Lesser General Public +# License as published by the Free Software Foundation; either +# version 2.1 of the License, or (at your option) any later version. +# +# This library is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +# Lesser General Public License for more details. +# +# You should have received a copy of the GNU Lesser General Public +# License along with this library; if not, write to the Free Software +# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + +from __future__ import absolute_import, print_function, unicode_literals +del absolute_import, print_function, unicode_literals + +from gpg import util +util.process_constants('GPGME_PK_', globals()) +del util diff --git a/lang/python/src/constants/protocol.py b/lang/python/src/constants/protocol.py new file mode 100644 index 00000000..d086bbde --- /dev/null +++ b/lang/python/src/constants/protocol.py @@ -0,0 +1,23 @@ +# Copyright (C) 2004 Igor Belyi +# Copyright (C) 2002 John Goerzen +# +# This library is free software; you can redistribute it and/or +# modify it under the terms of the GNU Lesser General Public +# License as published by the Free Software Foundation; either +# version 2.1 of the License, or (at your option) any later version. +# +# This library is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +# Lesser General Public License for more details. +# +# You should have received a copy of the GNU Lesser General Public +# License along with this library; if not, write to the Free Software +# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + +from __future__ import absolute_import, print_function, unicode_literals +del absolute_import, print_function, unicode_literals + +from gpg import util +util.process_constants('GPGME_PROTOCOL_', globals()) +del util diff --git a/lang/python/src/constants/sig/__init__.py b/lang/python/src/constants/sig/__init__.py new file mode 100644 index 00000000..39d4e6e1 --- /dev/null +++ b/lang/python/src/constants/sig/__init__.py @@ -0,0 +1,6 @@ + +from __future__ import absolute_import, print_function, unicode_literals +del absolute_import, print_function, unicode_literals + +from . import mode, notation +__all__ = ['mode', 'notation'] diff --git a/lang/python/src/constants/sig/mode.py b/lang/python/src/constants/sig/mode.py new file mode 100644 index 00000000..0f4f0efc --- /dev/null +++ b/lang/python/src/constants/sig/mode.py @@ -0,0 +1,23 @@ +# Copyright (C) 2004 Igor Belyi +# Copyright (C) 2002 John Goerzen +# +# This library is free software; you can redistribute it and/or +# modify it under the terms of the GNU Lesser General Public +# License as published by the Free Software Foundation; either +# version 2.1 of the License, or (at your option) any later version. +# +# This library is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +# Lesser General Public License for more details. +# +# You should have received a copy of the GNU Lesser General Public +# License along with this library; if not, write to the Free Software +# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + +from __future__ import absolute_import, print_function, unicode_literals +del absolute_import, print_function, unicode_literals + +from gpg import util +util.process_constants('GPGME_SIG_MODE_', globals()) +del util diff --git a/lang/python/src/constants/sig/notation.py b/lang/python/src/constants/sig/notation.py new file mode 100644 index 00000000..9a79e014 --- /dev/null +++ b/lang/python/src/constants/sig/notation.py @@ -0,0 +1,25 @@ +# Constants for signature notation data. +# +# Copyright (C) 2016 g10 Code GmbH +# +# This file is part of GPGME. +# +# GPGME is free software; you can redistribute it and/or modify it +# under the terms of the GNU Lesser General Public License as +# published by the Free Software Foundation; either version 2.1 of the +# License, or (at your option) any later version. +# +# GPGME is distributed in the hope that it will be useful, but WITHOUT +# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY +# or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General +# Public License for more details. +# +# You should have received a copy of the GNU Lesser General Public +# License along with this program; if not, see . + +from __future__ import absolute_import, print_function, unicode_literals +del absolute_import, print_function, unicode_literals + +from gpg import util +util.process_constants('GPGME_SIG_NOTATION_', globals()) +del util diff --git a/lang/python/src/constants/sigsum.py b/lang/python/src/constants/sigsum.py new file mode 100644 index 00000000..09ef9d78 --- /dev/null +++ b/lang/python/src/constants/sigsum.py @@ -0,0 +1,23 @@ +# Copyright (C) 2004 Igor Belyi +# Copyright (C) 2002 John Goerzen +# +# This library is free software; you can redistribute it and/or +# modify it under the terms of the GNU Lesser General Public +# License as published by the Free Software Foundation; either +# version 2.1 of the License, or (at your option) any later version. +# +# This library is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +# Lesser General Public License for more details. +# +# You should have received a copy of the GNU Lesser General Public +# License along with this library; if not, write to the Free Software +# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + +from __future__ import absolute_import, print_function, unicode_literals +del absolute_import, print_function, unicode_literals + +from gpg import util +util.process_constants('GPGME_SIGSUM_', globals()) +del util diff --git a/lang/python/src/constants/status.py b/lang/python/src/constants/status.py new file mode 100644 index 00000000..a0ad073e --- /dev/null +++ b/lang/python/src/constants/status.py @@ -0,0 +1,124 @@ +# Copyright (C) 2004 Igor Belyi +# Copyright (C) 2002 John Goerzen +# +# This library is free software; you can redistribute it and/or +# modify it under the terms of the GNU Lesser General Public +# License as published by the Free Software Foundation; either +# version 2.1 of the License, or (at your option) any later version. +# +# This library is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +# Lesser General Public License for more details. +# +# You should have received a copy of the GNU Lesser General Public +# License along with this library; if not, write to the Free Software +# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + +from __future__ import absolute_import, print_function, unicode_literals +del absolute_import, print_function, unicode_literals + +# GPGME 1.7 replaced gpgme_op_edit with gpgme_op_interact. We +# implement gpg.Context.op_edit using gpgme_op_interact, so the +# callbacks will be called with string keywords instead of numeric +# status messages. Code that is using these constants will continue +# to work. + +ABORT = "ABORT" +ALREADY_SIGNED = "ALREADY_SIGNED" +ATTRIBUTE = "ATTRIBUTE" +BACKUP_KEY_CREATED = "BACKUP_KEY_CREATED" +BAD_PASSPHRASE = "BAD_PASSPHRASE" +BADARMOR = "BADARMOR" +BADMDC = "BADMDC" +BADSIG = "BADSIG" +BEGIN_DECRYPTION = "BEGIN_DECRYPTION" +BEGIN_ENCRYPTION = "BEGIN_ENCRYPTION" +BEGIN_SIGNING = "BEGIN_SIGNING" +BEGIN_STREAM = "BEGIN_STREAM" +CARDCTRL = "CARDCTRL" +DECRYPTION_FAILED = "DECRYPTION_FAILED" +DECRYPTION_INFO = "DECRYPTION_INFO" +DECRYPTION_OKAY = "DECRYPTION_OKAY" +DELETE_PROBLEM = "DELETE_PROBLEM" +ENC_TO = "ENC_TO" +END_DECRYPTION = "END_DECRYPTION" +END_ENCRYPTION = "END_ENCRYPTION" +END_STREAM = "END_STREAM" +ENTER = "ENTER" +ERRMDC = "ERRMDC" +ERROR = "ERROR" +ERRSIG = "ERRSIG" +EXPKEYSIG = "EXPKEYSIG" +EXPSIG = "EXPSIG" +FAILURE = "FAILURE" +FILE_DONE = "FILE_DONE" +FILE_ERROR = "FILE_ERROR" +FILE_START = "FILE_START" +GET_BOOL = "GET_BOOL" +GET_HIDDEN = "GET_HIDDEN" +GET_LINE = "GET_LINE" +GOOD_PASSPHRASE = "GOOD_PASSPHRASE" +GOODMDC = "GOODMDC" +GOODSIG = "GOODSIG" +GOT_IT = "GOT_IT" +IMPORT_OK = "IMPORT_OK" +IMPORT_PROBLEM = "IMPORT_PROBLEM" +IMPORT_RES = "IMPORT_RES" +IMPORTED = "IMPORTED" +INQUIRE_MAXLEN = "INQUIRE_MAXLEN" +INV_RECP = "INV_RECP" +INV_SGNR = "INV_SGNR" +KEY_CONSIDERED = "KEY_CONSIDERED" +KEY_CREATED = "KEY_CREATED" +KEY_NOT_CREATED = "KEY_NOT_CREATED" +KEYEXPIRED = "KEYEXPIRED" +KEYREVOKED = "KEYREVOKED" +LEAVE = "LEAVE" +MISSING_PASSPHRASE = "MISSING_PASSPHRASE" +MOUNTPOINT = "MOUNTPOINT" +NEED_PASSPHRASE = "NEED_PASSPHRASE" +NEED_PASSPHRASE_PIN = "NEED_PASSPHRASE_PIN" +NEED_PASSPHRASE_SYM = "NEED_PASSPHRASE_SYM" +NEWSIG = "NEWSIG" +NO_PUBKEY = "NO_PUBKEY" +NO_RECP = "NO_RECP" +NO_SECKEY = "NO_SECKEY" +NO_SGNR = "NO_SGNR" +NODATA = "NODATA" +NOTATION_DATA = "NOTATION_DATA" +NOTATION_FLAGS = "NOTATION_FLAGS" +NOTATION_NAME = "NOTATION_NAME" +PINENTRY_LAUNCHED = "PINENTRY_LAUNCHED" +PKA_TRUST_BAD = "PKA_TRUST_BAD" +PKA_TRUST_GOOD = "PKA_TRUST_GOOD" +PLAINTEXT = "PLAINTEXT" +PLAINTEXT_LENGTH = "PLAINTEXT_LENGTH" +POLICY_URL = "POLICY_URL" +PROGRESS = "PROGRESS" +REVKEYSIG = "REVKEYSIG" +RSA_OR_IDEA = "RSA_OR_IDEA" +SC_OP_FAILURE = "SC_OP_FAILURE" +SC_OP_SUCCESS = "SC_OP_SUCCESS" +SESSION_KEY = "SESSION_KEY" +SHM_GET = "SHM_GET" +SHM_GET_BOOL = "SHM_GET_BOOL" +SHM_GET_HIDDEN = "SHM_GET_HIDDEN" +SHM_INFO = "SHM_INFO" +SIG_CREATED = "SIG_CREATED" +SIG_ID = "SIG_ID" +SIG_SUBPACKET = "SIG_SUBPACKET" +SIGEXPIRED = "SIGEXPIRED" +SUCCESS = "SUCCESS" +TOFU_STATS = "TOFU_STATS" +TOFU_STATS_LONG = "TOFU_STATS_LONG" +TOFU_USER = "TOFU_USER" +TRUNCATED = "TRUNCATED" +TRUST_FULLY = "TRUST_FULLY" +TRUST_MARGINAL = "TRUST_MARGINAL" +TRUST_NEVER = "TRUST_NEVER" +TRUST_ULTIMATE = "TRUST_ULTIMATE" +TRUST_UNDEFINED = "TRUST_UNDEFINED" +UNEXPECTED = "UNEXPECTED" +USERID_HINT = "USERID_HINT" +VALIDSIG = "VALIDSIG" diff --git a/lang/python/src/constants/tofu/__init__.py b/lang/python/src/constants/tofu/__init__.py new file mode 100644 index 00000000..819a58bb --- /dev/null +++ b/lang/python/src/constants/tofu/__init__.py @@ -0,0 +1,24 @@ +# TOFU +# +# Copyright (C) 2017 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 . + +from __future__ import absolute_import, print_function, unicode_literals +del absolute_import, print_function, unicode_literals + +from . import policy +__all__ = ['policy'] diff --git a/lang/python/src/constants/tofu/policy.py b/lang/python/src/constants/tofu/policy.py new file mode 100644 index 00000000..5a61f067 --- /dev/null +++ b/lang/python/src/constants/tofu/policy.py @@ -0,0 +1,25 @@ +# TOFU policies +# +# Copyright (C) 2017 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 . + +from __future__ import absolute_import, print_function, unicode_literals +del absolute_import, print_function, unicode_literals + +from gpg import util +util.process_constants('GPGME_TOFU_POLICY_', globals()) +del util diff --git a/lang/python/src/constants/validity.py b/lang/python/src/constants/validity.py new file mode 100644 index 00000000..d3c53458 --- /dev/null +++ b/lang/python/src/constants/validity.py @@ -0,0 +1,23 @@ +# Copyright (C) 2004 Igor Belyi +# Copyright (C) 2002 John Goerzen +# +# This library is free software; you can redistribute it and/or +# modify it under the terms of the GNU Lesser General Public +# License as published by the Free Software Foundation; either +# version 2.1 of the License, or (at your option) any later version. +# +# This library is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +# Lesser General Public License for more details. +# +# You should have received a copy of the GNU Lesser General Public +# License along with this library; if not, write to the Free Software +# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + +from __future__ import absolute_import, print_function, unicode_literals +del absolute_import, print_function, unicode_literals + +from gpg import util +util.process_constants('GPGME_VALIDITY_', globals()) +del util diff --git a/lang/python/src/core.py b/lang/python/src/core.py new file mode 100644 index 00000000..632f4ca5 --- /dev/null +++ b/lang/python/src/core.py @@ -0,0 +1,1490 @@ +# Copyright (C) 2016-2017 g10 Code GmbH +# Copyright (C) 2004,2008 Igor Belyi +# Copyright (C) 2002 John Goerzen +# +# This library is free software; you can redistribute it and/or +# modify it under the terms of the GNU Lesser General Public +# License as published by the Free Software Foundation; either +# version 2.1 of the License, or (at your option) any later version. +# +# This library is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +# Lesser General Public License for more details. +# +# You should have received a copy of the GNU Lesser General Public +# License along with this library; if not, write to the Free Software +# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + +"""Core functionality + +Core functionality of GPGME wrapped in a object-oriented fashion. +Provides the 'Context' class for performing cryptographic operations, +and the 'Data' class describing buffers of data. + +""" + +from __future__ import absolute_import, print_function, unicode_literals +del absolute_import, print_function, unicode_literals + +import re +import os +import warnings +import weakref +from . import gpgme +from .errors import errorcheck, GPGMEError +from . import constants +from . import errors +from . import util + +class GpgmeWrapper(object): + """Base wrapper class + + Not to be instantiated directly. + + """ + + def __init__(self, wrapped): + self._callback_excinfo = None + self.wrapped = wrapped + + def __repr__(self): + return '<{}/{!r}>'.format(super(GpgmeWrapper, self).__repr__(), + self.wrapped) + + def __str__(self): + acc = ['{}.{}'.format(__name__, self.__class__.__name__)] + flags = [f for f in self._boolean_properties if getattr(self, f)] + if flags: + acc.append('({})'.format(' '.join(flags))) + + return '<{}>'.format(' '.join(acc)) + + def __hash__(self): + return hash(repr(self.wrapped)) + + def __eq__(self, other): + if other == None: + return False + else: + return repr(self.wrapped) == repr(other.wrapped) + + @property + def _ctype(self): + """The name of the c type wrapped by this class + + Must be set by child classes. + + """ + raise NotImplementedError() + + @property + def _cprefix(self): + """The common prefix of c functions wrapped by this class + + Must be set by child classes. + + """ + raise NotImplementedError() + + def _errorcheck(self, name): + """Must be implemented by child classes. + + This function must return a trueish value for all c functions + returning gpgme_error_t.""" + raise NotImplementedError() + + """The set of all boolean properties""" + _boolean_properties = set() + + def __wrap_boolean_property(self, key, do_set=False, value=None): + get_func = getattr(gpgme, + "{}get_{}".format(self._cprefix, key)) + set_func = getattr(gpgme, + "{}set_{}".format(self._cprefix, key)) + def get(slf): + return bool(get_func(slf.wrapped)) + def set_(slf, value): + set_func(slf.wrapped, bool(value)) + + p = property(get, set_, doc="{} flag".format(key)) + setattr(self.__class__, key, p) + + if do_set: + set_(self, bool(value)) + else: + return get(self) + + _munge_docstring = re.compile(r'gpgme_([^(]*)\(([^,]*), (.*\) -> .*)') + def __getattr__(self, key): + """On-the-fly generation of wrapper methods and properties""" + if key[0] == '_' or self._cprefix == None: + return None + + if key in self._boolean_properties: + return self.__wrap_boolean_property(key) + + name = self._cprefix + key + func = getattr(gpgme, name) + + if self._errorcheck(name): + def _funcwrap(slf, *args): + result = func(slf.wrapped, *args) + if slf._callback_excinfo: + gpgme.gpg_raise_callback_exception(slf) + return errorcheck(result, "Invocation of " + name) + else: + def _funcwrap(slf, *args): + result = func(slf.wrapped, *args) + if slf._callback_excinfo: + gpgme.gpg_raise_callback_exception(slf) + return result + + doc = self._munge_docstring.sub(r'\2.\1(\3', getattr(func, "__doc__")) + _funcwrap.__doc__ = doc + + # Monkey-patch the class. + setattr(self.__class__, key, _funcwrap) + + # Bind the method to 'self'. + def wrapper(*args): + return _funcwrap(self, *args) + wrapper.__doc__ = doc + + return wrapper + + def __setattr__(self, key, value): + """On-the-fly generation of properties""" + if key in self._boolean_properties: + self.__wrap_boolean_property(key, True, value) + else: + super(GpgmeWrapper, self).__setattr__(key, value) + +class Context(GpgmeWrapper): + """Context for cryptographic operations + + All cryptographic operations in GPGME are performed within a + context, which contains the internal state of the operation as + well as configuration parameters. By using several contexts you + can run several cryptographic operations in parallel, with + different configuration. + + Access to a context must be synchronized. + + """ + + def __init__(self, armor=False, textmode=False, offline=False, + signers=[], pinentry_mode=constants.PINENTRY_MODE_DEFAULT, + protocol=constants.PROTOCOL_OpenPGP, + wrapped=None, home_dir=None): + """Construct a context object + + Keyword arguments: + armor -- enable ASCII armoring (default False) + textmode -- enable canonical text mode (default False) + offline -- do not contact external key sources (default False) + signers -- list of keys used for signing (default []) + pinentry_mode -- pinentry mode (default PINENTRY_MODE_DEFAULT) + protocol -- protocol to use (default PROTOCOL_OpenPGP) + home_dir -- state directory (default is the engine default) + + """ + if wrapped: + self.own = False + else: + tmp = gpgme.new_gpgme_ctx_t_p() + errorcheck(gpgme.gpgme_new(tmp)) + wrapped = gpgme.gpgme_ctx_t_p_value(tmp) + gpgme.delete_gpgme_ctx_t_p(tmp) + self.own = True + super(Context, self).__init__(wrapped) + self.armor = armor + self.textmode = textmode + self.offline = offline + self.signers = signers + self.pinentry_mode = pinentry_mode + self.protocol = protocol + self.home_dir = home_dir + + def __repr__(self): + return ( + "Context(armor={0.armor}, " + "textmode={0.textmode}, offline={0.offline}, " + "signers={0.signers}, pinentry_mode={0.pinentry_mode}, " + "protocol={0.protocol}, home_dir={0.home_dir}" + ")").format(self) + + def encrypt(self, plaintext, recipients=[], sign=True, sink=None, + passphrase=None, always_trust=False, add_encrypt_to=False, + prepare=False, expect_sign=False, compress=True): + """Encrypt data + + Encrypt the given plaintext for the given recipients. If the + list of recipients is empty, the data is encrypted + symmetrically with a passphrase. + + The passphrase can be given as parameter, using a callback + registered at the context, or out-of-band via pinentry. + + Keyword arguments: + recipients -- list of keys to encrypt to + sign -- sign plaintext (default True) + sink -- write result to sink instead of returning it + passphrase -- for symmetric encryption + always_trust -- always trust the keys (default False) + add_encrypt_to -- encrypt to configured additional keys (default False) + prepare -- (ui) prepare for encryption (default False) + expect_sign -- (ui) prepare for signing (default False) + compress -- compress plaintext (default True) + + Returns: + ciphertext -- the encrypted data (or None if sink is given) + result -- additional information about the encryption + sign_result -- additional information about the signature(s) + + Raises: + InvalidRecipients -- if encryption using a particular key failed + InvalidSigners -- if signing using a particular key failed + GPGMEError -- as signaled by the underlying library + + """ + ciphertext = sink if sink else Data() + flags = 0 + flags |= always_trust * constants.ENCRYPT_ALWAYS_TRUST + flags |= (not add_encrypt_to) * constants.ENCRYPT_NO_ENCRYPT_TO + flags |= prepare * constants.ENCRYPT_PREPARE + flags |= expect_sign * constants.ENCRYPT_EXPECT_SIGN + flags |= (not compress) * constants.ENCRYPT_NO_COMPRESS + + if passphrase != None: + old_pinentry_mode = self.pinentry_mode + old_passphrase_cb = getattr(self, '_passphrase_cb', None) + self.pinentry_mode = constants.PINENTRY_MODE_LOOPBACK + def passphrase_cb(hint, desc, prev_bad, hook=None): + return passphrase + self.set_passphrase_cb(passphrase_cb) + + try: + if sign: + self.op_encrypt_sign(recipients, flags, plaintext, ciphertext) + else: + self.op_encrypt(recipients, flags, plaintext, ciphertext) + except errors.GPGMEError as e: + if e.getcode() == errors.UNUSABLE_PUBKEY: + result = self.op_encrypt_result() + if result.invalid_recipients: + raise errors.InvalidRecipients(result.invalid_recipients) + if e.getcode() == errors.UNUSABLE_SECKEY: + sig_result = self.op_sign_result() + if sig_result.invalid_signers: + raise errors.InvalidSigners(sig_result.invalid_signers) + raise + finally: + if passphrase != None: + self.pinentry_mode = old_pinentry_mode + if old_passphrase_cb: + self.set_passphrase_cb(*old_passphrase_cb[1:]) + + result = self.op_encrypt_result() + assert not result.invalid_recipients + sig_result = self.op_sign_result() if sign else None + assert not sig_result or not sig_result.invalid_signers + + cipherbytes = None + if not sink: + ciphertext.seek(0, os.SEEK_SET) + cipherbytes = ciphertext.read() + return cipherbytes, result, sig_result + + def decrypt(self, ciphertext, sink=None, passphrase=None, verify=True): + """Decrypt data + + Decrypt the given ciphertext and verify any signatures. If + VERIFY is an iterable of keys, the ciphertext must be signed + by all those keys, otherwise an error is raised. + + If the ciphertext is symmetrically encrypted using a + passphrase, that passphrase can be given as parameter, using a + callback registered at the context, or out-of-band via + pinentry. + + Keyword arguments: + sink -- write result to sink instead of returning it + passphrase -- for symmetric decryption + verify -- check signatures (default True) + + Returns: + plaintext -- the decrypted data (or None if sink is given) + result -- additional information about the decryption + verify_result -- additional information about the signature(s) + + Raises: + UnsupportedAlgorithm -- if an unsupported algorithm was used + BadSignatures -- if a bad signature is encountered + MissingSignatures -- if expected signatures are missing or bad + GPGMEError -- as signaled by the underlying library + + """ + plaintext = sink if sink else Data() + + if passphrase != None: + old_pinentry_mode = self.pinentry_mode + old_passphrase_cb = getattr(self, '_passphrase_cb', None) + self.pinentry_mode = constants.PINENTRY_MODE_LOOPBACK + def passphrase_cb(hint, desc, prev_bad, hook=None): + return passphrase + self.set_passphrase_cb(passphrase_cb) + + try: + if verify: + self.op_decrypt_verify(ciphertext, plaintext) + else: + self.op_decrypt(ciphertext, plaintext) + finally: + if passphrase != None: + self.pinentry_mode = old_pinentry_mode + if old_passphrase_cb: + self.set_passphrase_cb(*old_passphrase_cb[1:]) + + result = self.op_decrypt_result() + verify_result = self.op_verify_result() if verify else None + if result.unsupported_algorithm: + raise errors.UnsupportedAlgorithm(result.unsupported_algorithm) + + if verify: + if any(s.status != errors.NO_ERROR + for s in verify_result.signatures): + raise errors.BadSignatures(verify_result) + + if verify and verify != True: + missing = list() + for key in verify: + ok = False + for subkey in key.subkeys: + for sig in verify_result.signatures: + if sig.summary & constants.SIGSUM_VALID == 0: + continue + if subkey.can_sign and subkey.fpr == sig.fpr: + ok = True + break + if ok: + break + if not ok: + missing.append(key) + if missing: + raise errors.MissingSignatures(verify_result, missing) + + plainbytes = None + if not sink: + plaintext.seek(0, os.SEEK_SET) + plainbytes = plaintext.read() + return plainbytes, result, verify_result + + def sign(self, data, sink=None, mode=constants.SIG_MODE_NORMAL): + """Sign data + + Sign the given data with either the configured default local + key, or the 'signers' keys of this context. + + Keyword arguments: + mode -- signature mode (default: normal, see below) + sink -- write result to sink instead of returning it + + Returns: + either + signed_data -- encoded data and signature (normal mode) + signature -- only the signature data (detached mode) + cleartext -- data and signature as text (cleartext mode) + (or None if sink is given) + result -- additional information about the signature(s) + + Raises: + InvalidSigners -- if signing using a particular key failed + GPGMEError -- as signaled by the underlying library + + """ + signeddata = sink if sink else Data() + + try: + self.op_sign(data, signeddata, mode) + except errors.GPGMEError as e: + if e.getcode() == errors.UNUSABLE_SECKEY: + result = self.op_sign_result() + if result.invalid_signers: + raise errors.InvalidSigners(result.invalid_signers) + raise + + result = self.op_sign_result() + assert not result.invalid_signers + + signedbytes = None + if not sink: + signeddata.seek(0, os.SEEK_SET) + signedbytes = signeddata.read() + return signedbytes, result + + def verify(self, signed_data, signature=None, sink=None, verify=[]): + """Verify signatures + + Verify signatures over data. If VERIFY is an iterable of + keys, the ciphertext must be signed by all those keys, + otherwise an error is raised. + + Keyword arguments: + signature -- detached signature data + sink -- write result to sink instead of returning it + + Returns: + data -- the plain data + (or None if sink is given, or we verified a detached signature) + result -- additional information about the signature(s) + + Raises: + BadSignatures -- if a bad signature is encountered + MissingSignatures -- if expected signatures are missing or bad + GPGMEError -- as signaled by the underlying library + + """ + if signature: + # Detached signature, we don't return the plain text. + data = None + else: + data = sink if sink else Data() + + if signature: + self.op_verify(signature, signed_data, None) + else: + self.op_verify(signed_data, None, data) + + result = self.op_verify_result() + if any(s.status != errors.NO_ERROR for s in result.signatures): + raise errors.BadSignatures(result) + + missing = list() + for key in verify: + ok = False + for subkey in key.subkeys: + for sig in result.signatures: + if sig.summary & constants.SIGSUM_VALID == 0: + continue + if subkey.can_sign and subkey.fpr == sig.fpr: + ok = True + break + if ok: + break + if not ok: + missing.append(key) + if missing: + raise errors.MissingSignatures(result, missing) + + plainbytes = None + if data and not sink: + data.seek(0, os.SEEK_SET) + plainbytes = data.read() + return plainbytes, result + + def keylist(self, pattern=None, secret=False, + mode=constants.keylist.mode.LOCAL, + source=None): + """List keys + + Keyword arguments: + pattern -- return keys matching pattern (default: all keys) + secret -- return only secret keys (default: False) + mode -- keylist mode (default: list local keys) + source -- read keys from source instead from the keyring + (all other options are ignored in this case) + + Returns: + -- an iterator returning key objects + + Raises: + GPGMEError -- as signaled by the underlying library + """ + if not source: + self.set_keylist_mode(mode) + self.op_keylist_start(pattern, secret) + else: + # Automatic wrapping of SOURCE is not possible here, + # because the object must not be deallocated until the + # iteration over the results ends. + if not isinstance(source, Data): + source = Data(file=source) + self.op_keylist_from_data_start(source, 0) + + key = self.op_keylist_next() + while key: + yield key + key = self.op_keylist_next() + self.op_keylist_end() + + def create_key(self, userid, algorithm=None, expires_in=0, expires=True, + sign=False, encrypt=False, certify=False, authenticate=False, + passphrase=None, force=False): + """Create a primary key + + Create a primary key for the user id USERID. + + ALGORITHM may be used to specify the public key encryption + algorithm for the new key. By default, a reasonable default + is chosen. You may use "future-default" to select an + algorithm that will be the default in a future implementation + of the engine. ALGORITHM may be a string like "rsa", or + "rsa2048" to explicitly request an algorithm and a key size. + + EXPIRES_IN specifies the expiration time of the key in number + of seconds since the keys creation. By default, a reasonable + expiration time is chosen. If you want to create a key that + does not expire, use the keyword argument EXPIRES. + + SIGN, ENCRYPT, CERTIFY, and AUTHENTICATE can be used to + request the capabilities of the new key. If you don't request + any, a reasonable set of capabilities is selected, and in case + of OpenPGP, a subkey with a reasonable set of capabilities is + created. + + If PASSPHRASE is None (the default), then the key will not be + protected with a passphrase. If PASSPHRASE is a string, it + will be used to protect the key. If PASSPHRASE is True, the + passphrase must be supplied using a passphrase callback or + out-of-band with a pinentry. + + Keyword arguments: + algorithm -- public key algorithm, see above (default: reasonable) + expires_in -- expiration time in seconds (default: reasonable) + expires -- whether or not the key should expire (default: True) + sign -- request the signing capability (see above) + encrypt -- request the encryption capability (see above) + certify -- request the certification capability (see above) + authenticate -- request the authentication capability (see above) + passphrase -- protect the key with a passphrase (default: no passphrase) + force -- force key creation even if a key with the same userid exists + (default: False) + + Returns: + -- an object describing the result of the key creation + + Raises: + GPGMEError -- as signaled by the underlying library + + """ + if util.is_a_string(passphrase): + old_pinentry_mode = self.pinentry_mode + old_passphrase_cb = getattr(self, '_passphrase_cb', None) + self.pinentry_mode = constants.PINENTRY_MODE_LOOPBACK + def passphrase_cb(hint, desc, prev_bad, hook=None): + return passphrase + self.set_passphrase_cb(passphrase_cb) + + try: + self.op_createkey(userid, algorithm, + 0, # reserved + expires_in, + None, # extrakey + ((constants.create.SIGN if sign else 0) + | (constants.create.ENCR if encrypt else 0) + | (constants.create.CERT if certify else 0) + | (constants.create.AUTH if authenticate else 0) + | (constants.create.NOPASSWD if passphrase == None else 0) + | (0 if expires else constants.create.NOEXPIRE) + | (constants.create.FORCE if force else 0))) + finally: + if util.is_a_string(passphrase): + self.pinentry_mode = old_pinentry_mode + if old_passphrase_cb: + self.set_passphrase_cb(*old_passphrase_cb[1:]) + + return self.op_genkey_result() + + def create_subkey(self, key, algorithm=None, expires_in=0, expires=True, + sign=False, encrypt=False, authenticate=False, passphrase=None): + """Create a subkey + + Create a subkey for the given KEY. As subkeys are a concept + of OpenPGP, calling this is only valid for the OpenPGP + protocol. + + ALGORITHM may be used to specify the public key encryption + algorithm for the new subkey. By default, a reasonable + default is chosen. You may use "future-default" to select an + algorithm that will be the default in a future implementation + of the engine. ALGORITHM may be a string like "rsa", or + "rsa2048" to explicitly request an algorithm and a key size. + + EXPIRES_IN specifies the expiration time of the subkey in + number of seconds since the subkeys creation. By default, a + reasonable expiration time is chosen. If you want to create a + subkey that does not expire, use the keyword argument EXPIRES. + + SIGN, ENCRYPT, and AUTHENTICATE can be used to request the + capabilities of the new subkey. If you don't request any, an + encryption subkey is generated. + + If PASSPHRASE is None (the default), then the subkey will not + be protected with a passphrase. If PASSPHRASE is a string, it + will be used to protect the subkey. If PASSPHRASE is True, + the passphrase must be supplied using a passphrase callback or + out-of-band with a pinentry. + + Keyword arguments: + algorithm -- public key algorithm, see above (default: reasonable) + expires_in -- expiration time in seconds (default: reasonable) + expires -- whether or not the subkey should expire (default: True) + sign -- request the signing capability (see above) + encrypt -- request the encryption capability (see above) + authenticate -- request the authentication capability (see above) + passphrase -- protect the subkey with a passphrase (default: no passphrase) + + Returns: + -- an object describing the result of the subkey creation + + Raises: + GPGMEError -- as signaled by the underlying library + + """ + if util.is_a_string(passphrase): + old_pinentry_mode = self.pinentry_mode + old_passphrase_cb = getattr(self, '_passphrase_cb', None) + self.pinentry_mode = constants.PINENTRY_MODE_LOOPBACK + def passphrase_cb(hint, desc, prev_bad, hook=None): + return passphrase + self.set_passphrase_cb(passphrase_cb) + + try: + self.op_createsubkey(key, algorithm, + 0, # reserved + expires_in, + ((constants.create.SIGN if sign else 0) + | (constants.create.ENCR if encrypt else 0) + | (constants.create.AUTH if authenticate else 0) + | (constants.create.NOPASSWD + if passphrase == None else 0) + | (0 if expires else constants.create.NOEXPIRE))) + finally: + if util.is_a_string(passphrase): + self.pinentry_mode = old_pinentry_mode + if old_passphrase_cb: + self.set_passphrase_cb(*old_passphrase_cb[1:]) + + return self.op_genkey_result() + + def key_add_uid(self, key, uid): + """Add a UID + + Add the uid UID to the given KEY. Calling this function is + only valid for the OpenPGP protocol. + + Raises: + GPGMEError -- as signaled by the underlying library + + """ + self.op_adduid(key, uid, 0) + + def key_revoke_uid(self, key, uid): + """Revoke a UID + + Revoke the uid UID from the given KEY. Calling this function + is only valid for the OpenPGP protocol. + + Raises: + GPGMEError -- as signaled by the underlying library + + """ + self.op_revuid(key, uid, 0) + + def key_sign(self, key, uids=None, expires_in=False, local=False): + """Sign a key + + Sign a key with the current set of signing keys. Calling this + function is only valid for the OpenPGP protocol. + + If UIDS is None (the default), then all UIDs are signed. If + it is a string, then only the matching UID is signed. If it + is a list of strings, then all matching UIDs are signed. Note + that a case-sensitive exact string comparison is done. + + EXPIRES_IN specifies the expiration time of the signature in + seconds. If EXPIRES_IN is False, the signature does not + expire. + + Keyword arguments: + uids -- user ids to sign, see above (default: sign all) + expires_in -- validity period of the signature in seconds + (default: do not expire) + local -- create a local, non-exportable signature + (default: False) + + Raises: + GPGMEError -- as signaled by the underlying library + + """ + flags = 0 + if uids == None or util.is_a_string(uids): + pass#through unchanged + else: + flags |= constants.keysign.LFSEP + uids = "\n".join(uids) + + if not expires_in: + flags |= constants.keysign.NOEXPIRE + + if local: + flags |= constants.keysign.LOCAL + + self.op_keysign(key, uids, expires_in, flags) + + def key_tofu_policy(self, key, policy): + """Set a keys' TOFU policy + + Set the TOFU policy associated with KEY to POLICY. Calling + this function is only valid for the OpenPGP protocol. + + Raises: + GPGMEError -- as signaled by the underlying library + + """ + self.op_tofu_policy(key, policy) + + def assuan_transact(self, command, + data_cb=None, inquire_cb=None, status_cb=None): + """Issue a raw assuan command + + This function can be used to issue a raw assuan command to the + engine. + + If command is a string or bytes, it will be used as-is. If it + is an iterable of strings, it will be properly escaped and + joined into an well-formed assuan command. + + Keyword arguments: + data_cb -- a callback receiving data lines + inquire_cb -- a callback providing more information + status_cb -- a callback receiving status lines + + Returns: + result -- the result of command as GPGMEError + + Raises: + GPGMEError -- as signaled by the underlying library + + """ + + if util.is_a_string(command) or isinstance(command, bytes): + cmd = command + else: + cmd = " ".join(util.percent_escape(f) for f in command) + + errptr = gpgme.new_gpgme_error_t_p() + + err = gpgme.gpgme_op_assuan_transact_ext( + self.wrapped, + cmd, + (weakref.ref(self), data_cb) if data_cb else None, + (weakref.ref(self), inquire_cb) if inquire_cb else None, + (weakref.ref(self), status_cb) if status_cb else None, + errptr) + + if self._callback_excinfo: + gpgme.gpg_raise_callback_exception(self) + + errorcheck(err) + + status = gpgme.gpgme_error_t_p_value(errptr) + gpgme.delete_gpgme_error_t_p(errptr) + + return GPGMEError(status) if status != 0 else None + + def interact(self, key, func, sink=None, flags=0, fnc_value=None): + """Interact with the engine + + This method can be used to edit keys and cards interactively. + KEY is the key to edit, FUNC is called repeatedly with two + unicode arguments, 'keyword' and 'args'. See the GPGME manual + for details. + + Keyword arguments: + sink -- if given, additional output is written here + flags -- use constants.INTERACT_CARD to edit a card + + Raises: + GPGMEError -- as signaled by the underlying library + + """ + if key == None: + raise ValueError("First argument cannot be None") + + if sink == None: + sink = Data() + + if fnc_value: + opaquedata = (weakref.ref(self), func, fnc_value) + else: + opaquedata = (weakref.ref(self), func) + + result = gpgme.gpgme_op_interact(self.wrapped, key, flags, + opaquedata, sink) + if self._callback_excinfo: + gpgme.gpg_raise_callback_exception(self) + errorcheck(result) + + @property + def signers(self): + """Keys used for signing""" + return [self.signers_enum(i) for i in range(self.signers_count())] + @signers.setter + def signers(self, signers): + old = self.signers + self.signers_clear() + try: + for key in signers: + self.signers_add(key) + except: + self.signers = old + raise + + @property + def pinentry_mode(self): + """Pinentry mode""" + return self.get_pinentry_mode() + @pinentry_mode.setter + def pinentry_mode(self, value): + self.set_pinentry_mode(value) + + @property + def protocol(self): + """Protocol to use""" + return self.get_protocol() + @protocol.setter + def protocol(self, value): + errorcheck(gpgme.gpgme_engine_check_version(value)) + self.set_protocol(value) + + @property + def home_dir(self): + """Engine's home directory""" + return self.engine_info.home_dir + @home_dir.setter + def home_dir(self, value): + self.set_engine_info(self.protocol, home_dir=value) + + _ctype = 'gpgme_ctx_t' + _cprefix = 'gpgme_' + + def _errorcheck(self, name): + """This function should list all functions returning gpgme_error_t""" + # The list of functions is created using: + # + # $ grep '^gpgme_error_t ' obj/lang/python/python3.5-gpg/gpgme.h \ + # | grep -v _op_ | awk "/\(gpgme_ctx/ { printf (\"'%s',\\n\", \$2) } " + return ((name.startswith('gpgme_op_') + and not name.endswith('_result')) + or name in { + 'gpgme_new', + 'gpgme_set_ctx_flag', + 'gpgme_set_protocol', + 'gpgme_set_sub_protocol', + 'gpgme_set_keylist_mode', + 'gpgme_set_pinentry_mode', + 'gpgme_set_locale', + 'gpgme_ctx_set_engine_info', + 'gpgme_signers_add', + 'gpgme_sig_notation_add', + 'gpgme_set_sender', + 'gpgme_cancel', + 'gpgme_cancel_async', + 'gpgme_get_key', + }) + + _boolean_properties = {'armor', 'textmode', 'offline'} + + def __del__(self): + if not gpgme: + # At interpreter shutdown, gpgme is set to NONE. + return + + self._free_passcb() + self._free_progresscb() + self._free_statuscb() + if self.own and self.wrapped and gpgme.gpgme_release: + gpgme.gpgme_release(self.wrapped) + self.wrapped = None + + # Implement the context manager protocol. + def __enter__(self): + return self + def __exit__(self, type, value, tb): + self.__del__() + + def op_keylist_all(self, *args, **kwargs): + self.op_keylist_start(*args, **kwargs) + key = self.op_keylist_next() + while key: + yield key + key = self.op_keylist_next() + self.op_keylist_end() + + def op_keylist_next(self): + """Returns the next key in the list created + by a call to op_keylist_start(). The object returned + is of type Key.""" + ptr = gpgme.new_gpgme_key_t_p() + try: + errorcheck(gpgme.gpgme_op_keylist_next(self.wrapped, ptr)) + key = gpgme.gpgme_key_t_p_value(ptr) + except errors.GPGMEError as excp: + key = None + if excp.getcode() != errors.EOF: + raise excp + gpgme.delete_gpgme_key_t_p(ptr) + if key: + key.__del__ = lambda self: gpgme.gpgme_key_unref(self) + return key + + def get_key(self, fpr, secret=False): + """Get a key given a fingerprint + + Keyword arguments: + secret -- to request a secret key + + Returns: + -- the matching key + + Raises: + KeyError -- if the key was not found + GPGMEError -- as signaled by the underlying library + + """ + ptr = gpgme.new_gpgme_key_t_p() + + try: + errorcheck(gpgme.gpgme_get_key(self.wrapped, fpr, ptr, secret)) + except errors.GPGMEError as e: + if e.getcode() == errors.EOF: + raise errors.KeyNotFound(fpr) + raise e + + key = gpgme.gpgme_key_t_p_value(ptr) + gpgme.delete_gpgme_key_t_p(ptr) + assert key + key.__del__ = lambda self: gpgme.gpgme_key_unref(self) + return key + + def op_trustlist_all(self, *args, **kwargs): + self.op_trustlist_start(*args, **kwargs) + trust = self.op_trustlist_next() + while trust: + yield trust + trust = self.op_trustlist_next() + self.op_trustlist_end() + + def op_trustlist_next(self): + """Returns the next trust item in the list created + by a call to op_trustlist_start(). The object returned + is of type TrustItem.""" + ptr = gpgme.new_gpgme_trust_item_t_p() + try: + errorcheck(gpgme.gpgme_op_trustlist_next(self.wrapped, ptr)) + trust = gpgme.gpgme_trust_item_t_p_value(ptr) + except errors.GPGMEError as excp: + trust = None + if excp.getcode() != errors.EOF: + raise + gpgme.delete_gpgme_trust_item_t_p(ptr) + return trust + + def set_passphrase_cb(self, func, hook=None): + """Sets the passphrase callback to the function specified by func. + + When the system needs a passphrase, it will call func with three args: + hint, a string describing the key it needs the passphrase for; + desc, a string describing the passphrase it needs; + prev_bad, a boolean equal True if this is a call made after + unsuccessful previous attempt. + + If hook has a value other than None it will be passed into the func + as a forth argument. + + Please see the GPGME manual for more information. + """ + if func == None: + hookdata = None + else: + if hook == None: + hookdata = (weakref.ref(self), func) + else: + hookdata = (weakref.ref(self), func, hook) + gpgme.gpg_set_passphrase_cb(self, hookdata) + + def _free_passcb(self): + if gpgme.gpg_set_passphrase_cb: + self.set_passphrase_cb(None) + + def set_progress_cb(self, func, hook=None): + """Sets the progress meter callback to the function specified by FUNC. + If FUNC is None, the callback will be cleared. + + This function will be called to provide an interactive update + of the system's progress. The function will be called with + three arguments, type, total, and current. If HOOK is not + None, it will be supplied as fourth argument. + + Please see the GPGME manual for more information. + + """ + if func == None: + hookdata = None + else: + if hook == None: + hookdata = (weakref.ref(self), func) + else: + hookdata = (weakref.ref(self), func, hook) + gpgme.gpg_set_progress_cb(self, hookdata) + + def _free_progresscb(self): + if gpgme.gpg_set_progress_cb: + self.set_progress_cb(None) + + def set_status_cb(self, func, hook=None): + """Sets the status callback to the function specified by FUNC. If + FUNC is None, the callback will be cleared. + + The function will be called with two arguments, keyword and + args. If HOOK is not None, it will be supplied as third + argument. + + Please see the GPGME manual for more information. + + """ + if func == None: + hookdata = None + else: + if hook == None: + hookdata = (weakref.ref(self), func) + else: + hookdata = (weakref.ref(self), func, hook) + gpgme.gpg_set_status_cb(self, hookdata) + + def _free_statuscb(self): + if gpgme.gpg_set_status_cb: + self.set_status_cb(None) + + @property + def engine_info(self): + """Configuration of the engine currently in use""" + p = self.protocol + infos = [i for i in self.get_engine_info() if i.protocol == p] + assert len(infos) == 1 + return infos[0] + + def get_engine_info(self): + """Get engine configuration + + Returns information about all configured and installed + engines. + + Returns: + infos -- a list of engine infos + + """ + return gpgme.gpgme_ctx_get_engine_info(self.wrapped) + + def set_engine_info(self, proto, file_name=None, home_dir=None): + """Change engine configuration + + Changes the configuration of the crypto engine implementing + the protocol 'proto' for the context. + + Keyword arguments: + file_name -- engine program file name (unchanged if None) + home_dir -- configuration directory (unchanged if None) + + """ + self.ctx_set_engine_info(proto, file_name, home_dir) + + def wait(self, hang): + """Wait for asynchronous call to finish. Wait forever if hang is True. + Raises an exception on errors. + + Please read the GPGME manual for more information. + + """ + ptr = gpgme.new_gpgme_error_t_p() + gpgme.gpgme_wait(self.wrapped, ptr, hang) + status = gpgme.gpgme_error_t_p_value(ptr) + gpgme.delete_gpgme_error_t_p(ptr) + errorcheck(status) + + def op_edit(self, key, func, fnc_value, out): + """Start key editing using supplied callback function + + Note: This interface is deprecated and will be removed with + GPGME 1.8. Please use .interact instead. Furthermore, we + implement this using gpgme_op_interact, so callbacks will get + called with string keywords instead of numeric status + messages. Code that is using constants.STATUS_X or + constants.status.X will continue to work, whereas code using + magic numbers will break as a result. + + """ + warnings.warn("Call to deprecated method op_edit.", + category=DeprecationWarning) + return self.interact(key, func, sink=out, fnc_value=fnc_value) + + +class Data(GpgmeWrapper): + """Data buffer + + A lot of data has to be exchanged between the user and the crypto + engine, like plaintext messages, ciphertext, signatures and + information about the keys. The technical details about + exchanging the data information are completely abstracted by + GPGME. The user provides and receives the data via `gpgme_data_t' + objects, regardless of the communication protocol between GPGME + and the crypto engine in use. + + This Data class is the implementation of the GpgmeData objects. + + Please see the information about __init__ for instantiation. + + """ + + _ctype = 'gpgme_data_t' + _cprefix = 'gpgme_data_' + + def _errorcheck(self, name): + """This function should list all functions returning gpgme_error_t""" + # This list is compiled using + # + # $ grep -v '^gpgme_error_t ' obj/lang/python/python3.5-gpg/gpgme.h \ + # | awk "/\(gpgme_data_t/ { printf (\"'%s',\\n\", \$2) } " | sed "s/'\\*/'/" + return name not in { + 'gpgme_data_read', + 'gpgme_data_write', + 'gpgme_data_seek', + 'gpgme_data_release', + 'gpgme_data_release_and_get_mem', + 'gpgme_data_get_encoding', + 'gpgme_data_get_file_name', + 'gpgme_data_identify', + } + + def __init__(self, string=None, file=None, offset=None, + length=None, cbs=None, copy=True): + """Initialize a new gpgme_data_t object. + + If no args are specified, make it an empty object. + + If string alone is specified, initialize it with the data + contained there. + + If file, offset, and length are all specified, file must + be either a filename or a file-like object, and the object + will be initialized by reading the specified chunk from the file. + + If cbs is specified, it MUST be a tuple of the form: + + (read_cb, write_cb, seek_cb, release_cb[, hook]) + + where the first four items are functions implementing reading, + writing, seeking the data, and releasing any resources once + the data object is deallocated. The functions must match the + following prototypes: + + def read(amount, hook=None): + return + + def write(data, hook=None): + return + + def seek(offset, whence, hook=None): + return + + def release(hook=None): + + + The functions may be bound methods. In that case, you can + simply use the 'self' reference instead of using a hook. + + If file is specified without any other arguments, then + it must be a filename, and the object will be initialized from + that file. + + """ + super(Data, self).__init__(None) + self.data_cbs = None + + if cbs != None: + self.new_from_cbs(*cbs) + elif string != None: + self.new_from_mem(string, copy) + elif file != None and offset != None and length != None: + self.new_from_filepart(file, offset, length) + elif file != None: + if util.is_a_string(file): + self.new_from_file(file, copy) + else: + self.new_from_fd(file) + else: + self.new() + + def __del__(self): + if not gpgme: + # At interpreter shutdown, gpgme is set to NONE. + return + + if self.wrapped != None and gpgme.gpgme_data_release: + gpgme.gpgme_data_release(self.wrapped) + if self._callback_excinfo: + gpgme.gpg_raise_callback_exception(self) + self.wrapped = None + self._free_datacbs() + + # Implement the context manager protocol. + def __enter__(self): + return self + def __exit__(self, type, value, tb): + self.__del__() + + def _free_datacbs(self): + self._data_cbs = None + + def new(self): + tmp = gpgme.new_gpgme_data_t_p() + errorcheck(gpgme.gpgme_data_new(tmp)) + self.wrapped = gpgme.gpgme_data_t_p_value(tmp) + gpgme.delete_gpgme_data_t_p(tmp) + + def new_from_mem(self, string, copy=True): + tmp = gpgme.new_gpgme_data_t_p() + errorcheck(gpgme.gpgme_data_new_from_mem(tmp,string,len(string),copy)) + self.wrapped = gpgme.gpgme_data_t_p_value(tmp) + gpgme.delete_gpgme_data_t_p(tmp) + + def new_from_file(self, filename, copy=True): + tmp = gpgme.new_gpgme_data_t_p() + try: + errorcheck(gpgme.gpgme_data_new_from_file(tmp, filename, copy)) + except errors.GPGMEError as e: + if e.getcode() == errors.INV_VALUE and not copy: + raise ValueError("delayed reads are not yet supported") + else: + raise e + self.wrapped = gpgme.gpgme_data_t_p_value(tmp) + gpgme.delete_gpgme_data_t_p(tmp) + + def new_from_cbs(self, read_cb, write_cb, seek_cb, release_cb, hook=None): + tmp = gpgme.new_gpgme_data_t_p() + if hook != None: + hookdata = (weakref.ref(self), + read_cb, write_cb, seek_cb, release_cb, hook) + else: + hookdata = (weakref.ref(self), + read_cb, write_cb, seek_cb, release_cb) + gpgme.gpg_data_new_from_cbs(self, hookdata, tmp) + self.wrapped = gpgme.gpgme_data_t_p_value(tmp) + gpgme.delete_gpgme_data_t_p(tmp) + + def new_from_filepart(self, file, offset, length): + """This wraps the GPGME gpgme_data_new_from_filepart() function. + The argument "file" may be: + + * a string specifying a file name, or + * a file-like object supporting the fileno() and the mode attribute. + + """ + + tmp = gpgme.new_gpgme_data_t_p() + filename = None + fp = None + + if util.is_a_string(file): + filename = file + else: + fp = gpgme.fdopen(file.fileno(), file.mode) + if fp == None: + raise ValueError("Failed to open file from %s arg %s" % \ + (str(type(file)), str(file))) + + errorcheck(gpgme.gpgme_data_new_from_filepart(tmp, filename, fp, + offset, length)) + self.wrapped = gpgme.gpgme_data_t_p_value(tmp) + gpgme.delete_gpgme_data_t_p(tmp) + + def new_from_fd(self, file): + """This wraps the GPGME gpgme_data_new_from_fd() function. The + argument "file" must be a file-like object, supporting the + fileno() method. + + """ + tmp = gpgme.new_gpgme_data_t_p() + errorcheck(gpgme.gpgme_data_new_from_fd(tmp, file.fileno())) + self.wrapped = gpgme.gpgme_data_t_p_value(tmp) + gpgme.delete_gpgme_data_t_p(tmp) + + def new_from_stream(self, file): + """This wrap around gpgme_data_new_from_stream is an alias for + new_from_fd() method since in python there's not difference + between file stream and file descriptor""" + self.new_from_fd(file) + + def write(self, buffer): + """Write buffer given as string or bytes. + + If a string is given, it is implicitly encoded using UTF-8.""" + written = gpgme.gpgme_data_write(self.wrapped, buffer) + if written < 0: + if self._callback_excinfo: + gpgme.gpg_raise_callback_exception(self) + else: + raise GPGMEError.fromSyserror() + return written + + def read(self, size = -1): + """Read at most size bytes, returned as bytes. + + If the size argument is negative or omitted, read until EOF is reached. + + Returns the data read, or the empty string if there was no data + to read before EOF was reached.""" + + if size == 0: + return '' + + if size > 0: + try: + result = gpgme.gpgme_data_read(self.wrapped, size) + except: + if self._callback_excinfo: + gpgme.gpg_raise_callback_exception(self) + else: + raise + return result + else: + chunks = [] + while True: + try: + result = gpgme.gpgme_data_read(self.wrapped, 4096) + except: + if self._callback_excinfo: + gpgme.gpg_raise_callback_exception(self) + else: + raise + if len(result) == 0: + break + chunks.append(result) + return b''.join(chunks) + +def pubkey_algo_string(subkey): + """Return short algorithm string + + Return a public key algorithm string (e.g. "rsa2048") for a given + SUBKEY. + + Returns: + algo - a string + + """ + return gpgme.gpgme_pubkey_algo_string(subkey) + +def pubkey_algo_name(algo): + """Return name of public key algorithm + + Return the name of the public key algorithm for a given numeric + algorithm id ALGO (cf. RFC4880). + + Returns: + algo - a string + + """ + return gpgme.gpgme_pubkey_algo_name(algo) + +def hash_algo_name(algo): + """Return name of hash algorithm + + Return the name of the hash algorithm for a given numeric + algorithm id ALGO (cf. RFC4880). + + Returns: + algo - a string + + """ + return gpgme.gpgme_hash_algo_name(algo) + +def get_protocol_name(proto): + """Get protocol description + + Get the string describing protocol PROTO. + + Returns: + proto - a string + + """ + return gpgme.gpgme_get_protocol_name(proto) + +def addrspec_from_uid(uid): + """Return the address spec + + Return the addr-spec (cf. RFC2822 section 4.3) from a user id UID. + + Returns: + addr_spec - a string + + """ + return gpgme.gpgme_addrspec_from_uid(uid) + +def check_version(version=None): + return gpgme.gpgme_check_version(version) + +# check_version also makes sure that several subsystems are properly +# initialized, and it must be run at least once before invoking any +# other function. We do it here so that the user does not have to do +# it unless she really wants to check for a certain version. +check_version() + +def engine_check_version (proto): + try: + errorcheck(gpgme.gpgme_engine_check_version(proto)) + return True + except errors.GPGMEError: + return False + +def get_engine_info(): + ptr = gpgme.new_gpgme_engine_info_t_p() + try: + errorcheck(gpgme.gpgme_get_engine_info(ptr)) + info = gpgme.gpgme_engine_info_t_p_value(ptr) + except errors.GPGMEError: + info = None + gpgme.delete_gpgme_engine_info_t_p(ptr) + return info + +def set_engine_info(proto, file_name, home_dir=None): + """Changes the default configuration of the crypto engine implementing + the protocol 'proto'. 'file_name' is the file name of + the executable program implementing this protocol. 'home_dir' is the + directory name of the configuration directory (engine's default is + used if omitted).""" + errorcheck(gpgme.gpgme_set_engine_info(proto, file_name, home_dir)) + +def set_locale(category, value): + """Sets the default locale used by contexts""" + errorcheck(gpgme.gpgme_set_locale(None, category, value)) + +def wait(hang): + """Wait for asynchronous call on any Context to finish. + Wait forever if hang is True. + + For finished anynch calls it returns a tuple (status, context): + status - status return by asnynchronous call. + context - context which caused this call to return. + + Please read the GPGME manual of more information.""" + ptr = gpgme.new_gpgme_error_t_p() + context = gpgme.gpgme_wait(None, ptr, hang) + status = gpgme.gpgme_error_t_p_value(ptr) + gpgme.delete_gpgme_error_t_p(ptr) + if context == None: + errorcheck(status) + else: + context = Context(context) + return (status, context) diff --git a/lang/python/src/errors.py b/lang/python/src/errors.py new file mode 100644 index 00000000..1ce139e8 --- /dev/null +++ b/lang/python/src/errors.py @@ -0,0 +1,128 @@ +# Copyright (C) 2004 Igor Belyi +# Copyright (C) 2002 John Goerzen +# +# This library is free software; you can redistribute it and/or +# modify it under the terms of the GNU Lesser General Public +# License as published by the Free Software Foundation; either +# version 2.1 of the License, or (at your option) any later version. +# +# This library is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +# Lesser General Public License for more details. +# +# You should have received a copy of the GNU Lesser General Public +# License along with this library; if not, write to the Free Software +# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + +from __future__ import absolute_import, print_function, unicode_literals +del absolute_import, print_function, unicode_literals + +from . import gpgme +from . import util + +# To appease static analysis tools, we define some constants here. +# They are overwritten with the proper values by process_constants. +NO_ERROR = None +EOF = None + +util.process_constants('GPG_ERR_', globals()) +del util + +class GpgError(Exception): + pass + +class GPGMEError(GpgError): + def __init__(self, error = None, message = None): + self.error = error + self.message = message + + @classmethod + def fromSyserror(cls): + return cls(gpgme.gpgme_err_code_from_syserror()) + + def getstring(self): + message = "%s: %s" % (gpgme.gpgme_strsource(self.error), + gpgme.gpgme_strerror(self.error)) + if self.message != None: + message = "%s: %s" % (self.message, message) + return message + + def getcode(self): + return gpgme.gpgme_err_code(self.error) + + def getsource(self): + return gpgme.gpgme_err_source(self.error) + + def __str__(self): + return self.getstring() + +def errorcheck(retval, extradata = None): + if retval: + raise GPGMEError(retval, extradata) + +class KeyNotFound(GPGMEError, KeyError): + """Raised if a key was not found + + GPGME indicates this condition with EOF, which is not very + idiomatic. We raise this error that is both a GPGMEError + indicating EOF, and a KeyError. + + """ + def __init__(self, keystr): + self.keystr = keystr + GPGMEError.__init__(self, EOF) + def __str__(self): + return self.keystr + +# These errors are raised in the idiomatic interface code. + +class EncryptionError(GpgError): + pass + +class InvalidRecipients(EncryptionError): + def __init__(self, recipients): + self.recipients = recipients + def __str__(self): + return ", ".join("{}: {}".format(r.fpr, + gpgme.gpgme_strerror(r.reason)) + for r in self.recipients) + +class DeryptionError(GpgError): + pass + +class UnsupportedAlgorithm(DeryptionError): + def __init__(self, algorithm): + self.algorithm = algorithm + def __str__(self): + return self.algorithm + +class SigningError(GpgError): + pass + +class InvalidSigners(SigningError): + def __init__(self, signers): + self.signers = signers + def __str__(self): + return ", ".join("{}: {}".format(s.fpr, + gpgme.gpgme_strerror(s.reason)) + for s in self.signers) + +class VerificationError(GpgError): + pass + +class BadSignatures(VerificationError): + def __init__(self, result): + self.result = result + def __str__(self): + return ", ".join("{}: {}".format(s.fpr, + gpgme.gpgme_strerror(s.status)) + for s in self.result.signatures + if s.status != NO_ERROR) + +class MissingSignatures(VerificationError): + def __init__(self, result, missing): + self.result = result + self.missing = missing + def __str__(self): + return ", ".join(k.subkeys[0].fpr for k in self.missing) diff --git a/lang/python/src/results.py b/lang/python/src/results.py new file mode 100644 index 00000000..46ebeec6 --- /dev/null +++ b/lang/python/src/results.py @@ -0,0 +1,118 @@ +# Robust result objects +# +# Copyright (C) 2016 g10 Code GmbH +# +# This file is part of GPGME. +# +# GPGME is free software; you can redistribute it and/or modify it +# under the terms of the GNU Lesser General Public License as +# published by the Free Software Foundation; either version 2.1 of the +# License, or (at your option) any later version. +# +# GPGME is distributed in the hope that it will be useful, but WITHOUT +# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY +# or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General +# Public License for more details. +# +# You should have received a copy of the GNU Lesser General Public +# License along with this program; if not, see . + +from __future__ import absolute_import, print_function, unicode_literals +del absolute_import, print_function, unicode_literals + +"""Robust result objects + +Results returned by the underlying library are fragile, i.e. they are +only valid until the next operation is performed in the context. + +We cannot arbitrarily constrain the lifetime of Python objects, we +therefore create deep copies of the results. + +""" + +class Result(object): + """Result object + + Describes the result of an operation. + + """ + + """Convert to types""" + _type = {} + + """Map functions over list attributes""" + _map = {} + + """Automatically copy unless blacklisted""" + _blacklist = { + 'acquire', 'append', 'disown', 'next', 'own', 'this', 'thisown', + } + def __init__(self, fragile): + for key, func in self._type.items(): + if hasattr(fragile, key): + setattr(self, key, func(getattr(fragile, key))) + + for key, func in self._map.items(): + if hasattr(fragile, key): + setattr(self, key, list(map(func, getattr(fragile, key)))) + + for key in dir(fragile): + if key.startswith('_') or key in self._blacklist: + continue + if hasattr(self, key): + continue + + setattr(self, key, getattr(fragile, key)) + + def __repr__(self): + return '{}({})'.format( + self.__class__.__name__, + ', '.join('{}={!r}'.format(k, getattr(self, k)) + for k in dir(self) if not k.startswith('_'))) + +class InvalidKey(Result): + pass + +class EncryptResult(Result): + _map = dict(invalid_recipients=InvalidKey) + +class Recipient(Result): + pass + +class DecryptResult(Result): + _type = dict(wrong_key_usage=bool) + _map = dict(recipients=Recipient) + +class NewSignature(Result): + pass + +class SignResult(Result): + _map = dict(invalid_signers=InvalidKey, signatures=NewSignature) + +class Notation(Result): + pass + +class Signature(Result): + _type = dict(wrong_key_usage=bool, chain_model=bool) + _map = dict(notations=Notation) + +class VerifyResult(Result): + _map = dict(signatures=Signature) + +class ImportStatus(Result): + pass + +class ImportResult(Result): + _map = dict(imports=ImportStatus) + +class GenkeyResult(Result): + _type = dict(primary=bool, sub=bool) + +class KeylistResult(Result): + _type = dict(truncated=bool) + +class VFSMountResult(Result): + pass + +class EngineInfo(Result): + pass diff --git a/lang/python/src/util.py b/lang/python/src/util.py new file mode 100644 index 00000000..e4fca4c1 --- /dev/null +++ b/lang/python/src/util.py @@ -0,0 +1,53 @@ +# Copyright (C) 2016 g10 Code GmbH +# Copyright (C) 2004,2008 Igor Belyi +# Copyright (C) 2002 John Goerzen +# +# This library is free software; you can redistribute it and/or +# modify it under the terms of the GNU Lesser General Public +# License as published by the Free Software Foundation; either +# version 2.1 of the License, or (at your option) any later version. +# +# This library is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +# Lesser General Public License for more details. +# +# You should have received a copy of the GNU Lesser General Public +# License along with this library; if not, write to the Free Software +# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + +from __future__ import absolute_import, print_function, unicode_literals +del absolute_import, print_function, unicode_literals + +import sys + +def process_constants(prefix, scope): + """Called by the constant modules to load up the constants from the C + library starting with PREFIX. Matching constants will be inserted + into SCOPE with PREFIX stripped from the names. Returns the names + of inserted constants. + + """ + from . import gpgme + index = len(prefix) + constants = {identifier[index:]: getattr(gpgme, identifier) + for identifier in dir(gpgme) + if identifier.startswith(prefix)} + scope.update(constants) + return list(constants.keys()) + +def percent_escape(s): + return ''.join( + '%{0:2x}'.format(ord(c)) + if c == '+' or c == '"' or c == '%' or ord(c) <= 0x20 else c + for c in s) + +# Python2/3 compatibility +if sys.version_info[0] == 3: + # Python3 + def is_a_string(x): + return isinstance(x, str) +else: + # Python2 + def is_a_string(x): + return isinstance(x, basestring) diff --git a/lang/python/version.py.in b/lang/python/version.py.in new file mode 100644 index 00000000..1a1baf08 --- /dev/null +++ b/lang/python/version.py.in @@ -0,0 +1,68 @@ +# Copyright (C) 2016 g10 Code GmbH +# Copyright (C) 2015 Ben McGinnes +# Copyright (C) 2004 Igor Belyi +# +# This library is free software; you can redistribute it and/or +# modify it under the terms of the GNU Lesser General Public +# License as published by the Free Software Foundation; either +# version 2.1 of the License, or (at your option) any later version. +# +# This library is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +# Lesser General Public License for more details. +# +# You should have received a copy of the GNU Lesser General Public +# License along with this library; if not, write to the Free Software +# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + +from __future__ import absolute_import, print_function +del absolute_import, print_function + +from . import gpgme + +productname = 'gpg' +versionstr = "@VERSION@" +gpgme_versionstr = gpgme.GPGME_VERSION +in_tree_build = bool(gpgme.cvar.gpg_in_tree_build) + +versionlist = versionstr.split(".") +major = versionlist[0] +minor = versionlist[1] +patch = versionlist[2] + +copyright = """\ +Copyright (C) 2016 g10 Code GmbH +Copyright (C) 2015 Ben McGinnes +Copyright (C) 2014-2015 Martin Albrecht +Copyright (C) 2004-2008 Igor Belyi +Copyright (C) 2002 John Goerzen""" + +author = "The GnuPG hackers" +author_email = "gnupg-devel@gnupg.org" + +description = "Python support for GPGME GnuPG cryptography library" +homepage = "https://gnupg.org" + +license = """Copyright (C) 2016 g10 Code GmbH +Copyright (C) 2015 Ben McGinnes +Copyright (C) 2014, 2015 Martin Albrecht +Copyright (C) 2004, 2008 Igor Belyi +Copyright (C) 2002 John Goerzen + +This library is free software; you can redistribute it and/or +modify it under the terms of the GNU Lesser General Public +License as published by the Free Software Foundation; either +version 2.1 of the License, or (at your option) any later version. + +This library is distributed in the hope that it will be useful, +but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +Lesser General Public License for more details. + +You should have received a copy of the GNU Lesser General Public +License along with this library; if not, write to the Free Software +Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA""" + +# Interface hygiene. Keep this at the end. +del gpgme -- cgit v1.2.3