1# -*- coding: utf-8 -*-
2
3from __future__ import absolute_import, print_function, unicode_literals
4
5import re
6import os
7import warnings
8import weakref
9
10from . import gpgme
11from .errors import errorcheck, GPGMEError
12from . import constants
13from . import errors
14from . import util
15
16del 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
37Core functionality of GPGME wrapped in a object-oriented fashion.
38Provides the 'Context' class for performing cryptographic operations,
39and the 'Data' class describing buffers of data.
40
41"""
42
43
44class 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
177class 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
1397class 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
1657def 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
1670def 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
1683def 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
1696def 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
1708def 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
1720def 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.
1728check_version()
1729
1730
1731def 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
1739def 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
1750def 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
1759def set_locale(category, value):
1760    """Sets the default locale used by contexts"""
1761    errorcheck(gpgme.gpgme_set_locale(None, category, value))
1762
1763
1764def 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)
1782