Initial work using manual Python bindings for LDB, rather than SWIG-generated ones.
[tprouty/samba.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-2008 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 <stdint.h>
29 #include <stdbool.h>
30 #include "pyldb.h"
31 #include "events.h"
32 #include "ldb_errors.h"
33 #include "ldb_private.h"
34
35 PyObject *PyExc_LdbError;
36
37 #define PyErr_LDB_ERROR_IS_ERR_RAISE(ret,ldb) \
38         if (ret != LDB_SUCCESS) { \
39         PyErr_SetObject(PyExc_LdbError, Py_BuildValue((char *)"(i,s)", ret, ldb == NULL?ldb_strerror(ret):ldb_errstring(ldb))); \
40                 return NULL; \
41         }
42 #define PyLdb_AsLdbContext(pyobj) py_talloc_get_type(pyobj, struct ldb_context)
43 #define PyLdbModule_AsModule(pyobj) py_talloc_get_type(pyobj, struct ldb_module)
44 #define PyLdbMessage_AsMessage(pyobj) py_talloc_get_type(pyobj, struct ldb_message)
45 #define PyLdbMessageElement_AsMessageElement(pyobj) py_talloc_get_type(pyobj, struct ldb_message_element)
46
47 PyObject *PyObject_FromLdbValue(struct ldb_context *ldb_ctx, 
48                                struct ldb_message_element *el, 
49                                struct ldb_val *val)
50 {
51         const struct ldb_schema_attribute *a;
52         struct ldb_val new_val;
53         TALLOC_CTX *mem_ctx = talloc_new(NULL);
54         PyObject *ret;
55         
56         new_val = *val;
57         
58         if (ldb_ctx != NULL) {        
59                 a = ldb_schema_attribute_by_name(ldb_ctx, el->name);
60         
61                 if (a != NULL) {
62                         if (a->syntax->ldif_write_fn(ldb_ctx, mem_ctx, val, &new_val) != 0) {
63                                 talloc_free(mem_ctx);
64                                 return NULL;
65                         }
66                 }
67         } 
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 int PyObject_AsDn(TALLOC_CTX *mem_ctx, PyObject *object, 
77                          struct ldb_context *ldb_ctx, struct ldb_dn **dn)
78 {
79     struct ldb_dn *odn;
80     if (ldb_ctx != NULL && PyString_Check(object)) {
81         odn = ldb_dn_new(mem_ctx, ldb_ctx, PyString_AsString(object));
82                 *dn = odn;
83         return 0;
84     }
85         if (PyLdbDn_Check(object)) {
86                 *dn = PyLdbDn_AsDn(object);
87                 return 0;
88         }
89         return -1;
90 }
91
92 static PyObject *PyLdbResult_FromResult(struct ldb_result *result)
93 {
94         PyObject *ret;
95         int i;
96     if (result == NULL) {
97         return Py_None;
98     } 
99         ret = PyList_New(result->count);
100         for (i = 0; i < result->count; i++) {
101                 PyList_SetItem(ret, i, 
102                                            PyLdbMessage_FromMessage(result->msgs[i])
103                 );
104         }
105         return ret;
106 }
107
108 static struct ldb_result *PyLdbResult_AsResult(PyObject *obj)
109 {
110         /* FIXME */
111         return NULL;
112 }
113
114 static PyObject *py_ldb_dn_validate(PyLdbDnObject *self)
115 {
116         return PyBool_FromLong(ldb_dn_validate(self->ptr));
117 }
118
119 static PyObject *py_ldb_dn_is_valid(PyLdbDnObject *self)
120 {
121         return PyBool_FromLong(ldb_dn_is_valid(self->ptr));
122 }
123
124 static PyObject *py_ldb_dn_is_special(PyLdbDnObject *self)
125 {
126         return PyBool_FromLong(ldb_dn_is_special(self->ptr));
127 }
128
129 static PyObject *py_ldb_dn_is_null(PyLdbDnObject *self)
130 {
131         return PyBool_FromLong(ldb_dn_is_null(self->ptr));
132 }
133  
134 static PyObject *py_ldb_dn_get_casefold(PyLdbDnObject *self)
135 {
136         return PyString_FromString(ldb_dn_get_casefold(self->ptr));
137 }
138
139 static PyObject *py_ldb_dn_get_linearized(PyLdbDnObject *self)
140 {
141         return PyString_FromString(ldb_dn_get_linearized(self->ptr));
142 }
143
144 static PyObject *py_ldb_dn_canonical_str(PyLdbDnObject *self)
145 {
146         return PyString_FromString(ldb_dn_canonical_string(self->ptr, self->ptr));
147 }
148
149 static PyObject *py_ldb_dn_canonical_ex_str(PyLdbDnObject *self)
150 {
151         return PyString_FromString(ldb_dn_canonical_ex_string(self->ptr, self->ptr));
152 }
153
154 static PyObject *py_ldb_dn_repr(PyLdbDnObject *self)
155 {
156         return PyString_FromFormat("Dn('%s')", ldb_dn_get_linearized(self->ptr));
157 }
158
159 static PyObject *py_ldb_dn_check_special(PyLdbDnObject *self, PyObject *args)
160 {
161         char *name;
162
163         if (!PyArg_ParseTuple(args, "s", &name))
164                 return NULL;
165
166         return ldb_dn_check_special(self->ptr, name)?Py_True:Py_False;
167 }
168 static int py_ldb_dn_compare(PyLdbDnObject *dn1, PyLdbDnObject *dn2)
169 {
170         return ldb_dn_compare(dn1->ptr, dn2->ptr);
171 }
172
173 static PyMethodDef py_ldb_dn_methods[] = {
174         { "validate", (PyCFunction)py_ldb_dn_validate, METH_NOARGS, 
175                 "S.validate() -> bool\n"
176                 "Validate DN is correct." },
177         { "is_valid", (PyCFunction)py_ldb_dn_is_valid, METH_NOARGS,
178                 "S.is_valid() -> bool\n" },
179         { "is_special", (PyCFunction)py_ldb_dn_is_special, METH_NOARGS,
180                 "S.is_special() -> bool\n"
181                 "Check whether this is a special LDB DN." },
182         { "is_null", (PyCFunction)py_ldb_dn_is_null, METH_NOARGS,
183                 "Check whether this is a null DN." },
184         { "get_casefold", (PyCFunction)py_ldb_dn_get_casefold, METH_NOARGS,
185                 NULL },
186         { "get_linearized", (PyCFunction)py_ldb_dn_get_linearized, METH_NOARGS,
187                 NULL },
188         { "canonical_str", (PyCFunction)py_ldb_dn_canonical_str, METH_NOARGS,
189                 "S.canonical_str() -> string\n"
190                 "Canonical version of this DN (like a posix path)." },
191         { "canonical_ex_str", (PyCFunction)py_ldb_dn_canonical_ex_str, METH_NOARGS,
192                 "S.canonical_ex_str() -> string\n"
193                 "Canonical version of this DN (like a posix path, with terminating newline)." },
194         { "check_special", (PyCFunction)py_ldb_dn_is_special, METH_VARARGS, 
195                 NULL },
196         { NULL }
197 };
198
199 PyTypeObject PyLdbDn = {
200         .tp_name = "Dn",
201         .tp_methods = py_ldb_dn_methods,
202         .tp_str = (reprfunc)py_ldb_dn_get_linearized,
203         .tp_repr = (reprfunc)py_ldb_dn_repr,
204         .tp_compare = (cmpfunc)py_ldb_dn_compare,
205         .tp_doc = "A LDB distinguished name.",
206 };
207
208 /* Debug */
209 static void py_ldb_debug(void *context, enum ldb_debug_level level, const char *fmt, va_list ap)
210 {
211     PyObject *fn = context;
212     PyObject_CallFunction(fn, (char *)"(i,O)", level, PyString_FromFormatV(fmt, ap));
213 }
214
215 static PyObject *py_ldb_set_debug(PyLdbObject *self, PyObject *args)
216 {
217         PyObject *cb;
218         
219         if (!PyArg_ParseTuple(args, "O", &cb))
220                 return NULL;
221
222         Py_INCREF(cb);
223         /* FIXME: Where do we DECREF cb ? */
224         PyErr_LDB_ERROR_IS_ERR_RAISE(ldb_set_debug(self->ptr, py_ldb_debug, cb), PyLdb_AsLdbContext(self));
225         
226         return Py_None;
227 }
228
229 static PyObject *py_ldb_set_create_perms(PyTypeObject *self, PyObject *args)
230 {
231         unsigned int perms;
232         if (!PyArg_ParseTuple(args, "I", &perms))
233                 return NULL;
234
235         ldb_set_create_perms(PyLdb_AsLdbContext(self), perms);
236
237         return Py_None;
238 }
239
240 static PyObject *py_ldb_set_modules_dir(PyTypeObject *self, PyObject *args)
241 {
242         char *modules_dir;
243         if (!PyArg_ParseTuple(args, "s", &modules_dir))
244                 return NULL;
245
246         ldb_set_modules_dir(PyLdb_AsLdbContext(self), modules_dir);
247
248         return Py_None;
249 }
250
251 static PyObject *py_ldb_transaction_start(PyLdbObject *self)
252 {
253         PyErr_LDB_ERROR_IS_ERR_RAISE(ldb_transaction_start(PyLdb_AsLdbContext(self)), PyLdb_AsLdbContext(self));
254         return Py_None;
255 }
256
257 static PyObject *py_ldb_transaction_commit(PyLdbObject *self)
258 {
259         PyErr_LDB_ERROR_IS_ERR_RAISE(ldb_transaction_commit(PyLdb_AsLdbContext(self)), PyLdb_AsLdbContext(self));
260         return Py_None;
261 }
262
263 static PyObject *py_ldb_transaction_cancel(PyLdbObject *self)
264 {
265         PyErr_LDB_ERROR_IS_ERR_RAISE(ldb_transaction_cancel(PyLdb_AsLdbContext(self)), PyLdb_AsLdbContext(self));
266         return Py_None;
267 }
268
269 static PyObject *py_ldb_setup_wellknown_attributes(PyLdbObject *self)
270 {
271         PyErr_LDB_ERROR_IS_ERR_RAISE(ldb_setup_wellknown_attributes(PyLdb_AsLdbContext(self)), PyLdb_AsLdbContext(self));
272         return Py_None;
273 }
274
275 static PyObject *py_ldb_repr(PyLdbObject *self)
276 {
277         return PyString_FromFormat("<ldb connection>");
278 }
279
280 static PyObject *py_ldb_get_root_basedn(PyLdbObject *self)
281 {
282         struct ldb_dn *dn = ldb_get_root_basedn(PyLdb_AsLdbContext(self));
283         if (dn == NULL)
284                 return Py_None;
285         return PyLdbDn_FromDn(dn);
286 }
287
288
289 static PyObject *py_ldb_get_schema_basedn(PyLdbObject *self)
290 {
291         struct ldb_dn *dn = ldb_get_schema_basedn(PyLdb_AsLdbContext(self));
292         if (dn == NULL)
293                 return Py_None;
294         return PyLdbDn_FromDn(dn);
295 }
296
297
298 static PyObject *py_ldb_get_config_basedn(PyLdbObject *self)
299 {
300         struct ldb_dn *dn = ldb_get_config_basedn(PyLdb_AsLdbContext(self));
301         if (dn == NULL)
302                 return Py_None;
303         return PyLdbDn_FromDn(dn);
304 }
305
306
307 static PyObject *py_ldb_get_default_basedn(PyLdbObject *self)
308 {
309         struct ldb_dn *dn = ldb_get_default_basedn(PyLdb_AsLdbContext(self));
310         if (dn == NULL)
311                 return Py_None;
312         return PyLdbDn_FromDn(dn);
313 }
314
315 static PyObject *py_ldb_new(PyTypeObject *type, PyObject *args, PyObject *kwargs)
316 {
317         struct ldb_context *ldb;
318         char *kwnames[] = { NULL };
319         if (!PyArg_ParseTupleAndKeywords(args, kwargs, "", kwnames))
320                 return NULL;
321
322         ldb = ldb_init(NULL, event_context_init(NULL)); 
323         if (ldb == NULL) {
324                 PyErr_NoMemory();
325                 return NULL;
326         }
327
328         return py_talloc_import(&PyLdb, ldb);
329 }
330
331 static PyObject *py_ldb_connect(PyLdbObject *self, PyObject *args, PyObject *kwargs)
332 {
333         char *url;
334         int flags;
335         PyObject *py_options = Py_None;
336         int ret;
337         int i;
338         const char **options;
339         if (!PyArg_ParseTupleAndKeywords(args, kwargs, "s|iO", &url, &flags,
340                                                                          &py_options))
341                 return NULL;
342
343         if (py_options == Py_None) {
344                 options = NULL;
345         } else {
346                 if (!PyList_Check(py_options)) {
347                         PyErr_SetString(PyExc_TypeError, "options is not a list");
348                         return NULL;
349                 }
350                 options = talloc_array(NULL, const char *, PyList_Size(py_options));
351                 for (i = 0; i < PyList_Size(py_options); i++)
352                         options[i] = PyString_AsString(PyList_GetItem(py_options, i));
353         }
354         
355         ret = ldb_connect(PyLdb_AsLdbContext(self), url, flags, options);
356         talloc_free(options);
357
358         PyErr_LDB_ERROR_IS_ERR_RAISE(ret, PyLdb_AsLdbContext(self));
359
360         return Py_None;
361 }
362
363 static PyObject *py_ldb_modify(PyLdbObject *self, PyObject *args)
364 {
365         PyObject *py_msg;
366         int ret;
367         if (!PyArg_ParseTuple(args, "O", &py_msg))
368                 return NULL;
369
370         if (!PyLdbMessage_Check(py_msg)) {
371                 PyErr_SetString(PyExc_TypeError, "Expected Ldb Message");
372                 return NULL;
373         }
374
375         ret = ldb_modify(PyLdb_AsLdbContext(self), PyLdbMessage_AsMessage(py_msg));
376         PyErr_LDB_ERROR_IS_ERR_RAISE(ret, PyLdb_AsLdbContext(self));
377
378         return Py_None;
379 }
380
381 static PyObject *py_ldb_add(PyLdbObject *self, PyObject *args)
382 {
383         PyObject *py_msg;
384         int ret;
385     Py_ssize_t dict_pos, msg_pos;
386     struct ldb_message_element *msgel;
387         struct ldb_message *msg;
388     PyObject *key, *value;
389
390         if (!PyArg_ParseTuple(args, "O", &py_msg))
391                 return NULL;
392
393     if (PyDict_Check(py_msg)) {
394                 PyObject *dn_value = PyDict_GetItemString(py_msg, "dn");
395         msg = ldb_msg_new(NULL);
396         msg->elements = talloc_zero_array(msg, struct ldb_message_element, PyDict_Size(py_msg));
397         msg_pos = dict_pos = 0;
398                 if (dn_value) {
399                 if (PyObject_AsDn(msg, dn_value, PyLdb_AsLdbContext(self), &msg->dn) != 0) {
400                         PyErr_SetString(PyExc_TypeError, "unable to import dn object");
401                                 return NULL;
402                         }
403                         if (msg->dn == NULL) {
404                                 PyErr_SetString(PyExc_TypeError, "dn set but not found");
405                                 return NULL;
406                         }
407                 }
408
409                 while (PyDict_Next(py_msg, &dict_pos, &key, &value)) {
410                         char *key_str = PyString_AsString(key);
411                         if (strcmp(key_str, "dn") != 0) {
412                                 msgel = PyObject_AsMessageElement(msg->elements, value, 0, key_str);
413                                 if (msgel == NULL) {
414                                         PyErr_SetString(PyExc_TypeError, "unable to import element");
415                                         return NULL;
416                                 }
417                                 memcpy(&msg->elements[msg_pos], msgel, sizeof(*msgel));
418                                 msg_pos++;
419                         }
420                 }
421
422                 if (msg->dn == NULL) {
423                         PyErr_SetString(PyExc_TypeError, "no dn set");
424                         return NULL;
425                 }
426
427                 msg->num_elements = msg_pos;
428     } else {
429                 msg = PyLdbMessage_AsMessage(py_msg);
430     }
431         
432         ret = ldb_add(PyLdb_AsLdbContext(self), msg);
433         PyErr_LDB_ERROR_IS_ERR_RAISE(ret, PyLdb_AsLdbContext(self));
434
435         return Py_None;
436 }
437
438
439
440 static PyObject *py_ldb_delete(PyLdbObject *self, PyObject *args)
441 {
442         PyObject *py_dn;
443         struct ldb_dn *dn;
444         int ret;
445         if (!PyArg_ParseTuple(args, "O", &py_dn))
446                 return NULL;
447
448         if (!PyLdbDn_Check(py_dn)) {
449                 PyErr_SetString(PyExc_TypeError, "Expected Ldb Dn");
450                 return NULL;
451         }
452
453         dn = PyLdbDn_AsDn(py_dn);
454
455         ret = ldb_delete(PyLdb_AsLdbContext(self), dn);
456         PyErr_LDB_ERROR_IS_ERR_RAISE(ret, PyLdb_AsLdbContext(self));
457
458         return Py_None;
459 }
460
461 static PyObject *py_ldb_rename(PyLdbObject *self, PyObject *args)
462 {
463         PyObject *py_dn1, *py_dn2;
464         struct ldb_dn *dn1, *dn2;
465         int ret;
466         if (!PyArg_ParseTuple(args, "OO", &py_dn1, &py_dn2))
467                 return NULL;
468
469         if (!PyLdbDn_Check(py_dn1) || !PyLdbDn_Check(py_dn2)) {
470                 PyErr_SetString(PyExc_TypeError, "Expected Ldb Dn");
471                 return NULL;
472         }
473
474         dn1 = PyLdbDn_AsDn(py_dn1);
475         dn2 = PyLdbDn_AsDn(py_dn2);
476
477         ret = ldb_rename(PyLdb_AsLdbContext(self), dn1, dn2);
478         PyErr_LDB_ERROR_IS_ERR_RAISE(ret, PyLdb_AsLdbContext(self));
479
480         return Py_None;
481 }
482
483
484
485 static PyObject *py_ldb_schema_attribute_remove(PyLdbObject *self, PyObject *args)
486 {
487         char *name;
488         if (!PyArg_ParseTuple(args, "s", &name))
489                 return NULL;
490
491         ldb_schema_attribute_remove(PyLdb_AsLdbContext(self), name);
492
493         return Py_None;
494 }
495
496 static PyObject *py_ldb_schema_attribute_add(PyLdbObject *self, PyObject *args)
497 {
498         char *attribute, *syntax;
499         unsigned int flags;
500         int ret;
501         if (!PyArg_ParseTuple(args, "sIs", &attribute, &flags, &syntax))
502                 return NULL;
503
504         ret = ldb_schema_attribute_add(PyLdb_AsLdbContext(self), attribute, flags, syntax);
505
506         PyErr_LDB_ERROR_IS_ERR_RAISE(ret, PyLdb_AsLdbContext(self));
507
508         return Py_None;
509 }
510
511 static PyObject *ldb_ldif_to_pyobject(struct ldb_ldif *ldif)
512 {
513         if (ldif == NULL) {
514                 return Py_None;
515         } else {
516         /* We don't want this attached to the 'ldb' any more */
517                 talloc_steal(NULL, ldif);
518                 return Py_BuildValue((char *)"(iO)", ldif->changetype, 
519                                                          PyLdbMessage_FromMessage(ldif->msg));
520         }
521 }
522
523
524 static PyObject *py_ldb_parse_ldif(PyLdbObject *self, PyObject *args)
525 {
526         char *filename;
527         PyObject *list;
528         struct ldb_ldif *ldif;
529         const char *s;
530
531         if (!PyArg_ParseTuple(args, "s", &filename))
532                 return NULL;
533
534         list = PyList_New(0);
535         while ((ldif = ldb_ldif_read_string(self->ptr, &s)) != NULL) {
536                 PyList_Append(list, ldb_ldif_to_pyobject(ldif));
537         }
538         return PyObject_GetIter(list);
539 }
540
541 static PyObject *py_ldb_schema_format_value(PyLdbObject *self, PyObject *args)
542 {
543         const struct ldb_schema_attribute *a;
544         struct ldb_val old_val;
545         struct ldb_val new_val;
546         TALLOC_CTX *mem_ctx;
547         PyObject *ret;
548         char *element_name;
549         PyObject *val;
550
551         if (!PyArg_ParseTuple(args, "sO", &element_name, &val))
552                 return NULL;
553         
554         mem_ctx = talloc_new(NULL);
555         
556         old_val.data = (uint8_t *)PyString_AsString(val);
557         old_val.length = PyString_Size(val);
558                 
559         a = ldb_schema_attribute_by_name(PyLdb_AsLdbContext(self), element_name);
560
561         if (a == NULL) {
562                 return Py_None;
563         }
564         
565         if (a->syntax->ldif_write_fn(PyLdb_AsLdbContext(self), mem_ctx, &old_val, &new_val) != 0) {
566                 talloc_free(mem_ctx);
567                 return Py_None;
568         }
569
570         ret = PyString_FromStringAndSize((const char *)new_val.data, new_val.length);
571
572         talloc_free(mem_ctx);
573
574         return ret;
575 }
576
577 static PyMethodDef py_ldb_methods[] = {
578         { "set_debug", (PyCFunction)py_ldb_set_debug, METH_VARARGS, 
579                 "S.set_debug(callback) -> None\n"
580                 "Set callback for LDB debug messages.\n"
581                 "The callback should accept a debug level and debug text." },
582         { "set_create_perms", (PyCFunction)py_ldb_set_create_perms, METH_VARARGS, 
583                 "S.set_create_perms(mode) -> None\n"
584                 "Set mode to use when creating new LDB files." },
585         { "set_modules_dir", (PyCFunction)py_ldb_set_modules_dir, METH_VARARGS,
586                 "S.set_modules_dir(path) -> None\n"
587                 "Set path LDB should search for modules" },
588         { "transaction_start", (PyCFunction)py_ldb_transaction_start, METH_NOARGS, 
589                 "S.transaction_start() -> None\n"
590                 "Start a new transaction." },
591         { "transaction_commit", (PyCFunction)py_ldb_transaction_commit, METH_NOARGS, 
592                 "S.transaction_commit() -> None\n"
593                 "commit a new transaction." },
594         { "transaction_cancel", (PyCFunction)py_ldb_transaction_cancel, METH_NOARGS, 
595                 "S.transaction_cancel() -> None\n"
596                 "cancel a new transaction." },
597         { "setup_wellknown_attributes", (PyCFunction)py_ldb_setup_wellknown_attributes, METH_NOARGS, 
598                 NULL },
599         { "get_root_basedn", (PyCFunction)py_ldb_get_root_basedn, METH_NOARGS,
600                 NULL },
601         { "get_schema_basedn", (PyCFunction)py_ldb_get_schema_basedn, METH_NOARGS,
602                 NULL },
603         { "get_default_basedn", (PyCFunction)py_ldb_get_default_basedn, METH_NOARGS,
604                 NULL },
605         { "get_config_basedn", (PyCFunction)py_ldb_get_config_basedn, METH_NOARGS,
606                 NULL },
607         { "connect", (PyCFunction)py_ldb_connect, METH_VARARGS|METH_KEYWORDS, 
608                 "S.connect(url,flags=0,options=None) -> None\n"
609                 "Connect to a LDB URL." },
610         { "modify", (PyCFunction)py_ldb_modify, METH_VARARGS, 
611                 "S.modify(message) -> None\n"
612                 "Modify an entry." },
613         { "add", (PyCFunction)py_ldb_add, METH_VARARGS, 
614                 "S.add(message) -> None\n"
615                 "Add an entry." },
616         { "delete", (PyCFunction)py_ldb_delete, METH_VARARGS,
617                 "S.delete(dn) -> None\n"
618                 "Remove an entry." },
619         { "rename", (PyCFunction)py_ldb_rename, METH_VARARGS,
620                 "S.rename(old_dn, new_dn) -> None\n"
621                 "Rename an entry." },
622         { "schema_attribute_remove", (PyCFunction)py_ldb_schema_attribute_remove, METH_VARARGS,
623                 NULL },
624         { "schema_attribute_add", (PyCFunction)py_ldb_schema_attribute_add, METH_VARARGS,
625                 NULL },
626         { "schema_format_value", (PyCFunction)py_ldb_schema_format_value, METH_VARARGS,
627                 NULL },
628         { "parse_ldif", (PyCFunction)py_ldb_parse_ldif, METH_VARARGS,
629                 "S.parse_ldif(ldif) -> iter(messages)\n"
630         "Parse a string formatted using LDIF." },
631         { NULL },
632 };
633
634 PyObject *PyLdbModule_FromModule(struct ldb_module *mod)
635 {
636         return py_talloc_import(&PyLdbModule, mod);
637 }
638
639 static PyObject *py_ldb_get_firstmodule(PyLdbObject *self, void *closure)
640 {
641         return PyLdbModule_FromModule(PyLdb_AsLdbContext(self)->modules);
642 }
643
644 static PyGetSetDef py_ldb_getset[] = {
645         { (char *)"firstmodule", (getter)py_ldb_get_firstmodule, NULL, NULL },
646         { NULL }
647 };
648
649 PyTypeObject PyLdb = {
650         .tp_name = "Ldb",
651         .tp_methods = py_ldb_methods,
652         .tp_repr = (reprfunc)py_ldb_repr,
653         .tp_new = py_ldb_new,
654         .tp_dealloc = py_talloc_dealloc,
655         .tp_getset = py_ldb_getset,
656         .tp_basicsize = sizeof(PyLdbObject),
657         .tp_doc = "Connection to a LDB database.",
658 };
659
660 static PyObject *py_ldb_module_repr(PyLdbModuleObject *self)
661 {
662         return PyString_FromFormat("<ldb module '%s'>", PyLdbModule_AsModule(self)->ops->name);
663 }
664
665 static PyObject *py_ldb_module_str(PyLdbModuleObject *self)
666 {
667         return PyString_FromString(PyLdbModule_AsModule(self)->ops->name);
668 }
669
670 static PyObject *py_ldb_module_start_transaction(PyLdbModuleObject *self)
671 {
672         PyLdbModule_AsModule(self)->ops->start_transaction(PyLdbModule_AsModule(self));
673         return Py_None;
674 }
675
676 static PyObject *py_ldb_module_end_transaction(PyLdbModuleObject *self)
677 {
678         PyLdbModule_AsModule(self)->ops->end_transaction(PyLdbModule_AsModule(self));
679         return Py_None;
680 }
681
682 static PyObject *py_ldb_module_del_transaction(PyLdbModuleObject *self)
683 {
684         PyLdbModule_AsModule(self)->ops->del_transaction(PyLdbModule_AsModule(self));
685         return Py_None;
686 }
687
688 static PyObject *py_ldb_module_search(PyLdbModuleObject *self, PyObject *args, PyObject *kwargs)
689 {
690         PyObject *py_base, *py_tree, *py_attrs;
691         int ret, scope;
692         struct ldb_request *req;
693         const char *kwnames[] = { "base", "scope", "tree", "attrs", NULL };
694         if (!PyArg_ParseTupleAndKeywords(args, kwargs, "OiOO", (char **)kwnames, 
695                                                                          &py_base, &scope, &py_tree, &py_attrs))
696                 return NULL;
697
698         req = talloc_zero(NULL, struct ldb_request);
699
700         req->operation = LDB_SEARCH;
701         req->op.search.base = PyLdbDn_AsDn(py_base);
702         req->op.search.scope = scope;
703         req->op.search.tree = PyLdbTree_AsTree(py_tree);
704         req->op.search.attrs = attrs;
705
706         req->op.search.res = talloc_zero(NULL, struct ldb_result);
707
708         ret = PyLdbModule_AsModule(self)->ops->search(PyLdbModule_AsModule(self), req);
709         talloc_free(req);
710
711         PyErr_LDB_ERROR_IS_ERR_RAISE(ret, NULL);
712
713         return PyLdbResult_FromResult(req->op.search.res);
714 }
715
716
717 static PyObject *py_ldb_module_add(PyLdbModuleObject *self, PyObject *args)
718 {
719         struct ldb_request *req;
720         PyObject *py_message;
721         int ret;
722
723         if (!PyArg_ParseTuple(args, "O", &py_message))
724                 return NULL;
725
726         req = talloc_zero(NULL, struct ldb_request);
727         req->operation = LDB_ADD;
728         req->op.add.message = PyLdbMessage_AsMessage(py_message);
729
730         ret = PyLdbModule_AsModule(self)->ops->add(PyLdbModule_AsModule(self), req);
731
732         PyErr_LDB_ERROR_IS_ERR_RAISE(ret, NULL);
733
734         return Py_None;
735 }
736
737 static PyObject *py_ldb_module_modify(PyLdbModuleObject *self, PyObject *args) 
738 {
739         int ret;
740         struct ldb_request *req;
741         PyObject *py_message;
742
743         if (!PyArg_ParseTuple(args, "O", &py_message))
744                 return NULL;
745         
746         req = talloc_zero(NULL, struct ldb_request);
747         req->operation = LDB_MODIFY;
748         req->op.mod.message = PyLdbMessage_AsMessage(py_message);
749         
750         ret = PyLdbModule_AsModule(self)->ops->modify(PyLdbModule_AsModule(self), req);
751
752         PyErr_LDB_ERROR_IS_ERR_RAISE(ret, NULL);
753
754         return Py_None;
755 }
756
757 static PyObject *py_ldb_module_delete(PyLdbModuleObject *self, PyObject *args) 
758 {
759         int ret;
760         struct ldb_request *req;
761         PyObject *py_dn;
762
763         if (!PyArg_ParseTuple(args, "O", &py_dn))
764                 return NULL;
765         
766         req = talloc_zero(NULL, struct ldb_request);
767         req->operation = LDB_DELETE;
768         req->op.del.dn = PyLdbDn_AsDn(py_dn);
769         
770         ret = PyLdbModule_AsModule(self)->ops->del(PyLdbModule_AsModule(self), req);
771
772         PyErr_LDB_ERROR_IS_ERR_RAISE(ret, NULL);
773
774         return Py_None;
775 }
776
777 static PyObject *py_ldb_module_rename(PyLdbModuleObject *self, PyObject *args)
778 {
779         int ret;
780         struct ldb_request *req;
781         PyObject *py_dn1, *py_dn2;
782
783         if (!PyArg_ParseTuple(args, "OO", &py_dn1, &py_dn2))
784                 return NULL;
785         
786         req = talloc_zero(NULL, struct ldb_request);
787
788         req->operation = LDB_RENAME;
789         req->op.rename.olddn = PyLdbDn_AsDn(py_dn1);
790         req->op.rename.newdn = PyLdbDn_AsDn(py_dn2);
791         
792         ret = PyLdbModule_AsModule(self)->ops->rename(PyLdbModule_AsModule(self), req);
793
794         PyErr_LDB_ERROR_IS_ERR_RAISE(ret, NULL);
795
796         return Py_None;
797 }
798
799 static PyMethodDef py_ldb_module_methods[] = {
800         { "search", (PyCFunction)py_ldb_module_search, METH_VARARGS|METH_KEYWORDS, NULL },
801         { "add", (PyCFunction)py_ldb_module_add, METH_VARARGS, NULL },
802         { "modify", (PyCFunction)py_ldb_module_modify, METH_VARARGS, NULL },
803         { "rename", (PyCFunction)py_ldb_module_rename, METH_VARARGS, NULL },
804         { "delete", (PyCFunction)py_ldb_module_delete, METH_VARARGS, NULL },
805         { "start_transaction", (PyCFunction)py_ldb_module_start_transaction, METH_NOARGS, NULL },
806         { "end_transaction", (PyCFunction)py_ldb_module_end_transaction, METH_NOARGS, NULL },
807         { "del_transaction", (PyCFunction)py_ldb_module_del_transaction, METH_NOARGS, NULL },
808         { NULL },
809 };
810
811 PyTypeObject PyLdbModule = {
812         .tp_name = "LdbModule",
813         .tp_methods = py_ldb_module_methods,
814         .tp_repr = (reprfunc)py_ldb_module_repr,
815         .tp_str = (reprfunc)py_ldb_module_str,
816         .tp_basicsize = sizeof(py_talloc_Object),
817         .tp_dealloc = py_talloc_dealloc,
818 };
819
820 struct ldb_message_element *PyLdbMessagElement_AsMsgElement(TALLOC_CTX *mem_ctx,
821                                                PyObject *set_obj, int flags,
822                                                const char *attr_name)
823 {
824     struct ldb_message_element *me = talloc(mem_ctx, struct ldb_message_element);
825
826     me->name = attr_name;
827     me->flags = flags;
828     if (PyString_Check(set_obj)) {
829         me->num_values = 1;
830         me->values = talloc_array(me, struct ldb_val, me->num_values);
831         me->values[0].length = PyString_Size(set_obj);
832         me->values[0].data = (uint8_t *)talloc_strdup(me->values, 
833                                            PyString_AsString(set_obj));
834     } else if (PySequence_Check(set_obj)) {
835         int i;
836         me->num_values = PySequence_Size(set_obj);
837         me->values = talloc_array(me, struct ldb_val, me->num_values);
838         for (i = 0; i < me->num_values; i++) {
839             PyObject *obj = PySequence_GetItem(set_obj, i);
840             me->values[i].length = PyString_Size(obj);
841             me->values[i].data = (uint8_t *)PyString_AsString(obj);
842         }
843     } else {
844         talloc_free(me);
845         me = NULL;
846     }
847
848     return me;
849 }
850
851
852 PyObject *ldb_msg_element_to_set(struct ldb_context *ldb_ctx, 
853                                  struct ldb_message_element *me)
854 {
855     int i;
856     PyObject *result;
857
858     /* Python << 2.5 doesn't have PySet_New and PySet_Add. */
859     result = PyList_New(me->num_values);
860
861     for (i = 0; i < me->num_values; i++) {
862         PyList_SetItem(result, i,
863             PyObject_FromLdbValue(ldb_ctx, me, &me->values[i]));
864     }
865
866     return result;
867 }
868
869 PyObject *py_ldb_msg_element_get(PyLdbMessageElementObject *self, PyObject *args)
870 {
871         int i;
872         if (!PyArg_ParseTuple(args, "i", &i))
873                 return NULL;
874         if (i < 0 || i >= PyLdbMessageElement_AsMessageElement(self)->num_values)
875                 return Py_None;
876
877         return PyObject_FromLdbValue(NULL, PyLdbMessageElement_AsMessageElement(self), 
878                                                                  &(PyLdbMessageElement_AsMessageElement(self)->values[i]));
879 }
880
881 static PyMethodDef py_ldb_msg_element_methods[] = {
882         { "get", (PyCFunction)py_ldb_msg_element_get, METH_VARARGS, NULL },
883         { NULL },
884 };
885
886 PyTypeObject PyLdbMessageElement = {
887         .tp_name = "MessageElement",
888         .tp_basicsize = sizeof(PyLdbMessageElementObject),
889         .tp_dealloc = py_talloc_dealloc,
890         .tp_methods = py_ldb_msg_element_methods,
891 };
892
893 static PyObject *py_ldb_msg_remove_attr(PyLdbMessageObject *self, PyObject *args)
894 {
895         char *name;
896         if (!PyArg_ParseTuple(args, "s", &name))
897                 return NULL;
898
899         ldb_msg_remove_attr(self->ptr, name);
900
901         return Py_None;
902 }
903
904 static PyMethodDef py_ldb_msg_methods[] = { 
905         { "remove", (PyCFunction)py_ldb_msg_remove_attr, METH_VARARGS, NULL },
906         { NULL },
907 };
908
909 static PyObject *py_ldb_msg_getitem(PyLdbMessageObject *self, PyObject *name)
910 {
911         struct ldb_message_element *el;
912         el = ldb_msg_find_element(PyLdbMessage_AsMessage(self), PyString_AsString(name));
913         if (el == NULL)
914                 return NULL;
915         return PyLdbMessageElement_FromMessageElement(el);
916 }
917
918 static PyObject *py_ldb_msg_setitem(PyLdbMessageObject *self, PyObject *name, PyObject *value)
919 {
920         if (value == NULL) {
921                 ldb_msg_remove_attr(self->ptr, PyString_AsString(name));
922         } else {
923                 /* FIXME */
924         }
925         return Py_None;
926 }
927
928 static PyMappingMethods py_ldb_msg_mapping = {
929         .mp_subscript = (binaryfunc)py_ldb_msg_getitem,
930         .mp_ass_subscript = (objobjargproc)py_ldb_msg_setitem,
931 };
932
933 static PyObject *py_ldb_msg_new(PyTypeObject *type, PyObject *args, PyObject *kwargs)
934 {
935         char *kwnames[] = { NULL };
936         if (!PyArg_ParseTupleAndKeywords(args, kwargs, "", kwnames))
937                 return NULL;
938
939         return py_talloc_import(&PyLdbMessage, ldb_msg_new(NULL)); 
940 }
941
942 PyObject *PyLdbMessage_FromMessage(struct ldb_message *msg)
943 {
944         return py_talloc_import(&PyLdbMessage, msg);
945 }
946
947 PyTypeObject PyLdbMessage = {
948         .tp_name = "Message",
949         .tp_methods = py_ldb_msg_methods,
950         .tp_as_mapping = &py_ldb_msg_mapping,
951         .tp_basicsize = sizeof(PyLdbMessageObject),
952         .tp_dealloc = py_talloc_dealloc,
953         .tp_new = py_ldb_msg_new,
954 };
955
956 /* Ldb_module */
957 int py_module_search(struct ldb_module *mod, struct ldb_request *req)
958 {
959     PyObject *py_ldb = mod->private_data;
960     PyObject *py_result, *py_base, *py_attrs, *py_tree;
961
962     py_base = PyLdbDn_FromDn(req->op.search.base);
963
964     if (py_base == NULL)
965         return LDB_ERR_OPERATIONS_ERROR;
966
967     py_tree = PyLdbTree_FromTree(req->op.search.tree);
968
969     if (py_tree == NULL)
970         return LDB_ERR_OPERATIONS_ERROR;
971
972     if (req->op.search.attrs == NULL) {
973         py_attrs = Py_None;
974     } else {
975         int i, len;
976         for (len = 0; req->op.search.attrs[len]; len++);
977         py_attrs = PyList_New(len);
978         for (i = 0; i < len; i++)
979             PyList_SetItem(py_attrs, i, PyString_FromString(req->op.search.attrs[i]));
980     }
981
982     py_result = PyObject_CallMethod(py_ldb, (char *)"search", (char *)"OiOO", py_base, req->op.search.scope, py_tree, py_attrs);
983
984     Py_DECREF(py_attrs);
985     Py_DECREF(py_tree);
986     Py_DECREF(py_base);
987
988     if (py_result == NULL) {
989         return LDB_ERR_OPERATIONS_ERROR;
990     }
991
992         req->op.search.res = PyLdbResult_AsResult(py_result);
993         if (req->op.search.res == NULL) {
994         return LDB_ERR_OPERATIONS_ERROR;
995     }
996
997     Py_DECREF(py_result);
998
999     return LDB_SUCCESS;
1000 }
1001
1002 int py_module_add(struct ldb_module *mod, struct ldb_request *req)
1003 {
1004     PyObject *py_ldb = mod->private_data;
1005     PyObject *py_result, *py_msg;
1006
1007     py_msg = PyLdbMessage_FromMessage(req->op.add.message);
1008
1009     if (py_msg == NULL) {
1010         return LDB_ERR_OPERATIONS_ERROR;
1011     }
1012
1013     py_result = PyObject_CallMethod(py_ldb, (char *)"add", (char *)"O", py_msg);
1014
1015     Py_DECREF(py_msg);
1016
1017     if (py_result == NULL) {
1018         return LDB_ERR_OPERATIONS_ERROR;
1019     }
1020
1021     Py_DECREF(py_result);
1022
1023     return LDB_SUCCESS;
1024 }
1025
1026 int py_module_modify(struct ldb_module *mod, struct ldb_request *req)
1027 {
1028     PyObject *py_ldb = mod->private_data;
1029     PyObject *py_result, *py_msg;
1030
1031     py_msg = PyLdbMessage_FromMessage(req->op.mod.message);
1032
1033     if (py_msg == NULL) {
1034         return LDB_ERR_OPERATIONS_ERROR;
1035     }
1036
1037     py_result = PyObject_CallMethod(py_ldb, (char *)"modify", (char *)"O", py_msg);
1038
1039     Py_DECREF(py_msg);
1040
1041     if (py_result == NULL) {
1042         return LDB_ERR_OPERATIONS_ERROR;
1043     }
1044
1045     Py_DECREF(py_result);
1046
1047     return LDB_SUCCESS;
1048 }
1049
1050 int py_module_del(struct ldb_module *mod, struct ldb_request *req)
1051 {
1052     PyObject *py_ldb = mod->private_data;
1053     PyObject *py_result, *py_dn;
1054
1055     py_dn = PyLdbDn_FromDn(req->op.del.dn);
1056
1057     if (py_dn == NULL)
1058         return LDB_ERR_OPERATIONS_ERROR;
1059
1060     py_result = PyObject_CallMethod(py_ldb, (char *)"delete", (char *)"O", py_dn);
1061
1062     if (py_result == NULL) {
1063         return LDB_ERR_OPERATIONS_ERROR;
1064     }
1065
1066     Py_DECREF(py_result);
1067
1068     return LDB_SUCCESS;
1069 }
1070
1071 int py_module_rename(struct ldb_module *mod, struct ldb_request *req)
1072 {
1073     PyObject *py_ldb = mod->private_data;
1074     PyObject *py_result, *py_olddn, *py_newdn;
1075
1076     py_olddn = PyLdbDn_FromDn(req->op.rename.olddn);
1077
1078     if (py_olddn == NULL)
1079         return LDB_ERR_OPERATIONS_ERROR;
1080
1081     py_newdn = PyLdbDn_FromDn(req->op.rename.newdn);
1082
1083     if (py_newdn == NULL)
1084         return LDB_ERR_OPERATIONS_ERROR;
1085
1086     py_result = PyObject_CallMethod(py_ldb, (char *)"rename", (char *)"OO", py_olddn, py_newdn);
1087
1088     Py_DECREF(py_olddn);
1089     Py_DECREF(py_newdn);
1090
1091     if (py_result == NULL) {
1092         return LDB_ERR_OPERATIONS_ERROR;
1093     }
1094
1095     Py_DECREF(py_result);
1096
1097     return LDB_SUCCESS;
1098 }
1099
1100 int py_module_request(struct ldb_module *mod, struct ldb_request *req)
1101 {
1102     PyObject *py_ldb = mod->private_data;
1103     PyObject *py_result;
1104
1105     py_result = PyObject_CallMethod(py_ldb, (char *)"request", (char *)"");
1106
1107     return LDB_ERR_OPERATIONS_ERROR;
1108 }
1109
1110 int py_module_extended(struct ldb_module *mod, struct ldb_request *req)
1111 {
1112     PyObject *py_ldb = mod->private_data;
1113     PyObject *py_result;
1114
1115     py_result = PyObject_CallMethod(py_ldb, (char *)"extended", (char *)"");
1116
1117     return LDB_ERR_OPERATIONS_ERROR;
1118 }
1119
1120 int py_module_start_transaction(struct ldb_module *mod)
1121 {
1122     PyObject *py_ldb = mod->private_data;
1123     PyObject *py_result;
1124
1125     py_result = PyObject_CallMethod(py_ldb, (char *)"start_transaction", (char *)"");
1126
1127     if (py_result == NULL) {
1128         return LDB_ERR_OPERATIONS_ERROR;
1129     }
1130
1131     Py_DECREF(py_result);
1132
1133     return LDB_SUCCESS;
1134 }
1135
1136 int py_module_end_transaction(struct ldb_module *mod)
1137 {
1138     PyObject *py_ldb = mod->private_data;
1139     PyObject *py_result;
1140
1141     py_result = PyObject_CallMethod(py_ldb, (char *)"end_transaction", (char *)"");
1142
1143     if (py_result == NULL) {
1144         return LDB_ERR_OPERATIONS_ERROR;
1145     }
1146
1147     Py_DECREF(py_result);
1148
1149     return LDB_SUCCESS;
1150 }
1151
1152 int py_module_del_transaction(struct ldb_module *mod)
1153 {
1154     PyObject *py_ldb = mod->private_data;
1155     PyObject *py_result;
1156
1157     py_result = PyObject_CallMethod(py_ldb, (char *)"del_transaction", (char *)"");
1158
1159     if (py_result == NULL) {
1160         return LDB_ERR_OPERATIONS_ERROR;
1161     }
1162
1163     Py_DECREF(py_result);
1164
1165     return LDB_SUCCESS;
1166 }
1167
1168 static int py_module_destructor(void *_mod)
1169 {
1170     struct ldb_module *mod = _mod;
1171     Py_DECREF((PyObject *)mod->private_data);
1172     return 0;
1173 }
1174
1175 int py_module_init (struct ldb_module *mod)
1176 {
1177     PyObject *py_class = mod->ops->private_data;
1178     PyObject *py_result, *py_next, *py_ldb;
1179
1180     py_ldb = SWIG_NewPointerObj(mod->ldb, SWIGTYPE_p_ldb_context, 0);
1181
1182     if (py_ldb == NULL)
1183         return LDB_ERR_OPERATIONS_ERROR;
1184
1185     py_next = PyLdbModule_FromModule(mod->next);
1186
1187     if (py_next == NULL)
1188         return LDB_ERR_OPERATIONS_ERROR;
1189
1190     py_result = PyObject_CallFunction(py_class, (char *)"OO", py_ldb, py_next);
1191
1192     if (py_result == NULL) {
1193         return LDB_ERR_OPERATIONS_ERROR;
1194     }
1195
1196     mod->private_data = py_result;
1197
1198     talloc_set_destructor (mod, py_module_destructor);
1199
1200     return ldb_next_init(mod);
1201 }
1202
1203 static PyObject *py_register_module(PyObject *module, PyObject *args)
1204 {
1205         int ret;
1206         struct ldb_module_ops *ops;
1207         PyObject *input;
1208
1209         if (!PyArg_ParseTuple(args, "O", &input))
1210                 return NULL;
1211
1212     ops = talloc_zero(talloc_autofree_context(), struct ldb_module_ops);
1213         if (ops == NULL) {
1214                 PyErr_NoMemory();
1215                 return NULL;
1216         }
1217
1218     ops->name = talloc_strdup(ops, PyString_AsString(PyObject_GetAttrString(input, (char *)"name")));
1219
1220     Py_INCREF(input);
1221     ops->private_data = input;
1222     ops->init_context = py_module_init;
1223     ops->search = py_module_search;
1224     ops->add = py_module_add;
1225     ops->modify = py_module_modify;
1226     ops->del = py_module_del;
1227     ops->rename = py_module_rename;
1228     ops->request = py_module_request;
1229     ops->extended = py_module_extended;
1230     ops->start_transaction = py_module_start_transaction;
1231     ops->end_transaction = py_module_end_transaction;
1232     ops->del_transaction = py_module_del_transaction;
1233
1234         ret = ldb_register_module(ops);
1235
1236         PyErr_LDB_ERROR_IS_ERR_RAISE(ret, NULL);
1237
1238         return Py_None;
1239 }
1240
1241 static PyObject *py_timestring(PyObject *module, PyObject *args)
1242 {
1243         time_t t;
1244         char *tresult;
1245         PyObject *ret;
1246         if (!PyArg_ParseTuple(args, "L", &t))
1247                 return NULL;
1248     tresult = ldb_timestring(NULL, t);
1249     ret = PyString_FromString(tresult);
1250     talloc_free(tresult);
1251     return ret;
1252 }
1253
1254 static PyObject *py_string_to_time(PyObject *module, PyObject *args)
1255 {
1256         char *str;
1257         if (!PyArg_ParseTuple(args, "s", &str))
1258                 return NULL;
1259
1260         return PyInt_FromLong(ldb_string_to_time(str));
1261 }
1262
1263 static PyObject *py_valid_attr_name(PyObject *self, PyObject *args)
1264 {
1265         char *name;
1266         if (!PyArg_ParseTuple(args, "s", &name))
1267                 return NULL;
1268         return PyBool_FromLong(ldb_valid_attr_name(name));
1269 }
1270
1271 static PyMethodDef py_ldb_global_methods[] = {
1272         { "register_module", py_register_module, METH_VARARGS, 
1273                 "S.register_module(module) -> None\n"
1274                 "Register a LDB module."},
1275         { "timestring", py_timestring, METH_VARARGS, 
1276                 "S.timestring(int) -> string\n"
1277                 "Generate a LDAP time string from a UNIX timestamp" },
1278         { "string_to_time", py_string_to_time, METH_VARARGS,
1279                 "S.string_to_time(string) -> int\n"
1280                 "Parse a LDAP time string into a UNIX timestamp." },
1281         { "valid_attr_name", py_valid_attr_name, METH_VARARGS,
1282                 "S.valid_attr_name(name) -> bool\n"
1283                 "Check whether the supplied name is a valid attribute name." },
1284         { "open", (PyCFunction)py_ldb_new, METH_VARARGS|METH_KEYWORDS,
1285                 NULL },
1286         { NULL }
1287 };
1288
1289 void initldb(void)
1290 {
1291         PyObject *m;
1292
1293         if (PyType_Ready(&PyLdbDn) < 0)
1294                 return;
1295
1296         if (PyType_Ready(&PyLdbMessage) < 0)
1297                 return;
1298
1299         if (PyType_Ready(&PyLdbMessageElement) < 0)
1300                 return;
1301
1302         if (PyType_Ready(&PyLdb) < 0)
1303                 return;
1304
1305         if (PyType_Ready(&PyLdbModule) < 0)
1306                 return;
1307
1308         m = Py_InitModule3("ldb", py_ldb_global_methods, 
1309                 "An interface to LDB, a LDAP-like API that can either to talk an embedded database (TDB-based) or a standards-compliant LDAP server.");
1310         if (m == NULL)
1311                 return;
1312
1313         PyModule_AddObject(m, "SCOPE_DEFAULT", PyInt_FromLong(LDB_SCOPE_DEFAULT));
1314         PyModule_AddObject(m, "SCOPE_BASE", PyInt_FromLong(LDB_SCOPE_BASE));
1315         PyModule_AddObject(m, "SCOPE_ONELEVEL", PyInt_FromLong(LDB_SCOPE_ONELEVEL));
1316         PyModule_AddObject(m, "SCOPE_SUBTREE", PyInt_FromLong(LDB_SCOPE_SUBTREE));
1317
1318         PyModule_AddObject(m, "CHANGETYPE_NONE", PyInt_FromLong(LDB_CHANGETYPE_NONE));
1319         PyModule_AddObject(m, "CHANGETYPE_ADD", PyInt_FromLong(LDB_CHANGETYPE_ADD));
1320         PyModule_AddObject(m, "CHANGETYPE_DELETE", PyInt_FromLong(LDB_CHANGETYPE_DELETE));
1321         PyModule_AddObject(m, "CHANGETYPE_MODIFY", PyInt_FromLong(LDB_CHANGETYPE_MODIFY));
1322
1323         PyModule_AddObject(m, "__docformat__", PyString_FromString("restructuredText"));
1324
1325     PyExc_LdbError = PyErr_NewException((char *)"_ldb.LdbError", NULL, NULL);
1326     PyModule_AddObject(m, "LdbError", PyExc_LdbError);
1327 }
1328
1329 #if 0
1330
1331 /*
1332  * Wrap struct ldb_val
1333  */
1334
1335 %typemap(in,noblock=1) struct ldb_val *INPUT (struct ldb_val temp) {
1336         $1 = &temp;
1337         if (!PyString_Check($input)) {
1338                 PyErr_SetString(PyExc_TypeError, "string arg expected");
1339                 return NULL;
1340         }
1341         $1->length = PyString_Size($input);
1342         $1->data = PyString_AsString($input);
1343 }
1344
1345 %inline %{
1346
1347
1348 %}
1349
1350 %typemap(out,noblock=1) struct ldb_val * {
1351         $result = PyString_FromStringAndSize((const char *)$1->data, $1->length)
1352 }
1353
1354 %typemap(out,noblock=1) struct ldb_val {
1355         $result = PyString_FromStringAndSize((const char *)$1.data, $1.length)
1356 }
1357
1358 /*
1359  * Wrap struct ldb_result
1360  */
1361
1362 %typemap(in,noblock=1,numinputs=0) struct ldb_result ** (struct ldb_result *temp_ldb_result) {
1363         $1 = &temp_ldb_result;
1364 }
1365
1366 %typemap(in,noblock=1,numinputs=1) const char * const *NULL_STR_LIST {
1367     if ($input == Py_None) {
1368         $1 = NULL;
1369     } else if (PySequence_Check($input)) {
1370         int i;
1371         $1 = talloc_array(NULL, char *, PySequence_Size($input)+1);
1372         for(i = 0; i < PySequence_Size($input); i++)
1373             $1[i] = PyString_AsString(PySequence_GetItem($input, i));
1374         $1[i] = NULL;
1375     } else {
1376         SWIG_exception(SWIG_TypeError, "expected sequence");
1377     }
1378 }
1379
1380 %typemap(freearg,noblock=1) const char * const *NULL_STR_LIST {
1381     talloc_free($1);
1382 }
1383
1384 %apply const char * const *NULL_STR_LIST { const char * const *attrs }
1385 %apply const char * const *NULL_STR_LIST { const char * const *options }
1386 %apply const char * const *NULL_STR_LIST { const char * const *control_strings }
1387
1388 /*
1389  * Wrap struct ldb_dn
1390  */
1391
1392 %rename(__len__) ldb_dn::get_comp_num;
1393 typedef struct ldb_dn {
1394     %extend {
1395         %feature("docstring") ldb_dn "S.__init__(ldb, string)\n" \
1396                  "Create a new DN.";
1397         ldb_dn(ldb *ldb_ctx, const char *str)
1398         {
1399             ldb_dn *ret = ldb_dn_new(ldb_ctx, ldb_ctx, str);
1400             /* ldb_dn_new() doesn't accept NULL as memory context, so 
1401                we do it this way... */
1402             talloc_steal(NULL, ret);
1403
1404             if (ret == NULL || !ldb_dn_validate(ret))
1405                 SWIG_exception(SWIG_ValueError, 
1406                                 "unable to parse dn string");
1407 fail:
1408             return ret;
1409         }
1410         ~ldb_dn() { talloc_free($self); }
1411         %feature("docstring") parent "S.parent() -> dn\n" \
1412                                      "Get the parent for this DN.";
1413         ldb_dn *parent() { return ldb_dn_get_parent(NULL, $self); }
1414         int get_comp_num();
1415         %feature("docstring") add_child "S.add_child(dn) -> None\n" \
1416                                          "Add a child DN to this DN.";
1417         bool add_child(ldb_dn *child);
1418         %feature("docstring") add_base "S.add_base(dn) -> None\n" \
1419                                          "Add a base DN to this DN.";
1420         bool add_base(ldb_dn *base);
1421         ldb_dn *__add__(ldb_dn *other)
1422         {
1423             ldb_dn *ret = ldb_dn_copy(NULL, $self);
1424             ldb_dn_add_child(ret, other);
1425             return ret;
1426         }
1427
1428         /* FIXME: implement __getslice__ */
1429     }
1430 } ldb_dn;
1431
1432 %{
1433 struct ldb_context *ldb_context_from_py_object(PyObject *py_obj)
1434 {
1435         struct ldb_context *ldb_ctx;
1436     if (SWIG_ConvertPtr(py_obj, (void *)&ldb_ctx, SWIGTYPE_p_ldb_context, 0 |  0 ) < 0)
1437         return NULL;
1438     return ldb_ctx;
1439 }
1440
1441
1442 %}
1443
1444 /* ldb_message_element */
1445 %rename(MessageElement) ldb_message_element;
1446 %feature("docstring") ldb_message_element "Message element.";
1447 typedef struct ldb_message_element {
1448     %extend {
1449         int __cmp__(ldb_message_element *other)
1450         {
1451             return ldb_msg_element_compare($self, other);
1452         }
1453
1454         PyObject *__iter__(void)
1455         {
1456             return PyObject_GetIter(ldb_msg_element_to_set(NULL, $self));
1457         }
1458
1459         PyObject *__set__(void)
1460         {
1461             return ldb_msg_element_to_set(NULL, $self);
1462         }
1463
1464         ldb_message_element(PyObject *set_obj, int flags=0, const char *name = NULL)
1465         {
1466             return PyObject_AsMessageElement(NULL, set_obj, flags, name);
1467         }
1468
1469         int __len__()
1470         {
1471             return $self->num_values;
1472         }
1473         ~ldb_message_element() { talloc_free($self); }
1474     }
1475     %pythoncode {
1476         def __getitem__(self, i):
1477             ret = self.get(i)
1478             if ret is None:
1479                 raise KeyError("no such value")
1480             return ret
1481
1482         def __repr__(self):
1483             return "MessageElement([%s])" % (",".join(repr(x) for x in self.__set__()))
1484
1485         def __eq__(self, other):
1486             if (len(self) == 1 and self.get(0) == other):
1487                 return True
1488             if isinstance(other, self.__class__):
1489                 return self.__cmp__(other) == 0
1490             o = iter(other)
1491             for i in range(len(self)):
1492                 if self.get(i) != o.next():
1493                     return False
1494             return True
1495     }
1496 } ldb_message_element;
1497
1498 /* ldb_message */
1499
1500 %feature("docstring") ldb_message "Message.";
1501 %rename(Message) ldb_message;
1502 %rename(__delitem__) ldb_message::remove_attr;
1503 %typemap(out) ldb_message_element * {
1504         if ($1 == NULL)
1505                 PyErr_SetString(PyExc_KeyError, "no such element");
1506     else
1507         $result = SWIG_NewPointerObj($1, SWIGTYPE_p_ldb_message_element, 0);
1508 }
1509
1510 %inline {
1511     PyObject *ldb_msg_list_elements(ldb_msg *msg)
1512     {
1513         int i, j = 0;
1514         PyObject *obj = PyList_New(msg->num_elements+(msg->dn != NULL?1:0));
1515         if (msg->dn != NULL) {
1516             PyList_SetItem(obj, j, PyString_FromString("dn"));
1517             j++;
1518         }
1519         for (i = 0; i < msg->num_elements; i++) {
1520             PyList_SetItem(obj, j, PyString_FromString(msg->elements[i].name));
1521             j++;
1522         }
1523         return obj;
1524     }
1525 }
1526
1527
1528 typedef struct ldb_message {
1529         ldb_dn *dn;
1530
1531     %extend {
1532         ldb_msg(ldb_dn *dn = NULL) { 
1533             ret->dn = talloc_reference(ret, dn);
1534             return ret;
1535         }
1536         ~ldb_msg() { talloc_free($self); }
1537         
1538         void __setitem__(const char *attr_name, ldb_message_element *val)
1539         {
1540             struct ldb_message_element *el;
1541             
1542             ldb_msg_remove_attr($self, attr_name);
1543
1544             el = talloc($self, struct ldb_message_element);
1545             el->name = talloc_strdup(el, attr_name);
1546             el->num_values = val->num_values;
1547             el->values = talloc_reference(el, val->values);
1548
1549             ldb_msg_add($self, el, val->flags);
1550         }
1551
1552         void __setitem__(const char *attr_name, PyObject *val)
1553         {
1554             struct ldb_message_element *el = PyObject_AsMessageElement(NULL,
1555                                                 val, 0, attr_name);
1556             talloc_steal($self, el);
1557             ldb_msg_remove_attr($self, attr_name);
1558             ldb_msg_add($self, el, el->flags);
1559         }
1560
1561         unsigned int __len__() { return $self->num_elements; }
1562
1563         PyObject *keys(void)
1564         {
1565             return ldb_msg_list_elements($self);
1566         }
1567
1568         PyObject *__iter__(void)
1569         {
1570             return PyObject_GetIter(ldb_msg_list_elements($self));
1571         }
1572 %pythoncode {
1573     def get(self, key, default=None):
1574         if key == "dn":
1575             return self.dn
1576         return self.find_element(key)
1577
1578     def __getitem__(self, key):
1579         ret = self.get(key, None)
1580         if ret is None:
1581             raise KeyError("No such element")
1582         return ret
1583
1584     def iteritems(self):
1585         for k in self.keys():
1586             yield k, self[k]
1587     
1588     def items(self):
1589         return list(self.iteritems())
1590
1591     def __repr__(self):
1592         return "Message(%s)" % repr(dict(self.iteritems()))
1593 }
1594     }
1595 } ldb_msg;
1596
1597 /* FIXME: Convert ldb_result to 3-tuple:
1598    (msgs, refs, controls)
1599  */
1600
1601 typedef struct ldb_ldif ldb_ldif;
1602
1603 %inline {
1604 }
1605
1606 %typemap(out,noblock=1) struct ldb_control ** {
1607     if ($1 == NULL) {
1608         PyErr_SetObject(PyExc_LdbError, Py_BuildValue((char *)"(s)", ldb_errstring(arg1)));
1609         SWIG_fail;
1610     }
1611     $result = SWIG_NewPointerObj($1, $1_descriptor, 0);
1612 }
1613
1614 /* Top-level ldb operations */
1615 typedef struct ldb_context {
1616     %pythoncode {
1617         def itermodules(self):
1618             m = self.firstmodule
1619             while m is not None:
1620                 yield m
1621                 m = m.next
1622
1623         def modules(self):
1624             return list(self.itermodules())
1625     }
1626
1627     %extend {
1628         ldb_error search_ex(TALLOC_CTX *mem_ctx,
1629                    ldb_dn *base = NULL, 
1630                    enum ldb_scope scope = LDB_SCOPE_DEFAULT, 
1631                    const char *expression = NULL, 
1632                    const char *const *attrs = NULL, 
1633                    struct ldb_control **controls = NULL,
1634                    struct ldb_result **OUT) {
1635             int ret;
1636             struct ldb_result *res;
1637             struct ldb_request *req;
1638             res = talloc_zero(mem_ctx, struct ldb_result);
1639             if (!res) {
1640                 return LDB_ERR_OPERATIONS_ERROR;
1641             }
1642
1643             ret = ldb_build_search_req(&req, $self, mem_ctx,
1644                            base?base:ldb_get_default_basedn($self),
1645                            scope,
1646                            expression,
1647                            attrs,
1648                            controls,
1649                            res,
1650                            ldb_search_default_callback,
1651                            NULL);
1652
1653             if (ret != LDB_SUCCESS) {
1654                 talloc_free(res);
1655                 return ret;
1656             }
1657
1658             ret = ldb_request($self, req);
1659                 
1660             if (ret == LDB_SUCCESS) {
1661                 ret = ldb_wait(req->handle, LDB_WAIT_ALL);
1662             }
1663
1664             talloc_free(req);
1665
1666             *OUT = res;
1667             return ret;
1668         }
1669
1670         struct ldb_control **parse_control_strings(TALLOC_CTX *mem_ctx, 
1671                                                    const char * const*control_strings);
1672         const char *errstring();
1673         %feature("docstring") set_opaque "S.set_opaque(name, value) -> None\n" \
1674             "Set an opaque value on this LDB connection. \n"
1675             ":note: Passing incorrect values may cause crashes.";
1676         ldb_error set_opaque(const char *name, void *value);
1677         %feature("docstring") get_opaque "S.get_opaque(name) -> value\n" \
1678             "Get an opaque value set on this LDB connection. \n"
1679             ":note: The returned value may not be useful in Python.";
1680         void *get_opaque(const char *name);
1681  
1682         %typemap(in,numinputs=0,noblock=1) struct ldb_result **result_as_bool (struct ldb_result *tmp) { $1 = &tmp; }
1683         %typemap(argout,noblock=1) struct ldb_result **result_as_bool { $result = ((*$1)->count > 0)?Py_True:Py_False; }
1684         %typemap(freearg,noblock=1) struct ldb_result **result_as_bool { talloc_free(*$1); }
1685         ldb_error __contains__(ldb_dn *dn, struct ldb_result **result_as_bool)
1686         {
1687             return ldb_search($self, $self, result_as_bool, dn, LDB_SCOPE_BASE, NULL, NULL);
1688         }
1689     }
1690     %pythoncode {
1691         def __init__(self, url=None, flags=0, options=None):
1692             """Create a new LDB object.
1693
1694             Will also connect to the specified URL if one was given.
1695             """
1696             _ldb.Ldb_swiginit(self,_ldb.new_Ldb())
1697             if url is not None:
1698                 self.connect(url, flags, options)
1699
1700         def search(self, base=None, scope=SCOPE_DEFAULT, expression=None, 
1701                    attrs=None, controls=None):
1702             """Search in a database.
1703
1704             :param base: Optional base DN to search
1705             :param scope: Search scope (SCOPE_BASE, SCOPE_ONELEVEL or SCOPE_SUBTREE)
1706             :param expression: Optional search expression
1707             :param attrs: Attributes to return (defaults to all)
1708             :param controls: Optional list of controls
1709             :return: Iterator over Message objects
1710             """
1711             if not (attrs is None or isinstance(attrs, list)):
1712                 raise TypeError("attributes not a list")
1713             parsed_controls = None
1714             if controls is not None:
1715                 parsed_controls = self.parse_control_strings(controls)
1716             return self.search_ex(base, scope, expression, attrs, 
1717                                   parsed_controls)
1718     }
1719
1720 } ldb;
1721 #endif