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