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