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