Blame lang/python/helpers.c

Packit d7e8d0
/*
Packit d7e8d0
# Copyright (C) 2016 g10 Code GmbH
Packit d7e8d0
# Copyright (C) 2004 Igor Belyi <belyi@users.sourceforge.net>
Packit d7e8d0
# Copyright (C) 2002 John Goerzen <jgoerzen@complete.org>
Packit d7e8d0
#
Packit d7e8d0
#    This library is free software; you can redistribute it and/or
Packit d7e8d0
#    modify it under the terms of the GNU Lesser General Public
Packit d7e8d0
#    License as published by the Free Software Foundation; either
Packit d7e8d0
#    version 2.1 of the License, or (at your option) any later version.
Packit d7e8d0
#
Packit d7e8d0
#    This library is distributed in the hope that it will be useful,
Packit d7e8d0
#    but WITHOUT ANY WARRANTY; without even the implied warranty of
Packit d7e8d0
#    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
Packit d7e8d0
#    Lesser General Public License for more details.
Packit d7e8d0
#
Packit d7e8d0
#    You should have received a copy of the GNU Lesser General Public
Packit d7e8d0
#    License along with this library; if not, write to the Free Software
Packit d7e8d0
#    Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307  USA
Packit d7e8d0
*/
Packit d7e8d0
Packit d7e8d0
#ifdef HAVE_CONFIG_H
Packit d7e8d0
#include "config.h"
Packit d7e8d0
#endif
Packit d7e8d0
Packit d7e8d0
#include <assert.h>
Packit d7e8d0
#include <stdio.h>
Packit d7e8d0
#include <gpgme.h>
Packit d7e8d0
#include <stdlib.h>
Packit d7e8d0
#include <string.h>
Packit d7e8d0
#include "Python.h"
Packit d7e8d0
Packit d7e8d0
#include "helpers.h"
Packit d7e8d0
#include "private.h"
Packit d7e8d0
Packit d7e8d0
/* Flag specifying whether this is an in-tree build.  */
Packit d7e8d0
int gpg_in_tree_build =
Packit d7e8d0
#if IN_TREE_BUILD
Packit d7e8d0
  1
Packit d7e8d0
#else
Packit d7e8d0
  0
Packit d7e8d0
#endif
Packit d7e8d0
  ;
Packit d7e8d0
Packit d7e8d0
static PyObject *GPGMEError = NULL;
Packit d7e8d0
Packit d7e8d0
void _gpg_exception_init(void) {
Packit d7e8d0
  if (GPGMEError == NULL) {
Packit d7e8d0
    PyObject *errors;
Packit d7e8d0
    PyObject *from_list = PyList_New(0);
Packit d7e8d0
    errors = PyImport_ImportModuleLevel("errors", PyEval_GetGlobals(),
Packit d7e8d0
                                        PyEval_GetLocals(), from_list, 1);
Packit d7e8d0
    Py_XDECREF(from_list);
Packit d7e8d0
    if (errors) {
Packit d7e8d0
      GPGMEError=PyDict_GetItemString(PyModule_GetDict(errors), "GPGMEError");
Packit d7e8d0
      Py_XINCREF(GPGMEError);
Packit d7e8d0
    }
Packit d7e8d0
  }
Packit d7e8d0
}
Packit d7e8d0
Packit d7e8d0
static PyObject *
Packit d7e8d0
_gpg_raise_exception(gpgme_error_t err)
Packit d7e8d0
{
Packit d7e8d0
  PyObject *e;
Packit d7e8d0
Packit d7e8d0
  _gpg_exception_init();
Packit d7e8d0
  if (GPGMEError == NULL)
Packit d7e8d0
    return PyErr_Format(PyExc_RuntimeError, "Got gpgme_error_t %d", err);
Packit d7e8d0
Packit d7e8d0
  e = PyObject_CallFunction(GPGMEError, "l", (long) err);
Packit d7e8d0
  if (e == NULL)
Packit d7e8d0
    return NULL;
Packit d7e8d0
Packit d7e8d0
  PyErr_SetObject(GPGMEError, e);
Packit d7e8d0
  Py_DECREF(e);
Packit d7e8d0
Packit d7e8d0
  return NULL;	/* raise */
Packit d7e8d0
}
Packit d7e8d0
Packit d7e8d0
gpgme_error_t _gpg_exception2code(void) {
Packit d7e8d0
  gpgme_error_t err_status = gpg_error(GPG_ERR_GENERAL);
Packit d7e8d0
  if (GPGMEError && PyErr_ExceptionMatches(GPGMEError)) {
Packit d7e8d0
    PyObject *type = 0, *value = 0, *traceback = 0;
Packit d7e8d0
    PyObject *error = 0;
Packit d7e8d0
    PyErr_Fetch(&type, &value, &traceback);
Packit d7e8d0
    PyErr_NormalizeException(&type, &value, &traceback);
Packit d7e8d0
    error = PyObject_GetAttrString(value, "error");
Packit d7e8d0
    err_status = PyLong_AsLong(error);
Packit d7e8d0
    Py_DECREF(error);
Packit d7e8d0
    PyErr_Restore(type, value, traceback);
Packit d7e8d0
  }
Packit d7e8d0
  return err_status;
Packit d7e8d0
}
Packit d7e8d0
Packit d7e8d0
/* Exception support for callbacks.  */
Packit d7e8d0
#define EXCINFO	"_callback_excinfo"
Packit d7e8d0
Packit d7e8d0
static void _gpg_stash_callback_exception(PyObject *weak_self)
Packit d7e8d0
{
Packit d7e8d0
  PyObject *self, *ptype, *pvalue, *ptraceback, *excinfo;
Packit d7e8d0
Packit d7e8d0
  PyErr_Fetch(&ptype, &pvalue, &ptraceback);
Packit d7e8d0
  excinfo = PyTuple_New(3);
Packit d7e8d0
  PyTuple_SetItem(excinfo, 0, ptype);
Packit d7e8d0
Packit d7e8d0
  if (pvalue)
Packit d7e8d0
    PyTuple_SetItem(excinfo, 1, pvalue);
Packit d7e8d0
  else {
Packit d7e8d0
    Py_INCREF(Py_None);
Packit d7e8d0
    PyTuple_SetItem(excinfo, 1, Py_None);
Packit d7e8d0
  }
Packit d7e8d0
Packit d7e8d0
  if (ptraceback)
Packit d7e8d0
    PyTuple_SetItem(excinfo, 2, ptraceback);
Packit d7e8d0
  else {
Packit d7e8d0
    Py_INCREF(Py_None);
Packit d7e8d0
    PyTuple_SetItem(excinfo, 2, Py_None);
Packit d7e8d0
  }
Packit d7e8d0
Packit d7e8d0
  self = PyWeakref_GetObject(weak_self);
Packit d7e8d0
  /* self only has a borrowed reference.  */
Packit d7e8d0
  if (self == Py_None) {
Packit d7e8d0
    /* This should not happen, as even if we're called from the data
Packit d7e8d0
       release callback triggered from the wrappers destructor, the
Packit d7e8d0
       object is still alive and hence the weak reference still refers
Packit d7e8d0
       to the object.  However, in case this ever changes, not seeing
Packit d7e8d0
       any exceptions is worse than having a little extra code, so
Packit d7e8d0
       here we go.  */
Packit d7e8d0
      fprintf(stderr,
Packit d7e8d0
              "Error occurred in callback, but the wrapper object "
Packit d7e8d0
              "has been deallocated.\n");
Packit d7e8d0
      PyErr_Restore(ptype, pvalue, ptraceback);
Packit d7e8d0
      PyErr_Print();
Packit d7e8d0
    }
Packit d7e8d0
  else
Packit d7e8d0
    PyObject_SetAttrString(self, EXCINFO, excinfo);
Packit d7e8d0
  Py_DECREF(excinfo);
Packit d7e8d0
}
Packit d7e8d0
Packit d7e8d0
PyObject *gpg_raise_callback_exception(PyObject *self)
Packit d7e8d0
{
Packit d7e8d0
  PyGILState_STATE state = PyGILState_Ensure();
Packit d7e8d0
  PyObject *ptype, *pvalue, *ptraceback, *excinfo;
Packit d7e8d0
Packit d7e8d0
  if (! PyObject_HasAttrString(self, EXCINFO))
Packit d7e8d0
    goto leave;
Packit d7e8d0
Packit d7e8d0
  excinfo = PyObject_GetAttrString(self, EXCINFO);
Packit d7e8d0
  if (! PyTuple_Check(excinfo))
Packit d7e8d0
    {
Packit d7e8d0
      Py_DECREF(excinfo);
Packit d7e8d0
      goto leave;
Packit d7e8d0
    }
Packit d7e8d0
Packit d7e8d0
  ptype = PyTuple_GetItem(excinfo, 0);
Packit d7e8d0
  Py_INCREF(excinfo);
Packit d7e8d0
Packit d7e8d0
  pvalue = PyTuple_GetItem(excinfo, 1);
Packit d7e8d0
  if (pvalue == Py_None)
Packit d7e8d0
    pvalue = NULL;
Packit d7e8d0
  else
Packit d7e8d0
    Py_INCREF(pvalue);
Packit d7e8d0
Packit d7e8d0
  ptraceback = PyTuple_GetItem(excinfo, 2);
Packit d7e8d0
  if (ptraceback == Py_None)
Packit d7e8d0
    ptraceback = NULL;
Packit d7e8d0
  else
Packit d7e8d0
    Py_INCREF(ptraceback);
Packit d7e8d0
Packit d7e8d0
  /* We now have references for the extracted items.  */
Packit d7e8d0
  Py_DECREF(excinfo);
Packit d7e8d0
Packit d7e8d0
  /* Clear the exception information.  It is important to do this
Packit d7e8d0
     before setting the error, because setting the attribute may
Packit d7e8d0
     execute python code, and the runtime system raises a SystemError
Packit d7e8d0
     if an exception is set but values are returned.  */
Packit d7e8d0
  Py_INCREF(Py_None);
Packit d7e8d0
  PyObject_SetAttrString(self, EXCINFO, Py_None);
Packit d7e8d0
Packit d7e8d0
  /* Restore exception.  */
Packit d7e8d0
  PyErr_Restore(ptype, pvalue, ptraceback);
Packit d7e8d0
  PyGILState_Release(state);
Packit d7e8d0
  return NULL; /* Raise exception.  */
Packit d7e8d0
Packit d7e8d0
 leave:
Packit d7e8d0
  Py_INCREF(Py_None);
Packit d7e8d0
  PyGILState_Release(state);
Packit d7e8d0
  return Py_None;
Packit d7e8d0
}
Packit d7e8d0
#undef EXCINFO
Packit d7e8d0

Packit d7e8d0
/* Argument conversion.  */
Packit d7e8d0
Packit d7e8d0
/* Convert object to a pointer to gpgme type, generic version.  */
Packit d7e8d0
PyObject *
Packit d7e8d0
_gpg_obj2gpgme_t(PyObject *input, const char *objtype, int argnum)
Packit d7e8d0
{
Packit d7e8d0
  PyObject *pyname = NULL, *pypointer = NULL;
Packit d7e8d0
  pyname = PyObject_GetAttrString(input, "_ctype");
Packit d7e8d0
  if (pyname && PyUnicode_Check(pyname))
Packit d7e8d0
    {
Packit d7e8d0
      PyObject *encoded = PyUnicode_AsUTF8String(pyname);
Packit d7e8d0
      if (strcmp(PyBytes_AsString(encoded), objtype) != 0)
Packit d7e8d0
        {
Packit d7e8d0
          PyErr_Format(PyExc_TypeError,
Packit d7e8d0
                       "arg %d: Expected value of type %s, but got %s",
Packit d7e8d0
                       argnum, objtype, PyBytes_AsString(encoded));
Packit d7e8d0
          Py_DECREF(encoded);
Packit d7e8d0
          Py_DECREF(pyname);
Packit d7e8d0
          return NULL;
Packit d7e8d0
        }
Packit d7e8d0
      Py_DECREF(encoded);
Packit d7e8d0
    }
Packit d7e8d0
  else
Packit d7e8d0
    return NULL;
Packit d7e8d0
Packit d7e8d0
  Py_DECREF(pyname);
Packit d7e8d0
  pypointer = PyObject_GetAttrString(input, "wrapped");
Packit d7e8d0
  if (pypointer == NULL) {
Packit d7e8d0
    PyErr_Format(PyExc_TypeError,
Packit d7e8d0
		 "arg %d: Use of uninitialized Python object %s",
Packit d7e8d0
		 argnum, objtype);
Packit d7e8d0
    return NULL;
Packit d7e8d0
  }
Packit d7e8d0
  return pypointer;
Packit d7e8d0
}
Packit d7e8d0
Packit d7e8d0
/* Convert object to a pointer to gpgme type, version for data
Packit d7e8d0
   objects.  Constructs a wrapper Python on the fly e.g. for file-like
Packit d7e8d0
   objects with a fileno method, returning it in WRAPPER.  This object
Packit d7e8d0
   must be de-referenced when no longer needed.  */
Packit d7e8d0
PyObject *
Packit d7e8d0
_gpg_obj2gpgme_data_t(PyObject *input, int argnum, gpgme_data_t *wrapper,
Packit d7e8d0
                       PyObject **bytesio, Py_buffer *view)
Packit d7e8d0
{
Packit d7e8d0
  gpgme_error_t err;
Packit d7e8d0
  PyObject *data;
Packit d7e8d0
  PyObject *fd;
Packit d7e8d0
Packit d7e8d0
  /* See if it is a file-like object with file number.  */
Packit d7e8d0
  fd = PyObject_CallMethod(input, "fileno", NULL);
Packit d7e8d0
  if (fd) {
Packit d7e8d0
    err = gpgme_data_new_from_fd(wrapper, (int) PyLong_AsLong(fd));
Packit d7e8d0
    Py_DECREF(fd);
Packit d7e8d0
    if (err)
Packit d7e8d0
      return _gpg_raise_exception (err);
Packit d7e8d0
Packit d7e8d0
    return _gpg_wrap_gpgme_data_t(*wrapper);
Packit d7e8d0
  }
Packit d7e8d0
  else
Packit d7e8d0
    PyErr_Clear();
Packit d7e8d0
Packit d7e8d0
  /* No?  Maybe it implements the buffer protocol.  */
Packit d7e8d0
  data = PyObject_CallMethod(input, "getbuffer", NULL);
Packit d7e8d0
  if (data)
Packit d7e8d0
    {
Packit d7e8d0
      /* Save a reference to input, which seems to be a BytesIO
Packit d7e8d0
         object.  */
Packit d7e8d0
      Py_INCREF(input);
Packit d7e8d0
      *bytesio = input;
Packit d7e8d0
    }
Packit d7e8d0
  else
Packit d7e8d0
    {
Packit d7e8d0
      PyErr_Clear();
Packit d7e8d0
Packit d7e8d0
      /* No, but maybe the user supplied a buffer object?  */
Packit d7e8d0
      data = input;
Packit d7e8d0
    }
Packit d7e8d0
Packit d7e8d0
  /* Do we have a buffer object?  */
Packit d7e8d0
  if (PyObject_CheckBuffer(data))
Packit d7e8d0
    {
Packit d7e8d0
      if (PyObject_GetBuffer(data, view, PyBUF_SIMPLE) < 0)
Packit d7e8d0
        return NULL;
Packit d7e8d0
Packit d7e8d0
      if (data != input)
Packit d7e8d0
        Py_DECREF(data);
Packit d7e8d0
Packit d7e8d0
      assert (view->obj);
Packit d7e8d0
      assert (view->ndim == 1);
Packit d7e8d0
      assert (view->shape == NULL);
Packit d7e8d0
      assert (view->strides == NULL);
Packit d7e8d0
      assert (view->suboffsets == NULL);
Packit d7e8d0
Packit d7e8d0
      err = gpgme_data_new_from_mem(wrapper, view->buf, (size_t) view->len, 0);
Packit d7e8d0
      if (err)
Packit d7e8d0
        return _gpg_raise_exception (err);
Packit d7e8d0
Packit d7e8d0
      return _gpg_wrap_gpgme_data_t(*wrapper);
Packit d7e8d0
    }
Packit d7e8d0
Packit d7e8d0
  /* As last resort we assume it is a wrapped data object.  */
Packit d7e8d0
  if (PyObject_HasAttrString(data, "_ctype"))
Packit d7e8d0
    return _gpg_obj2gpgme_t(data, "gpgme_data_t", argnum);
Packit d7e8d0
Packit d7e8d0
  return PyErr_Format(PyExc_TypeError,
Packit d7e8d0
                      "arg %d: expected gpg.Data, file, "
Packit d7e8d0
                      "bytes (not string!), or an object "
Packit d7e8d0
                      "implementing the buffer protocol. Got: %s. "
Packit d7e8d0
                      "If you provided a string, try to encode() it.",
Packit d7e8d0
                      argnum, data->ob_type->tp_name);
Packit d7e8d0
}
Packit d7e8d0
Packit d7e8d0

Packit d7e8d0
Packit d7e8d0
PyObject *
Packit d7e8d0
_gpg_wrap_result(PyObject *fragile, const char *classname)
Packit d7e8d0
{
Packit d7e8d0
  static PyObject *results;
Packit d7e8d0
  PyObject *class;
Packit d7e8d0
  PyObject *replacement;
Packit d7e8d0
Packit d7e8d0
  if (results == NULL)
Packit d7e8d0
    {
Packit d7e8d0
      PyObject *from_list = PyList_New(0);
Packit d7e8d0
      if (from_list == NULL)
Packit d7e8d0
        return NULL;
Packit d7e8d0
Packit d7e8d0
      results = PyImport_ImportModuleLevel("results", PyEval_GetGlobals(),
Packit d7e8d0
                                           PyEval_GetLocals(), from_list, 1);
Packit d7e8d0
      Py_DECREF(from_list);
Packit d7e8d0
Packit d7e8d0
      if (results == NULL)
Packit d7e8d0
        return NULL;
Packit d7e8d0
    }
Packit d7e8d0
Packit d7e8d0
  class = PyMapping_GetItemString(PyModule_GetDict(results), classname);
Packit d7e8d0
  if (class == NULL)
Packit d7e8d0
    return NULL;
Packit d7e8d0
Packit d7e8d0
  replacement = PyObject_CallFunctionObjArgs(class, fragile, NULL);
Packit d7e8d0
  Py_DECREF(class);
Packit d7e8d0
  return replacement;
Packit d7e8d0
}
Packit d7e8d0
Packit d7e8d0

Packit d7e8d0
Packit d7e8d0
/* Callback support.  */
Packit d7e8d0
static gpgme_error_t pyPassphraseCb(void *hook,
Packit d7e8d0
				    const char *uid_hint,
Packit d7e8d0
				    const char *passphrase_info,
Packit d7e8d0
				    int prev_was_bad,
Packit d7e8d0
				    int fd) {
Packit d7e8d0
  PyGILState_STATE state = PyGILState_Ensure();
Packit d7e8d0
  PyObject *pyhook = (PyObject *) hook;
Packit d7e8d0
  PyObject *self = NULL;
Packit d7e8d0
  PyObject *func = NULL;
Packit d7e8d0
  PyObject *args = NULL;
Packit d7e8d0
  PyObject *retval = NULL;
Packit d7e8d0
  PyObject *dataarg = NULL;
Packit d7e8d0
  PyObject *encoded = NULL;
Packit d7e8d0
  gpgme_error_t err_status = 0;
Packit d7e8d0
Packit d7e8d0
  _gpg_exception_init();
Packit d7e8d0
Packit d7e8d0
  assert (PyTuple_Check(pyhook));
Packit d7e8d0
  assert (PyTuple_Size(pyhook) == 2 || PyTuple_Size(pyhook) == 3);
Packit d7e8d0
  self = PyTuple_GetItem(pyhook, 0);
Packit d7e8d0
  func = PyTuple_GetItem(pyhook, 1);
Packit d7e8d0
  if (PyTuple_Size(pyhook) == 3) {
Packit d7e8d0
    dataarg = PyTuple_GetItem(pyhook, 2);
Packit d7e8d0
    args = PyTuple_New(4);
Packit d7e8d0
  } else {
Packit d7e8d0
    args = PyTuple_New(3);
Packit d7e8d0
  }
Packit d7e8d0
Packit d7e8d0
  if (uid_hint == NULL)
Packit d7e8d0
    {
Packit d7e8d0
      Py_INCREF(Py_None);
Packit d7e8d0
      PyTuple_SetItem(args, 0, Py_None);
Packit d7e8d0
    }
Packit d7e8d0
  else
Packit d7e8d0
    PyTuple_SetItem(args, 0, PyUnicode_DecodeUTF8(uid_hint, strlen (uid_hint),
Packit d7e8d0
                                                  "strict"));
Packit d7e8d0
  if (PyErr_Occurred()) {
Packit d7e8d0
    Py_DECREF(args);
Packit d7e8d0
    err_status = gpg_error(GPG_ERR_GENERAL);
Packit d7e8d0
    goto leave;
Packit d7e8d0
  }
Packit d7e8d0
Packit d7e8d0
  if (passphrase_info == NULL)
Packit d7e8d0
    {
Packit d7e8d0
      Py_INCREF(Py_None);
Packit d7e8d0
      PyTuple_SetItem(args, 1, Py_None);
Packit d7e8d0
    }
Packit d7e8d0
  else
Packit d7e8d0
    PyTuple_SetItem(args, 1, PyUnicode_DecodeUTF8(passphrase_info,
Packit d7e8d0
                                                  strlen (passphrase_info),
Packit d7e8d0
                                                  "strict"));
Packit d7e8d0
  if (PyErr_Occurred()) {
Packit d7e8d0
    Py_DECREF(args);
Packit d7e8d0
    err_status = gpg_error(GPG_ERR_GENERAL);
Packit d7e8d0
    goto leave;
Packit d7e8d0
  }
Packit d7e8d0
Packit d7e8d0
  PyTuple_SetItem(args, 2, PyBool_FromLong((long)prev_was_bad));
Packit d7e8d0
  if (dataarg) {
Packit d7e8d0
    Py_INCREF(dataarg);		/* Because GetItem doesn't give a ref but SetItem taketh away */
Packit d7e8d0
    PyTuple_SetItem(args, 3, dataarg);
Packit d7e8d0
  }
Packit d7e8d0
Packit d7e8d0
  retval = PyObject_CallObject(func, args);
Packit d7e8d0
  Py_DECREF(args);
Packit d7e8d0
  if (PyErr_Occurred()) {
Packit d7e8d0
    err_status = _gpg_exception2code();
Packit d7e8d0
  } else {
Packit d7e8d0
    if (!retval) {
Packit d7e8d0
      if (write(fd, "\n", 1) < 0) {
Packit d7e8d0
        err_status = gpgme_error_from_syserror ();
Packit d7e8d0
        _gpg_raise_exception (err_status);
Packit d7e8d0
      }
Packit d7e8d0
    } else {
Packit d7e8d0
      char *buf;
Packit d7e8d0
      size_t len;
Packit d7e8d0
      if (PyBytes_Check(retval))
Packit d7e8d0
        buf = PyBytes_AsString(retval), len = PyBytes_Size(retval);
Packit d7e8d0
      else if (PyUnicode_Check(retval))
Packit d7e8d0
        {
Packit d7e8d0
          Py_ssize_t ssize;
Packit d7e8d0
          encoded = PyUnicode_AsUTF8String(retval);
Packit d7e8d0
          if (encoded == NULL)
Packit d7e8d0
            {
Packit d7e8d0
              err_status = gpg_error(GPG_ERR_GENERAL);
Packit d7e8d0
              goto leave;
Packit d7e8d0
            }
Packit d7e8d0
          if (PyBytes_AsStringAndSize(encoded, &buf, &ssize) == -1)
Packit d7e8d0
            {
Packit d7e8d0
              err_status = gpg_error(GPG_ERR_GENERAL);
Packit d7e8d0
              goto leave;
Packit d7e8d0
            }
Packit d7e8d0
          assert (! buf || ssize >= 0);
Packit d7e8d0
          len = (size_t) ssize;
Packit d7e8d0
        }
Packit d7e8d0
      else
Packit d7e8d0
        {
Packit d7e8d0
          PyErr_Format(PyExc_TypeError,
Packit d7e8d0
                       "expected str or bytes from passphrase callback, got %s",
Packit d7e8d0
                       retval->ob_type->tp_name);
Packit d7e8d0
          err_status = gpg_error(GPG_ERR_GENERAL);
Packit d7e8d0
          goto leave;
Packit d7e8d0
        }
Packit d7e8d0
Packit d7e8d0
      if (write(fd, buf, len) < 0) {
Packit d7e8d0
        err_status = gpgme_error_from_syserror ();
Packit d7e8d0
        _gpg_raise_exception (err_status);
Packit d7e8d0
      }
Packit d7e8d0
      if (! err_status && write(fd, "\n", 1) < 0) {
Packit d7e8d0
        err_status = gpgme_error_from_syserror ();
Packit d7e8d0
        _gpg_raise_exception (err_status);
Packit d7e8d0
      }
Packit d7e8d0
Packit d7e8d0
      Py_DECREF(retval);
Packit d7e8d0
    }
Packit d7e8d0
  }
Packit d7e8d0
Packit d7e8d0
 leave:
Packit d7e8d0
  if (err_status)
Packit d7e8d0
    _gpg_stash_callback_exception(self);
Packit d7e8d0
Packit d7e8d0
  Py_XDECREF(encoded);
Packit d7e8d0
  PyGILState_Release(state);
Packit d7e8d0
  return err_status;
Packit d7e8d0
}
Packit d7e8d0
Packit d7e8d0
PyObject *
Packit d7e8d0
gpg_set_passphrase_cb(PyObject *self, PyObject *cb) {
Packit d7e8d0
  PyGILState_STATE state = PyGILState_Ensure();
Packit d7e8d0
  PyObject *wrapped;
Packit d7e8d0
  gpgme_ctx_t ctx;
Packit d7e8d0
Packit d7e8d0
  wrapped = PyObject_GetAttrString(self, "wrapped");
Packit d7e8d0
  if (wrapped == NULL)
Packit d7e8d0
    {
Packit d7e8d0
      assert (PyErr_Occurred ());
Packit d7e8d0
      PyGILState_Release(state);
Packit d7e8d0
      return NULL;
Packit d7e8d0
    }
Packit d7e8d0
Packit d7e8d0
  ctx = _gpg_unwrap_gpgme_ctx_t(wrapped);
Packit d7e8d0
  Py_DECREF(wrapped);
Packit d7e8d0
  if (ctx == NULL)
Packit d7e8d0
    {
Packit d7e8d0
      if (cb == Py_None)
Packit d7e8d0
        goto out;
Packit d7e8d0
      else
Packit d7e8d0
        return PyErr_Format(PyExc_RuntimeError, "wrapped is NULL");
Packit d7e8d0
    }
Packit d7e8d0
Packit d7e8d0
  if (cb == Py_None) {
Packit d7e8d0
    gpgme_set_passphrase_cb(ctx, NULL, NULL);
Packit d7e8d0
    PyObject_SetAttrString(self, "_passphrase_cb", Py_None);
Packit d7e8d0
    goto out;
Packit d7e8d0
  }
Packit d7e8d0
Packit d7e8d0
  if (! PyTuple_Check(cb))
Packit d7e8d0
    return PyErr_Format(PyExc_TypeError, "cb must be a tuple");
Packit d7e8d0
  if (PyTuple_Size(cb) != 2 && PyTuple_Size(cb) != 3)
Packit d7e8d0
    return PyErr_Format(PyExc_TypeError,
Packit d7e8d0
                        "cb must be a tuple of size 2 or 3");
Packit d7e8d0
Packit d7e8d0
  gpgme_set_passphrase_cb(ctx, (gpgme_passphrase_cb_t) pyPassphraseCb,
Packit d7e8d0
                          (void *) cb);
Packit d7e8d0
  PyObject_SetAttrString(self, "_passphrase_cb", cb);
Packit d7e8d0
Packit d7e8d0
 out:
Packit d7e8d0
  Py_INCREF(Py_None);
Packit d7e8d0
  PyGILState_Release(state);
Packit d7e8d0
  return Py_None;
Packit d7e8d0
}
Packit d7e8d0
Packit d7e8d0
static void pyProgressCb(void *hook, const char *what, int type, int current,
Packit d7e8d0
			 int total) {
Packit d7e8d0
  PyGILState_STATE state = PyGILState_Ensure();
Packit d7e8d0
  PyObject *func = NULL, *dataarg = NULL, *args = NULL, *retval = NULL;
Packit d7e8d0
  PyObject *pyhook = (PyObject *) hook;
Packit d7e8d0
  PyObject *self = NULL;
Packit d7e8d0
Packit d7e8d0
  assert (PyTuple_Check(pyhook));
Packit d7e8d0
  assert (PyTuple_Size(pyhook) == 2 || PyTuple_Size(pyhook) == 3);
Packit d7e8d0
  self = PyTuple_GetItem(pyhook, 0);
Packit d7e8d0
  func = PyTuple_GetItem(pyhook, 1);
Packit d7e8d0
  if (PyTuple_Size(pyhook) == 3) {
Packit d7e8d0
    dataarg = PyTuple_GetItem(pyhook, 2);
Packit d7e8d0
    args = PyTuple_New(5);
Packit d7e8d0
  } else {
Packit d7e8d0
    args = PyTuple_New(4);
Packit d7e8d0
  }
Packit d7e8d0
Packit d7e8d0
  PyTuple_SetItem(args, 0, PyUnicode_DecodeUTF8(what, strlen (what),
Packit d7e8d0
                                                "strict"));
Packit d7e8d0
  if (PyErr_Occurred()) {
Packit d7e8d0
    _gpg_stash_callback_exception(self);
Packit d7e8d0
    Py_DECREF(args);
Packit d7e8d0
    PyGILState_Release(state);
Packit d7e8d0
    return;
Packit d7e8d0
  }
Packit d7e8d0
  PyTuple_SetItem(args, 1, PyLong_FromLong((long) type));
Packit d7e8d0
  PyTuple_SetItem(args, 2, PyLong_FromLong((long) current));
Packit d7e8d0
  PyTuple_SetItem(args, 3, PyLong_FromLong((long) total));
Packit d7e8d0
  if (dataarg) {
Packit d7e8d0
    Py_INCREF(dataarg);		/* Because GetItem doesn't give a ref but SetItem taketh away */
Packit d7e8d0
    PyTuple_SetItem(args, 4, dataarg);
Packit d7e8d0
  }
Packit d7e8d0
Packit d7e8d0
  retval = PyObject_CallObject(func, args);
Packit d7e8d0
  if (PyErr_Occurred())
Packit d7e8d0
    _gpg_stash_callback_exception(self);
Packit d7e8d0
  Py_DECREF(args);
Packit d7e8d0
  Py_XDECREF(retval);
Packit d7e8d0
  PyGILState_Release(state);
Packit d7e8d0
}
Packit d7e8d0
Packit d7e8d0
PyObject *
Packit d7e8d0
gpg_set_progress_cb(PyObject *self, PyObject *cb) {
Packit d7e8d0
  PyGILState_STATE state = PyGILState_Ensure();
Packit d7e8d0
  PyObject *wrapped;
Packit d7e8d0
  gpgme_ctx_t ctx;
Packit d7e8d0
Packit d7e8d0
  wrapped = PyObject_GetAttrString(self, "wrapped");
Packit d7e8d0
  if (wrapped == NULL)
Packit d7e8d0
    {
Packit d7e8d0
      assert (PyErr_Occurred ());
Packit d7e8d0
      PyGILState_Release(state);
Packit d7e8d0
      return NULL;
Packit d7e8d0
    }
Packit d7e8d0
Packit d7e8d0
  ctx = _gpg_unwrap_gpgme_ctx_t(wrapped);
Packit d7e8d0
  Py_DECREF(wrapped);
Packit d7e8d0
  if (ctx == NULL)
Packit d7e8d0
    {
Packit d7e8d0
      if (cb == Py_None)
Packit d7e8d0
        goto out;
Packit d7e8d0
      else
Packit d7e8d0
        return PyErr_Format(PyExc_RuntimeError, "wrapped is NULL");
Packit d7e8d0
    }
Packit d7e8d0
Packit d7e8d0
  if (cb == Py_None) {
Packit d7e8d0
    gpgme_set_progress_cb(ctx, NULL, NULL);
Packit d7e8d0
    PyObject_SetAttrString(self, "_progress_cb", Py_None);
Packit d7e8d0
    goto out;
Packit d7e8d0
  }
Packit d7e8d0
Packit d7e8d0
  if (! PyTuple_Check(cb))
Packit d7e8d0
    return PyErr_Format(PyExc_TypeError, "cb must be a tuple");
Packit d7e8d0
  if (PyTuple_Size(cb) != 2 && PyTuple_Size(cb) != 3)
Packit d7e8d0
    return PyErr_Format(PyExc_TypeError,
Packit d7e8d0
                        "cb must be a tuple of size 2 or 3");
Packit d7e8d0
Packit d7e8d0
  gpgme_set_progress_cb(ctx, (gpgme_progress_cb_t) pyProgressCb, (void *) cb);
Packit d7e8d0
  PyObject_SetAttrString(self, "_progress_cb", cb);
Packit d7e8d0
Packit d7e8d0
 out:
Packit d7e8d0
  Py_INCREF(Py_None);
Packit d7e8d0
  PyGILState_Release(state);
Packit d7e8d0
  return Py_None;
Packit d7e8d0
}
Packit d7e8d0

Packit d7e8d0
/* Status callbacks.  */
Packit d7e8d0
static gpgme_error_t pyStatusCb(void *hook, const char *keyword,
Packit d7e8d0
                                const char *args) {
Packit d7e8d0
  PyGILState_STATE state = PyGILState_Ensure();
Packit d7e8d0
  gpgme_error_t err = 0;
Packit d7e8d0
  PyObject *pyhook = (PyObject *) hook;
Packit d7e8d0
  PyObject *self = NULL;
Packit d7e8d0
  PyObject *func = NULL;
Packit d7e8d0
  PyObject *dataarg = NULL;
Packit d7e8d0
  PyObject *pyargs = NULL;
Packit d7e8d0
  PyObject *retval = NULL;
Packit d7e8d0
Packit d7e8d0
  assert (PyTuple_Check(pyhook));
Packit d7e8d0
  assert (PyTuple_Size(pyhook) == 2 || PyTuple_Size(pyhook) == 3);
Packit d7e8d0
  self = PyTuple_GetItem(pyhook, 0);
Packit d7e8d0
  func = PyTuple_GetItem(pyhook, 1);
Packit d7e8d0
  if (PyTuple_Size(pyhook) == 3) {
Packit d7e8d0
    dataarg = PyTuple_GetItem(pyhook, 2);
Packit d7e8d0
    pyargs = PyTuple_New(3);
Packit d7e8d0
  } else {
Packit d7e8d0
    pyargs = PyTuple_New(2);
Packit d7e8d0
  }
Packit d7e8d0
Packit d7e8d0
  if (keyword)
Packit d7e8d0
    PyTuple_SetItem(pyargs, 0, PyUnicode_DecodeUTF8(keyword, strlen (keyword),
Packit d7e8d0
                                                    "strict"));
Packit d7e8d0
  else
Packit d7e8d0
    {
Packit d7e8d0
      Py_INCREF(Py_None);
Packit d7e8d0
      PyTuple_SetItem(pyargs, 0, Py_None);
Packit d7e8d0
    }
Packit d7e8d0
  PyTuple_SetItem(pyargs, 1, PyUnicode_DecodeUTF8(args, strlen (args),
Packit d7e8d0
                                                "strict"));
Packit d7e8d0
  if (PyErr_Occurred()) {
Packit d7e8d0
    err = gpg_error(GPG_ERR_GENERAL);
Packit d7e8d0
    Py_DECREF(pyargs);
Packit d7e8d0
    goto leave;
Packit d7e8d0
  }
Packit d7e8d0
Packit d7e8d0
  if (dataarg) {
Packit d7e8d0
    Py_INCREF(dataarg);
Packit d7e8d0
    PyTuple_SetItem(pyargs, 2, dataarg);
Packit d7e8d0
  }
Packit d7e8d0
Packit d7e8d0
  retval = PyObject_CallObject(func, pyargs);
Packit d7e8d0
  if (PyErr_Occurred())
Packit d7e8d0
    err = _gpg_exception2code();
Packit d7e8d0
  Py_DECREF(pyargs);
Packit d7e8d0
  Py_XDECREF(retval);
Packit d7e8d0
Packit d7e8d0
 leave:
Packit d7e8d0
  if (err)
Packit d7e8d0
    _gpg_stash_callback_exception(self);
Packit d7e8d0
  PyGILState_Release(state);
Packit d7e8d0
  return err;
Packit d7e8d0
}
Packit d7e8d0
Packit d7e8d0
PyObject *
Packit d7e8d0
gpg_set_status_cb(PyObject *self, PyObject *cb) {
Packit d7e8d0
  PyGILState_STATE state = PyGILState_Ensure();
Packit d7e8d0
  PyObject *wrapped;
Packit d7e8d0
  gpgme_ctx_t ctx;
Packit d7e8d0
Packit d7e8d0
  wrapped = PyObject_GetAttrString(self, "wrapped");
Packit d7e8d0
  if (wrapped == NULL)
Packit d7e8d0
    {
Packit d7e8d0
      assert (PyErr_Occurred ());
Packit d7e8d0
      PyGILState_Release(state);
Packit d7e8d0
      return NULL;
Packit d7e8d0
    }
Packit d7e8d0
Packit d7e8d0
  ctx = _gpg_unwrap_gpgme_ctx_t(wrapped);
Packit d7e8d0
  Py_DECREF(wrapped);
Packit d7e8d0
  if (ctx == NULL)
Packit d7e8d0
    {
Packit d7e8d0
      if (cb == Py_None)
Packit d7e8d0
        goto out;
Packit d7e8d0
      else
Packit d7e8d0
        return PyErr_Format(PyExc_RuntimeError, "wrapped is NULL");
Packit d7e8d0
    }
Packit d7e8d0
Packit d7e8d0
  if (cb == Py_None) {
Packit d7e8d0
    gpgme_set_status_cb(ctx, NULL, NULL);
Packit d7e8d0
    PyObject_SetAttrString(self, "_status_cb", Py_None);
Packit d7e8d0
    goto out;
Packit d7e8d0
  }
Packit d7e8d0
Packit d7e8d0
  if (! PyTuple_Check(cb))
Packit d7e8d0
    return PyErr_Format(PyExc_TypeError, "cb must be a tuple");
Packit d7e8d0
  if (PyTuple_Size(cb) != 2 && PyTuple_Size(cb) != 3)
Packit d7e8d0
    return PyErr_Format(PyExc_TypeError,
Packit d7e8d0
                        "cb must be a tuple of size 2 or 3");
Packit d7e8d0
Packit d7e8d0
  gpgme_set_status_cb(ctx, (gpgme_status_cb_t) pyStatusCb, (void *) cb);
Packit d7e8d0
  PyObject_SetAttrString(self, "_status_cb", cb);
Packit d7e8d0
Packit d7e8d0
 out:
Packit d7e8d0
  Py_INCREF(Py_None);
Packit d7e8d0
  PyGILState_Release(state);
Packit d7e8d0
  return Py_None;
Packit d7e8d0
}
Packit d7e8d0
Packit d7e8d0

Packit d7e8d0
Packit d7e8d0
/* Interact callbacks.  */
Packit d7e8d0
gpgme_error_t
Packit d7e8d0
_gpg_interact_cb(void *opaque, const char *keyword,
Packit d7e8d0
                  const char *args, int fd)
Packit d7e8d0
{
Packit d7e8d0
  PyGILState_STATE state = PyGILState_Ensure();
Packit d7e8d0
  PyObject *func = NULL, *dataarg = NULL, *pyargs = NULL, *retval = NULL;
Packit d7e8d0
  PyObject *py_keyword;
Packit d7e8d0
  PyObject *pyopaque = (PyObject *) opaque;
Packit d7e8d0
  gpgme_error_t err_status = 0;
Packit d7e8d0
  PyObject *self = NULL;
Packit d7e8d0
Packit d7e8d0
  _gpg_exception_init();
Packit d7e8d0
Packit d7e8d0
  assert (PyTuple_Check(pyopaque));
Packit d7e8d0
  assert (PyTuple_Size(pyopaque) == 2 || PyTuple_Size(pyopaque) == 3);
Packit d7e8d0
  self = PyTuple_GetItem(pyopaque, 0);
Packit d7e8d0
  func = PyTuple_GetItem(pyopaque, 1);
Packit d7e8d0
  if (PyTuple_Size(pyopaque) == 3) {
Packit d7e8d0
    dataarg = PyTuple_GetItem(pyopaque, 2);
Packit d7e8d0
    pyargs = PyTuple_New(3);
Packit d7e8d0
  } else {
Packit d7e8d0
    pyargs = PyTuple_New(2);
Packit d7e8d0
  }
Packit d7e8d0
Packit d7e8d0
  if (keyword)
Packit d7e8d0
    py_keyword = PyUnicode_FromString(keyword);
Packit d7e8d0
  else
Packit d7e8d0
    {
Packit d7e8d0
      Py_INCREF(Py_None);
Packit d7e8d0
      py_keyword = Py_None;
Packit d7e8d0
    }
Packit d7e8d0
Packit d7e8d0
  PyTuple_SetItem(pyargs, 0, py_keyword);
Packit d7e8d0
  PyTuple_SetItem(pyargs, 1, PyUnicode_FromString(args));
Packit d7e8d0
  if (dataarg) {
Packit d7e8d0
    Py_INCREF(dataarg);		/* Because GetItem doesn't give a ref but SetItem taketh away */
Packit d7e8d0
    PyTuple_SetItem(pyargs, 2, dataarg);
Packit d7e8d0
  }
Packit d7e8d0
Packit d7e8d0
  retval = PyObject_CallObject(func, pyargs);
Packit d7e8d0
  Py_DECREF(pyargs);
Packit d7e8d0
  if (PyErr_Occurred()) {
Packit d7e8d0
    err_status = _gpg_exception2code();
Packit d7e8d0
  } else {
Packit d7e8d0
    if (fd>=0 && retval && PyUnicode_Check(retval)) {
Packit d7e8d0
      PyObject *encoded = NULL;
Packit d7e8d0
      char *buffer;
Packit d7e8d0
      Py_ssize_t size;
Packit d7e8d0
Packit d7e8d0
      encoded = PyUnicode_AsUTF8String(retval);
Packit d7e8d0
      if (encoded == NULL)
Packit d7e8d0
        {
Packit d7e8d0
          err_status = gpg_error(GPG_ERR_GENERAL);
Packit d7e8d0
          goto leave;
Packit d7e8d0
        }
Packit d7e8d0
      if (PyBytes_AsStringAndSize(encoded, &buffer, &size) == -1)
Packit d7e8d0
        {
Packit d7e8d0
          Py_DECREF(encoded);
Packit d7e8d0
          err_status = gpg_error(GPG_ERR_GENERAL);
Packit d7e8d0
          goto leave;
Packit d7e8d0
        }
Packit d7e8d0
Packit d7e8d0
      if (write(fd, buffer, size) < 0) {
Packit d7e8d0
        err_status = gpgme_error_from_syserror ();
Packit d7e8d0
        _gpg_raise_exception (err_status);
Packit d7e8d0
      }
Packit d7e8d0
      if (! err_status && write(fd, "\n", 1) < 0) {
Packit d7e8d0
        err_status = gpgme_error_from_syserror ();
Packit d7e8d0
        _gpg_raise_exception (err_status);
Packit d7e8d0
      }
Packit d7e8d0
      Py_DECREF(encoded);
Packit d7e8d0
    }
Packit d7e8d0
  }
Packit d7e8d0
 leave:
Packit d7e8d0
  if (err_status)
Packit d7e8d0
    _gpg_stash_callback_exception(self);
Packit d7e8d0
Packit d7e8d0
  Py_XDECREF(retval);
Packit d7e8d0
  PyGILState_Release(state);
Packit d7e8d0
  return err_status;
Packit d7e8d0
}
Packit d7e8d0
Packit d7e8d0

Packit d7e8d0
Packit d7e8d0
/* Data callbacks.  */
Packit d7e8d0
Packit d7e8d0
/* Read up to SIZE bytes into buffer BUFFER from the data object with
Packit d7e8d0
   the handle HOOK.  Return the number of characters read, 0 on EOF
Packit d7e8d0
   and -1 on error.  If an error occurs, errno is set.  */
Packit d7e8d0
static ssize_t pyDataReadCb(void *hook, void *buffer, size_t size)
Packit d7e8d0
{
Packit d7e8d0
  PyGILState_STATE state = PyGILState_Ensure();
Packit d7e8d0
  ssize_t result;
Packit d7e8d0
  PyObject *pyhook = (PyObject *) hook;
Packit d7e8d0
  PyObject *self = NULL;
Packit d7e8d0
  PyObject *func = NULL;
Packit d7e8d0
  PyObject *dataarg = NULL;
Packit d7e8d0
  PyObject *pyargs = NULL;
Packit d7e8d0
  PyObject *retval = NULL;
Packit d7e8d0
Packit d7e8d0
  assert (PyTuple_Check(pyhook));
Packit d7e8d0
  assert (PyTuple_Size(pyhook) == 5 || PyTuple_Size(pyhook) == 6);
Packit d7e8d0
Packit d7e8d0
  self = PyTuple_GetItem(pyhook, 0);
Packit d7e8d0
  func = PyTuple_GetItem(pyhook, 1);
Packit d7e8d0
  if (PyTuple_Size(pyhook) == 6) {
Packit d7e8d0
    dataarg = PyTuple_GetItem(pyhook, 5);
Packit d7e8d0
    pyargs = PyTuple_New(2);
Packit d7e8d0
  } else {
Packit d7e8d0
    pyargs = PyTuple_New(1);
Packit d7e8d0
  }
Packit d7e8d0
Packit d7e8d0
  PyTuple_SetItem(pyargs, 0, PyLong_FromSize_t(size));
Packit d7e8d0
  if (dataarg) {
Packit d7e8d0
    Py_INCREF(dataarg);
Packit d7e8d0
    PyTuple_SetItem(pyargs, 1, dataarg);
Packit d7e8d0
  }
Packit d7e8d0
Packit d7e8d0
  retval = PyObject_CallObject(func, pyargs);
Packit d7e8d0
  Py_DECREF(pyargs);
Packit d7e8d0
  if (PyErr_Occurred()) {
Packit d7e8d0
    _gpg_stash_callback_exception(self);
Packit d7e8d0
    result = -1;
Packit d7e8d0
    goto leave;
Packit d7e8d0
  }
Packit d7e8d0
Packit d7e8d0
  if (! PyBytes_Check(retval)) {
Packit d7e8d0
    PyErr_Format(PyExc_TypeError,
Packit d7e8d0
                 "expected bytes from read callback, got %s",
Packit d7e8d0
                 retval->ob_type->tp_name);
Packit d7e8d0
    _gpg_stash_callback_exception(self);
Packit d7e8d0
    result = -1;
Packit d7e8d0
    goto leave;
Packit d7e8d0
  }
Packit d7e8d0
Packit d7e8d0
  if (PyBytes_Size(retval) > size) {
Packit d7e8d0
    PyErr_Format(PyExc_TypeError,
Packit d7e8d0
                 "expected %zu bytes from read callback, got %zu",
Packit d7e8d0
                 size, PyBytes_Size(retval));
Packit d7e8d0
    _gpg_stash_callback_exception(self);
Packit d7e8d0
    result = -1;
Packit d7e8d0
    goto leave;
Packit d7e8d0
  }
Packit d7e8d0
Packit d7e8d0
  memcpy(buffer, PyBytes_AsString(retval), PyBytes_Size(retval));
Packit d7e8d0
  result = PyBytes_Size(retval);
Packit d7e8d0
Packit d7e8d0
 leave:
Packit d7e8d0
  Py_XDECREF(retval);
Packit d7e8d0
  PyGILState_Release(state);
Packit d7e8d0
  return result;
Packit d7e8d0
}
Packit d7e8d0
Packit d7e8d0
/* Write up to SIZE bytes from buffer BUFFER to the data object with
Packit d7e8d0
   the handle HOOK.  Return the number of characters written, or -1
Packit d7e8d0
   on error.  If an error occurs, errno is set.  */
Packit d7e8d0
static ssize_t pyDataWriteCb(void *hook, const void *buffer, size_t size)
Packit d7e8d0
{
Packit d7e8d0
  PyGILState_STATE state = PyGILState_Ensure();
Packit d7e8d0
  ssize_t result;
Packit d7e8d0
  PyObject *pyhook = (PyObject *) hook;
Packit d7e8d0
  PyObject *self = NULL;
Packit d7e8d0
  PyObject *func = NULL;
Packit d7e8d0
  PyObject *dataarg = NULL;
Packit d7e8d0
  PyObject *pyargs = NULL;
Packit d7e8d0
  PyObject *retval = NULL;
Packit d7e8d0
Packit d7e8d0
  assert (PyTuple_Check(pyhook));
Packit d7e8d0
  assert (PyTuple_Size(pyhook) == 5 || PyTuple_Size(pyhook) == 6);
Packit d7e8d0
Packit d7e8d0
  self = PyTuple_GetItem(pyhook, 0);
Packit d7e8d0
  func = PyTuple_GetItem(pyhook, 2);
Packit d7e8d0
  if (PyTuple_Size(pyhook) == 6) {
Packit d7e8d0
    dataarg = PyTuple_GetItem(pyhook, 5);
Packit d7e8d0
    pyargs = PyTuple_New(2);
Packit d7e8d0
  } else {
Packit d7e8d0
    pyargs = PyTuple_New(1);
Packit d7e8d0
  }
Packit d7e8d0
Packit d7e8d0
  PyTuple_SetItem(pyargs, 0, PyBytes_FromStringAndSize(buffer, size));
Packit d7e8d0
  if (dataarg) {
Packit d7e8d0
    Py_INCREF(dataarg);
Packit d7e8d0
    PyTuple_SetItem(pyargs, 1, dataarg);
Packit d7e8d0
  }
Packit d7e8d0
Packit d7e8d0
  retval = PyObject_CallObject(func, pyargs);
Packit d7e8d0
  Py_DECREF(pyargs);
Packit d7e8d0
  if (PyErr_Occurred()) {
Packit d7e8d0
    _gpg_stash_callback_exception(self);
Packit d7e8d0
    result = -1;
Packit d7e8d0
    goto leave;
Packit d7e8d0
  }
Packit d7e8d0
Packit d7e8d0
#if PY_MAJOR_VERSION < 3
Packit d7e8d0
  if (PyInt_Check(retval))
Packit d7e8d0
    result = PyInt_AsSsize_t(retval);
Packit d7e8d0
  else
Packit d7e8d0
#endif
Packit d7e8d0
  if (PyLong_Check(retval))
Packit d7e8d0
    result = PyLong_AsSsize_t(retval);
Packit d7e8d0
  else {
Packit d7e8d0
    PyErr_Format(PyExc_TypeError,
Packit d7e8d0
                 "expected int from write callback, got %s",
Packit d7e8d0
                 retval->ob_type->tp_name);
Packit d7e8d0
    _gpg_stash_callback_exception(self);
Packit d7e8d0
    result = -1;
Packit d7e8d0
  }
Packit d7e8d0
Packit d7e8d0
 leave:
Packit d7e8d0
  Py_XDECREF(retval);
Packit d7e8d0
  PyGILState_Release(state);
Packit d7e8d0
  return result;
Packit d7e8d0
}
Packit d7e8d0
Packit d7e8d0
/* Set the current position from where the next read or write starts
Packit d7e8d0
   in the data object with the handle HOOK to OFFSET, relativ to
Packit d7e8d0
   WHENCE.  Returns the new offset in bytes from the beginning of the
Packit d7e8d0
   data object.  */
Packit d7e8d0
static off_t pyDataSeekCb(void *hook, off_t offset, int whence)
Packit d7e8d0
{
Packit d7e8d0
  PyGILState_STATE state = PyGILState_Ensure();
Packit d7e8d0
  off_t result;
Packit d7e8d0
  PyObject *pyhook = (PyObject *) hook;
Packit d7e8d0
  PyObject *self = NULL;
Packit d7e8d0
  PyObject *func = NULL;
Packit d7e8d0
  PyObject *dataarg = NULL;
Packit d7e8d0
  PyObject *pyargs = NULL;
Packit d7e8d0
  PyObject *retval = NULL;
Packit d7e8d0
Packit d7e8d0
  assert (PyTuple_Check(pyhook));
Packit d7e8d0
  assert (PyTuple_Size(pyhook) == 5 || PyTuple_Size(pyhook) == 6);
Packit d7e8d0
Packit d7e8d0
  self = PyTuple_GetItem(pyhook, 0);
Packit d7e8d0
  func = PyTuple_GetItem(pyhook, 3);
Packit d7e8d0
  if (PyTuple_Size(pyhook) == 6) {
Packit d7e8d0
    dataarg = PyTuple_GetItem(pyhook, 5);
Packit d7e8d0
    pyargs = PyTuple_New(3);
Packit d7e8d0
  } else {
Packit d7e8d0
    pyargs = PyTuple_New(2);
Packit d7e8d0
  }
Packit d7e8d0
Packit d7e8d0
#if defined(_FILE_OFFSET_BITS) && _FILE_OFFSET_BITS == 64
Packit d7e8d0
  PyTuple_SetItem(pyargs, 0, PyLong_FromLongLong((long long) offset));
Packit d7e8d0
#else
Packit d7e8d0
  PyTuple_SetItem(pyargs, 0, PyLong_FromLong((long) offset));
Packit d7e8d0
#endif
Packit d7e8d0
  PyTuple_SetItem(pyargs, 1, PyLong_FromLong((long) whence));
Packit d7e8d0
  if (dataarg) {
Packit d7e8d0
    Py_INCREF(dataarg);
Packit d7e8d0
    PyTuple_SetItem(pyargs, 2, dataarg);
Packit d7e8d0
  }
Packit d7e8d0
Packit d7e8d0
  retval = PyObject_CallObject(func, pyargs);
Packit d7e8d0
  Py_DECREF(pyargs);
Packit d7e8d0
  if (PyErr_Occurred()) {
Packit d7e8d0
    _gpg_stash_callback_exception(self);
Packit d7e8d0
    result = -1;
Packit d7e8d0
    goto leave;
Packit d7e8d0
  }
Packit d7e8d0
Packit d7e8d0
#if PY_MAJOR_VERSION < 3
Packit d7e8d0
  if (PyInt_Check(retval))
Packit d7e8d0
    result = PyInt_AsLong(retval);
Packit d7e8d0
  else
Packit d7e8d0
#endif
Packit d7e8d0
  if (PyLong_Check(retval))
Packit d7e8d0
#if defined(_FILE_OFFSET_BITS) && _FILE_OFFSET_BITS == 64
Packit d7e8d0
    result = PyLong_AsLongLong(retval);
Packit d7e8d0
#else
Packit d7e8d0
    result = PyLong_AsLong(retval);
Packit d7e8d0
#endif
Packit d7e8d0
  else {
Packit d7e8d0
    PyErr_Format(PyExc_TypeError,
Packit d7e8d0
                 "expected int from seek callback, got %s",
Packit d7e8d0
                 retval->ob_type->tp_name);
Packit d7e8d0
    _gpg_stash_callback_exception(self);
Packit d7e8d0
    result = -1;
Packit d7e8d0
  }
Packit d7e8d0
Packit d7e8d0
 leave:
Packit d7e8d0
  Py_XDECREF(retval);
Packit d7e8d0
  PyGILState_Release(state);
Packit d7e8d0
  return result;
Packit d7e8d0
}
Packit d7e8d0
Packit d7e8d0
/* Close the data object with the handle HOOK.  */
Packit d7e8d0
static void pyDataReleaseCb(void *hook)
Packit d7e8d0
{
Packit d7e8d0
  PyGILState_STATE state = PyGILState_Ensure();
Packit d7e8d0
  PyObject *pyhook = (PyObject *) hook;
Packit d7e8d0
  PyObject *self = NULL;
Packit d7e8d0
  PyObject *func = NULL;
Packit d7e8d0
  PyObject *dataarg = NULL;
Packit d7e8d0
  PyObject *pyargs = NULL;
Packit d7e8d0
  PyObject *retval = NULL;
Packit d7e8d0
Packit d7e8d0
  assert (PyTuple_Check(pyhook));
Packit d7e8d0
  assert (PyTuple_Size(pyhook) == 5 || PyTuple_Size(pyhook) == 6);
Packit d7e8d0
Packit d7e8d0
  self = PyTuple_GetItem(pyhook, 0);
Packit d7e8d0
  func = PyTuple_GetItem(pyhook, 4);
Packit d7e8d0
  if (PyTuple_Size(pyhook) == 6) {
Packit d7e8d0
    dataarg = PyTuple_GetItem(pyhook, 5);
Packit d7e8d0
    pyargs = PyTuple_New(1);
Packit d7e8d0
  } else {
Packit d7e8d0
    pyargs = PyTuple_New(0);
Packit d7e8d0
  }
Packit d7e8d0
Packit d7e8d0
  if (dataarg) {
Packit d7e8d0
    Py_INCREF(dataarg);
Packit d7e8d0
    PyTuple_SetItem(pyargs, 0, dataarg);
Packit d7e8d0
  }
Packit d7e8d0
Packit d7e8d0
  retval = PyObject_CallObject(func, pyargs);
Packit d7e8d0
  Py_XDECREF(retval);
Packit d7e8d0
  Py_DECREF(pyargs);
Packit d7e8d0
  if (PyErr_Occurred())
Packit d7e8d0
    _gpg_stash_callback_exception(self);
Packit d7e8d0
  PyGILState_Release(state);
Packit d7e8d0
}
Packit d7e8d0
Packit d7e8d0
PyObject *
Packit d7e8d0
gpg_data_new_from_cbs(PyObject *self,
Packit d7e8d0
                       PyObject *pycbs,
Packit d7e8d0
                       gpgme_data_t *r_data)
Packit d7e8d0
{
Packit d7e8d0
  PyGILState_STATE state = PyGILState_Ensure();
Packit d7e8d0
  static struct gpgme_data_cbs cbs = {
Packit d7e8d0
    pyDataReadCb,
Packit d7e8d0
    pyDataWriteCb,
Packit d7e8d0
    pyDataSeekCb,
Packit d7e8d0
    pyDataReleaseCb,
Packit d7e8d0
  };
Packit d7e8d0
  gpgme_error_t err;
Packit d7e8d0
Packit d7e8d0
  if (! PyTuple_Check(pycbs))
Packit d7e8d0
    return PyErr_Format(PyExc_TypeError, "pycbs must be a tuple");
Packit d7e8d0
  if (PyTuple_Size(pycbs) != 5 && PyTuple_Size(pycbs) != 6)
Packit d7e8d0
    return PyErr_Format(PyExc_TypeError,
Packit d7e8d0
                        "pycbs must be a tuple of size 5 or 6");
Packit d7e8d0
Packit d7e8d0
  err = gpgme_data_new_from_cbs(r_data, &cbs, (void *) pycbs);
Packit d7e8d0
  if (err)
Packit d7e8d0
    return _gpg_raise_exception(err);
Packit d7e8d0
Packit d7e8d0
  PyObject_SetAttrString(self, "_data_cbs", pycbs);
Packit d7e8d0
Packit d7e8d0
  Py_INCREF(Py_None);
Packit d7e8d0
  PyGILState_Release(state);
Packit d7e8d0
  return Py_None;
Packit d7e8d0
}
Packit d7e8d0
Packit d7e8d0

Packit d7e8d0
Packit d7e8d0
/* The assuan callbacks.  */
Packit d7e8d0
Packit d7e8d0
gpgme_error_t
Packit d7e8d0
_gpg_assuan_data_cb (void *hook, const void *data, size_t datalen)
Packit d7e8d0
{
Packit d7e8d0
  PyGILState_STATE state = PyGILState_Ensure();
Packit d7e8d0
  gpgme_error_t err = 0;
Packit d7e8d0
  PyObject *pyhook = (PyObject *) hook;
Packit d7e8d0
  PyObject *self = NULL;
Packit d7e8d0
  PyObject *func = NULL;
Packit d7e8d0
  PyObject *py_data = NULL;
Packit d7e8d0
  PyObject *retval = NULL;
Packit d7e8d0
Packit d7e8d0
  assert (PyTuple_Check(pyhook));
Packit d7e8d0
  assert (PyTuple_Size(pyhook) == 2);
Packit d7e8d0
  self = PyTuple_GetItem(pyhook, 0);
Packit d7e8d0
  func = PyTuple_GetItem(pyhook, 1);
Packit d7e8d0
  assert (PyCallable_Check(func));
Packit d7e8d0
Packit d7e8d0
  py_data = PyBytes_FromStringAndSize(data, datalen);
Packit d7e8d0
  if (py_data == NULL)
Packit d7e8d0
    {
Packit d7e8d0
      err = _gpg_exception2code();
Packit d7e8d0
      goto leave;
Packit d7e8d0
    }
Packit d7e8d0
Packit d7e8d0
  retval = PyObject_CallFunctionObjArgs(func, py_data, NULL);
Packit d7e8d0
  if (PyErr_Occurred())
Packit d7e8d0
    err = _gpg_exception2code();
Packit d7e8d0
  Py_DECREF(py_data);
Packit d7e8d0
  Py_XDECREF(retval);
Packit d7e8d0
Packit d7e8d0
 leave:
Packit d7e8d0
  if (err)
Packit d7e8d0
    _gpg_stash_callback_exception(self);
Packit d7e8d0
  PyGILState_Release(state);
Packit d7e8d0
  return err;
Packit d7e8d0
}
Packit d7e8d0
Packit d7e8d0
gpgme_error_t
Packit d7e8d0
_gpg_assuan_inquire_cb (void *hook, const char *name, const char *args,
Packit d7e8d0
                         gpgme_data_t *r_data)
Packit d7e8d0
{
Packit d7e8d0
  PyGILState_STATE state = PyGILState_Ensure();
Packit d7e8d0
  gpgme_error_t err = 0;
Packit d7e8d0
  PyObject *pyhook = (PyObject *) hook;
Packit d7e8d0
  PyObject *self = NULL;
Packit d7e8d0
  PyObject *func = NULL;
Packit d7e8d0
  PyObject *py_name = NULL;
Packit d7e8d0
  PyObject *py_args = NULL;
Packit d7e8d0
  PyObject *retval = NULL;
Packit d7e8d0
Packit d7e8d0
  assert (PyTuple_Check(pyhook));
Packit d7e8d0
  assert (PyTuple_Size(pyhook) == 2);
Packit d7e8d0
  self = PyTuple_GetItem(pyhook, 0);
Packit d7e8d0
  func = PyTuple_GetItem(pyhook, 1);
Packit d7e8d0
  assert (PyCallable_Check(func));
Packit d7e8d0
Packit d7e8d0
  py_name = PyUnicode_FromString(name);
Packit d7e8d0
  if (py_name == NULL)
Packit d7e8d0
    {
Packit d7e8d0
      err = _gpg_exception2code();
Packit d7e8d0
      goto leave;
Packit d7e8d0
    }
Packit d7e8d0
Packit d7e8d0
  py_args = PyUnicode_FromString(args);
Packit d7e8d0
  if (py_args == NULL)
Packit d7e8d0
    {
Packit d7e8d0
      err = _gpg_exception2code();
Packit d7e8d0
      goto leave;
Packit d7e8d0
    }
Packit d7e8d0
Packit d7e8d0
  retval = PyObject_CallFunctionObjArgs(func, py_name, py_args, NULL);
Packit d7e8d0
  if (PyErr_Occurred())
Packit d7e8d0
    err = _gpg_exception2code();
Packit d7e8d0
  Py_XDECREF(retval);
Packit d7e8d0
Packit d7e8d0
  /* FIXME: Returning data is not yet implemented.  */
Packit d7e8d0
  *r_data = NULL;
Packit d7e8d0
Packit d7e8d0
 leave:
Packit d7e8d0
  Py_XDECREF(py_name);
Packit d7e8d0
  Py_XDECREF(py_args);
Packit d7e8d0
  if (err)
Packit d7e8d0
    _gpg_stash_callback_exception(self);
Packit d7e8d0
  PyGILState_Release(state);
Packit d7e8d0
  return err;
Packit d7e8d0
}
Packit d7e8d0
Packit d7e8d0
gpgme_error_t
Packit d7e8d0
_gpg_assuan_status_cb (void *hook, const char *status, const char *args)
Packit d7e8d0
{
Packit d7e8d0
  PyGILState_STATE state = PyGILState_Ensure();
Packit d7e8d0
  gpgme_error_t err = 0;
Packit d7e8d0
  PyObject *pyhook = (PyObject *) hook;
Packit d7e8d0
  PyObject *self = NULL;
Packit d7e8d0
  PyObject *func = NULL;
Packit d7e8d0
  PyObject *py_status = NULL;
Packit d7e8d0
  PyObject *py_args = NULL;
Packit d7e8d0
  PyObject *retval = NULL;
Packit d7e8d0
Packit d7e8d0
  assert (PyTuple_Check(pyhook));
Packit d7e8d0
  assert (PyTuple_Size(pyhook) == 2);
Packit d7e8d0
  self = PyTuple_GetItem(pyhook, 0);
Packit d7e8d0
  func = PyTuple_GetItem(pyhook, 1);
Packit d7e8d0
  assert (PyCallable_Check(func));
Packit d7e8d0
Packit d7e8d0
  py_status = PyUnicode_FromString(status);
Packit d7e8d0
  if (py_status == NULL)
Packit d7e8d0
    {
Packit d7e8d0
      err = _gpg_exception2code();
Packit d7e8d0
      goto leave;
Packit d7e8d0
    }
Packit d7e8d0
Packit d7e8d0
  py_args = PyUnicode_FromString(args);
Packit d7e8d0
  if (py_args == NULL)
Packit d7e8d0
    {
Packit d7e8d0
      err = _gpg_exception2code();
Packit d7e8d0
      goto leave;
Packit d7e8d0
    }
Packit d7e8d0
Packit d7e8d0
  retval = PyObject_CallFunctionObjArgs(func, py_status, py_args, NULL);
Packit d7e8d0
  if (PyErr_Occurred())
Packit d7e8d0
    err = _gpg_exception2code();
Packit d7e8d0
  Py_XDECREF(retval);
Packit d7e8d0
Packit d7e8d0
 leave:
Packit d7e8d0
  Py_XDECREF(py_status);
Packit d7e8d0
  Py_XDECREF(py_args);
Packit d7e8d0
  if (err)
Packit d7e8d0
    _gpg_stash_callback_exception(self);
Packit d7e8d0
  PyGILState_Release(state);
Packit d7e8d0
  return err;
Packit d7e8d0
}