Blame lang/python/src/core.py

Packit Service 30b792
# -*- coding: utf-8 -*-
Packit Service 30b792
Packit Service 30b792
from __future__ import absolute_import, print_function, unicode_literals
Packit Service 30b792
Packit Service 30b792
import re
Packit Service 30b792
import os
Packit Service 30b792
import warnings
Packit Service 30b792
import weakref
Packit Service 30b792
Packit Service 30b792
from . import gpgme
Packit Service 30b792
from .errors import errorcheck, GPGMEError
Packit Service 30b792
from . import constants
Packit Service 30b792
from . import errors
Packit Service 30b792
from . import util
Packit Service 30b792
Packit Service 30b792
del absolute_import, print_function, unicode_literals
Packit Service 30b792
Packit Service 30b792
# Copyright (C) 2016-2018 g10 Code GmbH
Packit Service 30b792
# Copyright (C) 2004, 2008 Igor Belyi <belyi@users.sourceforge.net>
Packit d7e8d0
# Copyright (C) 2002 John Goerzen <jgoerzen@complete.org>
Packit d7e8d0
#
Packit d7e8d0
#    This library is free software; you can redistribute it and/or
Packit d7e8d0
#    modify it under the terms of the GNU Lesser General Public
Packit d7e8d0
#    License as published by the Free Software Foundation; either
Packit d7e8d0
#    version 2.1 of the License, or (at your option) any later version.
Packit d7e8d0
#
Packit d7e8d0
#    This library is distributed in the hope that it will be useful,
Packit d7e8d0
#    but WITHOUT ANY WARRANTY; without even the implied warranty of
Packit d7e8d0
#    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
Packit d7e8d0
#    Lesser General Public License for more details.
Packit d7e8d0
#
Packit d7e8d0
#    You should have received a copy of the GNU Lesser General Public
Packit d7e8d0
#    License along with this library; if not, write to the Free Software
Packit d7e8d0
#    Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307  USA
Packit d7e8d0
"""Core functionality
Packit d7e8d0
Packit d7e8d0
Core functionality of GPGME wrapped in a object-oriented fashion.
Packit d7e8d0
Provides the 'Context' class for performing cryptographic operations,
Packit d7e8d0
and the 'Data' class describing buffers of data.
Packit d7e8d0
Packit d7e8d0
"""
Packit d7e8d0
Packit d7e8d0
Packit d7e8d0
class GpgmeWrapper(object):
Packit d7e8d0
    """Base wrapper class
Packit d7e8d0
Packit d7e8d0
    Not to be instantiated directly.
Packit d7e8d0
Packit d7e8d0
    """
Packit d7e8d0
Packit d7e8d0
    def __init__(self, wrapped):
Packit d7e8d0
        self._callback_excinfo = None
Packit d7e8d0
        self.wrapped = wrapped
Packit d7e8d0
Packit d7e8d0
    def __repr__(self):
Packit Service 30b792
        return '<{}/{!r}>'.format(
Packit Service 30b792
            super(GpgmeWrapper, self).__repr__(), self.wrapped)
Packit d7e8d0
Packit d7e8d0
    def __str__(self):
Packit d7e8d0
        acc = ['{}.{}'.format(__name__, self.__class__.__name__)]
Packit d7e8d0
        flags = [f for f in self._boolean_properties if getattr(self, f)]
Packit d7e8d0
        if flags:
Packit d7e8d0
            acc.append('({})'.format(' '.join(flags)))
Packit d7e8d0
Packit d7e8d0
        return '<{}>'.format(' '.join(acc))
Packit d7e8d0
Packit d7e8d0
    def __hash__(self):
Packit d7e8d0
        return hash(repr(self.wrapped))
Packit d7e8d0
Packit d7e8d0
    def __eq__(self, other):
Packit Service 30b792
        if other is None:
Packit d7e8d0
            return False
Packit d7e8d0
        else:
Packit d7e8d0
            return repr(self.wrapped) == repr(other.wrapped)
Packit d7e8d0
Packit d7e8d0
    @property
Packit d7e8d0
    def _ctype(self):
Packit d7e8d0
        """The name of the c type wrapped by this class
Packit d7e8d0
Packit d7e8d0
        Must be set by child classes.
Packit d7e8d0
Packit d7e8d0
        """
Packit d7e8d0
        raise NotImplementedError()
Packit d7e8d0
Packit d7e8d0
    @property
Packit d7e8d0
    def _cprefix(self):
Packit d7e8d0
        """The common prefix of c functions wrapped by this class
Packit d7e8d0
Packit d7e8d0
        Must be set by child classes.
Packit d7e8d0
Packit d7e8d0
        """
Packit d7e8d0
        raise NotImplementedError()
Packit d7e8d0
Packit d7e8d0
    def _errorcheck(self, name):
Packit d7e8d0
        """Must be implemented by child classes.
Packit d7e8d0
Packit d7e8d0
        This function must return a trueish value for all c functions
Packit d7e8d0
        returning gpgme_error_t."""
Packit d7e8d0
        raise NotImplementedError()
Packit d7e8d0
Packit d7e8d0
    """The set of all boolean properties"""
Packit d7e8d0
    _boolean_properties = set()
Packit d7e8d0
Packit d7e8d0
    def __wrap_boolean_property(self, key, do_set=False, value=None):
Packit Service 30b792
        get_func = getattr(gpgme, "{}get_{}".format(self._cprefix, key))
Packit Service 30b792
        set_func = getattr(gpgme, "{}set_{}".format(self._cprefix, key))
Packit Service 30b792
Packit d7e8d0
        def get(slf):
Packit d7e8d0
            return bool(get_func(slf.wrapped))
Packit Service 30b792
Packit d7e8d0
        def set_(slf, value):
Packit d7e8d0
            set_func(slf.wrapped, bool(value))
Packit d7e8d0
Packit d7e8d0
        p = property(get, set_, doc="{} flag".format(key))
Packit d7e8d0
        setattr(self.__class__, key, p)
Packit d7e8d0
Packit d7e8d0
        if do_set:
Packit d7e8d0
            set_(self, bool(value))
Packit d7e8d0
        else:
Packit d7e8d0
            return get(self)
Packit d7e8d0
Packit d7e8d0
    _munge_docstring = re.compile(r'gpgme_([^(]*)\(([^,]*), (.*\) -> .*)')
Packit Service 30b792
Packit d7e8d0
    def __getattr__(self, key):
Packit d7e8d0
        """On-the-fly generation of wrapper methods and properties"""
Packit Service 30b792
        if key[0] == '_' or self._cprefix is None:
Packit d7e8d0
            return None
Packit d7e8d0
Packit d7e8d0
        if key in self._boolean_properties:
Packit d7e8d0
            return self.__wrap_boolean_property(key)
Packit d7e8d0
Packit d7e8d0
        name = self._cprefix + key
Packit d7e8d0
        func = getattr(gpgme, name)
Packit d7e8d0
Packit d7e8d0
        if self._errorcheck(name):
Packit Service 30b792
Packit d7e8d0
            def _funcwrap(slf, *args):
Packit d7e8d0
                result = func(slf.wrapped, *args)
Packit d7e8d0
                if slf._callback_excinfo:
Packit d7e8d0
                    gpgme.gpg_raise_callback_exception(slf)
Packit d7e8d0
                return errorcheck(result, name)
Packit d7e8d0
        else:
Packit Service 30b792
Packit d7e8d0
            def _funcwrap(slf, *args):
Packit d7e8d0
                result = func(slf.wrapped, *args)
Packit d7e8d0
                if slf._callback_excinfo:
Packit d7e8d0
                    gpgme.gpg_raise_callback_exception(slf)
Packit d7e8d0
                return result
Packit d7e8d0
Packit d7e8d0
        doc = self._munge_docstring.sub(r'\2.\1(\3', getattr(func, "__doc__"))
Packit d7e8d0
        _funcwrap.__doc__ = doc
Packit d7e8d0
Packit d7e8d0
        # Monkey-patch the class.
Packit d7e8d0
        setattr(self.__class__, key, _funcwrap)
Packit d7e8d0
Packit d7e8d0
        # Bind the method to 'self'.
Packit d7e8d0
        def wrapper(*args):
Packit d7e8d0
            return _funcwrap(self, *args)
Packit Service 30b792
Packit d7e8d0
        wrapper.__doc__ = doc
Packit d7e8d0
Packit d7e8d0
        return wrapper
Packit d7e8d0
Packit d7e8d0
    def __setattr__(self, key, value):
Packit d7e8d0
        """On-the-fly generation of properties"""
Packit d7e8d0
        if key in self._boolean_properties:
Packit d7e8d0
            self.__wrap_boolean_property(key, True, value)
Packit d7e8d0
        else:
Packit d7e8d0
            super(GpgmeWrapper, self).__setattr__(key, value)
Packit d7e8d0
Packit Service 30b792
Packit d7e8d0
class Context(GpgmeWrapper):
Packit d7e8d0
    """Context for cryptographic operations
Packit d7e8d0
Packit d7e8d0
    All cryptographic operations in GPGME are performed within a
Packit d7e8d0
    context, which contains the internal state of the operation as
Packit d7e8d0
    well as configuration parameters.  By using several contexts you
Packit d7e8d0
    can run several cryptographic operations in parallel, with
Packit d7e8d0
    different configuration.
Packit d7e8d0
Packit d7e8d0
    Access to a context must be synchronized.
Packit d7e8d0
Packit d7e8d0
    """
Packit d7e8d0
Packit Service 30b792
    def __init__(self,
Packit Service 30b792
                 armor=False,
Packit Service 30b792
                 textmode=False,
Packit Service 30b792
                 offline=False,
Packit Service 30b792
                 signers=[],
Packit Service 30b792
                 pinentry_mode=constants.PINENTRY_MODE_DEFAULT,
Packit d7e8d0
                 protocol=constants.PROTOCOL_OpenPGP,
Packit Service 30b792
                 wrapped=None,
Packit Service 30b792
                 home_dir=None):
Packit d7e8d0
        """Construct a context object
Packit d7e8d0
Packit d7e8d0
        Keyword arguments:
Packit d7e8d0
        armor		-- enable ASCII armoring (default False)
Packit d7e8d0
        textmode	-- enable canonical text mode (default False)
Packit d7e8d0
        offline		-- do not contact external key sources (default False)
Packit d7e8d0
        signers		-- list of keys used for signing (default [])
Packit d7e8d0
        pinentry_mode	-- pinentry mode (default PINENTRY_MODE_DEFAULT)
Packit d7e8d0
        protocol	-- protocol to use (default PROTOCOL_OpenPGP)
Packit d7e8d0
        home_dir        -- state directory (default is the engine default)
Packit d7e8d0
Packit d7e8d0
        """
Packit d7e8d0
        if wrapped:
Packit d7e8d0
            self.own = False
Packit d7e8d0
        else:
Packit d7e8d0
            tmp = gpgme.new_gpgme_ctx_t_p()
Packit d7e8d0
            errorcheck(gpgme.gpgme_new(tmp))
Packit d7e8d0
            wrapped = gpgme.gpgme_ctx_t_p_value(tmp)
Packit d7e8d0
            gpgme.delete_gpgme_ctx_t_p(tmp)
Packit d7e8d0
            self.own = True
Packit d7e8d0
        super(Context, self).__init__(wrapped)
Packit d7e8d0
        self.armor = armor
Packit d7e8d0
        self.textmode = textmode
Packit d7e8d0
        self.offline = offline
Packit d7e8d0
        self.signers = signers
Packit d7e8d0
        self.pinentry_mode = pinentry_mode
Packit d7e8d0
        self.protocol = protocol
Packit d7e8d0
        self.home_dir = home_dir
Packit d7e8d0
Packit d7e8d0
    def __read__(self, sink, data):
Packit d7e8d0
        """Read helper
Packit d7e8d0
Packit d7e8d0
        Helper function to retrieve the results of an operation, or
Packit d7e8d0
        None if SINK is given.
Packit d7e8d0
        """
Packit Service 30b792
        if sink or data is None:
Packit d7e8d0
            return None
Packit d7e8d0
        data.seek(0, os.SEEK_SET)
Packit d7e8d0
        return data.read()
Packit d7e8d0
Packit d7e8d0
    def __repr__(self):
Packit Service 30b792
        return ("Context(armor={0.armor}, "
Packit Service 30b792
                "textmode={0.textmode}, offline={0.offline}, "
Packit Service 30b792
                "signers={0.signers}, pinentry_mode={0.pinentry_mode}, "
Packit Service 30b792
                "protocol={0.protocol}, home_dir={0.home_dir}"
Packit Service 30b792
                ")").format(self)
Packit Service 30b792
Packit Service 30b792
    def encrypt(self,
Packit Service 30b792
                plaintext,
Packit Service 30b792
                recipients=[],
Packit Service 30b792
                sign=True,
Packit Service 30b792
                sink=None,
Packit Service 30b792
                passphrase=None,
Packit Service 30b792
                always_trust=False,
Packit Service 30b792
                add_encrypt_to=False,
Packit Service 30b792
                prepare=False,
Packit Service 30b792
                expect_sign=False,
Packit Service 30b792
                compress=True):
Packit d7e8d0
        """Encrypt data
Packit d7e8d0
Packit d7e8d0
        Encrypt the given plaintext for the given recipients.  If the
Packit d7e8d0
        list of recipients is empty, the data is encrypted
Packit d7e8d0
        symmetrically with a passphrase.
Packit d7e8d0
Packit d7e8d0
        The passphrase can be given as parameter, using a callback
Packit d7e8d0
        registered at the context, or out-of-band via pinentry.
Packit d7e8d0
Packit d7e8d0
        Keyword arguments:
Packit d7e8d0
        recipients	-- list of keys to encrypt to
Packit d7e8d0
        sign		-- sign plaintext (default True)
Packit d7e8d0
        sink		-- write result to sink instead of returning it
Packit d7e8d0
        passphrase	-- for symmetric encryption
Packit d7e8d0
        always_trust	-- always trust the keys (default False)
Packit d7e8d0
        add_encrypt_to	-- encrypt to configured additional keys (default False)
Packit d7e8d0
        prepare		-- (ui) prepare for encryption (default False)
Packit d7e8d0
        expect_sign	-- (ui) prepare for signing (default False)
Packit d7e8d0
        compress	-- compress plaintext (default True)
Packit d7e8d0
Packit d7e8d0
        Returns:
Packit d7e8d0
        ciphertext	-- the encrypted data (or None if sink is given)
Packit d7e8d0
        result		-- additional information about the encryption
Packit d7e8d0
        sign_result	-- additional information about the signature(s)
Packit d7e8d0
Packit d7e8d0
        Raises:
Packit d7e8d0
        InvalidRecipients -- if encryption using a particular key failed
Packit d7e8d0
        InvalidSigners	-- if signing using a particular key failed
Packit d7e8d0
        GPGMEError	-- as signaled by the underlying library
Packit d7e8d0
Packit d7e8d0
        """
Packit d7e8d0
        ciphertext = sink if sink else Data()
Packit d7e8d0
        flags = 0
Packit d7e8d0
        flags |= always_trust * constants.ENCRYPT_ALWAYS_TRUST
Packit d7e8d0
        flags |= (not add_encrypt_to) * constants.ENCRYPT_NO_ENCRYPT_TO
Packit d7e8d0
        flags |= prepare * constants.ENCRYPT_PREPARE
Packit d7e8d0
        flags |= expect_sign * constants.ENCRYPT_EXPECT_SIGN
Packit d7e8d0
        flags |= (not compress) * constants.ENCRYPT_NO_COMPRESS
Packit d7e8d0
Packit Service 30b792
        if passphrase is not None:
Packit d7e8d0
            old_pinentry_mode = self.pinentry_mode
Packit d7e8d0
            old_passphrase_cb = getattr(self, '_passphrase_cb', None)
Packit d7e8d0
            self.pinentry_mode = constants.PINENTRY_MODE_LOOPBACK
Packit Service 30b792
Packit d7e8d0
            def passphrase_cb(hint, desc, prev_bad, hook=None):
Packit d7e8d0
                return passphrase
Packit Service 30b792
Packit d7e8d0
            self.set_passphrase_cb(passphrase_cb)
Packit d7e8d0
Packit d7e8d0
        try:
Packit d7e8d0
            if sign:
Packit d7e8d0
                self.op_encrypt_sign(recipients, flags, plaintext, ciphertext)
Packit d7e8d0
            else:
Packit d7e8d0
                self.op_encrypt(recipients, flags, plaintext, ciphertext)
Packit d7e8d0
        except errors.GPGMEError as e:
Packit d7e8d0
            result = self.op_encrypt_result()
Packit d7e8d0
            sig_result = self.op_sign_result() if sign else None
Packit Service 30b792
            results = (self.__read__(sink, ciphertext), result, sig_result)
Packit d7e8d0
            if e.getcode() == errors.UNUSABLE_PUBKEY:
Packit d7e8d0
                if result.invalid_recipients:
Packit Service 30b792
                    raise errors.InvalidRecipients(
Packit Service 30b792
                        result.invalid_recipients,
Packit Service 30b792
                        error=e.error,
Packit Service 30b792
                        results=results)
Packit d7e8d0
            if e.getcode() == errors.UNUSABLE_SECKEY:
Packit d7e8d0
                sig_result = self.op_sign_result()
Packit d7e8d0
                if sig_result.invalid_signers:
Packit Service 30b792
                    raise errors.InvalidSigners(
Packit Service 30b792
                        sig_result.invalid_signers,
Packit Service 30b792
                        error=e.error,
Packit Service 30b792
                        results=results)
Packit d7e8d0
            # Otherwise, just raise the error, but attach the results
Packit d7e8d0
            # first.
Packit d7e8d0
            e.results = results
Packit d7e8d0
            raise e
Packit d7e8d0
        finally:
Packit Service 30b792
            if passphrase is not None:
Packit d7e8d0
                self.pinentry_mode = old_pinentry_mode
Packit d7e8d0
                if old_passphrase_cb:
Packit d7e8d0
                    self.set_passphrase_cb(*old_passphrase_cb[1:])
Packit d7e8d0
Packit d7e8d0
        result = self.op_encrypt_result()
Packit d7e8d0
        assert not result.invalid_recipients
Packit d7e8d0
        sig_result = self.op_sign_result() if sign else None
Packit d7e8d0
        assert not sig_result or not sig_result.invalid_signers
Packit d7e8d0
Packit d7e8d0
        return self.__read__(sink, ciphertext), result, sig_result
Packit d7e8d0
Packit d7e8d0
    def decrypt(self, ciphertext, sink=None, passphrase=None, verify=True):
Packit d7e8d0
        """Decrypt data
Packit d7e8d0
Packit d7e8d0
        Decrypt the given ciphertext and verify any signatures.  If
Packit d7e8d0
        VERIFY is an iterable of keys, the ciphertext must be signed
Packit Service 30b792
        by all those keys, otherwise a MissingSignatures error is
Packit Service 30b792
        raised.  Note: if VERIFY is an empty iterable, that is treated
Packit Service 30b792
        the same as passing verify=True (that is, verify signatures
Packit Service 30b792
        and return data about any valid signatures found, but no
Packit Service 30b792
        signatures are required and no MissingSignatures error will be
Packit Service 30b792
        raised).
Packit d7e8d0
Packit d7e8d0
        If the ciphertext is symmetrically encrypted using a
Packit d7e8d0
        passphrase, that passphrase can be given as parameter, using a
Packit d7e8d0
        callback registered at the context, or out-of-band via
Packit d7e8d0
        pinentry.
Packit d7e8d0
Packit d7e8d0
        Keyword arguments:
Packit Service 30b792
        sink            -- write result to sink instead of returning it
Packit Service 30b792
        passphrase      -- for symmetric decryption
Packit Service 30b792
        verify          -- check signatures (boolean or iterable of keys,
Packit Service 30b792
                           see above) (default True)
Packit d7e8d0
Packit d7e8d0
        Returns:
Packit Service 30b792
        plaintext       -- the decrypted data (or None if sink is given)
Packit Service 30b792
        result          -- additional information about the decryption
Packit Service 30b792
        verify_result   -- additional information about the valid
Packit Service 30b792
                           signature(s) found
Packit d7e8d0
Packit d7e8d0
        Raises:
Packit d7e8d0
        UnsupportedAlgorithm -- if an unsupported algorithm was used
Packit Service 30b792
        MissingSignatures    -- if expected signatures are missing or bad
Packit Service 30b792
        GPGMEError           -- as signaled by the underlying library
Packit d7e8d0
Packit d7e8d0
        """
Packit Service 30b792
        do_sig_verification = False
Packit Service 30b792
        required_keys = None
Packit d7e8d0
        plaintext = sink if sink else Data()
Packit d7e8d0
Packit Service 30b792
        if passphrase is not None:
Packit d7e8d0
            old_pinentry_mode = self.pinentry_mode
Packit d7e8d0
            old_passphrase_cb = getattr(self, '_passphrase_cb', None)
Packit d7e8d0
            self.pinentry_mode = constants.PINENTRY_MODE_LOOPBACK
Packit Service 30b792
Packit d7e8d0
            def passphrase_cb(hint, desc, prev_bad, hook=None):
Packit d7e8d0
                return passphrase
Packit Service 30b792
Packit d7e8d0
            self.set_passphrase_cb(passphrase_cb)
Packit d7e8d0
Packit d7e8d0
        try:
Packit Service 30b792
            if isinstance(verify, bool):
Packit Service 30b792
                do_sig_verification = verify
Packit Service 30b792
            elif verify is None:
Packit Service 30b792
                warnings.warn(
Packit Service 30b792
                    "ctx.decrypt called with verify=None, should be bool or iterable (treating as False).",
Packit Service 30b792
                    category=DeprecationWarning)
Packit Service 30b792
                do_sig_verification = False
Packit Service 30b792
            else:
Packit Service 30b792
                # we hope this is an iterable:
Packit Service 30b792
                required_keys = verify
Packit Service 30b792
                do_sig_verification = True
Packit Service 30b792
Packit Service 30b792
            if do_sig_verification:
Packit d7e8d0
                self.op_decrypt_verify(ciphertext, plaintext)
Packit d7e8d0
            else:
Packit d7e8d0
                self.op_decrypt(ciphertext, plaintext)
Packit d7e8d0
        except errors.GPGMEError as e:
Packit d7e8d0
            result = self.op_decrypt_result()
Packit Service 30b792
            if do_sig_verification:
Packit Service 30b792
                verify_result = self.op_verify_result()
Packit Service 30b792
            else:
Packit Service 30b792
                verify_result = None
Packit d7e8d0
            # Just raise the error, but attach the results first.
Packit Service 30b792
            e.results = (self.__read__(sink, plaintext), result, verify_result)
Packit d7e8d0
            raise e
Packit d7e8d0
        finally:
Packit Service 30b792
            if passphrase is not None:
Packit d7e8d0
                self.pinentry_mode = old_pinentry_mode
Packit d7e8d0
                if old_passphrase_cb:
Packit d7e8d0
                    self.set_passphrase_cb(*old_passphrase_cb[1:])
Packit d7e8d0
Packit d7e8d0
        result = self.op_decrypt_result()
Packit Service 30b792
Packit Service 30b792
        if do_sig_verification:
Packit Service 30b792
            verify_result = self.op_verify_result()
Packit Service 30b792
        else:
Packit Service 30b792
            verify_result = None
Packit Service 30b792
Packit d7e8d0
        results = (self.__read__(sink, plaintext), result, verify_result)
Packit Service 30b792
Packit d7e8d0
        if result.unsupported_algorithm:
Packit d7e8d0
            raise errors.UnsupportedAlgorithm(result.unsupported_algorithm,
Packit d7e8d0
                                              results=results)
Packit d7e8d0
Packit Service 30b792
        if do_sig_verification:
Packit Service 30b792
            # filter out all invalid signatures
Packit Service 30b792
            verify_result.signatures = list(filter(lambda s: s.status == errors.NO_ERROR, verify_result.signatures))
Packit Service 30b792
            if required_keys is not None:
Packit Service 30b792
                missing = []
Packit Service 30b792
                for key in required_keys:
Packit Service 30b792
                    ok = False
Packit Service 30b792
                    for subkey in key.subkeys:
Packit Service 30b792
                        for sig in verify_result.signatures:
Packit Service 30b792
                            if sig.summary & constants.SIGSUM_VALID == 0:
Packit Service 30b792
                                continue
Packit Service 30b792
                            if subkey.can_sign and subkey.fpr == sig.fpr:
Packit Service 30b792
                                ok = True
Packit d7e8d0
                            break
Packit Service 30b792
                        if ok:
Packit Service 30b792
                            break
Packit Service 30b792
                    if not ok:
Packit Service 30b792
                        missing.append(key)
Packit Service 30b792
                if missing:
Packit Service 30b792
                    raise errors.MissingSignatures(verify_result, missing,
Packit Service 30b792
                                                   results=results)
Packit d7e8d0
Packit d7e8d0
        return results
Packit d7e8d0
Packit d7e8d0
    def sign(self, data, sink=None, mode=constants.SIG_MODE_NORMAL):
Packit d7e8d0
        """Sign data
Packit d7e8d0
Packit d7e8d0
        Sign the given data with either the configured default local
Packit d7e8d0
        key, or the 'signers' keys of this context.
Packit d7e8d0
Packit d7e8d0
        Keyword arguments:
Packit d7e8d0
        mode		-- signature mode (default: normal, see below)
Packit d7e8d0
        sink		-- write result to sink instead of returning it
Packit d7e8d0
Packit d7e8d0
        Returns:
Packit d7e8d0
        either
Packit d7e8d0
          signed_data	-- encoded data and signature (normal mode)
Packit d7e8d0
          signature	-- only the signature data (detached mode)
Packit d7e8d0
          cleartext	-- data and signature as text (cleartext mode)
Packit d7e8d0
            (or None if sink is given)
Packit d7e8d0
        result		-- additional information about the signature(s)
Packit d7e8d0
Packit d7e8d0
        Raises:
Packit d7e8d0
        InvalidSigners	-- if signing using a particular key failed
Packit d7e8d0
        GPGMEError	-- as signaled by the underlying library
Packit d7e8d0
Packit d7e8d0
        """
Packit d7e8d0
        signeddata = sink if sink else Data()
Packit d7e8d0
Packit d7e8d0
        try:
Packit d7e8d0
            self.op_sign(data, signeddata, mode)
Packit d7e8d0
        except errors.GPGMEError as e:
Packit Service 30b792
            results = (self.__read__(sink, signeddata), self.op_sign_result())
Packit d7e8d0
            if e.getcode() == errors.UNUSABLE_SECKEY:
Packit d7e8d0
                if results[1].invalid_signers:
Packit Service 30b792
                    raise errors.InvalidSigners(
Packit Service 30b792
                        results[1].invalid_signers,
Packit Service 30b792
                        error=e.error,
Packit Service 30b792
                        results=results)
Packit d7e8d0
            e.results = results
Packit d7e8d0
            raise e
Packit d7e8d0
Packit d7e8d0
        result = self.op_sign_result()
Packit d7e8d0
        assert not result.invalid_signers
Packit d7e8d0
Packit d7e8d0
        return self.__read__(sink, signeddata), result
Packit d7e8d0
Packit d7e8d0
    def verify(self, signed_data, signature=None, sink=None, verify=[]):
Packit d7e8d0
        """Verify signatures
Packit d7e8d0
Packit d7e8d0
        Verify signatures over data.  If VERIFY is an iterable of
Packit d7e8d0
        keys, the ciphertext must be signed by all those keys,
Packit d7e8d0
        otherwise an error is raised.
Packit d7e8d0
Packit d7e8d0
        Keyword arguments:
Packit d7e8d0
        signature	-- detached signature data
Packit d7e8d0
        sink		-- write result to sink instead of returning it
Packit d7e8d0
Packit d7e8d0
        Returns:
Packit d7e8d0
        data		-- the plain data
Packit d7e8d0
            (or None if sink is given, or we verified a detached signature)
Packit d7e8d0
        result		-- additional information about the signature(s)
Packit d7e8d0
Packit d7e8d0
        Raises:
Packit d7e8d0
        BadSignatures	-- if a bad signature is encountered
Packit d7e8d0
        MissingSignatures -- if expected signatures are missing or bad
Packit d7e8d0
        GPGMEError	-- as signaled by the underlying library
Packit d7e8d0
Packit d7e8d0
        """
Packit d7e8d0
        if signature:
Packit d7e8d0
            # Detached signature, we don't return the plain text.
Packit d7e8d0
            data = None
Packit d7e8d0
        else:
Packit d7e8d0
            data = sink if sink else Data()
Packit d7e8d0
Packit d7e8d0
        try:
Packit d7e8d0
            if signature:
Packit d7e8d0
                self.op_verify(signature, signed_data, None)
Packit d7e8d0
            else:
Packit d7e8d0
                self.op_verify(signed_data, None, data)
Packit d7e8d0
        except errors.GPGMEError as e:
Packit d7e8d0
            # Just raise the error, but attach the results first.
Packit Service 30b792
            e.results = (self.__read__(sink, data), self.op_verify_result())
Packit d7e8d0
            raise e
Packit d7e8d0
Packit d7e8d0
        results = (self.__read__(sink, data), self.op_verify_result())
Packit d7e8d0
        if any(s.status != errors.NO_ERROR for s in results[1].signatures):
Packit d7e8d0
            raise errors.BadSignatures(results[1], results=results)
Packit d7e8d0
Packit d7e8d0
        missing = list()
Packit d7e8d0
        for key in verify:
Packit d7e8d0
            ok = False
Packit d7e8d0
            for subkey in key.subkeys:
Packit d7e8d0
                for sig in results[1].signatures:
Packit d7e8d0
                    if sig.summary & constants.SIGSUM_VALID == 0:
Packit d7e8d0
                        continue
Packit d7e8d0
                    if subkey.can_sign and subkey.fpr == sig.fpr:
Packit d7e8d0
                        ok = True
Packit d7e8d0
                        break
Packit d7e8d0
                if ok:
Packit d7e8d0
                    break
Packit d7e8d0
            if not ok:
Packit d7e8d0
                missing.append(key)
Packit d7e8d0
        if missing:
Packit Service 30b792
            raise errors.MissingSignatures(
Packit Service 30b792
                results[1], missing, results=results)
Packit d7e8d0
Packit d7e8d0
        return results
Packit d7e8d0
Packit Service 30b792
    def key_import(self, data):
Packit Service 30b792
        """Import data
Packit Service 30b792
Packit Service 30b792
        Imports the given data into the Context.
Packit Service 30b792
Packit Service 30b792
        Returns:
Packit Service 30b792
                -- an object describing the results of imported or updated
Packit Service 30b792
                   keys
Packit Service 30b792
Packit Service 30b792
        Raises:
Packit Service 30b792
        TypeError      -- Very rarely.
Packit Service 30b792
        GPGMEError     -- as signaled by the underlying library:
Packit Service 30b792
Packit Service 30b792
                          Import status errors, when they occur, will usually
Packit Service 30b792
                          be of NODATA.  NO_PUBKEY indicates something
Packit Service 30b792
                          managed to run the function without any
Packit Service 30b792
                          arguments, while an argument of None triggers
Packit Service 30b792
                          the first NODATA of errors.GPGME in the
Packit Service 30b792
                          exception.
Packit Service 30b792
        """
Packit Service 30b792
        try:
Packit Service 30b792
            self.op_import(data)
Packit Service 30b792
            result = self.op_import_result()
Packit Service 30b792
            if result.considered == 0:
Packit Service 30b792
                status = constants.STATUS_IMPORT_PROBLEM
Packit Service 30b792
            else:
Packit Service 30b792
                status = constants.STATUS_KEY_CONSIDERED
Packit Service 30b792
        except Exception as e:
Packit Service 30b792
            if e == errors.GPGMEError:
Packit Service 30b792
                if e.code_str == "No data":
Packit Service 30b792
                    status = constants.STATUS_NODATA
Packit Service 30b792
                else:
Packit Service 30b792
                    status = constants.STATUS_FILE_ERROR
Packit Service 30b792
            elif e == TypeError and hasattr(data, "decode") is True:
Packit Service 30b792
                status = constants.STATUS_NO_PUBKEY
Packit Service 30b792
            elif e == TypeError and hasattr(data, "encode") is True:
Packit Service 30b792
                status = constants.STATUS_FILE_ERROR
Packit Service 30b792
            else:
Packit Service 30b792
                status = constants.STATUS_ERROR
Packit Service 30b792
Packit Service 30b792
        if status == constants.STATUS_KEY_CONSIDERED:
Packit Service 30b792
            import_result = result
Packit Service 30b792
        else:
Packit Service 30b792
            import_result = status
Packit Service 30b792
Packit Service 30b792
        return import_result
Packit Service 30b792
Packit Service 30b792
    def key_export(self, pattern=None):
Packit Service 30b792
        """Export keys.
Packit Service 30b792
Packit Service 30b792
        Exports public keys matching the pattern specified.  If no
Packit Service 30b792
        pattern is specified then exports all available keys.
Packit Service 30b792
Packit Service 30b792
        Keyword arguments:
Packit Service 30b792
        pattern	-- return keys matching pattern (default: all keys)
Packit Service 30b792
Packit Service 30b792
        Returns:
Packit Service 30b792
                -- A key block containing one or more OpenPGP keys in
Packit Service 30b792
                   either ASCII armoured or binary format as determined
Packit Service 30b792
                   by the Context().  If there are no matching keys it
Packit Service 30b792
                   returns None.
Packit Service 30b792
Packit Service 30b792
        Raises:
Packit Service 30b792
        GPGMEError     -- as signaled by the underlying library.
Packit Service 30b792
        """
Packit Service 30b792
        data = Data()
Packit Service 30b792
        mode = 0
Packit Service 30b792
        try:
Packit Service 30b792
            self.op_export(pattern, mode, data)
Packit Service 30b792
            data.seek(0, os.SEEK_SET)
Packit Service 30b792
            pk_result = data.read()
Packit Service 30b792
        except GPGMEError as e:
Packit Service 30b792
            pk_result = e
Packit Service 30b792
Packit Service 30b792
        if len(pk_result) > 0:
Packit Service 30b792
            result = pk_result
Packit Service 30b792
        else:
Packit Service 30b792
            result = None
Packit Service 30b792
Packit Service 30b792
        return result
Packit Service 30b792
Packit Service 30b792
    def key_export_minimal(self, pattern=None):
Packit Service 30b792
        """Export keys.
Packit Service 30b792
Packit Service 30b792
        Exports public keys matching the pattern specified in a
Packit Service 30b792
        minimised format.  If no pattern is specified then exports all
Packit Service 30b792
        available keys.
Packit Service 30b792
Packit Service 30b792
        Keyword arguments:
Packit Service 30b792
        pattern	-- return keys matching pattern (default: all keys)
Packit Service 30b792
Packit Service 30b792
        Returns:
Packit Service 30b792
                -- A key block containing one or more minimised OpenPGP
Packit Service 30b792
                   keys in either ASCII armoured or binary format as
Packit Service 30b792
                   determined by the Context().  If there are no matching
Packit Service 30b792
                   keys it returns None.
Packit Service 30b792
Packit Service 30b792
        Raises:
Packit Service 30b792
        GPGMEError     -- as signaled by the underlying library.
Packit Service 30b792
        """
Packit Service 30b792
        data = Data()
Packit Service 30b792
        mode = gpgme.GPGME_EXPORT_MODE_MINIMAL
Packit Service 30b792
        try:
Packit Service 30b792
            self.op_export(pattern, mode, data)
Packit Service 30b792
            data.seek(0, os.SEEK_SET)
Packit Service 30b792
            pk_result = data.read()
Packit Service 30b792
        except GPGMEError as e:
Packit Service 30b792
            pk_result = e
Packit Service 30b792
Packit Service 30b792
        if len(pk_result) > 0:
Packit Service 30b792
            result = pk_result
Packit Service 30b792
        else:
Packit Service 30b792
            result = None
Packit Service 30b792
Packit Service 30b792
        return result
Packit Service 30b792
Packit Service 30b792
    def key_export_secret(self, pattern=None):
Packit Service 30b792
        """Export secret keys.
Packit Service 30b792
Packit Service 30b792
        Exports secret keys matching the pattern specified.  If no
Packit Service 30b792
        pattern is specified then exports or attempts to export all
Packit Service 30b792
        available secret keys.
Packit Service 30b792
Packit Service 30b792
        IMPORTANT: Each secret key to be exported will prompt for its
Packit Service 30b792
        passphrase via an invocation of pinentry and gpg-agent.  If the
Packit Service 30b792
        passphrase is not entered or does not match then no data will be
Packit Service 30b792
        exported.  This is the same result as when specifying a pattern
Packit Service 30b792
        that is not matched by the available keys.
Packit Service 30b792
Packit Service 30b792
        Keyword arguments:
Packit Service 30b792
        pattern	-- return keys matching pattern (default: all keys)
Packit Service 30b792
Packit Service 30b792
        Returns:
Packit Service 30b792
                -- On success a key block containing one or more OpenPGP
Packit Service 30b792
                   secret keys in either ASCII armoured or binary format
Packit Service 30b792
                   as determined by the Context().
Packit Service 30b792
                -- On failure while not raising an exception, returns None.
Packit Service 30b792
Packit Service 30b792
        Raises:
Packit Service 30b792
        GPGMEError     -- as signaled by the underlying library.
Packit Service 30b792
        """
Packit Service 30b792
        data = Data()
Packit Service 30b792
        mode = gpgme.GPGME_EXPORT_MODE_SECRET
Packit Service 30b792
        try:
Packit Service 30b792
            self.op_export(pattern, mode, data)
Packit Service 30b792
            data.seek(0, os.SEEK_SET)
Packit Service 30b792
            sk_result = data.read()
Packit Service 30b792
        except GPGMEError as e:
Packit Service 30b792
            sk_result = e
Packit Service 30b792
Packit Service 30b792
        if len(sk_result) > 0:
Packit Service 30b792
            result = sk_result
Packit Service 30b792
        else:
Packit Service 30b792
            result = None
Packit Service 30b792
Packit Service 30b792
        return result
Packit Service 30b792
Packit Service 30b792
    def keylist(self,
Packit Service 30b792
                pattern=None,
Packit Service 30b792
                secret=False,
Packit d7e8d0
                mode=constants.keylist.mode.LOCAL,
Packit d7e8d0
                source=None):
Packit d7e8d0
        """List keys
Packit d7e8d0
Packit d7e8d0
        Keyword arguments:
Packit d7e8d0
        pattern	-- return keys matching pattern (default: all keys)
Packit d7e8d0
        secret	-- return only secret keys (default: False)
Packit d7e8d0
        mode    -- keylist mode (default: list local keys)
Packit d7e8d0
        source  -- read keys from source instead from the keyring
Packit d7e8d0
                       (all other options are ignored in this case)
Packit d7e8d0
Packit d7e8d0
        Returns:
Packit d7e8d0
                -- an iterator returning key objects
Packit d7e8d0
Packit d7e8d0
        Raises:
Packit d7e8d0
        GPGMEError	-- as signaled by the underlying library
Packit d7e8d0
        """
Packit d7e8d0
        if not source:
Packit d7e8d0
            self.set_keylist_mode(mode)
Packit d7e8d0
            self.op_keylist_start(pattern, secret)
Packit d7e8d0
        else:
Packit d7e8d0
            # Automatic wrapping of SOURCE is not possible here,
Packit d7e8d0
            # because the object must not be deallocated until the
Packit d7e8d0
            # iteration over the results ends.
Packit d7e8d0
            if not isinstance(source, Data):
Packit d7e8d0
                source = Data(file=source)
Packit d7e8d0
            self.op_keylist_from_data_start(source, 0)
Packit d7e8d0
Packit d7e8d0
        key = self.op_keylist_next()
Packit d7e8d0
        while key:
Packit d7e8d0
            yield key
Packit d7e8d0
            key = self.op_keylist_next()
Packit d7e8d0
        self.op_keylist_end()
Packit d7e8d0
Packit Service 30b792
    def create_key(self,
Packit Service 30b792
                   userid,
Packit Service 30b792
                   algorithm=None,
Packit Service 30b792
                   expires_in=0,
Packit Service 30b792
                   expires=True,
Packit Service 30b792
                   sign=False,
Packit Service 30b792
                   encrypt=False,
Packit Service 30b792
                   certify=False,
Packit Service 30b792
                   authenticate=False,
Packit Service 30b792
                   passphrase=None,
Packit Service 30b792
                   force=False):
Packit d7e8d0
        """Create a primary key
Packit d7e8d0
Packit d7e8d0
        Create a primary key for the user id USERID.
Packit d7e8d0
Packit d7e8d0
        ALGORITHM may be used to specify the public key encryption
Packit d7e8d0
        algorithm for the new key.  By default, a reasonable default
Packit d7e8d0
        is chosen.  You may use "future-default" to select an
Packit d7e8d0
        algorithm that will be the default in a future implementation
Packit d7e8d0
        of the engine.  ALGORITHM may be a string like "rsa", or
Packit d7e8d0
        "rsa2048" to explicitly request an algorithm and a key size.
Packit d7e8d0
Packit d7e8d0
        EXPIRES_IN specifies the expiration time of the key in number
Packit d7e8d0
        of seconds since the keys creation.  By default, a reasonable
Packit d7e8d0
        expiration time is chosen.  If you want to create a key that
Packit d7e8d0
        does not expire, use the keyword argument EXPIRES.
Packit d7e8d0
Packit d7e8d0
        SIGN, ENCRYPT, CERTIFY, and AUTHENTICATE can be used to
Packit d7e8d0
        request the capabilities of the new key.  If you don't request
Packit d7e8d0
        any, a reasonable set of capabilities is selected, and in case
Packit d7e8d0
        of OpenPGP, a subkey with a reasonable set of capabilities is
Packit d7e8d0
        created.
Packit d7e8d0
Packit d7e8d0
        If PASSPHRASE is None (the default), then the key will not be
Packit d7e8d0
        protected with a passphrase.  If PASSPHRASE is a string, it
Packit d7e8d0
        will be used to protect the key.  If PASSPHRASE is True, the
Packit d7e8d0
        passphrase must be supplied using a passphrase callback or
Packit d7e8d0
        out-of-band with a pinentry.
Packit d7e8d0
Packit d7e8d0
        Keyword arguments:
Packit d7e8d0
        algorithm    -- public key algorithm, see above (default: reasonable)
Packit d7e8d0
        expires_in   -- expiration time in seconds (default: reasonable)
Packit d7e8d0
        expires      -- whether or not the key should expire (default: True)
Packit d7e8d0
        sign         -- request the signing capability (see above)
Packit d7e8d0
        encrypt      -- request the encryption capability (see above)
Packit d7e8d0
        certify      -- request the certification capability (see above)
Packit d7e8d0
        authenticate -- request the authentication capability (see above)
Packit Service 30b792
        passphrase   -- protect the key with a passphrase (default: no
Packit Service 30b792
                        passphrase)
Packit Service 30b792
        force        -- force key creation even if a key with the same userid
Packit Service 30b792
                        exists (default: False)
Packit d7e8d0
Packit d7e8d0
        Returns:
Packit d7e8d0
                     -- an object describing the result of the key creation
Packit d7e8d0
Packit d7e8d0
        Raises:
Packit d7e8d0
        GPGMEError   -- as signaled by the underlying library
Packit d7e8d0
Packit d7e8d0
        """
Packit d7e8d0
        if util.is_a_string(passphrase):
Packit d7e8d0
            old_pinentry_mode = self.pinentry_mode
Packit d7e8d0
            old_passphrase_cb = getattr(self, '_passphrase_cb', None)
Packit d7e8d0
            self.pinentry_mode = constants.PINENTRY_MODE_LOOPBACK
Packit Service 30b792
Packit d7e8d0
            def passphrase_cb(hint, desc, prev_bad, hook=None):
Packit d7e8d0
                return passphrase
Packit Service 30b792
Packit d7e8d0
            self.set_passphrase_cb(passphrase_cb)
Packit d7e8d0
Packit d7e8d0
        try:
Packit Service 30b792
            self.op_createkey(
Packit Service 30b792
                userid,
Packit Service 30b792
                algorithm,
Packit Service 30b792
                0,  # reserved
Packit Service 30b792
                expires_in,
Packit Service 30b792
                None,  # extrakey
Packit Service 30b792
                ((constants.create.SIGN if sign else 0) |
Packit Service 30b792
                 (constants.create.ENCR if encrypt else 0) |
Packit Service 30b792
                 (constants.create.CERT if certify else 0) |
Packit Service 30b792
                 (constants.create.AUTH if authenticate else 0) |
Packit Service 30b792
                 (constants.create.NOPASSWD if passphrase is None else 0) |
Packit Service 30b792
                 (0 if expires else constants.create.NOEXPIRE) |
Packit Service 30b792
                 (constants.create.FORCE if force else 0)))
Packit d7e8d0
        finally:
Packit d7e8d0
            if util.is_a_string(passphrase):
Packit d7e8d0
                self.pinentry_mode = old_pinentry_mode
Packit d7e8d0
                if old_passphrase_cb:
Packit d7e8d0
                    self.set_passphrase_cb(*old_passphrase_cb[1:])
Packit d7e8d0
Packit d7e8d0
        return self.op_genkey_result()
Packit d7e8d0
Packit Service 30b792
    def create_subkey(self,
Packit Service 30b792
                      key,
Packit Service 30b792
                      algorithm=None,
Packit Service 30b792
                      expires_in=0,
Packit Service 30b792
                      expires=True,
Packit Service 30b792
                      sign=False,
Packit Service 30b792
                      encrypt=False,
Packit Service 30b792
                      authenticate=False,
Packit Service 30b792
                      passphrase=None):
Packit d7e8d0
        """Create a subkey
Packit d7e8d0
Packit d7e8d0
        Create a subkey for the given KEY.  As subkeys are a concept
Packit d7e8d0
        of OpenPGP, calling this is only valid for the OpenPGP
Packit d7e8d0
        protocol.
Packit d7e8d0
Packit d7e8d0
        ALGORITHM may be used to specify the public key encryption
Packit d7e8d0
        algorithm for the new subkey.  By default, a reasonable
Packit d7e8d0
        default is chosen.  You may use "future-default" to select an
Packit d7e8d0
        algorithm that will be the default in a future implementation
Packit d7e8d0
        of the engine.  ALGORITHM may be a string like "rsa", or
Packit d7e8d0
        "rsa2048" to explicitly request an algorithm and a key size.
Packit d7e8d0
Packit d7e8d0
        EXPIRES_IN specifies the expiration time of the subkey in
Packit d7e8d0
        number of seconds since the subkeys creation.  By default, a
Packit d7e8d0
        reasonable expiration time is chosen.  If you want to create a
Packit d7e8d0
        subkey that does not expire, use the keyword argument EXPIRES.
Packit d7e8d0
Packit d7e8d0
        SIGN, ENCRYPT, and AUTHENTICATE can be used to request the
Packit d7e8d0
        capabilities of the new subkey.  If you don't request any, an
Packit d7e8d0
        encryption subkey is generated.
Packit d7e8d0
Packit d7e8d0
        If PASSPHRASE is None (the default), then the subkey will not
Packit d7e8d0
        be protected with a passphrase.  If PASSPHRASE is a string, it
Packit d7e8d0
        will be used to protect the subkey.  If PASSPHRASE is True,
Packit d7e8d0
        the passphrase must be supplied using a passphrase callback or
Packit d7e8d0
        out-of-band with a pinentry.
Packit d7e8d0
Packit d7e8d0
        Keyword arguments:
Packit d7e8d0
        algorithm    -- public key algorithm, see above (default: reasonable)
Packit d7e8d0
        expires_in   -- expiration time in seconds (default: reasonable)
Packit d7e8d0
        expires      -- whether or not the subkey should expire (default: True)
Packit d7e8d0
        sign         -- request the signing capability (see above)
Packit d7e8d0
        encrypt      -- request the encryption capability (see above)
Packit d7e8d0
        authenticate -- request the authentication capability (see above)
Packit Service 30b792
        passphrase   -- protect the subkey with a passphrase (default: no
Packit Service 30b792
                        passphrase)
Packit d7e8d0
Packit d7e8d0
        Returns:
Packit d7e8d0
                     -- an object describing the result of the subkey creation
Packit d7e8d0
Packit d7e8d0
        Raises:
Packit d7e8d0
        GPGMEError   -- as signaled by the underlying library
Packit d7e8d0
Packit d7e8d0
        """
Packit d7e8d0
        if util.is_a_string(passphrase):
Packit d7e8d0
            old_pinentry_mode = self.pinentry_mode
Packit d7e8d0
            old_passphrase_cb = getattr(self, '_passphrase_cb', None)
Packit d7e8d0
            self.pinentry_mode = constants.PINENTRY_MODE_LOOPBACK
Packit Service 30b792
Packit d7e8d0
            def passphrase_cb(hint, desc, prev_bad, hook=None):
Packit d7e8d0
                return passphrase
Packit Service 30b792
Packit d7e8d0
            self.set_passphrase_cb(passphrase_cb)
Packit d7e8d0
Packit d7e8d0
        try:
Packit Service 30b792
            self.op_createsubkey(
Packit Service 30b792
                key,
Packit Service 30b792
                algorithm,
Packit Service 30b792
                0,  # reserved
Packit Service 30b792
                expires_in,
Packit Service 30b792
                ((constants.create.SIGN if sign else 0) |
Packit Service 30b792
                 (constants.create.ENCR if encrypt else 0) |
Packit Service 30b792
                 (constants.create.AUTH if authenticate else 0) |
Packit Service 30b792
                 (constants.create.NOPASSWD if passphrase is None else 0) |
Packit Service 30b792
                 (0 if expires else constants.create.NOEXPIRE)))
Packit d7e8d0
        finally:
Packit d7e8d0
            if util.is_a_string(passphrase):
Packit d7e8d0
                self.pinentry_mode = old_pinentry_mode
Packit d7e8d0
                if old_passphrase_cb:
Packit d7e8d0
                    self.set_passphrase_cb(*old_passphrase_cb[1:])
Packit d7e8d0
Packit d7e8d0
        return self.op_genkey_result()
Packit d7e8d0
Packit d7e8d0
    def key_add_uid(self, key, uid):
Packit d7e8d0
        """Add a UID
Packit d7e8d0
Packit d7e8d0
        Add the uid UID to the given KEY.  Calling this function is
Packit d7e8d0
        only valid for the OpenPGP protocol.
Packit d7e8d0
Packit d7e8d0
        Raises:
Packit d7e8d0
        GPGMEError   -- as signaled by the underlying library
Packit d7e8d0
Packit d7e8d0
        """
Packit d7e8d0
        self.op_adduid(key, uid, 0)
Packit d7e8d0
Packit d7e8d0
    def key_revoke_uid(self, key, uid):
Packit d7e8d0
        """Revoke a UID
Packit d7e8d0
Packit d7e8d0
        Revoke the uid UID from the given KEY.  Calling this function
Packit d7e8d0
        is only valid for the OpenPGP protocol.
Packit d7e8d0
Packit d7e8d0
        Raises:
Packit d7e8d0
        GPGMEError   -- as signaled by the underlying library
Packit d7e8d0
Packit d7e8d0
        """
Packit d7e8d0
        self.op_revuid(key, uid, 0)
Packit d7e8d0
Packit d7e8d0
    def key_sign(self, key, uids=None, expires_in=False, local=False):
Packit d7e8d0
        """Sign a key
Packit d7e8d0
Packit d7e8d0
        Sign a key with the current set of signing keys.  Calling this
Packit d7e8d0
        function is only valid for the OpenPGP protocol.
Packit d7e8d0
Packit d7e8d0
        If UIDS is None (the default), then all UIDs are signed.  If
Packit d7e8d0
        it is a string, then only the matching UID is signed.  If it
Packit d7e8d0
        is a list of strings, then all matching UIDs are signed.  Note
Packit d7e8d0
        that a case-sensitive exact string comparison is done.
Packit d7e8d0
Packit d7e8d0
        EXPIRES_IN specifies the expiration time of the signature in
Packit d7e8d0
        seconds.  If EXPIRES_IN is False, the signature does not
Packit d7e8d0
        expire.
Packit d7e8d0
Packit d7e8d0
        Keyword arguments:
Packit d7e8d0
        uids         -- user ids to sign, see above (default: sign all)
Packit d7e8d0
        expires_in   -- validity period of the signature in seconds
Packit d7e8d0
                                               (default: do not expire)
Packit d7e8d0
        local        -- create a local, non-exportable signature
Packit d7e8d0
                                               (default: False)
Packit d7e8d0
Packit d7e8d0
        Raises:
Packit d7e8d0
        GPGMEError   -- as signaled by the underlying library
Packit d7e8d0
Packit d7e8d0
        """
Packit d7e8d0
        flags = 0
Packit Service 30b792
        if uids is None or util.is_a_string(uids):
Packit Service 30b792
            pass  # through unchanged
Packit d7e8d0
        else:
Packit d7e8d0
            flags |= constants.keysign.LFSEP
Packit d7e8d0
            uids = "\n".join(uids)
Packit d7e8d0
Packit d7e8d0
        if not expires_in:
Packit d7e8d0
            flags |= constants.keysign.NOEXPIRE
Packit d7e8d0
Packit d7e8d0
        if local:
Packit d7e8d0
            flags |= constants.keysign.LOCAL
Packit d7e8d0
Packit d7e8d0
        self.op_keysign(key, uids, expires_in, flags)
Packit d7e8d0
Packit d7e8d0
    def key_tofu_policy(self, key, policy):
Packit d7e8d0
        """Set a keys' TOFU policy
Packit d7e8d0
Packit d7e8d0
        Set the TOFU policy associated with KEY to POLICY.  Calling
Packit d7e8d0
        this function is only valid for the OpenPGP protocol.
Packit d7e8d0
Packit d7e8d0
        Raises:
Packit d7e8d0
        GPGMEError   -- as signaled by the underlying library
Packit d7e8d0
Packit d7e8d0
        """
Packit d7e8d0
        self.op_tofu_policy(key, policy)
Packit d7e8d0
Packit Service 30b792
    def assuan_transact(self,
Packit Service 30b792
                        command,
Packit Service 30b792
                        data_cb=None,
Packit Service 30b792
                        inquire_cb=None,
Packit Service 30b792
                        status_cb=None):
Packit d7e8d0
        """Issue a raw assuan command
Packit d7e8d0
Packit d7e8d0
        This function can be used to issue a raw assuan command to the
Packit d7e8d0
        engine.
Packit d7e8d0
Packit d7e8d0
        If command is a string or bytes, it will be used as-is.  If it
Packit d7e8d0
        is an iterable of strings, it will be properly escaped and
Packit d7e8d0
        joined into an well-formed assuan command.
Packit d7e8d0
Packit d7e8d0
        Keyword arguments:
Packit d7e8d0
        data_cb		-- a callback receiving data lines
Packit d7e8d0
        inquire_cb	-- a callback providing more information
Packit d7e8d0
        status_cb	-- a callback receiving status lines
Packit d7e8d0
Packit d7e8d0
        Returns:
Packit d7e8d0
        result		-- the result of command as GPGMEError
Packit d7e8d0
Packit d7e8d0
        Raises:
Packit d7e8d0
        GPGMEError	-- as signaled by the underlying library
Packit d7e8d0
Packit d7e8d0
        """
Packit d7e8d0
Packit d7e8d0
        if util.is_a_string(command) or isinstance(command, bytes):
Packit d7e8d0
            cmd = command
Packit d7e8d0
        else:
Packit d7e8d0
            cmd = " ".join(util.percent_escape(f) for f in command)
Packit d7e8d0
Packit d7e8d0
        errptr = gpgme.new_gpgme_error_t_p()
Packit d7e8d0
Packit d7e8d0
        err = gpgme.gpgme_op_assuan_transact_ext(
Packit Service 30b792
            self.wrapped, cmd, (weakref.ref(self), data_cb)
Packit Service 30b792
            if data_cb else None, (weakref.ref(self), inquire_cb)
Packit Service 30b792
            if inquire_cb else None, (weakref.ref(self), status_cb)
Packit Service 30b792
            if status_cb else None, errptr)
Packit d7e8d0
Packit d7e8d0
        if self._callback_excinfo:
Packit d7e8d0
            gpgme.gpg_raise_callback_exception(self)
Packit d7e8d0
Packit d7e8d0
        errorcheck(err)
Packit d7e8d0
Packit d7e8d0
        status = gpgme.gpgme_error_t_p_value(errptr)
Packit d7e8d0
        gpgme.delete_gpgme_error_t_p(errptr)
Packit d7e8d0
Packit d7e8d0
        return GPGMEError(status) if status != 0 else None
Packit d7e8d0
Packit d7e8d0
    def interact(self, key, func, sink=None, flags=0, fnc_value=None):
Packit d7e8d0
        """Interact with the engine
Packit d7e8d0
Packit d7e8d0
        This method can be used to edit keys and cards interactively.
Packit d7e8d0
        KEY is the key to edit, FUNC is called repeatedly with two
Packit d7e8d0
        unicode arguments, 'keyword' and 'args'.  See the GPGME manual
Packit d7e8d0
        for details.
Packit d7e8d0
Packit d7e8d0
        Keyword arguments:
Packit d7e8d0
        sink		-- if given, additional output is written here
Packit d7e8d0
        flags		-- use constants.INTERACT_CARD to edit a card
Packit d7e8d0
Packit d7e8d0
        Raises:
Packit d7e8d0
        GPGMEError	-- as signaled by the underlying library
Packit d7e8d0
Packit d7e8d0
        """
Packit Service 30b792
        if key is None:
Packit d7e8d0
            raise ValueError("First argument cannot be None")
Packit d7e8d0
Packit Service 30b792
        if sink is None:
Packit d7e8d0
            sink = Data()
Packit d7e8d0
Packit d7e8d0
        if fnc_value:
Packit d7e8d0
            opaquedata = (weakref.ref(self), func, fnc_value)
Packit d7e8d0
        else:
Packit d7e8d0
            opaquedata = (weakref.ref(self), func)
Packit d7e8d0
Packit Service 30b792
        result = gpgme.gpgme_op_interact(self.wrapped, key, flags, opaquedata,
Packit Service 30b792
                                         sink)
Packit d7e8d0
        if self._callback_excinfo:
Packit d7e8d0
            gpgme.gpg_raise_callback_exception(self)
Packit d7e8d0
        errorcheck(result)
Packit d7e8d0
Packit d7e8d0
    @property
Packit d7e8d0
    def signers(self):
Packit d7e8d0
        """Keys used for signing"""
Packit d7e8d0
        return [self.signers_enum(i) for i in range(self.signers_count())]
Packit Service 30b792
Packit d7e8d0
    @signers.setter
Packit d7e8d0
    def signers(self, signers):
Packit d7e8d0
        old = self.signers
Packit d7e8d0
        self.signers_clear()
Packit d7e8d0
        try:
Packit d7e8d0
            for key in signers:
Packit d7e8d0
                self.signers_add(key)
Packit d7e8d0
        except:
Packit d7e8d0
            self.signers = old
Packit d7e8d0
            raise
Packit d7e8d0
Packit d7e8d0
    @property
Packit d7e8d0
    def pinentry_mode(self):
Packit d7e8d0
        """Pinentry mode"""
Packit d7e8d0
        return self.get_pinentry_mode()
Packit Service 30b792
Packit d7e8d0
    @pinentry_mode.setter
Packit d7e8d0
    def pinentry_mode(self, value):
Packit d7e8d0
        self.set_pinentry_mode(value)
Packit d7e8d0
Packit d7e8d0
    @property
Packit d7e8d0
    def protocol(self):
Packit d7e8d0
        """Protocol to use"""
Packit d7e8d0
        return self.get_protocol()
Packit Service 30b792
Packit d7e8d0
    @protocol.setter
Packit d7e8d0
    def protocol(self, value):
Packit d7e8d0
        errorcheck(gpgme.gpgme_engine_check_version(value))
Packit d7e8d0
        self.set_protocol(value)
Packit d7e8d0
Packit d7e8d0
    @property
Packit d7e8d0
    def home_dir(self):
Packit d7e8d0
        """Engine's home directory"""
Packit d7e8d0
        return self.engine_info.home_dir
Packit Service 30b792
Packit d7e8d0
    @home_dir.setter
Packit d7e8d0
    def home_dir(self, value):
Packit d7e8d0
        self.set_engine_info(self.protocol, home_dir=value)
Packit d7e8d0
Packit d7e8d0
    _ctype = 'gpgme_ctx_t'
Packit d7e8d0
    _cprefix = 'gpgme_'
Packit d7e8d0
Packit d7e8d0
    def _errorcheck(self, name):
Packit d7e8d0
        """This function should list all functions returning gpgme_error_t"""
Packit d7e8d0
        # The list of functions is created using:
Packit d7e8d0
        #
Packit d7e8d0
        # $ grep '^gpgme_error_t ' obj/lang/python/python3.5-gpg/gpgme.h \
Packit Service 30b792
        # | grep -v _op_ | awk "/\(gpgme_ctx/ { printf (\"'%s',\\n\", \$2) } "
Packit Service 30b792
        return ((name.startswith('gpgme_op_') and not
Packit Service 30b792
                 name.endswith('_result')) or name in {
Packit Service 30b792
                     'gpgme_new', 'gpgme_set_ctx_flag', 'gpgme_set_protocol',
Packit Service 30b792
                     'gpgme_set_sub_protocol', 'gpgme_set_keylist_mode',
Packit Service 30b792
                     'gpgme_set_pinentry_mode', 'gpgme_set_locale',
Packit Service 30b792
                     'gpgme_ctx_set_engine_info', 'gpgme_signers_add',
Packit Service 30b792
                     'gpgme_sig_notation_add', 'gpgme_set_sender',
Packit Service 30b792
                     'gpgme_cancel', 'gpgme_cancel_async', 'gpgme_get_key',
Packit Service 30b792
                     'gpgme_get_sig_key',
Packit d7e8d0
                })
Packit d7e8d0
Packit d7e8d0
    _boolean_properties = {'armor', 'textmode', 'offline'}
Packit d7e8d0
Packit d7e8d0
    def __del__(self):
Packit d7e8d0
        if not gpgme:
Packit d7e8d0
            # At interpreter shutdown, gpgme is set to NONE.
Packit d7e8d0
            return
Packit d7e8d0
Packit d7e8d0
        self._free_passcb()
Packit d7e8d0
        self._free_progresscb()
Packit d7e8d0
        self._free_statuscb()
Packit d7e8d0
        if self.own and self.wrapped and gpgme.gpgme_release:
Packit d7e8d0
            gpgme.gpgme_release(self.wrapped)
Packit d7e8d0
            self.wrapped = None
Packit d7e8d0
Packit d7e8d0
    # Implement the context manager protocol.
Packit d7e8d0
    def __enter__(self):
Packit d7e8d0
        return self
Packit Service 30b792
Packit d7e8d0
    def __exit__(self, type, value, tb):
Packit d7e8d0
        self.__del__()
Packit d7e8d0
Packit d7e8d0
    def op_keylist_all(self, *args, **kwargs):
Packit d7e8d0
        self.op_keylist_start(*args, **kwargs)
Packit d7e8d0
        key = self.op_keylist_next()
Packit d7e8d0
        while key:
Packit d7e8d0
            yield key
Packit d7e8d0
            key = self.op_keylist_next()
Packit d7e8d0
        self.op_keylist_end()
Packit d7e8d0
Packit d7e8d0
    def op_keylist_next(self):
Packit d7e8d0
        """Returns the next key in the list created
Packit d7e8d0
        by a call to op_keylist_start().  The object returned
Packit d7e8d0
        is of type Key."""
Packit d7e8d0
        ptr = gpgme.new_gpgme_key_t_p()
Packit d7e8d0
        try:
Packit d7e8d0
            errorcheck(gpgme.gpgme_op_keylist_next(self.wrapped, ptr))
Packit d7e8d0
            key = gpgme.gpgme_key_t_p_value(ptr)
Packit d7e8d0
        except errors.GPGMEError as excp:
Packit d7e8d0
            key = None
Packit d7e8d0
            if excp.getcode() != errors.EOF:
Packit d7e8d0
                raise excp
Packit d7e8d0
        gpgme.delete_gpgme_key_t_p(ptr)
Packit d7e8d0
        if key:
Packit d7e8d0
            key.__del__ = lambda self: gpgme.gpgme_key_unref(self)
Packit d7e8d0
            return key
Packit d7e8d0
Packit d7e8d0
    def get_key(self, fpr, secret=False):
Packit d7e8d0
        """Get a key given a fingerprint
Packit d7e8d0
Packit d7e8d0
        Keyword arguments:
Packit d7e8d0
        secret		-- to request a secret key
Packit d7e8d0
Packit d7e8d0
        Returns:
Packit d7e8d0
                        -- the matching key
Packit d7e8d0
Packit d7e8d0
        Raises:
Packit d7e8d0
        KeyError	-- if the key was not found
Packit d7e8d0
        GPGMEError	-- as signaled by the underlying library
Packit d7e8d0
Packit d7e8d0
        """
Packit d7e8d0
        ptr = gpgme.new_gpgme_key_t_p()
Packit d7e8d0
Packit d7e8d0
        try:
Packit d7e8d0
            errorcheck(gpgme.gpgme_get_key(self.wrapped, fpr, ptr, secret))
Packit d7e8d0
        except errors.GPGMEError as e:
Packit d7e8d0
            if e.getcode() == errors.EOF:
Packit d7e8d0
                raise errors.KeyNotFound(fpr)
Packit d7e8d0
            raise e
Packit d7e8d0
Packit d7e8d0
        key = gpgme.gpgme_key_t_p_value(ptr)
Packit d7e8d0
        gpgme.delete_gpgme_key_t_p(ptr)
Packit d7e8d0
        assert key
Packit d7e8d0
        key.__del__ = lambda self: gpgme.gpgme_key_unref(self)
Packit d7e8d0
        return key
Packit d7e8d0
Packit d7e8d0
    def op_trustlist_all(self, *args, **kwargs):
Packit d7e8d0
        self.op_trustlist_start(*args, **kwargs)
Packit d7e8d0
        trust = self.op_trustlist_next()
Packit d7e8d0
        while trust:
Packit d7e8d0
            yield trust
Packit d7e8d0
            trust = self.op_trustlist_next()
Packit d7e8d0
        self.op_trustlist_end()
Packit d7e8d0
Packit d7e8d0
    def op_trustlist_next(self):
Packit d7e8d0
        """Returns the next trust item in the list created
Packit d7e8d0
        by a call to op_trustlist_start().  The object returned
Packit d7e8d0
        is of type TrustItem."""
Packit d7e8d0
        ptr = gpgme.new_gpgme_trust_item_t_p()
Packit d7e8d0
        try:
Packit d7e8d0
            errorcheck(gpgme.gpgme_op_trustlist_next(self.wrapped, ptr))
Packit d7e8d0
            trust = gpgme.gpgme_trust_item_t_p_value(ptr)
Packit d7e8d0
        except errors.GPGMEError as excp:
Packit d7e8d0
            trust = None
Packit d7e8d0
            if excp.getcode() != errors.EOF:
Packit d7e8d0
                raise
Packit d7e8d0
        gpgme.delete_gpgme_trust_item_t_p(ptr)
Packit d7e8d0
        return trust
Packit d7e8d0
Packit d7e8d0
    def set_passphrase_cb(self, func, hook=None):
Packit d7e8d0
        """Sets the passphrase callback to the function specified by func.
Packit d7e8d0
Packit d7e8d0
        When the system needs a passphrase, it will call func with three args:
Packit d7e8d0
        hint, a string describing the key it needs the passphrase for;
Packit d7e8d0
        desc, a string describing the passphrase it needs;
Packit d7e8d0
        prev_bad, a boolean equal True if this is a call made after
Packit d7e8d0
        unsuccessful previous attempt.
Packit d7e8d0
Packit d7e8d0
        If hook has a value other than None it will be passed into the func
Packit d7e8d0
        as a forth argument.
Packit d7e8d0
Packit d7e8d0
        Please see the GPGME manual for more information.
Packit d7e8d0
        """
Packit Service 30b792
        if func is None:
Packit d7e8d0
            hookdata = None
Packit d7e8d0
        else:
Packit Service 30b792
            if hook is None:
Packit d7e8d0
                hookdata = (weakref.ref(self), func)
Packit d7e8d0
            else:
Packit d7e8d0
                hookdata = (weakref.ref(self), func, hook)
Packit d7e8d0
        gpgme.gpg_set_passphrase_cb(self, hookdata)
Packit d7e8d0
Packit d7e8d0
    def _free_passcb(self):
Packit d7e8d0
        if gpgme.gpg_set_passphrase_cb:
Packit d7e8d0
            self.set_passphrase_cb(None)
Packit d7e8d0
Packit d7e8d0
    def set_progress_cb(self, func, hook=None):
Packit d7e8d0
        """Sets the progress meter callback to the function specified by FUNC.
Packit d7e8d0
        If FUNC is None, the callback will be cleared.
Packit d7e8d0
Packit d7e8d0
        This function will be called to provide an interactive update
Packit d7e8d0
        of the system's progress.  The function will be called with
Packit d7e8d0
        three arguments, type, total, and current.  If HOOK is not
Packit d7e8d0
        None, it will be supplied as fourth argument.
Packit d7e8d0
Packit d7e8d0
        Please see the GPGME manual for more information.
Packit d7e8d0
Packit d7e8d0
        """
Packit Service 30b792
        if func is None:
Packit d7e8d0
            hookdata = None
Packit d7e8d0
        else:
Packit Service 30b792
            if hook is None:
Packit d7e8d0
                hookdata = (weakref.ref(self), func)
Packit d7e8d0
            else:
Packit d7e8d0
                hookdata = (weakref.ref(self), func, hook)
Packit d7e8d0
        gpgme.gpg_set_progress_cb(self, hookdata)
Packit d7e8d0
Packit d7e8d0
    def _free_progresscb(self):
Packit d7e8d0
        if gpgme.gpg_set_progress_cb:
Packit d7e8d0
            self.set_progress_cb(None)
Packit d7e8d0
Packit d7e8d0
    def set_status_cb(self, func, hook=None):
Packit d7e8d0
        """Sets the status callback to the function specified by FUNC.  If
Packit d7e8d0
        FUNC is None, the callback will be cleared.
Packit d7e8d0
Packit d7e8d0
        The function will be called with two arguments, keyword and
Packit d7e8d0
        args.  If HOOK is not None, it will be supplied as third
Packit d7e8d0
        argument.
Packit d7e8d0
Packit d7e8d0
        Please see the GPGME manual for more information.
Packit d7e8d0
Packit d7e8d0
        """
Packit Service 30b792
        if func is None:
Packit d7e8d0
            hookdata = None
Packit d7e8d0
        else:
Packit Service 30b792
            if hook is None:
Packit d7e8d0
                hookdata = (weakref.ref(self), func)
Packit d7e8d0
            else:
Packit d7e8d0
                hookdata = (weakref.ref(self), func, hook)
Packit d7e8d0
        gpgme.gpg_set_status_cb(self, hookdata)
Packit d7e8d0
Packit d7e8d0
    def _free_statuscb(self):
Packit d7e8d0
        if gpgme.gpg_set_status_cb:
Packit d7e8d0
            self.set_status_cb(None)
Packit d7e8d0
Packit d7e8d0
    @property
Packit d7e8d0
    def engine_info(self):
Packit d7e8d0
        """Configuration of the engine currently in use"""
Packit d7e8d0
        p = self.protocol
Packit d7e8d0
        infos = [i for i in self.get_engine_info() if i.protocol == p]
Packit d7e8d0
        assert len(infos) == 1
Packit d7e8d0
        return infos[0]
Packit d7e8d0
Packit d7e8d0
    def get_engine_info(self):
Packit d7e8d0
        """Get engine configuration
Packit d7e8d0
Packit d7e8d0
        Returns information about all configured and installed
Packit d7e8d0
        engines.
Packit d7e8d0
Packit d7e8d0
        Returns:
Packit d7e8d0
        infos		-- a list of engine infos
Packit d7e8d0
Packit d7e8d0
        """
Packit d7e8d0
        return gpgme.gpgme_ctx_get_engine_info(self.wrapped)
Packit d7e8d0
Packit d7e8d0
    def set_engine_info(self, proto, file_name=None, home_dir=None):
Packit d7e8d0
        """Change engine configuration
Packit d7e8d0
Packit d7e8d0
        Changes the configuration of the crypto engine implementing
Packit d7e8d0
        the protocol 'proto' for the context.
Packit d7e8d0
Packit d7e8d0
        Keyword arguments:
Packit d7e8d0
        file_name	-- engine program file name (unchanged if None)
Packit d7e8d0
        home_dir	-- configuration directory (unchanged if None)
Packit d7e8d0
Packit d7e8d0
        """
Packit d7e8d0
        self.ctx_set_engine_info(proto, file_name, home_dir)
Packit d7e8d0
Packit d7e8d0
    def wait(self, hang):
Packit d7e8d0
        """Wait for asynchronous call to finish. Wait forever if hang is True.
Packit d7e8d0
        Raises an exception on errors.
Packit d7e8d0
Packit d7e8d0
        Please read the GPGME manual for more information.
Packit d7e8d0
Packit d7e8d0
        """
Packit d7e8d0
        ptr = gpgme.new_gpgme_error_t_p()
Packit d7e8d0
        gpgme.gpgme_wait(self.wrapped, ptr, hang)
Packit d7e8d0
        status = gpgme.gpgme_error_t_p_value(ptr)
Packit d7e8d0
        gpgme.delete_gpgme_error_t_p(ptr)
Packit d7e8d0
        errorcheck(status)
Packit d7e8d0
Packit d7e8d0
    def op_edit(self, key, func, fnc_value, out):
Packit d7e8d0
        """Start key editing using supplied callback function
Packit d7e8d0
Packit d7e8d0
        Note: This interface is deprecated and will be removed with
Packit d7e8d0
        GPGME 1.8.  Please use .interact instead.  Furthermore, we
Packit d7e8d0
        implement this using gpgme_op_interact, so callbacks will get
Packit d7e8d0
        called with string keywords instead of numeric status
Packit d7e8d0
        messages.  Code that is using constants.STATUS_X or
Packit d7e8d0
        constants.status.X will continue to work, whereas code using
Packit d7e8d0
        magic numbers will break as a result.
Packit d7e8d0
Packit d7e8d0
        """
Packit Service 30b792
        warnings.warn(
Packit Service 30b792
            "Call to deprecated method op_edit.", category=DeprecationWarning)
Packit d7e8d0
        return self.interact(key, func, sink=out, fnc_value=fnc_value)
Packit d7e8d0
Packit d7e8d0
Packit d7e8d0
class Data(GpgmeWrapper):
Packit d7e8d0
    """Data buffer
Packit d7e8d0
Packit d7e8d0
    A lot of data has to be exchanged between the user and the crypto
Packit d7e8d0
    engine, like plaintext messages, ciphertext, signatures and
Packit d7e8d0
    information about the keys.  The technical details about
Packit d7e8d0
    exchanging the data information are completely abstracted by
Packit d7e8d0
    GPGME.  The user provides and receives the data via `gpgme_data_t'
Packit d7e8d0
    objects, regardless of the communication protocol between GPGME
Packit d7e8d0
    and the crypto engine in use.
Packit d7e8d0
Packit d7e8d0
    This Data class is the implementation of the GpgmeData objects.
Packit d7e8d0
Packit d7e8d0
    Please see the information about __init__ for instantiation.
Packit d7e8d0
Packit d7e8d0
    """
Packit d7e8d0
Packit d7e8d0
    _ctype = 'gpgme_data_t'
Packit d7e8d0
    _cprefix = 'gpgme_data_'
Packit d7e8d0
Packit d7e8d0
    def _errorcheck(self, name):
Packit d7e8d0
        """This function should list all functions returning gpgme_error_t"""
Packit d7e8d0
        # This list is compiled using
Packit d7e8d0
        #
Packit d7e8d0
        # $ grep -v '^gpgme_error_t ' obj/lang/python/python3.5-gpg/gpgme.h \
Packit Service 30b792
        #   | awk "/\(gpgme_data_t/ { printf (\"'%s',\\n\", \$2) } " \
Packit Service 30b792
        #   | sed "s/'\\*/'/"
Packit d7e8d0
        return name not in {
Packit d7e8d0
            'gpgme_data_read',
Packit d7e8d0
            'gpgme_data_write',
Packit d7e8d0
            'gpgme_data_seek',
Packit d7e8d0
            'gpgme_data_release',
Packit d7e8d0
            'gpgme_data_release_and_get_mem',
Packit d7e8d0
            'gpgme_data_get_encoding',
Packit d7e8d0
            'gpgme_data_get_file_name',
Packit Service 30b792
            'gpgme_data_set_flag',
Packit d7e8d0
            'gpgme_data_identify',
Packit d7e8d0
        }
Packit d7e8d0
Packit Service 30b792
    def __init__(self,
Packit Service 30b792
                 string=None,
Packit Service 30b792
                 file=None,
Packit Service 30b792
                 offset=None,
Packit Service 30b792
                 length=None,
Packit Service 30b792
                 cbs=None,
Packit Service 30b792
                 copy=True):
Packit d7e8d0
        """Initialize a new gpgme_data_t object.
Packit d7e8d0
Packit d7e8d0
        If no args are specified, make it an empty object.
Packit d7e8d0
Packit d7e8d0
        If string alone is specified, initialize it with the data
Packit d7e8d0
        contained there.
Packit d7e8d0
Packit d7e8d0
        If file, offset, and length are all specified, file must
Packit d7e8d0
        be either a filename or a file-like object, and the object
Packit d7e8d0
        will be initialized by reading the specified chunk from the file.
Packit d7e8d0
Packit d7e8d0
        If cbs is specified, it MUST be a tuple of the form:
Packit d7e8d0
Packit d7e8d0
        (read_cb, write_cb, seek_cb, release_cb[, hook])
Packit d7e8d0
Packit d7e8d0
        where the first four items are functions implementing reading,
Packit d7e8d0
        writing, seeking the data, and releasing any resources once
Packit d7e8d0
        the data object is deallocated.  The functions must match the
Packit d7e8d0
        following prototypes:
Packit d7e8d0
Packit d7e8d0
            def read(amount, hook=None):
Packit d7e8d0
                return 
Packit d7e8d0
Packit d7e8d0
            def write(data, hook=None):
Packit d7e8d0
                return <the number of bytes written>
Packit d7e8d0
Packit d7e8d0
            def seek(offset, whence, hook=None):
Packit d7e8d0
                return <the new file position>
Packit d7e8d0
Packit d7e8d0
            def release(hook=None):
Packit d7e8d0
                <return value and exceptions are ignored>
Packit d7e8d0
Packit d7e8d0
        The functions may be bound methods.  In that case, you can
Packit d7e8d0
        simply use the 'self' reference instead of using a hook.
Packit d7e8d0
Packit d7e8d0
        If file is specified without any other arguments, then
Packit d7e8d0
        it must be a filename, and the object will be initialized from
Packit d7e8d0
        that file.
Packit d7e8d0
Packit d7e8d0
        """
Packit d7e8d0
        super(Data, self).__init__(None)
Packit d7e8d0
        self.data_cbs = None
Packit d7e8d0
Packit Service 30b792
        if cbs is not None:
Packit d7e8d0
            self.new_from_cbs(*cbs)
Packit Service 30b792
        elif string is not None:
Packit d7e8d0
            self.new_from_mem(string, copy)
Packit Service 30b792
        elif file is not None and offset is not None and length is not None:
Packit d7e8d0
            self.new_from_filepart(file, offset, length)
Packit Service 30b792
        elif file is not None:
Packit d7e8d0
            if util.is_a_string(file):
Packit d7e8d0
                self.new_from_file(file, copy)
Packit d7e8d0
            else:
Packit d7e8d0
                self.new_from_fd(file)
Packit d7e8d0
        else:
Packit d7e8d0
            self.new()
Packit d7e8d0
Packit d7e8d0
    def __del__(self):
Packit d7e8d0
        if not gpgme:
Packit d7e8d0
            # At interpreter shutdown, gpgme is set to NONE.
Packit d7e8d0
            return
Packit d7e8d0
Packit Service 30b792
        if self.wrapped is not None and gpgme.gpgme_data_release:
Packit d7e8d0
            gpgme.gpgme_data_release(self.wrapped)
Packit d7e8d0
            if self._callback_excinfo:
Packit d7e8d0
                gpgme.gpg_raise_callback_exception(self)
Packit d7e8d0
            self.wrapped = None
Packit d7e8d0
        self._free_datacbs()
Packit d7e8d0
Packit d7e8d0
    # Implement the context manager protocol.
Packit d7e8d0
    def __enter__(self):
Packit d7e8d0
        return self
Packit Service 30b792
Packit d7e8d0
    def __exit__(self, type, value, tb):
Packit d7e8d0
        self.__del__()
Packit d7e8d0
Packit d7e8d0
    def _free_datacbs(self):
Packit d7e8d0
        self._data_cbs = None
Packit d7e8d0
Packit d7e8d0
    def new(self):
Packit d7e8d0
        tmp = gpgme.new_gpgme_data_t_p()
Packit d7e8d0
        errorcheck(gpgme.gpgme_data_new(tmp))
Packit d7e8d0
        self.wrapped = gpgme.gpgme_data_t_p_value(tmp)
Packit d7e8d0
        gpgme.delete_gpgme_data_t_p(tmp)
Packit d7e8d0
Packit d7e8d0
    def new_from_mem(self, string, copy=True):
Packit d7e8d0
        tmp = gpgme.new_gpgme_data_t_p()
Packit Service 30b792
        errorcheck(
Packit Service 30b792
            gpgme.gpgme_data_new_from_mem(tmp, string, len(string), copy))
Packit d7e8d0
        self.wrapped = gpgme.gpgme_data_t_p_value(tmp)
Packit d7e8d0
        gpgme.delete_gpgme_data_t_p(tmp)
Packit d7e8d0
Packit d7e8d0
    def new_from_file(self, filename, copy=True):
Packit d7e8d0
        tmp = gpgme.new_gpgme_data_t_p()
Packit d7e8d0
        try:
Packit d7e8d0
            errorcheck(gpgme.gpgme_data_new_from_file(tmp, filename, copy))
Packit d7e8d0
        except errors.GPGMEError as e:
Packit d7e8d0
            if e.getcode() == errors.INV_VALUE and not copy:
Packit d7e8d0
                raise ValueError("delayed reads are not yet supported")
Packit d7e8d0
            else:
Packit d7e8d0
                raise e
Packit d7e8d0
        self.wrapped = gpgme.gpgme_data_t_p_value(tmp)
Packit d7e8d0
        gpgme.delete_gpgme_data_t_p(tmp)
Packit d7e8d0
Packit d7e8d0
    def new_from_cbs(self, read_cb, write_cb, seek_cb, release_cb, hook=None):
Packit d7e8d0
        tmp = gpgme.new_gpgme_data_t_p()
Packit Service 30b792
        if hook is not None:
Packit Service 30b792
            hookdata = (weakref.ref(self), read_cb, write_cb, seek_cb,
Packit Service 30b792
                        release_cb, hook)
Packit d7e8d0
        else:
Packit Service 30b792
            hookdata = (weakref.ref(self), read_cb, write_cb, seek_cb,
Packit Service 30b792
                        release_cb)
Packit d7e8d0
        gpgme.gpg_data_new_from_cbs(self, hookdata, tmp)
Packit d7e8d0
        self.wrapped = gpgme.gpgme_data_t_p_value(tmp)
Packit d7e8d0
        gpgme.delete_gpgme_data_t_p(tmp)
Packit d7e8d0
Packit d7e8d0
    def new_from_filepart(self, file, offset, length):
Packit d7e8d0
        """This wraps the GPGME gpgme_data_new_from_filepart() function.
Packit d7e8d0
        The argument "file" may be:
Packit d7e8d0
Packit d7e8d0
        * a string specifying a file name, or
Packit d7e8d0
        * a file-like object supporting the fileno() and the mode attribute.
Packit d7e8d0
Packit d7e8d0
        """
Packit d7e8d0
Packit d7e8d0
        tmp = gpgme.new_gpgme_data_t_p()
Packit d7e8d0
        filename = None
Packit d7e8d0
        fp = None
Packit d7e8d0
Packit d7e8d0
        if util.is_a_string(file):
Packit d7e8d0
            filename = file
Packit d7e8d0
        else:
Packit d7e8d0
            fp = gpgme.fdopen(file.fileno(), file.mode)
Packit Service 30b792
            if fp is None:
Packit Service 30b792
                raise ValueError("Failed to open file from %s arg %s" % (str(
Packit Service 30b792
                    type(file)), str(file)))
Packit d7e8d0
Packit Service 30b792
        errorcheck(
Packit Service 30b792
            gpgme.gpgme_data_new_from_filepart(tmp, filename, fp, offset,
Packit Service 30b792
                                               length))
Packit d7e8d0
        self.wrapped = gpgme.gpgme_data_t_p_value(tmp)
Packit d7e8d0
        gpgme.delete_gpgme_data_t_p(tmp)
Packit d7e8d0
Packit d7e8d0
    def new_from_fd(self, file):
Packit d7e8d0
        """This wraps the GPGME gpgme_data_new_from_fd() function.  The
Packit d7e8d0
        argument "file" must be a file-like object, supporting the
Packit d7e8d0
        fileno() method.
Packit d7e8d0
Packit d7e8d0
        """
Packit d7e8d0
        tmp = gpgme.new_gpgme_data_t_p()
Packit d7e8d0
        errorcheck(gpgme.gpgme_data_new_from_fd(tmp, file.fileno()))
Packit d7e8d0
        self.wrapped = gpgme.gpgme_data_t_p_value(tmp)
Packit d7e8d0
        gpgme.delete_gpgme_data_t_p(tmp)
Packit d7e8d0
Packit d7e8d0
    def new_from_stream(self, file):
Packit d7e8d0
        """This wrap around gpgme_data_new_from_stream is an alias for
Packit Service 30b792
        new_from_fd() method since in python there's no difference
Packit Service 30b792
        between file stream and file descriptor."""
Packit d7e8d0
        self.new_from_fd(file)
Packit d7e8d0
Packit Service 30b792
    def new_from_estream(self, file):
Packit Service 30b792
        """This wrap around gpgme_data_new_from_estream is an alias for
Packit Service 30b792
        new_from_fd() method since in python there's no difference
Packit Service 30b792
        between file stream and file descriptor, but using fd broke."""
Packit Service 30b792
        self.new_from_stream(file)
Packit Service 30b792
Packit d7e8d0
    def write(self, buffer):
Packit d7e8d0
        """Write buffer given as string or bytes.
Packit d7e8d0
Packit d7e8d0
        If a string is given, it is implicitly encoded using UTF-8."""
Packit d7e8d0
        written = gpgme.gpgme_data_write(self.wrapped, buffer)
Packit d7e8d0
        if written < 0:
Packit d7e8d0
            if self._callback_excinfo:
Packit d7e8d0
                gpgme.gpg_raise_callback_exception(self)
Packit d7e8d0
            else:
Packit d7e8d0
                raise GPGMEError.fromSyserror()
Packit d7e8d0
        return written
Packit d7e8d0
Packit Service 30b792
    def read(self, size=-1):
Packit d7e8d0
        """Read at most size bytes, returned as bytes.
Packit d7e8d0
Packit d7e8d0
        If the size argument is negative or omitted, read until EOF is reached.
Packit d7e8d0
Packit d7e8d0
        Returns the data read, or the empty string if there was no data
Packit d7e8d0
        to read before EOF was reached."""
Packit d7e8d0
Packit d7e8d0
        if size == 0:
Packit d7e8d0
            return ''
Packit d7e8d0
Packit d7e8d0
        if size > 0:
Packit d7e8d0
            try:
Packit d7e8d0
                result = gpgme.gpgme_data_read(self.wrapped, size)
Packit d7e8d0
            except:
Packit d7e8d0
                if self._callback_excinfo:
Packit d7e8d0
                    gpgme.gpg_raise_callback_exception(self)
Packit d7e8d0
                else:
Packit d7e8d0
                    raise
Packit d7e8d0
            return result
Packit d7e8d0
        else:
Packit d7e8d0
            chunks = []
Packit d7e8d0
            while True:
Packit d7e8d0
                try:
Packit d7e8d0
                    result = gpgme.gpgme_data_read(self.wrapped, 4096)
Packit d7e8d0
                except:
Packit d7e8d0
                    if self._callback_excinfo:
Packit d7e8d0
                        gpgme.gpg_raise_callback_exception(self)
Packit d7e8d0
                    else:
Packit d7e8d0
                        raise
Packit d7e8d0
                if len(result) == 0:
Packit d7e8d0
                    break
Packit d7e8d0
                chunks.append(result)
Packit d7e8d0
            return b''.join(chunks)
Packit d7e8d0
Packit Service 30b792
Packit d7e8d0
def pubkey_algo_string(subkey):
Packit d7e8d0
    """Return short algorithm string
Packit d7e8d0
Packit d7e8d0
    Return a public key algorithm string (e.g. "rsa2048") for a given
Packit d7e8d0
    SUBKEY.
Packit d7e8d0
Packit d7e8d0
    Returns:
Packit d7e8d0
    algo      - a string
Packit d7e8d0
Packit d7e8d0
    """
Packit d7e8d0
    return gpgme.gpgme_pubkey_algo_string(subkey)
Packit d7e8d0
Packit Service 30b792
Packit d7e8d0
def pubkey_algo_name(algo):
Packit d7e8d0
    """Return name of public key algorithm
Packit d7e8d0
Packit d7e8d0
    Return the name of the public key algorithm for a given numeric
Packit d7e8d0
    algorithm id ALGO (cf. RFC4880).
Packit d7e8d0
Packit d7e8d0
    Returns:
Packit d7e8d0
    algo      - a string
Packit d7e8d0
Packit d7e8d0
    """
Packit d7e8d0
    return gpgme.gpgme_pubkey_algo_name(algo)
Packit d7e8d0
Packit Service 30b792
Packit d7e8d0
def hash_algo_name(algo):
Packit d7e8d0
    """Return name of hash algorithm
Packit d7e8d0
Packit d7e8d0
    Return the name of the hash algorithm for a given numeric
Packit d7e8d0
    algorithm id ALGO (cf. RFC4880).
Packit d7e8d0
Packit d7e8d0
    Returns:
Packit d7e8d0
    algo      - a string
Packit d7e8d0
Packit d7e8d0
    """
Packit d7e8d0
    return gpgme.gpgme_hash_algo_name(algo)
Packit d7e8d0
Packit Service 30b792
Packit d7e8d0
def get_protocol_name(proto):
Packit d7e8d0
    """Get protocol description
Packit d7e8d0
Packit d7e8d0
    Get the string describing protocol PROTO.
Packit d7e8d0
Packit d7e8d0
    Returns:
Packit d7e8d0
    proto     - a string
Packit d7e8d0
Packit d7e8d0
    """
Packit d7e8d0
    return gpgme.gpgme_get_protocol_name(proto)
Packit d7e8d0
Packit Service 30b792
Packit d7e8d0
def addrspec_from_uid(uid):
Packit d7e8d0
    """Return the address spec
Packit d7e8d0
Packit d7e8d0
    Return the addr-spec (cf. RFC2822 section 4.3) from a user id UID.
Packit d7e8d0
Packit d7e8d0
    Returns:
Packit d7e8d0
    addr_spec - a string
Packit d7e8d0
Packit d7e8d0
    """
Packit d7e8d0
    return gpgme.gpgme_addrspec_from_uid(uid)
Packit d7e8d0
Packit Service 30b792
Packit d7e8d0
def check_version(version=None):
Packit d7e8d0
    return gpgme.gpgme_check_version(version)
Packit d7e8d0
Packit Service 30b792
Packit d7e8d0
# check_version also makes sure that several subsystems are properly
Packit d7e8d0
# initialized, and it must be run at least once before invoking any
Packit d7e8d0
# other function.  We do it here so that the user does not have to do
Packit d7e8d0
# it unless she really wants to check for a certain version.
Packit d7e8d0
check_version()
Packit d7e8d0
Packit Service 30b792
Packit Service 30b792
def engine_check_version(proto):
Packit d7e8d0
    try:
Packit d7e8d0
        errorcheck(gpgme.gpgme_engine_check_version(proto))
Packit d7e8d0
        return True
Packit d7e8d0
    except errors.GPGMEError:
Packit d7e8d0
        return False
Packit d7e8d0
Packit Service 30b792
Packit d7e8d0
def get_engine_info():
Packit d7e8d0
    ptr = gpgme.new_gpgme_engine_info_t_p()
Packit d7e8d0
    try:
Packit d7e8d0
        errorcheck(gpgme.gpgme_get_engine_info(ptr))
Packit d7e8d0
        info = gpgme.gpgme_engine_info_t_p_value(ptr)
Packit d7e8d0
    except errors.GPGMEError:
Packit d7e8d0
        info = None
Packit d7e8d0
    gpgme.delete_gpgme_engine_info_t_p(ptr)
Packit d7e8d0
    return info
Packit d7e8d0
Packit Service 30b792
Packit d7e8d0
def set_engine_info(proto, file_name, home_dir=None):
Packit d7e8d0
    """Changes the default configuration of the crypto engine implementing
Packit d7e8d0
    the protocol 'proto'. 'file_name' is the file name of
Packit d7e8d0
    the executable program implementing this protocol. 'home_dir' is the
Packit d7e8d0
    directory name of the configuration directory (engine's default is
Packit d7e8d0
    used if omitted)."""
Packit d7e8d0
    errorcheck(gpgme.gpgme_set_engine_info(proto, file_name, home_dir))
Packit d7e8d0
Packit Service 30b792
Packit d7e8d0
def set_locale(category, value):
Packit d7e8d0
    """Sets the default locale used by contexts"""
Packit d7e8d0
    errorcheck(gpgme.gpgme_set_locale(None, category, value))
Packit d7e8d0
Packit Service 30b792
Packit d7e8d0
def wait(hang):
Packit d7e8d0
    """Wait for asynchronous call on any Context  to finish.
Packit d7e8d0
    Wait forever if hang is True.
Packit d7e8d0
Packit d7e8d0
    For finished anynch calls it returns a tuple (status, context):
Packit d7e8d0
        status  - status return by asnynchronous call.
Packit d7e8d0
        context - context which caused this call to return.
Packit d7e8d0
Packit d7e8d0
    Please read the GPGME manual of more information."""
Packit d7e8d0
    ptr = gpgme.new_gpgme_error_t_p()
Packit d7e8d0
    context = gpgme.gpgme_wait(None, ptr, hang)
Packit d7e8d0
    status = gpgme.gpgme_error_t_p_value(ptr)
Packit d7e8d0
    gpgme.delete_gpgme_error_t_p(ptr)
Packit Service 30b792
    if context is None:
Packit d7e8d0
        errorcheck(status)
Packit d7e8d0
    else:
Packit d7e8d0
        context = Context(context)
Packit d7e8d0
    return (status, context)