"Fossies" - the Fresh Open Source Software Archive

Member "gpgme-1.15.1/lang/python/src/core.py" (8 Jan 2021, 62131 Bytes) of package /linux/privat/gpgme-1.15.1.tar.bz2:


As a special service "Fossies" has tried to format the requested source page into HTML format using (guessed) Python source code syntax highlighting (style: standard) with prefixed line numbers. Alternatively you can here view or download the uninterpreted source code file. For more information about "core.py" see the Fossies "Dox" file reference documentation and the latest Fossies "Diffs" side-by-side code changes report: 1.15.0_vs_1.15.1.

    1 # -*- coding: utf-8 -*-
    2 
    3 from __future__ import absolute_import, print_function, unicode_literals
    4 
    5 import re
    6 import os
    7 import warnings
    8 import weakref
    9 
   10 from . import gpgme
   11 from .errors import errorcheck, GPGMEError
   12 from . import constants
   13 from . import errors
   14 from . import util
   15 
   16 del absolute_import, print_function, unicode_literals
   17 
   18 # Copyright (C) 2016-2018 g10 Code GmbH
   19 # Copyright (C) 2004, 2008 Igor Belyi <belyi@users.sourceforge.net>
   20 # Copyright (C) 2002 John Goerzen <jgoerzen@complete.org>
   21 #
   22 #    This library is free software; you can redistribute it and/or
   23 #    modify it under the terms of the GNU Lesser General Public
   24 #    License as published by the Free Software Foundation; either
   25 #    version 2.1 of the License, or (at your option) any later version.
   26 #
   27 #    This library is distributed in the hope that it will be useful,
   28 #    but WITHOUT ANY WARRANTY; without even the implied warranty of
   29 #    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
   30 #    Lesser General Public License for more details.
   31 #
   32 #    You should have received a copy of the GNU Lesser General Public
   33 #    License along with this library; if not, write to the Free Software
   34 #    Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307  USA
   35 """Core functionality
   36 
   37 Core functionality of GPGME wrapped in a object-oriented fashion.
   38 Provides the 'Context' class for performing cryptographic operations,
   39 and the 'Data' class describing buffers of data.
   40 
   41 """
   42 
   43 
   44 class GpgmeWrapper(object):
   45     """Base wrapper class
   46 
   47     Not to be instantiated directly.
   48 
   49     """
   50 
   51     def __init__(self, wrapped):
   52         self._callback_excinfo = None
   53         self.wrapped = wrapped
   54 
   55     def __repr__(self):
   56         return '<{}/{!r}>'.format(
   57             super(GpgmeWrapper, self).__repr__(), self.wrapped)
   58 
   59     def __str__(self):
   60         acc = ['{}.{}'.format(__name__, self.__class__.__name__)]
   61         flags = [f for f in self._boolean_properties if getattr(self, f)]
   62         if flags:
   63             acc.append('({})'.format(' '.join(flags)))
   64 
   65         return '<{}>'.format(' '.join(acc))
   66 
   67     def __hash__(self):
   68         return hash(repr(self.wrapped))
   69 
   70     def __eq__(self, other):
   71         if other is None:
   72             return False
   73         else:
   74             return repr(self.wrapped) == repr(other.wrapped)
   75 
   76     @property
   77     def _ctype(self):
   78         """The name of the c type wrapped by this class
   79 
   80         Must be set by child classes.
   81 
   82         """
   83         raise NotImplementedError()
   84 
   85     @property
   86     def _cprefix(self):
   87         """The common prefix of c functions wrapped by this class
   88 
   89         Must be set by child classes.
   90 
   91         """
   92         raise NotImplementedError()
   93 
   94     def _errorcheck(self, name):
   95         """Must be implemented by child classes.
   96 
   97         This function must return a trueish value for all c functions
   98         returning gpgme_error_t."""
   99         raise NotImplementedError()
  100 
  101     """The set of all boolean properties"""
  102     _boolean_properties = set()
  103 
  104     def __wrap_boolean_property(self, key, do_set=False, value=None):
  105         get_func = getattr(gpgme, "{}get_{}".format(self._cprefix, key))
  106         set_func = getattr(gpgme, "{}set_{}".format(self._cprefix, key))
  107 
  108         def get(slf):
  109             return bool(get_func(slf.wrapped))
  110 
  111         def set_(slf, value):
  112             set_func(slf.wrapped, bool(value))
  113 
  114         p = property(get, set_, doc="{} flag".format(key))
  115         setattr(self.__class__, key, p)
  116 
  117         if do_set:
  118             set_(self, bool(value))
  119         else:
  120             return get(self)
  121 
  122     _munge_docstring = re.compile(r'gpgme_([^(]*)\(([^,]*), (.*\) -> .*)')
  123 
  124     def __getattr__(self, key):
  125         """On-the-fly generation of wrapper methods and properties"""
  126         if key[0] == '_' or self._cprefix is None:
  127             return None
  128 
  129         if key in self._boolean_properties:
  130             return self.__wrap_boolean_property(key)
  131 
  132         name = self._cprefix + key
  133         func = getattr(gpgme, name)
  134 
  135         if self._errorcheck(name):
  136 
  137             def _funcwrap(slf, *args):
  138                 result = func(slf.wrapped, *args)
  139                 if slf._callback_excinfo:
  140                     gpgme.gpg_raise_callback_exception(slf)
  141                 return errorcheck(result, name)
  142         else:
  143 
  144             def _funcwrap(slf, *args):
  145                 result = func(slf.wrapped, *args)
  146                 if slf._callback_excinfo:
  147                     gpgme.gpg_raise_callback_exception(slf)
  148                 return result
  149 
  150         doc_orig = getattr(func, "__doc__")
  151         if doc_orig:
  152             doc = self._munge_docstring.sub(r'\2.\1(\3', doc_orig)
  153         else:
  154             doc = None
  155 
  156         _funcwrap.__doc__ = doc
  157 
  158         # Monkey-patch the class.
  159         setattr(self.__class__, key, _funcwrap)
  160 
  161         # Bind the method to 'self'.
  162         def wrapper(*args):
  163             return _funcwrap(self, *args)
  164 
  165         wrapper.__doc__ = doc
  166 
  167         return wrapper
  168 
  169     def __setattr__(self, key, value):
  170         """On-the-fly generation of properties"""
  171         if key in self._boolean_properties:
  172             self.__wrap_boolean_property(key, True, value)
  173         else:
  174             super(GpgmeWrapper, self).__setattr__(key, value)
  175 
  176 
  177 class Context(GpgmeWrapper):
  178     """Context for cryptographic operations
  179 
  180     All cryptographic operations in GPGME are performed within a
  181     context, which contains the internal state of the operation as
  182     well as configuration parameters.  By using several contexts you
  183     can run several cryptographic operations in parallel, with
  184     different configuration.
  185 
  186     Access to a context must be synchronized.
  187 
  188     """
  189 
  190     def __init__(self,
  191                  armor=False,
  192                  textmode=False,
  193                  offline=False,
  194                  signers=[],
  195                  pinentry_mode=constants.PINENTRY_MODE_DEFAULT,
  196                  protocol=constants.PROTOCOL_OpenPGP,
  197                  wrapped=None,
  198                  home_dir=None):
  199         """Construct a context object
  200 
  201         Keyword arguments:
  202         armor       -- enable ASCII armoring (default False)
  203         textmode    -- enable canonical text mode (default False)
  204         offline     -- do not contact external key sources (default False)
  205         signers     -- list of keys used for signing (default [])
  206         pinentry_mode   -- pinentry mode (default PINENTRY_MODE_DEFAULT)
  207         protocol    -- protocol to use (default PROTOCOL_OpenPGP)
  208         home_dir        -- state directory (default is the engine default)
  209 
  210         """
  211         if wrapped:
  212             self.own = False
  213         else:
  214             tmp = gpgme.new_gpgme_ctx_t_p()
  215             errorcheck(gpgme.gpgme_new(tmp))
  216             wrapped = gpgme.gpgme_ctx_t_p_value(tmp)
  217             gpgme.delete_gpgme_ctx_t_p(tmp)
  218             self.own = True
  219         super(Context, self).__init__(wrapped)
  220         self.armor = armor
  221         self.textmode = textmode
  222         self.offline = offline
  223         self.signers = signers
  224         self.pinentry_mode = pinentry_mode
  225         self.protocol = protocol
  226         self.home_dir = home_dir
  227 
  228     def __read__(self, sink, data):
  229         """Read helper
  230 
  231         Helper function to retrieve the results of an operation, or
  232         None if SINK is given.
  233         """
  234         if sink or data is None:
  235             return None
  236         data.seek(0, os.SEEK_SET)
  237         return data.read()
  238 
  239     def __repr__(self):
  240         return ("Context(armor={0.armor}, "
  241                 "textmode={0.textmode}, offline={0.offline}, "
  242                 "signers={0.signers}, pinentry_mode={0.pinentry_mode}, "
  243                 "protocol={0.protocol}, home_dir={0.home_dir}"
  244                 ")").format(self)
  245 
  246     def encrypt(self,
  247                 plaintext,
  248                 recipients=[],
  249                 sign=True,
  250                 sink=None,
  251                 passphrase=None,
  252                 always_trust=False,
  253                 add_encrypt_to=False,
  254                 prepare=False,
  255                 expect_sign=False,
  256                 compress=True):
  257         """Encrypt data
  258 
  259         Encrypt the given plaintext for the given recipients.  If the
  260         list of recipients is empty, the data is encrypted
  261         symmetrically with a passphrase.
  262 
  263         The passphrase can be given as parameter, using a callback
  264         registered at the context, or out-of-band via pinentry.
  265 
  266         Keyword arguments:
  267         recipients  -- list of keys to encrypt to
  268         sign        -- sign plaintext (default True)
  269         sink        -- write result to sink instead of returning it
  270         passphrase  -- for symmetric encryption
  271         always_trust    -- always trust the keys (default False)
  272         add_encrypt_to  -- encrypt to configured additional keys (default False)
  273         prepare     -- (ui) prepare for encryption (default False)
  274         expect_sign -- (ui) prepare for signing (default False)
  275         compress    -- compress plaintext (default True)
  276 
  277         Returns:
  278         ciphertext  -- the encrypted data (or None if sink is given)
  279         result      -- additional information about the encryption
  280         sign_result -- additional information about the signature(s)
  281 
  282         Raises:
  283         InvalidRecipients -- if encryption using a particular key failed
  284         InvalidSigners  -- if signing using a particular key failed
  285         GPGMEError  -- as signaled by the underlying library
  286 
  287         """
  288         ciphertext = sink if sink else Data()
  289         flags = 0
  290         flags |= always_trust * constants.ENCRYPT_ALWAYS_TRUST
  291         flags |= (not add_encrypt_to) * constants.ENCRYPT_NO_ENCRYPT_TO
  292         flags |= prepare * constants.ENCRYPT_PREPARE
  293         flags |= expect_sign * constants.ENCRYPT_EXPECT_SIGN
  294         flags |= (not compress) * constants.ENCRYPT_NO_COMPRESS
  295 
  296         if passphrase is not None:
  297             old_pinentry_mode = self.pinentry_mode
  298             old_passphrase_cb = getattr(self, '_passphrase_cb', None)
  299             self.pinentry_mode = constants.PINENTRY_MODE_LOOPBACK
  300 
  301             def passphrase_cb(hint, desc, prev_bad, hook=None):
  302                 return passphrase
  303 
  304             self.set_passphrase_cb(passphrase_cb)
  305 
  306         try:
  307             if sign:
  308                 self.op_encrypt_sign(recipients, flags, plaintext, ciphertext)
  309             else:
  310                 self.op_encrypt(recipients, flags, plaintext, ciphertext)
  311         except errors.GPGMEError as e:
  312             result = self.op_encrypt_result()
  313             sig_result = self.op_sign_result() if sign else None
  314             results = (self.__read__(sink, ciphertext), result, sig_result)
  315             if e.getcode() == errors.UNUSABLE_PUBKEY:
  316                 if result.invalid_recipients:
  317                     raise errors.InvalidRecipients(
  318                         result.invalid_recipients,
  319                         error=e.error,
  320                         results=results)
  321             if e.getcode() == errors.UNUSABLE_SECKEY:
  322                 sig_result = self.op_sign_result()
  323                 if sig_result.invalid_signers:
  324                     raise errors.InvalidSigners(
  325                         sig_result.invalid_signers,
  326                         error=e.error,
  327                         results=results)
  328             # Otherwise, just raise the error, but attach the results
  329             # first.
  330             e.results = results
  331             raise e
  332         finally:
  333             if passphrase is not None:
  334                 self.pinentry_mode = old_pinentry_mode
  335                 if old_passphrase_cb:
  336                     self.set_passphrase_cb(*old_passphrase_cb[1:])
  337 
  338         result = self.op_encrypt_result()
  339         assert not result.invalid_recipients
  340         sig_result = self.op_sign_result() if sign else None
  341         assert not sig_result or not sig_result.invalid_signers
  342 
  343         return self.__read__(sink, ciphertext), result, sig_result
  344 
  345     def decrypt(self, ciphertext, sink=None, passphrase=None, verify=True):
  346         """Decrypt data
  347 
  348         Decrypt the given ciphertext and verify any signatures.  If
  349         VERIFY is an iterable of keys, the ciphertext must be signed
  350         by all those keys, otherwise a MissingSignatures error is
  351         raised.  Note: if VERIFY is an empty iterable, that is treated
  352         the same as passing verify=True (that is, verify signatures
  353         and return data about any valid signatures found, but no
  354         signatures are required and no MissingSignatures error will be
  355         raised).
  356 
  357         If the ciphertext is symmetrically encrypted using a
  358         passphrase, that passphrase can be given as parameter, using a
  359         callback registered at the context, or out-of-band via
  360         pinentry.
  361 
  362         Keyword arguments:
  363         sink            -- write result to sink instead of returning it
  364         passphrase      -- for symmetric decryption
  365         verify          -- check signatures (boolean or iterable of keys,
  366                            see above) (default True)
  367 
  368         Returns:
  369         plaintext       -- the decrypted data (or None if sink is given)
  370         result          -- additional information about the decryption
  371         verify_result   -- additional information about the valid
  372                            signature(s) found
  373 
  374         Raises:
  375         UnsupportedAlgorithm -- if an unsupported algorithm was used
  376         MissingSignatures    -- if expected signatures are missing or bad
  377         GPGMEError           -- as signaled by the underlying library
  378 
  379         """
  380         do_sig_verification = False
  381         required_keys = None
  382         plaintext = sink if sink else Data()
  383 
  384         if passphrase is not None:
  385             old_pinentry_mode = self.pinentry_mode
  386             old_passphrase_cb = getattr(self, '_passphrase_cb', None)
  387             self.pinentry_mode = constants.PINENTRY_MODE_LOOPBACK
  388 
  389             def passphrase_cb(hint, desc, prev_bad, hook=None):
  390                 return passphrase
  391 
  392             self.set_passphrase_cb(passphrase_cb)
  393 
  394         try:
  395             if isinstance(verify, bool):
  396                 do_sig_verification = verify
  397             elif verify is None:
  398                 warnings.warn(
  399                     "ctx.decrypt called with verify=None, should be bool or iterable (treating as False).",
  400                     category=DeprecationWarning)
  401                 do_sig_verification = False
  402             else:
  403                 # we hope this is an iterable:
  404                 required_keys = verify
  405                 do_sig_verification = True
  406 
  407             if do_sig_verification:
  408                 self.op_decrypt_verify(ciphertext, plaintext)
  409             else:
  410                 self.op_decrypt(ciphertext, plaintext)
  411         except errors.GPGMEError as e:
  412             result = self.op_decrypt_result()
  413             if do_sig_verification:
  414                 verify_result = self.op_verify_result()
  415             else:
  416                 verify_result = None
  417             # Just raise the error, but attach the results first.
  418             e.results = (self.__read__(sink, plaintext), result, verify_result)
  419             raise e
  420         finally:
  421             if passphrase is not None:
  422                 self.pinentry_mode = old_pinentry_mode
  423                 if old_passphrase_cb:
  424                     self.set_passphrase_cb(*old_passphrase_cb[1:])
  425 
  426         result = self.op_decrypt_result()
  427 
  428         if do_sig_verification:
  429             verify_result = self.op_verify_result()
  430         else:
  431             verify_result = None
  432 
  433         results = (self.__read__(sink, plaintext), result, verify_result)
  434 
  435         if result.unsupported_algorithm:
  436             raise errors.UnsupportedAlgorithm(result.unsupported_algorithm,
  437                                               results=results)
  438 
  439         if do_sig_verification:
  440             # filter out all invalid signatures
  441             verify_result.signatures = list(filter(lambda s: s.status == errors.NO_ERROR, verify_result.signatures))
  442             if required_keys is not None:
  443                 missing = []
  444                 for key in required_keys:
  445                     ok = False
  446                     for subkey in key.subkeys:
  447                         for sig in verify_result.signatures:
  448                             if sig.summary & constants.SIGSUM_VALID == 0:
  449                                 continue
  450                             if subkey.can_sign and subkey.fpr == sig.fpr:
  451                                 ok = True
  452                             break
  453                         if ok:
  454                             break
  455                     if not ok:
  456                         missing.append(key)
  457                 if missing:
  458                     raise errors.MissingSignatures(verify_result, missing,
  459                                                    results=results)
  460 
  461         return results
  462 
  463     def sign(self, data, sink=None, mode=constants.SIG_MODE_NORMAL):
  464         """Sign data
  465 
  466         Sign the given data with either the configured default local
  467         key, or the 'signers' keys of this context.
  468 
  469         Keyword arguments:
  470         mode        -- signature mode (default: normal, see below)
  471         sink        -- write result to sink instead of returning it
  472 
  473         Returns:
  474         either
  475           signed_data   -- encoded data and signature (normal mode)
  476           signature -- only the signature data (detached mode)
  477           cleartext -- data and signature as text (cleartext mode)
  478             (or None if sink is given)
  479         result      -- additional information about the signature(s)
  480 
  481         Raises:
  482         InvalidSigners  -- if signing using a particular key failed
  483         GPGMEError  -- as signaled by the underlying library
  484 
  485         """
  486         signeddata = sink if sink else Data()
  487 
  488         try:
  489             self.op_sign(data, signeddata, mode)
  490         except errors.GPGMEError as e:
  491             results = (self.__read__(sink, signeddata), self.op_sign_result())
  492             if e.getcode() == errors.UNUSABLE_SECKEY:
  493                 if results[1].invalid_signers:
  494                     raise errors.InvalidSigners(
  495                         results[1].invalid_signers,
  496                         error=e.error,
  497                         results=results)
  498             e.results = results
  499             raise e
  500 
  501         result = self.op_sign_result()
  502         assert not result.invalid_signers
  503 
  504         return self.__read__(sink, signeddata), result
  505 
  506     def verify(self, signed_data, signature=None, sink=None, verify=[]):
  507         """Verify signatures
  508 
  509         Verify signatures over data.  If VERIFY is an iterable of
  510         keys, the ciphertext must be signed by all those keys,
  511         otherwise an error is raised.
  512 
  513         Keyword arguments:
  514         signature   -- detached signature data
  515         sink        -- write result to sink instead of returning it
  516 
  517         Returns:
  518         data        -- the plain data
  519             (or None if sink is given, or we verified a detached signature)
  520         result      -- additional information about the signature(s)
  521 
  522         Raises:
  523         BadSignatures   -- if a bad signature is encountered
  524         MissingSignatures -- if expected signatures are missing or bad
  525         GPGMEError  -- as signaled by the underlying library
  526 
  527         """
  528         if signature:
  529             # Detached signature, we don't return the plain text.
  530             data = None
  531         else:
  532             data = sink if sink else Data()
  533 
  534         try:
  535             if signature:
  536                 self.op_verify(signature, signed_data, None)
  537             else:
  538                 self.op_verify(signed_data, None, data)
  539         except errors.GPGMEError as e:
  540             # Just raise the error, but attach the results first.
  541             e.results = (self.__read__(sink, data), self.op_verify_result())
  542             raise e
  543 
  544         results = (self.__read__(sink, data), self.op_verify_result())
  545         if any(s.status != errors.NO_ERROR for s in results[1].signatures):
  546             raise errors.BadSignatures(results[1], results=results)
  547 
  548         missing = list()
  549         for key in verify:
  550             ok = False
  551             for subkey in key.subkeys:
  552                 for sig in results[1].signatures:
  553                     if sig.summary & constants.SIGSUM_VALID == 0:
  554                         continue
  555                     if subkey.can_sign and subkey.fpr == sig.fpr:
  556                         ok = True
  557                         break
  558                 if ok:
  559                     break
  560             if not ok:
  561                 missing.append(key)
  562         if missing:
  563             raise errors.MissingSignatures(
  564                 results[1], missing, results=results)
  565 
  566         return results
  567 
  568     def key_import(self, data):
  569         """Import data
  570 
  571         Imports the given data into the Context.
  572 
  573         Returns:
  574                 -- an object describing the results of imported or updated
  575                    keys
  576 
  577         Raises:
  578         TypeError      -- Very rarely.
  579         GPGMEError     -- as signaled by the underlying library:
  580 
  581                           Import status errors, when they occur, will usually
  582                           be of NODATA.  NO_PUBKEY indicates something
  583                           managed to run the function without any
  584                           arguments, while an argument of None triggers
  585                           the first NODATA of errors.GPGME in the
  586                           exception.
  587         """
  588         try:
  589             self.op_import(data)
  590             result = self.op_import_result()
  591             if result.considered == 0:
  592                 status = constants.STATUS_IMPORT_PROBLEM
  593             else:
  594                 status = constants.STATUS_KEY_CONSIDERED
  595         except Exception as e:
  596             if e == errors.GPGMEError:
  597                 if e.code_str == "No data":
  598                     status = constants.STATUS_NODATA
  599                 else:
  600                     status = constants.STATUS_FILE_ERROR
  601             elif e == TypeError and hasattr(data, "decode") is True:
  602                 status = constants.STATUS_NO_PUBKEY
  603             elif e == TypeError and hasattr(data, "encode") is True:
  604                 status = constants.STATUS_FILE_ERROR
  605             else:
  606                 status = constants.STATUS_ERROR
  607 
  608         if status == constants.STATUS_KEY_CONSIDERED:
  609             import_result = result
  610         else:
  611             import_result = status
  612 
  613         return import_result
  614 
  615     def key_export(self, pattern=None):
  616         """Export keys.
  617 
  618         Exports public keys matching the pattern specified.  If no
  619         pattern is specified then exports all available keys.
  620 
  621         Keyword arguments:
  622         pattern -- return keys matching pattern (default: all keys)
  623 
  624         Returns:
  625                 -- A key block containing one or more OpenPGP keys in
  626                    either ASCII armoured or binary format as determined
  627                    by the Context().  If there are no matching keys it
  628                    returns None.
  629 
  630         Raises:
  631         GPGMEError     -- as signaled by the underlying library.
  632         """
  633         data = Data()
  634         mode = 0
  635         try:
  636             self.op_export(pattern, mode, data)
  637             data.seek(0, os.SEEK_SET)
  638             pk_result = data.read()
  639         except GPGMEError as e:
  640             raise e
  641 
  642         if len(pk_result) > 0:
  643             result = pk_result
  644         else:
  645             result = None
  646 
  647         return result
  648 
  649     def key_export_minimal(self, pattern=None):
  650         """Export keys.
  651 
  652         Exports public keys matching the pattern specified in a
  653         minimised format.  If no pattern is specified then exports all
  654         available keys.
  655 
  656         Keyword arguments:
  657         pattern -- return keys matching pattern (default: all keys)
  658 
  659         Returns:
  660                 -- A key block containing one or more minimised OpenPGP
  661                    keys in either ASCII armoured or binary format as
  662                    determined by the Context().  If there are no matching
  663                    keys it returns None.
  664 
  665         Raises:
  666         GPGMEError     -- as signaled by the underlying library.
  667         """
  668         data = Data()
  669         mode = gpgme.GPGME_EXPORT_MODE_MINIMAL
  670         try:
  671             self.op_export(pattern, mode, data)
  672             data.seek(0, os.SEEK_SET)
  673             pk_result = data.read()
  674         except GPGMEError as e:
  675             raise e
  676 
  677         if len(pk_result) > 0:
  678             result = pk_result
  679         else:
  680             result = None
  681 
  682         return result
  683 
  684     def key_export_secret(self, pattern=None):
  685         """Export secret keys.
  686 
  687         Exports secret keys matching the pattern specified.  If no
  688         pattern is specified then exports or attempts to export all
  689         available secret keys.
  690 
  691         IMPORTANT: Each secret key to be exported will prompt for its
  692         passphrase via an invocation of pinentry and gpg-agent.  If the
  693         passphrase is not entered or does not match then no data will be
  694         exported.  This is the same result as when specifying a pattern
  695         that is not matched by the available keys.
  696 
  697         Keyword arguments:
  698         pattern -- return keys matching pattern (default: all keys)
  699 
  700         Returns:
  701                 -- On success a key block containing one or more OpenPGP
  702                    secret keys in either ASCII armoured or binary format
  703                    as determined by the Context().
  704                 -- On failure while not raising an exception, returns None.
  705 
  706         Raises:
  707         GPGMEError     -- as signaled by the underlying library.
  708         """
  709         data = Data()
  710         mode = gpgme.GPGME_EXPORT_MODE_SECRET
  711         try:
  712             self.op_export(pattern, mode, data)
  713             data.seek(0, os.SEEK_SET)
  714             sk_result = data.read()
  715         except GPGMEError as e:
  716             raise e
  717 
  718         if len(sk_result) > 0:
  719             result = sk_result
  720         else:
  721             result = None
  722 
  723         return result
  724 
  725     def keylist(self,
  726                 pattern=None,
  727                 secret=False,
  728                 mode=constants.keylist.mode.LOCAL,
  729                 source=None):
  730         """List keys
  731 
  732         Keyword arguments:
  733         pattern -- return keys matching pattern (default: all keys)
  734         secret  -- return only secret keys (default: False)
  735         mode    -- keylist mode (default: list local keys)
  736         source  -- read keys from source instead from the keyring
  737                        (all other options are ignored in this case)
  738 
  739         Returns:
  740                 -- an iterator returning key objects
  741 
  742         Raises:
  743         GPGMEError  -- as signaled by the underlying library
  744         """
  745         if not source:
  746             self.set_keylist_mode(mode)
  747             self.op_keylist_start(pattern, secret)
  748         else:
  749             # Automatic wrapping of SOURCE is not possible here,
  750             # because the object must not be deallocated until the
  751             # iteration over the results ends.
  752             if not isinstance(source, Data):
  753                 source = Data(file=source)
  754             self.op_keylist_from_data_start(source, 0)
  755 
  756         key = self.op_keylist_next()
  757         while key:
  758             yield key
  759             key = self.op_keylist_next()
  760         self.op_keylist_end()
  761 
  762     def create_key(self,
  763                    userid,
  764                    algorithm=None,
  765                    expires_in=0,
  766                    expires=True,
  767                    sign=False,
  768                    encrypt=False,
  769                    certify=False,
  770                    authenticate=False,
  771                    passphrase=None,
  772                    force=False):
  773         """Create a primary key
  774 
  775         Create a primary key for the user id USERID.
  776 
  777         ALGORITHM may be used to specify the public key encryption
  778         algorithm for the new key.  By default, a reasonable default
  779         is chosen.  You may use "future-default" to select an
  780         algorithm that will be the default in a future implementation
  781         of the engine.  ALGORITHM may be a string like "rsa", or
  782         "rsa2048" to explicitly request an algorithm and a key size.
  783 
  784         EXPIRES_IN specifies the expiration time of the key in number
  785         of seconds since the keys creation.  By default, a reasonable
  786         expiration time is chosen.  If you want to create a key that
  787         does not expire, use the keyword argument EXPIRES.
  788 
  789         SIGN, ENCRYPT, CERTIFY, and AUTHENTICATE can be used to
  790         request the capabilities of the new key.  If you don't request
  791         any, a reasonable set of capabilities is selected, and in case
  792         of OpenPGP, a subkey with a reasonable set of capabilities is
  793         created.
  794 
  795         If PASSPHRASE is None (the default), then the key will not be
  796         protected with a passphrase.  If PASSPHRASE is a string, it
  797         will be used to protect the key.  If PASSPHRASE is True, the
  798         passphrase must be supplied using a passphrase callback or
  799         out-of-band with a pinentry.
  800 
  801         Keyword arguments:
  802         algorithm    -- public key algorithm, see above (default: reasonable)
  803         expires_in   -- expiration time in seconds (default: reasonable)
  804         expires      -- whether or not the key should expire (default: True)
  805         sign         -- request the signing capability (see above)
  806         encrypt      -- request the encryption capability (see above)
  807         certify      -- request the certification capability (see above)
  808         authenticate -- request the authentication capability (see above)
  809         passphrase   -- protect the key with a passphrase (default: no
  810                         passphrase)
  811         force        -- force key creation even if a key with the same userid
  812                         exists (default: False)
  813 
  814         Returns:
  815                      -- an object describing the result of the key creation
  816 
  817         Raises:
  818         GPGMEError   -- as signaled by the underlying library
  819 
  820         """
  821         if util.is_a_string(passphrase):
  822             old_pinentry_mode = self.pinentry_mode
  823             old_passphrase_cb = getattr(self, '_passphrase_cb', None)
  824             self.pinentry_mode = constants.PINENTRY_MODE_LOOPBACK
  825 
  826             def passphrase_cb(hint, desc, prev_bad, hook=None):
  827                 return passphrase
  828 
  829             self.set_passphrase_cb(passphrase_cb)
  830 
  831         try:
  832             self.op_createkey(
  833                 userid,
  834                 algorithm,
  835                 0,  # reserved
  836                 expires_in,
  837                 None,  # extrakey
  838                 ((constants.create.SIGN if sign else 0) |
  839                  (constants.create.ENCR if encrypt else 0) |
  840                  (constants.create.CERT if certify else 0) |
  841                  (constants.create.AUTH if authenticate else 0) |
  842                  (constants.create.NOPASSWD if passphrase is None else 0) |
  843                  (0 if expires else constants.create.NOEXPIRE) |
  844                  (constants.create.FORCE if force else 0)))
  845         finally:
  846             if util.is_a_string(passphrase):
  847                 self.pinentry_mode = old_pinentry_mode
  848                 if old_passphrase_cb:
  849                     self.set_passphrase_cb(*old_passphrase_cb[1:])
  850 
  851         return self.op_genkey_result()
  852 
  853     def create_subkey(self,
  854                       key,
  855                       algorithm=None,
  856                       expires_in=0,
  857                       expires=True,
  858                       sign=False,
  859                       encrypt=False,
  860                       authenticate=False,
  861                       passphrase=None):
  862         """Create a subkey
  863 
  864         Create a subkey for the given KEY.  As subkeys are a concept
  865         of OpenPGP, calling this is only valid for the OpenPGP
  866         protocol.
  867 
  868         ALGORITHM may be used to specify the public key encryption
  869         algorithm for the new subkey.  By default, a reasonable
  870         default is chosen.  You may use "future-default" to select an
  871         algorithm that will be the default in a future implementation
  872         of the engine.  ALGORITHM may be a string like "rsa", or
  873         "rsa2048" to explicitly request an algorithm and a key size.
  874 
  875         EXPIRES_IN specifies the expiration time of the subkey in
  876         number of seconds since the subkeys creation.  By default, a
  877         reasonable expiration time is chosen.  If you want to create a
  878         subkey that does not expire, use the keyword argument EXPIRES.
  879 
  880         SIGN, ENCRYPT, and AUTHENTICATE can be used to request the
  881         capabilities of the new subkey.  If you don't request any, an
  882         encryption subkey is generated.
  883 
  884         If PASSPHRASE is None (the default), then the subkey will not
  885         be protected with a passphrase.  If PASSPHRASE is a string, it
  886         will be used to protect the subkey.  If PASSPHRASE is True,
  887         the passphrase must be supplied using a passphrase callback or
  888         out-of-band with a pinentry.
  889 
  890         Keyword arguments:
  891         algorithm    -- public key algorithm, see above (default: reasonable)
  892         expires_in   -- expiration time in seconds (default: reasonable)
  893         expires      -- whether or not the subkey should expire (default: True)
  894         sign         -- request the signing capability (see above)
  895         encrypt      -- request the encryption capability (see above)
  896         authenticate -- request the authentication capability (see above)
  897         passphrase   -- protect the subkey with a passphrase (default: no
  898                         passphrase)
  899 
  900         Returns:
  901                      -- an object describing the result of the subkey creation
  902 
  903         Raises:
  904         GPGMEError   -- as signaled by the underlying library
  905 
  906         """
  907         if util.is_a_string(passphrase):
  908             old_pinentry_mode = self.pinentry_mode
  909             old_passphrase_cb = getattr(self, '_passphrase_cb', None)
  910             self.pinentry_mode = constants.PINENTRY_MODE_LOOPBACK
  911 
  912             def passphrase_cb(hint, desc, prev_bad, hook=None):
  913                 return passphrase
  914 
  915             self.set_passphrase_cb(passphrase_cb)
  916 
  917         try:
  918             self.op_createsubkey(
  919                 key,
  920                 algorithm,
  921                 0,  # reserved
  922                 expires_in,
  923                 ((constants.create.SIGN if sign else 0) |
  924                  (constants.create.ENCR if encrypt else 0) |
  925                  (constants.create.AUTH if authenticate else 0) |
  926                  (constants.create.NOPASSWD if passphrase is None else 0) |
  927                  (0 if expires else constants.create.NOEXPIRE)))
  928         finally:
  929             if util.is_a_string(passphrase):
  930                 self.pinentry_mode = old_pinentry_mode
  931                 if old_passphrase_cb:
  932                     self.set_passphrase_cb(*old_passphrase_cb[1:])
  933 
  934         return self.op_genkey_result()
  935 
  936     def key_add_uid(self, key, uid):
  937         """Add a UID
  938 
  939         Add the uid UID to the given KEY.  Calling this function is
  940         only valid for the OpenPGP protocol.
  941 
  942         Raises:
  943         GPGMEError   -- as signaled by the underlying library
  944 
  945         """
  946         self.op_adduid(key, uid, 0)
  947 
  948     def key_revoke_uid(self, key, uid):
  949         """Revoke a UID
  950 
  951         Revoke the uid UID from the given KEY.  Calling this function
  952         is only valid for the OpenPGP protocol.
  953 
  954         Raises:
  955         GPGMEError   -- as signaled by the underlying library
  956 
  957         """
  958         self.op_revuid(key, uid, 0)
  959 
  960     def key_sign(self, key, uids=None, expires_in=False, local=False):
  961         """Sign a key
  962 
  963         Sign a key with the current set of signing keys.  Calling this
  964         function is only valid for the OpenPGP protocol.
  965 
  966         If UIDS is None (the default), then all UIDs are signed.  If
  967         it is a string, then only the matching UID is signed.  If it
  968         is a list of strings, then all matching UIDs are signed.  Note
  969         that a case-sensitive exact string comparison is done.
  970 
  971         EXPIRES_IN specifies the expiration time of the signature in
  972         seconds.  If EXPIRES_IN is False, the signature does not
  973         expire.
  974 
  975         Keyword arguments:
  976         uids         -- user ids to sign, see above (default: sign all)
  977         expires_in   -- validity period of the signature in seconds
  978                                                (default: do not expire)
  979         local        -- create a local, non-exportable signature
  980                                                (default: False)
  981 
  982         Raises:
  983         GPGMEError   -- as signaled by the underlying library
  984 
  985         """
  986         flags = 0
  987         if uids is None or util.is_a_string(uids):
  988             pass  # through unchanged
  989         else:
  990             flags |= constants.keysign.LFSEP
  991             uids = "\n".join(uids)
  992 
  993         if not expires_in:
  994             flags |= constants.keysign.NOEXPIRE
  995 
  996         if local:
  997             flags |= constants.keysign.LOCAL
  998 
  999         self.op_keysign(key, uids, expires_in, flags)
 1000 
 1001     def key_tofu_policy(self, key, policy):
 1002         """Set a keys' TOFU policy
 1003 
 1004         Set the TOFU policy associated with KEY to POLICY.  Calling
 1005         this function is only valid for the OpenPGP protocol.
 1006 
 1007         Raises:
 1008         GPGMEError   -- as signaled by the underlying library
 1009 
 1010         """
 1011         self.op_tofu_policy(key, policy)
 1012 
 1013     def assuan_transact(self,
 1014                         command,
 1015                         data_cb=None,
 1016                         inquire_cb=None,
 1017                         status_cb=None):
 1018         """Issue a raw assuan command
 1019 
 1020         This function can be used to issue a raw assuan command to the
 1021         engine.
 1022 
 1023         If command is a string or bytes, it will be used as-is.  If it
 1024         is an iterable of strings, it will be properly escaped and
 1025         joined into an well-formed assuan command.
 1026 
 1027         Keyword arguments:
 1028         data_cb     -- a callback receiving data lines
 1029         inquire_cb  -- a callback providing more information
 1030         status_cb   -- a callback receiving status lines
 1031 
 1032         Returns:
 1033         result      -- the result of command as GPGMEError
 1034 
 1035         Raises:
 1036         GPGMEError  -- as signaled by the underlying library
 1037 
 1038         """
 1039 
 1040         if util.is_a_string(command) or isinstance(command, bytes):
 1041             cmd = command
 1042         else:
 1043             cmd = " ".join(util.percent_escape(f) for f in command)
 1044 
 1045         errptr = gpgme.new_gpgme_error_t_p()
 1046 
 1047         err = gpgme.gpgme_op_assuan_transact_ext(
 1048             self.wrapped, cmd, (weakref.ref(self), data_cb)
 1049             if data_cb else None, (weakref.ref(self), inquire_cb)
 1050             if inquire_cb else None, (weakref.ref(self), status_cb)
 1051             if status_cb else None, errptr)
 1052 
 1053         if self._callback_excinfo:
 1054             gpgme.gpg_raise_callback_exception(self)
 1055 
 1056         errorcheck(err)
 1057 
 1058         status = gpgme.gpgme_error_t_p_value(errptr)
 1059         gpgme.delete_gpgme_error_t_p(errptr)
 1060 
 1061         return GPGMEError(status) if status != 0 else None
 1062 
 1063     def interact(self, key, func, sink=None, flags=0, fnc_value=None):
 1064         """Interact with the engine
 1065 
 1066         This method can be used to edit keys and cards interactively.
 1067         KEY is the key to edit, FUNC is called repeatedly with two
 1068         unicode arguments, 'keyword' and 'args'.  See the GPGME manual
 1069         for details.
 1070 
 1071         Keyword arguments:
 1072         sink        -- if given, additional output is written here
 1073         flags       -- use constants.INTERACT_CARD to edit a card
 1074 
 1075         Raises:
 1076         GPGMEError  -- as signaled by the underlying library
 1077 
 1078         """
 1079         if key is None:
 1080             raise ValueError("First argument cannot be None")
 1081 
 1082         if sink is None:
 1083             sink = Data()
 1084 
 1085         if fnc_value:
 1086             opaquedata = (weakref.ref(self), func, fnc_value)
 1087         else:
 1088             opaquedata = (weakref.ref(self), func)
 1089 
 1090         result = gpgme.gpgme_op_interact(self.wrapped, key, flags, opaquedata,
 1091                                          sink)
 1092         if self._callback_excinfo:
 1093             gpgme.gpg_raise_callback_exception(self)
 1094         errorcheck(result)
 1095 
 1096     @property
 1097     def signers(self):
 1098         """Keys used for signing"""
 1099         return [self.signers_enum(i) for i in range(self.signers_count())]
 1100 
 1101     @signers.setter
 1102     def signers(self, signers):
 1103         old = self.signers
 1104         self.signers_clear()
 1105         try:
 1106             for key in signers:
 1107                 self.signers_add(key)
 1108         except:
 1109             self.signers = old
 1110             raise
 1111 
 1112     @property
 1113     def pinentry_mode(self):
 1114         """Pinentry mode"""
 1115         return self.get_pinentry_mode()
 1116 
 1117     @pinentry_mode.setter
 1118     def pinentry_mode(self, value):
 1119         self.set_pinentry_mode(value)
 1120 
 1121     @property
 1122     def protocol(self):
 1123         """Protocol to use"""
 1124         return self.get_protocol()
 1125 
 1126     @protocol.setter
 1127     def protocol(self, value):
 1128         errorcheck(gpgme.gpgme_engine_check_version(value))
 1129         self.set_protocol(value)
 1130 
 1131     @property
 1132     def home_dir(self):
 1133         """Engine's home directory"""
 1134         return self.engine_info.home_dir
 1135 
 1136     @home_dir.setter
 1137     def home_dir(self, value):
 1138         self.set_engine_info(self.protocol, home_dir=value)
 1139 
 1140     _ctype = 'gpgme_ctx_t'
 1141     _cprefix = 'gpgme_'
 1142 
 1143     def _errorcheck(self, name):
 1144         """This function should list all functions returning gpgme_error_t"""
 1145         # The list of functions is created using:
 1146         #
 1147         # $ grep '^gpgme_error_t ' obj/lang/python/python3.5-gpg/gpgme.h \
 1148         # | grep -v _op_ | awk "/\(gpgme_ctx/ { printf (\"'%s',\\n\", \$2) } "
 1149         return ((name.startswith('gpgme_op_') and not
 1150                  name.endswith('_result')) or name in {
 1151                      'gpgme_new', 'gpgme_set_ctx_flag', 'gpgme_set_protocol',
 1152                      'gpgme_set_sub_protocol', 'gpgme_set_keylist_mode',
 1153                      'gpgme_set_pinentry_mode', 'gpgme_set_locale',
 1154                      'gpgme_ctx_set_engine_info', 'gpgme_signers_add',
 1155                      'gpgme_sig_notation_add', 'gpgme_set_sender',
 1156                      'gpgme_cancel', 'gpgme_cancel_async', 'gpgme_get_key',
 1157                      'gpgme_get_sig_key',
 1158                 })
 1159 
 1160     _boolean_properties = {'armor', 'textmode', 'offline'}
 1161 
 1162     def __del__(self):
 1163         if not gpgme:
 1164             # At interpreter shutdown, gpgme is set to NONE.
 1165             return
 1166 
 1167         self._free_passcb()
 1168         self._free_progresscb()
 1169         self._free_statuscb()
 1170         if self.own and self.wrapped and gpgme.gpgme_release:
 1171             gpgme.gpgme_release(self.wrapped)
 1172             self.wrapped = None
 1173 
 1174     # Implement the context manager protocol.
 1175     def __enter__(self):
 1176         return self
 1177 
 1178     def __exit__(self, type, value, tb):
 1179         self.__del__()
 1180 
 1181     def op_keylist_all(self, *args, **kwargs):
 1182         self.op_keylist_start(*args, **kwargs)
 1183         key = self.op_keylist_next()
 1184         while key:
 1185             yield key
 1186             key = self.op_keylist_next()
 1187         self.op_keylist_end()
 1188 
 1189     def op_keylist_next(self):
 1190         """Returns the next key in the list created
 1191         by a call to op_keylist_start().  The object returned
 1192         is of type Key."""
 1193         ptr = gpgme.new_gpgme_key_t_p()
 1194         try:
 1195             errorcheck(gpgme.gpgme_op_keylist_next(self.wrapped, ptr))
 1196             key = gpgme.gpgme_key_t_p_value(ptr)
 1197         except errors.GPGMEError as excp:
 1198             key = None
 1199             if excp.getcode() != errors.EOF:
 1200                 raise excp
 1201         gpgme.delete_gpgme_key_t_p(ptr)
 1202         if key:
 1203             key.__del__ = lambda self: gpgme.gpgme_key_unref(self)
 1204             return key
 1205 
 1206     def get_key(self, fpr, secret=False):
 1207         """Get a key given a fingerprint
 1208 
 1209         Keyword arguments:
 1210         secret      -- to request a secret key
 1211 
 1212         Returns:
 1213                         -- the matching key
 1214 
 1215         Raises:
 1216         KeyError    -- if the key was not found
 1217         GPGMEError  -- as signaled by the underlying library
 1218 
 1219         """
 1220         ptr = gpgme.new_gpgme_key_t_p()
 1221 
 1222         try:
 1223             errorcheck(gpgme.gpgme_get_key(self.wrapped, fpr, ptr, secret))
 1224         except errors.GPGMEError as e:
 1225             if e.getcode() == errors.EOF:
 1226                 raise errors.KeyNotFound(fpr)
 1227             raise e
 1228 
 1229         key = gpgme.gpgme_key_t_p_value(ptr)
 1230         gpgme.delete_gpgme_key_t_p(ptr)
 1231         assert key
 1232         key.__del__ = lambda self: gpgme.gpgme_key_unref(self)
 1233         return key
 1234 
 1235     def op_trustlist_all(self, *args, **kwargs):
 1236         self.op_trustlist_start(*args, **kwargs)
 1237         trust = self.op_trustlist_next()
 1238         while trust:
 1239             yield trust
 1240             trust = self.op_trustlist_next()
 1241         self.op_trustlist_end()
 1242 
 1243     def op_trustlist_next(self):
 1244         """Returns the next trust item in the list created
 1245         by a call to op_trustlist_start().  The object returned
 1246         is of type TrustItem."""
 1247         ptr = gpgme.new_gpgme_trust_item_t_p()
 1248         try:
 1249             errorcheck(gpgme.gpgme_op_trustlist_next(self.wrapped, ptr))
 1250             trust = gpgme.gpgme_trust_item_t_p_value(ptr)
 1251         except errors.GPGMEError as excp:
 1252             trust = None
 1253             if excp.getcode() != errors.EOF:
 1254                 raise
 1255         gpgme.delete_gpgme_trust_item_t_p(ptr)
 1256         return trust
 1257 
 1258     def set_passphrase_cb(self, func, hook=None):
 1259         """Sets the passphrase callback to the function specified by func.
 1260 
 1261         When the system needs a passphrase, it will call func with three args:
 1262         hint, a string describing the key it needs the passphrase for;
 1263         desc, a string describing the passphrase it needs;
 1264         prev_bad, a boolean equal True if this is a call made after
 1265         unsuccessful previous attempt.
 1266 
 1267         If hook has a value other than None it will be passed into the func
 1268         as a forth argument.
 1269 
 1270         Please see the GPGME manual for more information.
 1271         """
 1272         if func is None:
 1273             hookdata = None
 1274         else:
 1275             if hook is None:
 1276                 hookdata = (weakref.ref(self), func)
 1277             else:
 1278                 hookdata = (weakref.ref(self), func, hook)
 1279         gpgme.gpg_set_passphrase_cb(self, hookdata)
 1280 
 1281     def _free_passcb(self):
 1282         if gpgme.gpg_set_passphrase_cb:
 1283             self.set_passphrase_cb(None)
 1284 
 1285     def set_progress_cb(self, func, hook=None):
 1286         """Sets the progress meter callback to the function specified by FUNC.
 1287         If FUNC is None, the callback will be cleared.
 1288 
 1289         This function will be called to provide an interactive update
 1290         of the system's progress.  The function will be called with
 1291         three arguments, type, total, and current.  If HOOK is not
 1292         None, it will be supplied as fourth argument.
 1293 
 1294         Please see the GPGME manual for more information.
 1295 
 1296         """
 1297         if func is None:
 1298             hookdata = None
 1299         else:
 1300             if hook is None:
 1301                 hookdata = (weakref.ref(self), func)
 1302             else:
 1303                 hookdata = (weakref.ref(self), func, hook)
 1304         gpgme.gpg_set_progress_cb(self, hookdata)
 1305 
 1306     def _free_progresscb(self):
 1307         if gpgme.gpg_set_progress_cb:
 1308             self.set_progress_cb(None)
 1309 
 1310     def set_status_cb(self, func, hook=None):
 1311         """Sets the status callback to the function specified by FUNC.  If
 1312         FUNC is None, the callback will be cleared.
 1313 
 1314         The function will be called with two arguments, keyword and
 1315         args.  If HOOK is not None, it will be supplied as third
 1316         argument.
 1317 
 1318         Please see the GPGME manual for more information.
 1319 
 1320         """
 1321         if func is None:
 1322             hookdata = None
 1323         else:
 1324             if hook is None:
 1325                 hookdata = (weakref.ref(self), func)
 1326             else:
 1327                 hookdata = (weakref.ref(self), func, hook)
 1328         gpgme.gpg_set_status_cb(self, hookdata)
 1329 
 1330     def _free_statuscb(self):
 1331         if gpgme.gpg_set_status_cb:
 1332             self.set_status_cb(None)
 1333 
 1334     @property
 1335     def engine_info(self):
 1336         """Configuration of the engine currently in use"""
 1337         p = self.protocol
 1338         infos = [i for i in self.get_engine_info() if i.protocol == p]
 1339         assert len(infos) == 1
 1340         return infos[0]
 1341 
 1342     def get_engine_info(self):
 1343         """Get engine configuration
 1344 
 1345         Returns information about all configured and installed
 1346         engines.
 1347 
 1348         Returns:
 1349         infos       -- a list of engine infos
 1350 
 1351         """
 1352         return gpgme.gpgme_ctx_get_engine_info(self.wrapped)
 1353 
 1354     def set_engine_info(self, proto, file_name=None, home_dir=None):
 1355         """Change engine configuration
 1356 
 1357         Changes the configuration of the crypto engine implementing
 1358         the protocol 'proto' for the context.
 1359 
 1360         Keyword arguments:
 1361         file_name   -- engine program file name (unchanged if None)
 1362         home_dir    -- configuration directory (unchanged if None)
 1363 
 1364         """
 1365         self.ctx_set_engine_info(proto, file_name, home_dir)
 1366 
 1367     def wait(self, hang):
 1368         """Wait for asynchronous call to finish. Wait forever if hang is True.
 1369         Raises an exception on errors.
 1370 
 1371         Please read the GPGME manual for more information.
 1372 
 1373         """
 1374         ptr = gpgme.new_gpgme_error_t_p()
 1375         gpgme.gpgme_wait(self.wrapped, ptr, hang)
 1376         status = gpgme.gpgme_error_t_p_value(ptr)
 1377         gpgme.delete_gpgme_error_t_p(ptr)
 1378         errorcheck(status)
 1379 
 1380     def op_edit(self, key, func, fnc_value, out):
 1381         """Start key editing using supplied callback function
 1382 
 1383         Note: This interface is deprecated and will be removed with
 1384         GPGME 1.8.  Please use .interact instead.  Furthermore, we
 1385         implement this using gpgme_op_interact, so callbacks will get
 1386         called with string keywords instead of numeric status
 1387         messages.  Code that is using constants.STATUS_X or
 1388         constants.status.X will continue to work, whereas code using
 1389         magic numbers will break as a result.
 1390 
 1391         """
 1392         warnings.warn(
 1393             "Call to deprecated method op_edit.", category=DeprecationWarning)
 1394         return self.interact(key, func, sink=out, fnc_value=fnc_value)
 1395 
 1396 
 1397 class Data(GpgmeWrapper):
 1398     """Data buffer
 1399 
 1400     A lot of data has to be exchanged between the user and the crypto
 1401     engine, like plaintext messages, ciphertext, signatures and
 1402     information about the keys.  The technical details about
 1403     exchanging the data information are completely abstracted by
 1404     GPGME.  The user provides and receives the data via `gpgme_data_t'
 1405     objects, regardless of the communication protocol between GPGME
 1406     and the crypto engine in use.
 1407 
 1408     This Data class is the implementation of the GpgmeData objects.
 1409 
 1410     Please see the information about __init__ for instantiation.
 1411 
 1412     """
 1413 
 1414     _ctype = 'gpgme_data_t'
 1415     _cprefix = 'gpgme_data_'
 1416 
 1417     def _errorcheck(self, name):
 1418         """This function should list all functions returning gpgme_error_t"""
 1419         # This list is compiled using
 1420         #
 1421         # $ grep -v '^gpgme_error_t ' obj/lang/python/python3.5-gpg/gpgme.h \
 1422         #   | awk "/\(gpgme_data_t/ { printf (\"'%s',\\n\", \$2) } " \
 1423         #   | sed "s/'\\*/'/"
 1424         return name not in {
 1425             'gpgme_data_read',
 1426             'gpgme_data_write',
 1427             'gpgme_data_seek',
 1428             'gpgme_data_release',
 1429             'gpgme_data_release_and_get_mem',
 1430             'gpgme_data_get_encoding',
 1431             'gpgme_data_get_file_name',
 1432             'gpgme_data_set_flag',
 1433             'gpgme_data_identify',
 1434         }
 1435 
 1436     def __init__(self,
 1437                  string=None,
 1438                  file=None,
 1439                  offset=None,
 1440                  length=None,
 1441                  cbs=None,
 1442                  copy=True):
 1443         """Initialize a new gpgme_data_t object.
 1444 
 1445         If no args are specified, make it an empty object.
 1446 
 1447         If string alone is specified, initialize it with the data
 1448         contained there.
 1449 
 1450         If file, offset, and length are all specified, file must
 1451         be either a filename or a file-like object, and the object
 1452         will be initialized by reading the specified chunk from the file.
 1453 
 1454         If cbs is specified, it MUST be a tuple of the form:
 1455 
 1456         (read_cb, write_cb, seek_cb, release_cb[, hook])
 1457 
 1458         where the first four items are functions implementing reading,
 1459         writing, seeking the data, and releasing any resources once
 1460         the data object is deallocated.  The functions must match the
 1461         following prototypes:
 1462 
 1463             def read(amount, hook=None):
 1464                 return <a b"bytes" object>
 1465 
 1466             def write(data, hook=None):
 1467                 return <the number of bytes written>
 1468 
 1469             def seek(offset, whence, hook=None):
 1470                 return <the new file position>
 1471 
 1472             def release(hook=None):
 1473                 <return value and exceptions are ignored>
 1474 
 1475         The functions may be bound methods.  In that case, you can
 1476         simply use the 'self' reference instead of using a hook.
 1477 
 1478         If file is specified without any other arguments, then
 1479         it must be a filename, and the object will be initialized from
 1480         that file.
 1481 
 1482         """
 1483         super(Data, self).__init__(None)
 1484         self.data_cbs = None
 1485 
 1486         if cbs is not None:
 1487             self.new_from_cbs(*cbs)
 1488         elif string is not None:
 1489             self.new_from_mem(string, copy)
 1490         elif file is not None and offset is not None and length is not None:
 1491             self.new_from_filepart(file, offset, length)
 1492         elif file is not None:
 1493             if util.is_a_string(file):
 1494                 self.new_from_file(file, copy)
 1495             else:
 1496                 self.new_from_fd(file)
 1497         else:
 1498             self.new()
 1499 
 1500     def __del__(self):
 1501         if not gpgme:
 1502             # At interpreter shutdown, gpgme is set to NONE.
 1503             return
 1504 
 1505         if self.wrapped is not None and gpgme.gpgme_data_release:
 1506             gpgme.gpgme_data_release(self.wrapped)
 1507             if self._callback_excinfo:
 1508                 gpgme.gpg_raise_callback_exception(self)
 1509             self.wrapped = None
 1510         self._free_datacbs()
 1511 
 1512     # Implement the context manager protocol.
 1513     def __enter__(self):
 1514         return self
 1515 
 1516     def __exit__(self, type, value, tb):
 1517         self.__del__()
 1518 
 1519     def _free_datacbs(self):
 1520         self._data_cbs = None
 1521 
 1522     def new(self):
 1523         tmp = gpgme.new_gpgme_data_t_p()
 1524         errorcheck(gpgme.gpgme_data_new(tmp))
 1525         self.wrapped = gpgme.gpgme_data_t_p_value(tmp)
 1526         gpgme.delete_gpgme_data_t_p(tmp)
 1527 
 1528     def new_from_mem(self, string, copy=True):
 1529         tmp = gpgme.new_gpgme_data_t_p()
 1530         errorcheck(
 1531             gpgme.gpgme_data_new_from_mem(tmp, string, len(string), copy))
 1532         self.wrapped = gpgme.gpgme_data_t_p_value(tmp)
 1533         gpgme.delete_gpgme_data_t_p(tmp)
 1534 
 1535     def new_from_file(self, filename, copy=True):
 1536         tmp = gpgme.new_gpgme_data_t_p()
 1537         try:
 1538             errorcheck(gpgme.gpgme_data_new_from_file(tmp, filename, copy))
 1539         except errors.GPGMEError as e:
 1540             if e.getcode() == errors.INV_VALUE and not copy:
 1541                 raise ValueError("delayed reads are not yet supported")
 1542             else:
 1543                 raise e
 1544         self.wrapped = gpgme.gpgme_data_t_p_value(tmp)
 1545         gpgme.delete_gpgme_data_t_p(tmp)
 1546 
 1547     def new_from_cbs(self, read_cb, write_cb, seek_cb, release_cb, hook=None):
 1548         tmp = gpgme.new_gpgme_data_t_p()
 1549         if hook is not None:
 1550             hookdata = (weakref.ref(self), read_cb, write_cb, seek_cb,
 1551                         release_cb, hook)
 1552         else:
 1553             hookdata = (weakref.ref(self), read_cb, write_cb, seek_cb,
 1554                         release_cb)
 1555         gpgme.gpg_data_new_from_cbs(self, hookdata, tmp)
 1556         self.wrapped = gpgme.gpgme_data_t_p_value(tmp)
 1557         gpgme.delete_gpgme_data_t_p(tmp)
 1558 
 1559     def new_from_filepart(self, file, offset, length):
 1560         """This wraps the GPGME gpgme_data_new_from_filepart() function.
 1561         The argument "file" may be:
 1562 
 1563         * a string specifying a file name, or
 1564         * a file-like object supporting the fileno() and the mode attribute.
 1565 
 1566         """
 1567 
 1568         tmp = gpgme.new_gpgme_data_t_p()
 1569         filename = None
 1570         fp = None
 1571 
 1572         if util.is_a_string(file):
 1573             filename = file
 1574         else:
 1575             fp = gpgme.fdopen(file.fileno(), file.mode)
 1576             if fp is None:
 1577                 raise ValueError("Failed to open file from %s arg %s" % (str(
 1578                     type(file)), str(file)))
 1579 
 1580         errorcheck(
 1581             gpgme.gpgme_data_new_from_filepart(tmp, filename, fp, offset,
 1582                                                length))
 1583         self.wrapped = gpgme.gpgme_data_t_p_value(tmp)
 1584         gpgme.delete_gpgme_data_t_p(tmp)
 1585 
 1586     def new_from_fd(self, file):
 1587         """This wraps the GPGME gpgme_data_new_from_fd() function.  The
 1588         argument "file" must be a file-like object, supporting the
 1589         fileno() method.
 1590 
 1591         """
 1592         tmp = gpgme.new_gpgme_data_t_p()
 1593         errorcheck(gpgme.gpgme_data_new_from_fd(tmp, file.fileno()))
 1594         self.wrapped = gpgme.gpgme_data_t_p_value(tmp)
 1595         gpgme.delete_gpgme_data_t_p(tmp)
 1596 
 1597     def new_from_stream(self, file):
 1598         """This wrap around gpgme_data_new_from_stream is an alias for
 1599         new_from_fd() method since in python there's no difference
 1600         between file stream and file descriptor."""
 1601         self.new_from_fd(file)
 1602 
 1603     def new_from_estream(self, file):
 1604         """This wrap around gpgme_data_new_from_estream is an alias for
 1605         new_from_fd() method since in python there's no difference
 1606         between file stream and file descriptor, but using fd broke."""
 1607         self.new_from_stream(file)
 1608 
 1609     def write(self, buffer):
 1610         """Write buffer given as string or bytes.
 1611 
 1612         If a string is given, it is implicitly encoded using UTF-8."""
 1613         written = gpgme.gpgme_data_write(self.wrapped, buffer)
 1614         if written < 0:
 1615             if self._callback_excinfo:
 1616                 gpgme.gpg_raise_callback_exception(self)
 1617             else:
 1618                 raise GPGMEError.fromSyserror()
 1619         return written
 1620 
 1621     def read(self, size=-1):
 1622         """Read at most size bytes, returned as bytes.
 1623 
 1624         If the size argument is negative or omitted, read until EOF is reached.
 1625 
 1626         Returns the data read, or the empty string if there was no data
 1627         to read before EOF was reached."""
 1628 
 1629         if size == 0:
 1630             return ''
 1631 
 1632         if size > 0:
 1633             try:
 1634                 result = gpgme.gpgme_data_read(self.wrapped, size)
 1635             except:
 1636                 if self._callback_excinfo:
 1637                     gpgme.gpg_raise_callback_exception(self)
 1638                 else:
 1639                     raise
 1640             return result
 1641         else:
 1642             chunks = []
 1643             while True:
 1644                 try:
 1645                     result = gpgme.gpgme_data_read(self.wrapped, 4096)
 1646                 except:
 1647                     if self._callback_excinfo:
 1648                         gpgme.gpg_raise_callback_exception(self)
 1649                     else:
 1650                         raise
 1651                 if len(result) == 0:
 1652                     break
 1653                 chunks.append(result)
 1654             return b''.join(chunks)
 1655 
 1656 
 1657 def pubkey_algo_string(subkey):
 1658     """Return short algorithm string
 1659 
 1660     Return a public key algorithm string (e.g. "rsa2048") for a given
 1661     SUBKEY.
 1662 
 1663     Returns:
 1664     algo      - a string
 1665 
 1666     """
 1667     return gpgme.gpgme_pubkey_algo_string(subkey)
 1668 
 1669 
 1670 def pubkey_algo_name(algo):
 1671     """Return name of public key algorithm
 1672 
 1673     Return the name of the public key algorithm for a given numeric
 1674     algorithm id ALGO (cf. RFC4880).
 1675 
 1676     Returns:
 1677     algo      - a string
 1678 
 1679     """
 1680     return gpgme.gpgme_pubkey_algo_name(algo)
 1681 
 1682 
 1683 def hash_algo_name(algo):
 1684     """Return name of hash algorithm
 1685 
 1686     Return the name of the hash algorithm for a given numeric
 1687     algorithm id ALGO (cf. RFC4880).
 1688 
 1689     Returns:
 1690     algo      - a string
 1691 
 1692     """
 1693     return gpgme.gpgme_hash_algo_name(algo)
 1694 
 1695 
 1696 def get_protocol_name(proto):
 1697     """Get protocol description
 1698 
 1699     Get the string describing protocol PROTO.
 1700 
 1701     Returns:
 1702     proto     - a string
 1703 
 1704     """
 1705     return gpgme.gpgme_get_protocol_name(proto)
 1706 
 1707 
 1708 def addrspec_from_uid(uid):
 1709     """Return the address spec
 1710 
 1711     Return the addr-spec (cf. RFC2822 section 4.3) from a user id UID.
 1712 
 1713     Returns:
 1714     addr_spec - a string
 1715 
 1716     """
 1717     return gpgme.gpgme_addrspec_from_uid(uid)
 1718 
 1719 
 1720 def check_version(version=None):
 1721     return gpgme.gpgme_check_version(version)
 1722 
 1723 
 1724 # check_version also makes sure that several subsystems are properly
 1725 # initialized, and it must be run at least once before invoking any
 1726 # other function.  We do it here so that the user does not have to do
 1727 # it unless she really wants to check for a certain version.
 1728 check_version()
 1729 
 1730 
 1731 def engine_check_version(proto):
 1732     try:
 1733         errorcheck(gpgme.gpgme_engine_check_version(proto))
 1734         return True
 1735     except errors.GPGMEError:
 1736         return False
 1737 
 1738 
 1739 def get_engine_info():
 1740     ptr = gpgme.new_gpgme_engine_info_t_p()
 1741     try:
 1742         errorcheck(gpgme.gpgme_get_engine_info(ptr))
 1743         info = gpgme.gpgme_engine_info_t_p_value(ptr)
 1744     except errors.GPGMEError:
 1745         info = None
 1746     gpgme.delete_gpgme_engine_info_t_p(ptr)
 1747     return info
 1748 
 1749 
 1750 def set_engine_info(proto, file_name, home_dir=None):
 1751     """Changes the default configuration of the crypto engine implementing
 1752     the protocol 'proto'. 'file_name' is the file name of
 1753     the executable program implementing this protocol. 'home_dir' is the
 1754     directory name of the configuration directory (engine's default is
 1755     used if omitted)."""
 1756     errorcheck(gpgme.gpgme_set_engine_info(proto, file_name, home_dir))
 1757 
 1758 
 1759 def set_locale(category, value):
 1760     """Sets the default locale used by contexts"""
 1761     errorcheck(gpgme.gpgme_set_locale(None, category, value))
 1762 
 1763 
 1764 def wait(hang):
 1765     """Wait for asynchronous call on any Context  to finish.
 1766     Wait forever if hang is True.
 1767 
 1768     For finished anynch calls it returns a tuple (status, context):
 1769         status  - status return by asnynchronous call.
 1770         context - context which caused this call to return.
 1771 
 1772     Please read the GPGME manual of more information."""
 1773     ptr = gpgme.new_gpgme_error_t_p()
 1774     context = gpgme.gpgme_wait(None, ptr, hang)
 1775     status = gpgme.gpgme_error_t_p_value(ptr)
 1776     gpgme.delete_gpgme_error_t_p(ptr)
 1777     if context is None:
 1778         errorcheck(status)
 1779     else:
 1780         context = Context(context)
 1781     return (status, context)