LCOV - code coverage report
Current view: top level - build/lang/python - helpers.c (source / functions) Hit Total Coverage
Test: coverage.info Lines: 0 592 0.0 %
Date: 2016-12-15 13:18:47 Functions: 0 23 0.0 %

          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           0 : void _gpg_exception_init(void) {
      47           0 :   if (GPGMEError == NULL) {
      48             :     PyObject *errors;
      49           0 :     PyObject *from_list = PyList_New(0);
      50           0 :     errors = PyImport_ImportModuleLevel("errors", PyEval_GetGlobals(),
      51             :                                         PyEval_GetLocals(), from_list, 1);
      52           0 :     Py_XDECREF(from_list);
      53           0 :     if (errors) {
      54           0 :       GPGMEError=PyDict_GetItemString(PyModule_GetDict(errors), "GPGMEError");
      55           0 :       Py_XINCREF(GPGMEError);
      56             :     }
      57             :   }
      58           0 : }
      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           0 : gpgme_error_t _gpg_exception2code(void) {
      80           0 :   gpgme_error_t err_status = gpg_error(GPG_ERR_GENERAL);
      81           0 :   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           0 :   return err_status;
      92             : }
      93             : 
      94             : /* Exception support for callbacks.  */
      95             : #define EXCINFO "_callback_excinfo"
      96             : 
      97           0 : static void _gpg_stash_callback_exception(PyObject *weak_self)
      98             : {
      99             :   PyObject *self, *ptype, *pvalue, *ptraceback, *excinfo;
     100             : 
     101           0 :   PyErr_Fetch(&ptype, &pvalue, &ptraceback);
     102           0 :   excinfo = PyTuple_New(3);
     103           0 :   PyTuple_SetItem(excinfo, 0, ptype);
     104             : 
     105           0 :   if (pvalue)
     106           0 :     PyTuple_SetItem(excinfo, 1, pvalue);
     107             :   else {
     108           0 :     Py_INCREF(Py_None);
     109           0 :     PyTuple_SetItem(excinfo, 1, Py_None);
     110             :   }
     111             : 
     112           0 :   if (ptraceback)
     113           0 :     PyTuple_SetItem(excinfo, 2, ptraceback);
     114             :   else {
     115           0 :     Py_INCREF(Py_None);
     116           0 :     PyTuple_SetItem(excinfo, 2, Py_None);
     117             :   }
     118             : 
     119           0 :   self = PyWeakref_GetObject(weak_self);
     120             :   /* self only has a borrowed reference.  */
     121           0 :   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           0 :     PyObject_SetAttrString(self, EXCINFO, excinfo);
     136           0 :   Py_DECREF(excinfo);
     137           0 : }
     138             : 
     139           0 : PyObject *gpg_raise_callback_exception(PyObject *self)
     140             : {
     141           0 :   PyGILState_STATE state = PyGILState_Ensure();
     142             :   PyObject *ptype, *pvalue, *ptraceback, *excinfo;
     143             : 
     144           0 :   if (! PyObject_HasAttrString(self, EXCINFO))
     145             :     goto leave;
     146             : 
     147           0 :   excinfo = PyObject_GetAttrString(self, EXCINFO);
     148           0 :   if (! PyTuple_Check(excinfo))
     149             :     {
     150           0 :       Py_DECREF(excinfo);
     151             :       goto leave;
     152             :     }
     153             : 
     154           0 :   ptype = PyTuple_GetItem(excinfo, 0);
     155           0 :   Py_INCREF(excinfo);
     156             : 
     157           0 :   pvalue = PyTuple_GetItem(excinfo, 1);
     158           0 :   if (pvalue == Py_None)
     159             :     pvalue = NULL;
     160             :   else
     161           0 :     Py_INCREF(pvalue);
     162             : 
     163           0 :   ptraceback = PyTuple_GetItem(excinfo, 2);
     164           0 :   if (ptraceback == Py_None)
     165             :     ptraceback = NULL;
     166             :   else
     167           0 :     Py_INCREF(ptraceback);
     168             : 
     169             :   /* We now have references for the extracted items.  */
     170           0 :   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           0 :   Py_INCREF(Py_None);
     177           0 :   PyObject_SetAttrString(self, EXCINFO, Py_None);
     178             : 
     179             :   /* Restore exception.  */
     180           0 :   PyErr_Restore(ptype, pvalue, ptraceback);
     181           0 :   PyGILState_Release(state);
     182           0 :   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           0 : _gpg_obj2gpgme_t(PyObject *input, const char *objtype, int argnum)
     196             : {
     197           0 :   PyObject *pyname = NULL, *pypointer = NULL;
     198           0 :   pyname = PyObject_GetAttrString(input, "_ctype");
     199           0 :   if (pyname && PyUnicode_Check(pyname))
     200             :     {
     201           0 :       PyObject *encoded = PyUnicode_AsUTF8String(pyname);
     202           0 :       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           0 :       Py_DECREF(encoded);
     212             :     }
     213             :   else
     214             :     return NULL;
     215             : 
     216           0 :   Py_DECREF(pyname);
     217           0 :   pypointer = PyObject_GetAttrString(input, "wrapped");
     218           0 :   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           0 : _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           0 :   fd = PyObject_CallMethod(input, "fileno", NULL);
     241           0 :   if (fd) {
     242           0 :     err = gpgme_data_new_from_fd(wrapper, (int) PyLong_AsLong(fd));
     243           0 :     Py_DECREF(fd);
     244           0 :     if (err)
     245           0 :       return _gpg_raise_exception (err);
     246             : 
     247           0 :     return _gpg_wrap_gpgme_data_t(*wrapper);
     248             :   }
     249             :   else
     250           0 :     PyErr_Clear();
     251             : 
     252             :   /* No?  Maybe it implements the buffer protocol.  */
     253           0 :   data = PyObject_CallMethod(input, "getbuffer", NULL);
     254           0 :   if (data)
     255             :     {
     256             :       /* Save a reference to input, which seems to be a BytesIO
     257             :          object.  */
     258           0 :       Py_INCREF(input);
     259           0 :       *bytesio = input;
     260             :     }
     261             :   else
     262             :     {
     263           0 :       PyErr_Clear();
     264             : 
     265             :       /* No, but maybe the user supplied a buffer object?  */
     266           0 :       data = input;
     267             :     }
     268             : 
     269             :   /* Do we have a buffer object?  */
     270           0 :   if (PyObject_CheckBuffer(data))
     271             :     {
     272           0 :       if (PyObject_GetBuffer(data, view, PyBUF_SIMPLE) < 0)
     273             :         return NULL;
     274             : 
     275           0 :       if (data != input)
     276           0 :         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           0 :       err = gpgme_data_new_from_mem(wrapper, view->buf, (size_t) view->len, 0);
     285           0 :       if (err)
     286           0 :         return _gpg_raise_exception (err);
     287             : 
     288           0 :       return _gpg_wrap_gpgme_data_t(*wrapper);
     289             :     }
     290             : 
     291             :   /* As last resort we assume it is a wrapped data object.  */
     292           0 :   if (PyObject_HasAttrString(data, "_ctype"))
     293           0 :     return _gpg_obj2gpgme_t(data, "gpgme_data_t", argnum);
     294             : 
     295           0 :   return PyErr_Format(PyExc_TypeError,
     296             :                       "arg %d: expected gpg.Data, file, "
     297             :                       "bytes (not string!), or an object "
     298             :                       "implementing the buffer protocol. Got: %s. "
     299             :                       "If you provided a string, try to encode() it.",
     300           0 :                       argnum, data->ob_type->tp_name);
     301             : }
     302             : 
     303             : 
     304             : 
     305             : PyObject *
     306           0 : _gpg_wrap_result(PyObject *fragile, const char *classname)
     307             : {
     308             :   static PyObject *results;
     309             :   PyObject *class;
     310             :   PyObject *replacement;
     311             : 
     312           0 :   if (results == NULL)
     313             :     {
     314           0 :       PyObject *from_list = PyList_New(0);
     315           0 :       if (from_list == NULL)
     316             :         return NULL;
     317             : 
     318           0 :       results = PyImport_ImportModuleLevel("results", PyEval_GetGlobals(),
     319             :                                            PyEval_GetLocals(), from_list, 1);
     320           0 :       Py_DECREF(from_list);
     321             : 
     322           0 :       if (results == NULL)
     323             :         return NULL;
     324             :     }
     325             : 
     326           0 :   class = PyMapping_GetItemString(PyModule_GetDict(results), classname);
     327           0 :   if (class == NULL)
     328             :     return NULL;
     329             : 
     330           0 :   replacement = PyObject_CallFunctionObjArgs(class, fragile, NULL);
     331           0 :   Py_DECREF(class);
     332             :   return replacement;
     333             : }
     334             : 
     335             : 
     336             : 
     337             : /* Callback support.  */
     338           0 : static gpgme_error_t pyPassphraseCb(void *hook,
     339             :                                     const char *uid_hint,
     340             :                                     const char *passphrase_info,
     341             :                                     int prev_was_bad,
     342             :                                     int fd) {
     343           0 :   PyGILState_STATE state = PyGILState_Ensure();
     344           0 :   PyObject *pyhook = (PyObject *) hook;
     345           0 :   PyObject *self = NULL;
     346           0 :   PyObject *func = NULL;
     347           0 :   PyObject *args = NULL;
     348           0 :   PyObject *retval = NULL;
     349           0 :   PyObject *dataarg = NULL;
     350           0 :   PyObject *encoded = NULL;
     351           0 :   gpgme_error_t err_status = 0;
     352             : 
     353           0 :   _gpg_exception_init();
     354             : 
     355             :   assert (PyTuple_Check(pyhook));
     356             :   assert (PyTuple_Size(pyhook) == 2 || PyTuple_Size(pyhook) == 3);
     357           0 :   self = PyTuple_GetItem(pyhook, 0);
     358           0 :   func = PyTuple_GetItem(pyhook, 1);
     359           0 :   if (PyTuple_Size(pyhook) == 3) {
     360           0 :     dataarg = PyTuple_GetItem(pyhook, 2);
     361           0 :     args = PyTuple_New(4);
     362             :   } else {
     363           0 :     args = PyTuple_New(3);
     364             :   }
     365             : 
     366           0 :   if (uid_hint == NULL)
     367             :     {
     368           0 :       Py_INCREF(Py_None);
     369           0 :       PyTuple_SetItem(args, 0, Py_None);
     370             :     }
     371             :   else
     372           0 :     PyTuple_SetItem(args, 0, PyUnicode_DecodeUTF8(uid_hint, strlen (uid_hint),
     373             :                                                   "strict"));
     374           0 :   if (PyErr_Occurred()) {
     375           0 :     Py_DECREF(args);
     376             :     err_status = gpg_error(GPG_ERR_GENERAL);
     377             :     goto leave;
     378             :   }
     379             : 
     380           0 :   PyTuple_SetItem(args, 1, PyBytes_FromString(passphrase_info));
     381           0 :   PyTuple_SetItem(args, 2, PyBool_FromLong((long)prev_was_bad));
     382           0 :   if (dataarg) {
     383           0 :     Py_INCREF(dataarg);         /* Because GetItem doesn't give a ref but SetItem taketh away */
     384           0 :     PyTuple_SetItem(args, 3, dataarg);
     385             :   }
     386             : 
     387           0 :   retval = PyObject_CallObject(func, args);
     388           0 :   Py_DECREF(args);
     389           0 :   if (PyErr_Occurred()) {
     390           0 :     err_status = _gpg_exception2code();
     391             :   } else {
     392           0 :     if (!retval) {
     393           0 :       if (write(fd, "\n", 1) < 0) {
     394           0 :         err_status = gpgme_error_from_syserror ();
     395           0 :         _gpg_raise_exception (err_status);
     396             :       }
     397             :     } else {
     398             :       char *buf;
     399             :       size_t len;
     400           0 :       if (PyBytes_Check(retval))
     401           0 :         buf = PyBytes_AsString(retval), len = PyBytes_Size(retval);
     402           0 :       else if (PyUnicode_Check(retval))
     403             :         {
     404             :           Py_ssize_t ssize;
     405           0 :           encoded = PyUnicode_AsUTF8String(retval);
     406           0 :           if (encoded == NULL)
     407             :             {
     408             :               err_status = gpg_error(GPG_ERR_GENERAL);
     409           0 :               goto leave;
     410             :             }
     411           0 :           if (PyBytes_AsStringAndSize(encoded, &buf, &ssize) == -1)
     412             :             {
     413             :               err_status = gpg_error(GPG_ERR_GENERAL);
     414             :               goto leave;
     415             :             }
     416             :           assert (! buf || ssize >= 0);
     417           0 :           len = (size_t) ssize;
     418             :         }
     419             :       else
     420             :         {
     421           0 :           PyErr_Format(PyExc_TypeError,
     422             :                        "expected str or bytes from passphrase callback, got %s",
     423             :                        retval->ob_type->tp_name);
     424           0 :           err_status = gpg_error(GPG_ERR_GENERAL);
     425           0 :           goto leave;
     426             :         }
     427             : 
     428           0 :       if (write(fd, buf, len) < 0) {
     429           0 :         err_status = gpgme_error_from_syserror ();
     430           0 :         _gpg_raise_exception (err_status);
     431             :       }
     432           0 :       if (! err_status && write(fd, "\n", 1) < 0) {
     433           0 :         err_status = gpgme_error_from_syserror ();
     434           0 :         _gpg_raise_exception (err_status);
     435             :       }
     436             : 
     437           0 :       Py_DECREF(retval);
     438             :     }
     439             :   }
     440             : 
     441             :  leave:
     442           0 :   if (err_status)
     443           0 :     _gpg_stash_callback_exception(self);
     444             : 
     445           0 :   Py_XDECREF(encoded);
     446           0 :   PyGILState_Release(state);
     447           0 :   return err_status;
     448             : }
     449             : 
     450             : PyObject *
     451           0 : gpg_set_passphrase_cb(PyObject *self, PyObject *cb) {
     452           0 :   PyGILState_STATE state = PyGILState_Ensure();
     453             :   PyObject *wrapped;
     454             :   gpgme_ctx_t ctx;
     455             : 
     456           0 :   wrapped = PyObject_GetAttrString(self, "wrapped");
     457           0 :   if (wrapped == NULL)
     458             :     {
     459             :       assert (PyErr_Occurred ());
     460           0 :       PyGILState_Release(state);
     461           0 :       return NULL;
     462             :     }
     463             : 
     464           0 :   ctx = _gpg_unwrap_gpgme_ctx_t(wrapped);
     465           0 :   Py_DECREF(wrapped);
     466           0 :   if (ctx == NULL)
     467             :     {
     468           0 :       if (cb == Py_None)
     469             :         goto out;
     470             :       else
     471           0 :         return PyErr_Format(PyExc_RuntimeError, "wrapped is NULL");
     472             :     }
     473             : 
     474           0 :   if (cb == Py_None) {
     475           0 :     gpgme_set_passphrase_cb(ctx, NULL, NULL);
     476           0 :     PyObject_SetAttrString(self, "_passphrase_cb", Py_None);
     477           0 :     goto out;
     478             :   }
     479             : 
     480           0 :   if (! PyTuple_Check(cb))
     481           0 :     return PyErr_Format(PyExc_TypeError, "cb must be a tuple");
     482           0 :   if (PyTuple_Size(cb) != 2 && PyTuple_Size(cb) != 3)
     483           0 :     return PyErr_Format(PyExc_TypeError,
     484             :                         "cb must be a tuple of size 2 or 3");
     485             : 
     486           0 :   gpgme_set_passphrase_cb(ctx, (gpgme_passphrase_cb_t) pyPassphraseCb,
     487             :                           (void *) cb);
     488           0 :   PyObject_SetAttrString(self, "_passphrase_cb", cb);
     489             : 
     490             :  out:
     491           0 :   Py_INCREF(Py_None);
     492           0 :   PyGILState_Release(state);
     493           0 :   return Py_None;
     494             : }
     495             : 
     496           0 : static void pyProgressCb(void *hook, const char *what, int type, int current,
     497             :                          int total) {
     498           0 :   PyGILState_STATE state = PyGILState_Ensure();
     499           0 :   PyObject *func = NULL, *dataarg = NULL, *args = NULL, *retval = NULL;
     500           0 :   PyObject *pyhook = (PyObject *) hook;
     501           0 :   PyObject *self = NULL;
     502             : 
     503             :   assert (PyTuple_Check(pyhook));
     504             :   assert (PyTuple_Size(pyhook) == 2 || PyTuple_Size(pyhook) == 3);
     505           0 :   self = PyTuple_GetItem(pyhook, 0);
     506           0 :   func = PyTuple_GetItem(pyhook, 1);
     507           0 :   if (PyTuple_Size(pyhook) == 3) {
     508           0 :     dataarg = PyTuple_GetItem(pyhook, 2);
     509           0 :     args = PyTuple_New(5);
     510             :   } else {
     511           0 :     args = PyTuple_New(4);
     512             :   }
     513             : 
     514           0 :   PyTuple_SetItem(args, 0, PyUnicode_DecodeUTF8(what, strlen (what),
     515             :                                                 "strict"));
     516           0 :   if (PyErr_Occurred()) {
     517           0 :     _gpg_stash_callback_exception(self);
     518           0 :     Py_DECREF(args);
     519           0 :     PyGILState_Release(state);
     520           0 :     return;
     521             :   }
     522           0 :   PyTuple_SetItem(args, 1, PyLong_FromLong((long) type));
     523           0 :   PyTuple_SetItem(args, 2, PyLong_FromLong((long) current));
     524           0 :   PyTuple_SetItem(args, 3, PyLong_FromLong((long) total));
     525           0 :   if (dataarg) {
     526           0 :     Py_INCREF(dataarg);         /* Because GetItem doesn't give a ref but SetItem taketh away */
     527           0 :     PyTuple_SetItem(args, 4, dataarg);
     528             :   }
     529             : 
     530           0 :   retval = PyObject_CallObject(func, args);
     531           0 :   if (PyErr_Occurred())
     532           0 :     _gpg_stash_callback_exception(self);
     533           0 :   Py_DECREF(args);
     534           0 :   Py_XDECREF(retval);
     535           0 :   PyGILState_Release(state);
     536             : }
     537             : 
     538             : PyObject *
     539           0 : gpg_set_progress_cb(PyObject *self, PyObject *cb) {
     540           0 :   PyGILState_STATE state = PyGILState_Ensure();
     541             :   PyObject *wrapped;
     542             :   gpgme_ctx_t ctx;
     543             : 
     544           0 :   wrapped = PyObject_GetAttrString(self, "wrapped");
     545           0 :   if (wrapped == NULL)
     546             :     {
     547             :       assert (PyErr_Occurred ());
     548           0 :       PyGILState_Release(state);
     549           0 :       return NULL;
     550             :     }
     551             : 
     552           0 :   ctx = _gpg_unwrap_gpgme_ctx_t(wrapped);
     553           0 :   Py_DECREF(wrapped);
     554           0 :   if (ctx == NULL)
     555             :     {
     556           0 :       if (cb == Py_None)
     557             :         goto out;
     558             :       else
     559           0 :         return PyErr_Format(PyExc_RuntimeError, "wrapped is NULL");
     560             :     }
     561             : 
     562           0 :   if (cb == Py_None) {
     563           0 :     gpgme_set_progress_cb(ctx, NULL, NULL);
     564           0 :     PyObject_SetAttrString(self, "_progress_cb", Py_None);
     565           0 :     goto out;
     566             :   }
     567             : 
     568           0 :   if (! PyTuple_Check(cb))
     569           0 :     return PyErr_Format(PyExc_TypeError, "cb must be a tuple");
     570           0 :   if (PyTuple_Size(cb) != 2 && PyTuple_Size(cb) != 3)
     571           0 :     return PyErr_Format(PyExc_TypeError,
     572             :                         "cb must be a tuple of size 2 or 3");
     573             : 
     574           0 :   gpgme_set_progress_cb(ctx, (gpgme_progress_cb_t) pyProgressCb, (void *) cb);
     575           0 :   PyObject_SetAttrString(self, "_progress_cb", cb);
     576             : 
     577             :  out:
     578           0 :   Py_INCREF(Py_None);
     579           0 :   PyGILState_Release(state);
     580           0 :   return Py_None;
     581             : }
     582             : 
     583             : /* Status callbacks.  */
     584           0 : static gpgme_error_t pyStatusCb(void *hook, const char *keyword,
     585             :                                 const char *args) {
     586           0 :   PyGILState_STATE state = PyGILState_Ensure();
     587           0 :   gpgme_error_t err = 0;
     588           0 :   PyObject *pyhook = (PyObject *) hook;
     589           0 :   PyObject *self = NULL;
     590           0 :   PyObject *func = NULL;
     591           0 :   PyObject *dataarg = NULL;
     592           0 :   PyObject *pyargs = NULL;
     593           0 :   PyObject *retval = NULL;
     594             : 
     595             :   assert (PyTuple_Check(pyhook));
     596             :   assert (PyTuple_Size(pyhook) == 2 || PyTuple_Size(pyhook) == 3);
     597           0 :   self = PyTuple_GetItem(pyhook, 0);
     598           0 :   func = PyTuple_GetItem(pyhook, 1);
     599           0 :   if (PyTuple_Size(pyhook) == 3) {
     600           0 :     dataarg = PyTuple_GetItem(pyhook, 2);
     601           0 :     pyargs = PyTuple_New(3);
     602             :   } else {
     603           0 :     pyargs = PyTuple_New(2);
     604             :   }
     605             : 
     606           0 :   if (keyword)
     607           0 :     PyTuple_SetItem(pyargs, 0, PyUnicode_DecodeUTF8(keyword, strlen (keyword),
     608             :                                                     "strict"));
     609             :   else
     610             :     {
     611           0 :       Py_INCREF(Py_None);
     612           0 :       PyTuple_SetItem(pyargs, 0, Py_None);
     613             :     }
     614           0 :   PyTuple_SetItem(pyargs, 1, PyUnicode_DecodeUTF8(args, strlen (args),
     615             :                                                 "strict"));
     616           0 :   if (PyErr_Occurred()) {
     617           0 :     err = gpg_error(GPG_ERR_GENERAL);
     618           0 :     Py_DECREF(pyargs);
     619             :     goto leave;
     620             :   }
     621             : 
     622           0 :   if (dataarg) {
     623           0 :     Py_INCREF(dataarg);
     624           0 :     PyTuple_SetItem(pyargs, 2, dataarg);
     625             :   }
     626             : 
     627           0 :   retval = PyObject_CallObject(func, pyargs);
     628           0 :   if (PyErr_Occurred())
     629           0 :     err = _gpg_exception2code();
     630           0 :   Py_DECREF(pyargs);
     631           0 :   Py_XDECREF(retval);
     632             : 
     633             :  leave:
     634           0 :   if (err)
     635           0 :     _gpg_stash_callback_exception(self);
     636           0 :   PyGILState_Release(state);
     637           0 :   return err;
     638             : }
     639             : 
     640             : PyObject *
     641           0 : gpg_set_status_cb(PyObject *self, PyObject *cb) {
     642           0 :   PyGILState_STATE state = PyGILState_Ensure();
     643             :   PyObject *wrapped;
     644             :   gpgme_ctx_t ctx;
     645             : 
     646           0 :   wrapped = PyObject_GetAttrString(self, "wrapped");
     647           0 :   if (wrapped == NULL)
     648             :     {
     649             :       assert (PyErr_Occurred ());
     650           0 :       PyGILState_Release(state);
     651           0 :       return NULL;
     652             :     }
     653             : 
     654           0 :   ctx = _gpg_unwrap_gpgme_ctx_t(wrapped);
     655           0 :   Py_DECREF(wrapped);
     656           0 :   if (ctx == NULL)
     657             :     {
     658           0 :       if (cb == Py_None)
     659             :         goto out;
     660             :       else
     661           0 :         return PyErr_Format(PyExc_RuntimeError, "wrapped is NULL");
     662             :     }
     663             : 
     664           0 :   if (cb == Py_None) {
     665           0 :     gpgme_set_status_cb(ctx, NULL, NULL);
     666           0 :     PyObject_SetAttrString(self, "_status_cb", Py_None);
     667           0 :     goto out;
     668             :   }
     669             : 
     670           0 :   if (! PyTuple_Check(cb))
     671           0 :     return PyErr_Format(PyExc_TypeError, "cb must be a tuple");
     672           0 :   if (PyTuple_Size(cb) != 2 && PyTuple_Size(cb) != 3)
     673           0 :     return PyErr_Format(PyExc_TypeError,
     674             :                         "cb must be a tuple of size 2 or 3");
     675             : 
     676           0 :   gpgme_set_status_cb(ctx, (gpgme_status_cb_t) pyStatusCb, (void *) cb);
     677           0 :   PyObject_SetAttrString(self, "_status_cb", cb);
     678             : 
     679             :  out:
     680           0 :   Py_INCREF(Py_None);
     681           0 :   PyGILState_Release(state);
     682           0 :   return Py_None;
     683             : }
     684             : 
     685             : 
     686             : 
     687             : /* Interact callbacks.  */
     688             : gpgme_error_t
     689           0 : _gpg_interact_cb(void *opaque, const char *keyword,
     690             :                   const char *args, int fd)
     691             : {
     692           0 :   PyGILState_STATE state = PyGILState_Ensure();
     693           0 :   PyObject *func = NULL, *dataarg = NULL, *pyargs = NULL, *retval = NULL;
     694             :   PyObject *py_keyword;
     695           0 :   PyObject *pyopaque = (PyObject *) opaque;
     696           0 :   gpgme_error_t err_status = 0;
     697           0 :   PyObject *self = NULL;
     698             : 
     699           0 :   _gpg_exception_init();
     700             : 
     701             :   assert (PyTuple_Check(pyopaque));
     702             :   assert (PyTuple_Size(pyopaque) == 2 || PyTuple_Size(pyopaque) == 3);
     703           0 :   self = PyTuple_GetItem(pyopaque, 0);
     704           0 :   func = PyTuple_GetItem(pyopaque, 1);
     705           0 :   if (PyTuple_Size(pyopaque) == 3) {
     706           0 :     dataarg = PyTuple_GetItem(pyopaque, 2);
     707           0 :     pyargs = PyTuple_New(3);
     708             :   } else {
     709           0 :     pyargs = PyTuple_New(2);
     710             :   }
     711             : 
     712           0 :   if (keyword)
     713           0 :     py_keyword = PyUnicode_FromString(keyword);
     714             :   else
     715             :     {
     716           0 :       Py_INCREF(Py_None);
     717           0 :       py_keyword = Py_None;
     718             :     }
     719             : 
     720           0 :   PyTuple_SetItem(pyargs, 0, py_keyword);
     721           0 :   PyTuple_SetItem(pyargs, 1, PyUnicode_FromString(args));
     722           0 :   if (dataarg) {
     723           0 :     Py_INCREF(dataarg);         /* Because GetItem doesn't give a ref but SetItem taketh away */
     724           0 :     PyTuple_SetItem(pyargs, 2, dataarg);
     725             :   }
     726             : 
     727           0 :   retval = PyObject_CallObject(func, pyargs);
     728           0 :   Py_DECREF(pyargs);
     729           0 :   if (PyErr_Occurred()) {
     730           0 :     err_status = _gpg_exception2code();
     731             :   } else {
     732           0 :     if (fd>=0 && retval && PyUnicode_Check(retval)) {
     733           0 :       PyObject *encoded = NULL;
     734             :       char *buffer;
     735             :       Py_ssize_t size;
     736             : 
     737           0 :       encoded = PyUnicode_AsUTF8String(retval);
     738           0 :       if (encoded == NULL)
     739             :         {
     740             :           err_status = gpg_error(GPG_ERR_GENERAL);
     741           0 :           goto leave;
     742             :         }
     743           0 :       if (PyBytes_AsStringAndSize(encoded, &buffer, &size) == -1)
     744             :         {
     745           0 :           Py_DECREF(encoded);
     746             :           err_status = gpg_error(GPG_ERR_GENERAL);
     747             :           goto leave;
     748             :         }
     749             : 
     750           0 :       if (write(fd, buffer, size) < 0) {
     751           0 :         err_status = gpgme_error_from_syserror ();
     752           0 :         _gpg_raise_exception (err_status);
     753             :       }
     754           0 :       if (! err_status && write(fd, "\n", 1) < 0) {
     755           0 :         err_status = gpgme_error_from_syserror ();
     756           0 :         _gpg_raise_exception (err_status);
     757             :       }
     758           0 :       Py_DECREF(encoded);
     759             :     }
     760             :   }
     761             :  leave:
     762           0 :   if (err_status)
     763           0 :     _gpg_stash_callback_exception(self);
     764             : 
     765           0 :   Py_XDECREF(retval);
     766           0 :   PyGILState_Release(state);
     767           0 :   return err_status;
     768             : }
     769             : 
     770             : 
     771             : 
     772             : /* Data callbacks.  */
     773             : 
     774             : /* Read up to SIZE bytes into buffer BUFFER from the data object with
     775             :    the handle HOOK.  Return the number of characters read, 0 on EOF
     776             :    and -1 on error.  If an error occurs, errno is set.  */
     777           0 : static ssize_t pyDataReadCb(void *hook, void *buffer, size_t size)
     778             : {
     779           0 :   PyGILState_STATE state = PyGILState_Ensure();
     780             :   ssize_t result;
     781           0 :   PyObject *pyhook = (PyObject *) hook;
     782           0 :   PyObject *self = NULL;
     783           0 :   PyObject *func = NULL;
     784           0 :   PyObject *dataarg = NULL;
     785           0 :   PyObject *pyargs = NULL;
     786           0 :   PyObject *retval = NULL;
     787             : 
     788             :   assert (PyTuple_Check(pyhook));
     789             :   assert (PyTuple_Size(pyhook) == 5 || PyTuple_Size(pyhook) == 6);
     790             : 
     791           0 :   self = PyTuple_GetItem(pyhook, 0);
     792           0 :   func = PyTuple_GetItem(pyhook, 1);
     793           0 :   if (PyTuple_Size(pyhook) == 6) {
     794           0 :     dataarg = PyTuple_GetItem(pyhook, 5);
     795           0 :     pyargs = PyTuple_New(2);
     796             :   } else {
     797           0 :     pyargs = PyTuple_New(1);
     798             :   }
     799             : 
     800           0 :   PyTuple_SetItem(pyargs, 0, PyLong_FromSize_t(size));
     801           0 :   if (dataarg) {
     802           0 :     Py_INCREF(dataarg);
     803           0 :     PyTuple_SetItem(pyargs, 1, dataarg);
     804             :   }
     805             : 
     806           0 :   retval = PyObject_CallObject(func, pyargs);
     807           0 :   Py_DECREF(pyargs);
     808           0 :   if (PyErr_Occurred()) {
     809           0 :     _gpg_stash_callback_exception(self);
     810           0 :     result = -1;
     811           0 :     goto leave;
     812             :   }
     813             : 
     814           0 :   if (! PyBytes_Check(retval)) {
     815           0 :     PyErr_Format(PyExc_TypeError,
     816             :                  "expected bytes from read callback, got %s",
     817             :                  retval->ob_type->tp_name);
     818           0 :     _gpg_stash_callback_exception(self);
     819           0 :     result = -1;
     820           0 :     goto leave;
     821             :   }
     822             : 
     823           0 :   if (PyBytes_Size(retval) > size) {
     824           0 :     PyErr_Format(PyExc_TypeError,
     825             :                  "expected %zu bytes from read callback, got %zu",
     826             :                  size, PyBytes_Size(retval));
     827           0 :     _gpg_stash_callback_exception(self);
     828           0 :     result = -1;
     829           0 :     goto leave;
     830             :   }
     831             : 
     832           0 :   memcpy(buffer, PyBytes_AsString(retval), PyBytes_Size(retval));
     833           0 :   result = PyBytes_Size(retval);
     834             : 
     835             :  leave:
     836           0 :   Py_XDECREF(retval);
     837           0 :   PyGILState_Release(state);
     838           0 :   return result;
     839             : }
     840             : 
     841             : /* Write up to SIZE bytes from buffer BUFFER to the data object with
     842             :    the handle HOOK.  Return the number of characters written, or -1
     843             :    on error.  If an error occurs, errno is set.  */
     844           0 : static ssize_t pyDataWriteCb(void *hook, const void *buffer, size_t size)
     845             : {
     846           0 :   PyGILState_STATE state = PyGILState_Ensure();
     847             :   ssize_t result;
     848           0 :   PyObject *pyhook = (PyObject *) hook;
     849           0 :   PyObject *self = NULL;
     850           0 :   PyObject *func = NULL;
     851           0 :   PyObject *dataarg = NULL;
     852           0 :   PyObject *pyargs = NULL;
     853           0 :   PyObject *retval = NULL;
     854             : 
     855             :   assert (PyTuple_Check(pyhook));
     856             :   assert (PyTuple_Size(pyhook) == 5 || PyTuple_Size(pyhook) == 6);
     857             : 
     858           0 :   self = PyTuple_GetItem(pyhook, 0);
     859           0 :   func = PyTuple_GetItem(pyhook, 2);
     860           0 :   if (PyTuple_Size(pyhook) == 6) {
     861           0 :     dataarg = PyTuple_GetItem(pyhook, 5);
     862           0 :     pyargs = PyTuple_New(2);
     863             :   } else {
     864           0 :     pyargs = PyTuple_New(1);
     865             :   }
     866             : 
     867           0 :   PyTuple_SetItem(pyargs, 0, PyBytes_FromStringAndSize(buffer, size));
     868           0 :   if (dataarg) {
     869           0 :     Py_INCREF(dataarg);
     870           0 :     PyTuple_SetItem(pyargs, 1, dataarg);
     871             :   }
     872             : 
     873           0 :   retval = PyObject_CallObject(func, pyargs);
     874           0 :   Py_DECREF(pyargs);
     875           0 :   if (PyErr_Occurred()) {
     876           0 :     _gpg_stash_callback_exception(self);
     877           0 :     result = -1;
     878           0 :     goto leave;
     879             :   }
     880             : 
     881             : #if PY_MAJOR_VERSION < 3
     882           0 :   if (PyInt_Check(retval))
     883           0 :     result = PyInt_AsSsize_t(retval);
     884             :   else
     885             : #endif
     886           0 :   if (PyLong_Check(retval))
     887           0 :     result = PyLong_AsSsize_t(retval);
     888             :   else {
     889           0 :     PyErr_Format(PyExc_TypeError,
     890             :                  "expected int from write callback, got %s",
     891             :                  retval->ob_type->tp_name);
     892           0 :     _gpg_stash_callback_exception(self);
     893           0 :     result = -1;
     894             :   }
     895             : 
     896             :  leave:
     897           0 :   Py_XDECREF(retval);
     898           0 :   PyGILState_Release(state);
     899           0 :   return result;
     900             : }
     901             : 
     902             : /* Set the current position from where the next read or write starts
     903             :    in the data object with the handle HOOK to OFFSET, relativ to
     904             :    WHENCE.  Returns the new offset in bytes from the beginning of the
     905             :    data object.  */
     906           0 : static off_t pyDataSeekCb(void *hook, off_t offset, int whence)
     907             : {
     908           0 :   PyGILState_STATE state = PyGILState_Ensure();
     909             :   off_t result;
     910           0 :   PyObject *pyhook = (PyObject *) hook;
     911           0 :   PyObject *self = NULL;
     912           0 :   PyObject *func = NULL;
     913           0 :   PyObject *dataarg = NULL;
     914           0 :   PyObject *pyargs = NULL;
     915           0 :   PyObject *retval = NULL;
     916             : 
     917             :   assert (PyTuple_Check(pyhook));
     918             :   assert (PyTuple_Size(pyhook) == 5 || PyTuple_Size(pyhook) == 6);
     919             : 
     920           0 :   self = PyTuple_GetItem(pyhook, 0);
     921           0 :   func = PyTuple_GetItem(pyhook, 3);
     922           0 :   if (PyTuple_Size(pyhook) == 6) {
     923           0 :     dataarg = PyTuple_GetItem(pyhook, 5);
     924           0 :     pyargs = PyTuple_New(3);
     925             :   } else {
     926           0 :     pyargs = PyTuple_New(2);
     927             :   }
     928             : 
     929             : #if defined(_FILE_OFFSET_BITS) && _FILE_OFFSET_BITS == 64
     930           0 :   PyTuple_SetItem(pyargs, 0, PyLong_FromLongLong((long long) offset));
     931             : #else
     932             :   PyTuple_SetItem(pyargs, 0, PyLong_FromLong((long) offset));
     933             : #endif
     934           0 :   PyTuple_SetItem(pyargs, 1, PyLong_FromLong((long) whence));
     935           0 :   if (dataarg) {
     936           0 :     Py_INCREF(dataarg);
     937           0 :     PyTuple_SetItem(pyargs, 2, dataarg);
     938             :   }
     939             : 
     940           0 :   retval = PyObject_CallObject(func, pyargs);
     941           0 :   Py_DECREF(pyargs);
     942           0 :   if (PyErr_Occurred()) {
     943           0 :     _gpg_stash_callback_exception(self);
     944           0 :     result = -1;
     945           0 :     goto leave;
     946             :   }
     947             : 
     948             : #if PY_MAJOR_VERSION < 3
     949           0 :   if (PyInt_Check(retval))
     950           0 :     result = PyInt_AsLong(retval);
     951             :   else
     952             : #endif
     953           0 :   if (PyLong_Check(retval))
     954             : #if defined(_FILE_OFFSET_BITS) && _FILE_OFFSET_BITS == 64
     955           0 :     result = PyLong_AsLongLong(retval);
     956             : #else
     957             :     result = PyLong_AsLong(retval);
     958             : #endif
     959             :   else {
     960           0 :     PyErr_Format(PyExc_TypeError,
     961             :                  "expected int from seek callback, got %s",
     962             :                  retval->ob_type->tp_name);
     963           0 :     _gpg_stash_callback_exception(self);
     964           0 :     result = -1;
     965             :   }
     966             : 
     967             :  leave:
     968           0 :   Py_XDECREF(retval);
     969           0 :   PyGILState_Release(state);
     970           0 :   return result;
     971             : }
     972             : 
     973             : /* Close the data object with the handle HOOK.  */
     974           0 : static void pyDataReleaseCb(void *hook)
     975             : {
     976           0 :   PyGILState_STATE state = PyGILState_Ensure();
     977           0 :   PyObject *pyhook = (PyObject *) hook;
     978           0 :   PyObject *self = NULL;
     979           0 :   PyObject *func = NULL;
     980           0 :   PyObject *dataarg = NULL;
     981           0 :   PyObject *pyargs = NULL;
     982           0 :   PyObject *retval = NULL;
     983             : 
     984             :   assert (PyTuple_Check(pyhook));
     985             :   assert (PyTuple_Size(pyhook) == 5 || PyTuple_Size(pyhook) == 6);
     986             : 
     987           0 :   self = PyTuple_GetItem(pyhook, 0);
     988           0 :   func = PyTuple_GetItem(pyhook, 4);
     989           0 :   if (PyTuple_Size(pyhook) == 6) {
     990           0 :     dataarg = PyTuple_GetItem(pyhook, 5);
     991           0 :     pyargs = PyTuple_New(1);
     992             :   } else {
     993           0 :     pyargs = PyTuple_New(0);
     994             :   }
     995             : 
     996           0 :   if (dataarg) {
     997           0 :     Py_INCREF(dataarg);
     998           0 :     PyTuple_SetItem(pyargs, 0, dataarg);
     999             :   }
    1000             : 
    1001           0 :   retval = PyObject_CallObject(func, pyargs);
    1002           0 :   Py_XDECREF(retval);
    1003           0 :   Py_DECREF(pyargs);
    1004           0 :   if (PyErr_Occurred())
    1005           0 :     _gpg_stash_callback_exception(self);
    1006           0 :   PyGILState_Release(state);
    1007           0 : }
    1008             : 
    1009             : PyObject *
    1010           0 : gpg_data_new_from_cbs(PyObject *self,
    1011             :                        PyObject *pycbs,
    1012             :                        gpgme_data_t *r_data)
    1013             : {
    1014           0 :   PyGILState_STATE state = PyGILState_Ensure();
    1015             :   static struct gpgme_data_cbs cbs = {
    1016             :     pyDataReadCb,
    1017             :     pyDataWriteCb,
    1018             :     pyDataSeekCb,
    1019             :     pyDataReleaseCb,
    1020             :   };
    1021             :   gpgme_error_t err;
    1022             : 
    1023           0 :   if (! PyTuple_Check(pycbs))
    1024           0 :     return PyErr_Format(PyExc_TypeError, "pycbs must be a tuple");
    1025           0 :   if (PyTuple_Size(pycbs) != 5 && PyTuple_Size(pycbs) != 6)
    1026           0 :     return PyErr_Format(PyExc_TypeError,
    1027             :                         "pycbs must be a tuple of size 5 or 6");
    1028             : 
    1029           0 :   err = gpgme_data_new_from_cbs(r_data, &cbs, (void *) pycbs);
    1030           0 :   if (err)
    1031           0 :     return _gpg_raise_exception(err);
    1032             : 
    1033           0 :   PyObject_SetAttrString(self, "_data_cbs", pycbs);
    1034             : 
    1035           0 :   Py_INCREF(Py_None);
    1036           0 :   PyGILState_Release(state);
    1037           0 :   return Py_None;
    1038             : }
    1039             : 
    1040             : 
    1041             : 
    1042             : /* The assuan callbacks.  */
    1043             : 
    1044             : gpgme_error_t
    1045           0 : _gpg_assuan_data_cb (void *hook, const void *data, size_t datalen)
    1046             : {
    1047           0 :   PyGILState_STATE state = PyGILState_Ensure();
    1048           0 :   gpgme_error_t err = 0;
    1049           0 :   PyObject *pyhook = (PyObject *) hook;
    1050           0 :   PyObject *self = NULL;
    1051           0 :   PyObject *func = NULL;
    1052           0 :   PyObject *py_data = NULL;
    1053           0 :   PyObject *retval = NULL;
    1054             : 
    1055             :   assert (PyTuple_Check(pyhook));
    1056             :   assert (PyTuple_Size(pyhook) == 2);
    1057           0 :   self = PyTuple_GetItem(pyhook, 0);
    1058           0 :   func = PyTuple_GetItem(pyhook, 1);
    1059             :   assert (PyCallable_Check(func));
    1060             : 
    1061           0 :   py_data = PyBytes_FromStringAndSize(data, datalen);
    1062           0 :   if (py_data == NULL)
    1063             :     {
    1064           0 :       err = _gpg_exception2code();
    1065           0 :       goto leave;
    1066             :     }
    1067             : 
    1068           0 :   retval = PyObject_CallFunctionObjArgs(func, py_data, NULL);
    1069           0 :   if (PyErr_Occurred())
    1070           0 :     err = _gpg_exception2code();
    1071           0 :   Py_DECREF(py_data);
    1072           0 :   Py_XDECREF(retval);
    1073             : 
    1074             :  leave:
    1075           0 :   if (err)
    1076           0 :     _gpg_stash_callback_exception(self);
    1077           0 :   PyGILState_Release(state);
    1078           0 :   return err;
    1079             : }
    1080             : 
    1081             : gpgme_error_t
    1082           0 : _gpg_assuan_inquire_cb (void *hook, const char *name, const char *args,
    1083             :                          gpgme_data_t *r_data)
    1084             : {
    1085           0 :   PyGILState_STATE state = PyGILState_Ensure();
    1086           0 :   gpgme_error_t err = 0;
    1087           0 :   PyObject *pyhook = (PyObject *) hook;
    1088           0 :   PyObject *self = NULL;
    1089           0 :   PyObject *func = NULL;
    1090           0 :   PyObject *py_name = NULL;
    1091           0 :   PyObject *py_args = NULL;
    1092           0 :   PyObject *retval = NULL;
    1093             : 
    1094             :   assert (PyTuple_Check(pyhook));
    1095             :   assert (PyTuple_Size(pyhook) == 2);
    1096           0 :   self = PyTuple_GetItem(pyhook, 0);
    1097           0 :   func = PyTuple_GetItem(pyhook, 1);
    1098             :   assert (PyCallable_Check(func));
    1099             : 
    1100           0 :   py_name = PyUnicode_FromString(name);
    1101           0 :   if (py_name == NULL)
    1102             :     {
    1103           0 :       err = _gpg_exception2code();
    1104           0 :       goto leave;
    1105             :     }
    1106             : 
    1107           0 :   py_args = PyUnicode_FromString(args);
    1108           0 :   if (py_args == NULL)
    1109             :     {
    1110           0 :       err = _gpg_exception2code();
    1111           0 :       goto leave;
    1112             :     }
    1113             : 
    1114           0 :   retval = PyObject_CallFunctionObjArgs(func, py_name, py_args, NULL);
    1115           0 :   if (PyErr_Occurred())
    1116           0 :     err = _gpg_exception2code();
    1117           0 :   Py_XDECREF(retval);
    1118             : 
    1119             :   /* FIXME: Returning data is not yet implemented.  */
    1120           0 :   *r_data = NULL;
    1121             : 
    1122             :  leave:
    1123           0 :   Py_XDECREF(py_name);
    1124           0 :   Py_XDECREF(py_args);
    1125           0 :   if (err)
    1126           0 :     _gpg_stash_callback_exception(self);
    1127           0 :   PyGILState_Release(state);
    1128           0 :   return err;
    1129             : }
    1130             : 
    1131             : gpgme_error_t
    1132           0 : _gpg_assuan_status_cb (void *hook, const char *status, const char *args)
    1133             : {
    1134           0 :   PyGILState_STATE state = PyGILState_Ensure();
    1135           0 :   gpgme_error_t err = 0;
    1136           0 :   PyObject *pyhook = (PyObject *) hook;
    1137           0 :   PyObject *self = NULL;
    1138           0 :   PyObject *func = NULL;
    1139           0 :   PyObject *py_status = NULL;
    1140           0 :   PyObject *py_args = NULL;
    1141           0 :   PyObject *retval = NULL;
    1142             : 
    1143             :   assert (PyTuple_Check(pyhook));
    1144             :   assert (PyTuple_Size(pyhook) == 2);
    1145           0 :   self = PyTuple_GetItem(pyhook, 0);
    1146           0 :   func = PyTuple_GetItem(pyhook, 1);
    1147             :   assert (PyCallable_Check(func));
    1148             : 
    1149           0 :   py_status = PyUnicode_FromString(status);
    1150           0 :   if (py_status == NULL)
    1151             :     {
    1152           0 :       err = _gpg_exception2code();
    1153           0 :       goto leave;
    1154             :     }
    1155             : 
    1156           0 :   py_args = PyUnicode_FromString(args);
    1157           0 :   if (py_args == NULL)
    1158             :     {
    1159           0 :       err = _gpg_exception2code();
    1160           0 :       goto leave;
    1161             :     }
    1162             : 
    1163           0 :   retval = PyObject_CallFunctionObjArgs(func, py_status, py_args, NULL);
    1164           0 :   if (PyErr_Occurred())
    1165           0 :     err = _gpg_exception2code();
    1166           0 :   Py_XDECREF(retval);
    1167             : 
    1168             :  leave:
    1169           0 :   Py_XDECREF(py_status);
    1170           0 :   Py_XDECREF(py_args);
    1171           0 :   if (err)
    1172           0 :     _gpg_stash_callback_exception(self);
    1173           0 :   PyGILState_Release(state);
    1174           0 :   return err;
    1175             : }

Generated by: LCOV version 1.12