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