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

Generated by: LCOV version 1.13