python: Translate list of strings.
[gpgme.git] / lang / python / gpgme.i
1 /*
2 # $Id$
3 # Copyright (C) 2004,2008 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 %module pygpgme
21 %include "cpointer.i"
22 %include "cstring.i"
23
24 // Generate doc strings for all methods.
25 %feature("autodoc", "0");
26
27 /* Allow use of Unicode objects, bytes, and None for strings.  */
28
29 %typemap(in) const char * {
30   if ($input == Py_None)
31     $1 = NULL;
32   else if (PyUnicode_Check($input))
33     $1 = PyUnicode_AsUTF8($input);
34   else if (PyBytes_Check($input))
35     $1 = PyBytes_AsString($input);
36   else {
37     PyErr_Format(PyExc_TypeError,
38                  "arg %d: expected str, bytes, or None, got %s",
39                  $argnum, $input->ob_type->tp_name);
40     return NULL;
41   }
42 }
43 %typemap(freearg) const char * "";
44
45 /* Likewise for a list of strings.  */
46 %typemap(in) const char *[] {
47   /* Check if is a list */
48   if (PyList_Check($input)) {
49     size_t i, size = PyList_Size($input);
50     $1 = (char **) malloc((size+1) * sizeof(char *));
51
52     for (i = 0; i < size; i++) {
53       PyObject *o = PyList_GetItem($input,i);
54       if (PyUnicode_Check(o))
55         $1[i] = PyUnicode_AsUTF8(o);
56       else if (PyString_Check(o))
57         $1[i] = PyString_AsString(o);
58       else {
59         PyErr_Format(PyExc_TypeError,
60                      "arg %d: list must contain only str or bytes, got %s "
61                      "at position %d",
62                      $argnum, o->ob_type->tp_name, i);
63         free($1);
64         return NULL;
65       }
66     }
67     $1[i] = NULL;
68   } else {
69     PyErr_Format(PyExc_TypeError,
70                  "arg %d: expected a list of str or bytes, got %s",
71                  $argnum, $input->ob_type->tp_name);
72     return NULL;
73   }
74 }
75 %typemap(freearg) const char *[] {
76   free((char *) $1);
77 }
78
79 // Release returned buffers as necessary.
80 %typemap(newfree) char * "free($1);";
81 %newobject gpgme_data_release_and_get_mem;
82
83 %{
84 /* Convert object to a pointer to gpgme type */
85 PyObject* object_to_gpgme_t(PyObject* input, const char* objtype, int argnum) {
86   PyObject *pyname = NULL, *pypointer = NULL;
87   pyname = PyObject_CallMethod(input, "_getctype", NULL);
88   if (pyname && PyUnicode_Check(pyname))
89     {
90       if (strcmp(PyUnicode_AsUTF8(pyname), objtype) != 0)
91         {
92           PyErr_Format(PyExc_TypeError,
93                        "arg %d: Expected value of type %s, but got %s",
94                        argnum, objtype, PyUnicode_AsUTF8(pyname));
95           Py_DECREF(pyname);
96           return NULL;
97         }
98     }
99   else
100     {
101       PyErr_Format(PyExc_TypeError,
102                    "Protocol violation: Expected an instance of type str "
103                    "from _getctype, but got %s",
104                    pyname == NULL ? "NULL"
105                    : (pyname == Py_None ? "None" : pyname->ob_type->tp_name));
106       return NULL;
107     }
108
109   Py_DECREF(pyname);
110   pypointer = PyObject_GetAttrString(input, "wrapped");
111   if (pypointer == NULL) {
112     PyErr_Format(PyExc_TypeError,
113                  "arg %d: Use of uninitialized Python object %s",
114                  argnum, objtype);
115     return NULL;
116   }
117   return pypointer;
118 }
119 %}
120
121 %typemap(arginit) gpgme_key_t [] {
122   $1 = NULL;
123 }
124
125 %typemap(in) gpgme_key_t [] {
126   int i, numb = 0;
127   if (!PySequence_Check($input)) {
128     PyErr_Format(PyExc_ValueError, "arg %d: Expected a list of gpgme_key_t",
129                  $argnum);
130     return NULL;
131   }
132   if((numb = PySequence_Length($input)) != 0) {
133     $1 = (gpgme_key_t*)malloc((numb+1)*sizeof(gpgme_key_t));
134     for(i=0; i<numb; i++) {
135       PyObject *pypointer = PySequence_GetItem($input, i);
136
137       /* input = $input, 1 = $1, 1_descriptor = $1_descriptor */
138       /* &1_descriptor = $&1_descriptor *1_descriptor = $*1_descriptor */
139
140       // Following code is from swig's python.swg
141       if ((SWIG_ConvertPtr(pypointer,(void **) &$1[i], $*1_descriptor,SWIG_POINTER_EXCEPTION | $disown )) == -1) {
142         Py_DECREF(pypointer);
143         return NULL;
144       }
145       Py_DECREF(pypointer);
146     }
147     $1[numb] = NULL;
148   }
149 }
150 %typemap(freearg) gpgme_key_t [] {
151   if ($1) free($1);
152 }
153
154 // Special handling for references to our objects.
155 %typemap(in) gpgme_data_t DATAIN {
156   if ($input == Py_None)
157     $1 = NULL;
158   else {
159     PyObject *pypointer = NULL;
160
161     if((pypointer=object_to_gpgme_t($input, "$1_ltype", $argnum)) == NULL)
162       return NULL;
163
164     /* input = $input, 1 = $1, 1_descriptor = $1_descriptor */
165
166     // Following code is from swig's python.swg
167
168     if ((SWIG_ConvertPtr(pypointer,(void **) &$1, $1_descriptor,
169          SWIG_POINTER_EXCEPTION | $disown )) == -1) {
170       Py_DECREF(pypointer);
171       return NULL;
172     }
173     Py_DECREF(pypointer);
174   }
175 }
176
177 %apply gpgme_data_t DATAIN {gpgme_data_t plain, gpgme_data_t cipher,
178                         gpgme_data_t sig, gpgme_data_t signed_text,
179                         gpgme_data_t plaintext, gpgme_data_t keydata,
180                         gpgme_data_t pubkey, gpgme_data_t seckey,
181                         gpgme_data_t out};
182
183 // SWIG has problem interpreting ssize_t, off_t or gpgme_error_t in gpgme.h
184 %typemap(out) ssize_t, off_t, gpgme_error_t, gpgme_err_code_t, gpgme_err_source_t, gpg_error_t {
185   $result = PyLong_FromLong($1);
186 }
187 %typemap(in) ssize_t, off_t, gpgme_error_t, gpgme_err_code_t, gpgme_err_source_t, gpg_error_t {
188   $1 = PyLong_AsLong($input);
189 }
190
191 // Those are for gpgme_data_read() and gpgme_strerror_r()
192 %typemap(in) (void *buffer, size_t size), (char *buf, size_t buflen) {
193    $2 = PyLong_AsLong($input);
194    if ($2 < 0) {
195      PyErr_SetString(PyExc_ValueError, "Positive integer expected");
196      return NULL;
197    }
198    $1 = ($1_ltype) malloc($2+1);
199 }
200 %typemap(argout) (void *buffer, size_t size), (char *buf, size_t buflen) {
201   Py_XDECREF($result);   /* Blow away any previous result */
202   if (result < 0) {      /* Check for I/O error */
203     free($1);
204     return NULL;
205   }
206   $result = PyBytes_FromStringAndSize($1,result);
207   free($1);
208 }
209
210 /* For gpgme_data_write, but should be universal.  */
211 %typemap(in) (const void *buffer, size_t size) {
212   if ($input == Py_None)
213     $1 = NULL, $2 = 0;
214   else if (PyUnicode_Check($input))
215     $1 = PyUnicode_AsUTF8AndSize($input, (size_t *) &$2);
216   else if (PyBytes_Check($input))
217     PyBytes_AsStringAndSize($input, (char **) &$1, (size_t *) &$2);
218   else {
219     PyErr_Format(PyExc_TypeError,
220                  "arg %d: expected str, bytes, or None, got %s",
221                  $argnum, $input->ob_type->tp_name);
222     return NULL;
223   }
224 }
225 %typemap(freearg) (const void *buffer, size_t size) "";
226
227 // Make types containing 'next' field to be lists
228 %ignore next;
229 %typemap(out) gpgme_sig_notation_t, gpgme_engine_info_t, gpgme_subkey_t, gpgme_key_sig_t,
230         gpgme_user_id_t, gpgme_invalid_key_t, gpgme_recipient_t, gpgme_new_signature_t,
231         gpgme_signature_t, gpgme_import_status_t, gpgme_conf_arg_t, gpgme_conf_opt_t,
232         gpgme_conf_comp_t {
233   int i;
234   int size = 0;
235   $1_ltype curr;
236   for (curr = $1; curr != NULL; curr = curr->next) {
237     size++;
238   }
239   $result = PyList_New(size);
240   for (i=0,curr=$1; i<size; i++,curr=curr->next) {
241     PyObject *o = SWIG_NewPointerObj(SWIG_as_voidptr(curr), $1_descriptor, %newpointer_flags);
242     PyList_SetItem($result, i, o);
243   }
244 }
245
246 // Include mapper for edit callbacks
247 %typemap(in) (gpgme_edit_cb_t fnc, void *fnc_value) {
248   $1 = (gpgme_edit_cb_t) pyEditCb;
249   if ($input == Py_None)
250     $2 = NULL;
251   else
252     $2 = $input;
253 }
254
255 // Include the header file both for cc (first) and for swig (second)
256 // Include for swig locally since we need to fix 'class' usage there.
257 %{
258 #include <gpgme.h>
259 %}
260 %include "gpgme.h"
261
262 %constant long EOF = GPG_ERR_EOF;
263
264 // Generating and handling pointers-to-pointers.
265
266 %pointer_functions(gpgme_ctx_t, gpgme_ctx_t_p);
267 %pointer_functions(gpgme_data_t, gpgme_data_t_p);
268 %pointer_functions(gpgme_key_t, gpgme_key_t_p);
269 %pointer_functions(gpgme_error_t, gpgme_error_t_p);
270 %pointer_functions(gpgme_trust_item_t, gpgme_trust_item_t_p);
271 %pointer_functions(gpgme_engine_info_t, gpgme_engine_info_t_p);
272 %pointer_functions(PyObject *, PyObject_p_p);
273 %pointer_functions(void *, void_p_p);
274
275 // Helper functions.
276
277 %{
278 #include <stdio.h>
279 %}
280 FILE *fdopen(int fildes, const char *mode);
281
282 %{
283 #include "helpers.h"
284 %}
285 %include "helpers.h"
286
287 %{
288 gpgme_error_t pyEditCb(void *opaque, gpgme_status_code_t status,
289                        const char *args, int fd) {
290   PyObject *func = NULL, *dataarg = NULL, *pyargs = NULL, *retval = NULL;
291   PyObject *pyopaque = (PyObject *) opaque;
292   gpgme_error_t err_status = 0;
293
294   pygpgme_exception_init();
295
296   if (PyTuple_Check(pyopaque)) {
297     func = PyTuple_GetItem(pyopaque, 0);
298     dataarg = PyTuple_GetItem(pyopaque, 1);
299     pyargs = PyTuple_New(3);
300   } else {
301     func = pyopaque;
302     pyargs = PyTuple_New(2);
303   }
304
305   PyTuple_SetItem(pyargs, 0, PyLong_FromLong((long) status));
306   PyTuple_SetItem(pyargs, 1, PyUnicode_FromString(args));
307   if (dataarg) {
308     Py_INCREF(dataarg);         /* Because GetItem doesn't give a ref but SetItem taketh away */
309     PyTuple_SetItem(pyargs, 2, dataarg);
310   }
311
312   retval = PyObject_CallObject(func, pyargs);
313   Py_DECREF(pyargs);
314   if (PyErr_Occurred()) {
315     err_status = pygpgme_exception2code();
316   } else {
317     if (fd>=0 && retval && PyUnicode_Check(retval)) {
318       const char *buffer;
319       Py_ssize_t size;
320
321       buffer = PyUnicode_AsUTF8AndSize(retval, &size);
322       write(fd, buffer, size);
323       write(fd, "\n", 1);
324     }
325   }
326
327   Py_XDECREF(retval);
328   return err_status;
329 }
330 %}