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