ctdb-tests: Switch to using new event daemon
[samba.git] / lib / ldb / pyldb.c
blob110ec8e60ada3c0bf2c140be9123e3ef765233b0
1 /*
2 Unix SMB/CIFS implementation.
4 Python interface to ldb.
6 Copyright (C) 2005,2006 Tim Potter <tpot@samba.org>
7 Copyright (C) 2006 Simo Sorce <idra@samba.org>
8 Copyright (C) 2007-2010 Jelmer Vernooij <jelmer@samba.org>
9 Copyright (C) 2009-2010 Matthias Dieter Wallnöfer
10 Copyright (C) 2009-2011 Andrew Tridgell
11 Copyright (C) 2009-2011 Andrew Bartlett
13 ** NOTE! The following LGPL license applies to the ldb
14 ** library. This does NOT imply that all of Samba is released
15 ** under the LGPL
17 This library is free software; you can redistribute it and/or
18 modify it under the terms of the GNU Lesser General Public
19 License as published by the Free Software Foundation; either
20 version 3 of the License, or (at your option) any later version.
22 This library is distributed in the hope that it will be useful,
23 but WITHOUT ANY WARRANTY; without even the implied warranty of
24 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
25 Lesser General Public License for more details.
27 You should have received a copy of the GNU Lesser General Public
28 License along with this library; if not, see <http://www.gnu.org/licenses/>.
31 #include <Python.h>
32 #include "ldb_private.h"
33 #include "ldb_handlers.h"
34 #include "pyldb.h"
35 #include "dlinklist.h"
37 struct py_ldb_search_iterator_reply;
39 typedef struct {
40 PyObject_HEAD
41 TALLOC_CTX *mem_ctx;
42 PyLdbObject *ldb;
43 struct {
44 struct ldb_request *req;
45 struct py_ldb_search_iterator_reply *next;
46 struct py_ldb_search_iterator_reply *result;
47 PyObject *exception;
48 } state;
49 } PyLdbSearchIteratorObject;
51 struct py_ldb_search_iterator_reply {
52 struct py_ldb_search_iterator_reply *prev, *next;
53 PyLdbSearchIteratorObject *py_iter;
54 PyObject *obj;
57 void initldb(void);
58 static PyObject *PyLdbMessage_FromMessage(struct ldb_message *msg);
59 static PyObject *PyExc_LdbError;
61 static PyTypeObject PyLdbControl;
62 static PyTypeObject PyLdbResult;
63 static PyTypeObject PyLdbSearchIterator;
64 static PyTypeObject PyLdbMessage;
65 #define PyLdbMessage_Check(ob) PyObject_TypeCheck(ob, &PyLdbMessage)
66 static PyTypeObject PyLdbModule;
67 static PyTypeObject PyLdbDn;
68 #define pyldb_Dn_Check(ob) PyObject_TypeCheck(ob, &PyLdbDn)
69 static PyTypeObject PyLdb;
70 #define PyLdb_Check(ob) PyObject_TypeCheck(ob, &PyLdb)
71 static PyTypeObject PyLdbMessageElement;
72 #define pyldb_MessageElement_Check(ob) PyObject_TypeCheck(ob, &PyLdbMessageElement)
74 static PyTypeObject PyLdbTree;
75 static PyObject *PyLdb_FromLdbContext(struct ldb_context *ldb_ctx);
76 static PyObject *PyLdbModule_FromModule(struct ldb_module *mod);
77 static struct ldb_message_element *PyObject_AsMessageElement(
78 TALLOC_CTX *mem_ctx,
79 PyObject *set_obj,
80 unsigned int flags,
81 const char *attr_name);
83 #if PY_MAJOR_VERSION >= 3
84 #define PyStr_Check PyUnicode_Check
85 #define PyStr_FromString PyUnicode_FromString
86 #define PyStr_FromStringAndSize PyUnicode_FromStringAndSize
87 #define PyStr_FromFormat PyUnicode_FromFormat
88 #define PyStr_FromFormatV PyUnicode_FromFormatV
89 #define PyStr_AsUTF8 PyUnicode_AsUTF8
90 #define PyStr_AsUTF8AndSize PyUnicode_AsUTF8AndSize
91 #define PyInt_FromLong PyLong_FromLong
92 #else
93 #define PyStr_Check PyString_Check
94 #define PyStr_FromString PyString_FromString
95 #define PyStr_FromStringAndSize PyString_FromStringAndSize
96 #define PyStr_FromFormat PyString_FromFormat
97 #define PyStr_FromFormatV PyString_FromFormatV
98 #define PyStr_AsUTF8 PyString_AsString
100 const char *PyStr_AsUTF8AndSize(PyObject *pystr, Py_ssize_t *sizeptr);
101 const char *
102 PyStr_AsUTF8AndSize(PyObject *pystr, Py_ssize_t *sizeptr)
104 const char * ret = PyString_AsString(pystr);
105 if (ret == NULL)
106 return NULL;
107 *sizeptr = PyString_Size(pystr);
108 return ret;
110 #endif
112 static PyObject *richcmp(int cmp_val, int op)
114 int ret;
115 switch (op) {
116 case Py_LT: ret = cmp_val < 0; break;
117 case Py_LE: ret = cmp_val <= 0; break;
118 case Py_EQ: ret = cmp_val == 0; break;
119 case Py_NE: ret = cmp_val != 0; break;
120 case Py_GT: ret = cmp_val > 0; break;
121 case Py_GE: ret = cmp_val >= 0; break;
122 default:
123 Py_INCREF(Py_NotImplemented);
124 return Py_NotImplemented;
126 return PyBool_FromLong(ret);
130 static PyObject *py_ldb_control_str(PyLdbControlObject *self)
132 if (self->data != NULL) {
133 char* control = ldb_control_to_string(self->mem_ctx, self->data);
134 if (control == NULL) {
135 PyErr_NoMemory();
136 return NULL;
138 return PyStr_FromString(control);
139 } else {
140 return PyStr_FromString("ldb control");
144 static void py_ldb_control_dealloc(PyLdbControlObject *self)
146 if (self->mem_ctx != NULL) {
147 talloc_free(self->mem_ctx);
149 self->data = NULL;
150 Py_TYPE(self)->tp_free(self);
153 /* Create a text (rather than bytes) interface for a LDB result object */
154 static PyObject *wrap_text(const char *type, PyObject *wrapped)
156 PyObject *mod, *cls, *constructor, *inst;
157 mod = PyImport_ImportModule("_ldb_text");
158 if (mod == NULL)
159 return NULL;
160 cls = PyObject_GetAttrString(mod, type);
161 Py_DECREF(mod);
162 if (cls == NULL) {
163 Py_DECREF(mod);
164 return NULL;
166 constructor = PyObject_GetAttrString(cls, "_wrap");
167 Py_DECREF(cls);
168 if (constructor == NULL) {
169 return NULL;
171 inst = PyObject_CallFunction(constructor, discard_const_p(char, "O"), wrapped);
172 Py_DECREF(constructor);
173 return inst;
176 static PyObject *py_ldb_control_get_oid(PyLdbControlObject *self)
178 return PyStr_FromString(self->data->oid);
181 static PyObject *py_ldb_control_get_critical(PyLdbControlObject *self)
183 return PyBool_FromLong(self->data->critical);
186 static PyObject *py_ldb_control_set_critical(PyLdbControlObject *self, PyObject *value, void *closure)
188 if (PyObject_IsTrue(value)) {
189 self->data->critical = true;
190 } else {
191 self->data->critical = false;
193 return 0;
196 static PyObject *py_ldb_control_new(PyTypeObject *type, PyObject *args, PyObject *kwargs)
198 char *data = NULL;
199 const char * const kwnames[] = { "ldb", "data", NULL };
200 struct ldb_control *parsed_controls;
201 PyLdbControlObject *ret;
202 PyObject *py_ldb;
203 TALLOC_CTX *mem_ctx;
204 struct ldb_context *ldb_ctx;
206 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "O!s",
207 discard_const_p(char *, kwnames),
208 &PyLdb, &py_ldb, &data))
209 return NULL;
211 mem_ctx = talloc_new(NULL);
212 if (mem_ctx == NULL) {
213 PyErr_NoMemory();
214 return NULL;
217 ldb_ctx = pyldb_Ldb_AsLdbContext(py_ldb);
218 parsed_controls = ldb_parse_control_from_string(ldb_ctx, mem_ctx, data);
220 if (!parsed_controls) {
221 talloc_free(mem_ctx);
222 PyErr_SetString(PyExc_ValueError, "unable to parse control string");
223 return NULL;
226 ret = PyObject_New(PyLdbControlObject, type);
227 if (ret == NULL) {
228 PyErr_NoMemory();
229 talloc_free(mem_ctx);
230 return NULL;
233 ret->mem_ctx = mem_ctx;
235 ret->data = talloc_move(mem_ctx, &parsed_controls);
236 if (ret->data == NULL) {
237 Py_DECREF(ret);
238 PyErr_NoMemory();
239 talloc_free(mem_ctx);
240 return NULL;
243 return (PyObject *)ret;
246 static PyGetSetDef py_ldb_control_getset[] = {
247 { discard_const_p(char, "oid"), (getter)py_ldb_control_get_oid, NULL, NULL },
248 { discard_const_p(char, "critical"), (getter)py_ldb_control_get_critical, (setter)py_ldb_control_set_critical, NULL },
249 { NULL }
252 static PyTypeObject PyLdbControl = {
253 .tp_name = "ldb.control",
254 .tp_dealloc = (destructor)py_ldb_control_dealloc,
255 .tp_getattro = PyObject_GenericGetAttr,
256 .tp_basicsize = sizeof(PyLdbControlObject),
257 .tp_getset = py_ldb_control_getset,
258 .tp_doc = "LDB control.",
259 .tp_str = (reprfunc)py_ldb_control_str,
260 .tp_new = py_ldb_control_new,
261 .tp_flags = Py_TPFLAGS_DEFAULT|Py_TPFLAGS_BASETYPE,
264 static void PyErr_SetLdbError(PyObject *error, int ret, struct ldb_context *ldb_ctx)
266 if (ret == LDB_ERR_PYTHON_EXCEPTION)
267 return; /* Python exception should already be set, just keep that */
269 PyErr_SetObject(error,
270 Py_BuildValue(discard_const_p(char, "(i,s)"), ret,
271 ldb_ctx == NULL?ldb_strerror(ret):ldb_errstring(ldb_ctx)));
274 static PyObject *PyObject_FromLdbValue(const struct ldb_val *val)
276 return PyBytes_FromStringAndSize((const char *)val->data, val->length);
279 static PyObject *PyStr_FromLdbValue(const struct ldb_val *val)
281 return PyStr_FromStringAndSize((const char *)val->data, val->length);
285 * Create a Python object from a ldb_result.
287 * @param result LDB result to convert
288 * @return Python object with converted result (a list object)
290 static PyObject *PyLdbControl_FromControl(struct ldb_control *control)
292 TALLOC_CTX *ctl_ctx = talloc_new(NULL);
293 PyLdbControlObject *ctrl;
294 if (ctl_ctx == NULL) {
295 PyErr_NoMemory();
296 return NULL;
299 ctrl = (PyLdbControlObject *)PyLdbControl.tp_alloc(&PyLdbControl, 0);
300 if (ctrl == NULL) {
301 talloc_free(ctl_ctx);
302 PyErr_NoMemory();
303 return NULL;
305 ctrl->mem_ctx = ctl_ctx;
306 ctrl->data = talloc_steal(ctrl->mem_ctx, control);
307 if (ctrl->data == NULL) {
308 Py_DECREF(ctrl);
309 PyErr_NoMemory();
310 return NULL;
312 return (PyObject*) ctrl;
316 * Create a Python object from a ldb_result.
318 * @param result LDB result to convert
319 * @return Python object with converted result (a list object)
321 static PyObject *PyLdbResult_FromResult(struct ldb_result *result)
323 PyLdbResultObject *ret;
324 PyObject *list, *controls, *referals;
325 Py_ssize_t i;
327 if (result == NULL) {
328 Py_RETURN_NONE;
331 ret = (PyLdbResultObject *)PyLdbResult.tp_alloc(&PyLdbResult, 0);
332 if (ret == NULL) {
333 PyErr_NoMemory();
334 return NULL;
337 list = PyList_New(result->count);
338 if (list == NULL) {
339 PyErr_NoMemory();
340 Py_DECREF(ret);
341 return NULL;
344 for (i = 0; i < result->count; i++) {
345 PyList_SetItem(list, i, PyLdbMessage_FromMessage(result->msgs[i]));
348 ret->mem_ctx = talloc_new(NULL);
349 if (ret->mem_ctx == NULL) {
350 Py_DECREF(list);
351 Py_DECREF(ret);
352 PyErr_NoMemory();
353 return NULL;
356 ret->msgs = list;
358 if (result->controls) {
359 i = 0;
360 while (result->controls[i]) {
361 i++;
363 controls = PyList_New(i);
364 if (controls == NULL) {
365 Py_DECREF(ret);
366 PyErr_NoMemory();
367 return NULL;
369 for (i=0; result->controls[i]; i++) {
370 PyObject *ctrl = (PyObject*) PyLdbControl_FromControl(result->controls[i]);
371 if (ctrl == NULL) {
372 Py_DECREF(ret);
373 Py_DECREF(controls);
374 PyErr_NoMemory();
375 return NULL;
377 PyList_SetItem(controls, i, ctrl);
379 } else {
381 * No controls so we keep an empty list
383 controls = PyList_New(0);
384 if (controls == NULL) {
385 Py_DECREF(ret);
386 PyErr_NoMemory();
387 return NULL;
391 ret->controls = controls;
393 i = 0;
395 while (result->refs && result->refs[i]) {
396 i++;
399 referals = PyList_New(i);
400 if (referals == NULL) {
401 Py_DECREF(ret);
402 PyErr_NoMemory();
403 return NULL;
406 for (i = 0;result->refs && result->refs[i]; i++) {
407 PyList_SetItem(referals, i, PyStr_FromString(result->refs[i]));
409 ret->referals = referals;
410 return (PyObject *)ret;
414 * Create a LDB Result from a Python object.
415 * If conversion fails, NULL will be returned and a Python exception set.
417 * Note: the result object only includes the messages at the moment; extended
418 * result, controls and referrals are ignored.
420 * @param mem_ctx Memory context in which to allocate the LDB Result
421 * @param obj Python object to convert
422 * @return a ldb_result, or NULL if the conversion failed
424 static struct ldb_result *PyLdbResult_AsResult(TALLOC_CTX *mem_ctx,
425 PyObject *obj)
427 struct ldb_result *res;
428 Py_ssize_t i;
430 if (obj == Py_None)
431 return NULL;
433 res = talloc_zero(mem_ctx, struct ldb_result);
434 res->count = PyList_Size(obj);
435 res->msgs = talloc_array(res, struct ldb_message *, res->count);
436 for (i = 0; i < res->count; i++) {
437 PyObject *item = PyList_GetItem(obj, i);
438 res->msgs[i] = pyldb_Message_AsMessage(item);
440 return res;
443 static PyObject *py_ldb_dn_validate(PyLdbDnObject *self)
445 return PyBool_FromLong(ldb_dn_validate(self->dn));
448 static PyObject *py_ldb_dn_is_valid(PyLdbDnObject *self)
450 return PyBool_FromLong(ldb_dn_is_valid(self->dn));
453 static PyObject *py_ldb_dn_is_special(PyLdbDnObject *self)
455 return PyBool_FromLong(ldb_dn_is_special(self->dn));
458 static PyObject *py_ldb_dn_is_null(PyLdbDnObject *self)
460 return PyBool_FromLong(ldb_dn_is_null(self->dn));
463 static PyObject *py_ldb_dn_get_casefold(PyLdbDnObject *self)
465 return PyStr_FromString(ldb_dn_get_casefold(self->dn));
468 static PyObject *py_ldb_dn_get_linearized(PyLdbDnObject *self)
470 return PyStr_FromString(ldb_dn_get_linearized(self->dn));
473 static PyObject *py_ldb_dn_canonical_str(PyLdbDnObject *self)
475 return PyStr_FromString(ldb_dn_canonical_string(self->dn, self->dn));
478 static PyObject *py_ldb_dn_canonical_ex_str(PyLdbDnObject *self)
480 return PyStr_FromString(ldb_dn_canonical_ex_string(self->dn, self->dn));
483 static PyObject *py_ldb_dn_extended_str(PyLdbDnObject *self, PyObject *args, PyObject *kwargs)
485 const char * const kwnames[] = { "mode", NULL };
486 int mode = 1;
487 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "|i",
488 discard_const_p(char *, kwnames),
489 &mode))
490 return NULL;
491 return PyStr_FromString(ldb_dn_get_extended_linearized(self->dn, self->dn, mode));
494 static PyObject *py_ldb_dn_get_extended_component(PyLdbDnObject *self, PyObject *args)
496 char *name;
497 const struct ldb_val *val;
499 if (!PyArg_ParseTuple(args, "s", &name))
500 return NULL;
501 val = ldb_dn_get_extended_component(self->dn, name);
502 if (val == NULL) {
503 Py_RETURN_NONE;
506 return PyBytes_FromStringAndSize((const char *)val->data, val->length);
509 static PyObject *py_ldb_dn_set_extended_component(PyLdbDnObject *self, PyObject *args)
511 char *name;
512 int err;
513 uint8_t *value = NULL;
514 Py_ssize_t size = 0;
516 if (!PyArg_ParseTuple(args, "sz#", &name, (char **)&value, &size))
517 return NULL;
519 if (value == NULL) {
520 err = ldb_dn_set_extended_component(self->dn, name, NULL);
521 } else {
522 struct ldb_val val;
523 val.data = (uint8_t *)value;
524 val.length = size;
525 err = ldb_dn_set_extended_component(self->dn, name, &val);
528 if (err != LDB_SUCCESS) {
529 PyErr_SetString(PyExc_TypeError, "Failed to set extended component");
530 return NULL;
533 Py_RETURN_NONE;
536 static PyObject *py_ldb_dn_repr(PyLdbDnObject *self)
538 PyObject *str = PyStr_FromString(ldb_dn_get_linearized(self->dn));
539 PyObject *repr, *result;
540 if (str == NULL)
541 return NULL;
542 repr = PyObject_Repr(str);
543 if (repr == NULL) {
544 Py_DECREF(str);
545 return NULL;
547 result = PyStr_FromFormat("Dn(%s)", PyStr_AsUTF8(repr));
548 Py_DECREF(str);
549 Py_DECREF(repr);
550 return result;
553 static PyObject *py_ldb_dn_check_special(PyLdbDnObject *self, PyObject *args)
555 char *name;
557 if (!PyArg_ParseTuple(args, "s", &name))
558 return NULL;
560 return PyBool_FromLong(ldb_dn_check_special(self->dn, name));
563 static PyObject *py_ldb_dn_richcmp(PyObject *dn1, PyObject *dn2, int op)
565 int ret;
566 if (!pyldb_Dn_Check(dn2)) {
567 Py_INCREF(Py_NotImplemented);
568 return Py_NotImplemented;
570 ret = ldb_dn_compare(pyldb_Dn_AsDn(dn1), pyldb_Dn_AsDn(dn2));
571 return richcmp(ret, op);
574 static PyObject *py_ldb_dn_get_parent(PyLdbDnObject *self)
576 struct ldb_dn *dn = pyldb_Dn_AsDn((PyObject *)self);
577 struct ldb_dn *parent;
578 PyLdbDnObject *py_ret;
579 TALLOC_CTX *mem_ctx = talloc_new(NULL);
581 parent = ldb_dn_get_parent(mem_ctx, dn);
582 if (parent == NULL) {
583 talloc_free(mem_ctx);
584 Py_RETURN_NONE;
587 py_ret = (PyLdbDnObject *)PyLdbDn.tp_alloc(&PyLdbDn, 0);
588 if (py_ret == NULL) {
589 PyErr_NoMemory();
590 talloc_free(mem_ctx);
591 return NULL;
593 py_ret->mem_ctx = mem_ctx;
594 py_ret->dn = parent;
595 return (PyObject *)py_ret;
598 static PyObject *py_ldb_dn_add_child(PyLdbDnObject *self, PyObject *args)
600 PyObject *py_other;
601 struct ldb_dn *dn, *other;
602 if (!PyArg_ParseTuple(args, "O", &py_other))
603 return NULL;
605 dn = pyldb_Dn_AsDn((PyObject *)self);
607 if (!pyldb_Object_AsDn(NULL, py_other, ldb_dn_get_ldb_context(dn), &other))
608 return NULL;
610 return PyBool_FromLong(ldb_dn_add_child(dn, other));
613 static PyObject *py_ldb_dn_add_base(PyLdbDnObject *self, PyObject *args)
615 PyObject *py_other;
616 struct ldb_dn *other, *dn;
617 if (!PyArg_ParseTuple(args, "O", &py_other))
618 return NULL;
620 dn = pyldb_Dn_AsDn((PyObject *)self);
622 if (!pyldb_Object_AsDn(NULL, py_other, ldb_dn_get_ldb_context(dn), &other))
623 return NULL;
625 return PyBool_FromLong(ldb_dn_add_base(dn, other));
628 static PyObject *py_ldb_dn_remove_base_components(PyLdbDnObject *self, PyObject *args)
630 struct ldb_dn *dn;
631 int i;
632 if (!PyArg_ParseTuple(args, "i", &i))
633 return NULL;
635 dn = pyldb_Dn_AsDn((PyObject *)self);
637 return PyBool_FromLong(ldb_dn_remove_base_components(dn, i));
640 static PyObject *py_ldb_dn_is_child_of(PyLdbDnObject *self, PyObject *args)
642 PyObject *py_base;
643 struct ldb_dn *dn, *base;
644 if (!PyArg_ParseTuple(args, "O", &py_base))
645 return NULL;
647 dn = pyldb_Dn_AsDn((PyObject *)self);
649 if (!pyldb_Object_AsDn(NULL, py_base, ldb_dn_get_ldb_context(dn), &base))
650 return NULL;
652 return PyBool_FromLong(ldb_dn_compare_base(base, dn) == 0);
655 static PyObject *py_ldb_dn_get_component_name(PyLdbDnObject *self, PyObject *args)
657 struct ldb_dn *dn;
658 const char *name;
659 unsigned int num = 0;
661 if (!PyArg_ParseTuple(args, "I", &num))
662 return NULL;
664 dn = pyldb_Dn_AsDn((PyObject *)self);
666 name = ldb_dn_get_component_name(dn, num);
667 if (name == NULL) {
668 Py_RETURN_NONE;
671 return PyStr_FromString(name);
674 static PyObject *py_ldb_dn_get_component_value(PyLdbDnObject *self, PyObject *args)
676 struct ldb_dn *dn;
677 const struct ldb_val *val;
678 unsigned int num = 0;
680 if (!PyArg_ParseTuple(args, "I", &num))
681 return NULL;
683 dn = pyldb_Dn_AsDn((PyObject *)self);
685 val = ldb_dn_get_component_val(dn, num);
686 if (val == NULL) {
687 Py_RETURN_NONE;
690 return PyStr_FromLdbValue(val);
693 static PyObject *py_ldb_dn_set_component(PyLdbDnObject *self, PyObject *args)
695 unsigned int num = 0;
696 char *name = NULL, *value = NULL;
697 struct ldb_val val = { NULL, };
698 int err;
699 Py_ssize_t size = 0;
701 if (!PyArg_ParseTuple(args, "Iss#", &num, &name, &value, &size))
702 return NULL;
704 val.data = (unsigned char*) value;
705 val.length = size;
707 err = ldb_dn_set_component(self->dn, num, name, val);
708 if (err != LDB_SUCCESS) {
709 PyErr_SetString(PyExc_TypeError, "Failed to set component");
710 return NULL;
713 Py_RETURN_NONE;
716 static PyObject *py_ldb_dn_get_rdn_name(PyLdbDnObject *self)
718 struct ldb_dn *dn;
719 const char *name;
721 dn = pyldb_Dn_AsDn((PyObject *)self);
723 name = ldb_dn_get_rdn_name(dn);
724 if (name == NULL) {
725 Py_RETURN_NONE;
728 return PyStr_FromString(name);
731 static PyObject *py_ldb_dn_get_rdn_value(PyLdbDnObject *self)
733 struct ldb_dn *dn;
734 const struct ldb_val *val;
736 dn = pyldb_Dn_AsDn((PyObject *)self);
738 val = ldb_dn_get_rdn_val(dn);
739 if (val == NULL) {
740 Py_RETURN_NONE;
743 return PyStr_FromLdbValue(val);
746 static PyMethodDef py_ldb_dn_methods[] = {
747 { "validate", (PyCFunction)py_ldb_dn_validate, METH_NOARGS,
748 "S.validate() -> bool\n"
749 "Validate DN is correct." },
750 { "is_valid", (PyCFunction)py_ldb_dn_is_valid, METH_NOARGS,
751 "S.is_valid() -> bool\n" },
752 { "is_special", (PyCFunction)py_ldb_dn_is_special, METH_NOARGS,
753 "S.is_special() -> bool\n"
754 "Check whether this is a special LDB DN." },
755 { "is_null", (PyCFunction)py_ldb_dn_is_null, METH_NOARGS,
756 "Check whether this is a null DN." },
757 { "get_casefold", (PyCFunction)py_ldb_dn_get_casefold, METH_NOARGS,
758 NULL },
759 { "get_linearized", (PyCFunction)py_ldb_dn_get_linearized, METH_NOARGS,
760 NULL },
761 { "canonical_str", (PyCFunction)py_ldb_dn_canonical_str, METH_NOARGS,
762 "S.canonical_str() -> string\n"
763 "Canonical version of this DN (like a posix path)." },
764 { "is_child_of", (PyCFunction)py_ldb_dn_is_child_of, METH_VARARGS,
765 "S.is_child_of(basedn) -> int\nReturns True if this DN is a child of basedn\n"},
766 { "canonical_ex_str", (PyCFunction)py_ldb_dn_canonical_ex_str, METH_NOARGS,
767 "S.canonical_ex_str() -> string\n"
768 "Canonical version of this DN (like a posix path, with terminating newline)." },
769 { "extended_str", (PyCFunction)py_ldb_dn_extended_str, METH_VARARGS | METH_KEYWORDS,
770 "S.extended_str(mode=1) -> string\n"
771 "Extended version of this DN" },
772 { "parent", (PyCFunction)py_ldb_dn_get_parent, METH_NOARGS,
773 "S.parent() -> dn\n"
774 "Get the parent for this DN." },
775 { "add_child", (PyCFunction)py_ldb_dn_add_child, METH_VARARGS,
776 "S.add_child(dn) -> None\n"
777 "Add a child DN to this DN." },
778 { "add_base", (PyCFunction)py_ldb_dn_add_base, METH_VARARGS,
779 "S.add_base(dn) -> None\n"
780 "Add a base DN to this DN." },
781 { "remove_base_components", (PyCFunction)py_ldb_dn_remove_base_components, METH_VARARGS,
782 "S.remove_base_components(int) -> bool\n"
783 "Remove a number of DN components from the base of this DN." },
784 { "check_special", (PyCFunction)py_ldb_dn_check_special, METH_VARARGS,
785 "S.check_special(name) -> bool\n\n"
786 "Check if name is a special DN name"},
787 { "get_extended_component", (PyCFunction)py_ldb_dn_get_extended_component, METH_VARARGS,
788 "S.get_extended_component(name) -> string\n\n"
789 "returns a DN extended component as a binary string"},
790 { "set_extended_component", (PyCFunction)py_ldb_dn_set_extended_component, METH_VARARGS,
791 "S.set_extended_component(name, value) -> None\n\n"
792 "set a DN extended component as a binary string"},
793 { "get_component_name", (PyCFunction)py_ldb_dn_get_component_name, METH_VARARGS,
794 "S.get_component_name(num) -> string\n"
795 "get the attribute name of the specified component" },
796 { "get_component_value", (PyCFunction)py_ldb_dn_get_component_value, METH_VARARGS,
797 "S.get_component_value(num) -> string\n"
798 "get the attribute value of the specified component as a binary string" },
799 { "set_component", (PyCFunction)py_ldb_dn_set_component, METH_VARARGS,
800 "S.get_component_value(num, name, value) -> None\n"
801 "set the attribute name and value of the specified component" },
802 { "get_rdn_name", (PyCFunction)py_ldb_dn_get_rdn_name, METH_NOARGS,
803 "S.get_rdn_name() -> string\n"
804 "get the RDN attribute name" },
805 { "get_rdn_value", (PyCFunction)py_ldb_dn_get_rdn_value, METH_NOARGS,
806 "S.get_rdn_value() -> string\n"
807 "get the RDN attribute value as a binary string" },
808 { NULL }
811 static Py_ssize_t py_ldb_dn_len(PyLdbDnObject *self)
813 return ldb_dn_get_comp_num(pyldb_Dn_AsDn((PyObject *)self));
817 copy a DN as a python object
819 static PyObject *py_ldb_dn_copy(struct ldb_dn *dn)
821 PyLdbDnObject *py_ret;
823 py_ret = (PyLdbDnObject *)PyLdbDn.tp_alloc(&PyLdbDn, 0);
824 if (py_ret == NULL) {
825 PyErr_NoMemory();
826 return NULL;
828 py_ret->mem_ctx = talloc_new(NULL);
829 py_ret->dn = ldb_dn_copy(py_ret->mem_ctx, dn);
830 return (PyObject *)py_ret;
833 static PyObject *py_ldb_dn_concat(PyLdbDnObject *self, PyObject *py_other)
835 struct ldb_dn *dn = pyldb_Dn_AsDn((PyObject *)self),
836 *other;
837 PyLdbDnObject *py_ret;
839 if (!pyldb_Object_AsDn(NULL, py_other, NULL, &other))
840 return NULL;
842 py_ret = (PyLdbDnObject *)PyLdbDn.tp_alloc(&PyLdbDn, 0);
843 if (py_ret == NULL) {
844 PyErr_NoMemory();
845 return NULL;
847 py_ret->mem_ctx = talloc_new(NULL);
848 py_ret->dn = ldb_dn_copy(py_ret->mem_ctx, dn);
849 ldb_dn_add_base(py_ret->dn, other);
850 return (PyObject *)py_ret;
853 static PySequenceMethods py_ldb_dn_seq = {
854 .sq_length = (lenfunc)py_ldb_dn_len,
855 .sq_concat = (binaryfunc)py_ldb_dn_concat,
858 static PyObject *py_ldb_dn_new(PyTypeObject *type, PyObject *args, PyObject *kwargs)
860 struct ldb_dn *ret;
861 char *str;
862 PyObject *py_ldb;
863 struct ldb_context *ldb_ctx;
864 TALLOC_CTX *mem_ctx;
865 PyLdbDnObject *py_ret;
866 const char * const kwnames[] = { "ldb", "dn", NULL };
868 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "Os",
869 discard_const_p(char *, kwnames),
870 &py_ldb, &str))
871 return NULL;
873 if (!PyLdb_Check(py_ldb)) {
874 PyErr_SetString(PyExc_TypeError, "Expected Ldb");
875 return NULL;
878 ldb_ctx = pyldb_Ldb_AsLdbContext(py_ldb);
880 mem_ctx = talloc_new(NULL);
881 if (mem_ctx == NULL) {
882 PyErr_NoMemory();
883 return NULL;
886 ret = ldb_dn_new(mem_ctx, ldb_ctx, str);
887 if (!ldb_dn_validate(ret)) {
888 talloc_free(mem_ctx);
889 PyErr_SetString(PyExc_ValueError, "unable to parse dn string");
890 return NULL;
893 py_ret = (PyLdbDnObject *)type->tp_alloc(type, 0);
894 if (ret == NULL) {
895 talloc_free(mem_ctx);
896 PyErr_NoMemory();
897 return NULL;
899 py_ret->mem_ctx = mem_ctx;
900 py_ret->dn = ret;
901 return (PyObject *)py_ret;
904 static void py_ldb_dn_dealloc(PyLdbDnObject *self)
906 talloc_free(self->mem_ctx);
907 PyObject_Del(self);
910 static PyTypeObject PyLdbDn = {
911 .tp_name = "ldb.Dn",
912 .tp_methods = py_ldb_dn_methods,
913 .tp_str = (reprfunc)py_ldb_dn_get_linearized,
914 .tp_repr = (reprfunc)py_ldb_dn_repr,
915 .tp_richcompare = (richcmpfunc)py_ldb_dn_richcmp,
916 .tp_as_sequence = &py_ldb_dn_seq,
917 .tp_doc = "A LDB distinguished name.",
918 .tp_new = py_ldb_dn_new,
919 .tp_dealloc = (destructor)py_ldb_dn_dealloc,
920 .tp_basicsize = sizeof(PyLdbDnObject),
921 .tp_flags = Py_TPFLAGS_DEFAULT,
924 /* Debug */
925 static void py_ldb_debug(void *context, enum ldb_debug_level level, const char *fmt, va_list ap) PRINTF_ATTRIBUTE(3, 0);
926 static void py_ldb_debug(void *context, enum ldb_debug_level level, const char *fmt, va_list ap)
928 PyObject *fn = (PyObject *)context;
929 PyObject_CallFunction(fn, discard_const_p(char, "(i,O)"), level, PyStr_FromFormatV(fmt, ap));
932 static PyObject *py_ldb_debug_func;
934 static PyObject *py_ldb_set_debug(PyObject *self, PyObject *args)
936 PyObject *cb;
937 struct ldb_context *ldb_ctx;
939 if (!PyArg_ParseTuple(args, "O", &cb))
940 return NULL;
942 if (py_ldb_debug_func != NULL) {
943 Py_DECREF(py_ldb_debug_func);
946 Py_INCREF(cb);
947 /* FIXME: DECREF cb when exiting program */
948 py_ldb_debug_func = cb;
949 ldb_ctx = pyldb_Ldb_AsLdbContext(self);
950 PyErr_LDB_ERROR_IS_ERR_RAISE(PyExc_LdbError,
951 ldb_set_debug(ldb_ctx, py_ldb_debug, cb),
952 ldb_ctx);
954 Py_RETURN_NONE;
957 static PyObject *py_ldb_set_create_perms(PyTypeObject *self, PyObject *args)
959 unsigned int perms;
960 if (!PyArg_ParseTuple(args, "I", &perms))
961 return NULL;
963 ldb_set_create_perms(pyldb_Ldb_AsLdbContext(self), perms);
965 Py_RETURN_NONE;
968 static PyObject *py_ldb_set_modules_dir(PyTypeObject *self, PyObject *args)
970 char *modules_dir;
971 if (!PyArg_ParseTuple(args, "s", &modules_dir))
972 return NULL;
974 ldb_set_modules_dir(pyldb_Ldb_AsLdbContext(self), modules_dir);
976 Py_RETURN_NONE;
979 static PyObject *py_ldb_transaction_start(PyLdbObject *self)
981 struct ldb_context *ldb_ctx = pyldb_Ldb_AsLdbContext(self);
982 int ldb_err;
983 ldb_err = ldb_transaction_start(ldb_ctx);
984 PyErr_LDB_ERROR_IS_ERR_RAISE(PyExc_LdbError, ldb_err, ldb_ctx);
985 Py_RETURN_NONE;
988 static PyObject *py_ldb_transaction_commit(PyLdbObject *self)
990 struct ldb_context *ldb_ctx = pyldb_Ldb_AsLdbContext(self);
991 int ldb_err;
992 ldb_err = ldb_transaction_commit(ldb_ctx);
993 PyErr_LDB_ERROR_IS_ERR_RAISE(PyExc_LdbError, ldb_err, ldb_ctx);
994 Py_RETURN_NONE;
997 static PyObject *py_ldb_transaction_prepare_commit(PyLdbObject *self)
999 struct ldb_context *ldb_ctx = pyldb_Ldb_AsLdbContext(self);
1000 int ldb_err;
1001 ldb_err = ldb_transaction_prepare_commit(ldb_ctx);
1002 PyErr_LDB_ERROR_IS_ERR_RAISE(PyExc_LdbError, ldb_err, ldb_ctx);
1003 Py_RETURN_NONE;
1006 static PyObject *py_ldb_transaction_cancel(PyLdbObject *self)
1008 struct ldb_context *ldb_ctx = pyldb_Ldb_AsLdbContext(self);
1009 int ldb_err;
1010 ldb_err = ldb_transaction_cancel(ldb_ctx);
1011 PyErr_LDB_ERROR_IS_ERR_RAISE(PyExc_LdbError, ldb_err, ldb_ctx);
1012 Py_RETURN_NONE;
1015 static PyObject *py_ldb_setup_wellknown_attributes(PyLdbObject *self)
1017 struct ldb_context *ldb_ctx = pyldb_Ldb_AsLdbContext(self);
1018 int ldb_err;
1019 ldb_err = ldb_setup_wellknown_attributes(ldb_ctx);
1020 PyErr_LDB_ERROR_IS_ERR_RAISE(PyExc_LdbError, ldb_err, ldb_ctx);
1021 Py_RETURN_NONE;
1024 static PyObject *py_ldb_repr(PyLdbObject *self)
1026 return PyStr_FromString("<ldb connection>");
1029 static PyObject *py_ldb_get_root_basedn(PyLdbObject *self)
1031 struct ldb_dn *dn = ldb_get_root_basedn(pyldb_Ldb_AsLdbContext(self));
1032 if (dn == NULL)
1033 Py_RETURN_NONE;
1034 return py_ldb_dn_copy(dn);
1038 static PyObject *py_ldb_get_schema_basedn(PyLdbObject *self)
1040 struct ldb_dn *dn = ldb_get_schema_basedn(pyldb_Ldb_AsLdbContext(self));
1041 if (dn == NULL)
1042 Py_RETURN_NONE;
1043 return py_ldb_dn_copy(dn);
1046 static PyObject *py_ldb_get_config_basedn(PyLdbObject *self)
1048 struct ldb_dn *dn = ldb_get_config_basedn(pyldb_Ldb_AsLdbContext(self));
1049 if (dn == NULL)
1050 Py_RETURN_NONE;
1051 return py_ldb_dn_copy(dn);
1054 static PyObject *py_ldb_get_default_basedn(PyLdbObject *self)
1056 struct ldb_dn *dn = ldb_get_default_basedn(pyldb_Ldb_AsLdbContext(self));
1057 if (dn == NULL)
1058 Py_RETURN_NONE;
1059 return py_ldb_dn_copy(dn);
1062 static const char **PyList_AsStrList(TALLOC_CTX *mem_ctx, PyObject *list,
1063 const char *paramname)
1065 const char **ret;
1066 Py_ssize_t i;
1067 if (!PyList_Check(list)) {
1068 PyErr_Format(PyExc_TypeError, "%s is not a list", paramname);
1069 return NULL;
1071 ret = talloc_array(NULL, const char *, PyList_Size(list)+1);
1072 if (ret == NULL) {
1073 PyErr_NoMemory();
1074 return NULL;
1077 for (i = 0; i < PyList_Size(list); i++) {
1078 const char *str = NULL;
1079 Py_ssize_t size;
1080 PyObject *item = PyList_GetItem(list, i);
1081 if (!(PyStr_Check(item) || PyUnicode_Check(item))) {
1082 PyErr_Format(PyExc_TypeError, "%s should be strings", paramname);
1083 talloc_free(ret);
1084 return NULL;
1086 str = PyStr_AsUTF8AndSize(item, &size);
1087 if (str == NULL) {
1088 talloc_free(ret);
1089 return NULL;
1091 ret[i] = talloc_strndup(ret, str, size);
1093 ret[i] = NULL;
1094 return ret;
1097 static int py_ldb_init(PyLdbObject *self, PyObject *args, PyObject *kwargs)
1099 const char * const kwnames[] = { "url", "flags", "options", NULL };
1100 char *url = NULL;
1101 PyObject *py_options = Py_None;
1102 const char **options;
1103 unsigned int flags = 0;
1104 int ret;
1105 struct ldb_context *ldb;
1107 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "|zIO:Ldb.__init__",
1108 discard_const_p(char *, kwnames),
1109 &url, &flags, &py_options))
1110 return -1;
1112 ldb = pyldb_Ldb_AsLdbContext(self);
1114 if (py_options == Py_None) {
1115 options = NULL;
1116 } else {
1117 options = PyList_AsStrList(ldb, py_options, "options");
1118 if (options == NULL)
1119 return -1;
1122 if (url != NULL) {
1123 ret = ldb_connect(ldb, url, flags, options);
1124 if (ret != LDB_SUCCESS) {
1125 PyErr_SetLdbError(PyExc_LdbError, ret, ldb);
1126 return -1;
1130 talloc_free(options);
1131 return 0;
1134 static PyObject *py_ldb_new(PyTypeObject *type, PyObject *args, PyObject *kwargs)
1136 PyLdbObject *ret;
1137 struct ldb_context *ldb;
1138 ret = (PyLdbObject *)type->tp_alloc(type, 0);
1139 if (ret == NULL) {
1140 PyErr_NoMemory();
1141 return NULL;
1143 ret->mem_ctx = talloc_new(NULL);
1144 ldb = ldb_init(ret->mem_ctx, NULL);
1146 if (ldb == NULL) {
1147 PyErr_NoMemory();
1148 return NULL;
1151 ret->ldb_ctx = ldb;
1152 return (PyObject *)ret;
1155 static PyObject *py_ldb_connect(PyLdbObject *self, PyObject *args, PyObject *kwargs)
1157 char *url = NULL;
1158 unsigned int flags = 0;
1159 PyObject *py_options = Py_None;
1160 int ret;
1161 const char **options;
1162 const char * const kwnames[] = { "url", "flags", "options", NULL };
1163 struct ldb_context *ldb_ctx;
1165 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "|zIO",
1166 discard_const_p(char *, kwnames),
1167 &url, &flags, &py_options))
1168 return NULL;
1170 if (py_options == Py_None) {
1171 options = NULL;
1172 } else {
1173 options = PyList_AsStrList(NULL, py_options, "options");
1174 if (options == NULL)
1175 return NULL;
1178 ldb_ctx = pyldb_Ldb_AsLdbContext(self);
1179 ret = ldb_connect(ldb_ctx, url, flags, options);
1180 talloc_free(options);
1182 PyErr_LDB_ERROR_IS_ERR_RAISE(PyExc_LdbError, ret, ldb_ctx);
1184 Py_RETURN_NONE;
1187 static PyObject *py_ldb_modify(PyLdbObject *self, PyObject *args, PyObject *kwargs)
1189 PyObject *py_msg;
1190 PyObject *py_controls = Py_None;
1191 struct ldb_context *ldb_ctx;
1192 struct ldb_request *req;
1193 struct ldb_control **parsed_controls;
1194 struct ldb_message *msg;
1195 int ret;
1196 TALLOC_CTX *mem_ctx;
1197 bool validate=true;
1198 const char * const kwnames[] = { "message", "controls", "validate", NULL };
1200 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "O|Ob",
1201 discard_const_p(char *, kwnames),
1202 &py_msg, &py_controls, &validate))
1203 return NULL;
1205 mem_ctx = talloc_new(NULL);
1206 if (mem_ctx == NULL) {
1207 PyErr_NoMemory();
1208 return NULL;
1210 ldb_ctx = pyldb_Ldb_AsLdbContext(self);
1212 if (py_controls == Py_None) {
1213 parsed_controls = NULL;
1214 } else {
1215 const char **controls = PyList_AsStrList(mem_ctx, py_controls, "controls");
1216 if (controls == NULL) {
1217 talloc_free(mem_ctx);
1218 return NULL;
1220 parsed_controls = ldb_parse_control_strings(ldb_ctx, mem_ctx, controls);
1221 talloc_free(controls);
1224 if (!PyLdbMessage_Check(py_msg)) {
1225 PyErr_SetString(PyExc_TypeError, "Expected Ldb Message");
1226 talloc_free(mem_ctx);
1227 return NULL;
1229 msg = pyldb_Message_AsMessage(py_msg);
1231 if (validate) {
1232 ret = ldb_msg_sanity_check(ldb_ctx, msg);
1233 if (ret != LDB_SUCCESS) {
1234 PyErr_SetLdbError(PyExc_LdbError, ret, ldb_ctx);
1235 talloc_free(mem_ctx);
1236 return NULL;
1240 ret = ldb_build_mod_req(&req, ldb_ctx, mem_ctx, msg, parsed_controls,
1241 NULL, ldb_op_default_callback, NULL);
1242 if (ret != LDB_SUCCESS) {
1243 PyErr_SetString(PyExc_TypeError, "failed to build request");
1244 talloc_free(mem_ctx);
1245 return NULL;
1248 /* do request and autostart a transaction */
1249 /* Then let's LDB handle the message error in case of pb as they are meaningful */
1251 ret = ldb_transaction_start(ldb_ctx);
1252 if (ret != LDB_SUCCESS) {
1253 talloc_free(mem_ctx);
1254 PyErr_SetLdbError(PyExc_LdbError, ret, ldb_ctx);
1255 return NULL;
1258 ret = ldb_request(ldb_ctx, req);
1259 if (ret == LDB_SUCCESS) {
1260 ret = ldb_wait(req->handle, LDB_WAIT_ALL);
1263 if (ret == LDB_SUCCESS) {
1264 ret = ldb_transaction_commit(ldb_ctx);
1265 } else {
1266 ldb_transaction_cancel(ldb_ctx);
1269 talloc_free(mem_ctx);
1270 PyErr_LDB_ERROR_IS_ERR_RAISE(PyExc_LdbError, ret, ldb_ctx);
1272 Py_RETURN_NONE;
1277 * Obtain a ldb message from a Python Dictionary object.
1279 * @param mem_ctx Memory context
1280 * @param py_obj Python Dictionary object
1281 * @param ldb_ctx LDB context
1282 * @param mod_flags Flags to be set on every message element
1283 * @return ldb_message on success or NULL on failure
1285 static struct ldb_message *PyDict_AsMessage(TALLOC_CTX *mem_ctx,
1286 PyObject *py_obj,
1287 struct ldb_context *ldb_ctx,
1288 unsigned int mod_flags)
1290 struct ldb_message *msg;
1291 unsigned int msg_pos = 0;
1292 Py_ssize_t dict_pos = 0;
1293 PyObject *key, *value;
1294 struct ldb_message_element *msg_el;
1295 PyObject *dn_value = PyDict_GetItemString(py_obj, "dn");
1297 msg = ldb_msg_new(mem_ctx);
1298 if (msg == NULL) {
1299 PyErr_NoMemory();
1300 return NULL;
1302 msg->elements = talloc_zero_array(msg, struct ldb_message_element, PyDict_Size(py_obj));
1304 if (dn_value) {
1305 if (!pyldb_Object_AsDn(msg, dn_value, ldb_ctx, &msg->dn)) {
1306 PyErr_SetString(PyExc_TypeError, "unable to import dn object");
1307 return NULL;
1309 if (msg->dn == NULL) {
1310 PyErr_SetString(PyExc_TypeError, "dn set but not found");
1311 return NULL;
1313 } else {
1314 PyErr_SetString(PyExc_TypeError, "no dn set");
1315 return NULL;
1318 while (PyDict_Next(py_obj, &dict_pos, &key, &value)) {
1319 char *key_str = PyStr_AsUTF8(key);
1320 if (ldb_attr_cmp(key_str, "dn") != 0) {
1321 msg_el = PyObject_AsMessageElement(msg->elements, value,
1322 mod_flags, key_str);
1323 if (msg_el == NULL) {
1324 PyErr_Format(PyExc_TypeError, "unable to import element '%s'", key_str);
1325 return NULL;
1327 memcpy(&msg->elements[msg_pos], msg_el, sizeof(*msg_el));
1328 msg_pos++;
1332 msg->num_elements = msg_pos;
1334 return msg;
1337 static PyObject *py_ldb_add(PyLdbObject *self, PyObject *args, PyObject *kwargs)
1339 PyObject *py_obj;
1340 int ret;
1341 struct ldb_context *ldb_ctx;
1342 struct ldb_request *req;
1343 struct ldb_message *msg = NULL;
1344 PyObject *py_controls = Py_None;
1345 TALLOC_CTX *mem_ctx;
1346 struct ldb_control **parsed_controls;
1347 const char * const kwnames[] = { "message", "controls", NULL };
1349 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "O|O",
1350 discard_const_p(char *, kwnames),
1351 &py_obj, &py_controls))
1352 return NULL;
1354 mem_ctx = talloc_new(NULL);
1355 if (mem_ctx == NULL) {
1356 PyErr_NoMemory();
1357 return NULL;
1359 ldb_ctx = pyldb_Ldb_AsLdbContext(self);
1361 if (py_controls == Py_None) {
1362 parsed_controls = NULL;
1363 } else {
1364 const char **controls = PyList_AsStrList(mem_ctx, py_controls, "controls");
1365 if (controls == NULL) {
1366 talloc_free(mem_ctx);
1367 return NULL;
1369 parsed_controls = ldb_parse_control_strings(ldb_ctx, mem_ctx, controls);
1370 talloc_free(controls);
1373 if (PyLdbMessage_Check(py_obj)) {
1374 msg = pyldb_Message_AsMessage(py_obj);
1375 } else if (PyDict_Check(py_obj)) {
1376 msg = PyDict_AsMessage(mem_ctx, py_obj, ldb_ctx, LDB_FLAG_MOD_ADD);
1377 } else {
1378 PyErr_SetString(PyExc_TypeError,
1379 "Dictionary or LdbMessage object expected!");
1382 if (!msg) {
1383 /* we should have a PyErr already set */
1384 talloc_free(mem_ctx);
1385 return NULL;
1388 ret = ldb_msg_sanity_check(ldb_ctx, msg);
1389 if (ret != LDB_SUCCESS) {
1390 PyErr_SetLdbError(PyExc_LdbError, ret, ldb_ctx);
1391 talloc_free(mem_ctx);
1392 return NULL;
1395 ret = ldb_build_add_req(&req, ldb_ctx, mem_ctx, msg, parsed_controls,
1396 NULL, ldb_op_default_callback, NULL);
1397 if (ret != LDB_SUCCESS) {
1398 PyErr_SetString(PyExc_TypeError, "failed to build request");
1399 talloc_free(mem_ctx);
1400 return NULL;
1403 /* do request and autostart a transaction */
1404 /* Then let's LDB handle the message error in case of pb as they are meaningful */
1406 ret = ldb_transaction_start(ldb_ctx);
1407 if (ret != LDB_SUCCESS) {
1408 talloc_free(mem_ctx);
1409 PyErr_SetLdbError(PyExc_LdbError, ret, ldb_ctx);
1410 return NULL;
1413 ret = ldb_request(ldb_ctx, req);
1414 if (ret == LDB_SUCCESS) {
1415 ret = ldb_wait(req->handle, LDB_WAIT_ALL);
1418 if (ret == LDB_SUCCESS) {
1419 ret = ldb_transaction_commit(ldb_ctx);
1420 } else {
1421 ldb_transaction_cancel(ldb_ctx);
1424 talloc_free(mem_ctx);
1425 PyErr_LDB_ERROR_IS_ERR_RAISE(PyExc_LdbError, ret, ldb_ctx);
1427 Py_RETURN_NONE;
1430 static PyObject *py_ldb_delete(PyLdbObject *self, PyObject *args, PyObject *kwargs)
1432 PyObject *py_dn;
1433 struct ldb_dn *dn;
1434 int ret;
1435 struct ldb_context *ldb_ctx;
1436 struct ldb_request *req;
1437 PyObject *py_controls = Py_None;
1438 TALLOC_CTX *mem_ctx;
1439 struct ldb_control **parsed_controls;
1440 const char * const kwnames[] = { "dn", "controls", NULL };
1442 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "O|O",
1443 discard_const_p(char *, kwnames),
1444 &py_dn, &py_controls))
1445 return NULL;
1447 mem_ctx = talloc_new(NULL);
1448 if (mem_ctx == NULL) {
1449 PyErr_NoMemory();
1450 return NULL;
1452 ldb_ctx = pyldb_Ldb_AsLdbContext(self);
1454 if (py_controls == Py_None) {
1455 parsed_controls = NULL;
1456 } else {
1457 const char **controls = PyList_AsStrList(mem_ctx, py_controls, "controls");
1458 if (controls == NULL) {
1459 talloc_free(mem_ctx);
1460 return NULL;
1462 parsed_controls = ldb_parse_control_strings(ldb_ctx, mem_ctx, controls);
1463 talloc_free(controls);
1466 if (!pyldb_Object_AsDn(mem_ctx, py_dn, ldb_ctx, &dn)) {
1467 talloc_free(mem_ctx);
1468 return NULL;
1471 ret = ldb_build_del_req(&req, ldb_ctx, mem_ctx, dn, parsed_controls,
1472 NULL, ldb_op_default_callback, NULL);
1473 if (ret != LDB_SUCCESS) {
1474 PyErr_SetString(PyExc_TypeError, "failed to build request");
1475 talloc_free(mem_ctx);
1476 return NULL;
1479 /* do request and autostart a transaction */
1480 /* Then let's LDB handle the message error in case of pb as they are meaningful */
1482 ret = ldb_transaction_start(ldb_ctx);
1483 if (ret != LDB_SUCCESS) {
1484 talloc_free(mem_ctx);
1485 PyErr_SetLdbError(PyExc_LdbError, ret, ldb_ctx);
1486 return NULL;
1489 ret = ldb_request(ldb_ctx, req);
1490 if (ret == LDB_SUCCESS) {
1491 ret = ldb_wait(req->handle, LDB_WAIT_ALL);
1494 if (ret == LDB_SUCCESS) {
1495 ret = ldb_transaction_commit(ldb_ctx);
1496 } else {
1497 ldb_transaction_cancel(ldb_ctx);
1500 talloc_free(mem_ctx);
1501 PyErr_LDB_ERROR_IS_ERR_RAISE(PyExc_LdbError, ret, ldb_ctx);
1503 Py_RETURN_NONE;
1506 static PyObject *py_ldb_rename(PyLdbObject *self, PyObject *args, PyObject *kwargs)
1508 PyObject *py_dn1, *py_dn2;
1509 struct ldb_dn *dn1, *dn2;
1510 int ret;
1511 TALLOC_CTX *mem_ctx;
1512 PyObject *py_controls = Py_None;
1513 struct ldb_control **parsed_controls;
1514 struct ldb_context *ldb_ctx;
1515 struct ldb_request *req;
1516 const char * const kwnames[] = { "dn1", "dn2", "controls", NULL };
1518 ldb_ctx = pyldb_Ldb_AsLdbContext(self);
1520 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "OO|O",
1521 discard_const_p(char *, kwnames),
1522 &py_dn1, &py_dn2, &py_controls))
1523 return NULL;
1526 mem_ctx = talloc_new(NULL);
1527 if (mem_ctx == NULL) {
1528 PyErr_NoMemory();
1529 return NULL;
1532 if (py_controls == Py_None) {
1533 parsed_controls = NULL;
1534 } else {
1535 const char **controls = PyList_AsStrList(mem_ctx, py_controls, "controls");
1536 if (controls == NULL) {
1537 talloc_free(mem_ctx);
1538 return NULL;
1540 parsed_controls = ldb_parse_control_strings(ldb_ctx, mem_ctx, controls);
1541 talloc_free(controls);
1545 if (!pyldb_Object_AsDn(mem_ctx, py_dn1, ldb_ctx, &dn1)) {
1546 talloc_free(mem_ctx);
1547 return NULL;
1550 if (!pyldb_Object_AsDn(mem_ctx, py_dn2, ldb_ctx, &dn2)) {
1551 talloc_free(mem_ctx);
1552 return NULL;
1555 ret = ldb_build_rename_req(&req, ldb_ctx, mem_ctx, dn1, dn2, parsed_controls,
1556 NULL, ldb_op_default_callback, NULL);
1557 if (ret != LDB_SUCCESS) {
1558 PyErr_SetString(PyExc_TypeError, "failed to build request");
1559 talloc_free(mem_ctx);
1560 return NULL;
1563 /* do request and autostart a transaction */
1564 /* Then let's LDB handle the message error in case of pb as they are meaningful */
1566 ret = ldb_transaction_start(ldb_ctx);
1567 if (ret != LDB_SUCCESS) {
1568 talloc_free(mem_ctx);
1569 PyErr_SetLdbError(PyExc_LdbError, ret, ldb_ctx);
1570 return NULL;
1573 ret = ldb_request(ldb_ctx, req);
1574 if (ret == LDB_SUCCESS) {
1575 ret = ldb_wait(req->handle, LDB_WAIT_ALL);
1578 if (ret == LDB_SUCCESS) {
1579 ret = ldb_transaction_commit(ldb_ctx);
1580 } else {
1581 ldb_transaction_cancel(ldb_ctx);
1584 talloc_free(mem_ctx);
1585 PyErr_LDB_ERROR_IS_ERR_RAISE(PyExc_LdbError, ret, ldb_ctx);
1587 Py_RETURN_NONE;
1590 static PyObject *py_ldb_schema_attribute_remove(PyLdbObject *self, PyObject *args)
1592 char *name;
1593 if (!PyArg_ParseTuple(args, "s", &name))
1594 return NULL;
1596 ldb_schema_attribute_remove(pyldb_Ldb_AsLdbContext(self), name);
1598 Py_RETURN_NONE;
1601 static PyObject *py_ldb_schema_attribute_add(PyLdbObject *self, PyObject *args)
1603 char *attribute, *syntax;
1604 unsigned int flags;
1605 int ret;
1606 struct ldb_context *ldb_ctx;
1608 if (!PyArg_ParseTuple(args, "sIs", &attribute, &flags, &syntax))
1609 return NULL;
1611 ldb_ctx = pyldb_Ldb_AsLdbContext(self);
1612 ret = ldb_schema_attribute_add(ldb_ctx, attribute, flags, syntax);
1614 PyErr_LDB_ERROR_IS_ERR_RAISE(PyExc_LdbError, ret, ldb_ctx);
1616 Py_RETURN_NONE;
1619 static PyObject *ldb_ldif_to_pyobject(struct ldb_ldif *ldif)
1621 if (ldif == NULL) {
1622 Py_RETURN_NONE;
1623 } else {
1624 /* We don't want this attached to the 'ldb' any more */
1625 return Py_BuildValue(discard_const_p(char, "(iO)"),
1626 ldif->changetype,
1627 PyLdbMessage_FromMessage(ldif->msg));
1632 static PyObject *py_ldb_write_ldif(PyLdbObject *self, PyObject *args)
1634 int changetype;
1635 PyObject *py_msg;
1636 struct ldb_ldif ldif;
1637 PyObject *ret;
1638 char *string;
1639 TALLOC_CTX *mem_ctx;
1641 if (!PyArg_ParseTuple(args, "Oi", &py_msg, &changetype))
1642 return NULL;
1644 if (!PyLdbMessage_Check(py_msg)) {
1645 PyErr_SetString(PyExc_TypeError, "Expected Ldb Message for msg");
1646 return NULL;
1649 ldif.msg = pyldb_Message_AsMessage(py_msg);
1650 ldif.changetype = changetype;
1652 mem_ctx = talloc_new(NULL);
1654 string = ldb_ldif_write_string(pyldb_Ldb_AsLdbContext(self), mem_ctx, &ldif);
1655 if (!string) {
1656 PyErr_SetString(PyExc_KeyError, "Failed to generate LDIF");
1657 return NULL;
1660 ret = PyStr_FromString(string);
1662 talloc_free(mem_ctx);
1664 return ret;
1667 static PyObject *py_ldb_parse_ldif(PyLdbObject *self, PyObject *args)
1669 PyObject *list, *ret;
1670 struct ldb_ldif *ldif;
1671 const char *s;
1672 struct ldb_dn *last_dn = NULL;
1674 TALLOC_CTX *mem_ctx;
1676 if (!PyArg_ParseTuple(args, "s", &s))
1677 return NULL;
1679 mem_ctx = talloc_new(NULL);
1680 if (!mem_ctx) {
1681 Py_RETURN_NONE;
1684 list = PyList_New(0);
1685 while (s && *s != '\0') {
1686 ldif = ldb_ldif_read_string(self->ldb_ctx, &s);
1687 talloc_steal(mem_ctx, ldif);
1688 if (ldif) {
1689 PyList_Append(list, ldb_ldif_to_pyobject(ldif));
1690 last_dn = ldif->msg->dn;
1691 } else {
1692 const char *last_dn_str = NULL;
1693 const char *err_string = NULL;
1694 if (last_dn == NULL) {
1695 PyErr_SetString(PyExc_ValueError,
1696 "unable to parse LDIF "
1697 "string at first chunk");
1698 talloc_free(mem_ctx);
1699 return NULL;
1702 last_dn_str
1703 = ldb_dn_get_linearized(last_dn);
1705 err_string
1706 = talloc_asprintf(mem_ctx,
1707 "unable to parse ldif "
1708 "string AFTER %s",
1709 last_dn_str);
1711 PyErr_SetString(PyExc_ValueError,
1712 err_string);
1713 talloc_free(mem_ctx);
1714 return NULL;
1717 talloc_free(mem_ctx); /* The pyobject already has a reference to the things it needs */
1718 ret = PyObject_GetIter(list);
1719 Py_DECREF(list);
1720 return ret;
1723 static PyObject *py_ldb_msg_diff(PyLdbObject *self, PyObject *args)
1725 int ldb_ret;
1726 PyObject *py_msg_old;
1727 PyObject *py_msg_new;
1728 struct ldb_message *diff;
1729 struct ldb_context *ldb;
1730 PyObject *py_ret;
1732 if (!PyArg_ParseTuple(args, "OO", &py_msg_old, &py_msg_new))
1733 return NULL;
1735 if (!PyLdbMessage_Check(py_msg_old)) {
1736 PyErr_SetString(PyExc_TypeError, "Expected Ldb Message for old message");
1737 return NULL;
1740 if (!PyLdbMessage_Check(py_msg_new)) {
1741 PyErr_SetString(PyExc_TypeError, "Expected Ldb Message for new message");
1742 return NULL;
1745 ldb = pyldb_Ldb_AsLdbContext(self);
1746 ldb_ret = ldb_msg_difference(ldb, ldb,
1747 pyldb_Message_AsMessage(py_msg_old),
1748 pyldb_Message_AsMessage(py_msg_new),
1749 &diff);
1750 if (ldb_ret != LDB_SUCCESS) {
1751 PyErr_SetString(PyExc_RuntimeError, "Failed to generate the Ldb Message diff");
1752 return NULL;
1755 py_ret = PyLdbMessage_FromMessage(diff);
1757 talloc_unlink(ldb, diff);
1759 return py_ret;
1762 static PyObject *py_ldb_schema_format_value(PyLdbObject *self, PyObject *args)
1764 const struct ldb_schema_attribute *a;
1765 struct ldb_val old_val;
1766 struct ldb_val new_val;
1767 TALLOC_CTX *mem_ctx;
1768 PyObject *ret;
1769 char *element_name;
1770 PyObject *val;
1771 Py_ssize_t size;
1772 int result;
1774 if (!PyArg_ParseTuple(args, "sO", &element_name, &val))
1775 return NULL;
1777 result = PyBytes_AsStringAndSize(val, (char **)&old_val.data, &size);
1778 old_val.length = size;
1780 if (result != 0) {
1781 PyErr_SetString(PyExc_RuntimeError, "Failed to convert passed value to String");
1782 return NULL;
1785 a = ldb_schema_attribute_by_name(pyldb_Ldb_AsLdbContext(self), element_name);
1787 if (a == NULL) {
1788 Py_RETURN_NONE;
1791 mem_ctx = talloc_new(NULL);
1792 if (mem_ctx == NULL) {
1793 PyErr_NoMemory();
1794 return NULL;
1797 if (a->syntax->ldif_write_fn(pyldb_Ldb_AsLdbContext(self), mem_ctx, &old_val, &new_val) != 0) {
1798 talloc_free(mem_ctx);
1799 Py_RETURN_NONE;
1802 ret = PyBytes_FromStringAndSize((const char *)new_val.data, new_val.length);
1804 talloc_free(mem_ctx);
1806 return ret;
1809 static PyObject *py_ldb_search(PyLdbObject *self, PyObject *args, PyObject *kwargs)
1811 PyObject *py_base = Py_None;
1812 int scope = LDB_SCOPE_DEFAULT;
1813 char *expr = NULL;
1814 PyObject *py_attrs = Py_None;
1815 PyObject *py_controls = Py_None;
1816 const char * const kwnames[] = { "base", "scope", "expression", "attrs", "controls", NULL };
1817 int ret;
1818 struct ldb_result *res;
1819 struct ldb_request *req;
1820 const char **attrs;
1821 struct ldb_context *ldb_ctx;
1822 struct ldb_control **parsed_controls;
1823 struct ldb_dn *base;
1824 PyObject *py_ret;
1825 TALLOC_CTX *mem_ctx;
1827 /* type "int" rather than "enum" for "scope" is intentional */
1828 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "|OizOO",
1829 discard_const_p(char *, kwnames),
1830 &py_base, &scope, &expr, &py_attrs, &py_controls))
1831 return NULL;
1834 mem_ctx = talloc_new(NULL);
1835 if (mem_ctx == NULL) {
1836 PyErr_NoMemory();
1837 return NULL;
1839 ldb_ctx = pyldb_Ldb_AsLdbContext(self);
1841 if (py_attrs == Py_None) {
1842 attrs = NULL;
1843 } else {
1844 attrs = PyList_AsStrList(mem_ctx, py_attrs, "attrs");
1845 if (attrs == NULL) {
1846 talloc_free(mem_ctx);
1847 return NULL;
1851 if (py_base == Py_None) {
1852 base = ldb_get_default_basedn(ldb_ctx);
1853 } else {
1854 if (!pyldb_Object_AsDn(mem_ctx, py_base, ldb_ctx, &base)) {
1855 talloc_free(mem_ctx);
1856 return NULL;
1860 if (py_controls == Py_None) {
1861 parsed_controls = NULL;
1862 } else {
1863 const char **controls = PyList_AsStrList(mem_ctx, py_controls, "controls");
1864 if (controls == NULL) {
1865 talloc_free(mem_ctx);
1866 return NULL;
1868 parsed_controls = ldb_parse_control_strings(ldb_ctx, mem_ctx, controls);
1869 talloc_free(controls);
1872 res = talloc_zero(mem_ctx, struct ldb_result);
1873 if (res == NULL) {
1874 PyErr_NoMemory();
1875 talloc_free(mem_ctx);
1876 return NULL;
1879 ret = ldb_build_search_req(&req, ldb_ctx, mem_ctx,
1880 base,
1881 scope,
1882 expr,
1883 attrs,
1884 parsed_controls,
1885 res,
1886 ldb_search_default_callback,
1887 NULL);
1889 if (ret != LDB_SUCCESS) {
1890 talloc_free(mem_ctx);
1891 PyErr_SetLdbError(PyExc_LdbError, ret, ldb_ctx);
1892 return NULL;
1895 talloc_steal(req, attrs);
1897 ret = ldb_request(ldb_ctx, req);
1899 if (ret == LDB_SUCCESS) {
1900 ret = ldb_wait(req->handle, LDB_WAIT_ALL);
1903 if (ret != LDB_SUCCESS) {
1904 talloc_free(mem_ctx);
1905 PyErr_SetLdbError(PyExc_LdbError, ret, ldb_ctx);
1906 return NULL;
1909 py_ret = PyLdbResult_FromResult(res);
1911 talloc_free(mem_ctx);
1913 return py_ret;
1916 static int py_ldb_search_iterator_reply_destructor(struct py_ldb_search_iterator_reply *reply)
1918 if (reply->py_iter != NULL) {
1919 DLIST_REMOVE(reply->py_iter->state.next, reply);
1920 if (reply->py_iter->state.result == reply) {
1921 reply->py_iter->state.result = NULL;
1923 reply->py_iter = NULL;
1926 if (reply->obj != NULL) {
1927 Py_DECREF(reply->obj);
1928 reply->obj = NULL;
1931 return 0;
1934 static int py_ldb_search_iterator_callback(struct ldb_request *req,
1935 struct ldb_reply *ares)
1937 PyLdbSearchIteratorObject *py_iter = (PyLdbSearchIteratorObject *)req->context;
1938 struct ldb_result result = { .msgs = NULL };
1939 struct py_ldb_search_iterator_reply *reply = NULL;
1941 if (ares == NULL) {
1942 return ldb_request_done(req, LDB_ERR_OPERATIONS_ERROR);
1945 if (ares->error != LDB_SUCCESS) {
1946 int ret = ares->error;
1947 TALLOC_FREE(ares);
1948 return ldb_request_done(req, ret);
1951 reply = talloc_zero(py_iter->mem_ctx,
1952 struct py_ldb_search_iterator_reply);
1953 if (reply == NULL) {
1954 TALLOC_FREE(ares);
1955 return ldb_request_done(req, LDB_ERR_OPERATIONS_ERROR);
1957 reply->py_iter = py_iter;
1958 talloc_set_destructor(reply, py_ldb_search_iterator_reply_destructor);
1960 switch (ares->type) {
1961 case LDB_REPLY_ENTRY:
1962 reply->obj = PyLdbMessage_FromMessage(ares->message);
1963 if (reply->obj == NULL) {
1964 TALLOC_FREE(ares);
1965 return ldb_request_done(req, LDB_ERR_OPERATIONS_ERROR);
1967 DLIST_ADD_END(py_iter->state.next, reply);
1968 TALLOC_FREE(ares);
1969 return LDB_SUCCESS;
1971 case LDB_REPLY_REFERRAL:
1972 reply->obj = PyStr_FromString(ares->referral);
1973 if (reply->obj == NULL) {
1974 TALLOC_FREE(ares);
1975 return ldb_request_done(req, LDB_ERR_OPERATIONS_ERROR);
1977 DLIST_ADD_END(py_iter->state.next, reply);
1978 TALLOC_FREE(ares);
1979 return LDB_SUCCESS;
1981 case LDB_REPLY_DONE:
1982 result = (struct ldb_result) { .controls = ares->controls };
1983 reply->obj = PyLdbResult_FromResult(&result);
1984 if (reply->obj == NULL) {
1985 TALLOC_FREE(ares);
1986 return ldb_request_done(req, LDB_ERR_OPERATIONS_ERROR);
1988 py_iter->state.result = reply;
1989 TALLOC_FREE(ares);
1990 return ldb_request_done(req, LDB_SUCCESS);
1993 TALLOC_FREE(ares);
1994 return ldb_request_done(req, LDB_ERR_OPERATIONS_ERROR);
1997 static PyObject *py_ldb_search_iterator(PyLdbObject *self, PyObject *args, PyObject *kwargs)
1999 PyObject *py_base = Py_None;
2000 int scope = LDB_SCOPE_DEFAULT;
2001 int timeout = 0;
2002 char *expr = NULL;
2003 PyObject *py_attrs = Py_None;
2004 PyObject *py_controls = Py_None;
2005 const char * const kwnames[] = { "base", "scope", "expression", "attrs", "controls", "timeout", NULL };
2006 int ret;
2007 const char **attrs;
2008 struct ldb_context *ldb_ctx;
2009 struct ldb_control **parsed_controls;
2010 struct ldb_dn *base;
2011 PyLdbSearchIteratorObject *py_iter;
2013 /* type "int" rather than "enum" for "scope" is intentional */
2014 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "|OizOOi",
2015 discard_const_p(char *, kwnames),
2016 &py_base, &scope, &expr, &py_attrs, &py_controls, &timeout))
2017 return NULL;
2019 py_iter = (PyLdbSearchIteratorObject *)PyLdbSearchIterator.tp_alloc(&PyLdbSearchIterator, 0);
2020 if (py_iter == NULL) {
2021 PyErr_NoMemory();
2022 return NULL;
2024 py_iter->ldb = self;
2025 Py_INCREF(self);
2026 ZERO_STRUCT(py_iter->state);
2027 py_iter->mem_ctx = talloc_new(NULL);
2028 if (py_iter->mem_ctx == NULL) {
2029 Py_DECREF(py_iter);
2030 PyErr_NoMemory();
2031 return NULL;
2034 ldb_ctx = pyldb_Ldb_AsLdbContext(self);
2036 if (py_attrs == Py_None) {
2037 attrs = NULL;
2038 } else {
2039 attrs = PyList_AsStrList(py_iter->mem_ctx, py_attrs, "attrs");
2040 if (attrs == NULL) {
2041 Py_DECREF(py_iter);
2042 PyErr_NoMemory();
2043 return NULL;
2047 if (py_base == Py_None) {
2048 base = ldb_get_default_basedn(ldb_ctx);
2049 } else {
2050 if (!pyldb_Object_AsDn(py_iter->mem_ctx, py_base, ldb_ctx, &base)) {
2051 Py_DECREF(py_iter);
2052 PyErr_NoMemory();
2053 return NULL;
2057 if (py_controls == Py_None) {
2058 parsed_controls = NULL;
2059 } else {
2060 const char **controls = NULL;
2062 controls = PyList_AsStrList(py_iter->mem_ctx,
2063 py_controls, "controls");
2064 if (controls == NULL) {
2065 Py_DECREF(py_iter);
2066 PyErr_NoMemory();
2067 return NULL;
2070 parsed_controls = ldb_parse_control_strings(ldb_ctx,
2071 py_iter->mem_ctx,
2072 controls);
2073 if (controls[0] != NULL && parsed_controls == NULL) {
2074 Py_DECREF(py_iter);
2075 PyErr_NoMemory();
2076 return NULL;
2078 talloc_free(controls);
2081 ret = ldb_build_search_req(&py_iter->state.req,
2082 ldb_ctx,
2083 py_iter->mem_ctx,
2084 base,
2085 scope,
2086 expr,
2087 attrs,
2088 parsed_controls,
2089 py_iter,
2090 py_ldb_search_iterator_callback,
2091 NULL);
2092 if (ret != LDB_SUCCESS) {
2093 Py_DECREF(py_iter);
2094 PyErr_SetLdbError(PyExc_LdbError, ret, ldb_ctx);
2095 return NULL;
2098 ldb_set_timeout(ldb_ctx, py_iter->state.req, timeout);
2100 ret = ldb_request(ldb_ctx, py_iter->state.req);
2101 if (ret != LDB_SUCCESS) {
2102 Py_DECREF(py_iter);
2103 PyErr_SetLdbError(PyExc_LdbError, ret, ldb_ctx);
2104 return NULL;
2107 return (PyObject *)py_iter;
2110 static PyObject *py_ldb_get_opaque(PyLdbObject *self, PyObject *args)
2112 char *name;
2113 void *data;
2115 if (!PyArg_ParseTuple(args, "s", &name))
2116 return NULL;
2118 data = ldb_get_opaque(pyldb_Ldb_AsLdbContext(self), name);
2120 if (data == NULL)
2121 Py_RETURN_NONE;
2123 /* FIXME: More interpretation */
2125 Py_RETURN_TRUE;
2128 static PyObject *py_ldb_set_opaque(PyLdbObject *self, PyObject *args)
2130 char *name;
2131 PyObject *data;
2133 if (!PyArg_ParseTuple(args, "sO", &name, &data))
2134 return NULL;
2136 /* FIXME: More interpretation */
2138 ldb_set_opaque(pyldb_Ldb_AsLdbContext(self), name, data);
2140 Py_RETURN_NONE;
2143 static PyObject *py_ldb_modules(PyLdbObject *self)
2145 struct ldb_context *ldb = pyldb_Ldb_AsLdbContext(self);
2146 PyObject *ret = PyList_New(0);
2147 struct ldb_module *mod;
2149 for (mod = ldb->modules; mod; mod = mod->next) {
2150 PyList_Append(ret, PyLdbModule_FromModule(mod));
2153 return ret;
2156 static PyObject *py_ldb_sequence_number(PyLdbObject *self, PyObject *args)
2158 struct ldb_context *ldb = pyldb_Ldb_AsLdbContext(self);
2159 int type, ret;
2160 uint64_t value;
2162 if (!PyArg_ParseTuple(args, "i", &type))
2163 return NULL;
2165 /* FIXME: More interpretation */
2167 ret = ldb_sequence_number(ldb, type, &value);
2169 PyErr_LDB_ERROR_IS_ERR_RAISE(PyExc_LdbError, ret, ldb);
2171 return PyLong_FromLongLong(value);
2175 static const struct ldb_dn_extended_syntax test_dn_syntax = {
2176 .name = "TEST",
2177 .read_fn = ldb_handler_copy,
2178 .write_clear_fn = ldb_handler_copy,
2179 .write_hex_fn = ldb_handler_copy,
2182 static PyObject *py_ldb_register_test_extensions(PyLdbObject *self)
2184 struct ldb_context *ldb = pyldb_Ldb_AsLdbContext(self);
2185 int ret;
2187 ret = ldb_dn_extended_add_syntax(ldb, LDB_ATTR_FLAG_FIXED, &test_dn_syntax);
2189 PyErr_LDB_ERROR_IS_ERR_RAISE(PyExc_LdbError, ret, ldb);
2191 Py_RETURN_NONE;
2195 static PyMethodDef py_ldb_methods[] = {
2196 { "set_debug", (PyCFunction)py_ldb_set_debug, METH_VARARGS,
2197 "S.set_debug(callback) -> None\n"
2198 "Set callback for LDB debug messages.\n"
2199 "The callback should accept a debug level and debug text." },
2200 { "set_create_perms", (PyCFunction)py_ldb_set_create_perms, METH_VARARGS,
2201 "S.set_create_perms(mode) -> None\n"
2202 "Set mode to use when creating new LDB files." },
2203 { "set_modules_dir", (PyCFunction)py_ldb_set_modules_dir, METH_VARARGS,
2204 "S.set_modules_dir(path) -> None\n"
2205 "Set path LDB should search for modules" },
2206 { "transaction_start", (PyCFunction)py_ldb_transaction_start, METH_NOARGS,
2207 "S.transaction_start() -> None\n"
2208 "Start a new transaction." },
2209 { "transaction_prepare_commit", (PyCFunction)py_ldb_transaction_prepare_commit, METH_NOARGS,
2210 "S.transaction_prepare_commit() -> None\n"
2211 "prepare to commit a new transaction (2-stage commit)." },
2212 { "transaction_commit", (PyCFunction)py_ldb_transaction_commit, METH_NOARGS,
2213 "S.transaction_commit() -> None\n"
2214 "commit a new transaction." },
2215 { "transaction_cancel", (PyCFunction)py_ldb_transaction_cancel, METH_NOARGS,
2216 "S.transaction_cancel() -> None\n"
2217 "cancel a new transaction." },
2218 { "setup_wellknown_attributes", (PyCFunction)py_ldb_setup_wellknown_attributes, METH_NOARGS,
2219 NULL },
2220 { "get_root_basedn", (PyCFunction)py_ldb_get_root_basedn, METH_NOARGS,
2221 NULL },
2222 { "get_schema_basedn", (PyCFunction)py_ldb_get_schema_basedn, METH_NOARGS,
2223 NULL },
2224 { "get_default_basedn", (PyCFunction)py_ldb_get_default_basedn, METH_NOARGS,
2225 NULL },
2226 { "get_config_basedn", (PyCFunction)py_ldb_get_config_basedn, METH_NOARGS,
2227 NULL },
2228 { "connect", (PyCFunction)py_ldb_connect, METH_VARARGS|METH_KEYWORDS,
2229 "S.connect(url, flags=0, options=None) -> None\n"
2230 "Connect to a LDB URL." },
2231 { "modify", (PyCFunction)py_ldb_modify, METH_VARARGS|METH_KEYWORDS,
2232 "S.modify(message, controls=None, validate=False) -> None\n"
2233 "Modify an entry." },
2234 { "add", (PyCFunction)py_ldb_add, METH_VARARGS|METH_KEYWORDS,
2235 "S.add(message, controls=None) -> None\n"
2236 "Add an entry." },
2237 { "delete", (PyCFunction)py_ldb_delete, METH_VARARGS|METH_KEYWORDS,
2238 "S.delete(dn, controls=None) -> None\n"
2239 "Remove an entry." },
2240 { "rename", (PyCFunction)py_ldb_rename, METH_VARARGS|METH_KEYWORDS,
2241 "S.rename(old_dn, new_dn, controls=None) -> None\n"
2242 "Rename an entry." },
2243 { "search", (PyCFunction)py_ldb_search, METH_VARARGS|METH_KEYWORDS,
2244 "S.search(base=None, scope=None, expression=None, attrs=None, controls=None) -> result\n"
2245 "Search in a database.\n"
2246 "\n"
2247 ":param base: Optional base DN to search\n"
2248 ":param scope: Search scope (SCOPE_BASE, SCOPE_ONELEVEL or SCOPE_SUBTREE)\n"
2249 ":param expression: Optional search expression\n"
2250 ":param attrs: Attributes to return (defaults to all)\n"
2251 ":param controls: Optional list of controls\n"
2252 ":return: ldb.Result object\n"
2254 { "search_iterator", (PyCFunction)py_ldb_search_iterator, METH_VARARGS|METH_KEYWORDS,
2255 "S.search_iterator(base=None, scope=None, expression=None, attrs=None, controls=None, timeout=None) -> iterator\n"
2256 "Search in a database.\n"
2257 "\n"
2258 ":param base: Optional base DN to search\n"
2259 ":param scope: Search scope (SCOPE_BASE, SCOPE_ONELEVEL or SCOPE_SUBTREE)\n"
2260 ":param expression: Optional search expression\n"
2261 ":param attrs: Attributes to return (defaults to all)\n"
2262 ":param controls: Optional list of controls\n"
2263 ":param timeout: Optional timeout in seconds (defaults to 300), 0 means the default, -1 no timeout\n"
2264 ":return: ldb.SearchIterator object that provides results when they arrive\n"
2266 { "schema_attribute_remove", (PyCFunction)py_ldb_schema_attribute_remove, METH_VARARGS,
2267 NULL },
2268 { "schema_attribute_add", (PyCFunction)py_ldb_schema_attribute_add, METH_VARARGS,
2269 NULL },
2270 { "schema_format_value", (PyCFunction)py_ldb_schema_format_value, METH_VARARGS,
2271 NULL },
2272 { "parse_ldif", (PyCFunction)py_ldb_parse_ldif, METH_VARARGS,
2273 "S.parse_ldif(ldif) -> iter(messages)\n"
2274 "Parse a string formatted using LDIF." },
2275 { "write_ldif", (PyCFunction)py_ldb_write_ldif, METH_VARARGS,
2276 "S.write_ldif(message, changetype) -> ldif\n"
2277 "Print the message as a string formatted using LDIF." },
2278 { "msg_diff", (PyCFunction)py_ldb_msg_diff, METH_VARARGS,
2279 "S.msg_diff(Message) -> Message\n"
2280 "Return an LDB Message of the difference between two Message objects." },
2281 { "get_opaque", (PyCFunction)py_ldb_get_opaque, METH_VARARGS,
2282 "S.get_opaque(name) -> value\n"
2283 "Get an opaque value set on this LDB connection. \n"
2284 ":note: The returned value may not be useful in Python."
2286 { "set_opaque", (PyCFunction)py_ldb_set_opaque, METH_VARARGS,
2287 "S.set_opaque(name, value) -> None\n"
2288 "Set an opaque value on this LDB connection. \n"
2289 ":note: Passing incorrect values may cause crashes." },
2290 { "modules", (PyCFunction)py_ldb_modules, METH_NOARGS,
2291 "S.modules() -> list\n"
2292 "Return the list of modules on this LDB connection " },
2293 { "sequence_number", (PyCFunction)py_ldb_sequence_number, METH_VARARGS,
2294 "S.sequence_number(type) -> value\n"
2295 "Return the value of the sequence according to the requested type" },
2296 { "_register_test_extensions", (PyCFunction)py_ldb_register_test_extensions, METH_NOARGS,
2297 "S._register_test_extensions() -> None\n"
2298 "Register internal extensions used in testing" },
2299 { NULL },
2302 static PyObject *PyLdbModule_FromModule(struct ldb_module *mod)
2304 PyLdbModuleObject *ret;
2306 ret = (PyLdbModuleObject *)PyLdbModule.tp_alloc(&PyLdbModule, 0);
2307 if (ret == NULL) {
2308 PyErr_NoMemory();
2309 return NULL;
2311 ret->mem_ctx = talloc_new(NULL);
2312 ret->mod = talloc_reference(ret->mem_ctx, mod);
2313 return (PyObject *)ret;
2316 static PyObject *py_ldb_get_firstmodule(PyLdbObject *self, void *closure)
2318 struct ldb_module *mod = pyldb_Ldb_AsLdbContext(self)->modules;
2319 if (mod == NULL) {
2320 Py_RETURN_NONE;
2322 return PyLdbModule_FromModule(mod);
2325 static PyGetSetDef py_ldb_getset[] = {
2326 { discard_const_p(char, "firstmodule"), (getter)py_ldb_get_firstmodule, NULL, NULL },
2327 { NULL }
2330 static int py_ldb_contains(PyLdbObject *self, PyObject *obj)
2332 struct ldb_context *ldb_ctx = pyldb_Ldb_AsLdbContext(self);
2333 struct ldb_dn *dn;
2334 struct ldb_result *result;
2335 unsigned int count;
2336 int ret;
2338 if (!pyldb_Object_AsDn(ldb_ctx, obj, ldb_ctx, &dn)) {
2339 return -1;
2342 ret = ldb_search(ldb_ctx, ldb_ctx, &result, dn, LDB_SCOPE_BASE, NULL,
2343 NULL);
2344 if (ret != LDB_SUCCESS) {
2345 PyErr_SetLdbError(PyExc_LdbError, ret, ldb_ctx);
2346 return -1;
2349 count = result->count;
2351 talloc_free(result);
2353 if (count > 1) {
2354 PyErr_Format(PyExc_RuntimeError,
2355 "Searching for [%s] dn gave %u results!",
2356 ldb_dn_get_linearized(dn),
2357 count);
2358 return -1;
2361 return count;
2364 static PySequenceMethods py_ldb_seq = {
2365 .sq_contains = (objobjproc)py_ldb_contains,
2368 static PyObject *PyLdb_FromLdbContext(struct ldb_context *ldb_ctx)
2370 PyLdbObject *ret;
2372 ret = (PyLdbObject *)PyLdb.tp_alloc(&PyLdb, 0);
2373 if (ret == NULL) {
2374 PyErr_NoMemory();
2375 return NULL;
2377 ret->mem_ctx = talloc_new(NULL);
2378 ret->ldb_ctx = talloc_reference(ret->mem_ctx, ldb_ctx);
2379 return (PyObject *)ret;
2382 static void py_ldb_dealloc(PyLdbObject *self)
2384 talloc_free(self->mem_ctx);
2385 Py_TYPE(self)->tp_free(self);
2388 static PyTypeObject PyLdb = {
2389 .tp_name = "ldb.Ldb",
2390 .tp_methods = py_ldb_methods,
2391 .tp_repr = (reprfunc)py_ldb_repr,
2392 .tp_new = py_ldb_new,
2393 .tp_init = (initproc)py_ldb_init,
2394 .tp_dealloc = (destructor)py_ldb_dealloc,
2395 .tp_getset = py_ldb_getset,
2396 .tp_getattro = PyObject_GenericGetAttr,
2397 .tp_basicsize = sizeof(PyLdbObject),
2398 .tp_doc = "Connection to a LDB database.",
2399 .tp_as_sequence = &py_ldb_seq,
2400 .tp_flags = Py_TPFLAGS_DEFAULT|Py_TPFLAGS_BASETYPE,
2403 static void py_ldb_result_dealloc(PyLdbResultObject *self)
2405 talloc_free(self->mem_ctx);
2406 Py_DECREF(self->msgs);
2407 Py_DECREF(self->referals);
2408 Py_DECREF(self->controls);
2409 Py_TYPE(self)->tp_free(self);
2412 static PyObject *py_ldb_result_get_msgs(PyLdbResultObject *self, void *closure)
2414 Py_INCREF(self->msgs);
2415 return self->msgs;
2418 static PyObject *py_ldb_result_get_controls(PyLdbResultObject *self, void *closure)
2420 Py_INCREF(self->controls);
2421 return self->controls;
2424 static PyObject *py_ldb_result_get_referals(PyLdbResultObject *self, void *closure)
2426 Py_INCREF(self->referals);
2427 return self->referals;
2430 static PyObject *py_ldb_result_get_count(PyLdbResultObject *self, void *closure)
2432 Py_ssize_t size;
2433 if (self->msgs == NULL) {
2434 PyErr_SetString(PyExc_AttributeError, "Count attribute is meaningless in this context");
2435 return NULL;
2437 size = PyList_Size(self->msgs);
2438 return PyInt_FromLong(size);
2441 static PyGetSetDef py_ldb_result_getset[] = {
2442 { discard_const_p(char, "controls"), (getter)py_ldb_result_get_controls, NULL, NULL },
2443 { discard_const_p(char, "msgs"), (getter)py_ldb_result_get_msgs, NULL, NULL },
2444 { discard_const_p(char, "referals"), (getter)py_ldb_result_get_referals, NULL, NULL },
2445 { discard_const_p(char, "count"), (getter)py_ldb_result_get_count, NULL, NULL },
2446 { NULL }
2449 static PyObject *py_ldb_result_iter(PyLdbResultObject *self)
2451 return PyObject_GetIter(self->msgs);
2454 static Py_ssize_t py_ldb_result_len(PyLdbResultObject *self)
2456 return PySequence_Size(self->msgs);
2459 static PyObject *py_ldb_result_find(PyLdbResultObject *self, Py_ssize_t idx)
2461 return PySequence_GetItem(self->msgs, idx);
2464 static PySequenceMethods py_ldb_result_seq = {
2465 .sq_length = (lenfunc)py_ldb_result_len,
2466 .sq_item = (ssizeargfunc)py_ldb_result_find,
2469 static PyObject *py_ldb_result_repr(PyLdbObject *self)
2471 return PyStr_FromString("<ldb result>");
2475 static PyTypeObject PyLdbResult = {
2476 .tp_name = "ldb.Result",
2477 .tp_repr = (reprfunc)py_ldb_result_repr,
2478 .tp_dealloc = (destructor)py_ldb_result_dealloc,
2479 .tp_iter = (getiterfunc)py_ldb_result_iter,
2480 .tp_getset = py_ldb_result_getset,
2481 .tp_getattro = PyObject_GenericGetAttr,
2482 .tp_basicsize = sizeof(PyLdbResultObject),
2483 .tp_as_sequence = &py_ldb_result_seq,
2484 .tp_doc = "LDB result.",
2485 .tp_flags = Py_TPFLAGS_DEFAULT|Py_TPFLAGS_BASETYPE,
2488 static void py_ldb_search_iterator_dealloc(PyLdbSearchIteratorObject *self)
2490 Py_XDECREF(self->state.exception);
2491 TALLOC_FREE(self->mem_ctx);
2492 ZERO_STRUCT(self->state);
2493 Py_DECREF(self->ldb);
2494 Py_TYPE(self)->tp_free(self);
2497 static PyObject *py_ldb_search_iterator_next(PyLdbSearchIteratorObject *self)
2499 PyObject *py_ret = NULL;
2501 if (self->state.req == NULL) {
2502 PyErr_SetString(PyExc_RuntimeError,
2503 "ldb.SearchIterator request already finished");
2504 return NULL;
2508 * TODO: do we want a non-blocking mode?
2509 * In future we may add an optional 'nonblocking'
2510 * argument to search_iterator().
2512 * For now we keep it simple and wait for at
2513 * least one reply.
2516 while (self->state.next == NULL) {
2517 int ret;
2519 if (self->state.result != NULL) {
2521 * We (already) got a final result from the server.
2523 * We stop the iteration and let
2524 * py_ldb_search_iterator_result() will deliver
2525 * the result details.
2527 TALLOC_FREE(self->state.req);
2528 PyErr_SetNone(PyExc_StopIteration);
2529 return NULL;
2532 ret = ldb_wait(self->state.req->handle, LDB_WAIT_NONE);
2533 if (ret != LDB_SUCCESS) {
2534 struct ldb_context *ldb_ctx;
2535 TALLOC_FREE(self->state.req);
2536 ldb_ctx = pyldb_Ldb_AsLdbContext(self->ldb);
2538 * We stop the iteration and let
2539 * py_ldb_search_iterator_result() will deliver
2540 * the exception.
2542 self->state.exception = Py_BuildValue(discard_const_p(char, "(i,s)"),
2543 ret, ldb_errstring(ldb_ctx));
2544 PyErr_SetNone(PyExc_StopIteration);
2545 return NULL;
2549 py_ret = self->state.next->obj;
2550 self->state.next->obj = NULL;
2551 /* no TALLOC_FREE() as self->state.next is a list */
2552 talloc_free(self->state.next);
2553 return py_ret;
2556 static PyObject *py_ldb_search_iterator_result(PyLdbSearchIteratorObject *self)
2558 PyObject *py_ret = NULL;
2560 if (self->state.req != NULL) {
2561 PyErr_SetString(PyExc_RuntimeError,
2562 "ldb.SearchIterator request running");
2563 return NULL;
2566 if (self->state.next != NULL) {
2567 PyErr_SetString(PyExc_RuntimeError,
2568 "ldb.SearchIterator not fully consumed.");
2569 return NULL;
2572 if (self->state.exception != NULL) {
2573 PyErr_SetObject(PyExc_LdbError, self->state.exception);
2574 self->state.exception = NULL;
2575 return NULL;
2578 if (self->state.result == NULL) {
2579 PyErr_SetString(PyExc_RuntimeError,
2580 "ldb.SearchIterator result already consumed");
2581 return NULL;
2584 py_ret = self->state.result->obj;
2585 self->state.result->obj = NULL;
2586 TALLOC_FREE(self->state.result);
2587 return py_ret;
2590 static PyObject *py_ldb_search_iterator_abandon(PyLdbSearchIteratorObject *self)
2592 if (self->state.req == NULL) {
2593 PyErr_SetString(PyExc_RuntimeError,
2594 "ldb.SearchIterator request already finished");
2595 return NULL;
2598 Py_XDECREF(self->state.exception);
2599 TALLOC_FREE(self->mem_ctx);
2600 ZERO_STRUCT(self->state);
2601 Py_RETURN_NONE;
2604 static PyMethodDef py_ldb_search_iterator_methods[] = {
2605 { "result", (PyCFunction)py_ldb_search_iterator_result, METH_NOARGS,
2606 "S.result() -> ldb.Result (without msgs and referrals)\n" },
2607 { "abandon", (PyCFunction)py_ldb_search_iterator_abandon, METH_NOARGS,
2608 "S.abandon()\n" },
2609 { NULL }
2612 static PyObject *py_ldb_search_iterator_repr(PyLdbSearchIteratorObject *self)
2614 return PyStr_FromString("<ldb search iterator>");
2617 static PyTypeObject PyLdbSearchIterator = {
2618 .tp_name = "ldb.SearchIterator",
2619 .tp_repr = (reprfunc)py_ldb_search_iterator_repr,
2620 .tp_dealloc = (destructor)py_ldb_search_iterator_dealloc,
2621 .tp_iter = PyObject_SelfIter,
2622 .tp_iternext = (iternextfunc)py_ldb_search_iterator_next,
2623 .tp_methods = py_ldb_search_iterator_methods,
2624 .tp_basicsize = sizeof(PyLdbSearchIteratorObject),
2625 .tp_doc = "LDB search_iterator.",
2626 .tp_flags = Py_TPFLAGS_DEFAULT|Py_TPFLAGS_BASETYPE,
2629 static PyObject *py_ldb_module_repr(PyLdbModuleObject *self)
2631 return PyStr_FromFormat("<ldb module '%s'>",
2632 pyldb_Module_AsModule(self)->ops->name);
2635 static PyObject *py_ldb_module_str(PyLdbModuleObject *self)
2637 return PyStr_FromString(pyldb_Module_AsModule(self)->ops->name);
2640 static PyObject *py_ldb_module_start_transaction(PyLdbModuleObject *self)
2642 pyldb_Module_AsModule(self)->ops->start_transaction(pyldb_Module_AsModule(self));
2643 Py_RETURN_NONE;
2646 static PyObject *py_ldb_module_end_transaction(PyLdbModuleObject *self)
2648 pyldb_Module_AsModule(self)->ops->end_transaction(pyldb_Module_AsModule(self));
2649 Py_RETURN_NONE;
2652 static PyObject *py_ldb_module_del_transaction(PyLdbModuleObject *self)
2654 pyldb_Module_AsModule(self)->ops->del_transaction(pyldb_Module_AsModule(self));
2655 Py_RETURN_NONE;
2658 static PyObject *py_ldb_module_search(PyLdbModuleObject *self, PyObject *args, PyObject *kwargs)
2660 PyObject *py_base, *py_tree, *py_attrs, *py_ret;
2661 int ret, scope;
2662 struct ldb_request *req;
2663 const char * const kwnames[] = { "base", "scope", "tree", "attrs", NULL };
2664 struct ldb_module *mod;
2665 const char * const*attrs;
2667 /* type "int" rather than "enum" for "scope" is intentional */
2668 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "O!iOO",
2669 discard_const_p(char *, kwnames),
2670 &PyLdbDn, &py_base, &scope, &py_tree, &py_attrs))
2671 return NULL;
2673 mod = self->mod;
2675 if (py_attrs == Py_None) {
2676 attrs = NULL;
2677 } else {
2678 attrs = PyList_AsStrList(NULL, py_attrs, "attrs");
2679 if (attrs == NULL)
2680 return NULL;
2683 ret = ldb_build_search_req(&req, mod->ldb, NULL, pyldb_Dn_AsDn(py_base),
2684 scope, NULL /* expr */, attrs,
2685 NULL /* controls */, NULL, NULL, NULL);
2687 talloc_steal(req, attrs);
2689 PyErr_LDB_ERROR_IS_ERR_RAISE(PyExc_LdbError, ret, mod->ldb);
2691 req->op.search.res = NULL;
2693 ret = mod->ops->search(mod, req);
2695 PyErr_LDB_ERROR_IS_ERR_RAISE(PyExc_LdbError, ret, mod->ldb);
2697 py_ret = PyLdbResult_FromResult(req->op.search.res);
2699 talloc_free(req);
2701 return py_ret;
2705 static PyObject *py_ldb_module_add(PyLdbModuleObject *self, PyObject *args)
2707 struct ldb_request *req;
2708 PyObject *py_message;
2709 int ret;
2710 struct ldb_module *mod;
2712 if (!PyArg_ParseTuple(args, "O!", &PyLdbMessage, &py_message))
2713 return NULL;
2715 req = talloc_zero(NULL, struct ldb_request);
2716 req->operation = LDB_ADD;
2717 req->op.add.message = pyldb_Message_AsMessage(py_message);
2719 mod = pyldb_Module_AsModule(self);
2720 ret = mod->ops->add(mod, req);
2722 PyErr_LDB_ERROR_IS_ERR_RAISE(PyExc_LdbError, ret, mod->ldb);
2724 Py_RETURN_NONE;
2727 static PyObject *py_ldb_module_modify(PyLdbModuleObject *self, PyObject *args)
2729 int ret;
2730 struct ldb_request *req;
2731 PyObject *py_message;
2732 struct ldb_module *mod;
2734 if (!PyArg_ParseTuple(args, "O!", &PyLdbMessage, &py_message))
2735 return NULL;
2737 req = talloc_zero(NULL, struct ldb_request);
2738 req->operation = LDB_MODIFY;
2739 req->op.mod.message = pyldb_Message_AsMessage(py_message);
2741 mod = pyldb_Module_AsModule(self);
2742 ret = mod->ops->modify(mod, req);
2744 PyErr_LDB_ERROR_IS_ERR_RAISE(PyExc_LdbError, ret, mod->ldb);
2746 Py_RETURN_NONE;
2749 static PyObject *py_ldb_module_delete(PyLdbModuleObject *self, PyObject *args)
2751 int ret;
2752 struct ldb_request *req;
2753 PyObject *py_dn;
2755 if (!PyArg_ParseTuple(args, "O!", &PyLdbDn, &py_dn))
2756 return NULL;
2758 req = talloc_zero(NULL, struct ldb_request);
2759 req->operation = LDB_DELETE;
2760 req->op.del.dn = pyldb_Dn_AsDn(py_dn);
2762 ret = pyldb_Module_AsModule(self)->ops->del(pyldb_Module_AsModule(self), req);
2764 PyErr_LDB_ERROR_IS_ERR_RAISE(PyExc_LdbError, ret, NULL);
2766 Py_RETURN_NONE;
2769 static PyObject *py_ldb_module_rename(PyLdbModuleObject *self, PyObject *args)
2771 int ret;
2772 struct ldb_request *req;
2773 PyObject *py_dn1, *py_dn2;
2775 if (!PyArg_ParseTuple(args, "O!O!", &PyLdbDn, &py_dn1, &PyLdbDn, &py_dn2))
2776 return NULL;
2778 req = talloc_zero(NULL, struct ldb_request);
2780 req->operation = LDB_RENAME;
2781 req->op.rename.olddn = pyldb_Dn_AsDn(py_dn1);
2782 req->op.rename.newdn = pyldb_Dn_AsDn(py_dn2);
2784 ret = pyldb_Module_AsModule(self)->ops->rename(pyldb_Module_AsModule(self), req);
2786 PyErr_LDB_ERROR_IS_ERR_RAISE(PyExc_LdbError, ret, NULL);
2788 Py_RETURN_NONE;
2791 static PyMethodDef py_ldb_module_methods[] = {
2792 { "search", (PyCFunction)py_ldb_module_search, METH_VARARGS|METH_KEYWORDS, NULL },
2793 { "add", (PyCFunction)py_ldb_module_add, METH_VARARGS, NULL },
2794 { "modify", (PyCFunction)py_ldb_module_modify, METH_VARARGS, NULL },
2795 { "rename", (PyCFunction)py_ldb_module_rename, METH_VARARGS, NULL },
2796 { "delete", (PyCFunction)py_ldb_module_delete, METH_VARARGS, NULL },
2797 { "start_transaction", (PyCFunction)py_ldb_module_start_transaction, METH_NOARGS, NULL },
2798 { "end_transaction", (PyCFunction)py_ldb_module_end_transaction, METH_NOARGS, NULL },
2799 { "del_transaction", (PyCFunction)py_ldb_module_del_transaction, METH_NOARGS, NULL },
2800 { NULL },
2803 static void py_ldb_module_dealloc(PyLdbModuleObject *self)
2805 talloc_free(self->mem_ctx);
2806 PyObject_Del(self);
2809 static PyTypeObject PyLdbModule = {
2810 .tp_name = "ldb.LdbModule",
2811 .tp_methods = py_ldb_module_methods,
2812 .tp_repr = (reprfunc)py_ldb_module_repr,
2813 .tp_str = (reprfunc)py_ldb_module_str,
2814 .tp_basicsize = sizeof(PyLdbModuleObject),
2815 .tp_dealloc = (destructor)py_ldb_module_dealloc,
2816 .tp_flags = Py_TPFLAGS_DEFAULT,
2817 .tp_doc = "LDB module (extension)",
2822 * Create a ldb_message_element from a Python object.
2824 * This will accept any sequence objects that contains strings, or
2825 * a string object.
2827 * A reference to set_obj will be borrowed.
2829 * @param mem_ctx Memory context
2830 * @param set_obj Python object to convert
2831 * @param flags ldb_message_element flags to set
2832 * @param attr_name Name of the attribute
2833 * @return New ldb_message_element, allocated as child of mem_ctx
2835 static struct ldb_message_element *PyObject_AsMessageElement(
2836 TALLOC_CTX *mem_ctx,
2837 PyObject *set_obj,
2838 unsigned int flags,
2839 const char *attr_name)
2841 struct ldb_message_element *me;
2842 const char *msg = NULL;
2843 Py_ssize_t size;
2844 int result;
2846 if (pyldb_MessageElement_Check(set_obj)) {
2847 PyLdbMessageElementObject *set_obj_as_me = (PyLdbMessageElementObject *)set_obj;
2848 /* We have to talloc_reference() the memory context, not the pointer
2849 * which may not actually be it's own context */
2850 if (talloc_reference(mem_ctx, set_obj_as_me->mem_ctx)) {
2851 return pyldb_MessageElement_AsMessageElement(set_obj);
2853 return NULL;
2856 me = talloc(mem_ctx, struct ldb_message_element);
2857 if (me == NULL) {
2858 PyErr_NoMemory();
2859 return NULL;
2862 me->name = talloc_strdup(me, attr_name);
2863 me->flags = flags;
2864 if (PyBytes_Check(set_obj) || PyUnicode_Check(set_obj)) {
2865 me->num_values = 1;
2866 me->values = talloc_array(me, struct ldb_val, me->num_values);
2867 if (PyBytes_Check(set_obj)) {
2868 char *_msg = NULL;
2869 result = PyBytes_AsStringAndSize(set_obj, &_msg, &size);
2870 if (result != 0) {
2871 talloc_free(me);
2872 return NULL;
2874 msg = _msg;
2875 } else {
2876 msg = PyStr_AsUTF8AndSize(set_obj, &size);
2877 if (msg == NULL) {
2878 talloc_free(me);
2879 return NULL;
2882 me->values[0].data = talloc_memdup(me,
2883 (const uint8_t *)msg,
2884 size+1);
2885 me->values[0].length = size;
2886 } else if (PySequence_Check(set_obj)) {
2887 Py_ssize_t i;
2888 me->num_values = PySequence_Size(set_obj);
2889 me->values = talloc_array(me, struct ldb_val, me->num_values);
2890 for (i = 0; i < me->num_values; i++) {
2891 PyObject *obj = PySequence_GetItem(set_obj, i);
2892 if (PyBytes_Check(obj)) {
2893 char *_msg = NULL;
2894 result = PyBytes_AsStringAndSize(obj, &_msg, &size);
2895 if (result != 0) {
2896 talloc_free(me);
2897 return NULL;
2899 msg = _msg;
2900 } else if (PyUnicode_Check(obj)) {
2901 msg = PyStr_AsUTF8AndSize(obj, &size);
2902 if (msg == NULL) {
2903 talloc_free(me);
2904 return NULL;
2906 } else {
2907 PyErr_Format(PyExc_TypeError,
2908 "Expected string as element %zd in list", i);
2909 talloc_free(me);
2910 return NULL;
2912 me->values[i].data = talloc_memdup(me,
2913 (const uint8_t *)msg,
2914 size+1);
2915 me->values[i].length = size;
2917 } else {
2918 PyErr_Format(PyExc_TypeError,
2919 "String or List type expected for '%s' attribute", attr_name);
2920 talloc_free(me);
2921 me = NULL;
2924 return me;
2928 static PyObject *ldb_msg_element_to_set(struct ldb_context *ldb_ctx,
2929 struct ldb_message_element *me)
2931 Py_ssize_t i;
2932 PyObject *result;
2934 /* Python << 2.5 doesn't have PySet_New and PySet_Add. */
2935 result = PyList_New(me->num_values);
2937 for (i = 0; i < me->num_values; i++) {
2938 PyList_SetItem(result, i,
2939 PyObject_FromLdbValue(&me->values[i]));
2942 return result;
2945 static PyObject *py_ldb_msg_element_get(PyLdbMessageElementObject *self, PyObject *args)
2947 unsigned int i;
2948 if (!PyArg_ParseTuple(args, "I", &i))
2949 return NULL;
2950 if (i >= pyldb_MessageElement_AsMessageElement(self)->num_values)
2951 Py_RETURN_NONE;
2953 return PyObject_FromLdbValue(&(pyldb_MessageElement_AsMessageElement(self)->values[i]));
2956 static PyObject *py_ldb_msg_element_flags(PyLdbMessageElementObject *self, PyObject *args)
2958 struct ldb_message_element *el = pyldb_MessageElement_AsMessageElement(self);
2959 return PyInt_FromLong(el->flags);
2962 static PyObject *py_ldb_msg_element_set_flags(PyLdbMessageElementObject *self, PyObject *args)
2964 unsigned int flags;
2965 struct ldb_message_element *el;
2966 if (!PyArg_ParseTuple(args, "I", &flags))
2967 return NULL;
2969 el = pyldb_MessageElement_AsMessageElement(self);
2970 el->flags = flags;
2971 Py_RETURN_NONE;
2974 static PyMethodDef py_ldb_msg_element_methods[] = {
2975 { "get", (PyCFunction)py_ldb_msg_element_get, METH_VARARGS, NULL },
2976 { "set_flags", (PyCFunction)py_ldb_msg_element_set_flags, METH_VARARGS, NULL },
2977 { "flags", (PyCFunction)py_ldb_msg_element_flags, METH_NOARGS, NULL },
2978 { NULL },
2981 static Py_ssize_t py_ldb_msg_element_len(PyLdbMessageElementObject *self)
2983 return pyldb_MessageElement_AsMessageElement(self)->num_values;
2986 static PyObject *py_ldb_msg_element_find(PyLdbMessageElementObject *self, Py_ssize_t idx)
2988 struct ldb_message_element *el = pyldb_MessageElement_AsMessageElement(self);
2989 if (idx < 0 || idx >= el->num_values) {
2990 PyErr_SetString(PyExc_IndexError, "Out of range");
2991 return NULL;
2993 return PyBytes_FromStringAndSize((char *)el->values[idx].data, el->values[idx].length);
2996 static PySequenceMethods py_ldb_msg_element_seq = {
2997 .sq_length = (lenfunc)py_ldb_msg_element_len,
2998 .sq_item = (ssizeargfunc)py_ldb_msg_element_find,
3001 static PyObject *py_ldb_msg_element_richcmp(PyObject *self, PyObject *other, int op)
3003 int ret;
3004 if (!pyldb_MessageElement_Check(other)) {
3005 Py_INCREF(Py_NotImplemented);
3006 return Py_NotImplemented;
3008 ret = ldb_msg_element_compare(pyldb_MessageElement_AsMessageElement(self),
3009 pyldb_MessageElement_AsMessageElement(other));
3010 return richcmp(ret, op);
3013 static PyObject *py_ldb_msg_element_iter(PyLdbMessageElementObject *self)
3015 PyObject *el = ldb_msg_element_to_set(NULL,
3016 pyldb_MessageElement_AsMessageElement(self));
3017 PyObject *ret = PyObject_GetIter(el);
3018 Py_DECREF(el);
3019 return ret;
3022 static PyObject *PyLdbMessageElement_FromMessageElement(struct ldb_message_element *el, TALLOC_CTX *mem_ctx)
3024 PyLdbMessageElementObject *ret;
3025 ret = PyObject_New(PyLdbMessageElementObject, &PyLdbMessageElement);
3026 if (ret == NULL) {
3027 PyErr_NoMemory();
3028 return NULL;
3030 ret->mem_ctx = talloc_new(NULL);
3031 if (talloc_reference(ret->mem_ctx, mem_ctx) == NULL) {
3032 PyErr_NoMemory();
3033 return NULL;
3035 ret->el = el;
3036 return (PyObject *)ret;
3039 static PyObject *py_ldb_msg_element_new(PyTypeObject *type, PyObject *args, PyObject *kwargs)
3041 PyObject *py_elements = NULL;
3042 struct ldb_message_element *el;
3043 unsigned int flags = 0;
3044 char *name = NULL;
3045 const char * const kwnames[] = { "elements", "flags", "name", NULL };
3046 PyLdbMessageElementObject *ret;
3047 TALLOC_CTX *mem_ctx;
3048 const char *msg = NULL;
3049 Py_ssize_t size;
3050 int result;
3052 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "|OIs",
3053 discard_const_p(char *, kwnames),
3054 &py_elements, &flags, &name))
3055 return NULL;
3057 mem_ctx = talloc_new(NULL);
3058 if (mem_ctx == NULL) {
3059 PyErr_NoMemory();
3060 return NULL;
3063 el = talloc_zero(mem_ctx, struct ldb_message_element);
3064 if (el == NULL) {
3065 PyErr_NoMemory();
3066 talloc_free(mem_ctx);
3067 return NULL;
3070 if (py_elements != NULL) {
3071 Py_ssize_t i;
3072 if (PyBytes_Check(py_elements) || PyUnicode_Check(py_elements)) {
3073 char *_msg = NULL;
3074 el->num_values = 1;
3075 el->values = talloc_array(el, struct ldb_val, 1);
3076 if (el->values == NULL) {
3077 talloc_free(mem_ctx);
3078 PyErr_NoMemory();
3079 return NULL;
3081 if (PyBytes_Check(py_elements)) {
3082 result = PyBytes_AsStringAndSize(py_elements, &_msg, &size);
3083 msg = _msg;
3084 } else {
3085 msg = PyStr_AsUTF8AndSize(py_elements, &size);
3086 result = (msg == NULL) ? -1 : 0;
3088 if (result != 0) {
3089 talloc_free(mem_ctx);
3090 return NULL;
3092 el->values[0].data = talloc_memdup(el->values,
3093 (const uint8_t *)msg, size + 1);
3094 el->values[0].length = size;
3095 } else if (PySequence_Check(py_elements)) {
3096 el->num_values = PySequence_Size(py_elements);
3097 el->values = talloc_array(el, struct ldb_val, el->num_values);
3098 if (el->values == NULL) {
3099 talloc_free(mem_ctx);
3100 PyErr_NoMemory();
3101 return NULL;
3103 for (i = 0; i < el->num_values; i++) {
3104 PyObject *item = PySequence_GetItem(py_elements, i);
3105 if (item == NULL) {
3106 talloc_free(mem_ctx);
3107 return NULL;
3109 if (PyBytes_Check(item)) {
3110 char *_msg = NULL;
3111 result = PyBytes_AsStringAndSize(item, &_msg, &size);
3112 msg = _msg;
3113 } else if (PyUnicode_Check(item)) {
3114 msg = PyStr_AsUTF8AndSize(item, &size);
3115 result = (msg == NULL) ? -1 : 0;
3116 } else {
3117 PyErr_Format(PyExc_TypeError,
3118 "Expected string as element %zd in list", i);
3119 result = -1;
3121 if (result != 0) {
3122 talloc_free(mem_ctx);
3123 return NULL;
3125 el->values[i].data = talloc_memdup(el,
3126 (const uint8_t *)msg, size+1);
3127 el->values[i].length = size;
3129 } else {
3130 PyErr_SetString(PyExc_TypeError,
3131 "Expected string or list");
3132 talloc_free(mem_ctx);
3133 return NULL;
3137 el->flags = flags;
3138 el->name = talloc_strdup(el, name);
3140 ret = PyObject_New(PyLdbMessageElementObject, type);
3141 if (ret == NULL) {
3142 talloc_free(mem_ctx);
3143 return NULL;
3146 ret->mem_ctx = mem_ctx;
3147 ret->el = el;
3148 return (PyObject *)ret;
3151 static PyObject *py_ldb_msg_element_repr(PyLdbMessageElementObject *self)
3153 char *element_str = NULL;
3154 Py_ssize_t i;
3155 struct ldb_message_element *el = pyldb_MessageElement_AsMessageElement(self);
3156 PyObject *ret, *repr;
3158 for (i = 0; i < el->num_values; i++) {
3159 PyObject *o = py_ldb_msg_element_find(self, i);
3160 repr = PyObject_Repr(o);
3161 if (element_str == NULL)
3162 element_str = talloc_strdup(NULL, PyStr_AsUTF8(repr));
3163 else
3164 element_str = talloc_asprintf_append(element_str, ",%s", PyStr_AsUTF8(repr));
3165 Py_DECREF(repr);
3168 if (element_str != NULL) {
3169 ret = PyStr_FromFormat("MessageElement([%s])", element_str);
3170 talloc_free(element_str);
3171 } else {
3172 ret = PyStr_FromString("MessageElement([])");
3175 return ret;
3178 static PyObject *py_ldb_msg_element_str(PyLdbMessageElementObject *self)
3180 struct ldb_message_element *el = pyldb_MessageElement_AsMessageElement(self);
3182 if (el->num_values == 1)
3183 return PyStr_FromStringAndSize((char *)el->values[0].data, el->values[0].length);
3184 else
3185 Py_RETURN_NONE;
3188 static void py_ldb_msg_element_dealloc(PyLdbMessageElementObject *self)
3190 talloc_free(self->mem_ctx);
3191 PyObject_Del(self);
3194 static PyObject *py_ldb_msg_element_get_text(PyObject *self, void *closure)
3196 return wrap_text("MessageElementTextWrapper", self);
3199 static PyGetSetDef py_ldb_msg_element_getset[] = {
3200 { discard_const_p(char, "text"), (getter)py_ldb_msg_element_get_text, NULL, NULL },
3201 { NULL }
3204 static PyTypeObject PyLdbMessageElement = {
3205 .tp_name = "ldb.MessageElement",
3206 .tp_basicsize = sizeof(PyLdbMessageElementObject),
3207 .tp_dealloc = (destructor)py_ldb_msg_element_dealloc,
3208 .tp_repr = (reprfunc)py_ldb_msg_element_repr,
3209 .tp_str = (reprfunc)py_ldb_msg_element_str,
3210 .tp_methods = py_ldb_msg_element_methods,
3211 .tp_getset = py_ldb_msg_element_getset,
3212 .tp_richcompare = (richcmpfunc)py_ldb_msg_element_richcmp,
3213 .tp_iter = (getiterfunc)py_ldb_msg_element_iter,
3214 .tp_as_sequence = &py_ldb_msg_element_seq,
3215 .tp_new = py_ldb_msg_element_new,
3216 .tp_flags = Py_TPFLAGS_DEFAULT,
3217 .tp_doc = "An element of a Message",
3221 static PyObject *py_ldb_msg_from_dict(PyTypeObject *type, PyObject *args)
3223 PyObject *py_ldb;
3224 PyObject *py_dict;
3225 PyObject *py_ret;
3226 struct ldb_message *msg;
3227 struct ldb_context *ldb_ctx;
3228 unsigned int mod_flags = LDB_FLAG_MOD_REPLACE;
3230 if (!PyArg_ParseTuple(args, "O!O!|I",
3231 &PyLdb, &py_ldb, &PyDict_Type, &py_dict,
3232 &mod_flags)) {
3233 return NULL;
3236 if (!PyLdb_Check(py_ldb)) {
3237 PyErr_SetString(PyExc_TypeError, "Expected Ldb");
3238 return NULL;
3241 /* mask only flags we are going to use */
3242 mod_flags = LDB_FLAG_MOD_TYPE(mod_flags);
3243 if (!mod_flags) {
3244 PyErr_SetString(PyExc_ValueError,
3245 "FLAG_MOD_ADD, FLAG_MOD_REPLACE or FLAG_MOD_DELETE"
3246 " expected as mod_flag value");
3247 return NULL;
3250 ldb_ctx = pyldb_Ldb_AsLdbContext(py_ldb);
3252 msg = PyDict_AsMessage(ldb_ctx, py_dict, ldb_ctx, mod_flags);
3253 if (!msg) {
3254 return NULL;
3257 py_ret = PyLdbMessage_FromMessage(msg);
3259 talloc_unlink(ldb_ctx, msg);
3261 return py_ret;
3264 static PyObject *py_ldb_msg_remove_attr(PyLdbMessageObject *self, PyObject *args)
3266 char *name;
3267 if (!PyArg_ParseTuple(args, "s", &name))
3268 return NULL;
3270 ldb_msg_remove_attr(self->msg, name);
3272 Py_RETURN_NONE;
3275 static PyObject *py_ldb_msg_keys(PyLdbMessageObject *self)
3277 struct ldb_message *msg = pyldb_Message_AsMessage(self);
3278 Py_ssize_t i, j = 0;
3279 PyObject *obj = PyList_New(msg->num_elements+(msg->dn != NULL?1:0));
3280 if (msg->dn != NULL) {
3281 PyList_SetItem(obj, j, PyStr_FromString("dn"));
3282 j++;
3284 for (i = 0; i < msg->num_elements; i++) {
3285 PyList_SetItem(obj, j, PyStr_FromString(msg->elements[i].name));
3286 j++;
3288 return obj;
3291 static PyObject *py_ldb_msg_getitem_helper(PyLdbMessageObject *self, PyObject *py_name)
3293 struct ldb_message_element *el;
3294 char *name;
3295 struct ldb_message *msg = pyldb_Message_AsMessage(self);
3296 name = PyStr_AsUTF8(py_name);
3297 if (name == NULL) {
3298 PyErr_SetNone(PyExc_TypeError);
3299 return NULL;
3301 if (!ldb_attr_cmp(name, "dn"))
3302 return pyldb_Dn_FromDn(msg->dn);
3303 el = ldb_msg_find_element(msg, name);
3304 if (el == NULL) {
3305 return NULL;
3307 return (PyObject *)PyLdbMessageElement_FromMessageElement(el, msg->elements);
3310 static PyObject *py_ldb_msg_getitem(PyLdbMessageObject *self, PyObject *py_name)
3312 PyObject *ret = py_ldb_msg_getitem_helper(self, py_name);
3313 if (ret == NULL) {
3314 PyErr_SetString(PyExc_KeyError, "No such element");
3315 return NULL;
3317 return ret;
3320 static PyObject *py_ldb_msg_get(PyLdbMessageObject *self, PyObject *args, PyObject *kwargs)
3322 PyObject *def = NULL;
3323 const char *kwnames[] = { "name", "default", "idx", NULL };
3324 const char *name = NULL;
3325 int idx = -1;
3326 struct ldb_message *msg = pyldb_Message_AsMessage(self);
3327 struct ldb_message_element *el;
3329 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "s|Oi:msg",
3330 discard_const_p(char *, kwnames), &name, &def, &idx)) {
3331 return NULL;
3334 if (strcasecmp(name, "dn") == 0) {
3335 return pyldb_Dn_FromDn(msg->dn);
3338 el = ldb_msg_find_element(msg, name);
3340 if (el == NULL || (idx != -1 && el->num_values <= idx)) {
3341 if (def != NULL) {
3342 Py_INCREF(def);
3343 return def;
3345 Py_RETURN_NONE;
3348 if (idx == -1) {
3349 return (PyObject *)PyLdbMessageElement_FromMessageElement(el, msg->elements);
3352 return PyObject_FromLdbValue(&el->values[idx]);
3355 static PyObject *py_ldb_msg_items(PyLdbMessageObject *self)
3357 struct ldb_message *msg = pyldb_Message_AsMessage(self);
3358 Py_ssize_t i, j = 0;
3359 PyObject *l = PyList_New(msg->num_elements + (msg->dn == NULL?0:1));
3360 if (msg->dn != NULL) {
3361 PyList_SetItem(l, 0, Py_BuildValue("(sO)", "dn", pyldb_Dn_FromDn(msg->dn)));
3362 j++;
3364 for (i = 0; i < msg->num_elements; i++, j++) {
3365 PyObject *py_el = PyLdbMessageElement_FromMessageElement(&msg->elements[i], msg->elements);
3366 PyObject *value = Py_BuildValue("(sO)", msg->elements[i].name, py_el);
3367 PyList_SetItem(l, j, value);
3369 return l;
3372 static PyObject *py_ldb_msg_elements(PyLdbMessageObject *self)
3374 struct ldb_message *msg = pyldb_Message_AsMessage(self);
3375 Py_ssize_t i = 0;
3376 PyObject *l = PyList_New(msg->num_elements);
3377 for (i = 0; i < msg->num_elements; i++) {
3378 PyList_SetItem(l, i, PyLdbMessageElement_FromMessageElement(&msg->elements[i], msg->elements));
3380 return l;
3383 static PyObject *py_ldb_msg_add(PyLdbMessageObject *self, PyObject *args)
3385 struct ldb_message *msg = pyldb_Message_AsMessage(self);
3386 PyLdbMessageElementObject *py_element;
3387 int i, ret;
3388 struct ldb_message_element *el;
3389 struct ldb_message_element *el_new;
3391 if (!PyArg_ParseTuple(args, "O!", &PyLdbMessageElement, &py_element))
3392 return NULL;
3394 el = py_element->el;
3395 if (el == NULL) {
3396 PyErr_SetString(PyExc_ValueError, "Invalid MessageElement object");
3397 return NULL;
3400 ret = ldb_msg_add_empty(msg, el->name, el->flags, &el_new);
3401 PyErr_LDB_ERROR_IS_ERR_RAISE(PyExc_LdbError, ret, NULL);
3403 /* now deep copy all attribute values */
3404 el_new->values = talloc_array(msg->elements, struct ldb_val, el->num_values);
3405 if (el_new->values == NULL) {
3406 PyErr_NoMemory();
3407 return NULL;
3409 el_new->num_values = el->num_values;
3411 for (i = 0; i < el->num_values; i++) {
3412 el_new->values[i] = ldb_val_dup(el_new->values, &el->values[i]);
3413 if (el_new->values[i].data == NULL
3414 && el->values[i].length != 0) {
3415 PyErr_NoMemory();
3416 return NULL;
3420 Py_RETURN_NONE;
3423 static PyMethodDef py_ldb_msg_methods[] = {
3424 { "from_dict", (PyCFunction)py_ldb_msg_from_dict, METH_CLASS | METH_VARARGS,
3425 "Message.from_dict(ldb, dict, mod_flag=FLAG_MOD_REPLACE) -> ldb.Message\n"
3426 "Class method to create ldb.Message object from Dictionary.\n"
3427 "mod_flag is one of FLAG_MOD_ADD, FLAG_MOD_REPLACE or FLAG_MOD_DELETE."},
3428 { "keys", (PyCFunction)py_ldb_msg_keys, METH_NOARGS,
3429 "S.keys() -> list\n\n"
3430 "Return sequence of all attribute names." },
3431 { "remove", (PyCFunction)py_ldb_msg_remove_attr, METH_VARARGS,
3432 "S.remove(name)\n\n"
3433 "Remove all entries for attributes with the specified name."},
3434 { "get", (PyCFunction)py_ldb_msg_get, METH_VARARGS | METH_KEYWORDS,
3435 "msg.get(name,default=None,idx=None) -> string\n"
3436 "idx is the index into the values array\n"
3437 "if idx is None, then a list is returned\n"
3438 "if idx is not None, then the element with that index is returned\n"
3439 "if you pass the special name 'dn' then the DN object is returned\n"},
3440 { "items", (PyCFunction)py_ldb_msg_items, METH_NOARGS, NULL },
3441 { "elements", (PyCFunction)py_ldb_msg_elements, METH_NOARGS, NULL },
3442 { "add", (PyCFunction)py_ldb_msg_add, METH_VARARGS,
3443 "S.add(element)\n\n"
3444 "Add an element to this message." },
3445 { NULL },
3448 static PyObject *py_ldb_msg_iter(PyLdbMessageObject *self)
3450 PyObject *list, *iter;
3452 list = py_ldb_msg_keys(self);
3453 iter = PyObject_GetIter(list);
3454 Py_DECREF(list);
3455 return iter;
3458 static int py_ldb_msg_setitem(PyLdbMessageObject *self, PyObject *name, PyObject *value)
3460 char *attr_name;
3462 attr_name = PyStr_AsUTF8(name);
3463 if (attr_name == NULL) {
3464 PyErr_SetNone(PyExc_TypeError);
3465 return -1;
3468 if (value == NULL) {
3469 /* delitem */
3470 ldb_msg_remove_attr(self->msg, attr_name);
3471 } else {
3472 int ret;
3473 struct ldb_message_element *el = PyObject_AsMessageElement(self->msg,
3474 value, 0, attr_name);
3475 if (el == NULL) {
3476 return -1;
3478 ldb_msg_remove_attr(pyldb_Message_AsMessage(self), attr_name);
3479 ret = ldb_msg_add(pyldb_Message_AsMessage(self), el, el->flags);
3480 if (ret != LDB_SUCCESS) {
3481 PyErr_SetLdbError(PyExc_LdbError, ret, NULL);
3482 return -1;
3485 return 0;
3488 static Py_ssize_t py_ldb_msg_length(PyLdbMessageObject *self)
3490 return pyldb_Message_AsMessage(self)->num_elements;
3493 static PyMappingMethods py_ldb_msg_mapping = {
3494 .mp_length = (lenfunc)py_ldb_msg_length,
3495 .mp_subscript = (binaryfunc)py_ldb_msg_getitem,
3496 .mp_ass_subscript = (objobjargproc)py_ldb_msg_setitem,
3499 static PyObject *py_ldb_msg_new(PyTypeObject *type, PyObject *args, PyObject *kwargs)
3501 const char * const kwnames[] = { "dn", NULL };
3502 struct ldb_message *ret;
3503 TALLOC_CTX *mem_ctx;
3504 PyObject *pydn = NULL;
3505 PyLdbMessageObject *py_ret;
3507 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "|O",
3508 discard_const_p(char *, kwnames),
3509 &pydn))
3510 return NULL;
3512 mem_ctx = talloc_new(NULL);
3513 if (mem_ctx == NULL) {
3514 PyErr_NoMemory();
3515 return NULL;
3518 ret = ldb_msg_new(mem_ctx);
3519 if (ret == NULL) {
3520 talloc_free(mem_ctx);
3521 PyErr_NoMemory();
3522 return NULL;
3525 if (pydn != NULL) {
3526 struct ldb_dn *dn;
3527 if (!pyldb_Object_AsDn(NULL, pydn, NULL, &dn)) {
3528 talloc_free(mem_ctx);
3529 return NULL;
3531 ret->dn = talloc_reference(ret, dn);
3534 py_ret = (PyLdbMessageObject *)type->tp_alloc(type, 0);
3535 if (py_ret == NULL) {
3536 PyErr_NoMemory();
3537 talloc_free(mem_ctx);
3538 return NULL;
3541 py_ret->mem_ctx = mem_ctx;
3542 py_ret->msg = ret;
3543 return (PyObject *)py_ret;
3546 static PyObject *PyLdbMessage_FromMessage(struct ldb_message *msg)
3548 PyLdbMessageObject *ret;
3550 ret = (PyLdbMessageObject *)PyLdbMessage.tp_alloc(&PyLdbMessage, 0);
3551 if (ret == NULL) {
3552 PyErr_NoMemory();
3553 return NULL;
3555 ret->mem_ctx = talloc_new(NULL);
3556 ret->msg = talloc_reference(ret->mem_ctx, msg);
3557 return (PyObject *)ret;
3560 static PyObject *py_ldb_msg_get_dn(PyLdbMessageObject *self, void *closure)
3562 struct ldb_message *msg = pyldb_Message_AsMessage(self);
3563 return pyldb_Dn_FromDn(msg->dn);
3566 static int py_ldb_msg_set_dn(PyLdbMessageObject *self, PyObject *value, void *closure)
3568 struct ldb_message *msg = pyldb_Message_AsMessage(self);
3569 if (!pyldb_Dn_Check(value)) {
3570 PyErr_SetString(PyExc_TypeError, "expected dn");
3571 return -1;
3574 msg->dn = talloc_reference(msg, pyldb_Dn_AsDn(value));
3575 return 0;
3578 static PyObject *py_ldb_msg_get_text(PyObject *self, void *closure)
3580 return wrap_text("MessageTextWrapper", self);
3583 static PyGetSetDef py_ldb_msg_getset[] = {
3584 { discard_const_p(char, "dn"), (getter)py_ldb_msg_get_dn, (setter)py_ldb_msg_set_dn, NULL },
3585 { discard_const_p(char, "text"), (getter)py_ldb_msg_get_text, NULL, NULL },
3586 { NULL }
3589 static PyObject *py_ldb_msg_repr(PyLdbMessageObject *self)
3591 PyObject *dict = PyDict_New(), *ret, *repr;
3592 if (PyDict_Update(dict, (PyObject *)self) != 0)
3593 return NULL;
3594 repr = PyObject_Repr(dict);
3595 if (repr == NULL) {
3596 Py_DECREF(dict);
3597 return NULL;
3599 ret = PyStr_FromFormat("Message(%s)", PyStr_AsUTF8(repr));
3600 Py_DECREF(repr);
3601 Py_DECREF(dict);
3602 return ret;
3605 static void py_ldb_msg_dealloc(PyLdbMessageObject *self)
3607 talloc_free(self->mem_ctx);
3608 PyObject_Del(self);
3611 static PyObject *py_ldb_msg_richcmp(PyLdbMessageObject *py_msg1,
3612 PyLdbMessageObject *py_msg2, int op)
3614 struct ldb_message *msg1, *msg2;
3615 unsigned int i;
3616 int ret;
3618 if (!PyLdbMessage_Check(py_msg2)) {
3619 Py_INCREF(Py_NotImplemented);
3620 return Py_NotImplemented;
3623 msg1 = pyldb_Message_AsMessage(py_msg1),
3624 msg2 = pyldb_Message_AsMessage(py_msg2);
3626 if ((msg1->dn != NULL) || (msg2->dn != NULL)) {
3627 ret = ldb_dn_compare(msg1->dn, msg2->dn);
3628 if (ret != 0) {
3629 return richcmp(ret, op);
3633 ret = msg1->num_elements - msg2->num_elements;
3634 if (ret != 0) {
3635 return richcmp(ret, op);
3638 for (i = 0; i < msg1->num_elements; i++) {
3639 ret = ldb_msg_element_compare_name(&msg1->elements[i],
3640 &msg2->elements[i]);
3641 if (ret != 0) {
3642 return richcmp(ret, op);
3645 ret = ldb_msg_element_compare(&msg1->elements[i],
3646 &msg2->elements[i]);
3647 if (ret != 0) {
3648 return richcmp(ret, op);
3652 return richcmp(0, op);
3655 static PyTypeObject PyLdbMessage = {
3656 .tp_name = "ldb.Message",
3657 .tp_methods = py_ldb_msg_methods,
3658 .tp_getset = py_ldb_msg_getset,
3659 .tp_as_mapping = &py_ldb_msg_mapping,
3660 .tp_basicsize = sizeof(PyLdbMessageObject),
3661 .tp_dealloc = (destructor)py_ldb_msg_dealloc,
3662 .tp_new = py_ldb_msg_new,
3663 .tp_repr = (reprfunc)py_ldb_msg_repr,
3664 .tp_flags = Py_TPFLAGS_DEFAULT,
3665 .tp_iter = (getiterfunc)py_ldb_msg_iter,
3666 .tp_richcompare = (richcmpfunc)py_ldb_msg_richcmp,
3667 .tp_doc = "A LDB Message",
3670 static PyObject *PyLdbTree_FromTree(struct ldb_parse_tree *tree)
3672 PyLdbTreeObject *ret;
3674 ret = (PyLdbTreeObject *)PyLdbTree.tp_alloc(&PyLdbTree, 0);
3675 if (ret == NULL) {
3676 PyErr_NoMemory();
3677 return NULL;
3680 ret->mem_ctx = talloc_new(NULL);
3681 ret->tree = talloc_reference(ret->mem_ctx, tree);
3682 return (PyObject *)ret;
3685 static void py_ldb_tree_dealloc(PyLdbTreeObject *self)
3687 talloc_free(self->mem_ctx);
3688 PyObject_Del(self);
3691 static PyTypeObject PyLdbTree = {
3692 .tp_name = "ldb.Tree",
3693 .tp_basicsize = sizeof(PyLdbTreeObject),
3694 .tp_dealloc = (destructor)py_ldb_tree_dealloc,
3695 .tp_flags = Py_TPFLAGS_DEFAULT,
3696 .tp_doc = "A search tree",
3699 /* Ldb_module */
3700 static int py_module_search(struct ldb_module *mod, struct ldb_request *req)
3702 PyObject *py_ldb = (PyObject *)mod->private_data;
3703 PyObject *py_result, *py_base, *py_attrs, *py_tree;
3705 py_base = pyldb_Dn_FromDn(req->op.search.base);
3707 if (py_base == NULL)
3708 return LDB_ERR_OPERATIONS_ERROR;
3710 py_tree = PyLdbTree_FromTree(req->op.search.tree);
3712 if (py_tree == NULL)
3713 return LDB_ERR_OPERATIONS_ERROR;
3715 if (req->op.search.attrs == NULL) {
3716 py_attrs = Py_None;
3717 } else {
3718 int i, len;
3719 for (len = 0; req->op.search.attrs[len]; len++);
3720 py_attrs = PyList_New(len);
3721 for (i = 0; i < len; i++)
3722 PyList_SetItem(py_attrs, i, PyStr_FromString(req->op.search.attrs[i]));
3725 py_result = PyObject_CallMethod(py_ldb, discard_const_p(char, "search"),
3726 discard_const_p(char, "OiOO"),
3727 py_base, req->op.search.scope, py_tree, py_attrs);
3729 Py_DECREF(py_attrs);
3730 Py_DECREF(py_tree);
3731 Py_DECREF(py_base);
3733 if (py_result == NULL) {
3734 return LDB_ERR_PYTHON_EXCEPTION;
3737 req->op.search.res = PyLdbResult_AsResult(NULL, py_result);
3738 if (req->op.search.res == NULL) {
3739 return LDB_ERR_PYTHON_EXCEPTION;
3742 Py_DECREF(py_result);
3744 return LDB_SUCCESS;
3747 static int py_module_add(struct ldb_module *mod, struct ldb_request *req)
3749 PyObject *py_ldb = (PyObject *)mod->private_data;
3750 PyObject *py_result, *py_msg;
3752 py_msg = PyLdbMessage_FromMessage(discard_const_p(struct ldb_message, req->op.add.message));
3754 if (py_msg == NULL) {
3755 return LDB_ERR_OPERATIONS_ERROR;
3758 py_result = PyObject_CallMethod(py_ldb, discard_const_p(char, "add"),
3759 discard_const_p(char, "O"),
3760 py_msg);
3762 Py_DECREF(py_msg);
3764 if (py_result == NULL) {
3765 return LDB_ERR_PYTHON_EXCEPTION;
3768 Py_DECREF(py_result);
3770 return LDB_SUCCESS;
3773 static int py_module_modify(struct ldb_module *mod, struct ldb_request *req)
3775 PyObject *py_ldb = (PyObject *)mod->private_data;
3776 PyObject *py_result, *py_msg;
3778 py_msg = PyLdbMessage_FromMessage(discard_const_p(struct ldb_message, req->op.mod.message));
3780 if (py_msg == NULL) {
3781 return LDB_ERR_OPERATIONS_ERROR;
3784 py_result = PyObject_CallMethod(py_ldb, discard_const_p(char, "modify"),
3785 discard_const_p(char, "O"),
3786 py_msg);
3788 Py_DECREF(py_msg);
3790 if (py_result == NULL) {
3791 return LDB_ERR_PYTHON_EXCEPTION;
3794 Py_DECREF(py_result);
3796 return LDB_SUCCESS;
3799 static int py_module_del(struct ldb_module *mod, struct ldb_request *req)
3801 PyObject *py_ldb = (PyObject *)mod->private_data;
3802 PyObject *py_result, *py_dn;
3804 py_dn = pyldb_Dn_FromDn(req->op.del.dn);
3806 if (py_dn == NULL)
3807 return LDB_ERR_OPERATIONS_ERROR;
3809 py_result = PyObject_CallMethod(py_ldb, discard_const_p(char, "delete"),
3810 discard_const_p(char, "O"),
3811 py_dn);
3813 if (py_result == NULL) {
3814 return LDB_ERR_PYTHON_EXCEPTION;
3817 Py_DECREF(py_result);
3819 return LDB_SUCCESS;
3822 static int py_module_rename(struct ldb_module *mod, struct ldb_request *req)
3824 PyObject *py_ldb = (PyObject *)mod->private_data;
3825 PyObject *py_result, *py_olddn, *py_newdn;
3827 py_olddn = pyldb_Dn_FromDn(req->op.rename.olddn);
3829 if (py_olddn == NULL)
3830 return LDB_ERR_OPERATIONS_ERROR;
3832 py_newdn = pyldb_Dn_FromDn(req->op.rename.newdn);
3834 if (py_newdn == NULL)
3835 return LDB_ERR_OPERATIONS_ERROR;
3837 py_result = PyObject_CallMethod(py_ldb, discard_const_p(char, "rename"),
3838 discard_const_p(char, "OO"),
3839 py_olddn, py_newdn);
3841 Py_DECREF(py_olddn);
3842 Py_DECREF(py_newdn);
3844 if (py_result == NULL) {
3845 return LDB_ERR_PYTHON_EXCEPTION;
3848 Py_DECREF(py_result);
3850 return LDB_SUCCESS;
3853 static int py_module_request(struct ldb_module *mod, struct ldb_request *req)
3855 PyObject *py_ldb = (PyObject *)mod->private_data;
3856 PyObject *py_result;
3858 py_result = PyObject_CallMethod(py_ldb, discard_const_p(char, "request"),
3859 discard_const_p(char, ""));
3861 Py_XDECREF(py_result);
3863 return LDB_ERR_OPERATIONS_ERROR;
3866 static int py_module_extended(struct ldb_module *mod, struct ldb_request *req)
3868 PyObject *py_ldb = (PyObject *)mod->private_data;
3869 PyObject *py_result;
3871 py_result = PyObject_CallMethod(py_ldb, discard_const_p(char, "extended"),
3872 discard_const_p(char, ""));
3874 Py_XDECREF(py_result);
3876 return LDB_ERR_OPERATIONS_ERROR;
3879 static int py_module_start_transaction(struct ldb_module *mod)
3881 PyObject *py_ldb = (PyObject *)mod->private_data;
3882 PyObject *py_result;
3884 py_result = PyObject_CallMethod(py_ldb, discard_const_p(char, "start_transaction"),
3885 discard_const_p(char, ""));
3887 if (py_result == NULL) {
3888 return LDB_ERR_PYTHON_EXCEPTION;
3891 Py_DECREF(py_result);
3893 return LDB_SUCCESS;
3896 static int py_module_end_transaction(struct ldb_module *mod)
3898 PyObject *py_ldb = (PyObject *)mod->private_data;
3899 PyObject *py_result;
3901 py_result = PyObject_CallMethod(py_ldb, discard_const_p(char, "end_transaction"),
3902 discard_const_p(char, ""));
3904 if (py_result == NULL) {
3905 return LDB_ERR_PYTHON_EXCEPTION;
3908 Py_DECREF(py_result);
3910 return LDB_SUCCESS;
3913 static int py_module_del_transaction(struct ldb_module *mod)
3915 PyObject *py_ldb = (PyObject *)mod->private_data;
3916 PyObject *py_result;
3918 py_result = PyObject_CallMethod(py_ldb, discard_const_p(char, "del_transaction"),
3919 discard_const_p(char, ""));
3921 if (py_result == NULL) {
3922 return LDB_ERR_PYTHON_EXCEPTION;
3925 Py_DECREF(py_result);
3927 return LDB_SUCCESS;
3930 static int py_module_destructor(struct ldb_module *mod)
3932 Py_DECREF((PyObject *)mod->private_data);
3933 return 0;
3936 static int py_module_init(struct ldb_module *mod)
3938 PyObject *py_class = (PyObject *)mod->ops->private_data;
3939 PyObject *py_result, *py_next, *py_ldb;
3941 py_ldb = PyLdb_FromLdbContext(mod->ldb);
3943 if (py_ldb == NULL)
3944 return LDB_ERR_OPERATIONS_ERROR;
3946 py_next = PyLdbModule_FromModule(mod->next);
3948 if (py_next == NULL)
3949 return LDB_ERR_OPERATIONS_ERROR;
3951 py_result = PyObject_CallFunction(py_class, discard_const_p(char, "OO"),
3952 py_ldb, py_next);
3954 if (py_result == NULL) {
3955 return LDB_ERR_PYTHON_EXCEPTION;
3958 mod->private_data = py_result;
3960 talloc_set_destructor(mod, py_module_destructor);
3962 return ldb_next_init(mod);
3965 static PyObject *py_register_module(PyObject *module, PyObject *args)
3967 int ret;
3968 struct ldb_module_ops *ops;
3969 PyObject *input;
3971 if (!PyArg_ParseTuple(args, "O", &input))
3972 return NULL;
3974 ops = talloc_zero(NULL, struct ldb_module_ops);
3975 if (ops == NULL) {
3976 PyErr_NoMemory();
3977 return NULL;
3980 ops->name = talloc_strdup(ops, PyStr_AsUTF8(PyObject_GetAttrString(input, discard_const_p(char, "name"))));
3982 Py_INCREF(input);
3983 ops->private_data = input;
3984 ops->init_context = py_module_init;
3985 ops->search = py_module_search;
3986 ops->add = py_module_add;
3987 ops->modify = py_module_modify;
3988 ops->del = py_module_del;
3989 ops->rename = py_module_rename;
3990 ops->request = py_module_request;
3991 ops->extended = py_module_extended;
3992 ops->start_transaction = py_module_start_transaction;
3993 ops->end_transaction = py_module_end_transaction;
3994 ops->del_transaction = py_module_del_transaction;
3996 ret = ldb_register_module(ops);
3997 if (ret != LDB_SUCCESS) {
3998 TALLOC_FREE(ops);
4001 PyErr_LDB_ERROR_IS_ERR_RAISE(PyExc_LdbError, ret, NULL);
4003 Py_RETURN_NONE;
4006 static PyObject *py_timestring(PyObject *module, PyObject *args)
4008 /* most times "time_t" is a signed integer type with 32 or 64 bit:
4009 * http://stackoverflow.com/questions/471248/what-is-ultimately-a-time-t-typedef-to */
4010 long int t_val;
4011 char *tresult;
4012 PyObject *ret;
4013 if (!PyArg_ParseTuple(args, "l", &t_val))
4014 return NULL;
4015 tresult = ldb_timestring(NULL, (time_t) t_val);
4016 ret = PyStr_FromString(tresult);
4017 talloc_free(tresult);
4018 return ret;
4021 static PyObject *py_string_to_time(PyObject *module, PyObject *args)
4023 char *str;
4024 if (!PyArg_ParseTuple(args, "s", &str))
4025 return NULL;
4027 return PyInt_FromLong(ldb_string_to_time(str));
4030 static PyObject *py_valid_attr_name(PyObject *self, PyObject *args)
4032 char *name;
4033 if (!PyArg_ParseTuple(args, "s", &name))
4034 return NULL;
4035 return PyBool_FromLong(ldb_valid_attr_name(name));
4039 encode a string using RFC2254 rules
4041 static PyObject *py_binary_encode(PyObject *self, PyObject *args)
4043 char *str, *encoded;
4044 Py_ssize_t size = 0;
4045 struct ldb_val val;
4046 PyObject *ret;
4048 if (!PyArg_ParseTuple(args, "s#", &str, &size))
4049 return NULL;
4050 val.data = (uint8_t *)str;
4051 val.length = size;
4053 encoded = ldb_binary_encode(NULL, val);
4054 if (encoded == NULL) {
4055 PyErr_SetString(PyExc_TypeError, "unable to encode binary string");
4056 return NULL;
4058 ret = PyStr_FromString(encoded);
4059 talloc_free(encoded);
4060 return ret;
4064 decode a string using RFC2254 rules
4066 static PyObject *py_binary_decode(PyObject *self, PyObject *args)
4068 char *str;
4069 struct ldb_val val;
4070 PyObject *ret;
4072 if (!PyArg_ParseTuple(args, "s", &str))
4073 return NULL;
4075 val = ldb_binary_decode(NULL, str);
4076 if (val.data == NULL) {
4077 PyErr_SetString(PyExc_TypeError, "unable to decode binary string");
4078 return NULL;
4080 ret = PyBytes_FromStringAndSize((const char*)val.data, val.length);
4081 talloc_free(val.data);
4082 return ret;
4085 static PyMethodDef py_ldb_global_methods[] = {
4086 { "register_module", py_register_module, METH_VARARGS,
4087 "S.register_module(module) -> None\n\n"
4088 "Register a LDB module."},
4089 { "timestring", py_timestring, METH_VARARGS,
4090 "S.timestring(int) -> string\n\n"
4091 "Generate a LDAP time string from a UNIX timestamp" },
4092 { "string_to_time", py_string_to_time, METH_VARARGS,
4093 "S.string_to_time(string) -> int\n\n"
4094 "Parse a LDAP time string into a UNIX timestamp." },
4095 { "valid_attr_name", py_valid_attr_name, METH_VARARGS,
4096 "S.valid_attr_name(name) -> bool\n\nn"
4097 "Check whether the supplied name is a valid attribute name." },
4098 { "open", (PyCFunction)py_ldb_new, METH_VARARGS|METH_KEYWORDS,
4099 "S.open() -> Ldb\n\n"
4100 "Open a new LDB context." },
4101 { "binary_encode", py_binary_encode, METH_VARARGS,
4102 "S.binary_encode(string) -> string\n\n"
4103 "Perform a RFC2254 binary encoding on a string" },
4104 { "binary_decode", py_binary_decode, METH_VARARGS,
4105 "S.binary_decode(string) -> string\n\n"
4106 "Perform a RFC2254 binary decode on a string" },
4107 { NULL }
4110 #define MODULE_DOC "An interface to LDB, a LDAP-like API that can either to talk an embedded database (TDB-based) or a standards-compliant LDAP server."
4112 #if PY_MAJOR_VERSION >= 3
4113 static struct PyModuleDef moduledef = {
4114 PyModuleDef_HEAD_INIT,
4115 .m_name = "ldb",
4116 .m_doc = MODULE_DOC,
4117 .m_size = -1,
4118 .m_methods = py_ldb_global_methods,
4120 #endif
4122 static PyObject* module_init(void)
4124 PyObject *m;
4126 if (PyType_Ready(&PyLdbDn) < 0)
4127 return NULL;
4129 if (PyType_Ready(&PyLdbMessage) < 0)
4130 return NULL;
4132 if (PyType_Ready(&PyLdbMessageElement) < 0)
4133 return NULL;
4135 if (PyType_Ready(&PyLdb) < 0)
4136 return NULL;
4138 if (PyType_Ready(&PyLdbModule) < 0)
4139 return NULL;
4141 if (PyType_Ready(&PyLdbTree) < 0)
4142 return NULL;
4144 if (PyType_Ready(&PyLdbResult) < 0)
4145 return NULL;
4147 if (PyType_Ready(&PyLdbSearchIterator) < 0)
4148 return NULL;
4150 if (PyType_Ready(&PyLdbControl) < 0)
4151 return NULL;
4153 #if PY_MAJOR_VERSION >= 3
4154 m = PyModule_Create(&moduledef);
4155 #else
4156 m = Py_InitModule3("ldb", py_ldb_global_methods, MODULE_DOC);
4157 #endif
4158 if (m == NULL)
4159 return NULL;
4161 #define ADD_LDB_INT(val) PyModule_AddIntConstant(m, #val, LDB_ ## val)
4163 ADD_LDB_INT(SEQ_HIGHEST_SEQ);
4164 ADD_LDB_INT(SEQ_HIGHEST_TIMESTAMP);
4165 ADD_LDB_INT(SEQ_NEXT);
4166 ADD_LDB_INT(SCOPE_DEFAULT);
4167 ADD_LDB_INT(SCOPE_BASE);
4168 ADD_LDB_INT(SCOPE_ONELEVEL);
4169 ADD_LDB_INT(SCOPE_SUBTREE);
4171 ADD_LDB_INT(CHANGETYPE_NONE);
4172 ADD_LDB_INT(CHANGETYPE_ADD);
4173 ADD_LDB_INT(CHANGETYPE_DELETE);
4174 ADD_LDB_INT(CHANGETYPE_MODIFY);
4176 ADD_LDB_INT(FLAG_MOD_ADD);
4177 ADD_LDB_INT(FLAG_MOD_REPLACE);
4178 ADD_LDB_INT(FLAG_MOD_DELETE);
4180 ADD_LDB_INT(ATTR_FLAG_HIDDEN);
4181 ADD_LDB_INT(ATTR_FLAG_UNIQUE_INDEX);
4182 ADD_LDB_INT(ATTR_FLAG_SINGLE_VALUE);
4183 ADD_LDB_INT(ATTR_FLAG_FORCE_BASE64_LDIF);
4185 ADD_LDB_INT(SUCCESS);
4186 ADD_LDB_INT(ERR_OPERATIONS_ERROR);
4187 ADD_LDB_INT(ERR_PROTOCOL_ERROR);
4188 ADD_LDB_INT(ERR_TIME_LIMIT_EXCEEDED);
4189 ADD_LDB_INT(ERR_SIZE_LIMIT_EXCEEDED);
4190 ADD_LDB_INT(ERR_COMPARE_FALSE);
4191 ADD_LDB_INT(ERR_COMPARE_TRUE);
4192 ADD_LDB_INT(ERR_AUTH_METHOD_NOT_SUPPORTED);
4193 ADD_LDB_INT(ERR_STRONG_AUTH_REQUIRED);
4194 ADD_LDB_INT(ERR_REFERRAL);
4195 ADD_LDB_INT(ERR_ADMIN_LIMIT_EXCEEDED);
4196 ADD_LDB_INT(ERR_UNSUPPORTED_CRITICAL_EXTENSION);
4197 ADD_LDB_INT(ERR_CONFIDENTIALITY_REQUIRED);
4198 ADD_LDB_INT(ERR_SASL_BIND_IN_PROGRESS);
4199 ADD_LDB_INT(ERR_NO_SUCH_ATTRIBUTE);
4200 ADD_LDB_INT(ERR_UNDEFINED_ATTRIBUTE_TYPE);
4201 ADD_LDB_INT(ERR_INAPPROPRIATE_MATCHING);
4202 ADD_LDB_INT(ERR_CONSTRAINT_VIOLATION);
4203 ADD_LDB_INT(ERR_ATTRIBUTE_OR_VALUE_EXISTS);
4204 ADD_LDB_INT(ERR_INVALID_ATTRIBUTE_SYNTAX);
4205 ADD_LDB_INT(ERR_NO_SUCH_OBJECT);
4206 ADD_LDB_INT(ERR_ALIAS_PROBLEM);
4207 ADD_LDB_INT(ERR_INVALID_DN_SYNTAX);
4208 ADD_LDB_INT(ERR_ALIAS_DEREFERENCING_PROBLEM);
4209 ADD_LDB_INT(ERR_INAPPROPRIATE_AUTHENTICATION);
4210 ADD_LDB_INT(ERR_INVALID_CREDENTIALS);
4211 ADD_LDB_INT(ERR_INSUFFICIENT_ACCESS_RIGHTS);
4212 ADD_LDB_INT(ERR_BUSY);
4213 ADD_LDB_INT(ERR_UNAVAILABLE);
4214 ADD_LDB_INT(ERR_UNWILLING_TO_PERFORM);
4215 ADD_LDB_INT(ERR_LOOP_DETECT);
4216 ADD_LDB_INT(ERR_NAMING_VIOLATION);
4217 ADD_LDB_INT(ERR_OBJECT_CLASS_VIOLATION);
4218 ADD_LDB_INT(ERR_NOT_ALLOWED_ON_NON_LEAF);
4219 ADD_LDB_INT(ERR_NOT_ALLOWED_ON_RDN);
4220 ADD_LDB_INT(ERR_ENTRY_ALREADY_EXISTS);
4221 ADD_LDB_INT(ERR_OBJECT_CLASS_MODS_PROHIBITED);
4222 ADD_LDB_INT(ERR_AFFECTS_MULTIPLE_DSAS);
4223 ADD_LDB_INT(ERR_OTHER);
4225 ADD_LDB_INT(FLG_RDONLY);
4226 ADD_LDB_INT(FLG_NOSYNC);
4227 ADD_LDB_INT(FLG_RECONNECT);
4228 ADD_LDB_INT(FLG_NOMMAP);
4229 ADD_LDB_INT(FLG_SHOW_BINARY);
4230 ADD_LDB_INT(FLG_ENABLE_TRACING);
4231 ADD_LDB_INT(FLG_DONT_CREATE_DB);
4234 /* Historical misspelling */
4235 PyModule_AddIntConstant(m, "ERR_ALIAS_DEREFERINCING_PROBLEM", LDB_ERR_ALIAS_DEREFERENCING_PROBLEM);
4237 PyModule_AddStringConstant(m, "__docformat__", "restructuredText");
4239 PyExc_LdbError = PyErr_NewException(discard_const_p(char, "_ldb.LdbError"), NULL, NULL);
4240 PyModule_AddObject(m, "LdbError", PyExc_LdbError);
4242 Py_INCREF(&PyLdb);
4243 Py_INCREF(&PyLdbDn);
4244 Py_INCREF(&PyLdbModule);
4245 Py_INCREF(&PyLdbMessage);
4246 Py_INCREF(&PyLdbMessageElement);
4247 Py_INCREF(&PyLdbTree);
4248 Py_INCREF(&PyLdbResult);
4249 Py_INCREF(&PyLdbControl);
4251 PyModule_AddObject(m, "Ldb", (PyObject *)&PyLdb);
4252 PyModule_AddObject(m, "Dn", (PyObject *)&PyLdbDn);
4253 PyModule_AddObject(m, "Message", (PyObject *)&PyLdbMessage);
4254 PyModule_AddObject(m, "MessageElement", (PyObject *)&PyLdbMessageElement);
4255 PyModule_AddObject(m, "Module", (PyObject *)&PyLdbModule);
4256 PyModule_AddObject(m, "Tree", (PyObject *)&PyLdbTree);
4257 PyModule_AddObject(m, "Control", (PyObject *)&PyLdbControl);
4259 PyModule_AddStringConstant(m, "__version__", PACKAGE_VERSION);
4261 #define ADD_LDB_STRING(val) PyModule_AddStringConstant(m, #val, LDB_## val)
4263 ADD_LDB_STRING(SYNTAX_DN);
4264 ADD_LDB_STRING(SYNTAX_DIRECTORY_STRING);
4265 ADD_LDB_STRING(SYNTAX_INTEGER);
4266 ADD_LDB_STRING(SYNTAX_BOOLEAN);
4267 ADD_LDB_STRING(SYNTAX_OCTET_STRING);
4268 ADD_LDB_STRING(SYNTAX_UTC_TIME);
4269 ADD_LDB_STRING(OID_COMPARATOR_AND);
4270 ADD_LDB_STRING(OID_COMPARATOR_OR);
4272 return m;
4275 #if PY_MAJOR_VERSION >= 3
4276 PyMODINIT_FUNC PyInit_ldb(void);
4277 PyMODINIT_FUNC PyInit_ldb(void)
4279 return module_init();
4281 #else
4282 void initldb(void);
4283 void initldb(void)
4285 module_init();
4287 #endif