pyldb: Drop unnecessary dependency on pytalloc-util.
[sfrench/samba-autobuild/.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                 if (ldb_ctx->err_string == NULL) {
1006                         /* no error string was setup by the backend */
1007                         ldb_asprintf_errstring(ldb_ctx, "%s (%d)", ldb_strerror(ret), ret);
1008                 }
1009         }
1010
1011         talloc_free(mem_ctx);
1012         PyErr_LDB_ERROR_IS_ERR_RAISE(PyExc_LdbError, ret, ldb_ctx);
1013
1014         Py_RETURN_NONE;
1015 }
1016
1017
1018 /**
1019  * Obtain a ldb message from a Python Dictionary object.
1020  *
1021  * @param mem_ctx Memory context
1022  * @param py_obj Python Dictionary object
1023  * @param ldb_ctx LDB context
1024  * @param mod_flags Flags to be set on every message element
1025  * @return ldb_message on success or NULL on failure
1026  */
1027 static struct ldb_message *PyDict_AsMessage(TALLOC_CTX *mem_ctx,
1028                                             PyObject *py_obj,
1029                                             struct ldb_context *ldb_ctx,
1030                                             unsigned int mod_flags)
1031 {
1032         struct ldb_message *msg;
1033         unsigned int msg_pos = 0;
1034         Py_ssize_t dict_pos = 0;
1035         PyObject *key, *value;
1036         struct ldb_message_element *msg_el;
1037         PyObject *dn_value = PyDict_GetItemString(py_obj, "dn");
1038
1039         msg = ldb_msg_new(mem_ctx);
1040         msg->elements = talloc_zero_array(msg, struct ldb_message_element, PyDict_Size(py_obj));
1041
1042         if (dn_value) {
1043                 if (!pyldb_Object_AsDn(msg, dn_value, ldb_ctx, &msg->dn)) {
1044                         PyErr_SetString(PyExc_TypeError, "unable to import dn object");
1045                         return NULL;
1046                 }
1047                 if (msg->dn == NULL) {
1048                         PyErr_SetString(PyExc_TypeError, "dn set but not found");
1049                         return NULL;
1050                 }
1051         } else {
1052                 PyErr_SetString(PyExc_TypeError, "no dn set");
1053                 return NULL;
1054         }
1055
1056         while (PyDict_Next(py_obj, &dict_pos, &key, &value)) {
1057                 char *key_str = PyString_AsString(key);
1058                 if (strcmp(key_str, "dn") != 0) {
1059                         msg_el = PyObject_AsMessageElement(msg->elements, value,
1060                                                            mod_flags, key_str);
1061                         if (msg_el == NULL) {
1062                                 PyErr_SetString(PyExc_TypeError, "unable to import element");
1063                                 return NULL;
1064                         }
1065                         memcpy(&msg->elements[msg_pos], msg_el, sizeof(*msg_el));
1066                         msg_pos++;
1067                 }
1068         }
1069
1070         msg->num_elements = msg_pos;
1071
1072         return msg;
1073 }
1074
1075 static PyObject *py_ldb_add(PyLdbObject *self, PyObject *args, PyObject *kwargs)
1076 {
1077         PyObject *py_obj;
1078         int ret;
1079         struct ldb_context *ldb_ctx;
1080         struct ldb_request *req;
1081         struct ldb_message *msg = NULL;
1082         PyObject *py_controls = Py_None;
1083         TALLOC_CTX *mem_ctx;
1084         struct ldb_control **parsed_controls;
1085         const char * const kwnames[] = { "message", "controls", NULL };
1086
1087         if (!PyArg_ParseTupleAndKeywords(args, kwargs, "O|O",
1088                                          discard_const_p(char *, kwnames),
1089                                          &py_obj, &py_controls))
1090                 return NULL;
1091
1092         mem_ctx = talloc_new(NULL);
1093         if (mem_ctx == NULL) {
1094                 PyErr_NoMemory();
1095                 return NULL;
1096         }
1097         ldb_ctx = pyldb_Ldb_AsLdbContext(self);
1098
1099         if (py_controls == Py_None) {
1100                 parsed_controls = NULL;
1101         } else {
1102                 const char **controls = PyList_AsStringList(mem_ctx, py_controls, "controls");
1103                 parsed_controls = ldb_parse_control_strings(ldb_ctx, mem_ctx, controls);
1104                 talloc_free(controls);
1105         }
1106
1107         if (PyLdbMessage_Check(py_obj)) {
1108                 msg = pyldb_Message_AsMessage(py_obj);
1109         } else if (PyDict_Check(py_obj)) {
1110                 msg = PyDict_AsMessage(mem_ctx, py_obj, ldb_ctx, LDB_FLAG_MOD_ADD);
1111         } else {
1112                 PyErr_SetString(PyExc_TypeError,
1113                                 "Dictionary or LdbMessage object expected!");
1114         }
1115
1116         if (!msg) {
1117                 /* we should have a PyErr already set */
1118                 talloc_free(mem_ctx);
1119                 return NULL;
1120         }
1121
1122         ret = ldb_msg_sanity_check(ldb_ctx, msg);
1123         if (ret != LDB_SUCCESS) {
1124                 PyErr_LDB_ERROR_IS_ERR_RAISE(PyExc_LdbError, ret, ldb_ctx);
1125                 talloc_free(mem_ctx);
1126                 return NULL;
1127         }
1128
1129         ret = ldb_build_add_req(&req, ldb_ctx, mem_ctx, msg, parsed_controls,
1130                                 NULL, ldb_op_default_callback, NULL);
1131         if (ret != LDB_SUCCESS) {
1132                 PyErr_SetString(PyExc_TypeError, "failed to build request");
1133                 talloc_free(mem_ctx);
1134                 return NULL;
1135         }
1136
1137         /* do request and autostart a transaction */
1138         /* Then let's LDB handle the message error in case of pb as they are meaningful */
1139
1140         ret = ldb_transaction_start(ldb_ctx);
1141         if (ret != LDB_SUCCESS) {
1142                 talloc_free(mem_ctx);
1143                 PyErr_LDB_ERROR_IS_ERR_RAISE(PyExc_LdbError, ret, ldb_ctx);
1144         }
1145
1146         ret = ldb_request(ldb_ctx, req);
1147         if (ret == LDB_SUCCESS) {
1148                 ret = ldb_wait(req->handle, LDB_WAIT_ALL);
1149         } 
1150
1151         if (ret == LDB_SUCCESS) {
1152                 ret = ldb_transaction_commit(ldb_ctx);
1153         } else {
1154                 ldb_transaction_cancel(ldb_ctx);
1155                 if (ldb_ctx->err_string == NULL) {
1156                         /* no error string was setup by the backend */
1157                         ldb_asprintf_errstring(ldb_ctx, "%s (%d)", ldb_strerror(ret), ret);
1158                 }
1159         }
1160
1161         talloc_free(mem_ctx);
1162         PyErr_LDB_ERROR_IS_ERR_RAISE(PyExc_LdbError, ret, ldb_ctx);
1163
1164         Py_RETURN_NONE;
1165 }
1166
1167 static PyObject *py_ldb_delete(PyLdbObject *self, PyObject *args, PyObject *kwargs)
1168 {
1169         PyObject *py_dn;
1170         struct ldb_dn *dn;
1171         int ret;
1172         struct ldb_context *ldb_ctx;
1173         struct ldb_request *req;
1174         PyObject *py_controls = Py_None;
1175         TALLOC_CTX *mem_ctx;
1176         struct ldb_control **parsed_controls;
1177         const char * const kwnames[] = { "dn", "controls", NULL };
1178
1179         if (!PyArg_ParseTupleAndKeywords(args, kwargs, "O|O",
1180                                          discard_const_p(char *, kwnames),
1181                                          &py_dn, &py_controls))
1182                 return NULL;
1183
1184         mem_ctx = talloc_new(NULL);
1185         if (mem_ctx == NULL) {
1186                 PyErr_NoMemory();
1187                 return NULL;
1188         }
1189         ldb_ctx = pyldb_Ldb_AsLdbContext(self);
1190
1191         if (py_controls == Py_None) {
1192                 parsed_controls = NULL;
1193         } else {
1194                 const char **controls = PyList_AsStringList(mem_ctx, py_controls, "controls");
1195                 parsed_controls = ldb_parse_control_strings(ldb_ctx, mem_ctx, controls);
1196                 talloc_free(controls);
1197         }
1198
1199         if (!pyldb_Object_AsDn(mem_ctx, py_dn, ldb_ctx, &dn)) {
1200                 talloc_free(mem_ctx);
1201                 return NULL;
1202         }
1203
1204         ret = ldb_build_del_req(&req, ldb_ctx, mem_ctx, dn, parsed_controls,
1205                                 NULL, ldb_op_default_callback, NULL);
1206         if (ret != LDB_SUCCESS) {
1207                 PyErr_SetString(PyExc_TypeError, "failed to build request");
1208                 talloc_free(mem_ctx);
1209                 return NULL;
1210         }
1211
1212         /* do request and autostart a transaction */
1213         /* Then let's LDB handle the message error in case of pb as they are meaningful */
1214
1215         ret = ldb_transaction_start(ldb_ctx);
1216         if (ret != LDB_SUCCESS) {
1217                 talloc_free(mem_ctx);
1218                 PyErr_LDB_ERROR_IS_ERR_RAISE(PyExc_LdbError, ret, ldb_ctx);
1219         }
1220
1221         ret = ldb_request(ldb_ctx, req);
1222         if (ret == LDB_SUCCESS) {
1223                 ret = ldb_wait(req->handle, LDB_WAIT_ALL);
1224         }
1225
1226         if (ret == LDB_SUCCESS) {
1227                 ret = ldb_transaction_commit(ldb_ctx);
1228         } else {
1229                 ldb_transaction_cancel(ldb_ctx);
1230                 if (ldb_ctx->err_string == NULL) {
1231                         /* no error string was setup by the backend */
1232                         ldb_asprintf_errstring(ldb_ctx, "%s (%d)", ldb_strerror(ret), ret);
1233                 }
1234         }
1235
1236         talloc_free(mem_ctx);
1237         PyErr_LDB_ERROR_IS_ERR_RAISE(PyExc_LdbError, ret, ldb_ctx);
1238
1239         Py_RETURN_NONE;
1240 }
1241
1242 static PyObject *py_ldb_rename(PyLdbObject *self, PyObject *args, PyObject *kwargs)
1243 {
1244         PyObject *py_dn1, *py_dn2;
1245         struct ldb_dn *dn1, *dn2;
1246         int ret;
1247         TALLOC_CTX *mem_ctx;
1248         PyObject *py_controls = Py_None;
1249         struct ldb_control **parsed_controls;
1250         struct ldb_context *ldb_ctx;
1251         struct ldb_request *req;
1252         const char * const kwnames[] = { "dn1", "dn2", "controls", NULL };
1253
1254         ldb_ctx = pyldb_Ldb_AsLdbContext(self);
1255
1256         if (!PyArg_ParseTupleAndKeywords(args, kwargs, "OO|O",
1257                                          discard_const_p(char *, kwnames),
1258                                          &py_dn1, &py_dn2, &py_controls))
1259                 return NULL;
1260
1261
1262         mem_ctx = talloc_new(NULL);
1263         if (mem_ctx == NULL) {
1264                 PyErr_NoMemory();
1265                 return NULL;
1266         }
1267
1268         if (py_controls == Py_None) {
1269                 parsed_controls = NULL;
1270         } else {
1271                 const char **controls = PyList_AsStringList(mem_ctx, py_controls, "controls");
1272                 parsed_controls = ldb_parse_control_strings(ldb_ctx, mem_ctx, controls);
1273                 talloc_free(controls);
1274         }
1275
1276
1277         if (!pyldb_Object_AsDn(mem_ctx, py_dn1, ldb_ctx, &dn1)) {
1278                 talloc_free(mem_ctx);
1279                 return NULL;
1280         }
1281
1282         if (!pyldb_Object_AsDn(mem_ctx, py_dn2, ldb_ctx, &dn2)) {
1283                 talloc_free(mem_ctx);
1284                 return NULL;
1285         }
1286
1287         ret = ldb_build_rename_req(&req, ldb_ctx, mem_ctx, dn1, dn2, parsed_controls,
1288                                 NULL, ldb_op_default_callback, NULL);
1289         if (ret != LDB_SUCCESS) {
1290                 PyErr_SetString(PyExc_TypeError, "failed to build request");
1291                 talloc_free(mem_ctx);
1292                 return NULL;
1293         }
1294
1295         /* do request and autostart a transaction */
1296         /* Then let's LDB handle the message error in case of pb as they are meaningful */
1297
1298         ret = ldb_transaction_start(ldb_ctx);
1299         if (ret != LDB_SUCCESS) {
1300                 talloc_free(mem_ctx);
1301                 PyErr_LDB_ERROR_IS_ERR_RAISE(PyExc_LdbError, ret, ldb_ctx);
1302         }
1303
1304         ret = ldb_request(ldb_ctx, req);
1305         if (ret == LDB_SUCCESS) {
1306                 ret = ldb_wait(req->handle, LDB_WAIT_ALL);
1307         }
1308
1309         if (ret == LDB_SUCCESS) {
1310                 ret = ldb_transaction_commit(ldb_ctx);
1311         } else {
1312                 ldb_transaction_cancel(ldb_ctx);
1313                 if (ldb_ctx->err_string == NULL) {
1314                         /* no error string was setup by the backend */
1315                         ldb_asprintf_errstring(ldb_ctx, "%s (%d)", ldb_strerror(ret), ret);
1316                 }
1317         }
1318
1319         talloc_free(mem_ctx);
1320         PyErr_LDB_ERROR_IS_ERR_RAISE(PyExc_LdbError, ret, ldb_ctx);
1321
1322         Py_RETURN_NONE;
1323 }
1324
1325 static PyObject *py_ldb_schema_attribute_remove(PyLdbObject *self, PyObject *args)
1326 {
1327         char *name;
1328         if (!PyArg_ParseTuple(args, "s", &name))
1329                 return NULL;
1330
1331         ldb_schema_attribute_remove(pyldb_Ldb_AsLdbContext(self), name);
1332
1333         Py_RETURN_NONE;
1334 }
1335
1336 static PyObject *py_ldb_schema_attribute_add(PyLdbObject *self, PyObject *args)
1337 {
1338         char *attribute, *syntax;
1339         unsigned int flags;
1340         int ret;
1341         if (!PyArg_ParseTuple(args, "sIs", &attribute, &flags, &syntax))
1342                 return NULL;
1343
1344         ret = ldb_schema_attribute_add(pyldb_Ldb_AsLdbContext(self), attribute, flags, syntax);
1345
1346         PyErr_LDB_ERROR_IS_ERR_RAISE(PyExc_LdbError, ret, pyldb_Ldb_AsLdbContext(self));
1347
1348         Py_RETURN_NONE;
1349 }
1350
1351 static PyObject *ldb_ldif_to_pyobject(struct ldb_ldif *ldif)
1352 {
1353         if (ldif == NULL) {
1354                 Py_RETURN_NONE;
1355         } else {
1356         /* We don't want this attached to the 'ldb' any more */
1357                 return Py_BuildValue(discard_const_p(char, "(iO)"),
1358                                      ldif->changetype,
1359                                      PyLdbMessage_FromMessage(ldif->msg));
1360         }
1361 }
1362
1363
1364 static PyObject *py_ldb_write_ldif(PyLdbObject *self, PyObject *args)
1365 {
1366         int changetype;
1367         PyObject *py_msg;
1368         struct ldb_ldif ldif;
1369         PyObject *ret;
1370         char *string;
1371         TALLOC_CTX *mem_ctx;
1372
1373         if (!PyArg_ParseTuple(args, "Oi", &py_msg, &changetype))
1374                 return NULL;
1375
1376         if (!PyLdbMessage_Check(py_msg)) {
1377                 PyErr_SetString(PyExc_TypeError, "Expected Ldb Message for msg");
1378                 return NULL;
1379         }
1380
1381         ldif.msg = pyldb_Message_AsMessage(py_msg);
1382         ldif.changetype = changetype;
1383
1384         mem_ctx = talloc_new(NULL);
1385
1386         string = ldb_ldif_write_string(pyldb_Ldb_AsLdbContext(self), mem_ctx, &ldif);
1387         if (!string) {
1388                 PyErr_SetString(PyExc_KeyError, "Failed to generate LDIF");
1389                 return NULL;
1390         }
1391
1392         ret = PyString_FromString(string);
1393
1394         talloc_free(mem_ctx);
1395
1396         return ret;
1397 }
1398
1399 static PyObject *py_ldb_parse_ldif(PyLdbObject *self, PyObject *args)
1400 {
1401         PyObject *list;
1402         struct ldb_ldif *ldif;
1403         const char *s;
1404
1405         TALLOC_CTX *mem_ctx;
1406
1407         if (!PyArg_ParseTuple(args, "s", &s))
1408                 return NULL;
1409
1410         mem_ctx = talloc_new(NULL);
1411         if (!mem_ctx) {
1412                 Py_RETURN_NONE;
1413         }
1414
1415         list = PyList_New(0);
1416         while (s && *s != '\0') {
1417                 ldif = ldb_ldif_read_string(self->ldb_ctx, &s);
1418                 talloc_steal(mem_ctx, ldif);
1419                 if (ldif) {
1420                         PyList_Append(list, ldb_ldif_to_pyobject(ldif));
1421                 } else {
1422                         PyErr_SetString(PyExc_ValueError, "unable to parse ldif string");
1423                         talloc_free(mem_ctx);
1424                         return NULL;
1425                 }
1426         }
1427         talloc_free(mem_ctx); /* The pyobject already has a reference to the things it needs */
1428         return PyObject_GetIter(list);
1429 }
1430
1431 static PyObject *py_ldb_msg_diff(PyLdbObject *self, PyObject *args)
1432 {
1433         int ldb_ret;
1434         PyObject *py_msg_old;
1435         PyObject *py_msg_new;
1436         struct ldb_message *diff;
1437         struct ldb_context *ldb;
1438         PyObject *py_ret;
1439
1440         if (!PyArg_ParseTuple(args, "OO", &py_msg_old, &py_msg_new))
1441                 return NULL;
1442
1443         if (!PyLdbMessage_Check(py_msg_old)) {
1444                 PyErr_SetString(PyExc_TypeError, "Expected Ldb Message for old message");
1445                 return NULL;
1446         }
1447
1448         if (!PyLdbMessage_Check(py_msg_new)) {
1449                 PyErr_SetString(PyExc_TypeError, "Expected Ldb Message for new message");
1450                 return NULL;
1451         }
1452
1453         ldb = pyldb_Ldb_AsLdbContext(self);
1454         ldb_ret = ldb_msg_difference(ldb, ldb,
1455                                      pyldb_Message_AsMessage(py_msg_old),
1456                                      pyldb_Message_AsMessage(py_msg_new),
1457                                      &diff);
1458         if (ldb_ret != LDB_SUCCESS) {
1459                 PyErr_SetString(PyExc_RuntimeError, "Failed to generate the Ldb Message diff");
1460                 return NULL;
1461         }
1462
1463         py_ret = PyLdbMessage_FromMessage(diff);
1464
1465         talloc_unlink(ldb, diff);
1466
1467         return py_ret;
1468 }
1469
1470 static PyObject *py_ldb_schema_format_value(PyLdbObject *self, PyObject *args)
1471 {
1472         const struct ldb_schema_attribute *a;
1473         struct ldb_val old_val;
1474         struct ldb_val new_val;
1475         TALLOC_CTX *mem_ctx;
1476         PyObject *ret;
1477         char *element_name;
1478         PyObject *val;
1479
1480         if (!PyArg_ParseTuple(args, "sO", &element_name, &val))
1481                 return NULL;
1482
1483         mem_ctx = talloc_new(NULL);
1484
1485         old_val.data = (uint8_t *)PyString_AsString(val);
1486         old_val.length = PyString_Size(val);
1487
1488         a = ldb_schema_attribute_by_name(pyldb_Ldb_AsLdbContext(self), element_name);
1489
1490         if (a == NULL) {
1491                 Py_RETURN_NONE;
1492         }
1493
1494         if (a->syntax->ldif_write_fn(pyldb_Ldb_AsLdbContext(self), mem_ctx, &old_val, &new_val) != 0) {
1495                 talloc_free(mem_ctx);
1496                 Py_RETURN_NONE;
1497         }
1498
1499         ret = PyString_FromStringAndSize((const char *)new_val.data, new_val.length);
1500
1501         talloc_free(mem_ctx);
1502
1503         return ret;
1504 }
1505
1506 static PyObject *py_ldb_search(PyLdbObject *self, PyObject *args, PyObject *kwargs)
1507 {
1508         PyObject *py_base = Py_None;
1509         int scope = LDB_SCOPE_DEFAULT;
1510         char *expr = NULL;
1511         PyObject *py_attrs = Py_None;
1512         PyObject *py_controls = Py_None;
1513         const char * const kwnames[] = { "base", "scope", "expression", "attrs", "controls", NULL };
1514         int ret;
1515         struct ldb_result *res;
1516         struct ldb_request *req;
1517         const char **attrs;
1518         struct ldb_context *ldb_ctx;
1519         struct ldb_control **parsed_controls;
1520         struct ldb_dn *base;
1521         PyObject *py_ret;
1522         TALLOC_CTX *mem_ctx;
1523
1524         /* type "int" rather than "enum" for "scope" is intentional */
1525         if (!PyArg_ParseTupleAndKeywords(args, kwargs, "|OizOO",
1526                                          discard_const_p(char *, kwnames),
1527                                          &py_base, &scope, &expr, &py_attrs, &py_controls))
1528                 return NULL;
1529
1530
1531         mem_ctx = talloc_new(NULL);
1532         if (mem_ctx == NULL) {
1533                 PyErr_NoMemory();
1534                 return NULL;
1535         }
1536         ldb_ctx = pyldb_Ldb_AsLdbContext(self);
1537
1538         if (py_attrs == Py_None) {
1539                 attrs = NULL;
1540         } else {
1541                 attrs = PyList_AsStringList(mem_ctx, py_attrs, "attrs");
1542                 if (attrs == NULL) {
1543                         talloc_free(mem_ctx);
1544                         return NULL;
1545                 }
1546         }
1547
1548         if (py_base == Py_None) {
1549                 base = ldb_get_default_basedn(ldb_ctx);
1550         } else {
1551                 if (!pyldb_Object_AsDn(ldb_ctx, py_base, ldb_ctx, &base)) {
1552                         talloc_free(attrs);
1553                         return NULL;
1554                 }
1555         }
1556
1557         if (py_controls == Py_None) {
1558                 parsed_controls = NULL;
1559         } else {
1560                 const char **controls = PyList_AsStringList(mem_ctx, py_controls, "controls");
1561                 parsed_controls = ldb_parse_control_strings(ldb_ctx, mem_ctx, controls);
1562                 talloc_free(controls);
1563         }
1564
1565         res = talloc_zero(mem_ctx, struct ldb_result);
1566         if (res == NULL) {
1567                 PyErr_NoMemory();
1568                 talloc_free(mem_ctx);
1569                 return NULL;
1570         }
1571
1572         ret = ldb_build_search_req(&req, ldb_ctx, mem_ctx,
1573                                    base,
1574                                    scope,
1575                                    expr,
1576                                    attrs,
1577                                    parsed_controls,
1578                                    res,
1579                                    ldb_search_default_callback,
1580                                    NULL);
1581
1582         if (ret != LDB_SUCCESS) {
1583                 talloc_free(mem_ctx);
1584                 PyErr_LDB_ERROR_IS_ERR_RAISE(PyExc_LdbError, ret, ldb_ctx);
1585                 return NULL;
1586         }
1587
1588         talloc_steal(req, attrs);
1589
1590         ret = ldb_request(ldb_ctx, req);
1591
1592         if (ret == LDB_SUCCESS) {
1593                 ret = ldb_wait(req->handle, LDB_WAIT_ALL);
1594         }
1595
1596         if (ret != LDB_SUCCESS) {
1597                 talloc_free(mem_ctx);
1598                 PyErr_LDB_ERROR_IS_ERR_RAISE(PyExc_LdbError, ret, ldb_ctx);
1599                 return NULL;
1600         }
1601
1602         py_ret = PyLdbResult_FromResult(res);
1603
1604         talloc_free(mem_ctx);
1605
1606         return py_ret;
1607 }
1608
1609 static PyObject *py_ldb_get_opaque(PyLdbObject *self, PyObject *args)
1610 {
1611         char *name;
1612         void *data;
1613
1614         if (!PyArg_ParseTuple(args, "s", &name))
1615                 return NULL;
1616
1617         data = ldb_get_opaque(pyldb_Ldb_AsLdbContext(self), name);
1618
1619         if (data == NULL)
1620                 Py_RETURN_NONE;
1621
1622         /* FIXME: More interpretation */
1623
1624         return Py_True;
1625 }
1626
1627 static PyObject *py_ldb_set_opaque(PyLdbObject *self, PyObject *args)
1628 {
1629         char *name;
1630         PyObject *data;
1631
1632         if (!PyArg_ParseTuple(args, "sO", &name, &data))
1633                 return NULL;
1634
1635         /* FIXME: More interpretation */
1636
1637         ldb_set_opaque(pyldb_Ldb_AsLdbContext(self), name, data);
1638
1639         Py_RETURN_NONE;
1640 }
1641
1642 static PyObject *py_ldb_modules(PyLdbObject *self)
1643 {
1644         struct ldb_context *ldb = pyldb_Ldb_AsLdbContext(self);
1645         PyObject *ret = PyList_New(0);
1646         struct ldb_module *mod;
1647
1648         for (mod = ldb->modules; mod; mod = mod->next) {
1649                 PyList_Append(ret, PyLdbModule_FromModule(mod));
1650         }
1651
1652         return ret;
1653 }
1654
1655 static PyObject *py_ldb_sequence_number(PyLdbObject *self, PyObject *args)
1656 {
1657         struct ldb_context *ldb = pyldb_Ldb_AsLdbContext(self);
1658         int type, ret;
1659         uint64_t value;
1660
1661         if (!PyArg_ParseTuple(args, "i", &type))
1662                 return NULL;
1663
1664         /* FIXME: More interpretation */
1665
1666         ret = ldb_sequence_number(ldb, type, &value);
1667
1668         if (ret != LDB_SUCCESS) {
1669                 PyErr_LDB_ERROR_IS_ERR_RAISE(PyExc_LdbError, ret, ldb);
1670                 return NULL;
1671         }
1672         return PyLong_FromLongLong(value);
1673 }
1674 static PyMethodDef py_ldb_methods[] = {
1675         { "set_debug", (PyCFunction)py_ldb_set_debug, METH_VARARGS, 
1676                 "S.set_debug(callback) -> None\n"
1677                 "Set callback for LDB debug messages.\n"
1678                 "The callback should accept a debug level and debug text." },
1679         { "set_create_perms", (PyCFunction)py_ldb_set_create_perms, METH_VARARGS, 
1680                 "S.set_create_perms(mode) -> None\n"
1681                 "Set mode to use when creating new LDB files." },
1682         { "set_modules_dir", (PyCFunction)py_ldb_set_modules_dir, METH_VARARGS,
1683                 "S.set_modules_dir(path) -> None\n"
1684                 "Set path LDB should search for modules" },
1685         { "transaction_start", (PyCFunction)py_ldb_transaction_start, METH_NOARGS, 
1686                 "S.transaction_start() -> None\n"
1687                 "Start a new transaction." },
1688         { "transaction_prepare_commit", (PyCFunction)py_ldb_transaction_prepare_commit, METH_NOARGS,
1689                 "S.transaction_prepare_commit() -> None\n"
1690                 "prepare to commit a new transaction (2-stage commit)." },
1691         { "transaction_commit", (PyCFunction)py_ldb_transaction_commit, METH_NOARGS, 
1692                 "S.transaction_commit() -> None\n"
1693                 "commit a new transaction." },
1694         { "transaction_cancel", (PyCFunction)py_ldb_transaction_cancel, METH_NOARGS, 
1695                 "S.transaction_cancel() -> None\n"
1696                 "cancel a new transaction." },
1697         { "setup_wellknown_attributes", (PyCFunction)py_ldb_setup_wellknown_attributes, METH_NOARGS, 
1698                 NULL },
1699         { "get_root_basedn", (PyCFunction)py_ldb_get_root_basedn, METH_NOARGS,
1700                 NULL },
1701         { "get_schema_basedn", (PyCFunction)py_ldb_get_schema_basedn, METH_NOARGS,
1702                 NULL },
1703         { "get_default_basedn", (PyCFunction)py_ldb_get_default_basedn, METH_NOARGS,
1704                 NULL },
1705         { "get_config_basedn", (PyCFunction)py_ldb_get_config_basedn, METH_NOARGS,
1706                 NULL },
1707         { "connect", (PyCFunction)py_ldb_connect, METH_VARARGS|METH_KEYWORDS, 
1708                 "S.connect(url, flags=0, options=None) -> None\n"
1709                 "Connect to a LDB URL." },
1710         { "modify", (PyCFunction)py_ldb_modify, METH_VARARGS|METH_KEYWORDS,
1711                 "S.modify(message, controls=None, validate=False) -> None\n"
1712                 "Modify an entry." },
1713         { "add", (PyCFunction)py_ldb_add, METH_VARARGS|METH_KEYWORDS,
1714                 "S.add(message, controls=None) -> None\n"
1715                 "Add an entry." },
1716         { "delete", (PyCFunction)py_ldb_delete, METH_VARARGS|METH_KEYWORDS,
1717                 "S.delete(dn, controls=None) -> None\n"
1718                 "Remove an entry." },
1719         { "rename", (PyCFunction)py_ldb_rename, METH_VARARGS|METH_KEYWORDS,
1720                 "S.rename(old_dn, new_dn, controls=None) -> None\n"
1721                 "Rename an entry." },
1722         { "search", (PyCFunction)py_ldb_search, METH_VARARGS|METH_KEYWORDS,
1723                 "S.search(base=None, scope=None, expression=None, attrs=None, controls=None) -> msgs\n"
1724                 "Search in a database.\n"
1725                 "\n"
1726                 ":param base: Optional base DN to search\n"
1727                 ":param scope: Search scope (SCOPE_BASE, SCOPE_ONELEVEL or SCOPE_SUBTREE)\n"
1728                 ":param expression: Optional search expression\n"
1729                 ":param attrs: Attributes to return (defaults to all)\n"
1730                 ":param controls: Optional list of controls\n"
1731                 ":return: Iterator over Message objects\n"
1732         },
1733         { "schema_attribute_remove", (PyCFunction)py_ldb_schema_attribute_remove, METH_VARARGS,
1734                 NULL },
1735         { "schema_attribute_add", (PyCFunction)py_ldb_schema_attribute_add, METH_VARARGS,
1736                 NULL },
1737         { "schema_format_value", (PyCFunction)py_ldb_schema_format_value, METH_VARARGS,
1738                 NULL },
1739         { "parse_ldif", (PyCFunction)py_ldb_parse_ldif, METH_VARARGS,
1740                 "S.parse_ldif(ldif) -> iter(messages)\n"
1741                 "Parse a string formatted using LDIF." },
1742         { "write_ldif", (PyCFunction)py_ldb_write_ldif, METH_VARARGS,
1743                 "S.write_ldif(message, changetype) -> ldif\n"
1744                 "Print the message as a string formatted using LDIF." },
1745         { "msg_diff", (PyCFunction)py_ldb_msg_diff, METH_VARARGS,
1746                 "S.msg_diff(Message) -> Message\n"
1747                 "Return an LDB Message of the difference between two Message objects." },
1748         { "get_opaque", (PyCFunction)py_ldb_get_opaque, METH_VARARGS,
1749                 "S.get_opaque(name) -> value\n"
1750                 "Get an opaque value set on this LDB connection. \n"
1751                 ":note: The returned value may not be useful in Python."
1752         },
1753         { "set_opaque", (PyCFunction)py_ldb_set_opaque, METH_VARARGS,
1754                 "S.set_opaque(name, value) -> None\n"
1755                 "Set an opaque value on this LDB connection. \n"
1756                 ":note: Passing incorrect values may cause crashes." },
1757         { "modules", (PyCFunction)py_ldb_modules, METH_NOARGS,
1758                 "S.modules() -> list\n"
1759                 "Return the list of modules on this LDB connection " },
1760         { "sequence_number", (PyCFunction)py_ldb_sequence_number, METH_VARARGS,
1761                 "S.sequence_number(type) -> value\n"
1762                 "Return the value of the sequence according to the requested type" },
1763         { NULL },
1764 };
1765
1766 static PyObject *PyLdbModule_FromModule(struct ldb_module *mod)
1767 {
1768         PyLdbModuleObject *ret;
1769
1770         ret = (PyLdbModuleObject *)PyLdbModule.tp_alloc(&PyLdbModule, 0);
1771         if (ret == NULL) {
1772                 PyErr_NoMemory();
1773                 return NULL;
1774         }
1775         ret->mem_ctx = talloc_new(NULL);
1776         ret->mod = talloc_reference(ret->mem_ctx, mod);
1777         return (PyObject *)ret;
1778 }
1779
1780 static PyObject *py_ldb_get_firstmodule(PyLdbObject *self, void *closure)
1781 {
1782         return PyLdbModule_FromModule(pyldb_Ldb_AsLdbContext(self)->modules);
1783 }
1784
1785 static PyGetSetDef py_ldb_getset[] = {
1786         { discard_const_p(char, "firstmodule"), (getter)py_ldb_get_firstmodule, NULL, NULL },
1787         { NULL }
1788 };
1789
1790 static int py_ldb_contains(PyLdbObject *self, PyObject *obj)
1791 {
1792         struct ldb_context *ldb_ctx = pyldb_Ldb_AsLdbContext(self);
1793         struct ldb_dn *dn;
1794         struct ldb_result *result;
1795         unsigned int count;
1796         int ret;
1797
1798         if (!pyldb_Object_AsDn(ldb_ctx, obj, ldb_ctx, &dn)) {
1799                 return -1;
1800         }
1801
1802         ret = ldb_search(ldb_ctx, ldb_ctx, &result, dn, LDB_SCOPE_BASE, NULL,
1803                          NULL);
1804         if (ret != LDB_SUCCESS) {
1805                 PyErr_SetLdbError(PyExc_LdbError, ret, ldb_ctx);
1806                 return -1;
1807         }
1808
1809         count = result->count;
1810
1811         talloc_free(result);
1812
1813         if (count > 1) {
1814                 PyErr_Format(PyExc_RuntimeError,
1815                              "Searching for [%s] dn gave %u results!",
1816                              ldb_dn_get_linearized(dn),
1817                              count);
1818                 return -1;
1819         }
1820
1821         return count;
1822 }
1823
1824 static PySequenceMethods py_ldb_seq = {
1825         .sq_contains = (objobjproc)py_ldb_contains,
1826 };
1827
1828 static PyObject *PyLdb_FromLdbContext(struct ldb_context *ldb_ctx)
1829 {
1830         PyLdbObject *ret;
1831
1832         ret = (PyLdbObject *)PyLdb.tp_alloc(&PyLdb, 0);
1833         if (ret == NULL) {
1834                 PyErr_NoMemory();
1835                 return NULL;
1836         }
1837         ret->mem_ctx = talloc_new(NULL);
1838         ret->ldb_ctx = talloc_reference(ret->mem_ctx, ldb_ctx);
1839         return (PyObject *)ret;
1840 }
1841
1842 static void py_ldb_dealloc(PyLdbObject *self)
1843 {
1844         talloc_free(self->mem_ctx);
1845         self->ob_type->tp_free(self);
1846 }
1847
1848 static PyTypeObject PyLdb = {
1849         .tp_name = "ldb.Ldb",
1850         .tp_methods = py_ldb_methods,
1851         .tp_repr = (reprfunc)py_ldb_repr,
1852         .tp_new = py_ldb_new,
1853         .tp_init = (initproc)py_ldb_init,
1854         .tp_dealloc = (destructor)py_ldb_dealloc,
1855         .tp_getset = py_ldb_getset,
1856         .tp_getattro = PyObject_GenericGetAttr,
1857         .tp_basicsize = sizeof(PyLdbObject),
1858         .tp_doc = "Connection to a LDB database.",
1859         .tp_as_sequence = &py_ldb_seq,
1860         .tp_flags = Py_TPFLAGS_DEFAULT|Py_TPFLAGS_BASETYPE,
1861 };
1862
1863 static void py_ldb_result_dealloc(PyLdbResultObject *self)
1864 {
1865         talloc_free(self->mem_ctx);
1866         Py_DECREF(self->msgs);
1867         Py_DECREF(self->referals);
1868         Py_DECREF(self->controls);
1869         self->ob_type->tp_free(self);
1870 }
1871
1872 static PyObject *py_ldb_result_get_msgs(PyLdbResultObject *self, void *closure)
1873 {
1874         Py_INCREF(self->msgs);
1875         return self->msgs;
1876 }
1877
1878 static PyObject *py_ldb_result_get_controls(PyLdbResultObject *self, void *closure)
1879 {
1880         Py_INCREF(self->controls);
1881         return self->controls;
1882 }
1883
1884 static PyObject *py_ldb_result_get_referals(PyLdbResultObject *self, void *closure)
1885 {
1886         Py_INCREF(self->referals);
1887         return self->referals;
1888 }
1889
1890 static PyObject *py_ldb_result_get_count(PyLdbResultObject *self, void *closure)
1891 {
1892         Py_ssize_t size;
1893         if (self->msgs == NULL) {
1894                 PyErr_SetString(PyExc_AttributeError, "Count attribute is meaningless in this context");
1895                 return NULL;
1896         }
1897         size = PyList_Size(self->msgs);
1898         return PyInt_FromLong(size);
1899 }
1900
1901 static PyGetSetDef py_ldb_result_getset[] = {
1902         { discard_const_p(char, "controls"), (getter)py_ldb_result_get_controls, NULL, NULL },
1903         { discard_const_p(char, "msgs"), (getter)py_ldb_result_get_msgs, NULL, NULL },
1904         { discard_const_p(char, "referals"), (getter)py_ldb_result_get_referals, NULL, NULL },
1905         { discard_const_p(char, "count"), (getter)py_ldb_result_get_count, NULL, NULL },
1906         { NULL }
1907 };
1908
1909 static PyObject *py_ldb_result_iter(PyLdbResultObject *self)
1910 {
1911         return PyObject_GetIter(self->msgs);
1912 }
1913
1914 static Py_ssize_t py_ldb_result_len(PyLdbResultObject *self)
1915 {
1916         return PySequence_Size(self->msgs);
1917 }
1918
1919 static PyObject *py_ldb_result_find(PyLdbResultObject *self, Py_ssize_t idx)
1920 {
1921         return PySequence_GetItem(self->msgs, idx);
1922 }
1923
1924 static PySequenceMethods py_ldb_result_seq = {
1925         .sq_length = (lenfunc)py_ldb_result_len,
1926         .sq_item = (ssizeargfunc)py_ldb_result_find,
1927 };
1928
1929 static PyObject *py_ldb_result_repr(PyLdbObject *self)
1930 {
1931         return PyString_FromFormat("<ldb result>");
1932 }
1933
1934
1935 static PyTypeObject PyLdbResult = {
1936         .tp_name = "ldb.Result",
1937         .tp_repr = (reprfunc)py_ldb_result_repr,
1938         .tp_dealloc = (destructor)py_ldb_result_dealloc,
1939         .tp_iter = (getiterfunc)py_ldb_result_iter,
1940         .tp_getset = py_ldb_result_getset,
1941         .tp_getattro = PyObject_GenericGetAttr,
1942         .tp_basicsize = sizeof(PyLdbResultObject),
1943         .tp_as_sequence = &py_ldb_result_seq,
1944         .tp_doc = "LDB result.",
1945         .tp_flags = Py_TPFLAGS_DEFAULT|Py_TPFLAGS_BASETYPE,
1946 };
1947
1948 static PyObject *py_ldb_module_repr(PyLdbModuleObject *self)
1949 {
1950         return PyString_FromFormat("<ldb module '%s'>",
1951                 pyldb_Module_AsModule(self)->ops->name);
1952 }
1953
1954 static PyObject *py_ldb_module_str(PyLdbModuleObject *self)
1955 {
1956         return PyString_FromString(pyldb_Module_AsModule(self)->ops->name);
1957 }
1958
1959 static PyObject *py_ldb_module_start_transaction(PyLdbModuleObject *self)
1960 {
1961         pyldb_Module_AsModule(self)->ops->start_transaction(pyldb_Module_AsModule(self));
1962         Py_RETURN_NONE;
1963 }
1964
1965 static PyObject *py_ldb_module_end_transaction(PyLdbModuleObject *self)
1966 {
1967         pyldb_Module_AsModule(self)->ops->end_transaction(pyldb_Module_AsModule(self));
1968         Py_RETURN_NONE;
1969 }
1970
1971 static PyObject *py_ldb_module_del_transaction(PyLdbModuleObject *self)
1972 {
1973         pyldb_Module_AsModule(self)->ops->del_transaction(pyldb_Module_AsModule(self));
1974         Py_RETURN_NONE;
1975 }
1976
1977 static PyObject *py_ldb_module_search(PyLdbModuleObject *self, PyObject *args, PyObject *kwargs)
1978 {
1979         PyObject *py_base, *py_tree, *py_attrs, *py_ret;
1980         int ret, scope;
1981         struct ldb_request *req;
1982         const char * const kwnames[] = { "base", "scope", "tree", "attrs", NULL };
1983         struct ldb_module *mod;
1984         const char * const*attrs;
1985
1986         /* type "int" rather than "enum" for "scope" is intentional */
1987         if (!PyArg_ParseTupleAndKeywords(args, kwargs, "OiOO",
1988                                          discard_const_p(char *, kwnames),
1989                                          &py_base, &scope, &py_tree, &py_attrs))
1990                 return NULL;
1991
1992         mod = self->mod;
1993
1994         if (py_attrs == Py_None) {
1995                 attrs = NULL;
1996         } else {
1997                 attrs = PyList_AsStringList(NULL, py_attrs, "attrs");
1998                 if (attrs == NULL)
1999                         return NULL;
2000         }
2001
2002         ret = ldb_build_search_req(&req, mod->ldb, NULL, pyldb_Dn_AsDn(py_base), 
2003                              scope, NULL /* expr */, attrs,
2004                              NULL /* controls */, NULL, NULL, NULL);
2005
2006         talloc_steal(req, attrs);
2007
2008         PyErr_LDB_ERROR_IS_ERR_RAISE(PyExc_LdbError, ret, mod->ldb);
2009
2010         req->op.search.res = NULL;
2011
2012         ret = mod->ops->search(mod, req);
2013
2014         PyErr_LDB_ERROR_IS_ERR_RAISE(PyExc_LdbError, ret, mod->ldb);
2015
2016         py_ret = PyLdbResult_FromResult(req->op.search.res);
2017
2018         talloc_free(req);
2019
2020         return py_ret;  
2021 }
2022
2023
2024 static PyObject *py_ldb_module_add(PyLdbModuleObject *self, PyObject *args)
2025 {
2026         struct ldb_request *req;
2027         PyObject *py_message;
2028         int ret;
2029         struct ldb_module *mod;
2030
2031         if (!PyArg_ParseTuple(args, "O", &py_message))
2032                 return NULL;
2033
2034         req = talloc_zero(NULL, struct ldb_request);
2035         req->operation = LDB_ADD;
2036         req->op.add.message = pyldb_Message_AsMessage(py_message);
2037
2038         mod = pyldb_Module_AsModule(self);
2039         ret = mod->ops->add(mod, req);
2040
2041         PyErr_LDB_ERROR_IS_ERR_RAISE(PyExc_LdbError, ret, mod->ldb);
2042
2043         Py_RETURN_NONE;
2044 }
2045
2046 static PyObject *py_ldb_module_modify(PyLdbModuleObject *self, PyObject *args) 
2047 {
2048         int ret;
2049         struct ldb_request *req;
2050         PyObject *py_message;
2051         struct ldb_module *mod;
2052
2053         if (!PyArg_ParseTuple(args, "O", &py_message))
2054                 return NULL;
2055
2056         req = talloc_zero(NULL, struct ldb_request);
2057         req->operation = LDB_MODIFY;
2058         req->op.mod.message = pyldb_Message_AsMessage(py_message);
2059
2060         mod = pyldb_Module_AsModule(self);
2061         ret = mod->ops->modify(mod, req);
2062
2063         PyErr_LDB_ERROR_IS_ERR_RAISE(PyExc_LdbError, ret, mod->ldb);
2064
2065         Py_RETURN_NONE;
2066 }
2067
2068 static PyObject *py_ldb_module_delete(PyLdbModuleObject *self, PyObject *args) 
2069 {
2070         int ret;
2071         struct ldb_request *req;
2072         PyObject *py_dn;
2073
2074         if (!PyArg_ParseTuple(args, "O", &py_dn))
2075                 return NULL;
2076
2077         req = talloc_zero(NULL, struct ldb_request);
2078         req->operation = LDB_DELETE;
2079         req->op.del.dn = pyldb_Dn_AsDn(py_dn);
2080
2081         ret = pyldb_Module_AsModule(self)->ops->del(pyldb_Module_AsModule(self), req);
2082
2083         PyErr_LDB_ERROR_IS_ERR_RAISE(PyExc_LdbError, ret, NULL);
2084
2085         Py_RETURN_NONE;
2086 }
2087
2088 static PyObject *py_ldb_module_rename(PyLdbModuleObject *self, PyObject *args)
2089 {
2090         int ret;
2091         struct ldb_request *req;
2092         PyObject *py_dn1, *py_dn2;
2093
2094         if (!PyArg_ParseTuple(args, "OO", &py_dn1, &py_dn2))
2095                 return NULL;
2096
2097         req = talloc_zero(NULL, struct ldb_request);
2098
2099         req->operation = LDB_RENAME;
2100         req->op.rename.olddn = pyldb_Dn_AsDn(py_dn1);
2101         req->op.rename.newdn = pyldb_Dn_AsDn(py_dn2);
2102
2103         ret = pyldb_Module_AsModule(self)->ops->rename(pyldb_Module_AsModule(self), req);
2104
2105         PyErr_LDB_ERROR_IS_ERR_RAISE(PyExc_LdbError, ret, NULL);
2106
2107         Py_RETURN_NONE;
2108 }
2109
2110 static PyMethodDef py_ldb_module_methods[] = {
2111         { "search", (PyCFunction)py_ldb_module_search, METH_VARARGS|METH_KEYWORDS, NULL },
2112         { "add", (PyCFunction)py_ldb_module_add, METH_VARARGS, NULL },
2113         { "modify", (PyCFunction)py_ldb_module_modify, METH_VARARGS, NULL },
2114         { "rename", (PyCFunction)py_ldb_module_rename, METH_VARARGS, NULL },
2115         { "delete", (PyCFunction)py_ldb_module_delete, METH_VARARGS, NULL },
2116         { "start_transaction", (PyCFunction)py_ldb_module_start_transaction, METH_NOARGS, NULL },
2117         { "end_transaction", (PyCFunction)py_ldb_module_end_transaction, METH_NOARGS, NULL },
2118         { "del_transaction", (PyCFunction)py_ldb_module_del_transaction, METH_NOARGS, NULL },
2119         { NULL },
2120 };
2121
2122 static void py_ldb_module_dealloc(PyLdbModuleObject *self)
2123 {
2124         talloc_free(self->mem_ctx);
2125         PyObject_Del(self);
2126 }
2127
2128 static PyTypeObject PyLdbModule = {
2129         .tp_name = "ldb.LdbModule",
2130         .tp_methods = py_ldb_module_methods,
2131         .tp_repr = (reprfunc)py_ldb_module_repr,
2132         .tp_str = (reprfunc)py_ldb_module_str,
2133         .tp_basicsize = sizeof(PyLdbModuleObject),
2134         .tp_dealloc = (destructor)py_ldb_module_dealloc,
2135         .tp_flags = Py_TPFLAGS_DEFAULT,
2136 };
2137
2138
2139 /**
2140  * Create a ldb_message_element from a Python object.
2141  *
2142  * This will accept any sequence objects that contains strings, or 
2143  * a string object.
2144  *
2145  * A reference to set_obj will be borrowed. 
2146  *
2147  * @param mem_ctx Memory context
2148  * @param set_obj Python object to convert
2149  * @param flags ldb_message_element flags to set
2150  * @param attr_name Name of the attribute
2151  * @return New ldb_message_element, allocated as child of mem_ctx
2152  */
2153 static struct ldb_message_element *PyObject_AsMessageElement(
2154                                                       TALLOC_CTX *mem_ctx,
2155                                                       PyObject *set_obj,
2156                                                       unsigned int flags,
2157                                                       const char *attr_name)
2158 {
2159         struct ldb_message_element *me;
2160
2161         if (pyldb_MessageElement_Check(set_obj)) {
2162                 PyLdbMessageElementObject *set_obj_as_me = (PyLdbMessageElementObject *)set_obj;
2163                 /* We have to talloc_reference() the memory context, not the pointer
2164                  * which may not actually be it's own context */
2165                 if (talloc_reference(mem_ctx, set_obj_as_me->mem_ctx)) {
2166                         return pyldb_MessageElement_AsMessageElement(set_obj);
2167                 }
2168                 return NULL;
2169         }
2170
2171         me = talloc(mem_ctx, struct ldb_message_element);
2172         if (me == NULL) {
2173                 PyErr_NoMemory();
2174                 return NULL;
2175         }
2176
2177         me->name = talloc_strdup(me, attr_name);
2178         me->flags = flags;
2179         if (PyString_Check(set_obj)) {
2180                 me->num_values = 1;
2181                 me->values = talloc_array(me, struct ldb_val, me->num_values);
2182                 me->values[0].length = PyString_Size(set_obj);
2183                 me->values[0].data = talloc_memdup(me, 
2184                         (uint8_t *)PyString_AsString(set_obj), me->values[0].length+1);
2185         } else if (PySequence_Check(set_obj)) {
2186                 Py_ssize_t i;
2187                 me->num_values = PySequence_Size(set_obj);
2188                 me->values = talloc_array(me, struct ldb_val, me->num_values);
2189                 for (i = 0; i < me->num_values; i++) {
2190                         PyObject *obj = PySequence_GetItem(set_obj, i);
2191                         if (!PyString_Check(obj)) {
2192                                 PyErr_Format(PyExc_TypeError,
2193                                              "Expected string as element %zd in list", i);
2194                                 talloc_free(me);
2195                                 return NULL;
2196                         }
2197
2198                         me->values[i].length = PyString_Size(obj);
2199                         me->values[i].data = talloc_memdup(me, 
2200                                 (uint8_t *)PyString_AsString(obj), me->values[i].length+1);
2201                 }
2202         } else {
2203                 talloc_free(me);
2204                 me = NULL;
2205         }
2206
2207         return me;
2208 }
2209
2210
2211 static PyObject *ldb_msg_element_to_set(struct ldb_context *ldb_ctx,
2212                                         struct ldb_message_element *me)
2213 {
2214         Py_ssize_t i;
2215         PyObject *result;
2216
2217         /* Python << 2.5 doesn't have PySet_New and PySet_Add. */
2218         result = PyList_New(me->num_values);
2219
2220         for (i = 0; i < me->num_values; i++) {
2221                 PyList_SetItem(result, i,
2222                         PyObject_FromLdbValue(&me->values[i]));
2223         }
2224
2225         return result;
2226 }
2227
2228 static PyObject *py_ldb_msg_element_get(PyLdbMessageElementObject *self, PyObject *args)
2229 {
2230         unsigned int i;
2231         if (!PyArg_ParseTuple(args, "I", &i))
2232                 return NULL;
2233         if (i >= pyldb_MessageElement_AsMessageElement(self)->num_values)
2234                 Py_RETURN_NONE;
2235
2236         return PyObject_FromLdbValue(&(pyldb_MessageElement_AsMessageElement(self)->values[i]));
2237 }
2238
2239 static PyObject *py_ldb_msg_element_flags(PyLdbMessageElementObject *self, PyObject *args)
2240 {
2241         struct ldb_message_element *el = pyldb_MessageElement_AsMessageElement(self);
2242         return PyInt_FromLong(el->flags);
2243 }
2244
2245 static PyObject *py_ldb_msg_element_set_flags(PyLdbMessageElementObject *self, PyObject *args)
2246 {
2247         unsigned int flags;
2248         struct ldb_message_element *el;
2249         if (!PyArg_ParseTuple(args, "I", &flags))
2250                 return NULL;
2251
2252         el = pyldb_MessageElement_AsMessageElement(self);
2253         el->flags = flags;
2254         Py_RETURN_NONE;
2255 }
2256
2257 static PyMethodDef py_ldb_msg_element_methods[] = {
2258         { "get", (PyCFunction)py_ldb_msg_element_get, METH_VARARGS, NULL },
2259         { "set_flags", (PyCFunction)py_ldb_msg_element_set_flags, METH_VARARGS, NULL },
2260         { "flags", (PyCFunction)py_ldb_msg_element_flags, METH_NOARGS, NULL },
2261         { NULL },
2262 };
2263
2264 static Py_ssize_t py_ldb_msg_element_len(PyLdbMessageElementObject *self)
2265 {
2266         return pyldb_MessageElement_AsMessageElement(self)->num_values;
2267 }
2268
2269 static PyObject *py_ldb_msg_element_find(PyLdbMessageElementObject *self, Py_ssize_t idx)
2270 {
2271         struct ldb_message_element *el = pyldb_MessageElement_AsMessageElement(self);
2272         if (idx < 0 || idx >= el->num_values) {
2273                 PyErr_SetString(PyExc_IndexError, "Out of range");
2274                 return NULL;
2275         }
2276         return PyString_FromStringAndSize((char *)el->values[idx].data, el->values[idx].length);
2277 }
2278
2279 static PySequenceMethods py_ldb_msg_element_seq = {
2280         .sq_length = (lenfunc)py_ldb_msg_element_len,
2281         .sq_item = (ssizeargfunc)py_ldb_msg_element_find,
2282 };
2283
2284 static int py_ldb_msg_element_cmp(PyLdbMessageElementObject *self, PyLdbMessageElementObject *other)
2285 {
2286         int ret = ldb_msg_element_compare(pyldb_MessageElement_AsMessageElement(self),
2287                                                                           pyldb_MessageElement_AsMessageElement(other));
2288         return SIGN(ret);
2289 }
2290
2291 static PyObject *py_ldb_msg_element_iter(PyLdbMessageElementObject *self)
2292 {
2293         PyObject *el = ldb_msg_element_to_set(NULL,
2294                                               pyldb_MessageElement_AsMessageElement(self));
2295         return PyObject_GetIter(el);
2296 }
2297
2298 static PyObject *PyLdbMessageElement_FromMessageElement(struct ldb_message_element *el, TALLOC_CTX *mem_ctx)
2299 {
2300         PyLdbMessageElementObject *ret;
2301         ret = PyObject_New(PyLdbMessageElementObject, &PyLdbMessageElement);
2302         if (ret == NULL) {
2303                 PyErr_NoMemory();
2304                 return NULL;
2305         }
2306         ret->mem_ctx = talloc_new(NULL);
2307         if (talloc_reference(ret->mem_ctx, mem_ctx) == NULL) {
2308                 PyErr_NoMemory();
2309                 return NULL;
2310         }
2311         ret->el = el;
2312         return (PyObject *)ret;
2313 }
2314
2315 static PyObject *py_ldb_msg_element_new(PyTypeObject *type, PyObject *args, PyObject *kwargs)
2316 {
2317         PyObject *py_elements = NULL;
2318         struct ldb_message_element *el;
2319         unsigned int flags = 0;
2320         char *name = NULL;
2321         const char * const kwnames[] = { "elements", "flags", "name", NULL };
2322         PyLdbMessageElementObject *ret;
2323         TALLOC_CTX *mem_ctx;
2324
2325         if (!PyArg_ParseTupleAndKeywords(args, kwargs, "|OIs",
2326                                          discard_const_p(char *, kwnames),
2327                                          &py_elements, &flags, &name))
2328                 return NULL;
2329
2330         mem_ctx = talloc_new(NULL);
2331         if (mem_ctx == NULL) {
2332                 PyErr_NoMemory();
2333                 return NULL;
2334         }
2335
2336         el = talloc_zero(mem_ctx, struct ldb_message_element);
2337         if (el == NULL) {
2338                 PyErr_NoMemory();
2339                 talloc_free(mem_ctx);
2340                 return NULL;
2341         }
2342
2343         if (py_elements != NULL) {
2344                 Py_ssize_t i;
2345                 if (PyString_Check(py_elements)) {
2346                         el->num_values = 1;
2347                         el->values = talloc_array(el, struct ldb_val, 1);
2348                         if (el->values == NULL) {
2349                                 talloc_free(mem_ctx);
2350                                 PyErr_NoMemory();
2351                                 return NULL;
2352                         }
2353                         el->values[0].length = PyString_Size(py_elements);
2354                         el->values[0].data = talloc_memdup(el->values, 
2355                                 (uint8_t *)PyString_AsString(py_elements), el->values[0].length+1);
2356                 } else if (PySequence_Check(py_elements)) {
2357                         el->num_values = PySequence_Size(py_elements);
2358                         el->values = talloc_array(el, struct ldb_val, el->num_values);
2359                         if (el->values == NULL) {
2360                                 talloc_free(mem_ctx);
2361                                 PyErr_NoMemory();
2362                                 return NULL;
2363                         }
2364                         for (i = 0; i < el->num_values; i++) {
2365                                 PyObject *item = PySequence_GetItem(py_elements, i);
2366                                 if (item == NULL) {
2367                                         talloc_free(mem_ctx);
2368                                         return NULL;
2369                                 }
2370                                 if (!PyString_Check(item)) {
2371                                         PyErr_Format(PyExc_TypeError, 
2372                                                      "Expected string as element %zd in list", i);
2373                                         talloc_free(mem_ctx);
2374                                         return NULL;
2375                                 }
2376                                 el->values[i].length = PyString_Size(item);
2377                                 el->values[i].data = talloc_memdup(el,
2378                                         (uint8_t *)PyString_AsString(item), el->values[i].length+1);
2379                         }
2380                 } else {
2381                         PyErr_SetString(PyExc_TypeError, 
2382                                         "Expected string or list");
2383                         talloc_free(mem_ctx);
2384                         return NULL;
2385                 }
2386         }
2387
2388         el->flags = flags;
2389         el->name = talloc_strdup(el, name);
2390
2391         ret = PyObject_New(PyLdbMessageElementObject, type);
2392         if (ret == NULL) {
2393                 talloc_free(mem_ctx);
2394                 return NULL;
2395         }
2396
2397         ret->mem_ctx = mem_ctx;
2398         ret->el = el;
2399         return (PyObject *)ret;
2400 }
2401
2402 static PyObject *py_ldb_msg_element_repr(PyLdbMessageElementObject *self)
2403 {
2404         char *element_str = NULL;
2405         Py_ssize_t i;
2406         struct ldb_message_element *el = pyldb_MessageElement_AsMessageElement(self);
2407         PyObject *ret;
2408
2409         for (i = 0; i < el->num_values; i++) {
2410                 PyObject *o = py_ldb_msg_element_find(self, i);
2411                 if (element_str == NULL)
2412                         element_str = talloc_strdup(NULL, PyObject_REPR(o));
2413                 else
2414                         element_str = talloc_asprintf_append(element_str, ",%s", PyObject_REPR(o));
2415         }
2416
2417         if (element_str != NULL) {
2418                 ret = PyString_FromFormat("MessageElement([%s])", element_str);
2419                 talloc_free(element_str);
2420         } else {
2421                 ret = PyString_FromString("MessageElement([])");
2422         }
2423
2424         return ret;
2425 }
2426
2427 static PyObject *py_ldb_msg_element_str(PyLdbMessageElementObject *self)
2428 {
2429         struct ldb_message_element *el = pyldb_MessageElement_AsMessageElement(self);
2430
2431         if (el->num_values == 1)
2432                 return PyString_FromStringAndSize((char *)el->values[0].data, el->values[0].length);
2433         else
2434                 Py_RETURN_NONE;
2435 }
2436
2437 static void py_ldb_msg_element_dealloc(PyLdbMessageElementObject *self)
2438 {
2439         talloc_free(self->mem_ctx);
2440         PyObject_Del(self);
2441 }
2442
2443 static PyTypeObject PyLdbMessageElement = {
2444         .tp_name = "ldb.MessageElement",
2445         .tp_basicsize = sizeof(PyLdbMessageElementObject),
2446         .tp_dealloc = (destructor)py_ldb_msg_element_dealloc,
2447         .tp_repr = (reprfunc)py_ldb_msg_element_repr,
2448         .tp_str = (reprfunc)py_ldb_msg_element_str,
2449         .tp_methods = py_ldb_msg_element_methods,
2450         .tp_compare = (cmpfunc)py_ldb_msg_element_cmp,
2451         .tp_iter = (getiterfunc)py_ldb_msg_element_iter,
2452         .tp_as_sequence = &py_ldb_msg_element_seq,
2453         .tp_new = py_ldb_msg_element_new,
2454         .tp_flags = Py_TPFLAGS_DEFAULT,
2455 };
2456
2457
2458 static PyObject *py_ldb_msg_from_dict(PyTypeObject *type, PyObject *args)
2459 {
2460         PyObject *py_ldb;
2461         PyObject *py_dict;
2462         PyObject *py_ret;
2463         struct ldb_message *msg;
2464         struct ldb_context *ldb_ctx;
2465         unsigned int mod_flags = LDB_FLAG_MOD_REPLACE;
2466
2467         if (!PyArg_ParseTuple(args, "O!O!|I",
2468                               &PyLdb, &py_ldb, &PyDict_Type, &py_dict,
2469                               &mod_flags)) {
2470                 return NULL;
2471         }
2472
2473         /* mask only flags we are going to use */
2474         mod_flags = LDB_FLAG_MOD_TYPE(mod_flags);
2475         if (!mod_flags) {
2476                 PyErr_SetString(PyExc_ValueError,
2477                                 "FLAG_MOD_ADD, FLAG_MOD_REPLACE or FLAG_MOD_DELETE"
2478                                 " expected as mod_flag value");
2479                 return NULL;
2480         }
2481
2482         ldb_ctx = pyldb_Ldb_AsLdbContext(py_ldb);
2483
2484         msg = PyDict_AsMessage(ldb_ctx, py_dict, ldb_ctx, mod_flags);
2485         if (!msg) {
2486                 return NULL;
2487         }
2488
2489         py_ret = PyLdbMessage_FromMessage(msg);
2490
2491         talloc_unlink(ldb_ctx, msg);
2492
2493         return py_ret;
2494 }
2495
2496 static PyObject *py_ldb_msg_remove_attr(PyLdbMessageObject *self, PyObject *args)
2497 {
2498         char *name;
2499         if (!PyArg_ParseTuple(args, "s", &name))
2500                 return NULL;
2501
2502         ldb_msg_remove_attr(self->msg, name);
2503
2504         Py_RETURN_NONE;
2505 }
2506
2507 static PyObject *py_ldb_msg_keys(PyLdbMessageObject *self)
2508 {
2509         struct ldb_message *msg = pyldb_Message_AsMessage(self);
2510         Py_ssize_t i, j = 0;
2511         PyObject *obj = PyList_New(msg->num_elements+(msg->dn != NULL?1:0));
2512         if (msg->dn != NULL) {
2513                 PyList_SetItem(obj, j, PyString_FromString("dn"));
2514                 j++;
2515         }
2516         for (i = 0; i < msg->num_elements; i++) {
2517                 PyList_SetItem(obj, j, PyString_FromString(msg->elements[i].name));
2518                 j++;
2519         }
2520         return obj;
2521 }
2522
2523 static PyObject *py_ldb_msg_getitem_helper(PyLdbMessageObject *self, PyObject *py_name)
2524 {
2525         struct ldb_message_element *el;
2526         char *name;
2527         struct ldb_message *msg = pyldb_Message_AsMessage(self);
2528         if (!PyString_Check(py_name)) {
2529                 PyErr_SetNone(PyExc_TypeError);
2530                 return NULL;
2531         }
2532         name = PyString_AsString(py_name);
2533         if (!strcmp(name, "dn"))
2534                 return pyldb_Dn_FromDn(msg->dn);
2535         el = ldb_msg_find_element(msg, name);
2536         if (el == NULL) {
2537                 return NULL;
2538         }
2539         return (PyObject *)PyLdbMessageElement_FromMessageElement(el, msg->elements);
2540 }
2541
2542 static PyObject *py_ldb_msg_getitem(PyLdbMessageObject *self, PyObject *py_name)
2543 {
2544         PyObject *ret = py_ldb_msg_getitem_helper(self, py_name);
2545         if (ret == NULL) {
2546                 PyErr_SetString(PyExc_KeyError, "No such element");
2547                 return NULL;
2548         }
2549         return ret;
2550 }
2551
2552 static PyObject *py_ldb_msg_get(PyLdbMessageObject *self, PyObject *args)
2553 {
2554         PyObject *name, *ret, *retobj;
2555         retobj = NULL;
2556         if (!PyArg_ParseTuple(args, "O|O", &name, &retobj))
2557                 return NULL;
2558
2559         ret = py_ldb_msg_getitem_helper(self, name);
2560         if (ret == NULL) {
2561                 if (PyErr_Occurred())
2562                         return NULL;
2563                 if (retobj != NULL) {
2564                         return retobj;
2565                 } else {
2566                         Py_RETURN_NONE;
2567                 }
2568         }
2569         return ret;
2570 }
2571
2572 static PyObject *py_ldb_msg_items(PyLdbMessageObject *self)
2573 {
2574         struct ldb_message *msg = pyldb_Message_AsMessage(self);
2575         Py_ssize_t i, j = 0;
2576         PyObject *l = PyList_New(msg->num_elements + (msg->dn == NULL?0:1));
2577         if (msg->dn != NULL) {
2578                 PyList_SetItem(l, 0, Py_BuildValue("(sO)", "dn", pyldb_Dn_FromDn(msg->dn)));
2579                 j++;
2580         }
2581         for (i = 0; i < msg->num_elements; i++, j++) {
2582                 PyObject *py_el = PyLdbMessageElement_FromMessageElement(&msg->elements[i], msg->elements);
2583                 PyObject *value = Py_BuildValue("(sO)", msg->elements[i].name, py_el);
2584                 PyList_SetItem(l, j, value);
2585         }
2586         return l;
2587 }
2588
2589 static PyObject *py_ldb_msg_elements(PyLdbMessageObject *self)
2590 {
2591         struct ldb_message *msg = pyldb_Message_AsMessage(self);
2592         Py_ssize_t i = 0;
2593         PyObject *l = PyList_New(msg->num_elements);
2594         for (i = 0; i < msg->num_elements; i++) {
2595                 PyList_SetItem(l, i, PyLdbMessageElement_FromMessageElement(&msg->elements[i], msg->elements));
2596         }
2597         return l;
2598 }
2599
2600 static PyObject *py_ldb_msg_add(PyLdbMessageObject *self, PyObject *args)
2601 {
2602         struct ldb_message *msg = pyldb_Message_AsMessage(self);
2603         PyLdbMessageElementObject *py_element;
2604         int ret;
2605         struct ldb_message_element *el;
2606
2607         if (!PyArg_ParseTuple(args, "O!", &PyLdbMessageElement, &py_element))
2608                 return NULL;
2609
2610         el = talloc_reference(msg, py_element->el);
2611         if (el == NULL) {
2612                 PyErr_NoMemory();
2613                 return NULL;
2614         }
2615
2616         ret = ldb_msg_add(msg, el, el->flags);
2617         PyErr_LDB_ERROR_IS_ERR_RAISE(PyExc_LdbError, ret, NULL);
2618
2619         Py_RETURN_NONE;
2620 }
2621
2622 static PyMethodDef py_ldb_msg_methods[] = {
2623         { "from_dict", (PyCFunction)py_ldb_msg_from_dict, METH_CLASS | METH_VARARGS,
2624                 "Message.from_dict(ldb, dict, mod_flag=FLAG_MOD_REPLACE) -> ldb.Message\n"
2625                 "Class method to create ldb.Message object from Dictionary.\n"
2626                 "mod_flag is one of FLAG_MOD_ADD, FLAG_MOD_REPLACE or FLAG_MOD_DELETE."},
2627         { "keys", (PyCFunction)py_ldb_msg_keys, METH_NOARGS, 
2628                 "S.keys() -> list\n\n"
2629                 "Return sequence of all attribute names." },
2630         { "remove", (PyCFunction)py_ldb_msg_remove_attr, METH_VARARGS, 
2631                 "S.remove(name)\n\n"
2632                 "Remove all entries for attributes with the specified name."},
2633         { "get", (PyCFunction)py_ldb_msg_get, METH_VARARGS, NULL },
2634         { "items", (PyCFunction)py_ldb_msg_items, METH_NOARGS, NULL },
2635         { "elements", (PyCFunction)py_ldb_msg_elements, METH_NOARGS, NULL },
2636         { "add", (PyCFunction)py_ldb_msg_add, METH_VARARGS,
2637                 "S.append(element)\n\n"
2638                 "Add an element to this message." },
2639         { NULL },
2640 };
2641
2642 static PyObject *py_ldb_msg_iter(PyLdbMessageObject *self)
2643 {
2644         PyObject *list, *iter;
2645
2646         list = py_ldb_msg_keys(self);
2647         iter = PyObject_GetIter(list);
2648         Py_DECREF(list);
2649         return iter;
2650 }
2651
2652 static int py_ldb_msg_setitem(PyLdbMessageObject *self, PyObject *name, PyObject *value)
2653 {
2654         char *attr_name;
2655
2656         if (!PyString_Check(name)) {
2657                 PyErr_SetNone(PyExc_TypeError);
2658                 return -1;
2659         }
2660
2661         attr_name = PyString_AsString(name);
2662         if (value == NULL) {
2663                 /* delitem */
2664                 ldb_msg_remove_attr(self->msg, attr_name);
2665         } else {
2666                 struct ldb_message_element *el = PyObject_AsMessageElement(self->msg,
2667                                                                            value, 0, attr_name);
2668                 if (el == NULL)
2669                         return -1;
2670                 ldb_msg_remove_attr(pyldb_Message_AsMessage(self), attr_name);
2671                 ldb_msg_add(pyldb_Message_AsMessage(self), el, el->flags);
2672         }
2673         return 0;
2674 }
2675
2676 static Py_ssize_t py_ldb_msg_length(PyLdbMessageObject *self)
2677 {
2678         return pyldb_Message_AsMessage(self)->num_elements;
2679 }
2680
2681 static PyMappingMethods py_ldb_msg_mapping = {
2682         .mp_length = (lenfunc)py_ldb_msg_length,
2683         .mp_subscript = (binaryfunc)py_ldb_msg_getitem,
2684         .mp_ass_subscript = (objobjargproc)py_ldb_msg_setitem,
2685 };
2686
2687 static PyObject *py_ldb_msg_new(PyTypeObject *type, PyObject *args, PyObject *kwargs)
2688 {
2689         const char * const kwnames[] = { "dn", NULL };
2690         struct ldb_message *ret;
2691         TALLOC_CTX *mem_ctx;
2692         PyObject *pydn = NULL;
2693         PyLdbMessageObject *py_ret;
2694
2695         if (!PyArg_ParseTupleAndKeywords(args, kwargs, "|O",
2696                                          discard_const_p(char *, kwnames),
2697                                          &pydn))
2698                 return NULL;
2699
2700         mem_ctx = talloc_new(NULL);
2701         if (mem_ctx == NULL) {
2702                 PyErr_NoMemory();
2703                 return NULL;
2704         }
2705
2706         ret = ldb_msg_new(mem_ctx);
2707         if (ret == NULL) {
2708                 talloc_free(mem_ctx);
2709                 PyErr_NoMemory();
2710                 return NULL;
2711         }
2712
2713         if (pydn != NULL) {
2714                 struct ldb_dn *dn;
2715                 if (!pyldb_Object_AsDn(NULL, pydn, NULL, &dn)) {
2716                         talloc_free(mem_ctx);
2717                         return NULL;
2718                 }
2719                 ret->dn = talloc_reference(ret, dn);
2720         }
2721
2722         py_ret = (PyLdbMessageObject *)type->tp_alloc(type, 0);
2723         if (py_ret == NULL) {
2724                 PyErr_NoMemory();
2725                 talloc_free(mem_ctx);
2726                 return NULL;
2727         }
2728
2729         py_ret->mem_ctx = mem_ctx;
2730         py_ret->msg = ret;
2731         return (PyObject *)py_ret;
2732 }
2733
2734 static PyObject *PyLdbMessage_FromMessage(struct ldb_message *msg)
2735 {
2736         PyLdbMessageObject *ret;
2737
2738         ret = (PyLdbMessageObject *)PyLdbMessage.tp_alloc(&PyLdbMessage, 0);
2739         if (ret == NULL) {
2740                 PyErr_NoMemory();
2741                 return NULL;
2742         }
2743         ret->mem_ctx = talloc_new(NULL);
2744         ret->msg = talloc_reference(ret->mem_ctx, msg);
2745         return (PyObject *)ret;
2746 }
2747
2748 static PyObject *py_ldb_msg_get_dn(PyLdbMessageObject *self, void *closure)
2749 {
2750         struct ldb_message *msg = pyldb_Message_AsMessage(self);
2751         return pyldb_Dn_FromDn(msg->dn);
2752 }
2753
2754 static int py_ldb_msg_set_dn(PyLdbMessageObject *self, PyObject *value, void *closure)
2755 {
2756         struct ldb_message *msg = pyldb_Message_AsMessage(self);
2757         if (!pyldb_Dn_Check(value)) {
2758                 PyErr_SetNone(PyExc_TypeError);
2759                 return -1;
2760         }
2761
2762         msg->dn = talloc_reference(msg, pyldb_Dn_AsDn(value));
2763         return 0;
2764 }
2765
2766 static PyGetSetDef py_ldb_msg_getset[] = {
2767         { discard_const_p(char, "dn"), (getter)py_ldb_msg_get_dn, (setter)py_ldb_msg_set_dn, NULL },
2768         { NULL }
2769 };
2770
2771 static PyObject *py_ldb_msg_repr(PyLdbMessageObject *self)
2772 {
2773         PyObject *dict = PyDict_New(), *ret;
2774         if (PyDict_Update(dict, (PyObject *)self) != 0)
2775                 return NULL;
2776         ret = PyString_FromFormat("Message(%s)", PyObject_REPR(dict));
2777         Py_DECREF(dict);
2778         return ret;
2779 }
2780
2781 static void py_ldb_msg_dealloc(PyLdbMessageObject *self)
2782 {
2783         talloc_free(self->mem_ctx);
2784         PyObject_Del(self);
2785 }
2786
2787 static int py_ldb_msg_compare(PyLdbMessageObject *py_msg1,
2788                               PyLdbMessageObject *py_msg2)
2789 {
2790         struct ldb_message *msg1 = pyldb_Message_AsMessage(py_msg1),
2791                            *msg2 = pyldb_Message_AsMessage(py_msg2);
2792         unsigned int i;
2793         int ret;
2794
2795         if ((msg1->dn != NULL) || (msg2->dn != NULL)) {
2796                 ret = ldb_dn_compare(msg1->dn, msg2->dn);
2797                 if (ret != 0) {
2798                         return SIGN(ret);
2799                 }
2800         }
2801
2802         ret = msg1->num_elements - msg2->num_elements;
2803         if (ret != 0) {
2804                 return SIGN(ret);
2805         }
2806
2807         for (i = 0; i < msg1->num_elements; i++) {
2808                 ret = ldb_msg_element_compare_name(&msg1->elements[i],
2809                                                    &msg2->elements[i]);
2810                 if (ret != 0) {
2811                         return SIGN(ret);
2812                 }
2813
2814                 ret = ldb_msg_element_compare(&msg1->elements[i],
2815                                               &msg2->elements[i]);
2816                 if (ret != 0) {
2817                         return SIGN(ret);
2818                 }
2819         }
2820
2821         return 0;
2822 }
2823
2824 static PyTypeObject PyLdbMessage = {
2825         .tp_name = "ldb.Message",
2826         .tp_methods = py_ldb_msg_methods,
2827         .tp_getset = py_ldb_msg_getset,
2828         .tp_as_mapping = &py_ldb_msg_mapping,
2829         .tp_basicsize = sizeof(PyLdbMessageObject),
2830         .tp_dealloc = (destructor)py_ldb_msg_dealloc,
2831         .tp_new = py_ldb_msg_new,
2832         .tp_repr = (reprfunc)py_ldb_msg_repr,
2833         .tp_flags = Py_TPFLAGS_DEFAULT,
2834         .tp_iter = (getiterfunc)py_ldb_msg_iter,
2835         .tp_compare = (cmpfunc)py_ldb_msg_compare,
2836 };
2837
2838 static PyObject *PyLdbTree_FromTree(struct ldb_parse_tree *tree)
2839 {
2840         PyLdbTreeObject *ret;
2841
2842         ret = (PyLdbTreeObject *)PyLdbTree.tp_alloc(&PyLdbTree, 0);
2843         if (ret == NULL) {
2844                 PyErr_NoMemory();
2845                 return NULL;
2846         }
2847
2848         ret->mem_ctx = talloc_new(NULL);
2849         ret->tree = talloc_reference(ret->mem_ctx, tree);
2850         return (PyObject *)ret;
2851 }
2852
2853 static void py_ldb_tree_dealloc(PyLdbTreeObject *self)
2854 {
2855         talloc_free(self->mem_ctx);
2856         PyObject_Del(self);
2857 }
2858
2859 static PyTypeObject PyLdbTree = {
2860         .tp_name = "ldb.Tree",
2861         .tp_basicsize = sizeof(PyLdbTreeObject),
2862         .tp_dealloc = (destructor)py_ldb_tree_dealloc,
2863         .tp_flags = Py_TPFLAGS_DEFAULT,
2864 };
2865
2866 /* Ldb_module */
2867 static int py_module_search(struct ldb_module *mod, struct ldb_request *req)
2868 {
2869         PyObject *py_ldb = (PyObject *)mod->private_data;
2870         PyObject *py_result, *py_base, *py_attrs, *py_tree;
2871
2872         py_base = pyldb_Dn_FromDn(req->op.search.base);
2873
2874         if (py_base == NULL)
2875                 return LDB_ERR_OPERATIONS_ERROR;
2876
2877         py_tree = PyLdbTree_FromTree(req->op.search.tree);
2878
2879         if (py_tree == NULL)
2880                 return LDB_ERR_OPERATIONS_ERROR;
2881
2882         if (req->op.search.attrs == NULL) {
2883                 py_attrs = Py_None;
2884         } else {
2885                 int i, len;
2886                 for (len = 0; req->op.search.attrs[len]; len++);
2887                 py_attrs = PyList_New(len);
2888                 for (i = 0; i < len; i++)
2889                         PyList_SetItem(py_attrs, i, PyString_FromString(req->op.search.attrs[i]));
2890         }
2891
2892         py_result = PyObject_CallMethod(py_ldb, discard_const_p(char, "search"),
2893                                         discard_const_p(char, "OiOO"),
2894                                         py_base, req->op.search.scope, py_tree, py_attrs);
2895
2896         Py_DECREF(py_attrs);
2897         Py_DECREF(py_tree);
2898         Py_DECREF(py_base);
2899
2900         if (py_result == NULL) {
2901                 return LDB_ERR_PYTHON_EXCEPTION;
2902         }
2903
2904         req->op.search.res = PyLdbResult_AsResult(NULL, py_result);
2905         if (req->op.search.res == NULL) {
2906                 return LDB_ERR_PYTHON_EXCEPTION;
2907         }
2908
2909         Py_DECREF(py_result);
2910
2911         return LDB_SUCCESS;
2912 }
2913
2914 static int py_module_add(struct ldb_module *mod, struct ldb_request *req)
2915 {
2916         PyObject *py_ldb = (PyObject *)mod->private_data;
2917         PyObject *py_result, *py_msg;
2918
2919         py_msg = PyLdbMessage_FromMessage(discard_const_p(struct ldb_message, req->op.add.message));
2920
2921         if (py_msg == NULL) {
2922                 return LDB_ERR_OPERATIONS_ERROR;
2923         }
2924
2925         py_result = PyObject_CallMethod(py_ldb, discard_const_p(char, "add"),
2926                                         discard_const_p(char, "O"),
2927                                         py_msg);
2928
2929         Py_DECREF(py_msg);
2930
2931         if (py_result == NULL) {
2932                 return LDB_ERR_PYTHON_EXCEPTION;
2933         }
2934
2935         Py_DECREF(py_result);
2936
2937         return LDB_SUCCESS;
2938 }
2939
2940 static int py_module_modify(struct ldb_module *mod, struct ldb_request *req)
2941 {
2942         PyObject *py_ldb = (PyObject *)mod->private_data;
2943         PyObject *py_result, *py_msg;
2944
2945         py_msg = PyLdbMessage_FromMessage(discard_const_p(struct ldb_message, req->op.mod.message));
2946
2947         if (py_msg == NULL) {
2948                 return LDB_ERR_OPERATIONS_ERROR;
2949         }
2950
2951         py_result = PyObject_CallMethod(py_ldb, discard_const_p(char, "modify"),
2952                                         discard_const_p(char, "O"),
2953                                         py_msg);
2954
2955         Py_DECREF(py_msg);
2956
2957         if (py_result == NULL) {
2958                 return LDB_ERR_PYTHON_EXCEPTION;
2959         }
2960
2961         Py_DECREF(py_result);
2962
2963         return LDB_SUCCESS;
2964 }
2965
2966 static int py_module_del(struct ldb_module *mod, struct ldb_request *req)
2967 {
2968         PyObject *py_ldb = (PyObject *)mod->private_data;
2969         PyObject *py_result, *py_dn;
2970
2971         py_dn = pyldb_Dn_FromDn(req->op.del.dn);
2972
2973         if (py_dn == NULL)
2974                 return LDB_ERR_OPERATIONS_ERROR;
2975
2976         py_result = PyObject_CallMethod(py_ldb, discard_const_p(char, "delete"),
2977                                         discard_const_p(char, "O"),
2978                                         py_dn);
2979
2980         if (py_result == NULL) {
2981                 return LDB_ERR_PYTHON_EXCEPTION;
2982         }
2983
2984         Py_DECREF(py_result);
2985
2986         return LDB_SUCCESS;
2987 }
2988
2989 static int py_module_rename(struct ldb_module *mod, struct ldb_request *req)
2990 {
2991         PyObject *py_ldb = (PyObject *)mod->private_data;
2992         PyObject *py_result, *py_olddn, *py_newdn;
2993
2994         py_olddn = pyldb_Dn_FromDn(req->op.rename.olddn);
2995
2996         if (py_olddn == NULL)
2997                 return LDB_ERR_OPERATIONS_ERROR;
2998
2999         py_newdn = pyldb_Dn_FromDn(req->op.rename.newdn);
3000
3001         if (py_newdn == NULL)
3002                 return LDB_ERR_OPERATIONS_ERROR;
3003
3004         py_result = PyObject_CallMethod(py_ldb, discard_const_p(char, "rename"),
3005                                         discard_const_p(char, "OO"),
3006                                         py_olddn, py_newdn);
3007
3008         Py_DECREF(py_olddn);
3009         Py_DECREF(py_newdn);
3010
3011         if (py_result == NULL) {
3012                 return LDB_ERR_PYTHON_EXCEPTION;
3013         }
3014
3015         Py_DECREF(py_result);
3016
3017         return LDB_SUCCESS;
3018 }
3019
3020 static int py_module_request(struct ldb_module *mod, struct ldb_request *req)
3021 {
3022         PyObject *py_ldb = (PyObject *)mod->private_data;
3023         PyObject *py_result;
3024
3025         py_result = PyObject_CallMethod(py_ldb, discard_const_p(char, "request"),
3026                                         discard_const_p(char, ""));
3027
3028         return LDB_ERR_OPERATIONS_ERROR;
3029 }
3030
3031 static int py_module_extended(struct ldb_module *mod, struct ldb_request *req)
3032 {
3033         PyObject *py_ldb = (PyObject *)mod->private_data;
3034         PyObject *py_result;
3035
3036         py_result = PyObject_CallMethod(py_ldb, discard_const_p(char, "extended"),
3037                                         discard_const_p(char, ""));
3038
3039         return LDB_ERR_OPERATIONS_ERROR;
3040 }
3041
3042 static int py_module_start_transaction(struct ldb_module *mod)
3043 {
3044         PyObject *py_ldb = (PyObject *)mod->private_data;
3045         PyObject *py_result;
3046
3047         py_result = PyObject_CallMethod(py_ldb, discard_const_p(char, "start_transaction"),
3048                                         discard_const_p(char, ""));
3049
3050         if (py_result == NULL) {
3051                 return LDB_ERR_PYTHON_EXCEPTION;
3052         }
3053
3054         Py_DECREF(py_result);
3055
3056         return LDB_SUCCESS;
3057 }
3058
3059 static int py_module_end_transaction(struct ldb_module *mod)
3060 {
3061         PyObject *py_ldb = (PyObject *)mod->private_data;
3062         PyObject *py_result;
3063
3064         py_result = PyObject_CallMethod(py_ldb, discard_const_p(char, "end_transaction"),
3065                                         discard_const_p(char, ""));
3066
3067         if (py_result == NULL) {
3068                 return LDB_ERR_PYTHON_EXCEPTION;
3069         }
3070
3071         Py_DECREF(py_result);
3072
3073         return LDB_SUCCESS;
3074 }
3075
3076 static int py_module_del_transaction(struct ldb_module *mod)
3077 {
3078         PyObject *py_ldb = (PyObject *)mod->private_data;
3079         PyObject *py_result;
3080
3081         py_result = PyObject_CallMethod(py_ldb, discard_const_p(char, "del_transaction"),
3082                                         discard_const_p(char, ""));
3083
3084         if (py_result == NULL) {
3085                 return LDB_ERR_PYTHON_EXCEPTION;
3086         }
3087
3088         Py_DECREF(py_result);
3089
3090         return LDB_SUCCESS;
3091 }
3092
3093 static int py_module_destructor(struct ldb_module *mod)
3094 {
3095         Py_DECREF((PyObject *)mod->private_data);
3096         return 0;
3097 }
3098
3099 static int py_module_init(struct ldb_module *mod)
3100 {
3101         PyObject *py_class = (PyObject *)mod->ops->private_data;
3102         PyObject *py_result, *py_next, *py_ldb;
3103
3104         py_ldb = PyLdb_FromLdbContext(mod->ldb);
3105
3106         if (py_ldb == NULL)
3107                 return LDB_ERR_OPERATIONS_ERROR;
3108
3109         py_next = PyLdbModule_FromModule(mod->next);
3110
3111         if (py_next == NULL)
3112                 return LDB_ERR_OPERATIONS_ERROR;
3113
3114         py_result = PyObject_CallFunction(py_class, discard_const_p(char, "OO"),
3115                                           py_ldb, py_next);
3116
3117         if (py_result == NULL) {
3118                 return LDB_ERR_PYTHON_EXCEPTION;
3119         }
3120
3121         mod->private_data = py_result;
3122
3123         talloc_set_destructor(mod, py_module_destructor);
3124
3125         return ldb_next_init(mod);
3126 }
3127
3128 static PyObject *py_register_module(PyObject *module, PyObject *args)
3129 {
3130         int ret;
3131         struct ldb_module_ops *ops;
3132         PyObject *input;
3133
3134         if (!PyArg_ParseTuple(args, "O", &input))
3135                 return NULL;
3136
3137         ops = talloc_zero(talloc_autofree_context(), struct ldb_module_ops);
3138         if (ops == NULL) {
3139                 PyErr_NoMemory();
3140                 return NULL;
3141         }
3142
3143         ops->name = talloc_strdup(ops, PyString_AsString(PyObject_GetAttrString(input, discard_const_p(char, "name"))));
3144
3145         Py_INCREF(input);
3146         ops->private_data = input;
3147         ops->init_context = py_module_init;
3148         ops->search = py_module_search;
3149         ops->add = py_module_add;
3150         ops->modify = py_module_modify;
3151         ops->del = py_module_del;
3152         ops->rename = py_module_rename;
3153         ops->request = py_module_request;
3154         ops->extended = py_module_extended;
3155         ops->start_transaction = py_module_start_transaction;
3156         ops->end_transaction = py_module_end_transaction;
3157         ops->del_transaction = py_module_del_transaction;
3158
3159         ret = ldb_register_module(ops);
3160
3161         PyErr_LDB_ERROR_IS_ERR_RAISE(PyExc_LdbError, ret, NULL);
3162
3163         Py_RETURN_NONE;
3164 }
3165
3166 static PyObject *py_timestring(PyObject *module, PyObject *args)
3167 {
3168         /* most times "time_t" is a signed integer type with 32 or 64 bit:
3169          * http://stackoverflow.com/questions/471248/what-is-ultimately-a-time-t-typedef-to */
3170         long int t_val;
3171         char *tresult;
3172         PyObject *ret;
3173         if (!PyArg_ParseTuple(args, "l", &t_val))
3174                 return NULL;
3175         tresult = ldb_timestring(NULL, (time_t) t_val);
3176         ret = PyString_FromString(tresult);
3177         talloc_free(tresult);
3178         return ret;
3179 }
3180
3181 static PyObject *py_string_to_time(PyObject *module, PyObject *args)
3182 {
3183         char *str;
3184         if (!PyArg_ParseTuple(args, "s", &str))
3185                 return NULL;
3186
3187         return PyInt_FromLong(ldb_string_to_time(str));
3188 }
3189
3190 static PyObject *py_valid_attr_name(PyObject *self, PyObject *args)
3191 {
3192         char *name;
3193         if (!PyArg_ParseTuple(args, "s", &name))
3194                 return NULL;
3195         return PyBool_FromLong(ldb_valid_attr_name(name));
3196 }
3197
3198 /*
3199   encode a string using RFC2254 rules
3200  */
3201 static PyObject *py_binary_encode(PyObject *self, PyObject *args)
3202 {
3203         char *str, *encoded;
3204         int size = 0;
3205         struct ldb_val val;
3206         PyObject *ret;
3207
3208         if (!PyArg_ParseTuple(args, "s#", &str, &size))
3209                 return NULL;
3210         val.data = (uint8_t *)str;
3211         val.length = size;
3212
3213         encoded = ldb_binary_encode(NULL, val);
3214         if (encoded == NULL) {
3215                 PyErr_SetString(PyExc_TypeError, "unable to encode binary string");
3216                 return NULL;
3217         }
3218         ret = PyString_FromString(encoded);
3219         talloc_free(encoded);
3220         return ret;
3221 }
3222
3223 /*
3224   decode a string using RFC2254 rules
3225  */
3226 static PyObject *py_binary_decode(PyObject *self, PyObject *args)
3227 {
3228         char *str;
3229         struct ldb_val val;
3230         PyObject *ret;
3231
3232         if (!PyArg_ParseTuple(args, "s", &str))
3233                 return NULL;
3234
3235         val = ldb_binary_decode(NULL, str);
3236         if (val.data == NULL) {
3237                 PyErr_SetString(PyExc_TypeError, "unable to decode binary string");
3238                 return NULL;
3239         }
3240         ret = Py_BuildValue("s#", val.data, val.length);
3241         talloc_free(val.data);
3242         return ret;
3243 }
3244
3245 static PyMethodDef py_ldb_global_methods[] = {
3246         { "register_module", py_register_module, METH_VARARGS, 
3247                 "S.register_module(module) -> None\n"
3248                 "Register a LDB module."},
3249         { "timestring", py_timestring, METH_VARARGS, 
3250                 "S.timestring(int) -> string\n"
3251                 "Generate a LDAP time string from a UNIX timestamp" },
3252         { "string_to_time", py_string_to_time, METH_VARARGS,
3253                 "S.string_to_time(string) -> int\n"
3254                 "Parse a LDAP time string into a UNIX timestamp." },
3255         { "valid_attr_name", py_valid_attr_name, METH_VARARGS,
3256                 "S.valid_attr_name(name) -> bool\n"
3257                 "Check whether the supplied name is a valid attribute name." },
3258         { "open", (PyCFunction)py_ldb_new, METH_VARARGS|METH_KEYWORDS,
3259                 NULL },
3260         { "binary_encode", py_binary_encode, METH_VARARGS,
3261                 "S.binary_encode(string) -> string\n"
3262                 "Perform a RFC2254 binary encoding on a string" },
3263         { "binary_decode", py_binary_decode, METH_VARARGS,
3264                 "S.binary_decode(string) -> string\n"
3265                 "Perform a RFC2254 binary decode on a string" },
3266         { NULL }
3267 };
3268
3269 void initldb(void)
3270 {
3271         PyObject *m;
3272
3273         if (PyType_Ready(&PyLdbDn) < 0)
3274                 return;
3275
3276         if (PyType_Ready(&PyLdbMessage) < 0)
3277                 return;
3278
3279         if (PyType_Ready(&PyLdbMessageElement) < 0)
3280                 return;
3281
3282         if (PyType_Ready(&PyLdb) < 0)
3283                 return;
3284
3285         if (PyType_Ready(&PyLdbModule) < 0)
3286                 return;
3287
3288         if (PyType_Ready(&PyLdbTree) < 0)
3289                 return;
3290
3291         if (PyType_Ready(&PyLdbResult) < 0)
3292                 return;
3293
3294         if (PyType_Ready(&PyLdbControl) < 0)
3295                 return;
3296
3297         m = Py_InitModule3("ldb", py_ldb_global_methods, 
3298                 "An interface to LDB, a LDAP-like API that can either to talk an embedded database (TDB-based) or a standards-compliant LDAP server.");
3299         if (m == NULL)
3300                 return;
3301
3302         PyModule_AddObject(m, "SEQ_HIGHEST_SEQ", PyInt_FromLong(LDB_SEQ_HIGHEST_SEQ));
3303         PyModule_AddObject(m, "SEQ_HIGHEST_TIMESTAMP", PyInt_FromLong(LDB_SEQ_HIGHEST_TIMESTAMP));
3304         PyModule_AddObject(m, "SEQ_NEXT", PyInt_FromLong(LDB_SEQ_NEXT));
3305         PyModule_AddObject(m, "SCOPE_DEFAULT", PyInt_FromLong(LDB_SCOPE_DEFAULT));
3306         PyModule_AddObject(m, "SCOPE_BASE", PyInt_FromLong(LDB_SCOPE_BASE));
3307         PyModule_AddObject(m, "SCOPE_ONELEVEL", PyInt_FromLong(LDB_SCOPE_ONELEVEL));
3308         PyModule_AddObject(m, "SCOPE_SUBTREE", PyInt_FromLong(LDB_SCOPE_SUBTREE));
3309
3310         PyModule_AddObject(m, "CHANGETYPE_NONE", PyInt_FromLong(LDB_CHANGETYPE_NONE));
3311         PyModule_AddObject(m, "CHANGETYPE_ADD", PyInt_FromLong(LDB_CHANGETYPE_ADD));
3312         PyModule_AddObject(m, "CHANGETYPE_DELETE", PyInt_FromLong(LDB_CHANGETYPE_DELETE));
3313         PyModule_AddObject(m, "CHANGETYPE_MODIFY", PyInt_FromLong(LDB_CHANGETYPE_MODIFY));
3314
3315         PyModule_AddObject(m, "FLAG_MOD_ADD", PyInt_FromLong(LDB_FLAG_MOD_ADD));
3316         PyModule_AddObject(m, "FLAG_MOD_REPLACE", PyInt_FromLong(LDB_FLAG_MOD_REPLACE));
3317         PyModule_AddObject(m, "FLAG_MOD_DELETE", PyInt_FromLong(LDB_FLAG_MOD_DELETE));
3318
3319         PyModule_AddObject(m, "SUCCESS", PyInt_FromLong(LDB_SUCCESS));
3320         PyModule_AddObject(m, "ERR_OPERATIONS_ERROR", PyInt_FromLong(LDB_ERR_OPERATIONS_ERROR));
3321         PyModule_AddObject(m, "ERR_PROTOCOL_ERROR", PyInt_FromLong(LDB_ERR_PROTOCOL_ERROR));
3322         PyModule_AddObject(m, "ERR_TIME_LIMIT_EXCEEDED", PyInt_FromLong(LDB_ERR_TIME_LIMIT_EXCEEDED));
3323         PyModule_AddObject(m, "ERR_SIZE_LIMIT_EXCEEDED", PyInt_FromLong(LDB_ERR_SIZE_LIMIT_EXCEEDED));
3324         PyModule_AddObject(m, "ERR_COMPARE_FALSE", PyInt_FromLong(LDB_ERR_COMPARE_FALSE));
3325         PyModule_AddObject(m, "ERR_COMPARE_TRUE", PyInt_FromLong(LDB_ERR_COMPARE_TRUE));
3326         PyModule_AddObject(m, "ERR_AUTH_METHOD_NOT_SUPPORTED", PyInt_FromLong(LDB_ERR_AUTH_METHOD_NOT_SUPPORTED));
3327         PyModule_AddObject(m, "ERR_STRONG_AUTH_REQUIRED", PyInt_FromLong(LDB_ERR_STRONG_AUTH_REQUIRED));
3328         PyModule_AddObject(m, "ERR_REFERRAL", PyInt_FromLong(LDB_ERR_REFERRAL));
3329         PyModule_AddObject(m, "ERR_ADMIN_LIMIT_EXCEEDED", PyInt_FromLong(LDB_ERR_ADMIN_LIMIT_EXCEEDED));
3330         PyModule_AddObject(m, "ERR_UNSUPPORTED_CRITICAL_EXTENSION", PyInt_FromLong(LDB_ERR_UNSUPPORTED_CRITICAL_EXTENSION));
3331         PyModule_AddObject(m, "ERR_CONFIDENTIALITY_REQUIRED", PyInt_FromLong(LDB_ERR_CONFIDENTIALITY_REQUIRED));
3332         PyModule_AddObject(m, "ERR_SASL_BIND_IN_PROGRESS", PyInt_FromLong(LDB_ERR_SASL_BIND_IN_PROGRESS));
3333         PyModule_AddObject(m, "ERR_NO_SUCH_ATTRIBUTE", PyInt_FromLong(LDB_ERR_NO_SUCH_ATTRIBUTE));
3334         PyModule_AddObject(m, "ERR_UNDEFINED_ATTRIBUTE_TYPE", PyInt_FromLong(LDB_ERR_UNDEFINED_ATTRIBUTE_TYPE));
3335         PyModule_AddObject(m, "ERR_INAPPROPRIATE_MATCHING", PyInt_FromLong(LDB_ERR_INAPPROPRIATE_MATCHING));
3336         PyModule_AddObject(m, "ERR_CONSTRAINT_VIOLATION", PyInt_FromLong(LDB_ERR_CONSTRAINT_VIOLATION));
3337         PyModule_AddObject(m, "ERR_ATTRIBUTE_OR_VALUE_EXISTS", PyInt_FromLong(LDB_ERR_ATTRIBUTE_OR_VALUE_EXISTS));
3338         PyModule_AddObject(m, "ERR_INVALID_ATTRIBUTE_SYNTAX", PyInt_FromLong(LDB_ERR_INVALID_ATTRIBUTE_SYNTAX));
3339         PyModule_AddObject(m, "ERR_NO_SUCH_OBJECT", PyInt_FromLong(LDB_ERR_NO_SUCH_OBJECT));
3340         PyModule_AddObject(m, "ERR_ALIAS_PROBLEM", PyInt_FromLong(LDB_ERR_ALIAS_PROBLEM));
3341         PyModule_AddObject(m, "ERR_INVALID_DN_SYNTAX", PyInt_FromLong(LDB_ERR_INVALID_DN_SYNTAX));
3342         PyModule_AddObject(m, "ERR_ALIAS_DEREFERINCING_PROBLEM", PyInt_FromLong(LDB_ERR_ALIAS_DEREFERENCING_PROBLEM));
3343         PyModule_AddObject(m, "ERR_INAPPROPRIATE_AUTHENTICATION", PyInt_FromLong(LDB_ERR_INAPPROPRIATE_AUTHENTICATION));
3344         PyModule_AddObject(m, "ERR_INVALID_CREDENTIALS", PyInt_FromLong(LDB_ERR_INVALID_CREDENTIALS));
3345         PyModule_AddObject(m, "ERR_INSUFFICIENT_ACCESS_RIGHTS", PyInt_FromLong(LDB_ERR_INSUFFICIENT_ACCESS_RIGHTS));
3346         PyModule_AddObject(m, "ERR_BUSY", PyInt_FromLong(LDB_ERR_BUSY));
3347         PyModule_AddObject(m, "ERR_UNAVAILABLE", PyInt_FromLong(LDB_ERR_UNAVAILABLE));
3348         PyModule_AddObject(m, "ERR_UNWILLING_TO_PERFORM", PyInt_FromLong(LDB_ERR_UNWILLING_TO_PERFORM));
3349         PyModule_AddObject(m, "ERR_LOOP_DETECT", PyInt_FromLong(LDB_ERR_LOOP_DETECT));
3350         PyModule_AddObject(m, "ERR_NAMING_VIOLATION", PyInt_FromLong(LDB_ERR_NAMING_VIOLATION));
3351         PyModule_AddObject(m, "ERR_OBJECT_CLASS_VIOLATION", PyInt_FromLong(LDB_ERR_OBJECT_CLASS_VIOLATION));
3352         PyModule_AddObject(m, "ERR_NOT_ALLOWED_ON_NON_LEAF", PyInt_FromLong(LDB_ERR_NOT_ALLOWED_ON_NON_LEAF));
3353         PyModule_AddObject(m, "ERR_NOT_ALLOWED_ON_RDN", PyInt_FromLong(LDB_ERR_NOT_ALLOWED_ON_RDN));
3354         PyModule_AddObject(m, "ERR_ENTRY_ALREADY_EXISTS", PyInt_FromLong(LDB_ERR_ENTRY_ALREADY_EXISTS));
3355         PyModule_AddObject(m, "ERR_OBJECT_CLASS_MODS_PROHIBITED", PyInt_FromLong(LDB_ERR_OBJECT_CLASS_MODS_PROHIBITED));
3356         PyModule_AddObject(m, "ERR_AFFECTS_MULTIPLE_DSAS", PyInt_FromLong(LDB_ERR_AFFECTS_MULTIPLE_DSAS));
3357         PyModule_AddObject(m, "ERR_OTHER", PyInt_FromLong(LDB_ERR_OTHER));
3358
3359         PyModule_AddObject(m, "FLG_RDONLY", PyInt_FromLong(LDB_FLG_RDONLY));
3360         PyModule_AddObject(m, "FLG_NOSYNC", PyInt_FromLong(LDB_FLG_NOSYNC));
3361         PyModule_AddObject(m, "FLG_RECONNECT", PyInt_FromLong(LDB_FLG_RECONNECT));
3362         PyModule_AddObject(m, "FLG_NOMMAP", PyInt_FromLong(LDB_FLG_NOMMAP));
3363
3364         PyModule_AddObject(m, "__docformat__", PyString_FromString("restructuredText"));
3365
3366         PyExc_LdbError = PyErr_NewException(discard_const_p(char, "_ldb.LdbError"), NULL, NULL);
3367         PyModule_AddObject(m, "LdbError", PyExc_LdbError);
3368
3369         Py_INCREF(&PyLdb);
3370         Py_INCREF(&PyLdbDn);
3371         Py_INCREF(&PyLdbModule);
3372         Py_INCREF(&PyLdbMessage);
3373         Py_INCREF(&PyLdbMessageElement);
3374         Py_INCREF(&PyLdbTree);
3375         Py_INCREF(&PyLdbResult);
3376         Py_INCREF(&PyLdbControl);
3377
3378         PyModule_AddObject(m, "Ldb", (PyObject *)&PyLdb);
3379         PyModule_AddObject(m, "Dn", (PyObject *)&PyLdbDn);
3380         PyModule_AddObject(m, "Message", (PyObject *)&PyLdbMessage);
3381         PyModule_AddObject(m, "MessageElement", (PyObject *)&PyLdbMessageElement);
3382         PyModule_AddObject(m, "Module", (PyObject *)&PyLdbModule);
3383         PyModule_AddObject(m, "Tree", (PyObject *)&PyLdbTree);
3384         PyModule_AddObject(m, "Control", (PyObject *)&PyLdbControl);
3385
3386         PyModule_AddObject(m, "__version__", PyString_FromString(PACKAGE_VERSION));
3387
3388 #define ADD_LDB_STRING(val)  PyModule_AddObject(m, #val, PyString_FromString(LDB_## val))
3389
3390         ADD_LDB_STRING(SYNTAX_DN);
3391         ADD_LDB_STRING(SYNTAX_DN);
3392         ADD_LDB_STRING(SYNTAX_DIRECTORY_STRING);
3393         ADD_LDB_STRING(SYNTAX_INTEGER);
3394         ADD_LDB_STRING(SYNTAX_BOOLEAN);
3395         ADD_LDB_STRING(SYNTAX_OCTET_STRING);
3396         ADD_LDB_STRING(SYNTAX_UTC_TIME);
3397         ADD_LDB_STRING(OID_COMPARATOR_AND);
3398         ADD_LDB_STRING(OID_COMPARATOR_OR);
3399 }