s3: client - "client use spnego principal = yes" code checks wrong name.
[Samba.git] / lib / ldb / pyldb.c
blobf18e06e5c686512a03c1a7b8ff7ea7fcaba64efa
1 /*
2 Unix SMB/CIFS implementation.
4 Python interface to ldb.
6 Copyright (C) 2005,2006 Tim Potter <tpot@samba.org>
7 Copyright (C) 2006 Simo Sorce <idra@samba.org>
8 Copyright (C) 2007-2010 Jelmer Vernooij <jelmer@samba.org>
9 Copyright (C) 2009-2010 Matthias Dieter Wallnöfer
10 Copyright (C) 2009-2011 Andrew Tridgell
11 Copyright (C) 2009-2011 Andrew Bartlett
13 ** NOTE! The following LGPL license applies to the ldb
14 ** library. This does NOT imply that all of Samba is released
15 ** under the LGPL
17 This library is free software; you can redistribute it and/or
18 modify it under the terms of the GNU Lesser General Public
19 License as published by the Free Software Foundation; either
20 version 3 of the License, or (at your option) any later version.
22 This library is distributed in the hope that it will be useful,
23 but WITHOUT ANY WARRANTY; without even the implied warranty of
24 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
25 Lesser General Public License for more details.
27 You should have received a copy of the GNU Lesser General Public
28 License along with this library; if not, see <http://www.gnu.org/licenses/>.
31 #include <Python.h>
32 #include "ldb_private.h"
33 #include "pyldb.h"
35 void initldb(void);
36 static PyObject *PyLdbMessage_FromMessage(struct ldb_message *msg);
37 static PyObject *PyExc_LdbError;
39 static PyTypeObject PyLdbControl;
40 static PyTypeObject PyLdbResult;
41 static PyTypeObject PyLdbMessage;
42 #define PyLdbMessage_Check(ob) PyObject_TypeCheck(ob, &PyLdbMessage)
43 static PyTypeObject PyLdbModule;
44 static PyTypeObject PyLdbDn;
45 #define pyldb_Dn_Check(ob) PyObject_TypeCheck(ob, &PyLdbDn)
46 static PyTypeObject PyLdb;
47 #define PyLdb_Check(ob) PyObject_TypeCheck(ob, &PyLdb)
48 static PyTypeObject PyLdbMessageElement;
49 #define pyldb_MessageElement_Check(ob) PyObject_TypeCheck(ob, &PyLdbMessageElement)
51 static PyTypeObject PyLdbTree;
52 static PyObject *PyLdb_FromLdbContext(struct ldb_context *ldb_ctx);
53 static PyObject *PyLdbModule_FromModule(struct ldb_module *mod);
54 static struct ldb_message_element *PyObject_AsMessageElement(
55 TALLOC_CTX *mem_ctx,
56 PyObject *set_obj,
57 unsigned int flags,
58 const char *attr_name);
60 /* There's no Py_ssize_t in 2.4, apparently */
61 #if PY_MAJOR_VERSION == 2 && PY_MINOR_VERSION < 5
62 typedef int Py_ssize_t;
63 typedef inquiry lenfunc;
64 typedef intargfunc ssizeargfunc;
65 #endif
67 #define SIGN(a) (((a) == 0)?0:((a) < 0?-1:1))
71 static PyObject *py_ldb_control_str(PyLdbControlObject *self)
73 if (self->data != NULL) {
74 char* control = ldb_control_to_string(self->mem_ctx, self->data);
75 if (control == NULL) {
76 PyErr_NoMemory();
77 return NULL;
79 return PyString_FromString(control);
80 } else {
81 return PyString_FromFormat("ldb control");
85 static void py_ldb_control_dealloc(PyLdbControlObject *self)
87 if (self->mem_ctx != NULL) {
88 talloc_free(self->mem_ctx);
90 self->data = NULL;
91 Py_TYPE(self)->tp_free(self);
94 static PyObject *py_ldb_control_get_oid(PyLdbControlObject *self)
96 return PyString_FromString(self->data->oid);
99 static PyObject *py_ldb_control_get_critical(PyLdbControlObject *self)
101 return PyBool_FromLong(self->data->critical);
104 static PyObject *py_ldb_control_set_critical(PyLdbControlObject *self, PyObject *value, void *closure)
106 if (PyObject_IsTrue(value)) {
107 self->data->critical = true;
108 } else {
109 self->data->critical = false;
111 return 0;
114 static PyObject *py_ldb_control_new(PyTypeObject *type, PyObject *args, PyObject *kwargs)
116 char *data = NULL;
117 const char * const kwnames[] = { "ldb", "data", NULL };
118 struct ldb_control *parsed_controls;
119 PyLdbControlObject *ret;
120 PyObject *py_ldb;
121 TALLOC_CTX *mem_ctx;
122 struct ldb_context *ldb_ctx;
124 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "O!s",
125 discard_const_p(char *, kwnames),
126 &PyLdb, &py_ldb, &data))
127 return NULL;
129 mem_ctx = talloc_new(NULL);
130 if (mem_ctx == NULL) {
131 PyErr_NoMemory();
132 return NULL;
135 ldb_ctx = pyldb_Ldb_AsLdbContext(py_ldb);
136 parsed_controls = ldb_parse_control_from_string(ldb_ctx, mem_ctx, data);
138 if (!parsed_controls) {
139 talloc_free(mem_ctx);
140 PyErr_SetString(PyExc_ValueError, "unable to parse control string");
141 return NULL;
144 ret = PyObject_New(PyLdbControlObject, type);
145 if (ret == NULL) {
146 PyErr_NoMemory();
147 talloc_free(mem_ctx);
148 return NULL;
151 ret->mem_ctx = mem_ctx;
153 ret->data = talloc_move(mem_ctx, &parsed_controls);
154 if (ret->data == NULL) {
155 Py_DECREF(ret);
156 PyErr_NoMemory();
157 talloc_free(mem_ctx);
158 return NULL;
161 return (PyObject *)ret;
164 static PyGetSetDef py_ldb_control_getset[] = {
165 { discard_const_p(char, "oid"), (getter)py_ldb_control_get_oid, NULL, NULL },
166 { discard_const_p(char, "critical"), (getter)py_ldb_control_get_critical, (setter)py_ldb_control_set_critical, NULL },
167 { NULL }
170 static PyTypeObject PyLdbControl = {
171 .tp_name = "ldb.control",
172 .tp_dealloc = (destructor)py_ldb_control_dealloc,
173 .tp_getattro = PyObject_GenericGetAttr,
174 .tp_basicsize = sizeof(PyLdbControlObject),
175 .tp_getset = py_ldb_control_getset,
176 .tp_doc = "LDB control.",
177 .tp_str = (reprfunc)py_ldb_control_str,
178 .tp_new = py_ldb_control_new,
179 .tp_flags = Py_TPFLAGS_DEFAULT|Py_TPFLAGS_BASETYPE,
182 static void PyErr_SetLdbError(PyObject *error, int ret, struct ldb_context *ldb_ctx)
184 if (ret == LDB_ERR_PYTHON_EXCEPTION)
185 return; /* Python exception should already be set, just keep that */
187 PyErr_SetObject(error,
188 Py_BuildValue(discard_const_p(char, "(i,s)"), ret,
189 ldb_ctx == NULL?ldb_strerror(ret):ldb_errstring(ldb_ctx)));
192 static PyObject *PyObject_FromLdbValue(const struct ldb_val *val)
194 return PyString_FromStringAndSize((const char *)val->data, val->length);
198 * Create a Python object from a ldb_result.
200 * @param result LDB result to convert
201 * @return Python object with converted result (a list object)
203 static PyObject *PyLdbControl_FromControl(struct ldb_control *control)
205 TALLOC_CTX *ctl_ctx = talloc_new(NULL);
206 PyLdbControlObject *ctrl;
207 if (ctl_ctx == NULL) {
208 PyErr_NoMemory();
209 return NULL;
212 ctrl = (PyLdbControlObject *)PyLdbControl.tp_alloc(&PyLdbControl, 0);
213 if (ctrl == NULL) {
214 talloc_free(ctl_ctx);
215 PyErr_NoMemory();
216 return NULL;
218 ctrl->mem_ctx = ctl_ctx;
219 ctrl->data = talloc_steal(ctrl->mem_ctx, control);
220 if (ctrl->data == NULL) {
221 Py_DECREF(ctrl);
222 PyErr_NoMemory();
223 return NULL;
225 return (PyObject*) ctrl;
229 * Create a Python object from a ldb_result.
231 * @param result LDB result to convert
232 * @return Python object with converted result (a list object)
234 static PyObject *PyLdbResult_FromResult(struct ldb_result *result)
236 PyLdbResultObject *ret;
237 PyObject *list, *controls, *referals;
238 Py_ssize_t i;
240 if (result == NULL) {
241 Py_RETURN_NONE;
244 ret = (PyLdbResultObject *)PyLdbResult.tp_alloc(&PyLdbResult, 0);
245 if (ret == NULL) {
246 PyErr_NoMemory();
247 return NULL;
250 list = PyList_New(result->count);
251 if (list == NULL) {
252 PyErr_NoMemory();
253 Py_DECREF(ret);
254 return NULL;
257 for (i = 0; i < result->count; i++) {
258 PyList_SetItem(list, i, PyLdbMessage_FromMessage(result->msgs[i]));
261 ret->mem_ctx = talloc_new(NULL);
262 if (ret->mem_ctx == NULL) {
263 Py_DECREF(list);
264 Py_DECREF(ret);
265 PyErr_NoMemory();
266 return NULL;
269 ret->msgs = list;
271 if (result->controls) {
272 i = 0;
273 while (result->controls[i]) {
274 i++;
276 controls = PyList_New(i);
277 if (controls == NULL) {
278 Py_DECREF(ret);
279 PyErr_NoMemory();
280 return NULL;
282 for (i=0; result->controls[i]; i++) {
283 PyObject *ctrl = (PyObject*) PyLdbControl_FromControl(result->controls[i]);
284 if (ctrl == NULL) {
285 Py_DECREF(ret);
286 Py_DECREF(controls);
287 PyErr_NoMemory();
288 return NULL;
290 PyList_SetItem(controls, i, ctrl);
292 } else {
294 * No controls so we keep an empty list
296 controls = PyList_New(0);
297 if (controls == NULL) {
298 Py_DECREF(ret);
299 PyErr_NoMemory();
300 return NULL;
304 ret->controls = controls;
306 i = 0;
308 while (result->refs && result->refs[i]) {
309 i++;
312 referals = PyList_New(i);
313 if (referals == NULL) {
314 Py_DECREF(ret);
315 PyErr_NoMemory();
316 return NULL;
319 for (i = 0;result->refs && result->refs[i]; i++) {
320 PyList_SetItem(referals, i, PyString_FromString(result->refs[i]));
322 ret->referals = referals;
323 return (PyObject *)ret;
327 * Create a LDB Result from a Python object.
328 * If conversion fails, NULL will be returned and a Python exception set.
330 * Note: the result object only includes the messages at the moment; extended
331 * result, controls and referrals are ignored.
333 * @param mem_ctx Memory context in which to allocate the LDB Result
334 * @param obj Python object to convert
335 * @return a ldb_result, or NULL if the conversion failed
337 static struct ldb_result *PyLdbResult_AsResult(TALLOC_CTX *mem_ctx,
338 PyObject *obj)
340 struct ldb_result *res;
341 Py_ssize_t i;
343 if (obj == Py_None)
344 return NULL;
346 res = talloc_zero(mem_ctx, struct ldb_result);
347 res->count = PyList_Size(obj);
348 res->msgs = talloc_array(res, struct ldb_message *, res->count);
349 for (i = 0; i < res->count; i++) {
350 PyObject *item = PyList_GetItem(obj, i);
351 res->msgs[i] = pyldb_Message_AsMessage(item);
353 return res;
356 static PyObject *py_ldb_dn_validate(PyLdbDnObject *self)
358 return PyBool_FromLong(ldb_dn_validate(self->dn));
361 static PyObject *py_ldb_dn_is_valid(PyLdbDnObject *self)
363 return PyBool_FromLong(ldb_dn_is_valid(self->dn));
366 static PyObject *py_ldb_dn_is_special(PyLdbDnObject *self)
368 return PyBool_FromLong(ldb_dn_is_special(self->dn));
371 static PyObject *py_ldb_dn_is_null(PyLdbDnObject *self)
373 return PyBool_FromLong(ldb_dn_is_null(self->dn));
376 static PyObject *py_ldb_dn_get_casefold(PyLdbDnObject *self)
378 return PyString_FromString(ldb_dn_get_casefold(self->dn));
381 static PyObject *py_ldb_dn_get_linearized(PyLdbDnObject *self)
383 return PyString_FromString(ldb_dn_get_linearized(self->dn));
386 static PyObject *py_ldb_dn_canonical_str(PyLdbDnObject *self)
388 return PyString_FromString(ldb_dn_canonical_string(self->dn, self->dn));
391 static PyObject *py_ldb_dn_canonical_ex_str(PyLdbDnObject *self)
393 return PyString_FromString(ldb_dn_canonical_ex_string(self->dn, self->dn));
396 static PyObject *py_ldb_dn_extended_str(PyLdbDnObject *self, PyObject *args, PyObject *kwargs)
398 const char * const kwnames[] = { "mode", NULL };
399 int mode = 1;
400 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "|i",
401 discard_const_p(char *, kwnames),
402 &mode))
403 return NULL;
404 return PyString_FromString(ldb_dn_get_extended_linearized(self->dn, self->dn, mode));
407 static PyObject *py_ldb_dn_get_extended_component(PyLdbDnObject *self, PyObject *args)
409 char *name;
410 const struct ldb_val *val;
412 if (!PyArg_ParseTuple(args, "s", &name))
413 return NULL;
414 val = ldb_dn_get_extended_component(self->dn, name);
415 if (val == NULL) {
416 Py_RETURN_NONE;
419 return PyString_FromStringAndSize((const char *)val->data, val->length);
422 static PyObject *py_ldb_dn_set_extended_component(PyLdbDnObject *self, PyObject *args)
424 char *name;
425 PyObject *value;
426 int err;
428 if (!PyArg_ParseTuple(args, "sO", &name, &value))
429 return NULL;
431 if (value == Py_None) {
432 err = ldb_dn_set_extended_component(self->dn, name, NULL);
433 } else {
434 struct ldb_val val;
435 if (!PyString_Check(value)) {
436 PyErr_SetString(PyExc_TypeError, "Expected a string argument");
437 return NULL;
439 val.data = (uint8_t *)PyString_AsString(value);
440 val.length = PyString_Size(value);
441 err = ldb_dn_set_extended_component(self->dn, name, &val);
444 if (err != LDB_SUCCESS) {
445 PyErr_SetString(PyExc_TypeError, "Failed to set extended component");
446 return NULL;
449 Py_RETURN_NONE;
452 static PyObject *py_ldb_dn_repr(PyLdbDnObject *self)
454 return PyString_FromFormat("Dn(%s)", PyObject_REPR(PyString_FromString(ldb_dn_get_linearized(self->dn))));
457 static PyObject *py_ldb_dn_check_special(PyLdbDnObject *self, PyObject *args)
459 char *name;
461 if (!PyArg_ParseTuple(args, "s", &name))
462 return NULL;
464 return PyBool_FromLong(ldb_dn_check_special(self->dn, name));
467 static int py_ldb_dn_compare(PyLdbDnObject *dn1, PyLdbDnObject *dn2)
469 int ret;
470 ret = ldb_dn_compare(dn1->dn, dn2->dn);
471 if (ret < 0) ret = -1;
472 if (ret > 0) ret = 1;
473 return ret;
476 static PyObject *py_ldb_dn_get_parent(PyLdbDnObject *self)
478 struct ldb_dn *dn = pyldb_Dn_AsDn((PyObject *)self);
479 struct ldb_dn *parent;
480 PyLdbDnObject *py_ret;
481 TALLOC_CTX *mem_ctx = talloc_new(NULL);
483 parent = ldb_dn_get_parent(mem_ctx, dn);
484 if (parent == NULL) {
485 talloc_free(mem_ctx);
486 Py_RETURN_NONE;
489 py_ret = (PyLdbDnObject *)PyLdbDn.tp_alloc(&PyLdbDn, 0);
490 if (py_ret == NULL) {
491 PyErr_NoMemory();
492 talloc_free(mem_ctx);
493 return NULL;
495 py_ret->mem_ctx = mem_ctx;
496 py_ret->dn = parent;
497 return (PyObject *)py_ret;
500 #define dn_ldb_ctx(dn) ((struct ldb_context *)dn)
502 static PyObject *py_ldb_dn_add_child(PyLdbDnObject *self, PyObject *args)
504 PyObject *py_other;
505 struct ldb_dn *dn, *other;
506 if (!PyArg_ParseTuple(args, "O", &py_other))
507 return NULL;
509 dn = pyldb_Dn_AsDn((PyObject *)self);
511 if (!pyldb_Object_AsDn(NULL, py_other, dn_ldb_ctx(dn), &other))
512 return NULL;
514 return PyBool_FromLong(ldb_dn_add_child(dn, other));
517 static PyObject *py_ldb_dn_add_base(PyLdbDnObject *self, PyObject *args)
519 PyObject *py_other;
520 struct ldb_dn *other, *dn;
521 if (!PyArg_ParseTuple(args, "O", &py_other))
522 return NULL;
524 dn = pyldb_Dn_AsDn((PyObject *)self);
526 if (!pyldb_Object_AsDn(NULL, py_other, dn_ldb_ctx(dn), &other))
527 return NULL;
529 return PyBool_FromLong(ldb_dn_add_base(dn, other));
532 static PyObject *py_ldb_dn_remove_base_components(PyLdbDnObject *self, PyObject *args)
534 struct ldb_dn *dn;
535 int i;
536 if (!PyArg_ParseTuple(args, "i", &i))
537 return NULL;
539 dn = pyldb_Dn_AsDn((PyObject *)self);
541 return PyBool_FromLong(ldb_dn_remove_base_components(dn, i));
544 static PyObject *py_ldb_dn_is_child_of(PyLdbDnObject *self, PyObject *args)
546 PyObject *py_base;
547 struct ldb_dn *dn, *base;
548 if (!PyArg_ParseTuple(args, "O", &py_base))
549 return NULL;
551 dn = pyldb_Dn_AsDn((PyObject *)self);
553 if (!pyldb_Object_AsDn(NULL, py_base, dn_ldb_ctx(dn), &base))
554 return NULL;
556 return PyBool_FromLong(ldb_dn_compare_base(base, dn) == 0);
559 static PyObject *py_ldb_dn_get_component_name(PyLdbDnObject *self, PyObject *args)
561 struct ldb_dn *dn;
562 const char *name;
563 unsigned int num = 0;
565 if (!PyArg_ParseTuple(args, "I", &num))
566 return NULL;
568 dn = pyldb_Dn_AsDn((PyObject *)self);
570 name = ldb_dn_get_component_name(dn, num);
571 if (name == NULL) {
572 Py_RETURN_NONE;
575 return PyString_FromString(name);
578 static PyObject *py_ldb_dn_get_component_value(PyLdbDnObject *self, PyObject *args)
580 struct ldb_dn *dn;
581 const struct ldb_val *val;
582 unsigned int num = 0;
584 if (!PyArg_ParseTuple(args, "I", &num))
585 return NULL;
587 dn = pyldb_Dn_AsDn((PyObject *)self);
589 val = ldb_dn_get_component_val(dn, num);
590 if (val == NULL) {
591 Py_RETURN_NONE;
594 return PyObject_FromLdbValue(val);
597 static PyObject *py_ldb_dn_set_component(PyLdbDnObject *self, PyObject *args)
599 unsigned int num = 0;
600 char *name = NULL;
601 PyObject *value = Py_None;
602 struct ldb_val val = { NULL, };
603 int err;
605 if (!PyArg_ParseTuple(args, "IsO", &num, &name, &value))
606 return NULL;
608 if (value != Py_None) {
609 if (!PyString_Check(value)) {
610 PyErr_SetString(PyExc_TypeError, "Expected a string argument");
611 return NULL;
613 val.data = (uint8_t *)PyString_AsString(value);
614 val.length = PyString_Size(value);
617 err = ldb_dn_set_component(self->dn, num, name, val);
618 if (err != LDB_SUCCESS) {
619 PyErr_SetString(PyExc_TypeError, "Failed to set component");
620 return NULL;
623 Py_RETURN_NONE;
626 static PyObject *py_ldb_dn_get_rdn_name(PyLdbDnObject *self)
628 struct ldb_dn *dn;
629 const char *name;
631 dn = pyldb_Dn_AsDn((PyObject *)self);
633 name = ldb_dn_get_rdn_name(dn);
634 if (name == NULL) {
635 Py_RETURN_NONE;
638 return PyString_FromString(name);
641 static PyObject *py_ldb_dn_get_rdn_value(PyLdbDnObject *self)
643 struct ldb_dn *dn;
644 const struct ldb_val *val;
646 dn = pyldb_Dn_AsDn((PyObject *)self);
648 val = ldb_dn_get_rdn_val(dn);
649 if (val == NULL) {
650 Py_RETURN_NONE;
653 return PyObject_FromLdbValue(val);
656 static PyMethodDef py_ldb_dn_methods[] = {
657 { "validate", (PyCFunction)py_ldb_dn_validate, METH_NOARGS,
658 "S.validate() -> bool\n"
659 "Validate DN is correct." },
660 { "is_valid", (PyCFunction)py_ldb_dn_is_valid, METH_NOARGS,
661 "S.is_valid() -> bool\n" },
662 { "is_special", (PyCFunction)py_ldb_dn_is_special, METH_NOARGS,
663 "S.is_special() -> bool\n"
664 "Check whether this is a special LDB DN." },
665 { "is_null", (PyCFunction)py_ldb_dn_is_null, METH_NOARGS,
666 "Check whether this is a null DN." },
667 { "get_casefold", (PyCFunction)py_ldb_dn_get_casefold, METH_NOARGS,
668 NULL },
669 { "get_linearized", (PyCFunction)py_ldb_dn_get_linearized, METH_NOARGS,
670 NULL },
671 { "canonical_str", (PyCFunction)py_ldb_dn_canonical_str, METH_NOARGS,
672 "S.canonical_str() -> string\n"
673 "Canonical version of this DN (like a posix path)." },
674 { "is_child_of", (PyCFunction)py_ldb_dn_is_child_of, METH_VARARGS,
675 "S.is_child_of(basedn) -> int\nReturns True if this DN is a child of basedn\n"},
676 { "canonical_ex_str", (PyCFunction)py_ldb_dn_canonical_ex_str, METH_NOARGS,
677 "S.canonical_ex_str() -> string\n"
678 "Canonical version of this DN (like a posix path, with terminating newline)." },
679 { "extended_str", (PyCFunction)py_ldb_dn_extended_str, METH_VARARGS | METH_KEYWORDS,
680 "S.extended_str(mode=1) -> string\n"
681 "Extended version of this DN" },
682 { "parent", (PyCFunction)py_ldb_dn_get_parent, METH_NOARGS,
683 "S.parent() -> dn\n"
684 "Get the parent for this DN." },
685 { "add_child", (PyCFunction)py_ldb_dn_add_child, METH_VARARGS,
686 "S.add_child(dn) -> None\n"
687 "Add a child DN to this DN." },
688 { "add_base", (PyCFunction)py_ldb_dn_add_base, METH_VARARGS,
689 "S.add_base(dn) -> None\n"
690 "Add a base DN to this DN." },
691 { "remove_base_components", (PyCFunction)py_ldb_dn_remove_base_components, METH_VARARGS,
692 "S.remove_base_components(int) -> bool\n"
693 "Remove a number of DN components from the base of this DN." },
694 { "check_special", (PyCFunction)py_ldb_dn_check_special, METH_VARARGS,
695 "S.check_special(name) -> bool\n\n"
696 "Check if name is a special DN name"},
697 { "get_extended_component", (PyCFunction)py_ldb_dn_get_extended_component, METH_VARARGS,
698 "S.get_extended_component(name) -> string\n\n"
699 "returns a DN extended component as a binary string"},
700 { "set_extended_component", (PyCFunction)py_ldb_dn_set_extended_component, METH_VARARGS,
701 "S.set_extended_component(name, value) -> None\n\n"
702 "set a DN extended component as a binary string"},
703 { "get_component_name", (PyCFunction)py_ldb_dn_get_component_name, METH_VARARGS,
704 "S.get_component_name(num) -> string\n"
705 "get the attribute name of the specified component" },
706 { "get_component_value", (PyCFunction)py_ldb_dn_get_component_value, METH_VARARGS,
707 "S.get_component_value(num) -> string\n"
708 "get the attribute value of the specified component as a binary string" },
709 { "set_component", (PyCFunction)py_ldb_dn_set_component, METH_VARARGS,
710 "S.get_component_value(num, name, value) -> None\n"
711 "set the attribute name and value of the specified component" },
712 { "get_rdn_name", (PyCFunction)py_ldb_dn_get_rdn_name, METH_NOARGS,
713 "S.get_rdn_name() -> string\n"
714 "get the RDN attribute name" },
715 { "get_rdn_value", (PyCFunction)py_ldb_dn_get_rdn_value, METH_NOARGS,
716 "S.get_rdn_value() -> string\n"
717 "get the RDN attribute value as a binary string" },
718 { NULL }
721 static Py_ssize_t py_ldb_dn_len(PyLdbDnObject *self)
723 return ldb_dn_get_comp_num(pyldb_Dn_AsDn((PyObject *)self));
727 copy a DN as a python object
729 static PyObject *py_ldb_dn_copy(struct ldb_dn *dn)
731 PyLdbDnObject *py_ret;
733 py_ret = (PyLdbDnObject *)PyLdbDn.tp_alloc(&PyLdbDn, 0);
734 if (py_ret == NULL) {
735 PyErr_NoMemory();
736 return NULL;
738 py_ret->mem_ctx = talloc_new(NULL);
739 py_ret->dn = ldb_dn_copy(py_ret->mem_ctx, dn);
740 return (PyObject *)py_ret;
743 static PyObject *py_ldb_dn_concat(PyLdbDnObject *self, PyObject *py_other)
745 struct ldb_dn *dn = pyldb_Dn_AsDn((PyObject *)self),
746 *other;
747 PyLdbDnObject *py_ret;
749 if (!pyldb_Object_AsDn(NULL, py_other, NULL, &other))
750 return NULL;
752 py_ret = (PyLdbDnObject *)PyLdbDn.tp_alloc(&PyLdbDn, 0);
753 if (py_ret == NULL) {
754 PyErr_NoMemory();
755 return NULL;
757 py_ret->mem_ctx = talloc_new(NULL);
758 py_ret->dn = ldb_dn_copy(py_ret->mem_ctx, dn);
759 ldb_dn_add_base(py_ret->dn, other);
760 return (PyObject *)py_ret;
763 static PySequenceMethods py_ldb_dn_seq = {
764 .sq_length = (lenfunc)py_ldb_dn_len,
765 .sq_concat = (binaryfunc)py_ldb_dn_concat,
768 static PyObject *py_ldb_dn_new(PyTypeObject *type, PyObject *args, PyObject *kwargs)
770 struct ldb_dn *ret;
771 char *str;
772 PyObject *py_ldb;
773 struct ldb_context *ldb_ctx;
774 TALLOC_CTX *mem_ctx;
775 PyLdbDnObject *py_ret;
776 const char * const kwnames[] = { "ldb", "dn", NULL };
778 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "Os",
779 discard_const_p(char *, kwnames),
780 &py_ldb, &str))
781 return NULL;
783 if (!PyLdb_Check(py_ldb)) {
784 PyErr_SetString(PyExc_TypeError, "Expected Ldb");
785 return NULL;
788 ldb_ctx = pyldb_Ldb_AsLdbContext(py_ldb);
790 mem_ctx = talloc_new(NULL);
791 if (mem_ctx == NULL) {
792 PyErr_NoMemory();
793 return NULL;
796 ret = ldb_dn_new(mem_ctx, ldb_ctx, str);
797 if (!ldb_dn_validate(ret)) {
798 talloc_free(mem_ctx);
799 PyErr_SetString(PyExc_ValueError, "unable to parse dn string");
800 return NULL;
803 py_ret = (PyLdbDnObject *)type->tp_alloc(type, 0);
804 if (ret == NULL) {
805 talloc_free(mem_ctx);
806 PyErr_NoMemory();
807 return NULL;
809 py_ret->mem_ctx = mem_ctx;
810 py_ret->dn = ret;
811 return (PyObject *)py_ret;
814 static void py_ldb_dn_dealloc(PyLdbDnObject *self)
816 talloc_free(self->mem_ctx);
817 PyObject_Del(self);
820 static PyTypeObject PyLdbDn = {
821 .tp_name = "ldb.Dn",
822 .tp_methods = py_ldb_dn_methods,
823 .tp_str = (reprfunc)py_ldb_dn_get_linearized,
824 .tp_repr = (reprfunc)py_ldb_dn_repr,
825 .tp_compare = (cmpfunc)py_ldb_dn_compare,
826 .tp_as_sequence = &py_ldb_dn_seq,
827 .tp_doc = "A LDB distinguished name.",
828 .tp_new = py_ldb_dn_new,
829 .tp_dealloc = (destructor)py_ldb_dn_dealloc,
830 .tp_basicsize = sizeof(PyLdbDnObject),
831 .tp_flags = Py_TPFLAGS_DEFAULT,
834 /* Debug */
835 static void py_ldb_debug(void *context, enum ldb_debug_level level, const char *fmt, va_list ap) PRINTF_ATTRIBUTE(3, 0);
836 static void py_ldb_debug(void *context, enum ldb_debug_level level, const char *fmt, va_list ap)
838 PyObject *fn = (PyObject *)context;
839 PyObject_CallFunction(fn, discard_const_p(char, "(i,O)"), level, PyString_FromFormatV(fmt, ap));
842 static PyObject *py_ldb_set_debug(PyObject *self, PyObject *args)
844 PyObject *cb;
845 struct ldb_context *ldb_ctx;
847 if (!PyArg_ParseTuple(args, "O", &cb))
848 return NULL;
850 Py_INCREF(cb);
851 /* FIXME: Where do we DECREF cb ? */
852 ldb_ctx = pyldb_Ldb_AsLdbContext(self);
853 PyErr_LDB_ERROR_IS_ERR_RAISE(PyExc_LdbError,
854 ldb_set_debug(ldb_ctx, py_ldb_debug, cb),
855 ldb_ctx);
857 Py_RETURN_NONE;
860 static PyObject *py_ldb_set_create_perms(PyTypeObject *self, PyObject *args)
862 unsigned int perms;
863 if (!PyArg_ParseTuple(args, "I", &perms))
864 return NULL;
866 ldb_set_create_perms(pyldb_Ldb_AsLdbContext(self), perms);
868 Py_RETURN_NONE;
871 static PyObject *py_ldb_set_modules_dir(PyTypeObject *self, PyObject *args)
873 char *modules_dir;
874 if (!PyArg_ParseTuple(args, "s", &modules_dir))
875 return NULL;
877 ldb_set_modules_dir(pyldb_Ldb_AsLdbContext(self), modules_dir);
879 Py_RETURN_NONE;
882 static PyObject *py_ldb_transaction_start(PyLdbObject *self)
884 struct ldb_context *ldb_ctx = pyldb_Ldb_AsLdbContext(self);
885 int ldb_err;
886 ldb_err = ldb_transaction_start(ldb_ctx);
887 PyErr_LDB_ERROR_IS_ERR_RAISE(PyExc_LdbError, ldb_err, ldb_ctx);
888 Py_RETURN_NONE;
891 static PyObject *py_ldb_transaction_commit(PyLdbObject *self)
893 struct ldb_context *ldb_ctx = pyldb_Ldb_AsLdbContext(self);
894 int ldb_err;
895 ldb_err = ldb_transaction_commit(ldb_ctx);
896 PyErr_LDB_ERROR_IS_ERR_RAISE(PyExc_LdbError, ldb_err, ldb_ctx);
897 Py_RETURN_NONE;
900 static PyObject *py_ldb_transaction_prepare_commit(PyLdbObject *self)
902 struct ldb_context *ldb_ctx = pyldb_Ldb_AsLdbContext(self);
903 int ldb_err;
904 ldb_err = ldb_transaction_prepare_commit(ldb_ctx);
905 PyErr_LDB_ERROR_IS_ERR_RAISE(PyExc_LdbError, ldb_err, ldb_ctx);
906 Py_RETURN_NONE;
909 static PyObject *py_ldb_transaction_cancel(PyLdbObject *self)
911 struct ldb_context *ldb_ctx = pyldb_Ldb_AsLdbContext(self);
912 int ldb_err;
913 ldb_err = ldb_transaction_cancel(ldb_ctx);
914 PyErr_LDB_ERROR_IS_ERR_RAISE(PyExc_LdbError, ldb_err, ldb_ctx);
915 Py_RETURN_NONE;
918 static PyObject *py_ldb_setup_wellknown_attributes(PyLdbObject *self)
920 struct ldb_context *ldb_ctx = pyldb_Ldb_AsLdbContext(self);
921 int ldb_err;
922 ldb_err = ldb_setup_wellknown_attributes(ldb_ctx);
923 PyErr_LDB_ERROR_IS_ERR_RAISE(PyExc_LdbError, ldb_err, ldb_ctx);
924 Py_RETURN_NONE;
927 static PyObject *py_ldb_repr(PyLdbObject *self)
929 return PyString_FromFormat("<ldb connection>");
932 static PyObject *py_ldb_get_root_basedn(PyLdbObject *self)
934 struct ldb_dn *dn = ldb_get_root_basedn(pyldb_Ldb_AsLdbContext(self));
935 if (dn == NULL)
936 Py_RETURN_NONE;
937 return py_ldb_dn_copy(dn);
941 static PyObject *py_ldb_get_schema_basedn(PyLdbObject *self)
943 struct ldb_dn *dn = ldb_get_schema_basedn(pyldb_Ldb_AsLdbContext(self));
944 if (dn == NULL)
945 Py_RETURN_NONE;
946 return py_ldb_dn_copy(dn);
949 static PyObject *py_ldb_get_config_basedn(PyLdbObject *self)
951 struct ldb_dn *dn = ldb_get_config_basedn(pyldb_Ldb_AsLdbContext(self));
952 if (dn == NULL)
953 Py_RETURN_NONE;
954 return py_ldb_dn_copy(dn);
957 static PyObject *py_ldb_get_default_basedn(PyLdbObject *self)
959 struct ldb_dn *dn = ldb_get_default_basedn(pyldb_Ldb_AsLdbContext(self));
960 if (dn == NULL)
961 Py_RETURN_NONE;
962 return py_ldb_dn_copy(dn);
965 static const char **PyList_AsStringList(TALLOC_CTX *mem_ctx, PyObject *list,
966 const char *paramname)
968 const char **ret;
969 Py_ssize_t i;
970 if (!PyList_Check(list)) {
971 PyErr_Format(PyExc_TypeError, "%s is not a list", paramname);
972 return NULL;
974 ret = talloc_array(NULL, const char *, PyList_Size(list)+1);
975 if (ret == NULL) {
976 PyErr_NoMemory();
977 return NULL;
980 for (i = 0; i < PyList_Size(list); i++) {
981 PyObject *item = PyList_GetItem(list, i);
982 if (!PyString_Check(item)) {
983 PyErr_Format(PyExc_TypeError, "%s should be strings", paramname);
984 return NULL;
986 ret[i] = talloc_strndup(ret, PyString_AsString(item),
987 PyString_Size(item));
989 ret[i] = NULL;
990 return ret;
993 static int py_ldb_init(PyLdbObject *self, PyObject *args, PyObject *kwargs)
995 const char * const kwnames[] = { "url", "flags", "options", NULL };
996 char *url = NULL;
997 PyObject *py_options = Py_None;
998 const char **options;
999 unsigned int flags = 0;
1000 int ret;
1001 struct ldb_context *ldb;
1003 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "|zIO:Ldb.__init__",
1004 discard_const_p(char *, kwnames),
1005 &url, &flags, &py_options))
1006 return -1;
1008 ldb = pyldb_Ldb_AsLdbContext(self);
1010 if (py_options == Py_None) {
1011 options = NULL;
1012 } else {
1013 options = PyList_AsStringList(ldb, py_options, "options");
1014 if (options == NULL)
1015 return -1;
1018 if (url != NULL) {
1019 ret = ldb_connect(ldb, url, flags, options);
1020 if (ret != LDB_SUCCESS) {
1021 PyErr_SetLdbError(PyExc_LdbError, ret, ldb);
1022 return -1;
1026 talloc_free(options);
1027 return 0;
1030 static PyObject *py_ldb_new(PyTypeObject *type, PyObject *args, PyObject *kwargs)
1032 PyLdbObject *ret;
1033 struct ldb_context *ldb;
1034 ret = (PyLdbObject *)type->tp_alloc(type, 0);
1035 if (ret == NULL) {
1036 PyErr_NoMemory();
1037 return NULL;
1039 ret->mem_ctx = talloc_new(NULL);
1040 ldb = ldb_init(ret->mem_ctx, NULL);
1042 if (ldb == NULL) {
1043 PyErr_NoMemory();
1044 return NULL;
1047 ret->ldb_ctx = ldb;
1048 return (PyObject *)ret;
1051 static PyObject *py_ldb_connect(PyLdbObject *self, PyObject *args, PyObject *kwargs)
1053 char *url;
1054 unsigned int flags = 0;
1055 PyObject *py_options = Py_None;
1056 int ret;
1057 const char **options;
1058 const char * const kwnames[] = { "url", "flags", "options", NULL };
1059 struct ldb_context *ldb_ctx;
1061 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "|zIO",
1062 discard_const_p(char *, kwnames),
1063 &url, &flags, &py_options))
1064 return NULL;
1066 if (py_options == Py_None) {
1067 options = NULL;
1068 } else {
1069 options = PyList_AsStringList(NULL, py_options, "options");
1070 if (options == NULL)
1071 return NULL;
1074 ldb_ctx = pyldb_Ldb_AsLdbContext(self);
1075 ret = ldb_connect(ldb_ctx, url, flags, options);
1076 talloc_free(options);
1078 PyErr_LDB_ERROR_IS_ERR_RAISE(PyExc_LdbError, ret, ldb_ctx);
1080 Py_RETURN_NONE;
1083 static PyObject *py_ldb_modify(PyLdbObject *self, PyObject *args, PyObject *kwargs)
1085 PyObject *py_msg;
1086 PyObject *py_controls = Py_None;
1087 struct ldb_context *ldb_ctx;
1088 struct ldb_request *req;
1089 struct ldb_control **parsed_controls;
1090 struct ldb_message *msg;
1091 int ret;
1092 TALLOC_CTX *mem_ctx;
1093 bool validate=true;
1094 const char * const kwnames[] = { "message", "controls", "validate", NULL };
1096 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "O|Ob",
1097 discard_const_p(char *, kwnames),
1098 &py_msg, &py_controls, &validate))
1099 return NULL;
1101 mem_ctx = talloc_new(NULL);
1102 if (mem_ctx == NULL) {
1103 PyErr_NoMemory();
1104 return NULL;
1106 ldb_ctx = pyldb_Ldb_AsLdbContext(self);
1108 if (py_controls == Py_None) {
1109 parsed_controls = NULL;
1110 } else {
1111 const char **controls = PyList_AsStringList(mem_ctx, py_controls, "controls");
1112 if (controls == NULL) {
1113 talloc_free(mem_ctx);
1114 return NULL;
1116 parsed_controls = ldb_parse_control_strings(ldb_ctx, mem_ctx, controls);
1117 talloc_free(controls);
1120 if (!PyLdbMessage_Check(py_msg)) {
1121 PyErr_SetString(PyExc_TypeError, "Expected Ldb Message");
1122 talloc_free(mem_ctx);
1123 return NULL;
1125 msg = pyldb_Message_AsMessage(py_msg);
1127 if (validate) {
1128 ret = ldb_msg_sanity_check(ldb_ctx, msg);
1129 if (ret != LDB_SUCCESS) {
1130 PyErr_SetLdbError(PyExc_LdbError, ret, ldb_ctx);
1131 talloc_free(mem_ctx);
1132 return NULL;
1136 ret = ldb_build_mod_req(&req, ldb_ctx, mem_ctx, msg, parsed_controls,
1137 NULL, ldb_op_default_callback, NULL);
1138 if (ret != LDB_SUCCESS) {
1139 PyErr_SetString(PyExc_TypeError, "failed to build request");
1140 talloc_free(mem_ctx);
1141 return NULL;
1144 /* do request and autostart a transaction */
1145 /* Then let's LDB handle the message error in case of pb as they are meaningful */
1147 ret = ldb_transaction_start(ldb_ctx);
1148 if (ret != LDB_SUCCESS) {
1149 talloc_free(mem_ctx);
1150 PyErr_SetLdbError(PyExc_LdbError, ret, ldb_ctx);
1151 return NULL;
1154 ret = ldb_request(ldb_ctx, req);
1155 if (ret == LDB_SUCCESS) {
1156 ret = ldb_wait(req->handle, LDB_WAIT_ALL);
1159 if (ret == LDB_SUCCESS) {
1160 ret = ldb_transaction_commit(ldb_ctx);
1161 } else {
1162 ldb_transaction_cancel(ldb_ctx);
1165 talloc_free(mem_ctx);
1166 PyErr_LDB_ERROR_IS_ERR_RAISE(PyExc_LdbError, ret, ldb_ctx);
1168 Py_RETURN_NONE;
1173 * Obtain a ldb message from a Python Dictionary object.
1175 * @param mem_ctx Memory context
1176 * @param py_obj Python Dictionary object
1177 * @param ldb_ctx LDB context
1178 * @param mod_flags Flags to be set on every message element
1179 * @return ldb_message on success or NULL on failure
1181 static struct ldb_message *PyDict_AsMessage(TALLOC_CTX *mem_ctx,
1182 PyObject *py_obj,
1183 struct ldb_context *ldb_ctx,
1184 unsigned int mod_flags)
1186 struct ldb_message *msg;
1187 unsigned int msg_pos = 0;
1188 Py_ssize_t dict_pos = 0;
1189 PyObject *key, *value;
1190 struct ldb_message_element *msg_el;
1191 PyObject *dn_value = PyDict_GetItemString(py_obj, "dn");
1193 msg = ldb_msg_new(mem_ctx);
1194 if (msg == NULL) {
1195 PyErr_NoMemory();
1196 return NULL;
1198 msg->elements = talloc_zero_array(msg, struct ldb_message_element, PyDict_Size(py_obj));
1200 if (dn_value) {
1201 if (!pyldb_Object_AsDn(msg, dn_value, ldb_ctx, &msg->dn)) {
1202 PyErr_SetString(PyExc_TypeError, "unable to import dn object");
1203 return NULL;
1205 if (msg->dn == NULL) {
1206 PyErr_SetString(PyExc_TypeError, "dn set but not found");
1207 return NULL;
1209 } else {
1210 PyErr_SetString(PyExc_TypeError, "no dn set");
1211 return NULL;
1214 while (PyDict_Next(py_obj, &dict_pos, &key, &value)) {
1215 char *key_str = PyString_AsString(key);
1216 if (ldb_attr_cmp(key_str, "dn") != 0) {
1217 msg_el = PyObject_AsMessageElement(msg->elements, value,
1218 mod_flags, key_str);
1219 if (msg_el == NULL) {
1220 PyErr_Format(PyExc_TypeError, "unable to import element '%s'", key_str);
1221 return NULL;
1223 memcpy(&msg->elements[msg_pos], msg_el, sizeof(*msg_el));
1224 msg_pos++;
1228 msg->num_elements = msg_pos;
1230 return msg;
1233 static PyObject *py_ldb_add(PyLdbObject *self, PyObject *args, PyObject *kwargs)
1235 PyObject *py_obj;
1236 int ret;
1237 struct ldb_context *ldb_ctx;
1238 struct ldb_request *req;
1239 struct ldb_message *msg = NULL;
1240 PyObject *py_controls = Py_None;
1241 TALLOC_CTX *mem_ctx;
1242 struct ldb_control **parsed_controls;
1243 const char * const kwnames[] = { "message", "controls", NULL };
1245 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "O|O",
1246 discard_const_p(char *, kwnames),
1247 &py_obj, &py_controls))
1248 return NULL;
1250 mem_ctx = talloc_new(NULL);
1251 if (mem_ctx == NULL) {
1252 PyErr_NoMemory();
1253 return NULL;
1255 ldb_ctx = pyldb_Ldb_AsLdbContext(self);
1257 if (py_controls == Py_None) {
1258 parsed_controls = NULL;
1259 } else {
1260 const char **controls = PyList_AsStringList(mem_ctx, py_controls, "controls");
1261 if (controls == NULL) {
1262 talloc_free(mem_ctx);
1263 return NULL;
1265 parsed_controls = ldb_parse_control_strings(ldb_ctx, mem_ctx, controls);
1266 talloc_free(controls);
1269 if (PyLdbMessage_Check(py_obj)) {
1270 msg = pyldb_Message_AsMessage(py_obj);
1271 } else if (PyDict_Check(py_obj)) {
1272 msg = PyDict_AsMessage(mem_ctx, py_obj, ldb_ctx, LDB_FLAG_MOD_ADD);
1273 } else {
1274 PyErr_SetString(PyExc_TypeError,
1275 "Dictionary or LdbMessage object expected!");
1278 if (!msg) {
1279 /* we should have a PyErr already set */
1280 talloc_free(mem_ctx);
1281 return NULL;
1284 ret = ldb_msg_sanity_check(ldb_ctx, msg);
1285 if (ret != LDB_SUCCESS) {
1286 PyErr_SetLdbError(PyExc_LdbError, ret, ldb_ctx);
1287 talloc_free(mem_ctx);
1288 return NULL;
1291 ret = ldb_build_add_req(&req, ldb_ctx, mem_ctx, msg, parsed_controls,
1292 NULL, ldb_op_default_callback, NULL);
1293 if (ret != LDB_SUCCESS) {
1294 PyErr_SetString(PyExc_TypeError, "failed to build request");
1295 talloc_free(mem_ctx);
1296 return NULL;
1299 /* do request and autostart a transaction */
1300 /* Then let's LDB handle the message error in case of pb as they are meaningful */
1302 ret = ldb_transaction_start(ldb_ctx);
1303 if (ret != LDB_SUCCESS) {
1304 talloc_free(mem_ctx);
1305 PyErr_SetLdbError(PyExc_LdbError, ret, ldb_ctx);
1306 return NULL;
1309 ret = ldb_request(ldb_ctx, req);
1310 if (ret == LDB_SUCCESS) {
1311 ret = ldb_wait(req->handle, LDB_WAIT_ALL);
1314 if (ret == LDB_SUCCESS) {
1315 ret = ldb_transaction_commit(ldb_ctx);
1316 } else {
1317 ldb_transaction_cancel(ldb_ctx);
1320 talloc_free(mem_ctx);
1321 PyErr_LDB_ERROR_IS_ERR_RAISE(PyExc_LdbError, ret, ldb_ctx);
1323 Py_RETURN_NONE;
1326 static PyObject *py_ldb_delete(PyLdbObject *self, PyObject *args, PyObject *kwargs)
1328 PyObject *py_dn;
1329 struct ldb_dn *dn;
1330 int ret;
1331 struct ldb_context *ldb_ctx;
1332 struct ldb_request *req;
1333 PyObject *py_controls = Py_None;
1334 TALLOC_CTX *mem_ctx;
1335 struct ldb_control **parsed_controls;
1336 const char * const kwnames[] = { "dn", "controls", NULL };
1338 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "O|O",
1339 discard_const_p(char *, kwnames),
1340 &py_dn, &py_controls))
1341 return NULL;
1343 mem_ctx = talloc_new(NULL);
1344 if (mem_ctx == NULL) {
1345 PyErr_NoMemory();
1346 return NULL;
1348 ldb_ctx = pyldb_Ldb_AsLdbContext(self);
1350 if (py_controls == Py_None) {
1351 parsed_controls = NULL;
1352 } else {
1353 const char **controls = PyList_AsStringList(mem_ctx, py_controls, "controls");
1354 if (controls == NULL) {
1355 talloc_free(mem_ctx);
1356 return NULL;
1358 parsed_controls = ldb_parse_control_strings(ldb_ctx, mem_ctx, controls);
1359 talloc_free(controls);
1362 if (!pyldb_Object_AsDn(mem_ctx, py_dn, ldb_ctx, &dn)) {
1363 talloc_free(mem_ctx);
1364 return NULL;
1367 ret = ldb_build_del_req(&req, ldb_ctx, mem_ctx, dn, parsed_controls,
1368 NULL, ldb_op_default_callback, NULL);
1369 if (ret != LDB_SUCCESS) {
1370 PyErr_SetString(PyExc_TypeError, "failed to build request");
1371 talloc_free(mem_ctx);
1372 return NULL;
1375 /* do request and autostart a transaction */
1376 /* Then let's LDB handle the message error in case of pb as they are meaningful */
1378 ret = ldb_transaction_start(ldb_ctx);
1379 if (ret != LDB_SUCCESS) {
1380 talloc_free(mem_ctx);
1381 PyErr_SetLdbError(PyExc_LdbError, ret, ldb_ctx);
1382 return NULL;
1385 ret = ldb_request(ldb_ctx, req);
1386 if (ret == LDB_SUCCESS) {
1387 ret = ldb_wait(req->handle, LDB_WAIT_ALL);
1390 if (ret == LDB_SUCCESS) {
1391 ret = ldb_transaction_commit(ldb_ctx);
1392 } else {
1393 ldb_transaction_cancel(ldb_ctx);
1396 talloc_free(mem_ctx);
1397 PyErr_LDB_ERROR_IS_ERR_RAISE(PyExc_LdbError, ret, ldb_ctx);
1399 Py_RETURN_NONE;
1402 static PyObject *py_ldb_rename(PyLdbObject *self, PyObject *args, PyObject *kwargs)
1404 PyObject *py_dn1, *py_dn2;
1405 struct ldb_dn *dn1, *dn2;
1406 int ret;
1407 TALLOC_CTX *mem_ctx;
1408 PyObject *py_controls = Py_None;
1409 struct ldb_control **parsed_controls;
1410 struct ldb_context *ldb_ctx;
1411 struct ldb_request *req;
1412 const char * const kwnames[] = { "dn1", "dn2", "controls", NULL };
1414 ldb_ctx = pyldb_Ldb_AsLdbContext(self);
1416 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "OO|O",
1417 discard_const_p(char *, kwnames),
1418 &py_dn1, &py_dn2, &py_controls))
1419 return NULL;
1422 mem_ctx = talloc_new(NULL);
1423 if (mem_ctx == NULL) {
1424 PyErr_NoMemory();
1425 return NULL;
1428 if (py_controls == Py_None) {
1429 parsed_controls = NULL;
1430 } else {
1431 const char **controls = PyList_AsStringList(mem_ctx, py_controls, "controls");
1432 if (controls == NULL) {
1433 talloc_free(mem_ctx);
1434 return NULL;
1436 parsed_controls = ldb_parse_control_strings(ldb_ctx, mem_ctx, controls);
1437 talloc_free(controls);
1441 if (!pyldb_Object_AsDn(mem_ctx, py_dn1, ldb_ctx, &dn1)) {
1442 talloc_free(mem_ctx);
1443 return NULL;
1446 if (!pyldb_Object_AsDn(mem_ctx, py_dn2, ldb_ctx, &dn2)) {
1447 talloc_free(mem_ctx);
1448 return NULL;
1451 ret = ldb_build_rename_req(&req, ldb_ctx, mem_ctx, dn1, dn2, parsed_controls,
1452 NULL, ldb_op_default_callback, NULL);
1453 if (ret != LDB_SUCCESS) {
1454 PyErr_SetString(PyExc_TypeError, "failed to build request");
1455 talloc_free(mem_ctx);
1456 return NULL;
1459 /* do request and autostart a transaction */
1460 /* Then let's LDB handle the message error in case of pb as they are meaningful */
1462 ret = ldb_transaction_start(ldb_ctx);
1463 if (ret != LDB_SUCCESS) {
1464 talloc_free(mem_ctx);
1465 PyErr_SetLdbError(PyExc_LdbError, ret, ldb_ctx);
1466 return NULL;
1469 ret = ldb_request(ldb_ctx, req);
1470 if (ret == LDB_SUCCESS) {
1471 ret = ldb_wait(req->handle, LDB_WAIT_ALL);
1474 if (ret == LDB_SUCCESS) {
1475 ret = ldb_transaction_commit(ldb_ctx);
1476 } else {
1477 ldb_transaction_cancel(ldb_ctx);
1480 talloc_free(mem_ctx);
1481 PyErr_LDB_ERROR_IS_ERR_RAISE(PyExc_LdbError, ret, ldb_ctx);
1483 Py_RETURN_NONE;
1486 static PyObject *py_ldb_schema_attribute_remove(PyLdbObject *self, PyObject *args)
1488 char *name;
1489 if (!PyArg_ParseTuple(args, "s", &name))
1490 return NULL;
1492 ldb_schema_attribute_remove(pyldb_Ldb_AsLdbContext(self), name);
1494 Py_RETURN_NONE;
1497 static PyObject *py_ldb_schema_attribute_add(PyLdbObject *self, PyObject *args)
1499 char *attribute, *syntax;
1500 unsigned int flags;
1501 int ret;
1502 struct ldb_context *ldb_ctx;
1504 if (!PyArg_ParseTuple(args, "sIs", &attribute, &flags, &syntax))
1505 return NULL;
1507 ldb_ctx = pyldb_Ldb_AsLdbContext(self);
1508 ret = ldb_schema_attribute_add(ldb_ctx, attribute, flags, syntax);
1510 PyErr_LDB_ERROR_IS_ERR_RAISE(PyExc_LdbError, ret, ldb_ctx);
1512 Py_RETURN_NONE;
1515 static PyObject *ldb_ldif_to_pyobject(struct ldb_ldif *ldif)
1517 if (ldif == NULL) {
1518 Py_RETURN_NONE;
1519 } else {
1520 /* We don't want this attached to the 'ldb' any more */
1521 return Py_BuildValue(discard_const_p(char, "(iO)"),
1522 ldif->changetype,
1523 PyLdbMessage_FromMessage(ldif->msg));
1528 static PyObject *py_ldb_write_ldif(PyLdbObject *self, PyObject *args)
1530 int changetype;
1531 PyObject *py_msg;
1532 struct ldb_ldif ldif;
1533 PyObject *ret;
1534 char *string;
1535 TALLOC_CTX *mem_ctx;
1537 if (!PyArg_ParseTuple(args, "Oi", &py_msg, &changetype))
1538 return NULL;
1540 if (!PyLdbMessage_Check(py_msg)) {
1541 PyErr_SetString(PyExc_TypeError, "Expected Ldb Message for msg");
1542 return NULL;
1545 ldif.msg = pyldb_Message_AsMessage(py_msg);
1546 ldif.changetype = changetype;
1548 mem_ctx = talloc_new(NULL);
1550 string = ldb_ldif_write_string(pyldb_Ldb_AsLdbContext(self), mem_ctx, &ldif);
1551 if (!string) {
1552 PyErr_SetString(PyExc_KeyError, "Failed to generate LDIF");
1553 return NULL;
1556 ret = PyString_FromString(string);
1558 talloc_free(mem_ctx);
1560 return ret;
1563 static PyObject *py_ldb_parse_ldif(PyLdbObject *self, PyObject *args)
1565 PyObject *list, *ret;
1566 struct ldb_ldif *ldif;
1567 const char *s;
1569 TALLOC_CTX *mem_ctx;
1571 if (!PyArg_ParseTuple(args, "s", &s))
1572 return NULL;
1574 mem_ctx = talloc_new(NULL);
1575 if (!mem_ctx) {
1576 Py_RETURN_NONE;
1579 list = PyList_New(0);
1580 while (s && *s != '\0') {
1581 ldif = ldb_ldif_read_string(self->ldb_ctx, &s);
1582 talloc_steal(mem_ctx, ldif);
1583 if (ldif) {
1584 PyList_Append(list, ldb_ldif_to_pyobject(ldif));
1585 } else {
1586 PyErr_SetString(PyExc_ValueError, "unable to parse ldif string");
1587 talloc_free(mem_ctx);
1588 return NULL;
1591 talloc_free(mem_ctx); /* The pyobject already has a reference to the things it needs */
1592 ret = PyObject_GetIter(list);
1593 Py_DECREF(list);
1594 return ret;
1597 static PyObject *py_ldb_msg_diff(PyLdbObject *self, PyObject *args)
1599 int ldb_ret;
1600 PyObject *py_msg_old;
1601 PyObject *py_msg_new;
1602 struct ldb_message *diff;
1603 struct ldb_context *ldb;
1604 PyObject *py_ret;
1606 if (!PyArg_ParseTuple(args, "OO", &py_msg_old, &py_msg_new))
1607 return NULL;
1609 if (!PyLdbMessage_Check(py_msg_old)) {
1610 PyErr_SetString(PyExc_TypeError, "Expected Ldb Message for old message");
1611 return NULL;
1614 if (!PyLdbMessage_Check(py_msg_new)) {
1615 PyErr_SetString(PyExc_TypeError, "Expected Ldb Message for new message");
1616 return NULL;
1619 ldb = pyldb_Ldb_AsLdbContext(self);
1620 ldb_ret = ldb_msg_difference(ldb, ldb,
1621 pyldb_Message_AsMessage(py_msg_old),
1622 pyldb_Message_AsMessage(py_msg_new),
1623 &diff);
1624 if (ldb_ret != LDB_SUCCESS) {
1625 PyErr_SetString(PyExc_RuntimeError, "Failed to generate the Ldb Message diff");
1626 return NULL;
1629 py_ret = PyLdbMessage_FromMessage(diff);
1631 talloc_unlink(ldb, diff);
1633 return py_ret;
1636 static PyObject *py_ldb_schema_format_value(PyLdbObject *self, PyObject *args)
1638 const struct ldb_schema_attribute *a;
1639 struct ldb_val old_val;
1640 struct ldb_val new_val;
1641 TALLOC_CTX *mem_ctx;
1642 PyObject *ret;
1643 char *element_name;
1644 PyObject *val;
1646 if (!PyArg_ParseTuple(args, "sO", &element_name, &val))
1647 return NULL;
1649 old_val.data = (uint8_t *)PyString_AsString(val);
1650 old_val.length = PyString_Size(val);
1652 if (old_val.data == NULL) {
1653 PyErr_SetString(PyExc_RuntimeError, "Failed to convert passed value to String");
1654 return NULL;
1657 a = ldb_schema_attribute_by_name(pyldb_Ldb_AsLdbContext(self), element_name);
1659 if (a == NULL) {
1660 Py_RETURN_NONE;
1663 mem_ctx = talloc_new(NULL);
1664 if (mem_ctx == NULL) {
1665 PyErr_NoMemory();
1666 return NULL;
1669 if (a->syntax->ldif_write_fn(pyldb_Ldb_AsLdbContext(self), mem_ctx, &old_val, &new_val) != 0) {
1670 talloc_free(mem_ctx);
1671 Py_RETURN_NONE;
1674 ret = PyString_FromStringAndSize((const char *)new_val.data, new_val.length);
1676 talloc_free(mem_ctx);
1678 return ret;
1681 static PyObject *py_ldb_search(PyLdbObject *self, PyObject *args, PyObject *kwargs)
1683 PyObject *py_base = Py_None;
1684 int scope = LDB_SCOPE_DEFAULT;
1685 char *expr = NULL;
1686 PyObject *py_attrs = Py_None;
1687 PyObject *py_controls = Py_None;
1688 const char * const kwnames[] = { "base", "scope", "expression", "attrs", "controls", NULL };
1689 int ret;
1690 struct ldb_result *res;
1691 struct ldb_request *req;
1692 const char **attrs;
1693 struct ldb_context *ldb_ctx;
1694 struct ldb_control **parsed_controls;
1695 struct ldb_dn *base;
1696 PyObject *py_ret;
1697 TALLOC_CTX *mem_ctx;
1699 /* type "int" rather than "enum" for "scope" is intentional */
1700 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "|OizOO",
1701 discard_const_p(char *, kwnames),
1702 &py_base, &scope, &expr, &py_attrs, &py_controls))
1703 return NULL;
1706 mem_ctx = talloc_new(NULL);
1707 if (mem_ctx == NULL) {
1708 PyErr_NoMemory();
1709 return NULL;
1711 ldb_ctx = pyldb_Ldb_AsLdbContext(self);
1713 if (py_attrs == Py_None) {
1714 attrs = NULL;
1715 } else {
1716 attrs = PyList_AsStringList(mem_ctx, py_attrs, "attrs");
1717 if (attrs == NULL) {
1718 talloc_free(mem_ctx);
1719 return NULL;
1723 if (py_base == Py_None) {
1724 base = ldb_get_default_basedn(ldb_ctx);
1725 } else {
1726 if (!pyldb_Object_AsDn(ldb_ctx, py_base, ldb_ctx, &base)) {
1727 talloc_free(attrs);
1728 return NULL;
1732 if (py_controls == Py_None) {
1733 parsed_controls = NULL;
1734 } else {
1735 const char **controls = PyList_AsStringList(mem_ctx, py_controls, "controls");
1736 if (controls == NULL) {
1737 talloc_free(mem_ctx);
1738 return NULL;
1740 parsed_controls = ldb_parse_control_strings(ldb_ctx, mem_ctx, controls);
1741 talloc_free(controls);
1744 res = talloc_zero(mem_ctx, struct ldb_result);
1745 if (res == NULL) {
1746 PyErr_NoMemory();
1747 talloc_free(mem_ctx);
1748 return NULL;
1751 ret = ldb_build_search_req(&req, ldb_ctx, mem_ctx,
1752 base,
1753 scope,
1754 expr,
1755 attrs,
1756 parsed_controls,
1757 res,
1758 ldb_search_default_callback,
1759 NULL);
1761 if (ret != LDB_SUCCESS) {
1762 talloc_free(mem_ctx);
1763 PyErr_SetLdbError(PyExc_LdbError, ret, ldb_ctx);
1764 return NULL;
1767 talloc_steal(req, attrs);
1769 ret = ldb_request(ldb_ctx, req);
1771 if (ret == LDB_SUCCESS) {
1772 ret = ldb_wait(req->handle, LDB_WAIT_ALL);
1775 if (ret != LDB_SUCCESS) {
1776 talloc_free(mem_ctx);
1777 PyErr_SetLdbError(PyExc_LdbError, ret, ldb_ctx);
1778 return NULL;
1781 py_ret = PyLdbResult_FromResult(res);
1783 talloc_free(mem_ctx);
1785 return py_ret;
1788 static PyObject *py_ldb_get_opaque(PyLdbObject *self, PyObject *args)
1790 char *name;
1791 void *data;
1793 if (!PyArg_ParseTuple(args, "s", &name))
1794 return NULL;
1796 data = ldb_get_opaque(pyldb_Ldb_AsLdbContext(self), name);
1798 if (data == NULL)
1799 Py_RETURN_NONE;
1801 /* FIXME: More interpretation */
1803 return Py_True;
1806 static PyObject *py_ldb_set_opaque(PyLdbObject *self, PyObject *args)
1808 char *name;
1809 PyObject *data;
1811 if (!PyArg_ParseTuple(args, "sO", &name, &data))
1812 return NULL;
1814 /* FIXME: More interpretation */
1816 ldb_set_opaque(pyldb_Ldb_AsLdbContext(self), name, data);
1818 Py_RETURN_NONE;
1821 static PyObject *py_ldb_modules(PyLdbObject *self)
1823 struct ldb_context *ldb = pyldb_Ldb_AsLdbContext(self);
1824 PyObject *ret = PyList_New(0);
1825 struct ldb_module *mod;
1827 for (mod = ldb->modules; mod; mod = mod->next) {
1828 PyList_Append(ret, PyLdbModule_FromModule(mod));
1831 return ret;
1834 static PyObject *py_ldb_sequence_number(PyLdbObject *self, PyObject *args)
1836 struct ldb_context *ldb = pyldb_Ldb_AsLdbContext(self);
1837 int type, ret;
1838 uint64_t value;
1840 if (!PyArg_ParseTuple(args, "i", &type))
1841 return NULL;
1843 /* FIXME: More interpretation */
1845 ret = ldb_sequence_number(ldb, type, &value);
1847 PyErr_LDB_ERROR_IS_ERR_RAISE(PyExc_LdbError, ret, ldb);
1849 return PyLong_FromLongLong(value);
1851 static PyMethodDef py_ldb_methods[] = {
1852 { "set_debug", (PyCFunction)py_ldb_set_debug, METH_VARARGS,
1853 "S.set_debug(callback) -> None\n"
1854 "Set callback for LDB debug messages.\n"
1855 "The callback should accept a debug level and debug text." },
1856 { "set_create_perms", (PyCFunction)py_ldb_set_create_perms, METH_VARARGS,
1857 "S.set_create_perms(mode) -> None\n"
1858 "Set mode to use when creating new LDB files." },
1859 { "set_modules_dir", (PyCFunction)py_ldb_set_modules_dir, METH_VARARGS,
1860 "S.set_modules_dir(path) -> None\n"
1861 "Set path LDB should search for modules" },
1862 { "transaction_start", (PyCFunction)py_ldb_transaction_start, METH_NOARGS,
1863 "S.transaction_start() -> None\n"
1864 "Start a new transaction." },
1865 { "transaction_prepare_commit", (PyCFunction)py_ldb_transaction_prepare_commit, METH_NOARGS,
1866 "S.transaction_prepare_commit() -> None\n"
1867 "prepare to commit a new transaction (2-stage commit)." },
1868 { "transaction_commit", (PyCFunction)py_ldb_transaction_commit, METH_NOARGS,
1869 "S.transaction_commit() -> None\n"
1870 "commit a new transaction." },
1871 { "transaction_cancel", (PyCFunction)py_ldb_transaction_cancel, METH_NOARGS,
1872 "S.transaction_cancel() -> None\n"
1873 "cancel a new transaction." },
1874 { "setup_wellknown_attributes", (PyCFunction)py_ldb_setup_wellknown_attributes, METH_NOARGS,
1875 NULL },
1876 { "get_root_basedn", (PyCFunction)py_ldb_get_root_basedn, METH_NOARGS,
1877 NULL },
1878 { "get_schema_basedn", (PyCFunction)py_ldb_get_schema_basedn, METH_NOARGS,
1879 NULL },
1880 { "get_default_basedn", (PyCFunction)py_ldb_get_default_basedn, METH_NOARGS,
1881 NULL },
1882 { "get_config_basedn", (PyCFunction)py_ldb_get_config_basedn, METH_NOARGS,
1883 NULL },
1884 { "connect", (PyCFunction)py_ldb_connect, METH_VARARGS|METH_KEYWORDS,
1885 "S.connect(url, flags=0, options=None) -> None\n"
1886 "Connect to a LDB URL." },
1887 { "modify", (PyCFunction)py_ldb_modify, METH_VARARGS|METH_KEYWORDS,
1888 "S.modify(message, controls=None, validate=False) -> None\n"
1889 "Modify an entry." },
1890 { "add", (PyCFunction)py_ldb_add, METH_VARARGS|METH_KEYWORDS,
1891 "S.add(message, controls=None) -> None\n"
1892 "Add an entry." },
1893 { "delete", (PyCFunction)py_ldb_delete, METH_VARARGS|METH_KEYWORDS,
1894 "S.delete(dn, controls=None) -> None\n"
1895 "Remove an entry." },
1896 { "rename", (PyCFunction)py_ldb_rename, METH_VARARGS|METH_KEYWORDS,
1897 "S.rename(old_dn, new_dn, controls=None) -> None\n"
1898 "Rename an entry." },
1899 { "search", (PyCFunction)py_ldb_search, METH_VARARGS|METH_KEYWORDS,
1900 "S.search(base=None, scope=None, expression=None, attrs=None, controls=None) -> msgs\n"
1901 "Search in a database.\n"
1902 "\n"
1903 ":param base: Optional base DN to search\n"
1904 ":param scope: Search scope (SCOPE_BASE, SCOPE_ONELEVEL or SCOPE_SUBTREE)\n"
1905 ":param expression: Optional search expression\n"
1906 ":param attrs: Attributes to return (defaults to all)\n"
1907 ":param controls: Optional list of controls\n"
1908 ":return: Iterator over Message objects\n"
1910 { "schema_attribute_remove", (PyCFunction)py_ldb_schema_attribute_remove, METH_VARARGS,
1911 NULL },
1912 { "schema_attribute_add", (PyCFunction)py_ldb_schema_attribute_add, METH_VARARGS,
1913 NULL },
1914 { "schema_format_value", (PyCFunction)py_ldb_schema_format_value, METH_VARARGS,
1915 NULL },
1916 { "parse_ldif", (PyCFunction)py_ldb_parse_ldif, METH_VARARGS,
1917 "S.parse_ldif(ldif) -> iter(messages)\n"
1918 "Parse a string formatted using LDIF." },
1919 { "write_ldif", (PyCFunction)py_ldb_write_ldif, METH_VARARGS,
1920 "S.write_ldif(message, changetype) -> ldif\n"
1921 "Print the message as a string formatted using LDIF." },
1922 { "msg_diff", (PyCFunction)py_ldb_msg_diff, METH_VARARGS,
1923 "S.msg_diff(Message) -> Message\n"
1924 "Return an LDB Message of the difference between two Message objects." },
1925 { "get_opaque", (PyCFunction)py_ldb_get_opaque, METH_VARARGS,
1926 "S.get_opaque(name) -> value\n"
1927 "Get an opaque value set on this LDB connection. \n"
1928 ":note: The returned value may not be useful in Python."
1930 { "set_opaque", (PyCFunction)py_ldb_set_opaque, METH_VARARGS,
1931 "S.set_opaque(name, value) -> None\n"
1932 "Set an opaque value on this LDB connection. \n"
1933 ":note: Passing incorrect values may cause crashes." },
1934 { "modules", (PyCFunction)py_ldb_modules, METH_NOARGS,
1935 "S.modules() -> list\n"
1936 "Return the list of modules on this LDB connection " },
1937 { "sequence_number", (PyCFunction)py_ldb_sequence_number, METH_VARARGS,
1938 "S.sequence_number(type) -> value\n"
1939 "Return the value of the sequence according to the requested type" },
1940 { NULL },
1943 static PyObject *PyLdbModule_FromModule(struct ldb_module *mod)
1945 PyLdbModuleObject *ret;
1947 ret = (PyLdbModuleObject *)PyLdbModule.tp_alloc(&PyLdbModule, 0);
1948 if (ret == NULL) {
1949 PyErr_NoMemory();
1950 return NULL;
1952 ret->mem_ctx = talloc_new(NULL);
1953 ret->mod = talloc_reference(ret->mem_ctx, mod);
1954 return (PyObject *)ret;
1957 static PyObject *py_ldb_get_firstmodule(PyLdbObject *self, void *closure)
1959 return PyLdbModule_FromModule(pyldb_Ldb_AsLdbContext(self)->modules);
1962 static PyGetSetDef py_ldb_getset[] = {
1963 { discard_const_p(char, "firstmodule"), (getter)py_ldb_get_firstmodule, NULL, NULL },
1964 { NULL }
1967 static int py_ldb_contains(PyLdbObject *self, PyObject *obj)
1969 struct ldb_context *ldb_ctx = pyldb_Ldb_AsLdbContext(self);
1970 struct ldb_dn *dn;
1971 struct ldb_result *result;
1972 unsigned int count;
1973 int ret;
1975 if (!pyldb_Object_AsDn(ldb_ctx, obj, ldb_ctx, &dn)) {
1976 return -1;
1979 ret = ldb_search(ldb_ctx, ldb_ctx, &result, dn, LDB_SCOPE_BASE, NULL,
1980 NULL);
1981 if (ret != LDB_SUCCESS) {
1982 PyErr_SetLdbError(PyExc_LdbError, ret, ldb_ctx);
1983 return -1;
1986 count = result->count;
1988 talloc_free(result);
1990 if (count > 1) {
1991 PyErr_Format(PyExc_RuntimeError,
1992 "Searching for [%s] dn gave %u results!",
1993 ldb_dn_get_linearized(dn),
1994 count);
1995 return -1;
1998 return count;
2001 static PySequenceMethods py_ldb_seq = {
2002 .sq_contains = (objobjproc)py_ldb_contains,
2005 static PyObject *PyLdb_FromLdbContext(struct ldb_context *ldb_ctx)
2007 PyLdbObject *ret;
2009 ret = (PyLdbObject *)PyLdb.tp_alloc(&PyLdb, 0);
2010 if (ret == NULL) {
2011 PyErr_NoMemory();
2012 return NULL;
2014 ret->mem_ctx = talloc_new(NULL);
2015 ret->ldb_ctx = talloc_reference(ret->mem_ctx, ldb_ctx);
2016 return (PyObject *)ret;
2019 static void py_ldb_dealloc(PyLdbObject *self)
2021 talloc_free(self->mem_ctx);
2022 Py_TYPE(self)->tp_free(self);
2025 static PyTypeObject PyLdb = {
2026 .tp_name = "ldb.Ldb",
2027 .tp_methods = py_ldb_methods,
2028 .tp_repr = (reprfunc)py_ldb_repr,
2029 .tp_new = py_ldb_new,
2030 .tp_init = (initproc)py_ldb_init,
2031 .tp_dealloc = (destructor)py_ldb_dealloc,
2032 .tp_getset = py_ldb_getset,
2033 .tp_getattro = PyObject_GenericGetAttr,
2034 .tp_basicsize = sizeof(PyLdbObject),
2035 .tp_doc = "Connection to a LDB database.",
2036 .tp_as_sequence = &py_ldb_seq,
2037 .tp_flags = Py_TPFLAGS_DEFAULT|Py_TPFLAGS_BASETYPE,
2040 static void py_ldb_result_dealloc(PyLdbResultObject *self)
2042 talloc_free(self->mem_ctx);
2043 Py_DECREF(self->msgs);
2044 Py_DECREF(self->referals);
2045 Py_DECREF(self->controls);
2046 Py_TYPE(self)->tp_free(self);
2049 static PyObject *py_ldb_result_get_msgs(PyLdbResultObject *self, void *closure)
2051 Py_INCREF(self->msgs);
2052 return self->msgs;
2055 static PyObject *py_ldb_result_get_controls(PyLdbResultObject *self, void *closure)
2057 Py_INCREF(self->controls);
2058 return self->controls;
2061 static PyObject *py_ldb_result_get_referals(PyLdbResultObject *self, void *closure)
2063 Py_INCREF(self->referals);
2064 return self->referals;
2067 static PyObject *py_ldb_result_get_count(PyLdbResultObject *self, void *closure)
2069 Py_ssize_t size;
2070 if (self->msgs == NULL) {
2071 PyErr_SetString(PyExc_AttributeError, "Count attribute is meaningless in this context");
2072 return NULL;
2074 size = PyList_Size(self->msgs);
2075 return PyInt_FromLong(size);
2078 static PyGetSetDef py_ldb_result_getset[] = {
2079 { discard_const_p(char, "controls"), (getter)py_ldb_result_get_controls, NULL, NULL },
2080 { discard_const_p(char, "msgs"), (getter)py_ldb_result_get_msgs, NULL, NULL },
2081 { discard_const_p(char, "referals"), (getter)py_ldb_result_get_referals, NULL, NULL },
2082 { discard_const_p(char, "count"), (getter)py_ldb_result_get_count, NULL, NULL },
2083 { NULL }
2086 static PyObject *py_ldb_result_iter(PyLdbResultObject *self)
2088 return PyObject_GetIter(self->msgs);
2091 static Py_ssize_t py_ldb_result_len(PyLdbResultObject *self)
2093 return PySequence_Size(self->msgs);
2096 static PyObject *py_ldb_result_find(PyLdbResultObject *self, Py_ssize_t idx)
2098 return PySequence_GetItem(self->msgs, idx);
2101 static PySequenceMethods py_ldb_result_seq = {
2102 .sq_length = (lenfunc)py_ldb_result_len,
2103 .sq_item = (ssizeargfunc)py_ldb_result_find,
2106 static PyObject *py_ldb_result_repr(PyLdbObject *self)
2108 return PyString_FromFormat("<ldb result>");
2112 static PyTypeObject PyLdbResult = {
2113 .tp_name = "ldb.Result",
2114 .tp_repr = (reprfunc)py_ldb_result_repr,
2115 .tp_dealloc = (destructor)py_ldb_result_dealloc,
2116 .tp_iter = (getiterfunc)py_ldb_result_iter,
2117 .tp_getset = py_ldb_result_getset,
2118 .tp_getattro = PyObject_GenericGetAttr,
2119 .tp_basicsize = sizeof(PyLdbResultObject),
2120 .tp_as_sequence = &py_ldb_result_seq,
2121 .tp_doc = "LDB result.",
2122 .tp_flags = Py_TPFLAGS_DEFAULT|Py_TPFLAGS_BASETYPE,
2125 static PyObject *py_ldb_module_repr(PyLdbModuleObject *self)
2127 return PyString_FromFormat("<ldb module '%s'>",
2128 pyldb_Module_AsModule(self)->ops->name);
2131 static PyObject *py_ldb_module_str(PyLdbModuleObject *self)
2133 return PyString_FromString(pyldb_Module_AsModule(self)->ops->name);
2136 static PyObject *py_ldb_module_start_transaction(PyLdbModuleObject *self)
2138 pyldb_Module_AsModule(self)->ops->start_transaction(pyldb_Module_AsModule(self));
2139 Py_RETURN_NONE;
2142 static PyObject *py_ldb_module_end_transaction(PyLdbModuleObject *self)
2144 pyldb_Module_AsModule(self)->ops->end_transaction(pyldb_Module_AsModule(self));
2145 Py_RETURN_NONE;
2148 static PyObject *py_ldb_module_del_transaction(PyLdbModuleObject *self)
2150 pyldb_Module_AsModule(self)->ops->del_transaction(pyldb_Module_AsModule(self));
2151 Py_RETURN_NONE;
2154 static PyObject *py_ldb_module_search(PyLdbModuleObject *self, PyObject *args, PyObject *kwargs)
2156 PyObject *py_base, *py_tree, *py_attrs, *py_ret;
2157 int ret, scope;
2158 struct ldb_request *req;
2159 const char * const kwnames[] = { "base", "scope", "tree", "attrs", NULL };
2160 struct ldb_module *mod;
2161 const char * const*attrs;
2163 /* type "int" rather than "enum" for "scope" is intentional */
2164 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "O!iOO",
2165 discard_const_p(char *, kwnames),
2166 &PyLdbDn, &py_base, &scope, &py_tree, &py_attrs))
2167 return NULL;
2169 mod = self->mod;
2171 if (py_attrs == Py_None) {
2172 attrs = NULL;
2173 } else {
2174 attrs = PyList_AsStringList(NULL, py_attrs, "attrs");
2175 if (attrs == NULL)
2176 return NULL;
2179 ret = ldb_build_search_req(&req, mod->ldb, NULL, pyldb_Dn_AsDn(py_base),
2180 scope, NULL /* expr */, attrs,
2181 NULL /* controls */, NULL, NULL, NULL);
2183 talloc_steal(req, attrs);
2185 PyErr_LDB_ERROR_IS_ERR_RAISE(PyExc_LdbError, ret, mod->ldb);
2187 req->op.search.res = NULL;
2189 ret = mod->ops->search(mod, req);
2191 PyErr_LDB_ERROR_IS_ERR_RAISE(PyExc_LdbError, ret, mod->ldb);
2193 py_ret = PyLdbResult_FromResult(req->op.search.res);
2195 talloc_free(req);
2197 return py_ret;
2201 static PyObject *py_ldb_module_add(PyLdbModuleObject *self, PyObject *args)
2203 struct ldb_request *req;
2204 PyObject *py_message;
2205 int ret;
2206 struct ldb_module *mod;
2208 if (!PyArg_ParseTuple(args, "O!", &PyLdbMessage, &py_message))
2209 return NULL;
2211 req = talloc_zero(NULL, struct ldb_request);
2212 req->operation = LDB_ADD;
2213 req->op.add.message = pyldb_Message_AsMessage(py_message);
2215 mod = pyldb_Module_AsModule(self);
2216 ret = mod->ops->add(mod, req);
2218 PyErr_LDB_ERROR_IS_ERR_RAISE(PyExc_LdbError, ret, mod->ldb);
2220 Py_RETURN_NONE;
2223 static PyObject *py_ldb_module_modify(PyLdbModuleObject *self, PyObject *args)
2225 int ret;
2226 struct ldb_request *req;
2227 PyObject *py_message;
2228 struct ldb_module *mod;
2230 if (!PyArg_ParseTuple(args, "O!", &PyLdbMessage, &py_message))
2231 return NULL;
2233 req = talloc_zero(NULL, struct ldb_request);
2234 req->operation = LDB_MODIFY;
2235 req->op.mod.message = pyldb_Message_AsMessage(py_message);
2237 mod = pyldb_Module_AsModule(self);
2238 ret = mod->ops->modify(mod, req);
2240 PyErr_LDB_ERROR_IS_ERR_RAISE(PyExc_LdbError, ret, mod->ldb);
2242 Py_RETURN_NONE;
2245 static PyObject *py_ldb_module_delete(PyLdbModuleObject *self, PyObject *args)
2247 int ret;
2248 struct ldb_request *req;
2249 PyObject *py_dn;
2251 if (!PyArg_ParseTuple(args, "O!", &PyLdbDn, &py_dn))
2252 return NULL;
2254 req = talloc_zero(NULL, struct ldb_request);
2255 req->operation = LDB_DELETE;
2256 req->op.del.dn = pyldb_Dn_AsDn(py_dn);
2258 ret = pyldb_Module_AsModule(self)->ops->del(pyldb_Module_AsModule(self), req);
2260 PyErr_LDB_ERROR_IS_ERR_RAISE(PyExc_LdbError, ret, NULL);
2262 Py_RETURN_NONE;
2265 static PyObject *py_ldb_module_rename(PyLdbModuleObject *self, PyObject *args)
2267 int ret;
2268 struct ldb_request *req;
2269 PyObject *py_dn1, *py_dn2;
2271 if (!PyArg_ParseTuple(args, "O!O!", &PyLdbDn, &py_dn1, &PyLdbDn, &py_dn2))
2272 return NULL;
2274 req = talloc_zero(NULL, struct ldb_request);
2276 req->operation = LDB_RENAME;
2277 req->op.rename.olddn = pyldb_Dn_AsDn(py_dn1);
2278 req->op.rename.newdn = pyldb_Dn_AsDn(py_dn2);
2280 ret = pyldb_Module_AsModule(self)->ops->rename(pyldb_Module_AsModule(self), req);
2282 PyErr_LDB_ERROR_IS_ERR_RAISE(PyExc_LdbError, ret, NULL);
2284 Py_RETURN_NONE;
2287 static PyMethodDef py_ldb_module_methods[] = {
2288 { "search", (PyCFunction)py_ldb_module_search, METH_VARARGS|METH_KEYWORDS, NULL },
2289 { "add", (PyCFunction)py_ldb_module_add, METH_VARARGS, NULL },
2290 { "modify", (PyCFunction)py_ldb_module_modify, METH_VARARGS, NULL },
2291 { "rename", (PyCFunction)py_ldb_module_rename, METH_VARARGS, NULL },
2292 { "delete", (PyCFunction)py_ldb_module_delete, METH_VARARGS, NULL },
2293 { "start_transaction", (PyCFunction)py_ldb_module_start_transaction, METH_NOARGS, NULL },
2294 { "end_transaction", (PyCFunction)py_ldb_module_end_transaction, METH_NOARGS, NULL },
2295 { "del_transaction", (PyCFunction)py_ldb_module_del_transaction, METH_NOARGS, NULL },
2296 { NULL },
2299 static void py_ldb_module_dealloc(PyLdbModuleObject *self)
2301 talloc_free(self->mem_ctx);
2302 PyObject_Del(self);
2305 static PyTypeObject PyLdbModule = {
2306 .tp_name = "ldb.LdbModule",
2307 .tp_methods = py_ldb_module_methods,
2308 .tp_repr = (reprfunc)py_ldb_module_repr,
2309 .tp_str = (reprfunc)py_ldb_module_str,
2310 .tp_basicsize = sizeof(PyLdbModuleObject),
2311 .tp_dealloc = (destructor)py_ldb_module_dealloc,
2312 .tp_flags = Py_TPFLAGS_DEFAULT,
2313 .tp_doc = "LDB module (extension)",
2318 * Create a ldb_message_element from a Python object.
2320 * This will accept any sequence objects that contains strings, or
2321 * a string object.
2323 * A reference to set_obj will be borrowed.
2325 * @param mem_ctx Memory context
2326 * @param set_obj Python object to convert
2327 * @param flags ldb_message_element flags to set
2328 * @param attr_name Name of the attribute
2329 * @return New ldb_message_element, allocated as child of mem_ctx
2331 static struct ldb_message_element *PyObject_AsMessageElement(
2332 TALLOC_CTX *mem_ctx,
2333 PyObject *set_obj,
2334 unsigned int flags,
2335 const char *attr_name)
2337 struct ldb_message_element *me;
2339 if (pyldb_MessageElement_Check(set_obj)) {
2340 PyLdbMessageElementObject *set_obj_as_me = (PyLdbMessageElementObject *)set_obj;
2341 /* We have to talloc_reference() the memory context, not the pointer
2342 * which may not actually be it's own context */
2343 if (talloc_reference(mem_ctx, set_obj_as_me->mem_ctx)) {
2344 return pyldb_MessageElement_AsMessageElement(set_obj);
2346 return NULL;
2349 me = talloc(mem_ctx, struct ldb_message_element);
2350 if (me == NULL) {
2351 PyErr_NoMemory();
2352 return NULL;
2355 me->name = talloc_strdup(me, attr_name);
2356 me->flags = flags;
2357 if (PyString_Check(set_obj)) {
2358 me->num_values = 1;
2359 me->values = talloc_array(me, struct ldb_val, me->num_values);
2360 me->values[0].length = PyString_Size(set_obj);
2361 me->values[0].data = talloc_memdup(me,
2362 (uint8_t *)PyString_AsString(set_obj), me->values[0].length+1);
2363 } else if (PySequence_Check(set_obj)) {
2364 Py_ssize_t i;
2365 me->num_values = PySequence_Size(set_obj);
2366 me->values = talloc_array(me, struct ldb_val, me->num_values);
2367 for (i = 0; i < me->num_values; i++) {
2368 PyObject *obj = PySequence_GetItem(set_obj, i);
2369 if (!PyString_Check(obj)) {
2370 PyErr_Format(PyExc_TypeError,
2371 "Expected string as element %zd in list", i);
2372 talloc_free(me);
2373 return NULL;
2376 me->values[i].length = PyString_Size(obj);
2377 me->values[i].data = talloc_memdup(me,
2378 (uint8_t *)PyString_AsString(obj), me->values[i].length+1);
2380 } else {
2381 PyErr_Format(PyExc_TypeError,
2382 "String or List type expected for '%s' attribute", attr_name);
2383 talloc_free(me);
2384 me = NULL;
2387 return me;
2391 static PyObject *ldb_msg_element_to_set(struct ldb_context *ldb_ctx,
2392 struct ldb_message_element *me)
2394 Py_ssize_t i;
2395 PyObject *result;
2397 /* Python << 2.5 doesn't have PySet_New and PySet_Add. */
2398 result = PyList_New(me->num_values);
2400 for (i = 0; i < me->num_values; i++) {
2401 PyList_SetItem(result, i,
2402 PyObject_FromLdbValue(&me->values[i]));
2405 return result;
2408 static PyObject *py_ldb_msg_element_get(PyLdbMessageElementObject *self, PyObject *args)
2410 unsigned int i;
2411 if (!PyArg_ParseTuple(args, "I", &i))
2412 return NULL;
2413 if (i >= pyldb_MessageElement_AsMessageElement(self)->num_values)
2414 Py_RETURN_NONE;
2416 return PyObject_FromLdbValue(&(pyldb_MessageElement_AsMessageElement(self)->values[i]));
2419 static PyObject *py_ldb_msg_element_flags(PyLdbMessageElementObject *self, PyObject *args)
2421 struct ldb_message_element *el = pyldb_MessageElement_AsMessageElement(self);
2422 return PyInt_FromLong(el->flags);
2425 static PyObject *py_ldb_msg_element_set_flags(PyLdbMessageElementObject *self, PyObject *args)
2427 unsigned int flags;
2428 struct ldb_message_element *el;
2429 if (!PyArg_ParseTuple(args, "I", &flags))
2430 return NULL;
2432 el = pyldb_MessageElement_AsMessageElement(self);
2433 el->flags = flags;
2434 Py_RETURN_NONE;
2437 static PyMethodDef py_ldb_msg_element_methods[] = {
2438 { "get", (PyCFunction)py_ldb_msg_element_get, METH_VARARGS, NULL },
2439 { "set_flags", (PyCFunction)py_ldb_msg_element_set_flags, METH_VARARGS, NULL },
2440 { "flags", (PyCFunction)py_ldb_msg_element_flags, METH_NOARGS, NULL },
2441 { NULL },
2444 static Py_ssize_t py_ldb_msg_element_len(PyLdbMessageElementObject *self)
2446 return pyldb_MessageElement_AsMessageElement(self)->num_values;
2449 static PyObject *py_ldb_msg_element_find(PyLdbMessageElementObject *self, Py_ssize_t idx)
2451 struct ldb_message_element *el = pyldb_MessageElement_AsMessageElement(self);
2452 if (idx < 0 || idx >= el->num_values) {
2453 PyErr_SetString(PyExc_IndexError, "Out of range");
2454 return NULL;
2456 return PyString_FromStringAndSize((char *)el->values[idx].data, el->values[idx].length);
2459 static PySequenceMethods py_ldb_msg_element_seq = {
2460 .sq_length = (lenfunc)py_ldb_msg_element_len,
2461 .sq_item = (ssizeargfunc)py_ldb_msg_element_find,
2464 static int py_ldb_msg_element_cmp(PyLdbMessageElementObject *self, PyLdbMessageElementObject *other)
2466 int ret = ldb_msg_element_compare(pyldb_MessageElement_AsMessageElement(self),
2467 pyldb_MessageElement_AsMessageElement(other));
2468 return SIGN(ret);
2471 static PyObject *py_ldb_msg_element_iter(PyLdbMessageElementObject *self)
2473 PyObject *el = ldb_msg_element_to_set(NULL,
2474 pyldb_MessageElement_AsMessageElement(self));
2475 PyObject *ret = PyObject_GetIter(el);
2476 Py_DECREF(el);
2477 return ret;
2480 static PyObject *PyLdbMessageElement_FromMessageElement(struct ldb_message_element *el, TALLOC_CTX *mem_ctx)
2482 PyLdbMessageElementObject *ret;
2483 ret = PyObject_New(PyLdbMessageElementObject, &PyLdbMessageElement);
2484 if (ret == NULL) {
2485 PyErr_NoMemory();
2486 return NULL;
2488 ret->mem_ctx = talloc_new(NULL);
2489 if (talloc_reference(ret->mem_ctx, mem_ctx) == NULL) {
2490 PyErr_NoMemory();
2491 return NULL;
2493 ret->el = el;
2494 return (PyObject *)ret;
2497 static PyObject *py_ldb_msg_element_new(PyTypeObject *type, PyObject *args, PyObject *kwargs)
2499 PyObject *py_elements = NULL;
2500 struct ldb_message_element *el;
2501 unsigned int flags = 0;
2502 char *name = NULL;
2503 const char * const kwnames[] = { "elements", "flags", "name", NULL };
2504 PyLdbMessageElementObject *ret;
2505 TALLOC_CTX *mem_ctx;
2507 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "|OIs",
2508 discard_const_p(char *, kwnames),
2509 &py_elements, &flags, &name))
2510 return NULL;
2512 mem_ctx = talloc_new(NULL);
2513 if (mem_ctx == NULL) {
2514 PyErr_NoMemory();
2515 return NULL;
2518 el = talloc_zero(mem_ctx, struct ldb_message_element);
2519 if (el == NULL) {
2520 PyErr_NoMemory();
2521 talloc_free(mem_ctx);
2522 return NULL;
2525 if (py_elements != NULL) {
2526 Py_ssize_t i;
2527 if (PyString_Check(py_elements)) {
2528 el->num_values = 1;
2529 el->values = talloc_array(el, struct ldb_val, 1);
2530 if (el->values == NULL) {
2531 talloc_free(mem_ctx);
2532 PyErr_NoMemory();
2533 return NULL;
2535 el->values[0].length = PyString_Size(py_elements);
2536 el->values[0].data = talloc_memdup(el->values,
2537 (uint8_t *)PyString_AsString(py_elements), el->values[0].length+1);
2538 } else if (PySequence_Check(py_elements)) {
2539 el->num_values = PySequence_Size(py_elements);
2540 el->values = talloc_array(el, struct ldb_val, el->num_values);
2541 if (el->values == NULL) {
2542 talloc_free(mem_ctx);
2543 PyErr_NoMemory();
2544 return NULL;
2546 for (i = 0; i < el->num_values; i++) {
2547 PyObject *item = PySequence_GetItem(py_elements, i);
2548 if (item == NULL) {
2549 talloc_free(mem_ctx);
2550 return NULL;
2552 if (!PyString_Check(item)) {
2553 PyErr_Format(PyExc_TypeError,
2554 "Expected string as element %zd in list", i);
2555 talloc_free(mem_ctx);
2556 return NULL;
2558 el->values[i].length = PyString_Size(item);
2559 el->values[i].data = talloc_memdup(el,
2560 (uint8_t *)PyString_AsString(item), el->values[i].length+1);
2562 } else {
2563 PyErr_SetString(PyExc_TypeError,
2564 "Expected string or list");
2565 talloc_free(mem_ctx);
2566 return NULL;
2570 el->flags = flags;
2571 el->name = talloc_strdup(el, name);
2573 ret = PyObject_New(PyLdbMessageElementObject, type);
2574 if (ret == NULL) {
2575 talloc_free(mem_ctx);
2576 return NULL;
2579 ret->mem_ctx = mem_ctx;
2580 ret->el = el;
2581 return (PyObject *)ret;
2584 static PyObject *py_ldb_msg_element_repr(PyLdbMessageElementObject *self)
2586 char *element_str = NULL;
2587 Py_ssize_t i;
2588 struct ldb_message_element *el = pyldb_MessageElement_AsMessageElement(self);
2589 PyObject *ret, *repr;
2591 for (i = 0; i < el->num_values; i++) {
2592 PyObject *o = py_ldb_msg_element_find(self, i);
2593 repr = PyObject_Repr(o);
2594 if (element_str == NULL)
2595 element_str = talloc_strdup(NULL, PyString_AsString(repr));
2596 else
2597 element_str = talloc_asprintf_append(element_str, ",%s", PyString_AsString(repr));
2598 Py_DECREF(repr);
2601 if (element_str != NULL) {
2602 ret = PyString_FromFormat("MessageElement([%s])", element_str);
2603 talloc_free(element_str);
2604 } else {
2605 ret = PyString_FromString("MessageElement([])");
2608 return ret;
2611 static PyObject *py_ldb_msg_element_str(PyLdbMessageElementObject *self)
2613 struct ldb_message_element *el = pyldb_MessageElement_AsMessageElement(self);
2615 if (el->num_values == 1)
2616 return PyString_FromStringAndSize((char *)el->values[0].data, el->values[0].length);
2617 else
2618 Py_RETURN_NONE;
2621 static void py_ldb_msg_element_dealloc(PyLdbMessageElementObject *self)
2623 talloc_free(self->mem_ctx);
2624 PyObject_Del(self);
2627 static PyTypeObject PyLdbMessageElement = {
2628 .tp_name = "ldb.MessageElement",
2629 .tp_basicsize = sizeof(PyLdbMessageElementObject),
2630 .tp_dealloc = (destructor)py_ldb_msg_element_dealloc,
2631 .tp_repr = (reprfunc)py_ldb_msg_element_repr,
2632 .tp_str = (reprfunc)py_ldb_msg_element_str,
2633 .tp_methods = py_ldb_msg_element_methods,
2634 .tp_compare = (cmpfunc)py_ldb_msg_element_cmp,
2635 .tp_iter = (getiterfunc)py_ldb_msg_element_iter,
2636 .tp_as_sequence = &py_ldb_msg_element_seq,
2637 .tp_new = py_ldb_msg_element_new,
2638 .tp_flags = Py_TPFLAGS_DEFAULT,
2639 .tp_doc = "An element of a Message",
2643 static PyObject *py_ldb_msg_from_dict(PyTypeObject *type, PyObject *args)
2645 PyObject *py_ldb;
2646 PyObject *py_dict;
2647 PyObject *py_ret;
2648 struct ldb_message *msg;
2649 struct ldb_context *ldb_ctx;
2650 unsigned int mod_flags = LDB_FLAG_MOD_REPLACE;
2652 if (!PyArg_ParseTuple(args, "O!O!|I",
2653 &PyLdb, &py_ldb, &PyDict_Type, &py_dict,
2654 &mod_flags)) {
2655 return NULL;
2658 if (!PyLdb_Check(py_ldb)) {
2659 PyErr_SetString(PyExc_TypeError, "Expected Ldb");
2660 return NULL;
2663 /* mask only flags we are going to use */
2664 mod_flags = LDB_FLAG_MOD_TYPE(mod_flags);
2665 if (!mod_flags) {
2666 PyErr_SetString(PyExc_ValueError,
2667 "FLAG_MOD_ADD, FLAG_MOD_REPLACE or FLAG_MOD_DELETE"
2668 " expected as mod_flag value");
2669 return NULL;
2672 ldb_ctx = pyldb_Ldb_AsLdbContext(py_ldb);
2674 msg = PyDict_AsMessage(ldb_ctx, py_dict, ldb_ctx, mod_flags);
2675 if (!msg) {
2676 return NULL;
2679 py_ret = PyLdbMessage_FromMessage(msg);
2681 talloc_unlink(ldb_ctx, msg);
2683 return py_ret;
2686 static PyObject *py_ldb_msg_remove_attr(PyLdbMessageObject *self, PyObject *args)
2688 char *name;
2689 if (!PyArg_ParseTuple(args, "s", &name))
2690 return NULL;
2692 ldb_msg_remove_attr(self->msg, name);
2694 Py_RETURN_NONE;
2697 static PyObject *py_ldb_msg_keys(PyLdbMessageObject *self)
2699 struct ldb_message *msg = pyldb_Message_AsMessage(self);
2700 Py_ssize_t i, j = 0;
2701 PyObject *obj = PyList_New(msg->num_elements+(msg->dn != NULL?1:0));
2702 if (msg->dn != NULL) {
2703 PyList_SetItem(obj, j, PyString_FromString("dn"));
2704 j++;
2706 for (i = 0; i < msg->num_elements; i++) {
2707 PyList_SetItem(obj, j, PyString_FromString(msg->elements[i].name));
2708 j++;
2710 return obj;
2713 static PyObject *py_ldb_msg_getitem_helper(PyLdbMessageObject *self, PyObject *py_name)
2715 struct ldb_message_element *el;
2716 char *name;
2717 struct ldb_message *msg = pyldb_Message_AsMessage(self);
2718 if (!PyString_Check(py_name)) {
2719 PyErr_SetNone(PyExc_TypeError);
2720 return NULL;
2722 name = PyString_AsString(py_name);
2723 if (!ldb_attr_cmp(name, "dn"))
2724 return pyldb_Dn_FromDn(msg->dn);
2725 el = ldb_msg_find_element(msg, name);
2726 if (el == NULL) {
2727 return NULL;
2729 return (PyObject *)PyLdbMessageElement_FromMessageElement(el, msg->elements);
2732 static PyObject *py_ldb_msg_getitem(PyLdbMessageObject *self, PyObject *py_name)
2734 PyObject *ret = py_ldb_msg_getitem_helper(self, py_name);
2735 if (ret == NULL) {
2736 PyErr_SetString(PyExc_KeyError, "No such element");
2737 return NULL;
2739 return ret;
2742 static PyObject *py_ldb_msg_get(PyLdbMessageObject *self, PyObject *args, PyObject *kwargs)
2744 PyObject *def = NULL;
2745 const char *kwnames[] = { "name", "default", "idx", NULL };
2746 const char *name = NULL;
2747 int idx = -1;
2748 struct ldb_message *msg = pyldb_Message_AsMessage(self);
2749 struct ldb_message_element *el;
2751 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "s|Oi:msg",
2752 discard_const_p(char *, kwnames), &name, &def, &idx)) {
2753 return NULL;
2756 if (strcasecmp(name, "dn") == 0) {
2757 return pyldb_Dn_FromDn(msg->dn);
2760 el = ldb_msg_find_element(msg, name);
2762 if (el == NULL || (idx != -1 && el->num_values <= idx)) {
2763 if (def != NULL) {
2764 return def;
2766 Py_RETURN_NONE;
2769 if (idx == -1) {
2770 return (PyObject *)PyLdbMessageElement_FromMessageElement(el, msg->elements);
2773 return PyObject_FromLdbValue(&el->values[idx]);
2776 static PyObject *py_ldb_msg_items(PyLdbMessageObject *self)
2778 struct ldb_message *msg = pyldb_Message_AsMessage(self);
2779 Py_ssize_t i, j = 0;
2780 PyObject *l = PyList_New(msg->num_elements + (msg->dn == NULL?0:1));
2781 if (msg->dn != NULL) {
2782 PyList_SetItem(l, 0, Py_BuildValue("(sO)", "dn", pyldb_Dn_FromDn(msg->dn)));
2783 j++;
2785 for (i = 0; i < msg->num_elements; i++, j++) {
2786 PyObject *py_el = PyLdbMessageElement_FromMessageElement(&msg->elements[i], msg->elements);
2787 PyObject *value = Py_BuildValue("(sO)", msg->elements[i].name, py_el);
2788 PyList_SetItem(l, j, value);
2790 return l;
2793 static PyObject *py_ldb_msg_elements(PyLdbMessageObject *self)
2795 struct ldb_message *msg = pyldb_Message_AsMessage(self);
2796 Py_ssize_t i = 0;
2797 PyObject *l = PyList_New(msg->num_elements);
2798 for (i = 0; i < msg->num_elements; i++) {
2799 PyList_SetItem(l, i, PyLdbMessageElement_FromMessageElement(&msg->elements[i], msg->elements));
2801 return l;
2804 static PyObject *py_ldb_msg_add(PyLdbMessageObject *self, PyObject *args)
2806 struct ldb_message *msg = pyldb_Message_AsMessage(self);
2807 PyLdbMessageElementObject *py_element;
2808 int i, ret;
2809 struct ldb_message_element *el;
2810 struct ldb_message_element *el_new;
2812 if (!PyArg_ParseTuple(args, "O!", &PyLdbMessageElement, &py_element))
2813 return NULL;
2815 el = py_element->el;
2816 if (el == NULL) {
2817 PyErr_SetString(PyExc_ValueError, "Invalid MessageElement object");
2818 return NULL;
2821 ret = ldb_msg_add_empty(msg, el->name, el->flags, &el_new);
2822 PyErr_LDB_ERROR_IS_ERR_RAISE(PyExc_LdbError, ret, NULL);
2824 /* now deep copy all attribute values */
2825 el_new->values = talloc_array(msg->elements, struct ldb_val, el->num_values);
2826 if (el_new->values == NULL) {
2827 PyErr_NoMemory();
2828 return NULL;
2830 el_new->num_values = el->num_values;
2832 for (i = 0; i < el->num_values; i++) {
2833 el_new->values[i] = ldb_val_dup(el_new->values, &el->values[i]);
2834 if (el_new->values[i].data == NULL
2835 && el->values[i].length != 0) {
2836 PyErr_NoMemory();
2837 return NULL;
2841 Py_RETURN_NONE;
2844 static PyMethodDef py_ldb_msg_methods[] = {
2845 { "from_dict", (PyCFunction)py_ldb_msg_from_dict, METH_CLASS | METH_VARARGS,
2846 "Message.from_dict(ldb, dict, mod_flag=FLAG_MOD_REPLACE) -> ldb.Message\n"
2847 "Class method to create ldb.Message object from Dictionary.\n"
2848 "mod_flag is one of FLAG_MOD_ADD, FLAG_MOD_REPLACE or FLAG_MOD_DELETE."},
2849 { "keys", (PyCFunction)py_ldb_msg_keys, METH_NOARGS,
2850 "S.keys() -> list\n\n"
2851 "Return sequence of all attribute names." },
2852 { "remove", (PyCFunction)py_ldb_msg_remove_attr, METH_VARARGS,
2853 "S.remove(name)\n\n"
2854 "Remove all entries for attributes with the specified name."},
2855 { "get", (PyCFunction)py_ldb_msg_get, METH_VARARGS | METH_KEYWORDS,
2856 "msg.get(name,default=None,idx=None) -> string\n"
2857 "idx is the index into the values array\n"
2858 "if idx is None, then a list is returned\n"
2859 "if idx is not None, then the element with that index is returned\n"
2860 "if you pass the special name 'dn' then the DN object is returned\n"},
2861 { "items", (PyCFunction)py_ldb_msg_items, METH_NOARGS, NULL },
2862 { "elements", (PyCFunction)py_ldb_msg_elements, METH_NOARGS, NULL },
2863 { "add", (PyCFunction)py_ldb_msg_add, METH_VARARGS,
2864 "S.add(element)\n\n"
2865 "Add an element to this message." },
2866 { NULL },
2869 static PyObject *py_ldb_msg_iter(PyLdbMessageObject *self)
2871 PyObject *list, *iter;
2873 list = py_ldb_msg_keys(self);
2874 iter = PyObject_GetIter(list);
2875 Py_DECREF(list);
2876 return iter;
2879 static int py_ldb_msg_setitem(PyLdbMessageObject *self, PyObject *name, PyObject *value)
2881 char *attr_name;
2883 if (!PyString_Check(name)) {
2884 PyErr_SetNone(PyExc_TypeError);
2885 return -1;
2888 attr_name = PyString_AsString(name);
2889 if (value == NULL) {
2890 /* delitem */
2891 ldb_msg_remove_attr(self->msg, attr_name);
2892 } else {
2893 int ret;
2894 struct ldb_message_element *el = PyObject_AsMessageElement(self->msg,
2895 value, 0, attr_name);
2896 if (el == NULL) {
2897 return -1;
2899 ldb_msg_remove_attr(pyldb_Message_AsMessage(self), attr_name);
2900 ret = ldb_msg_add(pyldb_Message_AsMessage(self), el, el->flags);
2901 if (ret != LDB_SUCCESS) {
2902 PyErr_SetLdbError(PyExc_LdbError, ret, NULL);
2903 return -1;
2906 return 0;
2909 static Py_ssize_t py_ldb_msg_length(PyLdbMessageObject *self)
2911 return pyldb_Message_AsMessage(self)->num_elements;
2914 static PyMappingMethods py_ldb_msg_mapping = {
2915 .mp_length = (lenfunc)py_ldb_msg_length,
2916 .mp_subscript = (binaryfunc)py_ldb_msg_getitem,
2917 .mp_ass_subscript = (objobjargproc)py_ldb_msg_setitem,
2920 static PyObject *py_ldb_msg_new(PyTypeObject *type, PyObject *args, PyObject *kwargs)
2922 const char * const kwnames[] = { "dn", NULL };
2923 struct ldb_message *ret;
2924 TALLOC_CTX *mem_ctx;
2925 PyObject *pydn = NULL;
2926 PyLdbMessageObject *py_ret;
2928 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "|O",
2929 discard_const_p(char *, kwnames),
2930 &pydn))
2931 return NULL;
2933 mem_ctx = talloc_new(NULL);
2934 if (mem_ctx == NULL) {
2935 PyErr_NoMemory();
2936 return NULL;
2939 ret = ldb_msg_new(mem_ctx);
2940 if (ret == NULL) {
2941 talloc_free(mem_ctx);
2942 PyErr_NoMemory();
2943 return NULL;
2946 if (pydn != NULL) {
2947 struct ldb_dn *dn;
2948 if (!pyldb_Object_AsDn(NULL, pydn, NULL, &dn)) {
2949 talloc_free(mem_ctx);
2950 return NULL;
2952 ret->dn = talloc_reference(ret, dn);
2955 py_ret = (PyLdbMessageObject *)type->tp_alloc(type, 0);
2956 if (py_ret == NULL) {
2957 PyErr_NoMemory();
2958 talloc_free(mem_ctx);
2959 return NULL;
2962 py_ret->mem_ctx = mem_ctx;
2963 py_ret->msg = ret;
2964 return (PyObject *)py_ret;
2967 static PyObject *PyLdbMessage_FromMessage(struct ldb_message *msg)
2969 PyLdbMessageObject *ret;
2971 ret = (PyLdbMessageObject *)PyLdbMessage.tp_alloc(&PyLdbMessage, 0);
2972 if (ret == NULL) {
2973 PyErr_NoMemory();
2974 return NULL;
2976 ret->mem_ctx = talloc_new(NULL);
2977 ret->msg = talloc_reference(ret->mem_ctx, msg);
2978 return (PyObject *)ret;
2981 static PyObject *py_ldb_msg_get_dn(PyLdbMessageObject *self, void *closure)
2983 struct ldb_message *msg = pyldb_Message_AsMessage(self);
2984 return pyldb_Dn_FromDn(msg->dn);
2987 static int py_ldb_msg_set_dn(PyLdbMessageObject *self, PyObject *value, void *closure)
2989 struct ldb_message *msg = pyldb_Message_AsMessage(self);
2990 if (!pyldb_Dn_Check(value)) {
2991 PyErr_SetString(PyExc_TypeError, "expected dn");
2992 return -1;
2995 msg->dn = talloc_reference(msg, pyldb_Dn_AsDn(value));
2996 return 0;
2999 static PyGetSetDef py_ldb_msg_getset[] = {
3000 { discard_const_p(char, "dn"), (getter)py_ldb_msg_get_dn, (setter)py_ldb_msg_set_dn, NULL },
3001 { NULL }
3004 static PyObject *py_ldb_msg_repr(PyLdbMessageObject *self)
3006 PyObject *dict = PyDict_New(), *ret;
3007 if (PyDict_Update(dict, (PyObject *)self) != 0)
3008 return NULL;
3009 ret = PyString_FromFormat("Message(%s)", PyObject_REPR(dict));
3010 Py_DECREF(dict);
3011 return ret;
3014 static void py_ldb_msg_dealloc(PyLdbMessageObject *self)
3016 talloc_free(self->mem_ctx);
3017 PyObject_Del(self);
3020 static int py_ldb_msg_compare(PyLdbMessageObject *py_msg1,
3021 PyLdbMessageObject *py_msg2)
3023 struct ldb_message *msg1 = pyldb_Message_AsMessage(py_msg1),
3024 *msg2 = pyldb_Message_AsMessage(py_msg2);
3025 unsigned int i;
3026 int ret;
3028 if ((msg1->dn != NULL) || (msg2->dn != NULL)) {
3029 ret = ldb_dn_compare(msg1->dn, msg2->dn);
3030 if (ret != 0) {
3031 return SIGN(ret);
3035 ret = msg1->num_elements - msg2->num_elements;
3036 if (ret != 0) {
3037 return SIGN(ret);
3040 for (i = 0; i < msg1->num_elements; i++) {
3041 ret = ldb_msg_element_compare_name(&msg1->elements[i],
3042 &msg2->elements[i]);
3043 if (ret != 0) {
3044 return SIGN(ret);
3047 ret = ldb_msg_element_compare(&msg1->elements[i],
3048 &msg2->elements[i]);
3049 if (ret != 0) {
3050 return SIGN(ret);
3054 return 0;
3057 static PyTypeObject PyLdbMessage = {
3058 .tp_name = "ldb.Message",
3059 .tp_methods = py_ldb_msg_methods,
3060 .tp_getset = py_ldb_msg_getset,
3061 .tp_as_mapping = &py_ldb_msg_mapping,
3062 .tp_basicsize = sizeof(PyLdbMessageObject),
3063 .tp_dealloc = (destructor)py_ldb_msg_dealloc,
3064 .tp_new = py_ldb_msg_new,
3065 .tp_repr = (reprfunc)py_ldb_msg_repr,
3066 .tp_flags = Py_TPFLAGS_DEFAULT,
3067 .tp_iter = (getiterfunc)py_ldb_msg_iter,
3068 .tp_compare = (cmpfunc)py_ldb_msg_compare,
3069 .tp_doc = "A LDB Message",
3072 static PyObject *PyLdbTree_FromTree(struct ldb_parse_tree *tree)
3074 PyLdbTreeObject *ret;
3076 ret = (PyLdbTreeObject *)PyLdbTree.tp_alloc(&PyLdbTree, 0);
3077 if (ret == NULL) {
3078 PyErr_NoMemory();
3079 return NULL;
3082 ret->mem_ctx = talloc_new(NULL);
3083 ret->tree = talloc_reference(ret->mem_ctx, tree);
3084 return (PyObject *)ret;
3087 static void py_ldb_tree_dealloc(PyLdbTreeObject *self)
3089 talloc_free(self->mem_ctx);
3090 PyObject_Del(self);
3093 static PyTypeObject PyLdbTree = {
3094 .tp_name = "ldb.Tree",
3095 .tp_basicsize = sizeof(PyLdbTreeObject),
3096 .tp_dealloc = (destructor)py_ldb_tree_dealloc,
3097 .tp_flags = Py_TPFLAGS_DEFAULT,
3098 .tp_doc = "A search tree",
3101 /* Ldb_module */
3102 static int py_module_search(struct ldb_module *mod, struct ldb_request *req)
3104 PyObject *py_ldb = (PyObject *)mod->private_data;
3105 PyObject *py_result, *py_base, *py_attrs, *py_tree;
3107 py_base = pyldb_Dn_FromDn(req->op.search.base);
3109 if (py_base == NULL)
3110 return LDB_ERR_OPERATIONS_ERROR;
3112 py_tree = PyLdbTree_FromTree(req->op.search.tree);
3114 if (py_tree == NULL)
3115 return LDB_ERR_OPERATIONS_ERROR;
3117 if (req->op.search.attrs == NULL) {
3118 py_attrs = Py_None;
3119 } else {
3120 int i, len;
3121 for (len = 0; req->op.search.attrs[len]; len++);
3122 py_attrs = PyList_New(len);
3123 for (i = 0; i < len; i++)
3124 PyList_SetItem(py_attrs, i, PyString_FromString(req->op.search.attrs[i]));
3127 py_result = PyObject_CallMethod(py_ldb, discard_const_p(char, "search"),
3128 discard_const_p(char, "OiOO"),
3129 py_base, req->op.search.scope, py_tree, py_attrs);
3131 Py_DECREF(py_attrs);
3132 Py_DECREF(py_tree);
3133 Py_DECREF(py_base);
3135 if (py_result == NULL) {
3136 return LDB_ERR_PYTHON_EXCEPTION;
3139 req->op.search.res = PyLdbResult_AsResult(NULL, py_result);
3140 if (req->op.search.res == NULL) {
3141 return LDB_ERR_PYTHON_EXCEPTION;
3144 Py_DECREF(py_result);
3146 return LDB_SUCCESS;
3149 static int py_module_add(struct ldb_module *mod, struct ldb_request *req)
3151 PyObject *py_ldb = (PyObject *)mod->private_data;
3152 PyObject *py_result, *py_msg;
3154 py_msg = PyLdbMessage_FromMessage(discard_const_p(struct ldb_message, req->op.add.message));
3156 if (py_msg == NULL) {
3157 return LDB_ERR_OPERATIONS_ERROR;
3160 py_result = PyObject_CallMethod(py_ldb, discard_const_p(char, "add"),
3161 discard_const_p(char, "O"),
3162 py_msg);
3164 Py_DECREF(py_msg);
3166 if (py_result == NULL) {
3167 return LDB_ERR_PYTHON_EXCEPTION;
3170 Py_DECREF(py_result);
3172 return LDB_SUCCESS;
3175 static int py_module_modify(struct ldb_module *mod, struct ldb_request *req)
3177 PyObject *py_ldb = (PyObject *)mod->private_data;
3178 PyObject *py_result, *py_msg;
3180 py_msg = PyLdbMessage_FromMessage(discard_const_p(struct ldb_message, req->op.mod.message));
3182 if (py_msg == NULL) {
3183 return LDB_ERR_OPERATIONS_ERROR;
3186 py_result = PyObject_CallMethod(py_ldb, discard_const_p(char, "modify"),
3187 discard_const_p(char, "O"),
3188 py_msg);
3190 Py_DECREF(py_msg);
3192 if (py_result == NULL) {
3193 return LDB_ERR_PYTHON_EXCEPTION;
3196 Py_DECREF(py_result);
3198 return LDB_SUCCESS;
3201 static int py_module_del(struct ldb_module *mod, struct ldb_request *req)
3203 PyObject *py_ldb = (PyObject *)mod->private_data;
3204 PyObject *py_result, *py_dn;
3206 py_dn = pyldb_Dn_FromDn(req->op.del.dn);
3208 if (py_dn == NULL)
3209 return LDB_ERR_OPERATIONS_ERROR;
3211 py_result = PyObject_CallMethod(py_ldb, discard_const_p(char, "delete"),
3212 discard_const_p(char, "O"),
3213 py_dn);
3215 if (py_result == NULL) {
3216 return LDB_ERR_PYTHON_EXCEPTION;
3219 Py_DECREF(py_result);
3221 return LDB_SUCCESS;
3224 static int py_module_rename(struct ldb_module *mod, struct ldb_request *req)
3226 PyObject *py_ldb = (PyObject *)mod->private_data;
3227 PyObject *py_result, *py_olddn, *py_newdn;
3229 py_olddn = pyldb_Dn_FromDn(req->op.rename.olddn);
3231 if (py_olddn == NULL)
3232 return LDB_ERR_OPERATIONS_ERROR;
3234 py_newdn = pyldb_Dn_FromDn(req->op.rename.newdn);
3236 if (py_newdn == NULL)
3237 return LDB_ERR_OPERATIONS_ERROR;
3239 py_result = PyObject_CallMethod(py_ldb, discard_const_p(char, "rename"),
3240 discard_const_p(char, "OO"),
3241 py_olddn, py_newdn);
3243 Py_DECREF(py_olddn);
3244 Py_DECREF(py_newdn);
3246 if (py_result == NULL) {
3247 return LDB_ERR_PYTHON_EXCEPTION;
3250 Py_DECREF(py_result);
3252 return LDB_SUCCESS;
3255 static int py_module_request(struct ldb_module *mod, struct ldb_request *req)
3257 PyObject *py_ldb = (PyObject *)mod->private_data;
3258 PyObject *py_result;
3260 py_result = PyObject_CallMethod(py_ldb, discard_const_p(char, "request"),
3261 discard_const_p(char, ""));
3263 Py_XDECREF(py_result);
3265 return LDB_ERR_OPERATIONS_ERROR;
3268 static int py_module_extended(struct ldb_module *mod, struct ldb_request *req)
3270 PyObject *py_ldb = (PyObject *)mod->private_data;
3271 PyObject *py_result;
3273 py_result = PyObject_CallMethod(py_ldb, discard_const_p(char, "extended"),
3274 discard_const_p(char, ""));
3276 Py_XDECREF(py_result);
3278 return LDB_ERR_OPERATIONS_ERROR;
3281 static int py_module_start_transaction(struct ldb_module *mod)
3283 PyObject *py_ldb = (PyObject *)mod->private_data;
3284 PyObject *py_result;
3286 py_result = PyObject_CallMethod(py_ldb, discard_const_p(char, "start_transaction"),
3287 discard_const_p(char, ""));
3289 if (py_result == NULL) {
3290 return LDB_ERR_PYTHON_EXCEPTION;
3293 Py_DECREF(py_result);
3295 return LDB_SUCCESS;
3298 static int py_module_end_transaction(struct ldb_module *mod)
3300 PyObject *py_ldb = (PyObject *)mod->private_data;
3301 PyObject *py_result;
3303 py_result = PyObject_CallMethod(py_ldb, discard_const_p(char, "end_transaction"),
3304 discard_const_p(char, ""));
3306 if (py_result == NULL) {
3307 return LDB_ERR_PYTHON_EXCEPTION;
3310 Py_DECREF(py_result);
3312 return LDB_SUCCESS;
3315 static int py_module_del_transaction(struct ldb_module *mod)
3317 PyObject *py_ldb = (PyObject *)mod->private_data;
3318 PyObject *py_result;
3320 py_result = PyObject_CallMethod(py_ldb, discard_const_p(char, "del_transaction"),
3321 discard_const_p(char, ""));
3323 if (py_result == NULL) {
3324 return LDB_ERR_PYTHON_EXCEPTION;
3327 Py_DECREF(py_result);
3329 return LDB_SUCCESS;
3332 static int py_module_destructor(struct ldb_module *mod)
3334 Py_DECREF((PyObject *)mod->private_data);
3335 return 0;
3338 static int py_module_init(struct ldb_module *mod)
3340 PyObject *py_class = (PyObject *)mod->ops->private_data;
3341 PyObject *py_result, *py_next, *py_ldb;
3343 py_ldb = PyLdb_FromLdbContext(mod->ldb);
3345 if (py_ldb == NULL)
3346 return LDB_ERR_OPERATIONS_ERROR;
3348 py_next = PyLdbModule_FromModule(mod->next);
3350 if (py_next == NULL)
3351 return LDB_ERR_OPERATIONS_ERROR;
3353 py_result = PyObject_CallFunction(py_class, discard_const_p(char, "OO"),
3354 py_ldb, py_next);
3356 if (py_result == NULL) {
3357 return LDB_ERR_PYTHON_EXCEPTION;
3360 mod->private_data = py_result;
3362 talloc_set_destructor(mod, py_module_destructor);
3364 return ldb_next_init(mod);
3367 static PyObject *py_register_module(PyObject *module, PyObject *args)
3369 int ret;
3370 struct ldb_module_ops *ops;
3371 PyObject *input;
3373 if (!PyArg_ParseTuple(args, "O", &input))
3374 return NULL;
3376 ops = talloc_zero(talloc_autofree_context(), struct ldb_module_ops);
3377 if (ops == NULL) {
3378 PyErr_NoMemory();
3379 return NULL;
3382 ops->name = talloc_strdup(ops, PyString_AsString(PyObject_GetAttrString(input, discard_const_p(char, "name"))));
3384 Py_INCREF(input);
3385 ops->private_data = input;
3386 ops->init_context = py_module_init;
3387 ops->search = py_module_search;
3388 ops->add = py_module_add;
3389 ops->modify = py_module_modify;
3390 ops->del = py_module_del;
3391 ops->rename = py_module_rename;
3392 ops->request = py_module_request;
3393 ops->extended = py_module_extended;
3394 ops->start_transaction = py_module_start_transaction;
3395 ops->end_transaction = py_module_end_transaction;
3396 ops->del_transaction = py_module_del_transaction;
3398 ret = ldb_register_module(ops);
3400 PyErr_LDB_ERROR_IS_ERR_RAISE(PyExc_LdbError, ret, NULL);
3402 Py_RETURN_NONE;
3405 static PyObject *py_timestring(PyObject *module, PyObject *args)
3407 /* most times "time_t" is a signed integer type with 32 or 64 bit:
3408 * http://stackoverflow.com/questions/471248/what-is-ultimately-a-time-t-typedef-to */
3409 long int t_val;
3410 char *tresult;
3411 PyObject *ret;
3412 if (!PyArg_ParseTuple(args, "l", &t_val))
3413 return NULL;
3414 tresult = ldb_timestring(NULL, (time_t) t_val);
3415 ret = PyString_FromString(tresult);
3416 talloc_free(tresult);
3417 return ret;
3420 static PyObject *py_string_to_time(PyObject *module, PyObject *args)
3422 char *str;
3423 if (!PyArg_ParseTuple(args, "s", &str))
3424 return NULL;
3426 return PyInt_FromLong(ldb_string_to_time(str));
3429 static PyObject *py_valid_attr_name(PyObject *self, PyObject *args)
3431 char *name;
3432 if (!PyArg_ParseTuple(args, "s", &name))
3433 return NULL;
3434 return PyBool_FromLong(ldb_valid_attr_name(name));
3438 encode a string using RFC2254 rules
3440 static PyObject *py_binary_encode(PyObject *self, PyObject *args)
3442 char *str, *encoded;
3443 int size = 0;
3444 struct ldb_val val;
3445 PyObject *ret;
3447 if (!PyArg_ParseTuple(args, "s#", &str, &size))
3448 return NULL;
3449 val.data = (uint8_t *)str;
3450 val.length = size;
3452 encoded = ldb_binary_encode(NULL, val);
3453 if (encoded == NULL) {
3454 PyErr_SetString(PyExc_TypeError, "unable to encode binary string");
3455 return NULL;
3457 ret = PyString_FromString(encoded);
3458 talloc_free(encoded);
3459 return ret;
3463 decode a string using RFC2254 rules
3465 static PyObject *py_binary_decode(PyObject *self, PyObject *args)
3467 char *str;
3468 struct ldb_val val;
3469 PyObject *ret;
3471 if (!PyArg_ParseTuple(args, "s", &str))
3472 return NULL;
3474 val = ldb_binary_decode(NULL, str);
3475 if (val.data == NULL) {
3476 PyErr_SetString(PyExc_TypeError, "unable to decode binary string");
3477 return NULL;
3479 ret = Py_BuildValue("s#", val.data, val.length);
3480 talloc_free(val.data);
3481 return ret;
3484 static PyMethodDef py_ldb_global_methods[] = {
3485 { "register_module", py_register_module, METH_VARARGS,
3486 "S.register_module(module) -> None\n\n"
3487 "Register a LDB module."},
3488 { "timestring", py_timestring, METH_VARARGS,
3489 "S.timestring(int) -> string\n\n"
3490 "Generate a LDAP time string from a UNIX timestamp" },
3491 { "string_to_time", py_string_to_time, METH_VARARGS,
3492 "S.string_to_time(string) -> int\n\n"
3493 "Parse a LDAP time string into a UNIX timestamp." },
3494 { "valid_attr_name", py_valid_attr_name, METH_VARARGS,
3495 "S.valid_attr_name(name) -> bool\n\nn"
3496 "Check whether the supplied name is a valid attribute name." },
3497 { "open", (PyCFunction)py_ldb_new, METH_VARARGS|METH_KEYWORDS,
3498 "S.open() -> Ldb\n\n"
3499 "Open a new LDB context." },
3500 { "binary_encode", py_binary_encode, METH_VARARGS,
3501 "S.binary_encode(string) -> string\n\n"
3502 "Perform a RFC2254 binary encoding on a string" },
3503 { "binary_decode", py_binary_decode, METH_VARARGS,
3504 "S.binary_decode(string) -> string\n\n"
3505 "Perform a RFC2254 binary decode on a string" },
3506 { NULL }
3509 void initldb(void)
3511 PyObject *m;
3513 if (PyType_Ready(&PyLdbDn) < 0)
3514 return;
3516 if (PyType_Ready(&PyLdbMessage) < 0)
3517 return;
3519 if (PyType_Ready(&PyLdbMessageElement) < 0)
3520 return;
3522 if (PyType_Ready(&PyLdb) < 0)
3523 return;
3525 if (PyType_Ready(&PyLdbModule) < 0)
3526 return;
3528 if (PyType_Ready(&PyLdbTree) < 0)
3529 return;
3531 if (PyType_Ready(&PyLdbResult) < 0)
3532 return;
3534 if (PyType_Ready(&PyLdbControl) < 0)
3535 return;
3537 m = Py_InitModule3("ldb", py_ldb_global_methods,
3538 "An interface to LDB, a LDAP-like API that can either to talk an embedded database (TDB-based) or a standards-compliant LDAP server.");
3539 if (m == NULL)
3540 return;
3542 PyModule_AddObject(m, "SEQ_HIGHEST_SEQ", PyInt_FromLong(LDB_SEQ_HIGHEST_SEQ));
3543 PyModule_AddObject(m, "SEQ_HIGHEST_TIMESTAMP", PyInt_FromLong(LDB_SEQ_HIGHEST_TIMESTAMP));
3544 PyModule_AddObject(m, "SEQ_NEXT", PyInt_FromLong(LDB_SEQ_NEXT));
3545 PyModule_AddObject(m, "SCOPE_DEFAULT", PyInt_FromLong(LDB_SCOPE_DEFAULT));
3546 PyModule_AddObject(m, "SCOPE_BASE", PyInt_FromLong(LDB_SCOPE_BASE));
3547 PyModule_AddObject(m, "SCOPE_ONELEVEL", PyInt_FromLong(LDB_SCOPE_ONELEVEL));
3548 PyModule_AddObject(m, "SCOPE_SUBTREE", PyInt_FromLong(LDB_SCOPE_SUBTREE));
3550 PyModule_AddObject(m, "CHANGETYPE_NONE", PyInt_FromLong(LDB_CHANGETYPE_NONE));
3551 PyModule_AddObject(m, "CHANGETYPE_ADD", PyInt_FromLong(LDB_CHANGETYPE_ADD));
3552 PyModule_AddObject(m, "CHANGETYPE_DELETE", PyInt_FromLong(LDB_CHANGETYPE_DELETE));
3553 PyModule_AddObject(m, "CHANGETYPE_MODIFY", PyInt_FromLong(LDB_CHANGETYPE_MODIFY));
3555 PyModule_AddObject(m, "FLAG_MOD_ADD", PyInt_FromLong(LDB_FLAG_MOD_ADD));
3556 PyModule_AddObject(m, "FLAG_MOD_REPLACE", PyInt_FromLong(LDB_FLAG_MOD_REPLACE));
3557 PyModule_AddObject(m, "FLAG_MOD_DELETE", PyInt_FromLong(LDB_FLAG_MOD_DELETE));
3559 PyModule_AddObject(m, "SUCCESS", PyInt_FromLong(LDB_SUCCESS));
3560 PyModule_AddObject(m, "ERR_OPERATIONS_ERROR", PyInt_FromLong(LDB_ERR_OPERATIONS_ERROR));
3561 PyModule_AddObject(m, "ERR_PROTOCOL_ERROR", PyInt_FromLong(LDB_ERR_PROTOCOL_ERROR));
3562 PyModule_AddObject(m, "ERR_TIME_LIMIT_EXCEEDED", PyInt_FromLong(LDB_ERR_TIME_LIMIT_EXCEEDED));
3563 PyModule_AddObject(m, "ERR_SIZE_LIMIT_EXCEEDED", PyInt_FromLong(LDB_ERR_SIZE_LIMIT_EXCEEDED));
3564 PyModule_AddObject(m, "ERR_COMPARE_FALSE", PyInt_FromLong(LDB_ERR_COMPARE_FALSE));
3565 PyModule_AddObject(m, "ERR_COMPARE_TRUE", PyInt_FromLong(LDB_ERR_COMPARE_TRUE));
3566 PyModule_AddObject(m, "ERR_AUTH_METHOD_NOT_SUPPORTED", PyInt_FromLong(LDB_ERR_AUTH_METHOD_NOT_SUPPORTED));
3567 PyModule_AddObject(m, "ERR_STRONG_AUTH_REQUIRED", PyInt_FromLong(LDB_ERR_STRONG_AUTH_REQUIRED));
3568 PyModule_AddObject(m, "ERR_REFERRAL", PyInt_FromLong(LDB_ERR_REFERRAL));
3569 PyModule_AddObject(m, "ERR_ADMIN_LIMIT_EXCEEDED", PyInt_FromLong(LDB_ERR_ADMIN_LIMIT_EXCEEDED));
3570 PyModule_AddObject(m, "ERR_UNSUPPORTED_CRITICAL_EXTENSION", PyInt_FromLong(LDB_ERR_UNSUPPORTED_CRITICAL_EXTENSION));
3571 PyModule_AddObject(m, "ERR_CONFIDENTIALITY_REQUIRED", PyInt_FromLong(LDB_ERR_CONFIDENTIALITY_REQUIRED));
3572 PyModule_AddObject(m, "ERR_SASL_BIND_IN_PROGRESS", PyInt_FromLong(LDB_ERR_SASL_BIND_IN_PROGRESS));
3573 PyModule_AddObject(m, "ERR_NO_SUCH_ATTRIBUTE", PyInt_FromLong(LDB_ERR_NO_SUCH_ATTRIBUTE));
3574 PyModule_AddObject(m, "ERR_UNDEFINED_ATTRIBUTE_TYPE", PyInt_FromLong(LDB_ERR_UNDEFINED_ATTRIBUTE_TYPE));
3575 PyModule_AddObject(m, "ERR_INAPPROPRIATE_MATCHING", PyInt_FromLong(LDB_ERR_INAPPROPRIATE_MATCHING));
3576 PyModule_AddObject(m, "ERR_CONSTRAINT_VIOLATION", PyInt_FromLong(LDB_ERR_CONSTRAINT_VIOLATION));
3577 PyModule_AddObject(m, "ERR_ATTRIBUTE_OR_VALUE_EXISTS", PyInt_FromLong(LDB_ERR_ATTRIBUTE_OR_VALUE_EXISTS));
3578 PyModule_AddObject(m, "ERR_INVALID_ATTRIBUTE_SYNTAX", PyInt_FromLong(LDB_ERR_INVALID_ATTRIBUTE_SYNTAX));
3579 PyModule_AddObject(m, "ERR_NO_SUCH_OBJECT", PyInt_FromLong(LDB_ERR_NO_SUCH_OBJECT));
3580 PyModule_AddObject(m, "ERR_ALIAS_PROBLEM", PyInt_FromLong(LDB_ERR_ALIAS_PROBLEM));
3581 PyModule_AddObject(m, "ERR_INVALID_DN_SYNTAX", PyInt_FromLong(LDB_ERR_INVALID_DN_SYNTAX));
3582 PyModule_AddObject(m, "ERR_ALIAS_DEREFERINCING_PROBLEM", PyInt_FromLong(LDB_ERR_ALIAS_DEREFERENCING_PROBLEM));
3583 PyModule_AddObject(m, "ERR_INAPPROPRIATE_AUTHENTICATION", PyInt_FromLong(LDB_ERR_INAPPROPRIATE_AUTHENTICATION));
3584 PyModule_AddObject(m, "ERR_INVALID_CREDENTIALS", PyInt_FromLong(LDB_ERR_INVALID_CREDENTIALS));
3585 PyModule_AddObject(m, "ERR_INSUFFICIENT_ACCESS_RIGHTS", PyInt_FromLong(LDB_ERR_INSUFFICIENT_ACCESS_RIGHTS));
3586 PyModule_AddObject(m, "ERR_BUSY", PyInt_FromLong(LDB_ERR_BUSY));
3587 PyModule_AddObject(m, "ERR_UNAVAILABLE", PyInt_FromLong(LDB_ERR_UNAVAILABLE));
3588 PyModule_AddObject(m, "ERR_UNWILLING_TO_PERFORM", PyInt_FromLong(LDB_ERR_UNWILLING_TO_PERFORM));
3589 PyModule_AddObject(m, "ERR_LOOP_DETECT", PyInt_FromLong(LDB_ERR_LOOP_DETECT));
3590 PyModule_AddObject(m, "ERR_NAMING_VIOLATION", PyInt_FromLong(LDB_ERR_NAMING_VIOLATION));
3591 PyModule_AddObject(m, "ERR_OBJECT_CLASS_VIOLATION", PyInt_FromLong(LDB_ERR_OBJECT_CLASS_VIOLATION));
3592 PyModule_AddObject(m, "ERR_NOT_ALLOWED_ON_NON_LEAF", PyInt_FromLong(LDB_ERR_NOT_ALLOWED_ON_NON_LEAF));
3593 PyModule_AddObject(m, "ERR_NOT_ALLOWED_ON_RDN", PyInt_FromLong(LDB_ERR_NOT_ALLOWED_ON_RDN));
3594 PyModule_AddObject(m, "ERR_ENTRY_ALREADY_EXISTS", PyInt_FromLong(LDB_ERR_ENTRY_ALREADY_EXISTS));
3595 PyModule_AddObject(m, "ERR_OBJECT_CLASS_MODS_PROHIBITED", PyInt_FromLong(LDB_ERR_OBJECT_CLASS_MODS_PROHIBITED));
3596 PyModule_AddObject(m, "ERR_AFFECTS_MULTIPLE_DSAS", PyInt_FromLong(LDB_ERR_AFFECTS_MULTIPLE_DSAS));
3597 PyModule_AddObject(m, "ERR_OTHER", PyInt_FromLong(LDB_ERR_OTHER));
3599 PyModule_AddObject(m, "FLG_RDONLY", PyInt_FromLong(LDB_FLG_RDONLY));
3600 PyModule_AddObject(m, "FLG_NOSYNC", PyInt_FromLong(LDB_FLG_NOSYNC));
3601 PyModule_AddObject(m, "FLG_RECONNECT", PyInt_FromLong(LDB_FLG_RECONNECT));
3602 PyModule_AddObject(m, "FLG_NOMMAP", PyInt_FromLong(LDB_FLG_NOMMAP));
3604 PyModule_AddObject(m, "__docformat__", PyString_FromString("restructuredText"));
3606 PyExc_LdbError = PyErr_NewException(discard_const_p(char, "_ldb.LdbError"), NULL, NULL);
3607 PyModule_AddObject(m, "LdbError", PyExc_LdbError);
3609 Py_INCREF(&PyLdb);
3610 Py_INCREF(&PyLdbDn);
3611 Py_INCREF(&PyLdbModule);
3612 Py_INCREF(&PyLdbMessage);
3613 Py_INCREF(&PyLdbMessageElement);
3614 Py_INCREF(&PyLdbTree);
3615 Py_INCREF(&PyLdbResult);
3616 Py_INCREF(&PyLdbControl);
3618 PyModule_AddObject(m, "Ldb", (PyObject *)&PyLdb);
3619 PyModule_AddObject(m, "Dn", (PyObject *)&PyLdbDn);
3620 PyModule_AddObject(m, "Message", (PyObject *)&PyLdbMessage);
3621 PyModule_AddObject(m, "MessageElement", (PyObject *)&PyLdbMessageElement);
3622 PyModule_AddObject(m, "Module", (PyObject *)&PyLdbModule);
3623 PyModule_AddObject(m, "Tree", (PyObject *)&PyLdbTree);
3624 PyModule_AddObject(m, "Control", (PyObject *)&PyLdbControl);
3626 PyModule_AddObject(m, "__version__", PyString_FromString(PACKAGE_VERSION));
3628 #define ADD_LDB_STRING(val) PyModule_AddObject(m, #val, PyString_FromString(LDB_## val))
3630 ADD_LDB_STRING(SYNTAX_DN);
3631 ADD_LDB_STRING(SYNTAX_DIRECTORY_STRING);
3632 ADD_LDB_STRING(SYNTAX_INTEGER);
3633 ADD_LDB_STRING(SYNTAX_BOOLEAN);
3634 ADD_LDB_STRING(SYNTAX_OCTET_STRING);
3635 ADD_LDB_STRING(SYNTAX_UTC_TIME);
3636 ADD_LDB_STRING(OID_COMPARATOR_AND);
3637 ADD_LDB_STRING(OID_COMPARATOR_OR);