pyldb: Properly preallocate result control list
[Samba.git] / lib / ldb / pyldb.c
blob9ee71eb73fa68a78a6ee27abcaeaf0e05adedc0b
1 /*
2 Unix SMB/CIFS implementation.
4 Python interface to ldb.
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 Copyright (C) 2009-2011 Andrew Tridgell
11 Copyright (C) 2009-2011 Andrew Bartlett
13 ** NOTE! The following LGPL license applies to the ldb
14 ** library. This does NOT imply that all of Samba is released
15 ** under the LGPL
17 This library is free software; you can redistribute it and/or
18 modify it under the terms of the GNU Lesser General Public
19 License as published by the Free Software Foundation; either
20 version 3 of the License, or (at your option) any later version.
22 This library is distributed in the hope that it will be useful,
23 but WITHOUT ANY WARRANTY; without even the implied warranty of
24 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
25 Lesser General Public License for more details.
27 You should have received a copy of the GNU Lesser General Public
28 License along with this library; if not, see <http://www.gnu.org/licenses/>.
31 #include <Python.h>
32 #include "ldb_private.h"
33 #include "pyldb.h"
35 void initldb(void);
36 static PyObject *PyLdbMessage_FromMessage(struct ldb_message *msg);
37 static PyObject *PyExc_LdbError;
39 static PyTypeObject PyLdbControl;
40 static PyTypeObject PyLdbResult;
41 static PyTypeObject PyLdbMessage;
42 #define PyLdbMessage_Check(ob) PyObject_TypeCheck(ob, &PyLdbMessage)
43 static PyTypeObject PyLdbModule;
44 static PyTypeObject PyLdbDn;
45 #define pyldb_Dn_Check(ob) PyObject_TypeCheck(ob, &PyLdbDn)
46 static PyTypeObject PyLdb;
47 #define PyLdb_Check(ob) PyObject_TypeCheck(ob, &PyLdb)
48 static PyTypeObject PyLdbMessageElement;
49 #define pyldb_MessageElement_Check(ob) PyObject_TypeCheck(ob, &PyLdbMessageElement)
51 staticforward PyTypeObject PyLdbTree;
52 static PyObject *PyLdb_FromLdbContext(struct ldb_context *ldb_ctx);
53 static PyObject *PyLdbModule_FromModule(struct ldb_module *mod);
54 static struct ldb_message_element *PyObject_AsMessageElement(
55 TALLOC_CTX *mem_ctx,
56 PyObject *set_obj,
57 unsigned int flags,
58 const char *attr_name);
60 /* There's no Py_ssize_t in 2.4, apparently */
61 #if PY_MAJOR_VERSION == 2 && PY_MINOR_VERSION < 5
62 typedef int Py_ssize_t;
63 typedef inquiry lenfunc;
64 typedef intargfunc ssizeargfunc;
65 #endif
67 #define SIGN(a) (((a) == 0)?0:((a) < 0?-1:1))
71 static PyObject *py_ldb_control_str(PyLdbControlObject *self)
73 if (self->data != NULL) {
74 char* control = ldb_control_to_string(self->mem_ctx, self->data);
75 if (control == NULL) {
76 PyErr_NoMemory();
77 return NULL;
79 return PyString_FromString(control);
80 } else {
81 return PyString_FromFormat("ldb control");
85 static void py_ldb_control_dealloc(PyLdbControlObject *self)
87 if (self->mem_ctx != NULL) {
88 talloc_free(self->mem_ctx);
90 self->data = NULL;
91 Py_TYPE(self)->tp_free(self);
94 static PyObject *py_ldb_control_get_oid(PyLdbControlObject *self)
96 return PyString_FromString(self->data->oid);
99 static PyObject *py_ldb_control_get_critical(PyLdbControlObject *self)
101 return PyBool_FromLong(self->data->critical);
104 static PyObject *py_ldb_control_set_critical(PyLdbControlObject *self, PyObject *value, void *closure)
106 if (PyObject_IsTrue(value)) {
107 self->data->critical = true;
108 } else {
109 self->data->critical = false;
111 return 0;
114 static PyObject *py_ldb_control_new(PyTypeObject *type, PyObject *args, PyObject *kwargs)
116 char *data = NULL;
117 const char * const kwnames[] = { "ldb", "data", NULL };
118 struct ldb_control *parsed_controls;
119 PyLdbControlObject *ret;
120 PyObject *py_ldb;
121 TALLOC_CTX *mem_ctx;
122 struct ldb_context *ldb_ctx;
124 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "Os",
125 discard_const_p(char *, kwnames),
126 &py_ldb, &data))
127 return NULL;
129 mem_ctx = talloc_new(NULL);
130 if (mem_ctx == NULL) {
131 PyErr_NoMemory();
132 return NULL;
135 ldb_ctx = pyldb_Ldb_AsLdbContext(py_ldb);
136 parsed_controls = ldb_parse_control_from_string(ldb_ctx, mem_ctx, data);
138 if (!parsed_controls) {
139 talloc_free(mem_ctx);
140 PyErr_SetString(PyExc_ValueError, "unable to parse control string");
141 return NULL;
144 ret = PyObject_New(PyLdbControlObject, type);
145 if (ret == NULL) {
146 PyErr_NoMemory();
147 talloc_free(mem_ctx);
148 return NULL;
151 ret->mem_ctx = mem_ctx;
153 ret->data = talloc_move(mem_ctx, &parsed_controls);
154 if (ret->data == NULL) {
155 Py_DECREF(ret);
156 PyErr_NoMemory();
157 talloc_free(mem_ctx);
158 return NULL;
161 return (PyObject *)ret;
164 static PyGetSetDef py_ldb_control_getset[] = {
165 { discard_const_p(char, "oid"), (getter)py_ldb_control_get_oid, NULL, NULL },
166 { discard_const_p(char, "critical"), (getter)py_ldb_control_get_critical, (setter)py_ldb_control_set_critical, NULL },
167 { NULL }
170 static PyTypeObject PyLdbControl = {
171 .tp_name = "ldb.control",
172 .tp_dealloc = (destructor)py_ldb_control_dealloc,
173 .tp_getattro = PyObject_GenericGetAttr,
174 .tp_basicsize = sizeof(PyLdbControlObject),
175 .tp_getset = py_ldb_control_getset,
176 .tp_doc = "LDB control.",
177 .tp_str = (reprfunc)py_ldb_control_str,
178 .tp_new = py_ldb_control_new,
179 .tp_flags = Py_TPFLAGS_DEFAULT|Py_TPFLAGS_BASETYPE,
182 static void PyErr_SetLdbError(PyObject *error, int ret, struct ldb_context *ldb_ctx)
184 if (ret == LDB_ERR_PYTHON_EXCEPTION)
185 return; /* Python exception should already be set, just keep that */
187 PyErr_SetObject(error,
188 Py_BuildValue(discard_const_p(char, "(i,s)"), ret,
189 ldb_ctx == NULL?ldb_strerror(ret):ldb_errstring(ldb_ctx)));
192 static PyObject *PyObject_FromLdbValue(const struct ldb_val *val)
194 return PyString_FromStringAndSize((const char *)val->data, val->length);
198 * Create a Python object from a ldb_result.
200 * @param result LDB result to convert
201 * @return Python object with converted result (a list object)
203 static PyObject *PyLdbControl_FromControl(struct ldb_control *control)
205 TALLOC_CTX *ctl_ctx = talloc_new(NULL);
206 PyLdbControlObject *ctrl;
207 if (ctl_ctx == NULL) {
208 PyErr_NoMemory();
209 return NULL;
212 ctrl = (PyLdbControlObject *)PyLdbControl.tp_alloc(&PyLdbControl, 0);
213 if (ctrl == NULL) {
214 talloc_free(ctl_ctx);
215 PyErr_NoMemory();
216 return NULL;
218 ctrl->mem_ctx = ctl_ctx;
219 ctrl->data = talloc_steal(ctrl->mem_ctx, control);
220 if (ctrl->data == NULL) {
221 Py_DECREF(ctrl);
222 PyErr_NoMemory();
223 return NULL;
225 return (PyObject*) ctrl;
229 * Create a Python object from a ldb_result.
231 * @param result LDB result to convert
232 * @return Python object with converted result (a list object)
234 static PyObject *PyLdbResult_FromResult(struct ldb_result *result)
236 PyLdbResultObject *ret;
237 PyObject *list, *controls, *referals;
238 Py_ssize_t i;
240 if (result == NULL) {
241 Py_RETURN_NONE;
244 ret = (PyLdbResultObject *)PyLdbResult.tp_alloc(&PyLdbResult, 0);
245 if (ret == NULL) {
246 PyErr_NoMemory();
247 return NULL;
250 list = PyList_New(result->count);
251 if (list == NULL) {
252 PyErr_NoMemory();
253 Py_DECREF(ret);
254 return NULL;
257 for (i = 0; i < result->count; i++) {
258 PyList_SetItem(list, i, PyLdbMessage_FromMessage(result->msgs[i]));
261 ret->mem_ctx = talloc_new(NULL);
262 if (ret->mem_ctx == NULL) {
263 Py_DECREF(list);
264 Py_DECREF(ret);
265 PyErr_NoMemory();
266 return NULL;
269 ret->msgs = list;
271 if (result->controls) {
272 i = 0;
273 while (result->controls[i]) {
274 i++;
276 controls = PyList_New(i);
277 if (controls == NULL) {
278 Py_DECREF(ret);
279 PyErr_NoMemory();
280 return NULL;
282 for (i=0; result->controls[i]; i++) {
283 PyObject *ctrl = (PyObject*) PyLdbControl_FromControl(result->controls[i]);
284 if (ctrl == NULL) {
285 Py_DECREF(ret);
286 Py_DECREF(controls);
287 PyErr_NoMemory();
288 return NULL;
290 PyList_SetItem(controls, i, ctrl);
292 } else {
294 * No controls so we keep an empty list
296 controls = PyList_New(0);
297 if (controls == NULL) {
298 Py_DECREF(ret);
299 PyErr_NoMemory();
300 return NULL;
304 ret->controls = controls;
306 i = 0;
308 while (result->refs && result->refs[i]) {
309 i++;
312 referals = PyList_New(i);
313 if (referals == NULL) {
314 Py_DECREF(ret);
315 PyErr_NoMemory();
316 return NULL;
319 for (i = 0;result->refs && result->refs[i]; i++) {
320 PyList_SetItem(referals, i, PyString_FromString(result->refs[i]));
322 ret->referals = referals;
323 return (PyObject *)ret;
327 * Create a LDB Result from a Python object.
328 * If conversion fails, NULL will be returned and a Python exception set.
330 * Note: the result object only includes the messages at the moment; extended
331 * result, controls and referrals are ignored.
333 * @param mem_ctx Memory context in which to allocate the LDB Result
334 * @param obj Python object to convert
335 * @return a ldb_result, or NULL if the conversion failed
337 static struct ldb_result *PyLdbResult_AsResult(TALLOC_CTX *mem_ctx,
338 PyObject *obj)
340 struct ldb_result *res;
341 Py_ssize_t i;
343 if (obj == Py_None)
344 return NULL;
346 res = talloc_zero(mem_ctx, struct ldb_result);
347 res->count = PyList_Size(obj);
348 res->msgs = talloc_array(res, struct ldb_message *, res->count);
349 for (i = 0; i < res->count; i++) {
350 PyObject *item = PyList_GetItem(obj, i);
351 res->msgs[i] = pyldb_Message_AsMessage(item);
353 return res;
356 static PyObject *py_ldb_dn_validate(PyLdbDnObject *self)
358 return PyBool_FromLong(ldb_dn_validate(self->dn));
361 static PyObject *py_ldb_dn_is_valid(PyLdbDnObject *self)
363 return PyBool_FromLong(ldb_dn_is_valid(self->dn));
366 static PyObject *py_ldb_dn_is_special(PyLdbDnObject *self)
368 return PyBool_FromLong(ldb_dn_is_special(self->dn));
371 static PyObject *py_ldb_dn_is_null(PyLdbDnObject *self)
373 return PyBool_FromLong(ldb_dn_is_null(self->dn));
376 static PyObject *py_ldb_dn_get_casefold(PyLdbDnObject *self)
378 return PyString_FromString(ldb_dn_get_casefold(self->dn));
381 static PyObject *py_ldb_dn_get_linearized(PyLdbDnObject *self)
383 return PyString_FromString(ldb_dn_get_linearized(self->dn));
386 static PyObject *py_ldb_dn_canonical_str(PyLdbDnObject *self)
388 return PyString_FromString(ldb_dn_canonical_string(self->dn, self->dn));
391 static PyObject *py_ldb_dn_canonical_ex_str(PyLdbDnObject *self)
393 return PyString_FromString(ldb_dn_canonical_ex_string(self->dn, self->dn));
396 static PyObject *py_ldb_dn_extended_str(PyLdbDnObject *self, PyObject *args, PyObject *kwargs)
398 const char * const kwnames[] = { "mode", NULL };
399 int mode = 1;
400 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "|i",
401 discard_const_p(char *, kwnames),
402 &mode))
403 return NULL;
404 return PyString_FromString(ldb_dn_get_extended_linearized(self->dn, self->dn, mode));
407 static PyObject *py_ldb_dn_get_extended_component(PyLdbDnObject *self, PyObject *args)
409 char *name;
410 const struct ldb_val *val;
412 if (!PyArg_ParseTuple(args, "s", &name))
413 return NULL;
414 val = ldb_dn_get_extended_component(self->dn, name);
415 if (val == NULL) {
416 Py_RETURN_NONE;
419 return PyString_FromStringAndSize((const char *)val->data, val->length);
422 static PyObject *py_ldb_dn_set_extended_component(PyLdbDnObject *self, PyObject *args)
424 char *name;
425 PyObject *value;
426 int err;
428 if (!PyArg_ParseTuple(args, "sO", &name, &value))
429 return NULL;
431 if (value == Py_None) {
432 err = ldb_dn_set_extended_component(self->dn, name, NULL);
433 } else {
434 struct ldb_val val;
435 if (!PyString_Check(value)) {
436 PyErr_SetString(PyExc_TypeError, "Expected a string argument");
437 return NULL;
439 val.data = (uint8_t *)PyString_AsString(value);
440 val.length = PyString_Size(value);
441 err = ldb_dn_set_extended_component(self->dn, name, &val);
444 if (err != LDB_SUCCESS) {
445 PyErr_SetString(PyExc_TypeError, "Failed to set extended component");
446 return NULL;
449 Py_RETURN_NONE;
452 static PyObject *py_ldb_dn_repr(PyLdbDnObject *self)
454 return PyString_FromFormat("Dn(%s)", PyObject_REPR(PyString_FromString(ldb_dn_get_linearized(self->dn))));
457 static PyObject *py_ldb_dn_check_special(PyLdbDnObject *self, PyObject *args)
459 char *name;
461 if (!PyArg_ParseTuple(args, "s", &name))
462 return NULL;
464 return PyBool_FromLong(ldb_dn_check_special(self->dn, name));
467 static int py_ldb_dn_compare(PyLdbDnObject *dn1, PyLdbDnObject *dn2)
469 int ret;
470 ret = ldb_dn_compare(dn1->dn, dn2->dn);
471 if (ret < 0) ret = -1;
472 if (ret > 0) ret = 1;
473 return ret;
476 static PyObject *py_ldb_dn_get_parent(PyLdbDnObject *self)
478 struct ldb_dn *dn = pyldb_Dn_AsDn((PyObject *)self);
479 struct ldb_dn *parent;
480 PyLdbDnObject *py_ret;
481 TALLOC_CTX *mem_ctx = talloc_new(NULL);
483 parent = ldb_dn_get_parent(mem_ctx, dn);
484 if (parent == NULL) {
485 talloc_free(mem_ctx);
486 Py_RETURN_NONE;
489 py_ret = (PyLdbDnObject *)PyLdbDn.tp_alloc(&PyLdbDn, 0);
490 if (py_ret == NULL) {
491 PyErr_NoMemory();
492 talloc_free(mem_ctx);
493 return NULL;
495 py_ret->mem_ctx = mem_ctx;
496 py_ret->dn = parent;
497 return (PyObject *)py_ret;
500 #define dn_ldb_ctx(dn) ((struct ldb_context *)dn)
502 static PyObject *py_ldb_dn_add_child(PyLdbDnObject *self, PyObject *args)
504 PyObject *py_other;
505 struct ldb_dn *dn, *other;
506 if (!PyArg_ParseTuple(args, "O", &py_other))
507 return NULL;
509 dn = pyldb_Dn_AsDn((PyObject *)self);
511 if (!pyldb_Object_AsDn(NULL, py_other, dn_ldb_ctx(dn), &other))
512 return NULL;
514 return PyBool_FromLong(ldb_dn_add_child(dn, other));
517 static PyObject *py_ldb_dn_add_base(PyLdbDnObject *self, PyObject *args)
519 PyObject *py_other;
520 struct ldb_dn *other, *dn;
521 if (!PyArg_ParseTuple(args, "O", &py_other))
522 return NULL;
524 dn = pyldb_Dn_AsDn((PyObject *)self);
526 if (!pyldb_Object_AsDn(NULL, py_other, dn_ldb_ctx(dn), &other))
527 return NULL;
529 return PyBool_FromLong(ldb_dn_add_base(dn, other));
532 static PyObject *py_ldb_dn_remove_base_components(PyLdbDnObject *self, PyObject *args)
534 struct ldb_dn *dn;
535 int i;
536 if (!PyArg_ParseTuple(args, "i", &i))
537 return NULL;
539 dn = pyldb_Dn_AsDn((PyObject *)self);
541 return PyBool_FromLong(ldb_dn_remove_base_components(dn, i));
544 static PyObject *py_ldb_dn_is_child_of(PyLdbDnObject *self, PyObject *args)
546 PyObject *py_base;
547 struct ldb_dn *dn, *base;
548 if (!PyArg_ParseTuple(args, "O", &py_base))
549 return NULL;
551 dn = pyldb_Dn_AsDn((PyObject *)self);
553 if (!pyldb_Object_AsDn(NULL, py_base, dn_ldb_ctx(dn), &base))
554 return NULL;
556 return PyBool_FromLong(ldb_dn_compare_base(base, dn) == 0);
559 static PyObject *py_ldb_dn_get_component_name(PyLdbDnObject *self, PyObject *args)
561 struct ldb_dn *dn;
562 const char *name;
563 unsigned int num = 0;
565 if (!PyArg_ParseTuple(args, "I", &num))
566 return NULL;
568 dn = pyldb_Dn_AsDn((PyObject *)self);
570 name = ldb_dn_get_component_name(dn, num);
571 if (name == NULL) {
572 Py_RETURN_NONE;
575 return PyString_FromString(name);
578 static PyObject *py_ldb_dn_get_component_value(PyLdbDnObject *self, PyObject *args)
580 struct ldb_dn *dn;
581 const struct ldb_val *val;
582 unsigned int num = 0;
584 if (!PyArg_ParseTuple(args, "I", &num))
585 return NULL;
587 dn = pyldb_Dn_AsDn((PyObject *)self);
589 val = ldb_dn_get_component_val(dn, num);
590 if (val == NULL) {
591 Py_RETURN_NONE;
594 return PyObject_FromLdbValue(val);
597 static PyObject *py_ldb_dn_set_component(PyLdbDnObject *self, PyObject *args)
599 unsigned int num = 0;
600 char *name = NULL;
601 PyObject *value = Py_None;
602 struct ldb_val val = { NULL, };
603 int err;
605 if (!PyArg_ParseTuple(args, "IsO", &num, &name, &value))
606 return NULL;
608 if (value != Py_None) {
609 if (!PyString_Check(value)) {
610 PyErr_SetString(PyExc_TypeError, "Expected a string argument");
611 return NULL;
613 val.data = (uint8_t *)PyString_AsString(value);
614 val.length = PyString_Size(value);
617 err = ldb_dn_set_component(self->dn, num, name, val);
618 if (err != LDB_SUCCESS) {
619 PyErr_SetString(PyExc_TypeError, "Failed to set component");
620 return NULL;
623 Py_RETURN_NONE;
626 static PyObject *py_ldb_dn_get_rdn_name(PyLdbDnObject *self)
628 struct ldb_dn *dn;
629 const char *name;
631 dn = pyldb_Dn_AsDn((PyObject *)self);
633 name = ldb_dn_get_rdn_name(dn);
634 if (name == NULL) {
635 Py_RETURN_NONE;
638 return PyString_FromString(name);
641 static PyObject *py_ldb_dn_get_rdn_value(PyLdbDnObject *self)
643 struct ldb_dn *dn;
644 const struct ldb_val *val;
646 dn = pyldb_Dn_AsDn((PyObject *)self);
648 val = ldb_dn_get_rdn_val(dn);
649 if (val == NULL) {
650 Py_RETURN_NONE;
653 return PyObject_FromLdbValue(val);
656 static PyMethodDef py_ldb_dn_methods[] = {
657 { "validate", (PyCFunction)py_ldb_dn_validate, METH_NOARGS,
658 "S.validate() -> bool\n"
659 "Validate DN is correct." },
660 { "is_valid", (PyCFunction)py_ldb_dn_is_valid, METH_NOARGS,
661 "S.is_valid() -> bool\n" },
662 { "is_special", (PyCFunction)py_ldb_dn_is_special, METH_NOARGS,
663 "S.is_special() -> bool\n"
664 "Check whether this is a special LDB DN." },
665 { "is_null", (PyCFunction)py_ldb_dn_is_null, METH_NOARGS,
666 "Check whether this is a null DN." },
667 { "get_casefold", (PyCFunction)py_ldb_dn_get_casefold, METH_NOARGS,
668 NULL },
669 { "get_linearized", (PyCFunction)py_ldb_dn_get_linearized, METH_NOARGS,
670 NULL },
671 { "canonical_str", (PyCFunction)py_ldb_dn_canonical_str, METH_NOARGS,
672 "S.canonical_str() -> string\n"
673 "Canonical version of this DN (like a posix path)." },
674 { "is_child_of", (PyCFunction)py_ldb_dn_is_child_of, METH_VARARGS,
675 "S.is_child_of(basedn) -> int\nReturns True if this DN is a child of basedn\n"},
676 { "canonical_ex_str", (PyCFunction)py_ldb_dn_canonical_ex_str, METH_NOARGS,
677 "S.canonical_ex_str() -> string\n"
678 "Canonical version of this DN (like a posix path, with terminating newline)." },
679 { "extended_str", (PyCFunction)py_ldb_dn_extended_str, METH_VARARGS | METH_KEYWORDS,
680 "S.extended_str(mode=1) -> string\n"
681 "Extended version of this DN" },
682 { "parent", (PyCFunction)py_ldb_dn_get_parent, METH_NOARGS,
683 "S.parent() -> dn\n"
684 "Get the parent for this DN." },
685 { "add_child", (PyCFunction)py_ldb_dn_add_child, METH_VARARGS,
686 "S.add_child(dn) -> None\n"
687 "Add a child DN to this DN." },
688 { "add_base", (PyCFunction)py_ldb_dn_add_base, METH_VARARGS,
689 "S.add_base(dn) -> None\n"
690 "Add a base DN to this DN." },
691 { "remove_base_components", (PyCFunction)py_ldb_dn_remove_base_components, METH_VARARGS,
692 "S.remove_base_components(int) -> bool\n"
693 "Remove a number of DN components from the base of this DN." },
694 { "check_special", (PyCFunction)py_ldb_dn_check_special, METH_VARARGS,
695 "S.check_special(name) -> bool\n\n"
696 "Check if name is a special DN name"},
697 { "get_extended_component", (PyCFunction)py_ldb_dn_get_extended_component, METH_VARARGS,
698 "S.get_extended_component(name) -> string\n\n"
699 "returns a DN extended component as a binary string"},
700 { "set_extended_component", (PyCFunction)py_ldb_dn_set_extended_component, METH_VARARGS,
701 "S.set_extended_component(name, value) -> None\n\n"
702 "set a DN extended component as a binary string"},
703 { "get_component_name", (PyCFunction)py_ldb_dn_get_component_name, METH_VARARGS,
704 "S.get_component_name(num) -> string\n"
705 "get the attribute name of the specified component" },
706 { "get_component_value", (PyCFunction)py_ldb_dn_get_component_value, METH_VARARGS,
707 "S.get_component_value(num) -> string\n"
708 "get the attribute value of the specified component as a binary string" },
709 { "set_component", (PyCFunction)py_ldb_dn_set_component, METH_VARARGS,
710 "S.get_component_value(num, name, value) -> None\n"
711 "set the attribute name and value of the specified component" },
712 { "get_rdn_name", (PyCFunction)py_ldb_dn_get_rdn_name, METH_NOARGS,
713 "S.get_rdn_name() -> string\n"
714 "get the RDN attribute name" },
715 { "get_rdn_value", (PyCFunction)py_ldb_dn_get_rdn_value, METH_NOARGS,
716 "S.get_rdn_value() -> string\n"
717 "get the RDN attribute value as a binary string" },
718 { NULL }
721 static Py_ssize_t py_ldb_dn_len(PyLdbDnObject *self)
723 return ldb_dn_get_comp_num(pyldb_Dn_AsDn((PyObject *)self));
727 copy a DN as a python object
729 static PyObject *py_ldb_dn_copy(struct ldb_dn *dn)
731 PyLdbDnObject *py_ret;
733 py_ret = (PyLdbDnObject *)PyLdbDn.tp_alloc(&PyLdbDn, 0);
734 if (py_ret == NULL) {
735 PyErr_NoMemory();
736 return NULL;
738 py_ret->mem_ctx = talloc_new(NULL);
739 py_ret->dn = ldb_dn_copy(py_ret->mem_ctx, dn);
740 return (PyObject *)py_ret;
743 static PyObject *py_ldb_dn_concat(PyLdbDnObject *self, PyObject *py_other)
745 struct ldb_dn *dn = pyldb_Dn_AsDn((PyObject *)self),
746 *other;
747 PyLdbDnObject *py_ret;
749 if (!pyldb_Object_AsDn(NULL, py_other, NULL, &other))
750 return NULL;
752 py_ret = (PyLdbDnObject *)PyLdbDn.tp_alloc(&PyLdbDn, 0);
753 if (py_ret == NULL) {
754 PyErr_NoMemory();
755 return NULL;
757 py_ret->mem_ctx = talloc_new(NULL);
758 py_ret->dn = ldb_dn_copy(py_ret->mem_ctx, dn);
759 ldb_dn_add_base(py_ret->dn, other);
760 return (PyObject *)py_ret;
763 static PySequenceMethods py_ldb_dn_seq = {
764 .sq_length = (lenfunc)py_ldb_dn_len,
765 .sq_concat = (binaryfunc)py_ldb_dn_concat,
768 static PyObject *py_ldb_dn_new(PyTypeObject *type, PyObject *args, PyObject *kwargs)
770 struct ldb_dn *ret;
771 char *str;
772 PyObject *py_ldb;
773 struct ldb_context *ldb_ctx;
774 TALLOC_CTX *mem_ctx;
775 PyLdbDnObject *py_ret;
776 const char * const kwnames[] = { "ldb", "dn", NULL };
778 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "Os",
779 discard_const_p(char *, kwnames),
780 &py_ldb, &str))
781 return NULL;
783 if (!PyLdb_Check(py_ldb)) {
784 PyErr_SetString(PyExc_TypeError, "Expected Ldb");
785 return NULL;
788 ldb_ctx = pyldb_Ldb_AsLdbContext(py_ldb);
790 mem_ctx = talloc_new(NULL);
791 if (mem_ctx == NULL) {
792 PyErr_NoMemory();
793 return NULL;
796 ret = ldb_dn_new(mem_ctx, ldb_ctx, str);
797 if (!ldb_dn_validate(ret)) {
798 talloc_free(mem_ctx);
799 PyErr_SetString(PyExc_ValueError, "unable to parse dn string");
800 return NULL;
803 py_ret = (PyLdbDnObject *)type->tp_alloc(type, 0);
804 if (ret == NULL) {
805 talloc_free(mem_ctx);
806 PyErr_NoMemory();
807 return NULL;
809 py_ret->mem_ctx = mem_ctx;
810 py_ret->dn = ret;
811 return (PyObject *)py_ret;
814 static void py_ldb_dn_dealloc(PyLdbDnObject *self)
816 talloc_free(self->mem_ctx);
817 PyObject_Del(self);
820 static PyTypeObject PyLdbDn = {
821 .tp_name = "ldb.Dn",
822 .tp_methods = py_ldb_dn_methods,
823 .tp_str = (reprfunc)py_ldb_dn_get_linearized,
824 .tp_repr = (reprfunc)py_ldb_dn_repr,
825 .tp_compare = (cmpfunc)py_ldb_dn_compare,
826 .tp_as_sequence = &py_ldb_dn_seq,
827 .tp_doc = "A LDB distinguished name.",
828 .tp_new = py_ldb_dn_new,
829 .tp_dealloc = (destructor)py_ldb_dn_dealloc,
830 .tp_basicsize = sizeof(PyLdbDnObject),
831 .tp_flags = Py_TPFLAGS_DEFAULT,
834 /* Debug */
835 static void py_ldb_debug(void *context, enum ldb_debug_level level, const char *fmt, va_list ap) PRINTF_ATTRIBUTE(3, 0);
836 static void py_ldb_debug(void *context, enum ldb_debug_level level, const char *fmt, va_list ap)
838 PyObject *fn = (PyObject *)context;
839 PyObject_CallFunction(fn, discard_const_p(char, "(i,O)"), level, PyString_FromFormatV(fmt, ap));
842 static PyObject *py_ldb_set_debug(PyObject *self, PyObject *args)
844 PyObject *cb;
845 struct ldb_context *ldb_ctx;
847 if (!PyArg_ParseTuple(args, "O", &cb))
848 return NULL;
850 Py_INCREF(cb);
851 /* FIXME: Where do we DECREF cb ? */
852 ldb_ctx = pyldb_Ldb_AsLdbContext(self);
853 PyErr_LDB_ERROR_IS_ERR_RAISE(PyExc_LdbError,
854 ldb_set_debug(ldb_ctx, py_ldb_debug, cb),
855 ldb_ctx);
857 Py_RETURN_NONE;
860 static PyObject *py_ldb_set_create_perms(PyTypeObject *self, PyObject *args)
862 unsigned int perms;
863 if (!PyArg_ParseTuple(args, "I", &perms))
864 return NULL;
866 ldb_set_create_perms(pyldb_Ldb_AsLdbContext(self), perms);
868 Py_RETURN_NONE;
871 static PyObject *py_ldb_set_modules_dir(PyTypeObject *self, PyObject *args)
873 char *modules_dir;
874 if (!PyArg_ParseTuple(args, "s", &modules_dir))
875 return NULL;
877 ldb_set_modules_dir(pyldb_Ldb_AsLdbContext(self), modules_dir);
879 Py_RETURN_NONE;
882 static PyObject *py_ldb_transaction_start(PyLdbObject *self)
884 struct ldb_context *ldb_ctx = pyldb_Ldb_AsLdbContext(self);
885 int ldb_err;
886 ldb_err = ldb_transaction_start(ldb_ctx);
887 PyErr_LDB_ERROR_IS_ERR_RAISE(PyExc_LdbError, ldb_err, ldb_ctx);
888 Py_RETURN_NONE;
891 static PyObject *py_ldb_transaction_commit(PyLdbObject *self)
893 struct ldb_context *ldb_ctx = pyldb_Ldb_AsLdbContext(self);
894 int ldb_err;
895 ldb_err = ldb_transaction_commit(ldb_ctx);
896 PyErr_LDB_ERROR_IS_ERR_RAISE(PyExc_LdbError, ldb_err, ldb_ctx);
897 Py_RETURN_NONE;
900 static PyObject *py_ldb_transaction_prepare_commit(PyLdbObject *self)
902 struct ldb_context *ldb_ctx = pyldb_Ldb_AsLdbContext(self);
903 int ldb_err;
904 ldb_err = ldb_transaction_prepare_commit(ldb_ctx);
905 PyErr_LDB_ERROR_IS_ERR_RAISE(PyExc_LdbError, ldb_err, ldb_ctx);
906 Py_RETURN_NONE;
909 static PyObject *py_ldb_transaction_cancel(PyLdbObject *self)
911 struct ldb_context *ldb_ctx = pyldb_Ldb_AsLdbContext(self);
912 int ldb_err;
913 ldb_err = ldb_transaction_cancel(ldb_ctx);
914 PyErr_LDB_ERROR_IS_ERR_RAISE(PyExc_LdbError, ldb_err, ldb_ctx);
915 Py_RETURN_NONE;
918 static PyObject *py_ldb_setup_wellknown_attributes(PyLdbObject *self)
920 struct ldb_context *ldb_ctx = pyldb_Ldb_AsLdbContext(self);
921 int ldb_err;
922 ldb_err = ldb_setup_wellknown_attributes(ldb_ctx);
923 PyErr_LDB_ERROR_IS_ERR_RAISE(PyExc_LdbError, ldb_err, ldb_ctx);
924 Py_RETURN_NONE;
927 static PyObject *py_ldb_repr(PyLdbObject *self)
929 return PyString_FromFormat("<ldb connection>");
932 static PyObject *py_ldb_get_root_basedn(PyLdbObject *self)
934 struct ldb_dn *dn = ldb_get_root_basedn(pyldb_Ldb_AsLdbContext(self));
935 if (dn == NULL)
936 Py_RETURN_NONE;
937 return py_ldb_dn_copy(dn);
941 static PyObject *py_ldb_get_schema_basedn(PyLdbObject *self)
943 struct ldb_dn *dn = ldb_get_schema_basedn(pyldb_Ldb_AsLdbContext(self));
944 if (dn == NULL)
945 Py_RETURN_NONE;
946 return py_ldb_dn_copy(dn);
949 static PyObject *py_ldb_get_config_basedn(PyLdbObject *self)
951 struct ldb_dn *dn = ldb_get_config_basedn(pyldb_Ldb_AsLdbContext(self));
952 if (dn == NULL)
953 Py_RETURN_NONE;
954 return py_ldb_dn_copy(dn);
957 static PyObject *py_ldb_get_default_basedn(PyLdbObject *self)
959 struct ldb_dn *dn = ldb_get_default_basedn(pyldb_Ldb_AsLdbContext(self));
960 if (dn == NULL)
961 Py_RETURN_NONE;
962 return py_ldb_dn_copy(dn);
965 static const char **PyList_AsStringList(TALLOC_CTX *mem_ctx, PyObject *list,
966 const char *paramname)
968 const char **ret;
969 Py_ssize_t i;
970 if (!PyList_Check(list)) {
971 PyErr_Format(PyExc_TypeError, "%s is not a list", paramname);
972 return NULL;
974 ret = talloc_array(NULL, const char *, PyList_Size(list)+1);
975 if (ret == NULL) {
976 PyErr_NoMemory();
977 return NULL;
980 for (i = 0; i < PyList_Size(list); i++) {
981 PyObject *item = PyList_GetItem(list, i);
982 if (!PyString_Check(item)) {
983 PyErr_Format(PyExc_TypeError, "%s should be strings", paramname);
984 return NULL;
986 ret[i] = talloc_strndup(ret, PyString_AsString(item),
987 PyString_Size(item));
989 ret[i] = NULL;
990 return ret;
993 static int py_ldb_init(PyLdbObject *self, PyObject *args, PyObject *kwargs)
995 const char * const kwnames[] = { "url", "flags", "options", NULL };
996 char *url = NULL;
997 PyObject *py_options = Py_None;
998 const char **options;
999 unsigned int flags = 0;
1000 int ret;
1001 struct ldb_context *ldb;
1003 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "|zIO:Ldb.__init__",
1004 discard_const_p(char *, kwnames),
1005 &url, &flags, &py_options))
1006 return -1;
1008 ldb = pyldb_Ldb_AsLdbContext(self);
1010 if (py_options == Py_None) {
1011 options = NULL;
1012 } else {
1013 options = PyList_AsStringList(ldb, py_options, "options");
1014 if (options == NULL)
1015 return -1;
1018 if (url != NULL) {
1019 ret = ldb_connect(ldb, url, flags, options);
1020 if (ret != LDB_SUCCESS) {
1021 PyErr_SetLdbError(PyExc_LdbError, ret, ldb);
1022 return -1;
1026 talloc_free(options);
1027 return 0;
1030 static PyObject *py_ldb_new(PyTypeObject *type, PyObject *args, PyObject *kwargs)
1032 PyLdbObject *ret;
1033 struct ldb_context *ldb;
1034 ret = (PyLdbObject *)type->tp_alloc(type, 0);
1035 if (ret == NULL) {
1036 PyErr_NoMemory();
1037 return NULL;
1039 ret->mem_ctx = talloc_new(NULL);
1040 ldb = ldb_init(ret->mem_ctx, NULL);
1042 if (ldb == NULL) {
1043 PyErr_NoMemory();
1044 return NULL;
1047 ret->ldb_ctx = ldb;
1048 return (PyObject *)ret;
1051 static PyObject *py_ldb_connect(PyLdbObject *self, PyObject *args, PyObject *kwargs)
1053 char *url;
1054 unsigned int flags = 0;
1055 PyObject *py_options = Py_None;
1056 int ret;
1057 const char **options;
1058 const char * const kwnames[] = { "url", "flags", "options", NULL };
1059 struct ldb_context *ldb_ctx;
1061 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "|zIO",
1062 discard_const_p(char *, kwnames),
1063 &url, &flags, &py_options))
1064 return NULL;
1066 if (py_options == Py_None) {
1067 options = NULL;
1068 } else {
1069 options = PyList_AsStringList(NULL, py_options, "options");
1070 if (options == NULL)
1071 return NULL;
1074 ldb_ctx = pyldb_Ldb_AsLdbContext(self);
1075 ret = ldb_connect(ldb_ctx, url, flags, options);
1076 talloc_free(options);
1078 PyErr_LDB_ERROR_IS_ERR_RAISE(PyExc_LdbError, ret, ldb_ctx);
1080 Py_RETURN_NONE;
1083 static PyObject *py_ldb_modify(PyLdbObject *self, PyObject *args, PyObject *kwargs)
1085 PyObject *py_msg;
1086 PyObject *py_controls = Py_None;
1087 struct ldb_context *ldb_ctx;
1088 struct ldb_request *req;
1089 struct ldb_control **parsed_controls;
1090 struct ldb_message *msg;
1091 int ret;
1092 TALLOC_CTX *mem_ctx;
1093 bool validate=true;
1094 const char * const kwnames[] = { "message", "controls", "validate", NULL };
1096 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "O|Ob",
1097 discard_const_p(char *, kwnames),
1098 &py_msg, &py_controls, &validate))
1099 return NULL;
1101 mem_ctx = talloc_new(NULL);
1102 if (mem_ctx == NULL) {
1103 PyErr_NoMemory();
1104 return NULL;
1106 ldb_ctx = pyldb_Ldb_AsLdbContext(self);
1108 if (py_controls == Py_None) {
1109 parsed_controls = NULL;
1110 } else {
1111 const char **controls = PyList_AsStringList(mem_ctx, py_controls, "controls");
1112 parsed_controls = ldb_parse_control_strings(ldb_ctx, mem_ctx, controls);
1113 talloc_free(controls);
1116 if (!PyLdbMessage_Check(py_msg)) {
1117 PyErr_SetString(PyExc_TypeError, "Expected Ldb Message");
1118 talloc_free(mem_ctx);
1119 return NULL;
1121 msg = pyldb_Message_AsMessage(py_msg);
1123 if (validate) {
1124 ret = ldb_msg_sanity_check(ldb_ctx, msg);
1125 if (ret != LDB_SUCCESS) {
1126 PyErr_SetLdbError(PyExc_LdbError, ret, ldb_ctx);
1127 talloc_free(mem_ctx);
1128 return NULL;
1132 ret = ldb_build_mod_req(&req, ldb_ctx, mem_ctx, msg, parsed_controls,
1133 NULL, ldb_op_default_callback, NULL);
1134 if (ret != LDB_SUCCESS) {
1135 PyErr_SetString(PyExc_TypeError, "failed to build request");
1136 talloc_free(mem_ctx);
1137 return NULL;
1140 /* do request and autostart a transaction */
1141 /* Then let's LDB handle the message error in case of pb as they are meaningful */
1143 ret = ldb_transaction_start(ldb_ctx);
1144 if (ret != LDB_SUCCESS) {
1145 talloc_free(mem_ctx);
1146 PyErr_SetLdbError(PyExc_LdbError, ret, ldb_ctx);
1147 return NULL;
1150 ret = ldb_request(ldb_ctx, req);
1151 if (ret == LDB_SUCCESS) {
1152 ret = ldb_wait(req->handle, LDB_WAIT_ALL);
1155 if (ret == LDB_SUCCESS) {
1156 ret = ldb_transaction_commit(ldb_ctx);
1157 } else {
1158 ldb_transaction_cancel(ldb_ctx);
1161 talloc_free(mem_ctx);
1162 PyErr_LDB_ERROR_IS_ERR_RAISE(PyExc_LdbError, ret, ldb_ctx);
1164 Py_RETURN_NONE;
1169 * Obtain a ldb message from a Python Dictionary object.
1171 * @param mem_ctx Memory context
1172 * @param py_obj Python Dictionary object
1173 * @param ldb_ctx LDB context
1174 * @param mod_flags Flags to be set on every message element
1175 * @return ldb_message on success or NULL on failure
1177 static struct ldb_message *PyDict_AsMessage(TALLOC_CTX *mem_ctx,
1178 PyObject *py_obj,
1179 struct ldb_context *ldb_ctx,
1180 unsigned int mod_flags)
1182 struct ldb_message *msg;
1183 unsigned int msg_pos = 0;
1184 Py_ssize_t dict_pos = 0;
1185 PyObject *key, *value;
1186 struct ldb_message_element *msg_el;
1187 PyObject *dn_value = PyDict_GetItemString(py_obj, "dn");
1189 msg = ldb_msg_new(mem_ctx);
1190 if (msg == NULL) {
1191 PyErr_NoMemory();
1192 return NULL;
1194 msg->elements = talloc_zero_array(msg, struct ldb_message_element, PyDict_Size(py_obj));
1196 if (dn_value) {
1197 if (!pyldb_Object_AsDn(msg, dn_value, ldb_ctx, &msg->dn)) {
1198 PyErr_SetString(PyExc_TypeError, "unable to import dn object");
1199 return NULL;
1201 if (msg->dn == NULL) {
1202 PyErr_SetString(PyExc_TypeError, "dn set but not found");
1203 return NULL;
1205 } else {
1206 PyErr_SetString(PyExc_TypeError, "no dn set");
1207 return NULL;
1210 while (PyDict_Next(py_obj, &dict_pos, &key, &value)) {
1211 char *key_str = PyString_AsString(key);
1212 if (ldb_attr_cmp(key_str, "dn") != 0) {
1213 msg_el = PyObject_AsMessageElement(msg->elements, value,
1214 mod_flags, key_str);
1215 if (msg_el == NULL) {
1216 PyErr_SetString(PyExc_TypeError, "unable to import element");
1217 return NULL;
1219 memcpy(&msg->elements[msg_pos], msg_el, sizeof(*msg_el));
1220 msg_pos++;
1224 msg->num_elements = msg_pos;
1226 return msg;
1229 static PyObject *py_ldb_add(PyLdbObject *self, PyObject *args, PyObject *kwargs)
1231 PyObject *py_obj;
1232 int ret;
1233 struct ldb_context *ldb_ctx;
1234 struct ldb_request *req;
1235 struct ldb_message *msg = NULL;
1236 PyObject *py_controls = Py_None;
1237 TALLOC_CTX *mem_ctx;
1238 struct ldb_control **parsed_controls;
1239 const char * const kwnames[] = { "message", "controls", NULL };
1241 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "O|O",
1242 discard_const_p(char *, kwnames),
1243 &py_obj, &py_controls))
1244 return NULL;
1246 mem_ctx = talloc_new(NULL);
1247 if (mem_ctx == NULL) {
1248 PyErr_NoMemory();
1249 return NULL;
1251 ldb_ctx = pyldb_Ldb_AsLdbContext(self);
1253 if (py_controls == Py_None) {
1254 parsed_controls = NULL;
1255 } else {
1256 const char **controls = PyList_AsStringList(mem_ctx, py_controls, "controls");
1257 parsed_controls = ldb_parse_control_strings(ldb_ctx, mem_ctx, controls);
1258 talloc_free(controls);
1261 if (PyLdbMessage_Check(py_obj)) {
1262 msg = pyldb_Message_AsMessage(py_obj);
1263 } else if (PyDict_Check(py_obj)) {
1264 msg = PyDict_AsMessage(mem_ctx, py_obj, ldb_ctx, LDB_FLAG_MOD_ADD);
1265 } else {
1266 PyErr_SetString(PyExc_TypeError,
1267 "Dictionary or LdbMessage object expected!");
1270 if (!msg) {
1271 /* we should have a PyErr already set */
1272 talloc_free(mem_ctx);
1273 return NULL;
1276 ret = ldb_msg_sanity_check(ldb_ctx, msg);
1277 if (ret != LDB_SUCCESS) {
1278 PyErr_SetLdbError(PyExc_LdbError, ret, ldb_ctx);
1279 talloc_free(mem_ctx);
1280 return NULL;
1283 ret = ldb_build_add_req(&req, ldb_ctx, mem_ctx, msg, parsed_controls,
1284 NULL, ldb_op_default_callback, NULL);
1285 if (ret != LDB_SUCCESS) {
1286 PyErr_SetString(PyExc_TypeError, "failed to build request");
1287 talloc_free(mem_ctx);
1288 return NULL;
1291 /* do request and autostart a transaction */
1292 /* Then let's LDB handle the message error in case of pb as they are meaningful */
1294 ret = ldb_transaction_start(ldb_ctx);
1295 if (ret != LDB_SUCCESS) {
1296 talloc_free(mem_ctx);
1297 PyErr_SetLdbError(PyExc_LdbError, ret, ldb_ctx);
1298 return NULL;
1301 ret = ldb_request(ldb_ctx, req);
1302 if (ret == LDB_SUCCESS) {
1303 ret = ldb_wait(req->handle, LDB_WAIT_ALL);
1306 if (ret == LDB_SUCCESS) {
1307 ret = ldb_transaction_commit(ldb_ctx);
1308 } else {
1309 ldb_transaction_cancel(ldb_ctx);
1312 talloc_free(mem_ctx);
1313 PyErr_LDB_ERROR_IS_ERR_RAISE(PyExc_LdbError, ret, ldb_ctx);
1315 Py_RETURN_NONE;
1318 static PyObject *py_ldb_delete(PyLdbObject *self, PyObject *args, PyObject *kwargs)
1320 PyObject *py_dn;
1321 struct ldb_dn *dn;
1322 int ret;
1323 struct ldb_context *ldb_ctx;
1324 struct ldb_request *req;
1325 PyObject *py_controls = Py_None;
1326 TALLOC_CTX *mem_ctx;
1327 struct ldb_control **parsed_controls;
1328 const char * const kwnames[] = { "dn", "controls", NULL };
1330 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "O|O",
1331 discard_const_p(char *, kwnames),
1332 &py_dn, &py_controls))
1333 return NULL;
1335 mem_ctx = talloc_new(NULL);
1336 if (mem_ctx == NULL) {
1337 PyErr_NoMemory();
1338 return NULL;
1340 ldb_ctx = pyldb_Ldb_AsLdbContext(self);
1342 if (py_controls == Py_None) {
1343 parsed_controls = NULL;
1344 } else {
1345 const char **controls = PyList_AsStringList(mem_ctx, py_controls, "controls");
1346 parsed_controls = ldb_parse_control_strings(ldb_ctx, mem_ctx, controls);
1347 talloc_free(controls);
1350 if (!pyldb_Object_AsDn(mem_ctx, py_dn, ldb_ctx, &dn)) {
1351 talloc_free(mem_ctx);
1352 return NULL;
1355 ret = ldb_build_del_req(&req, ldb_ctx, mem_ctx, dn, parsed_controls,
1356 NULL, ldb_op_default_callback, NULL);
1357 if (ret != LDB_SUCCESS) {
1358 PyErr_SetString(PyExc_TypeError, "failed to build request");
1359 talloc_free(mem_ctx);
1360 return NULL;
1363 /* do request and autostart a transaction */
1364 /* Then let's LDB handle the message error in case of pb as they are meaningful */
1366 ret = ldb_transaction_start(ldb_ctx);
1367 if (ret != LDB_SUCCESS) {
1368 talloc_free(mem_ctx);
1369 PyErr_SetLdbError(PyExc_LdbError, ret, ldb_ctx);
1370 return NULL;
1373 ret = ldb_request(ldb_ctx, req);
1374 if (ret == LDB_SUCCESS) {
1375 ret = ldb_wait(req->handle, LDB_WAIT_ALL);
1378 if (ret == LDB_SUCCESS) {
1379 ret = ldb_transaction_commit(ldb_ctx);
1380 } else {
1381 ldb_transaction_cancel(ldb_ctx);
1384 talloc_free(mem_ctx);
1385 PyErr_LDB_ERROR_IS_ERR_RAISE(PyExc_LdbError, ret, ldb_ctx);
1387 Py_RETURN_NONE;
1390 static PyObject *py_ldb_rename(PyLdbObject *self, PyObject *args, PyObject *kwargs)
1392 PyObject *py_dn1, *py_dn2;
1393 struct ldb_dn *dn1, *dn2;
1394 int ret;
1395 TALLOC_CTX *mem_ctx;
1396 PyObject *py_controls = Py_None;
1397 struct ldb_control **parsed_controls;
1398 struct ldb_context *ldb_ctx;
1399 struct ldb_request *req;
1400 const char * const kwnames[] = { "dn1", "dn2", "controls", NULL };
1402 ldb_ctx = pyldb_Ldb_AsLdbContext(self);
1404 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "OO|O",
1405 discard_const_p(char *, kwnames),
1406 &py_dn1, &py_dn2, &py_controls))
1407 return NULL;
1410 mem_ctx = talloc_new(NULL);
1411 if (mem_ctx == NULL) {
1412 PyErr_NoMemory();
1413 return NULL;
1416 if (py_controls == Py_None) {
1417 parsed_controls = NULL;
1418 } else {
1419 const char **controls = PyList_AsStringList(mem_ctx, py_controls, "controls");
1420 parsed_controls = ldb_parse_control_strings(ldb_ctx, mem_ctx, controls);
1421 talloc_free(controls);
1425 if (!pyldb_Object_AsDn(mem_ctx, py_dn1, ldb_ctx, &dn1)) {
1426 talloc_free(mem_ctx);
1427 return NULL;
1430 if (!pyldb_Object_AsDn(mem_ctx, py_dn2, ldb_ctx, &dn2)) {
1431 talloc_free(mem_ctx);
1432 return NULL;
1435 ret = ldb_build_rename_req(&req, ldb_ctx, mem_ctx, dn1, dn2, parsed_controls,
1436 NULL, ldb_op_default_callback, NULL);
1437 if (ret != LDB_SUCCESS) {
1438 PyErr_SetString(PyExc_TypeError, "failed to build request");
1439 talloc_free(mem_ctx);
1440 return NULL;
1443 /* do request and autostart a transaction */
1444 /* Then let's LDB handle the message error in case of pb as they are meaningful */
1446 ret = ldb_transaction_start(ldb_ctx);
1447 if (ret != LDB_SUCCESS) {
1448 talloc_free(mem_ctx);
1449 PyErr_SetLdbError(PyExc_LdbError, ret, ldb_ctx);
1450 return NULL;
1453 ret = ldb_request(ldb_ctx, req);
1454 if (ret == LDB_SUCCESS) {
1455 ret = ldb_wait(req->handle, LDB_WAIT_ALL);
1458 if (ret == LDB_SUCCESS) {
1459 ret = ldb_transaction_commit(ldb_ctx);
1460 } else {
1461 ldb_transaction_cancel(ldb_ctx);
1464 talloc_free(mem_ctx);
1465 PyErr_LDB_ERROR_IS_ERR_RAISE(PyExc_LdbError, ret, ldb_ctx);
1467 Py_RETURN_NONE;
1470 static PyObject *py_ldb_schema_attribute_remove(PyLdbObject *self, PyObject *args)
1472 char *name;
1473 if (!PyArg_ParseTuple(args, "s", &name))
1474 return NULL;
1476 ldb_schema_attribute_remove(pyldb_Ldb_AsLdbContext(self), name);
1478 Py_RETURN_NONE;
1481 static PyObject *py_ldb_schema_attribute_add(PyLdbObject *self, PyObject *args)
1483 char *attribute, *syntax;
1484 unsigned int flags;
1485 int ret;
1486 struct ldb_context *ldb_ctx;
1488 if (!PyArg_ParseTuple(args, "sIs", &attribute, &flags, &syntax))
1489 return NULL;
1491 ldb_ctx = pyldb_Ldb_AsLdbContext(self);
1492 ret = ldb_schema_attribute_add(ldb_ctx, attribute, flags, syntax);
1494 PyErr_LDB_ERROR_IS_ERR_RAISE(PyExc_LdbError, ret, ldb_ctx);
1496 Py_RETURN_NONE;
1499 static PyObject *ldb_ldif_to_pyobject(struct ldb_ldif *ldif)
1501 if (ldif == NULL) {
1502 Py_RETURN_NONE;
1503 } else {
1504 /* We don't want this attached to the 'ldb' any more */
1505 return Py_BuildValue(discard_const_p(char, "(iO)"),
1506 ldif->changetype,
1507 PyLdbMessage_FromMessage(ldif->msg));
1512 static PyObject *py_ldb_write_ldif(PyLdbObject *self, PyObject *args)
1514 int changetype;
1515 PyObject *py_msg;
1516 struct ldb_ldif ldif;
1517 PyObject *ret;
1518 char *string;
1519 TALLOC_CTX *mem_ctx;
1521 if (!PyArg_ParseTuple(args, "Oi", &py_msg, &changetype))
1522 return NULL;
1524 if (!PyLdbMessage_Check(py_msg)) {
1525 PyErr_SetString(PyExc_TypeError, "Expected Ldb Message for msg");
1526 return NULL;
1529 ldif.msg = pyldb_Message_AsMessage(py_msg);
1530 ldif.changetype = changetype;
1532 mem_ctx = talloc_new(NULL);
1534 string = ldb_ldif_write_string(pyldb_Ldb_AsLdbContext(self), mem_ctx, &ldif);
1535 if (!string) {
1536 PyErr_SetString(PyExc_KeyError, "Failed to generate LDIF");
1537 return NULL;
1540 ret = PyString_FromString(string);
1542 talloc_free(mem_ctx);
1544 return ret;
1547 static PyObject *py_ldb_parse_ldif(PyLdbObject *self, PyObject *args)
1549 PyObject *list;
1550 struct ldb_ldif *ldif;
1551 const char *s;
1553 TALLOC_CTX *mem_ctx;
1555 if (!PyArg_ParseTuple(args, "s", &s))
1556 return NULL;
1558 mem_ctx = talloc_new(NULL);
1559 if (!mem_ctx) {
1560 Py_RETURN_NONE;
1563 list = PyList_New(0);
1564 while (s && *s != '\0') {
1565 ldif = ldb_ldif_read_string(self->ldb_ctx, &s);
1566 talloc_steal(mem_ctx, ldif);
1567 if (ldif) {
1568 PyList_Append(list, ldb_ldif_to_pyobject(ldif));
1569 } else {
1570 PyErr_SetString(PyExc_ValueError, "unable to parse ldif string");
1571 talloc_free(mem_ctx);
1572 return NULL;
1575 talloc_free(mem_ctx); /* The pyobject already has a reference to the things it needs */
1576 return PyObject_GetIter(list);
1579 static PyObject *py_ldb_msg_diff(PyLdbObject *self, PyObject *args)
1581 int ldb_ret;
1582 PyObject *py_msg_old;
1583 PyObject *py_msg_new;
1584 struct ldb_message *diff;
1585 struct ldb_context *ldb;
1586 PyObject *py_ret;
1588 if (!PyArg_ParseTuple(args, "OO", &py_msg_old, &py_msg_new))
1589 return NULL;
1591 if (!PyLdbMessage_Check(py_msg_old)) {
1592 PyErr_SetString(PyExc_TypeError, "Expected Ldb Message for old message");
1593 return NULL;
1596 if (!PyLdbMessage_Check(py_msg_new)) {
1597 PyErr_SetString(PyExc_TypeError, "Expected Ldb Message for new message");
1598 return NULL;
1601 ldb = pyldb_Ldb_AsLdbContext(self);
1602 ldb_ret = ldb_msg_difference(ldb, ldb,
1603 pyldb_Message_AsMessage(py_msg_old),
1604 pyldb_Message_AsMessage(py_msg_new),
1605 &diff);
1606 if (ldb_ret != LDB_SUCCESS) {
1607 PyErr_SetString(PyExc_RuntimeError, "Failed to generate the Ldb Message diff");
1608 return NULL;
1611 py_ret = PyLdbMessage_FromMessage(diff);
1613 talloc_unlink(ldb, diff);
1615 return py_ret;
1618 static PyObject *py_ldb_schema_format_value(PyLdbObject *self, PyObject *args)
1620 const struct ldb_schema_attribute *a;
1621 struct ldb_val old_val;
1622 struct ldb_val new_val;
1623 TALLOC_CTX *mem_ctx;
1624 PyObject *ret;
1625 char *element_name;
1626 PyObject *val;
1628 if (!PyArg_ParseTuple(args, "sO", &element_name, &val))
1629 return NULL;
1631 old_val.data = (uint8_t *)PyString_AsString(val);
1632 old_val.length = PyString_Size(val);
1634 if (old_val.data == NULL) {
1635 PyErr_SetString(PyExc_RuntimeError, "Failed to convert passed value to String");
1636 return NULL;
1639 a = ldb_schema_attribute_by_name(pyldb_Ldb_AsLdbContext(self), element_name);
1641 if (a == NULL) {
1642 Py_RETURN_NONE;
1645 mem_ctx = talloc_new(NULL);
1646 if (mem_ctx == NULL) {
1647 PyErr_NoMemory();
1648 return NULL;
1651 if (a->syntax->ldif_write_fn(pyldb_Ldb_AsLdbContext(self), mem_ctx, &old_val, &new_val) != 0) {
1652 talloc_free(mem_ctx);
1653 Py_RETURN_NONE;
1656 ret = PyString_FromStringAndSize((const char *)new_val.data, new_val.length);
1658 talloc_free(mem_ctx);
1660 return ret;
1663 static PyObject *py_ldb_search(PyLdbObject *self, PyObject *args, PyObject *kwargs)
1665 PyObject *py_base = Py_None;
1666 int scope = LDB_SCOPE_DEFAULT;
1667 char *expr = NULL;
1668 PyObject *py_attrs = Py_None;
1669 PyObject *py_controls = Py_None;
1670 const char * const kwnames[] = { "base", "scope", "expression", "attrs", "controls", NULL };
1671 int ret;
1672 struct ldb_result *res;
1673 struct ldb_request *req;
1674 const char **attrs;
1675 struct ldb_context *ldb_ctx;
1676 struct ldb_control **parsed_controls;
1677 struct ldb_dn *base;
1678 PyObject *py_ret;
1679 TALLOC_CTX *mem_ctx;
1681 /* type "int" rather than "enum" for "scope" is intentional */
1682 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "|OizOO",
1683 discard_const_p(char *, kwnames),
1684 &py_base, &scope, &expr, &py_attrs, &py_controls))
1685 return NULL;
1688 mem_ctx = talloc_new(NULL);
1689 if (mem_ctx == NULL) {
1690 PyErr_NoMemory();
1691 return NULL;
1693 ldb_ctx = pyldb_Ldb_AsLdbContext(self);
1695 if (py_attrs == Py_None) {
1696 attrs = NULL;
1697 } else {
1698 attrs = PyList_AsStringList(mem_ctx, py_attrs, "attrs");
1699 if (attrs == NULL) {
1700 talloc_free(mem_ctx);
1701 return NULL;
1705 if (py_base == Py_None) {
1706 base = ldb_get_default_basedn(ldb_ctx);
1707 } else {
1708 if (!pyldb_Object_AsDn(ldb_ctx, py_base, ldb_ctx, &base)) {
1709 talloc_free(attrs);
1710 return NULL;
1714 if (py_controls == Py_None) {
1715 parsed_controls = NULL;
1716 } else {
1717 const char **controls = PyList_AsStringList(mem_ctx, py_controls, "controls");
1718 parsed_controls = ldb_parse_control_strings(ldb_ctx, mem_ctx, controls);
1719 talloc_free(controls);
1722 res = talloc_zero(mem_ctx, struct ldb_result);
1723 if (res == NULL) {
1724 PyErr_NoMemory();
1725 talloc_free(mem_ctx);
1726 return NULL;
1729 ret = ldb_build_search_req(&req, ldb_ctx, mem_ctx,
1730 base,
1731 scope,
1732 expr,
1733 attrs,
1734 parsed_controls,
1735 res,
1736 ldb_search_default_callback,
1737 NULL);
1739 if (ret != LDB_SUCCESS) {
1740 talloc_free(mem_ctx);
1741 PyErr_SetLdbError(PyExc_LdbError, ret, ldb_ctx);
1742 return NULL;
1745 talloc_steal(req, attrs);
1747 ret = ldb_request(ldb_ctx, req);
1749 if (ret == LDB_SUCCESS) {
1750 ret = ldb_wait(req->handle, LDB_WAIT_ALL);
1753 if (ret != LDB_SUCCESS) {
1754 talloc_free(mem_ctx);
1755 PyErr_SetLdbError(PyExc_LdbError, ret, ldb_ctx);
1756 return NULL;
1759 py_ret = PyLdbResult_FromResult(res);
1761 talloc_free(mem_ctx);
1763 return py_ret;
1766 static PyObject *py_ldb_get_opaque(PyLdbObject *self, PyObject *args)
1768 char *name;
1769 void *data;
1771 if (!PyArg_ParseTuple(args, "s", &name))
1772 return NULL;
1774 data = ldb_get_opaque(pyldb_Ldb_AsLdbContext(self), name);
1776 if (data == NULL)
1777 Py_RETURN_NONE;
1779 /* FIXME: More interpretation */
1781 return Py_True;
1784 static PyObject *py_ldb_set_opaque(PyLdbObject *self, PyObject *args)
1786 char *name;
1787 PyObject *data;
1789 if (!PyArg_ParseTuple(args, "sO", &name, &data))
1790 return NULL;
1792 /* FIXME: More interpretation */
1794 ldb_set_opaque(pyldb_Ldb_AsLdbContext(self), name, data);
1796 Py_RETURN_NONE;
1799 static PyObject *py_ldb_modules(PyLdbObject *self)
1801 struct ldb_context *ldb = pyldb_Ldb_AsLdbContext(self);
1802 PyObject *ret = PyList_New(0);
1803 struct ldb_module *mod;
1805 for (mod = ldb->modules; mod; mod = mod->next) {
1806 PyList_Append(ret, PyLdbModule_FromModule(mod));
1809 return ret;
1812 static PyObject *py_ldb_sequence_number(PyLdbObject *self, PyObject *args)
1814 struct ldb_context *ldb = pyldb_Ldb_AsLdbContext(self);
1815 int type, ret;
1816 uint64_t value;
1818 if (!PyArg_ParseTuple(args, "i", &type))
1819 return NULL;
1821 /* FIXME: More interpretation */
1823 ret = ldb_sequence_number(ldb, type, &value);
1825 PyErr_LDB_ERROR_IS_ERR_RAISE(PyExc_LdbError, ret, ldb);
1827 return PyLong_FromLongLong(value);
1829 static PyMethodDef py_ldb_methods[] = {
1830 { "set_debug", (PyCFunction)py_ldb_set_debug, METH_VARARGS,
1831 "S.set_debug(callback) -> None\n"
1832 "Set callback for LDB debug messages.\n"
1833 "The callback should accept a debug level and debug text." },
1834 { "set_create_perms", (PyCFunction)py_ldb_set_create_perms, METH_VARARGS,
1835 "S.set_create_perms(mode) -> None\n"
1836 "Set mode to use when creating new LDB files." },
1837 { "set_modules_dir", (PyCFunction)py_ldb_set_modules_dir, METH_VARARGS,
1838 "S.set_modules_dir(path) -> None\n"
1839 "Set path LDB should search for modules" },
1840 { "transaction_start", (PyCFunction)py_ldb_transaction_start, METH_NOARGS,
1841 "S.transaction_start() -> None\n"
1842 "Start a new transaction." },
1843 { "transaction_prepare_commit", (PyCFunction)py_ldb_transaction_prepare_commit, METH_NOARGS,
1844 "S.transaction_prepare_commit() -> None\n"
1845 "prepare to commit a new transaction (2-stage commit)." },
1846 { "transaction_commit", (PyCFunction)py_ldb_transaction_commit, METH_NOARGS,
1847 "S.transaction_commit() -> None\n"
1848 "commit a new transaction." },
1849 { "transaction_cancel", (PyCFunction)py_ldb_transaction_cancel, METH_NOARGS,
1850 "S.transaction_cancel() -> None\n"
1851 "cancel a new transaction." },
1852 { "setup_wellknown_attributes", (PyCFunction)py_ldb_setup_wellknown_attributes, METH_NOARGS,
1853 NULL },
1854 { "get_root_basedn", (PyCFunction)py_ldb_get_root_basedn, METH_NOARGS,
1855 NULL },
1856 { "get_schema_basedn", (PyCFunction)py_ldb_get_schema_basedn, METH_NOARGS,
1857 NULL },
1858 { "get_default_basedn", (PyCFunction)py_ldb_get_default_basedn, METH_NOARGS,
1859 NULL },
1860 { "get_config_basedn", (PyCFunction)py_ldb_get_config_basedn, METH_NOARGS,
1861 NULL },
1862 { "connect", (PyCFunction)py_ldb_connect, METH_VARARGS|METH_KEYWORDS,
1863 "S.connect(url, flags=0, options=None) -> None\n"
1864 "Connect to a LDB URL." },
1865 { "modify", (PyCFunction)py_ldb_modify, METH_VARARGS|METH_KEYWORDS,
1866 "S.modify(message, controls=None, validate=False) -> None\n"
1867 "Modify an entry." },
1868 { "add", (PyCFunction)py_ldb_add, METH_VARARGS|METH_KEYWORDS,
1869 "S.add(message, controls=None) -> None\n"
1870 "Add an entry." },
1871 { "delete", (PyCFunction)py_ldb_delete, METH_VARARGS|METH_KEYWORDS,
1872 "S.delete(dn, controls=None) -> None\n"
1873 "Remove an entry." },
1874 { "rename", (PyCFunction)py_ldb_rename, METH_VARARGS|METH_KEYWORDS,
1875 "S.rename(old_dn, new_dn, controls=None) -> None\n"
1876 "Rename an entry." },
1877 { "search", (PyCFunction)py_ldb_search, METH_VARARGS|METH_KEYWORDS,
1878 "S.search(base=None, scope=None, expression=None, attrs=None, controls=None) -> msgs\n"
1879 "Search in a database.\n"
1880 "\n"
1881 ":param base: Optional base DN to search\n"
1882 ":param scope: Search scope (SCOPE_BASE, SCOPE_ONELEVEL or SCOPE_SUBTREE)\n"
1883 ":param expression: Optional search expression\n"
1884 ":param attrs: Attributes to return (defaults to all)\n"
1885 ":param controls: Optional list of controls\n"
1886 ":return: Iterator over Message objects\n"
1888 { "schema_attribute_remove", (PyCFunction)py_ldb_schema_attribute_remove, METH_VARARGS,
1889 NULL },
1890 { "schema_attribute_add", (PyCFunction)py_ldb_schema_attribute_add, METH_VARARGS,
1891 NULL },
1892 { "schema_format_value", (PyCFunction)py_ldb_schema_format_value, METH_VARARGS,
1893 NULL },
1894 { "parse_ldif", (PyCFunction)py_ldb_parse_ldif, METH_VARARGS,
1895 "S.parse_ldif(ldif) -> iter(messages)\n"
1896 "Parse a string formatted using LDIF." },
1897 { "write_ldif", (PyCFunction)py_ldb_write_ldif, METH_VARARGS,
1898 "S.write_ldif(message, changetype) -> ldif\n"
1899 "Print the message as a string formatted using LDIF." },
1900 { "msg_diff", (PyCFunction)py_ldb_msg_diff, METH_VARARGS,
1901 "S.msg_diff(Message) -> Message\n"
1902 "Return an LDB Message of the difference between two Message objects." },
1903 { "get_opaque", (PyCFunction)py_ldb_get_opaque, METH_VARARGS,
1904 "S.get_opaque(name) -> value\n"
1905 "Get an opaque value set on this LDB connection. \n"
1906 ":note: The returned value may not be useful in Python."
1908 { "set_opaque", (PyCFunction)py_ldb_set_opaque, METH_VARARGS,
1909 "S.set_opaque(name, value) -> None\n"
1910 "Set an opaque value on this LDB connection. \n"
1911 ":note: Passing incorrect values may cause crashes." },
1912 { "modules", (PyCFunction)py_ldb_modules, METH_NOARGS,
1913 "S.modules() -> list\n"
1914 "Return the list of modules on this LDB connection " },
1915 { "sequence_number", (PyCFunction)py_ldb_sequence_number, METH_VARARGS,
1916 "S.sequence_number(type) -> value\n"
1917 "Return the value of the sequence according to the requested type" },
1918 { NULL },
1921 static PyObject *PyLdbModule_FromModule(struct ldb_module *mod)
1923 PyLdbModuleObject *ret;
1925 ret = (PyLdbModuleObject *)PyLdbModule.tp_alloc(&PyLdbModule, 0);
1926 if (ret == NULL) {
1927 PyErr_NoMemory();
1928 return NULL;
1930 ret->mem_ctx = talloc_new(NULL);
1931 ret->mod = talloc_reference(ret->mem_ctx, mod);
1932 return (PyObject *)ret;
1935 static PyObject *py_ldb_get_firstmodule(PyLdbObject *self, void *closure)
1937 return PyLdbModule_FromModule(pyldb_Ldb_AsLdbContext(self)->modules);
1940 static PyGetSetDef py_ldb_getset[] = {
1941 { discard_const_p(char, "firstmodule"), (getter)py_ldb_get_firstmodule, NULL, NULL },
1942 { NULL }
1945 static int py_ldb_contains(PyLdbObject *self, PyObject *obj)
1947 struct ldb_context *ldb_ctx = pyldb_Ldb_AsLdbContext(self);
1948 struct ldb_dn *dn;
1949 struct ldb_result *result;
1950 unsigned int count;
1951 int ret;
1953 if (!pyldb_Object_AsDn(ldb_ctx, obj, ldb_ctx, &dn)) {
1954 return -1;
1957 ret = ldb_search(ldb_ctx, ldb_ctx, &result, dn, LDB_SCOPE_BASE, NULL,
1958 NULL);
1959 if (ret != LDB_SUCCESS) {
1960 PyErr_SetLdbError(PyExc_LdbError, ret, ldb_ctx);
1961 return -1;
1964 count = result->count;
1966 talloc_free(result);
1968 if (count > 1) {
1969 PyErr_Format(PyExc_RuntimeError,
1970 "Searching for [%s] dn gave %u results!",
1971 ldb_dn_get_linearized(dn),
1972 count);
1973 return -1;
1976 return count;
1979 static PySequenceMethods py_ldb_seq = {
1980 .sq_contains = (objobjproc)py_ldb_contains,
1983 static PyObject *PyLdb_FromLdbContext(struct ldb_context *ldb_ctx)
1985 PyLdbObject *ret;
1987 ret = (PyLdbObject *)PyLdb.tp_alloc(&PyLdb, 0);
1988 if (ret == NULL) {
1989 PyErr_NoMemory();
1990 return NULL;
1992 ret->mem_ctx = talloc_new(NULL);
1993 ret->ldb_ctx = talloc_reference(ret->mem_ctx, ldb_ctx);
1994 return (PyObject *)ret;
1997 static void py_ldb_dealloc(PyLdbObject *self)
1999 talloc_free(self->mem_ctx);
2000 Py_TYPE(self)->tp_free(self);
2003 static PyTypeObject PyLdb = {
2004 .tp_name = "ldb.Ldb",
2005 .tp_methods = py_ldb_methods,
2006 .tp_repr = (reprfunc)py_ldb_repr,
2007 .tp_new = py_ldb_new,
2008 .tp_init = (initproc)py_ldb_init,
2009 .tp_dealloc = (destructor)py_ldb_dealloc,
2010 .tp_getset = py_ldb_getset,
2011 .tp_getattro = PyObject_GenericGetAttr,
2012 .tp_basicsize = sizeof(PyLdbObject),
2013 .tp_doc = "Connection to a LDB database.",
2014 .tp_as_sequence = &py_ldb_seq,
2015 .tp_flags = Py_TPFLAGS_DEFAULT|Py_TPFLAGS_BASETYPE,
2018 static void py_ldb_result_dealloc(PyLdbResultObject *self)
2020 talloc_free(self->mem_ctx);
2021 Py_DECREF(self->msgs);
2022 Py_DECREF(self->referals);
2023 Py_DECREF(self->controls);
2024 Py_TYPE(self)->tp_free(self);
2027 static PyObject *py_ldb_result_get_msgs(PyLdbResultObject *self, void *closure)
2029 Py_INCREF(self->msgs);
2030 return self->msgs;
2033 static PyObject *py_ldb_result_get_controls(PyLdbResultObject *self, void *closure)
2035 Py_INCREF(self->controls);
2036 return self->controls;
2039 static PyObject *py_ldb_result_get_referals(PyLdbResultObject *self, void *closure)
2041 Py_INCREF(self->referals);
2042 return self->referals;
2045 static PyObject *py_ldb_result_get_count(PyLdbResultObject *self, void *closure)
2047 Py_ssize_t size;
2048 if (self->msgs == NULL) {
2049 PyErr_SetString(PyExc_AttributeError, "Count attribute is meaningless in this context");
2050 return NULL;
2052 size = PyList_Size(self->msgs);
2053 return PyInt_FromLong(size);
2056 static PyGetSetDef py_ldb_result_getset[] = {
2057 { discard_const_p(char, "controls"), (getter)py_ldb_result_get_controls, NULL, NULL },
2058 { discard_const_p(char, "msgs"), (getter)py_ldb_result_get_msgs, NULL, NULL },
2059 { discard_const_p(char, "referals"), (getter)py_ldb_result_get_referals, NULL, NULL },
2060 { discard_const_p(char, "count"), (getter)py_ldb_result_get_count, NULL, NULL },
2061 { NULL }
2064 static PyObject *py_ldb_result_iter(PyLdbResultObject *self)
2066 return PyObject_GetIter(self->msgs);
2069 static Py_ssize_t py_ldb_result_len(PyLdbResultObject *self)
2071 return PySequence_Size(self->msgs);
2074 static PyObject *py_ldb_result_find(PyLdbResultObject *self, Py_ssize_t idx)
2076 return PySequence_GetItem(self->msgs, idx);
2079 static PySequenceMethods py_ldb_result_seq = {
2080 .sq_length = (lenfunc)py_ldb_result_len,
2081 .sq_item = (ssizeargfunc)py_ldb_result_find,
2084 static PyObject *py_ldb_result_repr(PyLdbObject *self)
2086 return PyString_FromFormat("<ldb result>");
2090 static PyTypeObject PyLdbResult = {
2091 .tp_name = "ldb.Result",
2092 .tp_repr = (reprfunc)py_ldb_result_repr,
2093 .tp_dealloc = (destructor)py_ldb_result_dealloc,
2094 .tp_iter = (getiterfunc)py_ldb_result_iter,
2095 .tp_getset = py_ldb_result_getset,
2096 .tp_getattro = PyObject_GenericGetAttr,
2097 .tp_basicsize = sizeof(PyLdbResultObject),
2098 .tp_as_sequence = &py_ldb_result_seq,
2099 .tp_doc = "LDB result.",
2100 .tp_flags = Py_TPFLAGS_DEFAULT|Py_TPFLAGS_BASETYPE,
2103 static PyObject *py_ldb_module_repr(PyLdbModuleObject *self)
2105 return PyString_FromFormat("<ldb module '%s'>",
2106 pyldb_Module_AsModule(self)->ops->name);
2109 static PyObject *py_ldb_module_str(PyLdbModuleObject *self)
2111 return PyString_FromString(pyldb_Module_AsModule(self)->ops->name);
2114 static PyObject *py_ldb_module_start_transaction(PyLdbModuleObject *self)
2116 pyldb_Module_AsModule(self)->ops->start_transaction(pyldb_Module_AsModule(self));
2117 Py_RETURN_NONE;
2120 static PyObject *py_ldb_module_end_transaction(PyLdbModuleObject *self)
2122 pyldb_Module_AsModule(self)->ops->end_transaction(pyldb_Module_AsModule(self));
2123 Py_RETURN_NONE;
2126 static PyObject *py_ldb_module_del_transaction(PyLdbModuleObject *self)
2128 pyldb_Module_AsModule(self)->ops->del_transaction(pyldb_Module_AsModule(self));
2129 Py_RETURN_NONE;
2132 static PyObject *py_ldb_module_search(PyLdbModuleObject *self, PyObject *args, PyObject *kwargs)
2134 PyObject *py_base, *py_tree, *py_attrs, *py_ret;
2135 int ret, scope;
2136 struct ldb_request *req;
2137 const char * const kwnames[] = { "base", "scope", "tree", "attrs", NULL };
2138 struct ldb_module *mod;
2139 const char * const*attrs;
2141 /* type "int" rather than "enum" for "scope" is intentional */
2142 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "OiOO",
2143 discard_const_p(char *, kwnames),
2144 &py_base, &scope, &py_tree, &py_attrs))
2145 return NULL;
2147 mod = self->mod;
2149 if (py_attrs == Py_None) {
2150 attrs = NULL;
2151 } else {
2152 attrs = PyList_AsStringList(NULL, py_attrs, "attrs");
2153 if (attrs == NULL)
2154 return NULL;
2157 ret = ldb_build_search_req(&req, mod->ldb, NULL, pyldb_Dn_AsDn(py_base),
2158 scope, NULL /* expr */, attrs,
2159 NULL /* controls */, NULL, NULL, NULL);
2161 talloc_steal(req, attrs);
2163 PyErr_LDB_ERROR_IS_ERR_RAISE(PyExc_LdbError, ret, mod->ldb);
2165 req->op.search.res = NULL;
2167 ret = mod->ops->search(mod, req);
2169 PyErr_LDB_ERROR_IS_ERR_RAISE(PyExc_LdbError, ret, mod->ldb);
2171 py_ret = PyLdbResult_FromResult(req->op.search.res);
2173 talloc_free(req);
2175 return py_ret;
2179 static PyObject *py_ldb_module_add(PyLdbModuleObject *self, PyObject *args)
2181 struct ldb_request *req;
2182 PyObject *py_message;
2183 int ret;
2184 struct ldb_module *mod;
2186 if (!PyArg_ParseTuple(args, "O", &py_message))
2187 return NULL;
2189 req = talloc_zero(NULL, struct ldb_request);
2190 req->operation = LDB_ADD;
2191 req->op.add.message = pyldb_Message_AsMessage(py_message);
2193 mod = pyldb_Module_AsModule(self);
2194 ret = mod->ops->add(mod, req);
2196 PyErr_LDB_ERROR_IS_ERR_RAISE(PyExc_LdbError, ret, mod->ldb);
2198 Py_RETURN_NONE;
2201 static PyObject *py_ldb_module_modify(PyLdbModuleObject *self, PyObject *args)
2203 int ret;
2204 struct ldb_request *req;
2205 PyObject *py_message;
2206 struct ldb_module *mod;
2208 if (!PyArg_ParseTuple(args, "O", &py_message))
2209 return NULL;
2211 req = talloc_zero(NULL, struct ldb_request);
2212 req->operation = LDB_MODIFY;
2213 req->op.mod.message = pyldb_Message_AsMessage(py_message);
2215 mod = pyldb_Module_AsModule(self);
2216 ret = mod->ops->modify(mod, req);
2218 PyErr_LDB_ERROR_IS_ERR_RAISE(PyExc_LdbError, ret, mod->ldb);
2220 Py_RETURN_NONE;
2223 static PyObject *py_ldb_module_delete(PyLdbModuleObject *self, PyObject *args)
2225 int ret;
2226 struct ldb_request *req;
2227 PyObject *py_dn;
2229 if (!PyArg_ParseTuple(args, "O", &py_dn))
2230 return NULL;
2232 req = talloc_zero(NULL, struct ldb_request);
2233 req->operation = LDB_DELETE;
2234 req->op.del.dn = pyldb_Dn_AsDn(py_dn);
2236 ret = pyldb_Module_AsModule(self)->ops->del(pyldb_Module_AsModule(self), req);
2238 PyErr_LDB_ERROR_IS_ERR_RAISE(PyExc_LdbError, ret, NULL);
2240 Py_RETURN_NONE;
2243 static PyObject *py_ldb_module_rename(PyLdbModuleObject *self, PyObject *args)
2245 int ret;
2246 struct ldb_request *req;
2247 PyObject *py_dn1, *py_dn2;
2249 if (!PyArg_ParseTuple(args, "OO", &py_dn1, &py_dn2))
2250 return NULL;
2252 req = talloc_zero(NULL, struct ldb_request);
2254 req->operation = LDB_RENAME;
2255 req->op.rename.olddn = pyldb_Dn_AsDn(py_dn1);
2256 req->op.rename.newdn = pyldb_Dn_AsDn(py_dn2);
2258 ret = pyldb_Module_AsModule(self)->ops->rename(pyldb_Module_AsModule(self), req);
2260 PyErr_LDB_ERROR_IS_ERR_RAISE(PyExc_LdbError, ret, NULL);
2262 Py_RETURN_NONE;
2265 static PyMethodDef py_ldb_module_methods[] = {
2266 { "search", (PyCFunction)py_ldb_module_search, METH_VARARGS|METH_KEYWORDS, NULL },
2267 { "add", (PyCFunction)py_ldb_module_add, METH_VARARGS, NULL },
2268 { "modify", (PyCFunction)py_ldb_module_modify, METH_VARARGS, NULL },
2269 { "rename", (PyCFunction)py_ldb_module_rename, METH_VARARGS, NULL },
2270 { "delete", (PyCFunction)py_ldb_module_delete, METH_VARARGS, NULL },
2271 { "start_transaction", (PyCFunction)py_ldb_module_start_transaction, METH_NOARGS, NULL },
2272 { "end_transaction", (PyCFunction)py_ldb_module_end_transaction, METH_NOARGS, NULL },
2273 { "del_transaction", (PyCFunction)py_ldb_module_del_transaction, METH_NOARGS, NULL },
2274 { NULL },
2277 static void py_ldb_module_dealloc(PyLdbModuleObject *self)
2279 talloc_free(self->mem_ctx);
2280 PyObject_Del(self);
2283 static PyTypeObject PyLdbModule = {
2284 .tp_name = "ldb.LdbModule",
2285 .tp_methods = py_ldb_module_methods,
2286 .tp_repr = (reprfunc)py_ldb_module_repr,
2287 .tp_str = (reprfunc)py_ldb_module_str,
2288 .tp_basicsize = sizeof(PyLdbModuleObject),
2289 .tp_dealloc = (destructor)py_ldb_module_dealloc,
2290 .tp_flags = Py_TPFLAGS_DEFAULT,
2291 .tp_doc = "LDB module (extension)",
2296 * Create a ldb_message_element from a Python object.
2298 * This will accept any sequence objects that contains strings, or
2299 * a string object.
2301 * A reference to set_obj will be borrowed.
2303 * @param mem_ctx Memory context
2304 * @param set_obj Python object to convert
2305 * @param flags ldb_message_element flags to set
2306 * @param attr_name Name of the attribute
2307 * @return New ldb_message_element, allocated as child of mem_ctx
2309 static struct ldb_message_element *PyObject_AsMessageElement(
2310 TALLOC_CTX *mem_ctx,
2311 PyObject *set_obj,
2312 unsigned int flags,
2313 const char *attr_name)
2315 struct ldb_message_element *me;
2317 if (pyldb_MessageElement_Check(set_obj)) {
2318 PyLdbMessageElementObject *set_obj_as_me = (PyLdbMessageElementObject *)set_obj;
2319 /* We have to talloc_reference() the memory context, not the pointer
2320 * which may not actually be it's own context */
2321 if (talloc_reference(mem_ctx, set_obj_as_me->mem_ctx)) {
2322 return pyldb_MessageElement_AsMessageElement(set_obj);
2324 return NULL;
2327 me = talloc(mem_ctx, struct ldb_message_element);
2328 if (me == NULL) {
2329 PyErr_NoMemory();
2330 return NULL;
2333 me->name = talloc_strdup(me, attr_name);
2334 me->flags = flags;
2335 if (PyString_Check(set_obj)) {
2336 me->num_values = 1;
2337 me->values = talloc_array(me, struct ldb_val, me->num_values);
2338 me->values[0].length = PyString_Size(set_obj);
2339 me->values[0].data = talloc_memdup(me,
2340 (uint8_t *)PyString_AsString(set_obj), me->values[0].length+1);
2341 } else if (PySequence_Check(set_obj)) {
2342 Py_ssize_t i;
2343 me->num_values = PySequence_Size(set_obj);
2344 me->values = talloc_array(me, struct ldb_val, me->num_values);
2345 for (i = 0; i < me->num_values; i++) {
2346 PyObject *obj = PySequence_GetItem(set_obj, i);
2347 if (!PyString_Check(obj)) {
2348 PyErr_Format(PyExc_TypeError,
2349 "Expected string as element %zd in list", i);
2350 talloc_free(me);
2351 return NULL;
2354 me->values[i].length = PyString_Size(obj);
2355 me->values[i].data = talloc_memdup(me,
2356 (uint8_t *)PyString_AsString(obj), me->values[i].length+1);
2358 } else {
2359 PyErr_Format(PyExc_TypeError,
2360 "String or List type expected for '%s' attribute", attr_name);
2361 talloc_free(me);
2362 me = NULL;
2365 return me;
2369 static PyObject *ldb_msg_element_to_set(struct ldb_context *ldb_ctx,
2370 struct ldb_message_element *me)
2372 Py_ssize_t i;
2373 PyObject *result;
2375 /* Python << 2.5 doesn't have PySet_New and PySet_Add. */
2376 result = PyList_New(me->num_values);
2378 for (i = 0; i < me->num_values; i++) {
2379 PyList_SetItem(result, i,
2380 PyObject_FromLdbValue(&me->values[i]));
2383 return result;
2386 static PyObject *py_ldb_msg_element_get(PyLdbMessageElementObject *self, PyObject *args)
2388 unsigned int i;
2389 if (!PyArg_ParseTuple(args, "I", &i))
2390 return NULL;
2391 if (i >= pyldb_MessageElement_AsMessageElement(self)->num_values)
2392 Py_RETURN_NONE;
2394 return PyObject_FromLdbValue(&(pyldb_MessageElement_AsMessageElement(self)->values[i]));
2397 static PyObject *py_ldb_msg_element_flags(PyLdbMessageElementObject *self, PyObject *args)
2399 struct ldb_message_element *el = pyldb_MessageElement_AsMessageElement(self);
2400 return PyInt_FromLong(el->flags);
2403 static PyObject *py_ldb_msg_element_set_flags(PyLdbMessageElementObject *self, PyObject *args)
2405 unsigned int flags;
2406 struct ldb_message_element *el;
2407 if (!PyArg_ParseTuple(args, "I", &flags))
2408 return NULL;
2410 el = pyldb_MessageElement_AsMessageElement(self);
2411 el->flags = flags;
2412 Py_RETURN_NONE;
2415 static PyMethodDef py_ldb_msg_element_methods[] = {
2416 { "get", (PyCFunction)py_ldb_msg_element_get, METH_VARARGS, NULL },
2417 { "set_flags", (PyCFunction)py_ldb_msg_element_set_flags, METH_VARARGS, NULL },
2418 { "flags", (PyCFunction)py_ldb_msg_element_flags, METH_NOARGS, NULL },
2419 { NULL },
2422 static Py_ssize_t py_ldb_msg_element_len(PyLdbMessageElementObject *self)
2424 return pyldb_MessageElement_AsMessageElement(self)->num_values;
2427 static PyObject *py_ldb_msg_element_find(PyLdbMessageElementObject *self, Py_ssize_t idx)
2429 struct ldb_message_element *el = pyldb_MessageElement_AsMessageElement(self);
2430 if (idx < 0 || idx >= el->num_values) {
2431 PyErr_SetString(PyExc_IndexError, "Out of range");
2432 return NULL;
2434 return PyString_FromStringAndSize((char *)el->values[idx].data, el->values[idx].length);
2437 static PySequenceMethods py_ldb_msg_element_seq = {
2438 .sq_length = (lenfunc)py_ldb_msg_element_len,
2439 .sq_item = (ssizeargfunc)py_ldb_msg_element_find,
2442 static int py_ldb_msg_element_cmp(PyLdbMessageElementObject *self, PyLdbMessageElementObject *other)
2444 int ret = ldb_msg_element_compare(pyldb_MessageElement_AsMessageElement(self),
2445 pyldb_MessageElement_AsMessageElement(other));
2446 return SIGN(ret);
2449 static PyObject *py_ldb_msg_element_iter(PyLdbMessageElementObject *self)
2451 PyObject *el = ldb_msg_element_to_set(NULL,
2452 pyldb_MessageElement_AsMessageElement(self));
2453 return PyObject_GetIter(el);
2456 static PyObject *PyLdbMessageElement_FromMessageElement(struct ldb_message_element *el, TALLOC_CTX *mem_ctx)
2458 PyLdbMessageElementObject *ret;
2459 ret = PyObject_New(PyLdbMessageElementObject, &PyLdbMessageElement);
2460 if (ret == NULL) {
2461 PyErr_NoMemory();
2462 return NULL;
2464 ret->mem_ctx = talloc_new(NULL);
2465 if (talloc_reference(ret->mem_ctx, mem_ctx) == NULL) {
2466 PyErr_NoMemory();
2467 return NULL;
2469 ret->el = el;
2470 return (PyObject *)ret;
2473 static PyObject *py_ldb_msg_element_new(PyTypeObject *type, PyObject *args, PyObject *kwargs)
2475 PyObject *py_elements = NULL;
2476 struct ldb_message_element *el;
2477 unsigned int flags = 0;
2478 char *name = NULL;
2479 const char * const kwnames[] = { "elements", "flags", "name", NULL };
2480 PyLdbMessageElementObject *ret;
2481 TALLOC_CTX *mem_ctx;
2483 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "|OIs",
2484 discard_const_p(char *, kwnames),
2485 &py_elements, &flags, &name))
2486 return NULL;
2488 mem_ctx = talloc_new(NULL);
2489 if (mem_ctx == NULL) {
2490 PyErr_NoMemory();
2491 return NULL;
2494 el = talloc_zero(mem_ctx, struct ldb_message_element);
2495 if (el == NULL) {
2496 PyErr_NoMemory();
2497 talloc_free(mem_ctx);
2498 return NULL;
2501 if (py_elements != NULL) {
2502 Py_ssize_t i;
2503 if (PyString_Check(py_elements)) {
2504 el->num_values = 1;
2505 el->values = talloc_array(el, struct ldb_val, 1);
2506 if (el->values == NULL) {
2507 talloc_free(mem_ctx);
2508 PyErr_NoMemory();
2509 return NULL;
2511 el->values[0].length = PyString_Size(py_elements);
2512 el->values[0].data = talloc_memdup(el->values,
2513 (uint8_t *)PyString_AsString(py_elements), el->values[0].length+1);
2514 } else if (PySequence_Check(py_elements)) {
2515 el->num_values = PySequence_Size(py_elements);
2516 el->values = talloc_array(el, struct ldb_val, el->num_values);
2517 if (el->values == NULL) {
2518 talloc_free(mem_ctx);
2519 PyErr_NoMemory();
2520 return NULL;
2522 for (i = 0; i < el->num_values; i++) {
2523 PyObject *item = PySequence_GetItem(py_elements, i);
2524 if (item == NULL) {
2525 talloc_free(mem_ctx);
2526 return NULL;
2528 if (!PyString_Check(item)) {
2529 PyErr_Format(PyExc_TypeError,
2530 "Expected string as element %zd in list", i);
2531 talloc_free(mem_ctx);
2532 return NULL;
2534 el->values[i].length = PyString_Size(item);
2535 el->values[i].data = talloc_memdup(el,
2536 (uint8_t *)PyString_AsString(item), el->values[i].length+1);
2538 } else {
2539 PyErr_SetString(PyExc_TypeError,
2540 "Expected string or list");
2541 talloc_free(mem_ctx);
2542 return NULL;
2546 el->flags = flags;
2547 el->name = talloc_strdup(el, name);
2549 ret = PyObject_New(PyLdbMessageElementObject, type);
2550 if (ret == NULL) {
2551 talloc_free(mem_ctx);
2552 return NULL;
2555 ret->mem_ctx = mem_ctx;
2556 ret->el = el;
2557 return (PyObject *)ret;
2560 static PyObject *py_ldb_msg_element_repr(PyLdbMessageElementObject *self)
2562 char *element_str = NULL;
2563 Py_ssize_t i;
2564 struct ldb_message_element *el = pyldb_MessageElement_AsMessageElement(self);
2565 PyObject *ret;
2567 for (i = 0; i < el->num_values; i++) {
2568 PyObject *o = py_ldb_msg_element_find(self, i);
2569 if (element_str == NULL)
2570 element_str = talloc_strdup(NULL, PyObject_REPR(o));
2571 else
2572 element_str = talloc_asprintf_append(element_str, ",%s", PyObject_REPR(o));
2575 if (element_str != NULL) {
2576 ret = PyString_FromFormat("MessageElement([%s])", element_str);
2577 talloc_free(element_str);
2578 } else {
2579 ret = PyString_FromString("MessageElement([])");
2582 return ret;
2585 static PyObject *py_ldb_msg_element_str(PyLdbMessageElementObject *self)
2587 struct ldb_message_element *el = pyldb_MessageElement_AsMessageElement(self);
2589 if (el->num_values == 1)
2590 return PyString_FromStringAndSize((char *)el->values[0].data, el->values[0].length);
2591 else
2592 Py_RETURN_NONE;
2595 static void py_ldb_msg_element_dealloc(PyLdbMessageElementObject *self)
2597 talloc_free(self->mem_ctx);
2598 PyObject_Del(self);
2601 static PyTypeObject PyLdbMessageElement = {
2602 .tp_name = "ldb.MessageElement",
2603 .tp_basicsize = sizeof(PyLdbMessageElementObject),
2604 .tp_dealloc = (destructor)py_ldb_msg_element_dealloc,
2605 .tp_repr = (reprfunc)py_ldb_msg_element_repr,
2606 .tp_str = (reprfunc)py_ldb_msg_element_str,
2607 .tp_methods = py_ldb_msg_element_methods,
2608 .tp_compare = (cmpfunc)py_ldb_msg_element_cmp,
2609 .tp_iter = (getiterfunc)py_ldb_msg_element_iter,
2610 .tp_as_sequence = &py_ldb_msg_element_seq,
2611 .tp_new = py_ldb_msg_element_new,
2612 .tp_flags = Py_TPFLAGS_DEFAULT,
2613 .tp_doc = "An element of a Message",
2617 static PyObject *py_ldb_msg_from_dict(PyTypeObject *type, PyObject *args)
2619 PyObject *py_ldb;
2620 PyObject *py_dict;
2621 PyObject *py_ret;
2622 struct ldb_message *msg;
2623 struct ldb_context *ldb_ctx;
2624 unsigned int mod_flags = LDB_FLAG_MOD_REPLACE;
2626 if (!PyArg_ParseTuple(args, "O!O!|I",
2627 &PyLdb, &py_ldb, &PyDict_Type, &py_dict,
2628 &mod_flags)) {
2629 return NULL;
2632 if (!PyLdb_Check(py_ldb)) {
2633 PyErr_SetString(PyExc_TypeError, "Expected Ldb");
2634 return NULL;
2637 /* mask only flags we are going to use */
2638 mod_flags = LDB_FLAG_MOD_TYPE(mod_flags);
2639 if (!mod_flags) {
2640 PyErr_SetString(PyExc_ValueError,
2641 "FLAG_MOD_ADD, FLAG_MOD_REPLACE or FLAG_MOD_DELETE"
2642 " expected as mod_flag value");
2643 return NULL;
2646 ldb_ctx = pyldb_Ldb_AsLdbContext(py_ldb);
2648 msg = PyDict_AsMessage(ldb_ctx, py_dict, ldb_ctx, mod_flags);
2649 if (!msg) {
2650 return NULL;
2653 py_ret = PyLdbMessage_FromMessage(msg);
2655 talloc_unlink(ldb_ctx, msg);
2657 return py_ret;
2660 static PyObject *py_ldb_msg_remove_attr(PyLdbMessageObject *self, PyObject *args)
2662 char *name;
2663 if (!PyArg_ParseTuple(args, "s", &name))
2664 return NULL;
2666 ldb_msg_remove_attr(self->msg, name);
2668 Py_RETURN_NONE;
2671 static PyObject *py_ldb_msg_keys(PyLdbMessageObject *self)
2673 struct ldb_message *msg = pyldb_Message_AsMessage(self);
2674 Py_ssize_t i, j = 0;
2675 PyObject *obj = PyList_New(msg->num_elements+(msg->dn != NULL?1:0));
2676 if (msg->dn != NULL) {
2677 PyList_SetItem(obj, j, PyString_FromString("dn"));
2678 j++;
2680 for (i = 0; i < msg->num_elements; i++) {
2681 PyList_SetItem(obj, j, PyString_FromString(msg->elements[i].name));
2682 j++;
2684 return obj;
2687 static PyObject *py_ldb_msg_getitem_helper(PyLdbMessageObject *self, PyObject *py_name)
2689 struct ldb_message_element *el;
2690 char *name;
2691 struct ldb_message *msg = pyldb_Message_AsMessage(self);
2692 if (!PyString_Check(py_name)) {
2693 PyErr_SetNone(PyExc_TypeError);
2694 return NULL;
2696 name = PyString_AsString(py_name);
2697 if (!ldb_attr_cmp(name, "dn"))
2698 return pyldb_Dn_FromDn(msg->dn);
2699 el = ldb_msg_find_element(msg, name);
2700 if (el == NULL) {
2701 return NULL;
2703 return (PyObject *)PyLdbMessageElement_FromMessageElement(el, msg->elements);
2706 static PyObject *py_ldb_msg_getitem(PyLdbMessageObject *self, PyObject *py_name)
2708 PyObject *ret = py_ldb_msg_getitem_helper(self, py_name);
2709 if (ret == NULL) {
2710 PyErr_SetString(PyExc_KeyError, "No such element");
2711 return NULL;
2713 return ret;
2716 static PyObject *py_ldb_msg_get(PyLdbMessageObject *self, PyObject *args, PyObject *kwargs)
2718 PyObject *def = NULL;
2719 const char *kwnames[] = { "name", "default", "idx", NULL };
2720 const char *name = NULL;
2721 int idx = -1;
2722 struct ldb_message *msg = pyldb_Message_AsMessage(self);
2723 struct ldb_message_element *el;
2725 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "s|Oi:msg",
2726 discard_const_p(char *, kwnames), &name, &def, &idx)) {
2727 return NULL;
2730 if (strcasecmp(name, "dn") == 0) {
2731 return pyldb_Dn_FromDn(msg->dn);
2734 el = ldb_msg_find_element(msg, name);
2736 if (el == NULL || (idx != -1 && el->num_values <= idx)) {
2737 if (def != NULL) {
2738 return def;
2740 Py_RETURN_NONE;
2743 if (idx == -1) {
2744 return (PyObject *)PyLdbMessageElement_FromMessageElement(el, msg->elements);
2747 return PyObject_FromLdbValue(&el->values[idx]);
2750 static PyObject *py_ldb_msg_items(PyLdbMessageObject *self)
2752 struct ldb_message *msg = pyldb_Message_AsMessage(self);
2753 Py_ssize_t i, j = 0;
2754 PyObject *l = PyList_New(msg->num_elements + (msg->dn == NULL?0:1));
2755 if (msg->dn != NULL) {
2756 PyList_SetItem(l, 0, Py_BuildValue("(sO)", "dn", pyldb_Dn_FromDn(msg->dn)));
2757 j++;
2759 for (i = 0; i < msg->num_elements; i++, j++) {
2760 PyObject *py_el = PyLdbMessageElement_FromMessageElement(&msg->elements[i], msg->elements);
2761 PyObject *value = Py_BuildValue("(sO)", msg->elements[i].name, py_el);
2762 PyList_SetItem(l, j, value);
2764 return l;
2767 static PyObject *py_ldb_msg_elements(PyLdbMessageObject *self)
2769 struct ldb_message *msg = pyldb_Message_AsMessage(self);
2770 Py_ssize_t i = 0;
2771 PyObject *l = PyList_New(msg->num_elements);
2772 for (i = 0; i < msg->num_elements; i++) {
2773 PyList_SetItem(l, i, PyLdbMessageElement_FromMessageElement(&msg->elements[i], msg->elements));
2775 return l;
2778 static PyObject *py_ldb_msg_add(PyLdbMessageObject *self, PyObject *args)
2780 struct ldb_message *msg = pyldb_Message_AsMessage(self);
2781 PyLdbMessageElementObject *py_element;
2782 int i, ret;
2783 struct ldb_message_element *el;
2784 struct ldb_message_element *el_new;
2786 if (!PyArg_ParseTuple(args, "O!", &PyLdbMessageElement, &py_element))
2787 return NULL;
2789 el = py_element->el;
2790 if (el == NULL) {
2791 PyErr_SetString(PyExc_ValueError, "Invalid MessageElement object");
2792 return NULL;
2795 ret = ldb_msg_add_empty(msg, el->name, el->flags, &el_new);
2796 PyErr_LDB_ERROR_IS_ERR_RAISE(PyExc_LdbError, ret, NULL);
2798 /* now deep copy all attribute values */
2799 el_new->values = talloc_array(msg->elements, struct ldb_val, el->num_values);
2800 if (el_new->values == NULL) {
2801 PyErr_NoMemory();
2802 return NULL;
2804 el_new->num_values = el->num_values;
2806 for (i = 0; i < el->num_values; i++) {
2807 el_new->values[i] = ldb_val_dup(el_new->values, &el->values[i]);
2808 if (el_new->values[i].data == NULL
2809 && el->values[i].length != 0) {
2810 PyErr_NoMemory();
2811 return NULL;
2815 Py_RETURN_NONE;
2818 static PyMethodDef py_ldb_msg_methods[] = {
2819 { "from_dict", (PyCFunction)py_ldb_msg_from_dict, METH_CLASS | METH_VARARGS,
2820 "Message.from_dict(ldb, dict, mod_flag=FLAG_MOD_REPLACE) -> ldb.Message\n"
2821 "Class method to create ldb.Message object from Dictionary.\n"
2822 "mod_flag is one of FLAG_MOD_ADD, FLAG_MOD_REPLACE or FLAG_MOD_DELETE."},
2823 { "keys", (PyCFunction)py_ldb_msg_keys, METH_NOARGS,
2824 "S.keys() -> list\n\n"
2825 "Return sequence of all attribute names." },
2826 { "remove", (PyCFunction)py_ldb_msg_remove_attr, METH_VARARGS,
2827 "S.remove(name)\n\n"
2828 "Remove all entries for attributes with the specified name."},
2829 { "get", (PyCFunction)py_ldb_msg_get, METH_VARARGS | METH_KEYWORDS,
2830 "msg.get(name,default=None,idx=None) -> string\n"
2831 "idx is the index into the values array\n"
2832 "if idx is None, then a list is returned\n"
2833 "if idx is not None, then the element with that index is returned\n"
2834 "if you pass the special name 'dn' then the DN object is returned\n"},
2835 { "items", (PyCFunction)py_ldb_msg_items, METH_NOARGS, NULL },
2836 { "elements", (PyCFunction)py_ldb_msg_elements, METH_NOARGS, NULL },
2837 { "add", (PyCFunction)py_ldb_msg_add, METH_VARARGS,
2838 "S.add(element)\n\n"
2839 "Add an element to this message." },
2840 { NULL },
2843 static PyObject *py_ldb_msg_iter(PyLdbMessageObject *self)
2845 PyObject *list, *iter;
2847 list = py_ldb_msg_keys(self);
2848 iter = PyObject_GetIter(list);
2849 Py_DECREF(list);
2850 return iter;
2853 static int py_ldb_msg_setitem(PyLdbMessageObject *self, PyObject *name, PyObject *value)
2855 char *attr_name;
2857 if (!PyString_Check(name)) {
2858 PyErr_SetNone(PyExc_TypeError);
2859 return -1;
2862 attr_name = PyString_AsString(name);
2863 if (value == NULL) {
2864 /* delitem */
2865 ldb_msg_remove_attr(self->msg, attr_name);
2866 } else {
2867 int ret;
2868 struct ldb_message_element *el = PyObject_AsMessageElement(self->msg,
2869 value, 0, attr_name);
2870 if (el == NULL) {
2871 return -1;
2873 ldb_msg_remove_attr(pyldb_Message_AsMessage(self), attr_name);
2874 ret = ldb_msg_add(pyldb_Message_AsMessage(self), el, el->flags);
2875 if (ret != LDB_SUCCESS) {
2876 PyErr_SetLdbError(PyExc_LdbError, ret, NULL);
2877 return -1;
2880 return 0;
2883 static Py_ssize_t py_ldb_msg_length(PyLdbMessageObject *self)
2885 return pyldb_Message_AsMessage(self)->num_elements;
2888 static PyMappingMethods py_ldb_msg_mapping = {
2889 .mp_length = (lenfunc)py_ldb_msg_length,
2890 .mp_subscript = (binaryfunc)py_ldb_msg_getitem,
2891 .mp_ass_subscript = (objobjargproc)py_ldb_msg_setitem,
2894 static PyObject *py_ldb_msg_new(PyTypeObject *type, PyObject *args, PyObject *kwargs)
2896 const char * const kwnames[] = { "dn", NULL };
2897 struct ldb_message *ret;
2898 TALLOC_CTX *mem_ctx;
2899 PyObject *pydn = NULL;
2900 PyLdbMessageObject *py_ret;
2902 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "|O",
2903 discard_const_p(char *, kwnames),
2904 &pydn))
2905 return NULL;
2907 mem_ctx = talloc_new(NULL);
2908 if (mem_ctx == NULL) {
2909 PyErr_NoMemory();
2910 return NULL;
2913 ret = ldb_msg_new(mem_ctx);
2914 if (ret == NULL) {
2915 talloc_free(mem_ctx);
2916 PyErr_NoMemory();
2917 return NULL;
2920 if (pydn != NULL) {
2921 struct ldb_dn *dn;
2922 if (!pyldb_Object_AsDn(NULL, pydn, NULL, &dn)) {
2923 talloc_free(mem_ctx);
2924 return NULL;
2926 ret->dn = talloc_reference(ret, dn);
2929 py_ret = (PyLdbMessageObject *)type->tp_alloc(type, 0);
2930 if (py_ret == NULL) {
2931 PyErr_NoMemory();
2932 talloc_free(mem_ctx);
2933 return NULL;
2936 py_ret->mem_ctx = mem_ctx;
2937 py_ret->msg = ret;
2938 return (PyObject *)py_ret;
2941 static PyObject *PyLdbMessage_FromMessage(struct ldb_message *msg)
2943 PyLdbMessageObject *ret;
2945 ret = (PyLdbMessageObject *)PyLdbMessage.tp_alloc(&PyLdbMessage, 0);
2946 if (ret == NULL) {
2947 PyErr_NoMemory();
2948 return NULL;
2950 ret->mem_ctx = talloc_new(NULL);
2951 ret->msg = talloc_reference(ret->mem_ctx, msg);
2952 return (PyObject *)ret;
2955 static PyObject *py_ldb_msg_get_dn(PyLdbMessageObject *self, void *closure)
2957 struct ldb_message *msg = pyldb_Message_AsMessage(self);
2958 return pyldb_Dn_FromDn(msg->dn);
2961 static int py_ldb_msg_set_dn(PyLdbMessageObject *self, PyObject *value, void *closure)
2963 struct ldb_message *msg = pyldb_Message_AsMessage(self);
2964 if (!pyldb_Dn_Check(value)) {
2965 PyErr_SetNone(PyExc_TypeError);
2966 return -1;
2969 msg->dn = talloc_reference(msg, pyldb_Dn_AsDn(value));
2970 return 0;
2973 static PyGetSetDef py_ldb_msg_getset[] = {
2974 { discard_const_p(char, "dn"), (getter)py_ldb_msg_get_dn, (setter)py_ldb_msg_set_dn, NULL },
2975 { NULL }
2978 static PyObject *py_ldb_msg_repr(PyLdbMessageObject *self)
2980 PyObject *dict = PyDict_New(), *ret;
2981 if (PyDict_Update(dict, (PyObject *)self) != 0)
2982 return NULL;
2983 ret = PyString_FromFormat("Message(%s)", PyObject_REPR(dict));
2984 Py_DECREF(dict);
2985 return ret;
2988 static void py_ldb_msg_dealloc(PyLdbMessageObject *self)
2990 talloc_free(self->mem_ctx);
2991 PyObject_Del(self);
2994 static int py_ldb_msg_compare(PyLdbMessageObject *py_msg1,
2995 PyLdbMessageObject *py_msg2)
2997 struct ldb_message *msg1 = pyldb_Message_AsMessage(py_msg1),
2998 *msg2 = pyldb_Message_AsMessage(py_msg2);
2999 unsigned int i;
3000 int ret;
3002 if ((msg1->dn != NULL) || (msg2->dn != NULL)) {
3003 ret = ldb_dn_compare(msg1->dn, msg2->dn);
3004 if (ret != 0) {
3005 return SIGN(ret);
3009 ret = msg1->num_elements - msg2->num_elements;
3010 if (ret != 0) {
3011 return SIGN(ret);
3014 for (i = 0; i < msg1->num_elements; i++) {
3015 ret = ldb_msg_element_compare_name(&msg1->elements[i],
3016 &msg2->elements[i]);
3017 if (ret != 0) {
3018 return SIGN(ret);
3021 ret = ldb_msg_element_compare(&msg1->elements[i],
3022 &msg2->elements[i]);
3023 if (ret != 0) {
3024 return SIGN(ret);
3028 return 0;
3031 static PyTypeObject PyLdbMessage = {
3032 .tp_name = "ldb.Message",
3033 .tp_methods = py_ldb_msg_methods,
3034 .tp_getset = py_ldb_msg_getset,
3035 .tp_as_mapping = &py_ldb_msg_mapping,
3036 .tp_basicsize = sizeof(PyLdbMessageObject),
3037 .tp_dealloc = (destructor)py_ldb_msg_dealloc,
3038 .tp_new = py_ldb_msg_new,
3039 .tp_repr = (reprfunc)py_ldb_msg_repr,
3040 .tp_flags = Py_TPFLAGS_DEFAULT,
3041 .tp_iter = (getiterfunc)py_ldb_msg_iter,
3042 .tp_compare = (cmpfunc)py_ldb_msg_compare,
3043 .tp_doc = "A LDB Message",
3046 static PyObject *PyLdbTree_FromTree(struct ldb_parse_tree *tree)
3048 PyLdbTreeObject *ret;
3050 ret = (PyLdbTreeObject *)PyLdbTree.tp_alloc(&PyLdbTree, 0);
3051 if (ret == NULL) {
3052 PyErr_NoMemory();
3053 return NULL;
3056 ret->mem_ctx = talloc_new(NULL);
3057 ret->tree = talloc_reference(ret->mem_ctx, tree);
3058 return (PyObject *)ret;
3061 static void py_ldb_tree_dealloc(PyLdbTreeObject *self)
3063 talloc_free(self->mem_ctx);
3064 PyObject_Del(self);
3067 static PyTypeObject PyLdbTree = {
3068 .tp_name = "ldb.Tree",
3069 .tp_basicsize = sizeof(PyLdbTreeObject),
3070 .tp_dealloc = (destructor)py_ldb_tree_dealloc,
3071 .tp_flags = Py_TPFLAGS_DEFAULT,
3072 .tp_doc = "A search tree",
3075 /* Ldb_module */
3076 static int py_module_search(struct ldb_module *mod, struct ldb_request *req)
3078 PyObject *py_ldb = (PyObject *)mod->private_data;
3079 PyObject *py_result, *py_base, *py_attrs, *py_tree;
3081 py_base = pyldb_Dn_FromDn(req->op.search.base);
3083 if (py_base == NULL)
3084 return LDB_ERR_OPERATIONS_ERROR;
3086 py_tree = PyLdbTree_FromTree(req->op.search.tree);
3088 if (py_tree == NULL)
3089 return LDB_ERR_OPERATIONS_ERROR;
3091 if (req->op.search.attrs == NULL) {
3092 py_attrs = Py_None;
3093 } else {
3094 int i, len;
3095 for (len = 0; req->op.search.attrs[len]; len++);
3096 py_attrs = PyList_New(len);
3097 for (i = 0; i < len; i++)
3098 PyList_SetItem(py_attrs, i, PyString_FromString(req->op.search.attrs[i]));
3101 py_result = PyObject_CallMethod(py_ldb, discard_const_p(char, "search"),
3102 discard_const_p(char, "OiOO"),
3103 py_base, req->op.search.scope, py_tree, py_attrs);
3105 Py_DECREF(py_attrs);
3106 Py_DECREF(py_tree);
3107 Py_DECREF(py_base);
3109 if (py_result == NULL) {
3110 return LDB_ERR_PYTHON_EXCEPTION;
3113 req->op.search.res = PyLdbResult_AsResult(NULL, py_result);
3114 if (req->op.search.res == NULL) {
3115 return LDB_ERR_PYTHON_EXCEPTION;
3118 Py_DECREF(py_result);
3120 return LDB_SUCCESS;
3123 static int py_module_add(struct ldb_module *mod, struct ldb_request *req)
3125 PyObject *py_ldb = (PyObject *)mod->private_data;
3126 PyObject *py_result, *py_msg;
3128 py_msg = PyLdbMessage_FromMessage(discard_const_p(struct ldb_message, req->op.add.message));
3130 if (py_msg == NULL) {
3131 return LDB_ERR_OPERATIONS_ERROR;
3134 py_result = PyObject_CallMethod(py_ldb, discard_const_p(char, "add"),
3135 discard_const_p(char, "O"),
3136 py_msg);
3138 Py_DECREF(py_msg);
3140 if (py_result == NULL) {
3141 return LDB_ERR_PYTHON_EXCEPTION;
3144 Py_DECREF(py_result);
3146 return LDB_SUCCESS;
3149 static int py_module_modify(struct ldb_module *mod, struct ldb_request *req)
3151 PyObject *py_ldb = (PyObject *)mod->private_data;
3152 PyObject *py_result, *py_msg;
3154 py_msg = PyLdbMessage_FromMessage(discard_const_p(struct ldb_message, req->op.mod.message));
3156 if (py_msg == NULL) {
3157 return LDB_ERR_OPERATIONS_ERROR;
3160 py_result = PyObject_CallMethod(py_ldb, discard_const_p(char, "modify"),
3161 discard_const_p(char, "O"),
3162 py_msg);
3164 Py_DECREF(py_msg);
3166 if (py_result == NULL) {
3167 return LDB_ERR_PYTHON_EXCEPTION;
3170 Py_DECREF(py_result);
3172 return LDB_SUCCESS;
3175 static int py_module_del(struct ldb_module *mod, struct ldb_request *req)
3177 PyObject *py_ldb = (PyObject *)mod->private_data;
3178 PyObject *py_result, *py_dn;
3180 py_dn = pyldb_Dn_FromDn(req->op.del.dn);
3182 if (py_dn == NULL)
3183 return LDB_ERR_OPERATIONS_ERROR;
3185 py_result = PyObject_CallMethod(py_ldb, discard_const_p(char, "delete"),
3186 discard_const_p(char, "O"),
3187 py_dn);
3189 if (py_result == NULL) {
3190 return LDB_ERR_PYTHON_EXCEPTION;
3193 Py_DECREF(py_result);
3195 return LDB_SUCCESS;
3198 static int py_module_rename(struct ldb_module *mod, struct ldb_request *req)
3200 PyObject *py_ldb = (PyObject *)mod->private_data;
3201 PyObject *py_result, *py_olddn, *py_newdn;
3203 py_olddn = pyldb_Dn_FromDn(req->op.rename.olddn);
3205 if (py_olddn == NULL)
3206 return LDB_ERR_OPERATIONS_ERROR;
3208 py_newdn = pyldb_Dn_FromDn(req->op.rename.newdn);
3210 if (py_newdn == NULL)
3211 return LDB_ERR_OPERATIONS_ERROR;
3213 py_result = PyObject_CallMethod(py_ldb, discard_const_p(char, "rename"),
3214 discard_const_p(char, "OO"),
3215 py_olddn, py_newdn);
3217 Py_DECREF(py_olddn);
3218 Py_DECREF(py_newdn);
3220 if (py_result == NULL) {
3221 return LDB_ERR_PYTHON_EXCEPTION;
3224 Py_DECREF(py_result);
3226 return LDB_SUCCESS;
3229 static int py_module_request(struct ldb_module *mod, struct ldb_request *req)
3231 PyObject *py_ldb = (PyObject *)mod->private_data;
3232 PyObject *py_result;
3234 py_result = PyObject_CallMethod(py_ldb, discard_const_p(char, "request"),
3235 discard_const_p(char, ""));
3237 Py_XDECREF(py_result);
3239 return LDB_ERR_OPERATIONS_ERROR;
3242 static int py_module_extended(struct ldb_module *mod, struct ldb_request *req)
3244 PyObject *py_ldb = (PyObject *)mod->private_data;
3245 PyObject *py_result;
3247 py_result = PyObject_CallMethod(py_ldb, discard_const_p(char, "extended"),
3248 discard_const_p(char, ""));
3250 Py_XDECREF(py_result);
3252 return LDB_ERR_OPERATIONS_ERROR;
3255 static int py_module_start_transaction(struct ldb_module *mod)
3257 PyObject *py_ldb = (PyObject *)mod->private_data;
3258 PyObject *py_result;
3260 py_result = PyObject_CallMethod(py_ldb, discard_const_p(char, "start_transaction"),
3261 discard_const_p(char, ""));
3263 if (py_result == NULL) {
3264 return LDB_ERR_PYTHON_EXCEPTION;
3267 Py_DECREF(py_result);
3269 return LDB_SUCCESS;
3272 static int py_module_end_transaction(struct ldb_module *mod)
3274 PyObject *py_ldb = (PyObject *)mod->private_data;
3275 PyObject *py_result;
3277 py_result = PyObject_CallMethod(py_ldb, discard_const_p(char, "end_transaction"),
3278 discard_const_p(char, ""));
3280 if (py_result == NULL) {
3281 return LDB_ERR_PYTHON_EXCEPTION;
3284 Py_DECREF(py_result);
3286 return LDB_SUCCESS;
3289 static int py_module_del_transaction(struct ldb_module *mod)
3291 PyObject *py_ldb = (PyObject *)mod->private_data;
3292 PyObject *py_result;
3294 py_result = PyObject_CallMethod(py_ldb, discard_const_p(char, "del_transaction"),
3295 discard_const_p(char, ""));
3297 if (py_result == NULL) {
3298 return LDB_ERR_PYTHON_EXCEPTION;
3301 Py_DECREF(py_result);
3303 return LDB_SUCCESS;
3306 static int py_module_destructor(struct ldb_module *mod)
3308 Py_DECREF((PyObject *)mod->private_data);
3309 return 0;
3312 static int py_module_init(struct ldb_module *mod)
3314 PyObject *py_class = (PyObject *)mod->ops->private_data;
3315 PyObject *py_result, *py_next, *py_ldb;
3317 py_ldb = PyLdb_FromLdbContext(mod->ldb);
3319 if (py_ldb == NULL)
3320 return LDB_ERR_OPERATIONS_ERROR;
3322 py_next = PyLdbModule_FromModule(mod->next);
3324 if (py_next == NULL)
3325 return LDB_ERR_OPERATIONS_ERROR;
3327 py_result = PyObject_CallFunction(py_class, discard_const_p(char, "OO"),
3328 py_ldb, py_next);
3330 if (py_result == NULL) {
3331 return LDB_ERR_PYTHON_EXCEPTION;
3334 mod->private_data = py_result;
3336 talloc_set_destructor(mod, py_module_destructor);
3338 return ldb_next_init(mod);
3341 static PyObject *py_register_module(PyObject *module, PyObject *args)
3343 int ret;
3344 struct ldb_module_ops *ops;
3345 PyObject *input;
3347 if (!PyArg_ParseTuple(args, "O", &input))
3348 return NULL;
3350 ops = talloc_zero(talloc_autofree_context(), struct ldb_module_ops);
3351 if (ops == NULL) {
3352 PyErr_NoMemory();
3353 return NULL;
3356 ops->name = talloc_strdup(ops, PyString_AsString(PyObject_GetAttrString(input, discard_const_p(char, "name"))));
3358 Py_INCREF(input);
3359 ops->private_data = input;
3360 ops->init_context = py_module_init;
3361 ops->search = py_module_search;
3362 ops->add = py_module_add;
3363 ops->modify = py_module_modify;
3364 ops->del = py_module_del;
3365 ops->rename = py_module_rename;
3366 ops->request = py_module_request;
3367 ops->extended = py_module_extended;
3368 ops->start_transaction = py_module_start_transaction;
3369 ops->end_transaction = py_module_end_transaction;
3370 ops->del_transaction = py_module_del_transaction;
3372 ret = ldb_register_module(ops);
3374 PyErr_LDB_ERROR_IS_ERR_RAISE(PyExc_LdbError, ret, NULL);
3376 Py_RETURN_NONE;
3379 static PyObject *py_timestring(PyObject *module, PyObject *args)
3381 /* most times "time_t" is a signed integer type with 32 or 64 bit:
3382 * http://stackoverflow.com/questions/471248/what-is-ultimately-a-time-t-typedef-to */
3383 long int t_val;
3384 char *tresult;
3385 PyObject *ret;
3386 if (!PyArg_ParseTuple(args, "l", &t_val))
3387 return NULL;
3388 tresult = ldb_timestring(NULL, (time_t) t_val);
3389 ret = PyString_FromString(tresult);
3390 talloc_free(tresult);
3391 return ret;
3394 static PyObject *py_string_to_time(PyObject *module, PyObject *args)
3396 char *str;
3397 if (!PyArg_ParseTuple(args, "s", &str))
3398 return NULL;
3400 return PyInt_FromLong(ldb_string_to_time(str));
3403 static PyObject *py_valid_attr_name(PyObject *self, PyObject *args)
3405 char *name;
3406 if (!PyArg_ParseTuple(args, "s", &name))
3407 return NULL;
3408 return PyBool_FromLong(ldb_valid_attr_name(name));
3412 encode a string using RFC2254 rules
3414 static PyObject *py_binary_encode(PyObject *self, PyObject *args)
3416 char *str, *encoded;
3417 int size = 0;
3418 struct ldb_val val;
3419 PyObject *ret;
3421 if (!PyArg_ParseTuple(args, "s#", &str, &size))
3422 return NULL;
3423 val.data = (uint8_t *)str;
3424 val.length = size;
3426 encoded = ldb_binary_encode(NULL, val);
3427 if (encoded == NULL) {
3428 PyErr_SetString(PyExc_TypeError, "unable to encode binary string");
3429 return NULL;
3431 ret = PyString_FromString(encoded);
3432 talloc_free(encoded);
3433 return ret;
3437 decode a string using RFC2254 rules
3439 static PyObject *py_binary_decode(PyObject *self, PyObject *args)
3441 char *str;
3442 struct ldb_val val;
3443 PyObject *ret;
3445 if (!PyArg_ParseTuple(args, "s", &str))
3446 return NULL;
3448 val = ldb_binary_decode(NULL, str);
3449 if (val.data == NULL) {
3450 PyErr_SetString(PyExc_TypeError, "unable to decode binary string");
3451 return NULL;
3453 ret = Py_BuildValue("s#", val.data, val.length);
3454 talloc_free(val.data);
3455 return ret;
3458 static PyMethodDef py_ldb_global_methods[] = {
3459 { "register_module", py_register_module, METH_VARARGS,
3460 "S.register_module(module) -> None\n\n"
3461 "Register a LDB module."},
3462 { "timestring", py_timestring, METH_VARARGS,
3463 "S.timestring(int) -> string\n\n"
3464 "Generate a LDAP time string from a UNIX timestamp" },
3465 { "string_to_time", py_string_to_time, METH_VARARGS,
3466 "S.string_to_time(string) -> int\n\n"
3467 "Parse a LDAP time string into a UNIX timestamp." },
3468 { "valid_attr_name", py_valid_attr_name, METH_VARARGS,
3469 "S.valid_attr_name(name) -> bool\n\nn"
3470 "Check whether the supplied name is a valid attribute name." },
3471 { "open", (PyCFunction)py_ldb_new, METH_VARARGS|METH_KEYWORDS,
3472 "S.open() -> Ldb\n\n"
3473 "Open a new LDB context." },
3474 { "binary_encode", py_binary_encode, METH_VARARGS,
3475 "S.binary_encode(string) -> string\n\n"
3476 "Perform a RFC2254 binary encoding on a string" },
3477 { "binary_decode", py_binary_decode, METH_VARARGS,
3478 "S.binary_decode(string) -> string\n\n"
3479 "Perform a RFC2254 binary decode on a string" },
3480 { NULL }
3483 void initldb(void)
3485 PyObject *m;
3487 if (PyType_Ready(&PyLdbDn) < 0)
3488 return;
3490 if (PyType_Ready(&PyLdbMessage) < 0)
3491 return;
3493 if (PyType_Ready(&PyLdbMessageElement) < 0)
3494 return;
3496 if (PyType_Ready(&PyLdb) < 0)
3497 return;
3499 if (PyType_Ready(&PyLdbModule) < 0)
3500 return;
3502 if (PyType_Ready(&PyLdbTree) < 0)
3503 return;
3505 if (PyType_Ready(&PyLdbResult) < 0)
3506 return;
3508 if (PyType_Ready(&PyLdbControl) < 0)
3509 return;
3511 m = Py_InitModule3("ldb", py_ldb_global_methods,
3512 "An interface to LDB, a LDAP-like API that can either to talk an embedded database (TDB-based) or a standards-compliant LDAP server.");
3513 if (m == NULL)
3514 return;
3516 PyModule_AddObject(m, "SEQ_HIGHEST_SEQ", PyInt_FromLong(LDB_SEQ_HIGHEST_SEQ));
3517 PyModule_AddObject(m, "SEQ_HIGHEST_TIMESTAMP", PyInt_FromLong(LDB_SEQ_HIGHEST_TIMESTAMP));
3518 PyModule_AddObject(m, "SEQ_NEXT", PyInt_FromLong(LDB_SEQ_NEXT));
3519 PyModule_AddObject(m, "SCOPE_DEFAULT", PyInt_FromLong(LDB_SCOPE_DEFAULT));
3520 PyModule_AddObject(m, "SCOPE_BASE", PyInt_FromLong(LDB_SCOPE_BASE));
3521 PyModule_AddObject(m, "SCOPE_ONELEVEL", PyInt_FromLong(LDB_SCOPE_ONELEVEL));
3522 PyModule_AddObject(m, "SCOPE_SUBTREE", PyInt_FromLong(LDB_SCOPE_SUBTREE));
3524 PyModule_AddObject(m, "CHANGETYPE_NONE", PyInt_FromLong(LDB_CHANGETYPE_NONE));
3525 PyModule_AddObject(m, "CHANGETYPE_ADD", PyInt_FromLong(LDB_CHANGETYPE_ADD));
3526 PyModule_AddObject(m, "CHANGETYPE_DELETE", PyInt_FromLong(LDB_CHANGETYPE_DELETE));
3527 PyModule_AddObject(m, "CHANGETYPE_MODIFY", PyInt_FromLong(LDB_CHANGETYPE_MODIFY));
3529 PyModule_AddObject(m, "FLAG_MOD_ADD", PyInt_FromLong(LDB_FLAG_MOD_ADD));
3530 PyModule_AddObject(m, "FLAG_MOD_REPLACE", PyInt_FromLong(LDB_FLAG_MOD_REPLACE));
3531 PyModule_AddObject(m, "FLAG_MOD_DELETE", PyInt_FromLong(LDB_FLAG_MOD_DELETE));
3533 PyModule_AddObject(m, "SUCCESS", PyInt_FromLong(LDB_SUCCESS));
3534 PyModule_AddObject(m, "ERR_OPERATIONS_ERROR", PyInt_FromLong(LDB_ERR_OPERATIONS_ERROR));
3535 PyModule_AddObject(m, "ERR_PROTOCOL_ERROR", PyInt_FromLong(LDB_ERR_PROTOCOL_ERROR));
3536 PyModule_AddObject(m, "ERR_TIME_LIMIT_EXCEEDED", PyInt_FromLong(LDB_ERR_TIME_LIMIT_EXCEEDED));
3537 PyModule_AddObject(m, "ERR_SIZE_LIMIT_EXCEEDED", PyInt_FromLong(LDB_ERR_SIZE_LIMIT_EXCEEDED));
3538 PyModule_AddObject(m, "ERR_COMPARE_FALSE", PyInt_FromLong(LDB_ERR_COMPARE_FALSE));
3539 PyModule_AddObject(m, "ERR_COMPARE_TRUE", PyInt_FromLong(LDB_ERR_COMPARE_TRUE));
3540 PyModule_AddObject(m, "ERR_AUTH_METHOD_NOT_SUPPORTED", PyInt_FromLong(LDB_ERR_AUTH_METHOD_NOT_SUPPORTED));
3541 PyModule_AddObject(m, "ERR_STRONG_AUTH_REQUIRED", PyInt_FromLong(LDB_ERR_STRONG_AUTH_REQUIRED));
3542 PyModule_AddObject(m, "ERR_REFERRAL", PyInt_FromLong(LDB_ERR_REFERRAL));
3543 PyModule_AddObject(m, "ERR_ADMIN_LIMIT_EXCEEDED", PyInt_FromLong(LDB_ERR_ADMIN_LIMIT_EXCEEDED));
3544 PyModule_AddObject(m, "ERR_UNSUPPORTED_CRITICAL_EXTENSION", PyInt_FromLong(LDB_ERR_UNSUPPORTED_CRITICAL_EXTENSION));
3545 PyModule_AddObject(m, "ERR_CONFIDENTIALITY_REQUIRED", PyInt_FromLong(LDB_ERR_CONFIDENTIALITY_REQUIRED));
3546 PyModule_AddObject(m, "ERR_SASL_BIND_IN_PROGRESS", PyInt_FromLong(LDB_ERR_SASL_BIND_IN_PROGRESS));
3547 PyModule_AddObject(m, "ERR_NO_SUCH_ATTRIBUTE", PyInt_FromLong(LDB_ERR_NO_SUCH_ATTRIBUTE));
3548 PyModule_AddObject(m, "ERR_UNDEFINED_ATTRIBUTE_TYPE", PyInt_FromLong(LDB_ERR_UNDEFINED_ATTRIBUTE_TYPE));
3549 PyModule_AddObject(m, "ERR_INAPPROPRIATE_MATCHING", PyInt_FromLong(LDB_ERR_INAPPROPRIATE_MATCHING));
3550 PyModule_AddObject(m, "ERR_CONSTRAINT_VIOLATION", PyInt_FromLong(LDB_ERR_CONSTRAINT_VIOLATION));
3551 PyModule_AddObject(m, "ERR_ATTRIBUTE_OR_VALUE_EXISTS", PyInt_FromLong(LDB_ERR_ATTRIBUTE_OR_VALUE_EXISTS));
3552 PyModule_AddObject(m, "ERR_INVALID_ATTRIBUTE_SYNTAX", PyInt_FromLong(LDB_ERR_INVALID_ATTRIBUTE_SYNTAX));
3553 PyModule_AddObject(m, "ERR_NO_SUCH_OBJECT", PyInt_FromLong(LDB_ERR_NO_SUCH_OBJECT));
3554 PyModule_AddObject(m, "ERR_ALIAS_PROBLEM", PyInt_FromLong(LDB_ERR_ALIAS_PROBLEM));
3555 PyModule_AddObject(m, "ERR_INVALID_DN_SYNTAX", PyInt_FromLong(LDB_ERR_INVALID_DN_SYNTAX));
3556 PyModule_AddObject(m, "ERR_ALIAS_DEREFERINCING_PROBLEM", PyInt_FromLong(LDB_ERR_ALIAS_DEREFERENCING_PROBLEM));
3557 PyModule_AddObject(m, "ERR_INAPPROPRIATE_AUTHENTICATION", PyInt_FromLong(LDB_ERR_INAPPROPRIATE_AUTHENTICATION));
3558 PyModule_AddObject(m, "ERR_INVALID_CREDENTIALS", PyInt_FromLong(LDB_ERR_INVALID_CREDENTIALS));
3559 PyModule_AddObject(m, "ERR_INSUFFICIENT_ACCESS_RIGHTS", PyInt_FromLong(LDB_ERR_INSUFFICIENT_ACCESS_RIGHTS));
3560 PyModule_AddObject(m, "ERR_BUSY", PyInt_FromLong(LDB_ERR_BUSY));
3561 PyModule_AddObject(m, "ERR_UNAVAILABLE", PyInt_FromLong(LDB_ERR_UNAVAILABLE));
3562 PyModule_AddObject(m, "ERR_UNWILLING_TO_PERFORM", PyInt_FromLong(LDB_ERR_UNWILLING_TO_PERFORM));
3563 PyModule_AddObject(m, "ERR_LOOP_DETECT", PyInt_FromLong(LDB_ERR_LOOP_DETECT));
3564 PyModule_AddObject(m, "ERR_NAMING_VIOLATION", PyInt_FromLong(LDB_ERR_NAMING_VIOLATION));
3565 PyModule_AddObject(m, "ERR_OBJECT_CLASS_VIOLATION", PyInt_FromLong(LDB_ERR_OBJECT_CLASS_VIOLATION));
3566 PyModule_AddObject(m, "ERR_NOT_ALLOWED_ON_NON_LEAF", PyInt_FromLong(LDB_ERR_NOT_ALLOWED_ON_NON_LEAF));
3567 PyModule_AddObject(m, "ERR_NOT_ALLOWED_ON_RDN", PyInt_FromLong(LDB_ERR_NOT_ALLOWED_ON_RDN));
3568 PyModule_AddObject(m, "ERR_ENTRY_ALREADY_EXISTS", PyInt_FromLong(LDB_ERR_ENTRY_ALREADY_EXISTS));
3569 PyModule_AddObject(m, "ERR_OBJECT_CLASS_MODS_PROHIBITED", PyInt_FromLong(LDB_ERR_OBJECT_CLASS_MODS_PROHIBITED));
3570 PyModule_AddObject(m, "ERR_AFFECTS_MULTIPLE_DSAS", PyInt_FromLong(LDB_ERR_AFFECTS_MULTIPLE_DSAS));
3571 PyModule_AddObject(m, "ERR_OTHER", PyInt_FromLong(LDB_ERR_OTHER));
3573 PyModule_AddObject(m, "FLG_RDONLY", PyInt_FromLong(LDB_FLG_RDONLY));
3574 PyModule_AddObject(m, "FLG_NOSYNC", PyInt_FromLong(LDB_FLG_NOSYNC));
3575 PyModule_AddObject(m, "FLG_RECONNECT", PyInt_FromLong(LDB_FLG_RECONNECT));
3576 PyModule_AddObject(m, "FLG_NOMMAP", PyInt_FromLong(LDB_FLG_NOMMAP));
3578 PyModule_AddObject(m, "__docformat__", PyString_FromString("restructuredText"));
3580 PyExc_LdbError = PyErr_NewException(discard_const_p(char, "_ldb.LdbError"), NULL, NULL);
3581 PyModule_AddObject(m, "LdbError", PyExc_LdbError);
3583 Py_INCREF(&PyLdb);
3584 Py_INCREF(&PyLdbDn);
3585 Py_INCREF(&PyLdbModule);
3586 Py_INCREF(&PyLdbMessage);
3587 Py_INCREF(&PyLdbMessageElement);
3588 Py_INCREF(&PyLdbTree);
3589 Py_INCREF(&PyLdbResult);
3590 Py_INCREF(&PyLdbControl);
3592 PyModule_AddObject(m, "Ldb", (PyObject *)&PyLdb);
3593 PyModule_AddObject(m, "Dn", (PyObject *)&PyLdbDn);
3594 PyModule_AddObject(m, "Message", (PyObject *)&PyLdbMessage);
3595 PyModule_AddObject(m, "MessageElement", (PyObject *)&PyLdbMessageElement);
3596 PyModule_AddObject(m, "Module", (PyObject *)&PyLdbModule);
3597 PyModule_AddObject(m, "Tree", (PyObject *)&PyLdbTree);
3598 PyModule_AddObject(m, "Control", (PyObject *)&PyLdbControl);
3600 PyModule_AddObject(m, "__version__", PyString_FromString(PACKAGE_VERSION));
3602 #define ADD_LDB_STRING(val) PyModule_AddObject(m, #val, PyString_FromString(LDB_## val))
3604 ADD_LDB_STRING(SYNTAX_DN);
3605 ADD_LDB_STRING(SYNTAX_DIRECTORY_STRING);
3606 ADD_LDB_STRING(SYNTAX_INTEGER);
3607 ADD_LDB_STRING(SYNTAX_BOOLEAN);
3608 ADD_LDB_STRING(SYNTAX_OCTET_STRING);
3609 ADD_LDB_STRING(SYNTAX_UTC_TIME);
3610 ADD_LDB_STRING(OID_COMPARATOR_AND);
3611 ADD_LDB_STRING(OID_COMPARATOR_OR);