r26088: Import some native-python python modules and move original python swig tortur...
[ira/wip.git] / source / lib / ldb / ldb.i
1 /*
2    Unix SMB/CIFS implementation.
3
4    Swig interface to ldb.
5
6    Copyright (C) 2005,2006 Tim Potter <tpot@samba.org>
7    Copyright (C) 2006 Simo Sorce <idra@samba.org>
8    Copyright (C) 2007 Jelmer Vernooij <jelmer@samba.org>
9
10      ** NOTE! The following LGPL license applies to the ldb
11      ** library. This does NOT imply that all of Samba is released
12      ** under the LGPL
13    
14    This library is free software; you can redistribute it and/or
15    modify it under the terms of the GNU Lesser General Public
16    License as published by the Free Software Foundation; either
17    version 3 of the License, or (at your option) any later version.
18
19    This library is distributed in the hope that it will be useful,
20    but WITHOUT ANY WARRANTY; without even the implied warranty of
21    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
22    Lesser General Public License for more details.
23
24    You should have received a copy of the GNU Lesser General Public
25    License along with this library; if not, see <http://www.gnu.org/licenses/>.
26 */
27
28 %module(package="ldb") ldb
29
30 %{
31
32 /* Include headers */
33
34 #include <stdint.h>
35 #include <stdbool.h>
36 #include "talloc.h"
37 #include "ldb.h"
38 #include "ldb_errors.h"
39
40 typedef struct ldb_message ldb_msg;
41 typedef struct ldb_context ldb;
42 typedef struct ldb_dn ldb_dn;
43 typedef struct ldb_ldif ldb_ldif;
44 typedef struct ldb_message_element ldb_msg_element;
45 typedef int ldb_error;
46
47 %}
48
49 %import "carrays.i"
50 %import "typemaps.i"
51 %include "exception.i"
52 %import "stdint.i"
53
54 %constant int SCOPE_DEFAULT = LDB_SCOPE_DEFAULT;
55 %constant int SCOPE_BASE = LDB_SCOPE_BASE;
56 %constant int SCOPE_ONELEVEL = LDB_SCOPE_ONELEVEL;
57 %constant int SCOPE_SUBTREE = LDB_SCOPE_SUBTREE;
58
59 %constant int CHANGETYPE_NONE = LDB_CHANGETYPE_NONE;
60 %constant int CHANGETYPE_ADD = LDB_CHANGETYPE_ADD;
61 %constant int CHANGETYPE_DELETE = LDB_CHANGETYPE_DELETE;
62 %constant int CHANGETYPE_MODIFY = LDB_CHANGETYPE_MODIFY;
63
64 /* 
65  * Wrap struct ldb_context
66  */
67
68 /* The ldb functions will crash if a NULL ldb context is passed so
69    catch this before it happens. */
70
71 %typemap(check) struct ldb_context* {
72         if ($1 == NULL)
73                 SWIG_exception(SWIG_ValueError, 
74                         "ldb context must be non-NULL");
75 }
76
77 %typemap(check) ldb_msg * {
78         if ($1 == NULL)
79                 SWIG_exception(SWIG_ValueError, 
80                         "Message can not be None");
81 }
82
83 /* 
84  * Wrap a small bit of talloc
85  */
86
87 /*
88  * Wrap struct ldb_val
89  */
90
91 %typemap(in) struct ldb_val *INPUT (struct ldb_val temp) {
92         $1 = &temp;
93         if (!PyString_Check($input)) {
94                 PyErr_SetString(PyExc_TypeError, "string arg expected");
95                 return NULL;
96         }
97         $1->length = PyString_Size($input);
98         $1->data = PyString_AsString($input);
99 }
100
101 %typemap(out) struct ldb_val {
102         $result = PyString_FromStringAndSize((const char *)$1.data, $1.length);
103 }
104
105 %typemap(in) ldb_msg *add_msg (int dict_pos, int msg_pos, PyObject *key, 
106                                PyObject *value, ldb_msg_element *msgel) {
107     if (PyDict_Check($input)) {
108         $1 = ldb_msg_new(NULL);
109         $1->num_elements = PyDict_Size($input) - 1; /* dn isn't in there */
110         $1->elements = talloc_zero_array($1, struct ldb_message_element, $1->num_elements+1);
111         msg_pos = dict_pos = 0;
112         while (PyDict_Next($input, &dict_pos, &key, &value)) {
113             if (!strcmp(PyString_AsString(key), "dn")) {
114                 if (ldb_dn_from_pyobject(value, &$1->dn) != 0)
115                     SWIG_exception(SWIG_TypeError, "unable to convert dn");
116             } else {
117                 msgel = ldb_msg_element_from_pyobject(value, 0, PyString_AsString(key));
118                 memcpy(&$1->elements[msg_pos], msgel, sizeof(*msgel));
119                 msg_pos++;
120             }
121             dict_pos++;
122         }
123
124         if ($1->dn == NULL)
125             SWIG_exception(SWIG_TypeError, "no dn set");
126     } else {
127         if (SWIG_ConvertPtr($input, &$1, SWIGTYPE_p_ldb_message, 0) != 0)
128             return NULL;
129     }
130 }
131
132 %typemap(freearg) ldb_msg *add_msg {
133 //talloc_free($1);
134 }
135
136
137 /*
138  * Wrap struct ldb_result
139  */
140
141 %typemap(in, numinputs=0) struct ldb_result **OUT (struct ldb_result *temp_ldb_result) {
142         $1 = &temp_ldb_result;
143 }
144
145 #ifdef SWIGPYTHON
146 %typemap(argout) struct ldb_result ** (int i) {
147         $result = PyList_New((*$1)->count);
148     for (i = 0; i < (*$1)->count; i++) {
149         PyList_SetItem($result, i, 
150             SWIG_NewPointerObj((*$1)->msgs[i], SWIGTYPE_p_ldb_message, 0)
151         );
152     }
153 }
154
155 %typemap(in, numinputs=1) const char * const *attrs {
156     if ($input == Py_None) {
157         $1 = NULL;
158     } else if (PySequence_Check($input)) {
159         int i;
160         $1 = talloc_array(NULL, char *, PySequence_Size($input)+1);
161         for(i = 0; i < PySequence_Size($input); i++)
162             $1[i] = PyString_AsString(PySequence_GetItem($input, i));
163         $1[i] = NULL;
164     } else {
165         SWIG_exception(SWIG_TypeError, "expected sequence");
166     }
167 }
168
169 %typemap(freearg) const char * const *attrs {
170     talloc_free($1);
171 }
172 #endif
173
174 %types(struct ldb_result *);
175
176 /*
177  * Wrap struct ldb_dn
178  */
179
180 %rename(__str__) ldb_dn::get_linearized;
181 %rename(__cmp__) ldb_dn::compare;
182 %rename(__len__) ldb_dn::get_comp_num;
183 %rename(Dn) ldb_dn;
184 typedef struct ldb_dn {
185     %extend {
186         ldb_dn(ldb *ldb, const char *str)
187         {
188             ldb_dn *ret = ldb_dn_new(ldb, ldb, str);
189             /* ldb_dn_new() doesn't accept NULL as memory context, so 
190                we do it this way... */
191             talloc_steal(NULL, ret);
192
193             if (ret == NULL)
194                 SWIG_exception(SWIG_ValueError, 
195                                 "unable to parse dn string");
196 fail:
197             return ret;
198         }
199         ~ldb_dn() { talloc_free($self); }
200         bool validate();
201         const char *get_casefold();
202         const char *get_linearized();
203         ldb_dn *parent() { return ldb_dn_get_parent(NULL, $self); }
204         int compare(ldb_dn *other);
205         bool is_valid();
206         bool is_special();
207         bool is_null();
208         bool check_special(const char *name);
209         int get_comp_num();
210         bool add_child(ldb_dn *child);
211         bool add_base(ldb_dn *base);
212         const char *canonical_str() {
213             return ldb_dn_canonical_string($self, $self);
214         }
215         const char *canonical_ex_str() {
216             return ldb_dn_canonical_ex_string($self, $self);
217         }
218 #ifdef SWIGPYTHON
219         ldb_dn *__add__(ldb_dn *other)
220         {
221             ldb_dn *ret = ldb_dn_copy(NULL, $self);
222             ldb_dn_add_child(ret, other);
223             return ret;
224         }
225
226         /* FIXME: implement __getslice__ */
227 #endif
228     }
229 } ldb_dn;
230
231 #ifdef SWIGPYTHON
232 %inline {
233 int ldb_dn_from_pyobject(PyObject *object, ldb_dn **dn)
234 {
235     return SWIG_ConvertPtr(object, dn, SWIGTYPE_p_ldb_dn, 0);
236 }
237
238 ldb_msg_element *ldb_msg_element_from_pyobject(PyObject *set_obj, int flags,
239                                                const char *attr_name)
240 {
241     struct ldb_message_element *me = talloc(NULL, struct ldb_message_element);
242     me->name = attr_name;
243     me->flags = flags;
244     if (PyString_Check(set_obj)) {
245         me->num_values = 1;
246         me->values = talloc_array(me, struct ldb_val, me->num_values);
247         me->values[0].length = PyString_Size(set_obj);
248         me->values[0].data = (uint8_t *)talloc_strdup(me->values, 
249                                            PyString_AsString(set_obj));
250     } else if (PySequence_Check(set_obj)) {
251         int i;
252         me->num_values = PySequence_Size(set_obj);
253         me->values = talloc_array(me, struct ldb_val, me->num_values);
254         for (i = 0; i < me->num_values; i++) {
255             PyObject *obj = PySequence_GetItem(set_obj, i);
256             me->values[i].length = PyString_Size(obj);
257             me->values[i].data = (uint8_t *)PyString_AsString(obj);
258         }
259     } else {
260         talloc_free(me);
261         me = NULL;
262     }
263
264     return me;
265 }
266
267 PyObject *ldb_msg_element_to_set(ldb_msg_element *me)
268 {
269     int i;
270     PyObject *result;
271
272     /* Python << 2.5 doesn't have PySet_New and PySet_Add. */
273     result = PyList_New(me->num_values);
274
275     for (i = 0; i < me->num_values; i++) {
276         PyList_SetItem(result, i,
277             PyString_FromStringAndSize((const char *)me->values[i].data, 
278                                        me->values[i].length));
279     }
280
281     return result;
282 }
283
284 }
285 #endif
286
287 /* ldb_message_element */
288 %rename(__cmp__) ldb_message_element::compare;
289 %rename(MessageElement) ldb_msg_element;
290 typedef struct ldb_message_element {
291     %extend {
292 #ifdef SWIGPYTHON
293         PyObject *__iter__(void)
294         {
295             return PyObject_GetIter(ldb_msg_element_to_set($self));
296         }
297
298         PyObject *__set__(void)
299         {
300             return ldb_msg_element_to_set($self);
301         }
302
303         ldb_msg_element(PyObject *set_obj, int flags=0, const char *name = NULL)
304         {
305             return ldb_msg_element_from_pyobject(set_obj, flags, name);
306         }
307 #endif
308         ~ldb_msg_element() { talloc_free($self); }
309         int compare(ldb_msg_element *);
310     }
311 } ldb_msg_element;
312
313 /* ldb_message */
314
315 %rename(Message) ldb_message;
316 #ifdef SWIGPYTHON
317 %rename(__delitem__) ldb_message::remove_attr;
318 %typemap(out) ldb_msg_element * {
319         if ($1 == NULL)
320                 PyErr_SetString(PyExc_KeyError, "no such element");
321     else
322         $result = SWIG_NewPointerObj($1, SWIGTYPE_p_ldb_message_element, 0);
323 }
324 %rename(__getitem__) ldb_message::find_element;
325 //%typemap(out) ldb_msg_element *;
326
327
328 %inline {
329     PyObject *ldb_msg_list_elements(ldb_msg *msg)
330     {
331         int i;
332         PyObject *obj = PyList_New(msg->num_elements);
333         for (i = 0; i < msg->num_elements; i++)
334             PyList_SetItem(obj, i, PyString_FromString(msg->elements[i].name));
335         return obj;
336     }
337 }
338
339 #endif
340
341 typedef struct ldb_message {
342         ldb_dn *dn;
343
344     %extend {
345         ldb_msg(ldb_dn *dn = NULL) { 
346             ldb_msg *ret = ldb_msg_new(NULL); 
347             ret->dn = talloc_reference(ret, dn);
348             return ret;
349         }
350         ~ldb_msg() { talloc_free($self); }
351
352         ldb_msg_element *find_element(const char *name);
353         
354 #ifdef SWIGPYTHON
355         void __setitem__(const char *attr_name, ldb_msg_element *val)
356         {
357             struct ldb_message_element *el;
358             
359             ldb_msg_remove_attr($self, attr_name);
360
361             el = talloc($self, struct ldb_message_element);
362             el->name = talloc_strdup(el, attr_name);
363             el->num_values = val->num_values;
364             el->values = talloc_reference(el, val->values);
365
366             ldb_msg_add($self, el, val->flags);
367         }
368
369         void __setitem__(const char *attr_name, PyObject *val)
370         {
371             struct ldb_message_element *el = ldb_msg_element_from_pyobject(
372                                                 val, 0, attr_name);
373             talloc_steal($self, el);
374             ldb_msg_remove_attr($self, attr_name);
375             ldb_msg_add($self, el, el->flags);
376         }
377
378         unsigned int __len__() { return $self->num_elements; }
379
380         PyObject *keys(void)
381         {
382             return ldb_msg_list_elements($self);
383         }
384
385         PyObject *__iter__(void)
386         {
387             return PyObject_GetIter(ldb_msg_list_elements($self));
388         }
389 #endif
390         void remove_attr(const char *name);
391     }
392 } ldb_msg;
393
394 /* FIXME: Convert ldb_result to 3-tuple:
395    (msgs, refs, controls)
396  */
397
398 typedef struct ldb_ldif ldb_ldif;
399
400 #ifdef SWIGPYTHON
401 %{
402 static void py_ldb_debug(void *context, enum ldb_debug_level level, const char *fmt, va_list ap)
403 {
404     char *text;
405     PyObject *fn = context;
406
407     vasprintf(&text, fmt, ap);
408     PyObject_CallFunction(fn, "(i,s)", level, text);
409     free(text);
410 }
411 %}
412
413 %typemap(in,numinputs=1) (void (*debug)(void *context, enum ldb_debug_level level, const char *fmt, va_list ap),
414                             void *context) {
415     $1 = py_ldb_debug;
416     /* FIXME: Should be decreased somewhere as well. Perhaps register a destructor and 
417        tie it to the ldb context ? */
418     Py_INCREF($input);
419     $2 = $input;
420 }
421 #endif
422
423 %inline {
424     static PyObject *ldb_ldif_to_pyobject(ldb_ldif *ldif)
425     {
426         if (ldif == NULL) {
427             return Py_None;
428         } else {
429             return Py_BuildValue("(iO)", ldif->changetype, 
430                    SWIG_NewPointerObj(ldif->msg, SWIGTYPE_p_ldb_message, 0));
431         }
432     }
433 }
434
435 /*
436  * Wrap ldb errors
437  */
438
439 %{
440 PyObject *PyExc_LdbError;
441 %}
442
443 %pythoncode %{
444     LdbError = _ldb.LdbError
445 %}
446
447 %init %{
448     PyExc_LdbError = PyErr_NewException("_ldb.LdbError", NULL, NULL);
449     PyDict_SetItemString(d, "LdbError", PyExc_LdbError);
450 %}
451
452 %ignore _LDB_ERRORS_H_;
453 %ignore LDB_SUCCESS;
454 %include "include/ldb_errors.h"
455
456 /*
457  * Wrap ldb functions 
458  */
459
460 %rename(Ldb) ldb;
461 /* Top-level ldb operations */
462 typedef struct ldb_context {
463     %typemap(out) ldb_error {
464         if ($1 != LDB_SUCCESS) {
465             PyErr_SetObject(PyExc_LdbError, Py_BuildValue("(i,s)", $1, ldb_strerror($1)));
466             SWIG_fail;
467         }
468         $result = Py_None;
469     };
470     %extend {
471         ldb(const char *url=NULL, unsigned int flags = 0, 
472             const char *options[] = NULL)
473         {
474             ldb *ldb = ldb_init(NULL);
475             
476             if (url != NULL) {
477                 int ret;
478
479                 ret = ldb_connect(ldb, url, flags, options);
480                 if (ret != LDB_SUCCESS)
481                     SWIG_exception(SWIG_ValueError, ldb_errstring(ldb));
482             }
483
484             return ldb;
485
486 fail:
487             talloc_free(ldb);
488             return NULL;
489         }
490
491         ldb_error connect(const char *url, unsigned int flags = 0, 
492             const char *options[] = NULL);
493
494         ~ldb() { talloc_free($self); }
495         ldb_error search(ldb_dn *base = NULL, 
496                    enum ldb_scope scope = LDB_SCOPE_DEFAULT, 
497                    const char *expression = NULL, 
498                    const char * const *attrs = NULL, 
499                    struct ldb_result **OUT);
500         ldb_error delete(ldb_dn *dn);
501         ldb_error rename(ldb_dn *olddn, ldb_dn *newdn);
502         ldb_error add(ldb_msg *add_msg);
503         ldb_error modify(ldb_msg *message);
504         ldb_dn *get_config_basedn();
505         ldb_dn *get_root_basedn();
506         ldb_dn *get_schema_basedn();
507         ldb_dn *get_default_basedn();
508         const char *errstring();
509         void set_create_perms(unsigned int perms);
510         void set_modules_dir(const char *path);
511         ldb_error set_debug(void (*debug)(void *context, enum ldb_debug_level level, 
512                                           const char *fmt, va_list ap),
513                             void *context);
514         ldb_error set_opaque(const char *name, void *value);
515         void *get_opaque(const char *name);
516         ldb_error transaction_start();
517         ldb_error transaction_commit();
518         ldb_error transaction_cancel();
519
520 #ifdef SWIGPYTHON
521         bool __contains__(ldb_dn *dn)
522         {
523             struct ldb_result *result;
524             
525             int ret = ldb_search($self, dn, LDB_SCOPE_BASE, NULL, NULL, 
526                              &result);
527
528             /* FIXME: Check ret and set exception if necessary */
529
530             return result->count > 0;
531         }
532
533         PyObject *parse_ldif(const char *s)
534         {
535             PyObject *list = PyList_New(0);
536             struct ldb_ldif *ldif;
537             while ((ldif = ldb_ldif_read_string($self, &s)) != NULL) {
538                 PyList_Append(list, ldb_ldif_to_pyobject(ldif));
539             }
540             return PyObject_GetIter(list);
541         }
542
543 #endif
544     }
545 } ldb;
546
547 %nodefault ldb_message;
548 %nodefault Ldb;
549 %nodefault Dn;
550
551 %rename(valid_attr_name) ldb_valid_attr_name;
552 int ldb_valid_attr_name(const char *s);
553
554 typedef unsigned long time_t;
555
556 %inline %{
557 static char *timestring(time_t t)
558 {
559     char *tresult = ldb_timestring(NULL, t);
560     char *result = strdup(tresult);
561     talloc_free(tresult);
562     return result; 
563 }
564 %}
565
566 %rename(string_to_time) ldb_string_to_time;
567 time_t ldb_string_to_time(const char *s);