pyldb: Free correct context when pyldb_Object_AsDn() fails
[Samba.git] / lib / ldb / pyldb.c
blob8c3162ab0016aea36a56669ef5845942afeab4f8
1 /*
2 Unix SMB/CIFS implementation.
4 Python interface to ldb.
6 Copyright (C) 2005,2006 Tim Potter <tpot@samba.org>
7 Copyright (C) 2006 Simo Sorce <idra@samba.org>
8 Copyright (C) 2007-2010 Jelmer Vernooij <jelmer@samba.org>
9 Copyright (C) 2009-2010 Matthias Dieter Wallnöfer
10 Copyright (C) 2009-2011 Andrew Tridgell
11 Copyright (C) 2009-2011 Andrew Bartlett
13 ** NOTE! The following LGPL license applies to the ldb
14 ** library. This does NOT imply that all of Samba is released
15 ** under the LGPL
17 This library is free software; you can redistribute it and/or
18 modify it under the terms of the GNU Lesser General Public
19 License as published by the Free Software Foundation; either
20 version 3 of the License, or (at your option) any later version.
22 This library is distributed in the hope that it will be useful,
23 but WITHOUT ANY WARRANTY; without even the implied warranty of
24 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
25 Lesser General Public License for more details.
27 You should have received a copy of the GNU Lesser General Public
28 License along with this library; if not, see <http://www.gnu.org/licenses/>.
31 #include <Python.h>
32 #include "ldb_private.h"
33 #include "ldb_handlers.h"
34 #include "pyldb.h"
36 void initldb(void);
37 static PyObject *PyLdbMessage_FromMessage(struct ldb_message *msg);
38 static PyObject *PyExc_LdbError;
40 static PyTypeObject PyLdbControl;
41 static PyTypeObject PyLdbResult;
42 static PyTypeObject PyLdbMessage;
43 #define PyLdbMessage_Check(ob) PyObject_TypeCheck(ob, &PyLdbMessage)
44 static PyTypeObject PyLdbModule;
45 static PyTypeObject PyLdbDn;
46 #define pyldb_Dn_Check(ob) PyObject_TypeCheck(ob, &PyLdbDn)
47 static PyTypeObject PyLdb;
48 #define PyLdb_Check(ob) PyObject_TypeCheck(ob, &PyLdb)
49 static PyTypeObject PyLdbMessageElement;
50 #define pyldb_MessageElement_Check(ob) PyObject_TypeCheck(ob, &PyLdbMessageElement)
52 static PyTypeObject PyLdbTree;
53 static PyObject *PyLdb_FromLdbContext(struct ldb_context *ldb_ctx);
54 static PyObject *PyLdbModule_FromModule(struct ldb_module *mod);
55 static struct ldb_message_element *PyObject_AsMessageElement(
56 TALLOC_CTX *mem_ctx,
57 PyObject *set_obj,
58 unsigned int flags,
59 const char *attr_name);
61 #if PY_MAJOR_VERSION >= 3
62 #define PyStr_Check PyUnicode_Check
63 #define PyStr_FromString PyUnicode_FromString
64 #define PyStr_FromStringAndSize PyUnicode_FromStringAndSize
65 #define PyStr_FromFormat PyUnicode_FromFormat
66 #define PyStr_FromFormatV PyUnicode_FromFormatV
67 #define PyStr_AsUTF8 PyUnicode_AsUTF8
68 #define PyStr_AsUTF8AndSize PyUnicode_AsUTF8AndSize
69 #define PyInt_FromLong PyLong_FromLong
70 #else
71 #define PyStr_Check PyString_Check
72 #define PyStr_FromString PyString_FromString
73 #define PyStr_FromStringAndSize PyString_FromStringAndSize
74 #define PyStr_FromFormat PyString_FromFormat
75 #define PyStr_FromFormatV PyString_FromFormatV
76 #define PyStr_AsUTF8 PyString_AsString
78 const char *PyStr_AsUTF8AndSize(PyObject *pystr, Py_ssize_t *sizeptr);
79 const char *
80 PyStr_AsUTF8AndSize(PyObject *pystr, Py_ssize_t *sizeptr)
82 const char * ret = PyString_AsString(pystr);
83 if (ret == NULL)
84 return NULL;
85 *sizeptr = PyString_Size(pystr);
86 return ret;
88 #endif
90 static PyObject *richcmp(int cmp_val, int op)
92 int ret;
93 switch (op) {
94 case Py_LT: ret = cmp_val < 0; break;
95 case Py_LE: ret = cmp_val <= 0; break;
96 case Py_EQ: ret = cmp_val == 0; break;
97 case Py_NE: ret = cmp_val != 0; break;
98 case Py_GT: ret = cmp_val > 0; break;
99 case Py_GE: ret = cmp_val >= 0; break;
100 default:
101 Py_INCREF(Py_NotImplemented);
102 return Py_NotImplemented;
104 return PyBool_FromLong(ret);
108 static PyObject *py_ldb_control_str(PyLdbControlObject *self)
110 if (self->data != NULL) {
111 char* control = ldb_control_to_string(self->mem_ctx, self->data);
112 if (control == NULL) {
113 PyErr_NoMemory();
114 return NULL;
116 return PyStr_FromString(control);
117 } else {
118 return PyStr_FromString("ldb control");
122 static void py_ldb_control_dealloc(PyLdbControlObject *self)
124 if (self->mem_ctx != NULL) {
125 talloc_free(self->mem_ctx);
127 self->data = NULL;
128 Py_TYPE(self)->tp_free(self);
131 /* Create a text (rather than bytes) interface for a LDB result object */
132 static PyObject *wrap_text(const char *type, PyObject *wrapped)
134 PyObject *mod, *cls, *constructor, *inst;
135 mod = PyImport_ImportModule("_ldb_text");
136 if (mod == NULL)
137 return NULL;
138 cls = PyObject_GetAttrString(mod, type);
139 Py_DECREF(mod);
140 if (cls == NULL) {
141 Py_DECREF(mod);
142 return NULL;
144 constructor = PyObject_GetAttrString(cls, "_wrap");
145 Py_DECREF(cls);
146 if (constructor == NULL) {
147 return NULL;
149 inst = PyObject_CallFunction(constructor, discard_const_p(char, "O"), wrapped);
150 Py_DECREF(constructor);
151 return inst;
154 static PyObject *py_ldb_control_get_oid(PyLdbControlObject *self)
156 return PyStr_FromString(self->data->oid);
159 static PyObject *py_ldb_control_get_critical(PyLdbControlObject *self)
161 return PyBool_FromLong(self->data->critical);
164 static PyObject *py_ldb_control_set_critical(PyLdbControlObject *self, PyObject *value, void *closure)
166 if (PyObject_IsTrue(value)) {
167 self->data->critical = true;
168 } else {
169 self->data->critical = false;
171 return 0;
174 static PyObject *py_ldb_control_new(PyTypeObject *type, PyObject *args, PyObject *kwargs)
176 char *data = NULL;
177 const char * const kwnames[] = { "ldb", "data", NULL };
178 struct ldb_control *parsed_controls;
179 PyLdbControlObject *ret;
180 PyObject *py_ldb;
181 TALLOC_CTX *mem_ctx;
182 struct ldb_context *ldb_ctx;
184 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "O!s",
185 discard_const_p(char *, kwnames),
186 &PyLdb, &py_ldb, &data))
187 return NULL;
189 mem_ctx = talloc_new(NULL);
190 if (mem_ctx == NULL) {
191 PyErr_NoMemory();
192 return NULL;
195 ldb_ctx = pyldb_Ldb_AsLdbContext(py_ldb);
196 parsed_controls = ldb_parse_control_from_string(ldb_ctx, mem_ctx, data);
198 if (!parsed_controls) {
199 talloc_free(mem_ctx);
200 PyErr_SetString(PyExc_ValueError, "unable to parse control string");
201 return NULL;
204 ret = PyObject_New(PyLdbControlObject, type);
205 if (ret == NULL) {
206 PyErr_NoMemory();
207 talloc_free(mem_ctx);
208 return NULL;
211 ret->mem_ctx = mem_ctx;
213 ret->data = talloc_move(mem_ctx, &parsed_controls);
214 if (ret->data == NULL) {
215 Py_DECREF(ret);
216 PyErr_NoMemory();
217 talloc_free(mem_ctx);
218 return NULL;
221 return (PyObject *)ret;
224 static PyGetSetDef py_ldb_control_getset[] = {
225 { discard_const_p(char, "oid"), (getter)py_ldb_control_get_oid, NULL, NULL },
226 { discard_const_p(char, "critical"), (getter)py_ldb_control_get_critical, (setter)py_ldb_control_set_critical, NULL },
227 { NULL }
230 static PyTypeObject PyLdbControl = {
231 .tp_name = "ldb.control",
232 .tp_dealloc = (destructor)py_ldb_control_dealloc,
233 .tp_getattro = PyObject_GenericGetAttr,
234 .tp_basicsize = sizeof(PyLdbControlObject),
235 .tp_getset = py_ldb_control_getset,
236 .tp_doc = "LDB control.",
237 .tp_str = (reprfunc)py_ldb_control_str,
238 .tp_new = py_ldb_control_new,
239 .tp_flags = Py_TPFLAGS_DEFAULT|Py_TPFLAGS_BASETYPE,
242 static void PyErr_SetLdbError(PyObject *error, int ret, struct ldb_context *ldb_ctx)
244 if (ret == LDB_ERR_PYTHON_EXCEPTION)
245 return; /* Python exception should already be set, just keep that */
247 PyErr_SetObject(error,
248 Py_BuildValue(discard_const_p(char, "(i,s)"), ret,
249 ldb_ctx == NULL?ldb_strerror(ret):ldb_errstring(ldb_ctx)));
252 static PyObject *PyObject_FromLdbValue(const struct ldb_val *val)
254 return PyBytes_FromStringAndSize((const char *)val->data, val->length);
257 static PyObject *PyStr_FromLdbValue(const struct ldb_val *val)
259 return PyStr_FromStringAndSize((const char *)val->data, val->length);
263 * Create a Python object from a ldb_result.
265 * @param result LDB result to convert
266 * @return Python object with converted result (a list object)
268 static PyObject *PyLdbControl_FromControl(struct ldb_control *control)
270 TALLOC_CTX *ctl_ctx = talloc_new(NULL);
271 PyLdbControlObject *ctrl;
272 if (ctl_ctx == NULL) {
273 PyErr_NoMemory();
274 return NULL;
277 ctrl = (PyLdbControlObject *)PyLdbControl.tp_alloc(&PyLdbControl, 0);
278 if (ctrl == NULL) {
279 talloc_free(ctl_ctx);
280 PyErr_NoMemory();
281 return NULL;
283 ctrl->mem_ctx = ctl_ctx;
284 ctrl->data = talloc_steal(ctrl->mem_ctx, control);
285 if (ctrl->data == NULL) {
286 Py_DECREF(ctrl);
287 PyErr_NoMemory();
288 return NULL;
290 return (PyObject*) ctrl;
294 * Create a Python object from a ldb_result.
296 * @param result LDB result to convert
297 * @return Python object with converted result (a list object)
299 static PyObject *PyLdbResult_FromResult(struct ldb_result *result)
301 PyLdbResultObject *ret;
302 PyObject *list, *controls, *referals;
303 Py_ssize_t i;
305 if (result == NULL) {
306 Py_RETURN_NONE;
309 ret = (PyLdbResultObject *)PyLdbResult.tp_alloc(&PyLdbResult, 0);
310 if (ret == NULL) {
311 PyErr_NoMemory();
312 return NULL;
315 list = PyList_New(result->count);
316 if (list == NULL) {
317 PyErr_NoMemory();
318 Py_DECREF(ret);
319 return NULL;
322 for (i = 0; i < result->count; i++) {
323 PyList_SetItem(list, i, PyLdbMessage_FromMessage(result->msgs[i]));
326 ret->mem_ctx = talloc_new(NULL);
327 if (ret->mem_ctx == NULL) {
328 Py_DECREF(list);
329 Py_DECREF(ret);
330 PyErr_NoMemory();
331 return NULL;
334 ret->msgs = list;
336 if (result->controls) {
337 i = 0;
338 while (result->controls[i]) {
339 i++;
341 controls = PyList_New(i);
342 if (controls == NULL) {
343 Py_DECREF(ret);
344 PyErr_NoMemory();
345 return NULL;
347 for (i=0; result->controls[i]; i++) {
348 PyObject *ctrl = (PyObject*) PyLdbControl_FromControl(result->controls[i]);
349 if (ctrl == NULL) {
350 Py_DECREF(ret);
351 Py_DECREF(controls);
352 PyErr_NoMemory();
353 return NULL;
355 PyList_SetItem(controls, i, ctrl);
357 } else {
359 * No controls so we keep an empty list
361 controls = PyList_New(0);
362 if (controls == NULL) {
363 Py_DECREF(ret);
364 PyErr_NoMemory();
365 return NULL;
369 ret->controls = controls;
371 i = 0;
373 while (result->refs && result->refs[i]) {
374 i++;
377 referals = PyList_New(i);
378 if (referals == NULL) {
379 Py_DECREF(ret);
380 PyErr_NoMemory();
381 return NULL;
384 for (i = 0;result->refs && result->refs[i]; i++) {
385 PyList_SetItem(referals, i, PyStr_FromString(result->refs[i]));
387 ret->referals = referals;
388 return (PyObject *)ret;
392 * Create a LDB Result from a Python object.
393 * If conversion fails, NULL will be returned and a Python exception set.
395 * Note: the result object only includes the messages at the moment; extended
396 * result, controls and referrals are ignored.
398 * @param mem_ctx Memory context in which to allocate the LDB Result
399 * @param obj Python object to convert
400 * @return a ldb_result, or NULL if the conversion failed
402 static struct ldb_result *PyLdbResult_AsResult(TALLOC_CTX *mem_ctx,
403 PyObject *obj)
405 struct ldb_result *res;
406 Py_ssize_t i;
408 if (obj == Py_None)
409 return NULL;
411 res = talloc_zero(mem_ctx, struct ldb_result);
412 res->count = PyList_Size(obj);
413 res->msgs = talloc_array(res, struct ldb_message *, res->count);
414 for (i = 0; i < res->count; i++) {
415 PyObject *item = PyList_GetItem(obj, i);
416 res->msgs[i] = pyldb_Message_AsMessage(item);
418 return res;
421 static PyObject *py_ldb_dn_validate(PyLdbDnObject *self)
423 return PyBool_FromLong(ldb_dn_validate(self->dn));
426 static PyObject *py_ldb_dn_is_valid(PyLdbDnObject *self)
428 return PyBool_FromLong(ldb_dn_is_valid(self->dn));
431 static PyObject *py_ldb_dn_is_special(PyLdbDnObject *self)
433 return PyBool_FromLong(ldb_dn_is_special(self->dn));
436 static PyObject *py_ldb_dn_is_null(PyLdbDnObject *self)
438 return PyBool_FromLong(ldb_dn_is_null(self->dn));
441 static PyObject *py_ldb_dn_get_casefold(PyLdbDnObject *self)
443 return PyStr_FromString(ldb_dn_get_casefold(self->dn));
446 static PyObject *py_ldb_dn_get_linearized(PyLdbDnObject *self)
448 return PyStr_FromString(ldb_dn_get_linearized(self->dn));
451 static PyObject *py_ldb_dn_canonical_str(PyLdbDnObject *self)
453 return PyStr_FromString(ldb_dn_canonical_string(self->dn, self->dn));
456 static PyObject *py_ldb_dn_canonical_ex_str(PyLdbDnObject *self)
458 return PyStr_FromString(ldb_dn_canonical_ex_string(self->dn, self->dn));
461 static PyObject *py_ldb_dn_extended_str(PyLdbDnObject *self, PyObject *args, PyObject *kwargs)
463 const char * const kwnames[] = { "mode", NULL };
464 int mode = 1;
465 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "|i",
466 discard_const_p(char *, kwnames),
467 &mode))
468 return NULL;
469 return PyStr_FromString(ldb_dn_get_extended_linearized(self->dn, self->dn, mode));
472 static PyObject *py_ldb_dn_get_extended_component(PyLdbDnObject *self, PyObject *args)
474 char *name;
475 const struct ldb_val *val;
477 if (!PyArg_ParseTuple(args, "s", &name))
478 return NULL;
479 val = ldb_dn_get_extended_component(self->dn, name);
480 if (val == NULL) {
481 Py_RETURN_NONE;
484 return PyBytes_FromStringAndSize((const char *)val->data, val->length);
487 static PyObject *py_ldb_dn_set_extended_component(PyLdbDnObject *self, PyObject *args)
489 char *name;
490 int err;
491 uint8_t *value;
492 Py_ssize_t size = 0;
494 if (!PyArg_ParseTuple(args, "sz#", &name, (const char**)&value, &size))
495 return NULL;
497 if (value == NULL) {
498 err = ldb_dn_set_extended_component(self->dn, name, NULL);
499 } else {
500 struct ldb_val val;
501 val.data = (uint8_t *)value;
502 val.length = size;
503 err = ldb_dn_set_extended_component(self->dn, name, &val);
506 if (err != LDB_SUCCESS) {
507 PyErr_SetString(PyExc_TypeError, "Failed to set extended component");
508 return NULL;
511 Py_RETURN_NONE;
514 static PyObject *py_ldb_dn_repr(PyLdbDnObject *self)
516 PyObject *str = PyStr_FromString(ldb_dn_get_linearized(self->dn));
517 PyObject *repr, *result;
518 if (str == NULL)
519 return NULL;
520 repr = PyObject_Repr(str);
521 if (repr == NULL) {
522 Py_DECREF(str);
523 return NULL;
525 result = PyStr_FromFormat("Dn(%s)", PyStr_AsUTF8(repr));
526 Py_DECREF(str);
527 Py_DECREF(repr);
528 return result;
531 static PyObject *py_ldb_dn_check_special(PyLdbDnObject *self, PyObject *args)
533 char *name;
535 if (!PyArg_ParseTuple(args, "s", &name))
536 return NULL;
538 return PyBool_FromLong(ldb_dn_check_special(self->dn, name));
541 static PyObject *py_ldb_dn_richcmp(PyObject *dn1, PyObject *dn2, int op)
543 int ret;
544 if (!pyldb_Dn_Check(dn2)) {
545 Py_INCREF(Py_NotImplemented);
546 return Py_NotImplemented;
548 ret = ldb_dn_compare(pyldb_Dn_AsDn(dn1), pyldb_Dn_AsDn(dn2));
549 return richcmp(ret, op);
552 static PyObject *py_ldb_dn_get_parent(PyLdbDnObject *self)
554 struct ldb_dn *dn = pyldb_Dn_AsDn((PyObject *)self);
555 struct ldb_dn *parent;
556 PyLdbDnObject *py_ret;
557 TALLOC_CTX *mem_ctx = talloc_new(NULL);
559 parent = ldb_dn_get_parent(mem_ctx, dn);
560 if (parent == NULL) {
561 talloc_free(mem_ctx);
562 Py_RETURN_NONE;
565 py_ret = (PyLdbDnObject *)PyLdbDn.tp_alloc(&PyLdbDn, 0);
566 if (py_ret == NULL) {
567 PyErr_NoMemory();
568 talloc_free(mem_ctx);
569 return NULL;
571 py_ret->mem_ctx = mem_ctx;
572 py_ret->dn = parent;
573 return (PyObject *)py_ret;
576 static PyObject *py_ldb_dn_add_child(PyLdbDnObject *self, PyObject *args)
578 PyObject *py_other;
579 struct ldb_dn *dn, *other;
580 if (!PyArg_ParseTuple(args, "O", &py_other))
581 return NULL;
583 dn = pyldb_Dn_AsDn((PyObject *)self);
585 if (!pyldb_Object_AsDn(NULL, py_other, ldb_dn_get_ldb_context(dn), &other))
586 return NULL;
588 return PyBool_FromLong(ldb_dn_add_child(dn, other));
591 static PyObject *py_ldb_dn_add_base(PyLdbDnObject *self, PyObject *args)
593 PyObject *py_other;
594 struct ldb_dn *other, *dn;
595 if (!PyArg_ParseTuple(args, "O", &py_other))
596 return NULL;
598 dn = pyldb_Dn_AsDn((PyObject *)self);
600 if (!pyldb_Object_AsDn(NULL, py_other, ldb_dn_get_ldb_context(dn), &other))
601 return NULL;
603 return PyBool_FromLong(ldb_dn_add_base(dn, other));
606 static PyObject *py_ldb_dn_remove_base_components(PyLdbDnObject *self, PyObject *args)
608 struct ldb_dn *dn;
609 int i;
610 if (!PyArg_ParseTuple(args, "i", &i))
611 return NULL;
613 dn = pyldb_Dn_AsDn((PyObject *)self);
615 return PyBool_FromLong(ldb_dn_remove_base_components(dn, i));
618 static PyObject *py_ldb_dn_is_child_of(PyLdbDnObject *self, PyObject *args)
620 PyObject *py_base;
621 struct ldb_dn *dn, *base;
622 if (!PyArg_ParseTuple(args, "O", &py_base))
623 return NULL;
625 dn = pyldb_Dn_AsDn((PyObject *)self);
627 if (!pyldb_Object_AsDn(NULL, py_base, ldb_dn_get_ldb_context(dn), &base))
628 return NULL;
630 return PyBool_FromLong(ldb_dn_compare_base(base, dn) == 0);
633 static PyObject *py_ldb_dn_get_component_name(PyLdbDnObject *self, PyObject *args)
635 struct ldb_dn *dn;
636 const char *name;
637 unsigned int num = 0;
639 if (!PyArg_ParseTuple(args, "I", &num))
640 return NULL;
642 dn = pyldb_Dn_AsDn((PyObject *)self);
644 name = ldb_dn_get_component_name(dn, num);
645 if (name == NULL) {
646 Py_RETURN_NONE;
649 return PyStr_FromString(name);
652 static PyObject *py_ldb_dn_get_component_value(PyLdbDnObject *self, PyObject *args)
654 struct ldb_dn *dn;
655 const struct ldb_val *val;
656 unsigned int num = 0;
658 if (!PyArg_ParseTuple(args, "I", &num))
659 return NULL;
661 dn = pyldb_Dn_AsDn((PyObject *)self);
663 val = ldb_dn_get_component_val(dn, num);
664 if (val == NULL) {
665 Py_RETURN_NONE;
668 return PyStr_FromLdbValue(val);
671 static PyObject *py_ldb_dn_set_component(PyLdbDnObject *self, PyObject *args)
673 unsigned int num = 0;
674 char *name = NULL, *value = NULL;
675 struct ldb_val val = { NULL, };
676 int err;
677 Py_ssize_t size = 0;
679 if (!PyArg_ParseTuple(args, "Iss#", &num, &name, &value, &size))
680 return NULL;
682 val.data = (unsigned char*) value;
683 val.length = size;
685 err = ldb_dn_set_component(self->dn, num, name, val);
686 if (err != LDB_SUCCESS) {
687 PyErr_SetString(PyExc_TypeError, "Failed to set component");
688 return NULL;
691 Py_RETURN_NONE;
694 static PyObject *py_ldb_dn_get_rdn_name(PyLdbDnObject *self)
696 struct ldb_dn *dn;
697 const char *name;
699 dn = pyldb_Dn_AsDn((PyObject *)self);
701 name = ldb_dn_get_rdn_name(dn);
702 if (name == NULL) {
703 Py_RETURN_NONE;
706 return PyStr_FromString(name);
709 static PyObject *py_ldb_dn_get_rdn_value(PyLdbDnObject *self)
711 struct ldb_dn *dn;
712 const struct ldb_val *val;
714 dn = pyldb_Dn_AsDn((PyObject *)self);
716 val = ldb_dn_get_rdn_val(dn);
717 if (val == NULL) {
718 Py_RETURN_NONE;
721 return PyStr_FromLdbValue(val);
724 static PyMethodDef py_ldb_dn_methods[] = {
725 { "validate", (PyCFunction)py_ldb_dn_validate, METH_NOARGS,
726 "S.validate() -> bool\n"
727 "Validate DN is correct." },
728 { "is_valid", (PyCFunction)py_ldb_dn_is_valid, METH_NOARGS,
729 "S.is_valid() -> bool\n" },
730 { "is_special", (PyCFunction)py_ldb_dn_is_special, METH_NOARGS,
731 "S.is_special() -> bool\n"
732 "Check whether this is a special LDB DN." },
733 { "is_null", (PyCFunction)py_ldb_dn_is_null, METH_NOARGS,
734 "Check whether this is a null DN." },
735 { "get_casefold", (PyCFunction)py_ldb_dn_get_casefold, METH_NOARGS,
736 NULL },
737 { "get_linearized", (PyCFunction)py_ldb_dn_get_linearized, METH_NOARGS,
738 NULL },
739 { "canonical_str", (PyCFunction)py_ldb_dn_canonical_str, METH_NOARGS,
740 "S.canonical_str() -> string\n"
741 "Canonical version of this DN (like a posix path)." },
742 { "is_child_of", (PyCFunction)py_ldb_dn_is_child_of, METH_VARARGS,
743 "S.is_child_of(basedn) -> int\nReturns True if this DN is a child of basedn\n"},
744 { "canonical_ex_str", (PyCFunction)py_ldb_dn_canonical_ex_str, METH_NOARGS,
745 "S.canonical_ex_str() -> string\n"
746 "Canonical version of this DN (like a posix path, with terminating newline)." },
747 { "extended_str", (PyCFunction)py_ldb_dn_extended_str, METH_VARARGS | METH_KEYWORDS,
748 "S.extended_str(mode=1) -> string\n"
749 "Extended version of this DN" },
750 { "parent", (PyCFunction)py_ldb_dn_get_parent, METH_NOARGS,
751 "S.parent() -> dn\n"
752 "Get the parent for this DN." },
753 { "add_child", (PyCFunction)py_ldb_dn_add_child, METH_VARARGS,
754 "S.add_child(dn) -> None\n"
755 "Add a child DN to this DN." },
756 { "add_base", (PyCFunction)py_ldb_dn_add_base, METH_VARARGS,
757 "S.add_base(dn) -> None\n"
758 "Add a base DN to this DN." },
759 { "remove_base_components", (PyCFunction)py_ldb_dn_remove_base_components, METH_VARARGS,
760 "S.remove_base_components(int) -> bool\n"
761 "Remove a number of DN components from the base of this DN." },
762 { "check_special", (PyCFunction)py_ldb_dn_check_special, METH_VARARGS,
763 "S.check_special(name) -> bool\n\n"
764 "Check if name is a special DN name"},
765 { "get_extended_component", (PyCFunction)py_ldb_dn_get_extended_component, METH_VARARGS,
766 "S.get_extended_component(name) -> string\n\n"
767 "returns a DN extended component as a binary string"},
768 { "set_extended_component", (PyCFunction)py_ldb_dn_set_extended_component, METH_VARARGS,
769 "S.set_extended_component(name, value) -> None\n\n"
770 "set a DN extended component as a binary string"},
771 { "get_component_name", (PyCFunction)py_ldb_dn_get_component_name, METH_VARARGS,
772 "S.get_component_name(num) -> string\n"
773 "get the attribute name of the specified component" },
774 { "get_component_value", (PyCFunction)py_ldb_dn_get_component_value, METH_VARARGS,
775 "S.get_component_value(num) -> string\n"
776 "get the attribute value of the specified component as a binary string" },
777 { "set_component", (PyCFunction)py_ldb_dn_set_component, METH_VARARGS,
778 "S.get_component_value(num, name, value) -> None\n"
779 "set the attribute name and value of the specified component" },
780 { "get_rdn_name", (PyCFunction)py_ldb_dn_get_rdn_name, METH_NOARGS,
781 "S.get_rdn_name() -> string\n"
782 "get the RDN attribute name" },
783 { "get_rdn_value", (PyCFunction)py_ldb_dn_get_rdn_value, METH_NOARGS,
784 "S.get_rdn_value() -> string\n"
785 "get the RDN attribute value as a binary string" },
786 { NULL }
789 static Py_ssize_t py_ldb_dn_len(PyLdbDnObject *self)
791 return ldb_dn_get_comp_num(pyldb_Dn_AsDn((PyObject *)self));
795 copy a DN as a python object
797 static PyObject *py_ldb_dn_copy(struct ldb_dn *dn)
799 PyLdbDnObject *py_ret;
801 py_ret = (PyLdbDnObject *)PyLdbDn.tp_alloc(&PyLdbDn, 0);
802 if (py_ret == NULL) {
803 PyErr_NoMemory();
804 return NULL;
806 py_ret->mem_ctx = talloc_new(NULL);
807 py_ret->dn = ldb_dn_copy(py_ret->mem_ctx, dn);
808 return (PyObject *)py_ret;
811 static PyObject *py_ldb_dn_concat(PyLdbDnObject *self, PyObject *py_other)
813 struct ldb_dn *dn = pyldb_Dn_AsDn((PyObject *)self),
814 *other;
815 PyLdbDnObject *py_ret;
817 if (!pyldb_Object_AsDn(NULL, py_other, NULL, &other))
818 return NULL;
820 py_ret = (PyLdbDnObject *)PyLdbDn.tp_alloc(&PyLdbDn, 0);
821 if (py_ret == NULL) {
822 PyErr_NoMemory();
823 return NULL;
825 py_ret->mem_ctx = talloc_new(NULL);
826 py_ret->dn = ldb_dn_copy(py_ret->mem_ctx, dn);
827 ldb_dn_add_base(py_ret->dn, other);
828 return (PyObject *)py_ret;
831 static PySequenceMethods py_ldb_dn_seq = {
832 .sq_length = (lenfunc)py_ldb_dn_len,
833 .sq_concat = (binaryfunc)py_ldb_dn_concat,
836 static PyObject *py_ldb_dn_new(PyTypeObject *type, PyObject *args, PyObject *kwargs)
838 struct ldb_dn *ret;
839 char *str;
840 PyObject *py_ldb;
841 struct ldb_context *ldb_ctx;
842 TALLOC_CTX *mem_ctx;
843 PyLdbDnObject *py_ret;
844 const char * const kwnames[] = { "ldb", "dn", NULL };
846 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "Os",
847 discard_const_p(char *, kwnames),
848 &py_ldb, &str))
849 return NULL;
851 if (!PyLdb_Check(py_ldb)) {
852 PyErr_SetString(PyExc_TypeError, "Expected Ldb");
853 return NULL;
856 ldb_ctx = pyldb_Ldb_AsLdbContext(py_ldb);
858 mem_ctx = talloc_new(NULL);
859 if (mem_ctx == NULL) {
860 PyErr_NoMemory();
861 return NULL;
864 ret = ldb_dn_new(mem_ctx, ldb_ctx, str);
865 if (!ldb_dn_validate(ret)) {
866 talloc_free(mem_ctx);
867 PyErr_SetString(PyExc_ValueError, "unable to parse dn string");
868 return NULL;
871 py_ret = (PyLdbDnObject *)type->tp_alloc(type, 0);
872 if (ret == NULL) {
873 talloc_free(mem_ctx);
874 PyErr_NoMemory();
875 return NULL;
877 py_ret->mem_ctx = mem_ctx;
878 py_ret->dn = ret;
879 return (PyObject *)py_ret;
882 static void py_ldb_dn_dealloc(PyLdbDnObject *self)
884 talloc_free(self->mem_ctx);
885 PyObject_Del(self);
888 static PyTypeObject PyLdbDn = {
889 .tp_name = "ldb.Dn",
890 .tp_methods = py_ldb_dn_methods,
891 .tp_str = (reprfunc)py_ldb_dn_get_linearized,
892 .tp_repr = (reprfunc)py_ldb_dn_repr,
893 .tp_richcompare = (richcmpfunc)py_ldb_dn_richcmp,
894 .tp_as_sequence = &py_ldb_dn_seq,
895 .tp_doc = "A LDB distinguished name.",
896 .tp_new = py_ldb_dn_new,
897 .tp_dealloc = (destructor)py_ldb_dn_dealloc,
898 .tp_basicsize = sizeof(PyLdbDnObject),
899 .tp_flags = Py_TPFLAGS_DEFAULT,
902 /* Debug */
903 static void py_ldb_debug(void *context, enum ldb_debug_level level, const char *fmt, va_list ap) PRINTF_ATTRIBUTE(3, 0);
904 static void py_ldb_debug(void *context, enum ldb_debug_level level, const char *fmt, va_list ap)
906 PyObject *fn = (PyObject *)context;
907 PyObject_CallFunction(fn, discard_const_p(char, "(i,O)"), level, PyStr_FromFormatV(fmt, ap));
910 static PyObject *py_ldb_debug_func;
912 static PyObject *py_ldb_set_debug(PyObject *self, PyObject *args)
914 PyObject *cb;
915 struct ldb_context *ldb_ctx;
917 if (!PyArg_ParseTuple(args, "O", &cb))
918 return NULL;
920 if (py_ldb_debug_func != NULL) {
921 Py_DECREF(py_ldb_debug_func);
924 Py_INCREF(cb);
925 /* FIXME: DECREF cb when exiting program */
926 py_ldb_debug_func = cb;
927 ldb_ctx = pyldb_Ldb_AsLdbContext(self);
928 PyErr_LDB_ERROR_IS_ERR_RAISE(PyExc_LdbError,
929 ldb_set_debug(ldb_ctx, py_ldb_debug, cb),
930 ldb_ctx);
932 Py_RETURN_NONE;
935 static PyObject *py_ldb_set_create_perms(PyTypeObject *self, PyObject *args)
937 unsigned int perms;
938 if (!PyArg_ParseTuple(args, "I", &perms))
939 return NULL;
941 ldb_set_create_perms(pyldb_Ldb_AsLdbContext(self), perms);
943 Py_RETURN_NONE;
946 static PyObject *py_ldb_set_modules_dir(PyTypeObject *self, PyObject *args)
948 char *modules_dir;
949 if (!PyArg_ParseTuple(args, "s", &modules_dir))
950 return NULL;
952 ldb_set_modules_dir(pyldb_Ldb_AsLdbContext(self), modules_dir);
954 Py_RETURN_NONE;
957 static PyObject *py_ldb_transaction_start(PyLdbObject *self)
959 struct ldb_context *ldb_ctx = pyldb_Ldb_AsLdbContext(self);
960 int ldb_err;
961 ldb_err = ldb_transaction_start(ldb_ctx);
962 PyErr_LDB_ERROR_IS_ERR_RAISE(PyExc_LdbError, ldb_err, ldb_ctx);
963 Py_RETURN_NONE;
966 static PyObject *py_ldb_transaction_commit(PyLdbObject *self)
968 struct ldb_context *ldb_ctx = pyldb_Ldb_AsLdbContext(self);
969 int ldb_err;
970 ldb_err = ldb_transaction_commit(ldb_ctx);
971 PyErr_LDB_ERROR_IS_ERR_RAISE(PyExc_LdbError, ldb_err, ldb_ctx);
972 Py_RETURN_NONE;
975 static PyObject *py_ldb_transaction_prepare_commit(PyLdbObject *self)
977 struct ldb_context *ldb_ctx = pyldb_Ldb_AsLdbContext(self);
978 int ldb_err;
979 ldb_err = ldb_transaction_prepare_commit(ldb_ctx);
980 PyErr_LDB_ERROR_IS_ERR_RAISE(PyExc_LdbError, ldb_err, ldb_ctx);
981 Py_RETURN_NONE;
984 static PyObject *py_ldb_transaction_cancel(PyLdbObject *self)
986 struct ldb_context *ldb_ctx = pyldb_Ldb_AsLdbContext(self);
987 int ldb_err;
988 ldb_err = ldb_transaction_cancel(ldb_ctx);
989 PyErr_LDB_ERROR_IS_ERR_RAISE(PyExc_LdbError, ldb_err, ldb_ctx);
990 Py_RETURN_NONE;
993 static PyObject *py_ldb_setup_wellknown_attributes(PyLdbObject *self)
995 struct ldb_context *ldb_ctx = pyldb_Ldb_AsLdbContext(self);
996 int ldb_err;
997 ldb_err = ldb_setup_wellknown_attributes(ldb_ctx);
998 PyErr_LDB_ERROR_IS_ERR_RAISE(PyExc_LdbError, ldb_err, ldb_ctx);
999 Py_RETURN_NONE;
1002 static PyObject *py_ldb_repr(PyLdbObject *self)
1004 return PyStr_FromString("<ldb connection>");
1007 static PyObject *py_ldb_get_root_basedn(PyLdbObject *self)
1009 struct ldb_dn *dn = ldb_get_root_basedn(pyldb_Ldb_AsLdbContext(self));
1010 if (dn == NULL)
1011 Py_RETURN_NONE;
1012 return py_ldb_dn_copy(dn);
1016 static PyObject *py_ldb_get_schema_basedn(PyLdbObject *self)
1018 struct ldb_dn *dn = ldb_get_schema_basedn(pyldb_Ldb_AsLdbContext(self));
1019 if (dn == NULL)
1020 Py_RETURN_NONE;
1021 return py_ldb_dn_copy(dn);
1024 static PyObject *py_ldb_get_config_basedn(PyLdbObject *self)
1026 struct ldb_dn *dn = ldb_get_config_basedn(pyldb_Ldb_AsLdbContext(self));
1027 if (dn == NULL)
1028 Py_RETURN_NONE;
1029 return py_ldb_dn_copy(dn);
1032 static PyObject *py_ldb_get_default_basedn(PyLdbObject *self)
1034 struct ldb_dn *dn = ldb_get_default_basedn(pyldb_Ldb_AsLdbContext(self));
1035 if (dn == NULL)
1036 Py_RETURN_NONE;
1037 return py_ldb_dn_copy(dn);
1040 static const char **PyList_AsStrList(TALLOC_CTX *mem_ctx, PyObject *list,
1041 const char *paramname)
1043 const char **ret;
1044 Py_ssize_t i;
1045 if (!PyList_Check(list)) {
1046 PyErr_Format(PyExc_TypeError, "%s is not a list", paramname);
1047 return NULL;
1049 ret = talloc_array(NULL, const char *, PyList_Size(list)+1);
1050 if (ret == NULL) {
1051 PyErr_NoMemory();
1052 return NULL;
1055 for (i = 0; i < PyList_Size(list); i++) {
1056 const char *str = NULL;
1057 Py_ssize_t size;
1058 PyObject *item = PyList_GetItem(list, i);
1059 if (!PyStr_Check(item)) {
1060 PyErr_Format(PyExc_TypeError, "%s should be strings", paramname);
1061 talloc_free(ret);
1062 return NULL;
1064 str = PyStr_AsUTF8AndSize(item, &size);
1065 if (str == NULL) {
1066 talloc_free(ret);
1067 return NULL;
1069 ret[i] = talloc_strndup(ret, str, size);
1071 ret[i] = NULL;
1072 return ret;
1075 static int py_ldb_init(PyLdbObject *self, PyObject *args, PyObject *kwargs)
1077 const char * const kwnames[] = { "url", "flags", "options", NULL };
1078 char *url = NULL;
1079 PyObject *py_options = Py_None;
1080 const char **options;
1081 unsigned int flags = 0;
1082 int ret;
1083 struct ldb_context *ldb;
1085 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "|zIO:Ldb.__init__",
1086 discard_const_p(char *, kwnames),
1087 &url, &flags, &py_options))
1088 return -1;
1090 ldb = pyldb_Ldb_AsLdbContext(self);
1092 if (py_options == Py_None) {
1093 options = NULL;
1094 } else {
1095 options = PyList_AsStrList(ldb, py_options, "options");
1096 if (options == NULL)
1097 return -1;
1100 if (url != NULL) {
1101 ret = ldb_connect(ldb, url, flags, options);
1102 if (ret != LDB_SUCCESS) {
1103 PyErr_SetLdbError(PyExc_LdbError, ret, ldb);
1104 return -1;
1108 talloc_free(options);
1109 return 0;
1112 static PyObject *py_ldb_new(PyTypeObject *type, PyObject *args, PyObject *kwargs)
1114 PyLdbObject *ret;
1115 struct ldb_context *ldb;
1116 ret = (PyLdbObject *)type->tp_alloc(type, 0);
1117 if (ret == NULL) {
1118 PyErr_NoMemory();
1119 return NULL;
1121 ret->mem_ctx = talloc_new(NULL);
1122 ldb = ldb_init(ret->mem_ctx, NULL);
1124 if (ldb == NULL) {
1125 PyErr_NoMemory();
1126 return NULL;
1129 ret->ldb_ctx = ldb;
1130 return (PyObject *)ret;
1133 static PyObject *py_ldb_connect(PyLdbObject *self, PyObject *args, PyObject *kwargs)
1135 char *url;
1136 unsigned int flags = 0;
1137 PyObject *py_options = Py_None;
1138 int ret;
1139 const char **options;
1140 const char * const kwnames[] = { "url", "flags", "options", NULL };
1141 struct ldb_context *ldb_ctx;
1143 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "|zIO",
1144 discard_const_p(char *, kwnames),
1145 &url, &flags, &py_options))
1146 return NULL;
1148 if (py_options == Py_None) {
1149 options = NULL;
1150 } else {
1151 options = PyList_AsStrList(NULL, py_options, "options");
1152 if (options == NULL)
1153 return NULL;
1156 ldb_ctx = pyldb_Ldb_AsLdbContext(self);
1157 ret = ldb_connect(ldb_ctx, url, flags, options);
1158 talloc_free(options);
1160 PyErr_LDB_ERROR_IS_ERR_RAISE(PyExc_LdbError, ret, ldb_ctx);
1162 Py_RETURN_NONE;
1165 static PyObject *py_ldb_modify(PyLdbObject *self, PyObject *args, PyObject *kwargs)
1167 PyObject *py_msg;
1168 PyObject *py_controls = Py_None;
1169 struct ldb_context *ldb_ctx;
1170 struct ldb_request *req;
1171 struct ldb_control **parsed_controls;
1172 struct ldb_message *msg;
1173 int ret;
1174 TALLOC_CTX *mem_ctx;
1175 bool validate=true;
1176 const char * const kwnames[] = { "message", "controls", "validate", NULL };
1178 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "O|Ob",
1179 discard_const_p(char *, kwnames),
1180 &py_msg, &py_controls, &validate))
1181 return NULL;
1183 mem_ctx = talloc_new(NULL);
1184 if (mem_ctx == NULL) {
1185 PyErr_NoMemory();
1186 return NULL;
1188 ldb_ctx = pyldb_Ldb_AsLdbContext(self);
1190 if (py_controls == Py_None) {
1191 parsed_controls = NULL;
1192 } else {
1193 const char **controls = PyList_AsStrList(mem_ctx, py_controls, "controls");
1194 if (controls == NULL) {
1195 talloc_free(mem_ctx);
1196 return NULL;
1198 parsed_controls = ldb_parse_control_strings(ldb_ctx, mem_ctx, controls);
1199 talloc_free(controls);
1202 if (!PyLdbMessage_Check(py_msg)) {
1203 PyErr_SetString(PyExc_TypeError, "Expected Ldb Message");
1204 talloc_free(mem_ctx);
1205 return NULL;
1207 msg = pyldb_Message_AsMessage(py_msg);
1209 if (validate) {
1210 ret = ldb_msg_sanity_check(ldb_ctx, msg);
1211 if (ret != LDB_SUCCESS) {
1212 PyErr_SetLdbError(PyExc_LdbError, ret, ldb_ctx);
1213 talloc_free(mem_ctx);
1214 return NULL;
1218 ret = ldb_build_mod_req(&req, ldb_ctx, mem_ctx, msg, parsed_controls,
1219 NULL, ldb_op_default_callback, NULL);
1220 if (ret != LDB_SUCCESS) {
1221 PyErr_SetString(PyExc_TypeError, "failed to build request");
1222 talloc_free(mem_ctx);
1223 return NULL;
1226 /* do request and autostart a transaction */
1227 /* Then let's LDB handle the message error in case of pb as they are meaningful */
1229 ret = ldb_transaction_start(ldb_ctx);
1230 if (ret != LDB_SUCCESS) {
1231 talloc_free(mem_ctx);
1232 PyErr_SetLdbError(PyExc_LdbError, ret, ldb_ctx);
1233 return NULL;
1236 ret = ldb_request(ldb_ctx, req);
1237 if (ret == LDB_SUCCESS) {
1238 ret = ldb_wait(req->handle, LDB_WAIT_ALL);
1241 if (ret == LDB_SUCCESS) {
1242 ret = ldb_transaction_commit(ldb_ctx);
1243 } else {
1244 ldb_transaction_cancel(ldb_ctx);
1247 talloc_free(mem_ctx);
1248 PyErr_LDB_ERROR_IS_ERR_RAISE(PyExc_LdbError, ret, ldb_ctx);
1250 Py_RETURN_NONE;
1255 * Obtain a ldb message from a Python Dictionary object.
1257 * @param mem_ctx Memory context
1258 * @param py_obj Python Dictionary object
1259 * @param ldb_ctx LDB context
1260 * @param mod_flags Flags to be set on every message element
1261 * @return ldb_message on success or NULL on failure
1263 static struct ldb_message *PyDict_AsMessage(TALLOC_CTX *mem_ctx,
1264 PyObject *py_obj,
1265 struct ldb_context *ldb_ctx,
1266 unsigned int mod_flags)
1268 struct ldb_message *msg;
1269 unsigned int msg_pos = 0;
1270 Py_ssize_t dict_pos = 0;
1271 PyObject *key, *value;
1272 struct ldb_message_element *msg_el;
1273 PyObject *dn_value = PyDict_GetItemString(py_obj, "dn");
1275 msg = ldb_msg_new(mem_ctx);
1276 if (msg == NULL) {
1277 PyErr_NoMemory();
1278 return NULL;
1280 msg->elements = talloc_zero_array(msg, struct ldb_message_element, PyDict_Size(py_obj));
1282 if (dn_value) {
1283 if (!pyldb_Object_AsDn(msg, dn_value, ldb_ctx, &msg->dn)) {
1284 PyErr_SetString(PyExc_TypeError, "unable to import dn object");
1285 return NULL;
1287 if (msg->dn == NULL) {
1288 PyErr_SetString(PyExc_TypeError, "dn set but not found");
1289 return NULL;
1291 } else {
1292 PyErr_SetString(PyExc_TypeError, "no dn set");
1293 return NULL;
1296 while (PyDict_Next(py_obj, &dict_pos, &key, &value)) {
1297 char *key_str = PyStr_AsUTF8(key);
1298 if (ldb_attr_cmp(key_str, "dn") != 0) {
1299 msg_el = PyObject_AsMessageElement(msg->elements, value,
1300 mod_flags, key_str);
1301 if (msg_el == NULL) {
1302 PyErr_Format(PyExc_TypeError, "unable to import element '%s'", key_str);
1303 return NULL;
1305 memcpy(&msg->elements[msg_pos], msg_el, sizeof(*msg_el));
1306 msg_pos++;
1310 msg->num_elements = msg_pos;
1312 return msg;
1315 static PyObject *py_ldb_add(PyLdbObject *self, PyObject *args, PyObject *kwargs)
1317 PyObject *py_obj;
1318 int ret;
1319 struct ldb_context *ldb_ctx;
1320 struct ldb_request *req;
1321 struct ldb_message *msg = NULL;
1322 PyObject *py_controls = Py_None;
1323 TALLOC_CTX *mem_ctx;
1324 struct ldb_control **parsed_controls;
1325 const char * const kwnames[] = { "message", "controls", NULL };
1327 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "O|O",
1328 discard_const_p(char *, kwnames),
1329 &py_obj, &py_controls))
1330 return NULL;
1332 mem_ctx = talloc_new(NULL);
1333 if (mem_ctx == NULL) {
1334 PyErr_NoMemory();
1335 return NULL;
1337 ldb_ctx = pyldb_Ldb_AsLdbContext(self);
1339 if (py_controls == Py_None) {
1340 parsed_controls = NULL;
1341 } else {
1342 const char **controls = PyList_AsStrList(mem_ctx, py_controls, "controls");
1343 if (controls == NULL) {
1344 talloc_free(mem_ctx);
1345 return NULL;
1347 parsed_controls = ldb_parse_control_strings(ldb_ctx, mem_ctx, controls);
1348 talloc_free(controls);
1351 if (PyLdbMessage_Check(py_obj)) {
1352 msg = pyldb_Message_AsMessage(py_obj);
1353 } else if (PyDict_Check(py_obj)) {
1354 msg = PyDict_AsMessage(mem_ctx, py_obj, ldb_ctx, LDB_FLAG_MOD_ADD);
1355 } else {
1356 PyErr_SetString(PyExc_TypeError,
1357 "Dictionary or LdbMessage object expected!");
1360 if (!msg) {
1361 /* we should have a PyErr already set */
1362 talloc_free(mem_ctx);
1363 return NULL;
1366 ret = ldb_msg_sanity_check(ldb_ctx, msg);
1367 if (ret != LDB_SUCCESS) {
1368 PyErr_SetLdbError(PyExc_LdbError, ret, ldb_ctx);
1369 talloc_free(mem_ctx);
1370 return NULL;
1373 ret = ldb_build_add_req(&req, ldb_ctx, mem_ctx, msg, parsed_controls,
1374 NULL, ldb_op_default_callback, NULL);
1375 if (ret != LDB_SUCCESS) {
1376 PyErr_SetString(PyExc_TypeError, "failed to build request");
1377 talloc_free(mem_ctx);
1378 return NULL;
1381 /* do request and autostart a transaction */
1382 /* Then let's LDB handle the message error in case of pb as they are meaningful */
1384 ret = ldb_transaction_start(ldb_ctx);
1385 if (ret != LDB_SUCCESS) {
1386 talloc_free(mem_ctx);
1387 PyErr_SetLdbError(PyExc_LdbError, ret, ldb_ctx);
1388 return NULL;
1391 ret = ldb_request(ldb_ctx, req);
1392 if (ret == LDB_SUCCESS) {
1393 ret = ldb_wait(req->handle, LDB_WAIT_ALL);
1396 if (ret == LDB_SUCCESS) {
1397 ret = ldb_transaction_commit(ldb_ctx);
1398 } else {
1399 ldb_transaction_cancel(ldb_ctx);
1402 talloc_free(mem_ctx);
1403 PyErr_LDB_ERROR_IS_ERR_RAISE(PyExc_LdbError, ret, ldb_ctx);
1405 Py_RETURN_NONE;
1408 static PyObject *py_ldb_delete(PyLdbObject *self, PyObject *args, PyObject *kwargs)
1410 PyObject *py_dn;
1411 struct ldb_dn *dn;
1412 int ret;
1413 struct ldb_context *ldb_ctx;
1414 struct ldb_request *req;
1415 PyObject *py_controls = Py_None;
1416 TALLOC_CTX *mem_ctx;
1417 struct ldb_control **parsed_controls;
1418 const char * const kwnames[] = { "dn", "controls", NULL };
1420 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "O|O",
1421 discard_const_p(char *, kwnames),
1422 &py_dn, &py_controls))
1423 return NULL;
1425 mem_ctx = talloc_new(NULL);
1426 if (mem_ctx == NULL) {
1427 PyErr_NoMemory();
1428 return NULL;
1430 ldb_ctx = pyldb_Ldb_AsLdbContext(self);
1432 if (py_controls == Py_None) {
1433 parsed_controls = NULL;
1434 } else {
1435 const char **controls = PyList_AsStrList(mem_ctx, py_controls, "controls");
1436 if (controls == NULL) {
1437 talloc_free(mem_ctx);
1438 return NULL;
1440 parsed_controls = ldb_parse_control_strings(ldb_ctx, mem_ctx, controls);
1441 talloc_free(controls);
1444 if (!pyldb_Object_AsDn(mem_ctx, py_dn, ldb_ctx, &dn)) {
1445 talloc_free(mem_ctx);
1446 return NULL;
1449 ret = ldb_build_del_req(&req, ldb_ctx, mem_ctx, dn, parsed_controls,
1450 NULL, ldb_op_default_callback, NULL);
1451 if (ret != LDB_SUCCESS) {
1452 PyErr_SetString(PyExc_TypeError, "failed to build request");
1453 talloc_free(mem_ctx);
1454 return NULL;
1457 /* do request and autostart a transaction */
1458 /* Then let's LDB handle the message error in case of pb as they are meaningful */
1460 ret = ldb_transaction_start(ldb_ctx);
1461 if (ret != LDB_SUCCESS) {
1462 talloc_free(mem_ctx);
1463 PyErr_SetLdbError(PyExc_LdbError, ret, ldb_ctx);
1464 return NULL;
1467 ret = ldb_request(ldb_ctx, req);
1468 if (ret == LDB_SUCCESS) {
1469 ret = ldb_wait(req->handle, LDB_WAIT_ALL);
1472 if (ret == LDB_SUCCESS) {
1473 ret = ldb_transaction_commit(ldb_ctx);
1474 } else {
1475 ldb_transaction_cancel(ldb_ctx);
1478 talloc_free(mem_ctx);
1479 PyErr_LDB_ERROR_IS_ERR_RAISE(PyExc_LdbError, ret, ldb_ctx);
1481 Py_RETURN_NONE;
1484 static PyObject *py_ldb_rename(PyLdbObject *self, PyObject *args, PyObject *kwargs)
1486 PyObject *py_dn1, *py_dn2;
1487 struct ldb_dn *dn1, *dn2;
1488 int ret;
1489 TALLOC_CTX *mem_ctx;
1490 PyObject *py_controls = Py_None;
1491 struct ldb_control **parsed_controls;
1492 struct ldb_context *ldb_ctx;
1493 struct ldb_request *req;
1494 const char * const kwnames[] = { "dn1", "dn2", "controls", NULL };
1496 ldb_ctx = pyldb_Ldb_AsLdbContext(self);
1498 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "OO|O",
1499 discard_const_p(char *, kwnames),
1500 &py_dn1, &py_dn2, &py_controls))
1501 return NULL;
1504 mem_ctx = talloc_new(NULL);
1505 if (mem_ctx == NULL) {
1506 PyErr_NoMemory();
1507 return NULL;
1510 if (py_controls == Py_None) {
1511 parsed_controls = NULL;
1512 } else {
1513 const char **controls = PyList_AsStrList(mem_ctx, py_controls, "controls");
1514 if (controls == NULL) {
1515 talloc_free(mem_ctx);
1516 return NULL;
1518 parsed_controls = ldb_parse_control_strings(ldb_ctx, mem_ctx, controls);
1519 talloc_free(controls);
1523 if (!pyldb_Object_AsDn(mem_ctx, py_dn1, ldb_ctx, &dn1)) {
1524 talloc_free(mem_ctx);
1525 return NULL;
1528 if (!pyldb_Object_AsDn(mem_ctx, py_dn2, ldb_ctx, &dn2)) {
1529 talloc_free(mem_ctx);
1530 return NULL;
1533 ret = ldb_build_rename_req(&req, ldb_ctx, mem_ctx, dn1, dn2, parsed_controls,
1534 NULL, ldb_op_default_callback, NULL);
1535 if (ret != LDB_SUCCESS) {
1536 PyErr_SetString(PyExc_TypeError, "failed to build request");
1537 talloc_free(mem_ctx);
1538 return NULL;
1541 /* do request and autostart a transaction */
1542 /* Then let's LDB handle the message error in case of pb as they are meaningful */
1544 ret = ldb_transaction_start(ldb_ctx);
1545 if (ret != LDB_SUCCESS) {
1546 talloc_free(mem_ctx);
1547 PyErr_SetLdbError(PyExc_LdbError, ret, ldb_ctx);
1548 return NULL;
1551 ret = ldb_request(ldb_ctx, req);
1552 if (ret == LDB_SUCCESS) {
1553 ret = ldb_wait(req->handle, LDB_WAIT_ALL);
1556 if (ret == LDB_SUCCESS) {
1557 ret = ldb_transaction_commit(ldb_ctx);
1558 } else {
1559 ldb_transaction_cancel(ldb_ctx);
1562 talloc_free(mem_ctx);
1563 PyErr_LDB_ERROR_IS_ERR_RAISE(PyExc_LdbError, ret, ldb_ctx);
1565 Py_RETURN_NONE;
1568 static PyObject *py_ldb_schema_attribute_remove(PyLdbObject *self, PyObject *args)
1570 char *name;
1571 if (!PyArg_ParseTuple(args, "s", &name))
1572 return NULL;
1574 ldb_schema_attribute_remove(pyldb_Ldb_AsLdbContext(self), name);
1576 Py_RETURN_NONE;
1579 static PyObject *py_ldb_schema_attribute_add(PyLdbObject *self, PyObject *args)
1581 char *attribute, *syntax;
1582 unsigned int flags;
1583 int ret;
1584 struct ldb_context *ldb_ctx;
1586 if (!PyArg_ParseTuple(args, "sIs", &attribute, &flags, &syntax))
1587 return NULL;
1589 ldb_ctx = pyldb_Ldb_AsLdbContext(self);
1590 ret = ldb_schema_attribute_add(ldb_ctx, attribute, flags, syntax);
1592 PyErr_LDB_ERROR_IS_ERR_RAISE(PyExc_LdbError, ret, ldb_ctx);
1594 Py_RETURN_NONE;
1597 static PyObject *ldb_ldif_to_pyobject(struct ldb_ldif *ldif)
1599 if (ldif == NULL) {
1600 Py_RETURN_NONE;
1601 } else {
1602 /* We don't want this attached to the 'ldb' any more */
1603 return Py_BuildValue(discard_const_p(char, "(iO)"),
1604 ldif->changetype,
1605 PyLdbMessage_FromMessage(ldif->msg));
1610 static PyObject *py_ldb_write_ldif(PyLdbObject *self, PyObject *args)
1612 int changetype;
1613 PyObject *py_msg;
1614 struct ldb_ldif ldif;
1615 PyObject *ret;
1616 char *string;
1617 TALLOC_CTX *mem_ctx;
1619 if (!PyArg_ParseTuple(args, "Oi", &py_msg, &changetype))
1620 return NULL;
1622 if (!PyLdbMessage_Check(py_msg)) {
1623 PyErr_SetString(PyExc_TypeError, "Expected Ldb Message for msg");
1624 return NULL;
1627 ldif.msg = pyldb_Message_AsMessage(py_msg);
1628 ldif.changetype = changetype;
1630 mem_ctx = talloc_new(NULL);
1632 string = ldb_ldif_write_string(pyldb_Ldb_AsLdbContext(self), mem_ctx, &ldif);
1633 if (!string) {
1634 PyErr_SetString(PyExc_KeyError, "Failed to generate LDIF");
1635 return NULL;
1638 ret = PyStr_FromString(string);
1640 talloc_free(mem_ctx);
1642 return ret;
1645 static PyObject *py_ldb_parse_ldif(PyLdbObject *self, PyObject *args)
1647 PyObject *list, *ret;
1648 struct ldb_ldif *ldif;
1649 const char *s;
1651 TALLOC_CTX *mem_ctx;
1653 if (!PyArg_ParseTuple(args, "s", &s))
1654 return NULL;
1656 mem_ctx = talloc_new(NULL);
1657 if (!mem_ctx) {
1658 Py_RETURN_NONE;
1661 list = PyList_New(0);
1662 while (s && *s != '\0') {
1663 ldif = ldb_ldif_read_string(self->ldb_ctx, &s);
1664 talloc_steal(mem_ctx, ldif);
1665 if (ldif) {
1666 PyList_Append(list, ldb_ldif_to_pyobject(ldif));
1667 } else {
1668 PyErr_SetString(PyExc_ValueError, "unable to parse ldif string");
1669 talloc_free(mem_ctx);
1670 return NULL;
1673 talloc_free(mem_ctx); /* The pyobject already has a reference to the things it needs */
1674 ret = PyObject_GetIter(list);
1675 Py_DECREF(list);
1676 return ret;
1679 static PyObject *py_ldb_msg_diff(PyLdbObject *self, PyObject *args)
1681 int ldb_ret;
1682 PyObject *py_msg_old;
1683 PyObject *py_msg_new;
1684 struct ldb_message *diff;
1685 struct ldb_context *ldb;
1686 PyObject *py_ret;
1688 if (!PyArg_ParseTuple(args, "OO", &py_msg_old, &py_msg_new))
1689 return NULL;
1691 if (!PyLdbMessage_Check(py_msg_old)) {
1692 PyErr_SetString(PyExc_TypeError, "Expected Ldb Message for old message");
1693 return NULL;
1696 if (!PyLdbMessage_Check(py_msg_new)) {
1697 PyErr_SetString(PyExc_TypeError, "Expected Ldb Message for new message");
1698 return NULL;
1701 ldb = pyldb_Ldb_AsLdbContext(self);
1702 ldb_ret = ldb_msg_difference(ldb, ldb,
1703 pyldb_Message_AsMessage(py_msg_old),
1704 pyldb_Message_AsMessage(py_msg_new),
1705 &diff);
1706 if (ldb_ret != LDB_SUCCESS) {
1707 PyErr_SetString(PyExc_RuntimeError, "Failed to generate the Ldb Message diff");
1708 return NULL;
1711 py_ret = PyLdbMessage_FromMessage(diff);
1713 talloc_unlink(ldb, diff);
1715 return py_ret;
1718 static PyObject *py_ldb_schema_format_value(PyLdbObject *self, PyObject *args)
1720 const struct ldb_schema_attribute *a;
1721 struct ldb_val old_val;
1722 struct ldb_val new_val;
1723 TALLOC_CTX *mem_ctx;
1724 PyObject *ret;
1725 char *element_name;
1726 PyObject *val;
1727 Py_ssize_t size;
1728 int result;
1730 if (!PyArg_ParseTuple(args, "sO", &element_name, &val))
1731 return NULL;
1733 result = PyBytes_AsStringAndSize(val, (char **)&old_val.data, &size);
1734 old_val.length = size;
1736 if (result != 0) {
1737 PyErr_SetString(PyExc_RuntimeError, "Failed to convert passed value to String");
1738 return NULL;
1741 a = ldb_schema_attribute_by_name(pyldb_Ldb_AsLdbContext(self), element_name);
1743 if (a == NULL) {
1744 Py_RETURN_NONE;
1747 mem_ctx = talloc_new(NULL);
1748 if (mem_ctx == NULL) {
1749 PyErr_NoMemory();
1750 return NULL;
1753 if (a->syntax->ldif_write_fn(pyldb_Ldb_AsLdbContext(self), mem_ctx, &old_val, &new_val) != 0) {
1754 talloc_free(mem_ctx);
1755 Py_RETURN_NONE;
1758 ret = PyBytes_FromStringAndSize((const char *)new_val.data, new_val.length);
1760 talloc_free(mem_ctx);
1762 return ret;
1765 static PyObject *py_ldb_search(PyLdbObject *self, PyObject *args, PyObject *kwargs)
1767 PyObject *py_base = Py_None;
1768 int scope = LDB_SCOPE_DEFAULT;
1769 char *expr = NULL;
1770 PyObject *py_attrs = Py_None;
1771 PyObject *py_controls = Py_None;
1772 const char * const kwnames[] = { "base", "scope", "expression", "attrs", "controls", NULL };
1773 int ret;
1774 struct ldb_result *res;
1775 struct ldb_request *req;
1776 const char **attrs;
1777 struct ldb_context *ldb_ctx;
1778 struct ldb_control **parsed_controls;
1779 struct ldb_dn *base;
1780 PyObject *py_ret;
1781 TALLOC_CTX *mem_ctx;
1783 /* type "int" rather than "enum" for "scope" is intentional */
1784 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "|OizOO",
1785 discard_const_p(char *, kwnames),
1786 &py_base, &scope, &expr, &py_attrs, &py_controls))
1787 return NULL;
1790 mem_ctx = talloc_new(NULL);
1791 if (mem_ctx == NULL) {
1792 PyErr_NoMemory();
1793 return NULL;
1795 ldb_ctx = pyldb_Ldb_AsLdbContext(self);
1797 if (py_attrs == Py_None) {
1798 attrs = NULL;
1799 } else {
1800 attrs = PyList_AsStrList(mem_ctx, py_attrs, "attrs");
1801 if (attrs == NULL) {
1802 talloc_free(mem_ctx);
1803 return NULL;
1807 if (py_base == Py_None) {
1808 base = ldb_get_default_basedn(ldb_ctx);
1809 } else {
1810 if (!pyldb_Object_AsDn(ldb_ctx, py_base, ldb_ctx, &base)) {
1811 talloc_free(mem_ctx);
1812 return NULL;
1816 if (py_controls == Py_None) {
1817 parsed_controls = NULL;
1818 } else {
1819 const char **controls = PyList_AsStrList(mem_ctx, py_controls, "controls");
1820 if (controls == NULL) {
1821 talloc_free(mem_ctx);
1822 return NULL;
1824 parsed_controls = ldb_parse_control_strings(ldb_ctx, mem_ctx, controls);
1825 talloc_free(controls);
1828 res = talloc_zero(mem_ctx, struct ldb_result);
1829 if (res == NULL) {
1830 PyErr_NoMemory();
1831 talloc_free(mem_ctx);
1832 return NULL;
1835 ret = ldb_build_search_req(&req, ldb_ctx, mem_ctx,
1836 base,
1837 scope,
1838 expr,
1839 attrs,
1840 parsed_controls,
1841 res,
1842 ldb_search_default_callback,
1843 NULL);
1845 if (ret != LDB_SUCCESS) {
1846 talloc_free(mem_ctx);
1847 PyErr_SetLdbError(PyExc_LdbError, ret, ldb_ctx);
1848 return NULL;
1851 talloc_steal(req, attrs);
1853 ret = ldb_request(ldb_ctx, req);
1855 if (ret == LDB_SUCCESS) {
1856 ret = ldb_wait(req->handle, LDB_WAIT_ALL);
1859 if (ret != LDB_SUCCESS) {
1860 talloc_free(mem_ctx);
1861 PyErr_SetLdbError(PyExc_LdbError, ret, ldb_ctx);
1862 return NULL;
1865 py_ret = PyLdbResult_FromResult(res);
1867 talloc_free(mem_ctx);
1869 return py_ret;
1872 static PyObject *py_ldb_get_opaque(PyLdbObject *self, PyObject *args)
1874 char *name;
1875 void *data;
1877 if (!PyArg_ParseTuple(args, "s", &name))
1878 return NULL;
1880 data = ldb_get_opaque(pyldb_Ldb_AsLdbContext(self), name);
1882 if (data == NULL)
1883 Py_RETURN_NONE;
1885 /* FIXME: More interpretation */
1887 Py_RETURN_TRUE;
1890 static PyObject *py_ldb_set_opaque(PyLdbObject *self, PyObject *args)
1892 char *name;
1893 PyObject *data;
1895 if (!PyArg_ParseTuple(args, "sO", &name, &data))
1896 return NULL;
1898 /* FIXME: More interpretation */
1900 ldb_set_opaque(pyldb_Ldb_AsLdbContext(self), name, data);
1902 Py_RETURN_NONE;
1905 static PyObject *py_ldb_modules(PyLdbObject *self)
1907 struct ldb_context *ldb = pyldb_Ldb_AsLdbContext(self);
1908 PyObject *ret = PyList_New(0);
1909 struct ldb_module *mod;
1911 for (mod = ldb->modules; mod; mod = mod->next) {
1912 PyList_Append(ret, PyLdbModule_FromModule(mod));
1915 return ret;
1918 static PyObject *py_ldb_sequence_number(PyLdbObject *self, PyObject *args)
1920 struct ldb_context *ldb = pyldb_Ldb_AsLdbContext(self);
1921 int type, ret;
1922 uint64_t value;
1924 if (!PyArg_ParseTuple(args, "i", &type))
1925 return NULL;
1927 /* FIXME: More interpretation */
1929 ret = ldb_sequence_number(ldb, type, &value);
1931 PyErr_LDB_ERROR_IS_ERR_RAISE(PyExc_LdbError, ret, ldb);
1933 return PyLong_FromLongLong(value);
1937 static const struct ldb_dn_extended_syntax test_dn_syntax = {
1938 .name = "TEST",
1939 .read_fn = ldb_handler_copy,
1940 .write_clear_fn = ldb_handler_copy,
1941 .write_hex_fn = ldb_handler_copy,
1944 static PyObject *py_ldb_register_test_extensions(PyLdbObject *self)
1946 struct ldb_context *ldb = pyldb_Ldb_AsLdbContext(self);
1947 int ret;
1949 ret = ldb_dn_extended_add_syntax(ldb, LDB_ATTR_FLAG_FIXED, &test_dn_syntax);
1951 PyErr_LDB_ERROR_IS_ERR_RAISE(PyExc_LdbError, ret, ldb);
1953 Py_RETURN_NONE;
1957 static PyMethodDef py_ldb_methods[] = {
1958 { "set_debug", (PyCFunction)py_ldb_set_debug, METH_VARARGS,
1959 "S.set_debug(callback) -> None\n"
1960 "Set callback for LDB debug messages.\n"
1961 "The callback should accept a debug level and debug text." },
1962 { "set_create_perms", (PyCFunction)py_ldb_set_create_perms, METH_VARARGS,
1963 "S.set_create_perms(mode) -> None\n"
1964 "Set mode to use when creating new LDB files." },
1965 { "set_modules_dir", (PyCFunction)py_ldb_set_modules_dir, METH_VARARGS,
1966 "S.set_modules_dir(path) -> None\n"
1967 "Set path LDB should search for modules" },
1968 { "transaction_start", (PyCFunction)py_ldb_transaction_start, METH_NOARGS,
1969 "S.transaction_start() -> None\n"
1970 "Start a new transaction." },
1971 { "transaction_prepare_commit", (PyCFunction)py_ldb_transaction_prepare_commit, METH_NOARGS,
1972 "S.transaction_prepare_commit() -> None\n"
1973 "prepare to commit a new transaction (2-stage commit)." },
1974 { "transaction_commit", (PyCFunction)py_ldb_transaction_commit, METH_NOARGS,
1975 "S.transaction_commit() -> None\n"
1976 "commit a new transaction." },
1977 { "transaction_cancel", (PyCFunction)py_ldb_transaction_cancel, METH_NOARGS,
1978 "S.transaction_cancel() -> None\n"
1979 "cancel a new transaction." },
1980 { "setup_wellknown_attributes", (PyCFunction)py_ldb_setup_wellknown_attributes, METH_NOARGS,
1981 NULL },
1982 { "get_root_basedn", (PyCFunction)py_ldb_get_root_basedn, METH_NOARGS,
1983 NULL },
1984 { "get_schema_basedn", (PyCFunction)py_ldb_get_schema_basedn, METH_NOARGS,
1985 NULL },
1986 { "get_default_basedn", (PyCFunction)py_ldb_get_default_basedn, METH_NOARGS,
1987 NULL },
1988 { "get_config_basedn", (PyCFunction)py_ldb_get_config_basedn, METH_NOARGS,
1989 NULL },
1990 { "connect", (PyCFunction)py_ldb_connect, METH_VARARGS|METH_KEYWORDS,
1991 "S.connect(url, flags=0, options=None) -> None\n"
1992 "Connect to a LDB URL." },
1993 { "modify", (PyCFunction)py_ldb_modify, METH_VARARGS|METH_KEYWORDS,
1994 "S.modify(message, controls=None, validate=False) -> None\n"
1995 "Modify an entry." },
1996 { "add", (PyCFunction)py_ldb_add, METH_VARARGS|METH_KEYWORDS,
1997 "S.add(message, controls=None) -> None\n"
1998 "Add an entry." },
1999 { "delete", (PyCFunction)py_ldb_delete, METH_VARARGS|METH_KEYWORDS,
2000 "S.delete(dn, controls=None) -> None\n"
2001 "Remove an entry." },
2002 { "rename", (PyCFunction)py_ldb_rename, METH_VARARGS|METH_KEYWORDS,
2003 "S.rename(old_dn, new_dn, controls=None) -> None\n"
2004 "Rename an entry." },
2005 { "search", (PyCFunction)py_ldb_search, METH_VARARGS|METH_KEYWORDS,
2006 "S.search(base=None, scope=None, expression=None, attrs=None, controls=None) -> msgs\n"
2007 "Search in a database.\n"
2008 "\n"
2009 ":param base: Optional base DN to search\n"
2010 ":param scope: Search scope (SCOPE_BASE, SCOPE_ONELEVEL or SCOPE_SUBTREE)\n"
2011 ":param expression: Optional search expression\n"
2012 ":param attrs: Attributes to return (defaults to all)\n"
2013 ":param controls: Optional list of controls\n"
2014 ":return: Iterator over Message objects\n"
2016 { "schema_attribute_remove", (PyCFunction)py_ldb_schema_attribute_remove, METH_VARARGS,
2017 NULL },
2018 { "schema_attribute_add", (PyCFunction)py_ldb_schema_attribute_add, METH_VARARGS,
2019 NULL },
2020 { "schema_format_value", (PyCFunction)py_ldb_schema_format_value, METH_VARARGS,
2021 NULL },
2022 { "parse_ldif", (PyCFunction)py_ldb_parse_ldif, METH_VARARGS,
2023 "S.parse_ldif(ldif) -> iter(messages)\n"
2024 "Parse a string formatted using LDIF." },
2025 { "write_ldif", (PyCFunction)py_ldb_write_ldif, METH_VARARGS,
2026 "S.write_ldif(message, changetype) -> ldif\n"
2027 "Print the message as a string formatted using LDIF." },
2028 { "msg_diff", (PyCFunction)py_ldb_msg_diff, METH_VARARGS,
2029 "S.msg_diff(Message) -> Message\n"
2030 "Return an LDB Message of the difference between two Message objects." },
2031 { "get_opaque", (PyCFunction)py_ldb_get_opaque, METH_VARARGS,
2032 "S.get_opaque(name) -> value\n"
2033 "Get an opaque value set on this LDB connection. \n"
2034 ":note: The returned value may not be useful in Python."
2036 { "set_opaque", (PyCFunction)py_ldb_set_opaque, METH_VARARGS,
2037 "S.set_opaque(name, value) -> None\n"
2038 "Set an opaque value on this LDB connection. \n"
2039 ":note: Passing incorrect values may cause crashes." },
2040 { "modules", (PyCFunction)py_ldb_modules, METH_NOARGS,
2041 "S.modules() -> list\n"
2042 "Return the list of modules on this LDB connection " },
2043 { "sequence_number", (PyCFunction)py_ldb_sequence_number, METH_VARARGS,
2044 "S.sequence_number(type) -> value\n"
2045 "Return the value of the sequence according to the requested type" },
2046 { "_register_test_extensions", (PyCFunction)py_ldb_register_test_extensions, METH_NOARGS,
2047 "S._register_test_extensions() -> None\n"
2048 "Register internal extensions used in testing" },
2049 { NULL },
2052 static PyObject *PyLdbModule_FromModule(struct ldb_module *mod)
2054 PyLdbModuleObject *ret;
2056 ret = (PyLdbModuleObject *)PyLdbModule.tp_alloc(&PyLdbModule, 0);
2057 if (ret == NULL) {
2058 PyErr_NoMemory();
2059 return NULL;
2061 ret->mem_ctx = talloc_new(NULL);
2062 ret->mod = talloc_reference(ret->mem_ctx, mod);
2063 return (PyObject *)ret;
2066 static PyObject *py_ldb_get_firstmodule(PyLdbObject *self, void *closure)
2068 struct ldb_module *mod = pyldb_Ldb_AsLdbContext(self)->modules;
2069 if (mod == NULL) {
2070 Py_RETURN_NONE;
2072 return PyLdbModule_FromModule(mod);
2075 static PyGetSetDef py_ldb_getset[] = {
2076 { discard_const_p(char, "firstmodule"), (getter)py_ldb_get_firstmodule, NULL, NULL },
2077 { NULL }
2080 static int py_ldb_contains(PyLdbObject *self, PyObject *obj)
2082 struct ldb_context *ldb_ctx = pyldb_Ldb_AsLdbContext(self);
2083 struct ldb_dn *dn;
2084 struct ldb_result *result;
2085 unsigned int count;
2086 int ret;
2088 if (!pyldb_Object_AsDn(ldb_ctx, obj, ldb_ctx, &dn)) {
2089 return -1;
2092 ret = ldb_search(ldb_ctx, ldb_ctx, &result, dn, LDB_SCOPE_BASE, NULL,
2093 NULL);
2094 if (ret != LDB_SUCCESS) {
2095 PyErr_SetLdbError(PyExc_LdbError, ret, ldb_ctx);
2096 return -1;
2099 count = result->count;
2101 talloc_free(result);
2103 if (count > 1) {
2104 PyErr_Format(PyExc_RuntimeError,
2105 "Searching for [%s] dn gave %u results!",
2106 ldb_dn_get_linearized(dn),
2107 count);
2108 return -1;
2111 return count;
2114 static PySequenceMethods py_ldb_seq = {
2115 .sq_contains = (objobjproc)py_ldb_contains,
2118 static PyObject *PyLdb_FromLdbContext(struct ldb_context *ldb_ctx)
2120 PyLdbObject *ret;
2122 ret = (PyLdbObject *)PyLdb.tp_alloc(&PyLdb, 0);
2123 if (ret == NULL) {
2124 PyErr_NoMemory();
2125 return NULL;
2127 ret->mem_ctx = talloc_new(NULL);
2128 ret->ldb_ctx = talloc_reference(ret->mem_ctx, ldb_ctx);
2129 return (PyObject *)ret;
2132 static void py_ldb_dealloc(PyLdbObject *self)
2134 talloc_free(self->mem_ctx);
2135 Py_TYPE(self)->tp_free(self);
2138 static PyTypeObject PyLdb = {
2139 .tp_name = "ldb.Ldb",
2140 .tp_methods = py_ldb_methods,
2141 .tp_repr = (reprfunc)py_ldb_repr,
2142 .tp_new = py_ldb_new,
2143 .tp_init = (initproc)py_ldb_init,
2144 .tp_dealloc = (destructor)py_ldb_dealloc,
2145 .tp_getset = py_ldb_getset,
2146 .tp_getattro = PyObject_GenericGetAttr,
2147 .tp_basicsize = sizeof(PyLdbObject),
2148 .tp_doc = "Connection to a LDB database.",
2149 .tp_as_sequence = &py_ldb_seq,
2150 .tp_flags = Py_TPFLAGS_DEFAULT|Py_TPFLAGS_BASETYPE,
2153 static void py_ldb_result_dealloc(PyLdbResultObject *self)
2155 talloc_free(self->mem_ctx);
2156 Py_DECREF(self->msgs);
2157 Py_DECREF(self->referals);
2158 Py_DECREF(self->controls);
2159 Py_TYPE(self)->tp_free(self);
2162 static PyObject *py_ldb_result_get_msgs(PyLdbResultObject *self, void *closure)
2164 Py_INCREF(self->msgs);
2165 return self->msgs;
2168 static PyObject *py_ldb_result_get_controls(PyLdbResultObject *self, void *closure)
2170 Py_INCREF(self->controls);
2171 return self->controls;
2174 static PyObject *py_ldb_result_get_referals(PyLdbResultObject *self, void *closure)
2176 Py_INCREF(self->referals);
2177 return self->referals;
2180 static PyObject *py_ldb_result_get_count(PyLdbResultObject *self, void *closure)
2182 Py_ssize_t size;
2183 if (self->msgs == NULL) {
2184 PyErr_SetString(PyExc_AttributeError, "Count attribute is meaningless in this context");
2185 return NULL;
2187 size = PyList_Size(self->msgs);
2188 return PyInt_FromLong(size);
2191 static PyGetSetDef py_ldb_result_getset[] = {
2192 { discard_const_p(char, "controls"), (getter)py_ldb_result_get_controls, NULL, NULL },
2193 { discard_const_p(char, "msgs"), (getter)py_ldb_result_get_msgs, NULL, NULL },
2194 { discard_const_p(char, "referals"), (getter)py_ldb_result_get_referals, NULL, NULL },
2195 { discard_const_p(char, "count"), (getter)py_ldb_result_get_count, NULL, NULL },
2196 { NULL }
2199 static PyObject *py_ldb_result_iter(PyLdbResultObject *self)
2201 return PyObject_GetIter(self->msgs);
2204 static Py_ssize_t py_ldb_result_len(PyLdbResultObject *self)
2206 return PySequence_Size(self->msgs);
2209 static PyObject *py_ldb_result_find(PyLdbResultObject *self, Py_ssize_t idx)
2211 return PySequence_GetItem(self->msgs, idx);
2214 static PySequenceMethods py_ldb_result_seq = {
2215 .sq_length = (lenfunc)py_ldb_result_len,
2216 .sq_item = (ssizeargfunc)py_ldb_result_find,
2219 static PyObject *py_ldb_result_repr(PyLdbObject *self)
2221 return PyStr_FromString("<ldb result>");
2225 static PyTypeObject PyLdbResult = {
2226 .tp_name = "ldb.Result",
2227 .tp_repr = (reprfunc)py_ldb_result_repr,
2228 .tp_dealloc = (destructor)py_ldb_result_dealloc,
2229 .tp_iter = (getiterfunc)py_ldb_result_iter,
2230 .tp_getset = py_ldb_result_getset,
2231 .tp_getattro = PyObject_GenericGetAttr,
2232 .tp_basicsize = sizeof(PyLdbResultObject),
2233 .tp_as_sequence = &py_ldb_result_seq,
2234 .tp_doc = "LDB result.",
2235 .tp_flags = Py_TPFLAGS_DEFAULT|Py_TPFLAGS_BASETYPE,
2238 static PyObject *py_ldb_module_repr(PyLdbModuleObject *self)
2240 return PyStr_FromFormat("<ldb module '%s'>",
2241 pyldb_Module_AsModule(self)->ops->name);
2244 static PyObject *py_ldb_module_str(PyLdbModuleObject *self)
2246 return PyStr_FromString(pyldb_Module_AsModule(self)->ops->name);
2249 static PyObject *py_ldb_module_start_transaction(PyLdbModuleObject *self)
2251 pyldb_Module_AsModule(self)->ops->start_transaction(pyldb_Module_AsModule(self));
2252 Py_RETURN_NONE;
2255 static PyObject *py_ldb_module_end_transaction(PyLdbModuleObject *self)
2257 pyldb_Module_AsModule(self)->ops->end_transaction(pyldb_Module_AsModule(self));
2258 Py_RETURN_NONE;
2261 static PyObject *py_ldb_module_del_transaction(PyLdbModuleObject *self)
2263 pyldb_Module_AsModule(self)->ops->del_transaction(pyldb_Module_AsModule(self));
2264 Py_RETURN_NONE;
2267 static PyObject *py_ldb_module_search(PyLdbModuleObject *self, PyObject *args, PyObject *kwargs)
2269 PyObject *py_base, *py_tree, *py_attrs, *py_ret;
2270 int ret, scope;
2271 struct ldb_request *req;
2272 const char * const kwnames[] = { "base", "scope", "tree", "attrs", NULL };
2273 struct ldb_module *mod;
2274 const char * const*attrs;
2276 /* type "int" rather than "enum" for "scope" is intentional */
2277 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "O!iOO",
2278 discard_const_p(char *, kwnames),
2279 &PyLdbDn, &py_base, &scope, &py_tree, &py_attrs))
2280 return NULL;
2282 mod = self->mod;
2284 if (py_attrs == Py_None) {
2285 attrs = NULL;
2286 } else {
2287 attrs = PyList_AsStrList(NULL, py_attrs, "attrs");
2288 if (attrs == NULL)
2289 return NULL;
2292 ret = ldb_build_search_req(&req, mod->ldb, NULL, pyldb_Dn_AsDn(py_base),
2293 scope, NULL /* expr */, attrs,
2294 NULL /* controls */, NULL, NULL, NULL);
2296 talloc_steal(req, attrs);
2298 PyErr_LDB_ERROR_IS_ERR_RAISE(PyExc_LdbError, ret, mod->ldb);
2300 req->op.search.res = NULL;
2302 ret = mod->ops->search(mod, req);
2304 PyErr_LDB_ERROR_IS_ERR_RAISE(PyExc_LdbError, ret, mod->ldb);
2306 py_ret = PyLdbResult_FromResult(req->op.search.res);
2308 talloc_free(req);
2310 return py_ret;
2314 static PyObject *py_ldb_module_add(PyLdbModuleObject *self, PyObject *args)
2316 struct ldb_request *req;
2317 PyObject *py_message;
2318 int ret;
2319 struct ldb_module *mod;
2321 if (!PyArg_ParseTuple(args, "O!", &PyLdbMessage, &py_message))
2322 return NULL;
2324 req = talloc_zero(NULL, struct ldb_request);
2325 req->operation = LDB_ADD;
2326 req->op.add.message = pyldb_Message_AsMessage(py_message);
2328 mod = pyldb_Module_AsModule(self);
2329 ret = mod->ops->add(mod, req);
2331 PyErr_LDB_ERROR_IS_ERR_RAISE(PyExc_LdbError, ret, mod->ldb);
2333 Py_RETURN_NONE;
2336 static PyObject *py_ldb_module_modify(PyLdbModuleObject *self, PyObject *args)
2338 int ret;
2339 struct ldb_request *req;
2340 PyObject *py_message;
2341 struct ldb_module *mod;
2343 if (!PyArg_ParseTuple(args, "O!", &PyLdbMessage, &py_message))
2344 return NULL;
2346 req = talloc_zero(NULL, struct ldb_request);
2347 req->operation = LDB_MODIFY;
2348 req->op.mod.message = pyldb_Message_AsMessage(py_message);
2350 mod = pyldb_Module_AsModule(self);
2351 ret = mod->ops->modify(mod, req);
2353 PyErr_LDB_ERROR_IS_ERR_RAISE(PyExc_LdbError, ret, mod->ldb);
2355 Py_RETURN_NONE;
2358 static PyObject *py_ldb_module_delete(PyLdbModuleObject *self, PyObject *args)
2360 int ret;
2361 struct ldb_request *req;
2362 PyObject *py_dn;
2364 if (!PyArg_ParseTuple(args, "O!", &PyLdbDn, &py_dn))
2365 return NULL;
2367 req = talloc_zero(NULL, struct ldb_request);
2368 req->operation = LDB_DELETE;
2369 req->op.del.dn = pyldb_Dn_AsDn(py_dn);
2371 ret = pyldb_Module_AsModule(self)->ops->del(pyldb_Module_AsModule(self), req);
2373 PyErr_LDB_ERROR_IS_ERR_RAISE(PyExc_LdbError, ret, NULL);
2375 Py_RETURN_NONE;
2378 static PyObject *py_ldb_module_rename(PyLdbModuleObject *self, PyObject *args)
2380 int ret;
2381 struct ldb_request *req;
2382 PyObject *py_dn1, *py_dn2;
2384 if (!PyArg_ParseTuple(args, "O!O!", &PyLdbDn, &py_dn1, &PyLdbDn, &py_dn2))
2385 return NULL;
2387 req = talloc_zero(NULL, struct ldb_request);
2389 req->operation = LDB_RENAME;
2390 req->op.rename.olddn = pyldb_Dn_AsDn(py_dn1);
2391 req->op.rename.newdn = pyldb_Dn_AsDn(py_dn2);
2393 ret = pyldb_Module_AsModule(self)->ops->rename(pyldb_Module_AsModule(self), req);
2395 PyErr_LDB_ERROR_IS_ERR_RAISE(PyExc_LdbError, ret, NULL);
2397 Py_RETURN_NONE;
2400 static PyMethodDef py_ldb_module_methods[] = {
2401 { "search", (PyCFunction)py_ldb_module_search, METH_VARARGS|METH_KEYWORDS, NULL },
2402 { "add", (PyCFunction)py_ldb_module_add, METH_VARARGS, NULL },
2403 { "modify", (PyCFunction)py_ldb_module_modify, METH_VARARGS, NULL },
2404 { "rename", (PyCFunction)py_ldb_module_rename, METH_VARARGS, NULL },
2405 { "delete", (PyCFunction)py_ldb_module_delete, METH_VARARGS, NULL },
2406 { "start_transaction", (PyCFunction)py_ldb_module_start_transaction, METH_NOARGS, NULL },
2407 { "end_transaction", (PyCFunction)py_ldb_module_end_transaction, METH_NOARGS, NULL },
2408 { "del_transaction", (PyCFunction)py_ldb_module_del_transaction, METH_NOARGS, NULL },
2409 { NULL },
2412 static void py_ldb_module_dealloc(PyLdbModuleObject *self)
2414 talloc_free(self->mem_ctx);
2415 PyObject_Del(self);
2418 static PyTypeObject PyLdbModule = {
2419 .tp_name = "ldb.LdbModule",
2420 .tp_methods = py_ldb_module_methods,
2421 .tp_repr = (reprfunc)py_ldb_module_repr,
2422 .tp_str = (reprfunc)py_ldb_module_str,
2423 .tp_basicsize = sizeof(PyLdbModuleObject),
2424 .tp_dealloc = (destructor)py_ldb_module_dealloc,
2425 .tp_flags = Py_TPFLAGS_DEFAULT,
2426 .tp_doc = "LDB module (extension)",
2431 * Create a ldb_message_element from a Python object.
2433 * This will accept any sequence objects that contains strings, or
2434 * a string object.
2436 * A reference to set_obj will be borrowed.
2438 * @param mem_ctx Memory context
2439 * @param set_obj Python object to convert
2440 * @param flags ldb_message_element flags to set
2441 * @param attr_name Name of the attribute
2442 * @return New ldb_message_element, allocated as child of mem_ctx
2444 static struct ldb_message_element *PyObject_AsMessageElement(
2445 TALLOC_CTX *mem_ctx,
2446 PyObject *set_obj,
2447 unsigned int flags,
2448 const char *attr_name)
2450 struct ldb_message_element *me;
2451 const char *msg = NULL;
2452 Py_ssize_t size;
2453 int result;
2455 if (pyldb_MessageElement_Check(set_obj)) {
2456 PyLdbMessageElementObject *set_obj_as_me = (PyLdbMessageElementObject *)set_obj;
2457 /* We have to talloc_reference() the memory context, not the pointer
2458 * which may not actually be it's own context */
2459 if (talloc_reference(mem_ctx, set_obj_as_me->mem_ctx)) {
2460 return pyldb_MessageElement_AsMessageElement(set_obj);
2462 return NULL;
2465 me = talloc(mem_ctx, struct ldb_message_element);
2466 if (me == NULL) {
2467 PyErr_NoMemory();
2468 return NULL;
2471 me->name = talloc_strdup(me, attr_name);
2472 me->flags = flags;
2473 if (PyBytes_Check(set_obj) || PyStr_Check(set_obj)) {
2474 me->num_values = 1;
2475 me->values = talloc_array(me, struct ldb_val, me->num_values);
2476 if (PyBytes_Check(set_obj)) {
2477 char *_msg = NULL;
2478 result = PyBytes_AsStringAndSize(set_obj, &_msg, &size);
2479 if (result != 0) {
2480 talloc_free(me);
2481 return NULL;
2483 msg = _msg;
2484 } else {
2485 msg = PyStr_AsUTF8AndSize(set_obj, &size);
2486 if (msg == NULL) {
2487 talloc_free(me);
2488 return NULL;
2491 me->values[0].data = talloc_memdup(me,
2492 (const uint8_t *)msg,
2493 size+1);
2494 me->values[0].length = size;
2495 } else if (PySequence_Check(set_obj)) {
2496 Py_ssize_t i;
2497 me->num_values = PySequence_Size(set_obj);
2498 me->values = talloc_array(me, struct ldb_val, me->num_values);
2499 for (i = 0; i < me->num_values; i++) {
2500 PyObject *obj = PySequence_GetItem(set_obj, i);
2501 if (PyBytes_Check(obj)) {
2502 char *_msg = NULL;
2503 result = PyBytes_AsStringAndSize(obj, &_msg, &size);
2504 if (result != 0) {
2505 talloc_free(me);
2506 return NULL;
2508 msg = _msg;
2509 } else if (PyStr_Check(obj)) {
2510 msg = PyStr_AsUTF8AndSize(obj, &size);
2511 if (msg == NULL) {
2512 talloc_free(me);
2513 return NULL;
2515 } else {
2516 PyErr_Format(PyExc_TypeError,
2517 "Expected string as element %zd in list", i);
2518 talloc_free(me);
2519 return NULL;
2521 me->values[i].data = talloc_memdup(me,
2522 (const uint8_t *)msg,
2523 size+1);
2524 me->values[i].length = size;
2526 } else {
2527 PyErr_Format(PyExc_TypeError,
2528 "String or List type expected for '%s' attribute", attr_name);
2529 talloc_free(me);
2530 me = NULL;
2533 return me;
2537 static PyObject *ldb_msg_element_to_set(struct ldb_context *ldb_ctx,
2538 struct ldb_message_element *me)
2540 Py_ssize_t i;
2541 PyObject *result;
2543 /* Python << 2.5 doesn't have PySet_New and PySet_Add. */
2544 result = PyList_New(me->num_values);
2546 for (i = 0; i < me->num_values; i++) {
2547 PyList_SetItem(result, i,
2548 PyObject_FromLdbValue(&me->values[i]));
2551 return result;
2554 static PyObject *py_ldb_msg_element_get(PyLdbMessageElementObject *self, PyObject *args)
2556 unsigned int i;
2557 if (!PyArg_ParseTuple(args, "I", &i))
2558 return NULL;
2559 if (i >= pyldb_MessageElement_AsMessageElement(self)->num_values)
2560 Py_RETURN_NONE;
2562 return PyObject_FromLdbValue(&(pyldb_MessageElement_AsMessageElement(self)->values[i]));
2565 static PyObject *py_ldb_msg_element_flags(PyLdbMessageElementObject *self, PyObject *args)
2567 struct ldb_message_element *el = pyldb_MessageElement_AsMessageElement(self);
2568 return PyInt_FromLong(el->flags);
2571 static PyObject *py_ldb_msg_element_set_flags(PyLdbMessageElementObject *self, PyObject *args)
2573 unsigned int flags;
2574 struct ldb_message_element *el;
2575 if (!PyArg_ParseTuple(args, "I", &flags))
2576 return NULL;
2578 el = pyldb_MessageElement_AsMessageElement(self);
2579 el->flags = flags;
2580 Py_RETURN_NONE;
2583 static PyMethodDef py_ldb_msg_element_methods[] = {
2584 { "get", (PyCFunction)py_ldb_msg_element_get, METH_VARARGS, NULL },
2585 { "set_flags", (PyCFunction)py_ldb_msg_element_set_flags, METH_VARARGS, NULL },
2586 { "flags", (PyCFunction)py_ldb_msg_element_flags, METH_NOARGS, NULL },
2587 { NULL },
2590 static Py_ssize_t py_ldb_msg_element_len(PyLdbMessageElementObject *self)
2592 return pyldb_MessageElement_AsMessageElement(self)->num_values;
2595 static PyObject *py_ldb_msg_element_find(PyLdbMessageElementObject *self, Py_ssize_t idx)
2597 struct ldb_message_element *el = pyldb_MessageElement_AsMessageElement(self);
2598 if (idx < 0 || idx >= el->num_values) {
2599 PyErr_SetString(PyExc_IndexError, "Out of range");
2600 return NULL;
2602 return PyBytes_FromStringAndSize((char *)el->values[idx].data, el->values[idx].length);
2605 static PySequenceMethods py_ldb_msg_element_seq = {
2606 .sq_length = (lenfunc)py_ldb_msg_element_len,
2607 .sq_item = (ssizeargfunc)py_ldb_msg_element_find,
2610 static PyObject *py_ldb_msg_element_richcmp(PyObject *self, PyObject *other, int op)
2612 int ret;
2613 if (!pyldb_MessageElement_Check(other)) {
2614 Py_INCREF(Py_NotImplemented);
2615 return Py_NotImplemented;
2617 ret = ldb_msg_element_compare(pyldb_MessageElement_AsMessageElement(self),
2618 pyldb_MessageElement_AsMessageElement(other));
2619 return richcmp(ret, op);
2622 static PyObject *py_ldb_msg_element_iter(PyLdbMessageElementObject *self)
2624 PyObject *el = ldb_msg_element_to_set(NULL,
2625 pyldb_MessageElement_AsMessageElement(self));
2626 PyObject *ret = PyObject_GetIter(el);
2627 Py_DECREF(el);
2628 return ret;
2631 static PyObject *PyLdbMessageElement_FromMessageElement(struct ldb_message_element *el, TALLOC_CTX *mem_ctx)
2633 PyLdbMessageElementObject *ret;
2634 ret = PyObject_New(PyLdbMessageElementObject, &PyLdbMessageElement);
2635 if (ret == NULL) {
2636 PyErr_NoMemory();
2637 return NULL;
2639 ret->mem_ctx = talloc_new(NULL);
2640 if (talloc_reference(ret->mem_ctx, mem_ctx) == NULL) {
2641 PyErr_NoMemory();
2642 return NULL;
2644 ret->el = el;
2645 return (PyObject *)ret;
2648 static PyObject *py_ldb_msg_element_new(PyTypeObject *type, PyObject *args, PyObject *kwargs)
2650 PyObject *py_elements = NULL;
2651 struct ldb_message_element *el;
2652 unsigned int flags = 0;
2653 char *name = NULL;
2654 const char * const kwnames[] = { "elements", "flags", "name", NULL };
2655 PyLdbMessageElementObject *ret;
2656 TALLOC_CTX *mem_ctx;
2657 const char *msg = NULL;
2658 Py_ssize_t size;
2659 int result;
2661 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "|OIs",
2662 discard_const_p(char *, kwnames),
2663 &py_elements, &flags, &name))
2664 return NULL;
2666 mem_ctx = talloc_new(NULL);
2667 if (mem_ctx == NULL) {
2668 PyErr_NoMemory();
2669 return NULL;
2672 el = talloc_zero(mem_ctx, struct ldb_message_element);
2673 if (el == NULL) {
2674 PyErr_NoMemory();
2675 talloc_free(mem_ctx);
2676 return NULL;
2679 if (py_elements != NULL) {
2680 Py_ssize_t i;
2681 if (PyBytes_Check(py_elements)) {
2682 char *_msg = NULL;
2683 el->num_values = 1;
2684 el->values = talloc_array(el, struct ldb_val, 1);
2685 if (el->values == NULL) {
2686 talloc_free(mem_ctx);
2687 PyErr_NoMemory();
2688 return NULL;
2690 result = PyBytes_AsStringAndSize(py_elements, &_msg, &size);
2691 if (result != 0) {
2692 talloc_free(mem_ctx);
2693 return NULL;
2695 msg = _msg;
2696 el->values[0].data = talloc_memdup(el->values,
2697 (const uint8_t *)msg, size + 1);
2698 el->values[0].length = size;
2699 } else if (PySequence_Check(py_elements)) {
2700 el->num_values = PySequence_Size(py_elements);
2701 el->values = talloc_array(el, struct ldb_val, el->num_values);
2702 if (el->values == NULL) {
2703 talloc_free(mem_ctx);
2704 PyErr_NoMemory();
2705 return NULL;
2707 for (i = 0; i < el->num_values; i++) {
2708 PyObject *item = PySequence_GetItem(py_elements, i);
2709 if (item == NULL) {
2710 talloc_free(mem_ctx);
2711 return NULL;
2713 if (PyBytes_Check(item)) {
2714 char *_msg = NULL;
2715 result = PyBytes_AsStringAndSize(item, &_msg, &size);
2716 msg = _msg;
2717 } else if (PyStr_Check(item)) {
2718 msg = PyStr_AsUTF8AndSize(item, &size);
2719 result = (msg == NULL) ? -1 : 0;
2720 } else {
2721 PyErr_Format(PyExc_TypeError,
2722 "Expected string as element %zd in list", i);
2723 result = -1;
2725 if (result != 0) {
2726 talloc_free(mem_ctx);
2727 return NULL;
2729 el->values[i].data = talloc_memdup(el,
2730 (const uint8_t *)msg, size+1);
2731 el->values[i].length = size;
2733 } else {
2734 PyErr_SetString(PyExc_TypeError,
2735 "Expected string or list");
2736 talloc_free(mem_ctx);
2737 return NULL;
2741 el->flags = flags;
2742 el->name = talloc_strdup(el, name);
2744 ret = PyObject_New(PyLdbMessageElementObject, type);
2745 if (ret == NULL) {
2746 talloc_free(mem_ctx);
2747 return NULL;
2750 ret->mem_ctx = mem_ctx;
2751 ret->el = el;
2752 return (PyObject *)ret;
2755 static PyObject *py_ldb_msg_element_repr(PyLdbMessageElementObject *self)
2757 char *element_str = NULL;
2758 Py_ssize_t i;
2759 struct ldb_message_element *el = pyldb_MessageElement_AsMessageElement(self);
2760 PyObject *ret, *repr;
2762 for (i = 0; i < el->num_values; i++) {
2763 PyObject *o = py_ldb_msg_element_find(self, i);
2764 repr = PyObject_Repr(o);
2765 if (element_str == NULL)
2766 element_str = talloc_strdup(NULL, PyStr_AsUTF8(repr));
2767 else
2768 element_str = talloc_asprintf_append(element_str, ",%s", PyStr_AsUTF8(repr));
2769 Py_DECREF(repr);
2772 if (element_str != NULL) {
2773 ret = PyStr_FromFormat("MessageElement([%s])", element_str);
2774 talloc_free(element_str);
2775 } else {
2776 ret = PyStr_FromString("MessageElement([])");
2779 return ret;
2782 static PyObject *py_ldb_msg_element_str(PyLdbMessageElementObject *self)
2784 struct ldb_message_element *el = pyldb_MessageElement_AsMessageElement(self);
2786 if (el->num_values == 1)
2787 return PyStr_FromStringAndSize((char *)el->values[0].data, el->values[0].length);
2788 else
2789 Py_RETURN_NONE;
2792 static void py_ldb_msg_element_dealloc(PyLdbMessageElementObject *self)
2794 talloc_free(self->mem_ctx);
2795 PyObject_Del(self);
2798 static PyObject *py_ldb_msg_element_get_text(PyObject *self, void *closure)
2800 return wrap_text("MessageElementTextWrapper", self);
2803 static PyGetSetDef py_ldb_msg_element_getset[] = {
2804 { discard_const_p(char, "text"), (getter)py_ldb_msg_element_get_text, NULL, NULL },
2805 { NULL }
2808 static PyTypeObject PyLdbMessageElement = {
2809 .tp_name = "ldb.MessageElement",
2810 .tp_basicsize = sizeof(PyLdbMessageElementObject),
2811 .tp_dealloc = (destructor)py_ldb_msg_element_dealloc,
2812 .tp_repr = (reprfunc)py_ldb_msg_element_repr,
2813 .tp_str = (reprfunc)py_ldb_msg_element_str,
2814 .tp_methods = py_ldb_msg_element_methods,
2815 .tp_getset = py_ldb_msg_element_getset,
2816 .tp_richcompare = (richcmpfunc)py_ldb_msg_element_richcmp,
2817 .tp_iter = (getiterfunc)py_ldb_msg_element_iter,
2818 .tp_as_sequence = &py_ldb_msg_element_seq,
2819 .tp_new = py_ldb_msg_element_new,
2820 .tp_flags = Py_TPFLAGS_DEFAULT,
2821 .tp_doc = "An element of a Message",
2825 static PyObject *py_ldb_msg_from_dict(PyTypeObject *type, PyObject *args)
2827 PyObject *py_ldb;
2828 PyObject *py_dict;
2829 PyObject *py_ret;
2830 struct ldb_message *msg;
2831 struct ldb_context *ldb_ctx;
2832 unsigned int mod_flags = LDB_FLAG_MOD_REPLACE;
2834 if (!PyArg_ParseTuple(args, "O!O!|I",
2835 &PyLdb, &py_ldb, &PyDict_Type, &py_dict,
2836 &mod_flags)) {
2837 return NULL;
2840 if (!PyLdb_Check(py_ldb)) {
2841 PyErr_SetString(PyExc_TypeError, "Expected Ldb");
2842 return NULL;
2845 /* mask only flags we are going to use */
2846 mod_flags = LDB_FLAG_MOD_TYPE(mod_flags);
2847 if (!mod_flags) {
2848 PyErr_SetString(PyExc_ValueError,
2849 "FLAG_MOD_ADD, FLAG_MOD_REPLACE or FLAG_MOD_DELETE"
2850 " expected as mod_flag value");
2851 return NULL;
2854 ldb_ctx = pyldb_Ldb_AsLdbContext(py_ldb);
2856 msg = PyDict_AsMessage(ldb_ctx, py_dict, ldb_ctx, mod_flags);
2857 if (!msg) {
2858 return NULL;
2861 py_ret = PyLdbMessage_FromMessage(msg);
2863 talloc_unlink(ldb_ctx, msg);
2865 return py_ret;
2868 static PyObject *py_ldb_msg_remove_attr(PyLdbMessageObject *self, PyObject *args)
2870 char *name;
2871 if (!PyArg_ParseTuple(args, "s", &name))
2872 return NULL;
2874 ldb_msg_remove_attr(self->msg, name);
2876 Py_RETURN_NONE;
2879 static PyObject *py_ldb_msg_keys(PyLdbMessageObject *self)
2881 struct ldb_message *msg = pyldb_Message_AsMessage(self);
2882 Py_ssize_t i, j = 0;
2883 PyObject *obj = PyList_New(msg->num_elements+(msg->dn != NULL?1:0));
2884 if (msg->dn != NULL) {
2885 PyList_SetItem(obj, j, PyStr_FromString("dn"));
2886 j++;
2888 for (i = 0; i < msg->num_elements; i++) {
2889 PyList_SetItem(obj, j, PyStr_FromString(msg->elements[i].name));
2890 j++;
2892 return obj;
2895 static PyObject *py_ldb_msg_getitem_helper(PyLdbMessageObject *self, PyObject *py_name)
2897 struct ldb_message_element *el;
2898 char *name;
2899 struct ldb_message *msg = pyldb_Message_AsMessage(self);
2900 name = PyStr_AsUTF8(py_name);
2901 if (name == NULL) {
2902 PyErr_SetNone(PyExc_TypeError);
2903 return NULL;
2905 if (!ldb_attr_cmp(name, "dn"))
2906 return pyldb_Dn_FromDn(msg->dn);
2907 el = ldb_msg_find_element(msg, name);
2908 if (el == NULL) {
2909 return NULL;
2911 return (PyObject *)PyLdbMessageElement_FromMessageElement(el, msg->elements);
2914 static PyObject *py_ldb_msg_getitem(PyLdbMessageObject *self, PyObject *py_name)
2916 PyObject *ret = py_ldb_msg_getitem_helper(self, py_name);
2917 if (ret == NULL) {
2918 PyErr_SetString(PyExc_KeyError, "No such element");
2919 return NULL;
2921 return ret;
2924 static PyObject *py_ldb_msg_get(PyLdbMessageObject *self, PyObject *args, PyObject *kwargs)
2926 PyObject *def = NULL;
2927 const char *kwnames[] = { "name", "default", "idx", NULL };
2928 const char *name = NULL;
2929 int idx = -1;
2930 struct ldb_message *msg = pyldb_Message_AsMessage(self);
2931 struct ldb_message_element *el;
2933 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "s|Oi:msg",
2934 discard_const_p(char *, kwnames), &name, &def, &idx)) {
2935 return NULL;
2938 if (strcasecmp(name, "dn") == 0) {
2939 return pyldb_Dn_FromDn(msg->dn);
2942 el = ldb_msg_find_element(msg, name);
2944 if (el == NULL || (idx != -1 && el->num_values <= idx)) {
2945 if (def != NULL) {
2946 Py_INCREF(def);
2947 return def;
2949 Py_RETURN_NONE;
2952 if (idx == -1) {
2953 return (PyObject *)PyLdbMessageElement_FromMessageElement(el, msg->elements);
2956 return PyObject_FromLdbValue(&el->values[idx]);
2959 static PyObject *py_ldb_msg_items(PyLdbMessageObject *self)
2961 struct ldb_message *msg = pyldb_Message_AsMessage(self);
2962 Py_ssize_t i, j = 0;
2963 PyObject *l = PyList_New(msg->num_elements + (msg->dn == NULL?0:1));
2964 if (msg->dn != NULL) {
2965 PyList_SetItem(l, 0, Py_BuildValue("(sO)", "dn", pyldb_Dn_FromDn(msg->dn)));
2966 j++;
2968 for (i = 0; i < msg->num_elements; i++, j++) {
2969 PyObject *py_el = PyLdbMessageElement_FromMessageElement(&msg->elements[i], msg->elements);
2970 PyObject *value = Py_BuildValue("(sO)", msg->elements[i].name, py_el);
2971 PyList_SetItem(l, j, value);
2973 return l;
2976 static PyObject *py_ldb_msg_elements(PyLdbMessageObject *self)
2978 struct ldb_message *msg = pyldb_Message_AsMessage(self);
2979 Py_ssize_t i = 0;
2980 PyObject *l = PyList_New(msg->num_elements);
2981 for (i = 0; i < msg->num_elements; i++) {
2982 PyList_SetItem(l, i, PyLdbMessageElement_FromMessageElement(&msg->elements[i], msg->elements));
2984 return l;
2987 static PyObject *py_ldb_msg_add(PyLdbMessageObject *self, PyObject *args)
2989 struct ldb_message *msg = pyldb_Message_AsMessage(self);
2990 PyLdbMessageElementObject *py_element;
2991 int i, ret;
2992 struct ldb_message_element *el;
2993 struct ldb_message_element *el_new;
2995 if (!PyArg_ParseTuple(args, "O!", &PyLdbMessageElement, &py_element))
2996 return NULL;
2998 el = py_element->el;
2999 if (el == NULL) {
3000 PyErr_SetString(PyExc_ValueError, "Invalid MessageElement object");
3001 return NULL;
3004 ret = ldb_msg_add_empty(msg, el->name, el->flags, &el_new);
3005 PyErr_LDB_ERROR_IS_ERR_RAISE(PyExc_LdbError, ret, NULL);
3007 /* now deep copy all attribute values */
3008 el_new->values = talloc_array(msg->elements, struct ldb_val, el->num_values);
3009 if (el_new->values == NULL) {
3010 PyErr_NoMemory();
3011 return NULL;
3013 el_new->num_values = el->num_values;
3015 for (i = 0; i < el->num_values; i++) {
3016 el_new->values[i] = ldb_val_dup(el_new->values, &el->values[i]);
3017 if (el_new->values[i].data == NULL
3018 && el->values[i].length != 0) {
3019 PyErr_NoMemory();
3020 return NULL;
3024 Py_RETURN_NONE;
3027 static PyMethodDef py_ldb_msg_methods[] = {
3028 { "from_dict", (PyCFunction)py_ldb_msg_from_dict, METH_CLASS | METH_VARARGS,
3029 "Message.from_dict(ldb, dict, mod_flag=FLAG_MOD_REPLACE) -> ldb.Message\n"
3030 "Class method to create ldb.Message object from Dictionary.\n"
3031 "mod_flag is one of FLAG_MOD_ADD, FLAG_MOD_REPLACE or FLAG_MOD_DELETE."},
3032 { "keys", (PyCFunction)py_ldb_msg_keys, METH_NOARGS,
3033 "S.keys() -> list\n\n"
3034 "Return sequence of all attribute names." },
3035 { "remove", (PyCFunction)py_ldb_msg_remove_attr, METH_VARARGS,
3036 "S.remove(name)\n\n"
3037 "Remove all entries for attributes with the specified name."},
3038 { "get", (PyCFunction)py_ldb_msg_get, METH_VARARGS | METH_KEYWORDS,
3039 "msg.get(name,default=None,idx=None) -> string\n"
3040 "idx is the index into the values array\n"
3041 "if idx is None, then a list is returned\n"
3042 "if idx is not None, then the element with that index is returned\n"
3043 "if you pass the special name 'dn' then the DN object is returned\n"},
3044 { "items", (PyCFunction)py_ldb_msg_items, METH_NOARGS, NULL },
3045 { "elements", (PyCFunction)py_ldb_msg_elements, METH_NOARGS, NULL },
3046 { "add", (PyCFunction)py_ldb_msg_add, METH_VARARGS,
3047 "S.add(element)\n\n"
3048 "Add an element to this message." },
3049 { NULL },
3052 static PyObject *py_ldb_msg_iter(PyLdbMessageObject *self)
3054 PyObject *list, *iter;
3056 list = py_ldb_msg_keys(self);
3057 iter = PyObject_GetIter(list);
3058 Py_DECREF(list);
3059 return iter;
3062 static int py_ldb_msg_setitem(PyLdbMessageObject *self, PyObject *name, PyObject *value)
3064 char *attr_name;
3066 attr_name = PyStr_AsUTF8(name);
3067 if (attr_name == NULL) {
3068 PyErr_SetNone(PyExc_TypeError);
3069 return -1;
3072 if (value == NULL) {
3073 /* delitem */
3074 ldb_msg_remove_attr(self->msg, attr_name);
3075 } else {
3076 int ret;
3077 struct ldb_message_element *el = PyObject_AsMessageElement(self->msg,
3078 value, 0, attr_name);
3079 if (el == NULL) {
3080 return -1;
3082 ldb_msg_remove_attr(pyldb_Message_AsMessage(self), attr_name);
3083 ret = ldb_msg_add(pyldb_Message_AsMessage(self), el, el->flags);
3084 if (ret != LDB_SUCCESS) {
3085 PyErr_SetLdbError(PyExc_LdbError, ret, NULL);
3086 return -1;
3089 return 0;
3092 static Py_ssize_t py_ldb_msg_length(PyLdbMessageObject *self)
3094 return pyldb_Message_AsMessage(self)->num_elements;
3097 static PyMappingMethods py_ldb_msg_mapping = {
3098 .mp_length = (lenfunc)py_ldb_msg_length,
3099 .mp_subscript = (binaryfunc)py_ldb_msg_getitem,
3100 .mp_ass_subscript = (objobjargproc)py_ldb_msg_setitem,
3103 static PyObject *py_ldb_msg_new(PyTypeObject *type, PyObject *args, PyObject *kwargs)
3105 const char * const kwnames[] = { "dn", NULL };
3106 struct ldb_message *ret;
3107 TALLOC_CTX *mem_ctx;
3108 PyObject *pydn = NULL;
3109 PyLdbMessageObject *py_ret;
3111 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "|O",
3112 discard_const_p(char *, kwnames),
3113 &pydn))
3114 return NULL;
3116 mem_ctx = talloc_new(NULL);
3117 if (mem_ctx == NULL) {
3118 PyErr_NoMemory();
3119 return NULL;
3122 ret = ldb_msg_new(mem_ctx);
3123 if (ret == NULL) {
3124 talloc_free(mem_ctx);
3125 PyErr_NoMemory();
3126 return NULL;
3129 if (pydn != NULL) {
3130 struct ldb_dn *dn;
3131 if (!pyldb_Object_AsDn(NULL, pydn, NULL, &dn)) {
3132 talloc_free(mem_ctx);
3133 return NULL;
3135 ret->dn = talloc_reference(ret, dn);
3138 py_ret = (PyLdbMessageObject *)type->tp_alloc(type, 0);
3139 if (py_ret == NULL) {
3140 PyErr_NoMemory();
3141 talloc_free(mem_ctx);
3142 return NULL;
3145 py_ret->mem_ctx = mem_ctx;
3146 py_ret->msg = ret;
3147 return (PyObject *)py_ret;
3150 static PyObject *PyLdbMessage_FromMessage(struct ldb_message *msg)
3152 PyLdbMessageObject *ret;
3154 ret = (PyLdbMessageObject *)PyLdbMessage.tp_alloc(&PyLdbMessage, 0);
3155 if (ret == NULL) {
3156 PyErr_NoMemory();
3157 return NULL;
3159 ret->mem_ctx = talloc_new(NULL);
3160 ret->msg = talloc_reference(ret->mem_ctx, msg);
3161 return (PyObject *)ret;
3164 static PyObject *py_ldb_msg_get_dn(PyLdbMessageObject *self, void *closure)
3166 struct ldb_message *msg = pyldb_Message_AsMessage(self);
3167 return pyldb_Dn_FromDn(msg->dn);
3170 static int py_ldb_msg_set_dn(PyLdbMessageObject *self, PyObject *value, void *closure)
3172 struct ldb_message *msg = pyldb_Message_AsMessage(self);
3173 if (!pyldb_Dn_Check(value)) {
3174 PyErr_SetString(PyExc_TypeError, "expected dn");
3175 return -1;
3178 msg->dn = talloc_reference(msg, pyldb_Dn_AsDn(value));
3179 return 0;
3182 static PyObject *py_ldb_msg_get_text(PyObject *self, void *closure)
3184 return wrap_text("MessageTextWrapper", self);
3187 static PyGetSetDef py_ldb_msg_getset[] = {
3188 { discard_const_p(char, "dn"), (getter)py_ldb_msg_get_dn, (setter)py_ldb_msg_set_dn, NULL },
3189 { discard_const_p(char, "text"), (getter)py_ldb_msg_get_text, NULL, NULL },
3190 { NULL }
3193 static PyObject *py_ldb_msg_repr(PyLdbMessageObject *self)
3195 PyObject *dict = PyDict_New(), *ret, *repr;
3196 if (PyDict_Update(dict, (PyObject *)self) != 0)
3197 return NULL;
3198 repr = PyObject_Repr(dict);
3199 if (repr == NULL) {
3200 Py_DECREF(dict);
3201 return NULL;
3203 ret = PyStr_FromFormat("Message(%s)", PyStr_AsUTF8(repr));
3204 Py_DECREF(repr);
3205 Py_DECREF(dict);
3206 return ret;
3209 static void py_ldb_msg_dealloc(PyLdbMessageObject *self)
3211 talloc_free(self->mem_ctx);
3212 PyObject_Del(self);
3215 static PyObject *py_ldb_msg_richcmp(PyLdbMessageObject *py_msg1,
3216 PyLdbMessageObject *py_msg2, int op)
3218 struct ldb_message *msg1, *msg2;
3219 unsigned int i;
3220 int ret;
3222 if (!PyLdbMessage_Check(py_msg2)) {
3223 Py_INCREF(Py_NotImplemented);
3224 return Py_NotImplemented;
3227 msg1 = pyldb_Message_AsMessage(py_msg1),
3228 msg2 = pyldb_Message_AsMessage(py_msg2);
3230 if ((msg1->dn != NULL) || (msg2->dn != NULL)) {
3231 ret = ldb_dn_compare(msg1->dn, msg2->dn);
3232 if (ret != 0) {
3233 return richcmp(ret, op);
3237 ret = msg1->num_elements - msg2->num_elements;
3238 if (ret != 0) {
3239 return richcmp(ret, op);
3242 for (i = 0; i < msg1->num_elements; i++) {
3243 ret = ldb_msg_element_compare_name(&msg1->elements[i],
3244 &msg2->elements[i]);
3245 if (ret != 0) {
3246 return richcmp(ret, op);
3249 ret = ldb_msg_element_compare(&msg1->elements[i],
3250 &msg2->elements[i]);
3251 if (ret != 0) {
3252 return richcmp(ret, op);
3256 return richcmp(0, op);
3259 static PyTypeObject PyLdbMessage = {
3260 .tp_name = "ldb.Message",
3261 .tp_methods = py_ldb_msg_methods,
3262 .tp_getset = py_ldb_msg_getset,
3263 .tp_as_mapping = &py_ldb_msg_mapping,
3264 .tp_basicsize = sizeof(PyLdbMessageObject),
3265 .tp_dealloc = (destructor)py_ldb_msg_dealloc,
3266 .tp_new = py_ldb_msg_new,
3267 .tp_repr = (reprfunc)py_ldb_msg_repr,
3268 .tp_flags = Py_TPFLAGS_DEFAULT,
3269 .tp_iter = (getiterfunc)py_ldb_msg_iter,
3270 .tp_richcompare = (richcmpfunc)py_ldb_msg_richcmp,
3271 .tp_doc = "A LDB Message",
3274 static PyObject *PyLdbTree_FromTree(struct ldb_parse_tree *tree)
3276 PyLdbTreeObject *ret;
3278 ret = (PyLdbTreeObject *)PyLdbTree.tp_alloc(&PyLdbTree, 0);
3279 if (ret == NULL) {
3280 PyErr_NoMemory();
3281 return NULL;
3284 ret->mem_ctx = talloc_new(NULL);
3285 ret->tree = talloc_reference(ret->mem_ctx, tree);
3286 return (PyObject *)ret;
3289 static void py_ldb_tree_dealloc(PyLdbTreeObject *self)
3291 talloc_free(self->mem_ctx);
3292 PyObject_Del(self);
3295 static PyTypeObject PyLdbTree = {
3296 .tp_name = "ldb.Tree",
3297 .tp_basicsize = sizeof(PyLdbTreeObject),
3298 .tp_dealloc = (destructor)py_ldb_tree_dealloc,
3299 .tp_flags = Py_TPFLAGS_DEFAULT,
3300 .tp_doc = "A search tree",
3303 /* Ldb_module */
3304 static int py_module_search(struct ldb_module *mod, struct ldb_request *req)
3306 PyObject *py_ldb = (PyObject *)mod->private_data;
3307 PyObject *py_result, *py_base, *py_attrs, *py_tree;
3309 py_base = pyldb_Dn_FromDn(req->op.search.base);
3311 if (py_base == NULL)
3312 return LDB_ERR_OPERATIONS_ERROR;
3314 py_tree = PyLdbTree_FromTree(req->op.search.tree);
3316 if (py_tree == NULL)
3317 return LDB_ERR_OPERATIONS_ERROR;
3319 if (req->op.search.attrs == NULL) {
3320 py_attrs = Py_None;
3321 } else {
3322 int i, len;
3323 for (len = 0; req->op.search.attrs[len]; len++);
3324 py_attrs = PyList_New(len);
3325 for (i = 0; i < len; i++)
3326 PyList_SetItem(py_attrs, i, PyStr_FromString(req->op.search.attrs[i]));
3329 py_result = PyObject_CallMethod(py_ldb, discard_const_p(char, "search"),
3330 discard_const_p(char, "OiOO"),
3331 py_base, req->op.search.scope, py_tree, py_attrs);
3333 Py_DECREF(py_attrs);
3334 Py_DECREF(py_tree);
3335 Py_DECREF(py_base);
3337 if (py_result == NULL) {
3338 return LDB_ERR_PYTHON_EXCEPTION;
3341 req->op.search.res = PyLdbResult_AsResult(NULL, py_result);
3342 if (req->op.search.res == NULL) {
3343 return LDB_ERR_PYTHON_EXCEPTION;
3346 Py_DECREF(py_result);
3348 return LDB_SUCCESS;
3351 static int py_module_add(struct ldb_module *mod, struct ldb_request *req)
3353 PyObject *py_ldb = (PyObject *)mod->private_data;
3354 PyObject *py_result, *py_msg;
3356 py_msg = PyLdbMessage_FromMessage(discard_const_p(struct ldb_message, req->op.add.message));
3358 if (py_msg == NULL) {
3359 return LDB_ERR_OPERATIONS_ERROR;
3362 py_result = PyObject_CallMethod(py_ldb, discard_const_p(char, "add"),
3363 discard_const_p(char, "O"),
3364 py_msg);
3366 Py_DECREF(py_msg);
3368 if (py_result == NULL) {
3369 return LDB_ERR_PYTHON_EXCEPTION;
3372 Py_DECREF(py_result);
3374 return LDB_SUCCESS;
3377 static int py_module_modify(struct ldb_module *mod, struct ldb_request *req)
3379 PyObject *py_ldb = (PyObject *)mod->private_data;
3380 PyObject *py_result, *py_msg;
3382 py_msg = PyLdbMessage_FromMessage(discard_const_p(struct ldb_message, req->op.mod.message));
3384 if (py_msg == NULL) {
3385 return LDB_ERR_OPERATIONS_ERROR;
3388 py_result = PyObject_CallMethod(py_ldb, discard_const_p(char, "modify"),
3389 discard_const_p(char, "O"),
3390 py_msg);
3392 Py_DECREF(py_msg);
3394 if (py_result == NULL) {
3395 return LDB_ERR_PYTHON_EXCEPTION;
3398 Py_DECREF(py_result);
3400 return LDB_SUCCESS;
3403 static int py_module_del(struct ldb_module *mod, struct ldb_request *req)
3405 PyObject *py_ldb = (PyObject *)mod->private_data;
3406 PyObject *py_result, *py_dn;
3408 py_dn = pyldb_Dn_FromDn(req->op.del.dn);
3410 if (py_dn == NULL)
3411 return LDB_ERR_OPERATIONS_ERROR;
3413 py_result = PyObject_CallMethod(py_ldb, discard_const_p(char, "delete"),
3414 discard_const_p(char, "O"),
3415 py_dn);
3417 if (py_result == NULL) {
3418 return LDB_ERR_PYTHON_EXCEPTION;
3421 Py_DECREF(py_result);
3423 return LDB_SUCCESS;
3426 static int py_module_rename(struct ldb_module *mod, struct ldb_request *req)
3428 PyObject *py_ldb = (PyObject *)mod->private_data;
3429 PyObject *py_result, *py_olddn, *py_newdn;
3431 py_olddn = pyldb_Dn_FromDn(req->op.rename.olddn);
3433 if (py_olddn == NULL)
3434 return LDB_ERR_OPERATIONS_ERROR;
3436 py_newdn = pyldb_Dn_FromDn(req->op.rename.newdn);
3438 if (py_newdn == NULL)
3439 return LDB_ERR_OPERATIONS_ERROR;
3441 py_result = PyObject_CallMethod(py_ldb, discard_const_p(char, "rename"),
3442 discard_const_p(char, "OO"),
3443 py_olddn, py_newdn);
3445 Py_DECREF(py_olddn);
3446 Py_DECREF(py_newdn);
3448 if (py_result == NULL) {
3449 return LDB_ERR_PYTHON_EXCEPTION;
3452 Py_DECREF(py_result);
3454 return LDB_SUCCESS;
3457 static int py_module_request(struct ldb_module *mod, struct ldb_request *req)
3459 PyObject *py_ldb = (PyObject *)mod->private_data;
3460 PyObject *py_result;
3462 py_result = PyObject_CallMethod(py_ldb, discard_const_p(char, "request"),
3463 discard_const_p(char, ""));
3465 Py_XDECREF(py_result);
3467 return LDB_ERR_OPERATIONS_ERROR;
3470 static int py_module_extended(struct ldb_module *mod, struct ldb_request *req)
3472 PyObject *py_ldb = (PyObject *)mod->private_data;
3473 PyObject *py_result;
3475 py_result = PyObject_CallMethod(py_ldb, discard_const_p(char, "extended"),
3476 discard_const_p(char, ""));
3478 Py_XDECREF(py_result);
3480 return LDB_ERR_OPERATIONS_ERROR;
3483 static int py_module_start_transaction(struct ldb_module *mod)
3485 PyObject *py_ldb = (PyObject *)mod->private_data;
3486 PyObject *py_result;
3488 py_result = PyObject_CallMethod(py_ldb, discard_const_p(char, "start_transaction"),
3489 discard_const_p(char, ""));
3491 if (py_result == NULL) {
3492 return LDB_ERR_PYTHON_EXCEPTION;
3495 Py_DECREF(py_result);
3497 return LDB_SUCCESS;
3500 static int py_module_end_transaction(struct ldb_module *mod)
3502 PyObject *py_ldb = (PyObject *)mod->private_data;
3503 PyObject *py_result;
3505 py_result = PyObject_CallMethod(py_ldb, discard_const_p(char, "end_transaction"),
3506 discard_const_p(char, ""));
3508 if (py_result == NULL) {
3509 return LDB_ERR_PYTHON_EXCEPTION;
3512 Py_DECREF(py_result);
3514 return LDB_SUCCESS;
3517 static int py_module_del_transaction(struct ldb_module *mod)
3519 PyObject *py_ldb = (PyObject *)mod->private_data;
3520 PyObject *py_result;
3522 py_result = PyObject_CallMethod(py_ldb, discard_const_p(char, "del_transaction"),
3523 discard_const_p(char, ""));
3525 if (py_result == NULL) {
3526 return LDB_ERR_PYTHON_EXCEPTION;
3529 Py_DECREF(py_result);
3531 return LDB_SUCCESS;
3534 static int py_module_destructor(struct ldb_module *mod)
3536 Py_DECREF((PyObject *)mod->private_data);
3537 return 0;
3540 static int py_module_init(struct ldb_module *mod)
3542 PyObject *py_class = (PyObject *)mod->ops->private_data;
3543 PyObject *py_result, *py_next, *py_ldb;
3545 py_ldb = PyLdb_FromLdbContext(mod->ldb);
3547 if (py_ldb == NULL)
3548 return LDB_ERR_OPERATIONS_ERROR;
3550 py_next = PyLdbModule_FromModule(mod->next);
3552 if (py_next == NULL)
3553 return LDB_ERR_OPERATIONS_ERROR;
3555 py_result = PyObject_CallFunction(py_class, discard_const_p(char, "OO"),
3556 py_ldb, py_next);
3558 if (py_result == NULL) {
3559 return LDB_ERR_PYTHON_EXCEPTION;
3562 mod->private_data = py_result;
3564 talloc_set_destructor(mod, py_module_destructor);
3566 return ldb_next_init(mod);
3569 static PyObject *py_register_module(PyObject *module, PyObject *args)
3571 int ret;
3572 struct ldb_module_ops *ops;
3573 PyObject *input;
3575 if (!PyArg_ParseTuple(args, "O", &input))
3576 return NULL;
3578 ops = talloc_zero(talloc_autofree_context(), struct ldb_module_ops);
3579 if (ops == NULL) {
3580 PyErr_NoMemory();
3581 return NULL;
3584 ops->name = talloc_strdup(ops, PyStr_AsUTF8(PyObject_GetAttrString(input, discard_const_p(char, "name"))));
3586 Py_INCREF(input);
3587 ops->private_data = input;
3588 ops->init_context = py_module_init;
3589 ops->search = py_module_search;
3590 ops->add = py_module_add;
3591 ops->modify = py_module_modify;
3592 ops->del = py_module_del;
3593 ops->rename = py_module_rename;
3594 ops->request = py_module_request;
3595 ops->extended = py_module_extended;
3596 ops->start_transaction = py_module_start_transaction;
3597 ops->end_transaction = py_module_end_transaction;
3598 ops->del_transaction = py_module_del_transaction;
3600 ret = ldb_register_module(ops);
3602 PyErr_LDB_ERROR_IS_ERR_RAISE(PyExc_LdbError, ret, NULL);
3604 Py_RETURN_NONE;
3607 static PyObject *py_timestring(PyObject *module, PyObject *args)
3609 /* most times "time_t" is a signed integer type with 32 or 64 bit:
3610 * http://stackoverflow.com/questions/471248/what-is-ultimately-a-time-t-typedef-to */
3611 long int t_val;
3612 char *tresult;
3613 PyObject *ret;
3614 if (!PyArg_ParseTuple(args, "l", &t_val))
3615 return NULL;
3616 tresult = ldb_timestring(NULL, (time_t) t_val);
3617 ret = PyStr_FromString(tresult);
3618 talloc_free(tresult);
3619 return ret;
3622 static PyObject *py_string_to_time(PyObject *module, PyObject *args)
3624 char *str;
3625 if (!PyArg_ParseTuple(args, "s", &str))
3626 return NULL;
3628 return PyInt_FromLong(ldb_string_to_time(str));
3631 static PyObject *py_valid_attr_name(PyObject *self, PyObject *args)
3633 char *name;
3634 if (!PyArg_ParseTuple(args, "s", &name))
3635 return NULL;
3636 return PyBool_FromLong(ldb_valid_attr_name(name));
3640 encode a string using RFC2254 rules
3642 static PyObject *py_binary_encode(PyObject *self, PyObject *args)
3644 char *str, *encoded;
3645 Py_ssize_t size = 0;
3646 struct ldb_val val;
3647 PyObject *ret;
3649 if (!PyArg_ParseTuple(args, "s#", &str, &size))
3650 return NULL;
3651 val.data = (uint8_t *)str;
3652 val.length = size;
3654 encoded = ldb_binary_encode(NULL, val);
3655 if (encoded == NULL) {
3656 PyErr_SetString(PyExc_TypeError, "unable to encode binary string");
3657 return NULL;
3659 ret = PyStr_FromString(encoded);
3660 talloc_free(encoded);
3661 return ret;
3665 decode a string using RFC2254 rules
3667 static PyObject *py_binary_decode(PyObject *self, PyObject *args)
3669 char *str;
3670 struct ldb_val val;
3671 PyObject *ret;
3673 if (!PyArg_ParseTuple(args, "s", &str))
3674 return NULL;
3676 val = ldb_binary_decode(NULL, str);
3677 if (val.data == NULL) {
3678 PyErr_SetString(PyExc_TypeError, "unable to decode binary string");
3679 return NULL;
3681 ret = PyBytes_FromStringAndSize((const char*)val.data, val.length);
3682 talloc_free(val.data);
3683 return ret;
3686 static PyMethodDef py_ldb_global_methods[] = {
3687 { "register_module", py_register_module, METH_VARARGS,
3688 "S.register_module(module) -> None\n\n"
3689 "Register a LDB module."},
3690 { "timestring", py_timestring, METH_VARARGS,
3691 "S.timestring(int) -> string\n\n"
3692 "Generate a LDAP time string from a UNIX timestamp" },
3693 { "string_to_time", py_string_to_time, METH_VARARGS,
3694 "S.string_to_time(string) -> int\n\n"
3695 "Parse a LDAP time string into a UNIX timestamp." },
3696 { "valid_attr_name", py_valid_attr_name, METH_VARARGS,
3697 "S.valid_attr_name(name) -> bool\n\nn"
3698 "Check whether the supplied name is a valid attribute name." },
3699 { "open", (PyCFunction)py_ldb_new, METH_VARARGS|METH_KEYWORDS,
3700 "S.open() -> Ldb\n\n"
3701 "Open a new LDB context." },
3702 { "binary_encode", py_binary_encode, METH_VARARGS,
3703 "S.binary_encode(string) -> string\n\n"
3704 "Perform a RFC2254 binary encoding on a string" },
3705 { "binary_decode", py_binary_decode, METH_VARARGS,
3706 "S.binary_decode(string) -> string\n\n"
3707 "Perform a RFC2254 binary decode on a string" },
3708 { NULL }
3711 #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."
3713 #if PY_MAJOR_VERSION >= 3
3714 static struct PyModuleDef moduledef = {
3715 PyModuleDef_HEAD_INIT,
3716 .m_name = "ldb",
3717 .m_doc = MODULE_DOC,
3718 .m_size = -1,
3719 .m_methods = py_ldb_global_methods,
3721 #endif
3723 static PyObject* module_init(void)
3725 PyObject *m;
3727 if (PyType_Ready(&PyLdbDn) < 0)
3728 return NULL;
3730 if (PyType_Ready(&PyLdbMessage) < 0)
3731 return NULL;
3733 if (PyType_Ready(&PyLdbMessageElement) < 0)
3734 return NULL;
3736 if (PyType_Ready(&PyLdb) < 0)
3737 return NULL;
3739 if (PyType_Ready(&PyLdbModule) < 0)
3740 return NULL;
3742 if (PyType_Ready(&PyLdbTree) < 0)
3743 return NULL;
3745 if (PyType_Ready(&PyLdbResult) < 0)
3746 return NULL;
3748 if (PyType_Ready(&PyLdbControl) < 0)
3749 return NULL;
3751 #if PY_MAJOR_VERSION >= 3
3752 m = PyModule_Create(&moduledef);
3753 #else
3754 m = Py_InitModule3("ldb", py_ldb_global_methods, MODULE_DOC);
3755 #endif
3756 if (m == NULL)
3757 return NULL;
3759 #define ADD_LDB_INT(val) PyModule_AddIntConstant(m, #val, LDB_ ## val)
3761 ADD_LDB_INT(SEQ_HIGHEST_SEQ);
3762 ADD_LDB_INT(SEQ_HIGHEST_TIMESTAMP);
3763 ADD_LDB_INT(SEQ_NEXT);
3764 ADD_LDB_INT(SCOPE_DEFAULT);
3765 ADD_LDB_INT(SCOPE_BASE);
3766 ADD_LDB_INT(SCOPE_ONELEVEL);
3767 ADD_LDB_INT(SCOPE_SUBTREE);
3769 ADD_LDB_INT(CHANGETYPE_NONE);
3770 ADD_LDB_INT(CHANGETYPE_ADD);
3771 ADD_LDB_INT(CHANGETYPE_DELETE);
3772 ADD_LDB_INT(CHANGETYPE_MODIFY);
3774 ADD_LDB_INT(FLAG_MOD_ADD);
3775 ADD_LDB_INT(FLAG_MOD_REPLACE);
3776 ADD_LDB_INT(FLAG_MOD_DELETE);
3778 ADD_LDB_INT(SUCCESS);
3779 ADD_LDB_INT(ERR_OPERATIONS_ERROR);
3780 ADD_LDB_INT(ERR_PROTOCOL_ERROR);
3781 ADD_LDB_INT(ERR_TIME_LIMIT_EXCEEDED);
3782 ADD_LDB_INT(ERR_SIZE_LIMIT_EXCEEDED);
3783 ADD_LDB_INT(ERR_COMPARE_FALSE);
3784 ADD_LDB_INT(ERR_COMPARE_TRUE);
3785 ADD_LDB_INT(ERR_AUTH_METHOD_NOT_SUPPORTED);
3786 ADD_LDB_INT(ERR_STRONG_AUTH_REQUIRED);
3787 ADD_LDB_INT(ERR_REFERRAL);
3788 ADD_LDB_INT(ERR_ADMIN_LIMIT_EXCEEDED);
3789 ADD_LDB_INT(ERR_UNSUPPORTED_CRITICAL_EXTENSION);
3790 ADD_LDB_INT(ERR_CONFIDENTIALITY_REQUIRED);
3791 ADD_LDB_INT(ERR_SASL_BIND_IN_PROGRESS);
3792 ADD_LDB_INT(ERR_NO_SUCH_ATTRIBUTE);
3793 ADD_LDB_INT(ERR_UNDEFINED_ATTRIBUTE_TYPE);
3794 ADD_LDB_INT(ERR_INAPPROPRIATE_MATCHING);
3795 ADD_LDB_INT(ERR_CONSTRAINT_VIOLATION);
3796 ADD_LDB_INT(ERR_ATTRIBUTE_OR_VALUE_EXISTS);
3797 ADD_LDB_INT(ERR_INVALID_ATTRIBUTE_SYNTAX);
3798 ADD_LDB_INT(ERR_NO_SUCH_OBJECT);
3799 ADD_LDB_INT(ERR_ALIAS_PROBLEM);
3800 ADD_LDB_INT(ERR_INVALID_DN_SYNTAX);
3801 ADD_LDB_INT(ERR_ALIAS_DEREFERENCING_PROBLEM);
3802 ADD_LDB_INT(ERR_INAPPROPRIATE_AUTHENTICATION);
3803 ADD_LDB_INT(ERR_INVALID_CREDENTIALS);
3804 ADD_LDB_INT(ERR_INSUFFICIENT_ACCESS_RIGHTS);
3805 ADD_LDB_INT(ERR_BUSY);
3806 ADD_LDB_INT(ERR_UNAVAILABLE);
3807 ADD_LDB_INT(ERR_UNWILLING_TO_PERFORM);
3808 ADD_LDB_INT(ERR_LOOP_DETECT);
3809 ADD_LDB_INT(ERR_NAMING_VIOLATION);
3810 ADD_LDB_INT(ERR_OBJECT_CLASS_VIOLATION);
3811 ADD_LDB_INT(ERR_NOT_ALLOWED_ON_NON_LEAF);
3812 ADD_LDB_INT(ERR_NOT_ALLOWED_ON_RDN);
3813 ADD_LDB_INT(ERR_ENTRY_ALREADY_EXISTS);
3814 ADD_LDB_INT(ERR_OBJECT_CLASS_MODS_PROHIBITED);
3815 ADD_LDB_INT(ERR_AFFECTS_MULTIPLE_DSAS);
3816 ADD_LDB_INT(ERR_OTHER);
3818 ADD_LDB_INT(FLG_RDONLY);
3819 ADD_LDB_INT(FLG_NOSYNC);
3820 ADD_LDB_INT(FLG_RECONNECT);
3821 ADD_LDB_INT(FLG_NOMMAP);
3823 /* Historical misspelling */
3824 PyModule_AddIntConstant(m, "ERR_ALIAS_DEREFERINCING_PROBLEM", LDB_ERR_ALIAS_DEREFERENCING_PROBLEM);
3826 PyModule_AddStringConstant(m, "__docformat__", "restructuredText");
3828 PyExc_LdbError = PyErr_NewException(discard_const_p(char, "_ldb.LdbError"), NULL, NULL);
3829 PyModule_AddObject(m, "LdbError", PyExc_LdbError);
3831 Py_INCREF(&PyLdb);
3832 Py_INCREF(&PyLdbDn);
3833 Py_INCREF(&PyLdbModule);
3834 Py_INCREF(&PyLdbMessage);
3835 Py_INCREF(&PyLdbMessageElement);
3836 Py_INCREF(&PyLdbTree);
3837 Py_INCREF(&PyLdbResult);
3838 Py_INCREF(&PyLdbControl);
3840 PyModule_AddObject(m, "Ldb", (PyObject *)&PyLdb);
3841 PyModule_AddObject(m, "Dn", (PyObject *)&PyLdbDn);
3842 PyModule_AddObject(m, "Message", (PyObject *)&PyLdbMessage);
3843 PyModule_AddObject(m, "MessageElement", (PyObject *)&PyLdbMessageElement);
3844 PyModule_AddObject(m, "Module", (PyObject *)&PyLdbModule);
3845 PyModule_AddObject(m, "Tree", (PyObject *)&PyLdbTree);
3846 PyModule_AddObject(m, "Control", (PyObject *)&PyLdbControl);
3848 PyModule_AddStringConstant(m, "__version__", PACKAGE_VERSION);
3850 #define ADD_LDB_STRING(val) PyModule_AddStringConstant(m, #val, LDB_## val)
3852 ADD_LDB_STRING(SYNTAX_DN);
3853 ADD_LDB_STRING(SYNTAX_DIRECTORY_STRING);
3854 ADD_LDB_STRING(SYNTAX_INTEGER);
3855 ADD_LDB_STRING(SYNTAX_BOOLEAN);
3856 ADD_LDB_STRING(SYNTAX_OCTET_STRING);
3857 ADD_LDB_STRING(SYNTAX_UTC_TIME);
3858 ADD_LDB_STRING(OID_COMPARATOR_AND);
3859 ADD_LDB_STRING(OID_COMPARATOR_OR);
3861 return m;
3864 #if PY_MAJOR_VERSION >= 3
3865 PyMODINIT_FUNC PyInit_ldb(void);
3866 PyMODINIT_FUNC PyInit_ldb(void)
3868 return module_init();
3870 #else
3871 void initldb(void);
3872 void initldb(void)
3874 module_init();
3876 #endif