python: Rename bindings.
[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     errors = PyImport_ImportModule("errors");
33     if (errors) {
34       GPGMEError=PyDict_GetItemString(PyModule_GetDict(errors), "GPGMEError");
35       Py_XINCREF(GPGMEError);
36     }
37   }
38 }
39
40 gpgme_error_t pygpgme_exception2code(void) {
41   gpgme_error_t err_status = gpg_error(GPG_ERR_GENERAL);
42   if (GPGMEError && PyErr_ExceptionMatches(GPGMEError)) {
43     PyObject *type = 0, *value = 0, *traceback = 0;
44     PyObject *error = 0;
45     PyErr_Fetch(&type, &value, &traceback);
46     PyErr_NormalizeException(&type, &value, &traceback);
47     error = PyObject_GetAttrString(value, "error");
48     err_status = PyLong_AsLong(error);
49     Py_DECREF(error);
50     PyErr_Restore(type, value, traceback);
51   }
52   return err_status;
53 }
54
55 void pygpgme_clear_generic_cb(PyObject **cb) {
56   Py_DECREF(*cb);
57 }
58
59 static gpgme_error_t pyPassphraseCb(void *hook,
60                                     const char *uid_hint,
61                                     const char *passphrase_info,
62                                     int prev_was_bad,
63                                     int fd) {
64   PyObject *pyhook = (PyObject *) hook;
65   PyObject *func = NULL;
66   PyObject *args = NULL;
67   PyObject *retval = NULL;
68   PyObject *dataarg = NULL;
69   gpgme_error_t err_status = 0;  
70
71   pygpgme_exception_init();
72
73   if (PyTuple_Check(pyhook)) {
74     func = PyTuple_GetItem(pyhook, 0);
75     dataarg = PyTuple_GetItem(pyhook, 1);
76     args = PyTuple_New(4);
77   } else {
78     func = pyhook;
79     args = PyTuple_New(3);
80   }
81
82   PyTuple_SetItem(args, 0, PyBytes_FromString(uid_hint));
83   PyTuple_SetItem(args, 1, PyBytes_FromString(passphrase_info));
84   PyTuple_SetItem(args, 2, PyBool_FromLong((long)prev_was_bad));
85   if (dataarg) {
86     Py_INCREF(dataarg);         /* Because GetItem doesn't give a ref but SetItem taketh away */
87     PyTuple_SetItem(args, 3, dataarg);
88   }
89
90   retval = PyObject_CallObject(func, args);
91   Py_DECREF(args);
92   if (PyErr_Occurred()) {
93     err_status = pygpgme_exception2code();
94   } else {
95     if (!retval) {
96       write(fd, "\n", 1);
97     } else {
98       write(fd, PyBytes_AsString(retval), PyBytes_Size(retval));
99       write(fd, "\n", 1);
100       Py_DECREF(retval);
101     }
102   }
103
104   return err_status;
105 }
106
107 void pygpgme_set_passphrase_cb(gpgme_ctx_t ctx, PyObject *cb,
108                                PyObject **freelater) {
109   if (cb == Py_None) {
110     gpgme_set_passphrase_cb(ctx, NULL, NULL);
111     return;
112   }
113   Py_INCREF(cb);
114   *freelater = cb;
115   gpgme_set_passphrase_cb(ctx, (gpgme_passphrase_cb_t)pyPassphraseCb, (void *) cb);
116 }
117
118 static void pyProgressCb(void *hook, const char *what, int type, int current,
119                          int total) {
120   PyObject *func = NULL, *dataarg = NULL, *args = NULL, *retval = NULL;
121   PyObject *pyhook = (PyObject *) hook;
122   
123   if (PyTuple_Check(pyhook)) {
124     func = PyTuple_GetItem(pyhook, 0);
125     dataarg = PyTuple_GetItem(pyhook, 1);
126     args = PyTuple_New(5);
127   } else {
128     func = pyhook;
129     args = PyTuple_New(4);
130   }
131
132   PyTuple_SetItem(args, 0, PyBytes_FromString(what));
133   PyTuple_SetItem(args, 1, PyLong_FromLong((long) type));
134   PyTuple_SetItem(args, 2, PyLong_FromLong((long) current));
135   PyTuple_SetItem(args, 3, PyLong_FromLong((long) total));
136   if (dataarg) {
137     Py_INCREF(dataarg);         /* Because GetItem doesn't give a ref but SetItem taketh away */
138     PyTuple_SetItem(args, 4, dataarg);
139   }
140   
141   retval = PyObject_CallObject(func, args);
142   Py_DECREF(args);
143   Py_XDECREF(retval);
144 }
145
146 void pygpgme_set_progress_cb(gpgme_ctx_t ctx, PyObject *cb, PyObject **freelater){
147   if (cb == Py_None) {
148     gpgme_set_progress_cb(ctx, NULL, NULL);
149     return;
150   }
151   Py_INCREF(cb);
152   *freelater = cb;
153   gpgme_set_progress_cb(ctx, (gpgme_progress_cb_t) pyProgressCb, (void *) cb);
154 }