LCOV - code coverage report
Current view: top level - build/lang/python - helpers.c (source / functions) Hit Total Coverage
Test: coverage.info Lines: 470 593 79.3 %
Date: 2016-12-01 18:45:36 Functions: 21 23 91.3 %

          Line data    Source code
       1             : /*
       2             : # Copyright (C) 2016 g10 Code GmbH
       3             : # Copyright (C) 2004 Igor Belyi <belyi@users.sourceforge.net>
       4             : # Copyright (C) 2002 John Goerzen <jgoerzen@complete.org>
       5             : #
       6             : #    This library is free software; you can redistribute it and/or
       7             : #    modify it under the terms of the GNU Lesser General Public
       8             : #    License as published by the Free Software Foundation; either
       9             : #    version 2.1 of the License, or (at your option) any later version.
      10             : #
      11             : #    This library is distributed in the hope that it will be useful,
      12             : #    but WITHOUT ANY WARRANTY; without even the implied warranty of
      13             : #    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
      14             : #    Lesser General Public License for more details.
      15             : #
      16             : #    You should have received a copy of the GNU Lesser General Public
      17             : #    License along with this library; if not, write to the Free Software
      18             : #    Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307  USA
      19             : */
      20             : 
      21             : #ifdef HAVE_CONFIG_H
      22             : #include "config.h"
      23             : #endif
      24             : 
      25             : #include <assert.h>
      26             : #include <stdio.h>
      27             : #include <gpgme.h>
      28             : #include <stdlib.h>
      29             : #include <string.h>
      30             : #include "Python.h"
      31             : 
      32             : #include "helpers.h"
      33             : #include "private.h"
      34             : 
      35             : /* Flag specifying whether this is an in-tree build.  */
      36             : int gpg_in_tree_build =
      37             : #if IN_TREE_BUILD
      38             :   1
      39             : #else
      40             :   0
      41             : #endif
      42             :   ;
      43             : 
      44             : static PyObject *GPGMEError = NULL;
      45             : 
      46         128 : void _gpg_exception_init(void) {
      47         128 :   if (GPGMEError == NULL) {
      48             :     PyObject *errors;
      49           8 :     PyObject *from_list = PyList_New(0);
      50           8 :     errors = PyImport_ImportModuleLevel("errors", PyEval_GetGlobals(),
      51             :                                         PyEval_GetLocals(), from_list, 1);
      52           8 :     Py_XDECREF(from_list);
      53           8 :     if (errors) {
      54           8 :       GPGMEError=PyDict_GetItemString(PyModule_GetDict(errors), "GPGMEError");
      55           8 :       Py_XINCREF(GPGMEError);
      56             :     }
      57             :   }
      58         128 : }
      59             : 
      60             : static PyObject *
      61           0 : _gpg_raise_exception(gpgme_error_t err)
      62             : {
      63             :   PyObject *e;
      64             : 
      65           0 :   _gpg_exception_init();
      66           0 :   if (GPGMEError == NULL)
      67           0 :     return PyErr_Format(PyExc_RuntimeError, "Got gpgme_error_t %d", err);
      68             : 
      69           0 :   e = PyObject_CallFunction(GPGMEError, "l", (long) err);
      70           0 :   if (e == NULL)
      71             :     return NULL;
      72             : 
      73           0 :   PyErr_SetObject(GPGMEError, e);
      74           0 :   Py_DECREF(e);
      75             : 
      76             :   return NULL;  /* raise */
      77             : }
      78             : 
      79           8 : gpgme_error_t _gpg_exception2code(void) {
      80           8 :   gpgme_error_t err_status = gpg_error(GPG_ERR_GENERAL);
      81           8 :   if (GPGMEError && PyErr_ExceptionMatches(GPGMEError)) {
      82           0 :     PyObject *type = 0, *value = 0, *traceback = 0;
      83           0 :     PyObject *error = 0;
      84           0 :     PyErr_Fetch(&type, &value, &traceback);
      85           0 :     PyErr_NormalizeException(&type, &value, &traceback);
      86           0 :     error = PyObject_GetAttrString(value, "error");
      87           0 :     err_status = PyLong_AsLong(error);
      88           0 :     Py_DECREF(error);
      89           0 :     PyErr_Restore(type, value, traceback);
      90             :   }
      91           8 :   return err_status;
      92             : }
      93             : 
      94             : /* Exception support for callbacks.  */
      95             : #define EXCINFO "_callback_excinfo"
      96             : 
      97          46 : static void _gpg_stash_callback_exception(PyObject *weak_self)
      98             : {
      99             :   PyObject *self, *ptype, *pvalue, *ptraceback, *excinfo;
     100             : 
     101          46 :   PyErr_Fetch(&ptype, &pvalue, &ptraceback);
     102          46 :   excinfo = PyTuple_New(3);
     103          46 :   PyTuple_SetItem(excinfo, 0, ptype);
     104             : 
     105          46 :   if (pvalue)
     106          46 :     PyTuple_SetItem(excinfo, 1, pvalue);
     107             :   else {
     108           0 :     Py_INCREF(Py_None);
     109           0 :     PyTuple_SetItem(excinfo, 1, Py_None);
     110             :   }
     111             : 
     112          46 :   if (ptraceback)
     113          36 :     PyTuple_SetItem(excinfo, 2, ptraceback);
     114             :   else {
     115          10 :     Py_INCREF(Py_None);
     116          10 :     PyTuple_SetItem(excinfo, 2, Py_None);
     117             :   }
     118             : 
     119          46 :   self = PyWeakref_GetObject(weak_self);
     120             :   /* self only has a borrowed reference.  */
     121          46 :   if (self == Py_None) {
     122             :     /* This should not happen, as even if we're called from the data
     123             :        release callback triggered from the wrappers destructor, the
     124             :        object is still alive and hence the weak reference still refers
     125             :        to the object.  However, in case this ever changes, not seeing
     126             :        any exceptions is worse than having a little extra code, so
     127             :        here we go.  */
     128           0 :       fprintf(stderr,
     129             :               "Error occurred in callback, but the wrapper object "
     130             :               "has been deallocated.\n");
     131           0 :       PyErr_Restore(ptype, pvalue, ptraceback);
     132           0 :       PyErr_Print();
     133             :     }
     134             :   else
     135          46 :     PyObject_SetAttrString(self, EXCINFO, excinfo);
     136          46 :   Py_DECREF(excinfo);
     137          46 : }
     138             : 
     139          24 : PyObject *gpg_raise_callback_exception(PyObject *self)
     140             : {
     141          24 :   PyGILState_STATE state = PyGILState_Ensure();
     142             :   PyObject *ptype, *pvalue, *ptraceback, *excinfo;
     143             : 
     144          24 :   if (! PyObject_HasAttrString(self, EXCINFO))
     145             :     goto leave;
     146             : 
     147          24 :   excinfo = PyObject_GetAttrString(self, EXCINFO);
     148          24 :   if (! PyTuple_Check(excinfo))
     149             :     {
     150           0 :       Py_DECREF(excinfo);
     151             :       goto leave;
     152             :     }
     153             : 
     154          24 :   ptype = PyTuple_GetItem(excinfo, 0);
     155          24 :   Py_INCREF(excinfo);
     156             : 
     157          24 :   pvalue = PyTuple_GetItem(excinfo, 1);
     158          24 :   if (pvalue == Py_None)
     159             :     pvalue = NULL;
     160             :   else
     161          24 :     Py_INCREF(pvalue);
     162             : 
     163          24 :   ptraceback = PyTuple_GetItem(excinfo, 2);
     164          24 :   if (ptraceback == Py_None)
     165             :     ptraceback = NULL;
     166             :   else
     167          14 :     Py_INCREF(ptraceback);
     168             : 
     169             :   /* We now have references for the extracted items.  */
     170          24 :   Py_DECREF(excinfo);
     171             : 
     172             :   /* Clear the exception information.  It is important to do this
     173             :      before setting the error, because setting the attribute may
     174             :      execute python code, and the runtime system raises a SystemError
     175             :      if an exception is set but values are returned.  */
     176          24 :   Py_INCREF(Py_None);
     177          24 :   PyObject_SetAttrString(self, EXCINFO, Py_None);
     178             : 
     179             :   /* Restore exception.  */
     180          24 :   PyErr_Restore(ptype, pvalue, ptraceback);
     181          24 :   PyGILState_Release(state);
     182          24 :   return NULL; /* Raise exception.  */
     183             : 
     184             :  leave:
     185           0 :   Py_INCREF(Py_None);
     186           0 :   PyGILState_Release(state);
     187           0 :   return Py_None;
     188             : }
     189             : #undef EXCINFO
     190             : 
     191             : /* Argument conversion.  */
     192             : 
     193             : /* Convert object to a pointer to gpgme type, generic version.  */
     194             : PyObject *
     195         193 : _gpg_obj2gpgme_t(PyObject *input, const char *objtype, int argnum)
     196             : {
     197         193 :   PyObject *pyname = NULL, *pypointer = NULL;
     198         193 :   pyname = PyObject_GetAttrString(input, "_ctype");
     199         193 :   if (pyname && PyUnicode_Check(pyname))
     200             :     {
     201         193 :       PyObject *encoded = PyUnicode_AsUTF8String(pyname);
     202         193 :       if (strcmp(PyBytes_AsString(encoded), objtype) != 0)
     203             :         {
     204           0 :           PyErr_Format(PyExc_TypeError,
     205             :                        "arg %d: Expected value of type %s, but got %s",
     206             :                        argnum, objtype, PyBytes_AsString(encoded));
     207           0 :           Py_DECREF(encoded);
     208           0 :           Py_DECREF(pyname);
     209             :           return NULL;
     210             :         }
     211         193 :       Py_DECREF(encoded);
     212             :     }
     213             :   else
     214             :     return NULL;
     215             : 
     216         193 :   Py_DECREF(pyname);
     217         193 :   pypointer = PyObject_GetAttrString(input, "wrapped");
     218         193 :   if (pypointer == NULL) {
     219           0 :     PyErr_Format(PyExc_TypeError,
     220             :                  "arg %d: Use of uninitialized Python object %s",
     221             :                  argnum, objtype);
     222           0 :     return NULL;
     223             :   }
     224             :   return pypointer;
     225             : }
     226             : 
     227             : /* Convert object to a pointer to gpgme type, version for data
     228             :    objects.  Constructs a wrapper Python on the fly e.g. for file-like
     229             :    objects with a fileno method, returning it in WRAPPER.  This object
     230             :    must be de-referenced when no longer needed.  */
     231             : PyObject *
     232         270 : _gpg_obj2gpgme_data_t(PyObject *input, int argnum, gpgme_data_t *wrapper,
     233             :                        PyObject **bytesio, Py_buffer *view)
     234             : {
     235             :   gpgme_error_t err;
     236             :   PyObject *data;
     237             :   PyObject *fd;
     238             : 
     239             :   /* See if it is a file-like object with file number.  */
     240         270 :   fd = PyObject_CallMethod(input, "fileno", NULL);
     241         270 :   if (fd) {
     242          18 :     err = gpgme_data_new_from_fd(wrapper, (int) PyLong_AsLong(fd));
     243          18 :     Py_DECREF(fd);
     244          18 :     if (err)
     245           0 :       return _gpg_raise_exception (err);
     246             : 
     247          18 :     return _gpg_wrap_gpgme_data_t(*wrapper);
     248             :   }
     249             :   else
     250         252 :     PyErr_Clear();
     251             : 
     252             :   /* No?  Maybe it implements the buffer protocol.  */
     253         252 :   data = PyObject_CallMethod(input, "getbuffer", NULL);
     254         252 :   if (data)
     255             :     {
     256             :       /* Save a reference to input, which seems to be a BytesIO
     257             :          object.  */
     258           2 :       Py_INCREF(input);
     259           2 :       *bytesio = input;
     260             :     }
     261             :   else
     262             :     {
     263         250 :       PyErr_Clear();
     264             : 
     265             :       /* No, but maybe the user supplied a buffer object?  */
     266         250 :       data = input;
     267             :     }
     268             : 
     269             :   /* Do we have a buffer object?  */
     270         252 :   if (PyObject_CheckBuffer(data))
     271             :     {
     272          59 :       if (PyObject_GetBuffer(data, view, PyBUF_SIMPLE) < 0)
     273             :         return NULL;
     274             : 
     275          59 :       if (data != input)
     276           2 :         Py_DECREF(data);
     277             : 
     278             :       assert (view->obj);
     279             :       assert (view->ndim == 1);
     280             :       assert (view->shape == NULL);
     281             :       assert (view->strides == NULL);
     282             :       assert (view->suboffsets == NULL);
     283             : 
     284          59 :       err = gpgme_data_new_from_mem(wrapper, view->buf, (size_t) view->len, 0);
     285          59 :       if (err)
     286           0 :         return _gpg_raise_exception (err);
     287             : 
     288          59 :       return _gpg_wrap_gpgme_data_t(*wrapper);
     289             :     }
     290             : 
     291             :   /* As last resort we assume it is a wrapped data object.  */
     292         193 :   if (PyObject_HasAttrString(data, "_ctype"))
     293         193 :     return _gpg_obj2gpgme_t(data, "gpgme_data_t", argnum);
     294             : 
     295           0 :   return PyErr_Format(PyExc_TypeError,
     296             :                       "arg %d: expected gpg.Data, file, or an object "
     297             :                       "implementing the buffer protocol, got %s",
     298           0 :                       argnum, data->ob_type->tp_name);
     299             : }
     300             : 
     301             : 
     302             : 
     303             : PyObject *
     304         139 : _gpg_wrap_result(PyObject *fragile, const char *classname)
     305             : {
     306             :   static PyObject *results;
     307             :   PyObject *class;
     308             :   PyObject *replacement;
     309             : 
     310         139 :   if (results == NULL)
     311             :     {
     312          28 :       PyObject *from_list = PyList_New(0);
     313          28 :       if (from_list == NULL)
     314             :         return NULL;
     315             : 
     316          28 :       results = PyImport_ImportModuleLevel("results", PyEval_GetGlobals(),
     317             :                                            PyEval_GetLocals(), from_list, 1);
     318          28 :       Py_DECREF(from_list);
     319             : 
     320          28 :       if (results == NULL)
     321             :         return NULL;
     322             :     }
     323             : 
     324         139 :   class = PyMapping_GetItemString(PyModule_GetDict(results), classname);
     325         139 :   if (class == NULL)
     326             :     return NULL;
     327             : 
     328         139 :   replacement = PyObject_CallFunctionObjArgs(class, fragile, NULL);
     329         139 :   Py_DECREF(class);
     330         139 :   return replacement;
     331             : }
     332             : 
     333             : 
     334             : 
     335             : /* Callback support.  */
     336          18 : static gpgme_error_t pyPassphraseCb(void *hook,
     337             :                                     const char *uid_hint,
     338             :                                     const char *passphrase_info,
     339             :                                     int prev_was_bad,
     340             :                                     int fd) {
     341          18 :   PyGILState_STATE state = PyGILState_Ensure();
     342          18 :   PyObject *pyhook = (PyObject *) hook;
     343          18 :   PyObject *self = NULL;
     344          18 :   PyObject *func = NULL;
     345          18 :   PyObject *args = NULL;
     346          18 :   PyObject *retval = NULL;
     347          18 :   PyObject *dataarg = NULL;
     348          18 :   PyObject *encoded = NULL;
     349          18 :   gpgme_error_t err_status = 0;
     350             : 
     351          18 :   _gpg_exception_init();
     352             : 
     353             :   assert (PyTuple_Check(pyhook));
     354             :   assert (PyTuple_Size(pyhook) == 2 || PyTuple_Size(pyhook) == 3);
     355          18 :   self = PyTuple_GetItem(pyhook, 0);
     356          18 :   func = PyTuple_GetItem(pyhook, 1);
     357          18 :   if (PyTuple_Size(pyhook) == 3) {
     358           4 :     dataarg = PyTuple_GetItem(pyhook, 2);
     359           4 :     args = PyTuple_New(4);
     360             :   } else {
     361          14 :     args = PyTuple_New(3);
     362             :   }
     363             : 
     364          18 :   if (uid_hint == NULL)
     365             :     {
     366          18 :       Py_INCREF(Py_None);
     367          18 :       PyTuple_SetItem(args, 0, Py_None);
     368             :     }
     369             :   else
     370           0 :     PyTuple_SetItem(args, 0, PyUnicode_DecodeUTF8(uid_hint, strlen (uid_hint),
     371             :                                                   "strict"));
     372          18 :   if (PyErr_Occurred()) {
     373           0 :     Py_DECREF(args);
     374             :     err_status = gpg_error(GPG_ERR_GENERAL);
     375             :     goto leave;
     376             :   }
     377             : 
     378          18 :   PyTuple_SetItem(args, 1, PyBytes_FromString(passphrase_info));
     379          18 :   PyTuple_SetItem(args, 2, PyBool_FromLong((long)prev_was_bad));
     380          18 :   if (dataarg) {
     381           4 :     Py_INCREF(dataarg);         /* Because GetItem doesn't give a ref but SetItem taketh away */
     382           4 :     PyTuple_SetItem(args, 3, dataarg);
     383             :   }
     384             : 
     385          18 :   retval = PyObject_CallObject(func, args);
     386          18 :   Py_DECREF(args);
     387          18 :   if (PyErr_Occurred()) {
     388           4 :     err_status = _gpg_exception2code();
     389             :   } else {
     390          14 :     if (!retval) {
     391           0 :       if (write(fd, "\n", 1) < 0) {
     392           0 :         err_status = gpgme_error_from_syserror ();
     393           0 :         _gpg_raise_exception (err_status);
     394             :       }
     395             :     } else {
     396             :       char *buf;
     397             :       size_t len;
     398          14 :       if (PyBytes_Check(retval))
     399           6 :         buf = PyBytes_AsString(retval), len = PyBytes_Size(retval);
     400           8 :       else if (PyUnicode_Check(retval))
     401             :         {
     402             :           Py_ssize_t ssize;
     403           6 :           encoded = PyUnicode_AsUTF8String(retval);
     404           6 :           if (encoded == NULL)
     405             :             {
     406             :               err_status = gpg_error(GPG_ERR_GENERAL);
     407           0 :               goto leave;
     408             :             }
     409           6 :           if (PyBytes_AsStringAndSize(encoded, &buf, &ssize) == -1)
     410             :             {
     411             :               err_status = gpg_error(GPG_ERR_GENERAL);
     412             :               goto leave;
     413             :             }
     414             :           assert (! buf || ssize >= 0);
     415           6 :           len = (size_t) ssize;
     416             :         }
     417             :       else
     418             :         {
     419           2 :           PyErr_Format(PyExc_TypeError,
     420             :                        "expected str or bytes from passphrase callback, got %s",
     421             :                        retval->ob_type->tp_name);
     422           2 :           err_status = gpg_error(GPG_ERR_GENERAL);
     423           2 :           goto leave;
     424             :         }
     425             : 
     426          12 :       if (write(fd, buf, len) < 0) {
     427           0 :         err_status = gpgme_error_from_syserror ();
     428           0 :         _gpg_raise_exception (err_status);
     429             :       }
     430          12 :       if (! err_status && write(fd, "\n", 1) < 0) {
     431           0 :         err_status = gpgme_error_from_syserror ();
     432           0 :         _gpg_raise_exception (err_status);
     433             :       }
     434             : 
     435          12 :       Py_DECREF(retval);
     436             :     }
     437             :   }
     438             : 
     439             :  leave:
     440          18 :   if (err_status)
     441           6 :     _gpg_stash_callback_exception(self);
     442             : 
     443          18 :   Py_XDECREF(encoded);
     444          18 :   PyGILState_Release(state);
     445          18 :   return err_status;
     446             : }
     447             : 
     448             : PyObject *
     449         156 : gpg_set_passphrase_cb(PyObject *self, PyObject *cb) {
     450         156 :   PyGILState_STATE state = PyGILState_Ensure();
     451             :   PyObject *wrapped;
     452             :   gpgme_ctx_t ctx;
     453             : 
     454         156 :   wrapped = PyObject_GetAttrString(self, "wrapped");
     455         156 :   if (wrapped == NULL)
     456             :     {
     457             :       assert (PyErr_Occurred ());
     458           0 :       PyGILState_Release(state);
     459           0 :       return NULL;
     460             :     }
     461             : 
     462         156 :   ctx = _gpg_unwrap_gpgme_ctx_t(wrapped);
     463         156 :   Py_DECREF(wrapped);
     464         156 :   if (ctx == NULL)
     465             :     {
     466          33 :       if (cb == Py_None)
     467             :         goto out;
     468             :       else
     469           0 :         return PyErr_Format(PyExc_RuntimeError, "wrapped is NULL");
     470             :     }
     471             : 
     472         123 :   if (cb == Py_None) {
     473          79 :     gpgme_set_passphrase_cb(ctx, NULL, NULL);
     474          79 :     PyObject_SetAttrString(self, "_passphrase_cb", Py_None);
     475          79 :     goto out;
     476             :   }
     477             : 
     478          44 :   if (! PyTuple_Check(cb))
     479           0 :     return PyErr_Format(PyExc_TypeError, "cb must be a tuple");
     480          44 :   if (PyTuple_Size(cb) != 2 && PyTuple_Size(cb) != 3)
     481           0 :     return PyErr_Format(PyExc_TypeError,
     482             :                         "cb must be a tuple of size 2 or 3");
     483             : 
     484          44 :   gpgme_set_passphrase_cb(ctx, (gpgme_passphrase_cb_t) pyPassphraseCb,
     485             :                           (void *) cb);
     486          44 :   PyObject_SetAttrString(self, "_passphrase_cb", cb);
     487             : 
     488             :  out:
     489         156 :   Py_INCREF(Py_None);
     490         156 :   PyGILState_Release(state);
     491         156 :   return Py_None;
     492             : }
     493             : 
     494          44 : static void pyProgressCb(void *hook, const char *what, int type, int current,
     495             :                          int total) {
     496          44 :   PyGILState_STATE state = PyGILState_Ensure();
     497          44 :   PyObject *func = NULL, *dataarg = NULL, *args = NULL, *retval = NULL;
     498          44 :   PyObject *pyhook = (PyObject *) hook;
     499          44 :   PyObject *self = NULL;
     500             : 
     501             :   assert (PyTuple_Check(pyhook));
     502             :   assert (PyTuple_Size(pyhook) == 2 || PyTuple_Size(pyhook) == 3);
     503          44 :   self = PyTuple_GetItem(pyhook, 0);
     504          44 :   func = PyTuple_GetItem(pyhook, 1);
     505          44 :   if (PyTuple_Size(pyhook) == 3) {
     506          20 :     dataarg = PyTuple_GetItem(pyhook, 2);
     507          20 :     args = PyTuple_New(5);
     508             :   } else {
     509          24 :     args = PyTuple_New(4);
     510             :   }
     511             : 
     512          44 :   PyTuple_SetItem(args, 0, PyUnicode_DecodeUTF8(what, strlen (what),
     513             :                                                 "strict"));
     514          44 :   if (PyErr_Occurred()) {
     515           0 :     _gpg_stash_callback_exception(self);
     516           0 :     Py_DECREF(args);
     517           0 :     PyGILState_Release(state);
     518          44 :     return;
     519             :   }
     520          44 :   PyTuple_SetItem(args, 1, PyLong_FromLong((long) type));
     521          44 :   PyTuple_SetItem(args, 2, PyLong_FromLong((long) current));
     522          44 :   PyTuple_SetItem(args, 3, PyLong_FromLong((long) total));
     523          44 :   if (dataarg) {
     524          20 :     Py_INCREF(dataarg);         /* Because GetItem doesn't give a ref but SetItem taketh away */
     525          20 :     PyTuple_SetItem(args, 4, dataarg);
     526             :   }
     527             : 
     528          44 :   retval = PyObject_CallObject(func, args);
     529          44 :   if (PyErr_Occurred())
     530          24 :     _gpg_stash_callback_exception(self);
     531          44 :   Py_DECREF(args);
     532          44 :   Py_XDECREF(retval);
     533          44 :   PyGILState_Release(state);
     534             : }
     535             : 
     536             : PyObject *
     537         116 : gpg_set_progress_cb(PyObject *self, PyObject *cb) {
     538         116 :   PyGILState_STATE state = PyGILState_Ensure();
     539             :   PyObject *wrapped;
     540             :   gpgme_ctx_t ctx;
     541             : 
     542         116 :   wrapped = PyObject_GetAttrString(self, "wrapped");
     543         116 :   if (wrapped == NULL)
     544             :     {
     545             :       assert (PyErr_Occurred ());
     546           0 :       PyGILState_Release(state);
     547           0 :       return NULL;
     548             :     }
     549             : 
     550         116 :   ctx = _gpg_unwrap_gpgme_ctx_t(wrapped);
     551         116 :   Py_DECREF(wrapped);
     552         116 :   if (ctx == NULL)
     553             :     {
     554          33 :       if (cb == Py_None)
     555             :         goto out;
     556             :       else
     557           0 :         return PyErr_Format(PyExc_RuntimeError, "wrapped is NULL");
     558             :     }
     559             : 
     560          83 :   if (cb == Py_None) {
     561          79 :     gpgme_set_progress_cb(ctx, NULL, NULL);
     562          79 :     PyObject_SetAttrString(self, "_progress_cb", Py_None);
     563          79 :     goto out;
     564             :   }
     565             : 
     566           4 :   if (! PyTuple_Check(cb))
     567           0 :     return PyErr_Format(PyExc_TypeError, "cb must be a tuple");
     568           4 :   if (PyTuple_Size(cb) != 2 && PyTuple_Size(cb) != 3)
     569           0 :     return PyErr_Format(PyExc_TypeError,
     570             :                         "cb must be a tuple of size 2 or 3");
     571             : 
     572           4 :   gpgme_set_progress_cb(ctx, (gpgme_progress_cb_t) pyProgressCb, (void *) cb);
     573           4 :   PyObject_SetAttrString(self, "_progress_cb", cb);
     574             : 
     575             :  out:
     576         116 :   Py_INCREF(Py_None);
     577         116 :   PyGILState_Release(state);
     578         116 :   return Py_None;
     579             : }
     580             : 
     581             : /* Status callbacks.  */
     582          12 : static gpgme_error_t pyStatusCb(void *hook, const char *keyword,
     583             :                                 const char *args) {
     584          12 :   PyGILState_STATE state = PyGILState_Ensure();
     585          12 :   gpgme_error_t err = 0;
     586          12 :   PyObject *pyhook = (PyObject *) hook;
     587          12 :   PyObject *self = NULL;
     588          12 :   PyObject *func = NULL;
     589          12 :   PyObject *dataarg = NULL;
     590          12 :   PyObject *pyargs = NULL;
     591          12 :   PyObject *retval = NULL;
     592             : 
     593             :   assert (PyTuple_Check(pyhook));
     594             :   assert (PyTuple_Size(pyhook) == 2 || PyTuple_Size(pyhook) == 3);
     595          12 :   self = PyTuple_GetItem(pyhook, 0);
     596          12 :   func = PyTuple_GetItem(pyhook, 1);
     597          12 :   if (PyTuple_Size(pyhook) == 3) {
     598          10 :     dataarg = PyTuple_GetItem(pyhook, 2);
     599          10 :     pyargs = PyTuple_New(3);
     600             :   } else {
     601           2 :     pyargs = PyTuple_New(2);
     602             :   }
     603             : 
     604          12 :   if (keyword)
     605          12 :     PyTuple_SetItem(pyargs, 0, PyUnicode_DecodeUTF8(keyword, strlen (keyword),
     606             :                                                     "strict"));
     607             :   else
     608             :     {
     609           0 :       Py_INCREF(Py_None);
     610           0 :       PyTuple_SetItem(pyargs, 0, Py_None);
     611             :     }
     612          12 :   PyTuple_SetItem(pyargs, 1, PyUnicode_DecodeUTF8(args, strlen (args),
     613             :                                                 "strict"));
     614          12 :   if (PyErr_Occurred()) {
     615           0 :     err = gpg_error(GPG_ERR_GENERAL);
     616           0 :     Py_DECREF(pyargs);
     617             :     goto leave;
     618             :   }
     619             : 
     620          12 :   if (dataarg) {
     621          10 :     Py_INCREF(dataarg);
     622          10 :     PyTuple_SetItem(pyargs, 2, dataarg);
     623             :   }
     624             : 
     625          12 :   retval = PyObject_CallObject(func, pyargs);
     626          12 :   if (PyErr_Occurred())
     627           2 :     err = _gpg_exception2code();
     628          12 :   Py_DECREF(pyargs);
     629          12 :   Py_XDECREF(retval);
     630             : 
     631             :  leave:
     632          12 :   if (err)
     633           2 :     _gpg_stash_callback_exception(self);
     634          12 :   PyGILState_Release(state);
     635          12 :   return err;
     636             : }
     637             : 
     638             : PyObject *
     639         116 : gpg_set_status_cb(PyObject *self, PyObject *cb) {
     640         116 :   PyGILState_STATE state = PyGILState_Ensure();
     641             :   PyObject *wrapped;
     642             :   gpgme_ctx_t ctx;
     643             : 
     644         116 :   wrapped = PyObject_GetAttrString(self, "wrapped");
     645         116 :   if (wrapped == NULL)
     646             :     {
     647             :       assert (PyErr_Occurred ());
     648           0 :       PyGILState_Release(state);
     649           0 :       return NULL;
     650             :     }
     651             : 
     652         116 :   ctx = _gpg_unwrap_gpgme_ctx_t(wrapped);
     653         116 :   Py_DECREF(wrapped);
     654         116 :   if (ctx == NULL)
     655             :     {
     656          33 :       if (cb == Py_None)
     657             :         goto out;
     658             :       else
     659           0 :         return PyErr_Format(PyExc_RuntimeError, "wrapped is NULL");
     660             :     }
     661             : 
     662          83 :   if (cb == Py_None) {
     663          79 :     gpgme_set_status_cb(ctx, NULL, NULL);
     664          79 :     PyObject_SetAttrString(self, "_status_cb", Py_None);
     665          79 :     goto out;
     666             :   }
     667             : 
     668           4 :   if (! PyTuple_Check(cb))
     669           0 :     return PyErr_Format(PyExc_TypeError, "cb must be a tuple");
     670           4 :   if (PyTuple_Size(cb) != 2 && PyTuple_Size(cb) != 3)
     671           0 :     return PyErr_Format(PyExc_TypeError,
     672             :                         "cb must be a tuple of size 2 or 3");
     673             : 
     674           4 :   gpgme_set_status_cb(ctx, (gpgme_status_cb_t) pyStatusCb, (void *) cb);
     675           4 :   PyObject_SetAttrString(self, "_status_cb", cb);
     676             : 
     677             :  out:
     678         116 :   Py_INCREF(Py_None);
     679         116 :   PyGILState_Release(state);
     680         116 :   return Py_None;
     681             : }
     682             : 
     683             : 
     684             : 
     685             : /* Interact callbacks.  */
     686             : gpgme_error_t
     687         110 : _gpg_interact_cb(void *opaque, const char *keyword,
     688             :                   const char *args, int fd)
     689             : {
     690         110 :   PyGILState_STATE state = PyGILState_Ensure();
     691         110 :   PyObject *func = NULL, *dataarg = NULL, *pyargs = NULL, *retval = NULL;
     692             :   PyObject *py_keyword;
     693         110 :   PyObject *pyopaque = (PyObject *) opaque;
     694         110 :   gpgme_error_t err_status = 0;
     695         110 :   PyObject *self = NULL;
     696             : 
     697         110 :   _gpg_exception_init();
     698             : 
     699             :   assert (PyTuple_Check(pyopaque));
     700             :   assert (PyTuple_Size(pyopaque) == 2 || PyTuple_Size(pyopaque) == 3);
     701         110 :   self = PyTuple_GetItem(pyopaque, 0);
     702         110 :   func = PyTuple_GetItem(pyopaque, 1);
     703         110 :   if (PyTuple_Size(pyopaque) == 3) {
     704          74 :     dataarg = PyTuple_GetItem(pyopaque, 2);
     705          74 :     pyargs = PyTuple_New(3);
     706             :   } else {
     707          36 :     pyargs = PyTuple_New(2);
     708             :   }
     709             : 
     710         110 :   if (keyword)
     711         110 :     py_keyword = PyUnicode_FromString(keyword);
     712             :   else
     713             :     {
     714           0 :       Py_INCREF(Py_None);
     715           0 :       py_keyword = Py_None;
     716             :     }
     717             : 
     718         110 :   PyTuple_SetItem(pyargs, 0, py_keyword);
     719         110 :   PyTuple_SetItem(pyargs, 1, PyUnicode_FromString(args));
     720         110 :   if (dataarg) {
     721          74 :     Py_INCREF(dataarg);         /* Because GetItem doesn't give a ref but SetItem taketh away */
     722          74 :     PyTuple_SetItem(pyargs, 2, dataarg);
     723             :   }
     724             : 
     725         110 :   retval = PyObject_CallObject(func, pyargs);
     726         110 :   Py_DECREF(pyargs);
     727         110 :   if (PyErr_Occurred()) {
     728           2 :     err_status = _gpg_exception2code();
     729             :   } else {
     730         108 :     if (fd>=0 && retval && PyUnicode_Check(retval)) {
     731          38 :       PyObject *encoded = NULL;
     732             :       char *buffer;
     733             :       Py_ssize_t size;
     734             : 
     735          38 :       encoded = PyUnicode_AsUTF8String(retval);
     736          38 :       if (encoded == NULL)
     737             :         {
     738             :           err_status = gpg_error(GPG_ERR_GENERAL);
     739           0 :           goto leave;
     740             :         }
     741          38 :       if (PyBytes_AsStringAndSize(encoded, &buffer, &size) == -1)
     742             :         {
     743           0 :           Py_DECREF(encoded);
     744             :           err_status = gpg_error(GPG_ERR_GENERAL);
     745             :           goto leave;
     746             :         }
     747             : 
     748          38 :       if (write(fd, buffer, size) < 0) {
     749           0 :         err_status = gpgme_error_from_syserror ();
     750           0 :         _gpg_raise_exception (err_status);
     751             :       }
     752          38 :       if (! err_status && write(fd, "\n", 1) < 0) {
     753           0 :         err_status = gpgme_error_from_syserror ();
     754           0 :         _gpg_raise_exception (err_status);
     755             :       }
     756          38 :       Py_DECREF(encoded);
     757             :     }
     758             :   }
     759             :  leave:
     760         110 :   if (err_status)
     761           2 :     _gpg_stash_callback_exception(self);
     762             : 
     763         110 :   Py_XDECREF(retval);
     764         110 :   PyGILState_Release(state);
     765         110 :   return err_status;
     766             : }
     767             : 
     768             : 
     769             : 
     770             : /* Data callbacks.  */
     771             : 
     772             : /* Read up to SIZE bytes into buffer BUFFER from the data object with
     773             :    the handle HOOK.  Return the number of characters read, 0 on EOF
     774             :    and -1 on error.  If an error occurs, errno is set.  */
     775          64 : static ssize_t pyDataReadCb(void *hook, void *buffer, size_t size)
     776             : {
     777          64 :   PyGILState_STATE state = PyGILState_Ensure();
     778             :   ssize_t result;
     779          64 :   PyObject *pyhook = (PyObject *) hook;
     780          64 :   PyObject *self = NULL;
     781          64 :   PyObject *func = NULL;
     782          64 :   PyObject *dataarg = NULL;
     783          64 :   PyObject *pyargs = NULL;
     784          64 :   PyObject *retval = NULL;
     785             : 
     786             :   assert (PyTuple_Check(pyhook));
     787             :   assert (PyTuple_Size(pyhook) == 5 || PyTuple_Size(pyhook) == 6);
     788             : 
     789          64 :   self = PyTuple_GetItem(pyhook, 0);
     790          64 :   func = PyTuple_GetItem(pyhook, 1);
     791          64 :   if (PyTuple_Size(pyhook) == 6) {
     792           6 :     dataarg = PyTuple_GetItem(pyhook, 5);
     793           6 :     pyargs = PyTuple_New(2);
     794             :   } else {
     795          58 :     pyargs = PyTuple_New(1);
     796             :   }
     797             : 
     798          64 :   PyTuple_SetItem(pyargs, 0, PyLong_FromSize_t(size));
     799          64 :   if (dataarg) {
     800           6 :     Py_INCREF(dataarg);
     801           6 :     PyTuple_SetItem(pyargs, 1, dataarg);
     802             :   }
     803             : 
     804          64 :   retval = PyObject_CallObject(func, pyargs);
     805          64 :   Py_DECREF(pyargs);
     806          64 :   if (PyErr_Occurred()) {
     807           2 :     _gpg_stash_callback_exception(self);
     808           2 :     result = -1;
     809           2 :     goto leave;
     810             :   }
     811             : 
     812          62 :   if (! PyBytes_Check(retval)) {
     813           2 :     PyErr_Format(PyExc_TypeError,
     814             :                  "expected bytes from read callback, got %s",
     815             :                  retval->ob_type->tp_name);
     816           2 :     _gpg_stash_callback_exception(self);
     817           2 :     result = -1;
     818           2 :     goto leave;
     819             :   }
     820             : 
     821          60 :   if (PyBytes_Size(retval) > size) {
     822           0 :     PyErr_Format(PyExc_TypeError,
     823             :                  "expected %zu bytes from read callback, got %zu",
     824             :                  size, PyBytes_Size(retval));
     825           0 :     _gpg_stash_callback_exception(self);
     826           0 :     result = -1;
     827           0 :     goto leave;
     828             :   }
     829             : 
     830          60 :   memcpy(buffer, PyBytes_AsString(retval), PyBytes_Size(retval));
     831          60 :   result = PyBytes_Size(retval);
     832             : 
     833             :  leave:
     834          64 :   Py_XDECREF(retval);
     835          64 :   PyGILState_Release(state);
     836          64 :   return result;
     837             : }
     838             : 
     839             : /* Write up to SIZE bytes from buffer BUFFER to the data object with
     840             :    the handle HOOK.  Return the number of characters written, or -1
     841             :    on error.  If an error occurs, errno is set.  */
     842          60 : static ssize_t pyDataWriteCb(void *hook, const void *buffer, size_t size)
     843             : {
     844          60 :   PyGILState_STATE state = PyGILState_Ensure();
     845             :   ssize_t result;
     846          60 :   PyObject *pyhook = (PyObject *) hook;
     847          60 :   PyObject *self = NULL;
     848          60 :   PyObject *func = NULL;
     849          60 :   PyObject *dataarg = NULL;
     850          60 :   PyObject *pyargs = NULL;
     851          60 :   PyObject *retval = NULL;
     852             : 
     853             :   assert (PyTuple_Check(pyhook));
     854             :   assert (PyTuple_Size(pyhook) == 5 || PyTuple_Size(pyhook) == 6);
     855             : 
     856          60 :   self = PyTuple_GetItem(pyhook, 0);
     857          60 :   func = PyTuple_GetItem(pyhook, 2);
     858          60 :   if (PyTuple_Size(pyhook) == 6) {
     859           4 :     dataarg = PyTuple_GetItem(pyhook, 5);
     860           4 :     pyargs = PyTuple_New(2);
     861             :   } else {
     862          56 :     pyargs = PyTuple_New(1);
     863             :   }
     864             : 
     865          60 :   PyTuple_SetItem(pyargs, 0, PyBytes_FromStringAndSize(buffer, size));
     866          60 :   if (dataarg) {
     867           4 :     Py_INCREF(dataarg);
     868           4 :     PyTuple_SetItem(pyargs, 1, dataarg);
     869             :   }
     870             : 
     871          60 :   retval = PyObject_CallObject(func, pyargs);
     872          60 :   Py_DECREF(pyargs);
     873          60 :   if (PyErr_Occurred()) {
     874           2 :     _gpg_stash_callback_exception(self);
     875           2 :     result = -1;
     876           2 :     goto leave;
     877             :   }
     878             : 
     879             : #if PY_MAJOR_VERSION < 3
     880          29 :   if (PyInt_Check(retval))
     881          26 :     result = PyInt_AsSsize_t(retval);
     882             :   else
     883             : #endif
     884          32 :   if (PyLong_Check(retval))
     885          30 :     result = PyLong_AsSsize_t(retval);
     886             :   else {
     887           2 :     PyErr_Format(PyExc_TypeError,
     888             :                  "expected int from write callback, got %s",
     889             :                  retval->ob_type->tp_name);
     890           2 :     _gpg_stash_callback_exception(self);
     891           2 :     result = -1;
     892             :   }
     893             : 
     894             :  leave:
     895          60 :   Py_XDECREF(retval);
     896          60 :   PyGILState_Release(state);
     897          60 :   return result;
     898             : }
     899             : 
     900             : /* Set the current position from where the next read or write starts
     901             :    in the data object with the handle HOOK to OFFSET, relativ to
     902             :    WHENCE.  Returns the new offset in bytes from the beginning of the
     903             :    data object.  */
     904           8 : static off_t pyDataSeekCb(void *hook, off_t offset, int whence)
     905             : {
     906           8 :   PyGILState_STATE state = PyGILState_Ensure();
     907             :   off_t result;
     908           8 :   PyObject *pyhook = (PyObject *) hook;
     909           8 :   PyObject *self = NULL;
     910           8 :   PyObject *func = NULL;
     911           8 :   PyObject *dataarg = NULL;
     912           8 :   PyObject *pyargs = NULL;
     913           8 :   PyObject *retval = NULL;
     914             : 
     915             :   assert (PyTuple_Check(pyhook));
     916             :   assert (PyTuple_Size(pyhook) == 5 || PyTuple_Size(pyhook) == 6);
     917             : 
     918           8 :   self = PyTuple_GetItem(pyhook, 0);
     919           8 :   func = PyTuple_GetItem(pyhook, 3);
     920           8 :   if (PyTuple_Size(pyhook) == 6) {
     921           4 :     dataarg = PyTuple_GetItem(pyhook, 5);
     922           4 :     pyargs = PyTuple_New(3);
     923             :   } else {
     924           4 :     pyargs = PyTuple_New(2);
     925             :   }
     926             : 
     927             : #if defined(_FILE_OFFSET_BITS) && _FILE_OFFSET_BITS == 64
     928           8 :   PyTuple_SetItem(pyargs, 0, PyLong_FromLongLong((long long) offset));
     929             : #else
     930             :   PyTuple_SetItem(pyargs, 0, PyLong_FromLong((long) offset));
     931             : #endif
     932           8 :   PyTuple_SetItem(pyargs, 1, PyLong_FromLong((long) whence));
     933           8 :   if (dataarg) {
     934           4 :     Py_INCREF(dataarg);
     935           4 :     PyTuple_SetItem(pyargs, 2, dataarg);
     936             :   }
     937             : 
     938           8 :   retval = PyObject_CallObject(func, pyargs);
     939           8 :   Py_DECREF(pyargs);
     940           8 :   if (PyErr_Occurred()) {
     941           2 :     _gpg_stash_callback_exception(self);
     942           2 :     result = -1;
     943           2 :     goto leave;
     944             :   }
     945             : 
     946             : #if PY_MAJOR_VERSION < 3
     947           3 :   if (PyInt_Check(retval))
     948           0 :     result = PyInt_AsLong(retval);
     949             :   else
     950             : #endif
     951           6 :   if (PyLong_Check(retval))
     952             : #if defined(_FILE_OFFSET_BITS) && _FILE_OFFSET_BITS == 64
     953           4 :     result = PyLong_AsLongLong(retval);
     954             : #else
     955             :     result = PyLong_AsLong(retval);
     956             : #endif
     957             :   else {
     958           2 :     PyErr_Format(PyExc_TypeError,
     959             :                  "expected int from seek callback, got %s",
     960             :                  retval->ob_type->tp_name);
     961           2 :     _gpg_stash_callback_exception(self);
     962           2 :     result = -1;
     963             :   }
     964             : 
     965             :  leave:
     966           8 :   Py_XDECREF(retval);
     967           8 :   PyGILState_Release(state);
     968           8 :   return result;
     969             : }
     970             : 
     971             : /* Close the data object with the handle HOOK.  */
     972          14 : static void pyDataReleaseCb(void *hook)
     973             : {
     974          14 :   PyGILState_STATE state = PyGILState_Ensure();
     975          14 :   PyObject *pyhook = (PyObject *) hook;
     976          14 :   PyObject *self = NULL;
     977          14 :   PyObject *func = NULL;
     978          14 :   PyObject *dataarg = NULL;
     979          14 :   PyObject *pyargs = NULL;
     980          14 :   PyObject *retval = NULL;
     981             : 
     982             :   assert (PyTuple_Check(pyhook));
     983             :   assert (PyTuple_Size(pyhook) == 5 || PyTuple_Size(pyhook) == 6);
     984             : 
     985          14 :   self = PyTuple_GetItem(pyhook, 0);
     986          14 :   func = PyTuple_GetItem(pyhook, 4);
     987          14 :   if (PyTuple_Size(pyhook) == 6) {
     988           8 :     dataarg = PyTuple_GetItem(pyhook, 5);
     989           8 :     pyargs = PyTuple_New(1);
     990             :   } else {
     991           6 :     pyargs = PyTuple_New(0);
     992             :   }
     993             : 
     994          14 :   if (dataarg) {
     995           8 :     Py_INCREF(dataarg);
     996           8 :     PyTuple_SetItem(pyargs, 0, dataarg);
     997             :   }
     998             : 
     999          14 :   retval = PyObject_CallObject(func, pyargs);
    1000          14 :   Py_XDECREF(retval);
    1001          14 :   Py_DECREF(pyargs);
    1002          14 :   if (PyErr_Occurred())
    1003           0 :     _gpg_stash_callback_exception(self);
    1004          14 :   PyGILState_Release(state);
    1005          14 : }
    1006             : 
    1007             : PyObject *
    1008          20 : gpg_data_new_from_cbs(PyObject *self,
    1009             :                        PyObject *pycbs,
    1010             :                        gpgme_data_t *r_data)
    1011             : {
    1012          20 :   PyGILState_STATE state = PyGILState_Ensure();
    1013             :   static struct gpgme_data_cbs cbs = {
    1014             :     pyDataReadCb,
    1015             :     pyDataWriteCb,
    1016             :     pyDataSeekCb,
    1017             :     pyDataReleaseCb,
    1018             :   };
    1019             :   gpgme_error_t err;
    1020             : 
    1021          20 :   if (! PyTuple_Check(pycbs))
    1022           0 :     return PyErr_Format(PyExc_TypeError, "pycbs must be a tuple");
    1023          20 :   if (PyTuple_Size(pycbs) != 5 && PyTuple_Size(pycbs) != 6)
    1024           0 :     return PyErr_Format(PyExc_TypeError,
    1025             :                         "pycbs must be a tuple of size 5 or 6");
    1026             : 
    1027          20 :   err = gpgme_data_new_from_cbs(r_data, &cbs, (void *) pycbs);
    1028          20 :   if (err)
    1029           0 :     return _gpg_raise_exception(err);
    1030             : 
    1031          20 :   PyObject_SetAttrString(self, "_data_cbs", pycbs);
    1032             : 
    1033          20 :   Py_INCREF(Py_None);
    1034          20 :   PyGILState_Release(state);
    1035          20 :   return Py_None;
    1036             : }
    1037             : 
    1038             : 
    1039             : 
    1040             : /* The assuan callbacks.  */
    1041             : 
    1042             : gpgme_error_t
    1043           4 : _gpg_assuan_data_cb (void *hook, const void *data, size_t datalen)
    1044             : {
    1045           4 :   PyGILState_STATE state = PyGILState_Ensure();
    1046           4 :   gpgme_error_t err = 0;
    1047           4 :   PyObject *pyhook = (PyObject *) hook;
    1048           4 :   PyObject *self = NULL;
    1049           4 :   PyObject *func = NULL;
    1050           4 :   PyObject *py_data = NULL;
    1051           4 :   PyObject *retval = NULL;
    1052             : 
    1053             :   assert (PyTuple_Check(pyhook));
    1054             :   assert (PyTuple_Size(pyhook) == 2);
    1055           4 :   self = PyTuple_GetItem(pyhook, 0);
    1056           4 :   func = PyTuple_GetItem(pyhook, 1);
    1057             :   assert (PyCallable_Check(func));
    1058             : 
    1059           4 :   py_data = PyBytes_FromStringAndSize(data, datalen);
    1060           4 :   if (py_data == NULL)
    1061             :     {
    1062           0 :       err = _gpg_exception2code();
    1063           0 :       goto leave;
    1064             :     }
    1065             : 
    1066           4 :   retval = PyObject_CallFunctionObjArgs(func, py_data, NULL);
    1067           4 :   if (PyErr_Occurred())
    1068           0 :     err = _gpg_exception2code();
    1069           4 :   Py_DECREF(py_data);
    1070           4 :   Py_XDECREF(retval);
    1071             : 
    1072             :  leave:
    1073           4 :   if (err)
    1074           0 :     _gpg_stash_callback_exception(self);
    1075           4 :   PyGILState_Release(state);
    1076           4 :   return err;
    1077             : }
    1078             : 
    1079             : gpgme_error_t
    1080           0 : _gpg_assuan_inquire_cb (void *hook, const char *name, const char *args,
    1081             :                          gpgme_data_t *r_data)
    1082             : {
    1083           0 :   PyGILState_STATE state = PyGILState_Ensure();
    1084           0 :   gpgme_error_t err = 0;
    1085           0 :   PyObject *pyhook = (PyObject *) hook;
    1086           0 :   PyObject *self = NULL;
    1087           0 :   PyObject *func = NULL;
    1088           0 :   PyObject *py_name = NULL;
    1089           0 :   PyObject *py_args = NULL;
    1090           0 :   PyObject *retval = NULL;
    1091             : 
    1092             :   assert (PyTuple_Check(pyhook));
    1093             :   assert (PyTuple_Size(pyhook) == 2);
    1094           0 :   self = PyTuple_GetItem(pyhook, 0);
    1095           0 :   func = PyTuple_GetItem(pyhook, 1);
    1096             :   assert (PyCallable_Check(func));
    1097             : 
    1098           0 :   py_name = PyUnicode_FromString(name);
    1099           0 :   if (py_name == NULL)
    1100             :     {
    1101           0 :       err = _gpg_exception2code();
    1102           0 :       goto leave;
    1103             :     }
    1104             : 
    1105           0 :   py_args = PyUnicode_FromString(args);
    1106           0 :   if (py_args == NULL)
    1107             :     {
    1108           0 :       err = _gpg_exception2code();
    1109           0 :       goto leave;
    1110             :     }
    1111             : 
    1112           0 :   retval = PyObject_CallFunctionObjArgs(func, py_name, py_args, NULL);
    1113           0 :   if (PyErr_Occurred())
    1114           0 :     err = _gpg_exception2code();
    1115           0 :   Py_XDECREF(retval);
    1116             : 
    1117             :   /* FIXME: Returning data is not yet implemented.  */
    1118           0 :   *r_data = NULL;
    1119             : 
    1120             :  leave:
    1121           0 :   Py_XDECREF(py_name);
    1122           0 :   Py_XDECREF(py_args);
    1123           0 :   if (err)
    1124           0 :     _gpg_stash_callback_exception(self);
    1125           0 :   PyGILState_Release(state);
    1126           0 :   return err;
    1127             : }
    1128             : 
    1129             : gpgme_error_t
    1130           2 : _gpg_assuan_status_cb (void *hook, const char *status, const char *args)
    1131             : {
    1132           2 :   PyGILState_STATE state = PyGILState_Ensure();
    1133           2 :   gpgme_error_t err = 0;
    1134           2 :   PyObject *pyhook = (PyObject *) hook;
    1135           2 :   PyObject *self = NULL;
    1136           2 :   PyObject *func = NULL;
    1137           2 :   PyObject *py_status = NULL;
    1138           2 :   PyObject *py_args = NULL;
    1139           2 :   PyObject *retval = NULL;
    1140             : 
    1141             :   assert (PyTuple_Check(pyhook));
    1142             :   assert (PyTuple_Size(pyhook) == 2);
    1143           2 :   self = PyTuple_GetItem(pyhook, 0);
    1144           2 :   func = PyTuple_GetItem(pyhook, 1);
    1145             :   assert (PyCallable_Check(func));
    1146             : 
    1147           2 :   py_status = PyUnicode_FromString(status);
    1148           2 :   if (py_status == NULL)
    1149             :     {
    1150           0 :       err = _gpg_exception2code();
    1151           0 :       goto leave;
    1152             :     }
    1153             : 
    1154           2 :   py_args = PyUnicode_FromString(args);
    1155           2 :   if (py_args == NULL)
    1156             :     {
    1157           0 :       err = _gpg_exception2code();
    1158           0 :       goto leave;
    1159             :     }
    1160             : 
    1161           2 :   retval = PyObject_CallFunctionObjArgs(func, py_status, py_args, NULL);
    1162           2 :   if (PyErr_Occurred())
    1163           0 :     err = _gpg_exception2code();
    1164           2 :   Py_XDECREF(retval);
    1165             : 
    1166             :  leave:
    1167           2 :   Py_XDECREF(py_status);
    1168           2 :   Py_XDECREF(py_args);
    1169           2 :   if (err)
    1170           0 :     _gpg_stash_callback_exception(self);
    1171           2 :   PyGILState_Release(state);
    1172           2 :   return err;
    1173             : }

Generated by: LCOV version 1.11