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