diff options
Diffstat (limited to 'lang/python/helpers.c')
-rw-r--r-- | lang/python/helpers.c | 95 |
1 files changed, 90 insertions, 5 deletions
diff --git a/lang/python/helpers.c b/lang/python/helpers.c index 447a29fb..c3cf3b38 100644 --- a/lang/python/helpers.c +++ b/lang/python/helpers.c @@ -17,6 +17,8 @@ # License along with this library; if not, write to the Free Software # Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ + +#include <assert.h> #include <stdio.h> #include <gpgme.h> #include <stdlib.h> @@ -59,12 +61,84 @@ void pygpgme_clear_generic_cb(PyObject **cb) { Py_DECREF(*cb); } +/* Exception support for callbacks. */ +#define EXCINFO "_callback_excinfo" + +static void pygpgme_stash_callback_exception(PyObject *self) +{ + PyObject *ptype, *pvalue, *ptraceback, *excinfo; + + PyErr_Fetch(&ptype, &pvalue, &ptraceback); + excinfo = PyTuple_New(3); + PyTuple_SetItem(excinfo, 0, ptype); + + if (pvalue) + PyTuple_SetItem(excinfo, 1, pvalue); + else { + Py_INCREF(Py_None); + PyTuple_SetItem(excinfo, 1, Py_None); + } + + if (ptraceback) + PyTuple_SetItem(excinfo, 2, ptraceback); + else { + Py_INCREF(Py_None); + PyTuple_SetItem(excinfo, 2, Py_None); + } + + PyObject_SetAttrString(self, EXCINFO, excinfo); +} + +PyObject *pygpgme_raise_callback_exception(PyObject *self) +{ + PyObject *ptype, *pvalue, *ptraceback, *excinfo; + + if (! PyObject_HasAttrString(self, EXCINFO)) + goto leave; + + excinfo = PyObject_GetAttrString(self, EXCINFO); + if (! PyTuple_Check(excinfo)) + { + Py_DECREF(excinfo); + goto leave; + } + + ptype = PyTuple_GetItem(excinfo, 0); + Py_INCREF(excinfo); + + pvalue = PyTuple_GetItem(excinfo, 1); + if (pvalue == Py_None) + pvalue = NULL; + else + Py_INCREF(pvalue); + + ptraceback = PyTuple_GetItem(excinfo, 2); + if (ptraceback == Py_None) + ptraceback = NULL; + else + Py_INCREF(ptraceback); + + Py_DECREF(excinfo); + PyErr_Restore(ptype, pvalue, ptraceback); + + Py_INCREF(Py_None); + PyObject_SetAttrString(self, EXCINFO, Py_None); + + return NULL; /* Raise exception. */ + + leave: + Py_INCREF(Py_None); + return Py_None; +} +#undef EXCINFO + static gpgme_error_t pyPassphraseCb(void *hook, const char *uid_hint, const char *passphrase_info, int prev_was_bad, int fd) { PyObject *pyhook = (PyObject *) hook; + PyObject *self = NULL; PyObject *func = NULL; PyObject *args = NULL; PyObject *retval = NULL; @@ -73,12 +147,13 @@ static gpgme_error_t pyPassphraseCb(void *hook, pygpgme_exception_init(); - if (PyTuple_Check(pyhook)) { - func = PyTuple_GetItem(pyhook, 0); - dataarg = PyTuple_GetItem(pyhook, 1); + assert (PyTuple_Check(pyhook)); + self = PyTuple_GetItem(pyhook, 0); + func = PyTuple_GetItem(pyhook, 1); + if (PyTuple_Size(pyhook) == 3) { + dataarg = PyTuple_GetItem(pyhook, 2); args = PyTuple_New(4); } else { - func = pyhook; args = PyTuple_New(3); } @@ -90,6 +165,11 @@ static gpgme_error_t pyPassphraseCb(void *hook, else PyTuple_SetItem(args, 0, PyUnicode_DecodeUTF8(uid_hint, strlen (uid_hint), "strict")); + if (PyErr_Occurred()) { + Py_DECREF(args); + err_status = gpg_error(GPG_ERR_GENERAL); + goto leave; + } PyTuple_SetItem(args, 1, PyBytes_FromString(passphrase_info)); PyTuple_SetItem(args, 2, PyBool_FromLong((long)prev_was_bad)); @@ -117,7 +197,8 @@ static gpgme_error_t pyPassphraseCb(void *hook, PyErr_Format(PyExc_TypeError, "expected str or bytes from passphrase callback, got %s", retval->ob_type->tp_name); - return gpg_error(GPG_ERR_GENERAL); + err_status = gpg_error(GPG_ERR_GENERAL); + goto leave; } write(fd, buf, len); @@ -126,6 +207,10 @@ static gpgme_error_t pyPassphraseCb(void *hook, } } + leave: + if (err_status) + pygpgme_stash_callback_exception(self); + return err_status; } |