--- /dev/null
+include Makefile
+include MANIFEST.in
+include test_all.py
+
+recursive-include gpgme *.py
+include gpgme/tests/keys/*.pub
+include gpgme/tests/keys/*.sec
+
+include src/*.c
+include src/*.h
--- /dev/null
+PYTHON = python2.4
+
+build:
+ $(PYTHON) setup.py build_ext -i
+
+check: build
+ $(PYTHON) test_all.py -v
+
+clean:
+ $(PYTHON) setup.py clean
+
+dist: build
+ $(PYTHON) setup.py sdist --force-manifest
+
+.PHONY: build check clean dist
--- /dev/null
+Metadata-Version: 1.0
+Name: pygpgme
+Version: 0.1
+Summary: A Python module for working with OpenPGP messages
+Home-page: https://launchpad.net/products/pygpgme
+Author: James Henstridge
+Author-email: james@jamesh.id.au
+License: LGPL
+Description:
+ PyGPGME is a Python module that lets you sign, verify, encrypt
+ and decrypt messages using the OpenPGP format.
+
+ It is built on top of the GNU Privacy Guard and the GPGME
+ library.
+Platform: UNKNOWN
+Classifier: Intended Audience :: Developers
+Classifier: License :: OSI Approved :: GNU Library or Lesser General Public License (LGPL)
+Classifier: Operating System :: POSIX
+Classifier: Programming Language :: C
+Classifier: Programming Language :: Python
+Classifier: Topic :: Security :: Cryptography
+Classifier: Topic :: Software Development :: Libraries :: Python Modules
--- /dev/null
+A Python binding for the gpgme library, used to drive the gpg command
+line program.
+
+More information about gpgme can be found here:
+ http://www.gnupg.org/(en)/related_software/gpgme/index.html
+
+This binding stays fairly close to the C API with the following
+exceptions:
+
+ * Memory management is not exposed to the user
+
+ * Functions like gpgme_get_foo()/gpgme_set_foo() are converted to
+ attribute access on gpgme.Context objects.
+
+ * Functions that take gpgme_data_t arguments take arbitrary Python
+ file-like objects. The read(), write(), seek() and tell() methods
+ may be used on the object.
+
+ * Non-zero gpgme_error_t return values are converted to gpgme.error
+ exceptions.
+
+ * Only the synchronous versions of functions have been wrapped.
+ However, the Python global interpreter lock is dropped, so should
+ play nicely in multi-threaded Python programs.
+
+ * Function pairs like gpgme_op_import()/gpgme_op_import_result() are
+ combined into single method calls.
+
+ * The Python version of gpgme_op_keylist() returns an iterator over
+ the matched keys, rather than requiring the user to use a special
+ iteration function.
+
+This library is licensed under the LGPL, the same license as the gpgme
+library.
--- /dev/null
+# pygpgme - a Python wrapper for the gpgme library
+# Copyright (C) 2006 James Henstridge
+#
+# This library is free software; you can redistribute it and/or
+# modify it under the terms of the GNU Lesser General Public
+# License as published by the Free Software Foundation; either
+# version 2.1 of the License, or (at your option) any later version.
+#
+# This library is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+# Lesser General Public License for more details.
+#
+# You should have received a copy of the GNU Lesser General Public
+# License along with this library; if not, write to the Free Software
+# Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
+
+from _gpgme import *
+
+# create constants
+make_constants(globals())
+del make_constants
--- /dev/null
+# pygpgme - a Python wrapper for the gpgme library
+# Copyright (C) 2006 James Henstridge
+#
+# This library is free software; you can redistribute it and/or
+# modify it under the terms of the GNU Lesser General Public
+# License as published by the Free Software Foundation; either
+# version 2.1 of the License, or (at your option) any later version.
+#
+# This library is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+# Lesser General Public License for more details.
+#
+# You should have received a copy of the GNU Lesser General Public
+# License along with this library; if not, write to the Free Software
+# Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
+
+"""Utilities related to editing keys.
+
+Currently only contains a utility function for editing the owner trust
+value of a key in a keyring.
+"""
+
+__metaclass__ = type
+
+__all__ = ['edit_trust']
+
+import os
+import StringIO
+import gpgme
+
+
+class _EditData:
+ """Simple base class to wrap 'edit key' interactions"""
+
+ STATE_START = 0
+ STATE_ERROR = -1
+
+ def __init__(self):
+ self.state = self.STATE_START
+ self.transitions = {}
+ # a default state transition to try and quit the edit on error
+ self.addTransition(self.STATE_ERROR,
+ gpgme.STATUS_GET_LINE, 'keyedit.prompt',
+ self.STATE_ERROR, 'quit\n')
+
+ def addTransition(self, state, status, args, newstate, data):
+ self.transitions[state, status, args] = newstate, data
+
+ def do_edit(self, ctx, key):
+ output = StringIO.StringIO()
+ ctx.edit(key, self.callback, output)
+
+ def callback(self, status, args, fd):
+ if status in (gpgme.STATUS_EOF,
+ gpgme.STATUS_GOT_IT,
+ gpgme.STATUS_NEED_PASSPHRASE,
+ gpgme.STATUS_GOOD_PASSPHRASE,
+ gpgme.STATUS_BAD_PASSPHRASE,
+ gpgme.STATUS_USERID_HINT,
+ gpgme.STATUS_SIGEXPIRED,
+ gpgme.STATUS_KEYEXPIRED,
+ gpgme.STATUS_PROGRESS,
+ gpgme.STATUS_KEY_CREATED,
+ gpgme.STATUS_ALREADY_SIGNED):
+ return
+
+ #print 'S: %s (%d)' % (args, status)
+
+ if (self.state, status, args) in self.transitions:
+ self.state, data = self.transitions[self.state, status, args]
+ #print 'C: %r' % data
+ if data is not None:
+ os.write(fd, data)
+ else:
+ self.state = STATE_ERROR
+ raise gpgme.error(gpgme.ERR_SOURCE_UNKNOWN, gpgme.ERR_GENERAL)
+
+
+class _EditTrust(_EditData):
+ # states
+ STATE_COMMAND = 1
+ STATE_VALUE = 2
+ STATE_CONFIRM = 3
+ STATE_QUIT = 4
+
+ def __init__(self, trust):
+ _EditData.__init__(self)
+
+ self.addTransition(self.STATE_START,
+ gpgme.STATUS_GET_LINE, 'keyedit.prompt',
+ self.STATE_COMMAND, 'trust\n')
+
+ self.addTransition(self.STATE_COMMAND,
+ gpgme.STATUS_GET_LINE, 'edit_ownertrust.value',
+ self.STATE_VALUE, '%d\n' % trust)
+
+ self.addTransition(self.STATE_VALUE,
+ gpgme.STATUS_GET_LINE, 'keyedit.prompt',
+ self.STATE_QUIT, 'quit\n')
+
+ self.addTransition(self.STATE_VALUE,
+ gpgme.STATUS_GET_BOOL, 'edit_ownertrust.set_ultimate.okay',
+ self.STATE_CONFIRM, 'Y\n')
+
+ self.addTransition(self.STATE_CONFIRM,
+ gpgme.STATUS_GET_LINE, 'keyedit.prompt',
+ self.STATE_QUIT, 'quit\n')
+
+ self.addTransition(self.STATE_QUIT,
+ gpgme.STATUS_GET_BOOL, 'keyedit.save.okay',
+ self.STATE_CONFIRM, 'Y\n')
+
+class _EditSign(_EditData):
+ # states
+ STATE_UID = 1
+ STATE_COMMAND = 2
+ STATE_QUIT = 3
+
+ def __init__(self, index, command, expire, check):
+ _EditData.__init__(self)
+
+ self.addTransition(self.STATE_START,
+ gpgme.STATUS_GET_LINE, 'keyedit.prompt',
+ self.STATE_UID, 'uid %d\n' % index)
+
+ self.addTransition(self.STATE_UID,
+ gpgme.STATUS_GET_LINE, 'keyedit.prompt',
+ self.STATE_COMMAND, '%s\n' % command)
+
+ self.addTransition(self.STATE_COMMAND,
+ gpgme.STATUS_GET_BOOL, 'keyedit.sign_all.okay',
+ self.STATE_COMMAND, 'Y\n')
+ self.addTransition(self.STATE_COMMAND,
+ gpgme.STATUS_GET_LINE, 'sign_uid.expire',
+ self.STATE_COMMAND, '%s\n' % (expire and 'Y' or 'N'))
+ self.addTransition(self.STATE_COMMAND,
+ gpgme.STATUS_GET_LINE, 'sign_uid.class',
+ self.STATE_COMMAND, '%d\n' % check)
+ self.addTransition(self.STATE_COMMAND,
+ gpgme.STATUS_GET_BOOL, 'sign_uid.okay',
+ self.STATE_COMMAND, 'Y\n')
+ self.addTransition(self.STATE_COMMAND,
+ gpgme.STATUS_GET_LINE, 'keyedit.prompt',
+ self.STATE_QUIT, 'quit\n')
+
+ self.addTransition(self.STATE_QUIT,
+ gpgme.STATUS_GET_BOOL, 'keyedit.save.okay',
+ self.STATE_COMMAND, 'Y\n')
+
+
+def edit_trust(ctx, key, trust):
+ if trust not in (gpgme.VALIDITY_UNDEFINED,
+ gpgme.VALIDITY_NEVER,
+ gpgme.VALIDITY_MARGINAL,
+ gpgme.VALIDITY_FULL,
+ gpgme.VALIDITY_ULTIMATE):
+ raise ValueError('Bad trust value %d' % trust)
+ statemachine = _EditTrust(trust)
+ statemachine.do_edit(ctx, key)
+
+def edit_sign(ctx, key, index=0, local=False, norevoke=False,
+ expire=True, check=0):
+ """Sign the given key.
+
+ index: the index of the user ID to sign, starting at 1. Sign all
+ user IDs if set to 0.
+ local: make a local signature
+ norevoke: make a non-revokable signature
+ command: the type of signature. One of sign, lsign, tsign or nrsign.
+ expire: whether the signature should expire with the key.
+ check: Amount of checking performed. One of:
+ 0 - no answer
+ 1 - no checking
+ 2 - casual checking
+ 3 - careful checking
+ """
+ if index < 0 or index > len(key.uids):
+ raise ValueError('user ID index out of range')
+ command = 'sign'
+ if local:
+ command = 'l%s' % command
+ if norevoke:
+ command = 'nr%s' % command
+ if check not in [0, 1, 2, 3]:
+ raise ValueError('check must be one of 0, 1, 2, 3')
+ statemachine = _EditSign(index, command, expire, check)
+ statemachine.do_edit(ctx, key)
--- /dev/null
+# pygpgme - a Python wrapper for the gpgme library
+# Copyright (C) 2006 James Henstridge
+#
+# This library is free software; you can redistribute it and/or
+# modify it under the terms of the GNU Lesser General Public
+# License as published by the Free Software Foundation; either
+# version 2.1 of the License, or (at your option) any later version.
+#
+# This library is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+# Lesser General Public License for more details.
+#
+# You should have received a copy of the GNU Lesser General Public
+# License along with this library; if not, write to the Free Software
+# Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
+
+import unittest
+
+def test_suite():
+ import gpgme.tests.test_context
+ import gpgme.tests.test_keys
+ import gpgme.tests.test_keylist
+ import gpgme.tests.test_import
+ import gpgme.tests.test_export
+ import gpgme.tests.test_delete
+ import gpgme.tests.test_sign_verify
+ import gpgme.tests.test_encrypt_decrypt
+ import gpgme.tests.test_passphrase
+ import gpgme.tests.test_progress
+ import gpgme.tests.test_editkey
+ suite = unittest.TestSuite()
+ suite.addTest(gpgme.tests.test_context.test_suite())
+ suite.addTest(gpgme.tests.test_keys.test_suite())
+ suite.addTest(gpgme.tests.test_keylist.test_suite())
+ suite.addTest(gpgme.tests.test_import.test_suite())
+ suite.addTest(gpgme.tests.test_export.test_suite())
+ suite.addTest(gpgme.tests.test_delete.test_suite())
+ suite.addTest(gpgme.tests.test_sign_verify.test_suite())
+ suite.addTest(gpgme.tests.test_encrypt_decrypt.test_suite())
+ suite.addTest(gpgme.tests.test_passphrase.test_suite())
+ suite.addTest(gpgme.tests.test_progress.test_suite())
+ suite.addTest(gpgme.tests.test_editkey.test_suite())
+ return suite
--- /dev/null
+-----BEGIN PGP PUBLIC KEY BLOCK-----
+Version: GnuPG v1.4.1 (GNU/Linux)
+
+mQGiBEPN6eMRBAC3/jKHCnI9c9fATgGLV4x53wN6ZZoqzcgks4rR9BgrYLvPBzDX
+em74/m5uRMY90hGzJw8kb/rG8ZznJTU/ZE50qCmEEQuTyZar80LEb4ujbqTfZzGK
+v3blpSS+f5ON+2VATiL85roJ7BhpMnhUvS7nk/rSoKFYz+sdf/l3SR76ywCgg+OK
+ISC9UWqI9wlyhs7BpZib6SkEAJ7SzSDHNFI0Uvl5/+QYwy1N9IxCx6po7OJuBFK8
+9XBSbqRnnrlcCko/qTIuPxy9R9g+0JPhi2cNB++f3I/TPz73Xsg7JjkNnqD7aZS7
+MXRlzxESuu7Br+JVwzIERfXDLuA0pnMy+nt1mhuUFxc4dFEzD0DDsbFNWmo57rlr
+t2BZA/4naBrB6L763BMIzebjTCOJ5d0/4pbqlQrP2O+2BxKvkb7OA3ySgXlTpQsb
+Q1E5D+prEI6fTKeqytar9NR2FuOc61kEEmN4ACdEX5FWSYM0grAm68BfJ3Q2IHCV
+pVMF4ExSWlRb05k3TK1HDqjoj8uXMACmz5XAU+69q8ydh3B1LrQYS2V5IDEgPGtl
+eTFAZXhhbXBsZS5vcmc+iF4EExECAB4FAkPN6eMCGwMGCwkIBwMCAxUCAwMWAgEC
+HgECF4AACgkQRrtV8IhcZaSq1QCeObAJFNF3yGlgfV26ACIZyM84gXcAn1yM0T5/
+Qcwkbeu4J/e2PKw/uQ7QuQINBEPN6eoQCACMxxJidY6L1c5zHgU7vZ3yRvnp8tkr
+ShyNtwj6MCgyp9kHK8lgndsIpwXWxfXsSbTPT6wtdH15is7uitHjG1tKphmNgkTH
+KEE62ZMAP5XSfr0ntd9fMxGAqlKcsjdnkC4m/FQzJSFQRnZE9OsGMbACaCtEfc6t
+LU8e3th/tyFCT3nTkfHLYmfVeBWjbsZPoAVcDVAs094E05EmA7lg72PJwzgxyKRM
+4rO1DLgUf9zeXbukYA98SMAPLzf1X9/zY4CfMCicrFkFOkul/maXF7chfxrQqabn
+etu9XvAO/nxE5lJvtHu0hQotmK3WyAQidPP+fx3dPO2SLVi2bEt4Wy7HAAMFB/4n
+rQbjh1x5fjNyLu+UlQL8xpKf3NDreP7ncvUmXn516wNxzk8S5KEDrxAwevEeixxY
+2LPTE4FbbUhIEkRilz22YIWxrFaKywAkbomGFaHkj5miily2daS1bxYidkjb4mGU
+DFujMMIOqI1N3Ag4lNo9NP7XkESj6uqcBOS6pd735pFg0j3+9+HGT1e1dwynoMdS
+60oSnCMEaD2xod1T5We2vofgwj53w/4yug0h84dWYSKFfgOgycslBJ1Z2aJDp664
+/Ora5PpPjBw6pHklvmOiLWD0UEL3nv/B7UxU+UgD3fYZ63j5RKuvmzw9YdHtVUyH
+kRy7A70j1pHt1aDt7GqoiEkEGBECAAkFAkPN6eoCGwwACgkQRrtV8IhcZaR5XACf
+fc3iRAkf1hOGAx7Qi4yIqfVoG+4AoIAlsvKuGQ/9Q7fSSBsp1mWTLl4D
+=A4B6
+-----END PGP PUBLIC KEY BLOCK-----
--- /dev/null
+-----BEGIN PGP PRIVATE KEY BLOCK-----
+Version: GnuPG v1.4.1 (GNU/Linux)
+
+lQG7BEPN6eMRBAC3/jKHCnI9c9fATgGLV4x53wN6ZZoqzcgks4rR9BgrYLvPBzDX
+em74/m5uRMY90hGzJw8kb/rG8ZznJTU/ZE50qCmEEQuTyZar80LEb4ujbqTfZzGK
+v3blpSS+f5ON+2VATiL85roJ7BhpMnhUvS7nk/rSoKFYz+sdf/l3SR76ywCgg+OK
+ISC9UWqI9wlyhs7BpZib6SkEAJ7SzSDHNFI0Uvl5/+QYwy1N9IxCx6po7OJuBFK8
+9XBSbqRnnrlcCko/qTIuPxy9R9g+0JPhi2cNB++f3I/TPz73Xsg7JjkNnqD7aZS7
+MXRlzxESuu7Br+JVwzIERfXDLuA0pnMy+nt1mhuUFxc4dFEzD0DDsbFNWmo57rlr
+t2BZA/4naBrB6L763BMIzebjTCOJ5d0/4pbqlQrP2O+2BxKvkb7OA3ySgXlTpQsb
+Q1E5D+prEI6fTKeqytar9NR2FuOc61kEEmN4ACdEX5FWSYM0grAm68BfJ3Q2IHCV
+pVMF4ExSWlRb05k3TK1HDqjoj8uXMACmz5XAU+69q8ydh3B1LgAAni2eZ4K2MRJq
+oqJc5SsgIMHzLXw2CTi0GEtleSAxIDxrZXkxQGV4YW1wbGUub3JnPoheBBMRAgAe
+BQJDzenjAhsDBgsJCAcDAgMVAgMDFgIBAh4BAheAAAoJEEa7VfCIXGWkqtUAnjI7
+uB1911Iaf5Ab4xmriEfKbj+EAJ93FeHcuajBs6TEoLKLNetpCf8TCJ0CPQRDzenq
+EAgAjMcSYnWOi9XOcx4FO72d8kb56fLZK0ocjbcI+jAoMqfZByvJYJ3bCKcF1sX1
+7Em0z0+sLXR9eYrO7orR4xtbSqYZjYJExyhBOtmTAD+V0n69J7XfXzMRgKpSnLI3
+Z5AuJvxUMyUhUEZ2RPTrBjGwAmgrRH3OrS1PHt7Yf7chQk9505Hxy2Jn1XgVo27G
+T6AFXA1QLNPeBNORJgO5YO9jycM4McikTOKztQy4FH/c3l27pGAPfEjADy839V/f
+82OAnzAonKxZBTpLpf5mlxe3IX8a0Kmm53rbvV7wDv58ROZSb7R7tIUKLZit1sgE
+InTz/n8d3Tztki1YtmxLeFsuxwADBQf+J60G44dceX4zci7vlJUC/MaSn9zQ63j+
+53L1Jl5+desDcc5PEuShA68QMHrxHoscWNiz0xOBW21ISBJEYpc9tmCFsaxWissA
+JG6JhhWh5I+ZoopctnWktW8WInZI2+JhlAxbozDCDqiNTdwIOJTaPTT+15BEo+rq
+nATkuqXe9+aRYNI9/vfhxk9XtXcMp6DHUutKEpwjBGg9saHdU+Vntr6H4MI+d8P+
+MroNIfOHVmEihX4DoMnLJQSdWdmiQ6euuPzq2uT6T4wcOqR5Jb5joi1g9FBC957/
+we1MVPlIA932Get4+USrr5s8PWHR7VVMh5EcuwO9I9aR7dWg7exqqAABUwYkXGcj
+ydeyTvGPtJx23TAu6UCJ9ycRv1DEjZXgyz/0KJa8MuLdp6PKq/YYWYhJBBgRAgAJ
+BQJDzenqAhsMAAoJEEa7VfCIXGWkeVwAn1Z2OsXbZ32B+U/jvl5QG0NE66+cAJ4r
+jyoVKtrbw0t7+xoBOMft2cv6Xw==
+=kwYN
+-----END PGP PRIVATE KEY BLOCK-----
--- /dev/null
+-----BEGIN PGP PUBLIC KEY BLOCK-----
+Version: GnuPG v1.4.1 (GNU/Linux)
+
+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
+zw+9DaUWqQ==
+=guWc
+-----END PGP PUBLIC KEY BLOCK-----
--- /dev/null
+-----BEGIN PGP PRIVATE KEY BLOCK-----
+Version: GnuPG v1.4.1 (GNU/Linux)
+
+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
+FTstUwJS/LPkRekNydTPD70NpRap
+=e8Ot
+-----END PGP PRIVATE KEY BLOCK-----
--- /dev/null
+-----BEGIN PGP PUBLIC KEY BLOCK-----
+Version: GnuPG v1.4.1 (GNU/Linux)
+
+mQGiBEPN7RMRBACqAXL6t6ZVuyFkjqM8FH52eN06p+XFHG+PqxXYTnUUWyumLO5T
+Pjmpgf22QmHnSI6IaB13rC7v5gA2B4z5P6/j/LTV51d/T/0thFy/p7XINSBw+CES
+6RpST3AWdkmj+TvX4Kb4xP9klIbcC3cFexLKjWe+V78Nli05DpqR3V8rZwCguKwn
+MyaMS4smhncgSbdFZ/jSbN8D/iU7vlQ2r1tiH5G70WWyeV/+8Rz/gOEhlKo+Yfds
+x3t94qpWr+qn7u9615w9eX4WYyGmRXdxEzQqAyagqkXZBNyPNE1nA6/lCx/2hAlQ
+mPOSN2F7YII29RuRjNF3Cd1z/RuobP0yjmXyIYOo4Qf1/GKHWjp0Xu+qcCPDmnmD
+a6YHA/0Xwe2VSY9BQg74FI+L7C83R3Xm9qubgkWpyYwrpN/aSlVCywqG3VjYNAZ5
+RvXfkFW43r0dURAMz6I01X/LrkIWxvgz2pii7qfjs1pBGNM2kYK3Vwzcdp7Lg9uf
+/c5aljGBDpn7SF4jBenOPH51LYI8N9NIMioEmOyaD1jrBvmk7ohcBCARAgAcBQJD
+ze1GFR0DVGVzdCBvZiByZXZva2VkIGtleQAKCRAu9ljJh3VDaH0bAJ9K2nuztlmt
+b8tMy9+FApwomHC0kQCfSLAgQa9hZS1TyPtHXGAMoghNif20HVJldm9rZWQgPHJl
+dm9rZWRAZXhhbXBsZS5vcmc+iF4EExECAB4FAkPN7RMCGwMGCwkIBwMCAxUCAwMW
+AgECHgECF4AACgkQLvZYyYd1Q2jE8gCeP9IXvrznkFehQGBMf3gGeO57GJgAn2uL
+DkgH811s1LN9GKqKBGbCLH5CuQENBEPN7RcQBADoHXOivf3MqUR99JJTQtYo9b3f
+zQzZIgMtqmOwCFfe/jWA0VNf1svUemhXgiqi/gQUC2JLIJgIArhlxey5mU1gn7L/
+OMtwKfXD5zUrOKptTby8RIcySv20LR+vh6SmeYTI9ELdlwrG2efYDWtl2jBodnHf
+1u38PjzE2NhvqqjdNwADBQQAlIbPfQmFSnB8YRsLCq6w9Qc/kqwPcAgGbPsIaFsG
+qLc0HRk4/SivyH+i/TTUlpcQ3gXoZ/eUInO9R2IMmQzg+J4XAtx/llSJ0krO27Cy
+qs0QLdvtpaN9dvunhf7FGduHmJys8uPcxo6h/TvBsVUF1ZJCWZzCT7iMOjUZYSau
+99SISQQYEQIACQUCQ83tFwIbDAAKCRAu9ljJh3VDaOcpAKCFql4b4u7YEr3enZx5
+3c2YXJUubQCeP+/3+KFxmfr+NS5d08JjplMT96I=
+=+ttA
+-----END PGP PUBLIC KEY BLOCK-----
--- /dev/null
+-----BEGIN PGP PUBLIC KEY BLOCK-----
+Version: GnuPG v1.4.1 (GNU/Linux)
+
+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
+IiupsX+7alW4D8gI++6xtVTyanhtymAW
+=WN/+
+-----END PGP PUBLIC KEY BLOCK-----
--- /dev/null
+-----BEGIN PGP PRIVATE KEY BLOCK-----
+Version: GnuPG v1.4.1 (GNU/Linux)
+
+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
+ewllGZCqbWy9TQ==
+=pPlO
+-----END PGP PRIVATE KEY BLOCK-----
--- /dev/null
+# pygpgme - a Python wrapper for the gpgme library
+# Copyright (C) 2006 James Henstridge
+#
+# This library is free software; you can redistribute it and/or
+# modify it under the terms of the GNU Lesser General Public
+# License as published by the Free Software Foundation; either
+# version 2.1 of the License, or (at your option) any later version.
+#
+# This library is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+# Lesser General Public License for more details.
+#
+# You should have received a copy of the GNU Lesser General Public
+# License along with this library; if not, write to the Free Software
+# Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
+
+import unittest
+
+import gpgme
+from gpgme.tests.util import GpgHomeTestCase
+
+class ContextTestCase(GpgHomeTestCase):
+
+ def test_constructor(self):
+ ctx = gpgme.Context()
+
+ def test_protocol(self):
+ ctx = gpgme.Context()
+ # XXX: this should use symbolic constant names
+ self.assertEqual(ctx.protocol, gpgme.PROTOCOL_OpenPGP)
+ ctx.protocol = gpgme.PROTOCOL_CMS
+ self.assertEqual(ctx.protocol, gpgme.PROTOCOL_CMS)
+ ctx.protocol = gpgme.PROTOCOL_OpenPGP
+ self.assertEqual(ctx.protocol, gpgme.PROTOCOL_OpenPGP)
+
+ # check error on setting to invalid protocol value
+ def set_protocol(ctx, value):
+ ctx.protocol = value
+ self.assertRaises(gpgme.GpgmeError, set_protocol, ctx, 999)
+
+ def del_protocol(ctx):
+ del ctx.protocol
+ self.assertRaises(TypeError, del_protocol, ctx)
+
+ def test_armor(self):
+ ctx = gpgme.Context()
+ self.assertEqual(ctx.armor, False)
+ ctx.armor = True
+ self.assertEqual(ctx.armor, True)
+ ctx.armor = False
+ self.assertEqual(ctx.armor, False)
+
+ def del_armor(ctx):
+ del ctx.armor
+ self.assertRaises(TypeError, del_armor, ctx)
+
+ def test_textmode(self):
+ ctx = gpgme.Context()
+ self.assertEqual(ctx.textmode, False)
+ ctx.textmode = True
+ self.assertEqual(ctx.textmode, True)
+ ctx.textmode = False
+ self.assertEqual(ctx.textmode, False)
+
+ def del_textmode(ctx):
+ del ctx.textmode
+ self.assertRaises(TypeError, del_textmode, ctx)
+
+ def test_include_certs(self):
+ ctx = gpgme.Context()
+ self.assertEqual(ctx.include_certs, 1)
+ ctx.include_certs = 2
+ self.assertEqual(ctx.include_certs, 2)
+
+ def del_include_certs(ctx):
+ del ctx.include_certs
+ self.assertRaises(TypeError, del_include_certs, ctx)
+
+ def test_keylist_mode(self):
+ ctx = gpgme.Context()
+ self.assertEqual(ctx.keylist_mode, gpgme.KEYLIST_MODE_LOCAL)
+ ctx.keylist_mode = gpgme.KEYLIST_MODE_EXTERN
+ self.assertEqual(ctx.keylist_mode, gpgme.KEYLIST_MODE_EXTERN)
+ ctx.keylist_mode = gpgme.KEYLIST_MODE_LOCAL | gpgme.KEYLIST_MODE_EXTERN
+ self.assertEqual(ctx.keylist_mode,
+ gpgme.KEYLIST_MODE_LOCAL | gpgme.KEYLIST_MODE_EXTERN)
+
+ # check error on setting to invalid keylist_mode value
+ def set_keylist_mode(ctx, value):
+ ctx.keylist_mode = value
+ self.assertRaises(gpgme.GpgmeError, set_keylist_mode, ctx, 128)
+
+ def del_keylist_mode(ctx):
+ del ctx.keylist_mode
+ self.assertRaises(TypeError, del_keylist_mode, ctx)
+
+ def test_passphrase_cb(self):
+ ctx = gpgme.Context()
+ def passphrase_cb(uid_hint, passphrase_info, prev_was_bad, fd):
+ pass
+ self.assertEqual(ctx.passphrase_cb, None)
+ ctx.passphrase_cb = passphrase_cb
+ self.assertEqual(ctx.passphrase_cb, passphrase_cb)
+ ctx.passphrase_cb = None
+ self.assertEqual(ctx.passphrase_cb, None)
+ ctx.passphrase_cb = passphrase_cb
+ del ctx.passphrase_cb
+ self.assertEqual(ctx.passphrase_cb, None)
+
+ def test_progress_cb(self):
+ ctx = gpgme.Context()
+ def progress_cb(what, type, current, total):
+ pass
+ self.assertEqual(ctx.progress_cb, None)
+ ctx.progress_cb = progress_cb
+ self.assertEqual(ctx.progress_cb, progress_cb)
+ ctx.progress_cb = None
+ self.assertEqual(ctx.progress_cb, None)
+ ctx.progress_cb = progress_cb
+ del ctx.progress_cb
+ self.assertEqual(ctx.progress_cb, None)
+
+
+def test_suite():
+ loader = unittest.TestLoader()
+ return loader.loadTestsFromName(__name__)
--- /dev/null
+# pygpgme - a Python wrapper for the gpgme library
+# Copyright (C) 2006 James Henstridge
+#
+# This library is free software; you can redistribute it and/or
+# modify it under the terms of the GNU Lesser General Public
+# License as published by the Free Software Foundation; either
+# version 2.1 of the License, or (at your option) any later version.
+#
+# This library is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+# Lesser General Public License for more details.
+#
+# You should have received a copy of the GNU Lesser General Public
+# License along with this library; if not, write to the Free Software
+# Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
+
+import unittest
+import StringIO
+
+import gpgme
+from gpgme.tests.util import GpgHomeTestCase
+
+class DeleteTestCase(GpgHomeTestCase):
+
+ import_keys = ['key1.pub', 'key1.sec', 'key2.pub']
+
+ def test_delete_public_key(self):
+ ctx = gpgme.Context()
+ # key2
+ key = ctx.get_key('93C2240D6B8AA10AB28F701D2CF46B7FC97E6B0F')
+ ctx.delete(key)
+
+ # check that it is deleted
+ self.assertRaises(gpgme.GpgmeError, ctx.get_key,
+ '93C2240D6B8AA10AB28F701D2CF46B7FC97E6B0F')
+
+ def test_delete_public_key_with_secret_key(self):
+ ctx = gpgme.Context()
+ # key1
+ key = ctx.get_key('E79A842DA34A1CA383F64A1546BB55F0885C65A4')
+ self.assertRaises(gpgme.GpgmeError, ctx.delete, key)
+
+ def test_delete_secret_key(self):
+ ctx = gpgme.Context()
+ # key1
+ key = ctx.get_key('E79A842DA34A1CA383F64A1546BB55F0885C65A4')
+ ctx.delete(key, True)
+
+ def test_delete_non_existant(self):
+ ctx = gpgme.Context()
+ # key2
+ key = ctx.get_key('93C2240D6B8AA10AB28F701D2CF46B7FC97E6B0F')
+ ctx.delete(key)
+
+ # delete it again
+ try:
+ ctx.delete(key)
+ except gpgme.GpgmeError, exc:
+ self.assertEqual(exc[0], gpgme.ERR_SOURCE_GPGME)
+ self.assertEqual(exc[1], gpgme.ERR_NO_PUBKEY)
+ else:
+ self.fail('gpgme.GpgmeError was not raised')
+
+
+def test_suite():
+ loader = unittest.TestLoader()
+ return loader.loadTestsFromName(__name__)
--- /dev/null
+# pygpgme - a Python wrapper for the gpgme library
+# Copyright (C) 2006 James Henstridge
+#
+# This library is free software; you can redistribute it and/or
+# modify it under the terms of the GNU Lesser General Public
+# License as published by the Free Software Foundation; either
+# version 2.1 of the License, or (at your option) any later version.
+#
+# This library is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+# Lesser General Public License for more details.
+#
+# You should have received a copy of the GNU Lesser General Public
+# License along with this library; if not, write to the Free Software
+# Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
+
+import unittest
+import os
+import StringIO
+
+import gpgme
+import gpgme.editutil
+from gpgme.tests.util import GpgHomeTestCase
+
+class EditKeyTestCase(GpgHomeTestCase):
+
+ import_keys = ['key1.pub', 'key1.sec', 'key2.pub',
+ 'signonly.pub', 'signonly.sec']
+
+ def edit_quit_cb(self, status, args, fd):
+ if status in [gpgme.STATUS_EOF, gpgme.STATUS_GOT_IT]:
+ return
+ self.status = status
+ self.args = args
+ os.write(fd, 'quit\n')
+
+ def test_edit_quit(self):
+ ctx = gpgme.Context()
+ key = ctx.get_key('E79A842DA34A1CA383F64A1546BB55F0885C65A4')
+ output = StringIO.StringIO()
+
+ self.status = None
+ self.args = None
+ ctx.edit(key, self.edit_quit_cb, output)
+
+ self.assertEqual(self.status, gpgme.STATUS_GET_LINE)
+ self.assertEqual(self.args, 'keyedit.prompt')
+
+ def test_edit_ownertrust(self):
+ ctx = gpgme.Context()
+ key = ctx.get_key('93C2240D6B8AA10AB28F701D2CF46B7FC97E6B0F')
+ self.assertEqual(key.owner_trust, gpgme.VALIDITY_UNKNOWN)
+
+ # try setting each validity:
+ for trust in [gpgme.VALIDITY_NEVER,
+ gpgme.VALIDITY_MARGINAL,
+ gpgme.VALIDITY_FULL,
+ gpgme.VALIDITY_ULTIMATE]:
+ gpgme.editutil.edit_trust(ctx, key, trust)
+ key = ctx.get_key('93C2240D6B8AA10AB28F701D2CF46B7FC97E6B0F')
+ self.assertEqual(key.owner_trust, trust)
+
+ def test_edit_sign(self):
+ ctx = gpgme.Context()
+ # we set the keylist mode so we can see signatures
+ ctx.keylist_mode = gpgme.KEYLIST_MODE_SIGS
+ ctx.signers = [ctx.get_key('15E7CE9BF1771A4ABC550B31F540A569CB935A42')]
+ key = ctx.get_key('E79A842DA34A1CA383F64A1546BB55F0885C65A4')
+
+ # check that there are no signatures from 0xCB935A42
+ for uid in key.uids:
+ sigs = [sig for sig in uid.signatures
+ if sig.keyid == 'F540A569CB935A42']
+ self.assertEqual(len(sigs), 0)
+
+ gpgme.editutil.edit_sign(ctx, key, check=0)
+ key = ctx.get_key('E79A842DA34A1CA383F64A1546BB55F0885C65A4')
+
+ # check that there is a signature from 0xCB935A42 on each UID
+ for uid in key.uids:
+ sigs = [sig for sig in uid.signatures
+ if sig.keyid == 'F540A569CB935A42']
+ self.assertEqual(len(sigs), 1)
+
+
+def test_suite():
+ loader = unittest.TestLoader()
+ return loader.loadTestsFromName(__name__)
--- /dev/null
+# pygpgme - a Python wrapper for the gpgme library
+# Copyright (C) 2006 James Henstridge
+#
+# This library is free software; you can redistribute it and/or
+# modify it under the terms of the GNU Lesser General Public
+# License as published by the Free Software Foundation; either
+# version 2.1 of the License, or (at your option) any later version.
+#
+# This library is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+# Lesser General Public License for more details.
+#
+# You should have received a copy of the GNU Lesser General Public
+# License along with this library; if not, write to the Free Software
+# Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
+
+import unittest
+import StringIO
+from textwrap import dedent
+
+import gpgme
+from gpgme.tests.util import GpgHomeTestCase
+
+class EncryptDecryptTestCase(GpgHomeTestCase):
+
+ import_keys = ['key1.pub', 'key1.sec', 'key2.pub', 'key2.sec',
+ 'signonly.pub', 'signonly.sec']
+
+ def test_decrypt(self):
+ ciphertext = StringIO.StringIO(dedent('''
+ -----BEGIN PGP MESSAGE-----
+ Version: GnuPG v1.4.1 (GNU/Linux)
+
+ hQIMA6lSIdANy91kARAAtXjViihD6DVBAYGdVs0a2sMPGRXjIR5Tw1ONKx4MtKn+
+ pydR+/+0rBRGaQXe/mMODA8gqADQjz7PcTMWBa7ja969+K2nw7j5DUIMatonQVMf
+ vpc7ze5hovZ1jXYAgmmXdUzDmk8ZkpHaEc5mMMAHYKFn+mm37AFY5JUjg2Ae9k3H
+ 29t+pW+n9ncn/QBImW3oVslZ8Fza1xOIWZTUrmvtU0vELdlIxy+d945bvD9EhmTK
+ zRrD5m8V1etWINO2tE1Xhd4lV1KxncHzWafXLB5BKprztTqFUXNPAfnucYIczDon
+ 5VvkOz3WAtl/93o85hUKhbgGK0dvU3m+bj620ZUE5oDpPB4l1CiO5RqUFYtyN4LF
+ OSAceVOh7X764VLtpAzuOpNfTYgvzIFJqrFOZHlf3XJRdGdpJuxMe8BwhdLyDscx
+ pap4QxajOUSUAeS45x6ERA7xHO0QOwXZNzoxiOt9KRaoIhEacu70A9xRcGNJfZE2
+ 3z/AEMKr2CK6ny9/S8UQEhNvn1/gYfSXakFjWjM6PUXJSnz8WGjpFKKITpex3WBz
+ m/X8bKgG3fT92zqJdYocrl4wgz4Dt3+KirnGG4gITxaEYpTT0y6l6NAO60De0oRh
+ yqk+ulj2pvAlA82Ph0vTGZ9uOQGbrfN+NhwsG0HMNq+vmjShS1jJbSfoEt1AAIPS
+ RwGMq7SDk/V7nhKqZcxeIWdtRIgFvEf0KljthkOZxT/GozNjQclak7Kt69K2qyvt
+ XUfidNAhuOmeZ4pF31qSFiAnKRbzjzHp
+ =1s5N
+ -----END PGP MESSAGE-----
+ '''))
+ plaintext = StringIO.StringIO()
+ ctx = gpgme.Context()
+ ctx.decrypt(ciphertext, plaintext)
+ self.assertEqual(plaintext.getvalue(), 'hello world\n')
+
+ def test_decrypt_verify(self):
+ ciphertext = StringIO.StringIO(dedent('''
+ -----BEGIN PGP MESSAGE-----
+ Version: GnuPG v1.4.1 (GNU/Linux)
+
+ hQIMA6lSIdANy91kAQ/9GGQxL/OWvxrTchSMmIhsvwONJNlFE5cMIC0xejY4eN+t
+ HtTg8V1fWXLRw7WY6FNFLeoR2hzqaZWw15lU55TmSJfJmK2mdUZu/IhSpCUFMEFW
+ ZQpxslKq7N+S8NZHgq1WG32Ar1auOEflBQUMhj7sRSAtkvU7fWrTwf4Q4mcIV68P
+ LiAAQoKxXNNVam9+EV/b3kx3bnJPKTn+ArpJf5Im+5XOGOeu9Ll0QUTbicgFhfpR
+ esR6dKI/Ji5FGIu01kYNrDjDeMcJuzI52kNNoT+GJ72R+Gp4bZk2ycd+eVo3eeUW
+ klO8K+7E5bd5ni+1H+ZWbVp9bn7Q++mFP6Mruv+v9Di5mvFXxMoFuB/8NzcilFVt
+ h5VOexW1OaZk2bMp9bXVja/N7Y1oAADhINk0feaKkwYVOBJU9kJtL2O1WQui85Q3
+ 2dsL0YRJiR6mXesTezglZO44gsVAvCH8RUCtBnfEazfBg4jhcCHy6ooDgd0M4vcw
+ xG4U7IyDU5xyLi9QrTaSg5LzzwNFqb5k/lTemZw3ob3uwZinWewASLwn5N5OPVRs
+ gFT0eL0TfvDzHURsM/7QDvq9HX6JS7buyOlr5cZAsdSvm0FyE6YOkSvZR2jwp3vV
+ jfs7RHjq9V7jzPVVKHnWEDoJfchkT/3KyMRCIM/ukBk9MwTZTIJRhjTA2Xd4kWTS
+ kQEaU/OjumXPtw/T1pUH23nAkVssHsj8qgtxkFSmG/wrwNmfYx4tDhvgsHMJhar9
+ hqQKBMsGmLD6RNWKhF/LryNBKI2IRgJabKKYbbOsydom/hw8ZF4aWaZTcCBMoBB2
+ nhOi8WEIeWp93FGfHBa60nSBNGwgt24NmoFaXMjnCrJY/yK0L0MAajUC150OhtvG
+ OSk=
+ =fl3U
+ -----END PGP MESSAGE-----
+ '''))
+ plaintext = StringIO.StringIO()
+ ctx = gpgme.Context()
+ sigs = ctx.decrypt_verify(ciphertext, plaintext)
+ self.assertEqual(plaintext.getvalue(), 'hello world\n')
+ self.assertEqual(len(sigs), 1)
+ self.assertEqual(sigs[0].summary, 0)
+ self.assertEqual(sigs[0].fpr,
+ 'E79A842DA34A1CA383F64A1546BB55F0885C65A4')
+ self.assertEqual(sigs[0].status, None)
+ self.assertEqual(sigs[0].notations, [])
+ self.assertEqual(sigs[0].timestamp, 1138049495)
+ self.assertEqual(sigs[0].exp_timestamp, 0)
+ self.assertEqual(sigs[0].wrong_key_usage, False)
+ self.assertEqual(sigs[0].validity, gpgme.VALIDITY_UNKNOWN)
+ self.assertEqual(sigs[0].validity_reason, None)
+
+ def test_encrypt(self):
+ plaintext = StringIO.StringIO('Hello World\n')
+ ciphertext = StringIO.StringIO()
+ ctx = gpgme.Context()
+ recipient = ctx.get_key('93C2240D6B8AA10AB28F701D2CF46B7FC97E6B0F')
+ ctx.encrypt([recipient], gpgme.ENCRYPT_ALWAYS_TRUST,
+ plaintext, ciphertext)
+
+ # rewind ciphertext buffer, and try to decrypt:
+ ciphertext.seek(0)
+ plaintext = StringIO.StringIO()
+ ctx.decrypt(ciphertext, plaintext)
+ self.assertEqual(plaintext.getvalue(), 'Hello World\n')
+
+ def test_encrypt_armor(self):
+ plaintext = StringIO.StringIO('Hello World\n')
+ ciphertext = StringIO.StringIO()
+ ctx = gpgme.Context()
+ ctx.armor = True
+ recipient = ctx.get_key('93C2240D6B8AA10AB28F701D2CF46B7FC97E6B0F')
+ ctx.encrypt([recipient], gpgme.ENCRYPT_ALWAYS_TRUST,
+ plaintext, ciphertext)
+
+ # rewind ciphertext buffer, and try to decrypt:
+ ciphertext.seek(0)
+ plaintext = StringIO.StringIO()
+ ctx.decrypt(ciphertext, plaintext)
+ self.assertEqual(plaintext.getvalue(), 'Hello World\n')
+
+ def test_encrypt_sign(self):
+ plaintext = StringIO.StringIO('Hello World\n')
+ ciphertext = StringIO.StringIO()
+ ctx = gpgme.Context()
+ ctx.armor = True
+ signer = ctx.get_key('E79A842DA34A1CA383F64A1546BB55F0885C65A4')
+ recipient = ctx.get_key('93C2240D6B8AA10AB28F701D2CF46B7FC97E6B0F')
+ ctx.signers = [signer]
+ new_sigs = ctx.encrypt_sign([recipient], gpgme.ENCRYPT_ALWAYS_TRUST,
+ plaintext, ciphertext)
+
+ self.assertEqual(len(new_sigs), 1)
+ self.assertEqual(new_sigs[0].type, gpgme.SIG_MODE_NORMAL)
+ self.assertEqual(new_sigs[0].fpr,
+ 'E79A842DA34A1CA383F64A1546BB55F0885C65A4')
+
+ # rewind ciphertext buffer, and try to decrypt:
+ ciphertext.seek(0)
+ plaintext = StringIO.StringIO()
+ sigs = ctx.decrypt_verify(ciphertext, plaintext)
+ self.assertEqual(plaintext.getvalue(), 'Hello World\n')
+ self.assertEqual(len(sigs), 1)
+ self.assertEqual(sigs[0].summary, 0)
+ self.assertEqual(sigs[0].fpr,
+ 'E79A842DA34A1CA383F64A1546BB55F0885C65A4')
+ self.assertEqual(sigs[0].status, None)
+ self.assertEqual(sigs[0].wrong_key_usage, False)
+ self.assertEqual(sigs[0].validity, gpgme.VALIDITY_UNKNOWN)
+ self.assertEqual(sigs[0].validity_reason, None)
+
+ def test_encrypt_to_signonly(self):
+ plaintext = StringIO.StringIO('Hello World\n')
+ ciphertext = StringIO.StringIO()
+ ctx = gpgme.Context()
+ recipient = ctx.get_key('15E7CE9BF1771A4ABC550B31F540A569CB935A42')
+ try:
+ ctx.encrypt([recipient], gpgme.ENCRYPT_ALWAYS_TRUST,
+ plaintext, ciphertext)
+ except gpgme.GpgmeError, e:
+ self.assertEqual(e[0], gpgme.ERR_SOURCE_UNKNOWN)
+ self.assertEqual(e[1], gpgme.ERR_GENERAL)
+ else:
+ self.fail('gpgme.GpgmeError not raised')
+
+
+def test_suite():
+ loader = unittest.TestLoader()
+ return loader.loadTestsFromName(__name__)
--- /dev/null
+# pygpgme - a Python wrapper for the gpgme library
+# Copyright (C) 2006 James Henstridge
+#
+# This library is free software; you can redistribute it and/or
+# modify it under the terms of the GNU Lesser General Public
+# License as published by the Free Software Foundation; either
+# version 2.1 of the License, or (at your option) any later version.
+#
+# This library is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+# Lesser General Public License for more details.
+#
+# You should have received a copy of the GNU Lesser General Public
+# License along with this library; if not, write to the Free Software
+# Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
+
+import unittest
+import StringIO
+from textwrap import dedent
+
+import gpgme
+from gpgme.tests.util import GpgHomeTestCase
+
+class ExportTestCase(GpgHomeTestCase):
+
+ import_keys = ['signonly.pub', 'signonly.sec']
+
+ def test_export_by_fingerprint(self):
+ ctx = gpgme.Context()
+ ctx.armor = True
+ keydata = StringIO.StringIO()
+ ctx.export('15E7CE9BF1771A4ABC550B31F540A569CB935A42', keydata)
+
+ self.assertTrue(keydata.getvalue().startswith(
+ '-----BEGIN PGP PUBLIC KEY BLOCK-----\n'))
+
+ def test_export_by_email(self):
+ ctx = gpgme.Context()
+ ctx.armor = True
+ keydata = StringIO.StringIO()
+ ctx.export('signonly@example.org', keydata)
+
+ self.assertTrue(keydata.getvalue().startswith(
+ '-----BEGIN PGP PUBLIC KEY BLOCK-----\n'))
+
+ def test_export_by_name(self):
+ ctx = gpgme.Context()
+ ctx.armor = True
+ keydata = StringIO.StringIO()
+ ctx.export('Sign Only', keydata)
+
+ self.assertTrue(keydata.getvalue().startswith(
+ '-----BEGIN PGP PUBLIC KEY BLOCK-----\n'))
+
+
+def test_suite():
+ loader = unittest.TestLoader()
+ return loader.loadTestsFromName(__name__)
--- /dev/null
+# pygpgme - a Python wrapper for the gpgme library
+# Copyright (C) 2006 James Henstridge
+#
+# This library is free software; you can redistribute it and/or
+# modify it under the terms of the GNU Lesser General Public
+# License as published by the Free Software Foundation; either
+# version 2.1 of the License, or (at your option) any later version.
+#
+# This library is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+# Lesser General Public License for more details.
+#
+# You should have received a copy of the GNU Lesser General Public
+# License along with this library; if not, write to the Free Software
+# Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
+
+import unittest
+import StringIO
+
+import gpgme
+from gpgme.tests.util import GpgHomeTestCase
+
+class ImportTestCase(GpgHomeTestCase):
+
+ def test_import_file(self):
+ fp = self.keyfile('key1.pub')
+ ctx = gpgme.Context()
+ result = ctx.import_(fp)
+ self.assertEqual(result.considered, 1)
+ self.assertEqual(result.no_user_id, 0)
+ self.assertEqual(result.imported, 1)
+ self.assertEqual(result.imported_rsa, 0)
+ self.assertEqual(result.unchanged, 0)
+ self.assertEqual(result.new_user_ids, 0)
+ self.assertEqual(result.new_sub_keys, 0)
+ self.assertEqual(result.new_signatures, 0)
+ self.assertEqual(result.new_revocations, 0)
+ self.assertEqual(result.secret_read, 0)
+ self.assertEqual(result.secret_imported, 0)
+ self.assertEqual(result.secret_unchanged, 0)
+ self.assertEqual(result.skipped_new_keys, 0)
+ self.assertEqual(result.not_imported, 0)
+ self.assertEqual(len(result.imports), 1)
+ self.assertEqual(result.imports[0],
+ ('E79A842DA34A1CA383F64A1546BB55F0885C65A4',
+ None, gpgme.IMPORT_NEW))
+ # can we get the public key?
+ key = ctx.get_key('E79A842DA34A1CA383F64A1546BB55F0885C65A4')
+
+ def test_import_secret_file(self):
+ fp = self.keyfile('key1.sec')
+ ctx = gpgme.Context()
+ result = ctx.import_(fp)
+ self.assertEqual(result.considered, 1)
+ self.assertEqual(result.no_user_id, 0)
+ self.assertEqual(result.imported, 1)
+ self.assertEqual(result.imported_rsa, 0)
+ self.assertEqual(result.unchanged, 0)
+ self.assertEqual(result.new_user_ids, 0)
+ self.assertEqual(result.new_sub_keys, 0)
+ self.assertEqual(result.new_signatures, 0)
+ self.assertEqual(result.new_revocations, 0)
+ self.assertEqual(result.secret_read, 1)
+ self.assertEqual(result.secret_imported, 1)
+ self.assertEqual(result.secret_unchanged, 0)
+ self.assertEqual(result.skipped_new_keys, 0)
+ self.assertEqual(result.not_imported, 0)
+ self.assertEqual(len(result.imports), 2)
+ self.assertEqual(result.imports[0],
+ ('E79A842DA34A1CA383F64A1546BB55F0885C65A4',
+ None, gpgme.IMPORT_NEW | gpgme.IMPORT_SECRET))
+ self.assertEqual(result.imports[1],
+ ('E79A842DA34A1CA383F64A1546BB55F0885C65A4',
+ None, gpgme.IMPORT_NEW))
+ # can we get the public key?
+ key = ctx.get_key('E79A842DA34A1CA383F64A1546BB55F0885C65A4')
+ # can we get the secret key?
+ key = ctx.get_key('E79A842DA34A1CA383F64A1546BB55F0885C65A4', True)
+
+ def test_import_stringio(self):
+ fp = StringIO.StringIO(self.keyfile('key1.pub').read())
+ ctx = gpgme.Context()
+ result = ctx.import_(fp)
+ self.assertEqual(len(result.imports), 1)
+ self.assertEqual(result.imports[0],
+ ('E79A842DA34A1CA383F64A1546BB55F0885C65A4',
+ None, gpgme.IMPORT_NEW))
+ # can we get the public key?
+ key = ctx.get_key('E79A842DA34A1CA383F64A1546BB55F0885C65A4')
+
+ def test_import_concat(self):
+ keys = '\n'.join([self.keyfile('key1.pub').read(),
+ self.keyfile('key1.sec').read(),
+ self.keyfile('key2.pub').read()])
+ fp = StringIO.StringIO(keys)
+ ctx = gpgme.Context()
+ result = ctx.import_(fp)
+ self.assertEqual(result.considered, 3)
+ self.assertEqual(result.no_user_id, 0)
+ self.assertEqual(result.imported, 2)
+ self.assertEqual(result.imported_rsa, 1)
+ self.assertEqual(result.unchanged, 0)
+ self.assertEqual(result.new_user_ids, 0)
+ self.assertEqual(result.new_sub_keys, 0)
+ self.assertEqual(result.new_signatures, 1)
+ self.assertEqual(result.new_revocations, 0)
+ self.assertEqual(result.secret_read, 1)
+ self.assertEqual(result.secret_imported, 1)
+ self.assertEqual(result.secret_unchanged, 0)
+ self.assertEqual(result.skipped_new_keys, 0)
+ self.assertEqual(result.not_imported, 0)
+ self.assertEqual(len(result.imports), 4)
+ self.assertEqual(result.imports[0],
+ ('E79A842DA34A1CA383F64A1546BB55F0885C65A4',
+ None, gpgme.IMPORT_NEW))
+ self.assertEqual(result.imports[1],
+ ('E79A842DA34A1CA383F64A1546BB55F0885C65A4',
+ None, gpgme.IMPORT_NEW | gpgme.IMPORT_SECRET))
+ self.assertEqual(result.imports[2],
+ ('E79A842DA34A1CA383F64A1546BB55F0885C65A4',
+ None, gpgme.IMPORT_SIG))
+ self.assertEqual(result.imports[3],
+ ('93C2240D6B8AA10AB28F701D2CF46B7FC97E6B0F',
+ None, gpgme.IMPORT_NEW))
+ # can we get the public keys?
+ key = ctx.get_key('E79A842DA34A1CA383F64A1546BB55F0885C65A4')
+ key = ctx.get_key('93C2240D6B8AA10AB28F701D2CF46B7FC97E6B0F')
+ # can we get the secret key?
+ key = ctx.get_key('E79A842DA34A1CA383F64A1546BB55F0885C65A4', True)
+
+ def test_import_empty(self):
+ fp = StringIO.StringIO('')
+ ctx = gpgme.Context()
+ result = ctx.import_(fp)
+ self.assertEqual(result.considered, 0)
+ self.assertEqual(len(result.imports), 0)
+
+ def test_import_twice(self):
+ ctx = gpgme.Context()
+ fp = self.keyfile('key1.pub')
+ result = ctx.import_(fp)
+
+ fp = self.keyfile('key1.pub')
+ result = ctx.import_(fp)
+
+ self.assertEqual(result.considered, 1)
+ self.assertEqual(result.no_user_id, 0)
+ self.assertEqual(result.imported, 0)
+ self.assertEqual(result.imported_rsa, 0)
+ self.assertEqual(result.unchanged, 1)
+ self.assertEqual(result.new_user_ids, 0)
+ self.assertEqual(result.new_sub_keys, 0)
+ self.assertEqual(result.new_signatures, 0)
+ self.assertEqual(result.new_revocations, 0)
+ self.assertEqual(result.secret_read, 0)
+ self.assertEqual(result.secret_imported, 0)
+ self.assertEqual(result.secret_unchanged, 0)
+ self.assertEqual(result.skipped_new_keys, 0)
+ self.assertEqual(result.not_imported, 0)
+ self.assertEqual(len(result.imports), 1)
+ self.assertEqual(result.imports[0],
+ ('E79A842DA34A1CA383F64A1546BB55F0885C65A4', None, 0))
+ # can we get the public key?
+ key = ctx.get_key('E79A842DA34A1CA383F64A1546BB55F0885C65A4')
+
+def test_suite():
+ loader = unittest.TestLoader()
+ return loader.loadTestsFromName(__name__)
--- /dev/null
+# pygpgme - a Python wrapper for the gpgme library
+# Copyright (C) 2006 James Henstridge
+#
+# This library is free software; you can redistribute it and/or
+# modify it under the terms of the GNU Lesser General Public
+# License as published by the Free Software Foundation; either
+# version 2.1 of the License, or (at your option) any later version.
+#
+# This library is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+# Lesser General Public License for more details.
+#
+# You should have received a copy of the GNU Lesser General Public
+# License along with this library; if not, write to the Free Software
+# Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
+
+import unittest
+
+import gpgme
+from gpgme.tests.util import GpgHomeTestCase
+
+class KeylistTestCase(GpgHomeTestCase):
+
+ import_keys = ['key1.pub', 'key2.pub', 'revoked.pub', 'signonly.pub',
+ 'key1.sec']
+
+ def test_listall(self):
+ ctx = gpgme.Context()
+ keyids = set(key.subkeys[0].keyid for key in ctx.keylist())
+ self.assertTrue(keyids, set(['46BB55F0885C65A4',
+ '2CF46B7FC97E6B0F',
+ 'F540A569CB935A42',
+ '2EF658C987754368']))
+
+ def test_list_by_email(self):
+ ctx = gpgme.Context()
+ keyids = set(key.subkeys[0].keyid
+ for key in ctx.keylist('key1@example.org'))
+ self.assertTrue(keyids, set(['46BB55F0885C65A4']))
+ keyids = set(key.subkeys[0].keyid
+ for key in ctx.keylist(['key1@example.org',
+ 'signonly@example.com']))
+ self.assertTrue(keyids, set(['46BB55F0885C65A4', 'F540A569CB935A42']))
+
+ def test_list_by_name(self):
+ ctx = gpgme.Context()
+ keyids = set(key.subkeys[0].keyid
+ for key in ctx.keylist('Key 1'))
+ self.assertTrue(keyids, set(['46BB55F0885C65A4']))
+
+ def test_list_by_email_substring(self):
+ ctx = gpgme.Context()
+ keyids = set(key.subkeys[0].keyid
+ for key in ctx.keylist('@example.org'))
+ self.assertTrue(keyids, set(['46BB55F0885C65A4',
+ '2CF46B7FC97E6B0F',
+ 'F540A569CB935A42',
+ '2EF658C987754368']))
+
+ def test_list_secret(self):
+ ctx = gpgme.Context()
+ keyids = set(key.subkeys[0].keyid
+ for key in ctx.keylist(None, True))
+ self.assertTrue(keyids, set(['46BB55F0885C65A4']))
+
+
+def test_suite():
+ loader = unittest.TestLoader()
+ return loader.loadTestsFromName(__name__)
--- /dev/null
+# pygpgme - a Python wrapper for the gpgme library
+# Copyright (C) 2006 James Henstridge
+#
+# This library is free software; you can redistribute it and/or
+# modify it under the terms of the GNU Lesser General Public
+# License as published by the Free Software Foundation; either
+# version 2.1 of the License, or (at your option) any later version.
+#
+# This library is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+# Lesser General Public License for more details.
+#
+# You should have received a copy of the GNU Lesser General Public
+# License along with this library; if not, write to the Free Software
+# Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
+
+import unittest
+
+import gpgme
+from gpgme.tests.util import GpgHomeTestCase
+
+class KeyTestCase(GpgHomeTestCase):
+
+ import_keys = ['key1.pub', 'key2.pub', 'revoked.pub', 'signonly.pub']
+
+ def test_key1(self):
+ ctx = gpgme.Context()
+ key = ctx.get_key('E79A842DA34A1CA383F64A1546BB55F0885C65A4')
+ self.assertEqual(key.revoked, False)
+ self.assertEqual(key.expired, False)
+ self.assertEqual(key.invalid, False)
+ self.assertEqual(key.can_encrypt, True)
+ self.assertEqual(key.can_sign, True)
+ self.assertEqual(key.can_certify, True)
+ self.assertEqual(key.secret, False)
+ self.assertEqual(key.can_authenticate, False)
+ self.assertEqual(key.protocol, gpgme.PROTOCOL_OpenPGP)
+ self.assertEqual(len(key.subkeys), 2)
+ self.assertEqual(len(key.uids), 1)
+
+ self.assertEqual(key.subkeys[0].revoked, False)
+ self.assertEqual(key.subkeys[0].expired, False)
+ self.assertEqual(key.subkeys[0].disabled, False)
+ self.assertEqual(key.subkeys[0].invalid, False)
+ self.assertEqual(key.subkeys[0].can_encrypt, False)
+ self.assertEqual(key.subkeys[0].can_sign, True)
+ self.assertEqual(key.subkeys[0].can_certify, True)
+ self.assertEqual(key.subkeys[0].secret, False)
+ self.assertEqual(key.subkeys[0].can_authenticate, False)
+ self.assertEqual(key.subkeys[0].pubkey_algo, gpgme.PK_DSA)
+ self.assertEqual(key.subkeys[0].length, 1024)
+ self.assertEqual(key.subkeys[0].keyid, '46BB55F0885C65A4')
+ self.assertEqual(key.subkeys[0].fpr,
+ 'E79A842DA34A1CA383F64A1546BB55F0885C65A4')
+ self.assertEqual(key.subkeys[0].timestamp, 1137568227)
+ self.assertEqual(key.subkeys[0].expires, 0)
+
+ self.assertEqual(key.subkeys[1].revoked, False)
+ self.assertEqual(key.subkeys[1].expired, False)
+ self.assertEqual(key.subkeys[1].disabled, False)
+ self.assertEqual(key.subkeys[1].invalid, False)
+ self.assertEqual(key.subkeys[1].can_encrypt, True)
+ self.assertEqual(key.subkeys[1].can_sign, False)
+ self.assertEqual(key.subkeys[1].can_certify, False)
+ self.assertEqual(key.subkeys[1].secret, False)
+ self.assertEqual(key.subkeys[1].can_authenticate, False)
+ self.assertEqual(key.subkeys[1].pubkey_algo, gpgme.PK_ELG_E)
+ self.assertEqual(key.subkeys[1].length, 2048)
+ self.assertEqual(key.subkeys[1].keyid, '659A6AC69BC3B085')
+ self.assertEqual(key.subkeys[1].fpr, None)
+ self.assertEqual(key.subkeys[1].timestamp, 1137568234)
+ self.assertEqual(key.subkeys[1].expires, 0)
+
+ self.assertEqual(key.uids[0].revoked, False)
+ self.assertEqual(key.uids[0].invalid, False)
+ self.assertEqual(key.uids[0].validity, 0)
+ self.assertEqual(key.uids[0].uid, 'Key 1 <key1@example.org>')
+ self.assertEqual(key.uids[0].name, 'Key 1')
+ self.assertEqual(key.uids[0].email, 'key1@example.org')
+ self.assertEqual(key.uids[0].comment, '')
+
+ def test_key2(self):
+ ctx = gpgme.Context()
+ key = ctx.get_key('93C2240D6B8AA10AB28F701D2CF46B7FC97E6B0F')
+ self.assertEqual(key.revoked, False)
+ self.assertEqual(key.expired, False)
+ self.assertEqual(key.invalid, False)
+ self.assertEqual(key.can_encrypt, True)
+ self.assertEqual(key.can_sign, True)
+ self.assertEqual(key.can_certify, True)
+ self.assertEqual(key.secret, False)
+ self.assertEqual(key.can_authenticate, False)
+ self.assertEqual(key.protocol, gpgme.PROTOCOL_OpenPGP)
+ self.assertEqual(len(key.subkeys), 2)
+ self.assertEqual(len(key.uids), 1)
+
+ self.assertEqual(key.subkeys[0].revoked, False)
+ self.assertEqual(key.subkeys[0].expired, False)
+ self.assertEqual(key.subkeys[0].disabled, False)
+ self.assertEqual(key.subkeys[0].invalid, False)
+ self.assertEqual(key.subkeys[0].can_encrypt, False)
+ self.assertEqual(key.subkeys[0].can_sign, True)
+ self.assertEqual(key.subkeys[0].can_certify, True)
+ self.assertEqual(key.subkeys[0].secret, False)
+ self.assertEqual(key.subkeys[0].can_authenticate, False)
+ self.assertEqual(key.subkeys[0].pubkey_algo, gpgme.PK_RSA)
+ self.assertEqual(key.subkeys[0].length, 4096)
+ self.assertEqual(key.subkeys[0].keyid, '2CF46B7FC97E6B0F')
+ self.assertEqual(key.subkeys[0].fpr,
+ '93C2240D6B8AA10AB28F701D2CF46B7FC97E6B0F')
+ self.assertEqual(key.subkeys[0].timestamp, 1137568343)
+ self.assertEqual(key.subkeys[0].expires, 0)
+
+ self.assertEqual(key.subkeys[1].revoked, False)
+ self.assertEqual(key.subkeys[1].expired, False)
+ self.assertEqual(key.subkeys[1].disabled, False)
+ self.assertEqual(key.subkeys[1].invalid, False)
+ self.assertEqual(key.subkeys[1].can_encrypt, True)
+ self.assertEqual(key.subkeys[1].can_sign, False)
+ self.assertEqual(key.subkeys[1].can_certify, False)
+ self.assertEqual(key.subkeys[1].secret, False)
+ self.assertEqual(key.subkeys[1].can_authenticate, False)
+ self.assertEqual(key.subkeys[1].pubkey_algo, gpgme.PK_RSA)
+ self.assertEqual(key.subkeys[1].length, 4096)
+ self.assertEqual(key.subkeys[1].keyid, 'A95221D00DCBDD64')
+ self.assertEqual(key.subkeys[1].fpr, None)
+ self.assertEqual(key.subkeys[1].timestamp, 1137568395)
+ self.assertEqual(key.subkeys[1].expires, 0)
+
+ self.assertEqual(key.uids[0].revoked, False)
+ self.assertEqual(key.uids[0].invalid, False)
+ self.assertEqual(key.uids[0].validity, 0)
+ self.assertEqual(key.uids[0].uid, 'Key 2 <key2@example.org>')
+ self.assertEqual(key.uids[0].name, 'Key 2')
+ self.assertEqual(key.uids[0].email, 'key2@example.org')
+ self.assertEqual(key.uids[0].comment, '')
+
+ def test_revoked(self):
+ ctx = gpgme.Context()
+ key = ctx.get_key('B6525A39EB81F88B4D2CFB3E2EF658C987754368')
+ self.assertEqual(key.revoked, True)
+ self.assertEqual(key.expired, False)
+ self.assertEqual(key.invalid, False)
+ self.assertEqual(key.can_encrypt, False)
+ self.assertEqual(key.can_sign, True)
+ self.assertEqual(key.can_certify, True)
+ self.assertEqual(key.secret, False)
+ self.assertEqual(key.can_authenticate, False)
+ self.assertEqual(key.protocol, gpgme.PROTOCOL_OpenPGP)
+ self.assertEqual(len(key.subkeys), 2)
+ self.assertEqual(len(key.uids), 1)
+
+ self.assertEqual(key.subkeys[0].revoked, True)
+ self.assertEqual(key.subkeys[0].expired, False)
+ self.assertEqual(key.subkeys[0].disabled, False)
+ self.assertEqual(key.subkeys[0].invalid, False)
+ self.assertEqual(key.subkeys[0].can_encrypt, False)
+ self.assertEqual(key.subkeys[0].can_sign, True)
+ self.assertEqual(key.subkeys[0].can_certify, True)
+ self.assertEqual(key.subkeys[0].secret, False)
+ self.assertEqual(key.subkeys[0].can_authenticate, False)
+ self.assertEqual(key.subkeys[0].pubkey_algo, gpgme.PK_DSA)
+ self.assertEqual(key.subkeys[0].length, 1024)
+ self.assertEqual(key.subkeys[0].keyid, '2EF658C987754368')
+ self.assertEqual(key.subkeys[0].fpr,
+ 'B6525A39EB81F88B4D2CFB3E2EF658C987754368')
+ self.assertEqual(key.subkeys[0].timestamp, 1137569043)
+ self.assertEqual(key.subkeys[0].expires, 0)
+
+ self.assertEqual(key.subkeys[1].revoked, True)
+ self.assertEqual(key.subkeys[1].expired, False)
+ self.assertEqual(key.subkeys[1].disabled, False)
+ self.assertEqual(key.subkeys[1].invalid, False)
+ self.assertEqual(key.subkeys[1].can_encrypt, True)
+ self.assertEqual(key.subkeys[1].can_sign, False)
+ self.assertEqual(key.subkeys[1].can_certify, False)
+ self.assertEqual(key.subkeys[1].secret, False)
+ self.assertEqual(key.subkeys[1].can_authenticate, False)
+ self.assertEqual(key.subkeys[1].pubkey_algo, gpgme.PK_ELG_E)
+ self.assertEqual(key.subkeys[1].length, 1024)
+ self.assertEqual(key.subkeys[1].keyid, 'E50B59CF50CE4D54')
+ self.assertEqual(key.subkeys[1].fpr, None)
+ self.assertEqual(key.subkeys[1].timestamp, 1137569047)
+ self.assertEqual(key.subkeys[1].expires, 0)
+
+ self.assertEqual(key.uids[0].revoked, True)
+ self.assertEqual(key.uids[0].invalid, False)
+ self.assertEqual(key.uids[0].validity, 0)
+ self.assertEqual(key.uids[0].uid, 'Revoked <revoked@example.org>')
+ self.assertEqual(key.uids[0].name, 'Revoked')
+ self.assertEqual(key.uids[0].email, 'revoked@example.org')
+ self.assertEqual(key.uids[0].comment, '')
+
+ def test_signonly(self):
+ ctx = gpgme.Context()
+ key = ctx.get_key('15E7CE9BF1771A4ABC550B31F540A569CB935A42')
+ self.assertEqual(key.revoked, False)
+ self.assertEqual(key.expired, False)
+ self.assertEqual(key.invalid, False)
+ self.assertEqual(key.can_encrypt, False)
+ self.assertEqual(key.can_sign, True)
+ self.assertEqual(key.can_certify, True)
+ self.assertEqual(key.secret, False)
+ self.assertEqual(key.can_authenticate, False)
+ self.assertEqual(key.protocol, gpgme.PROTOCOL_OpenPGP)
+ self.assertEqual(len(key.subkeys), 1)
+ self.assertEqual(len(key.uids), 2)
+
+ self.assertEqual(key.subkeys[0].revoked, False)
+ self.assertEqual(key.subkeys[0].expired, False)
+ self.assertEqual(key.subkeys[0].disabled, False)
+ self.assertEqual(key.subkeys[0].invalid, False)
+ self.assertEqual(key.subkeys[0].can_encrypt, False)
+ self.assertEqual(key.subkeys[0].can_sign, True)
+ self.assertEqual(key.subkeys[0].can_certify, True)
+ self.assertEqual(key.subkeys[0].secret, False)
+ self.assertEqual(key.subkeys[0].can_authenticate, False)
+ self.assertEqual(key.subkeys[0].pubkey_algo, gpgme.PK_RSA)
+ self.assertEqual(key.subkeys[0].length, 4096)
+ self.assertEqual(key.subkeys[0].keyid, 'F540A569CB935A42')
+ self.assertEqual(key.subkeys[0].fpr,
+ '15E7CE9BF1771A4ABC550B31F540A569CB935A42')
+ self.assertEqual(key.subkeys[0].timestamp, 1137568835)
+ self.assertEqual(key.subkeys[0].expires, 0)
+
+ self.assertEqual(key.uids[0].revoked, False)
+ self.assertEqual(key.uids[0].invalid, False)
+ self.assertEqual(key.uids[0].validity, 0)
+ self.assertEqual(key.uids[0].uid, 'Sign Only <signonly@example.org>')
+ self.assertEqual(key.uids[0].name, 'Sign Only')
+ self.assertEqual(key.uids[0].email, 'signonly@example.org')
+ self.assertEqual(key.uids[0].comment, '')
+
+ self.assertEqual(key.uids[1].revoked, False)
+ self.assertEqual(key.uids[1].invalid, False)
+ self.assertEqual(key.uids[1].validity, 0)
+ self.assertEqual(key.uids[1].uid,
+ 'Sign Only (work address) <signonly@example.com>')
+ self.assertEqual(key.uids[1].name, 'Sign Only')
+ self.assertEqual(key.uids[1].email, 'signonly@example.com')
+ self.assertEqual(key.uids[1].comment, 'work address')
+
+
+def test_suite():
+ loader = unittest.TestLoader()
+ return loader.loadTestsFromName(__name__)
--- /dev/null
+# pygpgme - a Python wrapper for the gpgme library
+# Copyright (C) 2006 James Henstridge
+#
+# This library is free software; you can redistribute it and/or
+# modify it under the terms of the GNU Lesser General Public
+# License as published by the Free Software Foundation; either
+# version 2.1 of the License, or (at your option) any later version.
+#
+# This library is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+# Lesser General Public License for more details.
+#
+# You should have received a copy of the GNU Lesser General Public
+# License along with this library; if not, write to the Free Software
+# Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
+
+import unittest
+import os
+import StringIO
+from textwrap import dedent
+
+import gpgme
+from gpgme.tests.util import GpgHomeTestCase
+
+class PassphraseTestCase(GpgHomeTestCase):
+
+ import_keys = ['passphrase.pub', 'passphrase.sec']
+
+ def test_sign_without_passphrase_cb(self):
+ ctx = gpgme.Context()
+ key = ctx.get_key('EFB052B4230BBBC51914BCBB54DCBBC8DBFB9EB3')
+ ctx.signers = [key]
+ plaintext = StringIO.StringIO('Hello World\n')
+ signature = StringIO.StringIO()
+
+ try:
+ new_sigs = ctx.sign(plaintext, signature, gpgme.SIG_MODE_CLEAR)
+ except gpgme.GpgmeError, e:
+ self.assertEqual(e[0], gpgme.ERR_SOURCE_GPGME)
+ self.assertEqual(e[1], gpgme.ERR_BAD_PASSPHRASE)
+ else:
+ self.fail('gpgme.GpgmeError not raised')
+
+ def passphrase_cb(self, uid_hint, passphrase_info, prev_was_bad, fd):
+ self.uid_hint = uid_hint
+ self.passphrase_info = passphrase_info
+ self.prev_was_bad = prev_was_bad
+ os.write(fd, 'test\n')
+
+ def test_sign_with_passphrase_cb(self):
+ ctx = gpgme.Context()
+ key = ctx.get_key('EFB052B4230BBBC51914BCBB54DCBBC8DBFB9EB3')
+ ctx.signers = [key]
+ ctx.passphrase_cb = self.passphrase_cb
+ plaintext = StringIO.StringIO('Hello World\n')
+ signature = StringIO.StringIO()
+
+ self.uid_hint = None
+ self.passphrase_info = None
+ self.prev_was_bad = None
+ new_sigs = ctx.sign(plaintext, signature, gpgme.SIG_MODE_CLEAR)
+
+ # ensure that passphrase_cb has been run, and the data it was passed
+ self.assertEqual(self.uid_hint,
+ '54DCBBC8DBFB9EB3 Passphrase (test) <passphrase@example.org>')
+ self.assertEqual(self.passphrase_info,
+ '54DCBBC8DBFB9EB3 54DCBBC8DBFB9EB3 17 0')
+ self.assertEqual(self.prev_was_bad, False)
+
+ self.assertEqual(new_sigs[0].type, gpgme.SIG_MODE_CLEAR)
+ self.assertEqual(new_sigs[0].fpr,
+ 'EFB052B4230BBBC51914BCBB54DCBBC8DBFB9EB3')
+
+def test_suite():
+ loader = unittest.TestLoader()
+ return loader.loadTestsFromName(__name__)
--- /dev/null
+# pygpgme - a Python wrapper for the gpgme library
+# Copyright (C) 2006 James Henstridge
+#
+# This library is free software; you can redistribute it and/or
+# modify it under the terms of the GNU Lesser General Public
+# License as published by the Free Software Foundation; either
+# version 2.1 of the License, or (at your option) any later version.
+#
+# This library is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+# Lesser General Public License for more details.
+#
+# You should have received a copy of the GNU Lesser General Public
+# License along with this library; if not, write to the Free Software
+# Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
+
+import unittest
+import os
+import StringIO
+from textwrap import dedent
+
+import gpgme
+from gpgme.tests.util import GpgHomeTestCase
+
+class ProgressTestCase(GpgHomeTestCase):
+
+ import_keys = ['key1.pub', 'key1.sec']
+
+ def progress_cb(self, what, type_, current, total):
+ self.progress_cb_called = True
+
+ def test_sign_with_progress_cb(self):
+ ctx = gpgme.Context()
+ key = ctx.get_key('E79A842DA34A1CA383F64A1546BB55F0885C65A4')
+ ctx.signers = [key]
+ ctx.progress_cb = self.progress_cb
+ plaintext = StringIO.StringIO('Hello World\n')
+ signature = StringIO.StringIO()
+
+ self.progress_cb_called = False
+ new_sigs = ctx.sign(plaintext, signature, gpgme.SIG_MODE_CLEAR)
+
+ # ensure that progress_cb has been run
+ self.assertEqual(self.progress_cb_called, True)
+
+ self.assertEqual(new_sigs[0].type, gpgme.SIG_MODE_CLEAR)
+ self.assertEqual(new_sigs[0].fpr,
+ 'E79A842DA34A1CA383F64A1546BB55F0885C65A4')
+
+def test_suite():
+ loader = unittest.TestLoader()
+ return loader.loadTestsFromName(__name__)
--- /dev/null
+# pygpgme - a Python wrapper for the gpgme library
+# Copyright (C) 2006 James Henstridge
+#
+# This library is free software; you can redistribute it and/or
+# modify it under the terms of the GNU Lesser General Public
+# License as published by the Free Software Foundation; either
+# version 2.1 of the License, or (at your option) any later version.
+#
+# This library is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+# Lesser General Public License for more details.
+#
+# You should have received a copy of the GNU Lesser General Public
+# License along with this library; if not, write to the Free Software
+# Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
+
+import unittest
+import StringIO
+from textwrap import dedent
+
+import gpgme
+from gpgme.tests.util import GpgHomeTestCase
+
+class SignVerifyTestCase(GpgHomeTestCase):
+
+ import_keys = ['key1.pub', 'key1.sec', 'key2.pub', 'key2.sec',
+ 'signonly.pub', 'signonly.sec']
+
+ def test_verify_normal(self):
+ signature = StringIO.StringIO(dedent('''
+ -----BEGIN PGP MESSAGE-----
+ Version: GnuPG v1.4.1 (GNU/Linux)
+
+ owGbwMvMwCTotjv0Q0dM6hLG00JJDM7nNx31SM3JyVcIzy/KSeHqsGdmBQvCVAky
+ pR9hmGfw0qo3bfpWZwun5euYAsUcVkyZMJlhfvkU6UBjD8WF9RfeND05zC/TK+H+
+ EQA=
+ =HCW0
+ -----END PGP MESSAGE-----
+ '''))
+ plaintext = StringIO.StringIO()
+ ctx = gpgme.Context()
+ sigs = ctx.verify(signature, None, plaintext)
+
+ self.assertEqual(plaintext.getvalue(), 'Hello World\n')
+ self.assertEqual(len(sigs), 1)
+ self.assertEqual(sigs[0].summary, 0)
+ self.assertEqual(sigs[0].fpr,
+ 'E79A842DA34A1CA383F64A1546BB55F0885C65A4')
+ self.assertEqual(sigs[0].status, None)
+ self.assertEqual(sigs[0].notations, [])
+ self.assertEqual(sigs[0].timestamp, 1137685189)
+ self.assertEqual(sigs[0].exp_timestamp, 0)
+ self.assertEqual(sigs[0].wrong_key_usage, False)
+ self.assertEqual(sigs[0].validity, gpgme.VALIDITY_UNKNOWN)
+ self.assertEqual(sigs[0].validity_reason, None)
+
+ def test_verify_detached(self):
+ signature = StringIO.StringIO(dedent('''
+ -----BEGIN PGP SIGNATURE-----
+ Version: GnuPG v1.4.1 (GNU/Linux)
+
+ iD8DBQBDz7ReRrtV8IhcZaQRAtuUAJwMiJeS5QPohToxA3+vp+z5c3jr1wCdHhGP
+ hhSTiguzgSYNwKSuV6SLGOM=
+ =dyZS
+ -----END PGP SIGNATURE-----
+ '''))
+ signed_text = StringIO.StringIO('Hello World\n')
+ ctx = gpgme.Context()
+ sigs = ctx.verify(signature, signed_text, None)
+
+ self.assertEqual(len(sigs), 1)
+ self.assertEqual(sigs[0].summary, 0)
+ self.assertEqual(sigs[0].fpr,
+ 'E79A842DA34A1CA383F64A1546BB55F0885C65A4')
+ self.assertEqual(sigs[0].status, None)
+ self.assertEqual(sigs[0].notations, [])
+ self.assertEqual(sigs[0].timestamp, 1137685598)
+ self.assertEqual(sigs[0].exp_timestamp, 0)
+ self.assertEqual(sigs[0].wrong_key_usage, False)
+ self.assertEqual(sigs[0].validity, gpgme.VALIDITY_UNKNOWN)
+ self.assertEqual(sigs[0].validity_reason, None)
+
+ def test_verify_clearsign(self):
+ signature = StringIO.StringIO(dedent('''
+ -----BEGIN PGP SIGNED MESSAGE-----
+ Hash: SHA1
+
+ Hello World
+ -----BEGIN PGP SIGNATURE-----
+ Version: GnuPG v1.4.1 (GNU/Linux)
+
+ iD8DBQFDz7DiRrtV8IhcZaQRAjuYAJ43/NhhNHx+gzGBUqtIK5LpENTCGgCfV3aO
+ ZTFlGRyKN26HccsC6ZWcPUQ=
+ =kZ2c
+ -----END PGP SIGNATURE-----
+ '''))
+ plaintext = StringIO.StringIO()
+ ctx = gpgme.Context()
+ sigs = ctx.verify(signature, None, plaintext)
+
+ self.assertEqual(plaintext.getvalue(), 'Hello World\n')
+ self.assertEqual(len(sigs), 1)
+ self.assertEqual(sigs[0].summary, 0)
+ self.assertEqual(sigs[0].fpr,
+ 'E79A842DA34A1CA383F64A1546BB55F0885C65A4')
+ self.assertEqual(sigs[0].status, None)
+ self.assertEqual(sigs[0].notations, [])
+ self.assertEqual(sigs[0].timestamp, 1137684706)
+ self.assertEqual(sigs[0].exp_timestamp, 0)
+ self.assertEqual(sigs[0].wrong_key_usage, False)
+ self.assertEqual(sigs[0].validity, gpgme.VALIDITY_UNKNOWN)
+ self.assertEqual(sigs[0].validity_reason, None)
+
+ def test_verify_multiple_sigs(self):
+ signature = StringIO.StringIO(dedent('''
+ -----BEGIN PGP SIGNED MESSAGE-----
+ Hash: SHA1
+
+ Hello World
+ -----BEGIN PGP SIGNATURE-----
+ Version: GnuPG v1.4.1 (GNU/Linux)
+
+ iD8DBQFDz7V9RrtV8IhcZaQRAia/AJ9eC/Q3pssWW9PWckQ3+1kbiIiEVQCfSeFv
+ 7SlUCFJOs/sfl+EtaOafgQGJAhUDBQFDz7V9LPRrf8l+aw8BAia/EAClI1X/hL38
+ 6NeOnMD6zXNm7r20Qkpp7PT63PqUa9dU1P+Ha2Uju5C2jBVYouDOpHnEsw3AqItl
+ M0y6xiBAbXbdv0K2OdX8/290g/uODQE/oRGu+YtIh8HcY9N1JmzYw6msRO1LD/Oo
+ xVqfyJiPx+Ol3juAuVqggBzQQmhQpZ7MfHcZSIWxYtRZNlCGYp2lUVae7fJlrJc8
+ DvTkGSkdqBRoDqy0rKcdXRuExXyq081m7bli2sMvImejmEsqyMcbZrkW69v+/BQD
+ Tki8tEkxINw1YHhcBDI0KAn3SuynY+i132oU2qJWQF3ZBRqEbD0IxfakPSZyhJKj
+ sxk38VHgA+5r/QKRs+4n3z09yFqNIWpnvVVZ2iMfKhHtKd1nNq6tOzHiQrmdSdyK
+ dwRaRm4Zt0hWT8v+CXX/RPK5xGL3FCZQs7VTO0ANHR7cIS+v3ChaHO6naQSBQMrW
+ 7l69hTh009LFIKlYJ+7ZBS2pySkvHmEzJKl4Ko4UfOeD2xDsq5nHhi/AJ7TXtHCo
+ TLo8OwJvfiW6Fa9zzu6IkerhQlZrvbLOkmBpuyFo0UEuM/89bquaZ3GoEj3hePsZ
+ nD9LtsgsjkFV1jZQ4n/wM3jolo0aA4+ZEBCgw9XJUSZ67m+jvFNBvZtDqWnbQWxe
+ FsW3EQWNlQnwkn2lic51Cdp3w7yPH5CKfw==
+ =0A7N
+ -----END PGP SIGNATURE-----
+ '''))
+ plaintext = StringIO.StringIO()
+ ctx = gpgme.Context()
+ sigs = ctx.verify(signature, None, plaintext)
+
+ self.assertEqual(plaintext.getvalue(), 'Hello World\n')
+ self.assertEqual(len(sigs), 2)
+ self.assertEqual(sigs[0].summary, 0)
+ self.assertEqual(sigs[0].fpr,
+ 'E79A842DA34A1CA383F64A1546BB55F0885C65A4')
+ self.assertEqual(sigs[0].status, None)
+ self.assertEqual(sigs[0].notations, [])
+ self.assertEqual(sigs[0].timestamp, 1137685885)
+ self.assertEqual(sigs[0].exp_timestamp, 0)
+ self.assertEqual(sigs[0].wrong_key_usage, False)
+ self.assertEqual(sigs[0].validity, gpgme.VALIDITY_UNKNOWN)
+ self.assertEqual(sigs[0].validity_reason, None)
+
+ self.assertEqual(sigs[1].summary, 0)
+ self.assertEqual(sigs[1].fpr,
+ '93C2240D6B8AA10AB28F701D2CF46B7FC97E6B0F')
+ self.assertEqual(sigs[1].status, None)
+ self.assertEqual(sigs[1].notations, [])
+ self.assertEqual(sigs[1].timestamp, 1137685885)
+ self.assertEqual(sigs[1].exp_timestamp, 0)
+ self.assertEqual(sigs[1].wrong_key_usage, False)
+ self.assertEqual(sigs[1].validity, gpgme.VALIDITY_UNKNOWN)
+ self.assertEqual(sigs[1].validity_reason, None)
+
+ def test_verify_multiple_clearsigned_sections(self):
+ signature = StringIO.StringIO(dedent('''
+ -----BEGIN PGP SIGNED MESSAGE-----
+ Hash: SHA1
+
+ Hello World
+ -----BEGIN PGP SIGNATURE-----
+ Version: GnuPG v1.4.1 (GNU/Linux)
+
+ iD8DBQFD1tutRrtV8IhcZaQRAgD4AJ9oqVSFt3UW1lUxhnNM9YXh2G09AQCdGxEe
+ zlgLsoU2R8b0RrGZAHb+Dzw=
+ =rTzD
+ -----END PGP SIGNATURE-----
+
+ -----BEGIN PGP SIGNED MESSAGE-----
+ Hash: SHA1
+
+ Hello World
+ -----BEGIN PGP SIGNATURE-----
+ Version: GnuPG v1.4.1 (GNU/Linux)
+
+ iQIVAwUBQ9bbrSz0a3/JfmsPAQIA+A/+I5mr+hlq+keZZqZGGYQ/U9VdYBJHX/mG
+ Rf3KQERuReimE/pYUDmeLAxys9KD5uBwtd4ajhCYalNIsPZB1W3jXxpQWe0A238v
+ zAQD//bpEO8i2LH17IrSd3plAMCvcfR8Fk/CTAERZbQ5/cPc1Wrzt6BI+fQvqwI2
+ aEyi6vYVeYqq7WXdlyfo5WztfL0igGGrPj5Aw0BblyfaQAxkgNeLUXT2wvBNoOGF
+ Nk+hNW4UQiUVAmZX5iHNKD+CGUX2WNCQYwYCETVGa84Ve0wxMbstBnT3eMBczAPD
+ 6QESHmm0YtAM1rx1jLH2dehksXhCInvD6AHnmKNkcOk2C1tua5tr2hdbPRRkR4WY
+ 9/pAkV0CWVH9xomzLIDAlOlRYE/jsY14qX9iLvahoegORN749pWacMAUfXA+BhOQ
+ 6afPtM5tMwzz6Pc/pXTk2WQueWPXDXJ/CjFg6KqtcnXa3wMSi1LoyZosfkZXfIuz
+ wE3SZ2IQUMTQNXfjwyHj6DWPqKzjhlD8VdOvtHmle+eeRpT1xqb910Anfh/2WMY7
+ QxLCvwZcDKkGb8T8Rxc8ajjPUNrhHT6Tawk/msmNDZyWBZDNjXmh5Y/UzfaN77pf
+ 47G49HVk0RLx1hsNLVPFpHWsOCrLhbm8CgVNPy/TLtJiDmCHvL3n0KNSnZv5u2oE
+ 9mE1kR0aVOM=
+ =3Ryd
+ -----END PGP SIGNATURE-----
+ '''))
+ plaintext = StringIO.StringIO()
+ ctx = gpgme.Context()
+ sigs = ctx.verify(signature, None, plaintext)
+
+ self.assertEqual(plaintext.getvalue(),
+ 'Hello World\nHello World\n')
+ self.assertEqual(len(sigs), 2)
+ self.assertEqual(sigs[0].summary, 0)
+ self.assertEqual(sigs[0].fpr,
+ 'E79A842DA34A1CA383F64A1546BB55F0885C65A4')
+ self.assertEqual(sigs[0].status, None)
+ self.assertEqual(sigs[0].notations, [])
+ self.assertEqual(sigs[0].timestamp, 1138154413)
+ self.assertEqual(sigs[0].exp_timestamp, 0)
+ self.assertEqual(sigs[0].wrong_key_usage, False)
+ self.assertEqual(sigs[0].validity, gpgme.VALIDITY_UNKNOWN)
+ self.assertEqual(sigs[0].validity_reason, None)
+
+ self.assertEqual(sigs[1].summary, 0)
+ self.assertEqual(sigs[1].fpr,
+ '93C2240D6B8AA10AB28F701D2CF46B7FC97E6B0F')
+ self.assertEqual(sigs[1].status, None)
+ self.assertEqual(sigs[1].notations, [])
+ self.assertEqual(sigs[1].timestamp, 1138154413)
+ self.assertEqual(sigs[1].exp_timestamp, 0)
+ self.assertEqual(sigs[1].wrong_key_usage, False)
+ self.assertEqual(sigs[1].validity, gpgme.VALIDITY_UNKNOWN)
+ self.assertEqual(sigs[1].validity_reason, None)
+
+ def test_verify_no_signature(self):
+ signature = StringIO.StringIO(dedent('''
+ -----BEGIN PGP SIGNED MESSAGE-----
+ Hash: SHA1
+
+ Hello World
+ -----BEGIN PGP SIGNATURE-----
+ -----END PGP SIGNATURE-----
+ '''))
+ plaintext = StringIO.StringIO()
+ ctx = gpgme.Context()
+ sigs = ctx.verify(signature, None, plaintext)
+
+ self.assertEqual(plaintext.getvalue(), '')
+ self.assertEqual(len(sigs), 0)
+
+ def test_verify_bad_signature(self):
+ signature = StringIO.StringIO(dedent('''
+ -----BEGIN PGP SIGNED MESSAGE-----
+ Hash: SHA1
+
+ Hello World
+ -----BEGIN PGP SIGNATURE-----
+ Version: GnuPG v1.4.1 (GNU/Linux)
+
+ iNhhNHx+gzGBUqtIK5LpENTCGgCfV3aO
+ -----END PGP SIGNATURE-----
+ '''))
+ plaintext = StringIO.StringIO()
+ ctx = gpgme.Context()
+ try:
+ ctx.verify(signature, None, plaintext)
+ except gpgme.GpgmeError, exc:
+ self.assertEqual(exc[0], gpgme.ERR_SOURCE_GPGME)
+ self.assertEqual(exc[1], gpgme.ERR_NO_DATA)
+ else:
+ self.fail('gpgme.GpgmeError not raised')
+
+ def test_sign_normal(self):
+ ctx = gpgme.Context()
+ ctx.armor = False
+ key = ctx.get_key('E79A842DA34A1CA383F64A1546BB55F0885C65A4')
+ ctx.signers = [key]
+ plaintext = StringIO.StringIO('Hello World\n')
+ signature = StringIO.StringIO()
+
+ new_sigs = ctx.sign(plaintext, signature, gpgme.SIG_MODE_NORMAL)
+ self.assertEqual(len(new_sigs), 1)
+ self.assertEqual(new_sigs[0].type, gpgme.SIG_MODE_NORMAL)
+ self.assertEqual(new_sigs[0].fpr,
+ 'E79A842DA34A1CA383F64A1546BB55F0885C65A4')
+
+ # now verify the signature
+ signature.seek(0)
+ plaintext = StringIO.StringIO()
+ sigs = ctx.verify(signature, None, plaintext)
+ self.assertEqual(plaintext.getvalue(), 'Hello World\n')
+ self.assertEqual(len(sigs), 1)
+ self.assertEqual(sigs[0].summary, 0)
+ self.assertEqual(sigs[0].fpr,
+ 'E79A842DA34A1CA383F64A1546BB55F0885C65A4')
+ self.assertEqual(sigs[0].status, None)
+ self.assertEqual(sigs[0].wrong_key_usage, False)
+ self.assertEqual(sigs[0].validity, gpgme.VALIDITY_UNKNOWN)
+ self.assertEqual(sigs[0].validity_reason, None)
+
+ def test_sign_normal_armor(self):
+ ctx = gpgme.Context()
+ ctx.armor = True
+ key = ctx.get_key('E79A842DA34A1CA383F64A1546BB55F0885C65A4')
+ ctx.signers = [key]
+ plaintext = StringIO.StringIO('Hello World\n')
+ signature = StringIO.StringIO()
+
+ new_sigs = ctx.sign(plaintext, signature, gpgme.SIG_MODE_NORMAL)
+ self.assertEqual(len(new_sigs), 1)
+ self.assertEqual(new_sigs[0].type, gpgme.SIG_MODE_NORMAL)
+ self.assertEqual(new_sigs[0].fpr,
+ 'E79A842DA34A1CA383F64A1546BB55F0885C65A4')
+
+ # now verify the signature
+ signature.seek(0)
+ plaintext = StringIO.StringIO()
+ sigs = ctx.verify(signature, None, plaintext)
+ self.assertEqual(plaintext.getvalue(), 'Hello World\n')
+ self.assertEqual(len(sigs), 1)
+ self.assertEqual(sigs[0].summary, 0)
+ self.assertEqual(sigs[0].fpr,
+ 'E79A842DA34A1CA383F64A1546BB55F0885C65A4')
+ self.assertEqual(sigs[0].status, None)
+ self.assertEqual(sigs[0].wrong_key_usage, False)
+ self.assertEqual(sigs[0].validity, gpgme.VALIDITY_UNKNOWN)
+ self.assertEqual(sigs[0].validity_reason, None)
+
+ def test_sign_detatch(self):
+ ctx = gpgme.Context()
+ ctx.armor = True
+ key = ctx.get_key('E79A842DA34A1CA383F64A1546BB55F0885C65A4')
+ ctx.signers = [key]
+ plaintext = StringIO.StringIO('Hello World\n')
+ signature = StringIO.StringIO()
+
+ new_sigs = ctx.sign(plaintext, signature, gpgme.SIG_MODE_DETACH)
+ self.assertEqual(len(new_sigs), 1)
+ self.assertEqual(new_sigs[0].type, gpgme.SIG_MODE_DETACH)
+ self.assertEqual(new_sigs[0].fpr,
+ 'E79A842DA34A1CA383F64A1546BB55F0885C65A4')
+
+ # now verify the signature
+ signature.seek(0)
+ plaintext.seek(0)
+ sigs = ctx.verify(signature, plaintext, None)
+ self.assertEqual(len(sigs), 1)
+ self.assertEqual(sigs[0].summary, 0)
+ self.assertEqual(sigs[0].fpr,
+ 'E79A842DA34A1CA383F64A1546BB55F0885C65A4')
+ self.assertEqual(sigs[0].status, None)
+ self.assertEqual(sigs[0].wrong_key_usage, False)
+ self.assertEqual(sigs[0].validity, gpgme.VALIDITY_UNKNOWN)
+ self.assertEqual(sigs[0].validity_reason, None)
+
+ def test_sign_clearsign(self):
+ ctx = gpgme.Context()
+ ctx.armor = True
+ key = ctx.get_key('E79A842DA34A1CA383F64A1546BB55F0885C65A4')
+ ctx.signers = [key]
+ plaintext = StringIO.StringIO('Hello World\n')
+ signature = StringIO.StringIO()
+
+ new_sigs = ctx.sign(plaintext, signature, gpgme.SIG_MODE_CLEAR)
+ self.assertEqual(len(new_sigs), 1)
+ self.assertEqual(new_sigs[0].type, gpgme.SIG_MODE_CLEAR)
+ self.assertEqual(new_sigs[0].fpr,
+ 'E79A842DA34A1CA383F64A1546BB55F0885C65A4')
+
+ # now verify the signature
+ signature.seek(0)
+ plaintext = StringIO.StringIO()
+ sigs = ctx.verify(signature, None, plaintext)
+ self.assertEqual(plaintext.getvalue(), 'Hello World\n')
+ self.assertEqual(len(sigs), 1)
+ self.assertEqual(sigs[0].summary, 0)
+ self.assertEqual(sigs[0].fpr,
+ 'E79A842DA34A1CA383F64A1546BB55F0885C65A4')
+ self.assertEqual(sigs[0].status, None)
+ self.assertEqual(sigs[0].wrong_key_usage, False)
+ self.assertEqual(sigs[0].validity, gpgme.VALIDITY_UNKNOWN)
+ self.assertEqual(sigs[0].validity_reason, None)
+
+def test_suite():
+ loader = unittest.TestLoader()
+ return loader.loadTestsFromName(__name__)
--- /dev/null
+# pygpgme - a Python wrapper for the gpgme library
+# Copyright (C) 2006 James Henstridge
+#
+# This library is free software; you can redistribute it and/or
+# modify it under the terms of the GNU Lesser General Public
+# License as published by the Free Software Foundation; either
+# version 2.1 of the License, or (at your option) any later version.
+#
+# This library is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+# Lesser General Public License for more details.
+#
+# You should have received a copy of the GNU Lesser General Public
+# License along with this library; if not, write to the Free Software
+# Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
+
+import os
+import shutil
+import tempfile
+import unittest
+
+import gpgme
+
+__all__ = ['GpgHomeTestCase']
+
+keydir = os.path.join(os.path.dirname(__file__), 'keys')
+
+class GpgHomeTestCase(unittest.TestCase):
+
+ gpg_conf_contents = ''
+ import_keys = []
+
+ def keyfile(self, key):
+ return open(os.path.join(keydir, key), 'rb')
+
+ def setUp(self):
+ self._gpghome = tempfile.mkdtemp(prefix='tmp.gpghome')
+ os.environ['GNUPGHOME'] = self._gpghome
+ fp = open(os.path.join(self._gpghome, 'gpg.conf'), 'wb')
+ fp.write(self.gpg_conf_contents)
+ fp.close()
+
+ # import requested keys into the keyring
+ ctx = gpgme.Context()
+ for key in self.import_keys:
+ ctx.import_(self.keyfile(key))
+
+ def tearDown(self):
+ del os.environ['GNUPGHOME']
+ shutil.rmtree(self._gpghome, ignore_errors=True)
--- /dev/null
+#!/usr/bin/env python
+
+from distutils.core import setup, Extension
+
+gpgme = Extension(
+ 'gpgme._gpgme',
+ ['src/gpgme.c',
+ 'src/pygpgme-error.c',
+ 'src/pygpgme-data.c',
+ 'src/pygpgme-context.c',
+ 'src/pygpgme-key.c',
+ 'src/pygpgme-signature.c',
+ 'src/pygpgme-import.c',
+ 'src/pygpgme-keyiter.c',
+ 'src/pygpgme-constants.c',
+ ],
+ libraries=['gpgme'])
+
+setup(name='pygpgme',
+ version='0.1',
+ author='James Henstridge',
+ author_email='james@jamesh.id.au',
+ description='A Python module for working with OpenPGP messages',
+ long_description='''
+ PyGPGME is a Python module that lets you sign, verify, encrypt
+ and decrypt messages using the OpenPGP format.
+
+ It is built on top of the GNU Privacy Guard and the GPGME
+ library.''',
+ license='LGPL',
+ classifiers=[
+ 'Intended Audience :: Developers',
+ 'License :: OSI Approved :: GNU Library or Lesser General Public License (LGPL)',
+ 'Operating System :: POSIX',
+ 'Programming Language :: C',
+ 'Programming Language :: Python',
+ 'Topic :: Security :: Cryptography',
+ 'Topic :: Software Development :: Libraries :: Python Modules'
+ ],
+ url='https://launchpad.net/products/pygpgme',
+ ext_modules=[gpgme],
+ packages=['gpgme', 'gpgme.tests'],
+ package_data={'gpgme.tests': ['keys/*.pub', 'keys/*.sec']})
--- /dev/null
+/* -*- mode: C; c-basic-offset: 4; indent-tabs-mode: nil -*- */
+/*
+ pygpgme - a Python wrapper for the gpgme library
+ Copyright (C) 2006 James Henstridge
+
+ This library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Lesser General Public
+ License as published by the Free Software Foundation; either
+ version 2.1 of the License, or (at your option) any later version.
+
+ This library is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Lesser General Public License for more details.
+
+ You should have received a copy of the GNU Lesser General Public
+ License along with this library; if not, write to the Free Software
+ Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
+ */
+
+#include <Python.h>
+#include "pygpgme.h"
+
+static PyMethodDef pygpgme_functions[] = {
+ { "make_constants", (PyCFunction)pygpgme_make_constants, METH_VARARGS },
+ { NULL, NULL, 0 }
+};
+
+PyMODINIT_FUNC
+init_gpgme(void)
+{
+ PyObject *mod;
+
+ pygpgme_error = PyErr_NewException("gpgme.GpgmeError",
+ PyExc_RuntimeError, NULL);
+
+#define INIT_TYPE(type) \
+ if (!type.ob_type) \
+ type.ob_type = &PyType_Type; \
+ if (!type.tp_alloc) \
+ type.tp_alloc = PyType_GenericAlloc; \
+ if (!type.tp_new) \
+ type.tp_new = PyType_GenericNew; \
+ if (PyType_Ready(&type) < 0) \
+ return
+
+#define ADD_TYPE(type) \
+ Py_INCREF(&PyGpgme ## type ## _Type); \
+ PyModule_AddObject(mod, #type, (PyObject *)&PyGpgme ## type ## _Type)
+
+ INIT_TYPE(PyGpgmeContext_Type);
+ INIT_TYPE(PyGpgmeKey_Type);
+ INIT_TYPE(PyGpgmeSubkey_Type);
+ INIT_TYPE(PyGpgmeUserId_Type);
+ INIT_TYPE(PyGpgmeKeySig_Type);
+ INIT_TYPE(PyGpgmeNewSignature_Type);
+ INIT_TYPE(PyGpgmeSignature_Type);
+ INIT_TYPE(PyGpgmeImportResult_Type);
+ INIT_TYPE(PyGpgmeKeyIter_Type);
+
+ mod = Py_InitModule("gpgme._gpgme", pygpgme_functions);
+
+ ADD_TYPE(Context);
+ ADD_TYPE(Key);
+ ADD_TYPE(Subkey);
+ ADD_TYPE(UserId);
+ ADD_TYPE(KeySig);
+ ADD_TYPE(NewSignature);
+ ADD_TYPE(Signature);
+ ADD_TYPE(ImportResult);
+ ADD_TYPE(KeyIter);
+
+ Py_INCREF(pygpgme_error);
+ PyModule_AddObject(mod, "GpgmeError", pygpgme_error);
+}
--- /dev/null
+/* -*- mode: C; c-basic-offset: 4; indent-tabs-mode: nil -*- */
+/*
+ pygpgme - a Python wrapper for the gpgme library
+ Copyright (C) 2006 James Henstridge
+
+ This library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Lesser General Public
+ License as published by the Free Software Foundation; either
+ version 2.1 of the License, or (at your option) any later version.
+
+ This library is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Lesser General Public License for more details.
+
+ You should have received a copy of the GNU Lesser General Public
+ License along with this library; if not, write to the Free Software
+ Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
+ */
+#include "pygpgme.h"
+
+struct pygpgme_constant {
+ const char name[28];
+ long value;
+};
+
+#define CONST(name) { #name, GPGME_##name }
+
+static const struct pygpgme_constant constants[] = {
+ /* gpgme_data_encoding_t */
+ CONST(DATA_ENCODING_NONE),
+ CONST(DATA_ENCODING_BINARY),
+ CONST(DATA_ENCODING_BASE64),
+ CONST(DATA_ENCODING_ARMOR),
+
+ /* gpgme_pubkey_algo_t */
+ CONST(PK_RSA),
+ CONST(PK_RSA_E),
+ CONST(PK_RSA_S),
+ CONST(PK_ELG_E),
+ CONST(PK_DSA),
+ CONST(PK_ELG),
+
+ /* gpgme_hash_algo_t */
+ CONST(MD_NONE),
+ CONST(MD_MD5),
+ CONST(MD_SHA1),
+ CONST(MD_RMD160),
+ CONST(MD_MD2),
+ CONST(MD_TIGER),
+ CONST(MD_HAVAL),
+ CONST(MD_SHA256),
+ CONST(MD_SHA384),
+ CONST(MD_SHA512),
+ CONST(MD_MD4),
+ CONST(MD_CRC32),
+ CONST(MD_CRC32_RFC1510),
+ CONST(MD_CRC24_RFC2440),
+
+ /* gpgme_sig_mode_t */
+ CONST(SIG_MODE_NORMAL),
+ CONST(SIG_MODE_DETACH),
+ CONST(SIG_MODE_CLEAR),
+
+ /* gpgme_validity_t */
+ CONST(VALIDITY_UNKNOWN),
+ CONST(VALIDITY_UNDEFINED),
+ CONST(VALIDITY_NEVER),
+ CONST(VALIDITY_MARGINAL),
+ CONST(VALIDITY_FULL),
+ CONST(VALIDITY_ULTIMATE),
+
+ /* gpgme_protocol_t */
+ CONST(PROTOCOL_OpenPGP),
+ CONST(PROTOCOL_CMS),
+
+ /* gpgme_keylist_mode_t */
+ CONST(KEYLIST_MODE_LOCAL),
+ CONST(KEYLIST_MODE_EXTERN),
+ CONST(KEYLIST_MODE_SIGS),
+ CONST(KEYLIST_MODE_VALIDATE),
+
+ /* gpgme_status_code_t */
+ CONST(STATUS_EOF),
+ CONST(STATUS_ENTER),
+ CONST(STATUS_LEAVE),
+ CONST(STATUS_ABORT),
+ CONST(STATUS_GOODSIG),
+ CONST(STATUS_BADSIG),
+ CONST(STATUS_ERRSIG),
+ CONST(STATUS_BADARMOR),
+ CONST(STATUS_RSA_OR_IDEA),
+ CONST(STATUS_KEYEXPIRED),
+ CONST(STATUS_KEYREVOKED),
+ CONST(STATUS_TRUST_UNDEFINED),
+ CONST(STATUS_TRUST_NEVER),
+ CONST(STATUS_TRUST_MARGINAL),
+ CONST(STATUS_TRUST_FULLY),
+ CONST(STATUS_TRUST_ULTIMATE),
+ CONST(STATUS_SHM_INFO),
+ CONST(STATUS_SHM_GET),
+ CONST(STATUS_SHM_GET_BOOL),
+ CONST(STATUS_SHM_GET_HIDDEN),
+ CONST(STATUS_NEED_PASSPHRASE),
+ CONST(STATUS_VALIDSIG),
+ CONST(STATUS_SIG_ID),
+ CONST(STATUS_ENC_TO),
+ CONST(STATUS_NODATA),
+ CONST(STATUS_BAD_PASSPHRASE),
+ CONST(STATUS_NO_PUBKEY),
+ CONST(STATUS_NO_SECKEY),
+ CONST(STATUS_NEED_PASSPHRASE_SYM),
+ CONST(STATUS_DECRYPTION_FAILED),
+ CONST(STATUS_DECRYPTION_OKAY),
+ CONST(STATUS_MISSING_PASSPHRASE),
+ CONST(STATUS_GOOD_PASSPHRASE),
+ CONST(STATUS_GOODMDC),
+ CONST(STATUS_BADMDC),
+ CONST(STATUS_ERRMDC),
+ CONST(STATUS_IMPORTED),
+ CONST(STATUS_IMPORT_OK),
+ CONST(STATUS_IMPORT_PROBLEM),
+ CONST(STATUS_IMPORT_RES),
+ CONST(STATUS_FILE_START),
+ CONST(STATUS_FILE_DONE),
+ CONST(STATUS_FILE_ERROR),
+ CONST(STATUS_BEGIN_DECRYPTION),
+ CONST(STATUS_END_DECRYPTION),
+ CONST(STATUS_BEGIN_ENCRYPTION),
+ CONST(STATUS_END_ENCRYPTION),
+ CONST(STATUS_DELETE_PROBLEM),
+ CONST(STATUS_GET_BOOL),
+ CONST(STATUS_GET_LINE),
+ CONST(STATUS_GET_HIDDEN),
+ CONST(STATUS_GOT_IT),
+ CONST(STATUS_PROGRESS),
+ CONST(STATUS_SIG_CREATED),
+ CONST(STATUS_SESSION_KEY),
+ CONST(STATUS_NOTATION_NAME),
+ CONST(STATUS_NOTATION_DATA),
+ CONST(STATUS_POLICY_URL),
+ CONST(STATUS_BEGIN_STREAM),
+ CONST(STATUS_END_STREAM),
+ CONST(STATUS_KEY_CREATED),
+ CONST(STATUS_USERID_HINT),
+ CONST(STATUS_UNEXPECTED),
+ CONST(STATUS_INV_RECP),
+ CONST(STATUS_NO_RECP),
+ CONST(STATUS_ALREADY_SIGNED),
+ CONST(STATUS_SIGEXPIRED),
+ CONST(STATUS_EXPSIG),
+ CONST(STATUS_EXPKEYSIG),
+ CONST(STATUS_TRUNCATED),
+ CONST(STATUS_ERROR),
+ CONST(STATUS_NEWSIG),
+ CONST(STATUS_REVKEYSIG),
+
+ /* gpgme_encrypt_flags_t */
+ CONST(ENCRYPT_ALWAYS_TRUST),
+
+ /* gpgme_sigsum_t */
+ CONST(SIGSUM_VALID),
+ CONST(SIGSUM_GREEN),
+ CONST(SIGSUM_RED),
+ CONST(SIGSUM_KEY_REVOKED),
+ CONST(SIGSUM_KEY_EXPIRED),
+ CONST(SIGSUM_SIG_EXPIRED),
+ CONST(SIGSUM_KEY_MISSING),
+ CONST(SIGSUM_CRL_MISSING),
+ CONST(SIGSUM_CRL_TOO_OLD),
+ CONST(SIGSUM_BAD_POLICY),
+ CONST(SIGSUM_SYS_ERROR),
+
+ /* import status */
+ CONST(IMPORT_NEW),
+ CONST(IMPORT_UID),
+ CONST(IMPORT_SIG),
+ CONST(IMPORT_SUBKEY),
+ CONST(IMPORT_SECRET),
+
+ /* gpg-error.h constants */
+#undef CONST
+#define CONST(name) { #name, GPG_##name }
+ CONST(ERR_SOURCE_UNKNOWN),
+ CONST(ERR_SOURCE_GCRYPT),
+ CONST(ERR_SOURCE_GPG),
+ CONST(ERR_SOURCE_GPGSM),
+ CONST(ERR_SOURCE_GPGAGENT),
+ CONST(ERR_SOURCE_PINENTRY),
+ CONST(ERR_SOURCE_SCD),
+ CONST(ERR_SOURCE_GPGME),
+ CONST(ERR_SOURCE_KEYBOX),
+ CONST(ERR_SOURCE_KSBA),
+ CONST(ERR_SOURCE_DIRMNGR),
+ CONST(ERR_SOURCE_GSTI),
+ CONST(ERR_SOURCE_USER_1),
+ CONST(ERR_SOURCE_USER_2),
+ CONST(ERR_SOURCE_USER_3),
+ CONST(ERR_SOURCE_USER_4),
+
+ CONST(ERR_NO_ERROR),
+ CONST(ERR_GENERAL),
+ CONST(ERR_UNKNOWN_PACKET),
+ CONST(ERR_UNKNOWN_VERSION),
+ CONST(ERR_PUBKEY_ALGO),
+ CONST(ERR_DIGEST_ALGO),
+ CONST(ERR_BAD_PUBKEY),
+ CONST(ERR_BAD_SECKEY),
+ CONST(ERR_BAD_SIGNATURE),
+ CONST(ERR_NO_PUBKEY),
+ CONST(ERR_CHECKSUM),
+ CONST(ERR_BAD_PASSPHRASE),
+ CONST(ERR_CIPHER_ALGO),
+ CONST(ERR_KEYRING_OPEN),
+ CONST(ERR_INV_PACKET),
+ CONST(ERR_INV_ARMOR),
+ CONST(ERR_NO_USER_ID),
+ CONST(ERR_NO_SECKEY),
+ CONST(ERR_WRONG_SECKEY),
+ CONST(ERR_BAD_KEY),
+ CONST(ERR_COMPR_ALGO),
+ CONST(ERR_NO_PRIME),
+ CONST(ERR_NO_ENCODING_METHOD),
+ CONST(ERR_NO_ENCRYPTION_SCHEME),
+ CONST(ERR_NO_SIGNATURE_SCHEME),
+ CONST(ERR_INV_ATTR),
+ CONST(ERR_NO_VALUE),
+ CONST(ERR_NOT_FOUND),
+ CONST(ERR_VALUE_NOT_FOUND),
+ CONST(ERR_SYNTAX),
+ CONST(ERR_BAD_MPI),
+ CONST(ERR_INV_PASSPHRASE),
+ CONST(ERR_SIG_CLASS),
+ CONST(ERR_RESOURCE_LIMIT),
+ CONST(ERR_INV_KEYRING),
+ CONST(ERR_TRUSTDB),
+ CONST(ERR_BAD_CERT),
+ CONST(ERR_INV_USER_ID),
+ CONST(ERR_UNEXPECTED),
+ CONST(ERR_TIME_CONFLICT),
+ CONST(ERR_KEYSERVER),
+ CONST(ERR_WRONG_PUBKEY_ALGO),
+ CONST(ERR_TRIBUTE_TO_D_A),
+ CONST(ERR_WEAK_KEY),
+ CONST(ERR_INV_KEYLEN),
+ CONST(ERR_INV_ARG),
+ CONST(ERR_BAD_URI),
+ CONST(ERR_INV_URI),
+ CONST(ERR_NETWORK),
+ CONST(ERR_UNKNOWN_HOST),
+ CONST(ERR_SELFTEST_FAILED),
+ CONST(ERR_NOT_ENCRYPTED),
+ CONST(ERR_NOT_PROCESSED),
+ CONST(ERR_UNUSABLE_PUBKEY),
+ CONST(ERR_UNUSABLE_SECKEY),
+ CONST(ERR_INV_VALUE),
+ CONST(ERR_BAD_CERT_CHAIN),
+ CONST(ERR_MISSING_CERT),
+ CONST(ERR_NO_DATA),
+ CONST(ERR_BUG),
+ CONST(ERR_NOT_SUPPORTED),
+ CONST(ERR_INV_OP),
+ CONST(ERR_TIMEOUT),
+ CONST(ERR_INTERNAL),
+ CONST(ERR_EOF_GCRYPT),
+ CONST(ERR_INV_OBJ),
+ CONST(ERR_TOO_SHORT),
+ CONST(ERR_TOO_LARGE),
+ CONST(ERR_NO_OBJ),
+ CONST(ERR_NOT_IMPLEMENTED),
+ CONST(ERR_CONFLICT),
+ CONST(ERR_INV_CIPHER_MODE),
+ CONST(ERR_INV_FLAG),
+ CONST(ERR_INV_HANDLE),
+ CONST(ERR_TRUNCATED),
+ CONST(ERR_INCOMPLETE_LINE),
+ CONST(ERR_INV_RESPONSE),
+ CONST(ERR_NO_AGENT),
+ CONST(ERR_AGENT),
+ CONST(ERR_INV_DATA),
+ CONST(ERR_ASSUAN_SERVER_FAULT),
+ CONST(ERR_ASSUAN),
+ CONST(ERR_INV_SESSION_KEY),
+ CONST(ERR_INV_SEXP),
+ CONST(ERR_UNSUPPORTED_ALGORITHM),
+ CONST(ERR_NO_PIN_ENTRY),
+ CONST(ERR_PIN_ENTRY),
+ CONST(ERR_BAD_PIN),
+ CONST(ERR_INV_NAME),
+ CONST(ERR_BAD_DATA),
+ CONST(ERR_INV_PARAMETER),
+ CONST(ERR_WRONG_CARD),
+ CONST(ERR_NO_DIRMNGR),
+ CONST(ERR_DIRMNGR),
+ CONST(ERR_CERT_REVOKED),
+ CONST(ERR_NO_CRL_KNOWN),
+ CONST(ERR_CRL_TOO_OLD),
+ CONST(ERR_LINE_TOO_LONG),
+ CONST(ERR_NOT_TRUSTED),
+ CONST(ERR_CANCELED),
+ CONST(ERR_BAD_CA_CERT),
+ CONST(ERR_CERT_EXPIRED),
+ CONST(ERR_CERT_TOO_YOUNG),
+ CONST(ERR_UNSUPPORTED_CERT),
+ CONST(ERR_UNKNOWN_SEXP),
+ CONST(ERR_UNSUPPORTED_PROTECTION),
+ CONST(ERR_CORRUPTED_PROTECTION),
+ CONST(ERR_AMBIGUOUS_NAME),
+ CONST(ERR_CARD),
+ CONST(ERR_CARD_RESET),
+ CONST(ERR_CARD_REMOVED),
+ CONST(ERR_INV_CARD),
+ CONST(ERR_CARD_NOT_PRESENT),
+ CONST(ERR_NO_PKCS15_APP),
+ CONST(ERR_NOT_CONFIRMED),
+ CONST(ERR_CONFIGURATION),
+ CONST(ERR_NO_POLICY_MATCH),
+ CONST(ERR_INV_INDEX),
+ CONST(ERR_INV_ID),
+ CONST(ERR_NO_SCDAEMON),
+ CONST(ERR_SCDAEMON),
+ CONST(ERR_UNSUPPORTED_PROTOCOL),
+ CONST(ERR_BAD_PIN_METHOD),
+ CONST(ERR_CARD_NOT_INITIALIZED),
+ CONST(ERR_UNSUPPORTED_OPERATION),
+ CONST(ERR_WRONG_KEY_USAGE),
+ CONST(ERR_NOTHING_FOUND),
+ CONST(ERR_WRONG_BLOB_TYPE),
+ CONST(ERR_MISSING_VALUE),
+ CONST(ERR_HARDWARE),
+ CONST(ERR_PIN_BLOCKED),
+ CONST(ERR_USE_CONDITIONS),
+ CONST(ERR_PIN_NOT_SYNCED),
+ CONST(ERR_INV_CRL),
+ CONST(ERR_BAD_BER),
+ CONST(ERR_INV_BER),
+ CONST(ERR_ELEMENT_NOT_FOUND),
+ CONST(ERR_IDENTIFIER_NOT_FOUND),
+ CONST(ERR_INV_TAG),
+ CONST(ERR_INV_LENGTH),
+ CONST(ERR_INV_KEYINFO),
+ CONST(ERR_UNEXPECTED_TAG),
+ CONST(ERR_NOT_DER_ENCODED),
+ CONST(ERR_NO_CMS_OBJ),
+ CONST(ERR_INV_CMS_OBJ),
+ CONST(ERR_UNKNOWN_CMS_OBJ),
+ CONST(ERR_UNSUPPORTED_CMS_OBJ),
+ CONST(ERR_UNSUPPORTED_ENCODING),
+ CONST(ERR_UNSUPPORTED_CMS_VERSION),
+ CONST(ERR_UNKNOWN_ALGORITHM),
+ CONST(ERR_INV_ENGINE),
+ CONST(ERR_PUBKEY_NOT_TRUSTED),
+ CONST(ERR_DECRYPT_FAILED),
+ CONST(ERR_KEY_EXPIRED),
+ CONST(ERR_SIG_EXPIRED),
+ CONST(ERR_ENCODING_PROBLEM),
+ CONST(ERR_INV_STATE),
+ CONST(ERR_DUP_VALUE),
+ CONST(ERR_MISSING_ACTION),
+ CONST(ERR_MODULE_NOT_FOUND),
+ CONST(ERR_INV_OID_STRING),
+ CONST(ERR_INV_TIME),
+ CONST(ERR_INV_CRL_OBJ),
+ CONST(ERR_UNSUPPORTED_CRL_VERSION),
+ CONST(ERR_INV_CERT_OBJ),
+ CONST(ERR_UNKNOWN_NAME),
+ CONST(ERR_LOCALE_PROBLEM),
+ CONST(ERR_NOT_LOCKED),
+ CONST(ERR_PROTOCOL_VIOLATION),
+ CONST(ERR_INV_MAC),
+ CONST(ERR_INV_REQUEST),
+ CONST(ERR_BUFFER_TOO_SHORT),
+ CONST(ERR_SEXP_INV_LEN_SPEC),
+ CONST(ERR_SEXP_STRING_TOO_LONG),
+ CONST(ERR_SEXP_UNMATCHED_PAREN),
+ CONST(ERR_SEXP_NOT_CANONICAL),
+ CONST(ERR_SEXP_BAD_CHARACTER),
+ CONST(ERR_SEXP_BAD_QUOTATION),
+ CONST(ERR_SEXP_ZERO_PREFIX),
+ CONST(ERR_SEXP_NESTED_DH),
+ CONST(ERR_SEXP_UNMATCHED_DH),
+ CONST(ERR_SEXP_UNEXPECTED_PUNC),
+ CONST(ERR_SEXP_BAD_HEX_CHAR),
+ CONST(ERR_SEXP_ODD_HEX_NUMBERS),
+ CONST(ERR_SEXP_BAD_OCT_CHAR),
+ CONST(ERR_USER_1),
+ CONST(ERR_USER_2),
+ CONST(ERR_USER_3),
+ CONST(ERR_USER_4),
+ CONST(ERR_USER_5),
+ CONST(ERR_USER_6),
+ CONST(ERR_USER_7),
+ CONST(ERR_USER_8),
+ CONST(ERR_USER_9),
+ CONST(ERR_USER_10),
+ CONST(ERR_USER_11),
+ CONST(ERR_USER_12),
+ CONST(ERR_USER_13),
+ CONST(ERR_USER_14),
+ CONST(ERR_USER_15),
+ CONST(ERR_USER_16),
+ CONST(ERR_UNKNOWN_ERRNO),
+ CONST(ERR_EOF),
+ CONST(ERR_E2BIG),
+ CONST(ERR_EACCES),
+ CONST(ERR_EADDRINUSE),
+ CONST(ERR_EADDRNOTAVAIL),
+ CONST(ERR_EADV),
+ CONST(ERR_EAFNOSUPPORT),
+ CONST(ERR_EAGAIN),
+ CONST(ERR_EALREADY),
+ CONST(ERR_EAUTH),
+ CONST(ERR_EBACKGROUND),
+ CONST(ERR_EBADE),
+ CONST(ERR_EBADF),
+ CONST(ERR_EBADFD),
+ CONST(ERR_EBADMSG),
+ CONST(ERR_EBADR),
+ CONST(ERR_EBADRPC),
+ CONST(ERR_EBADRQC),
+ CONST(ERR_EBADSLT),
+ CONST(ERR_EBFONT),
+ CONST(ERR_EBUSY),
+ CONST(ERR_ECANCELED),
+ CONST(ERR_ECHILD),
+ CONST(ERR_ECHRNG),
+ CONST(ERR_ECOMM),
+ CONST(ERR_ECONNABORTED),
+ CONST(ERR_ECONNREFUSED),
+ CONST(ERR_ECONNRESET),
+ CONST(ERR_ED),
+ CONST(ERR_EDEADLK),
+ CONST(ERR_EDEADLOCK),
+ CONST(ERR_EDESTADDRREQ),
+ CONST(ERR_EDIED),
+ CONST(ERR_EDOM),
+ CONST(ERR_EDOTDOT),
+ CONST(ERR_EDQUOT),
+ CONST(ERR_EEXIST),
+ CONST(ERR_EFAULT),
+ CONST(ERR_EFBIG),
+ CONST(ERR_EFTYPE),
+ CONST(ERR_EGRATUITOUS),
+ CONST(ERR_EGREGIOUS),
+ CONST(ERR_EHOSTDOWN),
+ CONST(ERR_EHOSTUNREACH),
+ CONST(ERR_EIDRM),
+ CONST(ERR_EIEIO),
+ CONST(ERR_EILSEQ),
+ CONST(ERR_EINPROGRESS),
+ CONST(ERR_EINTR),
+ CONST(ERR_EINVAL),
+ CONST(ERR_EIO),
+ CONST(ERR_EISCONN),
+ CONST(ERR_EISDIR),
+ CONST(ERR_EISNAM),
+ CONST(ERR_EL2HLT),
+ CONST(ERR_EL2NSYNC),
+ CONST(ERR_EL3HLT),
+ CONST(ERR_EL3RST),
+ CONST(ERR_ELIBACC),
+ CONST(ERR_ELIBBAD),
+ CONST(ERR_ELIBEXEC),
+ CONST(ERR_ELIBMAX),
+ CONST(ERR_ELIBSCN),
+ CONST(ERR_ELNRNG),
+ CONST(ERR_ELOOP),
+ CONST(ERR_EMEDIUMTYPE),
+ CONST(ERR_EMFILE),
+ CONST(ERR_EMLINK),
+ CONST(ERR_EMSGSIZE),
+ CONST(ERR_EMULTIHOP),
+ CONST(ERR_ENAMETOOLONG),
+ CONST(ERR_ENAVAIL),
+ CONST(ERR_ENEEDAUTH),
+ CONST(ERR_ENETDOWN),
+ CONST(ERR_ENETRESET),
+ CONST(ERR_ENETUNREACH),
+ CONST(ERR_ENFILE),
+ CONST(ERR_ENOANO),
+ CONST(ERR_ENOBUFS),
+ CONST(ERR_ENOCSI),
+ CONST(ERR_ENODATA),
+ CONST(ERR_ENODEV),
+ CONST(ERR_ENOENT),
+ CONST(ERR_ENOEXEC),
+ CONST(ERR_ENOLCK),
+ CONST(ERR_ENOLINK),
+ CONST(ERR_ENOMEDIUM),
+ CONST(ERR_ENOMEM),
+ CONST(ERR_ENOMSG),
+ CONST(ERR_ENONET),
+ CONST(ERR_ENOPKG),
+ CONST(ERR_ENOPROTOOPT),
+ CONST(ERR_ENOSPC),
+ CONST(ERR_ENOSR),
+ CONST(ERR_ENOSTR),
+ CONST(ERR_ENOSYS),
+ CONST(ERR_ENOTBLK),
+ CONST(ERR_ENOTCONN),
+ CONST(ERR_ENOTDIR),
+ CONST(ERR_ENOTEMPTY),
+ CONST(ERR_ENOTNAM),
+ CONST(ERR_ENOTSOCK),
+ CONST(ERR_ENOTSUP),
+ CONST(ERR_ENOTTY),
+ CONST(ERR_ENOTUNIQ),
+ CONST(ERR_ENXIO),
+ CONST(ERR_EOPNOTSUPP),
+ CONST(ERR_EOVERFLOW),
+ CONST(ERR_EPERM),
+ CONST(ERR_EPFNOSUPPORT),
+ CONST(ERR_EPIPE),
+ CONST(ERR_EPROCLIM),
+ CONST(ERR_EPROCUNAVAIL),
+ CONST(ERR_EPROGMISMATCH),
+ CONST(ERR_EPROGUNAVAIL),
+ CONST(ERR_EPROTO),
+ CONST(ERR_EPROTONOSUPPORT),
+ CONST(ERR_EPROTOTYPE),
+ CONST(ERR_ERANGE),
+ CONST(ERR_EREMCHG),
+ CONST(ERR_EREMOTE),
+ CONST(ERR_EREMOTEIO),
+ CONST(ERR_ERESTART),
+ CONST(ERR_EROFS),
+ CONST(ERR_ERPCMISMATCH),
+ CONST(ERR_ESHUTDOWN),
+ CONST(ERR_ESOCKTNOSUPPORT),
+ CONST(ERR_ESPIPE),
+ CONST(ERR_ESRCH),
+ CONST(ERR_ESRMNT),
+ CONST(ERR_ESTALE),
+ CONST(ERR_ESTRPIPE),
+ CONST(ERR_ETIME),
+ CONST(ERR_ETIMEDOUT),
+ CONST(ERR_ETOOMANYREFS),
+ CONST(ERR_ETXTBSY),
+ CONST(ERR_EUCLEAN),
+ CONST(ERR_EUNATCH),
+ CONST(ERR_EUSERS),
+ CONST(ERR_EWOULDBLOCK),
+ CONST(ERR_EXDEV),
+ CONST(ERR_EXFULL),
+};
+
+static const int n_constants = sizeof(constants) / sizeof(constants[0]);
+
+PyObject *
+pygpgme_make_constants(PyObject *self, PyObject *args)
+{
+ PyObject *dict;
+ int i;
+
+ if (!PyArg_ParseTuple(args, "O!", &PyDict_Type, &dict))
+ return NULL;
+
+ for (i = 0; i < n_constants; i++) {
+ PyObject *item;
+
+ item = PyInt_FromLong(constants[i].value);
+ PyDict_SetItemString(dict, constants[i].name, item);
+ Py_DECREF(item);
+ }
+ Py_RETURN_NONE;
+}
--- /dev/null
+/* -*- mode: C; c-basic-offset: 4; indent-tabs-mode: nil -*- */
+/*
+ pygpgme - a Python wrapper for the gpgme library
+ Copyright (C) 2006 James Henstridge
+
+ This library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Lesser General Public
+ License as published by the Free Software Foundation; either
+ version 2.1 of the License, or (at your option) any later version.
+
+ This library is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Lesser General Public License for more details.
+
+ You should have received a copy of the GNU Lesser General Public
+ License along with this library; if not, write to the Free Software
+ Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
+ */
+#include "pygpgme.h"
+
+static gpgme_error_t
+pygpgme_passphrase_cb(void *hook, const char *uid_hint,
+ const char *passphrase_info, int prev_was_bad,
+ int fd)
+{
+ PyObject *callback, *ret;
+ PyGILState_STATE state;
+ gpgme_error_t err;
+
+ state = PyGILState_Ensure();
+ callback = (PyObject *)hook;
+ ret = PyObject_CallFunction(callback, "zzii", uid_hint, passphrase_info,
+ prev_was_bad, fd);
+ err = pygpgme_check_pyerror();
+ Py_XDECREF(ret);
+ PyGILState_Release(state);
+ return err;
+}
+
+static void
+pygpgme_progress_cb(void *hook, const char *what, int type,
+ int current, int total)
+{
+ PyObject *callback, *ret;
+ PyGILState_STATE state;
+
+ state = PyGILState_Ensure();
+ callback = (PyObject *)hook;
+ ret = PyObject_CallFunction(callback, "ziii", what, type, current, total);
+ PyErr_Clear();
+ Py_XDECREF(ret);
+ PyGILState_Release(state);
+}
+
+static void
+pygpgme_context_dealloc(PyGpgmeContext *self)
+{
+ gpgme_passphrase_cb_t passphrase_cb;
+ gpgme_progress_cb_t progress_cb;
+ PyObject *callback;
+
+ if (self->ctx) {
+ /* free the passphrase callback */
+ gpgme_get_passphrase_cb(self->ctx, &passphrase_cb, (void **)&callback);
+ if (passphrase_cb == pygpgme_passphrase_cb) {
+ Py_DECREF(callback);
+ }
+
+ /* free the progress callback */
+ gpgme_get_progress_cb(self->ctx, &progress_cb, (void **)&callback);
+ if (progress_cb == pygpgme_progress_cb) {
+ Py_DECREF(callback);
+ }
+
+ gpgme_release(self->ctx);
+ }
+ self->ctx = NULL;
+ PyObject_Del(self);
+}
+
+static int
+pygpgme_context_init(PyGpgmeContext *self, PyObject *args, PyObject *kwargs)
+{
+ static char *kwlist[] = { NULL };
+
+ if (!PyArg_ParseTupleAndKeywords(args, kwargs, "", kwlist))
+ return -1;
+
+ if (self->ctx != NULL) {
+ PyErr_SetString(PyExc_ValueError, "context already initialised");
+ return -1;
+ }
+
+ if (pygpgme_check_error(gpgme_new(&self->ctx)))
+ return -1;
+
+ return 0;
+}
+
+static PyObject *
+pygpgme_context_get_protocol(PyGpgmeContext *self)
+{
+ return PyInt_FromLong(gpgme_get_protocol(self->ctx));
+}
+
+static int
+pygpgme_context_set_protocol(PyGpgmeContext *self, PyObject *value)
+{
+ gpgme_protocol_t protocol;
+
+ protocol = PyInt_AsLong(value);
+ if (PyErr_Occurred())
+ return -1;
+
+ if (pygpgme_check_error(gpgme_set_protocol(self->ctx, protocol)))
+ return -1;
+
+ return 0;
+}
+
+static PyObject *
+pygpgme_context_get_armor(PyGpgmeContext *self)
+{
+ return PyBool_FromLong(gpgme_get_armor(self->ctx));
+}
+
+static int
+pygpgme_context_set_armor(PyGpgmeContext *self, PyObject *value)
+{
+ int armor;
+
+ armor = PyInt_AsLong(value) != 0;
+ if (PyErr_Occurred())
+ return -1;
+
+ gpgme_set_armor(self->ctx, armor);
+ return 0;
+}
+
+static PyObject *
+pygpgme_context_get_textmode(PyGpgmeContext *self)
+{
+ return PyBool_FromLong(gpgme_get_textmode(self->ctx));
+}
+
+static int
+pygpgme_context_set_textmode(PyGpgmeContext *self, PyObject *value)
+{
+ int textmode;
+
+ textmode = PyInt_AsLong(value) != 0;
+ if (PyErr_Occurred())
+ return -1;
+
+ gpgme_set_textmode(self->ctx, textmode);
+ return 0;
+}
+
+static PyObject *
+pygpgme_context_get_include_certs(PyGpgmeContext *self)
+{
+ return PyInt_FromLong(gpgme_get_include_certs(self->ctx));
+}
+
+static int
+pygpgme_context_set_include_certs(PyGpgmeContext *self, PyObject *value)
+{
+ int nr_of_certs;
+
+ nr_of_certs = PyInt_AsLong(value);
+ if (PyErr_Occurred())
+ return -1;
+
+ gpgme_set_include_certs(self->ctx, nr_of_certs);
+ return 0;
+}
+
+static PyObject *
+pygpgme_context_get_keylist_mode(PyGpgmeContext *self)
+{
+ return PyInt_FromLong(gpgme_get_keylist_mode(self->ctx));
+}
+
+static int
+pygpgme_context_set_keylist_mode(PyGpgmeContext *self, PyObject *value)
+{
+ gpgme_keylist_mode_t keylist_mode;
+
+ keylist_mode = PyInt_AsLong(value);
+ if (PyErr_Occurred())
+ return -1;
+
+ if (pygpgme_check_error(gpgme_set_keylist_mode(self->ctx, keylist_mode)))
+ return -1;
+
+ return 0;
+}
+
+static PyObject *
+pygpgme_context_get_passphrase_cb(PyGpgmeContext *self)
+{
+ gpgme_passphrase_cb_t passphrase_cb;
+ PyObject *callback;
+
+ /* free the passphrase callback */
+ gpgme_get_passphrase_cb(self->ctx, &passphrase_cb, (void **)&callback);
+ if (passphrase_cb == pygpgme_passphrase_cb) {
+ Py_INCREF(callback);
+ return callback;
+ } else {
+ Py_RETURN_NONE;
+ }
+}
+
+static int
+pygpgme_context_set_passphrase_cb(PyGpgmeContext *self, PyObject *value)
+{
+ gpgme_passphrase_cb_t passphrase_cb;
+ PyObject *callback;
+
+ /* free the passphrase callback */
+ gpgme_get_passphrase_cb(self->ctx, &passphrase_cb, (void **)&callback);
+ if (passphrase_cb == pygpgme_passphrase_cb) {
+ Py_DECREF(callback);
+ }
+
+ /* callback of None == unset */
+ if (value == Py_None)
+ value = NULL;
+
+ if (value != NULL) {
+ Py_INCREF(value);
+ gpgme_set_passphrase_cb(self->ctx, pygpgme_passphrase_cb, value);
+ } else {
+ gpgme_set_passphrase_cb(self->ctx, NULL, NULL);
+ }
+ return 0;
+}
+
+static PyObject *
+pygpgme_context_get_progress_cb(PyGpgmeContext *self)
+{
+ gpgme_progress_cb_t progress_cb;
+ PyObject *callback;
+
+ /* free the progress callback */
+ gpgme_get_progress_cb(self->ctx, &progress_cb, (void **)&callback);
+ if (progress_cb == pygpgme_progress_cb) {
+ Py_INCREF(callback);
+ return callback;
+ } else {
+ Py_RETURN_NONE;
+ }
+}
+
+static int
+pygpgme_context_set_progress_cb(PyGpgmeContext *self, PyObject *value)
+{
+ gpgme_progress_cb_t progress_cb;
+ PyObject *callback;
+
+ /* free the progress callback */
+ gpgme_get_progress_cb(self->ctx, &progress_cb, (void **)&callback);
+ if (progress_cb == pygpgme_progress_cb) {
+ Py_DECREF(callback);
+ }
+
+ /* callback of None == unset */
+ if (value == Py_None)
+ value = NULL;
+
+ if (value != NULL) {
+ Py_INCREF(value);
+ gpgme_set_progress_cb(self->ctx, pygpgme_progress_cb, value);
+ } else {
+ gpgme_set_progress_cb(self->ctx, NULL, NULL);
+ }
+ return 0;
+}
+
+static PyObject *
+pygpgme_context_get_signers(PyGpgmeContext *self)
+{
+ PyObject *list, *tuple;
+ gpgme_key_t key;
+ int i;
+
+ list = PyList_New(0);
+ for (i = 0, key = gpgme_signers_enum(self->ctx, 0);
+ key != NULL; key = gpgme_signers_enum(self->ctx, ++i)) {
+ PyObject *item;
+
+ item = pygpgme_key_new(key);
+ gpgme_key_unref(key);
+ if (item == NULL) {
+ Py_DECREF(list);
+ return NULL;
+ }
+ PyList_Append(list, item);
+ Py_DECREF(item);
+ }
+ tuple = PySequence_Tuple(list);
+ Py_DECREF(list);
+ return tuple;
+}
+
+static int
+pygpgme_context_set_signers(PyGpgmeContext *self, PyObject *value)
+{
+ PyObject *signers = NULL;
+ int i, length, ret = 0;
+
+ signers = PySequence_Fast(value, "signers must be a sequence of keys");
+ if (!signers) {
+ ret = -1;
+ goto end;
+ }
+
+ gpgme_signers_clear(self->ctx);
+ length = PySequence_Fast_GET_SIZE(signers);
+ for (i = 0; i < length; i++) {
+ PyObject *item = PySequence_Fast_GET_ITEM(signers, i);
+
+ if (!PyObject_TypeCheck(item, &PyGpgmeKey_Type)) {
+ PyErr_SetString(PyExc_TypeError,
+ "signers must be a sequence of keys");
+ ret = -1;
+ goto end;
+ }
+ gpgme_signers_add(self->ctx, ((PyGpgmeKey *)item)->key);
+ }
+
+ end:
+ Py_XDECREF(signers);
+ return ret;
+}
+
+static PyGetSetDef pygpgme_context_getsets[] = {
+ { "protocol", (getter)pygpgme_context_get_protocol,
+ (setter)pygpgme_context_set_protocol },
+ { "armor", (getter)pygpgme_context_get_armor,
+ (setter)pygpgme_context_set_armor },
+ { "textmode", (getter)pygpgme_context_get_textmode,
+ (setter)pygpgme_context_set_textmode },
+ { "include_certs", (getter)pygpgme_context_get_include_certs,
+ (setter)pygpgme_context_set_include_certs },
+ { "keylist_mode", (getter)pygpgme_context_get_keylist_mode,
+ (setter)pygpgme_context_set_keylist_mode },
+ { "passphrase_cb", (getter)pygpgme_context_get_passphrase_cb,
+ (setter)pygpgme_context_set_passphrase_cb },
+ { "progress_cb", (getter)pygpgme_context_get_progress_cb,
+ (setter)pygpgme_context_set_progress_cb },
+ { "signers", (getter)pygpgme_context_get_signers,
+ (setter)pygpgme_context_set_signers },
+ { NULL, (getter)0, (setter)0 }
+};
+
+/* XXX: set_locale */
+static PyObject *
+pygpgme_context_set_locale(PyGpgmeContext *self, PyObject *args)
+{
+ int category;
+ const char *value;
+
+ if (!PyArg_ParseTuple(args, "iz", &category, &value))
+ return NULL;
+
+ if (pygpgme_check_error(gpgme_set_locale(self->ctx, category, value)))
+ return NULL;
+
+ Py_RETURN_NONE;
+}
+
+/* the following don't seem to be used */
+/* XXX: signers_clear */
+/* XXX: signers_add */
+/* XXX: signers_enum */
+
+static PyObject *
+pygpgme_context_get_key(PyGpgmeContext *self, PyObject *args)
+{
+ const char *fpr;
+ int secret = 0;
+ gpgme_error_t err;
+ gpgme_key_t key;
+ PyObject *ret;
+
+ if (!PyArg_ParseTuple(args, "s|i", &fpr, &secret))
+ return NULL;
+
+ Py_BEGIN_ALLOW_THREADS;
+ err = gpgme_get_key(self->ctx, fpr, &key, secret);
+ Py_END_ALLOW_THREADS;
+
+ if (pygpgme_check_error(err))
+ return NULL;
+
+ ret = pygpgme_key_new(key);
+ gpgme_key_unref(key);
+ return ret;
+}
+
+/* XXX: cancel -- not needed unless we wrap the async calls */
+
+/* annotate exception with encrypt_result data */
+static void
+decode_encrypt_result(PyGpgmeContext *self)
+{
+ PyObject *err_type, *err_value, *err_traceback;
+ gpgme_encrypt_result_t res;
+ gpgme_invalid_key_t key;
+ PyObject *list;
+
+ PyErr_Fetch(&err_type, &err_value, &err_traceback);
+ PyErr_NormalizeException(&err_type, &err_value, &err_traceback);
+
+ if (!PyErr_GivenExceptionMatches(err_type, pygpgme_error))
+ goto end;
+
+ res = gpgme_op_encrypt_result(self->ctx);
+ if (res == NULL)
+ goto end;
+
+ list = PyList_New(0);
+ for (key = res->invalid_recipients; key != NULL; key = key->next) {
+ PyObject *item, *err;
+
+ err = pygpgme_error_object(key->reason);
+ item = Py_BuildValue("(zN)", key->fpr, err);
+ PyList_Append(list, item);
+ Py_DECREF(item);
+ }
+
+ PyObject_SetAttrString(err_value, "invalid_recipients", list);
+ Py_DECREF(list);
+
+ end:
+ PyErr_Restore(err_type, err_value, err_traceback);
+}
+
+static PyObject *
+pygpgme_context_encrypt(PyGpgmeContext *self, PyObject *args)
+{
+ PyObject *py_recp, *py_plain, *py_cipher;
+ int flags, i, length;
+ gpgme_key_t *recp;
+ gpgme_data_t plain, cipher;
+ gpgme_error_t err;
+
+ if (!PyArg_ParseTuple(args, "OiOO", &py_recp, &flags,
+ &py_plain, &py_cipher))
+ return NULL;
+
+ py_recp = PySequence_Fast(py_recp, "first argument must be a sequence");
+ if (py_recp == NULL)
+ return NULL;
+
+ length = PySequence_Fast_GET_SIZE(py_recp);
+ recp = malloc((length + 1) * sizeof (gpgme_key_t));
+ for (i = 0; i < length; i++) {
+ PyObject *item = PySequence_Fast_GET_ITEM(py_recp, i);
+
+ if (!PyObject_TypeCheck(item, &PyGpgmeKey_Type)) {
+ free(recp);
+ Py_DECREF(py_recp);
+ PyErr_SetString(PyExc_TypeError, "items in first argument must "
+ "be gpgme.Key objects");
+ return NULL;
+ }
+ recp[i] = ((PyGpgmeKey *)item)->key;
+ }
+ recp[i] = NULL;
+
+ if (pygpgme_data_new(&plain, py_plain)) {
+ free(recp);
+ Py_DECREF(py_recp);
+ return NULL;
+ }
+ if (pygpgme_data_new(&cipher, py_cipher)) {
+ free(recp);
+ Py_DECREF(py_recp);
+ gpgme_data_release(plain);
+ return NULL;
+ }
+
+ Py_BEGIN_ALLOW_THREADS;
+ err = gpgme_op_encrypt(self->ctx, recp, flags, plain, cipher);
+ Py_END_ALLOW_THREADS;
+
+ free(recp);
+ Py_DECREF(py_recp);
+ gpgme_data_release(plain);
+ gpgme_data_release(cipher);
+
+ if (pygpgme_check_error(err)) {
+ decode_encrypt_result(self);
+ return NULL;
+ }
+
+ Py_RETURN_NONE;
+}
+
+static PyObject *
+pygpgme_context_encrypt_sign(PyGpgmeContext *self, PyObject *args)
+{
+ PyObject *py_recp, *py_plain, *py_cipher;
+ int flags, i, length;
+ gpgme_key_t *recp;
+ gpgme_data_t plain, cipher;
+ gpgme_error_t err;
+ gpgme_sign_result_t result;
+
+ if (!PyArg_ParseTuple(args, "OiOO", &py_recp, &flags,
+ &py_plain, &py_cipher))
+ return NULL;
+
+ py_recp = PySequence_Fast(py_recp, "first argument must be a sequence");
+ if (py_recp == NULL)
+ return NULL;
+
+ length = PySequence_Fast_GET_SIZE(py_recp);
+ recp = malloc((length + 1) * sizeof (gpgme_key_t));
+ for (i = 0; i < length; i++) {
+ PyObject *item = PySequence_Fast_GET_ITEM(py_recp, i);
+
+ if (!PyObject_TypeCheck(item, &PyGpgmeKey_Type)) {
+ free(recp);
+ Py_DECREF(py_recp);
+ PyErr_SetString(PyExc_TypeError, "items in first argument must "
+ "be gpgme.Key objects");
+ return NULL;
+ }
+ recp[i] = ((PyGpgmeKey *)item)->key;
+ }
+ recp[i] = NULL;
+
+ if (pygpgme_data_new(&plain, py_plain)) {
+ free(recp);
+ Py_DECREF(py_recp);
+ return NULL;
+ }
+ if (pygpgme_data_new(&cipher, py_cipher)) {
+ free(recp);
+ Py_DECREF(py_recp);
+ gpgme_data_release(plain);
+ return NULL;
+ }
+
+ Py_BEGIN_ALLOW_THREADS;
+ err = gpgme_op_encrypt_sign(self->ctx, recp, flags, plain, cipher);
+ Py_END_ALLOW_THREADS;
+
+ free(recp);
+ Py_DECREF(py_recp);
+ gpgme_data_release(plain);
+ gpgme_data_release(cipher);
+
+ result = gpgme_op_sign_result(self->ctx);
+
+ /* annotate exception */
+ if (pygpgme_check_error(err)) {
+ PyObject *err_type, *err_value, *err_traceback;
+ PyObject *list;
+ gpgme_invalid_key_t key;
+
+ decode_encrypt_result(self);
+
+ PyErr_Fetch(&err_type, &err_value, &err_traceback);
+ PyErr_NormalizeException(&err_type, &err_value, &err_traceback);
+
+ if (result == NULL)
+ goto end;
+
+ if (!PyErr_GivenExceptionMatches(err_type, pygpgme_error))
+ goto end;
+
+ list = PyList_New(0);
+ for (key = result->invalid_signers; key != NULL; key = key->next) {
+ PyObject *item, *err;
+
+ err = pygpgme_error_object(key->reason);
+ item = Py_BuildValue("(zN)", key->fpr, err);
+ PyList_Append(list, item);
+ Py_DECREF(item);
+ }
+ PyObject_SetAttrString(err_value, "invalid_signers", list);
+ Py_DECREF(list);
+
+ list = pygpgme_newsiglist_new(result->signatures);
+ PyObject_SetAttrString(err_value, "signatures", list);
+ Py_DECREF(list);
+ end:
+ PyErr_Restore(err_type, err_value, err_traceback);
+ return NULL;
+ }
+
+ if (result)
+ return pygpgme_newsiglist_new(result->signatures);
+ else
+ return PyList_New(0);
+}
+
+static void
+decode_decrypt_result(PyGpgmeContext *self)
+{
+ PyObject *err_type, *err_value, *err_traceback;
+ PyObject *value;
+ gpgme_decrypt_result_t res;
+
+ PyErr_Fetch(&err_type, &err_value, &err_traceback);
+ PyErr_NormalizeException(&err_type, &err_value, &err_traceback);
+
+ if (!PyErr_GivenExceptionMatches(err_type, pygpgme_error))
+ goto end;
+
+ res = gpgme_op_decrypt_result(self->ctx);
+ if (res == NULL)
+ goto end;
+
+ if (res->unsupported_algorithm) {
+ value = PyString_FromString(res->unsupported_algorithm);
+ } else {
+ Py_INCREF(Py_None);
+ value = Py_None;
+ }
+ if (value) {
+ PyObject_SetAttrString(err_value, "unsupported_algorithm", value);
+ Py_DECREF(value);
+ }
+
+ value = PyBool_FromLong(res->wrong_key_usage);
+ if (value) {
+ PyObject_SetAttrString(err_value, "wrong_key_usage", value);
+ Py_DECREF(value);
+ }
+
+ end:
+ PyErr_Restore(err_type, err_value, err_traceback);
+}
+
+static PyObject *
+pygpgme_context_decrypt(PyGpgmeContext *self, PyObject *args)
+{
+ PyObject *py_cipher, *py_plain;
+ gpgme_data_t cipher, plain;
+ gpgme_error_t err;
+
+ if (!PyArg_ParseTuple(args, "OO", &py_cipher, &py_plain))
+ return NULL;
+
+ if (pygpgme_data_new(&cipher, py_cipher)) {
+ return NULL;
+ }
+
+ if (pygpgme_data_new(&plain, py_plain)) {
+ gpgme_data_release(cipher);
+ return NULL;
+ }
+
+ Py_BEGIN_ALLOW_THREADS;
+ err = gpgme_op_decrypt(self->ctx, cipher, plain);
+ Py_END_ALLOW_THREADS;
+
+ gpgme_data_release(cipher);
+ gpgme_data_release(plain);
+
+ if (pygpgme_check_error(err)) {
+ decode_decrypt_result(self);
+ return NULL;
+ }
+
+ Py_RETURN_NONE;
+}
+
+static PyObject *
+pygpgme_context_decrypt_verify(PyGpgmeContext *self, PyObject *args)
+{
+ PyObject *py_cipher, *py_plain;
+ gpgme_data_t cipher, plain;
+ gpgme_error_t err;
+ gpgme_verify_result_t result;
+
+ if (!PyArg_ParseTuple(args, "OO", &py_cipher, &py_plain))
+ return NULL;
+
+ if (pygpgme_data_new(&cipher, py_cipher)) {
+ return NULL;
+ }
+
+ if (pygpgme_data_new(&plain, py_plain)) {
+ gpgme_data_release(cipher);
+ return NULL;
+ }
+
+ Py_BEGIN_ALLOW_THREADS;
+ err = gpgme_op_decrypt_verify(self->ctx, cipher, plain);
+ Py_END_ALLOW_THREADS;
+
+ gpgme_data_release(cipher);
+ gpgme_data_release(plain);
+
+ if (pygpgme_check_error(err)) {
+ decode_decrypt_result(self);
+ return NULL;
+ }
+
+ result = gpgme_op_verify_result(self->ctx);
+
+ /* annotate exception */
+ if (pygpgme_check_error(err)) {
+ PyObject *err_type, *err_value, *err_traceback;
+ PyObject *list;
+
+ PyErr_Fetch(&err_type, &err_value, &err_traceback);
+ PyErr_NormalizeException(&err_type, &err_value, &err_traceback);
+
+ if (result == NULL)
+ goto end;
+
+ if (!PyErr_GivenExceptionMatches(err_type, pygpgme_error))
+ goto end;
+
+ list = pygpgme_siglist_new(result->signatures);
+ PyObject_SetAttrString(err_value, "signatures", list);
+ Py_DECREF(list);
+ end:
+ PyErr_Restore(err_type, err_value, err_traceback);
+ return NULL;
+ }
+
+ if (result)
+ return pygpgme_siglist_new(result->signatures);
+ else
+ return PyList_New(0);
+}
+
+static PyObject *
+pygpgme_context_sign(PyGpgmeContext *self, PyObject *args)
+{
+ PyObject *py_plain, *py_sig;
+ gpgme_data_t plain, sig;
+ int sig_mode = GPGME_SIG_MODE_NORMAL;
+ gpgme_error_t err;
+ gpgme_sign_result_t result;
+
+ if (!PyArg_ParseTuple(args, "OO|i", &py_plain, &py_sig, &sig_mode))
+ return NULL;
+
+ if (pygpgme_data_new(&plain, py_plain))
+ return NULL;
+
+ if (pygpgme_data_new(&sig, py_sig)) {
+ gpgme_data_release(plain);
+ return NULL;
+ }
+
+ Py_BEGIN_ALLOW_THREADS;
+ err = gpgme_op_sign(self->ctx, plain, sig, sig_mode);
+ Py_END_ALLOW_THREADS;
+
+ gpgme_data_release(plain);
+ gpgme_data_release(sig);
+
+ result = gpgme_op_sign_result(self->ctx);
+
+ /* annotate exception */
+ if (pygpgme_check_error(err)) {
+ PyObject *err_type, *err_value, *err_traceback;
+ PyObject *list;
+ gpgme_invalid_key_t key;
+
+ PyErr_Fetch(&err_type, &err_value, &err_traceback);
+ PyErr_NormalizeException(&err_type, &err_value, &err_traceback);
+
+ if (result == NULL)
+ goto end;
+
+ if (!PyErr_GivenExceptionMatches(err_type, pygpgme_error))
+ goto end;
+
+ list = PyList_New(0);
+ for (key = result->invalid_signers; key != NULL; key = key->next) {
+ PyObject *item, *err;
+
+ err = pygpgme_error_object(key->reason);
+ item = Py_BuildValue("(zN)", key->fpr, err);
+ PyList_Append(list, item);
+ Py_DECREF(item);
+ }
+ PyObject_SetAttrString(err_value, "invalid_signers", list);
+ Py_DECREF(list);
+
+ list = pygpgme_newsiglist_new(result->signatures);
+ PyObject_SetAttrString(err_value, "signatures", list);
+ Py_DECREF(list);
+ end:
+ PyErr_Restore(err_type, err_value, err_traceback);
+ return NULL;
+ }
+
+ if (result)
+ return pygpgme_newsiglist_new(result->signatures);
+ else
+ return PyList_New(0);
+}
+
+static PyObject *
+pygpgme_context_verify(PyGpgmeContext *self, PyObject *args)
+{
+ PyObject *py_sig, *py_signed_text, *py_plaintext;
+ gpgme_data_t sig, signed_text, plaintext;
+ gpgme_error_t err;
+ gpgme_verify_result_t result;
+
+ if (!PyArg_ParseTuple(args, "OOO", &py_sig, &py_signed_text,
+ &py_plaintext))
+ return NULL;
+
+ if (pygpgme_data_new(&sig, py_sig)) {
+ return NULL;
+ }
+ if (pygpgme_data_new(&signed_text, py_signed_text)) {
+ gpgme_data_release(sig);
+ return NULL;
+ }
+ if (pygpgme_data_new(&plaintext, py_plaintext)) {
+ gpgme_data_release(sig);
+ gpgme_data_release(signed_text);
+ return NULL;
+ }
+
+ Py_BEGIN_ALLOW_THREADS;
+ err = gpgme_op_verify(self->ctx, sig, signed_text, plaintext);
+ Py_END_ALLOW_THREADS;
+
+ gpgme_data_release(sig);
+ gpgme_data_release(signed_text);
+ gpgme_data_release(plaintext);
+
+ result = gpgme_op_verify_result(self->ctx);
+
+ /* annotate exception */
+ if (pygpgme_check_error(err)) {
+ PyObject *err_type, *err_value, *err_traceback;
+ PyObject *list;
+
+ PyErr_Fetch(&err_type, &err_value, &err_traceback);
+ PyErr_NormalizeException(&err_type, &err_value, &err_traceback);
+
+ if (result == NULL)
+ goto end;
+
+ if (!PyErr_GivenExceptionMatches(err_type, pygpgme_error))
+ goto end;
+
+ list = pygpgme_siglist_new(result->signatures);
+ PyObject_SetAttrString(err_value, "signatures", list);
+ Py_DECREF(list);
+ end:
+ PyErr_Restore(err_type, err_value, err_traceback);
+ return NULL;
+ }
+
+ if (result)
+ return pygpgme_siglist_new(result->signatures);
+ else
+ return PyList_New(0);
+}
+
+static PyObject *
+pygpgme_context_import(PyGpgmeContext *self, PyObject *args)
+{
+ PyObject *py_keydata, *result;
+ gpgme_data_t keydata;
+ gpgme_error_t err;
+
+ if (!PyArg_ParseTuple(args, "O", &py_keydata))
+ return NULL;
+
+ if (pygpgme_data_new(&keydata, py_keydata))
+ return NULL;
+
+ Py_BEGIN_ALLOW_THREADS;
+ err = gpgme_op_import(self->ctx, keydata);
+ Py_END_ALLOW_THREADS;
+
+ gpgme_data_release(keydata);
+ result = pygpgme_import_result(self->ctx);
+ if (pygpgme_check_error(err)) {
+ PyObject *err_type, *err_value, *err_traceback;
+
+ PyErr_Fetch(&err_type, &err_value, &err_traceback);
+ PyErr_NormalizeException(&err_type, &err_value, &err_traceback);
+
+ if (!PyErr_GivenExceptionMatches(err_type, pygpgme_error))
+ goto end;
+
+ if (result != NULL) {
+ PyObject_SetAttrString(err_value, "result", result);
+ Py_DECREF(result);
+ }
+ end:
+ PyErr_Restore(err_type, err_value, err_traceback);
+ return NULL;
+ }
+ return result;
+}
+
+static PyObject *
+pygpgme_context_export(PyGpgmeContext *self, PyObject *args)
+{
+ PyObject *py_pattern, *py_keydata;
+ const char *pattern;
+ const char **patterns;
+ int i, length;
+ gpgme_data_t keydata;
+ gpgme_error_t err;
+
+ if (!PyArg_ParseTuple(args, "OO", &py_pattern, &py_keydata))
+ return NULL;
+
+ if (py_pattern == Py_None) {
+ Py_INCREF(py_pattern);
+ pattern = NULL;
+ patterns = NULL;
+ } else if (PyString_Check(py_pattern)) {
+ Py_INCREF(py_pattern);
+ pattern = PyString_AsString(py_pattern);
+ patterns = NULL;
+ } else {
+ py_pattern = PySequence_Fast(py_pattern,
+ "first argument must be a string or sequence of strings");
+ if (py_pattern == NULL)
+ return NULL;
+ length = PySequence_Fast_GET_SIZE(py_pattern);
+ pattern = NULL;
+ patterns = malloc((length + 1) * sizeof(const char *));
+ for (i = 0; i < length; i++) {
+ PyObject *item = PySequence_Fast_GET_ITEM(py_pattern, i);
+
+ if (!PyString_Check(item)) {
+ PyErr_SetString(PyExc_TypeError,
+ "first argument must be a string or sequence of strings");
+ free(patterns);
+ Py_DECREF(py_pattern);
+ return NULL;
+ }
+ patterns[i] = PyString_AsString(item);
+ }
+ patterns[i] = NULL;
+ }
+
+ if (pygpgme_data_new(&keydata, py_keydata)) {
+ Py_DECREF(py_pattern);
+ if (patterns)
+ free(patterns);
+ return NULL;
+ }
+
+ Py_BEGIN_ALLOW_THREADS;
+ if (patterns)
+ err = gpgme_op_export_ext(self->ctx, patterns, 0, keydata);
+ else
+ err = gpgme_op_export(self->ctx, pattern, 0, keydata);
+ Py_END_ALLOW_THREADS;
+
+ Py_DECREF(py_pattern);
+ if (patterns)
+ free(patterns);
+ gpgme_data_release(keydata);
+ if (pygpgme_check_error(err))
+ return NULL;
+ Py_RETURN_NONE;
+}
+
+// pygpgme_context_genkey
+
+static PyObject *
+pygpgme_context_delete(PyGpgmeContext *self, PyObject *args)
+{
+ PyGpgmeKey *key;
+ int allow_secret = 0;
+ gpgme_error_t err;
+
+ if (!PyArg_ParseTuple(args, "O!|i", &PyGpgmeKey_Type, &key, &allow_secret))
+ return NULL;
+
+ Py_BEGIN_ALLOW_THREADS;
+ err = gpgme_op_delete(self->ctx, key->key, allow_secret);
+ Py_END_ALLOW_THREADS;
+
+ if (pygpgme_check_error(err))
+ return NULL;
+ Py_RETURN_NONE;
+}
+
+static gpgme_error_t
+pygpgme_edit_cb(void *user_data, gpgme_status_code_t status,
+ const char *args, int fd)
+{
+ PyObject *callback, *ret;
+ PyGILState_STATE state;
+ gpgme_error_t err;
+
+ state = PyGILState_Ensure();
+ callback = (PyObject *)user_data;
+ ret = PyObject_CallFunction(callback, "lzi", (long)status, args, fd);
+ err = pygpgme_check_pyerror();
+ Py_XDECREF(ret);
+ PyGILState_Release(state);
+ return err;
+}
+
+static PyObject *
+pygpgme_context_edit(PyGpgmeContext *self, PyObject *args)
+{
+ PyGpgmeKey *key;
+ PyObject *callback, *py_out;
+ gpgme_data_t out;
+ gpgme_error_t err;
+
+ if (!PyArg_ParseTuple(args, "O!OO", &PyGpgmeKey_Type, &key, &callback,
+ &py_out))
+ return NULL;
+
+ if (pygpgme_data_new(&out, py_out))
+ return NULL;
+
+ Py_BEGIN_ALLOW_THREADS;
+ err = gpgme_op_edit(self->ctx, key->key,
+ pygpgme_edit_cb, (void *)callback, out);
+ Py_END_ALLOW_THREADS;
+
+ gpgme_data_release(out);
+
+ if (pygpgme_check_error(err))
+ return NULL;
+ Py_RETURN_NONE;
+}
+
+static PyObject *
+pygpgme_context_card_edit(PyGpgmeContext *self, PyObject *args)
+{
+ PyGpgmeKey *key;
+ PyObject *callback, *py_out;
+ gpgme_data_t out;
+ gpgme_error_t err;
+
+ if (!PyArg_ParseTuple(args, "O!OO", &PyGpgmeKey_Type, &key, &callback,
+ &py_out))
+ return NULL;
+
+ if (pygpgme_data_new(&out, py_out))
+ return NULL;
+
+ Py_BEGIN_ALLOW_THREADS;
+ err = gpgme_op_card_edit(self->ctx, key->key,
+ pygpgme_edit_cb, (void *)callback, out);
+ Py_END_ALLOW_THREADS;
+
+ gpgme_data_release(out);
+
+ if (pygpgme_check_error(err))
+ return NULL;
+ Py_RETURN_NONE;
+}
+
+static PyObject *
+pygpgme_context_keylist(PyGpgmeContext *self, PyObject *args)
+{
+ PyObject *py_pattern = Py_None;
+ const char *pattern;
+ const char **patterns;
+ int secret_only = 0, i, length;
+ gpgme_error_t err;
+ PyGpgmeKeyIter *ret;
+
+ if (!PyArg_ParseTuple(args, "|Oi", &py_pattern, &secret_only))
+ return NULL;
+
+ if (py_pattern == Py_None) {
+ Py_INCREF(py_pattern);
+ pattern = NULL;
+ patterns = NULL;
+ } else if (PyString_Check(py_pattern)) {
+ Py_INCREF(py_pattern);
+ pattern = PyString_AsString(py_pattern);
+ patterns = NULL;
+ } else {
+ py_pattern = PySequence_Fast(py_pattern,
+ "first argument must be a string or sequence of strings");
+ if (py_pattern == NULL)
+ return NULL;
+ length = PySequence_Fast_GET_SIZE(py_pattern);
+ pattern = NULL;
+ patterns = malloc((length + 1) * sizeof(const char *));
+ for (i = 0; i < length; i++) {
+ PyObject *item = PySequence_Fast_GET_ITEM(py_pattern, i);
+
+ if (!PyString_Check(item)) {
+ PyErr_SetString(PyExc_TypeError,
+ "first argument must be a string or sequence of strings");
+ free(patterns);
+ Py_DECREF(py_pattern);
+ return NULL;
+ }
+ patterns[i] = PyString_AsString(item);
+ }
+ patterns[i] = NULL;
+ }
+
+ Py_BEGIN_ALLOW_THREADS;
+ if (patterns)
+ err = gpgme_op_keylist_ext_start(self->ctx, patterns, secret_only, 0);
+ else
+ err = gpgme_op_keylist_start(self->ctx, pattern, secret_only);
+ Py_END_ALLOW_THREADS;
+
+ Py_DECREF(py_pattern);
+ if (patterns)
+ free(patterns);
+
+ if (pygpgme_check_error(err))
+ return NULL;
+
+ /* return a KeyIter object */
+ ret = PyObject_New(PyGpgmeKeyIter, &PyGpgmeKeyIter_Type);
+ if (!ret)
+ return NULL;
+ Py_INCREF(self);
+ ret->ctx = self;
+ return (PyObject *)ret;
+}
+
+// pygpgme_context_trustlist
+
+static PyMethodDef pygpgme_context_methods[] = {
+ { "set_locale", (PyCFunction)pygpgme_context_set_locale, METH_VARARGS },
+ { "get_key", (PyCFunction)pygpgme_context_get_key, METH_VARARGS },
+ { "encrypt", (PyCFunction)pygpgme_context_encrypt, METH_VARARGS },
+ { "encrypt_sign", (PyCFunction)pygpgme_context_encrypt_sign, METH_VARARGS },
+ { "decrypt", (PyCFunction)pygpgme_context_decrypt, METH_VARARGS },
+ { "decrypt_verify", (PyCFunction)pygpgme_context_decrypt_verify, METH_VARARGS },
+ { "sign", (PyCFunction)pygpgme_context_sign, METH_VARARGS },
+ { "verify", (PyCFunction)pygpgme_context_verify, METH_VARARGS },
+ { "import_", (PyCFunction)pygpgme_context_import, METH_VARARGS },
+ { "export", (PyCFunction)pygpgme_context_export, METH_VARARGS },
+ // genkey
+ { "delete", (PyCFunction)pygpgme_context_delete, METH_VARARGS },
+ { "edit", (PyCFunction)pygpgme_context_edit, METH_VARARGS },
+ { "card_edit", (PyCFunction)pygpgme_context_card_edit, METH_VARARGS },
+ { "keylist", (PyCFunction)pygpgme_context_keylist, METH_VARARGS },
+ // trustlist
+ { NULL, 0, 0 }
+};
+
+PyTypeObject PyGpgmeContext_Type = {
+ PyObject_HEAD_INIT(NULL)
+ 0,
+ "gpgme.Context",
+ sizeof(PyGpgmeContext),
+ .tp_flags = Py_TPFLAGS_DEFAULT,
+ .tp_dealloc = (destructor)pygpgme_context_dealloc,
+ .tp_init = (initproc)pygpgme_context_init,
+ .tp_getset = pygpgme_context_getsets,
+ .tp_methods = pygpgme_context_methods,
+};
--- /dev/null
+/* -*- mode: C; c-basic-offset: 4; indent-tabs-mode: nil -*- */
+/*
+ pygpgme - a Python wrapper for the gpgme library
+ Copyright (C) 2006 James Henstridge
+
+ This library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Lesser General Public
+ License as published by the Free Software Foundation; either
+ version 2.1 of the License, or (at your option) any later version.
+
+ This library is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Lesser General Public License for more details.
+
+ You should have received a copy of the GNU Lesser General Public
+ License along with this library; if not, write to the Free Software
+ Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
+ */
+#include <Python.h>
+#include <errno.h>
+#include "pygpgme.h"
+
+/* called when a Python exception is set. Clears the exception and tries
+ * to set errno appropriately. */
+static void
+set_errno(void)
+{
+ PyObject *exc, *value, *tb, *py_errno;
+
+ PyErr_Fetch(&exc, &value, &tb);
+
+ /* if we have an IOError, try and get the actual errno */
+ if (PyErr_GivenExceptionMatches(exc, PyExc_IOError) && value != NULL) {
+ py_errno = PyObject_GetAttrString(value, "errno");
+ if (py_errno != NULL && PyInt_Check(py_errno)) {
+ errno = PyInt_AsLong(py_errno);
+ } else {
+ PyErr_Clear();
+ errno = EINVAL;
+ }
+ Py_XDECREF(py_errno);
+ } else {
+ errno = EINVAL;
+ }
+ Py_XDECREF(tb);
+ Py_XDECREF(value);
+ Py_DECREF(exc);
+}
+
+static ssize_t
+read_cb(void *handle, void *buffer, size_t size)
+{
+ PyGILState_STATE state;
+ PyObject *fp = handle;
+ PyObject *result;
+ int result_size;
+
+ state = PyGILState_Ensure();
+ result = PyObject_CallMethod(fp, "read", "l", (long)size);
+ /* check for exceptions or non-string return values */
+ if (result == NULL) {
+ set_errno();
+ result_size = -1;
+ goto end;
+ }
+ /* if we don't have a string return value, consider that an error too */
+ if (!PyString_Check(result)) {
+ Py_DECREF(result);
+ errno = EINVAL;
+ result_size = -1;
+ goto end;
+ }
+ /* copy the result into the given buffer */
+ result_size = PyString_Size(result);
+ if (result_size > size)
+ result_size = size;
+ memcpy(buffer, PyString_AsString(result), result_size);
+ Py_DECREF(result);
+ end:
+ PyGILState_Release(state);
+ return result_size;
+}
+
+static ssize_t
+write_cb(void *handle, const void *buffer, size_t size)
+{
+ PyGILState_STATE state;
+ PyObject *fp = handle;
+ PyObject *result;
+ ssize_t bytes_written = 0;
+
+ state = PyGILState_Ensure();
+ result = PyObject_CallMethod(fp, "write", "s#", buffer, (int)size);
+ if (result == NULL) {
+ set_errno();
+ bytes_written = -1;
+ goto end;
+ }
+ Py_DECREF(result);
+ bytes_written = size;
+ end:
+ PyGILState_Release(state);
+ return bytes_written;
+}
+
+static off_t
+seek_cb(void *handle, off_t offset, int whence)
+{
+ PyGILState_STATE state;
+ PyObject *fp = handle;
+ PyObject *result;
+
+ state = PyGILState_Ensure();
+ result = PyObject_CallMethod(fp, "seek", "li", (long)offset, whence);
+ if (result == NULL) {
+ set_errno();
+ offset = -1;
+ goto end;
+ }
+ Py_DECREF(result);
+
+ /* now get the file location */
+ result = PyObject_CallMethod(fp, "tell", NULL);
+ if (result == NULL) {
+ set_errno();
+ offset = -1;
+ goto end;
+ }
+ if (!PyInt_Check(result)) {
+ Py_DECREF(result);
+ errno = EINVAL;
+ offset = -1;
+ goto end;
+ }
+ offset = PyInt_AsLong(result);
+ Py_DECREF(result);
+ end:
+ PyGILState_Release(state);
+ return offset;
+}
+
+static void
+release_cb(void *handle)
+{
+ PyGILState_STATE state;
+ PyObject *fp = handle;
+
+ state = PyGILState_Ensure();
+ Py_DECREF(fp);
+ PyGILState_Release(state);
+}
+
+static struct gpgme_data_cbs python_data_cbs = {
+ .read = read_cb,
+ .write = write_cb,
+ .seek = seek_cb,
+ .release = release_cb,
+};
+
+/* create a gpgme data object wrapping a Python file like object */
+int
+pygpgme_data_new(gpgme_data_t *dh, PyObject *fp)
+{
+ gpgme_error_t error;
+
+ if (fp == Py_None) {
+ *dh = NULL;
+ return 0;
+ }
+
+ error = gpgme_data_new_from_cbs(dh, &python_data_cbs, fp);
+
+ if (pygpgme_check_error(error))
+ return -1;
+
+ /* if no error, then the new gpgme_data_t object owns a reference to
+ * the python object */
+ Py_INCREF(fp);
+ return 0;
+}
--- /dev/null
+/* -*- mode: C; c-basic-offset: 4; indent-tabs-mode: nil -*- */
+/*
+ pygpgme - a Python wrapper for the gpgme library
+ Copyright (C) 2006 James Henstridge
+
+ This library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Lesser General Public
+ License as published by the Free Software Foundation; either
+ version 2.1 of the License, or (at your option) any later version.
+
+ This library is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Lesser General Public License for more details.
+
+ You should have received a copy of the GNU Lesser General Public
+ License along with this library; if not, write to the Free Software
+ Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
+ */
+#include <Python.h>
+#include "pygpgme.h"
+
+PyObject *pygpgme_error = NULL;
+
+PyObject *
+pygpgme_error_object(gpgme_error_t err)
+{
+ char buf[256] = { '\0' };
+ PyObject *exc, *attr;
+
+ if (err == GPG_ERR_NO_ERROR)
+ Py_RETURN_NONE;
+
+ /* get the error string */
+ if (gpgme_strerror_r(err, buf, 255) != 0)
+ strcpy(buf, "Unknown");
+
+ exc = PyObject_CallFunction(pygpgme_error, "lls",
+ (long)gpgme_err_source(err),
+ (long)gpgme_err_code(err),
+ buf);
+ if (!exc)
+ return NULL;
+ /* set the source and code as attributes of the exception object: */
+ attr = PyInt_FromLong(gpgme_err_source(err));
+ PyObject_SetAttrString(exc, "source", attr);
+ Py_DECREF(attr);
+
+ attr = PyInt_FromLong(gpgme_err_code(err));
+ PyObject_SetAttrString(exc, "code", attr);
+ Py_DECREF(attr);
+
+ attr = PyString_FromString(buf);
+ PyObject_SetAttrString(exc, "message", attr);
+ Py_DECREF(attr);
+
+ return exc;
+}
+
+/* check whether the given gpgme_error_t value indicates an error. If so,
+ * raise an equivalent Python exception and return TRUE */
+int
+pygpgme_check_error(gpgme_error_t err)
+{
+ PyObject *exc;
+
+ if (err == GPG_ERR_NO_ERROR)
+ return 0;
+
+ exc = pygpgme_error_object(err);
+ if (!exc)
+ return -1;
+
+ PyErr_SetObject(pygpgme_error, exc);
+
+ return -1;
+}
+
+gpgme_error_t
+pygpgme_check_pyerror(void)
+{
+ PyObject *err_type, *err_value, *err_traceback;
+ gpgme_error_t err;
+ PyObject *args = NULL, *source = NULL, *code = NULL;
+
+ if (!PyErr_Occurred())
+ return GPG_ERR_NO_ERROR;
+
+ PyErr_Fetch(&err_type, &err_value, &err_traceback);
+ PyErr_NormalizeException(&err_type, &err_value, &err_traceback);
+ err = gpgme_error(GPG_ERR_GENERAL);
+
+ /* get the first argument of the exception */
+ args = PyObject_GetAttrString(err_value, "args");
+ if (args == NULL)
+ goto end;
+
+ source = PyTuple_GetItem(args, 0);
+ if (source == NULL)
+ goto end;
+
+ if (PyErr_GivenExceptionMatches(err_type, pygpgme_error)) {
+ code = PyTuple_GetItem(args, 1);
+ if (code == NULL)
+ goto end;
+
+ if (PyInt_Check(source) && PyInt_Check(code))
+ err = gpgme_err_make(PyInt_AsLong(source), PyInt_AsLong(code));
+ } else if (PyErr_GivenExceptionMatches(err_type, PyExc_IOError) ||
+ PyErr_GivenExceptionMatches(err_type, PyExc_OSError)) {
+ if (PyInt_Check(source))
+ err = gpgme_err_code_from_errno(PyInt_AsLong(source));
+ }
+
+ end:
+ Py_XDECREF(err_type);
+ Py_XDECREF(err_value);
+ Py_XDECREF(err_traceback);
+ Py_XDECREF(args);
+ PyErr_Clear();
+
+ return err;
+}
+
+int
+pygpgme_no_constructor(PyObject *self, PyObject *args, PyObject *kwargs)
+{
+ PyErr_Format(PyExc_NotImplementedError,
+ "can not directly create instances of %s",
+ self->ob_type->tp_name);
+ return -1;
+}
--- /dev/null
+/* -*- mode: C; c-basic-offset: 4; indent-tabs-mode: nil -*- */
+/*
+ pygpgme - a Python wrapper for the gpgme library
+ Copyright (C) 2006 James Henstridge
+
+ This library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Lesser General Public
+ License as published by the Free Software Foundation; either
+ version 2.1 of the License, or (at your option) any later version.
+
+ This library is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Lesser General Public License for more details.
+
+ You should have received a copy of the GNU Lesser General Public
+ License along with this library; if not, write to the Free Software
+ Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
+ */
+#include "pygpgme.h"
+#include <structmember.h>
+
+static void
+pygpgme_import_dealloc(PyGpgmeImportResult *self)
+{
+ Py_XDECREF(self->considered);
+ Py_XDECREF(self->no_user_id);
+ Py_XDECREF(self->imported);
+ Py_XDECREF(self->imported_rsa);
+ Py_XDECREF(self->unchanged);
+ Py_XDECREF(self->new_user_ids);
+ Py_XDECREF(self->new_sub_keys);
+ Py_XDECREF(self->new_signatures);
+ Py_XDECREF(self->new_revocations);
+ Py_XDECREF(self->secret_read);
+ Py_XDECREF(self->secret_imported);
+ Py_XDECREF(self->secret_unchanged);
+ Py_XDECREF(self->skipped_new_keys);
+ Py_XDECREF(self->not_imported);
+ Py_XDECREF(self->imports);
+ PyObject_Del(self);
+}
+
+static PyMemberDef pygpgme_import_members[] = {
+ { "considered", T_OBJECT, offsetof(PyGpgmeImportResult, considered), RO},
+ { "no_user_id", T_OBJECT, offsetof(PyGpgmeImportResult, no_user_id), RO},
+ { "imported", T_OBJECT, offsetof(PyGpgmeImportResult, imported), RO},
+ { "imported_rsa", T_OBJECT, offsetof(PyGpgmeImportResult, imported_rsa), RO},
+ { "unchanged", T_OBJECT, offsetof(PyGpgmeImportResult, unchanged), RO},
+ { "new_user_ids", T_OBJECT, offsetof(PyGpgmeImportResult, new_user_ids), RO},
+ { "new_sub_keys", T_OBJECT, offsetof(PyGpgmeImportResult, new_sub_keys), RO},
+ { "new_signatures", T_OBJECT, offsetof(PyGpgmeImportResult, new_signatures), RO},
+ { "new_revocations", T_OBJECT,
+ offsetof(PyGpgmeImportResult, new_revocations), RO},
+ { "secret_read", T_OBJECT,
+ offsetof(PyGpgmeImportResult, secret_read), RO},
+ { "secret_imported", T_OBJECT,
+ offsetof(PyGpgmeImportResult, secret_imported), RO},
+ { "secret_unchanged", T_OBJECT,
+ offsetof(PyGpgmeImportResult, secret_unchanged), RO},
+ { "skipped_new_keys", T_OBJECT,
+ offsetof(PyGpgmeImportResult, skipped_new_keys), RO},
+ { "not_imported", T_OBJECT,
+ offsetof(PyGpgmeImportResult, not_imported), RO},
+ { "imports", T_OBJECT, offsetof(PyGpgmeImportResult, imports), RO},
+ { NULL, 0, 0, 0}
+};
+
+PyTypeObject PyGpgmeImportResult_Type = {
+ PyObject_HEAD_INIT(NULL)
+ 0,
+ "gpgme.Import",
+ sizeof(PyGpgmeImportResult),
+ .tp_flags = Py_TPFLAGS_DEFAULT,
+ .tp_init = pygpgme_no_constructor,
+ .tp_dealloc = (destructor)pygpgme_import_dealloc,
+ .tp_members = pygpgme_import_members,
+};
+
+PyObject *
+pygpgme_import_result(gpgme_ctx_t ctx)
+{
+ gpgme_import_result_t result;
+ gpgme_import_status_t status;
+ PyGpgmeImportResult *self;
+
+ result = gpgme_op_import_result(ctx);
+
+ if (result == NULL)
+ Py_RETURN_NONE;
+
+ self = PyObject_New(PyGpgmeImportResult, &PyGpgmeImportResult_Type);
+ if (!self)
+ return NULL;
+
+#define ADD_INT(name) \
+ self->name = PyInt_FromLong(result->name)
+
+ ADD_INT(considered);
+ ADD_INT(no_user_id);
+ ADD_INT(imported);
+ ADD_INT(imported_rsa);
+ ADD_INT(unchanged);
+ ADD_INT(new_user_ids);
+ ADD_INT(new_sub_keys);
+ ADD_INT(new_signatures);
+ ADD_INT(new_revocations);
+ ADD_INT(secret_read);
+ ADD_INT(secret_imported);
+ ADD_INT(secret_unchanged);
+ ADD_INT(skipped_new_keys);
+ ADD_INT(not_imported);
+
+ self->imports = PyList_New(0);
+ if (!self->imports)
+ return NULL;
+ for (status = result->imports; status != NULL; status = status->next) {
+ PyObject *item;
+
+ item = Py_BuildValue("(zNi)",
+ status->fpr,
+ pygpgme_error_object(status->result),
+ status->status);
+ if (!item) {
+ Py_DECREF(self);
+ return NULL;
+ }
+ PyList_Append(self->imports, item);
+ Py_DECREF(item);
+ }
+
+ return (PyObject *)self;
+}
--- /dev/null
+/* -*- mode: C; c-basic-offset: 4; indent-tabs-mode: nil -*- */
+/*
+ pygpgme - a Python wrapper for the gpgme library
+ Copyright (C) 2006 James Henstridge
+
+ This library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Lesser General Public
+ License as published by the Free Software Foundation; either
+ version 2.1 of the License, or (at your option) any later version.
+
+ This library is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Lesser General Public License for more details.
+
+ You should have received a copy of the GNU Lesser General Public
+ License along with this library; if not, write to the Free Software
+ Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
+ */
+#include <Python.h>
+#include "pygpgme.h"
+
+static void
+pygpgme_subkey_dealloc(PyGpgmeSubkey *self)
+{
+ self->subkey = NULL;
+ Py_XDECREF(self->parent);
+ self->parent = NULL;
+ PyObject_Del(self);
+}
+
+static PyObject *
+pygpgme_subkey_get_revoked(PyGpgmeSubkey *self)
+{
+ return PyBool_FromLong(self->subkey->revoked);
+}
+
+static PyObject *
+pygpgme_subkey_get_expired(PyGpgmeSubkey *self)
+{
+ return PyBool_FromLong(self->subkey->expired);
+}
+
+static PyObject *
+pygpgme_subkey_get_disabled(PyGpgmeSubkey *self)
+{
+ return PyBool_FromLong(self->subkey->disabled);
+}
+
+static PyObject *
+pygpgme_subkey_get_invalid(PyGpgmeSubkey *self)
+{
+ return PyBool_FromLong(self->subkey->invalid);
+}
+
+static PyObject *
+pygpgme_subkey_get_can_encrypt(PyGpgmeSubkey *self)
+{
+ return PyBool_FromLong(self->subkey->can_encrypt);
+}
+
+static PyObject *
+pygpgme_subkey_get_can_sign(PyGpgmeSubkey *self)
+{
+ return PyBool_FromLong(self->subkey->can_sign);
+}
+
+static PyObject *
+pygpgme_subkey_get_can_certify(PyGpgmeSubkey *self)
+{
+ return PyBool_FromLong(self->subkey->can_certify);
+}
+
+static PyObject *
+pygpgme_subkey_get_secret(PyGpgmeSubkey *self)
+{
+ return PyBool_FromLong(self->subkey->secret);
+}
+
+static PyObject *
+pygpgme_subkey_get_can_authenticate(PyGpgmeSubkey *self)
+{
+ return PyBool_FromLong(self->subkey->can_authenticate);
+}
+
+static PyObject *
+pygpgme_subkey_get_pubkey_algo(PyGpgmeSubkey *self)
+{
+ return PyInt_FromLong(self->subkey->pubkey_algo);
+}
+
+static PyObject *
+pygpgme_subkey_get_length(PyGpgmeSubkey *self)
+{
+ return PyInt_FromLong(self->subkey->length);
+}
+
+static PyObject *
+pygpgme_subkey_get_keyid(PyGpgmeSubkey *self)
+{
+ if (self->subkey->keyid)
+ return PyString_FromString(self->subkey->keyid);
+ else
+ Py_RETURN_NONE;
+}
+
+static PyObject *
+pygpgme_subkey_get_fpr(PyGpgmeSubkey *self)
+{
+ if (self->subkey->fpr)
+ return PyString_FromString(self->subkey->fpr);
+ else
+ Py_RETURN_NONE;
+}
+
+static PyObject *
+pygpgme_subkey_get_timestamp(PyGpgmeSubkey *self)
+{
+ return PyInt_FromLong(self->subkey->timestamp);
+}
+
+static PyObject *
+pygpgme_subkey_get_expires(PyGpgmeSubkey *self)
+{
+ return PyInt_FromLong(self->subkey->expires);
+}
+
+static PyGetSetDef pygpgme_subkey_getsets[] = {
+ { "revoked", (getter)pygpgme_subkey_get_revoked },
+ { "expired", (getter)pygpgme_subkey_get_expired },
+ { "disabled", (getter)pygpgme_subkey_get_disabled },
+ { "invalid", (getter)pygpgme_subkey_get_invalid },
+ { "can_encrypt", (getter)pygpgme_subkey_get_can_encrypt },
+ { "can_sign", (getter)pygpgme_subkey_get_can_sign },
+ { "can_certify", (getter)pygpgme_subkey_get_can_certify },
+ { "secret", (getter)pygpgme_subkey_get_secret },
+ { "can_authenticate", (getter)pygpgme_subkey_get_can_authenticate },
+ { "pubkey_algo", (getter)pygpgme_subkey_get_pubkey_algo },
+ { "length", (getter)pygpgme_subkey_get_length },
+ { "keyid", (getter)pygpgme_subkey_get_keyid },
+ { "fpr", (getter)pygpgme_subkey_get_fpr },
+ { "timestamp", (getter)pygpgme_subkey_get_timestamp },
+ { "expires", (getter)pygpgme_subkey_get_expires },
+ { NULL, (getter)0, (setter)0 }
+};
+
+PyTypeObject PyGpgmeSubkey_Type = {
+ PyObject_HEAD_INIT(NULL)
+ 0,
+ "gpgme.Subkey",
+ sizeof(PyGpgmeSubkey),
+ .tp_flags = Py_TPFLAGS_DEFAULT,
+ .tp_init = pygpgme_no_constructor,
+ .tp_dealloc = (destructor)pygpgme_subkey_dealloc,
+ .tp_getset = pygpgme_subkey_getsets,
+};
+
+static void
+pygpgme_key_sig_dealloc(PyGpgmeKeySig *self)
+{
+ self->key_sig = NULL;
+ Py_XDECREF(self->parent);
+ self->parent = NULL;
+ PyObject_Del(self);
+}
+
+static PyObject *
+pygpgme_key_sig_get_revoked(PyGpgmeKeySig *self)
+{
+ return PyBool_FromLong(self->key_sig->revoked);
+}
+
+static PyObject *
+pygpgme_key_sig_get_expired(PyGpgmeKeySig *self)
+{
+ return PyBool_FromLong(self->key_sig->expired);
+}
+
+static PyObject *
+pygpgme_key_sig_get_invalid(PyGpgmeKeySig *self)
+{
+ return PyBool_FromLong(self->key_sig->invalid);
+}
+
+static PyObject *
+pygpgme_key_sig_get_exportable(PyGpgmeKeySig *self)
+{
+ return PyBool_FromLong(self->key_sig->exportable);
+}
+
+static PyObject *
+pygpgme_key_sig_get_pubkey_algo(PyGpgmeKeySig *self)
+{
+ return PyInt_FromLong(self->key_sig->pubkey_algo);
+}
+
+static PyObject *
+pygpgme_key_sig_get_keyid(PyGpgmeKeySig *self)
+{
+ if (self->key_sig->keyid)
+ return PyString_FromString(self->key_sig->keyid);
+ else
+ Py_RETURN_NONE;
+}
+
+static PyObject *
+pygpgme_key_sig_get_timestamp(PyGpgmeKeySig *self)
+{
+ return PyInt_FromLong(self->key_sig->timestamp);
+}
+
+static PyObject *
+pygpgme_key_sig_get_expires(PyGpgmeKeySig *self)
+{
+ return PyInt_FromLong(self->key_sig->expires);
+}
+
+static PyObject *
+pygpgme_key_sig_get_status(PyGpgmeKeySig *self)
+{
+ return pygpgme_error_object(self->key_sig->status);
+}
+
+static PyObject *
+pygpgme_key_sig_get_uid(PyGpgmeKeySig *self)
+{
+ if (self->key_sig->uid)
+ return PyString_FromString(self->key_sig->uid);
+ else
+ Py_RETURN_NONE;
+}
+
+static PyObject *
+pygpgme_key_sig_get_name(PyGpgmeKeySig *self)
+{
+ if (self->key_sig->name)
+ return PyString_FromString(self->key_sig->name);
+ else
+ Py_RETURN_NONE;
+}
+
+static PyObject *
+pygpgme_key_sig_get_email(PyGpgmeKeySig *self)
+{
+ if (self->key_sig->email)
+ return PyString_FromString(self->key_sig->email);
+ else
+ Py_RETURN_NONE;
+}
+
+static PyObject *
+pygpgme_key_sig_get_comment(PyGpgmeKeySig *self)
+{
+ if (self->key_sig->comment)
+ return PyString_FromString(self->key_sig->comment);
+ else
+ Py_RETURN_NONE;
+}
+
+static PyObject *
+pygpgme_key_sig_get_sig_class(PyGpgmeKeySig *self)
+{
+ return PyInt_FromLong(self->key_sig->sig_class);
+}
+
+static PyGetSetDef pygpgme_key_sig_getsets[] = {
+ { "revoked", (getter)pygpgme_key_sig_get_revoked },
+ { "expired", (getter)pygpgme_key_sig_get_expired },
+ { "invalid", (getter)pygpgme_key_sig_get_invalid },
+ { "exportable", (getter)pygpgme_key_sig_get_exportable },
+ { "pubkey_algo", (getter)pygpgme_key_sig_get_pubkey_algo },
+ { "keyid", (getter)pygpgme_key_sig_get_keyid },
+ { "timestamp", (getter)pygpgme_key_sig_get_timestamp },
+ { "expires", (getter)pygpgme_key_sig_get_expires },
+ { "status", (getter)pygpgme_key_sig_get_status },
+ { "uid", (getter)pygpgme_key_sig_get_uid },
+ { "name", (getter)pygpgme_key_sig_get_name },
+ { "email", (getter)pygpgme_key_sig_get_email },
+ { "comment", (getter)pygpgme_key_sig_get_comment },
+ { "sig_class", (getter)pygpgme_key_sig_get_sig_class },
+ { NULL, (getter)0, (setter)0 }
+};
+
+PyTypeObject PyGpgmeKeySig_Type = {
+ PyObject_HEAD_INIT(NULL)
+ 0,
+ "gpgme.KeySig",
+ sizeof(PyGpgmeKeySig),
+ .tp_flags = Py_TPFLAGS_DEFAULT,
+ .tp_init = pygpgme_no_constructor,
+ .tp_dealloc = (destructor)pygpgme_key_sig_dealloc,
+ .tp_getset = pygpgme_key_sig_getsets,
+};
+
+static void
+pygpgme_user_id_dealloc(PyGpgmeUserId *self)
+{
+ self->user_id = NULL;
+ Py_XDECREF(self->parent);
+ self->parent = NULL;
+ PyObject_Del(self);
+}
+
+static PyObject *
+pygpgme_user_id_get_revoked(PyGpgmeUserId *self)
+{
+ return PyBool_FromLong(self->user_id->revoked);
+}
+
+static PyObject *
+pygpgme_user_id_get_invalid(PyGpgmeUserId *self)
+{
+ return PyBool_FromLong(self->user_id->invalid);
+}
+
+static PyObject *
+pygpgme_user_id_get_validity(PyGpgmeUserId *self)
+{
+ return PyInt_FromLong(self->user_id->validity);
+}
+
+static PyObject *
+pygpgme_user_id_get_uid(PyGpgmeUserId *self)
+{
+ if (self->user_id->uid)
+ return PyString_FromString(self->user_id->uid);
+ else
+ Py_RETURN_NONE;
+}
+
+static PyObject *
+pygpgme_user_id_get_name(PyGpgmeUserId *self)
+{
+ if (self->user_id->name)
+ return PyString_FromString(self->user_id->name);
+ else
+ Py_RETURN_NONE;
+}
+
+static PyObject *
+pygpgme_user_id_get_email(PyGpgmeUserId *self)
+{
+ if (self->user_id->email)
+ return PyString_FromString(self->user_id->email);
+ else
+ Py_RETURN_NONE;
+}
+
+static PyObject *
+pygpgme_user_id_get_comment(PyGpgmeUserId *self)
+{
+ if (self->user_id->comment)
+ return PyString_FromString(self->user_id->comment);
+ else
+ Py_RETURN_NONE;
+}
+
+static PyObject *
+pygpgme_user_id_get_signatures(PyGpgmeUserId *self)
+{
+ PyObject *ret;
+ gpgme_key_sig_t sig;
+
+ ret = PyList_New(0);
+ if (ret == NULL)
+ return NULL;
+ for (sig = self->user_id->signatures; sig != NULL; sig = sig->next) {
+ PyGpgmeKeySig *item;
+
+ item = PyObject_New(PyGpgmeKeySig, &PyGpgmeKeySig_Type);
+ if (item == NULL) {
+ Py_DECREF(ret);
+ return NULL;
+ }
+ item->key_sig = sig;
+ Py_INCREF(self);
+ item->parent = (PyObject *)self;
+ PyList_Append(ret, (PyObject *)item);
+ Py_DECREF(item);
+ }
+ return ret;
+}
+
+static PyGetSetDef pygpgme_user_id_getsets[] = {
+ { "revoked", (getter)pygpgme_user_id_get_revoked },
+ { "invalid", (getter)pygpgme_user_id_get_invalid },
+ { "validity", (getter)pygpgme_user_id_get_validity },
+ { "uid", (getter)pygpgme_user_id_get_uid },
+ { "name", (getter)pygpgme_user_id_get_name },
+ { "email", (getter)pygpgme_user_id_get_email },
+ { "comment", (getter)pygpgme_user_id_get_comment },
+ { "signatures", (getter)pygpgme_user_id_get_signatures },
+ { NULL, (getter)0, (setter)0 }
+};
+
+PyTypeObject PyGpgmeUserId_Type = {
+ PyObject_HEAD_INIT(NULL)
+ 0,
+ "gpgme.UserId",
+ sizeof(PyGpgmeUserId),
+ .tp_flags = Py_TPFLAGS_DEFAULT,
+ .tp_init = pygpgme_no_constructor,
+ .tp_dealloc = (destructor)pygpgme_user_id_dealloc,
+ .tp_getset = pygpgme_user_id_getsets,
+};
+
+static void
+pygpgme_key_dealloc(PyGpgmeKey *self)
+{
+ gpgme_key_unref(self->key);
+ self->key = NULL;
+ PyObject_Del(self);
+}
+
+static PyObject *
+pygpgme_key_get_revoked(PyGpgmeKey *self)
+{
+ return PyBool_FromLong(self->key->revoked);
+}
+
+static PyObject *
+pygpgme_key_get_expired(PyGpgmeKey *self)
+{
+ return PyBool_FromLong(self->key->expired);
+}
+
+static PyObject *
+pygpgme_key_get_disabled(PyGpgmeKey *self)
+{
+ return PyBool_FromLong(self->key->disabled);
+}
+
+static PyObject *
+pygpgme_key_get_invalid(PyGpgmeKey *self)
+{
+ return PyBool_FromLong(self->key->invalid);
+}
+
+static PyObject *
+pygpgme_key_get_can_encrypt(PyGpgmeKey *self)
+{
+ return PyBool_FromLong(self->key->can_encrypt);
+}
+
+static PyObject *
+pygpgme_key_get_can_sign(PyGpgmeKey *self)
+{
+ return PyBool_FromLong(self->key->can_sign);
+}
+
+static PyObject *
+pygpgme_key_get_can_certify(PyGpgmeKey *self)
+{
+ return PyBool_FromLong(self->key->can_certify);
+}
+
+static PyObject *
+pygpgme_key_get_secret(PyGpgmeKey *self)
+{
+ return PyBool_FromLong(self->key->secret);
+}
+
+static PyObject *
+pygpgme_key_get_can_authenticate(PyGpgmeKey *self)
+{
+ return PyBool_FromLong(self->key->can_authenticate);
+}
+
+static PyObject *
+pygpgme_key_get_protocol(PyGpgmeKey *self)
+{
+ return PyInt_FromLong(self->key->protocol);
+}
+
+static PyObject *
+pygpgme_key_get_issuer_serial(PyGpgmeKey *self)
+{
+ if (self->key->issuer_serial)
+ return PyString_FromString(self->key->issuer_serial);
+ else
+ Py_RETURN_NONE;
+}
+
+static PyObject *
+pygpgme_key_get_issuer_name(PyGpgmeKey *self)
+{
+ if (self->key->issuer_name)
+ return PyString_FromString(self->key->issuer_name);
+ else
+ Py_RETURN_NONE;
+}
+
+static PyObject *
+pygpgme_key_get_chain_id(PyGpgmeKey *self)
+{
+ if (self->key->chain_id)
+ return PyString_FromString(self->key->chain_id);
+ else
+ Py_RETURN_NONE;
+}
+
+static PyObject *
+pygpgme_key_get_owner_trust(PyGpgmeKey *self)
+{
+ return PyInt_FromLong(self->key->owner_trust);
+}
+
+static PyObject *
+pygpgme_key_get_subkeys(PyGpgmeKey *self)
+{
+ PyObject *ret;
+ gpgme_subkey_t subkey;
+
+ ret = PyList_New(0);
+ if (ret == NULL)
+ return NULL;
+ for (subkey = self->key->subkeys; subkey != NULL; subkey = subkey->next) {
+ PyGpgmeSubkey *item;
+
+ item = PyObject_New(PyGpgmeSubkey, &PyGpgmeSubkey_Type);
+ if (item == NULL) {
+ Py_DECREF(ret);
+ return NULL;
+ }
+ item->subkey = subkey;
+ Py_INCREF(self);
+ item->parent = (PyObject *)self;
+ PyList_Append(ret, (PyObject *)item);
+ Py_DECREF(item);
+ }
+ return ret;
+}
+
+static PyObject *
+pygpgme_key_get_uids(PyGpgmeKey *self)
+{
+ PyObject *ret;
+ gpgme_user_id_t uid;
+
+ ret = PyList_New(0);
+ if (ret == NULL)
+ return NULL;
+ for (uid = self->key->uids; uid != NULL; uid = uid->next) {
+ PyGpgmeUserId *item;
+
+ item = PyObject_New(PyGpgmeUserId, &PyGpgmeUserId_Type);
+ if (item == NULL) {
+ Py_DECREF(ret);
+ return NULL;
+ }
+ item->user_id = uid;
+ Py_INCREF(self);
+ item->parent = (PyObject *)self;
+ PyList_Append(ret, (PyObject *)item);
+ Py_DECREF(item);
+ }
+ return ret;
+}
+
+static PyObject *
+pygpgme_key_get_keylist_mode(PyGpgmeKey *self)
+{
+ return PyInt_FromLong(self->key->keylist_mode);
+}
+
+static PyGetSetDef pygpgme_key_getsets[] = {
+ { "revoked", (getter)pygpgme_key_get_revoked },
+ { "expired", (getter)pygpgme_key_get_expired },
+ { "disabled", (getter)pygpgme_key_get_disabled },
+ { "invalid", (getter)pygpgme_key_get_invalid },
+ { "can_encrypt", (getter)pygpgme_key_get_can_encrypt },
+ { "can_sign", (getter)pygpgme_key_get_can_sign },
+ { "can_certify", (getter)pygpgme_key_get_can_certify },
+ { "secret", (getter)pygpgme_key_get_secret },
+ { "can_authenticate", (getter)pygpgme_key_get_can_authenticate },
+ { "protocol", (getter)pygpgme_key_get_protocol },
+ { "issuer_serial", (getter)pygpgme_key_get_issuer_serial },
+ { "issuer_name", (getter)pygpgme_key_get_issuer_name },
+ { "chain_id", (getter)pygpgme_key_get_chain_id },
+ { "owner_trust", (getter)pygpgme_key_get_owner_trust },
+ { "subkeys", (getter)pygpgme_key_get_subkeys },
+ { "uids", (getter)pygpgme_key_get_uids },
+ { "keylist_mode", (getter)pygpgme_key_get_keylist_mode },
+ { NULL, (getter)0, (setter)0 }
+};
+
+PyTypeObject PyGpgmeKey_Type = {
+ PyObject_HEAD_INIT(NULL)
+ 0,
+ "gpgme.Key",
+ sizeof(PyGpgmeKey),
+ .tp_flags = Py_TPFLAGS_DEFAULT,
+ .tp_init = pygpgme_no_constructor,
+ .tp_dealloc = (destructor)pygpgme_key_dealloc,
+ .tp_getset = pygpgme_key_getsets,
+};
+
+PyObject *
+pygpgme_key_new(gpgme_key_t key)
+{
+ PyGpgmeKey *self;
+
+ self = PyObject_New(PyGpgmeKey, &PyGpgmeKey_Type);
+ if (self == NULL)
+ return NULL;
+
+ gpgme_key_ref(key);
+ self->key = key;
+ return (PyObject *)self;
+}
--- /dev/null
+/* -*- mode: C; c-basic-offset: 4; indent-tabs-mode: nil -*- */
+/*
+ pygpgme - a Python wrapper for the gpgme library
+ Copyright (C) 2006 James Henstridge
+
+ This library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Lesser General Public
+ License as published by the Free Software Foundation; either
+ version 2.1 of the License, or (at your option) any later version.
+
+ This library is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Lesser General Public License for more details.
+
+ You should have received a copy of the GNU Lesser General Public
+ License along with this library; if not, write to the Free Software
+ Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
+ */
+#include "pygpgme.h"
+
+static void
+pygpgme_keyiter_dealloc(PyGpgmeKeyIter *self)
+{
+ if (self->ctx) {
+ gpgme_error_t err = gpgme_op_keylist_end(self->ctx->ctx);
+ PyObject *exc = pygpgme_error_object(err);
+
+ if (exc != NULL && exc != Py_None) {
+ PyErr_WriteUnraisable(exc);
+ }
+ Py_XDECREF(exc);
+ Py_DECREF(self->ctx);
+ self->ctx = NULL;
+ }
+ PyObject_Del(self);
+}
+
+static PyObject *
+pygpgme_keyiter_iter(PyGpgmeKeyIter *self)
+{
+ Py_INCREF(self);
+ return (PyObject *)self;
+}
+
+static PyObject *
+pygpgme_keyiter_next(PyGpgmeKeyIter *self)
+{
+ gpgme_key_t key = NULL;
+ gpgme_error_t err;
+ PyObject *ret;
+
+ Py_BEGIN_ALLOW_THREADS;
+ err = gpgme_op_keylist_next(self->ctx->ctx, &key);
+ Py_END_ALLOW_THREADS;
+
+ /* end iteration */
+ if (gpgme_err_source(err) == GPG_ERR_SOURCE_GPGME &&
+ gpgme_err_code(err) == GPG_ERR_EOF) {
+ PyErr_SetNone(PyExc_StopIteration);
+ return NULL;
+ }
+
+ if (pygpgme_check_error(err))
+ return NULL;
+
+ if (key == NULL)
+ Py_RETURN_NONE;
+
+ ret = pygpgme_key_new(key);
+ gpgme_key_unref(key);
+ return ret;
+}
+
+PyTypeObject PyGpgmeKeyIter_Type = {
+ PyObject_HEAD_INIT(NULL)
+ 0,
+ "gpgme.KeyIter",
+ sizeof(PyGpgmeKeyIter),
+ .tp_flags = Py_TPFLAGS_DEFAULT,
+ .tp_init = pygpgme_no_constructor,
+ .tp_dealloc = (destructor)pygpgme_keyiter_dealloc,
+ .tp_iter = (getiterfunc)pygpgme_keyiter_iter,
+ .tp_iternext = (iternextfunc)pygpgme_keyiter_next,
+};
--- /dev/null
+/* -*- mode: C; c-basic-offset: 4; indent-tabs-mode: nil -*- */
+/*
+ pygpgme - a Python wrapper for the gpgme library
+ Copyright (C) 2006 James Henstridge
+
+ This library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Lesser General Public
+ License as published by the Free Software Foundation; either
+ version 2.1 of the License, or (at your option) any later version.
+
+ This library is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Lesser General Public License for more details.
+
+ You should have received a copy of the GNU Lesser General Public
+ License along with this library; if not, write to the Free Software
+ Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
+ */
+#include "pygpgme.h"
+#include <structmember.h>
+
+static void
+pygpgme_newsig_dealloc(PyGpgmeNewSignature *self)
+{
+ Py_XDECREF(self->type);
+ Py_XDECREF(self->pubkey_algo);
+ Py_XDECREF(self->hash_algo);
+ Py_XDECREF(self->timestamp);
+ Py_XDECREF(self->fpr);
+ Py_XDECREF(self->sig_class);
+ PyObject_Del(self);
+}
+
+static PyMemberDef pygpgme_newsig_members[] = {
+ { "type", T_OBJECT, offsetof(PyGpgmeNewSignature, type), RO},
+ { "pubkey_algo", T_OBJECT, offsetof(PyGpgmeNewSignature, pubkey_algo), RO},
+ { "hash_algo", T_OBJECT, offsetof(PyGpgmeNewSignature, hash_algo), RO},
+ { "timestamp", T_OBJECT, offsetof(PyGpgmeNewSignature, timestamp), RO},
+ { "fpr", T_OBJECT, offsetof(PyGpgmeNewSignature, fpr), RO},
+ { "sig_class", T_OBJECT, offsetof(PyGpgmeNewSignature, sig_class), RO},
+ { NULL, 0, 0, 0}
+};
+
+PyTypeObject PyGpgmeNewSignature_Type = {
+ PyObject_HEAD_INIT(NULL)
+ 0,
+ "gpgme.NewSignature",
+ sizeof(PyGpgmeNewSignature),
+ .tp_flags = Py_TPFLAGS_DEFAULT,
+ .tp_init = pygpgme_no_constructor,
+ .tp_dealloc = (destructor)pygpgme_newsig_dealloc,
+ .tp_members = pygpgme_newsig_members,
+};
+
+PyObject *
+pygpgme_newsiglist_new(gpgme_new_signature_t siglist)
+{
+ PyObject *list;
+ gpgme_new_signature_t sig;
+
+ list = PyList_New(0);
+ for (sig = siglist; sig != NULL; sig = sig->next) {
+ PyGpgmeNewSignature *item = PyObject_New(PyGpgmeNewSignature,
+ &PyGpgmeNewSignature_Type);
+ if (item == NULL) {
+ Py_DECREF(list);
+ return NULL;
+ }
+ item->type = PyInt_FromLong(sig->type);
+ item->pubkey_algo = PyInt_FromLong(sig->pubkey_algo);
+ item->hash_algo = PyInt_FromLong(sig->hash_algo);
+ item->timestamp = PyInt_FromLong(sig->timestamp);
+ if (sig->fpr) {
+ item->fpr = PyString_FromString(sig->fpr);
+ } else {
+ Py_INCREF(Py_None);
+ item->fpr = Py_None;
+ }
+ item->sig_class = PyInt_FromLong(sig->sig_class);
+ if (PyErr_Occurred()) {
+ Py_DECREF(item);
+ Py_DECREF(list);
+ return NULL;
+ }
+ PyList_Append(list, (PyObject *)item);
+ Py_DECREF(item);
+ }
+ return list;
+}
+
+static void
+pygpgme_sig_dealloc(PyGpgmeSignature *self)
+{
+ Py_XDECREF(self->summary);
+ Py_XDECREF(self->fpr);
+ Py_XDECREF(self->status);
+ Py_XDECREF(self->notations);
+ Py_XDECREF(self->timestamp);
+ Py_XDECREF(self->exp_timestamp);
+ Py_XDECREF(self->wrong_key_usage);
+ Py_XDECREF(self->validity);
+ Py_XDECREF(self->validity_reason);
+ PyObject_Del(self);
+}
+
+static PyMemberDef pygpgme_sig_members[] = {
+ { "summary", T_OBJECT, offsetof(PyGpgmeSignature, summary), RO},
+ { "fpr", T_OBJECT, offsetof(PyGpgmeSignature, fpr), RO},
+ { "status", T_OBJECT, offsetof(PyGpgmeSignature, status), RO},
+ { "notations", T_OBJECT, offsetof(PyGpgmeSignature, notations), RO},
+ { "timestamp", T_OBJECT, offsetof(PyGpgmeSignature, timestamp), RO},
+ { "exp_timestamp", T_OBJECT,
+ offsetof(PyGpgmeSignature, exp_timestamp), RO},
+ { "wrong_key_usage", T_OBJECT,
+ offsetof(PyGpgmeSignature, wrong_key_usage), RO},
+ { "validity", T_OBJECT, offsetof(PyGpgmeSignature, validity), RO},
+ { "validity_reason", T_OBJECT,
+ offsetof(PyGpgmeSignature, validity_reason), RO},
+ { NULL, 0, 0, 0}
+};
+
+PyTypeObject PyGpgmeSignature_Type = {
+ PyObject_HEAD_INIT(NULL)
+ 0,
+ "gpgme.Signature",
+ sizeof(PyGpgmeSignature),
+ .tp_flags = Py_TPFLAGS_DEFAULT,
+ .tp_init = pygpgme_no_constructor,
+ .tp_dealloc = (destructor)pygpgme_sig_dealloc,
+ .tp_members = pygpgme_sig_members,
+};
+
+PyObject *
+pygpgme_siglist_new(gpgme_signature_t siglist)
+{
+ PyObject *list;
+ gpgme_signature_t sig;
+ gpgme_sig_notation_t not;
+
+ list = PyList_New(0);
+ for (sig = siglist; sig != NULL; sig = sig->next) {
+ PyGpgmeSignature *item = PyObject_New(PyGpgmeSignature,
+ &PyGpgmeSignature_Type);
+ if (item == NULL) {
+ Py_DECREF(list);
+ return NULL;
+ }
+ item->summary = PyInt_FromLong(sig->summary);
+ if (sig->fpr) {
+ item->fpr = PyString_FromString(sig->fpr);
+ } else {
+ Py_INCREF(Py_None);
+ item->fpr = Py_None;
+ }
+ item->status = pygpgme_error_object(sig->status);
+ item->notations = PyList_New(0);
+ for (not = sig->notations; not != NULL; not = not->next) {
+ PyObject *pynot = Py_BuildValue("(zz)", not->name, not->value);
+
+ if (!pynot)
+ break;
+ PyList_Append(item->notations, pynot);
+ Py_DECREF(pynot);
+ }
+ item->timestamp = PyInt_FromLong(sig->timestamp);
+ item->exp_timestamp = PyInt_FromLong(sig->exp_timestamp);
+ item->wrong_key_usage = PyBool_FromLong(sig->wrong_key_usage);
+ item->validity = PyInt_FromLong(sig->validity);
+ item->validity_reason = pygpgme_error_object(sig->validity_reason);
+ if (PyErr_Occurred()) {
+ Py_DECREF(item);
+ Py_DECREF(list);
+ return NULL;
+ }
+ PyList_Append(list, (PyObject *)item);
+ Py_DECREF(item);
+ }
+ return list;
+}
--- /dev/null
+/* -*- mode: C; c-basic-offset: 4; indent-tabs-mode: nil -*- */
+/*
+ pygpgme - a Python wrapper for the gpgme library
+ Copyright (C) 2006 James Henstridge
+
+ This library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Lesser General Public
+ License as published by the Free Software Foundation; either
+ version 2.1 of the License, or (at your option) any later version.
+
+ This library is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Lesser General Public License for more details.
+
+ You should have received a copy of the GNU Lesser General Public
+ License along with this library; if not, write to the Free Software
+ Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
+ */
+#ifndef PYGPGME_H
+#define PYGPGME_H
+
+#include <Python.h>
+#include <gpgme.h>
+
+#define HIDDEN __attribute__((visibility("hidden")))
+
+typedef struct {
+ PyObject_HEAD
+ gpgme_ctx_t ctx;
+} PyGpgmeContext;
+
+typedef struct {
+ PyObject_HEAD
+ gpgme_key_t key;
+} PyGpgmeKey;
+
+typedef struct {
+ PyObject_HEAD
+ gpgme_subkey_t subkey;
+ PyObject *parent;
+} PyGpgmeSubkey;
+
+typedef struct {
+ PyObject_HEAD
+ gpgme_user_id_t user_id;
+ PyObject *parent;
+} PyGpgmeUserId;
+
+typedef struct {
+ PyObject_HEAD
+ gpgme_key_sig_t key_sig;
+ PyObject *parent;
+} PyGpgmeKeySig;
+
+typedef struct {
+ PyObject_HEAD
+ PyObject *type;
+ PyObject *pubkey_algo;
+ PyObject *hash_algo;
+ PyObject *timestamp;
+ PyObject *fpr;
+ PyObject *sig_class;
+} PyGpgmeNewSignature;
+
+typedef struct {
+ PyObject_HEAD
+ PyObject *summary;
+ PyObject *fpr;
+ PyObject *status;
+ PyObject *notations;
+ PyObject *timestamp;
+ PyObject *exp_timestamp;
+ PyObject *wrong_key_usage;
+ PyObject *validity;
+ PyObject *validity_reason;
+} PyGpgmeSignature;
+
+typedef struct {
+ PyObject_HEAD
+ PyObject *considered;
+ PyObject *no_user_id;
+ PyObject *imported;
+ PyObject *imported_rsa;
+ PyObject *unchanged;
+ PyObject *new_user_ids;
+ PyObject *new_sub_keys;
+ PyObject *new_signatures;
+ PyObject *new_revocations;
+ PyObject *secret_read;
+ PyObject *secret_imported;
+ PyObject *secret_unchanged;
+ PyObject *skipped_new_keys;
+ PyObject *not_imported;
+ PyObject *imports;
+} PyGpgmeImportResult;
+
+typedef struct {
+ PyObject_HEAD
+ PyGpgmeContext *ctx;
+} PyGpgmeKeyIter;
+
+extern HIDDEN PyObject *pygpgme_error;
+extern HIDDEN PyTypeObject PyGpgmeContext_Type;
+extern HIDDEN PyTypeObject PyGpgmeKey_Type;
+extern HIDDEN PyTypeObject PyGpgmeSubkey_Type;
+extern HIDDEN PyTypeObject PyGpgmeUserId_Type;
+extern HIDDEN PyTypeObject PyGpgmeKeySig_Type;
+extern HIDDEN PyTypeObject PyGpgmeNewSignature_Type;
+extern HIDDEN PyTypeObject PyGpgmeSignature_Type;
+extern HIDDEN PyTypeObject PyGpgmeImportResult_Type;
+extern HIDDEN PyTypeObject PyGpgmeKeyIter_Type;
+
+HIDDEN int pygpgme_check_error (gpgme_error_t err);
+HIDDEN PyObject *pygpgme_error_object (gpgme_error_t err);
+HIDDEN gpgme_error_t pygpgme_check_pyerror (void);
+HIDDEN int pygpgme_no_constructor (PyObject *self, PyObject *args,
+ PyObject *kwargs);
+
+HIDDEN int pygpgme_data_new (gpgme_data_t *dh, PyObject *fp);
+HIDDEN PyObject *pygpgme_key_new (gpgme_key_t key);
+HIDDEN PyObject *pygpgme_newsiglist_new (gpgme_new_signature_t siglist);
+HIDDEN PyObject *pygpgme_siglist_new (gpgme_signature_t siglist);
+HIDDEN PyObject *pygpgme_import_result (gpgme_ctx_t ctx);
+
+HIDDEN PyObject *pygpgme_make_constants (PyObject *self, PyObject *args);
+
+#endif
--- /dev/null
+import sys
+import unittest
+
+import gpgme.tests
+
+def test_suite():
+ return gpgme.tests.test_suite()
+
+if __name__ == '__main__':
+ unittest.main(defaultTest='test_suite')