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
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/>.
32 #include "ldb_private.h"
33 #include "ldb_handlers.h"
35 #include "dlinklist.h"
37 /* discard signature of 'func' in favour of 'target_sig' */
38 #define PY_DISCARD_FUNC_SIG(target_sig, func) (target_sig)(void(*)(void))func
40 struct py_ldb_search_iterator_reply;
47 struct ldb_request *req;
48 struct py_ldb_search_iterator_reply *next;
49 struct py_ldb_search_iterator_reply *result;
52 } PyLdbSearchIteratorObject;
54 struct py_ldb_search_iterator_reply {
55 struct py_ldb_search_iterator_reply *prev, *next;
56 PyLdbSearchIteratorObject *py_iter;
61 static PyObject *PyLdbMessage_FromMessage(struct ldb_message *msg);
62 static PyObject *PyExc_LdbError;
64 static PyTypeObject PyLdbControl;
65 static PyTypeObject PyLdbResult;
66 static PyTypeObject PyLdbSearchIterator;
67 static PyTypeObject PyLdbMessage;
68 #define PyLdbMessage_Check(ob) PyObject_TypeCheck(ob, &PyLdbMessage)
69 static PyTypeObject PyLdbModule;
70 static PyTypeObject PyLdbDn;
71 #define pyldb_Dn_Check(ob) PyObject_TypeCheck(ob, &PyLdbDn)
72 static PyTypeObject PyLdb;
73 #define PyLdb_Check(ob) PyObject_TypeCheck(ob, &PyLdb)
74 static PyTypeObject PyLdbMessageElement;
75 #define pyldb_MessageElement_Check(ob) PyObject_TypeCheck(ob, &PyLdbMessageElement)
77 static PyTypeObject PyLdbTree;
78 static PyObject *PyLdb_FromLdbContext(struct ldb_context *ldb_ctx);
79 static PyObject *PyLdbModule_FromModule(struct ldb_module *mod);
80 static struct ldb_message_element *PyObject_AsMessageElement(
84 const char *attr_name);
85 static PyTypeObject PyLdbBytesType;
87 #if PY_MAJOR_VERSION >= 3
88 #define PyInt_FromLong PyLong_FromLong
90 #define PYARG_STR_UNI "es"
92 static PyObject *PyLdbBytes_FromStringAndSize(const char *msg, int size)
94 PyObject* result = NULL;
95 PyObject* args = NULL;
96 args = Py_BuildValue("(y#)", msg, size);
97 result = PyLdbBytesType.tp_new(&PyLdbBytesType, args, NULL);
102 #define PyLdbBytes_FromStringAndSize PyString_FromStringAndSize
104 #define PYARG_STR_UNI "et"
108 static PyObject *richcmp(int cmp_val, int op)
112 case Py_LT: ret = cmp_val < 0; break;
113 case Py_LE: ret = cmp_val <= 0; break;
114 case Py_EQ: ret = cmp_val == 0; break;
115 case Py_NE: ret = cmp_val != 0; break;
116 case Py_GT: ret = cmp_val > 0; break;
117 case Py_GE: ret = cmp_val >= 0; break;
119 Py_INCREF(Py_NotImplemented);
120 return Py_NotImplemented;
122 return PyBool_FromLong(ret);
126 static PyObject *py_ldb_control_str(PyLdbControlObject *self)
128 if (self->data != NULL) {
129 char* control = ldb_control_to_string(self->mem_ctx, self->data);
130 if (control == NULL) {
134 return PyUnicode_FromString(control);
136 return PyUnicode_FromString("ldb control");
140 static void py_ldb_control_dealloc(PyLdbControlObject *self)
142 if (self->mem_ctx != NULL) {
143 talloc_free(self->mem_ctx);
146 Py_TYPE(self)->tp_free(self);
149 /* Create a text (rather than bytes) interface for a LDB result object */
150 static PyObject *wrap_text(const char *type, PyObject *wrapped)
152 PyObject *mod, *cls, *constructor, *inst;
153 mod = PyImport_ImportModule("_ldb_text");
156 cls = PyObject_GetAttrString(mod, type);
162 constructor = PyObject_GetAttrString(cls, "_wrap");
164 if (constructor == NULL) {
167 inst = PyObject_CallFunction(constructor, discard_const_p(char, "O"), wrapped);
168 Py_DECREF(constructor);
172 static PyObject *py_ldb_control_get_oid(PyLdbControlObject *self,
173 PyObject *Py_UNUSED(ignored))
175 return PyUnicode_FromString(self->data->oid);
178 static PyObject *py_ldb_control_get_critical(PyLdbControlObject *self,
179 PyObject *Py_UNUSED(ignored))
181 return PyBool_FromLong(self->data->critical);
184 static int py_ldb_control_set_critical(PyLdbControlObject *self, PyObject *value, void *closure)
186 if (PyObject_IsTrue(value)) {
187 self->data->critical = true;
189 self->data->critical = false;
194 static PyObject *py_ldb_control_new(PyTypeObject *type, PyObject *args, PyObject *kwargs)
197 const char * const kwnames[] = { "ldb", "data", NULL };
198 struct ldb_control *parsed_controls;
199 PyLdbControlObject *ret;
202 struct ldb_context *ldb_ctx;
204 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "O!s",
205 discard_const_p(char *, kwnames),
206 &PyLdb, &py_ldb, &data))
209 mem_ctx = talloc_new(NULL);
210 if (mem_ctx == NULL) {
215 ldb_ctx = pyldb_Ldb_AS_LDBCONTEXT(py_ldb);
216 parsed_controls = ldb_parse_control_from_string(ldb_ctx, mem_ctx, data);
218 if (!parsed_controls) {
219 talloc_free(mem_ctx);
220 PyErr_SetString(PyExc_ValueError, "unable to parse control string");
224 ret = PyObject_New(PyLdbControlObject, type);
227 talloc_free(mem_ctx);
231 ret->mem_ctx = mem_ctx;
233 ret->data = talloc_move(mem_ctx, &parsed_controls);
234 if (ret->data == NULL) {
237 talloc_free(mem_ctx);
241 return (PyObject *)ret;
244 static PyGetSetDef py_ldb_control_getset[] = {
246 .name = discard_const_p(char, "oid"),
247 .get = (getter)py_ldb_control_get_oid,
250 .name = discard_const_p(char, "critical"),
251 .get = (getter)py_ldb_control_get_critical,
252 .set = (setter)py_ldb_control_set_critical,
257 static PyTypeObject PyLdbControl = {
258 .tp_name = "ldb.control",
259 .tp_dealloc = (destructor)py_ldb_control_dealloc,
260 .tp_getattro = PyObject_GenericGetAttr,
261 .tp_basicsize = sizeof(PyLdbControlObject),
262 .tp_getset = py_ldb_control_getset,
263 .tp_doc = "LDB control.",
264 .tp_str = (reprfunc)py_ldb_control_str,
265 .tp_new = py_ldb_control_new,
266 .tp_flags = Py_TPFLAGS_DEFAULT|Py_TPFLAGS_BASETYPE,
269 static void PyErr_SetLdbError(PyObject *error, int ret, struct ldb_context *ldb_ctx)
271 if (ret == LDB_ERR_PYTHON_EXCEPTION)
272 return; /* Python exception should already be set, just keep that */
274 PyErr_SetObject(error,
275 Py_BuildValue(discard_const_p(char, "(i,s)"), ret,
276 ldb_ctx == NULL?ldb_strerror(ret):ldb_errstring(ldb_ctx)));
278 static PyObject *py_ldb_bytes_str(PyBytesObject *self)
283 if (!PyBytes_Check(self)) {
284 PyErr_Format(PyExc_TypeError,"Unexpected type");
287 result = PyBytes_AsStringAndSize((PyObject *)self, &msg, &size);
289 PyErr_Format(PyExc_TypeError, "Failed to extract bytes");
292 return PyUnicode_FromStringAndSize(msg, size);
295 static PyTypeObject PyLdbBytesType = {
296 PyVarObject_HEAD_INIT(NULL, 0)
297 .tp_name = "ldb.bytes",
298 .tp_doc = "str/bytes (with custom str)",
299 .tp_str = (reprfunc)py_ldb_bytes_str,
300 .tp_flags = Py_TPFLAGS_DEFAULT|Py_TPFLAGS_BASETYPE,
303 static PyObject *PyObject_FromLdbValue(const struct ldb_val *val)
305 return PyLdbBytes_FromStringAndSize((const char *)val->data, val->length);
308 static PyObject *PyStr_FromLdbValue(const struct ldb_val *val)
310 return PyUnicode_FromStringAndSize((const char *)val->data, val->length);
314 * Create a Python object from a ldb_result.
316 * @param result LDB result to convert
317 * @return Python object with converted result (a list object)
319 static PyObject *PyLdbControl_FromControl(struct ldb_control *control)
321 TALLOC_CTX *ctl_ctx = talloc_new(NULL);
322 PyLdbControlObject *ctrl;
323 if (ctl_ctx == NULL) {
328 ctrl = (PyLdbControlObject *)PyLdbControl.tp_alloc(&PyLdbControl, 0);
330 talloc_free(ctl_ctx);
334 ctrl->mem_ctx = ctl_ctx;
335 ctrl->data = talloc_steal(ctrl->mem_ctx, control);
336 if (ctrl->data == NULL) {
341 return (PyObject*) ctrl;
345 * Create a Python object from a ldb_result.
347 * @param result LDB result to convert
348 * @return Python object with converted result (a list object)
350 static PyObject *PyLdbResult_FromResult(struct ldb_result *result)
352 PyLdbResultObject *ret;
353 PyObject *list, *controls, *referals;
356 if (result == NULL) {
360 ret = (PyLdbResultObject *)PyLdbResult.tp_alloc(&PyLdbResult, 0);
366 list = PyList_New(result->count);
373 for (i = 0; i < result->count; i++) {
374 PyList_SetItem(list, i, PyLdbMessage_FromMessage(result->msgs[i]));
377 ret->mem_ctx = talloc_new(NULL);
378 if (ret->mem_ctx == NULL) {
387 if (result->controls) {
389 while (result->controls[i]) {
392 controls = PyList_New(i);
393 if (controls == NULL) {
398 for (i=0; result->controls[i]; i++) {
399 PyObject *ctrl = (PyObject*) PyLdbControl_FromControl(result->controls[i]);
406 PyList_SetItem(controls, i, ctrl);
410 * No controls so we keep an empty list
412 controls = PyList_New(0);
413 if (controls == NULL) {
420 ret->controls = controls;
424 while (result->refs && result->refs[i]) {
428 referals = PyList_New(i);
429 if (referals == NULL) {
435 for (i = 0;result->refs && result->refs[i]; i++) {
436 PyList_SetItem(referals, i, PyUnicode_FromString(result->refs[i]));
438 ret->referals = referals;
439 return (PyObject *)ret;
443 * Create a LDB Result from a Python object.
444 * If conversion fails, NULL will be returned and a Python exception set.
446 * Note: the result object only includes the messages at the moment; extended
447 * result, controls and referrals are ignored.
449 * @param mem_ctx Memory context in which to allocate the LDB Result
450 * @param obj Python object to convert
451 * @return a ldb_result, or NULL if the conversion failed
453 static struct ldb_result *PyLdbResult_AsResult(TALLOC_CTX *mem_ctx,
456 struct ldb_result *res;
462 res = talloc_zero(mem_ctx, struct ldb_result);
463 res->count = PyList_Size(obj);
464 res->msgs = talloc_array(res, struct ldb_message *, res->count);
465 for (i = 0; i < res->count; i++) {
466 PyObject *item = PyList_GetItem(obj, i);
467 res->msgs[i] = pyldb_Message_AsMessage(item);
472 static PyObject *py_ldb_dn_validate(PyLdbDnObject *self,
473 PyObject *Py_UNUSED(ignored))
475 return PyBool_FromLong(ldb_dn_validate(self->dn));
478 static PyObject *py_ldb_dn_is_valid(PyLdbDnObject *self,
479 PyObject *Py_UNUSED(ignored))
481 return PyBool_FromLong(ldb_dn_is_valid(self->dn));
484 static PyObject *py_ldb_dn_is_special(PyLdbDnObject *self,
485 PyObject *Py_UNUSED(ignored))
487 return PyBool_FromLong(ldb_dn_is_special(self->dn));
490 static PyObject *py_ldb_dn_is_null(PyLdbDnObject *self,
491 PyObject *Py_UNUSED(ignored))
493 return PyBool_FromLong(ldb_dn_is_null(self->dn));
496 static PyObject *py_ldb_dn_get_casefold(PyLdbDnObject *self,
497 PyObject *Py_UNUSED(ignored))
499 return PyUnicode_FromString(ldb_dn_get_casefold(self->dn));
502 static PyObject *py_ldb_dn_get_linearized(PyLdbDnObject *self)
504 return PyUnicode_FromString(ldb_dn_get_linearized(self->dn));
507 static PyObject *py_ldb_dn_canonical_str(PyLdbDnObject *self,
508 PyObject *Py_UNUSED(ignored))
510 return PyUnicode_FromString(ldb_dn_canonical_string(self->dn, self->dn));
513 static PyObject *py_ldb_dn_canonical_ex_str(PyLdbDnObject *self,
514 PyObject *Py_UNUSED(ignored))
516 return PyUnicode_FromString(ldb_dn_canonical_ex_string(self->dn, self->dn));
519 static PyObject *py_ldb_dn_extended_str(PyLdbDnObject *self, PyObject *args, PyObject *kwargs)
521 const char * const kwnames[] = { "mode", NULL };
523 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "|i",
524 discard_const_p(char *, kwnames),
527 return PyUnicode_FromString(ldb_dn_get_extended_linearized(self->dn, self->dn, mode));
530 static PyObject *py_ldb_dn_get_extended_component(PyLdbDnObject *self, PyObject *args)
533 const struct ldb_val *val;
535 if (!PyArg_ParseTuple(args, "s", &name))
537 val = ldb_dn_get_extended_component(self->dn, name);
542 return PyBytes_FromStringAndSize((const char *)val->data, val->length);
545 static PyObject *py_ldb_dn_set_extended_component(PyLdbDnObject *self, PyObject *args)
549 uint8_t *value = NULL;
552 if (!PyArg_ParseTuple(args, "sz#", &name, (char **)&value, &size))
556 err = ldb_dn_set_extended_component(self->dn, name, NULL);
559 val.data = (uint8_t *)value;
561 err = ldb_dn_set_extended_component(self->dn, name, &val);
564 if (err != LDB_SUCCESS) {
565 PyErr_SetString(PyExc_TypeError, "Failed to set extended component");
572 static PyObject *py_ldb_dn_repr(PyLdbDnObject *self)
574 PyObject *str = PyUnicode_FromString(ldb_dn_get_linearized(self->dn));
575 PyObject *repr, *result;
578 repr = PyObject_Repr(str);
583 result = PyUnicode_FromFormat("Dn(%s)", PyUnicode_AsUTF8(repr));
589 static PyObject *py_ldb_dn_check_special(PyLdbDnObject *self, PyObject *args)
593 if (!PyArg_ParseTuple(args, "s", &name))
596 return PyBool_FromLong(ldb_dn_check_special(self->dn, name));
599 static PyObject *py_ldb_dn_richcmp(PyObject *dn1, PyObject *dn2, int op)
602 if (!pyldb_Dn_Check(dn2)) {
603 Py_INCREF(Py_NotImplemented);
604 return Py_NotImplemented;
606 ret = ldb_dn_compare(pyldb_Dn_AS_DN(dn1), pyldb_Dn_AS_DN(dn2));
607 return richcmp(ret, op);
610 static PyObject *py_ldb_dn_get_parent(PyLdbDnObject *self,
611 PyObject *Py_UNUSED(ignored))
613 struct ldb_dn *dn = pyldb_Dn_AS_DN((PyObject *)self);
614 struct ldb_dn *parent;
615 PyLdbDnObject *py_ret;
616 TALLOC_CTX *mem_ctx = talloc_new(NULL);
618 parent = ldb_dn_get_parent(mem_ctx, dn);
619 if (parent == NULL) {
620 talloc_free(mem_ctx);
624 py_ret = (PyLdbDnObject *)PyLdbDn.tp_alloc(&PyLdbDn, 0);
625 if (py_ret == NULL) {
627 talloc_free(mem_ctx);
630 py_ret->mem_ctx = mem_ctx;
632 return (PyObject *)py_ret;
635 static PyObject *py_ldb_dn_add_child(PyLdbDnObject *self, PyObject *args)
638 struct ldb_dn *dn, *other;
639 if (!PyArg_ParseTuple(args, "O", &py_other))
642 dn = pyldb_Dn_AS_DN((PyObject *)self);
644 if (!pyldb_Object_AsDn(NULL, py_other, ldb_dn_get_ldb_context(dn), &other))
647 return PyBool_FromLong(ldb_dn_add_child(dn, other));
650 static PyObject *py_ldb_dn_add_base(PyLdbDnObject *self, PyObject *args)
653 struct ldb_dn *other, *dn;
654 if (!PyArg_ParseTuple(args, "O", &py_other))
657 dn = pyldb_Dn_AS_DN((PyObject *)self);
659 if (!pyldb_Object_AsDn(NULL, py_other, ldb_dn_get_ldb_context(dn), &other))
662 return PyBool_FromLong(ldb_dn_add_base(dn, other));
665 static PyObject *py_ldb_dn_remove_base_components(PyLdbDnObject *self, PyObject *args)
669 if (!PyArg_ParseTuple(args, "i", &i))
672 dn = pyldb_Dn_AS_DN((PyObject *)self);
674 return PyBool_FromLong(ldb_dn_remove_base_components(dn, i));
677 static PyObject *py_ldb_dn_is_child_of(PyLdbDnObject *self, PyObject *args)
680 struct ldb_dn *dn, *base;
681 if (!PyArg_ParseTuple(args, "O", &py_base))
684 dn = pyldb_Dn_AS_DN((PyObject *)self);
686 if (!pyldb_Object_AsDn(NULL, py_base, ldb_dn_get_ldb_context(dn), &base))
689 return PyBool_FromLong(ldb_dn_compare_base(base, dn) == 0);
692 static PyObject *py_ldb_dn_get_component_name(PyLdbDnObject *self, PyObject *args)
696 unsigned int num = 0;
698 if (!PyArg_ParseTuple(args, "I", &num))
701 dn = pyldb_Dn_AS_DN((PyObject *)self);
703 name = ldb_dn_get_component_name(dn, num);
708 return PyUnicode_FromString(name);
711 static PyObject *py_ldb_dn_get_component_value(PyLdbDnObject *self, PyObject *args)
714 const struct ldb_val *val;
715 unsigned int num = 0;
717 if (!PyArg_ParseTuple(args, "I", &num))
720 dn = pyldb_Dn_AS_DN((PyObject *)self);
722 val = ldb_dn_get_component_val(dn, num);
727 return PyStr_FromLdbValue(val);
730 static PyObject *py_ldb_dn_set_component(PyLdbDnObject *self, PyObject *args)
732 unsigned int num = 0;
733 char *name = NULL, *value = NULL;
734 struct ldb_val val = { NULL, };
738 if (!PyArg_ParseTuple(args, "Iss#", &num, &name, &value, &size))
741 val.data = (unsigned char*) value;
744 err = ldb_dn_set_component(self->dn, num, name, val);
745 if (err != LDB_SUCCESS) {
746 PyErr_SetString(PyExc_TypeError, "Failed to set component");
753 static PyObject *py_ldb_dn_get_rdn_name(PyLdbDnObject *self,
754 PyObject *Py_UNUSED(ignored))
759 dn = pyldb_Dn_AS_DN((PyObject *)self);
761 name = ldb_dn_get_rdn_name(dn);
766 return PyUnicode_FromString(name);
769 static PyObject *py_ldb_dn_get_rdn_value(PyLdbDnObject *self,
770 PyObject *Py_UNUSED(ignored))
773 const struct ldb_val *val;
775 dn = pyldb_Dn_AS_DN((PyObject *)self);
777 val = ldb_dn_get_rdn_val(dn);
782 return PyStr_FromLdbValue(val);
785 static PyMethodDef py_ldb_dn_methods[] = {
786 { "validate", (PyCFunction)py_ldb_dn_validate, METH_NOARGS,
787 "S.validate() -> bool\n"
788 "Validate DN is correct." },
789 { "is_valid", (PyCFunction)py_ldb_dn_is_valid, METH_NOARGS,
790 "S.is_valid() -> bool\n" },
791 { "is_special", (PyCFunction)py_ldb_dn_is_special, METH_NOARGS,
792 "S.is_special() -> bool\n"
793 "Check whether this is a special LDB DN." },
794 { "is_null", (PyCFunction)py_ldb_dn_is_null, METH_NOARGS,
795 "Check whether this is a null DN." },
796 { "get_casefold", (PyCFunction)py_ldb_dn_get_casefold, METH_NOARGS,
798 { "get_linearized", PY_DISCARD_FUNC_SIG(PyCFunction,
799 py_ldb_dn_get_linearized),
802 { "canonical_str", (PyCFunction)py_ldb_dn_canonical_str, METH_NOARGS,
803 "S.canonical_str() -> string\n"
804 "Canonical version of this DN (like a posix path)." },
805 { "is_child_of", (PyCFunction)py_ldb_dn_is_child_of, METH_VARARGS,
806 "S.is_child_of(basedn) -> int\nReturns True if this DN is a child of basedn\n"},
807 { "canonical_ex_str", (PyCFunction)py_ldb_dn_canonical_ex_str, METH_NOARGS,
808 "S.canonical_ex_str() -> string\n"
809 "Canonical version of this DN (like a posix path, with terminating newline)." },
810 { "extended_str", PY_DISCARD_FUNC_SIG(PyCFunction,
811 py_ldb_dn_extended_str),
812 METH_VARARGS | METH_KEYWORDS,
813 "S.extended_str(mode=1) -> string\n"
814 "Extended version of this DN" },
815 { "parent", (PyCFunction)py_ldb_dn_get_parent, METH_NOARGS,
817 "Get the parent for this DN." },
818 { "add_child", (PyCFunction)py_ldb_dn_add_child, METH_VARARGS,
819 "S.add_child(dn) -> None\n"
820 "Add a child DN to this DN." },
821 { "add_base", (PyCFunction)py_ldb_dn_add_base, METH_VARARGS,
822 "S.add_base(dn) -> None\n"
823 "Add a base DN to this DN." },
824 { "remove_base_components", (PyCFunction)py_ldb_dn_remove_base_components, METH_VARARGS,
825 "S.remove_base_components(int) -> bool\n"
826 "Remove a number of DN components from the base of this DN." },
827 { "check_special", (PyCFunction)py_ldb_dn_check_special, METH_VARARGS,
828 "S.check_special(name) -> bool\n\n"
829 "Check if name is a special DN name"},
830 { "get_extended_component", (PyCFunction)py_ldb_dn_get_extended_component, METH_VARARGS,
831 "S.get_extended_component(name) -> string\n\n"
832 "returns a DN extended component as a binary string"},
833 { "set_extended_component", (PyCFunction)py_ldb_dn_set_extended_component, METH_VARARGS,
834 "S.set_extended_component(name, value) -> None\n\n"
835 "set a DN extended component as a binary string"},
836 { "get_component_name", (PyCFunction)py_ldb_dn_get_component_name, METH_VARARGS,
837 "S.get_component_name(num) -> string\n"
838 "get the attribute name of the specified component" },
839 { "get_component_value", (PyCFunction)py_ldb_dn_get_component_value, METH_VARARGS,
840 "S.get_component_value(num) -> string\n"
841 "get the attribute value of the specified component as a binary string" },
842 { "set_component", (PyCFunction)py_ldb_dn_set_component, METH_VARARGS,
843 "S.get_component_value(num, name, value) -> None\n"
844 "set the attribute name and value of the specified component" },
845 { "get_rdn_name", (PyCFunction)py_ldb_dn_get_rdn_name, METH_NOARGS,
846 "S.get_rdn_name() -> string\n"
847 "get the RDN attribute name" },
848 { "get_rdn_value", (PyCFunction)py_ldb_dn_get_rdn_value, METH_NOARGS,
849 "S.get_rdn_value() -> string\n"
850 "get the RDN attribute value as a binary string" },
854 static Py_ssize_t py_ldb_dn_len(PyLdbDnObject *self)
856 return ldb_dn_get_comp_num(pyldb_Dn_AS_DN((PyObject *)self));
860 copy a DN as a python object
862 static PyObject *py_ldb_dn_copy(struct ldb_dn *dn)
864 PyLdbDnObject *py_ret;
866 py_ret = (PyLdbDnObject *)PyLdbDn.tp_alloc(&PyLdbDn, 0);
867 if (py_ret == NULL) {
871 py_ret->mem_ctx = talloc_new(NULL);
872 py_ret->dn = ldb_dn_copy(py_ret->mem_ctx, dn);
873 return (PyObject *)py_ret;
876 static PyObject *py_ldb_dn_concat(PyLdbDnObject *self, PyObject *py_other)
878 struct ldb_dn *dn = pyldb_Dn_AS_DN((PyObject *)self),
880 PyLdbDnObject *py_ret;
882 if (!pyldb_Object_AsDn(NULL, py_other, NULL, &other))
885 py_ret = (PyLdbDnObject *)PyLdbDn.tp_alloc(&PyLdbDn, 0);
886 if (py_ret == NULL) {
890 py_ret->mem_ctx = talloc_new(NULL);
891 py_ret->dn = ldb_dn_copy(py_ret->mem_ctx, dn);
892 ldb_dn_add_base(py_ret->dn, other);
893 return (PyObject *)py_ret;
896 static PySequenceMethods py_ldb_dn_seq = {
897 .sq_length = (lenfunc)py_ldb_dn_len,
898 .sq_concat = (binaryfunc)py_ldb_dn_concat,
901 static PyObject *py_ldb_dn_new(PyTypeObject *type, PyObject *args, PyObject *kwargs)
903 struct ldb_dn *ret = NULL;
905 PyObject *py_ldb = NULL;
906 struct ldb_context *ldb_ctx = NULL;
907 TALLOC_CTX *mem_ctx = NULL;
908 PyLdbDnObject *py_ret = NULL;
909 const char * const kwnames[] = { "ldb", "dn", NULL };
911 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "O"PYARG_STR_UNI,
912 discard_const_p(char *, kwnames),
913 &py_ldb, "utf8", &str))
916 if (!PyLdb_Check(py_ldb)) {
917 PyErr_SetString(PyExc_TypeError, "Expected Ldb");
920 ldb_ctx = pyldb_Ldb_AS_LDBCONTEXT(py_ldb);
922 mem_ctx = talloc_new(NULL);
923 if (mem_ctx == NULL) {
928 ret = ldb_dn_new(mem_ctx, ldb_ctx, str);
929 if (!ldb_dn_validate(ret)) {
930 talloc_free(mem_ctx);
931 PyErr_SetString(PyExc_ValueError, "unable to parse dn string");
935 py_ret = (PyLdbDnObject *)type->tp_alloc(type, 0);
936 if (py_ret == NULL) {
937 talloc_free(mem_ctx);
941 py_ret->mem_ctx = mem_ctx;
945 PyMem_Free(discard_const_p(char, str));
947 return (PyObject *)py_ret;
950 static void py_ldb_dn_dealloc(PyLdbDnObject *self)
952 talloc_free(self->mem_ctx);
956 static PyTypeObject PyLdbDn = {
958 .tp_methods = py_ldb_dn_methods,
959 .tp_str = (reprfunc)py_ldb_dn_get_linearized,
960 .tp_repr = (reprfunc)py_ldb_dn_repr,
961 .tp_richcompare = (richcmpfunc)py_ldb_dn_richcmp,
962 .tp_as_sequence = &py_ldb_dn_seq,
963 .tp_doc = "A LDB distinguished name.",
964 .tp_new = py_ldb_dn_new,
965 .tp_dealloc = (destructor)py_ldb_dn_dealloc,
966 .tp_basicsize = sizeof(PyLdbDnObject),
967 .tp_flags = Py_TPFLAGS_DEFAULT,
971 static void py_ldb_debug(void *context, enum ldb_debug_level level, const char *fmt, va_list ap) PRINTF_ATTRIBUTE(3, 0);
972 static void py_ldb_debug(void *context, enum ldb_debug_level level, const char *fmt, va_list ap)
974 PyObject *fn = (PyObject *)context;
975 PyObject_CallFunction(fn, discard_const_p(char, "(i,O)"), level, PyUnicode_FromFormatV(fmt, ap));
978 static PyObject *py_ldb_debug_func;
980 static PyObject *py_ldb_set_debug(PyObject *self, PyObject *args)
983 struct ldb_context *ldb_ctx;
985 if (!PyArg_ParseTuple(args, "O", &cb))
988 if (py_ldb_debug_func != NULL) {
989 Py_DECREF(py_ldb_debug_func);
993 /* FIXME: DECREF cb when exiting program */
994 py_ldb_debug_func = cb;
995 ldb_ctx = pyldb_Ldb_AS_LDBCONTEXT(self);
996 PyErr_LDB_ERROR_IS_ERR_RAISE(PyExc_LdbError,
997 ldb_set_debug(ldb_ctx, py_ldb_debug, cb),
1003 static PyObject *py_ldb_set_create_perms(PyTypeObject *self, PyObject *args)
1006 if (!PyArg_ParseTuple(args, "I", &perms))
1009 ldb_set_create_perms(pyldb_Ldb_AS_LDBCONTEXT(self), perms);
1014 static PyObject *py_ldb_set_modules_dir(PyTypeObject *self, PyObject *args)
1017 if (!PyArg_ParseTuple(args, "s", &modules_dir))
1020 ldb_set_modules_dir(pyldb_Ldb_AS_LDBCONTEXT(self), modules_dir);
1025 static PyObject *py_ldb_transaction_start(PyLdbObject *self,
1026 PyObject *Py_UNUSED(ignored))
1028 struct ldb_context *ldb_ctx = pyldb_Ldb_AS_LDBCONTEXT(self);
1030 ldb_err = ldb_transaction_start(ldb_ctx);
1031 PyErr_LDB_ERROR_IS_ERR_RAISE(PyExc_LdbError, ldb_err, ldb_ctx);
1035 static PyObject *py_ldb_transaction_commit(PyLdbObject *self,
1036 PyObject *Py_UNUSED(ignored))
1038 struct ldb_context *ldb_ctx = pyldb_Ldb_AS_LDBCONTEXT(self);
1040 ldb_err = ldb_transaction_commit(ldb_ctx);
1041 PyErr_LDB_ERROR_IS_ERR_RAISE(PyExc_LdbError, ldb_err, ldb_ctx);
1045 static PyObject *py_ldb_transaction_prepare_commit(PyLdbObject *self,
1046 PyObject *Py_UNUSED(ignored))
1048 struct ldb_context *ldb_ctx = pyldb_Ldb_AS_LDBCONTEXT(self);
1050 ldb_err = ldb_transaction_prepare_commit(ldb_ctx);
1051 PyErr_LDB_ERROR_IS_ERR_RAISE(PyExc_LdbError, ldb_err, ldb_ctx);
1055 static PyObject *py_ldb_transaction_cancel(PyLdbObject *self,
1056 PyObject *Py_UNUSED(ignored))
1058 struct ldb_context *ldb_ctx = pyldb_Ldb_AS_LDBCONTEXT(self);
1060 ldb_err = ldb_transaction_cancel(ldb_ctx);
1061 PyErr_LDB_ERROR_IS_ERR_RAISE(PyExc_LdbError, ldb_err, ldb_ctx);
1065 static PyObject *py_ldb_setup_wellknown_attributes(PyLdbObject *self,
1066 PyObject *Py_UNUSED(ignored))
1068 struct ldb_context *ldb_ctx = pyldb_Ldb_AS_LDBCONTEXT(self);
1070 ldb_err = ldb_setup_wellknown_attributes(ldb_ctx);
1071 PyErr_LDB_ERROR_IS_ERR_RAISE(PyExc_LdbError, ldb_err, ldb_ctx);
1075 static PyObject *py_ldb_repr(PyLdbObject *self)
1077 return PyUnicode_FromString("<ldb connection>");
1080 static PyObject *py_ldb_get_root_basedn(PyLdbObject *self,
1081 PyObject *Py_UNUSED(ignored))
1083 struct ldb_dn *dn = ldb_get_root_basedn(pyldb_Ldb_AS_LDBCONTEXT(self));
1086 return py_ldb_dn_copy(dn);
1090 static PyObject *py_ldb_get_schema_basedn(PyLdbObject *self,
1091 PyObject *Py_UNUSED(ignored))
1093 struct ldb_dn *dn = ldb_get_schema_basedn(pyldb_Ldb_AS_LDBCONTEXT(self));
1096 return py_ldb_dn_copy(dn);
1099 static PyObject *py_ldb_get_config_basedn(PyLdbObject *self,
1100 PyObject *Py_UNUSED(ignored))
1102 struct ldb_dn *dn = ldb_get_config_basedn(pyldb_Ldb_AS_LDBCONTEXT(self));
1105 return py_ldb_dn_copy(dn);
1108 static PyObject *py_ldb_get_default_basedn(PyLdbObject *self,
1109 PyObject *Py_UNUSED(ignored))
1111 struct ldb_dn *dn = ldb_get_default_basedn(pyldb_Ldb_AS_LDBCONTEXT(self));
1114 return py_ldb_dn_copy(dn);
1117 static const char **PyList_AsStrList(TALLOC_CTX *mem_ctx, PyObject *list,
1118 const char *paramname)
1122 if (!PyList_Check(list)) {
1123 PyErr_Format(PyExc_TypeError, "%s is not a list", paramname);
1126 ret = talloc_array(NULL, const char *, PyList_Size(list)+1);
1132 for (i = 0; i < PyList_Size(list); i++) {
1133 const char *str = NULL;
1135 PyObject *item = PyList_GetItem(list, i);
1136 if (!PyUnicode_Check(item)) {
1137 PyErr_Format(PyExc_TypeError, "%s should be strings", paramname);
1141 str = PyUnicode_AsUTF8AndSize(item, &size);
1146 ret[i] = talloc_strndup(ret, str, size);
1152 static int py_ldb_init(PyLdbObject *self, PyObject *args, PyObject *kwargs)
1154 const char * const kwnames[] = { "url", "flags", "options", NULL };
1156 PyObject *py_options = Py_None;
1157 const char **options;
1158 unsigned int flags = 0;
1160 struct ldb_context *ldb;
1162 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "|zIO:Ldb.__init__",
1163 discard_const_p(char *, kwnames),
1164 &url, &flags, &py_options))
1167 ldb = pyldb_Ldb_AS_LDBCONTEXT(self);
1169 if (py_options == Py_None) {
1172 options = PyList_AsStrList(ldb, py_options, "options");
1173 if (options == NULL)
1178 ret = ldb_connect(ldb, url, flags, options);
1179 if (ret != LDB_SUCCESS) {
1180 PyErr_SetLdbError(PyExc_LdbError, ret, ldb);
1184 ldb_set_flags(ldb, flags);
1187 talloc_free(options);
1191 static PyObject *py_ldb_new(PyTypeObject *type, PyObject *args, PyObject *kwargs)
1194 struct ldb_context *ldb;
1195 ret = (PyLdbObject *)type->tp_alloc(type, 0);
1200 ret->mem_ctx = talloc_new(NULL);
1201 ldb = ldb_init(ret->mem_ctx, NULL);
1209 return (PyObject *)ret;
1212 static PyObject *py_ldb_connect(PyLdbObject *self, PyObject *args, PyObject *kwargs)
1215 unsigned int flags = 0;
1216 PyObject *py_options = Py_None;
1218 const char **options;
1219 const char * const kwnames[] = { "url", "flags", "options", NULL };
1220 struct ldb_context *ldb_ctx;
1222 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "z|IO",
1223 discard_const_p(char *, kwnames),
1224 &url, &flags, &py_options))
1227 if (py_options == Py_None) {
1230 options = PyList_AsStrList(NULL, py_options, "options");
1231 if (options == NULL)
1235 ldb_ctx = pyldb_Ldb_AS_LDBCONTEXT(self);
1236 ret = ldb_connect(ldb_ctx, url, flags, options);
1237 talloc_free(options);
1239 PyErr_LDB_ERROR_IS_ERR_RAISE(PyExc_LdbError, ret, ldb_ctx);
1244 static PyObject *py_ldb_modify(PyLdbObject *self, PyObject *args, PyObject *kwargs)
1247 PyObject *py_controls = Py_None;
1248 struct ldb_context *ldb_ctx;
1249 struct ldb_request *req;
1250 struct ldb_control **parsed_controls;
1251 struct ldb_message *msg;
1253 TALLOC_CTX *mem_ctx;
1255 const char * const kwnames[] = { "message", "controls", "validate", NULL };
1257 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "O|Ob",
1258 discard_const_p(char *, kwnames),
1259 &py_msg, &py_controls, &validate))
1262 mem_ctx = talloc_new(NULL);
1263 if (mem_ctx == NULL) {
1267 ldb_ctx = pyldb_Ldb_AS_LDBCONTEXT(self);
1269 if (py_controls == Py_None) {
1270 parsed_controls = NULL;
1272 const char **controls = PyList_AsStrList(mem_ctx, py_controls, "controls");
1273 if (controls == NULL) {
1274 talloc_free(mem_ctx);
1277 parsed_controls = ldb_parse_control_strings(ldb_ctx, mem_ctx, controls);
1278 talloc_free(controls);
1281 if (!PyLdbMessage_Check(py_msg)) {
1282 PyErr_SetString(PyExc_TypeError, "Expected Ldb Message");
1283 talloc_free(mem_ctx);
1286 msg = pyldb_Message_AsMessage(py_msg);
1289 ret = ldb_msg_sanity_check(ldb_ctx, msg);
1290 if (ret != LDB_SUCCESS) {
1291 PyErr_SetLdbError(PyExc_LdbError, ret, ldb_ctx);
1292 talloc_free(mem_ctx);
1297 ret = ldb_build_mod_req(&req, ldb_ctx, mem_ctx, msg, parsed_controls,
1298 NULL, ldb_op_default_callback, NULL);
1299 if (ret != LDB_SUCCESS) {
1300 PyErr_SetString(PyExc_TypeError, "failed to build request");
1301 talloc_free(mem_ctx);
1305 /* do request and autostart a transaction */
1306 /* Then let's LDB handle the message error in case of pb as they are meaningful */
1308 ret = ldb_transaction_start(ldb_ctx);
1309 if (ret != LDB_SUCCESS) {
1310 talloc_free(mem_ctx);
1311 PyErr_SetLdbError(PyExc_LdbError, ret, ldb_ctx);
1315 ret = ldb_request(ldb_ctx, req);
1316 if (ret == LDB_SUCCESS) {
1317 ret = ldb_wait(req->handle, LDB_WAIT_ALL);
1320 if (ret == LDB_SUCCESS) {
1321 ret = ldb_transaction_commit(ldb_ctx);
1323 ldb_transaction_cancel(ldb_ctx);
1326 talloc_free(mem_ctx);
1327 PyErr_LDB_ERROR_IS_ERR_RAISE(PyExc_LdbError, ret, ldb_ctx);
1334 * Obtain a ldb message from a Python Dictionary object.
1336 * @param mem_ctx Memory context
1337 * @param py_obj Python Dictionary object
1338 * @param ldb_ctx LDB context
1339 * @param mod_flags Flags to be set on every message element
1340 * @return ldb_message on success or NULL on failure
1342 static struct ldb_message *PyDict_AsMessage(TALLOC_CTX *mem_ctx,
1344 struct ldb_context *ldb_ctx,
1345 unsigned int mod_flags)
1347 struct ldb_message *msg;
1348 unsigned int msg_pos = 0;
1349 Py_ssize_t dict_pos = 0;
1350 PyObject *key, *value;
1351 struct ldb_message_element *msg_el;
1352 PyObject *dn_value = PyDict_GetItemString(py_obj, "dn");
1354 msg = ldb_msg_new(mem_ctx);
1359 msg->elements = talloc_zero_array(msg, struct ldb_message_element, PyDict_Size(py_obj));
1362 if (!pyldb_Object_AsDn(msg, dn_value, ldb_ctx, &msg->dn)) {
1363 PyErr_SetString(PyExc_TypeError, "unable to import dn object");
1366 if (msg->dn == NULL) {
1367 PyErr_SetString(PyExc_TypeError, "dn set but not found");
1371 PyErr_SetString(PyExc_TypeError, "no dn set");
1375 while (PyDict_Next(py_obj, &dict_pos, &key, &value)) {
1376 const char *key_str = PyUnicode_AsUTF8(key);
1377 if (ldb_attr_cmp(key_str, "dn") != 0) {
1378 msg_el = PyObject_AsMessageElement(msg->elements, value,
1379 mod_flags, key_str);
1380 if (msg_el == NULL) {
1381 PyErr_Format(PyExc_TypeError, "unable to import element '%s'", key_str);
1384 memcpy(&msg->elements[msg_pos], msg_el, sizeof(*msg_el));
1389 msg->num_elements = msg_pos;
1394 static PyObject *py_ldb_add(PyLdbObject *self, PyObject *args, PyObject *kwargs)
1398 struct ldb_context *ldb_ctx;
1399 struct ldb_request *req;
1400 struct ldb_message *msg = NULL;
1401 PyObject *py_controls = Py_None;
1402 TALLOC_CTX *mem_ctx;
1403 struct ldb_control **parsed_controls;
1404 const char * const kwnames[] = { "message", "controls", NULL };
1406 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "O|O",
1407 discard_const_p(char *, kwnames),
1408 &py_obj, &py_controls))
1411 mem_ctx = talloc_new(NULL);
1412 if (mem_ctx == NULL) {
1416 ldb_ctx = pyldb_Ldb_AS_LDBCONTEXT(self);
1418 if (py_controls == Py_None) {
1419 parsed_controls = NULL;
1421 const char **controls = PyList_AsStrList(mem_ctx, py_controls, "controls");
1422 if (controls == NULL) {
1423 talloc_free(mem_ctx);
1426 parsed_controls = ldb_parse_control_strings(ldb_ctx, mem_ctx, controls);
1427 talloc_free(controls);
1430 if (PyLdbMessage_Check(py_obj)) {
1431 msg = pyldb_Message_AsMessage(py_obj);
1432 } else if (PyDict_Check(py_obj)) {
1433 msg = PyDict_AsMessage(mem_ctx, py_obj, ldb_ctx, LDB_FLAG_MOD_ADD);
1435 PyErr_SetString(PyExc_TypeError,
1436 "Dictionary or LdbMessage object expected!");
1440 /* we should have a PyErr already set */
1441 talloc_free(mem_ctx);
1445 ret = ldb_msg_sanity_check(ldb_ctx, msg);
1446 if (ret != LDB_SUCCESS) {
1447 PyErr_SetLdbError(PyExc_LdbError, ret, ldb_ctx);
1448 talloc_free(mem_ctx);
1452 ret = ldb_build_add_req(&req, ldb_ctx, mem_ctx, msg, parsed_controls,
1453 NULL, ldb_op_default_callback, NULL);
1454 if (ret != LDB_SUCCESS) {
1455 PyErr_SetString(PyExc_TypeError, "failed to build request");
1456 talloc_free(mem_ctx);
1460 /* do request and autostart a transaction */
1461 /* Then let's LDB handle the message error in case of pb as they are meaningful */
1463 ret = ldb_transaction_start(ldb_ctx);
1464 if (ret != LDB_SUCCESS) {
1465 talloc_free(mem_ctx);
1466 PyErr_SetLdbError(PyExc_LdbError, ret, ldb_ctx);
1470 ret = ldb_request(ldb_ctx, req);
1471 if (ret == LDB_SUCCESS) {
1472 ret = ldb_wait(req->handle, LDB_WAIT_ALL);
1475 if (ret == LDB_SUCCESS) {
1476 ret = ldb_transaction_commit(ldb_ctx);
1478 ldb_transaction_cancel(ldb_ctx);
1481 talloc_free(mem_ctx);
1482 PyErr_LDB_ERROR_IS_ERR_RAISE(PyExc_LdbError, ret, ldb_ctx);
1487 static PyObject *py_ldb_delete(PyLdbObject *self, PyObject *args, PyObject *kwargs)
1492 struct ldb_context *ldb_ctx;
1493 struct ldb_request *req;
1494 PyObject *py_controls = Py_None;
1495 TALLOC_CTX *mem_ctx;
1496 struct ldb_control **parsed_controls;
1497 const char * const kwnames[] = { "dn", "controls", NULL };
1499 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "O|O",
1500 discard_const_p(char *, kwnames),
1501 &py_dn, &py_controls))
1504 mem_ctx = talloc_new(NULL);
1505 if (mem_ctx == NULL) {
1509 ldb_ctx = pyldb_Ldb_AS_LDBCONTEXT(self);
1511 if (py_controls == Py_None) {
1512 parsed_controls = NULL;
1514 const char **controls = PyList_AsStrList(mem_ctx, py_controls, "controls");
1515 if (controls == NULL) {
1516 talloc_free(mem_ctx);
1519 parsed_controls = ldb_parse_control_strings(ldb_ctx, mem_ctx, controls);
1520 talloc_free(controls);
1523 if (!pyldb_Object_AsDn(mem_ctx, py_dn, ldb_ctx, &dn)) {
1524 talloc_free(mem_ctx);
1528 ret = ldb_build_del_req(&req, ldb_ctx, mem_ctx, dn, parsed_controls,
1529 NULL, ldb_op_default_callback, NULL);
1530 if (ret != LDB_SUCCESS) {
1531 PyErr_SetString(PyExc_TypeError, "failed to build request");
1532 talloc_free(mem_ctx);
1536 /* do request and autostart a transaction */
1537 /* Then let's LDB handle the message error in case of pb as they are meaningful */
1539 ret = ldb_transaction_start(ldb_ctx);
1540 if (ret != LDB_SUCCESS) {
1541 talloc_free(mem_ctx);
1542 PyErr_SetLdbError(PyExc_LdbError, ret, ldb_ctx);
1546 ret = ldb_request(ldb_ctx, req);
1547 if (ret == LDB_SUCCESS) {
1548 ret = ldb_wait(req->handle, LDB_WAIT_ALL);
1551 if (ret == LDB_SUCCESS) {
1552 ret = ldb_transaction_commit(ldb_ctx);
1554 ldb_transaction_cancel(ldb_ctx);
1557 talloc_free(mem_ctx);
1558 PyErr_LDB_ERROR_IS_ERR_RAISE(PyExc_LdbError, ret, ldb_ctx);
1563 static PyObject *py_ldb_rename(PyLdbObject *self, PyObject *args, PyObject *kwargs)
1565 PyObject *py_dn1, *py_dn2;
1566 struct ldb_dn *dn1, *dn2;
1568 TALLOC_CTX *mem_ctx;
1569 PyObject *py_controls = Py_None;
1570 struct ldb_control **parsed_controls;
1571 struct ldb_context *ldb_ctx;
1572 struct ldb_request *req;
1573 const char * const kwnames[] = { "dn1", "dn2", "controls", NULL };
1575 ldb_ctx = pyldb_Ldb_AS_LDBCONTEXT(self);
1577 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "OO|O",
1578 discard_const_p(char *, kwnames),
1579 &py_dn1, &py_dn2, &py_controls))
1583 mem_ctx = talloc_new(NULL);
1584 if (mem_ctx == NULL) {
1589 if (py_controls == Py_None) {
1590 parsed_controls = NULL;
1592 const char **controls = PyList_AsStrList(mem_ctx, py_controls, "controls");
1593 if (controls == NULL) {
1594 talloc_free(mem_ctx);
1597 parsed_controls = ldb_parse_control_strings(ldb_ctx, mem_ctx, controls);
1598 talloc_free(controls);
1602 if (!pyldb_Object_AsDn(mem_ctx, py_dn1, ldb_ctx, &dn1)) {
1603 talloc_free(mem_ctx);
1607 if (!pyldb_Object_AsDn(mem_ctx, py_dn2, ldb_ctx, &dn2)) {
1608 talloc_free(mem_ctx);
1612 ret = ldb_build_rename_req(&req, ldb_ctx, mem_ctx, dn1, dn2, parsed_controls,
1613 NULL, ldb_op_default_callback, NULL);
1614 if (ret != LDB_SUCCESS) {
1615 PyErr_SetString(PyExc_TypeError, "failed to build request");
1616 talloc_free(mem_ctx);
1620 /* do request and autostart a transaction */
1621 /* Then let's LDB handle the message error in case of pb as they are meaningful */
1623 ret = ldb_transaction_start(ldb_ctx);
1624 if (ret != LDB_SUCCESS) {
1625 talloc_free(mem_ctx);
1626 PyErr_SetLdbError(PyExc_LdbError, ret, ldb_ctx);
1630 ret = ldb_request(ldb_ctx, req);
1631 if (ret == LDB_SUCCESS) {
1632 ret = ldb_wait(req->handle, LDB_WAIT_ALL);
1635 if (ret == LDB_SUCCESS) {
1636 ret = ldb_transaction_commit(ldb_ctx);
1638 ldb_transaction_cancel(ldb_ctx);
1641 talloc_free(mem_ctx);
1642 PyErr_LDB_ERROR_IS_ERR_RAISE(PyExc_LdbError, ret, ldb_ctx);
1647 static PyObject *py_ldb_schema_attribute_remove(PyLdbObject *self, PyObject *args)
1650 if (!PyArg_ParseTuple(args, "s", &name))
1653 ldb_schema_attribute_remove(pyldb_Ldb_AS_LDBCONTEXT(self), name);
1658 static PyObject *py_ldb_schema_attribute_add(PyLdbObject *self, PyObject *args)
1660 char *attribute, *syntax;
1663 struct ldb_context *ldb_ctx;
1665 if (!PyArg_ParseTuple(args, "sIs", &attribute, &flags, &syntax))
1668 ldb_ctx = pyldb_Ldb_AS_LDBCONTEXT(self);
1669 ret = ldb_schema_attribute_add(ldb_ctx, attribute, flags, syntax);
1671 PyErr_LDB_ERROR_IS_ERR_RAISE(PyExc_LdbError, ret, ldb_ctx);
1676 static PyObject *ldb_ldif_to_pyobject(struct ldb_ldif *ldif)
1681 /* We don't want this attached to the 'ldb' any more */
1682 PyObject *obj = PyLdbMessage_FromMessage(ldif->msg);
1684 Py_BuildValue(discard_const_p(char, "(iO)"),
1693 static PyObject *py_ldb_write_ldif(PyLdbObject *self, PyObject *args)
1697 struct ldb_ldif ldif;
1700 TALLOC_CTX *mem_ctx;
1702 if (!PyArg_ParseTuple(args, "Oi", &py_msg, &changetype))
1705 if (!PyLdbMessage_Check(py_msg)) {
1706 PyErr_SetString(PyExc_TypeError, "Expected Ldb Message for msg");
1710 ldif.msg = pyldb_Message_AsMessage(py_msg);
1711 ldif.changetype = changetype;
1713 mem_ctx = talloc_new(NULL);
1715 string = ldb_ldif_write_string(pyldb_Ldb_AS_LDBCONTEXT(self), mem_ctx, &ldif);
1717 PyErr_SetString(PyExc_KeyError, "Failed to generate LDIF");
1721 ret = PyUnicode_FromString(string);
1723 talloc_free(mem_ctx);
1728 static PyObject *py_ldb_parse_ldif(PyLdbObject *self, PyObject *args)
1730 PyObject *list, *ret;
1731 struct ldb_ldif *ldif;
1733 struct ldb_dn *last_dn = NULL;
1735 TALLOC_CTX *mem_ctx;
1737 if (!PyArg_ParseTuple(args, "s", &s))
1740 mem_ctx = talloc_new(NULL);
1745 list = PyList_New(0);
1746 while (s && *s != '\0') {
1747 ldif = ldb_ldif_read_string(self->ldb_ctx, &s);
1748 talloc_steal(mem_ctx, ldif);
1751 PyObject *py_ldif = ldb_ldif_to_pyobject(ldif);
1752 if (py_ldif == NULL) {
1754 PyErr_BadArgument();
1755 talloc_free(mem_ctx);
1758 res = PyList_Append(list, py_ldif);
1762 talloc_free(mem_ctx);
1765 last_dn = ldif->msg->dn;
1767 const char *last_dn_str = NULL;
1768 const char *err_string = NULL;
1769 if (last_dn == NULL) {
1770 PyErr_SetString(PyExc_ValueError,
1771 "unable to parse LDIF "
1772 "string at first chunk");
1774 talloc_free(mem_ctx);
1779 = ldb_dn_get_linearized(last_dn);
1782 = talloc_asprintf(mem_ctx,
1783 "unable to parse ldif "
1787 PyErr_SetString(PyExc_ValueError,
1789 talloc_free(mem_ctx);
1794 talloc_free(mem_ctx); /* The pyobject already has a reference to the things it needs */
1795 ret = PyObject_GetIter(list);
1800 static PyObject *py_ldb_msg_diff(PyLdbObject *self, PyObject *args)
1803 PyObject *py_msg_old;
1804 PyObject *py_msg_new;
1805 struct ldb_message *diff;
1806 struct ldb_context *ldb;
1809 if (!PyArg_ParseTuple(args, "OO", &py_msg_old, &py_msg_new))
1812 if (!PyLdbMessage_Check(py_msg_old)) {
1813 PyErr_SetString(PyExc_TypeError, "Expected Ldb Message for old message");
1817 if (!PyLdbMessage_Check(py_msg_new)) {
1818 PyErr_SetString(PyExc_TypeError, "Expected Ldb Message for new message");
1822 ldb = pyldb_Ldb_AS_LDBCONTEXT(self);
1823 ldb_ret = ldb_msg_difference(ldb, ldb,
1824 pyldb_Message_AsMessage(py_msg_old),
1825 pyldb_Message_AsMessage(py_msg_new),
1827 if (ldb_ret != LDB_SUCCESS) {
1828 PyErr_SetString(PyExc_RuntimeError, "Failed to generate the Ldb Message diff");
1832 py_ret = PyLdbMessage_FromMessage(diff);
1834 talloc_unlink(ldb, diff);
1839 static PyObject *py_ldb_schema_format_value(PyLdbObject *self, PyObject *args)
1841 const struct ldb_schema_attribute *a;
1842 struct ldb_val old_val;
1843 struct ldb_val new_val;
1844 TALLOC_CTX *mem_ctx;
1851 if (!PyArg_ParseTuple(args, "sO", &element_name, &val))
1854 result = PyBytes_AsStringAndSize(val, (char **)&old_val.data, &size);
1855 old_val.length = size;
1858 PyErr_SetString(PyExc_RuntimeError, "Failed to convert passed value to String");
1862 a = ldb_schema_attribute_by_name(pyldb_Ldb_AS_LDBCONTEXT(self), element_name);
1868 mem_ctx = talloc_new(NULL);
1869 if (mem_ctx == NULL) {
1874 if (a->syntax->ldif_write_fn(pyldb_Ldb_AS_LDBCONTEXT(self), mem_ctx, &old_val, &new_val) != 0) {
1875 talloc_free(mem_ctx);
1879 ret = PyBytes_FromStringAndSize((const char *)new_val.data, new_val.length);
1881 talloc_free(mem_ctx);
1886 static PyObject *py_ldb_search(PyLdbObject *self, PyObject *args, PyObject *kwargs)
1888 PyObject *py_base = Py_None;
1889 int scope = LDB_SCOPE_DEFAULT;
1891 PyObject *py_attrs = Py_None;
1892 PyObject *py_controls = Py_None;
1893 const char * const kwnames[] = { "base", "scope", "expression", "attrs", "controls", NULL };
1895 struct ldb_result *res;
1896 struct ldb_request *req;
1898 struct ldb_context *ldb_ctx;
1899 struct ldb_control **parsed_controls;
1900 struct ldb_dn *base;
1902 TALLOC_CTX *mem_ctx;
1904 /* type "int" rather than "enum" for "scope" is intentional */
1905 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "|OizOO",
1906 discard_const_p(char *, kwnames),
1907 &py_base, &scope, &expr, &py_attrs, &py_controls))
1911 mem_ctx = talloc_new(NULL);
1912 if (mem_ctx == NULL) {
1916 ldb_ctx = pyldb_Ldb_AS_LDBCONTEXT(self);
1918 if (py_attrs == Py_None) {
1921 attrs = PyList_AsStrList(mem_ctx, py_attrs, "attrs");
1922 if (attrs == NULL) {
1923 talloc_free(mem_ctx);
1928 if (py_base == Py_None) {
1929 base = ldb_get_default_basedn(ldb_ctx);
1931 if (!pyldb_Object_AsDn(mem_ctx, py_base, ldb_ctx, &base)) {
1932 talloc_free(mem_ctx);
1937 if (py_controls == Py_None) {
1938 parsed_controls = NULL;
1940 const char **controls = PyList_AsStrList(mem_ctx, py_controls, "controls");
1941 if (controls == NULL) {
1942 talloc_free(mem_ctx);
1945 parsed_controls = ldb_parse_control_strings(ldb_ctx, mem_ctx, controls);
1946 talloc_free(controls);
1949 res = talloc_zero(mem_ctx, struct ldb_result);
1952 talloc_free(mem_ctx);
1956 ret = ldb_build_search_req(&req, ldb_ctx, mem_ctx,
1963 ldb_search_default_callback,
1966 if (ret != LDB_SUCCESS) {
1967 talloc_free(mem_ctx);
1968 PyErr_SetLdbError(PyExc_LdbError, ret, ldb_ctx);
1972 talloc_steal(req, attrs);
1974 ret = ldb_request(ldb_ctx, req);
1976 if (ret == LDB_SUCCESS) {
1977 ret = ldb_wait(req->handle, LDB_WAIT_ALL);
1980 if (ret != LDB_SUCCESS) {
1981 talloc_free(mem_ctx);
1982 PyErr_SetLdbError(PyExc_LdbError, ret, ldb_ctx);
1986 py_ret = PyLdbResult_FromResult(res);
1988 talloc_free(mem_ctx);
1993 static int py_ldb_search_iterator_reply_destructor(struct py_ldb_search_iterator_reply *reply)
1995 if (reply->py_iter != NULL) {
1996 DLIST_REMOVE(reply->py_iter->state.next, reply);
1997 if (reply->py_iter->state.result == reply) {
1998 reply->py_iter->state.result = NULL;
2000 reply->py_iter = NULL;
2003 if (reply->obj != NULL) {
2004 Py_DECREF(reply->obj);
2011 static int py_ldb_search_iterator_callback(struct ldb_request *req,
2012 struct ldb_reply *ares)
2014 PyLdbSearchIteratorObject *py_iter = (PyLdbSearchIteratorObject *)req->context;
2015 struct ldb_result result = { .msgs = NULL };
2016 struct py_ldb_search_iterator_reply *reply = NULL;
2019 return ldb_request_done(req, LDB_ERR_OPERATIONS_ERROR);
2022 if (ares->error != LDB_SUCCESS) {
2023 int ret = ares->error;
2025 return ldb_request_done(req, ret);
2028 reply = talloc_zero(py_iter->mem_ctx,
2029 struct py_ldb_search_iterator_reply);
2030 if (reply == NULL) {
2032 return ldb_request_done(req, LDB_ERR_OPERATIONS_ERROR);
2034 reply->py_iter = py_iter;
2035 talloc_set_destructor(reply, py_ldb_search_iterator_reply_destructor);
2037 switch (ares->type) {
2038 case LDB_REPLY_ENTRY:
2039 reply->obj = PyLdbMessage_FromMessage(ares->message);
2040 if (reply->obj == NULL) {
2042 return ldb_request_done(req, LDB_ERR_OPERATIONS_ERROR);
2044 DLIST_ADD_END(py_iter->state.next, reply);
2048 case LDB_REPLY_REFERRAL:
2049 reply->obj = PyUnicode_FromString(ares->referral);
2050 if (reply->obj == NULL) {
2052 return ldb_request_done(req, LDB_ERR_OPERATIONS_ERROR);
2054 DLIST_ADD_END(py_iter->state.next, reply);
2058 case LDB_REPLY_DONE:
2059 result = (struct ldb_result) { .controls = ares->controls };
2060 reply->obj = PyLdbResult_FromResult(&result);
2061 if (reply->obj == NULL) {
2063 return ldb_request_done(req, LDB_ERR_OPERATIONS_ERROR);
2065 py_iter->state.result = reply;
2067 return ldb_request_done(req, LDB_SUCCESS);
2071 return ldb_request_done(req, LDB_ERR_OPERATIONS_ERROR);
2074 static PyObject *py_ldb_search_iterator(PyLdbObject *self, PyObject *args, PyObject *kwargs)
2076 PyObject *py_base = Py_None;
2077 int scope = LDB_SCOPE_DEFAULT;
2080 PyObject *py_attrs = Py_None;
2081 PyObject *py_controls = Py_None;
2082 const char * const kwnames[] = { "base", "scope", "expression", "attrs", "controls", "timeout", NULL };
2085 struct ldb_context *ldb_ctx;
2086 struct ldb_control **parsed_controls;
2087 struct ldb_dn *base;
2088 PyLdbSearchIteratorObject *py_iter;
2090 /* type "int" rather than "enum" for "scope" is intentional */
2091 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "|OizOOi",
2092 discard_const_p(char *, kwnames),
2093 &py_base, &scope, &expr, &py_attrs, &py_controls, &timeout))
2096 py_iter = (PyLdbSearchIteratorObject *)PyLdbSearchIterator.tp_alloc(&PyLdbSearchIterator, 0);
2097 if (py_iter == NULL) {
2101 py_iter->ldb = self;
2103 ZERO_STRUCT(py_iter->state);
2104 py_iter->mem_ctx = talloc_new(NULL);
2105 if (py_iter->mem_ctx == NULL) {
2111 ldb_ctx = pyldb_Ldb_AS_LDBCONTEXT(self);
2113 if (py_attrs == Py_None) {
2116 attrs = PyList_AsStrList(py_iter->mem_ctx, py_attrs, "attrs");
2117 if (attrs == NULL) {
2124 if (py_base == Py_None) {
2125 base = ldb_get_default_basedn(ldb_ctx);
2127 if (!pyldb_Object_AsDn(py_iter->mem_ctx, py_base, ldb_ctx, &base)) {
2134 if (py_controls == Py_None) {
2135 parsed_controls = NULL;
2137 const char **controls = NULL;
2139 controls = PyList_AsStrList(py_iter->mem_ctx,
2140 py_controls, "controls");
2141 if (controls == NULL) {
2147 parsed_controls = ldb_parse_control_strings(ldb_ctx,
2150 if (controls[0] != NULL && parsed_controls == NULL) {
2155 talloc_free(controls);
2158 ret = ldb_build_search_req(&py_iter->state.req,
2167 py_ldb_search_iterator_callback,
2169 if (ret != LDB_SUCCESS) {
2171 PyErr_SetLdbError(PyExc_LdbError, ret, ldb_ctx);
2175 ldb_set_timeout(ldb_ctx, py_iter->state.req, timeout);
2177 ret = ldb_request(ldb_ctx, py_iter->state.req);
2178 if (ret != LDB_SUCCESS) {
2180 PyErr_SetLdbError(PyExc_LdbError, ret, ldb_ctx);
2184 return (PyObject *)py_iter;
2187 static PyObject *py_ldb_get_opaque(PyLdbObject *self, PyObject *args)
2192 if (!PyArg_ParseTuple(args, "s", &name))
2195 data = ldb_get_opaque(pyldb_Ldb_AS_LDBCONTEXT(self), name);
2200 /* FIXME: More interpretation */
2205 static PyObject *py_ldb_set_opaque(PyLdbObject *self, PyObject *args)
2210 if (!PyArg_ParseTuple(args, "sO", &name, &data))
2213 /* FIXME: More interpretation */
2215 ldb_set_opaque(pyldb_Ldb_AS_LDBCONTEXT(self), name, data);
2220 static PyObject *py_ldb_modules(PyLdbObject *self,
2221 PyObject *Py_UNUSED(ignored))
2223 struct ldb_context *ldb = pyldb_Ldb_AS_LDBCONTEXT(self);
2224 PyObject *ret = PyList_New(0);
2225 struct ldb_module *mod;
2228 return PyErr_NoMemory();
2230 for (mod = ldb->modules; mod; mod = mod->next) {
2231 PyObject *item = PyLdbModule_FromModule(mod);
2234 PyErr_SetString(PyExc_RuntimeError,
2235 "Failed to load LdbModule");
2239 res = PyList_Append(ret, item);
2250 static PyObject *py_ldb_sequence_number(PyLdbObject *self, PyObject *args)
2252 struct ldb_context *ldb = pyldb_Ldb_AS_LDBCONTEXT(self);
2256 if (!PyArg_ParseTuple(args, "i", &type))
2259 /* FIXME: More interpretation */
2261 ret = ldb_sequence_number(ldb, type, &value);
2263 PyErr_LDB_ERROR_IS_ERR_RAISE(PyExc_LdbError, ret, ldb);
2265 return PyLong_FromLongLong(value);
2269 static const struct ldb_dn_extended_syntax test_dn_syntax = {
2271 .read_fn = ldb_handler_copy,
2272 .write_clear_fn = ldb_handler_copy,
2273 .write_hex_fn = ldb_handler_copy,
2276 static PyObject *py_ldb_register_test_extensions(PyLdbObject *self,
2277 PyObject *Py_UNUSED(ignored))
2279 struct ldb_context *ldb = pyldb_Ldb_AS_LDBCONTEXT(self);
2282 ret = ldb_dn_extended_add_syntax(ldb, LDB_ATTR_FLAG_FIXED, &test_dn_syntax);
2284 PyErr_LDB_ERROR_IS_ERR_RAISE(PyExc_LdbError, ret, ldb);
2290 static PyMethodDef py_ldb_methods[] = {
2291 { "set_debug", (PyCFunction)py_ldb_set_debug, METH_VARARGS,
2292 "S.set_debug(callback) -> None\n"
2293 "Set callback for LDB debug messages.\n"
2294 "The callback should accept a debug level and debug text." },
2295 { "set_create_perms", (PyCFunction)py_ldb_set_create_perms, METH_VARARGS,
2296 "S.set_create_perms(mode) -> None\n"
2297 "Set mode to use when creating new LDB files." },
2298 { "set_modules_dir", (PyCFunction)py_ldb_set_modules_dir, METH_VARARGS,
2299 "S.set_modules_dir(path) -> None\n"
2300 "Set path LDB should search for modules" },
2301 { "transaction_start", (PyCFunction)py_ldb_transaction_start, METH_NOARGS,
2302 "S.transaction_start() -> None\n"
2303 "Start a new transaction." },
2304 { "transaction_prepare_commit", (PyCFunction)py_ldb_transaction_prepare_commit, METH_NOARGS,
2305 "S.transaction_prepare_commit() -> None\n"
2306 "prepare to commit a new transaction (2-stage commit)." },
2307 { "transaction_commit", (PyCFunction)py_ldb_transaction_commit, METH_NOARGS,
2308 "S.transaction_commit() -> None\n"
2309 "commit a new transaction." },
2310 { "transaction_cancel", (PyCFunction)py_ldb_transaction_cancel, METH_NOARGS,
2311 "S.transaction_cancel() -> None\n"
2312 "cancel a new transaction." },
2313 { "setup_wellknown_attributes", (PyCFunction)py_ldb_setup_wellknown_attributes, METH_NOARGS,
2315 { "get_root_basedn", (PyCFunction)py_ldb_get_root_basedn, METH_NOARGS,
2317 { "get_schema_basedn", (PyCFunction)py_ldb_get_schema_basedn, METH_NOARGS,
2319 { "get_default_basedn", (PyCFunction)py_ldb_get_default_basedn, METH_NOARGS,
2321 { "get_config_basedn", (PyCFunction)py_ldb_get_config_basedn, METH_NOARGS,
2323 { "connect", PY_DISCARD_FUNC_SIG(PyCFunction, py_ldb_connect),
2324 METH_VARARGS|METH_KEYWORDS,
2325 "S.connect(url, flags=0, options=None) -> None\n"
2326 "Connect to a LDB URL." },
2327 { "modify", PY_DISCARD_FUNC_SIG(PyCFunction, py_ldb_modify),
2328 METH_VARARGS|METH_KEYWORDS,
2329 "S.modify(message, controls=None, validate=False) -> None\n"
2330 "Modify an entry." },
2331 { "add", PY_DISCARD_FUNC_SIG(PyCFunction, py_ldb_add),
2332 METH_VARARGS|METH_KEYWORDS,
2333 "S.add(message, controls=None) -> None\n"
2335 { "delete", PY_DISCARD_FUNC_SIG(PyCFunction, py_ldb_delete),
2336 METH_VARARGS|METH_KEYWORDS,
2337 "S.delete(dn, controls=None) -> None\n"
2338 "Remove an entry." },
2339 { "rename", PY_DISCARD_FUNC_SIG(PyCFunction, py_ldb_rename),
2340 METH_VARARGS|METH_KEYWORDS,
2341 "S.rename(old_dn, new_dn, controls=None) -> None\n"
2342 "Rename an entry." },
2343 { "search", PY_DISCARD_FUNC_SIG(PyCFunction, py_ldb_search),
2344 METH_VARARGS|METH_KEYWORDS,
2345 "S.search(base=None, scope=None, expression=None, attrs=None, controls=None) -> result\n"
2346 "Search in a database.\n"
2348 ":param base: Optional base DN to search\n"
2349 ":param scope: Search scope (SCOPE_BASE, SCOPE_ONELEVEL or SCOPE_SUBTREE)\n"
2350 ":param expression: Optional search expression\n"
2351 ":param attrs: Attributes to return (defaults to all)\n"
2352 ":param controls: Optional list of controls\n"
2353 ":return: ldb.Result object\n"
2355 { "search_iterator", PY_DISCARD_FUNC_SIG(PyCFunction,
2356 py_ldb_search_iterator),
2357 METH_VARARGS|METH_KEYWORDS,
2358 "S.search_iterator(base=None, scope=None, expression=None, attrs=None, controls=None, timeout=None) -> iterator\n"
2359 "Search in a database.\n"
2361 ":param base: Optional base DN to search\n"
2362 ":param scope: Search scope (SCOPE_BASE, SCOPE_ONELEVEL or SCOPE_SUBTREE)\n"
2363 ":param expression: Optional search expression\n"
2364 ":param attrs: Attributes to return (defaults to all)\n"
2365 ":param controls: Optional list of controls\n"
2366 ":param timeout: Optional timeout in seconds (defaults to 300), 0 means the default, -1 no timeout\n"
2367 ":return: ldb.SearchIterator object that provides results when they arrive\n"
2369 { "schema_attribute_remove", (PyCFunction)py_ldb_schema_attribute_remove, METH_VARARGS,
2371 { "schema_attribute_add", (PyCFunction)py_ldb_schema_attribute_add, METH_VARARGS,
2373 { "schema_format_value", (PyCFunction)py_ldb_schema_format_value, METH_VARARGS,
2375 { "parse_ldif", (PyCFunction)py_ldb_parse_ldif, METH_VARARGS,
2376 "S.parse_ldif(ldif) -> iter(messages)\n"
2377 "Parse a string formatted using LDIF." },
2378 { "write_ldif", (PyCFunction)py_ldb_write_ldif, METH_VARARGS,
2379 "S.write_ldif(message, changetype) -> ldif\n"
2380 "Print the message as a string formatted using LDIF." },
2381 { "msg_diff", (PyCFunction)py_ldb_msg_diff, METH_VARARGS,
2382 "S.msg_diff(Message) -> Message\n"
2383 "Return an LDB Message of the difference between two Message objects." },
2384 { "get_opaque", (PyCFunction)py_ldb_get_opaque, METH_VARARGS,
2385 "S.get_opaque(name) -> value\n"
2386 "Get an opaque value set on this LDB connection. \n"
2387 ":note: The returned value may not be useful in Python."
2389 { "set_opaque", (PyCFunction)py_ldb_set_opaque, METH_VARARGS,
2390 "S.set_opaque(name, value) -> None\n"
2391 "Set an opaque value on this LDB connection. \n"
2392 ":note: Passing incorrect values may cause crashes." },
2393 { "modules", (PyCFunction)py_ldb_modules, METH_NOARGS,
2394 "S.modules() -> list\n"
2395 "Return the list of modules on this LDB connection " },
2396 { "sequence_number", (PyCFunction)py_ldb_sequence_number, METH_VARARGS,
2397 "S.sequence_number(type) -> value\n"
2398 "Return the value of the sequence according to the requested type" },
2399 { "_register_test_extensions", (PyCFunction)py_ldb_register_test_extensions, METH_NOARGS,
2400 "S._register_test_extensions() -> None\n"
2401 "Register internal extensions used in testing" },
2405 static PyObject *PyLdbModule_FromModule(struct ldb_module *mod)
2407 PyLdbModuleObject *ret;
2409 ret = (PyLdbModuleObject *)PyLdbModule.tp_alloc(&PyLdbModule, 0);
2414 ret->mem_ctx = talloc_new(NULL);
2415 ret->mod = talloc_reference(ret->mem_ctx, mod);
2416 return (PyObject *)ret;
2419 static PyObject *py_ldb_get_firstmodule(PyLdbObject *self, void *closure)
2421 struct ldb_module *mod = pyldb_Ldb_AS_LDBCONTEXT(self)->modules;
2425 return PyLdbModule_FromModule(mod);
2428 static PyGetSetDef py_ldb_getset[] = {
2430 .name = discard_const_p(char, "firstmodule"),
2431 .get = (getter)py_ldb_get_firstmodule,
2436 static int py_ldb_contains(PyLdbObject *self, PyObject *obj)
2438 struct ldb_context *ldb_ctx = pyldb_Ldb_AS_LDBCONTEXT(self);
2440 struct ldb_result *result;
2444 if (!pyldb_Object_AsDn(ldb_ctx, obj, ldb_ctx, &dn)) {
2448 ret = ldb_search(ldb_ctx, ldb_ctx, &result, dn, LDB_SCOPE_BASE, NULL,
2450 if (ret != LDB_SUCCESS) {
2451 PyErr_SetLdbError(PyExc_LdbError, ret, ldb_ctx);
2455 count = result->count;
2457 talloc_free(result);
2460 PyErr_Format(PyExc_RuntimeError,
2461 "Searching for [%s] dn gave %u results!",
2462 ldb_dn_get_linearized(dn),
2470 static PySequenceMethods py_ldb_seq = {
2471 .sq_contains = (objobjproc)py_ldb_contains,
2474 static PyObject *PyLdb_FromLdbContext(struct ldb_context *ldb_ctx)
2478 ret = (PyLdbObject *)PyLdb.tp_alloc(&PyLdb, 0);
2483 ret->mem_ctx = talloc_new(NULL);
2484 ret->ldb_ctx = talloc_reference(ret->mem_ctx, ldb_ctx);
2485 return (PyObject *)ret;
2488 static void py_ldb_dealloc(PyLdbObject *self)
2490 talloc_free(self->mem_ctx);
2491 Py_TYPE(self)->tp_free(self);
2494 static PyTypeObject PyLdb = {
2495 .tp_name = "ldb.Ldb",
2496 .tp_methods = py_ldb_methods,
2497 .tp_repr = (reprfunc)py_ldb_repr,
2498 .tp_new = py_ldb_new,
2499 .tp_init = (initproc)py_ldb_init,
2500 .tp_dealloc = (destructor)py_ldb_dealloc,
2501 .tp_getset = py_ldb_getset,
2502 .tp_getattro = PyObject_GenericGetAttr,
2503 .tp_basicsize = sizeof(PyLdbObject),
2504 .tp_doc = "Connection to a LDB database.",
2505 .tp_as_sequence = &py_ldb_seq,
2506 .tp_flags = Py_TPFLAGS_DEFAULT|Py_TPFLAGS_BASETYPE,
2509 static void py_ldb_result_dealloc(PyLdbResultObject *self)
2511 talloc_free(self->mem_ctx);
2512 Py_DECREF(self->msgs);
2513 Py_DECREF(self->referals);
2514 Py_DECREF(self->controls);
2515 Py_TYPE(self)->tp_free(self);
2518 static PyObject *py_ldb_result_get_msgs(PyLdbResultObject *self, void *closure)
2520 Py_INCREF(self->msgs);
2524 static PyObject *py_ldb_result_get_controls(PyLdbResultObject *self, void *closure)
2526 Py_INCREF(self->controls);
2527 return self->controls;
2530 static PyObject *py_ldb_result_get_referals(PyLdbResultObject *self, void *closure)
2532 Py_INCREF(self->referals);
2533 return self->referals;
2536 static PyObject *py_ldb_result_get_count(PyLdbResultObject *self, void *closure)
2539 if (self->msgs == NULL) {
2540 PyErr_SetString(PyExc_AttributeError, "Count attribute is meaningless in this context");
2543 size = PyList_Size(self->msgs);
2544 return PyInt_FromLong(size);
2547 static PyGetSetDef py_ldb_result_getset[] = {
2549 .name = discard_const_p(char, "controls"),
2550 .get = (getter)py_ldb_result_get_controls,
2553 .name = discard_const_p(char, "msgs"),
2554 .get = (getter)py_ldb_result_get_msgs,
2557 .name = discard_const_p(char, "referals"),
2558 .get = (getter)py_ldb_result_get_referals,
2561 .name = discard_const_p(char, "count"),
2562 .get = (getter)py_ldb_result_get_count,
2567 static PyObject *py_ldb_result_iter(PyLdbResultObject *self)
2569 return PyObject_GetIter(self->msgs);
2572 static Py_ssize_t py_ldb_result_len(PyLdbResultObject *self)
2574 return PySequence_Size(self->msgs);
2577 static PyObject *py_ldb_result_find(PyLdbResultObject *self, Py_ssize_t idx)
2579 return PySequence_GetItem(self->msgs, idx);
2582 static PySequenceMethods py_ldb_result_seq = {
2583 .sq_length = (lenfunc)py_ldb_result_len,
2584 .sq_item = (ssizeargfunc)py_ldb_result_find,
2587 static PyObject *py_ldb_result_repr(PyLdbObject *self)
2589 return PyUnicode_FromString("<ldb result>");
2593 static PyTypeObject PyLdbResult = {
2594 .tp_name = "ldb.Result",
2595 .tp_repr = (reprfunc)py_ldb_result_repr,
2596 .tp_dealloc = (destructor)py_ldb_result_dealloc,
2597 .tp_iter = (getiterfunc)py_ldb_result_iter,
2598 .tp_getset = py_ldb_result_getset,
2599 .tp_getattro = PyObject_GenericGetAttr,
2600 .tp_basicsize = sizeof(PyLdbResultObject),
2601 .tp_as_sequence = &py_ldb_result_seq,
2602 .tp_doc = "LDB result.",
2603 .tp_flags = Py_TPFLAGS_DEFAULT|Py_TPFLAGS_BASETYPE,
2606 static void py_ldb_search_iterator_dealloc(PyLdbSearchIteratorObject *self)
2608 Py_XDECREF(self->state.exception);
2609 TALLOC_FREE(self->mem_ctx);
2610 ZERO_STRUCT(self->state);
2611 Py_DECREF(self->ldb);
2612 Py_TYPE(self)->tp_free(self);
2615 static PyObject *py_ldb_search_iterator_next(PyLdbSearchIteratorObject *self)
2617 PyObject *py_ret = NULL;
2619 if (self->state.req == NULL) {
2620 PyErr_SetString(PyExc_RuntimeError,
2621 "ldb.SearchIterator request already finished");
2626 * TODO: do we want a non-blocking mode?
2627 * In future we may add an optional 'nonblocking'
2628 * argument to search_iterator().
2630 * For now we keep it simple and wait for at
2634 while (self->state.next == NULL) {
2637 if (self->state.result != NULL) {
2639 * We (already) got a final result from the server.
2641 * We stop the iteration and let
2642 * py_ldb_search_iterator_result() will deliver
2643 * the result details.
2645 TALLOC_FREE(self->state.req);
2646 PyErr_SetNone(PyExc_StopIteration);
2650 ret = ldb_wait(self->state.req->handle, LDB_WAIT_NONE);
2651 if (ret != LDB_SUCCESS) {
2652 struct ldb_context *ldb_ctx;
2653 TALLOC_FREE(self->state.req);
2654 ldb_ctx = pyldb_Ldb_AS_LDBCONTEXT(self->ldb);
2656 * We stop the iteration and let
2657 * py_ldb_search_iterator_result() will deliver
2660 self->state.exception = Py_BuildValue(discard_const_p(char, "(i,s)"),
2661 ret, ldb_errstring(ldb_ctx));
2662 PyErr_SetNone(PyExc_StopIteration);
2667 py_ret = self->state.next->obj;
2668 self->state.next->obj = NULL;
2669 /* no TALLOC_FREE() as self->state.next is a list */
2670 talloc_free(self->state.next);
2674 static PyObject *py_ldb_search_iterator_result(PyLdbSearchIteratorObject *self,
2675 PyObject *Py_UNUSED(ignored))
2677 PyObject *py_ret = NULL;
2679 if (self->state.req != NULL) {
2680 PyErr_SetString(PyExc_RuntimeError,
2681 "ldb.SearchIterator request running");
2685 if (self->state.next != NULL) {
2686 PyErr_SetString(PyExc_RuntimeError,
2687 "ldb.SearchIterator not fully consumed.");
2691 if (self->state.exception != NULL) {
2692 PyErr_SetObject(PyExc_LdbError, self->state.exception);
2693 self->state.exception = NULL;
2697 if (self->state.result == NULL) {
2698 PyErr_SetString(PyExc_RuntimeError,
2699 "ldb.SearchIterator result already consumed");
2703 py_ret = self->state.result->obj;
2704 self->state.result->obj = NULL;
2705 TALLOC_FREE(self->state.result);
2709 static PyObject *py_ldb_search_iterator_abandon(PyLdbSearchIteratorObject *self,
2710 PyObject *Py_UNUSED(ignored))
2712 if (self->state.req == NULL) {
2713 PyErr_SetString(PyExc_RuntimeError,
2714 "ldb.SearchIterator request already finished");
2718 Py_XDECREF(self->state.exception);
2719 TALLOC_FREE(self->mem_ctx);
2720 ZERO_STRUCT(self->state);
2724 static PyMethodDef py_ldb_search_iterator_methods[] = {
2725 { "result", (PyCFunction)py_ldb_search_iterator_result, METH_NOARGS,
2726 "S.result() -> ldb.Result (without msgs and referrals)\n" },
2727 { "abandon", (PyCFunction)py_ldb_search_iterator_abandon, METH_NOARGS,
2732 static PyObject *py_ldb_search_iterator_repr(PyLdbSearchIteratorObject *self)
2734 return PyUnicode_FromString("<ldb search iterator>");
2737 static PyTypeObject PyLdbSearchIterator = {
2738 .tp_name = "ldb.SearchIterator",
2739 .tp_repr = (reprfunc)py_ldb_search_iterator_repr,
2740 .tp_dealloc = (destructor)py_ldb_search_iterator_dealloc,
2741 .tp_iter = PyObject_SelfIter,
2742 .tp_iternext = (iternextfunc)py_ldb_search_iterator_next,
2743 .tp_methods = py_ldb_search_iterator_methods,
2744 .tp_basicsize = sizeof(PyLdbSearchIteratorObject),
2745 .tp_doc = "LDB search_iterator.",
2746 .tp_flags = Py_TPFLAGS_DEFAULT|Py_TPFLAGS_BASETYPE,
2749 static PyObject *py_ldb_module_repr(PyLdbModuleObject *self)
2751 return PyUnicode_FromFormat("<ldb module '%s'>",
2752 pyldb_Module_AsModule(self)->ops->name);
2755 static PyObject *py_ldb_module_str(PyLdbModuleObject *self)
2757 return PyUnicode_FromString(pyldb_Module_AsModule(self)->ops->name);
2760 static PyObject *py_ldb_module_start_transaction(PyLdbModuleObject *self,
2761 PyObject *Py_UNUSED(ignored))
2763 pyldb_Module_AsModule(self)->ops->start_transaction(pyldb_Module_AsModule(self));
2767 static PyObject *py_ldb_module_end_transaction(PyLdbModuleObject *self,
2768 PyObject *Py_UNUSED(ignored))
2770 pyldb_Module_AsModule(self)->ops->end_transaction(pyldb_Module_AsModule(self));
2774 static PyObject *py_ldb_module_del_transaction(PyLdbModuleObject *self,
2775 PyObject *Py_UNUSED(ignored))
2777 pyldb_Module_AsModule(self)->ops->del_transaction(pyldb_Module_AsModule(self));
2781 static PyObject *py_ldb_module_search(PyLdbModuleObject *self, PyObject *args, PyObject *kwargs)
2783 PyObject *py_base, *py_tree, *py_attrs, *py_ret;
2785 struct ldb_request *req;
2786 const char * const kwnames[] = { "base", "scope", "tree", "attrs", NULL };
2787 struct ldb_module *mod;
2788 const char * const*attrs;
2790 /* type "int" rather than "enum" for "scope" is intentional */
2791 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "O!iOO",
2792 discard_const_p(char *, kwnames),
2793 &PyLdbDn, &py_base, &scope, &py_tree, &py_attrs))
2798 if (py_attrs == Py_None) {
2801 attrs = PyList_AsStrList(NULL, py_attrs, "attrs");
2806 ret = ldb_build_search_req(&req, mod->ldb, NULL, pyldb_Dn_AS_DN(py_base),
2807 scope, NULL /* expr */, attrs,
2808 NULL /* controls */, NULL, NULL, NULL);
2810 talloc_steal(req, attrs);
2812 PyErr_LDB_ERROR_IS_ERR_RAISE(PyExc_LdbError, ret, mod->ldb);
2814 req->op.search.res = NULL;
2816 ret = mod->ops->search(mod, req);
2818 PyErr_LDB_ERROR_IS_ERR_RAISE(PyExc_LdbError, ret, mod->ldb);
2820 py_ret = PyLdbResult_FromResult(req->op.search.res);
2828 static PyObject *py_ldb_module_add(PyLdbModuleObject *self, PyObject *args)
2830 struct ldb_request *req;
2831 PyObject *py_message;
2833 struct ldb_module *mod;
2835 if (!PyArg_ParseTuple(args, "O!", &PyLdbMessage, &py_message))
2838 req = talloc_zero(NULL, struct ldb_request);
2839 req->operation = LDB_ADD;
2840 req->op.add.message = pyldb_Message_AsMessage(py_message);
2842 mod = pyldb_Module_AsModule(self);
2843 ret = mod->ops->add(mod, req);
2845 PyErr_LDB_ERROR_IS_ERR_RAISE(PyExc_LdbError, ret, mod->ldb);
2850 static PyObject *py_ldb_module_modify(PyLdbModuleObject *self, PyObject *args)
2853 struct ldb_request *req;
2854 PyObject *py_message;
2855 struct ldb_module *mod;
2857 if (!PyArg_ParseTuple(args, "O!", &PyLdbMessage, &py_message))
2860 req = talloc_zero(NULL, struct ldb_request);
2861 req->operation = LDB_MODIFY;
2862 req->op.mod.message = pyldb_Message_AsMessage(py_message);
2864 mod = pyldb_Module_AsModule(self);
2865 ret = mod->ops->modify(mod, req);
2867 PyErr_LDB_ERROR_IS_ERR_RAISE(PyExc_LdbError, ret, mod->ldb);
2872 static PyObject *py_ldb_module_delete(PyLdbModuleObject *self, PyObject *args)
2875 struct ldb_request *req;
2878 if (!PyArg_ParseTuple(args, "O!", &PyLdbDn, &py_dn))
2881 req = talloc_zero(NULL, struct ldb_request);
2882 req->operation = LDB_DELETE;
2883 req->op.del.dn = pyldb_Dn_AS_DN(py_dn);
2885 ret = pyldb_Module_AsModule(self)->ops->del(pyldb_Module_AsModule(self), req);
2887 PyErr_LDB_ERROR_IS_ERR_RAISE(PyExc_LdbError, ret, NULL);
2892 static PyObject *py_ldb_module_rename(PyLdbModuleObject *self, PyObject *args)
2895 struct ldb_request *req;
2896 PyObject *py_dn1, *py_dn2;
2898 if (!PyArg_ParseTuple(args, "O!O!", &PyLdbDn, &py_dn1, &PyLdbDn, &py_dn2))
2901 req = talloc_zero(NULL, struct ldb_request);
2903 req->operation = LDB_RENAME;
2904 req->op.rename.olddn = pyldb_Dn_AS_DN(py_dn1);
2905 req->op.rename.newdn = pyldb_Dn_AS_DN(py_dn2);
2907 ret = pyldb_Module_AsModule(self)->ops->rename(pyldb_Module_AsModule(self), req);
2909 PyErr_LDB_ERROR_IS_ERR_RAISE(PyExc_LdbError, ret, NULL);
2914 static PyMethodDef py_ldb_module_methods[] = {
2915 { "search", PY_DISCARD_FUNC_SIG(PyCFunction, py_ldb_module_search),
2916 METH_VARARGS|METH_KEYWORDS, NULL },
2917 { "add", (PyCFunction)py_ldb_module_add, METH_VARARGS, NULL },
2918 { "modify", (PyCFunction)py_ldb_module_modify, METH_VARARGS, NULL },
2919 { "rename", (PyCFunction)py_ldb_module_rename, METH_VARARGS, NULL },
2920 { "delete", (PyCFunction)py_ldb_module_delete, METH_VARARGS, NULL },
2921 { "start_transaction", (PyCFunction)py_ldb_module_start_transaction, METH_NOARGS, NULL },
2922 { "end_transaction", (PyCFunction)py_ldb_module_end_transaction, METH_NOARGS, NULL },
2923 { "del_transaction", (PyCFunction)py_ldb_module_del_transaction, METH_NOARGS, NULL },
2927 static void py_ldb_module_dealloc(PyLdbModuleObject *self)
2929 talloc_free(self->mem_ctx);
2933 static PyTypeObject PyLdbModule = {
2934 .tp_name = "ldb.LdbModule",
2935 .tp_methods = py_ldb_module_methods,
2936 .tp_repr = (reprfunc)py_ldb_module_repr,
2937 .tp_str = (reprfunc)py_ldb_module_str,
2938 .tp_basicsize = sizeof(PyLdbModuleObject),
2939 .tp_dealloc = (destructor)py_ldb_module_dealloc,
2940 .tp_flags = Py_TPFLAGS_DEFAULT,
2941 .tp_doc = "LDB module (extension)",
2946 * Create a ldb_message_element from a Python object.
2948 * This will accept any sequence objects that contains strings, or
2951 * A reference to set_obj will be borrowed.
2953 * @param mem_ctx Memory context
2954 * @param set_obj Python object to convert
2955 * @param flags ldb_message_element flags to set
2956 * @param attr_name Name of the attribute
2957 * @return New ldb_message_element, allocated as child of mem_ctx
2959 static struct ldb_message_element *PyObject_AsMessageElement(
2960 TALLOC_CTX *mem_ctx,
2963 const char *attr_name)
2965 struct ldb_message_element *me;
2966 const char *msg = NULL;
2970 if (pyldb_MessageElement_Check(set_obj)) {
2971 PyLdbMessageElementObject *set_obj_as_me = (PyLdbMessageElementObject *)set_obj;
2972 /* We have to talloc_reference() the memory context, not the pointer
2973 * which may not actually be it's own context */
2974 if (talloc_reference(mem_ctx, set_obj_as_me->mem_ctx)) {
2975 return pyldb_MessageElement_AsMessageElement(set_obj);
2980 me = talloc(mem_ctx, struct ldb_message_element);
2986 me->name = talloc_strdup(me, attr_name);
2988 if (PyBytes_Check(set_obj) || PyUnicode_Check(set_obj)) {
2990 me->values = talloc_array(me, struct ldb_val, me->num_values);
2991 if (PyBytes_Check(set_obj)) {
2993 result = PyBytes_AsStringAndSize(set_obj, &_msg, &size);
3000 msg = PyUnicode_AsUTF8AndSize(set_obj, &size);
3006 me->values[0].data = talloc_memdup(me,
3007 (const uint8_t *)msg,
3009 me->values[0].length = size;
3010 } else if (PySequence_Check(set_obj)) {
3012 me->num_values = PySequence_Size(set_obj);
3013 me->values = talloc_array(me, struct ldb_val, me->num_values);
3014 for (i = 0; i < me->num_values; i++) {
3015 PyObject *obj = PySequence_GetItem(set_obj, i);
3016 if (PyBytes_Check(obj)) {
3018 result = PyBytes_AsStringAndSize(obj, &_msg, &size);
3024 } else if (PyUnicode_Check(obj)) {
3025 msg = PyUnicode_AsUTF8AndSize(obj, &size);
3031 PyErr_Format(PyExc_TypeError,
3032 "Expected string as element %zd in list", i);
3036 me->values[i].data = talloc_memdup(me,
3037 (const uint8_t *)msg,
3039 me->values[i].length = size;
3042 PyErr_Format(PyExc_TypeError,
3043 "String or List type expected for '%s' attribute", attr_name);
3052 static PyObject *ldb_msg_element_to_set(struct ldb_context *ldb_ctx,
3053 struct ldb_message_element *me)
3058 /* Python << 2.5 doesn't have PySet_New and PySet_Add. */
3059 result = PyList_New(me->num_values);
3061 for (i = 0; i < me->num_values; i++) {
3062 PyList_SetItem(result, i,
3063 PyObject_FromLdbValue(&me->values[i]));
3069 static PyObject *py_ldb_msg_element_get(PyLdbMessageElementObject *self, PyObject *args)
3072 if (!PyArg_ParseTuple(args, "I", &i))
3074 if (i >= pyldb_MessageElement_AsMessageElement(self)->num_values)
3077 return PyObject_FromLdbValue(&(pyldb_MessageElement_AsMessageElement(self)->values[i]));
3080 static PyObject *py_ldb_msg_element_flags(PyLdbMessageElementObject *self, PyObject *args)
3082 struct ldb_message_element *el = pyldb_MessageElement_AsMessageElement(self);
3083 return PyInt_FromLong(el->flags);
3086 static PyObject *py_ldb_msg_element_set_flags(PyLdbMessageElementObject *self, PyObject *args)
3089 struct ldb_message_element *el;
3090 if (!PyArg_ParseTuple(args, "I", &flags))
3093 el = pyldb_MessageElement_AsMessageElement(self);
3098 static PyMethodDef py_ldb_msg_element_methods[] = {
3099 { "get", (PyCFunction)py_ldb_msg_element_get, METH_VARARGS, NULL },
3100 { "set_flags", (PyCFunction)py_ldb_msg_element_set_flags, METH_VARARGS, NULL },
3101 { "flags", (PyCFunction)py_ldb_msg_element_flags, METH_NOARGS, NULL },
3105 static Py_ssize_t py_ldb_msg_element_len(PyLdbMessageElementObject *self)
3107 return pyldb_MessageElement_AsMessageElement(self)->num_values;
3110 static PyObject *py_ldb_msg_element_find(PyLdbMessageElementObject *self, Py_ssize_t idx)
3112 struct ldb_message_element *el = pyldb_MessageElement_AsMessageElement(self);
3113 if (idx < 0 || idx >= el->num_values) {
3114 PyErr_SetString(PyExc_IndexError, "Out of range");
3117 return PyLdbBytes_FromStringAndSize((char *)el->values[idx].data, el->values[idx].length);
3120 static PySequenceMethods py_ldb_msg_element_seq = {
3121 .sq_length = (lenfunc)py_ldb_msg_element_len,
3122 .sq_item = (ssizeargfunc)py_ldb_msg_element_find,
3125 static PyObject *py_ldb_msg_element_richcmp(PyObject *self, PyObject *other, int op)
3128 if (!pyldb_MessageElement_Check(other)) {
3129 Py_INCREF(Py_NotImplemented);
3130 return Py_NotImplemented;
3132 ret = ldb_msg_element_compare(pyldb_MessageElement_AsMessageElement(self),
3133 pyldb_MessageElement_AsMessageElement(other));
3134 return richcmp(ret, op);
3137 static PyObject *py_ldb_msg_element_iter(PyLdbMessageElementObject *self)
3139 PyObject *el = ldb_msg_element_to_set(NULL,
3140 pyldb_MessageElement_AsMessageElement(self));
3141 PyObject *ret = PyObject_GetIter(el);
3146 static PyObject *PyLdbMessageElement_FromMessageElement(struct ldb_message_element *el, TALLOC_CTX *mem_ctx)
3148 PyLdbMessageElementObject *ret;
3149 ret = PyObject_New(PyLdbMessageElementObject, &PyLdbMessageElement);
3154 ret->mem_ctx = talloc_new(NULL);
3155 if (talloc_reference(ret->mem_ctx, mem_ctx) == NULL) {
3160 return (PyObject *)ret;
3163 static PyObject *py_ldb_msg_element_new(PyTypeObject *type, PyObject *args, PyObject *kwargs)
3165 PyObject *py_elements = NULL;
3166 struct ldb_message_element *el;
3167 unsigned int flags = 0;
3169 const char * const kwnames[] = { "elements", "flags", "name", NULL };
3170 PyLdbMessageElementObject *ret;
3171 TALLOC_CTX *mem_ctx;
3172 const char *msg = NULL;
3176 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "|OIs",
3177 discard_const_p(char *, kwnames),
3178 &py_elements, &flags, &name))
3181 mem_ctx = talloc_new(NULL);
3182 if (mem_ctx == NULL) {
3187 el = talloc_zero(mem_ctx, struct ldb_message_element);
3190 talloc_free(mem_ctx);
3194 if (py_elements != NULL) {
3196 if (PyBytes_Check(py_elements) || PyUnicode_Check(py_elements)) {
3199 el->values = talloc_array(el, struct ldb_val, 1);
3200 if (el->values == NULL) {
3201 talloc_free(mem_ctx);
3205 if (PyBytes_Check(py_elements)) {
3206 result = PyBytes_AsStringAndSize(py_elements, &_msg, &size);
3209 msg = PyUnicode_AsUTF8AndSize(py_elements, &size);
3210 result = (msg == NULL) ? -1 : 0;
3213 talloc_free(mem_ctx);
3216 el->values[0].data = talloc_memdup(el->values,
3217 (const uint8_t *)msg, size + 1);
3218 el->values[0].length = size;
3219 } else if (PySequence_Check(py_elements)) {
3220 el->num_values = PySequence_Size(py_elements);
3221 el->values = talloc_array(el, struct ldb_val, el->num_values);
3222 if (el->values == NULL) {
3223 talloc_free(mem_ctx);
3227 for (i = 0; i < el->num_values; i++) {
3228 PyObject *item = PySequence_GetItem(py_elements, i);
3230 talloc_free(mem_ctx);
3233 if (PyBytes_Check(item)) {
3235 result = PyBytes_AsStringAndSize(item, &_msg, &size);
3237 } else if (PyUnicode_Check(item)) {
3238 msg = PyUnicode_AsUTF8AndSize(item, &size);
3239 result = (msg == NULL) ? -1 : 0;
3241 PyErr_Format(PyExc_TypeError,
3242 "Expected string as element %zd in list", i);
3246 talloc_free(mem_ctx);
3249 el->values[i].data = talloc_memdup(el,
3250 (const uint8_t *)msg, size+1);
3251 el->values[i].length = size;
3254 PyErr_SetString(PyExc_TypeError,
3255 "Expected string or list");
3256 talloc_free(mem_ctx);
3262 el->name = talloc_strdup(el, name);
3264 ret = PyObject_New(PyLdbMessageElementObject, type);
3266 talloc_free(mem_ctx);
3270 ret->mem_ctx = mem_ctx;
3272 return (PyObject *)ret;
3275 static PyObject *py_ldb_msg_element_repr(PyLdbMessageElementObject *self)
3277 char *element_str = NULL;
3279 struct ldb_message_element *el = pyldb_MessageElement_AsMessageElement(self);
3280 PyObject *ret, *repr;
3282 for (i = 0; i < el->num_values; i++) {
3283 PyObject *o = py_ldb_msg_element_find(self, i);
3284 repr = PyObject_Repr(o);
3285 if (element_str == NULL)
3286 element_str = talloc_strdup(NULL, PyUnicode_AsUTF8(repr));
3288 element_str = talloc_asprintf_append(element_str, ",%s", PyUnicode_AsUTF8(repr));
3292 if (element_str != NULL) {
3293 ret = PyUnicode_FromFormat("MessageElement([%s])", element_str);
3294 talloc_free(element_str);
3296 ret = PyUnicode_FromString("MessageElement([])");
3302 static PyObject *py_ldb_msg_element_str(PyLdbMessageElementObject *self)
3304 struct ldb_message_element *el = pyldb_MessageElement_AsMessageElement(self);
3306 if (el->num_values == 1)
3307 return PyUnicode_FromStringAndSize((char *)el->values[0].data, el->values[0].length);
3312 static void py_ldb_msg_element_dealloc(PyLdbMessageElementObject *self)
3314 talloc_free(self->mem_ctx);
3318 static PyObject *py_ldb_msg_element_get_text(PyObject *self, void *closure)
3320 return wrap_text("MessageElementTextWrapper", self);
3323 static PyGetSetDef py_ldb_msg_element_getset[] = {
3325 .name = discard_const_p(char, "text"),
3326 .get = (getter)py_ldb_msg_element_get_text,
3331 static PyTypeObject PyLdbMessageElement = {
3332 .tp_name = "ldb.MessageElement",
3333 .tp_basicsize = sizeof(PyLdbMessageElementObject),
3334 .tp_dealloc = (destructor)py_ldb_msg_element_dealloc,
3335 .tp_repr = (reprfunc)py_ldb_msg_element_repr,
3336 .tp_str = (reprfunc)py_ldb_msg_element_str,
3337 .tp_methods = py_ldb_msg_element_methods,
3338 .tp_getset = py_ldb_msg_element_getset,
3339 .tp_richcompare = (richcmpfunc)py_ldb_msg_element_richcmp,
3340 .tp_iter = (getiterfunc)py_ldb_msg_element_iter,
3341 .tp_as_sequence = &py_ldb_msg_element_seq,
3342 .tp_new = py_ldb_msg_element_new,
3343 .tp_flags = Py_TPFLAGS_DEFAULT,
3344 .tp_doc = "An element of a Message",
3348 static PyObject *py_ldb_msg_from_dict(PyTypeObject *type, PyObject *args)
3353 struct ldb_message *msg;
3354 struct ldb_context *ldb_ctx;
3355 unsigned int mod_flags = LDB_FLAG_MOD_REPLACE;
3357 if (!PyArg_ParseTuple(args, "O!O!|I",
3358 &PyLdb, &py_ldb, &PyDict_Type, &py_dict,
3363 if (!PyLdb_Check(py_ldb)) {
3364 PyErr_SetString(PyExc_TypeError, "Expected Ldb");
3368 /* mask only flags we are going to use */
3369 mod_flags = LDB_FLAG_MOD_TYPE(mod_flags);
3371 PyErr_SetString(PyExc_ValueError,
3372 "FLAG_MOD_ADD, FLAG_MOD_REPLACE or FLAG_MOD_DELETE"
3373 " expected as mod_flag value");
3377 ldb_ctx = pyldb_Ldb_AS_LDBCONTEXT(py_ldb);
3379 msg = PyDict_AsMessage(ldb_ctx, py_dict, ldb_ctx, mod_flags);
3384 py_ret = PyLdbMessage_FromMessage(msg);
3386 talloc_unlink(ldb_ctx, msg);
3391 static PyObject *py_ldb_msg_remove_attr(PyLdbMessageObject *self, PyObject *args)
3394 if (!PyArg_ParseTuple(args, "s", &name))
3397 ldb_msg_remove_attr(self->msg, name);
3402 static PyObject *py_ldb_msg_keys(PyLdbMessageObject *self,
3403 PyObject *Py_UNUSED(ignored))
3405 struct ldb_message *msg = pyldb_Message_AsMessage(self);
3406 Py_ssize_t i, j = 0;
3407 PyObject *obj = PyList_New(msg->num_elements+(msg->dn != NULL?1:0));
3408 if (msg->dn != NULL) {
3409 PyList_SetItem(obj, j, PyUnicode_FromString("dn"));
3412 for (i = 0; i < msg->num_elements; i++) {
3413 PyList_SetItem(obj, j, PyUnicode_FromString(msg->elements[i].name));
3419 static PyObject *py_ldb_msg_getitem_helper(PyLdbMessageObject *self, PyObject *py_name)
3421 struct ldb_message_element *el;
3423 struct ldb_message *msg = pyldb_Message_AsMessage(self);
3424 name = PyUnicode_AsUTF8(py_name);
3426 PyErr_SetNone(PyExc_TypeError);
3429 if (!ldb_attr_cmp(name, "dn"))
3430 return pyldb_Dn_FromDn(msg->dn);
3431 el = ldb_msg_find_element(msg, name);
3435 return (PyObject *)PyLdbMessageElement_FromMessageElement(el, msg->elements);
3438 static PyObject *py_ldb_msg_getitem(PyLdbMessageObject *self, PyObject *py_name)
3440 PyObject *ret = py_ldb_msg_getitem_helper(self, py_name);
3442 PyErr_SetString(PyExc_KeyError, "No such element");
3448 static PyObject *py_ldb_msg_get(PyLdbMessageObject *self, PyObject *args, PyObject *kwargs)
3450 PyObject *def = NULL;
3451 const char *kwnames[] = { "name", "default", "idx", NULL };
3452 const char *name = NULL;
3454 struct ldb_message *msg = pyldb_Message_AsMessage(self);
3455 struct ldb_message_element *el;
3457 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "s|Oi:msg",
3458 discard_const_p(char *, kwnames), &name, &def, &idx)) {
3462 if (strcasecmp(name, "dn") == 0) {
3463 return pyldb_Dn_FromDn(msg->dn);
3466 el = ldb_msg_find_element(msg, name);
3468 if (el == NULL || (idx != -1 && el->num_values <= idx)) {
3477 return (PyObject *)PyLdbMessageElement_FromMessageElement(el, msg->elements);
3480 return PyObject_FromLdbValue(&el->values[idx]);
3483 static PyObject *py_ldb_msg_items(PyLdbMessageObject *self,
3484 PyObject *Py_UNUSED(ignored))
3486 struct ldb_message *msg = pyldb_Message_AsMessage(self);
3487 Py_ssize_t i, j = 0;
3488 PyObject *l = PyList_New(msg->num_elements + (msg->dn == NULL?0:1));
3490 return PyErr_NoMemory();
3492 if (msg->dn != NULL) {
3493 PyObject *value = NULL;
3494 PyObject *obj = pyldb_Dn_FromDn(msg->dn);
3496 value = Py_BuildValue("(sO)", "dn", obj);
3498 if (value == NULL) {
3502 res = PyList_SetItem(l, 0, value);
3509 for (i = 0; i < msg->num_elements; i++, j++) {
3510 PyObject *value = NULL;
3511 PyObject *py_el = PyLdbMessageElement_FromMessageElement(&msg->elements[i], msg->elements);
3514 value = Py_BuildValue("(sO)", msg->elements[i].name, py_el);
3515 if (value == NULL ) {
3519 res = PyList_SetItem(l, 0, value);
3528 static PyObject *py_ldb_msg_elements(PyLdbMessageObject *self,
3529 PyObject *Py_UNUSED(ignored))
3531 struct ldb_message *msg = pyldb_Message_AsMessage(self);
3533 PyObject *l = PyList_New(msg->num_elements);
3534 for (i = 0; i < msg->num_elements; i++) {
3535 PyList_SetItem(l, i, PyLdbMessageElement_FromMessageElement(&msg->elements[i], msg->elements));
3540 static PyObject *py_ldb_msg_add(PyLdbMessageObject *self, PyObject *args)
3542 struct ldb_message *msg = pyldb_Message_AsMessage(self);
3543 PyLdbMessageElementObject *py_element;
3545 struct ldb_message_element *el;
3546 struct ldb_message_element *el_new;
3548 if (!PyArg_ParseTuple(args, "O!", &PyLdbMessageElement, &py_element))
3551 el = py_element->el;
3553 PyErr_SetString(PyExc_ValueError, "Invalid MessageElement object");
3556 if (el->name == NULL) {
3557 PyErr_SetString(PyExc_ValueError,
3558 "The element has no name");
3561 ret = ldb_msg_add_empty(msg, el->name, el->flags, &el_new);
3562 PyErr_LDB_ERROR_IS_ERR_RAISE(PyExc_LdbError, ret, NULL);
3564 /* now deep copy all attribute values */
3565 el_new->values = talloc_array(msg->elements, struct ldb_val, el->num_values);
3566 if (el_new->values == NULL) {
3570 el_new->num_values = el->num_values;
3572 for (i = 0; i < el->num_values; i++) {
3573 el_new->values[i] = ldb_val_dup(el_new->values, &el->values[i]);
3574 if (el_new->values[i].data == NULL
3575 && el->values[i].length != 0) {
3584 static PyMethodDef py_ldb_msg_methods[] = {
3585 { "from_dict", (PyCFunction)py_ldb_msg_from_dict, METH_CLASS | METH_VARARGS,
3586 "Message.from_dict(ldb, dict, mod_flag=FLAG_MOD_REPLACE) -> ldb.Message\n"
3587 "Class method to create ldb.Message object from Dictionary.\n"
3588 "mod_flag is one of FLAG_MOD_ADD, FLAG_MOD_REPLACE or FLAG_MOD_DELETE."},
3589 { "keys", (PyCFunction)py_ldb_msg_keys, METH_NOARGS,
3590 "S.keys() -> list\n\n"
3591 "Return sequence of all attribute names." },
3592 { "remove", (PyCFunction)py_ldb_msg_remove_attr, METH_VARARGS,
3593 "S.remove(name)\n\n"
3594 "Remove all entries for attributes with the specified name."},
3595 { "get", PY_DISCARD_FUNC_SIG(PyCFunction, py_ldb_msg_get),
3596 METH_VARARGS | METH_KEYWORDS,
3597 "msg.get(name,default=None,idx=None) -> string\n"
3598 "idx is the index into the values array\n"
3599 "if idx is None, then a list is returned\n"
3600 "if idx is not None, then the element with that index is returned\n"
3601 "if you pass the special name 'dn' then the DN object is returned\n"},
3602 { "items", (PyCFunction)py_ldb_msg_items, METH_NOARGS, NULL },
3603 { "elements", (PyCFunction)py_ldb_msg_elements, METH_NOARGS, NULL },
3604 { "add", (PyCFunction)py_ldb_msg_add, METH_VARARGS,
3605 "S.add(element)\n\n"
3606 "Add an element to this message." },
3610 static PyObject *py_ldb_msg_iter(PyLdbMessageObject *self)
3612 PyObject *list, *iter;
3614 list = py_ldb_msg_keys(self, NULL);
3615 iter = PyObject_GetIter(list);
3620 static int py_ldb_msg_setitem(PyLdbMessageObject *self, PyObject *name, PyObject *value)
3622 const char *attr_name;
3624 attr_name = PyUnicode_AsUTF8(name);
3625 if (attr_name == NULL) {
3626 PyErr_SetNone(PyExc_TypeError);
3630 if (value == NULL) {
3632 ldb_msg_remove_attr(self->msg, attr_name);
3635 struct ldb_message_element *el = PyObject_AsMessageElement(self->msg,
3636 value, 0, attr_name);
3640 ldb_msg_remove_attr(pyldb_Message_AsMessage(self), attr_name);
3641 ret = ldb_msg_add(pyldb_Message_AsMessage(self), el, el->flags);
3642 if (ret != LDB_SUCCESS) {
3643 PyErr_SetLdbError(PyExc_LdbError, ret, NULL);
3650 static Py_ssize_t py_ldb_msg_length(PyLdbMessageObject *self)
3652 return pyldb_Message_AsMessage(self)->num_elements;
3655 static PyMappingMethods py_ldb_msg_mapping = {
3656 .mp_length = (lenfunc)py_ldb_msg_length,
3657 .mp_subscript = (binaryfunc)py_ldb_msg_getitem,
3658 .mp_ass_subscript = (objobjargproc)py_ldb_msg_setitem,
3661 static PyObject *py_ldb_msg_new(PyTypeObject *type, PyObject *args, PyObject *kwargs)
3663 const char * const kwnames[] = { "dn", NULL };
3664 struct ldb_message *ret;
3665 TALLOC_CTX *mem_ctx;
3666 PyObject *pydn = NULL;
3667 PyLdbMessageObject *py_ret;
3669 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "|O",
3670 discard_const_p(char *, kwnames),
3674 mem_ctx = talloc_new(NULL);
3675 if (mem_ctx == NULL) {
3680 ret = ldb_msg_new(mem_ctx);
3682 talloc_free(mem_ctx);
3689 if (!pyldb_Object_AsDn(NULL, pydn, NULL, &dn)) {
3690 talloc_free(mem_ctx);
3693 ret->dn = talloc_reference(ret, dn);
3696 py_ret = (PyLdbMessageObject *)type->tp_alloc(type, 0);
3697 if (py_ret == NULL) {
3699 talloc_free(mem_ctx);
3703 py_ret->mem_ctx = mem_ctx;
3705 return (PyObject *)py_ret;
3708 static PyObject *PyLdbMessage_FromMessage(struct ldb_message *msg)
3710 PyLdbMessageObject *ret;
3712 ret = (PyLdbMessageObject *)PyLdbMessage.tp_alloc(&PyLdbMessage, 0);
3717 ret->mem_ctx = talloc_new(NULL);
3718 ret->msg = talloc_reference(ret->mem_ctx, msg);
3719 return (PyObject *)ret;
3722 static PyObject *py_ldb_msg_get_dn(PyLdbMessageObject *self, void *closure)
3724 struct ldb_message *msg = pyldb_Message_AsMessage(self);
3725 return pyldb_Dn_FromDn(msg->dn);
3728 static int py_ldb_msg_set_dn(PyLdbMessageObject *self, PyObject *value, void *closure)
3730 struct ldb_message *msg = pyldb_Message_AsMessage(self);
3731 if (!pyldb_Dn_Check(value)) {
3732 PyErr_SetString(PyExc_TypeError, "expected dn");
3736 msg->dn = talloc_reference(msg, pyldb_Dn_AS_DN(value));
3740 static PyObject *py_ldb_msg_get_text(PyObject *self, void *closure)
3742 return wrap_text("MessageTextWrapper", self);
3745 static PyGetSetDef py_ldb_msg_getset[] = {
3747 .name = discard_const_p(char, "dn"),
3748 .get = (getter)py_ldb_msg_get_dn,
3749 .set = (setter)py_ldb_msg_set_dn,
3752 .name = discard_const_p(char, "text"),
3753 .get = (getter)py_ldb_msg_get_text,
3758 static PyObject *py_ldb_msg_repr(PyLdbMessageObject *self)
3760 PyObject *dict = PyDict_New(), *ret, *repr;
3761 if (PyDict_Update(dict, (PyObject *)self) != 0)
3763 repr = PyObject_Repr(dict);
3768 ret = PyUnicode_FromFormat("Message(%s)", PyUnicode_AsUTF8(repr));
3774 static void py_ldb_msg_dealloc(PyLdbMessageObject *self)
3776 talloc_free(self->mem_ctx);
3780 static PyObject *py_ldb_msg_richcmp(PyLdbMessageObject *py_msg1,
3781 PyLdbMessageObject *py_msg2, int op)
3783 struct ldb_message *msg1, *msg2;
3787 if (!PyLdbMessage_Check(py_msg2)) {
3788 Py_INCREF(Py_NotImplemented);
3789 return Py_NotImplemented;
3792 msg1 = pyldb_Message_AsMessage(py_msg1),
3793 msg2 = pyldb_Message_AsMessage(py_msg2);
3795 if ((msg1->dn != NULL) || (msg2->dn != NULL)) {
3796 ret = ldb_dn_compare(msg1->dn, msg2->dn);
3798 return richcmp(ret, op);
3802 ret = msg1->num_elements - msg2->num_elements;
3804 return richcmp(ret, op);
3807 for (i = 0; i < msg1->num_elements; i++) {
3808 ret = ldb_msg_element_compare_name(&msg1->elements[i],
3809 &msg2->elements[i]);
3811 return richcmp(ret, op);
3814 ret = ldb_msg_element_compare(&msg1->elements[i],
3815 &msg2->elements[i]);
3817 return richcmp(ret, op);
3821 return richcmp(0, op);
3824 static PyTypeObject PyLdbMessage = {
3825 .tp_name = "ldb.Message",
3826 .tp_methods = py_ldb_msg_methods,
3827 .tp_getset = py_ldb_msg_getset,
3828 .tp_as_mapping = &py_ldb_msg_mapping,
3829 .tp_basicsize = sizeof(PyLdbMessageObject),
3830 .tp_dealloc = (destructor)py_ldb_msg_dealloc,
3831 .tp_new = py_ldb_msg_new,
3832 .tp_repr = (reprfunc)py_ldb_msg_repr,
3833 .tp_flags = Py_TPFLAGS_DEFAULT,
3834 .tp_iter = (getiterfunc)py_ldb_msg_iter,
3835 .tp_richcompare = (richcmpfunc)py_ldb_msg_richcmp,
3836 .tp_doc = "A LDB Message",
3839 static PyObject *PyLdbTree_FromTree(struct ldb_parse_tree *tree)
3841 PyLdbTreeObject *ret;
3843 ret = (PyLdbTreeObject *)PyLdbTree.tp_alloc(&PyLdbTree, 0);
3849 ret->mem_ctx = talloc_new(NULL);
3850 ret->tree = talloc_reference(ret->mem_ctx, tree);
3851 return (PyObject *)ret;
3854 static void py_ldb_tree_dealloc(PyLdbTreeObject *self)
3856 talloc_free(self->mem_ctx);
3860 static PyTypeObject PyLdbTree = {
3861 .tp_name = "ldb.Tree",
3862 .tp_basicsize = sizeof(PyLdbTreeObject),
3863 .tp_dealloc = (destructor)py_ldb_tree_dealloc,
3864 .tp_flags = Py_TPFLAGS_DEFAULT,
3865 .tp_doc = "A search tree",
3869 static int py_module_search(struct ldb_module *mod, struct ldb_request *req)
3871 PyObject *py_ldb = (PyObject *)mod->private_data;
3872 PyObject *py_result, *py_base, *py_attrs, *py_tree;
3874 py_base = pyldb_Dn_FromDn(req->op.search.base);
3876 if (py_base == NULL)
3877 return LDB_ERR_OPERATIONS_ERROR;
3879 py_tree = PyLdbTree_FromTree(req->op.search.tree);
3881 if (py_tree == NULL)
3882 return LDB_ERR_OPERATIONS_ERROR;
3884 if (req->op.search.attrs == NULL) {
3888 for (len = 0; req->op.search.attrs[len]; len++);
3889 py_attrs = PyList_New(len);
3890 for (i = 0; i < len; i++)
3891 PyList_SetItem(py_attrs, i, PyUnicode_FromString(req->op.search.attrs[i]));
3894 py_result = PyObject_CallMethod(py_ldb, discard_const_p(char, "search"),
3895 discard_const_p(char, "OiOO"),
3896 py_base, req->op.search.scope, py_tree, py_attrs);
3898 Py_DECREF(py_attrs);
3902 if (py_result == NULL) {
3903 return LDB_ERR_PYTHON_EXCEPTION;
3906 req->op.search.res = PyLdbResult_AsResult(NULL, py_result);
3907 if (req->op.search.res == NULL) {
3908 return LDB_ERR_PYTHON_EXCEPTION;
3911 Py_DECREF(py_result);
3916 static int py_module_add(struct ldb_module *mod, struct ldb_request *req)
3918 PyObject *py_ldb = (PyObject *)mod->private_data;
3919 PyObject *py_result, *py_msg;
3921 py_msg = PyLdbMessage_FromMessage(discard_const_p(struct ldb_message, req->op.add.message));
3923 if (py_msg == NULL) {
3924 return LDB_ERR_OPERATIONS_ERROR;
3927 py_result = PyObject_CallMethod(py_ldb, discard_const_p(char, "add"),
3928 discard_const_p(char, "O"),
3933 if (py_result == NULL) {
3934 return LDB_ERR_PYTHON_EXCEPTION;
3937 Py_DECREF(py_result);
3942 static int py_module_modify(struct ldb_module *mod, struct ldb_request *req)
3944 PyObject *py_ldb = (PyObject *)mod->private_data;
3945 PyObject *py_result, *py_msg;
3947 py_msg = PyLdbMessage_FromMessage(discard_const_p(struct ldb_message, req->op.mod.message));
3949 if (py_msg == NULL) {
3950 return LDB_ERR_OPERATIONS_ERROR;
3953 py_result = PyObject_CallMethod(py_ldb, discard_const_p(char, "modify"),
3954 discard_const_p(char, "O"),
3959 if (py_result == NULL) {
3960 return LDB_ERR_PYTHON_EXCEPTION;
3963 Py_DECREF(py_result);
3968 static int py_module_del(struct ldb_module *mod, struct ldb_request *req)
3970 PyObject *py_ldb = (PyObject *)mod->private_data;
3971 PyObject *py_result, *py_dn;
3973 py_dn = pyldb_Dn_FromDn(req->op.del.dn);
3976 return LDB_ERR_OPERATIONS_ERROR;
3978 py_result = PyObject_CallMethod(py_ldb, discard_const_p(char, "delete"),
3979 discard_const_p(char, "O"),
3982 if (py_result == NULL) {
3983 return LDB_ERR_PYTHON_EXCEPTION;
3986 Py_DECREF(py_result);
3991 static int py_module_rename(struct ldb_module *mod, struct ldb_request *req)
3993 PyObject *py_ldb = (PyObject *)mod->private_data;
3994 PyObject *py_result, *py_olddn, *py_newdn;
3996 py_olddn = pyldb_Dn_FromDn(req->op.rename.olddn);
3998 if (py_olddn == NULL)
3999 return LDB_ERR_OPERATIONS_ERROR;
4001 py_newdn = pyldb_Dn_FromDn(req->op.rename.newdn);
4003 if (py_newdn == NULL)
4004 return LDB_ERR_OPERATIONS_ERROR;
4006 py_result = PyObject_CallMethod(py_ldb, discard_const_p(char, "rename"),
4007 discard_const_p(char, "OO"),
4008 py_olddn, py_newdn);
4010 Py_DECREF(py_olddn);
4011 Py_DECREF(py_newdn);
4013 if (py_result == NULL) {
4014 return LDB_ERR_PYTHON_EXCEPTION;
4017 Py_DECREF(py_result);
4022 static int py_module_request(struct ldb_module *mod, struct ldb_request *req)
4024 PyObject *py_ldb = (PyObject *)mod->private_data;
4025 PyObject *py_result;
4027 py_result = PyObject_CallMethod(py_ldb, discard_const_p(char, "request"),
4028 discard_const_p(char, ""));
4030 Py_XDECREF(py_result);
4032 return LDB_ERR_OPERATIONS_ERROR;
4035 static int py_module_extended(struct ldb_module *mod, struct ldb_request *req)
4037 PyObject *py_ldb = (PyObject *)mod->private_data;
4038 PyObject *py_result;
4040 py_result = PyObject_CallMethod(py_ldb, discard_const_p(char, "extended"),
4041 discard_const_p(char, ""));
4043 Py_XDECREF(py_result);
4045 return LDB_ERR_OPERATIONS_ERROR;
4048 static int py_module_start_transaction(struct ldb_module *mod)
4050 PyObject *py_ldb = (PyObject *)mod->private_data;
4051 PyObject *py_result;
4053 py_result = PyObject_CallMethod(py_ldb, discard_const_p(char, "start_transaction"),
4054 discard_const_p(char, ""));
4056 if (py_result == NULL) {
4057 return LDB_ERR_PYTHON_EXCEPTION;
4060 Py_DECREF(py_result);
4065 static int py_module_end_transaction(struct ldb_module *mod)
4067 PyObject *py_ldb = (PyObject *)mod->private_data;
4068 PyObject *py_result;
4070 py_result = PyObject_CallMethod(py_ldb, discard_const_p(char, "end_transaction"),
4071 discard_const_p(char, ""));
4073 if (py_result == NULL) {
4074 return LDB_ERR_PYTHON_EXCEPTION;
4077 Py_DECREF(py_result);
4082 static int py_module_del_transaction(struct ldb_module *mod)
4084 PyObject *py_ldb = (PyObject *)mod->private_data;
4085 PyObject *py_result;
4087 py_result = PyObject_CallMethod(py_ldb, discard_const_p(char, "del_transaction"),
4088 discard_const_p(char, ""));
4090 if (py_result == NULL) {
4091 return LDB_ERR_PYTHON_EXCEPTION;
4094 Py_DECREF(py_result);
4099 static int py_module_destructor(struct ldb_module *mod)
4101 Py_DECREF((PyObject *)mod->private_data);
4105 static int py_module_init(struct ldb_module *mod)
4107 PyObject *py_class = (PyObject *)mod->ops->private_data;
4108 PyObject *py_result, *py_next, *py_ldb;
4110 py_ldb = PyLdb_FromLdbContext(mod->ldb);
4113 return LDB_ERR_OPERATIONS_ERROR;
4115 py_next = PyLdbModule_FromModule(mod->next);
4117 if (py_next == NULL)
4118 return LDB_ERR_OPERATIONS_ERROR;
4120 py_result = PyObject_CallFunction(py_class, discard_const_p(char, "OO"),
4123 if (py_result == NULL) {
4124 return LDB_ERR_PYTHON_EXCEPTION;
4127 mod->private_data = py_result;
4129 talloc_set_destructor(mod, py_module_destructor);
4131 return ldb_next_init(mod);
4134 static PyObject *py_register_module(PyObject *module, PyObject *args)
4137 struct ldb_module_ops *ops;
4139 PyObject *tmp = NULL;
4140 const char *name = NULL;
4142 if (!PyArg_ParseTuple(args, "O", &input))
4145 ops = talloc_zero(NULL, struct ldb_module_ops);
4151 tmp = PyObject_GetAttrString(input, discard_const_p(char, "name"));
4155 name = PyUnicode_AsUTF8(tmp);
4162 ops->name = talloc_strdup(ops, name);
4163 ops->private_data = input;
4164 ops->init_context = py_module_init;
4165 ops->search = py_module_search;
4166 ops->add = py_module_add;
4167 ops->modify = py_module_modify;
4168 ops->del = py_module_del;
4169 ops->rename = py_module_rename;
4170 ops->request = py_module_request;
4171 ops->extended = py_module_extended;
4172 ops->start_transaction = py_module_start_transaction;
4173 ops->end_transaction = py_module_end_transaction;
4174 ops->del_transaction = py_module_del_transaction;
4176 ret = ldb_register_module(ops);
4177 if (ret != LDB_SUCCESS) {
4181 PyErr_LDB_ERROR_IS_ERR_RAISE(PyExc_LdbError, ret, NULL);
4186 static PyObject *py_timestring(PyObject *module, PyObject *args)
4188 /* most times "time_t" is a signed integer type with 32 or 64 bit:
4189 * http://stackoverflow.com/questions/471248/what-is-ultimately-a-time-t-typedef-to */
4193 if (!PyArg_ParseTuple(args, "l", &t_val))
4195 tresult = ldb_timestring(NULL, (time_t) t_val);
4196 ret = PyUnicode_FromString(tresult);
4197 talloc_free(tresult);
4201 static PyObject *py_string_to_time(PyObject *module, PyObject *args)
4204 if (!PyArg_ParseTuple(args, "s", &str))
4207 return PyInt_FromLong(ldb_string_to_time(str));
4210 static PyObject *py_valid_attr_name(PyObject *self, PyObject *args)
4213 if (!PyArg_ParseTuple(args, "s", &name))
4215 return PyBool_FromLong(ldb_valid_attr_name(name));
4219 encode a string using RFC2254 rules
4221 static PyObject *py_binary_encode(PyObject *self, PyObject *args)
4223 char *str, *encoded;
4224 Py_ssize_t size = 0;
4228 if (!PyArg_ParseTuple(args, "s#", &str, &size))
4230 val.data = (uint8_t *)str;
4233 encoded = ldb_binary_encode(NULL, val);
4234 if (encoded == NULL) {
4235 PyErr_SetString(PyExc_TypeError, "unable to encode binary string");
4238 ret = PyUnicode_FromString(encoded);
4239 talloc_free(encoded);
4244 decode a string using RFC2254 rules
4246 static PyObject *py_binary_decode(PyObject *self, PyObject *args)
4252 if (!PyArg_ParseTuple(args, "s", &str))
4255 val = ldb_binary_decode(NULL, str);
4256 if (val.data == NULL) {
4257 PyErr_SetString(PyExc_TypeError, "unable to decode binary string");
4260 ret = PyBytes_FromStringAndSize((const char*)val.data, val.length);
4261 talloc_free(val.data);
4265 static PyMethodDef py_ldb_global_methods[] = {
4266 { "register_module", py_register_module, METH_VARARGS,
4267 "S.register_module(module) -> None\n\n"
4268 "Register a LDB module."},
4269 { "timestring", py_timestring, METH_VARARGS,
4270 "S.timestring(int) -> string\n\n"
4271 "Generate a LDAP time string from a UNIX timestamp" },
4272 { "string_to_time", py_string_to_time, METH_VARARGS,
4273 "S.string_to_time(string) -> int\n\n"
4274 "Parse a LDAP time string into a UNIX timestamp." },
4275 { "valid_attr_name", py_valid_attr_name, METH_VARARGS,
4276 "S.valid_attr_name(name) -> bool\n\nn"
4277 "Check whether the supplied name is a valid attribute name." },
4278 { "binary_encode", py_binary_encode, METH_VARARGS,
4279 "S.binary_encode(string) -> string\n\n"
4280 "Perform a RFC2254 binary encoding on a string" },
4281 { "binary_decode", py_binary_decode, METH_VARARGS,
4282 "S.binary_decode(string) -> string\n\n"
4283 "Perform a RFC2254 binary decode on a string" },
4287 #define MODULE_DOC "An interface to LDB, a LDAP-like API that can either to talk an embedded database (TDB-based) or a standards-compliant LDAP server."
4289 #if PY_MAJOR_VERSION >= 3
4290 static struct PyModuleDef moduledef = {
4291 PyModuleDef_HEAD_INIT,
4293 .m_doc = MODULE_DOC,
4295 .m_methods = py_ldb_global_methods,
4299 static PyObject* module_init(void)
4303 PyLdbBytesType.tp_base = &PyBytes_Type;
4304 if (PyType_Ready(&PyLdbBytesType) < 0) {
4308 if (PyType_Ready(&PyLdbDn) < 0)
4311 if (PyType_Ready(&PyLdbMessage) < 0)
4314 if (PyType_Ready(&PyLdbMessageElement) < 0)
4317 if (PyType_Ready(&PyLdb) < 0)
4320 if (PyType_Ready(&PyLdbModule) < 0)
4323 if (PyType_Ready(&PyLdbTree) < 0)
4326 if (PyType_Ready(&PyLdbResult) < 0)
4329 if (PyType_Ready(&PyLdbSearchIterator) < 0)
4332 if (PyType_Ready(&PyLdbControl) < 0)
4335 #if PY_MAJOR_VERSION >= 3
4336 m = PyModule_Create(&moduledef);
4338 m = Py_InitModule3("ldb", py_ldb_global_methods, MODULE_DOC);
4343 #define ADD_LDB_INT(val) PyModule_AddIntConstant(m, #val, LDB_ ## val)
4345 ADD_LDB_INT(SEQ_HIGHEST_SEQ);
4346 ADD_LDB_INT(SEQ_HIGHEST_TIMESTAMP);
4347 ADD_LDB_INT(SEQ_NEXT);
4348 ADD_LDB_INT(SCOPE_DEFAULT);
4349 ADD_LDB_INT(SCOPE_BASE);
4350 ADD_LDB_INT(SCOPE_ONELEVEL);
4351 ADD_LDB_INT(SCOPE_SUBTREE);
4353 ADD_LDB_INT(CHANGETYPE_NONE);
4354 ADD_LDB_INT(CHANGETYPE_ADD);
4355 ADD_LDB_INT(CHANGETYPE_DELETE);
4356 ADD_LDB_INT(CHANGETYPE_MODIFY);
4358 ADD_LDB_INT(FLAG_MOD_ADD);
4359 ADD_LDB_INT(FLAG_MOD_REPLACE);
4360 ADD_LDB_INT(FLAG_MOD_DELETE);
4361 ADD_LDB_INT(FLAG_FORCE_NO_BASE64_LDIF);
4363 ADD_LDB_INT(ATTR_FLAG_HIDDEN);
4364 ADD_LDB_INT(ATTR_FLAG_UNIQUE_INDEX);
4365 ADD_LDB_INT(ATTR_FLAG_SINGLE_VALUE);
4366 ADD_LDB_INT(ATTR_FLAG_FORCE_BASE64_LDIF);
4368 ADD_LDB_INT(SUCCESS);
4369 ADD_LDB_INT(ERR_OPERATIONS_ERROR);
4370 ADD_LDB_INT(ERR_PROTOCOL_ERROR);
4371 ADD_LDB_INT(ERR_TIME_LIMIT_EXCEEDED);
4372 ADD_LDB_INT(ERR_SIZE_LIMIT_EXCEEDED);
4373 ADD_LDB_INT(ERR_COMPARE_FALSE);
4374 ADD_LDB_INT(ERR_COMPARE_TRUE);
4375 ADD_LDB_INT(ERR_AUTH_METHOD_NOT_SUPPORTED);
4376 ADD_LDB_INT(ERR_STRONG_AUTH_REQUIRED);
4377 ADD_LDB_INT(ERR_REFERRAL);
4378 ADD_LDB_INT(ERR_ADMIN_LIMIT_EXCEEDED);
4379 ADD_LDB_INT(ERR_UNSUPPORTED_CRITICAL_EXTENSION);
4380 ADD_LDB_INT(ERR_CONFIDENTIALITY_REQUIRED);
4381 ADD_LDB_INT(ERR_SASL_BIND_IN_PROGRESS);
4382 ADD_LDB_INT(ERR_NO_SUCH_ATTRIBUTE);
4383 ADD_LDB_INT(ERR_UNDEFINED_ATTRIBUTE_TYPE);
4384 ADD_LDB_INT(ERR_INAPPROPRIATE_MATCHING);
4385 ADD_LDB_INT(ERR_CONSTRAINT_VIOLATION);
4386 ADD_LDB_INT(ERR_ATTRIBUTE_OR_VALUE_EXISTS);
4387 ADD_LDB_INT(ERR_INVALID_ATTRIBUTE_SYNTAX);
4388 ADD_LDB_INT(ERR_NO_SUCH_OBJECT);
4389 ADD_LDB_INT(ERR_ALIAS_PROBLEM);
4390 ADD_LDB_INT(ERR_INVALID_DN_SYNTAX);
4391 ADD_LDB_INT(ERR_ALIAS_DEREFERENCING_PROBLEM);
4392 ADD_LDB_INT(ERR_INAPPROPRIATE_AUTHENTICATION);
4393 ADD_LDB_INT(ERR_INVALID_CREDENTIALS);
4394 ADD_LDB_INT(ERR_INSUFFICIENT_ACCESS_RIGHTS);
4395 ADD_LDB_INT(ERR_BUSY);
4396 ADD_LDB_INT(ERR_UNAVAILABLE);
4397 ADD_LDB_INT(ERR_UNWILLING_TO_PERFORM);
4398 ADD_LDB_INT(ERR_LOOP_DETECT);
4399 ADD_LDB_INT(ERR_NAMING_VIOLATION);
4400 ADD_LDB_INT(ERR_OBJECT_CLASS_VIOLATION);
4401 ADD_LDB_INT(ERR_NOT_ALLOWED_ON_NON_LEAF);
4402 ADD_LDB_INT(ERR_NOT_ALLOWED_ON_RDN);
4403 ADD_LDB_INT(ERR_ENTRY_ALREADY_EXISTS);
4404 ADD_LDB_INT(ERR_OBJECT_CLASS_MODS_PROHIBITED);
4405 ADD_LDB_INT(ERR_AFFECTS_MULTIPLE_DSAS);
4406 ADD_LDB_INT(ERR_OTHER);
4408 ADD_LDB_INT(FLG_RDONLY);
4409 ADD_LDB_INT(FLG_NOSYNC);
4410 ADD_LDB_INT(FLG_RECONNECT);
4411 ADD_LDB_INT(FLG_NOMMAP);
4412 ADD_LDB_INT(FLG_SHOW_BINARY);
4413 ADD_LDB_INT(FLG_ENABLE_TRACING);
4414 ADD_LDB_INT(FLG_DONT_CREATE_DB);
4416 ADD_LDB_INT(PACKING_FORMAT);
4417 ADD_LDB_INT(PACKING_FORMAT_V2);
4419 /* Historical misspelling */
4420 PyModule_AddIntConstant(m, "ERR_ALIAS_DEREFERINCING_PROBLEM", LDB_ERR_ALIAS_DEREFERENCING_PROBLEM);
4422 PyModule_AddStringConstant(m, "__docformat__", "restructuredText");
4424 PyExc_LdbError = PyErr_NewException(discard_const_p(char, "_ldb.LdbError"), NULL, NULL);
4425 PyModule_AddObject(m, "LdbError", PyExc_LdbError);
4428 Py_INCREF(&PyLdbDn);
4429 Py_INCREF(&PyLdbModule);
4430 Py_INCREF(&PyLdbMessage);
4431 Py_INCREF(&PyLdbMessageElement);
4432 Py_INCREF(&PyLdbTree);
4433 Py_INCREF(&PyLdbResult);
4434 Py_INCREF(&PyLdbControl);
4436 PyModule_AddObject(m, "Ldb", (PyObject *)&PyLdb);
4437 PyModule_AddObject(m, "Dn", (PyObject *)&PyLdbDn);
4438 PyModule_AddObject(m, "Message", (PyObject *)&PyLdbMessage);
4439 PyModule_AddObject(m, "MessageElement", (PyObject *)&PyLdbMessageElement);
4440 PyModule_AddObject(m, "Module", (PyObject *)&PyLdbModule);
4441 PyModule_AddObject(m, "Tree", (PyObject *)&PyLdbTree);
4442 PyModule_AddObject(m, "Control", (PyObject *)&PyLdbControl);
4444 PyModule_AddStringConstant(m, "__version__", PACKAGE_VERSION);
4446 #define ADD_LDB_STRING(val) PyModule_AddStringConstant(m, #val, LDB_## val)
4448 ADD_LDB_STRING(SYNTAX_DN);
4449 ADD_LDB_STRING(SYNTAX_DIRECTORY_STRING);
4450 ADD_LDB_STRING(SYNTAX_INTEGER);
4451 ADD_LDB_STRING(SYNTAX_ORDERED_INTEGER);
4452 ADD_LDB_STRING(SYNTAX_BOOLEAN);
4453 ADD_LDB_STRING(SYNTAX_OCTET_STRING);
4454 ADD_LDB_STRING(SYNTAX_UTC_TIME);
4455 ADD_LDB_STRING(OID_COMPARATOR_AND);
4456 ADD_LDB_STRING(OID_COMPARATOR_OR);
4461 #if PY_MAJOR_VERSION >= 3
4462 PyMODINIT_FUNC PyInit_ldb(void);
4463 PyMODINIT_FUNC PyInit_ldb(void)
4465 return module_init();