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