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