Blame lang/python/helpers.c

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