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>
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.
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.
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
25 /* We use public symbols (eg. "_obsolete_class") which are marked as
26 * deprecated but we need to keep them. Silence the warning. */
27 #pragma GCC diagnostic ignored "-Wdeprecated-declarations"
30 /* Generate doc strings for all methods.
32 This will generate docstrings of the form
34 gpgme_op_encrypt(ctx, recp, flags, plain, cipher) -> gpgme_error_t
36 which we transform into
38 ctx.op_encrypt(recp, flags, plain, cipher) -> gpgme_error_t
40 for automagically wrapped functions. */
41 %feature("autodoc", "0");
44 /* Allow use of Unicode objects, bytes, and None for strings. */
45 %typemap(in) const char *(PyObject *encodedInput = NULL) {
46 if ($input == Py_None)
48 else if (PyUnicode_Check($input))
50 encodedInput = PyUnicode_AsUTF8String($input);
51 if (encodedInput == NULL)
53 $1 = PyBytes_AsString(encodedInput);
55 else if (PyBytes_Check($input))
56 $1 = PyBytes_AsString($input);
58 PyErr_Format(PyExc_TypeError,
59 "arg %d: expected str, bytes, or None, got %s",
60 $argnum, $input->ob_type->tp_name);
64 %typemap(freearg) const char * {
65 Py_XDECREF(encodedInput$argnum);
68 /* Likewise for a list of strings. */
69 %typemap(in) const char *[] (void *vector = NULL,
71 PyObject **pyVector = NULL) {
72 /* Check if is a list */
73 if (PyList_Check($input)) {
75 size = PyList_Size($input);
76 $1 = (char **) (vector = malloc((size+1) * sizeof(char *)));
77 pyVector = calloc(sizeof *pyVector, size);
79 for (i = 0; i < size; i++) {
80 PyObject *o = PyList_GetItem($input,i);
81 if (PyUnicode_Check(o))
83 pyVector[i] = PyUnicode_AsUTF8String(o);
84 if (pyVector[i] == NULL)
87 for (j = 0; j < i; j++)
88 Py_XDECREF(pyVector[j]);
91 $1[i] = PyBytes_AsString(pyVector[i]);
93 else if (PyString_Check(o))
94 $1[i] = PyString_AsString(o);
96 PyErr_Format(PyExc_TypeError,
97 "arg %d: list must contain only str or bytes, got %s "
99 $argnum, o->ob_type->tp_name, i);
106 PyErr_Format(PyExc_TypeError,
107 "arg %d: expected a list of str or bytes, got %s",
108 $argnum, $input->ob_type->tp_name);
112 %typemap(freearg) const char *[] {
115 for (i = 0; i < size$argnum; i++)
116 Py_XDECREF(pyVector$argnum[i]);
119 /* Release returned buffers as necessary. */
120 %typemap(newfree) char * "gpgme_free($1);";
121 %newobject gpgme_data_release_and_get_mem;
122 %newobject gpgme_pubkey_algo_string;
123 %newobject gpgme_addrspec_from_uid;
125 %typemap(arginit) gpgme_key_t [] {
129 %typemap(in) gpgme_key_t [] {
131 if (!PySequence_Check($input)) {
132 PyErr_Format(PyExc_ValueError, "arg %d: Expected a list of gpgme_key_t",
136 if((numb = PySequence_Length($input)) != 0) {
137 $1 = (gpgme_key_t*)malloc((numb+1)*sizeof(gpgme_key_t));
138 for(i=0; i<numb; i++) {
139 PyObject *pypointer = PySequence_GetItem($input, i);
141 /* input = $input, 1 = $1, 1_descriptor = $1_descriptor */
142 /* &1_descriptor = $&1_descriptor *1_descriptor = $*1_descriptor */
144 /* Following code is from swig's python.swg. */
145 if ((SWIG_ConvertPtr(pypointer,(void **) &$1[i], $*1_descriptor,SWIG_POINTER_EXCEPTION | $disown )) == -1) {
146 Py_DECREF(pypointer);
147 PyErr_Format(PyExc_TypeError,
148 "arg %d: list must contain only gpgme_key_ts, got %s "
150 $argnum, pypointer->ob_type->tp_name, i);
154 Py_DECREF(pypointer);
159 %typemap(freearg) gpgme_key_t [] {
163 /* Special handling for references to our objects. */
164 %typemap(in) gpgme_data_t DATAIN (gpgme_data_t wrapper = NULL,
165 PyObject *bytesio = NULL,
166 Py_buffer view, int have_view = 0) {
167 /* If we create a temporary wrapper object, we will store it in
168 wrapperN, where N is $argnum. Here in this fragment, SWIG will
169 automatically append $argnum. */
170 memset(&view, 0, sizeof view);
171 if ($input == Py_None)
175 pypointer = _gpg_obj2gpgme_data_t($input, $argnum, &wrapper,
177 if (pypointer == NULL)
179 have_view = !! view.obj;
181 /* input = $input, 1 = $1, 1_descriptor = $1_descriptor */
183 /* Following code is from swig's python.swg. */
185 if ((SWIG_ConvertPtr(pypointer,(void **) &$1, $1_descriptor,
186 SWIG_POINTER_EXCEPTION | $disown )) == -1) {
187 Py_DECREF(pypointer);
190 Py_DECREF(pypointer);
195 /* If we are doing an in-tree build, we can use the internal
196 representation of struct gpgme_data for an very efficient check if
197 the buffer has been modified. */
199 #include "data.h" /* For struct gpgme_data. */
203 %typemap(freearg) gpgme_data_t DATAIN {
204 /* See whether we need to update the Python buffer. */
205 if (resultobj && wrapper$argnum && view$argnum.buf)
208 char *new_data = NULL;
212 new_data = wrapper$argnum->data.mem.buffer;
213 new_size = wrapper$argnum->data.mem.length;
214 dirty = new_data != NULL;
216 new_data = gpgme_data_release_and_get_mem (wrapper$argnum, &new_size);
217 wrapper$argnum = NULL;
218 dirty = new_size != view$argnum.len
219 || memcmp (new_data, view$argnum.buf, view$argnum.len);
224 /* The buffer is dirty. */
225 if (view$argnum.readonly)
227 Py_XDECREF(resultobj);
229 PyErr_SetString(PyExc_ValueError,
230 "cannot update read-only buffer");
233 /* See if we need to truncate the buffer. */
234 if (resultobj && view$argnum.len != new_size)
236 if (bytesio$argnum == NULL)
238 Py_XDECREF(resultobj);
240 PyErr_SetString(PyExc_ValueError, "cannot resize buffer");
245 PyBuffer_Release(&view$argnum);
246 assert(view$argnum.obj == NULL);
247 retval = PyObject_CallMethod(bytesio$argnum, "truncate",
248 "l", (long) new_size);
251 Py_XDECREF(resultobj);
258 retval = PyObject_CallMethod(bytesio$argnum,
261 || PyObject_GetBuffer(retval, &view$argnum,
262 PyBUF_SIMPLE|PyBUF_WRITABLE) < 0)
264 Py_XDECREF(resultobj);
270 if (resultobj && view$argnum.len
273 Py_XDECREF(resultobj);
275 PyErr_Format(PyExc_ValueError,
276 "Expected buffer of length %zu, got %zi",
284 memcpy(view$argnum.buf, new_data, new_size);
291 /* Free the temporary wrapper, if any. */
293 gpgme_data_release(wrapper$argnum);
294 Py_XDECREF (bytesio$argnum);
295 if (have_view$argnum && view$argnum.buf)
296 PyBuffer_Release(&view$argnum);
299 %apply gpgme_data_t DATAIN {gpgme_data_t plain, gpgme_data_t cipher,
300 gpgme_data_t sig, gpgme_data_t signed_text,
301 gpgme_data_t plaintext, gpgme_data_t keydata,
302 gpgme_data_t pubkey, gpgme_data_t seckey,
303 gpgme_data_t out, gpgme_data_t data};
305 /* SWIG has problems interpreting ssize_t, off_t or gpgme_error_t in
307 %typemap(out) ssize_t, gpgme_error_t, gpgme_err_code_t, gpgme_err_source_t, gpg_error_t {
308 $result = PyLong_FromLong($1);
311 %typemap(in) ssize_t, gpgme_error_t, gpgme_err_code_t, gpgme_err_source_t, gpg_error_t {
312 if (PyLong_Check($input))
313 $1 = PyLong_AsLong($input);
314 #if PY_MAJOR_VERSION < 3
315 else if (PyInt_Check($input))
316 $1 = PyInt_AsLong($input);
319 PyErr_SetString(PyExc_TypeError, "Numeric argument expected");
322 %typemap(out) off_t {
323 #if _FILE_OFFSET_BITS == 64
324 $result = PyLong_FromLongLong($1);
326 $result = PyLong_FromLong($1);
331 if (PyLong_Check($input))
332 #if _FILE_OFFSET_BITS == 64
333 $1 = PyLong_AsLongLong($input);
335 $1 = PyLong_AsLong($input);
337 #if PY_MAJOR_VERSION < 3
338 else if (PyInt_Check($input))
339 $1 = PyInt_AsLong($input);
342 PyErr_SetString(PyExc_TypeError, "Numeric argument expected");
345 /* Those are for gpgme_data_read() and gpgme_strerror_r(). */
346 %typemap(in) (void *buffer, size_t size), (char *buf, size_t buflen) {
349 if (PyLong_Check($input))
350 tmp$argnum = PyLong_AsLong($input);
351 #if PY_MAJOR_VERSION < 3
352 else if (PyInt_Check($input))
353 tmp$argnum = PyInt_AsLong($input);
357 PyErr_SetString(PyExc_TypeError, "Numeric argument expected");
361 if (tmp$argnum < 0) {
362 PyErr_SetString(PyExc_ValueError, "Positive integer expected");
365 $2 = (size_t) tmp$argnum;
366 $1 = ($1_ltype) malloc($2+1);
369 %typemap(argout) (void *buffer, size_t size), (char *buf, size_t buflen) {
370 Py_XDECREF($result); /* Blow away any previous result */
371 if (result < 0) { /* Check for I/O error */
373 return PyErr_SetFromErrno(PyExc_RuntimeError);
375 $result = PyBytes_FromStringAndSize($1,result);
379 /* For gpgme_data_write, but should be universal. */
380 %typemap(in) (const void *buffer, size_t size)(PyObject *encodedInput = NULL) {
383 if ($input == Py_None)
385 else if (PyUnicode_Check($input))
387 encodedInput = PyUnicode_AsUTF8String($input);
388 if (encodedInput == NULL)
390 if (PyBytes_AsStringAndSize(encodedInput, (char **) &$1, &ssize) == -1)
392 Py_DECREF(encodedInput);
396 else if (PyBytes_Check($input))
397 PyBytes_AsStringAndSize($input, (char **) &$1, &ssize);
399 PyErr_Format(PyExc_TypeError,
400 "arg %d: expected str, bytes, or None, got %s",
401 $argnum, $input->ob_type->tp_name);
413 %typemap(freearg) (const void *buffer, size_t size) {
414 Py_XDECREF(encodedInput$argnum);
417 /* Make types containing 'next' field to be lists. */
419 %typemap(out) gpgme_sig_notation_t, gpgme_subkey_t,
420 gpgme_key_sig_t, gpgme_user_id_t, gpgme_invalid_key_t,
421 gpgme_recipient_t, gpgme_new_signature_t, gpgme_signature_t,
422 gpgme_import_status_t, gpgme_conf_arg_t, gpgme_conf_opt_t,
423 gpgme_conf_comp_t, gpgme_tofu_info_t {
427 for (curr = $1; curr != NULL; curr = curr->next) {
430 $result = PyList_New(size);
431 for (i=0,curr=$1; i<size; i++,curr=curr->next) {
432 PyObject *o = SWIG_NewPointerObj(SWIG_as_voidptr(curr), $1_descriptor, %newpointer_flags);
433 PyList_SetItem($result, i, o);
439 /* Wrap the fragile result objects into robust Python ones. */
440 %define wrapresult(cls, name)
443 fragile = SWIG_NewPointerObj(SWIG_as_voidptr($1), $1_descriptor,
445 $result = _gpg_wrap_result(fragile, name);
450 wrapresult(gpgme_encrypt_result_t, "EncryptResult")
451 wrapresult(gpgme_decrypt_result_t, "DecryptResult")
452 wrapresult(gpgme_sign_result_t, "SignResult")
453 wrapresult(gpgme_verify_result_t, "VerifyResult")
454 wrapresult(gpgme_import_result_t, "ImportResult")
455 wrapresult(gpgme_genkey_result_t, "GenkeyResult")
456 wrapresult(gpgme_keylist_result_t, "KeylistResult")
457 wrapresult(gpgme_vfs_mount_result_t, "VFSMountResult")
459 %typemap(out) gpgme_engine_info_t {
463 for (curr = $1; curr != NULL; curr = curr->next) {
466 $result = PyList_New(size);
468 return NULL; /* raise */
469 for (i=0,curr=$1; i<size; i++,curr=curr->next) {
470 PyObject *fragile, *o;
471 fragile = SWIG_NewPointerObj(SWIG_as_voidptr(curr), $1_descriptor,
476 return NULL; /* raise */
478 o = _gpg_wrap_result(fragile, "EngineInfo");
483 return NULL; /* raise */
485 PyList_SetItem($result, i, o);
491 /* Include mapper for interact callbacks. */
492 %typemap(in) (gpgme_interact_cb_t fnc, void *fnc_value) {
493 if (! PyTuple_Check($input))
494 return PyErr_Format(PyExc_TypeError, "interact callback must be a tuple");
495 if (PyTuple_Size($input) != 2 && PyTuple_Size($input) != 3)
496 return PyErr_Format(PyExc_TypeError,
497 "interact callback must be a tuple of size 2 or 3");
499 $1 = (gpgme_interact_cb_t) _gpg_interact_cb;
505 /* The assuan protocol callbacks. */
506 %typemap(in) (gpgme_assuan_data_cb_t data_cb, void *data_cb_value) {
507 if ($input == Py_None)
511 if (! PyTuple_Check($input))
512 return PyErr_Format(PyExc_TypeError, "callback must be a tuple");
513 if (PyTuple_Size($input) != 2)
514 return PyErr_Format(PyExc_TypeError,
515 "callback must be a tuple of size 2");
516 if (! PyCallable_Check(PyTuple_GetItem($input, 1)))
517 return PyErr_Format(PyExc_TypeError, "second item must be callable");
518 $1 = _gpg_assuan_data_cb;
523 %typemap(in) (gpgme_assuan_inquire_cb_t inq_cb, void *inq_cb_value) {
524 if ($input == Py_None)
528 if (! PyTuple_Check($input))
529 return PyErr_Format(PyExc_TypeError, "callback must be a tuple");
530 if (PyTuple_Size($input) != 2)
531 return PyErr_Format(PyExc_TypeError,
532 "callback must be a tuple of size 2");
533 if (! PyCallable_Check(PyTuple_GetItem($input, 1)))
534 return PyErr_Format(PyExc_TypeError, "second item must be callable");
535 $1 = _gpg_assuan_inquire_cb;
540 %typemap(in) (gpgme_assuan_status_cb_t stat_cb, void *stat_cb_value) {
541 if ($input == Py_None)
545 if (! PyTuple_Check($input))
546 return PyErr_Format(PyExc_TypeError, "callback must be a tuple");
547 if (PyTuple_Size($input) != 2)
548 return PyErr_Format(PyExc_TypeError,
549 "callback must be a tuple of size 2");
550 if (! PyCallable_Check(PyTuple_GetItem($input, 1)))
551 return PyErr_Format(PyExc_TypeError, "second item must be callable");
552 $1 = _gpg_assuan_status_cb;
558 /* With SWIG, you can define default arguments for parameters.
559 * While it's legal in C++ it is not in C, so we cannot change the
560 * already existing gpgme.h. We need, however, to declare the function
561 * *before* SWIG loads it from gpgme.h. Hence, we define it here. */
562 gpgme_error_t gpgme_op_keylist_start (gpgme_ctx_t ctx,
563 const char *pattern="",
566 /* The whence argument is surprising in Python-land,
567 because BytesIO or StringIO objects do not require it.
568 It defaults to SEEK_SET. Let's do that for Data objects, too */
569 off_t gpgme_data_seek (gpgme_data_t dh, off_t offset, int whence=SEEK_SET);
571 /* Include the unmodified <gpgme.h> for cc, and the cleaned-up local
572 version for SWIG. We do, however, want to hide certain fields on
573 some structs, which we provide prior to including the version for
583 /* This is for notations, where we want to hide the length fields, and
584 * the unused bit field block. We silence the warning. */
585 %warnfilter(302) _gpgme_sig_notation;
586 struct _gpgme_sig_notation
588 struct _gpgme_sig_notation *next;
590 /* If NAME is a null pointer, then VALUE contains a policy URL
591 rather than a notation. */
594 /* The value of the notation data. */
597 /* The accumulated flags. */
598 gpgme_sig_notation_flags_t flags;
600 /* Notation data is human-readable. */
601 unsigned int human_readable : 1;
603 /* Notation data is critical. */
604 unsigned int critical : 1;
607 /* Now include our local modified version. Any structs defined above
617 /* Generating and handling pointers-to-pointers. */
619 %pointer_functions(gpgme_ctx_t, gpgme_ctx_t_p);
620 %pointer_functions(gpgme_data_t, gpgme_data_t_p);
621 %pointer_functions(gpgme_key_t, gpgme_key_t_p);
622 %pointer_functions(gpgme_error_t, gpgme_error_t_p);
623 %pointer_functions(gpgme_trust_item_t, gpgme_trust_item_t_p);
624 %pointer_functions(gpgme_engine_info_t, gpgme_engine_info_t_p);
626 /* Helper functions. */
631 FILE *fdopen(int fildes, const char *mode);
633 /* We include both headers in the generated c code... */
638 /* SWIG runtime support for helpers.c */
640 _gpg_wrap_gpgme_data_t(gpgme_data_t data)
643 * If SWIG is invoked without -builtin, the macro SWIG_NewPointerObj
644 * expects a variable named "self".
646 * XXX: It is not quite clear why passing NULL as self is okay, but
647 * it works with -builtin, and it seems to work just fine without
650 PyObject* self = NULL;
652 return SWIG_NewPointerObj(data, SWIGTYPE_p_gpgme_data, 0);
656 _gpg_unwrap_gpgme_ctx_t(PyObject *wrapped)
659 if (SWIG_ConvertPtr(wrapped,
661 SWIGTYPE_p_gpgme_context,
662 SWIG_POINTER_EXCEPTION) == -1)
668 /* ... but only the public definitions here. They will be exposed to
669 the Python world, so let's be careful. */
673 %define genericrepr(cls)
676 names = [name for name in dir(self)
677 if not name.startswith("_") and name != "this"]
678 props = ", ".join(("{}={!r}".format(name, getattr(self, name))
681 return "cls({})".format(props)
691 %extend _gpgme_subkey {
695 %extend _gpgme_key_sig {
699 %extend _gpgme_user_id {
703 %extend _gpgme_tofu_info {
704 genericrepr(TofuInfo)