s3-winbindd: remove some dead prototypes
[Samba.git] / lib / ldb / pyldb.c
blobb65e25525ad0aa6158b90ac1fa31b57d43715d3b
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;
514 Py_ssize_t size = 0;
516 if (!PyArg_ParseTuple(args, "sz#", &name, (const 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)) {
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;
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;
1673 TALLOC_CTX *mem_ctx;
1675 if (!PyArg_ParseTuple(args, "s", &s))
1676 return NULL;
1678 mem_ctx = talloc_new(NULL);
1679 if (!mem_ctx) {
1680 Py_RETURN_NONE;
1683 list = PyList_New(0);
1684 while (s && *s != '\0') {
1685 ldif = ldb_ldif_read_string(self->ldb_ctx, &s);
1686 talloc_steal(mem_ctx, ldif);
1687 if (ldif) {
1688 PyList_Append(list, ldb_ldif_to_pyobject(ldif));
1689 } else {
1690 PyErr_SetString(PyExc_ValueError, "unable to parse ldif string");
1691 talloc_free(mem_ctx);
1692 return NULL;
1695 talloc_free(mem_ctx); /* The pyobject already has a reference to the things it needs */
1696 ret = PyObject_GetIter(list);
1697 Py_DECREF(list);
1698 return ret;
1701 static PyObject *py_ldb_msg_diff(PyLdbObject *self, PyObject *args)
1703 int ldb_ret;
1704 PyObject *py_msg_old;
1705 PyObject *py_msg_new;
1706 struct ldb_message *diff;
1707 struct ldb_context *ldb;
1708 PyObject *py_ret;
1710 if (!PyArg_ParseTuple(args, "OO", &py_msg_old, &py_msg_new))
1711 return NULL;
1713 if (!PyLdbMessage_Check(py_msg_old)) {
1714 PyErr_SetString(PyExc_TypeError, "Expected Ldb Message for old message");
1715 return NULL;
1718 if (!PyLdbMessage_Check(py_msg_new)) {
1719 PyErr_SetString(PyExc_TypeError, "Expected Ldb Message for new message");
1720 return NULL;
1723 ldb = pyldb_Ldb_AsLdbContext(self);
1724 ldb_ret = ldb_msg_difference(ldb, ldb,
1725 pyldb_Message_AsMessage(py_msg_old),
1726 pyldb_Message_AsMessage(py_msg_new),
1727 &diff);
1728 if (ldb_ret != LDB_SUCCESS) {
1729 PyErr_SetString(PyExc_RuntimeError, "Failed to generate the Ldb Message diff");
1730 return NULL;
1733 py_ret = PyLdbMessage_FromMessage(diff);
1735 talloc_unlink(ldb, diff);
1737 return py_ret;
1740 static PyObject *py_ldb_schema_format_value(PyLdbObject *self, PyObject *args)
1742 const struct ldb_schema_attribute *a;
1743 struct ldb_val old_val;
1744 struct ldb_val new_val;
1745 TALLOC_CTX *mem_ctx;
1746 PyObject *ret;
1747 char *element_name;
1748 PyObject *val;
1749 Py_ssize_t size;
1750 int result;
1752 if (!PyArg_ParseTuple(args, "sO", &element_name, &val))
1753 return NULL;
1755 result = PyBytes_AsStringAndSize(val, (char **)&old_val.data, &size);
1756 old_val.length = size;
1758 if (result != 0) {
1759 PyErr_SetString(PyExc_RuntimeError, "Failed to convert passed value to String");
1760 return NULL;
1763 a = ldb_schema_attribute_by_name(pyldb_Ldb_AsLdbContext(self), element_name);
1765 if (a == NULL) {
1766 Py_RETURN_NONE;
1769 mem_ctx = talloc_new(NULL);
1770 if (mem_ctx == NULL) {
1771 PyErr_NoMemory();
1772 return NULL;
1775 if (a->syntax->ldif_write_fn(pyldb_Ldb_AsLdbContext(self), mem_ctx, &old_val, &new_val) != 0) {
1776 talloc_free(mem_ctx);
1777 Py_RETURN_NONE;
1780 ret = PyBytes_FromStringAndSize((const char *)new_val.data, new_val.length);
1782 talloc_free(mem_ctx);
1784 return ret;
1787 static PyObject *py_ldb_search(PyLdbObject *self, PyObject *args, PyObject *kwargs)
1789 PyObject *py_base = Py_None;
1790 int scope = LDB_SCOPE_DEFAULT;
1791 char *expr = NULL;
1792 PyObject *py_attrs = Py_None;
1793 PyObject *py_controls = Py_None;
1794 const char * const kwnames[] = { "base", "scope", "expression", "attrs", "controls", NULL };
1795 int ret;
1796 struct ldb_result *res;
1797 struct ldb_request *req;
1798 const char **attrs;
1799 struct ldb_context *ldb_ctx;
1800 struct ldb_control **parsed_controls;
1801 struct ldb_dn *base;
1802 PyObject *py_ret;
1803 TALLOC_CTX *mem_ctx;
1805 /* type "int" rather than "enum" for "scope" is intentional */
1806 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "|OizOO",
1807 discard_const_p(char *, kwnames),
1808 &py_base, &scope, &expr, &py_attrs, &py_controls))
1809 return NULL;
1812 mem_ctx = talloc_new(NULL);
1813 if (mem_ctx == NULL) {
1814 PyErr_NoMemory();
1815 return NULL;
1817 ldb_ctx = pyldb_Ldb_AsLdbContext(self);
1819 if (py_attrs == Py_None) {
1820 attrs = NULL;
1821 } else {
1822 attrs = PyList_AsStrList(mem_ctx, py_attrs, "attrs");
1823 if (attrs == NULL) {
1824 talloc_free(mem_ctx);
1825 return NULL;
1829 if (py_base == Py_None) {
1830 base = ldb_get_default_basedn(ldb_ctx);
1831 } else {
1832 if (!pyldb_Object_AsDn(mem_ctx, py_base, ldb_ctx, &base)) {
1833 talloc_free(mem_ctx);
1834 return NULL;
1838 if (py_controls == Py_None) {
1839 parsed_controls = NULL;
1840 } else {
1841 const char **controls = PyList_AsStrList(mem_ctx, py_controls, "controls");
1842 if (controls == NULL) {
1843 talloc_free(mem_ctx);
1844 return NULL;
1846 parsed_controls = ldb_parse_control_strings(ldb_ctx, mem_ctx, controls);
1847 talloc_free(controls);
1850 res = talloc_zero(mem_ctx, struct ldb_result);
1851 if (res == NULL) {
1852 PyErr_NoMemory();
1853 talloc_free(mem_ctx);
1854 return NULL;
1857 ret = ldb_build_search_req(&req, ldb_ctx, mem_ctx,
1858 base,
1859 scope,
1860 expr,
1861 attrs,
1862 parsed_controls,
1863 res,
1864 ldb_search_default_callback,
1865 NULL);
1867 if (ret != LDB_SUCCESS) {
1868 talloc_free(mem_ctx);
1869 PyErr_SetLdbError(PyExc_LdbError, ret, ldb_ctx);
1870 return NULL;
1873 talloc_steal(req, attrs);
1875 ret = ldb_request(ldb_ctx, req);
1877 if (ret == LDB_SUCCESS) {
1878 ret = ldb_wait(req->handle, LDB_WAIT_ALL);
1881 if (ret != LDB_SUCCESS) {
1882 talloc_free(mem_ctx);
1883 PyErr_SetLdbError(PyExc_LdbError, ret, ldb_ctx);
1884 return NULL;
1887 py_ret = PyLdbResult_FromResult(res);
1889 talloc_free(mem_ctx);
1891 return py_ret;
1894 static int py_ldb_search_iterator_reply_destructor(struct py_ldb_search_iterator_reply *reply)
1896 if (reply->py_iter != NULL) {
1897 DLIST_REMOVE(reply->py_iter->state.next, reply);
1898 if (reply->py_iter->state.result == reply) {
1899 reply->py_iter->state.result = NULL;
1901 reply->py_iter = NULL;
1904 if (reply->obj != NULL) {
1905 Py_DECREF(reply->obj);
1906 reply->obj = NULL;
1909 return 0;
1912 static int py_ldb_search_iterator_callback(struct ldb_request *req,
1913 struct ldb_reply *ares)
1915 PyLdbSearchIteratorObject *py_iter = (PyLdbSearchIteratorObject *)req->context;
1916 struct ldb_result result = { .msgs = NULL };
1917 struct py_ldb_search_iterator_reply *reply = NULL;
1919 if (ares == NULL) {
1920 return ldb_request_done(req, LDB_ERR_OPERATIONS_ERROR);
1923 if (ares->error != LDB_SUCCESS) {
1924 int ret = ares->error;
1925 TALLOC_FREE(ares);
1926 return ldb_request_done(req, ret);
1929 reply = talloc_zero(py_iter->mem_ctx,
1930 struct py_ldb_search_iterator_reply);
1931 if (reply == NULL) {
1932 TALLOC_FREE(ares);
1933 return ldb_request_done(req, LDB_ERR_OPERATIONS_ERROR);
1935 reply->py_iter = py_iter;
1936 talloc_set_destructor(reply, py_ldb_search_iterator_reply_destructor);
1938 switch (ares->type) {
1939 case LDB_REPLY_ENTRY:
1940 reply->obj = PyLdbMessage_FromMessage(ares->message);
1941 if (reply->obj == NULL) {
1942 TALLOC_FREE(ares);
1943 return ldb_request_done(req, LDB_ERR_OPERATIONS_ERROR);
1945 DLIST_ADD_END(py_iter->state.next, reply);
1946 TALLOC_FREE(ares);
1947 return LDB_SUCCESS;
1949 case LDB_REPLY_REFERRAL:
1950 reply->obj = PyStr_FromString(ares->referral);
1951 if (reply->obj == NULL) {
1952 TALLOC_FREE(ares);
1953 return ldb_request_done(req, LDB_ERR_OPERATIONS_ERROR);
1955 DLIST_ADD_END(py_iter->state.next, reply);
1956 TALLOC_FREE(ares);
1957 return LDB_SUCCESS;
1959 case LDB_REPLY_DONE:
1960 result = (struct ldb_result) { .controls = ares->controls };
1961 reply->obj = PyLdbResult_FromResult(&result);
1962 if (reply->obj == NULL) {
1963 TALLOC_FREE(ares);
1964 return ldb_request_done(req, LDB_ERR_OPERATIONS_ERROR);
1966 py_iter->state.result = reply;
1967 TALLOC_FREE(ares);
1968 return ldb_request_done(req, LDB_SUCCESS);
1971 TALLOC_FREE(ares);
1972 return ldb_request_done(req, LDB_ERR_OPERATIONS_ERROR);
1975 static PyObject *py_ldb_search_iterator(PyLdbObject *self, PyObject *args, PyObject *kwargs)
1977 PyObject *py_base = Py_None;
1978 int scope = LDB_SCOPE_DEFAULT;
1979 int timeout = 0;
1980 char *expr = NULL;
1981 PyObject *py_attrs = Py_None;
1982 PyObject *py_controls = Py_None;
1983 const char * const kwnames[] = { "base", "scope", "expression", "attrs", "controls", "timeout", NULL };
1984 int ret;
1985 const char **attrs;
1986 struct ldb_context *ldb_ctx;
1987 struct ldb_control **parsed_controls;
1988 struct ldb_dn *base;
1989 PyLdbSearchIteratorObject *py_iter;
1991 /* type "int" rather than "enum" for "scope" is intentional */
1992 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "|OizOOi",
1993 discard_const_p(char *, kwnames),
1994 &py_base, &scope, &expr, &py_attrs, &py_controls, &timeout))
1995 return NULL;
1997 py_iter = (PyLdbSearchIteratorObject *)PyLdbSearchIterator.tp_alloc(&PyLdbSearchIterator, 0);
1998 if (py_iter == NULL) {
1999 PyErr_NoMemory();
2000 return NULL;
2002 py_iter->ldb = self;
2003 Py_INCREF(self);
2004 ZERO_STRUCT(py_iter->state);
2005 py_iter->mem_ctx = talloc_new(NULL);
2006 if (py_iter->mem_ctx == NULL) {
2007 Py_DECREF(py_iter);
2008 PyErr_NoMemory();
2009 return NULL;
2012 ldb_ctx = pyldb_Ldb_AsLdbContext(self);
2014 if (py_attrs == Py_None) {
2015 attrs = NULL;
2016 } else {
2017 attrs = PyList_AsStrList(py_iter->mem_ctx, py_attrs, "attrs");
2018 if (attrs == NULL) {
2019 Py_DECREF(py_iter);
2020 PyErr_NoMemory();
2021 return NULL;
2025 if (py_base == Py_None) {
2026 base = ldb_get_default_basedn(ldb_ctx);
2027 } else {
2028 if (!pyldb_Object_AsDn(py_iter->mem_ctx, py_base, ldb_ctx, &base)) {
2029 Py_DECREF(py_iter);
2030 PyErr_NoMemory();
2031 return NULL;
2035 if (py_controls == Py_None) {
2036 parsed_controls = NULL;
2037 } else {
2038 const char **controls = NULL;
2040 controls = PyList_AsStrList(py_iter->mem_ctx,
2041 py_controls, "controls");
2042 if (controls == NULL) {
2043 Py_DECREF(py_iter);
2044 PyErr_NoMemory();
2045 return NULL;
2048 parsed_controls = ldb_parse_control_strings(ldb_ctx,
2049 py_iter->mem_ctx,
2050 controls);
2051 if (controls[0] != NULL && parsed_controls == NULL) {
2052 Py_DECREF(py_iter);
2053 PyErr_NoMemory();
2054 return NULL;
2056 talloc_free(controls);
2059 ret = ldb_build_search_req(&py_iter->state.req,
2060 ldb_ctx,
2061 py_iter->mem_ctx,
2062 base,
2063 scope,
2064 expr,
2065 attrs,
2066 parsed_controls,
2067 py_iter,
2068 py_ldb_search_iterator_callback,
2069 NULL);
2070 if (ret != LDB_SUCCESS) {
2071 Py_DECREF(py_iter);
2072 PyErr_SetLdbError(PyExc_LdbError, ret, ldb_ctx);
2073 return NULL;
2076 ldb_set_timeout(ldb_ctx, py_iter->state.req, timeout);
2078 ret = ldb_request(ldb_ctx, py_iter->state.req);
2079 if (ret != LDB_SUCCESS) {
2080 Py_DECREF(py_iter);
2081 PyErr_SetLdbError(PyExc_LdbError, ret, ldb_ctx);
2082 return NULL;
2085 return (PyObject *)py_iter;
2088 static PyObject *py_ldb_get_opaque(PyLdbObject *self, PyObject *args)
2090 char *name;
2091 void *data;
2093 if (!PyArg_ParseTuple(args, "s", &name))
2094 return NULL;
2096 data = ldb_get_opaque(pyldb_Ldb_AsLdbContext(self), name);
2098 if (data == NULL)
2099 Py_RETURN_NONE;
2101 /* FIXME: More interpretation */
2103 Py_RETURN_TRUE;
2106 static PyObject *py_ldb_set_opaque(PyLdbObject *self, PyObject *args)
2108 char *name;
2109 PyObject *data;
2111 if (!PyArg_ParseTuple(args, "sO", &name, &data))
2112 return NULL;
2114 /* FIXME: More interpretation */
2116 ldb_set_opaque(pyldb_Ldb_AsLdbContext(self), name, data);
2118 Py_RETURN_NONE;
2121 static PyObject *py_ldb_modules(PyLdbObject *self)
2123 struct ldb_context *ldb = pyldb_Ldb_AsLdbContext(self);
2124 PyObject *ret = PyList_New(0);
2125 struct ldb_module *mod;
2127 for (mod = ldb->modules; mod; mod = mod->next) {
2128 PyList_Append(ret, PyLdbModule_FromModule(mod));
2131 return ret;
2134 static PyObject *py_ldb_sequence_number(PyLdbObject *self, PyObject *args)
2136 struct ldb_context *ldb = pyldb_Ldb_AsLdbContext(self);
2137 int type, ret;
2138 uint64_t value;
2140 if (!PyArg_ParseTuple(args, "i", &type))
2141 return NULL;
2143 /* FIXME: More interpretation */
2145 ret = ldb_sequence_number(ldb, type, &value);
2147 PyErr_LDB_ERROR_IS_ERR_RAISE(PyExc_LdbError, ret, ldb);
2149 return PyLong_FromLongLong(value);
2153 static const struct ldb_dn_extended_syntax test_dn_syntax = {
2154 .name = "TEST",
2155 .read_fn = ldb_handler_copy,
2156 .write_clear_fn = ldb_handler_copy,
2157 .write_hex_fn = ldb_handler_copy,
2160 static PyObject *py_ldb_register_test_extensions(PyLdbObject *self)
2162 struct ldb_context *ldb = pyldb_Ldb_AsLdbContext(self);
2163 int ret;
2165 ret = ldb_dn_extended_add_syntax(ldb, LDB_ATTR_FLAG_FIXED, &test_dn_syntax);
2167 PyErr_LDB_ERROR_IS_ERR_RAISE(PyExc_LdbError, ret, ldb);
2169 Py_RETURN_NONE;
2173 static PyMethodDef py_ldb_methods[] = {
2174 { "set_debug", (PyCFunction)py_ldb_set_debug, METH_VARARGS,
2175 "S.set_debug(callback) -> None\n"
2176 "Set callback for LDB debug messages.\n"
2177 "The callback should accept a debug level and debug text." },
2178 { "set_create_perms", (PyCFunction)py_ldb_set_create_perms, METH_VARARGS,
2179 "S.set_create_perms(mode) -> None\n"
2180 "Set mode to use when creating new LDB files." },
2181 { "set_modules_dir", (PyCFunction)py_ldb_set_modules_dir, METH_VARARGS,
2182 "S.set_modules_dir(path) -> None\n"
2183 "Set path LDB should search for modules" },
2184 { "transaction_start", (PyCFunction)py_ldb_transaction_start, METH_NOARGS,
2185 "S.transaction_start() -> None\n"
2186 "Start a new transaction." },
2187 { "transaction_prepare_commit", (PyCFunction)py_ldb_transaction_prepare_commit, METH_NOARGS,
2188 "S.transaction_prepare_commit() -> None\n"
2189 "prepare to commit a new transaction (2-stage commit)." },
2190 { "transaction_commit", (PyCFunction)py_ldb_transaction_commit, METH_NOARGS,
2191 "S.transaction_commit() -> None\n"
2192 "commit a new transaction." },
2193 { "transaction_cancel", (PyCFunction)py_ldb_transaction_cancel, METH_NOARGS,
2194 "S.transaction_cancel() -> None\n"
2195 "cancel a new transaction." },
2196 { "setup_wellknown_attributes", (PyCFunction)py_ldb_setup_wellknown_attributes, METH_NOARGS,
2197 NULL },
2198 { "get_root_basedn", (PyCFunction)py_ldb_get_root_basedn, METH_NOARGS,
2199 NULL },
2200 { "get_schema_basedn", (PyCFunction)py_ldb_get_schema_basedn, METH_NOARGS,
2201 NULL },
2202 { "get_default_basedn", (PyCFunction)py_ldb_get_default_basedn, METH_NOARGS,
2203 NULL },
2204 { "get_config_basedn", (PyCFunction)py_ldb_get_config_basedn, METH_NOARGS,
2205 NULL },
2206 { "connect", (PyCFunction)py_ldb_connect, METH_VARARGS|METH_KEYWORDS,
2207 "S.connect(url, flags=0, options=None) -> None\n"
2208 "Connect to a LDB URL." },
2209 { "modify", (PyCFunction)py_ldb_modify, METH_VARARGS|METH_KEYWORDS,
2210 "S.modify(message, controls=None, validate=False) -> None\n"
2211 "Modify an entry." },
2212 { "add", (PyCFunction)py_ldb_add, METH_VARARGS|METH_KEYWORDS,
2213 "S.add(message, controls=None) -> None\n"
2214 "Add an entry." },
2215 { "delete", (PyCFunction)py_ldb_delete, METH_VARARGS|METH_KEYWORDS,
2216 "S.delete(dn, controls=None) -> None\n"
2217 "Remove an entry." },
2218 { "rename", (PyCFunction)py_ldb_rename, METH_VARARGS|METH_KEYWORDS,
2219 "S.rename(old_dn, new_dn, controls=None) -> None\n"
2220 "Rename an entry." },
2221 { "search", (PyCFunction)py_ldb_search, METH_VARARGS|METH_KEYWORDS,
2222 "S.search(base=None, scope=None, expression=None, attrs=None, controls=None) -> result\n"
2223 "Search in a database.\n"
2224 "\n"
2225 ":param base: Optional base DN to search\n"
2226 ":param scope: Search scope (SCOPE_BASE, SCOPE_ONELEVEL or SCOPE_SUBTREE)\n"
2227 ":param expression: Optional search expression\n"
2228 ":param attrs: Attributes to return (defaults to all)\n"
2229 ":param controls: Optional list of controls\n"
2230 ":return: ldb.Result object\n"
2232 { "search_iterator", (PyCFunction)py_ldb_search_iterator, METH_VARARGS|METH_KEYWORDS,
2233 "S.search_iterator(base=None, scope=None, expression=None, attrs=None, controls=None, timeout=None) -> iterator\n"
2234 "Search in a database.\n"
2235 "\n"
2236 ":param base: Optional base DN to search\n"
2237 ":param scope: Search scope (SCOPE_BASE, SCOPE_ONELEVEL or SCOPE_SUBTREE)\n"
2238 ":param expression: Optional search expression\n"
2239 ":param attrs: Attributes to return (defaults to all)\n"
2240 ":param controls: Optional list of controls\n"
2241 ":param timeout: Optional timeout in seconds (defaults to 300), 0 means the default, -1 no timeout\n"
2242 ":return: ldb.SearchIterator object that provides results when they arrive\n"
2244 { "schema_attribute_remove", (PyCFunction)py_ldb_schema_attribute_remove, METH_VARARGS,
2245 NULL },
2246 { "schema_attribute_add", (PyCFunction)py_ldb_schema_attribute_add, METH_VARARGS,
2247 NULL },
2248 { "schema_format_value", (PyCFunction)py_ldb_schema_format_value, METH_VARARGS,
2249 NULL },
2250 { "parse_ldif", (PyCFunction)py_ldb_parse_ldif, METH_VARARGS,
2251 "S.parse_ldif(ldif) -> iter(messages)\n"
2252 "Parse a string formatted using LDIF." },
2253 { "write_ldif", (PyCFunction)py_ldb_write_ldif, METH_VARARGS,
2254 "S.write_ldif(message, changetype) -> ldif\n"
2255 "Print the message as a string formatted using LDIF." },
2256 { "msg_diff", (PyCFunction)py_ldb_msg_diff, METH_VARARGS,
2257 "S.msg_diff(Message) -> Message\n"
2258 "Return an LDB Message of the difference between two Message objects." },
2259 { "get_opaque", (PyCFunction)py_ldb_get_opaque, METH_VARARGS,
2260 "S.get_opaque(name) -> value\n"
2261 "Get an opaque value set on this LDB connection. \n"
2262 ":note: The returned value may not be useful in Python."
2264 { "set_opaque", (PyCFunction)py_ldb_set_opaque, METH_VARARGS,
2265 "S.set_opaque(name, value) -> None\n"
2266 "Set an opaque value on this LDB connection. \n"
2267 ":note: Passing incorrect values may cause crashes." },
2268 { "modules", (PyCFunction)py_ldb_modules, METH_NOARGS,
2269 "S.modules() -> list\n"
2270 "Return the list of modules on this LDB connection " },
2271 { "sequence_number", (PyCFunction)py_ldb_sequence_number, METH_VARARGS,
2272 "S.sequence_number(type) -> value\n"
2273 "Return the value of the sequence according to the requested type" },
2274 { "_register_test_extensions", (PyCFunction)py_ldb_register_test_extensions, METH_NOARGS,
2275 "S._register_test_extensions() -> None\n"
2276 "Register internal extensions used in testing" },
2277 { NULL },
2280 static PyObject *PyLdbModule_FromModule(struct ldb_module *mod)
2282 PyLdbModuleObject *ret;
2284 ret = (PyLdbModuleObject *)PyLdbModule.tp_alloc(&PyLdbModule, 0);
2285 if (ret == NULL) {
2286 PyErr_NoMemory();
2287 return NULL;
2289 ret->mem_ctx = talloc_new(NULL);
2290 ret->mod = talloc_reference(ret->mem_ctx, mod);
2291 return (PyObject *)ret;
2294 static PyObject *py_ldb_get_firstmodule(PyLdbObject *self, void *closure)
2296 struct ldb_module *mod = pyldb_Ldb_AsLdbContext(self)->modules;
2297 if (mod == NULL) {
2298 Py_RETURN_NONE;
2300 return PyLdbModule_FromModule(mod);
2303 static PyGetSetDef py_ldb_getset[] = {
2304 { discard_const_p(char, "firstmodule"), (getter)py_ldb_get_firstmodule, NULL, NULL },
2305 { NULL }
2308 static int py_ldb_contains(PyLdbObject *self, PyObject *obj)
2310 struct ldb_context *ldb_ctx = pyldb_Ldb_AsLdbContext(self);
2311 struct ldb_dn *dn;
2312 struct ldb_result *result;
2313 unsigned int count;
2314 int ret;
2316 if (!pyldb_Object_AsDn(ldb_ctx, obj, ldb_ctx, &dn)) {
2317 return -1;
2320 ret = ldb_search(ldb_ctx, ldb_ctx, &result, dn, LDB_SCOPE_BASE, NULL,
2321 NULL);
2322 if (ret != LDB_SUCCESS) {
2323 PyErr_SetLdbError(PyExc_LdbError, ret, ldb_ctx);
2324 return -1;
2327 count = result->count;
2329 talloc_free(result);
2331 if (count > 1) {
2332 PyErr_Format(PyExc_RuntimeError,
2333 "Searching for [%s] dn gave %u results!",
2334 ldb_dn_get_linearized(dn),
2335 count);
2336 return -1;
2339 return count;
2342 static PySequenceMethods py_ldb_seq = {
2343 .sq_contains = (objobjproc)py_ldb_contains,
2346 static PyObject *PyLdb_FromLdbContext(struct ldb_context *ldb_ctx)
2348 PyLdbObject *ret;
2350 ret = (PyLdbObject *)PyLdb.tp_alloc(&PyLdb, 0);
2351 if (ret == NULL) {
2352 PyErr_NoMemory();
2353 return NULL;
2355 ret->mem_ctx = talloc_new(NULL);
2356 ret->ldb_ctx = talloc_reference(ret->mem_ctx, ldb_ctx);
2357 return (PyObject *)ret;
2360 static void py_ldb_dealloc(PyLdbObject *self)
2362 talloc_free(self->mem_ctx);
2363 Py_TYPE(self)->tp_free(self);
2366 static PyTypeObject PyLdb = {
2367 .tp_name = "ldb.Ldb",
2368 .tp_methods = py_ldb_methods,
2369 .tp_repr = (reprfunc)py_ldb_repr,
2370 .tp_new = py_ldb_new,
2371 .tp_init = (initproc)py_ldb_init,
2372 .tp_dealloc = (destructor)py_ldb_dealloc,
2373 .tp_getset = py_ldb_getset,
2374 .tp_getattro = PyObject_GenericGetAttr,
2375 .tp_basicsize = sizeof(PyLdbObject),
2376 .tp_doc = "Connection to a LDB database.",
2377 .tp_as_sequence = &py_ldb_seq,
2378 .tp_flags = Py_TPFLAGS_DEFAULT|Py_TPFLAGS_BASETYPE,
2381 static void py_ldb_result_dealloc(PyLdbResultObject *self)
2383 talloc_free(self->mem_ctx);
2384 Py_DECREF(self->msgs);
2385 Py_DECREF(self->referals);
2386 Py_DECREF(self->controls);
2387 Py_TYPE(self)->tp_free(self);
2390 static PyObject *py_ldb_result_get_msgs(PyLdbResultObject *self, void *closure)
2392 Py_INCREF(self->msgs);
2393 return self->msgs;
2396 static PyObject *py_ldb_result_get_controls(PyLdbResultObject *self, void *closure)
2398 Py_INCREF(self->controls);
2399 return self->controls;
2402 static PyObject *py_ldb_result_get_referals(PyLdbResultObject *self, void *closure)
2404 Py_INCREF(self->referals);
2405 return self->referals;
2408 static PyObject *py_ldb_result_get_count(PyLdbResultObject *self, void *closure)
2410 Py_ssize_t size;
2411 if (self->msgs == NULL) {
2412 PyErr_SetString(PyExc_AttributeError, "Count attribute is meaningless in this context");
2413 return NULL;
2415 size = PyList_Size(self->msgs);
2416 return PyInt_FromLong(size);
2419 static PyGetSetDef py_ldb_result_getset[] = {
2420 { discard_const_p(char, "controls"), (getter)py_ldb_result_get_controls, NULL, NULL },
2421 { discard_const_p(char, "msgs"), (getter)py_ldb_result_get_msgs, NULL, NULL },
2422 { discard_const_p(char, "referals"), (getter)py_ldb_result_get_referals, NULL, NULL },
2423 { discard_const_p(char, "count"), (getter)py_ldb_result_get_count, NULL, NULL },
2424 { NULL }
2427 static PyObject *py_ldb_result_iter(PyLdbResultObject *self)
2429 return PyObject_GetIter(self->msgs);
2432 static Py_ssize_t py_ldb_result_len(PyLdbResultObject *self)
2434 return PySequence_Size(self->msgs);
2437 static PyObject *py_ldb_result_find(PyLdbResultObject *self, Py_ssize_t idx)
2439 return PySequence_GetItem(self->msgs, idx);
2442 static PySequenceMethods py_ldb_result_seq = {
2443 .sq_length = (lenfunc)py_ldb_result_len,
2444 .sq_item = (ssizeargfunc)py_ldb_result_find,
2447 static PyObject *py_ldb_result_repr(PyLdbObject *self)
2449 return PyStr_FromString("<ldb result>");
2453 static PyTypeObject PyLdbResult = {
2454 .tp_name = "ldb.Result",
2455 .tp_repr = (reprfunc)py_ldb_result_repr,
2456 .tp_dealloc = (destructor)py_ldb_result_dealloc,
2457 .tp_iter = (getiterfunc)py_ldb_result_iter,
2458 .tp_getset = py_ldb_result_getset,
2459 .tp_getattro = PyObject_GenericGetAttr,
2460 .tp_basicsize = sizeof(PyLdbResultObject),
2461 .tp_as_sequence = &py_ldb_result_seq,
2462 .tp_doc = "LDB result.",
2463 .tp_flags = Py_TPFLAGS_DEFAULT|Py_TPFLAGS_BASETYPE,
2466 static void py_ldb_search_iterator_dealloc(PyLdbSearchIteratorObject *self)
2468 Py_XDECREF(self->state.exception);
2469 TALLOC_FREE(self->mem_ctx);
2470 ZERO_STRUCT(self->state);
2471 Py_DECREF(self->ldb);
2472 Py_TYPE(self)->tp_free(self);
2475 static PyObject *py_ldb_search_iterator_next(PyLdbSearchIteratorObject *self)
2477 PyObject *py_ret = NULL;
2479 if (self->state.req == NULL) {
2480 PyErr_SetString(PyExc_RuntimeError,
2481 "ldb.SearchIterator request already finished");
2482 return NULL;
2486 * TODO: do we want a non-blocking mode?
2487 * In future we may add an optional 'nonblocking'
2488 * argument to search_iterator().
2490 * For now we keep it simple and wait for at
2491 * least one reply.
2494 while (self->state.next == NULL) {
2495 int ret;
2497 if (self->state.result != NULL) {
2499 * We (already) got a final result from the server.
2501 * We stop the iteration and let
2502 * py_ldb_search_iterator_result() will deliver
2503 * the result details.
2505 TALLOC_FREE(self->state.req);
2506 PyErr_SetNone(PyExc_StopIteration);
2507 return NULL;
2510 ret = ldb_wait(self->state.req->handle, LDB_WAIT_NONE);
2511 if (ret != LDB_SUCCESS) {
2512 struct ldb_context *ldb_ctx;
2513 TALLOC_FREE(self->state.req);
2514 ldb_ctx = pyldb_Ldb_AsLdbContext(self->ldb);
2516 * We stop the iteration and let
2517 * py_ldb_search_iterator_result() will deliver
2518 * the exception.
2520 self->state.exception = Py_BuildValue(discard_const_p(char, "(i,s)"),
2521 ret, ldb_errstring(ldb_ctx));
2522 PyErr_SetNone(PyExc_StopIteration);
2523 return NULL;
2527 py_ret = self->state.next->obj;
2528 self->state.next->obj = NULL;
2529 /* no TALLOC_FREE() as self->state.next is a list */
2530 talloc_free(self->state.next);
2531 return py_ret;
2534 static PyObject *py_ldb_search_iterator_result(PyLdbSearchIteratorObject *self)
2536 PyObject *py_ret = NULL;
2538 if (self->state.req != NULL) {
2539 PyErr_SetString(PyExc_RuntimeError,
2540 "ldb.SearchIterator request running");
2541 return NULL;
2544 if (self->state.next != NULL) {
2545 PyErr_SetString(PyExc_RuntimeError,
2546 "ldb.SearchIterator not fully consumed.");
2547 return NULL;
2550 if (self->state.exception != NULL) {
2551 PyErr_SetObject(PyExc_LdbError, self->state.exception);
2552 self->state.exception = NULL;
2553 return NULL;
2556 if (self->state.result == NULL) {
2557 PyErr_SetString(PyExc_RuntimeError,
2558 "ldb.SearchIterator result already consumed");
2559 return NULL;
2562 py_ret = self->state.result->obj;
2563 self->state.result->obj = NULL;
2564 TALLOC_FREE(self->state.result);
2565 return py_ret;
2568 static PyObject *py_ldb_search_iterator_abandon(PyLdbSearchIteratorObject *self)
2570 if (self->state.req == NULL) {
2571 PyErr_SetString(PyExc_RuntimeError,
2572 "ldb.SearchIterator request already finished");
2573 return NULL;
2576 Py_XDECREF(self->state.exception);
2577 TALLOC_FREE(self->mem_ctx);
2578 ZERO_STRUCT(self->state);
2579 Py_RETURN_NONE;
2582 static PyMethodDef py_ldb_search_iterator_methods[] = {
2583 { "result", (PyCFunction)py_ldb_search_iterator_result, METH_NOARGS,
2584 "S.result() -> ldb.Result (without msgs and referrals)\n" },
2585 { "abandon", (PyCFunction)py_ldb_search_iterator_abandon, METH_NOARGS,
2586 "S.abandon()\n" },
2587 { NULL }
2590 static PyObject *py_ldb_search_iterator_repr(PyLdbSearchIteratorObject *self)
2592 return PyStr_FromString("<ldb search iterator>");
2595 static PyTypeObject PyLdbSearchIterator = {
2596 .tp_name = "ldb.SearchIterator",
2597 .tp_repr = (reprfunc)py_ldb_search_iterator_repr,
2598 .tp_dealloc = (destructor)py_ldb_search_iterator_dealloc,
2599 .tp_iter = PyObject_SelfIter,
2600 .tp_iternext = (iternextfunc)py_ldb_search_iterator_next,
2601 .tp_methods = py_ldb_search_iterator_methods,
2602 .tp_basicsize = sizeof(PyLdbSearchIteratorObject),
2603 .tp_doc = "LDB search_iterator.",
2604 .tp_flags = Py_TPFLAGS_DEFAULT|Py_TPFLAGS_BASETYPE,
2607 static PyObject *py_ldb_module_repr(PyLdbModuleObject *self)
2609 return PyStr_FromFormat("<ldb module '%s'>",
2610 pyldb_Module_AsModule(self)->ops->name);
2613 static PyObject *py_ldb_module_str(PyLdbModuleObject *self)
2615 return PyStr_FromString(pyldb_Module_AsModule(self)->ops->name);
2618 static PyObject *py_ldb_module_start_transaction(PyLdbModuleObject *self)
2620 pyldb_Module_AsModule(self)->ops->start_transaction(pyldb_Module_AsModule(self));
2621 Py_RETURN_NONE;
2624 static PyObject *py_ldb_module_end_transaction(PyLdbModuleObject *self)
2626 pyldb_Module_AsModule(self)->ops->end_transaction(pyldb_Module_AsModule(self));
2627 Py_RETURN_NONE;
2630 static PyObject *py_ldb_module_del_transaction(PyLdbModuleObject *self)
2632 pyldb_Module_AsModule(self)->ops->del_transaction(pyldb_Module_AsModule(self));
2633 Py_RETURN_NONE;
2636 static PyObject *py_ldb_module_search(PyLdbModuleObject *self, PyObject *args, PyObject *kwargs)
2638 PyObject *py_base, *py_tree, *py_attrs, *py_ret;
2639 int ret, scope;
2640 struct ldb_request *req;
2641 const char * const kwnames[] = { "base", "scope", "tree", "attrs", NULL };
2642 struct ldb_module *mod;
2643 const char * const*attrs;
2645 /* type "int" rather than "enum" for "scope" is intentional */
2646 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "O!iOO",
2647 discard_const_p(char *, kwnames),
2648 &PyLdbDn, &py_base, &scope, &py_tree, &py_attrs))
2649 return NULL;
2651 mod = self->mod;
2653 if (py_attrs == Py_None) {
2654 attrs = NULL;
2655 } else {
2656 attrs = PyList_AsStrList(NULL, py_attrs, "attrs");
2657 if (attrs == NULL)
2658 return NULL;
2661 ret = ldb_build_search_req(&req, mod->ldb, NULL, pyldb_Dn_AsDn(py_base),
2662 scope, NULL /* expr */, attrs,
2663 NULL /* controls */, NULL, NULL, NULL);
2665 talloc_steal(req, attrs);
2667 PyErr_LDB_ERROR_IS_ERR_RAISE(PyExc_LdbError, ret, mod->ldb);
2669 req->op.search.res = NULL;
2671 ret = mod->ops->search(mod, req);
2673 PyErr_LDB_ERROR_IS_ERR_RAISE(PyExc_LdbError, ret, mod->ldb);
2675 py_ret = PyLdbResult_FromResult(req->op.search.res);
2677 talloc_free(req);
2679 return py_ret;
2683 static PyObject *py_ldb_module_add(PyLdbModuleObject *self, PyObject *args)
2685 struct ldb_request *req;
2686 PyObject *py_message;
2687 int ret;
2688 struct ldb_module *mod;
2690 if (!PyArg_ParseTuple(args, "O!", &PyLdbMessage, &py_message))
2691 return NULL;
2693 req = talloc_zero(NULL, struct ldb_request);
2694 req->operation = LDB_ADD;
2695 req->op.add.message = pyldb_Message_AsMessage(py_message);
2697 mod = pyldb_Module_AsModule(self);
2698 ret = mod->ops->add(mod, req);
2700 PyErr_LDB_ERROR_IS_ERR_RAISE(PyExc_LdbError, ret, mod->ldb);
2702 Py_RETURN_NONE;
2705 static PyObject *py_ldb_module_modify(PyLdbModuleObject *self, PyObject *args)
2707 int ret;
2708 struct ldb_request *req;
2709 PyObject *py_message;
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_MODIFY;
2717 req->op.mod.message = pyldb_Message_AsMessage(py_message);
2719 mod = pyldb_Module_AsModule(self);
2720 ret = mod->ops->modify(mod, req);
2722 PyErr_LDB_ERROR_IS_ERR_RAISE(PyExc_LdbError, ret, mod->ldb);
2724 Py_RETURN_NONE;
2727 static PyObject *py_ldb_module_delete(PyLdbModuleObject *self, PyObject *args)
2729 int ret;
2730 struct ldb_request *req;
2731 PyObject *py_dn;
2733 if (!PyArg_ParseTuple(args, "O!", &PyLdbDn, &py_dn))
2734 return NULL;
2736 req = talloc_zero(NULL, struct ldb_request);
2737 req->operation = LDB_DELETE;
2738 req->op.del.dn = pyldb_Dn_AsDn(py_dn);
2740 ret = pyldb_Module_AsModule(self)->ops->del(pyldb_Module_AsModule(self), req);
2742 PyErr_LDB_ERROR_IS_ERR_RAISE(PyExc_LdbError, ret, NULL);
2744 Py_RETURN_NONE;
2747 static PyObject *py_ldb_module_rename(PyLdbModuleObject *self, PyObject *args)
2749 int ret;
2750 struct ldb_request *req;
2751 PyObject *py_dn1, *py_dn2;
2753 if (!PyArg_ParseTuple(args, "O!O!", &PyLdbDn, &py_dn1, &PyLdbDn, &py_dn2))
2754 return NULL;
2756 req = talloc_zero(NULL, struct ldb_request);
2758 req->operation = LDB_RENAME;
2759 req->op.rename.olddn = pyldb_Dn_AsDn(py_dn1);
2760 req->op.rename.newdn = pyldb_Dn_AsDn(py_dn2);
2762 ret = pyldb_Module_AsModule(self)->ops->rename(pyldb_Module_AsModule(self), req);
2764 PyErr_LDB_ERROR_IS_ERR_RAISE(PyExc_LdbError, ret, NULL);
2766 Py_RETURN_NONE;
2769 static PyMethodDef py_ldb_module_methods[] = {
2770 { "search", (PyCFunction)py_ldb_module_search, METH_VARARGS|METH_KEYWORDS, NULL },
2771 { "add", (PyCFunction)py_ldb_module_add, METH_VARARGS, NULL },
2772 { "modify", (PyCFunction)py_ldb_module_modify, METH_VARARGS, NULL },
2773 { "rename", (PyCFunction)py_ldb_module_rename, METH_VARARGS, NULL },
2774 { "delete", (PyCFunction)py_ldb_module_delete, METH_VARARGS, NULL },
2775 { "start_transaction", (PyCFunction)py_ldb_module_start_transaction, METH_NOARGS, NULL },
2776 { "end_transaction", (PyCFunction)py_ldb_module_end_transaction, METH_NOARGS, NULL },
2777 { "del_transaction", (PyCFunction)py_ldb_module_del_transaction, METH_NOARGS, NULL },
2778 { NULL },
2781 static void py_ldb_module_dealloc(PyLdbModuleObject *self)
2783 talloc_free(self->mem_ctx);
2784 PyObject_Del(self);
2787 static PyTypeObject PyLdbModule = {
2788 .tp_name = "ldb.LdbModule",
2789 .tp_methods = py_ldb_module_methods,
2790 .tp_repr = (reprfunc)py_ldb_module_repr,
2791 .tp_str = (reprfunc)py_ldb_module_str,
2792 .tp_basicsize = sizeof(PyLdbModuleObject),
2793 .tp_dealloc = (destructor)py_ldb_module_dealloc,
2794 .tp_flags = Py_TPFLAGS_DEFAULT,
2795 .tp_doc = "LDB module (extension)",
2800 * Create a ldb_message_element from a Python object.
2802 * This will accept any sequence objects that contains strings, or
2803 * a string object.
2805 * A reference to set_obj will be borrowed.
2807 * @param mem_ctx Memory context
2808 * @param set_obj Python object to convert
2809 * @param flags ldb_message_element flags to set
2810 * @param attr_name Name of the attribute
2811 * @return New ldb_message_element, allocated as child of mem_ctx
2813 static struct ldb_message_element *PyObject_AsMessageElement(
2814 TALLOC_CTX *mem_ctx,
2815 PyObject *set_obj,
2816 unsigned int flags,
2817 const char *attr_name)
2819 struct ldb_message_element *me;
2820 const char *msg = NULL;
2821 Py_ssize_t size;
2822 int result;
2824 if (pyldb_MessageElement_Check(set_obj)) {
2825 PyLdbMessageElementObject *set_obj_as_me = (PyLdbMessageElementObject *)set_obj;
2826 /* We have to talloc_reference() the memory context, not the pointer
2827 * which may not actually be it's own context */
2828 if (talloc_reference(mem_ctx, set_obj_as_me->mem_ctx)) {
2829 return pyldb_MessageElement_AsMessageElement(set_obj);
2831 return NULL;
2834 me = talloc(mem_ctx, struct ldb_message_element);
2835 if (me == NULL) {
2836 PyErr_NoMemory();
2837 return NULL;
2840 me->name = talloc_strdup(me, attr_name);
2841 me->flags = flags;
2842 if (PyBytes_Check(set_obj) || PyStr_Check(set_obj)) {
2843 me->num_values = 1;
2844 me->values = talloc_array(me, struct ldb_val, me->num_values);
2845 if (PyBytes_Check(set_obj)) {
2846 char *_msg = NULL;
2847 result = PyBytes_AsStringAndSize(set_obj, &_msg, &size);
2848 if (result != 0) {
2849 talloc_free(me);
2850 return NULL;
2852 msg = _msg;
2853 } else {
2854 msg = PyStr_AsUTF8AndSize(set_obj, &size);
2855 if (msg == NULL) {
2856 talloc_free(me);
2857 return NULL;
2860 me->values[0].data = talloc_memdup(me,
2861 (const uint8_t *)msg,
2862 size+1);
2863 me->values[0].length = size;
2864 } else if (PySequence_Check(set_obj)) {
2865 Py_ssize_t i;
2866 me->num_values = PySequence_Size(set_obj);
2867 me->values = talloc_array(me, struct ldb_val, me->num_values);
2868 for (i = 0; i < me->num_values; i++) {
2869 PyObject *obj = PySequence_GetItem(set_obj, i);
2870 if (PyBytes_Check(obj)) {
2871 char *_msg = NULL;
2872 result = PyBytes_AsStringAndSize(obj, &_msg, &size);
2873 if (result != 0) {
2874 talloc_free(me);
2875 return NULL;
2877 msg = _msg;
2878 } else if (PyStr_Check(obj)) {
2879 msg = PyStr_AsUTF8AndSize(obj, &size);
2880 if (msg == NULL) {
2881 talloc_free(me);
2882 return NULL;
2884 } else {
2885 PyErr_Format(PyExc_TypeError,
2886 "Expected string as element %zd in list", i);
2887 talloc_free(me);
2888 return NULL;
2890 me->values[i].data = talloc_memdup(me,
2891 (const uint8_t *)msg,
2892 size+1);
2893 me->values[i].length = size;
2895 } else {
2896 PyErr_Format(PyExc_TypeError,
2897 "String or List type expected for '%s' attribute", attr_name);
2898 talloc_free(me);
2899 me = NULL;
2902 return me;
2906 static PyObject *ldb_msg_element_to_set(struct ldb_context *ldb_ctx,
2907 struct ldb_message_element *me)
2909 Py_ssize_t i;
2910 PyObject *result;
2912 /* Python << 2.5 doesn't have PySet_New and PySet_Add. */
2913 result = PyList_New(me->num_values);
2915 for (i = 0; i < me->num_values; i++) {
2916 PyList_SetItem(result, i,
2917 PyObject_FromLdbValue(&me->values[i]));
2920 return result;
2923 static PyObject *py_ldb_msg_element_get(PyLdbMessageElementObject *self, PyObject *args)
2925 unsigned int i;
2926 if (!PyArg_ParseTuple(args, "I", &i))
2927 return NULL;
2928 if (i >= pyldb_MessageElement_AsMessageElement(self)->num_values)
2929 Py_RETURN_NONE;
2931 return PyObject_FromLdbValue(&(pyldb_MessageElement_AsMessageElement(self)->values[i]));
2934 static PyObject *py_ldb_msg_element_flags(PyLdbMessageElementObject *self, PyObject *args)
2936 struct ldb_message_element *el = pyldb_MessageElement_AsMessageElement(self);
2937 return PyInt_FromLong(el->flags);
2940 static PyObject *py_ldb_msg_element_set_flags(PyLdbMessageElementObject *self, PyObject *args)
2942 unsigned int flags;
2943 struct ldb_message_element *el;
2944 if (!PyArg_ParseTuple(args, "I", &flags))
2945 return NULL;
2947 el = pyldb_MessageElement_AsMessageElement(self);
2948 el->flags = flags;
2949 Py_RETURN_NONE;
2952 static PyMethodDef py_ldb_msg_element_methods[] = {
2953 { "get", (PyCFunction)py_ldb_msg_element_get, METH_VARARGS, NULL },
2954 { "set_flags", (PyCFunction)py_ldb_msg_element_set_flags, METH_VARARGS, NULL },
2955 { "flags", (PyCFunction)py_ldb_msg_element_flags, METH_NOARGS, NULL },
2956 { NULL },
2959 static Py_ssize_t py_ldb_msg_element_len(PyLdbMessageElementObject *self)
2961 return pyldb_MessageElement_AsMessageElement(self)->num_values;
2964 static PyObject *py_ldb_msg_element_find(PyLdbMessageElementObject *self, Py_ssize_t idx)
2966 struct ldb_message_element *el = pyldb_MessageElement_AsMessageElement(self);
2967 if (idx < 0 || idx >= el->num_values) {
2968 PyErr_SetString(PyExc_IndexError, "Out of range");
2969 return NULL;
2971 return PyBytes_FromStringAndSize((char *)el->values[idx].data, el->values[idx].length);
2974 static PySequenceMethods py_ldb_msg_element_seq = {
2975 .sq_length = (lenfunc)py_ldb_msg_element_len,
2976 .sq_item = (ssizeargfunc)py_ldb_msg_element_find,
2979 static PyObject *py_ldb_msg_element_richcmp(PyObject *self, PyObject *other, int op)
2981 int ret;
2982 if (!pyldb_MessageElement_Check(other)) {
2983 Py_INCREF(Py_NotImplemented);
2984 return Py_NotImplemented;
2986 ret = ldb_msg_element_compare(pyldb_MessageElement_AsMessageElement(self),
2987 pyldb_MessageElement_AsMessageElement(other));
2988 return richcmp(ret, op);
2991 static PyObject *py_ldb_msg_element_iter(PyLdbMessageElementObject *self)
2993 PyObject *el = ldb_msg_element_to_set(NULL,
2994 pyldb_MessageElement_AsMessageElement(self));
2995 PyObject *ret = PyObject_GetIter(el);
2996 Py_DECREF(el);
2997 return ret;
3000 static PyObject *PyLdbMessageElement_FromMessageElement(struct ldb_message_element *el, TALLOC_CTX *mem_ctx)
3002 PyLdbMessageElementObject *ret;
3003 ret = PyObject_New(PyLdbMessageElementObject, &PyLdbMessageElement);
3004 if (ret == NULL) {
3005 PyErr_NoMemory();
3006 return NULL;
3008 ret->mem_ctx = talloc_new(NULL);
3009 if (talloc_reference(ret->mem_ctx, mem_ctx) == NULL) {
3010 PyErr_NoMemory();
3011 return NULL;
3013 ret->el = el;
3014 return (PyObject *)ret;
3017 static PyObject *py_ldb_msg_element_new(PyTypeObject *type, PyObject *args, PyObject *kwargs)
3019 PyObject *py_elements = NULL;
3020 struct ldb_message_element *el;
3021 unsigned int flags = 0;
3022 char *name = NULL;
3023 const char * const kwnames[] = { "elements", "flags", "name", NULL };
3024 PyLdbMessageElementObject *ret;
3025 TALLOC_CTX *mem_ctx;
3026 const char *msg = NULL;
3027 Py_ssize_t size;
3028 int result;
3030 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "|OIs",
3031 discard_const_p(char *, kwnames),
3032 &py_elements, &flags, &name))
3033 return NULL;
3035 mem_ctx = talloc_new(NULL);
3036 if (mem_ctx == NULL) {
3037 PyErr_NoMemory();
3038 return NULL;
3041 el = talloc_zero(mem_ctx, struct ldb_message_element);
3042 if (el == NULL) {
3043 PyErr_NoMemory();
3044 talloc_free(mem_ctx);
3045 return NULL;
3048 if (py_elements != NULL) {
3049 Py_ssize_t i;
3050 if (PyBytes_Check(py_elements) || PyStr_Check(py_elements)) {
3051 char *_msg = NULL;
3052 el->num_values = 1;
3053 el->values = talloc_array(el, struct ldb_val, 1);
3054 if (el->values == NULL) {
3055 talloc_free(mem_ctx);
3056 PyErr_NoMemory();
3057 return NULL;
3059 if (PyBytes_Check(py_elements)) {
3060 result = PyBytes_AsStringAndSize(py_elements, &_msg, &size);
3061 msg = _msg;
3062 } else {
3063 msg = PyStr_AsUTF8AndSize(py_elements, &size);
3064 result = (msg == NULL) ? -1 : 0;
3066 if (result != 0) {
3067 talloc_free(mem_ctx);
3068 return NULL;
3070 el->values[0].data = talloc_memdup(el->values,
3071 (const uint8_t *)msg, size + 1);
3072 el->values[0].length = size;
3073 } else if (PySequence_Check(py_elements)) {
3074 el->num_values = PySequence_Size(py_elements);
3075 el->values = talloc_array(el, struct ldb_val, el->num_values);
3076 if (el->values == NULL) {
3077 talloc_free(mem_ctx);
3078 PyErr_NoMemory();
3079 return NULL;
3081 for (i = 0; i < el->num_values; i++) {
3082 PyObject *item = PySequence_GetItem(py_elements, i);
3083 if (item == NULL) {
3084 talloc_free(mem_ctx);
3085 return NULL;
3087 if (PyBytes_Check(item)) {
3088 char *_msg = NULL;
3089 result = PyBytes_AsStringAndSize(item, &_msg, &size);
3090 msg = _msg;
3091 } else if (PyStr_Check(item)) {
3092 msg = PyStr_AsUTF8AndSize(item, &size);
3093 result = (msg == NULL) ? -1 : 0;
3094 } else {
3095 PyErr_Format(PyExc_TypeError,
3096 "Expected string as element %zd in list", i);
3097 result = -1;
3099 if (result != 0) {
3100 talloc_free(mem_ctx);
3101 return NULL;
3103 el->values[i].data = talloc_memdup(el,
3104 (const uint8_t *)msg, size+1);
3105 el->values[i].length = size;
3107 } else {
3108 PyErr_SetString(PyExc_TypeError,
3109 "Expected string or list");
3110 talloc_free(mem_ctx);
3111 return NULL;
3115 el->flags = flags;
3116 el->name = talloc_strdup(el, name);
3118 ret = PyObject_New(PyLdbMessageElementObject, type);
3119 if (ret == NULL) {
3120 talloc_free(mem_ctx);
3121 return NULL;
3124 ret->mem_ctx = mem_ctx;
3125 ret->el = el;
3126 return (PyObject *)ret;
3129 static PyObject *py_ldb_msg_element_repr(PyLdbMessageElementObject *self)
3131 char *element_str = NULL;
3132 Py_ssize_t i;
3133 struct ldb_message_element *el = pyldb_MessageElement_AsMessageElement(self);
3134 PyObject *ret, *repr;
3136 for (i = 0; i < el->num_values; i++) {
3137 PyObject *o = py_ldb_msg_element_find(self, i);
3138 repr = PyObject_Repr(o);
3139 if (element_str == NULL)
3140 element_str = talloc_strdup(NULL, PyStr_AsUTF8(repr));
3141 else
3142 element_str = talloc_asprintf_append(element_str, ",%s", PyStr_AsUTF8(repr));
3143 Py_DECREF(repr);
3146 if (element_str != NULL) {
3147 ret = PyStr_FromFormat("MessageElement([%s])", element_str);
3148 talloc_free(element_str);
3149 } else {
3150 ret = PyStr_FromString("MessageElement([])");
3153 return ret;
3156 static PyObject *py_ldb_msg_element_str(PyLdbMessageElementObject *self)
3158 struct ldb_message_element *el = pyldb_MessageElement_AsMessageElement(self);
3160 if (el->num_values == 1)
3161 return PyStr_FromStringAndSize((char *)el->values[0].data, el->values[0].length);
3162 else
3163 Py_RETURN_NONE;
3166 static void py_ldb_msg_element_dealloc(PyLdbMessageElementObject *self)
3168 talloc_free(self->mem_ctx);
3169 PyObject_Del(self);
3172 static PyObject *py_ldb_msg_element_get_text(PyObject *self, void *closure)
3174 return wrap_text("MessageElementTextWrapper", self);
3177 static PyGetSetDef py_ldb_msg_element_getset[] = {
3178 { discard_const_p(char, "text"), (getter)py_ldb_msg_element_get_text, NULL, NULL },
3179 { NULL }
3182 static PyTypeObject PyLdbMessageElement = {
3183 .tp_name = "ldb.MessageElement",
3184 .tp_basicsize = sizeof(PyLdbMessageElementObject),
3185 .tp_dealloc = (destructor)py_ldb_msg_element_dealloc,
3186 .tp_repr = (reprfunc)py_ldb_msg_element_repr,
3187 .tp_str = (reprfunc)py_ldb_msg_element_str,
3188 .tp_methods = py_ldb_msg_element_methods,
3189 .tp_getset = py_ldb_msg_element_getset,
3190 .tp_richcompare = (richcmpfunc)py_ldb_msg_element_richcmp,
3191 .tp_iter = (getiterfunc)py_ldb_msg_element_iter,
3192 .tp_as_sequence = &py_ldb_msg_element_seq,
3193 .tp_new = py_ldb_msg_element_new,
3194 .tp_flags = Py_TPFLAGS_DEFAULT,
3195 .tp_doc = "An element of a Message",
3199 static PyObject *py_ldb_msg_from_dict(PyTypeObject *type, PyObject *args)
3201 PyObject *py_ldb;
3202 PyObject *py_dict;
3203 PyObject *py_ret;
3204 struct ldb_message *msg;
3205 struct ldb_context *ldb_ctx;
3206 unsigned int mod_flags = LDB_FLAG_MOD_REPLACE;
3208 if (!PyArg_ParseTuple(args, "O!O!|I",
3209 &PyLdb, &py_ldb, &PyDict_Type, &py_dict,
3210 &mod_flags)) {
3211 return NULL;
3214 if (!PyLdb_Check(py_ldb)) {
3215 PyErr_SetString(PyExc_TypeError, "Expected Ldb");
3216 return NULL;
3219 /* mask only flags we are going to use */
3220 mod_flags = LDB_FLAG_MOD_TYPE(mod_flags);
3221 if (!mod_flags) {
3222 PyErr_SetString(PyExc_ValueError,
3223 "FLAG_MOD_ADD, FLAG_MOD_REPLACE or FLAG_MOD_DELETE"
3224 " expected as mod_flag value");
3225 return NULL;
3228 ldb_ctx = pyldb_Ldb_AsLdbContext(py_ldb);
3230 msg = PyDict_AsMessage(ldb_ctx, py_dict, ldb_ctx, mod_flags);
3231 if (!msg) {
3232 return NULL;
3235 py_ret = PyLdbMessage_FromMessage(msg);
3237 talloc_unlink(ldb_ctx, msg);
3239 return py_ret;
3242 static PyObject *py_ldb_msg_remove_attr(PyLdbMessageObject *self, PyObject *args)
3244 char *name;
3245 if (!PyArg_ParseTuple(args, "s", &name))
3246 return NULL;
3248 ldb_msg_remove_attr(self->msg, name);
3250 Py_RETURN_NONE;
3253 static PyObject *py_ldb_msg_keys(PyLdbMessageObject *self)
3255 struct ldb_message *msg = pyldb_Message_AsMessage(self);
3256 Py_ssize_t i, j = 0;
3257 PyObject *obj = PyList_New(msg->num_elements+(msg->dn != NULL?1:0));
3258 if (msg->dn != NULL) {
3259 PyList_SetItem(obj, j, PyStr_FromString("dn"));
3260 j++;
3262 for (i = 0; i < msg->num_elements; i++) {
3263 PyList_SetItem(obj, j, PyStr_FromString(msg->elements[i].name));
3264 j++;
3266 return obj;
3269 static PyObject *py_ldb_msg_getitem_helper(PyLdbMessageObject *self, PyObject *py_name)
3271 struct ldb_message_element *el;
3272 char *name;
3273 struct ldb_message *msg = pyldb_Message_AsMessage(self);
3274 name = PyStr_AsUTF8(py_name);
3275 if (name == NULL) {
3276 PyErr_SetNone(PyExc_TypeError);
3277 return NULL;
3279 if (!ldb_attr_cmp(name, "dn"))
3280 return pyldb_Dn_FromDn(msg->dn);
3281 el = ldb_msg_find_element(msg, name);
3282 if (el == NULL) {
3283 return NULL;
3285 return (PyObject *)PyLdbMessageElement_FromMessageElement(el, msg->elements);
3288 static PyObject *py_ldb_msg_getitem(PyLdbMessageObject *self, PyObject *py_name)
3290 PyObject *ret = py_ldb_msg_getitem_helper(self, py_name);
3291 if (ret == NULL) {
3292 PyErr_SetString(PyExc_KeyError, "No such element");
3293 return NULL;
3295 return ret;
3298 static PyObject *py_ldb_msg_get(PyLdbMessageObject *self, PyObject *args, PyObject *kwargs)
3300 PyObject *def = NULL;
3301 const char *kwnames[] = { "name", "default", "idx", NULL };
3302 const char *name = NULL;
3303 int idx = -1;
3304 struct ldb_message *msg = pyldb_Message_AsMessage(self);
3305 struct ldb_message_element *el;
3307 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "s|Oi:msg",
3308 discard_const_p(char *, kwnames), &name, &def, &idx)) {
3309 return NULL;
3312 if (strcasecmp(name, "dn") == 0) {
3313 return pyldb_Dn_FromDn(msg->dn);
3316 el = ldb_msg_find_element(msg, name);
3318 if (el == NULL || (idx != -1 && el->num_values <= idx)) {
3319 if (def != NULL) {
3320 Py_INCREF(def);
3321 return def;
3323 Py_RETURN_NONE;
3326 if (idx == -1) {
3327 return (PyObject *)PyLdbMessageElement_FromMessageElement(el, msg->elements);
3330 return PyObject_FromLdbValue(&el->values[idx]);
3333 static PyObject *py_ldb_msg_items(PyLdbMessageObject *self)
3335 struct ldb_message *msg = pyldb_Message_AsMessage(self);
3336 Py_ssize_t i, j = 0;
3337 PyObject *l = PyList_New(msg->num_elements + (msg->dn == NULL?0:1));
3338 if (msg->dn != NULL) {
3339 PyList_SetItem(l, 0, Py_BuildValue("(sO)", "dn", pyldb_Dn_FromDn(msg->dn)));
3340 j++;
3342 for (i = 0; i < msg->num_elements; i++, j++) {
3343 PyObject *py_el = PyLdbMessageElement_FromMessageElement(&msg->elements[i], msg->elements);
3344 PyObject *value = Py_BuildValue("(sO)", msg->elements[i].name, py_el);
3345 PyList_SetItem(l, j, value);
3347 return l;
3350 static PyObject *py_ldb_msg_elements(PyLdbMessageObject *self)
3352 struct ldb_message *msg = pyldb_Message_AsMessage(self);
3353 Py_ssize_t i = 0;
3354 PyObject *l = PyList_New(msg->num_elements);
3355 for (i = 0; i < msg->num_elements; i++) {
3356 PyList_SetItem(l, i, PyLdbMessageElement_FromMessageElement(&msg->elements[i], msg->elements));
3358 return l;
3361 static PyObject *py_ldb_msg_add(PyLdbMessageObject *self, PyObject *args)
3363 struct ldb_message *msg = pyldb_Message_AsMessage(self);
3364 PyLdbMessageElementObject *py_element;
3365 int i, ret;
3366 struct ldb_message_element *el;
3367 struct ldb_message_element *el_new;
3369 if (!PyArg_ParseTuple(args, "O!", &PyLdbMessageElement, &py_element))
3370 return NULL;
3372 el = py_element->el;
3373 if (el == NULL) {
3374 PyErr_SetString(PyExc_ValueError, "Invalid MessageElement object");
3375 return NULL;
3378 ret = ldb_msg_add_empty(msg, el->name, el->flags, &el_new);
3379 PyErr_LDB_ERROR_IS_ERR_RAISE(PyExc_LdbError, ret, NULL);
3381 /* now deep copy all attribute values */
3382 el_new->values = talloc_array(msg->elements, struct ldb_val, el->num_values);
3383 if (el_new->values == NULL) {
3384 PyErr_NoMemory();
3385 return NULL;
3387 el_new->num_values = el->num_values;
3389 for (i = 0; i < el->num_values; i++) {
3390 el_new->values[i] = ldb_val_dup(el_new->values, &el->values[i]);
3391 if (el_new->values[i].data == NULL
3392 && el->values[i].length != 0) {
3393 PyErr_NoMemory();
3394 return NULL;
3398 Py_RETURN_NONE;
3401 static PyMethodDef py_ldb_msg_methods[] = {
3402 { "from_dict", (PyCFunction)py_ldb_msg_from_dict, METH_CLASS | METH_VARARGS,
3403 "Message.from_dict(ldb, dict, mod_flag=FLAG_MOD_REPLACE) -> ldb.Message\n"
3404 "Class method to create ldb.Message object from Dictionary.\n"
3405 "mod_flag is one of FLAG_MOD_ADD, FLAG_MOD_REPLACE or FLAG_MOD_DELETE."},
3406 { "keys", (PyCFunction)py_ldb_msg_keys, METH_NOARGS,
3407 "S.keys() -> list\n\n"
3408 "Return sequence of all attribute names." },
3409 { "remove", (PyCFunction)py_ldb_msg_remove_attr, METH_VARARGS,
3410 "S.remove(name)\n\n"
3411 "Remove all entries for attributes with the specified name."},
3412 { "get", (PyCFunction)py_ldb_msg_get, METH_VARARGS | METH_KEYWORDS,
3413 "msg.get(name,default=None,idx=None) -> string\n"
3414 "idx is the index into the values array\n"
3415 "if idx is None, then a list is returned\n"
3416 "if idx is not None, then the element with that index is returned\n"
3417 "if you pass the special name 'dn' then the DN object is returned\n"},
3418 { "items", (PyCFunction)py_ldb_msg_items, METH_NOARGS, NULL },
3419 { "elements", (PyCFunction)py_ldb_msg_elements, METH_NOARGS, NULL },
3420 { "add", (PyCFunction)py_ldb_msg_add, METH_VARARGS,
3421 "S.add(element)\n\n"
3422 "Add an element to this message." },
3423 { NULL },
3426 static PyObject *py_ldb_msg_iter(PyLdbMessageObject *self)
3428 PyObject *list, *iter;
3430 list = py_ldb_msg_keys(self);
3431 iter = PyObject_GetIter(list);
3432 Py_DECREF(list);
3433 return iter;
3436 static int py_ldb_msg_setitem(PyLdbMessageObject *self, PyObject *name, PyObject *value)
3438 char *attr_name;
3440 attr_name = PyStr_AsUTF8(name);
3441 if (attr_name == NULL) {
3442 PyErr_SetNone(PyExc_TypeError);
3443 return -1;
3446 if (value == NULL) {
3447 /* delitem */
3448 ldb_msg_remove_attr(self->msg, attr_name);
3449 } else {
3450 int ret;
3451 struct ldb_message_element *el = PyObject_AsMessageElement(self->msg,
3452 value, 0, attr_name);
3453 if (el == NULL) {
3454 return -1;
3456 ldb_msg_remove_attr(pyldb_Message_AsMessage(self), attr_name);
3457 ret = ldb_msg_add(pyldb_Message_AsMessage(self), el, el->flags);
3458 if (ret != LDB_SUCCESS) {
3459 PyErr_SetLdbError(PyExc_LdbError, ret, NULL);
3460 return -1;
3463 return 0;
3466 static Py_ssize_t py_ldb_msg_length(PyLdbMessageObject *self)
3468 return pyldb_Message_AsMessage(self)->num_elements;
3471 static PyMappingMethods py_ldb_msg_mapping = {
3472 .mp_length = (lenfunc)py_ldb_msg_length,
3473 .mp_subscript = (binaryfunc)py_ldb_msg_getitem,
3474 .mp_ass_subscript = (objobjargproc)py_ldb_msg_setitem,
3477 static PyObject *py_ldb_msg_new(PyTypeObject *type, PyObject *args, PyObject *kwargs)
3479 const char * const kwnames[] = { "dn", NULL };
3480 struct ldb_message *ret;
3481 TALLOC_CTX *mem_ctx;
3482 PyObject *pydn = NULL;
3483 PyLdbMessageObject *py_ret;
3485 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "|O",
3486 discard_const_p(char *, kwnames),
3487 &pydn))
3488 return NULL;
3490 mem_ctx = talloc_new(NULL);
3491 if (mem_ctx == NULL) {
3492 PyErr_NoMemory();
3493 return NULL;
3496 ret = ldb_msg_new(mem_ctx);
3497 if (ret == NULL) {
3498 talloc_free(mem_ctx);
3499 PyErr_NoMemory();
3500 return NULL;
3503 if (pydn != NULL) {
3504 struct ldb_dn *dn;
3505 if (!pyldb_Object_AsDn(NULL, pydn, NULL, &dn)) {
3506 talloc_free(mem_ctx);
3507 return NULL;
3509 ret->dn = talloc_reference(ret, dn);
3512 py_ret = (PyLdbMessageObject *)type->tp_alloc(type, 0);
3513 if (py_ret == NULL) {
3514 PyErr_NoMemory();
3515 talloc_free(mem_ctx);
3516 return NULL;
3519 py_ret->mem_ctx = mem_ctx;
3520 py_ret->msg = ret;
3521 return (PyObject *)py_ret;
3524 static PyObject *PyLdbMessage_FromMessage(struct ldb_message *msg)
3526 PyLdbMessageObject *ret;
3528 ret = (PyLdbMessageObject *)PyLdbMessage.tp_alloc(&PyLdbMessage, 0);
3529 if (ret == NULL) {
3530 PyErr_NoMemory();
3531 return NULL;
3533 ret->mem_ctx = talloc_new(NULL);
3534 ret->msg = talloc_reference(ret->mem_ctx, msg);
3535 return (PyObject *)ret;
3538 static PyObject *py_ldb_msg_get_dn(PyLdbMessageObject *self, void *closure)
3540 struct ldb_message *msg = pyldb_Message_AsMessage(self);
3541 return pyldb_Dn_FromDn(msg->dn);
3544 static int py_ldb_msg_set_dn(PyLdbMessageObject *self, PyObject *value, void *closure)
3546 struct ldb_message *msg = pyldb_Message_AsMessage(self);
3547 if (!pyldb_Dn_Check(value)) {
3548 PyErr_SetString(PyExc_TypeError, "expected dn");
3549 return -1;
3552 msg->dn = talloc_reference(msg, pyldb_Dn_AsDn(value));
3553 return 0;
3556 static PyObject *py_ldb_msg_get_text(PyObject *self, void *closure)
3558 return wrap_text("MessageTextWrapper", self);
3561 static PyGetSetDef py_ldb_msg_getset[] = {
3562 { discard_const_p(char, "dn"), (getter)py_ldb_msg_get_dn, (setter)py_ldb_msg_set_dn, NULL },
3563 { discard_const_p(char, "text"), (getter)py_ldb_msg_get_text, NULL, NULL },
3564 { NULL }
3567 static PyObject *py_ldb_msg_repr(PyLdbMessageObject *self)
3569 PyObject *dict = PyDict_New(), *ret, *repr;
3570 if (PyDict_Update(dict, (PyObject *)self) != 0)
3571 return NULL;
3572 repr = PyObject_Repr(dict);
3573 if (repr == NULL) {
3574 Py_DECREF(dict);
3575 return NULL;
3577 ret = PyStr_FromFormat("Message(%s)", PyStr_AsUTF8(repr));
3578 Py_DECREF(repr);
3579 Py_DECREF(dict);
3580 return ret;
3583 static void py_ldb_msg_dealloc(PyLdbMessageObject *self)
3585 talloc_free(self->mem_ctx);
3586 PyObject_Del(self);
3589 static PyObject *py_ldb_msg_richcmp(PyLdbMessageObject *py_msg1,
3590 PyLdbMessageObject *py_msg2, int op)
3592 struct ldb_message *msg1, *msg2;
3593 unsigned int i;
3594 int ret;
3596 if (!PyLdbMessage_Check(py_msg2)) {
3597 Py_INCREF(Py_NotImplemented);
3598 return Py_NotImplemented;
3601 msg1 = pyldb_Message_AsMessage(py_msg1),
3602 msg2 = pyldb_Message_AsMessage(py_msg2);
3604 if ((msg1->dn != NULL) || (msg2->dn != NULL)) {
3605 ret = ldb_dn_compare(msg1->dn, msg2->dn);
3606 if (ret != 0) {
3607 return richcmp(ret, op);
3611 ret = msg1->num_elements - msg2->num_elements;
3612 if (ret != 0) {
3613 return richcmp(ret, op);
3616 for (i = 0; i < msg1->num_elements; i++) {
3617 ret = ldb_msg_element_compare_name(&msg1->elements[i],
3618 &msg2->elements[i]);
3619 if (ret != 0) {
3620 return richcmp(ret, op);
3623 ret = ldb_msg_element_compare(&msg1->elements[i],
3624 &msg2->elements[i]);
3625 if (ret != 0) {
3626 return richcmp(ret, op);
3630 return richcmp(0, op);
3633 static PyTypeObject PyLdbMessage = {
3634 .tp_name = "ldb.Message",
3635 .tp_methods = py_ldb_msg_methods,
3636 .tp_getset = py_ldb_msg_getset,
3637 .tp_as_mapping = &py_ldb_msg_mapping,
3638 .tp_basicsize = sizeof(PyLdbMessageObject),
3639 .tp_dealloc = (destructor)py_ldb_msg_dealloc,
3640 .tp_new = py_ldb_msg_new,
3641 .tp_repr = (reprfunc)py_ldb_msg_repr,
3642 .tp_flags = Py_TPFLAGS_DEFAULT,
3643 .tp_iter = (getiterfunc)py_ldb_msg_iter,
3644 .tp_richcompare = (richcmpfunc)py_ldb_msg_richcmp,
3645 .tp_doc = "A LDB Message",
3648 static PyObject *PyLdbTree_FromTree(struct ldb_parse_tree *tree)
3650 PyLdbTreeObject *ret;
3652 ret = (PyLdbTreeObject *)PyLdbTree.tp_alloc(&PyLdbTree, 0);
3653 if (ret == NULL) {
3654 PyErr_NoMemory();
3655 return NULL;
3658 ret->mem_ctx = talloc_new(NULL);
3659 ret->tree = talloc_reference(ret->mem_ctx, tree);
3660 return (PyObject *)ret;
3663 static void py_ldb_tree_dealloc(PyLdbTreeObject *self)
3665 talloc_free(self->mem_ctx);
3666 PyObject_Del(self);
3669 static PyTypeObject PyLdbTree = {
3670 .tp_name = "ldb.Tree",
3671 .tp_basicsize = sizeof(PyLdbTreeObject),
3672 .tp_dealloc = (destructor)py_ldb_tree_dealloc,
3673 .tp_flags = Py_TPFLAGS_DEFAULT,
3674 .tp_doc = "A search tree",
3677 /* Ldb_module */
3678 static int py_module_search(struct ldb_module *mod, struct ldb_request *req)
3680 PyObject *py_ldb = (PyObject *)mod->private_data;
3681 PyObject *py_result, *py_base, *py_attrs, *py_tree;
3683 py_base = pyldb_Dn_FromDn(req->op.search.base);
3685 if (py_base == NULL)
3686 return LDB_ERR_OPERATIONS_ERROR;
3688 py_tree = PyLdbTree_FromTree(req->op.search.tree);
3690 if (py_tree == NULL)
3691 return LDB_ERR_OPERATIONS_ERROR;
3693 if (req->op.search.attrs == NULL) {
3694 py_attrs = Py_None;
3695 } else {
3696 int i, len;
3697 for (len = 0; req->op.search.attrs[len]; len++);
3698 py_attrs = PyList_New(len);
3699 for (i = 0; i < len; i++)
3700 PyList_SetItem(py_attrs, i, PyStr_FromString(req->op.search.attrs[i]));
3703 py_result = PyObject_CallMethod(py_ldb, discard_const_p(char, "search"),
3704 discard_const_p(char, "OiOO"),
3705 py_base, req->op.search.scope, py_tree, py_attrs);
3707 Py_DECREF(py_attrs);
3708 Py_DECREF(py_tree);
3709 Py_DECREF(py_base);
3711 if (py_result == NULL) {
3712 return LDB_ERR_PYTHON_EXCEPTION;
3715 req->op.search.res = PyLdbResult_AsResult(NULL, py_result);
3716 if (req->op.search.res == NULL) {
3717 return LDB_ERR_PYTHON_EXCEPTION;
3720 Py_DECREF(py_result);
3722 return LDB_SUCCESS;
3725 static int py_module_add(struct ldb_module *mod, struct ldb_request *req)
3727 PyObject *py_ldb = (PyObject *)mod->private_data;
3728 PyObject *py_result, *py_msg;
3730 py_msg = PyLdbMessage_FromMessage(discard_const_p(struct ldb_message, req->op.add.message));
3732 if (py_msg == NULL) {
3733 return LDB_ERR_OPERATIONS_ERROR;
3736 py_result = PyObject_CallMethod(py_ldb, discard_const_p(char, "add"),
3737 discard_const_p(char, "O"),
3738 py_msg);
3740 Py_DECREF(py_msg);
3742 if (py_result == NULL) {
3743 return LDB_ERR_PYTHON_EXCEPTION;
3746 Py_DECREF(py_result);
3748 return LDB_SUCCESS;
3751 static int py_module_modify(struct ldb_module *mod, struct ldb_request *req)
3753 PyObject *py_ldb = (PyObject *)mod->private_data;
3754 PyObject *py_result, *py_msg;
3756 py_msg = PyLdbMessage_FromMessage(discard_const_p(struct ldb_message, req->op.mod.message));
3758 if (py_msg == NULL) {
3759 return LDB_ERR_OPERATIONS_ERROR;
3762 py_result = PyObject_CallMethod(py_ldb, discard_const_p(char, "modify"),
3763 discard_const_p(char, "O"),
3764 py_msg);
3766 Py_DECREF(py_msg);
3768 if (py_result == NULL) {
3769 return LDB_ERR_PYTHON_EXCEPTION;
3772 Py_DECREF(py_result);
3774 return LDB_SUCCESS;
3777 static int py_module_del(struct ldb_module *mod, struct ldb_request *req)
3779 PyObject *py_ldb = (PyObject *)mod->private_data;
3780 PyObject *py_result, *py_dn;
3782 py_dn = pyldb_Dn_FromDn(req->op.del.dn);
3784 if (py_dn == NULL)
3785 return LDB_ERR_OPERATIONS_ERROR;
3787 py_result = PyObject_CallMethod(py_ldb, discard_const_p(char, "delete"),
3788 discard_const_p(char, "O"),
3789 py_dn);
3791 if (py_result == NULL) {
3792 return LDB_ERR_PYTHON_EXCEPTION;
3795 Py_DECREF(py_result);
3797 return LDB_SUCCESS;
3800 static int py_module_rename(struct ldb_module *mod, struct ldb_request *req)
3802 PyObject *py_ldb = (PyObject *)mod->private_data;
3803 PyObject *py_result, *py_olddn, *py_newdn;
3805 py_olddn = pyldb_Dn_FromDn(req->op.rename.olddn);
3807 if (py_olddn == NULL)
3808 return LDB_ERR_OPERATIONS_ERROR;
3810 py_newdn = pyldb_Dn_FromDn(req->op.rename.newdn);
3812 if (py_newdn == NULL)
3813 return LDB_ERR_OPERATIONS_ERROR;
3815 py_result = PyObject_CallMethod(py_ldb, discard_const_p(char, "rename"),
3816 discard_const_p(char, "OO"),
3817 py_olddn, py_newdn);
3819 Py_DECREF(py_olddn);
3820 Py_DECREF(py_newdn);
3822 if (py_result == NULL) {
3823 return LDB_ERR_PYTHON_EXCEPTION;
3826 Py_DECREF(py_result);
3828 return LDB_SUCCESS;
3831 static int py_module_request(struct ldb_module *mod, struct ldb_request *req)
3833 PyObject *py_ldb = (PyObject *)mod->private_data;
3834 PyObject *py_result;
3836 py_result = PyObject_CallMethod(py_ldb, discard_const_p(char, "request"),
3837 discard_const_p(char, ""));
3839 Py_XDECREF(py_result);
3841 return LDB_ERR_OPERATIONS_ERROR;
3844 static int py_module_extended(struct ldb_module *mod, struct ldb_request *req)
3846 PyObject *py_ldb = (PyObject *)mod->private_data;
3847 PyObject *py_result;
3849 py_result = PyObject_CallMethod(py_ldb, discard_const_p(char, "extended"),
3850 discard_const_p(char, ""));
3852 Py_XDECREF(py_result);
3854 return LDB_ERR_OPERATIONS_ERROR;
3857 static int py_module_start_transaction(struct ldb_module *mod)
3859 PyObject *py_ldb = (PyObject *)mod->private_data;
3860 PyObject *py_result;
3862 py_result = PyObject_CallMethod(py_ldb, discard_const_p(char, "start_transaction"),
3863 discard_const_p(char, ""));
3865 if (py_result == NULL) {
3866 return LDB_ERR_PYTHON_EXCEPTION;
3869 Py_DECREF(py_result);
3871 return LDB_SUCCESS;
3874 static int py_module_end_transaction(struct ldb_module *mod)
3876 PyObject *py_ldb = (PyObject *)mod->private_data;
3877 PyObject *py_result;
3879 py_result = PyObject_CallMethod(py_ldb, discard_const_p(char, "end_transaction"),
3880 discard_const_p(char, ""));
3882 if (py_result == NULL) {
3883 return LDB_ERR_PYTHON_EXCEPTION;
3886 Py_DECREF(py_result);
3888 return LDB_SUCCESS;
3891 static int py_module_del_transaction(struct ldb_module *mod)
3893 PyObject *py_ldb = (PyObject *)mod->private_data;
3894 PyObject *py_result;
3896 py_result = PyObject_CallMethod(py_ldb, discard_const_p(char, "del_transaction"),
3897 discard_const_p(char, ""));
3899 if (py_result == NULL) {
3900 return LDB_ERR_PYTHON_EXCEPTION;
3903 Py_DECREF(py_result);
3905 return LDB_SUCCESS;
3908 static int py_module_destructor(struct ldb_module *mod)
3910 Py_DECREF((PyObject *)mod->private_data);
3911 return 0;
3914 static int py_module_init(struct ldb_module *mod)
3916 PyObject *py_class = (PyObject *)mod->ops->private_data;
3917 PyObject *py_result, *py_next, *py_ldb;
3919 py_ldb = PyLdb_FromLdbContext(mod->ldb);
3921 if (py_ldb == NULL)
3922 return LDB_ERR_OPERATIONS_ERROR;
3924 py_next = PyLdbModule_FromModule(mod->next);
3926 if (py_next == NULL)
3927 return LDB_ERR_OPERATIONS_ERROR;
3929 py_result = PyObject_CallFunction(py_class, discard_const_p(char, "OO"),
3930 py_ldb, py_next);
3932 if (py_result == NULL) {
3933 return LDB_ERR_PYTHON_EXCEPTION;
3936 mod->private_data = py_result;
3938 talloc_set_destructor(mod, py_module_destructor);
3940 return ldb_next_init(mod);
3943 static PyObject *py_register_module(PyObject *module, PyObject *args)
3945 int ret;
3946 struct ldb_module_ops *ops;
3947 PyObject *input;
3949 if (!PyArg_ParseTuple(args, "O", &input))
3950 return NULL;
3952 ops = talloc_zero(talloc_autofree_context(), struct ldb_module_ops);
3953 if (ops == NULL) {
3954 PyErr_NoMemory();
3955 return NULL;
3958 ops->name = talloc_strdup(ops, PyStr_AsUTF8(PyObject_GetAttrString(input, discard_const_p(char, "name"))));
3960 Py_INCREF(input);
3961 ops->private_data = input;
3962 ops->init_context = py_module_init;
3963 ops->search = py_module_search;
3964 ops->add = py_module_add;
3965 ops->modify = py_module_modify;
3966 ops->del = py_module_del;
3967 ops->rename = py_module_rename;
3968 ops->request = py_module_request;
3969 ops->extended = py_module_extended;
3970 ops->start_transaction = py_module_start_transaction;
3971 ops->end_transaction = py_module_end_transaction;
3972 ops->del_transaction = py_module_del_transaction;
3974 ret = ldb_register_module(ops);
3976 PyErr_LDB_ERROR_IS_ERR_RAISE(PyExc_LdbError, ret, NULL);
3978 Py_RETURN_NONE;
3981 static PyObject *py_timestring(PyObject *module, PyObject *args)
3983 /* most times "time_t" is a signed integer type with 32 or 64 bit:
3984 * http://stackoverflow.com/questions/471248/what-is-ultimately-a-time-t-typedef-to */
3985 long int t_val;
3986 char *tresult;
3987 PyObject *ret;
3988 if (!PyArg_ParseTuple(args, "l", &t_val))
3989 return NULL;
3990 tresult = ldb_timestring(NULL, (time_t) t_val);
3991 ret = PyStr_FromString(tresult);
3992 talloc_free(tresult);
3993 return ret;
3996 static PyObject *py_string_to_time(PyObject *module, PyObject *args)
3998 char *str;
3999 if (!PyArg_ParseTuple(args, "s", &str))
4000 return NULL;
4002 return PyInt_FromLong(ldb_string_to_time(str));
4005 static PyObject *py_valid_attr_name(PyObject *self, PyObject *args)
4007 char *name;
4008 if (!PyArg_ParseTuple(args, "s", &name))
4009 return NULL;
4010 return PyBool_FromLong(ldb_valid_attr_name(name));
4014 encode a string using RFC2254 rules
4016 static PyObject *py_binary_encode(PyObject *self, PyObject *args)
4018 char *str, *encoded;
4019 Py_ssize_t size = 0;
4020 struct ldb_val val;
4021 PyObject *ret;
4023 if (!PyArg_ParseTuple(args, "s#", &str, &size))
4024 return NULL;
4025 val.data = (uint8_t *)str;
4026 val.length = size;
4028 encoded = ldb_binary_encode(NULL, val);
4029 if (encoded == NULL) {
4030 PyErr_SetString(PyExc_TypeError, "unable to encode binary string");
4031 return NULL;
4033 ret = PyStr_FromString(encoded);
4034 talloc_free(encoded);
4035 return ret;
4039 decode a string using RFC2254 rules
4041 static PyObject *py_binary_decode(PyObject *self, PyObject *args)
4043 char *str;
4044 struct ldb_val val;
4045 PyObject *ret;
4047 if (!PyArg_ParseTuple(args, "s", &str))
4048 return NULL;
4050 val = ldb_binary_decode(NULL, str);
4051 if (val.data == NULL) {
4052 PyErr_SetString(PyExc_TypeError, "unable to decode binary string");
4053 return NULL;
4055 ret = PyBytes_FromStringAndSize((const char*)val.data, val.length);
4056 talloc_free(val.data);
4057 return ret;
4060 static PyMethodDef py_ldb_global_methods[] = {
4061 { "register_module", py_register_module, METH_VARARGS,
4062 "S.register_module(module) -> None\n\n"
4063 "Register a LDB module."},
4064 { "timestring", py_timestring, METH_VARARGS,
4065 "S.timestring(int) -> string\n\n"
4066 "Generate a LDAP time string from a UNIX timestamp" },
4067 { "string_to_time", py_string_to_time, METH_VARARGS,
4068 "S.string_to_time(string) -> int\n\n"
4069 "Parse a LDAP time string into a UNIX timestamp." },
4070 { "valid_attr_name", py_valid_attr_name, METH_VARARGS,
4071 "S.valid_attr_name(name) -> bool\n\nn"
4072 "Check whether the supplied name is a valid attribute name." },
4073 { "open", (PyCFunction)py_ldb_new, METH_VARARGS|METH_KEYWORDS,
4074 "S.open() -> Ldb\n\n"
4075 "Open a new LDB context." },
4076 { "binary_encode", py_binary_encode, METH_VARARGS,
4077 "S.binary_encode(string) -> string\n\n"
4078 "Perform a RFC2254 binary encoding on a string" },
4079 { "binary_decode", py_binary_decode, METH_VARARGS,
4080 "S.binary_decode(string) -> string\n\n"
4081 "Perform a RFC2254 binary decode on a string" },
4082 { NULL }
4085 #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."
4087 #if PY_MAJOR_VERSION >= 3
4088 static struct PyModuleDef moduledef = {
4089 PyModuleDef_HEAD_INIT,
4090 .m_name = "ldb",
4091 .m_doc = MODULE_DOC,
4092 .m_size = -1,
4093 .m_methods = py_ldb_global_methods,
4095 #endif
4097 static PyObject* module_init(void)
4099 PyObject *m;
4101 if (PyType_Ready(&PyLdbDn) < 0)
4102 return NULL;
4104 if (PyType_Ready(&PyLdbMessage) < 0)
4105 return NULL;
4107 if (PyType_Ready(&PyLdbMessageElement) < 0)
4108 return NULL;
4110 if (PyType_Ready(&PyLdb) < 0)
4111 return NULL;
4113 if (PyType_Ready(&PyLdbModule) < 0)
4114 return NULL;
4116 if (PyType_Ready(&PyLdbTree) < 0)
4117 return NULL;
4119 if (PyType_Ready(&PyLdbResult) < 0)
4120 return NULL;
4122 if (PyType_Ready(&PyLdbSearchIterator) < 0)
4123 return NULL;
4125 if (PyType_Ready(&PyLdbControl) < 0)
4126 return NULL;
4128 #if PY_MAJOR_VERSION >= 3
4129 m = PyModule_Create(&moduledef);
4130 #else
4131 m = Py_InitModule3("ldb", py_ldb_global_methods, MODULE_DOC);
4132 #endif
4133 if (m == NULL)
4134 return NULL;
4136 #define ADD_LDB_INT(val) PyModule_AddIntConstant(m, #val, LDB_ ## val)
4138 ADD_LDB_INT(SEQ_HIGHEST_SEQ);
4139 ADD_LDB_INT(SEQ_HIGHEST_TIMESTAMP);
4140 ADD_LDB_INT(SEQ_NEXT);
4141 ADD_LDB_INT(SCOPE_DEFAULT);
4142 ADD_LDB_INT(SCOPE_BASE);
4143 ADD_LDB_INT(SCOPE_ONELEVEL);
4144 ADD_LDB_INT(SCOPE_SUBTREE);
4146 ADD_LDB_INT(CHANGETYPE_NONE);
4147 ADD_LDB_INT(CHANGETYPE_ADD);
4148 ADD_LDB_INT(CHANGETYPE_DELETE);
4149 ADD_LDB_INT(CHANGETYPE_MODIFY);
4151 ADD_LDB_INT(FLAG_MOD_ADD);
4152 ADD_LDB_INT(FLAG_MOD_REPLACE);
4153 ADD_LDB_INT(FLAG_MOD_DELETE);
4155 ADD_LDB_INT(ATTR_FLAG_HIDDEN);
4156 ADD_LDB_INT(ATTR_FLAG_UNIQUE_INDEX);
4157 ADD_LDB_INT(ATTR_FLAG_SINGLE_VALUE);
4158 ADD_LDB_INT(ATTR_FLAG_FORCE_BASE64_LDIF);
4160 ADD_LDB_INT(SUCCESS);
4161 ADD_LDB_INT(ERR_OPERATIONS_ERROR);
4162 ADD_LDB_INT(ERR_PROTOCOL_ERROR);
4163 ADD_LDB_INT(ERR_TIME_LIMIT_EXCEEDED);
4164 ADD_LDB_INT(ERR_SIZE_LIMIT_EXCEEDED);
4165 ADD_LDB_INT(ERR_COMPARE_FALSE);
4166 ADD_LDB_INT(ERR_COMPARE_TRUE);
4167 ADD_LDB_INT(ERR_AUTH_METHOD_NOT_SUPPORTED);
4168 ADD_LDB_INT(ERR_STRONG_AUTH_REQUIRED);
4169 ADD_LDB_INT(ERR_REFERRAL);
4170 ADD_LDB_INT(ERR_ADMIN_LIMIT_EXCEEDED);
4171 ADD_LDB_INT(ERR_UNSUPPORTED_CRITICAL_EXTENSION);
4172 ADD_LDB_INT(ERR_CONFIDENTIALITY_REQUIRED);
4173 ADD_LDB_INT(ERR_SASL_BIND_IN_PROGRESS);
4174 ADD_LDB_INT(ERR_NO_SUCH_ATTRIBUTE);
4175 ADD_LDB_INT(ERR_UNDEFINED_ATTRIBUTE_TYPE);
4176 ADD_LDB_INT(ERR_INAPPROPRIATE_MATCHING);
4177 ADD_LDB_INT(ERR_CONSTRAINT_VIOLATION);
4178 ADD_LDB_INT(ERR_ATTRIBUTE_OR_VALUE_EXISTS);
4179 ADD_LDB_INT(ERR_INVALID_ATTRIBUTE_SYNTAX);
4180 ADD_LDB_INT(ERR_NO_SUCH_OBJECT);
4181 ADD_LDB_INT(ERR_ALIAS_PROBLEM);
4182 ADD_LDB_INT(ERR_INVALID_DN_SYNTAX);
4183 ADD_LDB_INT(ERR_ALIAS_DEREFERENCING_PROBLEM);
4184 ADD_LDB_INT(ERR_INAPPROPRIATE_AUTHENTICATION);
4185 ADD_LDB_INT(ERR_INVALID_CREDENTIALS);
4186 ADD_LDB_INT(ERR_INSUFFICIENT_ACCESS_RIGHTS);
4187 ADD_LDB_INT(ERR_BUSY);
4188 ADD_LDB_INT(ERR_UNAVAILABLE);
4189 ADD_LDB_INT(ERR_UNWILLING_TO_PERFORM);
4190 ADD_LDB_INT(ERR_LOOP_DETECT);
4191 ADD_LDB_INT(ERR_NAMING_VIOLATION);
4192 ADD_LDB_INT(ERR_OBJECT_CLASS_VIOLATION);
4193 ADD_LDB_INT(ERR_NOT_ALLOWED_ON_NON_LEAF);
4194 ADD_LDB_INT(ERR_NOT_ALLOWED_ON_RDN);
4195 ADD_LDB_INT(ERR_ENTRY_ALREADY_EXISTS);
4196 ADD_LDB_INT(ERR_OBJECT_CLASS_MODS_PROHIBITED);
4197 ADD_LDB_INT(ERR_AFFECTS_MULTIPLE_DSAS);
4198 ADD_LDB_INT(ERR_OTHER);
4200 ADD_LDB_INT(FLG_RDONLY);
4201 ADD_LDB_INT(FLG_NOSYNC);
4202 ADD_LDB_INT(FLG_RECONNECT);
4203 ADD_LDB_INT(FLG_NOMMAP);
4205 /* Historical misspelling */
4206 PyModule_AddIntConstant(m, "ERR_ALIAS_DEREFERINCING_PROBLEM", LDB_ERR_ALIAS_DEREFERENCING_PROBLEM);
4208 PyModule_AddStringConstant(m, "__docformat__", "restructuredText");
4210 PyExc_LdbError = PyErr_NewException(discard_const_p(char, "_ldb.LdbError"), NULL, NULL);
4211 PyModule_AddObject(m, "LdbError", PyExc_LdbError);
4213 Py_INCREF(&PyLdb);
4214 Py_INCREF(&PyLdbDn);
4215 Py_INCREF(&PyLdbModule);
4216 Py_INCREF(&PyLdbMessage);
4217 Py_INCREF(&PyLdbMessageElement);
4218 Py_INCREF(&PyLdbTree);
4219 Py_INCREF(&PyLdbResult);
4220 Py_INCREF(&PyLdbControl);
4222 PyModule_AddObject(m, "Ldb", (PyObject *)&PyLdb);
4223 PyModule_AddObject(m, "Dn", (PyObject *)&PyLdbDn);
4224 PyModule_AddObject(m, "Message", (PyObject *)&PyLdbMessage);
4225 PyModule_AddObject(m, "MessageElement", (PyObject *)&PyLdbMessageElement);
4226 PyModule_AddObject(m, "Module", (PyObject *)&PyLdbModule);
4227 PyModule_AddObject(m, "Tree", (PyObject *)&PyLdbTree);
4228 PyModule_AddObject(m, "Control", (PyObject *)&PyLdbControl);
4230 PyModule_AddStringConstant(m, "__version__", PACKAGE_VERSION);
4232 #define ADD_LDB_STRING(val) PyModule_AddStringConstant(m, #val, LDB_## val)
4234 ADD_LDB_STRING(SYNTAX_DN);
4235 ADD_LDB_STRING(SYNTAX_DIRECTORY_STRING);
4236 ADD_LDB_STRING(SYNTAX_INTEGER);
4237 ADD_LDB_STRING(SYNTAX_BOOLEAN);
4238 ADD_LDB_STRING(SYNTAX_OCTET_STRING);
4239 ADD_LDB_STRING(SYNTAX_UTC_TIME);
4240 ADD_LDB_STRING(OID_COMPARATOR_AND);
4241 ADD_LDB_STRING(OID_COMPARATOR_OR);
4243 return m;
4246 #if PY_MAJOR_VERSION >= 3
4247 PyMODINIT_FUNC PyInit_ldb(void);
4248 PyMODINIT_FUNC PyInit_ldb(void)
4250 return module_init();
4252 #else
4253 void initldb(void);
4254 void initldb(void)
4256 module_init();
4258 #endif