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