python: Fix import.
[gpgme.git] / lang / python / helpers.c
1 /*
2 # $Id$
3 # Copyright (C) 2004 Igor Belyi <belyi@users.sourceforge.net>
4 # Copyright (C) 2002 John Goerzen <jgoerzen@complete.org>
5 #
6 #    This library is free software; you can redistribute it and/or
7 #    modify it under the terms of the GNU Lesser General Public
8 #    License as published by the Free Software Foundation; either
9 #    version 2.1 of the License, or (at your option) any later version.
10 #
11 #    This library is distributed in the hope that it will be useful,
12 #    but WITHOUT ANY WARRANTY; without even the implied warranty of
13 #    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
14 #    Lesser General Public License for more details.
15 #
16 #    You should have received a copy of the GNU Lesser General Public
17 #    License along with this library; if not, write to the Free Software
18 #    Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307  USA
19 */
20 #include <stdio.h>
21 #include <gpgme.h>
22 #include <stdlib.h>
23 #include <string.h>
24 #include "Python.h"
25 #include "helpers.h"
26
27 static PyObject *GPGMEError = NULL;
28
29 void pygpgme_exception_init(void) {
30   if (GPGMEError == NULL) {
31     PyObject *errors;
32     PyObject *from_list = PyList_New(0);
33     errors = PyImport_ImportModuleLevel("errors", PyEval_GetGlobals(),
34                                         PyEval_GetLocals(), from_list, 1);
35     Py_XDECREF(from_list);
36     if (errors) {
37       GPGMEError=PyDict_GetItemString(PyModule_GetDict(errors), "GPGMEError");
38       Py_XINCREF(GPGMEError);
39     }
40   }
41 }
42
43 gpgme_error_t pygpgme_exception2code(void) {
44   gpgme_error_t err_status = gpg_error(GPG_ERR_GENERAL);
45   if (GPGMEError && PyErr_ExceptionMatches(GPGMEError)) {
46     PyObject *type = 0, *value = 0, *traceback = 0;
47     PyObject *error = 0;
48     PyErr_Fetch(&type, &value, &traceback);
49     PyErr_NormalizeException(&type, &value, &traceback);
50     error = PyObject_GetAttrString(value, "error");
51     err_status = PyLong_AsLong(error);
52     Py_DECREF(error);
53     PyErr_Restore(type, value, traceback);
54   }
55   return err_status;
56 }
57
58 void pygpgme_clear_generic_cb(PyObject **cb) {
59   Py_DECREF(*cb);
60 }
61
62 static gpgme_error_t pyPassphraseCb(void *hook,
63                                     const char *uid_hint,
64                                     const char *passphrase_info,
65                                     int prev_was_bad,
66                                     int fd) {
67   PyObject *pyhook = (PyObject *) hook;
68   PyObject *func = NULL;
69   PyObject *args = NULL;
70   PyObject *retval = NULL;
71   PyObject *dataarg = NULL;
72   gpgme_error_t err_status = 0;
73
74   pygpgme_exception_init();
75
76   if (PyTuple_Check(pyhook)) {
77     func = PyTuple_GetItem(pyhook, 0);
78     dataarg = PyTuple_GetItem(pyhook, 1);
79     args = PyTuple_New(4);
80   } else {
81     func = pyhook;
82     args = PyTuple_New(3);
83   }
84
85   PyTuple_SetItem(args, 0, PyBytes_FromString(uid_hint));
86   PyTuple_SetItem(args, 1, PyBytes_FromString(passphrase_info));
87   PyTuple_SetItem(args, 2, PyBool_FromLong((long)prev_was_bad));
88   if (dataarg) {
89     Py_INCREF(dataarg);         /* Because GetItem doesn't give a ref but SetItem taketh away */
90     PyTuple_SetItem(args, 3, dataarg);
91   }
92
93   retval = PyObject_CallObject(func, args);
94   Py_DECREF(args);
95   if (PyErr_Occurred()) {
96     err_status = pygpgme_exception2code();
97   } else {
98     if (!retval) {
99       write(fd, "\n", 1);
100     } else {
101       write(fd, PyBytes_AsString(retval), PyBytes_Size(retval));
102       write(fd, "\n", 1);
103       Py_DECREF(retval);
104     }
105   }
106
107   return err_status;
108 }
109
110 void pygpgme_set_passphrase_cb(gpgme_ctx_t ctx, PyObject *cb,
111                                PyObject **freelater) {
112   if (cb == Py_None) {
113     gpgme_set_passphrase_cb(ctx, NULL, NULL);
114     return;
115   }
116   Py_INCREF(cb);
117   *freelater = cb;
118   gpgme_set_passphrase_cb(ctx, (gpgme_passphrase_cb_t)pyPassphraseCb, (void *) cb);
119 }
120
121 static void pyProgressCb(void *hook, const char *what, int type, int current,
122                          int total) {
123   PyObject *func = NULL, *dataarg = NULL, *args = NULL, *retval = NULL;
124   PyObject *pyhook = (PyObject *) hook;
125
126   if (PyTuple_Check(pyhook)) {
127     func = PyTuple_GetItem(pyhook, 0);
128     dataarg = PyTuple_GetItem(pyhook, 1);
129     args = PyTuple_New(5);
130   } else {
131     func = pyhook;
132     args = PyTuple_New(4);
133   }
134
135   PyTuple_SetItem(args, 0, PyBytes_FromString(what));
136   PyTuple_SetItem(args, 1, PyLong_FromLong((long) type));
137   PyTuple_SetItem(args, 2, PyLong_FromLong((long) current));
138   PyTuple_SetItem(args, 3, PyLong_FromLong((long) total));
139   if (dataarg) {
140     Py_INCREF(dataarg);         /* Because GetItem doesn't give a ref but SetItem taketh away */
141     PyTuple_SetItem(args, 4, dataarg);
142   }
143
144   retval = PyObject_CallObject(func, args);
145   Py_DECREF(args);
146   Py_XDECREF(retval);
147 }
148
149 void pygpgme_set_progress_cb(gpgme_ctx_t ctx, PyObject *cb, PyObject **freelater){
150   if (cb == Py_None) {
151     gpgme_set_progress_cb(ctx, NULL, NULL);
152     return;
153   }
154   Py_INCREF(cb);
155   *freelater = cb;
156   gpgme_set_progress_cb(ctx, (gpgme_progress_cb_t) pyProgressCb, (void *) cb);
157 }