s3: smbd: rename_internals_fsp() has to reopen the parent directory of the target...
[Samba.git] / lib / ldb / pyldb.c
blob49641957223a4687083a5eadb32484e99a2e28b2
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 /* discard signature of 'func' in favour of 'target_sig' */
38 #define PY_DISCARD_FUNC_SIG(target_sig, func) (target_sig)(void(*)(void))func
40 struct py_ldb_search_iterator_reply;
42 typedef struct {
43 PyObject_HEAD
44 TALLOC_CTX *mem_ctx;
45 PyLdbObject *ldb;
46 struct {
47 struct ldb_request *req;
48 struct py_ldb_search_iterator_reply *next;
49 struct py_ldb_search_iterator_reply *result;
50 PyObject *exception;
51 } state;
52 } PyLdbSearchIteratorObject;
54 struct py_ldb_search_iterator_reply {
55 struct py_ldb_search_iterator_reply *prev, *next;
56 PyLdbSearchIteratorObject *py_iter;
57 PyObject *obj;
60 void initldb(void);
61 static PyObject *PyLdbMessage_FromMessage(struct ldb_message *msg);
62 static PyObject *PyExc_LdbError;
64 static PyTypeObject PyLdbControl;
65 static PyTypeObject PyLdbResult;
66 static PyTypeObject PyLdbSearchIterator;
67 static PyTypeObject PyLdbMessage;
68 #define PyLdbMessage_Check(ob) PyObject_TypeCheck(ob, &PyLdbMessage)
69 static PyTypeObject PyLdbModule;
70 static PyTypeObject PyLdbDn;
71 #define pyldb_Dn_Check(ob) PyObject_TypeCheck(ob, &PyLdbDn)
72 static PyTypeObject PyLdb;
73 #define PyLdb_Check(ob) PyObject_TypeCheck(ob, &PyLdb)
74 static PyTypeObject PyLdbMessageElement;
75 #define pyldb_MessageElement_Check(ob) PyObject_TypeCheck(ob, &PyLdbMessageElement)
77 static PyTypeObject PyLdbTree;
78 static PyObject *PyLdb_FromLdbContext(struct ldb_context *ldb_ctx);
79 static PyObject *PyLdbModule_FromModule(struct ldb_module *mod);
80 static struct ldb_message_element *PyObject_AsMessageElement(
81 TALLOC_CTX *mem_ctx,
82 PyObject *set_obj,
83 unsigned int flags,
84 const char *attr_name);
85 static PyTypeObject PyLdbBytesType;
87 #define PYARG_STR_UNI "es"
89 static PyObject *PyLdbBytes_FromStringAndSize(const char *msg, int size)
91 PyObject* result = NULL;
92 PyObject* args = NULL;
93 args = Py_BuildValue("(y#)", msg, size);
94 if (args == NULL) {
95 return NULL;
97 result = PyLdbBytesType.tp_new(&PyLdbBytesType, args, NULL);
98 Py_DECREF(args);
99 return result;
102 static PyObject *richcmp(int cmp_val, int op)
104 int ret;
105 switch (op) {
106 case Py_LT: ret = cmp_val < 0; break;
107 case Py_LE: ret = cmp_val <= 0; break;
108 case Py_EQ: ret = cmp_val == 0; break;
109 case Py_NE: ret = cmp_val != 0; break;
110 case Py_GT: ret = cmp_val > 0; break;
111 case Py_GE: ret = cmp_val >= 0; break;
112 default:
113 Py_INCREF(Py_NotImplemented);
114 return Py_NotImplemented;
116 return PyBool_FromLong(ret);
120 static PyObject *py_ldb_control_str(PyLdbControlObject *self)
122 if (self->data != NULL) {
123 char* control = ldb_control_to_string(self->mem_ctx, self->data);
124 if (control == NULL) {
125 PyErr_NoMemory();
126 return NULL;
128 return PyUnicode_FromString(control);
129 } else {
130 return PyUnicode_FromString("ldb control");
134 static void py_ldb_control_dealloc(PyLdbControlObject *self)
136 if (self->mem_ctx != NULL) {
137 talloc_free(self->mem_ctx);
139 self->data = NULL;
140 Py_TYPE(self)->tp_free(self);
143 /* Create a text (rather than bytes) interface for a LDB result object */
144 static PyObject *wrap_text(const char *type, PyObject *wrapped)
146 PyObject *mod, *cls, *constructor, *inst;
147 mod = PyImport_ImportModule("_ldb_text");
148 if (mod == NULL)
149 return NULL;
150 cls = PyObject_GetAttrString(mod, type);
151 Py_DECREF(mod);
152 if (cls == NULL) {
153 Py_DECREF(mod);
154 return NULL;
156 constructor = PyObject_GetAttrString(cls, "_wrap");
157 Py_DECREF(cls);
158 if (constructor == NULL) {
159 return NULL;
161 inst = PyObject_CallFunction(constructor, discard_const_p(char, "O"), wrapped);
162 Py_DECREF(constructor);
163 return inst;
166 static PyObject *py_ldb_control_get_oid(PyLdbControlObject *self,
167 PyObject *Py_UNUSED(ignored))
169 return PyUnicode_FromString(self->data->oid);
172 static PyObject *py_ldb_control_get_critical(PyLdbControlObject *self,
173 PyObject *Py_UNUSED(ignored))
175 return PyBool_FromLong(self->data->critical);
178 static int py_ldb_control_set_critical(PyLdbControlObject *self, PyObject *value, void *closure)
180 if (value == NULL) {
181 PyErr_SetString(PyExc_AttributeError, "cannot delete critical flag");
182 return -1;
184 if (PyObject_IsTrue(value)) {
185 self->data->critical = true;
186 } else {
187 self->data->critical = false;
189 return 0;
192 static PyObject *py_ldb_control_new(PyTypeObject *type, PyObject *args, PyObject *kwargs)
194 char *data = NULL;
195 const char * const kwnames[] = { "ldb", "data", NULL };
196 struct ldb_control *parsed_controls;
197 PyLdbControlObject *ret;
198 PyObject *py_ldb;
199 TALLOC_CTX *mem_ctx;
200 struct ldb_context *ldb_ctx;
202 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "O!s",
203 discard_const_p(char *, kwnames),
204 &PyLdb, &py_ldb, &data))
205 return NULL;
207 mem_ctx = talloc_new(NULL);
208 if (mem_ctx == NULL) {
209 PyErr_NoMemory();
210 return NULL;
213 ldb_ctx = pyldb_Ldb_AS_LDBCONTEXT(py_ldb);
214 parsed_controls = ldb_parse_control_from_string(ldb_ctx, mem_ctx, data);
216 if (!parsed_controls) {
217 talloc_free(mem_ctx);
218 PyErr_SetString(PyExc_ValueError, "unable to parse control string");
219 return NULL;
222 ret = PyObject_New(PyLdbControlObject, type);
223 if (ret == NULL) {
224 PyErr_NoMemory();
225 talloc_free(mem_ctx);
226 return NULL;
229 ret->mem_ctx = mem_ctx;
231 ret->data = talloc_move(mem_ctx, &parsed_controls);
232 if (ret->data == NULL) {
233 Py_DECREF(ret);
234 PyErr_NoMemory();
235 talloc_free(mem_ctx);
236 return NULL;
239 return (PyObject *)ret;
242 static PyGetSetDef py_ldb_control_getset[] = {
244 .name = discard_const_p(char, "oid"),
245 .get = (getter)py_ldb_control_get_oid,
248 .name = discard_const_p(char, "critical"),
249 .get = (getter)py_ldb_control_get_critical,
250 .set = (setter)py_ldb_control_set_critical,
252 { .name = NULL },
255 static PyTypeObject PyLdbControl = {
256 .tp_name = "ldb.control",
257 .tp_dealloc = (destructor)py_ldb_control_dealloc,
258 .tp_getattro = PyObject_GenericGetAttr,
259 .tp_basicsize = sizeof(PyLdbControlObject),
260 .tp_getset = py_ldb_control_getset,
261 .tp_doc = "LDB control.",
262 .tp_str = (reprfunc)py_ldb_control_str,
263 .tp_new = py_ldb_control_new,
264 .tp_flags = Py_TPFLAGS_DEFAULT|Py_TPFLAGS_BASETYPE,
267 static void PyErr_SetLdbError(PyObject *error, int ret, struct ldb_context *ldb_ctx)
269 if (ret == LDB_ERR_PYTHON_EXCEPTION)
270 return; /* Python exception should already be set, just keep that */
272 PyErr_SetObject(error,
273 Py_BuildValue(discard_const_p(char, "(i,s)"), ret,
274 ldb_ctx == NULL?ldb_strerror(ret):ldb_errstring(ldb_ctx)));
276 static PyObject *py_ldb_bytes_str(PyBytesObject *self)
278 char *msg = NULL;
279 Py_ssize_t size;
280 int result = 0;
281 if (!PyBytes_Check(self)) {
282 PyErr_Format(PyExc_TypeError,"Unexpected type");
283 return NULL;
285 result = PyBytes_AsStringAndSize((PyObject *)self, &msg, &size);
286 if (result != 0) {
287 PyErr_Format(PyExc_TypeError, "Failed to extract bytes");
288 return NULL;
290 return PyUnicode_FromStringAndSize(msg, size);
293 static PyTypeObject PyLdbBytesType = {
294 PyVarObject_HEAD_INIT(NULL, 0)
295 .tp_name = "ldb.bytes",
296 .tp_doc = "str/bytes (with custom str)",
297 .tp_str = (reprfunc)py_ldb_bytes_str,
298 .tp_flags = Py_TPFLAGS_DEFAULT|Py_TPFLAGS_BASETYPE,
301 static PyObject *PyObject_FromLdbValue(const struct ldb_val *val)
303 return PyLdbBytes_FromStringAndSize((const char *)val->data, val->length);
306 static PyObject *PyStr_FromLdbValue(const struct ldb_val *val)
308 return PyUnicode_FromStringAndSize((const char *)val->data, val->length);
312 * Create a Python object from a ldb_result.
314 * @param result LDB result to convert
315 * @return Python object with converted result (a list object)
317 static PyObject *PyLdbControl_FromControl(struct ldb_control *control)
319 TALLOC_CTX *ctl_ctx = talloc_new(NULL);
320 PyLdbControlObject *ctrl;
321 if (ctl_ctx == NULL) {
322 PyErr_NoMemory();
323 return NULL;
326 ctrl = (PyLdbControlObject *)PyLdbControl.tp_alloc(&PyLdbControl, 0);
327 if (ctrl == NULL) {
328 talloc_free(ctl_ctx);
329 PyErr_NoMemory();
330 return NULL;
332 ctrl->mem_ctx = ctl_ctx;
333 ctrl->data = talloc_steal(ctrl->mem_ctx, control);
334 if (ctrl->data == NULL) {
335 Py_DECREF(ctrl);
336 PyErr_NoMemory();
337 return NULL;
339 return (PyObject*) ctrl;
343 * Create a Python object from a ldb_result.
345 * @param result LDB result to convert
346 * @return Python object with converted result (a list object)
348 static PyObject *PyLdbResult_FromResult(struct ldb_result *result)
350 PyLdbResultObject *ret;
351 PyObject *list, *controls, *referals;
352 Py_ssize_t i;
354 if (result == NULL) {
355 Py_RETURN_NONE;
358 ret = (PyLdbResultObject *)PyLdbResult.tp_alloc(&PyLdbResult, 0);
359 if (ret == NULL) {
360 PyErr_NoMemory();
361 return NULL;
364 list = PyList_New(result->count);
365 if (list == NULL) {
366 PyErr_NoMemory();
367 Py_DECREF(ret);
368 return NULL;
371 for (i = 0; i < result->count; i++) {
372 PyList_SetItem(list, i, PyLdbMessage_FromMessage(result->msgs[i]));
375 ret->mem_ctx = talloc_new(NULL);
376 if (ret->mem_ctx == NULL) {
377 Py_DECREF(list);
378 Py_DECREF(ret);
379 PyErr_NoMemory();
380 return NULL;
383 ret->msgs = list;
385 if (result->controls) {
386 i = 0;
387 while (result->controls[i]) {
388 i++;
390 controls = PyList_New(i);
391 if (controls == NULL) {
392 Py_DECREF(ret);
393 PyErr_NoMemory();
394 return NULL;
396 for (i=0; result->controls[i]; i++) {
397 PyObject *ctrl = (PyObject*) PyLdbControl_FromControl(result->controls[i]);
398 if (ctrl == NULL) {
399 Py_DECREF(ret);
400 Py_DECREF(controls);
401 PyErr_NoMemory();
402 return NULL;
404 PyList_SetItem(controls, i, ctrl);
406 } else {
408 * No controls so we keep an empty list
410 controls = PyList_New(0);
411 if (controls == NULL) {
412 Py_DECREF(ret);
413 PyErr_NoMemory();
414 return NULL;
418 ret->controls = controls;
420 i = 0;
422 while (result->refs && result->refs[i]) {
423 i++;
426 referals = PyList_New(i);
427 if (referals == NULL) {
428 Py_DECREF(ret);
429 PyErr_NoMemory();
430 return NULL;
433 for (i = 0;result->refs && result->refs[i]; i++) {
434 PyList_SetItem(referals, i, PyUnicode_FromString(result->refs[i]));
436 ret->referals = referals;
437 return (PyObject *)ret;
441 * Create a LDB Result from a Python object.
442 * If conversion fails, NULL will be returned and a Python exception set.
444 * Note: the result object only includes the messages at the moment; extended
445 * result, controls and referrals are ignored.
447 * @param mem_ctx Memory context in which to allocate the LDB Result
448 * @param obj Python object to convert
449 * @return a ldb_result, or NULL if the conversion failed
451 static struct ldb_result *PyLdbResult_AsResult(TALLOC_CTX *mem_ctx,
452 PyObject *obj)
454 struct ldb_result *res;
455 Py_ssize_t i;
457 if (obj == Py_None)
458 return NULL;
460 if (!PyList_Check(obj)) {
461 PyErr_SetString(PyExc_ValueError, "Expected list of LDB results");
462 return NULL;
465 res = talloc_zero(mem_ctx, struct ldb_result);
466 if (res == NULL) {
467 PyErr_NoMemory();
468 return NULL;
470 res->count = PyList_Size(obj);
471 res->msgs = talloc_array(res, struct ldb_message *, res->count);
472 if (res->msgs == NULL) {
473 talloc_free(res);
474 PyErr_NoMemory();
475 return NULL;
477 for (i = 0; i < res->count; i++) {
478 PyObject *item = PyList_GetItem(obj, i);
479 if (item == NULL) {
480 talloc_free(res);
481 return NULL;
483 res->msgs[i] = pyldb_Message_AsMessage(item);
485 return res;
488 static PyObject *py_ldb_dn_validate(PyLdbDnObject *self,
489 PyObject *Py_UNUSED(ignored))
491 return PyBool_FromLong(ldb_dn_validate(self->dn));
494 static PyObject *py_ldb_dn_is_valid(PyLdbDnObject *self,
495 PyObject *Py_UNUSED(ignored))
497 return PyBool_FromLong(ldb_dn_is_valid(self->dn));
500 static PyObject *py_ldb_dn_is_special(PyLdbDnObject *self,
501 PyObject *Py_UNUSED(ignored))
503 return PyBool_FromLong(ldb_dn_is_special(self->dn));
506 static PyObject *py_ldb_dn_is_null(PyLdbDnObject *self,
507 PyObject *Py_UNUSED(ignored))
509 return PyBool_FromLong(ldb_dn_is_null(self->dn));
512 static PyObject *py_ldb_dn_get_casefold(PyLdbDnObject *self,
513 PyObject *Py_UNUSED(ignored))
515 return PyUnicode_FromString(ldb_dn_get_casefold(self->dn));
518 static PyObject *py_ldb_dn_get_linearized(PyLdbDnObject *self,
519 PyObject *Py_UNUSED(ignored))
521 return PyUnicode_FromString(ldb_dn_get_linearized(self->dn));
524 static PyObject *py_ldb_dn_canonical_str(PyLdbDnObject *self,
525 PyObject *Py_UNUSED(ignored))
527 return PyUnicode_FromString(ldb_dn_canonical_string(self->dn, self->dn));
530 static PyObject *py_ldb_dn_canonical_ex_str(PyLdbDnObject *self,
531 PyObject *Py_UNUSED(ignored))
533 return PyUnicode_FromString(ldb_dn_canonical_ex_string(self->dn, self->dn));
536 static PyObject *py_ldb_dn_extended_str(PyLdbDnObject *self, PyObject *args, PyObject *kwargs)
538 const char * const kwnames[] = { "mode", NULL };
539 int mode = 1;
540 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "|i",
541 discard_const_p(char *, kwnames),
542 &mode))
543 return NULL;
544 return PyUnicode_FromString(ldb_dn_get_extended_linearized(self->dn, self->dn, mode));
547 static PyObject *py_ldb_dn_get_extended_component(PyLdbDnObject *self, PyObject *args)
549 char *name;
550 const struct ldb_val *val;
552 if (!PyArg_ParseTuple(args, "s", &name))
553 return NULL;
554 val = ldb_dn_get_extended_component(self->dn, name);
555 if (val == NULL) {
556 Py_RETURN_NONE;
559 return PyBytes_FromStringAndSize((const char *)val->data, val->length);
562 static PyObject *py_ldb_dn_set_extended_component(PyLdbDnObject *self, PyObject *args)
564 char *name;
565 int err;
566 uint8_t *value = NULL;
567 Py_ssize_t size = 0;
569 if (!PyArg_ParseTuple(args, "sz#", &name, (char **)&value, &size))
570 return NULL;
572 if (value == NULL) {
573 err = ldb_dn_set_extended_component(self->dn, name, NULL);
574 } else {
575 struct ldb_val val;
576 val.data = (uint8_t *)value;
577 val.length = size;
578 err = ldb_dn_set_extended_component(self->dn, name, &val);
581 if (err != LDB_SUCCESS) {
582 PyErr_SetString(PyExc_TypeError, "Failed to set extended component");
583 return NULL;
586 Py_RETURN_NONE;
589 static PyObject *py_ldb_dn_repr(PyLdbDnObject *self)
591 PyObject *str = PyUnicode_FromString(ldb_dn_get_linearized(self->dn));
592 PyObject *repr, *result;
593 if (str == NULL)
594 return NULL;
595 repr = PyObject_Repr(str);
596 if (repr == NULL) {
597 Py_DECREF(str);
598 return NULL;
600 result = PyUnicode_FromFormat("Dn(%s)", PyUnicode_AsUTF8(repr));
601 Py_DECREF(str);
602 Py_DECREF(repr);
603 return result;
606 static PyObject *py_ldb_dn_check_special(PyLdbDnObject *self, PyObject *args)
608 char *name;
610 if (!PyArg_ParseTuple(args, "s", &name))
611 return NULL;
613 return PyBool_FromLong(ldb_dn_check_special(self->dn, name));
616 static PyObject *py_ldb_dn_richcmp(PyObject *dn1, PyObject *dn2, int op)
618 int ret;
619 if (!pyldb_Dn_Check(dn2)) {
620 Py_INCREF(Py_NotImplemented);
621 return Py_NotImplemented;
623 ret = ldb_dn_compare(pyldb_Dn_AS_DN(dn1), pyldb_Dn_AS_DN(dn2));
624 return richcmp(ret, op);
627 static PyObject *py_ldb_dn_get_parent(PyLdbDnObject *self,
628 PyObject *Py_UNUSED(ignored))
630 struct ldb_dn *dn = pyldb_Dn_AS_DN((PyObject *)self);
631 struct ldb_dn *parent;
632 PyLdbDnObject *py_ret;
633 TALLOC_CTX *mem_ctx = NULL;
635 if (ldb_dn_get_comp_num(dn) < 1) {
636 Py_RETURN_NONE;
639 mem_ctx = talloc_new(NULL);
640 if (mem_ctx == NULL) {
641 PyErr_NoMemory();
642 return NULL;
645 parent = ldb_dn_get_parent(mem_ctx, dn);
646 if (parent == NULL) {
647 PyErr_NoMemory();
648 talloc_free(mem_ctx);
649 return NULL;
652 py_ret = (PyLdbDnObject *)PyLdbDn.tp_alloc(&PyLdbDn, 0);
653 if (py_ret == NULL) {
654 PyErr_NoMemory();
655 talloc_free(mem_ctx);
656 return NULL;
658 py_ret->mem_ctx = mem_ctx;
659 py_ret->dn = parent;
660 return (PyObject *)py_ret;
663 static PyObject *py_ldb_dn_add_child(PyLdbDnObject *self, PyObject *args)
665 PyObject *py_other;
666 struct ldb_dn *dn, *other;
667 bool ok;
668 if (!PyArg_ParseTuple(args, "O", &py_other))
669 return NULL;
671 dn = pyldb_Dn_AS_DN((PyObject *)self);
673 if (!pyldb_Object_AsDn(NULL, py_other, ldb_dn_get_ldb_context(dn), &other))
674 return NULL;
676 ok = ldb_dn_add_child(dn, other);
677 if (!ok) {
678 PyErr_SetLdbError(PyExc_LdbError, LDB_ERR_OPERATIONS_ERROR, NULL);
679 return NULL;
682 Py_RETURN_TRUE;
685 static PyObject *py_ldb_dn_add_base(PyLdbDnObject *self, PyObject *args)
687 PyObject *py_other;
688 struct ldb_dn *other, *dn;
689 bool ok;
690 if (!PyArg_ParseTuple(args, "O", &py_other))
691 return NULL;
693 dn = pyldb_Dn_AS_DN((PyObject *)self);
695 if (!pyldb_Object_AsDn(NULL, py_other, ldb_dn_get_ldb_context(dn), &other))
696 return NULL;
698 ok = ldb_dn_add_base(dn, other);
699 if (!ok) {
700 PyErr_SetLdbError(PyExc_LdbError, LDB_ERR_OPERATIONS_ERROR, NULL);
701 return NULL;
704 Py_RETURN_TRUE;
707 static PyObject *py_ldb_dn_remove_base_components(PyLdbDnObject *self, PyObject *args)
709 struct ldb_dn *dn;
710 int i;
711 bool ok;
712 if (!PyArg_ParseTuple(args, "i", &i))
713 return NULL;
715 dn = pyldb_Dn_AS_DN((PyObject *)self);
717 ok = ldb_dn_remove_base_components(dn, i);
718 if (!ok) {
719 PyErr_SetLdbError(PyExc_LdbError, LDB_ERR_OPERATIONS_ERROR, NULL);
720 return NULL;
723 Py_RETURN_TRUE;
726 static PyObject *py_ldb_dn_is_child_of(PyLdbDnObject *self, PyObject *args)
728 PyObject *py_base;
729 struct ldb_dn *dn, *base;
730 if (!PyArg_ParseTuple(args, "O", &py_base))
731 return NULL;
733 dn = pyldb_Dn_AS_DN((PyObject *)self);
735 if (!pyldb_Object_AsDn(NULL, py_base, ldb_dn_get_ldb_context(dn), &base))
736 return NULL;
738 return PyBool_FromLong(ldb_dn_compare_base(base, dn) == 0);
741 static PyObject *py_ldb_dn_get_component_name(PyLdbDnObject *self, PyObject *args)
743 struct ldb_dn *dn;
744 const char *name;
745 unsigned int num = 0;
747 if (!PyArg_ParseTuple(args, "I", &num))
748 return NULL;
750 dn = pyldb_Dn_AS_DN((PyObject *)self);
752 name = ldb_dn_get_component_name(dn, num);
753 if (name == NULL) {
754 Py_RETURN_NONE;
757 return PyUnicode_FromString(name);
760 static PyObject *py_ldb_dn_get_component_value(PyLdbDnObject *self, PyObject *args)
762 struct ldb_dn *dn;
763 const struct ldb_val *val;
764 unsigned int num = 0;
766 if (!PyArg_ParseTuple(args, "I", &num))
767 return NULL;
769 dn = pyldb_Dn_AS_DN((PyObject *)self);
771 val = ldb_dn_get_component_val(dn, num);
772 if (val == NULL) {
773 Py_RETURN_NONE;
776 return PyStr_FromLdbValue(val);
779 static PyObject *py_ldb_dn_set_component(PyLdbDnObject *self, PyObject *args)
781 unsigned int num = 0;
782 char *name = NULL, *value = NULL;
783 struct ldb_val val = { 0 };
784 int err;
785 Py_ssize_t size = 0;
787 if (!PyArg_ParseTuple(args, "Iss#", &num, &name, &value, &size))
788 return NULL;
790 val.data = (unsigned char*) value;
791 val.length = size;
793 err = ldb_dn_set_component(self->dn, num, name, val);
794 if (err != LDB_SUCCESS) {
795 PyErr_SetString(PyExc_TypeError, "Failed to set component");
796 return NULL;
799 Py_RETURN_NONE;
802 static PyObject *py_ldb_dn_get_rdn_name(PyLdbDnObject *self,
803 PyObject *Py_UNUSED(ignored))
805 struct ldb_dn *dn;
806 const char *name;
808 dn = pyldb_Dn_AS_DN((PyObject *)self);
810 name = ldb_dn_get_rdn_name(dn);
811 if (name == NULL) {
812 Py_RETURN_NONE;
815 return PyUnicode_FromString(name);
818 static PyObject *py_ldb_dn_get_rdn_value(PyLdbDnObject *self,
819 PyObject *Py_UNUSED(ignored))
821 struct ldb_dn *dn;
822 const struct ldb_val *val;
824 dn = pyldb_Dn_AS_DN((PyObject *)self);
826 val = ldb_dn_get_rdn_val(dn);
827 if (val == NULL) {
828 Py_RETURN_NONE;
831 return PyStr_FromLdbValue(val);
834 static PyMethodDef py_ldb_dn_methods[] = {
835 { "validate", (PyCFunction)py_ldb_dn_validate, METH_NOARGS,
836 "S.validate() -> bool\n"
837 "Validate DN is correct." },
838 { "is_valid", (PyCFunction)py_ldb_dn_is_valid, METH_NOARGS,
839 "S.is_valid() -> bool\n" },
840 { "is_special", (PyCFunction)py_ldb_dn_is_special, METH_NOARGS,
841 "S.is_special() -> bool\n"
842 "Check whether this is a special LDB DN." },
843 { "is_null", (PyCFunction)py_ldb_dn_is_null, METH_NOARGS,
844 "Check whether this is a null DN." },
845 { "get_casefold", (PyCFunction)py_ldb_dn_get_casefold, METH_NOARGS,
846 NULL },
847 { "get_linearized", PY_DISCARD_FUNC_SIG(PyCFunction,
848 py_ldb_dn_get_linearized),
849 METH_NOARGS,
850 NULL },
851 { "canonical_str", (PyCFunction)py_ldb_dn_canonical_str, METH_NOARGS,
852 "S.canonical_str() -> string\n"
853 "Canonical version of this DN (like a posix path)." },
854 { "is_child_of", (PyCFunction)py_ldb_dn_is_child_of, METH_VARARGS,
855 "S.is_child_of(basedn) -> int\nReturns True if this DN is a child of basedn\n"},
856 { "canonical_ex_str", (PyCFunction)py_ldb_dn_canonical_ex_str, METH_NOARGS,
857 "S.canonical_ex_str() -> string\n"
858 "Canonical version of this DN (like a posix path, with terminating newline)." },
859 { "extended_str", PY_DISCARD_FUNC_SIG(PyCFunction,
860 py_ldb_dn_extended_str),
861 METH_VARARGS | METH_KEYWORDS,
862 "S.extended_str(mode=1) -> string\n"
863 "Extended version of this DN" },
864 { "parent", (PyCFunction)py_ldb_dn_get_parent, METH_NOARGS,
865 "S.parent() -> dn\n"
866 "Get the parent for this DN." },
867 { "add_child", (PyCFunction)py_ldb_dn_add_child, METH_VARARGS,
868 "S.add_child(dn) -> bool\n"
869 "Add a child DN to this DN." },
870 { "add_base", (PyCFunction)py_ldb_dn_add_base, METH_VARARGS,
871 "S.add_base(dn) -> bool\n"
872 "Add a base DN to this DN." },
873 { "remove_base_components", (PyCFunction)py_ldb_dn_remove_base_components, METH_VARARGS,
874 "S.remove_base_components(int) -> bool\n"
875 "Remove a number of DN components from the base of this DN." },
876 { "check_special", (PyCFunction)py_ldb_dn_check_special, METH_VARARGS,
877 "S.check_special(name) -> bool\n\n"
878 "Check if name is a special DN name"},
879 { "get_extended_component", (PyCFunction)py_ldb_dn_get_extended_component, METH_VARARGS,
880 "S.get_extended_component(name) -> string\n\n"
881 "returns a DN extended component as a binary string"},
882 { "set_extended_component", (PyCFunction)py_ldb_dn_set_extended_component, METH_VARARGS,
883 "S.set_extended_component(name, value) -> None\n\n"
884 "set a DN extended component as a binary string"},
885 { "get_component_name", (PyCFunction)py_ldb_dn_get_component_name, METH_VARARGS,
886 "S.get_component_name(num) -> string\n"
887 "get the attribute name of the specified component" },
888 { "get_component_value", (PyCFunction)py_ldb_dn_get_component_value, METH_VARARGS,
889 "S.get_component_value(num) -> string\n"
890 "get the attribute value of the specified component as a binary string" },
891 { "set_component", (PyCFunction)py_ldb_dn_set_component, METH_VARARGS,
892 "S.set_component(num, name, value) -> None\n"
893 "set the attribute name and value of the specified component" },
894 { "get_rdn_name", (PyCFunction)py_ldb_dn_get_rdn_name, METH_NOARGS,
895 "S.get_rdn_name() -> string\n"
896 "get the RDN attribute name" },
897 { "get_rdn_value", (PyCFunction)py_ldb_dn_get_rdn_value, METH_NOARGS,
898 "S.get_rdn_value() -> string\n"
899 "get the RDN attribute value as a binary string" },
903 static Py_ssize_t py_ldb_dn_len(PyLdbDnObject *self)
905 return ldb_dn_get_comp_num(pyldb_Dn_AS_DN((PyObject *)self));
909 copy a DN as a python object
911 static PyObject *py_ldb_dn_copy(struct ldb_dn *dn)
913 TALLOC_CTX *mem_ctx = NULL;
914 struct ldb_dn *new_dn = NULL;
915 PyLdbDnObject *py_ret;
917 mem_ctx = talloc_new(NULL);
918 if (mem_ctx == NULL) {
919 return PyErr_NoMemory();
922 new_dn = ldb_dn_copy(mem_ctx, dn);
923 if (new_dn == NULL) {
924 talloc_free(mem_ctx);
925 return PyErr_NoMemory();
928 py_ret = (PyLdbDnObject *)PyLdbDn.tp_alloc(&PyLdbDn, 0);
929 if (py_ret == NULL) {
930 talloc_free(mem_ctx);
931 PyErr_NoMemory();
932 return NULL;
934 py_ret->mem_ctx = mem_ctx;
935 py_ret->dn = new_dn;
936 return (PyObject *)py_ret;
939 static PyObject *py_ldb_dn_concat(PyLdbDnObject *self, PyObject *py_other)
941 TALLOC_CTX *mem_ctx = NULL;
942 struct ldb_dn *dn = pyldb_Dn_AS_DN((PyObject *)self),
943 *other;
944 struct ldb_dn *new_dn = NULL;
945 PyLdbDnObject *py_ret;
947 if (!pyldb_Object_AsDn(NULL, py_other, NULL, &other))
948 return NULL;
950 mem_ctx = talloc_new(NULL);
951 if (mem_ctx == NULL) {
952 return PyErr_NoMemory();
955 new_dn = ldb_dn_copy(mem_ctx, dn);
956 if (new_dn == NULL) {
957 talloc_free(mem_ctx);
958 return PyErr_NoMemory();
961 if (!ldb_dn_add_base(new_dn, other)) {
962 PyErr_SetString(PyExc_RuntimeError, "unable to concatenate DNs");
963 talloc_free(mem_ctx);
964 return NULL;
967 py_ret = (PyLdbDnObject *)PyLdbDn.tp_alloc(&PyLdbDn, 0);
968 if (py_ret == NULL) {
969 talloc_free(mem_ctx);
970 PyErr_NoMemory();
971 return NULL;
973 py_ret->mem_ctx = mem_ctx;
974 py_ret->dn = new_dn;
976 return (PyObject *)py_ret;
979 static PySequenceMethods py_ldb_dn_seq = {
980 .sq_length = (lenfunc)py_ldb_dn_len,
981 .sq_concat = (binaryfunc)py_ldb_dn_concat,
984 static PyObject *py_ldb_dn_new(PyTypeObject *type, PyObject *args, PyObject *kwargs)
986 struct ldb_dn *ret = NULL;
987 char *str = NULL;
988 PyObject *py_ldb = NULL;
989 struct ldb_context *ldb_ctx = NULL;
990 TALLOC_CTX *mem_ctx = NULL;
991 PyLdbDnObject *py_ret = NULL;
992 const char * const kwnames[] = { "ldb", "dn", NULL };
994 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "O"PYARG_STR_UNI,
995 discard_const_p(char *, kwnames),
996 &py_ldb, "utf8", &str))
997 goto out;
999 if (!PyLdb_Check(py_ldb)) {
1000 PyErr_SetString(PyExc_TypeError, "Expected Ldb");
1001 goto out;
1003 ldb_ctx = pyldb_Ldb_AS_LDBCONTEXT(py_ldb);
1005 mem_ctx = talloc_new(NULL);
1006 if (mem_ctx == NULL) {
1007 PyErr_NoMemory();
1008 goto out;
1011 ret = ldb_dn_new(mem_ctx, ldb_ctx, str);
1012 if (!ldb_dn_validate(ret)) {
1013 talloc_free(mem_ctx);
1014 PyErr_SetString(PyExc_ValueError, "unable to parse dn string");
1015 goto out;
1018 py_ret = (PyLdbDnObject *)type->tp_alloc(type, 0);
1019 if (py_ret == NULL) {
1020 talloc_free(mem_ctx);
1021 PyErr_NoMemory();
1022 goto out;
1024 py_ret->mem_ctx = mem_ctx;
1025 py_ret->dn = ret;
1026 out:
1027 if (str != NULL) {
1028 PyMem_Free(discard_const_p(char, str));
1030 return (PyObject *)py_ret;
1033 static void py_ldb_dn_dealloc(PyLdbDnObject *self)
1035 talloc_free(self->mem_ctx);
1036 PyObject_Del(self);
1039 static PyTypeObject PyLdbDn = {
1040 .tp_name = "ldb.Dn",
1041 .tp_methods = py_ldb_dn_methods,
1042 .tp_str = (reprfunc)py_ldb_dn_get_linearized,
1043 .tp_repr = (reprfunc)py_ldb_dn_repr,
1044 .tp_richcompare = (richcmpfunc)py_ldb_dn_richcmp,
1045 .tp_as_sequence = &py_ldb_dn_seq,
1046 .tp_doc = "A LDB distinguished name.",
1047 .tp_new = py_ldb_dn_new,
1048 .tp_dealloc = (destructor)py_ldb_dn_dealloc,
1049 .tp_basicsize = sizeof(PyLdbDnObject),
1050 .tp_flags = Py_TPFLAGS_DEFAULT,
1053 /* Debug */
1054 static void py_ldb_debug(void *context, enum ldb_debug_level level, const char *fmt, va_list ap) PRINTF_ATTRIBUTE(3, 0);
1055 static void py_ldb_debug(void *context, enum ldb_debug_level level, const char *fmt, va_list ap)
1057 PyObject *fn = (PyObject *)context;
1058 PyObject *result = NULL;
1059 result = PyObject_CallFunction(fn, discard_const_p(char, "(i,O)"), level, PyUnicode_FromFormatV(fmt, ap));
1060 Py_XDECREF(result);
1063 static PyObject *py_ldb_debug_func;
1065 static PyObject *py_ldb_set_debug(PyObject *self, PyObject *args)
1067 PyObject *cb;
1068 struct ldb_context *ldb_ctx;
1070 if (!PyArg_ParseTuple(args, "O", &cb))
1071 return NULL;
1073 if (py_ldb_debug_func != NULL) {
1074 Py_DECREF(py_ldb_debug_func);
1077 Py_INCREF(cb);
1078 /* FIXME: DECREF cb when exiting program */
1079 py_ldb_debug_func = cb;
1080 ldb_ctx = pyldb_Ldb_AS_LDBCONTEXT(self);
1081 PyErr_LDB_ERROR_IS_ERR_RAISE(PyExc_LdbError,
1082 ldb_set_debug(ldb_ctx, py_ldb_debug, cb),
1083 ldb_ctx);
1085 Py_RETURN_NONE;
1088 static PyObject *py_ldb_set_create_perms(PyTypeObject *self, PyObject *args)
1090 unsigned int perms;
1091 if (!PyArg_ParseTuple(args, "I", &perms))
1092 return NULL;
1094 ldb_set_create_perms(pyldb_Ldb_AS_LDBCONTEXT(self), perms);
1096 Py_RETURN_NONE;
1099 static PyObject *py_ldb_set_modules_dir(PyTypeObject *self, PyObject *args)
1101 char *modules_dir;
1102 if (!PyArg_ParseTuple(args, "s", &modules_dir))
1103 return NULL;
1105 ldb_set_modules_dir(pyldb_Ldb_AS_LDBCONTEXT(self), modules_dir);
1107 Py_RETURN_NONE;
1110 static PyObject *py_ldb_transaction_start(PyLdbObject *self,
1111 PyObject *Py_UNUSED(ignored))
1113 struct ldb_context *ldb_ctx = pyldb_Ldb_AS_LDBCONTEXT(self);
1114 int ldb_err;
1115 ldb_err = ldb_transaction_start(ldb_ctx);
1116 PyErr_LDB_ERROR_IS_ERR_RAISE(PyExc_LdbError, ldb_err, ldb_ctx);
1117 Py_RETURN_NONE;
1120 static PyObject *py_ldb_transaction_commit(PyLdbObject *self,
1121 PyObject *Py_UNUSED(ignored))
1123 struct ldb_context *ldb_ctx = pyldb_Ldb_AS_LDBCONTEXT(self);
1124 int ldb_err;
1125 ldb_err = ldb_transaction_commit(ldb_ctx);
1126 PyErr_LDB_ERROR_IS_ERR_RAISE(PyExc_LdbError, ldb_err, ldb_ctx);
1127 Py_RETURN_NONE;
1130 static PyObject *py_ldb_transaction_prepare_commit(PyLdbObject *self,
1131 PyObject *Py_UNUSED(ignored))
1133 struct ldb_context *ldb_ctx = pyldb_Ldb_AS_LDBCONTEXT(self);
1134 int ldb_err;
1135 ldb_err = ldb_transaction_prepare_commit(ldb_ctx);
1136 PyErr_LDB_ERROR_IS_ERR_RAISE(PyExc_LdbError, ldb_err, ldb_ctx);
1137 Py_RETURN_NONE;
1140 static PyObject *py_ldb_transaction_cancel(PyLdbObject *self,
1141 PyObject *Py_UNUSED(ignored))
1143 struct ldb_context *ldb_ctx = pyldb_Ldb_AS_LDBCONTEXT(self);
1144 int ldb_err;
1145 ldb_err = ldb_transaction_cancel(ldb_ctx);
1146 PyErr_LDB_ERROR_IS_ERR_RAISE(PyExc_LdbError, ldb_err, ldb_ctx);
1147 Py_RETURN_NONE;
1150 static PyObject *py_ldb_setup_wellknown_attributes(PyLdbObject *self,
1151 PyObject *Py_UNUSED(ignored))
1153 struct ldb_context *ldb_ctx = pyldb_Ldb_AS_LDBCONTEXT(self);
1154 int ldb_err;
1155 ldb_err = ldb_setup_wellknown_attributes(ldb_ctx);
1156 PyErr_LDB_ERROR_IS_ERR_RAISE(PyExc_LdbError, ldb_err, ldb_ctx);
1157 Py_RETURN_NONE;
1160 static PyObject *py_ldb_repr(PyLdbObject *self)
1162 return PyUnicode_FromString("<ldb connection>");
1165 static PyObject *py_ldb_get_root_basedn(PyLdbObject *self,
1166 PyObject *Py_UNUSED(ignored))
1168 struct ldb_dn *dn = ldb_get_root_basedn(pyldb_Ldb_AS_LDBCONTEXT(self));
1169 if (dn == NULL)
1170 Py_RETURN_NONE;
1171 return py_ldb_dn_copy(dn);
1175 static PyObject *py_ldb_get_schema_basedn(PyLdbObject *self,
1176 PyObject *Py_UNUSED(ignored))
1178 struct ldb_dn *dn = ldb_get_schema_basedn(pyldb_Ldb_AS_LDBCONTEXT(self));
1179 if (dn == NULL)
1180 Py_RETURN_NONE;
1181 return py_ldb_dn_copy(dn);
1184 static PyObject *py_ldb_get_config_basedn(PyLdbObject *self,
1185 PyObject *Py_UNUSED(ignored))
1187 struct ldb_dn *dn = ldb_get_config_basedn(pyldb_Ldb_AS_LDBCONTEXT(self));
1188 if (dn == NULL)
1189 Py_RETURN_NONE;
1190 return py_ldb_dn_copy(dn);
1193 static PyObject *py_ldb_get_default_basedn(PyLdbObject *self,
1194 PyObject *Py_UNUSED(ignored))
1196 struct ldb_dn *dn = ldb_get_default_basedn(pyldb_Ldb_AS_LDBCONTEXT(self));
1197 if (dn == NULL)
1198 Py_RETURN_NONE;
1199 return py_ldb_dn_copy(dn);
1202 static const char **PyList_AsStrList(TALLOC_CTX *mem_ctx, PyObject *list,
1203 const char *paramname)
1205 const char **ret;
1206 Py_ssize_t i;
1207 if (!PyList_Check(list)) {
1208 PyErr_Format(PyExc_TypeError, "%s is not a list", paramname);
1209 return NULL;
1211 ret = talloc_array(NULL, const char *, PyList_Size(list)+1);
1212 if (ret == NULL) {
1213 PyErr_NoMemory();
1214 return NULL;
1217 for (i = 0; i < PyList_Size(list); i++) {
1218 const char *str = NULL;
1219 Py_ssize_t size;
1220 PyObject *item = PyList_GetItem(list, i);
1221 if (!PyUnicode_Check(item)) {
1222 PyErr_Format(PyExc_TypeError, "%s should be strings", paramname);
1223 talloc_free(ret);
1224 return NULL;
1226 str = PyUnicode_AsUTF8AndSize(item, &size);
1227 if (str == NULL) {
1228 talloc_free(ret);
1229 return NULL;
1231 ret[i] = talloc_strndup(ret, str, size);
1233 ret[i] = NULL;
1234 return ret;
1237 static int py_ldb_init(PyLdbObject *self, PyObject *args, PyObject *kwargs)
1239 const char * const kwnames[] = { "url", "flags", "options", NULL };
1240 char *url = NULL;
1241 PyObject *py_options = Py_None;
1242 const char **options;
1243 unsigned int flags = 0;
1244 int ret;
1245 struct ldb_context *ldb;
1247 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "|zIO:Ldb.__init__",
1248 discard_const_p(char *, kwnames),
1249 &url, &flags, &py_options))
1250 return -1;
1252 ldb = pyldb_Ldb_AS_LDBCONTEXT(self);
1254 if (py_options == Py_None) {
1255 options = NULL;
1256 } else {
1257 options = PyList_AsStrList(ldb, py_options, "options");
1258 if (options == NULL)
1259 return -1;
1262 if (url != NULL) {
1263 ret = ldb_connect(ldb, url, flags, options);
1264 if (ret != LDB_SUCCESS) {
1265 PyErr_SetLdbError(PyExc_LdbError, ret, ldb);
1266 talloc_free(options);
1267 return -1;
1269 } else {
1270 ldb_set_flags(ldb, flags);
1273 talloc_free(options);
1274 return 0;
1277 static PyObject *py_ldb_new(PyTypeObject *type, PyObject *args, PyObject *kwargs)
1279 TALLOC_CTX *mem_ctx = NULL;
1280 PyLdbObject *ret;
1281 struct ldb_context *ldb;
1283 mem_ctx = talloc_new(NULL);
1284 if (mem_ctx == NULL) {
1285 return PyErr_NoMemory();
1288 ldb = ldb_init(mem_ctx, NULL);
1289 if (ldb == NULL) {
1290 talloc_free(mem_ctx);
1291 PyErr_NoMemory();
1292 return NULL;
1295 ret = (PyLdbObject *)type->tp_alloc(type, 0);
1296 if (ret == NULL) {
1297 talloc_free(mem_ctx);
1298 PyErr_NoMemory();
1299 return NULL;
1301 ret->mem_ctx = mem_ctx;
1303 ret->ldb_ctx = ldb;
1304 return (PyObject *)ret;
1307 static PyObject *py_ldb_connect(PyLdbObject *self, PyObject *args, PyObject *kwargs)
1309 char *url = NULL;
1310 unsigned int flags = 0;
1311 PyObject *py_options = Py_None;
1312 int ret;
1313 const char **options;
1314 const char * const kwnames[] = { "url", "flags", "options", NULL };
1315 struct ldb_context *ldb_ctx;
1317 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "z|IO",
1318 discard_const_p(char *, kwnames),
1319 &url, &flags, &py_options))
1320 return NULL;
1322 if (py_options == Py_None) {
1323 options = NULL;
1324 } else {
1325 options = PyList_AsStrList(NULL, py_options, "options");
1326 if (options == NULL)
1327 return NULL;
1330 ldb_ctx = pyldb_Ldb_AS_LDBCONTEXT(self);
1331 ret = ldb_connect(ldb_ctx, url, flags, options);
1332 talloc_free(options);
1334 PyErr_LDB_ERROR_IS_ERR_RAISE(PyExc_LdbError, ret, ldb_ctx);
1336 Py_RETURN_NONE;
1339 static PyObject *py_ldb_modify(PyLdbObject *self, PyObject *args, PyObject *kwargs)
1341 PyObject *py_msg;
1342 PyObject *py_controls = Py_None;
1343 struct ldb_context *ldb_ctx;
1344 struct ldb_request *req;
1345 struct ldb_control **parsed_controls;
1346 struct ldb_message *msg;
1347 int ret;
1348 TALLOC_CTX *mem_ctx;
1349 bool validate=true;
1350 const char * const kwnames[] = { "message", "controls", "validate", NULL };
1352 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "O|Ob",
1353 discard_const_p(char *, kwnames),
1354 &py_msg, &py_controls, &validate))
1355 return NULL;
1357 mem_ctx = talloc_new(NULL);
1358 if (mem_ctx == NULL) {
1359 PyErr_NoMemory();
1360 return NULL;
1362 ldb_ctx = pyldb_Ldb_AS_LDBCONTEXT(self);
1364 if (py_controls == Py_None) {
1365 parsed_controls = NULL;
1366 } else {
1367 const char **controls = PyList_AsStrList(mem_ctx, py_controls, "controls");
1368 if (controls == NULL) {
1369 talloc_free(mem_ctx);
1370 return NULL;
1372 parsed_controls = ldb_parse_control_strings(ldb_ctx, mem_ctx, controls);
1373 if (controls[0] != NULL && parsed_controls == NULL) {
1374 talloc_free(mem_ctx);
1375 PyErr_SetLdbError(PyExc_LdbError, LDB_ERR_OPERATIONS_ERROR, ldb_ctx);
1376 return NULL;
1378 talloc_free(controls);
1381 if (!PyLdbMessage_Check(py_msg)) {
1382 PyErr_SetString(PyExc_TypeError, "Expected Ldb Message");
1383 talloc_free(mem_ctx);
1384 return NULL;
1386 msg = pyldb_Message_AsMessage(py_msg);
1388 if (validate) {
1389 ret = ldb_msg_sanity_check(ldb_ctx, msg);
1390 if (ret != LDB_SUCCESS) {
1391 PyErr_SetLdbError(PyExc_LdbError, ret, ldb_ctx);
1392 talloc_free(mem_ctx);
1393 return NULL;
1397 ret = ldb_build_mod_req(&req, ldb_ctx, mem_ctx, msg, parsed_controls,
1398 NULL, ldb_op_default_callback, NULL);
1399 if (ret != LDB_SUCCESS) {
1400 PyErr_SetString(PyExc_TypeError, "failed to build request");
1401 talloc_free(mem_ctx);
1402 return NULL;
1405 /* do request and autostart a transaction */
1406 /* Then let's LDB handle the message error in case of pb as they are meaningful */
1408 ret = ldb_transaction_start(ldb_ctx);
1409 if (ret != LDB_SUCCESS) {
1410 talloc_free(mem_ctx);
1411 PyErr_SetLdbError(PyExc_LdbError, ret, ldb_ctx);
1412 return NULL;
1415 ret = ldb_request(ldb_ctx, req);
1416 if (ret == LDB_SUCCESS) {
1417 ret = ldb_wait(req->handle, LDB_WAIT_ALL);
1420 if (ret == LDB_SUCCESS) {
1421 ret = ldb_transaction_commit(ldb_ctx);
1422 } else {
1423 ldb_transaction_cancel(ldb_ctx);
1426 talloc_free(mem_ctx);
1427 PyErr_LDB_ERROR_IS_ERR_RAISE(PyExc_LdbError, ret, ldb_ctx);
1429 Py_RETURN_NONE;
1434 * Obtain a ldb message from a Python Dictionary object.
1436 * @param mem_ctx Memory context
1437 * @param py_obj Python Dictionary object
1438 * @param ldb_ctx LDB context
1439 * @param mod_flags Flags to be set on every message element
1440 * @return ldb_message on success or NULL on failure
1442 static struct ldb_message *PyDict_AsMessage(TALLOC_CTX *mem_ctx,
1443 PyObject *py_obj,
1444 struct ldb_context *ldb_ctx,
1445 unsigned int mod_flags)
1447 struct ldb_message *msg;
1448 unsigned int msg_pos = 0;
1449 Py_ssize_t dict_pos = 0;
1450 PyObject *key, *value;
1451 struct ldb_message_element *msg_el;
1452 PyObject *dn_value = PyDict_GetItemString(py_obj, "dn");
1454 msg = ldb_msg_new(mem_ctx);
1455 if (msg == NULL) {
1456 PyErr_NoMemory();
1457 return NULL;
1459 msg->elements = talloc_zero_array(msg, struct ldb_message_element, PyDict_Size(py_obj));
1460 if (msg->elements == NULL) {
1461 PyErr_NoMemory();
1462 TALLOC_FREE(msg);
1463 return NULL;
1466 if (dn_value) {
1467 if (!pyldb_Object_AsDn(msg, dn_value, ldb_ctx, &msg->dn)) {
1468 PyErr_SetString(PyExc_TypeError, "unable to import dn object");
1469 TALLOC_FREE(msg);
1470 return NULL;
1472 if (msg->dn == NULL) {
1473 PyErr_SetString(PyExc_TypeError, "dn set but not found");
1474 TALLOC_FREE(msg);
1475 return NULL;
1477 } else {
1478 PyErr_SetString(PyExc_TypeError, "no dn set");
1479 TALLOC_FREE(msg);
1480 return NULL;
1483 while (PyDict_Next(py_obj, &dict_pos, &key, &value)) {
1484 const char *key_str = PyUnicode_AsUTF8(key);
1485 if (ldb_attr_cmp(key_str, "dn") != 0) {
1486 msg_el = PyObject_AsMessageElement(msg->elements, value,
1487 mod_flags, key_str);
1488 if (msg_el == NULL) {
1489 PyErr_Format(PyExc_TypeError, "unable to import element '%s'", key_str);
1490 TALLOC_FREE(msg);
1491 return NULL;
1493 memcpy(&msg->elements[msg_pos], msg_el, sizeof(*msg_el));
1496 * PyObject_AsMessageElement might have returned a
1497 * reference to an existing MessageElement, and so left
1498 * the name and flags unchanged. Thus if those members
1499 * aren’t set, we’ll assume that the user forgot to
1500 * initialize them.
1502 if (msg->elements[msg_pos].name == NULL) {
1503 /* No name was set — set it now. */
1504 msg->elements[msg_pos].name = talloc_strdup(msg->elements, key_str);
1505 if (msg->elements[msg_pos].name == NULL) {
1506 PyErr_NoMemory();
1507 TALLOC_FREE(msg);
1508 return NULL;
1511 if (msg->elements[msg_pos].flags == 0) {
1512 /* No flags were set — set them now. */
1513 msg->elements[msg_pos].flags = mod_flags;
1516 msg_pos++;
1520 msg->num_elements = msg_pos;
1522 return msg;
1525 static PyObject *py_ldb_add(PyLdbObject *self, PyObject *args, PyObject *kwargs)
1527 PyObject *py_obj;
1528 int ret;
1529 struct ldb_context *ldb_ctx;
1530 struct ldb_request *req;
1531 struct ldb_message *msg = NULL;
1532 PyObject *py_controls = Py_None;
1533 TALLOC_CTX *mem_ctx;
1534 struct ldb_control **parsed_controls;
1535 const char * const kwnames[] = { "message", "controls", NULL };
1537 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "O|O",
1538 discard_const_p(char *, kwnames),
1539 &py_obj, &py_controls))
1540 return NULL;
1542 mem_ctx = talloc_new(NULL);
1543 if (mem_ctx == NULL) {
1544 PyErr_NoMemory();
1545 return NULL;
1547 ldb_ctx = pyldb_Ldb_AS_LDBCONTEXT(self);
1549 if (py_controls == Py_None) {
1550 parsed_controls = NULL;
1551 } else {
1552 const char **controls = PyList_AsStrList(mem_ctx, py_controls, "controls");
1553 if (controls == NULL) {
1554 talloc_free(mem_ctx);
1555 return NULL;
1557 parsed_controls = ldb_parse_control_strings(ldb_ctx, mem_ctx, controls);
1558 if (controls[0] != NULL && parsed_controls == NULL) {
1559 talloc_free(mem_ctx);
1560 PyErr_SetLdbError(PyExc_LdbError, LDB_ERR_OPERATIONS_ERROR, ldb_ctx);
1561 return NULL;
1563 talloc_free(controls);
1566 if (PyLdbMessage_Check(py_obj)) {
1567 msg = pyldb_Message_AsMessage(py_obj);
1568 } else if (PyDict_Check(py_obj)) {
1569 msg = PyDict_AsMessage(mem_ctx, py_obj, ldb_ctx, LDB_FLAG_MOD_ADD);
1570 } else {
1571 PyErr_SetString(PyExc_TypeError,
1572 "Dictionary or LdbMessage object expected!");
1575 if (!msg) {
1576 /* we should have a PyErr already set */
1577 talloc_free(mem_ctx);
1578 return NULL;
1581 ret = ldb_msg_sanity_check(ldb_ctx, msg);
1582 if (ret != LDB_SUCCESS) {
1583 PyErr_SetLdbError(PyExc_LdbError, ret, ldb_ctx);
1584 talloc_free(mem_ctx);
1585 return NULL;
1588 ret = ldb_build_add_req(&req, ldb_ctx, mem_ctx, msg, parsed_controls,
1589 NULL, ldb_op_default_callback, NULL);
1590 if (ret != LDB_SUCCESS) {
1591 PyErr_SetString(PyExc_TypeError, "failed to build request");
1592 talloc_free(mem_ctx);
1593 return NULL;
1596 /* do request and autostart a transaction */
1597 /* Then let's LDB handle the message error in case of pb as they are meaningful */
1599 ret = ldb_transaction_start(ldb_ctx);
1600 if (ret != LDB_SUCCESS) {
1601 talloc_free(mem_ctx);
1602 PyErr_SetLdbError(PyExc_LdbError, ret, ldb_ctx);
1603 return NULL;
1606 ret = ldb_request(ldb_ctx, req);
1607 if (ret == LDB_SUCCESS) {
1608 ret = ldb_wait(req->handle, LDB_WAIT_ALL);
1611 if (ret == LDB_SUCCESS) {
1612 ret = ldb_transaction_commit(ldb_ctx);
1613 } else {
1614 ldb_transaction_cancel(ldb_ctx);
1617 talloc_free(mem_ctx);
1618 PyErr_LDB_ERROR_IS_ERR_RAISE(PyExc_LdbError, ret, ldb_ctx);
1620 Py_RETURN_NONE;
1623 static PyObject *py_ldb_delete(PyLdbObject *self, PyObject *args, PyObject *kwargs)
1625 PyObject *py_dn;
1626 struct ldb_dn *dn;
1627 int ret;
1628 struct ldb_context *ldb_ctx;
1629 struct ldb_request *req;
1630 PyObject *py_controls = Py_None;
1631 TALLOC_CTX *mem_ctx;
1632 struct ldb_control **parsed_controls;
1633 const char * const kwnames[] = { "dn", "controls", NULL };
1635 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "O|O",
1636 discard_const_p(char *, kwnames),
1637 &py_dn, &py_controls))
1638 return NULL;
1640 mem_ctx = talloc_new(NULL);
1641 if (mem_ctx == NULL) {
1642 PyErr_NoMemory();
1643 return NULL;
1645 ldb_ctx = pyldb_Ldb_AS_LDBCONTEXT(self);
1647 if (py_controls == Py_None) {
1648 parsed_controls = NULL;
1649 } else {
1650 const char **controls = PyList_AsStrList(mem_ctx, py_controls, "controls");
1651 if (controls == NULL) {
1652 talloc_free(mem_ctx);
1653 return NULL;
1655 parsed_controls = ldb_parse_control_strings(ldb_ctx, mem_ctx, controls);
1656 if (controls[0] != NULL && parsed_controls == NULL) {
1657 talloc_free(mem_ctx);
1658 PyErr_SetLdbError(PyExc_LdbError, LDB_ERR_OPERATIONS_ERROR, ldb_ctx);
1659 return NULL;
1661 talloc_free(controls);
1664 if (!pyldb_Object_AsDn(mem_ctx, py_dn, ldb_ctx, &dn)) {
1665 talloc_free(mem_ctx);
1666 return NULL;
1669 ret = ldb_build_del_req(&req, ldb_ctx, mem_ctx, dn, parsed_controls,
1670 NULL, ldb_op_default_callback, NULL);
1671 if (ret != LDB_SUCCESS) {
1672 PyErr_SetString(PyExc_TypeError, "failed to build request");
1673 talloc_free(mem_ctx);
1674 return NULL;
1677 /* do request and autostart a transaction */
1678 /* Then let's LDB handle the message error in case of pb as they are meaningful */
1680 ret = ldb_transaction_start(ldb_ctx);
1681 if (ret != LDB_SUCCESS) {
1682 talloc_free(mem_ctx);
1683 PyErr_SetLdbError(PyExc_LdbError, ret, ldb_ctx);
1684 return NULL;
1687 ret = ldb_request(ldb_ctx, req);
1688 if (ret == LDB_SUCCESS) {
1689 ret = ldb_wait(req->handle, LDB_WAIT_ALL);
1692 if (ret == LDB_SUCCESS) {
1693 ret = ldb_transaction_commit(ldb_ctx);
1694 } else {
1695 ldb_transaction_cancel(ldb_ctx);
1698 talloc_free(mem_ctx);
1699 PyErr_LDB_ERROR_IS_ERR_RAISE(PyExc_LdbError, ret, ldb_ctx);
1701 Py_RETURN_NONE;
1704 static PyObject *py_ldb_rename(PyLdbObject *self, PyObject *args, PyObject *kwargs)
1706 PyObject *py_dn1, *py_dn2;
1707 struct ldb_dn *dn1, *dn2;
1708 int ret;
1709 TALLOC_CTX *mem_ctx;
1710 PyObject *py_controls = Py_None;
1711 struct ldb_control **parsed_controls;
1712 struct ldb_context *ldb_ctx;
1713 struct ldb_request *req;
1714 const char * const kwnames[] = { "dn1", "dn2", "controls", NULL };
1716 ldb_ctx = pyldb_Ldb_AS_LDBCONTEXT(self);
1718 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "OO|O",
1719 discard_const_p(char *, kwnames),
1720 &py_dn1, &py_dn2, &py_controls))
1721 return NULL;
1724 mem_ctx = talloc_new(NULL);
1725 if (mem_ctx == NULL) {
1726 PyErr_NoMemory();
1727 return NULL;
1730 if (py_controls == Py_None) {
1731 parsed_controls = NULL;
1732 } else {
1733 const char **controls = PyList_AsStrList(mem_ctx, py_controls, "controls");
1734 if (controls == NULL) {
1735 talloc_free(mem_ctx);
1736 return NULL;
1738 parsed_controls = ldb_parse_control_strings(ldb_ctx, mem_ctx, controls);
1739 if (controls[0] != NULL && parsed_controls == NULL) {
1740 talloc_free(mem_ctx);
1741 PyErr_SetLdbError(PyExc_LdbError, LDB_ERR_OPERATIONS_ERROR, ldb_ctx);
1742 return NULL;
1744 talloc_free(controls);
1748 if (!pyldb_Object_AsDn(mem_ctx, py_dn1, ldb_ctx, &dn1)) {
1749 talloc_free(mem_ctx);
1750 return NULL;
1753 if (!pyldb_Object_AsDn(mem_ctx, py_dn2, ldb_ctx, &dn2)) {
1754 talloc_free(mem_ctx);
1755 return NULL;
1758 ret = ldb_build_rename_req(&req, ldb_ctx, mem_ctx, dn1, dn2, parsed_controls,
1759 NULL, ldb_op_default_callback, NULL);
1760 if (ret != LDB_SUCCESS) {
1761 PyErr_SetString(PyExc_TypeError, "failed to build request");
1762 talloc_free(mem_ctx);
1763 return NULL;
1766 /* do request and autostart a transaction */
1767 /* Then let's LDB handle the message error in case of pb as they are meaningful */
1769 ret = ldb_transaction_start(ldb_ctx);
1770 if (ret != LDB_SUCCESS) {
1771 talloc_free(mem_ctx);
1772 PyErr_SetLdbError(PyExc_LdbError, ret, ldb_ctx);
1773 return NULL;
1776 ret = ldb_request(ldb_ctx, req);
1777 if (ret == LDB_SUCCESS) {
1778 ret = ldb_wait(req->handle, LDB_WAIT_ALL);
1781 if (ret == LDB_SUCCESS) {
1782 ret = ldb_transaction_commit(ldb_ctx);
1783 } else {
1784 ldb_transaction_cancel(ldb_ctx);
1787 talloc_free(mem_ctx);
1788 PyErr_LDB_ERROR_IS_ERR_RAISE(PyExc_LdbError, ret, ldb_ctx);
1790 Py_RETURN_NONE;
1793 static PyObject *py_ldb_schema_attribute_remove(PyLdbObject *self, PyObject *args)
1795 char *name;
1796 if (!PyArg_ParseTuple(args, "s", &name))
1797 return NULL;
1799 ldb_schema_attribute_remove(pyldb_Ldb_AS_LDBCONTEXT(self), name);
1801 Py_RETURN_NONE;
1804 static PyObject *py_ldb_schema_attribute_add(PyLdbObject *self, PyObject *args)
1806 char *attribute, *syntax;
1807 unsigned int flags;
1808 int ret;
1809 struct ldb_context *ldb_ctx;
1811 if (!PyArg_ParseTuple(args, "sIs", &attribute, &flags, &syntax))
1812 return NULL;
1814 ldb_ctx = pyldb_Ldb_AS_LDBCONTEXT(self);
1815 ret = ldb_schema_attribute_add(ldb_ctx, attribute, flags, syntax);
1817 PyErr_LDB_ERROR_IS_ERR_RAISE(PyExc_LdbError, ret, ldb_ctx);
1819 Py_RETURN_NONE;
1822 static PyObject *ldb_ldif_to_pyobject(struct ldb_context *ldb, struct ldb_ldif *ldif)
1824 PyObject *obj = NULL;
1825 PyObject *result = NULL;
1827 if (ldif == NULL) {
1828 Py_RETURN_NONE;
1831 switch (ldif->changetype) {
1832 case LDB_CHANGETYPE_NONE:
1833 case LDB_CHANGETYPE_ADD:
1834 obj = PyLdbMessage_FromMessage(ldif->msg);
1835 break;
1836 case LDB_CHANGETYPE_MODIFY:
1837 obj = PyLdbMessage_FromMessage(ldif->msg);
1838 break;
1839 case LDB_CHANGETYPE_DELETE:
1840 if (ldif->msg->num_elements != 0) {
1841 PyErr_Format(PyExc_ValueError,
1842 "CHANGETYPE(DELETE) with num_elements=%u",
1843 ldif->msg->num_elements);
1844 return NULL;
1846 obj = pyldb_Dn_FromDn(ldif->msg->dn);
1847 break;
1848 case LDB_CHANGETYPE_MODRDN: {
1849 struct ldb_dn *olddn = NULL;
1850 PyObject *olddn_obj = NULL;
1851 bool deleteoldrdn = false;
1852 PyObject *deleteoldrdn_obj = NULL;
1853 struct ldb_dn *newdn = NULL;
1854 PyObject *newdn_obj = NULL;
1855 int ret;
1857 ret = ldb_ldif_parse_modrdn(ldb,
1858 ldif,
1859 ldif,
1860 &olddn,
1861 NULL,
1862 &deleteoldrdn,
1863 NULL,
1864 &newdn);
1865 if (ret != LDB_SUCCESS) {
1866 PyErr_Format(PyExc_ValueError,
1867 "ldb_ldif_parse_modrdn() failed");
1868 return NULL;
1871 olddn_obj = pyldb_Dn_FromDn(olddn);
1872 if (olddn_obj == NULL) {
1873 return NULL;
1875 if (deleteoldrdn) {
1876 deleteoldrdn_obj = Py_True;
1877 } else {
1878 deleteoldrdn_obj = Py_False;
1880 newdn_obj = pyldb_Dn_FromDn(newdn);
1881 if (newdn_obj == NULL) {
1882 deleteoldrdn_obj = NULL;
1883 Py_CLEAR(olddn_obj);
1884 return NULL;
1887 obj = Py_BuildValue(discard_const_p(char, "{s:O,s:O,s:O}"),
1888 "olddn", olddn_obj,
1889 "deleteoldrdn", deleteoldrdn_obj,
1890 "newdn", newdn_obj);
1891 Py_CLEAR(olddn_obj);
1892 deleteoldrdn_obj = NULL;
1893 Py_CLEAR(newdn_obj);
1895 break;
1896 default:
1897 PyErr_Format(PyExc_NotImplementedError,
1898 "Unsupported LDB_CHANGETYPE(%u)",
1899 ldif->changetype);
1900 return NULL;
1903 if (obj == NULL) {
1904 return NULL;
1907 /* We don't want this being attached * to the 'ldb' any more */
1908 result = Py_BuildValue(discard_const_p(char, "(iO)"),
1909 ldif->changetype,
1910 obj);
1911 Py_CLEAR(obj);
1912 return result;
1916 static PyObject *py_ldb_write_ldif(PyLdbObject *self, PyObject *args)
1918 int changetype;
1919 PyObject *py_msg;
1920 struct ldb_ldif ldif;
1921 PyObject *ret;
1922 char *string;
1923 TALLOC_CTX *mem_ctx;
1925 if (!PyArg_ParseTuple(args, "Oi", &py_msg, &changetype))
1926 return NULL;
1928 if (!PyLdbMessage_Check(py_msg)) {
1929 PyErr_SetString(PyExc_TypeError, "Expected Ldb Message for msg");
1930 return NULL;
1933 ldif.msg = pyldb_Message_AsMessage(py_msg);
1934 ldif.changetype = changetype;
1936 mem_ctx = talloc_new(NULL);
1937 if (mem_ctx == NULL) {
1938 return PyErr_NoMemory();
1941 string = ldb_ldif_write_string(pyldb_Ldb_AS_LDBCONTEXT(self), mem_ctx, &ldif);
1942 if (!string) {
1943 PyErr_SetString(PyExc_KeyError, "Failed to generate LDIF");
1944 talloc_free(mem_ctx);
1945 return NULL;
1948 ret = PyUnicode_FromString(string);
1950 talloc_free(mem_ctx);
1952 return ret;
1955 static PyObject *py_ldb_parse_ldif(PyLdbObject *self, PyObject *args)
1957 PyObject *list, *ret;
1958 struct ldb_ldif *ldif;
1959 const char *s;
1960 struct ldb_dn *last_dn = NULL;
1962 TALLOC_CTX *mem_ctx;
1964 if (!PyArg_ParseTuple(args, "s", &s))
1965 return NULL;
1967 mem_ctx = talloc_new(NULL);
1968 if (!mem_ctx) {
1969 Py_RETURN_NONE;
1972 list = PyList_New(0);
1973 if (list == NULL) {
1974 talloc_free(mem_ctx);
1975 return NULL;
1978 while (s && *s != '\0') {
1979 ldif = ldb_ldif_read_string(self->ldb_ctx, &s);
1980 talloc_steal(mem_ctx, ldif);
1981 if (ldif) {
1982 int res = 0;
1983 PyObject *py_ldif = ldb_ldif_to_pyobject(self->ldb_ctx, ldif);
1984 if (py_ldif == NULL) {
1985 Py_CLEAR(list);
1986 if (PyErr_Occurred() == NULL) {
1987 PyErr_BadArgument();
1989 talloc_free(mem_ctx);
1990 return NULL;
1992 res = PyList_Append(list, py_ldif);
1993 Py_CLEAR(py_ldif);
1994 if (res == -1) {
1995 Py_CLEAR(list);
1996 talloc_free(mem_ctx);
1997 return NULL;
1999 last_dn = ldif->msg->dn;
2000 } else {
2001 const char *last_dn_str = NULL;
2002 const char *err_string = NULL;
2003 if (last_dn == NULL) {
2004 PyErr_SetString(PyExc_ValueError,
2005 "unable to parse LDIF "
2006 "string at first chunk");
2007 Py_CLEAR(list);
2008 talloc_free(mem_ctx);
2009 return NULL;
2012 last_dn_str
2013 = ldb_dn_get_linearized(last_dn);
2015 err_string
2016 = talloc_asprintf(mem_ctx,
2017 "unable to parse ldif "
2018 "string AFTER %s",
2019 last_dn_str);
2021 PyErr_SetString(PyExc_ValueError,
2022 err_string);
2023 talloc_free(mem_ctx);
2024 Py_CLEAR(list);
2025 return NULL;
2028 talloc_free(mem_ctx); /* The pyobject already has a reference to the things it needs */
2029 ret = PyObject_GetIter(list);
2030 Py_DECREF(list);
2031 return ret;
2034 static PyObject *py_ldb_msg_diff(PyLdbObject *self, PyObject *args)
2036 int ldb_ret;
2037 PyObject *py_msg_old;
2038 PyObject *py_msg_new;
2039 struct ldb_message *diff;
2040 struct ldb_context *ldb;
2041 PyObject *py_ret;
2042 TALLOC_CTX *mem_ctx = NULL;
2044 if (!PyArg_ParseTuple(args, "OO", &py_msg_old, &py_msg_new))
2045 return NULL;
2047 if (!PyLdbMessage_Check(py_msg_old)) {
2048 PyErr_SetString(PyExc_TypeError, "Expected Ldb Message for old message");
2049 return NULL;
2052 if (!PyLdbMessage_Check(py_msg_new)) {
2053 PyErr_SetString(PyExc_TypeError, "Expected Ldb Message for new message");
2054 return NULL;
2057 mem_ctx = talloc_new(NULL);
2058 if (mem_ctx == NULL) {
2059 PyErr_NoMemory();
2060 return NULL;
2063 ldb = pyldb_Ldb_AS_LDBCONTEXT(self);
2064 ldb_ret = ldb_msg_difference(ldb, mem_ctx,
2065 pyldb_Message_AsMessage(py_msg_old),
2066 pyldb_Message_AsMessage(py_msg_new),
2067 &diff);
2068 if (ldb_ret != LDB_SUCCESS) {
2069 talloc_free(mem_ctx);
2070 PyErr_SetString(PyExc_RuntimeError, "Failed to generate the Ldb Message diff");
2071 return NULL;
2074 diff = ldb_msg_copy(mem_ctx, diff);
2075 if (diff == NULL) {
2076 talloc_free(mem_ctx);
2077 PyErr_NoMemory();
2078 return NULL;
2081 py_ret = PyLdbMessage_FromMessage(diff);
2083 talloc_free(mem_ctx);
2085 return py_ret;
2088 static PyObject *py_ldb_schema_format_value(PyLdbObject *self, PyObject *args)
2090 const struct ldb_schema_attribute *a;
2091 struct ldb_val old_val;
2092 struct ldb_val new_val;
2093 TALLOC_CTX *mem_ctx;
2094 PyObject *ret;
2095 char *element_name;
2096 PyObject *val;
2097 Py_ssize_t size;
2098 int result;
2100 if (!PyArg_ParseTuple(args, "sO", &element_name, &val))
2101 return NULL;
2103 result = PyBytes_AsStringAndSize(val, (char **)&old_val.data, &size);
2104 old_val.length = size;
2106 if (result != 0) {
2107 PyErr_SetString(PyExc_RuntimeError, "Failed to convert passed value to String");
2108 return NULL;
2111 a = ldb_schema_attribute_by_name(pyldb_Ldb_AS_LDBCONTEXT(self), element_name);
2113 if (a == NULL) {
2114 Py_RETURN_NONE;
2117 mem_ctx = talloc_new(NULL);
2118 if (mem_ctx == NULL) {
2119 PyErr_NoMemory();
2120 return NULL;
2123 if (a->syntax->ldif_write_fn(pyldb_Ldb_AS_LDBCONTEXT(self), mem_ctx, &old_val, &new_val) != 0) {
2124 talloc_free(mem_ctx);
2125 Py_RETURN_NONE;
2128 ret = PyBytes_FromStringAndSize((const char *)new_val.data, new_val.length);
2130 talloc_free(mem_ctx);
2132 return ret;
2135 static PyObject *py_ldb_search(PyLdbObject *self, PyObject *args, PyObject *kwargs)
2137 PyObject *py_base = Py_None;
2138 int scope = LDB_SCOPE_DEFAULT;
2139 char *expr = NULL;
2140 PyObject *py_attrs = Py_None;
2141 PyObject *py_controls = Py_None;
2142 const char * const kwnames[] = { "base", "scope", "expression", "attrs", "controls", NULL };
2143 int ret;
2144 struct ldb_result *res;
2145 struct ldb_request *req;
2146 const char **attrs;
2147 struct ldb_context *ldb_ctx;
2148 struct ldb_control **parsed_controls;
2149 struct ldb_dn *base;
2150 PyObject *py_ret;
2151 TALLOC_CTX *mem_ctx;
2153 /* type "int" rather than "enum" for "scope" is intentional */
2154 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "|OizOO",
2155 discard_const_p(char *, kwnames),
2156 &py_base, &scope, &expr, &py_attrs, &py_controls))
2157 return NULL;
2160 mem_ctx = talloc_new(NULL);
2161 if (mem_ctx == NULL) {
2162 PyErr_NoMemory();
2163 return NULL;
2165 ldb_ctx = pyldb_Ldb_AS_LDBCONTEXT(self);
2167 if (py_attrs == Py_None) {
2168 attrs = NULL;
2169 } else {
2170 attrs = PyList_AsStrList(mem_ctx, py_attrs, "attrs");
2171 if (attrs == NULL) {
2172 talloc_free(mem_ctx);
2173 return NULL;
2177 if (py_base == Py_None) {
2178 base = ldb_get_default_basedn(ldb_ctx);
2179 } else {
2180 if (!pyldb_Object_AsDn(mem_ctx, py_base, ldb_ctx, &base)) {
2181 talloc_free(mem_ctx);
2182 return NULL;
2186 if (py_controls == Py_None) {
2187 parsed_controls = NULL;
2188 } else {
2189 const char **controls = PyList_AsStrList(mem_ctx, py_controls, "controls");
2190 if (controls == NULL) {
2191 talloc_free(mem_ctx);
2192 return NULL;
2194 parsed_controls = ldb_parse_control_strings(ldb_ctx, mem_ctx, controls);
2195 if (controls[0] != NULL && parsed_controls == NULL) {
2196 talloc_free(mem_ctx);
2197 PyErr_SetLdbError(PyExc_LdbError, LDB_ERR_OPERATIONS_ERROR, ldb_ctx);
2198 return NULL;
2200 talloc_free(controls);
2203 res = talloc_zero(mem_ctx, struct ldb_result);
2204 if (res == NULL) {
2205 PyErr_NoMemory();
2206 talloc_free(mem_ctx);
2207 return NULL;
2210 ret = ldb_build_search_req(&req, ldb_ctx, mem_ctx,
2211 base,
2212 scope,
2213 expr,
2214 attrs,
2215 parsed_controls,
2216 res,
2217 ldb_search_default_callback,
2218 NULL);
2220 if (ret != LDB_SUCCESS) {
2221 talloc_free(mem_ctx);
2222 PyErr_SetLdbError(PyExc_LdbError, ret, ldb_ctx);
2223 return NULL;
2226 talloc_steal(req, attrs);
2228 ret = ldb_request(ldb_ctx, req);
2230 if (ret == LDB_SUCCESS) {
2231 ret = ldb_wait(req->handle, LDB_WAIT_ALL);
2234 if (ret != LDB_SUCCESS) {
2235 talloc_free(mem_ctx);
2236 PyErr_SetLdbError(PyExc_LdbError, ret, ldb_ctx);
2237 return NULL;
2240 py_ret = PyLdbResult_FromResult(res);
2242 talloc_free(mem_ctx);
2244 return py_ret;
2247 static int py_ldb_search_iterator_reply_destructor(struct py_ldb_search_iterator_reply *reply)
2249 if (reply->py_iter != NULL) {
2250 DLIST_REMOVE(reply->py_iter->state.next, reply);
2251 if (reply->py_iter->state.result == reply) {
2252 reply->py_iter->state.result = NULL;
2254 reply->py_iter = NULL;
2257 Py_CLEAR(reply->obj);
2259 return 0;
2262 static int py_ldb_search_iterator_callback(struct ldb_request *req,
2263 struct ldb_reply *ares)
2265 PyLdbSearchIteratorObject *py_iter = (PyLdbSearchIteratorObject *)req->context;
2266 struct ldb_result result = { .msgs = NULL };
2267 struct py_ldb_search_iterator_reply *reply = NULL;
2269 if (ares == NULL) {
2270 return ldb_request_done(req, LDB_ERR_OPERATIONS_ERROR);
2273 if (ares->error != LDB_SUCCESS) {
2274 int ret = ares->error;
2275 TALLOC_FREE(ares);
2276 return ldb_request_done(req, ret);
2279 reply = talloc_zero(py_iter->mem_ctx,
2280 struct py_ldb_search_iterator_reply);
2281 if (reply == NULL) {
2282 TALLOC_FREE(ares);
2283 return ldb_request_done(req, LDB_ERR_OPERATIONS_ERROR);
2285 reply->py_iter = py_iter;
2286 talloc_set_destructor(reply, py_ldb_search_iterator_reply_destructor);
2288 switch (ares->type) {
2289 case LDB_REPLY_ENTRY:
2290 reply->obj = PyLdbMessage_FromMessage(ares->message);
2291 if (reply->obj == NULL) {
2292 TALLOC_FREE(ares);
2293 return ldb_request_done(req, LDB_ERR_OPERATIONS_ERROR);
2295 DLIST_ADD_END(py_iter->state.next, reply);
2296 TALLOC_FREE(ares);
2297 return LDB_SUCCESS;
2299 case LDB_REPLY_REFERRAL:
2300 reply->obj = PyUnicode_FromString(ares->referral);
2301 if (reply->obj == NULL) {
2302 TALLOC_FREE(ares);
2303 return ldb_request_done(req, LDB_ERR_OPERATIONS_ERROR);
2305 DLIST_ADD_END(py_iter->state.next, reply);
2306 TALLOC_FREE(ares);
2307 return LDB_SUCCESS;
2309 case LDB_REPLY_DONE:
2310 result = (struct ldb_result) { .controls = ares->controls };
2311 reply->obj = PyLdbResult_FromResult(&result);
2312 if (reply->obj == NULL) {
2313 TALLOC_FREE(ares);
2314 return ldb_request_done(req, LDB_ERR_OPERATIONS_ERROR);
2316 py_iter->state.result = reply;
2317 TALLOC_FREE(ares);
2318 return ldb_request_done(req, LDB_SUCCESS);
2321 TALLOC_FREE(ares);
2322 return ldb_request_done(req, LDB_ERR_OPERATIONS_ERROR);
2325 static PyObject *py_ldb_search_iterator(PyLdbObject *self, PyObject *args, PyObject *kwargs)
2327 PyObject *py_base = Py_None;
2328 int scope = LDB_SCOPE_DEFAULT;
2329 int timeout = 0;
2330 char *expr = NULL;
2331 PyObject *py_attrs = Py_None;
2332 PyObject *py_controls = Py_None;
2333 const char * const kwnames[] = { "base", "scope", "expression", "attrs", "controls", "timeout", NULL };
2334 int ret;
2335 const char **attrs;
2336 struct ldb_context *ldb_ctx;
2337 struct ldb_control **parsed_controls;
2338 struct ldb_dn *base;
2339 PyLdbSearchIteratorObject *py_iter;
2341 /* type "int" rather than "enum" for "scope" is intentional */
2342 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "|OizOOi",
2343 discard_const_p(char *, kwnames),
2344 &py_base, &scope, &expr, &py_attrs, &py_controls, &timeout))
2345 return NULL;
2347 py_iter = (PyLdbSearchIteratorObject *)PyLdbSearchIterator.tp_alloc(&PyLdbSearchIterator, 0);
2348 if (py_iter == NULL) {
2349 PyErr_NoMemory();
2350 return NULL;
2352 py_iter->ldb = self;
2353 Py_INCREF(self);
2354 ZERO_STRUCT(py_iter->state);
2355 py_iter->mem_ctx = talloc_new(NULL);
2356 if (py_iter->mem_ctx == NULL) {
2357 Py_DECREF(py_iter);
2358 PyErr_NoMemory();
2359 return NULL;
2362 ldb_ctx = pyldb_Ldb_AS_LDBCONTEXT(self);
2364 if (py_attrs == Py_None) {
2365 attrs = NULL;
2366 } else {
2367 attrs = PyList_AsStrList(py_iter->mem_ctx, py_attrs, "attrs");
2368 if (attrs == NULL) {
2369 Py_DECREF(py_iter);
2370 PyErr_NoMemory();
2371 return NULL;
2375 if (py_base == Py_None) {
2376 base = ldb_get_default_basedn(ldb_ctx);
2377 } else {
2378 if (!pyldb_Object_AsDn(py_iter->mem_ctx, py_base, ldb_ctx, &base)) {
2379 Py_DECREF(py_iter);
2380 PyErr_NoMemory();
2381 return NULL;
2385 if (py_controls == Py_None) {
2386 parsed_controls = NULL;
2387 } else {
2388 const char **controls = NULL;
2390 controls = PyList_AsStrList(py_iter->mem_ctx,
2391 py_controls, "controls");
2392 if (controls == NULL) {
2393 Py_DECREF(py_iter);
2394 PyErr_NoMemory();
2395 return NULL;
2398 parsed_controls = ldb_parse_control_strings(ldb_ctx,
2399 py_iter->mem_ctx,
2400 controls);
2401 if (controls[0] != NULL && parsed_controls == NULL) {
2402 Py_DECREF(py_iter);
2403 PyErr_SetLdbError(PyExc_LdbError, LDB_ERR_OPERATIONS_ERROR, ldb_ctx);
2404 return NULL;
2406 talloc_free(controls);
2409 ret = ldb_build_search_req(&py_iter->state.req,
2410 ldb_ctx,
2411 py_iter->mem_ctx,
2412 base,
2413 scope,
2414 expr,
2415 attrs,
2416 parsed_controls,
2417 py_iter,
2418 py_ldb_search_iterator_callback,
2419 NULL);
2420 if (ret != LDB_SUCCESS) {
2421 Py_DECREF(py_iter);
2422 PyErr_SetLdbError(PyExc_LdbError, ret, ldb_ctx);
2423 return NULL;
2426 ldb_set_timeout(ldb_ctx, py_iter->state.req, timeout);
2428 ret = ldb_request(ldb_ctx, py_iter->state.req);
2429 if (ret != LDB_SUCCESS) {
2430 Py_DECREF(py_iter);
2431 PyErr_SetLdbError(PyExc_LdbError, ret, ldb_ctx);
2432 return NULL;
2435 return (PyObject *)py_iter;
2438 static PyObject *py_ldb_get_opaque(PyLdbObject *self, PyObject *args)
2440 char *name;
2441 void *data;
2443 if (!PyArg_ParseTuple(args, "s", &name))
2444 return NULL;
2446 data = ldb_get_opaque(pyldb_Ldb_AS_LDBCONTEXT(self), name);
2448 if (data == NULL)
2449 Py_RETURN_NONE;
2451 /* FIXME: More interpretation */
2453 Py_RETURN_TRUE;
2456 static PyObject *py_ldb_set_opaque(PyLdbObject *self, PyObject *args)
2458 char *name;
2459 PyObject *data;
2461 if (!PyArg_ParseTuple(args, "sO", &name, &data))
2462 return NULL;
2464 /* FIXME: More interpretation */
2466 ldb_set_opaque(pyldb_Ldb_AS_LDBCONTEXT(self), name, data);
2468 Py_RETURN_NONE;
2471 static PyObject *py_ldb_modules(PyLdbObject *self,
2472 PyObject *Py_UNUSED(ignored))
2474 struct ldb_context *ldb = pyldb_Ldb_AS_LDBCONTEXT(self);
2475 PyObject *ret = PyList_New(0);
2476 struct ldb_module *mod;
2478 if (ret == NULL) {
2479 return PyErr_NoMemory();
2481 for (mod = ldb->modules; mod; mod = mod->next) {
2482 PyObject *item = PyLdbModule_FromModule(mod);
2483 int res = 0;
2484 if (item == NULL) {
2485 PyErr_SetString(PyExc_RuntimeError,
2486 "Failed to load LdbModule");
2487 Py_CLEAR(ret);
2488 return NULL;
2490 res = PyList_Append(ret, item);
2491 Py_CLEAR(item);
2492 if (res == -1) {
2493 Py_CLEAR(ret);
2494 return NULL;
2498 return ret;
2501 static PyObject *py_ldb_sequence_number(PyLdbObject *self, PyObject *args)
2503 struct ldb_context *ldb = pyldb_Ldb_AS_LDBCONTEXT(self);
2504 int type, ret;
2505 uint64_t value;
2507 if (!PyArg_ParseTuple(args, "i", &type))
2508 return NULL;
2510 /* FIXME: More interpretation */
2512 ret = ldb_sequence_number(ldb, type, &value);
2514 PyErr_LDB_ERROR_IS_ERR_RAISE(PyExc_LdbError, ret, ldb);
2516 return PyLong_FromLongLong(value);
2519 static PyObject *py_ldb_whoami(PyLdbObject *self, PyObject *args)
2521 struct ldb_context *ldb = pyldb_Ldb_AS_LDBCONTEXT(self);
2522 struct ldb_result *res = NULL;
2523 struct ldb_extended *ext_res = NULL;
2524 size_t len = 0;
2525 int ret;
2527 ret = ldb_extended(ldb, LDB_EXTENDED_WHOAMI_OID, NULL, &res);
2528 PyErr_LDB_ERROR_IS_ERR_RAISE(PyExc_LdbError, ret, ldb);
2530 ext_res = res->extended;
2531 if (ext_res == NULL) {
2532 PyErr_SetString(PyExc_TypeError, "Got no exop reply");
2533 return NULL;
2536 if (strcmp(ext_res->oid, LDB_EXTENDED_WHOAMI_OID) != 0) {
2537 PyErr_SetString(PyExc_TypeError, "Got wrong reply OID");
2538 return NULL;
2541 len = talloc_get_size(ext_res->data);
2542 if (len == 0) {
2543 Py_RETURN_NONE;
2546 return PyUnicode_FromStringAndSize(ext_res->data, len);
2550 static const struct ldb_dn_extended_syntax test_dn_syntax = {
2551 .name = "TEST",
2552 .read_fn = ldb_handler_copy,
2553 .write_clear_fn = ldb_handler_copy,
2554 .write_hex_fn = ldb_handler_copy,
2557 static PyObject *py_ldb_register_test_extensions(PyLdbObject *self,
2558 PyObject *Py_UNUSED(ignored))
2560 struct ldb_context *ldb = pyldb_Ldb_AS_LDBCONTEXT(self);
2561 int ret;
2563 ret = ldb_dn_extended_add_syntax(ldb, LDB_ATTR_FLAG_FIXED, &test_dn_syntax);
2565 PyErr_LDB_ERROR_IS_ERR_RAISE(PyExc_LdbError, ret, ldb);
2567 Py_RETURN_NONE;
2571 static PyMethodDef py_ldb_methods[] = {
2572 { "set_debug", (PyCFunction)py_ldb_set_debug, METH_VARARGS,
2573 "S.set_debug(callback) -> None\n"
2574 "Set callback for LDB debug messages.\n"
2575 "The callback should accept a debug level and debug text." },
2576 { "set_create_perms", (PyCFunction)py_ldb_set_create_perms, METH_VARARGS,
2577 "S.set_create_perms(mode) -> None\n"
2578 "Set mode to use when creating new LDB files." },
2579 { "set_modules_dir", (PyCFunction)py_ldb_set_modules_dir, METH_VARARGS,
2580 "S.set_modules_dir(path) -> None\n"
2581 "Set path LDB should search for modules" },
2582 { "transaction_start", (PyCFunction)py_ldb_transaction_start, METH_NOARGS,
2583 "S.transaction_start() -> None\n"
2584 "Start a new transaction." },
2585 { "transaction_prepare_commit", (PyCFunction)py_ldb_transaction_prepare_commit, METH_NOARGS,
2586 "S.transaction_prepare_commit() -> None\n"
2587 "prepare to commit a new transaction (2-stage commit)." },
2588 { "transaction_commit", (PyCFunction)py_ldb_transaction_commit, METH_NOARGS,
2589 "S.transaction_commit() -> None\n"
2590 "commit a new transaction." },
2591 { "transaction_cancel", (PyCFunction)py_ldb_transaction_cancel, METH_NOARGS,
2592 "S.transaction_cancel() -> None\n"
2593 "cancel a new transaction." },
2594 { "setup_wellknown_attributes", (PyCFunction)py_ldb_setup_wellknown_attributes, METH_NOARGS,
2595 NULL },
2596 { "get_root_basedn", (PyCFunction)py_ldb_get_root_basedn, METH_NOARGS,
2597 NULL },
2598 { "get_schema_basedn", (PyCFunction)py_ldb_get_schema_basedn, METH_NOARGS,
2599 NULL },
2600 { "get_default_basedn", (PyCFunction)py_ldb_get_default_basedn, METH_NOARGS,
2601 NULL },
2602 { "get_config_basedn", (PyCFunction)py_ldb_get_config_basedn, METH_NOARGS,
2603 NULL },
2604 { "connect", PY_DISCARD_FUNC_SIG(PyCFunction, py_ldb_connect),
2605 METH_VARARGS|METH_KEYWORDS,
2606 "S.connect(url, flags=0, options=None) -> None\n"
2607 "Connect to a LDB URL." },
2608 { "modify", PY_DISCARD_FUNC_SIG(PyCFunction, py_ldb_modify),
2609 METH_VARARGS|METH_KEYWORDS,
2610 "S.modify(message, controls=None, validate=False) -> None\n"
2611 "Modify an entry." },
2612 { "add", PY_DISCARD_FUNC_SIG(PyCFunction, py_ldb_add),
2613 METH_VARARGS|METH_KEYWORDS,
2614 "S.add(message, controls=None) -> None\n"
2615 "Add an entry." },
2616 { "delete", PY_DISCARD_FUNC_SIG(PyCFunction, py_ldb_delete),
2617 METH_VARARGS|METH_KEYWORDS,
2618 "S.delete(dn, controls=None) -> None\n"
2619 "Remove an entry." },
2620 { "rename", PY_DISCARD_FUNC_SIG(PyCFunction, py_ldb_rename),
2621 METH_VARARGS|METH_KEYWORDS,
2622 "S.rename(old_dn, new_dn, controls=None) -> None\n"
2623 "Rename an entry." },
2624 { "search", PY_DISCARD_FUNC_SIG(PyCFunction, py_ldb_search),
2625 METH_VARARGS|METH_KEYWORDS,
2626 "S.search(base=None, scope=None, expression=None, attrs=None, controls=None) -> result\n"
2627 "Search in a database.\n"
2628 "\n"
2629 ":param base: Optional base DN to search\n"
2630 ":param scope: Search scope (SCOPE_BASE, SCOPE_ONELEVEL or SCOPE_SUBTREE)\n"
2631 ":param expression: Optional search expression\n"
2632 ":param attrs: Attributes to return (defaults to all)\n"
2633 ":param controls: Optional list of controls\n"
2634 ":return: ldb.Result object\n"
2636 { "search_iterator", PY_DISCARD_FUNC_SIG(PyCFunction,
2637 py_ldb_search_iterator),
2638 METH_VARARGS|METH_KEYWORDS,
2639 "S.search_iterator(base=None, scope=None, expression=None, attrs=None, controls=None, timeout=None) -> iterator\n"
2640 "Search in a database.\n"
2641 "\n"
2642 ":param base: Optional base DN to search\n"
2643 ":param scope: Search scope (SCOPE_BASE, SCOPE_ONELEVEL or SCOPE_SUBTREE)\n"
2644 ":param expression: Optional search expression\n"
2645 ":param attrs: Attributes to return (defaults to all)\n"
2646 ":param controls: Optional list of controls\n"
2647 ":param timeout: Optional timeout in seconds (defaults to 300), 0 means the default, -1 no timeout\n"
2648 ":return: ldb.SearchIterator object that provides results when they arrive\n"
2650 { "schema_attribute_remove", (PyCFunction)py_ldb_schema_attribute_remove, METH_VARARGS,
2651 NULL },
2652 { "schema_attribute_add", (PyCFunction)py_ldb_schema_attribute_add, METH_VARARGS,
2653 NULL },
2654 { "schema_format_value", (PyCFunction)py_ldb_schema_format_value, METH_VARARGS,
2655 NULL },
2656 { "parse_ldif", (PyCFunction)py_ldb_parse_ldif, METH_VARARGS,
2657 "S.parse_ldif(ldif) -> iter(messages)\n"
2658 "Parse a string formatted using LDIF." },
2659 { "write_ldif", (PyCFunction)py_ldb_write_ldif, METH_VARARGS,
2660 "S.write_ldif(message, changetype) -> ldif\n"
2661 "Print the message as a string formatted using LDIF." },
2662 { "msg_diff", (PyCFunction)py_ldb_msg_diff, METH_VARARGS,
2663 "S.msg_diff(Message) -> Message\n"
2664 "Return an LDB Message of the difference between two Message objects." },
2665 { "get_opaque", (PyCFunction)py_ldb_get_opaque, METH_VARARGS,
2666 "S.get_opaque(name) -> value\n"
2667 "Get an opaque value set on this LDB connection. \n"
2668 ":note: The returned value may not be useful in Python."
2670 { "set_opaque", (PyCFunction)py_ldb_set_opaque, METH_VARARGS,
2671 "S.set_opaque(name, value) -> None\n"
2672 "Set an opaque value on this LDB connection. \n"
2673 ":note: Passing incorrect values may cause crashes." },
2674 { "modules", (PyCFunction)py_ldb_modules, METH_NOARGS,
2675 "S.modules() -> list\n"
2676 "Return the list of modules on this LDB connection " },
2677 { "sequence_number", (PyCFunction)py_ldb_sequence_number, METH_VARARGS,
2678 "S.sequence_number(type) -> value\n"
2679 "Return the value of the sequence according to the requested type" },
2680 { "whoami",
2681 (PyCFunction)py_ldb_whoami,
2682 METH_NOARGS,
2683 "S.whoami(type) -> value\n"
2684 "Return the RFC4532 whoami string",
2686 { "_register_test_extensions", (PyCFunction)py_ldb_register_test_extensions, METH_NOARGS,
2687 "S._register_test_extensions() -> None\n"
2688 "Register internal extensions used in testing" },
2689 {0},
2692 static PyObject *PyLdbModule_FromModule(struct ldb_module *mod)
2694 TALLOC_CTX *mem_ctx = NULL;
2695 struct ldb_module *mod_ref = NULL;
2696 PyLdbModuleObject *ret;
2698 mem_ctx = talloc_new(NULL);
2699 if (mem_ctx == NULL) {
2700 return PyErr_NoMemory();
2703 mod_ref = talloc_reference(mem_ctx, mod);
2704 if (mod_ref == NULL) {
2705 talloc_free(mem_ctx);
2706 return PyErr_NoMemory();
2709 ret = (PyLdbModuleObject *)PyLdbModule.tp_alloc(&PyLdbModule, 0);
2710 if (ret == NULL) {
2711 talloc_free(mem_ctx);
2712 PyErr_NoMemory();
2713 return NULL;
2715 ret->mem_ctx = mem_ctx;
2716 ret->mod = mod_ref;
2717 return (PyObject *)ret;
2720 static PyObject *py_ldb_get_firstmodule(PyLdbObject *self, void *closure)
2722 struct ldb_module *mod = pyldb_Ldb_AS_LDBCONTEXT(self)->modules;
2723 if (mod == NULL) {
2724 Py_RETURN_NONE;
2726 return PyLdbModule_FromModule(mod);
2729 static PyGetSetDef py_ldb_getset[] = {
2731 .name = discard_const_p(char, "firstmodule"),
2732 .get = (getter)py_ldb_get_firstmodule,
2734 { .name = NULL },
2737 static int py_ldb_contains(PyLdbObject *self, PyObject *obj)
2739 struct ldb_context *ldb_ctx = pyldb_Ldb_AS_LDBCONTEXT(self);
2740 struct ldb_dn *dn;
2741 struct ldb_result *result;
2742 unsigned int count;
2743 int ret;
2745 if (!pyldb_Object_AsDn(ldb_ctx, obj, ldb_ctx, &dn)) {
2746 return -1;
2749 ret = ldb_search(ldb_ctx, ldb_ctx, &result, dn, LDB_SCOPE_BASE, NULL,
2750 NULL);
2751 if (ret != LDB_SUCCESS) {
2752 PyErr_SetLdbError(PyExc_LdbError, ret, ldb_ctx);
2753 return -1;
2756 count = result->count;
2758 talloc_free(result);
2760 if (count > 1) {
2761 PyErr_Format(PyExc_RuntimeError,
2762 "Searching for [%s] dn gave %u results!",
2763 ldb_dn_get_linearized(dn),
2764 count);
2765 return -1;
2768 return count;
2771 static PySequenceMethods py_ldb_seq = {
2772 .sq_contains = (objobjproc)py_ldb_contains,
2775 static PyObject *PyLdb_FromLdbContext(struct ldb_context *ldb_ctx)
2777 TALLOC_CTX *mem_ctx = NULL;
2778 struct ldb_context *ldb_ctx_ref = NULL;
2779 PyLdbObject *ret;
2781 mem_ctx = talloc_new(NULL);
2782 if (mem_ctx == NULL) {
2783 return PyErr_NoMemory();
2786 ldb_ctx_ref = talloc_reference(mem_ctx, ldb_ctx);
2787 if (ldb_ctx_ref == NULL) {
2788 talloc_free(mem_ctx);
2789 return PyErr_NoMemory();
2792 ret = (PyLdbObject *)PyLdb.tp_alloc(&PyLdb, 0);
2793 if (ret == NULL) {
2794 talloc_free(mem_ctx);
2795 PyErr_NoMemory();
2796 return NULL;
2798 ret->mem_ctx = mem_ctx;
2799 ret->ldb_ctx = ldb_ctx_ref;
2800 return (PyObject *)ret;
2803 static void py_ldb_dealloc(PyLdbObject *self)
2805 talloc_free(self->mem_ctx);
2806 Py_TYPE(self)->tp_free(self);
2809 static PyTypeObject PyLdb = {
2810 .tp_name = "ldb.Ldb",
2811 .tp_methods = py_ldb_methods,
2812 .tp_repr = (reprfunc)py_ldb_repr,
2813 .tp_new = py_ldb_new,
2814 .tp_init = (initproc)py_ldb_init,
2815 .tp_dealloc = (destructor)py_ldb_dealloc,
2816 .tp_getset = py_ldb_getset,
2817 .tp_getattro = PyObject_GenericGetAttr,
2818 .tp_basicsize = sizeof(PyLdbObject),
2819 .tp_doc = "Connection to a LDB database.",
2820 .tp_as_sequence = &py_ldb_seq,
2821 .tp_flags = Py_TPFLAGS_DEFAULT|Py_TPFLAGS_BASETYPE,
2824 static void py_ldb_result_dealloc(PyLdbResultObject *self)
2826 talloc_free(self->mem_ctx);
2827 Py_CLEAR(self->msgs);
2828 Py_CLEAR(self->referals);
2829 Py_CLEAR(self->controls);
2830 Py_TYPE(self)->tp_free(self);
2833 static PyObject *py_ldb_result_get_msgs(PyLdbResultObject *self, void *closure)
2835 Py_INCREF(self->msgs);
2836 return self->msgs;
2839 static PyObject *py_ldb_result_get_controls(PyLdbResultObject *self, void *closure)
2841 Py_INCREF(self->controls);
2842 return self->controls;
2845 static PyObject *py_ldb_result_get_referals(PyLdbResultObject *self, void *closure)
2847 Py_INCREF(self->referals);
2848 return self->referals;
2851 static PyObject *py_ldb_result_get_count(PyLdbResultObject *self, void *closure)
2853 Py_ssize_t size;
2854 if (self->msgs == NULL) {
2855 PyErr_SetString(PyExc_AttributeError, "Count attribute is meaningless in this context");
2856 return NULL;
2858 size = PyList_Size(self->msgs);
2859 return PyLong_FromLong(size);
2862 static PyGetSetDef py_ldb_result_getset[] = {
2864 .name = discard_const_p(char, "controls"),
2865 .get = (getter)py_ldb_result_get_controls,
2868 .name = discard_const_p(char, "msgs"),
2869 .get = (getter)py_ldb_result_get_msgs,
2872 .name = discard_const_p(char, "referals"),
2873 .get = (getter)py_ldb_result_get_referals,
2876 .name = discard_const_p(char, "count"),
2877 .get = (getter)py_ldb_result_get_count,
2879 { .name = NULL },
2882 static PyObject *py_ldb_result_iter(PyLdbResultObject *self)
2884 return PyObject_GetIter(self->msgs);
2887 static Py_ssize_t py_ldb_result_len(PyLdbResultObject *self)
2889 return PySequence_Size(self->msgs);
2892 static PyObject *py_ldb_result_find(PyLdbResultObject *self, Py_ssize_t idx)
2894 return PySequence_GetItem(self->msgs, idx);
2897 static PySequenceMethods py_ldb_result_seq = {
2898 .sq_length = (lenfunc)py_ldb_result_len,
2899 .sq_item = (ssizeargfunc)py_ldb_result_find,
2902 static PyObject *py_ldb_result_repr(PyLdbObject *self)
2904 return PyUnicode_FromString("<ldb result>");
2908 static PyTypeObject PyLdbResult = {
2909 .tp_name = "ldb.Result",
2910 .tp_repr = (reprfunc)py_ldb_result_repr,
2911 .tp_dealloc = (destructor)py_ldb_result_dealloc,
2912 .tp_iter = (getiterfunc)py_ldb_result_iter,
2913 .tp_getset = py_ldb_result_getset,
2914 .tp_getattro = PyObject_GenericGetAttr,
2915 .tp_basicsize = sizeof(PyLdbResultObject),
2916 .tp_as_sequence = &py_ldb_result_seq,
2917 .tp_doc = "LDB result.",
2918 .tp_flags = Py_TPFLAGS_DEFAULT|Py_TPFLAGS_BASETYPE,
2921 static void py_ldb_search_iterator_dealloc(PyLdbSearchIteratorObject *self)
2923 Py_CLEAR(self->state.exception);
2924 TALLOC_FREE(self->mem_ctx);
2925 ZERO_STRUCT(self->state);
2926 Py_CLEAR(self->ldb);
2927 Py_TYPE(self)->tp_free(self);
2930 static PyObject *py_ldb_search_iterator_next(PyLdbSearchIteratorObject *self)
2932 PyObject *py_ret = NULL;
2934 if (self->state.req == NULL) {
2935 PyErr_SetString(PyExc_RuntimeError,
2936 "ldb.SearchIterator request already finished");
2937 return NULL;
2941 * TODO: do we want a non-blocking mode?
2942 * In future we may add an optional 'nonblocking'
2943 * argument to search_iterator().
2945 * For now we keep it simple and wait for at
2946 * least one reply.
2949 while (self->state.next == NULL) {
2950 int ret;
2952 if (self->state.result != NULL) {
2954 * We (already) got a final result from the server.
2956 * We stop the iteration and let
2957 * py_ldb_search_iterator_result() will deliver
2958 * the result details.
2960 TALLOC_FREE(self->state.req);
2961 PyErr_SetNone(PyExc_StopIteration);
2962 return NULL;
2965 ret = ldb_wait(self->state.req->handle, LDB_WAIT_NONE);
2966 if (ret != LDB_SUCCESS) {
2967 struct ldb_context *ldb_ctx;
2968 TALLOC_FREE(self->state.req);
2969 ldb_ctx = pyldb_Ldb_AS_LDBCONTEXT(self->ldb);
2971 * We stop the iteration and let
2972 * py_ldb_search_iterator_result() will deliver
2973 * the exception.
2975 self->state.exception = Py_BuildValue(discard_const_p(char, "(i,s)"),
2976 ret, ldb_errstring(ldb_ctx));
2977 PyErr_SetNone(PyExc_StopIteration);
2978 return NULL;
2982 py_ret = self->state.next->obj;
2983 self->state.next->obj = NULL;
2984 /* no TALLOC_FREE() as self->state.next is a list */
2985 talloc_free(self->state.next);
2986 return py_ret;
2989 static PyObject *py_ldb_search_iterator_result(PyLdbSearchIteratorObject *self,
2990 PyObject *Py_UNUSED(ignored))
2992 PyObject *py_ret = NULL;
2994 if (self->state.req != NULL) {
2995 PyErr_SetString(PyExc_RuntimeError,
2996 "ldb.SearchIterator request running");
2997 return NULL;
3000 if (self->state.next != NULL) {
3001 PyErr_SetString(PyExc_RuntimeError,
3002 "ldb.SearchIterator not fully consumed.");
3003 return NULL;
3006 if (self->state.exception != NULL) {
3007 PyErr_SetObject(PyExc_LdbError, self->state.exception);
3008 self->state.exception = NULL;
3009 return NULL;
3012 if (self->state.result == NULL) {
3013 PyErr_SetString(PyExc_RuntimeError,
3014 "ldb.SearchIterator result already consumed");
3015 return NULL;
3018 py_ret = self->state.result->obj;
3019 self->state.result->obj = NULL;
3020 TALLOC_FREE(self->state.result);
3021 return py_ret;
3024 static PyObject *py_ldb_search_iterator_abandon(PyLdbSearchIteratorObject *self,
3025 PyObject *Py_UNUSED(ignored))
3027 if (self->state.req == NULL) {
3028 PyErr_SetString(PyExc_RuntimeError,
3029 "ldb.SearchIterator request already finished");
3030 return NULL;
3033 Py_CLEAR(self->state.exception);
3034 TALLOC_FREE(self->mem_ctx);
3035 ZERO_STRUCT(self->state);
3036 Py_RETURN_NONE;
3039 static PyMethodDef py_ldb_search_iterator_methods[] = {
3040 { "result", (PyCFunction)py_ldb_search_iterator_result, METH_NOARGS,
3041 "S.result() -> ldb.Result (without msgs and referrals)\n" },
3042 { "abandon", (PyCFunction)py_ldb_search_iterator_abandon, METH_NOARGS,
3043 "S.abandon()\n" },
3047 static PyObject *py_ldb_search_iterator_repr(PyLdbSearchIteratorObject *self)
3049 return PyUnicode_FromString("<ldb search iterator>");
3052 static PyTypeObject PyLdbSearchIterator = {
3053 .tp_name = "ldb.SearchIterator",
3054 .tp_repr = (reprfunc)py_ldb_search_iterator_repr,
3055 .tp_dealloc = (destructor)py_ldb_search_iterator_dealloc,
3056 .tp_iter = PyObject_SelfIter,
3057 .tp_iternext = (iternextfunc)py_ldb_search_iterator_next,
3058 .tp_methods = py_ldb_search_iterator_methods,
3059 .tp_basicsize = sizeof(PyLdbSearchIteratorObject),
3060 .tp_doc = "LDB search_iterator.",
3061 .tp_flags = Py_TPFLAGS_DEFAULT|Py_TPFLAGS_BASETYPE,
3064 static PyObject *py_ldb_module_repr(PyLdbModuleObject *self)
3066 return PyUnicode_FromFormat("<ldb module '%s'>",
3067 pyldb_Module_AsModule(self)->ops->name);
3070 static PyObject *py_ldb_module_str(PyLdbModuleObject *self)
3072 return PyUnicode_FromString(pyldb_Module_AsModule(self)->ops->name);
3075 static PyObject *py_ldb_module_start_transaction(PyLdbModuleObject *self,
3076 PyObject *Py_UNUSED(ignored))
3078 pyldb_Module_AsModule(self)->ops->start_transaction(pyldb_Module_AsModule(self));
3079 Py_RETURN_NONE;
3082 static PyObject *py_ldb_module_end_transaction(PyLdbModuleObject *self,
3083 PyObject *Py_UNUSED(ignored))
3085 pyldb_Module_AsModule(self)->ops->end_transaction(pyldb_Module_AsModule(self));
3086 Py_RETURN_NONE;
3089 static PyObject *py_ldb_module_del_transaction(PyLdbModuleObject *self,
3090 PyObject *Py_UNUSED(ignored))
3092 pyldb_Module_AsModule(self)->ops->del_transaction(pyldb_Module_AsModule(self));
3093 Py_RETURN_NONE;
3096 static PyObject *py_ldb_module_search(PyLdbModuleObject *self, PyObject *args, PyObject *kwargs)
3098 PyObject *py_base, *py_tree, *py_attrs, *py_ret;
3099 int ret, scope;
3100 struct ldb_request *req;
3101 const char * const kwnames[] = { "base", "scope", "tree", "attrs", NULL };
3102 struct ldb_module *mod;
3103 const char * const*attrs;
3105 /* type "int" rather than "enum" for "scope" is intentional */
3106 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "O!iOO",
3107 discard_const_p(char *, kwnames),
3108 &PyLdbDn, &py_base, &scope, &py_tree, &py_attrs))
3109 return NULL;
3111 mod = self->mod;
3113 if (py_attrs == Py_None) {
3114 attrs = NULL;
3115 } else {
3116 attrs = PyList_AsStrList(NULL, py_attrs, "attrs");
3117 if (attrs == NULL)
3118 return NULL;
3121 ret = ldb_build_search_req(&req, mod->ldb, NULL, pyldb_Dn_AS_DN(py_base),
3122 scope, NULL /* expr */, attrs,
3123 NULL /* controls */, NULL, NULL, NULL);
3125 talloc_steal(req, attrs);
3127 PyErr_LDB_ERROR_IS_ERR_RAISE(PyExc_LdbError, ret, mod->ldb);
3129 req->op.search.res = NULL;
3131 ret = mod->ops->search(mod, req);
3133 PyErr_LDB_ERROR_IS_ERR_RAISE(PyExc_LdbError, ret, mod->ldb);
3135 py_ret = PyLdbResult_FromResult(req->op.search.res);
3137 talloc_free(req);
3139 return py_ret;
3143 static PyObject *py_ldb_module_add(PyLdbModuleObject *self, PyObject *args)
3145 struct ldb_request *req;
3146 PyObject *py_message;
3147 int ret;
3148 struct ldb_module *mod;
3150 if (!PyArg_ParseTuple(args, "O!", &PyLdbMessage, &py_message))
3151 return NULL;
3153 req = talloc_zero(NULL, struct ldb_request);
3154 req->operation = LDB_ADD;
3155 req->op.add.message = pyldb_Message_AsMessage(py_message);
3157 mod = pyldb_Module_AsModule(self);
3158 ret = mod->ops->add(mod, req);
3160 PyErr_LDB_ERROR_IS_ERR_RAISE(PyExc_LdbError, ret, mod->ldb);
3162 Py_RETURN_NONE;
3165 static PyObject *py_ldb_module_modify(PyLdbModuleObject *self, PyObject *args)
3167 int ret;
3168 struct ldb_request *req;
3169 PyObject *py_message;
3170 struct ldb_module *mod;
3172 if (!PyArg_ParseTuple(args, "O!", &PyLdbMessage, &py_message))
3173 return NULL;
3175 req = talloc_zero(NULL, struct ldb_request);
3176 req->operation = LDB_MODIFY;
3177 req->op.mod.message = pyldb_Message_AsMessage(py_message);
3179 mod = pyldb_Module_AsModule(self);
3180 ret = mod->ops->modify(mod, req);
3182 PyErr_LDB_ERROR_IS_ERR_RAISE(PyExc_LdbError, ret, mod->ldb);
3184 Py_RETURN_NONE;
3187 static PyObject *py_ldb_module_delete(PyLdbModuleObject *self, PyObject *args)
3189 int ret;
3190 struct ldb_request *req;
3191 PyObject *py_dn;
3193 if (!PyArg_ParseTuple(args, "O!", &PyLdbDn, &py_dn))
3194 return NULL;
3196 req = talloc_zero(NULL, struct ldb_request);
3197 req->operation = LDB_DELETE;
3198 req->op.del.dn = pyldb_Dn_AS_DN(py_dn);
3200 ret = pyldb_Module_AsModule(self)->ops->del(pyldb_Module_AsModule(self), req);
3202 PyErr_LDB_ERROR_IS_ERR_RAISE(PyExc_LdbError, ret, NULL);
3204 Py_RETURN_NONE;
3207 static PyObject *py_ldb_module_rename(PyLdbModuleObject *self, PyObject *args)
3209 int ret;
3210 struct ldb_request *req;
3211 PyObject *py_dn1, *py_dn2;
3213 if (!PyArg_ParseTuple(args, "O!O!", &PyLdbDn, &py_dn1, &PyLdbDn, &py_dn2))
3214 return NULL;
3216 req = talloc_zero(NULL, struct ldb_request);
3218 req->operation = LDB_RENAME;
3219 req->op.rename.olddn = pyldb_Dn_AS_DN(py_dn1);
3220 req->op.rename.newdn = pyldb_Dn_AS_DN(py_dn2);
3222 ret = pyldb_Module_AsModule(self)->ops->rename(pyldb_Module_AsModule(self), req);
3224 PyErr_LDB_ERROR_IS_ERR_RAISE(PyExc_LdbError, ret, NULL);
3226 Py_RETURN_NONE;
3229 static PyMethodDef py_ldb_module_methods[] = {
3230 { "search", PY_DISCARD_FUNC_SIG(PyCFunction, py_ldb_module_search),
3231 METH_VARARGS|METH_KEYWORDS, NULL },
3232 { "add", (PyCFunction)py_ldb_module_add, METH_VARARGS, NULL },
3233 { "modify", (PyCFunction)py_ldb_module_modify, METH_VARARGS, NULL },
3234 { "rename", (PyCFunction)py_ldb_module_rename, METH_VARARGS, NULL },
3235 { "delete", (PyCFunction)py_ldb_module_delete, METH_VARARGS, NULL },
3236 { "start_transaction", (PyCFunction)py_ldb_module_start_transaction, METH_NOARGS, NULL },
3237 { "end_transaction", (PyCFunction)py_ldb_module_end_transaction, METH_NOARGS, NULL },
3238 { "del_transaction", (PyCFunction)py_ldb_module_del_transaction, METH_NOARGS, NULL },
3239 {0},
3242 static void py_ldb_module_dealloc(PyLdbModuleObject *self)
3244 talloc_free(self->mem_ctx);
3245 PyObject_Del(self);
3248 static PyTypeObject PyLdbModule = {
3249 .tp_name = "ldb.LdbModule",
3250 .tp_methods = py_ldb_module_methods,
3251 .tp_repr = (reprfunc)py_ldb_module_repr,
3252 .tp_str = (reprfunc)py_ldb_module_str,
3253 .tp_basicsize = sizeof(PyLdbModuleObject),
3254 .tp_dealloc = (destructor)py_ldb_module_dealloc,
3255 .tp_flags = Py_TPFLAGS_DEFAULT,
3256 .tp_doc = "LDB module (extension)",
3261 * Create a ldb_message_element from a Python object.
3263 * This will accept any sequence objects that contains strings, or
3264 * a string object.
3266 * A reference to set_obj might be borrowed.
3268 * @param mem_ctx Memory context
3269 * @param set_obj Python object to convert
3270 * @param flags ldb_message_element flags to set, if a new element is returned
3271 * @param attr_name Name of the attribute to set, if a new element is returned
3272 * @return New ldb_message_element, allocated as child of mem_ctx
3274 static struct ldb_message_element *PyObject_AsMessageElement(
3275 TALLOC_CTX *mem_ctx,
3276 PyObject *set_obj,
3277 unsigned int flags,
3278 const char *attr_name)
3280 struct ldb_message_element *me;
3281 const char *msg = NULL;
3282 Py_ssize_t size;
3283 int result;
3285 if (pyldb_MessageElement_Check(set_obj)) {
3286 PyLdbMessageElementObject *set_obj_as_me = (PyLdbMessageElementObject *)set_obj;
3287 /* We have to talloc_reference() the memory context, not the pointer
3288 * which may not actually be it's own context */
3289 if (talloc_reference(mem_ctx, set_obj_as_me->mem_ctx)) {
3290 return pyldb_MessageElement_AsMessageElement(set_obj);
3292 return NULL;
3295 me = talloc(mem_ctx, struct ldb_message_element);
3296 if (me == NULL) {
3297 PyErr_NoMemory();
3298 return NULL;
3301 me->name = talloc_strdup(me, attr_name);
3302 if (me->name == NULL) {
3303 PyErr_NoMemory();
3304 talloc_free(me);
3305 return NULL;
3307 me->flags = flags;
3308 if (PyBytes_Check(set_obj) || PyUnicode_Check(set_obj)) {
3309 me->num_values = 1;
3310 me->values = talloc_array(me, struct ldb_val, me->num_values);
3311 if (PyBytes_Check(set_obj)) {
3312 char *_msg = NULL;
3313 result = PyBytes_AsStringAndSize(set_obj, &_msg, &size);
3314 if (result != 0) {
3315 talloc_free(me);
3316 return NULL;
3318 msg = _msg;
3319 } else {
3320 msg = PyUnicode_AsUTF8AndSize(set_obj, &size);
3321 if (msg == NULL) {
3322 talloc_free(me);
3323 return NULL;
3326 me->values[0].data = talloc_memdup(me,
3327 (const uint8_t *)msg,
3328 size+1);
3329 me->values[0].length = size;
3330 } else if (PySequence_Check(set_obj)) {
3331 Py_ssize_t i;
3332 me->num_values = PySequence_Size(set_obj);
3333 me->values = talloc_array(me, struct ldb_val, me->num_values);
3334 for (i = 0; i < me->num_values; i++) {
3335 PyObject *obj = PySequence_GetItem(set_obj, i);
3336 if (PyBytes_Check(obj)) {
3337 char *_msg = NULL;
3338 result = PyBytes_AsStringAndSize(obj, &_msg, &size);
3339 if (result != 0) {
3340 talloc_free(me);
3341 return NULL;
3343 msg = _msg;
3344 } else if (PyUnicode_Check(obj)) {
3345 msg = PyUnicode_AsUTF8AndSize(obj, &size);
3346 if (msg == NULL) {
3347 talloc_free(me);
3348 return NULL;
3350 } else {
3351 PyErr_Format(PyExc_TypeError,
3352 "Expected string as element %zd in list", i);
3353 talloc_free(me);
3354 return NULL;
3356 me->values[i].data = talloc_memdup(me,
3357 (const uint8_t *)msg,
3358 size+1);
3359 me->values[i].length = size;
3361 } else {
3362 PyErr_Format(PyExc_TypeError,
3363 "String or List type expected for '%s' attribute", attr_name);
3364 talloc_free(me);
3365 me = NULL;
3368 return me;
3372 static PyObject *ldb_msg_element_to_set(struct ldb_context *ldb_ctx,
3373 struct ldb_message_element *me)
3375 Py_ssize_t i;
3376 PyObject *result;
3378 /* Python << 2.5 doesn't have PySet_New and PySet_Add. */
3379 result = PyList_New(me->num_values);
3380 if (result == NULL) {
3381 return NULL;
3384 for (i = 0; i < me->num_values; i++) {
3385 PyObject *obj = NULL;
3386 int ret;
3388 obj = PyObject_FromLdbValue(&me->values[i]);
3389 if (obj == NULL) {
3390 Py_DECREF(result);
3391 return NULL;
3394 ret = PyList_SetItem(result, i, obj);
3395 if (ret) {
3396 Py_DECREF(obj);
3397 Py_DECREF(result);
3398 return NULL;
3402 return result;
3405 static PyObject *py_ldb_msg_element_get(PyLdbMessageElementObject *self, PyObject *args)
3407 unsigned int i;
3408 if (!PyArg_ParseTuple(args, "I", &i))
3409 return NULL;
3410 if (i >= pyldb_MessageElement_AsMessageElement(self)->num_values)
3411 Py_RETURN_NONE;
3413 return PyObject_FromLdbValue(&(pyldb_MessageElement_AsMessageElement(self)->values[i]));
3416 static PyObject *py_ldb_msg_element_flags(PyLdbMessageElementObject *self, PyObject *args)
3418 struct ldb_message_element *el = pyldb_MessageElement_AsMessageElement(self);
3419 return PyLong_FromLong(el->flags);
3422 static PyObject *py_ldb_msg_element_set_flags(PyLdbMessageElementObject *self, PyObject *args)
3424 unsigned int flags;
3425 struct ldb_message_element *el;
3426 if (!PyArg_ParseTuple(args, "I", &flags))
3427 return NULL;
3429 el = pyldb_MessageElement_AsMessageElement(self);
3430 el->flags = flags;
3431 Py_RETURN_NONE;
3434 static PyMethodDef py_ldb_msg_element_methods[] = {
3435 { "get", (PyCFunction)py_ldb_msg_element_get, METH_VARARGS, NULL },
3436 { "set_flags", (PyCFunction)py_ldb_msg_element_set_flags, METH_VARARGS, NULL },
3437 { "flags", (PyCFunction)py_ldb_msg_element_flags, METH_NOARGS, NULL },
3438 {0},
3441 static Py_ssize_t py_ldb_msg_element_len(PyLdbMessageElementObject *self)
3443 return pyldb_MessageElement_AsMessageElement(self)->num_values;
3446 static PyObject *py_ldb_msg_element_find(PyLdbMessageElementObject *self, Py_ssize_t idx)
3448 struct ldb_message_element *el = pyldb_MessageElement_AsMessageElement(self);
3449 if (idx < 0 || idx >= el->num_values) {
3450 PyErr_SetString(PyExc_IndexError, "Out of range");
3451 return NULL;
3453 return PyLdbBytes_FromStringAndSize((char *)el->values[idx].data, el->values[idx].length);
3456 static PySequenceMethods py_ldb_msg_element_seq = {
3457 .sq_length = (lenfunc)py_ldb_msg_element_len,
3458 .sq_item = (ssizeargfunc)py_ldb_msg_element_find,
3461 static PyObject *py_ldb_msg_element_richcmp(PyObject *self, PyObject *other, int op)
3463 int ret;
3464 if (!pyldb_MessageElement_Check(other)) {
3465 Py_INCREF(Py_NotImplemented);
3466 return Py_NotImplemented;
3468 ret = ldb_msg_element_compare(pyldb_MessageElement_AsMessageElement(self),
3469 pyldb_MessageElement_AsMessageElement(other));
3470 return richcmp(ret, op);
3473 static PyObject *py_ldb_msg_element_iter(PyLdbMessageElementObject *self)
3475 PyObject *el = ldb_msg_element_to_set(NULL,
3476 pyldb_MessageElement_AsMessageElement(self));
3477 PyObject *ret = PyObject_GetIter(el);
3478 Py_DECREF(el);
3479 return ret;
3482 static PyObject *PyLdbMessageElement_FromMessageElement(struct ldb_message_element *el, TALLOC_CTX *mem_ctx)
3484 TALLOC_CTX *ret_mem_ctx = NULL;
3485 PyLdbMessageElementObject *ret;
3487 ret_mem_ctx = talloc_new(NULL);
3488 if (ret_mem_ctx == NULL) {
3489 return PyErr_NoMemory();
3492 if (talloc_reference(ret_mem_ctx, mem_ctx) == NULL) {
3493 talloc_free(ret_mem_ctx);
3494 PyErr_NoMemory();
3495 return NULL;
3498 ret = PyObject_New(PyLdbMessageElementObject, &PyLdbMessageElement);
3499 if (ret == NULL) {
3500 talloc_free(ret_mem_ctx);
3501 PyErr_NoMemory();
3502 return NULL;
3504 ret->mem_ctx = ret_mem_ctx;
3505 ret->el = el;
3506 return (PyObject *)ret;
3509 static PyObject *py_ldb_msg_element_new(PyTypeObject *type, PyObject *args, PyObject *kwargs)
3511 PyObject *py_elements = NULL;
3512 struct ldb_message_element *el;
3513 unsigned int flags = 0;
3514 char *name = NULL;
3515 const char * const kwnames[] = { "elements", "flags", "name", NULL };
3516 PyLdbMessageElementObject *ret;
3517 TALLOC_CTX *mem_ctx;
3518 const char *msg = NULL;
3519 Py_ssize_t size;
3520 int result;
3522 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "|OIs",
3523 discard_const_p(char *, kwnames),
3524 &py_elements, &flags, &name))
3525 return NULL;
3527 mem_ctx = talloc_new(NULL);
3528 if (mem_ctx == NULL) {
3529 PyErr_NoMemory();
3530 return NULL;
3533 el = talloc_zero(mem_ctx, struct ldb_message_element);
3534 if (el == NULL) {
3535 PyErr_NoMemory();
3536 talloc_free(mem_ctx);
3537 return NULL;
3540 if (py_elements != NULL) {
3541 Py_ssize_t i;
3542 if (PyBytes_Check(py_elements) || PyUnicode_Check(py_elements)) {
3543 char *_msg = NULL;
3544 el->num_values = 1;
3545 el->values = talloc_array(el, struct ldb_val, 1);
3546 if (el->values == NULL) {
3547 talloc_free(mem_ctx);
3548 PyErr_NoMemory();
3549 return NULL;
3551 if (PyBytes_Check(py_elements)) {
3552 result = PyBytes_AsStringAndSize(py_elements, &_msg, &size);
3553 msg = _msg;
3554 } else {
3555 msg = PyUnicode_AsUTF8AndSize(py_elements, &size);
3556 result = (msg == NULL) ? -1 : 0;
3558 if (result != 0) {
3559 talloc_free(mem_ctx);
3560 return NULL;
3562 el->values[0].data = talloc_memdup(el->values,
3563 (const uint8_t *)msg, size + 1);
3564 el->values[0].length = size;
3565 } else if (PySequence_Check(py_elements)) {
3566 el->num_values = PySequence_Size(py_elements);
3567 el->values = talloc_array(el, struct ldb_val, el->num_values);
3568 if (el->values == NULL) {
3569 talloc_free(mem_ctx);
3570 PyErr_NoMemory();
3571 return NULL;
3573 for (i = 0; i < el->num_values; i++) {
3574 PyObject *item = PySequence_GetItem(py_elements, i);
3575 if (item == NULL) {
3576 talloc_free(mem_ctx);
3577 return NULL;
3579 if (PyBytes_Check(item)) {
3580 char *_msg = NULL;
3581 result = PyBytes_AsStringAndSize(item, &_msg, &size);
3582 msg = _msg;
3583 } else if (PyUnicode_Check(item)) {
3584 msg = PyUnicode_AsUTF8AndSize(item, &size);
3585 result = (msg == NULL) ? -1 : 0;
3586 } else {
3587 PyErr_Format(PyExc_TypeError,
3588 "Expected string as element %zd in list", i);
3589 result = -1;
3591 if (result != 0) {
3592 talloc_free(mem_ctx);
3593 return NULL;
3595 el->values[i].data = talloc_memdup(el,
3596 (const uint8_t *)msg, size+1);
3597 el->values[i].length = size;
3599 } else {
3600 PyErr_SetString(PyExc_TypeError,
3601 "Expected string or list");
3602 talloc_free(mem_ctx);
3603 return NULL;
3607 el->flags = flags;
3608 if (name != NULL) {
3609 el->name = talloc_strdup(el, name);
3610 if (el->name == NULL) {
3611 talloc_free(mem_ctx);
3612 return PyErr_NoMemory();
3616 ret = PyObject_New(PyLdbMessageElementObject, type);
3617 if (ret == NULL) {
3618 talloc_free(mem_ctx);
3619 return NULL;
3622 ret->mem_ctx = mem_ctx;
3623 ret->el = el;
3624 return (PyObject *)ret;
3627 static PyObject *py_ldb_msg_element_repr(PyLdbMessageElementObject *self)
3629 char *element_str = NULL;
3630 Py_ssize_t i;
3631 struct ldb_message_element *el = pyldb_MessageElement_AsMessageElement(self);
3632 PyObject *ret, *repr;
3634 for (i = 0; i < el->num_values; i++) {
3635 PyObject *o = py_ldb_msg_element_find(self, i);
3636 repr = PyObject_Repr(o);
3637 if (element_str == NULL)
3638 element_str = talloc_strdup(NULL, PyUnicode_AsUTF8(repr));
3639 else
3640 element_str = talloc_asprintf_append(element_str, ",%s", PyUnicode_AsUTF8(repr));
3641 Py_DECREF(repr);
3643 if (element_str == NULL) {
3644 return PyErr_NoMemory();
3648 if (element_str != NULL) {
3649 ret = PyUnicode_FromFormat("MessageElement([%s])", element_str);
3650 talloc_free(element_str);
3651 } else {
3652 ret = PyUnicode_FromString("MessageElement([])");
3655 return ret;
3658 static PyObject *py_ldb_msg_element_str(PyLdbMessageElementObject *self)
3660 struct ldb_message_element *el = pyldb_MessageElement_AsMessageElement(self);
3662 if (el->num_values == 1)
3663 return PyUnicode_FromStringAndSize((char *)el->values[0].data, el->values[0].length);
3664 else
3665 Py_RETURN_NONE;
3668 static void py_ldb_msg_element_dealloc(PyLdbMessageElementObject *self)
3670 talloc_free(self->mem_ctx);
3671 PyObject_Del(self);
3674 static PyObject *py_ldb_msg_element_get_text(PyObject *self, void *closure)
3676 return wrap_text("MessageElementTextWrapper", self);
3679 static PyGetSetDef py_ldb_msg_element_getset[] = {
3681 .name = discard_const_p(char, "text"),
3682 .get = (getter)py_ldb_msg_element_get_text,
3684 { .name = NULL }
3687 static PyTypeObject PyLdbMessageElement = {
3688 .tp_name = "ldb.MessageElement",
3689 .tp_basicsize = sizeof(PyLdbMessageElementObject),
3690 .tp_dealloc = (destructor)py_ldb_msg_element_dealloc,
3691 .tp_repr = (reprfunc)py_ldb_msg_element_repr,
3692 .tp_str = (reprfunc)py_ldb_msg_element_str,
3693 .tp_methods = py_ldb_msg_element_methods,
3694 .tp_getset = py_ldb_msg_element_getset,
3695 .tp_richcompare = (richcmpfunc)py_ldb_msg_element_richcmp,
3696 .tp_iter = (getiterfunc)py_ldb_msg_element_iter,
3697 .tp_as_sequence = &py_ldb_msg_element_seq,
3698 .tp_new = py_ldb_msg_element_new,
3699 .tp_flags = Py_TPFLAGS_DEFAULT,
3700 .tp_doc = "An element of a Message",
3704 static PyObject *py_ldb_msg_from_dict(PyTypeObject *type, PyObject *args)
3706 PyObject *py_ldb;
3707 PyObject *py_dict;
3708 PyObject *py_ret;
3709 struct ldb_message *msg;
3710 struct ldb_context *ldb_ctx;
3711 unsigned int mod_flags = LDB_FLAG_MOD_REPLACE;
3713 if (!PyArg_ParseTuple(args, "O!O!|I",
3714 &PyLdb, &py_ldb, &PyDict_Type, &py_dict,
3715 &mod_flags)) {
3716 return NULL;
3719 if (!PyLdb_Check(py_ldb)) {
3720 PyErr_SetString(PyExc_TypeError, "Expected Ldb");
3721 return NULL;
3724 /* mask only flags we are going to use */
3725 mod_flags = LDB_FLAG_MOD_TYPE(mod_flags);
3726 if (!mod_flags) {
3727 PyErr_SetString(PyExc_ValueError,
3728 "FLAG_MOD_ADD, FLAG_MOD_REPLACE or FLAG_MOD_DELETE"
3729 " expected as mod_flag value");
3730 return NULL;
3733 ldb_ctx = pyldb_Ldb_AS_LDBCONTEXT(py_ldb);
3735 msg = PyDict_AsMessage(ldb_ctx, py_dict, ldb_ctx, mod_flags);
3736 if (!msg) {
3737 return NULL;
3740 py_ret = PyLdbMessage_FromMessage(msg);
3742 talloc_unlink(ldb_ctx, msg);
3744 return py_ret;
3747 static PyObject *py_ldb_msg_remove_attr(PyLdbMessageObject *self, PyObject *args)
3749 char *name;
3750 if (!PyArg_ParseTuple(args, "s", &name))
3751 return NULL;
3753 ldb_msg_remove_attr(self->msg, name);
3755 Py_RETURN_NONE;
3758 static PyObject *py_ldb_msg_keys(PyLdbMessageObject *self,
3759 PyObject *Py_UNUSED(ignored))
3761 struct ldb_message *msg = pyldb_Message_AsMessage(self);
3762 Py_ssize_t i, j = 0;
3763 PyObject *obj = PyList_New(msg->num_elements+(msg->dn != NULL?1:0));
3764 if (obj == NULL) {
3765 return NULL;
3768 if (msg->dn != NULL) {
3769 PyObject *py_dn = NULL;
3770 int ret;
3772 py_dn = PyUnicode_FromString("dn");
3773 if (py_dn == NULL) {
3774 Py_DECREF(obj);
3775 return NULL;
3778 ret = PyList_SetItem(obj, j, py_dn);
3779 if (ret) {
3780 Py_DECREF(py_dn);
3781 Py_DECREF(obj);
3782 return NULL;
3785 j++;
3787 for (i = 0; i < msg->num_elements; i++) {
3788 PyObject *py_name = NULL;
3789 int ret;
3791 py_name = PyUnicode_FromString(msg->elements[i].name);
3792 if (py_name == NULL) {
3793 Py_DECREF(obj);
3794 return NULL;
3797 ret = PyList_SetItem(obj, j, py_name);
3798 if (ret) {
3799 Py_DECREF(py_name);
3800 Py_DECREF(obj);
3801 return NULL;
3804 j++;
3806 return obj;
3809 static int py_ldb_msg_contains(PyLdbMessageObject *self, PyObject *py_name)
3811 struct ldb_message_element *el = NULL;
3812 const char *name = NULL;
3813 struct ldb_message *msg = pyldb_Message_AsMessage(self);
3814 name = PyUnicode_AsUTF8(py_name);
3815 if (name == NULL) {
3816 return -1;
3818 if (!ldb_attr_cmp(name, "dn")) {
3819 return 1;
3821 el = ldb_msg_find_element(msg, name);
3822 return el != NULL ? 1 : 0;
3825 static PyObject *py_ldb_msg_getitem(PyLdbMessageObject *self, PyObject *py_name)
3827 struct ldb_message_element *el = NULL;
3828 const char *name = NULL;
3829 struct ldb_message *msg = pyldb_Message_AsMessage(self);
3830 name = PyUnicode_AsUTF8(py_name);
3831 if (name == NULL) {
3832 return NULL;
3834 if (!ldb_attr_cmp(name, "dn")) {
3835 return pyldb_Dn_FromDn(msg->dn);
3837 el = ldb_msg_find_element(msg, name);
3838 if (el == NULL) {
3839 PyErr_SetString(PyExc_KeyError, "No such element");
3840 return NULL;
3843 return PyLdbMessageElement_FromMessageElement(el, msg->elements);
3846 static PyObject *py_ldb_msg_get(PyLdbMessageObject *self, PyObject *args, PyObject *kwargs)
3848 PyObject *def = NULL;
3849 const char *kwnames[] = { "name", "default", "idx", NULL };
3850 const char *name = NULL;
3851 int idx = -1;
3852 struct ldb_message *msg = pyldb_Message_AsMessage(self);
3853 struct ldb_message_element *el;
3855 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "s|Oi:msg",
3856 discard_const_p(char *, kwnames), &name, &def, &idx)) {
3857 return NULL;
3860 if (strcasecmp(name, "dn") == 0) {
3861 return pyldb_Dn_FromDn(msg->dn);
3864 el = ldb_msg_find_element(msg, name);
3866 if (el == NULL || (idx != -1 && el->num_values <= idx)) {
3867 if (def != NULL) {
3868 Py_INCREF(def);
3869 return def;
3871 Py_RETURN_NONE;
3874 if (idx == -1) {
3875 return (PyObject *)PyLdbMessageElement_FromMessageElement(el, msg->elements);
3878 return PyObject_FromLdbValue(&el->values[idx]);
3881 static PyObject *py_ldb_msg_items(PyLdbMessageObject *self,
3882 PyObject *Py_UNUSED(ignored))
3884 struct ldb_message *msg = pyldb_Message_AsMessage(self);
3885 Py_ssize_t i, j = 0;
3886 PyObject *l = PyList_New(msg->num_elements + (msg->dn == NULL?0:1));
3887 if (l == NULL) {
3888 return PyErr_NoMemory();
3890 if (msg->dn != NULL) {
3891 PyObject *value = NULL;
3892 PyObject *obj = pyldb_Dn_FromDn(msg->dn);
3893 int res = 0;
3894 value = Py_BuildValue("(sO)", "dn", obj);
3895 Py_CLEAR(obj);
3896 if (value == NULL) {
3897 Py_CLEAR(l);
3898 return NULL;
3900 res = PyList_SetItem(l, 0, value);
3901 if (res == -1) {
3902 Py_CLEAR(l);
3903 return NULL;
3905 j++;
3907 for (i = 0; i < msg->num_elements; i++, j++) {
3908 PyObject *value = NULL;
3909 PyObject *py_el = PyLdbMessageElement_FromMessageElement(&msg->elements[i], msg->elements);
3910 int res = 0;
3911 value = Py_BuildValue("(sO)", msg->elements[i].name, py_el);
3912 Py_CLEAR(py_el);
3913 if (value == NULL ) {
3914 Py_CLEAR(l);
3915 return NULL;
3917 res = PyList_SetItem(l, j, value);
3918 if (res == -1) {
3919 Py_CLEAR(l);
3920 return NULL;
3923 return l;
3926 static PyObject *py_ldb_msg_elements(PyLdbMessageObject *self,
3927 PyObject *Py_UNUSED(ignored))
3929 struct ldb_message *msg = pyldb_Message_AsMessage(self);
3930 Py_ssize_t i = 0;
3931 PyObject *l = PyList_New(msg->num_elements);
3932 if (l == NULL) {
3933 return NULL;
3935 for (i = 0; i < msg->num_elements; i++) {
3936 PyObject *msg_el = NULL;
3937 int ret;
3939 msg_el = PyLdbMessageElement_FromMessageElement(&msg->elements[i], msg->elements);
3940 if (msg_el == NULL) {
3941 Py_DECREF(l);
3942 return NULL;
3945 ret = PyList_SetItem(l, i, msg_el);
3946 if (ret) {
3947 Py_DECREF(msg_el);
3948 Py_DECREF(l);
3949 return NULL;
3952 return l;
3955 static PyObject *py_ldb_msg_add(PyLdbMessageObject *self, PyObject *args)
3957 struct ldb_message *msg = pyldb_Message_AsMessage(self);
3958 PyLdbMessageElementObject *py_element;
3959 int i, ret;
3960 struct ldb_message_element *el;
3961 struct ldb_message_element *el_new;
3963 if (!PyArg_ParseTuple(args, "O!", &PyLdbMessageElement, &py_element))
3964 return NULL;
3966 el = py_element->el;
3967 if (el == NULL) {
3968 PyErr_SetString(PyExc_ValueError, "Invalid MessageElement object");
3969 return NULL;
3971 if (el->name == NULL) {
3972 PyErr_SetString(PyExc_ValueError,
3973 "The element has no name");
3974 return NULL;
3976 ret = ldb_msg_add_empty(msg, el->name, el->flags, &el_new);
3977 PyErr_LDB_ERROR_IS_ERR_RAISE(PyExc_LdbError, ret, NULL);
3979 /* now deep copy all attribute values */
3980 el_new->values = talloc_array(msg->elements, struct ldb_val, el->num_values);
3981 if (el_new->values == NULL) {
3982 PyErr_NoMemory();
3983 return NULL;
3985 el_new->num_values = el->num_values;
3987 for (i = 0; i < el->num_values; i++) {
3988 el_new->values[i] = ldb_val_dup(el_new->values, &el->values[i]);
3989 if (el_new->values[i].data == NULL
3990 && el->values[i].length != 0) {
3991 PyErr_NoMemory();
3992 return NULL;
3996 Py_RETURN_NONE;
3999 static PyMethodDef py_ldb_msg_methods[] = {
4000 { "from_dict", (PyCFunction)py_ldb_msg_from_dict, METH_CLASS | METH_VARARGS,
4001 "Message.from_dict(ldb, dict, mod_flag=FLAG_MOD_REPLACE) -> ldb.Message\n"
4002 "Class method to create ldb.Message object from Dictionary.\n"
4003 "mod_flag is one of FLAG_MOD_ADD, FLAG_MOD_REPLACE or FLAG_MOD_DELETE."},
4004 { "keys", (PyCFunction)py_ldb_msg_keys, METH_NOARGS,
4005 "S.keys() -> list\n\n"
4006 "Return sequence of all attribute names." },
4007 { "remove", (PyCFunction)py_ldb_msg_remove_attr, METH_VARARGS,
4008 "S.remove(name)\n\n"
4009 "Remove all entries for attributes with the specified name."},
4010 { "get", PY_DISCARD_FUNC_SIG(PyCFunction, py_ldb_msg_get),
4011 METH_VARARGS | METH_KEYWORDS,
4012 "msg.get(name,default=None,idx=None) -> string\n"
4013 "idx is the index into the values array\n"
4014 "if idx is None, then a list is returned\n"
4015 "if idx is not None, then the element with that index is returned\n"
4016 "if you pass the special name 'dn' then the DN object is returned\n"},
4017 { "items", (PyCFunction)py_ldb_msg_items, METH_NOARGS, NULL },
4018 { "elements", (PyCFunction)py_ldb_msg_elements, METH_NOARGS, NULL },
4019 { "add", (PyCFunction)py_ldb_msg_add, METH_VARARGS,
4020 "S.add(element)\n\n"
4021 "Add an element to this message." },
4022 {0},
4025 static PyObject *py_ldb_msg_iter(PyLdbMessageObject *self)
4027 PyObject *list, *iter;
4029 list = py_ldb_msg_keys(self, NULL);
4030 iter = PyObject_GetIter(list);
4031 Py_DECREF(list);
4032 return iter;
4035 static int py_ldb_msg_setitem(PyLdbMessageObject *self, PyObject *name, PyObject *value)
4037 const char *attr_name;
4039 attr_name = PyUnicode_AsUTF8(name);
4040 if (attr_name == NULL) {
4041 PyErr_SetNone(PyExc_TypeError);
4042 return -1;
4045 if (value == NULL) {
4046 /* delitem */
4047 ldb_msg_remove_attr(self->msg, attr_name);
4048 } else {
4049 int ret;
4050 struct ldb_message_element *el = PyObject_AsMessageElement(self->msg,
4051 value, 0, attr_name);
4052 if (el == NULL) {
4053 return -1;
4055 if (el->name == NULL) {
4057 * If ‘value’ is a MessageElement,
4058 * PyObject_AsMessageElement() will have returned a
4059 * reference to it without setting the name. We don’t
4060 * want to modify the original object to set the name
4061 * ourselves, but making a copy would result in
4062 * different behaviour for a caller relying on a
4063 * reference being kept. Rather than continue with a
4064 * NULL name (and probably fail later on), let’s catch
4065 * this potential mistake early.
4067 PyErr_SetString(PyExc_ValueError, "MessageElement has no name set");
4068 talloc_unlink(self->msg, el);
4069 return -1;
4071 ldb_msg_remove_attr(pyldb_Message_AsMessage(self), attr_name);
4072 ret = ldb_msg_add(pyldb_Message_AsMessage(self), el, el->flags);
4073 if (ret != LDB_SUCCESS) {
4074 PyErr_SetLdbError(PyExc_LdbError, ret, NULL);
4075 talloc_unlink(self->msg, el);
4076 return -1;
4079 return 0;
4082 static Py_ssize_t py_ldb_msg_length(PyLdbMessageObject *self)
4084 return pyldb_Message_AsMessage(self)->num_elements;
4087 static PySequenceMethods py_ldb_msg_sequence = {
4088 .sq_contains = (objobjproc)py_ldb_msg_contains,
4091 static PyMappingMethods py_ldb_msg_mapping = {
4092 .mp_length = (lenfunc)py_ldb_msg_length,
4093 .mp_subscript = (binaryfunc)py_ldb_msg_getitem,
4094 .mp_ass_subscript = (objobjargproc)py_ldb_msg_setitem,
4097 static PyObject *py_ldb_msg_new(PyTypeObject *type, PyObject *args, PyObject *kwargs)
4099 const char * const kwnames[] = { "dn", NULL };
4100 struct ldb_message *ret;
4101 TALLOC_CTX *mem_ctx;
4102 PyObject *pydn = NULL;
4103 PyLdbMessageObject *py_ret;
4105 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "|O",
4106 discard_const_p(char *, kwnames),
4107 &pydn))
4108 return NULL;
4110 mem_ctx = talloc_new(NULL);
4111 if (mem_ctx == NULL) {
4112 PyErr_NoMemory();
4113 return NULL;
4116 ret = ldb_msg_new(mem_ctx);
4117 if (ret == NULL) {
4118 talloc_free(mem_ctx);
4119 PyErr_NoMemory();
4120 return NULL;
4123 if (pydn != NULL) {
4124 struct ldb_dn *dn;
4125 if (!pyldb_Object_AsDn(NULL, pydn, NULL, &dn)) {
4126 talloc_free(mem_ctx);
4127 return NULL;
4129 ret->dn = talloc_reference(ret, dn);
4130 if (ret->dn == NULL) {
4131 talloc_free(mem_ctx);
4132 return PyErr_NoMemory();
4136 py_ret = (PyLdbMessageObject *)type->tp_alloc(type, 0);
4137 if (py_ret == NULL) {
4138 PyErr_NoMemory();
4139 talloc_free(mem_ctx);
4140 return NULL;
4143 py_ret->mem_ctx = mem_ctx;
4144 py_ret->msg = ret;
4145 return (PyObject *)py_ret;
4148 static PyObject *PyLdbMessage_FromMessage(struct ldb_message *msg)
4150 TALLOC_CTX *mem_ctx = NULL;
4151 struct ldb_message *msg_ref = NULL;
4152 PyLdbMessageObject *ret;
4154 mem_ctx = talloc_new(NULL);
4155 if (mem_ctx == NULL) {
4156 return PyErr_NoMemory();
4159 msg_ref = talloc_reference(mem_ctx, msg);
4160 if (msg_ref == NULL) {
4161 talloc_free(mem_ctx);
4162 return PyErr_NoMemory();
4165 ret = (PyLdbMessageObject *)PyLdbMessage.tp_alloc(&PyLdbMessage, 0);
4166 if (ret == NULL) {
4167 talloc_free(mem_ctx);
4168 PyErr_NoMemory();
4169 return NULL;
4171 ret->mem_ctx = mem_ctx;
4172 ret->msg = msg_ref;
4173 return (PyObject *)ret;
4176 static PyObject *py_ldb_msg_get_dn(PyLdbMessageObject *self, void *closure)
4178 struct ldb_message *msg = pyldb_Message_AsMessage(self);
4179 return pyldb_Dn_FromDn(msg->dn);
4182 static int py_ldb_msg_set_dn(PyLdbMessageObject *self, PyObject *value, void *closure)
4184 struct ldb_message *msg = pyldb_Message_AsMessage(self);
4185 struct ldb_dn *dn = NULL;
4186 if (value == NULL) {
4187 PyErr_SetString(PyExc_AttributeError, "cannot delete dn");
4188 return -1;
4190 if (!pyldb_Dn_Check(value)) {
4191 PyErr_SetString(PyExc_TypeError, "expected dn");
4192 return -1;
4195 dn = talloc_reference(msg, pyldb_Dn_AS_DN(value));
4196 if (dn == NULL) {
4197 PyErr_NoMemory();
4198 return -1;
4201 msg->dn = dn;
4202 return 0;
4205 static PyObject *py_ldb_msg_get_text(PyObject *self, void *closure)
4207 return wrap_text("MessageTextWrapper", self);
4210 static PyGetSetDef py_ldb_msg_getset[] = {
4212 .name = discard_const_p(char, "dn"),
4213 .get = (getter)py_ldb_msg_get_dn,
4214 .set = (setter)py_ldb_msg_set_dn,
4217 .name = discard_const_p(char, "text"),
4218 .get = (getter)py_ldb_msg_get_text,
4220 { .name = NULL },
4223 static PyObject *py_ldb_msg_repr(PyLdbMessageObject *self)
4225 PyObject *dict = PyDict_New(), *ret, *repr;
4226 const char *repr_str = NULL;
4227 if (dict == NULL) {
4228 return NULL;
4230 if (PyDict_Update(dict, (PyObject *)self) != 0) {
4231 Py_DECREF(dict);
4232 return NULL;
4234 repr = PyObject_Repr(dict);
4235 if (repr == NULL) {
4236 Py_DECREF(dict);
4237 return NULL;
4239 repr_str = PyUnicode_AsUTF8(repr);
4240 if (repr_str == NULL) {
4241 Py_DECREF(repr);
4242 Py_DECREF(dict);
4243 return NULL;
4245 ret = PyUnicode_FromFormat("Message(%s)", repr_str);
4246 Py_DECREF(repr);
4247 Py_DECREF(dict);
4248 return ret;
4251 static void py_ldb_msg_dealloc(PyLdbMessageObject *self)
4253 talloc_free(self->mem_ctx);
4254 PyObject_Del(self);
4257 static PyObject *py_ldb_msg_richcmp(PyLdbMessageObject *py_msg1,
4258 PyLdbMessageObject *py_msg2, int op)
4260 struct ldb_message *msg1, *msg2;
4261 unsigned int i;
4262 int ret;
4264 if (!PyLdbMessage_Check(py_msg2)) {
4265 Py_INCREF(Py_NotImplemented);
4266 return Py_NotImplemented;
4269 msg1 = pyldb_Message_AsMessage(py_msg1),
4270 msg2 = pyldb_Message_AsMessage(py_msg2);
4272 if ((msg1->dn != NULL) || (msg2->dn != NULL)) {
4273 ret = ldb_dn_compare(msg1->dn, msg2->dn);
4274 if (ret != 0) {
4275 return richcmp(ret, op);
4279 ret = msg1->num_elements - msg2->num_elements;
4280 if (ret != 0) {
4281 return richcmp(ret, op);
4284 for (i = 0; i < msg1->num_elements; i++) {
4285 ret = ldb_msg_element_compare_name(&msg1->elements[i],
4286 &msg2->elements[i]);
4287 if (ret != 0) {
4288 return richcmp(ret, op);
4291 ret = ldb_msg_element_compare(&msg1->elements[i],
4292 &msg2->elements[i]);
4293 if (ret != 0) {
4294 return richcmp(ret, op);
4298 return richcmp(0, op);
4301 static PyTypeObject PyLdbMessage = {
4302 .tp_name = "ldb.Message",
4303 .tp_methods = py_ldb_msg_methods,
4304 .tp_getset = py_ldb_msg_getset,
4305 .tp_as_sequence = &py_ldb_msg_sequence,
4306 .tp_as_mapping = &py_ldb_msg_mapping,
4307 .tp_basicsize = sizeof(PyLdbMessageObject),
4308 .tp_dealloc = (destructor)py_ldb_msg_dealloc,
4309 .tp_new = py_ldb_msg_new,
4310 .tp_repr = (reprfunc)py_ldb_msg_repr,
4311 .tp_flags = Py_TPFLAGS_DEFAULT,
4312 .tp_iter = (getiterfunc)py_ldb_msg_iter,
4313 .tp_richcompare = (richcmpfunc)py_ldb_msg_richcmp,
4314 .tp_doc = "A LDB Message",
4317 static PyObject *PyLdbTree_FromTree(struct ldb_parse_tree *tree)
4319 TALLOC_CTX *mem_ctx = NULL;
4320 struct ldb_parse_tree *tree_ref = NULL;
4321 PyLdbTreeObject *ret;
4323 mem_ctx = talloc_new(NULL);
4324 if (mem_ctx == NULL) {
4325 return PyErr_NoMemory();
4328 tree_ref = talloc_reference(mem_ctx, tree);
4329 if (tree_ref == NULL) {
4330 talloc_free(mem_ctx);
4331 return PyErr_NoMemory();
4334 ret = (PyLdbTreeObject *)PyLdbTree.tp_alloc(&PyLdbTree, 0);
4335 if (ret == NULL) {
4336 talloc_free(mem_ctx);
4337 PyErr_NoMemory();
4338 return NULL;
4341 ret->mem_ctx = mem_ctx;
4342 ret->tree = tree_ref;
4343 return (PyObject *)ret;
4346 static void py_ldb_tree_dealloc(PyLdbTreeObject *self)
4348 talloc_free(self->mem_ctx);
4349 PyObject_Del(self);
4352 static PyTypeObject PyLdbTree = {
4353 .tp_name = "ldb.Tree",
4354 .tp_basicsize = sizeof(PyLdbTreeObject),
4355 .tp_dealloc = (destructor)py_ldb_tree_dealloc,
4356 .tp_flags = Py_TPFLAGS_DEFAULT,
4357 .tp_doc = "A search tree",
4360 /* Ldb_module */
4361 static int py_module_search(struct ldb_module *mod, struct ldb_request *req)
4363 PyObject *py_ldb = (PyObject *)mod->private_data;
4364 PyObject *py_result, *py_base, *py_attrs, *py_tree;
4366 py_base = pyldb_Dn_FromDn(req->op.search.base);
4368 if (py_base == NULL)
4369 return LDB_ERR_OPERATIONS_ERROR;
4371 py_tree = PyLdbTree_FromTree(req->op.search.tree);
4373 if (py_tree == NULL) {
4374 Py_DECREF(py_base);
4375 return LDB_ERR_OPERATIONS_ERROR;
4378 if (req->op.search.attrs == NULL) {
4379 py_attrs = Py_None;
4380 } else {
4381 int i, len;
4382 for (len = 0; req->op.search.attrs[len]; len++);
4383 py_attrs = PyList_New(len);
4384 if (py_attrs == NULL) {
4385 Py_DECREF(py_tree);
4386 Py_DECREF(py_base);
4387 return LDB_ERR_OPERATIONS_ERROR;
4389 for (i = 0; i < len; i++) {
4390 PyObject *py_attr = NULL;
4391 int ret;
4393 py_attr = PyUnicode_FromString(req->op.search.attrs[i]);
4394 if (py_attr == NULL) {
4395 Py_DECREF(py_tree);
4396 Py_DECREF(py_base);
4397 Py_DECREF(py_attrs);
4398 return LDB_ERR_OPERATIONS_ERROR;
4401 ret = PyList_SetItem(py_attrs, i, py_attr);
4402 if (ret) {
4403 Py_DECREF(py_attr);
4404 Py_DECREF(py_tree);
4405 Py_DECREF(py_base);
4406 Py_DECREF(py_attrs);
4407 return LDB_ERR_OPERATIONS_ERROR;
4412 py_result = PyObject_CallMethod(py_ldb, discard_const_p(char, "search"),
4413 discard_const_p(char, "OiOO"),
4414 py_base, req->op.search.scope, py_tree, py_attrs);
4416 Py_DECREF(py_attrs);
4417 Py_DECREF(py_tree);
4418 Py_DECREF(py_base);
4420 if (py_result == NULL) {
4421 return LDB_ERR_PYTHON_EXCEPTION;
4424 req->op.search.res = PyLdbResult_AsResult(NULL, py_result);
4425 if (req->op.search.res == NULL) {
4426 Py_DECREF(py_result);
4427 return LDB_ERR_PYTHON_EXCEPTION;
4430 Py_DECREF(py_result);
4432 return LDB_SUCCESS;
4435 static int py_module_add(struct ldb_module *mod, struct ldb_request *req)
4437 PyObject *py_ldb = (PyObject *)mod->private_data;
4438 PyObject *py_result, *py_msg;
4440 py_msg = PyLdbMessage_FromMessage(discard_const_p(struct ldb_message, req->op.add.message));
4442 if (py_msg == NULL) {
4443 return LDB_ERR_OPERATIONS_ERROR;
4446 py_result = PyObject_CallMethod(py_ldb, discard_const_p(char, "add"),
4447 discard_const_p(char, "O"),
4448 py_msg);
4450 Py_DECREF(py_msg);
4452 if (py_result == NULL) {
4453 return LDB_ERR_PYTHON_EXCEPTION;
4456 Py_DECREF(py_result);
4458 return LDB_SUCCESS;
4461 static int py_module_modify(struct ldb_module *mod, struct ldb_request *req)
4463 PyObject *py_ldb = (PyObject *)mod->private_data;
4464 PyObject *py_result, *py_msg;
4466 py_msg = PyLdbMessage_FromMessage(discard_const_p(struct ldb_message, req->op.mod.message));
4468 if (py_msg == NULL) {
4469 return LDB_ERR_OPERATIONS_ERROR;
4472 py_result = PyObject_CallMethod(py_ldb, discard_const_p(char, "modify"),
4473 discard_const_p(char, "O"),
4474 py_msg);
4476 Py_DECREF(py_msg);
4478 if (py_result == NULL) {
4479 return LDB_ERR_PYTHON_EXCEPTION;
4482 Py_DECREF(py_result);
4484 return LDB_SUCCESS;
4487 static int py_module_del(struct ldb_module *mod, struct ldb_request *req)
4489 PyObject *py_ldb = (PyObject *)mod->private_data;
4490 PyObject *py_result, *py_dn;
4492 py_dn = pyldb_Dn_FromDn(req->op.del.dn);
4494 if (py_dn == NULL)
4495 return LDB_ERR_OPERATIONS_ERROR;
4497 py_result = PyObject_CallMethod(py_ldb, discard_const_p(char, "delete"),
4498 discard_const_p(char, "O"),
4499 py_dn);
4500 Py_DECREF(py_dn);
4502 if (py_result == NULL) {
4503 return LDB_ERR_PYTHON_EXCEPTION;
4506 Py_DECREF(py_result);
4508 return LDB_SUCCESS;
4511 static int py_module_rename(struct ldb_module *mod, struct ldb_request *req)
4513 PyObject *py_ldb = (PyObject *)mod->private_data;
4514 PyObject *py_result, *py_olddn, *py_newdn;
4516 py_olddn = pyldb_Dn_FromDn(req->op.rename.olddn);
4518 if (py_olddn == NULL)
4519 return LDB_ERR_OPERATIONS_ERROR;
4521 py_newdn = pyldb_Dn_FromDn(req->op.rename.newdn);
4523 if (py_newdn == NULL) {
4524 Py_DECREF(py_olddn);
4525 return LDB_ERR_OPERATIONS_ERROR;
4528 py_result = PyObject_CallMethod(py_ldb, discard_const_p(char, "rename"),
4529 discard_const_p(char, "OO"),
4530 py_olddn, py_newdn);
4532 Py_DECREF(py_olddn);
4533 Py_DECREF(py_newdn);
4535 if (py_result == NULL) {
4536 return LDB_ERR_PYTHON_EXCEPTION;
4539 Py_DECREF(py_result);
4541 return LDB_SUCCESS;
4544 static int py_module_request(struct ldb_module *mod, struct ldb_request *req)
4546 PyObject *py_ldb = (PyObject *)mod->private_data;
4547 PyObject *py_result;
4549 py_result = PyObject_CallMethod(py_ldb, discard_const_p(char, "request"),
4550 discard_const_p(char, ""));
4552 Py_XDECREF(py_result);
4554 return LDB_ERR_OPERATIONS_ERROR;
4557 static int py_module_extended(struct ldb_module *mod, struct ldb_request *req)
4559 PyObject *py_ldb = (PyObject *)mod->private_data;
4560 PyObject *py_result;
4562 py_result = PyObject_CallMethod(py_ldb, discard_const_p(char, "extended"),
4563 discard_const_p(char, ""));
4565 Py_XDECREF(py_result);
4567 return LDB_ERR_OPERATIONS_ERROR;
4570 static int py_module_start_transaction(struct ldb_module *mod)
4572 PyObject *py_ldb = (PyObject *)mod->private_data;
4573 PyObject *py_result;
4575 py_result = PyObject_CallMethod(py_ldb, discard_const_p(char, "start_transaction"),
4576 discard_const_p(char, ""));
4578 if (py_result == NULL) {
4579 return LDB_ERR_PYTHON_EXCEPTION;
4582 Py_DECREF(py_result);
4584 return LDB_SUCCESS;
4587 static int py_module_end_transaction(struct ldb_module *mod)
4589 PyObject *py_ldb = (PyObject *)mod->private_data;
4590 PyObject *py_result;
4592 py_result = PyObject_CallMethod(py_ldb, discard_const_p(char, "end_transaction"),
4593 discard_const_p(char, ""));
4595 if (py_result == NULL) {
4596 return LDB_ERR_PYTHON_EXCEPTION;
4599 Py_DECREF(py_result);
4601 return LDB_SUCCESS;
4604 static int py_module_del_transaction(struct ldb_module *mod)
4606 PyObject *py_ldb = (PyObject *)mod->private_data;
4607 PyObject *py_result;
4609 py_result = PyObject_CallMethod(py_ldb, discard_const_p(char, "del_transaction"),
4610 discard_const_p(char, ""));
4612 if (py_result == NULL) {
4613 return LDB_ERR_PYTHON_EXCEPTION;
4616 Py_DECREF(py_result);
4618 return LDB_SUCCESS;
4621 static int py_module_destructor(struct ldb_module *mod)
4623 Py_CLEAR(mod->private_data);
4624 return 0;
4627 static int py_module_init(struct ldb_module *mod)
4629 PyObject *py_class = (PyObject *)mod->ops->private_data;
4630 PyObject *py_result, *py_next, *py_ldb;
4632 py_ldb = PyLdb_FromLdbContext(mod->ldb);
4634 if (py_ldb == NULL)
4635 return LDB_ERR_OPERATIONS_ERROR;
4637 py_next = PyLdbModule_FromModule(mod->next);
4639 if (py_next == NULL) {
4640 Py_DECREF(py_ldb);
4641 return LDB_ERR_OPERATIONS_ERROR;
4644 py_result = PyObject_CallFunction(py_class, discard_const_p(char, "OO"),
4645 py_ldb, py_next);
4647 Py_DECREF(py_next);
4648 Py_DECREF(py_ldb);
4650 if (py_result == NULL) {
4651 return LDB_ERR_PYTHON_EXCEPTION;
4654 mod->private_data = py_result;
4656 talloc_set_destructor(mod, py_module_destructor);
4658 return ldb_next_init(mod);
4661 static PyObject *py_register_module(PyObject *module, PyObject *args)
4663 int ret;
4664 struct ldb_module_ops *ops;
4665 PyObject *input;
4666 PyObject *tmp = NULL;
4667 const char *name = NULL;
4669 if (!PyArg_ParseTuple(args, "O", &input))
4670 return NULL;
4672 ops = talloc_zero(NULL, struct ldb_module_ops);
4673 if (ops == NULL) {
4674 PyErr_NoMemory();
4675 return NULL;
4678 tmp = PyObject_GetAttrString(input, discard_const_p(char, "name"));
4679 if (tmp == NULL) {
4680 TALLOC_FREE(ops);
4681 return NULL;
4683 name = PyUnicode_AsUTF8(tmp);
4684 if (name == NULL) {
4685 Py_DECREF(tmp);
4686 TALLOC_FREE(ops);
4687 return NULL;
4690 ops->name = talloc_strdup(ops, name);
4691 Py_XDECREF(tmp);
4692 if (ops->name == NULL) {
4693 TALLOC_FREE(ops);
4694 return PyErr_NoMemory();
4696 Py_INCREF(input);
4697 ops->private_data = input;
4698 ops->init_context = py_module_init;
4699 ops->search = py_module_search;
4700 ops->add = py_module_add;
4701 ops->modify = py_module_modify;
4702 ops->del = py_module_del;
4703 ops->rename = py_module_rename;
4704 ops->request = py_module_request;
4705 ops->extended = py_module_extended;
4706 ops->start_transaction = py_module_start_transaction;
4707 ops->end_transaction = py_module_end_transaction;
4708 ops->del_transaction = py_module_del_transaction;
4710 ret = ldb_register_module(ops);
4711 if (ret != LDB_SUCCESS) {
4712 Py_DECREF(input);
4713 TALLOC_FREE(ops);
4716 PyErr_LDB_ERROR_IS_ERR_RAISE(PyExc_LdbError, ret, NULL);
4718 Py_RETURN_NONE;
4721 static PyObject *py_timestring(PyObject *module, PyObject *args)
4723 /* most times "time_t" is a signed integer type with 32 or 64 bit:
4724 * http://stackoverflow.com/questions/471248/what-is-ultimately-a-time-t-typedef-to */
4725 long int t_val;
4726 char *tresult;
4727 PyObject *ret;
4728 if (!PyArg_ParseTuple(args, "l", &t_val))
4729 return NULL;
4730 tresult = ldb_timestring(NULL, (time_t) t_val);
4731 if (tresult == NULL) {
4733 * Most likely EOVERFLOW from gmtime()
4735 PyErr_SetFromErrno(PyExc_OSError);
4736 return NULL;
4738 ret = PyUnicode_FromString(tresult);
4739 talloc_free(tresult);
4740 return ret;
4743 static PyObject *py_string_to_time(PyObject *module, PyObject *args)
4745 char *str;
4746 if (!PyArg_ParseTuple(args, "s", &str))
4747 return NULL;
4749 return PyLong_FromLong(ldb_string_to_time(str));
4752 static PyObject *py_valid_attr_name(PyObject *self, PyObject *args)
4754 char *name;
4755 if (!PyArg_ParseTuple(args, "s", &name))
4756 return NULL;
4757 return PyBool_FromLong(ldb_valid_attr_name(name));
4761 encode a string using RFC2254 rules
4763 static PyObject *py_binary_encode(PyObject *self, PyObject *args)
4765 char *str, *encoded;
4766 Py_ssize_t size = 0;
4767 struct ldb_val val;
4768 PyObject *ret;
4770 if (!PyArg_ParseTuple(args, "s#", &str, &size))
4771 return NULL;
4772 val.data = (uint8_t *)str;
4773 val.length = size;
4775 encoded = ldb_binary_encode(NULL, val);
4776 if (encoded == NULL) {
4777 PyErr_SetString(PyExc_TypeError, "unable to encode binary string");
4778 return NULL;
4780 ret = PyUnicode_FromString(encoded);
4781 talloc_free(encoded);
4782 return ret;
4786 decode a string using RFC2254 rules
4788 static PyObject *py_binary_decode(PyObject *self, PyObject *args)
4790 char *str;
4791 struct ldb_val val;
4792 PyObject *ret;
4794 if (!PyArg_ParseTuple(args, "s", &str))
4795 return NULL;
4797 val = ldb_binary_decode(NULL, str);
4798 if (val.data == NULL) {
4799 PyErr_SetString(PyExc_TypeError, "unable to decode binary string");
4800 return NULL;
4802 ret = PyBytes_FromStringAndSize((const char*)val.data, val.length);
4803 talloc_free(val.data);
4804 return ret;
4807 static PyMethodDef py_ldb_global_methods[] = {
4808 { "register_module", py_register_module, METH_VARARGS,
4809 "S.register_module(module) -> None\n\n"
4810 "Register a LDB module."},
4811 { "timestring", py_timestring, METH_VARARGS,
4812 "S.timestring(int) -> string\n\n"
4813 "Generate a LDAP time string from a UNIX timestamp" },
4814 { "string_to_time", py_string_to_time, METH_VARARGS,
4815 "S.string_to_time(string) -> int\n\n"
4816 "Parse a LDAP time string into a UNIX timestamp." },
4817 { "valid_attr_name", py_valid_attr_name, METH_VARARGS,
4818 "S.valid_attr_name(name) -> bool\n\n"
4819 "Check whether the supplied name is a valid attribute name." },
4820 { "binary_encode", py_binary_encode, METH_VARARGS,
4821 "S.binary_encode(string) -> string\n\n"
4822 "Perform a RFC2254 binary encoding on a string" },
4823 { "binary_decode", py_binary_decode, METH_VARARGS,
4824 "S.binary_decode(string) -> string\n\n"
4825 "Perform a RFC2254 binary decode on a string" },
4829 #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."
4831 static struct PyModuleDef moduledef = {
4832 PyModuleDef_HEAD_INIT,
4833 .m_name = "ldb",
4834 .m_doc = MODULE_DOC,
4835 .m_size = -1,
4836 .m_methods = py_ldb_global_methods,
4839 static PyObject* module_init(void)
4841 PyObject *m;
4843 PyLdbBytesType.tp_base = &PyBytes_Type;
4844 if (PyType_Ready(&PyLdbBytesType) < 0) {
4845 return NULL;
4848 if (PyType_Ready(&PyLdbDn) < 0)
4849 return NULL;
4851 if (PyType_Ready(&PyLdbMessage) < 0)
4852 return NULL;
4854 if (PyType_Ready(&PyLdbMessageElement) < 0)
4855 return NULL;
4857 if (PyType_Ready(&PyLdb) < 0)
4858 return NULL;
4860 if (PyType_Ready(&PyLdbModule) < 0)
4861 return NULL;
4863 if (PyType_Ready(&PyLdbTree) < 0)
4864 return NULL;
4866 if (PyType_Ready(&PyLdbResult) < 0)
4867 return NULL;
4869 if (PyType_Ready(&PyLdbSearchIterator) < 0)
4870 return NULL;
4872 if (PyType_Ready(&PyLdbControl) < 0)
4873 return NULL;
4875 m = PyModule_Create(&moduledef);
4876 if (m == NULL)
4877 return NULL;
4879 #define ADD_LDB_INT(val) PyModule_AddIntConstant(m, #val, LDB_ ## val)
4881 ADD_LDB_INT(SEQ_HIGHEST_SEQ);
4882 ADD_LDB_INT(SEQ_HIGHEST_TIMESTAMP);
4883 ADD_LDB_INT(SEQ_NEXT);
4884 ADD_LDB_INT(SCOPE_DEFAULT);
4885 ADD_LDB_INT(SCOPE_BASE);
4886 ADD_LDB_INT(SCOPE_ONELEVEL);
4887 ADD_LDB_INT(SCOPE_SUBTREE);
4889 ADD_LDB_INT(CHANGETYPE_NONE);
4890 ADD_LDB_INT(CHANGETYPE_ADD);
4891 ADD_LDB_INT(CHANGETYPE_DELETE);
4892 ADD_LDB_INT(CHANGETYPE_MODIFY);
4893 ADD_LDB_INT(CHANGETYPE_MODRDN);
4895 ADD_LDB_INT(FLAG_MOD_ADD);
4896 ADD_LDB_INT(FLAG_MOD_REPLACE);
4897 ADD_LDB_INT(FLAG_MOD_DELETE);
4898 ADD_LDB_INT(FLAG_FORCE_NO_BASE64_LDIF);
4900 ADD_LDB_INT(ATTR_FLAG_HIDDEN);
4901 ADD_LDB_INT(ATTR_FLAG_UNIQUE_INDEX);
4902 ADD_LDB_INT(ATTR_FLAG_SINGLE_VALUE);
4903 ADD_LDB_INT(ATTR_FLAG_FORCE_BASE64_LDIF);
4905 ADD_LDB_INT(SUCCESS);
4906 ADD_LDB_INT(ERR_OPERATIONS_ERROR);
4907 ADD_LDB_INT(ERR_PROTOCOL_ERROR);
4908 ADD_LDB_INT(ERR_TIME_LIMIT_EXCEEDED);
4909 ADD_LDB_INT(ERR_SIZE_LIMIT_EXCEEDED);
4910 ADD_LDB_INT(ERR_COMPARE_FALSE);
4911 ADD_LDB_INT(ERR_COMPARE_TRUE);
4912 ADD_LDB_INT(ERR_AUTH_METHOD_NOT_SUPPORTED);
4913 ADD_LDB_INT(ERR_STRONG_AUTH_REQUIRED);
4914 ADD_LDB_INT(ERR_REFERRAL);
4915 ADD_LDB_INT(ERR_ADMIN_LIMIT_EXCEEDED);
4916 ADD_LDB_INT(ERR_UNSUPPORTED_CRITICAL_EXTENSION);
4917 ADD_LDB_INT(ERR_CONFIDENTIALITY_REQUIRED);
4918 ADD_LDB_INT(ERR_SASL_BIND_IN_PROGRESS);
4919 ADD_LDB_INT(ERR_NO_SUCH_ATTRIBUTE);
4920 ADD_LDB_INT(ERR_UNDEFINED_ATTRIBUTE_TYPE);
4921 ADD_LDB_INT(ERR_INAPPROPRIATE_MATCHING);
4922 ADD_LDB_INT(ERR_CONSTRAINT_VIOLATION);
4923 ADD_LDB_INT(ERR_ATTRIBUTE_OR_VALUE_EXISTS);
4924 ADD_LDB_INT(ERR_INVALID_ATTRIBUTE_SYNTAX);
4925 ADD_LDB_INT(ERR_NO_SUCH_OBJECT);
4926 ADD_LDB_INT(ERR_ALIAS_PROBLEM);
4927 ADD_LDB_INT(ERR_INVALID_DN_SYNTAX);
4928 ADD_LDB_INT(ERR_ALIAS_DEREFERENCING_PROBLEM);
4929 ADD_LDB_INT(ERR_INAPPROPRIATE_AUTHENTICATION);
4930 ADD_LDB_INT(ERR_INVALID_CREDENTIALS);
4931 ADD_LDB_INT(ERR_INSUFFICIENT_ACCESS_RIGHTS);
4932 ADD_LDB_INT(ERR_BUSY);
4933 ADD_LDB_INT(ERR_UNAVAILABLE);
4934 ADD_LDB_INT(ERR_UNWILLING_TO_PERFORM);
4935 ADD_LDB_INT(ERR_LOOP_DETECT);
4936 ADD_LDB_INT(ERR_NAMING_VIOLATION);
4937 ADD_LDB_INT(ERR_OBJECT_CLASS_VIOLATION);
4938 ADD_LDB_INT(ERR_NOT_ALLOWED_ON_NON_LEAF);
4939 ADD_LDB_INT(ERR_NOT_ALLOWED_ON_RDN);
4940 ADD_LDB_INT(ERR_ENTRY_ALREADY_EXISTS);
4941 ADD_LDB_INT(ERR_OBJECT_CLASS_MODS_PROHIBITED);
4942 ADD_LDB_INT(ERR_AFFECTS_MULTIPLE_DSAS);
4943 ADD_LDB_INT(ERR_OTHER);
4945 ADD_LDB_INT(FLG_RDONLY);
4946 ADD_LDB_INT(FLG_NOSYNC);
4947 ADD_LDB_INT(FLG_RECONNECT);
4948 ADD_LDB_INT(FLG_NOMMAP);
4949 ADD_LDB_INT(FLG_SHOW_BINARY);
4950 ADD_LDB_INT(FLG_ENABLE_TRACING);
4951 ADD_LDB_INT(FLG_DONT_CREATE_DB);
4953 ADD_LDB_INT(PACKING_FORMAT);
4954 ADD_LDB_INT(PACKING_FORMAT_V2);
4956 /* Historical misspelling */
4957 PyModule_AddIntConstant(m, "ERR_ALIAS_DEREFERINCING_PROBLEM", LDB_ERR_ALIAS_DEREFERENCING_PROBLEM);
4959 PyModule_AddStringConstant(m, "__docformat__", "restructuredText");
4961 PyExc_LdbError = PyErr_NewException(discard_const_p(char, "_ldb.LdbError"), NULL, NULL);
4962 PyModule_AddObject(m, "LdbError", PyExc_LdbError);
4964 Py_INCREF(&PyLdb);
4965 Py_INCREF(&PyLdbDn);
4966 Py_INCREF(&PyLdbModule);
4967 Py_INCREF(&PyLdbMessage);
4968 Py_INCREF(&PyLdbMessageElement);
4969 Py_INCREF(&PyLdbTree);
4970 Py_INCREF(&PyLdbResult);
4971 Py_INCREF(&PyLdbControl);
4973 PyModule_AddObject(m, "Ldb", (PyObject *)&PyLdb);
4974 PyModule_AddObject(m, "Dn", (PyObject *)&PyLdbDn);
4975 PyModule_AddObject(m, "Message", (PyObject *)&PyLdbMessage);
4976 PyModule_AddObject(m, "MessageElement", (PyObject *)&PyLdbMessageElement);
4977 PyModule_AddObject(m, "Module", (PyObject *)&PyLdbModule);
4978 PyModule_AddObject(m, "Tree", (PyObject *)&PyLdbTree);
4979 PyModule_AddObject(m, "Control", (PyObject *)&PyLdbControl);
4981 PyModule_AddStringConstant(m, "__version__", PACKAGE_VERSION);
4983 #define ADD_LDB_STRING(val) PyModule_AddStringConstant(m, #val, LDB_## val)
4985 ADD_LDB_STRING(SYNTAX_DN);
4986 ADD_LDB_STRING(SYNTAX_DIRECTORY_STRING);
4987 ADD_LDB_STRING(SYNTAX_INTEGER);
4988 ADD_LDB_STRING(SYNTAX_ORDERED_INTEGER);
4989 ADD_LDB_STRING(SYNTAX_BOOLEAN);
4990 ADD_LDB_STRING(SYNTAX_OCTET_STRING);
4991 ADD_LDB_STRING(SYNTAX_UTC_TIME);
4992 ADD_LDB_STRING(OID_COMPARATOR_AND);
4993 ADD_LDB_STRING(OID_COMPARATOR_OR);
4995 return m;
4998 PyMODINIT_FUNC PyInit_ldb(void);
4999 PyMODINIT_FUNC PyInit_ldb(void)
5001 return module_init();