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