python: Support the Assuan engine.
[gpgme.git] / lang / python / gpgme.i
1 /*
2 # Copyright (C) 2016 g10 Code GmbH
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
26    This will generate docstrings of the form
27
28      gpgme_op_encrypt(ctx, recp, flags, plain, cipher) -> gpgme_error_t
29
30    which we transform into
31
32      ctx.op_encrypt(recp, flags, plain, cipher) -> gpgme_error_t
33
34    for automagically wrapped functions.  */
35 %feature("autodoc", "0");
36
37
38 /* Allow use of Unicode objects, bytes, and None for strings.  */
39 %typemap(in) const char * {
40   if ($input == Py_None)
41     $1 = NULL;
42   else if (PyUnicode_Check($input))
43     $1 = PyUnicode_AsUTF8($input);
44   else if (PyBytes_Check($input))
45     $1 = PyBytes_AsString($input);
46   else {
47     PyErr_Format(PyExc_TypeError,
48                  "arg %d: expected str, bytes, or None, got %s",
49                  $argnum, $input->ob_type->tp_name);
50     return NULL;
51   }
52 }
53 %typemap(freearg) const char * "";
54
55 /* Likewise for a list of strings.  */
56 %typemap(in) const char *[] (void *vector = NULL) {
57   /* Check if is a list */
58   if (PyList_Check($input)) {
59     size_t i, size = PyList_Size($input);
60     $1 = (char **) (vector = malloc((size+1) * sizeof(char *)));
61
62     for (i = 0; i < size; i++) {
63       PyObject *o = PyList_GetItem($input,i);
64       if (PyUnicode_Check(o))
65         $1[i] = PyUnicode_AsUTF8(o);
66       else if (PyString_Check(o))
67         $1[i] = PyString_AsString(o);
68       else {
69         PyErr_Format(PyExc_TypeError,
70                      "arg %d: list must contain only str or bytes, got %s "
71                      "at position %d",
72                      $argnum, o->ob_type->tp_name, i);
73         free($1);
74         return NULL;
75       }
76     }
77     $1[i] = NULL;
78   } else {
79     PyErr_Format(PyExc_TypeError,
80                  "arg %d: expected a list of str or bytes, got %s",
81                  $argnum, $input->ob_type->tp_name);
82     return NULL;
83   }
84 }
85 %typemap(freearg) const char *[] {
86   free(vector$argnum);
87 }
88
89 // Release returned buffers as necessary.
90 %typemap(newfree) char * "free($1);";
91 %newobject gpgme_data_release_and_get_mem;
92
93 %typemap(arginit) gpgme_key_t [] {
94   $1 = NULL;
95 }
96
97 %typemap(in) gpgme_key_t [] {
98   int i, numb = 0;
99   if (!PySequence_Check($input)) {
100     PyErr_Format(PyExc_ValueError, "arg %d: Expected a list of gpgme_key_t",
101                  $argnum);
102     return NULL;
103   }
104   if((numb = PySequence_Length($input)) != 0) {
105     $1 = (gpgme_key_t*)malloc((numb+1)*sizeof(gpgme_key_t));
106     for(i=0; i<numb; i++) {
107       PyObject *pypointer = PySequence_GetItem($input, i);
108
109       /* input = $input, 1 = $1, 1_descriptor = $1_descriptor */
110       /* &1_descriptor = $&1_descriptor *1_descriptor = $*1_descriptor */
111
112       // Following code is from swig's python.swg
113       if ((SWIG_ConvertPtr(pypointer,(void **) &$1[i], $*1_descriptor,SWIG_POINTER_EXCEPTION | $disown )) == -1) {
114         Py_DECREF(pypointer);
115         return NULL;
116       }
117       Py_DECREF(pypointer);
118     }
119     $1[numb] = NULL;
120   }
121 }
122 %typemap(freearg) gpgme_key_t [] {
123   if ($1) free($1);
124 }
125
126 // Special handling for references to our objects.
127 %typemap(in) gpgme_data_t DATAIN (gpgme_data_t wrapper = NULL,
128                                   PyObject *bytesio = NULL,
129                                   Py_buffer view, int have_view = 0) {
130   /* If we create a temporary wrapper object, we will store it in
131      wrapperN, where N is $argnum.  Here in this fragment, SWIG will
132      automatically append $argnum.  */
133   memset(&view, 0, sizeof view);
134   if ($input == Py_None)
135     $1 = NULL;
136   else {
137     PyObject *pypointer;
138     pypointer = object_to_gpgme_data_t($input, $argnum, &wrapper,
139                                        &bytesio, &view);
140     if (pypointer == NULL)
141       return NULL;
142     have_view = !! view.obj;
143
144     /* input = $input, 1 = $1, 1_descriptor = $1_descriptor */
145
146     // Following code is from swig's python.swg
147
148     if ((SWIG_ConvertPtr(pypointer,(void **) &$1, $1_descriptor,
149          SWIG_POINTER_EXCEPTION | $disown )) == -1) {
150       Py_DECREF(pypointer);
151       return NULL;
152     }
153     Py_DECREF(pypointer);
154   }
155 }
156
157 #if HAVE_DATA_H
158 /* If we are doing an in-tree build, we can use the internal
159    representation of struct gpgme_data for an very efficient check if
160    the buffer has been modified.  */
161 %{
162 #include "src/data.h"   /* For struct gpgme_data.  */
163 %}
164 #endif
165
166 %typemap(freearg) gpgme_data_t DATAIN {
167   /* See whether we need to update the Python buffer.  */
168   if (resultobj && wrapper$argnum && view$argnum.buf)
169     {
170       int dirty;
171       char *new_data = NULL;
172       size_t new_size;
173
174 #if HAVE_DATA_H
175       new_data = wrapper$argnum->data.mem.buffer;
176       new_size = wrapper$argnum->data.mem.length;
177       dirty = new_data != NULL;
178 #else
179       new_data = gpgme_data_release_and_get_mem (wrapper$argnum, &new_size);
180       wrapper$argnum = NULL;
181       dirty = new_size != view$argnum.len
182         || memcmp (new_data, view$argnum.buf, view$argnum.len);
183 #endif
184
185       if (dirty)
186         {
187           /* The buffer is dirty.  */
188           if (view$argnum.readonly)
189             {
190               Py_XDECREF(resultobj);
191               resultobj = NULL;
192               PyErr_SetString(PyExc_ValueError,
193                               "cannot update read-only buffer");
194             }
195
196           /* See if we need to truncate the buffer.  */
197           if (resultobj && view$argnum.len != new_size)
198             {
199               if (bytesio$argnum == NULL)
200                 {
201                   Py_XDECREF(resultobj);
202                   resultobj = NULL;
203                   PyErr_SetString(PyExc_ValueError, "cannot resize buffer");
204                 }
205               else
206                 {
207                   PyObject *retval;
208                   PyBuffer_Release(&view$argnum);
209                   assert(view$argnum.obj == NULL);
210                   retval = PyObject_CallMethod(bytesio$argnum, "truncate",
211                                                "l", (long) new_size);
212                   if (retval == NULL)
213                     {
214                       Py_XDECREF(resultobj);
215                       resultobj = NULL;
216                     }
217                   else
218                     {
219                       Py_DECREF(retval);
220
221                       retval = PyObject_CallMethod(bytesio$argnum,
222                                                    "getbuffer", NULL);
223                       if (retval == NULL
224                           || PyObject_GetBuffer(retval, &view$argnum,
225                                            PyBUF_SIMPLE|PyBUF_WRITABLE) < 0)
226                         {
227                           Py_XDECREF(resultobj);
228                           resultobj = NULL;
229                         }
230
231                       Py_XDECREF(retval);
232
233                       if (resultobj && view$argnum.len
234                           != new_size)
235                         {
236                           Py_XDECREF(resultobj);
237                           resultobj = NULL;
238                           PyErr_Format(PyExc_ValueError,
239                                        "Expected buffer of length %zu, got %zi",
240                                        new_size,
241                                        view$argnum.len);
242                         }
243                     }
244                 }
245             }
246           if (resultobj)
247             memcpy(view$argnum.buf, new_data, new_size);
248         }
249 #if ! HAVE_DATA_H
250       free (new_data);
251 #endif
252     }
253
254   /* Free the temporary wrapper, if any.  */
255   if (wrapper$argnum)
256     gpgme_data_release(wrapper$argnum);
257   Py_XDECREF (bytesio$argnum);
258   if (have_view$argnum && view$argnum.buf)
259     PyBuffer_Release(&view$argnum);
260 }
261
262 %apply gpgme_data_t DATAIN {gpgme_data_t plain, gpgme_data_t cipher,
263                         gpgme_data_t sig, gpgme_data_t signed_text,
264                         gpgme_data_t plaintext, gpgme_data_t keydata,
265                         gpgme_data_t pubkey, gpgme_data_t seckey,
266                         gpgme_data_t out};
267
268 /* SWIG has problems interpreting ssize_t, off_t or gpgme_error_t in
269    gpgme.h.  */
270 /* XXX: This is wrong at least for off_t if compiled with LFS.  */
271 %typemap(out) ssize_t, off_t, gpgme_error_t, gpgme_err_code_t, gpgme_err_source_t, gpg_error_t {
272   $result = PyLong_FromLong($1);
273 }
274 /* XXX: This is wrong at least for off_t if compiled with LFS.  */
275 %typemap(in) ssize_t, off_t, gpgme_error_t, gpgme_err_code_t, gpgme_err_source_t, gpg_error_t {
276   $1 = PyLong_AsLong($input);
277 }
278
279 // Those are for gpgme_data_read() and gpgme_strerror_r()
280 %typemap(in) (void *buffer, size_t size), (char *buf, size_t buflen) {
281    $2 = PyLong_AsLong($input);
282    if ($2 < 0) {
283      PyErr_SetString(PyExc_ValueError, "Positive integer expected");
284      return NULL;
285    }
286    $1 = ($1_ltype) malloc($2+1);
287 }
288 %typemap(argout) (void *buffer, size_t size), (char *buf, size_t buflen) {
289   Py_XDECREF($result);   /* Blow away any previous result */
290   if (result < 0) {      /* Check for I/O error */
291     free($1);
292     return PyErr_SetFromErrno(PyExc_RuntimeError);
293   }
294   $result = PyBytes_FromStringAndSize($1,result);
295   free($1);
296 }
297
298 /* For gpgme_data_write, but should be universal.  */
299 %typemap(in) (const void *buffer, size_t size) {
300   Py_ssize_t ssize;
301
302   if ($input == Py_None)
303     $1 = NULL, $2 = 0;
304   else if (PyUnicode_Check($input))
305     $1 = PyUnicode_AsUTF8AndSize($input, &ssize);
306   else if (PyBytes_Check($input))
307     PyBytes_AsStringAndSize($input, (char **) &$1, &ssize);
308   else {
309     PyErr_Format(PyExc_TypeError,
310                  "arg %d: expected str, bytes, or None, got %s",
311                  $argnum, $input->ob_type->tp_name);
312     return NULL;
313   }
314
315   if (! $1)
316     $2 = 0;
317   else
318     {
319       assert (ssize >= 0);
320       $2 = (size_t) ssize;
321     }
322 }
323 %typemap(freearg) (const void *buffer, size_t size) "";
324
325 // Make types containing 'next' field to be lists
326 %ignore next;
327 %typemap(out) gpgme_sig_notation_t, gpgme_subkey_t,
328    gpgme_key_sig_t, gpgme_user_id_t, gpgme_invalid_key_t,
329    gpgme_recipient_t, gpgme_new_signature_t, gpgme_signature_t,
330    gpgme_import_status_t, gpgme_conf_arg_t, gpgme_conf_opt_t,
331    gpgme_conf_comp_t, gpgme_tofu_info_t {
332   int i;
333   int size = 0;
334   $1_ltype curr;
335   for (curr = $1; curr != NULL; curr = curr->next) {
336     size++;
337   }
338   $result = PyList_New(size);
339   for (i=0,curr=$1; i<size; i++,curr=curr->next) {
340     PyObject *o = SWIG_NewPointerObj(SWIG_as_voidptr(curr), $1_descriptor, %newpointer_flags);
341     PyList_SetItem($result, i, o);
342   }
343 }
344
345 \f
346
347 /* Wrap the fragile result objects into robust Python ones.  */
348 %typemap(out) gpgme_encrypt_result_t {
349   PyObject *fragile;
350   fragile = SWIG_NewPointerObj(SWIG_as_voidptr($1), $1_descriptor,
351                                %newpointer_flags);
352   $result = pygpgme_wrap_fragile_result(fragile, "EncryptResult");
353   Py_DECREF(fragile);
354 }
355
356 %typemap(out) gpgme_decrypt_result_t {
357   PyObject *fragile;
358   fragile = SWIG_NewPointerObj(SWIG_as_voidptr($1), $1_descriptor,
359                                %newpointer_flags);
360   $result = pygpgme_wrap_fragile_result(fragile, "DecryptResult");
361   Py_DECREF(fragile);
362 }
363
364 %typemap(out) gpgme_sign_result_t {
365   PyObject *fragile;
366   fragile = SWIG_NewPointerObj(SWIG_as_voidptr($1), $1_descriptor,
367                                %newpointer_flags);
368   $result = pygpgme_wrap_fragile_result(fragile, "SignResult");
369   Py_DECREF(fragile);
370 }
371
372 %typemap(out) gpgme_verify_result_t {
373   PyObject *fragile;
374   fragile = SWIG_NewPointerObj(SWIG_as_voidptr($1), $1_descriptor,
375                                %newpointer_flags);
376   $result = pygpgme_wrap_fragile_result(fragile, "VerifyResult");
377   Py_DECREF(fragile);
378 }
379
380 %typemap(out) gpgme_import_result_t {
381   PyObject *fragile;
382   fragile = SWIG_NewPointerObj(SWIG_as_voidptr($1), $1_descriptor,
383                                %newpointer_flags);
384   $result = pygpgme_wrap_fragile_result(fragile, "ImportResult");
385   Py_DECREF(fragile);
386 }
387
388 %typemap(out) gpgme_genkey_result_t {
389   PyObject *fragile;
390   fragile = SWIG_NewPointerObj(SWIG_as_voidptr($1), $1_descriptor,
391                                %newpointer_flags);
392   $result = pygpgme_wrap_fragile_result(fragile, "GenkeyResult");
393   Py_DECREF(fragile);
394 }
395
396 %typemap(out) gpgme_keylist_result_t {
397   PyObject *fragile;
398   fragile = SWIG_NewPointerObj(SWIG_as_voidptr($1), $1_descriptor,
399                                %newpointer_flags);
400   $result = pygpgme_wrap_fragile_result(fragile, "KeylistResult");
401   Py_DECREF(fragile);
402 }
403
404 %typemap(out) gpgme_vfs_mount_result_t {
405   PyObject *fragile;
406   fragile = SWIG_NewPointerObj(SWIG_as_voidptr($1), $1_descriptor,
407                                %newpointer_flags);
408   $result = pygpgme_wrap_fragile_result(fragile, "VFSMountResult");
409   Py_DECREF(fragile);
410 }
411
412 %typemap(out) gpgme_engine_info_t {
413   int i;
414   int size = 0;
415   $1_ltype curr;
416   for (curr = $1; curr != NULL; curr = curr->next) {
417     size++;
418   }
419   $result = PyList_New(size);
420   for (i=0,curr=$1; i<size; i++,curr=curr->next) {
421     PyObject *fragile, *o;
422     fragile = SWIG_NewPointerObj(SWIG_as_voidptr(curr), $1_descriptor,
423                                  %newpointer_flags);
424     o = pygpgme_wrap_fragile_result(fragile, "EngineInfo");
425     if (o == NULL)
426       return NULL;      /* raise */
427     Py_DECREF(fragile);
428     PyList_SetItem($result, i, o);
429   }
430 }
431
432 \f
433
434 // Include mapper for edit callbacks
435 %typemap(in) (gpgme_edit_cb_t fnc, void *fnc_value) {
436   if (! PyTuple_Check($input))
437     return PyErr_Format(PyExc_TypeError, "edit callback must be a tuple");
438   if (PyTuple_Size($input) != 2 && PyTuple_Size($input) != 3)
439     return PyErr_Format(PyExc_TypeError,
440                         "edit callback must be a tuple of size 2 or 3");
441
442   $1 = (gpgme_edit_cb_t) pyEditCb;
443   $2 = $input;
444 }
445
446 \f
447
448 /* The assuan protocol callbacks.  */
449 %typemap(in) (gpgme_assuan_data_cb_t data_cb, void *data_cb_value) {
450   if ($input == Py_None)
451     $1 = $2 = NULL;
452   else
453     {
454       if (! PyTuple_Check($input))
455         return PyErr_Format(PyExc_TypeError, "callback must be a tuple");
456       if (PyTuple_Size($input) != 2)
457         return PyErr_Format(PyExc_TypeError,
458                             "callback must be a tuple of size 2");
459       if (! PyCallable_Check(PyTuple_GetItem($input, 1)))
460         return PyErr_Format(PyExc_TypeError, "second item must be callable");
461       $1 = _pyme_assuan_data_cb;
462       $2 = $input;
463     }
464 }
465
466 %typemap(in) (gpgme_assuan_inquire_cb_t inq_cb, void *inq_cb_value) {
467   if ($input == Py_None)
468     $1 = $2 = NULL;
469   else
470     {
471       if (! PyTuple_Check($input))
472         return PyErr_Format(PyExc_TypeError, "callback must be a tuple");
473       if (PyTuple_Size($input) != 2)
474         return PyErr_Format(PyExc_TypeError,
475                             "callback must be a tuple of size 2");
476       if (! PyCallable_Check(PyTuple_GetItem($input, 1)))
477         return PyErr_Format(PyExc_TypeError, "second item must be callable");
478       $1 = _pyme_assuan_inquire_cb;
479       $2 = $input;
480     }
481 }
482
483 %typemap(in) (gpgme_assuan_status_cb_t stat_cb, void *stat_cb_value) {
484   if ($input == Py_None)
485     $1 = $2 = NULL;
486   else
487     {
488       if (! PyTuple_Check($input))
489         return PyErr_Format(PyExc_TypeError, "callback must be a tuple");
490       if (PyTuple_Size($input) != 2)
491         return PyErr_Format(PyExc_TypeError,
492                             "callback must be a tuple of size 2");
493       if (! PyCallable_Check(PyTuple_GetItem($input, 1)))
494         return PyErr_Format(PyExc_TypeError, "second item must be callable");
495       $1 = _pyme_assuan_status_cb;
496       $2 = $input;
497     }
498 }
499
500 /* Include the unmodified <gpgme.h> for cc, and the cleaned-up local
501    version for SWIG.  We do, however, want to hide certain fields on
502    some structs, which we provide prior to including the version for
503    SWIG.  */
504 %{
505 #include <gpgme.h>
506 %}
507
508 /* This is for notations, where we want to hide the length fields, and
509    the unused bit field block.  */
510 struct _gpgme_sig_notation
511 {
512   struct _gpgme_sig_notation *next;
513
514   /* If NAME is a null pointer, then VALUE contains a policy URL
515      rather than a notation.  */
516   char *name;
517
518   /* The value of the notation data.  */
519   char *value;
520
521   /* The accumulated flags.  */
522   gpgme_sig_notation_flags_t flags;
523
524   /* Notation data is human-readable.  */
525   unsigned int human_readable : 1;
526
527   /* Notation data is critical.  */
528   unsigned int critical : 1;
529 };
530
531 /* Now include our local modified version.  Any structs defined above
532    are ignored.  */
533 %include "gpgme.h"
534
535 %include "errors.i"
536
537 // Generating and handling pointers-to-pointers.
538
539 %pointer_functions(gpgme_ctx_t, gpgme_ctx_t_p);
540 %pointer_functions(gpgme_data_t, gpgme_data_t_p);
541 %pointer_functions(gpgme_key_t, gpgme_key_t_p);
542 %pointer_functions(gpgme_error_t, gpgme_error_t_p);
543 %pointer_functions(gpgme_trust_item_t, gpgme_trust_item_t_p);
544 %pointer_functions(gpgme_engine_info_t, gpgme_engine_info_t_p);
545
546 // Helper functions.
547
548 %{
549 #include <stdio.h>
550 %}
551 FILE *fdopen(int fildes, const char *mode);
552
553 /* We include both headers in the generated c code...  */
554 %{
555 #include "helpers.h"
556 #include "private.h"
557
558 /* SWIG support for helpers.c  */
559 PyObject *
560 pygpgme_wrap_gpgme_data_t(gpgme_data_t data)
561 {
562   return SWIG_Python_NewPointerObj(NULL, data, SWIGTYPE_p_gpgme_data, 0);
563 }
564
565 gpgme_ctx_t
566 pygpgme_unwrap_gpgme_ctx_t(PyObject *wrapped)
567 {
568   gpgme_ctx_t result;
569   if (SWIG_ConvertPtr(wrapped,
570                       (void **) &result,
571                       SWIGTYPE_p_gpgme_context,
572                       SWIG_POINTER_EXCEPTION) == -1)
573     return NULL;
574   return result;
575 }
576 %}
577
578 /* ... but only the public definitions here.  They will be exposed to
579    the Python world, so let's be careful.  */
580 %include "helpers.h"