Merge branch 'master' of ssh://git.samba.org/data/git/samba
[ira/wip.git] / source4 / lib / ldb / pyldb.c
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-2008 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 #include <stdint.h>
29 #include <stdbool.h>
30 #include "pyldb.h"
31 #include "events.h"
32 #include "ldb.h"
33 #include "ldb_errors.h"
34 #include "ldb_private.h"
35
36 PyObject *PyExc_LdbError;
37
38 void PyErr_SetLdbError(int ret, struct ldb_context *ldb_ctx)
39 {
40         PyErr_SetObject(PyExc_LdbError, Py_BuildValue((char *)"(i,s)", ret, ldb_ctx == NULL?ldb_strerror(ret):ldb_errstring(ldb_ctx)));
41 }
42 PyObject *PyObject_FromLdbValue(struct ldb_context *ldb_ctx, 
43                                struct ldb_message_element *el, 
44                                struct ldb_val *val)
45 {
46         const struct ldb_schema_attribute *a;
47         struct ldb_val new_val;
48         TALLOC_CTX *mem_ctx = talloc_new(NULL);
49         PyObject *ret;
50         
51         new_val = *val;
52         
53         if (ldb_ctx != NULL) {        
54                 a = ldb_schema_attribute_by_name(ldb_ctx, el->name);
55         
56                 if (a != NULL) {
57                         if (a->syntax->ldif_write_fn(ldb_ctx, mem_ctx, val, &new_val) != 0) {
58                                 talloc_free(mem_ctx);
59                                 return NULL;
60                         }
61                 }
62         } 
63         
64         ret = PyString_FromStringAndSize((const char *)new_val.data, new_val.length);
65         
66         talloc_free(mem_ctx);
67         
68         return ret;
69 }
70
71 bool PyObject_AsDn(TALLOC_CTX *mem_ctx, PyObject *object, 
72                          struct ldb_context *ldb_ctx, struct ldb_dn **dn)
73 {
74     struct ldb_dn *odn;
75
76     if (ldb_ctx != NULL && PyString_Check(object)) {
77         odn = ldb_dn_new(mem_ctx, ldb_ctx, PyString_AsString(object));
78                 *dn = odn;
79         return true;
80     }
81         if (PyLdbDn_Check(object)) {
82                 *dn = PyLdbDn_AsDn(object);
83                 return true;
84         }
85
86         PyErr_SetString(PyExc_TypeError, "Expected DN");
87         return false;
88 }
89
90 static PyObject *PyLdbResult_FromResult(struct ldb_result *result)
91 {
92         PyObject *ret;
93         int i;
94     if (result == NULL) {
95         return Py_None;
96     } 
97         ret = PyList_New(result->count);
98         for (i = 0; i < result->count; i++) {
99                 PyList_SetItem(ret, i, 
100                                            PyLdbMessage_FromMessage(result->msgs[i])
101                 );
102         }
103         return ret;
104 }
105
106 static struct ldb_result *PyLdbResult_AsResult(TALLOC_CTX *mem_ctx, PyObject *obj)
107 {
108         struct ldb_result *res;
109         int i;
110         
111         if (obj == Py_None)
112                 return NULL;
113
114         res = talloc_zero(mem_ctx, struct ldb_result);
115         res->count = PyList_Size(obj);
116         res->msgs = talloc_array(res, struct ldb_message *, res->count);
117         for (i = 0; i < res->count; i++) {
118                 PyObject *item = PyList_GetItem(obj, i);
119                 res->msgs[i] = PyLdbMessage_AsMessage(item);
120         }
121         return res;
122 }
123
124 static PyObject *py_ldb_dn_validate(PyLdbDnObject *self)
125 {
126         return PyBool_FromLong(ldb_dn_validate(self->ptr));
127 }
128
129 static PyObject *py_ldb_dn_is_valid(PyLdbDnObject *self)
130 {
131         return PyBool_FromLong(ldb_dn_is_valid(self->ptr));
132 }
133
134 static PyObject *py_ldb_dn_is_special(PyLdbDnObject *self)
135 {
136         return PyBool_FromLong(ldb_dn_is_special(self->ptr));
137 }
138
139 static PyObject *py_ldb_dn_is_null(PyLdbDnObject *self)
140 {
141         return PyBool_FromLong(ldb_dn_is_null(self->ptr));
142 }
143  
144 static PyObject *py_ldb_dn_get_casefold(PyLdbDnObject *self)
145 {
146         return PyString_FromString(ldb_dn_get_casefold(self->ptr));
147 }
148
149 static PyObject *py_ldb_dn_get_linearized(PyLdbDnObject *self)
150 {
151         return PyString_FromString(ldb_dn_get_linearized(self->ptr));
152 }
153
154 static PyObject *py_ldb_dn_canonical_str(PyLdbDnObject *self)
155 {
156         return PyString_FromString(ldb_dn_canonical_string(self->ptr, self->ptr));
157 }
158
159 static PyObject *py_ldb_dn_canonical_ex_str(PyLdbDnObject *self)
160 {
161         return PyString_FromString(ldb_dn_canonical_ex_string(self->ptr, self->ptr));
162 }
163
164 static PyObject *py_ldb_dn_repr(PyLdbDnObject *self)
165 {
166         return PyString_FromFormat("Dn('%s')", ldb_dn_get_linearized(self->ptr));
167 }
168
169 static PyObject *py_ldb_dn_check_special(PyLdbDnObject *self, PyObject *args)
170 {
171         char *name;
172
173         if (!PyArg_ParseTuple(args, "s", &name))
174                 return NULL;
175
176         return ldb_dn_check_special(self->ptr, name)?Py_True:Py_False;
177 }
178
179 static int py_ldb_dn_compare(PyLdbDnObject *dn1, PyLdbDnObject *dn2)
180 {
181         return ldb_dn_compare(dn1->ptr, dn2->ptr);
182 }
183
184 static PyObject *py_ldb_dn_get_parent(PyLdbDnObject *self)
185 {
186         struct ldb_dn *dn = PyLdbDn_AsDn((PyObject *)self);
187         return PyLdbDn_FromDn(ldb_dn_get_parent(NULL, dn));
188 }
189
190 #define dn_ldb_ctx(dn) ((struct ldb_context *)dn)
191
192 static PyObject *py_ldb_dn_add_child(PyLdbDnObject *self, PyObject *args)
193 {
194         PyObject *py_other;
195         struct ldb_dn *dn, *other;
196         if (!PyArg_ParseTuple(args, "O", &other))
197                 return NULL;
198
199         dn = PyLdbDn_AsDn((PyObject *)self);
200
201         if (!PyObject_AsDn(NULL, py_other, dn_ldb_ctx(dn), &other))
202                 return NULL;
203
204         return ldb_dn_add_child(dn, other)?Py_True:Py_False;
205 }
206
207 static PyObject *py_ldb_dn_add_base(PyLdbDnObject *self, PyObject *args)
208 {
209         PyObject *py_other;
210         struct ldb_dn *other, *dn;
211         if (!PyArg_ParseTuple(args, "O", &other))
212                 return NULL;
213
214         dn = PyLdbDn_AsDn((PyObject *)self);
215
216         if (!PyObject_AsDn(NULL, py_other, dn_ldb_ctx(dn), &other))
217                 return NULL;
218
219         return ldb_dn_add_base(dn, other)?Py_True:Py_False;
220 }
221
222 static PyMethodDef py_ldb_dn_methods[] = {
223         { "validate", (PyCFunction)py_ldb_dn_validate, METH_NOARGS, 
224                 "S.validate() -> bool\n"
225                 "Validate DN is correct." },
226         { "is_valid", (PyCFunction)py_ldb_dn_is_valid, METH_NOARGS,
227                 "S.is_valid() -> bool\n" },
228         { "is_special", (PyCFunction)py_ldb_dn_is_special, METH_NOARGS,
229                 "S.is_special() -> bool\n"
230                 "Check whether this is a special LDB DN." },
231         { "is_null", (PyCFunction)py_ldb_dn_is_null, METH_NOARGS,
232                 "Check whether this is a null DN." },
233         { "get_casefold", (PyCFunction)py_ldb_dn_get_casefold, METH_NOARGS,
234                 NULL },
235         { "get_linearized", (PyCFunction)py_ldb_dn_get_linearized, METH_NOARGS,
236                 NULL },
237         { "canonical_str", (PyCFunction)py_ldb_dn_canonical_str, METH_NOARGS,
238                 "S.canonical_str() -> string\n"
239                 "Canonical version of this DN (like a posix path)." },
240         { "canonical_ex_str", (PyCFunction)py_ldb_dn_canonical_ex_str, METH_NOARGS,
241                 "S.canonical_ex_str() -> string\n"
242                 "Canonical version of this DN (like a posix path, with terminating newline)." },
243         { "check_special", (PyCFunction)py_ldb_dn_is_special, METH_VARARGS, 
244                 NULL },
245         { "parent", (PyCFunction)py_ldb_dn_get_parent, METH_NOARGS,
246                 "S.parent() -> dn\n"
247                 "Get the parent for this DN." },
248         { "add_child", (PyCFunction)py_ldb_dn_add_child, METH_VARARGS, 
249                 "S.add_child(dn) -> None\n"
250                 "Add a child DN to this DN." },
251         { "add_base", (PyCFunction)py_ldb_dn_add_base, METH_VARARGS,
252         "S.add_base(dn) -> None\n"
253                 "Add a base DN to this DN." },
254         { "check_special", (PyCFunction)py_ldb_dn_check_special, METH_VARARGS,
255                 NULL },
256         { NULL }
257 };
258
259 static Py_ssize_t py_ldb_dn_len(PyLdbDnObject *self)
260 {
261         return ldb_dn_get_comp_num(PyLdbDn_AsDn((PyObject *)self));
262 }
263
264 static PyObject *py_ldb_dn_concat(PyLdbDnObject *self, PyObject *py_other)
265 {
266         struct ldb_dn *dn = PyLdbDn_AsDn((PyObject *)self), 
267                                   *other;
268         struct ldb_dn *ret = ldb_dn_copy(NULL, dn);
269         if (!PyObject_AsDn(NULL, py_other, NULL, &other))
270                 return NULL;
271         ldb_dn_add_child(ret, other);
272         return PyLdbDn_FromDn(ret);
273 }
274
275 static PySequenceMethods py_ldb_dn_seq = {
276         .sq_length = (lenfunc)py_ldb_dn_len,
277         .sq_concat = (binaryfunc)py_ldb_dn_concat,
278 };
279
280 static PyObject *py_ldb_dn_new(PyTypeObject *type, PyObject *args, PyObject *kwargs)
281 {
282         struct ldb_dn *ret;
283         char *str;
284         PyObject *py_ldb;
285         struct ldb_context *ldb_ctx;
286         const char *kwnames[] = { "ldb", "dn", NULL };
287
288         if (!PyArg_ParseTupleAndKeywords(args, kwargs, "Os", (char **)kwnames, &py_ldb, &str))
289                 return NULL;
290
291         ldb_ctx = PyLdb_AsLdbContext(py_ldb);
292         
293         ret = ldb_dn_new(ldb_ctx, ldb_ctx, str);
294         /* ldb_dn_new() doesn't accept NULL as memory context, so 
295            we do it this way... */
296         talloc_steal(NULL, ret);
297
298         if (ret == NULL || !ldb_dn_validate(ret)) {
299                 PyErr_SetString(PyExc_ValueError, "unable to parse dn string");
300                 return NULL;
301         }
302
303         return py_talloc_import(&PyLdbDn, ret);
304 }
305
306 PyObject *PyLdbDn_FromDn(struct ldb_dn *dn)
307 {
308         return py_talloc_import(&PyLdbDn, dn);
309 }
310
311 PyTypeObject PyLdbDn = {
312         .tp_name = "Dn",
313         .tp_methods = py_ldb_dn_methods,
314         .tp_str = (reprfunc)py_ldb_dn_get_linearized,
315         .tp_repr = (reprfunc)py_ldb_dn_repr,
316         .tp_compare = (cmpfunc)py_ldb_dn_compare,
317         .tp_as_sequence = &py_ldb_dn_seq,
318         .tp_doc = "A LDB distinguished name.",
319         .tp_new = py_ldb_dn_new,
320         .tp_dealloc = py_talloc_dealloc,
321         .tp_basicsize = sizeof(PyLdbObject),
322 };
323
324 /* Debug */
325 static void py_ldb_debug(void *context, enum ldb_debug_level level, const char *fmt, va_list ap) PRINTF_ATTRIBUTE(3, 0);
326 static void py_ldb_debug(void *context, enum ldb_debug_level level, const char *fmt, va_list ap)
327 {
328     PyObject *fn = context;
329     PyObject_CallFunction(fn, (char *)"(i,O)", level, PyString_FromFormatV(fmt, ap));
330 }
331
332 static PyObject *py_ldb_set_debug(PyLdbObject *self, PyObject *args)
333 {
334         PyObject *cb;
335         
336         if (!PyArg_ParseTuple(args, "O", &cb))
337                 return NULL;
338
339         Py_INCREF(cb);
340         /* FIXME: Where do we DECREF cb ? */
341         PyErr_LDB_ERROR_IS_ERR_RAISE(ldb_set_debug(self->ptr, py_ldb_debug, cb), PyLdb_AsLdbContext(self));
342         
343         return Py_None;
344 }
345
346 static PyObject *py_ldb_set_create_perms(PyTypeObject *self, PyObject *args)
347 {
348         unsigned int perms;
349         if (!PyArg_ParseTuple(args, "I", &perms))
350                 return NULL;
351
352         ldb_set_create_perms(PyLdb_AsLdbContext(self), perms);
353
354         return Py_None;
355 }
356
357 static PyObject *py_ldb_set_modules_dir(PyTypeObject *self, PyObject *args)
358 {
359         char *modules_dir;
360         if (!PyArg_ParseTuple(args, "s", &modules_dir))
361                 return NULL;
362
363         ldb_set_modules_dir(PyLdb_AsLdbContext(self), modules_dir);
364
365         return Py_None;
366 }
367
368 static PyObject *py_ldb_transaction_start(PyLdbObject *self)
369 {
370         PyErr_LDB_ERROR_IS_ERR_RAISE(ldb_transaction_start(PyLdb_AsLdbContext(self)), PyLdb_AsLdbContext(self));
371         return Py_None;
372 }
373
374 static PyObject *py_ldb_transaction_commit(PyLdbObject *self)
375 {
376         PyErr_LDB_ERROR_IS_ERR_RAISE(ldb_transaction_commit(PyLdb_AsLdbContext(self)), PyLdb_AsLdbContext(self));
377         return Py_None;
378 }
379
380 static PyObject *py_ldb_transaction_cancel(PyLdbObject *self)
381 {
382         PyErr_LDB_ERROR_IS_ERR_RAISE(ldb_transaction_cancel(PyLdb_AsLdbContext(self)), PyLdb_AsLdbContext(self));
383         return Py_None;
384 }
385
386 static PyObject *py_ldb_setup_wellknown_attributes(PyLdbObject *self)
387 {
388         PyErr_LDB_ERROR_IS_ERR_RAISE(ldb_setup_wellknown_attributes(PyLdb_AsLdbContext(self)), PyLdb_AsLdbContext(self));
389         return Py_None;
390 }
391
392 static PyObject *py_ldb_repr(PyLdbObject *self)
393 {
394         return PyString_FromFormat("<ldb connection>");
395 }
396
397 static PyObject *py_ldb_get_root_basedn(PyLdbObject *self)
398 {
399         struct ldb_dn *dn = ldb_get_root_basedn(PyLdb_AsLdbContext(self));
400         if (dn == NULL)
401                 return Py_None;
402         return PyLdbDn_FromDn(dn);
403 }
404
405
406 static PyObject *py_ldb_get_schema_basedn(PyLdbObject *self)
407 {
408         struct ldb_dn *dn = ldb_get_schema_basedn(PyLdb_AsLdbContext(self));
409         if (dn == NULL)
410                 return Py_None;
411         return PyLdbDn_FromDn(dn);
412 }
413
414
415 static PyObject *py_ldb_get_config_basedn(PyLdbObject *self)
416 {
417         struct ldb_dn *dn = ldb_get_config_basedn(PyLdb_AsLdbContext(self));
418         if (dn == NULL)
419                 return Py_None;
420         return PyLdbDn_FromDn(dn);
421 }
422
423
424 static PyObject *py_ldb_get_default_basedn(PyLdbObject *self)
425 {
426         struct ldb_dn *dn = ldb_get_default_basedn(PyLdb_AsLdbContext(self));
427         if (dn == NULL)
428                 return Py_None;
429         return PyLdbDn_FromDn(dn);
430 }
431
432 static const char **PyList_AsStringList(TALLOC_CTX *mem_ctx, PyObject *list)
433 {
434         const char **ret;
435         int i;
436         if (!PyList_Check(list)) {
437                 PyErr_SetString(PyExc_TypeError, "options is not a list");
438                 return NULL;
439         }
440         ret = talloc_array(NULL, const char *, PyList_Size(list)+1);
441         for (i = 0; i < PyList_Size(list); i++) {
442                 PyObject *item = PyList_GetItem(list, i);
443                 if (!PyString_Check(item)) {
444                         PyErr_SetString(PyExc_TypeError, "options should be strings");
445                         return NULL;
446                 }
447                 ret[i] = PyString_AsString(item);
448         }
449         ret[i] = NULL;
450         return ret;
451 }
452
453 static PyObject *py_ldb_new(PyTypeObject *type, PyObject *args, PyObject *kwargs)
454 {
455         struct ldb_context *ldb;
456         const char *kwnames[] = { "url", "flags", "options", NULL };
457         char *url = NULL;
458         PyObject *py_options = Py_None;
459         const char **options;
460         int flags = 0;
461         int ret;
462
463         if (!PyArg_ParseTupleAndKeywords(args, kwargs, "|ziO", (char **)kwnames,
464                                                                          &url, &flags, &py_options))
465                 return NULL;
466
467         ldb = ldb_init(NULL, event_context_init(NULL)); 
468         if (ldb == NULL) {
469                 PyErr_NoMemory();
470                 return NULL;
471         }
472
473         if (py_options == Py_None) {
474                 options = NULL;
475         } else {
476                 options = PyList_AsStringList(ldb, py_options);
477                 if (options == NULL)
478                         return NULL;
479         }
480         
481         if (url != NULL) {
482                 ret = ldb_connect(ldb, url, flags, options);
483                 PyErr_LDB_ERROR_IS_ERR_RAISE(ret, ldb);
484         }
485
486         talloc_free(options);
487
488         return py_talloc_import(&PyLdb, ldb);
489 }
490
491 static PyObject *py_ldb_connect(PyLdbObject *self, PyObject *args, PyObject *kwargs)
492 {
493         char *url;
494         int flags;
495         PyObject *py_options = Py_None;
496         int ret;
497         const char **options;
498         const char *kwnames[] = { "url", "flags", "options", NULL };
499         if (!PyArg_ParseTupleAndKeywords(args, kwargs, "s|iO", (char **)kwnames, &url, &flags,
500                                                                          &py_options))
501                 return NULL;
502
503         if (py_options == Py_None) {
504                 options = NULL;
505         } else {
506                 options = PyList_AsStringList(NULL, py_options);
507                 if (options == NULL)
508                         return NULL;
509         }
510         
511         ret = ldb_connect(PyLdb_AsLdbContext(self), url, flags, options);
512         talloc_free(options);
513
514         PyErr_LDB_ERROR_IS_ERR_RAISE(ret, PyLdb_AsLdbContext(self));
515
516         return Py_None;
517 }
518
519 static PyObject *py_ldb_modify(PyLdbObject *self, PyObject *args)
520 {
521         PyObject *py_msg;
522         int ret;
523         if (!PyArg_ParseTuple(args, "O", &py_msg))
524                 return NULL;
525
526         if (!PyLdbMessage_Check(py_msg)) {
527                 PyErr_SetString(PyExc_TypeError, "Expected Ldb Message");
528                 return NULL;
529         }
530
531         ret = ldb_modify(PyLdb_AsLdbContext(self), PyLdbMessage_AsMessage(py_msg));
532         PyErr_LDB_ERROR_IS_ERR_RAISE(ret, PyLdb_AsLdbContext(self));
533
534         return Py_None;
535 }
536
537 static PyObject *py_ldb_add(PyLdbObject *self, PyObject *args)
538 {
539         PyObject *py_msg;
540         int ret;
541     Py_ssize_t dict_pos, msg_pos;
542     struct ldb_message_element *msgel;
543         struct ldb_message *msg;
544     PyObject *key, *value;
545
546         if (!PyArg_ParseTuple(args, "O", &py_msg))
547                 return NULL;
548
549     if (PyDict_Check(py_msg)) {
550                 PyObject *dn_value = PyDict_GetItemString(py_msg, "dn");
551         msg = ldb_msg_new(NULL);
552         msg->elements = talloc_zero_array(msg, struct ldb_message_element, PyDict_Size(py_msg));
553         msg_pos = dict_pos = 0;
554                 if (dn_value) {
555                 if (!PyObject_AsDn(msg, dn_value, PyLdb_AsLdbContext(self), &msg->dn)) {
556                         PyErr_SetString(PyExc_TypeError, "unable to import dn object");
557                                 return NULL;
558                         }
559                         if (msg->dn == NULL) {
560                                 PyErr_SetString(PyExc_TypeError, "dn set but not found");
561                                 return NULL;
562                         }
563                 }
564
565                 while (PyDict_Next(py_msg, &dict_pos, &key, &value)) {
566                         char *key_str = PyString_AsString(key);
567                         if (strcmp(key_str, "dn") != 0) {
568                                 msgel = PyObject_AsMessageElement(msg->elements, value, 0, key_str);
569                                 if (msgel == NULL) {
570                                         PyErr_SetString(PyExc_TypeError, "unable to import element");
571                                         return NULL;
572                                 }
573                                 memcpy(&msg->elements[msg_pos], msgel, sizeof(*msgel));
574                                 msg_pos++;
575                         }
576                 }
577
578                 if (msg->dn == NULL) {
579                         PyErr_SetString(PyExc_TypeError, "no dn set");
580                         return NULL;
581                 }
582
583                 msg->num_elements = msg_pos;
584     } else {
585                 msg = PyLdbMessage_AsMessage(py_msg);
586     }
587         
588         ret = ldb_add(PyLdb_AsLdbContext(self), msg);
589         PyErr_LDB_ERROR_IS_ERR_RAISE(ret, PyLdb_AsLdbContext(self));
590
591         return Py_None;
592 }
593
594
595
596 static PyObject *py_ldb_delete(PyLdbObject *self, PyObject *args)
597 {
598         PyObject *py_dn;
599         struct ldb_dn *dn;
600         int ret;
601         if (!PyArg_ParseTuple(args, "O", &py_dn))
602                 return NULL;
603
604         if (!PyObject_AsDn(NULL, py_dn, PyLdb_AsLdbContext(self), &dn))
605                 return NULL;
606
607         ret = ldb_delete(PyLdb_AsLdbContext(self), dn);
608         PyErr_LDB_ERROR_IS_ERR_RAISE(ret, PyLdb_AsLdbContext(self));
609
610         return Py_None;
611 }
612
613 static PyObject *py_ldb_rename(PyLdbObject *self, PyObject *args)
614 {
615         PyObject *py_dn1, *py_dn2;
616         struct ldb_dn *dn1, *dn2;
617         int ret;
618         if (!PyArg_ParseTuple(args, "OO", &py_dn1, &py_dn2))
619                 return NULL;
620
621         if (!PyLdbDn_Check(py_dn1) || !PyLdbDn_Check(py_dn2)) {
622                 PyErr_SetString(PyExc_TypeError, "Expected Ldb Dn");
623                 return NULL;
624         }
625
626         if (!PyObject_AsDn(NULL, py_dn1, PyLdb_AsLdbContext(self), &dn1))
627                 return NULL;
628
629         if (!PyObject_AsDn(NULL, py_dn2, PyLdb_AsLdbContext(self), &dn2))
630                 return NULL;
631
632         ret = ldb_rename(PyLdb_AsLdbContext(self), dn1, dn2);
633         PyErr_LDB_ERROR_IS_ERR_RAISE(ret, PyLdb_AsLdbContext(self));
634
635         return Py_None;
636 }
637
638 static PyObject *py_ldb_schema_attribute_remove(PyLdbObject *self, PyObject *args)
639 {
640         char *name;
641         if (!PyArg_ParseTuple(args, "s", &name))
642                 return NULL;
643
644         ldb_schema_attribute_remove(PyLdb_AsLdbContext(self), name);
645
646         return Py_None;
647 }
648
649 static PyObject *py_ldb_schema_attribute_add(PyLdbObject *self, PyObject *args)
650 {
651         char *attribute, *syntax;
652         unsigned int flags;
653         int ret;
654         if (!PyArg_ParseTuple(args, "sIs", &attribute, &flags, &syntax))
655                 return NULL;
656
657         ret = ldb_schema_attribute_add(PyLdb_AsLdbContext(self), attribute, flags, syntax);
658
659         PyErr_LDB_ERROR_IS_ERR_RAISE(ret, PyLdb_AsLdbContext(self));
660
661         return Py_None;
662 }
663
664 static PyObject *ldb_ldif_to_pyobject(struct ldb_ldif *ldif)
665 {
666         if (ldif == NULL) {
667                 return Py_None;
668         } else {
669         /* We don't want this attached to the 'ldb' any more */
670                 talloc_steal(NULL, ldif);
671                 return Py_BuildValue((char *)"(iO)", ldif->changetype, 
672                                                          PyLdbMessage_FromMessage(ldif->msg));
673         }
674 }
675
676
677 static PyObject *py_ldb_parse_ldif(PyLdbObject *self, PyObject *args)
678 {
679         char *filename;
680         PyObject *list;
681         struct ldb_ldif *ldif;
682         const char *s;
683
684         if (!PyArg_ParseTuple(args, "s", &filename))
685                 return NULL;
686
687         list = PyList_New(0);
688         while ((ldif = ldb_ldif_read_string(self->ptr, &s)) != NULL) {
689                 PyList_Append(list, ldb_ldif_to_pyobject(ldif));
690         }
691         return PyObject_GetIter(list);
692 }
693
694 static PyObject *py_ldb_schema_format_value(PyLdbObject *self, PyObject *args)
695 {
696         const struct ldb_schema_attribute *a;
697         struct ldb_val old_val;
698         struct ldb_val new_val;
699         TALLOC_CTX *mem_ctx;
700         PyObject *ret;
701         char *element_name;
702         PyObject *val;
703
704         if (!PyArg_ParseTuple(args, "sO", &element_name, &val))
705                 return NULL;
706         
707         mem_ctx = talloc_new(NULL);
708         
709         old_val.data = (uint8_t *)PyString_AsString(val);
710         old_val.length = PyString_Size(val);
711                 
712         a = ldb_schema_attribute_by_name(PyLdb_AsLdbContext(self), element_name);
713
714         if (a == NULL) {
715                 return Py_None;
716         }
717         
718         if (a->syntax->ldif_write_fn(PyLdb_AsLdbContext(self), mem_ctx, &old_val, &new_val) != 0) {
719                 talloc_free(mem_ctx);
720                 return Py_None;
721         }
722
723         ret = PyString_FromStringAndSize((const char *)new_val.data, new_val.length);
724
725         talloc_free(mem_ctx);
726
727         return ret;
728 }
729
730 static PyObject *py_ldb_search(PyLdbObject *self, PyObject *args, PyObject *kwargs)
731 {
732         PyObject *py_base = Py_None;
733         enum ldb_scope scope = LDB_SCOPE_DEFAULT;
734         char *expr = NULL;
735         PyObject *py_attrs = Py_None;
736         PyObject *py_controls = Py_None;
737         const char *kwnames[] = { "base", "scope", "expression", "attrs", "controls", NULL };
738         int ret;
739         struct ldb_result *res;
740         struct ldb_request *req;
741         const char **attrs;
742         struct ldb_context *ldb_ctx;
743         struct ldb_control **parsed_controls;
744         struct ldb_dn *base;
745
746         if (!PyArg_ParseTupleAndKeywords(args, kwargs, "|OisOO", (char **)kwnames,
747                                                                          &py_base, &scope, &expr, &py_attrs, &py_controls))
748                 return NULL;
749
750         ldb_ctx = PyLdb_AsLdbContext(self);
751
752         if (py_attrs == Py_None) {
753                 attrs = NULL;
754         } else {
755                 attrs = PyList_AsStringList(ldb_ctx, py_attrs);
756                 if (attrs == NULL)
757                         return NULL;
758         }
759
760         if (py_base == Py_None) {
761                 base = ldb_get_default_basedn(ldb_ctx);
762         } else {
763                 if (!PyObject_AsDn(ldb_ctx, py_base, ldb_ctx, &base))
764                         return NULL;
765         }
766
767         if (py_controls == Py_None) {
768                 parsed_controls = NULL;
769         } else {
770                 const char **controls = PyList_AsStringList(ldb_ctx, py_controls);
771         parsed_controls = ldb_parse_control_strings(ldb_ctx, ldb_ctx, controls);
772                 talloc_free(controls);
773         }
774
775         res = talloc_zero(ldb_ctx, struct ldb_result);
776         if (res == NULL) {
777                 PyErr_NoMemory();
778                 return NULL;
779         }
780
781         ret = ldb_build_search_req(&req, ldb_ctx, ldb_ctx,
782                                    base,
783                                    scope,
784                                    expr,
785                                    attrs,
786                                    parsed_controls,
787                                    res,
788                                    ldb_search_default_callback,
789                                    NULL);
790
791         if (ret != LDB_SUCCESS) {
792                 talloc_free(res);
793                 PyErr_LDB_ERROR_IS_ERR_RAISE(ret, ldb_ctx);
794                 return NULL;
795         }
796
797         ret = ldb_request(ldb_ctx, req);
798                 
799         if (ret == LDB_SUCCESS) {
800                 ret = ldb_wait(req->handle, LDB_WAIT_ALL);
801         }
802
803         talloc_free(req);
804
805         return PyLdbResult_FromResult(res);
806 }
807
808 static PyObject *py_ldb_get_opaque(PyLdbObject *self, PyObject *args)
809 {
810         char *name;
811         void *data;
812
813         if (!PyArg_ParseTuple(args, "s", &name))
814                 return NULL;
815
816         data = ldb_get_opaque(PyLdb_AsLdbContext(self), name);
817
818         /* FIXME: More interpretation */
819
820         return Py_None; 
821 }
822
823 static PyObject *py_ldb_set_opaque(PyLdbObject *self, PyObject *args)
824 {
825         char *name;
826         PyObject *data;
827
828         if (!PyArg_ParseTuple(args, "sO", &name, &data))
829                 return NULL;
830
831         /* FIXME: More interpretation */
832
833         ldb_set_opaque(PyLdb_AsLdbContext(self), name, data);
834
835         return Py_None;
836 }
837
838 static PyMethodDef py_ldb_methods[] = {
839         { "set_debug", (PyCFunction)py_ldb_set_debug, METH_VARARGS, 
840                 "S.set_debug(callback) -> None\n"
841                 "Set callback for LDB debug messages.\n"
842                 "The callback should accept a debug level and debug text." },
843         { "set_create_perms", (PyCFunction)py_ldb_set_create_perms, METH_VARARGS, 
844                 "S.set_create_perms(mode) -> None\n"
845                 "Set mode to use when creating new LDB files." },
846         { "set_modules_dir", (PyCFunction)py_ldb_set_modules_dir, METH_VARARGS,
847                 "S.set_modules_dir(path) -> None\n"
848                 "Set path LDB should search for modules" },
849         { "transaction_start", (PyCFunction)py_ldb_transaction_start, METH_NOARGS, 
850                 "S.transaction_start() -> None\n"
851                 "Start a new transaction." },
852         { "transaction_commit", (PyCFunction)py_ldb_transaction_commit, METH_NOARGS, 
853                 "S.transaction_commit() -> None\n"
854                 "commit a new transaction." },
855         { "transaction_cancel", (PyCFunction)py_ldb_transaction_cancel, METH_NOARGS, 
856                 "S.transaction_cancel() -> None\n"
857                 "cancel a new transaction." },
858         { "setup_wellknown_attributes", (PyCFunction)py_ldb_setup_wellknown_attributes, METH_NOARGS, 
859                 NULL },
860         { "get_root_basedn", (PyCFunction)py_ldb_get_root_basedn, METH_NOARGS,
861                 NULL },
862         { "get_schema_basedn", (PyCFunction)py_ldb_get_schema_basedn, METH_NOARGS,
863                 NULL },
864         { "get_default_basedn", (PyCFunction)py_ldb_get_default_basedn, METH_NOARGS,
865                 NULL },
866         { "get_config_basedn", (PyCFunction)py_ldb_get_config_basedn, METH_NOARGS,
867                 NULL },
868         { "connect", (PyCFunction)py_ldb_connect, METH_VARARGS|METH_KEYWORDS, 
869                 "S.connect(url, flags=0, options=None) -> None\n"
870                 "Connect to a LDB URL." },
871         { "modify", (PyCFunction)py_ldb_modify, METH_VARARGS, 
872                 "S.modify(message) -> None\n"
873                 "Modify an entry." },
874         { "add", (PyCFunction)py_ldb_add, METH_VARARGS, 
875                 "S.add(message) -> None\n"
876                 "Add an entry." },
877         { "delete", (PyCFunction)py_ldb_delete, METH_VARARGS,
878                 "S.delete(dn) -> None\n"
879                 "Remove an entry." },
880         { "rename", (PyCFunction)py_ldb_rename, METH_VARARGS,
881                 "S.rename(old_dn, new_dn) -> None\n"
882                 "Rename an entry." },
883         { "search", (PyCFunction)py_ldb_search, METH_VARARGS|METH_KEYWORDS,
884                 "Search in a database.\n"
885                 "\n"
886                 ":param base: Optional base DN to search\n"
887                 ":param scope: Search scope (SCOPE_BASE, SCOPE_ONELEVEL or SCOPE_SUBTREE)\n"
888                 ":param expression: Optional search expression\n"
889                 ":param attrs: Attributes to return (defaults to all)\n"
890                 ":param controls: Optional list of controls\n"
891                 ":return: Iterator over Message objects\n"
892         },
893         { "schema_attribute_remove", (PyCFunction)py_ldb_schema_attribute_remove, METH_VARARGS,
894                 NULL },
895         { "schema_attribute_add", (PyCFunction)py_ldb_schema_attribute_add, METH_VARARGS,
896                 NULL },
897         { "schema_format_value", (PyCFunction)py_ldb_schema_format_value, METH_VARARGS,
898                 NULL },
899         { "parse_ldif", (PyCFunction)py_ldb_parse_ldif, METH_VARARGS,
900                 "S.parse_ldif(ldif) -> iter(messages)\n"
901         "Parse a string formatted using LDIF." },
902         { "get_opaque", (PyCFunction)py_ldb_set_opaque, METH_VARARGS,
903         "S.get_opaque(name) -> value\n"
904         "Get an opaque value set on this LDB connection. \n"
905         ":note: The returned value may not be useful in Python."
906         },
907         { "set_opaque", (PyCFunction)py_ldb_get_opaque, METH_VARARGS,
908                 "S.set_opaque(name, value) -> None\n"
909                 "Set an opaque value on this LDB connection. \n"
910         ":note: Passing incorrect values may cause crashes." },
911         { NULL },
912 };
913
914 PyObject *PyLdbModule_FromModule(struct ldb_module *mod)
915 {
916         return py_talloc_import(&PyLdbModule, mod);
917 }
918
919 static PyObject *py_ldb_get_firstmodule(PyLdbObject *self, void *closure)
920 {
921         return PyLdbModule_FromModule(PyLdb_AsLdbContext(self)->modules);
922 }
923
924 static PyGetSetDef py_ldb_getset[] = {
925         { (char *)"firstmodule", (getter)py_ldb_get_firstmodule, NULL, NULL },
926         { NULL }
927 };
928
929 static int py_ldb_contains(PyLdbObject *self, PyObject *obj)
930 {
931         struct ldb_context *ldb_ctx = PyLdb_AsLdbContext(self);
932         struct ldb_dn *dn;
933         struct ldb_result *result;
934         int ret;
935         int count;
936
937         if (!PyObject_AsDn(ldb_ctx, obj, ldb_ctx, &dn))
938                 return -1;
939
940         ret = ldb_search(ldb_ctx, ldb_ctx, &result, dn, LDB_SCOPE_BASE, NULL, NULL);
941         if (ret != LDB_SUCCESS) {
942                 PyErr_SetLdbError(ret, ldb_ctx);
943                 return -1;
944         }
945
946         count = result->count;
947
948         talloc_free(result);
949
950         return count;
951 }
952
953 static PySequenceMethods py_ldb_seq = {
954         .sq_contains = (objobjproc)py_ldb_contains,
955 };
956
957 PyObject *PyLdb_FromLdbContext(struct ldb_context *ldb_ctx)
958 {
959         return py_talloc_import(&PyLdb, ldb_ctx);
960 }
961
962 PyTypeObject PyLdb = {
963         .tp_name = "Ldb",
964         .tp_methods = py_ldb_methods,
965         .tp_repr = (reprfunc)py_ldb_repr,
966         .tp_new = py_ldb_new,
967         .tp_dealloc = py_talloc_dealloc,
968         .tp_getset = py_ldb_getset,
969         .tp_basicsize = sizeof(PyLdbObject),
970         .tp_doc = "Connection to a LDB database.",
971         .tp_as_sequence = &py_ldb_seq,
972         .tp_flags = Py_TPFLAGS_DEFAULT|Py_TPFLAGS_BASETYPE,
973 };
974
975 static PyObject *py_ldb_module_repr(PyLdbModuleObject *self)
976 {
977         return PyString_FromFormat("<ldb module '%s'>", PyLdbModule_AsModule(self)->ops->name);
978 }
979
980 static PyObject *py_ldb_module_str(PyLdbModuleObject *self)
981 {
982         return PyString_FromString(PyLdbModule_AsModule(self)->ops->name);
983 }
984
985 static PyObject *py_ldb_module_start_transaction(PyLdbModuleObject *self)
986 {
987         PyLdbModule_AsModule(self)->ops->start_transaction(PyLdbModule_AsModule(self));
988         return Py_None;
989 }
990
991 static PyObject *py_ldb_module_end_transaction(PyLdbModuleObject *self)
992 {
993         PyLdbModule_AsModule(self)->ops->end_transaction(PyLdbModule_AsModule(self));
994         return Py_None;
995 }
996
997 static PyObject *py_ldb_module_del_transaction(PyLdbModuleObject *self)
998 {
999         PyLdbModule_AsModule(self)->ops->del_transaction(PyLdbModule_AsModule(self));
1000         return Py_None;
1001 }
1002
1003 static PyObject *py_ldb_module_search(PyLdbModuleObject *self, PyObject *args, PyObject *kwargs)
1004 {
1005         PyObject *py_base, *py_tree, *py_attrs;
1006         int ret, scope;
1007         struct ldb_request *req;
1008         const char *kwnames[] = { "base", "scope", "tree", "attrs", NULL };
1009         struct ldb_module *mod;
1010         if (!PyArg_ParseTupleAndKeywords(args, kwargs, "OiOO", (char **)kwnames, 
1011                                                                          &py_base, &scope, &py_tree, &py_attrs))
1012                 return NULL;
1013
1014         req = talloc_zero(NULL, struct ldb_request);
1015
1016         req->operation = LDB_SEARCH;
1017         req->op.search.base = PyLdbDn_AsDn(py_base);
1018         req->op.search.scope = scope;
1019         req->op.search.tree = PyLdbTree_AsTree(py_tree);
1020         if (py_attrs == Py_None) {
1021                 req->op.search.attrs = NULL;
1022         } else {
1023                 req->op.search.attrs = PyList_AsStringList(req, py_attrs);
1024         }
1025
1026         req->op.search.res = talloc_zero(NULL, struct ldb_result);
1027
1028         mod = self->ptr;
1029
1030         ret = mod->ops->search(mod, req);
1031         talloc_free(req);
1032
1033         PyErr_LDB_ERROR_IS_ERR_RAISE(ret, NULL);
1034
1035         return PyLdbResult_FromResult(req->op.search.res);
1036 }
1037
1038
1039 static PyObject *py_ldb_module_add(PyLdbModuleObject *self, PyObject *args)
1040 {
1041         struct ldb_request *req;
1042         PyObject *py_message;
1043         int ret;
1044
1045         if (!PyArg_ParseTuple(args, "O", &py_message))
1046                 return NULL;
1047
1048         req = talloc_zero(NULL, struct ldb_request);
1049         req->operation = LDB_ADD;
1050         req->op.add.message = PyLdbMessage_AsMessage(py_message);
1051
1052         ret = PyLdbModule_AsModule(self)->ops->add(PyLdbModule_AsModule(self), req);
1053
1054         PyErr_LDB_ERROR_IS_ERR_RAISE(ret, NULL);
1055
1056         return Py_None;
1057 }
1058
1059 static PyObject *py_ldb_module_modify(PyLdbModuleObject *self, PyObject *args) 
1060 {
1061         int ret;
1062         struct ldb_request *req;
1063         PyObject *py_message;
1064
1065         if (!PyArg_ParseTuple(args, "O", &py_message))
1066                 return NULL;
1067         
1068         req = talloc_zero(NULL, struct ldb_request);
1069         req->operation = LDB_MODIFY;
1070         req->op.mod.message = PyLdbMessage_AsMessage(py_message);
1071         
1072         ret = PyLdbModule_AsModule(self)->ops->modify(PyLdbModule_AsModule(self), req);
1073
1074         PyErr_LDB_ERROR_IS_ERR_RAISE(ret, NULL);
1075
1076         return Py_None;
1077 }
1078
1079 static PyObject *py_ldb_module_delete(PyLdbModuleObject *self, PyObject *args) 
1080 {
1081         int ret;
1082         struct ldb_request *req;
1083         PyObject *py_dn;
1084
1085         if (!PyArg_ParseTuple(args, "O", &py_dn))
1086                 return NULL;
1087         
1088         req = talloc_zero(NULL, struct ldb_request);
1089         req->operation = LDB_DELETE;
1090         req->op.del.dn = PyLdbDn_AsDn(py_dn);
1091         
1092         ret = PyLdbModule_AsModule(self)->ops->del(PyLdbModule_AsModule(self), req);
1093
1094         PyErr_LDB_ERROR_IS_ERR_RAISE(ret, NULL);
1095
1096         return Py_None;
1097 }
1098
1099 static PyObject *py_ldb_module_rename(PyLdbModuleObject *self, PyObject *args)
1100 {
1101         int ret;
1102         struct ldb_request *req;
1103         PyObject *py_dn1, *py_dn2;
1104
1105         if (!PyArg_ParseTuple(args, "OO", &py_dn1, &py_dn2))
1106                 return NULL;
1107         
1108         req = talloc_zero(NULL, struct ldb_request);
1109
1110         req->operation = LDB_RENAME;
1111         req->op.rename.olddn = PyLdbDn_AsDn(py_dn1);
1112         req->op.rename.newdn = PyLdbDn_AsDn(py_dn2);
1113         
1114         ret = PyLdbModule_AsModule(self)->ops->rename(PyLdbModule_AsModule(self), req);
1115
1116         PyErr_LDB_ERROR_IS_ERR_RAISE(ret, NULL);
1117
1118         return Py_None;
1119 }
1120
1121 static PyMethodDef py_ldb_module_methods[] = {
1122         { "search", (PyCFunction)py_ldb_module_search, METH_VARARGS|METH_KEYWORDS, NULL },
1123         { "add", (PyCFunction)py_ldb_module_add, METH_VARARGS, NULL },
1124         { "modify", (PyCFunction)py_ldb_module_modify, METH_VARARGS, NULL },
1125         { "rename", (PyCFunction)py_ldb_module_rename, METH_VARARGS, NULL },
1126         { "delete", (PyCFunction)py_ldb_module_delete, METH_VARARGS, NULL },
1127         { "start_transaction", (PyCFunction)py_ldb_module_start_transaction, METH_NOARGS, NULL },
1128         { "end_transaction", (PyCFunction)py_ldb_module_end_transaction, METH_NOARGS, NULL },
1129         { "del_transaction", (PyCFunction)py_ldb_module_del_transaction, METH_NOARGS, NULL },
1130         { NULL },
1131 };
1132
1133 PyTypeObject PyLdbModule = {
1134         .tp_name = "LdbModule",
1135         .tp_methods = py_ldb_module_methods,
1136         .tp_repr = (reprfunc)py_ldb_module_repr,
1137         .tp_str = (reprfunc)py_ldb_module_str,
1138         .tp_basicsize = sizeof(py_talloc_Object),
1139         .tp_dealloc = py_talloc_dealloc,
1140 };
1141
1142 struct ldb_message_element *PyObject_AsMessageElement(TALLOC_CTX *mem_ctx,
1143                                                PyObject *set_obj, int flags,
1144                                                const char *attr_name)
1145 {
1146     struct ldb_message_element *me;
1147
1148         if (PyLdbMessageElement_Check(set_obj))
1149                 return PyLdbMessageElement_AsMessageElement(set_obj);
1150
1151         me = talloc(mem_ctx, struct ldb_message_element);
1152
1153     me->name = attr_name;
1154     me->flags = flags;
1155     if (PyString_Check(set_obj)) {
1156         me->num_values = 1;
1157         me->values = talloc_array(me, struct ldb_val, me->num_values);
1158         me->values[0].length = PyString_Size(set_obj);
1159         me->values[0].data = (uint8_t *)talloc_strdup(me->values, 
1160                                            PyString_AsString(set_obj));
1161     } else if (PySequence_Check(set_obj)) {
1162         int i;
1163         me->num_values = PySequence_Size(set_obj);
1164         me->values = talloc_array(me, struct ldb_val, me->num_values);
1165         for (i = 0; i < me->num_values; i++) {
1166             PyObject *obj = PySequence_GetItem(set_obj, i);
1167             me->values[i].length = PyString_Size(obj);
1168             me->values[i].data = (uint8_t *)PyString_AsString(obj);
1169         }
1170     } else {
1171         talloc_free(me);
1172         me = NULL;
1173     }
1174
1175     return me;
1176 }
1177
1178
1179 PyObject *ldb_msg_element_to_set(struct ldb_context *ldb_ctx, 
1180                                  struct ldb_message_element *me)
1181 {
1182     int i;
1183     PyObject *result;
1184
1185     /* Python << 2.5 doesn't have PySet_New and PySet_Add. */
1186     result = PyList_New(me->num_values);
1187
1188     for (i = 0; i < me->num_values; i++) {
1189         PyList_SetItem(result, i,
1190             PyObject_FromLdbValue(ldb_ctx, me, &me->values[i]));
1191     }
1192
1193     return result;
1194 }
1195
1196 PyObject *py_ldb_msg_element_get(PyLdbMessageElementObject *self, PyObject *args)
1197 {
1198         int i;
1199         if (!PyArg_ParseTuple(args, "i", &i))
1200                 return NULL;
1201         if (i < 0 || i >= PyLdbMessageElement_AsMessageElement(self)->num_values)
1202                 return Py_None;
1203
1204         return PyObject_FromLdbValue(NULL, PyLdbMessageElement_AsMessageElement(self), 
1205                                                                  &(PyLdbMessageElement_AsMessageElement(self)->values[i]));
1206 }
1207
1208 static PyMethodDef py_ldb_msg_element_methods[] = {
1209         { "get", (PyCFunction)py_ldb_msg_element_get, METH_VARARGS, NULL },
1210         { NULL },
1211 };
1212
1213 static Py_ssize_t py_ldb_msg_element_len(PyLdbMessageElementObject *self)
1214 {
1215         return PyLdbMessageElement_AsMessageElement(self)->num_values;
1216 }
1217
1218 static PyObject *py_ldb_msg_element_find(PyLdbMessageElementObject *self, Py_ssize_t idx)
1219 {
1220         struct ldb_message_element *el = PyLdbMessageElement_AsMessageElement(self);
1221         if (idx < 0 || idx >= el->num_values) {
1222                 PyErr_SetString(PyExc_IndexError, "Out of range");
1223                 return NULL;
1224         }
1225         return PyString_FromStringAndSize((char *)el->values[idx].data, el->values[idx].length);
1226 }
1227
1228 static PySequenceMethods py_ldb_msg_element_seq = {
1229         .sq_length = (lenfunc)py_ldb_msg_element_len,
1230         .sq_item = (ssizeargfunc)py_ldb_msg_element_find,
1231 };
1232
1233 static int py_ldb_msg_element_cmp(PyLdbMessageElementObject *self, PyLdbMessageElementObject *other)
1234 {
1235         return ldb_msg_element_compare(PyLdbMessageElement_AsMessageElement(self), 
1236                                                                    PyLdbMessageElement_AsMessageElement(other));
1237 }
1238
1239 static PyObject *py_ldb_msg_element_iter(PyLdbMessageElementObject *self)
1240 {
1241         return PyObject_GetIter(ldb_msg_element_to_set(NULL, PyLdbMessageElement_AsMessageElement(self)));
1242 }
1243
1244 PyObject *PyLdbMessageElement_FromMessageElement(struct ldb_message_element *el)
1245 {
1246         return py_talloc_import(&PyLdbMessageElement, el);
1247 }
1248
1249 static PyObject *py_ldb_msg_element_new(PyTypeObject *type, PyObject *args, PyObject *kwargs)
1250 {
1251         PyObject *py_elements = NULL;
1252         struct ldb_message_element *el;
1253         int flags = 0;
1254         char *name = NULL;
1255         const char *kwnames[] = { "elements", "flags", "name", NULL };
1256         if (!PyArg_ParseTupleAndKeywords(args, kwargs, "|Ois", (char **)kwnames, &py_elements, &flags, &name))
1257                 return NULL;
1258
1259         el = talloc_zero(NULL, struct ldb_message_element);
1260
1261         if (py_elements != NULL) {
1262                 int i;
1263                 el->num_values = PySequence_Size(py_elements);
1264                 el->values = talloc_array(el, struct ldb_val, el->num_values);
1265                 for (i = 0; i < el->num_values; i++) {
1266                         PyObject *item = PySequence_GetItem(py_elements, i);
1267                         el->values[i].data = (uint8_t *)PyString_AsString(item);
1268                         el->values[i].length = PyString_Size(item);
1269                 }
1270         }
1271
1272         el->flags = flags;
1273         el->name = talloc_strdup(el, name);
1274
1275         return py_talloc_import(&PyLdbMessageElement, el);
1276 }
1277
1278 static PyObject *py_ldb_msg_element_repr(PyLdbMessageElementObject *self)
1279 {
1280         return PyString_FromFormat("MessageElement()");
1281 }
1282
1283 PyTypeObject PyLdbMessageElement = {
1284         .tp_name = "MessageElement",
1285         .tp_basicsize = sizeof(PyLdbMessageElementObject),
1286         .tp_dealloc = py_talloc_dealloc,
1287         .tp_repr = (reprfunc)py_ldb_msg_element_repr,
1288         .tp_methods = py_ldb_msg_element_methods,
1289         .tp_compare = (cmpfunc)py_ldb_msg_element_cmp,
1290         .tp_iter = (getiterfunc)py_ldb_msg_element_iter,
1291         .tp_as_sequence = &py_ldb_msg_element_seq,
1292         .tp_new = py_ldb_msg_element_new,
1293 };
1294
1295 static PyObject *py_ldb_msg_remove_attr(PyLdbMessageObject *self, PyObject *args)
1296 {
1297         char *name;
1298         if (!PyArg_ParseTuple(args, "s", &name))
1299                 return NULL;
1300
1301         ldb_msg_remove_attr(self->ptr, name);
1302
1303         return Py_None;
1304 }
1305
1306 static PyObject *py_ldb_msg_keys(PyLdbMessageObject *self)
1307 {
1308         struct ldb_message *msg = PyLdbMessage_AsMessage(self);
1309         int i, j = 0;
1310         PyObject *obj = PyList_New(msg->num_elements+(msg->dn != NULL?1:0));
1311         if (msg->dn != NULL) {
1312                 PyList_SetItem(obj, j, PyString_FromString("dn"));
1313                 j++;
1314         }
1315         for (i = 0; i < msg->num_elements; i++) {
1316                 PyList_SetItem(obj, j, PyString_FromString(msg->elements[i].name));
1317                 j++;
1318         }
1319         return obj;
1320 }
1321
1322 static PyObject *py_ldb_msg_getitem(PyLdbMessageObject *self, PyObject *py_name)
1323 {
1324         struct ldb_message_element *el;
1325         char *name = PyString_AsString(py_name);
1326         if (!strcmp(name, "dn"))
1327                 return PyLdbDn_FromDn(PyLdbMessage_AsMessage(self)->dn);
1328         el = ldb_msg_find_element(PyLdbMessage_AsMessage(self), name);
1329         if (el == NULL)
1330                 return NULL;
1331         return (PyObject *)PyLdbMessageElement_FromMessageElement(el);
1332 }
1333
1334 static PyObject *py_ldb_msg_get(PyLdbMessageObject *self, PyObject *args)
1335 {
1336         PyObject *name, *ret;
1337         if (!PyArg_ParseTuple(args, "O", &name))
1338                 return NULL;
1339
1340         ret = py_ldb_msg_getitem(self, name);
1341         if (ret == NULL)
1342                 return Py_None;
1343         return ret;
1344 }
1345
1346 static PyObject *py_ldb_msg_items(PyLdbMessageObject *self)
1347 {
1348         struct ldb_message *msg = PyLdbMessage_AsMessage(self);
1349         int i, j;
1350         PyObject *l = PyList_New(msg->num_elements + (msg->dn == NULL?0:1));
1351         j = 0;
1352         if (msg->dn != NULL) {
1353                 PyList_SetItem(l, 0, Py_BuildValue("(sO)", "dn", PyLdbDn_FromDn(msg->dn)));
1354                 j++;
1355         }
1356         for (i = 0; i < msg->num_elements; i++, j++) {
1357                 PyList_SetItem(l, j, Py_BuildValue("(sO)", msg->elements[i].name, PyLdbMessageElement_FromMessageElement(&msg->elements[i])));
1358         }
1359         return l;
1360 }
1361
1362 static PyMethodDef py_ldb_msg_methods[] = { 
1363         { "keys", (PyCFunction)py_ldb_msg_keys, METH_NOARGS, NULL },
1364         { "remove", (PyCFunction)py_ldb_msg_remove_attr, METH_VARARGS, NULL },
1365         { "get", (PyCFunction)py_ldb_msg_get, METH_VARARGS, NULL },
1366         { "items", (PyCFunction)py_ldb_msg_items, METH_NOARGS, NULL },
1367         { NULL },
1368 };
1369
1370 static int py_ldb_msg_setitem(PyLdbMessageObject *self, PyObject *name, PyObject *value)
1371 {
1372         char *attr_name = PyString_AsString(name);
1373         if (value == NULL) {
1374                 ldb_msg_remove_attr(self->ptr, attr_name);
1375         } else {
1376                 struct ldb_message_element *el = PyObject_AsMessageElement(NULL,
1377                                                                                         value, 0, attr_name);
1378                 if (el == NULL)
1379                         return -1;
1380                 talloc_steal(self->ptr, el);
1381                 ldb_msg_remove_attr(PyLdbMessage_AsMessage(self), attr_name);
1382                 ldb_msg_add(PyLdbMessage_AsMessage(self), el, el->flags);
1383         }
1384         return 0;
1385 }
1386
1387 static Py_ssize_t py_ldb_msg_length(PyLdbMessageObject *self)
1388 {
1389         return PyLdbMessage_AsMessage(self)->num_elements;
1390 }
1391
1392 static PyMappingMethods py_ldb_msg_mapping = {
1393         .mp_length = (lenfunc)py_ldb_msg_length,
1394         .mp_subscript = (binaryfunc)py_ldb_msg_getitem,
1395         .mp_ass_subscript = (objobjargproc)py_ldb_msg_setitem,
1396 };
1397
1398 static PyObject *py_ldb_msg_new(PyTypeObject *type, PyObject *args, PyObject *kwargs)
1399 {
1400         const char *kwnames[] = { "dn", NULL };
1401         struct ldb_message *ret;
1402         PyObject *pydn = NULL;
1403         if (!PyArg_ParseTupleAndKeywords(args, kwargs, "|O", (char **)kwnames, &pydn))
1404                 return NULL;
1405
1406         ret = ldb_msg_new(NULL);
1407         if (ret == NULL) {
1408                 PyErr_NoMemory();
1409                 return NULL;
1410         }
1411
1412         if (pydn != NULL)
1413                 if (!PyObject_AsDn(NULL, pydn, NULL, &ret->dn))
1414                         return NULL;
1415
1416         return py_talloc_import(&PyLdbMessage, ret); 
1417 }
1418
1419 PyObject *PyLdbMessage_FromMessage(struct ldb_message *msg)
1420 {
1421         return py_talloc_import(&PyLdbMessage, msg);
1422 }
1423
1424 static PyObject *py_ldb_msg_get_dn(PyLdbMessageObject *self, void *closure)
1425 {
1426         return PyLdbDn_FromDn(PyLdbMessage_AsMessage(self)->dn);
1427 }
1428
1429 static int py_ldb_msg_set_dn(PyLdbMessageObject *self, PyObject *value, void *closure)
1430 {
1431         PyLdbMessage_AsMessage(self)->dn = PyLdbDn_AsDn(value);
1432         return 0;
1433 }
1434
1435 static PyGetSetDef py_ldb_msg_getset[] = {
1436         { (char *)"dn", (getter)py_ldb_msg_get_dn, (setter)py_ldb_msg_set_dn, NULL },
1437         { NULL }
1438 };
1439
1440 PyTypeObject PyLdbMessage = {
1441         .tp_name = "Message",
1442         .tp_methods = py_ldb_msg_methods,
1443         .tp_getset = py_ldb_msg_getset,
1444         .tp_as_mapping = &py_ldb_msg_mapping,
1445         .tp_basicsize = sizeof(PyLdbMessageObject),
1446         .tp_dealloc = py_talloc_dealloc,
1447         .tp_new = py_ldb_msg_new,
1448 };
1449
1450 PyObject *PyLdbTree_FromTree(struct ldb_parse_tree *tree)
1451 {
1452         return py_talloc_import(&PyLdbTree, tree);
1453 }
1454
1455 PyTypeObject PyLdbTree = {
1456         .tp_name = "Tree",
1457         .tp_basicsize = sizeof(PyLdbTreeObject),
1458         .tp_dealloc = py_talloc_dealloc,
1459 };
1460
1461 /* Ldb_module */
1462 int py_module_search(struct ldb_module *mod, struct ldb_request *req)
1463 {
1464     PyObject *py_ldb = mod->private_data;
1465     PyObject *py_result, *py_base, *py_attrs, *py_tree;
1466
1467     py_base = PyLdbDn_FromDn(req->op.search.base);
1468
1469     if (py_base == NULL)
1470         return LDB_ERR_OPERATIONS_ERROR;
1471
1472     py_tree = PyLdbTree_FromTree(req->op.search.tree);
1473
1474     if (py_tree == NULL)
1475         return LDB_ERR_OPERATIONS_ERROR;
1476
1477     if (req->op.search.attrs == NULL) {
1478         py_attrs = Py_None;
1479     } else {
1480         int i, len;
1481         for (len = 0; req->op.search.attrs[len]; len++);
1482         py_attrs = PyList_New(len);
1483         for (i = 0; i < len; i++)
1484             PyList_SetItem(py_attrs, i, PyString_FromString(req->op.search.attrs[i]));
1485     }
1486
1487     py_result = PyObject_CallMethod(py_ldb, (char *)"search", (char *)"OiOO", py_base, req->op.search.scope, py_tree, py_attrs);
1488
1489     Py_DECREF(py_attrs);
1490     Py_DECREF(py_tree);
1491     Py_DECREF(py_base);
1492
1493     if (py_result == NULL) {
1494         return LDB_ERR_OPERATIONS_ERROR;
1495     }
1496
1497         req->op.search.res = PyLdbResult_AsResult(NULL, py_result);
1498         if (req->op.search.res == NULL) {
1499         return LDB_ERR_OPERATIONS_ERROR;
1500     }
1501
1502     Py_DECREF(py_result);
1503
1504     return LDB_SUCCESS;
1505 }
1506
1507 int py_module_add(struct ldb_module *mod, struct ldb_request *req)
1508 {
1509     PyObject *py_ldb = mod->private_data;
1510     PyObject *py_result, *py_msg;
1511
1512     py_msg = PyLdbMessage_FromMessage((struct ldb_message *)req->op.add.message);
1513
1514     if (py_msg == NULL) {
1515         return LDB_ERR_OPERATIONS_ERROR;
1516     }
1517
1518     py_result = PyObject_CallMethod(py_ldb, (char *)"add", (char *)"O", py_msg);
1519
1520     Py_DECREF(py_msg);
1521
1522     if (py_result == NULL) {
1523         return LDB_ERR_OPERATIONS_ERROR;
1524     }
1525
1526     Py_DECREF(py_result);
1527
1528     return LDB_SUCCESS;
1529 }
1530
1531 int py_module_modify(struct ldb_module *mod, struct ldb_request *req)
1532 {
1533     PyObject *py_ldb = mod->private_data;
1534     PyObject *py_result, *py_msg;
1535
1536     py_msg = PyLdbMessage_FromMessage((struct ldb_message *)req->op.mod.message);
1537
1538     if (py_msg == NULL) {
1539         return LDB_ERR_OPERATIONS_ERROR;
1540     }
1541
1542     py_result = PyObject_CallMethod(py_ldb, (char *)"modify", (char *)"O", py_msg);
1543
1544     Py_DECREF(py_msg);
1545
1546     if (py_result == NULL) {
1547         return LDB_ERR_OPERATIONS_ERROR;
1548     }
1549
1550     Py_DECREF(py_result);
1551
1552     return LDB_SUCCESS;
1553 }
1554
1555 int py_module_del(struct ldb_module *mod, struct ldb_request *req)
1556 {
1557     PyObject *py_ldb = mod->private_data;
1558     PyObject *py_result, *py_dn;
1559
1560     py_dn = PyLdbDn_FromDn(req->op.del.dn);
1561
1562     if (py_dn == NULL)
1563         return LDB_ERR_OPERATIONS_ERROR;
1564
1565     py_result = PyObject_CallMethod(py_ldb, (char *)"delete", (char *)"O", py_dn);
1566
1567     if (py_result == NULL) {
1568         return LDB_ERR_OPERATIONS_ERROR;
1569     }
1570
1571     Py_DECREF(py_result);
1572
1573     return LDB_SUCCESS;
1574 }
1575
1576 int py_module_rename(struct ldb_module *mod, struct ldb_request *req)
1577 {
1578     PyObject *py_ldb = mod->private_data;
1579     PyObject *py_result, *py_olddn, *py_newdn;
1580
1581     py_olddn = PyLdbDn_FromDn(req->op.rename.olddn);
1582
1583     if (py_olddn == NULL)
1584         return LDB_ERR_OPERATIONS_ERROR;
1585
1586     py_newdn = PyLdbDn_FromDn(req->op.rename.newdn);
1587
1588     if (py_newdn == NULL)
1589         return LDB_ERR_OPERATIONS_ERROR;
1590
1591     py_result = PyObject_CallMethod(py_ldb, (char *)"rename", (char *)"OO", py_olddn, py_newdn);
1592
1593     Py_DECREF(py_olddn);
1594     Py_DECREF(py_newdn);
1595
1596     if (py_result == NULL) {
1597         return LDB_ERR_OPERATIONS_ERROR;
1598     }
1599
1600     Py_DECREF(py_result);
1601
1602     return LDB_SUCCESS;
1603 }
1604
1605 int py_module_request(struct ldb_module *mod, struct ldb_request *req)
1606 {
1607     PyObject *py_ldb = mod->private_data;
1608     PyObject *py_result;
1609
1610     py_result = PyObject_CallMethod(py_ldb, (char *)"request", (char *)"");
1611
1612     return LDB_ERR_OPERATIONS_ERROR;
1613 }
1614
1615 int py_module_extended(struct ldb_module *mod, struct ldb_request *req)
1616 {
1617     PyObject *py_ldb = mod->private_data;
1618     PyObject *py_result;
1619
1620     py_result = PyObject_CallMethod(py_ldb, (char *)"extended", (char *)"");
1621
1622     return LDB_ERR_OPERATIONS_ERROR;
1623 }
1624
1625 int py_module_start_transaction(struct ldb_module *mod)
1626 {
1627     PyObject *py_ldb = mod->private_data;
1628     PyObject *py_result;
1629
1630     py_result = PyObject_CallMethod(py_ldb, (char *)"start_transaction", (char *)"");
1631
1632     if (py_result == NULL) {
1633         return LDB_ERR_OPERATIONS_ERROR;
1634     }
1635
1636     Py_DECREF(py_result);
1637
1638     return LDB_SUCCESS;
1639 }
1640
1641 int py_module_end_transaction(struct ldb_module *mod)
1642 {
1643     PyObject *py_ldb = mod->private_data;
1644     PyObject *py_result;
1645
1646     py_result = PyObject_CallMethod(py_ldb, (char *)"end_transaction", (char *)"");
1647
1648     if (py_result == NULL) {
1649         return LDB_ERR_OPERATIONS_ERROR;
1650     }
1651
1652     Py_DECREF(py_result);
1653
1654     return LDB_SUCCESS;
1655 }
1656
1657 int py_module_del_transaction(struct ldb_module *mod)
1658 {
1659     PyObject *py_ldb = mod->private_data;
1660     PyObject *py_result;
1661
1662     py_result = PyObject_CallMethod(py_ldb, (char *)"del_transaction", (char *)"");
1663
1664     if (py_result == NULL) {
1665         return LDB_ERR_OPERATIONS_ERROR;
1666     }
1667
1668     Py_DECREF(py_result);
1669
1670     return LDB_SUCCESS;
1671 }
1672
1673 static int py_module_destructor(struct ldb_module *mod)
1674 {
1675     Py_DECREF((PyObject *)mod->private_data);
1676     return 0;
1677 }
1678
1679 int py_module_init (struct ldb_module *mod)
1680 {
1681     PyObject *py_class = mod->ops->private_data;
1682     PyObject *py_result, *py_next, *py_ldb;
1683
1684     py_ldb = PyLdb_FromLdbContext(mod->ldb);
1685
1686     if (py_ldb == NULL)
1687         return LDB_ERR_OPERATIONS_ERROR;
1688
1689     py_next = PyLdbModule_FromModule(mod->next);
1690
1691     if (py_next == NULL)
1692         return LDB_ERR_OPERATIONS_ERROR;
1693
1694     py_result = PyObject_CallFunction(py_class, (char *)"OO", py_ldb, py_next);
1695
1696     if (py_result == NULL) {
1697         return LDB_ERR_OPERATIONS_ERROR;
1698     }
1699
1700     mod->private_data = py_result;
1701
1702     talloc_set_destructor(mod, py_module_destructor);
1703
1704     return ldb_next_init(mod);
1705 }
1706
1707 static PyObject *py_register_module(PyObject *module, PyObject *args)
1708 {
1709         int ret;
1710         struct ldb_module_ops *ops;
1711         PyObject *input;
1712
1713         if (!PyArg_ParseTuple(args, "O", &input))
1714                 return NULL;
1715
1716     ops = talloc_zero(talloc_autofree_context(), struct ldb_module_ops);
1717         if (ops == NULL) {
1718                 PyErr_NoMemory();
1719                 return NULL;
1720         }
1721
1722     ops->name = talloc_strdup(ops, PyString_AsString(PyObject_GetAttrString(input, (char *)"name")));
1723
1724     Py_INCREF(input);
1725     ops->private_data = input;
1726     ops->init_context = py_module_init;
1727     ops->search = py_module_search;
1728     ops->add = py_module_add;
1729     ops->modify = py_module_modify;
1730     ops->del = py_module_del;
1731     ops->rename = py_module_rename;
1732     ops->request = py_module_request;
1733     ops->extended = py_module_extended;
1734     ops->start_transaction = py_module_start_transaction;
1735     ops->end_transaction = py_module_end_transaction;
1736     ops->del_transaction = py_module_del_transaction;
1737
1738         ret = ldb_register_module(ops);
1739
1740         PyErr_LDB_ERROR_IS_ERR_RAISE(ret, NULL);
1741
1742         return Py_None;
1743 }
1744
1745 static PyObject *py_timestring(PyObject *module, PyObject *args)
1746 {
1747         time_t t;
1748         char *tresult;
1749         PyObject *ret;
1750         if (!PyArg_ParseTuple(args, "L", &t))
1751                 return NULL;
1752     tresult = ldb_timestring(NULL, t);
1753     ret = PyString_FromString(tresult);
1754     talloc_free(tresult);
1755     return ret;
1756 }
1757
1758 static PyObject *py_string_to_time(PyObject *module, PyObject *args)
1759 {
1760         char *str;
1761         if (!PyArg_ParseTuple(args, "s", &str))
1762                 return NULL;
1763
1764         return PyInt_FromLong(ldb_string_to_time(str));
1765 }
1766
1767 static PyObject *py_valid_attr_name(PyObject *self, PyObject *args)
1768 {
1769         char *name;
1770         if (!PyArg_ParseTuple(args, "s", &name))
1771                 return NULL;
1772         return PyBool_FromLong(ldb_valid_attr_name(name));
1773 }
1774
1775 static PyMethodDef py_ldb_global_methods[] = {
1776         { "register_module", py_register_module, METH_VARARGS, 
1777                 "S.register_module(module) -> None\n"
1778                 "Register a LDB module."},
1779         { "timestring", py_timestring, METH_VARARGS, 
1780                 "S.timestring(int) -> string\n"
1781                 "Generate a LDAP time string from a UNIX timestamp" },
1782         { "string_to_time", py_string_to_time, METH_VARARGS,
1783                 "S.string_to_time(string) -> int\n"
1784                 "Parse a LDAP time string into a UNIX timestamp." },
1785         { "valid_attr_name", py_valid_attr_name, METH_VARARGS,
1786                 "S.valid_attr_name(name) -> bool\n"
1787                 "Check whether the supplied name is a valid attribute name." },
1788         { "open", (PyCFunction)py_ldb_new, METH_VARARGS|METH_KEYWORDS,
1789                 NULL },
1790         { NULL }
1791 };
1792
1793 void initldb(void)
1794 {
1795         PyObject *m;
1796
1797         if (PyType_Ready(&PyLdbDn) < 0)
1798                 return;
1799
1800         if (PyType_Ready(&PyLdbMessage) < 0)
1801                 return;
1802
1803         if (PyType_Ready(&PyLdbMessageElement) < 0)
1804                 return;
1805
1806         if (PyType_Ready(&PyLdb) < 0)
1807                 return;
1808
1809         if (PyType_Ready(&PyLdbModule) < 0)
1810                 return;
1811
1812         if (PyType_Ready(&PyLdbTree) < 0)
1813                 return;
1814
1815         m = Py_InitModule3("ldb", py_ldb_global_methods, 
1816                 "An interface to LDB, a LDAP-like API that can either to talk an embedded database (TDB-based) or a standards-compliant LDAP server.");
1817         if (m == NULL)
1818                 return;
1819
1820         PyModule_AddObject(m, "SCOPE_DEFAULT", PyInt_FromLong(LDB_SCOPE_DEFAULT));
1821         PyModule_AddObject(m, "SCOPE_BASE", PyInt_FromLong(LDB_SCOPE_BASE));
1822         PyModule_AddObject(m, "SCOPE_ONELEVEL", PyInt_FromLong(LDB_SCOPE_ONELEVEL));
1823         PyModule_AddObject(m, "SCOPE_SUBTREE", PyInt_FromLong(LDB_SCOPE_SUBTREE));
1824
1825         PyModule_AddObject(m, "CHANGETYPE_NONE", PyInt_FromLong(LDB_CHANGETYPE_NONE));
1826         PyModule_AddObject(m, "CHANGETYPE_ADD", PyInt_FromLong(LDB_CHANGETYPE_ADD));
1827         PyModule_AddObject(m, "CHANGETYPE_DELETE", PyInt_FromLong(LDB_CHANGETYPE_DELETE));
1828         PyModule_AddObject(m, "CHANGETYPE_MODIFY", PyInt_FromLong(LDB_CHANGETYPE_MODIFY));
1829
1830         PyModule_AddObject(m, "__docformat__", PyString_FromString("restructuredText"));
1831
1832     PyExc_LdbError = PyErr_NewException((char *)"_ldb.LdbError", NULL, NULL);
1833     PyModule_AddObject(m, "LdbError", PyExc_LdbError);
1834
1835         Py_INCREF(&PyLdb);
1836         Py_INCREF(&PyLdbDn);
1837         Py_INCREF(&PyLdbModule);
1838         Py_INCREF(&PyLdbMessage);
1839         Py_INCREF(&PyLdbMessageElement);
1840         Py_INCREF(&PyLdbTree);
1841
1842         PyModule_AddObject(m, "Ldb", (PyObject *)&PyLdb);
1843         PyModule_AddObject(m, "Dn", (PyObject *)&PyLdbDn);
1844         PyModule_AddObject(m, "Message", (PyObject *)&PyLdbMessage);
1845         PyModule_AddObject(m, "MessageElement", (PyObject *)&PyLdbMessageElement);
1846         PyModule_AddObject(m, "Module", (PyObject *)&PyLdbModule);
1847         PyModule_AddObject(m, "Tree", (PyObject *)&PyLdbTree);
1848 }
1849
1850 #if 0
1851
1852 /* ldb_message_element */
1853 %rename(MessageElement) ldb_message_element;
1854 %feature("docstring") ldb_message_element "Message element.";
1855 typedef struct ldb_message_element {
1856     %extend {
1857             PyObject *__set__(void)
1858         {
1859             return ldb_msg_element_to_set(NULL, $self);
1860         }
1861
1862         ldb_message_element(PyObject *set_obj, int flags=0, const char *name = NULL)
1863         {
1864             return PyObject_AsMessageElement(NULL, set_obj, flags, name);
1865         }
1866
1867     }
1868     %pythoncode {
1869         def __getitem__(self, i):
1870             ret = self.get(i)
1871             if ret is None:
1872                 raise KeyError("no such value")
1873             return ret
1874
1875         def __repr__(self):
1876             return "MessageElement([%s])" % (",".join(repr(x) for x in self.__set__()))
1877     }
1878 } ldb_message_element;
1879
1880 /* ldb_message */
1881
1882 typedef struct ldb_message {
1883         ldb_dn *dn;
1884
1885     %extend {
1886         ldb_msg(ldb_dn *dn = NULL) { 
1887             ret->dn = talloc_reference(ret, dn);
1888             return ret;
1889         }
1890         
1891         void __setitem__(const char *attr_name, ldb_message_element *val)
1892         {
1893             struct ldb_message_element *el;
1894             
1895             ldb_msg_remove_attr($self, attr_name);
1896
1897             el = talloc($self, struct ldb_message_element);
1898             el->name = talloc_strdup(el, attr_name);
1899             el->num_values = val->num_values;
1900             el->values = talloc_reference(el, val->values);
1901
1902             ldb_msg_add($self, el, val->flags);
1903         }
1904
1905         void __setitem__(const char *attr_name, PyObject *val)
1906         {
1907         }
1908 %pythoncode {
1909     def get(self, key, default=None):
1910         if key == "dn":
1911             return self.dn
1912         return self.find_element(key)
1913
1914     def iteritems(self):
1915         for k in self.keys():
1916             yield k, self[k]
1917     
1918     def items(self):
1919         return list(self.iteritems())
1920
1921     def __repr__(self):
1922         return "Message(%s)" % repr(dict(self.iteritems()))
1923 }
1924     }
1925 } ldb_msg;
1926
1927 typedef struct ldb_context {
1928     %pythoncode {
1929         def itermodules(self):
1930             m = self.firstmodule
1931             while m is not None:
1932                 yield m
1933                 m = m.next
1934
1935         def modules(self):
1936             return list(self.itermodules())
1937     }
1938 } ldb;
1939 #endif