Merge branch 'master' into wspp-schema
[ira/wip.git] / source4 / lib / ldb / pyldb.c
1 /*
2    Unix SMB/CIFS implementation.
3
4    Swig 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-2009 Jelmer Vernooij <jelmer@samba.org>
9
10          ** NOTE! The following LGPL license applies to the ldb
11          ** library. This does NOT imply that all of Samba is released
12          ** under the LGPL
13    
14    This library is free software; you can redistribute it and/or
15    modify it under the terms of the GNU Lesser General Public
16    License as published by the Free Software Foundation; either
17    version 3 of the License, or (at your option) any later version.
18
19    This library is distributed in the hope that it will be useful,
20    but WITHOUT ANY WARRANTY; without even the implied warranty of
21    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
22    Lesser General Public License for more details.
23
24    You should have received a copy of the GNU Lesser General Public
25    License along with this library; if not, see <http://www.gnu.org/licenses/>.
26 */
27
28 #include "replace.h"
29 #include "ldb_private.h"
30 #include <Python.h>
31 #include "pyldb.h"
32
33 /* There's no Py_ssize_t in 2.4, apparently */
34 #if PY_MAJOR_VERSION == 2 && PY_MINOR_VERSION < 5
35 typedef int Py_ssize_t;
36 typedef inquiry lenfunc;
37 typedef intargfunc ssizeargfunc;
38 #endif
39
40 #ifndef Py_RETURN_NONE
41 #define Py_RETURN_NONE return Py_INCREF(Py_None), Py_None
42 #endif
43
44 /* Picked out of thin air. To do this properly, we should probably have some part of the 
45  * errors in LDB be allocated to bindings ? */
46 #define LDB_ERR_PYTHON_EXCEPTION        142
47
48 static PyObject *PyExc_LdbError;
49
50 void PyErr_SetLdbError(int ret, struct ldb_context *ldb_ctx)
51 {
52         if (ret == LDB_ERR_PYTHON_EXCEPTION)
53                 return; /* Python exception should already be set, just keep that */
54         PyErr_SetObject(PyExc_LdbError, Py_BuildValue(discard_const_p(char, "(i,s)"),
55                         ret, ldb_ctx == NULL?ldb_strerror(ret):ldb_errstring(ldb_ctx)));
56 }
57
58 static PyObject *PyObject_FromLdbValue(struct ldb_context *ldb_ctx, 
59                                                            struct ldb_message_element *el, 
60                                                            struct ldb_val *val)
61 {
62         const struct ldb_schema_attribute *a;
63         struct ldb_val new_val;
64         TALLOC_CTX *mem_ctx = talloc_new(NULL);
65         PyObject *ret;
66         
67         new_val = *val;
68
69         ret = PyString_FromStringAndSize((const char *)new_val.data, new_val.length);
70         
71         talloc_free(mem_ctx);
72         
73         return ret;
74 }
75
76 /**
77  * Obtain a ldb DN from a Python object.
78  *
79  * @param mem_ctx Memory context
80  * @param object Python object
81  * @param ldb_ctx LDB context
82  * @return Whether or not the conversion succeeded
83  */
84 bool PyObject_AsDn(TALLOC_CTX *mem_ctx, PyObject *object, 
85                    struct ldb_context *ldb_ctx, struct ldb_dn **dn)
86 {
87         struct ldb_dn *odn;
88
89         if (ldb_ctx != NULL && PyString_Check(object)) {
90                 odn = ldb_dn_new(mem_ctx, ldb_ctx, PyString_AsString(object));
91                 *dn = odn;
92                 return true;
93         }
94
95         if (PyLdbDn_Check(object)) {
96                 *dn = PyLdbDn_AsDn(object);
97                 return true;
98         }
99
100         PyErr_SetString(PyExc_TypeError, "Expected DN");
101         return false;
102 }
103
104 /**
105  * Create a Python object from a ldb_result.
106  *
107  * @param result LDB result to convert
108  * @return Python object with converted result (a list object)
109  */
110 static PyObject *PyLdbResult_FromResult(struct ldb_result *result)
111 {
112         PyObject *ret;
113         int i;
114         if (result == NULL) {
115                 Py_RETURN_NONE;
116         } 
117         ret = PyList_New(result->count);
118         for (i = 0; i < result->count; i++) {
119                 PyList_SetItem(ret, i, PyLdbMessage_FromMessage(result->msgs[i])
120                 );
121         }
122         return ret;
123 }
124
125 /**
126  * Create a LDB Result from a Python object. 
127  * If conversion fails, NULL will be returned and a Python exception set.
128  *
129  * @param mem_ctx Memory context in which to allocate the LDB Result
130  * @param obj Python object to convert
131  * @return a ldb_result, or NULL if the conversion failed
132  */
133 static struct ldb_result *PyLdbResult_AsResult(TALLOC_CTX *mem_ctx, 
134                                                                                            PyObject *obj)
135 {
136         struct ldb_result *res;
137         int i;
138         
139         if (obj == Py_None)
140                 return NULL;
141
142         res = talloc_zero(mem_ctx, struct ldb_result);
143         res->count = PyList_Size(obj);
144         res->msgs = talloc_array(res, struct ldb_message *, res->count);
145         for (i = 0; i < res->count; i++) {
146                 PyObject *item = PyList_GetItem(obj, i);
147                 res->msgs[i] = PyLdbMessage_AsMessage(item);
148         }
149         return res;
150 }
151
152 static PyObject *py_ldb_dn_validate(PyLdbDnObject *self)
153 {
154         return PyBool_FromLong(ldb_dn_validate(self->dn));
155 }
156
157 static PyObject *py_ldb_dn_is_valid(PyLdbDnObject *self)
158 {
159         return PyBool_FromLong(ldb_dn_is_valid(self->dn));
160 }
161
162 static PyObject *py_ldb_dn_is_special(PyLdbDnObject *self)
163 {
164         return PyBool_FromLong(ldb_dn_is_special(self->dn));
165 }
166
167 static PyObject *py_ldb_dn_is_null(PyLdbDnObject *self)
168 {
169         return PyBool_FromLong(ldb_dn_is_null(self->dn));
170 }
171  
172 static PyObject *py_ldb_dn_get_casefold(PyLdbDnObject *self)
173 {
174         return PyString_FromString(ldb_dn_get_casefold(self->dn));
175 }
176
177 static PyObject *py_ldb_dn_get_linearized(PyLdbDnObject *self)
178 {
179         return PyString_FromString(ldb_dn_get_linearized(self->dn));
180 }
181
182 static PyObject *py_ldb_dn_canonical_str(PyLdbDnObject *self)
183 {
184         return PyString_FromString(ldb_dn_canonical_string(self->dn, self->dn));
185 }
186
187 static PyObject *py_ldb_dn_canonical_ex_str(PyLdbDnObject *self)
188 {
189         return PyString_FromString(ldb_dn_canonical_ex_string(self->dn, self->dn));
190 }
191
192 static PyObject *py_ldb_dn_repr(PyLdbDnObject *self)
193 {
194         return PyString_FromFormat("Dn(%s)", PyObject_REPR(PyString_FromString(ldb_dn_get_linearized(self->dn))));
195 }
196
197 static PyObject *py_ldb_dn_check_special(PyLdbDnObject *self, PyObject *args)
198 {
199         char *name;
200
201         if (!PyArg_ParseTuple(args, "s", &name))
202                 return NULL;
203
204         return ldb_dn_check_special(self->dn, name)?Py_True:Py_False;
205 }
206
207 static int py_ldb_dn_compare(PyLdbDnObject *dn1, PyLdbDnObject *dn2)
208 {
209         return ldb_dn_compare(dn1->dn, dn2->dn);
210 }
211
212 static PyObject *py_ldb_dn_get_parent(PyLdbDnObject *self)
213 {
214         struct ldb_dn *dn = PyLdbDn_AsDn((PyObject *)self);
215         return PyLdbDn_FromDn(ldb_dn_get_parent(NULL, dn));
216 }
217
218 #define dn_ldb_ctx(dn) ((struct ldb_context *)dn)
219
220 static PyObject *py_ldb_dn_add_child(PyLdbDnObject *self, PyObject *args)
221 {
222         PyObject *py_other;
223         struct ldb_dn *dn, *other;
224         if (!PyArg_ParseTuple(args, "O", &py_other))
225                 return NULL;
226
227         dn = PyLdbDn_AsDn((PyObject *)self);
228
229         if (!PyObject_AsDn(NULL, py_other, dn_ldb_ctx(dn), &other))
230                 return NULL;
231
232         return ldb_dn_add_child(dn, other)?Py_True:Py_False;
233 }
234
235 static PyObject *py_ldb_dn_add_base(PyLdbDnObject *self, PyObject *args)
236 {
237         PyObject *py_other;
238         struct ldb_dn *other, *dn;
239         if (!PyArg_ParseTuple(args, "O", &py_other))
240                 return NULL;
241
242         dn = PyLdbDn_AsDn((PyObject *)self);
243
244         if (!PyObject_AsDn(NULL, py_other, dn_ldb_ctx(dn), &other))
245                 return NULL;
246
247         return ldb_dn_add_base(dn, other)?Py_True:Py_False;
248 }
249
250 static PyMethodDef py_ldb_dn_methods[] = {
251         { "validate", (PyCFunction)py_ldb_dn_validate, METH_NOARGS, 
252                 "S.validate() -> bool\n"
253                 "Validate DN is correct." },
254         { "is_valid", (PyCFunction)py_ldb_dn_is_valid, METH_NOARGS,
255                 "S.is_valid() -> bool\n" },
256         { "is_special", (PyCFunction)py_ldb_dn_is_special, METH_NOARGS,
257                 "S.is_special() -> bool\n"
258                 "Check whether this is a special LDB DN." },
259         { "is_null", (PyCFunction)py_ldb_dn_is_null, METH_NOARGS,
260                 "Check whether this is a null DN." },
261         { "get_casefold", (PyCFunction)py_ldb_dn_get_casefold, METH_NOARGS,
262                 NULL },
263         { "get_linearized", (PyCFunction)py_ldb_dn_get_linearized, METH_NOARGS,
264                 NULL },
265         { "canonical_str", (PyCFunction)py_ldb_dn_canonical_str, METH_NOARGS,
266                 "S.canonical_str() -> string\n"
267                 "Canonical version of this DN (like a posix path)." },
268         { "canonical_ex_str", (PyCFunction)py_ldb_dn_canonical_ex_str, METH_NOARGS,
269                 "S.canonical_ex_str() -> string\n"
270                 "Canonical version of this DN (like a posix path, with terminating newline)." },
271         { "check_special", (PyCFunction)py_ldb_dn_is_special, METH_VARARGS, 
272                 NULL },
273         { "parent", (PyCFunction)py_ldb_dn_get_parent, METH_NOARGS,
274                 "S.parent() -> dn\n"
275                 "Get the parent for this DN." },
276         { "add_child", (PyCFunction)py_ldb_dn_add_child, METH_VARARGS, 
277                 "S.add_child(dn) -> None\n"
278                 "Add a child DN to this DN." },
279         { "add_base", (PyCFunction)py_ldb_dn_add_base, METH_VARARGS,
280                 "S.add_base(dn) -> None\n"
281                 "Add a base DN to this DN." },
282         { "check_special", (PyCFunction)py_ldb_dn_check_special, METH_VARARGS,
283                 NULL },
284         { NULL }
285 };
286
287 static Py_ssize_t py_ldb_dn_len(PyLdbDnObject *self)
288 {
289         return ldb_dn_get_comp_num(PyLdbDn_AsDn((PyObject *)self));
290 }
291
292 static PyObject *py_ldb_dn_concat(PyLdbDnObject *self, PyObject *py_other)
293 {
294         struct ldb_dn *dn = PyLdbDn_AsDn((PyObject *)self), 
295                                   *other;
296         struct ldb_dn *ret = ldb_dn_copy(NULL, dn);
297         if (!PyObject_AsDn(NULL, py_other, NULL, &other))
298                 return NULL;
299         ldb_dn_add_child(ret, other);
300         return PyLdbDn_FromDn(ret);
301 }
302
303 static PySequenceMethods py_ldb_dn_seq = {
304         .sq_length = (lenfunc)py_ldb_dn_len,
305         .sq_concat = (binaryfunc)py_ldb_dn_concat,
306 };
307
308 static PyObject *py_ldb_dn_new(PyTypeObject *type, PyObject *args, PyObject *kwargs)
309 {
310         struct ldb_dn *ret;
311         char *str;
312         PyObject *py_ldb;
313         struct ldb_context *ldb_ctx;
314         PyLdbDnObject *py_ret;
315         const char * const kwnames[] = { "ldb", "dn", NULL };
316
317         if (!PyArg_ParseTupleAndKeywords(args, kwargs, "Os",
318                                          discard_const_p(char *, kwnames),
319                                          &py_ldb, &str))
320                 return NULL;
321
322         ldb_ctx = PyLdb_AsLdbContext(py_ldb);
323         
324         ret = ldb_dn_new(ldb_ctx, ldb_ctx, str);
325         /* ldb_dn_new() doesn't accept NULL as memory context, so 
326            we do it this way... */
327         talloc_steal(NULL, ret);
328
329         if (ret == NULL || !ldb_dn_validate(ret)) {
330                 PyErr_SetString(PyExc_ValueError, "unable to parse dn string");
331                 return NULL;
332         }
333
334         py_ret = (PyLdbDnObject *)type->tp_alloc(type, 0);
335         if (ret == NULL) {
336                 PyErr_NoMemory();
337                 return NULL;
338         }
339         py_ret->dn = ret;
340         return (PyObject *)py_ret;
341 }
342
343 PyObject *PyLdbDn_FromDn(struct ldb_dn *dn)
344 {
345         PyLdbDnObject *py_ret;
346         py_ret = (PyLdbDnObject *)PyLdbDn.tp_alloc(&PyLdbDn, 0);
347         if (py_ret == NULL) {
348                 PyErr_NoMemory();
349                 return NULL;
350         }
351         py_ret->mem_ctx = talloc_new(NULL);
352         py_ret->dn = talloc_reference(py_ret->mem_ctx, dn);
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 = "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(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(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(ldb_transaction_commit(PyLdb_AsLdbContext(self)), PyLdb_AsLdbContext(self));
429         Py_RETURN_NONE;
430 }
431
432 static PyObject *py_ldb_transaction_cancel(PyLdbObject *self)
433 {
434         PyErr_LDB_ERROR_IS_ERR_RAISE(ldb_transaction_cancel(PyLdb_AsLdbContext(self)), PyLdb_AsLdbContext(self));
435         Py_RETURN_NONE;
436 }
437
438 static PyObject *py_ldb_setup_wellknown_attributes(PyLdbObject *self)
439 {
440         PyErr_LDB_ERROR_IS_ERR_RAISE(ldb_setup_wellknown_attributes(PyLdb_AsLdbContext(self)), PyLdb_AsLdbContext(self));
441         Py_RETURN_NONE;
442 }
443
444 static PyObject *py_ldb_repr(PyLdbObject *self)
445 {
446         return PyString_FromFormat("<ldb connection>");
447 }
448
449 static PyObject *py_ldb_get_root_basedn(PyLdbObject *self)
450 {
451         struct ldb_dn *dn = ldb_get_root_basedn(PyLdb_AsLdbContext(self));
452         if (dn == NULL)
453                 Py_RETURN_NONE;
454         return PyLdbDn_FromDn(dn);
455 }
456
457
458 static PyObject *py_ldb_get_schema_basedn(PyLdbObject *self)
459 {
460         struct ldb_dn *dn = ldb_get_schema_basedn(PyLdb_AsLdbContext(self));
461         if (dn == NULL)
462                 Py_RETURN_NONE;
463         return PyLdbDn_FromDn(dn);
464 }
465
466 static PyObject *py_ldb_get_config_basedn(PyLdbObject *self)
467 {
468         struct ldb_dn *dn = ldb_get_config_basedn(PyLdb_AsLdbContext(self));
469         if (dn == NULL)
470                 Py_RETURN_NONE;
471         return PyLdbDn_FromDn(dn);
472 }
473
474 static PyObject *py_ldb_get_default_basedn(PyLdbObject *self)
475 {
476         struct ldb_dn *dn = ldb_get_default_basedn(PyLdb_AsLdbContext(self));
477         if (dn == NULL)
478                 Py_RETURN_NONE;
479         return PyLdbDn_FromDn(dn);
480 }
481
482 static const char **PyList_AsStringList(TALLOC_CTX *mem_ctx, PyObject *list, 
483                                                                                 const char *paramname)
484 {
485         const char **ret;
486         int i;
487         if (!PyList_Check(list)) {
488                 PyErr_Format(PyExc_TypeError, "%s is not a list", paramname);
489                 return NULL;
490         }
491         ret = talloc_array(NULL, const char *, PyList_Size(list)+1);
492         for (i = 0; i < PyList_Size(list); i++) {
493                 PyObject *item = PyList_GetItem(list, i);
494                 if (!PyString_Check(item)) {
495                         PyErr_Format(PyExc_TypeError, "%s should be strings", paramname);
496                         return NULL;
497                 }
498                 ret[i] = PyString_AsString(item);
499         }
500         ret[i] = NULL;
501         return ret;
502 }
503
504 static int py_ldb_init(PyLdbObject *self, PyObject *args, PyObject *kwargs)
505 {
506         const char * const kwnames[] = { "url", "flags", "options", NULL };
507         char *url = NULL;
508         PyObject *py_options = Py_None;
509         const char **options;
510         int flags = 0;
511         int ret;
512         struct ldb_context *ldb;
513
514         if (!PyArg_ParseTupleAndKeywords(args, kwargs, "|ziO:Ldb.__init__",
515                                          discard_const_p(char *, kwnames),
516                                          &url, &flags, &py_options))
517                 return -1;
518
519         ldb = PyLdb_AsLdbContext(self);
520
521         if (py_options == Py_None) {
522                 options = NULL;
523         } else {
524                 options = PyList_AsStringList(ldb, py_options, "options");
525                 if (options == NULL)
526                         return -1;
527         }
528         
529         if (url != NULL) {
530                 ret = ldb_connect(ldb, url, flags, options);
531                 if (ret != LDB_SUCCESS) {
532                         PyErr_SetLdbError(ret, ldb);
533                         return -1;
534                 }
535         }
536
537         talloc_free(options);
538         return 0;
539 }
540
541 static PyObject *py_ldb_new(PyTypeObject *type, PyObject *args, PyObject *kwargs)
542 {
543         PyLdbObject *ret;
544         struct ldb_context *ldb;
545         ldb = ldb_init(NULL, NULL);
546         if (ldb == NULL) {
547                 PyErr_NoMemory();
548                 return NULL;
549         }
550
551         ret = (PyLdbObject *)type->tp_alloc(type, 0);
552         if (ret == NULL) {
553                 PyErr_NoMemory();
554                 return NULL;
555         }
556         ret->ldb_ctx = ldb;
557         return (PyObject *)ret;
558 }
559
560 static PyObject *py_ldb_connect(PyLdbObject *self, PyObject *args, PyObject *kwargs)
561 {
562         char *url;
563         int flags = 0;
564         PyObject *py_options = Py_None;
565         int ret;
566         const char **options;
567         const char * const kwnames[] = { "url", "flags", "options", NULL };
568
569         if (!PyArg_ParseTupleAndKeywords(args, kwargs, "s|iO",
570                                          discard_const_p(char *, kwnames),
571                                          &url, &flags, &py_options))
572                 return NULL;
573
574         if (py_options == Py_None) {
575                 options = NULL;
576         } else {
577                 options = PyList_AsStringList(NULL, py_options, "options");
578                 if (options == NULL)
579                         return NULL;
580         }
581         
582         ret = ldb_connect(PyLdb_AsLdbContext(self), url, flags, options);
583         talloc_free(options);
584
585         PyErr_LDB_ERROR_IS_ERR_RAISE(ret, PyLdb_AsLdbContext(self));
586
587         Py_RETURN_NONE;
588 }
589
590 static PyObject *py_ldb_modify(PyLdbObject *self, PyObject *args)
591 {
592         PyObject *py_msg;
593         int ret;
594         if (!PyArg_ParseTuple(args, "O", &py_msg))
595                 return NULL;
596
597         if (!PyLdbMessage_Check(py_msg)) {
598                 PyErr_SetString(PyExc_TypeError, "Expected Ldb Message");
599                 return NULL;
600         }
601
602         ret = ldb_modify(PyLdb_AsLdbContext(self), PyLdbMessage_AsMessage(py_msg));
603         PyErr_LDB_ERROR_IS_ERR_RAISE(ret, PyLdb_AsLdbContext(self));
604
605         Py_RETURN_NONE;
606 }
607
608 static PyObject *py_ldb_add(PyLdbObject *self, PyObject *args)
609 {
610         PyObject *py_msg;
611         int ret;
612         Py_ssize_t dict_pos, msg_pos;
613         struct ldb_message_element *msgel;
614         struct ldb_message *msg;
615         PyObject *key, *value;
616
617         if (!PyArg_ParseTuple(args, "O", &py_msg))
618                 return NULL;
619
620         if (PyDict_Check(py_msg)) {
621                 PyObject *dn_value = PyDict_GetItemString(py_msg, "dn");
622                 msg = ldb_msg_new(NULL);
623                 msg->elements = talloc_zero_array(msg, struct ldb_message_element, PyDict_Size(py_msg));
624                 msg_pos = dict_pos = 0;
625                 if (dn_value) {
626                         if (!PyObject_AsDn(msg, dn_value, PyLdb_AsLdbContext(self), &msg->dn)) {
627                                 PyErr_SetString(PyExc_TypeError, "unable to import dn object");
628                                 return NULL;
629                         }
630                         if (msg->dn == NULL) {
631                                 PyErr_SetString(PyExc_TypeError, "dn set but not found");
632                                 return NULL;
633                         }
634                 }
635
636                 while (PyDict_Next(py_msg, &dict_pos, &key, &value)) {
637                         char *key_str = PyString_AsString(key);
638                         if (strcmp(key_str, "dn") != 0) {
639                                 msgel = PyObject_AsMessageElement(msg->elements, value, 0, key_str);
640                                 if (msgel == NULL) {
641                                         PyErr_SetString(PyExc_TypeError, "unable to import element");
642                                         return NULL;
643                                 }
644                                 memcpy(&msg->elements[msg_pos], msgel, sizeof(*msgel));
645                                 msg_pos++;
646                         }
647                 }
648
649                 if (msg->dn == NULL) {
650                         PyErr_SetString(PyExc_TypeError, "no dn set");
651                         return NULL;
652                 }
653
654                 msg->num_elements = msg_pos;
655         } else {
656                 msg = PyLdbMessage_AsMessage(py_msg);
657         }
658         
659         ret = ldb_add(PyLdb_AsLdbContext(self), msg);
660         PyErr_LDB_ERROR_IS_ERR_RAISE(ret, PyLdb_AsLdbContext(self));
661
662         Py_RETURN_NONE;
663 }
664
665 static PyObject *py_ldb_delete(PyLdbObject *self, PyObject *args)
666 {
667         PyObject *py_dn;
668         struct ldb_dn *dn;
669         int ret;
670         struct ldb_context *ldb;
671         if (!PyArg_ParseTuple(args, "O", &py_dn))
672                 return NULL;
673
674         ldb = PyLdb_AsLdbContext(self);
675
676         if (!PyObject_AsDn(NULL, py_dn, ldb, &dn))
677                 return NULL;
678
679         ret = ldb_delete(ldb, dn);
680         PyErr_LDB_ERROR_IS_ERR_RAISE(ret, ldb);
681
682         Py_RETURN_NONE;
683 }
684
685 static PyObject *py_ldb_rename(PyLdbObject *self, PyObject *args)
686 {
687         PyObject *py_dn1, *py_dn2;
688         struct ldb_dn *dn1, *dn2;
689         int ret;
690         struct ldb_context *ldb;
691         if (!PyArg_ParseTuple(args, "OO", &py_dn1, &py_dn2))
692                 return NULL;
693
694         ldb = PyLdb_AsLdbContext(self);
695         if (!PyObject_AsDn(NULL, py_dn1, ldb, &dn1))
696                 return NULL;
697
698         if (!PyObject_AsDn(NULL, py_dn2, ldb, &dn2))
699                 return NULL;
700
701         ret = ldb_rename(ldb, dn1, dn2);
702         PyErr_LDB_ERROR_IS_ERR_RAISE(ret, ldb);
703
704         Py_RETURN_NONE;
705 }
706
707 static PyObject *py_ldb_schema_attribute_remove(PyLdbObject *self, PyObject *args)
708 {
709         char *name;
710         if (!PyArg_ParseTuple(args, "s", &name))
711                 return NULL;
712
713         ldb_schema_attribute_remove(PyLdb_AsLdbContext(self), name);
714
715         Py_RETURN_NONE;
716 }
717
718 static PyObject *py_ldb_schema_attribute_add(PyLdbObject *self, PyObject *args)
719 {
720         char *attribute, *syntax;
721         unsigned int flags;
722         int ret;
723         if (!PyArg_ParseTuple(args, "sIs", &attribute, &flags, &syntax))
724                 return NULL;
725
726         ret = ldb_schema_attribute_add(PyLdb_AsLdbContext(self), attribute, flags, syntax);
727
728         PyErr_LDB_ERROR_IS_ERR_RAISE(ret, PyLdb_AsLdbContext(self));
729
730         Py_RETURN_NONE;
731 }
732
733 static PyObject *ldb_ldif_to_pyobject(struct ldb_ldif *ldif)
734 {
735         if (ldif == NULL) {
736                 Py_RETURN_NONE;
737         } else {
738         /* We don't want this attached to the 'ldb' any more */
739                 talloc_steal(NULL, ldif);
740                 return Py_BuildValue(discard_const_p(char, "(iO)"),
741                                      ldif->changetype,
742                                      PyLdbMessage_FromMessage(ldif->msg));
743         }
744 }
745
746
747 static PyObject *py_ldb_parse_ldif(PyLdbObject *self, PyObject *args)
748 {
749         PyObject *list;
750         struct ldb_ldif *ldif;
751         const char *s;
752
753         if (!PyArg_ParseTuple(args, "s", &s))
754                 return NULL;
755
756         list = PyList_New(0);
757         while ((ldif = ldb_ldif_read_string(self->ldb_ctx, &s)) != NULL) {
758                 PyList_Append(list, ldb_ldif_to_pyobject(ldif));
759         }
760         return PyObject_GetIter(list);
761 }
762
763 static PyObject *py_ldb_schema_format_value(PyLdbObject *self, PyObject *args)
764 {
765         const struct ldb_schema_attribute *a;
766         struct ldb_val old_val;
767         struct ldb_val new_val;
768         TALLOC_CTX *mem_ctx;
769         PyObject *ret;
770         char *element_name;
771         PyObject *val;
772
773         if (!PyArg_ParseTuple(args, "sO", &element_name, &val))
774                 return NULL;
775         
776         mem_ctx = talloc_new(NULL);
777         
778         old_val.data = (uint8_t *)PyString_AsString(val);
779         old_val.length = PyString_Size(val);
780                 
781         a = ldb_schema_attribute_by_name(PyLdb_AsLdbContext(self), element_name);
782
783         if (a == NULL) {
784                 Py_RETURN_NONE;
785         }
786         
787         if (a->syntax->ldif_write_fn(PyLdb_AsLdbContext(self), mem_ctx, &old_val, &new_val) != 0) {
788                 talloc_free(mem_ctx);
789                 Py_RETURN_NONE;
790         }
791
792         ret = PyString_FromStringAndSize((const char *)new_val.data, new_val.length);
793
794         talloc_free(mem_ctx);
795
796         return ret;
797 }
798
799 static PyObject *py_ldb_search(PyLdbObject *self, PyObject *args, PyObject *kwargs)
800 {
801         PyObject *py_base = Py_None;
802         enum ldb_scope scope = LDB_SCOPE_DEFAULT;
803         char *expr = NULL;
804         PyObject *py_attrs = Py_None;
805         PyObject *py_controls = Py_None;
806         const char * const kwnames[] = { "base", "scope", "expression", "attrs", "controls", NULL };
807         int ret;
808         struct ldb_result *res;
809         struct ldb_request *req;
810         const char **attrs;
811         struct ldb_context *ldb_ctx;
812         struct ldb_control **parsed_controls;
813         struct ldb_dn *base;
814
815         if (!PyArg_ParseTupleAndKeywords(args, kwargs, "|OizOO",
816                                          discard_const_p(char *, kwnames),
817                                          &py_base, &scope, &expr, &py_attrs, &py_controls))
818                 return NULL;
819
820         ldb_ctx = PyLdb_AsLdbContext(self);
821
822         if (py_attrs == Py_None) {
823                 attrs = NULL;
824         } else {
825                 attrs = PyList_AsStringList(ldb_ctx, py_attrs, "attrs");
826                 if (attrs == NULL)
827                         return NULL;
828         }
829
830         if (py_base == Py_None) {
831                 base = ldb_get_default_basedn(ldb_ctx);
832         } else {
833                 if (!PyObject_AsDn(ldb_ctx, py_base, ldb_ctx, &base))
834                         return NULL;
835         }
836
837         if (py_controls == Py_None) {
838                 parsed_controls = NULL;
839         } else {
840                 const char **controls = PyList_AsStringList(ldb_ctx, py_controls, "controls");
841                 parsed_controls = ldb_parse_control_strings(ldb_ctx, ldb_ctx, controls);
842                 talloc_free(controls);
843         }
844
845         res = talloc_zero(ldb_ctx, struct ldb_result);
846         if (res == NULL) {
847                 PyErr_NoMemory();
848                 return NULL;
849         }
850
851         ret = ldb_build_search_req(&req, ldb_ctx, ldb_ctx,
852                                    base,
853                                    scope,
854                                    expr,
855                                    attrs,
856                                    parsed_controls,
857                                    res,
858                                    ldb_search_default_callback,
859                                    NULL);
860
861         if (ret != LDB_SUCCESS) {
862                 talloc_free(res);
863                 PyErr_LDB_ERROR_IS_ERR_RAISE(ret, ldb_ctx);
864                 return NULL;
865         }
866
867         ret = ldb_request(ldb_ctx, req);
868                 
869         if (ret == LDB_SUCCESS) {
870                 ret = ldb_wait(req->handle, LDB_WAIT_ALL);
871         }
872
873         talloc_free(req);
874
875         if (ret != LDB_SUCCESS) {
876                 talloc_free(res);
877                 PyErr_LDB_ERROR_IS_ERR_RAISE(ret, ldb_ctx);
878                 return NULL;
879         }
880
881         return PyLdbResult_FromResult(res);
882 }
883
884 static PyObject *py_ldb_get_opaque(PyLdbObject *self, PyObject *args)
885 {
886         char *name;
887         void *data;
888
889         if (!PyArg_ParseTuple(args, "s", &name))
890                 return NULL;
891
892         data = ldb_get_opaque(PyLdb_AsLdbContext(self), name);
893
894         if (data == NULL)
895                 Py_RETURN_NONE;
896
897         /* FIXME: More interpretation */
898
899         return Py_True;
900 }
901
902 static PyObject *py_ldb_set_opaque(PyLdbObject *self, PyObject *args)
903 {
904         char *name;
905         PyObject *data;
906
907         if (!PyArg_ParseTuple(args, "sO", &name, &data))
908                 return NULL;
909
910         /* FIXME: More interpretation */
911
912         ldb_set_opaque(PyLdb_AsLdbContext(self), name, data);
913
914         Py_RETURN_NONE;
915 }
916
917 static PyObject *py_ldb_modules(PyLdbObject *self)
918 {
919         struct ldb_context *ldb = PyLdb_AsLdbContext(self);
920         PyObject *ret = PyList_New(0);
921         struct ldb_module *mod;
922
923         for (mod = ldb->modules; mod; mod = mod->next) {
924                 PyList_Append(ret, PyLdbModule_FromModule(mod));
925         }
926
927         return ret;
928 }
929
930 static PyMethodDef py_ldb_methods[] = {
931         { "set_debug", (PyCFunction)py_ldb_set_debug, METH_VARARGS, 
932                 "S.set_debug(callback) -> None\n"
933                 "Set callback for LDB debug messages.\n"
934                 "The callback should accept a debug level and debug text." },
935         { "set_create_perms", (PyCFunction)py_ldb_set_create_perms, METH_VARARGS, 
936                 "S.set_create_perms(mode) -> None\n"
937                 "Set mode to use when creating new LDB files." },
938         { "set_modules_dir", (PyCFunction)py_ldb_set_modules_dir, METH_VARARGS,
939                 "S.set_modules_dir(path) -> None\n"
940                 "Set path LDB should search for modules" },
941         { "transaction_start", (PyCFunction)py_ldb_transaction_start, METH_NOARGS, 
942                 "S.transaction_start() -> None\n"
943                 "Start a new transaction." },
944         { "transaction_commit", (PyCFunction)py_ldb_transaction_commit, METH_NOARGS, 
945                 "S.transaction_commit() -> None\n"
946                 "commit a new transaction." },
947         { "transaction_cancel", (PyCFunction)py_ldb_transaction_cancel, METH_NOARGS, 
948                 "S.transaction_cancel() -> None\n"
949                 "cancel a new transaction." },
950         { "setup_wellknown_attributes", (PyCFunction)py_ldb_setup_wellknown_attributes, METH_NOARGS, 
951                 NULL },
952         { "get_root_basedn", (PyCFunction)py_ldb_get_root_basedn, METH_NOARGS,
953                 NULL },
954         { "get_schema_basedn", (PyCFunction)py_ldb_get_schema_basedn, METH_NOARGS,
955                 NULL },
956         { "get_default_basedn", (PyCFunction)py_ldb_get_default_basedn, METH_NOARGS,
957                 NULL },
958         { "get_config_basedn", (PyCFunction)py_ldb_get_config_basedn, METH_NOARGS,
959                 NULL },
960         { "connect", (PyCFunction)py_ldb_connect, METH_VARARGS|METH_KEYWORDS, 
961                 "S.connect(url, flags=0, options=None) -> None\n"
962                 "Connect to a LDB URL." },
963         { "modify", (PyCFunction)py_ldb_modify, METH_VARARGS, 
964                 "S.modify(message) -> None\n"
965                 "Modify an entry." },
966         { "add", (PyCFunction)py_ldb_add, METH_VARARGS, 
967                 "S.add(message) -> None\n"
968                 "Add an entry." },
969         { "delete", (PyCFunction)py_ldb_delete, METH_VARARGS,
970                 "S.delete(dn) -> None\n"
971                 "Remove an entry." },
972         { "rename", (PyCFunction)py_ldb_rename, METH_VARARGS,
973                 "S.rename(old_dn, new_dn) -> None\n"
974                 "Rename an entry." },
975         { "search", (PyCFunction)py_ldb_search, METH_VARARGS|METH_KEYWORDS,
976                 "S.search(base=None, scope=None, expression=None, attrs=None, controls=None) -> msgs\n"
977                 "Search in a database.\n"
978                 "\n"
979                 ":param base: Optional base DN to search\n"
980                 ":param scope: Search scope (SCOPE_BASE, SCOPE_ONELEVEL or SCOPE_SUBTREE)\n"
981                 ":param expression: Optional search expression\n"
982                 ":param attrs: Attributes to return (defaults to all)\n"
983                 ":param controls: Optional list of controls\n"
984                 ":return: Iterator over Message objects\n"
985         },
986         { "schema_attribute_remove", (PyCFunction)py_ldb_schema_attribute_remove, METH_VARARGS,
987                 NULL },
988         { "schema_attribute_add", (PyCFunction)py_ldb_schema_attribute_add, METH_VARARGS,
989                 NULL },
990         { "schema_format_value", (PyCFunction)py_ldb_schema_format_value, METH_VARARGS,
991                 NULL },
992         { "parse_ldif", (PyCFunction)py_ldb_parse_ldif, METH_VARARGS,
993                 "S.parse_ldif(ldif) -> iter(messages)\n"
994                 "Parse a string formatted using LDIF." },
995         { "get_opaque", (PyCFunction)py_ldb_get_opaque, METH_VARARGS,
996                 "S.get_opaque(name) -> value\n"
997                 "Get an opaque value set on this LDB connection. \n"
998                 ":note: The returned value may not be useful in Python."
999         },
1000         { "set_opaque", (PyCFunction)py_ldb_set_opaque, METH_VARARGS,
1001                 "S.set_opaque(name, value) -> None\n"
1002                 "Set an opaque value on this LDB connection. \n"
1003                 ":note: Passing incorrect values may cause crashes." },
1004         { "modules", (PyCFunction)py_ldb_modules, METH_NOARGS,
1005                 "S.modules() -> list\n"
1006                 "Return the list of modules on this LDB connection " },
1007         { NULL },
1008 };
1009
1010 PyObject *PyLdbModule_FromModule(struct ldb_module *mod)
1011 {
1012         PyLdbModuleObject *ret;
1013
1014         ret = (PyLdbModuleObject *)PyLdbModule.tp_alloc(&PyLdbModule, 0);
1015         if (ret == NULL) {
1016                 PyErr_NoMemory();
1017                 return NULL;
1018         }
1019         ret->mem_ctx = talloc_new(NULL);
1020         ret->mod = talloc_reference(ret->mem_ctx, mod);
1021         return (PyObject *)ret;
1022 }
1023
1024 static PyObject *py_ldb_get_firstmodule(PyLdbObject *self, void *closure)
1025 {
1026         return PyLdbModule_FromModule(PyLdb_AsLdbContext(self)->modules);
1027 }
1028
1029 static PyGetSetDef py_ldb_getset[] = {
1030         { discard_const_p(char, "firstmodule"), (getter)py_ldb_get_firstmodule, NULL, NULL },
1031         { NULL }
1032 };
1033
1034 static int py_ldb_contains(PyLdbObject *self, PyObject *obj)
1035 {
1036         struct ldb_context *ldb_ctx = PyLdb_AsLdbContext(self);
1037         struct ldb_dn *dn;
1038         struct ldb_result *result;
1039         int ret;
1040         int count;
1041
1042         if (!PyObject_AsDn(ldb_ctx, obj, ldb_ctx, &dn))
1043                 return -1;
1044
1045         ret = ldb_search(ldb_ctx, ldb_ctx, &result, dn, LDB_SCOPE_BASE, NULL, NULL);
1046         if (ret != LDB_SUCCESS) {
1047                 PyErr_SetLdbError(ret, ldb_ctx);
1048                 return -1;
1049         }
1050
1051         count = result->count;
1052
1053         talloc_free(result);
1054
1055         return count;
1056 }
1057
1058 static PySequenceMethods py_ldb_seq = {
1059         .sq_contains = (objobjproc)py_ldb_contains,
1060 };
1061
1062 PyObject *PyLdb_FromLdbContext(struct ldb_context *ldb_ctx)
1063 {
1064         PyLdbObject *ret;
1065
1066         ret = (PyLdbObject *)PyLdb.tp_alloc(&PyLdb, 0);
1067         if (ret == NULL) {
1068                 PyErr_NoMemory();
1069                 return NULL;
1070         }
1071         ret->mem_ctx = talloc_new(NULL);
1072         ret->ldb_ctx = talloc_reference(ret->mem_ctx, ldb_ctx);
1073         return (PyObject *)ret;
1074 }
1075
1076 static void py_ldb_dealloc(PyLdbObject *self)
1077 {
1078         talloc_free(self->mem_ctx);
1079         self->ob_type->tp_free(self);
1080 }
1081
1082 PyTypeObject PyLdb = {
1083         .tp_name = "Ldb",
1084         .tp_methods = py_ldb_methods,
1085         .tp_repr = (reprfunc)py_ldb_repr,
1086         .tp_new = py_ldb_new,
1087         .tp_init = (initproc)py_ldb_init,
1088         .tp_dealloc = (destructor)py_ldb_dealloc,
1089         .tp_getset = py_ldb_getset,
1090         .tp_getattro = PyObject_GenericGetAttr,
1091         .tp_basicsize = sizeof(PyLdbObject),
1092         .tp_doc = "Connection to a LDB database.",
1093         .tp_as_sequence = &py_ldb_seq,
1094         .tp_flags = Py_TPFLAGS_DEFAULT|Py_TPFLAGS_BASETYPE,
1095 };
1096
1097 static PyObject *py_ldb_module_repr(PyLdbModuleObject *self)
1098 {
1099         return PyString_FromFormat("<ldb module '%s'>", PyLdbModule_AsModule(self)->ops->name);
1100 }
1101
1102 static PyObject *py_ldb_module_str(PyLdbModuleObject *self)
1103 {
1104         return PyString_FromString(PyLdbModule_AsModule(self)->ops->name);
1105 }
1106
1107 static PyObject *py_ldb_module_start_transaction(PyLdbModuleObject *self)
1108 {
1109         PyLdbModule_AsModule(self)->ops->start_transaction(PyLdbModule_AsModule(self));
1110         Py_RETURN_NONE;
1111 }
1112
1113 static PyObject *py_ldb_module_end_transaction(PyLdbModuleObject *self)
1114 {
1115         PyLdbModule_AsModule(self)->ops->end_transaction(PyLdbModule_AsModule(self));
1116         Py_RETURN_NONE;
1117 }
1118
1119 static PyObject *py_ldb_module_del_transaction(PyLdbModuleObject *self)
1120 {
1121         PyLdbModule_AsModule(self)->ops->del_transaction(PyLdbModule_AsModule(self));
1122         Py_RETURN_NONE;
1123 }
1124
1125 static PyObject *py_ldb_module_search(PyLdbModuleObject *self, PyObject *args, PyObject *kwargs)
1126 {
1127         PyObject *py_base, *py_tree, *py_attrs;
1128         int ret, scope;
1129         struct ldb_request *req;
1130         const char * const kwnames[] = { "base", "scope", "tree", "attrs", NULL };
1131         struct ldb_module *mod;
1132
1133         if (!PyArg_ParseTupleAndKeywords(args, kwargs, "OiOO",
1134                                          discard_const_p(char *, kwnames),
1135                                          &py_base, &scope, &py_tree, &py_attrs))
1136                 return NULL;
1137
1138         mod = self->mod;
1139
1140         ret = ldb_build_search_req(&req, mod->ldb, NULL, PyLdbDn_AsDn(py_base), 
1141                              scope, NULL /* expr */, py_attrs == Py_None?NULL:PyList_AsStringList(req, py_attrs, "attrs"),
1142                              NULL /* controls */, NULL, NULL, NULL);
1143         PyErr_LDB_ERROR_IS_ERR_RAISE(ret, mod->ldb);
1144
1145         ret = mod->ops->search(mod, req);
1146         talloc_free(req);
1147
1148         PyErr_LDB_ERROR_IS_ERR_RAISE(ret, mod->ldb);
1149
1150         return PyLdbResult_FromResult(req->op.search.res);
1151 }
1152
1153
1154 static PyObject *py_ldb_module_add(PyLdbModuleObject *self, PyObject *args)
1155 {
1156         struct ldb_request *req;
1157         PyObject *py_message;
1158         int ret;
1159         struct ldb_module *mod;
1160
1161         if (!PyArg_ParseTuple(args, "O", &py_message))
1162                 return NULL;
1163
1164         req = talloc_zero(NULL, struct ldb_request);
1165         req->operation = LDB_ADD;
1166         req->op.add.message = PyLdbMessage_AsMessage(py_message);
1167
1168         mod = PyLdbModule_AsModule(self);
1169         ret = mod->ops->add(mod, req);
1170
1171         PyErr_LDB_ERROR_IS_ERR_RAISE(ret, mod->ldb);
1172
1173         Py_RETURN_NONE;
1174 }
1175
1176 static PyObject *py_ldb_module_modify(PyLdbModuleObject *self, PyObject *args) 
1177 {
1178         int ret;
1179         struct ldb_request *req;
1180         PyObject *py_message;
1181         struct ldb_module *mod;
1182
1183         if (!PyArg_ParseTuple(args, "O", &py_message))
1184                 return NULL;
1185         
1186         req = talloc_zero(NULL, struct ldb_request);
1187         req->operation = LDB_MODIFY;
1188         req->op.mod.message = PyLdbMessage_AsMessage(py_message);
1189         
1190         mod = PyLdbModule_AsModule(self);
1191         ret = mod->ops->modify(mod, req);
1192
1193         PyErr_LDB_ERROR_IS_ERR_RAISE(ret, mod->ldb);
1194
1195         Py_RETURN_NONE;
1196 }
1197
1198 static PyObject *py_ldb_module_delete(PyLdbModuleObject *self, PyObject *args) 
1199 {
1200         int ret;
1201         struct ldb_request *req;
1202         PyObject *py_dn;
1203
1204         if (!PyArg_ParseTuple(args, "O", &py_dn))
1205                 return NULL;
1206         
1207         req = talloc_zero(NULL, struct ldb_request);
1208         req->operation = LDB_DELETE;
1209         req->op.del.dn = PyLdbDn_AsDn(py_dn);
1210         
1211         ret = PyLdbModule_AsModule(self)->ops->del(PyLdbModule_AsModule(self), req);
1212
1213         PyErr_LDB_ERROR_IS_ERR_RAISE(ret, NULL);
1214
1215         Py_RETURN_NONE;
1216 }
1217
1218 static PyObject *py_ldb_module_rename(PyLdbModuleObject *self, PyObject *args)
1219 {
1220         int ret;
1221         struct ldb_request *req;
1222         PyObject *py_dn1, *py_dn2;
1223
1224         if (!PyArg_ParseTuple(args, "OO", &py_dn1, &py_dn2))
1225                 return NULL;
1226         
1227         req = talloc_zero(NULL, struct ldb_request);
1228
1229         req->operation = LDB_RENAME;
1230         req->op.rename.olddn = PyLdbDn_AsDn(py_dn1);
1231         req->op.rename.newdn = PyLdbDn_AsDn(py_dn2);
1232         
1233         ret = PyLdbModule_AsModule(self)->ops->rename(PyLdbModule_AsModule(self), req);
1234
1235         PyErr_LDB_ERROR_IS_ERR_RAISE(ret, NULL);
1236
1237         Py_RETURN_NONE;
1238 }
1239
1240 static PyMethodDef py_ldb_module_methods[] = {
1241         { "search", (PyCFunction)py_ldb_module_search, METH_VARARGS|METH_KEYWORDS, NULL },
1242         { "add", (PyCFunction)py_ldb_module_add, METH_VARARGS, NULL },
1243         { "modify", (PyCFunction)py_ldb_module_modify, METH_VARARGS, NULL },
1244         { "rename", (PyCFunction)py_ldb_module_rename, METH_VARARGS, NULL },
1245         { "delete", (PyCFunction)py_ldb_module_delete, METH_VARARGS, NULL },
1246         { "start_transaction", (PyCFunction)py_ldb_module_start_transaction, METH_NOARGS, NULL },
1247         { "end_transaction", (PyCFunction)py_ldb_module_end_transaction, METH_NOARGS, NULL },
1248         { "del_transaction", (PyCFunction)py_ldb_module_del_transaction, METH_NOARGS, NULL },
1249         { NULL },
1250 };
1251
1252 static void py_ldb_module_dealloc(PyLdbModuleObject *self)
1253 {
1254         talloc_free(self->mem_ctx);
1255         self->ob_type->tp_free(self);
1256 }
1257
1258 PyTypeObject PyLdbModule = {
1259         .tp_name = "LdbModule",
1260         .tp_methods = py_ldb_module_methods,
1261         .tp_repr = (reprfunc)py_ldb_module_repr,
1262         .tp_str = (reprfunc)py_ldb_module_str,
1263         .tp_basicsize = sizeof(PyLdbModuleObject),
1264         .tp_dealloc = (destructor)py_ldb_module_dealloc,
1265         .tp_flags = Py_TPFLAGS_DEFAULT,
1266 };
1267
1268
1269 /**
1270  * Create a ldb_message_element from a Python object.
1271  *
1272  * This will accept any sequence objects that contains strings, or 
1273  * a string object.
1274  *
1275  * A reference to set_obj will be borrowed. 
1276  *
1277  * @param mem_ctx Memory context
1278  * @param set_obj Python object to convert
1279  * @param flags ldb_message_element flags to set
1280  * @param attr_name Name of the attribute
1281  * @return New ldb_message_element, allocated as child of mem_ctx
1282  */
1283 struct ldb_message_element *PyObject_AsMessageElement(TALLOC_CTX *mem_ctx,
1284                                                                                            PyObject *set_obj, int flags,
1285                                                                                            const char *attr_name)
1286 {
1287         struct ldb_message_element *me;
1288
1289         if (PyLdbMessageElement_Check(set_obj))
1290                 return PyLdbMessageElement_AsMessageElement(set_obj);
1291
1292         me = talloc(mem_ctx, struct ldb_message_element);
1293
1294         me->name = attr_name;
1295         me->flags = flags;
1296         if (PyString_Check(set_obj)) {
1297                 me->num_values = 1;
1298                 me->values = talloc_array(me, struct ldb_val, me->num_values);
1299                 me->values[0].length = PyString_Size(set_obj);
1300                 me->values[0].data = (uint8_t *)PyString_AsString(set_obj);
1301         } else if (PySequence_Check(set_obj)) {
1302                 int i;
1303                 me->num_values = PySequence_Size(set_obj);
1304                 me->values = talloc_array(me, struct ldb_val, me->num_values);
1305                 for (i = 0; i < me->num_values; i++) {
1306                         PyObject *obj = PySequence_GetItem(set_obj, i);
1307
1308                         me->values[i].length = PyString_Size(obj);
1309                         me->values[i].data = (uint8_t *)PyString_AsString(obj);
1310                 }
1311         } else {
1312                 talloc_free(me);
1313                 me = NULL;
1314         }
1315
1316         return me;
1317 }
1318
1319
1320 static PyObject *ldb_msg_element_to_set(struct ldb_context *ldb_ctx, 
1321                                                                  struct ldb_message_element *me)
1322 {
1323         int i;
1324         PyObject *result;
1325
1326         /* Python << 2.5 doesn't have PySet_New and PySet_Add. */
1327         result = PyList_New(me->num_values);
1328
1329         for (i = 0; i < me->num_values; i++) {
1330                 PyList_SetItem(result, i,
1331                         PyObject_FromLdbValue(ldb_ctx, me, &me->values[i]));
1332         }
1333
1334         return result;
1335 }
1336
1337 static PyObject *py_ldb_msg_element_get(PyLdbMessageElementObject *self, PyObject *args)
1338 {
1339         int i;
1340         if (!PyArg_ParseTuple(args, "i", &i))
1341                 return NULL;
1342         if (i < 0 || i >= PyLdbMessageElement_AsMessageElement(self)->num_values)
1343                 Py_RETURN_NONE;
1344
1345         return PyObject_FromLdbValue(NULL, PyLdbMessageElement_AsMessageElement(self), 
1346                                                                  &(PyLdbMessageElement_AsMessageElement(self)->values[i]));
1347 }
1348
1349 static PyMethodDef py_ldb_msg_element_methods[] = {
1350         { "get", (PyCFunction)py_ldb_msg_element_get, METH_VARARGS, NULL },
1351         { NULL },
1352 };
1353
1354 static Py_ssize_t py_ldb_msg_element_len(PyLdbMessageElementObject *self)
1355 {
1356         return PyLdbMessageElement_AsMessageElement(self)->num_values;
1357 }
1358
1359 static PyObject *py_ldb_msg_element_find(PyLdbMessageElementObject *self, Py_ssize_t idx)
1360 {
1361         struct ldb_message_element *el = PyLdbMessageElement_AsMessageElement(self);
1362         if (idx < 0 || idx >= el->num_values) {
1363                 PyErr_SetString(PyExc_IndexError, "Out of range");
1364                 return NULL;
1365         }
1366         return PyString_FromStringAndSize((char *)el->values[idx].data, el->values[idx].length);
1367 }
1368
1369 static PySequenceMethods py_ldb_msg_element_seq = {
1370         .sq_length = (lenfunc)py_ldb_msg_element_len,
1371         .sq_item = (ssizeargfunc)py_ldb_msg_element_find,
1372 };
1373
1374 static int py_ldb_msg_element_cmp(PyLdbMessageElementObject *self, PyLdbMessageElementObject *other)
1375 {
1376         return ldb_msg_element_compare(PyLdbMessageElement_AsMessageElement(self), 
1377                                                                    PyLdbMessageElement_AsMessageElement(other));
1378 }
1379
1380 static PyObject *py_ldb_msg_element_iter(PyLdbMessageElementObject *self)
1381 {
1382         return PyObject_GetIter(ldb_msg_element_to_set(NULL, PyLdbMessageElement_AsMessageElement(self)));
1383 }
1384
1385 PyObject *PyLdbMessageElement_FromMessageElement(struct ldb_message_element *el, TALLOC_CTX *mem_ctx)
1386 {
1387         PyLdbMessageElementObject *ret;
1388         ret = (PyLdbMessageElementObject *)PyLdbMessageElement.tp_alloc(&PyLdbMessageElement, 0);
1389         if (ret == NULL) {
1390                 PyErr_NoMemory();
1391                 return NULL;
1392         }
1393         ret->mem_ctx = talloc_new(NULL);
1394         if (talloc_reference(ret->mem_ctx, mem_ctx) == NULL) {
1395                 PyErr_NoMemory();
1396                 return NULL;
1397         }
1398         ret->el = el;
1399         return (PyObject *)ret;
1400 }
1401
1402 static PyObject *py_ldb_msg_element_new(PyTypeObject *type, PyObject *args, PyObject *kwargs)
1403 {
1404         PyObject *py_elements = NULL;
1405         struct ldb_message_element *el;
1406         int flags = 0;
1407         char *name = NULL;
1408         const char * const kwnames[] = { "elements", "flags", "name", NULL };
1409         PyLdbMessageElementObject *ret;
1410
1411         if (!PyArg_ParseTupleAndKeywords(args, kwargs, "|Ois",
1412                                          discard_const_p(char *, kwnames),
1413                                          &py_elements, &flags, &name))
1414                 return NULL;
1415
1416         el = talloc_zero(NULL, struct ldb_message_element);
1417
1418         if (py_elements != NULL) {
1419                 int i;
1420                 if (PyString_Check(py_elements)) {
1421                         el->num_values = 1;
1422                         el->values = talloc_array(el, struct ldb_val, 1);
1423                         el->values[0].data = (uint8_t *)PyString_AsString(py_elements);
1424                         el->values[0].length = PyString_Size(py_elements);
1425                 } else if (PySequence_Check(py_elements)) {
1426                         el->num_values = PySequence_Size(py_elements);
1427                         el->values = talloc_array(el, struct ldb_val, el->num_values);
1428                         for (i = 0; i < el->num_values; i++) {
1429                                 PyObject *item = PySequence_GetItem(py_elements, i);
1430                                 el->values[i].data = (uint8_t *)PyString_AsString(item);
1431                                 el->values[i].length = PyString_Size(item);
1432                         }
1433                 } else {
1434                         PyErr_SetString(PyExc_TypeError, 
1435                                         "Expected string or list");
1436                         talloc_free(el);
1437                         return NULL;
1438                 }
1439         }
1440
1441         el->flags = flags;
1442         el->name = talloc_strdup(el, name);
1443
1444         ret = (PyLdbMessageElementObject *)PyLdbMessageElement.tp_alloc(&PyLdbMessageElement, 0);
1445         if (ret == NULL) {
1446                 PyErr_NoMemory();
1447                 talloc_free(el);
1448                 return NULL;
1449         }
1450
1451         ret->mem_ctx = talloc_new(NULL);
1452         ret->el = talloc_reference(ret->mem_ctx, el);
1453         return (PyObject *)ret;
1454 }
1455
1456 static PyObject *py_ldb_msg_element_repr(PyLdbMessageElementObject *self)
1457 {
1458         char *element_str = NULL;
1459         int i;
1460         struct ldb_message_element *el = PyLdbMessageElement_AsMessageElement(self);
1461         PyObject *ret;
1462
1463         for (i = 0; i < el->num_values; i++) {
1464                 PyObject *o = py_ldb_msg_element_find(self, i);
1465                 if (element_str == NULL)
1466                         element_str = talloc_strdup(NULL, PyObject_REPR(o));
1467                 else
1468                         element_str = talloc_asprintf_append(element_str, ",%s", PyObject_REPR(o));
1469         }
1470
1471         ret = PyString_FromFormat("MessageElement([%s])", element_str);
1472
1473         talloc_free(element_str);
1474
1475         return ret;
1476 }
1477
1478 static PyObject *py_ldb_msg_element_str(PyLdbMessageElementObject *self)
1479 {
1480         struct ldb_message_element *el = PyLdbMessageElement_AsMessageElement(self);
1481
1482         if (el->num_values == 1)
1483                 return PyString_FromStringAndSize((char *)el->values[0].data, el->values[0].length);
1484         else 
1485                 Py_RETURN_NONE;
1486 }
1487
1488 static void py_ldb_msg_element_dealloc(PyLdbMessageElementObject *self)
1489 {
1490         talloc_free(self->mem_ctx);
1491         self->ob_type->tp_free(self);
1492 }
1493
1494 PyTypeObject PyLdbMessageElement = {
1495         .tp_name = "MessageElement",
1496         .tp_basicsize = sizeof(PyLdbMessageElementObject),
1497         .tp_dealloc = (destructor)py_ldb_msg_element_dealloc,
1498         .tp_repr = (reprfunc)py_ldb_msg_element_repr,
1499         .tp_str = (reprfunc)py_ldb_msg_element_str,
1500         .tp_methods = py_ldb_msg_element_methods,
1501         .tp_compare = (cmpfunc)py_ldb_msg_element_cmp,
1502         .tp_iter = (getiterfunc)py_ldb_msg_element_iter,
1503         .tp_as_sequence = &py_ldb_msg_element_seq,
1504         .tp_new = py_ldb_msg_element_new,
1505         .tp_flags = Py_TPFLAGS_DEFAULT,
1506 };
1507
1508 static PyObject *py_ldb_msg_remove_attr(PyLdbMessageObject *self, PyObject *args)
1509 {
1510         char *name;
1511         if (!PyArg_ParseTuple(args, "s", &name))
1512                 return NULL;
1513
1514         ldb_msg_remove_attr(self->msg, name);
1515
1516         Py_RETURN_NONE;
1517 }
1518
1519 static PyObject *py_ldb_msg_keys(PyLdbMessageObject *self)
1520 {
1521         struct ldb_message *msg = PyLdbMessage_AsMessage(self);
1522         int i, j = 0;
1523         PyObject *obj = PyList_New(msg->num_elements+(msg->dn != NULL?1:0));
1524         if (msg->dn != NULL) {
1525                 PyList_SetItem(obj, j, PyString_FromString("dn"));
1526                 j++;
1527         }
1528         for (i = 0; i < msg->num_elements; i++) {
1529                 PyList_SetItem(obj, j, PyString_FromString(msg->elements[i].name));
1530                 j++;
1531         }
1532         return obj;
1533 }
1534
1535 static PyObject *py_ldb_msg_getitem_helper(PyLdbMessageObject *self, PyObject *py_name)
1536 {
1537         struct ldb_message_element *el;
1538         char *name = PyString_AsString(py_name);
1539         struct ldb_message *msg = PyLdbMessage_AsMessage(self);
1540         if (!strcmp(name, "dn"))
1541                 return PyLdbDn_FromDn(msg->dn);
1542         el = ldb_msg_find_element(msg, name);
1543         if (el == NULL) {
1544                 return NULL;
1545         }
1546         return (PyObject *)PyLdbMessageElement_FromMessageElement(el, msg);
1547 }
1548
1549 static PyObject *py_ldb_msg_getitem(PyLdbMessageObject *self, PyObject *py_name)
1550 {
1551         PyObject *ret = py_ldb_msg_getitem_helper(self, py_name);
1552         if (ret == NULL) {
1553                 PyErr_SetString(PyExc_KeyError, "No such element");
1554                 return NULL;
1555         }
1556         return ret;
1557 }
1558
1559 static PyObject *py_ldb_msg_get(PyLdbMessageObject *self, PyObject *args)
1560 {
1561         PyObject *name, *ret;
1562         if (!PyArg_ParseTuple(args, "O", &name))
1563                 return NULL;
1564
1565         ret = py_ldb_msg_getitem_helper(self, name);
1566         if (ret == NULL)
1567                 Py_RETURN_NONE;
1568         return ret;
1569 }
1570
1571 static PyObject *py_ldb_msg_items(PyLdbMessageObject *self)
1572 {
1573         struct ldb_message *msg = PyLdbMessage_AsMessage(self);
1574         int i, j;
1575         PyObject *l = PyList_New(msg->num_elements + (msg->dn == NULL?0:1));
1576         j = 0;
1577         if (msg->dn != NULL) {
1578                 PyList_SetItem(l, 0, Py_BuildValue("(sO)", "dn", PyLdbDn_FromDn(msg->dn)));
1579                 j++;
1580         }
1581         for (i = 0; i < msg->num_elements; i++, j++) {
1582                 PyList_SetItem(l, j, Py_BuildValue("(sO)", msg->elements[i].name, PyLdbMessageElement_FromMessageElement(&msg->elements[i], self->msg)));
1583         }
1584         return l;
1585 }
1586
1587 static PyMethodDef py_ldb_msg_methods[] = { 
1588         { "keys", (PyCFunction)py_ldb_msg_keys, METH_NOARGS, NULL },
1589         { "remove", (PyCFunction)py_ldb_msg_remove_attr, METH_VARARGS, NULL },
1590         { "get", (PyCFunction)py_ldb_msg_get, METH_VARARGS, NULL },
1591         { "items", (PyCFunction)py_ldb_msg_items, METH_NOARGS, NULL },
1592         { NULL },
1593 };
1594
1595 static PyObject *py_ldb_msg_iter(PyLdbMessageObject *self)
1596 {
1597         PyObject *list, *iter;
1598
1599         list = py_ldb_msg_keys(self);
1600         iter = PyObject_GetIter(list);
1601         Py_DECREF(list);
1602         return iter;
1603 }
1604
1605 static int py_ldb_msg_setitem(PyLdbMessageObject *self, PyObject *name, PyObject *value)
1606 {
1607         char *attr_name = PyString_AsString(name);
1608         if (value == NULL) {
1609                 ldb_msg_remove_attr(self->msg, attr_name);
1610         } else {
1611                 struct ldb_message_element *el = PyObject_AsMessageElement(NULL,
1612                                                                                         value, 0, attr_name);
1613                 if (el == NULL)
1614                         return -1;
1615                 talloc_steal(self->msg, el);
1616                 ldb_msg_remove_attr(PyLdbMessage_AsMessage(self), attr_name);
1617                 ldb_msg_add(PyLdbMessage_AsMessage(self), el, el->flags);
1618         }
1619         return 0;
1620 }
1621
1622 static Py_ssize_t py_ldb_msg_length(PyLdbMessageObject *self)
1623 {
1624         return PyLdbMessage_AsMessage(self)->num_elements;
1625 }
1626
1627 static PyMappingMethods py_ldb_msg_mapping = {
1628         .mp_length = (lenfunc)py_ldb_msg_length,
1629         .mp_subscript = (binaryfunc)py_ldb_msg_getitem,
1630         .mp_ass_subscript = (objobjargproc)py_ldb_msg_setitem,
1631 };
1632
1633 static PyObject *py_ldb_msg_new(PyTypeObject *type, PyObject *args, PyObject *kwargs)
1634 {
1635         const char * const kwnames[] = { "dn", NULL };
1636         struct ldb_message *ret;
1637         PyObject *pydn = NULL;
1638         PyLdbMessageObject *py_ret;
1639
1640         if (!PyArg_ParseTupleAndKeywords(args, kwargs, "|O",
1641                                          discard_const_p(char *, kwnames),
1642                                          &pydn))
1643                 return NULL;
1644
1645         ret = ldb_msg_new(NULL);
1646         if (ret == NULL) {
1647                 PyErr_NoMemory();
1648                 return NULL;
1649         }
1650
1651         if (pydn != NULL)
1652                 if (!PyObject_AsDn(NULL, pydn, NULL, &ret->dn))
1653                         return NULL;
1654
1655         py_ret = (PyLdbMessageObject *)type->tp_alloc(type, 0);
1656         if (py_ret == NULL) {
1657                 PyErr_NoMemory();
1658                 return NULL;
1659         }
1660
1661         py_ret->mem_ctx = talloc_new(NULL);
1662         py_ret->msg = talloc_reference(py_ret->mem_ctx, ret);
1663         return (PyObject *)py_ret;
1664 }
1665
1666 PyObject *PyLdbMessage_FromMessage(struct ldb_message *msg)
1667 {
1668         PyLdbMessageObject *ret;
1669
1670         ret = (PyLdbMessageObject *)PyLdbMessage.tp_alloc(&PyLdbMessage, 0);
1671         if (ret == NULL) {
1672                 PyErr_NoMemory();
1673                 return NULL;
1674         }
1675         ret->mem_ctx = talloc_new(NULL);
1676         ret->msg = talloc_reference(ret->mem_ctx, msg);
1677         return (PyObject *)ret;
1678 }
1679
1680 static PyObject *py_ldb_msg_get_dn(PyLdbMessageObject *self, void *closure)
1681 {
1682         return PyLdbDn_FromDn(PyLdbMessage_AsMessage(self)->dn);
1683 }
1684
1685 static int py_ldb_msg_set_dn(PyLdbMessageObject *self, PyObject *value, void *closure)
1686 {
1687         PyLdbMessage_AsMessage(self)->dn = PyLdbDn_AsDn(value);
1688         return 0;
1689 }
1690
1691 static PyGetSetDef py_ldb_msg_getset[] = {
1692         { discard_const_p(char, "dn"), (getter)py_ldb_msg_get_dn, (setter)py_ldb_msg_set_dn, NULL },
1693         { NULL }
1694 };
1695
1696 static PyObject *py_ldb_msg_repr(PyLdbMessageObject *self)
1697 {
1698         PyObject *dict = PyDict_New(), *ret;
1699         if (PyDict_Update(dict, (PyObject *)self) != 0)
1700                 return NULL;
1701         ret = PyString_FromFormat("Message(%s)", PyObject_REPR(dict));
1702         Py_DECREF(dict);
1703         return ret;
1704 }
1705
1706 static void py_ldb_msg_dealloc(PyLdbMessageObject *self)
1707 {
1708         talloc_free(self->mem_ctx);
1709         self->ob_type->tp_free(self);
1710 }
1711
1712 PyTypeObject PyLdbMessage = {
1713         .tp_name = "Message",
1714         .tp_methods = py_ldb_msg_methods,
1715         .tp_getset = py_ldb_msg_getset,
1716         .tp_as_mapping = &py_ldb_msg_mapping,
1717         .tp_basicsize = sizeof(PyLdbMessageObject),
1718         .tp_dealloc = (destructor)py_ldb_msg_dealloc,
1719         .tp_new = py_ldb_msg_new,
1720         .tp_repr = (reprfunc)py_ldb_msg_repr,
1721         .tp_flags = Py_TPFLAGS_DEFAULT,
1722         .tp_iter = (getiterfunc)py_ldb_msg_iter,
1723 };
1724
1725 PyObject *PyLdbTree_FromTree(struct ldb_parse_tree *tree)
1726 {
1727         PyLdbTreeObject *ret;
1728
1729         ret = (PyLdbTreeObject *)PyLdbTree.tp_alloc(&PyLdbTree, 0);
1730         if (ret == NULL) {
1731                 PyErr_NoMemory();
1732                 return NULL;
1733         }
1734         
1735         ret->mem_ctx = talloc_new(NULL);
1736         ret->tree = talloc_reference(ret->mem_ctx, tree);
1737         return (PyObject *)ret;
1738 }
1739
1740 static void py_ldb_tree_dealloc(PyLdbTreeObject *self)
1741 {
1742         talloc_free(self->mem_ctx);
1743         self->ob_type->tp_free(self);
1744 }
1745
1746 PyTypeObject PyLdbTree = {
1747         .tp_name = "Tree",
1748         .tp_basicsize = sizeof(PyLdbTreeObject),
1749         .tp_dealloc = (destructor)py_ldb_tree_dealloc,
1750         .tp_flags = Py_TPFLAGS_DEFAULT,
1751 };
1752
1753 /* Ldb_module */
1754 static int py_module_search(struct ldb_module *mod, struct ldb_request *req)
1755 {
1756         PyObject *py_ldb = (PyObject *)mod->private_data;
1757         PyObject *py_result, *py_base, *py_attrs, *py_tree;
1758
1759         py_base = PyLdbDn_FromDn(req->op.search.base);
1760
1761         if (py_base == NULL)
1762                 return LDB_ERR_OPERATIONS_ERROR;
1763
1764         py_tree = PyLdbTree_FromTree(req->op.search.tree);
1765
1766         if (py_tree == NULL)
1767                 return LDB_ERR_OPERATIONS_ERROR;
1768
1769         if (req->op.search.attrs == NULL) {
1770                 py_attrs = Py_None;
1771         } else {
1772                 int i, len;
1773                 for (len = 0; req->op.search.attrs[len]; len++);
1774                 py_attrs = PyList_New(len);
1775                 for (i = 0; i < len; i++)
1776                         PyList_SetItem(py_attrs, i, PyString_FromString(req->op.search.attrs[i]));
1777         }
1778
1779         py_result = PyObject_CallMethod(py_ldb, discard_const_p(char, "search"),
1780                                         discard_const_p(char, "OiOO"),
1781                                         py_base, req->op.search.scope, py_tree, py_attrs);
1782
1783         Py_DECREF(py_attrs);
1784         Py_DECREF(py_tree);
1785         Py_DECREF(py_base);
1786
1787         if (py_result == NULL) {
1788                 return LDB_ERR_PYTHON_EXCEPTION;
1789         }
1790
1791         req->op.search.res = PyLdbResult_AsResult(NULL, py_result);
1792         if (req->op.search.res == NULL) {
1793                 return LDB_ERR_PYTHON_EXCEPTION;
1794         }
1795
1796         Py_DECREF(py_result);
1797
1798         return LDB_SUCCESS;
1799 }
1800
1801 static int py_module_add(struct ldb_module *mod, struct ldb_request *req)
1802 {
1803         PyObject *py_ldb = (PyObject *)mod->private_data;
1804         PyObject *py_result, *py_msg;
1805
1806         py_msg = PyLdbMessage_FromMessage(discard_const_p(struct ldb_message, req->op.add.message));
1807
1808         if (py_msg == NULL) {
1809                 return LDB_ERR_OPERATIONS_ERROR;
1810         }
1811
1812         py_result = PyObject_CallMethod(py_ldb, discard_const_p(char, "add"),
1813                                         discard_const_p(char, "O"),
1814                                         py_msg);
1815
1816         Py_DECREF(py_msg);
1817
1818         if (py_result == NULL) {
1819                 return LDB_ERR_PYTHON_EXCEPTION;
1820         }
1821
1822         Py_DECREF(py_result);
1823
1824         return LDB_SUCCESS;
1825 }
1826
1827 static int py_module_modify(struct ldb_module *mod, struct ldb_request *req)
1828 {
1829         PyObject *py_ldb = (PyObject *)mod->private_data;
1830         PyObject *py_result, *py_msg;
1831
1832         py_msg = PyLdbMessage_FromMessage(discard_const_p(struct ldb_message, req->op.mod.message));
1833
1834         if (py_msg == NULL) {
1835                 return LDB_ERR_OPERATIONS_ERROR;
1836         }
1837
1838         py_result = PyObject_CallMethod(py_ldb, discard_const_p(char, "modify"),
1839                                         discard_const_p(char, "O"),
1840                                         py_msg);
1841
1842         Py_DECREF(py_msg);
1843
1844         if (py_result == NULL) {
1845                 return LDB_ERR_PYTHON_EXCEPTION;
1846         }
1847
1848         Py_DECREF(py_result);
1849
1850         return LDB_SUCCESS;
1851 }
1852
1853 static int py_module_del(struct ldb_module *mod, struct ldb_request *req)
1854 {
1855         PyObject *py_ldb = (PyObject *)mod->private_data;
1856         PyObject *py_result, *py_dn;
1857
1858         py_dn = PyLdbDn_FromDn(req->op.del.dn);
1859
1860         if (py_dn == NULL)
1861                 return LDB_ERR_OPERATIONS_ERROR;
1862
1863         py_result = PyObject_CallMethod(py_ldb, discard_const_p(char, "delete"),
1864                                         discard_const_p(char, "O"),
1865                                         py_dn);
1866
1867         if (py_result == NULL) {
1868                 return LDB_ERR_PYTHON_EXCEPTION;
1869         }
1870
1871         Py_DECREF(py_result);
1872
1873         return LDB_SUCCESS;
1874 }
1875
1876 static int py_module_rename(struct ldb_module *mod, struct ldb_request *req)
1877 {
1878         PyObject *py_ldb = (PyObject *)mod->private_data;
1879         PyObject *py_result, *py_olddn, *py_newdn;
1880
1881         py_olddn = PyLdbDn_FromDn(req->op.rename.olddn);
1882
1883         if (py_olddn == NULL)
1884                 return LDB_ERR_OPERATIONS_ERROR;
1885
1886         py_newdn = PyLdbDn_FromDn(req->op.rename.newdn);
1887
1888         if (py_newdn == NULL)
1889                 return LDB_ERR_OPERATIONS_ERROR;
1890
1891         py_result = PyObject_CallMethod(py_ldb, discard_const_p(char, "rename"),
1892                                         discard_const_p(char, "OO"),
1893                                         py_olddn, py_newdn);
1894
1895         Py_DECREF(py_olddn);
1896         Py_DECREF(py_newdn);
1897
1898         if (py_result == NULL) {
1899                 return LDB_ERR_PYTHON_EXCEPTION;
1900         }
1901
1902         Py_DECREF(py_result);
1903
1904         return LDB_SUCCESS;
1905 }
1906
1907 static int py_module_request(struct ldb_module *mod, struct ldb_request *req)
1908 {
1909         PyObject *py_ldb = (PyObject *)mod->private_data;
1910         PyObject *py_result;
1911
1912         py_result = PyObject_CallMethod(py_ldb, discard_const_p(char, "request"),
1913                                         discard_const_p(char, ""));
1914
1915         return LDB_ERR_OPERATIONS_ERROR;
1916 }
1917
1918 static int py_module_extended(struct ldb_module *mod, struct ldb_request *req)
1919 {
1920         PyObject *py_ldb = (PyObject *)mod->private_data;
1921         PyObject *py_result;
1922
1923         py_result = PyObject_CallMethod(py_ldb, discard_const_p(char, "extended"),
1924                                         discard_const_p(char, ""));
1925
1926         return LDB_ERR_OPERATIONS_ERROR;
1927 }
1928
1929 static int py_module_start_transaction(struct ldb_module *mod)
1930 {
1931         PyObject *py_ldb = (PyObject *)mod->private_data;
1932         PyObject *py_result;
1933
1934         py_result = PyObject_CallMethod(py_ldb, discard_const_p(char, "start_transaction"),
1935                                         discard_const_p(char, ""));
1936
1937         if (py_result == NULL) {
1938                 return LDB_ERR_PYTHON_EXCEPTION;
1939         }
1940
1941         Py_DECREF(py_result);
1942
1943         return LDB_SUCCESS;
1944 }
1945
1946 static int py_module_end_transaction(struct ldb_module *mod)
1947 {
1948         PyObject *py_ldb = (PyObject *)mod->private_data;
1949         PyObject *py_result;
1950
1951         py_result = PyObject_CallMethod(py_ldb, discard_const_p(char, "end_transaction"),
1952                                         discard_const_p(char, ""));
1953
1954         if (py_result == NULL) {
1955                 return LDB_ERR_PYTHON_EXCEPTION;
1956         }
1957
1958         Py_DECREF(py_result);
1959
1960         return LDB_SUCCESS;
1961 }
1962
1963 static int py_module_del_transaction(struct ldb_module *mod)
1964 {
1965         PyObject *py_ldb = (PyObject *)mod->private_data;
1966         PyObject *py_result;
1967
1968         py_result = PyObject_CallMethod(py_ldb, discard_const_p(char, "del_transaction"),
1969                                         discard_const_p(char, ""));
1970
1971         if (py_result == NULL) {
1972                 return LDB_ERR_PYTHON_EXCEPTION;
1973         }
1974
1975         Py_DECREF(py_result);
1976
1977         return LDB_SUCCESS;
1978 }
1979
1980 static int py_module_destructor(struct ldb_module *mod)
1981 {
1982         Py_DECREF((PyObject *)mod->private_data);
1983         return 0;
1984 }
1985
1986 static int py_module_init(struct ldb_module *mod)
1987 {
1988         PyObject *py_class = (PyObject *)mod->ops->private_data;
1989         PyObject *py_result, *py_next, *py_ldb;
1990
1991         py_ldb = PyLdb_FromLdbContext(mod->ldb);
1992
1993         if (py_ldb == NULL)
1994                 return LDB_ERR_OPERATIONS_ERROR;
1995
1996         py_next = PyLdbModule_FromModule(mod->next);
1997
1998         if (py_next == NULL)
1999                 return LDB_ERR_OPERATIONS_ERROR;
2000
2001         py_result = PyObject_CallFunction(py_class, discard_const_p(char, "OO"),
2002                                           py_ldb, py_next);
2003
2004         if (py_result == NULL) {
2005                 return LDB_ERR_PYTHON_EXCEPTION;
2006         }
2007
2008         mod->private_data = py_result;
2009
2010         talloc_set_destructor(mod, py_module_destructor);
2011
2012         return ldb_next_init(mod);
2013 }
2014
2015 static PyObject *py_register_module(PyObject *module, PyObject *args)
2016 {
2017         int ret;
2018         struct ldb_module_ops *ops;
2019         PyObject *input;
2020
2021         if (!PyArg_ParseTuple(args, "O", &input))
2022                 return NULL;
2023
2024         ops = talloc_zero(talloc_autofree_context(), struct ldb_module_ops);
2025         if (ops == NULL) {
2026                 PyErr_NoMemory();
2027                 return NULL;
2028         }
2029
2030         ops->name = talloc_strdup(ops, PyString_AsString(PyObject_GetAttrString(input, discard_const_p(char, "name"))));
2031
2032         Py_INCREF(input);
2033         ops->private_data = input;
2034         ops->init_context = py_module_init;
2035         ops->search = py_module_search;
2036         ops->add = py_module_add;
2037         ops->modify = py_module_modify;
2038         ops->del = py_module_del;
2039         ops->rename = py_module_rename;
2040         ops->request = py_module_request;
2041         ops->extended = py_module_extended;
2042         ops->start_transaction = py_module_start_transaction;
2043         ops->end_transaction = py_module_end_transaction;
2044         ops->del_transaction = py_module_del_transaction;
2045
2046         ret = ldb_register_module(ops);
2047
2048         PyErr_LDB_ERROR_IS_ERR_RAISE(ret, NULL);
2049
2050         Py_RETURN_NONE;
2051 }
2052
2053 static PyObject *py_timestring(PyObject *module, PyObject *args)
2054 {
2055         time_t t;
2056         char *tresult;
2057         PyObject *ret;
2058         if (!PyArg_ParseTuple(args, "L", &t))
2059                 return NULL;
2060         tresult = ldb_timestring(NULL, t);
2061         ret = PyString_FromString(tresult);
2062         talloc_free(tresult);
2063         return ret;
2064 }
2065
2066 static PyObject *py_string_to_time(PyObject *module, PyObject *args)
2067 {
2068         char *str;
2069         if (!PyArg_ParseTuple(args, "s", &str))
2070                 return NULL;
2071
2072         return PyInt_FromLong(ldb_string_to_time(str));
2073 }
2074
2075 static PyObject *py_valid_attr_name(PyObject *self, PyObject *args)
2076 {
2077         char *name;
2078         if (!PyArg_ParseTuple(args, "s", &name))
2079                 return NULL;
2080         return PyBool_FromLong(ldb_valid_attr_name(name));
2081 }
2082
2083 static PyMethodDef py_ldb_global_methods[] = {
2084         { "register_module", py_register_module, METH_VARARGS, 
2085                 "S.register_module(module) -> None\n"
2086                 "Register a LDB module."},
2087         { "timestring", py_timestring, METH_VARARGS, 
2088                 "S.timestring(int) -> string\n"
2089                 "Generate a LDAP time string from a UNIX timestamp" },
2090         { "string_to_time", py_string_to_time, METH_VARARGS,
2091                 "S.string_to_time(string) -> int\n"
2092                 "Parse a LDAP time string into a UNIX timestamp." },
2093         { "valid_attr_name", py_valid_attr_name, METH_VARARGS,
2094                 "S.valid_attr_name(name) -> bool\n"
2095                 "Check whether the supplied name is a valid attribute name." },
2096         { "open", (PyCFunction)py_ldb_new, METH_VARARGS|METH_KEYWORDS,
2097                 NULL },
2098         { NULL }
2099 };
2100
2101 void initldb(void)
2102 {
2103         PyObject *m;
2104
2105         if (PyType_Ready(&PyLdbDn) < 0)
2106                 return;
2107
2108         if (PyType_Ready(&PyLdbMessage) < 0)
2109                 return;
2110
2111         if (PyType_Ready(&PyLdbMessageElement) < 0)
2112                 return;
2113
2114         if (PyType_Ready(&PyLdb) < 0)
2115                 return;
2116
2117         if (PyType_Ready(&PyLdbModule) < 0)
2118                 return;
2119
2120         if (PyType_Ready(&PyLdbTree) < 0)
2121                 return;
2122
2123         m = Py_InitModule3("ldb", py_ldb_global_methods, 
2124                 "An interface to LDB, a LDAP-like API that can either to talk an embedded database (TDB-based) or a standards-compliant LDAP server.");
2125         if (m == NULL)
2126                 return;
2127
2128         PyModule_AddObject(m, "SCOPE_DEFAULT", PyInt_FromLong(LDB_SCOPE_DEFAULT));
2129         PyModule_AddObject(m, "SCOPE_BASE", PyInt_FromLong(LDB_SCOPE_BASE));
2130         PyModule_AddObject(m, "SCOPE_ONELEVEL", PyInt_FromLong(LDB_SCOPE_ONELEVEL));
2131         PyModule_AddObject(m, "SCOPE_SUBTREE", PyInt_FromLong(LDB_SCOPE_SUBTREE));
2132
2133         PyModule_AddObject(m, "CHANGETYPE_NONE", PyInt_FromLong(LDB_CHANGETYPE_NONE));
2134         PyModule_AddObject(m, "CHANGETYPE_ADD", PyInt_FromLong(LDB_CHANGETYPE_ADD));
2135         PyModule_AddObject(m, "CHANGETYPE_DELETE", PyInt_FromLong(LDB_CHANGETYPE_DELETE));
2136         PyModule_AddObject(m, "CHANGETYPE_MODIFY", PyInt_FromLong(LDB_CHANGETYPE_MODIFY));
2137
2138         PyModule_AddObject(m, "SUCCESS", PyInt_FromLong(LDB_SUCCESS));
2139         PyModule_AddObject(m, "ERR_OPERATIONS_ERROR", PyInt_FromLong(LDB_ERR_OPERATIONS_ERROR));
2140         PyModule_AddObject(m, "ERR_PROTOCOL_ERROR", PyInt_FromLong(LDB_ERR_PROTOCOL_ERROR));
2141         PyModule_AddObject(m, "ERR_TIME_LIMIT_EXCEEDED", PyInt_FromLong(LDB_ERR_TIME_LIMIT_EXCEEDED));
2142         PyModule_AddObject(m, "ERR_SIZE_LIMIT_EXCEEDED", PyInt_FromLong(LDB_ERR_SIZE_LIMIT_EXCEEDED));
2143         PyModule_AddObject(m, "ERR_COMPARE_FALSE", PyInt_FromLong(LDB_ERR_COMPARE_FALSE));
2144         PyModule_AddObject(m, "ERR_COMPARE_TRUE", PyInt_FromLong(LDB_ERR_COMPARE_TRUE));
2145         PyModule_AddObject(m, "ERR_AUTH_METHOD_NOT_SUPPORTED", PyInt_FromLong(LDB_ERR_AUTH_METHOD_NOT_SUPPORTED));
2146         PyModule_AddObject(m, "ERR_STRONG_AUTH_REQUIRED", PyInt_FromLong(LDB_ERR_STRONG_AUTH_REQUIRED));
2147         PyModule_AddObject(m, "ERR_REFERRAL", PyInt_FromLong(LDB_ERR_REFERRAL));
2148         PyModule_AddObject(m, "ERR_ADMIN_LIMIT_EXCEEDED", PyInt_FromLong(LDB_ERR_ADMIN_LIMIT_EXCEEDED));
2149         PyModule_AddObject(m, "ERR_UNSUPPORTED_CRITICAL_EXTENSION", PyInt_FromLong(LDB_ERR_UNSUPPORTED_CRITICAL_EXTENSION));
2150         PyModule_AddObject(m, "ERR_CONFIDENTIALITY_REQUIRED", PyInt_FromLong(LDB_ERR_CONFIDENTIALITY_REQUIRED));
2151         PyModule_AddObject(m, "ERR_SASL_BIND_IN_PROGRESS", PyInt_FromLong(LDB_ERR_SASL_BIND_IN_PROGRESS));
2152         PyModule_AddObject(m, "ERR_NO_SUCH_ATTRIBUTE", PyInt_FromLong(LDB_ERR_NO_SUCH_ATTRIBUTE));
2153         PyModule_AddObject(m, "ERR_UNDEFINED_ATTRIBUTE_TYPE", PyInt_FromLong(LDB_ERR_UNDEFINED_ATTRIBUTE_TYPE));
2154         PyModule_AddObject(m, "ERR_INAPPROPRIATE_MATCHING", PyInt_FromLong(LDB_ERR_INAPPROPRIATE_MATCHING));
2155         PyModule_AddObject(m, "ERR_CONSTRAINT_VIOLATION", PyInt_FromLong(LDB_ERR_CONSTRAINT_VIOLATION));
2156         PyModule_AddObject(m, "ERR_ATTRIBUTE_OR_VALUE_EXISTS", PyInt_FromLong(LDB_ERR_ATTRIBUTE_OR_VALUE_EXISTS));
2157         PyModule_AddObject(m, "ERR_INVALID_ATTRIBUTE_SYNTAX", PyInt_FromLong(LDB_ERR_INVALID_ATTRIBUTE_SYNTAX));
2158         PyModule_AddObject(m, "ERR_NO_SUCH_OBJECT", PyInt_FromLong(LDB_ERR_NO_SUCH_OBJECT));
2159         PyModule_AddObject(m, "ERR_ALIAS_PROBLEM", PyInt_FromLong(LDB_ERR_ALIAS_PROBLEM));
2160         PyModule_AddObject(m, "ERR_INVALID_DN_SYNTAX", PyInt_FromLong(LDB_ERR_INVALID_DN_SYNTAX));
2161         PyModule_AddObject(m, "ERR_ALIAS_DEREFERINCING_PROBLEM", PyInt_FromLong(LDB_ERR_ALIAS_DEREFERENCING_PROBLEM));
2162         PyModule_AddObject(m, "ERR_INAPPROPRIATE_AUTHENTICATION", PyInt_FromLong(LDB_ERR_INAPPROPRIATE_AUTHENTICATION));
2163         PyModule_AddObject(m, "ERR_INVALID_CREDENTIALS", PyInt_FromLong(LDB_ERR_INVALID_CREDENTIALS));
2164         PyModule_AddObject(m, "ERR_INSUFFICIENT_ACCESS_RIGHTS", PyInt_FromLong(LDB_ERR_INSUFFICIENT_ACCESS_RIGHTS));
2165         PyModule_AddObject(m, "ERR_BUSY", PyInt_FromLong(LDB_ERR_BUSY));
2166         PyModule_AddObject(m, "ERR_UNAVAILABLE", PyInt_FromLong(LDB_ERR_UNAVAILABLE));
2167         PyModule_AddObject(m, "ERR_UNWILLING_TO_PERFORM", PyInt_FromLong(LDB_ERR_UNWILLING_TO_PERFORM));
2168         PyModule_AddObject(m, "ERR_LOOP_DETECT", PyInt_FromLong(LDB_ERR_LOOP_DETECT));
2169         PyModule_AddObject(m, "ERR_NAMING_VIOLATION", PyInt_FromLong(LDB_ERR_NAMING_VIOLATION));
2170         PyModule_AddObject(m, "ERR_OBJECT_CLASS_VIOLATION", PyInt_FromLong(LDB_ERR_OBJECT_CLASS_VIOLATION));
2171         PyModule_AddObject(m, "ERR_NOT_ALLOWED_ON_NON_LEAF", PyInt_FromLong(LDB_ERR_NOT_ALLOWED_ON_NON_LEAF));
2172         PyModule_AddObject(m, "ERR_NOT_ALLOWED_ON_RDN", PyInt_FromLong(LDB_ERR_NOT_ALLOWED_ON_RDN));
2173         PyModule_AddObject(m, "ERR_ENTRY_ALREADY_EXISTS", PyInt_FromLong(LDB_ERR_ENTRY_ALREADY_EXISTS));
2174         PyModule_AddObject(m, "ERR_OBJECT_CLASS_MODS_PROHIBITED", PyInt_FromLong(LDB_ERR_OBJECT_CLASS_MODS_PROHIBITED));
2175         PyModule_AddObject(m, "ERR_AFFECTS_MULTIPLE_DSAS", PyInt_FromLong(LDB_ERR_AFFECTS_MULTIPLE_DSAS));
2176
2177         PyModule_AddObject(m, "ERR_OTHER", PyInt_FromLong(LDB_ERR_OTHER));
2178
2179         PyModule_AddObject(m, "__docformat__", PyString_FromString("restructuredText"));
2180
2181         PyExc_LdbError = PyErr_NewException(discard_const_p(char, "_ldb.LdbError"), NULL, NULL);
2182         PyModule_AddObject(m, "LdbError", PyExc_LdbError);
2183
2184         Py_INCREF(&PyLdb);
2185         Py_INCREF(&PyLdbDn);
2186         Py_INCREF(&PyLdbModule);
2187         Py_INCREF(&PyLdbMessage);
2188         Py_INCREF(&PyLdbMessageElement);
2189         Py_INCREF(&PyLdbTree);
2190
2191         PyModule_AddObject(m, "Ldb", (PyObject *)&PyLdb);
2192         PyModule_AddObject(m, "Dn", (PyObject *)&PyLdbDn);
2193         PyModule_AddObject(m, "Message", (PyObject *)&PyLdbMessage);
2194         PyModule_AddObject(m, "MessageElement", (PyObject *)&PyLdbMessageElement);
2195         PyModule_AddObject(m, "Module", (PyObject *)&PyLdbModule);
2196         PyModule_AddObject(m, "Tree", (PyObject *)&PyLdbTree);
2197 }