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