ldb: make ldb a top level library for Samba 4.0
[kai/samba.git] / lib / ldb / pyldb.c
1 /*
2    Unix SMB/CIFS implementation.
3
4    Python 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-2010 Jelmer Vernooij <jelmer@samba.org>
9    Copyright (C) 2009-2010 Matthias Dieter Wallnöfer
10    Copyright (C) 2009-2011 Andrew Tridgell
11    Copyright (C) 2009-2011 Andrew Bartlett
12
13     ** NOTE! The following LGPL license applies to the ldb
14     ** library. This does NOT imply that all of Samba is released
15     ** under the LGPL
16
17    This library is free software; you can redistribute it and/or
18    modify it under the terms of the GNU Lesser General Public
19    License as published by the Free Software Foundation; either
20    version 3 of the License, or (at your option) any later version.
21
22    This library is distributed in the hope that it will be useful,
23    but WITHOUT ANY WARRANTY; without even the implied warranty of
24    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
25    Lesser General Public License for more details.
26
27    You should have received a copy of the GNU Lesser General Public
28    License along with this library; if not, see <http://www.gnu.org/licenses/>.
29 */
30
31 #include <Python.h>
32 #include <pytalloc.h>
33 #include "ldb_private.h"
34 #include "pyldb.h"
35
36 void initldb(void);
37 static PyObject *PyLdbMessage_FromMessage(struct ldb_message *msg);
38 static PyObject *PyExc_LdbError;
39
40 staticforward PyTypeObject PyLdbControl;
41 staticforward PyTypeObject PyLdbResult;
42 staticforward PyTypeObject PyLdbMessage;
43 staticforward PyTypeObject PyLdbModule;
44 staticforward PyTypeObject PyLdbDn;
45 staticforward PyTypeObject PyLdb;
46 staticforward PyTypeObject PyLdbMessageElement;
47 staticforward PyTypeObject PyLdbTree;
48 static PyObject *PyLdb_FromLdbContext(struct ldb_context *ldb_ctx);
49 static PyObject *PyLdbModule_FromModule(struct ldb_module *mod);
50 static struct ldb_message_element *PyObject_AsMessageElement(
51                                                       TALLOC_CTX *mem_ctx,
52                                                       PyObject *set_obj,
53                                                       unsigned int flags,
54                                                       const char *attr_name);
55
56 /* There's no Py_ssize_t in 2.4, apparently */
57 #if PY_MAJOR_VERSION == 2 && PY_MINOR_VERSION < 5
58 typedef int Py_ssize_t;
59 typedef inquiry lenfunc;
60 typedef intargfunc ssizeargfunc;
61 #endif
62
63 #ifndef Py_RETURN_NONE
64 #define Py_RETURN_NONE return Py_INCREF(Py_None), Py_None
65 #endif
66
67 #define SIGN(a) (((a) == 0)?0:((a) < 0?-1:1))
68
69
70
71 static PyObject *py_ldb_control_str(PyLdbControlObject *self)
72 {
73         if (self->data != NULL) {
74                 char* control = ldb_control_to_string(self->mem_ctx, self->data);
75                 if (control == NULL) {
76                         PyErr_NoMemory();
77                         return NULL;
78                 }
79                 return PyString_FromString(control);
80         } else {
81                 return PyString_FromFormat("ldb control");
82         }
83 }
84
85 static void py_ldb_control_dealloc(PyLdbControlObject *self)
86 {
87         if (self->mem_ctx != NULL) {
88                 talloc_free(self->mem_ctx);
89         }
90         self->data = NULL;
91         self->ob_type->tp_free(self);
92 }
93
94 static PyObject *py_ldb_control_get_oid(PyLdbControlObject *self)
95 {
96         return PyString_FromString(self->data->oid);
97 }
98
99 static PyObject *py_ldb_control_get_critical(PyLdbControlObject *self)
100 {
101         return PyBool_FromLong(self->data->critical);
102 }
103
104 static PyObject *py_ldb_control_set_critical(PyLdbControlObject *self, PyObject *value, void *closure)
105 {
106         if (PyObject_IsTrue(value)) {
107                 self->data->critical = true;
108         } else {
109                 self->data->critical = false;
110         }
111         return 0;
112 }
113
114 static PyObject *py_ldb_control_new(PyTypeObject *type, PyObject *args, PyObject *kwargs)
115 {
116         char *data = NULL;
117         const char * const kwnames[] = { "ldb", "data", NULL };
118         struct ldb_control *parsed_controls;
119         PyLdbControlObject *ret;
120         PyObject *py_ldb;
121         TALLOC_CTX *mem_ctx;
122         struct ldb_context *ldb_ctx;
123
124         if (!PyArg_ParseTupleAndKeywords(args, kwargs, "Os",
125                                          discard_const_p(char *, kwnames),
126                                          &py_ldb, &data))
127                 return NULL;
128
129         mem_ctx = talloc_new(NULL);
130         if (mem_ctx == NULL) {
131                 PyErr_NoMemory();
132                 return NULL;
133         }
134
135         ldb_ctx = PyLdb_AsLdbContext(py_ldb);
136         parsed_controls = ldb_parse_control_from_string(ldb_ctx, mem_ctx, data);
137
138         if (!parsed_controls) {
139                 talloc_free(mem_ctx);
140                 PyErr_SetString(PyExc_ValueError, "unable to parse control string");
141                 return NULL;
142         }
143
144         ret = PyObject_New(PyLdbControlObject, type);
145         if (ret == NULL) {
146                 PyErr_NoMemory();
147                 talloc_free(mem_ctx);
148                 return NULL;
149         }
150
151         ret->mem_ctx = mem_ctx;
152
153         ret->data = talloc_move(mem_ctx, &parsed_controls);
154         if (ret->data == NULL) {
155                 Py_DECREF(ret);
156                 PyErr_NoMemory();
157                 talloc_free(mem_ctx);
158                 return NULL;
159         }
160
161         return (PyObject *)ret;
162 }
163
164 static PyGetSetDef py_ldb_control_getset[] = {
165         { discard_const_p(char, "oid"), (getter)py_ldb_control_get_oid, NULL, NULL },
166         { discard_const_p(char, "critical"), (getter)py_ldb_control_get_critical, (setter)py_ldb_control_set_critical, NULL },
167         { NULL }
168 };
169
170 static PyTypeObject PyLdbControl = {
171         .tp_name = "ldb.control",
172         .tp_dealloc = (destructor)py_ldb_control_dealloc,
173         .tp_getattro = PyObject_GenericGetAttr,
174         .tp_basicsize = sizeof(PyLdbControlObject),
175         .tp_getset = py_ldb_control_getset,
176         .tp_doc = "LDB control.",
177         .tp_str = (reprfunc)py_ldb_control_str,
178         .tp_new = py_ldb_control_new,
179         .tp_flags = Py_TPFLAGS_DEFAULT|Py_TPFLAGS_BASETYPE,
180 };
181
182 static void PyErr_SetLdbError(PyObject *error, int ret, struct ldb_context *ldb_ctx)
183 {
184         if (ret == LDB_ERR_PYTHON_EXCEPTION)
185                 return; /* Python exception should already be set, just keep that */
186
187         PyErr_SetObject(error, 
188                         Py_BuildValue(discard_const_p(char, "(i,s)"), ret,
189                                       ldb_ctx == NULL?ldb_strerror(ret):ldb_errstring(ldb_ctx)));
190 }
191
192 static PyObject *PyObject_FromLdbValue(struct ldb_val *val)
193 {
194         return PyString_FromStringAndSize((const char *)val->data, val->length);
195 }
196
197 /**
198  * Create a Python object from a ldb_result.
199  *
200  * @param result LDB result to convert
201  * @return Python object with converted result (a list object)
202  */
203 static PyObject *PyLdbControl_FromControl(struct ldb_control *control)
204 {
205         TALLOC_CTX *ctl_ctx = talloc_new(NULL);
206         PyLdbControlObject *ctrl;
207         if (ctl_ctx == NULL) {
208                 PyErr_NoMemory();
209                 return NULL;
210         }
211
212         ctrl = (PyLdbControlObject *)PyLdbControl.tp_alloc(&PyLdbControl, 0);
213         if (ctrl == NULL) {
214                 talloc_free(ctl_ctx);
215                 PyErr_NoMemory();
216                 return NULL;
217         }
218         ctrl->mem_ctx = ctl_ctx;
219         ctrl->data = talloc_steal(ctrl->mem_ctx, control);
220         if (ctrl->data == NULL) {
221                 Py_DECREF(ctrl);
222                 PyErr_NoMemory();
223                 return NULL;
224         }
225         return (PyObject*) ctrl;
226 }
227
228 /**
229  * Create a Python object from a ldb_result.
230  *
231  * @param result LDB result to convert
232  * @return Python object with converted result (a list object)
233  */
234 static PyObject *PyLdbResult_FromResult(struct ldb_result *result)
235 {
236         PyLdbResultObject *ret;
237         PyObject *list, *controls, *referals;
238         Py_ssize_t i;
239
240         if (result == NULL) {
241                 Py_RETURN_NONE;
242         }
243
244         ret = (PyLdbResultObject *)PyLdbResult.tp_alloc(&PyLdbResult, 0);
245         if (ret == NULL) {
246                 PyErr_NoMemory();
247                 return NULL;
248         }
249
250         list = PyList_New(result->count);
251         if (list == NULL) {
252                 PyErr_NoMemory();
253                 Py_DECREF(ret);
254                 return NULL;
255         }
256
257         for (i = 0; i < result->count; i++) {
258                 PyList_SetItem(list, i, PyLdbMessage_FromMessage(result->msgs[i]));
259         }
260
261         ret->mem_ctx = talloc_new(NULL);
262         if (ret->mem_ctx == NULL) {
263                 Py_DECREF(list);
264                 Py_DECREF(ret);
265                 PyErr_NoMemory();
266                 return NULL;
267         }
268
269         ret->msgs = list;
270
271         if (result->controls) {
272                 controls = PyList_New(1);
273                 if (controls == NULL) {
274                         Py_DECREF(ret);
275                         PyErr_NoMemory();
276                         return NULL;
277                 }
278                 for (i=0; result->controls[i]; i++) {
279                         PyObject *ctrl = (PyObject*) PyLdbControl_FromControl(result->controls[i]);
280                         if (ctrl == NULL) {
281                                 Py_DECREF(ret);
282                                 Py_DECREF(controls);
283                                 PyErr_NoMemory();
284                                 return NULL;
285                         }
286                         PyList_SetItem(controls, i, ctrl);
287                 }
288         } else {
289                 /*
290                  * No controls so we keep an empty list
291                  */
292                 controls = PyList_New(0);
293                 if (controls == NULL) {
294                         Py_DECREF(ret);
295                         PyErr_NoMemory();
296                         return NULL;
297                 }
298         }
299
300         ret->controls = controls;
301
302         i = 0;
303
304         while (result->refs && result->refs[i]) {
305                 i++;
306         }
307
308         referals = PyList_New(i);
309         if (referals == NULL) {
310                 Py_DECREF(ret);
311                 PyErr_NoMemory();
312                 return NULL;
313         }
314
315         for (i = 0;result->refs && result->refs[i]; i++) {
316                 PyList_SetItem(referals, i, PyString_FromString(result->refs[i]));
317         }
318         ret->referals = referals;
319         return (PyObject *)ret;
320 }
321
322 /**
323  * Create a LDB Result from a Python object. 
324  * If conversion fails, NULL will be returned and a Python exception set.
325  *
326  * @param mem_ctx Memory context in which to allocate the LDB Result
327  * @param obj Python object to convert
328  * @return a ldb_result, or NULL if the conversion failed
329  */
330 static struct ldb_result *PyLdbResult_AsResult(TALLOC_CTX *mem_ctx, 
331                                                PyObject *obj)
332 {
333         struct ldb_result *res;
334         Py_ssize_t i;
335
336         if (obj == Py_None)
337                 return NULL;
338
339         res = talloc_zero(mem_ctx, struct ldb_result);
340         res->count = PyList_Size(obj);
341         res->msgs = talloc_array(res, struct ldb_message *, res->count);
342         for (i = 0; i < res->count; i++) {
343                 PyObject *item = PyList_GetItem(obj, i);
344                 res->msgs[i] = PyLdbMessage_AsMessage(item);
345         }
346         return res;
347 }
348
349 static PyObject *py_ldb_dn_validate(PyLdbDnObject *self)
350 {
351         return PyBool_FromLong(ldb_dn_validate(self->dn));
352 }
353
354 static PyObject *py_ldb_dn_is_valid(PyLdbDnObject *self)
355 {
356         return PyBool_FromLong(ldb_dn_is_valid(self->dn));
357 }
358
359 static PyObject *py_ldb_dn_is_special(PyLdbDnObject *self)
360 {
361         return PyBool_FromLong(ldb_dn_is_special(self->dn));
362 }
363
364 static PyObject *py_ldb_dn_is_null(PyLdbDnObject *self)
365 {
366         return PyBool_FromLong(ldb_dn_is_null(self->dn));
367 }
368  
369 static PyObject *py_ldb_dn_get_casefold(PyLdbDnObject *self)
370 {
371         return PyString_FromString(ldb_dn_get_casefold(self->dn));
372 }
373
374 static PyObject *py_ldb_dn_get_linearized(PyLdbDnObject *self)
375 {
376         return PyString_FromString(ldb_dn_get_linearized(self->dn));
377 }
378
379 static PyObject *py_ldb_dn_canonical_str(PyLdbDnObject *self)
380 {
381         return PyString_FromString(ldb_dn_canonical_string(self->dn, self->dn));
382 }
383
384 static PyObject *py_ldb_dn_canonical_ex_str(PyLdbDnObject *self)
385 {
386         return PyString_FromString(ldb_dn_canonical_ex_string(self->dn, self->dn));
387 }
388
389 static PyObject *py_ldb_dn_extended_str(PyLdbDnObject *self, PyObject *args, PyObject *kwargs)
390 {
391         const char * const kwnames[] = { "mode", NULL };
392         int mode = 1;
393         if (!PyArg_ParseTupleAndKeywords(args, kwargs, "|i",
394                                          discard_const_p(char *, kwnames),
395                                          &mode))
396                 return NULL;
397         return PyString_FromString(ldb_dn_get_extended_linearized(self->dn, self->dn, mode));
398 }
399
400 static PyObject *py_ldb_dn_get_extended_component(PyLdbDnObject *self, PyObject *args)
401 {
402         char *name;
403         const struct ldb_val *val;
404
405         if (!PyArg_ParseTuple(args, "s", &name))
406                 return NULL;
407         val = ldb_dn_get_extended_component(self->dn, name);
408         if (val == NULL) {
409                 Py_RETURN_NONE;
410         }
411
412         return PyString_FromStringAndSize((const char *)val->data, val->length);
413 }
414
415 static PyObject *py_ldb_dn_set_extended_component(PyLdbDnObject *self, PyObject *args)
416 {
417         char *name;
418         PyObject *value;
419         int err;
420
421         if (!PyArg_ParseTuple(args, "sO", &name, &value))
422                 return NULL;
423
424         if (value == Py_None) {
425                 err = ldb_dn_set_extended_component(self->dn, name, NULL);
426         } else {
427                 struct ldb_val val;
428                 if (!PyString_Check(value)) {
429                         PyErr_SetString(PyExc_TypeError, "Expected a string argument");
430                         return NULL;
431                 }
432                 val.data = (uint8_t *)PyString_AsString(value);
433                 val.length = PyString_Size(value);
434                 err = ldb_dn_set_extended_component(self->dn, name, &val);
435         }
436
437         if (err != LDB_SUCCESS) {
438                 PyErr_SetString(PyExc_TypeError, "Failed to set extended component");
439                 return NULL;
440         }
441
442         Py_RETURN_NONE;
443 }
444
445 static PyObject *py_ldb_dn_repr(PyLdbDnObject *self)
446 {
447         return PyString_FromFormat("Dn(%s)", PyObject_REPR(PyString_FromString(ldb_dn_get_linearized(self->dn))));
448 }
449
450 static PyObject *py_ldb_dn_check_special(PyLdbDnObject *self, PyObject *args)
451 {
452         char *name;
453
454         if (!PyArg_ParseTuple(args, "s", &name))
455                 return NULL;
456
457         return ldb_dn_check_special(self->dn, name)?Py_True:Py_False;
458 }
459
460 static int py_ldb_dn_compare(PyLdbDnObject *dn1, PyLdbDnObject *dn2)
461 {
462         int ret;
463         ret = ldb_dn_compare(dn1->dn, dn2->dn);
464         if (ret < 0) ret = -1;
465         if (ret > 0) ret = 1;
466         return ret;
467 }
468
469 static PyObject *py_ldb_dn_get_parent(PyLdbDnObject *self)
470 {
471         struct ldb_dn *dn = PyLdbDn_AsDn((PyObject *)self);
472         struct ldb_dn *parent;
473         PyLdbDnObject *py_ret;
474         TALLOC_CTX *mem_ctx = talloc_new(NULL);
475
476         parent = ldb_dn_get_parent(mem_ctx, dn);
477         if (parent == NULL) {
478                 talloc_free(mem_ctx);
479                 Py_RETURN_NONE;
480         }
481
482         py_ret = (PyLdbDnObject *)PyLdbDn.tp_alloc(&PyLdbDn, 0);
483         if (py_ret == NULL) {
484                 PyErr_NoMemory();
485                 talloc_free(mem_ctx);
486                 return NULL;
487         }
488         py_ret->mem_ctx = mem_ctx;
489         py_ret->dn = parent;
490         return (PyObject *)py_ret;
491 }
492
493 #define dn_ldb_ctx(dn) ((struct ldb_context *)dn)
494
495 static PyObject *py_ldb_dn_add_child(PyLdbDnObject *self, PyObject *args)
496 {
497         PyObject *py_other;
498         struct ldb_dn *dn, *other;
499         if (!PyArg_ParseTuple(args, "O", &py_other))
500                 return NULL;
501
502         dn = PyLdbDn_AsDn((PyObject *)self);
503
504         if (!PyObject_AsDn(NULL, py_other, dn_ldb_ctx(dn), &other))
505                 return NULL;
506
507         return ldb_dn_add_child(dn, other)?Py_True:Py_False;
508 }
509
510 static PyObject *py_ldb_dn_add_base(PyLdbDnObject *self, PyObject *args)
511 {
512         PyObject *py_other;
513         struct ldb_dn *other, *dn;
514         if (!PyArg_ParseTuple(args, "O", &py_other))
515                 return NULL;
516
517         dn = PyLdbDn_AsDn((PyObject *)self);
518
519         if (!PyObject_AsDn(NULL, py_other, dn_ldb_ctx(dn), &other))
520                 return NULL;
521
522         return ldb_dn_add_base(dn, other)?Py_True:Py_False;
523 }
524
525 static PyMethodDef py_ldb_dn_methods[] = {
526         { "validate", (PyCFunction)py_ldb_dn_validate, METH_NOARGS, 
527                 "S.validate() -> bool\n"
528                 "Validate DN is correct." },
529         { "is_valid", (PyCFunction)py_ldb_dn_is_valid, METH_NOARGS,
530                 "S.is_valid() -> bool\n" },
531         { "is_special", (PyCFunction)py_ldb_dn_is_special, METH_NOARGS,
532                 "S.is_special() -> bool\n"
533                 "Check whether this is a special LDB DN." },
534         { "is_null", (PyCFunction)py_ldb_dn_is_null, METH_NOARGS,
535                 "Check whether this is a null DN." },
536         { "get_casefold", (PyCFunction)py_ldb_dn_get_casefold, METH_NOARGS,
537                 NULL },
538         { "get_linearized", (PyCFunction)py_ldb_dn_get_linearized, METH_NOARGS,
539                 NULL },
540         { "canonical_str", (PyCFunction)py_ldb_dn_canonical_str, METH_NOARGS,
541                 "S.canonical_str() -> string\n"
542                 "Canonical version of this DN (like a posix path)." },
543         { "canonical_ex_str", (PyCFunction)py_ldb_dn_canonical_ex_str, METH_NOARGS,
544                 "S.canonical_ex_str() -> string\n"
545                 "Canonical version of this DN (like a posix path, with terminating newline)." },
546         { "extended_str", (PyCFunction)py_ldb_dn_extended_str, METH_VARARGS | METH_KEYWORDS,
547                 "S.extended_str(mode=1) -> string\n"
548                 "Extended version of this DN" },
549         { "parent", (PyCFunction)py_ldb_dn_get_parent, METH_NOARGS,
550                 "S.parent() -> dn\n"
551                 "Get the parent for this DN." },
552         { "add_child", (PyCFunction)py_ldb_dn_add_child, METH_VARARGS, 
553                 "S.add_child(dn) -> None\n"
554                 "Add a child DN to this DN." },
555         { "add_base", (PyCFunction)py_ldb_dn_add_base, METH_VARARGS,
556                 "S.add_base(dn) -> None\n"
557                 "Add a base DN to this DN." },
558         { "check_special", (PyCFunction)py_ldb_dn_check_special, METH_VARARGS,
559                 "S.check_special(name) -> bool\n\n"
560                 "Check if name is a special DN name"},
561         { "get_extended_component", (PyCFunction)py_ldb_dn_get_extended_component, METH_VARARGS,
562                 "S.get_extended_component(name) -> string\n\n"
563                 "returns a DN extended component as a binary string"},
564         { "set_extended_component", (PyCFunction)py_ldb_dn_set_extended_component, METH_VARARGS,
565                 "S.set_extended_component(name, value) -> string\n\n"
566                 "set a DN extended component as a binary string"},
567         { NULL }
568 };
569
570 static Py_ssize_t py_ldb_dn_len(PyLdbDnObject *self)
571 {
572         return ldb_dn_get_comp_num(PyLdbDn_AsDn((PyObject *)self));
573 }
574
575 static PyObject *py_ldb_dn_concat(PyLdbDnObject *self, PyObject *py_other)
576 {
577         struct ldb_dn *dn = PyLdbDn_AsDn((PyObject *)self), 
578                                   *other;
579         PyLdbDnObject *py_ret;
580         
581         if (!PyObject_AsDn(NULL, py_other, NULL, &other))
582                 return NULL;
583
584         py_ret = (PyLdbDnObject *)PyLdbDn.tp_alloc(&PyLdbDn, 0);
585         if (py_ret == NULL) {
586                 PyErr_NoMemory();
587                 return NULL;
588         }
589         py_ret->mem_ctx = talloc_new(NULL);
590         py_ret->dn = ldb_dn_copy(py_ret->mem_ctx, dn);
591         ldb_dn_add_child(py_ret->dn, other);
592         return (PyObject *)py_ret;
593 }
594
595 static PySequenceMethods py_ldb_dn_seq = {
596         .sq_length = (lenfunc)py_ldb_dn_len,
597         .sq_concat = (binaryfunc)py_ldb_dn_concat,
598 };
599
600 static PyObject *py_ldb_dn_new(PyTypeObject *type, PyObject *args, PyObject *kwargs)
601 {
602         struct ldb_dn *ret;
603         char *str;
604         PyObject *py_ldb;
605         struct ldb_context *ldb_ctx;
606         TALLOC_CTX *mem_ctx;
607         PyLdbDnObject *py_ret;
608         const char * const kwnames[] = { "ldb", "dn", NULL };
609
610         if (!PyArg_ParseTupleAndKeywords(args, kwargs, "Os",
611                                          discard_const_p(char *, kwnames),
612                                          &py_ldb, &str))
613                 return NULL;
614
615         ldb_ctx = PyLdb_AsLdbContext(py_ldb);
616
617         mem_ctx = talloc_new(NULL);
618         if (mem_ctx == NULL) {
619                 PyErr_NoMemory();
620                 return NULL;
621         }
622
623         ret = ldb_dn_new(mem_ctx, ldb_ctx, str);
624         if (!ldb_dn_validate(ret)) {
625                 talloc_free(mem_ctx);
626                 PyErr_SetString(PyExc_ValueError, "unable to parse dn string");
627                 return NULL;
628         }
629
630         py_ret = (PyLdbDnObject *)type->tp_alloc(type, 0);
631         if (ret == NULL) {
632                 talloc_free(mem_ctx);
633                 PyErr_NoMemory();
634                 return NULL;
635         }
636         py_ret->mem_ctx = mem_ctx;
637         py_ret->dn = ret;
638         return (PyObject *)py_ret;
639 }
640
641 static void py_ldb_dn_dealloc(PyLdbDnObject *self)
642 {
643         talloc_free(self->mem_ctx);
644         PyObject_Del(self);
645 }
646
647 static PyTypeObject PyLdbDn = {
648         .tp_name = "ldb.Dn",
649         .tp_methods = py_ldb_dn_methods,
650         .tp_str = (reprfunc)py_ldb_dn_get_linearized,
651         .tp_repr = (reprfunc)py_ldb_dn_repr,
652         .tp_compare = (cmpfunc)py_ldb_dn_compare,
653         .tp_as_sequence = &py_ldb_dn_seq,
654         .tp_doc = "A LDB distinguished name.",
655         .tp_new = py_ldb_dn_new,
656         .tp_dealloc = (destructor)py_ldb_dn_dealloc,
657         .tp_basicsize = sizeof(PyLdbDnObject),
658         .tp_flags = Py_TPFLAGS_DEFAULT,
659 };
660
661 /* Debug */
662 static void py_ldb_debug(void *context, enum ldb_debug_level level, const char *fmt, va_list ap) PRINTF_ATTRIBUTE(3, 0);
663 static void py_ldb_debug(void *context, enum ldb_debug_level level, const char *fmt, va_list ap)
664 {
665         PyObject *fn = (PyObject *)context;
666         PyObject_CallFunction(fn, discard_const_p(char, "(i,O)"), level, PyString_FromFormatV(fmt, ap));
667 }
668
669 static PyObject *py_ldb_set_debug(PyLdbObject *self, PyObject *args)
670 {
671         PyObject *cb;
672
673         if (!PyArg_ParseTuple(args, "O", &cb))
674                 return NULL;
675
676         Py_INCREF(cb);
677         /* FIXME: Where do we DECREF cb ? */
678         PyErr_LDB_ERROR_IS_ERR_RAISE(PyExc_LdbError, ldb_set_debug(self->ldb_ctx, py_ldb_debug, cb), PyLdb_AsLdbContext(self));
679
680         Py_RETURN_NONE;
681 }
682
683 static PyObject *py_ldb_set_create_perms(PyTypeObject *self, PyObject *args)
684 {
685         unsigned int perms;
686         if (!PyArg_ParseTuple(args, "I", &perms))
687                 return NULL;
688
689         ldb_set_create_perms(PyLdb_AsLdbContext(self), perms);
690
691         Py_RETURN_NONE;
692 }
693
694 static PyObject *py_ldb_set_modules_dir(PyTypeObject *self, PyObject *args)
695 {
696         char *modules_dir;
697         if (!PyArg_ParseTuple(args, "s", &modules_dir))
698                 return NULL;
699
700         ldb_set_modules_dir(PyLdb_AsLdbContext(self), modules_dir);
701
702         Py_RETURN_NONE;
703 }
704
705 static PyObject *py_ldb_transaction_start(PyLdbObject *self)
706 {
707         PyErr_LDB_ERROR_IS_ERR_RAISE(PyExc_LdbError, ldb_transaction_start(PyLdb_AsLdbContext(self)), PyLdb_AsLdbContext(self));
708         Py_RETURN_NONE;
709 }
710
711 static PyObject *py_ldb_transaction_commit(PyLdbObject *self)
712 {
713         PyErr_LDB_ERROR_IS_ERR_RAISE(PyExc_LdbError, ldb_transaction_commit(PyLdb_AsLdbContext(self)), PyLdb_AsLdbContext(self));
714         Py_RETURN_NONE;
715 }
716
717 static PyObject *py_ldb_transaction_prepare_commit(PyLdbObject *self)
718 {
719         PyErr_LDB_ERROR_IS_ERR_RAISE(PyExc_LdbError, ldb_transaction_prepare_commit(PyLdb_AsLdbContext(self)), PyLdb_AsLdbContext(self));
720         Py_RETURN_NONE;
721 }
722
723 static PyObject *py_ldb_transaction_cancel(PyLdbObject *self)
724 {
725         PyErr_LDB_ERROR_IS_ERR_RAISE(PyExc_LdbError, ldb_transaction_cancel(PyLdb_AsLdbContext(self)), PyLdb_AsLdbContext(self));
726         Py_RETURN_NONE;
727 }
728
729 static PyObject *py_ldb_setup_wellknown_attributes(PyLdbObject *self)
730 {
731         PyErr_LDB_ERROR_IS_ERR_RAISE(PyExc_LdbError, ldb_setup_wellknown_attributes(PyLdb_AsLdbContext(self)), PyLdb_AsLdbContext(self));
732         Py_RETURN_NONE;
733 }
734
735 static PyObject *py_ldb_repr(PyLdbObject *self)
736 {
737         return PyString_FromFormat("<ldb connection>");
738 }
739
740 static PyObject *py_ldb_get_root_basedn(PyLdbObject *self)
741 {
742         struct ldb_dn *dn = ldb_get_root_basedn(PyLdb_AsLdbContext(self));
743         if (dn == NULL)
744                 Py_RETURN_NONE;
745         return PyLdbDn_FromDn(dn);
746 }
747
748
749 static PyObject *py_ldb_get_schema_basedn(PyLdbObject *self)
750 {
751         struct ldb_dn *dn = ldb_get_schema_basedn(PyLdb_AsLdbContext(self));
752         if (dn == NULL)
753                 Py_RETURN_NONE;
754         return PyLdbDn_FromDn(dn);
755 }
756
757 static PyObject *py_ldb_get_config_basedn(PyLdbObject *self)
758 {
759         struct ldb_dn *dn = ldb_get_config_basedn(PyLdb_AsLdbContext(self));
760         if (dn == NULL)
761                 Py_RETURN_NONE;
762         return PyLdbDn_FromDn(dn);
763 }
764
765 static PyObject *py_ldb_get_default_basedn(PyLdbObject *self)
766 {
767         struct ldb_dn *dn = ldb_get_default_basedn(PyLdb_AsLdbContext(self));
768         if (dn == NULL)
769                 Py_RETURN_NONE;
770         return PyLdbDn_FromDn(dn);
771 }
772
773 static const char **PyList_AsStringList(TALLOC_CTX *mem_ctx, PyObject *list, 
774                                         const char *paramname)
775 {
776         const char **ret;
777         Py_ssize_t i;
778         if (!PyList_Check(list)) {
779                 PyErr_Format(PyExc_TypeError, "%s is not a list", paramname);
780                 return NULL;
781         }
782         ret = talloc_array(NULL, const char *, PyList_Size(list)+1);
783         if (ret == NULL) {
784                 PyErr_NoMemory();
785                 return NULL;
786         }
787
788         for (i = 0; i < PyList_Size(list); i++) {
789                 PyObject *item = PyList_GetItem(list, i);
790                 if (!PyString_Check(item)) {
791                         PyErr_Format(PyExc_TypeError, "%s should be strings", paramname);
792                         return NULL;
793                 }
794                 ret[i] = talloc_strndup(ret, PyString_AsString(item),
795                                         PyString_Size(item));
796         }
797         ret[i] = NULL;
798         return ret;
799 }
800
801 static int py_ldb_init(PyLdbObject *self, PyObject *args, PyObject *kwargs)
802 {
803         const char * const kwnames[] = { "url", "flags", "options", NULL };
804         char *url = NULL;
805         PyObject *py_options = Py_None;
806         const char **options;
807         unsigned int flags = 0;
808         int ret;
809         struct ldb_context *ldb;
810
811         if (!PyArg_ParseTupleAndKeywords(args, kwargs, "|zIO:Ldb.__init__",
812                                          discard_const_p(char *, kwnames),
813                                          &url, &flags, &py_options))
814                 return -1;
815
816         ldb = PyLdb_AsLdbContext(self);
817
818         if (py_options == Py_None) {
819                 options = NULL;
820         } else {
821                 options = PyList_AsStringList(ldb, py_options, "options");
822                 if (options == NULL)
823                         return -1;
824         }
825
826         if (url != NULL) {
827                 ret = ldb_connect(ldb, url, flags, options);
828                 if (ret != LDB_SUCCESS) {
829                         PyErr_SetLdbError(PyExc_LdbError, ret, ldb);
830                         return -1;
831                 }
832         }
833
834         talloc_free(options);
835         return 0;
836 }
837
838 static PyObject *py_ldb_new(PyTypeObject *type, PyObject *args, PyObject *kwargs)
839 {
840         PyLdbObject *ret;
841         struct ldb_context *ldb;
842         ret = (PyLdbObject *)type->tp_alloc(type, 0);
843         if (ret == NULL) {
844                 PyErr_NoMemory();
845                 return NULL;
846         }
847         ret->mem_ctx = talloc_new(NULL);
848         ldb = ldb_init(ret->mem_ctx, NULL);
849
850         if (ldb == NULL) {
851                 PyErr_NoMemory();
852                 return NULL;
853         }
854
855         ret->ldb_ctx = ldb;
856         return (PyObject *)ret;
857 }
858
859 static PyObject *py_ldb_connect(PyLdbObject *self, PyObject *args, PyObject *kwargs)
860 {
861         char *url;
862         unsigned int flags = 0;
863         PyObject *py_options = Py_None;
864         int ret;
865         const char **options;
866         const char * const kwnames[] = { "url", "flags", "options", NULL };
867
868         if (!PyArg_ParseTupleAndKeywords(args, kwargs, "|zIO",
869                                          discard_const_p(char *, kwnames),
870                                          &url, &flags, &py_options))
871                 return NULL;
872
873         if (py_options == Py_None) {
874                 options = NULL;
875         } else {
876                 options = PyList_AsStringList(NULL, py_options, "options");
877                 if (options == NULL)
878                         return NULL;
879         }
880
881         ret = ldb_connect(PyLdb_AsLdbContext(self), url, flags, options);
882         talloc_free(options);
883
884         PyErr_LDB_ERROR_IS_ERR_RAISE(PyExc_LdbError, ret, PyLdb_AsLdbContext(self));
885
886         Py_RETURN_NONE;
887 }
888
889 static PyObject *py_ldb_modify(PyLdbObject *self, PyObject *args, PyObject *kwargs)
890 {
891         PyObject *py_msg;
892         PyObject *py_controls = Py_None;
893         struct ldb_context *ldb_ctx;
894         struct ldb_request *req;
895         struct ldb_control **parsed_controls;
896         struct ldb_message *msg;
897         int ret;
898         TALLOC_CTX *mem_ctx;
899         bool validate=true;
900         const char * const kwnames[] = { "message", "controls", "validate", NULL };
901
902         if (!PyArg_ParseTupleAndKeywords(args, kwargs, "O|Ob",
903                                          discard_const_p(char *, kwnames),
904                                          &py_msg, &py_controls, &validate))
905                 return NULL;
906
907         mem_ctx = talloc_new(NULL);
908         if (mem_ctx == NULL) {
909                 PyErr_NoMemory();
910                 return NULL;
911         }
912         ldb_ctx = PyLdb_AsLdbContext(self);
913
914         if (py_controls == Py_None) {
915                 parsed_controls = NULL;
916         } else {
917                 const char **controls = PyList_AsStringList(mem_ctx, py_controls, "controls");
918                 parsed_controls = ldb_parse_control_strings(ldb_ctx, mem_ctx, controls);
919                 talloc_free(controls);
920         }
921
922         if (!PyLdbMessage_Check(py_msg)) {
923                 PyErr_SetString(PyExc_TypeError, "Expected Ldb Message");
924                 talloc_free(mem_ctx);
925                 return NULL;
926         }
927         msg = PyLdbMessage_AsMessage(py_msg);
928
929         if (validate) {
930                 ret = ldb_msg_sanity_check(ldb_ctx, msg);
931                 if (ret != LDB_SUCCESS) {
932                         PyErr_LDB_ERROR_IS_ERR_RAISE(PyExc_LdbError, ret, ldb_ctx);
933                         talloc_free(mem_ctx);
934                         return NULL;
935                 }
936         }
937
938         ret = ldb_build_mod_req(&req, ldb_ctx, mem_ctx, msg, parsed_controls,
939                                 NULL, ldb_op_default_callback, NULL);
940         if (ret != LDB_SUCCESS) {
941                 PyErr_SetString(PyExc_TypeError, "failed to build request");
942                 talloc_free(mem_ctx);
943                 return NULL;
944         }
945
946         /* do request and autostart a transaction */
947         /* Then let's LDB handle the message error in case of pb as they are meaningful */
948
949         ret = ldb_transaction_start(ldb_ctx);
950         if (ret != LDB_SUCCESS) {
951                 talloc_free(mem_ctx);
952                 PyErr_LDB_ERROR_IS_ERR_RAISE(PyExc_LdbError, ret, ldb_ctx);
953         }
954
955         ret = ldb_request(ldb_ctx, req);
956         if (ret == LDB_SUCCESS) {
957                         ret = ldb_wait(req->handle, LDB_WAIT_ALL);
958         }
959
960         if (ret == LDB_SUCCESS) {
961                 ret = ldb_transaction_commit(ldb_ctx);
962         } else {
963                 ldb_transaction_cancel(ldb_ctx);
964                 if (ldb_ctx->err_string == NULL) {
965                         /* no error string was setup by the backend */
966                         ldb_asprintf_errstring(ldb_ctx, "%s (%d)", ldb_strerror(ret), ret);
967                 }
968         }
969
970         talloc_free(mem_ctx);
971         PyErr_LDB_ERROR_IS_ERR_RAISE(PyExc_LdbError, ret, ldb_ctx);
972
973         Py_RETURN_NONE;
974 }
975
976
977 /**
978  * Obtain a ldb message from a Python Dictionary object.
979  *
980  * @param mem_ctx Memory context
981  * @param py_obj Python Dictionary object
982  * @param ldb_ctx LDB context
983  * @param mod_flags Flags to be set on every message element
984  * @return ldb_message on success or NULL on failure
985  */
986 static struct ldb_message *PyDict_AsMessage(TALLOC_CTX *mem_ctx,
987                                             PyObject *py_obj,
988                                             struct ldb_context *ldb_ctx,
989                                             unsigned int mod_flags)
990 {
991         struct ldb_message *msg;
992         unsigned int msg_pos = 0;
993         Py_ssize_t dict_pos = 0;
994         PyObject *key, *value;
995         struct ldb_message_element *msg_el;
996         PyObject *dn_value = PyDict_GetItemString(py_obj, "dn");
997
998         msg = ldb_msg_new(mem_ctx);
999         msg->elements = talloc_zero_array(msg, struct ldb_message_element, PyDict_Size(py_obj));
1000
1001         if (dn_value) {
1002                 if (!PyObject_AsDn(msg, dn_value, ldb_ctx, &msg->dn)) {
1003                         PyErr_SetString(PyExc_TypeError, "unable to import dn object");
1004                         return NULL;
1005                 }
1006                 if (msg->dn == NULL) {
1007                         PyErr_SetString(PyExc_TypeError, "dn set but not found");
1008                         return NULL;
1009                 }
1010         } else {
1011                 PyErr_SetString(PyExc_TypeError, "no dn set");
1012                 return NULL;
1013         }
1014
1015         while (PyDict_Next(py_obj, &dict_pos, &key, &value)) {
1016                 char *key_str = PyString_AsString(key);
1017                 if (strcmp(key_str, "dn") != 0) {
1018                         msg_el = PyObject_AsMessageElement(msg->elements, value,
1019                                                            mod_flags, key_str);
1020                         if (msg_el == NULL) {
1021                                 PyErr_SetString(PyExc_TypeError, "unable to import element");
1022                                 return NULL;
1023                         }
1024                         memcpy(&msg->elements[msg_pos], msg_el, sizeof(*msg_el));
1025                         msg_pos++;
1026                 }
1027         }
1028
1029         msg->num_elements = msg_pos;
1030
1031         return msg;
1032 }
1033
1034 static PyObject *py_ldb_add(PyLdbObject *self, PyObject *args, PyObject *kwargs)
1035 {
1036         PyObject *py_obj;
1037         int ret;
1038         struct ldb_context *ldb_ctx;
1039         struct ldb_request *req;
1040         struct ldb_message *msg = NULL;
1041         PyObject *py_controls = Py_None;
1042         TALLOC_CTX *mem_ctx;
1043         struct ldb_control **parsed_controls;
1044         const char * const kwnames[] = { "message", "controls", NULL };
1045
1046         if (!PyArg_ParseTupleAndKeywords(args, kwargs, "O|O",
1047                                          discard_const_p(char *, kwnames),
1048                                          &py_obj, &py_controls))
1049                 return NULL;
1050
1051         mem_ctx = talloc_new(NULL);
1052         if (mem_ctx == NULL) {
1053                 PyErr_NoMemory();
1054                 return NULL;
1055         }
1056         ldb_ctx = PyLdb_AsLdbContext(self);
1057
1058         if (py_controls == Py_None) {
1059                 parsed_controls = NULL;
1060         } else {
1061                 const char **controls = PyList_AsStringList(mem_ctx, py_controls, "controls");
1062                 parsed_controls = ldb_parse_control_strings(ldb_ctx, mem_ctx, controls);
1063                 talloc_free(controls);
1064         }
1065
1066         if (PyLdbMessage_Check(py_obj)) {
1067                 msg = PyLdbMessage_AsMessage(py_obj);
1068         } else if (PyDict_Check(py_obj)) {
1069                 msg = PyDict_AsMessage(mem_ctx, py_obj, ldb_ctx, LDB_FLAG_MOD_ADD);
1070         } else {
1071                 PyErr_SetString(PyExc_TypeError,
1072                                 "Dictionary or LdbMessage object expected!");
1073         }
1074
1075         if (!msg) {
1076                 /* we should have a PyErr already set */
1077                 talloc_free(mem_ctx);
1078                 return NULL;
1079         }
1080
1081         ret = ldb_msg_sanity_check(ldb_ctx, msg);
1082         if (ret != LDB_SUCCESS) {
1083                 PyErr_LDB_ERROR_IS_ERR_RAISE(PyExc_LdbError, ret, ldb_ctx);
1084                 talloc_free(mem_ctx);
1085                 return NULL;
1086         }
1087
1088         ret = ldb_build_add_req(&req, ldb_ctx, mem_ctx, msg, parsed_controls,
1089                                 NULL, ldb_op_default_callback, NULL);
1090         if (ret != LDB_SUCCESS) {
1091                 PyErr_SetString(PyExc_TypeError, "failed to build request");
1092                 talloc_free(mem_ctx);
1093                 return NULL;
1094         }
1095
1096         /* do request and autostart a transaction */
1097         /* Then let's LDB handle the message error in case of pb as they are meaningful */
1098
1099         ret = ldb_transaction_start(ldb_ctx);
1100         if (ret != LDB_SUCCESS) {
1101                 talloc_free(mem_ctx);
1102                 PyErr_LDB_ERROR_IS_ERR_RAISE(PyExc_LdbError, ret, ldb_ctx);
1103         }
1104
1105         ret = ldb_request(ldb_ctx, req);
1106         if (ret == LDB_SUCCESS) {
1107                         ret = ldb_wait(req->handle, LDB_WAIT_ALL);
1108         } 
1109
1110         if (ret == LDB_SUCCESS) {
1111                         ret = ldb_transaction_commit(ldb_ctx);
1112         } else {
1113                 ldb_transaction_cancel(ldb_ctx);
1114                 if (ldb_ctx->err_string == NULL) {
1115                         /* no error string was setup by the backend */
1116                         ldb_asprintf_errstring(ldb_ctx, "%s (%d)", ldb_strerror(ret), ret);
1117                 }
1118         }
1119
1120         talloc_free(mem_ctx);
1121         PyErr_LDB_ERROR_IS_ERR_RAISE(PyExc_LdbError, ret, ldb_ctx);
1122
1123         Py_RETURN_NONE;
1124 }
1125
1126 static PyObject *py_ldb_delete(PyLdbObject *self, PyObject *args, PyObject *kwargs)
1127 {
1128         PyObject *py_dn;
1129         struct ldb_dn *dn;
1130         int ret;
1131         struct ldb_context *ldb_ctx;
1132         struct ldb_request *req;
1133         PyObject *py_controls = Py_None;
1134         TALLOC_CTX *mem_ctx;
1135         struct ldb_control **parsed_controls;
1136         const char * const kwnames[] = { "dn", "controls", NULL };
1137
1138         if (!PyArg_ParseTupleAndKeywords(args, kwargs, "O|O",
1139                                          discard_const_p(char *, kwnames),
1140                                          &py_dn, &py_controls))
1141                 return NULL;
1142
1143         mem_ctx = talloc_new(NULL);
1144         if (mem_ctx == NULL) {
1145                 PyErr_NoMemory();
1146                 return NULL;
1147         }
1148         ldb_ctx = PyLdb_AsLdbContext(self);
1149
1150         if (py_controls == Py_None) {
1151                 parsed_controls = NULL;
1152         } else {
1153                 const char **controls = PyList_AsStringList(mem_ctx, py_controls, "controls");
1154                 parsed_controls = ldb_parse_control_strings(ldb_ctx, mem_ctx, controls);
1155                 talloc_free(controls);
1156         }
1157
1158         if (!PyObject_AsDn(mem_ctx, py_dn, ldb_ctx, &dn)) {
1159                 talloc_free(mem_ctx);
1160                 return NULL;
1161         }
1162
1163         ret = ldb_build_del_req(&req, ldb_ctx, mem_ctx, dn, parsed_controls,
1164                                 NULL, ldb_op_default_callback, NULL);
1165         if (ret != LDB_SUCCESS) {
1166                 PyErr_SetString(PyExc_TypeError, "failed to build request");
1167                 talloc_free(mem_ctx);
1168                 return NULL;
1169         }
1170
1171         /* do request and autostart a transaction */
1172         /* Then let's LDB handle the message error in case of pb as they are meaningful */
1173
1174         ret = ldb_transaction_start(ldb_ctx);
1175         if (ret != LDB_SUCCESS) {
1176                 talloc_free(mem_ctx);
1177                 PyErr_LDB_ERROR_IS_ERR_RAISE(PyExc_LdbError, ret, ldb_ctx);
1178         }
1179
1180         ret = ldb_request(ldb_ctx, req);
1181         if (ret == LDB_SUCCESS) {
1182                 ret = ldb_wait(req->handle, LDB_WAIT_ALL);
1183         }
1184
1185         if (ret == LDB_SUCCESS) {
1186                 ret = ldb_transaction_commit(ldb_ctx);
1187         } else {
1188                 ldb_transaction_cancel(ldb_ctx);
1189                 if (ldb_ctx->err_string == NULL) {
1190                         /* no error string was setup by the backend */
1191                         ldb_asprintf_errstring(ldb_ctx, "%s (%d)", ldb_strerror(ret), ret);
1192                 }
1193         }
1194
1195         talloc_free(mem_ctx);
1196         PyErr_LDB_ERROR_IS_ERR_RAISE(PyExc_LdbError, ret, ldb_ctx);
1197
1198         Py_RETURN_NONE;
1199 }
1200
1201 static PyObject *py_ldb_rename(PyLdbObject *self, PyObject *args, PyObject *kwargs)
1202 {
1203         PyObject *py_dn1, *py_dn2;
1204         struct ldb_dn *dn1, *dn2;
1205         int ret;
1206         struct ldb_context *ldb;
1207         TALLOC_CTX *mem_ctx;
1208         PyObject *py_controls = Py_None;
1209         struct ldb_control **parsed_controls;
1210         struct ldb_context *ldb_ctx;
1211         struct ldb_request *req;
1212         const char * const kwnames[] = { "dn1", "dn2", "controls", NULL };
1213
1214         ldb_ctx = PyLdb_AsLdbContext(self);
1215
1216         if (!PyArg_ParseTupleAndKeywords(args, kwargs, "OO|O",
1217                                          discard_const_p(char *, kwnames),
1218                                          &py_dn1, &py_dn2, &py_controls))
1219                 return NULL;
1220
1221
1222         mem_ctx = talloc_new(NULL);
1223         if (mem_ctx == NULL) {
1224                 PyErr_NoMemory();
1225                 return NULL;
1226         }
1227         ldb = PyLdb_AsLdbContext(self);
1228
1229         if (py_controls == Py_None) {
1230                 parsed_controls = NULL;
1231         } else {
1232                 const char **controls = PyList_AsStringList(mem_ctx, py_controls, "controls");
1233                 parsed_controls = ldb_parse_control_strings(ldb_ctx, mem_ctx, controls);
1234                 talloc_free(controls);
1235         }
1236
1237
1238         if (!PyObject_AsDn(mem_ctx, py_dn1, ldb, &dn1)) {
1239                 talloc_free(mem_ctx);
1240                 return NULL;
1241         }
1242
1243         if (!PyObject_AsDn(mem_ctx, py_dn2, ldb, &dn2)) {
1244                 talloc_free(mem_ctx);
1245                 return NULL;
1246         }
1247
1248         ret = ldb_build_rename_req(&req, ldb_ctx, mem_ctx, dn1, dn2, parsed_controls,
1249                                 NULL, ldb_op_default_callback, NULL);
1250         if (ret != LDB_SUCCESS) {
1251                 PyErr_SetString(PyExc_TypeError, "failed to build request");
1252                 talloc_free(mem_ctx);
1253                 return NULL;
1254         }
1255
1256         /* do request and autostart a transaction */
1257         /* Then let's LDB handle the message error in case of pb as they are meaningful */
1258
1259         ret = ldb_transaction_start(ldb_ctx);
1260         if (ret != LDB_SUCCESS) {
1261                 talloc_free(mem_ctx);
1262                 PyErr_LDB_ERROR_IS_ERR_RAISE(PyExc_LdbError, ret, ldb_ctx);
1263         }
1264
1265         ret = ldb_request(ldb_ctx, req);
1266         if (ret == LDB_SUCCESS) {
1267                 ret = ldb_wait(req->handle, LDB_WAIT_ALL);
1268         }
1269
1270         if (ret == LDB_SUCCESS) {
1271                 ret = ldb_transaction_commit(ldb_ctx);
1272         } else {
1273                 ldb_transaction_cancel(ldb_ctx);
1274                 if (ldb_ctx->err_string == NULL) {
1275                         /* no error string was setup by the backend */
1276                         ldb_asprintf_errstring(ldb_ctx, "%s (%d)", ldb_strerror(ret), ret);
1277                 }
1278         }
1279
1280         talloc_free(mem_ctx);
1281         PyErr_LDB_ERROR_IS_ERR_RAISE(PyExc_LdbError, ret, ldb_ctx);
1282
1283         Py_RETURN_NONE;
1284 }
1285
1286 static PyObject *py_ldb_schema_attribute_remove(PyLdbObject *self, PyObject *args)
1287 {
1288         char *name;
1289         if (!PyArg_ParseTuple(args, "s", &name))
1290                 return NULL;
1291
1292         ldb_schema_attribute_remove(PyLdb_AsLdbContext(self), name);
1293
1294         Py_RETURN_NONE;
1295 }
1296
1297 static PyObject *py_ldb_schema_attribute_add(PyLdbObject *self, PyObject *args)
1298 {
1299         char *attribute, *syntax;
1300         unsigned int flags;
1301         int ret;
1302         if (!PyArg_ParseTuple(args, "sIs", &attribute, &flags, &syntax))
1303                 return NULL;
1304
1305         ret = ldb_schema_attribute_add(PyLdb_AsLdbContext(self), attribute, flags, syntax);
1306
1307         PyErr_LDB_ERROR_IS_ERR_RAISE(PyExc_LdbError, ret, PyLdb_AsLdbContext(self));
1308
1309         Py_RETURN_NONE;
1310 }
1311
1312 static PyObject *ldb_ldif_to_pyobject(struct ldb_ldif *ldif)
1313 {
1314         if (ldif == NULL) {
1315                 Py_RETURN_NONE;
1316         } else {
1317         /* We don't want this attached to the 'ldb' any more */
1318                 return Py_BuildValue(discard_const_p(char, "(iO)"),
1319                                      ldif->changetype,
1320                                      PyLdbMessage_FromMessage(ldif->msg));
1321         }
1322 }
1323
1324
1325 static PyObject *py_ldb_write_ldif(PyLdbObject *self, PyObject *args)
1326 {
1327         int changetype;
1328         PyObject *py_msg;
1329         struct ldb_ldif ldif;
1330         PyObject *ret;
1331         char *string;
1332         TALLOC_CTX *mem_ctx;
1333
1334         if (!PyArg_ParseTuple(args, "Oi", &py_msg, &changetype))
1335                 return NULL;
1336
1337         if (!PyLdbMessage_Check(py_msg)) {
1338                 PyErr_SetString(PyExc_TypeError, "Expected Ldb Message for msg");
1339                 return NULL;
1340         }
1341
1342         ldif.msg = PyLdbMessage_AsMessage(py_msg);
1343         ldif.changetype = changetype;
1344
1345         mem_ctx = talloc_new(NULL);
1346
1347         string = ldb_ldif_write_string(PyLdb_AsLdbContext(self), mem_ctx, &ldif);
1348         if (!string) {
1349                 PyErr_SetString(PyExc_KeyError, "Failed to generate LDIF");
1350                 return NULL;
1351         }
1352
1353         ret = PyString_FromString(string);
1354
1355         talloc_free(mem_ctx);
1356
1357         return ret;
1358 }
1359
1360 static PyObject *py_ldb_parse_ldif(PyLdbObject *self, PyObject *args)
1361 {
1362         PyObject *list;
1363         struct ldb_ldif *ldif;
1364         const char *s;
1365
1366         TALLOC_CTX *mem_ctx;
1367
1368         if (!PyArg_ParseTuple(args, "s", &s))
1369                 return NULL;
1370
1371         mem_ctx = talloc_new(NULL);
1372         if (!mem_ctx) {
1373                 Py_RETURN_NONE;
1374         }
1375
1376         list = PyList_New(0);
1377         while (s && *s != '\0') {
1378                 ldif = ldb_ldif_read_string(self->ldb_ctx, &s);
1379                 talloc_steal(mem_ctx, ldif);
1380                 if (ldif) {
1381                         PyList_Append(list, ldb_ldif_to_pyobject(ldif));
1382                 } else {
1383                         PyErr_SetString(PyExc_ValueError, "unable to parse ldif string");
1384                         talloc_free(mem_ctx);
1385                         return NULL;
1386                 }
1387         }
1388         talloc_free(mem_ctx); /* The pyobject already has a reference to the things it needs */
1389         return PyObject_GetIter(list);
1390 }
1391
1392 static PyObject *py_ldb_msg_diff(PyLdbObject *self, PyObject *args)
1393 {
1394         int ldb_ret;
1395         PyObject *py_msg_old;
1396         PyObject *py_msg_new;
1397         struct ldb_message *diff;
1398         struct ldb_context *ldb;
1399         PyObject *py_ret;
1400
1401         if (!PyArg_ParseTuple(args, "OO", &py_msg_old, &py_msg_new))
1402                 return NULL;
1403
1404         if (!PyLdbMessage_Check(py_msg_old)) {
1405                 PyErr_SetString(PyExc_TypeError, "Expected Ldb Message for old message");
1406                 return NULL;
1407         }
1408
1409         if (!PyLdbMessage_Check(py_msg_new)) {
1410                 PyErr_SetString(PyExc_TypeError, "Expected Ldb Message for new message");
1411                 return NULL;
1412         }
1413
1414         ldb = PyLdb_AsLdbContext(self);
1415         ldb_ret = ldb_msg_difference(ldb, ldb,
1416                                      PyLdbMessage_AsMessage(py_msg_old),
1417                                      PyLdbMessage_AsMessage(py_msg_new),
1418                                      &diff);
1419         if (ldb_ret != LDB_SUCCESS) {
1420                 PyErr_SetString(PyExc_RuntimeError, "Failed to generate the Ldb Message diff");
1421                 return NULL;
1422         }
1423
1424         py_ret = PyLdbMessage_FromMessage(diff);
1425
1426         talloc_unlink(ldb, diff);
1427
1428         return py_ret;
1429 }
1430
1431 static PyObject *py_ldb_schema_format_value(PyLdbObject *self, PyObject *args)
1432 {
1433         const struct ldb_schema_attribute *a;
1434         struct ldb_val old_val;
1435         struct ldb_val new_val;
1436         TALLOC_CTX *mem_ctx;
1437         PyObject *ret;
1438         char *element_name;
1439         PyObject *val;
1440
1441         if (!PyArg_ParseTuple(args, "sO", &element_name, &val))
1442                 return NULL;
1443
1444         mem_ctx = talloc_new(NULL);
1445
1446         old_val.data = (uint8_t *)PyString_AsString(val);
1447         old_val.length = PyString_Size(val);
1448
1449         a = ldb_schema_attribute_by_name(PyLdb_AsLdbContext(self), element_name);
1450
1451         if (a == NULL) {
1452                 Py_RETURN_NONE;
1453         }
1454
1455         if (a->syntax->ldif_write_fn(PyLdb_AsLdbContext(self), mem_ctx, &old_val, &new_val) != 0) {
1456                 talloc_free(mem_ctx);
1457                 Py_RETURN_NONE;
1458         }
1459
1460         ret = PyString_FromStringAndSize((const char *)new_val.data, new_val.length);
1461
1462         talloc_free(mem_ctx);
1463
1464         return ret;
1465 }
1466
1467 static PyObject *py_ldb_search(PyLdbObject *self, PyObject *args, PyObject *kwargs)
1468 {
1469         PyObject *py_base = Py_None;
1470         int scope = LDB_SCOPE_DEFAULT;
1471         char *expr = NULL;
1472         PyObject *py_attrs = Py_None;
1473         PyObject *py_controls = Py_None;
1474         const char * const kwnames[] = { "base", "scope", "expression", "attrs", "controls", NULL };
1475         int ret;
1476         struct ldb_result *res;
1477         struct ldb_request *req;
1478         const char **attrs;
1479         struct ldb_context *ldb_ctx;
1480         struct ldb_control **parsed_controls;
1481         struct ldb_dn *base;
1482         PyObject *py_ret;
1483         TALLOC_CTX *mem_ctx;
1484
1485         /* type "int" rather than "enum" for "scope" is intentional */
1486         if (!PyArg_ParseTupleAndKeywords(args, kwargs, "|OizOO",
1487                                          discard_const_p(char *, kwnames),
1488                                          &py_base, &scope, &expr, &py_attrs, &py_controls))
1489                 return NULL;
1490
1491
1492         mem_ctx = talloc_new(NULL);
1493         if (mem_ctx == NULL) {
1494                 PyErr_NoMemory();
1495                 return NULL;
1496         }
1497         ldb_ctx = PyLdb_AsLdbContext(self);
1498
1499         if (py_attrs == Py_None) {
1500                 attrs = NULL;
1501         } else {
1502                 attrs = PyList_AsStringList(mem_ctx, py_attrs, "attrs");
1503                 if (attrs == NULL) {
1504                         talloc_free(mem_ctx);
1505                         return NULL;
1506                 }
1507         }
1508
1509         if (py_base == Py_None) {
1510                 base = ldb_get_default_basedn(ldb_ctx);
1511         } else {
1512                 if (!PyObject_AsDn(ldb_ctx, py_base, ldb_ctx, &base)) {
1513                         talloc_free(attrs);
1514                         return NULL;
1515                 }
1516         }
1517
1518         if (py_controls == Py_None) {
1519                 parsed_controls = NULL;
1520         } else {
1521                 const char **controls = PyList_AsStringList(mem_ctx, py_controls, "controls");
1522                 parsed_controls = ldb_parse_control_strings(ldb_ctx, mem_ctx, controls);
1523                 talloc_free(controls);
1524         }
1525
1526         res = talloc_zero(mem_ctx, struct ldb_result);
1527         if (res == NULL) {
1528                 PyErr_NoMemory();
1529                 talloc_free(mem_ctx);
1530                 return NULL;
1531         }
1532
1533         ret = ldb_build_search_req(&req, ldb_ctx, mem_ctx,
1534                                    base,
1535                                    scope,
1536                                    expr,
1537                                    attrs,
1538                                    parsed_controls,
1539                                    res,
1540                                    ldb_search_default_callback,
1541                                    NULL);
1542
1543         if (ret != LDB_SUCCESS) {
1544                 talloc_free(mem_ctx);
1545                 PyErr_LDB_ERROR_IS_ERR_RAISE(PyExc_LdbError, ret, ldb_ctx);
1546                 return NULL;
1547         }
1548
1549         talloc_steal(req, attrs);
1550
1551         ret = ldb_request(ldb_ctx, req);
1552
1553         if (ret == LDB_SUCCESS) {
1554                 ret = ldb_wait(req->handle, LDB_WAIT_ALL);
1555         }
1556
1557         if (ret != LDB_SUCCESS) {
1558                 talloc_free(mem_ctx);
1559                 PyErr_LDB_ERROR_IS_ERR_RAISE(PyExc_LdbError, ret, ldb_ctx);
1560                 return NULL;
1561         }
1562
1563         py_ret = PyLdbResult_FromResult(res);
1564
1565         talloc_free(mem_ctx);
1566
1567         return py_ret;
1568 }
1569
1570 static PyObject *py_ldb_get_opaque(PyLdbObject *self, PyObject *args)
1571 {
1572         char *name;
1573         void *data;
1574
1575         if (!PyArg_ParseTuple(args, "s", &name))
1576                 return NULL;
1577
1578         data = ldb_get_opaque(PyLdb_AsLdbContext(self), name);
1579
1580         if (data == NULL)
1581                 Py_RETURN_NONE;
1582
1583         /* FIXME: More interpretation */
1584
1585         return Py_True;
1586 }
1587
1588 static PyObject *py_ldb_set_opaque(PyLdbObject *self, PyObject *args)
1589 {
1590         char *name;
1591         PyObject *data;
1592
1593         if (!PyArg_ParseTuple(args, "sO", &name, &data))
1594                 return NULL;
1595
1596         /* FIXME: More interpretation */
1597
1598         ldb_set_opaque(PyLdb_AsLdbContext(self), name, data);
1599
1600         Py_RETURN_NONE;
1601 }
1602
1603 static PyObject *py_ldb_modules(PyLdbObject *self)
1604 {
1605         struct ldb_context *ldb = PyLdb_AsLdbContext(self);
1606         PyObject *ret = PyList_New(0);
1607         struct ldb_module *mod;
1608
1609         for (mod = ldb->modules; mod; mod = mod->next) {
1610                 PyList_Append(ret, PyLdbModule_FromModule(mod));
1611         }
1612
1613         return ret;
1614 }
1615
1616 static PyObject *py_ldb_sequence_number(PyLdbObject *self, PyObject *args)
1617 {
1618         struct ldb_context *ldb = PyLdb_AsLdbContext(self);
1619         int type, ret;
1620         uint64_t value;
1621
1622         if (!PyArg_ParseTuple(args, "i", &type))
1623                 return NULL;
1624
1625         /* FIXME: More interpretation */
1626
1627         ret = ldb_sequence_number(ldb, type, &value);
1628
1629         if (ret != LDB_SUCCESS) {
1630                 PyErr_LDB_ERROR_IS_ERR_RAISE(PyExc_LdbError, ret, ldb);
1631                 return NULL;
1632         }
1633         return PyLong_FromLongLong(value);
1634 }
1635 static PyMethodDef py_ldb_methods[] = {
1636         { "set_debug", (PyCFunction)py_ldb_set_debug, METH_VARARGS, 
1637                 "S.set_debug(callback) -> None\n"
1638                 "Set callback for LDB debug messages.\n"
1639                 "The callback should accept a debug level and debug text." },
1640         { "set_create_perms", (PyCFunction)py_ldb_set_create_perms, METH_VARARGS, 
1641                 "S.set_create_perms(mode) -> None\n"
1642                 "Set mode to use when creating new LDB files." },
1643         { "set_modules_dir", (PyCFunction)py_ldb_set_modules_dir, METH_VARARGS,
1644                 "S.set_modules_dir(path) -> None\n"
1645                 "Set path LDB should search for modules" },
1646         { "transaction_start", (PyCFunction)py_ldb_transaction_start, METH_NOARGS, 
1647                 "S.transaction_start() -> None\n"
1648                 "Start a new transaction." },
1649         { "transaction_prepare_commit", (PyCFunction)py_ldb_transaction_prepare_commit, METH_NOARGS,
1650                 "S.transaction_prepare_commit() -> None\n"
1651                 "prepare to commit a new transaction (2-stage commit)." },
1652         { "transaction_commit", (PyCFunction)py_ldb_transaction_commit, METH_NOARGS, 
1653                 "S.transaction_commit() -> None\n"
1654                 "commit a new transaction." },
1655         { "transaction_cancel", (PyCFunction)py_ldb_transaction_cancel, METH_NOARGS, 
1656                 "S.transaction_cancel() -> None\n"
1657                 "cancel a new transaction." },
1658         { "setup_wellknown_attributes", (PyCFunction)py_ldb_setup_wellknown_attributes, METH_NOARGS, 
1659                 NULL },
1660         { "get_root_basedn", (PyCFunction)py_ldb_get_root_basedn, METH_NOARGS,
1661                 NULL },
1662         { "get_schema_basedn", (PyCFunction)py_ldb_get_schema_basedn, METH_NOARGS,
1663                 NULL },
1664         { "get_default_basedn", (PyCFunction)py_ldb_get_default_basedn, METH_NOARGS,
1665                 NULL },
1666         { "get_config_basedn", (PyCFunction)py_ldb_get_config_basedn, METH_NOARGS,
1667                 NULL },
1668         { "connect", (PyCFunction)py_ldb_connect, METH_VARARGS|METH_KEYWORDS, 
1669                 "S.connect(url, flags=0, options=None) -> None\n"
1670                 "Connect to a LDB URL." },
1671         { "modify", (PyCFunction)py_ldb_modify, METH_VARARGS|METH_KEYWORDS,
1672                 "S.modify(message, controls=None, validate=False) -> None\n"
1673                 "Modify an entry." },
1674         { "add", (PyCFunction)py_ldb_add, METH_VARARGS|METH_KEYWORDS,
1675                 "S.add(message, controls=None) -> None\n"
1676                 "Add an entry." },
1677         { "delete", (PyCFunction)py_ldb_delete, METH_VARARGS|METH_KEYWORDS,
1678                 "S.delete(dn, controls=None) -> None\n"
1679                 "Remove an entry." },
1680         { "rename", (PyCFunction)py_ldb_rename, METH_VARARGS|METH_KEYWORDS,
1681                 "S.rename(old_dn, new_dn, controls=None) -> None\n"
1682                 "Rename an entry." },
1683         { "search", (PyCFunction)py_ldb_search, METH_VARARGS|METH_KEYWORDS,
1684                 "S.search(base=None, scope=None, expression=None, attrs=None, controls=None) -> msgs\n"
1685                 "Search in a database.\n"
1686                 "\n"
1687                 ":param base: Optional base DN to search\n"
1688                 ":param scope: Search scope (SCOPE_BASE, SCOPE_ONELEVEL or SCOPE_SUBTREE)\n"
1689                 ":param expression: Optional search expression\n"
1690                 ":param attrs: Attributes to return (defaults to all)\n"
1691                 ":param controls: Optional list of controls\n"
1692                 ":return: Iterator over Message objects\n"
1693         },
1694         { "schema_attribute_remove", (PyCFunction)py_ldb_schema_attribute_remove, METH_VARARGS,
1695                 NULL },
1696         { "schema_attribute_add", (PyCFunction)py_ldb_schema_attribute_add, METH_VARARGS,
1697                 NULL },
1698         { "schema_format_value", (PyCFunction)py_ldb_schema_format_value, METH_VARARGS,
1699                 NULL },
1700         { "parse_ldif", (PyCFunction)py_ldb_parse_ldif, METH_VARARGS,
1701                 "S.parse_ldif(ldif) -> iter(messages)\n"
1702                 "Parse a string formatted using LDIF." },
1703         { "write_ldif", (PyCFunction)py_ldb_write_ldif, METH_VARARGS,
1704                 "S.write_ldif(message, changetype) -> ldif\n"
1705                 "Print the message as a string formatted using LDIF." },
1706         { "msg_diff", (PyCFunction)py_ldb_msg_diff, METH_VARARGS,
1707                 "S.msg_diff(Message) -> Message\n"
1708                 "Return an LDB Message of the difference between two Message objects." },
1709         { "get_opaque", (PyCFunction)py_ldb_get_opaque, METH_VARARGS,
1710                 "S.get_opaque(name) -> value\n"
1711                 "Get an opaque value set on this LDB connection. \n"
1712                 ":note: The returned value may not be useful in Python."
1713         },
1714         { "set_opaque", (PyCFunction)py_ldb_set_opaque, METH_VARARGS,
1715                 "S.set_opaque(name, value) -> None\n"
1716                 "Set an opaque value on this LDB connection. \n"
1717                 ":note: Passing incorrect values may cause crashes." },
1718         { "modules", (PyCFunction)py_ldb_modules, METH_NOARGS,
1719                 "S.modules() -> list\n"
1720                 "Return the list of modules on this LDB connection " },
1721         { "sequence_number", (PyCFunction)py_ldb_sequence_number, METH_VARARGS,
1722                 "S.sequence_number(type) -> value\n"
1723                 "Return the value of the sequence according to the requested type" },
1724         { NULL },
1725 };
1726
1727 static PyObject *PyLdbModule_FromModule(struct ldb_module *mod)
1728 {
1729         PyLdbModuleObject *ret;
1730
1731         ret = (PyLdbModuleObject *)PyLdbModule.tp_alloc(&PyLdbModule, 0);
1732         if (ret == NULL) {
1733                 PyErr_NoMemory();
1734                 return NULL;
1735         }
1736         ret->mem_ctx = talloc_new(NULL);
1737         ret->mod = talloc_reference(ret->mem_ctx, mod);
1738         return (PyObject *)ret;
1739 }
1740
1741 static PyObject *py_ldb_get_firstmodule(PyLdbObject *self, void *closure)
1742 {
1743         return PyLdbModule_FromModule(PyLdb_AsLdbContext(self)->modules);
1744 }
1745
1746 static PyGetSetDef py_ldb_getset[] = {
1747         { discard_const_p(char, "firstmodule"), (getter)py_ldb_get_firstmodule, NULL, NULL },
1748         { NULL }
1749 };
1750
1751 static int py_ldb_contains(PyLdbObject *self, PyObject *obj)
1752 {
1753         struct ldb_context *ldb_ctx = PyLdb_AsLdbContext(self);
1754         struct ldb_dn *dn;
1755         struct ldb_result *result;
1756         unsigned int count;
1757         int ret;
1758
1759         if (!PyObject_AsDn(ldb_ctx, obj, ldb_ctx, &dn)) {
1760                 return -1;
1761         }
1762
1763         ret = ldb_search(ldb_ctx, ldb_ctx, &result, dn, LDB_SCOPE_BASE, NULL,
1764                          NULL);
1765         if (ret != LDB_SUCCESS) {
1766                 PyErr_SetLdbError(PyExc_LdbError, ret, ldb_ctx);
1767                 return -1;
1768         }
1769
1770         count = result->count;
1771
1772         talloc_free(result);
1773
1774         if (count > 1) {
1775                 PyErr_Format(PyExc_RuntimeError,
1776                              "Searching for [%s] dn gave %u results!",
1777                              ldb_dn_get_linearized(dn),
1778                              count);
1779                 return -1;
1780         }
1781
1782         return count;
1783 }
1784
1785 static PySequenceMethods py_ldb_seq = {
1786         .sq_contains = (objobjproc)py_ldb_contains,
1787 };
1788
1789 static PyObject *PyLdb_FromLdbContext(struct ldb_context *ldb_ctx)
1790 {
1791         PyLdbObject *ret;
1792
1793         ret = (PyLdbObject *)PyLdb.tp_alloc(&PyLdb, 0);
1794         if (ret == NULL) {
1795                 PyErr_NoMemory();
1796                 return NULL;
1797         }
1798         ret->mem_ctx = talloc_new(NULL);
1799         ret->ldb_ctx = talloc_reference(ret->mem_ctx, ldb_ctx);
1800         return (PyObject *)ret;
1801 }
1802
1803 static void py_ldb_dealloc(PyLdbObject *self)
1804 {
1805         talloc_free(self->mem_ctx);
1806         self->ob_type->tp_free(self);
1807 }
1808
1809 static PyTypeObject PyLdb = {
1810         .tp_name = "ldb.Ldb",
1811         .tp_methods = py_ldb_methods,
1812         .tp_repr = (reprfunc)py_ldb_repr,
1813         .tp_new = py_ldb_new,
1814         .tp_init = (initproc)py_ldb_init,
1815         .tp_dealloc = (destructor)py_ldb_dealloc,
1816         .tp_getset = py_ldb_getset,
1817         .tp_getattro = PyObject_GenericGetAttr,
1818         .tp_basicsize = sizeof(PyLdbObject),
1819         .tp_doc = "Connection to a LDB database.",
1820         .tp_as_sequence = &py_ldb_seq,
1821         .tp_flags = Py_TPFLAGS_DEFAULT|Py_TPFLAGS_BASETYPE,
1822 };
1823
1824 static void py_ldb_result_dealloc(PyLdbResultObject *self)
1825 {
1826         talloc_free(self->mem_ctx);
1827         Py_DECREF(self->msgs);
1828         Py_DECREF(self->referals);
1829         Py_DECREF(self->controls);
1830         self->ob_type->tp_free(self);
1831 }
1832
1833 static PyObject *py_ldb_result_get_msgs(PyLdbResultObject *self, void *closure)
1834 {
1835         Py_INCREF(self->msgs);
1836         return self->msgs;
1837 }
1838
1839 static PyObject *py_ldb_result_get_controls(PyLdbResultObject *self, void *closure)
1840 {
1841         Py_INCREF(self->controls);
1842         return self->controls;
1843 }
1844
1845 static PyObject *py_ldb_result_get_referals(PyLdbResultObject *self, void *closure)
1846 {
1847         Py_INCREF(self->referals);
1848         return self->referals;
1849 }
1850
1851 static PyObject *py_ldb_result_get_count(PyLdbResultObject *self, void *closure)
1852 {
1853         Py_ssize_t size;
1854         if (self->msgs == NULL) {
1855                 PyErr_SetString(PyExc_AttributeError, "Count attribute is meaningless in this context");
1856                 return NULL;
1857         }
1858         size = PyList_Size(self->msgs);
1859         return PyInt_FromLong(size);
1860 }
1861
1862 static PyGetSetDef py_ldb_result_getset[] = {
1863         { discard_const_p(char, "controls"), (getter)py_ldb_result_get_controls, NULL, NULL },
1864         { discard_const_p(char, "msgs"), (getter)py_ldb_result_get_msgs, NULL, NULL },
1865         { discard_const_p(char, "referals"), (getter)py_ldb_result_get_referals, NULL, NULL },
1866         { discard_const_p(char, "count"), (getter)py_ldb_result_get_count, NULL, NULL },
1867         { NULL }
1868 };
1869
1870 static PyObject *py_ldb_result_iter(PyLdbResultObject *self)
1871 {
1872         return PyObject_GetIter(self->msgs);
1873 }
1874
1875 static Py_ssize_t py_ldb_result_len(PyLdbResultObject *self)
1876 {
1877         return PySequence_Size(self->msgs);
1878 }
1879
1880 static PyObject *py_ldb_result_find(PyLdbResultObject *self, Py_ssize_t idx)
1881 {
1882         return PySequence_GetItem(self->msgs, idx);
1883 }
1884
1885 static PySequenceMethods py_ldb_result_seq = {
1886         .sq_length = (lenfunc)py_ldb_result_len,
1887         .sq_item = (ssizeargfunc)py_ldb_result_find,
1888 };
1889
1890 static PyObject *py_ldb_result_repr(PyLdbObject *self)
1891 {
1892         return PyString_FromFormat("<ldb result>");
1893 }
1894
1895
1896 static PyTypeObject PyLdbResult = {
1897         .tp_name = "ldb.Result",
1898         .tp_repr = (reprfunc)py_ldb_result_repr,
1899         .tp_dealloc = (destructor)py_ldb_result_dealloc,
1900         .tp_iter = (getiterfunc)py_ldb_result_iter,
1901         .tp_getset = py_ldb_result_getset,
1902         .tp_getattro = PyObject_GenericGetAttr,
1903         .tp_basicsize = sizeof(PyLdbResultObject),
1904         .tp_as_sequence = &py_ldb_result_seq,
1905         .tp_doc = "LDB result.",
1906         .tp_flags = Py_TPFLAGS_DEFAULT|Py_TPFLAGS_BASETYPE,
1907 };
1908
1909 static PyObject *py_ldb_module_repr(PyLdbModuleObject *self)
1910 {
1911         return PyString_FromFormat("<ldb module '%s'>", PyLdbModule_AsModule(self)->ops->name);
1912 }
1913
1914 static PyObject *py_ldb_module_str(PyLdbModuleObject *self)
1915 {
1916         return PyString_FromString(PyLdbModule_AsModule(self)->ops->name);
1917 }
1918
1919 static PyObject *py_ldb_module_start_transaction(PyLdbModuleObject *self)
1920 {
1921         PyLdbModule_AsModule(self)->ops->start_transaction(PyLdbModule_AsModule(self));
1922         Py_RETURN_NONE;
1923 }
1924
1925 static PyObject *py_ldb_module_end_transaction(PyLdbModuleObject *self)
1926 {
1927         PyLdbModule_AsModule(self)->ops->end_transaction(PyLdbModule_AsModule(self));
1928         Py_RETURN_NONE;
1929 }
1930
1931 static PyObject *py_ldb_module_del_transaction(PyLdbModuleObject *self)
1932 {
1933         PyLdbModule_AsModule(self)->ops->del_transaction(PyLdbModule_AsModule(self));
1934         Py_RETURN_NONE;
1935 }
1936
1937 static PyObject *py_ldb_module_search(PyLdbModuleObject *self, PyObject *args, PyObject *kwargs)
1938 {
1939         PyObject *py_base, *py_tree, *py_attrs, *py_ret;
1940         int ret, scope;
1941         struct ldb_request *req;
1942         const char * const kwnames[] = { "base", "scope", "tree", "attrs", NULL };
1943         struct ldb_module *mod;
1944         const char * const*attrs;
1945
1946         /* type "int" rather than "enum" for "scope" is intentional */
1947         if (!PyArg_ParseTupleAndKeywords(args, kwargs, "OiOO",
1948                                          discard_const_p(char *, kwnames),
1949                                          &py_base, &scope, &py_tree, &py_attrs))
1950                 return NULL;
1951
1952         mod = self->mod;
1953
1954         if (py_attrs == Py_None) {
1955                 attrs = NULL;
1956         } else {
1957                 attrs = PyList_AsStringList(NULL, py_attrs, "attrs");
1958                 if (attrs == NULL)
1959                         return NULL;
1960         }
1961
1962         ret = ldb_build_search_req(&req, mod->ldb, NULL, PyLdbDn_AsDn(py_base), 
1963                              scope, NULL /* expr */, attrs,
1964                              NULL /* controls */, NULL, NULL, NULL);
1965
1966         talloc_steal(req, attrs);
1967
1968         PyErr_LDB_ERROR_IS_ERR_RAISE(PyExc_LdbError, ret, mod->ldb);
1969
1970         req->op.search.res = NULL;
1971
1972         ret = mod->ops->search(mod, req);
1973
1974         PyErr_LDB_ERROR_IS_ERR_RAISE(PyExc_LdbError, ret, mod->ldb);
1975
1976         py_ret = PyLdbResult_FromResult(req->op.search.res);
1977
1978         talloc_free(req);
1979
1980         return py_ret;  
1981 }
1982
1983
1984 static PyObject *py_ldb_module_add(PyLdbModuleObject *self, PyObject *args)
1985 {
1986         struct ldb_request *req;
1987         PyObject *py_message;
1988         int ret;
1989         struct ldb_module *mod;
1990
1991         if (!PyArg_ParseTuple(args, "O", &py_message))
1992                 return NULL;
1993
1994         req = talloc_zero(NULL, struct ldb_request);
1995         req->operation = LDB_ADD;
1996         req->op.add.message = PyLdbMessage_AsMessage(py_message);
1997
1998         mod = PyLdbModule_AsModule(self);
1999         ret = mod->ops->add(mod, req);
2000
2001         PyErr_LDB_ERROR_IS_ERR_RAISE(PyExc_LdbError, ret, mod->ldb);
2002
2003         Py_RETURN_NONE;
2004 }
2005
2006 static PyObject *py_ldb_module_modify(PyLdbModuleObject *self, PyObject *args) 
2007 {
2008         int ret;
2009         struct ldb_request *req;
2010         PyObject *py_message;
2011         struct ldb_module *mod;
2012
2013         if (!PyArg_ParseTuple(args, "O", &py_message))
2014                 return NULL;
2015
2016         req = talloc_zero(NULL, struct ldb_request);
2017         req->operation = LDB_MODIFY;
2018         req->op.mod.message = PyLdbMessage_AsMessage(py_message);
2019
2020         mod = PyLdbModule_AsModule(self);
2021         ret = mod->ops->modify(mod, req);
2022
2023         PyErr_LDB_ERROR_IS_ERR_RAISE(PyExc_LdbError, ret, mod->ldb);
2024
2025         Py_RETURN_NONE;
2026 }
2027
2028 static PyObject *py_ldb_module_delete(PyLdbModuleObject *self, PyObject *args) 
2029 {
2030         int ret;
2031         struct ldb_request *req;
2032         PyObject *py_dn;
2033
2034         if (!PyArg_ParseTuple(args, "O", &py_dn))
2035                 return NULL;
2036
2037         req = talloc_zero(NULL, struct ldb_request);
2038         req->operation = LDB_DELETE;
2039         req->op.del.dn = PyLdbDn_AsDn(py_dn);
2040
2041         ret = PyLdbModule_AsModule(self)->ops->del(PyLdbModule_AsModule(self), req);
2042
2043         PyErr_LDB_ERROR_IS_ERR_RAISE(PyExc_LdbError, ret, NULL);
2044
2045         Py_RETURN_NONE;
2046 }
2047
2048 static PyObject *py_ldb_module_rename(PyLdbModuleObject *self, PyObject *args)
2049 {
2050         int ret;
2051         struct ldb_request *req;
2052         PyObject *py_dn1, *py_dn2;
2053
2054         if (!PyArg_ParseTuple(args, "OO", &py_dn1, &py_dn2))
2055                 return NULL;
2056
2057         req = talloc_zero(NULL, struct ldb_request);
2058
2059         req->operation = LDB_RENAME;
2060         req->op.rename.olddn = PyLdbDn_AsDn(py_dn1);
2061         req->op.rename.newdn = PyLdbDn_AsDn(py_dn2);
2062
2063         ret = PyLdbModule_AsModule(self)->ops->rename(PyLdbModule_AsModule(self), req);
2064
2065         PyErr_LDB_ERROR_IS_ERR_RAISE(PyExc_LdbError, ret, NULL);
2066
2067         Py_RETURN_NONE;
2068 }
2069
2070 static PyMethodDef py_ldb_module_methods[] = {
2071         { "search", (PyCFunction)py_ldb_module_search, METH_VARARGS|METH_KEYWORDS, NULL },
2072         { "add", (PyCFunction)py_ldb_module_add, METH_VARARGS, NULL },
2073         { "modify", (PyCFunction)py_ldb_module_modify, METH_VARARGS, NULL },
2074         { "rename", (PyCFunction)py_ldb_module_rename, METH_VARARGS, NULL },
2075         { "delete", (PyCFunction)py_ldb_module_delete, METH_VARARGS, NULL },
2076         { "start_transaction", (PyCFunction)py_ldb_module_start_transaction, METH_NOARGS, NULL },
2077         { "end_transaction", (PyCFunction)py_ldb_module_end_transaction, METH_NOARGS, NULL },
2078         { "del_transaction", (PyCFunction)py_ldb_module_del_transaction, METH_NOARGS, NULL },
2079         { NULL },
2080 };
2081
2082 static void py_ldb_module_dealloc(PyLdbModuleObject *self)
2083 {
2084         talloc_free(self->mem_ctx);
2085         PyObject_Del(self);
2086 }
2087
2088 static PyTypeObject PyLdbModule = {
2089         .tp_name = "ldb.LdbModule",
2090         .tp_methods = py_ldb_module_methods,
2091         .tp_repr = (reprfunc)py_ldb_module_repr,
2092         .tp_str = (reprfunc)py_ldb_module_str,
2093         .tp_basicsize = sizeof(PyLdbModuleObject),
2094         .tp_dealloc = (destructor)py_ldb_module_dealloc,
2095         .tp_flags = Py_TPFLAGS_DEFAULT,
2096 };
2097
2098
2099 /**
2100  * Create a ldb_message_element from a Python object.
2101  *
2102  * This will accept any sequence objects that contains strings, or 
2103  * a string object.
2104  *
2105  * A reference to set_obj will be borrowed. 
2106  *
2107  * @param mem_ctx Memory context
2108  * @param set_obj Python object to convert
2109  * @param flags ldb_message_element flags to set
2110  * @param attr_name Name of the attribute
2111  * @return New ldb_message_element, allocated as child of mem_ctx
2112  */
2113 static struct ldb_message_element *PyObject_AsMessageElement(
2114                                                       TALLOC_CTX *mem_ctx,
2115                                                       PyObject *set_obj,
2116                                                       unsigned int flags,
2117                                                       const char *attr_name)
2118 {
2119         struct ldb_message_element *me;
2120
2121         if (PyLdbMessageElement_Check(set_obj)) {
2122                 PyLdbMessageElementObject *set_obj_as_me = (PyLdbMessageElementObject *)set_obj;
2123                 /* We have to talloc_reference() the memory context, not the pointer
2124                  * which may not actually be it's own context */
2125                 if (talloc_reference(mem_ctx, set_obj_as_me->mem_ctx)) {
2126                         return PyLdbMessageElement_AsMessageElement(set_obj);
2127                 }
2128                 return NULL;
2129         }
2130
2131         me = talloc(mem_ctx, struct ldb_message_element);
2132         if (me == NULL) {
2133                 PyErr_NoMemory();
2134                 return NULL;
2135         }
2136
2137         me->name = talloc_strdup(me, attr_name);
2138         me->flags = flags;
2139         if (PyString_Check(set_obj)) {
2140                 me->num_values = 1;
2141                 me->values = talloc_array(me, struct ldb_val, me->num_values);
2142                 me->values[0].length = PyString_Size(set_obj);
2143                 me->values[0].data = talloc_memdup(me, 
2144                         (uint8_t *)PyString_AsString(set_obj), me->values[0].length+1);
2145         } else if (PySequence_Check(set_obj)) {
2146                 Py_ssize_t i;
2147                 me->num_values = PySequence_Size(set_obj);
2148                 me->values = talloc_array(me, struct ldb_val, me->num_values);
2149                 for (i = 0; i < me->num_values; i++) {
2150                         PyObject *obj = PySequence_GetItem(set_obj, i);
2151                         if (!PyString_Check(obj)) {
2152                                 PyErr_Format(PyExc_TypeError,
2153                                              "Expected string as element %zd in list", i);
2154                                 talloc_free(me);
2155                                 return NULL;
2156                         }
2157
2158                         me->values[i].length = PyString_Size(obj);
2159                         me->values[i].data = talloc_memdup(me, 
2160                                 (uint8_t *)PyString_AsString(obj), me->values[i].length+1);
2161                 }
2162         } else {
2163                 talloc_free(me);
2164                 me = NULL;
2165         }
2166
2167         return me;
2168 }
2169
2170
2171 static PyObject *ldb_msg_element_to_set(struct ldb_context *ldb_ctx,
2172                                         struct ldb_message_element *me)
2173 {
2174         Py_ssize_t i;
2175         PyObject *result;
2176
2177         /* Python << 2.5 doesn't have PySet_New and PySet_Add. */
2178         result = PyList_New(me->num_values);
2179
2180         for (i = 0; i < me->num_values; i++) {
2181                 PyList_SetItem(result, i,
2182                         PyObject_FromLdbValue(&me->values[i]));
2183         }
2184
2185         return result;
2186 }
2187
2188 static PyObject *py_ldb_msg_element_get(PyLdbMessageElementObject *self, PyObject *args)
2189 {
2190         unsigned int i;
2191         if (!PyArg_ParseTuple(args, "I", &i))
2192                 return NULL;
2193         if (i >= PyLdbMessageElement_AsMessageElement(self)->num_values)
2194                 Py_RETURN_NONE;
2195
2196         return PyObject_FromLdbValue(&(PyLdbMessageElement_AsMessageElement(self)->values[i]));
2197 }
2198
2199 static PyObject *py_ldb_msg_element_flags(PyLdbMessageElementObject *self, PyObject *args)
2200 {
2201         struct ldb_message_element *el = PyLdbMessageElement_AsMessageElement(self);
2202         return PyInt_FromLong(el->flags);
2203 }
2204
2205 static PyObject *py_ldb_msg_element_set_flags(PyLdbMessageElementObject *self, PyObject *args)
2206 {
2207         unsigned int flags;
2208         struct ldb_message_element *el;
2209         if (!PyArg_ParseTuple(args, "I", &flags))
2210                 return NULL;
2211
2212         el = PyLdbMessageElement_AsMessageElement(self);
2213         el->flags = flags;
2214         Py_RETURN_NONE;
2215 }
2216
2217 static PyMethodDef py_ldb_msg_element_methods[] = {
2218         { "get", (PyCFunction)py_ldb_msg_element_get, METH_VARARGS, NULL },
2219         { "set_flags", (PyCFunction)py_ldb_msg_element_set_flags, METH_VARARGS, NULL },
2220         { "flags", (PyCFunction)py_ldb_msg_element_flags, METH_NOARGS, NULL },
2221         { NULL },
2222 };
2223
2224 static Py_ssize_t py_ldb_msg_element_len(PyLdbMessageElementObject *self)
2225 {
2226         return PyLdbMessageElement_AsMessageElement(self)->num_values;
2227 }
2228
2229 static PyObject *py_ldb_msg_element_find(PyLdbMessageElementObject *self, Py_ssize_t idx)
2230 {
2231         struct ldb_message_element *el = PyLdbMessageElement_AsMessageElement(self);
2232         if (idx < 0 || idx >= el->num_values) {
2233                 PyErr_SetString(PyExc_IndexError, "Out of range");
2234                 return NULL;
2235         }
2236         return PyString_FromStringAndSize((char *)el->values[idx].data, el->values[idx].length);
2237 }
2238
2239 static PySequenceMethods py_ldb_msg_element_seq = {
2240         .sq_length = (lenfunc)py_ldb_msg_element_len,
2241         .sq_item = (ssizeargfunc)py_ldb_msg_element_find,
2242 };
2243
2244 static int py_ldb_msg_element_cmp(PyLdbMessageElementObject *self, PyLdbMessageElementObject *other)
2245 {
2246         int ret = ldb_msg_element_compare(PyLdbMessageElement_AsMessageElement(self),
2247                                                                           PyLdbMessageElement_AsMessageElement(other));
2248         return SIGN(ret);
2249 }
2250
2251 static PyObject *py_ldb_msg_element_iter(PyLdbMessageElementObject *self)
2252 {
2253         return PyObject_GetIter(ldb_msg_element_to_set(NULL, PyLdbMessageElement_AsMessageElement(self)));
2254 }
2255
2256 static PyObject *PyLdbMessageElement_FromMessageElement(struct ldb_message_element *el, TALLOC_CTX *mem_ctx)
2257 {
2258         PyLdbMessageElementObject *ret;
2259         ret = PyObject_New(PyLdbMessageElementObject, &PyLdbMessageElement);
2260         if (ret == NULL) {
2261                 PyErr_NoMemory();
2262                 return NULL;
2263         }
2264         ret->mem_ctx = talloc_new(NULL);
2265         if (talloc_reference(ret->mem_ctx, mem_ctx) == NULL) {
2266                 PyErr_NoMemory();
2267                 return NULL;
2268         }
2269         ret->el = el;
2270         return (PyObject *)ret;
2271 }
2272
2273 static PyObject *py_ldb_msg_element_new(PyTypeObject *type, PyObject *args, PyObject *kwargs)
2274 {
2275         PyObject *py_elements = NULL;
2276         struct ldb_message_element *el;
2277         unsigned int flags = 0;
2278         char *name = NULL;
2279         const char * const kwnames[] = { "elements", "flags", "name", NULL };
2280         PyLdbMessageElementObject *ret;
2281         TALLOC_CTX *mem_ctx;
2282
2283         if (!PyArg_ParseTupleAndKeywords(args, kwargs, "|OIs",
2284                                          discard_const_p(char *, kwnames),
2285                                          &py_elements, &flags, &name))
2286                 return NULL;
2287
2288         mem_ctx = talloc_new(NULL);
2289         if (mem_ctx == NULL) {
2290                 PyErr_NoMemory();
2291                 return NULL;
2292         }
2293
2294         el = talloc_zero(mem_ctx, struct ldb_message_element);
2295         if (el == NULL) {
2296                 PyErr_NoMemory();
2297                 talloc_free(mem_ctx);
2298                 return NULL;
2299         }
2300
2301         if (py_elements != NULL) {
2302                 Py_ssize_t i;
2303                 if (PyString_Check(py_elements)) {
2304                         el->num_values = 1;
2305                         el->values = talloc_array(el, struct ldb_val, 1);
2306                         if (el->values == NULL) {
2307                                 talloc_free(mem_ctx);
2308                                 PyErr_NoMemory();
2309                                 return NULL;
2310                         }
2311                         el->values[0].length = PyString_Size(py_elements);
2312                         el->values[0].data = talloc_memdup(el->values, 
2313                                 (uint8_t *)PyString_AsString(py_elements), el->values[0].length+1);
2314                 } else if (PySequence_Check(py_elements)) {
2315                         el->num_values = PySequence_Size(py_elements);
2316                         el->values = talloc_array(el, struct ldb_val, el->num_values);
2317                         if (el->values == NULL) {
2318                                 talloc_free(mem_ctx);
2319                                 PyErr_NoMemory();
2320                                 return NULL;
2321                         }
2322                         for (i = 0; i < el->num_values; i++) {
2323                                 PyObject *item = PySequence_GetItem(py_elements, i);
2324                                 if (item == NULL) {
2325                                         talloc_free(mem_ctx);
2326                                         return NULL;
2327                                 }
2328                                 if (!PyString_Check(item)) {
2329                                         PyErr_Format(PyExc_TypeError, 
2330                                                      "Expected string as element %zd in list", i);
2331                                         talloc_free(mem_ctx);
2332                                         return NULL;
2333                                 }
2334                                 el->values[i].length = PyString_Size(item);
2335                                 el->values[i].data = talloc_memdup(el,
2336                                         (uint8_t *)PyString_AsString(item), el->values[i].length+1);
2337                         }
2338                 } else {
2339                         PyErr_SetString(PyExc_TypeError, 
2340                                         "Expected string or list");
2341                         talloc_free(mem_ctx);
2342                         return NULL;
2343                 }
2344         }
2345
2346         el->flags = flags;
2347         el->name = talloc_strdup(el, name);
2348
2349         ret = PyObject_New(PyLdbMessageElementObject, type);
2350         if (ret == NULL) {
2351                 talloc_free(mem_ctx);
2352                 return NULL;
2353         }
2354
2355         ret->mem_ctx = mem_ctx;
2356         ret->el = el;
2357         return (PyObject *)ret;
2358 }
2359
2360 static PyObject *py_ldb_msg_element_repr(PyLdbMessageElementObject *self)
2361 {
2362         char *element_str = NULL;
2363         Py_ssize_t i;
2364         struct ldb_message_element *el = PyLdbMessageElement_AsMessageElement(self);
2365         PyObject *ret;
2366
2367         for (i = 0; i < el->num_values; i++) {
2368                 PyObject *o = py_ldb_msg_element_find(self, i);
2369                 if (element_str == NULL)
2370                         element_str = talloc_strdup(NULL, PyObject_REPR(o));
2371                 else
2372                         element_str = talloc_asprintf_append(element_str, ",%s", PyObject_REPR(o));
2373         }
2374
2375         if (element_str != NULL) {
2376                 ret = PyString_FromFormat("MessageElement([%s])", element_str);
2377                 talloc_free(element_str);
2378         } else {
2379                 ret = PyString_FromString("MessageElement([])");
2380         }
2381
2382         return ret;
2383 }
2384
2385 static PyObject *py_ldb_msg_element_str(PyLdbMessageElementObject *self)
2386 {
2387         struct ldb_message_element *el = PyLdbMessageElement_AsMessageElement(self);
2388
2389         if (el->num_values == 1)
2390                 return PyString_FromStringAndSize((char *)el->values[0].data, el->values[0].length);
2391         else
2392                 Py_RETURN_NONE;
2393 }
2394
2395 static void py_ldb_msg_element_dealloc(PyLdbMessageElementObject *self)
2396 {
2397         talloc_free(self->mem_ctx);
2398         PyObject_Del(self);
2399 }
2400
2401 static PyTypeObject PyLdbMessageElement = {
2402         .tp_name = "ldb.MessageElement",
2403         .tp_basicsize = sizeof(PyLdbMessageElementObject),
2404         .tp_dealloc = (destructor)py_ldb_msg_element_dealloc,
2405         .tp_repr = (reprfunc)py_ldb_msg_element_repr,
2406         .tp_str = (reprfunc)py_ldb_msg_element_str,
2407         .tp_methods = py_ldb_msg_element_methods,
2408         .tp_compare = (cmpfunc)py_ldb_msg_element_cmp,
2409         .tp_iter = (getiterfunc)py_ldb_msg_element_iter,
2410         .tp_as_sequence = &py_ldb_msg_element_seq,
2411         .tp_new = py_ldb_msg_element_new,
2412         .tp_flags = Py_TPFLAGS_DEFAULT,
2413 };
2414
2415
2416 static PyObject *py_ldb_msg_from_dict(PyTypeObject *type, PyObject *args)
2417 {
2418         PyObject *py_ldb;
2419         PyObject *py_dict;
2420         PyObject *py_ret;
2421         struct ldb_message *msg;
2422         struct ldb_context *ldb_ctx;
2423         unsigned int mod_flags = LDB_FLAG_MOD_REPLACE;
2424
2425         if (!PyArg_ParseTuple(args, "O!O!|I",
2426                               &PyLdb, &py_ldb, &PyDict_Type, &py_dict,
2427                               &mod_flags)) {
2428                 return NULL;
2429         }
2430
2431         /* mask only flags we are going to use */
2432         mod_flags = LDB_FLAG_MOD_TYPE(mod_flags);
2433         if (!mod_flags) {
2434                 PyErr_SetString(PyExc_ValueError,
2435                                 "FLAG_MOD_ADD, FLAG_MOD_REPLACE or FLAG_MOD_DELETE"
2436                                 " expected as mod_flag value");
2437                 return NULL;
2438         }
2439
2440         ldb_ctx = PyLdb_AsLdbContext(py_ldb);
2441
2442         msg = PyDict_AsMessage(ldb_ctx, py_dict, ldb_ctx, mod_flags);
2443         if (!msg) {
2444                 return NULL;
2445         }
2446
2447         py_ret = PyLdbMessage_FromMessage(msg);
2448
2449         talloc_unlink(ldb_ctx, msg);
2450
2451         return py_ret;
2452 }
2453
2454 static PyObject *py_ldb_msg_remove_attr(PyLdbMessageObject *self, PyObject *args)
2455 {
2456         char *name;
2457         if (!PyArg_ParseTuple(args, "s", &name))
2458                 return NULL;
2459
2460         ldb_msg_remove_attr(self->msg, name);
2461
2462         Py_RETURN_NONE;
2463 }
2464
2465 static PyObject *py_ldb_msg_keys(PyLdbMessageObject *self)
2466 {
2467         struct ldb_message *msg = PyLdbMessage_AsMessage(self);
2468         Py_ssize_t i, j = 0;
2469         PyObject *obj = PyList_New(msg->num_elements+(msg->dn != NULL?1:0));
2470         if (msg->dn != NULL) {
2471                 PyList_SetItem(obj, j, PyString_FromString("dn"));
2472                 j++;
2473         }
2474         for (i = 0; i < msg->num_elements; i++) {
2475                 PyList_SetItem(obj, j, PyString_FromString(msg->elements[i].name));
2476                 j++;
2477         }
2478         return obj;
2479 }
2480
2481 static PyObject *py_ldb_msg_getitem_helper(PyLdbMessageObject *self, PyObject *py_name)
2482 {
2483         struct ldb_message_element *el;
2484         char *name;
2485         struct ldb_message *msg = PyLdbMessage_AsMessage(self);
2486         if (!PyString_Check(py_name)) {
2487                 PyErr_SetNone(PyExc_TypeError);
2488                 return NULL;
2489         }
2490         name = PyString_AsString(py_name);
2491         if (!strcmp(name, "dn"))
2492                 return PyLdbDn_FromDn(msg->dn);
2493         el = ldb_msg_find_element(msg, name);
2494         if (el == NULL) {
2495                 return NULL;
2496         }
2497         return (PyObject *)PyLdbMessageElement_FromMessageElement(el, msg->elements);
2498 }
2499
2500 static PyObject *py_ldb_msg_getitem(PyLdbMessageObject *self, PyObject *py_name)
2501 {
2502         PyObject *ret = py_ldb_msg_getitem_helper(self, py_name);
2503         if (ret == NULL) {
2504                 PyErr_SetString(PyExc_KeyError, "No such element");
2505                 return NULL;
2506         }
2507         return ret;
2508 }
2509
2510 static PyObject *py_ldb_msg_get(PyLdbMessageObject *self, PyObject *args)
2511 {
2512         PyObject *name, *ret, *retobj;
2513         retobj = NULL;
2514         if (!PyArg_ParseTuple(args, "O|O", &name, &retobj))
2515                 return NULL;
2516
2517         ret = py_ldb_msg_getitem_helper(self, name);
2518         if (ret == NULL) {
2519                 if (PyErr_Occurred())
2520                         return NULL;
2521                 if (retobj != NULL) {
2522                         return retobj;
2523                 } else {
2524                         Py_RETURN_NONE;
2525                 }
2526         }
2527         return ret;
2528 }
2529
2530 static PyObject *py_ldb_msg_items(PyLdbMessageObject *self)
2531 {
2532         struct ldb_message *msg = PyLdbMessage_AsMessage(self);
2533         Py_ssize_t i, j = 0;
2534         PyObject *l = PyList_New(msg->num_elements + (msg->dn == NULL?0:1));
2535         if (msg->dn != NULL) {
2536                 PyList_SetItem(l, 0, Py_BuildValue("(sO)", "dn", PyLdbDn_FromDn(msg->dn)));
2537                 j++;
2538         }
2539         for (i = 0; i < msg->num_elements; i++, j++) {
2540                 PyObject *py_el = PyLdbMessageElement_FromMessageElement(&msg->elements[i], msg->elements);
2541                 PyObject *value = Py_BuildValue("(sO)", msg->elements[i].name, py_el);
2542                 PyList_SetItem(l, j, value);
2543         }
2544         return l;
2545 }
2546
2547 static PyObject *py_ldb_msg_elements(PyLdbMessageObject *self)
2548 {
2549         struct ldb_message *msg = PyLdbMessage_AsMessage(self);
2550         Py_ssize_t i = 0;
2551         PyObject *l = PyList_New(msg->num_elements);
2552         for (i = 0; i < msg->num_elements; i++) {
2553                 PyList_SetItem(l, i, PyLdbMessageElement_FromMessageElement(&msg->elements[i], msg->elements));
2554         }
2555         return l;
2556 }
2557
2558 static PyObject *py_ldb_msg_add(PyLdbMessageObject *self, PyObject *args)
2559 {
2560         struct ldb_message *msg = PyLdbMessage_AsMessage(self);
2561         PyLdbMessageElementObject *py_element;
2562         int ret;
2563         struct ldb_message_element *el;
2564
2565         if (!PyArg_ParseTuple(args, "O!", &PyLdbMessageElement, &py_element))
2566                 return NULL;
2567
2568         el = talloc_reference(msg, py_element->el);
2569         if (el == NULL) {
2570                 PyErr_NoMemory();
2571                 return NULL;
2572         }
2573
2574         ret = ldb_msg_add(msg, el, el->flags);
2575         PyErr_LDB_ERROR_IS_ERR_RAISE(PyExc_LdbError, ret, NULL);
2576
2577         Py_RETURN_NONE;
2578 }
2579
2580 static PyMethodDef py_ldb_msg_methods[] = {
2581         { "from_dict", (PyCFunction)py_ldb_msg_from_dict, METH_CLASS | METH_VARARGS,
2582                 "Message.from_dict(ldb, dict, mod_flag=FLAG_MOD_REPLACE) -> ldb.Message\n"
2583                 "Class method to create ldb.Message object from Dictionary.\n"
2584                 "mod_flag is one of FLAG_MOD_ADD, FLAG_MOD_REPLACE or FLAG_MOD_DELETE."},
2585         { "keys", (PyCFunction)py_ldb_msg_keys, METH_NOARGS, 
2586                 "S.keys() -> list\n\n"
2587                 "Return sequence of all attribute names." },
2588         { "remove", (PyCFunction)py_ldb_msg_remove_attr, METH_VARARGS, 
2589                 "S.remove(name)\n\n"
2590                 "Remove all entries for attributes with the specified name."},
2591         { "get", (PyCFunction)py_ldb_msg_get, METH_VARARGS, NULL },
2592         { "items", (PyCFunction)py_ldb_msg_items, METH_NOARGS, NULL },
2593         { "elements", (PyCFunction)py_ldb_msg_elements, METH_NOARGS, NULL },
2594         { "add", (PyCFunction)py_ldb_msg_add, METH_VARARGS,
2595                 "S.append(element)\n\n"
2596                 "Add an element to this message." },
2597         { NULL },
2598 };
2599
2600 static PyObject *py_ldb_msg_iter(PyLdbMessageObject *self)
2601 {
2602         PyObject *list, *iter;
2603
2604         list = py_ldb_msg_keys(self);
2605         iter = PyObject_GetIter(list);
2606         Py_DECREF(list);
2607         return iter;
2608 }
2609
2610 static int py_ldb_msg_setitem(PyLdbMessageObject *self, PyObject *name, PyObject *value)
2611 {
2612         char *attr_name;
2613
2614         if (!PyString_Check(name)) {
2615                 PyErr_SetNone(PyExc_TypeError);
2616                 return -1;
2617         }
2618
2619         attr_name = PyString_AsString(name);
2620         if (value == NULL) {
2621                 /* delitem */
2622                 ldb_msg_remove_attr(self->msg, attr_name);
2623         } else {
2624                 struct ldb_message_element *el = PyObject_AsMessageElement(self->msg,
2625                                                                            value, 0, attr_name);
2626                 if (el == NULL)
2627                         return -1;
2628                 ldb_msg_remove_attr(PyLdbMessage_AsMessage(self), attr_name);
2629                 ldb_msg_add(PyLdbMessage_AsMessage(self), el, el->flags);
2630         }
2631         return 0;
2632 }
2633
2634 static Py_ssize_t py_ldb_msg_length(PyLdbMessageObject *self)
2635 {
2636         return PyLdbMessage_AsMessage(self)->num_elements;
2637 }
2638
2639 static PyMappingMethods py_ldb_msg_mapping = {
2640         .mp_length = (lenfunc)py_ldb_msg_length,
2641         .mp_subscript = (binaryfunc)py_ldb_msg_getitem,
2642         .mp_ass_subscript = (objobjargproc)py_ldb_msg_setitem,
2643 };
2644
2645 static PyObject *py_ldb_msg_new(PyTypeObject *type, PyObject *args, PyObject *kwargs)
2646 {
2647         const char * const kwnames[] = { "dn", NULL };
2648         struct ldb_message *ret;
2649         TALLOC_CTX *mem_ctx;
2650         PyObject *pydn = NULL;
2651         PyLdbMessageObject *py_ret;
2652
2653         if (!PyArg_ParseTupleAndKeywords(args, kwargs, "|O",
2654                                          discard_const_p(char *, kwnames),
2655                                          &pydn))
2656                 return NULL;
2657
2658         mem_ctx = talloc_new(NULL);
2659         if (mem_ctx == NULL) {
2660                 PyErr_NoMemory();
2661                 return NULL;
2662         }
2663
2664         ret = ldb_msg_new(mem_ctx);
2665         if (ret == NULL) {
2666                 talloc_free(mem_ctx);
2667                 PyErr_NoMemory();
2668                 return NULL;
2669         }
2670
2671         if (pydn != NULL) {
2672                 struct ldb_dn *dn;
2673                 if (!PyObject_AsDn(NULL, pydn, NULL, &dn)) {
2674                         talloc_free(mem_ctx);
2675                         return NULL;
2676                 }
2677                 ret->dn = talloc_reference(ret, dn);
2678         }
2679
2680         py_ret = (PyLdbMessageObject *)type->tp_alloc(type, 0);
2681         if (py_ret == NULL) {
2682                 PyErr_NoMemory();
2683                 talloc_free(mem_ctx);
2684                 return NULL;
2685         }
2686
2687         py_ret->mem_ctx = mem_ctx;
2688         py_ret->msg = ret;
2689         return (PyObject *)py_ret;
2690 }
2691
2692 static PyObject *PyLdbMessage_FromMessage(struct ldb_message *msg)
2693 {
2694         PyLdbMessageObject *ret;
2695
2696         ret = (PyLdbMessageObject *)PyLdbMessage.tp_alloc(&PyLdbMessage, 0);
2697         if (ret == NULL) {
2698                 PyErr_NoMemory();
2699                 return NULL;
2700         }
2701         ret->mem_ctx = talloc_new(NULL);
2702         ret->msg = talloc_reference(ret->mem_ctx, msg);
2703         return (PyObject *)ret;
2704 }
2705
2706 static PyObject *py_ldb_msg_get_dn(PyLdbMessageObject *self, void *closure)
2707 {
2708         struct ldb_message *msg = PyLdbMessage_AsMessage(self);
2709         return PyLdbDn_FromDn(msg->dn);
2710 }
2711
2712 static int py_ldb_msg_set_dn(PyLdbMessageObject *self, PyObject *value, void *closure)
2713 {
2714         struct ldb_message *msg = PyLdbMessage_AsMessage(self);
2715         if (!PyLdbDn_Check(value)) {
2716                 PyErr_SetNone(PyExc_TypeError);
2717                 return -1;
2718         }
2719
2720         msg->dn = talloc_reference(msg, PyLdbDn_AsDn(value));
2721         return 0;
2722 }
2723
2724 static PyGetSetDef py_ldb_msg_getset[] = {
2725         { discard_const_p(char, "dn"), (getter)py_ldb_msg_get_dn, (setter)py_ldb_msg_set_dn, NULL },
2726         { NULL }
2727 };
2728
2729 static PyObject *py_ldb_msg_repr(PyLdbMessageObject *self)
2730 {
2731         PyObject *dict = PyDict_New(), *ret;
2732         if (PyDict_Update(dict, (PyObject *)self) != 0)
2733                 return NULL;
2734         ret = PyString_FromFormat("Message(%s)", PyObject_REPR(dict));
2735         Py_DECREF(dict);
2736         return ret;
2737 }
2738
2739 static void py_ldb_msg_dealloc(PyLdbMessageObject *self)
2740 {
2741         talloc_free(self->mem_ctx);
2742         PyObject_Del(self);
2743 }
2744
2745 static int py_ldb_msg_compare(PyLdbMessageObject *py_msg1,
2746                               PyLdbMessageObject *py_msg2)
2747 {
2748         struct ldb_message *msg1 = PyLdbMessage_AsMessage(py_msg1),
2749                            *msg2 = PyLdbMessage_AsMessage(py_msg2);
2750         unsigned int i;
2751         int ret;
2752
2753         if ((msg1->dn != NULL) || (msg2->dn != NULL)) {
2754                 ret = ldb_dn_compare(msg1->dn, msg2->dn);
2755                 if (ret != 0) {
2756                         return SIGN(ret);
2757                 }
2758         }
2759
2760         ret = msg1->num_elements - msg2->num_elements;
2761         if (ret != 0) {
2762                 return SIGN(ret);
2763         }
2764
2765         for (i = 0; i < msg1->num_elements; i++) {
2766                 ret = ldb_msg_element_compare_name(&msg1->elements[i],
2767                                                    &msg2->elements[i]);
2768                 if (ret != 0) {
2769                         return SIGN(ret);
2770                 }
2771
2772                 ret = ldb_msg_element_compare(&msg1->elements[i],
2773                                               &msg2->elements[i]);
2774                 if (ret != 0) {
2775                         return SIGN(ret);
2776                 }
2777         }
2778
2779         return 0;
2780 }
2781
2782 static PyTypeObject PyLdbMessage = {
2783         .tp_name = "ldb.Message",
2784         .tp_methods = py_ldb_msg_methods,
2785         .tp_getset = py_ldb_msg_getset,
2786         .tp_as_mapping = &py_ldb_msg_mapping,
2787         .tp_basicsize = sizeof(PyLdbMessageObject),
2788         .tp_dealloc = (destructor)py_ldb_msg_dealloc,
2789         .tp_new = py_ldb_msg_new,
2790         .tp_repr = (reprfunc)py_ldb_msg_repr,
2791         .tp_flags = Py_TPFLAGS_DEFAULT,
2792         .tp_iter = (getiterfunc)py_ldb_msg_iter,
2793         .tp_compare = (cmpfunc)py_ldb_msg_compare,
2794 };
2795
2796 static PyObject *PyLdbTree_FromTree(struct ldb_parse_tree *tree)
2797 {
2798         PyLdbTreeObject *ret;
2799
2800         ret = (PyLdbTreeObject *)PyLdbTree.tp_alloc(&PyLdbTree, 0);
2801         if (ret == NULL) {
2802                 PyErr_NoMemory();
2803                 return NULL;
2804         }
2805
2806         ret->mem_ctx = talloc_new(NULL);
2807         ret->tree = talloc_reference(ret->mem_ctx, tree);
2808         return (PyObject *)ret;
2809 }
2810
2811 static void py_ldb_tree_dealloc(PyLdbTreeObject *self)
2812 {
2813         talloc_free(self->mem_ctx);
2814         PyObject_Del(self);
2815 }
2816
2817 static PyTypeObject PyLdbTree = {
2818         .tp_name = "ldb.Tree",
2819         .tp_basicsize = sizeof(PyLdbTreeObject),
2820         .tp_dealloc = (destructor)py_ldb_tree_dealloc,
2821         .tp_flags = Py_TPFLAGS_DEFAULT,
2822 };
2823
2824 /* Ldb_module */
2825 static int py_module_search(struct ldb_module *mod, struct ldb_request *req)
2826 {
2827         PyObject *py_ldb = (PyObject *)mod->private_data;
2828         PyObject *py_result, *py_base, *py_attrs, *py_tree;
2829
2830         py_base = PyLdbDn_FromDn(req->op.search.base);
2831
2832         if (py_base == NULL)
2833                 return LDB_ERR_OPERATIONS_ERROR;
2834
2835         py_tree = PyLdbTree_FromTree(req->op.search.tree);
2836
2837         if (py_tree == NULL)
2838                 return LDB_ERR_OPERATIONS_ERROR;
2839
2840         if (req->op.search.attrs == NULL) {
2841                 py_attrs = Py_None;
2842         } else {
2843                 int i, len;
2844                 for (len = 0; req->op.search.attrs[len]; len++);
2845                 py_attrs = PyList_New(len);
2846                 for (i = 0; i < len; i++)
2847                         PyList_SetItem(py_attrs, i, PyString_FromString(req->op.search.attrs[i]));
2848         }
2849
2850         py_result = PyObject_CallMethod(py_ldb, discard_const_p(char, "search"),
2851                                         discard_const_p(char, "OiOO"),
2852                                         py_base, req->op.search.scope, py_tree, py_attrs);
2853
2854         Py_DECREF(py_attrs);
2855         Py_DECREF(py_tree);
2856         Py_DECREF(py_base);
2857
2858         if (py_result == NULL) {
2859                 return LDB_ERR_PYTHON_EXCEPTION;
2860         }
2861
2862         req->op.search.res = PyLdbResult_AsResult(NULL, py_result);
2863         if (req->op.search.res == NULL) {
2864                 return LDB_ERR_PYTHON_EXCEPTION;
2865         }
2866
2867         Py_DECREF(py_result);
2868
2869         return LDB_SUCCESS;
2870 }
2871
2872 static int py_module_add(struct ldb_module *mod, struct ldb_request *req)
2873 {
2874         PyObject *py_ldb = (PyObject *)mod->private_data;
2875         PyObject *py_result, *py_msg;
2876
2877         py_msg = PyLdbMessage_FromMessage(discard_const_p(struct ldb_message, req->op.add.message));
2878
2879         if (py_msg == NULL) {
2880                 return LDB_ERR_OPERATIONS_ERROR;
2881         }
2882
2883         py_result = PyObject_CallMethod(py_ldb, discard_const_p(char, "add"),
2884                                         discard_const_p(char, "O"),
2885                                         py_msg);
2886
2887         Py_DECREF(py_msg);
2888
2889         if (py_result == NULL) {
2890                 return LDB_ERR_PYTHON_EXCEPTION;
2891         }
2892
2893         Py_DECREF(py_result);
2894
2895         return LDB_SUCCESS;
2896 }
2897
2898 static int py_module_modify(struct ldb_module *mod, struct ldb_request *req)
2899 {
2900         PyObject *py_ldb = (PyObject *)mod->private_data;
2901         PyObject *py_result, *py_msg;
2902
2903         py_msg = PyLdbMessage_FromMessage(discard_const_p(struct ldb_message, req->op.mod.message));
2904
2905         if (py_msg == NULL) {
2906                 return LDB_ERR_OPERATIONS_ERROR;
2907         }
2908
2909         py_result = PyObject_CallMethod(py_ldb, discard_const_p(char, "modify"),
2910                                         discard_const_p(char, "O"),
2911                                         py_msg);
2912
2913         Py_DECREF(py_msg);
2914
2915         if (py_result == NULL) {
2916                 return LDB_ERR_PYTHON_EXCEPTION;
2917         }
2918
2919         Py_DECREF(py_result);
2920
2921         return LDB_SUCCESS;
2922 }
2923
2924 static int py_module_del(struct ldb_module *mod, struct ldb_request *req)
2925 {
2926         PyObject *py_ldb = (PyObject *)mod->private_data;
2927         PyObject *py_result, *py_dn;
2928
2929         py_dn = PyLdbDn_FromDn(req->op.del.dn);
2930
2931         if (py_dn == NULL)
2932                 return LDB_ERR_OPERATIONS_ERROR;
2933
2934         py_result = PyObject_CallMethod(py_ldb, discard_const_p(char, "delete"),
2935                                         discard_const_p(char, "O"),
2936                                         py_dn);
2937
2938         if (py_result == NULL) {
2939                 return LDB_ERR_PYTHON_EXCEPTION;
2940         }
2941
2942         Py_DECREF(py_result);
2943
2944         return LDB_SUCCESS;
2945 }
2946
2947 static int py_module_rename(struct ldb_module *mod, struct ldb_request *req)
2948 {
2949         PyObject *py_ldb = (PyObject *)mod->private_data;
2950         PyObject *py_result, *py_olddn, *py_newdn;
2951
2952         py_olddn = PyLdbDn_FromDn(req->op.rename.olddn);
2953
2954         if (py_olddn == NULL)
2955                 return LDB_ERR_OPERATIONS_ERROR;
2956
2957         py_newdn = PyLdbDn_FromDn(req->op.rename.newdn);
2958
2959         if (py_newdn == NULL)
2960                 return LDB_ERR_OPERATIONS_ERROR;
2961
2962         py_result = PyObject_CallMethod(py_ldb, discard_const_p(char, "rename"),
2963                                         discard_const_p(char, "OO"),
2964                                         py_olddn, py_newdn);
2965
2966         Py_DECREF(py_olddn);
2967         Py_DECREF(py_newdn);
2968
2969         if (py_result == NULL) {
2970                 return LDB_ERR_PYTHON_EXCEPTION;
2971         }
2972
2973         Py_DECREF(py_result);
2974
2975         return LDB_SUCCESS;
2976 }
2977
2978 static int py_module_request(struct ldb_module *mod, struct ldb_request *req)
2979 {
2980         PyObject *py_ldb = (PyObject *)mod->private_data;
2981         PyObject *py_result;
2982
2983         py_result = PyObject_CallMethod(py_ldb, discard_const_p(char, "request"),
2984                                         discard_const_p(char, ""));
2985
2986         return LDB_ERR_OPERATIONS_ERROR;
2987 }
2988
2989 static int py_module_extended(struct ldb_module *mod, struct ldb_request *req)
2990 {
2991         PyObject *py_ldb = (PyObject *)mod->private_data;
2992         PyObject *py_result;
2993
2994         py_result = PyObject_CallMethod(py_ldb, discard_const_p(char, "extended"),
2995                                         discard_const_p(char, ""));
2996
2997         return LDB_ERR_OPERATIONS_ERROR;
2998 }
2999
3000 static int py_module_start_transaction(struct ldb_module *mod)
3001 {
3002         PyObject *py_ldb = (PyObject *)mod->private_data;
3003         PyObject *py_result;
3004
3005         py_result = PyObject_CallMethod(py_ldb, discard_const_p(char, "start_transaction"),
3006                                         discard_const_p(char, ""));
3007
3008         if (py_result == NULL) {
3009                 return LDB_ERR_PYTHON_EXCEPTION;
3010         }
3011
3012         Py_DECREF(py_result);
3013
3014         return LDB_SUCCESS;
3015 }
3016
3017 static int py_module_end_transaction(struct ldb_module *mod)
3018 {
3019         PyObject *py_ldb = (PyObject *)mod->private_data;
3020         PyObject *py_result;
3021
3022         py_result = PyObject_CallMethod(py_ldb, discard_const_p(char, "end_transaction"),
3023                                         discard_const_p(char, ""));
3024
3025         if (py_result == NULL) {
3026                 return LDB_ERR_PYTHON_EXCEPTION;
3027         }
3028
3029         Py_DECREF(py_result);
3030
3031         return LDB_SUCCESS;
3032 }
3033
3034 static int py_module_del_transaction(struct ldb_module *mod)
3035 {
3036         PyObject *py_ldb = (PyObject *)mod->private_data;
3037         PyObject *py_result;
3038
3039         py_result = PyObject_CallMethod(py_ldb, discard_const_p(char, "del_transaction"),
3040                                         discard_const_p(char, ""));
3041
3042         if (py_result == NULL) {
3043                 return LDB_ERR_PYTHON_EXCEPTION;
3044         }
3045
3046         Py_DECREF(py_result);
3047
3048         return LDB_SUCCESS;
3049 }
3050
3051 static int py_module_destructor(struct ldb_module *mod)
3052 {
3053         Py_DECREF((PyObject *)mod->private_data);
3054         return 0;
3055 }
3056
3057 static int py_module_init(struct ldb_module *mod)
3058 {
3059         PyObject *py_class = (PyObject *)mod->ops->private_data;
3060         PyObject *py_result, *py_next, *py_ldb;
3061
3062         py_ldb = PyLdb_FromLdbContext(mod->ldb);
3063
3064         if (py_ldb == NULL)
3065                 return LDB_ERR_OPERATIONS_ERROR;
3066
3067         py_next = PyLdbModule_FromModule(mod->next);
3068
3069         if (py_next == NULL)
3070                 return LDB_ERR_OPERATIONS_ERROR;
3071
3072         py_result = PyObject_CallFunction(py_class, discard_const_p(char, "OO"),
3073                                           py_ldb, py_next);
3074
3075         if (py_result == NULL) {
3076                 return LDB_ERR_PYTHON_EXCEPTION;
3077         }
3078
3079         mod->private_data = py_result;
3080
3081         talloc_set_destructor(mod, py_module_destructor);
3082
3083         return ldb_next_init(mod);
3084 }
3085
3086 static PyObject *py_register_module(PyObject *module, PyObject *args)
3087 {
3088         int ret;
3089         struct ldb_module_ops *ops;
3090         PyObject *input;
3091
3092         if (!PyArg_ParseTuple(args, "O", &input))
3093                 return NULL;
3094
3095         ops = talloc_zero(talloc_autofree_context(), struct ldb_module_ops);
3096         if (ops == NULL) {
3097                 PyErr_NoMemory();
3098                 return NULL;
3099         }
3100
3101         ops->name = talloc_strdup(ops, PyString_AsString(PyObject_GetAttrString(input, discard_const_p(char, "name"))));
3102
3103         Py_INCREF(input);
3104         ops->private_data = input;
3105         ops->init_context = py_module_init;
3106         ops->search = py_module_search;
3107         ops->add = py_module_add;
3108         ops->modify = py_module_modify;
3109         ops->del = py_module_del;
3110         ops->rename = py_module_rename;
3111         ops->request = py_module_request;
3112         ops->extended = py_module_extended;
3113         ops->start_transaction = py_module_start_transaction;
3114         ops->end_transaction = py_module_end_transaction;
3115         ops->del_transaction = py_module_del_transaction;
3116
3117         ret = ldb_register_module(ops);
3118
3119         PyErr_LDB_ERROR_IS_ERR_RAISE(PyExc_LdbError, ret, NULL);
3120
3121         Py_RETURN_NONE;
3122 }
3123
3124 static PyObject *py_timestring(PyObject *module, PyObject *args)
3125 {
3126         /* most times "time_t" is a signed integer type with 32 or 64 bit:
3127          * http://stackoverflow.com/questions/471248/what-is-ultimately-a-time-t-typedef-to */
3128         long int t_val;
3129         char *tresult;
3130         PyObject *ret;
3131         if (!PyArg_ParseTuple(args, "l", &t_val))
3132                 return NULL;
3133         tresult = ldb_timestring(NULL, (time_t) t_val);
3134         ret = PyString_FromString(tresult);
3135         talloc_free(tresult);
3136         return ret;
3137 }
3138
3139 static PyObject *py_string_to_time(PyObject *module, PyObject *args)
3140 {
3141         char *str;
3142         if (!PyArg_ParseTuple(args, "s", &str))
3143                 return NULL;
3144
3145         return PyInt_FromLong(ldb_string_to_time(str));
3146 }
3147
3148 static PyObject *py_valid_attr_name(PyObject *self, PyObject *args)
3149 {
3150         char *name;
3151         if (!PyArg_ParseTuple(args, "s", &name))
3152                 return NULL;
3153         return PyBool_FromLong(ldb_valid_attr_name(name));
3154 }
3155
3156 static PyMethodDef py_ldb_global_methods[] = {
3157         { "register_module", py_register_module, METH_VARARGS, 
3158                 "S.register_module(module) -> None\n"
3159                 "Register a LDB module."},
3160         { "timestring", py_timestring, METH_VARARGS, 
3161                 "S.timestring(int) -> string\n"
3162                 "Generate a LDAP time string from a UNIX timestamp" },
3163         { "string_to_time", py_string_to_time, METH_VARARGS,
3164                 "S.string_to_time(string) -> int\n"
3165                 "Parse a LDAP time string into a UNIX timestamp." },
3166         { "valid_attr_name", py_valid_attr_name, METH_VARARGS,
3167                 "S.valid_attr_name(name) -> bool\n"
3168                 "Check whether the supplied name is a valid attribute name." },
3169         { "open", (PyCFunction)py_ldb_new, METH_VARARGS|METH_KEYWORDS,
3170                 NULL },
3171         { NULL }
3172 };
3173
3174 void initldb(void)
3175 {
3176         PyObject *m;
3177
3178         if (PyType_Ready(&PyLdbDn) < 0)
3179                 return;
3180
3181         if (PyType_Ready(&PyLdbMessage) < 0)
3182                 return;
3183
3184         if (PyType_Ready(&PyLdbMessageElement) < 0)
3185                 return;
3186
3187         if (PyType_Ready(&PyLdb) < 0)
3188                 return;
3189
3190         if (PyType_Ready(&PyLdbModule) < 0)
3191                 return;
3192
3193         if (PyType_Ready(&PyLdbTree) < 0)
3194                 return;
3195
3196         if (PyType_Ready(&PyLdbResult) < 0)
3197                 return;
3198
3199         if (PyType_Ready(&PyLdbControl) < 0)
3200                 return;
3201
3202         m = Py_InitModule3("ldb", py_ldb_global_methods, 
3203                 "An interface to LDB, a LDAP-like API that can either to talk an embedded database (TDB-based) or a standards-compliant LDAP server.");
3204         if (m == NULL)
3205                 return;
3206
3207         PyModule_AddObject(m, "SEQ_HIGHEST_SEQ", PyInt_FromLong(LDB_SEQ_HIGHEST_SEQ));
3208         PyModule_AddObject(m, "SEQ_HIGHEST_TIMESTAMP", PyInt_FromLong(LDB_SEQ_HIGHEST_TIMESTAMP));
3209         PyModule_AddObject(m, "SEQ_NEXT", PyInt_FromLong(LDB_SEQ_NEXT));
3210         PyModule_AddObject(m, "SCOPE_DEFAULT", PyInt_FromLong(LDB_SCOPE_DEFAULT));
3211         PyModule_AddObject(m, "SCOPE_BASE", PyInt_FromLong(LDB_SCOPE_BASE));
3212         PyModule_AddObject(m, "SCOPE_ONELEVEL", PyInt_FromLong(LDB_SCOPE_ONELEVEL));
3213         PyModule_AddObject(m, "SCOPE_SUBTREE", PyInt_FromLong(LDB_SCOPE_SUBTREE));
3214
3215         PyModule_AddObject(m, "CHANGETYPE_NONE", PyInt_FromLong(LDB_CHANGETYPE_NONE));
3216         PyModule_AddObject(m, "CHANGETYPE_ADD", PyInt_FromLong(LDB_CHANGETYPE_ADD));
3217         PyModule_AddObject(m, "CHANGETYPE_DELETE", PyInt_FromLong(LDB_CHANGETYPE_DELETE));
3218         PyModule_AddObject(m, "CHANGETYPE_MODIFY", PyInt_FromLong(LDB_CHANGETYPE_MODIFY));
3219
3220         PyModule_AddObject(m, "FLAG_MOD_ADD", PyInt_FromLong(LDB_FLAG_MOD_ADD));
3221         PyModule_AddObject(m, "FLAG_MOD_REPLACE", PyInt_FromLong(LDB_FLAG_MOD_REPLACE));
3222         PyModule_AddObject(m, "FLAG_MOD_DELETE", PyInt_FromLong(LDB_FLAG_MOD_DELETE));
3223
3224         PyModule_AddObject(m, "SUCCESS", PyInt_FromLong(LDB_SUCCESS));
3225         PyModule_AddObject(m, "ERR_OPERATIONS_ERROR", PyInt_FromLong(LDB_ERR_OPERATIONS_ERROR));
3226         PyModule_AddObject(m, "ERR_PROTOCOL_ERROR", PyInt_FromLong(LDB_ERR_PROTOCOL_ERROR));
3227         PyModule_AddObject(m, "ERR_TIME_LIMIT_EXCEEDED", PyInt_FromLong(LDB_ERR_TIME_LIMIT_EXCEEDED));
3228         PyModule_AddObject(m, "ERR_SIZE_LIMIT_EXCEEDED", PyInt_FromLong(LDB_ERR_SIZE_LIMIT_EXCEEDED));
3229         PyModule_AddObject(m, "ERR_COMPARE_FALSE", PyInt_FromLong(LDB_ERR_COMPARE_FALSE));
3230         PyModule_AddObject(m, "ERR_COMPARE_TRUE", PyInt_FromLong(LDB_ERR_COMPARE_TRUE));
3231         PyModule_AddObject(m, "ERR_AUTH_METHOD_NOT_SUPPORTED", PyInt_FromLong(LDB_ERR_AUTH_METHOD_NOT_SUPPORTED));
3232         PyModule_AddObject(m, "ERR_STRONG_AUTH_REQUIRED", PyInt_FromLong(LDB_ERR_STRONG_AUTH_REQUIRED));
3233         PyModule_AddObject(m, "ERR_REFERRAL", PyInt_FromLong(LDB_ERR_REFERRAL));
3234         PyModule_AddObject(m, "ERR_ADMIN_LIMIT_EXCEEDED", PyInt_FromLong(LDB_ERR_ADMIN_LIMIT_EXCEEDED));
3235         PyModule_AddObject(m, "ERR_UNSUPPORTED_CRITICAL_EXTENSION", PyInt_FromLong(LDB_ERR_UNSUPPORTED_CRITICAL_EXTENSION));
3236         PyModule_AddObject(m, "ERR_CONFIDENTIALITY_REQUIRED", PyInt_FromLong(LDB_ERR_CONFIDENTIALITY_REQUIRED));
3237         PyModule_AddObject(m, "ERR_SASL_BIND_IN_PROGRESS", PyInt_FromLong(LDB_ERR_SASL_BIND_IN_PROGRESS));
3238         PyModule_AddObject(m, "ERR_NO_SUCH_ATTRIBUTE", PyInt_FromLong(LDB_ERR_NO_SUCH_ATTRIBUTE));
3239         PyModule_AddObject(m, "ERR_UNDEFINED_ATTRIBUTE_TYPE", PyInt_FromLong(LDB_ERR_UNDEFINED_ATTRIBUTE_TYPE));
3240         PyModule_AddObject(m, "ERR_INAPPROPRIATE_MATCHING", PyInt_FromLong(LDB_ERR_INAPPROPRIATE_MATCHING));
3241         PyModule_AddObject(m, "ERR_CONSTRAINT_VIOLATION", PyInt_FromLong(LDB_ERR_CONSTRAINT_VIOLATION));
3242         PyModule_AddObject(m, "ERR_ATTRIBUTE_OR_VALUE_EXISTS", PyInt_FromLong(LDB_ERR_ATTRIBUTE_OR_VALUE_EXISTS));
3243         PyModule_AddObject(m, "ERR_INVALID_ATTRIBUTE_SYNTAX", PyInt_FromLong(LDB_ERR_INVALID_ATTRIBUTE_SYNTAX));
3244         PyModule_AddObject(m, "ERR_NO_SUCH_OBJECT", PyInt_FromLong(LDB_ERR_NO_SUCH_OBJECT));
3245         PyModule_AddObject(m, "ERR_ALIAS_PROBLEM", PyInt_FromLong(LDB_ERR_ALIAS_PROBLEM));
3246         PyModule_AddObject(m, "ERR_INVALID_DN_SYNTAX", PyInt_FromLong(LDB_ERR_INVALID_DN_SYNTAX));
3247         PyModule_AddObject(m, "ERR_ALIAS_DEREFERINCING_PROBLEM", PyInt_FromLong(LDB_ERR_ALIAS_DEREFERENCING_PROBLEM));
3248         PyModule_AddObject(m, "ERR_INAPPROPRIATE_AUTHENTICATION", PyInt_FromLong(LDB_ERR_INAPPROPRIATE_AUTHENTICATION));
3249         PyModule_AddObject(m, "ERR_INVALID_CREDENTIALS", PyInt_FromLong(LDB_ERR_INVALID_CREDENTIALS));
3250         PyModule_AddObject(m, "ERR_INSUFFICIENT_ACCESS_RIGHTS", PyInt_FromLong(LDB_ERR_INSUFFICIENT_ACCESS_RIGHTS));
3251         PyModule_AddObject(m, "ERR_BUSY", PyInt_FromLong(LDB_ERR_BUSY));
3252         PyModule_AddObject(m, "ERR_UNAVAILABLE", PyInt_FromLong(LDB_ERR_UNAVAILABLE));
3253         PyModule_AddObject(m, "ERR_UNWILLING_TO_PERFORM", PyInt_FromLong(LDB_ERR_UNWILLING_TO_PERFORM));
3254         PyModule_AddObject(m, "ERR_LOOP_DETECT", PyInt_FromLong(LDB_ERR_LOOP_DETECT));
3255         PyModule_AddObject(m, "ERR_NAMING_VIOLATION", PyInt_FromLong(LDB_ERR_NAMING_VIOLATION));
3256         PyModule_AddObject(m, "ERR_OBJECT_CLASS_VIOLATION", PyInt_FromLong(LDB_ERR_OBJECT_CLASS_VIOLATION));
3257         PyModule_AddObject(m, "ERR_NOT_ALLOWED_ON_NON_LEAF", PyInt_FromLong(LDB_ERR_NOT_ALLOWED_ON_NON_LEAF));
3258         PyModule_AddObject(m, "ERR_NOT_ALLOWED_ON_RDN", PyInt_FromLong(LDB_ERR_NOT_ALLOWED_ON_RDN));
3259         PyModule_AddObject(m, "ERR_ENTRY_ALREADY_EXISTS", PyInt_FromLong(LDB_ERR_ENTRY_ALREADY_EXISTS));
3260         PyModule_AddObject(m, "ERR_OBJECT_CLASS_MODS_PROHIBITED", PyInt_FromLong(LDB_ERR_OBJECT_CLASS_MODS_PROHIBITED));
3261         PyModule_AddObject(m, "ERR_AFFECTS_MULTIPLE_DSAS", PyInt_FromLong(LDB_ERR_AFFECTS_MULTIPLE_DSAS));
3262         PyModule_AddObject(m, "ERR_OTHER", PyInt_FromLong(LDB_ERR_OTHER));
3263
3264         PyModule_AddObject(m, "FLG_RDONLY", PyInt_FromLong(LDB_FLG_RDONLY));
3265         PyModule_AddObject(m, "FLG_NOSYNC", PyInt_FromLong(LDB_FLG_NOSYNC));
3266         PyModule_AddObject(m, "FLG_RECONNECT", PyInt_FromLong(LDB_FLG_RECONNECT));
3267         PyModule_AddObject(m, "FLG_NOMMAP", PyInt_FromLong(LDB_FLG_NOMMAP));
3268
3269         PyModule_AddObject(m, "__docformat__", PyString_FromString("restructuredText"));
3270
3271         PyExc_LdbError = PyErr_NewException(discard_const_p(char, "_ldb.LdbError"), NULL, NULL);
3272         PyModule_AddObject(m, "LdbError", PyExc_LdbError);
3273
3274         Py_INCREF(&PyLdb);
3275         Py_INCREF(&PyLdbDn);
3276         Py_INCREF(&PyLdbModule);
3277         Py_INCREF(&PyLdbMessage);
3278         Py_INCREF(&PyLdbMessageElement);
3279         Py_INCREF(&PyLdbTree);
3280         Py_INCREF(&PyLdbResult);
3281         Py_INCREF(&PyLdbControl);
3282
3283         PyModule_AddObject(m, "Ldb", (PyObject *)&PyLdb);
3284         PyModule_AddObject(m, "Dn", (PyObject *)&PyLdbDn);
3285         PyModule_AddObject(m, "Message", (PyObject *)&PyLdbMessage);
3286         PyModule_AddObject(m, "MessageElement", (PyObject *)&PyLdbMessageElement);
3287         PyModule_AddObject(m, "Module", (PyObject *)&PyLdbModule);
3288         PyModule_AddObject(m, "Tree", (PyObject *)&PyLdbTree);
3289         PyModule_AddObject(m, "Control", (PyObject *)&PyLdbControl);
3290
3291         PyModule_AddObject(m, "__version__", PyString_FromString(PACKAGE_VERSION));
3292
3293 #define ADD_LDB_STRING(val)  PyModule_AddObject(m, #val, PyString_FromString(val))
3294
3295         ADD_LDB_STRING(LDB_SYNTAX_DN);
3296         ADD_LDB_STRING(LDB_SYNTAX_DN);
3297         ADD_LDB_STRING(LDB_SYNTAX_DIRECTORY_STRING);
3298         ADD_LDB_STRING(LDB_SYNTAX_INTEGER);
3299         ADD_LDB_STRING(LDB_SYNTAX_BOOLEAN);
3300         ADD_LDB_STRING(LDB_SYNTAX_OCTET_STRING);
3301         ADD_LDB_STRING(LDB_SYNTAX_UTC_TIME);
3302 }